Compare commits
1 commit
Author | SHA1 | Date | |
---|---|---|---|
9cb178aea4 |
18 changed files with 368 additions and 340 deletions
24
.forgejo/workflows/biomejs.yml
Normal file
24
.forgejo/workflows/biomejs.yml
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
name: Code quality checks
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
biome:
|
||||||
|
runs-on: docker
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install Bun
|
||||||
|
run: |
|
||||||
|
curl -fsSL https://bun.sh/install | bash
|
||||||
|
export BUN_INSTALL="$HOME/.bun"
|
||||||
|
echo "$BUN_INSTALL/bin" >> $GITHUB_PATH
|
||||||
|
|
||||||
|
- name: Install Dependencies
|
||||||
|
run: bun install
|
||||||
|
|
||||||
|
- name: Run Biome with verbose output
|
||||||
|
run: bunx biome ci . --verbose
|
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
|
@ -1,5 +1,4 @@
|
||||||
{
|
{
|
||||||
"cSpell.words": [
|
"cSpell.words": ["Booru"],
|
||||||
"Booru"
|
"explorer.excludeGitIgnore": false
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
23
README.md
23
README.md
|
@ -48,21 +48,20 @@
|
||||||
---
|
---
|
||||||
|
|
||||||
> **Note**
|
> **Note**
|
||||||
> To use the **e621 API**, you must update the following environment variables in your `.env` file:
|
> To use the **e621 Booru route**, include the following **headers** in your request:
|
||||||
>
|
>
|
||||||
> ```env
|
> ```http
|
||||||
> E621_USER_AGENT=YourApplication/1.0 (by username on e621)
|
> e621UserAgent: YourApplication/1.0 (by username on e621)
|
||||||
> E621_USERNAME=your-username
|
> e621Username: your-username
|
||||||
> E621_API_KEY=your-apikey
|
> e621ApiKey: your-apikey
|
||||||
> ```
|
> ```
|
||||||
> Replace `your-username` and `your-apikey` with your e621 account credentials. Update the `User-Agent` string to include your application name, version, and a contact method (e.g., your e621 username) to comply with e621's API guidelines.
|
> Replace `your-username` and `your-apikey` with your e621 account credentials. Update the `e621UserAgent` string to include your application name, version, and a contact method (e.g., your e621 username) to comply with e621's API guidelines.
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
> To use the **Gelbooru API**, you must also update the following:
|
> To use the **Gelbooru Booru route**, include these **headers** in your request:
|
||||||
>
|
>
|
||||||
> ```env
|
> ```http
|
||||||
> GELBOORU_API_KEY=your-apikey
|
> gelbooruApiKey: your-apikey
|
||||||
> GELBOORU_USER_ID=your-user-id
|
> gelbooruUserId: your-user-id
|
||||||
> ```
|
> ```
|
||||||
> You can find these credentials in your [Gelbooru account settings](https://gelbooru.com/index.php?page=account&s=options).
|
> You can find these credentials in your [Gelbooru account settings](https://gelbooru.com/index.php?page=account&s=options). These are required for authenticated API requests and higher rate limits.
|
||||||
> These are required for authenticated API requests and higher rate limits.
|
|
||||||
|
|
35
biome.json
Normal file
35
biome.json
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
|
||||||
|
"vcs": {
|
||||||
|
"enabled": true,
|
||||||
|
"clientKind": "git",
|
||||||
|
"useIgnoreFile": false
|
||||||
|
},
|
||||||
|
"files": {
|
||||||
|
"ignoreUnknown": true,
|
||||||
|
"ignore": []
|
||||||
|
},
|
||||||
|
"formatter": {
|
||||||
|
"enabled": true,
|
||||||
|
"indentStyle": "tab",
|
||||||
|
"lineEnding": "lf"
|
||||||
|
},
|
||||||
|
"organizeImports": {
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
"linter": {
|
||||||
|
"enabled": true,
|
||||||
|
"rules": {
|
||||||
|
"recommended": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"javascript": {
|
||||||
|
"formatter": {
|
||||||
|
"quoteStyle": "double",
|
||||||
|
"indentStyle": "tab",
|
||||||
|
"lineEnding": "lf",
|
||||||
|
"jsxQuoteStyle": "double",
|
||||||
|
"semicolons": "always"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,5 @@
|
||||||
// cSpell:disable
|
// cSpell:disable
|
||||||
|
|
||||||
import { gelBooruAUTH, getE621Auth } from "@config/environment";
|
|
||||||
|
|
||||||
const booruDefaults: IBooruDefaults = {
|
const booruDefaults: IBooruDefaults = {
|
||||||
search: "index.php?page=dapi&s=post&q=index&json=1",
|
search: "index.php?page=dapi&s=post&q=index&json=1",
|
||||||
random: "s",
|
random: "s",
|
||||||
|
@ -68,7 +66,6 @@ export const booruConfig: IBooruConfigMap = {
|
||||||
random: "defaultRandom",
|
random: "defaultRandom",
|
||||||
id: ["posts/", ".json"],
|
id: ["posts/", ".json"],
|
||||||
},
|
},
|
||||||
auth: getE621Auth(),
|
|
||||||
},
|
},
|
||||||
"gelbooru.com": {
|
"gelbooru.com": {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
@ -77,6 +74,5 @@ export const booruConfig: IBooruConfigMap = {
|
||||||
endpoint: "gelbooru.com",
|
endpoint: "gelbooru.com",
|
||||||
autocomplete: "gelbooru.com/index.php?page=autocomplete&term=",
|
autocomplete: "gelbooru.com/index.php?page=autocomplete&term=",
|
||||||
functions: booruDefaults,
|
functions: booruDefaults,
|
||||||
auth: gelBooruAUTH(),
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,47 +1,6 @@
|
||||||
import { logger } from "@/helpers/logger";
|
|
||||||
|
|
||||||
export const environment: Environment = {
|
export const environment: Environment = {
|
||||||
port: parseInt(process.env.PORT || "6600", 10),
|
port: Number.parseInt(process.env.PORT || "6600", 10),
|
||||||
host: process.env.HOST || "0.0.0.0",
|
host: process.env.HOST || "0.0.0.0",
|
||||||
development:
|
development:
|
||||||
process.env.NODE_ENV === "development" ||
|
process.env.NODE_ENV === "development" || process.argv.includes("--dev"),
|
||||||
process.argv.includes("--dev"),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (
|
|
||||||
!process.env.E621_USER_AGENT ||
|
|
||||||
!process.env.E621_USERNAME ||
|
|
||||||
!process.env.E621_API_KEY
|
|
||||||
) {
|
|
||||||
logger.error("Missing e621 credentials in .env file");
|
|
||||||
} else {
|
|
||||||
if (
|
|
||||||
process.env.E621_USERNAME === "username" ||
|
|
||||||
process.env.E621_API_KEY === "apikey"
|
|
||||||
) {
|
|
||||||
logger.error("Please update your e621 credentials in the .env file");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getE621Auth(): Record<string, string> {
|
|
||||||
const e621UserAgent: string | undefined = process.env.E621_USER_AGENT;
|
|
||||||
const e621Username: string | undefined = process.env.E621_USERNAME;
|
|
||||||
const e621ApiKey: string | undefined = process.env.E621_API_KEY;
|
|
||||||
|
|
||||||
return {
|
|
||||||
"User-Agent": e621UserAgent || "",
|
|
||||||
Authorization:
|
|
||||||
"Basic " + btoa(`${e621Username || ""}:${e621ApiKey || ""}`),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!process.env.GELBOORU_API_KEY || !process.env.GELBOORU_USER_ID) {
|
|
||||||
logger.error("Missing Gelbooru credentials in .env file");
|
|
||||||
}
|
|
||||||
|
|
||||||
export function gelBooruAUTH(): Record<string, string> {
|
|
||||||
return {
|
|
||||||
apiKey: process.env.GELBOORU_API_KEY || "",
|
|
||||||
userId: process.env.GELBOORU_USER_ID || "",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
132
eslint.config.js
132
eslint.config.js
|
@ -1,132 +0,0 @@
|
||||||
import pluginJs from "@eslint/js";
|
|
||||||
import tseslintPlugin from "@typescript-eslint/eslint-plugin";
|
|
||||||
import tsParser from "@typescript-eslint/parser";
|
|
||||||
import prettier from "eslint-plugin-prettier";
|
|
||||||
import promisePlugin from "eslint-plugin-promise";
|
|
||||||
import simpleImportSort from "eslint-plugin-simple-import-sort";
|
|
||||||
import unicorn from "eslint-plugin-unicorn";
|
|
||||||
import unusedImports from "eslint-plugin-unused-imports";
|
|
||||||
import globals from "globals";
|
|
||||||
|
|
||||||
/** @type {import('eslint').Linter.FlatConfig[]} */
|
|
||||||
export default [
|
|
||||||
{
|
|
||||||
files: ["**/*.{js,mjs,cjs}"],
|
|
||||||
languageOptions: {
|
|
||||||
globals: globals.node,
|
|
||||||
},
|
|
||||||
...pluginJs.configs.recommended,
|
|
||||||
plugins: {
|
|
||||||
"simple-import-sort": simpleImportSort,
|
|
||||||
"unused-imports": unusedImports,
|
|
||||||
promise: promisePlugin,
|
|
||||||
prettier: prettier,
|
|
||||||
unicorn: unicorn,
|
|
||||||
},
|
|
||||||
rules: {
|
|
||||||
"eol-last": ["error", "always"],
|
|
||||||
"no-multiple-empty-lines": ["error", { max: 1, maxEOF: 1 }],
|
|
||||||
"no-mixed-spaces-and-tabs": ["error", "smart-tabs"],
|
|
||||||
"simple-import-sort/imports": "error",
|
|
||||||
"simple-import-sort/exports": "error",
|
|
||||||
"unused-imports/no-unused-imports": "error",
|
|
||||||
"unused-imports/no-unused-vars": [
|
|
||||||
"warn",
|
|
||||||
{
|
|
||||||
vars: "all",
|
|
||||||
varsIgnorePattern: "^_",
|
|
||||||
args: "after-used",
|
|
||||||
argsIgnorePattern: "^_",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"promise/always-return": "error",
|
|
||||||
"promise/no-return-wrap": "error",
|
|
||||||
"promise/param-names": "error",
|
|
||||||
"promise/catch-or-return": "error",
|
|
||||||
"promise/no-nesting": "warn",
|
|
||||||
"promise/no-promise-in-callback": "warn",
|
|
||||||
"promise/no-callback-in-promise": "warn",
|
|
||||||
"prettier/prettier": [
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
useTabs: true,
|
|
||||||
tabWidth: 4,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
indent: ["error", "tab", { SwitchCase: 1 }],
|
|
||||||
"unicorn/filename-case": [
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
case: "camelCase",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
files: ["**/*.{ts,tsx}"],
|
|
||||||
languageOptions: {
|
|
||||||
parser: tsParser,
|
|
||||||
globals: globals.node,
|
|
||||||
},
|
|
||||||
plugins: {
|
|
||||||
"@typescript-eslint": tseslintPlugin,
|
|
||||||
"simple-import-sort": simpleImportSort,
|
|
||||||
"unused-imports": unusedImports,
|
|
||||||
promise: promisePlugin,
|
|
||||||
prettier: prettier,
|
|
||||||
unicorn: unicorn,
|
|
||||||
},
|
|
||||||
rules: {
|
|
||||||
...tseslintPlugin.configs.recommended.rules,
|
|
||||||
quotes: ["error", "double"],
|
|
||||||
"eol-last": ["error", "always"],
|
|
||||||
"no-multiple-empty-lines": ["error", { max: 1, maxEOF: 1 }],
|
|
||||||
"no-mixed-spaces-and-tabs": ["error", "smart-tabs"],
|
|
||||||
"simple-import-sort/imports": "error",
|
|
||||||
"simple-import-sort/exports": "error",
|
|
||||||
"unused-imports/no-unused-imports": "error",
|
|
||||||
"unused-imports/no-unused-vars": [
|
|
||||||
"warn",
|
|
||||||
{
|
|
||||||
vars: "all",
|
|
||||||
varsIgnorePattern: "^_",
|
|
||||||
args: "after-used",
|
|
||||||
argsIgnorePattern: "^_",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"promise/always-return": "error",
|
|
||||||
"promise/no-return-wrap": "error",
|
|
||||||
"promise/param-names": "error",
|
|
||||||
"promise/catch-or-return": "error",
|
|
||||||
"promise/no-nesting": "warn",
|
|
||||||
"promise/no-promise-in-callback": "warn",
|
|
||||||
"promise/no-callback-in-promise": "warn",
|
|
||||||
"prettier/prettier": [
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
useTabs: true,
|
|
||||||
tabWidth: 4,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
indent: ["error", "tab", { SwitchCase: 1 }],
|
|
||||||
"unicorn/filename-case": [
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
case: "camelCase",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"@typescript-eslint/explicit-function-return-type": ["error"],
|
|
||||||
"@typescript-eslint/explicit-module-boundary-types": ["error"],
|
|
||||||
"@typescript-eslint/typedef": [
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
arrowParameter: true,
|
|
||||||
variableDeclaration: true,
|
|
||||||
propertyDeclaration: true,
|
|
||||||
memberVariableDeclaration: true,
|
|
||||||
parameter: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
26
package.json
26
package.json
|
@ -2,28 +2,20 @@
|
||||||
"name": "booru-api",
|
"name": "booru-api",
|
||||||
"module": "src/index.ts",
|
"module": "src/index.ts",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.17.0",
|
"@biomejs/biome": "^1.9.4",
|
||||||
"@types/bun": "^1.1.14",
|
"@eslint/js": "^9.24.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.18.1",
|
"@types/bun": "^1.2.9",
|
||||||
"@typescript-eslint/parser": "^8.18.1",
|
"globals": "^16.0.0"
|
||||||
"eslint": "^9.17.0",
|
|
||||||
"eslint-plugin-prettier": "^5.2.1",
|
|
||||||
"eslint-plugin-promise": "^7.2.1",
|
|
||||||
"eslint-plugin-simple-import-sort": "^12.1.1",
|
|
||||||
"eslint-plugin-unicorn": "^56.0.1",
|
|
||||||
"eslint-plugin-unused-imports": "^4.1.4",
|
|
||||||
"globals": "^15.14.0",
|
|
||||||
"prettier": "^3.4.2"
|
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"typescript": "^5.7.2"
|
"typescript": "^5.8.3"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "bun run src/index.ts",
|
"start": "bun run src/index.ts",
|
||||||
"dev": "bun run --watch src/index.ts --dev",
|
"dev": "bun run --hot src/index.ts --dev",
|
||||||
"lint": "eslint",
|
"lint": "bunx biome check",
|
||||||
"lint:fix": "bun lint --fix",
|
"lint:fix": "bunx biome check --fix",
|
||||||
"cleanup": "rm -rf logs node_modules bun.lockb"
|
"cleanup": "rm -rf logs node_modules bun.lock"
|
||||||
},
|
},
|
||||||
"type": "module"
|
"type": "module"
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,15 +4,15 @@ import { booruConfig } from "@config/booru";
|
||||||
|
|
||||||
export function timestampToReadable(timestamp?: number): string {
|
export function timestampToReadable(timestamp?: number): string {
|
||||||
const date: Date =
|
const date: Date =
|
||||||
timestamp && !isNaN(timestamp) ? new Date(timestamp) : new Date();
|
timestamp && !Number.isNaN(timestamp) ? new Date(timestamp) : new Date();
|
||||||
if (isNaN(date.getTime())) return "Invalid Date";
|
if (Number.isNaN(date.getTime())) return "Invalid Date";
|
||||||
return date.toISOString().replace("T", " ").replace("Z", "");
|
return date.toISOString().replace("T", " ").replace("Z", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function tagsToExpectedFormat(
|
export function tagsToExpectedFormat(
|
||||||
tags: string[] | string | Record<string, string[]>,
|
tags: string[] | string | Record<string, string[]>,
|
||||||
minus: boolean = false,
|
minus = false,
|
||||||
onlyMinus: boolean = false,
|
onlyMinus = false,
|
||||||
): string {
|
): string {
|
||||||
const delimiter: string = minus ? (onlyMinus ? "-" : "+-") : "+";
|
const delimiter: string = minus ? (onlyMinus ? "-" : "+-") : "+";
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ export function determineBooru(
|
||||||
export function postExpectedFormat(
|
export function postExpectedFormat(
|
||||||
booru: IBooruConfig,
|
booru: IBooruConfig,
|
||||||
posts: BooruPost[] | BooruPost,
|
posts: BooruPost[] | BooruPost,
|
||||||
tag_format: string = "string",
|
tag_format = "string",
|
||||||
): { posts: BooruPost[] } | null {
|
): { posts: BooruPost[] } | null {
|
||||||
if (!posts) return null;
|
if (!posts) return null;
|
||||||
|
|
||||||
|
@ -90,8 +90,7 @@ export function postExpectedFormat(
|
||||||
...post,
|
...post,
|
||||||
file_url: post.file.url ?? null,
|
file_url: post.file.url ?? null,
|
||||||
post_url:
|
post_url:
|
||||||
post.post_url ??
|
post.post_url ?? `https://${booru.endpoint}/posts/${post.id}`,
|
||||||
`https://${booru.endpoint}/posts/${post.id}`,
|
|
||||||
tags:
|
tags:
|
||||||
tag_format === "unformatted"
|
tag_format === "unformatted"
|
||||||
? post.tags
|
? post.tags
|
||||||
|
@ -104,8 +103,7 @@ export function postExpectedFormat(
|
||||||
}
|
}
|
||||||
|
|
||||||
const fixedDomain: string = booru.endpoint.replace(/^api\./, "");
|
const fixedDomain: string = booru.endpoint.replace(/^api\./, "");
|
||||||
const formattedPosts: BooruPost[] = normalizedPosts.map(
|
const formattedPosts: BooruPost[] = normalizedPosts.map((post: BooruPost) => {
|
||||||
(post: BooruPost) => {
|
|
||||||
const postUrl: string =
|
const postUrl: string =
|
||||||
post.post_url ??
|
post.post_url ??
|
||||||
`https://${fixedDomain}/index.php?page=post&s=view&id=${post.id}`;
|
`https://${fixedDomain}/index.php?page=post&s=view&id=${post.id}`;
|
||||||
|
@ -122,8 +120,34 @@ export function postExpectedFormat(
|
||||||
file_url: fileUrl,
|
file_url: fileUrl,
|
||||||
post_url: postUrl,
|
post_url: postUrl,
|
||||||
};
|
};
|
||||||
},
|
});
|
||||||
);
|
|
||||||
|
|
||||||
return { posts: formattedPosts };
|
return { posts: formattedPosts };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getE621Auth(headers: Headers): Record<string, string> | null {
|
||||||
|
const userAgent = headers.get("e621UserAgent") ?? "";
|
||||||
|
const username = headers.get("e621Username");
|
||||||
|
const apiKey = headers.get("e621ApiKey");
|
||||||
|
|
||||||
|
if (!userAgent || !username || !apiKey) return null;
|
||||||
|
|
||||||
|
return {
|
||||||
|
"User-Agent": userAgent,
|
||||||
|
Authorization: `Basic ${btoa(`${username}:${apiKey}`)}`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getGelBooruAuth(
|
||||||
|
headers: Headers,
|
||||||
|
): Record<string, string> | null {
|
||||||
|
const apiKey = headers.get("gelbooruApiKey");
|
||||||
|
const userId = headers.get("gelbooruUserId");
|
||||||
|
|
||||||
|
if (!apiKey || !userId) return null;
|
||||||
|
|
||||||
|
return {
|
||||||
|
apiKey,
|
||||||
|
userId,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
import { environment } from "@config/environment";
|
import type { Stats } from "node:fs";
|
||||||
import type { Stats } from "fs";
|
|
||||||
import {
|
import {
|
||||||
|
type WriteStream,
|
||||||
createWriteStream,
|
createWriteStream,
|
||||||
existsSync,
|
existsSync,
|
||||||
mkdirSync,
|
mkdirSync,
|
||||||
statSync,
|
statSync,
|
||||||
WriteStream,
|
} from "node:fs";
|
||||||
} from "fs";
|
import { EOL } from "node:os";
|
||||||
import { EOL } from "os";
|
import { basename, join } from "node:path";
|
||||||
import { basename, join } from "path";
|
import { environment } from "@config/environment";
|
||||||
|
|
||||||
import { timestampToReadable } from "./char";
|
import { timestampToReadable } from "./char";
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ class Logger {
|
||||||
mkdirSync(logDir, { recursive: true });
|
mkdirSync(logDir, { recursive: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
let addSeparator: boolean = false;
|
let addSeparator = false;
|
||||||
|
|
||||||
if (existsSync(logFile)) {
|
if (existsSync(logFile)) {
|
||||||
const fileStats: Stats = statSync(logFile);
|
const fileStats: Stats = statSync(logFile);
|
||||||
|
@ -67,9 +67,9 @@ class Logger {
|
||||||
|
|
||||||
private extractFileName(stack: string): string {
|
private extractFileName(stack: string): string {
|
||||||
const stackLines: string[] = stack.split("\n");
|
const stackLines: string[] = stack.split("\n");
|
||||||
let callerFile: string = "";
|
let callerFile = "";
|
||||||
|
|
||||||
for (let i: number = 2; i < stackLines.length; i++) {
|
for (let i = 2; i < stackLines.length; i++) {
|
||||||
const line: string = stackLines[i].trim();
|
const line: string = stackLines[i].trim();
|
||||||
if (line && !line.includes("Logger.") && line.includes("(")) {
|
if (line && !line.includes("Logger.") && line.includes("(")) {
|
||||||
callerFile = line.split("(")[1]?.split(")")[0] || "";
|
callerFile = line.split("(")[1]?.split(")")[0] || "";
|
||||||
|
@ -92,7 +92,7 @@ class Logger {
|
||||||
return { filename, timestamp: readableTimestamp };
|
return { filename, timestamp: readableTimestamp };
|
||||||
}
|
}
|
||||||
|
|
||||||
public info(message: string | string[], breakLine: boolean = false): void {
|
public info(message: string | string[], breakLine = false): void {
|
||||||
const stack: string = new Error().stack || "";
|
const stack: string = new Error().stack || "";
|
||||||
const { filename, timestamp } = this.getCallerInfo(stack);
|
const { filename, timestamp } = this.getCallerInfo(stack);
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ class Logger {
|
||||||
this.writeConsoleMessageColored(logMessageParts, breakLine);
|
this.writeConsoleMessageColored(logMessageParts, breakLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
public warn(message: string | string[], breakLine: boolean = false): void {
|
public warn(message: string | string[], breakLine = false): void {
|
||||||
const stack: string = new Error().stack || "";
|
const stack: string = new Error().stack || "";
|
||||||
const { filename, timestamp } = this.getCallerInfo(stack);
|
const { filename, timestamp } = this.getCallerInfo(stack);
|
||||||
|
|
||||||
|
@ -132,7 +132,7 @@ class Logger {
|
||||||
|
|
||||||
public error(
|
public error(
|
||||||
message: string | string[] | Error | Error[],
|
message: string | string[] | Error | Error[],
|
||||||
breakLine: boolean = false,
|
breakLine = false,
|
||||||
): void {
|
): void {
|
||||||
const stack: string = new Error().stack || "";
|
const stack: string = new Error().stack || "";
|
||||||
const { filename, timestamp } = this.getCallerInfo(stack);
|
const { filename, timestamp } = this.getCallerInfo(stack);
|
||||||
|
@ -159,7 +159,7 @@ class Logger {
|
||||||
|
|
||||||
private writeConsoleMessageColored(
|
private writeConsoleMessageColored(
|
||||||
logMessageParts: ILogMessageParts,
|
logMessageParts: ILogMessageParts,
|
||||||
breakLine: boolean = false,
|
breakLine = false,
|
||||||
): void {
|
): void {
|
||||||
const logMessage: string = Object.keys(logMessageParts)
|
const logMessage: string = Object.keys(logMessageParts)
|
||||||
.map((key: string) => {
|
.map((key: string) => {
|
||||||
|
|
|
@ -3,11 +3,7 @@ import { logger } from "@helpers/logger";
|
||||||
import { serverHandler } from "./server";
|
import { serverHandler } from "./server";
|
||||||
|
|
||||||
async function main(): Promise<void> {
|
async function main(): Promise<void> {
|
||||||
try {
|
|
||||||
serverHandler.initialize();
|
serverHandler.initialize();
|
||||||
} catch (error) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
main().catch((error: Error) => {
|
main().catch((error: Error) => {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { determineBooru } from "@helpers/char";
|
import { determineBooru, getE621Auth, getGelBooruAuth } from "@helpers/char";
|
||||||
import { fetch } from "bun";
|
import { fetch } from "bun";
|
||||||
|
|
||||||
import { logger } from "@/helpers/logger";
|
import { logger } from "@helpers/logger";
|
||||||
|
|
||||||
const routeDef: RouteDef = {
|
const routeDef: RouteDef = {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
|
@ -10,7 +10,7 @@ const routeDef: RouteDef = {
|
||||||
};
|
};
|
||||||
|
|
||||||
async function handler(
|
async function handler(
|
||||||
_request: Request,
|
request: Request,
|
||||||
_server: BunServer,
|
_server: BunServer,
|
||||||
_requestBody: unknown,
|
_requestBody: unknown,
|
||||||
query: Query,
|
query: Query,
|
||||||
|
@ -47,6 +47,22 @@ async function handler(
|
||||||
const booruConfig: IBooruConfig | null = determineBooru(booru);
|
const booruConfig: IBooruConfig | null = determineBooru(booru);
|
||||||
const isE621: boolean = booruConfig?.name === "e621.net";
|
const isE621: boolean = booruConfig?.name === "e621.net";
|
||||||
const isGelbooru: boolean = booruConfig?.name === "gelbooru.com";
|
const isGelbooru: boolean = booruConfig?.name === "gelbooru.com";
|
||||||
|
const gelbooruAuth: Record<string, string> | null = getGelBooruAuth(
|
||||||
|
request.headers,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isGelbooru && !gelbooruAuth) {
|
||||||
|
return Response.json(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
code: 401,
|
||||||
|
error: "Missing Gelbooru authentication headers",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
status: 401,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (!booruConfig) {
|
if (!booruConfig) {
|
||||||
return Response.json(
|
return Response.json(
|
||||||
|
@ -106,15 +122,37 @@ async function handler(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let url: string = `https://${booruConfig.autocomplete}${editedTag}`;
|
let url = `https://${booruConfig.autocomplete}${editedTag}`;
|
||||||
|
|
||||||
if (isGelbooru) {
|
if (isGelbooru && gelbooruAuth) {
|
||||||
url += `&api_key=${booruConfig.auth?.api_key}&user_id=${booruConfig.auth?.user_id}`;
|
url += `?api_key=${gelbooruAuth.api_key}&user_id=${gelbooruAuth.user_id}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const headers: IBooruConfig["auth"] | undefined =
|
let headers: Record<string, string> | undefined;
|
||||||
booruConfig.auth && isE621 ? booruConfig.auth : undefined;
|
|
||||||
|
if (isE621) {
|
||||||
|
const e621Auth: Record<string, string> | null = getE621Auth(
|
||||||
|
request.headers,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!e621Auth) {
|
||||||
|
return Response.json(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
code: 401,
|
||||||
|
error: "Missing E621 authentication headers",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
status: 401,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
...e621Auth,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const response: Response = await fetch(url, {
|
const response: Response = await fetch(url, {
|
||||||
headers,
|
headers,
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
import { determineBooru, postExpectedFormat } from "@helpers/char";
|
import {
|
||||||
|
determineBooru,
|
||||||
|
getE621Auth,
|
||||||
|
getGelBooruAuth,
|
||||||
|
postExpectedFormat,
|
||||||
|
} from "@helpers/char";
|
||||||
import { fetch } from "bun";
|
import { fetch } from "bun";
|
||||||
|
|
||||||
import { logger } from "@/helpers/logger";
|
import { logger } from "@helpers/logger";
|
||||||
|
|
||||||
const routeDef: RouteDef = {
|
const routeDef: RouteDef = {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
|
@ -10,7 +15,7 @@ const routeDef: RouteDef = {
|
||||||
};
|
};
|
||||||
|
|
||||||
async function handler(
|
async function handler(
|
||||||
_request: Request,
|
request: Request,
|
||||||
_server: BunServer,
|
_server: BunServer,
|
||||||
_requestBody: unknown,
|
_requestBody: unknown,
|
||||||
query: Query,
|
query: Query,
|
||||||
|
@ -37,6 +42,22 @@ async function handler(
|
||||||
const booruConfig: IBooruConfig | null = determineBooru(booru);
|
const booruConfig: IBooruConfig | null = determineBooru(booru);
|
||||||
const isE621: boolean = booruConfig?.name === "e621.net";
|
const isE621: boolean = booruConfig?.name === "e621.net";
|
||||||
const isGelbooru: boolean = booruConfig?.name === "gelbooru.com";
|
const isGelbooru: boolean = booruConfig?.name === "gelbooru.com";
|
||||||
|
const gelbooruAuth: Record<string, string> | null = getGelBooruAuth(
|
||||||
|
request.headers,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isGelbooru && !gelbooruAuth) {
|
||||||
|
return Response.json(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
code: 401,
|
||||||
|
error: "Missing Gelbooru authentication headers",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
status: 401,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (!booruConfig) {
|
if (!booruConfig) {
|
||||||
return Response.json(
|
return Response.json(
|
||||||
|
@ -65,10 +86,10 @@ async function handler(
|
||||||
}
|
}
|
||||||
|
|
||||||
const funcString: string | [string, string] = booruConfig.functions.id;
|
const funcString: string | [string, string] = booruConfig.functions.id;
|
||||||
let url: string = `https://${booruConfig.endpoint}/${booruConfig.functions.id}${id}`;
|
let url = `https://${booruConfig.endpoint}/${booruConfig.functions.id}${id}`;
|
||||||
|
|
||||||
if (isGelbooru) {
|
if (isGelbooru && gelbooruAuth) {
|
||||||
url += `&api_key=${booruConfig.auth?.api_key}&user_id=${booruConfig.auth?.user_id}`;
|
url += `?api_key=${gelbooruAuth.api_key}&user_id=${gelbooruAuth.user_id}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Array.isArray(funcString)) {
|
if (Array.isArray(funcString)) {
|
||||||
|
@ -78,8 +99,30 @@ async function handler(
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const headers: IBooruConfig["auth"] | undefined =
|
let headers: Record<string, string> | undefined;
|
||||||
booruConfig.auth && isE621 ? booruConfig.auth : undefined;
|
|
||||||
|
if (isE621) {
|
||||||
|
const e621Auth: Record<string, string> | null = getE621Auth(
|
||||||
|
request.headers,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!e621Auth) {
|
||||||
|
return Response.json(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
code: 401,
|
||||||
|
error: "Missing E621 authentication headers",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
status: 401,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
...e621Auth,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const response: Response = await fetch(url, {
|
const response: Response = await fetch(url, {
|
||||||
headers,
|
headers,
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import {
|
import {
|
||||||
determineBooru,
|
determineBooru,
|
||||||
|
getE621Auth,
|
||||||
|
getGelBooruAuth,
|
||||||
minPosts,
|
minPosts,
|
||||||
postExpectedFormat,
|
postExpectedFormat,
|
||||||
shufflePosts,
|
shufflePosts,
|
||||||
|
@ -7,7 +9,7 @@ import {
|
||||||
} from "@helpers/char";
|
} from "@helpers/char";
|
||||||
import { fetch } from "bun";
|
import { fetch } from "bun";
|
||||||
|
|
||||||
import { logger } from "@/helpers/logger";
|
import { logger } from "@helpers/logger";
|
||||||
|
|
||||||
const routeDef: RouteDef = {
|
const routeDef: RouteDef = {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
|
@ -17,7 +19,7 @@ const routeDef: RouteDef = {
|
||||||
};
|
};
|
||||||
|
|
||||||
async function handler(
|
async function handler(
|
||||||
_request: Request,
|
request: Request,
|
||||||
_server: BunServer,
|
_server: BunServer,
|
||||||
requestBody: unknown,
|
requestBody: unknown,
|
||||||
query: Query,
|
query: Query,
|
||||||
|
@ -121,6 +123,22 @@ async function handler(
|
||||||
|
|
||||||
const isE621: boolean = booruConfig.name === "e621.net";
|
const isE621: boolean = booruConfig.name === "e621.net";
|
||||||
const isGelbooru: boolean = booruConfig.name === "gelbooru.com";
|
const isGelbooru: boolean = booruConfig.name === "gelbooru.com";
|
||||||
|
const gelbooruAuth: Record<string, string> | null = getGelBooruAuth(
|
||||||
|
request.headers,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isGelbooru && !gelbooruAuth) {
|
||||||
|
return Response.json(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
code: 401,
|
||||||
|
error: "Missing Gelbooru authentication headers",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
status: 401,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const formattedTags: string = tags ? tagsToExpectedFormat(tags) : "";
|
const formattedTags: string = tags ? tagsToExpectedFormat(tags) : "";
|
||||||
const formattedExcludeTags: string = excludeTags
|
const formattedExcludeTags: string = excludeTags
|
||||||
|
@ -130,9 +148,11 @@ async function handler(
|
||||||
const tagsString: () => string = (): string => {
|
const tagsString: () => string = (): string => {
|
||||||
if (formattedTags && formattedExcludeTags) {
|
if (formattedTags && formattedExcludeTags) {
|
||||||
return `tags=${formattedTags}+-${formattedExcludeTags}`;
|
return `tags=${formattedTags}+-${formattedExcludeTags}`;
|
||||||
} else if (formattedTags) {
|
}
|
||||||
|
if (formattedTags) {
|
||||||
return `tags=${formattedTags}`;
|
return `tags=${formattedTags}`;
|
||||||
} else if (formattedExcludeTags) {
|
}
|
||||||
|
if (formattedExcludeTags) {
|
||||||
return `tags=-${formattedExcludeTags}`;
|
return `tags=-${formattedExcludeTags}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,12 +184,12 @@ async function handler(
|
||||||
parts.push("&");
|
parts.push("&");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isGelbooru) {
|
if (isGelbooru && gelbooruAuth) {
|
||||||
parts.push("api_key");
|
parts.push("api_key");
|
||||||
parts.push(booruConfig.auth?.apiKey || "");
|
parts.push(gelbooruAuth.apiKey);
|
||||||
parts.push("&");
|
parts.push("&");
|
||||||
parts.push("user_id");
|
parts.push("user_id");
|
||||||
parts.push(booruConfig.auth?.userId || "");
|
parts.push(gelbooruAuth.userId);
|
||||||
parts.push("&");
|
parts.push("&");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,7 +198,6 @@ async function handler(
|
||||||
.join("&");
|
.join("&");
|
||||||
parts.push(queryParams);
|
parts.push(queryParams);
|
||||||
|
|
||||||
console.log("URL", parts.join(""));
|
|
||||||
return parts.join("");
|
return parts.join("");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -186,15 +205,37 @@ async function handler(
|
||||||
maxPage: 12,
|
maxPage: 12,
|
||||||
maxTries: 6,
|
maxTries: 6,
|
||||||
};
|
};
|
||||||
let state: { tries: number; page: number } = { tries: 0, page: 16 };
|
const state: { tries: number; page: number } = { tries: 0, page: 16 };
|
||||||
|
|
||||||
while (state.tries < config.maxTries) {
|
while (state.tries < config.maxTries) {
|
||||||
const url: string = getUrl(pageString(state.page), resultsString);
|
const url: string = getUrl(pageString(state.page), resultsString);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const headers: IBooruConfig["auth"] | undefined = booruConfig.auth
|
let headers: Record<string, string> | undefined;
|
||||||
? booruConfig.auth
|
|
||||||
: undefined;
|
if (isE621) {
|
||||||
|
const e621Auth: Record<string, string> | null = getE621Auth(
|
||||||
|
request.headers,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!e621Auth) {
|
||||||
|
return Response.json(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
code: 401,
|
||||||
|
error: "Missing E621 authentication headers",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
status: 401,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
...e621Auth,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const response: Response = await fetch(url, {
|
const response: Response = await fetch(url, {
|
||||||
headers,
|
headers,
|
||||||
});
|
});
|
||||||
|
@ -204,9 +245,7 @@ async function handler(
|
||||||
{
|
{
|
||||||
success: false,
|
success: false,
|
||||||
code: response.status || 500,
|
code: response.status || 500,
|
||||||
error:
|
error: response.statusText || `Could not reach ${booruConfig.name}`,
|
||||||
response.statusText ||
|
|
||||||
`Could not reach ${booruConfig.name}`,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
status: response.status || 500,
|
status: response.status || 500,
|
||||||
|
@ -246,8 +285,11 @@ async function handler(
|
||||||
|
|
||||||
if (posts.length === 0) continue;
|
if (posts.length === 0) continue;
|
||||||
|
|
||||||
let expectedData: { posts: BooruPost[] } | null =
|
const expectedData: { posts: BooruPost[] } | null = postExpectedFormat(
|
||||||
postExpectedFormat(booruConfig, posts, tag_format);
|
booruConfig,
|
||||||
|
posts,
|
||||||
|
tag_format,
|
||||||
|
);
|
||||||
|
|
||||||
if (!expectedData) continue;
|
if (!expectedData) continue;
|
||||||
|
|
||||||
|
@ -265,7 +307,6 @@ async function handler(
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
} catch {
|
} catch {
|
||||||
continue;
|
|
||||||
} finally {
|
} finally {
|
||||||
state.tries++;
|
state.tries++;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import {
|
import {
|
||||||
determineBooru,
|
determineBooru,
|
||||||
|
getE621Auth,
|
||||||
|
getGelBooruAuth,
|
||||||
postExpectedFormat,
|
postExpectedFormat,
|
||||||
tagsToExpectedFormat,
|
tagsToExpectedFormat,
|
||||||
} from "@helpers/char";
|
} from "@helpers/char";
|
||||||
|
@ -13,7 +15,7 @@ const routeDef: RouteDef = {
|
||||||
};
|
};
|
||||||
|
|
||||||
async function handler(
|
async function handler(
|
||||||
_request: Request,
|
request: Request,
|
||||||
_server: BunServer,
|
_server: BunServer,
|
||||||
requestBody: unknown,
|
requestBody: unknown,
|
||||||
query: Query,
|
query: Query,
|
||||||
|
@ -119,6 +121,22 @@ async function handler(
|
||||||
|
|
||||||
const isE621: boolean = booruConfig.name === "e621.net";
|
const isE621: boolean = booruConfig.name === "e621.net";
|
||||||
const isGelbooru: boolean = booruConfig.name === "gelbooru.com";
|
const isGelbooru: boolean = booruConfig.name === "gelbooru.com";
|
||||||
|
const gelbooruAuth: Record<string, string> | null = getGelBooruAuth(
|
||||||
|
request.headers,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isGelbooru && !gelbooruAuth) {
|
||||||
|
return Response.json(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
code: 401,
|
||||||
|
error: "Missing Gelbooru authentication headers",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
status: 401,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const formattedTags: string = tags ? tagsToExpectedFormat(tags) : "";
|
const formattedTags: string = tags ? tagsToExpectedFormat(tags) : "";
|
||||||
const formattedExcludeTags: string = excludeTags
|
const formattedExcludeTags: string = excludeTags
|
||||||
|
@ -133,9 +151,11 @@ async function handler(
|
||||||
const tagsString: () => string = (): string => {
|
const tagsString: () => string = (): string => {
|
||||||
if (formattedTags && formattedExcludeTags) {
|
if (formattedTags && formattedExcludeTags) {
|
||||||
return `tags=${formattedTags}+-${formattedExcludeTags}`;
|
return `tags=${formattedTags}+-${formattedExcludeTags}`;
|
||||||
} else if (formattedTags) {
|
}
|
||||||
|
if (formattedTags) {
|
||||||
return `tags=${formattedTags}`;
|
return `tags=${formattedTags}`;
|
||||||
} else if (formattedExcludeTags) {
|
}
|
||||||
|
if (formattedExcludeTags) {
|
||||||
return `tags=-${formattedExcludeTags}`;
|
return `tags=-${formattedExcludeTags}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,12 +182,12 @@ async function handler(
|
||||||
parts.push("&");
|
parts.push("&");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isGelbooru) {
|
if (isGelbooru && gelbooruAuth) {
|
||||||
parts.push("api_key");
|
parts.push("api_key");
|
||||||
parts.push(booruConfig.auth?.apiKey || "");
|
parts.push(gelbooruAuth.apiKey);
|
||||||
parts.push("&");
|
parts.push("&");
|
||||||
parts.push("user_id");
|
parts.push("user_id");
|
||||||
parts.push(booruConfig.auth?.userId || "");
|
parts.push(gelbooruAuth.userId);
|
||||||
parts.push("&");
|
parts.push("&");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,9 +200,31 @@ async function handler(
|
||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const headers: IBooruConfig["auth"] | undefined = booruConfig.auth
|
let headers: Record<string, string> | undefined;
|
||||||
? booruConfig.auth
|
|
||||||
: undefined;
|
if (isE621) {
|
||||||
|
const e621Auth: Record<string, string> | null = getE621Auth(
|
||||||
|
request.headers,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!e621Auth) {
|
||||||
|
return Response.json(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
code: 401,
|
||||||
|
error: "Missing E621 authentication headers",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
status: 401,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
...e621Auth,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const response: Response = await fetch(url(), {
|
const response: Response = await fetch(url(), {
|
||||||
headers,
|
headers,
|
||||||
});
|
});
|
||||||
|
@ -192,9 +234,7 @@ async function handler(
|
||||||
{
|
{
|
||||||
success: false,
|
success: false,
|
||||||
code: response.status || 500,
|
code: response.status || 500,
|
||||||
error:
|
error: response.statusText || `Could not reach ${booruConfig.name}`,
|
||||||
response.statusText ||
|
|
||||||
`Could not reach ${booruConfig.name}`,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
status: response.status || 500,
|
status: response.status || 500,
|
||||||
|
|
|
@ -58,8 +58,7 @@ class ServerHandler {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const routeModule: RouteModule = await import(filePath);
|
const routeModule: RouteModule = await import(filePath);
|
||||||
const contentType: string | null =
|
const contentType: string | null = request.headers.get("Content-Type");
|
||||||
request.headers.get("Content-Type");
|
|
||||||
const actualContentType: string | null = contentType
|
const actualContentType: string | null = contentType
|
||||||
? contentType.split(";")[0].trim()
|
? contentType.split(";")[0].trim()
|
||||||
: null;
|
: null;
|
||||||
|
@ -119,10 +118,7 @@ class ServerHandler {
|
||||||
params,
|
params,
|
||||||
);
|
);
|
||||||
|
|
||||||
response.headers.set(
|
response.headers.set("Content-Type", routeModule.routeDef.returns);
|
||||||
"Content-Type",
|
|
||||||
routeModule.routeDef.returns,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
|
|
|
@ -2,31 +2,15 @@
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": "./",
|
"baseUrl": "./",
|
||||||
"paths": {
|
"paths": {
|
||||||
"@/*": [
|
"@/*": ["src/*"],
|
||||||
"src/*"
|
"@config/*": ["config/*"],
|
||||||
],
|
"@types/*": ["types/*"],
|
||||||
"@config/*": [
|
"@helpers/*": ["src/helpers/*"],
|
||||||
"config/*"
|
"@database/*": ["src/database/*"]
|
||||||
],
|
|
||||||
"@types/*": [
|
|
||||||
"types/*"
|
|
||||||
],
|
|
||||||
"@helpers/*": [
|
|
||||||
"src/helpers/*"
|
|
||||||
],
|
|
||||||
"@database/*": [
|
|
||||||
"src/database/*"
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
"typeRoots": [
|
"typeRoots": ["./src/types", "./node_modules/@types"],
|
||||||
"./src/types",
|
|
||||||
"./node_modules/@types"
|
|
||||||
],
|
|
||||||
// Enable latest features
|
// Enable latest features
|
||||||
"lib": [
|
"lib": ["ESNext", "DOM"],
|
||||||
"ESNext",
|
|
||||||
"DOM"
|
|
||||||
],
|
|
||||||
"target": "ESNext",
|
"target": "ESNext",
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"moduleDetection": "force",
|
"moduleDetection": "force",
|
||||||
|
@ -44,11 +28,7 @@
|
||||||
// Some stricter flags (disabled by default)
|
// Some stricter flags (disabled by default)
|
||||||
"noUnusedLocals": false,
|
"noUnusedLocals": false,
|
||||||
"noUnusedParameters": false,
|
"noUnusedParameters": false,
|
||||||
"noPropertyAccessFromIndexSignature": false,
|
"noPropertyAccessFromIndexSignature": false
|
||||||
},
|
},
|
||||||
"include": [
|
"include": ["src", "types", "config"]
|
||||||
"src",
|
|
||||||
"types",
|
|
||||||
"config"
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
|
|
2
types/config.d.ts
vendored
2
types/config.d.ts
vendored
|
@ -18,7 +18,6 @@ type IBooruConfigMap = {
|
||||||
endpoint: string;
|
endpoint: string;
|
||||||
functions: IBooruDefaults;
|
functions: IBooruDefaults;
|
||||||
autocomplete?: string;
|
autocomplete?: string;
|
||||||
auth?: Record<string, string>;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -29,5 +28,4 @@ type IBooruConfig = {
|
||||||
endpoint: string;
|
endpoint: string;
|
||||||
functions: IBooruDefaults;
|
functions: IBooruDefaults;
|
||||||
autocomplete?: string;
|
autocomplete?: string;
|
||||||
auth?: Record<string, string>;
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue