- Wrap clientedit (description) with 5s timeout to prevent blocking
channel description and now-playing updates if the command hangs
- Check generation counter in clearAvatar to avoid clearing a newer
song's avatar when stop→play happens in quick succession
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add generation counter to prevent stale avatar uploads from
overwriting newer song's profile when rapidly skipping tracks
- Fix nickname truncation to use UTF-8 byte length instead of JS
string length (TS3 counts bytes, Chinese chars are 3 bytes)
- Add timeout to clearAvatar file transfer (was missing)
- Extract withTimeout helper to deduplicate timeout logic
- Add BiliBili CDN thumbnail resize support (@200w_200h)
- Bump generation on reconnect to discard in-flight updates from
the old connection
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Description via clientupdate is rejected (error 1538) on TS3 full-client
protocol. Switch to clientedit on the bot's own clid, which is how
TS3AudioBot handles it. Requires b_client_modify_description permission.
Also add sendCommandNoWait to TS3Client for fire-and-forget commands
(clientupdate, channeledit) that don't return timely responses.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add BotProfileManager that updates the bot's TeamSpeak presence when
songs change: album cover as avatar, song info in nickname, away status
toggled on stop/play. Each feature is independently configurable via
REST API and persisted to the database. Permission-safe — features that
fail due to insufficient server permissions are silently disabled until
reconnect. Description falls back to nickname display on TS3 (only
supported via TS6 HTTP Query).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>