57 lines
1.3 KiB
TypeScript
57 lines
1.3 KiB
TypeScript
import { z } from "zod";
|
|
|
|
import { getDb } from "@tline/db";
|
|
|
|
const paramsSchema = z.object({ id: z.string().uuid() });
|
|
|
|
type DbLike = ReturnType<typeof getDb>;
|
|
|
|
export async function handleGetDupes(input: {
|
|
params: { id: string };
|
|
db?: DbLike;
|
|
}): Promise<{ status: number; body: unknown }> {
|
|
const paramsParsed = paramsSchema.safeParse(input.params);
|
|
if (!paramsParsed.success) {
|
|
return {
|
|
status: 400,
|
|
body: { error: "invalid_params", issues: paramsParsed.error.issues },
|
|
};
|
|
}
|
|
|
|
const db = (input.db ?? getDb()) as DbLike;
|
|
const hashRows = await db<
|
|
{
|
|
bucket: string;
|
|
sha256: string;
|
|
}[]
|
|
>`
|
|
select bucket, sha256
|
|
from asset_hashes
|
|
where asset_id = ${paramsParsed.data.id}
|
|
limit 1
|
|
`;
|
|
|
|
const hash = hashRows[0];
|
|
if (!hash) {
|
|
return { status: 200, body: { items: [] } };
|
|
}
|
|
|
|
const dupes = await db<
|
|
{
|
|
id: string;
|
|
media_type: "image" | "video";
|
|
status: "new" | "processing" | "ready" | "failed";
|
|
}[]
|
|
>`
|
|
select a.id, a.media_type, a.status
|
|
from assets a
|
|
join asset_hashes h on h.asset_id = a.id
|
|
where h.bucket = ${hash.bucket}
|
|
and h.sha256 = ${hash.sha256}
|
|
and a.id <> ${paramsParsed.data.id}
|
|
order by a.id asc
|
|
`;
|
|
|
|
return { status: 200, body: { items: dupes } };
|
|
}
|