mirror of
https://github.com/ZHANGTIANYAO1/teamspeak-music-bot.git
synced 2026-10-04 05:52:50 +08:00
Adds artist support for the NetEase and QQ providers plus the matching UI. Backend: - SearchResult gains `artists`; new optional MusicProvider methods getArtistDetail / getArtistSongs / getArtistAlbums / getArtistAllSongs. - NetEase: /cloudsearch type=100 for artist search, /artists, /artist/songs, /artist/album and /artist/desc for the artist page. - QQ: singer search rides along in the existing musicu.fcg batch (search_type=1); singer detail via music.web_singer_info_svr. QQ exposes no working singer-song paging endpoint, so the full catalogue is built from the hot 50 plus every album of the singer (album search filtered by singerMID, songs fetched per album, de-duplicated, cached for 10 minutes). A failed album sweep is never cached and degrades to the hot list. - API: GET /api/music/artist/:id and POST /api/player/:botId/play-artist (player.control capability, guest flag playCollection); /search/all now aggregates artists too. Frontend: - Search history in localStorage (max 10, per platform, never shared between users), shown as a dropdown under the search box and as 最近搜索 chips. - Artist row in the search results; new /artist/:id page (portrait, aliases, stats, description, top songs, album shelf) with 播放 / 随机播放, which queue the singer's whole catalogue. - playArtist store action. Tests cover the provider mappers, the new routes, the play-artist collector (paging, de-duplication, 500-track cap), permission gating and the new views.
43 lines
1.4 KiB
TypeScript
43 lines
1.4 KiB
TypeScript
import { readFileSync } from "node:fs";
|
|
import { fileURLToPath } from "node:url";
|
|
import { dirname, join } from "node:path";
|
|
import { describe, expect, it } from "vitest";
|
|
|
|
const currentDir = dirname(fileURLToPath(import.meta.url));
|
|
const source = () => readFileSync(join(currentDir, "Artist.vue"), "utf8");
|
|
|
|
describe("Artist page layout", () => {
|
|
it("has no 全部歌曲 browser section (play buttons queue the catalogue instead)", () => {
|
|
const src = source();
|
|
|
|
expect(src).not.toContain("全部歌曲</h2>");
|
|
expect(src).not.toContain("加载更多");
|
|
expect(src).not.toContain("加载全部歌曲");
|
|
expect(src).not.toContain("ALL_SONGS_PAGE");
|
|
expect(src).not.toContain("loadMoreSongs");
|
|
expect(src).not.toContain("allSongs");
|
|
});
|
|
|
|
it("keeps the hot songs and album sections", () => {
|
|
const src = source();
|
|
|
|
expect(src).toContain("热门歌曲");
|
|
expect(src).toContain("专辑");
|
|
expect(src).toContain("显示全部");
|
|
});
|
|
|
|
it("plays through playArtist without an all flag (the server always loads everything)", () => {
|
|
const src = source();
|
|
|
|
expect(src).toContain("store.playArtist(artistId(), platform.value)");
|
|
expect(src).not.toContain("playArtist(artistId(), platform.value, true)");
|
|
});
|
|
|
|
it("refetches when navigating between artists", () => {
|
|
const src = source();
|
|
|
|
expect(src).toContain("watch(");
|
|
expect(src).toContain("route.params.id");
|
|
});
|
|
});
|