feat(isac): add avatar oversight queue

This commit is contained in:
JB
2026-07-25 14:26:38 -04:00
parent 8079a75c6e
commit e30d4e4598
11 changed files with 217 additions and 20 deletions
+10
View File
@@ -3,6 +3,7 @@ import type { Database } from '@tursodatabase/database';
import { mkdir, readFile, unlink, writeFile } from 'node:fs/promises';
import path from 'node:path';
import sharp from 'sharp';
import { randomUUID } from 'node:crypto';
export const MAX_AVATAR_BYTES = 5 * 1024 * 1024;
export const MAX_AVATAR_PIXELS = 20_000_000;
@@ -57,6 +58,11 @@ export async function saveUploadedAvatar(database: Database, userId: string, out
VALUES(?,?,?,?,?) ON CONFLICT(user_id) DO UPDATE SET
source=excluded.source,value=excluded.value,byte_size=excluded.byte_size,updated_at=excluded.updated_at`))
.run(userId, 'upload', key, output.length, now);
await (await database.prepare("UPDATE avatar_reviews SET status='superseded',reviewed_at=? WHERE user_id=? AND status='pending'"))
.run(now, userId);
await (await database.prepare(`INSERT INTO avatar_reviews
(id,user_id,avatar_updated_at,storage_key,byte_size,status,submitted_at)
VALUES(?,?,?,?,?,'pending',?)`)).run(randomUUID(), userId, now, key, output.length, now);
return now;
}
@@ -68,6 +74,8 @@ export async function selectPresetAvatar(database: Database, userId: string, pre
VALUES(?,?,?,?,?) ON CONFLICT(user_id) DO UPDATE SET
source=excluded.source,value=excluded.value,byte_size=excluded.byte_size,updated_at=excluded.updated_at`))
.run(userId, 'preset', preset, null, now);
await (await database.prepare("UPDATE avatar_reviews SET status='withdrawn',reviewed_at=? WHERE user_id=? AND status='pending'"))
.run(now, userId);
if (existing?.source === 'upload' && typeof existing.value === 'string') {
await unlink(storagePath(existing.value)).catch((error: NodeJS.ErrnoException) => {
if (error.code !== 'ENOENT') throw error;
@@ -91,6 +99,8 @@ export async function readUploadedAvatar(database: Database, userId: string): Pr
export async function deleteUploadedAvatar(database: Database, userId: string): Promise<void> {
const avatar = await (await database.prepare('SELECT source,value FROM user_avatars WHERE user_id=?')).get(userId);
await (await database.prepare('DELETE FROM user_avatars WHERE user_id=?')).run(userId);
await (await database.prepare("UPDATE avatar_reviews SET status='removed',reviewed_at=COALESCE(reviewed_at,?) WHERE user_id=? AND status='pending'"))
.run(new Date().toISOString(), userId);
if (avatar?.source === 'upload' && typeof avatar.value === 'string') {
await unlink(storagePath(avatar.value)).catch((error: NodeJS.ErrnoException) => {
if (error.code !== 'ENOENT') throw error;