From e96b099fc236a1d6caac5e51ebc4702e177daeca Mon Sep 17 00:00:00 2001 From: lifegpc Date: Fri, 15 Sep 2023 14:29:16 +0800 Subject: [PATCH] /api/gallery/list support filter with upload and tag --- db.ts | 75 +++++++++++++++++++++++++++++++++++--- routes/api/gallery/list.ts | 15 +++++++- 2 files changed, 82 insertions(+), 8 deletions(-) diff --git a/db.ts b/db.ts index 14e3c4b..3578c41 100644 --- a/db.ts +++ b/db.ts @@ -256,6 +256,13 @@ const TOKEN_TABLE = `CREATE TABLE token ( secure BOOLEAN );`; +function escape_fields(fields: string, namespace: string) { + const fs = fields.split(","); + return fs.map((f) => { + return `${namespace}.${f.trim()}`; + }).join(","); +} + export class EhDb { db; #flock_enabled: boolean = eval('typeof Deno.flock !== "undefined"'); @@ -914,24 +921,80 @@ export class EhDb { limit = 20, fields = "*", sort_by_gid: boolean | null = null, + uploader: string | null = null, + tag: string | null, ) { const sort_sql = sort_by_gid !== null - ? ` ORDER BY gid ${sort_by_gid ? "ASC" : "DESC"}` + ? ` ORDER BY gmeta.gid ${sort_by_gid ? "ASC" : "DESC"}` : ""; + ""; + const join_sqls = []; + const where_sqls = []; + const args = []; + let escape = false; + if (tag) { + const tag_id = this.#tags.get(tag); + if (tag_id !== undefined) { + join_sqls.push("INNER JOIN gtag ON gmeta.gid = gtag.gid"); + where_sqls.push("gtag.id = ?"); + args.push(tag_id); + escape = true; + } + } + if (uploader) { + where_sqls.push("uploader = ?"); + args.push(uploader); + } + const where_sql = where_sqls.length + ? ` WHERE ${where_sqls.join(" AND ")}` + : ""; + const join_sql = join_sqls.length ? ` ${join_sqls.join(" ")}` : ""; + args.push(limit, offset); return this.convert_gmeta( this.db.queryEntries( - `SELECT ${fields} FROM gmeta${sort_sql} LIMIT ? OFFSET ?;`, - [limit, offset], + `SELECT ${ + escape ? escape_fields(fields, "gmeta") : fields + } FROM gmeta${join_sql}${where_sql}${sort_sql} LIMIT ? OFFSET ?;`, + args, ), ); } - get_gmetas_all(fields = "*", sort_by_gid: boolean | null = null) { + get_gmetas_all( + fields = "*", + sort_by_gid: boolean | null = null, + uploader: string | null = null, + tag: string | null = null, + ) { const sort_sql = sort_by_gid !== null - ? ` ORDER BY gid ${sort_by_gid ? "ASC" : "DESC"}` + ? ` ORDER BY gmeta.gid ${sort_by_gid ? "ASC" : "DESC"}` : ""; + const join_sqls = []; + const where_sqls = []; + const args = []; + let escape = false; + if (tag) { + const tag_id = this.#tags.get(tag); + if (tag_id !== undefined) { + join_sqls.push("INNER JOIN gtag ON gmeta.gid = gtag.gid"); + where_sqls.push("gtag.id = ?"); + args.push(tag_id); + escape = true; + } + } + if (uploader) { + where_sqls.push("uploader = ?"); + args.push(uploader); + } + const where_sql = where_sqls.length + ? ` WHERE ${where_sqls.join(" AND ")}` + : ""; + const join_sql = join_sqls.length ? ` ${join_sqls.join(" ")}` : ""; return this.convert_gmeta( this.db.queryEntries( - `SELECT ${fields} FROM gmeta${sort_sql};`, + `SELECT ${ + escape ? escape_fields(fields, "gmeta") : fields + } FROM gmeta${join_sql}${where_sql}${sort_sql};`, + args, ), ); } diff --git a/routes/api/gallery/list.ts b/routes/api/gallery/list.ts index fefe8c4..f5db10c 100644 --- a/routes/api/gallery/list.ts +++ b/routes/api/gallery/list.ts @@ -33,6 +33,8 @@ export const handler: Handlers = { u.searchParams.get("sort_by_gid"), null, ); + const uploader = u.searchParams.get("uploader"); + const tag = u.searchParams.get("tag"); if (fields !== "*") { const fs = fields.split(","); const ok = fs.every((d) => { @@ -42,10 +44,19 @@ export const handler: Handlers = { if (!ok) return return_error(1, "Some fields not allowed."); } if (all) { - return return_data(t.db.get_gmetas_all(fields, sort_by_gid)); + return return_data( + t.db.get_gmetas_all(fields, sort_by_gid, uploader, tag), + ); } else { return return_data( - t.db.get_gmetas(offset, limit, fields, sort_by_gid), + t.db.get_gmetas( + offset, + limit, + fields, + sort_by_gid, + uploader, + tag, + ), ); } },