Skip to content

Artist Watch: a catalogue of the artist's releases, with a switch per release - #589

Open
BigBrownMF69 wants to merge 2 commits into
henriquesebastiao:mainfrom
BigBrownMF69:feat/artist-watch-catalogue
Open

BigBrownMF69 wants to merge 2 commits into
henriquesebastiao:mainfrom
BigBrownMF69:feat/artist-watch-catalogue

Conversation

@BigBrownMF69

Copy link
Copy Markdown
Contributor

Phase 2 of #581, second part: an artist watch's releases, with a switch per release. This is the "have / missing" catalogue view and Lidarr-style per-album monitoring from the proposal.

Stacked on #588 (MusicBrainz catalogue), so it includes that PR's commit. This PR's own change is the second commit, dc1bdec. Please review #588 first.

What it does

Top of the panel Switched on / off Mixtapes, MusicBrainz-only

(A local test instance in Docker: a real Drake watch, added with "new releases only" and then paused, so nothing was downloaded.)

The listing.

  • Each artist sweep keeps what its catalogues listed in a new table, artist_catalogue, in the monitor db (downtify/artist_catalogue.py). The record is upserted, so what was learnt along the way is kept:
    • a release's track count, once its tracklist was fetched;
    • whether it turned out to be a guest spot or bootleg (_release_tracks returned None);
    • the user's choice.
  • A retarget clears it with the rest of the watch's history.

The panel, on the watch's page (WatchView, artist watches only):

  • One row per release. The same name and type from two catalogues is merged, folding (feat. …) and remaster tags like PR 579's song key. Laugh Now Cry Later (feat. Lil Durk) on YouTube Music is Deezer's Laugh Now Cry Later.
  • Sections: albums, mixtapes, EPs, singles, and live, compilation and remix releases, newest first.
  • Each row shows its year, catalogues and state:
    • Complete n/n
    • Partly n/n
    • To download
    • Out before the watch (skipped by a "new releases only" baseline)
    • Not watched (a type or MusicBrainz kind the watch doesn't download)
    • Off
    • Guest spot or bootleg (own filter, no switch)
  • Counts come from artist_release_tracks, so no disk access.
  • Filter chips by state.

The switch (PATCH /api/monitor/playlists/{id}/releases {album_ids, choice}) overrides the watch for that release:

  • On downloads it whatever the watch's release_types or "new releases only" say. Its baseline skip is dropped, and a check starts if the watch is enabled.
  • Off never downloads it. Songs already there stay.
  • '' follows the watch again.
  • check_artist picks releases through artist_catalogue.wanted(album, types, kinds, choices) instead of the type check alone.

Release kinds per watch:

  • MusicBrainz now lists groups of every kind, so the panel can show them. Which kinds download is decided per watch by a new column, musicbrainz_kinds. NULL follows the artist_watch_musicbrainz_kinds setting.
  • The panel's chips set it: Mixtapes, Soundtracks, Live albums, Compilations, Remixes, DJ mixes, Demos. PATCH /api/monitor/playlists/{id} takes musicbrainz_kinds. This is the UI Read Artist Watch discographies from MusicBrainz too #588 left out.
  • A guest spot switched on is still not downloaded, because its tracklist check still says it isn't the artist's.

Real data

Drake, YouTube Music + Deezer + MusicBrainz, after the first check: 160 releases, of which 73 only MusicBrainz knows (mostly singles, plus his early mixtapes). Every catalogue's entry for the same release merged into one row. The listing cost the check nothing extra; it is the same discography the sweep already reads.

Tests

  • tests/test_artist_catalogue.py, 14 tests:
    • the store keeps track count, guest flag and choice across listings, and is cleared on retarget;
    • the page after a real sweep: merging across catalogues, complete counts, not-watched singles and live albums;
    • switching on downloads a single the watch doesn't watch;
    • a guest spot switched on is still skipped;
    • switching off keeps a mixtape out;
    • a watch letting live albums in;
    • a "new releases only" baseline release switched on;
    • every state;
    • merging across a (feat. …) tag;
    • the routes (list, switch, bad bodies, unknown release, kinds, playlist watch refused).
  • tests/test_artist_watch_musicbrainz.py is updated: a live group is now listed (not downloaded), so last_track_count counts it.
  • Full backend suite in Docker (python 3.13 + ffmpeg): 3455 passed. The 13 failures are the music-trash tests, which fail the same way on main on my Windows/Docker setup. ruff check . passes.
  • Frontend: 740 passed (locale parity included), with the new lib/artistReleases.js covered. The build succeeds.
  • Docs tests: the new An artist's releases section is in English and all 10 translated playlist-monitor.md pages. The only failure is zh-CN/features/doctor.md, already failing on main since docs: complete Simplified Chinese feature translations and fix iOS links #585.
  • By hand in the Docker test instance at phone width, with a real Drake watch:
    • the listing (160 rows) and filters;
    • switching Views on: its baseline skip row was dropped, checked in the db;
    • switching Scorpion on, then off;
    • turning on Live albums: musicbrainz_kinds saved.
  • Not tested by hand: a switched-on release actually downloading (the watch was paused on purpose). The sweep side is covered by the tests above.

Strings are in all 12 locales. Docs: features/playlist-monitor.md (new section, all languages) and the API reference.

🤖 Generated with Claude Code

BigBrownMF69 and others added 2 commits November 13, 2026 16:50
Phase 2 of henriquesebastiao#581, first part. Artist Watch reads MusicBrainz as a third
catalogue (downtify/musicbrainz.py): one request a second process-wide,
a User-Agent naming Downtify, 503s retried. The artist is found once
through their Deezer page, YouTube Music channel or an unambiguous
name, and kept (musicbrainz_id).

Only the artist's own release groups (not guest spots), of the watch's
primary types, with secondary types let in by
artist_watch_musicbrainz_kinds (mixtapes and soundtracks by default),
and not bootleg-only. One official edition per group: explicit, the
most tracks, digital, earliest. Groups YouTube Music or Deezer already
list are left to them; songs found elsewhere are linked as before.

library_songs also folds (From "Film") title tags, which Indian labels
add on one catalogue and not another.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Phase 2 of henriquesebastiao#581, second part (on top of the MusicBrainz catalogue).
Each artist sweep keeps its listing (downtify/artist_catalogue.py,
table artist_catalogue), plus each release's track count and whether
it turned out to be a guest spot or bootleg. The watch's page gets a
Releases panel: every release YouTube Music, Deezer and MusicBrainz
list (one row per release, merged across catalogues, folding feat.
tags), what the library has of it (complete, partly, to download, out
before the watch, not watched, off, guest spot), and a switch per
release like Lidarr's per-album monitoring: on downloads it whatever
the watch's types or "new releases only" say, off never does.

MusicBrainz now lists groups of every kind; which kinds download is
per watch (musicbrainz_kinds, else the setting), chosen on the panel.

GET/PATCH /api/monitor/playlists/{id}/releases; PATCH watch takes
musicbrainz_kinds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@codspeed

codspeed Bot commented Nov 13, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

1 warning

⚠️ 1 benchmark is dominated by system calls

System calls cannot be simulated consistently and are left out of the measure. The reported value understates the real cost. Switch to the Walltime instrument to measure them.

Learn more about system calls

See affected benchmarks

✅ 10 untouched benchmarks


Comparing BigBrownMF69:feat/artist-watch-catalogue (dc1bdec) with main (ead6db5)

Open in CodSpeed

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

1 participant