sync the rest of the source models

refactor music download/storage to avoid re-download during reset
add palylist to test server setup
This commit is contained in:
austinried
2025-11-07 15:20:38 +09:00
parent 0e6acbed0f
commit 0c80dbdba5
13 changed files with 451 additions and 149 deletions

View File

@@ -3,9 +3,6 @@ import * as path from "jsr:@std/path@1.1.2";
import { MUSIC_DIR } from "./util/env.ts";
import { SubsonicClient } from "./util/subsonic.ts";
await new Deno.Command("rm", { args: ["-rf", path.join(MUSIC_DIR, "*")] })
.output();
const client = new SubsonicClient(
"http://demo.subsonic.org",
"guest1",
@@ -13,7 +10,7 @@ const client = new SubsonicClient(
);
for (const id of ["197", "199", "321"]) {
const { res } = await client.get("download", { id });
const { res } = await client.get("download", [["id", id]]);
let filename = res.headers.get("Content-Disposition")
?.split(";")[1];

View File

@@ -2,31 +2,69 @@
import { SubsonicClient } from "./util/subsonic.ts";
import { sleep } from "./util/util.ts";
async function scrobbleTrack(
async function getSongId(
client: SubsonicClient,
album: string,
track: number,
): Promise<string> {
const { xml: albumsXml } = await client.get("getAlbumList2", [
["type", "newest"],
]);
const albumId = albumsXml.querySelector(
`album[name='${album.replaceAll("'", "\\'")}']`,
)?.id;
const { xml: songsXml } = await client.get("getAlbum", [["id", albumId!]]);
return songsXml.querySelector(`song[track='${track}']`)?.id!;
}
async function scrobbleTrack(
client: SubsonicClient,
songId: string,
) {
const { xml: albumsXml } = await client.get("getAlbumList2", {
type: "newest",
});
const albumId = albumsXml.querySelector(`album[name='${album}']`)?.id;
await client.get("scrobble", [
["id", songId!],
["submission", "true"],
]);
}
const { xml: songsXml } = await client.get("getAlbum", { id: albumId! });
const songId = songsXml.querySelector(`song[track='${track}']`)?.id;
async function createPlaylist(
client: SubsonicClient,
name: string,
songs: { album: string; track: number }[],
) {
const songIds = await Promise.all(songs.map(({ album, track }) => {
return getSongId(client, album, track);
}));
await client.get("scrobble", {
id: songId!,
submission: "true",
});
await client.get("createPlaylist", [
["name", name],
...songIds.map((songId) => ["songId", songId] as [string, string]),
]);
}
async function setupTestData(client: SubsonicClient) {
await scrobbleTrack(client, "Retroconnaissance EP", 1);
await scrobbleTrack(
client,
await getSongId(client, "Retroconnaissance EP", 1),
);
await sleep(1_000);
await scrobbleTrack(client, "Retroconnaissance EP", 2);
await scrobbleTrack(
client,
await getSongId(client, "Retroconnaissance EP", 2),
);
await sleep(1_000);
await scrobbleTrack(client, "Kosmonaut", 1);
await scrobbleTrack(client, await getSongId(client, "Kosmonaut", 1));
await createPlaylist(client, "Playlist 1", [
{ album: "Retroconnaissance EP", track: 2 },
{ album: "Retroconnaissance EP", track: 1 },
{ album: "Kosmonaut", track: 2 },
{ album: "Kosmonaut", track: 4 },
{ album: "I Don't Know What I'm Doing", track: 9 },
{ album: "I Don't Know What I'm Doing", track: 10 },
{ album: "I Don't Know What I'm Doing", track: 11 },
]);
}
async function setupNavidrome() {

View File

@@ -10,15 +10,15 @@ export class SubsonicClient {
async get(
method: "download",
params?: Record<string, string>,
params?: [string, string][],
): Promise<{ res: Response; xml: undefined }>;
async get(
method: string,
params?: Record<string, string>,
params?: [string, string][],
): Promise<{ res: Response; xml: Document }>;
async get(
method: string,
params?: Record<string, string>,
params?: [string, string][],
): Promise<{ res: Response; xml: Document | undefined }> {
const url = new URL(`rest/${method}.view`, this.baseUrl);
@@ -28,9 +28,9 @@ export class SubsonicClient {
url.searchParams.set("c", "subtracks-test-fixture");
if (params) {
Object.entries(params).forEach(([key, value]) =>
url.searchParams.append(key, value)
);
for (const [key, value] of params) {
url.searchParams.append(key, value);
}
}
const res = await fetch(url);