Skip to content

fix(english/crimsonscrolls): support redesigned site - #2617

Open
RibatTRW wants to merge 2 commits into
lnreader:masterfrom
RibatTRW:fm/lnreader-crimsonscrolls-2423
Open

RibatTRW wants to merge 2 commits into
lnreader:masterfrom
RibatTRW:fm/lnreader-crimsonscrolls-2423

Conversation

@RibatTRW

@RibatTRW RibatTRW commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Closes #2423

What was wrong

The Crimson Scrolls plugin (plugins/english/crimsonscrolls.ts, v1.0.1) was already in the repo, but it stopped working after the site moved to a new theme (crimsonscrolls-v2). npm run check:plugin failed on the first call: popularNovels → cheerio.load() expects a string.

  • The admin-ajax.php actions load_novels and live_novel_search no longer return HTML, so browse and search broke.
  • The wp-json/cs/v1/novels/{id}/chapters API is gone, and so are #single-novel-content-wrapper, #chapter-list and #chapter-display.
  • Chapters now live at /novel/<novel-slug>/<chapter-slug>/. The old /chapter/<slug>/ URLs 301-redirect there.

What changed (1.0.1 → 1.1.0)

  • Browse/search: the plugin now scrapes /novels/?cs_page=N, and search uses ?s= on the same page. Search is now paginated.
  • Filters added: sort (Latest Updated / Newest Added / Highest Rated), status and genres, all from the site's browse form. I left out the site's "Most Viewed" and "Most Chapters" sorts because the site itself returns 0 results for them.
  • Novel page: title, cover, author, genres, status, and the summary with its paragraphs kept.
  • Chapters: fetched from wp-json/crimsonscrolls/v2/novel-chapters for every access tier the novel lists (free, tier_1…tier_4), 100 per page. Paid-tier chapters get the 🔒 prefix. The existing "Hide locked chapters" setting skips the paid tiers entirely.
  • Chapter text: taken from article.cs-reader. The plugin removes ads, scripts, the duplicated title header and the hidden per-paragraph copy watermarks. It also strips any on* attributes and javascript: URLs. A locked chapter (tier gate) now raises a clear error instead of returning the paywall markup.
  • Paths: novel paths keep their old format (novel/<slug>/). New chapter paths are the full novel/<slug>/<chapter>/. Chapters saved by 1.0.1 used the bare chapter slug, so resolveUrl sends those to /chapter/<slug>/, which the site redirects. As a result, previously downloaded chapter entries still open. Once a library novel is refreshed, though, its chapters will appear under the new paths. Complete http(s):// URLs, such as defaultCover, pass through resolveUrl unchanged, and protocol-relative // URLs get https:.

Testing

All testing was run by an AI agent against the live site. There has been no human review or in-app testing yet.

  • npm run check:plugin -- plugins/english/crimsonscrolls.ts passed: popularNovels 18 novels, searchNovels 1 result, parseNovel 333 chapters, parseChapter ~11k chars.
  • I bundled the plugin and spot-checked it:
    • Browse pages 1–4 return 18/18/4/0, matching the site's 40 novels.
    • Each sort option works, and the completed/ongoing status filters work.
    • A single genre on page 2 works, and so does a multi-genre filter.
    • The "villain" search returns 18 + 18 + 0 results across three pages, with no duplicates. A search with no matches returns 0.
    • For a novel with 4 paid tiers: 483 chapters, strictly ascending, no duplicate paths, 235 locked.
    • Locked chapters throw the error, and "Hide locked chapters" leaves only the free chapters.
    • A mature chapter loads without logging in.
    • The chapter HTML contains no on* attributes, javascript: URLs, scripts or ad markup.
  • resolveUrl checked on the bundled plugin with a full URL, a protocol-relative URL, a legacy bare chapter slug, a novel/<slug>/<chapter>/ path and a novel path.
  • npx eslint, prettier --check, tsc --noEmit and npm run build:compile all pass.
  • Caveat: Cloudflare challenges /chapter/<slug>/ (the legacy redirect) when the request has a bare node/curl User-Agent. With a browser User-Agent it returns 301 as expected. So the legacy-path fallback is verified only with a browser UA, not through the Node checker. The /novel/... chapter URLs work with every UA I tried.

🤖 Authored by an AI agent (Claude Code, Claude Opus 5.5). Please weight review accordingly.

Crimson Scrolls moved to a new theme: the admin-ajax listing/search
actions and the cs/v1 chapter API are gone, and chapters now live under
/novel/<novel>/<chapter>/. Browse and search use the /novels/ page,
chapters come from the crimsonscrolls/v2 novel-chapters endpoint across
all access tiers, and locked chapters raise a clear error. Adds sort,
status and genre filters.
@greptile-apps

greptile-apps Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 4/5

[Medium risk] Updates plugin to work with redesigned website.

The PR appears safe to merge, though EPUB exports can lose the fallback cover.

Findings

  1. P2 EPUB cover disappears ▶

Summary

The Crimson Scrolls plugin now follows the site's redesigned browse, novel, and chapter pages. It adds browse filters and tier-aware chapter lists while keeping older saved chapter links usable.

  • Browse and search use paged site pages, with sort, status, and genre filters.
  • Novel details and chapters come from the redesigned pages and chapter API.
  • Chapter text is cleaned before display, and locked chapters get a clear message.

Reviews (1) · Last reviewed commit: "fix(english/crimsonscrolls): support red..."

Comment thread plugins/english/crimsonscrolls.ts Outdated
Comment on lines +252 to +254
!isNovel && !path.includes('/')
? `${this.site}/chapter/${path}/`
: `${this.site}/${path}`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 EPUB cover disappears

When a novel uses defaultCover, resolveUrl adds the Crimson Scrolls address to a URL that is already complete. EPUB export cannot fetch that address, so the file has no cover image. Leave complete URLs unchanged.

Suggested change
!isNovel && !path.includes('/')
? `${this.site}/chapter/${path}/`
: `${this.site}/${path}`;
path.startsWith('http://') || path.startsWith('https://')
? path
: !isNovel && !path.includes('/')
? `${this.site}/chapter/${path}/`
: `${this.site}/${path}`;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 4b2d7a1: resolveUrl now returns http(s):// URLs unchanged (so defaultCover is no longer prefixed) and turns protocol-relative // URLs into https:. Bare legacy chapter slugs still go to /chapter/<slug>/, and novel/... paths still get the site prefix. I checked all four cases on the bundled plugin and re-ran the live check, which passes.

Return http(s) URLs unchanged and give protocol-relative URLs https, so
defaultCover and other complete URLs are not prefixed with the site.

This branch has not been deployed

No deployments
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.

Add Crimson Scroll

1 participant