Skip to content

v0.73.0: Missing details filled in; sources rated Adult only, AniList's pace and engine passwords - #273

Merged
AngeloSha merged 8 commits into
mainfrom
release/v0.73.0
Oct 16, 2026
Merged

AngeloSha merged 8 commits into
mainfrom
release/v0.73.0

Conversation

@AngeloSha

Copy link
Copy Markdown
Owner

A series with no description, genres or author can have them filled in, a whole source can be rated Adult only, AniList sync waits when AniList asks instead of giving up, and a new Unraid extension engine asks for a password. #257, #245 and #256 are @Squeaks72's, rebuilt on the app's own parts and credited as co-author.

Missing details (#257, #245)

  • Fill in missing details (Admin → Settings → Library housekeeping, off by default) is a ninth nightly repair step, details, with counters, a Tasks line and REPAIR_DETAILS_MAX (15).
  • What it finds goes into a layer of its own, series_auto_details, below the scan and never into series_overrides. Every read is override > scan > filled in (autoDetailsSql.ts), the 18+ filter included, and genres cleared on purpose ({}) stay cleared.
  • AniList first, by id: linked and checked series in English, in libraries that look AniList up, fifty to one Media(id_in:) request, read through readCapped. No Kitsu or MangaUpdates calls.
  • Then the series' own source and its same-language followers. Monitored series only, never a source that is off, failing or cooling down (blockedNow), each lookup on the source's own budget, text through cleanDescription and cleanGenres. A series with no chapters gets a cover. A miss waits 30 days; following a source by hand asks at once.
  • Switching it off deletes the layer and takes back the covers it set.

Adult only (#256)

  • PUT /api/admin/sources/:id/age-rating (18 or null), on the source's sheet as Automatic | Adult only. It is stored in the existing adult-sources list, which becomes a permission: an account limited below 18 is refused the source everywhere an extension-flagged one is, by id too (latest, popular, detail, add, preview, each tested and reintroduced). No Mixed.
  • The 18+ filter's source chips become a pointer to the sheet. The CHANGELOG's upgrade note: sources ticked there before are now refused to capped accounts.

One AniList quota

  • lib/anilistLimit.ts: every AniList GraphQL request (trackers, scores, art, Discover, reading directions, related works, details) shares one per-server limiter, spaced by AniList's live X-RateLimit-Limit and holding on Retry-After, X-RateLimit-Reset or a spent quota. A push waits and sends the same push again; a person or an image is told AniList is busy at once.
  • A rate limit is a state, not an error. Connections says "Syncing slowly: AniList asks us to wait", Health's Tracker sync card leaves it out, and the next good push clears it (old "anilist 429" rows read the same).

Engine sign-in

  • A new Unraid install of the extension engine asks for a password, and Uchiyomi's template has the matching user name. An existing install keeps its settings; extensions.md says how to add one.
  • The desktop app's engine gets a new password at every launch, kept in memory.

Not in this release: #245's Kitsu and MangaUpdates lookups, and #256's Mixed.

Checks (local, before pushing)

  • bff: the full sharded suite (3447 tests, 0 failures, 2 skipped), then the 44 files that use the tracker and Health code again on the final tree; web: 1438/1438; desktop: 151/151; both typechecks.
  • Every "Reintroduce by" note checked by reintroducing it, among them a 40-series backfill held to 30 requests a minute and a 429 waited out with nothing written as an error.
  • The engine template's sign-in against the engine v2.4.2366: no pair 401, the pair 200.
  • Browser: the main walk, the language walk, the embedded leg and all four v0.55.8 gate phases; screenshots of the new screens on phone and desktop; a rollback drill (v0.72.0 on a database v0.73.0 has migrated and filled).
  • 15 new strings, translated into all eight languages and reviewed.

🤖 Generated with Claude Code

AngeloSha and others added 8 commits October 16, 2026 11:57
…ount limited below 18 (rebuild of #256)

Admin → Sources → a source → Age rating: Automatic leaves it to the source's extension, Adult only makes the
whole source adult whatever the extension declares -- the one way a built-in or added site can be rated.

- The rating is the 18+ lists' existing adult_sources, now a permission as well as a surfacing filter:
  sourceAllowedFor refuses a rated source to an account limited below 18 exactly as it refuses a flagged one,
  everywhere it is asked (latest, popular, detail, add, preview, the fan-outs, icons, archive, Find). Held in
  memory because the check is synchronous: loaded at boot, replaced on every write and every read of the lists;
  a capped account's request reads it first if nothing has yet.
- PUT /api/admin/sources/:id/age-rating {ageRating: 18 | null}, one atomic jsonb statement, audited
  source.age_rating; 409 too_many past 200 (said code rating.tooMany). The overview reports ageRating and
  defaultAgeRating.
- No "Mixed": cancelling an extension's adult flag would lift the age cap for a whole site (the #130 ruling).
- The 18+ filter's source chips go: the list they saved is a permission now, so it is set on the source, and the
  section says where. Sources ticked there become refused to capped accounts: said in the upgrade note.
- Tests: sourceAdultRating.int drives the five by-id routes as a capped account before and after the rating,
  each reintroduced; the preview note says why that step holds by the age_limited rule as well.
- 8 new strings, translated in all eight languages.

Co-Authored-By: Squeaks72 <Squeaks72@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ilds of #257 and #245)

Admin → Settings → Library housekeeping → Fill in missing details, off by default: the nightly repair's ninth step
(`details`) gives a series with no description, genres or author of its own the ones another place has, and a series
with no chapters yet a cover.

- Its own layer, series_auto_details, read only where the series' own value (lib_series, the scan) and the admin's
  edit (series_overrides) are both empty: lib/autoDetailsSql.ts is the one expression for the series source, OPDS,
  the Komga authors and the 18+ filter (which judges the genres a series shows), and the hero rule counts all three.
  #257 wrote into series_overrides: it shadowed better data a later scan brought, refilled genres cleared on purpose
  (`{}`), and could change what Show 18+ hides.
- AniList first (#245, ported AniList-first): one batched Media(id_in:) request per fifty series linked there with a
  checked link, in libraries whose lookups are on, in English. No Kitsu or MangaUpdates call. mediaById reads through
  readCapped.
- Then, as stepNames does: at most REPAIR_DETAILS_MAX (15) series that are kept updated, their own source and then
  the ones they follow in their language, only usable sources (standing, then blockedNow right before), each lookup
  bounded by the source's budget and the series by a minute; text through cleanDescription and cleanGenres.
- A series asked waits 30 days (sources_at, anilist_at); a manual follow asks at once. Counters, a Tasks line, the
  limits and the estimate. Switching it off deletes the layer and puts back any cover it set. Forget purges it.
- Behaviour tests (autoDetails.int): off by default, the order and the cleaning, below the scan, `{}` kept, the
  cooldown and language rules, monitored only, the 18+ filter, AniList's one batch, the month's wait, the manual
  follow over HTTP, the take-back. Three reintroduced.
- 5 new strings, translated in all eight languages.

Co-Authored-By: Squeaks72 <Squeaks72@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nd the desktop's changes every launch

- Unraid: the engine template publishes its port on the bridge network (Uchiyomi reaches it at the server's address),
  so a new install starts with AUTH_MODE basic_auth, AUTH_USERNAME uchiyomi and a required, masked AUTH_PASSWORD; the
  Uchiyomi template's SUWAYOMI_USERNAME defaults to the same user. The three variables have been in the template
  since its first version, so an existing install keeps its own values (Unraid adds missing variables, never changes
  a value). Checked on v2.4.2366: no credentials 401, the pair 200. docs/extensions.md "A password on the engine" says
  how an existing install turns it on; INSTALL.md and the in-app Unraid steps ask for the password (1 new string,
  translated in all eight languages); releasePipeline pins the defaults.
- Desktop: the engine's basic-auth pair is made with each launch's Supervisor and held in memory only, handed to the
  engine (environment) and the bff (SUWAYOMI_*); secrets.json keeps the database password and drops the old pair.
  shell.supervisor proves a second launch gets a new pair, reintroduced.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…, a 429 waited out, a wait never an error

The owner connected AniList and the backfill pushed fourteen series, met a 429, dropped the push and left
"anilist 429" on Profile → Connections. AniList limits each address (90 a minute, 30 while degraded, as its
X-RateLimit-Limit says), and every AniList request this server makes counts against that one number, while each
caller paced itself alone: 2.4 s per user's push lane (two calls a push), 2.2 s between batch pages.

- lib/anilistLimit.ts: every AniList GraphQL request goes through anilistFetch -- the tracker calls, the scores,
  art, Discover's lookups and trending, the reading directions, the related works and the missing details. It
  spaces requests 60 s / (limit - 2) apart once AniList has stated its limit, holds every caller on a 429 until
  Retry-After (else X-RateLimit-Reset, else a minute) and on a spent quota, then makes the request again. Each
  attempt's timeout starts with the attempt. A caller someone waits on (art behind an image, Connect, Test, the
  import, recommendations, a rail) is answered AniListBusy at once rather than held past 15 s; a push or a batch
  waits up to ten minutes and five retries. The push lanes keep their order with no extra gap for AniList.
- A 429 that outlasts the retries is a pace, not an error: last_error 'rate_limited' (and the old "anilist 429"
  rows), served as slowedDown with no lastError, said on Connections as "Syncing slowly: AniList asks us to wait"
  in the help's own colour. The next push that lands clears it, as before; needsReconnect never reads it.
- lib/trackerPace.ts holds that one reading, so Health's Tracker sync card (v0.72.0) does not list a member
  whose tracker only asked us to wait.
- anilistQuota.int (virtual clock, a scripted AniList stating 30 a minute): a 40-series backfill through the
  route stays at 30 or under in any minute and pushes every series; a 429 is waited out for its Retry-After and the
  same push lands with nothing written; an endless 429 reads slowedDown, stays off Health's Tracker sync card and
  clears; a person is told "busy" at once. Each reintroduced. trackerVerdicts and trackerRecs start each case with
  a fresh quota.
- 1 new string, translated in all eight languages.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…he app does elsewhere, and four fixes in three more languages

- Arabic: the source path reads right to left (◂), "accounts limited below 18" names the age limit the way the rest of
  the app does (حدّ عمرها), and "At most {limit} sources" no longer uses the 11-99 number form for a limit of 200.
- Russian: an age rating is set (задаётся), not scored, and the limit is a возрастное ограничение, as elsewhere.
- Japanese: the sources a series follows are フォロー中, as everywhere else in the app.
- Chinese: the details result line counts 部作品 like the lines beside it.
- Portuguese (Brazil): "nos pede para esperar", in the register the rest of the file uses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…gine passwords

@Squeaks72 is credited for #257, #245 and #256. The upgrade note says what changes for sources that were ticked as
adult under the 18+ filter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@AngeloSha
AngeloSha merged commit f107873 into main Oct 16, 2026
12 checks passed
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