aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFuwn <[email protected]>2023-12-24 00:59:14 -0800
committerFuwn <[email protected]>2023-12-24 00:59:14 -0800
commit31ea88d915e27d15efd7c110f8189130338c759b (patch)
treedf6fce79682d33890505857084adf52d13d60063
parentfix(subtiteld): lessen subtitled match (diff)
downloaddue.moe-31ea88d915e27d15efd7c110f8189130338c759b.tar.xz
due.moe-31ea88d915e27d15efd7c110f8189130338c759b.zip
feat(mangadex): server-side rate-limit 5/s
-rwxr-xr-xbun.lockbbin125230 -> 126026 bytes
-rw-r--r--package.json93
-rw-r--r--src/lib/rateLimit.ts12
-rw-r--r--src/routes/api/mangadex/chapter/+server.ts9
-rw-r--r--src/routes/api/mangadex/feed/+server.ts10
-rw-r--r--src/routes/api/mangadex/manga/+server.ts9
6 files changed, 83 insertions, 50 deletions
diff --git a/bun.lockb b/bun.lockb
index 2225371f..cf7e9157 100755
--- a/bun.lockb
+++ b/bun.lockb
Binary files differ
diff --git a/package.json b/package.json
index 0c09dadf..d47ed879 100644
--- a/package.json
+++ b/package.json
@@ -1,48 +1,49 @@
{
- "name": "due.moe",
- "version": "0.0.0",
- "private": true,
- "scripts": {
- "dev": "vite dev",
- "build": "vite build",
- "preview": "vite preview",
- "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
- "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
- "lint": "prettier --plugin-search-dir . --check . && eslint .",
- "format": "prettier --plugin-search-dir . --write ."
- },
- "devDependencies": {
- "@sveltejs/adapter-auto": "^2.0.0",
- "@sveltejs/kit": "^1.20.4",
- "@types/dom-to-image": "^2.6.5",
- "@types/fast-levenshtein": "^0.0.4",
- "@types/file-saver": "^2.0.5",
- "@types/jsdom": "^21.1.6",
- "@typescript-eslint/eslint-plugin": "^5.45.0",
- "@typescript-eslint/parser": "^5.45.0",
- "eslint": "^8.28.0",
- "eslint-config-prettier": "^8.5.0",
- "eslint-plugin-svelte": "^2.30.0",
- "prettier": "^2.8.0",
- "prettier-plugin-svelte": "^2.10.1",
- "svelte": "^4.0.5",
- "svelte-adapter-bun": "^0.5.0",
- "svelte-check": "^3.4.3",
- "tslib": "^2.4.1",
- "typescript": "^5.0.0",
- "vite": "^4.4.2"
- },
- "type": "module",
- "dependencies": {
- "bun-types": "^1.0.15",
- "dexie": "^4.0.1-alpha.25",
- "fast-levenshtein": "^3.0.0",
- "html2canvas": "^1.4.1",
- "jsdom": "^23.0.1",
- "modern-screenshot": "^4.4.33",
- "rss-parser": "^3.13.0",
- "socket.io": "^4.7.2",
- "socket.io-client": "^4.7.2",
- "wanakana": "^5.3.1"
- }
+ "name": "due.moe",
+ "version": "0.0.0",
+ "private": true,
+ "scripts": {
+ "dev": "vite dev",
+ "build": "vite build",
+ "preview": "vite preview",
+ "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
+ "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
+ "lint": "prettier --plugin-search-dir . --check . && eslint .",
+ "format": "prettier --plugin-search-dir . --write ."
+ },
+ "devDependencies": {
+ "@sveltejs/adapter-auto": "^2.0.0",
+ "@sveltejs/kit": "^1.20.4",
+ "@types/dom-to-image": "^2.6.5",
+ "@types/fast-levenshtein": "^0.0.4",
+ "@types/file-saver": "^2.0.5",
+ "@types/jsdom": "^21.1.6",
+ "@typescript-eslint/eslint-plugin": "^5.45.0",
+ "@typescript-eslint/parser": "^5.45.0",
+ "eslint": "^8.28.0",
+ "eslint-config-prettier": "^8.5.0",
+ "eslint-plugin-svelte": "^2.30.0",
+ "prettier": "^2.8.0",
+ "prettier-plugin-svelte": "^2.10.1",
+ "svelte": "^4.0.5",
+ "svelte-adapter-bun": "^0.5.0",
+ "svelte-check": "^3.4.3",
+ "sveltekit-rate-limiter": "^0.4.2",
+ "tslib": "^2.4.1",
+ "typescript": "^5.0.0",
+ "vite": "^4.4.2"
+ },
+ "type": "module",
+ "dependencies": {
+ "bun-types": "^1.0.15",
+ "dexie": "^4.0.1-alpha.25",
+ "fast-levenshtein": "^3.0.0",
+ "html2canvas": "^1.4.1",
+ "jsdom": "^23.0.1",
+ "modern-screenshot": "^4.4.33",
+ "rss-parser": "^3.13.0",
+ "socket.io": "^4.7.2",
+ "socket.io-client": "^4.7.2",
+ "wanakana": "^5.3.1"
+ }
}
diff --git a/src/lib/rateLimit.ts b/src/lib/rateLimit.ts
new file mode 100644
index 00000000..98e726a2
--- /dev/null
+++ b/src/lib/rateLimit.ts
@@ -0,0 +1,12 @@
+import type { RequestEvent } from '@sveltejs/kit';
+import { RateLimiter } from 'sveltekit-rate-limiter/server';
+
+export const checkRateLimit = async (event: RequestEvent) => {
+ const limiter = new RateLimiter({ rates: { IP: [5, 's'] } });
+
+ await limiter.cookieLimiter?.preflight(event);
+
+ if (await limiter.isLimited(event)) return new Response('rate-limited');
+
+ return null;
+};
diff --git a/src/routes/api/mangadex/chapter/+server.ts b/src/routes/api/mangadex/chapter/+server.ts
index 68e125bd..ad291e42 100644
--- a/src/routes/api/mangadex/chapter/+server.ts
+++ b/src/routes/api/mangadex/chapter/+server.ts
@@ -1,4 +1,11 @@
-export const GET = async ({ url }) => {
+import { checkRateLimit } from '$lib/rateLimit.js';
+
+export const GET = async (event) => {
+ const limit = await checkRateLimit(event);
+ const { url } = event;
+
+ if (limit) return limit;
+
try {
return Response.json(
await (
diff --git a/src/routes/api/mangadex/feed/+server.ts b/src/routes/api/mangadex/feed/+server.ts
index ebfdd094..458d3914 100644
--- a/src/routes/api/mangadex/feed/+server.ts
+++ b/src/routes/api/mangadex/feed/+server.ts
@@ -1,9 +1,15 @@
-export const GET = async ({ url }) => {
+import { checkRateLimit } from '$lib/rateLimit.js';
+
+export const GET = async (event) => {
+ const limit = await checkRateLimit(event);
+
+ if (limit) return limit;
+
try {
return Response.json(
await (
await fetch(
- `https://api.mangadex.org/manga/${url.searchParams.get(
+ `https://api.mangadex.org/manga/${event.url.searchParams.get(
'id'
)}/feed?order[chapter]=desc&translatedLanguage[]=en&limit=1&contentRating[]=safe&contentRating[]=suggestive&contentRating[]=erotica&contentRating[]=pornographic`
)
diff --git a/src/routes/api/mangadex/manga/+server.ts b/src/routes/api/mangadex/manga/+server.ts
index 521bde6c..73c15481 100644
--- a/src/routes/api/mangadex/manga/+server.ts
+++ b/src/routes/api/mangadex/manga/+server.ts
@@ -1,4 +1,11 @@
-export const GET = async ({ url }) => {
+import { checkRateLimit } from '$lib/rateLimit.js';
+
+export const GET = async (event) => {
+ const limit = await checkRateLimit(event);
+ const { url } = event;
+
+ if (limit) return limit;
+
let status = '';
let error = false;