From 09a0bfb48957b04534e67c70b8b59c3b0c9c94bb Mon Sep 17 00:00:00 2001 From: Adam Kemish <49228220+Soopyboo32@users.noreply.github.com> Date: Thu, 30 Jan 2025 11:17:58 +0800 Subject: [PATCH] Add fictioneer multisrc (#1468) * Add fictioneer multisrc, auto source req labeling for it, move daoistquest to it, add novelib * fictioneer pagination, fix author, add status --- .github/workflows/theme_auto_label.yml | 19 +++++ .../fictioneer}/daoistquest/icon.png | Bin .../multisrc/fictioneer/novelib/icon.png | Bin 0 -> 1401 bytes scripts/multisrc/fictioneer/generator.js | 33 +++++++++ scripts/multisrc/fictioneer/sources.json | 19 +++++ .../multisrc/fictioneer/template.ts | 69 +++++++++++++----- 6 files changed, 122 insertions(+), 18 deletions(-) rename public/static/{src/en => multisrc/fictioneer}/daoistquest/icon.png (100%) create mode 100644 public/static/multisrc/fictioneer/novelib/icon.png create mode 100644 scripts/multisrc/fictioneer/generator.js create mode 100644 scripts/multisrc/fictioneer/sources.json rename src/plugins/english/daoistquest.ts => scripts/multisrc/fictioneer/template.ts (65%) diff --git a/.github/workflows/theme_auto_label.yml b/.github/workflows/theme_auto_label.yml index 41b4521..7c6364b 100644 --- a/.github/workflows/theme_auto_label.yml +++ b/.github/workflows/theme_auto_label.yml @@ -84,11 +84,28 @@ jobs: echo "hotnovelpub=false" >> $GITHUB_OUTPUT fi + - name: Check Fictioneer theme + id: check_fictioneer + env: + BASE_URL: ${{ steps.get_base_url.outputs.BASE_URL }} + USER_AGENT: ${{ steps.get_user_agent.outputs.USER_AGENT }} + run: | + if curl --location --output /dev/null --silent --head --fail "https://$BASE_URL/wp-content/themes/fictioneer/css/application.css" -H "User-Agent: $USER_AGENT"; then + echo "fictioneer=true" >> $GITHUB_OUTPUT + echo "✅ Fictioneer Theme Detected" >> $GITHUB_STEP_SUMMARY + elif curl --location --output /dev/null --silent --head --fail "http://$BASE_URL/wp-content/themes/fictioneer/css/application.css" -H "User-Agent: $USER_AGENT"; then + echo "fictioneer=true" >> $GITHUB_OUTPUT + echo "✅ Fictioneer Theme Detected" >> $GITHUB_STEP_SUMMARY + else + echo "fictioneer=false" >> $GITHUB_OUTPUT + fi + - name: Add Label env: MADARA: ${{ steps.check_madara.outputs.madara }} LIGHNOVELWP: ${{ steps.check_lighnovelwp.outputs.lighnovelwp }} HOTNOVELPUB: ${{ steps.check_hotnovelpub.outputs.hotnovelpub }} + FICTIONEER: ${{ steps.check_fictioneer.outputs.fictioneer }} GH_TOKEN: ${{ github.token }} run: | if [[ "$MADARA" == "true" ]]; then @@ -97,6 +114,8 @@ jobs: gh issue edit $ISSUE_NUMBER --add-label "Theme: Lighnovelwp" -R $REPO elif [[ "$HOTNOVELPUB" == "true" ]]; then gh issue edit $ISSUE_NUMBER --add-label "Theme: Hotnovelpub" -R $REPO + elif [[ "$FICTIONEER" == "true" ]]; then + gh issue edit $ISSUE_NUMBER --add-label "Theme: Fictioneer" -R $REPO else echo "No Theme Detected" >> $GITHUB_STEP_SUMMARY fi diff --git a/public/static/src/en/daoistquest/icon.png b/public/static/multisrc/fictioneer/daoistquest/icon.png similarity index 100% rename from public/static/src/en/daoistquest/icon.png rename to public/static/multisrc/fictioneer/daoistquest/icon.png diff --git a/public/static/multisrc/fictioneer/novelib/icon.png b/public/static/multisrc/fictioneer/novelib/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..e08bee797d0f3d395fa8068366542aa2e980e6c4 GIT binary patch literal 1401 zcmV-<1%~>GP)Q6k8$ZA&3P>5ClO*=oE3D+6OPxdcl*2q0l~55QG5* z1Li0`h!k%RQXfPpg7_kcP!ts=sZOBQNwFO*Gfpn&kw04MG!TWl%hh3f1XN3%dBlC- ztDpyg$FVMhfAx+4AU*{A2e`QJh6(0=;9tm7*k1>I3dn&mAVRzV3PAb)1AvDxXT8*U z1{ok%ccs8IfNvsR20euQD3E|!dtlB1cLT5A5&-u)q1J~D+z)&KaSC(^{0(3oJPkZz z^Ee1e0F*^VRYB4S0Ph1n>t5%(>MjqCFGBkc@OjV=fu|7Tz^8#}(53*SdBdsgeu3?g zn;G;A%5q08O0d3&dEizlXpI#7@b$pRK(3bN?!kN&XqTla@`^??BFieO$~0TiUZ)p9 z7mo$Ny-osjz-O>#(GB|_0e{KxG4RJF5hsBxEs2xBa8NKd9`Djo2SKYen&olpfU!S} zc^c8m(vmDKcf)HukN81Z`0Vzeh-{NI0%d8^?Sc^1fNWEiRZWd~f;2tjrMZbC0jRrN z06#{00YE_vw(|ObVM&qK+=d{sw8Dlc5>;jTTLmGA{$|d`wT%8|?T5Gnm;$OpDezJ! z0ndYmzy^2~sNz_m(TW&sdT1< zFLh>sXF;>>b)Ez^FeQ*`VcC1ru#No(#0=;(5CLRa$#76$Lpm&IwPVnzMgmjQO&X1w z^Bv$LI|clFbjkORX#NfO@4)k*-vPcZ)BXK9QR-gc+lVIsRh6l#`n0MtgRO#z$%HH` zuM=iEEU}?I7PI3M$2Vm8%fOd0f7HTCxzkAx>IIz|EvNRcrNe?jzYhD;FqB z3L`YIi)>Si0Yf9oc zFg6hbWLTHL$#I&|R2_a_0A8&J61lSfedW#Jz0-F!PlrhJAc$amGGTjA(42@!8iCFA zoc35u(%9RS_&su0-IZ&{0H8MZw-779H6VZO)y;r;4AF14q6(Pb*PzT7 z;OL-v@=&{UZbq1U5NAP?;2+H{uD$8r+$89yz+*>@wEY^WeyQ%V4;yG%J2xZXlSU`O zuL%mQNyLM;-;4Mw@Z#*^+V<`g-0M6F{9-hAuY>IC;XJO?8VGbVf*D9200000NkvXX Hu0mjfEj*A_ literal 0 HcmV?d00001 diff --git a/scripts/multisrc/fictioneer/generator.js b/scripts/multisrc/fictioneer/generator.js new file mode 100644 index 0000000..da53d43 --- /dev/null +++ b/scripts/multisrc/fictioneer/generator.js @@ -0,0 +1,33 @@ +import { readFileSync } from 'fs'; +import { fileURLToPath } from 'url'; +import { dirname, join } from 'path'; + +const folder = dirname(fileURLToPath(import.meta.url)); + +import list from './sources.json' with { type: 'json' }; + +export const generateAll = function () { + return list.map(source => { + console.log( + `[fictioneer] Generating: ${source.id}${' '.repeat(20 - source.id.length)}`, + ); + return generator(source); + }); +}; + +const generator = function generator(source) { + const readNovelFullTemplate = readFileSync(join(folder, 'template.ts'), { + encoding: 'utf-8', + }); + + const pluginScript = ` +${readNovelFullTemplate} +const plugin = new FictioneerPlugin(${JSON.stringify(source)}); +export default plugin; + `.trim(); + return { + lang: source.options?.lang || 'English', + filename: source.sourceName, + pluginScript, + }; +}; diff --git a/scripts/multisrc/fictioneer/sources.json b/scripts/multisrc/fictioneer/sources.json new file mode 100644 index 0000000..441f10b --- /dev/null +++ b/scripts/multisrc/fictioneer/sources.json @@ -0,0 +1,19 @@ +[ + { + "id": "daoistquest", + "sourceSite": "https://daoist.quest", + "sourceName": "Daoist Quest", + "options": { + "browsePage": "collection/novels", + "versionIncrements": 1 + } + }, + { + "id": "novelib", + "sourceSite": "https://novelib.com", + "sourceName": "NovelLib", + "options": { + "browsePage": "browse" + } + } +] diff --git a/src/plugins/english/daoistquest.ts b/scripts/multisrc/fictioneer/template.ts similarity index 65% rename from src/plugins/english/daoistquest.ts rename to scripts/multisrc/fictioneer/template.ts index ac73505..61d152b 100644 --- a/src/plugins/english/daoistquest.ts +++ b/scripts/multisrc/fictioneer/template.ts @@ -1,19 +1,40 @@ +import { CheerioAPI, load as loadCheerio, load } from 'cheerio'; import { fetchApi } from '@libs/fetch'; import { Plugin } from '@typings/plugin'; -import { Filters } from '@libs/filterInputs'; -import { load as loadCheerio } from 'cheerio'; +import { NovelStatus } from '@libs/novelStatus'; +import { Filters } from '../../../src/libs/filterInputs'; -class DaoistQuestPlugin implements Plugin.PluginBase { - id = 'daoistquest'; - name = 'Daoist Quest'; - icon = 'src/en/daoistquest/icon.png'; - site = 'https://daoist.quest'; - version = '1.0.0'; +type FictioneerOptions = { + browsePage: string; + lang?: string; + versionIncrements?: number; +}; + +export type FictioneerMetadata = { + id: string; + sourceSite: string; + sourceName: string; + options: FictioneerOptions; +}; + +class FictioneerPlugin implements Plugin.PluginBase { + id: string; + name: string; + icon: string; + site: string; + version: string; + options: FictioneerOptions; filters: Filters | undefined = undefined; - imageRequestInit?: Plugin.ImageRequestInit | undefined = undefined; - //flag indicates whether access to LocalStorage, SesesionStorage is required. - webStorageUtilized?: boolean; + constructor(metadata: FictioneerMetadata) { + this.id = metadata.id; + this.name = metadata.sourceName; + this.icon = `multisrc/fictioneer/${metadata.id.toLowerCase()}/icon.png`; + this.site = metadata.sourceSite; + const versionIncrements = metadata.options?.versionIncrements || 0; + this.version = `1.0.${0 + versionIncrements}`; + this.options = metadata.options; + } async popularNovels( pageNo: number, @@ -22,12 +43,19 @@ class DaoistQuestPlugin implements Plugin.PluginBase { filters, }: Plugin.PopularNovelsOptions, ): Promise { - if (pageNo !== 1) return []; - const req = await fetchApi(this.site + '/collection/novels/'); + const req = await fetchApi( + this.site + + '/' + + this.options.browsePage + + '/' + + (pageNo === 1 ? '' : 'page/' + pageNo + '/'), + ); const body = await req.text(); const loadedCheerio = loadCheerio(body); - return loadedCheerio('#featured-list > li > div > div') + return loadedCheerio( + '#featured-list > li > div > div, #list-of-stories > li > div > div', + ) .map((i, el) => { const novelName = loadedCheerio(el).find('h3 > a').text(); const novelCover = loadedCheerio(el) @@ -59,6 +87,7 @@ class DaoistQuestPlugin implements Plugin.PluginBase { .text() .split('|')[0] .replace('Author: ', '') + .replace('by ', '') .trim(); novel.cover = loadedCheerio('figure.story__thumbnail > a').attr('href'); novel.genres = loadedCheerio('div.tag-group > a') @@ -84,6 +113,12 @@ class DaoistQuestPlugin implements Plugin.PluginBase { }) .toArray(); + const status = loadedCheerio('span.story__status').text().trim(); + if (status === 'Ongoing') novel.status = NovelStatus.Ongoing; + if (status === 'Completed') novel.status = NovelStatus.Completed; + if (status === 'Cancelled') novel.status = NovelStatus.Cancelled; + if (status === 'Hiatus') novel.status = NovelStatus.OnHiatus; + return novel; } @@ -99,9 +134,9 @@ class DaoistQuestPlugin implements Plugin.PluginBase { searchTerm: string, pageNo: number, ): Promise { - if (pageNo !== 1) return []; const req = await fetchApi( - this.site + `?s=${encodeURIComponent(searchTerm)}&post_type=fcn_story`, + this.site + + `/${pageNo === 1 ? '' : 'page/' + pageNo + '/'}?s=${encodeURIComponent(searchTerm)}&post_type=fcn_story`, ); const body = await req.text(); const loadedCheerio = loadCheerio(body); @@ -126,5 +161,3 @@ class DaoistQuestPlugin implements Plugin.PluginBase { resolveUrl = (path: string, isNovel?: boolean) => this.site + '/' + path + '/'; } - -export default new DaoistQuestPlugin();