With several people sharing one bot, personal FM always followed the one
account the bot was logged in with. Each signed-in (non-guest) web user
can now scan a QR code under Settings → 账户 to link their own NetEase
account; FM they start from the WebUI then comes from their account.
- user_music_cookies table (per user + platform, dropped with the user).
- NeteaseProvider.pollQrLogin returns the cookie without storing it, so
a personal login can never replace the bot's shared account;
checkQrCodeStatus is now built on it. withCookie gives a view bound to
another account.
- /api/me/music/netease: status / qrcode / qrcode/status / unlink, acting
only on req.user. The cookie never leaves the server.
- POST /api/player/:botId/fm uses the caller's linked account for
NetEase. Songs still resolve through the shared provider when played.
TeamSpeak chat !fm keeps using the shared account: chat users are not
tied to web accounts.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>