diff --git a/PROJECT.md b/PROJECT.md index 5642c5d..bd8bb16 100644 --- a/PROJECT.md +++ b/PROJECT.md @@ -28,10 +28,13 @@ CLI (argparse) -> Config (TOML) -> Bot (orchestrator) | Category | Plugins | Purpose | |----------|---------|---------| | Core | core | Bot management, help, plugin lifecycle | -| OSINT | dns, crtsh | Reconnaissance and enumeration | +| OSINT | dns, crtsh, internetdb | Reconnaissance and enumeration | | Red Team | revshell, encode, hash | Offensive tooling | | OPSEC | defang | Safe IOC handling | -| Utility | cidr, example | Network tools, demo | +| Utility | cidr, rand, timer, remind | Network tools, scheduling | +| Music | music, lastfm | Mumble playback, discovery (Last.fm/MB) | +| Voice | voice, mumble_admin | STT/TTS, server admin | +| Subscriptions | rss, yt, twitch, alert | Feed monitoring, keyword alerts | ### Key Design Decisions diff --git a/ROADMAP.md b/ROADMAP.md index 971d144..f760953 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -179,11 +179,14 @@ - [x] Alias plugin (!alias add/del/list) - [x] Container management tools (tools/build, start, stop, restart, nuke, logs, status) -## v2.4.0 -- Music Discovery + Performance +## v2.4.0 -- Music Discovery + Performance (done) -- [ ] Last.fm integration (artist.getSimilar, artist.getTopTags, track.getSimilar) -- [ ] `!similar` command (find similar artists, optionally queue via YouTube) -- [ ] `!tags` command (genre/style tags for current track) +- [x] Last.fm integration (artist.getSimilar, artist.getTopTags, track.getSimilar) +- [x] `!similar` command (find similar artists, optionally queue via YouTube) +- [x] `!tags` command (genre/style tags for current track) +- [x] MusicBrainz fallback for `!similar` and `!tags` (no API key required) +- [x] Auto-discover similar tracks during autoplay via Last.fm/MusicBrainz +- [x] Mumble server admin plugin (`!mu` -- kick, ban, mute, move, channels) - [x] Pause/unpause (`!pause` toggle, position tracking, stale re-download) - [x] Autoplay continuous radio (random kept, silence-aware, cooldown between tracks) - [x] Periodic resume persistence (10s interval, survives hard kills) diff --git a/TASKS.md b/TASKS.md index 423a06b..954c950 100644 --- a/TASKS.md +++ b/TASKS.md @@ -8,6 +8,7 @@ | P0 | [x] | `!tags` MusicBrainz fallback when no Last.fm API key or empty results | | P1 | [x] | `!similar play` works through MB fallback path | | P1 | [x] | Tests: MB fallback for both commands (6 new cases, 70 total in test_lastfm.py) | +| P2 | [x] | Documentation update (USAGE.md, CHEATSHEET.md, ROADMAP.md, TODO.md, PROJECT.md) | ## Previous Sprint -- Voice + Music UX (2026-02-22) @@ -44,7 +45,7 @@ | P1 | [x] | `!tags` command -- show genre/style tags for current or named track | | P1 | [x] | Config: `[lastfm] api_key` or `LASTFM_API_KEY` env var | | P2 | [x] | Tests: `test_lastfm.py` (50 cases: API helpers, metadata, commands) | -| P2 | [ ] | Documentation update (USAGE.md, CHEATSHEET.md) | +| P2 | [x] | Documentation update (USAGE.md, CHEATSHEET.md) | ## Previous Sprint -- v2.3.0 Mumble Voice + Multi-Bot (2026-02-22) diff --git a/TODO.md b/TODO.md index a059962..de1b178 100644 --- a/TODO.md +++ b/TODO.md @@ -132,9 +132,9 @@ is preserved in git history for reference. ## Performance -- [ ] Iterative `_extract_videos` in alert.py (51K recursive calls, 6.7s CPU) -- [ ] Bypass SOCKS5 for local services (FlaskPaste, SearXNG) -- [ ] Connection pool tuning (529 SOCKS connections per 25min session) +- [x] Iterative `_extract_videos` in alert.py (replaced 51K-deep recursion) +- [x] Bypass SOCKS5 for local services (SearXNG `proxy=False`) +- [x] Connection pool tuning (30 pools / 8 connections) - [ ] Async HTTP client (aiohttp + aiohttp-socks) to avoid blocking executors - [x] Connection pooling via urllib3 SOCKSProxyManager - [x] Batch OG fetch via ThreadPoolExecutor @@ -166,11 +166,11 @@ is preserved in git history for reference. ## Music Discovery -- [ ] Last.fm integration (API key, free tier) -- [ ] `!similar` command -- find similar artists/tracks via Last.fm -- [ ] `!tags` command -- show genre/style tags for current track -- [ ] Auto-queue similar tracks when autoplay has no kept tracks -- [ ] MusicBrainz fallback (no API key, 1 req/sec rate limit) +- [x] Last.fm integration (API key, free tier) +- [x] `!similar` command -- find similar artists/tracks via Last.fm +- [x] `!tags` command -- show genre/style tags for current track +- [x] Auto-discover similar tracks during autoplay via Last.fm/MusicBrainz +- [x] MusicBrainz fallback for `!similar` and `!tags` (no API key required) ## Slack diff --git a/docs/CHEATSHEET.md b/docs/CHEATSHEET.md index d3c882a..482ef40 100644 --- a/docs/CHEATSHEET.md +++ b/docs/CHEATSHEET.md @@ -605,6 +605,38 @@ Skip/stop/prev/seek fade out smoothly (~0.8s); volume ramps over ~1s. Auto-resumes on reconnect if channel is silent (waits up to 60s for silence). Mumble-only: `!play` replies with error on other adapters, others silently no-op. +## Music Discovery + +``` +!similar # Similar to currently playing track +!similar # Similar artists to named artist +!similar play # Queue a random similar track +!similar play # Queue similar track for named artist +!tags # Genre tags for current artist +!tags # Genre tags for named artist +``` + +Uses Last.fm when API key is set; falls back to MusicBrainz automatically. +Config: `[lastfm] api_key` or `LASTFM_API_KEY` env var. + +## Mumble Admin (admin) + +``` +!mu kick [reason] # Kick user +!mu ban [reason] # Ban user +!mu mute # Server-mute +!mu unmute # Remove server-mute +!mu deafen # Server-deafen +!mu undeafen # Remove server-deafen +!mu move # Move user to channel +!mu users # List connected users +!mu channels # List channels +!mu mkchan [parent] # Create channel +!mu rmchan # Remove empty channel +!mu rename # Rename channel +!mu desc # Set channel description +``` + ## Plugin Template ```python diff --git a/docs/USAGE.md b/docs/USAGE.md index 87301de..10213b6 100644 --- a/docs/USAGE.md +++ b/docs/USAGE.md @@ -1760,6 +1760,53 @@ file (natural dedup). missing (e.g. after a cleanup or volume mount issue) - On cancel/error, files are not deleted (needed for `!resume`) +### Music Discovery + +Find similar music and genre tags for artists. Uses Last.fm when an API +key is configured; falls back to MusicBrainz automatically (no key +required). + +``` +!similar Similar to currently playing track +!similar Similar artists to named artist +!similar play Queue a random similar track +!similar play Queue a similar track for named artist +!tags Genre tags for currently playing artist +!tags Genre tags for named artist +``` + +- When an API key is set, Last.fm is tried first for richer results +- When no API key is set (or Last.fm returns empty), MusicBrainz is + used as a fallback (artist search -> tags -> similar recordings) +- `!similar play` picks a random result and delegates to `!play` + (searches YouTube for the artist + title) +- MusicBrainz rate limit: 1 request/second (handled automatically) + +Configuration (optional): + +```toml +[lastfm] +api_key = "" # Last.fm API key (or set LASTFM_API_KEY env var) +``` + +### Autoplay Discovery + +During autoplay, the bot periodically discovers new tracks instead of +only playing from the kept library. Every Nth autoplay pick (configurable +via `discover_ratio`), it queries Last.fm or MusicBrainz for a track +similar to the last-played one. Discovered tracks are searched on YouTube +and queued automatically. + +Configuration (optional): + +```toml +[music] +autoplay = true # Enable autoplay (default: true) +autoplay_cooldown = 30 # Seconds between autoplay tracks (default: 30) +discover = true # Enable discovery during autoplay (default: true) +discover_ratio = 3 # Discover every Nth pick (default: 3) +``` + ### Extra Mumble Bots Run additional bot identities on the same Mumble server. Each extra bot @@ -1856,3 +1903,24 @@ Available voices: To switch the active voice, set `piper_tts_voice` (e.g. `fr_FR-siwis-medium`) and redeploy the TTS service. + +### Mumble Server Admin (admin) + +Manage Mumble users and channels via chat commands. All subcommands +require admin tier. Mumble-only (no-op on other adapters). + +``` +!mu kick [reason] Kick user from server +!mu ban [reason] Ban user from server +!mu mute Server-mute user +!mu unmute Remove server-mute +!mu deafen Server-deafen user +!mu undeafen Remove server-deafen +!mu move Move user to channel +!mu users List connected users +!mu channels List server channels +!mu mkchan [parent] Create channel (under parent or root) +!mu rmchan Remove empty channel +!mu rename Rename channel +!mu desc Set channel description +```