diff --git a/src/plugins/english/novelupdates.ts b/src/plugins/english/novelupdates.ts index e6ecd07da..120201270 100644 --- a/src/plugins/english/novelupdates.ts +++ b/src/plugins/english/novelupdates.ts @@ -2,15 +2,18 @@ import { CheerioAPI, load as parseHTML } from 'cheerio'; import { fetchApi } from '@libs/fetch'; import { Filters, FilterTypes } from '@libs/filterInputs'; import { Plugin } from '@typings/plugin'; +import { storage } from '@libs/storage'; class NovelUpdates implements Plugin.PluginBase { id = 'novelupdates'; name = 'Novel Updates'; - version = '0.9.0'; + version = '0.10.0'; icon = 'src/en/novelupdates/icon.png'; customCSS = 'src/en/novelupdates/customCSS.css'; site = 'https://www.novelupdates.com/'; + syncChapter = storage.get('syncChapter'); + parseNovels(loadedCheerio: CheerioAPI) { const novels: Plugin.NovelItem[] = []; loadedCheerio('div.search_main_box_nu').each((_, el) => { @@ -899,6 +902,34 @@ class NovelUpdates implements Plugin.PluginBase { return chapterCheerio.html()!; } + async handleChapterEvent( + novelPath: string, + chapter: Plugin.ChapterItem, + ): Promise { + try { + // Get HTML content + const result = await fetchApi(this.site + novelPath); + const body = await result.text(); + const loadedCheerio = parseHTML(body); + + // Extract IDs + const shortlink = loadedCheerio('link[rel="shortlink"]').attr('href'); + const novelId = shortlink?.match(/\?p=(\d+)/)?.[1]; + const chapterId = chapter.path.match(/\/(\d+)\//)?.[1]; + + // Validation + if (!novelId || !chapterId) return false; + + // Chapter sync + const syncUrl = `${this.site}readinglist_update.php?rid=${chapterId}&sid=${novelId}&checked=yes`; + await fetchApi(syncUrl); + + return true; + } catch (error) { + return false; + } + } + async searchNovels( searchTerm: string, page: number, @@ -1054,6 +1085,14 @@ class NovelUpdates implements Plugin.PluginBase { type: FilterTypes.CheckboxGroup, }, } satisfies Filters; + + pluginSettings = { + syncChapter: { + value: '', + label: 'Sync chapter progress with plugin site', + type: 'Switch', + }, + }; } export default new NovelUpdates(); diff --git a/src/plugins/english/scribblehub.ts b/src/plugins/english/scribblehub.ts index d62e3c749..c4941f2d1 100644 --- a/src/plugins/english/scribblehub.ts +++ b/src/plugins/english/scribblehub.ts @@ -3,13 +3,16 @@ import { fetchApi } from '@libs/fetch'; import { FilterTypes, Filters } from '@libs/filterInputs'; import { Plugin } from '@typings/plugin'; import dayjs from 'dayjs'; +import { storage } from '@libs/storage'; class ScribbleHubPlugin implements Plugin.PluginBase { id = 'scribblehub'; name = 'Scribble Hub'; icon = 'src/en/scribblehub/icon.png'; site = 'https://www.scribblehub.com/'; - version = '1.0.2'; + version = '1.1.0'; + + syncChapter = storage.get('syncChapter'); parseNovels(loadedCheerio: CheerioAPI) { const novels: Plugin.NovelItem[] = []; @@ -176,6 +179,36 @@ class ScribbleHubPlugin implements Plugin.PluginBase { return chapterText; } + async handleChapterEvent( + novelPath: string, + chapter: Plugin.ChapterItem, + ): Promise { + try { + // Extract IDs from paths + const novelId = novelPath.match(/series\/(\d+)\//)?.[1]; + const chapterId = chapter.path.match(/chapter\/(\d+)\//)?.[1]; + + // Validation + if (!novelId || !chapterId) return false; + + const formData = new FormData(); + formData.append('action', 'wi_addchangerl'); + formData.append('strCID', chapterId); + formData.append('strSID', novelId); + + // Chapter sync + const syncUrl = `${this.site}wp-admin/admin-ajax.php`; + await fetchApi(syncUrl, { + method: 'POST', + body: formData, + }); + + return true; + } catch (error) { + return false; + } + } + async searchNovels(searchTerm: string): Promise { const url = `${this.site}?s=${encodeURIComponent(searchTerm)}&post_type=fictionposts`; const result = await fetchApi(url); @@ -298,6 +331,14 @@ class ScribbleHubPlugin implements Plugin.PluginBase { type: FilterTypes.ExcludableCheckboxGroup, }, } satisfies Filters; + + pluginSettings = { + syncChapter: { + value: '', + label: 'Sync chapter progress with plugin site', + type: 'Switch', + }, + }; } export default new ScribbleHubPlugin(); diff --git a/src/types/plugin.ts b/src/types/plugin.ts index 477a01734..fa3ebcce2 100644 --- a/src/types/plugin.ts +++ b/src/types/plugin.ts @@ -74,8 +74,10 @@ export namespace Plugin { imageRequestInit?: ImageRequestInit; filters?: Filters; version: string; - //flag indicates whether access to LocalStorage, SesesionStorage is required. + // Flag indicates whether access to LocalStorage, SesesionStorage is required. webStorageUtilized?: boolean; + // Flag indicates whether chapter status is synced. + syncChapter?: boolean; popularNovels( pageNo: number, options: PopularNovelsOptions, @@ -87,6 +89,10 @@ export namespace Plugin { */ parseNovel(novelPath: string): Promise; parseChapter(chapterPath: string): Promise; + handleChapterEvent?( + novelPath: string, + chapter: ChapterItem, + ): Promise; searchNovels(searchTerm: string, pageNo: number): Promise; resolveUrl?(path: string, isNovel?: boolean): string; };