Skip to content

feat(english): add Empire Novel plugin - #2615

Open
RibatTRW wants to merge 2 commits into
lnreader:masterfrom
RibatTRW:fm/lnreader-empirenovel-2498
Open

RibatTRW wants to merge 2 commits into
lnreader:masterfrom
RibatTRW:fm/lnreader-empirenovel-2498

Conversation

@RibatTRW

@RibatTRW RibatTRW commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Closes #2498

Adds a standalone plugin for Empire Novel (English). It's a custom Laravel site, not one of the multisrc themes.

What it supports

  • Popular / browse: /novels-list, paged, with Category and Status (Ongoing / Completed / Abandoned) filters. The site has no popularity ranking, and it ignores sort parameters on GET, so this list is alphabetical, the same as the site's own catalog.
  • Latest: the home page's "Latest Releases" section (/?page=N).
  • Search: /search-live?q=, the JSON endpoint behind the site's search box. It returns every match in one response, so page 2 and later return an empty list.
  • Novel: title, cover, author, genres, status and summary. The site cuts the summary in two for its "More" toggle, and the plugin joins the two parts back together. The novel page lists only 30 chapters per page (The Innkeeper has 82 pages), so the plugin reads the full chapter list from the reader's chapter selector (/select-partial/<slug>/<chapter>) in a single request. Chapters are listed oldest first. The site doesn't show chapter titles in its lists, so chapters are named "Chapter N".
  • Chapter: the contents of #read-novel. Script, iframe, object, embed and form elements are removed, along with all on* attributes and javascript: URLs.
  • Icon: the site's apple-touch-icon, resized to 96x96.

Cloudflare

Every URL on the site, including robots.txt, returns a Cloudflare managed challenge (cf-mitigated: challenge) to plain HTTP clients and to headless Chromium. So when npm run check:plugin runs from Node, it can only report:

| `siteReachability` | ⚠️ INCONCLUSIVE | HTTP 403 (Cloudflare) |

The CI Plugin Live Check will likely report INCONCLUSIVE for the same reason. The plugin doesn't override the User-Agent, so it should work with the cookie the app gets when the challenge is solved in its WebView. I haven't tested that in the app. When a request gets a 403 or 503, the plugin shows the same message other plugins here use (novel543, truyendich), asking the user to open the plugin in WebView to solve the challenge. Other HTTP errors still show Request failed: <status>.

How it was tested

  • A headed Chromium window passed the challenge. I bundled the plugin with esbuild, using the same config as scripts/live-check-plugin.js, and ran it in Node with fetch sending each request from inside that browser tab (same cookies). Against the live site:
    • popularNovels: page 1 and page 2 (30 novels each, different novels), category=romance + status=2, and latest pages 1 and 2 (18 each)
    • searchNovels('innkeeper') returns The Innkeeper; page 2 returns []
    • parseNovel('novel/the-innkeeper'): all metadata filled; 2456 chapters, Chapter 1 through Chapter 2456 in order. novel/prince has 11 chapters and status Completed.
    • parseChapter: The Innkeeper chapters 1 and 2456 and ½ Prince chapters 1 and 11 returned full text with no on* attributes or javascript: URLs.
  • I checked the error messages with mocked 403, 503 and 500 responses. After adding the WebView message, I ran the whole browser-session check above again and got the same results.
  • I also ran the chapter sanitizer on hand-made HTML containing onclick, onerror, <script>, <iframe> and an obfuscated java\tscript: href. All of them were removed.
  • eslint and prettier --check pass on the new file, and npm run build:compile passes. (npm run lint still reports errors, but they are pre-existing ones in rewayatfans.ts and wetriedtls.ts.)
  • Not tested: the LNReader app itself and the playground.

This PR was written by an AI agent (Claude). No human has reviewed it yet, so please review it with that in mind.

@greptile-apps

greptile-apps Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 4/5

[Medium risk] Adds a new novel-scraping plugin for one website.

The PR appears safe to merge, though the Cloudflare error and search next-page experience should be improved.

Findings

  1. P2 Cloudflare block gives no next step ▶
  2. P2 Search matches vanish on next page ▶

Summary

Adds a standalone LNReader source for Empire Novel, from browsing and search through chapter reading.

  • Catalog browsing includes Category and Status filters, plus a latest-release feed.
  • Novel pages show details and full chapter lists; chapter text is returned without script-capable markup.

Reviews (1) · Last reviewed commit: "feat(english): add Empire Novel plugin"

Comment thread plugins/english/empirenovel.ts Outdated
Comment on lines +39 to +42
if (!res.ok) {
throw Object.assign(new Error('Request failed: ' + res.status), {
status: res.status,
});

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 Cloudflare block gives no next step

When Cloudflare blocks a request, fetchSite shows only Request failed: 403. Users need to open the site in WebView to pass the challenge, but this error gives them no way to tell what to do. Please give them that hint when the site blocks a request.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

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 ec9fb99. A 403 or 503 response now throws the same message other plugins in this repo use (novel543, truyendich): "Cloudflare protection detected (HTTP error). Please try opening the plugin in WebView first to solve the challenge." Other HTTP errors still throw Request failed: <status>. The error still carries status, so the live checker keeps classifying a block as INCONCLUSIVE. I checked it with mocked 403, 503 and 500 responses, and the normal requests still work against the live site through a browser session that had passed the challenge.

Comment on lines +209 to +210
// search-live returns every match at once.
if (pageNo > 1) return [];

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 Search matches vanish on next page

After a search finds matches, the page enables Next Page. Clicking it calls searchNovels for page 2, which always returns []. The page then replaces the matches with “No results found.” Since this site returns every match on page 1, the search page needs a way to avoid offering a next page for this source.

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.

I've kept this as it is. searchNovels returns only Promise<NovelItem[]> (src/types/plugin.ts), and docs/docs.md describes no other way to say "no more pages". Returning [] past the last page is how plugins in this repo mark the end of results: about 46 of them return [] when pageNo > 1 or past the end, for example daotekno, novel543, konkon, kakuyomu and lightnovelworld. The Next Page button you mention is in the repo's playground (src/components/search-novels.tsx). It's a manual pager that replaces the results and is enabled whenever the current page has results, so every one of those plugins shows "No results found" on the page after its last one. That's playground behaviour, not something this plugin can change. This site's /search-live endpoint returns every match in one response, so page 1 is complete.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

You're right. searchNovels has no pagination metadata or end-of-results signal, and returning [] for pageNo > 1 is consistent with the repository's existing plugin convention. The “No results found” state is a playground pager limitation, not a defect this plugin can address through the PluginBase API. I'll withdraw this finding; no change is needed in empirenovel.ts.

Tip: You can customize Greptile's behavior for this repo with .greptile/rules.md and .greptile/config.json.

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.

Empire novel plugin

1 participant