Open
Conversation
Backend: Inject IFileMover into ManualImportController and use it to perform hardlink operations for "hardlink/copy" input mode (with fallback to copy for companion files). Update ManualImportRequest comment to include the new mode and adjust tests to provide a mock IFileMover. Frontend: Add responsive CSS for top navigation and refine mobile behaviors across AddNewView and App (pagination controls, results scrolling, layout/spacing, and button sizing). Update AddNewView to conditionally render title results controls via hasTitleResultControls and improve client-side pagination layout. Other: Default library import inputMode logic simplified to choose 'move' for Move or unset, otherwise 'hardlink/copy'. Tests updated to account for the new dependency.
Add a Changelog maintenance section to .github/CLAUDE.md with guidance on when and how to update CHANGELOG.md (unpublished vs published branches, entry format, and rules for entries). Also update CHANGELOG.md with a new 0.2.62 release containing two fixes: preserve hardlink behavior in ManualImportController by injecting IFileMover and adding the missing hardlink branch in ImportFileAsync/ImportCompanionFilesAsync; and correct Library Import view mapping so non-Move settings map to "hardlink/copy" (falling back to plain copy when hardlinking is not possible).
CallXmlRpcAsync now builds the /xmlrpc URI and sends an HttpRequestMessage with an explicit Authorization header (via BuildAuthHeader) instead of embedding credentials in the URL. This prevents HttpClient from silently stripping userinfo and ensures Basic auth is sent. The old BuildBaseUrl helper was removed. CHANGELOG updated and package versions bumped to 0.2.60 for root and frontend.
Multiple fixes to address MyAnonamouse (MAM) torrent failures, indexer redaction issues, and duplicate-download blocking. Key changes: - DownloadController: return 409 Conflict when a duplicate active download blocks creation. - DownloadService: duplicate detection now excludes Completed and only considers enabled download clients; added authenticated retry logic for MAM torrent fetches (disable auto-redirect and reapply cookies) and safer handling/logging of response content and filenames. - QbittorrentAdapter: improved post-add detection of the torrent hash (non-blocking loop), and fallback to inject tracker URLs via the addTrackers API using announce URLs extracted from the torrent file. - ApiResponseRedactor: switch to per-field JSON redaction for AdditionalSettings and add MergeAdditionalSettings to preserve real secrets when incoming payloads contain "REDACTED" placeholders; helper to redact sensitive keys preserved structure. - MyAnonamouseHelper: fixed bencode parsing/stream consumption bugs to avoid desynchronization when extracting announce URLs. - Tests: updated expectation to normalize stored path using Path.GetFullPath (platform-dependent). - CHANGELOG updated to document the fixes (MAM tracker URL, lost MAM ID, phantom duplicate check). These changes resolve stalled MAM downloads (missing trackers / dropped auth), prevent accidental erasure of sensitive indexer fields on save, and stop invisible stale client records from permanently blocking re-downloads.
Add a set of new languages and ISO/alias mappings to the frontend language options and normalization logic (Arabic, Chinese, Czech, Danish, Dutch, Finnish, Greek, Hindi, Japanese, Korean, Norwegian, Portuguese, Spanish, Swedish, Turkish). Update normalizePreferredSearchLanguage/normalizeSearchResultLanguage behavior and unit tests to cover the new aliases and fallbacks (e.g. region codes like `br` -> portuguese, `jp` -> japanese), and add tests for unsupported values. Also update CHANGELOG to document the expanded language filter support and MAM parser recognition.
Adds Hebrew to the frontend language options and normalizations, and extends the MyAnonamouse provider with many additional ISO 639 mappings. Implements diacritic-insensitive search and matching: introduces RemoveDiacritics and HasDiacritics, retries Audible queries with diacritics stripped when needed, and switches title/author/series comparisons to CultureInfo.CompareInfo with IgnoreNonSpace to avoid filtering accented metadata. Fixes Advanced Search when only a series name is provided by using the series as a TITLE token. Adds unit tests for RemoveDiacritics and updates the changelog.
Fix series-only/series-by-name advanced searches and make Audible series results consistent with unified search paths. Changes include: resolve series ASINs by casting to SeriesLookupItem and preferring region-matching entries (with first-item fallback); guard against passing raw series names as ASINs; fetch books by series ASIN and map AudibleSearchResult items to the same Audible-shaped output via a new MapAudibleSearchResultToOutputAsync converter; apply post-fetch language filtering while treating null/empty language as acceptable; change direct product search to use "keywords" param; add diagnostic logging around series lookups and fetches; keep unfiltered results as a fallback when series metadata is missing; and remove an exposed metadataSource field from the metadata mapper. Tests updated to the new SeriesLookupItem shape and to cover region fallback, null-language preservation, series-only flows, and series filtering behavior. Also update CHANGELOG entry to reflect the broader set of fixes and behaviors.
Introduce docker-entrypoint.sh to handle PUID/PGID/UMASK, chown the config dir and drop privileges via gosu. Install gosu in both Docker runtime files, ensure /app/config/database exists, copy and chmod the entrypoint, and replace direct dotnet ENTRYPOINTs with the script. Update docker-compose to expose PUID/PGID/UMASK environment variables (remove hardcoded user) so the container can run with custom UID/GID and correct permissions.
Add login and image publishing to atcr.io across canary, nightly, and release workflows: add docker/login-action for ATCR, expose ATCR_IMAGE outputs, and include ATCR image tags when pushing. Also replace the generic DISCORD_DOCKER_UPDATE_URL webhook secret with LISTENARR_DISCORD_WEBHOOK_URL for Discord notifications. Updated files: .github/workflows/canary.yml, nightly.yml, release.yml.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d63fc7462b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Frontend: extend Audible metadata mapping to include language, subtitle, description and lengthMinutes (plus alternate-cased keys) and map them into search results so ASIN lookups no longer get dropped by language/metadata filters. Backend: prefer TorrentHash, then ClientDownloadId when resolving client-side IDs for post-download removal; add SABnzbd handling to use ClientDownloadId (nzo_id) for removal requests. Changelog: document ASIN and SABnzbd fixes. Also remove unused config/appsettings/appsettings.json.
Multiple small fixes across the project: - docker-entrypoint.sh: default PGID to PUID when not set and skip groupmod/addgroup when PGID is 0 (root) to avoid unnecessary/root group changes in root containers. - ApiResponseRedactor.cs: replace manual property loop with LINQ Any for a concise quick-scan, and broaden the sensitive-key check from exact "mam_id" to contains "mam" for more robust matching. - AudibleService.cs: remove unused totalRawProducts local variable. - DownloadService.cs: ensure HttpRequestMessage is disposed by using 'using var' for retry requests to prevent resource leaks.
Fetch completed items from SABnzbd history and append them to the active queue results so completed downloads can be discovered for import/removal. Adds a history API request (mode=history), parses history slots into QueueItem entries (nzo_id, name, category, bytes, completed timestamp), maps statuses, filters by configured category, translates remote paths via the path mapping service, and updates logging. Non-fatal parsing/fetch errors are caught and logged at debug level.
Introduce a normalized QueueSnapshot model and helpers (normalizeQueueSnapshot, createEmptyQueueSnapshot) and add QueueSnapshot/QueueClientStatus types. Update api.getQueue and SignalR handling to accept/emit a normalized snapshot (handles old array payloads too). Rework downloads store to track queue-only IDs and reconcile DB downloads with incoming queue snapshots to avoid stale duplicates/removals. Revamp ActivityView: search/filter input, grid layout, snapshot health banner, virtual scroll tuning, status label mapping, and prefer queue snapshot entries over external DB downloads when IDs conflict. Add unit tests for downloads store reconciliation and ActivityView snapshot behaviours.
Add AudiobookId propagation from DB to API and frontend queue items, enabling linked titles in the Activity and Wanted views (router links, resolved via library store) and small UI tweaks (grid height, link styles). Backend model and repo updates: Download and QueueTrackedDownload now include AudiobookId and EfDownloadRepository maps it. DownloadQueueService/DownloadService now carry AudiobookId into queue items and avoid rewriting tracker hosts; announce URLs are logged for diagnostics. Torrent/tracker handling improved: MyAnonamouseHelper gains a skip-scanner and only captures/uses real tracker announce URLs (skips url-list/web-seeds and limits regex fallback), QbittorrentAdapter filters to tracker announces before injecting, and mam_id appending is skipped for non-tracker URLs to avoid corrupting web-seeds.
Use download-client reported source file lists to reliably scope automatic imports and directory batch processing. Adds a SourceFiles property to tracked downloads and populates/translates it in qBittorrent and Transmission adapters (including path mapping and per-file translation). Completed-download processing and the background move/copy job now filter directory imports to only the files reported by the client, avoid finalizing multiple times, and select a primary imported path preferring audio files. Non-audio files are refused by ImportService and skipped by AudioFileService; MetadataRescanService removes non-audio AudiobookFile entries. FileUtils gains helpers for identifying companion files and common companion stem keys. Also propagate Language metadata from search results and DB lookups, and include language in queue enrichment. Tests added/updated to cover adapters, audio-file checks, completed-download behaviors, and directory move/copy finalization.
Add .tmp and obj2 patterns to DefaultItemExcludes (Directory.Build.props and Listenarr.Domain.csproj) to prevent temporary/extra folders from being treated as project items. In Listenarr.Domain.csproj disable automatic compile item inclusion (EnableDefaultCompileItems=false) and explicitly include Models/**/*.cs so only intended source files are compiled.
Add structured-field normalization for advanced searches and improve Audible title search behavior. Implements NormalizeStructuredAdvancedField in SearchController to strip AUTHOR:/TITLE:/ISBN:/ASIN: prefixes (returning null for empty stripped values) and applies it to advanced search requests. Update AudibleService.SearchByTitleAsync to trim input, return an empty response for blank titles, prefer a keyword/catalog search first then fall back to a title-field search if no results, and log the retry; also reuse SearchByTitleAsync from SearchByTitleAndAuthor when author is blank. Add unit tests covering the Audible title search flow and advanced search normalization.
Capture _hubContext.Clients.All into a local clientProxy and use it for SendAsync/SendCoreAsync in DownloadService and SignalRHubBroadcaster to simplify null checks and ensure consistent calls. Update tests: replace Path.Combine with Path.Join for temp file paths; make cleanup catch blocks explicit (catch Exception) with best-effort comments; use tolerant floating-point assertions (Math.Abs) for metrics verifications; and supply a real HttpClient instance when mocking AudibleService. Small robustness and compatibility improvements across services and tests.
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.
This PR aims to close some of the longer standing bugs and/or feature requests such as PUID/PGID support for example. See the full changes below:
Added
Add Newlanguage filters with support for Swedish, Norwegian, Danish, Finnish, Dutch, Portuguese, Japanese, Chinese, Czech, Turkish, Hindi, Korean, Arabic, Greek, and Hebrew. (Closes Add Swedish as a language selector for searching for new audiobooks #432, Closes [Feature Request] Support Multi-language product and indexer searching #205)PUID,PGID, andUMASKsupport so containers can run as a custom user/group, with automatic ownership correction for existing config files. (Closes Docker image cannot run as non-root user - documentation examples don't work #309)atcr.ioas a published container registry alongside Docker Hub and GHCR for nightly, canary, and release workflows. (Closes [Feature Request] atcr.io container registry #268)Fixed
Add Newview returning zero results by restoring missing metadata fields needed for language-filtered results. (Closes unable to search for ASIN #434)hardlink/copymode now correctly hardlinks primary and companion files when possible.move.409 Conflictwhen a download is skipped.RemoveandRemove and Deletenow use the correctnzo_idinstead of Listenarr’s internal GUID, allowing history cleanup and source-directory removal to work properly. (Closes [Bug] Remove and Delete Completed Download Action not Working as Expected in Sabnzbd #300)