Conversation
added 2 commits
September 23, 2026 20:04
Tangerine Archive's chapter list returns every row, but coin-locked rows carry href="#" and were dropped by the template's `chapterUrl != '#'` guard, so a 212-chapter novel showed only its 160 free chapters. Locked rows are now listed with the URL the site actually serves them at (`<novelPath>chapter-<n>/`, n from the row title, which returns 200 with a lock notice instead of the body), behind a new `listLockedChapters` source option that only tangerinearchive sets, so other Madara sources take the unchanged path. The plain slug is used as-is only when the title is exactly "Chapter <n>" and that number is unique in the novel; the site's own free rows confirm the convention (3065/3083 exact, every exception a suffixed, decimal or duplicated title). Other titles do not slugify the way they read - a trailing emoji is sometimes part of the slug and sometimes not - so their candidate slugs are verified against the chapter page's own post id (`#wp-manga-current-chap[data-id]`) and a row is skipped rather than listed with a URL that serves a different chapter or the series page. Of the 785 locked rows across all 16 series, 784 are listed and 1 (a duplicate-number row whose slug no candidate matches) is skipped. parseChapter now reports locked chapters with a clear error instead of an empty chapter, and reports an unknown chapter URL (which silently falls back to the series page) instead of returning an empty chapter. Verified anonymously and read-only against the live site: parseNovel returns 212/212 chapters for garden-of-may (52 locked, all 52 derived URLs resolve to a real chapter page), 464/464 for holy-night (105 locked), 264/264 for it-seems-like (34 locked), 173/173 for i-thought-i-was-the-monster-dukes (120 locked) and 190/191 for villain-let-me-touch-you (45 locked, 1 unresolvable row skipped). Free chapters still parse (chapter-160 -> 6538 chars). No entitled-session test: locked bodies are server-gated, so no locked prose was read. Co-Authored-By: pi crewmate <crewmate@pi.local>
Co-Authored-By: pi crewmate <crewmate@pi.local>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked candidate fix for the premium (coin-locked) chapter listing gap in lnreader#2564 — base branch is deliberately
fm/lnreader-plugins-2555-tangerine, not the default branch.What changed
plugins/multisrc/madara/template.ts(additive, flag-gated),plugins/multisrc/madara/sources.json(tangerinearchiveonly, plugin version 2.2.0 → 2.2.1) and a README note for the new option:listLockedChapterssource option, off by default and set only fortangerinearchive, so every other Madara source takes the unchanged code path.parseNovellists coin-locked rows. They carryhref="#", which the template'schapterUrl != '#'guard dropped, so Garden of May showed 160 of its 212 chapters. They are now listed with the URL the site actually serves them at,<novelPath>chapter-<n>/(HTTP 200 with the lock notice in place of the body).Chapter <n>and that number is unique in the novel — the site's own free rows confirm the convention (3065/3083 exact across all 16 series; every exception is a suffixed, decimal or duplicated title).Chapter 176 🔞is/chapter-176-%f0%9f%94%9e/whileChapter 244 - 🔞is/chapter-244/— so its candidate slugs are fetched and accepted only when the page's own post id (#wp-manga-current-chap[data-id]) matches the row'sdata-chapter-<id>class. If no candidate matches, the row is skipped rather than listed with a URL that serves a different chapter or the series page. Across all 16 series: 784 of 785 locked rows are listed; 1 (villain-let-me-touch-youid 16701, a duplicateChapter 166whose slug no candidate matches) is deliberately skipped.releaseTime: null: their date cell holds an unlock countdown (Unlocked in 4 weeks/TBA), whichparseDatawould have turned into a bogus past date.parseChapterreports locked/unavailable chapters instead of returning a blank chapter (same flag): a coin-locked page throwsThis chapter is locked on Tangerine Archive (premium, 10 coins). Its text is only served to readers who unlocked it, so it becomes readable here once the site unlocks it., and a chapter URL the site no longer resolves — an unknown slug silently falls back to the series page — throwsThis chapter is not available on Tangerine Archive anymore.instead of returning''.plugins/multisrc/madara/README.mddocuments the option alongside the generator's other source options.Verification
Live, anonymous, read-only (no cookies, no login, no purchase, never the buy endpoint).
npm run build:compile,npm run build:multisrc, prettier andeslint plugins/multisrc/madara/template.tspass.npm run check:plugin -- 'plugins/english/TangerineArchive[madara].ts'passes (popularNovels 12, searchNovels PASS, parseNovel 173 chapters, parseChapter 14497 chars).A custom probe compares
parseNovelagainst an independent read of the live ajax chapter list:For garden-of-may every one of the 52 derived locked URLs was re-fetched: 52/52 returned HTTP 200 with
#wp-manga-current-chap, i.e. they are real chapter pages, not the series-page fallback.parseChapterwas exercised on: freechapter-160(6538 chars of prose), lockedchapter-161andchapter-212,villain-let-me-touch-you/chapter-176-%f0%9f%94%9e/(the emoji-suffixed slug),villain-let-me-touch-you/chapter-166/(the duplicate-number owner) — all four throw the locked error — andgarden-of-may/chapter-9999/, which throws the not-available error.Shared-template guard:
plugins/english/SleepyTranslations[madara].ts(does not set the flag) still passes all four live checks.Probed and ruled out (anonymous)
POST /series/<slug>/ajax/chapters/already returns every row including premium, with the premiumdata-chapter-<id>class — the gap was only the missing URL. The reading-nav endpoint (POST admin-ajax.php action=manga_get_reading_nav&manga=<id>&chapter=<slug>&volume_id=0&style=list&type=content) returns all 212/464<option>s but no URLs: premium options carrydata-redirect="#"and every option'svalueis the currently-open chapter slug, and its id sequence is identical to the ajax list's, so it adds nothing. Also ruled out:/wp-json/wp/v2/search→[]and no chapter CPT in REST,?s=…&post_type=wp-manga-chapterreturns no chapters,/sitemap.xmllists only the 997 free chapters, the series/feed/returns the HTML page,/?p=<chapter id>→ 404, and the coin plugin's JS only branches ondata-redirect == '#'. No endpoint exposes a locked chapter's URL, so derivation plus post-id verification is the only route; the site's own free rows and the 52/52 re-fetch above are the evidence that the derived URLs are real.Not tested / known limits
🔒name prefix. Richer labels (coin price, unlock countdown) were deliberately left out of this diff, as was enablinghasLocked: true(the existing "Hide locked chapters" switch) — easy to add if wanted.releaseTime: 'LL'bug for free chapters (dayjs().format('LL')without thelocalizedFormatplugin) is untouched; it affects every Madara source and is not introduced here.Authored by an AI agent (pi crewmate) on behalf of the task that requested it; reviewed evidence is in this description and reproducible with the commands above.