mirror of
				https://github.com/zoriya/Kyoo.git
				synced 2025-10-31 02:27:11 -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 path from "node:path"; | ||||
| import { encode } from "blurhash"; | ||||
| import { eq, sql } from "drizzle-orm"; | ||||
| import type { PgColumn } from "drizzle-orm/pg-core"; | ||||
| import { type SQLWrapper, eq, sql } from "drizzle-orm"; | ||||
| import type { PgColumn, 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 * as schema from "~/db/schema"; | ||||
| import { mqueue } from "~/db/schema/queue"; | ||||
| import type { Image } from "~/models/utils"; | ||||
| 
 | ||||
| @ -21,30 +20,38 @@ type ImageTask = { | ||||
| 	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 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
 | ||||
| export const enqueueImage = async ( | ||||
| export const enqueueOptImage = async ( | ||||
| 	tx: Transaction, | ||||
| 	img: ImageTaskC, | ||||
| ): Promise<Image> => { | ||||
| 	img: | ||||
| 		| { 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"); | ||||
| 	hasher.update(img.url); | ||||
| 	const id = hasher.digest().toString("hex"); | ||||
| 
 | ||||
| 	await tx.insert(mqueue).values({ | ||||
| 		kind: "image", | ||||
| 		message: { | ||||
| 	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.name, | ||||
| 		} satisfies ImageTask, | ||||
| 					column: img.column, | ||||
| 				}; | ||||
| 	await tx.insert(mqueue).values({ | ||||
| 		kind: "image", | ||||
| 		message, | ||||
| 	}); | ||||
| 	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 () => { | ||||
| 	async function processOne() { | ||||
| 		return await db.transaction(async (tx) => { | ||||
| @ -78,19 +77,14 @@ export const processImages = async () => { | ||||
| 
 | ||||
| 			const img = item.message as ImageTask; | ||||
| 			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 | ||||
| 				.update(table) | ||||
| 				.set({ | ||||
| 					[img.column]: { | ||||
| 						id: img.id, | ||||
| 						source: img.url, | ||||
| 						blurhash, | ||||
| 					} satisfies Image, | ||||
| 				}) | ||||
| 				.where(eq(sql`${table[img.column]}->'id'`, img.id)); | ||||
| 			await tx.execute(sql` | ||||
| 				update ${table} set ${column} = ${ret} where ${column}->'id' = '${item.id}' | ||||
| 			`);
 | ||||
| 
 | ||||
| 			await tx.delete(mqueue).where(eq(mqueue.id, item.id)); | ||||
| 			return true; | ||||
|  | ||||
| @ -30,19 +30,23 @@ export const insertShow = async ( | ||||
| 			...original, | ||||
| 			poster: await enqueueOptImage(tx, { | ||||
| 				url: original.poster, | ||||
| 				column: shows.original.poster, | ||||
| 				table: shows, | ||||
| 				column: sql`${shows.original}['poster']`, | ||||
| 			}), | ||||
| 			thumbnail: await enqueueOptImage(tx, { | ||||
| 				url: original.thumbnail, | ||||
| 				column: shows.original.thumbnail, | ||||
| 				table: shows, | ||||
| 				column: sql`${shows.original}['thumbnail']`, | ||||
| 			}), | ||||
| 			banner: await enqueueOptImage(tx, { | ||||
| 				url: original.banner, | ||||
| 				column: shows.original.banner, | ||||
| 				table: shows, | ||||
| 				column: sql`${shows.original}['banner']`, | ||||
| 			}), | ||||
| 			logo: await enqueueOptImage(tx, { | ||||
| 				url: original.logo, | ||||
| 				column: shows.original.logo, | ||||
| 				table: shows, | ||||
| 				column: sql`${shows.original}['logo']`, | ||||
| 			}), | ||||
| 		}; | ||||
| 		const ret = await insertBaseShow(tx, { ...show, original: orig }); | ||||
|  | ||||
| @ -40,7 +40,8 @@ export const insertStaff = async ( | ||||
| 					...x.character, | ||||
| 					image: await enqueueOptImage(tx, { | ||||
| 						url: x.character.image, | ||||
| 						column: roles.character.image, | ||||
| 						table: roles, | ||||
| 						column: `${roles.character}['image']`, | ||||
| 					}), | ||||
| 				}, | ||||
| 			})), | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user