feat: rework !similar to build and play discovery playlists

Default !similar now discovers similar artists/tracks, resolves each
against YouTube in parallel via ThreadPoolExecutor, fades out current
playback, and starts the new playlist. Old display behavior moves to
!similar list subcommand.

New helpers: _search_queries() normalizes Last.fm/MB results into search
strings, _resolve_playlist() resolves queries to _Track objects in
parallel. Falls back to display mode when music plugin not loaded.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
user
2026-02-23 23:56:51 +01:00
parent b658053711
commit dd4c6b95b7
5 changed files with 357 additions and 173 deletions

View File

@@ -613,14 +613,17 @@ Mumble-only: `!play` replies with error on other adapters, others silently no-op
## Music Discovery
```
!similar # Similar to currently playing track
!similar <artist> # Similar artists to named artist
!similar play # Queue a random similar track
!similar play <artist># Queue similar track for named artist
!similar # Discover + play similar to current track
!similar <artist> # Discover + play similar to named artist
!similar list # Show similar (display only)
!similar list <artist># Show similar for named artist
!tags # Genre tags for current artist
!tags <artist> # Genre tags for named artist
```
Default `!similar` builds a playlist: discovers similar artists, resolves
via YouTube in parallel, fades out current, plays the new playlist.
`!similar list` shows results without playing.
Uses Last.fm when API key is set; falls back to MusicBrainz automatically.
Config: `[lastfm] api_key` or `LASTFM_API_KEY` env var.