Skip to content

Commit

Permalink
skip read manga
Browse files Browse the repository at this point in the history
  • Loading branch information
hammyo-o committed Nov 19, 2024
1 parent 74f1a16 commit 71ce54d
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 11 deletions.
63 changes: 57 additions & 6 deletions src/NHentai/NHentai.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,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',
Expand Down Expand Up @@ -84,7 +84,7 @@ export class NHentai implements SearchResultsProviding, MangaProviding, ChapterP

stateManager = App.createSourceStateManager()

// Sourrce Settings
// Source Settings
async getSourceMenu(): Promise<DUISection> {
return Promise.resolve(App.createDUISection({
id: 'main',
Expand Down Expand Up @@ -132,9 +132,20 @@ export class NHentai implements SearchResultsProviding, MangaProviding, ChapterP
this.CloudFlareError(response.status)

const jsonData = this.parseJson(response)

// Add the manga ID to the read list
await this.addToReadMangaIds(mangaId)

return parseChapterDetails(jsonData, mangaId)
}

// Method to store read manga IDs
async addToReadMangaIds(mangaId: string): Promise<void> {
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<TagSection[]> {
const arrayTags: Tag[] = []

Expand All @@ -150,6 +161,8 @@ export class NHentai implements SearchResultsProviding, MangaProviding, ChapterP
async getSearchResults(query: SearchRequest, metadata: any): Promise<PagedResults> {
const page: number = metadata?.page ?? 1
const title: string = query.title ?? ''
const skipReadManga = await this.stateManager.retrieve('skip_read_manga') ?? false
const readMangaIds = skipReadManga ? await this.getReadMangaIds() : []

if (metadata?.stopSearch ?? false) {
return App.createPagedResults({
Expand Down Expand Up @@ -178,7 +191,7 @@ export class NHentai implements SearchResultsProviding, MangaProviding, ChapterP
}
})

// Normal search query
// Normal search query
} else {
const q: string = encodeURIComponent(`${title} ${query?.includedTags?.map((x: Tag) => ` +${x.id}`)} `) + await this.generateQuery()

Expand All @@ -190,8 +203,9 @@ export class NHentai implements SearchResultsProviding, MangaProviding, ChapterP
this.CloudFlareError(response.status)

const jsonData = this.parseJson(response)
const results = parseSearch(jsonData).filter(manga => !readMangaIds.includes(manga.mangaId))
return App.createPagedResults({
results: parseSearch(jsonData),
results,
metadata: {
page: page + 1
}
Expand All @@ -200,6 +214,8 @@ export class NHentai implements SearchResultsProviding, MangaProviding, ChapterP
}

async getHomePageSections(sectionCallback: (section: HomeSection) => void): Promise<void> {
const skipReadManga = await this.stateManager.retrieve('skip_read_manga') ?? false
const readMangaIds = skipReadManga ? await this.getReadMangaIds() : []
const sections = [
{
request: App.createRequest({
Expand Down Expand Up @@ -236,6 +252,30 @@ export class NHentai implements SearchResultsProviding, MangaProviding, ChapterP
containsMoreItems: true,
type: HomeSectionType.singleRowNormal
})
},
{
request: App.createRequest({
url: `${NHENTAI_URL}/api/galleries/search?query=${await this.generateQuery()}&sort=popular-month`,
method: 'GET'
}),
sectionID: App.createHomeSection({
id: 'popular-month',
title: 'Popular Monthly',
containsMoreItems: true,
type: HomeSectionType.singleRowNormal
})
},
{
request: App.createRequest({
url: `${NHENTAI_URL}/api/galleries/search?query=${await this.generateQuery()}&sort=popular`,
method: 'GET'
}),
sectionID: App.createHomeSection({
id: 'popular',
title: 'Popular All-Time',
containsMoreItems: true,
type: HomeSectionType.singleRowNormal
})
}
]

Expand All @@ -251,7 +291,7 @@ export class NHentai implements SearchResultsProviding, MangaProviding, ChapterP
if (hasNoResults(jsonData)) {
return
}
section.sectionID.items = parseSearch(jsonData)
section.sectionID.items = parseSearch(jsonData).filter(manga => !readMangaIds.includes(manga.mangaId))

sectionCallback(section.sectionID)
})
Expand All @@ -263,6 +303,8 @@ export class NHentai implements SearchResultsProviding, MangaProviding, ChapterP

async getViewMoreItems(homepageSectionId: string, metadata: any): Promise<PagedResults> {
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'
Expand All @@ -273,14 +315,23 @@ export class NHentai implements SearchResultsProviding, MangaProviding, ChapterP
const jsonData = this.parseJson(response)

page++
const results = parseSearch(jsonData).filter(manga => !readMangaIds.includes(manga.mangaId))
return App.createPagedResults({
results: parseSearch(jsonData),
results,
metadata: {
page: page
}
})
}

async getReadMangaIds(): Promise<string[]> {
const allData = await this.stateManager.retrieve('read_manga_ids')
if (!allData) {
return []
}
return Object.keys(allData).filter(key => key.startsWith('read_manga_')).map(key => key.replace('read_manga_', ''))
}

CloudFlareError(status: number): void {
if (status == 503 || status == 403) {
throw new Error(`CLOUDFLARE BYPASS ERROR:\nPlease go to the homepage of <${NHentai.name}> and press the cloud icon.`)
Expand Down
6 changes: 6 additions & 0 deletions src/NHentai/NHentaiHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ class NHSortOrderClass {
name: 'Most Recent',
NHCode: 'date',
shortcuts: ['s:r', 's:recent', 'sort:r', 'sort:recent']
},
{
// Sort by popular this month
name: 'Popular This Month',
NHCode: 'popular-month',
shortcuts: ['s:pm', 's:m', 's:popular-month', 'sort:pm', 'sort:m', 'sort:popular-month']
}
]

Expand Down
4 changes: 2 additions & 2 deletions src/NHentai/NHentaiInterfaces.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

export interface ImagePageObject {
t: 'j' | 'p' | 'g';// JPG (≧◡≦)
t: 'j' | 'p' | 'g' | 'w'; // Added 'w' for webp
w: number;
h: number;
}
Expand Down Expand Up @@ -107,5 +107,5 @@ export interface QueryResponse {
export interface RequestMetadata {
nextPage?: number;
maxPages?: number;
sort: 'popular-today' | 'popular-week' | 'popular' | '';
sort: 'popular-today' | 'popular-week' | 'popular-month' | 'popular' | '';
}
4 changes: 2 additions & 2 deletions src/NHentai/NHentaiParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,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}`
})
})
}
Expand Down Expand Up @@ -76,7 +76,7 @@ export const parseSearch = (data: QueryResponse): PartialSourceManga[] => {
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())
}
Expand Down
11 changes: 10 additions & 1 deletion src/NHentai/NHentaiSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ export const getSortOrders = async (stateManager: SourceStateManager): Promise<s
}

export const getExtraArgs = async (stateManager: SourceStateManager): Promise<string> => {
return (await stateManager.retrieve('extra_args') as string) ?? '-lolicon -shotacon -yaoi'
const value = await stateManager.retrieve('extra_args');
return typeof value === 'string' ? value : '';
}


Expand Down Expand Up @@ -75,6 +76,14 @@ export const settings = (stateManager: SourceStateManager): DUINavigationButton
)
}
})
}),
App.createDUISwitch({
id: 'skip_read_manga',
label: 'Skip Read Manga',
value: App.createDUIBinding({
get: async () => await stateManager.retrieve('skip_read_manga') ?? false,
set: async (newValue) => await stateManager.store('skip_read_manga', newValue)
})
})
]
},
Expand Down

0 comments on commit 71ce54d

Please sign in to comment.