From f0b59652a55357196435bc0ea2ce7e98093b5f2d Mon Sep 17 00:00:00 2001 From: Adam Kemish <49228220+Soopyboo32@users.noreply.github.com> Date: Sat, 25 Jan 2025 22:26:13 +0800 Subject: [PATCH] Add inkitt (#1459) * Add inkitt * Clean up --- public/static/src/en/inkitt/icon.png | Bin 0 -> 1494 bytes src/plugins/english/inkitt.ts | 160 +++++++++++++++++++++++++++ 2 files changed, 160 insertions(+) create mode 100644 public/static/src/en/inkitt/icon.png create mode 100644 src/plugins/english/inkitt.ts diff --git a/public/static/src/en/inkitt/icon.png b/public/static/src/en/inkitt/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..b0215d2f272956c75cc4a6e2405df3dd5d33c289 GIT binary patch literal 1494 zcmZ{kc~BB~6vuyJo63-iVqTy1pej=}( z;-p+`KJ4v50vq4rMrX}s05%D|Nc;Uf`}zLf2|s%voTUSj`|r6Js9&La*d2?4O_Vy+ zK}+&?nJ@j;AU#lp8uR%!)$Nc-3M-2<1-KnNT z^&BE}KT*3d+h#6Bkc6yZyyLZsK6Gi#6%%|8*CA~Ey%}~!dCM{Rt}kR zC3W;e>;f|dj0PspN|N=R?-f)s1mhg44%!UjN~2|H6KNb^M@2oArwGQ6*v(3%(b3UX zRTwX3MWr7F!DzU8e|6Qb_48DBRTVBsqq+x6(#M5$u;jCsjCcE7cV6f; zH#3785Y>kWpjK>5Rgan&l#_P2Rd=`;Tlpe-r>Cd+G2*TI`g{?HW%EU5XRcJ#TkZce z-FxvWF1#-ZhJIhD>pChePl5!?A0D&^%92~Zm%USPIO*3+4wW|v~}*tiOJKYn4qO{u`Eb-a($w&&;8a&u4L3e zmn`%wYlct|`_^aXW#XnXCl&;l4*Kk1R1|HNUXvfFTUf~BJLE-}I%#|?M_`;?Z&*Oh z-mNH_g&GZXPSk+%Qo8-saSU(C>(WwDa0E=FUi>brn}*R+$u~(t>JHQJzEqoJ3Id?2 zEOSGxtSfmXWp}IesGjIcHW0XBeG*3NTxQNh>dx$BSST8AYvwQTTtY7$331E?aDudw z>eMqdpqHw!6D>b0I$uv$7ZS|RHs%ob)IOY2Mdmg`8ky9`9gkFQ)Dt6qM38eME%qHl zEz^UbI}7lMwCr^i*Dn%J^lE89_CTgKe7@k(sX)z%((?3@tPO}M_CY4x%TkX_LG}mF z!#7|vlJu1+&r8c?D3prp@xZS$-M;R9>NEh$NR_9n6w(zG2p02}<&w9(s%NY%9Y(3&h{eq0*sw;|<Vb$c#M1q&r3&qbmjM z!tb)T#@kr$viHLi9PJ$(?RQz>@s4=Bkxh~Dzks-eNJbRv|AClT>l!6s@s9(O5l2sE b9*Rr+5613qlkhqMQON)=vJa_|NIUZvn2(qz literal 0 HcmV?d00001 diff --git a/src/plugins/english/inkitt.ts b/src/plugins/english/inkitt.ts new file mode 100644 index 0000000..113164c --- /dev/null +++ b/src/plugins/english/inkitt.ts @@ -0,0 +1,160 @@ +import { fetchApi } from '@libs/fetch'; +import { Plugin } from '@typings/plugin'; +import { Filters, FilterTypes } from '@libs/filterInputs'; +import { load as loadCheerio } from 'cheerio'; +import { NovelStatus } from '@libs/novelStatus'; + +class InkittPlugin implements Plugin.PluginBase { + id = 'inkitt'; + name = 'Inkitt'; + icon = 'src/en/inkitt/icon.png'; + site = 'https://www.inkitt.com'; + version = '1.0.0'; + imageRequestInit?: Plugin.ImageRequestInit | undefined = undefined; + + //flag indicates whether access to LocalStorage, SesesionStorage is required. + webStorageUtilized?: boolean; + + async popularNovels( + pageNo: number, + { + showLatestNovels, + filters, + }: Plugin.PopularNovelsOptions, + ): Promise { + let req; + if (filters?.genres?.value) { + req = await fetchApi( + this.site + + `/genre/${filters.genres.value}/${pageNo}?period=alltime&sort=popular`, + ); + } else { + req = await fetchApi( + this.site + `/trending_stories?page=${pageNo}&period=alltime`, + ); + } + let data; + try { + data = await req.json(); + } catch (e) { + throw new Error('Failed to load novels, try opening in webview.'); + } + + return data.stories.map((novel: any) => { + return { + name: novel.title, + path: this.getPath(novel), + cover: + novel.vertical_cover.url || + novel.vertical_cover.iphone || + novel.cover.url, + }; + }); + } + + getPath(novel: any) { + return novel.category_one + '/' + novel.id; + } + + async parseNovel(novelPath: string): Promise { + let req = await fetchApi(this.site + `/stories/${novelPath}`); + let text = await req.text(); + let loadedCheerio = loadCheerio(text); + + const novel: Plugin.SourceNovel = { + path: novelPath, + name: loadedCheerio('h1.story-title').text(), + }; + + novel.author = loadedCheerio('a.author-link').text(); + + novel.genres = loadedCheerio('dd.genres > a') + .map((i, el) => loadedCheerio(el).text()) + .toArray() + .join(', '); + const status = loadedCheerio('div.dlc > dl > dd').text().trim(); + if (status === 'Complete') novel.status = NovelStatus.Completed; + if (status === 'Ongoing') novel.status = NovelStatus.Ongoing; + + const apiReq = await fetchApi( + this.site + `/api/stories/${novelPath.split('/')[1]}`, + ); + const apiData = await apiReq.json(); + novel.cover = apiData.vertical_cover.url; + + novel.summary = loadedCheerio('p.story-summary').text(); + + novel.chapters = apiData.chapters.map((c: any) => { + return { + name: c.name, + path: novelPath + '/chapters/' + c.chapter_number, + chapterNumber: c.chapter_number, + }; + }); + return novel; + } + + async parseChapter(chapterPath: string): Promise { + const req = await fetchApi(this.site + '/stories/' + chapterPath); + const text = await req.text(); + const loadedCheerio = loadCheerio(text); + + return loadedCheerio('div#chapterText').html() || ''; + } + + async searchNovels( + searchTerm: string, + pageNo: number, + ): Promise { + const req = await fetchApi( + this.site + + `/api/2/search/title?q=${encodeURIComponent(searchTerm)}&page=${pageNo}`, + ); + let data; + try { + data = await req.json(); + } catch (e) { + throw new Error('Failed to search novels, try opening in webview.'); + } + + return data.stories.map((novel: any) => { + return { + name: novel.title, + path: this.getPath(novel), + cover: + novel.vertical_cover.url || + novel.vertical_cover.iphone || + novel.cover.url, + }; + }); + } + + resolveUrl = (path: string, isNovel?: boolean) => + this.site + '/stories/' + path; + + filters = { + genres: { + type: FilterTypes.Picker, + label: 'Genre', + value: '', + options: [ + { 'label': 'Sci-Fi', 'value': 'scifi' }, + { 'label': 'Fantasy', 'value': 'fantasy' }, + { 'label': 'Adventure', 'value': 'adventure' }, + { 'label': 'Mystery', 'value': 'mystery' }, + { 'label': 'Action', 'value': 'action' }, + { 'label': 'Horror', 'value': 'horror' }, + { 'label': 'Humor', 'value': 'humor' }, + { 'label': 'Erotica', 'value': 'erotica' }, + { 'label': 'Poetry', 'value': 'poetry' }, + { 'label': 'Other', 'value': 'other' }, + { 'label': 'Thriller', 'value': 'thriller' }, + { 'label': 'Romance', 'value': 'romance' }, + { 'label': 'Children', 'value': 'children' }, + { 'label': 'Drama', 'value': 'drama' }, + ], + }, + } satisfies Filters; +} + +export default new InkittPlugin();