Add /studios & /studios/random

This commit is contained in:
Zoe Roux 2025-03-03 11:45:18 +01:00
parent 44658ce6b0
commit bf16231350
No known key found for this signature in database
2 changed files with 107 additions and 7 deletions

View File

@ -7,7 +7,7 @@ import {
studioTranslations, studioTranslations,
studios, studios,
} from "~/db/schema"; } from "~/db/schema";
import { sqlarr } from "~/db/utils"; import { getColumns, sqlarr } from "~/db/utils";
import { KError } from "~/models/error"; import { KError } from "~/models/error";
import { Movie } from "~/models/movie"; import { Movie } from "~/models/movie";
import { Serie } from "~/models/serie"; import { Serie } from "~/models/serie";
@ -17,13 +17,18 @@ import {
AcceptLanguage, AcceptLanguage,
Filter, Filter,
Page, Page,
Sort,
createPage, createPage,
isUuid, isUuid,
keysetPaginate,
processLanguages, processLanguages,
sortToSql,
} from "~/models/utils"; } from "~/models/utils";
import { desc } from "~/models/utils/descriptions"; import { desc } from "~/models/utils/descriptions";
import { getShows, showFilters, showSort } from "./shows/logic"; import { getShows, showFilters, showSort } from "./shows/logic";
const studioSort = Sort(["slug", "createdAt"], { default: ["slug"] });
export const studiosH = new Elysia({ prefix: "/studios", tags: ["studios"] }) export const studiosH = new Elysia({ prefix: "/studios", tags: ["studios"] })
.model({ .model({
studio: Studio, studio: Studio,
@ -111,6 +116,98 @@ export const studiosH = new Elysia({ prefix: "/studios", tags: ["studios"] })
}, },
}, },
) )
.get(
"random",
async ({ error, redirect }) => {
const [studio] = await db
.select({ slug: studios.slug })
.from(studios)
.orderBy(sql`random()`)
.limit(1);
if (!studio)
return error(404, {
status: 404,
message: "No studios in the database.",
});
return redirect(`/studios/${studio.slug}`);
},
{
detail: {
description: "Get a random studio.",
},
response: {
302: t.Void({
description:
"Redirected to the [/studios/{id}](#tag/studios/GET/studios/{id}) route.",
}),
404: {
...KError,
description: "No studios in the database.",
},
},
},
)
.get(
"",
async ({
query: { limit, after, query, sort, filter },
headers: { "accept-language": languages },
request: { url },
}) => {
const langs = processLanguages(languages);
const transQ = db
.selectDistinctOn([studioTranslations.pk])
.from(studioTranslations)
.orderBy(
studioTranslations.pk,
sql`array_position(${sqlarr(langs)}, ${studioTranslations.language}`,
)
.as("t");
const { pk, ...transCol } = getColumns(transQ);
const items = await db
.select({
...getColumns(studios),
...transCol,
})
.from(studios)
.where(
and(
query ? sql`${transQ.name} %> ${query}::text` : undefined,
keysetPaginate({ table: studios, after, sort }),
),
)
.orderBy(
...(query
? [sql`word_similarity(${query}::text, ${transQ.name})`]
: sortToSql(sort, studios)),
studios.pk,
)
.limit(limit);
return createPage(items, { url, sort, limit });
},
{
detail: { description: "Get all studios" },
query: t.Object({
sort: studioSort,
query: t.Optional(t.String({ description: desc.query })),
limit: t.Integer({
minimum: 1,
maximum: 250,
default: 50,
description: "Max page size.",
}),
after: t.Optional(t.String({ description: desc.after })),
}),
headers: t.Object({
"accept-language": AcceptLanguage({ autoFallback: true }),
}),
response: {
200: Page(Studio),
422: KError,
},
},
)
.guard({ .guard({
params: t.Object({ params: t.Object({
id: t.String({ id: t.String({

View File

@ -1,6 +1,6 @@
import { t } from "elysia"; import { t } from "elysia";
import type { Prettify } from "elysia/dist/types"; import type { Prettify } from "elysia/dist/types";
import { madeInAbyss, registerExamples } from "./examples"; import { bubbleImages, madeInAbyss, registerExamples } from "./examples";
import { DbMetadata, ExternalId, Resource, TranslationRecord } from "./utils"; import { DbMetadata, ExternalId, Resource, TranslationRecord } from "./utils";
import { Image, SeedImage } from "./utils/image"; import { Image, SeedImage } from "./utils/image";
@ -26,13 +26,16 @@ export const SeedStudio = t.Intersect([
t.Object({ t.Object({
slug: t.String({ format: "slug" }), slug: t.String({ format: "slug" }),
translations: TranslationRecord( translations: TranslationRecord(
t.Object({ t.Intersect([
name: t.String(), t.Omit(StudioTranslation, ["logo"]),
logo: t.Nullable(SeedImage), t.Object({
}), logo: t.Nullable(SeedImage),
}),
]),
), ),
}), }),
]); ]);
export type SeedStudio = Prettify<typeof SeedStudio.static>; export type SeedStudio = Prettify<typeof SeedStudio.static>;
registerExamples(Studio, madeInAbyss.studios[0]); const ex = madeInAbyss.studios[0];
registerExamples(Studio, { ...ex, ...ex.translations.en, ...bubbleImages });