feat : add metrial fetcher

This commit is contained in:
2026-09-06 13:59:32 +07:00 Unverified
parent 2808a27406
commit 37d6d6703f
8 changed files with 3827 additions and 8 deletions
+35 -5
View File
@@ -10,6 +10,7 @@ import {
artifactRecommendations,
catalogArtifacts,
catalogCharacters,
catalogMaterials,
catalogWeapons,
constellationConditions,
constellationRecommendations,
@@ -28,7 +29,10 @@ import { aliasesByItem } from "@/lib/glossary";
const catalogVersionSchema = z.object({ version: z.string() });
function catalogCharacterWithUrls(item: typeof catalogCharacters.$inferSelect) {
function catalogCharacterWithUrls(
item: typeof catalogCharacters.$inferSelect,
materialByKey = new Map<string, typeof catalogMaterials.$inferSelect>(),
) {
return {
...item,
imageUrl: publicMediaUrl(item.imageKey),
@@ -43,28 +47,47 @@ function catalogCharacterWithUrls(item: typeof catalogCharacters.$inferSelect) {
...talent,
iconUrl: talent.iconKey ? publicMediaUrl(talent.iconKey) : null,
})),
ascension: item.ascension.map((group) => ({
...group,
items: group.items.map((entry) => {
const material = materialByKey.get(entry.key);
return {
...entry,
name: material?.name ?? entry.key,
description: material?.description ?? null,
rarity: material?.rarity ?? null,
type: material?.type ?? null,
imageUrl: material ? publicMediaUrl(material.imageKey) : null,
lunarisUrl: `https://lunaris.moe/material/${encodeURIComponent(entry.key)}`,
available: Boolean(material),
};
}),
})),
};
}
export async function getActiveCatalog() {
const db = getDb();
const [characters, weapons, artifacts, aliases] = await Promise.all([
const [characters, weapons, artifacts, materials, aliases] = await Promise.all([
db.select().from(catalogCharacters).orderBy(asc(catalogCharacters.name)),
db.select().from(catalogWeapons).orderBy(asc(catalogWeapons.name)),
db.select().from(catalogArtifacts).orderBy(asc(catalogArtifacts.name)),
db.select().from(catalogMaterials).orderBy(asc(catalogMaterials.name)),
db.select().from(glossaryAliases),
]);
if (!characters.length) return null;
const groupedAliases = aliasesByItem(aliases);
const materialByKey = new Map(materials.map((item) => [item.key, item]));
const storage = await getMediaStorage();
const { version } = catalogVersionSchema.parse(
await storage.file("catalog/current.json").json(),
);
return {
version,
characters: characters.map((item) => ({ ...catalogCharacterWithUrls(item), aliases: groupedAliases.character.get(item.key) ?? [] })),
characters: characters.map((item) => ({ ...catalogCharacterWithUrls(item, materialByKey), aliases: groupedAliases.character.get(item.key) ?? [] })),
weapons: weapons.map((item) => ({ ...item, aliases: groupedAliases.weapon.get(item.key) ?? [], imageUrl: publicMediaUrl(item.imageKey) })),
artifacts: artifacts.map((item) => ({ ...item, aliases: groupedAliases.artifact.get(item.key) ?? [], imageUrl: publicMediaUrl(item.imageKey) })),
materials: materials.map((item) => ({ ...item, imageUrl: publicMediaUrl(item.imageKey), lunarisUrl: `https://lunaris.moe/material/${encodeURIComponent(item.key)}` })),
};
}
@@ -114,7 +137,10 @@ async function getGuideContent(slug: string, publicOnly: boolean) {
))
.limit(1);
if (!row) return null;
const [sections, weaponConditionsRows, groups, profile, constellationGroups, teams, aliases] = await Promise.all([
const materialKeys = [...new Set(
row.character.ascension.flatMap((group) => group.items.map((item) => item.key)),
)];
const [sections, weaponConditionsRows, groups, profile, constellationGroups, teams, aliases, materials] = await Promise.all([
getDb().select().from(guideSections).where(and(eq(guideSections.guideId, row.guide.id), eq(guideSections.enabled, true))).orderBy(asc(guideSections.sortOrder)),
getDb().select().from(weaponConditions).where(eq(weaponConditions.guideId, row.guide.id)).orderBy(asc(weaponConditions.sortOrder)),
getDb().select().from(artifactGroups).where(eq(artifactGroups.guideId, row.guide.id)).orderBy(asc(artifactGroups.sortOrder)),
@@ -122,8 +148,12 @@ async function getGuideContent(slug: string, publicOnly: boolean) {
getDb().select().from(constellationConditions).where(eq(constellationConditions.guideId, row.guide.id)).orderBy(asc(constellationConditions.sortOrder)),
getDb().select().from(teamCompositions).where(eq(teamCompositions.guideId, row.guide.id)).orderBy(asc(teamCompositions.sortOrder)),
getDb().select().from(glossaryAliases),
materialKeys.length
? getDb().select().from(catalogMaterials).where(inArray(catalogMaterials.key, materialKeys))
: [],
]);
const groupedAliases = aliasesByItem(aliases);
const materialByKey = new Map(materials.map((item) => [item.key, item]));
const elementIconUrls = Object.fromEntries(
(await getDb()
@@ -168,7 +198,7 @@ async function getGuideContent(slug: string, publicOnly: boolean) {
return {
...row.guide,
coverUrl: publicMediaUrl(row.cover.objectKey),
character: { ...catalogCharacterWithUrls(row.character), aliases: groupedAliases.character.get(row.character.key) ?? [] },
character: { ...catalogCharacterWithUrls(row.character, materialByKey), aliases: groupedAliases.character.get(row.character.key) ?? [] },
elementIconUrls,
sections,
weapons: weaponRows.map(({ recommendation, weapon }) => ({ ...recommendation, weapon: { ...weapon, aliases: groupedAliases.weapon.get(weapon.key) ?? [], imageUrl: publicMediaUrl(weapon.imageKey) } })),