mirror of
https://github.com/ZHANGTIANYAO1/teamspeak-music-bot.git
synced 2026-10-01 20:42:50 +08:00
feat(fm): let each web user link their own NetEase account for personal FM (#164)
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>
This commit is contained in:
1 parent
8ff51ea6e0
commit
ac4a12d8bd
11 files changed
+652
-11
No files matched your search
@@ -345,3 +345,36 @@ describe("guest principal migration", () => {
|
||||
rmSync(dir, { recursive: true, force: true });
|
||||
});
|
||||
});
|
||||
|
||||
describe("user music cookies (#164)", () => {
|
||||
let botDb: BotDatabase;
|
||||
const addUser = (id: string) =>
|
||||
botDb.db
|
||||
.prepare("INSERT INTO users (id, username, passwordHash, createdAt, updatedAt, role) VALUES (?,?,?,?,?,?)")
|
||||
.run(id, id, "x", 0, 0, "member");
|
||||
|
||||
beforeEach(() => {
|
||||
botDb = createDatabase(":memory:");
|
||||
addUser("u1");
|
||||
addUser("u2");
|
||||
});
|
||||
afterEach(() => botDb.close());
|
||||
|
||||
it("stores, overwrites and deletes a cookie per user and platform", () => {
|
||||
expect(botDb.getUserMusicCookie("u1", "netease")).toBeNull();
|
||||
botDb.setUserMusicCookie("u1", "netease", "MUSIC_U=a");
|
||||
botDb.setUserMusicCookie("u1", "netease", "MUSIC_U=b");
|
||||
expect(botDb.getUserMusicCookie("u1", "netease")).toBe("MUSIC_U=b");
|
||||
expect(botDb.getUserMusicCookie("u2", "netease")).toBeNull();
|
||||
expect(botDb.getUserMusicCookie("u1", "qq")).toBeNull();
|
||||
expect(botDb.deleteUserMusicCookie("u1", "netease")).toBe(true);
|
||||
expect(botDb.deleteUserMusicCookie("u1", "netease")).toBe(false);
|
||||
expect(botDb.getUserMusicCookie("u1", "netease")).toBeNull();
|
||||
});
|
||||
|
||||
it("drops a user's cookies when the user is deleted", () => {
|
||||
botDb.setUserMusicCookie("u1", "netease", "MUSIC_U=a");
|
||||
botDb.db.prepare("DELETE FROM users WHERE id = ?").run("u1");
|
||||
expect(botDb.getUserMusicCookie("u1", "netease")).toBeNull();
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user