Skip to content

Commit

Permalink
Add new api
Browse files Browse the repository at this point in the history
  • Loading branch information
lifegpc committed Feb 17, 2024
1 parent 21c05dd commit 6b9a7cb
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 0 deletions.
7 changes: 7 additions & 0 deletions config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ export type ConfigType = {
ffprobe_path: string;
redirect_to_flutter: boolean;
download_timeout_check_interval: number;
/** EH metadata cache time in hours */
eh_metadata_cache_time: number;
};

export enum ThumbnailMethod {
Expand Down Expand Up @@ -194,6 +196,10 @@ export class Config {
get download_timeout_check_interval() {
return this._return_number("download_timeout_check_interval") || 10;
}
/** EH metadata cache time in hours */
get eh_metadata_cache_time() {
return this._return_number("eh_metadata_cache_time") || 168;
}
to_json(): ConfigType {
return {
cookies: typeof this.cookies === "string",
Expand Down Expand Up @@ -226,6 +232,7 @@ export class Config {
redirect_to_flutter: this.redirect_to_flutter,
download_timeout_check_interval:
this.download_timeout_check_interval,
eh_metadata_cache_time: this.eh_metadata_cache_time,
};
}
}
Expand Down
29 changes: 29 additions & 0 deletions db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { Status } from "sqlite/src/constants.ts";
import { parse_bool, sleep, sure_dir_sync, try_remove_sync } from "./utils.ts";
import { Task, TaskType } from "./task.ts";
import { generate as randomstring } from "randomstring";
import type { GalleryMetadataSingle } from "./page/GalleryMetadata.ts";

type SqliteMaster = {
type: string;
Expand Down Expand Up @@ -187,6 +188,7 @@ const ALL_TABLES = [
"filemeta",
"user",
"token",
"ehmeta",
];
const VERSION_TABLE = `CREATE TABLE version (
id TEXT,
Expand Down Expand Up @@ -274,6 +276,12 @@ const TOKEN_TABLE = `CREATE TABLE token (
client_version TEXT,
client_platform TEXT
);`;
const EHMETA_TABLE = `CREATE TABLE ehmeta (
gid INT,
data TEXT,
cached_time TEXT,
PRIMARY KEY (gid)
);`;

function escape_fields(fields: string, namespace: string) {
const fs = fields.split(",");
Expand Down Expand Up @@ -497,6 +505,9 @@ export class EhDb {
if (!this.#exist_table.has("token")) {
this.db.execute(TOKEN_TABLE);
}
if (!this.#exist_table.has("ehmeta")) {
this.db.execute(EHMETA_TABLE);
}
this.#updateExistsTable();
}
#read_version() {
Expand Down Expand Up @@ -538,6 +549,12 @@ export class EhDb {
]);
});
}
add_ehmeta(data: GalleryMetadataSingle) {
this.db.query(
"INSERT OR REPLACE INTO ehmeta VALUES (?, ?, ?);",
[data.gid, JSON.stringify(data), new Date()],
);
}
add_gmeta(gmeta: GMeta) {
this.db.queryEntries(
"INSERT OR REPLACE INTO gmeta VALUES (:gid, :token, :title, :title_jpn, :category, :uploader, :posted, :filecount, :filesize, :expunged, :rating, :parent_gid, :parent_key, :first_gid, :first_key);",
Expand Down Expand Up @@ -949,6 +966,13 @@ export class EhDb {
if (!this.#dblock) return;
eval(`Deno.funlockSync(${this.#dblock.rid});`);
}
get_ehmeta(gid: number) {
const d = this.db.query<[string]>(
"SELECT data FROM ehmeta WHERE gid = ?;",
[gid],
);
return d.length ? JSON.parse(d[0][0]) as GalleryMetadataSingle : null;
}
get_extended_pmeta(gid: number) {
return this.convert_extended_pmeta(
this.db.queryEntries<ExtendedPMetaRaw>(
Expand Down Expand Up @@ -1244,6 +1268,11 @@ export class EhDb {
optimize() {
this.db.execute("VACUUM;");
}
remove_expired_ehmeta(cache_time: number) {
const date = new Date();
date.setTime(date.getTime() - cache_time * 3600_000);
this.db.query("DELETE FROM ehmeta WHERE cached_time < ?;", [date]);
}
remove_expired_token() {
this.db.query("DELETE FROM token WHERE expired < ?;", [new Date()]);
}
Expand Down
2 changes: 2 additions & 0 deletions fresh.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import * as $api_middleware from "./routes/api/_middleware.ts";
import * as $api_config from "./routes/api/config.ts";
import * as $api_deploy_id from "./routes/api/deploy_id.ts";
import * as $api_eh_image_limit from "./routes/api/eh/image_limit.ts";
import * as $api_eh_metadata from "./routes/api/eh/metadata.ts";
import * as $api_exit from "./routes/api/exit.ts";
import * as $api_export_gallery_zip_gid_ from "./routes/api/export/gallery/zip/[gid].ts";
import * as $api_file_id_ from "./routes/api/file/[id].ts";
Expand Down Expand Up @@ -45,6 +46,7 @@ const manifest = {
"./routes/api/config.ts": $api_config,
"./routes/api/deploy_id.ts": $api_deploy_id,
"./routes/api/eh/image_limit.ts": $api_eh_image_limit,
"./routes/api/eh/metadata.ts": $api_eh_metadata,
"./routes/api/exit.ts": $api_exit,
"./routes/api/export/gallery/zip/[gid].ts":
$api_export_gallery_zip_gid_,
Expand Down
86 changes: 86 additions & 0 deletions routes/api/eh/metadata.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { Handlers } from "$fresh/server.ts";
import type { GID } from "../../../client.ts";
import { User, UserPermission } from "../../../db.ts";
import { get_task_manager } from "../../../server.ts";
import { EHMetaInfo } from "../../../server/eh.ts";
import { parse_int } from "../../../server/parse_form.ts";
import {
gen_data,
gen_error,
return_data,
return_error,
} from "../../../server/utils.ts";

export const handler: Handlers = {
async GET(req, ctx) {
const user = <User | undefined> ctx.state.user;
if (
user && !user.is_admin &&
!(user.permissions & UserPermission.ManageTasks)
) {
return return_error(403, "Permission denied.");
}
const m = get_task_manager();
const url = new URL(req.url);
const gids: Array<number> = [];
for (const gid of url.searchParams.getAll("gid")) {
const i = await parse_int(gid, null);
if (i === null) {
return return_error(1, `Invalid gid: ${gid}`);
}
gids.push(i);
}
for (const gid of url.searchParams.getAll("gid[]")) {
const i = await parse_int(gid, null);
if (i === null) {
return return_error(1, `Invalid gid: ${gid}`);
}
gids.push(i);
}
const tokens = url.searchParams.getAll("token").concat(
url.searchParams.getAll("token[]"),
);
if (gids.length === 0 && tokens.length === 0) {
return return_error(2, "No gids and tokens provided.");
}
if (gids.length !== tokens.length) {
return return_error(3, "Length of gids and tokens do not match.");
}
const data: EHMetaInfo = {};
const needed: GID[] = [];
for (let i = 0; i < gids.length; i++) {
const gid = gids[i];
const token = tokens[i];
const cache = m.db.get_ehmeta(gid);
if (cache && cache.gid === gid && cache.token === token) {
data[gid] = gen_data(cache);
} else if (cache && cache.gid === gid) {
data[gid] = gen_error(1, "Token not matched.");
} else {
needed.push([gid, token]);
}
}
while (needed.length > 0) {
const query = needed.splice(0, 25);
try {
const metas = await m.client.fetchGalleryMetadataByAPI(
...query,
);
for (const [k, v] of metas.map) {
if (typeof v === "string") {
data[k] = gen_error(2, v);
} else {
data[k] = gen_data(v);
m.db.add_ehmeta(v);
}
}
} catch (e) {
return return_error(
4,
`Failed to fetch metadata: ${e.message}`,
);
}
}
return return_data(data);
},
};
6 changes: 6 additions & 0 deletions server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ export async function startServer(path: string) {
setInterval(() => {
task_manager?.db.remove_expired_token();
}, 86_400_000);
setInterval(() => {
if (!task_manager) return;
task_manager.db.remove_expired_ehmeta(
task_manager.cfg.eh_metadata_cache_time,
);
}, 3600_000);
return start(manifest, {
signal: task_manager.aborts,
plugins: [twindPlugin(twindConfig)],
Expand Down
5 changes: 5 additions & 0 deletions server/eh.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import type { JSONResult } from "./utils.ts";
import type { GalleryMetadataSingle } from "../page/GalleryMetadata.ts";

export type EHImageLimit = {
current: number;
max: number;
};

export type EHMetaInfo = Record<string, JSONResult<GalleryMetadataSingle>>;

0 comments on commit 6b9a7cb

Please sign in to comment.