Repository navigation
Conversation
A downloaded chapter's file is named from its number alone, so the scanner's title for it was the number said twice. Sources do give real names, and the downloader already wrote them into each CBZ's ComicInfo -- nothing read them back. setBookMeta now stores the landed copy's name, filtered so a source that also just says "Chapter 12" does not replace one restatement with another, and rows show it beside the number. The series page also names the chapter the Continue button opens, with the page position when one is part-read. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A chapter downloaded before the downloader learned to record the source's name is stuck titled after its own file, which is named from the number alone. The listing written on each check is the same data for the same chapters and is already in hand, so replaceListing now fills in any book title that is still a bare restatement of its number. Only from a listing title that is not itself one: plenty of sources genuinely call every chapter "Chapter 12", and swapping one restatement for another is churn. A title set by hand never matches the pattern, so an override is safe. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The sweep is how most chapters arrive, and its Landed record carried the group and the source but not the chapter's name, so a chapter fetched overnight stayed "Chapter 12" until the next check's listing heal. It now passes the name to setBookMeta like the add and download paths do. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
persistScan's upsert re-derived every book title from its filename, and it runs on every add, every sweep and every manual scan -- so each time anything anywhere was fetched, every name in the library went back to "Chapter 12" until that series' next check healed it. The scan now keeps the row's title when the filename says nothing but the number and the row holds a real name; a file that carries a name of its own still wins. Tests: the name filter, the landed stamp, the listing heal and the rescan. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Plenty of sources publish no chapter titles -- Weeb Central answers "Chapter 1" for the whole of One Piece -- while another source has had "Romance Dawn" all along. Same work's names, different source. The hazard is numbering, not names: matching by number is only sound if both sources number the work identically, and past a divergence every borrowed name is wrong in the way that looks right. So this reuses the one rule the app already applies before taking chapters from a second source -- 90% of the numbers we hold listed there, and the verdict agreeing -- and a donor that fails is not used at all. Donors come from the per-source search map, on an exact title match (normTitle); a fuzzy match would be a second way to be wrong that the numbering check cannot catch. Every borrowed name records its donor in lib_books.title_source, so a bad one is identifiable and clearable in bulk; a chapter that already has a real name is never touched, and the chapter's own source naming it later wins. Off per server and per series, because it is outbound traffic to a source that carries nothing else for you; switching it off takes the names back to what each file says. A search that finds no donor is remembered for a week rather than repeated on every check. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
OpenAPI: borrow_names on the settings row, borrowNames on the settings and series PATCH bodies (the latter is additionalProperties: false), and borrowNames / borrowNamesEffective on the admin view of a series. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
AngeloSha
added a commit
that referenced
this pull request
Sep 25, 2026
…oading Read a chapter before adding a series (#91), a source order for new chapters (#93, first half), swapping in a preferred group's copy once it exists (#93, second half; closes #81), chapter names borrowed from a source that numbers the work the same way (#85) and a compact chapter list (#88) -- @Squeaks72's ideas, rebuilt where the originals could not be merged. Every running download, including the server's own sweeps, repairs and bulk fetches, now shows with a Cancel (#82). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
AngeloSha
added a commit
to Squeaks72/uchiyomi
that referenced
this pull request
Sep 25, 2026
… (rebuild of AngeloSha#85) Some sources publish no chapter titles at all -- every row reads "Ch. 12" -- while another source has had "Romance Dawn" all along. The nightly repair gets a seventh step that takes the names from that other source. Off by default, per server and per series: it is traffic to sources that carry nothing else for you. @Squeaks72's idea and its shape. Rebuilt on the hunt's own parts, because the first version: - searched through searchAll, which REPORTS to source health, so a lookup only for names could put a series' own source into a cooldown and stop real downloads. Nothing here reports; each search and lookup is bounded and a failure is just a source that did not answer; - filtered donors by neither language nor the adult rule, so a Spanish "One Piece" matched and named the chapters in Spanish. The hunt's sweepAllowedFor applies, a source in another language is never asked, and a multi-language donor's chapters in another language are never used; - matched names by a floored number with no minimum, so a donor one chapter off named every later chapter wrongly. A donor must now pass judgeCandidate -- the identity and both-way numbering check an automatic follow must pass -- and names are matched by exact number; - trusted a remembered donor the admin had since disabled. It is re-judged. Names go to chapter_name only, never `title`, marked with the donor in chapter_name_source: the chapter's own source replaces a borrowed name the moment it supplies one (the listing heal and setBookMeta), and switching the setting off takes back exactly what was borrowed. Each rule was proved by reintroducing its bug. Two assertions that first passed vacuously -- the language and adult filters, which the good donor's being found first made unreachable -- now have a test that takes that donor away. Co-authored-by: Squeaks72 <Squeaks72@users.noreply.github.com> Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> (cherry picked from commit 900601235e5f7865d742aebdce17b013caa559e2)
Owner
|
Thanks, this is a clever idea and I do want it. I closed this version though, because a few of the problems need it restructured rather than patched:
Since #84 keeps names in their own column, I rebuilt this on the existing hunt pipeline (adult rule, own-language order, budgets, no health reporting). It shipped in v0.47.0 as Borrow chapter names from other sources, off by default, with credit to you in the changelog. |
5 tasks done
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.
Summary
Many sources publish no chapter titles at all. Some answer "Chapter 1", "Chapter 2" for the whole of One Piece, while another source has had "Romance Dawn" all along. This PR lets an admin borrow those names from another source, off by default. It can be turned on server-wide (Admin → Settings → Updates & schedules) or per series (a checkbox in the Sources & translations sheet).
The danger is the numbering, not the names. Matching a name to a chapter by number is only sound if both sources number the work the same way. When they don't, every borrowed name is wrong, and wrong in a way that looks right. So
bff/src/lib/borrowNames.tsis deliberately conservative:normTitle, from the per-sourcesearchAllmap). A fuzzy match would add a second way to be wrong, and the numbering check cannot catch it. A title that folds to nothing (entirely non-Latin script) is never searched, because it would "match" every other such title.assess/verdict/followablefromlib/fill.ts: at least 90% of the numbers we hold, and the verdict agreeing). A donor that fails is not used at all.lib_books.title_sourcecolumn. The chapter's own source naming a chapter later (the landed stamp or the listing heal from Show chapter names, and say which chapter Continue opens #84) replaces the borrowed name and clears the mark.lib_series.name_donor). A search that found no donor is remembered for a week instead of re-running a cross-source search every few hours.Schema:
server_settings.borrow_names(default false),lib_series.borrow_names(null follows the server),lib_series.name_donor,lib_books.title_source. All areADD COLUMN IF NOT EXISTS.API:
borrowNamesonPATCH /api/admin/settingsandPATCH /api/admin/series/:id(nullable there),borrow_nameson the settings row, andborrowNames/borrowNamesEffectiveon the admin view ofGET /api/series/:id. The checkbox has to show what actually applies, including the server's setting. All are documented inbff/openapi.yaml. There are no new routes, so thedocs/api.mdroute list is unchanged. It works the same on Desktop: none of these routes are desktop-hidden, and the switch lives next to the existing "Look for failed chapters on other sources" switch.A known limit, stated plainly: the coverage check proves the donor lists the numbers we hold. It cannot detect a donor that lists the same range with a one-chapter offset, such as a prologue counted as chapter 1. The exact-title requirement, the opt-in default and the recorded
title_source(removable in bulk by switching off) are the mitigations. That limit is the main reason this stays off by default.Type
Testing
Re-run after rebasing onto v0.45.0 (91b41aa): bff 1867 tests, 1854 pass, 9 fail, 4 skipped — the same 9 embedded-Postgres entrypoint failures
mainhas in this environment (main: 1857 / 1844 / 9 / 4), nothing new; web 432/432; both typechecks OK. The detail below is from the first run, on v0.44.0.I ran the upstream CI setup in
node:24-alpineagainst a realpostgres:16-alpine(TEST_DATABASE_URLset), with the same baseline as upstreammain(a8bc502).maintsc --noEmittsc --noEmitThe same 9 failures appear on both sides. They are the
entrypointEmbeddedtests, which need an embedded Postgres binary that this sandbox lacks. There are no new failures. The full run first caughtpredicateHygieneflagging a hand-writtendeleted_at IS NULL. The series lookup now usesvisibleToAll('s'), and I re-ranpredicateHygiene,borrowNames,chapterNames,seriesListing,updaterandopenapiCoverage: all 74 tests passed.openapiCoveragepasses with the schema additions.New:
bff/test/borrowNames.int.test.ts, using fake sources for a correct donor, a donor with numbers shifted to 101–110, and a look-alike title with matching numbers. It pins:trim(trailing '0' ...)reset turned it into "Chapter 1".The new UI strings are translated in all eight locale files.
npm run test:i18nis a Puppeteer walk against a running server, so it could not run in this sandbox. The locale-parity unit test passes.Checklist
docs/USAGE.md)🤖 Generated with Claude Code