mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-24 02:02:36 -04:00
Handle image in jsonb
This commit is contained in:
parent
6e642db7db
commit
71b57c50e7
@ -1,13 +1,12 @@
|
|||||||
import { mkdir, writeFile } from "node:fs/promises";
|
import { mkdir, writeFile } from "node:fs/promises";
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import { encode } from "blurhash";
|
import { encode } from "blurhash";
|
||||||
import { eq, sql } from "drizzle-orm";
|
import { type SQLWrapper, eq, sql } from "drizzle-orm";
|
||||||
import type { PgColumn } from "drizzle-orm/pg-core";
|
import type { PgColumn, PgTable } from "drizzle-orm/pg-core";
|
||||||
import { version } from "package.json";
|
import { version } from "package.json";
|
||||||
import type { PoolClient } from "pg";
|
import type { PoolClient } from "pg";
|
||||||
import sharp from "sharp";
|
import sharp from "sharp";
|
||||||
import { type Transaction, db } from "~/db";
|
import { type Transaction, db } from "~/db";
|
||||||
import * as schema from "~/db/schema";
|
|
||||||
import { mqueue } from "~/db/schema/queue";
|
import { mqueue } from "~/db/schema/queue";
|
||||||
import type { Image } from "~/models/utils";
|
import type { Image } from "~/models/utils";
|
||||||
|
|
||||||
@ -21,30 +20,38 @@ type ImageTask = {
|
|||||||
column: string;
|
column: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
type ImageTaskC = {
|
|
||||||
url: string;
|
|
||||||
column: PgColumn;
|
|
||||||
};
|
|
||||||
|
|
||||||
// this will only push a task to the image downloader service and not download it instantly.
|
// this will only push a task to the image downloader service and not download it instantly.
|
||||||
// this is both done to prevent to many requests to be sent at once and to make sure POST
|
// this is both done to prevent to many requests to be sent at once and to make sure POST
|
||||||
// requests are not blocked by image downloading or blurhash calculation
|
// requests are not blocked by image downloading or blurhash calculation
|
||||||
export const enqueueImage = async (
|
export const enqueueOptImage = async (
|
||||||
tx: Transaction,
|
tx: Transaction,
|
||||||
img: ImageTaskC,
|
img:
|
||||||
): Promise<Image> => {
|
| { url: string | null; column: PgColumn }
|
||||||
|
| { url: string | null; table: PgTable; column: SQLWrapper },
|
||||||
|
): Promise<Image | null> => {
|
||||||
|
if (!img.url) return null;
|
||||||
|
|
||||||
const hasher = new Bun.CryptoHasher("sha256");
|
const hasher = new Bun.CryptoHasher("sha256");
|
||||||
hasher.update(img.url);
|
hasher.update(img.url);
|
||||||
const id = hasher.digest().toString("hex");
|
const id = hasher.digest().toString("hex");
|
||||||
|
|
||||||
|
const message: ImageTask =
|
||||||
|
"table" in img
|
||||||
|
? {
|
||||||
|
id,
|
||||||
|
url: img.url,
|
||||||
|
table: img.table._.name,
|
||||||
|
column: img.column.getSQL().sql,
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
id,
|
||||||
|
url: img.url,
|
||||||
|
table: img.column.table._.name,
|
||||||
|
column: img.column,
|
||||||
|
};
|
||||||
await tx.insert(mqueue).values({
|
await tx.insert(mqueue).values({
|
||||||
kind: "image",
|
kind: "image",
|
||||||
message: {
|
message,
|
||||||
id,
|
|
||||||
url: img.url,
|
|
||||||
table: img.column.table._.name,
|
|
||||||
column: img.column.name,
|
|
||||||
} satisfies ImageTask,
|
|
||||||
});
|
});
|
||||||
await tx.execute(sql`notify image`);
|
await tx.execute(sql`notify image`);
|
||||||
|
|
||||||
@ -55,14 +62,6 @@ export const enqueueImage = async (
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const enqueueOptImage = async (
|
|
||||||
tx: Transaction,
|
|
||||||
img: { url: string | null; column: PgColumn },
|
|
||||||
): Promise<Image | null> => {
|
|
||||||
if (!img.url) return null;
|
|
||||||
return await enqueueImage(tx, { url: img.url, column: img.column });
|
|
||||||
};
|
|
||||||
|
|
||||||
export const processImages = async () => {
|
export const processImages = async () => {
|
||||||
async function processOne() {
|
async function processOne() {
|
||||||
return await db.transaction(async (tx) => {
|
return await db.transaction(async (tx) => {
|
||||||
@ -78,19 +77,14 @@ export const processImages = async () => {
|
|||||||
|
|
||||||
const img = item.message as ImageTask;
|
const img = item.message as ImageTask;
|
||||||
const blurhash = await downloadImage(img.id, img.url);
|
const blurhash = await downloadImage(img.id, img.url);
|
||||||
|
const ret: Image = { id: img.id, source: img.url, blurhash };
|
||||||
|
|
||||||
const table = schema[img.table as keyof typeof schema] as any;
|
const table = sql.raw(img.table);
|
||||||
|
const column = sql.raw(img.column);
|
||||||
|
|
||||||
await tx
|
await tx.execute(sql`
|
||||||
.update(table)
|
update ${table} set ${column} = ${ret} where ${column}->'id' = '${item.id}'
|
||||||
.set({
|
`);
|
||||||
[img.column]: {
|
|
||||||
id: img.id,
|
|
||||||
source: img.url,
|
|
||||||
blurhash,
|
|
||||||
} satisfies Image,
|
|
||||||
})
|
|
||||||
.where(eq(sql`${table[img.column]}->'id'`, img.id));
|
|
||||||
|
|
||||||
await tx.delete(mqueue).where(eq(mqueue.id, item.id));
|
await tx.delete(mqueue).where(eq(mqueue.id, item.id));
|
||||||
return true;
|
return true;
|
||||||
|
@ -30,19 +30,23 @@ export const insertShow = async (
|
|||||||
...original,
|
...original,
|
||||||
poster: await enqueueOptImage(tx, {
|
poster: await enqueueOptImage(tx, {
|
||||||
url: original.poster,
|
url: original.poster,
|
||||||
column: shows.original.poster,
|
table: shows,
|
||||||
|
column: sql`${shows.original}['poster']`,
|
||||||
}),
|
}),
|
||||||
thumbnail: await enqueueOptImage(tx, {
|
thumbnail: await enqueueOptImage(tx, {
|
||||||
url: original.thumbnail,
|
url: original.thumbnail,
|
||||||
column: shows.original.thumbnail,
|
table: shows,
|
||||||
|
column: sql`${shows.original}['thumbnail']`,
|
||||||
}),
|
}),
|
||||||
banner: await enqueueOptImage(tx, {
|
banner: await enqueueOptImage(tx, {
|
||||||
url: original.banner,
|
url: original.banner,
|
||||||
column: shows.original.banner,
|
table: shows,
|
||||||
|
column: sql`${shows.original}['banner']`,
|
||||||
}),
|
}),
|
||||||
logo: await enqueueOptImage(tx, {
|
logo: await enqueueOptImage(tx, {
|
||||||
url: original.logo,
|
url: original.logo,
|
||||||
column: shows.original.logo,
|
table: shows,
|
||||||
|
column: sql`${shows.original}['logo']`,
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
const ret = await insertBaseShow(tx, { ...show, original: orig });
|
const ret = await insertBaseShow(tx, { ...show, original: orig });
|
||||||
|
@ -40,7 +40,8 @@ export const insertStaff = async (
|
|||||||
...x.character,
|
...x.character,
|
||||||
image: await enqueueOptImage(tx, {
|
image: await enqueueOptImage(tx, {
|
||||||
url: x.character.image,
|
url: x.character.image,
|
||||||
column: roles.character.image,
|
table: roles,
|
||||||
|
column: `${roles.character}['image']`,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
})),
|
})),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user