Add GET /videos/ that also list guesses

This commit is contained in:
Zoe Roux 2025-04-09 22:41:45 +02:00
parent c504cbbff5
commit 621c9cec82
No known key found for this signature in database
3 changed files with 84 additions and 3 deletions

View File

@ -3,10 +3,10 @@ import { alias } from "drizzle-orm/pg-core";
import { Elysia, t } from "elysia"; import { Elysia, t } from "elysia";
import { db } from "~/db"; import { db } from "~/db";
import { entries, entryVideoJoin, shows, videos } from "~/db/schema"; import { entries, entryVideoJoin, shows, videos } from "~/db/schema";
import { sqlarr } from "~/db/utils"; import { jsonbBuildObject, jsonbObjectAgg, sqlarr } from "~/db/utils";
import { bubbleVideo } from "~/models/examples"; import { bubbleVideo } from "~/models/examples";
import { Page } from "~/models/utils"; import { Page } from "~/models/utils";
import { SeedVideo, Video } from "~/models/video"; import { Guesses, SeedVideo, Video } from "~/models/video";
import { comment } from "~/utils"; import { comment } from "~/utils";
import { computeVideoSlug } from "./seed/insert/entries"; import { computeVideoSlug } from "./seed/insert/entries";
import { updateAvailableCount } from "./seed/insert/shows"; import { updateAvailableCount } from "./seed/insert/shows";
@ -27,6 +27,56 @@ export const videosH = new Elysia({ prefix: "/videos", tags: ["videos"] })
"created-videos": t.Array(CreatedVideo), "created-videos": t.Array(CreatedVideo),
error: t.Object({}), error: t.Object({}),
}) })
.get(
"",
async () => {
const years = db.$with("years").as(
db
.select({
guess: sql`${videos.guess}->>'title'`.as("guess"),
year: sql`coalesce(year, 'unknown')`.as("year"),
id: shows.id,
slug: shows.slug,
})
.from(videos)
.leftJoin(
sql`jsonb_array_elements_text(${videos.guess}->'year') as year`,
sql`true`,
)
.innerJoin(entryVideoJoin, eq(entryVideoJoin.videoPk, videos.pk))
.innerJoin(entries, eq(entries.pk, entryVideoJoin.entryPk))
.innerJoin(shows, eq(shows.pk, entries.showPk)),
);
const guess = db.$with("guess").as(
db
.select({
guess: years.guess,
years: jsonbObjectAgg(
years.year,
jsonbBuildObject({ id: years.id, slug: years.slug }),
).as("years"),
})
.from(years)
.groupBy(years.guess),
);
const [{ guesses }] = await db
.with(years, guess)
.select({ guesses: jsonbObjectAgg<Guesses["guesses"]>(guess.guess, guess.years) })
.from(guess);
const paths = await db.select({ path: videos.path }).from(videos);
return { paths: paths.map((x) => x.path), guesses };
},
{
detail: { description: "Get all video registered & guessed made" },
response: {
200: Guesses,
},
},
)
.post( .post(
"", "",
async ({ body, error }) => { async ({ body, error }) => {

View File

@ -103,7 +103,7 @@ export const nullif = <T>(val: SQL<T> | Column, eq: SQL<T>) => {
return sql<T>`nullif(${val}, ${eq})`; return sql<T>`nullif(${val}, ${eq})`;
}; };
export const jsonbObjectAgg = <T>(key: SQLWrapper, value: SQL<T>) => { export const jsonbObjectAgg = <T>(key: SQLWrapper, value: SQL<T> | SQLWrapper) => {
return sql< return sql<
Record<string, T> Record<string, T>
>`jsonb_object_agg(${sql.join([key, value], sql.raw(","))})`; >`jsonb_object_agg(${sql.join([key, value], sql.raw(","))})`;

View File

@ -124,3 +124,34 @@ export const EmbeddedVideo = t.Omit(Video, ["guess", "createdAt", "updatedAt"]);
export type EmbeddedVideo = Prettify<typeof EmbeddedVideo.static>; export type EmbeddedVideo = Prettify<typeof EmbeddedVideo.static>;
registerExamples(Video, bubbleVideo); registerExamples(Video, bubbleVideo);
export const Guesses = t.Object({
paths: t.Array(t.String()),
guesses: t.Record(
t.String(),
t.Record(
t.Union([t.Literal("unknown"), t.String({ pattern: "[1-9][0-9]*" })]),
Resource(),
),
),
});
export type Guesses = typeof Guesses.static;
registerExamples(Guesses, {
paths: [
"/videos/Evangelion S01E02.mkv",
"/videos/Evangelion (1995) S01E26.mkv",
],
guesses: {
Evangelion: {
unknown: {
id: "43b742f5-9ce6-467d-ad29-74460624020a",
slug: "evangelion",
},
1995: {
id: "43b742f5-9ce6-467d-ad29-74460624020a",
slug: "evangelion",
},
},
},
});