From fc366184b2334d0b5d6e614031b768ed0ad0f9f3 Mon Sep 17 00:00:00 2001 From: Broque Thomas <26755000+Nezreka@users.noreply.github.com> Date: Wed, 13 May 2026 13:50:51 -0700 Subject: [PATCH] Raise discography limit from 50 to 200 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Discord report: prolific artists (Bach, Beatles complete box, deep dance/electronic catalogues) only showed ~50 entries in the "Download Discography" modal. `MetadataLookupOptions(limit=50, max_pages=0)` was hardcoded at three call sites. Spotify's `max_pages=0` already paginates through everything (per-page is clamped to 10 internally), so Spotify-primary users were unaffected. But Deezer / iTunes / Discogs / Hydrabase all honor the outer `limit` as a hard cap, so non-Spotify users were silently clipped. Bump `limit` to 200 at all three call sites — matches iTunes's and Discogs's own internal caps and covers near-everyone's full catalogue. Spotify behavior unchanged. - web_server.py:9221 — discography endpoint (modal) - web_server.py:8700 — artist-detail discography view - core/artist_source_detail.py:129 — source-specific artist detail --- core/artist_source_detail.py | 6 +++++- web_server.py | 20 ++++++++++++++++++-- webui/static/helper.js | 1 + 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/core/artist_source_detail.py b/core/artist_source_detail.py index 8cf11fbf..c376052e 100644 --- a/core/artist_source_detail.py +++ b/core/artist_source_detail.py @@ -126,7 +126,11 @@ def build_source_only_artist_detail( allow_fallback=True, skip_cache=False, max_pages=0, - limit=50, + # Match the Download Discography endpoint cap (200). + # Spotify already paginates all; Deezer / iTunes / Discogs / + # Hydrabase clamp at the outer limit. 200 covers prolific + # catalogues without exceeding iTunes/Discogs internal caps. + limit=200, artist_source_ids={source: artist_id}, dedup_variants=False, ), diff --git a/web_server.py b/web_server.py index 8283c224..354c7ca9 100644 --- a/web_server.py +++ b/web_server.py @@ -8697,7 +8697,13 @@ def get_artist_detail(artist_id): allow_fallback=True, skip_cache=False, max_pages=0, - limit=50, + # Match the Download Discography endpoint cap (200) + # so the artist detail view sees the same release + # set the modal lists. Spotify already paginates + # all; Deezer/iTunes/Discogs/Hydrabase respect the + # outer limit. 200 matches iTunes/Discogs internal + # caps and covers prolific catalogues. + limit=200, artist_source_ids=artist_source_ids, ), ) @@ -9218,7 +9224,17 @@ def get_artist_discography(artist_id): allow_fallback=True, skip_cache=False, max_pages=0, - limit=50, + # Discord report: prolific artists (Bach, Beatles + # complete box, deep dance/electronic catalogues) + # showed only ~50 entries in the Download Discography + # modal. Spotify's `max_pages=0` already paginates + # through everything (per-page is clamped to 10 + # internally), but Deezer / iTunes / Discogs / + # Hydrabase all honor the outer `limit` as a hard + # cap. 200 lines up with iTunes's and Discogs's own + # internal caps and covers near-everyone's full + # catalogue. + limit=200, artist_source_ids=artist_source_ids or None, ), ) diff --git a/webui/static/helper.js b/webui/static/helper.js index 7384c970..dd3d24a6 100644 --- a/webui/static/helper.js +++ b/webui/static/helper.js @@ -3416,6 +3416,7 @@ const WHATS_NEW = { '2.5.2': [ // --- May 13, 2026 — 2.5.2 release --- { date: 'May 13, 2026 — 2.5.2 release' }, + { title: 'Download Discography: No Longer Caps Prolific Artists At 50 Releases', desc: 'discord report: clicking "download discography" on an artist with a deep catalogue (bach, beatles complete box, dance / electronic artists with hundreds of remixes) only showed ~50 albums in the modal. trace: `MetadataLookupOptions(limit=50, max_pages=0)` was hardcoded at the discography endpoint and the artist-detail discography view. spotify\'s `max_pages=0` already paginates through everything (per-page is clamped to 10 internally) so spotify-primary users were unaffected. but deezer / itunes / discogs / hydrabase all honor the outer `limit` as a hard cap. fix: bump `limit` from 50 to 200 at all three call sites (`web_server.py` discography endpoint + artist-detail view + `core/artist_source_detail.py`). 200 matches iTunes\'s and Discogs\'s own internal caps and covers near-everyone\'s full catalogue. spotify behavior unchanged.', page: 'library' }, { title: 'Artist Page: "Write Artist Image" Button (Real Artist Photos For Navidrome)', desc: 'github issue #572 (rhwc): navidrome shows album-art-derived thumbnails as artist photos because navidrome has no api for setting an artist image — it only reads `artist.jpg` from the artist folder during library scans. soulsync\'s `update_artist_poster` for navidrome was a no-op. new button on the artist detail page header writes `artist.jpg` to the artist\'s folder on disk: looks up any album track, resolves it through the path resolver (handles docker mount translation like #558 settled on), goes up one level to the artist folder, fetches the artist photo from the configured metadata source priority chain (spotify primary, fallback to deezer / discogs / etc), downloads with content-type validation + atomic write via `.tmp + os.replace`. when active server is navidrome, triggers a library scan immediately so the new file gets indexed. respects existing `artist.jpg` files (asks before overwriting) so user-supplied photos aren\'t clobbered. works for plex / jellyfin too as a fallback layer — both servers also read `artist.jpg` from disk. 26 tests pin the pure helpers in `core/library/artist_image.py`: folder derivation (trailing slash / backslash / empty / non-string), image url picking (missing attr / whitespace strip / non-string), download (non-image content-type / 404 / timeout / empty body), and write (atomic replace / temp-cleanup-on-failure / overwrite guard / missing folder).', page: 'library' }, { title: 'Library History: Per-Download Audit Trail Modal', desc: 'each download row in library history now has an "audit" button that opens a second modal visualizing the download lifecycle as a vertical chain of decision blocks: request → source selected → source match → verification → post processing → final placement. each step has a status (complete / partial / unknown / error) with a color-coded node, plus a card showing what was decided and the supporting metadata. post-processing step infers observable changes from source-vs-final state (format conversion, file rename via tag template, title/artist rewrite, folder template). new "embedded tags" section below the flow reads the audio file live via mutagen at audit-open time and surfaces every tag actually on the file — title / artist / album / album artist / date / genre / track # / disc # / bpm / mood / style / copyright / publisher / release type+status+country / barcode / catalog # / asin / isrc / replaygain values / cover-art status / lyrics / every source id (spotify, tidal, deezer, musicbrainz, audiodb, lastfm, genius, itunes, beatport ...). file is the single source of truth — a persisted snapshot would drift the moment a background enrichment worker writes more tags. clean fallback when file is missing or unreadable. 19 tests pin the pure mutagen reader: id3 path (TIT2/TPE1/TALB + TXXX user-defined frames + USLT + APIC cover-art), vorbis path (FLAC dict-style + pass-through for unknown _id / _url keys), mp4 stub, format+bitrate+duration metadata, defensive paths (empty path, missing file, mutagen returns None, mutagen raises), stringify edge cases (list / tuple / int / frame-with-text / whitespace). files: core/library/file_tags.py (new mutagen reader), web_server.py (new GET /api/library/history//file-tags endpoint), webui/index.html (audit-overlay modal), webui/static/wishlist-tools.js (renderer + async fetch + tag-grid render), webui/static/style.css (flow + tags section + lyrics block styles).', page: 'wishlist' }, { title: '$albumtype Folder Template Now Splits EPs / Singles For Non-Spotify Sources', desc: 'discord report (cal): downloading an artist\'s discography with `$albumtype` in the path template put every release under `Album/` regardless of actual type — eps, singles, all dumped into the album folder. trace: the legacy duck-typed album-info builder at `core/metadata/album_tracks.py:_build_album_info_legacy` only checked the `album_type` key. spotify uses `album_type` (lowercase) so spotify discographies worked. but deezer\'s api uses `record_type`, tidal uses `type` (uppercase ALBUM/EP/SINGLE), and some flattened musicbrainz shapes use `primary-type` — none of those matched, all defaulted to `album`. fix: widen the legacy lookup to check `album_type` / `record_type` / `type` / `primary-type` and route the value through a new pure `_normalize_album_type` helper that lowercases + validates against the canonical token set (`album` / `single` / `ep` / `compilation`) and falls back to `album` for unknowns. typed-converter path for spotify / deezer / itunes / discogs / musicbrainz / hydrabase / qobuz unchanged — they were already correct. tidal users were the main offender (no typed converter for dict-shaped tidal data). 25 new tests pin: case-insensitive normalization for each canonical type, compilation preserved (spotify supports it), unknown values default to album, defensive against none / empty / non-string inputs, multi-key precedence (`album_type` wins over `record_type`), each known source shape produces correct token, generic `type=track` / `type=artist` collision case defaults to album rather than poisoning the path.', page: 'tools' },