Skip to content

fix(madara): list Tangerine Archive premium chapters with lock metadata - #1

Closed
RibatTRW wants to merge 2 commits into
fm/lnreader-plugins-2555-tangerinefrom
fm/tangerine-premium-name-meta
Closed

RibatTRW wants to merge 2 commits into
fm/lnreader-plugins-2555-tangerinefrom
fm/tangerine-premium-name-meta

Conversation

@RibatTRW

@RibatTRW RibatTRW commented Sep 23, 2026 •

Copy link
Copy Markdown
Owner

Stacked candidate fix for lnreader#2564 (Tangerine Archive). Base is deliberately fm/lnreader-plugins-2555-tangerine, not a default branch.

Closes the gap called out in lnreader#2564's body: premium (coin-locked) chapters were excluded from the chapter list, so the app showed e.g. 160 of Garden of May's 212 chapters and readers had no way to see the rest.

What changed

plugins/multisrc/madara/template.ts — new listLockedChapters source option, off by default:

  • Chapter rows with premium-block are kept in the list when the option is on. Their name gets a compact suffix: Chapter 161 [Premium - 10 coins - TBA], … - Unlocked in 4 weeks], or … - locked] when the row carries neither countdown nor TBA. The coin price is read from the row's coin-N class (prices are not always 10: Holy Night has 12 and 16).
  • The site renders these rows with href="#", so the real (still server-gated) URL is rebuilt from the first number in the chapter name: /series/<slug>/chapter-<n>/. Verified exact for plain and annotated names (Chapter 250 - (End of the Side Stories) → chapter-250/).
  • parseChapter detects the gate (.reading-content .content-blocked / .premium-block) and throws This chapter is locked on Tangerine Archive (10 coins). It requires a site login and a coin unlock, so its text cannot be shown here. instead of returning the empty body the site serves to anonymous readers.
  • parseChapter also checks that the fetched page is a chapter page (#wp-manga-current-chap). A derived /chapter-<n>/ URL is not exact for every premium row — emoji-suffixed titles such as Chapter 176 🔞 have a different slug, and duplicate numbers can collide — and those URLs silently render the series page with HTTP 200 and no chapter body, which would come back as a blank chapter. Those now throw Could not find this chapter's page on Tangerine Archive… instead.
  • Premium rows get releaseTime: null: their countdown/"TBA" text is not a release date and is already encoded in the name.

plugins/multisrc/madara/sources.json — sets listLockedChapters: true only for tangerinearchive, and bumps it to 2.2.1. plugins/multisrc/madara/README.md documents the option.

Shared-template guard: the new behavior is entirely behind the per-source flag; with it off the code takes the previous path. Spot-checked an unrelated Madara source, SleepyTranslations[madara] — popularNovels 16 novels, searchNovels, parseNovel 44 chapters, parseChapter 9872 chars, all PASS.

Probed anonymously (read-only, no login, no cookies, no purchase)

  • POST /series/<slug>/ajax/chapters/ for 9 series: premium rows are li.wp-manga-chapter … premium coin-N … premium-block with href="#", span.coin, a lock icon, and span.chapter-release-date holding either TBA or Unlocked in N ….
  • GET /series/<slug>/chapter-<n>/ for premium chapters across 7 series (including side-story titles): HTTP 200, body replaced by the lock notice. Free chapter garden-of-may/chapter-160/ returns the prose; free rows' hrefs confirm the number-only URL slug.
  • Plugin-level runs against the generated plugins/english/TangerineArchive[madara].ts, comparing parseNovel against an independent fetch of the same ajax list:
    • garden-of-may: 212 chapters = 52 premium + 160 free (10 coins) — matches live
    • holy-night…: 464 = 105 + 359 (12/16 coins) — matches live
    • in-the-doghouse: 251 = 8 + 243 (12 coins) — matches live
    • parseChapter('series/garden-of-may/chapter-160/') → 6532 chars of prose; chapter-161/ and in-the-doghouse/chapter-250/ throw the locked error instead of returning ''.
    • villain-let-me-touch-you lists its emoji-suffixed premium row as Chapter 176 🔞 [Premium - 10 coins - TBA] with the derived chapter-176/ path; that path now throws the "could not find this chapter's page" error instead of a blank body, while the real emoji slug (chapter-176-%f0%9f%94%9e/) throws the locked-chapter error.
  • npm run build:multisrc, npm run build:compile, npm run check:plugin (all four steps PASS), prettier and eslint on the changed files pass.

NOT tested

  • No entitled-session test: no account, login, coin purchase, or unlock request was made, so the unlocked rendering path is unverified. The fix only lists, labels, and fails loudly on locked chapters; it does not claim or fetch gated prose.
  • Reader-app rendering of the thrown error (only the plugin-level throw is verified).
  • releaseTime: 'LL' on Tangerine's free chapters is the pre-existing dayjs().format('LL')-without-localizedFormat bug in the shared template and is intentionally out of scope here.

Co-Authored-By: firstmate crewmate (AI agent) crewmate@local

RibatTRW and others added 2 commits September 23, 2026 19:50
Tangerine Archive renders coin-locked chapters with href="#" and
premium-block/coin-N classes, so the shared template dropped them and the
chapter list understated the novel's real length. Add a flag-gated
listLockedChapters source option that:

- keeps premium rows in the list, appending
  "[Premium - <n> coins - <countdown|TBA|locked>]" to the chapter name;
- rebuilds the real (still server-gated) /series/<slug>/chapter-<n>/ URL
  from the chapter number so opening one reaches the gated page;
- makes parseChapter throw a clear locked-chapter error instead of
  returning the empty body the site serves anonymous visitors.

The option is set only for tangerinearchive, so other Madara sources are
unchanged (SleepyTranslations spot-checked). Tangerine Archive is now
2.2.1.

Co-Authored-By: firstmate crewmate (AI agent) <crewmate@local>
… series page

A reconstructed /chapter-<n>/ URL is not exact for every premium row
(emoji-suffixed titles such as "Chapter 176 🔞" have a different slug, and
duplicate numbers can collide). Those rows resolve to the series page with
HTTP 200 and no chapter body, so parseChapter returned '' - the blank
chapter this feature is meant to remove. When listLockedChapters is on,
verify the fetched page is a chapter page (#wp-manga-current-chap) before
reading the lock notice, and throw a clear error otherwise.

Verified: villain-let-me-touch-you's derived chapter-176/ now throws the
clear error while the real emoji slug still throws the locked-chapter
error; all previous checks and SleepyTranslations spot-check still pass.

Co-Authored-By: firstmate crewmate (AI agent) <crewmate@local>
@RibatTRW RibatTRW closed this Sep 23, 2026
@RibatTRW
RibatTRW deleted the fm/tangerine-premium-name-meta branch September 23, 2026 13:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant