Repository navigation
Retry automatic search without the author when the full query returns nothing (Fixes #1068) - #1072
Conversation
therobbiedavis
left a comment
There was a problem hiding this comment.
The author-free retry is useful, but the title guard still lets a different book reach automatic download selection. I reproduced this in a live container pass. This needs an identity check before the broadened results reach quality scoring.
|
Closing in favor of #825, which already tracks the title-only retry — thanks for the pointer. I agree the retry is a band-aid over the real selection issue (ranking by quality before establishing the release matches the requested book), and #1054 is reworking the search path in that direction. The one piece worth carrying forward is constraining results to titles that match the requested book before quality ranking (the |
|
Backend matching is delegated to #1076 Any match revision before the step of doing a backend matching is welcomed IMO. We should revise matching because I will not change the buisness logic rules during the backend refactoring. This PR should stay open then. |
Addresses the Listenarrs#1072 review: the previous IsMatchingTitle (containment) guard let a different book reach automatic download selection — e.g. Eoin Colfer's "Artemis Fowl" for Andy Weir's "Artemis", and a different author's "Revival". Replaces it with CanAutomaticallySelectFallback, following the maintainer's conservative candidate: parse only "Title" or "Author - Title" layouts (with optional trailing year/format suffixes), require the complete remaining title to match the book exactly after normalization, and require at least one corroborating signal (parsed author, Artist field, or ASIN) with any conflicting evidence vetoing. The Artist field is only corroboration when it matches (it can be a provider guess). Uncertain layouts and uncorroborated authorless results are skipped, so this won't recover every title-only release but refuses to grab a different book. Tests cover a valid author-matched fallback, both reported collisions (same-word title and same-title/different-author), an uncorroborated authorless skip, and Artist-field corroboration. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Reopened — sorry, I'd closed this before your review landed. Thanks for catching the collision and for the detailed candidate; that's a real wrong-book hazard and the containment guard clearly wasn't enough. Replaced Tests ( On the full-cycle coverage: the guard is what gates fallback results before they reach selection, so these assert the collisions can't be selected. I kept them at the classifier level — the retry orchestration lives in the hosted-service loop (resolves ~7 services + a SignalR hub from a scope), which your own candidate's tests also stopped short of. Happy to add a scope-driven handoff test if you'd like that layer too. |
|
Added the full-cycle regression coverage you asked for. The previous tests stopped at the classifier (
Both collisions are the ones you reproduced reaching |
There was a problem hiding this comment.
@dny238 The updated guard addresses the wrong-book cases I reproduced. I have one non-blocking follow-up suggestion for numeric titles: the missed recovery below also occurs before this PR, so I wouldn't hold this change up for it.
| var parts = Regex.Split(result.Title.Trim(), @"\s+[-–—]\s+").ToList(); | ||
|
|
||
| // Drop trailing year / format suffix segments ("... - 2017", "... - [M4B]"). | ||
| while (parts.Count > 1 && Regex.IsMatch( |
There was a problem hiding this comment.
Good follow-up PR candidate: could we preserve numeric book titles before treating trailing numbers as publication years? For George Orwell - 1984 - M4B, this loop removes both M4B and 1984, leaving George Orwell as the parsed title and dropping the correct release. David McCullough - 1776 - 2005 - M4B behaves the same way. This edge case was also in the prototype I suggested.
I compared the pre-PR path and this head in a live HTTP indexer container. When the full query returns nothing, neither selects these numeric-title releases; when it returns a valid 1984 result, both select it. The suffix parsing is new, but the missed recovery is not a user-visible regression—the previous path never retried.
For a follow-up, stop removing a segment when it matches the requested title:
while (parts.Count > 1
&& !string.Equals(
NormalizeIdentity(parts[^1]),
NormalizeIdentity(audiobook.Title),
StringComparison.Ordinal)
&& Regex.IsMatch(
parts[^1],
@"^(?:\d{4}|\[?(?:m4b|mp3|flac|aac|ogg|opus)\]?)$",
RegexOptions.IgnoreCase))
{
parts.RemoveAt(parts.Count - 1);
}That candidate recovered both numeric titles in the same container while still rejecting conflicting-author and uncorroborated authorless results. Add cases for a numeric title alone, with a format suffix, and with a separate publication year, retaining those negative controls. Validation stops at the recorded StartDownloadAsync handoff; no actual media download or import was exercised.
Addresses the Listenarrs#1072 review: the previous IsMatchingTitle (containment) guard let a different book reach automatic download selection — e.g. Eoin Colfer's "Artemis Fowl" for Andy Weir's "Artemis", and a different author's "Revival". Replaces it with CanAutomaticallySelectFallback, following the maintainer's conservative candidate: parse only "Title" or "Author - Title" layouts (with optional trailing year/format suffixes), require the complete remaining title to match the book exactly after normalization, and require at least one corroborating signal (parsed author, Artist field, or ASIN) with any conflicting evidence vetoing. The Artist field is only corroboration when it matches (it can be a provider guess). Uncertain layouts and uncorroborated authorless results are skipped, so this won't recover every title-only release but refuses to grab a different book. Tests cover a valid author-matched fallback, both reported collisions (same-word title and same-title/different-author), an uncorroborated authorless skip, and Artist-field corroboration. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1a98902 to
9f69405
Compare
Addresses the Listenarrs#1072 review: the previous IsMatchingTitle (containment) guard let a different book reach automatic download selection — e.g. Eoin Colfer's "Artemis Fowl" for Andy Weir's "Artemis", and a different author's "Revival". Replaces it with CanAutomaticallySelectFallback, following the maintainer's conservative candidate: parse only "Title" or "Author - Title" layouts (with optional trailing year/format suffixes), require the complete remaining title to match the book exactly after normalization, and require at least one corroborating signal (parsed author, Artist field, or ASIN) with any conflicting evidence vetoing. The Artist field is only corroboration when it matches (it can be a provider guess). Uncertain layouts and uncorroborated authorless results are skipped, so this won't recover every title-only release but refuses to grab a different book. Tests cover a valid author-matched fallback, both reported collisions (same-word title and same-title/different-author), an uncorroborated authorless skip, and Artist-field corroboration. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
9f69405 to
9d27813
Compare
… nothing Fixes Listenarrs#1068: automatic search for a book returned 0 results when the release names don't carry the author. A read-only comparison against NZBgeek showed the title+author query returning nothing while the title-only query returned the releases (de-hyphenating made no difference; the author and query specificity were the cause). AutomaticSearchService now retries once with an author-free query (title + series) when the full query returns no results. Because the automatic path scores by quality only — relevance comes from the query itself — the broadened fallback results are constrained to titles that still match the book (ConstrainFallbackResultsToTitle, via TitleUtils) before they reach scoring, so a same-title/different-book release can't be grabbed. Short/generic titles fail that match and are safely dropped. Adds AutomaticSearchResultClassifierTests for the author-free query and the title constraint. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Addresses the Listenarrs#1072 review: the previous IsMatchingTitle (containment) guard let a different book reach automatic download selection — e.g. Eoin Colfer's "Artemis Fowl" for Andy Weir's "Artemis", and a different author's "Revival". Replaces it with CanAutomaticallySelectFallback, following the maintainer's conservative candidate: parse only "Title" or "Author - Title" layouts (with optional trailing year/format suffixes), require the complete remaining title to match the book exactly after normalization, and require at least one corroborating signal (parsed author, Artist field, or ASIN) with any conflicting evidence vetoing. The Artist field is only corroboration when it matches (it can be a provider guess). Uncertain layouts and uncorroborated authorless results are skipped, so this won't recover every title-only release but refuses to grab a different book. Tests cover a valid author-matched fallback, both reported collisions (same-word title and same-title/different-author), an uncorroborated authorless skip, and Artist-field corroboration. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The classifier tests stop at ConstrainFallbackResultsToTitle. Add tests that drive the whole automatic-search cycle (AutomaticSearchProcessor .RunCycleAsync) through to the download-service handoff: - A same-word different book (Eoin Colfer's Artemis Fowl for Andy Weir's Artemis) never reaches StartDownloadAsync. - A same-title different author (Chris Weitz's Revival for Stephen King's) never reaches StartDownloadAsync. - A correctly attributed fallback (Andy Weir - Artemis) does reach StartDownloadAsync with the requested book's id. Both collisions were reported reaching download selection in the live container pass; these lock that down at the cycle level. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
9d27813 to
9882668
Compare
…v1.5.2) Upstream v1.3.24-v1.5.2: Listenarrs#757 indexer-timeout containment, Listenarrs#605 quality-profile picker, Listenarrs#714 automatic-search timing (sweep interval / per-book cooldown / book delay), Listenarrs#1072 author-free retry with title constraint, Listenarrs#990 post-nominal author folders. Resolutions: - ApplicationSettings / AutomaticSearchService / AutomaticSearchResultClassifier: upstream's three timing columns and author-free fallback replace the fork's AutomaticSearchIntervalHours-as-cooldown, trailing book delay and opt-out title-only fallback. Fork's SearchProgressReporter broadcasts, blocked-release and filter-pipeline hooks kept; SearchNow.cs no longer passes the fallback flag. - Migrations: fork-only 20261021212417_RetireForkAutomaticSearchTuning renames the July fork columns to Retired_* (native transactional ALTER, no rebuild) so upstream's 20261021212418_AddAutomaticSearchTiming applies unchanged. Snapshot = upstream's. SqliteMigrationSchemaTests expected history updated. - IndexerSearchWorkflow: fork's inner HttpClient-timeout catch removed in favor of upstream's per-indexer OperationCanceledException containment (Listenarrs#757 supersedes Listenarrs#967); the contradicted cooperative-cancellation test removed. Torznab provider catch and HttpClientTimeoutClassifier remain. - WantedView.vue: fork's server-side wanted-search strip/queue kept alongside Listenarrs#605's profile-recovery banner, modal and pending-refresh set; upstream's browser-loop remnants (sleep/abortDelay/showConfirmSearchAll) not reintroduced; duplicated useToast import collapsed. - AutomaticSearchProcessorFallbackTests: scorer mock adapted to the fork's three-parameter ScoreSearchResults. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Fixes #1068
Problem
Automatic search for a book could return 0 results even when the book is available, because the auto-built query is
Title Author (Series)and many release names don't carry the author.I verified this read-only against NZBgeek's API:
…Full Cast Editionreturned 5 results, but appendingJ.K. Rowlingdropped it to 0 (release names omit the author); and over-specific multi-word queries AND-matched to nothing. (De-hyphenating made no difference — that's a separate normalization, see #1070.)Fix
AutomaticSearchServicenow retries once with an author-free query (title + series) when the full query returns no results.Safety: the automatic path scores results by quality only — relevance comes entirely from the query — so broadening the query could otherwise let a same-title/different-book release pass scoring and be grabbed. The fallback therefore constrains its results to titles that still match the book (
ConstrainFallbackResultsToTitle, built onTitleUtils.IsMatchingTitle) before they reach scoring. Distinctive multi-word/long titles recover their releases; short or generic titles (where same-title collisions are likely) fail the match and are safely dropped, so nothing unrelated is grabbed.Testing
AutomaticSearchResultClassifierTests:Andy Weir - Artemis - 2017 - M4Bfor Artemis) and drops an unrelated one (… The Martian …);The retry orchestration itself lives in the hosted-service loop (
ProcessAudiobookAsync), which resolves ~7 services + a SignalR hub from a scope; happy to add a scope-driven integration test if you'd like it, but I kept the safety-critical pieces (query shape + title constraint) in the testable classifier.🤖 Generated with Claude Code