Skip to content

feat(english): add Nightjar Reads source plugin - #2575

Open
RevDev909 wants to merge 21 commits into
lnreader:masterfrom
RevDev909:feat/nightjarreads-plugin
Open

RevDev909 wants to merge 21 commits into
lnreader:masterfrom
RevDev909:feat/nightjarreads-plugin

Conversation

@RevDev909

Copy link
Copy Markdown
Contributor

Adds a source plugin for Nightjar Reads (https://nightjarreads.com), an English novel site running on Next.js. The site embeds its data in Next.js React Flight payloads, which the plugin decodes and parses.

Features:

  • Browse popular novels
  • Search
  • Full novel details (title, author, genres, status, synopsis, cover) + complete chapter list
  • Chapter reading for free chapters; premium/locked chapters show a notice instead of failing

Verification:

  • npm run check:plugin -- plugins/english/nightjarreads.ts passes all 4 checks (popularNovels, searchNovels, parseNovel, parseChapter)
  • ESLint and Prettier clean
  • Tested live in the LNReader app via a custom repository

@greptile-apps

greptile-apps Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 4/5

[Medium risk] Adds a new content source plugin for English novels.

The PR appears safe to merge, with non-blocking Flight-parser hardening and test coverage worth addressing.

Findings

  1. P2 Flight chunks can be skipped ▶
  2. P2 Payload edge cases lack tests ▶

Summary

Adds an English Nightjar Reads plugin that decodes Next.js Flight data for browsing, search, novel details, and chapter reading, plus its icon.

  • Flight extraction is unnecessarily sensitive to script formatting.
  • The new payload parsers need focused tests beyond the live checker’s four basic checks.

Reviews (1) · Last reviewed commit: "Add Nightjar Reads plugin icon"

Comment thread plugins/english/nightjarreads.ts Outdated
* scripts. Decode every payload into one searchable text blob.
*/
function extractFlightText(html: string): string {
const re = /self\.__next_f\.push\(\[1,"([\s\S]*?)"\]\)<\/script>/g;

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 Flight chunks can be skipped

If a Flight script has a semicolon or whitespace before </script>, this pattern does not match it, and the parser silently skips the chunk. That can leave browse results or chapter content empty. Match the Flight push without depending on the closing tag’s formatting.

Comment on lines +257 to +260
function parseChapterPage(flight: string): string | null {
if (/"locked":true/.test(flight)) return LOCKED_MESSAGE;
const m = /"body":\["([\s\S]*?)"\],"translatorNotes"/.exec(flight);
if (!m) return null;

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 Payload edge cases lack tests

Please add captured-payload tests for search and chapter parsing. The live checker accepts an empty search result and reads only the first chapter, so it cannot catch changes that make the query marker, locked-chapter check, or body extraction show unrelated results or unreadable chapters.

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!

@RevDev909

Copy link
Copy Markdown
Contributor Author

Added captured-payload tests covering the remaining review item — plugins/english/__tests__/nightjarreads.test.mjs (run: npm install && node --test plugins/english/__tests__/nightjarreads.test.mjs):

  • Search: a real query returns exactly the marked result. The fixture also carries a suggestion index before the query marker, so a broken marker would leak unrelated novels. A nonsense query returns nothing.
  • Chapter: a free chapter parses to <p> paragraphs with the promo footer filtered out; a locked premium chapter returns the locked notice.
  • Regex hardening: the same captured search payload is replayed with ;</script> and whitespace-before-</script> closings — both fail with the previous strict regex and pass with the hardened one.

Fixtures are minimized captured flight chunks (~20 KB total), so the tests need no live network. esbuild (already a devDependency) bundles the plugin at test time with @libs/* aliased to shims.

@rajarsheechatterjee

Copy link
Copy Markdown
Member

Could we remove the tests? I'll configure PR reviews to not ask for tests until a proper test framework is added.

@RevDev909

Copy link
Copy Markdown
Contributor Author

Done — removed the tests (the whole plugins/english/tests directory). Happy to drop them entirely given there's no test framework set up yet.

@RevDev909

Copy link
Copy Markdown
Contributor Author

Updated the plugin with a hardening pass from a full code audit: search results are now bounded to the result section and the page's own result count (quoted queries work), the locked-chapter check is scoped to the chapter's own record instead of the whole page, chapter parsing tolerates fractional chapter numbers and non-string body entries, and page responses are size-capped. Normal content parses identically to before.

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.

2 participants