diff --git a/src/mangaplus/manifest.json b/src/mangaplus/manifest.json index 868a3ca..aa0aa42 100644 --- a/src/mangaplus/manifest.json +++ b/src/mangaplus/manifest.json @@ -1,6 +1,6 @@ { "name": "mangaplus", - "version": "1.2.1", + "version": "1.3.0", "publoader_api": "^2.0.0", "runtime": "node", "entrypoint": "index.mjs", diff --git a/src/mangaplus/package.json b/src/mangaplus/package.json index 6d51455..f14d2ef 100644 --- a/src/mangaplus/package.json +++ b/src/mangaplus/package.json @@ -1,6 +1,6 @@ { "name": "publoader-ext-mangaplus", - "version": "1.2.1", + "version": "1.3.0", "private": true, "type": "module", "description": "publoader extension for MangaPlus by Shueisha (extension API v2)", diff --git a/src/mangaplus/src/api.d.ts b/src/mangaplus/src/api.d.ts index c956493..c95a7b3 100644 --- a/src/mangaplus/src/api.d.ts +++ b/src/mangaplus/src/api.d.ts @@ -23,6 +23,17 @@ export interface ChapterInput { mdMangaId: string | null; mangaName: string | null; mangaUrl: string | null; + /** + * Why an ordinary reader cannot open this chapter, when they cannot. + * + * Null (or omitted) means freely readable and the chapter is published + * normally. Anything else means the publisher still lists it but will not + * serve it to a logged-out reader, and the platform publishes it already + * carded with wording that says so. + */ + unavailableReason?: "subscriber-only" | "region-locked" | "removed" | null; + /** The tier a `subscriber-only` chapter needs, e.g. "MANGA Plus MAX". */ + subscriptionName?: string | null; images?: Uint8Array[]; } diff --git a/src/mangaplus/src/index.ts b/src/mangaplus/src/index.ts index f4e8180..e9be47b 100644 --- a/src/mangaplus/src/index.ts +++ b/src/mangaplus/src/index.ts @@ -60,6 +60,9 @@ const CHAPTER_URL = (chapterId: string) => `https://mangaplus.shueisha.co.jp/viewer/${chapterId}`; const MANGA_URL = (mangaId: string) => `https://mangaplus.shueisha.co.jp/titles/${mangaId}`; +/** What MangaPlus calls the tier that unlocks a subscriber-only chapter. */ +const SUBSCRIPTION_NAME = "MANGA Plus MAX"; + /** Stand-in for a missing timestamp, matching the Python DEFAULT_TIMESTAMP. */ const DEFAULT_TIMESTAMP = 1; /** An update is only "new" if it went up within this window. */ @@ -189,6 +192,10 @@ function toChapterInput(chapter: RawChapter): ChapterInput { return { chapterTimestamp: isoFromEpoch(chapter.chapterTimestamp), chapterExpire: chapter.chapterExpire === null ? null : isoFromEpoch(chapter.chapterExpire), + // Null for a readable chapter; set, the platform publishes it already + // carded and names the subscription that unlocks it. + unavailableReason: chapter.unavailableReason ?? null, + subscriptionName: chapter.subscriptionName ?? null, chapterLanguage: chapter.chapterLanguage, chapterNumber: chapter.chapterNumber, chapterTitle: chapter.chapterTitle, @@ -339,10 +346,19 @@ class MangaPlus implements ExtensionRuntime { }); } + // A dead chapter is LABELLED, not dropped. MangaPlus still lists it and a + // MANGA Plus MAX subscriber can still open it -- what the viewer refuses is + // the logged-out request this extension makes. Dropping it is + // indistinguishable, from the platform's side, from MangaPlus deleting the + // chapter, so the removal pass cards it "removed" and tells a reader a + // chapter they could subscribe to read no longer exists. const dead = await this.findDeadChapters(input, allChapters, updatedChapters); - const isDead = (chapter: RawChapter): boolean => dead.has(chapter.chapterId); - const liveUpdated = updatedChapters.filter((chapter) => !isDead(chapter)); - const liveAll = allChapters.filter((chapter) => !isDead(chapter)); + const label = (chapter: RawChapter): RawChapter => + dead.has(chapter.chapterId) + ? { ...chapter, unavailableReason: "subscriber-only", subscriptionName: SUBSCRIPTION_NAME } + : chapter; + const liveUpdated = updatedChapters.map(label); + const liveAll = allChapters.map(label); // Every fetched series failing is the API refusing us, not a catalogue that // emptied itself. Publishing that as a clean run's catalogue would claim diff --git a/src/mangaplus/src/normalise.ts b/src/mangaplus/src/normalise.ts index fcc0fe9..63b163a 100644 --- a/src/mangaplus/src/normalise.ts +++ b/src/mangaplus/src/normalise.ts @@ -46,6 +46,14 @@ export interface RawChapter { mangaId: string; mangaName: string | null; mangaUrl: string; + /** + * Why a reader cannot open this chapter, when they cannot. Null for a normal + * chapter; `subscriber-only` for one the viewer refuses a logged-out request + * for but a MANGA Plus MAX subscriber can still read. + */ + unavailableReason?: "subscriber-only" | null; + /** The tier that unlocks it, carried onto the card. */ + subscriptionName?: string | null; } export interface OverrideOptions {