success pt. 8.0
This commit is contained in:
@@ -1,5 +1,11 @@
|
||||
import { desc, like } from "drizzle-orm";
|
||||
import { animeTable } from "$lib/db/schema";
|
||||
import { desc, eq, like } from "drizzle-orm";
|
||||
import {
|
||||
animeSongLinksTable,
|
||||
animeTable,
|
||||
artistsTable,
|
||||
groupsTable,
|
||||
songsTable,
|
||||
} from "$lib/db/schema";
|
||||
import type { ClientDb } from "./index";
|
||||
|
||||
/**
|
||||
@@ -75,6 +81,69 @@ export async function searchAnimeByName(
|
||||
.limit(safeLimit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a single anime plus its linked songs, including:
|
||||
* - anime name
|
||||
* - link metadata: type + number (OP1/ED2/etc)
|
||||
* - song metadata: song name, artist/group name, fileName for audio playback
|
||||
*
|
||||
* Note: this assumes the SQLite snapshot has `songs.file_name`, `songs.song_artist_id`,
|
||||
* and `songs.song_group_id` populated.
|
||||
*/
|
||||
export async function getAnimeWithSongsByAnnId(db: ClientDb, annId: number) {
|
||||
const animeRows = await db
|
||||
.select({
|
||||
annId: animeTable.annId,
|
||||
mainName: animeTable.mainName,
|
||||
year: animeTable.year,
|
||||
seasonId: animeTable.seasonId,
|
||||
malId: animeTable.malId,
|
||||
})
|
||||
.from(animeTable)
|
||||
.where(eq(animeTable.annId, annId))
|
||||
.limit(1);
|
||||
|
||||
const anime = animeRows[0];
|
||||
if (!anime) return null;
|
||||
|
||||
const rows = await db
|
||||
.select({
|
||||
annSongId: animeSongLinksTable.annSongId,
|
||||
type: animeSongLinksTable.type,
|
||||
number: animeSongLinksTable.number,
|
||||
|
||||
songName: songsTable.name,
|
||||
fileName: songsTable.fileName,
|
||||
|
||||
artistName: artistsTable.name,
|
||||
groupName: groupsTable.name,
|
||||
})
|
||||
.from(animeSongLinksTable)
|
||||
.innerJoin(
|
||||
songsTable,
|
||||
eq(songsTable.annSongId, animeSongLinksTable.annSongId),
|
||||
)
|
||||
.leftJoin(
|
||||
artistsTable,
|
||||
eq(artistsTable.songArtistId, songsTable.songArtistId),
|
||||
)
|
||||
.leftJoin(groupsTable, eq(groupsTable.songGroupId, songsTable.songGroupId))
|
||||
.where(eq(animeSongLinksTable.annId, annId))
|
||||
.orderBy(desc(animeSongLinksTable.type), desc(animeSongLinksTable.number));
|
||||
|
||||
return {
|
||||
anime,
|
||||
songs: rows.map((r) => ({
|
||||
annSongId: r.annSongId,
|
||||
type: r.type,
|
||||
number: r.number,
|
||||
songName: r.songName,
|
||||
fileName: r.fileName,
|
||||
artistName: r.artistName ?? r.groupName ?? null,
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
function clampLimit(limit: number) {
|
||||
const n = Number(limit);
|
||||
if (!Number.isFinite(n)) return DEFAULT_LIST_LIMIT;
|
||||
|
||||
@@ -331,6 +331,13 @@ export async function importAmqData(
|
||||
songId: s.songId,
|
||||
name: s.name,
|
||||
category: s.category,
|
||||
fileName: s.fileName,
|
||||
songArtistId: s.songArtistId,
|
||||
songGroupId: s.songGroupId,
|
||||
composerArtistId: s.composerArtistId,
|
||||
composerGroupId: s.composerGroupId,
|
||||
arrangerArtistId: s.arrangerArtistId,
|
||||
arrangerGroupId: s.arrangerGroupId,
|
||||
}));
|
||||
|
||||
for (const batch of chunk(songRows, batchSize)) {
|
||||
@@ -343,6 +350,13 @@ export async function importAmqData(
|
||||
songId: songsTable.songId,
|
||||
name: songsTable.name,
|
||||
category: songsTable.category,
|
||||
fileName: songsTable.fileName,
|
||||
songArtistId: songsTable.songArtistId,
|
||||
songGroupId: songsTable.songGroupId,
|
||||
composerArtistId: songsTable.composerArtistId,
|
||||
composerGroupId: songsTable.composerGroupId,
|
||||
arrangerArtistId: songsTable.arrangerArtistId,
|
||||
arrangerGroupId: songsTable.arrangerGroupId,
|
||||
},
|
||||
})
|
||||
.run();
|
||||
|
||||
@@ -81,9 +81,51 @@ export const songsTable = sqliteTable(
|
||||
* none(0), instrumental(1), chanting(2), character(3), standard(4)
|
||||
*/
|
||||
category: integer("category").notNull(),
|
||||
|
||||
/**
|
||||
* Song audio filename used by the AMQ CDN:
|
||||
* https://nawdist.animemusicquiz.com/{fileName}
|
||||
*/
|
||||
fileName: text("file_name"),
|
||||
|
||||
/**
|
||||
* Primary artist/group ids for this song (nullable in source).
|
||||
* These reference existing `artists` / `groups` rows.
|
||||
*/
|
||||
songArtistId: integer("song_artist_id").references(
|
||||
() => artistsTable.songArtistId,
|
||||
{ onDelete: "set null" },
|
||||
),
|
||||
songGroupId: integer("song_group_id").references(
|
||||
() => groupsTable.songGroupId,
|
||||
{ onDelete: "set null" },
|
||||
),
|
||||
|
||||
/**
|
||||
* Additional contributor ids (nullable in source)
|
||||
*/
|
||||
composerArtistId: integer("composer_artist_id").references(
|
||||
() => artistsTable.songArtistId,
|
||||
{ onDelete: "set null" },
|
||||
),
|
||||
composerGroupId: integer("composer_group_id").references(
|
||||
() => groupsTable.songGroupId,
|
||||
{ onDelete: "set null" },
|
||||
),
|
||||
arrangerArtistId: integer("arranger_artist_id").references(
|
||||
() => artistsTable.songArtistId,
|
||||
{ onDelete: "set null" },
|
||||
),
|
||||
arrangerGroupId: integer("arranger_group_id").references(
|
||||
() => groupsTable.songGroupId,
|
||||
{ onDelete: "set null" },
|
||||
),
|
||||
},
|
||||
(t) => ({
|
||||
songIdIndex: index("songs_song_id_idx").on(t.songId),
|
||||
fileNameIndex: index("songs_file_name_idx").on(t.fileName),
|
||||
songArtistIdIndex: index("songs_song_artist_id_idx").on(t.songArtistId),
|
||||
songGroupIdIndex: index("songs_song_group_id_idx").on(t.songGroupId),
|
||||
}),
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user