mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-12-06 06:36:25 +00:00
Prevent duplicated staff members
This commit is contained in:
@@ -52,8 +52,7 @@ export const base = new Elysia({ name: "base" })
|
|||||||
console.error(code, error);
|
console.error(code, error);
|
||||||
return {
|
return {
|
||||||
status: 500,
|
status: 500,
|
||||||
message: "message" in error ? (error?.message ?? code) : code,
|
message: "Internal server error",
|
||||||
details: error,
|
|
||||||
} as KError;
|
} as KError;
|
||||||
})
|
})
|
||||||
.get("/health", () => ({ status: "healthy" }) as const, {
|
.get("/health", () => ({ status: "healthy" }) as const, {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { roles, staff } from "~/db/schema";
|
|||||||
import { conflictUpdateAllExcept, unnestValues } from "~/db/utils";
|
import { conflictUpdateAllExcept, unnestValues } from "~/db/utils";
|
||||||
import type { SeedStaff } from "~/models/staff";
|
import type { SeedStaff } from "~/models/staff";
|
||||||
import { record } from "~/otel";
|
import { record } from "~/otel";
|
||||||
|
import { uniqBy } from "~/utils";
|
||||||
import { enqueueOptImage, flushImageQueue, type ImageTask } from "../images";
|
import { enqueueOptImage, flushImageQueue, type ImageTask } from "../images";
|
||||||
|
|
||||||
export const insertStaff = record(
|
export const insertStaff = record(
|
||||||
@@ -13,13 +14,16 @@ export const insertStaff = record(
|
|||||||
|
|
||||||
return await db.transaction(async (tx) => {
|
return await db.transaction(async (tx) => {
|
||||||
const imgQueue: ImageTask[] = [];
|
const imgQueue: ImageTask[] = [];
|
||||||
const people = seed.map((x) => ({
|
const people = uniqBy(
|
||||||
...x.staff,
|
seed.map((x) => ({
|
||||||
image: enqueueOptImage(imgQueue, {
|
...x.staff,
|
||||||
url: x.staff.image,
|
image: enqueueOptImage(imgQueue, {
|
||||||
column: staff.image,
|
url: x.staff.image,
|
||||||
}),
|
column: staff.image,
|
||||||
}));
|
}),
|
||||||
|
})),
|
||||||
|
(x) => x.slug,
|
||||||
|
);
|
||||||
const ret = await tx
|
const ret = await tx
|
||||||
.insert(staff)
|
.insert(staff)
|
||||||
.select(unnestValues(people, staff))
|
.select(unnestValues(people, staff))
|
||||||
@@ -36,7 +40,7 @@ export const insertStaff = record(
|
|||||||
|
|
||||||
const rval = seed.map((x, i) => ({
|
const rval = seed.map((x, i) => ({
|
||||||
showPk,
|
showPk,
|
||||||
staffPk: ret[i].pk,
|
staffPk: ret.find(y => y.slug === x.staff.slug)!.pk,
|
||||||
kind: x.kind,
|
kind: x.kind,
|
||||||
order: i,
|
order: i,
|
||||||
character: {
|
character: {
|
||||||
|
|||||||
@@ -831,6 +831,9 @@ export const videosWriteH = new Elysia({ prefix: "/videos", tags: ["videos"] })
|
|||||||
.post(
|
.post(
|
||||||
"",
|
"",
|
||||||
async ({ body, status }) => {
|
async ({ body, status }) => {
|
||||||
|
if (body.length === 0) {
|
||||||
|
return status(422, { status: 422, message: "No videos" });
|
||||||
|
}
|
||||||
return await db.transaction(async (tx) => {
|
return await db.transaction(async (tx) => {
|
||||||
let vids: { pk: number; id: string; path: string; guess: Guess }[] = [];
|
let vids: { pk: number; id: string; path: string; guess: Guess }[] = [];
|
||||||
try {
|
try {
|
||||||
@@ -925,6 +928,7 @@ export const videosWriteH = new Elysia({ prefix: "/videos", tags: ["videos"] })
|
|||||||
description:
|
description:
|
||||||
"Invalid rendering specified. (conflicts with an existing video)",
|
"Invalid rendering specified. (conflicts with an existing video)",
|
||||||
},
|
},
|
||||||
|
422: KError,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ export const seasonRelations = relations(seasons, ({ one, many }) => ({
|
|||||||
|
|
||||||
export const seasonTrRelations = relations(seasonTranslations, ({ one }) => ({
|
export const seasonTrRelations = relations(seasonTranslations, ({ one }) => ({
|
||||||
season: one(seasons, {
|
season: one(seasons, {
|
||||||
relationName: "season_translation",
|
relationName: "season_translations",
|
||||||
fields: [seasonTranslations.pk],
|
fields: [seasonTranslations.pk],
|
||||||
references: [seasons.pk],
|
references: [seasons.pk],
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -28,3 +28,13 @@ export function getFile(path: string): BunFile | S3File {
|
|||||||
|
|
||||||
return Bun.file(path);
|
return Bun.file(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function uniqBy<T>(a: T[], key: (val: T) => string) {
|
||||||
|
const seen: Record<string, boolean> = {};
|
||||||
|
return a.filter((item) => {
|
||||||
|
const k = key(item);
|
||||||
|
if (seen[k]) return false;
|
||||||
|
seen[k] = true;
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@@ -104,4 +104,60 @@ describe("Serie seeding", () => {
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("Can create a serie with quotes", async () => {
|
||||||
|
const [resp, body] = await createSerie({
|
||||||
|
...madeInAbyss,
|
||||||
|
slug: "quote-test",
|
||||||
|
seasons: [
|
||||||
|
{
|
||||||
|
...madeInAbyss.seasons[0],
|
||||||
|
translations: {
|
||||||
|
en: {
|
||||||
|
...madeInAbyss.seasons[0].translations.en,
|
||||||
|
name: "Season'1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
...madeInAbyss.seasons[1],
|
||||||
|
translations: {
|
||||||
|
en: {
|
||||||
|
...madeInAbyss.seasons[0].translations.en,
|
||||||
|
name: 'Season"2',
|
||||||
|
description: `This's """""quote, idk'''''`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
expectStatus(resp, body).toBe(201);
|
||||||
|
expect(body.id).toBeString();
|
||||||
|
expect(body.slug).toBe("quote-test");
|
||||||
|
|
||||||
|
const ret = await db.query.shows.findFirst({
|
||||||
|
where: eq(shows.id, body.id),
|
||||||
|
with: {
|
||||||
|
seasons: {
|
||||||
|
orderBy: seasons.seasonNumber,
|
||||||
|
with: { translations: true },
|
||||||
|
},
|
||||||
|
entries: {
|
||||||
|
with: {
|
||||||
|
translations: true,
|
||||||
|
evj: { with: { video: true } },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(ret).not.toBeNull();
|
||||||
|
expect(ret!.seasons).toBeArrayOfSize(2);
|
||||||
|
expect(ret!.seasons[0].translations[0].name).toBe("Season'1");
|
||||||
|
expect(ret!.seasons[1].translations[0].name).toBe('Season"2');
|
||||||
|
expect(ret!.entries).toBeArrayOfSize(
|
||||||
|
madeInAbyss.entries.length + madeInAbyss.extras.length,
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "ES2021",
|
"target": "ES2022",
|
||||||
"module": "ES2022",
|
"module": "ES2022",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
|
|||||||
Reference in New Issue
Block a user