mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-23 17:52:36 -04:00
Add image downloading test
This commit is contained in:
parent
0a729ccf75
commit
51558db1b2
1
api/.gitignore
vendored
1
api/.gitignore
vendored
@ -1,2 +1,3 @@
|
||||
node_modules
|
||||
**/*.bun
|
||||
images
|
||||
|
@ -1,18 +1,20 @@
|
||||
import { mkdir, writeFile } from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { encode } from "blurhash";
|
||||
import { SQL, type SQLWrapper, eq, getTableName, sql } from "drizzle-orm";
|
||||
import type { PgColumn, PgTable } from "drizzle-orm/pg-core";
|
||||
import { type SQL, eq, is, sql } from "drizzle-orm";
|
||||
import { PgColumn, type PgTable } from "drizzle-orm/pg-core";
|
||||
import { version } from "package.json";
|
||||
import type { PoolClient } from "pg";
|
||||
import sharp from "sharp";
|
||||
import { type Transaction, db } from "~/db";
|
||||
import { mqueue } from "~/db/schema/queue";
|
||||
import { mqueue } from "~/db/schema/mqueue";
|
||||
import type { Image } from "~/models/utils";
|
||||
|
||||
export const imageDir = process.env.IMAGES_PATH ?? "./images";
|
||||
await mkdir(imageDir, { recursive: true });
|
||||
|
||||
export const defaultBlurhash = "000000";
|
||||
|
||||
type ImageTask = {
|
||||
id: string;
|
||||
url: string;
|
||||
@ -35,19 +37,34 @@ export const enqueueOptImage = async (
|
||||
hasher.update(img.url);
|
||||
const id = hasher.digest().toString("hex");
|
||||
|
||||
const cleanupColumn = (column: SQL) =>
|
||||
// @ts-expect-error dialect is private
|
||||
db.dialect.sqlToQuery(
|
||||
sql.join(
|
||||
column.queryChunks.map((x) => {
|
||||
if (is(x, PgColumn)) {
|
||||
return sql.identifier(x.name);
|
||||
}
|
||||
return x;
|
||||
}),
|
||||
),
|
||||
).sql;
|
||||
|
||||
const message: ImageTask =
|
||||
"table" in img
|
||||
? {
|
||||
id,
|
||||
url: img.url,
|
||||
table: getTableName(img.table),
|
||||
column: db.execute(img.column).getQuery().sql,
|
||||
// @ts-expect-error dialect is private
|
||||
table: db.dialect.sqlToQuery(sql`${img.table}`).sql,
|
||||
column: cleanupColumn(img.column),
|
||||
}
|
||||
: {
|
||||
id,
|
||||
url: img.url,
|
||||
table: getTableName(img.column.table),
|
||||
column: img.column.name,
|
||||
// @ts-expect-error dialect is private
|
||||
table: db.dialect.sqlToQuery(sql`${img.column.table}`).sql,
|
||||
column: sql.identifier(img.column.name).value,
|
||||
};
|
||||
await tx.insert(mqueue).values({
|
||||
kind: "image",
|
||||
@ -58,7 +75,7 @@ export const enqueueOptImage = async (
|
||||
return {
|
||||
id,
|
||||
source: img.url,
|
||||
blurhash: "",
|
||||
blurhash: defaultBlurhash,
|
||||
};
|
||||
};
|
||||
|
||||
@ -83,7 +100,7 @@ export const processImages = async () => {
|
||||
const column = sql.raw(img.column);
|
||||
|
||||
await tx.execute(sql`
|
||||
update ${table} set ${column} = ${ret} where ${column}->'id' = '${item.id}'
|
||||
update ${table} set ${column} = ${ret} where ${column}->'id' = ${sql.raw(`'"${img.id}"'::jsonb`)}
|
||||
`);
|
||||
|
||||
await tx.delete(mqueue).where(eq(mqueue.id, item.id));
|
||||
@ -112,6 +129,7 @@ export const processImages = async () => {
|
||||
|
||||
// start processing old tasks
|
||||
await processAll();
|
||||
return () => client.release(true);
|
||||
};
|
||||
|
||||
async function downloadImage(id: string, url: string): Promise<string> {
|
||||
@ -144,6 +162,7 @@ async function downloadImage(id: string, url: string): Promise<string> {
|
||||
|
||||
const { data, info } = await image
|
||||
.resize(32, 32, { fit: "inside" })
|
||||
.ensureAlpha()
|
||||
.raw()
|
||||
.toBuffer({ resolveWithObject: true });
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { t } from "elysia";
|
||||
import type { SeedSerie } from "~/models/serie";
|
||||
import { getYear } from "~/utils";
|
||||
import { enqueueOptImage } from "./images";
|
||||
import { insertCollection } from "./insert/collection";
|
||||
import { insertEntries } from "./insert/entries";
|
||||
import { insertSeasons } from "./insert/seasons";
|
||||
|
@ -4,3 +4,4 @@ export * from "./shows";
|
||||
export * from "./studios";
|
||||
export * from "./staff";
|
||||
export * from "./videos";
|
||||
export * from "./mqueue";
|
||||
|
@ -1,5 +1,6 @@
|
||||
import jwt from "@elysiajs/jwt";
|
||||
import { swagger } from "@elysiajs/swagger";
|
||||
import { processImages } from "./controllers/seed/images";
|
||||
import { migrate } from "./db";
|
||||
import { app } from "./elysia";
|
||||
import { comment } from "./utils";
|
||||
@ -23,6 +24,9 @@ if (!secret) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// run image processor task in background
|
||||
processImages();
|
||||
|
||||
app
|
||||
.use(jwt({ secret }))
|
||||
.use(
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { processImages } from "~/controllers/seed/images";
|
||||
import { db, migrate } from "~/db";
|
||||
import { shows, videos } from "~/db/schema";
|
||||
import { mqueue, shows, videos } from "~/db/schema";
|
||||
import { madeInAbyss, madeInAbyssVideo } from "~/models/examples";
|
||||
import { createSerie, createVideo, getSerie } from "./helpers";
|
||||
|
||||
@ -8,10 +9,16 @@ import { createSerie, createVideo, getSerie } from "./helpers";
|
||||
await migrate();
|
||||
await db.delete(shows);
|
||||
await db.delete(videos);
|
||||
await db.delete(mqueue);
|
||||
|
||||
const [_, vid] = await createVideo(madeInAbyssVideo);
|
||||
console.log(vid);
|
||||
const [__, ser] = await createSerie(madeInAbyss);
|
||||
console.log(ser);
|
||||
|
||||
await processImages();
|
||||
|
||||
const [___, got] = await getSerie(madeInAbyss.slug, { with: ["translations"] });
|
||||
console.log(got);
|
||||
|
||||
process.exit(0);
|
||||
|
31
api/tests/misc/images.test.ts
Normal file
31
api/tests/misc/images.test.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import { beforeAll, describe, expect, it } from "bun:test";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { defaultBlurhash, processImages } from "~/controllers/seed/images";
|
||||
import { db } from "~/db";
|
||||
import { mqueue, shows, staff, studios, videos } from "~/db/schema";
|
||||
import { madeInAbyss } from "~/models/examples";
|
||||
import { createSerie } from "../helpers";
|
||||
|
||||
beforeAll(async () => {
|
||||
await db.delete(shows);
|
||||
await db.delete(studios);
|
||||
await db.delete(staff);
|
||||
await db.delete(videos);
|
||||
await db.delete(mqueue);
|
||||
|
||||
await createSerie(madeInAbyss);
|
||||
const release = await processImages();
|
||||
// remove notifications to prevent other images to be downloaded (do not curl 20000 images for nothing)
|
||||
release();
|
||||
});
|
||||
|
||||
describe("images", () => {
|
||||
it("Create a serie download images", async () => {
|
||||
const ret = await db.query.shows.findFirst({
|
||||
where: eq(shows.slug, madeInAbyss.slug),
|
||||
});
|
||||
expect(ret!.slug).toBe(madeInAbyss.slug);
|
||||
expect(ret!.original.poster!.blurhash).toBeString();
|
||||
expect(ret!.original.poster!.blurhash).not.toBe(defaultBlurhash);
|
||||
});
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user