diff --git a/package-lock.json b/package-lock.json index 7d00638..cb011ef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "express": "^4.18.1", "hono": "^3.8.3", "multer": "^1.4.5-lts.1", + "node-fetch": "^3.3.2", "nodemailer": "^6.9.3", "typescript": "^5.2.2" }, @@ -921,6 +922,14 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "engines": { + "node": ">= 12" + } + }, "node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -1107,6 +1116,28 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, "node_modules/file-type": { "version": "18.0.0", "resolved": "https://registry.npmjs.org/file-type/-/file-type-18.0.0.tgz", @@ -1184,6 +1215,17 @@ "node": ">= 6" } }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -1531,6 +1573,41 @@ "node": ">= 0.6" } }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, "node_modules/nodemailer": { "version": "6.9.3", "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.3.tgz", @@ -2134,6 +2211,14 @@ } } }, + "node_modules/web-streams-polyfill": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", + "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", + "engines": { + "node": ">= 8" + } + }, "node_modules/ws": { "version": "8.11.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", @@ -2738,6 +2823,11 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, + "data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==" + }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -2889,6 +2979,15 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, + "fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "requires": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + } + }, "file-type": { "version": "18.0.0", "resolved": "https://registry.npmjs.org/file-type/-/file-type-18.0.0.tgz", @@ -2937,6 +3036,14 @@ "mime-types": "^2.1.12" } }, + "formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "requires": { + "fetch-blob": "^3.1.2" + } + }, "forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -3173,6 +3280,21 @@ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" }, + "node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==" + }, + "node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "requires": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + } + }, "nodemailer": { "version": "6.9.3", "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.3.tgz", @@ -3563,6 +3685,11 @@ "dev": true, "requires": {} }, + "web-streams-polyfill": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", + "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==" + }, "ws": { "version": "8.11.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", diff --git a/package.json b/package.json index 2906996..1f7599d 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "express": "^4.18.1", "hono": "^3.8.3", "multer": "^1.4.5-lts.1", + "node-fetch": "^3.3.2", "nodemailer": "^6.9.3", "typescript": "^5.2.2" }, diff --git a/src/server/lib/DiscordAPI/DiscordRequests.ts b/src/server/lib/DiscordAPI/DiscordRequests.ts index f7f1c77..9dd4e24 100644 --- a/src/server/lib/DiscordAPI/DiscordRequests.ts +++ b/src/server/lib/DiscordAPI/DiscordRequests.ts @@ -57,9 +57,9 @@ class DiscordAPIBucket { dead : boolean = false // True if bucket has expired linked_routes : `/${string}`[] = [] // Routes linked to this bucket - constructor(rest: REST, base: Response) { + constructor(rest: REST, base: Headers) { - let rd = extractRatelimitData(base.headers) + let rd = extractRatelimitData(base) this.parent = rest this.name = rd.bucket_name @@ -70,7 +70,7 @@ class DiscordAPIBucket { this.expirationHold = setTimeout( this.destroy, - parseFloat(base.headers.get("x-ratelimit-reset-after")!) + parseFloat(base.get("x-ratelimit-reset-after")!) ) } @@ -133,15 +133,15 @@ function checkHeaders(headers: Headers) { * @param response Response or route to get a DiscordAPIBucket from */ function getBucket(response: string): DiscordAPIBucket | undefined -function getBucket(rest: REST, response: Response): DiscordAPIBucket -function getBucket(rest: REST | string, response?: Response) { - if (response instanceof Response && rest instanceof REST) { - if (!checkHeaders(response.headers)) throw new Error("Required ratelimiting headers not found") +function getBucket(rest: REST, headers: Headers): DiscordAPIBucket +function getBucket(rest: REST | string, headers?: Headers) { + if (headers instanceof Headers && rest instanceof REST) { + if (!checkHeaders(headers)) throw new Error("Required ratelimiting headers not found") - if (buckets.has(response.headers.get("x-ratelimit-bucket")!)) - return buckets.get(response.headers.get("x-ratelimit-bucket")!)! + if (buckets.has(headers.get("x-ratelimit-bucket")!)) + return buckets.get(headers.get("x-ratelimit-bucket")!)! else - return new DiscordAPIBucket(rest, response) + return new DiscordAPIBucket(rest, headers) } else if (typeof rest == "string") return routeConnections.get(rest) } @@ -198,7 +198,7 @@ export class REST { if ( checkHeaders(response.headers) ) { if (response.status == 429) { - let bucket = getBucket( this, response ) + let bucket = getBucket( this, response.headers ) bucket.link(path) // link the bucket so that hopefully no future errors occur return this.queue(path, options) /* it was ratelimited after all diff --git a/src/server/lib/files.ts b/src/server/lib/files.ts index 33b4495..5a1acce 100644 --- a/src/server/lib/files.ts +++ b/src/server/lib/files.ts @@ -4,7 +4,7 @@ import { readFile, writeFile } from "node:fs/promises" import { Readable } from "node:stream" import crypto from "node:crypto" import { files } from "./accounts" -import * as API from "./DiscordAPI" +import { Client as API } from "./DiscordAPI" import type {APIAttachment} from "discord-api-types/v10" import * as Accounts from "./accounts" @@ -75,13 +75,13 @@ export interface StatusCodeError { export default class Files { config: Configuration client: Client - api: API.Client + api: API files: { [key: string]: FilePointer } = {} uploadChannel?: TextBasedChannel constructor(config: Configuration) { this.config = config - this.api = new API.Client(process.env.TOKEN!, config.targetChannel) + this.api = new API(process.env.TOKEN!, config.targetChannel) this.client = new Client({ intents: [ IntentsBitField.Flags.GuildMessages, @@ -236,8 +236,7 @@ export default class Files { if (existingFile && this.uploadChannel) { for (let x of existingFile.messageids) { - this.uploadChannel.messages - .delete(x) + this.api.deleteMessage(x) .catch((err) => console.error(err)) } } @@ -499,8 +498,7 @@ export default class Files { return } for (let x of tmp.messageids) { - this.uploadChannel.messages - .delete(x) + this.api.deleteMessage(x) .catch((err) => console.error(err)) }