diff --git a/api.yml b/api.yml index e86b33e..45e9e9a 100644 --- a/api.yml +++ b/api.yml @@ -573,6 +573,25 @@ components: properties: data: $ref: "#/components/schemas/GalleryList" + GalleryThumbnailApiResult: + description: Api response for getGalleriesThumbnail + allOf: + - $ref: "#/components/schemas/ApiResponse" + - type: object + required: [data] + properties: + data: + type: object + additionalProperties: + oneOf: + - allOf: + - $ref: "#/components/schemas/ApiResponse" + - type: object + required: [data] + properties: + data: + $ref: "#/components/schemas/ExtendedPMeta" + - $ref: "#/components/schemas/ApiResponseError" GMeta: description: Gallery metadata allOf: @@ -2616,6 +2635,68 @@ paths: $ref: "#/components/schemas/ApiResponseError" example: { "ok": false, "status": 403, "error": "Permission denied." } + /gallery/thumbnail/{gids}: + parameters: + - name: gids + in: path + schema: + type: array + items: + type: integer + format: int64 + required: true + description: List of gallery ids + get: + tags: [gallery] + operationId: getGalleriesThumbnail + summary: Get gallery thumbnail information + description: Get the first page's extended metadata for specified galleries, commonly used to retrieve thumbnails + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/GalleryThumbnailApiResult' + example: { + "ok": true, + "status": 0, + "data": { + "1467583": { + "ok": true, + "status": 0, + "data": { + "gid": 1467583, + "token": "fb8be3ee60", + "index": 1, + "name": "00.jpg", + "width": 1280, + "height": 1807, + "is_nsfw": false, + "is_ad": false + } + }, + "1": { + "ok": false, + "status": 404, + "error": "Not found" + } + } + } + "401": + description: Authorization information is missing or invalid + content: + application/json: + schema: + $ref: "#/components/schemas/ApiResponseError" + example: { "ok": false, "status": 401, "error": "Unauthorized" } + "403": + description: Permission denied + content: + application/json: + schema: + $ref: "#/components/schemas/ApiResponseError" + example: { "ok": false, "status": 403, "error": "Permission denied." } /health_check: get: tags: [health_check] diff --git a/db.ts b/db.ts index d36782d..66fc6a7 100644 --- a/db.ts +++ b/db.ts @@ -1134,6 +1134,15 @@ export class EhDb { [token], )); } + get_first_extended_pmeta(gid: number | bigint) { + const d = this.convert_extended_pmeta( + this.db.queryEntries( + "SELECT pmeta.*, filemeta.is_nsfw, filemeta.is_ad FROM pmeta LEFT JOIN filemeta ON filemeta.token = pmeta.token WHERE gid = ? ORDER BY pmeta.\"index\" ASC LIMIT 1;", + [gid], + ) + ); + return d.length ? d[0] : null; + } get_gallery_count() { return this.db.query<[number | bigint]>( "SELECT COUNT(*) FROM gmeta;", diff --git a/fresh.gen.ts b/fresh.gen.ts index afce77a..7e12077 100644 --- a/fresh.gen.ts +++ b/fresh.gen.ts @@ -21,6 +21,7 @@ import * as $api_fs_list from "./routes/api/fs/list.ts"; import * as $api_gallery_gid_ from "./routes/api/gallery/[gid].ts"; import * as $api_gallery_list from "./routes/api/gallery/list.ts"; import * as $api_gallery_meta_gids_ from "./routes/api/gallery/meta/[gids].ts"; +import * as $api_gallery_thumbnail_gids_ from "./routes/api/gallery/thumbnail/[gids].ts"; import * as $api_health_check from "./routes/api/health_check.ts"; import * as $api_log from "./routes/api/log.ts"; import * as $api_log_id_ from "./routes/api/log/[id].ts"; @@ -74,6 +75,8 @@ const manifest = { "./routes/api/gallery/[gid].ts": $api_gallery_gid_, "./routes/api/gallery/list.ts": $api_gallery_list, "./routes/api/gallery/meta/[gids].ts": $api_gallery_meta_gids_, + "./routes/api/gallery/thumbnail/[gids].ts": + $api_gallery_thumbnail_gids_, "./routes/api/health_check.ts": $api_health_check, "./routes/api/log.ts": $api_log, "./routes/api/log/[id].ts": $api_log_id_, diff --git a/routes/api/gallery/thumbnail/[gids].ts b/routes/api/gallery/thumbnail/[gids].ts new file mode 100644 index 0000000..94f4f3c --- /dev/null +++ b/routes/api/gallery/thumbnail/[gids].ts @@ -0,0 +1,41 @@ +import { Handlers } from "$fresh/server.ts"; +import { get_task_manager } from "../../../../server.ts"; +import { + gen_data, + gen_error, + JSONResult, + return_data, + return_error, +} from "../../../../server/utils.ts"; +import { ExtendedPMeta, User, UserPermission } from "../../../../db.ts"; +import { isNumNaN, parseBigInt } from "../../../../utils.ts"; + + +export const handler: Handlers = { + GET(_req, ctx) { + const u = ctx.state.user; + if ( + u && !u.is_admin && + !(Number(u.permissions) & UserPermission.ReadGallery) + ) { + return return_error(403, "Permission denied."); + } + const gid = decodeURIComponent(ctx.params.gids); + const gids = new Set( + gid.split(",").map((v) => parseBigInt(v)).filter((v) => + !isNumNaN(v) + ).map((v) => BigInt(v)), + ); + const m = get_task_manager(); + const re: Record> = {}; + for (const gid of gids) { + const page = m.db.get_first_extended_pmeta(gid); + if (page) { + re[gid.toString()] = gen_data(page); + } else { + re[gid.toString()] = gen_error(404, "Not found"); + } + } + return return_data(re); + }, +};