From 528007872d37b17138275776daa705db6b63bb91 Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Tue, 7 Sep 2021 22:54:31 +0200 Subject: Update User.ts --- util/src/entities/User.ts | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'util/src') diff --git a/util/src/entities/User.ts b/util/src/entities/User.ts index f44b37b3..9394f9e8 100644 --- a/util/src/entities/User.ts +++ b/util/src/entities/User.ts @@ -250,13 +250,18 @@ export class UserFlags extends BitField { PARTNERED_SERVER_OWNER: BigInt(1) << BigInt(1), HYPESQUAD_EVENTS: BigInt(1) << BigInt(2), BUGHUNTER_LEVEL_1: BigInt(1) << BigInt(3), + MFA_SMS: BigInt(1) << BigInt(4), + PREMIUM_PROMO_DISMISSED: BigInt(1) << BigInt(5), HOUSE_BRAVERY: BigInt(1) << BigInt(6), HOUSE_BRILLIANCE: BigInt(1) << BigInt(7), HOUSE_BALANCE: BigInt(1) << BigInt(8), EARLY_SUPPORTER: BigInt(1) << BigInt(9), TEAM_USER: BigInt(1) << BigInt(10), + TRUST_AND_SAFETY: BigInt(1) << BigInt(11), SYSTEM: BigInt(1) << BigInt(12), + HAS_UNREAD_URGENT_MESSAGES: BigInt(1) << BigInt(13), BUGHUNTER_LEVEL_2: BigInt(1) << BigInt(14), + UNDERAGE_DELETED: BigInt(1) << BigInt(15), VERIFIED_BOT: BigInt(1) << BigInt(16), EARLY_VERIFIED_BOT_DEVELOPER: BigInt(1) << BigInt(17), }; -- cgit 1.5.1 From d50073fc41fc7d69d3dab9a2858158320983329b Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Sun, 12 Sep 2021 21:09:29 +0200 Subject: :art: remove long relatives paths -> short module paths --- api/package-lock.json | 76 +- api/package.json | 3 +- api/scripts/tsconfig-paths-bootstrap.js | 10 + api/src/index.ts | 11 +- api/src/middlewares/ErrorHandler.ts | 2 +- api/src/middlewares/RateLimit.ts | 2 +- api/src/routes/auth/login.ts | 2 +- api/src/routes/auth/register.ts | 4 +- api/src/routes/channels/#channel_id/index.ts | 2 +- api/src/routes/channels/#channel_id/invites.ts | 4 +- .../#channel_id/messages/#message_id/ack.ts | 2 +- .../#channel_id/messages/#message_id/index.ts | 4 +- .../channels/#channel_id/messages/bulk-delete.ts | 2 +- .../routes/channels/#channel_id/messages/index.ts | 6 +- api/src/routes/channels/#channel_id/permissions.ts | 2 +- api/src/routes/channels/#channel_id/webhooks.ts | 2 +- api/src/routes/guilds/#guild_id/bans.ts | 5 +- api/src/routes/guilds/#guild_id/channels.ts | 2 +- api/src/routes/guilds/#guild_id/index.ts | 4 +- .../guilds/#guild_id/members/#member_id/index.ts | 4 +- api/src/routes/guilds/#guild_id/members/index.ts | 2 +- api/src/routes/guilds/#guild_id/regions.ts | 6 +- api/src/routes/guilds/#guild_id/roles.ts | 2 +- api/src/routes/guilds/#guild_id/templates.ts | 4 +- api/src/routes/guilds/#guild_id/vanity-url.ts | 2 +- .../#guild_id/voice-states/#user_id/index.ts | 8 +- .../guilds/#guild_id/voice-states/@me/index.ts | 8 +- api/src/routes/guilds/#guild_id/welcome_screen.ts | 2 +- api/src/routes/guilds/#guild_id/widget.json.ts | 2 +- api/src/routes/guilds/#guild_id/widget.ts | 2 +- api/src/routes/guilds/index.ts | 2 +- api/src/routes/guilds/templates/index.ts | 2 +- api/src/routes/users/#id/index.ts | 2 +- api/src/routes/users/#id/profile.ts | 2 +- api/src/routes/users/@me/channels.ts | 6 +- api/src/routes/users/@me/index.ts | 4 +- api/src/routes/users/@me/relationships.ts | 2 +- api/src/routes/users/@me/settings.ts | 2 +- api/src/routes/voice/regions.ts | 6 +- api/src/test/password_test.ts | 12 +- api/src/util/index.ts | 11 + api/src/util/passwordStrength.ts | 2 +- api/tests/automatic.test.js | 0 api/tsconfig.json | 7 +- bundle/package-lock.json | 83 +- bundle/package.json | 5 +- bundle/tsconfig-paths-bootstrap.js | 14 + cdn/package.json | 2 +- cdn/scripts/tsconfig-paths-bootstrap.js | 10 + cdn/src/routes/attachments.ts | 120 ++- cdn/src/routes/avatars.ts | 70 +- cdn/src/routes/external.ts | 5 +- cdn/tsconfig.json | 7 +- gateway/package-lock.json | 1056 +++++++++++++++++++- gateway/package.json | 3 +- gateway/scripts/tsconfig-paths-bootstrap.js | 10 + gateway/src/events/Close.ts | 2 +- gateway/src/events/Connection.ts | 23 +- gateway/src/events/Message.ts | 13 +- gateway/src/index.ts | 3 + gateway/src/listener/listener.ts | 10 +- gateway/src/opcodes/Heartbeat.ts | 8 +- gateway/src/opcodes/Identify.ts | 10 +- gateway/src/opcodes/LazyRequest.ts | 6 +- gateway/src/opcodes/PresenceUpdate.ts | 4 +- gateway/src/opcodes/RequestGuildMembers.ts | 4 +- gateway/src/opcodes/Resume.ts | 6 +- gateway/src/opcodes/VoiceStateUpdate.ts | 46 +- gateway/src/opcodes/index.ts | 4 +- gateway/src/opcodes/instanceOf.ts | 4 +- gateway/src/util/Send.ts | 2 +- gateway/src/util/WebSocket.ts | 4 +- gateway/src/util/index.ts | 5 + gateway/tsconfig.json | 7 +- util/package-lock.json | 67 ++ util/package.json | 1 + util/src/interfaces/Event.ts | 45 + util/src/util/Constants.ts | 2 +- util/src/util/Database.ts | 2 +- 79 files changed, 1641 insertions(+), 269 deletions(-) create mode 100644 api/scripts/tsconfig-paths-bootstrap.js create mode 100644 api/src/util/index.ts create mode 100644 api/tests/automatic.test.js create mode 100644 bundle/tsconfig-paths-bootstrap.js create mode 100644 cdn/scripts/tsconfig-paths-bootstrap.js create mode 100644 gateway/scripts/tsconfig-paths-bootstrap.js create mode 100644 gateway/src/util/index.ts (limited to 'util/src') diff --git a/api/package-lock.json b/api/package-lock.json index 7b1e000b..8b2c93f8 100644 --- a/api/package-lock.json +++ b/api/package-lock.json @@ -38,6 +38,7 @@ "node-fetch": "^2.6.1", "patch-package": "^6.4.7", "supertest": "^6.1.6", + "tsconfig-paths": "^3.11.0", "typeorm": "^0.2.37" }, "devDependencies": { @@ -79,12 +80,13 @@ "env-paths": "^2.2.1", "jsonwebtoken": "^8.5.1", "lambert-server": "^1.2.10", - "missing-native-js-functions": "^1.2.14", + "missing-native-js-functions": "^1.2.15", "node-fetch": "^2.6.1", "patch-package": "^6.4.7", "pg": "^8.7.1", "reflect-metadata": "^0.1.13", "sqlite3": "^5.0.2", + "tsconfig-paths": "^3.11.0", "typeorm": "^0.2.37", "typescript": "^4.4.2", "typescript-json-schema": "^0.50.1" @@ -1396,6 +1398,11 @@ "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", "dev": true }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=" + }, "node_modules/@types/jsonwebtoken": { "version": "8.5.4", "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.5.4.tgz", @@ -11344,6 +11351,36 @@ "strip-json-comments": "^2.0.0" } }, + "node_modules/tsconfig-paths": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.11.0.tgz", + "integrity": "sha512-7ecdYDnIdmv639mmDwslG6KQg1Z9STTz1j7Gcz0xa+nshh/gKDAHcPxRbWOsA3SPp0tXP2leTcY9Kw+NAkfZzA==", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.0", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/tsconfig-paths/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "engines": { + "node": ">=4" + } + }, "node_modules/tsconfig/node_modules/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", @@ -12977,12 +13014,13 @@ "jest": "^27.0.6", "jsonwebtoken": "^8.5.1", "lambert-server": "^1.2.10", - "missing-native-js-functions": "^1.2.14", + "missing-native-js-functions": "^1.2.15", "node-fetch": "^2.6.1", "patch-package": "^6.4.7", "pg": "^8.7.1", "reflect-metadata": "^0.1.13", "sqlite3": "^5.0.2", + "tsconfig-paths": "^3.11.0", "typeorm": "^0.2.37", "typescript": "^4.4.2", "typescript-json-schema": "^0.50.1" @@ -13574,6 +13612,11 @@ "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", "dev": true }, + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=" + }, "@types/jsonwebtoken": { "version": "8.5.4", "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.5.4.tgz", @@ -18703,8 +18746,7 @@ "dev": true }, "mpath": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.8.4.tgz", + "version": "https://registry.npmjs.org/mpath/-/mpath-0.8.4.tgz", "integrity": "sha512-eb9rRvhDltXVNL6Fxd2zM9D4vKBxjVVQNLNijlj7uoXUy19zNDsIif5zR+pWmPCWNKwAtqyo4JveQm4nfD5+eA==" }, "mquery": { @@ -21726,6 +21768,32 @@ } } }, + "tsconfig-paths": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.11.0.tgz", + "integrity": "sha512-7ecdYDnIdmv639mmDwslG6KQg1Z9STTz1j7Gcz0xa+nshh/gKDAHcPxRbWOsA3SPp0tXP2leTcY9Kw+NAkfZzA==", + "requires": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.0", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "requires": { + "minimist": "^1.2.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" + } + } + }, "tslib": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", diff --git a/api/package.json b/api/package.json index a501fb15..b762b944 100644 --- a/api/package.json +++ b/api/package.json @@ -7,7 +7,7 @@ "scripts": { "test": "npm run build && jest --coverage --verbose --forceExit ./tests", "test:watch": "jest --watch", - "start": "npm run build && node dist/start", + "start": "npm run build && node -r ./scripts/tsconfig-paths-bootstrap.js dist/start", "build": "npx tsc -b .", "build-docker": "tsc -p tsconfig-docker.json", "dev": "tsnd --respawn src/start.ts", @@ -86,6 +86,7 @@ "node-fetch": "^2.6.1", "patch-package": "^6.4.7", "supertest": "^6.1.6", + "tsconfig-paths": "^3.11.0", "typeorm": "^0.2.37" }, "jest": { diff --git a/api/scripts/tsconfig-paths-bootstrap.js b/api/scripts/tsconfig-paths-bootstrap.js new file mode 100644 index 00000000..d6ad3c57 --- /dev/null +++ b/api/scripts/tsconfig-paths-bootstrap.js @@ -0,0 +1,10 @@ +const tsConfigPaths = require("tsconfig-paths"); +const path = require("path"); + +const cleanup = tsConfigPaths.register({ + baseUrl: path.join(__dirname, ".."), + paths: { + "@fosscord/api": ["dist/index.js"], + "@fosscord/api/*": ["dist/*"] + } +}); diff --git a/api/src/index.ts b/api/src/index.ts index fe59310f..adc7649c 100644 --- a/api/src/index.ts +++ b/api/src/index.ts @@ -1,12 +1,3 @@ export * from "./Server"; export * from "./middlewares/"; -export * from "./schema/Ban"; -export * from "./schema/Channel"; -export * from "./schema/Guild"; -export * from "./schema/Invite"; -export * from "./schema/Message"; -export * from "./util/instanceOf"; -export * from "./util/instanceOf"; -export * from "./util/RandomInviteID"; -export * from "./util/String"; -export { check as checkPassword } from "./util/passwordStrength"; +export * from "./util/"; diff --git a/api/src/middlewares/ErrorHandler.ts b/api/src/middlewares/ErrorHandler.ts index be2586cf..d288f3fb 100644 --- a/api/src/middlewares/ErrorHandler.ts +++ b/api/src/middlewares/ErrorHandler.ts @@ -1,7 +1,7 @@ import { NextFunction, Request, Response } from "express"; import { HTTPError } from "lambert-server"; import { EntityNotFoundError } from "typeorm"; -import { FieldError } from "../util/instanceOf"; +import { FieldError } from "@fosscord/api"; import { ApiError } from "@fosscord/util"; export function ErrorHandler(error: Error, req: Request, res: Response, next: NextFunction) { diff --git a/api/src/middlewares/RateLimit.ts b/api/src/middlewares/RateLimit.ts index dffbc0d9..d1fd072f 100644 --- a/api/src/middlewares/RateLimit.ts +++ b/api/src/middlewares/RateLimit.ts @@ -1,6 +1,6 @@ import { Config, listenEvent } from "@fosscord/util"; import { NextFunction, Request, Response, Router } from "express"; -import { getIpAdress } from "../util/ipAddress"; +import { getIpAdress } from "@fosscord/api"; import { API_PREFIX_TRAILING_SLASH } from "./Authentication"; // Docs: https://discord.com/developers/docs/topics/rate-limits diff --git a/api/src/routes/auth/login.ts b/api/src/routes/auth/login.ts index 7fd0f870..2e2f763d 100644 --- a/api/src/routes/auth/login.ts +++ b/api/src/routes/auth/login.ts @@ -1,5 +1,5 @@ import { Request, Response, Router } from "express"; -import { check, FieldErrors, Length } from "../../util/instanceOf"; +import { check, FieldErrors, Length } from "@fosscord/api"; import bcrypt from "bcrypt"; import jwt from "jsonwebtoken"; import { Config, User } from "@fosscord/util"; diff --git a/api/src/routes/auth/register.ts b/api/src/routes/auth/register.ts index a9518e91..d3c85778 100644 --- a/api/src/routes/auth/register.ts +++ b/api/src/routes/auth/register.ts @@ -1,10 +1,10 @@ import { Request, Response, Router } from "express"; import { trimSpecial, User, Snowflake, Config, defaultSettings } from "@fosscord/util"; import bcrypt from "bcrypt"; -import { check, Email, EMAIL_REGEX, FieldErrors, Length } from "../../util/instanceOf"; +import { check, Email, EMAIL_REGEX, FieldErrors, Length } from "@fosscord/api"; import "missing-native-js-functions"; import { generateToken } from "./login"; -import { getIpAdress, IPAnalysis, isProxy } from "../../util/ipAddress"; +import { getIpAdress, IPAnalysis, isProxy } from "@fosscord/api"; import { HTTPError } from "lambert-server"; import { In } from "typeorm"; diff --git a/api/src/routes/channels/#channel_id/index.ts b/api/src/routes/channels/#channel_id/index.ts index 4aa5a5b9..46554d70 100644 --- a/api/src/routes/channels/#channel_id/index.ts +++ b/api/src/routes/channels/#channel_id/index.ts @@ -2,7 +2,7 @@ import { ChannelDeleteEvent, Channel, ChannelUpdateEvent, emitEvent, getPermissi import { Router, Response, Request } from "express"; import { HTTPError } from "lambert-server"; import { ChannelModifySchema } from "../../../schema/Channel"; -import { check } from "../../../util/instanceOf"; +import { check } from "@fosscord/api"; const router: Router = Router(); // TODO: delete channel // TODO: Get channel diff --git a/api/src/routes/channels/#channel_id/invites.ts b/api/src/routes/channels/#channel_id/invites.ts index fe22d3bc..c6909fd0 100644 --- a/api/src/routes/channels/#channel_id/invites.ts +++ b/api/src/routes/channels/#channel_id/invites.ts @@ -1,7 +1,7 @@ import { Router, Request, Response } from "express"; import { HTTPError } from "lambert-server"; -import { check } from "../../../util/instanceOf"; -import { random } from "../../../util/RandomInviteID"; +import { check } from "@fosscord/api"; +import { random } from "@fosscord/api"; import { InviteCreateSchema } from "../../../schema/Invite"; import { getPermission, Channel, Invite, InviteCreateEvent, emitEvent, User, Guild, PublicInviteRelation } from "@fosscord/util"; import { isTextChannel } from "./messages"; diff --git a/api/src/routes/channels/#channel_id/messages/#message_id/ack.ts b/api/src/routes/channels/#channel_id/messages/#message_id/ack.ts index 0fd5f2be..aab51484 100644 --- a/api/src/routes/channels/#channel_id/messages/#message_id/ack.ts +++ b/api/src/routes/channels/#channel_id/messages/#message_id/ack.ts @@ -1,7 +1,7 @@ import { emitEvent, getPermission, MessageAckEvent, ReadState } from "@fosscord/util"; import { Request, Response, Router } from "express"; -import { check } from "../../../../../util/instanceOf"; +import { check } from "@fosscord/api"; const router = Router(); diff --git a/api/src/routes/channels/#channel_id/messages/#message_id/index.ts b/api/src/routes/channels/#channel_id/messages/#message_id/index.ts index 7a00de43..e9588bd3 100644 --- a/api/src/routes/channels/#channel_id/messages/#message_id/index.ts +++ b/api/src/routes/channels/#channel_id/messages/#message_id/index.ts @@ -1,8 +1,8 @@ import { Channel, emitEvent, getPermission, MessageDeleteEvent, Message, MessageUpdateEvent } from "@fosscord/util"; import { Router, Response, Request } from "express"; import { MessageCreateSchema } from "../../../../../schema/Message"; -import { check } from "../../../../../util/instanceOf"; -import { handleMessage, postHandleMessage } from "../../../../../util/Message"; +import { check } from "@fosscord/api"; +import { handleMessage, postHandleMessage } from "@fosscord/api"; const router = Router(); diff --git a/api/src/routes/channels/#channel_id/messages/bulk-delete.ts b/api/src/routes/channels/#channel_id/messages/bulk-delete.ts index 5c486676..5d7566e1 100644 --- a/api/src/routes/channels/#channel_id/messages/bulk-delete.ts +++ b/api/src/routes/channels/#channel_id/messages/bulk-delete.ts @@ -2,7 +2,7 @@ import { Router, Response, Request } from "express"; import { Channel, Config, emitEvent, getPermission, MessageDeleteBulkEvent, Message } from "@fosscord/util"; import { HTTPError } from "lambert-server"; -import { check } from "../../../../util/instanceOf"; +import { check } from "@fosscord/api"; import { In } from "typeorm"; const router: Router = Router(); diff --git a/api/src/routes/channels/#channel_id/messages/index.ts b/api/src/routes/channels/#channel_id/messages/index.ts index ad590d05..591ebbbe 100644 --- a/api/src/routes/channels/#channel_id/messages/index.ts +++ b/api/src/routes/channels/#channel_id/messages/index.ts @@ -2,11 +2,11 @@ import { Router, Response, Request } from "express"; import { Attachment, Channel, ChannelType, getPermission, Message } from "@fosscord/util"; import { HTTPError } from "lambert-server"; import { MessageCreateSchema } from "../../../../schema/Message"; -import { check, instanceOf, Length } from "../../../../util/instanceOf"; +import { check, instanceOf, Length } from "@fosscord/api"; import multer from "multer"; import { Query } from "mongoose"; -import { sendMessage } from "../../../../util/Message"; -import { uploadFile } from "../../../../util/cdn"; +import { sendMessage } from "@fosscord/api"; +import { uploadFile } from "@fosscord/api"; import { FindManyOptions, LessThan, MoreThan } from "typeorm"; const router: Router = Router(); diff --git a/api/src/routes/channels/#channel_id/permissions.ts b/api/src/routes/channels/#channel_id/permissions.ts index 9c49542b..0465ca31 100644 --- a/api/src/routes/channels/#channel_id/permissions.ts +++ b/api/src/routes/channels/#channel_id/permissions.ts @@ -2,7 +2,7 @@ import { Channel, ChannelPermissionOverwrite, ChannelUpdateEvent, emitEvent, get import { Router, Response, Request } from "express"; import { HTTPError } from "lambert-server"; -import { check } from "../../../util/instanceOf"; +import { check } from "@fosscord/api"; const router: Router = Router(); // TODO: Only permissions your bot has in the guild or channel can be allowed/denied (unless your bot has a MANAGE_ROLES overwrite in the channel) diff --git a/api/src/routes/channels/#channel_id/webhooks.ts b/api/src/routes/channels/#channel_id/webhooks.ts index e4125879..821a62db 100644 --- a/api/src/routes/channels/#channel_id/webhooks.ts +++ b/api/src/routes/channels/#channel_id/webhooks.ts @@ -1,5 +1,5 @@ import { Router, Response, Request } from "express"; -import { check, Length } from "../../../util/instanceOf"; +import { check, Length } from "@fosscord/api"; import { Channel, Config, getPermission, trimSpecial, Webhook } from "@fosscord/util"; import { HTTPError } from "lambert-server"; import { isTextChannel } from "./messages/index"; diff --git a/api/src/routes/guilds/#guild_id/bans.ts b/api/src/routes/guilds/#guild_id/bans.ts index 31aa2385..86bff6b4 100644 --- a/api/src/routes/guilds/#guild_id/bans.ts +++ b/api/src/routes/guilds/#guild_id/bans.ts @@ -1,9 +1,8 @@ import { Request, Response, Router } from "express"; import { emitEvent, getPermission, GuildBanAddEvent, GuildBanRemoveEvent, Guild, Ban, User, Member } from "@fosscord/util"; import { HTTPError } from "lambert-server"; -import { getIpAdress } from "../../../util/ipAddress"; -import { BanCreateSchema } from "../../../schema/Ban"; -import { check } from "../../../util/instanceOf"; +import { getIpAdress, check } from "@fosscord/api"; +import { BanCreateSchema } from "@fosscord/api/schema/Ban"; const router: Router = Router(); diff --git a/api/src/routes/guilds/#guild_id/channels.ts b/api/src/routes/guilds/#guild_id/channels.ts index 5aa1d33d..faeecb76 100644 --- a/api/src/routes/guilds/#guild_id/channels.ts +++ b/api/src/routes/guilds/#guild_id/channels.ts @@ -3,7 +3,7 @@ import { Channel, ChannelUpdateEvent, getPermission, emitEvent } from "@fosscord import { HTTPError } from "lambert-server"; import { ChannelModifySchema } from "../../../schema/Channel"; -import { check } from "../../../util/instanceOf"; +import { check } from "@fosscord/api"; const router = Router(); router.get("/", async (req: Request, res: Response) => { diff --git a/api/src/routes/guilds/#guild_id/index.ts b/api/src/routes/guilds/#guild_id/index.ts index 9d302a48..244900ec 100644 --- a/api/src/routes/guilds/#guild_id/index.ts +++ b/api/src/routes/guilds/#guild_id/index.ts @@ -3,8 +3,8 @@ import { emitEvent, getPermission, Guild, GuildUpdateEvent, Member } from "@foss import { HTTPError } from "lambert-server"; import { GuildUpdateSchema } from "../../../schema/Guild"; -import { check } from "../../../util/instanceOf"; -import { handleFile } from "../../../util/cdn"; +import { check } from "@fosscord/api"; +import { handleFile } from "@fosscord/api"; import "missing-native-js-functions"; const router = Router(); diff --git a/api/src/routes/guilds/#guild_id/members/#member_id/index.ts b/api/src/routes/guilds/#guild_id/members/#member_id/index.ts index 0d62e555..8b04a508 100644 --- a/api/src/routes/guilds/#guild_id/members/#member_id/index.ts +++ b/api/src/routes/guilds/#guild_id/members/#member_id/index.ts @@ -11,8 +11,8 @@ import { emitEvent } from "@fosscord/util"; import { HTTPError } from "lambert-server"; -import { check } from "../../../../../util/instanceOf"; -import { MemberChangeSchema } from "../../../../../schema/Member"; +import { check } from "@fosscord/api"; +import { MemberChangeSchema } from "@fosscord/api/schema/Member"; import { In } from "typeorm"; const router = Router(); diff --git a/api/src/routes/guilds/#guild_id/members/index.ts b/api/src/routes/guilds/#guild_id/members/index.ts index 0bfd71cb..198d6946 100644 --- a/api/src/routes/guilds/#guild_id/members/index.ts +++ b/api/src/routes/guilds/#guild_id/members/index.ts @@ -1,6 +1,6 @@ import { Request, Response, Router } from "express"; import { Guild, Member, PublicMemberProjection } from "@fosscord/util"; -import { instanceOf, Length } from "../../../../util/instanceOf"; +import { instanceOf, Length } from "@fosscord/api"; import { MoreThan } from "typeorm"; const router = Router(); diff --git a/api/src/routes/guilds/#guild_id/regions.ts b/api/src/routes/guilds/#guild_id/regions.ts index 212c9bcd..86208b79 100644 --- a/api/src/routes/guilds/#guild_id/regions.ts +++ b/api/src/routes/guilds/#guild_id/regions.ts @@ -1,7 +1,7 @@ -import {Config, Guild, Member} from "@fosscord/util"; +import { Config, Guild, Member } from "@fosscord/util"; import { Request, Response, Router } from "express"; -import {getVoiceRegions} from "../../../util/Voice"; -import {getIpAdress} from "../../../util/ipAddress"; +import { getVoiceRegions } from "@fosscord/api"; +import { getIpAdress } from "@fosscord/api"; const router = Router(); diff --git a/api/src/routes/guilds/#guild_id/roles.ts b/api/src/routes/guilds/#guild_id/roles.ts index 6a318688..76dd47c5 100644 --- a/api/src/routes/guilds/#guild_id/roles.ts +++ b/api/src/routes/guilds/#guild_id/roles.ts @@ -12,7 +12,7 @@ import { } from "@fosscord/util"; import { HTTPError } from "lambert-server"; -import { check } from "../../../util/instanceOf"; +import { check } from "@fosscord/api"; import { RoleModifySchema, RolePositionUpdateSchema } from "../../../schema/Roles"; import { DiscordApiErrors } from "@fosscord/util"; import { In } from "typeorm"; diff --git a/api/src/routes/guilds/#guild_id/templates.ts b/api/src/routes/guilds/#guild_id/templates.ts index a7613abf..e9304e11 100644 --- a/api/src/routes/guilds/#guild_id/templates.ts +++ b/api/src/routes/guilds/#guild_id/templates.ts @@ -2,8 +2,8 @@ import { Request, Response, Router } from "express"; import { Guild, getPermission, Template } from "@fosscord/util"; import { HTTPError } from "lambert-server"; import { TemplateCreateSchema, TemplateModifySchema } from "../../../schema/Template"; -import { check } from "../../../util/instanceOf"; -import { generateCode } from "../../../util/String"; +import { check } from "@fosscord/api"; +import { generateCode } from "@fosscord/api"; const router: Router = Router(); diff --git a/api/src/routes/guilds/#guild_id/vanity-url.ts b/api/src/routes/guilds/#guild_id/vanity-url.ts index 58940b42..f1887cc0 100644 --- a/api/src/routes/guilds/#guild_id/vanity-url.ts +++ b/api/src/routes/guilds/#guild_id/vanity-url.ts @@ -1,7 +1,7 @@ import { Channel, ChannelType, getPermission, Guild, Invite, trimSpecial } from "@fosscord/util"; import { Router, Request, Response } from "express"; import { HTTPError } from "lambert-server"; -import { check, Length } from "../../../util/instanceOf"; +import { check, Length } from "@fosscord/api"; const router = Router(); diff --git a/api/src/routes/guilds/#guild_id/voice-states/#user_id/index.ts b/api/src/routes/guilds/#guild_id/voice-states/#user_id/index.ts index 02951f81..447e15c1 100644 --- a/api/src/routes/guilds/#guild_id/voice-states/#user_id/index.ts +++ b/api/src/routes/guilds/#guild_id/voice-states/#user_id/index.ts @@ -1,15 +1,15 @@ -import { check } from "../../../../../util/instanceOf"; +import { check } from "@fosscord/api"; import { VoiceStateUpdateSchema } from "../../../../../schema"; import { Request, Response, Router } from "express"; -import { updateVoiceState } from "../../../../../util/VoiceState"; +import { updateVoiceState } from "@fosscord/api"; const router = Router(); router.patch("/", check(VoiceStateUpdateSchema), async (req: Request, res: Response) => { const body = req.body as VoiceStateUpdateSchema; const { guild_id, user_id } = req.params; - await updateVoiceState(body, guild_id, req.user_id, user_id) + await updateVoiceState(body, guild_id, req.user_id, user_id); return res.sendStatus(204); }); -export default router; \ No newline at end of file +export default router; diff --git a/api/src/routes/guilds/#guild_id/voice-states/@me/index.ts b/api/src/routes/guilds/#guild_id/voice-states/@me/index.ts index 42ba543e..b637ff66 100644 --- a/api/src/routes/guilds/#guild_id/voice-states/@me/index.ts +++ b/api/src/routes/guilds/#guild_id/voice-states/@me/index.ts @@ -1,15 +1,15 @@ -import { check } from "../../../../../util/instanceOf"; +import { check } from "@fosscord/api"; import { VoiceStateUpdateSchema } from "../../../../../schema"; import { Request, Response, Router } from "express"; -import { updateVoiceState } from "../../../../../util/VoiceState"; +import { updateVoiceState } from "@fosscord/api"; const router = Router(); router.patch("/", check(VoiceStateUpdateSchema), async (req: Request, res: Response) => { const body = req.body as VoiceStateUpdateSchema; const { guild_id } = req.params; - await updateVoiceState(body, guild_id, req.user_id) + await updateVoiceState(body, guild_id, req.user_id); return res.sendStatus(204); }); -export default router; \ No newline at end of file +export default router; diff --git a/api/src/routes/guilds/#guild_id/welcome_screen.ts b/api/src/routes/guilds/#guild_id/welcome_screen.ts index defbcd40..7ca49b4e 100644 --- a/api/src/routes/guilds/#guild_id/welcome_screen.ts +++ b/api/src/routes/guilds/#guild_id/welcome_screen.ts @@ -2,7 +2,7 @@ import { Request, Response, Router } from "express"; import { Guild, getPermission, Snowflake, Member } from "@fosscord/util"; import { HTTPError } from "lambert-server"; -import { check } from "../../../util/instanceOf"; +import { check } from "@fosscord/api"; import { GuildUpdateWelcomeScreenSchema } from "../../../schema/Guild"; const router: Router = Router(); diff --git a/api/src/routes/guilds/#guild_id/widget.json.ts b/api/src/routes/guilds/#guild_id/widget.json.ts index 193ed095..f871fac8 100644 --- a/api/src/routes/guilds/#guild_id/widget.json.ts +++ b/api/src/routes/guilds/#guild_id/widget.json.ts @@ -1,7 +1,7 @@ import { Request, Response, Router } from "express"; import { Config, Permissions, Guild, Invite, Channel, Member } from "@fosscord/util"; import { HTTPError } from "lambert-server"; -import { random } from "../../../util/RandomInviteID"; +import { random } from "@fosscord/api"; const router: Router = Router(); diff --git a/api/src/routes/guilds/#guild_id/widget.ts b/api/src/routes/guilds/#guild_id/widget.ts index fcf71402..d9ce817e 100644 --- a/api/src/routes/guilds/#guild_id/widget.ts +++ b/api/src/routes/guilds/#guild_id/widget.ts @@ -1,7 +1,7 @@ import { Request, Response, Router } from "express"; import { getPermission, Guild } from "@fosscord/util"; import { HTTPError } from "lambert-server"; -import { check } from "../../../util/instanceOf"; +import { check } from "@fosscord/api"; import { WidgetModifySchema } from "../../../schema/Widget"; const router: Router = Router(); diff --git a/api/src/routes/guilds/index.ts b/api/src/routes/guilds/index.ts index e5830647..a1b199e7 100644 --- a/api/src/routes/guilds/index.ts +++ b/api/src/routes/guilds/index.ts @@ -1,7 +1,7 @@ import { Router, Request, Response } from "express"; import { Role, Guild, Snowflake, Config, User, Member, Channel } from "@fosscord/util"; import { HTTPError } from "lambert-server"; -import { check } from "./../../util/instanceOf"; +import { check } from "@fosscord/api"; import { GuildCreateSchema } from "../../schema/Guild"; import { DiscordApiErrors } from "@fosscord/util"; diff --git a/api/src/routes/guilds/templates/index.ts b/api/src/routes/guilds/templates/index.ts index 58201f65..1d0f2716 100644 --- a/api/src/routes/guilds/templates/index.ts +++ b/api/src/routes/guilds/templates/index.ts @@ -3,7 +3,7 @@ const router: Router = Router(); import { Template, Guild, Role, Snowflake, Config, User, Member } from "@fosscord/util"; import { HTTPError } from "lambert-server"; import { GuildTemplateCreateSchema } from "../../../schema/Guild"; -import { check } from "../../../util/instanceOf"; +import { check } from "@fosscord/api"; import { DiscordApiErrors } from "@fosscord/util"; router.get("/:code", async (req: Request, res: Response) => { diff --git a/api/src/routes/users/#id/index.ts b/api/src/routes/users/#id/index.ts index 3841756b..07956360 100644 --- a/api/src/routes/users/#id/index.ts +++ b/api/src/routes/users/#id/index.ts @@ -1,5 +1,5 @@ import { Router, Request, Response } from "express"; -import { User } from "../../../../../util/dist"; +import { User } from "@fosscord/util"; const router: Router = Router(); diff --git a/api/src/routes/users/#id/profile.ts b/api/src/routes/users/#id/profile.ts index 8be03b47..0f43a82f 100644 --- a/api/src/routes/users/#id/profile.ts +++ b/api/src/routes/users/#id/profile.ts @@ -1,5 +1,5 @@ import { Router, Request, Response } from "express"; -import { PublicConnectedAccount, PublicUser, User, UserPublic } from "../../../../../util/dist"; +import { PublicConnectedAccount, PublicUser, User, UserPublic } from "@fosscord/util"; const router: Router = Router(); diff --git a/api/src/routes/users/@me/channels.ts b/api/src/routes/users/@me/channels.ts index 6fd396b8..77fc8296 100644 --- a/api/src/routes/users/@me/channels.ts +++ b/api/src/routes/users/@me/channels.ts @@ -1,11 +1,9 @@ import { Router, Request, Response } from "express"; -import { Channel, ChannelCreateEvent, ChannelType, Snowflake, trimSpecial, User, emitEvent } from "@fosscord/util"; +import { Channel, ChannelCreateEvent, ChannelType, Snowflake, trimSpecial, User, emitEvent, Recipient } from "@fosscord/util"; import { HTTPError } from "lambert-server"; - import { DmChannelCreateSchema } from "../../../schema/Channel"; -import { check } from "../../../util/instanceOf"; +import { check } from "@fosscord/api"; import { In } from "typeorm"; -import { Recipient } from "../../../../../util/dist/entities/Recipient"; const router: Router = Router(); diff --git a/api/src/routes/users/@me/index.ts b/api/src/routes/users/@me/index.ts index 68649215..451a657c 100644 --- a/api/src/routes/users/@me/index.ts +++ b/api/src/routes/users/@me/index.ts @@ -1,8 +1,8 @@ import { Router, Request, Response } from "express"; import { User, PrivateUserProjection } from "@fosscord/util"; import { UserModifySchema } from "../../../schema/User"; -import { check } from "../../../util/instanceOf"; -import { handleFile } from "../../../util/cdn"; +import { check } from "@fosscord/api"; +import { handleFile } from "@fosscord/api"; const router: Router = Router(); diff --git a/api/src/routes/users/@me/relationships.ts b/api/src/routes/users/@me/relationships.ts index 995b0244..67ca2f35 100644 --- a/api/src/routes/users/@me/relationships.ts +++ b/api/src/routes/users/@me/relationships.ts @@ -12,7 +12,7 @@ import { Router, Response, Request } from "express"; import { HTTPError } from "lambert-server"; import { DiscordApiErrors } from "@fosscord/util"; -import { check, Length } from "../../../util/instanceOf"; +import { check, Length } from "@fosscord/api"; const router = Router(); diff --git a/api/src/routes/users/@me/settings.ts b/api/src/routes/users/@me/settings.ts index 90ee6372..e7db85ed 100644 --- a/api/src/routes/users/@me/settings.ts +++ b/api/src/routes/users/@me/settings.ts @@ -1,6 +1,6 @@ import { Router, Response, Request } from "express"; import { User, UserSettings } from "@fosscord/util"; -import { check } from "../../../util/instanceOf"; +import { check } from "@fosscord/api"; import { UserSettingsSchema } from "../../../schema/User"; const router = Router(); diff --git a/api/src/routes/voice/regions.ts b/api/src/routes/voice/regions.ts index 812aa8f6..da1aaade 100644 --- a/api/src/routes/voice/regions.ts +++ b/api/src/routes/voice/regions.ts @@ -1,11 +1,11 @@ import { Router, Request, Response } from "express"; -import {getIpAdress} from "../../util/ipAddress"; -import {getVoiceRegions} from "../../util/Voice"; +import { getIpAdress } from "@fosscord/api"; +import { getVoiceRegions } from "@fosscord/api"; const router: Router = Router(); router.get("/", async (req: Request, res: Response) => { - res.json(await getVoiceRegions(getIpAdress(req), true))//vip true? + res.json(await getVoiceRegions(getIpAdress(req), true)); //vip true? }); export default router; diff --git a/api/src/test/password_test.ts b/api/src/test/password_test.ts index 59d36621..983b18ae 100644 --- a/api/src/test/password_test.ts +++ b/api/src/test/password_test.ts @@ -1,12 +1,12 @@ -import { check } from "./../util/passwordStrength"; +import { checkPassword } from "@fosscord/api"; -console.log(check("123456789012345")); +console.log(checkPassword("123456789012345")); // -> 0.25 -console.log(check("ABCDEFGHIJKLMOPQ")); +console.log(checkPassword("ABCDEFGHIJKLMOPQ")); // -> 0.25 -console.log(check("ABC123___...123")); +console.log(checkPassword("ABC123___...123")); // -> -console.log(check("")); +console.log(checkPassword("")); // -> -// console.log(check("")); +// console.log(checkPassword("")); // // -> diff --git a/api/src/util/index.ts b/api/src/util/index.ts new file mode 100644 index 00000000..43481289 --- /dev/null +++ b/api/src/util/index.ts @@ -0,0 +1,11 @@ +export * from "./Base64"; +export * from "./cdn"; +export * from "./instanceOf"; +export * from "./ipAddress"; +export * from "./Message"; +export * from "./passwordStrength"; +export * from "./RandomInviteID"; +export * from "./route"; +export * from "./String"; +export * from "./Voice"; +export * from "./VoiceState"; diff --git a/api/src/util/passwordStrength.ts b/api/src/util/passwordStrength.ts index dfffa2c0..047df008 100644 --- a/api/src/util/passwordStrength.ts +++ b/api/src/util/passwordStrength.ts @@ -16,7 +16,7 @@ const blocklist: string[] = []; // TODO: update ones passwordblocklist is stored * * Returns: 0 > pw > 1 */ -export function check(password: string): number { +export function checkPassword(password: string): number { const { minLength, minNumbers, minUpperCase, minSymbols } = Config.get().register.password; var strength = 0; diff --git a/api/tests/automatic.test.js b/api/tests/automatic.test.js new file mode 100644 index 00000000..e69de29b diff --git a/api/tsconfig.json b/api/tsconfig.json index 6bf2e6b7..21a8eb96 100644 --- a/api/tsconfig.json +++ b/api/tsconfig.json @@ -63,6 +63,11 @@ /* Advanced Options */ "skipLibCheck": true /* Skip type checking of declaration files. */, - "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */, + "baseUrl": ".", + "paths": { + "@fosscord/api": ["src/index.ts"], + "@fosscord/api/*": ["src/*"] + } } } diff --git a/bundle/package-lock.json b/bundle/package-lock.json index 944570ed..0092e0d5 100644 --- a/bundle/package-lock.json +++ b/bundle/package-lock.json @@ -17,7 +17,8 @@ "async-exit-hook": "^2.0.1", "express": "^4.17.1", "missing-native-js-functions": "^1.2.15", - "node-os-utils": "^1.3.5" + "node-os-utils": "^1.3.5", + "tsconfig-paths": "^3.11.0" }, "devDependencies": { "@types/amqplib": "^0.8.1", @@ -73,6 +74,7 @@ "node-fetch": "^2.6.1", "patch-package": "^6.4.7", "supertest": "^6.1.6", + "tsconfig-paths": "^3.11.0", "typeorm": "^0.2.37" }, "devDependencies": { @@ -158,6 +160,7 @@ "missing-native-js-functions": "^1.2.15", "mongoose-autopopulate": "^0.12.3", "node-fetch": "^2.6.1", + "typeorm": "^0.2.37", "uuid": "^8.3.2", "ws": "^7.4.2" }, @@ -194,6 +197,7 @@ "pg": "^8.7.1", "reflect-metadata": "^0.1.13", "sqlite3": "^5.0.2", + "tsconfig-paths": "^3.11.0", "typeorm": "^0.2.37", "typescript": "^4.4.2", "typescript-json-schema": "^0.50.1" @@ -326,6 +330,11 @@ "i18next": ">=17.0.11" } }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=" + }, "node_modules/@types/jsonwebtoken": { "version": "8.5.4", "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.5.4.tgz", @@ -795,6 +804,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -846,6 +866,11 @@ "node": ">= 0.6" } }, + "node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, "node_modules/missing-native-js-functions": { "version": "1.2.15", "resolved": "https://registry.npmjs.org/missing-native-js-functions/-/missing-native-js-functions-1.2.15.tgz", @@ -1025,6 +1050,14 @@ "node": ">= 0.6" } }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "engines": { + "node": ">=4" + } + }, "node_modules/toidentifier": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", @@ -1033,6 +1066,17 @@ "node": ">=0.6" } }, + "node_modules/tsconfig-paths": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.11.0.tgz", + "integrity": "sha512-7ecdYDnIdmv639mmDwslG6KQg1Z9STTz1j7Gcz0xa+nshh/gKDAHcPxRbWOsA3SPp0tXP2leTcY9Kw+NAkfZzA==", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.0", + "strip-bom": "^3.0.0" + } + }, "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -1145,6 +1189,7 @@ "supertest": "^6.1.6", "ts-node": "^9.1.1", "ts-node-dev": "^1.1.6", + "tsconfig-paths": "^3.11.0", "typeorm": "^0.2.37", "typescript": "^4.4.2", "typescript-json-schema": "^0.50.1" @@ -1211,6 +1256,7 @@ "mongoose-autopopulate": "^0.12.3", "node-fetch": "^2.6.1", "ts-node-dev": "^1.1.6", + "typeorm": "^0.2.37", "typescript": "^4.2.3", "uuid": "^8.3.2", "ws": "^7.4.2" @@ -1238,6 +1284,7 @@ "pg": "^8.7.1", "reflect-metadata": "^0.1.13", "sqlite3": "^5.0.2", + "tsconfig-paths": "^3.11.0", "typeorm": "^0.2.37", "typescript": "^4.4.2", "typescript-json-schema": "^0.50.1" @@ -1334,6 +1381,11 @@ "i18next": ">=17.0.11" } }, + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=" + }, "@types/jsonwebtoken": { "version": "8.5.4", "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.5.4.tgz", @@ -1731,6 +1783,14 @@ "has": "^1.0.3" } }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "requires": { + "minimist": "^1.2.0" + } + }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -1764,6 +1824,11 @@ "mime-db": "1.49.0" } }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, "missing-native-js-functions": { "version": "1.2.15", "resolved": "https://registry.npmjs.org/missing-native-js-functions/-/missing-native-js-functions-1.2.15.tgz", @@ -1912,11 +1977,27 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" + }, "toidentifier": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" }, + "tsconfig-paths": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.11.0.tgz", + "integrity": "sha512-7ecdYDnIdmv639mmDwslG6KQg1Z9STTz1j7Gcz0xa+nshh/gKDAHcPxRbWOsA3SPp0tXP2leTcY9Kw+NAkfZzA==", + "requires": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.0", + "strip-bom": "^3.0.0" + } + }, "type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", diff --git a/bundle/package.json b/bundle/package.json index a326a131..996ab30b 100644 --- a/bundle/package.json +++ b/bundle/package.json @@ -11,7 +11,7 @@ "build:api": "cd ../api/ && npm run build", "build:cdn": "cd ../cdn/ && npm run build", "build:gateway": "cd ../gateway/ && npm run build", - "start": "npm run build && node dist/start.js", + "start": "npm run build && node -r ./tsconfig-paths-bootstrap.js dist/start.js", "test": "echo \"Error: no test specified\" && exit 1" }, "repository": { @@ -52,6 +52,7 @@ "async-exit-hook": "^2.0.1", "express": "^4.17.1", "missing-native-js-functions": "^1.2.15", - "node-os-utils": "^1.3.5" + "node-os-utils": "^1.3.5", + "tsconfig-paths": "^3.11.0" } } diff --git a/bundle/tsconfig-paths-bootstrap.js b/bundle/tsconfig-paths-bootstrap.js new file mode 100644 index 00000000..efe4b3bc --- /dev/null +++ b/bundle/tsconfig-paths-bootstrap.js @@ -0,0 +1,14 @@ +const tsConfigPaths = require("tsconfig-paths"); +const path = require("path"); + +const cleanup = tsConfigPaths.register({ + baseUrl: path.join(__dirname, "node_modules", "@fosscord"), + paths: { + "@fosscord/api": ["api/dist/index.js"], + "@fosscord/api/*": ["api/dist/*"], + "@fosscord/gateway": ["gateway/dist/index.js"], + "@fosscord/gateway/*": ["gateway/dist/*"], + "@fosscord/cdn": ["cdn/dist/index.js"], + "@fosscord/cdn/*": ["cdn/dist/*"], + }, +}); diff --git a/cdn/package.json b/cdn/package.json index c2bdbd79..7c59381b 100644 --- a/cdn/package.json +++ b/cdn/package.json @@ -7,7 +7,7 @@ "scripts": { "test": "npm run build && jest --coverage ./tests", "build": "npx tsc -b .", - "start": "npm run build && node dist/start.js" + "start": "npm run build && node -r ./scripts/tsconfig-paths-bootstrap.js dist/start.js" }, "repository": { "type": "git", diff --git a/cdn/scripts/tsconfig-paths-bootstrap.js b/cdn/scripts/tsconfig-paths-bootstrap.js new file mode 100644 index 00000000..50602b02 --- /dev/null +++ b/cdn/scripts/tsconfig-paths-bootstrap.js @@ -0,0 +1,10 @@ +const tsConfigPaths = require("tsconfig-paths"); +const path = require("path"); + +const cleanup = tsConfigPaths.register({ + baseUrl: path.join(__dirname, ".."), + paths: { + "@fosscord/cdn": ["dist/index.js"], + "@fosscord/cdn/*": ["dist/*"], + }, +}); diff --git a/cdn/src/routes/attachments.ts b/cdn/src/routes/attachments.ts index 59845c94..7c55998b 100644 --- a/cdn/src/routes/attachments.ts +++ b/cdn/src/routes/attachments.ts @@ -1,73 +1,87 @@ import { Router, Response, Request } from "express"; import { Config, Snowflake } from "@fosscord/util"; -import { storage } from "../util/Storage"; +import { storage } from "@fosscord/cdn/util/Storage"; import FileType from "file-type"; import { HTTPError } from "lambert-server"; -import { multer } from "../util/multer"; +import { multer } from "@fosscord/cdn/util/multer"; import imageSize from "image-size"; const router = Router(); -router.post("/:channel_id", multer.single("file"), async (req: Request, res: Response) => { - if (req.headers.signature !== Config.get().security.requestSignature) - throw new HTTPError("Invalid request signature"); - if (!req.file) throw new HTTPError("file missing"); - - const { buffer, mimetype, size, originalname, fieldname } = req.file; - const { channel_id } = req.params; - const filename = originalname.replaceAll(" ", "_").replace(/[^a-zA-Z0-9._]+/g, ""); - const id = Snowflake.generate(); - const path = `attachments/${channel_id}/${id}/${filename}`; - - const endpoint = Config.get()?.cdn.endpoint || "http://localhost:3003"; - - await storage.set(path, buffer); - var width; - var height; - if (mimetype.includes("image")) { - const dimensions = imageSize(buffer); - if (dimensions) { - width = dimensions.width; - height = dimensions.height; +router.post( + "/:channel_id", + multer.single("file"), + async (req: Request, res: Response) => { + if (req.headers.signature !== Config.get().security.requestSignature) + throw new HTTPError("Invalid request signature"); + if (!req.file) throw new HTTPError("file missing"); + + const { buffer, mimetype, size, originalname, fieldname } = req.file; + const { channel_id } = req.params; + const filename = originalname + .replaceAll(" ", "_") + .replace(/[^a-zA-Z0-9._]+/g, ""); + const id = Snowflake.generate(); + const path = `attachments/${channel_id}/${id}/${filename}`; + + const endpoint = Config.get()?.cdn.endpoint || "http://localhost:3003"; + + await storage.set(path, buffer); + var width; + var height; + if (mimetype.includes("image")) { + const dimensions = imageSize(buffer); + if (dimensions) { + width = dimensions.width; + height = dimensions.height; + } } - } - - const file = { - id, - content_type: mimetype, - filename: filename, - size, - url: `${endpoint}/${path}`, - width, - height, - }; - return res.json(file); -}); + const file = { + id, + content_type: mimetype, + filename: filename, + size, + url: `${endpoint}/${path}`, + width, + height, + }; + + return res.json(file); + } +); -router.get("/:channel_id/:id/:filename", async (req: Request, res: Response) => { - const { channel_id, id, filename } = req.params; +router.get( + "/:channel_id/:id/:filename", + async (req: Request, res: Response) => { + const { channel_id, id, filename } = req.params; - const file = await storage.get(`attachments/${channel_id}/${id}/${filename}`); - if (!file) throw new HTTPError("File not found"); - const type = await FileType.fromBuffer(file); + const file = await storage.get( + `attachments/${channel_id}/${id}/${filename}` + ); + if (!file) throw new HTTPError("File not found"); + const type = await FileType.fromBuffer(file); - res.set("Content-Type", type?.mime); - res.set("Cache-Control", "public, max-age=31536000"); + res.set("Content-Type", type?.mime); + res.set("Cache-Control", "public, max-age=31536000"); - return res.send(file); -}); + return res.send(file); + } +); -router.delete("/:channel_id/:id/:filename", async (req: Request, res: Response) => { - if (req.headers.signature !== Config.get().security.requestSignature) - throw new HTTPError("Invalid request signature"); +router.delete( + "/:channel_id/:id/:filename", + async (req: Request, res: Response) => { + if (req.headers.signature !== Config.get().security.requestSignature) + throw new HTTPError("Invalid request signature"); - const { channel_id, id, filename } = req.params; - const path = `attachments/${channel_id}/${id}/${filename}`; + const { channel_id, id, filename } = req.params; + const path = `attachments/${channel_id}/${id}/${filename}`; - await storage.delete(path); + await storage.delete(path); - return res.send({ success: true }); -}); + return res.send({ success: true }); + } +); export default router; diff --git a/cdn/src/routes/avatars.ts b/cdn/src/routes/avatars.ts index 03388afc..3d745f90 100644 --- a/cdn/src/routes/avatars.ts +++ b/cdn/src/routes/avatars.ts @@ -1,9 +1,9 @@ import { Router, Response, Request } from "express"; import { Config, Snowflake } from "@fosscord/util"; -import { storage } from "../util/Storage"; +import { storage } from "@fosscord/cdn/util/Storage"; import FileType from "file-type"; import { HTTPError } from "lambert-server"; -import { multer } from "../util/multer"; +import { multer } from "@fosscord/cdn/util/multer"; import crypto from "crypto"; // TODO: check premium and animated pfp are allowed in the config @@ -12,36 +12,50 @@ import crypto from "crypto"; // TODO: delete old icons const ANIMATED_MIME_TYPES = ["image/apng", "image/gif", "image/gifv"]; -const STATIC_MIME_TYPES = ["image/png", "image/jpeg", "image/webp", "image/svg+xml", "image/svg"]; +const STATIC_MIME_TYPES = [ + "image/png", + "image/jpeg", + "image/webp", + "image/svg+xml", + "image/svg", +]; const ALLOWED_MIME_TYPES = [...ANIMATED_MIME_TYPES, ...STATIC_MIME_TYPES]; const router = Router(); -router.post("/:user_id", multer.single("file"), async (req: Request, res: Response) => { - if (req.headers.signature !== Config.get().security.requestSignature) - throw new HTTPError("Invalid request signature"); - if (!req.file) throw new HTTPError("Missing file"); - const { buffer, mimetype, size, originalname, fieldname } = req.file; - const { user_id } = req.params; - - var hash = crypto.createHash("md5").update(Snowflake.generate()).digest("hex"); - - const type = await FileType.fromBuffer(buffer); - if (!type || !ALLOWED_MIME_TYPES.includes(type.mime)) throw new HTTPError("Invalid file type"); - if (ANIMATED_MIME_TYPES.includes(type.mime)) hash = `a_${hash}`; // animated icons have a_ infront of the hash - - const path = `avatars/${user_id}/${hash}`; - const endpoint = Config.get().cdn.endpoint || "http://localhost:3003"; - - await storage.set(path, buffer); - - return res.json({ - id: hash, - content_type: type.mime, - size, - url: `${endpoint}${req.baseUrl}/${user_id}/${hash}`, - }); -}); +router.post( + "/:user_id", + multer.single("file"), + async (req: Request, res: Response) => { + if (req.headers.signature !== Config.get().security.requestSignature) + throw new HTTPError("Invalid request signature"); + if (!req.file) throw new HTTPError("Missing file"); + const { buffer, mimetype, size, originalname, fieldname } = req.file; + const { user_id } = req.params; + + var hash = crypto + .createHash("md5") + .update(Snowflake.generate()) + .digest("hex"); + + const type = await FileType.fromBuffer(buffer); + if (!type || !ALLOWED_MIME_TYPES.includes(type.mime)) + throw new HTTPError("Invalid file type"); + if (ANIMATED_MIME_TYPES.includes(type.mime)) hash = `a_${hash}`; // animated icons have a_ infront of the hash + + const path = `avatars/${user_id}/${hash}`; + const endpoint = Config.get().cdn.endpoint || "http://localhost:3003"; + + await storage.set(path, buffer); + + return res.json({ + id: hash, + content_type: type.mime, + size, + url: `${endpoint}${req.baseUrl}/${user_id}/${hash}`, + }); + } +); router.get("/:user_id/:hash", async (req: Request, res: Response) => { var { user_id, hash } = req.params; diff --git a/cdn/src/routes/external.ts b/cdn/src/routes/external.ts index 10bb0f7d..e7783ec3 100644 --- a/cdn/src/routes/external.ts +++ b/cdn/src/routes/external.ts @@ -2,7 +2,7 @@ import { Router, Response, Request } from "express"; import fetch from "node-fetch"; import { HTTPError } from "lambert-server"; import { Snowflake } from "@fosscord/util"; -import { storage } from "../util/Storage"; +import { storage } from "@fosscord/cdn/util/Storage"; import FileType from "file-type"; import { Config } from "@fosscord/util"; @@ -13,7 +13,8 @@ const DEFAULT_FETCH_OPTIONS: any = { redirect: "follow", follow: 1, headers: { - "user-agent": "Mozilla/5.0 (compatible Fosscordbot/0.1; +https://fosscord.com)", + "user-agent": + "Mozilla/5.0 (compatible Fosscordbot/0.1; +https://fosscord.com)", }, size: 1024 * 1024 * 8, compress: true, diff --git a/cdn/tsconfig.json b/cdn/tsconfig.json index 08e39435..2daac1ad 100644 --- a/cdn/tsconfig.json +++ b/cdn/tsconfig.json @@ -65,6 +65,11 @@ /* Advanced Options */ "skipLibCheck": true /* Skip type checking of declaration files. */, - "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */, + "baseUrl": ".", + "paths": { + "@fosscord/cdn/": ["src/index.ts"], + "@fosscord/cdn/*": ["src/*"] + } } } diff --git a/gateway/package-lock.json b/gateway/package-lock.json index 340f595d..64c542e4 100644 --- a/gateway/package-lock.json +++ b/gateway/package-lock.json @@ -18,6 +18,7 @@ "missing-native-js-functions": "^1.2.15", "mongoose-autopopulate": "^0.12.3", "node-fetch": "^2.6.1", + "typeorm": "^0.2.37", "uuid": "^8.3.2", "ws": "^7.4.2" }, @@ -48,12 +49,13 @@ "env-paths": "^2.2.1", "jsonwebtoken": "^8.5.1", "lambert-server": "^1.2.10", - "missing-native-js-functions": "^1.2.14", + "missing-native-js-functions": "^1.2.15", "node-fetch": "^2.6.1", "patch-package": "^6.4.7", "pg": "^8.7.1", "reflect-metadata": "^0.1.13", "sqlite3": "^5.0.2", + "tsconfig-paths": "^3.11.0", "typeorm": "^0.2.37", "typescript": "^4.4.2", "typescript-json-schema": "^0.50.1" @@ -71,6 +73,11 @@ "resolved": "../util", "link": true }, + "node_modules/@sqltools/formatter": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.3.tgz", + "integrity": "sha512-O3uyB/JbkAEMZaP3YqyHH7TMnex7tWyCbCI4EfJdOCoN6HIhqdJBWTM6aCCiWQ/5f5wxjgU735QAIpJbjDvmzg==" + }, "node_modules/@types/amqplib": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@types/amqplib/-/amqplib-0.8.1.tgz", @@ -183,6 +190,11 @@ "@types/node": "*" } }, + "node_modules/@types/zen-observable": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/@types/zen-observable/-/zen-observable-0.8.3.tgz", + "integrity": "sha512-fbF6oTd4sGGy0xjHPKAt+eS2CrxJ3+6gQ3FGcBoIJR2TLAyCkCyI8JqZNy+FeON0AhVgNJoUumVoZQjBFUqHkw==" + }, "node_modules/accepts": { "version": "1.3.7", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", @@ -226,6 +238,14 @@ "node": ">=10" } }, + "node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "engines": { + "node": ">=8" + } + }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -240,6 +260,11 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" + }, "node_modules/anymatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", @@ -253,12 +278,25 @@ "node": ">= 8" } }, + "node_modules/app-root-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.0.0.tgz", + "integrity": "sha512-qMcx+Gy2UZynHjOHOIXPNvpf+9cjvk3cWrBBK7zg4gH9+clobJRb9NGzcT7mQTcV/6Gm/1WelUtqxVXnNlrwcw==", + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", "dev": true }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -273,8 +311,26 @@ "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] }, "node_modules/binary-extensions": { "version": "2.2.0", @@ -378,7 +434,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -405,6 +460,29 @@ "node": ">=0.6.19" } }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, "node_modules/buffer-equal-constant-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", @@ -465,6 +543,53 @@ "fsevents": "~2.3.2" } }, + "node_modules/cli-highlight": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz", + "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==", + "dependencies": { + "chalk": "^4.0.0", + "highlight.js": "^10.7.1", + "mz": "^2.4.0", + "parse5": "^5.1.1", + "parse5-htmlparser2-tree-adapter": "^6.0.0", + "yargs": "^16.0.0" + }, + "bin": { + "highlight": "bin/highlight" + }, + "engines": { + "node": ">=8.0.0", + "npm": ">=5.0.0" + } + }, + "node_modules/cli-highlight/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -496,8 +621,7 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "node_modules/content-disposition": { "version": "0.5.3", @@ -625,6 +749,11 @@ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -633,11 +762,27 @@ "node": ">= 0.8" } }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "engines": { + "node": ">=6" + } + }, "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", @@ -704,6 +849,14 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, + "node_modules/figlet": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/figlet/-/figlet-1.5.2.tgz", + "integrity": "sha512-WOn21V8AhyE1QqVfPIVxe3tupJacq1xGkPTB4iagT6o+P2cAgEOOwIxMftr4+ZCTI6d551ij9j61DFr0nsP2uQ==", + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -766,8 +919,7 @@ "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "node_modules/fsevents": { "version": "2.3.2", @@ -789,11 +941,18 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, "node_modules/glob": { "version": "7.1.7", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -833,6 +992,25 @@ "node": ">= 0.4.0" } }, + "node_modules/has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-ansi/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -849,6 +1027,14 @@ "node": ">=10.0.0" } }, + "node_modules/highlight.js": { + "version": "10.7.3", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", + "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", + "engines": { + "node": "*" + } + }, "node_modules/http-errors": { "version": "1.7.2", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", @@ -875,11 +1061,29 @@ "node": ">=0.10.0" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -931,6 +1135,14 @@ "node": ">=0.10.0" } }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, "node_modules/is-glob": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", @@ -957,6 +1169,17 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", @@ -1129,7 +1352,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -1152,7 +1374,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, "bin": { "mkdirp": "bin/cmd.js" }, @@ -1302,6 +1523,16 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, "node_modules/negotiator": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", @@ -1327,6 +1558,14 @@ "node": ">=0.10.0" } }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -1342,7 +1581,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "dependencies": { "wrappy": "1" } @@ -1356,6 +1594,32 @@ "node": ">=4" } }, + "node_modules/parent-require": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parent-require/-/parent-require-1.0.0.tgz", + "integrity": "sha1-dGoWdjgIOoYLDu9nMssn7UbDKXc=", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/parse5": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==" + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", + "dependencies": { + "parse5": "^6.0.1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter/node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -1368,7 +1632,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -1480,12 +1743,25 @@ "node": ">=8.10.0" } }, + "node_modules/reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" + }, "node_modules/regexp-clone": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz", "integrity": "sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw==", "peer": true }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", @@ -1561,6 +1837,11 @@ "node": ">=6" } }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, "node_modules/semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -1616,6 +1897,18 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, "node_modules/sift": { "version": "13.5.2", "resolved": "https://registry.npmjs.org/sift/-/sift-13.5.2.tgz", @@ -1670,6 +1963,30 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" }, + "node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", @@ -1699,6 +2016,25 @@ "node": ">=8" } }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -1800,6 +2136,11 @@ "strip-json-comments": "^2.0.0" } }, + "node_modules/tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + }, "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -1812,6 +2153,121 @@ "node": ">= 0.6" } }, + "node_modules/typeorm": { + "version": "0.2.37", + "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.2.37.tgz", + "integrity": "sha512-7rkW0yCgFC24I5T0f3S/twmLSuccPh1SQmxET/oDWn2sSDVzbyWdnItSdKy27CdJGTlKHYtUVeOcMYw5LRsXVw==", + "dependencies": { + "@sqltools/formatter": "^1.2.2", + "app-root-path": "^3.0.0", + "buffer": "^6.0.3", + "chalk": "^4.1.0", + "cli-highlight": "^2.1.11", + "debug": "^4.3.1", + "dotenv": "^8.2.0", + "glob": "^7.1.6", + "js-yaml": "^4.0.0", + "mkdirp": "^1.0.4", + "reflect-metadata": "^0.1.13", + "sha.js": "^2.4.11", + "tslib": "^2.1.0", + "xml2js": "^0.4.23", + "yargonaut": "^1.1.4", + "yargs": "^17.0.1", + "zen-observable-ts": "^1.0.0" + }, + "bin": { + "typeorm": "cli.js" + }, + "funding": { + "url": "https://opencollective.com/typeorm" + }, + "peerDependencies": { + "@sap/hana-client": "*", + "better-sqlite3": "*", + "hdb-pool": "*", + "ioredis": "*", + "mongodb": "^3.6.0", + "mssql": "*", + "mysql2": "*", + "oracledb": "*", + "pg": "*", + "pg-native": "*", + "pg-query-stream": "*", + "redis": "*", + "sql.js": "*", + "sqlite3": "*", + "typeorm-aurora-data-api-driver": "*" + }, + "peerDependenciesMeta": { + "@sap/hana-client": { + "optional": true + }, + "better-sqlite3": { + "optional": true + }, + "hdb-pool": { + "optional": true + }, + "ioredis": { + "optional": true + }, + "mongodb": { + "optional": true + }, + "mssql": { + "optional": true + }, + "mysql2": { + "optional": true + }, + "oracledb": { + "optional": true + }, + "pg": { + "optional": true + }, + "pg-native": { + "optional": true + }, + "pg-query-stream": { + "optional": true + }, + "redis": { + "optional": true + }, + "sql.js": { + "optional": true + }, + "sqlite3": { + "optional": true + }, + "typeorm-aurora-data-api-driver": { + "optional": true + } + } + }, + "node_modules/typeorm/node_modules/debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/typeorm/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/typescript": { "version": "4.3.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", @@ -1880,11 +2336,26 @@ "node": ">= 0.8" } }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "node_modules/ws": { "version": "7.5.3", @@ -1906,6 +2377,26 @@ } } }, + "node_modules/xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "engines": { + "node": ">=4.0" + } + }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -1915,6 +2406,99 @@ "node": ">=0.4" } }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargonaut": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/yargonaut/-/yargonaut-1.1.4.tgz", + "integrity": "sha512-rHgFmbgXAAzl+1nngqOcwEljqHGG9uUZoPjsdZEs1w5JW9RXYzrSvH/u70C1JE5qFi0qjsdhnUX/dJRpWqitSA==", + "dependencies": { + "chalk": "^1.1.1", + "figlet": "^1.1.1", + "parent-require": "^1.0.0" + } + }, + "node_modules/yargonaut/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/yargonaut/node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/yargonaut/node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/yargonaut/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/yargonaut/node_modules/supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/yargs": { + "version": "17.1.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.1.1.tgz", + "integrity": "sha512-c2k48R0PwKIqKhPMWjeiF6y2xY/gPMUlro0sgxqXpbOIohWiLNXWslsootttv7E1e73QPAMQSg5FeySbVcpsPQ==", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "engines": { + "node": ">=10" + } + }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", @@ -1923,6 +2507,20 @@ "engines": { "node": ">=6" } + }, + "node_modules/zen-observable": { + "version": "0.8.15", + "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz", + "integrity": "sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==" + }, + "node_modules/zen-observable-ts": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-1.1.0.tgz", + "integrity": "sha512-1h4zlLSqI2cRLPJUHJFL8bCWHhkpuXkF+dbGkRaWjgDIG26DmzyshUMrdV/rL3UnR+mhaX4fRq8LPouq0MYYIA==", + "dependencies": { + "@types/zen-observable": "0.8.3", + "zen-observable": "0.8.15" + } } }, "dependencies": { @@ -1942,17 +2540,23 @@ "jest": "^27.0.6", "jsonwebtoken": "^8.5.1", "lambert-server": "^1.2.10", - "missing-native-js-functions": "^1.2.14", + "missing-native-js-functions": "^1.2.15", "node-fetch": "^2.6.1", "patch-package": "^6.4.7", "pg": "^8.7.1", "reflect-metadata": "^0.1.13", "sqlite3": "^5.0.2", + "tsconfig-paths": "^3.11.0", "typeorm": "^0.2.37", "typescript": "^4.4.2", "typescript-json-schema": "^0.50.1" } }, + "@sqltools/formatter": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.3.tgz", + "integrity": "sha512-O3uyB/JbkAEMZaP3YqyHH7TMnex7tWyCbCI4EfJdOCoN6HIhqdJBWTM6aCCiWQ/5f5wxjgU735QAIpJbjDvmzg==" + }, "@types/amqplib": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@types/amqplib/-/amqplib-0.8.1.tgz", @@ -2065,6 +2669,11 @@ "@types/node": "*" } }, + "@types/zen-observable": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/@types/zen-observable/-/zen-observable-0.8.3.tgz", + "integrity": "sha512-fbF6oTd4sGGy0xjHPKAt+eS2CrxJ3+6gQ3FGcBoIJR2TLAyCkCyI8JqZNy+FeON0AhVgNJoUumVoZQjBFUqHkw==" + }, "accepts": { "version": "1.3.7", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", @@ -2098,6 +2707,11 @@ "url-parse": "~1.5.1" } }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -2106,6 +2720,11 @@ "color-convert": "^2.0.1" } }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" + }, "anymatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", @@ -2116,12 +2735,22 @@ "picomatch": "^2.0.4" } }, + "app-root-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.0.0.tgz", + "integrity": "sha512-qMcx+Gy2UZynHjOHOIXPNvpf+9cjvk3cWrBBK7zg4gH9+clobJRb9NGzcT7mQTcV/6Gm/1WelUtqxVXnNlrwcw==" + }, "arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", "dev": true }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -2136,8 +2765,12 @@ "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, "binary-extensions": { "version": "2.2.0", @@ -2236,7 +2869,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2257,6 +2889,15 @@ "integrity": "sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg==", "peer": true }, + "buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, "buffer-equal-constant-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", @@ -2303,6 +2944,45 @@ "readdirp": "~3.6.0" } }, + "cli-highlight": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz", + "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==", + "requires": { + "chalk": "^4.0.0", + "highlight.js": "^10.7.1", + "mz": "^2.4.0", + "parse5": "^5.1.1", + "parse5-htmlparser2-tree-adapter": "^6.0.0", + "yargs": "^16.0.0" + }, + "dependencies": { + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + } + } + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -2328,8 +3008,7 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "content-disposition": { "version": "0.5.3", @@ -2435,16 +3114,31 @@ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", @@ -2505,6 +3199,11 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, + "figlet": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/figlet/-/figlet-1.5.2.tgz", + "integrity": "sha512-WOn21V8AhyE1QqVfPIVxe3tupJacq1xGkPTB4iagT6o+P2cAgEOOwIxMftr4+ZCTI6d551ij9j61DFr0nsP2uQ==" + }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -2552,8 +3251,7 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { "version": "2.3.2", @@ -2568,11 +3266,15 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + }, "glob": { "version": "7.1.7", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -2600,6 +3302,21 @@ "function-bind": "^1.1.1" } }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + } + } + }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -2610,6 +3327,11 @@ "resolved": "https://registry.npmjs.org/helmet/-/helmet-4.6.0.tgz", "integrity": "sha512-HVqALKZlR95ROkrnesdhbbZJFi/rIVSoNq6f3jA/9u6MIbTsPh3xZwihjeI5+DO/2sOV6HMHooXcEOuwskHpTg==" }, + "highlight.js": { + "version": "10.7.3", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", + "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==" + }, "http-errors": { "version": "1.7.2", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", @@ -2630,11 +3352,15 @@ "safer-buffer": ">= 2.1.2 < 3" } }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -2674,6 +3400,11 @@ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, "is-glob": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", @@ -2694,6 +3425,14 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "requires": { + "argparse": "^2.0.1" + } + }, "json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", @@ -2846,7 +3585,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -2865,8 +3603,7 @@ "mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" }, "mongodb": { "version": "3.6.11", @@ -2925,8 +3662,7 @@ "requires": {} }, "mpath": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.8.4.tgz", + "version": "https://registry.npmjs.org/mpath/-/mpath-0.8.4.tgz", "integrity": "sha512-eb9rRvhDltXVNL6Fxd2zM9D4vKBxjVVQNLNijlj7uoXUy19zNDsIif5zR+pWmPCWNKwAtqyo4JveQm4nfD5+eA==", "peer": true }, @@ -2971,6 +3707,16 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "requires": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, "negotiator": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", @@ -2987,6 +3733,11 @@ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -2999,7 +3750,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "requires": { "wrappy": "1" } @@ -3010,6 +3760,31 @@ "integrity": "sha512-RV2Zp2MY2aeYK5G+B/Sps8lW5NHAzE5QClbFP15j+PWmP+T9PxlJXBOOLoSAdgwFvS4t0aMR4vpedMkbHfh0nA==", "peer": true }, + "parent-require": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parent-require/-/parent-require-1.0.0.tgz", + "integrity": "sha1-dGoWdjgIOoYLDu9nMssn7UbDKXc=" + }, + "parse5": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==" + }, + "parse5-htmlparser2-tree-adapter": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", + "requires": { + "parse5": "^6.0.1" + }, + "dependencies": { + "parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + } + } + }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -3018,8 +3793,7 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, "path-parse": { "version": "1.0.7", @@ -3104,12 +3878,22 @@ "picomatch": "^2.2.1" } }, + "reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" + }, "regexp-clone": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz", "integrity": "sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw==", "peer": true }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, "require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", @@ -3159,6 +3943,11 @@ "sparse-bitfield": "^3.0.3" } }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -3207,6 +3996,15 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, "sift": { "version": "13.5.2", "resolved": "https://registry.npmjs.org/sift/-/sift-13.5.2.tgz", @@ -3255,6 +4053,24 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" }, + "string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "requires": { + "ansi-regex": "^5.0.0" + } + }, "strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", @@ -3275,6 +4091,22 @@ "has-flag": "^4.0.0" } }, + "thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "requires": { + "any-promise": "^1.0.0" + } + }, + "thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", + "requires": { + "thenify": ">= 3.1.0 < 4" + } + }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -3339,6 +4171,11 @@ "strip-json-comments": "^2.0.0" } }, + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" + }, "type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -3348,6 +4185,45 @@ "mime-types": "~2.1.24" } }, + "typeorm": { + "version": "0.2.37", + "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.2.37.tgz", + "integrity": "sha512-7rkW0yCgFC24I5T0f3S/twmLSuccPh1SQmxET/oDWn2sSDVzbyWdnItSdKy27CdJGTlKHYtUVeOcMYw5LRsXVw==", + "requires": { + "@sqltools/formatter": "^1.2.2", + "app-root-path": "^3.0.0", + "buffer": "^6.0.3", + "chalk": "^4.1.0", + "cli-highlight": "^2.1.11", + "debug": "^4.3.1", + "dotenv": "^8.2.0", + "glob": "^7.1.6", + "js-yaml": "^4.0.0", + "mkdirp": "^1.0.4", + "reflect-metadata": "^0.1.13", + "sha.js": "^2.4.11", + "tslib": "^2.1.0", + "xml2js": "^0.4.23", + "yargonaut": "^1.1.4", + "yargs": "^17.0.1", + "zen-observable-ts": "^1.0.0" + }, + "dependencies": { + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, "typescript": { "version": "4.3.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", @@ -3397,11 +4273,20 @@ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "ws": { "version": "7.5.3", @@ -3409,17 +4294,116 @@ "integrity": "sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==", "requires": {} }, + "xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + } + }, + "xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" + }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "dev": true }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" + }, + "yargonaut": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/yargonaut/-/yargonaut-1.1.4.tgz", + "integrity": "sha512-rHgFmbgXAAzl+1nngqOcwEljqHGG9uUZoPjsdZEs1w5JW9RXYzrSvH/u70C1JE5qFi0qjsdhnUX/dJRpWqitSA==", + "requires": { + "chalk": "^1.1.1", + "figlet": "^1.1.1", + "parent-require": "^1.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } + } + }, + "yargs": { + "version": "17.1.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.1.1.tgz", + "integrity": "sha512-c2k48R0PwKIqKhPMWjeiF6y2xY/gPMUlro0sgxqXpbOIohWiLNXWslsootttv7E1e73QPAMQSg5FeySbVcpsPQ==", + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==" + }, "yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true + }, + "zen-observable": { + "version": "0.8.15", + "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz", + "integrity": "sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==" + }, + "zen-observable-ts": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-1.1.0.tgz", + "integrity": "sha512-1h4zlLSqI2cRLPJUHJFL8bCWHhkpuXkF+dbGkRaWjgDIG26DmzyshUMrdV/rL3UnR+mhaX4fRq8LPouq0MYYIA==", + "requires": { + "@types/zen-observable": "0.8.3", + "zen-observable": "0.8.15" + } } } } diff --git a/gateway/package.json b/gateway/package.json index 310e867e..6b9e27d6 100644 --- a/gateway/package.json +++ b/gateway/package.json @@ -5,7 +5,7 @@ "main": "dist/index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", - "start": "npm run build && node dist/start.js", + "start": "npm run build && node -r ./scripts/tsconfig-paths-bootstrap.js dist/start.js", "build": "npx tsc -b .", "dev": "tsnd --respawn src/start.ts" }, @@ -35,6 +35,7 @@ "missing-native-js-functions": "^1.2.15", "mongoose-autopopulate": "^0.12.3", "node-fetch": "^2.6.1", + "typeorm": "^0.2.37", "uuid": "^8.3.2", "ws": "^7.4.2" } diff --git a/gateway/scripts/tsconfig-paths-bootstrap.js b/gateway/scripts/tsconfig-paths-bootstrap.js new file mode 100644 index 00000000..7308523b --- /dev/null +++ b/gateway/scripts/tsconfig-paths-bootstrap.js @@ -0,0 +1,10 @@ +const tsConfigPaths = require("tsconfig-paths"); +const path = require("path"); + +const cleanup = tsConfigPaths.register({ + baseUrl: path.join(__dirname, ".."), + paths: { + "@fosscord/gateway": ["dist/index.js"], + "@fosscord/gateway/*": ["dist/*"], + }, +}); diff --git a/gateway/src/events/Close.ts b/gateway/src/events/Close.ts index 2f274ec4..4afe8352 100644 --- a/gateway/src/events/Close.ts +++ b/gateway/src/events/Close.ts @@ -1,4 +1,4 @@ -import WebSocket from "../util/WebSocket"; +import WebSocket from "@fosscord/gateway/util/WebSocket"; import { Message } from "./Message"; import { Session } from "@fosscord/util"; diff --git a/gateway/src/events/Connection.ts b/gateway/src/events/Connection.ts index b3c94eaf..625ceaa2 100644 --- a/gateway/src/events/Connection.ts +++ b/gateway/src/events/Connection.ts @@ -1,10 +1,10 @@ -import WebSocket, { Server } from "../util/WebSocket"; +import WebSocket, { Server } from "@fosscord/gateway/util/WebSocket"; import { IncomingMessage } from "http"; import { Close } from "./Close"; import { Message } from "./Message"; -import { setHeartbeat } from "../util/setHeartbeat"; -import { Send } from "../util/Send"; -import { CLOSECODES, OPCODES } from "../util/Constants"; +import { setHeartbeat } from "@fosscord/gateway/util/setHeartbeat"; +import { Send } from "@fosscord/gateway/util/Send"; +import { CLOSECODES, OPCODES } from "@fosscord/gateway/util/Constants"; import { createDeflate } from "zlib"; import { URL } from "url"; import { Session } from "@fosscord/util"; @@ -17,7 +17,11 @@ try { // TODO: specify rate limit in config // TODO: check msg max size -export async function Connection(this: Server, socket: WebSocket, request: IncomingMessage) { +export async function Connection( + this: Server, + socket: WebSocket, + request: IncomingMessage +) { try { socket.on("close", Close); // @ts-ignore @@ -27,18 +31,21 @@ export async function Connection(this: Server, socket: WebSocket, request: Incom // @ts-ignore socket.encoding = searchParams.get("encoding") || "json"; if (!["json", "etf"].includes(socket.encoding)) { - if (socket.encoding === "etf" && erlpack) throw new Error("Erlpack is not installed: 'npm i -D erlpack'"); + if (socket.encoding === "etf" && erlpack) + throw new Error("Erlpack is not installed: 'npm i -D erlpack'"); return socket.close(CLOSECODES.Decode_error); } // @ts-ignore socket.version = Number(searchParams.get("version")) || 8; - if (socket.version != 8) return socket.close(CLOSECODES.Invalid_API_version); + if (socket.version != 8) + return socket.close(CLOSECODES.Invalid_API_version); // @ts-ignore socket.compress = searchParams.get("compress") || ""; if (socket.compress) { - if (socket.compress !== "zlib-stream") return socket.close(CLOSECODES.Decode_error); + if (socket.compress !== "zlib-stream") + return socket.close(CLOSECODES.Decode_error); socket.deflate = createDeflate({ chunkSize: 65535 }); socket.deflate.on("data", (chunk) => socket.send(chunk)); } diff --git a/gateway/src/events/Message.ts b/gateway/src/events/Message.ts index a8bf5d78..5c6bd2fc 100644 --- a/gateway/src/events/Message.ts +++ b/gateway/src/events/Message.ts @@ -1,10 +1,10 @@ -import WebSocket, { Data } from "../util/WebSocket"; +import WebSocket, { Data } from "@fosscord/gateway/util/WebSocket"; var erlpack: any; try { erlpack = require("erlpack"); } catch (error) {} import OPCodeHandlers from "../opcodes"; -import { Payload, CLOSECODES, OPCODES } from "../util/Constants"; +import { Payload, CLOSECODES, OPCODES } from "@fosscord/gateway/util/Constants"; import { instanceOf, Tuple } from "lambert-server"; import { check } from "../opcodes/instanceOf"; import WS from "ws"; @@ -20,8 +20,10 @@ export async function Message(this: WebSocket, buffer: WS.Data) { // TODO: compression var data: Payload; - if (this.encoding === "etf" && buffer instanceof Buffer) data = erlpack.unpack(buffer); - else if (this.encoding === "json" && typeof buffer === "string") data = JSON.parse(buffer); + if (this.encoding === "etf" && buffer instanceof Buffer) + data = erlpack.unpack(buffer); + else if (this.encoding === "json" && typeof buffer === "string") + data = JSON.parse(buffer); else return; check.call(this, PayloadSchema, data); @@ -41,6 +43,7 @@ export async function Message(this: WebSocket, buffer: WS.Data) { return await OPCodeHandler.call(this, data); } catch (error) { console.error(error); - if (!this.CLOSED && this.CLOSING) return this.close(CLOSECODES.Unknown_error); + if (!this.CLOSED && this.CLOSING) + return this.close(CLOSECODES.Unknown_error); } } diff --git a/gateway/src/index.ts b/gateway/src/index.ts index 7513bd2f..d77ce931 100644 --- a/gateway/src/index.ts +++ b/gateway/src/index.ts @@ -1 +1,4 @@ export * from "./Server"; +export * from "./util/"; +export * from "./opcodes/"; +export * from "./listener/listener"; diff --git a/gateway/src/listener/listener.ts b/gateway/src/listener/listener.ts index 0b6fa50c..e5630a43 100644 --- a/gateway/src/listener/listener.ts +++ b/gateway/src/listener/listener.ts @@ -9,13 +9,13 @@ import { ListenEventOpts, Member, } from "@fosscord/util"; -import { OPCODES } from "../util/Constants"; -import { Send } from "../util/Send"; -import WebSocket from "../util/WebSocket"; +import { OPCODES } from "@fosscord/gateway/util/Constants"; +import { Send } from "@fosscord/gateway/util/Send"; +import WebSocket from "@fosscord/gateway/util/WebSocket"; import "missing-native-js-functions"; import { Channel as AMQChannel } from "amqplib"; -import { In, Like } from "../../../util/node_modules/typeorm"; -import { Recipient } from "../../../util/dist/entities/Recipient"; +import { In, Like } from "typeorm"; +import { Recipient } from "@fosscord/util"; // TODO: close connection on Invalidated Token // TODO: check intent diff --git a/gateway/src/opcodes/Heartbeat.ts b/gateway/src/opcodes/Heartbeat.ts index 015257b9..34d8ca74 100644 --- a/gateway/src/opcodes/Heartbeat.ts +++ b/gateway/src/opcodes/Heartbeat.ts @@ -1,7 +1,7 @@ -import { CLOSECODES, Payload } from "../util/Constants"; -import { Send } from "../util/Send"; -import { setHeartbeat } from "../util/setHeartbeat"; -import WebSocket from "../util/WebSocket"; +import { CLOSECODES, Payload } from "@fosscord/gateway/util/Constants"; +import { Send } from "@fosscord/gateway/util/Send"; +import { setHeartbeat } from "@fosscord/gateway/util/setHeartbeat"; +import WebSocket from "@fosscord/gateway/util/WebSocket"; export async function onHeartbeat(this: WebSocket, data: Payload) { // TODO: validate payload diff --git a/gateway/src/opcodes/Identify.ts b/gateway/src/opcodes/Identify.ts index 95db7f3d..04a6c84c 100644 --- a/gateway/src/opcodes/Identify.ts +++ b/gateway/src/opcodes/Identify.ts @@ -1,5 +1,5 @@ -import { CLOSECODES, Payload, OPCODES } from "../util/Constants"; -import WebSocket from "../util/WebSocket"; +import { CLOSECODES, Payload, OPCODES } from "@fosscord/gateway/util/Constants"; +import WebSocket from "@fosscord/gateway/util/WebSocket"; import { Channel, checkToken, @@ -17,12 +17,12 @@ import { } from "@fosscord/util"; import { setupListener } from "../listener/listener"; import { IdentifySchema } from "../schema/Identify"; -import { Send } from "../util/Send"; +import { Send } from "@fosscord/gateway/util/Send"; // import experiments from "./experiments.json"; const experiments: any = []; import { check } from "./instanceOf"; -import { Recipient } from "../../../util/dist/entities/Recipient"; -import { genSessionId } from "../util/SessionUtils"; +import { Recipient } from "@fosscord/util"; +import { genSessionId } from "@fosscord/gateway/util/SessionUtils"; // TODO: bot sharding // TODO: check priviliged intents diff --git a/gateway/src/opcodes/LazyRequest.ts b/gateway/src/opcodes/LazyRequest.ts index b7ee9a96..41ec3446 100644 --- a/gateway/src/opcodes/LazyRequest.ts +++ b/gateway/src/opcodes/LazyRequest.ts @@ -6,9 +6,9 @@ import { Role, } from "@fosscord/util"; import { LazyRequest } from "../schema/LazyRequest"; -import { OPCODES, Payload } from "../util/Constants"; -import { Send } from "../util/Send"; -import WebSocket from "../util/WebSocket"; +import { OPCODES, Payload } from "@fosscord/gateway/util/Constants"; +import { Send } from "@fosscord/gateway/util/Send"; +import WebSocket from "@fosscord/gateway/util/WebSocket"; import { check } from "./instanceOf"; import "missing-native-js-functions"; diff --git a/gateway/src/opcodes/PresenceUpdate.ts b/gateway/src/opcodes/PresenceUpdate.ts index 3760f8a3..4febbfcb 100644 --- a/gateway/src/opcodes/PresenceUpdate.ts +++ b/gateway/src/opcodes/PresenceUpdate.ts @@ -1,5 +1,5 @@ -import { CLOSECODES, Payload } from "../util/Constants"; -import WebSocket from "../util/WebSocket"; +import { CLOSECODES, Payload } from "@fosscord/gateway/util/Constants"; +import WebSocket from "@fosscord/gateway/util/WebSocket"; export function onPresenceUpdate(this: WebSocket, data: Payload) { // return this.close(CLOSECODES.Unknown_error); diff --git a/gateway/src/opcodes/RequestGuildMembers.ts b/gateway/src/opcodes/RequestGuildMembers.ts index 2701d978..9c1654fa 100644 --- a/gateway/src/opcodes/RequestGuildMembers.ts +++ b/gateway/src/opcodes/RequestGuildMembers.ts @@ -1,6 +1,6 @@ -import { CLOSECODES, Payload } from "../util/Constants"; +import { CLOSECODES, Payload } from "@fosscord/gateway/util/Constants"; -import WebSocket from "../util/WebSocket"; +import WebSocket from "@fosscord/gateway/util/WebSocket"; export function onRequestGuildMembers(this: WebSocket, data: Payload) { // return this.close(CLOSECODES.Unknown_error); diff --git a/gateway/src/opcodes/Resume.ts b/gateway/src/opcodes/Resume.ts index 4efde9b0..e155c139 100644 --- a/gateway/src/opcodes/Resume.ts +++ b/gateway/src/opcodes/Resume.ts @@ -1,7 +1,7 @@ -import { CLOSECODES, Payload } from "../util/Constants"; -import { Send } from "../util/Send"; +import { CLOSECODES, Payload } from "@fosscord/gateway/util/Constants"; +import { Send } from "@fosscord/gateway/util/Send"; -import WebSocket from "../util/WebSocket"; +import WebSocket from "@fosscord/gateway/util/WebSocket"; export async function onResume(this: WebSocket, data: Payload) { console.log("Got Resume -> cancel not implemented"); diff --git a/gateway/src/opcodes/VoiceStateUpdate.ts b/gateway/src/opcodes/VoiceStateUpdate.ts index 95a01608..60803ec3 100644 --- a/gateway/src/opcodes/VoiceStateUpdate.ts +++ b/gateway/src/opcodes/VoiceStateUpdate.ts @@ -1,9 +1,18 @@ import { VoiceStateUpdateSchema } from "../schema/VoiceStateUpdateSchema"; -import { Payload } from "../util/Constants"; -import WebSocket from "../util/WebSocket"; +import { Payload } from "@fosscord/gateway/util/Constants"; +import WebSocket from "@fosscord/gateway/util/WebSocket"; import { check } from "./instanceOf"; -import { Config, emitEvent, Guild, Member, Region, VoiceServerUpdateEvent, VoiceState, VoiceStateUpdateEvent } from "@fosscord/util"; -import { genVoiceToken } from "../util/SessionUtils"; +import { + Config, + emitEvent, + Guild, + Member, + Region, + VoiceServerUpdateEvent, + VoiceState, + VoiceStateUpdateEvent, +} from "@fosscord/util"; +import { genVoiceToken } from "@fosscord/gateway/util/SessionUtils"; // TODO: check if a voice server is setup // Notice: Bot users respect the voice channel's user limit, if set. When the voice channel is full, you will not receive the Voice State Update or Voice Server Update events in response to your own Voice State Update. Having MANAGE_CHANNELS permission bypasses this limit and allows you to join regardless of the channel being full or not. @@ -14,21 +23,27 @@ export async function onVoiceStateUpdate(this: WebSocket, data: Payload) { let voiceState: VoiceState; try { voiceState = await VoiceState.findOneOrFail({ - where: { user_id: this.user_id } + where: { user_id: this.user_id }, }); - if (voiceState.session_id !== this.session_id && body.channel_id === null) { + if ( + voiceState.session_id !== this.session_id && + body.channel_id === null + ) { //Should we also check guild_id === null? //changing deaf or mute on a client that's not the one with the same session of the voicestate in the database should be ignored return; } //If a user change voice channel between guild we should send a left event first - if (voiceState.guild_id !== body.guild_id && voiceState.session_id === this.session_id) { + if ( + voiceState.guild_id !== body.guild_id && + voiceState.session_id === this.session_id + ) { await emitEvent({ event: "VOICE_STATE_UPDATE", data: { ...voiceState, channel_id: null }, guild_id: voiceState.guild_id, - }) + }); } //The event send by Discord's client on channel leave has both guild_id and channel_id as null @@ -50,10 +65,11 @@ export async function onVoiceStateUpdate(this: WebSocket, data: Payload) { voiceState.member = await Member.findOneOrFail({ where: { id: voiceState.user_id, guild_id: voiceState.guild_id }, relations: ["user", "roles"], - }) + }); //If the session changed we generate a new token - if (voiceState.session_id !== this.session_id) voiceState.token = genVoiceToken(); + if (voiceState.session_id !== this.session_id) + voiceState.token = genVoiceToken(); voiceState.session_id = this.session_id; const { id, ...newObj } = voiceState; @@ -69,13 +85,17 @@ export async function onVoiceStateUpdate(this: WebSocket, data: Payload) { //If it's null it means that we are leaving the channel and this event is not needed if (voiceState.channel_id !== null) { - const guild = await Guild.findOne({ id: voiceState.guild_id }) + const guild = await Guild.findOne({ id: voiceState.guild_id }); const regions = Config.get().regions; let guildRegion: Region; if (guild && guild.region) { - guildRegion = regions.available.filter(r => (r.id === guild.region))[0] + guildRegion = regions.available.filter( + (r) => r.id === guild.region + )[0]; } else { - guildRegion = regions.available.filter(r => (r.id === regions.default))[0] + guildRegion = regions.available.filter( + (r) => r.id === regions.default + )[0]; } await emitEvent({ diff --git a/gateway/src/opcodes/index.ts b/gateway/src/opcodes/index.ts index fa57f568..a6d13bfb 100644 --- a/gateway/src/opcodes/index.ts +++ b/gateway/src/opcodes/index.ts @@ -1,5 +1,5 @@ -import { Payload } from "../util/Constants"; -import WebSocket from "../util/WebSocket"; +import { Payload } from "@fosscord/gateway/util/Constants"; +import WebSocket from "@fosscord/gateway/util/WebSocket"; import { onHeartbeat } from "./Heartbeat"; import { onIdentify } from "./Identify"; import { onLazyRequest } from "./LazyRequest"; diff --git a/gateway/src/opcodes/instanceOf.ts b/gateway/src/opcodes/instanceOf.ts index c4ee5ee6..6d84ac21 100644 --- a/gateway/src/opcodes/instanceOf.ts +++ b/gateway/src/opcodes/instanceOf.ts @@ -1,6 +1,6 @@ import { instanceOf } from "lambert-server"; -import { CLOSECODES } from "../util/Constants"; -import WebSocket from "../util/WebSocket"; +import { CLOSECODES } from "@fosscord/gateway/util/Constants"; +import WebSocket from "@fosscord/gateway/util/WebSocket"; export function check(this: WebSocket, schema: any, data: any) { try { diff --git a/gateway/src/util/Send.ts b/gateway/src/util/Send.ts index be25ac4f..1b00e361 100644 --- a/gateway/src/util/Send.ts +++ b/gateway/src/util/Send.ts @@ -2,7 +2,7 @@ var erlpack: any; try { erlpack = require("erlpack"); } catch (error) {} -import { Payload } from "../util/Constants"; +import { Payload } from "@fosscord/gateway/util/Constants"; import WebSocket from "./WebSocket"; diff --git a/gateway/src/util/WebSocket.ts b/gateway/src/util/WebSocket.ts index 2c763743..820cb1a3 100644 --- a/gateway/src/util/WebSocket.ts +++ b/gateway/src/util/WebSocket.ts @@ -1,7 +1,6 @@ import { Intents, Permissions } from "@fosscord/util"; -import WS, { Server, Data } from "ws"; +import WS from "ws"; import { Deflate } from "zlib"; -import { Channel } from "amqplib"; interface WebSocket extends WS { version: number; @@ -21,4 +20,3 @@ interface WebSocket extends WS { } export default WebSocket; -export { Server, Data }; diff --git a/gateway/src/util/index.ts b/gateway/src/util/index.ts new file mode 100644 index 00000000..27af5813 --- /dev/null +++ b/gateway/src/util/index.ts @@ -0,0 +1,5 @@ +export * from "./Constants"; +export * from "./Send"; +export * from "./SessionUtils"; +export * from "./setHeartbeat"; +export * from "./WebSocket"; diff --git a/gateway/tsconfig.json b/gateway/tsconfig.json index e5bf92c6..2530aa41 100644 --- a/gateway/tsconfig.json +++ b/gateway/tsconfig.json @@ -67,6 +67,11 @@ /* Advanced Options */ "skipLibCheck": true /* Skip type checking of declaration files. */, "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */, - "resolveJsonModule": true + "resolveJsonModule": true, + "baseUrl": ".", + "paths": { + "@fosscord/gateway/*": ["src/*"], + "@fosscord/util/*": ["../util/src/*"] + } } } diff --git a/util/package-lock.json b/util/package-lock.json index 1f4c1875..97bd66d2 100644 --- a/util/package-lock.json +++ b/util/package-lock.json @@ -23,6 +23,7 @@ "pg": "^8.7.1", "reflect-metadata": "^0.1.13", "sqlite3": "^5.0.2", + "tsconfig-paths": "^3.11.0", "typeorm": "^0.2.37", "typescript": "^4.4.2", "typescript-json-schema": "^0.50.1" @@ -1156,6 +1157,11 @@ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==" }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=" + }, "node_modules/@types/jsonwebtoken": { "version": "8.5.4", "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.5.4.tgz", @@ -7875,6 +7881,14 @@ "node": ">=8" } }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "engines": { + "node": ">=4" + } + }, "node_modules/strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", @@ -8042,6 +8056,28 @@ "node": ">=0.8" } }, + "node_modules/tsconfig-paths": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.11.0.tgz", + "integrity": "sha512-7ecdYDnIdmv639mmDwslG6KQg1Z9STTz1j7Gcz0xa+nshh/gKDAHcPxRbWOsA3SPp0tXP2leTcY9Kw+NAkfZzA==", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.0", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, "node_modules/tslib": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", @@ -9666,6 +9702,11 @@ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==" }, + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=" + }, "@types/jsonwebtoken": { "version": "8.5.4", "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-8.5.4.tgz", @@ -14925,6 +14966,11 @@ "ansi-regex": "^5.0.0" } }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" + }, "strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", @@ -15051,6 +15097,27 @@ "punycode": "^2.1.1" } }, + "tsconfig-paths": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.11.0.tgz", + "integrity": "sha512-7ecdYDnIdmv639mmDwslG6KQg1Z9STTz1j7Gcz0xa+nshh/gKDAHcPxRbWOsA3SPp0tXP2leTcY9Kw+NAkfZzA==", + "requires": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.0", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "requires": { + "minimist": "^1.2.0" + } + } + } + }, "tslib": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", diff --git a/util/package.json b/util/package.json index 07623f7a..751484af 100644 --- a/util/package.json +++ b/util/package.json @@ -49,6 +49,7 @@ "pg": "^8.7.1", "reflect-metadata": "^0.1.13", "sqlite3": "^5.0.2", + "tsconfig-paths": "^3.11.0", "typeorm": "^0.2.37", "typescript": "^4.4.2", "typescript-json-schema": "^0.50.1" diff --git a/util/src/interfaces/Event.ts b/util/src/interfaces/Event.ts index ae966e42..5c2a01b0 100644 --- a/util/src/interfaces/Event.ts +++ b/util/src/interfaces/Event.ts @@ -423,6 +423,51 @@ export interface RelationshipRemoveEvent extends Event { data: Omit; } +export type EventData = + | InvalidatedEvent + | ReadyEvent + | ChannelCreateEvent + | ChannelUpdateEvent + | ChannelDeleteEvent + | ChannelPinsUpdateEvent + | GuildCreateEvent + | GuildUpdateEvent + | GuildDeleteEvent + | GuildBanAddEvent + | GuildBanRemoveEvent + | GuildEmojiUpdateEvent + | GuildIntegrationUpdateEvent + | GuildMemberAddEvent + | GuildMemberRemoveEvent + | GuildMemberUpdateEvent + | GuildMembersChunkEvent + | GuildRoleCreateEvent + | GuildRoleUpdateEvent + | GuildRoleDeleteEvent + | InviteCreateEvent + | InviteDeleteEvent + | MessageCreateEvent + | MessageUpdateEvent + | MessageDeleteEvent + | MessageDeleteBulkEvent + | MessageReactionAddEvent + | MessageReactionRemoveEvent + | MessageReactionRemoveAllEvent + | MessageReactionRemoveEmojiEvent + | PresenceUpdateEvent + | TypingStartEvent + | UserUpdateEvent + | VoiceStateUpdateEvent + | VoiceServerUpdateEvent + | WebhooksUpdateEvent + | ApplicationCommandCreateEvent + | ApplicationCommandUpdateEvent + | ApplicationCommandDeleteEvent + | InteractionCreateEvent + | MessageAckEvent + | RelationshipAddEvent + | RelationshipRemoveEvent; + // located in collection events export enum EVENTEnum { diff --git a/util/src/util/Constants.ts b/util/src/util/Constants.ts index 713d59da..d2cc5130 100644 --- a/util/src/util/Constants.ts +++ b/util/src/util/Constants.ts @@ -632,7 +632,7 @@ export const DiscordApiErrors = { OAUTH2_APPLICATION_BOT_ABSENT: new ApiError("OAuth2 application does not have a bot", 50010), MAXIMUM_OAUTH2_APPLICATIONS: new ApiError("OAuth2 application limit reached", 50011), INVALID_OAUTH_STATE: new ApiError("Invalid OAuth2 state", 50012), - MISSING_PERMISSIONS: new ApiError("You lack permissions to perform that action", 50013), + MISSING_PERMISSIONS: new ApiError("You lack permissions to perform that action ({})", 50013, undefined, [""]), INVALID_AUTHENTICATION_TOKEN: new ApiError("Invalid authentication token provided", 50014), NOTE_TOO_LONG: new ApiError("Note was too long", 50015), INVALID_BULK_DELETE_QUANTITY: new ApiError( diff --git a/util/src/util/Database.ts b/util/src/util/Database.ts index d3844cd9..c22d8abd 100644 --- a/util/src/util/Database.ts +++ b/util/src/util/Database.ts @@ -21,7 +21,7 @@ export function initDatabase() { // entities: Object.values(Models).filter((x) => x.constructor.name !== "Object"), synchronize: true, - logging: false, + logging: true, cache: { duration: 1000 * 3, // cache all find queries for 3 seconds }, -- cgit 1.5.1 From 78c1d6a82e02041b53c36b1dd7c30bcbc7805617 Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Sun, 12 Sep 2021 21:20:47 +0200 Subject: :bug: fix gateway --- gateway/src/events/Connection.ts | 5 +++-- gateway/src/events/Message.ts | 2 +- gateway/src/util/WebSocket.ts | 1 + util/src/util/Database.ts | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) (limited to 'util/src') diff --git a/gateway/src/events/Connection.ts b/gateway/src/events/Connection.ts index 625ceaa2..b9d2d6a1 100644 --- a/gateway/src/events/Connection.ts +++ b/gateway/src/events/Connection.ts @@ -1,4 +1,5 @@ -import WebSocket, { Server } from "@fosscord/gateway/util/WebSocket"; +import WS from "ws"; +import WebSocket from "@fosscord/gateway/util/WebSocket"; import { IncomingMessage } from "http"; import { Close } from "./Close"; import { Message } from "./Message"; @@ -18,7 +19,7 @@ try { // TODO: check msg max size export async function Connection( - this: Server, + this: WS.Server, socket: WebSocket, request: IncomingMessage ) { diff --git a/gateway/src/events/Message.ts b/gateway/src/events/Message.ts index 5c6bd2fc..66f98f1c 100644 --- a/gateway/src/events/Message.ts +++ b/gateway/src/events/Message.ts @@ -1,4 +1,4 @@ -import WebSocket, { Data } from "@fosscord/gateway/util/WebSocket"; +import WebSocket from "@fosscord/gateway/util/WebSocket"; var erlpack: any; try { erlpack = require("erlpack"); diff --git a/gateway/src/util/WebSocket.ts b/gateway/src/util/WebSocket.ts index 820cb1a3..15d1549f 100644 --- a/gateway/src/util/WebSocket.ts +++ b/gateway/src/util/WebSocket.ts @@ -1,6 +1,7 @@ import { Intents, Permissions } from "@fosscord/util"; import WS from "ws"; import { Deflate } from "zlib"; +import { Channel } from "amqplib"; interface WebSocket extends WS { version: number; diff --git a/util/src/util/Database.ts b/util/src/util/Database.ts index c22d8abd..d3844cd9 100644 --- a/util/src/util/Database.ts +++ b/util/src/util/Database.ts @@ -21,7 +21,7 @@ export function initDatabase() { // entities: Object.values(Models).filter((x) => x.constructor.name !== "Object"), synchronize: true, - logging: true, + logging: false, cache: { duration: 1000 * 3, // cache all find queries for 3 seconds }, -- cgit 1.5.1 From 13b7b847618b520112af568c5cd71a6068d576c0 Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Mon, 13 Sep 2021 00:17:56 +0200 Subject: :bug: fix channel events + message send --- bundle/package.json | 3 ++- gateway/src/listener/listener.ts | 26 ++++++++++++++------------ util/src/entities/Channel.ts | 1 + 3 files changed, 17 insertions(+), 13 deletions(-) (limited to 'util/src') diff --git a/bundle/package.json b/bundle/package.json index 996ab30b..83f26116 100644 --- a/bundle/package.json +++ b/bundle/package.json @@ -11,7 +11,8 @@ "build:api": "cd ../api/ && npm run build", "build:cdn": "cd ../cdn/ && npm run build", "build:gateway": "cd ../gateway/ && npm run build", - "start": "npm run build && node -r ./tsconfig-paths-bootstrap.js dist/start.js", + "start": "npm run build && npm run start:bundle", + "start:bundle": "node -r ./tsconfig-paths-bootstrap.js dist/start.js", "test": "echo \"Error: no test specified\" && exit 1" }, "repository": { diff --git a/gateway/src/listener/listener.ts b/gateway/src/listener/listener.ts index e5630a43..7152c74b 100644 --- a/gateway/src/listener/listener.ts +++ b/gateway/src/listener/listener.ts @@ -26,16 +26,16 @@ import { Recipient } from "@fosscord/util"; // TODO: use already queried guilds/channels of Identify and don't fetch them again export async function setupListener(this: WebSocket) { - const members = await Member.find({ id: this.user_id }); - const guild_ids = members.map((x) => x.guild_id); - const user = await User.findOneOrFail({ id: this.user_id }); + const members = await Member.find({ + where: { id: this.user_id }, + relations: ["guild", "guild.channels"], + }); + const guilds = members.map((x) => x.guild); const recipients = await Recipient.find({ where: { user_id: this.user_id }, relations: ["channel"], }); - const channels = await Channel.find({ guild_id: In(guild_ids) }); const dm_channels = recipients.map((x) => x.channel); - const guild_channels = channels.filter((x) => x.guild_id); const opts: { acknowledge: boolean; channel?: AMQChannel } = { acknowledge: true, @@ -54,18 +54,20 @@ export async function setupListener(this: WebSocket) { this.events[channel.id] = await listenEvent(channel.id, consumer, opts); } - for (const guild of guild_ids) { + for (const guild of guilds) { // contains guild and dm channels - getPermission(this.user_id, guild) + getPermission(this.user_id, guild.id) .then(async (x) => { - this.permissions[guild] = x; + this.permissions[guild.id] = x; this.listeners; - this.events[guild] = await listenEvent(guild, consumer, opts); + this.events[guild.id] = await listenEvent( + guild.id, + consumer, + opts + ); - for (const channel of guild_channels.filter( - (c) => c.guild_id === guild - )) { + for (const channel of guild.channels) { if ( x .overwriteChannel(channel.permission_overwrites) diff --git a/util/src/entities/Channel.ts b/util/src/entities/Channel.ts index fce85e3f..592b0b83 100644 --- a/util/src/entities/Channel.ts +++ b/util/src/entities/Channel.ts @@ -61,6 +61,7 @@ export class Channel extends BaseClass { @ManyToOne(() => Channel) parent?: Channel; + // only for group dms @Column({ nullable: true }) @RelationId((channel: Channel) => channel.owner) owner_id: string; -- cgit 1.5.1 From 07ba78d391ac517225d3afa537d7eb4f7b13c74d Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Mon, 13 Sep 2021 01:11:03 +0200 Subject: :bug: fix dm #321 --- api/src/routes/channels/#channel_id/permissions.ts | 4 +- api/src/routes/users/@me/channels.ts | 16 ++++---- api/tests/automatic.test.js | 2 + gateway/src/listener/listener.ts | 2 +- gateway/src/opcodes/Identify.ts | 43 +++++++++++++++------- util/src/entities/Channel.ts | 12 +++--- util/src/util/Permissions.ts | 2 +- 7 files changed, 50 insertions(+), 31 deletions(-) (limited to 'util/src') diff --git a/api/src/routes/channels/#channel_id/permissions.ts b/api/src/routes/channels/#channel_id/permissions.ts index 827e46f2..959ab8e0 100644 --- a/api/src/routes/channels/#channel_id/permissions.ts +++ b/api/src/routes/channels/#channel_id/permissions.ts @@ -35,7 +35,7 @@ router.put( allow: body.allow, deny: body.deny }; - channel.permission_overwrites.push(overwrite); + channel.permission_overwrites!.push(overwrite); } overwrite.allow = body.allow; overwrite.deny = body.deny; @@ -60,7 +60,7 @@ router.delete("/:overwrite_id", route({ permission: "MANAGE_ROLES" }), async (re const channel = await Channel.findOneOrFail({ id: channel_id }); if (!channel.guild_id) throw new HTTPError("Channel not found", 404); - channel.permission_overwrites = channel.permission_overwrites.filter((x) => x.id === overwrite_id); + channel.permission_overwrites = channel.permission_overwrites!.filter((x) => x.id === overwrite_id); await Promise.all([ channel.save(), diff --git a/api/src/routes/users/@me/channels.ts b/api/src/routes/users/@me/channels.ts index 5515a217..da33f204 100644 --- a/api/src/routes/users/@me/channels.ts +++ b/api/src/routes/users/@me/channels.ts @@ -4,11 +4,6 @@ import { HTTPError } from "lambert-server"; import { route } from "@fosscord/api"; import { In } from "typeorm"; -export interface DmChannelCreateSchema { - name?: string; - recipients: string[]; -} - const router: Router = Router(); router.get("/", route({}), async (req: Request, res: Response) => { @@ -17,12 +12,17 @@ router.get("/", route({}), async (req: Request, res: Response) => { res.json(recipients.map((x) => x.channel)); }); +export interface DmChannelCreateSchema { + name?: string; + recipients: string[]; +} + router.post("/", route({ body: "DmChannelCreateSchema" }), async (req: Request, res: Response) => { const body = req.body as DmChannelCreateSchema; body.recipients = body.recipients.filter((x) => x !== req.user_id).unique(); - const recipients = await User.find({ id: In(body.recipients) }); + const recipients = await User.find({ where: body.recipients.map((x) => ({ id: x })) }); if (recipients.length !== body.recipients.length) { throw new HTTPError("Recipient/s not found"); @@ -34,10 +34,10 @@ router.post("/", route({ body: "DmChannelCreateSchema" }), async (req: Request, const channel = await new Channel({ name, type, - owner_id: req.user_id, + // owner_id only for group dm channels created_at: new Date(), last_message_id: null, - recipients: [...body.recipients.map((x) => new Recipient({ id: x })), new Recipient({ id: req.user_id })] + recipients: [...body.recipients.map((x) => new Recipient({ user_id: x })), new Recipient({ user_id: req.user_id })] }).save(); await emitEvent({ event: "CHANNEL_CREATE", data: channel, user_id: req.user_id } as ChannelCreateEvent); diff --git a/api/tests/automatic.test.js b/api/tests/automatic.test.js index e69de29b..2d0a9fcb 100644 --- a/api/tests/automatic.test.js +++ b/api/tests/automatic.test.js @@ -0,0 +1,2 @@ +// TODO: check every route based on route() paramters: https://github.com/fosscord/fosscord-server/issues/308 +// TODO: check every route with different database engine diff --git a/gateway/src/listener/listener.ts b/gateway/src/listener/listener.ts index 7152c74b..ef3dd890 100644 --- a/gateway/src/listener/listener.ts +++ b/gateway/src/listener/listener.ts @@ -70,7 +70,7 @@ export async function setupListener(this: WebSocket) { for (const channel of guild.channels) { if ( x - .overwriteChannel(channel.permission_overwrites) + .overwriteChannel(channel.permission_overwrites!) .has("VIEW_CHANNEL") ) { this.events[channel.id] = await listenEvent( diff --git a/gateway/src/opcodes/Identify.ts b/gateway/src/opcodes/Identify.ts index 04a6c84c..88c9b942 100644 --- a/gateway/src/opcodes/Identify.ts +++ b/gateway/src/opcodes/Identify.ts @@ -14,6 +14,8 @@ import { dbConnection, PublicMemberProjection, PublicMember, + ChannelType, + PublicUser, } from "@fosscord/util"; import { setupListener } from "../listener/listener"; import { IdentifySchema } from "../schema/Identify"; @@ -57,6 +59,7 @@ export async function onIdentify(this: WebSocket, data: Payload) { return this.close(CLOSECODES.Invalid_shard); } } + var users: PublicUser[] = []; const members = await Member.find({ where: { id: this.user_id }, @@ -85,12 +88,36 @@ export async function onIdentify(this: WebSocket, data: Payload) { const recipients = await Recipient.find({ where: { user_id: this.user_id }, - relations: ["channel", "channel.recipients"], + relations: ["channel", "channel.recipients", "channel.recipients.user"], + // TODO: public user selection + }); + const channels = recipients.map((x) => { + // @ts-ignore + x.channel.recipients = x.channel.recipients?.map((x) => x.user); + // @ts-ignore + users = users.concat(x.channel.recipients); + if (x.channel.type === ChannelType.DM) { + x.channel.recipients = [ + // @ts-ignore + x.channel.recipients.find((x) => x.id !== this.user_id), + ]; + } + return x.channel; }); - const channels = recipients.map((x) => x.channel); const user = await User.findOneOrFail({ id: this.user_id }); if (!user) return this.close(CLOSECODES.Authentication_failed); + const public_user = { + username: user.username, + discriminator: user.discriminator, + id: user.id, + public_flags: user.public_flags, + avatar: user.avatar, + bot: user.bot, + bio: user.bio, + }; + users.push(public_user); + const session_id = genSessionId(); this.session_id = session_id; //Set the session of the WebSocket object const session = new Session({ @@ -108,16 +135,6 @@ export async function onIdentify(this: WebSocket, data: Payload) { //We save the session and we delete it when the websocket is closed await session.save(); - const public_user = { - username: user.username, - discriminator: user.discriminator, - id: user.id, - public_flags: user.public_flags, - avatar: user.avatar, - bot: user.bot, - bio: user.bio, - }; - const privateUser = { avatar: user.avatar, mobile: user.mobile, @@ -180,7 +197,7 @@ export async function onIdentify(this: WebSocket, data: Payload) { // @ts-ignore experiments: experiments, // TODO guild_join_requests: [], // TODO what is this? - users: [public_user].unique(), // TODO + users: users.unique(), // TODO merged_members: merged_members, // shard // TODO: only for bots sharding // application // TODO for applications diff --git a/util/src/entities/Channel.ts b/util/src/entities/Channel.ts index 592b0b83..fc954f63 100644 --- a/util/src/entities/Channel.ts +++ b/util/src/entities/Channel.ts @@ -28,8 +28,8 @@ export class Channel extends BaseClass { @Column() created_at: Date; - @Column() - name: string; + @Column({ nullable: true }) + name?: string; @Column({ type: "simple-enum", enum: ChannelType }) type: ChannelType; @@ -76,11 +76,11 @@ export class Channel extends BaseClass { @Column({ nullable: true }) default_auto_archive_duration?: number; - @Column() - position: number; + @Column({ nullable: true }) + position?: number; - @Column({ type: "simple-json" }) - permission_overwrites: ChannelPermissionOverwrite[]; + @Column({ type: "simple-json", nullable: true }) + permission_overwrites?: ChannelPermissionOverwrite[]; @Column({ nullable: true }) video_quality_mode?: number; diff --git a/util/src/util/Permissions.ts b/util/src/util/Permissions.ts index 628a495d..9d87253a 100644 --- a/util/src/util/Permissions.ts +++ b/util/src/util/Permissions.ts @@ -242,7 +242,7 @@ export async function getPermission( }); } - let recipient_ids: any = channel?.recipients?.map((x) => x.id); + let recipient_ids: any = channel?.recipients?.map((x) => x.user_id); if (!recipient_ids?.length) recipient_ids = null; // TODO: remove guild.roles and convert recipient_ids to recipients -- cgit 1.5.1 From dbbed7cbba8d5967d5b2bdc8a666fce22ac0e22c Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Mon, 13 Sep 2021 12:22:41 +0200 Subject: :bug: fix relationship --- api/src/routes/users/@me/relationships.ts | 108 +++++++++++++++--------------- gateway/src/opcodes/Identify.ts | 7 +- util/src/entities/Relationship.ts | 30 +++++++-- util/src/interfaces/Event.ts | 14 ++-- 4 files changed, 94 insertions(+), 65 deletions(-) (limited to 'util/src') diff --git a/api/src/routes/users/@me/relationships.ts b/api/src/routes/users/@me/relationships.ts index cc264f3f..58d2e481 100644 --- a/api/src/routes/users/@me/relationships.ts +++ b/api/src/routes/users/@me/relationships.ts @@ -31,7 +31,7 @@ router.put("/:id", route({ body: "RelationshipPutSchema" }), async (req: Request return await updateRelationship( req, res, - await User.findOneOrFail({ id: req.params.id }, { relations: ["relationships"], select: userProjection }), + await User.findOneOrFail({ id: req.params.id }, { relations: ["relationships", "relationships.to"], select: userProjection }), req.body.type ); }); @@ -46,7 +46,7 @@ router.post("/", route({ body: "RelationshipPostSchema" }), async (req: Request, req, res, await User.findOneOrFail({ - relations: ["relationships"], + relations: ["relationships", "relationships.to"], select: userProjection, where: req.body as { discriminator: string; username: string } }), @@ -61,37 +61,40 @@ router.delete("/:id", route({}), async (req: Request, res: Response) => { const user = await User.findOneOrFail({ id: req.user_id }, { select: userProjection, relations: ["relationships"] }); const friend = await User.findOneOrFail({ id: id }, { select: userProjection, relations: ["relationships"] }); - const relationship = user.relationships.find((x) => x.id === id); - const friendRequest = friend.relationships.find((x) => x.id === req.user_id); + const relationship = user.relationships.find((x) => x.to_id === id); + const friendRequest = friend.relationships.find((x) => x.to_id === req.user_id); + if (!relationship) throw new HTTPError("You are not friends with the user", 404); if (relationship?.type === RelationshipType.blocked) { // unblock user - user.relationships.remove(relationship); await Promise.all([ - user.save(), - emitEvent({ event: "RELATIONSHIP_REMOVE", user_id: req.user_id, data: relationship } as RelationshipRemoveEvent) + Relationship.delete({ id: relationship.id }), + emitEvent({ + event: "RELATIONSHIP_REMOVE", + user_id: req.user_id, + data: relationship.toPublicRelationship() + } as RelationshipRemoveEvent) ]); return res.sendStatus(204); } - if (!relationship || !friendRequest) throw new HTTPError("You are not friends with the user", 404); - if (friendRequest.type === RelationshipType.blocked) throw new HTTPError("The user blocked you"); - - user.relationships.remove(relationship); - friend.relationships.remove(friendRequest); + if (friendRequest && friendRequest.type !== RelationshipType.blocked) { + await Promise.all([ + Relationship.delete({ id: friendRequest.id }), + await emitEvent({ + event: "RELATIONSHIP_REMOVE", + data: friendRequest.toPublicRelationship(), + user_id: id + } as RelationshipRemoveEvent) + ]); + } await Promise.all([ - user.save(), - friend.save(), + Relationship.delete({ id: relationship.id }), emitEvent({ event: "RELATIONSHIP_REMOVE", - data: relationship, + data: relationship.toPublicRelationship(), user_id: req.user_id - } as RelationshipRemoveEvent), - emitEvent({ - event: "RELATIONSHIP_REMOVE", - data: friendRequest, - user_id: id } as RelationshipRemoveEvent) ]); @@ -104,44 +107,40 @@ async function updateRelationship(req: Request, res: Response, friend: User, typ const id = friend.id; if (id === req.user_id) throw new HTTPError("You can't add yourself as a friend"); - const user = await User.findOneOrFail({ id: req.user_id }, { relations: ["relationships"], select: userProjection }); + const user = await User.findOneOrFail( + { id: req.user_id }, + { relations: ["relationships", "relationships.to"], select: userProjection } + ); - var relationship = user.relationships.find((x) => x.id === id); - const friendRequest = friend.relationships.find((x) => x.id === req.user_id); + var relationship = user.relationships.find((x) => x.to_id === id); + const friendRequest = friend.relationships.find((x) => x.to_id === req.user_id); // TODO: you can add infinitely many blocked users (should this be prevented?) if (type === RelationshipType.blocked) { if (relationship) { if (relationship.type === RelationshipType.blocked) throw new HTTPError("You already blocked the user"); relationship.type = RelationshipType.blocked; + await relationship.save(); } else { - relationship = new Relationship({ id, type: RelationshipType.blocked }); - user.relationships.push(relationship); + relationship = await new Relationship({ to_id: id, type: RelationshipType.blocked, from_id: req.user_id }).save(); } if (friendRequest && friendRequest.type !== RelationshipType.blocked) { - friend.relationships.remove(friendRequest); await Promise.all([ - user.save(), + Relationship.delete({ id: friendRequest.id }), emitEvent({ event: "RELATIONSHIP_REMOVE", - data: friendRequest, + data: friendRequest.toPublicRelationship(), user_id: id } as RelationshipRemoveEvent) ]); } - await Promise.all([ - user.save(), - emitEvent({ - event: "RELATIONSHIP_ADD", - data: { - ...relationship, - user: { ...friend } - }, - user_id: req.user_id - } as RelationshipAddEvent) - ]); + await emitEvent({ + event: "RELATIONSHIP_ADD", + data: relationship.toPublicRelationship(), + user_id: req.user_id + } as RelationshipAddEvent); return res.sendStatus(204); } @@ -149,40 +148,43 @@ async function updateRelationship(req: Request, res: Response, friend: User, typ const { maxFriends } = Config.get().limits.user; if (user.relationships.length >= maxFriends) throw DiscordApiErrors.MAXIMUM_FRIENDS.withParams(maxFriends); - var incoming_relationship = new Relationship({ nickname: undefined, type: RelationshipType.incoming, id: req.user_id }); - var outgoing_relationship = new Relationship({ nickname: undefined, type: RelationshipType.outgoing, id }); + var incoming_relationship = new Relationship({ nickname: undefined, type: RelationshipType.incoming, to: user, from: friend }); + var outgoing_relationship = new Relationship({ + nickname: undefined, + type: RelationshipType.outgoing, + to: friend, + from: user + }); if (friendRequest) { if (friendRequest.type === RelationshipType.blocked) throw new HTTPError("The user blocked you"); + if (friendRequest.type === RelationshipType.friends) throw new HTTPError("You are already friends with the user"); // accept friend request incoming_relationship = friendRequest; incoming_relationship.type = RelationshipType.friends; - outgoing_relationship.type = RelationshipType.friends; - } else friend.relationships.push(incoming_relationship); + } if (relationship) { if (relationship.type === RelationshipType.outgoing) throw new HTTPError("You already sent a friend request"); if (relationship.type === RelationshipType.blocked) throw new HTTPError("Unblock the user before sending a friend request"); if (relationship.type === RelationshipType.friends) throw new HTTPError("You are already friends with the user"); - } else user.relationships.push(outgoing_relationship); + outgoing_relationship = relationship; + outgoing_relationship.type = RelationshipType.friends; + } await Promise.all([ - user.save(), - friend.save(), + incoming_relationship.save(), + outgoing_relationship.save(), emitEvent({ event: "RELATIONSHIP_ADD", - data: { - ...outgoing_relationship, - user: { ...friend } - }, + data: outgoing_relationship.toPublicRelationship(), user_id: req.user_id } as RelationshipAddEvent), emitEvent({ event: "RELATIONSHIP_ADD", data: { - ...incoming_relationship, - should_notify: true, - user: { ...user } + ...incoming_relationship.toPublicRelationship(), + should_notify: true }, user_id: id } as RelationshipAddEvent) diff --git a/gateway/src/opcodes/Identify.ts b/gateway/src/opcodes/Identify.ts index 88c9b942..9eb4cd32 100644 --- a/gateway/src/opcodes/Identify.ts +++ b/gateway/src/opcodes/Identify.ts @@ -104,7 +104,10 @@ export async function onIdentify(this: WebSocket, data: Payload) { } return x.channel; }); - const user = await User.findOneOrFail({ id: this.user_id }); + const user = await User.findOneOrFail({ + where: { id: this.user_id }, + relations: ["relationships", "relationships.to"], + }); if (!user) return this.close(CLOSECODES.Authentication_failed); const public_user = { @@ -171,7 +174,7 @@ export async function onIdentify(this: WebSocket, data: Payload) { }), guild_experiments: [], // TODO geo_ordered_rtc_regions: [], // TODO - relationships: user.relationships, + relationships: user.relationships.map((x) => x.toPublicRelationship()), read_state: { // TODO entries: [], diff --git a/util/src/entities/Relationship.ts b/util/src/entities/Relationship.ts index 5935f5b6..61b3ac82 100644 --- a/util/src/entities/Relationship.ts +++ b/util/src/entities/Relationship.ts @@ -1,4 +1,4 @@ -import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm"; +import { Column, Entity, Index, JoinColumn, ManyToOne, RelationId } from "typeorm"; import { BaseClass } from "./BaseClass"; import { User } from "./User"; @@ -10,18 +10,36 @@ export enum RelationshipType { } @Entity("relationships") +@Index(["from_id", "to_id"], { unique: true }) export class Relationship extends BaseClass { - @Column({ nullable: true }) - @RelationId((relationship: Relationship) => relationship.user) - user_id: string; + @Column({}) + @RelationId((relationship: Relationship) => relationship.from) + from_id: string; - @JoinColumn({ name: "user_id" }) + @JoinColumn({ name: "from_id" }) @ManyToOne(() => User) - user: User; + from: User; + + @Column({}) + @RelationId((relationship: Relationship) => relationship.to) + to_id: string; + + @JoinColumn({ name: "to_id" }) + @ManyToOne(() => User) + to: User; @Column({ nullable: true }) nickname?: string; @Column({ type: "simple-enum", enum: RelationshipType }) type: RelationshipType; + + toPublicRelationship() { + return { + id: this.to?.id || this.to_id, + type: this.type, + nickname: this.nickname, + user: this.to?.toPublicUser(), + }; + } } diff --git a/util/src/interfaces/Event.ts b/util/src/interfaces/Event.ts index 5c2a01b0..aff50300 100644 --- a/util/src/interfaces/Event.ts +++ b/util/src/interfaces/Event.ts @@ -10,7 +10,7 @@ import { VoiceState } from "../entities/VoiceState"; import { ApplicationCommand } from "../entities/Application"; import { Interaction } from "./Interaction"; import { ConnectedAccount } from "../entities/ConnectedAccount"; -import { Relationship } from "../entities/Relationship"; +import { Relationship, RelationshipType } from "../entities/Relationship"; import { Presence } from "./Presence"; export interface Event { @@ -28,6 +28,12 @@ export interface InvalidatedEvent extends Event { event: "INVALIDATED"; } +export interface PublicRelationship { + id: string; + user: PublicUser; + type: RelationshipType; +} + // ! END Custom Events that shouldn't get sent to the client but processed by the server export interface ReadyEventData { @@ -72,7 +78,7 @@ export interface ReadyEventData { guild_join_requests?: any[]; // ? what is this? this is new shard?: [number, number]; user_settings?: UserSettings; - relationships?: Relationship[]; // TODO + relationships?: PublicRelationship[]; // TODO read_state: { entries: any[]; // TODO partial: boolean; @@ -412,7 +418,7 @@ export interface MessageAckEvent extends Event { export interface RelationshipAddEvent extends Event { event: "RELATIONSHIP_ADD"; - data: Relationship & { + data: PublicRelationship & { should_notify?: boolean; user: PublicUser; }; @@ -420,7 +426,7 @@ export interface RelationshipAddEvent extends Event { export interface RelationshipRemoveEvent extends Event { event: "RELATIONSHIP_REMOVE"; - data: Omit; + data: Omit; } export type EventData = -- cgit 1.5.1 From 9429c5c09ab1b7ce081c0786e080da4ee78ad22c Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Mon, 13 Sep 2021 12:22:59 +0200 Subject: :bug: fix In() query --- api/src/routes/auth/register.ts | 2 +- api/src/routes/guilds/#guild_id/roles.ts | 2 +- util/src/entities/User.ts | 14 +++++++++++--- 3 files changed, 13 insertions(+), 5 deletions(-) (limited to 'util/src') diff --git a/api/src/routes/auth/register.ts b/api/src/routes/auth/register.ts index e0af1d6d..e70e01ed 100644 --- a/api/src/routes/auth/register.ts +++ b/api/src/routes/auth/register.ts @@ -137,7 +137,7 @@ router.post("/", route({ body: "RegisterSchema" }), async (req: Request, res: Re if (!register.allowMultipleAccounts) { // TODO: check if fingerprint was eligible generated - const exists = await User.findOne({ where: { fingerprints: In(fingerprint) } }); + const exists = await User.findOne({ where: { fingerprints: fingerprint } }); if (exists) { throw FieldErrors({ diff --git a/api/src/routes/guilds/#guild_id/roles.ts b/api/src/routes/guilds/#guild_id/roles.ts index 6b2902d9..5c549262 100644 --- a/api/src/routes/guilds/#guild_id/roles.ts +++ b/api/src/routes/guilds/#guild_id/roles.ts @@ -132,7 +132,7 @@ router.patch("/", route({ body: "RolePositionUpdateSchema" }), async (req: Reque await Promise.all(body.map(async (x) => Role.update({ guild_id, id: x.id }, { position: x.position }))); - const roles = await Role.find({ guild_id, id: In(body.map((x) => x.id)) }); + const roles = await Role.find({ where: body.map((x) => ({ id: x.id, guild_id })) }); await Promise.all( roles.map((x) => diff --git a/util/src/entities/User.ts b/util/src/entities/User.ts index 9394f9e8..736704f8 100644 --- a/util/src/entities/User.ts +++ b/util/src/entities/User.ts @@ -106,7 +106,7 @@ export class User extends BaseClass { mfa_enabled: boolean; // if multi factor authentication is enabled @Column() - created_at: Date = new Date(); // registration date + created_at: Date; // registration date @Column() verified: boolean; // if the user is offically verified @@ -127,7 +127,7 @@ export class User extends BaseClass { public_flags: string; @JoinColumn({ name: "relationship_ids" }) - @OneToMany(() => Relationship, (relationship: Relationship) => relationship.user, { cascade: true }) + @OneToMany(() => Relationship, (relationship: Relationship) => relationship.from) relationships: Relationship[]; @JoinColumn({ name: "connected_account_ids" }) @@ -146,6 +146,14 @@ export class User extends BaseClass { @Column({ type: "simple-json" }) settings: UserSettings; + toPublicUser() { + const user: any = {}; + PublicUserProjection.forEach((x) => { + user[x] = this[x]; + }); + return user as PublicUser; + } + static async getPublicUser(user_id: string, opts?: FindOneOptions) { const user = await User.findOne( { id: user_id }, @@ -261,7 +269,7 @@ export class UserFlags extends BitField { SYSTEM: BigInt(1) << BigInt(12), HAS_UNREAD_URGENT_MESSAGES: BigInt(1) << BigInt(13), BUGHUNTER_LEVEL_2: BigInt(1) << BigInt(14), - UNDERAGE_DELETED: BigInt(1) << BigInt(15), + UNDERAGE_DELETED: BigInt(1) << BigInt(15), VERIFIED_BOT: BigInt(1) << BigInt(16), EARLY_VERIFIED_BOT_DEVELOPER: BigInt(1) << BigInt(17), }; -- cgit 1.5.1 From 072be4383ffcdf528481cdc4b0512062ff7c1e12 Mon Sep 17 00:00:00 2001 From: AlTech98 Date: Mon, 13 Sep 2021 17:31:07 +0200 Subject: Fix attachments not being saved to db --- util/src/entities/Message.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'util/src') diff --git a/util/src/entities/Message.ts b/util/src/entities/Message.ts index f4c7fdc7..506db71a 100644 --- a/util/src/entities/Message.ts +++ b/util/src/entities/Message.ts @@ -128,7 +128,7 @@ export class Message extends BaseClass { sticker_items?: Sticker[]; @JoinColumn({ name: "attachment_ids" }) - @OneToMany(() => Attachment, (attachment: Attachment) => attachment.message) + @OneToMany(() => Attachment, (attachment: Attachment) => attachment.message, { cascade: true }) attachments?: Attachment[]; @Column({ type: "simple-json" }) -- cgit 1.5.1 From f691aa4c5aa47c8a8085c7b01912a1c403ce8732 Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Tue, 14 Sep 2021 22:15:55 +0200 Subject: :construction: webhook --- api/assets/schemas.json | 255 +++++++++++++++++++++++- api/client_test/index.html | 2 +- api/src/middlewares/Authentication.ts | 4 +- api/src/middlewares/ErrorHandler.ts | 7 +- api/src/routes/discoverable-guilds.ts | 2 +- api/src/routes/guilds/#guild_id/integrations.ts | 10 + api/src/routes/template.ts.disabled | 2 +- api/src/routes/webhooks/#webhook_id/index.ts | 89 +++++++++ api/src/util/route.ts | 8 +- util/src/entities/Webhook.ts | 6 +- util/src/util/Regex.ts | 2 +- 11 files changed, 369 insertions(+), 18 deletions(-) create mode 100644 api/src/routes/guilds/#guild_id/integrations.ts create mode 100644 api/src/routes/webhooks/#webhook_id/index.ts (limited to 'util/src') diff --git a/api/assets/schemas.json b/api/assets/schemas.json index 9c34f968..88558cfa 100644 --- a/api/assets/schemas.json +++ b/api/assets/schemas.json @@ -1770,10 +1770,6 @@ } }, "additionalProperties": false, - "required": [ - "avatar", - "name" - ], "definitions": { "ChannelType": { "enum": [ @@ -7446,5 +7442,256 @@ } }, "$schema": "http://json-schema.org/draft-07/schema#" + }, + "WebhookModifySchema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "avatar": { + "type": "string" + } + }, + "additionalProperties": false, + "definitions": { + "ChannelType": { + "enum": [ + 0, + 1, + 10, + 11, + 12, + 13, + 2, + 3, + 4, + 5, + 6 + ], + "type": "number" + }, + "ChannelPermissionOverwriteType": { + "enum": [ + 0, + 1 + ], + "type": "number" + }, + "Embed": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "type": { + "enum": [ + "article", + "gifv", + "image", + "link", + "rich", + "video" + ], + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + }, + "timestamp": { + "type": "string", + "format": "date-time" + }, + "color": { + "type": "integer" + }, + "footer": { + "type": "object", + "properties": { + "text": { + "type": "string" + }, + "icon_url": { + "type": "string" + }, + "proxy_icon_url": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "text" + ] + }, + "image": { + "$ref": "#/definitions/EmbedImage" + }, + "thumbnail": { + "$ref": "#/definitions/EmbedImage" + }, + "video": { + "$ref": "#/definitions/EmbedImage" + }, + "provider": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "additionalProperties": false + }, + "author": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "url": { + "type": "string" + }, + "icon_url": { + "type": "string" + }, + "proxy_icon_url": { + "type": "string" + } + }, + "additionalProperties": false + }, + "fields": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "value": { + "type": "string" + }, + "inline": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "name", + "value" + ] + } + } + }, + "additionalProperties": false + }, + "EmbedImage": { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "proxy_url": { + "type": "string" + }, + "height": { + "type": "integer" + }, + "width": { + "type": "integer" + } + }, + "additionalProperties": false + }, + "ChannelModifySchema": { + "type": "object", + "properties": { + "name": { + "maxLength": 100, + "type": "string" + }, + "type": { + "$ref": "#/definitions/ChannelType" + }, + "topic": { + "type": "string" + }, + "bitrate": { + "type": "integer" + }, + "user_limit": { + "type": "integer" + }, + "rate_limit_per_user": { + "type": "integer" + }, + "position": { + "type": "integer" + }, + "permission_overwrites": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "$ref": "#/definitions/ChannelPermissionOverwriteType" + }, + "allow": { + "type": "bigint" + }, + "deny": { + "type": "bigint" + } + }, + "additionalProperties": false, + "required": [ + "allow", + "deny", + "id", + "type" + ] + } + }, + "parent_id": { + "type": "string" + }, + "id": { + "type": "string" + }, + "nsfw": { + "type": "boolean" + }, + "rtc_region": { + "type": "string" + }, + "default_auto_archive_duration": { + "type": "integer" + } + }, + "additionalProperties": false, + "required": [ + "name", + "type" + ] + }, + "RelationshipType": { + "enum": [ + 1, + 2, + 3, + 4 + ], + "type": "number" + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" } } \ No newline at end of file diff --git a/api/client_test/index.html b/api/client_test/index.html index ac66df06..335b477c 100644 --- a/api/client_test/index.html +++ b/api/client_test/index.html @@ -11,7 +11,7 @@ window.__OVERLAY__ = /overlay/.test(location.pathname); window.__BILLING_STANDALONE__ = /^\/billing/.test(location.pathname); window.GLOBAL_ENV = { - API_ENDPOINT: "/api", + API_ENDPOINT: `//${location.host}/api`, API_VERSION: 9, GATEWAY_ENDPOINT: `${location.protocol === "https:" ? "wss://" : "ws://"}${location.hostname}:3002`, WEBAPP_ENDPOINT: "", diff --git a/api/src/middlewares/Authentication.ts b/api/src/middlewares/Authentication.ts index a300c786..32307f42 100644 --- a/api/src/middlewares/Authentication.ts +++ b/api/src/middlewares/Authentication.ts @@ -5,11 +5,11 @@ import { checkToken, Config } from "@fosscord/util"; export const NO_AUTHORIZATION_ROUTES = [ "/auth/login", "/auth/register", - "/webhooks/", "/ping", "/gateway", "/experiments", - /\/guilds\/\d+\/widget\.(json|png)/ + /\/guilds\/\d+\/widget\.(json|png)/, + /\/webhooks\/\d+\/\w+/ // only exclude webhook calls with webhook token ]; export const API_PREFIX = /^\/api(\/v\d+)?/; diff --git a/api/src/middlewares/ErrorHandler.ts b/api/src/middlewares/ErrorHandler.ts index d288f3fb..338da8d5 100644 --- a/api/src/middlewares/ErrorHandler.ts +++ b/api/src/middlewares/ErrorHandler.ts @@ -1,9 +1,10 @@ import { NextFunction, Request, Response } from "express"; import { HTTPError } from "lambert-server"; -import { EntityNotFoundError } from "typeorm"; import { FieldError } from "@fosscord/api"; import { ApiError } from "@fosscord/util"; +const EntityNotFoundErrorRegex = /"(\w+)"/; + export function ErrorHandler(error: Error, req: Request, res: Response, next: NextFunction) { if (!error) return next(); @@ -18,8 +19,8 @@ export function ErrorHandler(error: Error, req: Request, res: Response, next: Ne code = error.code; message = error.message; httpcode = error.httpStatus; - } else if (error instanceof EntityNotFoundError) { - message = `${(error as any).stringifyTarget || "Item"} could not be found`; + } else if (error.name === "EntityNotFoundError") { + message = `${error.message.match(EntityNotFoundErrorRegex)?.[1] || "Item"} could not be found`; code = 404; } else if (error instanceof FieldError) { code = Number(error.code); diff --git a/api/src/routes/discoverable-guilds.ts b/api/src/routes/discoverable-guilds.ts index f667eb2a..71789123 100644 --- a/api/src/routes/discoverable-guilds.ts +++ b/api/src/routes/discoverable-guilds.ts @@ -10,7 +10,7 @@ router.get("/", route({}), async (req: Request, res: Response) => { // ! this only works using SQL querys // TODO: implement this with default typeorm query // const guilds = await Guild.find({ where: { features: "DISCOVERABLE" } }); //, take: Math.abs(Number(limit)) }); - const guilds = await Guild.find({ where: `"features" LIKE 'COMMUNITY'`, take: Math.abs(Number(limit)) }); + const guilds = await Guild.find({ where: `"features" LIKE 'COMMUNITY'`, take: Math.abs(Number(limit) || 50) }); res.send({ guilds: guilds }); }); diff --git a/api/src/routes/guilds/#guild_id/integrations.ts b/api/src/routes/guilds/#guild_id/integrations.ts new file mode 100644 index 00000000..f6b8e99d --- /dev/null +++ b/api/src/routes/guilds/#guild_id/integrations.ts @@ -0,0 +1,10 @@ +import { route } from "@fosscord/api"; +import { Router, Request, Response } from "express"; +const router = Router(); + +router.get("/", route({ permission: "MANAGE_GUILD" }), async (req: Request, res: Response) => { + // TODO: integrations (followed channels, youtube, twitch) + res.send([]); +}); + +export default router; diff --git a/api/src/routes/template.ts.disabled b/api/src/routes/template.ts.disabled index ad785f10..524e981b 100644 --- a/api/src/routes/template.ts.disabled +++ b/api/src/routes/template.ts.disabled @@ -4,7 +4,7 @@ import { Router, Request, Response } from "express"; const router = Router(); router.get("/", async (req: Request, res: Response) => { - res.send({}); + res.json({}); }); export default router; diff --git a/api/src/routes/webhooks/#webhook_id/index.ts b/api/src/routes/webhooks/#webhook_id/index.ts new file mode 100644 index 00000000..e9b40ebf --- /dev/null +++ b/api/src/routes/webhooks/#webhook_id/index.ts @@ -0,0 +1,89 @@ +import { Channel, Config, emitEvent, JWTOptions, Webhook, WebhooksUpdateEvent } from "@fosscord/util"; +import { route, Authentication, handleFile } from "@fosscord/api"; +import { Router, Request, Response, NextFunction } from "express"; +import jwt from "jsonwebtoken"; +import { HTTPError } from "lambert-server"; +const router = Router(); + +export interface WebhookModifySchema { + name?: string; + avatar?: string; + // channel_id?: string; // TODO +} + +function validateWebhookToken(req: Request, res: Response, next: NextFunction) { + const { jwtSecret } = Config.get().security; + + jwt.verify(req.params.token, jwtSecret, JWTOptions, async (err, decoded: any) => { + if (err) return next(new HTTPError("Invalid Token", 401)); + next(); + }); +} + +router.get("/", route({}), async (req: Request, res: Response) => { + res.json(await Webhook.findOneOrFail({ id: req.params.webhook_id })); +}); + +router.get("/:token", route({}), validateWebhookToken, async (req: Request, res: Response) => { + res.json(await Webhook.findOneOrFail({ id: req.params.webhook_id })); +}); + +router.patch("/", route({ body: "WebhookModifySchema", permission: "MANAGE_WEBHOOKS" }), (req: Request, res: Response) => { + return updateWebhook(req, res); +}); + +router.patch("/:token", route({ body: "WebhookModifySchema" }), validateWebhookToken, (req: Request, res: Response) => { + return updateWebhook(req, res); +}); + +async function updateWebhook(req: Request, res: Response) { + const webhook = await Webhook.findOneOrFail({ id: req.params.webhook_id }); + if (req.body.channel_id) await Channel.findOneOrFail({ id: req.body.channel_id, guild_id: webhook.guild_id }); + + webhook.assign({ + ...req.body, + avatar: await handleFile(`/icons/${req.params.webhook_id}`, req.body.avatar) + }); + + await Promise.all([ + emitEvent({ + event: "WEBHOOKS_UPDATE", + channel_id: webhook.channel_id, + data: { + channel_id: webhook.channel_id, + guild_id: webhook.guild_id + } + } as WebhooksUpdateEvent), + webhook.save() + ]); + + res.json(webhook); +} + +router.delete("/", route({ permission: "MANAGE_WEBHOOKS" }), async (req: Request, res: Response) => { + return deleteWebhook(req, res); +}); + +router.delete("/:token", route({}), validateWebhookToken, (req: Request, res: Response) => { + return deleteWebhook(req, res); +}); + +async function deleteWebhook(req: Request, res: Response) { + const webhook = await Webhook.findOneOrFail({ id: req.params.webhook_id }); + + await Promise.all([ + emitEvent({ + event: "WEBHOOKS_UPDATE", + channel_id: webhook.channel_id, + data: { + channel_id: webhook.channel_id, + guild_id: webhook.guild_id + } + } as WebhooksUpdateEvent), + webhook.remove() + ]); + + res.sendStatus(204); +} + +export default router; diff --git a/api/src/util/route.ts b/api/src/util/route.ts index 6cd8f622..1e2beb5d 100644 --- a/api/src/util/route.ts +++ b/api/src/util/route.ts @@ -1,4 +1,4 @@ -import { DiscordApiErrors, Event, EventData, getPermission, PermissionResolvable, Permissions } from "@fosscord/util"; +import { DiscordApiErrors, Event, EventData, getPermission, PermissionResolvable, Permissions, Webhook } from "@fosscord/util"; import { NextFunction, Request, Response } from "express"; import fs from "fs"; import path from "path"; @@ -54,9 +54,13 @@ export function route(opts: RouteOptions) { return async (req: Request, res: Response, next: NextFunction) => { if (opts.permission) { const required = new Permissions(opts.permission); + if (req.params.webhook_id) { + const webhook = await Webhook.findOneOrFail({ id: req.params.webhook_id }); + req.params.channel_id = webhook.channel_id; + req.params.guild_id = webhook.guild_id; + } const permission = await getPermission(req.user_id, req.params.guild_id, req.params.channel_id); - // bitfield comparison: check if user lacks certain permission if (!permission.has(required)) { throw DiscordApiErrors.MISSING_PERMISSIONS.withParams(opts.permission as string); } diff --git a/util/src/entities/Webhook.ts b/util/src/entities/Webhook.ts index 12ba0d08..d0d98804 100644 --- a/util/src/entities/Webhook.ts +++ b/util/src/entities/Webhook.ts @@ -18,13 +18,13 @@ export class Webhook extends BaseClass { @Column({ type: "simple-enum", enum: WebhookType }) type: WebhookType; - @Column({ nullable: true }) - name?: string; + @Column() + name: string; @Column({ nullable: true }) avatar?: string; - @Column({ nullable: true }) + @Column({ nullable: true, select: false }) token?: string; @Column({ nullable: true }) diff --git a/util/src/util/Regex.ts b/util/src/util/Regex.ts index 83fc9fe8..b5d23b7f 100644 --- a/util/src/util/Regex.ts +++ b/util/src/util/Regex.ts @@ -1,5 +1,5 @@ export const DOUBLE_WHITE_SPACE = /\s\s+/g; -export const SPECIAL_CHAR = /[@#`:\r\n\t\f\v\p{C}]/gu; +export const SPECIAL_CHAR = /[@#\r\n\t\f\v]/gu; export const CHANNEL_MENTION = /<#(\d+)>/g; export const USER_MENTION = /<@!?(\d+)>/g; export const ROLE_MENTION = /<@&(\d+)>/g; -- cgit 1.5.1 From 1cd4b819171f9bbadb00b2e87d1a710ead355f95 Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Thu, 16 Sep 2021 20:49:07 +0200 Subject: Revert ":construction: webhook" This reverts commit f691aa4c5aa47c8a8085c7b01912a1c403ce8732. --- api/assets/schemas.json | 255 +----------------------- api/client_test/index.html | 2 +- api/src/middlewares/Authentication.ts | 4 +- api/src/middlewares/ErrorHandler.ts | 7 +- api/src/routes/discoverable-guilds.ts | 2 +- api/src/routes/guilds/#guild_id/integrations.ts | 10 - api/src/routes/template.ts.disabled | 2 +- api/src/routes/webhooks/#webhook_id/index.ts | 89 --------- api/src/util/route.ts | 8 +- util/src/entities/Webhook.ts | 6 +- util/src/util/Regex.ts | 2 +- 11 files changed, 18 insertions(+), 369 deletions(-) delete mode 100644 api/src/routes/guilds/#guild_id/integrations.ts delete mode 100644 api/src/routes/webhooks/#webhook_id/index.ts (limited to 'util/src') diff --git a/api/assets/schemas.json b/api/assets/schemas.json index 88558cfa..9c34f968 100644 --- a/api/assets/schemas.json +++ b/api/assets/schemas.json @@ -1770,6 +1770,10 @@ } }, "additionalProperties": false, + "required": [ + "avatar", + "name" + ], "definitions": { "ChannelType": { "enum": [ @@ -7442,256 +7446,5 @@ } }, "$schema": "http://json-schema.org/draft-07/schema#" - }, - "WebhookModifySchema": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "avatar": { - "type": "string" - } - }, - "additionalProperties": false, - "definitions": { - "ChannelType": { - "enum": [ - 0, - 1, - 10, - 11, - 12, - 13, - 2, - 3, - 4, - 5, - 6 - ], - "type": "number" - }, - "ChannelPermissionOverwriteType": { - "enum": [ - 0, - 1 - ], - "type": "number" - }, - "Embed": { - "type": "object", - "properties": { - "title": { - "type": "string" - }, - "type": { - "enum": [ - "article", - "gifv", - "image", - "link", - "rich", - "video" - ], - "type": "string" - }, - "description": { - "type": "string" - }, - "url": { - "type": "string" - }, - "timestamp": { - "type": "string", - "format": "date-time" - }, - "color": { - "type": "integer" - }, - "footer": { - "type": "object", - "properties": { - "text": { - "type": "string" - }, - "icon_url": { - "type": "string" - }, - "proxy_icon_url": { - "type": "string" - } - }, - "additionalProperties": false, - "required": [ - "text" - ] - }, - "image": { - "$ref": "#/definitions/EmbedImage" - }, - "thumbnail": { - "$ref": "#/definitions/EmbedImage" - }, - "video": { - "$ref": "#/definitions/EmbedImage" - }, - "provider": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "url": { - "type": "string" - } - }, - "additionalProperties": false - }, - "author": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "url": { - "type": "string" - }, - "icon_url": { - "type": "string" - }, - "proxy_icon_url": { - "type": "string" - } - }, - "additionalProperties": false - }, - "fields": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "value": { - "type": "string" - }, - "inline": { - "type": "boolean" - } - }, - "additionalProperties": false, - "required": [ - "name", - "value" - ] - } - } - }, - "additionalProperties": false - }, - "EmbedImage": { - "type": "object", - "properties": { - "url": { - "type": "string" - }, - "proxy_url": { - "type": "string" - }, - "height": { - "type": "integer" - }, - "width": { - "type": "integer" - } - }, - "additionalProperties": false - }, - "ChannelModifySchema": { - "type": "object", - "properties": { - "name": { - "maxLength": 100, - "type": "string" - }, - "type": { - "$ref": "#/definitions/ChannelType" - }, - "topic": { - "type": "string" - }, - "bitrate": { - "type": "integer" - }, - "user_limit": { - "type": "integer" - }, - "rate_limit_per_user": { - "type": "integer" - }, - "position": { - "type": "integer" - }, - "permission_overwrites": { - "type": "array", - "items": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "type": { - "$ref": "#/definitions/ChannelPermissionOverwriteType" - }, - "allow": { - "type": "bigint" - }, - "deny": { - "type": "bigint" - } - }, - "additionalProperties": false, - "required": [ - "allow", - "deny", - "id", - "type" - ] - } - }, - "parent_id": { - "type": "string" - }, - "id": { - "type": "string" - }, - "nsfw": { - "type": "boolean" - }, - "rtc_region": { - "type": "string" - }, - "default_auto_archive_duration": { - "type": "integer" - } - }, - "additionalProperties": false, - "required": [ - "name", - "type" - ] - }, - "RelationshipType": { - "enum": [ - 1, - 2, - 3, - 4 - ], - "type": "number" - } - }, - "$schema": "http://json-schema.org/draft-07/schema#" } } \ No newline at end of file diff --git a/api/client_test/index.html b/api/client_test/index.html index 335b477c..ac66df06 100644 --- a/api/client_test/index.html +++ b/api/client_test/index.html @@ -11,7 +11,7 @@ window.__OVERLAY__ = /overlay/.test(location.pathname); window.__BILLING_STANDALONE__ = /^\/billing/.test(location.pathname); window.GLOBAL_ENV = { - API_ENDPOINT: `//${location.host}/api`, + API_ENDPOINT: "/api", API_VERSION: 9, GATEWAY_ENDPOINT: `${location.protocol === "https:" ? "wss://" : "ws://"}${location.hostname}:3002`, WEBAPP_ENDPOINT: "", diff --git a/api/src/middlewares/Authentication.ts b/api/src/middlewares/Authentication.ts index 32307f42..a300c786 100644 --- a/api/src/middlewares/Authentication.ts +++ b/api/src/middlewares/Authentication.ts @@ -5,11 +5,11 @@ import { checkToken, Config } from "@fosscord/util"; export const NO_AUTHORIZATION_ROUTES = [ "/auth/login", "/auth/register", + "/webhooks/", "/ping", "/gateway", "/experiments", - /\/guilds\/\d+\/widget\.(json|png)/, - /\/webhooks\/\d+\/\w+/ // only exclude webhook calls with webhook token + /\/guilds\/\d+\/widget\.(json|png)/ ]; export const API_PREFIX = /^\/api(\/v\d+)?/; diff --git a/api/src/middlewares/ErrorHandler.ts b/api/src/middlewares/ErrorHandler.ts index 338da8d5..d288f3fb 100644 --- a/api/src/middlewares/ErrorHandler.ts +++ b/api/src/middlewares/ErrorHandler.ts @@ -1,10 +1,9 @@ import { NextFunction, Request, Response } from "express"; import { HTTPError } from "lambert-server"; +import { EntityNotFoundError } from "typeorm"; import { FieldError } from "@fosscord/api"; import { ApiError } from "@fosscord/util"; -const EntityNotFoundErrorRegex = /"(\w+)"/; - export function ErrorHandler(error: Error, req: Request, res: Response, next: NextFunction) { if (!error) return next(); @@ -19,8 +18,8 @@ export function ErrorHandler(error: Error, req: Request, res: Response, next: Ne code = error.code; message = error.message; httpcode = error.httpStatus; - } else if (error.name === "EntityNotFoundError") { - message = `${error.message.match(EntityNotFoundErrorRegex)?.[1] || "Item"} could not be found`; + } else if (error instanceof EntityNotFoundError) { + message = `${(error as any).stringifyTarget || "Item"} could not be found`; code = 404; } else if (error instanceof FieldError) { code = Number(error.code); diff --git a/api/src/routes/discoverable-guilds.ts b/api/src/routes/discoverable-guilds.ts index 71789123..f667eb2a 100644 --- a/api/src/routes/discoverable-guilds.ts +++ b/api/src/routes/discoverable-guilds.ts @@ -10,7 +10,7 @@ router.get("/", route({}), async (req: Request, res: Response) => { // ! this only works using SQL querys // TODO: implement this with default typeorm query // const guilds = await Guild.find({ where: { features: "DISCOVERABLE" } }); //, take: Math.abs(Number(limit)) }); - const guilds = await Guild.find({ where: `"features" LIKE 'COMMUNITY'`, take: Math.abs(Number(limit) || 50) }); + const guilds = await Guild.find({ where: `"features" LIKE 'COMMUNITY'`, take: Math.abs(Number(limit)) }); res.send({ guilds: guilds }); }); diff --git a/api/src/routes/guilds/#guild_id/integrations.ts b/api/src/routes/guilds/#guild_id/integrations.ts deleted file mode 100644 index f6b8e99d..00000000 --- a/api/src/routes/guilds/#guild_id/integrations.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { route } from "@fosscord/api"; -import { Router, Request, Response } from "express"; -const router = Router(); - -router.get("/", route({ permission: "MANAGE_GUILD" }), async (req: Request, res: Response) => { - // TODO: integrations (followed channels, youtube, twitch) - res.send([]); -}); - -export default router; diff --git a/api/src/routes/template.ts.disabled b/api/src/routes/template.ts.disabled index 524e981b..ad785f10 100644 --- a/api/src/routes/template.ts.disabled +++ b/api/src/routes/template.ts.disabled @@ -4,7 +4,7 @@ import { Router, Request, Response } from "express"; const router = Router(); router.get("/", async (req: Request, res: Response) => { - res.json({}); + res.send({}); }); export default router; diff --git a/api/src/routes/webhooks/#webhook_id/index.ts b/api/src/routes/webhooks/#webhook_id/index.ts deleted file mode 100644 index e9b40ebf..00000000 --- a/api/src/routes/webhooks/#webhook_id/index.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { Channel, Config, emitEvent, JWTOptions, Webhook, WebhooksUpdateEvent } from "@fosscord/util"; -import { route, Authentication, handleFile } from "@fosscord/api"; -import { Router, Request, Response, NextFunction } from "express"; -import jwt from "jsonwebtoken"; -import { HTTPError } from "lambert-server"; -const router = Router(); - -export interface WebhookModifySchema { - name?: string; - avatar?: string; - // channel_id?: string; // TODO -} - -function validateWebhookToken(req: Request, res: Response, next: NextFunction) { - const { jwtSecret } = Config.get().security; - - jwt.verify(req.params.token, jwtSecret, JWTOptions, async (err, decoded: any) => { - if (err) return next(new HTTPError("Invalid Token", 401)); - next(); - }); -} - -router.get("/", route({}), async (req: Request, res: Response) => { - res.json(await Webhook.findOneOrFail({ id: req.params.webhook_id })); -}); - -router.get("/:token", route({}), validateWebhookToken, async (req: Request, res: Response) => { - res.json(await Webhook.findOneOrFail({ id: req.params.webhook_id })); -}); - -router.patch("/", route({ body: "WebhookModifySchema", permission: "MANAGE_WEBHOOKS" }), (req: Request, res: Response) => { - return updateWebhook(req, res); -}); - -router.patch("/:token", route({ body: "WebhookModifySchema" }), validateWebhookToken, (req: Request, res: Response) => { - return updateWebhook(req, res); -}); - -async function updateWebhook(req: Request, res: Response) { - const webhook = await Webhook.findOneOrFail({ id: req.params.webhook_id }); - if (req.body.channel_id) await Channel.findOneOrFail({ id: req.body.channel_id, guild_id: webhook.guild_id }); - - webhook.assign({ - ...req.body, - avatar: await handleFile(`/icons/${req.params.webhook_id}`, req.body.avatar) - }); - - await Promise.all([ - emitEvent({ - event: "WEBHOOKS_UPDATE", - channel_id: webhook.channel_id, - data: { - channel_id: webhook.channel_id, - guild_id: webhook.guild_id - } - } as WebhooksUpdateEvent), - webhook.save() - ]); - - res.json(webhook); -} - -router.delete("/", route({ permission: "MANAGE_WEBHOOKS" }), async (req: Request, res: Response) => { - return deleteWebhook(req, res); -}); - -router.delete("/:token", route({}), validateWebhookToken, (req: Request, res: Response) => { - return deleteWebhook(req, res); -}); - -async function deleteWebhook(req: Request, res: Response) { - const webhook = await Webhook.findOneOrFail({ id: req.params.webhook_id }); - - await Promise.all([ - emitEvent({ - event: "WEBHOOKS_UPDATE", - channel_id: webhook.channel_id, - data: { - channel_id: webhook.channel_id, - guild_id: webhook.guild_id - } - } as WebhooksUpdateEvent), - webhook.remove() - ]); - - res.sendStatus(204); -} - -export default router; diff --git a/api/src/util/route.ts b/api/src/util/route.ts index 1e2beb5d..6cd8f622 100644 --- a/api/src/util/route.ts +++ b/api/src/util/route.ts @@ -1,4 +1,4 @@ -import { DiscordApiErrors, Event, EventData, getPermission, PermissionResolvable, Permissions, Webhook } from "@fosscord/util"; +import { DiscordApiErrors, Event, EventData, getPermission, PermissionResolvable, Permissions } from "@fosscord/util"; import { NextFunction, Request, Response } from "express"; import fs from "fs"; import path from "path"; @@ -54,13 +54,9 @@ export function route(opts: RouteOptions) { return async (req: Request, res: Response, next: NextFunction) => { if (opts.permission) { const required = new Permissions(opts.permission); - if (req.params.webhook_id) { - const webhook = await Webhook.findOneOrFail({ id: req.params.webhook_id }); - req.params.channel_id = webhook.channel_id; - req.params.guild_id = webhook.guild_id; - } const permission = await getPermission(req.user_id, req.params.guild_id, req.params.channel_id); + // bitfield comparison: check if user lacks certain permission if (!permission.has(required)) { throw DiscordApiErrors.MISSING_PERMISSIONS.withParams(opts.permission as string); } diff --git a/util/src/entities/Webhook.ts b/util/src/entities/Webhook.ts index d0d98804..12ba0d08 100644 --- a/util/src/entities/Webhook.ts +++ b/util/src/entities/Webhook.ts @@ -18,13 +18,13 @@ export class Webhook extends BaseClass { @Column({ type: "simple-enum", enum: WebhookType }) type: WebhookType; - @Column() - name: string; + @Column({ nullable: true }) + name?: string; @Column({ nullable: true }) avatar?: string; - @Column({ nullable: true, select: false }) + @Column({ nullable: true }) token?: string; @Column({ nullable: true }) diff --git a/util/src/util/Regex.ts b/util/src/util/Regex.ts index b5d23b7f..83fc9fe8 100644 --- a/util/src/util/Regex.ts +++ b/util/src/util/Regex.ts @@ -1,5 +1,5 @@ export const DOUBLE_WHITE_SPACE = /\s\s+/g; -export const SPECIAL_CHAR = /[@#\r\n\t\f\v]/gu; +export const SPECIAL_CHAR = /[@#`:\r\n\t\f\v\p{C}]/gu; export const CHANNEL_MENTION = /<#(\d+)>/g; export const USER_MENTION = /<@!?(\d+)>/g; export const ROLE_MENTION = /<@&(\d+)>/g; -- cgit 1.5.1 From 92cbfa75955fe309ddbb89092a534a858e5e7450 Mon Sep 17 00:00:00 2001 From: AlTech98 Date: Thu, 16 Sep 2021 21:30:05 +0200 Subject: Gateway permission check fix --- gateway/src/listener/listener.ts | 11 ++++++++--- util/src/util/Event.ts | 1 + util/src/util/Permissions.ts | 1 + 3 files changed, 10 insertions(+), 3 deletions(-) (limited to 'util/src') diff --git a/gateway/src/listener/listener.ts b/gateway/src/listener/listener.ts index ef3dd890..16803639 100644 --- a/gateway/src/listener/listener.ts +++ b/gateway/src/listener/listener.ts @@ -116,7 +116,7 @@ async function consume(this: WebSocket, opts: EventOpts) { .has("VIEW_CHANNEL") ) return; - // TODO: check if user has permission to channel + break; case "GUILD_CREATE": this.events[id] = await listenEvent(id, consumer, listenOpts); break; @@ -193,11 +193,16 @@ async function consume(this: WebSocket, opts: EventOpts) { break; } - Send(this, { + let aa = { op: OPCODES.Dispatch, t: event, d: data, s: this.sequence++, - }); + } + + //TODO remove before PR merge + console.log(aa) + + Send(this, aa); opts.acknowledge?.(); } diff --git a/util/src/util/Event.ts b/util/src/util/Event.ts index 765e5fc7..ae296df9 100644 --- a/util/src/util/Event.ts +++ b/util/src/util/Event.ts @@ -5,6 +5,7 @@ import { EVENT, Event } from "../interfaces"; const events = new EventEmitter(); export async function emitEvent(payload: Omit) { + console.log(payload) //TODO remove before merge const id = (payload.channel_id || payload.user_id || payload.guild_id) as string; if (!id) return console.error("event doesn't contain any id", payload); diff --git a/util/src/util/Permissions.ts b/util/src/util/Permissions.ts index 9d87253a..44852f1e 100644 --- a/util/src/util/Permissions.ts +++ b/util/src/util/Permissions.ts @@ -92,6 +92,7 @@ export class Permissions extends BitField { } overwriteChannel(overwrites: ChannelPermissionOverwrite[]) { + if (!overwrites) return this if (!this.cache) throw new Error("permission chache not available"); overwrites = overwrites.filter((x) => { if (x.type === 0 && this.cache.roles?.some((r) => r.id === x.id)) return true; -- cgit 1.5.1 From 4f87fd742f25a25782afb20131200bcff81b50f7 Mon Sep 17 00:00:00 2001 From: AlTech98 Date: Thu, 16 Sep 2021 21:33:36 +0200 Subject: Implemented DMs and group DMs --- api/src/routes/channels/#channel_id/index.ts | 28 +++++-- .../#channel_id/messages/#message_id/ack.ts | 2 +- .../routes/channels/#channel_id/messages/index.ts | 46 ++++++++--- api/src/routes/channels/#channel_id/recipients.ts | 56 +++++++++++++- api/src/routes/users/#id/profile.ts | 1 + api/src/routes/users/@me/channels.ts | 43 ++++------- api/src/routes/users/@me/relationships.ts | 19 ++++- gateway/src/opcodes/Identify.ts | 38 +++++----- gateway/src/opcodes/index.ts | 1 + util/src/dtos/DmChannelDTO.ts | 35 +++++++++ util/src/dtos/UserDTO.ts | 17 +++++ util/src/dtos/index.ts | 2 + util/src/entities/Channel.ts | 15 ++-- util/src/entities/Recipient.ts | 3 + util/src/entities/User.ts | 2 +- util/src/index.ts | 2 + util/src/interfaces/Event.ts | 22 ++++++ util/src/services/ChannelService.ts | 88 ++++++++++++++++++++++ util/src/services/index.ts | 1 + 19 files changed, 342 insertions(+), 79 deletions(-) create mode 100644 util/src/dtos/DmChannelDTO.ts create mode 100644 util/src/dtos/UserDTO.ts create mode 100644 util/src/dtos/index.ts create mode 100644 util/src/services/ChannelService.ts create mode 100644 util/src/services/index.ts (limited to 'util/src') diff --git a/api/src/routes/channels/#channel_id/index.ts b/api/src/routes/channels/#channel_id/index.ts index 02ac9884..e836622b 100644 --- a/api/src/routes/channels/#channel_id/index.ts +++ b/api/src/routes/channels/#channel_id/index.ts @@ -1,6 +1,7 @@ -import { ChannelDeleteEvent, Channel, ChannelUpdateEvent, emitEvent, ChannelType, ChannelPermissionOverwriteType } from "@fosscord/util"; -import { Router, Response, Request } from "express"; +import { Channel, ChannelDeleteEvent, ChannelPermissionOverwriteType, ChannelService, ChannelType, ChannelUpdateEvent, emitEvent, Recipient } from "@fosscord/util"; +import { Request, Response, Router } from "express"; import { route } from "@fosscord/api"; + const router: Router = Router(); // TODO: delete channel // TODO: Get channel @@ -16,14 +17,27 @@ router.get("/", route({ permission: "VIEW_CHANNEL" }), async (req: Request, res: router.delete("/", route({ permission: "MANAGE_CHANNELS" }), async (req: Request, res: Response) => { const { channel_id } = req.params; - const channel = await Channel.findOneOrFail({ id: channel_id }); + const channel = await Channel.findOneOrFail({ where: { id: channel_id }, relations: ["recipients"] }); - // TODO: Dm channel "close" not delete - const data = channel; + if (channel.type === ChannelType.DM) { + const recipient = await Recipient.findOneOrFail({ where: { channel_id: channel_id, user_id: req.user_id } }) + recipient.closed = true + await Promise.all([ + recipient.save(), + emitEvent({ event: "CHANNEL_DELETE", data: channel, user_id: req.user_id } as ChannelDeleteEvent) + ]); - await Promise.all([emitEvent({ event: "CHANNEL_DELETE", data, channel_id } as ChannelDeleteEvent), Channel.delete({ id: channel_id })]); + } else if (channel.type === ChannelType.GROUP_DM) { + await ChannelService.removeRecipientFromChannel(channel, req.user_id) + } else { + //TODO messages in this channel should be deleted before deleting the channel + await Promise.all([ + Channel.delete({ id: channel_id }), + emitEvent({ event: "CHANNEL_DELETE", data: channel, channel_id } as ChannelDeleteEvent) + ]); + } - res.send(data); + res.send(channel); }); export interface ChannelModifySchema { diff --git a/api/src/routes/channels/#channel_id/messages/#message_id/ack.ts b/api/src/routes/channels/#channel_id/messages/#message_id/ack.ts index 97d1d19e..786e4581 100644 --- a/api/src/routes/channels/#channel_id/messages/#message_id/ack.ts +++ b/api/src/routes/channels/#channel_id/messages/#message_id/ack.ts @@ -26,7 +26,7 @@ router.post("/", route({ body: "MessageAcknowledgeSchema" }), async (req: Reques data: { channel_id, message_id, - version: 496 + version: 3763 } } as MessageAckEvent); diff --git a/api/src/routes/channels/#channel_id/messages/index.ts b/api/src/routes/channels/#channel_id/messages/index.ts index ec93649e..bb610a6a 100644 --- a/api/src/routes/channels/#channel_id/messages/index.ts +++ b/api/src/routes/channels/#channel_id/messages/index.ts @@ -1,9 +1,8 @@ import { Router, Response, Request } from "express"; -import { Attachment, Channel, ChannelType, Embed, getPermission, Message } from "@fosscord/util"; +import { Attachment, Channel, ChannelType, DmChannelDTO, Embed, emitEvent, getPermission, Message, MessageCreateEvent } from "@fosscord/util"; import { HTTPError } from "lambert-server"; -import { route } from "@fosscord/api"; +import { handleMessage, postHandleMessage, route } from "@fosscord/api"; import multer from "multer"; -import { sendMessage } from "@fosscord/api"; import { uploadFile } from "@fosscord/api"; import { FindManyOptions, LessThan, MoreThan } from "typeorm"; @@ -62,9 +61,9 @@ router.get("/", async (req: Request, res: Response) => { if (!channel) throw new HTTPError("Channel not found", 404); isTextChannel(channel.type); - const around = `${req.query.around}`; - const before = `${req.query.before}`; - const after = `${req.query.after}`; + const around = req.query.around ? `${req.query.around}` : undefined; + const before = req.query.before ? `${req.query.before}` : undefined; + const after = req.query.after ? `${req.query.after}` : undefined; const limit = Number(req.query.limit) || 50; if (limit < 1 || limit > 100) throw new HTTPError("limit must be between 1 and 100"); @@ -151,10 +150,12 @@ router.post( return res.status(400).json(error); } } + //TODO querying the DB at every message post should be avoided, caching maybe? + const channel = await Channel.findOneOrFail({ where: { id: channel_id }, relations: ["recipients", "recipients.user"] }) const embeds = []; if (body.embed) embeds.push(body.embed); - const data = await sendMessage({ + let message = await handleMessage({ ...body, type: 0, pinned: false, @@ -162,9 +163,36 @@ router.post( embeds, channel_id, attachments, - edited_timestamp: undefined + edited_timestamp: undefined, + timestamp: new Date() }); - return res.json(data); + message = await message.save() + + await channel.assign({ last_message_id: message.id }).save() + + if (channel.isDm()) { + const channel_dto = await DmChannelDTO.from(channel) + + for (let recipient of channel.recipients!) { + if (recipient.closed) { + await emitEvent({ + event: "CHANNEL_CREATE", + data: channel_dto.excludedRecipients([recipient.user_id]), + user_id: recipient.user_id + }) + } + } + + await Promise.all(channel.recipients!.map(async r => { + r.closed = false; + return await r.save() + })); + } + + await emitEvent({ event: "MESSAGE_CREATE", channel_id: channel_id, data: message } as MessageCreateEvent) + postHandleMessage(message).catch((e) => {}); // no await as it shouldnt block the message send function and silently catch error + + return res.json(message); } ); diff --git a/api/src/routes/channels/#channel_id/recipients.ts b/api/src/routes/channels/#channel_id/recipients.ts index ea6bc563..d88b38f3 100644 --- a/api/src/routes/channels/#channel_id/recipients.ts +++ b/api/src/routes/channels/#channel_id/recipients.ts @@ -1,5 +1,57 @@ -import { Router, Response, Request } from "express"; +import { Request, Response, Router } from "express"; +import { Channel, ChannelRecipientAddEvent, ChannelService, ChannelType, DiscordApiErrors, DmChannelDTO, emitEvent, PublicUserProjection, Recipient, User } from "@fosscord/util"; + const router: Router = Router(); -// TODO: + +router.put("/:user_id", async (req: Request, res: Response) => { + const { channel_id, user_id } = req.params; + const channel = await Channel.findOneOrFail({ where: { id: channel_id }, relations: ["recipients"] }); + + if (channel.type !== ChannelType.GROUP_DM) { + const recipients = [ + ...channel.recipients!.map(r => r.user_id), + user_id + ].unique() + + const new_channel = await ChannelService.createDMChannel(recipients, req.user_id) + return res.status(201).json(new_channel); + } else { + if (channel.recipients!.map(r => r.user_id).includes(user_id)) { + throw DiscordApiErrors.INVALID_RECIPIENT //TODO is this the right error? + } + + channel.recipients!.push(new Recipient({ channel_id: channel_id, user_id: user_id })); + await channel.save() + + await emitEvent({ + event: "CHANNEL_CREATE", + data: await DmChannelDTO.from(channel, [user_id]), + user_id: user_id + }); + + await emitEvent({ + event: "CHANNEL_RECIPIENT_ADD", data: { + channel_id: channel_id, + user: await User.findOneOrFail({ where: { id: user_id }, select: PublicUserProjection }) + }, channel_id: channel_id + } as ChannelRecipientAddEvent); + return res.sendStatus(204); + } +}); + +router.delete("/:user_id", async (req: Request, res: Response) => { + const { channel_id, user_id } = req.params; + const channel = await Channel.findOneOrFail({ where: { id: channel_id }, relations: ["recipients"] }); + if (!(channel.type === ChannelType.GROUP_DM && (channel.owner_id === req.user_id || user_id === req.user_id))) + throw DiscordApiErrors.MISSING_PERMISSIONS + + if (!channel.recipients!.map(r => r.user_id).includes(user_id)) { + throw DiscordApiErrors.INVALID_RECIPIENT //TODO is this the right error? + } + + await ChannelService.removeRecipientFromChannel(channel, user_id) + + return res.sendStatus(204); +}); export default router; diff --git a/api/src/routes/users/#id/profile.ts b/api/src/routes/users/#id/profile.ts index d60c4f86..06d5c38c 100644 --- a/api/src/routes/users/#id/profile.ts +++ b/api/src/routes/users/#id/profile.ts @@ -19,6 +19,7 @@ router.get("/", route({ response: { body: "UserProfileResponse" } }), async (req connected_accounts: user.connected_accounts, premium_guild_since: null, // TODO premium_since: null, // TODO + mutual_guilds: [], // TODO {id: "", nick: null} when ?with_mutual_guilds=true user: { username: user.username, discriminator: user.discriminator, diff --git a/api/src/routes/users/@me/channels.ts b/api/src/routes/users/@me/channels.ts index da33f204..bd7af18c 100644 --- a/api/src/routes/users/@me/channels.ts +++ b/api/src/routes/users/@me/channels.ts @@ -1,15 +1,21 @@ -import { Router, Request, Response } from "express"; -import { Channel, ChannelCreateEvent, ChannelType, Snowflake, trimSpecial, User, emitEvent, Recipient } from "@fosscord/util"; -import { HTTPError } from "lambert-server"; +import { Request, Response, Router } from "express"; +import { PublicUserProjection, Recipient, User, ChannelService } from "@fosscord/util"; import { route } from "@fosscord/api"; -import { In } from "typeorm"; const router: Router = Router(); router.get("/", route({}), async (req: Request, res: Response) => { - const recipients = await Recipient.find({ where: { user_id: req.user_id }, relations: ["channel"] }); + const recipients = await Recipient.find({ where: { user_id: req.user_id }, relations: ["channel", "user"] }); - res.json(recipients.map((x) => x.channel)); + //TODO check if this is right + const aa = await Promise.all(recipients.map(async (x) => { + return { + ...(x.channel), + recipients: await User.findOneOrFail({ where: { id: x.user_id }, select: PublicUserProjection }), + } + })) + + res.json(aa); }); export interface DmChannelCreateSchema { @@ -19,30 +25,7 @@ export interface DmChannelCreateSchema { router.post("/", route({ body: "DmChannelCreateSchema" }), async (req: Request, res: Response) => { const body = req.body as DmChannelCreateSchema; - - body.recipients = body.recipients.filter((x) => x !== req.user_id).unique(); - - const recipients = await User.find({ where: body.recipients.map((x) => ({ id: x })) }); - - if (recipients.length !== body.recipients.length) { - throw new HTTPError("Recipient/s not found"); - } - - const type = body.recipients.length === 1 ? ChannelType.DM : ChannelType.GROUP_DM; - const name = trimSpecial(body.name); - - const channel = await new Channel({ - name, - type, - // owner_id only for group dm channels - created_at: new Date(), - last_message_id: null, - recipients: [...body.recipients.map((x) => new Recipient({ user_id: x })), new Recipient({ user_id: req.user_id })] - }).save(); - - await emitEvent({ event: "CHANNEL_CREATE", data: channel, user_id: req.user_id } as ChannelCreateEvent); - - res.json(channel); + res.json(await ChannelService.createDMChannel(body.recipients, req.user_id, body.name)); }); export default router; diff --git a/api/src/routes/users/@me/relationships.ts b/api/src/routes/users/@me/relationships.ts index 58d2e481..1d72f11a 100644 --- a/api/src/routes/users/@me/relationships.ts +++ b/api/src/routes/users/@me/relationships.ts @@ -18,9 +18,19 @@ const router = Router(); const userProjection: (keyof User)[] = ["relationships", ...PublicUserProjection]; router.get("/", route({}), async (req: Request, res: Response) => { - const user = await User.findOneOrFail({ where: { id: req.user_id }, relations: ["relationships"] }); + const user = await User.findOneOrFail({ where: { id: req.user_id }, relations: ["relationships", "relationships.to"] }); + + //TODO DTO + const related_users = user.relationships.map(r => { + return { + id: r.to.id, + type: r.type, + nickname: null, + user: r.to.toPublicUser(), + } + }) - return res.json(user.relationships); + return res.json(related_users); }); export interface RelationshipPutSchema { @@ -48,7 +58,10 @@ router.post("/", route({ body: "RelationshipPostSchema" }), async (req: Request, await User.findOneOrFail({ relations: ["relationships", "relationships.to"], select: userProjection, - where: req.body as { discriminator: string; username: string } + where: { + discriminator: String(req.body.discriminator,).padStart(4, '0'), //Discord send the discriminator as integer, we need to add leading zeroes + username: req.body.username + } }), req.body.type ); diff --git a/gateway/src/opcodes/Identify.ts b/gateway/src/opcodes/Identify.ts index f6a4478f..d91cd7f2 100644 --- a/gateway/src/opcodes/Identify.ts +++ b/gateway/src/opcodes/Identify.ts @@ -88,20 +88,17 @@ export async function onIdentify(this: WebSocket, data: Payload) { const user_guild_settings_entries = members.map((x) => x.settings); const recipients = await Recipient.find({ - where: { user_id: this.user_id }, + where: { user_id: this.user_id, closed: false }, relations: ["channel", "channel.recipients", "channel.recipients.user"], // TODO: public user selection }); const channels = recipients.map((x) => { // @ts-ignore x.channel.recipients = x.channel.recipients?.map((x) => x.user); - // @ts-ignore - users = users.concat(x.channel.recipients); - if (x.channel.type === ChannelType.DM) { - x.channel.recipients = [ - // @ts-ignore - x.channel.recipients.find((x) => x.id !== this.user_id), - ]; + //TODO is this needed? check if users in group dm that are not friends are sent in the READY event + //users = users.concat(x.channel.recipients); + if (x.channel.isDm()) { + x.channel.recipients = x.channel.recipients!.filter((x) => x.id !== this.user_id); } return x.channel; }); @@ -111,16 +108,19 @@ export async function onIdentify(this: WebSocket, data: Payload) { }); if (!user) return this.close(CLOSECODES.Authentication_failed); - const public_user = { - username: user.username, - discriminator: user.discriminator, - id: user.id, - public_flags: user.public_flags, - avatar: user.avatar, - bot: user.bot, - bio: user.bio, - }; - users.push(public_user); + for (let relation of user.relationships) { + const related_user = relation.to + const public_related_user = { + username: related_user.username, + discriminator: related_user.discriminator, + id: related_user.id, + public_flags: related_user.public_flags, + avatar: related_user.avatar, + bot: related_user.bot, + bio: related_user.bio, + }; + users.push(public_related_user); + } const session_id = genSessionId(); this.session_id = session_id; //Set the session of the WebSocket object @@ -201,7 +201,7 @@ export async function onIdentify(this: WebSocket, data: Payload) { // @ts-ignore experiments: experiments, // TODO guild_join_requests: [], // TODO what is this? - users: users.unique(), // TODO + users: users.unique(), merged_members: merged_members, // shard // TODO: only for bots sharding // application // TODO for applications diff --git a/gateway/src/opcodes/index.ts b/gateway/src/opcodes/index.ts index a6d13bfb..c4069589 100644 --- a/gateway/src/opcodes/index.ts +++ b/gateway/src/opcodes/index.ts @@ -21,5 +21,6 @@ export default { 8: onRequestGuildMembers, // 9: Invalid Session // 10: Hello + // 13: Dm_update 14: onLazyRequest, }; diff --git a/util/src/dtos/DmChannelDTO.ts b/util/src/dtos/DmChannelDTO.ts new file mode 100644 index 00000000..8b7a18fd --- /dev/null +++ b/util/src/dtos/DmChannelDTO.ts @@ -0,0 +1,35 @@ +import { MinimalPublicUserDTO } from "./UserDTO"; +import { Channel, PublicUserProjection, User } from "../entities"; + +export class DmChannelDTO { + icon: string | null; + id: string; + last_message_id: string | null; + name: string | null; + origin_channel_id: string | null; + owner_id?: string; + recipients: MinimalPublicUserDTO[]; + type: number; + + static async from(channel: Channel, excluded_recipients: string[] = [], origin_channel_id?: string) { + const obj = new DmChannelDTO() + obj.icon = channel.icon || null + obj.id = channel.id + obj.last_message_id = channel.last_message_id || null + obj.name = channel.name || null + obj.origin_channel_id = origin_channel_id || null + obj.owner_id = channel.owner_id + obj.type = channel.type + obj.recipients = (await Promise.all(channel.recipients!.filter(r => !excluded_recipients.includes(r.user_id)).map(async r => { + return await User.findOneOrFail({ where: { id: r.user_id }, select: PublicUserProjection }) + }))).map(u => new MinimalPublicUserDTO(u)) + return obj + } + + excludedRecipients(excluded_recipients: string[]): DmChannelDTO { + return { + ...this, + recipients: this.recipients.filter(r => !excluded_recipients.includes(r.id)) + } + } +} \ No newline at end of file diff --git a/util/src/dtos/UserDTO.ts b/util/src/dtos/UserDTO.ts new file mode 100644 index 00000000..f09b5f4e --- /dev/null +++ b/util/src/dtos/UserDTO.ts @@ -0,0 +1,17 @@ +import { User } from "../entities"; + +export class MinimalPublicUserDTO { + avatar?: string | null; + discriminator: string; + id: string; + public_flags: number; + username: string; + + constructor(user: User) { + this.avatar = user.avatar + this.discriminator = user.discriminator + this.id = user.id + this.public_flags = user.public_flags + this.username = user.username + } +} \ No newline at end of file diff --git a/util/src/dtos/index.ts b/util/src/dtos/index.ts new file mode 100644 index 00000000..13702342 --- /dev/null +++ b/util/src/dtos/index.ts @@ -0,0 +1,2 @@ +export * from "./DmChannelDTO"; +export * from "./UserDTO"; \ No newline at end of file diff --git a/util/src/entities/Channel.ts b/util/src/entities/Channel.ts index fc954f63..6eac19ca 100644 --- a/util/src/entities/Channel.ts +++ b/util/src/entities/Channel.ts @@ -1,7 +1,6 @@ -import { Column, Entity, JoinColumn, JoinTable, ManyToMany, ManyToOne, OneToMany, RelationId } from "typeorm"; +import { Column, Entity, JoinColumn, ManyToOne, OneToMany, RelationId } from "typeorm"; import { BaseClass } from "./BaseClass"; import { Guild } from "./Guild"; -import { Message } from "./Message"; import { User } from "./User"; import { HTTPError } from "lambert-server"; import { emitEvent, getPermission, Snowflake } from "../util"; @@ -31,6 +30,9 @@ export class Channel extends BaseClass { @Column({ nullable: true }) name?: string; + @Column({ nullable: true }) + icon?: string; + @Column({ type: "simple-enum", enum: ChannelType }) type: ChannelType; @@ -38,13 +40,8 @@ export class Channel extends BaseClass { recipients?: Recipient[]; @Column({ nullable: true }) - @RelationId((channel: Channel) => channel.last_message) last_message_id: string; - @JoinColumn({ name: "last_message_id" }) - @ManyToOne(() => Message) - last_message?: Message; - @Column({ nullable: true }) @RelationId((channel: Channel) => channel.guild) guild_id?: string; @@ -162,6 +159,10 @@ export class Channel extends BaseClass { return channel; } + + isDm() { + return this.type === ChannelType.DM || this.type === ChannelType.GROUP_DM + } } export interface ChannelPermissionOverwrite { diff --git a/util/src/entities/Recipient.ts b/util/src/entities/Recipient.ts index 2a27b29f..bb280588 100644 --- a/util/src/entities/Recipient.ts +++ b/util/src/entities/Recipient.ts @@ -19,5 +19,8 @@ export class Recipient extends BaseClass { @ManyToOne(() => require("./User").User) user: import("./User").User; + @Column({ default: false }) + closed: boolean; + // TODO: settings/mute/nick/added at/encryption keys/read_state } diff --git a/util/src/entities/User.ts b/util/src/entities/User.ts index 736704f8..cef88777 100644 --- a/util/src/entities/User.ts +++ b/util/src/entities/User.ts @@ -124,7 +124,7 @@ export class User extends BaseClass { flags: string; // UserFlags @Column() - public_flags: string; + public_flags: number; @JoinColumn({ name: "relationship_ids" }) @OneToMany(() => Relationship, (relationship: Relationship) => relationship.from) diff --git a/util/src/index.ts b/util/src/index.ts index f3bd9e9b..538bfdd1 100644 --- a/util/src/index.ts +++ b/util/src/index.ts @@ -4,6 +4,8 @@ import "reflect-metadata"; export * from "./util/index"; export * from "./interfaces/index"; export * from "./entities/index"; +export * from "./services/index"; +export * from "./dtos/index"; // import Config from "../util/Config"; // import db, { MongooseCache, toObject } from "./util/Database"; diff --git a/util/src/interfaces/Event.ts b/util/src/interfaces/Event.ts index aff50300..03099bbb 100644 --- a/util/src/interfaces/Event.ts +++ b/util/src/interfaces/Event.ts @@ -127,6 +127,22 @@ export interface ChannelPinsUpdateEvent extends Event { }; } +export interface ChannelRecipientAddEvent extends Event { + event: "CHANNEL_RECIPIENT_ADD"; + data: { + channel_id: string; + user: User; + }; +} + +export interface ChannelRecipientRemoveEvent extends Event { + event: "CHANNEL_RECIPIENT_REMOVE"; + data: { + channel_id: string; + user: User; + }; +} + export interface GuildCreateEvent extends Event { event: "GUILD_CREATE"; data: Guild & { @@ -436,6 +452,8 @@ export type EventData = | ChannelUpdateEvent | ChannelDeleteEvent | ChannelPinsUpdateEvent + | ChannelRecipientAddEvent + | ChannelRecipientRemoveEvent | GuildCreateEvent | GuildUpdateEvent | GuildDeleteEvent @@ -482,6 +500,8 @@ export enum EVENTEnum { ChannelUpdate = "CHANNEL_UPDATE", ChannelDelete = "CHANNEL_DELETE", ChannelPinsUpdate = "CHANNEL_PINS_UPDATE", + ChannelRecipientAdd = "CHANNEL_RECIPIENT_ADD", + ChannelRecipientRemove = "CHANNEL_RECIPIENT_REMOVE", GuildCreate = "GUILD_CREATE", GuildUpdate = "GUILD_UPDATE", GuildDelete = "GUILD_DELETE", @@ -525,6 +545,8 @@ export type EVENT = | "CHANNEL_UPDATE" | "CHANNEL_DELETE" | "CHANNEL_PINS_UPDATE" + | "CHANNEL_RECIPIENT_ADD" + | "CHANNEL_RECIPIENT_REMOVE" | "GUILD_CREATE" | "GUILD_UPDATE" | "GUILD_DELETE" diff --git a/util/src/services/ChannelService.ts b/util/src/services/ChannelService.ts new file mode 100644 index 00000000..7cded10f --- /dev/null +++ b/util/src/services/ChannelService.ts @@ -0,0 +1,88 @@ +import { Channel, ChannelType, PublicUserProjection, Recipient, User } from "../entities"; +import { HTTPError } from "lambert-server"; +import { emitEvent, trimSpecial } from "../util"; +import { DmChannelDTO } from "../dtos"; +import { ChannelRecipientRemoveEvent } from "../interfaces"; + +export function checker(arr: any[], target: any[]) { + return target.every(v => arr.includes(v)); +} + +export class ChannelService { + public static async createDMChannel(recipients: string[], creator_user_id: string, name?: string) { + recipients = recipients.unique().filter((x) => x !== creator_user_id); + const otherRecipientsUsers = await User.find({ where: recipients.map((x) => ({ id: x })) }); + + if (otherRecipientsUsers.length !== recipients.length) { + throw new HTTPError("Recipient/s not found"); + } + + const type = recipients.length === 1 ? ChannelType.DM : ChannelType.GROUP_DM; + + let channel = null; + + const channelRecipients = [...recipients, creator_user_id] + + const userRecipients = await Recipient.find({ where: { user_id: creator_user_id }, relations: ["channel", "channel.recipients"] }) + + for (let ur of userRecipients) { + let re = ur.channel.recipients!.map(r => r.user_id) + if (re.length === channelRecipients.length) { + if (checker(re, channelRecipients)) { + if (channel == null) { + channel = ur.channel + await ur.assign({ closed: false }).save() + } + } + } + } + + if (channel == null) { + name = trimSpecial(name); + + channel = await new Channel({ + name, + type, + owner_id: (type === ChannelType.DM ? undefined : creator_user_id), + created_at: new Date(), + last_message_id: null, + recipients: channelRecipients.map((x) => new Recipient({ user_id: x, closed: !(type === ChannelType.GROUP_DM || x === creator_user_id) })), + }).save(); + } + + + const channel_dto = await DmChannelDTO.from(channel) + + if (type === ChannelType.GROUP_DM) { + + for (let recipient of channel.recipients!) { + await emitEvent({ + event: "CHANNEL_CREATE", + data: channel_dto.excludedRecipients([recipient.user_id]), + user_id: recipient.user_id + }) + } + } else { + await emitEvent({ event: "CHANNEL_CREATE", data: channel_dto, user_id: creator_user_id }); + } + + return channel_dto.excludedRecipients([creator_user_id]) + } + + public static async removeRecipientFromChannel(channel: Channel, user_id: string) { + await Recipient.delete({ channel_id: channel.id, user_id: user_id }) + + await emitEvent({ + event: "CHANNEL_DELETE", + data: await DmChannelDTO.from(channel, [user_id]), + user_id: user_id + }); + + await emitEvent({ + event: "CHANNEL_RECIPIENT_REMOVE", data: { + channel_id: channel.id, + user: await User.findOneOrFail({ where: { id: user_id }, select: PublicUserProjection }) + }, channel_id: channel.id + } as ChannelRecipientRemoveEvent); + } +} \ No newline at end of file diff --git a/util/src/services/index.ts b/util/src/services/index.ts new file mode 100644 index 00000000..c012a208 --- /dev/null +++ b/util/src/services/index.ts @@ -0,0 +1 @@ +export * from "./ChannelService"; -- cgit 1.5.1 From f4db45ad9d84af24f9c0859a1e2bee05a1f72546 Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Fri, 17 Sep 2021 10:57:24 +0200 Subject: Update ChannelService.ts --- util/src/services/ChannelService.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'util/src') diff --git a/util/src/services/ChannelService.ts b/util/src/services/ChannelService.ts index 7cded10f..319475b6 100644 --- a/util/src/services/ChannelService.ts +++ b/util/src/services/ChannelService.ts @@ -13,6 +13,7 @@ export class ChannelService { recipients = recipients.unique().filter((x) => x !== creator_user_id); const otherRecipientsUsers = await User.find({ where: recipients.map((x) => ({ id: x })) }); + // TODO: check config for max number of recipients if (otherRecipientsUsers.length !== recipients.length) { throw new HTTPError("Recipient/s not found"); } @@ -85,4 +86,4 @@ export class ChannelService { }, channel_id: channel.id } as ChannelRecipientRemoveEvent); } -} \ No newline at end of file +} -- cgit 1.5.1 From 6123f359b0b58e72da70d0f0d89cc7714d54f8b6 Mon Sep 17 00:00:00 2001 From: AlTech98 Date: Fri, 17 Sep 2021 18:29:02 +0200 Subject: Fix icon, owner_id change and channel deletion for group DMs --- api/assets/schemas.json | 1190 +++++++++++++------------- api/src/routes/channels/#channel_id/index.ts | 8 +- cdn/src/Server.ts | 3 + util/src/entities/Channel.ts | 4 +- util/src/services/ChannelService.ts | 36 +- 5 files changed, 633 insertions(+), 608 deletions(-) (limited to 'util/src') diff --git a/api/assets/schemas.json b/api/assets/schemas.json index 9c34f968..05046b97 100644 --- a/api/assets/schemas.json +++ b/api/assets/schemas.json @@ -81,11 +81,30 @@ "type": "string" }, "type": { - "$ref": "#/definitions/ChannelType" + "enum": [ + 0, + 1, + 10, + 11, + 12, + 13, + 2, + 3, + 4, + 5, + 6 + ], + "type": "number" }, "topic": { "type": "string" }, + "icon": { + "type": [ + "null", + "string" + ] + }, "bitrate": { "type": "integer" }, @@ -142,27 +161,7 @@ } }, "additionalProperties": false, - "required": [ - "name", - "type" - ], "definitions": { - "ChannelType": { - "enum": [ - 0, - 1, - 10, - 11, - 12, - 13, - 2, - 3, - 4, - 5, - 6 - ], - "type": "number" - }, "ChannelPermissionOverwriteType": { "enum": [ 0, @@ -308,11 +307,30 @@ "type": "string" }, "type": { - "$ref": "#/definitions/ChannelType" + "enum": [ + 0, + 1, + 10, + 11, + 12, + 13, + 2, + 3, + 4, + 5, + 6 + ], + "type": "number" }, "topic": { "type": "string" }, + "icon": { + "type": [ + "null", + "string" + ] + }, "bitrate": { "type": "integer" }, @@ -368,11 +386,7 @@ "type": "integer" } }, - "additionalProperties": false, - "required": [ - "name", - "type" - ] + "additionalProperties": false }, "RelationshipType": { "enum": [ @@ -470,22 +484,6 @@ }, "additionalProperties": false, "definitions": { - "ChannelType": { - "enum": [ - 0, - 1, - 10, - 11, - 12, - 13, - 2, - 3, - 4, - 5, - 6 - ], - "type": "number" - }, "ChannelPermissionOverwriteType": { "enum": [ 0, @@ -631,11 +629,30 @@ "type": "string" }, "type": { - "$ref": "#/definitions/ChannelType" + "enum": [ + 0, + 1, + 10, + 11, + 12, + 13, + 2, + 3, + 4, + 5, + 6 + ], + "type": "number" }, "topic": { "type": "string" }, + "icon": { + "type": [ + "null", + "string" + ] + }, "bitrate": { "type": "integer" }, @@ -691,11 +708,7 @@ "type": "integer" } }, - "additionalProperties": false, - "required": [ - "name", - "type" - ] + "additionalProperties": false }, "RelationshipType": { "enum": [ @@ -751,22 +764,6 @@ }, "additionalProperties": false, "definitions": { - "ChannelType": { - "enum": [ - 0, - 1, - 10, - 11, - 12, - 13, - 2, - 3, - 4, - 5, - 6 - ], - "type": "number" - }, "ChannelPermissionOverwriteType": { "enum": [ 0, @@ -912,11 +909,30 @@ "type": "string" }, "type": { - "$ref": "#/definitions/ChannelType" + "enum": [ + 0, + 1, + 10, + 11, + 12, + 13, + 2, + 3, + 4, + 5, + 6 + ], + "type": "number" }, "topic": { "type": "string" }, + "icon": { + "type": [ + "null", + "string" + ] + }, "bitrate": { "type": "integer" }, @@ -972,11 +988,7 @@ "type": "integer" } }, - "additionalProperties": false, - "required": [ - "name", - "type" - ] + "additionalProperties": false }, "RelationshipType": { "enum": [ @@ -1002,22 +1014,6 @@ }, "additionalProperties": false, "definitions": { - "ChannelType": { - "enum": [ - 0, - 1, - 10, - 11, - 12, - 13, - 2, - 3, - 4, - 5, - 6 - ], - "type": "number" - }, "ChannelPermissionOverwriteType": { "enum": [ 0, @@ -1163,11 +1159,30 @@ "type": "string" }, "type": { - "$ref": "#/definitions/ChannelType" + "enum": [ + 0, + 1, + 10, + 11, + 12, + 13, + 2, + 3, + 4, + 5, + 6 + ], + "type": "number" }, "topic": { "type": "string" }, + "icon": { + "type": [ + "null", + "string" + ] + }, "bitrate": { "type": "integer" }, @@ -1223,11 +1238,7 @@ "type": "integer" } }, - "additionalProperties": false, - "required": [ - "name", - "type" - ] + "additionalProperties": false }, "RelationshipType": { "enum": [ @@ -1256,22 +1267,6 @@ "messages" ], "definitions": { - "ChannelType": { - "enum": [ - 0, - 1, - 10, - 11, - 12, - 13, - 2, - 3, - 4, - 5, - 6 - ], - "type": "number" - }, "ChannelPermissionOverwriteType": { "enum": [ 0, @@ -1417,11 +1412,30 @@ "type": "string" }, "type": { - "$ref": "#/definitions/ChannelType" + "enum": [ + 0, + 1, + 10, + 11, + 12, + 13, + 2, + 3, + 4, + 5, + 6 + ], + "type": "number" }, "topic": { "type": "string" }, + "icon": { + "type": [ + "null", + "string" + ] + }, "bitrate": { "type": "integer" }, @@ -1477,11 +1491,7 @@ "type": "integer" } }, - "additionalProperties": false, - "required": [ - "name", - "type" - ] + "additionalProperties": false }, "RelationshipType": { "enum": [ @@ -1519,22 +1529,6 @@ "type" ], "definitions": { - "ChannelType": { - "enum": [ - 0, - 1, - 10, - 11, - 12, - 13, - 2, - 3, - 4, - 5, - 6 - ], - "type": "number" - }, "ChannelPermissionOverwriteType": { "enum": [ 0, @@ -1680,11 +1674,30 @@ "type": "string" }, "type": { - "$ref": "#/definitions/ChannelType" + "enum": [ + 0, + 1, + 10, + 11, + 12, + 13, + 2, + 3, + 4, + 5, + 6 + ], + "type": "number" }, "topic": { "type": "string" }, + "icon": { + "type": [ + "null", + "string" + ] + }, "bitrate": { "type": "integer" }, @@ -1740,11 +1753,7 @@ "type": "integer" } }, - "additionalProperties": false, - "required": [ - "name", - "type" - ] + "additionalProperties": false }, "RelationshipType": { "enum": [ @@ -1775,22 +1784,6 @@ "name" ], "definitions": { - "ChannelType": { - "enum": [ - 0, - 1, - 10, - 11, - 12, - 13, - 2, - 3, - 4, - 5, - 6 - ], - "type": "number" - }, "ChannelPermissionOverwriteType": { "enum": [ 0, @@ -1936,11 +1929,30 @@ "type": "string" }, "type": { - "$ref": "#/definitions/ChannelType" + "enum": [ + 0, + 1, + 10, + 11, + 12, + 13, + 2, + 3, + 4, + 5, + 6 + ], + "type": "number" }, "topic": { "type": "string" }, + "icon": { + "type": [ + "null", + "string" + ] + }, "bitrate": { "type": "integer" }, @@ -1996,11 +2008,7 @@ "type": "integer" } }, - "additionalProperties": false, - "required": [ - "name", - "type" - ] + "additionalProperties": false }, "RelationshipType": { "enum": [ @@ -2026,22 +2034,6 @@ }, "additionalProperties": false, "definitions": { - "ChannelType": { - "enum": [ - 0, - 1, - 10, - 11, - 12, - 13, - 2, - 3, - 4, - 5, - 6 - ], - "type": "number" - }, "ChannelPermissionOverwriteType": { "enum": [ 0, @@ -2187,11 +2179,30 @@ "type": "string" }, "type": { - "$ref": "#/definitions/ChannelType" + "enum": [ + 0, + 1, + 10, + 11, + 12, + 13, + 2, + 3, + 4, + 5, + 6 + ], + "type": "number" }, "topic": { "type": "string" }, + "icon": { + "type": [ + "null", + "string" + ] + }, "bitrate": { "type": "integer" }, @@ -2247,11 +2258,7 @@ "type": "integer" } }, - "additionalProperties": false, - "required": [ - "name", - "type" - ] + "additionalProperties": false }, "RelationshipType": { "enum": [ @@ -2289,22 +2296,6 @@ ] }, "definitions": { - "ChannelType": { - "enum": [ - 0, - 1, - 10, - 11, - 12, - 13, - 2, - 3, - 4, - 5, - 6 - ], - "type": "number" - }, "ChannelPermissionOverwriteType": { "enum": [ 0, @@ -2450,11 +2441,30 @@ "type": "string" }, "type": { - "$ref": "#/definitions/ChannelType" + "enum": [ + 0, + 1, + 10, + 11, + 12, + 13, + 2, + 3, + 4, + 5, + 6 + ], + "type": "number" }, "topic": { "type": "string" }, + "icon": { + "type": [ + "null", + "string" + ] + }, "bitrate": { "type": "integer" }, @@ -2510,11 +2520,7 @@ "type": "integer" } }, - "additionalProperties": false, - "required": [ - "name", - "type" - ] + "additionalProperties": false }, "RelationshipType": { "enum": [ @@ -2565,22 +2571,6 @@ "name" ], "definitions": { - "ChannelType": { - "enum": [ - 0, - 1, - 10, - 11, - 12, - 13, - 2, - 3, - 4, - 5, - 6 - ], - "type": "number" - }, "ChannelPermissionOverwriteType": { "enum": [ 0, @@ -2726,11 +2716,30 @@ "type": "string" }, "type": { - "$ref": "#/definitions/ChannelType" + "enum": [ + 0, + 1, + 10, + 11, + 12, + 13, + 2, + 3, + 4, + 5, + 6 + ], + "type": "number" }, "topic": { "type": "string" }, + "icon": { + "type": [ + "null", + "string" + ] + }, "bitrate": { "type": "integer" }, @@ -2786,11 +2795,7 @@ "type": "integer" } }, - "additionalProperties": false, - "required": [ - "name", - "type" - ] + "additionalProperties": false }, "RelationshipType": { "enum": [ @@ -2889,22 +2894,6 @@ "name" ], "definitions": { - "ChannelType": { - "enum": [ - 0, - 1, - 10, - 11, - 12, - 13, - 2, - 3, - 4, - 5, - 6 - ], - "type": "number" - }, "ChannelPermissionOverwriteType": { "enum": [ 0, @@ -3050,11 +3039,30 @@ "type": "string" }, "type": { - "$ref": "#/definitions/ChannelType" + "enum": [ + 0, + 1, + 10, + 11, + 12, + 13, + 2, + 3, + 4, + 5, + 6 + ], + "type": "number" }, "topic": { "type": "string" }, + "icon": { + "type": [ + "null", + "string" + ] + }, "bitrate": { "type": "integer" }, @@ -3110,11 +3118,7 @@ "type": "integer" } }, - "additionalProperties": false, - "required": [ - "name", - "type" - ] + "additionalProperties": false }, "RelationshipType": { "enum": [ @@ -3140,22 +3144,6 @@ }, "additionalProperties": false, "definitions": { - "ChannelType": { - "enum": [ - 0, - 1, - 10, - 11, - 12, - 13, - 2, - 3, - 4, - 5, - 6 - ], - "type": "number" - }, "ChannelPermissionOverwriteType": { "enum": [ 0, @@ -3301,11 +3289,30 @@ "type": "string" }, "type": { - "$ref": "#/definitions/ChannelType" + "enum": [ + 0, + 1, + 10, + 11, + 12, + 13, + 2, + 3, + 4, + 5, + 6 + ], + "type": "number" }, "topic": { "type": "string" }, + "icon": { + "type": [ + "null", + "string" + ] + }, "bitrate": { "type": "integer" }, @@ -3361,11 +3368,7 @@ "type": "integer" } }, - "additionalProperties": false, - "required": [ - "name", - "type" - ] + "additionalProperties": false }, "RelationshipType": { "enum": [ @@ -3391,22 +3394,6 @@ "nick" ], "definitions": { - "ChannelType": { - "enum": [ - 0, - 1, - 10, - 11, - 12, - 13, - 2, - 3, - 4, - 5, - 6 - ], - "type": "number" - }, "ChannelPermissionOverwriteType": { "enum": [ 0, @@ -3552,11 +3539,30 @@ "type": "string" }, "type": { - "$ref": "#/definitions/ChannelType" + "enum": [ + 0, + 1, + 10, + 11, + 12, + 13, + 2, + 3, + 4, + 5, + 6 + ], + "type": "number" }, "topic": { "type": "string" }, + "icon": { + "type": [ + "null", + "string" + ] + }, "bitrate": { "type": "integer" }, @@ -3612,11 +3618,7 @@ "type": "integer" } }, - "additionalProperties": false, - "required": [ - "name", - "type" - ] + "additionalProperties": false }, "RelationshipType": { "enum": [ @@ -3654,22 +3656,6 @@ }, "additionalProperties": false, "definitions": { - "ChannelType": { - "enum": [ - 0, - 1, - 10, - 11, - 12, - 13, - 2, - 3, - 4, - 5, - 6 - ], - "type": "number" - }, "ChannelPermissionOverwriteType": { "enum": [ 0, @@ -3815,11 +3801,30 @@ "type": "string" }, "type": { - "$ref": "#/definitions/ChannelType" + "enum": [ + 0, + 1, + 10, + 11, + 12, + 13, + 2, + 3, + 4, + 5, + 6 + ], + "type": "number" }, "topic": { "type": "string" }, + "icon": { + "type": [ + "null", + "string" + ] + }, "bitrate": { "type": "integer" }, @@ -3875,11 +3880,7 @@ "type": "integer" } }, - "additionalProperties": false, - "required": [ - "name", - "type" - ] + "additionalProperties": false }, "RelationshipType": { "enum": [ @@ -3912,22 +3913,6 @@ ] }, "definitions": { - "ChannelType": { - "enum": [ - 0, - 1, - 10, - 11, - 12, - 13, - 2, - 3, - 4, - 5, - 6 - ], - "type": "number" - }, "ChannelPermissionOverwriteType": { "enum": [ 0, @@ -4073,11 +4058,30 @@ "type": "string" }, "type": { - "$ref": "#/definitions/ChannelType" + "enum": [ + 0, + 1, + 10, + 11, + 12, + 13, + 2, + 3, + 4, + 5, + 6 + ], + "type": "number" }, "topic": { "type": "string" }, + "icon": { + "type": [ + "null", + "string" + ] + }, "bitrate": { "type": "integer" }, @@ -4133,11 +4137,7 @@ "type": "integer" } }, - "additionalProperties": false, - "required": [ - "name", - "type" - ] + "additionalProperties": false }, "RelationshipType": { "enum": [ @@ -4166,22 +4166,6 @@ "name" ], "definitions": { - "ChannelType": { - "enum": [ - 0, - 1, - 10, - 11, - 12, - 13, - 2, - 3, - 4, - 5, - 6 - ], - "type": "number" - }, "ChannelPermissionOverwriteType": { "enum": [ 0, @@ -4327,11 +4311,30 @@ "type": "string" }, "type": { - "$ref": "#/definitions/ChannelType" + "enum": [ + 0, + 1, + 10, + 11, + 12, + 13, + 2, + 3, + 4, + 5, + 6 + ], + "type": "number" }, "topic": { "type": "string" }, + "icon": { + "type": [ + "null", + "string" + ] + }, "bitrate": { "type": "integer" }, @@ -4385,13 +4388,9 @@ }, "default_auto_archive_duration": { "type": "integer" - } - }, - "additionalProperties": false, - "required": [ - "name", - "type" - ] + } + }, + "additionalProperties": false }, "RelationshipType": { "enum": [ @@ -4420,22 +4419,6 @@ "name" ], "definitions": { - "ChannelType": { - "enum": [ - 0, - 1, - 10, - 11, - 12, - 13, - 2, - 3, - 4, - 5, - 6 - ], - "type": "number" - }, "ChannelPermissionOverwriteType": { "enum": [ 0, @@ -4581,11 +4564,30 @@ "type": "string" }, "type": { - "$ref": "#/definitions/ChannelType" + "enum": [ + 0, + 1, + 10, + 11, + 12, + 13, + 2, + 3, + 4, + 5, + 6 + ], + "type": "number" }, "topic": { "type": "string" }, + "icon": { + "type": [ + "null", + "string" + ] + }, "bitrate": { "type": "integer" }, @@ -4641,11 +4643,7 @@ "type": "integer" } }, - "additionalProperties": false, - "required": [ - "name", - "type" - ] + "additionalProperties": false }, "RelationshipType": { "enum": [ @@ -4670,22 +4668,6 @@ }, "additionalProperties": false, "definitions": { - "ChannelType": { - "enum": [ - 0, - 1, - 10, - 11, - 12, - 13, - 2, - 3, - 4, - 5, - 6 - ], - "type": "number" - }, "ChannelPermissionOverwriteType": { "enum": [ 0, @@ -4831,11 +4813,30 @@ "type": "string" }, "type": { - "$ref": "#/definitions/ChannelType" + "enum": [ + 0, + 1, + 10, + 11, + 12, + 13, + 2, + 3, + 4, + 5, + 6 + ], + "type": "number" }, "topic": { "type": "string" }, + "icon": { + "type": [ + "null", + "string" + ] + }, "bitrate": { "type": "integer" }, @@ -4891,11 +4892,7 @@ "type": "integer" } }, - "additionalProperties": false, - "required": [ - "name", - "type" - ] + "additionalProperties": false }, "RelationshipType": { "enum": [ @@ -4940,22 +4937,6 @@ "channel_id" ], "definitions": { - "ChannelType": { - "enum": [ - 0, - 1, - 10, - 11, - 12, - 13, - 2, - 3, - 4, - 5, - 6 - ], - "type": "number" - }, "ChannelPermissionOverwriteType": { "enum": [ 0, @@ -5101,11 +5082,30 @@ "type": "string" }, "type": { - "$ref": "#/definitions/ChannelType" + "enum": [ + 0, + 1, + 10, + 11, + 12, + 13, + 2, + 3, + 4, + 5, + 6 + ], + "type": "number" }, "topic": { "type": "string" }, + "icon": { + "type": [ + "null", + "string" + ] + }, "bitrate": { "type": "integer" }, @@ -5161,11 +5161,7 @@ "type": "integer" } }, - "additionalProperties": false, - "required": [ - "name", - "type" - ] + "additionalProperties": false }, "RelationshipType": { "enum": [ @@ -5217,22 +5213,6 @@ }, "additionalProperties": false, "definitions": { - "ChannelType": { - "enum": [ - 0, - 1, - 10, - 11, - 12, - 13, - 2, - 3, - 4, - 5, - 6 - ], - "type": "number" - }, "ChannelPermissionOverwriteType": { "enum": [ 0, @@ -5378,11 +5358,30 @@ "type": "string" }, "type": { - "$ref": "#/definitions/ChannelType" + "enum": [ + 0, + 1, + 10, + 11, + 12, + 13, + 2, + 3, + 4, + 5, + 6 + ], + "type": "number" }, "topic": { "type": "string" }, + "icon": { + "type": [ + "null", + "string" + ] + }, "bitrate": { "type": "integer" }, @@ -5438,11 +5437,7 @@ "type": "integer" } }, - "additionalProperties": false, - "required": [ - "name", - "type" - ] + "additionalProperties": false }, "RelationshipType": { "enum": [ @@ -5472,22 +5467,6 @@ "enabled" ], "definitions": { - "ChannelType": { - "enum": [ - 0, - 1, - 10, - 11, - 12, - 13, - 2, - 3, - 4, - 5, - 6 - ], - "type": "number" - }, "ChannelPermissionOverwriteType": { "enum": [ 0, @@ -5633,11 +5612,30 @@ "type": "string" }, "type": { - "$ref": "#/definitions/ChannelType" + "enum": [ + 0, + 1, + 10, + 11, + 12, + 13, + 2, + 3, + 4, + 5, + 6 + ], + "type": "number" }, "topic": { "type": "string" }, + "icon": { + "type": [ + "null", + "string" + ] + }, "bitrate": { "type": "integer" }, @@ -5693,11 +5691,7 @@ "type": "integer" } }, - "additionalProperties": false, - "required": [ - "name", - "type" - ] + "additionalProperties": false }, "RelationshipType": { "enum": [ @@ -5726,22 +5720,6 @@ "name" ], "definitions": { - "ChannelType": { - "enum": [ - 0, - 1, - 10, - 11, - 12, - 13, - 2, - 3, - 4, - 5, - 6 - ], - "type": "number" - }, "ChannelPermissionOverwriteType": { "enum": [ 0, @@ -5887,11 +5865,30 @@ "type": "string" }, "type": { - "$ref": "#/definitions/ChannelType" + "enum": [ + 0, + 1, + 10, + 11, + 12, + 13, + 2, + 3, + 4, + 5, + 6 + ], + "type": "number" }, "topic": { "type": "string" }, + "icon": { + "type": [ + "null", + "string" + ] + }, "bitrate": { "type": "integer" }, @@ -5947,11 +5944,7 @@ "type": "integer" } }, - "additionalProperties": false, - "required": [ - "name", - "type" - ] + "additionalProperties": false }, "RelationshipType": { "enum": [ @@ -5983,22 +5976,6 @@ "recipients" ], "definitions": { - "ChannelType": { - "enum": [ - 0, - 1, - 10, - 11, - 12, - 13, - 2, - 3, - 4, - 5, - 6 - ], - "type": "number" - }, "ChannelPermissionOverwriteType": { "enum": [ 0, @@ -6144,11 +6121,30 @@ "type": "string" }, "type": { - "$ref": "#/definitions/ChannelType" + "enum": [ + 0, + 1, + 10, + 11, + 12, + 13, + 2, + 3, + 4, + 5, + 6 + ], + "type": "number" }, "topic": { "type": "string" }, + "icon": { + "type": [ + "null", + "string" + ] + }, "bitrate": { "type": "integer" }, @@ -6204,11 +6200,7 @@ "type": "integer" } }, - "additionalProperties": false, - "required": [ - "name", - "type" - ] + "additionalProperties": false }, "RelationshipType": { "enum": [ @@ -6264,22 +6256,6 @@ }, "additionalProperties": false, "definitions": { - "ChannelType": { - "enum": [ - 0, - 1, - 10, - 11, - 12, - 13, - 2, - 3, - 4, - 5, - 6 - ], - "type": "number" - }, "ChannelPermissionOverwriteType": { "enum": [ 0, @@ -6425,11 +6401,30 @@ "type": "string" }, "type": { - "$ref": "#/definitions/ChannelType" + "enum": [ + 0, + 1, + 10, + 11, + 12, + 13, + 2, + 3, + 4, + 5, + 6 + ], + "type": "number" }, "topic": { "type": "string" }, + "icon": { + "type": [ + "null", + "string" + ] + }, "bitrate": { "type": "integer" }, @@ -6485,11 +6480,7 @@ "type": "integer" } }, - "additionalProperties": false, - "required": [ - "name", - "type" - ] + "additionalProperties": false }, "RelationshipType": { "enum": [ @@ -6515,22 +6506,6 @@ "type" ], "definitions": { - "ChannelType": { - "enum": [ - 0, - 1, - 10, - 11, - 12, - 13, - 2, - 3, - 4, - 5, - 6 - ], - "type": "number" - }, "ChannelPermissionOverwriteType": { "enum": [ 0, @@ -6676,11 +6651,30 @@ "type": "string" }, "type": { - "$ref": "#/definitions/ChannelType" + "enum": [ + 0, + 1, + 10, + 11, + 12, + 13, + 2, + 3, + 4, + 5, + 6 + ], + "type": "number" }, "topic": { "type": "string" }, + "icon": { + "type": [ + "null", + "string" + ] + }, "bitrate": { "type": "integer" }, @@ -6736,11 +6730,7 @@ "type": "integer" } }, - "additionalProperties": false, - "required": [ - "name", - "type" - ] + "additionalProperties": false }, "RelationshipType": { "enum": [ @@ -6770,22 +6760,6 @@ "username" ], "definitions": { - "ChannelType": { - "enum": [ - 0, - 1, - 10, - 11, - 12, - 13, - 2, - 3, - 4, - 5, - 6 - ], - "type": "number" - }, "ChannelPermissionOverwriteType": { "enum": [ 0, @@ -6931,11 +6905,30 @@ "type": "string" }, "type": { - "$ref": "#/definitions/ChannelType" + "enum": [ + 0, + 1, + 10, + 11, + 12, + 13, + 2, + 3, + 4, + 5, + 6 + ], + "type": "number" }, "topic": { "type": "string" }, + "icon": { + "type": [ + "null", + "string" + ] + }, "bitrate": { "type": "integer" }, @@ -6991,11 +6984,7 @@ "type": "integer" } }, - "additionalProperties": false, - "required": [ - "name", - "type" - ] + "additionalProperties": false }, "RelationshipType": { "enum": [ @@ -7208,22 +7197,6 @@ "timezone_offset" ], "definitions": { - "ChannelType": { - "enum": [ - 0, - 1, - 10, - 11, - 12, - 13, - 2, - 3, - 4, - 5, - 6 - ], - "type": "number" - }, "ChannelPermissionOverwriteType": { "enum": [ 0, @@ -7369,11 +7342,30 @@ "type": "string" }, "type": { - "$ref": "#/definitions/ChannelType" + "enum": [ + 0, + 1, + 10, + 11, + 12, + 13, + 2, + 3, + 4, + 5, + 6 + ], + "type": "number" }, "topic": { "type": "string" }, + "icon": { + "type": [ + "null", + "string" + ] + }, "bitrate": { "type": "integer" }, @@ -7429,11 +7421,7 @@ "type": "integer" } }, - "additionalProperties": false, - "required": [ - "name", - "type" - ] + "additionalProperties": false }, "RelationshipType": { "enum": [ diff --git a/api/src/routes/channels/#channel_id/index.ts b/api/src/routes/channels/#channel_id/index.ts index e836622b..70dd3994 100644 --- a/api/src/routes/channels/#channel_id/index.ts +++ b/api/src/routes/channels/#channel_id/index.ts @@ -1,6 +1,6 @@ import { Channel, ChannelDeleteEvent, ChannelPermissionOverwriteType, ChannelService, ChannelType, ChannelUpdateEvent, emitEvent, Recipient } from "@fosscord/util"; import { Request, Response, Router } from "express"; -import { route } from "@fosscord/api"; +import { handleFile, route } from "@fosscord/api"; const router: Router = Router(); // TODO: delete channel @@ -44,9 +44,10 @@ export interface ChannelModifySchema { /** * @maxLength 100 */ - name: string; - type: ChannelType; + name?: string; + type?: ChannelType; topic?: string; + icon?: string | null; bitrate?: number; user_limit?: number; rate_limit_per_user?: number; @@ -67,6 +68,7 @@ export interface ChannelModifySchema { router.patch("/", route({ body: "ChannelModifySchema", permission: "MANAGE_CHANNELS" }), async (req: Request, res: Response) => { var payload = req.body as ChannelModifySchema; const { channel_id } = req.params; + if (payload.icon) payload.icon = await handleFile(`/channel-icons/${channel_id}`, payload.icon); const channel = await Channel.findOneOrFail({ id: channel_id }); channel.assign(payload); diff --git a/cdn/src/Server.ts b/cdn/src/Server.ts index 5c4a8ae5..590eda6f 100644 --- a/cdn/src/Server.ts +++ b/cdn/src/Server.ts @@ -58,6 +58,9 @@ export class CDNServer extends Server { this.app.use("/team-icons/", avatarsRoute); this.log("verbose", "[Server] Route /team-icons registered"); + this.app.use("/channel-icons/", avatarsRoute); + this.log("verbose", "[Server] Route /channel-icons registered"); + return super.start(); } diff --git a/util/src/entities/Channel.ts b/util/src/entities/Channel.ts index 6eac19ca..aa2bfab3 100644 --- a/util/src/entities/Channel.ts +++ b/util/src/entities/Channel.ts @@ -30,8 +30,8 @@ export class Channel extends BaseClass { @Column({ nullable: true }) name?: string; - @Column({ nullable: true }) - icon?: string; + @Column({ type: 'text', nullable: true }) + icon?: string | null; @Column({ type: "simple-enum", enum: ChannelType }) type: ChannelType; diff --git a/util/src/services/ChannelService.ts b/util/src/services/ChannelService.ts index 319475b6..8f57a28a 100644 --- a/util/src/services/ChannelService.ts +++ b/util/src/services/ChannelService.ts @@ -1,4 +1,4 @@ -import { Channel, ChannelType, PublicUserProjection, Recipient, User } from "../entities"; +import { Channel, ChannelType, Message, PublicUserProjection, Recipient, User } from "../entities"; import { HTTPError } from "lambert-server"; import { emitEvent, trimSpecial } from "../util"; import { DmChannelDTO } from "../dtos"; @@ -72,10 +72,36 @@ export class ChannelService { public static async removeRecipientFromChannel(channel: Channel, user_id: string) { await Recipient.delete({ channel_id: channel.id, user_id: user_id }) + channel.recipients = channel.recipients?.filter(r => r.user_id !== user_id) + + if (channel.recipients?.length === 0) { + await ChannelService.deleteChannel(channel); + await emitEvent({ + event: "CHANNEL_DELETE", + data: await DmChannelDTO.from(channel, [user_id]), + user_id: user_id + }); + return + } + + let channel_dto = null; + + //If the owner leave we make the first recipient in the list the new owner + if (channel.owner_id === user_id) { + channel.owner_id = channel.recipients!.find(r => r.user_id !== user_id)!.user_id //Is there a criteria to choose the new owner? + channel_dto = await DmChannelDTO.from(channel, [user_id]) + await emitEvent({ + event: "CHANNEL_UPDATE", + data: channel_dto, + channel_id: channel.id + }); + } + + await channel.save() await emitEvent({ event: "CHANNEL_DELETE", - data: await DmChannelDTO.from(channel, [user_id]), + data: channel_dto !== null ? channel_dto : await DmChannelDTO.from(channel, [user_id]), user_id: user_id }); @@ -86,4 +112,10 @@ export class ChannelService { }, channel_id: channel.id } as ChannelRecipientRemoveEvent); } + + public static async deleteChannel(channel: Channel) { + await Message.delete({ channel_id: channel.id }) //TODO we should also delete the attachments from the cdn but to do that we need to move cdn.ts in util + //TODO before deleting the channel we should check and delete other relations + await Channel.delete({ id: channel.id }) + } } -- cgit 1.5.1 From 296375c67e388e08b09a9bda16348103df48b75c Mon Sep 17 00:00:00 2001 From: AlTech98 Date: Sat, 18 Sep 2021 10:44:25 +0200 Subject: Fix gateway not listening for new channels events --- gateway/src/listener/listener.ts | 11 +++-------- util/src/services/ChannelService.ts | 15 ++++++--------- util/src/util/Event.ts | 1 - 3 files changed, 9 insertions(+), 18 deletions(-) (limited to 'util/src') diff --git a/gateway/src/listener/listener.ts b/gateway/src/listener/listener.ts index 16803639..35841312 100644 --- a/gateway/src/listener/listener.ts +++ b/gateway/src/listener/listener.ts @@ -116,7 +116,7 @@ async function consume(this: WebSocket, opts: EventOpts) { .has("VIEW_CHANNEL") ) return; - break; + //No break needed here, we need to call the listenEvent function below case "GUILD_CREATE": this.events[id] = await listenEvent(id, consumer, listenOpts); break; @@ -193,16 +193,11 @@ async function consume(this: WebSocket, opts: EventOpts) { break; } - let aa = { + Send(this, { op: OPCODES.Dispatch, t: event, d: data, s: this.sequence++, - } - - //TODO remove before PR merge - console.log(aa) - - Send(this, aa); + }); opts.acknowledge?.(); } diff --git a/util/src/services/ChannelService.ts b/util/src/services/ChannelService.ts index 8f57a28a..aa021a4a 100644 --- a/util/src/services/ChannelService.ts +++ b/util/src/services/ChannelService.ts @@ -84,27 +84,24 @@ export class ChannelService { return } - let channel_dto = null; + await emitEvent({ + event: "CHANNEL_DELETE", + data: await DmChannelDTO.from(channel, [user_id]), + user_id: user_id + }); //If the owner leave we make the first recipient in the list the new owner if (channel.owner_id === user_id) { channel.owner_id = channel.recipients!.find(r => r.user_id !== user_id)!.user_id //Is there a criteria to choose the new owner? - channel_dto = await DmChannelDTO.from(channel, [user_id]) await emitEvent({ event: "CHANNEL_UPDATE", - data: channel_dto, + data: await DmChannelDTO.from(channel, [user_id]), channel_id: channel.id }); } await channel.save() - await emitEvent({ - event: "CHANNEL_DELETE", - data: channel_dto !== null ? channel_dto : await DmChannelDTO.from(channel, [user_id]), - user_id: user_id - }); - await emitEvent({ event: "CHANNEL_RECIPIENT_REMOVE", data: { channel_id: channel.id, diff --git a/util/src/util/Event.ts b/util/src/util/Event.ts index ae296df9..765e5fc7 100644 --- a/util/src/util/Event.ts +++ b/util/src/util/Event.ts @@ -5,7 +5,6 @@ import { EVENT, Event } from "../interfaces"; const events = new EventEmitter(); export async function emitEvent(payload: Omit) { - console.log(payload) //TODO remove before merge const id = (payload.channel_id || payload.user_id || payload.guild_id) as string; if (!id) return console.error("event doesn't contain any id", payload); -- cgit 1.5.1 From ceb770fb5b6648c18d66d6997c8916ed60b8c192 Mon Sep 17 00:00:00 2001 From: AlTech98 Date: Sat, 18 Sep 2021 18:36:29 +0200 Subject: Removed ChannelService, more fixes --- api/src/routes/channels/#channel_id/index.ts | 4 +- .../routes/channels/#channel_id/messages/index.ts | 6 +- api/src/routes/channels/#channel_id/recipients.ts | 6 +- api/src/routes/users/@me/channels.ts | 4 +- gateway/src/listener/listener.ts | 2 +- util/src/entities/Channel.ts | 124 +++++++++++++++++++-- util/src/index.ts | 1 - util/src/services/ChannelService.ts | 118 -------------------- util/src/services/index.ts | 1 - util/src/util/Array.ts | 3 + util/src/util/index.ts | 1 + 11 files changed, 131 insertions(+), 139 deletions(-) delete mode 100644 util/src/services/ChannelService.ts delete mode 100644 util/src/services/index.ts create mode 100644 util/src/util/Array.ts (limited to 'util/src') diff --git a/api/src/routes/channels/#channel_id/index.ts b/api/src/routes/channels/#channel_id/index.ts index 70dd3994..3f434f5e 100644 --- a/api/src/routes/channels/#channel_id/index.ts +++ b/api/src/routes/channels/#channel_id/index.ts @@ -1,4 +1,4 @@ -import { Channel, ChannelDeleteEvent, ChannelPermissionOverwriteType, ChannelService, ChannelType, ChannelUpdateEvent, emitEvent, Recipient } from "@fosscord/util"; +import { Channel, ChannelDeleteEvent, ChannelPermissionOverwriteType, ChannelType, ChannelUpdateEvent, emitEvent, Recipient } from "@fosscord/util"; import { Request, Response, Router } from "express"; import { handleFile, route } from "@fosscord/api"; @@ -28,7 +28,7 @@ router.delete("/", route({ permission: "MANAGE_CHANNELS" }), async (req: Request ]); } else if (channel.type === ChannelType.GROUP_DM) { - await ChannelService.removeRecipientFromChannel(channel, req.user_id) + await Channel.removeRecipientFromChannel(channel, req.user_id) } else { //TODO messages in this channel should be deleted before deleting the channel await Promise.all([ diff --git a/api/src/routes/channels/#channel_id/messages/index.ts b/api/src/routes/channels/#channel_id/messages/index.ts index bb610a6a..cde14164 100644 --- a/api/src/routes/channels/#channel_id/messages/index.ts +++ b/api/src/routes/channels/#channel_id/messages/index.ts @@ -1,5 +1,5 @@ import { Router, Response, Request } from "express"; -import { Attachment, Channel, ChannelType, DmChannelDTO, Embed, emitEvent, getPermission, Message, MessageCreateEvent } from "@fosscord/util"; +import { Attachment, Channel, ChannelType, DmChannelDTO, Embed, emitEvent, getPermission, Message, MessageCreateEvent, Recipient } from "@fosscord/util"; import { HTTPError } from "lambert-server"; import { handleMessage, postHandleMessage, route } from "@fosscord/api"; import multer from "multer"; @@ -150,7 +150,6 @@ router.post( return res.status(400).json(error); } } - //TODO querying the DB at every message post should be avoided, caching maybe? const channel = await Channel.findOneOrFail({ where: { id: channel_id }, relations: ["recipients", "recipients.user"] }) const embeds = []; @@ -184,7 +183,8 @@ router.post( } } - await Promise.all(channel.recipients!.map(async r => { + //Only one recipients should be closed here, since in group DMs the recipient is deleted not closed + await Promise.all(channel.recipients!.filter(r => r.closed).map(async r => { r.closed = false; return await r.save() })); diff --git a/api/src/routes/channels/#channel_id/recipients.ts b/api/src/routes/channels/#channel_id/recipients.ts index d88b38f3..c7beeee8 100644 --- a/api/src/routes/channels/#channel_id/recipients.ts +++ b/api/src/routes/channels/#channel_id/recipients.ts @@ -1,5 +1,5 @@ import { Request, Response, Router } from "express"; -import { Channel, ChannelRecipientAddEvent, ChannelService, ChannelType, DiscordApiErrors, DmChannelDTO, emitEvent, PublicUserProjection, Recipient, User } from "@fosscord/util"; +import { Channel, ChannelRecipientAddEvent, ChannelType, DiscordApiErrors, DmChannelDTO, emitEvent, PublicUserProjection, Recipient, User } from "@fosscord/util"; const router: Router = Router(); @@ -13,7 +13,7 @@ router.put("/:user_id", async (req: Request, res: Response) => { user_id ].unique() - const new_channel = await ChannelService.createDMChannel(recipients, req.user_id) + const new_channel = await Channel.createDMChannel(recipients, req.user_id) return res.status(201).json(new_channel); } else { if (channel.recipients!.map(r => r.user_id).includes(user_id)) { @@ -49,7 +49,7 @@ router.delete("/:user_id", async (req: Request, res: Response) => { throw DiscordApiErrors.INVALID_RECIPIENT //TODO is this the right error? } - await ChannelService.removeRecipientFromChannel(channel, user_id) + await Channel.removeRecipientFromChannel(channel, user_id) return res.sendStatus(204); }); diff --git a/api/src/routes/users/@me/channels.ts b/api/src/routes/users/@me/channels.ts index 873ff245..b5782eca 100644 --- a/api/src/routes/users/@me/channels.ts +++ b/api/src/routes/users/@me/channels.ts @@ -1,5 +1,5 @@ import { Request, Response, Router } from "express"; -import { Recipient, ChannelService, DmChannelDTO } from "@fosscord/util"; +import { Recipient, DmChannelDTO, Channel } from "@fosscord/util"; import { route } from "@fosscord/api"; const router: Router = Router(); @@ -16,7 +16,7 @@ export interface DmChannelCreateSchema { router.post("/", route({ body: "DmChannelCreateSchema" }), async (req: Request, res: Response) => { const body = req.body as DmChannelCreateSchema; - res.json(await ChannelService.createDMChannel(body.recipients, req.user_id, body.name)); + res.json(await Channel.createDMChannel(body.recipients, req.user_id, body.name)); }); export default router; diff --git a/gateway/src/listener/listener.ts b/gateway/src/listener/listener.ts index 35841312..ae13cca7 100644 --- a/gateway/src/listener/listener.ts +++ b/gateway/src/listener/listener.ts @@ -32,7 +32,7 @@ export async function setupListener(this: WebSocket) { }); const guilds = members.map((x) => x.guild); const recipients = await Recipient.find({ - where: { user_id: this.user_id }, + where: { user_id: this.user_id, closed: false }, relations: ["channel"], }); const dm_channels = recipients.map((x) => x.channel); diff --git a/util/src/entities/Channel.ts b/util/src/entities/Channel.ts index aa2bfab3..ea632778 100644 --- a/util/src/entities/Channel.ts +++ b/util/src/entities/Channel.ts @@ -1,11 +1,13 @@ import { Column, Entity, JoinColumn, ManyToOne, OneToMany, RelationId } from "typeorm"; import { BaseClass } from "./BaseClass"; import { Guild } from "./Guild"; -import { User } from "./User"; +import { PublicUserProjection, User } from "./User"; import { HTTPError } from "lambert-server"; -import { emitEvent, getPermission, Snowflake } from "../util"; -import { ChannelCreateEvent } from "../interfaces"; +import { containsAll, emitEvent, getPermission, Snowflake, trimSpecial } from "../util"; +import { ChannelCreateEvent, ChannelRecipientRemoveEvent } from "../interfaces"; import { Recipient } from "./Recipient"; +import { DmChannelDTO } from "../dtos"; +import { Message } from "./Message"; export enum ChannelType { GUILD_TEXT = 0, // a text channel within a server @@ -97,7 +99,6 @@ export class Channel extends BaseClass { @Column({ nullable: true }) topic?: string; - // TODO: DM channel static async createChannel( channel: Partial, user_id: string = "0", @@ -150,16 +151,123 @@ export class Channel extends BaseClass { new Channel(channel).save(), !opts?.skipEventEmit ? emitEvent({ - event: "CHANNEL_CREATE", - data: channel, - guild_id: channel.guild_id, - } as ChannelCreateEvent) + event: "CHANNEL_CREATE", + data: channel, + guild_id: channel.guild_id, + } as ChannelCreateEvent) : Promise.resolve(), ]); return channel; } + static async createDMChannel(recipients: string[], creator_user_id: string, name?: string) { + recipients = recipients.unique().filter((x) => x !== creator_user_id); + const otherRecipientsUsers = await User.find({ where: recipients.map((x) => ({ id: x })) }); + + // TODO: check config for max number of recipients + if (otherRecipientsUsers.length !== recipients.length) { + throw new HTTPError("Recipient/s not found"); + } + + const type = recipients.length === 1 ? ChannelType.DM : ChannelType.GROUP_DM; + + let channel = null; + + const channelRecipients = [...recipients, creator_user_id] + + const userRecipients = await Recipient.find({ where: { user_id: creator_user_id }, relations: ["channel", "channel.recipients"] }) + + for (let ur of userRecipients) { + let re = ur.channel.recipients!.map(r => r.user_id) + if (re.length === channelRecipients.length) { + if (containsAll(re, channelRecipients)) { + if (channel == null) { + channel = ur.channel + await ur.assign({ closed: false }).save() + } + } + } + } + + if (channel == null) { + name = trimSpecial(name); + + channel = await new Channel({ + name, + type, + owner_id: (type === ChannelType.DM ? undefined : creator_user_id), + created_at: new Date(), + last_message_id: null, + recipients: channelRecipients.map((x) => new Recipient({ user_id: x, closed: !(type === ChannelType.GROUP_DM || x === creator_user_id) })), + }).save(); + } + + + const channel_dto = await DmChannelDTO.from(channel) + + if (type === ChannelType.GROUP_DM) { + + for (let recipient of channel.recipients!) { + await emitEvent({ + event: "CHANNEL_CREATE", + data: channel_dto.excludedRecipients([recipient.user_id]), + user_id: recipient.user_id + }) + } + } else { + await emitEvent({ event: "CHANNEL_CREATE", data: channel_dto, user_id: creator_user_id }); + } + + return channel_dto.excludedRecipients([creator_user_id]) + } + + static async removeRecipientFromChannel(channel: Channel, user_id: string) { + await Recipient.delete({ channel_id: channel.id, user_id: user_id }) + channel.recipients = channel.recipients?.filter(r => r.user_id !== user_id) + + if (channel.recipients?.length === 0) { + await Channel.deleteChannel(channel); + await emitEvent({ + event: "CHANNEL_DELETE", + data: await DmChannelDTO.from(channel, [user_id]), + user_id: user_id + }); + return + } + + await emitEvent({ + event: "CHANNEL_DELETE", + data: await DmChannelDTO.from(channel, [user_id]), + user_id: user_id + }); + + //If the owner leave we make the first recipient in the list the new owner + if (channel.owner_id === user_id) { + channel.owner_id = channel.recipients!.find(r => r.user_id !== user_id)!.user_id //Is there a criteria to choose the new owner? + await emitEvent({ + event: "CHANNEL_UPDATE", + data: await DmChannelDTO.from(channel, [user_id]), + channel_id: channel.id + }); + } + + await channel.save() + + await emitEvent({ + event: "CHANNEL_RECIPIENT_REMOVE", data: { + channel_id: channel.id, + user: await User.findOneOrFail({ where: { id: user_id }, select: PublicUserProjection }) + }, channel_id: channel.id + } as ChannelRecipientRemoveEvent); + } + + static async deleteChannel(channel: Channel) { + await Message.delete({ channel_id: channel.id }) //TODO we should also delete the attachments from the cdn but to do that we need to move cdn.ts in util + //TODO before deleting the channel we should check and delete other relations + await Channel.delete({ id: channel.id }) + } + isDm() { return this.type === ChannelType.DM || this.type === ChannelType.GROUP_DM } diff --git a/util/src/index.ts b/util/src/index.ts index 538bfdd1..fc00d46b 100644 --- a/util/src/index.ts +++ b/util/src/index.ts @@ -4,7 +4,6 @@ import "reflect-metadata"; export * from "./util/index"; export * from "./interfaces/index"; export * from "./entities/index"; -export * from "./services/index"; export * from "./dtos/index"; // import Config from "../util/Config"; diff --git a/util/src/services/ChannelService.ts b/util/src/services/ChannelService.ts deleted file mode 100644 index aa021a4a..00000000 --- a/util/src/services/ChannelService.ts +++ /dev/null @@ -1,118 +0,0 @@ -import { Channel, ChannelType, Message, PublicUserProjection, Recipient, User } from "../entities"; -import { HTTPError } from "lambert-server"; -import { emitEvent, trimSpecial } from "../util"; -import { DmChannelDTO } from "../dtos"; -import { ChannelRecipientRemoveEvent } from "../interfaces"; - -export function checker(arr: any[], target: any[]) { - return target.every(v => arr.includes(v)); -} - -export class ChannelService { - public static async createDMChannel(recipients: string[], creator_user_id: string, name?: string) { - recipients = recipients.unique().filter((x) => x !== creator_user_id); - const otherRecipientsUsers = await User.find({ where: recipients.map((x) => ({ id: x })) }); - - // TODO: check config for max number of recipients - if (otherRecipientsUsers.length !== recipients.length) { - throw new HTTPError("Recipient/s not found"); - } - - const type = recipients.length === 1 ? ChannelType.DM : ChannelType.GROUP_DM; - - let channel = null; - - const channelRecipients = [...recipients, creator_user_id] - - const userRecipients = await Recipient.find({ where: { user_id: creator_user_id }, relations: ["channel", "channel.recipients"] }) - - for (let ur of userRecipients) { - let re = ur.channel.recipients!.map(r => r.user_id) - if (re.length === channelRecipients.length) { - if (checker(re, channelRecipients)) { - if (channel == null) { - channel = ur.channel - await ur.assign({ closed: false }).save() - } - } - } - } - - if (channel == null) { - name = trimSpecial(name); - - channel = await new Channel({ - name, - type, - owner_id: (type === ChannelType.DM ? undefined : creator_user_id), - created_at: new Date(), - last_message_id: null, - recipients: channelRecipients.map((x) => new Recipient({ user_id: x, closed: !(type === ChannelType.GROUP_DM || x === creator_user_id) })), - }).save(); - } - - - const channel_dto = await DmChannelDTO.from(channel) - - if (type === ChannelType.GROUP_DM) { - - for (let recipient of channel.recipients!) { - await emitEvent({ - event: "CHANNEL_CREATE", - data: channel_dto.excludedRecipients([recipient.user_id]), - user_id: recipient.user_id - }) - } - } else { - await emitEvent({ event: "CHANNEL_CREATE", data: channel_dto, user_id: creator_user_id }); - } - - return channel_dto.excludedRecipients([creator_user_id]) - } - - public static async removeRecipientFromChannel(channel: Channel, user_id: string) { - await Recipient.delete({ channel_id: channel.id, user_id: user_id }) - channel.recipients = channel.recipients?.filter(r => r.user_id !== user_id) - - if (channel.recipients?.length === 0) { - await ChannelService.deleteChannel(channel); - await emitEvent({ - event: "CHANNEL_DELETE", - data: await DmChannelDTO.from(channel, [user_id]), - user_id: user_id - }); - return - } - - await emitEvent({ - event: "CHANNEL_DELETE", - data: await DmChannelDTO.from(channel, [user_id]), - user_id: user_id - }); - - //If the owner leave we make the first recipient in the list the new owner - if (channel.owner_id === user_id) { - channel.owner_id = channel.recipients!.find(r => r.user_id !== user_id)!.user_id //Is there a criteria to choose the new owner? - await emitEvent({ - event: "CHANNEL_UPDATE", - data: await DmChannelDTO.from(channel, [user_id]), - channel_id: channel.id - }); - } - - await channel.save() - - await emitEvent({ - event: "CHANNEL_RECIPIENT_REMOVE", data: { - channel_id: channel.id, - user: await User.findOneOrFail({ where: { id: user_id }, select: PublicUserProjection }) - }, channel_id: channel.id - } as ChannelRecipientRemoveEvent); - } - - public static async deleteChannel(channel: Channel) { - await Message.delete({ channel_id: channel.id }) //TODO we should also delete the attachments from the cdn but to do that we need to move cdn.ts in util - //TODO before deleting the channel we should check and delete other relations - await Channel.delete({ id: channel.id }) - } -} diff --git a/util/src/services/index.ts b/util/src/services/index.ts deleted file mode 100644 index c012a208..00000000 --- a/util/src/services/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./ChannelService"; diff --git a/util/src/util/Array.ts b/util/src/util/Array.ts new file mode 100644 index 00000000..27f7c961 --- /dev/null +++ b/util/src/util/Array.ts @@ -0,0 +1,3 @@ +export function containsAll(arr: any[], target: any[]) { + return target.every(v => arr.includes(v)); +} \ No newline at end of file diff --git a/util/src/util/index.ts b/util/src/util/index.ts index 4e92f017..2de26fc7 100644 --- a/util/src/util/index.ts +++ b/util/src/util/index.ts @@ -12,3 +12,4 @@ export * from "./RabbitMQ"; export * from "./Regex"; export * from "./Snowflake"; export * from "./String"; +export * from "./Array"; -- cgit 1.5.1 From 313696d237cc614cca8f68d8a63ad3039d00baf9 Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Sun, 19 Sep 2021 18:46:22 +0200 Subject: :art: remove deleteMessageAttachments and move to entity --- .../channels/#channel_id/messages/#message_id/index.ts | 3 --- api/src/util/Attachments.ts | 12 ------------ api/src/util/index.ts | 1 - util/src/entities/Attachment.ts | 9 ++++++++- 4 files changed, 8 insertions(+), 17 deletions(-) delete mode 100644 api/src/util/Attachments.ts (limited to 'util/src') diff --git a/api/src/routes/channels/#channel_id/messages/#message_id/index.ts b/api/src/routes/channels/#channel_id/messages/#message_id/index.ts index b5220fab..7f7de264 100644 --- a/api/src/routes/channels/#channel_id/messages/#message_id/index.ts +++ b/api/src/routes/channels/#channel_id/messages/#message_id/index.ts @@ -3,7 +3,6 @@ import { Router, Response, Request } from "express"; import { route } from "@fosscord/api"; import { handleMessage, postHandleMessage } from "@fosscord/api"; import { MessageCreateSchema } from "../index"; -import { deleteMessageAttachments } from "@fosscord/api/util/Attachments"; const router = Router(); // TODO: message content/embed string length limit @@ -34,7 +33,6 @@ router.patch("/", route({ body: "MessageCreateSchema", permission: "SEND_MESSAGE }); await Promise.all([ - await deleteMessageAttachments(message_id, new_message.attachments), //This delete all the attachments not in the array new_message!.save(), await emitEvent({ event: "MESSAGE_UPDATE", @@ -60,7 +58,6 @@ router.delete("/", route({}), async (req: Request, res: Response) => { permission.hasThrow("MANAGE_MESSAGES"); } - await deleteMessageAttachments(message_id); await Message.delete({ id: message_id }); await emitEvent({ diff --git a/api/src/util/Attachments.ts b/api/src/util/Attachments.ts deleted file mode 100644 index addda97f..00000000 --- a/api/src/util/Attachments.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Attachment } from "@fosscord/util"; -import { deleteFile } from "@fosscord/api"; -import { URL } from "url"; - -export async function deleteMessageAttachments(messageId: string, keep?: Attachment[]) { - let attachments = await Attachment.find({ message_id: messageId }); - if (keep) - attachments = attachments.filter(x => !keep.map(k => k.id).includes(x.id)); - await Promise.all(attachments.map(a => a.remove())); - - attachments.forEach(a => deleteFile((new URL(a.url)).pathname)); //We don't need to await since this is done on the cdn -} diff --git a/api/src/util/index.ts b/api/src/util/index.ts index 4b1e8e77..3e47ce4e 100644 --- a/api/src/util/index.ts +++ b/api/src/util/index.ts @@ -1,5 +1,4 @@ export * from "./Base64"; -export * from "./cdn"; export * from "./FieldError"; export * from "./ipAddress"; export * from "./Message"; diff --git a/util/src/entities/Attachment.ts b/util/src/entities/Attachment.ts index ca893400..82c5ecf5 100644 --- a/util/src/entities/Attachment.ts +++ b/util/src/entities/Attachment.ts @@ -1,4 +1,6 @@ -import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm"; +import { BeforeRemove, Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm"; +import { URL } from "url"; +import { deleteFile } from "../util/cdn"; import { BaseClass } from "./BaseClass"; @Entity("attachments") @@ -31,4 +33,9 @@ export class Attachment extends BaseClass { @JoinColumn({ name: "message_id" }) @ManyToOne(() => require("./Message").Message, (message: import("./Message").Message) => message.attachments) message: import("./Message").Message; + + @BeforeRemove() + onDelete() { + return deleteFile(new URL(this.url).pathname); + } } -- cgit 1.5.1 From b5fb88ea8e63f66d6b6ba12519941ae92f0e776d Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Sun, 19 Sep 2021 18:47:38 +0200 Subject: :art: add orphanedRowAction and cascade onDelete to entities --- util/package-lock.json | 359 +++++++++++++++++++++++++++++++++++++++++++ util/package.json | 2 + util/src/entities/Channel.ts | 71 ++++++++- util/src/entities/Guild.ts | 54 +++++-- util/src/entities/Message.ts | 11 +- util/src/util/cdn.ts | 54 +++++++ util/src/util/index.ts | 1 + 7 files changed, 532 insertions(+), 20 deletions(-) create mode 100644 util/src/util/cdn.ts (limited to 'util/src') diff --git a/util/package-lock.json b/util/package-lock.json index 4b0f1f15..e5a62d0f 100644 --- a/util/package-lock.json +++ b/util/package-lock.json @@ -18,6 +18,7 @@ "jsonwebtoken": "^8.5.1", "lambert-server": "^1.2.10", "missing-native-js-functions": "^1.2.15", + "multer": "^1.4.3", "node-fetch": "^2.6.1", "patch-package": "^6.4.7", "pg": "^8.7.1", @@ -32,6 +33,7 @@ "@types/amqplib": "^0.8.1", "@types/jsonwebtoken": "^8.5.0", "@types/mongoose-autopopulate": "^0.10.1", + "@types/multer": "^1.4.7", "@types/node": "^14.17.9", "@types/node-fetch": "^2.5.12", "jest": "^27.0.6" @@ -1063,6 +1065,48 @@ "integrity": "sha512-HBNx4lhkxN7bx6P0++W8E289foSu8kO8GCk2unhuVggO+cE7rh9DhZUyPhUxNRG9m+5B5BTKxZQ5ZP92x/mx9Q==", "dev": true }, + "node_modules/@types/body-parser": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.1.tgz", + "integrity": "sha512-a6bTJ21vFOGIkwM0kzh9Yr89ziVxq4vYH2fQ6N8AeipEzai/cFK6aGMArIkUeIdRIgpwQa+2bXiLuUJCpSf2Cg==", + "dev": true, + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", + "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", + "dev": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.18", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.17.24", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.24.tgz", + "integrity": "sha512-3UJuW+Qxhzwjq3xhwXm2onQcFHn76frIYVbTu+kn24LFxI+dEhdfISDFovPB8VpEgW8oQCTpRuCe+0zJxB7NEA==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, "node_modules/@types/graceful-fs": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", @@ -1115,6 +1159,12 @@ "@types/node": "*" } }, + "node_modules/@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", + "dev": true + }, "node_modules/@types/mongodb": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-4.0.7.tgz", @@ -1144,6 +1194,15 @@ "@types/mongoose": "5.10.5" } }, + "node_modules/@types/multer": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.7.tgz", + "integrity": "sha512-/SNsDidUFCvqqcWDwxv2feww/yqhNeTRL5CVoL3jU4Goc4kKEL10T7Eye65ZqPNi4HRx8sAEX59pV1aEH7drNA==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, "node_modules/@types/node": { "version": "14.17.16", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.16.tgz", @@ -1165,6 +1224,28 @@ "integrity": "sha512-eI5Yrz3Qv4KPUa/nSIAi0h+qX0XyewOliug5F2QAtuRg6Kjg6jfmxe1GIwoIRhZspD1A0RP8ANrPwvEXXtRFog==", "dev": true }, + "node_modules/@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", + "dev": true + }, + "node_modules/@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", + "dev": true + }, + "node_modules/@types/serve-static": { + "version": "1.13.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", + "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", + "dev": true, + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, "node_modules/@types/stack-utils": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", @@ -1396,6 +1477,11 @@ "node": ">= 6.0.0" } }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY=" + }, "node_modules/aproba": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", @@ -1816,6 +1902,18 @@ "node": ">=4" } }, + "node_modules/busboy": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", + "integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=", + "dependencies": { + "dicer": "0.2.5", + "readable-stream": "1.1.x" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/bytes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", @@ -2028,6 +2126,52 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/concat-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/concat-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", @@ -2258,6 +2402,18 @@ "node": ">=8" } }, + "node_modules/dicer": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", + "integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=", + "dependencies": { + "readable-stream": "1.1.x", + "streamsearch": "0.1.2" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", @@ -4619,6 +4775,24 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "node_modules/multer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.3.tgz", + "integrity": "sha512-np0YLKncuZoTzufbkM6wEKp68EhWJXcU6fq6QqrSwkckd2LlMgd1UqhUJLj6NS/5sZ8dE8LYDWslsltJznnXlg==", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^0.2.11", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "on-finished": "^2.3.0", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 0.10.0" + } + }, "node_modules/mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", @@ -6095,6 +6269,14 @@ "node": ">= 0.6" } }, + "node_modules/streamsearch": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", + "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=", + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", @@ -6448,6 +6630,11 @@ "node": ">= 0.6" } }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, "node_modules/typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", @@ -8011,6 +8198,48 @@ "integrity": "sha512-HBNx4lhkxN7bx6P0++W8E289foSu8kO8GCk2unhuVggO+cE7rh9DhZUyPhUxNRG9m+5B5BTKxZQ5ZP92x/mx9Q==", "dev": true }, + "@types/body-parser": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.1.tgz", + "integrity": "sha512-a6bTJ21vFOGIkwM0kzh9Yr89ziVxq4vYH2fQ6N8AeipEzai/cFK6aGMArIkUeIdRIgpwQa+2bXiLuUJCpSf2Cg==", + "dev": true, + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/express": { + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", + "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", + "dev": true, + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.18", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.17.24", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.24.tgz", + "integrity": "sha512-3UJuW+Qxhzwjq3xhwXm2onQcFHn76frIYVbTu+kn24LFxI+dEhdfISDFovPB8VpEgW8oQCTpRuCe+0zJxB7NEA==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, "@types/graceful-fs": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", @@ -8063,6 +8292,12 @@ "@types/node": "*" } }, + "@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", + "dev": true + }, "@types/mongodb": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-4.0.7.tgz", @@ -8091,6 +8326,15 @@ "@types/mongoose": "5.10.5" } }, + "@types/multer": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.7.tgz", + "integrity": "sha512-/SNsDidUFCvqqcWDwxv2feww/yqhNeTRL5CVoL3jU4Goc4kKEL10T7Eye65ZqPNi4HRx8sAEX59pV1aEH7drNA==", + "dev": true, + "requires": { + "@types/express": "*" + } + }, "@types/node": { "version": "14.17.16", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.16.tgz", @@ -8112,6 +8356,28 @@ "integrity": "sha512-eI5Yrz3Qv4KPUa/nSIAi0h+qX0XyewOliug5F2QAtuRg6Kjg6jfmxe1GIwoIRhZspD1A0RP8ANrPwvEXXtRFog==", "dev": true }, + "@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", + "dev": true + }, + "@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", + "dev": true + }, + "@types/serve-static": { + "version": "1.13.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", + "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", + "dev": true, + "requires": { + "@types/mime": "^1", + "@types/node": "*" + } + }, "@types/stack-utils": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", @@ -8290,6 +8556,11 @@ "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.0.0.tgz", "integrity": "sha512-qMcx+Gy2UZynHjOHOIXPNvpf+9cjvk3cWrBBK7zg4gH9+clobJRb9NGzcT7mQTcV/6Gm/1WelUtqxVXnNlrwcw==" }, + "append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY=" + }, "aproba": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", @@ -8647,6 +8918,15 @@ "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==" }, + "busboy": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", + "integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=", + "requires": { + "dicer": "0.2.5", + "readable-stream": "1.1.x" + } + }, "bytes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", @@ -8815,6 +9095,51 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", @@ -9006,6 +9331,15 @@ "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true }, + "dicer": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", + "integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=", + "requires": { + "readable-stream": "1.1.x", + "streamsearch": "0.1.2" + } + }, "diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", @@ -10830,6 +11164,21 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "multer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.3.tgz", + "integrity": "sha512-np0YLKncuZoTzufbkM6wEKp68EhWJXcU6fq6QqrSwkckd2LlMgd1UqhUJLj6NS/5sZ8dE8LYDWslsltJznnXlg==", + "requires": { + "append-field": "^1.0.0", + "busboy": "^0.2.11", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "on-finished": "^2.3.0", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + } + }, "mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", @@ -11965,6 +12314,11 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" }, + "streamsearch": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", + "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" + }, "string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", @@ -12237,6 +12591,11 @@ "mime-types": "~2.1.24" } }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, "typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", diff --git a/util/package.json b/util/package.json index 751484af..2fa93f9b 100644 --- a/util/package.json +++ b/util/package.json @@ -31,6 +31,7 @@ "@types/amqplib": "^0.8.1", "@types/jsonwebtoken": "^8.5.0", "@types/mongoose-autopopulate": "^0.10.1", + "@types/multer": "^1.4.7", "@types/node": "^14.17.9", "@types/node-fetch": "^2.5.12", "jest": "^27.0.6" @@ -44,6 +45,7 @@ "jsonwebtoken": "^8.5.1", "lambert-server": "^1.2.10", "missing-native-js-functions": "^1.2.15", + "multer": "^1.4.3", "node-fetch": "^2.6.1", "patch-package": "^6.4.7", "pg": "^8.7.1", diff --git a/util/src/entities/Channel.ts b/util/src/entities/Channel.ts index fc954f63..0196fb3e 100644 --- a/util/src/entities/Channel.ts +++ b/util/src/entities/Channel.ts @@ -1,12 +1,26 @@ -import { Column, Entity, JoinColumn, JoinTable, ManyToMany, ManyToOne, OneToMany, RelationId } from "typeorm"; +import { + Column, + Entity, + FindConditions, + JoinColumn, + ManyToOne, + ObjectID, + OneToMany, + RelationId, + RemoveOptions, +} from "typeorm"; import { BaseClass } from "./BaseClass"; import { Guild } from "./Guild"; -import { Message } from "./Message"; import { User } from "./User"; import { HTTPError } from "lambert-server"; import { emitEvent, getPermission, Snowflake } from "../util"; import { ChannelCreateEvent } from "../interfaces"; import { Recipient } from "./Recipient"; +import { Message } from "./Message"; +import { ReadState } from "./ReadState"; +import { Invite } from "./Invite"; +import { VoiceState } from "./VoiceState"; +import { Webhook } from "./Webhook"; export enum ChannelType { GUILD_TEXT = 0, // a text channel within a server @@ -31,20 +45,22 @@ export class Channel extends BaseClass { @Column({ nullable: true }) name?: string; + @Column({ type: "text", nullable: true }) + icon?: string | null; + @Column({ type: "simple-enum", enum: ChannelType }) type: ChannelType; - @OneToMany(() => Recipient, (recipient: Recipient) => recipient.channel, { cascade: true }) + @OneToMany(() => Recipient, (recipient: Recipient) => recipient.channel, { + cascade: true, + orphanedRowAction: "delete", + onDelete: "CASCADE", + }) recipients?: Recipient[]; @Column({ nullable: true }) - @RelationId((channel: Channel) => channel.last_message) last_message_id: string; - @JoinColumn({ name: "last_message_id" }) - @ManyToOne(() => Message) - last_message?: Message; - @Column({ nullable: true }) @RelationId((channel: Channel) => channel.guild) guild_id?: string; @@ -100,6 +116,41 @@ export class Channel extends BaseClass { @Column({ nullable: true }) topic?: string; + @OneToMany(() => Invite, (invite: Invite) => invite.channel, { + cascade: true, + orphanedRowAction: "delete", + onDelete: "CASCADE", + }) + invites?: Invite[]; + + @OneToMany(() => Message, (message: Message) => message.channel, { + cascade: true, + orphanedRowAction: "delete", + onDelete: "CASCADE", + }) + messages?: Message[]; + + @OneToMany(() => VoiceState, (voice_state: VoiceState) => voice_state.channel, { + cascade: true, + orphanedRowAction: "delete", + onDelete: "CASCADE", + }) + voice_states?: VoiceState[]; + + @OneToMany(() => ReadState, (read_state: ReadState) => read_state.channel, { + cascade: true, + orphanedRowAction: "delete", + onDelete: "CASCADE", + }) + read_states?: ReadState[]; + + @OneToMany(() => Webhook, (webhook: Webhook) => webhook.channel, { + cascade: true, + orphanedRowAction: "delete", + onDelete: "CASCADE", + }) + webhooks?: Webhook[]; + // TODO: DM channel static async createChannel( channel: Partial, @@ -162,6 +213,10 @@ export class Channel extends BaseClass { return channel; } + + isDm() { + return this.type === ChannelType.DM || this.type === ChannelType.GROUP_DM; + } } export interface ChannelPermissionOverwrite { diff --git a/util/src/entities/Guild.ts b/util/src/entities/Guild.ts index 7b5d2908..d46d2161 100644 --- a/util/src/entities/Guild.ts +++ b/util/src/entities/Guild.ts @@ -81,7 +81,11 @@ export class Guild extends BaseClass { // application?: string; @JoinColumn({ name: "ban_ids" }) - @OneToMany(() => Ban, (ban: Ban) => ban.guild) + @OneToMany(() => Ban, (ban: Ban) => ban.guild, { + cascade: true, + orphanedRowAction: "delete", + onDelete: "CASCADE", + }) bans: Ban[]; @Column({ nullable: true }) @@ -124,15 +128,27 @@ export class Guild extends BaseClass { @Column({ nullable: true }) presence_count?: number; // users online - @OneToMany(() => Member, (member: Member) => member.guild) + @OneToMany(() => Member, (member: Member) => member.guild, { + cascade: true, + orphanedRowAction: "delete", + onDelete: "CASCADE", + }) members: Member[]; @JoinColumn({ name: "role_ids" }) - @OneToMany(() => Role, (role: Role) => role.guild) + @OneToMany(() => Role, (role: Role) => role.guild, { + cascade: true, + orphanedRowAction: "delete", + onDelete: "CASCADE", + }) roles: Role[]; @JoinColumn({ name: "channel_ids" }) - @OneToMany(() => Channel, (channel: Channel) => channel.guild) + @OneToMany(() => Channel, (channel: Channel) => channel.guild, { + cascade: true, + orphanedRowAction: "delete", + onDelete: "CASCADE", + }) channels: Channel[]; @Column({ nullable: true }) @@ -144,23 +160,43 @@ export class Guild extends BaseClass { template: Template; @JoinColumn({ name: "emoji_ids" }) - @OneToMany(() => Emoji, (emoji: Emoji) => emoji.guild) + @OneToMany(() => Emoji, (emoji: Emoji) => emoji.guild, { + cascade: true, + orphanedRowAction: "delete", + onDelete: "CASCADE", + }) emojis: Emoji[]; @JoinColumn({ name: "sticker_ids" }) - @OneToMany(() => Sticker, (sticker: Sticker) => sticker.guild) + @OneToMany(() => Sticker, (sticker: Sticker) => sticker.guild, { + cascade: true, + orphanedRowAction: "delete", + onDelete: "CASCADE", + }) stickers: Sticker[]; @JoinColumn({ name: "invite_ids" }) - @OneToMany(() => Invite, (invite: Invite) => invite.guild) + @OneToMany(() => Invite, (invite: Invite) => invite.guild, { + cascade: true, + orphanedRowAction: "delete", + onDelete: "CASCADE", + }) invites: Invite[]; @JoinColumn({ name: "voice_state_ids" }) - @OneToMany(() => VoiceState, (voicestate: VoiceState) => voicestate.guild) + @OneToMany(() => VoiceState, (voicestate: VoiceState) => voicestate.guild, { + cascade: true, + orphanedRowAction: "delete", + onDelete: "CASCADE", + }) voice_states: VoiceState[]; @JoinColumn({ name: "webhook_ids" }) - @OneToMany(() => Webhook, (webhook: Webhook) => webhook.guild) + @OneToMany(() => Webhook, (webhook: Webhook) => webhook.guild, { + cascade: true, + orphanedRowAction: "delete", + onDelete: "CASCADE", + }) webhooks: Webhook[]; @Column({ nullable: true }) diff --git a/util/src/entities/Message.ts b/util/src/entities/Message.ts index 506db71a..0712f545 100644 --- a/util/src/entities/Message.ts +++ b/util/src/entities/Message.ts @@ -8,12 +8,14 @@ import { Column, CreateDateColumn, Entity, + FindConditions, JoinColumn, JoinTable, ManyToMany, ManyToOne, OneToMany, RelationId, + RemoveOptions, UpdateDateColumn, } from "typeorm"; import { BaseClass } from "./BaseClass"; @@ -112,7 +114,7 @@ export class Message extends BaseClass { mention_everyone?: boolean; @JoinTable({ name: "message_user_mentions" }) - @ManyToMany(() => User) + @ManyToMany(() => User, { orphanedRowAction: "delete", onDelete: "CASCADE", cascade: true }) mentions: User[]; @JoinTable({ name: "message_role_mentions" }) @@ -127,8 +129,11 @@ export class Message extends BaseClass { @ManyToMany(() => Sticker) sticker_items?: Sticker[]; - @JoinColumn({ name: "attachment_ids" }) - @OneToMany(() => Attachment, (attachment: Attachment) => attachment.message, { cascade: true }) + @OneToMany(() => Attachment, (attachment: Attachment) => attachment.message, { + cascade: true, + orphanedRowAction: "delete", + onDelete: "CASCADE", + }) attachments?: Attachment[]; @Column({ type: "simple-json" }) diff --git a/util/src/util/cdn.ts b/util/src/util/cdn.ts new file mode 100644 index 00000000..754d6244 --- /dev/null +++ b/util/src/util/cdn.ts @@ -0,0 +1,54 @@ +import FormData from "form-data"; +import { HTTPError } from "lambert-server"; +import fetch from "node-fetch"; +import { Config } from "./Config"; +import multer from "multer"; + +export async function uploadFile(path: string, file: Express.Multer.File) { + const form = new FormData(); + form.append("file", file.buffer, { + contentType: file.mimetype, + filename: file.originalname, + }); + + const response = await fetch(`${Config.get().cdn.endpoint || "http://localhost:3003"}${path}`, { + headers: { + signature: Config.get().security.requestSignature, + ...form.getHeaders(), + }, + method: "POST", + body: form, + }); + const result = await response.json(); + + if (response.status !== 200) throw result; + return result; +} + +export async function handleFile(path: string, body?: string): Promise { + if (!body || !body.startsWith("data:")) return body; + try { + const mimetype = body.split(":")[1].split(";")[0]; + const buffer = Buffer.from(body.split(",")[1], "base64"); + + // @ts-ignore + const { id } = await uploadFile(path, { buffer, mimetype, originalname: "banner" }); + return id; + } catch (error) { + console.error(error); + throw new HTTPError("Invalid " + path); + } +} + +export async function deleteFile(path: string) { + const response = await fetch(`${Config.get().cdn.endpoint || "http://localhost:3003"}${path}`, { + headers: { + signature: Config.get().security.requestSignature, + }, + method: "DELETE", + }); + const result = await response.json(); + + if (response.status !== 200) throw result; + return result; +} diff --git a/util/src/util/index.ts b/util/src/util/index.ts index 4e92f017..1ae96da9 100644 --- a/util/src/util/index.ts +++ b/util/src/util/index.ts @@ -1,6 +1,7 @@ export * from "./ApiError"; export * from "./BitField"; export * from "./checkToken"; +export * from "./cdn"; export * from "./Config"; export * from "./Constants"; export * from "./Database"; -- cgit 1.5.1 From 9ae19d8e0628aa6d1dcd8bbb184a280812040b98 Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Sun, 19 Sep 2021 19:05:26 +0200 Subject: :truck: move file handle to utility --- bundle/package-lock.json | 8 +- cdn/package-lock.json | 1 + gateway/package-lock.json | 1 + util/package-lock.json | 359 ++++++++++++++++++++++++++++++++++++++++++++++ util/package.json | 2 + util/src/util/cdn.ts | 54 +++++++ util/src/util/index.ts | 1 + 7 files changed, 422 insertions(+), 4 deletions(-) create mode 100644 util/src/util/cdn.ts (limited to 'util/src') diff --git a/bundle/package-lock.json b/bundle/package-lock.json index 3199f7d8..f2dd7bee 100644 --- a/bundle/package-lock.json +++ b/bundle/package-lock.json @@ -48,6 +48,7 @@ "license": "ISC", "dependencies": { "@fosscord/util": "file:../util", + "@types/morgan": "^1.9.3", "ajv": "8.6.2", "ajv-formats": "^2.1.1", "amqplib": "^0.8.0", @@ -71,6 +72,7 @@ "mongoose": "^5.12.3", "mongoose-autopopulate": "^0.12.3", "mongoose-long": "^0.3.2", + "morgan": "^1.10.0", "multer": "^1.4.2", "node-fetch": "^2.6.1", "patch-package": "^6.4.7", @@ -193,7 +195,6 @@ "jsonwebtoken": "^8.5.1", "lambert-server": "^1.2.10", "missing-native-js-functions": "^1.2.15", - "multer": "^1.4.3", "node-fetch": "^2.6.1", "patch-package": "^6.4.7", "pg": "^8.7.1", @@ -208,7 +209,6 @@ "@types/amqplib": "^0.8.1", "@types/jsonwebtoken": "^8.5.0", "@types/mongoose-autopopulate": "^0.10.1", - "@types/multer": "^1.4.7", "@types/node": "^14.17.9", "@types/node-fetch": "^2.5.12", "jest": "^27.0.6" @@ -1392,6 +1392,7 @@ "@types/mongoose": "^5.10.5", "@types/mongoose-autopopulate": "^0.10.1", "@types/mongoose-lean-virtuals": "^0.5.1", + "@types/morgan": "^1.9.3", "@types/multer": "^1.4.5", "@types/node": "^14.17.9", "@types/node-fetch": "^2.5.7", @@ -1423,6 +1424,7 @@ "mongoose": "^5.12.3", "mongoose-autopopulate": "^0.12.3", "mongoose-long": "^0.3.2", + "morgan": "^1.10.0", "multer": "^1.4.2", "node-fetch": "^2.6.1", "patch-package": "^6.4.7", @@ -1509,7 +1511,6 @@ "@types/amqplib": "^0.8.1", "@types/jsonwebtoken": "^8.5.0", "@types/mongoose-autopopulate": "^0.10.1", - "@types/multer": "^1.4.7", "@types/node": "^14.17.9", "@types/node-fetch": "^2.5.12", "ajv": "^8.6.2", @@ -1521,7 +1522,6 @@ "jsonwebtoken": "^8.5.1", "lambert-server": "^1.2.10", "missing-native-js-functions": "^1.2.15", - "multer": "^1.4.3", "node-fetch": "^2.6.1", "patch-package": "^6.4.7", "pg": "^8.7.1", diff --git a/cdn/package-lock.json b/cdn/package-lock.json index 7a4edd89..8a2346f4 100644 --- a/cdn/package-lock.json +++ b/cdn/package-lock.json @@ -48,6 +48,7 @@ } }, "../util": { + "name": "@fosscord/util", "version": "1.0.0", "hasInstallScript": true, "license": "GPLV3", diff --git a/gateway/package-lock.json b/gateway/package-lock.json index 40db319d..ae6009db 100644 --- a/gateway/package-lock.json +++ b/gateway/package-lock.json @@ -37,6 +37,7 @@ } }, "../util": { + "name": "@fosscord/util", "version": "1.0.0", "hasInstallScript": true, "license": "GPLV3", diff --git a/util/package-lock.json b/util/package-lock.json index 4b0f1f15..e5a62d0f 100644 --- a/util/package-lock.json +++ b/util/package-lock.json @@ -18,6 +18,7 @@ "jsonwebtoken": "^8.5.1", "lambert-server": "^1.2.10", "missing-native-js-functions": "^1.2.15", + "multer": "^1.4.3", "node-fetch": "^2.6.1", "patch-package": "^6.4.7", "pg": "^8.7.1", @@ -32,6 +33,7 @@ "@types/amqplib": "^0.8.1", "@types/jsonwebtoken": "^8.5.0", "@types/mongoose-autopopulate": "^0.10.1", + "@types/multer": "^1.4.7", "@types/node": "^14.17.9", "@types/node-fetch": "^2.5.12", "jest": "^27.0.6" @@ -1063,6 +1065,48 @@ "integrity": "sha512-HBNx4lhkxN7bx6P0++W8E289foSu8kO8GCk2unhuVggO+cE7rh9DhZUyPhUxNRG9m+5B5BTKxZQ5ZP92x/mx9Q==", "dev": true }, + "node_modules/@types/body-parser": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.1.tgz", + "integrity": "sha512-a6bTJ21vFOGIkwM0kzh9Yr89ziVxq4vYH2fQ6N8AeipEzai/cFK6aGMArIkUeIdRIgpwQa+2bXiLuUJCpSf2Cg==", + "dev": true, + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", + "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", + "dev": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.18", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.17.24", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.24.tgz", + "integrity": "sha512-3UJuW+Qxhzwjq3xhwXm2onQcFHn76frIYVbTu+kn24LFxI+dEhdfISDFovPB8VpEgW8oQCTpRuCe+0zJxB7NEA==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, "node_modules/@types/graceful-fs": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", @@ -1115,6 +1159,12 @@ "@types/node": "*" } }, + "node_modules/@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", + "dev": true + }, "node_modules/@types/mongodb": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-4.0.7.tgz", @@ -1144,6 +1194,15 @@ "@types/mongoose": "5.10.5" } }, + "node_modules/@types/multer": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.7.tgz", + "integrity": "sha512-/SNsDidUFCvqqcWDwxv2feww/yqhNeTRL5CVoL3jU4Goc4kKEL10T7Eye65ZqPNi4HRx8sAEX59pV1aEH7drNA==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, "node_modules/@types/node": { "version": "14.17.16", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.16.tgz", @@ -1165,6 +1224,28 @@ "integrity": "sha512-eI5Yrz3Qv4KPUa/nSIAi0h+qX0XyewOliug5F2QAtuRg6Kjg6jfmxe1GIwoIRhZspD1A0RP8ANrPwvEXXtRFog==", "dev": true }, + "node_modules/@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", + "dev": true + }, + "node_modules/@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", + "dev": true + }, + "node_modules/@types/serve-static": { + "version": "1.13.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", + "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", + "dev": true, + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, "node_modules/@types/stack-utils": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", @@ -1396,6 +1477,11 @@ "node": ">= 6.0.0" } }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY=" + }, "node_modules/aproba": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", @@ -1816,6 +1902,18 @@ "node": ">=4" } }, + "node_modules/busboy": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", + "integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=", + "dependencies": { + "dicer": "0.2.5", + "readable-stream": "1.1.x" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/bytes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", @@ -2028,6 +2126,52 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/concat-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/concat-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", @@ -2258,6 +2402,18 @@ "node": ">=8" } }, + "node_modules/dicer": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", + "integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=", + "dependencies": { + "readable-stream": "1.1.x", + "streamsearch": "0.1.2" + }, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", @@ -4619,6 +4775,24 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "node_modules/multer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.3.tgz", + "integrity": "sha512-np0YLKncuZoTzufbkM6wEKp68EhWJXcU6fq6QqrSwkckd2LlMgd1UqhUJLj6NS/5sZ8dE8LYDWslsltJznnXlg==", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^0.2.11", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "on-finished": "^2.3.0", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 0.10.0" + } + }, "node_modules/mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", @@ -6095,6 +6269,14 @@ "node": ">= 0.6" } }, + "node_modules/streamsearch": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", + "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=", + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", @@ -6448,6 +6630,11 @@ "node": ">= 0.6" } }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, "node_modules/typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", @@ -8011,6 +8198,48 @@ "integrity": "sha512-HBNx4lhkxN7bx6P0++W8E289foSu8kO8GCk2unhuVggO+cE7rh9DhZUyPhUxNRG9m+5B5BTKxZQ5ZP92x/mx9Q==", "dev": true }, + "@types/body-parser": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.1.tgz", + "integrity": "sha512-a6bTJ21vFOGIkwM0kzh9Yr89ziVxq4vYH2fQ6N8AeipEzai/cFK6aGMArIkUeIdRIgpwQa+2bXiLuUJCpSf2Cg==", + "dev": true, + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/express": { + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", + "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", + "dev": true, + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.18", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.17.24", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.24.tgz", + "integrity": "sha512-3UJuW+Qxhzwjq3xhwXm2onQcFHn76frIYVbTu+kn24LFxI+dEhdfISDFovPB8VpEgW8oQCTpRuCe+0zJxB7NEA==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*" + } + }, "@types/graceful-fs": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", @@ -8063,6 +8292,12 @@ "@types/node": "*" } }, + "@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", + "dev": true + }, "@types/mongodb": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-4.0.7.tgz", @@ -8091,6 +8326,15 @@ "@types/mongoose": "5.10.5" } }, + "@types/multer": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.7.tgz", + "integrity": "sha512-/SNsDidUFCvqqcWDwxv2feww/yqhNeTRL5CVoL3jU4Goc4kKEL10T7Eye65ZqPNi4HRx8sAEX59pV1aEH7drNA==", + "dev": true, + "requires": { + "@types/express": "*" + } + }, "@types/node": { "version": "14.17.16", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.16.tgz", @@ -8112,6 +8356,28 @@ "integrity": "sha512-eI5Yrz3Qv4KPUa/nSIAi0h+qX0XyewOliug5F2QAtuRg6Kjg6jfmxe1GIwoIRhZspD1A0RP8ANrPwvEXXtRFog==", "dev": true }, + "@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", + "dev": true + }, + "@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", + "dev": true + }, + "@types/serve-static": { + "version": "1.13.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", + "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", + "dev": true, + "requires": { + "@types/mime": "^1", + "@types/node": "*" + } + }, "@types/stack-utils": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", @@ -8290,6 +8556,11 @@ "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.0.0.tgz", "integrity": "sha512-qMcx+Gy2UZynHjOHOIXPNvpf+9cjvk3cWrBBK7zg4gH9+clobJRb9NGzcT7mQTcV/6Gm/1WelUtqxVXnNlrwcw==" }, + "append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY=" + }, "aproba": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", @@ -8647,6 +8918,15 @@ "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==" }, + "busboy": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", + "integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=", + "requires": { + "dicer": "0.2.5", + "readable-stream": "1.1.x" + } + }, "bytes": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", @@ -8815,6 +9095,51 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", @@ -9006,6 +9331,15 @@ "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true }, + "dicer": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", + "integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=", + "requires": { + "readable-stream": "1.1.x", + "streamsearch": "0.1.2" + } + }, "diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", @@ -10830,6 +11164,21 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "multer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.3.tgz", + "integrity": "sha512-np0YLKncuZoTzufbkM6wEKp68EhWJXcU6fq6QqrSwkckd2LlMgd1UqhUJLj6NS/5sZ8dE8LYDWslsltJznnXlg==", + "requires": { + "append-field": "^1.0.0", + "busboy": "^0.2.11", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "on-finished": "^2.3.0", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + } + }, "mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", @@ -11965,6 +12314,11 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" }, + "streamsearch": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", + "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" + }, "string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", @@ -12237,6 +12591,11 @@ "mime-types": "~2.1.24" } }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, "typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", diff --git a/util/package.json b/util/package.json index 751484af..2fa93f9b 100644 --- a/util/package.json +++ b/util/package.json @@ -31,6 +31,7 @@ "@types/amqplib": "^0.8.1", "@types/jsonwebtoken": "^8.5.0", "@types/mongoose-autopopulate": "^0.10.1", + "@types/multer": "^1.4.7", "@types/node": "^14.17.9", "@types/node-fetch": "^2.5.12", "jest": "^27.0.6" @@ -44,6 +45,7 @@ "jsonwebtoken": "^8.5.1", "lambert-server": "^1.2.10", "missing-native-js-functions": "^1.2.15", + "multer": "^1.4.3", "node-fetch": "^2.6.1", "patch-package": "^6.4.7", "pg": "^8.7.1", diff --git a/util/src/util/cdn.ts b/util/src/util/cdn.ts new file mode 100644 index 00000000..754d6244 --- /dev/null +++ b/util/src/util/cdn.ts @@ -0,0 +1,54 @@ +import FormData from "form-data"; +import { HTTPError } from "lambert-server"; +import fetch from "node-fetch"; +import { Config } from "./Config"; +import multer from "multer"; + +export async function uploadFile(path: string, file: Express.Multer.File) { + const form = new FormData(); + form.append("file", file.buffer, { + contentType: file.mimetype, + filename: file.originalname, + }); + + const response = await fetch(`${Config.get().cdn.endpoint || "http://localhost:3003"}${path}`, { + headers: { + signature: Config.get().security.requestSignature, + ...form.getHeaders(), + }, + method: "POST", + body: form, + }); + const result = await response.json(); + + if (response.status !== 200) throw result; + return result; +} + +export async function handleFile(path: string, body?: string): Promise { + if (!body || !body.startsWith("data:")) return body; + try { + const mimetype = body.split(":")[1].split(";")[0]; + const buffer = Buffer.from(body.split(",")[1], "base64"); + + // @ts-ignore + const { id } = await uploadFile(path, { buffer, mimetype, originalname: "banner" }); + return id; + } catch (error) { + console.error(error); + throw new HTTPError("Invalid " + path); + } +} + +export async function deleteFile(path: string) { + const response = await fetch(`${Config.get().cdn.endpoint || "http://localhost:3003"}${path}`, { + headers: { + signature: Config.get().security.requestSignature, + }, + method: "DELETE", + }); + const result = await response.json(); + + if (response.status !== 200) throw result; + return result; +} diff --git a/util/src/util/index.ts b/util/src/util/index.ts index 2de26fc7..3160380f 100644 --- a/util/src/util/index.ts +++ b/util/src/util/index.ts @@ -1,6 +1,7 @@ export * from "./ApiError"; export * from "./BitField"; export * from "./checkToken"; +export * from "./cdn"; export * from "./Config"; export * from "./Constants"; export * from "./Database"; -- cgit 1.5.1 From e22ea776250381ab375de13a4e7eab9c16443935 Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Mon, 20 Sep 2021 17:11:22 +0200 Subject: :construction: auto delete relations --- api/src/routes/channels/#channel_id/index.ts | 20 ++++-- util/package-lock.json | 98 ++++++++++++++-------------- util/src/entities/BaseClass.ts | 49 +++++++++++++- util/src/entities/Channel.ts | 12 +--- util/src/util/Database.ts | 2 +- 5 files changed, 112 insertions(+), 69 deletions(-) (limited to 'util/src') diff --git a/api/src/routes/channels/#channel_id/index.ts b/api/src/routes/channels/#channel_id/index.ts index 3f434f5e..1063b151 100644 --- a/api/src/routes/channels/#channel_id/index.ts +++ b/api/src/routes/channels/#channel_id/index.ts @@ -1,6 +1,15 @@ -import { Channel, ChannelDeleteEvent, ChannelPermissionOverwriteType, ChannelType, ChannelUpdateEvent, emitEvent, Recipient } from "@fosscord/util"; +import { + Channel, + ChannelDeleteEvent, + ChannelPermissionOverwriteType, + ChannelType, + ChannelUpdateEvent, + emitEvent, + Recipient, + handleFile +} from "@fosscord/util"; import { Request, Response, Router } from "express"; -import { handleFile, route } from "@fosscord/api"; +import { route } from "@fosscord/api"; const router: Router = Router(); // TODO: delete channel @@ -20,15 +29,14 @@ router.delete("/", route({ permission: "MANAGE_CHANNELS" }), async (req: Request const channel = await Channel.findOneOrFail({ where: { id: channel_id }, relations: ["recipients"] }); if (channel.type === ChannelType.DM) { - const recipient = await Recipient.findOneOrFail({ where: { channel_id: channel_id, user_id: req.user_id } }) - recipient.closed = true + const recipient = await Recipient.findOneOrFail({ where: { channel_id: channel_id, user_id: req.user_id } }); + recipient.closed = true; await Promise.all([ recipient.save(), emitEvent({ event: "CHANNEL_DELETE", data: channel, user_id: req.user_id } as ChannelDeleteEvent) ]); - } else if (channel.type === ChannelType.GROUP_DM) { - await Channel.removeRecipientFromChannel(channel, req.user_id) + await Channel.removeRecipientFromChannel(channel, req.user_id); } else { //TODO messages in this channel should be deleted before deleting the channel await Promise.all([ diff --git a/util/package-lock.json b/util/package-lock.json index e5a62d0f..f4129614 100644 --- a/util/package-lock.json +++ b/util/package-lock.json @@ -226,19 +226,19 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.4.tgz", - "integrity": "sha512-9fHHSGE9zTC++KuXLZcB5FKgvlV83Ox+NLUmQTawovwlJ85+QMhk1CnVk406CQVj97LaWod6KVjl2Sfgw9Aktw==", + "version": "7.15.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.7.tgz", + "integrity": "sha512-ZNqjjQG/AuFfekFTY+7nY4RgBSklgTu970c7Rj3m/JOhIu5KPBUuTA9AY6zaKcUvk4g6EbDXdBnhi35FAssdSw==", "dev": true, "dependencies": { "@babel/helper-module-imports": "^7.15.4", "@babel/helper-replace-supers": "^7.15.4", "@babel/helper-simple-access": "^7.15.4", "@babel/helper-split-export-declaration": "^7.15.4", - "@babel/helper-validator-identifier": "^7.14.9", + "@babel/helper-validator-identifier": "^7.15.7", "@babel/template": "^7.15.4", "@babel/traverse": "^7.15.4", - "@babel/types": "^7.15.4" + "@babel/types": "^7.15.6" }, "engines": { "node": ">=6.9.0" @@ -305,9 +305,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz", - "integrity": "sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==", + "version": "7.15.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz", + "integrity": "sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==", "dev": true, "engines": { "node": ">=6.9.0" @@ -422,9 +422,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.15.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.6.tgz", - "integrity": "sha512-S/TSCcsRuCkmpUuoWijua0Snt+f3ewU/8spLo+4AXJCZfT0bVCzLD5MuOKdrx0mlAptbKzn5AdgEIIKXxXkz9Q==", + "version": "7.15.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.7.tgz", + "integrity": "sha512-rycZXvQ+xS9QyIcJ9HXeDWf1uxqlbVFAUq0Rq0dbc50Zb/+wUe/ehyfzGfm9KZZF0kBejYgxltBXocP+gKdL2g==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -1204,9 +1204,9 @@ } }, "node_modules/@types/node": { - "version": "14.17.16", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.16.tgz", - "integrity": "sha512-WiFf2izl01P1CpeY8WqFAeKWwByMueBEkND38EcN8N68qb0aDG3oIS1P5MhAX5kUdr469qRyqsY/MjanLjsFbQ==" + "version": "14.17.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.17.tgz", + "integrity": "sha512-niAjcewgEYvSPCZm3OaM9y6YQrL2SEPH9PymtE6fuZAvFiP6ereCcvApGl2jKTq7copTIguX3PBvfP08LN4LvQ==" }, "node_modules/@types/node-fetch": { "version": "2.5.12", @@ -1941,9 +1941,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001257", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001257.tgz", - "integrity": "sha512-JN49KplOgHSXpIsVSF+LUyhD8PUp6xPpAXeRrrcBh4KBeP7W864jHn6RvzJgDlrReyeVjMFJL3PLpPvKIxlIHA==", + "version": "1.0.30001258", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001258.tgz", + "integrity": "sha512-RBByOG6xWXUp0CR2/WU2amXz3stjKpSl5J1xU49F1n2OxD//uBZO4wCKUiG+QMGf7CHGfDDcqoKriomoGVxTeA==", "dev": true, "funding": { "type": "opencollective", @@ -2498,9 +2498,9 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "node_modules/electron-to-chromium": { - "version": "1.3.840", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.840.tgz", - "integrity": "sha512-yRoUmTLDJnkIJx23xLY7GbSvnmDCq++NSuxHDQ0jiyDJ9YZBUGJcrdUqm+ZwZFzMbCciVzfem2N2AWiHJcWlbw==", + "version": "1.3.843", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.843.tgz", + "integrity": "sha512-OWEwAbzaVd1Lk9MohVw8LxMXFlnYd9oYTYxfX8KS++kLLjDfbovLOcEEXwRhG612dqGQ6+44SZvim0GXuBRiKg==", "dev": true }, "node_modules/emittery": { @@ -6249,13 +6249,12 @@ } }, "node_modules/stack-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.4.tgz", - "integrity": "sha512-ERg+H//lSSYlZhBIUu+wJnqg30AbyBbpZlIhcshpn7BNzpoRODZgfyr9J+8ERf3ooC6af3u7Lcl01nleau7MrA==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", "dev": true, "dependencies": { - "escape-string-regexp": "^2.0.0", - "source-map-support": "^0.5.20" + "escape-string-regexp": "^2.0.0" }, "engines": { "node": ">=10" @@ -7535,19 +7534,19 @@ } }, "@babel/helper-module-transforms": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.4.tgz", - "integrity": "sha512-9fHHSGE9zTC++KuXLZcB5FKgvlV83Ox+NLUmQTawovwlJ85+QMhk1CnVk406CQVj97LaWod6KVjl2Sfgw9Aktw==", + "version": "7.15.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.7.tgz", + "integrity": "sha512-ZNqjjQG/AuFfekFTY+7nY4RgBSklgTu970c7Rj3m/JOhIu5KPBUuTA9AY6zaKcUvk4g6EbDXdBnhi35FAssdSw==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.15.4", "@babel/helper-replace-supers": "^7.15.4", "@babel/helper-simple-access": "^7.15.4", "@babel/helper-split-export-declaration": "^7.15.4", - "@babel/helper-validator-identifier": "^7.14.9", + "@babel/helper-validator-identifier": "^7.15.7", "@babel/template": "^7.15.4", "@babel/traverse": "^7.15.4", - "@babel/types": "^7.15.4" + "@babel/types": "^7.15.6" } }, "@babel/helper-optimise-call-expression": { @@ -7596,9 +7595,9 @@ } }, "@babel/helper-validator-identifier": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz", - "integrity": "sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==", + "version": "7.15.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz", + "integrity": "sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==", "dev": true }, "@babel/helper-validator-option": { @@ -7688,9 +7687,9 @@ } }, "@babel/parser": { - "version": "7.15.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.6.tgz", - "integrity": "sha512-S/TSCcsRuCkmpUuoWijua0Snt+f3ewU/8spLo+4AXJCZfT0bVCzLD5MuOKdrx0mlAptbKzn5AdgEIIKXxXkz9Q==", + "version": "7.15.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.7.tgz", + "integrity": "sha512-rycZXvQ+xS9QyIcJ9HXeDWf1uxqlbVFAUq0Rq0dbc50Zb/+wUe/ehyfzGfm9KZZF0kBejYgxltBXocP+gKdL2g==", "dev": true }, "@babel/plugin-syntax-async-generators": { @@ -8336,9 +8335,9 @@ } }, "@types/node": { - "version": "14.17.16", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.16.tgz", - "integrity": "sha512-WiFf2izl01P1CpeY8WqFAeKWwByMueBEkND38EcN8N68qb0aDG3oIS1P5MhAX5kUdr469qRyqsY/MjanLjsFbQ==" + "version": "14.17.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.17.tgz", + "integrity": "sha512-niAjcewgEYvSPCZm3OaM9y6YQrL2SEPH9PymtE6fuZAvFiP6ereCcvApGl2jKTq7copTIguX3PBvfP08LN4LvQ==" }, "@types/node-fetch": { "version": "2.5.12", @@ -8945,9 +8944,9 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30001257", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001257.tgz", - "integrity": "sha512-JN49KplOgHSXpIsVSF+LUyhD8PUp6xPpAXeRrrcBh4KBeP7W864jHn6RvzJgDlrReyeVjMFJL3PLpPvKIxlIHA==", + "version": "1.0.30001258", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001258.tgz", + "integrity": "sha512-RBByOG6xWXUp0CR2/WU2amXz3stjKpSl5J1xU49F1n2OxD//uBZO4wCKUiG+QMGf7CHGfDDcqoKriomoGVxTeA==", "dev": true }, "caseless": { @@ -9405,9 +9404,9 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "electron-to-chromium": { - "version": "1.3.840", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.840.tgz", - "integrity": "sha512-yRoUmTLDJnkIJx23xLY7GbSvnmDCq++NSuxHDQ0jiyDJ9YZBUGJcrdUqm+ZwZFzMbCciVzfem2N2AWiHJcWlbw==", + "version": "1.3.843", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.843.tgz", + "integrity": "sha512-OWEwAbzaVd1Lk9MohVw8LxMXFlnYd9oYTYxfX8KS++kLLjDfbovLOcEEXwRhG612dqGQ6+44SZvim0GXuBRiKg==", "dev": true }, "emittery": { @@ -12300,13 +12299,12 @@ } }, "stack-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.4.tgz", - "integrity": "sha512-ERg+H//lSSYlZhBIUu+wJnqg30AbyBbpZlIhcshpn7BNzpoRODZgfyr9J+8ERf3ooC6af3u7Lcl01nleau7MrA==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", "dev": true, "requires": { - "escape-string-regexp": "^2.0.0", - "source-map-support": "^0.5.20" + "escape-string-regexp": "^2.0.0" } }, "statuses": { diff --git a/util/src/entities/BaseClass.ts b/util/src/entities/BaseClass.ts index 9b2ce058..2a621f40 100644 --- a/util/src/entities/BaseClass.ts +++ b/util/src/entities/BaseClass.ts @@ -1,5 +1,14 @@ import "reflect-metadata"; -import { BaseEntity, BeforeInsert, BeforeUpdate, EntityMetadata, FindConditions, PrimaryColumn } from "typeorm"; +import { + BaseEntity, + BeforeInsert, + BeforeUpdate, + EntityMetadata, + FindConditions, + getConnection, + PrimaryColumn, + RemoveOptions, +} from "typeorm"; import { Snowflake } from "../util/Snowflake"; import "missing-native-js-functions"; @@ -69,6 +78,44 @@ export class BaseClassWithoutId extends BaseEntity { const repository = this.getRepository(); return repository.decrement(conditions, propertyPath, value); } + + static async delete(criteria: FindConditions, options?: RemoveOptions) { + if (!criteria) throw new Error("You need to specify delete criteria"); + + const repository = this.getRepository(); + const promises = repository.metadata.relations.map((x) => { + if (x.orphanedRowAction !== "delete") return; + if (typeof x.type === "string") return; + + const foreignKey = + x.foreignKeys.find((key) => key.entityMetadata === repository.metadata) || + x.inverseRelation?.foreignKeys[0]; // find foreign key for this entity + if (!foreignKey) { + throw new Error( + `Foreign key not found for entity ${repository.metadata.name} in relation ${x.propertyName}` + ); + } + console.log(foreignKey); + const id = (criteria as any)[foreignKey.referencedColumnNames[0]]; + if (!id) throw new Error("id missing in criteria options"); + + if (x.relationType === "many-to-many" || x.relationType === "one-to-many") { + return getConnection() + .createQueryBuilder() + .relation(this, x.propertyName) + .of(id) + .remove({ [foreignKey.columnNames[0]]: id }); + } else if (x.relationType === "one-to-one" || x.relationType === "many-to-one") { + return getConnection() + .createQueryBuilder() + .from(x.inverseEntityMetadata, "user") + .of(id) + .remove({ [foreignKey.name]: id }); + } + }); + await Promise.all(promises); + return super.delete(criteria, options); + } } export class BaseClass extends BaseClassWithoutId { diff --git a/util/src/entities/Channel.ts b/util/src/entities/Channel.ts index b1f75f33..74611eea 100644 --- a/util/src/entities/Channel.ts +++ b/util/src/entities/Channel.ts @@ -1,14 +1,4 @@ -import { - Column, - Entity, - FindConditions, - JoinColumn, - ManyToOne, - ObjectID, - OneToMany, - RelationId, - RemoveOptions, -} from "typeorm"; +import { Column, Entity, JoinColumn, ManyToOne, OneToMany, RelationId } from "typeorm"; import { BaseClass } from "./BaseClass"; import { Guild } from "./Guild"; import { PublicUserProjection, User } from "./User"; diff --git a/util/src/util/Database.ts b/util/src/util/Database.ts index d3844cd9..c22d8abd 100644 --- a/util/src/util/Database.ts +++ b/util/src/util/Database.ts @@ -21,7 +21,7 @@ export function initDatabase() { // entities: Object.values(Models).filter((x) => x.constructor.name !== "Object"), synchronize: true, - logging: false, + logging: true, cache: { duration: 1000 * 3, // cache all find queries for 3 seconds }, -- cgit 1.5.1 From 269bbdfeae9672e17f0dbd02172e925fc16eb904 Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Mon, 20 Sep 2021 17:38:16 +0200 Subject: :sparkles: accept invite page --- api/assets/schemas.json | 1 - api/client_test/index.html | 2 +- api/src/middlewares/TestClient.ts | 2 ++ api/src/routes/auth/register.ts | 36 ++++++++++++++++++++++-------------- api/src/routes/invites/index.ts | 9 ++------- util/src/entities/Config.ts | 10 ++++++---- util/src/entities/Invite.ts | 10 ++++++++++ 7 files changed, 43 insertions(+), 27 deletions(-) (limited to 'util/src') diff --git a/api/assets/schemas.json b/api/assets/schemas.json index bfe6092b..da193b28 100644 --- a/api/assets/schemas.json +++ b/api/assets/schemas.json @@ -38,7 +38,6 @@ "additionalProperties": false, "required": [ "consent", - "password", "username" ], "$schema": "http://json-schema.org/draft-07/schema#" diff --git a/api/client_test/index.html b/api/client_test/index.html index 9a0aeae1..ebe92e4c 100644 --- a/api/client_test/index.html +++ b/api/client_test/index.html @@ -19,7 +19,7 @@ ASSET_ENDPOINT: "", MEDIA_PROXY_ENDPOINT: "https://media.discordapp.net", WIDGET_ENDPOINT: `//${location.host}/widget`, - INVITE_HOST: `${location.hostname}`, + INVITE_HOST: `${location.host}/invite`, GUILD_TEMPLATE_HOST: "discord.new", GIFT_CODE_HOST: "discord.gift", RELEASE_CHANNEL: "stable", diff --git a/api/src/middlewares/TestClient.ts b/api/src/middlewares/TestClient.ts index 73e7b9c2..79f8f442 100644 --- a/api/src/middlewares/TestClient.ts +++ b/api/src/middlewares/TestClient.ts @@ -67,6 +67,8 @@ export default function TestClient(app: Application) { res.set("Cache-Control", "public, max-age=" + 60 * 60 * 24); res.set("content-type", "text/html"); + if (req.url.startsWith("/invite")) return res.send(html.replace("9b2b7f0632acd0c5e781", "9f24f709a3de09b67c49")); + res.send(html); }); } diff --git a/api/src/routes/auth/register.ts b/api/src/routes/auth/register.ts index c0b0e18a..4d3f2860 100644 --- a/api/src/routes/auth/register.ts +++ b/api/src/routes/auth/register.ts @@ -1,5 +1,5 @@ import { Request, Response, Router } from "express"; -import { trimSpecial, User, Snowflake, Config, defaultSettings } from "@fosscord/util"; +import { trimSpecial, User, Snowflake, Config, defaultSettings, Member, Invite } from "@fosscord/util"; import bcrypt from "bcrypt"; import { EMAIL_REGEX, FieldErrors, route } from "@fosscord/api"; import "missing-native-js-functions"; @@ -19,7 +19,7 @@ export interface RegisterSchema { * @minLength 1 * @maxLength 72 */ - password: string; // TODO: use password strength of config + password?: string; consent: boolean; /** * @TJS-format email @@ -60,7 +60,6 @@ router.post("/", route({ body: "RegisterSchema" }), async (req: Request, res: Re } console.log("register", req.body.email, req.body.username, ip); - // TODO: automatically join invite // TODO: gift_code_sku_id? // TODO: check password strength @@ -87,13 +86,6 @@ router.post("/", route({ body: "RegisterSchema" }), async (req: Request, res: Re }); } - // require invite to register -> e.g. for organizations to send invites to their employees - if (register.requireInvite && !invite) { - throw FieldErrors({ - email: { code: "INVITE_ONLY", message: req.t("auth:register.INVITE_ONLY") } - }); - } - if (email) { // replace all dots and chars after +, if its a gmail.com email if (!email) throw FieldErrors({ email: { code: "INVALID_EMAIL", message: req.t("auth:register.INVALID_EMAIL") } }); @@ -109,13 +101,13 @@ router.post("/", route({ body: "RegisterSchema" }), async (req: Request, res: Re } }); } - } else if (register.email.necessary) { + } else if (register.email.required) { throw FieldErrors({ email: { code: "BASE_TYPE_REQUIRED", message: req.t("common:field.BASE_TYPE_REQUIRED") } }); } - if (register.dateOfBirth.necessary && !date_of_birth) { + if (register.dateOfBirth.required && !date_of_birth) { throw FieldErrors({ date_of_birth: { code: "BASE_TYPE_REQUIRED", message: req.t("common:field.BASE_TYPE_REQUIRED") } }); @@ -162,8 +154,14 @@ router.post("/", route({ body: "RegisterSchema" }), async (req: Request, res: Re // TODO: check captcha } - // the salt is saved in the password refer to bcrypt docs - password = await bcrypt.hash(password, 12); + if (password) { + // the salt is saved in the password refer to bcrypt docs + password = await bcrypt.hash(password, 12); + } else if (register.password.required) { + throw FieldErrors({ + password: { code: "BASE_TYPE_REQUIRED", message: req.t("common:field.BASE_TYPE_REQUIRED") } + }); + } let exists; // randomly generates a discriminator between 1 and 9999 and checks max five times if it already exists @@ -217,6 +215,16 @@ router.post("/", route({ body: "RegisterSchema" }), async (req: Request, res: Re fingerprints: [] }).save(); + if (invite) { + // await to fail if the invite doesn't exist (necessary for requireInvite to work properly) (username only signups are possible) + await Invite.joinGuild(user.id, invite); + } else if (register.requireInvite) { + // require invite to register -> e.g. for organizations to send invites to their employees + throw FieldErrors({ + email: { code: "INVITE_ONLY", message: req.t("auth:register.INVITE_ONLY") } + }); + } + return res.json({ token: await generateToken(user.id) }); }); diff --git a/api/src/routes/invites/index.ts b/api/src/routes/invites/index.ts index ae8a5944..0fcf7c86 100644 --- a/api/src/routes/invites/index.ts +++ b/api/src/routes/invites/index.ts @@ -15,14 +15,9 @@ router.get("/:code", route({}), async (req: Request, res: Response) => { router.post("/:code", route({}), async (req: Request, res: Response) => { const { code } = req.params; + const invite = await Invite.joinGuild(req.user_id, code); - const invite = await Invite.findOneOrFail({ code }); - if (invite.uses++ >= invite.max_uses) await Invite.delete({ code }); - else await invite.save(); - - await Member.addToGuild(req.user_id, invite.guild_id); - - res.status(200).send(invite); + res.json(invite); }); // * cant use permission of route() function because path doesn't have guild_id/channel_id diff --git a/util/src/entities/Config.ts b/util/src/entities/Config.ts index fd830db8..f969b6bb 100644 --- a/util/src/entities/Config.ts +++ b/util/src/entities/Config.ts @@ -110,13 +110,13 @@ export interface ConfigValue { }; register: { email: { - necessary: boolean; // we have to use necessary instead of required as the cli tool uses json schema and can't use required + required: boolean; allowlist: boolean; blocklist: boolean; domains: string[]; }; dateOfBirth: { - necessary: boolean; + required: boolean; minimum: number; // in years }; requireCaptcha: boolean; @@ -125,6 +125,7 @@ export interface ConfigValue { allowMultipleAccounts: boolean; blockProxies: boolean; password: { + required: boolean; minLength: number; minNumbers: number; minUpperCase: number; @@ -246,14 +247,14 @@ export const DefaultConfigOptions: ConfigValue = { }, register: { email: { - necessary: true, + required: false, allowlist: false, blocklist: true, domains: [], // TODO: efficiently save domain blocklist in database // domains: fs.readFileSync(__dirname + "/blockedEmailDomains.txt", { encoding: "utf8" }).split("\n"), }, dateOfBirth: { - necessary: true, + required: false, minimum: 13, }, requireInvite: false, @@ -262,6 +263,7 @@ export const DefaultConfigOptions: ConfigValue = { allowMultipleAccounts: true, blockProxies: true, password: { + required: false, minLength: 8, minNumbers: 2, minUpperCase: 2, diff --git a/util/src/entities/Invite.ts b/util/src/entities/Invite.ts index afad9c02..1396004e 100644 --- a/util/src/entities/Invite.ts +++ b/util/src/entities/Invite.ts @@ -1,4 +1,5 @@ import { Column, Entity, JoinColumn, ManyToOne, PrimaryColumn, RelationId } from "typeorm"; +import { Member } from "."; import { BaseClass } from "./BaseClass"; import { Channel } from "./Channel"; import { Guild } from "./Guild"; @@ -63,4 +64,13 @@ export class Invite extends BaseClass { @Column({ nullable: true }) target_user_type?: number; + + static async joinGuild(user_id: string, code: string) { + const invite = await Invite.findOneOrFail({ code }); + if (invite.uses++ >= invite.max_uses && invite.max_uses !== 0) await Invite.delete({ code }); + else await invite.save(); + + await Member.addToGuild(user_id, invite.guild_id); + return invite; + } } -- cgit 1.5.1 From 7809148867c7e30a5bab43fa46b506f5a67f89ba Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Mon, 20 Sep 2021 18:02:57 +0200 Subject: :sparkles: finish and fix .delete() for one-to-many relations --- util/src/entities/BaseClass.ts | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'util/src') diff --git a/util/src/entities/BaseClass.ts b/util/src/entities/BaseClass.ts index 2a621f40..8a0b7a26 100644 --- a/util/src/entities/BaseClass.ts +++ b/util/src/entities/BaseClass.ts @@ -83,7 +83,7 @@ export class BaseClassWithoutId extends BaseEntity { if (!criteria) throw new Error("You need to specify delete criteria"); const repository = this.getRepository(); - const promises = repository.metadata.relations.map((x) => { + const promises = repository.metadata.relations.map(async (x) => { if (x.orphanedRowAction !== "delete") return; if (typeof x.type === "string") return; @@ -95,22 +95,23 @@ export class BaseClassWithoutId extends BaseEntity { `Foreign key not found for entity ${repository.metadata.name} in relation ${x.propertyName}` ); } - console.log(foreignKey); const id = (criteria as any)[foreignKey.referencedColumnNames[0]]; if (!id) throw new Error("id missing in criteria options"); - if (x.relationType === "many-to-many" || x.relationType === "one-to-many") { + if (x.relationType === "many-to-many") { return getConnection() .createQueryBuilder() .relation(this, x.propertyName) .of(id) .remove({ [foreignKey.columnNames[0]]: id }); - } else if (x.relationType === "one-to-one" || x.relationType === "many-to-one") { + } else if ( + x.relationType === "one-to-one" || + x.relationType === "many-to-one" || + x.relationType === "one-to-many" + ) { return getConnection() - .createQueryBuilder() - .from(x.inverseEntityMetadata, "user") - .of(id) - .remove({ [foreignKey.name]: id }); + .getRepository(x.inverseEntityMetadata.target) + .delete({ [foreignKey.columnNames[0]]: id }); } }); await Promise.all(promises); -- cgit 1.5.1 From 576cbf5794b2e146892d7080b699882c2ba6ec6a Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Mon, 20 Sep 2021 20:22:56 +0200 Subject: :bug: fix .delete -> add onDelete: "CASCADE" --- api/src/routes/guilds/#guild_id/delete.ts | 12 +---- util/src/entities/Application.ts | 4 +- util/src/entities/Attachment.ts | 4 +- util/src/entities/Ban.ts | 8 +++- util/src/entities/BaseClass.ts | 74 +++++++++++++++---------------- util/src/entities/Channel.ts | 10 ++--- util/src/entities/ConnectedAccount.ts | 4 +- util/src/entities/Emoji.ts | 4 +- util/src/entities/Guild.ts | 2 - util/src/entities/Invite.ts | 12 +++-- util/src/entities/Member.ts | 9 ++-- util/src/entities/Message.ts | 13 ++++-- util/src/entities/ReadState.ts | 8 +++- util/src/entities/Recipient.ts | 8 +++- util/src/entities/Relationship.ts | 8 +++- util/src/entities/Role.ts | 4 +- util/src/entities/Session.ts | 4 +- util/src/entities/Sticker.ts | 4 +- util/src/entities/Team.ts | 4 +- util/src/entities/TeamMember.ts | 8 +++- util/src/entities/User.ts | 10 ++++- util/src/entities/VoiceState.ts | 16 +++++-- util/src/entities/Webhook.ts | 20 ++++++--- 23 files changed, 153 insertions(+), 97 deletions(-) (limited to 'util/src') diff --git a/api/src/routes/guilds/#guild_id/delete.ts b/api/src/routes/guilds/#guild_id/delete.ts index 7c3c5530..bd158c56 100644 --- a/api/src/routes/guilds/#guild_id/delete.ts +++ b/api/src/routes/guilds/#guild_id/delete.ts @@ -13,15 +13,8 @@ router.post("/", route({}), async (req: Request, res: Response) => { const guild = await Guild.findOneOrFail({ where: { id: guild_id }, select: ["owner_id"] }); if (guild.owner_id !== req.user_id) throw new HTTPError("You are not the owner of this guild", 401); - // do not put everything into promise all, because of "QueryFailedError: SQLITE_CONSTRAINT: FOREIGN KEY constraint failed" - - await Message.delete({ guild_id }); // messages must be deleted before channel - await Promise.all([ - Role.delete({ guild_id }), - Channel.delete({ guild_id }), - Emoji.delete({ guild_id }), - Member.delete({ guild_id }), + Guild.delete({ id: guild_id }), // this will also delete all guild related data emitEvent({ event: "GUILD_DELETE", data: { @@ -31,9 +24,6 @@ router.post("/", route({}), async (req: Request, res: Response) => { } as GuildDeleteEvent) ]); - await Invite.delete({ guild_id }); // invite must be deleted after channel - await Guild.delete({ id: guild_id }); // guild must be deleted after everything else - return res.sendStatus(204); }); diff --git a/util/src/entities/Application.ts b/util/src/entities/Application.ts index 2092cd4e..fab3d93f 100644 --- a/util/src/entities/Application.ts +++ b/util/src/entities/Application.ts @@ -41,7 +41,9 @@ export class Application extends BaseClass { verify_key: string; @JoinColumn({ name: "team_id" }) - @ManyToOne(() => Team) + @ManyToOne(() => Team, { + onDelete: "CASCADE", + }) team?: Team; @JoinColumn({ name: "guild_id" }) diff --git a/util/src/entities/Attachment.ts b/util/src/entities/Attachment.ts index 82c5ecf5..7b4b17eb 100644 --- a/util/src/entities/Attachment.ts +++ b/util/src/entities/Attachment.ts @@ -31,7 +31,9 @@ export class Attachment extends BaseClass { message_id: string; @JoinColumn({ name: "message_id" }) - @ManyToOne(() => require("./Message").Message, (message: import("./Message").Message) => message.attachments) + @ManyToOne(() => require("./Message").Message, (message: import("./Message").Message) => message.attachments, { + onDelete: "CASCADE", + }) message: import("./Message").Message; @BeforeRemove() diff --git a/util/src/entities/Ban.ts b/util/src/entities/Ban.ts index e8a6d648..9504bd8e 100644 --- a/util/src/entities/Ban.ts +++ b/util/src/entities/Ban.ts @@ -10,7 +10,9 @@ export class Ban extends BaseClass { user_id: string; @JoinColumn({ name: "user_id" }) - @ManyToOne(() => User) + @ManyToOne(() => User, { + onDelete: "CASCADE", + }) user: User; @Column({ nullable: true }) @@ -18,7 +20,9 @@ export class Ban extends BaseClass { guild_id: string; @JoinColumn({ name: "guild_id" }) - @ManyToOne(() => Guild) + @ManyToOne(() => Guild, { + onDelete: "CASCADE", + }) guild: Guild; @Column({ nullable: true }) diff --git a/util/src/entities/BaseClass.ts b/util/src/entities/BaseClass.ts index 8a0b7a26..d18757f2 100644 --- a/util/src/entities/BaseClass.ts +++ b/util/src/entities/BaseClass.ts @@ -6,6 +6,7 @@ import { EntityMetadata, FindConditions, getConnection, + getManager, PrimaryColumn, RemoveOptions, } from "typeorm"; @@ -79,44 +80,41 @@ export class BaseClassWithoutId extends BaseEntity { return repository.decrement(conditions, propertyPath, value); } - static async delete(criteria: FindConditions, options?: RemoveOptions) { - if (!criteria) throw new Error("You need to specify delete criteria"); - - const repository = this.getRepository(); - const promises = repository.metadata.relations.map(async (x) => { - if (x.orphanedRowAction !== "delete") return; - if (typeof x.type === "string") return; - - const foreignKey = - x.foreignKeys.find((key) => key.entityMetadata === repository.metadata) || - x.inverseRelation?.foreignKeys[0]; // find foreign key for this entity - if (!foreignKey) { - throw new Error( - `Foreign key not found for entity ${repository.metadata.name} in relation ${x.propertyName}` - ); - } - const id = (criteria as any)[foreignKey.referencedColumnNames[0]]; - if (!id) throw new Error("id missing in criteria options"); - - if (x.relationType === "many-to-many") { - return getConnection() - .createQueryBuilder() - .relation(this, x.propertyName) - .of(id) - .remove({ [foreignKey.columnNames[0]]: id }); - } else if ( - x.relationType === "one-to-one" || - x.relationType === "many-to-one" || - x.relationType === "one-to-many" - ) { - return getConnection() - .getRepository(x.inverseEntityMetadata.target) - .delete({ [foreignKey.columnNames[0]]: id }); - } - }); - await Promise.all(promises); - return super.delete(criteria, options); - } + // static async delete(criteria: FindConditions, options?: RemoveOptions) { + // if (!criteria) throw new Error("You need to specify delete criteria"); + + // const repository = this.getRepository(); + // const promises = repository.metadata.relations.map(async (x) => { + // if (x.orphanedRowAction !== "delete") return; + + // const foreignKey = + // x.foreignKeys.find((key) => key.entityMetadata === repository.metadata) || + // x.inverseRelation?.foreignKeys[0]; // find foreign key for this entity + // if (!foreignKey) { + // throw new Error( + // `Foreign key not found for entity ${repository.metadata.name} in relation ${x.propertyName}` + // ); + // } + // const id = (criteria as any)[foreignKey.referencedColumnNames[0]]; + // if (!id) throw new Error("id missing in criteria options " + foreignKey.referencedColumnNames); + + // if (x.relationType === "many-to-many") { + // return getConnection() + // .createQueryBuilder() + // .relation(this, x.propertyName) + // .of(id) + // .remove({ [foreignKey.columnNames[0]]: id }); + // } else if ( + // x.relationType === "one-to-one" || + // x.relationType === "many-to-one" || + // x.relationType === "one-to-many" + // ) { + // return (x.inverseEntityMetadata.target as any).delete({ [foreignKey.columnNames[0]]: id }); + // } + // }); + // await Promise.all(promises); + // return super.delete(criteria, options); + // } } export class BaseClass extends BaseClassWithoutId { diff --git a/util/src/entities/Channel.ts b/util/src/entities/Channel.ts index 74611eea..ece82bd0 100644 --- a/util/src/entities/Channel.ts +++ b/util/src/entities/Channel.ts @@ -45,7 +45,6 @@ export class Channel extends BaseClass { @OneToMany(() => Recipient, (recipient: Recipient) => recipient.channel, { cascade: true, orphanedRowAction: "delete", - onDelete: "CASCADE", }) recipients?: Recipient[]; @@ -57,7 +56,9 @@ export class Channel extends BaseClass { guild_id?: string; @JoinColumn({ name: "guild_id" }) - @ManyToOne(() => Guild) + @ManyToOne(() => Guild, { + onDelete: "CASCADE", + }) guild: Guild; @Column({ nullable: true }) @@ -110,35 +111,30 @@ export class Channel extends BaseClass { @OneToMany(() => Invite, (invite: Invite) => invite.channel, { cascade: true, orphanedRowAction: "delete", - onDelete: "CASCADE", }) invites?: Invite[]; @OneToMany(() => Message, (message: Message) => message.channel, { cascade: true, orphanedRowAction: "delete", - onDelete: "CASCADE", }) messages?: Message[]; @OneToMany(() => VoiceState, (voice_state: VoiceState) => voice_state.channel, { cascade: true, orphanedRowAction: "delete", - onDelete: "CASCADE", }) voice_states?: VoiceState[]; @OneToMany(() => ReadState, (read_state: ReadState) => read_state.channel, { cascade: true, orphanedRowAction: "delete", - onDelete: "CASCADE", }) read_states?: ReadState[]; @OneToMany(() => Webhook, (webhook: Webhook) => webhook.channel, { cascade: true, orphanedRowAction: "delete", - onDelete: "CASCADE", }) webhooks?: Webhook[]; diff --git a/util/src/entities/ConnectedAccount.ts b/util/src/entities/ConnectedAccount.ts index 59a8f423..b8aa2889 100644 --- a/util/src/entities/ConnectedAccount.ts +++ b/util/src/entities/ConnectedAccount.ts @@ -11,7 +11,9 @@ export class ConnectedAccount extends BaseClass { user_id: string; @JoinColumn({ name: "user_id" }) - @ManyToOne(() => User) + @ManyToOne(() => User, { + onDelete: "CASCADE", + }) user: User; @Column({ select: false }) diff --git a/util/src/entities/Emoji.ts b/util/src/entities/Emoji.ts index 181aff2c..a252d9f4 100644 --- a/util/src/entities/Emoji.ts +++ b/util/src/entities/Emoji.ts @@ -15,7 +15,9 @@ export class Emoji extends BaseClass { guild_id: string; @JoinColumn({ name: "guild_id" }) - @ManyToOne(() => Guild) + @ManyToOne(() => Guild, { + onDelete: "CASCADE", + }) guild: Guild; @Column() diff --git a/util/src/entities/Guild.ts b/util/src/entities/Guild.ts index d46d2161..e107937d 100644 --- a/util/src/entities/Guild.ts +++ b/util/src/entities/Guild.ts @@ -84,7 +84,6 @@ export class Guild extends BaseClass { @OneToMany(() => Ban, (ban: Ban) => ban.guild, { cascade: true, orphanedRowAction: "delete", - onDelete: "CASCADE", }) bans: Ban[]; @@ -147,7 +146,6 @@ export class Guild extends BaseClass { @OneToMany(() => Channel, (channel: Channel) => channel.guild, { cascade: true, orphanedRowAction: "delete", - onDelete: "CASCADE", }) channels: Channel[]; diff --git a/util/src/entities/Invite.ts b/util/src/entities/Invite.ts index afad9c02..cb308823 100644 --- a/util/src/entities/Invite.ts +++ b/util/src/entities/Invite.ts @@ -34,7 +34,9 @@ export class Invite extends BaseClass { guild_id: string; @JoinColumn({ name: "guild_id" }) - @ManyToOne(() => Guild) + @ManyToOne(() => Guild, { + onDelete: "CASCADE", + }) guild: Guild; @Column({ nullable: true }) @@ -42,7 +44,9 @@ export class Invite extends BaseClass { channel_id: string; @JoinColumn({ name: "channel_id" }) - @ManyToOne(() => Channel) + @ManyToOne(() => Channel, { + onDelete: "CASCADE", + }) channel: Channel; @Column({ nullable: true }) @@ -58,7 +62,9 @@ export class Invite extends BaseClass { target_user_id: string; @JoinColumn({ name: "target_user_id" }) - @ManyToOne(() => User) + @ManyToOne(() => User, { + onDelete: "CASCADE", + }) target_user?: string; // could be used for "User specific invites" https://github.com/fosscord/fosscord/issues/62 @Column({ nullable: true }) diff --git a/util/src/entities/Member.ts b/util/src/entities/Member.ts index 66f5d9a1..feb9c069 100644 --- a/util/src/entities/Member.ts +++ b/util/src/entities/Member.ts @@ -39,7 +39,9 @@ export class Member extends BaseClassWithoutId { id: string; @JoinColumn({ name: "id" }) - @ManyToOne(() => User) + @ManyToOne(() => User, { + onDelete: "CASCADE", + }) user: User; @Column() @@ -47,7 +49,9 @@ export class Member extends BaseClassWithoutId { guild_id: string; @JoinColumn({ name: "guild_id" }) - @ManyToOne(() => Guild) + @ManyToOne(() => Guild, { + onDelete: "CASCADE", + }) guild: Guild; @Column({ nullable: true }) @@ -55,7 +59,6 @@ export class Member extends BaseClassWithoutId { @JoinTable({ name: "member_roles", - joinColumn: { name: "index", referencedColumnName: "index" }, inverseJoinColumn: { name: "role_id", diff --git a/util/src/entities/Message.ts b/util/src/entities/Message.ts index 0712f545..c4901693 100644 --- a/util/src/entities/Message.ts +++ b/util/src/entities/Message.ts @@ -54,7 +54,9 @@ export class Message extends BaseClass { channel_id: string; @JoinColumn({ name: "channel_id" }) - @ManyToOne(() => Channel) + @ManyToOne(() => Channel, { + onDelete: "CASCADE", + }) channel: Channel; @Column({ nullable: true }) @@ -62,7 +64,9 @@ export class Message extends BaseClass { guild_id?: string; @JoinColumn({ name: "guild_id" }) - @ManyToOne(() => Guild) + @ManyToOne(() => Guild, { + onDelete: "CASCADE", + }) guild?: Guild; @Column({ nullable: true }) @@ -70,7 +74,9 @@ export class Message extends BaseClass { author_id: string; @JoinColumn({ name: "author_id", referencedColumnName: "id" }) - @ManyToOne(() => User) + @ManyToOne(() => User, { + onDelete: "CASCADE", + }) author?: User; @Column({ nullable: true }) @@ -132,7 +138,6 @@ export class Message extends BaseClass { @OneToMany(() => Attachment, (attachment: Attachment) => attachment.message, { cascade: true, orphanedRowAction: "delete", - onDelete: "CASCADE", }) attachments?: Attachment[]; diff --git a/util/src/entities/ReadState.ts b/util/src/entities/ReadState.ts index 8dd05b21..68e867a0 100644 --- a/util/src/entities/ReadState.ts +++ b/util/src/entities/ReadState.ts @@ -15,7 +15,9 @@ export class ReadState extends BaseClass { channel_id: string; @JoinColumn({ name: "channel_id" }) - @ManyToOne(() => Channel) + @ManyToOne(() => Channel, { + onDelete: "CASCADE", + }) channel: Channel; @Column({ nullable: true }) @@ -23,7 +25,9 @@ export class ReadState extends BaseClass { user_id: string; @JoinColumn({ name: "user_id" }) - @ManyToOne(() => User) + @ManyToOne(() => User, { + onDelete: "CASCADE", + }) user: User; @Column({ nullable: true }) diff --git a/util/src/entities/Recipient.ts b/util/src/entities/Recipient.ts index bb280588..a945f938 100644 --- a/util/src/entities/Recipient.ts +++ b/util/src/entities/Recipient.ts @@ -8,7 +8,9 @@ export class Recipient extends BaseClass { channel_id: string; @JoinColumn({ name: "channel_id" }) - @ManyToOne(() => require("./Channel").Channel) + @ManyToOne(() => require("./Channel").Channel, { + onDelete: "CASCADE", + }) channel: import("./Channel").Channel; @Column() @@ -16,7 +18,9 @@ export class Recipient extends BaseClass { user_id: string; @JoinColumn({ name: "user_id" }) - @ManyToOne(() => require("./User").User) + @ManyToOne(() => require("./User").User, { + onDelete: "CASCADE", + }) user: import("./User").User; @Column({ default: false }) diff --git a/util/src/entities/Relationship.ts b/util/src/entities/Relationship.ts index 61b3ac82..e016b36b 100644 --- a/util/src/entities/Relationship.ts +++ b/util/src/entities/Relationship.ts @@ -17,7 +17,9 @@ export class Relationship extends BaseClass { from_id: string; @JoinColumn({ name: "from_id" }) - @ManyToOne(() => User) + @ManyToOne(() => User, { + onDelete: "CASCADE", + }) from: User; @Column({}) @@ -25,7 +27,9 @@ export class Relationship extends BaseClass { to_id: string; @JoinColumn({ name: "to_id" }) - @ManyToOne(() => User) + @ManyToOne(() => User, { + onDelete: "CASCADE", + }) to: User; @Column({ nullable: true }) diff --git a/util/src/entities/Role.ts b/util/src/entities/Role.ts index 33c8d272..9fca99a5 100644 --- a/util/src/entities/Role.ts +++ b/util/src/entities/Role.ts @@ -10,7 +10,9 @@ export class Role extends BaseClass { guild_id: string; @JoinColumn({ name: "guild_id" }) - @ManyToOne(() => Guild) + @ManyToOne(() => Guild, { + onDelete: "CASCADE", + }) guild: Guild; @Column() diff --git a/util/src/entities/Session.ts b/util/src/entities/Session.ts index d42a8f98..7cc325f5 100644 --- a/util/src/entities/Session.ts +++ b/util/src/entities/Session.ts @@ -11,7 +11,9 @@ export class Session extends BaseClass { user_id: string; @JoinColumn({ name: "user_id" }) - @ManyToOne(() => User) + @ManyToOne(() => User, { + onDelete: "CASCADE", + }) user: User; //TODO check, should be 32 char long hex string diff --git a/util/src/entities/Sticker.ts b/util/src/entities/Sticker.ts index 7730a86a..ab224d1d 100644 --- a/util/src/entities/Sticker.ts +++ b/util/src/entities/Sticker.ts @@ -31,7 +31,9 @@ export class Sticker extends BaseClass { guild_id?: string; @JoinColumn({ name: "guild_id" }) - @ManyToOne(() => Guild) + @ManyToOne(() => Guild, { + onDelete: "CASCADE", + }) guild?: Guild; @Column({ type: "simple-enum", enum: StickerType }) diff --git a/util/src/entities/Team.ts b/util/src/entities/Team.ts index beb8bf68..22140b7f 100644 --- a/util/src/entities/Team.ts +++ b/util/src/entities/Team.ts @@ -9,7 +9,9 @@ export class Team extends BaseClass { icon?: string; @JoinColumn({ name: "member_ids" }) - @OneToMany(() => TeamMember, (member: TeamMember) => member.team) + @OneToMany(() => TeamMember, (member: TeamMember) => member.team, { + orphanedRowAction: "delete", + }) members: TeamMember[]; @Column() diff --git a/util/src/entities/TeamMember.ts b/util/src/entities/TeamMember.ts index 6b184d08..bdfdccf0 100644 --- a/util/src/entities/TeamMember.ts +++ b/util/src/entities/TeamMember.ts @@ -20,7 +20,9 @@ export class TeamMember extends BaseClass { team_id: string; @JoinColumn({ name: "team_id" }) - @ManyToOne(() => require("./Team").Team, (team: import("./Team").Team) => team.members) + @ManyToOne(() => require("./Team").Team, (team: import("./Team").Team) => team.members, { + onDelete: "CASCADE", + }) team: import("./Team").Team; @Column({ nullable: true }) @@ -28,6 +30,8 @@ export class TeamMember extends BaseClass { user_id: string; @JoinColumn({ name: "user_id" }) - @ManyToOne(() => User) + @ManyToOne(() => User, { + onDelete: "CASCADE", + }) user: User; } diff --git a/util/src/entities/User.ts b/util/src/entities/User.ts index cef88777..4c86b2d8 100644 --- a/util/src/entities/User.ts +++ b/util/src/entities/User.ts @@ -127,11 +127,17 @@ export class User extends BaseClass { public_flags: number; @JoinColumn({ name: "relationship_ids" }) - @OneToMany(() => Relationship, (relationship: Relationship) => relationship.from) + @OneToMany(() => Relationship, (relationship: Relationship) => relationship.from, { + cascade: true, + orphanedRowAction: "delete", + }) relationships: Relationship[]; @JoinColumn({ name: "connected_account_ids" }) - @OneToMany(() => ConnectedAccount, (account: ConnectedAccount) => account.user) + @OneToMany(() => ConnectedAccount, (account: ConnectedAccount) => account.user, { + cascade: true, + orphanedRowAction: "delete", + }) connected_accounts: ConnectedAccount[]; @Column({ type: "simple-json", select: false }) diff --git a/util/src/entities/VoiceState.ts b/util/src/entities/VoiceState.ts index 56eb244e..75748a01 100644 --- a/util/src/entities/VoiceState.ts +++ b/util/src/entities/VoiceState.ts @@ -13,7 +13,9 @@ export class VoiceState extends BaseClass { guild_id: string; @JoinColumn({ name: "guild_id" }) - @ManyToOne(() => Guild) + @ManyToOne(() => Guild, { + onDelete: "CASCADE", + }) guild?: Guild; @Column({ nullable: true }) @@ -21,7 +23,9 @@ export class VoiceState extends BaseClass { channel_id: string; @JoinColumn({ name: "channel_id" }) - @ManyToOne(() => Channel) + @ManyToOne(() => Channel, { + onDelete: "CASCADE", + }) channel: Channel; @Column({ nullable: true }) @@ -29,11 +33,15 @@ export class VoiceState extends BaseClass { user_id: string; @JoinColumn({ name: "user_id" }) - @ManyToOne(() => User) + @ManyToOne(() => User, { + onDelete: "CASCADE", + }) user: User; // @JoinColumn([{ name: "user_id", referencedColumnName: "id" },{ name: "guild_id", referencedColumnName: "guild_id" }]) - // @ManyToOne(() => Member) + // @ManyToOne(() => Member, { + // onDelete: "CASCADE", + // }) //TODO find a way to make it work without breaking Guild.voice_states member: Member; diff --git a/util/src/entities/Webhook.ts b/util/src/entities/Webhook.ts index 12ba0d08..8382435f 100644 --- a/util/src/entities/Webhook.ts +++ b/util/src/entities/Webhook.ts @@ -32,7 +32,9 @@ export class Webhook extends BaseClass { guild_id: string; @JoinColumn({ name: "guild_id" }) - @ManyToOne(() => Guild) + @ManyToOne(() => Guild, { + onDelete: "CASCADE", + }) guild: Guild; @Column({ nullable: true }) @@ -40,7 +42,9 @@ export class Webhook extends BaseClass { channel_id: string; @JoinColumn({ name: "channel_id" }) - @ManyToOne(() => Channel) + @ManyToOne(() => Channel, { + onDelete: "CASCADE", + }) channel: Channel; @Column({ nullable: true }) @@ -48,7 +52,9 @@ export class Webhook extends BaseClass { application_id: string; @JoinColumn({ name: "application_id" }) - @ManyToOne(() => Application) + @ManyToOne(() => Application, { + onDelete: "CASCADE", + }) application: Application; @Column({ nullable: true }) @@ -56,7 +62,9 @@ export class Webhook extends BaseClass { user_id: string; @JoinColumn({ name: "user_id" }) - @ManyToOne(() => User) + @ManyToOne(() => User, { + onDelete: "CASCADE", + }) user: User; @Column({ nullable: true }) @@ -64,6 +72,8 @@ export class Webhook extends BaseClass { source_guild_id: string; @JoinColumn({ name: "source_guild_id" }) - @ManyToOne(() => Guild) + @ManyToOne(() => Guild, { + onDelete: "CASCADE", + }) source_guild: Guild; } -- cgit 1.5.1 From 022e82023d1a5a91e671eacf5ce054e097f379f7 Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Mon, 20 Sep 2021 23:35:32 +0200 Subject: :sparkles: add option to disable all rate limits --- api/src/middlewares/BodyParser.ts | 2 ++ api/src/middlewares/RateLimit.ts | 3 ++- util/src/entities/Config.ts | 2 ++ util/src/entities/User.ts | 4 +--- util/src/util/Config.ts | 2 +- util/src/util/Database.ts | 3 ++- 6 files changed, 10 insertions(+), 6 deletions(-) (limited to 'util/src') diff --git a/api/src/middlewares/BodyParser.ts b/api/src/middlewares/BodyParser.ts index b0ff699d..4cb376bc 100644 --- a/api/src/middlewares/BodyParser.ts +++ b/api/src/middlewares/BodyParser.ts @@ -6,6 +6,8 @@ export function BodyParser(opts?: OptionsJson) { const jsonParser = bodyParser.json(opts); return (req: Request, res: Response, next: NextFunction) => { + if (!req.headers["content-type"]) req.headers["content-type"] = "application/json"; + jsonParser(req, res, (err) => { if (err) { // TODO: different errors for body parser (request size limit, wrong body type, invalid body, ...) diff --git a/api/src/middlewares/RateLimit.ts b/api/src/middlewares/RateLimit.ts index d1fd072f..1a38cfcf 100644 --- a/api/src/middlewares/RateLimit.ts +++ b/api/src/middlewares/RateLimit.ts @@ -107,7 +107,8 @@ export default function rateLimit(opts: { } export async function initRateLimits(app: Router) { - const { routes, global, ip, error } = Config.get().limits.rate; + const { routes, global, ip, error, disabled } = Config.get().limits.rate; + if (disabled) return; await listenEvent(EventRateLimit, (event) => { Cache.set(event.channel_id as string, event.data); event.acknowledge?.(); diff --git a/util/src/entities/Config.ts b/util/src/entities/Config.ts index f969b6bb..a460b437 100644 --- a/util/src/entities/Config.ts +++ b/util/src/entities/Config.ts @@ -77,6 +77,7 @@ export interface ConfigValue { maxWebhooks: number; }; rate: { + disabled: boolean; ip: Omit; global: RateLimitOptions; error: RateLimitOptions; @@ -188,6 +189,7 @@ export const DefaultConfigOptions: ConfigValue = { maxWebhooks: 10, }, rate: { + disabled: true, ip: { count: 500, window: 5, diff --git a/util/src/entities/User.ts b/util/src/entities/User.ts index 4c86b2d8..b5c2c308 100644 --- a/util/src/entities/User.ts +++ b/util/src/entities/User.ts @@ -161,15 +161,13 @@ export class User extends BaseClass { } static async getPublicUser(user_id: string, opts?: FindOneOptions) { - const user = await User.findOne( + return await User.findOneOrFail( { id: user_id }, { ...opts, select: [...PublicUserProjection, ...(opts?.select || [])], } ); - if (!user) throw new HTTPError("User not found", 404); - return user; } } diff --git a/util/src/util/Config.ts b/util/src/util/Config.ts index 1ec71ad0..c87d598e 100644 --- a/util/src/util/Config.ts +++ b/util/src/util/Config.ts @@ -14,7 +14,7 @@ export const Config = { get: function get() { return config.value as ConfigValue; }, - set: function set(val: any) { + set: function set(val: Partial) { if (!config) return; config.value = val.merge(config?.value || {}); return config.save(); diff --git a/util/src/util/Database.ts b/util/src/util/Database.ts index c22d8abd..0c3d7cef 100644 --- a/util/src/util/Database.ts +++ b/util/src/util/Database.ts @@ -1,3 +1,4 @@ +import path from "path"; import "reflect-metadata"; import { Connection, createConnection, ValueTransformer } from "typeorm"; import * as Models from "../entities"; @@ -15,7 +16,7 @@ export function initDatabase() { // @ts-ignore promise = createConnection({ type: "sqlite", - database: "database.db", + database: path.join(process.cwd(), "database.db"), // type: "postgres", // url: "postgres://fosscord:wb94SmuURM2Syv&@localhost/fosscord", // -- cgit 1.5.1 From abdce76df4b6aa3a063b496e6c0575c54e9fa397 Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Tue, 21 Sep 2021 22:52:30 +0200 Subject: :sparkles: generate openapi documentation --- api/assets/openapi.json | 5978 +++++++++++++++++--- api/assets/responses.json | 90 - api/assets/schemas.json | 2013 ++++++- api/jest/getRouteDescriptions.js | 66 + api/jest/getRouteDescriptions.ts | 58 - api/scripts/generate_body_schema.js | 70 + api/scripts/generate_body_schema.ts | 60 - api/scripts/generate_openapi_schema.js | 127 + api/scripts/generate_openapi_schema.ts | 92 - api/scripts/generate_test_schema.ts | 68 - api/src/routes/auth/login.ts | 23 +- api/src/routes/auth/register.ts | 24 +- api/src/routes/channels/#channel_id/recipients.ts | 5 +- .../members/#member_id/roles/#role_id/index.ts | 4 +- api/src/routes/sticker-packs/#id/index.ts | 5 +- api/src/routes/sticker-packs/index.ts | 5 +- api/src/util/String.ts | 2 - api/tests/routes.test.ts | 4 +- util/src/util/Email.ts | 20 + util/src/util/Token.ts | 43 + util/src/util/checkToken.ts | 23 - util/src/util/index.ts | 3 +- 22 files changed, 7575 insertions(+), 1208 deletions(-) delete mode 100644 api/assets/responses.json create mode 100644 api/jest/getRouteDescriptions.js delete mode 100644 api/jest/getRouteDescriptions.ts create mode 100644 api/scripts/generate_body_schema.js delete mode 100644 api/scripts/generate_body_schema.ts create mode 100644 api/scripts/generate_openapi_schema.js delete mode 100644 api/scripts/generate_openapi_schema.ts delete mode 100644 api/scripts/generate_test_schema.ts create mode 100644 util/src/util/Email.ts create mode 100644 util/src/util/Token.ts delete mode 100644 util/src/util/checkToken.ts (limited to 'util/src') diff --git a/api/assets/openapi.json b/api/assets/openapi.json index fa527911..caf572b9 100644 --- a/api/assets/openapi.json +++ b/api/assets/openapi.json @@ -4,7 +4,12 @@ { "url": "https://api.fosscord.com/v{version}", "description": "Official fosscord instance", - "variables": { "version": { "description": "", "default": "9", "enum": ["8", "9"] } } + "variables": { + "version": { + "default": "9", + "enum": ["8", "9"] + } + } } ], "info": { @@ -12,95 +17,2866 @@ "version": "1.0.0", "title": "Fosscord HTTP API Routes", "termsOfService": "", - "contact": { "name": "Fosscord" }, - "license": { "name": "AGPLV3", "url": "https://www.gnu.org/licenses/agpl-3.0.en.html" } + "contact": { + "name": "Fosscord" + }, + "license": { + "name": "AGPLV3", + "url": "https://www.gnu.org/licenses/agpl-3.0.en.html" + } }, - "tags": [], + "tags": [ + { + "name": "voice" + }, + { + "name": "users" + }, + { + "name": "store" + }, + { + "name": "sticker-packs" + }, + { + "name": "science" + }, + { + "name": "ping" + }, + { + "name": "outbound-promotions" + }, + { + "name": "invites" + }, + { + "name": "guilds" + }, + { + "name": "gateway" + }, + { + "name": "experiments" + }, + { + "name": "discoverable-guilds" + }, + { + "name": "channels" + }, + { + "name": "auth" + }, + { + "name": "applications" + } + ], "paths": { "/users/{id}": { "get": { "summary": "", - "description": "", - "parameters": [{ "name": "id", "in": "path", "required": true, "schema": { "type": "string" }, "description": "user id" }], + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "user id" + } + ], "operationId": "", "responses": { "200": { "description": "User found", - "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UserPublic" } } } + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserPublic" + } + } + } }, "404": { "description": "User not found", - "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "security": [ + { + "Token": [] + } + ] + } + }, + "/users/@me": { + "get": { + "summary": "", + "parameters": [], + "operationId": "", + "responses": { + "200": { + "description": "Authenticated user", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserPublic" + } + } + } + } + }, + "security": [ + { + "Token": [] + } + ] + } + }, + "/voice/regions/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": ["voice"] + } + }, + "/users/@me/settings/": { + "patch": { + "description": "", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserSettingsSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": ["users"] + } + }, + "/users/@me/relationships/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": ["users", "relationships"] + }, + "post": { + "description": "", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RelationshipPostSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": ["users"] + } + }, + "/users/@me/relationships/{id}": { + "put": { + "description": "", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RelationshipPutSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "id" + } + ], + "tags": ["users"] + }, + "delete": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "id" + } + ], + "tags": ["users"] + } + }, + "/users/@me/library/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": ["users"] + } + }, + "/users/@me/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": ["users"] + }, + "patch": { + "description": "", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserModifySchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": ["users"] + } + }, + "/users/@me/guilds/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": ["users"] + } + }, + "/users/@me/guilds/{id}": { + "delete": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "id" + } + ], + "tags": ["users"] + } + }, + "/users/@me/disable/": { + "post": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": ["users"] + } + }, + "/users/@me/devices/": { + "post": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": ["users"] + } + }, + "/users/@me/delete/": { + "post": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": ["users"] + } + }, + "/users/@me/connections/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": ["users"] + } + }, + "/users/@me/channels/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": ["users"] + }, + "post": { + "description": "", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DmChannelCreateSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": ["users"] + } + }, + "/users/@me/billing/subscriptions/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": ["users"] + } + }, + "/users/@me/billing/country-code/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": ["users"] + } + }, + "/users/@me/applications/{app_id}/entitlements/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "app_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "app_id" + } + ], + "tags": ["users"] + } + }, + "/users/@me/affinities/users/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": ["users"] + } + }, + "/users/@me/affinities/guilds/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": ["users"] + } + }, + "/users/{id}/profile/": { + "get": { + "description": "", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserProfileResponse" + } + } + }, + "description": "" + } + }, + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "id" + } + ], + "tags": ["users"] + } + }, + "/users/{id}/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "id" + } + ], + "tags": ["users"] + } + }, + "/store/skus/skus/{id}": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "id" + } + ], + "tags": ["store"] + } + }, + "/store/applications/applications/{id}": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "id" + } + ], + "tags": ["store"] + } + }, + "/sticker-packs/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": ["sticker", "sticker-packs"] + } + }, + "/sticker-packs/{id}/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "id" + } + ], + "tags": ["sticker", "sticker-packs"] + } + }, + "/science/": { + "post": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": ["science"] + } + }, + "/ping/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": ["ping"] + } + }, + "/outbound-promotions/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": ["outbound", "outbound-promotions"] + } + }, + "/invites/{code}": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "code", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "code" + } + ], + "tags": ["invites"] + }, + "post": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "code", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "code" + } + ], + "tags": ["invites"] + }, + "delete": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "code", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "code" + } + ], + "tags": ["invites"] + } + }, + "/guilds/templates/{code}": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "code", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "code" + } + ], + "tags": ["guilds"] + }, + "post": { + "description": "", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GuildTemplateCreateSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "code", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "code" + } + ], + "tags": ["guilds"] + } + }, + "/guilds/": { + "post": { + "description": "", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GuildCreateSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": ["guilds"] + } + }, + "/guilds/{guild_id}/widget.png/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": ["guilds"] + } + }, + "/guilds/{guild_id}/widget.json/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": ["guilds"] + } + }, + "/guilds/{guild_id}/widget/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": ["guilds"] + }, + "patch": { + "description": "##### Requires the ``MANAGE_GUILD`` permission\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WidgetModifySchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": ["guilds"] + } + }, + "/guilds/{guild_id}/welcome_screen/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": ["guilds"] + }, + "patch": { + "description": "##### Requires the ``MANAGE_GUILD`` permission\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GuildUpdateWelcomeScreenSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": ["guilds"] + } + }, + "/guilds/{guild_id}/voice-states/{user_id}/": { + "patch": { + "description": "", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VoiceStateUpdateSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + }, + { + "name": "user_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "user_id" + } + ], + "tags": ["guilds"] + } + }, + "/guilds/{guild_id}/vanity-url/": { + "get": { + "description": "##### Requires the ``MANAGE_GUILD`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": ["guilds"] + }, + "patch": { + "description": "##### Requires the ``MANAGE_GUILD`` permission\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VanityUrlSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": ["guilds"] + } + }, + "/guilds/{guild_id}/templates/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": ["guilds"] + }, + "post": { + "description": "##### Requires the ``MANAGE_GUILD`` permission\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TemplateCreateSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": ["guilds"] + } + }, + "/guilds/{guild_id}/templates/{code}": { + "delete": { + "description": "##### Requires the ``MANAGE_GUILD`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + }, + { + "name": "code", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "code" + } + ], + "tags": ["guilds"] + }, + "put": { + "description": "##### Requires the ``MANAGE_GUILD`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + }, + { + "name": "code", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "code" + } + ], + "tags": ["guilds"] + }, + "patch": { + "description": "##### Requires the ``MANAGE_GUILD`` permission\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TemplateModifySchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + }, + { + "name": "code", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "code" + } + ], + "tags": ["guilds"] + } + }, + "/guilds/{guild_id}/roles/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": ["guilds"] + }, + "post": { + "description": "##### Requires the ``MANAGE_ROLES`` permission\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RoleModifySchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": ["guilds"] + }, + "patch": { + "description": "", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RolePositionUpdateSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": ["guilds"] + } + }, + "/guilds/{guild_id}/roles/{role_id}": { + "delete": { + "description": "##### Requires the ``MANAGE_ROLES`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + }, + { + "name": "role_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "role_id" + } + ], + "tags": ["guilds"] + }, + "patch": { + "description": "##### Requires the ``MANAGE_ROLES`` permission\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RoleModifySchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + }, + { + "name": "role_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "role_id" + } + ], + "tags": ["guilds"] + } + }, + "/guilds/{guild_id}/regions/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": ["guilds"] + } + }, + "/guilds/{guild_id}/members/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": ["guilds"] + } + }, + "/guilds/{guild_id}/members/{member_id}/nick/": { + "patch": { + "description": "", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MemberNickChangeSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + }, + { + "name": "member_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "member_id" + } + ], + "tags": ["guilds"] + } + }, + "/guilds/{guild_id}/members/{member_id}/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + }, + { + "name": "member_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "member_id" + } + ], + "tags": ["guilds"] + }, + "patch": { + "description": "", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MemberChangeSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + }, + { + "name": "member_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "member_id" + } + ], + "tags": ["guilds"] + }, + "put": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + }, + { + "name": "member_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "member_id" + } + ], + "tags": ["guilds"] + }, + "delete": { + "description": "##### Requires the ``KICK_MEMBERS`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + }, + { + "name": "member_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "member_id" + } + ], + "tags": ["guilds"] + } + }, + "/guilds/{guild_id}/invites/": { + "get": { + "description": "##### Requires the ``MANAGE_GUILD`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": ["guilds"] + } + }, + "/guilds/{guild_id}/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": ["guilds"] + }, + "patch": { + "description": "##### Requires the ``MANAGE_GUILD`` permission\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GuildUpdateSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": ["guilds"] + } + }, + "/guilds/{guild_id}/delete/": { + "post": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": ["guilds"] + } + }, + "/guilds/{guild_id}/channels/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": ["guilds"] + }, + "post": { + "description": "##### Requires the ``MANAGE_CHANNELS`` permission\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChannelModifySchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": ["guilds"] + }, + "patch": { + "description": "##### Requires the ``MANAGE_CHANNELS`` permission\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChannelReorderSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": ["guilds"] + } + }, + "/guilds/{guild_id}/bans/": { + "get": { + "description": "##### Requires the ``BAN_MEMBERS`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": ["guilds"] + } + }, + "/guilds/{guild_id}/bans/{user}": { + "get": { + "description": "##### Requires the ``BAN_MEMBERS`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + }, + { + "name": "user", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "user" + } + ], + "tags": ["guilds"] + } + }, + "/guilds/{guild_id}/bans/{user_id}": { + "put": { + "description": "##### Requires the ``BAN_MEMBERS`` permission\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BanCreateSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + }, + { + "name": "user_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "user_id" + } + ], + "tags": ["guilds"] + }, + "delete": { + "description": "##### Requires the ``BAN_MEMBERS`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + }, + { + "name": "user_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "user_id" + } + ], + "tags": ["guilds"] + } + }, + "/gateway/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": ["gateway"] + } + }, + "/gateway/bot": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": ["gateway"] + } + }, + "/experiments/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": ["experiments"] + } + }, + "/discoverable-guilds/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": ["discoverable", "discoverable-guilds"] + } + }, + "/channels/{channel_id}/webhooks/": { + "post": { + "description": "##### Requires the ``MANAGE_WEBHOOKS`` permission\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WebhookCreateSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + } + ], + "tags": ["channels"] + } + }, + "/channels/{channel_id}/typing/": { + "post": { + "description": "##### Requires the ``SEND_MESSAGES`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + } + ], + "tags": ["channels"] + } + }, + "/channels/{channel_id}/recipients/{user_id}": { + "put": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + }, + { + "name": "user_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "user_id" + } + ], + "tags": ["channels"] + }, + "delete": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + }, + { + "name": "user_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "user_id" + } + ], + "tags": ["channels"] + } + }, + "/channels/{channel_id}/pins/{message_id}": { + "put": { + "description": "##### Requires the ``VIEW_CHANNEL`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + }, + { + "name": "message_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "message_id" + } + ], + "tags": ["channels"] + }, + "delete": { + "description": "##### Requires the ``VIEW_CHANNEL`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + }, + { + "name": "message_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "message_id" + } + ], + "tags": ["channels"] + } + }, + "/channels/{channel_id}/pins/": { + "get": { + "description": "##### Requires the ``READ_MESSAGE_HISTORY`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + } + ], + "tags": ["channels"] + } + }, + "/channels/{channel_id}/permissions/{overwrite_id}": { + "put": { + "description": "##### Requires the ``MANAGE_ROLES`` permission\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChannelPermissionOverwriteSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + }, + { + "name": "overwrite_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "overwrite_id" + } + ], + "tags": ["channels"] + }, + "delete": { + "description": "##### Requires the ``MANAGE_ROLES`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + }, + { + "name": "overwrite_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "overwrite_id" + } + ], + "tags": ["channels"] + } + }, + "/channels/{channel_id}/messages/bulk-delete/": { + "post": { + "description": "", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BulkDeleteSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + } + ], + "tags": ["channels"] + } + }, + "/channels/{channel_id}/messages/{message_id}/reactions/": { + "delete": { + "description": "##### Requires the ``MANAGE_MESSAGES`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + }, + { + "name": "message_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "message_id" + } + ], + "tags": ["channels"] + } + }, + "/channels/{channel_id}/messages/{message_id}/reactions/{emoji}": { + "delete": { + "description": "##### Requires the ``MANAGE_MESSAGES`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + }, + { + "name": "message_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "message_id" + }, + { + "name": "emoji", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "emoji" + } + ], + "tags": ["channels"] + }, + "get": { + "description": "##### Requires the ``VIEW_CHANNEL`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + }, + { + "name": "message_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "message_id" + }, + { + "name": "emoji", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "emoji" + } + ], + "tags": ["channels"] + } + }, + "/channels/{channel_id}/messages/{message_id}/reactions/{emoji}/{user_id}": { + "put": { + "description": "##### Requires the ``READ_MESSAGE_HISTORY`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + }, + { + "name": "message_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "message_id" + }, + { + "name": "emoji", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "emoji" + }, + { + "name": "user_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "user_id" + } + ], + "tags": ["channels"] + }, + "delete": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + }, + { + "name": "message_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "message_id" + }, + { + "name": "emoji", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "emoji" + }, + { + "name": "user_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "user_id" + } + ], + "tags": ["channels"] + } + }, + "/channels/{channel_id}/messages/{message_id}/": { + "patch": { + "description": "##### Requires the ``SEND_MESSAGES`` permission\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MessageCreateSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + }, + { + "name": "message_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "message_id" + } + ], + "tags": ["channels"] + }, + "delete": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + }, + { + "name": "message_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "message_id" + } + ], + "tags": ["channels"] + } + }, + "/channels/{channel_id}/messages/{message_id}/ack/": { + "post": { + "description": "", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MessageAcknowledgeSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + }, + { + "name": "message_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "message_id" + } + ], + "tags": ["channels"] + } + }, + "/channels/{channel_id}/invites/": { + "post": { + "description": "##### Requires the ``CREATE_INSTANT_INVITE`` permission\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InviteCreateSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + } + ], + "tags": ["channels"] + }, + "get": { + "description": "##### Requires the ``MANAGE_CHANNELS`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + } + ], + "tags": ["channels"] + } + }, + "/channels/{channel_id}/": { + "get": { + "description": "##### Requires the ``VIEW_CHANNEL`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + } + ], + "tags": ["channels"] + }, + "delete": { + "description": "##### Requires the ``MANAGE_CHANNELS`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + } + ], + "tags": ["channels"] + }, + "patch": { + "description": "##### Requires the ``MANAGE_CHANNELS`` permission\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChannelModifySchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + } + ], + "tags": ["channels"] + } + }, + "/auth/register/": { + "post": { + "description": "", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RegisterSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": ["auth"] + } + }, + "/applications/detectable/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": ["applications"] + } + }, + "/guilds/{guild_id}/members/{member_id}/roles/{role_id}/": { + "delete": { + "description": "##### Requires the ``MANAGE_ROLES`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + }, + { + "name": "member_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "member_id" + }, + { + "name": "role_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "role_id" + } + ], + "tags": ["guilds"] + }, + "put": { + "description": "##### Requires the ``MANAGE_ROLES`` permission\n", + "responses": { + "default": { + "description": "not documented" } }, - "security": [{ "Token": [] }] + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + }, + { + "name": "member_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "member_id" + }, + { + "name": "role_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "role_id" + } + ], + "tags": ["guilds"] } }, - "/users/@me": { - "get": { - "summary": "", + "/auth/login/": { + "post": { "description": "", - "parameters": [], - "operationId": "", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LoginSchema" + } + } + } + }, "responses": { - "200": { - "description": "Authenticated user", - "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UserPublic" } } } + "default": { + "description": "not documented" } }, - "security": [{ "Token": [] }] + "tags": ["auth"] } } }, - "externalDocs": { "description": "", "url": "http://docs.fosscord.com/" }, + "externalDocs": { + "url": "http://docs.fosscord.com/" + }, "components": { "schemas": { "Error": { "type": "object", - "properties": { "code": { "type": "integer" }, "message": { "type": "string" } }, + "properties": { + "code": { + "type": "integer" + }, + "message": { + "type": "string" + } + }, "required": ["code", "message"] }, "RateLimit": { "type": "object", - "properties": { "retry_after": { "type": "integer" }, "message": { "type": "string" }, "global": { "type": "boolean" } }, + "properties": { + "retry_after": { + "type": "integer" + }, + "message": { + "type": "string" + }, + "global": { + "type": "boolean" + } + }, "required": ["code", "message", "globa"] }, "User": { "type": "object", "properties": { - "username": { "type": "string" }, - "discriminator": { "type": "string" }, - "avatar": { "type": "string" }, - "accent_color": { "type": "integer" }, - "banner": { "type": "string" }, - "phone": { "type": "string" }, - "desktop": { "type": "boolean" }, - "mobile": { "type": "boolean" }, - "premium": { "type": "boolean" }, - "premium_type": { "type": "integer" }, - "bot": { "type": "boolean" }, - "bio": { "type": "string" }, - "system": { "type": "boolean" }, - "nsfw_allowed": { "type": "boolean" }, - "mfa_enabled": { "type": "boolean" }, - "created_at": { "type": "string", "format": "date-time" }, - "verified": { "type": "boolean" }, - "disabled": { "type": "boolean" }, - "deleted": { "type": "boolean" }, - "email": { "type": "string" }, - "flags": { "type": "string" }, - "public_flags": { "type": "string" }, - "relationships": { "type": "array", "items": { "$ref": "#/components/schemas/Relationship" } }, - "connected_accounts": { "type": "array", "items": { "$ref": "#/components/schemas/ConnectedAccount" } }, + "username": { + "type": "string" + }, + "discriminator": { + "type": "string" + }, + "avatar": { + "type": "string" + }, + "accent_color": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "desktop": { + "type": "boolean" + }, + "mobile": { + "type": "boolean" + }, + "premium": { + "type": "boolean" + }, + "premium_type": { + "type": "integer" + }, + "bot": { + "type": "boolean" + }, + "bio": { + "type": "string" + }, + "system": { + "type": "boolean" + }, + "nsfw_allowed": { + "type": "boolean" + }, + "mfa_enabled": { + "type": "boolean" + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "verified": { + "type": "boolean" + }, + "disabled": { + "type": "boolean" + }, + "deleted": { + "type": "boolean" + }, + "email": { + "type": "string" + }, + "flags": { + "type": "string" + }, + "public_flags": { + "type": "string" + }, + "relationships": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Relationship" + } + }, + "connected_accounts": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ConnectedAccount" + } + }, "data": { "type": "object", - "properties": { "valid_tokens_since": { "type": "string", "format": "date-time" }, "hash": { "type": "string" } }, + "properties": { + "valid_tokens_since": { + "type": "string", + "format": "date-time" + }, + "hash": { + "type": "string" + } + }, "additionalProperties": false, "required": ["valid_tokens_since"] }, - "fingerprints": { "type": "array", "items": { "type": "string" } }, - "settings": { "$ref": "#/components/schemas/UserSettings" }, - "id": { "type": "string" } + "fingerprints": { + "type": "array", + "items": { + "type": "string" + } + }, + "settings": { + "$ref": "#/components/schemas/UserSettings" + }, + "id": { + "type": "string" + } }, "required": [ "bio", @@ -131,29 +2907,64 @@ "Relationship": { "type": "object", "properties": { - "user_id": { "type": "string" }, - "user": { "$ref": "#/components/schemas/User" }, - "nickname": { "type": "string" }, - "type": { "$ref": "#/components/schemas/RelationshipType" }, - "id": { "type": "string" } + "user_id": { + "type": "string" + }, + "user": { + "$ref": "#/components/schemas/User" + }, + "nickname": { + "type": "string" + }, + "type": { + "$ref": "#/components/schemas/RelationshipType" + }, + "id": { + "type": "string" + } }, "required": ["id", "type", "user", "user_id"] }, - "RelationshipType": { "enum": [1, 2, 3, 4], "type": "number" }, + "RelationshipType": { + "enum": [1, 2, 3, 4], + "type": "number" + }, "ConnectedAccount": { "type": "object", "properties": { - "user_id": { "type": "string" }, - "user": { "$ref": "#/components/schemas/User" }, - "access_token": { "type": "string" }, - "friend_sync": { "type": "boolean" }, - "name": { "type": "string" }, - "revoked": { "type": "boolean" }, - "show_activity": { "type": "boolean" }, - "type": { "type": "string" }, - "verifie": { "type": "boolean" }, - "visibility": { "type": "integer" }, - "id": { "type": "string" } + "user_id": { + "type": "string" + }, + "user": { + "$ref": "#/components/schemas/User" + }, + "access_token": { + "type": "string" + }, + "friend_sync": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "revoked": { + "type": "boolean" + }, + "show_activity": { + "type": "boolean" + }, + "type": { + "type": "string" + }, + "verifie": { + "type": "boolean" + }, + "visibility": { + "type": "integer" + }, + "id": { + "type": "string" + } }, "required": [ "access_token", @@ -172,64 +2983,151 @@ "UserSettings": { "type": "object", "properties": { - "afk_timeout": { "type": "integer" }, - "allow_accessibility_detection": { "type": "boolean" }, - "animate_emoji": { "type": "boolean" }, - "animate_stickers": { "type": "integer" }, - "contact_sync_enabled": { "type": "boolean" }, - "convert_emoticons": { "type": "boolean" }, + "afk_timeout": { + "type": "integer" + }, + "allow_accessibility_detection": { + "type": "boolean" + }, + "animate_emoji": { + "type": "boolean" + }, + "animate_stickers": { + "type": "integer" + }, + "contact_sync_enabled": { + "type": "boolean" + }, + "convert_emoticons": { + "type": "boolean" + }, "custom_status": { "type": "object", "properties": { - "emoji_id": { "type": "string" }, - "emoji_name": { "type": "string" }, - "expires_at": { "type": "integer" }, - "text": { "type": "string" } + "emoji_id": { + "type": "string" + }, + "emoji_name": { + "type": "string" + }, + "expires_at": { + "type": "integer" + }, + "text": { + "type": "string" + } }, "additionalProperties": false }, - "default_guilds_restricted": { "type": "boolean" }, - "detect_platform_accounts": { "type": "boolean" }, - "developer_mode": { "type": "boolean" }, - "disable_games_tab": { "type": "boolean" }, - "enable_tts_command": { "type": "boolean" }, - "explicit_content_filter": { "type": "integer" }, + "default_guilds_restricted": { + "type": "boolean" + }, + "detect_platform_accounts": { + "type": "boolean" + }, + "developer_mode": { + "type": "boolean" + }, + "disable_games_tab": { + "type": "boolean" + }, + "enable_tts_command": { + "type": "boolean" + }, + "explicit_content_filter": { + "type": "integer" + }, "friend_source_flags": { "type": "object", - "properties": { "all": { "type": "boolean" } }, + "properties": { + "all": { + "type": "boolean" + } + }, "additionalProperties": false, "required": ["all"] }, - "gateway_connected": { "type": "boolean" }, - "gif_auto_play": { "type": "boolean" }, + "gateway_connected": { + "type": "boolean" + }, + "gif_auto_play": { + "type": "boolean" + }, "guild_folders": { "type": "array", "items": { "type": "object", "properties": { - "color": { "type": "integer" }, - "guild_ids": { "type": "array", "items": { "type": "string" } }, - "id": { "type": "integer" }, - "name": { "type": "string" } + "color": { + "type": "integer" + }, + "guild_ids": { + "type": "array", + "items": { + "type": "string" + } + }, + "id": { + "type": "integer" + }, + "name": { + "type": "string" + } }, "additionalProperties": false, "required": ["color", "guild_ids", "id", "name"] } }, - "guild_positions": { "type": "array", "items": { "type": "string" } }, - "inline_attachment_media": { "type": "boolean" }, - "inline_embed_media": { "type": "boolean" }, - "locale": { "type": "string" }, - "message_display_compact": { "type": "boolean" }, - "native_phone_integration_enabled": { "type": "boolean" }, - "render_embeds": { "type": "boolean" }, - "render_reactions": { "type": "boolean" }, - "restricted_guilds": { "type": "array", "items": { "type": "string" } }, - "show_current_game": { "type": "boolean" }, - "status": { "enum": ["dnd", "idle", "offline", "online"], "type": "string" }, - "stream_notifications_enabled": { "type": "boolean" }, - "theme": { "enum": ["dark", "white"], "type": "string" }, - "timezone_offset": { "type": "integer" } + "guild_positions": { + "type": "array", + "items": { + "type": "string" + } + }, + "inline_attachment_media": { + "type": "boolean" + }, + "inline_embed_media": { + "type": "boolean" + }, + "locale": { + "type": "string" + }, + "message_display_compact": { + "type": "boolean" + }, + "native_phone_integration_enabled": { + "type": "boolean" + }, + "render_embeds": { + "type": "boolean" + }, + "render_reactions": { + "type": "boolean" + }, + "restricted_guilds": { + "type": "array", + "items": { + "type": "string" + } + }, + "show_current_game": { + "type": "boolean" + }, + "status": { + "enum": ["dnd", "idle", "offline", "online"], + "type": "string" + }, + "stream_notifications_enabled": { + "type": "boolean" + }, + "theme": { + "enum": ["dark", "white"], + "type": "string" + }, + "timezone_offset": { + "type": "integer" + } }, "required": [ "afk_timeout", @@ -268,93 +3166,264 @@ "Team": { "type": "object", "properties": { - "icon": { "type": "string" }, - "members": { "type": "array", "items": { "$ref": "#/components/schemas/TeamMember" } }, - "name": { "type": "string" }, - "owner_user_id": { "type": "string" }, - "owner_user": { "$ref": "#/components/schemas/User" }, - "id": { "type": "string" } + "icon": { + "type": "string" + }, + "members": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TeamMember" + } + }, + "name": { + "type": "string" + }, + "owner_user_id": { + "type": "string" + }, + "owner_user": { + "$ref": "#/components/schemas/User" + }, + "id": { + "type": "string" + } }, "required": ["id", "members", "name", "owner_user", "owner_user_id"] }, "TeamMember": { "type": "object", "properties": { - "membership_state": { "$ref": "#/components/schemas/TeamMemberState" }, - "permissions": { "type": "array", "items": { "type": "string" } }, - "team_id": { "type": "string" }, - "team": { "$ref": "#/components/schemas/Team" }, - "user_id": { "type": "string" }, - "user": { "$ref": "#/components/schemas/User" }, - "id": { "type": "string" } + "membership_state": { + "$ref": "#/components/schemas/TeamMemberState" + }, + "permissions": { + "type": "array", + "items": { + "type": "string" + } + }, + "team_id": { + "type": "string" + }, + "team": { + "$ref": "#/components/schemas/Team" + }, + "user_id": { + "type": "string" + }, + "user": { + "$ref": "#/components/schemas/User" + }, + "id": { + "type": "string" + } }, "required": ["id", "membership_state", "permissions", "team", "team_id", "user", "user_id"] }, - "TeamMemberState": { "enum": [1, 2], "type": "number" }, + "TeamMemberState": { + "enum": [1, 2], + "type": "number" + }, "Guild": { "type": "object", "properties": { - "afk_channel_id": { "type": "string" }, - "afk_channel": { "$ref": "#/components/schemas/Channel" }, - "afk_timeout": { "type": "integer" }, - "bans": { "type": "array", "items": { "$ref": "#/components/schemas/Ban" } }, - "banner": { "type": "string" }, - "default_message_notifications": { "type": "integer" }, - "description": { "type": "string" }, - "discovery_splash": { "type": "string" }, - "explicit_content_filter": { "type": "integer" }, - "features": { "type": "array", "items": { "type": "string" } }, - "icon": { "type": "string" }, - "large": { "type": "boolean" }, - "max_members": { "type": "integer" }, - "max_presences": { "type": "integer" }, - "max_video_channel_users": { "type": "integer" }, - "member_count": { "type": "integer" }, - "presence_count": { "type": "integer" }, - "members": { "type": "array", "items": { "$ref": "#/components/schemas/Member" } }, - "roles": { "type": "array", "items": { "$ref": "#/components/schemas/Role" } }, - "channels": { "type": "array", "items": { "$ref": "#/components/schemas/Channel" } }, - "template_id": { "type": "string" }, - "template": { "$ref": "#/components/schemas/Template" }, - "emojis": { "type": "array", "items": { "$ref": "#/components/schemas/Emoji" } }, - "stickers": { "type": "array", "items": { "$ref": "#/components/schemas/Sticker" } }, - "invites": { "type": "array", "items": { "$ref": "#/components/schemas/Invite" } }, - "voice_states": { "type": "array", "items": { "$ref": "#/components/schemas/VoiceState" } }, - "webhooks": { "type": "array", "items": { "$ref": "#/components/schemas/Webhook" } }, - "mfa_level": { "type": "integer" }, - "name": { "type": "string" }, - "owner_id": { "type": "string" }, - "owner": { "$ref": "#/components/schemas/User" }, - "preferred_locale": { "type": "string" }, - "premium_subscription_count": { "type": "integer" }, - "premium_tier": { "type": "integer" }, - "public_updates_channel_id": { "type": "string" }, - "public_updates_channel": { "$ref": "#/components/schemas/Channel" }, - "rules_channel_id": { "type": "string" }, - "rules_channel": { "type": "string" }, - "region": { "type": "string" }, - "splash": { "type": "string" }, - "system_channel_id": { "type": "string" }, - "system_channel": { "$ref": "#/components/schemas/Channel" }, - "system_channel_flags": { "type": "integer" }, - "unavailable": { "type": "boolean" }, - "vanity_url_code": { "type": "string" }, - "vanity_url": { "$ref": "#/components/schemas/Invite" }, - "verification_level": { "type": "integer" }, + "afk_channel_id": { + "type": "string" + }, + "afk_channel": { + "$ref": "#/components/schemas/Channel" + }, + "afk_timeout": { + "type": "integer" + }, + "bans": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Ban" + } + }, + "banner": { + "type": "string" + }, + "default_message_notifications": { + "type": "integer" + }, + "description": { + "type": "string" + }, + "discovery_splash": { + "type": "string" + }, + "explicit_content_filter": { + "type": "integer" + }, + "features": { + "type": "array", + "items": { + "type": "string" + } + }, + "icon": { + "type": "string" + }, + "large": { + "type": "boolean" + }, + "max_members": { + "type": "integer" + }, + "max_presences": { + "type": "integer" + }, + "max_video_channel_users": { + "type": "integer" + }, + "member_count": { + "type": "integer" + }, + "presence_count": { + "type": "integer" + }, + "members": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Member" + } + }, + "roles": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Role" + } + }, + "channels": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Channel" + } + }, + "template_id": { + "type": "string" + }, + "template": { + "$ref": "#/components/schemas/Template" + }, + "emojis": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Emoji" + } + }, + "stickers": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Sticker" + } + }, + "invites": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Invite" + } + }, + "voice_states": { + "type": "array", + "items": { + "$ref": "#/components/schemas/VoiceState" + } + }, + "webhooks": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Webhook" + } + }, + "mfa_level": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "owner_id": { + "type": "string" + }, + "owner": { + "$ref": "#/components/schemas/User" + }, + "preferred_locale": { + "type": "string" + }, + "premium_subscription_count": { + "type": "integer" + }, + "premium_tier": { + "type": "integer" + }, + "public_updates_channel_id": { + "type": "string" + }, + "public_updates_channel": { + "$ref": "#/components/schemas/Channel" + }, + "rules_channel_id": { + "type": "string" + }, + "rules_channel": { + "type": "string" + }, + "region": { + "type": "string" + }, + "splash": { + "type": "string" + }, + "system_channel_id": { + "type": "string" + }, + "system_channel": { + "$ref": "#/components/schemas/Channel" + }, + "system_channel_flags": { + "type": "integer" + }, + "unavailable": { + "type": "boolean" + }, + "vanity_url_code": { + "type": "string" + }, + "vanity_url": { + "$ref": "#/components/schemas/Invite" + }, + "verification_level": { + "type": "integer" + }, "welcome_screen": { "type": "object", "properties": { - "enabled": { "type": "boolean" }, - "description": { "type": "string" }, + "enabled": { + "type": "boolean" + }, + "description": { + "type": "string" + }, "welcome_channels": { "type": "array", "items": { "type": "object", "properties": { - "description": { "type": "string" }, - "emoji_id": { "type": "string" }, - "emoji_name": { "type": "string" }, - "channel_id": { "type": "string" } + "description": { + "type": "string" + }, + "emoji_id": { + "type": "string" + }, + "emoji_name": { + "type": "string" + }, + "channel_id": { + "type": "string" + } }, "additionalProperties": false, "required": ["channel_id", "description", "emoji_name"] @@ -364,10 +3433,18 @@ "additionalProperties": false, "required": ["description", "enabled", "welcome_channels"] }, - "widget_channel_id": { "type": "string" }, - "widget_channel": { "$ref": "#/components/schemas/Channel" }, - "widget_enabled": { "type": "boolean" }, - "id": { "type": "string" } + "widget_channel_id": { + "type": "string" + }, + "widget_channel": { + "$ref": "#/components/schemas/Channel" + }, + "widget_enabled": { + "type": "boolean" + }, + "id": { + "type": "string" + } }, "required": [ "bans", @@ -393,29 +3470,82 @@ "Channel": { "type": "object", "properties": { - "created_at": { "type": "string", "format": "date-time" }, - "name": { "type": "string" }, - "type": { "$ref": "#/components/schemas/ChannelType" }, - "recipients": { "type": "array", "items": { "$ref": "#/components/schemas/Recipient" } }, - "last_message_id": { "type": "string" }, - "last_message": { "$ref": "#/components/schemas/Message" }, - "guild_id": { "type": "string" }, - "guild": { "$ref": "#/components/schemas/Guild" }, - "parent_id": { "type": "string" }, - "parent": { "$ref": "#/components/schemas/Channel" }, - "owner_id": { "type": "string" }, - "owner": { "$ref": "#/components/schemas/User" }, - "last_pin_timestamp": { "type": "integer" }, - "default_auto_archive_duration": { "type": "integer" }, - "position": { "type": "integer" }, - "permission_overwrites": { "type": "array", "items": { "$ref": "#/components/schemas/ChannelPermissionOverwrite" } }, - "video_quality_mode": { "type": "integer" }, - "bitrate": { "type": "integer" }, - "user_limit": { "type": "integer" }, - "nsfw": { "type": "boolean" }, - "rate_limit_per_user": { "type": "integer" }, - "topic": { "type": "string" }, - "id": { "type": "string" } + "created_at": { + "type": "string", + "format": "date-time" + }, + "name": { + "type": "string" + }, + "type": { + "$ref": "#/components/schemas/ChannelType" + }, + "recipients": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Recipient" + } + }, + "last_message_id": { + "type": "string" + }, + "last_message": { + "$ref": "#/components/schemas/Message" + }, + "guild_id": { + "type": "string" + }, + "guild": { + "$ref": "#/components/schemas/Guild" + }, + "parent_id": { + "type": "string" + }, + "parent": { + "$ref": "#/components/schemas/Channel" + }, + "owner_id": { + "type": "string" + }, + "owner": { + "$ref": "#/components/schemas/User" + }, + "last_pin_timestamp": { + "type": "integer" + }, + "default_auto_archive_duration": { + "type": "integer" + }, + "position": { + "type": "integer" + }, + "permission_overwrites": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ChannelPermissionOverwrite" + } + }, + "video_quality_mode": { + "type": "integer" + }, + "bitrate": { + "type": "integer" + }, + "user_limit": { + "type": "integer" + }, + "nsfw": { + "type": "boolean" + }, + "rate_limit_per_user": { + "type": "integer" + }, + "topic": { + "type": "string" + }, + "id": { + "type": "string" + } }, "required": [ "created_at", @@ -431,78 +3561,198 @@ "type" ] }, - "ChannelType": { "enum": [0, 1, 2, 3, 4, 5, 6], "type": "number" }, + "ChannelType": { + "enum": [0, 1, 2, 3, 4, 5, 6], + "type": "number" + }, "Recipient": { "type": "object", "properties": { - "channel_id": { "type": "string" }, - "channel": { "$ref": "#/components/schemas/Channel" }, - "user": { "$ref": "#/components/schemas/User" }, - "id": { "type": "string" } + "channel_id": { + "type": "string" + }, + "channel": { + "$ref": "#/components/schemas/Channel" + }, + "user": { + "$ref": "#/components/schemas/User" + }, + "id": { + "type": "string" + } }, "required": ["channel", "channel_id", "id", "user"] }, "Message": { "type": "object", "properties": { - "id": { "type": "string" }, - "channel_id": { "type": "string" }, - "channel": { "$ref": "#/components/schemas/Channel" }, - "guild_id": { "type": "string" }, - "guild": { "$ref": "#/components/schemas/Guild" }, - "author_id": { "type": "string" }, - "author": { "$ref": "#/components/schemas/User" }, - "member_id": { "type": "string" }, - "member": { "$ref": "#/components/schemas/Member" }, - "webhook_id": { "type": "string" }, - "webhook": { "$ref": "#/components/schemas/Webhook" }, - "application_id": { "type": "string" }, - "application": { "$ref": "#/components/schemas/Application" }, - "content": { "type": "string" }, - "timestamp": { "type": "string", "format": "date-time" }, - "edited_timestamp": { "type": "string", "format": "date-time" }, - "tts": { "type": "boolean" }, - "mention_everyone": { "type": "boolean" }, - "mentions": { "type": "array", "items": { "$ref": "#/components/schemas/User" } }, - "mention_roles": { "type": "array", "items": { "$ref": "#/components/schemas/Role" } }, - "mention_channels": { "type": "array", "items": { "$ref": "#/components/schemas/Channel" } }, - "sticker_items": { "type": "array", "items": { "$ref": "#/components/schemas/Sticker" } }, - "attachments": { "type": "array", "items": { "$ref": "#/components/schemas/Attachment" } }, - "embeds": { "type": "array", "items": { "$ref": "#/components/schemas/Embed" } }, - "reactions": { "type": "array", "items": { "$ref": "#/components/schemas/Reaction" } }, - "nonce": { "type": "string" }, - "pinned": { "type": "boolean" }, - "type": { "$ref": "#/components/schemas/MessageType" }, + "id": { + "type": "string" + }, + "channel_id": { + "type": "string" + }, + "channel": { + "$ref": "#/components/schemas/Channel" + }, + "guild_id": { + "type": "string" + }, + "guild": { + "$ref": "#/components/schemas/Guild" + }, + "author_id": { + "type": "string" + }, + "author": { + "$ref": "#/components/schemas/User" + }, + "member_id": { + "type": "string" + }, + "member": { + "$ref": "#/components/schemas/Member" + }, + "webhook_id": { + "type": "string" + }, + "webhook": { + "$ref": "#/components/schemas/Webhook" + }, + "application_id": { + "type": "string" + }, + "application": { + "$ref": "#/components/schemas/Application" + }, + "content": { + "type": "string" + }, + "timestamp": { + "type": "string", + "format": "date-time" + }, + "edited_timestamp": { + "type": "string", + "format": "date-time" + }, + "tts": { + "type": "boolean" + }, + "mention_everyone": { + "type": "boolean" + }, + "mentions": { + "type": "array", + "items": { + "$ref": "#/components/schemas/User" + } + }, + "mention_roles": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Role" + } + }, + "mention_channels": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Channel" + } + }, + "sticker_items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Sticker" + } + }, + "attachments": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Attachment" + } + }, + "embeds": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Embed" + } + }, + "reactions": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Reaction" + } + }, + "nonce": { + "type": "string" + }, + "pinned": { + "type": "boolean" + }, + "type": { + "$ref": "#/components/schemas/MessageType" + }, "activity": { "type": "object", - "properties": { "type": { "type": "integer" }, "party_id": { "type": "string" } }, + "properties": { + "type": { + "type": "integer" + }, + "party_id": { + "type": "string" + } + }, "additionalProperties": false, "required": ["party_id", "type"] }, - "flags": { "type": "string" }, + "flags": { + "type": "string" + }, "message_reference": { "type": "object", "properties": { - "message_id": { "type": "string" }, - "channel_id": { "type": "string" }, - "guild_id": { "type": "string" } + "message_id": { + "type": "string" + }, + "channel_id": { + "type": "string" + }, + "guild_id": { + "type": "string" + } }, "additionalProperties": false, "required": ["message_id"] }, - "referenced_message": { "$ref": "#/components/schemas/Message" }, + "referenced_message": { + "$ref": "#/components/schemas/Message" + }, "interaction": { "type": "object", "properties": { - "id": { "type": "string" }, - "type": { "$ref": "#/components/schemas/InteractionType" }, - "name": { "type": "string" }, - "user_id": { "type": "string" } + "id": { + "type": "string" + }, + "type": { + "$ref": "#/components/schemas/InteractionType" + }, + "name": { + "type": "string" + }, + "user_id": { + "type": "string" + } }, "additionalProperties": false, "required": ["id", "name", "type", "user_id"] }, - "components": { "type": "array", "items": { "$ref": "#/components/schemas/MessageComponent" } } + "components": { + "type": "array", + "items": { + "$ref": "#/components/schemas/MessageComponent" + } + } }, "required": [ "application_id", @@ -524,44 +3774,100 @@ "Member": { "type": "object", "properties": { - "user_id": { "type": "string" }, - "user": { "$ref": "#/components/schemas/User" }, - "guild_id": { "type": "string" }, - "guild": { "$ref": "#/components/schemas/Guild" }, - "nick": { "type": "string" }, - "roles": { "type": "array", "items": { "$ref": "#/components/schemas/Role" } }, - "joined_at": { "type": "string", "format": "date-time" }, - "premium_since": { "type": "integer" }, - "deaf": { "type": "boolean" }, - "mute": { "type": "boolean" }, - "pending": { "type": "boolean" }, - "settings": { "$ref": "#/components/schemas/UserGuildSettings" }, - "id": { "type": "string" } + "user_id": { + "type": "string" + }, + "user": { + "$ref": "#/components/schemas/User" + }, + "guild_id": { + "type": "string" + }, + "guild": { + "$ref": "#/components/schemas/Guild" + }, + "nick": { + "type": "string" + }, + "roles": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Role" + } + }, + "joined_at": { + "type": "string", + "format": "date-time" + }, + "premium_since": { + "type": "integer" + }, + "deaf": { + "type": "boolean" + }, + "mute": { + "type": "boolean" + }, + "pending": { + "type": "boolean" + }, + "settings": { + "$ref": "#/components/schemas/UserGuildSettings" + }, + "id": { + "type": "string" + } }, "required": ["deaf", "guild", "guild_id", "id", "joined_at", "mute", "pending", "roles", "settings", "user", "user_id"] }, "Role": { "type": "object", "properties": { - "guild_id": { "type": "string" }, - "guild": { "$ref": "#/components/schemas/Guild" }, - "color": { "type": "integer" }, - "hoist": { "type": "boolean" }, - "managed": { "type": "boolean" }, - "mentionable": { "type": "boolean" }, - "name": { "type": "string" }, - "permissions": { "type": "string" }, - "position": { "type": "integer" }, + "guild_id": { + "type": "string" + }, + "guild": { + "$ref": "#/components/schemas/Guild" + }, + "color": { + "type": "integer" + }, + "hoist": { + "type": "boolean" + }, + "managed": { + "type": "boolean" + }, + "mentionable": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "permissions": { + "type": "string" + }, + "position": { + "type": "integer" + }, "tags": { "type": "object", "properties": { - "bot_id": { "type": "string" }, - "integration_id": { "type": "string" }, - "premium_subscriber": { "type": "boolean" } + "bot_id": { + "type": "string" + }, + "integration_id": { + "type": "string" + }, + "premium_subscriber": { + "type": "boolean" + } }, "additionalProperties": false }, - "id": { "type": "string" } + "id": { + "type": "string" + } }, "required": ["color", "guild", "guild_id", "hoist", "id", "managed", "mentionable", "name", "permissions", "position"] }, @@ -573,22 +3879,44 @@ "items": { "type": "object", "properties": { - "channel_id": { "type": "string" }, - "message_notifications": { "type": "integer" }, - "mute_config": { "$ref": "#/components/schemas/MuteConfig" }, - "muted": { "type": "boolean" } + "channel_id": { + "type": "string" + }, + "message_notifications": { + "type": "integer" + }, + "mute_config": { + "$ref": "#/components/schemas/MuteConfig" + }, + "muted": { + "type": "boolean" + } }, "additionalProperties": false, "required": ["channel_id", "message_notifications", "mute_config", "muted"] } }, - "message_notifications": { "type": "integer" }, - "mobile_push": { "type": "boolean" }, - "mute_config": { "$ref": "#/components/schemas/MuteConfig" }, - "muted": { "type": "boolean" }, - "suppress_everyone": { "type": "boolean" }, - "suppress_roles": { "type": "boolean" }, - "version": { "type": "integer" } + "message_notifications": { + "type": "integer" + }, + "mobile_push": { + "type": "boolean" + }, + "mute_config": { + "$ref": "#/components/schemas/MuteConfig" + }, + "muted": { + "type": "boolean" + }, + "suppress_everyone": { + "type": "boolean" + }, + "suppress_roles": { + "type": "boolean" + }, + "version": { + "type": "integer" + } }, "required": [ "channel_overrides", @@ -603,27 +3931,64 @@ }, "MuteConfig": { "type": "object", - "properties": { "end_time": { "type": "integer" }, "selected_time_window": { "type": "integer" } }, + "properties": { + "end_time": { + "type": "integer" + }, + "selected_time_window": { + "type": "integer" + } + }, "required": ["end_time", "selected_time_window"] }, "Webhook": { "type": "object", "properties": { - "id": { "type": "string" }, - "type": { "$ref": "#/components/schemas/WebhookType" }, - "name": { "type": "string" }, - "avatar": { "type": "string" }, - "token": { "type": "string" }, - "guild_id": { "type": "string" }, - "guild": { "$ref": "#/components/schemas/Guild" }, - "channel_id": { "type": "string" }, - "channel": { "$ref": "#/components/schemas/Channel" }, - "application_id": { "type": "string" }, - "application": { "$ref": "#/components/schemas/Application" }, - "user_id": { "type": "string" }, - "user": { "$ref": "#/components/schemas/User" }, - "source_guild_id": { "type": "string" }, - "source_guild": { "$ref": "#/components/schemas/Guild" } + "id": { + "type": "string" + }, + "type": { + "$ref": "#/components/schemas/WebhookType" + }, + "name": { + "type": "string" + }, + "avatar": { + "type": "string" + }, + "token": { + "type": "string" + }, + "guild_id": { + "type": "string" + }, + "guild": { + "$ref": "#/components/schemas/Guild" + }, + "channel_id": { + "type": "string" + }, + "channel": { + "$ref": "#/components/schemas/Channel" + }, + "application_id": { + "type": "string" + }, + "application": { + "$ref": "#/components/schemas/Application" + }, + "user_id": { + "type": "string" + }, + "user": { + "$ref": "#/components/schemas/User" + }, + "source_guild_id": { + "type": "string" + }, + "source_guild": { + "$ref": "#/components/schemas/Guild" + } }, "required": [ "application", @@ -640,98 +4005,225 @@ "user_id" ] }, - "WebhookType": { "enum": [1, 2], "type": "number" }, + "WebhookType": { + "enum": [1, 2], + "type": "number" + }, "Application": { "type": "object", "properties": { - "name": { "type": "string" }, - "icon": { "type": "string" }, - "description": { "type": "string" }, - "rpc_origins": { "type": "array", "items": { "type": "string" } }, - "bot_public": { "type": "boolean" }, - "bot_require_code_grant": { "type": "boolean" }, - "terms_of_service_url": { "type": "string" }, - "privacy_policy_url": { "type": "string" }, - "owner": { "$ref": "#/components/schemas/User" }, - "summary": { "type": "string" }, - "verify_key": { "type": "string" }, - "team": { "$ref": "#/components/schemas/Team" }, - "guild": { "$ref": "#/components/schemas/Guild" }, - "primary_sku_id": { "type": "string" }, - "slug": { "type": "string" }, - "cover_image": { "type": "string" }, - "flags": { "type": "string" }, - "id": { "type": "string" } + "name": { + "type": "string" + }, + "icon": { + "type": "string" + }, + "description": { + "type": "string" + }, + "rpc_origins": { + "type": "array", + "items": { + "type": "string" + } + }, + "bot_public": { + "type": "boolean" + }, + "bot_require_code_grant": { + "type": "boolean" + }, + "terms_of_service_url": { + "type": "string" + }, + "privacy_policy_url": { + "type": "string" + }, + "owner": { + "$ref": "#/components/schemas/User" + }, + "summary": { + "type": "string" + }, + "verify_key": { + "type": "string" + }, + "team": { + "$ref": "#/components/schemas/Team" + }, + "guild": { + "$ref": "#/components/schemas/Guild" + }, + "primary_sku_id": { + "type": "string" + }, + "slug": { + "type": "string" + }, + "cover_image": { + "type": "string" + }, + "flags": { + "type": "string" + }, + "id": { + "type": "string" + } }, "required": ["bot_public", "bot_require_code_grant", "description", "flags", "guild", "id", "name", "verify_key"] }, "Sticker": { "type": "object", "properties": { - "name": { "type": "string" }, - "description": { "type": "string" }, - "tags": { "type": "string" }, - "pack_id": { "type": "string" }, - "guild_id": { "type": "string" }, - "guild": { "$ref": "#/components/schemas/Guild" }, - "type": { "$ref": "#/components/schemas/StickerType" }, - "format_type": { "$ref": "#/components/schemas/StickerFormatType" }, - "id": { "type": "string" } + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "tags": { + "type": "string" + }, + "pack_id": { + "type": "string" + }, + "guild_id": { + "type": "string" + }, + "guild": { + "$ref": "#/components/schemas/Guild" + }, + "type": { + "$ref": "#/components/schemas/StickerType" + }, + "format_type": { + "$ref": "#/components/schemas/StickerFormatType" + }, + "id": { + "type": "string" + } }, "required": ["format_type", "id", "name", "pack_id", "tags", "type"] }, - "StickerType": { "enum": [1, 2], "type": "number" }, - "StickerFormatType": { "enum": [1, 2, 3], "type": "number" }, + "StickerType": { + "enum": [1, 2], + "type": "number" + }, + "StickerFormatType": { + "enum": [1, 2, 3], + "type": "number" + }, "Attachment": { "type": "object", "properties": { - "filename": { "type": "string" }, - "size": { "type": "integer" }, - "url": { "type": "string" }, - "proxy_url": { "type": "string" }, - "height": { "type": "integer" }, - "width": { "type": "integer" }, - "content_type": { "type": "string" }, - "message_id": { "type": "string" }, - "message": { "$ref": "#/components/schemas/Message" }, - "id": { "type": "string" } + "filename": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "url": { + "type": "string" + }, + "proxy_url": { + "type": "string" + }, + "height": { + "type": "integer" + }, + "width": { + "type": "integer" + }, + "content_type": { + "type": "string" + }, + "message_id": { + "type": "string" + }, + "message": { + "$ref": "#/components/schemas/Message" + }, + "id": { + "type": "string" + } }, "required": ["filename", "id", "message", "message_id", "proxy_url", "size", "url"] }, "Embed": { "type": "object", "properties": { - "title": { "type": "string" }, - "type": { "$ref": "#/components/schemas/EmbedType" }, - "description": { "type": "string" }, - "url": { "type": "string" }, - "timestamp": { "type": "string", "format": "date-time" }, - "color": { "type": "integer" }, + "title": { + "type": "string" + }, + "type": { + "enum": ["article", "gifv", "image", "link", "rich", "video"], + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + }, + "timestamp": { + "type": "string", + "format": "date-time" + }, + "color": { + "type": "integer" + }, "footer": { "type": "object", "properties": { - "text": { "type": "string" }, - "icon_url": { "type": "string" }, - "proxy_icon_url": { "type": "string" } + "text": { + "type": "string" + }, + "icon_url": { + "type": "string" + }, + "proxy_icon_url": { + "type": "string" + } }, "additionalProperties": false, "required": ["text"] }, - "image": { "$ref": "#/components/schemas/EmbedImage" }, - "thumbnail": { "$ref": "#/components/schemas/EmbedImage" }, - "video": { "$ref": "#/components/schemas/EmbedImage" }, + "image": { + "$ref": "#/components/schemas/EmbedImage" + }, + "thumbnail": { + "$ref": "#/components/schemas/EmbedImage" + }, + "video": { + "$ref": "#/components/schemas/EmbedImage" + }, "provider": { "type": "object", - "properties": { "name": { "type": "string" }, "url": { "type": "string" } }, + "properties": { + "name": { + "type": "string" + }, + "url": { + "type": "string" + } + }, "additionalProperties": false }, "author": { "type": "object", "properties": { - "name": { "type": "string" }, - "url": { "type": "string" }, - "icon_url": { "type": "string" }, - "proxy_icon_url": { "type": "string" } + "name": { + "type": "string" + }, + "url": { + "type": "string" + }, + "icon_url": { + "type": "string" + }, + "proxy_icon_url": { + "type": "string" + } }, "additionalProperties": false }, @@ -739,94 +4231,214 @@ "type": "array", "items": { "type": "object", - "properties": { "name": { "type": "string" }, "value": { "type": "string" }, "inline": { "type": "boolean" } }, + "properties": { + "name": { + "type": "string" + }, + "value": { + "type": "string" + }, + "inline": { + "type": "boolean" + } + }, "additionalProperties": false, "required": ["name", "value"] } } } }, - "EmbedType": { "enum": ["article", "gifv", "image", "link", "rich", "video"], "type": "string" }, + "EmbedType": { + "enum": ["article", "gifv", "image", "link", "rich", "video"], + "type": "string" + }, "EmbedImage": { "type": "object", "properties": { - "url": { "type": "string" }, - "proxy_url": { "type": "string" }, - "height": { "type": "integer" }, - "width": { "type": "integer" } + "url": { + "type": "string" + }, + "proxy_url": { + "type": "string" + }, + "height": { + "type": "integer" + }, + "width": { + "type": "integer" + } } }, "Reaction": { "type": "object", "properties": { - "count": { "type": "integer" }, - "emoji": { "$ref": "#/components/schemas/PartialEmoji" }, - "user_ids": { "type": "array", "items": { "type": "string" } } + "count": { + "type": "integer" + }, + "emoji": { + "$ref": "#/components/schemas/PartialEmoji" + }, + "user_ids": { + "type": "array", + "items": { + "type": "string" + } + } }, "required": ["count", "emoji", "user_ids"] }, "PartialEmoji": { "type": "object", - "properties": { "id": { "type": "string" }, "name": { "type": "string" }, "animated": { "type": "boolean" } }, + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "animated": { + "type": "boolean" + } + }, "required": ["name"] }, - "MessageType": { "enum": [0, 1, 10, 11, 12, 14, 15, 19, 2, 20, 3, 4, 5, 6, 7, 8, 9], "type": "number" }, - "InteractionType": { "enum": [1, 2], "type": "number" }, + "MessageType": { + "enum": [0, 1, 10, 11, 12, 14, 15, 19, 2, 20, 3, 4, 5, 6, 7, 8, 9], + "type": "number" + }, + "InteractionType": { + "enum": [1, 2], + "type": "number" + }, "MessageComponent": { "type": "object", "properties": { - "type": { "type": "integer" }, - "style": { "type": "integer" }, - "label": { "type": "string" }, - "emoji": { "$ref": "#/components/schemas/PartialEmoji" }, - "custom_id": { "type": "string" }, - "url": { "type": "string" }, - "disabled": { "type": "boolean" }, - "components": { "type": "array", "items": { "$ref": "#/components/schemas/MessageComponent" } } + "type": { + "type": "integer" + }, + "style": { + "type": "integer" + }, + "label": { + "type": "string" + }, + "emoji": { + "$ref": "#/components/schemas/PartialEmoji" + }, + "custom_id": { + "type": "string" + }, + "url": { + "type": "string" + }, + "disabled": { + "type": "boolean" + }, + "components": { + "type": "array", + "items": { + "$ref": "#/components/schemas/MessageComponent" + } + } }, "required": ["components", "type"] }, "ChannelPermissionOverwrite": { "type": "object", "properties": { - "allow": { "type": "number" }, - "deny": { "type": "number" }, - "id": { "type": "string" }, - "type": { "$ref": "#/components/schemas/ChannelPermissionOverwriteType" } + "allow": { + "type": "number" + }, + "deny": { + "type": "number" + }, + "id": { + "type": "string" + }, + "type": { + "$ref": "#/components/schemas/ChannelPermissionOverwriteType" + } }, "required": ["allow", "deny", "id", "type"] }, - "ChannelPermissionOverwriteType": { "enum": [0, 1], "type": "number" }, + "ChannelPermissionOverwriteType": { + "enum": [0, 1], + "type": "number" + }, "Ban": { "type": "object", "properties": { - "user_id": { "type": "string" }, - "user": { "$ref": "#/components/schemas/User" }, - "guild_id": { "type": "string" }, - "guild": { "$ref": "#/components/schemas/Guild" }, - "executor_id": { "type": "string" }, - "executor": { "$ref": "#/components/schemas/User" }, - "ip": { "type": "string" }, - "reason": { "type": "string" }, - "id": { "type": "string" } + "user_id": { + "type": "string" + }, + "user": { + "$ref": "#/components/schemas/User" + }, + "guild_id": { + "type": "string" + }, + "guild": { + "$ref": "#/components/schemas/Guild" + }, + "executor_id": { + "type": "string" + }, + "executor": { + "$ref": "#/components/schemas/User" + }, + "ip": { + "type": "string" + }, + "reason": { + "type": "string" + }, + "id": { + "type": "string" + } }, "required": ["executor", "executor_id", "guild", "guild_id", "id", "ip", "user", "user_id"] }, "Template": { "type": "object", "properties": { - "code": { "type": "string" }, - "name": { "type": "string" }, - "description": { "type": "string" }, - "usage_count": { "type": "integer" }, - "creator_id": { "type": "string" }, - "creator": { "$ref": "#/components/schemas/User" }, - "created_at": { "type": "string", "format": "date-time" }, - "updated_at": { "type": "string", "format": "date-time" }, - "source_guild_id": { "type": "string" }, - "source_guild": { "$ref": "#/components/schemas/Guild" }, - "serialized_source_guild": { "$ref": "#/components/schemas/Guild" }, - "id": { "type": "string" } + "code": { + "type": "string" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "usage_count": { + "type": "integer" + }, + "creator_id": { + "type": "string" + }, + "creator": { + "$ref": "#/components/schemas/User" + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "updated_at": { + "type": "string", + "format": "date-time" + }, + "source_guild_id": { + "type": "string" + }, + "source_guild": { + "$ref": "#/components/schemas/Guild" + }, + "serialized_source_guild": { + "$ref": "#/components/schemas/Guild" + }, + "id": { + "type": "string" + } }, "required": [ "code", @@ -844,37 +4456,89 @@ "Emoji": { "type": "object", "properties": { - "animated": { "type": "boolean" }, - "available": { "type": "boolean" }, - "guild_id": { "type": "string" }, - "guild": { "$ref": "#/components/schemas/Guild" }, - "managed": { "type": "boolean" }, - "name": { "type": "string" }, - "require_colons": { "type": "boolean" }, - "id": { "type": "string" } + "animated": { + "type": "boolean" + }, + "available": { + "type": "boolean" + }, + "guild_id": { + "type": "string" + }, + "guild": { + "$ref": "#/components/schemas/Guild" + }, + "managed": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "require_colons": { + "type": "boolean" + }, + "id": { + "type": "string" + } }, "required": ["animated", "available", "guild", "guild_id", "id", "managed", "name", "require_colons"] }, "Invite": { "type": "object", "properties": { - "code": { "type": "string" }, - "temporary": { "type": "boolean" }, - "uses": { "type": "integer" }, - "max_uses": { "type": "integer" }, - "max_age": { "type": "integer" }, - "created_at": { "type": "string", "format": "date-time" }, - "expires_at": { "type": "string", "format": "date-time" }, - "guild_id": { "type": "string" }, - "guild": { "$ref": "#/components/schemas/Guild" }, - "channel_id": { "type": "string" }, - "channel": { "$ref": "#/components/schemas/Channel" }, - "inviter_id": { "type": "string" }, - "inviter": { "$ref": "#/components/schemas/User" }, - "target_user_id": { "type": "string" }, - "target_user": { "type": "string" }, - "target_user_type": { "type": "integer" }, - "id": { "type": "string" } + "code": { + "type": "string" + }, + "temporary": { + "type": "boolean" + }, + "uses": { + "type": "integer" + }, + "max_uses": { + "type": "integer" + }, + "max_age": { + "type": "integer" + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "expires_at": { + "type": "string", + "format": "date-time" + }, + "guild_id": { + "type": "string" + }, + "guild": { + "$ref": "#/components/schemas/Guild" + }, + "channel_id": { + "type": "string" + }, + "channel": { + "$ref": "#/components/schemas/Channel" + }, + "inviter_id": { + "type": "string" + }, + "inviter": { + "$ref": "#/components/schemas/User" + }, + "target_user_id": { + "type": "string" + }, + "target_user": { + "type": "string" + }, + "target_user_type": { + "type": "integer" + }, + "id": { + "type": "string" + } }, "required": [ "channel", @@ -897,21 +4561,51 @@ "VoiceState": { "type": "object", "properties": { - "guild_id": { "type": "string" }, - "guild": { "$ref": "#/components/schemas/Guild" }, - "channel_id": { "type": "string" }, - "channel": { "$ref": "#/components/schemas/Channel" }, - "user_id": { "type": "string" }, - "user": { "$ref": "#/components/schemas/User" }, - "session_id": { "type": "string" }, - "deaf": { "type": "boolean" }, - "mute": { "type": "boolean" }, - "self_deaf": { "type": "boolean" }, - "self_mute": { "type": "boolean" }, - "self_stream": { "type": "boolean" }, - "self_video": { "type": "boolean" }, - "suppress": { "type": "boolean" }, - "id": { "type": "string" } + "guild_id": { + "type": "string" + }, + "guild": { + "$ref": "#/components/schemas/Guild" + }, + "channel_id": { + "type": "string" + }, + "channel": { + "$ref": "#/components/schemas/Channel" + }, + "user_id": { + "type": "string" + }, + "user": { + "$ref": "#/components/schemas/User" + }, + "session_id": { + "type": "string" + }, + "deaf": { + "type": "boolean" + }, + "mute": { + "type": "boolean" + }, + "self_deaf": { + "type": "boolean" + }, + "self_mute": { + "type": "boolean" + }, + "self_stream": { + "type": "boolean" + }, + "self_video": { + "type": "boolean" + }, + "suppress": { + "type": "boolean" + }, + "id": { + "type": "string" + } }, "required": [ "channel", @@ -939,151 +4633,386 @@ "AuditLogChange": { "type": "object", "properties": { - "new_value": { "$ref": "#/components/schemas/AuditLogChangeValue" }, - "old_value": { "$ref": "#/components/schemas/AuditLogChangeValue" }, - "key": { "type": "string" } + "new_value": { + "$ref": "#/components/schemas/AuditLogChangeValue" + }, + "old_value": { + "$ref": "#/components/schemas/AuditLogChangeValue" + }, + "key": { + "type": "string" + } }, "required": ["key"] }, "AuditLogChangeValue": { "type": "object", "properties": { - "name": { "type": "string" }, - "description": { "type": "string" }, - "icon_hash": { "type": "string" }, - "splash_hash": { "type": "string" }, - "discovery_splash_hash": { "type": "string" }, - "banner_hash": { "type": "string" }, - "owner_id": { "type": "string" }, - "region": { "type": "string" }, - "preferred_locale": { "type": "string" }, - "afk_channel_id": { "type": "string" }, - "afk_timeout": { "type": "integer" }, - "rules_channel_id": { "type": "string" }, - "public_updates_channel_id": { "type": "string" }, - "mfa_level": { "type": "integer" }, - "verification_level": { "type": "integer" }, - "explicit_content_filter": { "type": "integer" }, - "default_message_notifications": { "type": "integer" }, - "vanity_url_code": { "type": "string" }, - "$add": { "type": "array", "items": { "type": "object", "properties": {} } }, - "$remove": { "type": "array", "items": { "type": "object", "properties": {} } }, - "prune_delete_days": { "type": "integer" }, - "widget_enabled": { "type": "boolean" }, - "widget_channel_id": { "type": "string" }, - "system_channel_id": { "type": "string" }, - "position": { "type": "integer" }, - "topic": { "type": "string" }, - "bitrate": { "type": "integer" }, - "permission_overwrites": { "type": "array", "items": { "$ref": "#/components/schemas/ChannelPermissionOverwrite" } }, - "nsfw": { "type": "boolean" }, - "application_id": { "type": "string" }, - "rate_limit_per_user": { "type": "integer" }, - "permissions": { "type": "string" }, - "color": { "type": "integer" }, - "hoist": { "type": "boolean" }, - "mentionable": { "type": "boolean" }, - "allow": { "type": "string" }, - "deny": { "type": "string" }, - "code": { "type": "string" }, - "channel_id": { "type": "string" }, - "inviter_id": { "type": "string" }, - "max_uses": { "type": "integer" }, - "uses": { "type": "integer" }, - "max_age": { "type": "integer" }, - "temporary": { "type": "boolean" }, - "deaf": { "type": "boolean" }, - "mute": { "type": "boolean" }, - "nick": { "type": "string" }, - "avatar_hash": { "type": "string" }, - "id": { "type": "string" }, - "type": { "type": "integer" }, - "enable_emoticons": { "type": "boolean" }, - "expire_behavior": { "type": "integer" }, - "expire_grace_period": { "type": "integer" }, - "user_limit": { "type": "integer" } + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "icon_hash": { + "type": "string" + }, + "splash_hash": { + "type": "string" + }, + "discovery_splash_hash": { + "type": "string" + }, + "banner_hash": { + "type": "string" + }, + "owner_id": { + "type": "string" + }, + "region": { + "type": "string" + }, + "preferred_locale": { + "type": "string" + }, + "afk_channel_id": { + "type": "string" + }, + "afk_timeout": { + "type": "integer" + }, + "rules_channel_id": { + "type": "string" + }, + "public_updates_channel_id": { + "type": "string" + }, + "mfa_level": { + "type": "integer" + }, + "verification_level": { + "type": "integer" + }, + "explicit_content_filter": { + "type": "integer" + }, + "default_message_notifications": { + "type": "integer" + }, + "vanity_url_code": { + "type": "string" + }, + "$add": { + "type": "array", + "items": { + "type": "object", + "properties": {} + } + }, + "$remove": { + "type": "array", + "items": { + "type": "object", + "properties": {} + } + }, + "prune_delete_days": { + "type": "integer" + }, + "widget_enabled": { + "type": "boolean" + }, + "widget_channel_id": { + "type": "string" + }, + "system_channel_id": { + "type": "string" + }, + "position": { + "type": "integer" + }, + "topic": { + "type": "string" + }, + "bitrate": { + "type": "integer" + }, + "permission_overwrites": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ChannelPermissionOverwrite" + } + }, + "nsfw": { + "type": "boolean" + }, + "application_id": { + "type": "string" + }, + "rate_limit_per_user": { + "type": "integer" + }, + "permissions": { + "type": "string" + }, + "color": { + "type": "integer" + }, + "hoist": { + "type": "boolean" + }, + "mentionable": { + "type": "boolean" + }, + "allow": { + "type": "string" + }, + "deny": { + "type": "string" + }, + "code": { + "type": "string" + }, + "channel_id": { + "type": "string" + }, + "inviter_id": { + "type": "string" + }, + "max_uses": { + "type": "integer" + }, + "uses": { + "type": "integer" + }, + "max_age": { + "type": "integer" + }, + "temporary": { + "type": "boolean" + }, + "deaf": { + "type": "boolean" + }, + "mute": { + "type": "boolean" + }, + "nick": { + "type": "string" + }, + "avatar_hash": { + "type": "string" + }, + "id": { + "type": "string" + }, + "type": { + "type": "integer" + }, + "enable_emoticons": { + "type": "boolean" + }, + "expire_behavior": { + "type": "integer" + }, + "expire_grace_period": { + "type": "integer" + }, + "user_limit": { + "type": "integer" + } } }, "AuditLog": { "type": "object", "properties": { - "target": { "$ref": "#/components/schemas/User" }, - "user_id": { "type": "string" }, - "user": { "$ref": "#/components/schemas/User" }, - "action_type": { "$ref": "#/components/schemas/AuditLogEvents" }, + "target": { + "$ref": "#/components/schemas/User" + }, + "user_id": { + "type": "string" + }, + "user": { + "$ref": "#/components/schemas/User" + }, + "action_type": { + "$ref": "#/components/schemas/AuditLogEvents" + }, "options": { "type": "object", "properties": { - "delete_member_days": { "type": "string" }, - "members_removed": { "type": "string" }, - "channel_id": { "type": "string" }, - "messaged_id": { "type": "string" }, - "count": { "type": "string" }, - "id": { "type": "string" }, - "type": { "type": "string" }, - "role_name": { "type": "string" } + "delete_member_days": { + "type": "string" + }, + "members_removed": { + "type": "string" + }, + "channel_id": { + "type": "string" + }, + "messaged_id": { + "type": "string" + }, + "count": { + "type": "string" + }, + "id": { + "type": "string" + }, + "type": { + "type": "string" + }, + "role_name": { + "type": "string" + } }, "additionalProperties": false }, - "changes": { "type": "array", "items": { "$ref": "#/components/schemas/AuditLogChange" } }, - "reason": { "type": "string" }, - "id": { "type": "string" } + "changes": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AuditLogChange" + } + }, + "reason": { + "type": "string" + }, + "id": { + "type": "string" + } }, "required": ["action_type", "changes", "id", "user", "user_id"] }, "ReadState": { "type": "object", "properties": { - "channel_id": { "type": "string" }, - "channel": { "$ref": "#/components/schemas/Channel" }, - "user_id": { "type": "string" }, - "user": { "$ref": "#/components/schemas/User" }, - "last_message_id": { "type": "string" }, - "last_message": { "$ref": "#/components/schemas/Message" }, - "last_pin_timestamp": { "type": "string", "format": "date-time" }, - "mention_count": { "type": "integer" }, - "manual": { "type": "boolean" }, - "id": { "type": "string" } + "channel_id": { + "type": "string" + }, + "channel": { + "$ref": "#/components/schemas/Channel" + }, + "user_id": { + "type": "string" + }, + "user": { + "$ref": "#/components/schemas/User" + }, + "last_message_id": { + "type": "string" + }, + "last_message": { + "$ref": "#/components/schemas/Message" + }, + "last_pin_timestamp": { + "type": "string", + "format": "date-time" + }, + "mention_count": { + "type": "integer" + }, + "manual": { + "type": "boolean" + }, + "id": { + "type": "string" + } }, "required": ["channel", "channel_id", "id", "last_message_id", "manual", "mention_count", "user", "user_id"] }, "UserPublic": { "type": "object", "properties": { - "username": { "type": "string" }, - "discriminator": { "type": "string" }, - "id": { "type": "string" }, - "public_flags": { "type": "string" }, - "avatar": { "type": "string" }, - "accent_color": { "type": "integer" }, - "banner": { "type": "string" }, - "bio": { "type": "string" }, - "bot": { "type": "boolean" } + "username": { + "type": "string" + }, + "discriminator": { + "type": "string" + }, + "id": { + "type": "string" + }, + "public_flags": { + "type": "integer" + }, + "avatar": { + "type": "string" + }, + "accent_color": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "bio": { + "type": "string" + }, + "bot": { + "type": "boolean" + } }, "required": ["bio", "bot", "discriminator", "id", "public_flags", "username"] }, "UserPrivate": { "type": "object", "properties": { - "locale": { "type": "string" }, - "disabled": { "type": "boolean" }, - "username": { "type": "string" }, - "discriminator": { "type": "string" }, - "id": { "type": "string" }, - "public_flags": { "type": "string" }, - "avatar": { "type": "string" }, - "accent_color": { "type": "integer" }, - "banner": { "type": "string" }, - "bio": { "type": "string" }, - "bot": { "type": "boolean" }, - "flags": { "type": "string" }, - "mfa_enabled": { "type": "boolean" }, - "email": { "type": "string" }, - "phone": { "type": "string" }, - "verified": { "type": "boolean" }, - "nsfw_allowed": { "type": "boolean" }, - "premium": { "type": "boolean" }, - "premium_type": { "type": "integer" } + "locale": { + "type": "string" + }, + "disabled": { + "type": "boolean" + }, + "username": { + "type": "string" + }, + "discriminator": { + "type": "string" + }, + "id": { + "type": "string" + }, + "public_flags": { + "type": "string" + }, + "avatar": { + "type": "string" + }, + "accent_color": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "bio": { + "type": "string" + }, + "bot": { + "type": "boolean" + }, + "flags": { + "type": "string" + }, + "mfa_enabled": { + "type": "boolean" + }, + "email": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "verified": { + "type": "boolean" + }, + "nsfw_allowed": { + "type": "boolean" + }, + "premium": { + "type": "boolean" + }, + "premium_type": { + "type": "integer" + } }, "required": [ "bio", @@ -1104,50 +5033,111 @@ }, "BanCreateSchema": { "type": "object", - "properties": { "delete_message_days": { "type": "string" }, "reason": { "type": "string" } } + "properties": { + "delete_message_days": { + "type": "string" + }, + "reason": { + "type": "string" + } + } }, "DmChannelCreateSchema": { "type": "object", - "properties": { "name": { "type": "string" }, "recipients": { "type": "array", "items": { "type": "string" } } }, + "properties": { + "name": { + "type": "string" + }, + "recipients": { + "type": "array", + "items": { + "type": "string" + } + } + }, "required": ["recipients"] }, "ChannelModifySchema": { "type": "object", "properties": { - "name": { "type": "string" }, - "type": { "type": "integer" }, - "topic": { "type": "string" }, - "bitrate": { "type": "integer" }, - "user_limit": { "type": "integer" }, - "rate_limit_per_user": { "type": "integer" }, - "position": { "type": "integer" }, + "name": { + "maxLength": 100, + "type": "string" + }, + "type": { + "enum": [0, 1, 10, 11, 12, 13, 2, 3, 4, 5, 6], + "type": "number" + }, + "topic": { + "type": "string" + }, + "icon": { + "type": "string", + "nullable": true + }, + "bitrate": { + "type": "integer" + }, + "user_limit": { + "type": "integer" + }, + "rate_limit_per_user": { + "type": "integer" + }, + "position": { + "type": "integer" + }, "permission_overwrites": { "type": "array", "items": { "type": "object", "properties": { - "id": { "type": "string" }, - "type": { "type": "integer" }, - "allow": { "type": "number" }, - "deny": { "type": "number" } + "id": { + "type": "string" + }, + "type": { + "$ref": "#/components/schemas/ChannelPermissionOverwriteType" + }, + "allow": { + "type": "number" + }, + "deny": { + "type": "number" + } }, "additionalProperties": false, "required": ["allow", "deny", "id", "type"] } }, - "parent_id": { "type": "string" }, - "id": { "type": "string" }, - "nsfw": { "type": "boolean" }, - "rtc_region": { "type": "string" }, - "default_auto_archive_duration": { "type": "integer" } - }, - "required": ["name", "type"] + "parent_id": { + "type": "string" + }, + "id": { + "type": "string" + }, + "nsfw": { + "type": "boolean" + }, + "rtc_region": { + "type": "string" + }, + "default_auto_archive_duration": { + "type": "integer" + } + } }, "ChannelGuildPositionUpdateSchema": { "type": "array", "items": { "type": "object", - "properties": { "id": { "type": "string" }, "position": { "type": "integer" } }, + "properties": { + "id": { + "type": "string" + }, + "position": { + "type": "integer" + } + }, "additionalProperties": false, "required": ["id"] } @@ -1155,52 +5145,131 @@ "EmojiCreateSchema": { "type": "object", "properties": { - "name": { "type": "string" }, - "image": { "type": "string" }, - "roles": { "type": "array", "items": { "type": "string" } } + "name": { + "type": "string" + }, + "image": { + "type": "string" + }, + "roles": { + "type": "array", + "items": { + "type": "string" + } + } }, "required": ["image", "name"] }, "GuildCreateSchema": { "type": "object", "properties": { - "name": { "type": "string" }, - "region": { "type": "string" }, - "icon": { "type": "string" }, - "channels": { "type": "array", "items": { "$ref": "#/components/requestBodies/ChannelModifySchema" } }, - "guild_template_code": { "type": "string" }, - "system_channel_id": { "type": "string" }, - "rules_channel_id": { "type": "string" } + "name": { + "maxLength": 100, + "type": "string" + }, + "region": { + "type": "string" + }, + "icon": { + "type": "string", + "nullable": true + }, + "channels": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ChannelModifySchema" + } + }, + "guild_template_code": { + "type": "string" + }, + "system_channel_id": { + "type": "string" + }, + "rules_channel_id": { + "type": "string" + } }, "required": ["name"] }, "GuildUpdateSchema": { "type": "object", "properties": { - "banner": { "type": "string" }, - "splash": { "type": "string" }, - "description": { "type": "string" }, - "features": { "type": "array", "items": { "type": "string" } }, - "verification_level": { "type": "integer" }, - "default_message_notifications": { "type": "integer" }, - "system_channel_flags": { "type": "integer" }, - "explicit_content_filter": { "type": "integer" }, - "public_updates_channel_id": { "type": "string" }, - "afk_timeout": { "type": "integer" }, - "afk_channel_id": { "type": "string" }, - "preferred_locale": { "type": "string" }, - "name": { "type": "string" }, - "region": { "type": "string" }, - "icon": { "type": "string" }, - "guild_template_code": { "type": "string" }, - "system_channel_id": { "type": "string" }, - "rules_channel_id": { "type": "string" } + "banner": { + "type": "string", + "nullable": true + }, + "splash": { + "type": "string", + "nullable": true + }, + "description": { + "type": "string" + }, + "features": { + "type": "array", + "items": { + "type": "string" + } + }, + "verification_level": { + "type": "integer" + }, + "default_message_notifications": { + "type": "integer" + }, + "system_channel_flags": { + "type": "integer" + }, + "explicit_content_filter": { + "type": "integer" + }, + "public_updates_channel_id": { + "type": "string" + }, + "afk_timeout": { + "type": "integer" + }, + "afk_channel_id": { + "type": "string" + }, + "preferred_locale": { + "type": "string" + }, + "name": { + "maxLength": 100, + "type": "string" + }, + "region": { + "type": "string" + }, + "icon": { + "type": "string", + "nullable": true + }, + "guild_template_code": { + "type": "string" + }, + "system_channel_id": { + "type": "string" + }, + "rules_channel_id": { + "type": "string" + } }, "required": ["name"] }, "GuildTemplateCreateSchema": { "type": "object", - "properties": { "name": { "type": "string" }, "avatar": { "type": "string" } }, + "properties": { + "name": { + "type": "string" + }, + "avatar": { + "type": "string", + "nullable": true + } + }, "required": ["name"] }, "GuildUpdateWelcomeScreenSchema": { @@ -1211,225 +5280,411 @@ "items": { "type": "object", "properties": { - "channel_id": { "type": "string" }, - "description": { "type": "string" }, - "emoji_id": { "type": "string" }, - "emoji_name": { "type": "string" } + "channel_id": { + "type": "string" + }, + "description": { + "type": "string" + }, + "emoji_id": { + "type": "string" + }, + "emoji_name": { + "type": "string" + } }, "additionalProperties": false, "required": ["channel_id", "description", "emoji_name"] } }, - "enabled": { "type": "boolean" }, - "description": { "type": "string" } + "enabled": { + "type": "boolean" + }, + "description": { + "type": "string" + } } }, "InviteCreateSchema": { "type": "object", "properties": { - "target_user_id": { "type": "string" }, - "target_type": { "type": "string" }, - "validate": { "type": "string" }, - "max_age": { "type": "integer" }, - "max_uses": { "type": "integer" }, - "temporary": { "type": "boolean" }, - "unique": { "type": "boolean" }, - "target_user": { "type": "string" }, - "target_user_type": { "type": "integer" } + "target_user_id": { + "type": "string" + }, + "target_type": { + "type": "string" + }, + "validate": { + "type": "string" + }, + "max_age": { + "type": "integer" + }, + "max_uses": { + "type": "integer" + }, + "temporary": { + "type": "boolean" + }, + "unique": { + "type": "boolean" + }, + "target_user": { + "type": "string" + }, + "target_user_type": { + "type": "integer" + } } }, "MemberCreateSchema": { "type": "object", "properties": { - "id": { "type": "string" }, - "nick": { "type": "string" }, - "guild_id": { "type": "string" }, - "joined_at": { "type": "string", "format": "date-time" } + "id": { + "type": "string" + }, + "nick": { + "type": "string" + }, + "guild_id": { + "type": "string" + }, + "joined_at": { + "type": "string", + "format": "date-time" + } }, "required": ["guild_id", "id", "joined_at", "nick"] }, - "MemberNickChangeSchema": { "type": "object", "properties": { "nick": { "type": "string" } }, "required": ["nick"] }, - "MemberChangeSchema": { "type": "object", "properties": { "roles": { "type": "array", "items": { "type": "string" } } } }, + "MemberNickChangeSchema": { + "type": "object", + "properties": { + "nick": { + "type": "string" + } + }, + "required": ["nick"] + }, + "MemberChangeSchema": { + "type": "object", + "properties": { + "roles": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "MessageCreateSchema": { "type": "object", "properties": { - "content": { "type": "string" }, - "nonce": { "type": "string" }, - "tts": { "type": "boolean" }, - "flags": { "type": "string" }, + "content": { + "type": "string" + }, + "nonce": { + "type": "string" + }, + "tts": { + "type": "boolean" + }, + "flags": { + "type": "string" + }, + "embeds": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Embed" + } + }, "embed": { - "additionalProperties": false, + "$ref": "#/components/schemas/Embed" + }, + "allowed_mentions": { "type": "object", "properties": { - "title": { "type": "string" }, - "type": { "$ref": "#/components/requestBodies/EmbedType" }, - "description": { "type": "string" }, - "url": { "type": "string" }, - "timestamp": { "type": "string" }, - "color": { "type": "integer" }, - "footer": { - "type": "object", - "properties": { - "text": { "type": "string" }, - "icon_url": { "type": "string" }, - "proxy_icon_url": { "type": "string" } - }, - "additionalProperties": false, - "required": ["text"] - }, - "image": { "$ref": "#/components/requestBodies/EmbedImage" }, - "thumbnail": { "$ref": "#/components/requestBodies/EmbedImage" }, - "video": { "$ref": "#/components/requestBodies/EmbedImage" }, - "provider": { - "type": "object", - "properties": { "name": { "type": "string" }, "url": { "type": "string" } }, - "additionalProperties": false + "parse": { + "type": "array", + "items": { + "type": "string" + } }, - "author": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "url": { "type": "string" }, - "icon_url": { "type": "string" }, - "proxy_icon_url": { "type": "string" } - }, - "additionalProperties": false + "roles": { + "type": "array", + "items": { + "type": "string" + } }, - "fields": { + "users": { "type": "array", "items": { - "type": "object", - "properties": { - "name": { "type": "string" }, - "value": { "type": "string" }, - "inline": { "type": "boolean" } - }, - "additionalProperties": false, - "required": ["name", "value"] + "type": "string" } + }, + "replied_user": { + "type": "boolean" } - } - }, - "allowed_mentions": { - "type": "object", - "properties": { - "parse": { "type": "array", "items": { "type": "string" } }, - "roles": { "type": "array", "items": { "type": "string" } }, - "users": { "type": "array", "items": { "type": "string" } }, - "replied_user": { "type": "boolean" } }, "additionalProperties": false }, "message_reference": { "type": "object", "properties": { - "message_id": { "type": "string" }, - "channel_id": { "type": "string" }, - "guild_id": { "type": "string" }, - "fail_if_not_exists": { "type": "boolean" } + "message_id": { + "type": "string" + }, + "channel_id": { + "type": "string" + }, + "guild_id": { + "type": "string" + }, + "fail_if_not_exists": { + "type": "boolean" + } }, "additionalProperties": false, "required": ["channel_id", "message_id"] }, - "payload_json": { "type": "string" }, - "file": {} + "payload_json": { + "type": "string" + }, + "file": {}, + "attachments": { + "type": "array", + "items": {} + } } }, "RoleModifySchema": { "type": "object", "properties": { - "name": { "type": "string" }, - "permissions": { "type": "number" }, - "color": { "type": "integer" }, - "hoist": { "type": "boolean" }, - "mentionable": { "type": "boolean" }, - "position": { "type": "integer" } + "name": { + "type": "string" + }, + "permissions": { + "type": "number" + }, + "color": { + "type": "integer" + }, + "hoist": { + "type": "boolean" + }, + "mentionable": { + "type": "boolean" + }, + "position": { + "type": "integer" + } } }, "TemplateCreateSchema": { "type": "object", - "properties": { "name": { "type": "string" }, "description": { "type": "string" } }, + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + } + }, "required": ["name"] }, "TemplateModifySchema": { "type": "object", - "properties": { "name": { "type": "string" }, "description": { "type": "string" } }, + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + } + }, "required": ["name"] }, "UserModifySchema": { "type": "object", "properties": { - "username": { "type": "string" }, - "avatar": { "type": "string" }, - "bio": { "type": "string" }, - "accent_color": { "type": "integer" }, - "banner": { "type": "string" }, - "password": { "type": "string" }, - "new_password": { "type": "string" }, - "code": { "type": "string" } + "username": { + "minLength": 1, + "maxLength": 100, + "type": "string" + }, + "avatar": { + "type": "string", + "nullable": true + }, + "bio": { + "maxLength": 1024, + "type": "string" + }, + "accent_color": { + "type": "integer" + }, + "banner": { + "type": "string", + "nullable": true + }, + "password": { + "type": "string" + }, + "new_password": { + "type": "string" + }, + "code": { + "type": "string" + } } }, "UserSettingsSchema": { "type": "object", "properties": { - "afk_timeout": { "type": "integer" }, - "allow_accessibility_detection": { "type": "boolean" }, - "animate_emoji": { "type": "boolean" }, - "animate_stickers": { "type": "integer" }, - "contact_sync_enabled": { "type": "boolean" }, - "convert_emoticons": { "type": "boolean" }, + "afk_timeout": { + "type": "integer" + }, + "allow_accessibility_detection": { + "type": "boolean" + }, + "animate_emoji": { + "type": "boolean" + }, + "animate_stickers": { + "type": "integer" + }, + "contact_sync_enabled": { + "type": "boolean" + }, + "convert_emoticons": { + "type": "boolean" + }, "custom_status": { "type": "object", "properties": { - "emoji_id": { "type": "string" }, - "emoji_name": { "type": "string" }, - "expires_at": { "type": "integer" }, - "text": { "type": "string" } + "emoji_id": { + "type": "string" + }, + "emoji_name": { + "type": "string" + }, + "expires_at": { + "type": "integer" + }, + "text": { + "type": "string" + } }, "additionalProperties": false }, - "default_guilds_restricted": { "type": "boolean" }, - "detect_platform_accounts": { "type": "boolean" }, - "developer_mode": { "type": "boolean" }, - "disable_games_tab": { "type": "boolean" }, - "enable_tts_command": { "type": "boolean" }, - "explicit_content_filter": { "type": "integer" }, + "default_guilds_restricted": { + "type": "boolean" + }, + "detect_platform_accounts": { + "type": "boolean" + }, + "developer_mode": { + "type": "boolean" + }, + "disable_games_tab": { + "type": "boolean" + }, + "enable_tts_command": { + "type": "boolean" + }, + "explicit_content_filter": { + "type": "integer" + }, "friend_source_flags": { "type": "object", - "properties": { "all": { "type": "boolean" } }, + "properties": { + "all": { + "type": "boolean" + } + }, "additionalProperties": false, "required": ["all"] }, - "gateway_connected": { "type": "boolean" }, - "gif_auto_play": { "type": "boolean" }, + "gateway_connected": { + "type": "boolean" + }, + "gif_auto_play": { + "type": "boolean" + }, "guild_folders": { "type": "array", "items": { "type": "object", "properties": { - "color": { "type": "integer" }, - "guild_ids": { "type": "array", "items": { "type": "string" } }, - "id": { "type": "integer" }, - "name": { "type": "string" } + "color": { + "type": "integer" + }, + "guild_ids": { + "type": "array", + "items": { + "type": "string" + } + }, + "id": { + "type": "integer" + }, + "name": { + "type": "string" + } }, "additionalProperties": false, "required": ["color", "guild_ids", "id", "name"] } }, - "guild_positions": { "type": "array", "items": { "type": "string" } }, - "inline_attachment_media": { "type": "boolean" }, - "inline_embed_media": { "type": "boolean" }, - "locale": { "type": "string" }, - "message_display_compact": { "type": "boolean" }, - "native_phone_integration_enabled": { "type": "boolean" }, - "render_embeds": { "type": "boolean" }, - "render_reactions": { "type": "boolean" }, - "restricted_guilds": { "type": "array", "items": { "type": "string" } }, - "show_current_game": { "type": "boolean" }, - "status": { "enum": ["dnd", "idle", "offline", "online"], "type": "string" }, - "stream_notifications_enabled": { "type": "boolean" }, - "theme": { "enum": ["dark", "white"], "type": "string" }, - "timezone_offset": { "type": "integer" } + "guild_positions": { + "type": "array", + "items": { + "type": "string" + } + }, + "inline_attachment_media": { + "type": "boolean" + }, + "inline_embed_media": { + "type": "boolean" + }, + "locale": { + "type": "string" + }, + "message_display_compact": { + "type": "boolean" + }, + "native_phone_integration_enabled": { + "type": "boolean" + }, + "render_embeds": { + "type": "boolean" + }, + "render_reactions": { + "type": "boolean" + }, + "restricted_guilds": { + "type": "array", + "items": { + "type": "string" + } + }, + "show_current_game": { + "type": "boolean" + }, + "status": { + "enum": ["dnd", "idle", "offline", "online"], + "type": "string" + }, + "stream_notifications_enabled": { + "type": "boolean" + }, + "theme": { + "enum": ["dark", "white"], + "type": "string" + }, + "timezone_offset": { + "type": "integer" + } }, "required": [ "afk_timeout", @@ -1467,8 +5722,263 @@ }, "WidgetModifySchema": { "type": "object", - "properties": { "enabled": { "type": "boolean" }, "channel_id": { "type": "string" } }, + "properties": { + "enabled": { + "type": "boolean" + }, + "channel_id": { + "type": "string" + } + }, "required": ["channel_id", "enabled"] + }, + "RegisterSchema": { + "type": "object", + "properties": { + "username": { + "minLength": 2, + "maxLength": 32, + "type": "string" + }, + "password": { + "minLength": 1, + "maxLength": 72, + "type": "string" + }, + "consent": { + "type": "boolean" + }, + "email": { + "format": "email", + "type": "string" + }, + "fingerprint": { + "type": "string" + }, + "invite": { + "type": "string" + }, + "date_of_birth": { + "type": "string" + }, + "gift_code_sku_id": { + "type": "string" + }, + "captcha_key": { + "type": "string" + } + }, + "required": ["consent", "username"] + }, + "LoginSchema": { + "type": "object", + "properties": { + "login": { + "type": "string" + }, + "password": { + "type": "string" + }, + "undelete": { + "type": "boolean" + }, + "captcha_key": { + "type": "string" + }, + "login_source": { + "type": "string" + }, + "gift_code_sku_id": { + "type": "string" + } + }, + "required": ["login", "password"] + }, + "MessageAcknowledgeSchema": { + "type": "object", + "properties": { + "manual": { + "type": "boolean" + }, + "mention_count": { + "type": "integer" + } + } + }, + "BulkDeleteSchema": { + "type": "object", + "properties": { + "messages": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": ["messages"] + }, + "ChannelPermissionOverwriteSchema": { + "type": "object", + "properties": { + "allow": { + "type": "number" + }, + "deny": { + "type": "number" + }, + "id": { + "type": "string" + }, + "type": { + "$ref": "#/components/schemas/ChannelPermissionOverwriteType" + } + }, + "required": ["allow", "deny", "id", "type"] + }, + "WebhookCreateSchema": { + "type": "object", + "properties": { + "name": { + "maxLength": 80, + "type": "string" + }, + "avatar": { + "type": "string" + } + }, + "required": ["avatar", "name"] + }, + "ChannelReorderSchema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "position": { + "type": "integer" + }, + "lock_permissions": { + "type": "boolean" + }, + "parent_id": { + "type": "string" + } + }, + "additionalProperties": false, + "required": ["id"] + } + }, + "RolePositionUpdateSchema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "position": { + "type": "integer" + } + }, + "additionalProperties": false, + "required": ["id", "position"] + } + }, + "VanityUrlSchema": { + "type": "object", + "properties": { + "code": { + "minLength": 1, + "maxLength": 20, + "type": "string" + } + } + }, + "VoiceStateUpdateSchema": { + "type": "object", + "properties": { + "channel_id": { + "type": "string" + }, + "guild_id": { + "type": "string" + }, + "suppress": { + "type": "boolean" + }, + "request_to_speak_timestamp": { + "type": "string", + "format": "date-time" + }, + "self_mute": { + "type": "boolean" + }, + "self_deaf": { + "type": "boolean" + }, + "self_video": { + "type": "boolean" + } + }, + "required": ["channel_id"] + }, + "UserProfileResponse": { + "type": "object", + "properties": { + "user": { + "$ref": "#/components/schemas/UserPublic" + }, + "connected_accounts": { + "$ref": "#/components/schemas/PublicConnectedAccount" + }, + "premium_guild_since": { + "type": "string", + "format": "date-time" + }, + "premium_since": { + "type": "string", + "format": "date-time" + } + }, + "required": ["connected_accounts", "user"] + }, + "RelationshipPutSchema": { + "type": "object", + "properties": { + "type": { + "enum": [1, 2, 3, 4], + "type": "number" + } + } + }, + "RelationshipPostSchema": { + "type": "object", + "properties": { + "discriminator": { + "type": "string" + }, + "username": { + "type": "string" + } + }, + "required": ["discriminator", "username"] + }, + "PublicConnectedAccount": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "verifie": { + "type": "boolean" + } + }, + "required": ["name", "type", "verifie"] } }, "requestBodies": {}, @@ -1482,4 +5992,4 @@ "links": {}, "callbacks": {} } -} \ No newline at end of file +} diff --git a/api/assets/responses.json b/api/assets/responses.json deleted file mode 100644 index 35645d73..00000000 --- a/api/assets/responses.json +++ /dev/null @@ -1,90 +0,0 @@ -{ - "UserProfileResponse": { - "type": "object", - "properties": { - "user": { - "$ref": "#/definitions/UserPublic" - }, - "connected_accounts": { - "$ref": "#/definitions/PublicConnectedAccount" - }, - "premium_guild_since": { - "type": "string", - "format": "date-time" - }, - "premium_since": { - "type": "string", - "format": "date-time" - } - }, - "additionalProperties": false, - "required": [ - "connected_accounts", - "user" - ], - "definitions": { - "UserPublic": { - "type": "object", - "properties": { - "username": { - "type": "string" - }, - "discriminator": { - "type": "string" - }, - "id": { - "type": "string" - }, - "public_flags": { - "type": "string" - }, - "avatar": { - "type": "string" - }, - "accent_color": { - "type": "integer" - }, - "banner": { - "type": "string" - }, - "bio": { - "type": "string" - }, - "bot": { - "type": "boolean" - } - }, - "additionalProperties": false, - "required": [ - "bio", - "bot", - "discriminator", - "id", - "public_flags", - "username" - ] - }, - "PublicConnectedAccount": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "type": { - "type": "string" - }, - "verifie": { - "type": "boolean" - } - }, - "additionalProperties": false, - "required": [ - "name", - "type", - "verifie" - ] - } - }, - "$schema": "http://json-schema.org/draft-07/schema#" - } -} \ No newline at end of file diff --git a/api/assets/schemas.json b/api/assets/schemas.json index cc45ebb3..76ad3b16 100644 --- a/api/assets/schemas.json +++ b/api/assets/schemas.json @@ -385,6 +385,67 @@ } }, "additionalProperties": false + }, + "UserPublic": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "discriminator": { + "type": "string" + }, + "id": { + "type": "string" + }, + "public_flags": { + "type": "integer" + }, + "avatar": { + "type": "string" + }, + "accent_color": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "bio": { + "type": "string" + }, + "bot": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "bio", + "bot", + "discriminator", + "id", + "public_flags", + "username" + ] + }, + "PublicConnectedAccount": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "verifie": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "name", + "type", + "verifie" + ] } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -698,6 +759,67 @@ } }, "additionalProperties": false + }, + "UserPublic": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "discriminator": { + "type": "string" + }, + "id": { + "type": "string" + }, + "public_flags": { + "type": "integer" + }, + "avatar": { + "type": "string" + }, + "accent_color": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "bio": { + "type": "string" + }, + "bot": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "bio", + "bot", + "discriminator", + "id", + "public_flags", + "username" + ] + }, + "PublicConnectedAccount": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "verifie": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "name", + "type", + "verifie" + ] } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -960,6 +1082,67 @@ } }, "additionalProperties": false + }, + "UserPublic": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "discriminator": { + "type": "string" + }, + "id": { + "type": "string" + }, + "public_flags": { + "type": "integer" + }, + "avatar": { + "type": "string" + }, + "accent_color": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "bio": { + "type": "string" + }, + "bot": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "bio", + "bot", + "discriminator", + "id", + "public_flags", + "username" + ] + }, + "PublicConnectedAccount": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "verifie": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "name", + "type", + "verifie" + ] } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -1201,6 +1384,67 @@ } }, "additionalProperties": false + }, + "UserPublic": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "discriminator": { + "type": "string" + }, + "id": { + "type": "string" + }, + "public_flags": { + "type": "integer" + }, + "avatar": { + "type": "string" + }, + "accent_color": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "bio": { + "type": "string" + }, + "bot": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "bio", + "bot", + "discriminator", + "id", + "public_flags", + "username" + ] + }, + "PublicConnectedAccount": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "verifie": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "name", + "type", + "verifie" + ] } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -1445,6 +1689,67 @@ } }, "additionalProperties": false + }, + "UserPublic": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "discriminator": { + "type": "string" + }, + "id": { + "type": "string" + }, + "public_flags": { + "type": "integer" + }, + "avatar": { + "type": "string" + }, + "accent_color": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "bio": { + "type": "string" + }, + "bot": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "bio", + "bot", + "discriminator", + "id", + "public_flags", + "username" + ] + }, + "PublicConnectedAccount": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "verifie": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "name", + "type", + "verifie" + ] } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -1698,6 +2003,67 @@ } }, "additionalProperties": false + }, + "UserPublic": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "discriminator": { + "type": "string" + }, + "id": { + "type": "string" + }, + "public_flags": { + "type": "integer" + }, + "avatar": { + "type": "string" + }, + "accent_color": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "bio": { + "type": "string" + }, + "bot": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "bio", + "bot", + "discriminator", + "id", + "public_flags", + "username" + ] + }, + "PublicConnectedAccount": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "verifie": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "name", + "type", + "verifie" + ] } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -1944,17 +2310,78 @@ } }, "additionalProperties": false - } - }, - "$schema": "http://json-schema.org/draft-07/schema#" - }, - "BanCreateSchema": { - "type": "object", - "properties": { - "delete_message_days": { - "type": "string" }, - "reason": { + "UserPublic": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "discriminator": { + "type": "string" + }, + "id": { + "type": "string" + }, + "public_flags": { + "type": "integer" + }, + "avatar": { + "type": "string" + }, + "accent_color": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "bio": { + "type": "string" + }, + "bot": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "bio", + "bot", + "discriminator", + "id", + "public_flags", + "username" + ] + }, + "PublicConnectedAccount": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "verifie": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "name", + "type", + "verifie" + ] + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" + }, + "BanCreateSchema": { + "type": "object", + "properties": { + "delete_message_days": { + "type": "string" + }, + "reason": { "type": "string" } }, @@ -2185,6 +2612,67 @@ } }, "additionalProperties": false + }, + "UserPublic": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "discriminator": { + "type": "string" + }, + "id": { + "type": "string" + }, + "public_flags": { + "type": "integer" + }, + "avatar": { + "type": "string" + }, + "accent_color": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "bio": { + "type": "string" + }, + "bot": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "bio", + "bot", + "discriminator", + "id", + "public_flags", + "username" + ] + }, + "PublicConnectedAccount": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "verifie": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "name", + "type", + "verifie" + ] } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -2438,6 +2926,67 @@ } }, "additionalProperties": false + }, + "UserPublic": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "discriminator": { + "type": "string" + }, + "id": { + "type": "string" + }, + "public_flags": { + "type": "integer" + }, + "avatar": { + "type": "string" + }, + "accent_color": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "bio": { + "type": "string" + }, + "bot": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "bio", + "bot", + "discriminator", + "id", + "public_flags", + "username" + ] + }, + "PublicConnectedAccount": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "verifie": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "name", + "type", + "verifie" + ] } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -2704,6 +3253,67 @@ } }, "additionalProperties": false + }, + "UserPublic": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "discriminator": { + "type": "string" + }, + "id": { + "type": "string" + }, + "public_flags": { + "type": "integer" + }, + "avatar": { + "type": "string" + }, + "accent_color": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "bio": { + "type": "string" + }, + "bot": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "bio", + "bot", + "discriminator", + "id", + "public_flags", + "username" + ] + }, + "PublicConnectedAccount": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "verifie": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "name", + "type", + "verifie" + ] } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -3009,6 +3619,67 @@ } }, "additionalProperties": false + }, + "UserPublic": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "discriminator": { + "type": "string" + }, + "id": { + "type": "string" + }, + "public_flags": { + "type": "integer" + }, + "avatar": { + "type": "string" + }, + "accent_color": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "bio": { + "type": "string" + }, + "bot": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "bio", + "bot", + "discriminator", + "id", + "public_flags", + "username" + ] + }, + "PublicConnectedAccount": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "verifie": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "name", + "type", + "verifie" + ] } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -3250,6 +3921,67 @@ } }, "additionalProperties": false + }, + "UserPublic": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "discriminator": { + "type": "string" + }, + "id": { + "type": "string" + }, + "public_flags": { + "type": "integer" + }, + "avatar": { + "type": "string" + }, + "accent_color": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "bio": { + "type": "string" + }, + "bot": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "bio", + "bot", + "discriminator", + "id", + "public_flags", + "username" + ] + }, + "PublicConnectedAccount": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "verifie": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "name", + "type", + "verifie" + ] } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -3491,6 +4223,67 @@ } }, "additionalProperties": false + }, + "UserPublic": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "discriminator": { + "type": "string" + }, + "id": { + "type": "string" + }, + "public_flags": { + "type": "integer" + }, + "avatar": { + "type": "string" + }, + "accent_color": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "bio": { + "type": "string" + }, + "bot": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "bio", + "bot", + "discriminator", + "id", + "public_flags", + "username" + ] + }, + "PublicConnectedAccount": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "verifie": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "name", + "type", + "verifie" + ] } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -3744,6 +4537,67 @@ } }, "additionalProperties": false + }, + "UserPublic": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "discriminator": { + "type": "string" + }, + "id": { + "type": "string" + }, + "public_flags": { + "type": "integer" + }, + "avatar": { + "type": "string" + }, + "accent_color": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "bio": { + "type": "string" + }, + "bot": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "bio", + "bot", + "discriminator", + "id", + "public_flags", + "username" + ] + }, + "PublicConnectedAccount": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "verifie": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "name", + "type", + "verifie" + ] } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -3992,6 +4846,67 @@ } }, "additionalProperties": false + }, + "UserPublic": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "discriminator": { + "type": "string" + }, + "id": { + "type": "string" + }, + "public_flags": { + "type": "integer" + }, + "avatar": { + "type": "string" + }, + "accent_color": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "bio": { + "type": "string" + }, + "bot": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "bio", + "bot", + "discriminator", + "id", + "public_flags", + "username" + ] + }, + "PublicConnectedAccount": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "verifie": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "name", + "type", + "verifie" + ] } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -4236,6 +5151,67 @@ } }, "additionalProperties": false + }, + "UserPublic": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "discriminator": { + "type": "string" + }, + "id": { + "type": "string" + }, + "public_flags": { + "type": "integer" + }, + "avatar": { + "type": "string" + }, + "accent_color": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "bio": { + "type": "string" + }, + "bot": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "bio", + "bot", + "discriminator", + "id", + "public_flags", + "username" + ] + }, + "PublicConnectedAccount": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "verifie": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "name", + "type", + "verifie" + ] } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -4480,6 +5456,67 @@ } }, "additionalProperties": false + }, + "UserPublic": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "discriminator": { + "type": "string" + }, + "id": { + "type": "string" + }, + "public_flags": { + "type": "integer" + }, + "avatar": { + "type": "string" + }, + "accent_color": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "bio": { + "type": "string" + }, + "bot": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "bio", + "bot", + "discriminator", + "id", + "public_flags", + "username" + ] + }, + "PublicConnectedAccount": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "verifie": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "name", + "type", + "verifie" + ] } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -4720,6 +5757,67 @@ } }, "additionalProperties": false + }, + "UserPublic": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "discriminator": { + "type": "string" + }, + "id": { + "type": "string" + }, + "public_flags": { + "type": "integer" + }, + "avatar": { + "type": "string" + }, + "accent_color": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "bio": { + "type": "string" + }, + "bot": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "bio", + "bot", + "discriminator", + "id", + "public_flags", + "username" + ] + }, + "PublicConnectedAccount": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "verifie": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "name", + "type", + "verifie" + ] } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -4980,16 +6078,77 @@ } }, "additionalProperties": false - } - }, - "$schema": "http://json-schema.org/draft-07/schema#" - }, - "GuildUpdateWelcomeScreenSchema": { - "type": "object", - "properties": { - "welcome_channels": { - "type": "array", - "items": { + }, + "UserPublic": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "discriminator": { + "type": "string" + }, + "id": { + "type": "string" + }, + "public_flags": { + "type": "integer" + }, + "avatar": { + "type": "string" + }, + "accent_color": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "bio": { + "type": "string" + }, + "bot": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "bio", + "bot", + "discriminator", + "id", + "public_flags", + "username" + ] + }, + "PublicConnectedAccount": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "verifie": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "name", + "type", + "verifie" + ] + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" + }, + "GuildUpdateWelcomeScreenSchema": { + "type": "object", + "properties": { + "welcome_channels": { + "type": "array", + "items": { "type": "object", "properties": { "channel_id": { @@ -5247,6 +6406,67 @@ } }, "additionalProperties": false + }, + "UserPublic": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "discriminator": { + "type": "string" + }, + "id": { + "type": "string" + }, + "public_flags": { + "type": "integer" + }, + "avatar": { + "type": "string" + }, + "accent_color": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "bio": { + "type": "string" + }, + "bot": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "bio", + "bot", + "discriminator", + "id", + "public_flags", + "username" + ] + }, + "PublicConnectedAccount": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "verifie": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "name", + "type", + "verifie" + ] } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -5492,6 +6712,67 @@ } }, "additionalProperties": false + }, + "UserPublic": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "discriminator": { + "type": "string" + }, + "id": { + "type": "string" + }, + "public_flags": { + "type": "integer" + }, + "avatar": { + "type": "string" + }, + "accent_color": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "bio": { + "type": "string" + }, + "bot": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "bio", + "bot", + "discriminator", + "id", + "public_flags", + "username" + ] + }, + "PublicConnectedAccount": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "verifie": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "name", + "type", + "verifie" + ] } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -5502,16 +6783,330 @@ "name": { "type": "string" }, - "avatar": { - "type": [ - "null", - "string" - ] + "avatar": { + "type": [ + "null", + "string" + ] + } + }, + "additionalProperties": false, + "required": [ + "name" + ], + "definitions": { + "ChannelPermissionOverwriteType": { + "enum": [ + 0, + 1 + ], + "type": "number" + }, + "Embed": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "type": { + "enum": [ + "article", + "gifv", + "image", + "link", + "rich", + "video" + ], + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + }, + "timestamp": { + "type": "string", + "format": "date-time" + }, + "color": { + "type": "integer" + }, + "footer": { + "type": "object", + "properties": { + "text": { + "type": "string" + }, + "icon_url": { + "type": "string" + }, + "proxy_icon_url": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "text" + ] + }, + "image": { + "$ref": "#/definitions/EmbedImage" + }, + "thumbnail": { + "$ref": "#/definitions/EmbedImage" + }, + "video": { + "$ref": "#/definitions/EmbedImage" + }, + "provider": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "additionalProperties": false + }, + "author": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "url": { + "type": "string" + }, + "icon_url": { + "type": "string" + }, + "proxy_icon_url": { + "type": "string" + } + }, + "additionalProperties": false + }, + "fields": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "value": { + "type": "string" + }, + "inline": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "name", + "value" + ] + } + } + }, + "additionalProperties": false + }, + "EmbedImage": { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "proxy_url": { + "type": "string" + }, + "height": { + "type": "integer" + }, + "width": { + "type": "integer" + } + }, + "additionalProperties": false + }, + "ChannelModifySchema": { + "type": "object", + "properties": { + "name": { + "maxLength": 100, + "type": "string" + }, + "type": { + "enum": [ + 0, + 1, + 10, + 11, + 12, + 13, + 2, + 3, + 4, + 5, + 6 + ], + "type": "number" + }, + "topic": { + "type": "string" + }, + "icon": { + "type": [ + "null", + "string" + ] + }, + "bitrate": { + "type": "integer" + }, + "user_limit": { + "type": "integer" + }, + "rate_limit_per_user": { + "type": "integer" + }, + "position": { + "type": "integer" + }, + "permission_overwrites": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "$ref": "#/definitions/ChannelPermissionOverwriteType" + }, + "allow": { + "type": "bigint" + }, + "deny": { + "type": "bigint" + } + }, + "additionalProperties": false, + "required": [ + "allow", + "deny", + "id", + "type" + ] + } + }, + "parent_id": { + "type": "string" + }, + "id": { + "type": "string" + }, + "nsfw": { + "type": "boolean" + }, + "rtc_region": { + "type": "string" + }, + "default_auto_archive_duration": { + "type": "integer" + } + }, + "additionalProperties": false + }, + "UserPublic": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "discriminator": { + "type": "string" + }, + "id": { + "type": "string" + }, + "public_flags": { + "type": "integer" + }, + "avatar": { + "type": "string" + }, + "accent_color": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "bio": { + "type": "string" + }, + "bot": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "bio", + "bot", + "discriminator", + "id", + "public_flags", + "username" + ] + }, + "PublicConnectedAccount": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "verifie": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "name", + "type", + "verifie" + ] + } + }, + "$schema": "http://json-schema.org/draft-07/schema#" + }, + "UserProfileResponse": { + "type": "object", + "properties": { + "user": { + "$ref": "#/definitions/UserPublic" + }, + "connected_accounts": { + "$ref": "#/definitions/PublicConnectedAccount" + }, + "premium_guild_since": { + "type": "string", + "format": "date-time" + }, + "premium_since": { + "type": "string", + "format": "date-time" } }, "additionalProperties": false, "required": [ - "name" + "connected_accounts", + "user" ], "definitions": { "ChannelPermissionOverwriteType": { @@ -5739,6 +7334,67 @@ } }, "additionalProperties": false + }, + "UserPublic": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "discriminator": { + "type": "string" + }, + "id": { + "type": "string" + }, + "public_flags": { + "type": "integer" + }, + "avatar": { + "type": "string" + }, + "accent_color": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "bio": { + "type": "string" + }, + "bot": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "bio", + "bot", + "discriminator", + "id", + "public_flags", + "username" + ] + }, + "PublicConnectedAccount": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "verifie": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "name", + "type", + "verifie" + ] } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -5986,6 +7642,67 @@ } }, "additionalProperties": false + }, + "UserPublic": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "discriminator": { + "type": "string" + }, + "id": { + "type": "string" + }, + "public_flags": { + "type": "integer" + }, + "avatar": { + "type": "string" + }, + "accent_color": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "bio": { + "type": "string" + }, + "bot": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "bio", + "bot", + "discriminator", + "id", + "public_flags", + "username" + ] + }, + "PublicConnectedAccount": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "verifie": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "name", + "type", + "verifie" + ] } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -6254,6 +7971,67 @@ } }, "additionalProperties": false + }, + "UserPublic": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "discriminator": { + "type": "string" + }, + "id": { + "type": "string" + }, + "public_flags": { + "type": "integer" + }, + "avatar": { + "type": "string" + }, + "accent_color": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "bio": { + "type": "string" + }, + "bot": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "bio", + "bot", + "discriminator", + "id", + "public_flags", + "username" + ] + }, + "PublicConnectedAccount": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "verifie": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "name", + "type", + "verifie" + ] } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -6498,6 +8276,67 @@ } }, "additionalProperties": false + }, + "UserPublic": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "discriminator": { + "type": "string" + }, + "id": { + "type": "string" + }, + "public_flags": { + "type": "integer" + }, + "avatar": { + "type": "string" + }, + "accent_color": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "bio": { + "type": "string" + }, + "bot": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "bio", + "bot", + "discriminator", + "id", + "public_flags", + "username" + ] + }, + "PublicConnectedAccount": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "verifie": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "name", + "type", + "verifie" + ] } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -6743,6 +8582,67 @@ } }, "additionalProperties": false + }, + "UserPublic": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "discriminator": { + "type": "string" + }, + "id": { + "type": "string" + }, + "public_flags": { + "type": "integer" + }, + "avatar": { + "type": "string" + }, + "accent_color": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "bio": { + "type": "string" + }, + "bot": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "bio", + "bot", + "discriminator", + "id", + "public_flags", + "username" + ] + }, + "PublicConnectedAccount": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "verifie": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "name", + "type", + "verifie" + ] } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -7171,6 +9071,67 @@ } }, "additionalProperties": false + }, + "UserPublic": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "discriminator": { + "type": "string" + }, + "id": { + "type": "string" + }, + "public_flags": { + "type": "integer" + }, + "avatar": { + "type": "string" + }, + "accent_color": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "bio": { + "type": "string" + }, + "bot": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "bio", + "bot", + "discriminator", + "id", + "public_flags", + "username" + ] + }, + "PublicConnectedAccount": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "verifie": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "name", + "type", + "verifie" + ] } }, "$schema": "http://json-schema.org/draft-07/schema#" diff --git a/api/jest/getRouteDescriptions.js b/api/jest/getRouteDescriptions.js new file mode 100644 index 00000000..4f8d2e75 --- /dev/null +++ b/api/jest/getRouteDescriptions.js @@ -0,0 +1,66 @@ +const { traverseDirectory } = require("lambert-server"); +const path = require("path"); +const express = require("express"); +const RouteUtility = require("../dist/util/route"); +const Router = express.Router; + +/** + * Some documentation. + * + * @type {Map} + */ +const routes = new Map(); +let currentPath = ""; +let currentFile = ""; +const methods = ["get", "post", "put", "delete", "patch"]; + +function registerPath(file, method, prefix, path, ...args) { + const urlPath = prefix + path; + const sourceFile = file.replace("/dist/", "/src/").replace(".js", ".ts"); + const opts = args.find((x) => typeof x === "object"); + if (opts) { + routes.set(urlPath + "|" + method, opts); // @ts-ignore + opts.file = sourceFile; + // console.log(method, urlPath, opts); + } else { + console.log(`${sourceFile}\nrouter.${method}("${path}") is missing the "route()" description middleware\n`); + } +} + +function routeOptions(opts) { + return opts; +} + +// @ts-ignore +RouteUtility.route = routeOptions; + +express.Router = (opts) => { + const path = currentPath; + const file = currentFile; + const router = Router(opts); + + for (const method of methods) { + router[method] = registerPath.bind(null, file, method, path); + } + + return router; +}; + +module.exports = function getRouteDescriptions() { + const root = path.join(__dirname, "..", "dist", "routes", "/"); + traverseDirectory({ dirname: root, recursive: true }, (file) => { + currentFile = file; + let path = file.replace(root.slice(0, -1), ""); + path = path.split(".").slice(0, -1).join("."); // trancate .js/.ts file extension of path + path = path.replaceAll("#", ":").replaceAll("\\", "/"); // replace # with : for path parameters and windows paths with slashes + if (path.endsWith("/index")) path = path.slice(0, "/index".length * -1); // delete index from path + currentPath = path; + + try { + require(file); + } catch (error) { + console.error("error loading file " + file, error); + } + }); + return routes; +}; diff --git a/api/jest/getRouteDescriptions.ts b/api/jest/getRouteDescriptions.ts deleted file mode 100644 index 33922899..00000000 --- a/api/jest/getRouteDescriptions.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { traverseDirectory } from "lambert-server"; -import path from "path"; -import express from "express"; -import * as RouteUtility from "../dist/util/route"; -import { RouteOptions } from "../dist/util/route"; -const Router = express.Router; - -const routes = new Map(); -let currentPath = ""; -let currentFile = ""; -const methods = ["get", "post", "put", "delete", "patch"]; - -function registerPath(file, method, prefix, path, ...args) { - const urlPath = prefix + path; - const sourceFile = file.replace("/dist/", "/src/").replace(".js", ".ts"); - const opts: RouteOptions = args.find((x) => typeof x === "object"); - if (opts) { - routes.set(urlPath + "|" + method, opts); // @ts-ignore - opts.file = sourceFile; - // console.log(method, urlPath, opts); - } else { - console.log(`${sourceFile}\nrouter.${method}("${path}") is missing the "route()" description middleware\n`, args); - } -} - -function routeOptions(opts) { - return opts; -} - -// @ts-ignore -RouteUtility.route = routeOptions; - -express.Router = (opts) => { - const path = currentPath; - const file = currentFile; - const router = Router(opts); - - for (const method of methods) { - router[method] = registerPath.bind(null, file, method, path); - } - - return router; -}; - -export default function getRouteDescriptions() { - const root = path.join(__dirname, "..", "dist", "routes", "/"); - traverseDirectory({ dirname: root, recursive: true }, (file) => { - currentFile = file; - let path = file.replace(root.slice(0, -1), ""); - path = path.split(".").slice(0, -1).join("."); // trancate .js/.ts file extension of path - path = path.replaceAll("#", ":").replaceAll("\\", "/"); // replace # with : for path parameters and windows paths with slashes - if (path.endsWith("/index")) path = path.slice(0, "/index".length * -1); // delete index from path - currentPath = path; - - require(file); - }); - return routes; -} diff --git a/api/scripts/generate_body_schema.js b/api/scripts/generate_body_schema.js new file mode 100644 index 00000000..22d0b02e --- /dev/null +++ b/api/scripts/generate_body_schema.js @@ -0,0 +1,70 @@ +// https://mermade.github.io/openapi-gui/# +// https://editor.swagger.io/ +import path from "path"; +import fs from "fs"; +import * as TJS from "typescript-json-schema"; +import "missing-native-js-functions"; +const schemaPath = path.join(__dirname, "..", "assets", "schemas.json"); + +const settings = { + required: true, + ignoreErrors: true, + excludePrivate: true, + defaultNumberType: "integer", + noExtraProps: true, + defaultProps: false +}; +const compilerOptions = { + strictNullChecks: true +}; +const Excluded = [ + "DefaultSchema", + "Schema", + "EntitySchema", + "ServerResponse", + "Http2ServerResponse", + "global.Express.Response", + "Response", + "e.Response", + "request.Response", + "supertest.Response" +]; + +function main() { + const program = TJS.getProgramFromFiles(walk(path.join(__dirname, "..", "src", "routes")), compilerOptions); + const generator = TJS.buildGenerator(program, settings); + if (!generator || !program) return; + + const schemas = generator.getUserSymbols().filter((x) => (x.endsWith("Schema") || x.endsWith("Response")) && !Excluded.includes(x)); + console.log(schemas); + + var definitions = {}; + + for (const name of schemas) { + const part = TJS.generateSchema(program, name, settings, [], generator); + if (!part) continue; + + definitions = { ...definitions, [name]: { ...part } }; + } + + fs.writeFileSync(schemaPath, JSON.stringify(definitions, null, 4)); +} + +main(); + +function walk(dir) { + var results = []; + var list = fs.readdirSync(dir); + list.forEach(function (file) { + file = dir + "/" + file; + var stat = fs.statSync(file); + if (stat && stat.isDirectory()) { + /* Recurse into a subdirectory */ + results = results.concat(walk(file)); + } else { + if (!file.endsWith(".ts")) return; + results.push(file); + } + }); + return results; +} diff --git a/api/scripts/generate_body_schema.ts b/api/scripts/generate_body_schema.ts deleted file mode 100644 index 316e5a69..00000000 --- a/api/scripts/generate_body_schema.ts +++ /dev/null @@ -1,60 +0,0 @@ -// https://mermade.github.io/openapi-gui/# -// https://editor.swagger.io/ -import path from "path"; -import fs from "fs"; -import * as TJS from "typescript-json-schema"; -import "missing-native-js-functions"; -const schemaPath = path.join(__dirname, "..", "assets", "schemas.json"); - -const settings: TJS.PartialArgs = { - required: true, - ignoreErrors: true, - excludePrivate: true, - defaultNumberType: "integer", - noExtraProps: true, - defaultProps: false -}; -const compilerOptions: TJS.CompilerOptions = { - strictNullChecks: true -}; -const ExcludedSchemas = ["DefaultSchema", "Schema", "EntitySchema"]; - -function main() { - const program = TJS.getProgramFromFiles(walk(path.join(__dirname, "..", "src", "routes")), compilerOptions); - const generator = TJS.buildGenerator(program, settings); - if (!generator || !program) return; - - const schemas = generator.getUserSymbols().filter((x) => x.endsWith("Schema") && !ExcludedSchemas.includes(x)); - console.log(schemas); - - var definitions: any = {}; - - for (const name of schemas) { - const part = TJS.generateSchema(program, name, settings, [], generator as TJS.JsonSchemaGenerator); - if (!part) continue; - - definitions = { ...definitions, [name]: { ...part } }; - } - - fs.writeFileSync(schemaPath, JSON.stringify(definitions, null, 4)); -} - -// #/definitions/ -main(); - -function walk(dir: string) { - var results = [] as string[]; - var list = fs.readdirSync(dir); - list.forEach(function (file) { - file = dir + "/" + file; - var stat = fs.statSync(file); - if (stat && stat.isDirectory()) { - /* Recurse into a subdirectory */ - results = results.concat(walk(file)); - } else { - if (!file.endsWith(".ts")) return; - results.push(file); - } - }); - return results; -} diff --git a/api/scripts/generate_openapi_schema.js b/api/scripts/generate_openapi_schema.js new file mode 100644 index 00000000..eb979f14 --- /dev/null +++ b/api/scripts/generate_openapi_schema.js @@ -0,0 +1,127 @@ +// https://mermade.github.io/openapi-gui/# +// https://editor.swagger.io/ +const getRouteDescriptions = require("../jest/getRouteDescriptions"); +const path = require("path"); +const fs = require("fs"); +require("missing-native-js-functions"); + +const openapiPath = path.join(__dirname, "..", "assets", "openapi.json"); +const SchemaPath = path.join(__dirname, "..", "assets", "schemas.json"); +const schemas = JSON.parse(fs.readFileSync(SchemaPath, { encoding: "utf8" })); +const specification = JSON.parse(fs.readFileSync(openapiPath, { encoding: "utf8" })); + +function combineSchemas(schemas) { + var definitions = {}; + + for (const name in schemas) { + definitions = { + ...definitions, + ...schemas[name].definitions, + [name]: { ...schemas[name], definitions: undefined, $schema: undefined } + }; + } + + for (const key in definitions) { + specification.components.schemas[key] = definitions[key]; + delete definitions[key].additionalProperties; + delete definitions[key].$schema; + const definition = definitions[key]; + + if (typeof definition.properties === "object") { + for (const property of Object.values(definition.properties)) { + if (Array.isArray(property.type)) { + if (property.type.includes("null")) { + property.type = property.type.find((x) => x !== "null"); + property.nullable = true; + } + } + } + } + } + + return definitions; +} + +function getTag(key) { + return key.match(/\/([\w-]+)/)[1]; +} + +function apiRoutes() { + const routes = getRouteDescriptions(); + + const tags = Array.from(routes.keys()).map((x) => getTag(x)); + specification.tags = [...specification.tags.map((x) => x.name), ...tags].unique().map((x) => ({ name: x })); + + routes.forEach((route, pathAndMethod) => { + const [p, method] = pathAndMethod.split("|"); + const path = p.replace(/:(\w+)/g, "{$1}"); + + let obj = specification.paths[path]?.[method] || {}; + if (!obj.description) { + const permission = route.permission ? `##### Requires the \`\`${route.permission}\`\` permission\n` : ""; + const event = route.test?.event ? `##### Fires a \`\`${route.test?.event}\`\` event\n` : ""; + obj.description = permission + event; + } + if (route.body) { + obj.requestBody = { + required: true, + content: { + "application/json": { + schema: { $ref: `#/components/schemas/${route.body}` } + } + } + }.merge(obj.requestBody); + } + if (!obj.responses) { + obj.responses = { + default: { + description: "not documented" + } + }; + } + if (route.test?.response) { + const status = route.test.response.status || 200; + obj.responses = { + [status]: { + ...(route.test.response.body + ? { + description: obj.responses[status].description || "", + content: { + "application/json": { + schema: { + $ref: `#/components/schemas/${route.test.response.body}` + } + } + } + } + : {}) + } + }.merge(obj.responses); + delete obj.responses.default; + } + if (p.includes(":")) { + obj.parameters = p.match(/:\w+/g)?.map((x) => ({ + name: x.replace(":", ""), + in: "path", + required: true, + schema: { type: "string" }, + description: x.replace(":", "") + })); + } + obj.tags = [...(obj.tags || []), getTag(p)].unique(); + + specification.paths[path] = { ...specification.paths[path], [method]: obj }; + }); +} + +function main() { + combineSchemas(schemas); + apiRoutes(); + + fs.writeFileSync( + openapiPath, + JSON.stringify(specification, null, 4).replaceAll("#/definitions", "#/components/schemas").replaceAll("bigint", "number") + ); +} + +main(); diff --git a/api/scripts/generate_openapi_schema.ts b/api/scripts/generate_openapi_schema.ts deleted file mode 100644 index c0995b6c..00000000 --- a/api/scripts/generate_openapi_schema.ts +++ /dev/null @@ -1,92 +0,0 @@ -// https://mermade.github.io/openapi-gui/# -// https://editor.swagger.io/ -import path from "path"; -import fs from "fs"; -import * as TJS from "typescript-json-schema"; -import "missing-native-js-functions"; - -const settings: TJS.PartialArgs = { - required: true, - ignoreErrors: true, - excludePrivate: true, - defaultNumberType: "integer", - noExtraProps: true, - defaultProps: false -}; -const compilerOptions: TJS.CompilerOptions = { - strictNullChecks: false -}; -const openapiPath = path.join(__dirname, "..", "assets", "openapi.json"); -var specification = JSON.parse(fs.readFileSync(openapiPath, { encoding: "utf8" })); - -async function utilSchemas() { - const program = TJS.getProgramFromFiles([path.join(__dirname, "..", "..", "util", "src", "index.ts")], compilerOptions); - const generator = TJS.buildGenerator(program, settings); - - const schemas = ["UserPublic", "UserPrivate", "PublicConnectedAccount"]; - - // @ts-ignore - combineSchemas({ schemas, generator, program }); -} - -function combineSchemas(opts: { program: TJS.Program; generator: TJS.JsonSchemaGenerator; schemas: string[] }) { - var definitions: any = {}; - - for (const name of opts.schemas) { - const part = TJS.generateSchema(opts.program, name, settings, [], opts.generator as TJS.JsonSchemaGenerator); - if (!part) continue; - - definitions = { ...definitions, [name]: { ...part, definitions: undefined, $schema: undefined } }; - } - - for (const key in definitions) { - specification.components.schemas[key] = definitions[key]; - delete definitions[key].additionalProperties; - delete definitions[key].$schema; - } - - return definitions; -} - -const ExcludedSchemas = [ - "DefaultSchema", - "Schema", - "EntitySchema", - "ServerResponse", - "Http2ServerResponse", - "global.Express.Response", - "Response", - "e.Response", - "request.Response", - "supertest.Response" -]; - -function apiSchemas() { - const program = TJS.getProgramFromFiles([path.join(__dirname, "..", "src", "schema", "index.ts")], compilerOptions); - const generator = TJS.buildGenerator(program, settings); - - const schemas = generator - .getUserSymbols() - .filter((x) => x.endsWith("Response") && !ExcludedSchemas.includes(x)) - .concat(generator.getUserSymbols().filter((x) => x.endsWith("Schema") && !ExcludedSchemas.includes(x))); - - // @ts-ignore - combineSchemas({ schemas, generator, program }); -} - -function addDefaultResponses() { - Object.values(specification.paths).forEach((path: any) => Object.values(path).forEach((request: any) => {})); -} - -function main() { - addDefaultResponses(); - utilSchemas(); - apiSchemas(); - - fs.writeFileSync( - openapiPath, - JSON.stringify(specification, null, 4).replaceAll("#/definitions", "#/components/schemas").replaceAll("bigint", "number") - ); -} - -main(); diff --git a/api/scripts/generate_test_schema.ts b/api/scripts/generate_test_schema.ts deleted file mode 100644 index eed77738..00000000 --- a/api/scripts/generate_test_schema.ts +++ /dev/null @@ -1,68 +0,0 @@ -// https://mermade.github.io/openapi-gui/# -// https://editor.swagger.io/ -import path from "path"; -import fs from "fs"; -import * as TJS from "typescript-json-schema"; -import "missing-native-js-functions"; -const schemaPath = path.join(__dirname, "..", "assets", "responses.json"); - -const settings: TJS.PartialArgs = { - required: true, - ignoreErrors: true, - excludePrivate: true, - defaultNumberType: "integer", - noExtraProps: true, - defaultProps: false -}; -const compilerOptions: TJS.CompilerOptions = { - strictNullChecks: true -}; -const ExcludedSchemas = [ - "ServerResponse", - "Http2ServerResponse", - "global.Express.Response", - "Response", - "e.Response", - "request.Response", - "supertest.Response" -]; - -function main() { - const program = TJS.getProgramFromFiles(walk(path.join(__dirname, "..", "src", "routes")), compilerOptions); - const generator = TJS.buildGenerator(program, settings); - if (!generator || !program) return; - - const schemas = generator.getUserSymbols().filter((x) => x.endsWith("Response") && !ExcludedSchemas.includes(x)); - console.log(schemas); - - var definitions: any = {}; - - for (const name of schemas) { - const part = TJS.generateSchema(program, name, settings, [], generator as TJS.JsonSchemaGenerator); - if (!part) continue; - - definitions = { ...definitions, [name]: { ...part } }; - } - - fs.writeFileSync(schemaPath, JSON.stringify(definitions, null, 4)); -} - -// #/definitions/ -main(); - -function walk(dir: string) { - var results = [] as string[]; - var list = fs.readdirSync(dir); - list.forEach(function (file) { - file = dir + "/" + file; - var stat = fs.statSync(file); - if (stat && stat.isDirectory()) { - /* Recurse into a subdirectory */ - results = results.concat(walk(file)); - } else { - if (!file.endsWith(".ts")) return; - results.push(file); - } - }); - return results; -} diff --git a/api/src/routes/auth/login.ts b/api/src/routes/auth/login.ts index f672658a..ff04f8aa 100644 --- a/api/src/routes/auth/login.ts +++ b/api/src/routes/auth/login.ts @@ -1,9 +1,7 @@ import { Request, Response, Router } from "express"; import { FieldErrors, route } from "@fosscord/api"; import bcrypt from "bcrypt"; -import jwt from "jsonwebtoken"; -import { Config, User } from "@fosscord/util"; -import { adjustEmail } from "./register"; +import { Config, User, generateToken, adjustEmail } from "@fosscord/util"; const router: Router = Router(); export default router; @@ -68,25 +66,6 @@ router.post("/", route({ body: "LoginSchema" }), async (req: Request, res: Respo res.json({ token, settings: user.settings }); }); -export async function generateToken(id: string) { - const iat = Math.floor(Date.now() / 1000); - const algorithm = "HS256"; - - return new Promise((res, rej) => { - jwt.sign( - { id: id, iat }, - Config.get().security.jwtSecret, - { - algorithm - }, - (err, token) => { - if (err) return rej(err); - return res(token); - } - ); - }); -} - /** * POST /auth/login * @argument { login: "email@gmail.com", password: "cleartextpassword", undelete: false, captcha_key: null, login_source: null, gift_code_sku_id: null, } diff --git a/api/src/routes/auth/register.ts b/api/src/routes/auth/register.ts index 4d3f2860..9c058399 100644 --- a/api/src/routes/auth/register.ts +++ b/api/src/routes/auth/register.ts @@ -1,10 +1,8 @@ import { Request, Response, Router } from "express"; -import { trimSpecial, User, Snowflake, Config, defaultSettings, Member, Invite } from "@fosscord/util"; +import { trimSpecial, User, Snowflake, Config, defaultSettings, generateToken, Invite, adjustEmail } from "@fosscord/util"; import bcrypt from "bcrypt"; -import { EMAIL_REGEX, FieldErrors, route } from "@fosscord/api"; +import { FieldErrors, route, getIpAdress, IPAnalysis, isProxy } from "@fosscord/api"; import "missing-native-js-functions"; -import { generateToken } from "./login"; -import { getIpAdress, IPAnalysis, isProxy } from "@fosscord/api"; import { HTTPError } from "lambert-server"; const router: Router = Router(); @@ -228,24 +226,6 @@ router.post("/", route({ body: "RegisterSchema" }), async (req: Request, res: Re return res.json({ token: await generateToken(user.id) }); }); -export function adjustEmail(email: string): string | undefined { - if (!email) return email; - // body parser already checked if it is a valid email - const parts = email.match(EMAIL_REGEX); - // @ts-ignore - if (!parts || parts.length < 5) return undefined; - const domain = parts[5]; - const user = parts[1]; - - // TODO: check accounts with uncommon email domains - if (domain === "gmail.com" || domain === "googlemail.com") { - // replace .dots and +alternatives -> Gmail Dot Trick https://support.google.com/mail/answer/7436150 and https://generator.email/blog/gmail-generator - return user.replace(/[.]|(\+.*)/g, "") + "@gmail.com"; - } - - return email; -} - export default router; /** diff --git a/api/src/routes/channels/#channel_id/recipients.ts b/api/src/routes/channels/#channel_id/recipients.ts index c7beeee8..83b62049 100644 --- a/api/src/routes/channels/#channel_id/recipients.ts +++ b/api/src/routes/channels/#channel_id/recipients.ts @@ -1,9 +1,10 @@ import { Request, Response, Router } from "express"; import { Channel, ChannelRecipientAddEvent, ChannelType, DiscordApiErrors, DmChannelDTO, emitEvent, PublicUserProjection, Recipient, User } from "@fosscord/util"; +import { route } from "@fosscord/api" const router: Router = Router(); -router.put("/:user_id", async (req: Request, res: Response) => { +router.put("/:user_id", route({}), async (req: Request, res: Response) => { const { channel_id, user_id } = req.params; const channel = await Channel.findOneOrFail({ where: { id: channel_id }, relations: ["recipients"] }); @@ -39,7 +40,7 @@ router.put("/:user_id", async (req: Request, res: Response) => { } }); -router.delete("/:user_id", async (req: Request, res: Response) => { +router.delete("/:user_id", route({}), async (req: Request, res: Response) => { const { channel_id, user_id } = req.params; const channel = await Channel.findOneOrFail({ where: { id: channel_id }, relations: ["recipients"] }); if (!(channel.type === ChannelType.GROUP_DM && (channel.owner_id === req.user_id || user_id === req.user_id))) diff --git a/api/src/routes/guilds/#guild_id/members/#member_id/roles/#role_id/index.ts b/api/src/routes/guilds/#guild_id/members/#member_id/roles/#role_id/index.ts index ae10be82..8f5ca7ba 100644 --- a/api/src/routes/guilds/#guild_id/members/#member_id/roles/#role_id/index.ts +++ b/api/src/routes/guilds/#guild_id/members/#member_id/roles/#role_id/index.ts @@ -4,14 +4,14 @@ import { Request, Response, Router } from "express"; const router = Router(); -router.delete("/:member_id/roles/:role_id", route({ permission: "MANAGE_ROLES" }), async (req: Request, res: Response) => { +router.delete("/", route({ permission: "MANAGE_ROLES" }), async (req: Request, res: Response) => { const { guild_id, role_id, member_id } = req.params; await Member.removeRole(member_id, guild_id, role_id); res.sendStatus(204); }); -router.put("/:member_id/roles/:role_id", route({ permission: "MANAGE_ROLES" }), async (req: Request, res: Response) => { +router.put("/", route({ permission: "MANAGE_ROLES" }), async (req: Request, res: Response) => { const { guild_id, role_id, member_id } = req.params; await Member.addRole(member_id, guild_id, role_id); diff --git a/api/src/routes/sticker-packs/#id/index.ts b/api/src/routes/sticker-packs/#id/index.ts index 2344a48f..7f723e97 100644 --- a/api/src/routes/sticker-packs/#id/index.ts +++ b/api/src/routes/sticker-packs/#id/index.ts @@ -1,8 +1,9 @@ import { Request, Response, Router } from "express"; +import { route } from "@fosscord/api"; const router: Router = Router(); -router.get("/", async (req: Request, res: Response) => { +router.get("/", route({}), async (req: Request, res: Response) => { //TODO res.json({ id: "", @@ -15,4 +16,4 @@ router.get("/", async (req: Request, res: Response) => { }).status(200); }); -export default router; \ No newline at end of file +export default router; diff --git a/api/src/routes/sticker-packs/index.ts b/api/src/routes/sticker-packs/index.ts index 6c4e46d8..d671c161 100644 --- a/api/src/routes/sticker-packs/index.ts +++ b/api/src/routes/sticker-packs/index.ts @@ -1,10 +1,11 @@ import { Request, Response, Router } from "express"; +import { route } from "@fosscord/api"; const router: Router = Router(); -router.get("/", async (req: Request, res: Response) => { +router.get("/", route({}), async (req: Request, res: Response) => { //TODO res.json({ sticker_packs: [] }).status(200); }); -export default router; \ No newline at end of file +export default router; diff --git a/api/src/util/String.ts b/api/src/util/String.ts index 2fe32d2c..67d87e37 100644 --- a/api/src/util/String.ts +++ b/api/src/util/String.ts @@ -1,8 +1,6 @@ import { Request } from "express"; import { ntob } from "./Base64"; import { FieldErrors } from "./FieldError"; -export const EMAIL_REGEX = - /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; export function checkLength(str: string, min: number, max: number, key: string, req: Request) { if (str.length < min || str.length > max) { diff --git a/api/tests/routes.test.ts b/api/tests/routes.test.ts index 0473c579..a9c75df1 100644 --- a/api/tests/routes.test.ts +++ b/api/tests/routes.test.ts @@ -9,7 +9,7 @@ import addFormats from "ajv-formats"; import fetch from "node-fetch"; import { User } from "@fosscord/util"; -const SchemaPath = join(__dirname, "..", "assets", "responses.json"); +const SchemaPath = join(__dirname, "..", "assets", "schemas.json"); const schemas = JSON.parse(fs.readFileSync(SchemaPath, { encoding: "utf8" })); export const ajv = new Ajv({ allErrors: true, @@ -64,7 +64,7 @@ describe("Automatic unit tests with route description middleware", () => { routes.forEach((route, pathAndMethod) => { const [path, method] = pathAndMethod.split("|"); - test(path, async (done) => { + test(`${method.toUpperCase()} ${path}`, async (done) => { if (!route.test) { console.log(`${(route as any).file}\nrouter.${method} is missing the test property`); return done(); diff --git a/util/src/util/Email.ts b/util/src/util/Email.ts new file mode 100644 index 00000000..c304f584 --- /dev/null +++ b/util/src/util/Email.ts @@ -0,0 +1,20 @@ +export const EMAIL_REGEX = + /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; + +export function adjustEmail(email: string): string | undefined { + if (!email) return email; + // body parser already checked if it is a valid email + const parts = email.match(EMAIL_REGEX); + // @ts-ignore + if (!parts || parts.length < 5) return undefined; + const domain = parts[5]; + const user = parts[1]; + + // TODO: check accounts with uncommon email domains + if (domain === "gmail.com" || domain === "googlemail.com") { + // replace .dots and +alternatives -> Gmail Dot Trick https://support.google.com/mail/answer/7436150 and https://generator.email/blog/gmail-generator + return user.replace(/[.]|(\+.*)/g, "") + "@gmail.com"; + } + + return email; +} diff --git a/util/src/util/Token.ts b/util/src/util/Token.ts new file mode 100644 index 00000000..111d59a2 --- /dev/null +++ b/util/src/util/Token.ts @@ -0,0 +1,43 @@ +import jwt, { VerifyOptions } from "jsonwebtoken"; +import { Config } from "./Config"; +import { User } from "../entities"; + +export const JWTOptions: VerifyOptions = { algorithms: ["HS256"] }; + +export function checkToken(token: string, jwtSecret: string): Promise { + return new Promise((res, rej) => { + token = token.replace("Bot ", ""); // TODO: proper bot support + jwt.verify(token, jwtSecret, JWTOptions, async (err, decoded: any) => { + if (err || !decoded) return rej("Invalid Token"); + + const user = await User.findOne({ id: decoded.id }, { select: ["data", "bot", "disabled", "deleted"] }); + if (!user) return rej("Invalid Token"); + // we need to round it to seconds as it saved as seconds in jwt iat and valid_tokens_since is stored in milliseconds + if (decoded.iat * 1000 < new Date(user.data.valid_tokens_since).setSeconds(0, 0)) + return rej("Invalid Token"); + if (user.disabled) return rej("User disabled"); + if (user.deleted) return rej("User not found"); + + return res({ decoded, user }); + }); + }); +} + +export async function generateToken(id: string) { + const iat = Math.floor(Date.now() / 1000); + const algorithm = "HS256"; + + return new Promise((res, rej) => { + jwt.sign( + { id: id, iat }, + Config.get().security.jwtSecret, + { + algorithm, + }, + (err, token) => { + if (err) return rej(err); + return res(token); + } + ); + }); +} diff --git a/util/src/util/checkToken.ts b/util/src/util/checkToken.ts deleted file mode 100644 index 8415e8c0..00000000 --- a/util/src/util/checkToken.ts +++ /dev/null @@ -1,23 +0,0 @@ -import jwt, { VerifyOptions } from "jsonwebtoken"; -import { User } from "../entities"; - -export const JWTOptions: VerifyOptions = { algorithms: ["HS256"] }; - -export function checkToken(token: string, jwtSecret: string): Promise { - return new Promise((res, rej) => { - token = token.replace("Bot ", ""); // TODO: proper bot support - jwt.verify(token, jwtSecret, JWTOptions, async (err, decoded: any) => { - if (err || !decoded) return rej("Invalid Token"); - - const user = await User.findOne({ id: decoded.id }, { select: ["data", "bot", "disabled", "deleted"] }); - if (!user) return rej("Invalid Token"); - // we need to round it to seconds as it saved as seconds in jwt iat and valid_tokens_since is stored in milliseconds - if (decoded.iat * 1000 < new Date(user.data.valid_tokens_since).setSeconds(0, 0)) - return rej("Invalid Token"); - if (user.disabled) return rej("User disabled"); - if (user.deleted) return rej("User not found"); - - return res({ decoded, user }); - }); - }); -} diff --git a/util/src/util/index.ts b/util/src/util/index.ts index 3160380f..d73bf4ca 100644 --- a/util/src/util/index.ts +++ b/util/src/util/index.ts @@ -1,11 +1,12 @@ export * from "./ApiError"; export * from "./BitField"; -export * from "./checkToken"; +export * from "./Token"; export * from "./cdn"; export * from "./Config"; export * from "./Constants"; export * from "./Database"; export * from "./Event"; +export * from "./Email"; export * from "./Intents"; export * from "./MessageFlags"; export * from "./Permissions"; -- cgit 1.5.1 From b3f8df560af34ba6904821eea684be8ccef14c9d Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Tue, 21 Sep 2021 23:13:31 +0200 Subject: :sparkles: unit tests expect event --- api/assets/openapi.json | 12591 ++++++++++++++++++++++++--------------------- api/tests/routes.test.ts | 31 +- util/src/util/Event.ts | 2 +- 3 files changed, 6628 insertions(+), 5996 deletions(-) (limited to 'util/src') diff --git a/api/assets/openapi.json b/api/assets/openapi.json index caf572b9..a92fe706 100644 --- a/api/assets/openapi.json +++ b/api/assets/openapi.json @@ -1,5995 +1,6598 @@ { - "openapi": "3.0.0", - "servers": [ - { - "url": "https://api.fosscord.com/v{version}", - "description": "Official fosscord instance", - "variables": { - "version": { - "default": "9", - "enum": ["8", "9"] - } - } - } - ], - "info": { - "description": "Fosscord is a free open source selfhostable discord compatible chat, voice and video platform", - "version": "1.0.0", - "title": "Fosscord HTTP API Routes", - "termsOfService": "", - "contact": { - "name": "Fosscord" - }, - "license": { - "name": "AGPLV3", - "url": "https://www.gnu.org/licenses/agpl-3.0.en.html" - } - }, - "tags": [ - { - "name": "voice" - }, - { - "name": "users" - }, - { - "name": "store" - }, - { - "name": "sticker-packs" - }, - { - "name": "science" - }, - { - "name": "ping" - }, - { - "name": "outbound-promotions" - }, - { - "name": "invites" - }, - { - "name": "guilds" - }, - { - "name": "gateway" - }, - { - "name": "experiments" - }, - { - "name": "discoverable-guilds" - }, - { - "name": "channels" - }, - { - "name": "auth" - }, - { - "name": "applications" - } - ], - "paths": { - "/users/{id}": { - "get": { - "summary": "", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "user id" - } - ], - "operationId": "", - "responses": { - "200": { - "description": "User found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UserPublic" - } - } - } - }, - "404": { - "description": "User not found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/Error" - } - } - } - } - }, - "security": [ - { - "Token": [] - } - ] - } - }, - "/users/@me": { - "get": { - "summary": "", - "parameters": [], - "operationId": "", - "responses": { - "200": { - "description": "Authenticated user", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UserPublic" - } - } - } - } - }, - "security": [ - { - "Token": [] - } - ] - } - }, - "/voice/regions/": { - "get": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "tags": ["voice"] - } - }, - "/users/@me/settings/": { - "patch": { - "description": "", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UserSettingsSchema" - } - } - } - }, - "responses": { - "default": { - "description": "not documented" - } - }, - "tags": ["users"] - } - }, - "/users/@me/relationships/": { - "get": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "tags": ["users", "relationships"] - }, - "post": { - "description": "", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RelationshipPostSchema" - } - } - } - }, - "responses": { - "default": { - "description": "not documented" - } - }, - "tags": ["users"] - } - }, - "/users/@me/relationships/{id}": { - "put": { - "description": "", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RelationshipPutSchema" - } - } - } - }, - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "id" - } - ], - "tags": ["users"] - }, - "delete": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "id" - } - ], - "tags": ["users"] - } - }, - "/users/@me/library/": { - "get": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "tags": ["users"] - } - }, - "/users/@me/": { - "get": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "tags": ["users"] - }, - "patch": { - "description": "", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UserModifySchema" - } - } - } - }, - "responses": { - "default": { - "description": "not documented" - } - }, - "tags": ["users"] - } - }, - "/users/@me/guilds/": { - "get": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "tags": ["users"] - } - }, - "/users/@me/guilds/{id}": { - "delete": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "id" - } - ], - "tags": ["users"] - } - }, - "/users/@me/disable/": { - "post": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "tags": ["users"] - } - }, - "/users/@me/devices/": { - "post": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "tags": ["users"] - } - }, - "/users/@me/delete/": { - "post": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "tags": ["users"] - } - }, - "/users/@me/connections/": { - "get": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "tags": ["users"] - } - }, - "/users/@me/channels/": { - "get": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "tags": ["users"] - }, - "post": { - "description": "", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DmChannelCreateSchema" - } - } - } - }, - "responses": { - "default": { - "description": "not documented" - } - }, - "tags": ["users"] - } - }, - "/users/@me/billing/subscriptions/": { - "get": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "tags": ["users"] - } - }, - "/users/@me/billing/country-code/": { - "get": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "tags": ["users"] - } - }, - "/users/@me/applications/{app_id}/entitlements/": { - "get": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "app_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "app_id" - } - ], - "tags": ["users"] - } - }, - "/users/@me/affinities/users/": { - "get": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "tags": ["users"] - } - }, - "/users/@me/affinities/guilds/": { - "get": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "tags": ["users"] - } - }, - "/users/{id}/profile/": { - "get": { - "description": "", - "responses": { - "200": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UserProfileResponse" - } - } - }, - "description": "" - } - }, - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "id" - } - ], - "tags": ["users"] - } - }, - "/users/{id}/": { - "get": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "id" - } - ], - "tags": ["users"] - } - }, - "/store/skus/skus/{id}": { - "get": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "id" - } - ], - "tags": ["store"] - } - }, - "/store/applications/applications/{id}": { - "get": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "id" - } - ], - "tags": ["store"] - } - }, - "/sticker-packs/": { - "get": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "tags": ["sticker", "sticker-packs"] - } - }, - "/sticker-packs/{id}/": { - "get": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "id" - } - ], - "tags": ["sticker", "sticker-packs"] - } - }, - "/science/": { - "post": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "tags": ["science"] - } - }, - "/ping/": { - "get": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "tags": ["ping"] - } - }, - "/outbound-promotions/": { - "get": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "tags": ["outbound", "outbound-promotions"] - } - }, - "/invites/{code}": { - "get": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "code", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "code" - } - ], - "tags": ["invites"] - }, - "post": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "code", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "code" - } - ], - "tags": ["invites"] - }, - "delete": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "code", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "code" - } - ], - "tags": ["invites"] - } - }, - "/guilds/templates/{code}": { - "get": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "code", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "code" - } - ], - "tags": ["guilds"] - }, - "post": { - "description": "", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GuildTemplateCreateSchema" - } - } - } - }, - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "code", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "code" - } - ], - "tags": ["guilds"] - } - }, - "/guilds/": { - "post": { - "description": "", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GuildCreateSchema" - } - } - } - }, - "responses": { - "default": { - "description": "not documented" - } - }, - "tags": ["guilds"] - } - }, - "/guilds/{guild_id}/widget.png/": { - "get": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - } - ], - "tags": ["guilds"] - } - }, - "/guilds/{guild_id}/widget.json/": { - "get": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - } - ], - "tags": ["guilds"] - } - }, - "/guilds/{guild_id}/widget/": { - "get": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - } - ], - "tags": ["guilds"] - }, - "patch": { - "description": "##### Requires the ``MANAGE_GUILD`` permission\n", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WidgetModifySchema" - } - } - } - }, - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - } - ], - "tags": ["guilds"] - } - }, - "/guilds/{guild_id}/welcome_screen/": { - "get": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - } - ], - "tags": ["guilds"] - }, - "patch": { - "description": "##### Requires the ``MANAGE_GUILD`` permission\n", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GuildUpdateWelcomeScreenSchema" - } - } - } - }, - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - } - ], - "tags": ["guilds"] - } - }, - "/guilds/{guild_id}/voice-states/{user_id}/": { - "patch": { - "description": "", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/VoiceStateUpdateSchema" - } - } - } - }, - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - }, - { - "name": "user_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "user_id" - } - ], - "tags": ["guilds"] - } - }, - "/guilds/{guild_id}/vanity-url/": { - "get": { - "description": "##### Requires the ``MANAGE_GUILD`` permission\n", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - } - ], - "tags": ["guilds"] - }, - "patch": { - "description": "##### Requires the ``MANAGE_GUILD`` permission\n", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/VanityUrlSchema" - } - } - } - }, - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - } - ], - "tags": ["guilds"] - } - }, - "/guilds/{guild_id}/templates/": { - "get": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - } - ], - "tags": ["guilds"] - }, - "post": { - "description": "##### Requires the ``MANAGE_GUILD`` permission\n", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TemplateCreateSchema" - } - } - } - }, - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - } - ], - "tags": ["guilds"] - } - }, - "/guilds/{guild_id}/templates/{code}": { - "delete": { - "description": "##### Requires the ``MANAGE_GUILD`` permission\n", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - }, - { - "name": "code", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "code" - } - ], - "tags": ["guilds"] - }, - "put": { - "description": "##### Requires the ``MANAGE_GUILD`` permission\n", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - }, - { - "name": "code", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "code" - } - ], - "tags": ["guilds"] - }, - "patch": { - "description": "##### Requires the ``MANAGE_GUILD`` permission\n", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TemplateModifySchema" - } - } - } - }, - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - }, - { - "name": "code", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "code" - } - ], - "tags": ["guilds"] - } - }, - "/guilds/{guild_id}/roles/": { - "get": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - } - ], - "tags": ["guilds"] - }, - "post": { - "description": "##### Requires the ``MANAGE_ROLES`` permission\n", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RoleModifySchema" - } - } - } - }, - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - } - ], - "tags": ["guilds"] - }, - "patch": { - "description": "", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RolePositionUpdateSchema" - } - } - } - }, - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - } - ], - "tags": ["guilds"] - } - }, - "/guilds/{guild_id}/roles/{role_id}": { - "delete": { - "description": "##### Requires the ``MANAGE_ROLES`` permission\n", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - }, - { - "name": "role_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "role_id" - } - ], - "tags": ["guilds"] - }, - "patch": { - "description": "##### Requires the ``MANAGE_ROLES`` permission\n", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RoleModifySchema" - } - } - } - }, - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - }, - { - "name": "role_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "role_id" - } - ], - "tags": ["guilds"] - } - }, - "/guilds/{guild_id}/regions/": { - "get": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - } - ], - "tags": ["guilds"] - } - }, - "/guilds/{guild_id}/members/": { - "get": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - } - ], - "tags": ["guilds"] - } - }, - "/guilds/{guild_id}/members/{member_id}/nick/": { - "patch": { - "description": "", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MemberNickChangeSchema" - } - } - } - }, - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - }, - { - "name": "member_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "member_id" - } - ], - "tags": ["guilds"] - } - }, - "/guilds/{guild_id}/members/{member_id}/": { - "get": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - }, - { - "name": "member_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "member_id" - } - ], - "tags": ["guilds"] - }, - "patch": { - "description": "", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MemberChangeSchema" - } - } - } - }, - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - }, - { - "name": "member_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "member_id" - } - ], - "tags": ["guilds"] - }, - "put": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - }, - { - "name": "member_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "member_id" - } - ], - "tags": ["guilds"] - }, - "delete": { - "description": "##### Requires the ``KICK_MEMBERS`` permission\n", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - }, - { - "name": "member_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "member_id" - } - ], - "tags": ["guilds"] - } - }, - "/guilds/{guild_id}/invites/": { - "get": { - "description": "##### Requires the ``MANAGE_GUILD`` permission\n", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - } - ], - "tags": ["guilds"] - } - }, - "/guilds/{guild_id}/": { - "get": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - } - ], - "tags": ["guilds"] - }, - "patch": { - "description": "##### Requires the ``MANAGE_GUILD`` permission\n", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/GuildUpdateSchema" - } - } - } - }, - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - } - ], - "tags": ["guilds"] - } - }, - "/guilds/{guild_id}/delete/": { - "post": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - } - ], - "tags": ["guilds"] - } - }, - "/guilds/{guild_id}/channels/": { - "get": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - } - ], - "tags": ["guilds"] - }, - "post": { - "description": "##### Requires the ``MANAGE_CHANNELS`` permission\n", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ChannelModifySchema" - } - } - } - }, - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - } - ], - "tags": ["guilds"] - }, - "patch": { - "description": "##### Requires the ``MANAGE_CHANNELS`` permission\n", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ChannelReorderSchema" - } - } - } - }, - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - } - ], - "tags": ["guilds"] - } - }, - "/guilds/{guild_id}/bans/": { - "get": { - "description": "##### Requires the ``BAN_MEMBERS`` permission\n", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - } - ], - "tags": ["guilds"] - } - }, - "/guilds/{guild_id}/bans/{user}": { - "get": { - "description": "##### Requires the ``BAN_MEMBERS`` permission\n", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - }, - { - "name": "user", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "user" - } - ], - "tags": ["guilds"] - } - }, - "/guilds/{guild_id}/bans/{user_id}": { - "put": { - "description": "##### Requires the ``BAN_MEMBERS`` permission\n", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BanCreateSchema" - } - } - } - }, - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - }, - { - "name": "user_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "user_id" - } - ], - "tags": ["guilds"] - }, - "delete": { - "description": "##### Requires the ``BAN_MEMBERS`` permission\n", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - }, - { - "name": "user_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "user_id" - } - ], - "tags": ["guilds"] - } - }, - "/gateway/": { - "get": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "tags": ["gateway"] - } - }, - "/gateway/bot": { - "get": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "tags": ["gateway"] - } - }, - "/experiments/": { - "get": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "tags": ["experiments"] - } - }, - "/discoverable-guilds/": { - "get": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "tags": ["discoverable", "discoverable-guilds"] - } - }, - "/channels/{channel_id}/webhooks/": { - "post": { - "description": "##### Requires the ``MANAGE_WEBHOOKS`` permission\n", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/WebhookCreateSchema" - } - } - } - }, - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "channel_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "channel_id" - } - ], - "tags": ["channels"] - } - }, - "/channels/{channel_id}/typing/": { - "post": { - "description": "##### Requires the ``SEND_MESSAGES`` permission\n", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "channel_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "channel_id" - } - ], - "tags": ["channels"] - } - }, - "/channels/{channel_id}/recipients/{user_id}": { - "put": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "channel_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "channel_id" - }, - { - "name": "user_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "user_id" - } - ], - "tags": ["channels"] - }, - "delete": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "channel_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "channel_id" - }, - { - "name": "user_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "user_id" - } - ], - "tags": ["channels"] - } - }, - "/channels/{channel_id}/pins/{message_id}": { - "put": { - "description": "##### Requires the ``VIEW_CHANNEL`` permission\n", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "channel_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "channel_id" - }, - { - "name": "message_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "message_id" - } - ], - "tags": ["channels"] - }, - "delete": { - "description": "##### Requires the ``VIEW_CHANNEL`` permission\n", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "channel_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "channel_id" - }, - { - "name": "message_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "message_id" - } - ], - "tags": ["channels"] - } - }, - "/channels/{channel_id}/pins/": { - "get": { - "description": "##### Requires the ``READ_MESSAGE_HISTORY`` permission\n", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "channel_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "channel_id" - } - ], - "tags": ["channels"] - } - }, - "/channels/{channel_id}/permissions/{overwrite_id}": { - "put": { - "description": "##### Requires the ``MANAGE_ROLES`` permission\n", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ChannelPermissionOverwriteSchema" - } - } - } - }, - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "channel_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "channel_id" - }, - { - "name": "overwrite_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "overwrite_id" - } - ], - "tags": ["channels"] - }, - "delete": { - "description": "##### Requires the ``MANAGE_ROLES`` permission\n", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "channel_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "channel_id" - }, - { - "name": "overwrite_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "overwrite_id" - } - ], - "tags": ["channels"] - } - }, - "/channels/{channel_id}/messages/bulk-delete/": { - "post": { - "description": "", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BulkDeleteSchema" - } - } - } - }, - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "channel_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "channel_id" - } - ], - "tags": ["channels"] - } - }, - "/channels/{channel_id}/messages/{message_id}/reactions/": { - "delete": { - "description": "##### Requires the ``MANAGE_MESSAGES`` permission\n", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "channel_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "channel_id" - }, - { - "name": "message_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "message_id" - } - ], - "tags": ["channels"] - } - }, - "/channels/{channel_id}/messages/{message_id}/reactions/{emoji}": { - "delete": { - "description": "##### Requires the ``MANAGE_MESSAGES`` permission\n", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "channel_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "channel_id" - }, - { - "name": "message_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "message_id" - }, - { - "name": "emoji", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "emoji" - } - ], - "tags": ["channels"] - }, - "get": { - "description": "##### Requires the ``VIEW_CHANNEL`` permission\n", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "channel_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "channel_id" - }, - { - "name": "message_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "message_id" - }, - { - "name": "emoji", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "emoji" - } - ], - "tags": ["channels"] - } - }, - "/channels/{channel_id}/messages/{message_id}/reactions/{emoji}/{user_id}": { - "put": { - "description": "##### Requires the ``READ_MESSAGE_HISTORY`` permission\n", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "channel_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "channel_id" - }, - { - "name": "message_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "message_id" - }, - { - "name": "emoji", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "emoji" - }, - { - "name": "user_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "user_id" - } - ], - "tags": ["channels"] - }, - "delete": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "channel_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "channel_id" - }, - { - "name": "message_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "message_id" - }, - { - "name": "emoji", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "emoji" - }, - { - "name": "user_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "user_id" - } - ], - "tags": ["channels"] - } - }, - "/channels/{channel_id}/messages/{message_id}/": { - "patch": { - "description": "##### Requires the ``SEND_MESSAGES`` permission\n", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MessageCreateSchema" - } - } - } - }, - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "channel_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "channel_id" - }, - { - "name": "message_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "message_id" - } - ], - "tags": ["channels"] - }, - "delete": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "channel_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "channel_id" - }, - { - "name": "message_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "message_id" - } - ], - "tags": ["channels"] - } - }, - "/channels/{channel_id}/messages/{message_id}/ack/": { - "post": { - "description": "", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/MessageAcknowledgeSchema" - } - } - } - }, - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "channel_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "channel_id" - }, - { - "name": "message_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "message_id" - } - ], - "tags": ["channels"] - } - }, - "/channels/{channel_id}/invites/": { - "post": { - "description": "##### Requires the ``CREATE_INSTANT_INVITE`` permission\n", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/InviteCreateSchema" - } - } - } - }, - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "channel_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "channel_id" - } - ], - "tags": ["channels"] - }, - "get": { - "description": "##### Requires the ``MANAGE_CHANNELS`` permission\n", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "channel_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "channel_id" - } - ], - "tags": ["channels"] - } - }, - "/channels/{channel_id}/": { - "get": { - "description": "##### Requires the ``VIEW_CHANNEL`` permission\n", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "channel_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "channel_id" - } - ], - "tags": ["channels"] - }, - "delete": { - "description": "##### Requires the ``MANAGE_CHANNELS`` permission\n", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "channel_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "channel_id" - } - ], - "tags": ["channels"] - }, - "patch": { - "description": "##### Requires the ``MANAGE_CHANNELS`` permission\n", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ChannelModifySchema" - } - } - } - }, - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "channel_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "channel_id" - } - ], - "tags": ["channels"] - } - }, - "/auth/register/": { - "post": { - "description": "", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RegisterSchema" - } - } - } - }, - "responses": { - "default": { - "description": "not documented" - } - }, - "tags": ["auth"] - } - }, - "/applications/detectable/": { - "get": { - "description": "", - "responses": { - "default": { - "description": "not documented" - } - }, - "tags": ["applications"] - } - }, - "/guilds/{guild_id}/members/{member_id}/roles/{role_id}/": { - "delete": { - "description": "##### Requires the ``MANAGE_ROLES`` permission\n", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - }, - { - "name": "member_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "member_id" - }, - { - "name": "role_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "role_id" - } - ], - "tags": ["guilds"] - }, - "put": { - "description": "##### Requires the ``MANAGE_ROLES`` permission\n", - "responses": { - "default": { - "description": "not documented" - } - }, - "parameters": [ - { - "name": "guild_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "guild_id" - }, - { - "name": "member_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "member_id" - }, - { - "name": "role_id", - "in": "path", - "required": true, - "schema": { - "type": "string" - }, - "description": "role_id" - } - ], - "tags": ["guilds"] - } - }, - "/auth/login/": { - "post": { - "description": "", - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LoginSchema" - } - } - } - }, - "responses": { - "default": { - "description": "not documented" - } - }, - "tags": ["auth"] - } - } - }, - "externalDocs": { - "url": "http://docs.fosscord.com/" - }, - "components": { - "schemas": { - "Error": { - "type": "object", - "properties": { - "code": { - "type": "integer" - }, - "message": { - "type": "string" - } - }, - "required": ["code", "message"] - }, - "RateLimit": { - "type": "object", - "properties": { - "retry_after": { - "type": "integer" - }, - "message": { - "type": "string" - }, - "global": { - "type": "boolean" - } - }, - "required": ["code", "message", "globa"] - }, - "User": { - "type": "object", - "properties": { - "username": { - "type": "string" - }, - "discriminator": { - "type": "string" - }, - "avatar": { - "type": "string" - }, - "accent_color": { - "type": "integer" - }, - "banner": { - "type": "string" - }, - "phone": { - "type": "string" - }, - "desktop": { - "type": "boolean" - }, - "mobile": { - "type": "boolean" - }, - "premium": { - "type": "boolean" - }, - "premium_type": { - "type": "integer" - }, - "bot": { - "type": "boolean" - }, - "bio": { - "type": "string" - }, - "system": { - "type": "boolean" - }, - "nsfw_allowed": { - "type": "boolean" - }, - "mfa_enabled": { - "type": "boolean" - }, - "created_at": { - "type": "string", - "format": "date-time" - }, - "verified": { - "type": "boolean" - }, - "disabled": { - "type": "boolean" - }, - "deleted": { - "type": "boolean" - }, - "email": { - "type": "string" - }, - "flags": { - "type": "string" - }, - "public_flags": { - "type": "string" - }, - "relationships": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Relationship" - } - }, - "connected_accounts": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ConnectedAccount" - } - }, - "data": { - "type": "object", - "properties": { - "valid_tokens_since": { - "type": "string", - "format": "date-time" - }, - "hash": { - "type": "string" - } - }, - "additionalProperties": false, - "required": ["valid_tokens_since"] - }, - "fingerprints": { - "type": "array", - "items": { - "type": "string" - } - }, - "settings": { - "$ref": "#/components/schemas/UserSettings" - }, - "id": { - "type": "string" - } - }, - "required": [ - "bio", - "bot", - "connected_accounts", - "created_at", - "data", - "deleted", - "desktop", - "disabled", - "discriminator", - "fingerprints", - "flags", - "id", - "mfa_enabled", - "mobile", - "nsfw_allowed", - "premium", - "premium_type", - "public_flags", - "relationships", - "settings", - "system", - "username", - "verified" - ] - }, - "Relationship": { - "type": "object", - "properties": { - "user_id": { - "type": "string" - }, - "user": { - "$ref": "#/components/schemas/User" - }, - "nickname": { - "type": "string" - }, - "type": { - "$ref": "#/components/schemas/RelationshipType" - }, - "id": { - "type": "string" - } - }, - "required": ["id", "type", "user", "user_id"] - }, - "RelationshipType": { - "enum": [1, 2, 3, 4], - "type": "number" - }, - "ConnectedAccount": { - "type": "object", - "properties": { - "user_id": { - "type": "string" - }, - "user": { - "$ref": "#/components/schemas/User" - }, - "access_token": { - "type": "string" - }, - "friend_sync": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "revoked": { - "type": "boolean" - }, - "show_activity": { - "type": "boolean" - }, - "type": { - "type": "string" - }, - "verifie": { - "type": "boolean" - }, - "visibility": { - "type": "integer" - }, - "id": { - "type": "string" - } - }, - "required": [ - "access_token", - "friend_sync", - "id", - "name", - "revoked", - "show_activity", - "type", - "user", - "user_id", - "verifie", - "visibility" - ] - }, - "UserSettings": { - "type": "object", - "properties": { - "afk_timeout": { - "type": "integer" - }, - "allow_accessibility_detection": { - "type": "boolean" - }, - "animate_emoji": { - "type": "boolean" - }, - "animate_stickers": { - "type": "integer" - }, - "contact_sync_enabled": { - "type": "boolean" - }, - "convert_emoticons": { - "type": "boolean" - }, - "custom_status": { - "type": "object", - "properties": { - "emoji_id": { - "type": "string" - }, - "emoji_name": { - "type": "string" - }, - "expires_at": { - "type": "integer" - }, - "text": { - "type": "string" - } - }, - "additionalProperties": false - }, - "default_guilds_restricted": { - "type": "boolean" - }, - "detect_platform_accounts": { - "type": "boolean" - }, - "developer_mode": { - "type": "boolean" - }, - "disable_games_tab": { - "type": "boolean" - }, - "enable_tts_command": { - "type": "boolean" - }, - "explicit_content_filter": { - "type": "integer" - }, - "friend_source_flags": { - "type": "object", - "properties": { - "all": { - "type": "boolean" - } - }, - "additionalProperties": false, - "required": ["all"] - }, - "gateway_connected": { - "type": "boolean" - }, - "gif_auto_play": { - "type": "boolean" - }, - "guild_folders": { - "type": "array", - "items": { - "type": "object", - "properties": { - "color": { - "type": "integer" - }, - "guild_ids": { - "type": "array", - "items": { - "type": "string" - } - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - } - }, - "additionalProperties": false, - "required": ["color", "guild_ids", "id", "name"] - } - }, - "guild_positions": { - "type": "array", - "items": { - "type": "string" - } - }, - "inline_attachment_media": { - "type": "boolean" - }, - "inline_embed_media": { - "type": "boolean" - }, - "locale": { - "type": "string" - }, - "message_display_compact": { - "type": "boolean" - }, - "native_phone_integration_enabled": { - "type": "boolean" - }, - "render_embeds": { - "type": "boolean" - }, - "render_reactions": { - "type": "boolean" - }, - "restricted_guilds": { - "type": "array", - "items": { - "type": "string" - } - }, - "show_current_game": { - "type": "boolean" - }, - "status": { - "enum": ["dnd", "idle", "offline", "online"], - "type": "string" - }, - "stream_notifications_enabled": { - "type": "boolean" - }, - "theme": { - "enum": ["dark", "white"], - "type": "string" - }, - "timezone_offset": { - "type": "integer" - } - }, - "required": [ - "afk_timeout", - "allow_accessibility_detection", - "animate_emoji", - "animate_stickers", - "contact_sync_enabled", - "convert_emoticons", - "custom_status", - "default_guilds_restricted", - "detect_platform_accounts", - "developer_mode", - "disable_games_tab", - "enable_tts_command", - "explicit_content_filter", - "friend_source_flags", - "gateway_connected", - "gif_auto_play", - "guild_folders", - "guild_positions", - "inline_attachment_media", - "inline_embed_media", - "locale", - "message_display_compact", - "native_phone_integration_enabled", - "render_embeds", - "render_reactions", - "restricted_guilds", - "show_current_game", - "status", - "stream_notifications_enabled", - "theme", - "timezone_offset" - ] - }, - "Team": { - "type": "object", - "properties": { - "icon": { - "type": "string" - }, - "members": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TeamMember" - } - }, - "name": { - "type": "string" - }, - "owner_user_id": { - "type": "string" - }, - "owner_user": { - "$ref": "#/components/schemas/User" - }, - "id": { - "type": "string" - } - }, - "required": ["id", "members", "name", "owner_user", "owner_user_id"] - }, - "TeamMember": { - "type": "object", - "properties": { - "membership_state": { - "$ref": "#/components/schemas/TeamMemberState" - }, - "permissions": { - "type": "array", - "items": { - "type": "string" - } - }, - "team_id": { - "type": "string" - }, - "team": { - "$ref": "#/components/schemas/Team" - }, - "user_id": { - "type": "string" - }, - "user": { - "$ref": "#/components/schemas/User" - }, - "id": { - "type": "string" - } - }, - "required": ["id", "membership_state", "permissions", "team", "team_id", "user", "user_id"] - }, - "TeamMemberState": { - "enum": [1, 2], - "type": "number" - }, - "Guild": { - "type": "object", - "properties": { - "afk_channel_id": { - "type": "string" - }, - "afk_channel": { - "$ref": "#/components/schemas/Channel" - }, - "afk_timeout": { - "type": "integer" - }, - "bans": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Ban" - } - }, - "banner": { - "type": "string" - }, - "default_message_notifications": { - "type": "integer" - }, - "description": { - "type": "string" - }, - "discovery_splash": { - "type": "string" - }, - "explicit_content_filter": { - "type": "integer" - }, - "features": { - "type": "array", - "items": { - "type": "string" - } - }, - "icon": { - "type": "string" - }, - "large": { - "type": "boolean" - }, - "max_members": { - "type": "integer" - }, - "max_presences": { - "type": "integer" - }, - "max_video_channel_users": { - "type": "integer" - }, - "member_count": { - "type": "integer" - }, - "presence_count": { - "type": "integer" - }, - "members": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Member" - } - }, - "roles": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Role" - } - }, - "channels": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Channel" - } - }, - "template_id": { - "type": "string" - }, - "template": { - "$ref": "#/components/schemas/Template" - }, - "emojis": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Emoji" - } - }, - "stickers": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Sticker" - } - }, - "invites": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Invite" - } - }, - "voice_states": { - "type": "array", - "items": { - "$ref": "#/components/schemas/VoiceState" - } - }, - "webhooks": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Webhook" - } - }, - "mfa_level": { - "type": "integer" - }, - "name": { - "type": "string" - }, - "owner_id": { - "type": "string" - }, - "owner": { - "$ref": "#/components/schemas/User" - }, - "preferred_locale": { - "type": "string" - }, - "premium_subscription_count": { - "type": "integer" - }, - "premium_tier": { - "type": "integer" - }, - "public_updates_channel_id": { - "type": "string" - }, - "public_updates_channel": { - "$ref": "#/components/schemas/Channel" - }, - "rules_channel_id": { - "type": "string" - }, - "rules_channel": { - "type": "string" - }, - "region": { - "type": "string" - }, - "splash": { - "type": "string" - }, - "system_channel_id": { - "type": "string" - }, - "system_channel": { - "$ref": "#/components/schemas/Channel" - }, - "system_channel_flags": { - "type": "integer" - }, - "unavailable": { - "type": "boolean" - }, - "vanity_url_code": { - "type": "string" - }, - "vanity_url": { - "$ref": "#/components/schemas/Invite" - }, - "verification_level": { - "type": "integer" - }, - "welcome_screen": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean" - }, - "description": { - "type": "string" - }, - "welcome_channels": { - "type": "array", - "items": { - "type": "object", - "properties": { - "description": { - "type": "string" - }, - "emoji_id": { - "type": "string" - }, - "emoji_name": { - "type": "string" - }, - "channel_id": { - "type": "string" - } - }, - "additionalProperties": false, - "required": ["channel_id", "description", "emoji_name"] - } - } - }, - "additionalProperties": false, - "required": ["description", "enabled", "welcome_channels"] - }, - "widget_channel_id": { - "type": "string" - }, - "widget_channel": { - "$ref": "#/components/schemas/Channel" - }, - "widget_enabled": { - "type": "boolean" - }, - "id": { - "type": "string" - } - }, - "required": [ - "bans", - "channels", - "emojis", - "features", - "id", - "invites", - "members", - "name", - "owner", - "owner_id", - "public_updates_channel_id", - "roles", - "stickers", - "template", - "template_id", - "voice_states", - "webhooks", - "welcome_screen" - ] - }, - "Channel": { - "type": "object", - "properties": { - "created_at": { - "type": "string", - "format": "date-time" - }, - "name": { - "type": "string" - }, - "type": { - "$ref": "#/components/schemas/ChannelType" - }, - "recipients": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Recipient" - } - }, - "last_message_id": { - "type": "string" - }, - "last_message": { - "$ref": "#/components/schemas/Message" - }, - "guild_id": { - "type": "string" - }, - "guild": { - "$ref": "#/components/schemas/Guild" - }, - "parent_id": { - "type": "string" - }, - "parent": { - "$ref": "#/components/schemas/Channel" - }, - "owner_id": { - "type": "string" - }, - "owner": { - "$ref": "#/components/schemas/User" - }, - "last_pin_timestamp": { - "type": "integer" - }, - "default_auto_archive_duration": { - "type": "integer" - }, - "position": { - "type": "integer" - }, - "permission_overwrites": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ChannelPermissionOverwrite" - } - }, - "video_quality_mode": { - "type": "integer" - }, - "bitrate": { - "type": "integer" - }, - "user_limit": { - "type": "integer" - }, - "nsfw": { - "type": "boolean" - }, - "rate_limit_per_user": { - "type": "integer" - }, - "topic": { - "type": "string" - }, - "id": { - "type": "string" - } - }, - "required": [ - "created_at", - "guild", - "id", - "last_message_id", - "name", - "owner", - "owner_id", - "parent_id", - "permission_overwrites", - "position", - "type" - ] - }, - "ChannelType": { - "enum": [0, 1, 2, 3, 4, 5, 6], - "type": "number" - }, - "Recipient": { - "type": "object", - "properties": { - "channel_id": { - "type": "string" - }, - "channel": { - "$ref": "#/components/schemas/Channel" - }, - "user": { - "$ref": "#/components/schemas/User" - }, - "id": { - "type": "string" - } - }, - "required": ["channel", "channel_id", "id", "user"] - }, - "Message": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "channel_id": { - "type": "string" - }, - "channel": { - "$ref": "#/components/schemas/Channel" - }, - "guild_id": { - "type": "string" - }, - "guild": { - "$ref": "#/components/schemas/Guild" - }, - "author_id": { - "type": "string" - }, - "author": { - "$ref": "#/components/schemas/User" - }, - "member_id": { - "type": "string" - }, - "member": { - "$ref": "#/components/schemas/Member" - }, - "webhook_id": { - "type": "string" - }, - "webhook": { - "$ref": "#/components/schemas/Webhook" - }, - "application_id": { - "type": "string" - }, - "application": { - "$ref": "#/components/schemas/Application" - }, - "content": { - "type": "string" - }, - "timestamp": { - "type": "string", - "format": "date-time" - }, - "edited_timestamp": { - "type": "string", - "format": "date-time" - }, - "tts": { - "type": "boolean" - }, - "mention_everyone": { - "type": "boolean" - }, - "mentions": { - "type": "array", - "items": { - "$ref": "#/components/schemas/User" - } - }, - "mention_roles": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Role" - } - }, - "mention_channels": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Channel" - } - }, - "sticker_items": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Sticker" - } - }, - "attachments": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Attachment" - } - }, - "embeds": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Embed" - } - }, - "reactions": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Reaction" - } - }, - "nonce": { - "type": "string" - }, - "pinned": { - "type": "boolean" - }, - "type": { - "$ref": "#/components/schemas/MessageType" - }, - "activity": { - "type": "object", - "properties": { - "type": { - "type": "integer" - }, - "party_id": { - "type": "string" - } - }, - "additionalProperties": false, - "required": ["party_id", "type"] - }, - "flags": { - "type": "string" - }, - "message_reference": { - "type": "object", - "properties": { - "message_id": { - "type": "string" - }, - "channel_id": { - "type": "string" - }, - "guild_id": { - "type": "string" - } - }, - "additionalProperties": false, - "required": ["message_id"] - }, - "referenced_message": { - "$ref": "#/components/schemas/Message" - }, - "interaction": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "type": { - "$ref": "#/components/schemas/InteractionType" - }, - "name": { - "type": "string" - }, - "user_id": { - "type": "string" - } - }, - "additionalProperties": false, - "required": ["id", "name", "type", "user_id"] - }, - "components": { - "type": "array", - "items": { - "$ref": "#/components/schemas/MessageComponent" - } - } - }, - "required": [ - "application_id", - "author_id", - "channel", - "channel_id", - "embeds", - "id", - "member_id", - "mention_channels", - "mention_roles", - "mentions", - "reactions", - "timestamp", - "type", - "webhook_id" - ] - }, - "Member": { - "type": "object", - "properties": { - "user_id": { - "type": "string" - }, - "user": { - "$ref": "#/components/schemas/User" - }, - "guild_id": { - "type": "string" - }, - "guild": { - "$ref": "#/components/schemas/Guild" - }, - "nick": { - "type": "string" - }, - "roles": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Role" - } - }, - "joined_at": { - "type": "string", - "format": "date-time" - }, - "premium_since": { - "type": "integer" - }, - "deaf": { - "type": "boolean" - }, - "mute": { - "type": "boolean" - }, - "pending": { - "type": "boolean" - }, - "settings": { - "$ref": "#/components/schemas/UserGuildSettings" - }, - "id": { - "type": "string" - } - }, - "required": ["deaf", "guild", "guild_id", "id", "joined_at", "mute", "pending", "roles", "settings", "user", "user_id"] - }, - "Role": { - "type": "object", - "properties": { - "guild_id": { - "type": "string" - }, - "guild": { - "$ref": "#/components/schemas/Guild" - }, - "color": { - "type": "integer" - }, - "hoist": { - "type": "boolean" - }, - "managed": { - "type": "boolean" - }, - "mentionable": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "permissions": { - "type": "string" - }, - "position": { - "type": "integer" - }, - "tags": { - "type": "object", - "properties": { - "bot_id": { - "type": "string" - }, - "integration_id": { - "type": "string" - }, - "premium_subscriber": { - "type": "boolean" - } - }, - "additionalProperties": false - }, - "id": { - "type": "string" - } - }, - "required": ["color", "guild", "guild_id", "hoist", "id", "managed", "mentionable", "name", "permissions", "position"] - }, - "UserGuildSettings": { - "type": "object", - "properties": { - "channel_overrides": { - "type": "array", - "items": { - "type": "object", - "properties": { - "channel_id": { - "type": "string" - }, - "message_notifications": { - "type": "integer" - }, - "mute_config": { - "$ref": "#/components/schemas/MuteConfig" - }, - "muted": { - "type": "boolean" - } - }, - "additionalProperties": false, - "required": ["channel_id", "message_notifications", "mute_config", "muted"] - } - }, - "message_notifications": { - "type": "integer" - }, - "mobile_push": { - "type": "boolean" - }, - "mute_config": { - "$ref": "#/components/schemas/MuteConfig" - }, - "muted": { - "type": "boolean" - }, - "suppress_everyone": { - "type": "boolean" - }, - "suppress_roles": { - "type": "boolean" - }, - "version": { - "type": "integer" - } - }, - "required": [ - "channel_overrides", - "message_notifications", - "mobile_push", - "mute_config", - "muted", - "suppress_everyone", - "suppress_roles", - "version" - ] - }, - "MuteConfig": { - "type": "object", - "properties": { - "end_time": { - "type": "integer" - }, - "selected_time_window": { - "type": "integer" - } - }, - "required": ["end_time", "selected_time_window"] - }, - "Webhook": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "type": { - "$ref": "#/components/schemas/WebhookType" - }, - "name": { - "type": "string" - }, - "avatar": { - "type": "string" - }, - "token": { - "type": "string" - }, - "guild_id": { - "type": "string" - }, - "guild": { - "$ref": "#/components/schemas/Guild" - }, - "channel_id": { - "type": "string" - }, - "channel": { - "$ref": "#/components/schemas/Channel" - }, - "application_id": { - "type": "string" - }, - "application": { - "$ref": "#/components/schemas/Application" - }, - "user_id": { - "type": "string" - }, - "user": { - "$ref": "#/components/schemas/User" - }, - "source_guild_id": { - "type": "string" - }, - "source_guild": { - "$ref": "#/components/schemas/Guild" - } - }, - "required": [ - "application", - "application_id", - "channel", - "channel_id", - "guild", - "guild_id", - "id", - "source_guild", - "source_guild_id", - "type", - "user", - "user_id" - ] - }, - "WebhookType": { - "enum": [1, 2], - "type": "number" - }, - "Application": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "icon": { - "type": "string" - }, - "description": { - "type": "string" - }, - "rpc_origins": { - "type": "array", - "items": { - "type": "string" - } - }, - "bot_public": { - "type": "boolean" - }, - "bot_require_code_grant": { - "type": "boolean" - }, - "terms_of_service_url": { - "type": "string" - }, - "privacy_policy_url": { - "type": "string" - }, - "owner": { - "$ref": "#/components/schemas/User" - }, - "summary": { - "type": "string" - }, - "verify_key": { - "type": "string" - }, - "team": { - "$ref": "#/components/schemas/Team" - }, - "guild": { - "$ref": "#/components/schemas/Guild" - }, - "primary_sku_id": { - "type": "string" - }, - "slug": { - "type": "string" - }, - "cover_image": { - "type": "string" - }, - "flags": { - "type": "string" - }, - "id": { - "type": "string" - } - }, - "required": ["bot_public", "bot_require_code_grant", "description", "flags", "guild", "id", "name", "verify_key"] - }, - "Sticker": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "description": { - "type": "string" - }, - "tags": { - "type": "string" - }, - "pack_id": { - "type": "string" - }, - "guild_id": { - "type": "string" - }, - "guild": { - "$ref": "#/components/schemas/Guild" - }, - "type": { - "$ref": "#/components/schemas/StickerType" - }, - "format_type": { - "$ref": "#/components/schemas/StickerFormatType" - }, - "id": { - "type": "string" - } - }, - "required": ["format_type", "id", "name", "pack_id", "tags", "type"] - }, - "StickerType": { - "enum": [1, 2], - "type": "number" - }, - "StickerFormatType": { - "enum": [1, 2, 3], - "type": "number" - }, - "Attachment": { - "type": "object", - "properties": { - "filename": { - "type": "string" - }, - "size": { - "type": "integer" - }, - "url": { - "type": "string" - }, - "proxy_url": { - "type": "string" - }, - "height": { - "type": "integer" - }, - "width": { - "type": "integer" - }, - "content_type": { - "type": "string" - }, - "message_id": { - "type": "string" - }, - "message": { - "$ref": "#/components/schemas/Message" - }, - "id": { - "type": "string" - } - }, - "required": ["filename", "id", "message", "message_id", "proxy_url", "size", "url"] - }, - "Embed": { - "type": "object", - "properties": { - "title": { - "type": "string" - }, - "type": { - "enum": ["article", "gifv", "image", "link", "rich", "video"], - "type": "string" - }, - "description": { - "type": "string" - }, - "url": { - "type": "string" - }, - "timestamp": { - "type": "string", - "format": "date-time" - }, - "color": { - "type": "integer" - }, - "footer": { - "type": "object", - "properties": { - "text": { - "type": "string" - }, - "icon_url": { - "type": "string" - }, - "proxy_icon_url": { - "type": "string" - } - }, - "additionalProperties": false, - "required": ["text"] - }, - "image": { - "$ref": "#/components/schemas/EmbedImage" - }, - "thumbnail": { - "$ref": "#/components/schemas/EmbedImage" - }, - "video": { - "$ref": "#/components/schemas/EmbedImage" - }, - "provider": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "url": { - "type": "string" - } - }, - "additionalProperties": false - }, - "author": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "url": { - "type": "string" - }, - "icon_url": { - "type": "string" - }, - "proxy_icon_url": { - "type": "string" - } - }, - "additionalProperties": false - }, - "fields": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "value": { - "type": "string" - }, - "inline": { - "type": "boolean" - } - }, - "additionalProperties": false, - "required": ["name", "value"] - } - } - } - }, - "EmbedType": { - "enum": ["article", "gifv", "image", "link", "rich", "video"], - "type": "string" - }, - "EmbedImage": { - "type": "object", - "properties": { - "url": { - "type": "string" - }, - "proxy_url": { - "type": "string" - }, - "height": { - "type": "integer" - }, - "width": { - "type": "integer" - } - } - }, - "Reaction": { - "type": "object", - "properties": { - "count": { - "type": "integer" - }, - "emoji": { - "$ref": "#/components/schemas/PartialEmoji" - }, - "user_ids": { - "type": "array", - "items": { - "type": "string" - } - } - }, - "required": ["count", "emoji", "user_ids"] - }, - "PartialEmoji": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "name": { - "type": "string" - }, - "animated": { - "type": "boolean" - } - }, - "required": ["name"] - }, - "MessageType": { - "enum": [0, 1, 10, 11, 12, 14, 15, 19, 2, 20, 3, 4, 5, 6, 7, 8, 9], - "type": "number" - }, - "InteractionType": { - "enum": [1, 2], - "type": "number" - }, - "MessageComponent": { - "type": "object", - "properties": { - "type": { - "type": "integer" - }, - "style": { - "type": "integer" - }, - "label": { - "type": "string" - }, - "emoji": { - "$ref": "#/components/schemas/PartialEmoji" - }, - "custom_id": { - "type": "string" - }, - "url": { - "type": "string" - }, - "disabled": { - "type": "boolean" - }, - "components": { - "type": "array", - "items": { - "$ref": "#/components/schemas/MessageComponent" - } - } - }, - "required": ["components", "type"] - }, - "ChannelPermissionOverwrite": { - "type": "object", - "properties": { - "allow": { - "type": "number" - }, - "deny": { - "type": "number" - }, - "id": { - "type": "string" - }, - "type": { - "$ref": "#/components/schemas/ChannelPermissionOverwriteType" - } - }, - "required": ["allow", "deny", "id", "type"] - }, - "ChannelPermissionOverwriteType": { - "enum": [0, 1], - "type": "number" - }, - "Ban": { - "type": "object", - "properties": { - "user_id": { - "type": "string" - }, - "user": { - "$ref": "#/components/schemas/User" - }, - "guild_id": { - "type": "string" - }, - "guild": { - "$ref": "#/components/schemas/Guild" - }, - "executor_id": { - "type": "string" - }, - "executor": { - "$ref": "#/components/schemas/User" - }, - "ip": { - "type": "string" - }, - "reason": { - "type": "string" - }, - "id": { - "type": "string" - } - }, - "required": ["executor", "executor_id", "guild", "guild_id", "id", "ip", "user", "user_id"] - }, - "Template": { - "type": "object", - "properties": { - "code": { - "type": "string" - }, - "name": { - "type": "string" - }, - "description": { - "type": "string" - }, - "usage_count": { - "type": "integer" - }, - "creator_id": { - "type": "string" - }, - "creator": { - "$ref": "#/components/schemas/User" - }, - "created_at": { - "type": "string", - "format": "date-time" - }, - "updated_at": { - "type": "string", - "format": "date-time" - }, - "source_guild_id": { - "type": "string" - }, - "source_guild": { - "$ref": "#/components/schemas/Guild" - }, - "serialized_source_guild": { - "$ref": "#/components/schemas/Guild" - }, - "id": { - "type": "string" - } - }, - "required": [ - "code", - "created_at", - "creator", - "creator_id", - "id", - "name", - "serialized_source_guild", - "source_guild", - "source_guild_id", - "updated_at" - ] - }, - "Emoji": { - "type": "object", - "properties": { - "animated": { - "type": "boolean" - }, - "available": { - "type": "boolean" - }, - "guild_id": { - "type": "string" - }, - "guild": { - "$ref": "#/components/schemas/Guild" - }, - "managed": { - "type": "boolean" - }, - "name": { - "type": "string" - }, - "require_colons": { - "type": "boolean" - }, - "id": { - "type": "string" - } - }, - "required": ["animated", "available", "guild", "guild_id", "id", "managed", "name", "require_colons"] - }, - "Invite": { - "type": "object", - "properties": { - "code": { - "type": "string" - }, - "temporary": { - "type": "boolean" - }, - "uses": { - "type": "integer" - }, - "max_uses": { - "type": "integer" - }, - "max_age": { - "type": "integer" - }, - "created_at": { - "type": "string", - "format": "date-time" - }, - "expires_at": { - "type": "string", - "format": "date-time" - }, - "guild_id": { - "type": "string" - }, - "guild": { - "$ref": "#/components/schemas/Guild" - }, - "channel_id": { - "type": "string" - }, - "channel": { - "$ref": "#/components/schemas/Channel" - }, - "inviter_id": { - "type": "string" - }, - "inviter": { - "$ref": "#/components/schemas/User" - }, - "target_user_id": { - "type": "string" - }, - "target_user": { - "type": "string" - }, - "target_user_type": { - "type": "integer" - }, - "id": { - "type": "string" - } - }, - "required": [ - "channel", - "channel_id", - "code", - "created_at", - "expires_at", - "guild", - "guild_id", - "id", - "inviter", - "inviter_id", - "max_age", - "max_uses", - "target_user_id", - "temporary", - "uses" - ] - }, - "VoiceState": { - "type": "object", - "properties": { - "guild_id": { - "type": "string" - }, - "guild": { - "$ref": "#/components/schemas/Guild" - }, - "channel_id": { - "type": "string" - }, - "channel": { - "$ref": "#/components/schemas/Channel" - }, - "user_id": { - "type": "string" - }, - "user": { - "$ref": "#/components/schemas/User" - }, - "session_id": { - "type": "string" - }, - "deaf": { - "type": "boolean" - }, - "mute": { - "type": "boolean" - }, - "self_deaf": { - "type": "boolean" - }, - "self_mute": { - "type": "boolean" - }, - "self_stream": { - "type": "boolean" - }, - "self_video": { - "type": "boolean" - }, - "suppress": { - "type": "boolean" - }, - "id": { - "type": "string" - } - }, - "required": [ - "channel", - "channel_id", - "deaf", - "guild_id", - "id", - "mute", - "self_deaf", - "self_mute", - "self_video", - "session_id", - "suppress", - "user", - "user_id" - ] - }, - "AuditLogEvents": { - "enum": [ - 1, 10, 11, 12, 13, 14, 15, 20, 21, 22, 23, 24, 25, 26, 27, 28, 30, 31, 32, 40, 41, 42, 50, 51, 52, 60, 61, 62, 72, 73, - 74, 75, 80, 81, 82 - ], - "type": "number" - }, - "AuditLogChange": { - "type": "object", - "properties": { - "new_value": { - "$ref": "#/components/schemas/AuditLogChangeValue" - }, - "old_value": { - "$ref": "#/components/schemas/AuditLogChangeValue" - }, - "key": { - "type": "string" - } - }, - "required": ["key"] - }, - "AuditLogChangeValue": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "description": { - "type": "string" - }, - "icon_hash": { - "type": "string" - }, - "splash_hash": { - "type": "string" - }, - "discovery_splash_hash": { - "type": "string" - }, - "banner_hash": { - "type": "string" - }, - "owner_id": { - "type": "string" - }, - "region": { - "type": "string" - }, - "preferred_locale": { - "type": "string" - }, - "afk_channel_id": { - "type": "string" - }, - "afk_timeout": { - "type": "integer" - }, - "rules_channel_id": { - "type": "string" - }, - "public_updates_channel_id": { - "type": "string" - }, - "mfa_level": { - "type": "integer" - }, - "verification_level": { - "type": "integer" - }, - "explicit_content_filter": { - "type": "integer" - }, - "default_message_notifications": { - "type": "integer" - }, - "vanity_url_code": { - "type": "string" - }, - "$add": { - "type": "array", - "items": { - "type": "object", - "properties": {} - } - }, - "$remove": { - "type": "array", - "items": { - "type": "object", - "properties": {} - } - }, - "prune_delete_days": { - "type": "integer" - }, - "widget_enabled": { - "type": "boolean" - }, - "widget_channel_id": { - "type": "string" - }, - "system_channel_id": { - "type": "string" - }, - "position": { - "type": "integer" - }, - "topic": { - "type": "string" - }, - "bitrate": { - "type": "integer" - }, - "permission_overwrites": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ChannelPermissionOverwrite" - } - }, - "nsfw": { - "type": "boolean" - }, - "application_id": { - "type": "string" - }, - "rate_limit_per_user": { - "type": "integer" - }, - "permissions": { - "type": "string" - }, - "color": { - "type": "integer" - }, - "hoist": { - "type": "boolean" - }, - "mentionable": { - "type": "boolean" - }, - "allow": { - "type": "string" - }, - "deny": { - "type": "string" - }, - "code": { - "type": "string" - }, - "channel_id": { - "type": "string" - }, - "inviter_id": { - "type": "string" - }, - "max_uses": { - "type": "integer" - }, - "uses": { - "type": "integer" - }, - "max_age": { - "type": "integer" - }, - "temporary": { - "type": "boolean" - }, - "deaf": { - "type": "boolean" - }, - "mute": { - "type": "boolean" - }, - "nick": { - "type": "string" - }, - "avatar_hash": { - "type": "string" - }, - "id": { - "type": "string" - }, - "type": { - "type": "integer" - }, - "enable_emoticons": { - "type": "boolean" - }, - "expire_behavior": { - "type": "integer" - }, - "expire_grace_period": { - "type": "integer" - }, - "user_limit": { - "type": "integer" - } - } - }, - "AuditLog": { - "type": "object", - "properties": { - "target": { - "$ref": "#/components/schemas/User" - }, - "user_id": { - "type": "string" - }, - "user": { - "$ref": "#/components/schemas/User" - }, - "action_type": { - "$ref": "#/components/schemas/AuditLogEvents" - }, - "options": { - "type": "object", - "properties": { - "delete_member_days": { - "type": "string" - }, - "members_removed": { - "type": "string" - }, - "channel_id": { - "type": "string" - }, - "messaged_id": { - "type": "string" - }, - "count": { - "type": "string" - }, - "id": { - "type": "string" - }, - "type": { - "type": "string" - }, - "role_name": { - "type": "string" - } - }, - "additionalProperties": false - }, - "changes": { - "type": "array", - "items": { - "$ref": "#/components/schemas/AuditLogChange" - } - }, - "reason": { - "type": "string" - }, - "id": { - "type": "string" - } - }, - "required": ["action_type", "changes", "id", "user", "user_id"] - }, - "ReadState": { - "type": "object", - "properties": { - "channel_id": { - "type": "string" - }, - "channel": { - "$ref": "#/components/schemas/Channel" - }, - "user_id": { - "type": "string" - }, - "user": { - "$ref": "#/components/schemas/User" - }, - "last_message_id": { - "type": "string" - }, - "last_message": { - "$ref": "#/components/schemas/Message" - }, - "last_pin_timestamp": { - "type": "string", - "format": "date-time" - }, - "mention_count": { - "type": "integer" - }, - "manual": { - "type": "boolean" - }, - "id": { - "type": "string" - } - }, - "required": ["channel", "channel_id", "id", "last_message_id", "manual", "mention_count", "user", "user_id"] - }, - "UserPublic": { - "type": "object", - "properties": { - "username": { - "type": "string" - }, - "discriminator": { - "type": "string" - }, - "id": { - "type": "string" - }, - "public_flags": { - "type": "integer" - }, - "avatar": { - "type": "string" - }, - "accent_color": { - "type": "integer" - }, - "banner": { - "type": "string" - }, - "bio": { - "type": "string" - }, - "bot": { - "type": "boolean" - } - }, - "required": ["bio", "bot", "discriminator", "id", "public_flags", "username"] - }, - "UserPrivate": { - "type": "object", - "properties": { - "locale": { - "type": "string" - }, - "disabled": { - "type": "boolean" - }, - "username": { - "type": "string" - }, - "discriminator": { - "type": "string" - }, - "id": { - "type": "string" - }, - "public_flags": { - "type": "string" - }, - "avatar": { - "type": "string" - }, - "accent_color": { - "type": "integer" - }, - "banner": { - "type": "string" - }, - "bio": { - "type": "string" - }, - "bot": { - "type": "boolean" - }, - "flags": { - "type": "string" - }, - "mfa_enabled": { - "type": "boolean" - }, - "email": { - "type": "string" - }, - "phone": { - "type": "string" - }, - "verified": { - "type": "boolean" - }, - "nsfw_allowed": { - "type": "boolean" - }, - "premium": { - "type": "boolean" - }, - "premium_type": { - "type": "integer" - } - }, - "required": [ - "bio", - "bot", - "disabled", - "discriminator", - "flags", - "id", - "locale", - "mfa_enabled", - "nsfw_allowed", - "premium", - "premium_type", - "public_flags", - "username", - "verified" - ] - }, - "BanCreateSchema": { - "type": "object", - "properties": { - "delete_message_days": { - "type": "string" - }, - "reason": { - "type": "string" - } - } - }, - "DmChannelCreateSchema": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "recipients": { - "type": "array", - "items": { - "type": "string" - } - } - }, - "required": ["recipients"] - }, - "ChannelModifySchema": { - "type": "object", - "properties": { - "name": { - "maxLength": 100, - "type": "string" - }, - "type": { - "enum": [0, 1, 10, 11, 12, 13, 2, 3, 4, 5, 6], - "type": "number" - }, - "topic": { - "type": "string" - }, - "icon": { - "type": "string", - "nullable": true - }, - "bitrate": { - "type": "integer" - }, - "user_limit": { - "type": "integer" - }, - "rate_limit_per_user": { - "type": "integer" - }, - "position": { - "type": "integer" - }, - "permission_overwrites": { - "type": "array", - "items": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "type": { - "$ref": "#/components/schemas/ChannelPermissionOverwriteType" - }, - "allow": { - "type": "number" - }, - "deny": { - "type": "number" - } - }, - "additionalProperties": false, - "required": ["allow", "deny", "id", "type"] - } - }, - "parent_id": { - "type": "string" - }, - "id": { - "type": "string" - }, - "nsfw": { - "type": "boolean" - }, - "rtc_region": { - "type": "string" - }, - "default_auto_archive_duration": { - "type": "integer" - } - } - }, - "ChannelGuildPositionUpdateSchema": { - "type": "array", - "items": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "position": { - "type": "integer" - } - }, - "additionalProperties": false, - "required": ["id"] - } - }, - "EmojiCreateSchema": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "image": { - "type": "string" - }, - "roles": { - "type": "array", - "items": { - "type": "string" - } - } - }, - "required": ["image", "name"] - }, - "GuildCreateSchema": { - "type": "object", - "properties": { - "name": { - "maxLength": 100, - "type": "string" - }, - "region": { - "type": "string" - }, - "icon": { - "type": "string", - "nullable": true - }, - "channels": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ChannelModifySchema" - } - }, - "guild_template_code": { - "type": "string" - }, - "system_channel_id": { - "type": "string" - }, - "rules_channel_id": { - "type": "string" - } - }, - "required": ["name"] - }, - "GuildUpdateSchema": { - "type": "object", - "properties": { - "banner": { - "type": "string", - "nullable": true - }, - "splash": { - "type": "string", - "nullable": true - }, - "description": { - "type": "string" - }, - "features": { - "type": "array", - "items": { - "type": "string" - } - }, - "verification_level": { - "type": "integer" - }, - "default_message_notifications": { - "type": "integer" - }, - "system_channel_flags": { - "type": "integer" - }, - "explicit_content_filter": { - "type": "integer" - }, - "public_updates_channel_id": { - "type": "string" - }, - "afk_timeout": { - "type": "integer" - }, - "afk_channel_id": { - "type": "string" - }, - "preferred_locale": { - "type": "string" - }, - "name": { - "maxLength": 100, - "type": "string" - }, - "region": { - "type": "string" - }, - "icon": { - "type": "string", - "nullable": true - }, - "guild_template_code": { - "type": "string" - }, - "system_channel_id": { - "type": "string" - }, - "rules_channel_id": { - "type": "string" - } - }, - "required": ["name"] - }, - "GuildTemplateCreateSchema": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "avatar": { - "type": "string", - "nullable": true - } - }, - "required": ["name"] - }, - "GuildUpdateWelcomeScreenSchema": { - "type": "object", - "properties": { - "welcome_channels": { - "type": "array", - "items": { - "type": "object", - "properties": { - "channel_id": { - "type": "string" - }, - "description": { - "type": "string" - }, - "emoji_id": { - "type": "string" - }, - "emoji_name": { - "type": "string" - } - }, - "additionalProperties": false, - "required": ["channel_id", "description", "emoji_name"] - } - }, - "enabled": { - "type": "boolean" - }, - "description": { - "type": "string" - } - } - }, - "InviteCreateSchema": { - "type": "object", - "properties": { - "target_user_id": { - "type": "string" - }, - "target_type": { - "type": "string" - }, - "validate": { - "type": "string" - }, - "max_age": { - "type": "integer" - }, - "max_uses": { - "type": "integer" - }, - "temporary": { - "type": "boolean" - }, - "unique": { - "type": "boolean" - }, - "target_user": { - "type": "string" - }, - "target_user_type": { - "type": "integer" - } - } - }, - "MemberCreateSchema": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "nick": { - "type": "string" - }, - "guild_id": { - "type": "string" - }, - "joined_at": { - "type": "string", - "format": "date-time" - } - }, - "required": ["guild_id", "id", "joined_at", "nick"] - }, - "MemberNickChangeSchema": { - "type": "object", - "properties": { - "nick": { - "type": "string" - } - }, - "required": ["nick"] - }, - "MemberChangeSchema": { - "type": "object", - "properties": { - "roles": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "MessageCreateSchema": { - "type": "object", - "properties": { - "content": { - "type": "string" - }, - "nonce": { - "type": "string" - }, - "tts": { - "type": "boolean" - }, - "flags": { - "type": "string" - }, - "embeds": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Embed" - } - }, - "embed": { - "$ref": "#/components/schemas/Embed" - }, - "allowed_mentions": { - "type": "object", - "properties": { - "parse": { - "type": "array", - "items": { - "type": "string" - } - }, - "roles": { - "type": "array", - "items": { - "type": "string" - } - }, - "users": { - "type": "array", - "items": { - "type": "string" - } - }, - "replied_user": { - "type": "boolean" - } - }, - "additionalProperties": false - }, - "message_reference": { - "type": "object", - "properties": { - "message_id": { - "type": "string" - }, - "channel_id": { - "type": "string" - }, - "guild_id": { - "type": "string" - }, - "fail_if_not_exists": { - "type": "boolean" - } - }, - "additionalProperties": false, - "required": ["channel_id", "message_id"] - }, - "payload_json": { - "type": "string" - }, - "file": {}, - "attachments": { - "type": "array", - "items": {} - } - } - }, - "RoleModifySchema": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "permissions": { - "type": "number" - }, - "color": { - "type": "integer" - }, - "hoist": { - "type": "boolean" - }, - "mentionable": { - "type": "boolean" - }, - "position": { - "type": "integer" - } - } - }, - "TemplateCreateSchema": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "description": { - "type": "string" - } - }, - "required": ["name"] - }, - "TemplateModifySchema": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "description": { - "type": "string" - } - }, - "required": ["name"] - }, - "UserModifySchema": { - "type": "object", - "properties": { - "username": { - "minLength": 1, - "maxLength": 100, - "type": "string" - }, - "avatar": { - "type": "string", - "nullable": true - }, - "bio": { - "maxLength": 1024, - "type": "string" - }, - "accent_color": { - "type": "integer" - }, - "banner": { - "type": "string", - "nullable": true - }, - "password": { - "type": "string" - }, - "new_password": { - "type": "string" - }, - "code": { - "type": "string" - } - } - }, - "UserSettingsSchema": { - "type": "object", - "properties": { - "afk_timeout": { - "type": "integer" - }, - "allow_accessibility_detection": { - "type": "boolean" - }, - "animate_emoji": { - "type": "boolean" - }, - "animate_stickers": { - "type": "integer" - }, - "contact_sync_enabled": { - "type": "boolean" - }, - "convert_emoticons": { - "type": "boolean" - }, - "custom_status": { - "type": "object", - "properties": { - "emoji_id": { - "type": "string" - }, - "emoji_name": { - "type": "string" - }, - "expires_at": { - "type": "integer" - }, - "text": { - "type": "string" - } - }, - "additionalProperties": false - }, - "default_guilds_restricted": { - "type": "boolean" - }, - "detect_platform_accounts": { - "type": "boolean" - }, - "developer_mode": { - "type": "boolean" - }, - "disable_games_tab": { - "type": "boolean" - }, - "enable_tts_command": { - "type": "boolean" - }, - "explicit_content_filter": { - "type": "integer" - }, - "friend_source_flags": { - "type": "object", - "properties": { - "all": { - "type": "boolean" - } - }, - "additionalProperties": false, - "required": ["all"] - }, - "gateway_connected": { - "type": "boolean" - }, - "gif_auto_play": { - "type": "boolean" - }, - "guild_folders": { - "type": "array", - "items": { - "type": "object", - "properties": { - "color": { - "type": "integer" - }, - "guild_ids": { - "type": "array", - "items": { - "type": "string" - } - }, - "id": { - "type": "integer" - }, - "name": { - "type": "string" - } - }, - "additionalProperties": false, - "required": ["color", "guild_ids", "id", "name"] - } - }, - "guild_positions": { - "type": "array", - "items": { - "type": "string" - } - }, - "inline_attachment_media": { - "type": "boolean" - }, - "inline_embed_media": { - "type": "boolean" - }, - "locale": { - "type": "string" - }, - "message_display_compact": { - "type": "boolean" - }, - "native_phone_integration_enabled": { - "type": "boolean" - }, - "render_embeds": { - "type": "boolean" - }, - "render_reactions": { - "type": "boolean" - }, - "restricted_guilds": { - "type": "array", - "items": { - "type": "string" - } - }, - "show_current_game": { - "type": "boolean" - }, - "status": { - "enum": ["dnd", "idle", "offline", "online"], - "type": "string" - }, - "stream_notifications_enabled": { - "type": "boolean" - }, - "theme": { - "enum": ["dark", "white"], - "type": "string" - }, - "timezone_offset": { - "type": "integer" - } - }, - "required": [ - "afk_timeout", - "allow_accessibility_detection", - "animate_emoji", - "animate_stickers", - "contact_sync_enabled", - "convert_emoticons", - "custom_status", - "default_guilds_restricted", - "detect_platform_accounts", - "developer_mode", - "disable_games_tab", - "enable_tts_command", - "explicit_content_filter", - "friend_source_flags", - "gateway_connected", - "gif_auto_play", - "guild_folders", - "guild_positions", - "inline_attachment_media", - "inline_embed_media", - "locale", - "message_display_compact", - "native_phone_integration_enabled", - "render_embeds", - "render_reactions", - "restricted_guilds", - "show_current_game", - "status", - "stream_notifications_enabled", - "theme", - "timezone_offset" - ] - }, - "WidgetModifySchema": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean" - }, - "channel_id": { - "type": "string" - } - }, - "required": ["channel_id", "enabled"] - }, - "RegisterSchema": { - "type": "object", - "properties": { - "username": { - "minLength": 2, - "maxLength": 32, - "type": "string" - }, - "password": { - "minLength": 1, - "maxLength": 72, - "type": "string" - }, - "consent": { - "type": "boolean" - }, - "email": { - "format": "email", - "type": "string" - }, - "fingerprint": { - "type": "string" - }, - "invite": { - "type": "string" - }, - "date_of_birth": { - "type": "string" - }, - "gift_code_sku_id": { - "type": "string" - }, - "captcha_key": { - "type": "string" - } - }, - "required": ["consent", "username"] - }, - "LoginSchema": { - "type": "object", - "properties": { - "login": { - "type": "string" - }, - "password": { - "type": "string" - }, - "undelete": { - "type": "boolean" - }, - "captcha_key": { - "type": "string" - }, - "login_source": { - "type": "string" - }, - "gift_code_sku_id": { - "type": "string" - } - }, - "required": ["login", "password"] - }, - "MessageAcknowledgeSchema": { - "type": "object", - "properties": { - "manual": { - "type": "boolean" - }, - "mention_count": { - "type": "integer" - } - } - }, - "BulkDeleteSchema": { - "type": "object", - "properties": { - "messages": { - "type": "array", - "items": { - "type": "string" - } - } - }, - "required": ["messages"] - }, - "ChannelPermissionOverwriteSchema": { - "type": "object", - "properties": { - "allow": { - "type": "number" - }, - "deny": { - "type": "number" - }, - "id": { - "type": "string" - }, - "type": { - "$ref": "#/components/schemas/ChannelPermissionOverwriteType" - } - }, - "required": ["allow", "deny", "id", "type"] - }, - "WebhookCreateSchema": { - "type": "object", - "properties": { - "name": { - "maxLength": 80, - "type": "string" - }, - "avatar": { - "type": "string" - } - }, - "required": ["avatar", "name"] - }, - "ChannelReorderSchema": { - "type": "array", - "items": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "position": { - "type": "integer" - }, - "lock_permissions": { - "type": "boolean" - }, - "parent_id": { - "type": "string" - } - }, - "additionalProperties": false, - "required": ["id"] - } - }, - "RolePositionUpdateSchema": { - "type": "array", - "items": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "position": { - "type": "integer" - } - }, - "additionalProperties": false, - "required": ["id", "position"] - } - }, - "VanityUrlSchema": { - "type": "object", - "properties": { - "code": { - "minLength": 1, - "maxLength": 20, - "type": "string" - } - } - }, - "VoiceStateUpdateSchema": { - "type": "object", - "properties": { - "channel_id": { - "type": "string" - }, - "guild_id": { - "type": "string" - }, - "suppress": { - "type": "boolean" - }, - "request_to_speak_timestamp": { - "type": "string", - "format": "date-time" - }, - "self_mute": { - "type": "boolean" - }, - "self_deaf": { - "type": "boolean" - }, - "self_video": { - "type": "boolean" - } - }, - "required": ["channel_id"] - }, - "UserProfileResponse": { - "type": "object", - "properties": { - "user": { - "$ref": "#/components/schemas/UserPublic" - }, - "connected_accounts": { - "$ref": "#/components/schemas/PublicConnectedAccount" - }, - "premium_guild_since": { - "type": "string", - "format": "date-time" - }, - "premium_since": { - "type": "string", - "format": "date-time" - } - }, - "required": ["connected_accounts", "user"] - }, - "RelationshipPutSchema": { - "type": "object", - "properties": { - "type": { - "enum": [1, 2, 3, 4], - "type": "number" - } - } - }, - "RelationshipPostSchema": { - "type": "object", - "properties": { - "discriminator": { - "type": "string" - }, - "username": { - "type": "string" - } - }, - "required": ["discriminator", "username"] - }, - "PublicConnectedAccount": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "type": { - "type": "string" - }, - "verifie": { - "type": "boolean" - } - }, - "required": ["name", "type", "verifie"] - } - }, - "requestBodies": {}, - "securitySchemes": { - "Token": { - "type": "apiKey", - "name": "Authorization", - "in": "header" - } - }, - "links": {}, - "callbacks": {} - } -} + "openapi": "3.0.0", + "servers": [ + { + "url": "https://api.fosscord.com/v{version}", + "description": "Official fosscord instance", + "variables": { + "version": { + "default": "9", + "enum": [ + "8", + "9" + ] + } + } + } + ], + "info": { + "description": "Fosscord is a free open source selfhostable discord compatible chat, voice and video platform", + "version": "1.0.0", + "title": "Fosscord HTTP API Routes", + "termsOfService": "", + "contact": { + "name": "Fosscord" + }, + "license": { + "name": "AGPLV3", + "url": "https://www.gnu.org/licenses/agpl-3.0.en.html" + } + }, + "tags": [ + { + "name": "voice" + }, + { + "name": "users" + }, + { + "name": "store" + }, + { + "name": "sticker-packs" + }, + { + "name": "science" + }, + { + "name": "ping" + }, + { + "name": "outbound-promotions" + }, + { + "name": "invites" + }, + { + "name": "guilds" + }, + { + "name": "gateway" + }, + { + "name": "experiments" + }, + { + "name": "discoverable-guilds" + }, + { + "name": "channels" + }, + { + "name": "auth" + }, + { + "name": "applications" + } + ], + "paths": { + "/users/{id}": { + "get": { + "summary": "", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "user id" + } + ], + "operationId": "", + "responses": { + "200": { + "description": "User found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserPublic" + } + } + } + }, + "404": { + "description": "User not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Error" + } + } + } + } + }, + "security": [ + { + "Token": [] + } + ] + } + }, + "/users/@me": { + "get": { + "summary": "", + "parameters": [], + "operationId": "", + "responses": { + "200": { + "description": "Authenticated user", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserPublic" + } + } + } + } + }, + "security": [ + { + "Token": [] + } + ] + } + }, + "/voice/regions/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": [ + "voice" + ] + } + }, + "/users/@me/settings/": { + "patch": { + "description": "", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserSettingsSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": [ + "users" + ] + } + }, + "/users/@me/relationships/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": [ + "users", + "relationships" + ] + }, + "post": { + "description": "", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RelationshipPostSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": [ + "users" + ] + } + }, + "/users/@me/relationships/{id}": { + "put": { + "description": "", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RelationshipPutSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "id" + } + ], + "tags": [ + "users" + ] + }, + "delete": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "id" + } + ], + "tags": [ + "users" + ] + } + }, + "/users/@me/library/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": [ + "users" + ] + } + }, + "/users/@me/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": [ + "users" + ] + }, + "patch": { + "description": "", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserModifySchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": [ + "users" + ] + } + }, + "/users/@me/guilds/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": [ + "users" + ] + } + }, + "/users/@me/guilds/{id}": { + "delete": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "id" + } + ], + "tags": [ + "users" + ] + } + }, + "/users/@me/disable/": { + "post": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": [ + "users" + ] + } + }, + "/users/@me/devices/": { + "post": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": [ + "users" + ] + } + }, + "/users/@me/delete/": { + "post": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": [ + "users" + ] + } + }, + "/users/@me/connections/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": [ + "users" + ] + } + }, + "/users/@me/channels/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": [ + "users" + ] + }, + "post": { + "description": "", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DmChannelCreateSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": [ + "users" + ] + } + }, + "/users/@me/billing/subscriptions/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": [ + "users" + ] + } + }, + "/users/@me/billing/country-code/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": [ + "users" + ] + } + }, + "/users/@me/applications/{app_id}/entitlements/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "app_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "app_id" + } + ], + "tags": [ + "users" + ] + } + }, + "/users/@me/affinities/users/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": [ + "users" + ] + } + }, + "/users/@me/affinities/guilds/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": [ + "users" + ] + } + }, + "/users/{id}/profile/": { + "get": { + "description": "", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserProfileResponse" + } + } + }, + "description": "" + } + }, + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "id" + } + ], + "tags": [ + "users" + ] + } + }, + "/users/{id}/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "id" + } + ], + "tags": [ + "users" + ] + } + }, + "/store/skus/skus/{id}": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "id" + } + ], + "tags": [ + "store" + ] + } + }, + "/store/applications/applications/{id}": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "id" + } + ], + "tags": [ + "store" + ] + } + }, + "/sticker-packs/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": [ + "sticker", + "sticker-packs" + ] + } + }, + "/sticker-packs/{id}/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "id" + } + ], + "tags": [ + "sticker", + "sticker-packs" + ] + } + }, + "/science/": { + "post": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": [ + "science" + ] + } + }, + "/ping/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": [ + "ping" + ] + } + }, + "/outbound-promotions/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": [ + "outbound", + "outbound-promotions" + ] + } + }, + "/invites/{code}": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "code", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "code" + } + ], + "tags": [ + "invites" + ] + }, + "post": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "code", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "code" + } + ], + "tags": [ + "invites" + ] + }, + "delete": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "code", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "code" + } + ], + "tags": [ + "invites" + ] + } + }, + "/guilds/templates/{code}": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "code", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "code" + } + ], + "tags": [ + "guilds" + ] + }, + "post": { + "description": "", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GuildTemplateCreateSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "code", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "code" + } + ], + "tags": [ + "guilds" + ] + } + }, + "/guilds/": { + "post": { + "description": "", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GuildCreateSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": [ + "guilds" + ] + } + }, + "/guilds/{guild_id}/widget.png/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": [ + "guilds" + ] + } + }, + "/guilds/{guild_id}/widget.json/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": [ + "guilds" + ] + } + }, + "/guilds/{guild_id}/widget/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": [ + "guilds" + ] + }, + "patch": { + "description": "##### Requires the ``MANAGE_GUILD`` permission\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WidgetModifySchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": [ + "guilds" + ] + } + }, + "/guilds/{guild_id}/welcome_screen/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": [ + "guilds" + ] + }, + "patch": { + "description": "##### Requires the ``MANAGE_GUILD`` permission\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GuildUpdateWelcomeScreenSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": [ + "guilds" + ] + } + }, + "/guilds/{guild_id}/voice-states/{user_id}/": { + "patch": { + "description": "", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VoiceStateUpdateSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + }, + { + "name": "user_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "user_id" + } + ], + "tags": [ + "guilds" + ] + } + }, + "/guilds/{guild_id}/vanity-url/": { + "get": { + "description": "##### Requires the ``MANAGE_GUILD`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": [ + "guilds" + ] + }, + "patch": { + "description": "##### Requires the ``MANAGE_GUILD`` permission\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/VanityUrlSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": [ + "guilds" + ] + } + }, + "/guilds/{guild_id}/templates/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": [ + "guilds" + ] + }, + "post": { + "description": "##### Requires the ``MANAGE_GUILD`` permission\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TemplateCreateSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": [ + "guilds" + ] + } + }, + "/guilds/{guild_id}/templates/{code}": { + "delete": { + "description": "##### Requires the ``MANAGE_GUILD`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + }, + { + "name": "code", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "code" + } + ], + "tags": [ + "guilds" + ] + }, + "put": { + "description": "##### Requires the ``MANAGE_GUILD`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + }, + { + "name": "code", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "code" + } + ], + "tags": [ + "guilds" + ] + }, + "patch": { + "description": "##### Requires the ``MANAGE_GUILD`` permission\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TemplateModifySchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + }, + { + "name": "code", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "code" + } + ], + "tags": [ + "guilds" + ] + } + }, + "/guilds/{guild_id}/roles/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": [ + "guilds" + ] + }, + "post": { + "description": "##### Requires the ``MANAGE_ROLES`` permission\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RoleModifySchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": [ + "guilds" + ] + }, + "patch": { + "description": "", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RolePositionUpdateSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": [ + "guilds" + ] + } + }, + "/guilds/{guild_id}/roles/{role_id}": { + "delete": { + "description": "##### Requires the ``MANAGE_ROLES`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + }, + { + "name": "role_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "role_id" + } + ], + "tags": [ + "guilds" + ] + }, + "patch": { + "description": "##### Requires the ``MANAGE_ROLES`` permission\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RoleModifySchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + }, + { + "name": "role_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "role_id" + } + ], + "tags": [ + "guilds" + ] + } + }, + "/guilds/{guild_id}/regions/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": [ + "guilds" + ] + } + }, + "/guilds/{guild_id}/members/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": [ + "guilds" + ] + } + }, + "/guilds/{guild_id}/members/{member_id}/nick/": { + "patch": { + "description": "", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MemberNickChangeSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + }, + { + "name": "member_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "member_id" + } + ], + "tags": [ + "guilds" + ] + } + }, + "/guilds/{guild_id}/members/{member_id}/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + }, + { + "name": "member_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "member_id" + } + ], + "tags": [ + "guilds" + ] + }, + "patch": { + "description": "", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MemberChangeSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + }, + { + "name": "member_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "member_id" + } + ], + "tags": [ + "guilds" + ] + }, + "put": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + }, + { + "name": "member_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "member_id" + } + ], + "tags": [ + "guilds" + ] + }, + "delete": { + "description": "##### Requires the ``KICK_MEMBERS`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + }, + { + "name": "member_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "member_id" + } + ], + "tags": [ + "guilds" + ] + } + }, + "/guilds/{guild_id}/invites/": { + "get": { + "description": "##### Requires the ``MANAGE_GUILD`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": [ + "guilds" + ] + } + }, + "/guilds/{guild_id}/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": [ + "guilds" + ] + }, + "patch": { + "description": "##### Requires the ``MANAGE_GUILD`` permission\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GuildUpdateSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": [ + "guilds" + ] + } + }, + "/guilds/{guild_id}/delete/": { + "post": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": [ + "guilds" + ] + } + }, + "/guilds/{guild_id}/channels/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": [ + "guilds" + ] + }, + "post": { + "description": "##### Requires the ``MANAGE_CHANNELS`` permission\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChannelModifySchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": [ + "guilds" + ] + }, + "patch": { + "description": "##### Requires the ``MANAGE_CHANNELS`` permission\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChannelReorderSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": [ + "guilds" + ] + } + }, + "/guilds/{guild_id}/bans/": { + "get": { + "description": "##### Requires the ``BAN_MEMBERS`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + } + ], + "tags": [ + "guilds" + ] + } + }, + "/guilds/{guild_id}/bans/{user}": { + "get": { + "description": "##### Requires the ``BAN_MEMBERS`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + }, + { + "name": "user", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "user" + } + ], + "tags": [ + "guilds" + ] + } + }, + "/guilds/{guild_id}/bans/{user_id}": { + "put": { + "description": "##### Requires the ``BAN_MEMBERS`` permission\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BanCreateSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + }, + { + "name": "user_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "user_id" + } + ], + "tags": [ + "guilds" + ] + }, + "delete": { + "description": "##### Requires the ``BAN_MEMBERS`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + }, + { + "name": "user_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "user_id" + } + ], + "tags": [ + "guilds" + ] + } + }, + "/gateway/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": [ + "gateway" + ] + } + }, + "/gateway/bot": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": [ + "gateway" + ] + } + }, + "/experiments/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": [ + "experiments" + ] + } + }, + "/discoverable-guilds/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": [ + "discoverable", + "discoverable-guilds" + ] + } + }, + "/channels/{channel_id}/webhooks/": { + "post": { + "description": "##### Requires the ``MANAGE_WEBHOOKS`` permission\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WebhookCreateSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + } + ], + "tags": [ + "channels" + ] + } + }, + "/channels/{channel_id}/typing/": { + "post": { + "description": "##### Requires the ``SEND_MESSAGES`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + } + ], + "tags": [ + "channels" + ] + } + }, + "/channels/{channel_id}/recipients/{user_id}": { + "put": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + }, + { + "name": "user_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "user_id" + } + ], + "tags": [ + "channels" + ] + }, + "delete": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + }, + { + "name": "user_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "user_id" + } + ], + "tags": [ + "channels" + ] + } + }, + "/channels/{channel_id}/pins/{message_id}": { + "put": { + "description": "##### Requires the ``VIEW_CHANNEL`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + }, + { + "name": "message_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "message_id" + } + ], + "tags": [ + "channels" + ] + }, + "delete": { + "description": "##### Requires the ``VIEW_CHANNEL`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + }, + { + "name": "message_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "message_id" + } + ], + "tags": [ + "channels" + ] + } + }, + "/channels/{channel_id}/pins/": { + "get": { + "description": "##### Requires the ``READ_MESSAGE_HISTORY`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + } + ], + "tags": [ + "channels" + ] + } + }, + "/channels/{channel_id}/permissions/{overwrite_id}": { + "put": { + "description": "##### Requires the ``MANAGE_ROLES`` permission\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChannelPermissionOverwriteSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + }, + { + "name": "overwrite_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "overwrite_id" + } + ], + "tags": [ + "channels" + ] + }, + "delete": { + "description": "##### Requires the ``MANAGE_ROLES`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + }, + { + "name": "overwrite_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "overwrite_id" + } + ], + "tags": [ + "channels" + ] + } + }, + "/channels/{channel_id}/messages/bulk-delete/": { + "post": { + "description": "", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BulkDeleteSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + } + ], + "tags": [ + "channels" + ] + } + }, + "/channels/{channel_id}/messages/{message_id}/reactions/": { + "delete": { + "description": "##### Requires the ``MANAGE_MESSAGES`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + }, + { + "name": "message_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "message_id" + } + ], + "tags": [ + "channels" + ] + } + }, + "/channels/{channel_id}/messages/{message_id}/reactions/{emoji}": { + "delete": { + "description": "##### Requires the ``MANAGE_MESSAGES`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + }, + { + "name": "message_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "message_id" + }, + { + "name": "emoji", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "emoji" + } + ], + "tags": [ + "channels" + ] + }, + "get": { + "description": "##### Requires the ``VIEW_CHANNEL`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + }, + { + "name": "message_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "message_id" + }, + { + "name": "emoji", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "emoji" + } + ], + "tags": [ + "channels" + ] + } + }, + "/channels/{channel_id}/messages/{message_id}/reactions/{emoji}/{user_id}": { + "put": { + "description": "##### Requires the ``READ_MESSAGE_HISTORY`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + }, + { + "name": "message_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "message_id" + }, + { + "name": "emoji", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "emoji" + }, + { + "name": "user_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "user_id" + } + ], + "tags": [ + "channels" + ] + }, + "delete": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + }, + { + "name": "message_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "message_id" + }, + { + "name": "emoji", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "emoji" + }, + { + "name": "user_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "user_id" + } + ], + "tags": [ + "channels" + ] + } + }, + "/channels/{channel_id}/messages/{message_id}/": { + "patch": { + "description": "##### Requires the ``SEND_MESSAGES`` permission\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MessageCreateSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + }, + { + "name": "message_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "message_id" + } + ], + "tags": [ + "channels" + ] + }, + "delete": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + }, + { + "name": "message_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "message_id" + } + ], + "tags": [ + "channels" + ] + } + }, + "/channels/{channel_id}/messages/{message_id}/ack/": { + "post": { + "description": "", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MessageAcknowledgeSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + }, + { + "name": "message_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "message_id" + } + ], + "tags": [ + "channels" + ] + } + }, + "/channels/{channel_id}/invites/": { + "post": { + "description": "##### Requires the ``CREATE_INSTANT_INVITE`` permission\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InviteCreateSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + } + ], + "tags": [ + "channels" + ] + }, + "get": { + "description": "##### Requires the ``MANAGE_CHANNELS`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + } + ], + "tags": [ + "channels" + ] + } + }, + "/channels/{channel_id}/": { + "get": { + "description": "##### Requires the ``VIEW_CHANNEL`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + } + ], + "tags": [ + "channels" + ] + }, + "delete": { + "description": "##### Requires the ``MANAGE_CHANNELS`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + } + ], + "tags": [ + "channels" + ] + }, + "patch": { + "description": "##### Requires the ``MANAGE_CHANNELS`` permission\n", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChannelModifySchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "channel_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "channel_id" + } + ], + "tags": [ + "channels" + ] + } + }, + "/auth/register/": { + "post": { + "description": "", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RegisterSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": [ + "auth" + ] + } + }, + "/applications/detectable/": { + "get": { + "description": "", + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": [ + "applications" + ] + } + }, + "/guilds/{guild_id}/members/{member_id}/roles/{role_id}/": { + "delete": { + "description": "##### Requires the ``MANAGE_ROLES`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + }, + { + "name": "member_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "member_id" + }, + { + "name": "role_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "role_id" + } + ], + "tags": [ + "guilds" + ] + }, + "put": { + "description": "##### Requires the ``MANAGE_ROLES`` permission\n", + "responses": { + "default": { + "description": "not documented" + } + }, + "parameters": [ + { + "name": "guild_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "guild_id" + }, + { + "name": "member_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "member_id" + }, + { + "name": "role_id", + "in": "path", + "required": true, + "schema": { + "type": "string" + }, + "description": "role_id" + } + ], + "tags": [ + "guilds" + ] + } + }, + "/auth/login/": { + "post": { + "description": "", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LoginSchema" + } + } + } + }, + "responses": { + "default": { + "description": "not documented" + } + }, + "tags": [ + "auth" + ] + } + } + }, + "externalDocs": { + "url": "http://docs.fosscord.com/" + }, + "components": { + "schemas": { + "Error": { + "type": "object", + "properties": { + "code": { + "type": "integer" + }, + "message": { + "type": "string" + } + }, + "required": [ + "code", + "message" + ] + }, + "RateLimit": { + "type": "object", + "properties": { + "retry_after": { + "type": "integer" + }, + "message": { + "type": "string" + }, + "global": { + "type": "boolean" + } + }, + "required": [ + "code", + "message", + "globa" + ] + }, + "User": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "discriminator": { + "type": "string" + }, + "avatar": { + "type": "string" + }, + "accent_color": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "desktop": { + "type": "boolean" + }, + "mobile": { + "type": "boolean" + }, + "premium": { + "type": "boolean" + }, + "premium_type": { + "type": "integer" + }, + "bot": { + "type": "boolean" + }, + "bio": { + "type": "string" + }, + "system": { + "type": "boolean" + }, + "nsfw_allowed": { + "type": "boolean" + }, + "mfa_enabled": { + "type": "boolean" + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "verified": { + "type": "boolean" + }, + "disabled": { + "type": "boolean" + }, + "deleted": { + "type": "boolean" + }, + "email": { + "type": "string" + }, + "flags": { + "type": "string" + }, + "public_flags": { + "type": "string" + }, + "relationships": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Relationship" + } + }, + "connected_accounts": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ConnectedAccount" + } + }, + "data": { + "type": "object", + "properties": { + "valid_tokens_since": { + "type": "string", + "format": "date-time" + }, + "hash": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "valid_tokens_since" + ] + }, + "fingerprints": { + "type": "array", + "items": { + "type": "string" + } + }, + "settings": { + "$ref": "#/components/schemas/UserSettings" + }, + "id": { + "type": "string" + } + }, + "required": [ + "bio", + "bot", + "connected_accounts", + "created_at", + "data", + "deleted", + "desktop", + "disabled", + "discriminator", + "fingerprints", + "flags", + "id", + "mfa_enabled", + "mobile", + "nsfw_allowed", + "premium", + "premium_type", + "public_flags", + "relationships", + "settings", + "system", + "username", + "verified" + ] + }, + "Relationship": { + "type": "object", + "properties": { + "user_id": { + "type": "string" + }, + "user": { + "$ref": "#/components/schemas/User" + }, + "nickname": { + "type": "string" + }, + "type": { + "$ref": "#/components/schemas/RelationshipType" + }, + "id": { + "type": "string" + } + }, + "required": [ + "id", + "type", + "user", + "user_id" + ] + }, + "RelationshipType": { + "enum": [ + 1, + 2, + 3, + 4 + ], + "type": "number" + }, + "ConnectedAccount": { + "type": "object", + "properties": { + "user_id": { + "type": "string" + }, + "user": { + "$ref": "#/components/schemas/User" + }, + "access_token": { + "type": "string" + }, + "friend_sync": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "revoked": { + "type": "boolean" + }, + "show_activity": { + "type": "boolean" + }, + "type": { + "type": "string" + }, + "verifie": { + "type": "boolean" + }, + "visibility": { + "type": "integer" + }, + "id": { + "type": "string" + } + }, + "required": [ + "access_token", + "friend_sync", + "id", + "name", + "revoked", + "show_activity", + "type", + "user", + "user_id", + "verifie", + "visibility" + ] + }, + "UserSettings": { + "type": "object", + "properties": { + "afk_timeout": { + "type": "integer" + }, + "allow_accessibility_detection": { + "type": "boolean" + }, + "animate_emoji": { + "type": "boolean" + }, + "animate_stickers": { + "type": "integer" + }, + "contact_sync_enabled": { + "type": "boolean" + }, + "convert_emoticons": { + "type": "boolean" + }, + "custom_status": { + "type": "object", + "properties": { + "emoji_id": { + "type": "string" + }, + "emoji_name": { + "type": "string" + }, + "expires_at": { + "type": "integer" + }, + "text": { + "type": "string" + } + }, + "additionalProperties": false + }, + "default_guilds_restricted": { + "type": "boolean" + }, + "detect_platform_accounts": { + "type": "boolean" + }, + "developer_mode": { + "type": "boolean" + }, + "disable_games_tab": { + "type": "boolean" + }, + "enable_tts_command": { + "type": "boolean" + }, + "explicit_content_filter": { + "type": "integer" + }, + "friend_source_flags": { + "type": "object", + "properties": { + "all": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "all" + ] + }, + "gateway_connected": { + "type": "boolean" + }, + "gif_auto_play": { + "type": "boolean" + }, + "guild_folders": { + "type": "array", + "items": { + "type": "object", + "properties": { + "color": { + "type": "integer" + }, + "guild_ids": { + "type": "array", + "items": { + "type": "string" + } + }, + "id": { + "type": "integer" + }, + "name": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "color", + "guild_ids", + "id", + "name" + ] + } + }, + "guild_positions": { + "type": "array", + "items": { + "type": "string" + } + }, + "inline_attachment_media": { + "type": "boolean" + }, + "inline_embed_media": { + "type": "boolean" + }, + "locale": { + "type": "string" + }, + "message_display_compact": { + "type": "boolean" + }, + "native_phone_integration_enabled": { + "type": "boolean" + }, + "render_embeds": { + "type": "boolean" + }, + "render_reactions": { + "type": "boolean" + }, + "restricted_guilds": { + "type": "array", + "items": { + "type": "string" + } + }, + "show_current_game": { + "type": "boolean" + }, + "status": { + "enum": [ + "dnd", + "idle", + "offline", + "online" + ], + "type": "string" + }, + "stream_notifications_enabled": { + "type": "boolean" + }, + "theme": { + "enum": [ + "dark", + "white" + ], + "type": "string" + }, + "timezone_offset": { + "type": "integer" + } + }, + "required": [ + "afk_timeout", + "allow_accessibility_detection", + "animate_emoji", + "animate_stickers", + "contact_sync_enabled", + "convert_emoticons", + "custom_status", + "default_guilds_restricted", + "detect_platform_accounts", + "developer_mode", + "disable_games_tab", + "enable_tts_command", + "explicit_content_filter", + "friend_source_flags", + "gateway_connected", + "gif_auto_play", + "guild_folders", + "guild_positions", + "inline_attachment_media", + "inline_embed_media", + "locale", + "message_display_compact", + "native_phone_integration_enabled", + "render_embeds", + "render_reactions", + "restricted_guilds", + "show_current_game", + "status", + "stream_notifications_enabled", + "theme", + "timezone_offset" + ] + }, + "Team": { + "type": "object", + "properties": { + "icon": { + "type": "string" + }, + "members": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TeamMember" + } + }, + "name": { + "type": "string" + }, + "owner_user_id": { + "type": "string" + }, + "owner_user": { + "$ref": "#/components/schemas/User" + }, + "id": { + "type": "string" + } + }, + "required": [ + "id", + "members", + "name", + "owner_user", + "owner_user_id" + ] + }, + "TeamMember": { + "type": "object", + "properties": { + "membership_state": { + "$ref": "#/components/schemas/TeamMemberState" + }, + "permissions": { + "type": "array", + "items": { + "type": "string" + } + }, + "team_id": { + "type": "string" + }, + "team": { + "$ref": "#/components/schemas/Team" + }, + "user_id": { + "type": "string" + }, + "user": { + "$ref": "#/components/schemas/User" + }, + "id": { + "type": "string" + } + }, + "required": [ + "id", + "membership_state", + "permissions", + "team", + "team_id", + "user", + "user_id" + ] + }, + "TeamMemberState": { + "enum": [ + 1, + 2 + ], + "type": "number" + }, + "Guild": { + "type": "object", + "properties": { + "afk_channel_id": { + "type": "string" + }, + "afk_channel": { + "$ref": "#/components/schemas/Channel" + }, + "afk_timeout": { + "type": "integer" + }, + "bans": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Ban" + } + }, + "banner": { + "type": "string" + }, + "default_message_notifications": { + "type": "integer" + }, + "description": { + "type": "string" + }, + "discovery_splash": { + "type": "string" + }, + "explicit_content_filter": { + "type": "integer" + }, + "features": { + "type": "array", + "items": { + "type": "string" + } + }, + "icon": { + "type": "string" + }, + "large": { + "type": "boolean" + }, + "max_members": { + "type": "integer" + }, + "max_presences": { + "type": "integer" + }, + "max_video_channel_users": { + "type": "integer" + }, + "member_count": { + "type": "integer" + }, + "presence_count": { + "type": "integer" + }, + "members": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Member" + } + }, + "roles": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Role" + } + }, + "channels": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Channel" + } + }, + "template_id": { + "type": "string" + }, + "template": { + "$ref": "#/components/schemas/Template" + }, + "emojis": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Emoji" + } + }, + "stickers": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Sticker" + } + }, + "invites": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Invite" + } + }, + "voice_states": { + "type": "array", + "items": { + "$ref": "#/components/schemas/VoiceState" + } + }, + "webhooks": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Webhook" + } + }, + "mfa_level": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "owner_id": { + "type": "string" + }, + "owner": { + "$ref": "#/components/schemas/User" + }, + "preferred_locale": { + "type": "string" + }, + "premium_subscription_count": { + "type": "integer" + }, + "premium_tier": { + "type": "integer" + }, + "public_updates_channel_id": { + "type": "string" + }, + "public_updates_channel": { + "$ref": "#/components/schemas/Channel" + }, + "rules_channel_id": { + "type": "string" + }, + "rules_channel": { + "type": "string" + }, + "region": { + "type": "string" + }, + "splash": { + "type": "string" + }, + "system_channel_id": { + "type": "string" + }, + "system_channel": { + "$ref": "#/components/schemas/Channel" + }, + "system_channel_flags": { + "type": "integer" + }, + "unavailable": { + "type": "boolean" + }, + "vanity_url_code": { + "type": "string" + }, + "vanity_url": { + "$ref": "#/components/schemas/Invite" + }, + "verification_level": { + "type": "integer" + }, + "welcome_screen": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "description": { + "type": "string" + }, + "welcome_channels": { + "type": "array", + "items": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "emoji_id": { + "type": "string" + }, + "emoji_name": { + "type": "string" + }, + "channel_id": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "channel_id", + "description", + "emoji_name" + ] + } + } + }, + "additionalProperties": false, + "required": [ + "description", + "enabled", + "welcome_channels" + ] + }, + "widget_channel_id": { + "type": "string" + }, + "widget_channel": { + "$ref": "#/components/schemas/Channel" + }, + "widget_enabled": { + "type": "boolean" + }, + "id": { + "type": "string" + } + }, + "required": [ + "bans", + "channels", + "emojis", + "features", + "id", + "invites", + "members", + "name", + "owner", + "owner_id", + "public_updates_channel_id", + "roles", + "stickers", + "template", + "template_id", + "voice_states", + "webhooks", + "welcome_screen" + ] + }, + "Channel": { + "type": "object", + "properties": { + "created_at": { + "type": "string", + "format": "date-time" + }, + "name": { + "type": "string" + }, + "type": { + "$ref": "#/components/schemas/ChannelType" + }, + "recipients": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Recipient" + } + }, + "last_message_id": { + "type": "string" + }, + "last_message": { + "$ref": "#/components/schemas/Message" + }, + "guild_id": { + "type": "string" + }, + "guild": { + "$ref": "#/components/schemas/Guild" + }, + "parent_id": { + "type": "string" + }, + "parent": { + "$ref": "#/components/schemas/Channel" + }, + "owner_id": { + "type": "string" + }, + "owner": { + "$ref": "#/components/schemas/User" + }, + "last_pin_timestamp": { + "type": "integer" + }, + "default_auto_archive_duration": { + "type": "integer" + }, + "position": { + "type": "integer" + }, + "permission_overwrites": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ChannelPermissionOverwrite" + } + }, + "video_quality_mode": { + "type": "integer" + }, + "bitrate": { + "type": "integer" + }, + "user_limit": { + "type": "integer" + }, + "nsfw": { + "type": "boolean" + }, + "rate_limit_per_user": { + "type": "integer" + }, + "topic": { + "type": "string" + }, + "id": { + "type": "string" + } + }, + "required": [ + "created_at", + "guild", + "id", + "last_message_id", + "name", + "owner", + "owner_id", + "parent_id", + "permission_overwrites", + "position", + "type" + ] + }, + "ChannelType": { + "enum": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ], + "type": "number" + }, + "Recipient": { + "type": "object", + "properties": { + "channel_id": { + "type": "string" + }, + "channel": { + "$ref": "#/components/schemas/Channel" + }, + "user": { + "$ref": "#/components/schemas/User" + }, + "id": { + "type": "string" + } + }, + "required": [ + "channel", + "channel_id", + "id", + "user" + ] + }, + "Message": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "channel_id": { + "type": "string" + }, + "channel": { + "$ref": "#/components/schemas/Channel" + }, + "guild_id": { + "type": "string" + }, + "guild": { + "$ref": "#/components/schemas/Guild" + }, + "author_id": { + "type": "string" + }, + "author": { + "$ref": "#/components/schemas/User" + }, + "member_id": { + "type": "string" + }, + "member": { + "$ref": "#/components/schemas/Member" + }, + "webhook_id": { + "type": "string" + }, + "webhook": { + "$ref": "#/components/schemas/Webhook" + }, + "application_id": { + "type": "string" + }, + "application": { + "$ref": "#/components/schemas/Application" + }, + "content": { + "type": "string" + }, + "timestamp": { + "type": "string", + "format": "date-time" + }, + "edited_timestamp": { + "type": "string", + "format": "date-time" + }, + "tts": { + "type": "boolean" + }, + "mention_everyone": { + "type": "boolean" + }, + "mentions": { + "type": "array", + "items": { + "$ref": "#/components/schemas/User" + } + }, + "mention_roles": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Role" + } + }, + "mention_channels": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Channel" + } + }, + "sticker_items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Sticker" + } + }, + "attachments": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Attachment" + } + }, + "embeds": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Embed" + } + }, + "reactions": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Reaction" + } + }, + "nonce": { + "type": "string" + }, + "pinned": { + "type": "boolean" + }, + "type": { + "$ref": "#/components/schemas/MessageType" + }, + "activity": { + "type": "object", + "properties": { + "type": { + "type": "integer" + }, + "party_id": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "party_id", + "type" + ] + }, + "flags": { + "type": "string" + }, + "message_reference": { + "type": "object", + "properties": { + "message_id": { + "type": "string" + }, + "channel_id": { + "type": "string" + }, + "guild_id": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "message_id" + ] + }, + "referenced_message": { + "$ref": "#/components/schemas/Message" + }, + "interaction": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "$ref": "#/components/schemas/InteractionType" + }, + "name": { + "type": "string" + }, + "user_id": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "id", + "name", + "type", + "user_id" + ] + }, + "components": { + "type": "array", + "items": { + "$ref": "#/components/schemas/MessageComponent" + } + } + }, + "required": [ + "application_id", + "author_id", + "channel", + "channel_id", + "embeds", + "id", + "member_id", + "mention_channels", + "mention_roles", + "mentions", + "reactions", + "timestamp", + "type", + "webhook_id" + ] + }, + "Member": { + "type": "object", + "properties": { + "user_id": { + "type": "string" + }, + "user": { + "$ref": "#/components/schemas/User" + }, + "guild_id": { + "type": "string" + }, + "guild": { + "$ref": "#/components/schemas/Guild" + }, + "nick": { + "type": "string" + }, + "roles": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Role" + } + }, + "joined_at": { + "type": "string", + "format": "date-time" + }, + "premium_since": { + "type": "integer" + }, + "deaf": { + "type": "boolean" + }, + "mute": { + "type": "boolean" + }, + "pending": { + "type": "boolean" + }, + "settings": { + "$ref": "#/components/schemas/UserGuildSettings" + }, + "id": { + "type": "string" + } + }, + "required": [ + "deaf", + "guild", + "guild_id", + "id", + "joined_at", + "mute", + "pending", + "roles", + "settings", + "user", + "user_id" + ] + }, + "Role": { + "type": "object", + "properties": { + "guild_id": { + "type": "string" + }, + "guild": { + "$ref": "#/components/schemas/Guild" + }, + "color": { + "type": "integer" + }, + "hoist": { + "type": "boolean" + }, + "managed": { + "type": "boolean" + }, + "mentionable": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "permissions": { + "type": "string" + }, + "position": { + "type": "integer" + }, + "tags": { + "type": "object", + "properties": { + "bot_id": { + "type": "string" + }, + "integration_id": { + "type": "string" + }, + "premium_subscriber": { + "type": "boolean" + } + }, + "additionalProperties": false + }, + "id": { + "type": "string" + } + }, + "required": [ + "color", + "guild", + "guild_id", + "hoist", + "id", + "managed", + "mentionable", + "name", + "permissions", + "position" + ] + }, + "UserGuildSettings": { + "type": "object", + "properties": { + "channel_overrides": { + "type": "array", + "items": { + "type": "object", + "properties": { + "channel_id": { + "type": "string" + }, + "message_notifications": { + "type": "integer" + }, + "mute_config": { + "$ref": "#/components/schemas/MuteConfig" + }, + "muted": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "channel_id", + "message_notifications", + "mute_config", + "muted" + ] + } + }, + "message_notifications": { + "type": "integer" + }, + "mobile_push": { + "type": "boolean" + }, + "mute_config": { + "$ref": "#/components/schemas/MuteConfig" + }, + "muted": { + "type": "boolean" + }, + "suppress_everyone": { + "type": "boolean" + }, + "suppress_roles": { + "type": "boolean" + }, + "version": { + "type": "integer" + } + }, + "required": [ + "channel_overrides", + "message_notifications", + "mobile_push", + "mute_config", + "muted", + "suppress_everyone", + "suppress_roles", + "version" + ] + }, + "MuteConfig": { + "type": "object", + "properties": { + "end_time": { + "type": "integer" + }, + "selected_time_window": { + "type": "integer" + } + }, + "required": [ + "end_time", + "selected_time_window" + ] + }, + "Webhook": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "$ref": "#/components/schemas/WebhookType" + }, + "name": { + "type": "string" + }, + "avatar": { + "type": "string" + }, + "token": { + "type": "string" + }, + "guild_id": { + "type": "string" + }, + "guild": { + "$ref": "#/components/schemas/Guild" + }, + "channel_id": { + "type": "string" + }, + "channel": { + "$ref": "#/components/schemas/Channel" + }, + "application_id": { + "type": "string" + }, + "application": { + "$ref": "#/components/schemas/Application" + }, + "user_id": { + "type": "string" + }, + "user": { + "$ref": "#/components/schemas/User" + }, + "source_guild_id": { + "type": "string" + }, + "source_guild": { + "$ref": "#/components/schemas/Guild" + } + }, + "required": [ + "application", + "application_id", + "channel", + "channel_id", + "guild", + "guild_id", + "id", + "source_guild", + "source_guild_id", + "type", + "user", + "user_id" + ] + }, + "WebhookType": { + "enum": [ + 1, + 2 + ], + "type": "number" + }, + "Application": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "icon": { + "type": "string" + }, + "description": { + "type": "string" + }, + "rpc_origins": { + "type": "array", + "items": { + "type": "string" + } + }, + "bot_public": { + "type": "boolean" + }, + "bot_require_code_grant": { + "type": "boolean" + }, + "terms_of_service_url": { + "type": "string" + }, + "privacy_policy_url": { + "type": "string" + }, + "owner": { + "$ref": "#/components/schemas/User" + }, + "summary": { + "type": "string" + }, + "verify_key": { + "type": "string" + }, + "team": { + "$ref": "#/components/schemas/Team" + }, + "guild": { + "$ref": "#/components/schemas/Guild" + }, + "primary_sku_id": { + "type": "string" + }, + "slug": { + "type": "string" + }, + "cover_image": { + "type": "string" + }, + "flags": { + "type": "string" + }, + "id": { + "type": "string" + } + }, + "required": [ + "bot_public", + "bot_require_code_grant", + "description", + "flags", + "guild", + "id", + "name", + "verify_key" + ] + }, + "Sticker": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "tags": { + "type": "string" + }, + "pack_id": { + "type": "string" + }, + "guild_id": { + "type": "string" + }, + "guild": { + "$ref": "#/components/schemas/Guild" + }, + "type": { + "$ref": "#/components/schemas/StickerType" + }, + "format_type": { + "$ref": "#/components/schemas/StickerFormatType" + }, + "id": { + "type": "string" + } + }, + "required": [ + "format_type", + "id", + "name", + "pack_id", + "tags", + "type" + ] + }, + "StickerType": { + "enum": [ + 1, + 2 + ], + "type": "number" + }, + "StickerFormatType": { + "enum": [ + 1, + 2, + 3 + ], + "type": "number" + }, + "Attachment": { + "type": "object", + "properties": { + "filename": { + "type": "string" + }, + "size": { + "type": "integer" + }, + "url": { + "type": "string" + }, + "proxy_url": { + "type": "string" + }, + "height": { + "type": "integer" + }, + "width": { + "type": "integer" + }, + "content_type": { + "type": "string" + }, + "message_id": { + "type": "string" + }, + "message": { + "$ref": "#/components/schemas/Message" + }, + "id": { + "type": "string" + } + }, + "required": [ + "filename", + "id", + "message", + "message_id", + "proxy_url", + "size", + "url" + ] + }, + "Embed": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "type": { + "enum": [ + "article", + "gifv", + "image", + "link", + "rich", + "video" + ], + "type": "string" + }, + "description": { + "type": "string" + }, + "url": { + "type": "string" + }, + "timestamp": { + "type": "string", + "format": "date-time" + }, + "color": { + "type": "integer" + }, + "footer": { + "type": "object", + "properties": { + "text": { + "type": "string" + }, + "icon_url": { + "type": "string" + }, + "proxy_icon_url": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "text" + ] + }, + "image": { + "$ref": "#/components/schemas/EmbedImage" + }, + "thumbnail": { + "$ref": "#/components/schemas/EmbedImage" + }, + "video": { + "$ref": "#/components/schemas/EmbedImage" + }, + "provider": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "additionalProperties": false + }, + "author": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "url": { + "type": "string" + }, + "icon_url": { + "type": "string" + }, + "proxy_icon_url": { + "type": "string" + } + }, + "additionalProperties": false + }, + "fields": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "value": { + "type": "string" + }, + "inline": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "name", + "value" + ] + } + } + } + }, + "EmbedType": { + "enum": [ + "article", + "gifv", + "image", + "link", + "rich", + "video" + ], + "type": "string" + }, + "EmbedImage": { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "proxy_url": { + "type": "string" + }, + "height": { + "type": "integer" + }, + "width": { + "type": "integer" + } + } + }, + "Reaction": { + "type": "object", + "properties": { + "count": { + "type": "integer" + }, + "emoji": { + "$ref": "#/components/schemas/PartialEmoji" + }, + "user_ids": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "count", + "emoji", + "user_ids" + ] + }, + "PartialEmoji": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "animated": { + "type": "boolean" + } + }, + "required": [ + "name" + ] + }, + "MessageType": { + "enum": [ + 0, + 1, + 10, + 11, + 12, + 14, + 15, + 19, + 2, + 20, + 3, + 4, + 5, + 6, + 7, + 8, + 9 + ], + "type": "number" + }, + "InteractionType": { + "enum": [ + 1, + 2 + ], + "type": "number" + }, + "MessageComponent": { + "type": "object", + "properties": { + "type": { + "type": "integer" + }, + "style": { + "type": "integer" + }, + "label": { + "type": "string" + }, + "emoji": { + "$ref": "#/components/schemas/PartialEmoji" + }, + "custom_id": { + "type": "string" + }, + "url": { + "type": "string" + }, + "disabled": { + "type": "boolean" + }, + "components": { + "type": "array", + "items": { + "$ref": "#/components/schemas/MessageComponent" + } + } + }, + "required": [ + "components", + "type" + ] + }, + "ChannelPermissionOverwrite": { + "type": "object", + "properties": { + "allow": { + "type": "number" + }, + "deny": { + "type": "number" + }, + "id": { + "type": "string" + }, + "type": { + "$ref": "#/components/schemas/ChannelPermissionOverwriteType" + } + }, + "required": [ + "allow", + "deny", + "id", + "type" + ] + }, + "ChannelPermissionOverwriteType": { + "enum": [ + 0, + 1 + ], + "type": "number" + }, + "Ban": { + "type": "object", + "properties": { + "user_id": { + "type": "string" + }, + "user": { + "$ref": "#/components/schemas/User" + }, + "guild_id": { + "type": "string" + }, + "guild": { + "$ref": "#/components/schemas/Guild" + }, + "executor_id": { + "type": "string" + }, + "executor": { + "$ref": "#/components/schemas/User" + }, + "ip": { + "type": "string" + }, + "reason": { + "type": "string" + }, + "id": { + "type": "string" + } + }, + "required": [ + "executor", + "executor_id", + "guild", + "guild_id", + "id", + "ip", + "user", + "user_id" + ] + }, + "Template": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "usage_count": { + "type": "integer" + }, + "creator_id": { + "type": "string" + }, + "creator": { + "$ref": "#/components/schemas/User" + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "updated_at": { + "type": "string", + "format": "date-time" + }, + "source_guild_id": { + "type": "string" + }, + "source_guild": { + "$ref": "#/components/schemas/Guild" + }, + "serialized_source_guild": { + "$ref": "#/components/schemas/Guild" + }, + "id": { + "type": "string" + } + }, + "required": [ + "code", + "created_at", + "creator", + "creator_id", + "id", + "name", + "serialized_source_guild", + "source_guild", + "source_guild_id", + "updated_at" + ] + }, + "Emoji": { + "type": "object", + "properties": { + "animated": { + "type": "boolean" + }, + "available": { + "type": "boolean" + }, + "guild_id": { + "type": "string" + }, + "guild": { + "$ref": "#/components/schemas/Guild" + }, + "managed": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "require_colons": { + "type": "boolean" + }, + "id": { + "type": "string" + } + }, + "required": [ + "animated", + "available", + "guild", + "guild_id", + "id", + "managed", + "name", + "require_colons" + ] + }, + "Invite": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "temporary": { + "type": "boolean" + }, + "uses": { + "type": "integer" + }, + "max_uses": { + "type": "integer" + }, + "max_age": { + "type": "integer" + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "expires_at": { + "type": "string", + "format": "date-time" + }, + "guild_id": { + "type": "string" + }, + "guild": { + "$ref": "#/components/schemas/Guild" + }, + "channel_id": { + "type": "string" + }, + "channel": { + "$ref": "#/components/schemas/Channel" + }, + "inviter_id": { + "type": "string" + }, + "inviter": { + "$ref": "#/components/schemas/User" + }, + "target_user_id": { + "type": "string" + }, + "target_user": { + "type": "string" + }, + "target_user_type": { + "type": "integer" + }, + "id": { + "type": "string" + } + }, + "required": [ + "channel", + "channel_id", + "code", + "created_at", + "expires_at", + "guild", + "guild_id", + "id", + "inviter", + "inviter_id", + "max_age", + "max_uses", + "target_user_id", + "temporary", + "uses" + ] + }, + "VoiceState": { + "type": "object", + "properties": { + "guild_id": { + "type": "string" + }, + "guild": { + "$ref": "#/components/schemas/Guild" + }, + "channel_id": { + "type": "string" + }, + "channel": { + "$ref": "#/components/schemas/Channel" + }, + "user_id": { + "type": "string" + }, + "user": { + "$ref": "#/components/schemas/User" + }, + "session_id": { + "type": "string" + }, + "deaf": { + "type": "boolean" + }, + "mute": { + "type": "boolean" + }, + "self_deaf": { + "type": "boolean" + }, + "self_mute": { + "type": "boolean" + }, + "self_stream": { + "type": "boolean" + }, + "self_video": { + "type": "boolean" + }, + "suppress": { + "type": "boolean" + }, + "id": { + "type": "string" + } + }, + "required": [ + "channel", + "channel_id", + "deaf", + "guild_id", + "id", + "mute", + "self_deaf", + "self_mute", + "self_video", + "session_id", + "suppress", + "user", + "user_id" + ] + }, + "AuditLogEvents": { + "enum": [ + 1, + 10, + 11, + 12, + 13, + 14, + 15, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 30, + 31, + 32, + 40, + 41, + 42, + 50, + 51, + 52, + 60, + 61, + 62, + 72, + 73, + 74, + 75, + 80, + 81, + 82 + ], + "type": "number" + }, + "AuditLogChange": { + "type": "object", + "properties": { + "new_value": { + "$ref": "#/components/schemas/AuditLogChangeValue" + }, + "old_value": { + "$ref": "#/components/schemas/AuditLogChangeValue" + }, + "key": { + "type": "string" + } + }, + "required": [ + "key" + ] + }, + "AuditLogChangeValue": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "icon_hash": { + "type": "string" + }, + "splash_hash": { + "type": "string" + }, + "discovery_splash_hash": { + "type": "string" + }, + "banner_hash": { + "type": "string" + }, + "owner_id": { + "type": "string" + }, + "region": { + "type": "string" + }, + "preferred_locale": { + "type": "string" + }, + "afk_channel_id": { + "type": "string" + }, + "afk_timeout": { + "type": "integer" + }, + "rules_channel_id": { + "type": "string" + }, + "public_updates_channel_id": { + "type": "string" + }, + "mfa_level": { + "type": "integer" + }, + "verification_level": { + "type": "integer" + }, + "explicit_content_filter": { + "type": "integer" + }, + "default_message_notifications": { + "type": "integer" + }, + "vanity_url_code": { + "type": "string" + }, + "$add": { + "type": "array", + "items": { + "type": "object", + "properties": {} + } + }, + "$remove": { + "type": "array", + "items": { + "type": "object", + "properties": {} + } + }, + "prune_delete_days": { + "type": "integer" + }, + "widget_enabled": { + "type": "boolean" + }, + "widget_channel_id": { + "type": "string" + }, + "system_channel_id": { + "type": "string" + }, + "position": { + "type": "integer" + }, + "topic": { + "type": "string" + }, + "bitrate": { + "type": "integer" + }, + "permission_overwrites": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ChannelPermissionOverwrite" + } + }, + "nsfw": { + "type": "boolean" + }, + "application_id": { + "type": "string" + }, + "rate_limit_per_user": { + "type": "integer" + }, + "permissions": { + "type": "string" + }, + "color": { + "type": "integer" + }, + "hoist": { + "type": "boolean" + }, + "mentionable": { + "type": "boolean" + }, + "allow": { + "type": "string" + }, + "deny": { + "type": "string" + }, + "code": { + "type": "string" + }, + "channel_id": { + "type": "string" + }, + "inviter_id": { + "type": "string" + }, + "max_uses": { + "type": "integer" + }, + "uses": { + "type": "integer" + }, + "max_age": { + "type": "integer" + }, + "temporary": { + "type": "boolean" + }, + "deaf": { + "type": "boolean" + }, + "mute": { + "type": "boolean" + }, + "nick": { + "type": "string" + }, + "avatar_hash": { + "type": "string" + }, + "id": { + "type": "string" + }, + "type": { + "type": "integer" + }, + "enable_emoticons": { + "type": "boolean" + }, + "expire_behavior": { + "type": "integer" + }, + "expire_grace_period": { + "type": "integer" + }, + "user_limit": { + "type": "integer" + } + } + }, + "AuditLog": { + "type": "object", + "properties": { + "target": { + "$ref": "#/components/schemas/User" + }, + "user_id": { + "type": "string" + }, + "user": { + "$ref": "#/components/schemas/User" + }, + "action_type": { + "$ref": "#/components/schemas/AuditLogEvents" + }, + "options": { + "type": "object", + "properties": { + "delete_member_days": { + "type": "string" + }, + "members_removed": { + "type": "string" + }, + "channel_id": { + "type": "string" + }, + "messaged_id": { + "type": "string" + }, + "count": { + "type": "string" + }, + "id": { + "type": "string" + }, + "type": { + "type": "string" + }, + "role_name": { + "type": "string" + } + }, + "additionalProperties": false + }, + "changes": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AuditLogChange" + } + }, + "reason": { + "type": "string" + }, + "id": { + "type": "string" + } + }, + "required": [ + "action_type", + "changes", + "id", + "user", + "user_id" + ] + }, + "ReadState": { + "type": "object", + "properties": { + "channel_id": { + "type": "string" + }, + "channel": { + "$ref": "#/components/schemas/Channel" + }, + "user_id": { + "type": "string" + }, + "user": { + "$ref": "#/components/schemas/User" + }, + "last_message_id": { + "type": "string" + }, + "last_message": { + "$ref": "#/components/schemas/Message" + }, + "last_pin_timestamp": { + "type": "string", + "format": "date-time" + }, + "mention_count": { + "type": "integer" + }, + "manual": { + "type": "boolean" + }, + "id": { + "type": "string" + } + }, + "required": [ + "channel", + "channel_id", + "id", + "last_message_id", + "manual", + "mention_count", + "user", + "user_id" + ] + }, + "UserPublic": { + "type": "object", + "properties": { + "username": { + "type": "string" + }, + "discriminator": { + "type": "string" + }, + "id": { + "type": "string" + }, + "public_flags": { + "type": "integer" + }, + "avatar": { + "type": "string" + }, + "accent_color": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "bio": { + "type": "string" + }, + "bot": { + "type": "boolean" + } + }, + "required": [ + "bio", + "bot", + "discriminator", + "id", + "public_flags", + "username" + ] + }, + "UserPrivate": { + "type": "object", + "properties": { + "locale": { + "type": "string" + }, + "disabled": { + "type": "boolean" + }, + "username": { + "type": "string" + }, + "discriminator": { + "type": "string" + }, + "id": { + "type": "string" + }, + "public_flags": { + "type": "string" + }, + "avatar": { + "type": "string" + }, + "accent_color": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "bio": { + "type": "string" + }, + "bot": { + "type": "boolean" + }, + "flags": { + "type": "string" + }, + "mfa_enabled": { + "type": "boolean" + }, + "email": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "verified": { + "type": "boolean" + }, + "nsfw_allowed": { + "type": "boolean" + }, + "premium": { + "type": "boolean" + }, + "premium_type": { + "type": "integer" + } + }, + "required": [ + "bio", + "bot", + "disabled", + "discriminator", + "flags", + "id", + "locale", + "mfa_enabled", + "nsfw_allowed", + "premium", + "premium_type", + "public_flags", + "username", + "verified" + ] + }, + "BanCreateSchema": { + "type": "object", + "properties": { + "delete_message_days": { + "type": "string" + }, + "reason": { + "type": "string" + } + } + }, + "DmChannelCreateSchema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "recipients": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "recipients" + ] + }, + "ChannelModifySchema": { + "type": "object", + "properties": { + "name": { + "maxLength": 100, + "type": "string" + }, + "type": { + "enum": [ + 0, + 1, + 10, + 11, + 12, + 13, + 2, + 3, + 4, + 5, + 6 + ], + "type": "number" + }, + "topic": { + "type": "string" + }, + "icon": { + "type": "string", + "nullable": true + }, + "bitrate": { + "type": "integer" + }, + "user_limit": { + "type": "integer" + }, + "rate_limit_per_user": { + "type": "integer" + }, + "position": { + "type": "integer" + }, + "permission_overwrites": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "$ref": "#/components/schemas/ChannelPermissionOverwriteType" + }, + "allow": { + "type": "number" + }, + "deny": { + "type": "number" + } + }, + "additionalProperties": false, + "required": [ + "allow", + "deny", + "id", + "type" + ] + } + }, + "parent_id": { + "type": "string" + }, + "id": { + "type": "string" + }, + "nsfw": { + "type": "boolean" + }, + "rtc_region": { + "type": "string" + }, + "default_auto_archive_duration": { + "type": "integer" + } + } + }, + "ChannelGuildPositionUpdateSchema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "position": { + "type": "integer" + } + }, + "additionalProperties": false, + "required": [ + "id" + ] + } + }, + "EmojiCreateSchema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "image": { + "type": "string" + }, + "roles": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "image", + "name" + ] + }, + "GuildCreateSchema": { + "type": "object", + "properties": { + "name": { + "maxLength": 100, + "type": "string" + }, + "region": { + "type": "string" + }, + "icon": { + "type": "string", + "nullable": true + }, + "channels": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ChannelModifySchema" + } + }, + "guild_template_code": { + "type": "string" + }, + "system_channel_id": { + "type": "string" + }, + "rules_channel_id": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "GuildUpdateSchema": { + "type": "object", + "properties": { + "banner": { + "type": "string", + "nullable": true + }, + "splash": { + "type": "string", + "nullable": true + }, + "description": { + "type": "string" + }, + "features": { + "type": "array", + "items": { + "type": "string" + } + }, + "verification_level": { + "type": "integer" + }, + "default_message_notifications": { + "type": "integer" + }, + "system_channel_flags": { + "type": "integer" + }, + "explicit_content_filter": { + "type": "integer" + }, + "public_updates_channel_id": { + "type": "string" + }, + "afk_timeout": { + "type": "integer" + }, + "afk_channel_id": { + "type": "string" + }, + "preferred_locale": { + "type": "string" + }, + "name": { + "maxLength": 100, + "type": "string" + }, + "region": { + "type": "string" + }, + "icon": { + "type": "string", + "nullable": true + }, + "guild_template_code": { + "type": "string" + }, + "system_channel_id": { + "type": "string" + }, + "rules_channel_id": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "GuildTemplateCreateSchema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "avatar": { + "type": "string", + "nullable": true + } + }, + "required": [ + "name" + ] + }, + "GuildUpdateWelcomeScreenSchema": { + "type": "object", + "properties": { + "welcome_channels": { + "type": "array", + "items": { + "type": "object", + "properties": { + "channel_id": { + "type": "string" + }, + "description": { + "type": "string" + }, + "emoji_id": { + "type": "string" + }, + "emoji_name": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "channel_id", + "description", + "emoji_name" + ] + } + }, + "enabled": { + "type": "boolean" + }, + "description": { + "type": "string" + } + } + }, + "InviteCreateSchema": { + "type": "object", + "properties": { + "target_user_id": { + "type": "string" + }, + "target_type": { + "type": "string" + }, + "validate": { + "type": "string" + }, + "max_age": { + "type": "integer" + }, + "max_uses": { + "type": "integer" + }, + "temporary": { + "type": "boolean" + }, + "unique": { + "type": "boolean" + }, + "target_user": { + "type": "string" + }, + "target_user_type": { + "type": "integer" + } + } + }, + "MemberCreateSchema": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "nick": { + "type": "string" + }, + "guild_id": { + "type": "string" + }, + "joined_at": { + "type": "string", + "format": "date-time" + } + }, + "required": [ + "guild_id", + "id", + "joined_at", + "nick" + ] + }, + "MemberNickChangeSchema": { + "type": "object", + "properties": { + "nick": { + "type": "string" + } + }, + "required": [ + "nick" + ] + }, + "MemberChangeSchema": { + "type": "object", + "properties": { + "roles": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "MessageCreateSchema": { + "type": "object", + "properties": { + "content": { + "type": "string" + }, + "nonce": { + "type": "string" + }, + "tts": { + "type": "boolean" + }, + "flags": { + "type": "string" + }, + "embeds": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Embed" + } + }, + "embed": { + "$ref": "#/components/schemas/Embed" + }, + "allowed_mentions": { + "type": "object", + "properties": { + "parse": { + "type": "array", + "items": { + "type": "string" + } + }, + "roles": { + "type": "array", + "items": { + "type": "string" + } + }, + "users": { + "type": "array", + "items": { + "type": "string" + } + }, + "replied_user": { + "type": "boolean" + } + }, + "additionalProperties": false + }, + "message_reference": { + "type": "object", + "properties": { + "message_id": { + "type": "string" + }, + "channel_id": { + "type": "string" + }, + "guild_id": { + "type": "string" + }, + "fail_if_not_exists": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "channel_id", + "message_id" + ] + }, + "payload_json": { + "type": "string" + }, + "file": {}, + "attachments": { + "type": "array", + "items": {} + } + } + }, + "RoleModifySchema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "permissions": { + "type": "number" + }, + "color": { + "type": "integer" + }, + "hoist": { + "type": "boolean" + }, + "mentionable": { + "type": "boolean" + }, + "position": { + "type": "integer" + } + } + }, + "TemplateCreateSchema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "TemplateModifySchema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "required": [ + "name" + ] + }, + "UserModifySchema": { + "type": "object", + "properties": { + "username": { + "minLength": 1, + "maxLength": 100, + "type": "string" + }, + "avatar": { + "type": "string", + "nullable": true + }, + "bio": { + "maxLength": 1024, + "type": "string" + }, + "accent_color": { + "type": "integer" + }, + "banner": { + "type": "string", + "nullable": true + }, + "password": { + "type": "string" + }, + "new_password": { + "type": "string" + }, + "code": { + "type": "string" + } + } + }, + "UserSettingsSchema": { + "type": "object", + "properties": { + "afk_timeout": { + "type": "integer" + }, + "allow_accessibility_detection": { + "type": "boolean" + }, + "animate_emoji": { + "type": "boolean" + }, + "animate_stickers": { + "type": "integer" + }, + "contact_sync_enabled": { + "type": "boolean" + }, + "convert_emoticons": { + "type": "boolean" + }, + "custom_status": { + "type": "object", + "properties": { + "emoji_id": { + "type": "string" + }, + "emoji_name": { + "type": "string" + }, + "expires_at": { + "type": "integer" + }, + "text": { + "type": "string" + } + }, + "additionalProperties": false + }, + "default_guilds_restricted": { + "type": "boolean" + }, + "detect_platform_accounts": { + "type": "boolean" + }, + "developer_mode": { + "type": "boolean" + }, + "disable_games_tab": { + "type": "boolean" + }, + "enable_tts_command": { + "type": "boolean" + }, + "explicit_content_filter": { + "type": "integer" + }, + "friend_source_flags": { + "type": "object", + "properties": { + "all": { + "type": "boolean" + } + }, + "additionalProperties": false, + "required": [ + "all" + ] + }, + "gateway_connected": { + "type": "boolean" + }, + "gif_auto_play": { + "type": "boolean" + }, + "guild_folders": { + "type": "array", + "items": { + "type": "object", + "properties": { + "color": { + "type": "integer" + }, + "guild_ids": { + "type": "array", + "items": { + "type": "string" + } + }, + "id": { + "type": "integer" + }, + "name": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "color", + "guild_ids", + "id", + "name" + ] + } + }, + "guild_positions": { + "type": "array", + "items": { + "type": "string" + } + }, + "inline_attachment_media": { + "type": "boolean" + }, + "inline_embed_media": { + "type": "boolean" + }, + "locale": { + "type": "string" + }, + "message_display_compact": { + "type": "boolean" + }, + "native_phone_integration_enabled": { + "type": "boolean" + }, + "render_embeds": { + "type": "boolean" + }, + "render_reactions": { + "type": "boolean" + }, + "restricted_guilds": { + "type": "array", + "items": { + "type": "string" + } + }, + "show_current_game": { + "type": "boolean" + }, + "status": { + "enum": [ + "dnd", + "idle", + "offline", + "online" + ], + "type": "string" + }, + "stream_notifications_enabled": { + "type": "boolean" + }, + "theme": { + "enum": [ + "dark", + "white" + ], + "type": "string" + }, + "timezone_offset": { + "type": "integer" + } + }, + "required": [ + "afk_timeout", + "allow_accessibility_detection", + "animate_emoji", + "animate_stickers", + "contact_sync_enabled", + "convert_emoticons", + "custom_status", + "default_guilds_restricted", + "detect_platform_accounts", + "developer_mode", + "disable_games_tab", + "enable_tts_command", + "explicit_content_filter", + "friend_source_flags", + "gateway_connected", + "gif_auto_play", + "guild_folders", + "guild_positions", + "inline_attachment_media", + "inline_embed_media", + "locale", + "message_display_compact", + "native_phone_integration_enabled", + "render_embeds", + "render_reactions", + "restricted_guilds", + "show_current_game", + "status", + "stream_notifications_enabled", + "theme", + "timezone_offset" + ] + }, + "WidgetModifySchema": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "channel_id": { + "type": "string" + } + }, + "required": [ + "channel_id", + "enabled" + ] + }, + "RegisterSchema": { + "type": "object", + "properties": { + "username": { + "minLength": 2, + "maxLength": 32, + "type": "string" + }, + "password": { + "minLength": 1, + "maxLength": 72, + "type": "string" + }, + "consent": { + "type": "boolean" + }, + "email": { + "format": "email", + "type": "string" + }, + "fingerprint": { + "type": "string" + }, + "invite": { + "type": "string" + }, + "date_of_birth": { + "type": "string" + }, + "gift_code_sku_id": { + "type": "string" + }, + "captcha_key": { + "type": "string" + } + }, + "required": [ + "consent", + "username" + ] + }, + "LoginSchema": { + "type": "object", + "properties": { + "login": { + "type": "string" + }, + "password": { + "type": "string" + }, + "undelete": { + "type": "boolean" + }, + "captcha_key": { + "type": "string" + }, + "login_source": { + "type": "string" + }, + "gift_code_sku_id": { + "type": "string" + } + }, + "required": [ + "login", + "password" + ] + }, + "MessageAcknowledgeSchema": { + "type": "object", + "properties": { + "manual": { + "type": "boolean" + }, + "mention_count": { + "type": "integer" + } + } + }, + "BulkDeleteSchema": { + "type": "object", + "properties": { + "messages": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "messages" + ] + }, + "ChannelPermissionOverwriteSchema": { + "type": "object", + "properties": { + "allow": { + "type": "number" + }, + "deny": { + "type": "number" + }, + "id": { + "type": "string" + }, + "type": { + "$ref": "#/components/schemas/ChannelPermissionOverwriteType" + } + }, + "required": [ + "allow", + "deny", + "id", + "type" + ] + }, + "WebhookCreateSchema": { + "type": "object", + "properties": { + "name": { + "maxLength": 80, + "type": "string" + }, + "avatar": { + "type": "string" + } + }, + "required": [ + "avatar", + "name" + ] + }, + "ChannelReorderSchema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "position": { + "type": "integer" + }, + "lock_permissions": { + "type": "boolean" + }, + "parent_id": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "id" + ] + } + }, + "RolePositionUpdateSchema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "position": { + "type": "integer" + } + }, + "additionalProperties": false, + "required": [ + "id", + "position" + ] + } + }, + "VanityUrlSchema": { + "type": "object", + "properties": { + "code": { + "minLength": 1, + "maxLength": 20, + "type": "string" + } + } + }, + "VoiceStateUpdateSchema": { + "type": "object", + "properties": { + "channel_id": { + "type": "string" + }, + "guild_id": { + "type": "string" + }, + "suppress": { + "type": "boolean" + }, + "request_to_speak_timestamp": { + "type": "string", + "format": "date-time" + }, + "self_mute": { + "type": "boolean" + }, + "self_deaf": { + "type": "boolean" + }, + "self_video": { + "type": "boolean" + } + }, + "required": [ + "channel_id" + ] + }, + "UserProfileResponse": { + "type": "object", + "properties": { + "user": { + "$ref": "#/components/schemas/UserPublic" + }, + "connected_accounts": { + "$ref": "#/components/schemas/PublicConnectedAccount" + }, + "premium_guild_since": { + "type": "string", + "format": "date-time" + }, + "premium_since": { + "type": "string", + "format": "date-time" + } + }, + "required": [ + "connected_accounts", + "user" + ] + }, + "RelationshipPutSchema": { + "type": "object", + "properties": { + "type": { + "enum": [ + 1, + 2, + 3, + 4 + ], + "type": "number" + } + } + }, + "RelationshipPostSchema": { + "type": "object", + "properties": { + "discriminator": { + "type": "string" + }, + "username": { + "type": "string" + } + }, + "required": [ + "discriminator", + "username" + ] + }, + "PublicConnectedAccount": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "verifie": { + "type": "boolean" + } + }, + "required": [ + "name", + "type", + "verifie" + ] + } + }, + "requestBodies": {}, + "securitySchemes": { + "Token": { + "type": "apiKey", + "name": "Authorization", + "in": "header" + } + }, + "links": {}, + "callbacks": {} + } +} \ No newline at end of file diff --git a/api/tests/routes.test.ts b/api/tests/routes.test.ts index a9c75df1..fcaa3124 100644 --- a/api/tests/routes.test.ts +++ b/api/tests/routes.test.ts @@ -7,7 +7,7 @@ import fs from "fs"; import Ajv from "ajv"; import addFormats from "ajv-formats"; import fetch from "node-fetch"; -import { User } from "@fosscord/util"; +import { Event, User, events } from "@fosscord/util"; const SchemaPath = join(__dirname, "..", "assets", "schemas.json"); const schemas = JSON.parse(fs.readFileSync(SchemaPath, { encoding: "utf8" })); @@ -58,6 +58,12 @@ beforeAll(async (done) => { } }); +const emit = events.emit; +events.emit = (event: string | symbol, ...args: any[]) => { + events.emit("event", args[0]); + return emit(event, ...args); +}; + describe("Automatic unit tests with route description middleware", () => { const routes = getRouteDescriptions(); @@ -77,6 +83,23 @@ describe("Automatic unit tests with route description middleware", () => { } var body = ""; + let eventEmitted = Promise.resolve(); + + if (route.test.event) { + if (!Array.isArray(route.test.event)) route.test.event = [route.test.event]; + + eventEmitted = new Promise((resolve, reject) => { + const timeout = setTimeout(() => reject, 1000); + const received = []; + + events.on("event", (event: Event) => { + if (!route.test.event.includes(event.event)) return; + + received.push(event.event); + if (received.length === route.test.event.length) resolve(); + }); + }); + } try { const response = await fetch(`http://localhost:3001/api${urlPath}`, { @@ -101,6 +124,12 @@ describe("Automatic unit tests with route description middleware", () => { return done(error); } + try { + await eventEmitted; + } catch (error) { + return done(new Error(`Event ${route.test.event} was not emitted`)); + } + return done(); }); }); diff --git a/util/src/util/Event.ts b/util/src/util/Event.ts index 765e5fc7..bf9547b1 100644 --- a/util/src/util/Event.ts +++ b/util/src/util/Event.ts @@ -2,7 +2,7 @@ import { Channel } from "amqplib"; import { RabbitMQ } from "./RabbitMQ"; import EventEmitter from "events"; import { EVENT, Event } from "../interfaces"; -const events = new EventEmitter(); +export const events = new EventEmitter(); export async function emitEvent(payload: Omit) { const id = (payload.channel_id || payload.user_id || payload.guild_id) as string; -- cgit 1.5.1