mirror of
https://github.com/ZHANGTIANYAO1/teamspeak-music-bot.git
synced 2026-10-02 04:52:50 +08:00
Adds a self-contained Kugou provider (bilibili-style: direct API calls, no embedded API server, no new npm dependency) plus full backend + WebUI wiring. Provider (src/music/kugou.ts): search, song-url (with device registration), lyrics (KRC decode), song detail, playlist, album, personal FM, QR login + cookie persistence, and quality. Request signing / crypto / KRC decoding are ported from the MIT-licensed MakcRe/KuGouMusicApi using Node's built-in crypto and zlib (no third-party crypto packages). Wiring: the "kugou" platform is threaded through the provider contract, queue, play-history, bot instance/manager dispatch (getProviderFor + the -k command flag), index/server composition, the music/player/auth routers (unified /search/all, /quality, the platform coercions, QR login), the cookie store, and the WebUI (search source tab + badge, SongCard badge, brand token, and a Kugou QR/cookie login card in Settings). Verified live during development: search, lyrics, and album playback resolve correctly. NOT verifiable in CI (Kugou anti-bot blocks the build host's IP): play-URL resolution, QR login, and VIP audio — these are built faithfully to the reference and need end-to-end testing on a non-flagged IP / a Kugou account. See the header comment in kugou.ts. Includes src/music/kugou.test.ts (mappers + KRC→LRC). An adversarial review pass fixed: pagination truncating on filtered counts, an ms/seconds duration heuristic, dfid soft-fail caching, the /v5/url random-dfid fallback, the FM body identity, and an unguarded nickname decode. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
36 lines
1.1 KiB
TypeScript
36 lines
1.1 KiB
TypeScript
import fs from "node:fs";
|
|
import path from "node:path";
|
|
|
|
export interface CookieStore {
|
|
save(platform: "netease" | "qq" | "bilibili" | "kugou", cookie: string): void;
|
|
load(platform: "netease" | "qq" | "bilibili" | "kugou"): string;
|
|
}
|
|
|
|
export function createCookieStore(cookieDir: string): CookieStore {
|
|
if (!fs.existsSync(cookieDir)) {
|
|
fs.mkdirSync(cookieDir, { recursive: true });
|
|
}
|
|
|
|
return {
|
|
save(platform: "netease" | "qq" | "bilibili" | "kugou", cookie: string): void {
|
|
const filePath = path.join(cookieDir, `${platform}.json`);
|
|
fs.writeFileSync(
|
|
filePath,
|
|
JSON.stringify({ cookie, updatedAt: new Date().toISOString() }),
|
|
{ encoding: "utf-8", mode: 0o600 }
|
|
);
|
|
},
|
|
|
|
load(platform: "netease" | "qq" | "bilibili" | "kugou"): string {
|
|
const filePath = path.join(cookieDir, `${platform}.json`);
|
|
if (!fs.existsSync(filePath)) return "";
|
|
try {
|
|
const data = JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
|
return data.cookie ?? "";
|
|
} catch {
|
|
return "";
|
|
}
|
|
},
|
|
};
|
|
}
|