Retry automatic search with title only when title and author returns nothing - #824
Closed
matheusfillipe wants to merge 1442 commits into
Closed
Retry automatic search with title only when title and author returns nothing#824matheusfillipe wants to merge 1442 commits into
matheusfillipe wants to merge 1442 commits into
Conversation
Normalize application version to 0.2.67 across the repo: update version fields in root package.json and fe/package.json, update corresponding package-lock.json files, and set Version/AssemblyVersion in listenarr.api/Listenarr.Api.csproj. This reverts the previous 0.2.68 bump to restore consistent versioning.
…dates Fix security scan findings — lodash 4.18.1 + Docker image CVE remediation
[skip ci] Merge: Bump version to 0.2.68
…image-auth feat: add session cookie for browser-native image authentication
[skip ci] Merge: Bump version to 0.2.69
…mplate [skip ci] docs: add PR description template
Update build/runtime toolchain and dependencies to address security and compatibility issues. Dockerfile: bump gosu builder to golang:1.26, move Node setup from 20→24, upgrade pinned npm to 11.12.1 and overwrite bundled picomatch to 4.0.4 to mitigate several CVEs and Node EOL. Frontend: raise engines to >=24.0.0, bump TypeScript to ~6.0 and update several dev/runtime deps (vite, cypress, web-vitals, eslint plugins, etc.). Discord bot: convert to ESM (index.js → import/exports, package.json type: module), raise Node engine, and update related deps to ESM-compatible versions; fix runtime issues (discord.js import, single-use response body handling, normalize Audible isbn/series). Backend: fix Listenarr.Api.csproj tools paths so bot files are copied to output and adjust AntiforgeryValidationMiddleware to skip CSRF checks for ApiKey-authenticated requests. CHANGELOG updated with Unreleased notes.
Change AuthMethod comparison to use StringComparison.Ordinal so the "ApiKey" check is case-sensitive (prevents different-cased values from being treated as API keys). Also fix formatting in listenarr.api/tools/discord-bot/package.json by adjusting the trailing comma/brace so the overrides property is properly included and the JSON structure is valid.
…dates Upgrade to Node.js 24 LTS, migrate Discord bot to ESM, and patch Docker CVEs
[skip ci] Merge: Bump version to 0.2.70
… on files and set monitoring
[skip ci] Merge: Bump version to 0.2.71
Fix: inputMode leftovers + revert version
[skip ci] Merge: Bump version to 0.2.71
* test(series-monitoring): cover title folder persistence (Listenarrs#451) * test(series-monitoring): align regression with test framework * chore(deps): update dependency set * test(frontend): stabilize pre-push suite * chore(deps): refresh compatible dependency versions * test(series-monitoring): use catalog builders * test(frontend): align hook timeout with suite timeout * updating stale doc version references * Update CONTRIBUTING.md * more stale doc updates * more stale doc updates * more stale updates * chore(frontend): align node tooling with node 24 * Update package-lock.json
[skip ci] Merge: Bump version to 1.0.10
…stem disk (Listenarrs#508) (Listenarrs#656) * feat: report per-disk storage in /system/storage (Listenarrs#508) GET /api/v1/system/storage now returns a disks array alongside the existing fields: the System disk (container root, e.g. docker.img on Unraid), the App Data disk (config volume holding database/logs/cache), and one entry per configured root folder. Each disk is measured with DriveInfo on the path itself so Docker volume mounts report their own filesystem instead of the container root's. Missing or inaccessible paths yield an 'unavailable' entry instead of failing the request. The legacy top-level fields now describe the App Data disk (config volume) rather than the install-path root, and DriveName carries that path. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat: show per-disk storage list on System page (Listenarrs#508) The Storage card now renders one entry per disk from the new disks array — label and mount point, a full-width usage bar, and the percentage / used-of-total line — via a new StorageDisksList component. ProgressBar's size formatter gains a TB unit so multi-terabyte mounts no longer display as thousands of GB. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs: changelog entry for per-disk storage (Listenarrs#508) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: measure Windows paths via GetDiskFreeSpaceEx for UNC/NAS support (Listenarrs#508) DriveInfo throws on UNC/NAS roots (\\server\share), so those reported as unavailable. On Windows, measure any directory — drive paths, mounted-folder junctions, and UNC shares — via GetDiskFreeSpaceExW. Unix keeps DriveInfo (statvfs). Disk-info construction is now shared through a BuildDiskInfo helper. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: unique disk keys and per-row free space display (Listenarrs#508) Address PR review: - Composite v-for key (label:path:index) so a configured root folder sharing a path with the System/App Data entry no longer triggers a duplicate-key warning. - Each row shows free-of-total capacity (Listenarrs#508 is about available space), replacing the bar's used/total readout; the percentage stays. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix: address PR review follow-ups for per-disk storage (Listenarrs#508) - Extract disk-space measurement behind an IDiskSpaceProbe seam so the Windows GetDiskFreeSpaceEx path is unit-testable; cover UNC inputs. - Clamp used bytes/percentage so filesystems reporting free > total (reserved blocks, over-provisioning, ZFS/Btrfs, network shares) cannot go negative; add an over-provisioned test. - Document the legacy top-level StorageInfo fields as describing the App Data disk, with per-disk detail in Disks; fix the disk-order comment. - Drop the Storage card summary badge (it headlined the least useful disk); the per-disk list already shows each disk's free/total. - Add ProgressBar TB-formatting tests. - Remove the CHANGELOG entry per repo policy (no changelog on upstream PRs). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
[skip ci] Merge: Bump version to 1.0.11
* Fix dependency drift and clean frontend build warnings Enable deterministic NuGet restores for backend projects by turning on package lock files and CI locked restore mode. Add generated NuGet lock files so local and CI test runs resolve the same dependency graph before `dotnet test --no-restore`. Pull in the dependency updates from `chore/dependency-update`, including the Node engine update to `^24.15.0` and refreshed root/frontend npm lockfiles. Clean up frontend build warnings introduced during dependency validation by removing the auth store's dynamic router import and moving router instance access into a small shared service. Add a narrow Vite/Rolldown warning filter for known upstream `@vueuse/core` pure annotation noise. Validated with: - `dotnet restore listenarr.slnx /p:CI=true` - `dotnet test listenarr.slnx --no-restore` - `npm install` - `cd fe && npm install` - `cd fe && npm run test:unit` - `cd fe && npm run build` - `cd fe && npm run lint:check` - `git diff --check` * Clarify backend architecture boundaries * Fix architecture boundary build * Remove unnecessary usings and fix startup lifetime * Clarify realtime architecture boundary * Updating terminology to stay consistent * Move realtime wiring behind infrastructure extensions * Respect forwarded header trust model * Update NuGet locks for architecture split * Handle IPv4-mapped loopback notification callers * Extract large backend service slices * Extract audiobook identifier helpers * Extract remaining backend parsing helpers * Extract MyAnonamouse response parser * Extract library path planner * Split remaining backend helper concerns * Break down library and search workflows * Extract library scan workflows * Refactor backend services into focused workflows * Slice backend workflows into focused helpers * Extract remaining backend workflow seams * Extract deeper backend workflow orchestration * Extract backend workflow slices * Slice remaining backend workflows * refactor: slice backend helper workflows - Extract queue metadata matching and Prowlarr toast throttling helpers - Move notification diagnostics, scan path planning, and system formatting into focused helpers * refactor: extract queue snapshot helpers - Move queue snapshot result/cache shaping into focused helper types - Extract system log parsing from SystemService * refactor: extract service diagnostics helpers - Move queue metric and late poll diagnostics into a focused helper - Move system disk measurement mapping out of SystemService * refactor: extract system health mapper - Move service health status construction out of SystemService - Preserve existing enabled-client and API health semantics * refactor: extract notification payload context - Centralize startup base URL and API version resolution for notification payloads - Preserve provider-specific delivery and logging behavior * refactor: extract notification failure logging - Move failed webhook response logging into notification diagnostics - Preserve redaction markers and provider delivery behavior * refactor: extract image cache content validation - Move downloaded image media, extension, and placeholder checks into a helper - Preserve image cache IO, paths, and download behavior * refactor: extract image identifier helpers - Move image identifier normalization and lookup exception checks out of ImagesController - Preserve image lookup workflow, routes, and response behavior * refactor: extract cache and parser helpers - Move image download URL, redirect, and DNS validation into a focused helper - Extract qBittorrent import path resolution and MyAnonamouse JSON result extraction * refactor: extract adapter import path helpers - Move SABnzbd import path checks into a focused helper - Move Transmission content path and source-file helpers out of adapter workflows * refactor: extract ffprobe metadata mapper - Move ffprobe JSON-to-metadata translation into a focused mapper - Keep process execution and exception handling in FfmpegService * refactor: extract download record factory - Move queued download record construction out of DownloadService - Keep duplicate checks and client handoff behavior unchanged * fix: restore ffmpeg archive import - Restore SharpCompress archive extension import required by WriteToFile - Fix infrastructure build after ffprobe mapper extraction * refactor: extract download and adapter helpers - Move download duplicate, metadata, and notification helpers out of DownloadService - Extract MyAnonamouse contributor parsing - Split NZBGet, SABnzbd, and qBittorrent planning/connection helpers * refactor: extract image cache helpers - Move cached image path validation out of ImagesController - Extract image cache storage lookup, bounded content reads, and refresh backup workflow - Preserve routes, placeholder behavior, and cache layout * refactor: extract torrent adapter helpers - Centralize qBittorrent cookie client and login form setup - Move Transmission label, id, and torrent identifier parsing into a request planner * refactor: extract prowlarr import url planner - Move Prowlarr base/proxy URL construction out of IndexersController - Preserve import matching and outbound validation behavior * refactor: extract search mam option parsing - Move MyAnonamouse query parsing out of SearchController - Reuse parsing helper for indexer and API-specific search endpoints * refactor: extract ffprobe checksum parser - Move checksum file parsing out of FfmpegService - Keep ffprobe install and checksum validation behavior unchanged * refactor: extract torznab provider helpers - Move Torznab/Newznab request URL construction into a focused helper - Move response size and language parsing out of the provider * refactor: trim mam response parser - Remove unused recursive MAM id lookup from the response parser - Leave active MyAnonamouseHelper lookup behavior unchanged * refactor: extract nzbget authentication - Centralize NZBGet Basic Auth header construction - Remove unused version parsing helper from the adapter * refactor: extract sabnzbd json parsing - Move defensive SABnzbd numeric JSON parsing into the response mapper - Keep queue progress mapping behavior unchanged * refactor: extract image identifier validation - Move GetImage identifier normalization and validation into a focused helper - Preserve image route responses and fallback behavior * refactor: extract qbittorrent add content - Move qBittorrent torrent and URL add request content construction into a helper - Keep adapter authentication, posting, and tracker fallback behavior unchanged * refactor: extract lookup workflows - Move metadata author and series lookup orchestration into focused workflows - Extract qBittorrent torrent lookup and SABnzbd history parsing helpers - Move metadata-driven image fallback downloads out of ImagesController * refactor: extract sabnzbd polling workflow - Move SABnzbd queue/history download polling into a focused workflow - Keep adapter interface and reconciliation behavior unchanged * refactor: extract nzbget polling workflow - Move NZBGet JSON-RPC polling and progress reconciliation into a workflow - Keep adapter interface and matching behavior unchanged * refactor: extract transmission polling workflow - Move Transmission RPC polling and torrent reconciliation into a workflow - Preserve session-id retry and seed-limit metadata behavior * refactor: extract qbittorrent polling workflow - Move qBittorrent polling, torrent lookup, and download reconciliation into a workflow - Preserve login, category/hash querying, and completion behavior * refactor: extract prowlarr import workflow - Move Prowlarr import fetch, tag lookup, filtering, and creation into a focused workflow - Keep IndexersController responsible for HTTP response shaping * refactor: extract structured search workflow - Move POST search request orchestration into a focused workflow - Keep SearchController as the HTTP adapter for structured search responses * refactor: extract prowlarr notifications - Move indexer realtime broadcasts and toast throttling into a focused workflow - Keep Prowlarr compatibility endpoints focused on payload handling and responses * refactor: extract direct download workflow - Move DDL tracking record creation out of DownloadService - Register the workflow through existing application service DI * refactor: extract image candidate lookup - Move metadata-driven image candidate discovery into a focused workflow - Keep ImagesController responsible for request validation and image responses * refactor: extract mam date parsing - Move MyAnonamouse publish date and age parsing into a focused helper - Keep response parser result mapping behavior unchanged * refactor: extract download removal workflow - Move queue removal lookup, client removal, and cleanup rules into a focused workflow - Keep DownloadService as a thin delegate for removal requests * refactor: extract ffprobe asset discovery - Move GitHub release asset lookup out of FfmpegService - Keep ffprobe install and extraction behavior unchanged * refactor: extract nzbget removal workflow - Move NZBGet history lookup and queue deletion into a focused workflow - Keep adapter removal behavior and logging unchanged * refactor: extract sabnzbd removal workflow - Move SABnzbd queue and history deletion into a focused workflow - Keep adapter removal behavior and logging unchanged * refactor: extract qbittorrent removal workflow - Move qBittorrent auth probing and torrent deletion into a focused workflow - Keep adapter removal semantics and logging unchanged * refactor: extract transmission removal workflow - Move Transmission torrent-remove RPC payload handling into a focused workflow - Keep adapter removal semantics and logging unchanged * refactor: extract queue candidate loader - Move queue repository candidate loading into a focused helper - Preserve DDL visibility rules and known client ID matching inputs - Update queue reconciliation test construction for the new helper * refactor: extract download queue poller - Move client queue polling and stale snapshot fallback into a focused poller - Keep queue enrichment and orphan retention in DownloadQueueService - Preserve focused queue reconciliation test coverage * refactor: extract author catalog mapping - Move author catalog keying, matching, language normalization, and cache DTO mapping into a focused helper - Keep author catalog lookup and persistence orchestration in the service - Preserve focused author and metadata test coverage * refactor: extract prowlarr response builder - Move compatibility indexer response shaping into a focused builder - Preserve read versus save API-key response behavior - Remove the stale private field DTO from the controller * refactor: extract search disposition logger - Move final ASIN disposition auditing out of SearchService - Preserve candidate drop reason mutation and diagnostic logging - Register the helper in API and infrastructure service setup * refactor: extract mam torrent bencode helper - Move torrent bencode rewrite and announce parsing logic into a focused helper - Keep MyAnonamouseHelper public methods as compatibility delegates - Preserve MAM and torrent-focused test coverage * refactor: extract ffprobe platform defaults - Move platform-specific ffprobe download URL and checksum defaults into a focused helper - Keep installation orchestration and provider override behavior unchanged - Preserve ffmpeg-focused test coverage * refactor: extract search title workflow - Move title search ASIN lookup and Discord response shaping into a focused workflow - Keep route status codes and response payloads unchanged - Register the workflow through API startup * refactor: extract notification http sender - Move validated notification HTTP sending and redirect checks into a focused helper - Preserve request-context private target rules and existing HttpClient behavior - Keep provider-specific notification dispatch unchanged * refactor: reuse search image normalization - Replace inline search result image cache handling with SearchResponseMapper - Remove the now-unused controller image path wrapper - Preserve search-controller focused test coverage * refactor: extract mam download url builder - Move MyAnonamouse torrent download URL construction into a focused helper - Preserve mam_id decode and encode behavior - Keep parser mapping behavior unchanged * refactor: extract sabnzbd queue workflows - Move SABnzbd queue/history merge behavior into a focused workflow - Move SABnzbd import item resolution into a dedicated resolver - Keep adapter interface and request/response semantics unchanged * refactor: extract nzbget add workflows - Move NZBGet add orchestration into a focused workflow - Move NZBGet import item history resolution into a dedicated resolver - Keep adapter interface and XML-RPC behavior unchanged * refactor: extract indexer debug search - Move MyAnonamouse debug-search orchestration into a focused workflow - Keep route, response payloads, and local parsed-search behavior unchanged * refactor: extract automatic search helpers - Move existing-quality cutoff evaluation into a focused helper - Move automatic download-client selection into a dedicated selector - Keep search scheduling, scoring, and download queuing behavior unchanged * refactor: extract qbittorrent import resolver - Move qBittorrent import path resolution into a focused resolver - Keep queue-item and download-client-item import behavior unchanged * refactor: extract transmission import resolver - Move Transmission import path resolution into a focused resolver - Keep RPC lookup, content path, and source-file behavior unchanged * refactor: extract ffprobe archive extraction - Move ffprobe archive expansion and traversal checks into a focused helper - Keep install discovery, checksum validation, and binary promotion behavior unchanged * refactor(workers): harden background services - Add shared worker cycle and processor interfaces - Wire hosted workers through processor contracts - Add ownership and import handoff guard tests * refactor(workers): extract scan move processors - Move scan and move orchestration into processor services - Keep hosted services as queue adapters - Add processor tests and worker metrics * refactor(workers): complete ownership split - Extract hosted worker logic into explicit processors - Document ownership, retry, idempotency, and handoffs - Add processor boundary and worker metric tests - Rename moved-download cleanup hosted adapter * fix(fs): harden mutation path safety - Add shared containment and final-target validation for filesystem mutations - Harden imports, moves, deletes, cache writes, archive extraction, remote mappings, and ffprobe paths - Add temp-directory coverage for traversal, idempotent imports, mapping boundaries, and cache safety * test(fs): add mutation safety coverage - Cover archive extraction traversal blocking with real temp directories - Cover file storage write/delete containment around allowed roots * refactor(api): simplify startup composition - Split API startup into focused registration and pipeline modules - Move security setup and middleware ordering into one startup module - Add end-to-end coverage for auth, CSRF, SignalR, and proxy headers * fix(review): address pr findings - Use epsilon checks for metadata duration updates - Align remote path mapping test with exact-root behavior * fix(review): address pr findings - Use epsilon checks for metadata duration updates - Align remote path mapping test with exact-root behavior * test(fs): preserve mapped root separator - Expect exact remote path mappings to preserve directory root separators * style: trim header whitespace - Remove trailing spaces from license header blank lines - Restore clean git diff whitespace validation * Delete CHANGELOG.md * feat(downloads): harden download lifecycle - Commit imports before cleanup and preserve correlated activity history - Add trusted download preparation and adapter regression coverage - Enforce append-only history and unlimited retention by default * test(architecture): guard backend boundaries - Document the vertical feature layout and namespace rules - Add dependency, migration, filesystem, and HTTP registration guards - Remove duplicate external HTTP client registrations * refactor(downloads): group client adapters - Organize each download client as an owned infrastructure feature - Move shared adapter utilities and mirror client test folders - Preserve adapter behavior with the full backend suite * refactor(downloads): organize lifecycle features - Separate submission, queue, import, processing, monitoring, and cleanup - Move workers and finalization under their owned download features - Mirror the lifecycle structure in backend tests * refactor(history): group activity ledger - Colocate canonical history persistence, compatibility services, and EF mapping - Mirror history migrations, repositories, and service tests - Keep migration artifacts and public history behavior unchanged * refactor(library): group audiobook workflows - Organize catalog, files, identifiers, monitoring, quality, rename, and jobs - Move library-specific scan and move workers out of generic infrastructure buckets - Mirror library ownership in focused backend tests * refactor(search): group indexer workflows - Colocate search orchestration, parsing, scoring, and provider logic by ownership - Mirror application and provider structure in focused tests - Preserve search and indexer behavior with full regression coverage * refactor(metadata): separate provider ownership - Group Audible, Audnexus, extraction, and metadata workflows by feature - Move external provider, image cache, validation, and worker implementations into Infrastructure - Mirror metadata and image ownership in the test structure * refactor(notifications): isolate delivery runtime - Move webhook delivery and Discord process behavior into Infrastructure - Group notification contracts, payloads, diagnostics, and progress reporting by responsibility - Organize realtime hubs, broadcasting, clients, downloads, and logging by ownership * refactor(system): assign platform ownership - Group configuration, root folders, identity, outbound security, and redaction concerns - Replace generic platform and services buckets with system diagnostics and feature-owned implementations - Organize ffmpeg installation and metadata helpers with mirrored tests * refactor(api): group transport features - Move controllers and transport workflows into feature-owned API folders - Mirror controller tests under the same feature structure - Preserve routes, attributes, payloads, and workflow registrations * refactor(domain): consolidate feature contracts - Group domain models and pure rules by feature while preserving migration source - Move application ports and repositories into feature-owned contracts - Consolidate infrastructure composition under dependency injection ownership * refactor(filesystem): enforce application port - Route application file inspection and mutation through a filesystem contract - Move path metadata filesystem parsing into infrastructure - Add an architecture guard preventing direct application filesystem access * refactor(import): split planning collaborators - Extract destination idempotency and uniqueness planning from import orchestration - Isolate archive extraction lifecycle and quality comparison rules - Preserve import behavior with focused and integration regression tests * refactor(di): split feature registrations - assign service and worker registrations to feature-owned modules - retain compatibility composition surfaces for existing callers - guard HTTP client and module ownership with architecture tests * refactor(filesystem): purify domain rules - move mutation validation and cleanup into infrastructure - expose filesystem operations through the application port - guard domain code against direct filesystem access * refactor(api): isolate filesystem access - route API workflows through the filesystem application port - expose directory and root snapshots from infrastructure - restrict direct API filesystem access to test bootstrap * refactor(library): thin controller workflows - extract library query, path preview, and rename workflows - separate transport models from controller actions - retain existing routes and response behavior * refactor(backend): split large coordinators - separate mapping, parsing, notification, and storage concerns - extract scan discovery and moved-path collaborators - enforce focused source files and thin controller boundaries * style(backend): normalize source headers - remove trailing whitespace from reorganized source files * fix(startup): harden config file writes - Validate default config writes against the resolved content root - Add coverage for rejected and symlinked configuration paths * refactor: remove redundant assignments - Clean up unused manual import locals - Initialize search results only when parsed * refactor(backend): harden reliability boundaries - Standardize API failures, correlation, readiness, and metrics - Add explicit persistence boundaries and concurrency safeguards - Validate operational configuration and enforce architecture rules - Cover migrations, shutdown behavior, and Windows CI * optimization pass * test(mam): add request history support - Capture immutable HTTP request snapshots for redirect assertions - Add deterministic MyAnonamouse proof-route test support * test(nzbget): characterize XML-RPC routes - Lock existing XML-RPC methods, parameters, and response handling - Add method-aware NZBGet mock capture for compatibility tests * refactor(nzbget): add cancellation-aware RPC - Propagate cancellation through XML-RPC send and response reads - Preserve existing variadic wrapper behavior * mam regression tests * feat(nzbget): add typed history reader - Parse all visible NZBGet history into immutable entries - Centralize status, path, size, and time handling * fix(nzbget): merge history into polling - Match completed history to tracked downloads without changing list shape - Preserve active precedence, cancellation, and sanitized timing diagnostics * test(nzbget): enforce history guardrail - Measure parsing and merging for 1,000 visible history entries - Enforce latency and managed-allocation limits * fix(nzbget): append history to queue - Preserve active queue order and append terminal history entries - Apply category, deduplication, fallback, and cancellation contracts * fix(nzbget): append history to items - Add terminal history to normalized download-client items - Preserve active IDs, category policy, fallback, and cancellation * test(nzbget): verify history parity - Add cross-surface queue and item history parity coverage - Confirm category, identity, fallback, and cancellation behavior
[skip ci] Merge: Bump version to 1.1.0
…#648) * fix: profile-driven quality matching to stop the M4B re-grab loop Quality decisions previously ran through per-call-site string classifiers that emitted container labels such as "M4B". A container label never equals a codec/bitrate rung like "AAC 256kbps", so the cutoff was never met and the audiobook was re-grabbed on every automatic-search cycle. Introduce a single QualityMatcher (domain) that maps a file's codec/container/format/extension onto a profile's quality rungs, with round-down bitrate matching, explicit codec-mismatch reporting, lossless handling, and a lower-priority-number-is-better cutoff direction. Route the three quality call sites through it: - AudiobookQualityCutoffEvaluator: per-file/-download cutoff via QualityMatcher; exposes ResolveFileQualityLabel for the search evaluator. - AutomaticSearchQualityEvaluator: delegates cutoff to the shared evaluator and uses QualityMatcher.IsLabelBetter / ResolveFileQualityLabel (drops its own duplicate classifier). - AudiobookStatusEvaluator: delegates cutoff to QualityMatcher and forwards the file Path, so metadata-less path-only files (ffprobe unavailable / metadata off) resolve by extension instead of being dropped or mismatched. Tests: QualityMatcherTests covers round-down, the M4B regression, codec mismatch, lossless (incl. path-only), bitrate normalization, VBR/unknown bitrate, seed-style and bare-bitrate rungs, and the cutoff/label APIs. AudiobookStatusEvaluatorTests adds path-only FLAC and M4B regressions. * fix: make audiobook status the backend's job The frontend mirrored the backend quality-matching logic client-side, which duplicated business rules and could disagree with the server's automatic-search cutoff. The /library list endpoint already computes status server-side via AudiobookStatusEvaluator.ComputeStatus. computeAudiobookStatus now trusts the server-provided audiobook.status and only applies a client-side override for transient state the server snapshot can't see (an in-flight download). The duplicated profile/rung matching is removed; the two library views drop the now-unused qualityProfiles argument. Spec updated to assert the trust-server behaviour.
[skip ci] Merge: Bump version to 1.1.1
* fix(quality): ignore disabled rungs - Restrict quality matching and cutoff checks to allowed profile rungs - Add regressions for disabled matched, cutoff, and stored labels - Document the follow-up plan for disabled quality rung behavior * fix(quality): respect disabled bitrate rungs - Keep disabled rungs in bitrate boundary matching without treating them as allowed matches - Add regression coverage for disabled lower rungs below a cutoff
[skip ci] Merge: Bump version to 1.1.2
* Add region-aware Audible URLs and region support Introduce region-aware Audible/Amazon product URLs and search region handling across frontend and backend. Frontend: add region select UI, persist/derive preferred language from region, thread region through search results and metadata, use buildAudibleProductUrl util, and add region to Audible metadata types. Backend: normalize Audible/Amazon domains, build product links using region, treat Audible URLs/hosts robustly, and include locale headers for Audible API calls. Also propagate region into ASIN searches and metadata converters. Tests were updated/added to reflect region-specific behavior and URL generation. * Fix search default region fallback * Address regional search review feedback * Resolve search region and use market domain resolver Make SearchController's region parameter nullable and resolve it via ResolveSearchRegionAsync, then use the resolved region when building the Audible sourceUrl. Replace AudibleService's hardcoded region-to-URL switch with MarketDomainResolver.GetAudibleDomain and add the necessary using. Centralizes region/domain logic and ensures consistent Audible base URLs. * Cache default region; normalize images; add tests/docs Introduce caching and normalization for search results, add test builders and update docs. - SearchController / SettingsController: accept optional IMemoryCache, cache resolved default search region for 60s and remove cache when settings are saved. - Extract NormalizeMetadataSearchResultImagesAsync to centralize image normalization/caching (serve local /api images when possible) and replace duplicated code paths. - Frontend AddNewView: add region field to TitleSearchResult, extract normalizeResultRegionAndProductUrl helper, and add small test interaction (language select) in AddNewView.spec.ts. - Application: MarketDomainResolver now uses a single dictionary of markets; AsinSearchHandler signature allows nullable region. - Tests: add MetadataSearchResultBuilder and refactor SearchControllerUnifiedTests to use BaseTests/DI helpers; add new tests verifying default region fallbacks and regional sourceUrl behavior. - Docs: extend .github guidance files with pre-commit/pre-push rules, layering and async conventions, backend test conventions, and formatting quick-fix steps. These changes reduce duplication, improve regional URL handling, enable short-lived caching of default region, and add test helpers + docs to standardize test patterns. * Add test builders and search metadata fixes Introduce reusable test builders (AudibleBookResponse, AudibleSearchResponse, AudibleSearchResult, SeriesLookupItem) and extend ApplicationSettingsBuilder. Refactor Listenarr.Application.Search to centralize Audible->AudibleBookResponse mapping (ToAudibleBookResponse) and ensure Region is populated. Update Listenarr.Api.SearchController to determine metadata source base URLs (Amazon vs Audible), move image normalization into NormalizeMetadataSearchResultImagesAsync and add safe background caching with logged failures. Update many tests to use the new builders and add SearchService integration tests. Frontend: ensure Amazon product links include region and add a unit test for Amazon metadata badge. Update repository docs (.github) to clarify formatting, layering and backend test conventions. * Prefer user's defaultSearchLanguage on clear clearAdvancedSearch now checks applicationSettings.defaultSearchLanguage and uses it (after normalizePreferredSearchLanguage) when present; only if no saved default exists does it fall back to the region primary via getPrimaryPreferredSearchLanguageForRegion(searchLanguage.value). This mirrors the onMounted behavior and preserves existing reset logic for errors and paging. * fix(search): align rebased search flow - Forward language through advanced ASIN lookup - Keep search controller within architecture limits - Normalize rebased test builders for current defaults * style(test): remove redundant search import - Drop unused dependency injection import flagged by hooks * fix(search): align metadata result cards - Combine duplicate metadata and source links when they share a URL - Normalize Audible-backed simple and advanced result metadata - Preserve ASIN enrichment across metadata strategies
[skip ci] Merge: Bump version to 1.2.0
…rrs#649) The four catalog-cache read paths in AudiobookRepository ordered results by LastFetchedAt.GetValueOrDefault(UpdatedAt), which the SQLite EF Core provider cannot translate. The query threw at execution time and each caller's best-effort try/catch swallowed it as a cache miss, so the persisted author/series catalog cache never returned a hit — every author and series page re-fetched the full catalog from Audible on each load. Use null-coalescing (entry.LastFetchedAt ?? entry.UpdatedAt), which maps to SQL COALESCE with identical freshest-first ordering but is translatable. Add regression coverage that exercises these reads against the real SQLite provider; the EF InMemory provider tolerates the untranslatable LINQ and so could not catch this. Co-authored-by: Kevin Heneveld <1192102+kevinheneveld@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
[skip ci] Merge: Bump version to 1.2.1
* [enh] Harmonize queue updates on download clients * [enh] Harmonized adapter queue updates * [enh] Allows adapters to handle multiple protocols * [fix] Cleaned warning on build * fix(downloads): align adapters after rebase - Preserve ID-filtered queue polling in the reorganized adapter layout - Restore adapter contract compatibility for hash retrieval and tests * Align download queue reconciliation * Handle unlinked client downloads * Align orphan cleanup tests with DI * Fix SABnzbd queue path handling * Fix NZBGet history-driven import state * Extract NZBGet connection testing * Fix NZBGet failed history handling * Refine download client queue monitoring * Harden download monitor polling * Slice download client adapters into workflows * Hide untracked external activity items * Harden activity visibility filtering * Move download client workflow composition to DI * Remove NZBGet drone identity fallback * Harden deferred download cleanup retention * Add extensible direct-download processing * Harden direct download handling * Remove DDL staging path from info log --------- Co-authored-by: Robbie Davis <robbie@therobbiedavis.com>
[skip ci] Merge: Bump version to 1.2.2
…enarrs#717) * feat(filesystem): add pinned relative hierarchy cursor * fix(filesystem): bind Windows handle duplication entry point * fix(filesystem): walk owned hierarchy from pinned boundary * fix(filesystem): dispose rejected hierarchy anchors * test(filesystem): preserve linked managed boundaries * testability(filesystem): expose nested staging barrier * fix(filesystem): restore FileMover after hook extraction * testability(filesystem): expose nested staging barrier * chore(ci): prepare directory copy staging hook * chore(ci): trigger directory copy hook patch * chore(ci): remove unused directory copy hook workflow * test(filesystem): reproduce nested staging link replacement * chore(ci): prepare pinned directory copy patch * chore(ci): trigger pinned directory copy patch * chore(ci): trigger pinned copy patch from PR sync * chore(ci): apply reviewed pinned directory copy patch * chore(ci): restore standard validation workflow * chore(ci): add temporary pinned copy patch script * chore(ci): run temporary pinned copy patch * fix(filesystem): populate directory copy staging through pinned handles * chore(ci): remove temporary pinned copy patch tooling * testability(filesystem): expose directory publication barrier * test(filesystem): reproduce staging root replacement before publication * chore(ci): add temporary publication hardening script * chore(ci): run temporary publication hardening patch * fix(filesystem): verify pinned identity across directory publication * chore(ci): remove temporary publication patch tooling * chore(ci): capture format and Windows test diagnostics * chore(ci): remove temporary diagnostic jobs * chore(ci): add temporary marker handle fix script * chore(ci): apply marker handle mode fix * fix(filesystem): use synchronous marker file handles * chore(ci): remove temporary marker patch tooling * test(filesystem): use shared test fixture for tracked path index * test(rootfolders): use shared fixture for active move boundaries * test: use shared fixture for tracked path repository tests * chore: stage exact filesystem source splits * chore: apply reviewed filesystem source splits * refactor(filesystem): split focused native and copy helpers * chore: remove filesystem split automation * chore: stage explicit tracked path semantics * chore: apply explicit tracked path semantics * fix(paths): require explicit tracked path semantics * chore: remove tracked path patch automation * chore: apply reviewed backend formatting * style: apply backend formatter * chore: restore standard validation workflow * chore: capture merge formatting and Windows build diagnostics * chore: remove temporary build diagnostics * fix(build): import filesystem path semantics contract * chore: capture remaining Linux compile diagnostics * chore: remove temporary Linux build diagnostics * chore: stage explicit tracked path test call * chore: apply explicit tracked path test call * test(paths): pass explicit tracked path semantics * chore: remove explicit tracked path test automation * chore: capture cross-platform backend test diagnostics * chore: remove temporary cross-platform test diagnostics * test(filesystem): add empty destination quarantine barrier * chore: stage empty destination fallback regressions * chore: apply reviewed empty destination regressions * test(filesystem): lock empty destination handoff contract * chore: remove empty destination regression automation * feat(filesystem): expose no-follow pinned directory anchor * feat(filesystem): prepare verified empty destination placeholders * fix(filesystem): retry empty placeholder restoration * chore: stage empty destination handoff integration * chore: apply reviewed empty destination handoff * fix(filesystem): safely hand off empty move destinations * chore: remove empty destination handoff automation * chore: stage normalized directory robocopy destination * chore: apply reviewed robocopy destination normalization * fix(filesystem): use normalized directory robocopy target * chore: remove robocopy normalization automation * chore: add temporary backend test diagnostics * chore: remove backend diagnostic workflow * chore: stage exact file-move source split * chore: add one-shot file-move split workflow * refactor(filesystem): split file move workflow * chore: remove file-move split workflow * chore: remove file-move split script * chore: stage robocopy fallback test corrections * chore: add one-shot robocopy test workflow * test(filesystem): align robocopy fallback with exact destination contract * chore: remove robocopy test workflow * chore: remove robocopy test script * chore: stage empty destination contract regression * chore: add one-shot empty destination test workflow * test(filesystem): reject unowned empty move destinations * chore: remove empty destination test workflow * chore: remove empty destination test script * chore: stage removal of unowned destination quarantine * chore: add one-shot empty destination production workflow * fix(filesystem): reject unowned empty move destinations * chore: remove empty destination production workflow * chore: remove empty destination production script * chore: add temporary targeted FileMover diagnostics * chore: remove targeted FileMover diagnostics * chore: stage deterministic directory move test hook * chore: add one-shot directory move hook workflow * test(filesystem): add deterministic direct-move barrier * chore: remove directory move hook workflow * chore: remove directory move hook script * chore: stage deterministic robocopy fallback test * chore: add one-shot robocopy hook test workflow * test(filesystem): force verified robocopy fallback deterministically * chore: remove robocopy hook test workflow * chore: remove robocopy hook test script * test(filesystem): lock hardlink alias behavior * fix(filesystem): add regular file identity support * fix(filesystem): classify hardlink aliases by file identity * fix(filesystem): fail closed to object identity for linked aliases * chore: stage file alias classifier wiring * chore: add one-shot file alias classifier workflow * fix(filesystem): apply regular-file alias checks * chore: remove file alias classifier workflow * chore: remove file alias classifier script * chore: add temporary hardlink build diagnostics * test(filesystem): create hardlink aliases with native APIs * chore: remove hardlink build diagnostics * test(filesystem): reject linked destination ancestor during fallback * chore: stage linked directory-copy parent rejection * chore: add one-shot linked directory-copy parent workflow * fix(filesystem): reject linked directory-copy parent chains * chore: remove linked directory-copy parent workflow * chore: remove linked directory-copy parent script * test(filesystem): lock destination parent open race * test(filesystem): probe symlink support for parent-open race * chore: stage pinned directory-copy parent fix * chore: add one-shot pinned directory-copy parent workflow * fix(filesystem): pin directory-copy destination parent * chore: remove pinned directory-copy parent workflow * chore: remove pinned directory-copy parent script * test(filesystem): add file shortcut race barrier * test(filesystem): lock hardlink shortcut race * test(library): require backend-owned bulk physical moves * fix(library): orchestrate bulk physical moves in backend * fix(filesystem): import file action for test hook * fix(filesystem): revalidate aliases before content shortcut * test(move): block temp parent replacement race * fix(move): pin temporary ownership publication * test(move): require pinned quarantine creation * fix(move): pin quarantine ownership publication * test(move): add scaffold publication barrier * test(move): lock scaffold parent replacement races * fix(move): pin target scaffold publication * test(move): lock nested quarantine publication race * fix(move): pin source quarantine publication * test(move): lock quarantine removal race * fix(move): pin quarantine file removal * test(move): lock temp publication parent race * fix(move): pin final temp publication * test(move): lock copy destination parent race * fix(move): pin copy and source cleanup files * test(move): lock direct copy root race * fix(move): pin direct copy destination root * test(move): lock atomic publication race * fix(move): pin atomic directory publication * fix(move): preserve atomic marker recovery across platforms * fix(filesystem): harden pinned move recovery - Bind move publication, cleanup, and audiobook deletion to verified filesystem objects - Preserve replacement generations and durable ownership evidence during recovery - Add deterministic race and interrupted-state coverage * fix(library): harden filesystem ownership - Bind destructive filesystem operations to durable object identities - Make move recovery generation-safe and cancellation-safe - Add migration and adversarial regression coverage * fix(move): harden relocation and recovery protocols * fix(move): repair filesystem mutation contracts * fix(move): harden publication and ownership contracts * fix(filesystem): probe pinned linked boundaries * fix(filesystem): separate alias probing from mutation safety * fix(filesystem): avoid alias marker share violation * test(architecture): cover link-specific evidence * fix(code-quality): clarify nullable contracts * test(code-quality): narrow nullable evidence * test(code-quality): assert non-null results once * test(code-quality): narrow move retry values * test(code-quality): narrow move handoff values * test(code-quality): enforce non-null test contracts * test(code-quality): narrow scan worker values * test(architecture): recognize custom xunit attributes * test(ci): require native link capabilities * test(ci): enforce exact link capabilities * test: isolate generated entity identities * fix: enforce request cancellation mutation fence * test: harden cancellation boundary gate * fix(persistence): harden ownership migration recovery * fix(persistence): preserve legacy ownership recovery evidence * fix(persistence): harden migration and cross-host identity * fix(persistence): restore migration scaffolding provenance * fix(filesystem): reject foreign root identity syntax * Harden persisted path and move recovery contracts * Harden durable filesystem mutation recovery * Fix native recovery and migration provenance * Repair root storage identity authorization * Harden markerless move and recovery workflows * Fix native markerless ownership regressions * Strengthen Linux directory generation identity * Harden move recovery and markerless cleanup * Fix application-owned file move lock storage * Harden case-sensitive filesystem boundaries * Preserve case in directory rename recovery * Preserve exact filesystem recovery identities * chore(ci): add temporary PR 717 cleanup analysis * chore(ci): execute compatibility policy cleanup * chore(ci): fix cleanup executor syntax * docs: define target-branch compatibility boundary * chore(ci): execute legacy relocation cleanup * chore(ci): retry legacy relocation cleanup * chore(ci): add temporary PR cleanup script * chore(ci): use checked-in cleanup executor * chore(ci): trigger PR 717 cleanup executor * chore(ci): extend relocation cleanup gate * chore(ci): add relocation cleanup test scrub * chore(ci): make relocation test cleanup exact * refactor(relocation): remove intermediate target reauthorization * chore(ci): inventory obsolete root enrollment compatibility * chore(ci): trigger root enrollment inventory * chore(ci): add root enrollment compatibility cleanup * chore(ci): execute root enrollment compatibility cleanup * chore(ci): trigger root enrollment cleanup * chore(ci): exempt root enrollment negative gate * chore(ci): rerun root enrollment cleanup * chore(ci): fix root enrollment adversarial diagnostics * chore(ci): rerun root enrollment final gate * refactor(identity): remove intermediate root enrollment compatibility * chore(ci): inventory ownership compatibility * chore(ci): trigger ownership compatibility inventory * chore(ci): add ownership compatibility cleanup * chore(ci): execute ownership compatibility cleanup * chore(ci): trigger ownership compatibility cleanup * chore(ci): fix ownership cleanup transformer * chore(ci): rerun ownership compatibility cleanup * chore(ci): add ownership cleanup runner * chore(ci): add ownership cleanup gate * chore(ci): trigger gated ownership cleanup * chore(ci): remove markerless replacement legacy evidence fallback * chore(ci): rerun ownership cleanup after adversarial finding * chore(ci): fix ownership reconciler timestamp after legacy removal * chore(ci): rerun ownership cleanup after build finding * chore(ci): fix Step 5 convergence patch * Harden markerless library move contracts * fix: harden root storage authorization * fix: finalize durable markerless move contracts * fix: remove library-side scratch namespace protocol * docs: align filesystem architecture with unix contracts * test: align unix filesystem recovery coverage * fix: make rename and deletion recovery crash-safe * fix: preserve Unix path separators in library dialogs * fix: revalidate rename recovery owner binding * chore: consolidate filesystem recovery migrations * fix: clarify root folder path change conflicts * fix: allow unavailable root path repair * fix: allow cross-syntax root path repair * fix: harden root metadata repair recovery --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
[skip ci] Merge: Bump version to 1.3.0
Author
|
Wrong base branch, reopened against canary as #825. |
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.
Automatic search builds one query from the title plus the author, and gives up if it comes back empty. Audible titles often carry a suffix like
(Part 1 of 2)or(Dramatized Adaptation), and the author usually does not appear in release names, so that combined query matches nothing at the indexers.Refs #801.