diff --git a/src/NHentai/NHentai.ts b/src/NHentai/NHentai.ts index b02f893..b686a7c 100644 --- a/src/NHentai/NHentai.ts +++ b/src/NHentai/NHentai.ts @@ -29,7 +29,8 @@ import { parseMangaDetails, parseChapters, parseChapterDetails, - parseSearch + parseSearch, + addToReadMangaIds } from './NHentaiParser' import { @@ -43,7 +44,7 @@ import { popularTags } from './tags.json' const NHENTAI_URL = 'https://nhentai.net' export const NHentaiInfo: SourceInfo = { - version: '4.0.8', + version: '4.0.9', name: 'nhentai', icon: 'icon.png', author: 'NotMarek & Netsky', @@ -134,18 +135,11 @@ export class NHentai implements SearchResultsProviding, MangaProviding, ChapterP const jsonData = this.parseJson(response) // Add the manga ID to the read list - await this.addToReadMangaIds(mangaId) + await addToReadMangaIds(this.stateManager, mangaId) return parseChapterDetails(jsonData, mangaId) } - // Method to store read manga IDs - async addToReadMangaIds(mangaId: string): Promise { - const readMangaIds = await this.stateManager.retrieve('read_manga_ids') ?? {} - readMangaIds[`read_manga_${mangaId}`] = true - await this.stateManager.store('read_manga_ids', readMangaIds) - } - async getSearchTags(): Promise { const arrayTags: Tag[] = [] @@ -173,44 +167,23 @@ export class NHentai implements SearchResultsProviding, MangaProviding, ChapterP }) } - // When given number query - if (/^\d+$/.test(title)) { - const request = App.createRequest({ - url: `${NHENTAI_URL}/api/gallery/${title}`, - method: 'GET' - }) - const response = await this.requestManager.schedule(request, 1) - this.CloudFlareError(response.status) - - const jsonData = this.parseJson(response) - return App.createPagedResults({ - results: parseSearch({ result: [jsonData], num_pages: 1, per_page: 1 }), - metadata: { - page: page + 1, - stopSearch: true - } - }) - - // Normal search query - } else { - const q: string = encodeURIComponent(`${title} ${query?.includedTags?.map((x: Tag) => ` +${x.id}`)} `) + await this.generateQuery() + const q: string = encodeURIComponent(`${title} ${query?.includedTags?.map((x: Tag) => ` +${x.id}`)} `) + await this.generateQuery() + const request = App.createRequest({ + url: `${NHENTAI_URL}/api/galleries/search?query=${q}&page=${page}&sort=${await this.sortOrder(this.stateManager)}`, + method: 'GET' + }) + const response = await this.requestManager.schedule(request, 1) + this.CloudFlareError(response.status) - const request = App.createRequest({ - url: `${NHENTAI_URL}/api/galleries/search?query=${(q)}&page=${page}&sort=${await this.sortOrder(this.stateManager)}`, - method: 'GET' - }) - const response = await this.requestManager.schedule(request, 1) - this.CloudFlareError(response.status) + const jsonData = this.parseJson(response) + const results = parseSearch(jsonData, readMangaIds ?? []) - const jsonData = this.parseJson(response) - const results = parseSearch(jsonData).filter(manga => !readMangaIds.includes(manga.mangaId)) - return App.createPagedResults({ - results, - metadata: { - page: page + 1 - } - }) - } + return App.createPagedResults({ + results, + metadata: { + page: page + 1 // Increment by one page + } + }) } async getHomePageSections(sectionCallback: (section: HomeSection) => void): Promise { @@ -291,8 +264,7 @@ export class NHentai implements SearchResultsProviding, MangaProviding, ChapterP if (hasNoResults(jsonData)) { return } - section.sectionID.items = parseSearch(jsonData).filter(manga => !readMangaIds.includes(manga.mangaId)) - + section.sectionID.items = parseSearch(jsonData, readMangaIds ?? []) sectionCallback(section.sectionID) }) ) @@ -305,17 +277,18 @@ export class NHentai implements SearchResultsProviding, MangaProviding, ChapterP let page: number = metadata?.page ?? 1 const skipReadManga = await this.stateManager.retrieve('skip_read_manga') ?? false const readMangaIds = skipReadManga ? await this.getReadMangaIds() : [] + const request = App.createRequest({ url: `${NHENTAI_URL}/api/galleries/search?query=${await this.generateQuery()}&sort=${homepageSectionId}&page=${page}`, method: 'GET' }) - const response = await this.requestManager.schedule(request, 1) this.CloudFlareError(response.status) + const jsonData = this.parseJson(response) + const results = parseSearch(jsonData, readMangaIds ?? []) - page++ - const results = parseSearch(jsonData).filter(manga => !readMangaIds.includes(manga.mangaId)) + page += 1 // Increment by one page return App.createPagedResults({ results, metadata: { @@ -329,7 +302,7 @@ export class NHentai implements SearchResultsProviding, MangaProviding, ChapterP if (!allData) { return [] } - return Object.keys(allData).filter(key => key.startsWith('read_manga_')).map(key => key.replace('read_manga_', '')) + return Object.keys(allData).map(key => key) } CloudFlareError(status: number): void { @@ -360,8 +333,10 @@ export class NHentai implements SearchResultsProviding, MangaProviding, ChapterP } async generateQuery(): Promise { - const query = await this.language(this.stateManager) + await this.extraArgs(this.stateManager) - return encodeURIComponent(query) + const langQuery = await this.language(this.stateManager) + const extraArgs = await this.extraArgs(this.stateManager) + const minPages = await this.stateManager.retrieve('min_pages') ?? 0 + return encodeURIComponent(`${langQuery} ${extraArgs} pages:>${minPages}`) } async language(stateManager: SourceStateManager): Promise { diff --git a/src/NHentai/NHentaiParser.ts b/src/NHentai/NHentaiParser.ts index 84ef906..b51394b 100644 --- a/src/NHentai/NHentaiParser.ts +++ b/src/NHentai/NHentaiParser.ts @@ -3,7 +3,8 @@ import { ChapterDetails, PartialSourceManga, Tag, - Chapter + Chapter, + SourceStateManager } from '@paperback/types' import { NHLanguages } from './NHentaiHelper' @@ -34,7 +35,7 @@ export const parseMangaDetails = (data: Gallery): SourceManga => { image: `https://t.nhentai.net/galleries/${data.media_id}/cover.${typeOfImage(data.images.cover)}`, status: 'Completed', tags: [App.createTagSection({ id: 'tags', label: 'Tags', tags: tags })], - desc: `Pages: ${data.num_pages}` + desc: `Pages: ${data.num_pages} | Favorites: ${data.num_favorites}` }) }) } @@ -60,29 +61,34 @@ export const parseChapterDetails = (data: Gallery, mangaId: string): ChapterDeta }) } -export const parseSearch = (data: QueryResponse): PartialSourceManga[] => { +export const parseSearch = (data: QueryResponse, readMangaIds: string[]): PartialSourceManga[] => { const tiles: PartialSourceManga[] = [] const collectedIds: string[] = [] if (!data?.result) { console.log(JSON.stringify(data)) - throw new Error('JSON NO RESULT ERROR!\n\nYou\'ve like set too many additional arguments in this source\'s settings, remove some to see results!\nSo search with tags you need to use arguments like shown in the sourc\'s settings!') + throw new Error('JSON NO RESULT ERROR!\n\nYou\'ve like set too many additional arguments in this source\'s settings, remove some to see results!\nSo search with tags you need to use arguments like shown in the source\'s settings!') } for (const gallery of data.result) { - - if (collectedIds.includes(gallery.id.toString())) continue + if (collectedIds.includes(gallery.id.toString()) || readMangaIds.includes(gallery.id.toString())) continue tiles.push(App.createPartialSourceManga({ image: `https://t.nhentai.net/galleries/${gallery.media_id}/cover.${typeOfImage(gallery.images.cover)}`, title: gallery.title.pretty, mangaId: gallery.id.toString(), - subtitle: NHLanguages.getName(getLanguage(gallery)) + subtitle: NHLanguages.getName(getLanguage(gallery)).substring(0, 3) + ' | Pgs: ' + gallery.num_pages })) collectedIds.push(gallery.id.toString()) } return tiles } +export const addToReadMangaIds = async (stateManager: SourceStateManager, mangaId: string): Promise => { + const readMangaIds = await stateManager.retrieve('read_manga_ids') ?? {} + readMangaIds[mangaId] = true + await stateManager.store('read_manga_ids', readMangaIds) +} + // Utility function capitalizeTags(str: string) { return str.split(' ').map(word => { diff --git a/src/NHentai/NHentaiSettings.ts b/src/NHentai/NHentaiSettings.ts index 378d6ca..a7645af 100644 --- a/src/NHentai/NHentaiSettings.ts +++ b/src/NHentai/NHentaiSettings.ts @@ -21,6 +21,9 @@ export const getExtraArgs = async (stateManager: SourceStateManager): Promise => { + return (await stateManager.retrieve('min_pages') as number) ?? 0 +} export const settings = (stateManager: SourceStateManager): DUINavigationButton => { return App.createDUINavigationButton({ @@ -36,9 +39,10 @@ export const settings = (stateManager: SourceStateManager): DUINavigationButton await Promise.all([ getLanguages(stateManager), getSortOrders(stateManager), - getExtraArgs(stateManager) + getExtraArgs(stateManager), + getMinPages(stateManager) ]) - return await [ + return [ App.createDUISelect({ id: 'languages', label: 'Languages', @@ -83,6 +87,14 @@ export const settings = (stateManager: SourceStateManager): DUINavigationButton get: async () => await stateManager.retrieve('skip_read_manga') ?? false, set: async (newValue) => await stateManager.store('skip_read_manga', newValue) }) + }), + App.createDUIInputField({ + id: 'min_pages', + label: 'Minimum Pages', + value: App.createDUIBinding({ + get: () => getMinPages(stateManager), + set: async (newValue: number) => await stateManager.store('min_pages', newValue) + }) }) ] }, @@ -102,7 +114,8 @@ export const resetSettings = (stateManager: SourceStateManager): DUIButton => { await Promise.all([ stateManager.store('languages', null), stateManager.store('sort_order', null), - stateManager.store('extra_args', null) + stateManager.store('extra_args', null), + stateManager.store('min_pages', null) ]) } })