mirror of
https://github.com/zoriya/Kyoo.git
synced 2026-05-24 08:02:26 -04:00
Add ?with=studios in movies & series
This commit is contained in:
@@ -141,8 +141,8 @@ export const insertEntries = async (
|
||||
.select(
|
||||
db
|
||||
.select({
|
||||
entry: sql<number>`vids.entryPk::integer`.as("entry"),
|
||||
video: sql`${videos.pk}`.as("video"),
|
||||
entryPk: sql<number>`vids.entryPk::integer`.as("entry"),
|
||||
videoPk: sql`${videos.pk}`.as("video"),
|
||||
slug: computeVideoSlug(
|
||||
sql`${show.slug}::text`,
|
||||
sql`vids.needRendering::boolean`,
|
||||
@@ -154,7 +154,7 @@ export const insertEntries = async (
|
||||
.onConflictDoNothing()
|
||||
.returning({
|
||||
slug: entryVideoJoin.slug,
|
||||
entryPk: entryVideoJoin.entry,
|
||||
entryPk: entryVideoJoin.entryPk,
|
||||
});
|
||||
|
||||
return retEntries.map((entry) => ({
|
||||
|
||||
@@ -48,7 +48,7 @@ export const insertStudios = async (seed: SeedStudio[], showPk: number) => {
|
||||
|
||||
await tx
|
||||
.insert(showStudioJoin)
|
||||
.values(ret.map((studio) => ({ show: showPk, studio: studio.pk })))
|
||||
.values(ret.map((studio) => ({ showPk: showPk, studioPk: studio.pk })))
|
||||
.onConflictDoNothing();
|
||||
return ret;
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { StaticDecode } from "@sinclair/typebox";
|
||||
import { type SQL, and, eq, sql } from "drizzle-orm";
|
||||
import { db } from "~/db";
|
||||
import { showTranslations, shows } from "~/db/schema";
|
||||
import { showTranslations, shows, studioTranslations } from "~/db/schema";
|
||||
import { getColumns, sqlarr } from "~/db/utils";
|
||||
import type { MovieStatus } from "~/models/movie";
|
||||
import { SerieStatus } from "~/models/serie";
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
Sort,
|
||||
isUuid,
|
||||
keysetPaginate,
|
||||
selectTranslationQuery,
|
||||
sortToSql,
|
||||
} from "~/models/utils";
|
||||
|
||||
@@ -130,7 +131,7 @@ export async function getShow(
|
||||
}: {
|
||||
languages: string[];
|
||||
preferOriginal: boolean | undefined;
|
||||
relations: ("translations" | "videos")[];
|
||||
relations: ("translations" | "studios" | "videos")[];
|
||||
filters: SQL | undefined;
|
||||
},
|
||||
) {
|
||||
@@ -141,18 +142,7 @@ export async function getShow(
|
||||
},
|
||||
where: and(isUuid(id) ? eq(shows.id, id) : eq(shows.slug, id), filters),
|
||||
with: {
|
||||
selectedTranslation: {
|
||||
columns: {
|
||||
pk: false,
|
||||
},
|
||||
where: !languages.includes("*")
|
||||
? eq(showTranslations.language, sql`any(${sqlarr(languages)})`)
|
||||
: undefined,
|
||||
orderBy: [
|
||||
sql`array_position(${sqlarr(languages)}, ${showTranslations.language})`,
|
||||
],
|
||||
limit: 1,
|
||||
},
|
||||
selectedTranslation: selectTranslationQuery(showTranslations, languages),
|
||||
originalTranslation: {
|
||||
columns: {
|
||||
poster: true,
|
||||
@@ -175,6 +165,23 @@ export async function getShow(
|
||||
},
|
||||
},
|
||||
}),
|
||||
...(relations.includes("studios") && {
|
||||
studios: {
|
||||
with: {
|
||||
studio: {
|
||||
columns: {
|
||||
pk: false,
|
||||
},
|
||||
with: {
|
||||
selectedTranslation: selectTranslationQuery(
|
||||
studioTranslations,
|
||||
languages,
|
||||
),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
});
|
||||
if (!ret) return null;
|
||||
@@ -198,6 +205,12 @@ export async function getShow(
|
||||
),
|
||||
),
|
||||
}),
|
||||
...(ret.studios && {
|
||||
studios: ret.studios.map((x: any) => ({
|
||||
...x.studio,
|
||||
...x.studio.selectedTranslation[0],
|
||||
})),
|
||||
}),
|
||||
};
|
||||
return { show, language: translation.language };
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ export const movies = new Elysia({ prefix: "/movies", tags: ["movies"] })
|
||||
preferOriginal: t.Optional(
|
||||
t.Boolean({ description: desc.preferOriginal }),
|
||||
),
|
||||
with: t.Array(t.UnionEnum(["translations", "videos"]), {
|
||||
with: t.Array(t.UnionEnum(["translations", "studios", "videos"]), {
|
||||
default: [],
|
||||
description: "Include related resources in the response.",
|
||||
}),
|
||||
|
||||
@@ -65,7 +65,7 @@ export const series = new Elysia({ prefix: "/series", tags: ["series"] })
|
||||
preferOriginal: t.Optional(
|
||||
t.Boolean({ description: desc.preferOriginal }),
|
||||
),
|
||||
with: t.Array(t.UnionEnum(["translations"]), {
|
||||
with: t.Array(t.UnionEnum(["translations", "studios"]), {
|
||||
default: [],
|
||||
description: "Include related resources in the response.",
|
||||
}),
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
isUuid,
|
||||
keysetPaginate,
|
||||
processLanguages,
|
||||
selectTranslationQuery,
|
||||
sortToSql,
|
||||
} from "~/models/utils";
|
||||
import { desc } from "~/models/utils/descriptions";
|
||||
@@ -47,16 +48,10 @@ export const studiosH = new Elysia({ prefix: "/studios", tags: ["studios"] })
|
||||
const ret = await db.query.studios.findFirst({
|
||||
where: isUuid(id) ? eq(studios.id, id) : eq(studios.slug, id),
|
||||
with: {
|
||||
selectedTranslation: {
|
||||
columns: { pk: false },
|
||||
where: !languages.includes("*")
|
||||
? eq(studioTranslations.language, sql`any(${sqlarr(langs)})`)
|
||||
: undefined,
|
||||
orderBy: [
|
||||
sql`array_position(${sqlarr(langs)}, ${studioTranslations.language})`,
|
||||
],
|
||||
limit: 1,
|
||||
},
|
||||
selectedTranslation: selectTranslationQuery(
|
||||
studioTranslations,
|
||||
langs,
|
||||
),
|
||||
...(relations.includes("translations") && {
|
||||
translations: {
|
||||
columns: {
|
||||
@@ -150,7 +145,7 @@ export const studiosH = new Elysia({ prefix: "/studios", tags: ["studios"] })
|
||||
.get(
|
||||
"",
|
||||
async ({
|
||||
query: { limit, after, query, sort, filter },
|
||||
query: { limit, after, query, sort },
|
||||
headers: { "accept-language": languages },
|
||||
request: { url },
|
||||
}) => {
|
||||
@@ -271,8 +266,8 @@ export const studiosH = new Elysia({ prefix: "/studios", tags: ["studios"] })
|
||||
.from(showStudioJoin)
|
||||
.where(
|
||||
and(
|
||||
eq(showStudioJoin.studio, studio.pk),
|
||||
eq(showStudioJoin.show, shows.pk),
|
||||
eq(showStudioJoin.studioPk, studio.pk),
|
||||
eq(showStudioJoin.showPk, shows.pk),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -331,8 +326,8 @@ export const studiosH = new Elysia({ prefix: "/studios", tags: ["studios"] })
|
||||
.from(showStudioJoin)
|
||||
.where(
|
||||
and(
|
||||
eq(showStudioJoin.studio, studio.pk),
|
||||
eq(showStudioJoin.show, shows.pk),
|
||||
eq(showStudioJoin.studioPk, studio.pk),
|
||||
eq(showStudioJoin.showPk, shows.pk),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -391,8 +386,8 @@ export const studiosH = new Elysia({ prefix: "/studios", tags: ["studios"] })
|
||||
.from(showStudioJoin)
|
||||
.where(
|
||||
and(
|
||||
eq(showStudioJoin.studio, studio.pk),
|
||||
eq(showStudioJoin.show, shows.pk),
|
||||
eq(showStudioJoin.studioPk, studio.pk),
|
||||
eq(showStudioJoin.showPk, shows.pk),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -42,78 +42,77 @@ export const videosH = new Elysia({ prefix: "/videos", tags: ["videos"] })
|
||||
return error(201, oldRet);
|
||||
|
||||
// TODO: this is a huge untested wip
|
||||
// biome-ignore lint/correctness/noUnreachable: leave me alone
|
||||
const vidsI = db.$with("vidsI").as(
|
||||
db.insert(videos).values(body).onConflictDoNothing().returning({
|
||||
pk: videos.pk,
|
||||
id: videos.id,
|
||||
path: videos.path,
|
||||
guess: videos.guess,
|
||||
}),
|
||||
);
|
||||
|
||||
const findEntriesQ = db
|
||||
.select({
|
||||
guess: videos.guess,
|
||||
entryPk: entries.pk,
|
||||
showSlug: shows.slug,
|
||||
// TODO: handle extras here
|
||||
// guessit can't know if an episode is a special or not. treat specials like a normal episode.
|
||||
kind: sql`
|
||||
case when ${entries.kind} = 'movie' then 'movie' else 'episode' end
|
||||
`.as("kind"),
|
||||
season: entries.seasonNumber,
|
||||
episode: entries.episodeNumber,
|
||||
})
|
||||
.from(entries)
|
||||
.leftJoin(entryVideoJoin, eq(entryVideoJoin.entry, entries.pk))
|
||||
.leftJoin(videos, eq(videos.pk, entryVideoJoin.video))
|
||||
.leftJoin(shows, eq(shows.pk, entries.showPk))
|
||||
.as("find_entries");
|
||||
|
||||
const hasRenderingQ = db
|
||||
.select()
|
||||
.from(entryVideoJoin)
|
||||
.where(eq(entryVideoJoin.entry, findEntriesQ.entryPk));
|
||||
|
||||
const ret = await db
|
||||
.with(vidsI)
|
||||
.insert(entryVideoJoin)
|
||||
.select(
|
||||
db
|
||||
.select({
|
||||
entry: findEntriesQ.entryPk,
|
||||
video: vidsI.pk,
|
||||
slug: computeVideoSlug(
|
||||
findEntriesQ.showSlug,
|
||||
sql`exists(${hasRenderingQ})`,
|
||||
),
|
||||
})
|
||||
.from(vidsI)
|
||||
.leftJoin(
|
||||
findEntriesQ,
|
||||
and(
|
||||
eq(
|
||||
sql`${findEntriesQ.guess}->'title'`,
|
||||
sql`${vidsI.guess}->'title'`,
|
||||
),
|
||||
// TODO: find if @> with a jsonb created on the fly is
|
||||
// better than multiples checks
|
||||
sql`${vidsI.guess} @> {"kind": }::jsonb`,
|
||||
inArray(findEntriesQ.kind, sql`${vidsI.guess}->'type'`),
|
||||
inArray(findEntriesQ.episode, sql`${vidsI.guess}->'episode'`),
|
||||
inArray(findEntriesQ.season, sql`${vidsI.guess}->'season'`),
|
||||
),
|
||||
),
|
||||
)
|
||||
.onConflictDoNothing()
|
||||
.returning({
|
||||
slug: entryVideoJoin.slug,
|
||||
entryPk: entryVideoJoin.entry,
|
||||
id: vidsI.id,
|
||||
path: vidsI.path,
|
||||
});
|
||||
return error(201, ret as any);
|
||||
// const vidsI = db.$with("vidsI").as(
|
||||
// db.insert(videos).values(body).onConflictDoNothing().returning({
|
||||
// pk: videos.pk,
|
||||
// id: videos.id,
|
||||
// path: videos.path,
|
||||
// guess: videos.guess,
|
||||
// }),
|
||||
// );
|
||||
//
|
||||
// const findEntriesQ = db
|
||||
// .select({
|
||||
// guess: videos.guess,
|
||||
// entryPk: entries.pk,
|
||||
// showSlug: shows.slug,
|
||||
// // TODO: handle extras here
|
||||
// // guessit can't know if an episode is a special or not. treat specials like a normal episode.
|
||||
// kind: sql`
|
||||
// case when ${entries.kind} = 'movie' then 'movie' else 'episode' end
|
||||
// `.as("kind"),
|
||||
// season: entries.seasonNumber,
|
||||
// episode: entries.episodeNumber,
|
||||
// })
|
||||
// .from(entries)
|
||||
// .leftJoin(entryVideoJoin, eq(entryVideoJoin.entry, entries.pk))
|
||||
// .leftJoin(videos, eq(videos.pk, entryVideoJoin.video))
|
||||
// .leftJoin(shows, eq(shows.pk, entries.showPk))
|
||||
// .as("find_entries");
|
||||
//
|
||||
// const hasRenderingQ = db
|
||||
// .select()
|
||||
// .from(entryVideoJoin)
|
||||
// .where(eq(entryVideoJoin.entry, findEntriesQ.entryPk));
|
||||
//
|
||||
// const ret = await db
|
||||
// .with(vidsI)
|
||||
// .insert(entryVideoJoin)
|
||||
// .select(
|
||||
// db
|
||||
// .select({
|
||||
// entry: findEntriesQ.entryPk,
|
||||
// video: vidsI.pk,
|
||||
// slug: computeVideoSlug(
|
||||
// findEntriesQ.showSlug,
|
||||
// sql`exists(${hasRenderingQ})`,
|
||||
// ),
|
||||
// })
|
||||
// .from(vidsI)
|
||||
// .leftJoin(
|
||||
// findEntriesQ,
|
||||
// and(
|
||||
// eq(
|
||||
// sql`${findEntriesQ.guess}->'title'`,
|
||||
// sql`${vidsI.guess}->'title'`,
|
||||
// ),
|
||||
// // TODO: find if @> with a jsonb created on the fly is
|
||||
// // better than multiples checks
|
||||
// sql`${vidsI.guess} @> {"kind": }::jsonb`,
|
||||
// inArray(findEntriesQ.kind, sql`${vidsI.guess}->'type'`),
|
||||
// inArray(findEntriesQ.episode, sql`${vidsI.guess}->'episode'`),
|
||||
// inArray(findEntriesQ.season, sql`${vidsI.guess}->'season'`),
|
||||
// ),
|
||||
// ),
|
||||
// )
|
||||
// .onConflictDoNothing()
|
||||
// .returning({
|
||||
// slug: entryVideoJoin.slug,
|
||||
// entryPk: entryVideoJoin.entry,
|
||||
// id: vidsI.id,
|
||||
// path: vidsI.path,
|
||||
// });
|
||||
// return error(201, ret as any);
|
||||
},
|
||||
{
|
||||
body: t.Array(SeedVideo),
|
||||
|
||||
Reference in New Issue
Block a user