From 19f8b681ebf0e37b89e9fcef604d1762859bead1 Mon Sep 17 00:00:00 2001 From: Batorian <53831711+Batorian@users.noreply.github.com> Date: Fri, 12 Jul 2024 17:52:24 +0200 Subject: [PATCH] Plugin: Genesis studio (#1038) * genesis: started implementation * genesis: wip * genesis: implemented parse novel * genesis: added icon * genesis: wip * genesis: added chapters * genesis: wip * genesis: updated chapter name * genesis: parse chapter * genesis: revert version * genesis: fixed pages and custom css * genesis: update * genesis: edit ta-center * genesis: remove line-height * genesis: old genesis deprecated --- public/static/src/en/genesis/customCSS.css | 365 +++++++++++++++++++++ public/static/src/en/genesis/icon.png | Bin 0 -> 1814 bytes scripts/multisrc/lightnovelwp/sources.json | 2 +- src/plugins/english/genesis.ts | 168 ++++++++++ src/types/plugin.ts | 2 +- 5 files changed, 535 insertions(+), 2 deletions(-) create mode 100644 public/static/src/en/genesis/customCSS.css create mode 100644 public/static/src/en/genesis/icon.png create mode 100644 src/plugins/english/genesis.ts diff --git a/public/static/src/en/genesis/customCSS.css b/public/static/src/en/genesis/customCSS.css new file mode 100644 index 0000000..42ebf48 --- /dev/null +++ b/public/static/src/en/genesis/customCSS.css @@ -0,0 +1,365 @@ +.red-box .red-text, +.blue-box .blue-text, +.gold-box .gold-text, +.silver-box .silver-text { + display:inline-flex; + align-items:start; + justify-content:start; + text-align:left; + flex-direction:column; + margin-left:0; + margin-bottom:0; + margin-top:0 +} +.red-box .red-text p, +.blue-box .blue-text p, +.gold-box .gold-text p, +.silver-box .silver-text p { + text-align:left +} +.ta-center { + display:flex; + text-align:center!important; + align-items:center!important; + justify-content:center!important; + margin-left:auto; + margin-right:auto +} +.ta-between { + align-items:center!important +} +.blue-box, +.red-box, +.gold-box, +.silver-box { + overflow-wrap:break-word; + word-wrap:break-word; + word-break:break-word +} +.blue-box { + display:flex; + flex-direction:column; + justify-content:center; + min-width:250px; + max-width:500px!important; + box-sizing:content-box; + width:auto; + margin:15px auto; + box-shadow:0 0 10px 1px #00219b; + border-radius:5px; + background-color:#000; + padding:20px; + font-size:25px; + color:#fff; + font-family: Oswald Variable, serif +} +.blue-box div { + text-indent:0; + max-width:500px!important +} +.blue-box p { + text-align:center; + text-indent:0; + margin-bottom:.75rem; + margin-top:.75rem; + max-width:500px!important +} +.blue-title { + display:flex; + flex-direction:column; + text-align:center; + align-items:center; + justify-content:center; + padding-left:0; + margin-left:0; + color:#fff; + font-weight:700; + text-shadow:-1px 5px 13px #004fff,-1px 0 10px #002775; + border-bottom:3px solid #fff; + padding-bottom:15px; + margin-bottom:15px; + max-width:500px!important +} +.blue-text { + display:flex; + flex-direction:row; + align-items:start; + justify-content:center; + text-shadow:-1px 5px 13px #004fff,-1px 0 10px #002775; + font-weight:400; + max-width:500px!important; + font-family: Quattrocento, serif +} +.blue-text p { + text-align:center; + text-indent:0; + margin-bottom:.25rem; + margin-top:.25rem; + max-width:500px!important +} +.red-box { + display:flex; + flex-direction:column; + justify-content:center; + min-width:250px; + max-width:500px!important; + padding:20px; + box-sizing:content-box; + width:auto; + margin:15px auto; + border:solid #750b00e3; + box-shadow:0 0 20px 3px #750b0070; + border-radius:5px; + background-color:#000; + font-size:25px; + color:#fff; + font-family: Oswald Variable, serif +} +.red-box div { + text-indent:0; + max-width:500px!important +} +.red-box p { + text-align:center; + text-indent:0; + margin-bottom:.25rem; + margin-top:.25rem; + max-width:500px!important +} +.red-title { + display:flex; + flex-direction:column; + text-align:center; + align-items:center; + justify-content:center; + padding-left:0; + margin-left:0; + color:#ff4348; + font-weight:700; + text-shadow:-1px 5px 13px #ff230c,-1px 0px 10px #750b00; + border-bottom:3px solid #fff; + padding-bottom:15px; + margin-bottom:15px; + max-width:500px!important +} +.red-text { + display:flex; + flex-direction:row; + align-items:center; + justify-content:center; + text-shadow:-1px 5px 13px #ff230c,-1px 0px 10px #750b00; + font-weight:400; + max-width:500px!important; + margin-left:auto; + margin-right:auto; + font-family: Quattrocento, serif +} +.red-text p { + text-align:center; + text-indent:0; + margin-bottom:.25rem; + margin-top:.25rem; + max-width:500px!important +} +.gold-box { + display:flex; + flex-direction:column; + justify-content:center; + min-width:250px; + padding:20px; + box-sizing:content-box; + width:auto; + margin:15px auto; + border:solid #e0cc00; + box-shadow:0 0 10px 1px #e0cc00; + border-radius:5px; + background-color:#000; + font-size:25px; + color:#fff; + font-family: Oswald Variable, serif; + max-width:500px!important +} +.gold-box div { + text-indent:0; + max-width:500px!important +} +.gold-box p { + text-align:center; + text-indent:0; + margin-bottom:.75rem; + margin-top:.75rem; + max-width:500px!important +} +.gold-title { + display:flex; + flex-direction:column; + text-align:center; + align-items:center; + justify-content:center; + padding-left:0; + margin-left:0; + color:#fff; + font-weight:700; + text-shadow:-1px 5px 13px #e0cc00,-1px 0px 10px #544d00; + border-bottom:3px solid #fff; + padding-bottom:15px; + margin-bottom:15px; + max-width:500px!important +} +.gold-text { + display:flex; + flex-direction:row; + align-items:center; + justify-content:center; + text-align:center; + text-shadow:-1px 5px 13px #e0cc00,-1px 0 10px #e0cc00; + row-gap:1.5rem; + font-weight:400; + max-width:500px!important; + font-family: Quattrocento, serif +} +.gold-text p { + text-align:center; + text-indent:0; + margin-bottom:.25rem; + margin-top:.25rem; + max-width:500px!important +} +.gold-letter { + display:flex; + flex-direction:column; + align-items:center; + justify-content:center; + text-shadow:-1px 5px 13px #e0cc00,-1px 0 10px #e0cc00; + row-gap:1.5rem; + font-weight:700; + font-family: Amita, serif; + max-width:500px!important; + margin-left:auto; + margin-right:auto +} +.gold-letter p { + text-align:center; + text-indent:0; + margin-bottom:.25rem; + margin-top:.25rem; + max-width:500px!important +} +.silver-box { + display:flex; + flex-direction:column; + justify-content:center; + min-width:250px; + padding:20px; + box-sizing:content-box; + width:auto; + margin:15px auto; + border:solid #c2c2c2; + box-shadow:0 0 10px 1px #737373; + border-radius:5px; + background-color:#000; + font-size:25px; + color:#fff; + font-family: Oswald Variable, serif; + max-width:500px!important +} +.silver-box div { + text-indent:0; + max-width:500px!important +} +.silver-box p { + text-align:center; + text-indent:0; + margin-bottom:.75rem; + margin-top:.75rem; + max-width:500px!important +} +.silver-title { + display:flex; + flex-direction:column; + text-align:center; + align-items:center; + justify-content:center; + padding-left:0; + margin-left:0; + color:#fff; + font-weight:700; + text-shadow:-1px 5px 13px #b4b4b4,-1px 0 10px #737373; + border-bottom:3px solid #fff; + padding-bottom:15px; + margin-bottom:15px; + max-width:500px!important +} +.silver-text { + display:flex; + flex-direction:row; + align-items:center; + justify-content:center; + text-shadow:-1px 5px 13px #b4b4b4,-1px 0 10px #737373; + row-gap:1.5rem; + font-weight:400; + max-width:500px!important; + margin: 2rem auto; + font-family: Quattrocento, serif +} +.silver-text p { + text-align:center; + text-indent:0; + margin-bottom:.25rem; + margin-top:.25rem; + max-width:500px!important +} +.silver-letter { + display:flex; + flex-direction:column; + text-align:center; + align-items:center; + justify-content:center; + text-shadow:-1px 5px 13px #b4b4b4,-1px 0 10px #737373; + row-gap:1.5rem; + font-weight:700; + max-width:500px!important; + margin: 2rem auto; + font-family: MedievalSharp, serif +} +.silver-letter p { + text-align:center; + text-indent:0; + margin-bottom:.25rem; + margin-top:.25rem; + max-width:500px!important +} +.blue-text, +.gold-text, +.silver-text, +.red-text, +.blue-box, +.red-box, +.gold-box, +.silver-box, +.red-title, +.gold-title, +.silver-title, +.blue-title, +.blue-text p, +.gold-text p, +.silver-text p, +.red-text p { + text-indent:0!important +} +div.red-text, +div.gold-text, +div.silver-text, +div.blue-text { + display:flex; + flex-direction:column; + margin-bottom:2.25rem; + margin-top:2.25rem +} +.blue-box .blue-text p, +.red-box .red-text p, +.gold-box .gold-text p, +.silver-box .silver-text p { + display:flex; + flex-direction:column +} diff --git a/public/static/src/en/genesis/icon.png b/public/static/src/en/genesis/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..e3bb09de219030a3a81214bb46a8f5deff77064f GIT binary patch literal 1814 zcmZ{lX*Ao37Qp|t^rx-i1Yu+C>fTFd#0Sw=r3P-Uw{KH~4x6raG|UV|TyjbR(WtMijvD_M z-B7Sq{*65v&?MT-)H0R6fpa&izo3tuaOiFsC3>ylg_UoC_1snI38SzFMo zr1J;Pp~=behp-UN$@13T#}o6hqqwo7qIF79IMw=^aPD7!j;`8&wgbiQhbQ;8_gwmM zIo72`fq!B6o92sO&YKJOCNB#}7M!;RU3tMCl3^zLgRR|>W?KeJDYwN+jLYALk(0vm z8>>Vu!8RbHnk=&&QUwZhT!E}achK2)u+EL?{3CzgRuO!nk6CrTd9v#D{bJyw4eF3%0X6kZz&$z4xTbub$aupjmf7=6r0b zttUZ93}y@xk|&k7-f)1t3wR}5jH(|J4bQo@)K~T-cSLj5R|c}K)plkZgLK)<5rZuc zxeh21h~Dw9NG@@zd5^~i2MEISvq5apbf8{Ps%$S`1u?j$GHI$0or9taj1X1+j9?SVadJg82ArsKb(6v-8JQp@W9FD@au>zLp+|Ae!7x z>ROL(U;nJbN&1&@_LQ0|u26NG2H%x0&T3Y^20yau&-C$EwiR3yJH|0?<-J9pmZI*P zCnPD^%}7LMPT)7*`#sDkx+q_*ATzKKA_`)n-^erPbUNNAZ=({%WG$BZ+dSZ|yP9WO;C)V<4GmKdDZBUoje~Ae26aXURYy?hEhEQBsr8dfj@+65NoQL z&8tBAND%BjJ3fc-!$^wygrD4OrY!B_IS;$=Yun}vVn&3zv0mw0;V(}vwQa}9qJWRT zZwZ{yRqN+s&o>Vs(oxMf7{^5u}UAEtq1(PhpD**Z(+sP-T~&+lQ6 zF&pYTJTg6+%?{}SsgpBuN5!K}vf$ugXR)sFJ4lZ9{0lJ{?x>77jx(s4(W*s<_uARp zWTLhyN6)2MpH)4ipn@+K`9?b0<{b}W3VrTvVJXgPv*7e$#T@qC(jB9Qmm0SL`|6;a zjx0rlg^1f2qpHAf@_VcPakQ1#P{tgdqZ2YHc(qS!YAt^rlTrsuESo}aiCWU0@Chnc zc{3|=sIc7@NZ~|U~(C3Df;{I^k5ABJreqnd=rcX|b*<^oY`0HOH+s34ZR z|1yh7;#Z9|jYLx|*-F5qN?en;1UL|_@N9t0R>{QpJZ1P%B{a6}idPmh264yYB$Mf! zmL|AO$+OHZ|0$cVCW>N@V)!w&ZF5yr$N2U@BaXcJt8j zS@|`J?!~icK1GwWSBwG=;0xbO);BO!$n?qlj1}}oidG>D{&NlcAKq9kF{w3c5^Llf z8xl_sXDxO9tFi#jw}0PKj2ATC-Q-z(r7}9Dq9wMFa_5KQNuOVxWBpELOO&G%_Pfr` zp9}a-@viL2xnxPf3ia%t|BX!L_4rO4w*U#Ys>fN$29(m4MD{uu>rtAo%8E8QbwR8<#p}MBr&^5Xag_=U4qQ0Ma{!a)F!3X$8|Gf}z l=G@5@)c>SD literal 0 HcmV?d00001 diff --git a/scripts/multisrc/lightnovelwp/sources.json b/scripts/multisrc/lightnovelwp/sources.json index 859b6c7..de42924 100644 --- a/scripts/multisrc/lightnovelwp/sources.json +++ b/scripts/multisrc/lightnovelwp/sources.json @@ -93,7 +93,7 @@ { "id": "genesistls", "sourceSite": "https://genesistls.com/", - "sourceName": "GenesisTls", + "sourceName": "GenesisTls (Deprecated)", "options": { "lang": "English", "reverseChapters": false, diff --git a/src/plugins/english/genesis.ts b/src/plugins/english/genesis.ts new file mode 100644 index 0000000..010fe83 --- /dev/null +++ b/src/plugins/english/genesis.ts @@ -0,0 +1,168 @@ +/* eslint-disable no-case-declarations */ +import { fetchApi } from '@libs/fetch'; +import { Filters, FilterTypes } from '@libs/filterInputs'; +import { Plugin } from '@typings/plugin'; + +class Genesis implements Plugin.PluginBase { + id = 'genesistudio'; + name = 'Genesis'; + icon = 'src/en/genesis/icon.png'; + customCSS = 'src/en/genesis/customCSS.css'; + site = 'https://genesistudio.com'; + version = '1.0.0'; + imageRequestInit?: Plugin.ImageRequestInit | undefined = { + headers: { + 'referrer': this.site, + }, + }; + + async parseNovels(json: any[]): Promise { + const assets = 'https://edit.genesistudio.com/assets/'; + const format = '?format=auto&quality=70&width=400&height=600'; + + return json.map((novel: any) => { + return { + name: novel.novel_title, + path: `/novels/${novel.abbreviation}`, + cover: `${assets}${novel.cover}${format}`, + }; + }); + } + + async popularNovels( + pageNo: number, + { + showLatestNovels, + filters, + }: Plugin.PopularNovelsOptions, + ): Promise { + if (pageNo !== 1) return []; + + let link = `https://genesistudio.com/api/search?`; + if (showLatestNovels) { + link += 'sort=Recent'; + } else { + if (filters!.genres.value.length) { + link += filters!.genres.value.join('&'); + } + link += `&${filters!.storyStatus.value}&${filters!.sort.value}`; + } + + const json = await fetchApi(link).then(r => r.json()); + + return this.parseNovels(json); + } + + async parseNovel(novelPath: string): Promise { + const url = `${this.site}${novelPath}/__data.json?x-sveltekit-invalidated=001`; + const json = await fetchApi(url).then(r => r.json()); + + const nodes = json.nodes; + const data = nodes + .filter((node: { type: string }) => node.type === 'data') + .map((node: { data: any }) => node.data)[0]; + const novelData = data[data[0].novel]; + + const assets = 'https://edit.genesistudio.com/assets/'; + const format = '?format=auto&quality=70&width=400&height=600'; + + const novel: Plugin.SourceNovel = { + path: novelPath, + name: data[novelData.novel_title], + cover: `${assets}${data[novelData.cover]}${format}`, + summary: data[novelData.synopsis], + author: data[novelData.author], + status: data[novelData.serialization], + }; + + novel.genres = data[novelData.genres] + .map((index: number) => data[index]) + .join(','); + + const chapterData = data[data[0].chapters]; + const freeChapterData = chapterData.free; + // const premiumChapterData = chapterData.premium; + + novel.chapters = data[freeChapterData] + .map((index: number) => data[index]) + .map((chapter: any) => { + return { + name: `Chapter ${data[chapter.chapter_number]}: ${data[chapter.chapter_title]}`, + path: `/viewer/${data[chapter.id]}`, + releaseTime: data[chapter.date_created], + chapterNumber: data[chapter.chapter_number], + }; + }) + .reverse(); + + return novel; + } + + async parseChapter(chapterPath: string): Promise { + const url = `${this.site}${chapterPath}/__data.json?x-sveltekit-invalidated=001`; + const json = await fetchApi(url).then(r => r.json()); + + const nodes = json.nodes; + const data = nodes + .filter((node: { type: string }) => node.type === 'data') + .map((node: { data: any }) => node.data)[0]; + + return data[data[0].content]; + } + + async searchNovels( + searchTerm: string, + pageNo: number, + ): Promise { + if (pageNo !== 1) return []; + + const url = `${this.site}/api/search?serialization=All&sort=Popular&title=${searchTerm}`; + const json = await fetchApi(url).then(r => r.json()); + + return this.parseNovels(json); + } + + filters = { + sort: { + label: 'Sort Results By', + value: 'sort=Popular', + options: [ + { label: 'Popular', value: 'sort=Popular' }, + { label: 'Recent', value: 'sort=Recent' }, + { label: 'Views', value: 'sort=Views' }, + ], + type: FilterTypes.Picker, + }, + storyStatus: { + label: 'Status', + value: 'serialization=All', + options: [ + { label: 'All', value: 'serialization=All' }, + { label: 'Ongoing', value: 'serialization=Ongoing' }, + { label: 'Completed', value: 'serialization=Completed' }, + ], + type: FilterTypes.Picker, + }, + genres: { + label: 'Genres', + value: [], + options: [ + { label: 'Action', value: 'genres=Action' }, + { label: 'Comedy', value: 'genres=Comedy' }, + { label: 'Drama', value: 'genres=Drama' }, + { label: 'Fantasy', value: 'genres=Fantasy' }, + { label: 'Harem', value: 'genres=Harem' }, + { label: 'Martial Arts', value: 'genres=Martial+Arts' }, + { label: 'Modern', value: 'genres=Modern' }, + { label: 'Mystery', value: 'genres=Mystery' }, + { label: 'Psychological', value: 'genres=Psychological' }, + { label: 'Romance', value: 'genres=Romance' }, + { label: 'Slice of life', value: 'genres=Slice+of+Life' }, + { label: 'Tragedy', value: 'genres=Tragedy' }, + ], + type: FilterTypes.CheckboxGroup, + }, + } satisfies Filters; +} + +export default new Genesis(); diff --git a/src/types/plugin.ts b/src/types/plugin.ts index a97f0da..8f0a547 100644 --- a/src/types/plugin.ts +++ b/src/types/plugin.ts @@ -24,7 +24,7 @@ export namespace Plugin { cover?: string; } export interface SourceNovel extends NovelItem { - /** Comma separated genre list */ + /** Comma separated genre list -> "action,fantasy,romance" */ genres?: string; summary?: string; author?: string;