From 405a2964da9af043442a5bc51713670e58a95146 Mon Sep 17 00:00:00 2001 From: Cyber <44707958+CyberL1@users.noreply.github.com> Date: Sat, 4 Sep 2021 23:21:14 +0200 Subject: Add token authorization method to swagger openapi --- api/assets/openapi.json | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'api/assets') diff --git a/api/assets/openapi.json b/api/assets/openapi.json index 5244da36..fa527911 100644 --- a/api/assets/openapi.json +++ b/api/assets/openapi.json @@ -32,7 +32,8 @@ "description": "User not found", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } - } + }, + "security": [{ "Token": [] }] } }, "/users/@me": { @@ -46,7 +47,8 @@ "description": "Authenticated user", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UserPublic" } } } } - } + }, + "security": [{ "Token": [] }] } } }, @@ -1470,9 +1472,14 @@ } }, "requestBodies": {}, - "securitySchemes": {}, + "securitySchemes": { + "Token": { + "type": "apiKey", + "name": "Authorization", + "in": "header" + } + }, "links": {}, "callbacks": {} - }, - "security": [] -} + } +} \ No newline at end of file -- cgit 1.5.1 From e2c66a1fe578ece2c126d554ba04743ecb6991d8 Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Sun, 12 Sep 2021 21:21:08 +0200 Subject: :construction: :sparkles: new body parser (bans route) --- api/assets/schemas.json | 939 ++++++++++++++++++++++++++++++++ api/patches/ajv+8.6.2.patch | 249 +++++++++ api/scripts/generate_body_schema.ts | 59 ++ api/src/routes/guilds/#guild_id/bans.ts | 25 +- api/src/util/route.ts | 66 +++ 5 files changed, 1323 insertions(+), 15 deletions(-) create mode 100644 api/assets/schemas.json create mode 100644 api/patches/ajv+8.6.2.patch create mode 100644 api/scripts/generate_body_schema.ts create mode 100644 api/src/util/route.ts (limited to 'api/assets') diff --git a/api/assets/schemas.json b/api/assets/schemas.json new file mode 100644 index 00000000..b575bf60 --- /dev/null +++ b/api/assets/schemas.json @@ -0,0 +1,939 @@ +{ + "DmChannelCreateSchema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "recipients": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false, + "required": [ + "recipients" + ], + "$schema": "http://json-schema.org/draft-07/schema#" + }, + "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" + }, + "permission_overwrites": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "type": { + "type": "integer" + }, + "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" + ] + }, + "ChannelGuildPositionUpdateSchema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "position": { + "type": "integer" + } + }, + "additionalProperties": false, + "required": [ + "id" + ] + }, + "$schema": "http://json-schema.org/draft-07/schema#" + }, + "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" + } + }, + "additionalProperties": false, + "$schema": "http://json-schema.org/draft-07/schema#" + }, + "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" + } + }, + "additionalProperties": false + }, + "MessageCreateSchema": { + "type": "object", + "properties": { + "content": { + "type": "string" + }, + "nonce": { + "type": "string" + }, + "tts": { + "type": "boolean" + }, + "flags": { + "type": "string" + }, + "embed": { + "additionalProperties": false, + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "type": { + "$ref": "#/definitions/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": "#/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" + ] + } + } + } + }, + "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": {} + }, + "additionalProperties": false, + "$schema": "http://json-schema.org/draft-07/schema#" + }, + "BanCreateSchema": { + "type": "object", + "properties": { + "delete_message_days": { + "type": "string" + }, + "reason": { + "type": "string" + } + }, + "additionalProperties": false, + "$schema": "http://json-schema.org/draft-07/schema#" + }, + "GuildCreateSchema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "region": { + "type": "string" + }, + "icon": { + "type": "string" + }, + "channels": { + "type": "array", + "items": { + "$ref": "#/definitions/ChannelModifySchema" + } + }, + "guild_template_code": { + "type": "string" + }, + "system_channel_id": { + "type": "string" + }, + "rules_channel_id": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "name" + ], + "$schema": "http://json-schema.org/draft-07/schema#" + }, + "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" + } + }, + "additionalProperties": false, + "required": [ + "name" + ], + "$schema": "http://json-schema.org/draft-07/schema#" + }, + "GuildTemplateCreateSchema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "avatar": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "name" + ], + "$schema": "http://json-schema.org/draft-07/schema#" + }, + "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" + } + }, + "additionalProperties": false, + "$schema": "http://json-schema.org/draft-07/schema#" + }, + "VoiceStateUpdateSchema": { + "type": "object", + "properties": { + "channel_id": { + "type": "string" + }, + "suppress": { + "type": "boolean" + }, + "request_to_speak_timestamp": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "channel_id" + ], + "$schema": "http://json-schema.org/draft-07/schema#" + }, + "MemberCreateSchema": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "nick": { + "type": "string" + }, + "guild_id": { + "type": "string" + }, + "joined_at": { + "type": "string", + "format": "date-time" + } + }, + "additionalProperties": false, + "required": [ + "guild_id", + "id", + "joined_at", + "nick" + ], + "$schema": "http://json-schema.org/draft-07/schema#" + }, + "MemberNickChangeSchema": { + "type": "object", + "properties": { + "nick": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "nick" + ], + "$schema": "http://json-schema.org/draft-07/schema#" + }, + "MemberChangeSchema": { + "type": "object", + "properties": { + "roles": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false, + "$schema": "http://json-schema.org/draft-07/schema#" + }, + "RoleModifySchema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "permissions": { + "type": "bigint" + }, + "color": { + "type": "integer" + }, + "hoist": { + "type": "boolean" + }, + "mentionable": { + "type": "boolean" + }, + "position": { + "type": "integer" + } + }, + "additionalProperties": false, + "$schema": "http://json-schema.org/draft-07/schema#" + }, + "RolePositionUpdateSchema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "position": { + "type": "integer" + } + }, + "additionalProperties": false, + "required": [ + "id", + "position" + ] + }, + "$schema": "http://json-schema.org/draft-07/schema#" + }, + "TemplateCreateSchema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "name" + ], + "$schema": "http://json-schema.org/draft-07/schema#" + }, + "TemplateModifySchema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "name" + ], + "$schema": "http://json-schema.org/draft-07/schema#" + }, + "EmojiCreateSchema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "image": { + "type": "string" + }, + "roles": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false, + "required": [ + "image", + "name" + ], + "$schema": "http://json-schema.org/draft-07/schema#" + }, + "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" + } + }, + "additionalProperties": false, + "$schema": "http://json-schema.org/draft-07/schema#" + }, + "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" + } + }, + "additionalProperties": false, + "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" + ], + "$schema": "http://json-schema.org/draft-07/schema#" + }, + "WidgetModifySchema": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "channel_id": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "channel_id", + "enabled" + ], + "$schema": "http://json-schema.org/draft-07/schema#" + } +} \ No newline at end of file diff --git a/api/patches/ajv+8.6.2.patch b/api/patches/ajv+8.6.2.patch new file mode 100644 index 00000000..3f54881b --- /dev/null +++ b/api/patches/ajv+8.6.2.patch @@ -0,0 +1,249 @@ +diff --git a/node_modules/ajv/dist/compile/jtd/parse.js b/node_modules/ajv/dist/compile/jtd/parse.js +index 1eeb1be..7684121 100644 +--- a/node_modules/ajv/dist/compile/jtd/parse.js ++++ b/node_modules/ajv/dist/compile/jtd/parse.js +@@ -239,6 +239,9 @@ function parseType(cxt) { + gen.if(fail, () => parsingError(cxt, codegen_1.str `invalid timestamp`)); + break; + } ++ case "bigint": ++ parseBigInt(cxt); ++ break + case "float32": + case "float64": + parseNumber(cxt); +@@ -284,6 +287,15 @@ function parseNumber(cxt, maxDigits) { + skipWhitespace(cxt); + gen.if(codegen_1._ `"-0123456789".indexOf(${jsonSlice(1)}) < 0`, () => jsonSyntaxError(cxt), () => parseWith(cxt, parseJson_1.parseJsonNumber, maxDigits)); + } ++function parseBigInt(cxt, maxDigits) { ++ const {gen} = cxt ++ skipWhitespace(cxt) ++ gen.if( ++ _`"-0123456789".indexOf(${jsonSlice(1)}) < 0`, ++ () => jsonSyntaxError(cxt), ++ () => parseWith(cxt, parseJson_1.parseJsonBigInt, maxDigits) ++ ) ++} + function parseBooleanToken(bool, fail) { + return (cxt) => { + const { gen, data } = cxt; +diff --git a/node_modules/ajv/dist/compile/rules.js b/node_modules/ajv/dist/compile/rules.js +index 82a591f..1ebd8fe 100644 +--- a/node_modules/ajv/dist/compile/rules.js ++++ b/node_modules/ajv/dist/compile/rules.js +@@ -1,7 +1,7 @@ + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.getRules = exports.isJSONType = void 0; +-const _jsonTypes = ["string", "number", "integer", "boolean", "null", "object", "array"]; ++const _jsonTypes = ["string", "number", "integer", "boolean", "null", "object", "array","bigint"]; + const jsonTypes = new Set(_jsonTypes); + function isJSONType(x) { + return typeof x == "string" && jsonTypes.has(x); +@@ -13,10 +13,11 @@ function getRules() { + string: { type: "string", rules: [] }, + array: { type: "array", rules: [] }, + object: { type: "object", rules: [] }, ++ bigint: {type: "bigint", rules: []} + }; + return { +- types: { ...groups, integer: true, boolean: true, null: true }, +- rules: [{ rules: [] }, groups.number, groups.string, groups.array, groups.object], ++ types: { ...groups, integer: true, boolean: true, null: true, bigint: true }, ++ rules: [{ rules: [] }, groups.number, groups.string, groups.array, groups.object, groups.bigint], + post: { rules: [] }, + all: {}, + keywords: {}, +diff --git a/node_modules/ajv/dist/compile/validate/dataType.js b/node_modules/ajv/dist/compile/validate/dataType.js +index 6319e76..8b50b4c 100644 +--- a/node_modules/ajv/dist/compile/validate/dataType.js ++++ b/node_modules/ajv/dist/compile/validate/dataType.js +@@ -52,7 +52,7 @@ function coerceAndCheckDataType(it, types) { + return checkTypes; + } + exports.coerceAndCheckDataType = coerceAndCheckDataType; +-const COERCIBLE = new Set(["string", "number", "integer", "boolean", "null"]); ++const COERCIBLE = new Set(["string", "number", "integer", "boolean", "null","bigint"]); + function coerceToTypes(types, coerceTypes) { + return coerceTypes + ? types.filter((t) => COERCIBLE.has(t) || (coerceTypes === "array" && t === "array")) +@@ -83,6 +83,14 @@ function coerceData(it, types, coerceTo) { + }); + function coerceSpecificType(t) { + switch (t) { ++ case "bigint": ++ gen ++ .elseIf( ++ codegen_1._`${dataType} == "boolean" || ${data} === null ++ || (${dataType} == "string" && ${data} && ${data} == BigInt(${data}))` ++ ) ++ .assign(coerced, codegen_1._`BigInt(${data})`) ++ return + case "string": + gen + .elseIf(codegen_1._ `${dataType} == "number" || ${dataType} == "boolean"`) +@@ -143,6 +151,9 @@ function checkDataType(dataType, data, strictNums, correct = DataType.Correct) { + case "number": + cond = numCond(); + break; ++ case "bigint": ++ cond = codegen_1._`typeof ${data} == "bigint" && isFinite(${data})` ++ break + default: + return codegen_1._ `typeof ${data} ${EQ} ${dataType}`; + } +diff --git a/node_modules/ajv/dist/refs/json-schema-2019-09/meta/validation.json b/node_modules/ajv/dist/refs/json-schema-2019-09/meta/validation.json +index 7027a12..25679c8 100644 +--- a/node_modules/ajv/dist/refs/json-schema-2019-09/meta/validation.json ++++ b/node_modules/ajv/dist/refs/json-schema-2019-09/meta/validation.json +@@ -78,7 +78,7 @@ + "default": 0 + }, + "simpleTypes": { +- "enum": ["array", "boolean", "integer", "null", "number", "object", "string"] ++ "enum": ["array", "boolean", "integer", "null", "number", "object", "string","bigint"] + }, + "stringArray": { + "type": "array", +diff --git a/node_modules/ajv/dist/refs/json-schema-2020-12/meta/validation.json b/node_modules/ajv/dist/refs/json-schema-2020-12/meta/validation.json +index e0ae13d..57c9036 100644 +--- a/node_modules/ajv/dist/refs/json-schema-2020-12/meta/validation.json ++++ b/node_modules/ajv/dist/refs/json-schema-2020-12/meta/validation.json +@@ -78,7 +78,7 @@ + "default": 0 + }, + "simpleTypes": { +- "enum": ["array", "boolean", "integer", "null", "number", "object", "string"] ++ "enum": ["array", "boolean", "integer", "null", "number", "object", "string","bigint"] + }, + "stringArray": { + "type": "array", +diff --git a/node_modules/ajv/dist/refs/json-schema-draft-06.json b/node_modules/ajv/dist/refs/json-schema-draft-06.json +index 5410064..774435b 100644 +--- a/node_modules/ajv/dist/refs/json-schema-draft-06.json ++++ b/node_modules/ajv/dist/refs/json-schema-draft-06.json +@@ -16,7 +16,7 @@ + "allOf": [{"$ref": "#/definitions/nonNegativeInteger"}, {"default": 0}] + }, + "simpleTypes": { +- "enum": ["array", "boolean", "integer", "null", "number", "object", "string"] ++ "enum": ["array", "boolean", "integer", "null", "number", "object", "string","bigint"] + }, + "stringArray": { + "type": "array", +diff --git a/node_modules/ajv/dist/refs/json-schema-draft-07.json b/node_modules/ajv/dist/refs/json-schema-draft-07.json +index 6a74851..fc6dd7d 100644 +--- a/node_modules/ajv/dist/refs/json-schema-draft-07.json ++++ b/node_modules/ajv/dist/refs/json-schema-draft-07.json +@@ -16,7 +16,7 @@ + "allOf": [{"$ref": "#/definitions/nonNegativeInteger"}, {"default": 0}] + }, + "simpleTypes": { +- "enum": ["array", "boolean", "integer", "null", "number", "object", "string"] ++ "enum": ["array", "boolean", "integer", "null", "number", "object", "string","bigint"] + }, + "stringArray": { + "type": "array", +diff --git a/node_modules/ajv/dist/refs/jtd-schema.js b/node_modules/ajv/dist/refs/jtd-schema.js +index 1ee940a..1148887 100644 +--- a/node_modules/ajv/dist/refs/jtd-schema.js ++++ b/node_modules/ajv/dist/refs/jtd-schema.js +@@ -38,6 +38,7 @@ const typeForm = (root) => ({ + "uint16", + "int32", + "uint32", ++ "bigint", + ], + }, + }, +diff --git a/node_modules/ajv/dist/runtime/parseJson.js b/node_modules/ajv/dist/runtime/parseJson.js +index 2576a6e..e7447b1 100644 +--- a/node_modules/ajv/dist/runtime/parseJson.js ++++ b/node_modules/ajv/dist/runtime/parseJson.js +@@ -97,6 +97,71 @@ exports.parseJsonNumber = parseJsonNumber; + parseJsonNumber.message = undefined; + parseJsonNumber.position = 0; + parseJsonNumber.code = 'require("ajv/dist/runtime/parseJson").parseJsonNumber'; ++ ++function parseJsonBigInt(s, pos, maxDigits) { ++ let numStr = ""; ++ let c; ++ parseJsonBigInt.message = undefined; ++ if (s[pos] === "-") { ++ numStr += "-"; ++ pos++; ++ } ++ if (s[pos] === "0") { ++ numStr += "0"; ++ pos++; ++ } ++ else { ++ if (!parseDigits(maxDigits)) { ++ errorMessage(); ++ return undefined; ++ } ++ } ++ if (maxDigits) { ++ parseJsonBigInt.position = pos; ++ return BigInt(numStr); ++ } ++ if (s[pos] === ".") { ++ numStr += "."; ++ pos++; ++ if (!parseDigits()) { ++ errorMessage(); ++ return undefined; ++ } ++ } ++ if (((c = s[pos]), c === "e" || c === "E")) { ++ numStr += "e"; ++ pos++; ++ if (((c = s[pos]), c === "+" || c === "-")) { ++ numStr += c; ++ pos++; ++ } ++ if (!parseDigits()) { ++ errorMessage(); ++ return undefined; ++ } ++ } ++ parseJsonBigInt.position = pos; ++ return BigInt(numStr); ++ function parseDigits(maxLen) { ++ let digit = false; ++ while (((c = s[pos]), c >= "0" && c <= "9" && (maxLen === undefined || maxLen-- > 0))) { ++ digit = true; ++ numStr += c; ++ pos++; ++ } ++ return digit; ++ } ++ function errorMessage() { ++ parseJsonBigInt.position = pos; ++ parseJsonBigInt.message = pos < s.length ? `unexpected token ${s[pos]}` : "unexpected end"; ++ } ++} ++exports.parseJsonBigInt = parseJsonBigInt; ++parseJsonBigInt.message = undefined; ++parseJsonBigInt.position = 0; ++parseJsonBigInt.code = 'require("ajv/dist/runtime/parseJson").parseJsonBigInt'; ++ ++ + const escapedChars = { + b: "\b", + f: "\f", +diff --git a/node_modules/ajv/dist/vocabularies/jtd/type.js b/node_modules/ajv/dist/vocabularies/jtd/type.js +index 428bddb..fbc3070 100644 +--- a/node_modules/ajv/dist/vocabularies/jtd/type.js ++++ b/node_modules/ajv/dist/vocabularies/jtd/type.js +@@ -45,6 +45,9 @@ const def = { + cond = timestampCode(cxt); + break; + } ++ case "bigint": ++ cond = codegen_1._`typeof ${data} == "bigint" || typeof ${data} == "string"` ++ break + case "float32": + case "float64": + cond = codegen_1._ `typeof ${data} == "number"`; \ No newline at end of file diff --git a/api/scripts/generate_body_schema.ts b/api/scripts/generate_body_schema.ts new file mode 100644 index 00000000..69e62085 --- /dev/null +++ b/api/scripts/generate_body_schema.ts @@ -0,0 +1,59 @@ +// 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: false +}; +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, ...part.definitions, [name]: { ...part, definitions: undefined } }; + } + + fs.writeFileSync(schemaPath, JSON.stringify(definitions, null, 4)); +} + +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/guilds/#guild_id/bans.ts b/api/src/routes/guilds/#guild_id/bans.ts index 86bff6b4..41a97b6a 100644 --- a/api/src/routes/guilds/#guild_id/bans.ts +++ b/api/src/routes/guilds/#guild_id/bans.ts @@ -1,19 +1,18 @@ 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, check } from "@fosscord/api"; +import { getIpAdress, check, route } from "@fosscord/api"; import { BanCreateSchema } from "@fosscord/api/schema/Ban"; const router: Router = Router(); - -router.get("/", async (req: Request, res: Response) => { +router.get("/", route({ permission: "BAN_MEMBERS" }), async (req: Request, res: Response) => { const { guild_id } = req.params; var bans = await Ban.find({ guild_id: guild_id }); return res.json(bans); }); -router.get("/:user", async (req: Request, res: Response) => { +router.get("/:user", route({ permission: "BAN_MEMBERS" }), async (req: Request, res: Response) => { const { guild_id } = req.params; const user_id = req.params.ban; @@ -21,15 +20,14 @@ router.get("/:user", async (req: Request, res: Response) => { return res.json(ban); }); -router.put("/:user_id", check(BanCreateSchema), async (req: Request, res: Response) => { +router.put("/:user_id", route({ body: "BanCreateSchema", permission: "BAN_MEMBERS" }), async (req: Request, res: Response) => { const { guild_id } = req.params; const banned_user_id = req.params.user_id; const banned_user = await User.getPublicUser(banned_user_id); - const perms = await getPermission(req.user_id, guild_id); - perms.hasThrow("BAN_MEMBERS"); + if (req.user_id === banned_user_id) throw new HTTPError("You can't ban yourself", 400); - if (perms.cache.guild?.owner_id === banned_user_id) throw new HTTPError("You can't ban the owner", 400); + if (req.permission?.cache.guild?.owner_id === banned_user_id) throw new HTTPError("You can't ban the owner", 400); const ban = new Ban({ user_id: banned_user_id, @@ -55,17 +53,14 @@ router.put("/:user_id", check(BanCreateSchema), async (req: Request, res: Respon return res.json(ban); }); -router.delete("/:user_id", async (req: Request, res: Response) => { - var { guild_id } = req.params; - var banned_user_id = req.params.user_id; +router.delete("/:user_id", route({ permission: "BAN_MEMBERS" }), async (req: Request, res: Response) => { + const { guild_id, user_id } = req.params; - const banned_user = await User.getPublicUser(banned_user_id); - const perms = await getPermission(req.user_id, guild_id); - perms.hasThrow("BAN_MEMBERS"); + const banned_user = await User.getPublicUser(user_id); await Promise.all([ Ban.delete({ - user_id: banned_user_id, + user_id: user_id, guild_id }), diff --git a/api/src/util/route.ts b/api/src/util/route.ts new file mode 100644 index 00000000..0302f3ec --- /dev/null +++ b/api/src/util/route.ts @@ -0,0 +1,66 @@ +import { DiscordApiErrors, Event, EventData, getPermission, PermissionResolvable, Permissions } from "@fosscord/util"; +import { NextFunction, Request, Response } from "express"; +import fs from "fs"; +import path from "path"; +import Ajv from "ajv"; +import { AnyValidateFunction } from "ajv/dist/core"; +import { FieldErrors } from ".."; + +const SchemaPath = path.join(__dirname, "..", "..", "assets", "schemas.json"); +const schemas = JSON.parse(fs.readFileSync(SchemaPath, { encoding: "utf8" })); +export const ajv = new Ajv({ allErrors: true, parseDate: true, allowDate: true, schemas, messages: true }); + +declare global { + namespace Express { + interface Request { + permission?: Permissions; + } + } +} + +export type RouteSchema = string; // typescript interface name +export type RouteResponse = { status: number; body?: RouteSchema; headers?: Record }; + +export interface RouteOptions { + permission?: PermissionResolvable; + body?: RouteSchema; + response?: RouteResponse; + example?: { + body?: any; + path?: string; + event?: EventData; + headers?: Record; + }; +} + +export function route(opts: RouteOptions) { + var validate: AnyValidateFunction; + if (opts.body) { + // @ts-ignore + validate = ajv.getSchema(opts.body); + if (!validate) throw new Error(`Body schema ${opts.body} not found`); + } + + return async (req: Request, res: Response, next: NextFunction) => { + if (opts.permission) { + const required = new Permissions(opts.permission); + const permission = await getPermission(req.user_id, req.params.guild_id, req.params.channel_id); + console.log(required.bitfield, permission.bitfield, permission.bitfield & required.bitfield); + + // bitfield comparison: check if user lacks certain permission + if (!permission.has(required)) { + throw DiscordApiErrors.MISSING_PERMISSIONS.withParams(opts.permission as string); + } + + if (validate) { + const valid = validate(req.body); + if (!valid) { + const fields: Record = {}; + validate.errors?.forEach((x) => (fields[x.instancePath] = { code: x.keyword, message: x.message || "" })); + throw FieldErrors(fields); + } + } + } + next(); + }; +} -- cgit 1.5.1 From 6ba9c834bd2d5f4fac07e3fb9ded2625ce3c44ad Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Sun, 12 Sep 2021 23:28:56 +0200 Subject: :sparkles: #307 done --- api/assets/schemas.json | 7359 ++++++++++++++++++-- api/package-lock.json | 2 +- api/package.json | 6 +- api/scripts/generate_body_schema.ts | 3 +- api/src/routes/auth/login.ts | 108 +- api/src/routes/auth/register.ts | 357 +- api/src/routes/channels/#channel_id/index.ts | 49 +- api/src/routes/channels/#channel_id/invites.ts | 40 +- .../#channel_id/messages/#message_id/ack.ts | 10 +- .../#channel_id/messages/#message_id/index.ts | 16 +- .../#channel_id/messages/#message_id/reactions.ts | 33 +- .../channels/#channel_id/messages/bulk-delete.ts | 9 +- .../routes/channels/#channel_id/messages/index.ts | 101 +- api/src/routes/channels/#channel_id/permissions.ts | 82 +- api/src/routes/channels/#channel_id/pins.ts | 33 +- api/src/routes/channels/#channel_id/typing.ts | 6 +- api/src/routes/channels/#channel_id/webhooks.ts | 16 +- api/src/routes/discoverable-guilds.ts | 4 +- api/src/routes/experiments.ts | 3 +- api/src/routes/gateway.ts | 3 +- api/src/routes/guilds/#guild_id/bans.ts | 8 +- api/src/routes/guilds/#guild_id/channels.ts | 74 +- api/src/routes/guilds/#guild_id/delete.ts | 3 +- api/src/routes/guilds/#guild_id/index.ts | 34 +- api/src/routes/guilds/#guild_id/invites.ts | 6 +- .../guilds/#guild_id/members/#member_id/index.ts | 36 +- .../guilds/#guild_id/members/#member_id/nick.ts | 9 +- .../members/#member_id/roles/#role_id/index.ts | 11 +- api/src/routes/guilds/#guild_id/members/index.ts | 6 +- api/src/routes/guilds/#guild_id/regions.ts | 4 +- api/src/routes/guilds/#guild_id/roles.ts | 44 +- api/src/routes/guilds/#guild_id/templates.ts | 51 +- api/src/routes/guilds/#guild_id/vanity-url.ts | 24 +- .../#guild_id/voice-states/#user_id/index.ts | 57 +- .../guilds/#guild_id/voice-states/@me/index.ts | 15 - api/src/routes/guilds/#guild_id/welcome_screen.ts | 23 +- api/src/routes/guilds/#guild_id/widget.json.ts | 4 +- api/src/routes/guilds/#guild_id/widget.png.ts | 3 +- api/src/routes/guilds/#guild_id/widget.ts | 18 +- api/src/routes/guilds/index.ts | 19 +- api/src/routes/guilds/templates/index.ts | 12 +- api/src/routes/invites/index.ts | 8 +- api/src/routes/ping.ts | 3 +- api/src/routes/science.ts | 3 +- api/src/routes/users/#id/index.ts | 3 +- api/src/routes/users/#id/profile.ts | 17 +- api/src/routes/users/@me/affinities/guilds.ts | 3 +- api/src/routes/users/@me/affinities/user.ts | 3 +- api/src/routes/users/@me/channels.ts | 12 +- api/src/routes/users/@me/delete.ts | 4 +- api/src/routes/users/@me/devices.ts | 3 +- api/src/routes/users/@me/disable.ts | 3 +- api/src/routes/users/@me/guilds.ts | 6 +- api/src/routes/users/@me/index.ts | 25 +- api/src/routes/users/@me/library.ts | 3 +- api/src/routes/users/@me/relationships.ts | 150 +- api/src/routes/users/@me/settings.ts | 7 +- api/src/routes/voice/regions.ts | 4 +- api/src/schema/Ban.ts | 9 - api/src/schema/Channel.ts | 68 - api/src/schema/Emoji.ts | 13 - api/src/schema/Guild.ts | 106 - api/src/schema/Invite.ts | 22 - api/src/schema/Member.ts | 29 - api/src/schema/Message.ts | 92 - api/src/schema/Roles.ts | 29 - api/src/schema/Template.ts | 19 - api/src/schema/User.ts | 74 - api/src/schema/Widget.ts | 10 - api/src/schema/index.ts | 11 - api/src/util/Message.ts | 2 +- api/src/util/Voice.ts | 50 +- api/src/util/VoiceState.ts | 54 - api/src/util/index.ts | 1 - api/src/util/route.ts | 14 +- 75 files changed, 7857 insertions(+), 1704 deletions(-) delete mode 100644 api/src/routes/guilds/#guild_id/voice-states/@me/index.ts delete mode 100644 api/src/schema/Ban.ts delete mode 100644 api/src/schema/Channel.ts delete mode 100644 api/src/schema/Emoji.ts delete mode 100644 api/src/schema/Guild.ts delete mode 100644 api/src/schema/Invite.ts delete mode 100644 api/src/schema/Member.ts delete mode 100644 api/src/schema/Message.ts delete mode 100644 api/src/schema/Roles.ts delete mode 100644 api/src/schema/Template.ts delete mode 100644 api/src/schema/User.ts delete mode 100644 api/src/schema/Widget.ts delete mode 100644 api/src/schema/index.ts delete mode 100644 api/src/util/VoiceState.ts (limited to 'api/assets') diff --git a/api/assets/schemas.json b/api/assets/schemas.json index b575bf60..59ab4c04 100644 --- a/api/assets/schemas.json +++ b/api/assets/schemas.json @@ -1,20 +1,75 @@ { - "DmChannelCreateSchema": { + "RegisterSchema": { "type": "object", "properties": { - "name": { + "username": { + "minLength": 2, + "maxLength": 32, "type": "string" }, - "recipients": { - "type": "array", - "items": { - "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", + "format": "date-time" + }, + "gift_code_sku_id": { + "type": "string" + }, + "captcha_key": { + "type": "string" } }, "additionalProperties": false, "required": [ - "recipients" + "consent", + "password", + "username" + ], + "$schema": "http://json-schema.org/draft-07/schema#" + }, + "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" + } + }, + "additionalProperties": false, + "required": [ + "login", + "password" ], "$schema": "http://json-schema.org/draft-07/schema#" }, @@ -22,10 +77,11 @@ "type": "object", "properties": { "name": { + "maxLength": 100, "type": "string" }, "type": { - "type": "integer" + "$ref": "#/definitions/ChannelType" }, "topic": { "type": "string" @@ -51,7 +107,7 @@ "type": "string" }, "type": { - "type": "integer" + "$ref": "#/definitions/ChannelPermissionOverwriteType" }, "allow": { "type": "bigint" @@ -89,107 +145,32 @@ "required": [ "name", "type" - ] - }, - "ChannelGuildPositionUpdateSchema": { - "type": "array", - "items": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "position": { - "type": "integer" - } - }, - "additionalProperties": false, - "required": [ - "id" - ] - }, - "$schema": "http://json-schema.org/draft-07/schema#" - }, - "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" - } - }, - "additionalProperties": false, - "$schema": "http://json-schema.org/draft-07/schema#" - }, - "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" - } - }, - "additionalProperties": false - }, - "MessageCreateSchema": { - "type": "object", - "properties": { - "content": { - "type": "string" - }, - "nonce": { - "type": "string" - }, - "tts": { - "type": "boolean" + "definitions": { + "ChannelType": { + "enum": [ + 0, + 1, + 10, + 11, + 12, + 13, + 2, + 3, + 4, + 5, + 6 + ], + "type": "number" }, - "flags": { - "type": "string" + "ChannelPermissionOverwriteType": { + "enum": [ + 0, + 1 + ], + "type": "number" }, - "embed": { - "additionalProperties": false, + "Embed": { "type": "object", "properties": { "title": { @@ -205,7 +186,8 @@ "type": "string" }, "timestamp": { - "type": "string" + "type": "string", + "format": "date-time" }, "color": { "type": "integer" @@ -289,8 +271,148 @@ ] } } + }, + "additionalProperties": false + }, + "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" + } + }, + "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#" + }, + "MessageCreateSchema": { + "type": "object", + "properties": { + "content": { + "type": "string" + }, + "nonce": { + "type": "string" + }, + "tts": { + "type": "boolean" + }, + "flags": { + "type": "string" + }, + "embeds": { + "type": "array", + "items": { + "$ref": "#/definitions/Embed" } }, + "embed": { + "$ref": "#/definitions/Embed" + }, "allowed_mentions": { "type": "object", "properties": { @@ -346,377 +468,6580 @@ "file": {} }, "additionalProperties": false, - "$schema": "http://json-schema.org/draft-07/schema#" - }, - "BanCreateSchema": { - "type": "object", - "properties": { - "delete_message_days": { - "type": "string" - }, - "reason": { - "type": "string" - } - }, - "additionalProperties": false, - "$schema": "http://json-schema.org/draft-07/schema#" - }, - "GuildCreateSchema": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "region": { - "type": "string" + "definitions": { + "ChannelType": { + "enum": [ + 0, + 1, + 10, + 11, + 12, + 13, + 2, + 3, + 4, + 5, + 6 + ], + "type": "number" }, - "icon": { - "type": "string" + "ChannelPermissionOverwriteType": { + "enum": [ + 0, + 1 + ], + "type": "number" }, - "channels": { - "type": "array", - "items": { - "$ref": "#/definitions/ChannelModifySchema" - } + "Embed": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "type": { + "$ref": "#/definitions/EmbedType" + }, + "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 }, - "guild_template_code": { + "EmbedType": { + "enum": [ + "article", + "gifv", + "image", + "link", + "rich", + "video" + ], "type": "string" }, - "system_channel_id": { - "type": "string" + "EmbedImage": { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "proxy_url": { + "type": "string" + }, + "height": { + "type": "integer" + }, + "width": { + "type": "integer" + } + }, + "additionalProperties": false }, - "rules_channel_id": { - "type": "string" + "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" } }, - "additionalProperties": false, - "required": [ - "name" - ], "$schema": "http://json-schema.org/draft-07/schema#" }, - "GuildUpdateSchema": { + "InviteCreateSchema": { "type": "object", "properties": { - "banner": { + "target_user_id": { "type": "string" }, - "splash": { + "target_type": { "type": "string" }, - "description": { + "validate": { "type": "string" }, - "features": { - "type": "array", - "items": { - "type": "string" - } - }, - "verification_level": { + "max_age": { "type": "integer" }, - "default_message_notifications": { + "max_uses": { "type": "integer" }, - "system_channel_flags": { - "type": "integer" + "temporary": { + "type": "boolean" }, - "explicit_content_filter": { - "type": "integer" + "unique": { + "type": "boolean" }, - "public_updates_channel_id": { + "target_user": { "type": "string" }, - "afk_timeout": { + "target_user_type": { "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" } }, "additionalProperties": false, - "required": [ - "name" - ], - "$schema": "http://json-schema.org/draft-07/schema#" - }, - "GuildTemplateCreateSchema": { - "type": "object", - "properties": { - "name": { - "type": "string" + "definitions": { + "ChannelType": { + "enum": [ + 0, + 1, + 10, + 11, + 12, + 13, + 2, + 3, + 4, + 5, + 6 + ], + "type": "number" }, - "avatar": { - "type": "string" - } - }, - "additionalProperties": false, - "required": [ - "name" - ], - "$schema": "http://json-schema.org/draft-07/schema#" - }, - "GuildUpdateWelcomeScreenSchema": { - "type": "object", - "properties": { - "welcome_channels": { - "type": "array", - "items": { - "type": "object", - "properties": { - "channel_id": { - "type": "string" + "ChannelPermissionOverwriteType": { + "enum": [ + 0, + 1 + ], + "type": "number" + }, + "Embed": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "type": { + "$ref": "#/definitions/EmbedType" + }, + "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" + } }, - "description": { - "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" + } }, - "emoji_id": { - "type": "string" + "additionalProperties": false + }, + "author": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "url": { + "type": "string" + }, + "icon_url": { + "type": "string" + }, + "proxy_icon_url": { + "type": "string" + } }, - "emoji_name": { - "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 + }, + "EmbedType": { + "enum": [ + "article", + "gifv", + "image", + "link", + "rich", + "video" + ], + "type": "string" + }, + "EmbedImage": { + "type": "object", + "properties": { + "url": { + "type": "string" }, - "additionalProperties": false, - "required": [ - "channel_id", - "description", - "emoji_name" - ] - } + "proxy_url": { + "type": "string" + }, + "height": { + "type": "integer" + }, + "width": { + "type": "integer" + } + }, + "additionalProperties": false }, - "enabled": { - "type": "boolean" + "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" + ] }, - "description": { - "type": "string" + "RelationshipType": { + "enum": [ + 1, + 2, + 3, + 4 + ], + "type": "number" } }, - "additionalProperties": false, "$schema": "http://json-schema.org/draft-07/schema#" }, - "VoiceStateUpdateSchema": { + "MessageAcknowledgeSchema": { "type": "object", "properties": { - "channel_id": { - "type": "string" - }, - "suppress": { + "manual": { "type": "boolean" }, - "request_to_speak_timestamp": { - "type": "string" + "mention_count": { + "type": "integer" } }, "additionalProperties": false, - "required": [ - "channel_id" - ], - "$schema": "http://json-schema.org/draft-07/schema#" - }, - "MemberCreateSchema": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "nick": { - "type": "string" + "definitions": { + "ChannelType": { + "enum": [ + 0, + 1, + 10, + 11, + 12, + 13, + 2, + 3, + 4, + 5, + 6 + ], + "type": "number" }, - "guild_id": { - "type": "string" + "ChannelPermissionOverwriteType": { + "enum": [ + 0, + 1 + ], + "type": "number" }, - "joined_at": { - "type": "string", - "format": "date-time" - } - }, - "additionalProperties": false, - "required": [ - "guild_id", - "id", - "joined_at", - "nick" - ], - "$schema": "http://json-schema.org/draft-07/schema#" - }, - "MemberNickChangeSchema": { - "type": "object", - "properties": { - "nick": { - "type": "string" - } - }, - "additionalProperties": false, - "required": [ - "nick" - ], - "$schema": "http://json-schema.org/draft-07/schema#" - }, - "MemberChangeSchema": { - "type": "object", - "properties": { - "roles": { - "type": "array", - "items": { - "type": "string" - } - } - }, - "additionalProperties": false, - "$schema": "http://json-schema.org/draft-07/schema#" - }, - "RoleModifySchema": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "permissions": { - "type": "bigint" + "Embed": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "type": { + "$ref": "#/definitions/EmbedType" + }, + "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 }, - "color": { - "type": "integer" + "EmbedType": { + "enum": [ + "article", + "gifv", + "image", + "link", + "rich", + "video" + ], + "type": "string" }, - "hoist": { - "type": "boolean" + "EmbedImage": { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "proxy_url": { + "type": "string" + }, + "height": { + "type": "integer" + }, + "width": { + "type": "integer" + } + }, + "additionalProperties": false }, - "mentionable": { - "type": "boolean" + "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" + ] }, - "position": { - "type": "integer" + "RelationshipType": { + "enum": [ + 1, + 2, + 3, + 4 + ], + "type": "number" } }, - "additionalProperties": false, "$schema": "http://json-schema.org/draft-07/schema#" }, - "RolePositionUpdateSchema": { - "type": "array", - "items": { - "type": "object", - "properties": { - "id": { + "BulkDeleteSchema": { + "type": "object", + "properties": { + "messages": { + "type": "array", + "items": { "type": "string" + } + } + }, + "additionalProperties": false, + "required": [ + "messages" + ], + "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": { + "$ref": "#/definitions/EmbedType" + }, + "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 + }, + "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" + } + }, + "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#" + }, + "ChannelPermissionOverwriteSchema": { + "type": "object", + "properties": { + "allow": { + "type": "bigint" + }, + "deny": { + "type": "bigint" + }, + "id": { + "type": "string" + }, + "type": { + "$ref": "#/definitions/ChannelPermissionOverwriteType" + } + }, + "additionalProperties": false, + "required": [ + "allow", + "deny", + "id", + "type" + ], + "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": { + "$ref": "#/definitions/EmbedType" + }, + "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 + }, + "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" + } + }, + "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#" + }, + "WebhookCreateSchema": { + "type": "object", + "properties": { + "name": { + "maxLength": 80, + "type": "string" + }, + "avatar": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "avatar", + "name" + ], + "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": { + "$ref": "#/definitions/EmbedType" + }, + "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 + }, + "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" + } + }, + "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#" + }, + "BanCreateSchema": { + "type": "object", + "properties": { + "delete_message_days": { + "type": "string" + }, + "reason": { + "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": { + "$ref": "#/definitions/EmbedType" + }, + "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 + }, + "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" + } + }, + "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#" + }, + "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" + ] + }, + "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": { + "$ref": "#/definitions/EmbedType" + }, + "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 + }, + "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" + } + }, + "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#" + }, + "GuildCreateSchema": { + "type": "object", + "properties": { + "name": { + "maxLength": 100, + "type": "string" + }, + "region": { + "type": "string" + }, + "icon": { + "type": "string" + }, + "channels": { + "type": "array", + "items": { + "$ref": "#/definitions/ChannelModifySchema" + } + }, + "guild_template_code": { + "type": "string" + }, + "system_channel_id": { + "type": "string" + }, + "rules_channel_id": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "name" + ], + "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": { + "$ref": "#/definitions/EmbedType" + }, + "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 + }, + "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" + } + }, + "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#" + }, + "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": { + "maxLength": 100, + "type": "string" + }, + "region": { + "type": "string" + }, + "icon": { + "type": "string" + }, + "guild_template_code": { + "type": "string" + }, + "system_channel_id": { + "type": "string" + }, + "rules_channel_id": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "name" + ], + "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": { + "$ref": "#/definitions/EmbedType" + }, + "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 + }, + "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" + } + }, + "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#" + }, + "MemberChangeSchema": { + "type": "object", + "properties": { + "roles": { + "type": "array", + "items": { + "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": { + "$ref": "#/definitions/EmbedType" + }, + "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 + }, + "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" + } + }, + "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#" + }, + "MemberNickChangeSchema": { + "type": "object", + "properties": { + "nick": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "nick" + ], + "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": { + "$ref": "#/definitions/EmbedType" + }, + "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 + }, + "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" + } + }, + "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#" + }, + "RoleModifySchema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "permissions": { + "type": "bigint" + }, + "color": { + "type": "integer" + }, + "hoist": { + "type": "boolean" + }, + "mentionable": { + "type": "boolean" + }, + "position": { + "type": "integer" + } + }, + "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": { + "$ref": "#/definitions/EmbedType" + }, + "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 + }, + "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" + } + }, + "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#" + }, + "RolePositionUpdateSchema": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "position": { + "type": "integer" + } + }, + "additionalProperties": false, + "required": [ + "id", + "position" + ] + }, + "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": { + "$ref": "#/definitions/EmbedType" + }, + "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 + }, + "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" + } + }, + "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#" + }, + "TemplateCreateSchema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "name" + ], + "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": { + "$ref": "#/definitions/EmbedType" + }, + "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 + }, + "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" + } + }, + "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#" + }, + "TemplateModifySchema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "name" + ], + "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": { + "$ref": "#/definitions/EmbedType" + }, + "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 + }, + "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" + } + }, + "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#" + }, + "VanityUrlSchema": { + "type": "object", + "properties": { + "code": { + "minLength": 1, + "maxLength": 20, + "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": { + "$ref": "#/definitions/EmbedType" + }, + "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 + }, + "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" + } + }, + "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#" + }, + "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" + } + }, + "additionalProperties": false, + "required": [ + "channel_id" + ], + "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": { + "$ref": "#/definitions/EmbedType" + }, + "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 + }, + "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" + } + }, + "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#" + }, + "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" + } + }, + "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": { + "$ref": "#/definitions/EmbedType" + }, + "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 + }, + "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" + } + }, + "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#" + }, + "WidgetModifySchema": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "channel_id": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "channel_id", + "enabled" + ], + "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": { + "$ref": "#/definitions/EmbedType" + }, + "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 + }, + "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" + } + }, + "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#" + }, + "GuildTemplateCreateSchema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "avatar": { + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "name" + ], + "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": { + "$ref": "#/definitions/EmbedType" + }, + "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 + }, + "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" + } + }, + "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#" + }, + "DmChannelCreateSchema": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "recipients": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false, + "required": [ + "recipients" + ], + "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": { + "$ref": "#/definitions/EmbedType" + }, + "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 + }, + "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" + } + }, + "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#" + }, + "UserModifySchema": { + "type": "object", + "properties": { + "username": { + "minLength": 1, + "maxLength": 100, + "type": "string" + }, + "avatar": { + "type": "string" + }, + "bio": { + "maxLength": 1024, + "type": "string" + }, + "accent_color": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "password": { + "type": "string" + }, + "new_password": { + "type": "string" + }, + "code": { + "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": { + "$ref": "#/definitions/EmbedType" + }, + "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 + }, + "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" + } + }, + "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#" + }, + "RelationshipPutSchema": { + "type": "object", + "properties": { + "type": { + "$ref": "#/definitions/RelationshipType" + } + }, + "additionalProperties": false, + "required": [ + "type" + ], + "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": { + "$ref": "#/definitions/EmbedType" + }, + "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" + ] + } + } }, - "position": { - "type": "integer" - } + "additionalProperties": false }, - "additionalProperties": false, - "required": [ - "id", - "position" - ] - }, - "$schema": "http://json-schema.org/draft-07/schema#" - }, - "TemplateCreateSchema": { - "type": "object", - "properties": { - "name": { + "EmbedType": { + "enum": [ + "article", + "gifv", + "image", + "link", + "rich", + "video" + ], "type": "string" }, - "description": { - "type": "string" - } - }, - "additionalProperties": false, - "required": [ - "name" - ], - "$schema": "http://json-schema.org/draft-07/schema#" - }, - "TemplateModifySchema": { - "type": "object", - "properties": { - "name": { - "type": "string" + "EmbedImage": { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "proxy_url": { + "type": "string" + }, + "height": { + "type": "integer" + }, + "width": { + "type": "integer" + } + }, + "additionalProperties": false }, - "description": { - "type": "string" + "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" } }, - "additionalProperties": false, - "required": [ - "name" - ], "$schema": "http://json-schema.org/draft-07/schema#" }, - "EmojiCreateSchema": { + "RelationshipPostSchema": { "type": "object", "properties": { - "name": { + "discriminator": { "type": "string" }, - "image": { + "username": { "type": "string" - }, - "roles": { - "type": "array", - "items": { - "type": "string" - } } }, "additionalProperties": false, "required": [ - "image", - "name" + "discriminator", + "username" ], - "$schema": "http://json-schema.org/draft-07/schema#" - }, - "UserModifySchema": { - "type": "object", - "properties": { - "username": { - "type": "string" - }, - "avatar": { - "type": "string" + "definitions": { + "ChannelType": { + "enum": [ + 0, + 1, + 10, + 11, + 12, + 13, + 2, + 3, + 4, + 5, + 6 + ], + "type": "number" }, - "bio": { - "type": "string" + "ChannelPermissionOverwriteType": { + "enum": [ + 0, + 1 + ], + "type": "number" }, - "accent_color": { - "type": "integer" + "Embed": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "type": { + "$ref": "#/definitions/EmbedType" + }, + "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 }, - "banner": { + "EmbedType": { + "enum": [ + "article", + "gifv", + "image", + "link", + "rich", + "video" + ], "type": "string" }, - "password": { - "type": "string" + "EmbedImage": { + "type": "object", + "properties": { + "url": { + "type": "string" + }, + "proxy_url": { + "type": "string" + }, + "height": { + "type": "integer" + }, + "width": { + "type": "integer" + } + }, + "additionalProperties": false }, - "new_password": { - "type": "string" + "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" + ] }, - "code": { - "type": "string" + "RelationshipType": { + "enum": [ + 1, + 2, + 3, + 4 + ], + "type": "number" } }, - "additionalProperties": false, "$schema": "http://json-schema.org/draft-07/schema#" }, "UserSettingsSchema": { @@ -917,23 +7242,247 @@ "theme", "timezone_offset" ], - "$schema": "http://json-schema.org/draft-07/schema#" - }, - "WidgetModifySchema": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean" + "definitions": { + "ChannelType": { + "enum": [ + 0, + 1, + 10, + 11, + 12, + 13, + 2, + 3, + 4, + 5, + 6 + ], + "type": "number" }, - "channel_id": { + "ChannelPermissionOverwriteType": { + "enum": [ + 0, + 1 + ], + "type": "number" + }, + "Embed": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "type": { + "$ref": "#/definitions/EmbedType" + }, + "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 + }, + "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" + } + }, + "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" } }, - "additionalProperties": false, - "required": [ - "channel_id", - "enabled" - ], "$schema": "http://json-schema.org/draft-07/schema#" } } \ No newline at end of file diff --git a/api/package-lock.json b/api/package-lock.json index 8b2c93f8..c14b92fa 100644 --- a/api/package-lock.json +++ b/api/package-lock.json @@ -12,7 +12,7 @@ "dependencies": { "@fosscord/util": "file:../util", "ajv": "^8.4.0", - "ajv-formats": "^2.1.0", + "ajv-formats": "^2.1.1", "amqplib": "^0.8.0", "assert": "^1.5.0", "atomically": "^1.7.0", diff --git a/api/package.json b/api/package.json index b762b944..e7b476c7 100644 --- a/api/package.json +++ b/api/package.json @@ -12,7 +12,9 @@ "build-docker": "tsc -p tsconfig-docker.json", "dev": "tsnd --respawn src/start.ts", "patch": "npx patch-package", - "postinstall": "npm run patch" + "postinstall": "npm run patch", + "generate:docs": "ts-node scripts/generate_openapi_schema.ts", + "generate:schema": "ts-node scripts/generate_body_schema.ts" }, "repository": { "type": "git", @@ -60,7 +62,7 @@ "dependencies": { "@fosscord/util": "file:../util", "ajv": "^8.4.0", - "ajv-formats": "^2.1.0", + "ajv-formats": "^2.1.1", "amqplib": "^0.8.0", "assert": "^1.5.0", "atomically": "^1.7.0", diff --git a/api/scripts/generate_body_schema.ts b/api/scripts/generate_body_schema.ts index 69e62085..c406cab8 100644 --- a/api/scripts/generate_body_schema.ts +++ b/api/scripts/generate_body_schema.ts @@ -33,12 +33,13 @@ function main() { const part = TJS.generateSchema(program, name, settings, [], generator as TJS.JsonSchemaGenerator); if (!part) continue; - definitions = { ...definitions, ...part.definitions, [name]: { ...part, definitions: undefined } }; + definitions = { ...definitions, [name]: { ...part } }; } fs.writeFileSync(schemaPath, JSON.stringify(definitions, null, 4)); } +// #/definitions/ main(); function walk(dir: string) { diff --git a/api/src/routes/auth/login.ts b/api/src/routes/auth/login.ts index 2e2f763d..f672658a 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 "@fosscord/api"; +import { FieldErrors, route } from "@fosscord/api"; import bcrypt from "bcrypt"; import jwt from "jsonwebtoken"; import { Config, User } from "@fosscord/util"; @@ -8,67 +8,65 @@ import { adjustEmail } from "./register"; const router: Router = Router(); export default router; -router.post( - "/", - check({ - login: new Length(String, 2, 100), // email or telephone - password: new Length(String, 8, 72), - $undelete: Boolean, - $captcha_key: String, - $login_source: String, - $gift_code_sku_id: String - }), - async (req: Request, res: Response) => { - const { login, password, captcha_key, undelete } = req.body; - const email = adjustEmail(login); - console.log("login", email); - - const config = Config.get(); - - if (config.login.requireCaptcha && config.security.captcha.enabled) { - if (!captcha_key) { - const { sitekey, service } = config.security.captcha; - return res.status(400).json({ - captcha_key: ["captcha-required"], - captcha_sitekey: sitekey, - captcha_service: service - }); - } - - // TODO: check captcha - } +export interface LoginSchema { + login: string; + password: string; + undelete?: boolean; + captcha_key?: string; + login_source?: string; + gift_code_sku_id?: string; +} - const user = await User.findOneOrFail({ - where: [{ phone: login }, { email: login }], - select: ["data", "id", "disabled", "deleted", "settings"] - }).catch((e) => { - throw FieldErrors({ login: { message: req.t("auth:login.INVALID_LOGIN"), code: "INVALID_LOGIN" } }); - }); - - if (undelete) { - // undelete refers to un'disable' here - if (user.disabled) await User.update({ id: user.id }, { disabled: false }); - if (user.deleted) await User.update({ id: user.id }, { deleted: false }); - } else { - if (user.deleted) return res.status(400).json({ message: "This account is scheduled for deletion.", code: 20011 }); - if (user.disabled) return res.status(400).json({ message: req.t("auth:login.ACCOUNT_DISABLED"), code: 20013 }); +router.post("/", route({ body: "LoginSchema" }), async (req: Request, res: Response) => { + const { login, password, captcha_key, undelete } = req.body as LoginSchema; + const email = adjustEmail(login); + console.log("login", email); + + const config = Config.get(); + + if (config.login.requireCaptcha && config.security.captcha.enabled) { + if (!captcha_key) { + const { sitekey, service } = config.security.captcha; + return res.status(400).json({ + captcha_key: ["captcha-required"], + captcha_sitekey: sitekey, + captcha_service: service + }); } - // the salt is saved in the password refer to bcrypt docs - const same_password = await bcrypt.compare(password, user.data.hash || ""); - if (!same_password) { - throw FieldErrors({ password: { message: req.t("auth:login.INVALID_PASSWORD"), code: "INVALID_PASSWORD" } }); - } + // TODO: check captcha + } - const token = await generateToken(user.id); + const user = await User.findOneOrFail({ + where: [{ phone: login }, { email: login }], + select: ["data", "id", "disabled", "deleted", "settings"] + }).catch((e) => { + throw FieldErrors({ login: { message: req.t("auth:login.INVALID_LOGIN"), code: "INVALID_LOGIN" } }); + }); - // Notice this will have a different token structure, than discord - // Discord header is just the user id as string, which is not possible with npm-jsonwebtoken package - // https://user-images.githubusercontent.com/6506416/81051916-dd8c9900-8ec2-11ea-8794-daf12d6f31f0.png + if (undelete) { + // undelete refers to un'disable' here + if (user.disabled) await User.update({ id: user.id }, { disabled: false }); + if (user.deleted) await User.update({ id: user.id }, { deleted: false }); + } else { + if (user.deleted) return res.status(400).json({ message: "This account is scheduled for deletion.", code: 20011 }); + if (user.disabled) return res.status(400).json({ message: req.t("auth:login.ACCOUNT_DISABLED"), code: 20013 }); + } - res.json({ token, settings: user.settings }); + // the salt is saved in the password refer to bcrypt docs + const same_password = await bcrypt.compare(password, user.data.hash || ""); + if (!same_password) { + throw FieldErrors({ password: { message: req.t("auth:login.INVALID_PASSWORD"), code: "INVALID_PASSWORD" } }); } -); + + const token = await generateToken(user.id); + + // Notice this will have a different token structure, than discord + // Discord header is just the user id as string, which is not possible with npm-jsonwebtoken package + // https://user-images.githubusercontent.com/6506416/81051916-dd8c9900-8ec2-11ea-8794-daf12d6f31f0.png + + res.json({ token, settings: user.settings }); +}); export async function generateToken(id: string) { const iat = Math.floor(Date.now() / 1000); diff --git a/api/src/routes/auth/register.ts b/api/src/routes/auth/register.ts index d3c85778..e0af1d6d 100644 --- a/api/src/routes/auth/register.ts +++ b/api/src/routes/auth/register.ts @@ -1,7 +1,7 @@ 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 "@fosscord/api"; +import { EMAIL_REGEX, FieldErrors, route } from "@fosscord/api"; import "missing-native-js-functions"; import { generateToken } from "./login"; import { getIpAdress, IPAnalysis, isProxy } from "@fosscord/api"; @@ -10,208 +10,215 @@ import { In } from "typeorm"; const router: Router = Router(); -router.post( - "/", - check({ - username: new Length(String, 2, 32), - // TODO: check min password length in config - // prevent Denial of Service with max length of 72 chars - password: new Length(String, 8, 72), - consent: Boolean, - $email: new Length(Email, 5, 100), - $fingerprint: String, - $invite: String, - $date_of_birth: Date, // "2000-04-03" - $gift_code_sku_id: String, - $captcha_key: String - }), - async (req: Request, res: Response) => { - const { - email, - username, - password, - consent, - fingerprint, - invite, - date_of_birth, - gift_code_sku_id, // ? what is this - captcha_key - } = req.body; - - // get register Config - const { register, security } = Config.get(); - const ip = getIpAdress(req); - - if (register.blockProxies) { - if (isProxy(await IPAnalysis(ip))) { - console.log(`proxy ${ip} blocked from registration`); - throw new HTTPError("Your IP is blocked from registration"); - } +export interface RegisterSchema { + /** + * @minLength 2 + * @maxLength 32 + */ + username: string; + /** + * @minLength 1 + * @maxLength 72 + */ + password: string; // TODO: use password strength of config + consent: boolean; + /** + * @TJS-format email + */ + email?: string; + fingerprint?: string; + invite?: string; + date_of_birth?: Date; // "2000-04-03" + gift_code_sku_id?: string; + captcha_key?: string; +} + +router.post("/", route({ body: "RegisterSchema" }), async (req: Request, res: Response) => { + const { + email, + username, + password, + consent, + fingerprint, + invite, + date_of_birth, + gift_code_sku_id, // ? what is this + captcha_key + } = req.body; + + // get register Config + const { register, security } = Config.get(); + const ip = getIpAdress(req); + + if (register.blockProxies) { + if (isProxy(await IPAnalysis(ip))) { + console.log(`proxy ${ip} blocked from registration`); + throw new HTTPError("Your IP is blocked from registration"); } + } - console.log("register", req.body.email, req.body.username, ip); - // TODO: automatically join invite - // TODO: gift_code_sku_id? - // TODO: check password strength + console.log("register", req.body.email, req.body.username, ip); + // TODO: automatically join invite + // TODO: gift_code_sku_id? + // TODO: check password strength - // adjusted_email will be slightly modified version of the user supplied email -> e.g. protection against GMail Trick - let adjusted_email = adjustEmail(email); + // adjusted_email will be slightly modified version of the user supplied email -> e.g. protection against GMail Trick + let adjusted_email = adjustEmail(email); - // adjusted_password will be the hash of the password - let adjusted_password = ""; + // adjusted_password will be the hash of the password + let adjusted_password = ""; - // trim special uf8 control characters -> Backspace, Newline, ... - let adjusted_username = trimSpecial(username); + // trim special uf8 control characters -> Backspace, Newline, ... + let adjusted_username = trimSpecial(username); - // discriminator will be randomly generated - let discriminator = ""; + // discriminator will be randomly generated + let discriminator = ""; - // check if registration is allowed - if (!register.allowNewRegistration) { - throw FieldErrors({ - email: { code: "REGISTRATION_DISABLED", message: req.t("auth:register.REGISTRATION_DISABLED") } - }); - } + // check if registration is allowed + if (!register.allowNewRegistration) { + throw FieldErrors({ + email: { code: "REGISTRATION_DISABLED", message: req.t("auth:register.REGISTRATION_DISABLED") } + }); + } - // check if the user agreed to the Terms of Service - if (!consent) { - throw FieldErrors({ - consent: { code: "CONSENT_REQUIRED", message: req.t("auth:register.CONSENT_REQUIRED") } - }); - } + // check if the user agreed to the Terms of Service + if (!consent) { + throw FieldErrors({ + consent: { code: "CONSENT_REQUIRED", message: req.t("auth:register.CONSENT_REQUIRED") } + }); + } - // 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") } - }); - } + // 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 (!adjusted_email) throw FieldErrors({ email: { code: "INVALID_EMAIL", message: req.t("auth:register.INVALID_EMAIL") } }); + if (email) { + // replace all dots and chars after +, if its a gmail.com email + if (!adjusted_email) throw FieldErrors({ email: { code: "INVALID_EMAIL", message: req.t("auth:register.INVALID_EMAIL") } }); - // check if there is already an account with this email - const exists = await User.findOneOrFail({ email: adjusted_email }).catch((e) => {}); + // check if there is already an account with this email + const exists = await User.findOneOrFail({ email: adjusted_email }).catch((e) => {}); - if (exists) { - throw FieldErrors({ - email: { - code: "EMAIL_ALREADY_REGISTERED", - message: req.t("auth:register.EMAIL_ALREADY_REGISTERED") - } - }); - } - } else if (register.email.necessary) { + if (exists) { throw FieldErrors({ - email: { code: "BASE_TYPE_REQUIRED", message: req.t("common:field.BASE_TYPE_REQUIRED") } + email: { + code: "EMAIL_ALREADY_REGISTERED", + message: req.t("auth:register.EMAIL_ALREADY_REGISTERED") + } }); } + } else if (register.email.necessary) { + throw FieldErrors({ + email: { code: "BASE_TYPE_REQUIRED", message: req.t("common:field.BASE_TYPE_REQUIRED") } + }); + } + + if (register.dateOfBirth.necessary && !date_of_birth) { + throw FieldErrors({ + date_of_birth: { code: "BASE_TYPE_REQUIRED", message: req.t("common:field.BASE_TYPE_REQUIRED") } + }); + } else if (register.dateOfBirth.minimum) { + const minimum = new Date(); + minimum.setFullYear(minimum.getFullYear() - register.dateOfBirth.minimum); - if (register.dateOfBirth.necessary && !date_of_birth) { + // higher is younger + if (date_of_birth > minimum) { throw FieldErrors({ - date_of_birth: { code: "BASE_TYPE_REQUIRED", message: req.t("common:field.BASE_TYPE_REQUIRED") } + date_of_birth: { + code: "DATE_OF_BIRTH_UNDERAGE", + message: req.t("auth:register.DATE_OF_BIRTH_UNDERAGE", { years: register.dateOfBirth.minimum }) + } }); - } else if (register.dateOfBirth.minimum) { - const minimum = new Date(); - minimum.setFullYear(minimum.getFullYear() - register.dateOfBirth.minimum); - - // higher is younger - if (date_of_birth > minimum) { - throw FieldErrors({ - date_of_birth: { - code: "DATE_OF_BIRTH_UNDERAGE", - message: req.t("auth:register.DATE_OF_BIRTH_UNDERAGE", { years: register.dateOfBirth.minimum }) - } - }); - } - } - - if (!register.allowMultipleAccounts) { - // TODO: check if fingerprint was eligible generated - const exists = await User.findOne({ where: { fingerprints: In(fingerprint) } }); - - if (exists) { - throw FieldErrors({ - email: { - code: "EMAIL_ALREADY_REGISTERED", - message: req.t("auth:register.EMAIL_ALREADY_REGISTERED") - } - }); - } - } - - if (register.requireCaptcha && security.captcha.enabled) { - if (!captcha_key) { - const { sitekey, service } = security.captcha; - return res.status(400).json({ - captcha_key: ["captcha-required"], - captcha_sitekey: sitekey, - captcha_service: service - }); - } - - // TODO: check captcha } + } - // the salt is saved in the password refer to bcrypt docs - adjusted_password = await bcrypt.hash(password, 12); - - let exists; - // randomly generates a discriminator between 1 and 9999 and checks max five times if it already exists - // if it all five times already exists, abort with USERNAME_TOO_MANY_USERS error - // else just continue - // TODO: is there any better way to generate a random discriminator only once, without checking if it already exists in the mongodb database? - for (let tries = 0; tries < 5; tries++) { - discriminator = Math.randomIntBetween(1, 9999).toString().padStart(4, "0"); - exists = await User.findOne({ where: { discriminator, username: adjusted_username }, select: ["id"] }); - if (!exists) break; - } + if (!register.allowMultipleAccounts) { + // TODO: check if fingerprint was eligible generated + const exists = await User.findOne({ where: { fingerprints: In(fingerprint) } }); if (exists) { throw FieldErrors({ - username: { - code: "USERNAME_TOO_MANY_USERS", - message: req.t("auth:register.USERNAME_TOO_MANY_USERS") + email: { + code: "EMAIL_ALREADY_REGISTERED", + message: req.t("auth:register.EMAIL_ALREADY_REGISTERED") } }); } + } + + if (register.requireCaptcha && security.captcha.enabled) { + if (!captcha_key) { + const { sitekey, service } = security.captcha; + return res.status(400).json({ + captcha_key: ["captcha-required"], + captcha_sitekey: sitekey, + captcha_service: service + }); + } + + // TODO: check captcha + } - // TODO: save date_of_birth - // appearently discord doesn't save the date of birth and just calculate if nsfw is allowed - // if nsfw_allowed is null/undefined it'll require date_of_birth to set it to true/false - - const user = await new User({ - created_at: new Date(), - username: adjusted_username, - discriminator, - id: Snowflake.generate(), - bot: false, - system: false, - desktop: false, - mobile: false, - premium: true, - premium_type: 2, - bio: "", - mfa_enabled: false, - verified: false, - disabled: false, - deleted: false, - email: adjusted_email, - nsfw_allowed: true, // TODO: depending on age - public_flags: "0", - flags: "0", // TODO: generate - data: { - hash: adjusted_password, - valid_tokens_since: new Date() - }, - settings: { ...defaultSettings, locale: req.language || "en-US" }, - fingerprints: [] - }).save(); - - return res.json({ token: await generateToken(user.id) }); + // the salt is saved in the password refer to bcrypt docs + adjusted_password = await bcrypt.hash(password, 12); + + let exists; + // randomly generates a discriminator between 1 and 9999 and checks max five times if it already exists + // if it all five times already exists, abort with USERNAME_TOO_MANY_USERS error + // else just continue + // TODO: is there any better way to generate a random discriminator only once, without checking if it already exists in the mongodb database? + for (let tries = 0; tries < 5; tries++) { + discriminator = Math.randomIntBetween(1, 9999).toString().padStart(4, "0"); + exists = await User.findOne({ where: { discriminator, username: adjusted_username }, select: ["id"] }); + if (!exists) break; } -); + + if (exists) { + throw FieldErrors({ + username: { + code: "USERNAME_TOO_MANY_USERS", + message: req.t("auth:register.USERNAME_TOO_MANY_USERS") + } + }); + } + + // TODO: save date_of_birth + // appearently discord doesn't save the date of birth and just calculate if nsfw is allowed + // if nsfw_allowed is null/undefined it'll require date_of_birth to set it to true/false + + const user = await new User({ + created_at: new Date(), + username: adjusted_username, + discriminator, + id: Snowflake.generate(), + bot: false, + system: false, + desktop: false, + mobile: false, + premium: true, + premium_type: 2, + bio: "", + mfa_enabled: false, + verified: false, + disabled: false, + deleted: false, + email: adjusted_email, + nsfw_allowed: true, // TODO: depending on age + public_flags: "0", + flags: "0", // TODO: generate + data: { + hash: adjusted_password, + valid_tokens_since: new Date() + }, + settings: { ...defaultSettings, locale: req.language || "en-US" }, + fingerprints: [] + }).save(); + + return res.json({ token: await generateToken(user.id) }); +}); export function adjustEmail(email: string): string | undefined { // body parser already checked if it is a valid email diff --git a/api/src/routes/channels/#channel_id/index.ts b/api/src/routes/channels/#channel_id/index.ts index 46554d70..02ac9884 100644 --- a/api/src/routes/channels/#channel_id/index.ts +++ b/api/src/routes/channels/#channel_id/index.ts @@ -1,48 +1,59 @@ -import { ChannelDeleteEvent, Channel, ChannelUpdateEvent, emitEvent, getPermission } from "@fosscord/util"; +import { ChannelDeleteEvent, Channel, ChannelUpdateEvent, emitEvent, ChannelType, ChannelPermissionOverwriteType } from "@fosscord/util"; import { Router, Response, Request } from "express"; -import { HTTPError } from "lambert-server"; -import { ChannelModifySchema } from "../../../schema/Channel"; -import { check } from "@fosscord/api"; +import { route } from "@fosscord/api"; const router: Router = Router(); // TODO: delete channel // TODO: Get channel -router.get("/", async (req: Request, res: Response) => { +router.get("/", route({ permission: "VIEW_CHANNEL" }), async (req: Request, res: Response) => { const { channel_id } = req.params; const channel = await Channel.findOneOrFail({ id: channel_id }); - const permission = await getPermission(req.user_id, channel.guild_id, channel_id); - permission.hasThrow("VIEW_CHANNEL"); - return res.send(channel); }); -router.delete("/", async (req: Request, res: Response) => { +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 permission = await getPermission(req.user_id, channel?.guild_id, channel_id); - permission.hasThrow("MANAGE_CHANNELS"); - // TODO: Dm channel "close" not delete const data = channel; - await emitEvent({ event: "CHANNEL_DELETE", data, channel_id } as ChannelDeleteEvent); - - await Channel.delete({ id: channel_id }); + await Promise.all([emitEvent({ event: "CHANNEL_DELETE", data, channel_id } as ChannelDeleteEvent), Channel.delete({ id: channel_id })]); res.send(data); }); -router.patch("/", check(ChannelModifySchema), async (req: Request, res: Response) => { +export interface ChannelModifySchema { + /** + * @maxLength 100 + */ + name: string; + type: ChannelType; + topic?: string; + bitrate?: number; + user_limit?: number; + rate_limit_per_user?: number; + position?: number; + permission_overwrites?: { + id: string; + type: ChannelPermissionOverwriteType; + allow: bigint; + deny: bigint; + }[]; + parent_id?: string; + id?: string; // is not used (only for guild create) + nsfw?: boolean; + rtc_region?: string; + default_auto_archive_duration?: number; +} + +router.patch("/", route({ body: "ChannelModifySchema", permission: "MANAGE_CHANNELS" }), async (req: Request, res: Response) => { var payload = req.body as ChannelModifySchema; const { channel_id } = req.params; - const permission = await getPermission(req.user_id, undefined, channel_id); - permission.hasThrow("MANAGE_CHANNELS"); - const channel = await Channel.findOneOrFail({ id: channel_id }); channel.assign(payload); diff --git a/api/src/routes/channels/#channel_id/invites.ts b/api/src/routes/channels/#channel_id/invites.ts index c6909fd0..39263185 100644 --- a/api/src/routes/channels/#channel_id/invites.ts +++ b/api/src/routes/channels/#channel_id/invites.ts @@ -1,14 +1,25 @@ import { Router, Request, Response } from "express"; import { HTTPError } from "lambert-server"; -import { check } from "@fosscord/api"; +import { route } 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"; const router: Router = Router(); -router.post("/", check(InviteCreateSchema), async (req: Request, res: Response) => { +export interface InviteCreateSchema { + target_user_id?: string; + target_type?: string; + validate?: string; //? wtf is this + max_age?: number; + max_uses?: number; + temporary?: boolean; + unique?: boolean; + target_user?: string; + target_user_type?: number; +} + +router.post("/", route({ body: "InviteCreateSchema", permission: "CREATE_INSTANT_INVITE" }), async (req: Request, res: Response) => { const { user_id } = req; const { channel_id } = req.params; const channel = await Channel.findOneOrFail({ where: { id: channel_id }, select: ["id", "name", "type", "guild_id"] }); @@ -19,23 +30,6 @@ router.post("/", check(InviteCreateSchema), async (req: Request, res: Response) } const { guild_id } = channel; - const permission = await getPermission(user_id, guild_id, undefined, { - guild_select: [ - "banner", - "description", - "features", - "icon", - "id", - "name", - "nsfw", - "nsfw_level", - "splash", - "vanity_url_code", - "verification_level" - ] as (keyof Guild)[] - }); - permission.hasThrow("CREATE_INSTANT_INVITE"); - const expires_at = new Date(req.body.max_age * 1000 + Date.now()); const invite = await new Invite({ @@ -52,14 +46,14 @@ router.post("/", check(InviteCreateSchema), async (req: Request, res: Response) }).save(); const data = invite.toJSON(); data.inviter = await User.getPublicUser(req.user_id); - data.guild = permission.cache.guild; + data.guild = await Guild.findOne({ id: guild_id }); data.channel = channel; await emitEvent({ event: "INVITE_CREATE", data, guild_id } as InviteCreateEvent); res.status(201).send(data); }); -router.get("/", async (req: Request, res: Response) => { +router.get("/", route({ permission: "MANAGE_CHANNELS" }), async (req: Request, res: Response) => { const { user_id } = req; const { channel_id } = req.params; const channel = await Channel.findOneOrFail({ id: channel_id }); @@ -68,8 +62,6 @@ router.get("/", async (req: Request, res: Response) => { throw new HTTPError("This channel doesn't exist", 404); } const { guild_id } = channel; - const permission = await getPermission(user_id, guild_id); - permission.hasThrow("MANAGE_CHANNELS"); const invites = await Invite.find({ where: { guild_id }, relations: PublicInviteRelation }); 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 aab51484..97d1d19e 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,14 +1,18 @@ import { emitEvent, getPermission, MessageAckEvent, ReadState } from "@fosscord/util"; import { Request, Response, Router } from "express"; - -import { check } from "@fosscord/api"; +import { route } from "@fosscord/api"; const router = Router(); // TODO: check if message exists // TODO: send read state event to all channel members -router.post("/", check({ $manual: Boolean, $mention_count: Number }), async (req: Request, res: Response) => { +export interface MessageAcknowledgeSchema { + manual?: boolean; + mention_count?: number; +} + +router.post("/", route({ body: "MessageAcknowledgeSchema" }), async (req: Request, res: Response) => { const { channel_id, message_id } = req.params; const permission = await getPermission(req.user_id, undefined, channel_id); 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 e9588bd3..d0f780db 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,12 +1,13 @@ import { Channel, emitEvent, getPermission, MessageDeleteEvent, Message, MessageUpdateEvent } from "@fosscord/util"; import { Router, Response, Request } from "express"; -import { MessageCreateSchema } from "../../../../../schema/Message"; -import { check } from "@fosscord/api"; +import { route } from "@fosscord/api"; import { handleMessage, postHandleMessage } from "@fosscord/api"; +import { MessageCreateSchema } from "../index"; const router = Router(); +// TODO: message content/embed string length limit -router.patch("/", check(MessageCreateSchema), async (req: Request, res: Response) => { +router.patch("/", route({ body: "MessageCreateSchema", permission: "SEND_MESSAGES" }), async (req: Request, res: Response) => { const { message_id, channel_id } = req.params; var body = req.body as MessageCreateSchema; @@ -47,14 +48,17 @@ router.patch("/", check(MessageCreateSchema), async (req: Request, res: Response // TODO: delete attachments in message -router.delete("/", async (req: Request, res: Response) => { +// permission check only if deletes messagr from other user +router.delete("/", route({}), async (req: Request, res: Response) => { const { message_id, channel_id } = req.params; const channel = await Channel.findOneOrFail({ id: channel_id }); const message = await Message.findOneOrFail({ id: message_id }); - const permission = await getPermission(req.user_id, channel.guild_id, channel_id); - if (message.author_id !== req.user_id) permission.hasThrow("MANAGE_MESSAGES"); + if (message.author_id !== req.user_id) { + const permission = await getPermission(req.user_id, channel.guild_id, channel_id); + permission.hasThrow("MANAGE_MESSAGES"); + } await Message.delete({ id: message_id }); diff --git a/api/src/routes/channels/#channel_id/messages/#message_id/reactions.ts b/api/src/routes/channels/#channel_id/messages/#message_id/reactions.ts index f60484b5..f2b83d40 100644 --- a/api/src/routes/channels/#channel_id/messages/#message_id/reactions.ts +++ b/api/src/routes/channels/#channel_id/messages/#message_id/reactions.ts @@ -13,6 +13,7 @@ import { PublicUserProjection, User } from "@fosscord/util"; +import { route } from "@fosscord/api"; import { Router, Response, Request } from "express"; import { HTTPError } from "lambert-server"; import { In } from "typeorm"; @@ -35,14 +36,11 @@ function getEmoji(emoji: string): PartialEmoji { }; } -router.delete("/", async (req: Request, res: Response) => { +router.delete("/", route({ permission: "MANAGE_MESSAGES" }), async (req: Request, res: Response) => { const { message_id, channel_id } = req.params; const channel = await Channel.findOneOrFail({ id: channel_id }); - const permissions = await getPermission(req.user_id, undefined, channel_id); - permissions.hasThrow("MANAGE_MESSAGES"); - await Message.update({ id: message_id, channel_id }, { reactions: [] }); await emitEvent({ @@ -58,13 +56,10 @@ router.delete("/", async (req: Request, res: Response) => { res.sendStatus(204); }); -router.delete("/:emoji", async (req: Request, res: Response) => { +router.delete("/:emoji", route({ permission: "MANAGE_MESSAGES" }), async (req: Request, res: Response) => { const { message_id, channel_id } = req.params; const emoji = getEmoji(req.params.emoji); - const permissions = await getPermission(req.user_id, undefined, channel_id); - permissions.hasThrow("MANAGE_MESSAGES"); - const message = await Message.findOneOrFail({ id: message_id, channel_id }); const already_added = message.reactions.find((x) => (x.emoji.id === emoji.id && emoji.id) || x.emoji.name === emoji.name); @@ -88,7 +83,7 @@ router.delete("/:emoji", async (req: Request, res: Response) => { res.sendStatus(204); }); -router.get("/:emoji", async (req: Request, res: Response) => { +router.get("/:emoji", route({ permission: "VIEW_CHANNEL" }), async (req: Request, res: Response) => { const { message_id, channel_id } = req.params; const emoji = getEmoji(req.params.emoji); @@ -96,9 +91,6 @@ router.get("/:emoji", async (req: Request, res: Response) => { const reaction = message.reactions.find((x) => (x.emoji.id === emoji.id && emoji.id) || x.emoji.name === emoji.name); if (!reaction) throw new HTTPError("Reaction not found", 404); - const permissions = await getPermission(req.user_id, undefined, channel_id); - permissions.hasThrow("VIEW_CHANNEL"); - const users = await User.find({ where: { id: In(reaction.user_ids) @@ -109,7 +101,7 @@ router.get("/:emoji", async (req: Request, res: Response) => { res.json(users); }); -router.put("/:emoji/:user_id", async (req: Request, res: Response) => { +router.put("/:emoji/:user_id", route({ permission: "READ_MESSAGE_HISTORY" }), async (req: Request, res: Response) => { const { message_id, channel_id, user_id } = req.params; if (user_id !== "@me") throw new HTTPError("Invalid user"); const emoji = getEmoji(req.params.emoji); @@ -118,13 +110,11 @@ router.put("/:emoji/:user_id", async (req: Request, res: Response) => { const message = await Message.findOneOrFail({ id: message_id, channel_id }); const already_added = message.reactions.find((x) => (x.emoji.id === emoji.id && emoji.id) || x.emoji.name === emoji.name); - const permissions = await getPermission(req.user_id, undefined, channel_id); - permissions.hasThrow("READ_MESSAGE_HISTORY"); - if (!already_added) permissions.hasThrow("ADD_REACTIONS"); + if (!already_added) req.permission!.hasThrow("ADD_REACTIONS"); if (emoji.id) { const external_emoji = await Emoji.findOneOrFail({ id: emoji.id }); - if (!already_added) permissions.hasThrow("USE_EXTERNAL_EMOJIS"); + if (!already_added) req.permission!.hasThrow("USE_EXTERNAL_EMOJIS"); emoji.animated = external_emoji.animated; emoji.name = external_emoji.name; } @@ -154,7 +144,7 @@ router.put("/:emoji/:user_id", async (req: Request, res: Response) => { res.sendStatus(204); }); -router.delete("/:emoji/:user_id", async (req: Request, res: Response) => { +router.delete("/:emoji/:user_id", route({}), async (req: Request, res: Response) => { var { message_id, channel_id, user_id } = req.params; const emoji = getEmoji(req.params.emoji); @@ -162,10 +152,11 @@ router.delete("/:emoji/:user_id", async (req: Request, res: Response) => { const channel = await Channel.findOneOrFail({ id: channel_id }); const message = await Message.findOneOrFail({ id: message_id, channel_id }); - const permissions = await getPermission(req.user_id, undefined, channel_id); - if (user_id === "@me") user_id = req.user_id; - else permissions.hasThrow("MANAGE_MESSAGES"); + else { + const permissions = await getPermission(req.user_id, undefined, channel_id); + permissions.hasThrow("MANAGE_MESSAGES"); + } const already_added = message.reactions.find((x) => (x.emoji.id === emoji.id && emoji.id) || x.emoji.name === emoji.name); if (!already_added || !already_added.user_ids.includes(user_id)) throw new HTTPError("Reaction not found", 404); 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 5d7566e1..a0fe7cc0 100644 --- a/api/src/routes/channels/#channel_id/messages/bulk-delete.ts +++ b/api/src/routes/channels/#channel_id/messages/bulk-delete.ts @@ -1,18 +1,21 @@ import { Router, Response, Request } from "express"; import { Channel, Config, emitEvent, getPermission, MessageDeleteBulkEvent, Message } from "@fosscord/util"; import { HTTPError } from "lambert-server"; - -import { check } from "@fosscord/api"; +import { route } from "@fosscord/api"; import { In } from "typeorm"; const router: Router = Router(); export default router; +export interface BulkDeleteSchema { + messages: string[]; +} + // TODO: should users be able to bulk delete messages or only bots? // TODO: should this request fail, if you provide messages older than 14 days/invalid ids? // https://discord.com/developers/docs/resources/channel#bulk-delete-messages -router.post("/", check({ messages: [String] }), async (req: Request, res: Response) => { +router.post("/", route({ body: "BulkDeleteSchema" }), async (req: Request, res: Response) => { const { channel_id } = req.params; const channel = await Channel.findOneOrFail({ id: channel_id }); if (!channel.guild_id) throw new HTTPError("Can't bulk delete dm channel messages", 400); diff --git a/api/src/routes/channels/#channel_id/messages/index.ts b/api/src/routes/channels/#channel_id/messages/index.ts index 591ebbbe..11334367 100644 --- a/api/src/routes/channels/#channel_id/messages/index.ts +++ b/api/src/routes/channels/#channel_id/messages/index.ts @@ -1,10 +1,8 @@ import { Router, Response, Request } from "express"; -import { Attachment, Channel, ChannelType, getPermission, Message } from "@fosscord/util"; +import { Attachment, Channel, ChannelType, Embed, getPermission, Message } from "@fosscord/util"; import { HTTPError } from "lambert-server"; -import { MessageCreateSchema } from "../../../../schema/Message"; -import { check, instanceOf, Length } from "@fosscord/api"; +import { instanceOf, Length, route } from "@fosscord/api"; import multer from "multer"; -import { Query } from "mongoose"; import { sendMessage } from "@fosscord/api"; import { uploadFile } from "@fosscord/api"; import { FindManyOptions, LessThan, MoreThan } from "typeorm"; @@ -31,6 +29,30 @@ export function isTextChannel(type: ChannelType): boolean { } } +export interface MessageCreateSchema { + content?: string; + nonce?: string; + tts?: boolean; + flags?: string; + embeds?: Embed[]; + embed?: Embed; + // TODO: ^ embed is deprecated in favor of embeds (https://discord.com/developers/docs/resources/channel#message-object) + allowed_mentions?: { + parse?: string[]; + roles?: string[]; + users?: string[]; + replied_user?: boolean; + }; + message_reference?: { + message_id: string; + channel_id: string; + guild_id?: string; + fail_if_not_exists?: boolean; + }; + payload_json?: string; + file?: any; +} + // https://discord.com/developers/docs/resources/channel#create-message // get messages router.get("/", async (req: Request, res: Response) => { @@ -109,39 +131,44 @@ const messageUpload = multer({ // TODO: check allowed_mentions // Send message -router.post("/", messageUpload.single("file"), async (req: Request, res: Response) => { - const { channel_id } = req.params; - var body = req.body as MessageCreateSchema; - const attachments: Attachment[] = []; - - if (req.file) { - try { - const file = await uploadFile(`/attachments/${channel_id}`, req.file); - attachments.push({ ...file, proxy_url: file.url }); - } catch (error) { - return res.status(400).json(error); +router.post( + "/", + messageUpload.single("file"), + async (req, res, next) => { + if (req.body.payload_json) { + req.body = JSON.parse(req.body.payload_json); } - } - if (body.payload_json) { - body = JSON.parse(body.payload_json); - } + next(); + }, + route({ body: "MessageCreateSchema", permission: "SEND_MESSAGES" }), + async (req: Request, res: Response) => { + const { channel_id } = req.params; + var body = req.body as MessageCreateSchema; + const attachments: Attachment[] = []; + + if (req.file) { + try { + const file = await uploadFile(`/attachments/${req.params.channel_id}`, req.file); + attachments.push({ ...file, proxy_url: file.url }); + } catch (error) { + return res.status(400).json(error); + } + } - const errors = instanceOf(MessageCreateSchema, body, { req }); - if (errors !== true) throw errors; - - const embeds = []; - if (body.embed) embeds.push(body.embed); - const data = await sendMessage({ - ...body, - type: 0, - pinned: false, - author_id: req.user_id, - embeds, - channel_id, - attachments, - edited_timestamp: undefined - }); - - return res.json(data); -}); + const embeds = []; + if (body.embed) embeds.push(body.embed); + const data = await sendMessage({ + ...body, + type: 0, + pinned: false, + author_id: req.user_id, + embeds, + channel_id, + attachments, + edited_timestamp: undefined + }); + + return res.json(data); + } +); diff --git a/api/src/routes/channels/#channel_id/permissions.ts b/api/src/routes/channels/#channel_id/permissions.ts index 0465ca31..827e46f2 100644 --- a/api/src/routes/channels/#channel_id/permissions.ts +++ b/api/src/routes/channels/#channel_id/permissions.ts @@ -2,61 +2,61 @@ import { Channel, ChannelPermissionOverwrite, ChannelUpdateEvent, emitEvent, get import { Router, Response, Request } from "express"; import { HTTPError } from "lambert-server"; -import { check } from "@fosscord/api"; +import { check, route } 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) -router.put("/:overwrite_id", check({ allow: String, deny: String, type: Number, id: String }), async (req: Request, res: Response) => { - const { channel_id, overwrite_id } = req.params; - const body = req.body as { allow: bigint; deny: bigint; type: number; id: string }; +export interface ChannelPermissionOverwriteSchema extends ChannelPermissionOverwrite {} - var channel = await Channel.findOneOrFail({ id: channel_id }); - if (!channel.guild_id) throw new HTTPError("Channel not found", 404); +router.put( + "/:overwrite_id", + route({ body: "ChannelPermissionOverwriteSchema", permission: "MANAGE_ROLES" }), + async (req: Request, res: Response) => { + const { channel_id, overwrite_id } = req.params; + const body = req.body as { allow: bigint; deny: bigint; type: number; id: string }; - const permissions = await getPermission(req.user_id, channel.guild_id, channel_id); - permissions.hasThrow("MANAGE_ROLES"); + var channel = await Channel.findOneOrFail({ id: channel_id }); + if (!channel.guild_id) throw new HTTPError("Channel not found", 404); - if (body.type === 0) { - if (!(await Role.count({ id: overwrite_id }))) throw new HTTPError("role not found", 404); - } else if (body.type === 1) { - if (!(await Member.count({ id: overwrite_id }))) throw new HTTPError("user not found", 404); - } else throw new HTTPError("type not supported", 501); + if (body.type === 0) { + if (!(await Role.count({ id: overwrite_id }))) throw new HTTPError("role not found", 404); + } else if (body.type === 1) { + if (!(await Member.count({ id: overwrite_id }))) throw new HTTPError("user not found", 404); + } else throw new HTTPError("type not supported", 501); - // @ts-ignore - var overwrite: ChannelPermissionOverwrite = channel.permission_overwrites.find((x) => x.id === overwrite_id); - if (!overwrite) { // @ts-ignore - overwrite = { - id: overwrite_id, - type: body.type, - allow: body.allow, - deny: body.deny - }; - channel.permission_overwrites.push(overwrite); + var overwrite: ChannelPermissionOverwrite = channel.permission_overwrites.find((x) => x.id === overwrite_id); + if (!overwrite) { + // @ts-ignore + overwrite = { + id: overwrite_id, + type: body.type, + allow: body.allow, + deny: body.deny + }; + channel.permission_overwrites.push(overwrite); + } + overwrite.allow = body.allow; + overwrite.deny = body.deny; + + await Promise.all([ + channel.save(), + emitEvent({ + event: "CHANNEL_UPDATE", + channel_id, + data: channel + } as ChannelUpdateEvent) + ]); + + return res.sendStatus(204); } - overwrite.allow = body.allow; - overwrite.deny = body.deny; - - // @ts-ignore - channel = await Channel.findOneOrFailAndUpdate({ id: channel_id }, channel, { new: true }); - - await emitEvent({ - event: "CHANNEL_UPDATE", - channel_id, - data: channel - } as ChannelUpdateEvent); - - return res.sendStatus(204); -}); +); // TODO: check permission hierarchy -router.delete("/:overwrite_id", async (req: Request, res: Response) => { +router.delete("/:overwrite_id", route({ permission: "MANAGE_ROLES" }), async (req: Request, res: Response) => { const { channel_id, overwrite_id } = req.params; - const permissions = await getPermission(req.user_id, undefined, channel_id); - permissions.hasThrow("MANAGE_ROLES"); - const channel = await Channel.findOneOrFail({ id: channel_id }); if (!channel.guild_id) throw new HTTPError("Channel not found", 404); diff --git a/api/src/routes/channels/#channel_id/pins.ts b/api/src/routes/channels/#channel_id/pins.ts index 33309c86..e71e659f 100644 --- a/api/src/routes/channels/#channel_id/pins.ts +++ b/api/src/routes/channels/#channel_id/pins.ts @@ -1,19 +1,26 @@ -import { Channel, ChannelPinsUpdateEvent, Config, emitEvent, getPermission, Message, MessageUpdateEvent } from "@fosscord/util"; +import { + Channel, + ChannelPinsUpdateEvent, + Config, + emitEvent, + getPermission, + Message, + MessageUpdateEvent, + DiscordApiErrors +} from "@fosscord/util"; import { Router, Request, Response } from "express"; import { HTTPError } from "lambert-server"; -import { DiscordApiErrors } from "@fosscord/util"; +import { route } from "@fosscord/api"; const router: Router = Router(); -router.put("/:message_id", async (req: Request, res: Response) => { +router.put("/:message_id", route({ permission: "VIEW_CHANNEL" }), async (req: Request, res: Response) => { const { channel_id, message_id } = req.params; const message = await Message.findOneOrFail({ id: message_id }); - const permission = await getPermission(req.user_id, message.guild_id, channel_id); - permission.hasThrow("VIEW_CHANNEL"); // * in dm channels anyone can pin messages -> only check for guilds - if (message.guild_id) permission.hasThrow("MANAGE_MESSAGES"); + if (message.guild_id) req.permission!.hasThrow("MANAGE_MESSAGES"); const pinned_count = await Message.count({ channel: { id: channel_id }, pinned: true }); const { maxPins } = Config.get().limits.channel; @@ -26,7 +33,6 @@ router.put("/:message_id", async (req: Request, res: Response) => { channel_id, data: message } as MessageUpdateEvent), - emitEvent({ event: "CHANNEL_PINS_UPDATE", channel_id, @@ -41,14 +47,11 @@ router.put("/:message_id", async (req: Request, res: Response) => { res.sendStatus(204); }); -router.delete("/:message_id", async (req: Request, res: Response) => { +router.delete("/:message_id", route({ permission: "VIEW_CHANNEL" }), async (req: Request, res: Response) => { const { channel_id, message_id } = req.params; const channel = await Channel.findOneOrFail({ id: channel_id }); - - const permission = await getPermission(req.user_id, channel.guild_id, channel_id); - permission.hasThrow("VIEW_CHANNEL"); - if (channel.guild_id) permission.hasThrow("MANAGE_MESSAGES"); + if (channel.guild_id) req.permission!.hasThrow("MANAGE_MESSAGES"); const message = await Message.findOneOrFail({ id: message_id }); message.pinned = false; @@ -76,13 +79,9 @@ router.delete("/:message_id", async (req: Request, res: Response) => { res.sendStatus(204); }); -router.get("/", async (req: Request, res: Response) => { +router.get("/", route({ permission: ["READ_MESSAGE_HISTORY"] }), async (req: Request, res: Response) => { const { channel_id } = req.params; - const channel = await Channel.findOneOrFail({ id: channel_id }); - const permission = await getPermission(req.user_id, channel.guild_id, channel_id); - permission.hasThrow("VIEW_CHANNEL"); - let pins = await Message.find({ channel_id: channel_id, pinned: true }); res.send(pins); diff --git a/api/src/routes/channels/#channel_id/typing.ts b/api/src/routes/channels/#channel_id/typing.ts index f1fb3c86..ad973bca 100644 --- a/api/src/routes/channels/#channel_id/typing.ts +++ b/api/src/routes/channels/#channel_id/typing.ts @@ -1,11 +1,10 @@ import { Channel, emitEvent, Member, TypingStartEvent } from "@fosscord/util"; +import { route } from "@fosscord/api"; import { Router, Request, Response } from "express"; -import { HTTPError } from "lambert-server"; - const router: Router = Router(); -router.post("/", async (req: Request, res: Response) => { +router.post("/", route({ permission: "SEND_MESSAGES" }), async (req: Request, res: Response) => { const { channel_id } = req.params; const user_id = req.user_id; const timestamp = Date.now(); @@ -24,6 +23,7 @@ router.post("/", async (req: Request, res: Response) => { guild_id: channel.guild_id } } as TypingStartEvent); + res.sendStatus(204); }); diff --git a/api/src/routes/channels/#channel_id/webhooks.ts b/api/src/routes/channels/#channel_id/webhooks.ts index 821a62db..f84dfcc5 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 "@fosscord/api"; +import { check, Length, route } from "@fosscord/api"; import { Channel, Config, getPermission, trimSpecial, Webhook } from "@fosscord/util"; import { HTTPError } from "lambert-server"; import { isTextChannel } from "./messages/index"; @@ -7,9 +7,16 @@ import { DiscordApiErrors } from "@fosscord/util"; const router: Router = Router(); // TODO: webhooks +export interface WebhookCreateSchema { + /** + * @maxLength 80 + */ + name: string; + avatar: string; +} // TODO: use Image Data Type for avatar instead of String -router.post("/", check({ name: new Length(String, 1, 80), $avatar: String }), async (req: Request, res: Response) => { +router.post("/", route({ body: "WebhookCreateSchema", permission: "MANAGE_WEBHOOKS" }), async (req: Request, res: Response) => { const channel_id = req.params.channel_id; const channel = await Channel.findOneOrFail({ id: channel_id }); @@ -20,12 +27,11 @@ router.post("/", check({ name: new Length(String, 1, 80), $avatar: String }), as const { maxWebhooks } = Config.get().limits.channel; if (webhook_count > maxWebhooks) throw DiscordApiErrors.MAXIMUM_WEBHOOKS.withParams(maxWebhooks); - const permission = await getPermission(req.user_id, channel.guild_id); - permission.hasThrow("MANAGE_WEBHOOKS"); - var { avatar, name } = req.body as { name: string; avatar?: string }; name = trimSpecial(name); if (name === "clyde") throw new HTTPError("Invalid name", 400); + + // TODO: save webhook in database and send response }); export default router; diff --git a/api/src/routes/discoverable-guilds.ts b/api/src/routes/discoverable-guilds.ts index 0808727f..f667eb2a 100644 --- a/api/src/routes/discoverable-guilds.ts +++ b/api/src/routes/discoverable-guilds.ts @@ -1,10 +1,10 @@ import { Guild } from "@fosscord/util"; import { Router, Request, Response } from "express"; -import { In } from "typeorm"; +import { route } from "@fosscord/api"; const router = Router(); -router.get("/", async (req: Request, res: Response) => { +router.get("/", route({}), async (req: Request, res: Response) => { const { limit } = req.params; // ! this only works using SQL querys diff --git a/api/src/routes/experiments.ts b/api/src/routes/experiments.ts index 3bdbed62..966ed99c 100644 --- a/api/src/routes/experiments.ts +++ b/api/src/routes/experiments.ts @@ -1,8 +1,9 @@ import { Router, Response, Request } from "express"; +import { route } from "@fosscord/api"; const router = Router(); -router.get("/", (req: Request, res: Response) => { +router.get("/", route({}), (req: Request, res: Response) => { // TODO: res.send({ fingerprint: "", assignments: [] }); }); diff --git a/api/src/routes/gateway.ts b/api/src/routes/gateway.ts index 3120718e..d4208341 100644 --- a/api/src/routes/gateway.ts +++ b/api/src/routes/gateway.ts @@ -1,9 +1,10 @@ import { Config } from "@fosscord/util"; import { Router, Response, Request } from "express"; +import { route } from "@fosscord/api"; const router = Router(); -router.get("/", (req: Request, res: Response) => { +router.get("/", route({}), (req: Request, res: Response) => { const { endpoint } = Config.get().gateway; res.json({ url: endpoint || process.env.GATEWAY || "ws://localhost:3002" }); }); diff --git a/api/src/routes/guilds/#guild_id/bans.ts b/api/src/routes/guilds/#guild_id/bans.ts index 41a97b6a..c7fda9ad 100644 --- a/api/src/routes/guilds/#guild_id/bans.ts +++ b/api/src/routes/guilds/#guild_id/bans.ts @@ -2,7 +2,11 @@ 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, check, route } from "@fosscord/api"; -import { BanCreateSchema } from "@fosscord/api/schema/Ban"; + +export interface BanCreateSchema { + delete_message_days?: string; + reason?: string; +} const router: Router = Router(); router.get("/", route({ permission: "BAN_MEMBERS" }), async (req: Request, res: Response) => { @@ -27,7 +31,7 @@ router.put("/:user_id", route({ body: "BanCreateSchema", permission: "BAN_MEMBER const banned_user = await User.getPublicUser(banned_user_id); if (req.user_id === banned_user_id) throw new HTTPError("You can't ban yourself", 400); - if (req.permission?.cache.guild?.owner_id === banned_user_id) throw new HTTPError("You can't ban the owner", 400); + if (req.permission!.cache.guild?.owner_id === banned_user_id) throw new HTTPError("You can't ban the owner", 400); const ban = new Ban({ user_id: banned_user_id, diff --git a/api/src/routes/guilds/#guild_id/channels.ts b/api/src/routes/guilds/#guild_id/channels.ts index faeecb76..e21327d1 100644 --- a/api/src/routes/guilds/#guild_id/channels.ts +++ b/api/src/routes/guilds/#guild_id/channels.ts @@ -1,9 +1,8 @@ import { Router, Response, Request } from "express"; import { Channel, ChannelUpdateEvent, getPermission, emitEvent } from "@fosscord/util"; import { HTTPError } from "lambert-server"; -import { ChannelModifySchema } from "../../../schema/Channel"; - -import { check } from "@fosscord/api"; +import { check, route } from "@fosscord/api"; +import { ChannelModifySchema } from "../../channels/#channel_id"; const router = Router(); router.get("/", async (req: Request, res: Response) => { @@ -13,10 +12,7 @@ router.get("/", async (req: Request, res: Response) => { res.json(channels); }); -// TODO: check if channel type is permitted -// TODO: check if parent_id exists - -router.post("/", check(ChannelModifySchema), async (req: Request, res: Response) => { +router.post("/", route({ body: "ChannelModifySchema", permission: "MANAGE_CHANNELS" }), async (req: Request, res: Response) => { // creates a new guild channel https://discord.com/developers/docs/resources/guild#create-guild-channel const { guild_id } = req.params; const body = req.body as ChannelModifySchema; @@ -26,45 +22,39 @@ router.post("/", check(ChannelModifySchema), async (req: Request, res: Response) res.status(201).json(channel); }); -// TODO: check if parent_id exists -router.patch( - "/", - check([{ id: String, $position: Number, $lock_permissions: Boolean, $parent_id: String }]), - async (req: Request, res: Response) => { - // changes guild channel position - const { guild_id } = req.params; - const body = req.body as { id: string; position?: number; lock_permissions?: boolean; parent_id?: string }[]; - - const permission = await getPermission(req.user_id, guild_id); - permission.hasThrow("MANAGE_CHANNELS"); - - await Promise.all([ - body.map(async (x) => { - if (!x.position && !x.parent_id) throw new HTTPError(`You need to at least specify position or parent_id`, 400); +export type ChannelReorderSchema = { id: string; position?: number; lock_permissions?: boolean; parent_id?: string }[]; - const opts: any = {}; - if (x.position) opts.position = x.position; - - if (x.parent_id) { - opts.parent_id = x.parent_id; - const parent_channel = await Channel.findOneOrFail({ - where: { id: x.parent_id, guild_id }, - select: ["permission_overwrites"] - }); - if (x.lock_permissions) { - opts.permission_overwrites = parent_channel.permission_overwrites; - } +router.patch("/", route({ body: "ChannelReorderSchema", permission: "MANAGE_CHANNELS" }), async (req: Request, res: Response) => { + // changes guild channel position + const { guild_id } = req.params; + const body = req.body as ChannelReorderSchema; + + await Promise.all([ + body.map(async (x) => { + if (!x.position && !x.parent_id) throw new HTTPError(`You need to at least specify position or parent_id`, 400); + + const opts: any = {}; + if (x.position) opts.position = x.position; + + if (x.parent_id) { + opts.parent_id = x.parent_id; + const parent_channel = await Channel.findOneOrFail({ + where: { id: x.parent_id, guild_id }, + select: ["permission_overwrites"] + }); + if (x.lock_permissions) { + opts.permission_overwrites = parent_channel.permission_overwrites; } + } - await Channel.update({ guild_id, id: x.id }, opts); - const channel = await Channel.findOneOrFail({ guild_id, id: x.id }); + await Channel.update({ guild_id, id: x.id }, opts); + const channel = await Channel.findOneOrFail({ guild_id, id: x.id }); - await emitEvent({ event: "CHANNEL_UPDATE", data: channel, channel_id: x.id, guild_id } as ChannelUpdateEvent); - }) - ]); + await emitEvent({ event: "CHANNEL_UPDATE", data: channel, channel_id: x.id, guild_id } as ChannelUpdateEvent); + }) + ]); - res.sendStatus(204); - } -); + res.sendStatus(204); +}); export default router; diff --git a/api/src/routes/guilds/#guild_id/delete.ts b/api/src/routes/guilds/#guild_id/delete.ts index bbbd1fa4..7c3c5530 100644 --- a/api/src/routes/guilds/#guild_id/delete.ts +++ b/api/src/routes/guilds/#guild_id/delete.ts @@ -1,12 +1,13 @@ import { Channel, emitEvent, GuildDeleteEvent, Guild, Member, Message, Role, Invite, Emoji } from "@fosscord/util"; import { Router, Request, Response } from "express"; import { HTTPError } from "lambert-server"; +import { route } from "@fosscord/api"; const router = Router(); // discord prefixes this route with /delete instead of using the delete method // docs are wrong https://discord.com/developers/docs/resources/guild#delete-guild -router.post("/", async (req: Request, res: Response) => { +router.post("/", route({}), async (req: Request, res: Response) => { var { guild_id } = req.params; const guild = await Guild.findOneOrFail({ where: { id: guild_id }, select: ["owner_id"] }); diff --git a/api/src/routes/guilds/#guild_id/index.ts b/api/src/routes/guilds/#guild_id/index.ts index 244900ec..690d4103 100644 --- a/api/src/routes/guilds/#guild_id/index.ts +++ b/api/src/routes/guilds/#guild_id/index.ts @@ -1,23 +1,36 @@ import { Request, Response, Router } from "express"; import { emitEvent, getPermission, Guild, GuildUpdateEvent, Member } from "@fosscord/util"; import { HTTPError } from "lambert-server"; -import { GuildUpdateSchema } from "../../../schema/Guild"; - -import { check } from "@fosscord/api"; +import { check, route } from "@fosscord/api"; import { handleFile } from "@fosscord/api"; import "missing-native-js-functions"; +import { GuildCreateSchema } from "../index"; const router = Router(); -router.get("/", async (req: Request, res: Response) => { +export interface GuildUpdateSchema extends Omit { + banner?: string; + splash?: string; + description?: string; + features?: string[]; + verification_level?: number; + default_message_notifications?: number; + system_channel_flags?: number; + explicit_content_filter?: number; + public_updates_channel_id?: string; + afk_timeout?: number; + afk_channel_id?: string; + preferred_locale?: string; +} + +router.get("/", route({}), async (req: Request, res: Response) => { const { guild_id } = req.params; - const [guild, member_count, member] = await Promise.all([ + const [guild, member] = await Promise.all([ Guild.findOneOrFail({ id: guild_id }), - Member.count({ guild_id: guild_id, id: req.user_id }), - Member.findOneOrFail({ id: req.user_id }) + Member.findOne({ guild_id: guild_id, id: req.user_id }) ]); - if (!member_count) throw new HTTPError("You are not a member of the guild you are trying to access", 401); + if (!member) throw new HTTPError("You are not a member of the guild you are trying to access", 401); // @ts-ignore guild.joined_at = member?.joined_at; @@ -25,14 +38,11 @@ router.get("/", async (req: Request, res: Response) => { return res.json(guild); }); -router.patch("/", check(GuildUpdateSchema), async (req: Request, res: Response) => { +router.patch("/", route({ body: "GuildUpdateSchema", permission: "MANAGE_GUILD" }), async (req: Request, res: Response) => { const body = req.body as GuildUpdateSchema; const { guild_id } = req.params; // TODO: guild update check image - const perms = await getPermission(req.user_id, guild_id); - perms.hasThrow("MANAGE_GUILD"); - if (body.icon) body.icon = await handleFile(`/icons/${guild_id}`, body.icon); if (body.banner) body.banner = await handleFile(`/banners/${guild_id}`, body.banner); if (body.splash) body.splash = await handleFile(`/splashes/${guild_id}`, body.splash); diff --git a/api/src/routes/guilds/#guild_id/invites.ts b/api/src/routes/guilds/#guild_id/invites.ts index 39a934ee..b7534e31 100644 --- a/api/src/routes/guilds/#guild_id/invites.ts +++ b/api/src/routes/guilds/#guild_id/invites.ts @@ -1,14 +1,12 @@ import { getPermission, Invite, PublicInviteRelation } from "@fosscord/util"; +import { route } from "@fosscord/api"; import { Request, Response, Router } from "express"; const router = Router(); -router.get("/", async (req: Request, res: Response) => { +router.get("/", route({ permission: "MANAGE_GUILD" }), async (req: Request, res: Response) => { const { guild_id } = req.params; - const permissions = await getPermission(req.user_id, guild_id); - permissions.hasThrow("MANAGE_GUILD"); - const invites = await Invite.find({ where: { guild_id }, relations: PublicInviteRelation }); return res.json(invites); 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 8b04a508..1708b7eb 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 @@ -1,23 +1,15 @@ import { Request, Response, Router } from "express"; -import { - Guild, - Member, - User, - GuildMemberAddEvent, - getPermission, - PermissionResolvable, - Role, - GuildMemberUpdateEvent, - emitEvent -} from "@fosscord/util"; +import { Member, getPermission, Role, GuildMemberUpdateEvent, emitEvent } from "@fosscord/util"; import { HTTPError } from "lambert-server"; -import { check } from "@fosscord/api"; -import { MemberChangeSchema } from "@fosscord/api/schema/Member"; -import { In } from "typeorm"; +import { check, route } from "@fosscord/api"; const router = Router(); -router.get("/", async (req: Request, res: Response) => { +export interface MemberChangeSchema { + roles?: string[]; +} + +router.get("/", route({}), async (req: Request, res: Response) => { const { guild_id, member_id } = req.params; await Member.IsInGuildOrFail(req.user_id, guild_id); @@ -26,8 +18,9 @@ router.get("/", async (req: Request, res: Response) => { return res.json(member); }); -router.patch("/", check(MemberChangeSchema), async (req: Request, res: Response) => { - const { guild_id, member_id } = req.params; +router.patch("/", route({ body: "MemberChangeSchema" }), async (req: Request, res: Response) => { + let { guild_id, member_id } = req.params; + if (member_id === "@me") member_id = req.user_id; const body = req.body as MemberChangeSchema; const member = await Member.findOneOrFail({ where: { id: member_id, guild_id }, relations: ["roles", "user"] }); @@ -39,7 +32,7 @@ router.patch("/", check(MemberChangeSchema), async (req: Request, res: Response) } await member.save(); - // do not use promise.all as we have to first write to db before emitting the event + // do not use promise.all as we have to first write to db before emitting the event to catch errors await emitEvent({ event: "GUILD_MEMBER_UPDATE", guild_id, @@ -49,7 +42,7 @@ router.patch("/", check(MemberChangeSchema), async (req: Request, res: Response) res.json(member); }); -router.put("/", async (req: Request, res: Response) => { +router.put("/", route({}), async (req: Request, res: Response) => { let { guild_id, member_id } = req.params; if (member_id === "@me") member_id = req.user_id; @@ -59,12 +52,9 @@ router.put("/", async (req: Request, res: Response) => { res.sendStatus(204); }); -router.delete("/", async (req: Request, res: Response) => { +router.delete("/", route({ permission: "KICK_MEMBERS" }), async (req: Request, res: Response) => { const { guild_id, member_id } = req.params; - const perms = await getPermission(req.user_id, guild_id); - perms.hasThrow("KICK_MEMBERS"); - await Member.removeFromGuild(member_id, guild_id); res.sendStatus(204); }); diff --git a/api/src/routes/guilds/#guild_id/members/#member_id/nick.ts b/api/src/routes/guilds/#guild_id/members/#member_id/nick.ts index 3f2975e6..27f7f65d 100644 --- a/api/src/routes/guilds/#guild_id/members/#member_id/nick.ts +++ b/api/src/routes/guilds/#guild_id/members/#member_id/nick.ts @@ -1,11 +1,14 @@ import { getPermission, Member, PermissionResolvable } from "@fosscord/util"; +import { route } from "@fosscord/api"; import { Request, Response, Router } from "express"; -import { check } from "lambert-server"; -import { MemberNickChangeSchema } from "../../../../../schema/Member"; const router = Router(); -router.patch("/", check(MemberNickChangeSchema), async (req: Request, res: Response) => { +export interface MemberNickChangeSchema { + nick: string; +} + +router.patch("/", route({ body: "MemberNickChangeSchema" }), async (req: Request, res: Response) => { var { guild_id, member_id } = req.params; var permissionString: PermissionResolvable = "MANAGE_NICKNAMES"; if (member_id === "@me") { 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 cb9bad9a..ae10be82 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 @@ -1,24 +1,19 @@ import { getPermission, Member } from "@fosscord/util"; +import { route } from "@fosscord/api"; import { Request, Response, Router } from "express"; const router = Router(); -router.delete("/:member_id/roles/:role_id", async (req: Request, res: Response) => { +router.delete("/:member_id/roles/:role_id", route({ permission: "MANAGE_ROLES" }), async (req: Request, res: Response) => { const { guild_id, role_id, member_id } = req.params; - const perms = await getPermission(req.user_id, guild_id); - perms.hasThrow("MANAGE_ROLES"); - await Member.removeRole(member_id, guild_id, role_id); res.sendStatus(204); }); -router.put("/:member_id/roles/:role_id", async (req: Request, res: Response) => { +router.put("/:member_id/roles/:role_id", route({ permission: "MANAGE_ROLES" }), async (req: Request, res: Response) => { const { guild_id, role_id, member_id } = req.params; - const perms = await getPermission(req.user_id, guild_id); - perms.hasThrow("MANAGE_ROLES"); - await Member.addRole(member_id, guild_id, role_id); res.sendStatus(204); }); diff --git a/api/src/routes/guilds/#guild_id/members/index.ts b/api/src/routes/guilds/#guild_id/members/index.ts index 198d6946..335f21c7 100644 --- a/api/src/routes/guilds/#guild_id/members/index.ts +++ b/api/src/routes/guilds/#guild_id/members/index.ts @@ -1,13 +1,15 @@ import { Request, Response, Router } from "express"; import { Guild, Member, PublicMemberProjection } from "@fosscord/util"; -import { instanceOf, Length } from "@fosscord/api"; +import { instanceOf, Length, route } from "@fosscord/api"; import { MoreThan } from "typeorm"; const router = Router(); // TODO: not allowed for user -> only allowed for bots with privileged intents // TODO: send over websocket -router.get("/", async (req: Request, res: Response) => { +// TODO: check for GUILD_MEMBERS intent + +router.get("/", route({}), async (req: Request, res: Response) => { const { guild_id } = req.params; const guild = await Guild.findOneOrFail({ id: guild_id }); await Member.IsInGuildOrFail(req.user_id, guild_id); diff --git a/api/src/routes/guilds/#guild_id/regions.ts b/api/src/routes/guilds/#guild_id/regions.ts index 86208b79..75d24fd1 100644 --- a/api/src/routes/guilds/#guild_id/regions.ts +++ b/api/src/routes/guilds/#guild_id/regions.ts @@ -1,11 +1,11 @@ import { Config, Guild, Member } from "@fosscord/util"; import { Request, Response, Router } from "express"; -import { getVoiceRegions } from "@fosscord/api"; +import { getVoiceRegions, route } from "@fosscord/api"; import { getIpAdress } from "@fosscord/api"; const router = Router(); -router.get("/", async (req: Request, res: Response) => { +router.get("/", route({}), async (req: Request, res: Response) => { const { guild_id } = req.params; const guild = await Guild.findOneOrFail({ id: guild_id }); //TODO we should use an enum for guild's features and not hardcoded strings diff --git a/api/src/routes/guilds/#guild_id/roles.ts b/api/src/routes/guilds/#guild_id/roles.ts index 76dd47c5..6b2902d9 100644 --- a/api/src/routes/guilds/#guild_id/roles.ts +++ b/api/src/routes/guilds/#guild_id/roles.ts @@ -2,23 +2,34 @@ import { Request, Response, Router } from "express"; import { Role, getPermission, - Snowflake, Member, GuildRoleCreateEvent, GuildRoleUpdateEvent, GuildRoleDeleteEvent, emitEvent, - Config + Config, + DiscordApiErrors } from "@fosscord/util"; import { HTTPError } from "lambert-server"; - -import { check } from "@fosscord/api"; -import { RoleModifySchema, RolePositionUpdateSchema } from "../../../schema/Roles"; -import { DiscordApiErrors } from "@fosscord/util"; +import { check, route } from "@fosscord/api"; import { In } from "typeorm"; const router: Router = Router(); +export interface RoleModifySchema { + name?: string; + permissions?: bigint; + color?: number; + hoist?: boolean; // whether the role should be displayed separately in the sidebar + mentionable?: boolean; // whether the role should be mentionable + position?: number; +} + +export type RolePositionUpdateSchema = { + id: string; + position: number; +}[]; + router.get("/", async (req: Request, res: Response) => { const guild_id = req.params.guild_id; @@ -29,13 +40,10 @@ router.get("/", async (req: Request, res: Response) => { return res.json(roles); }); -router.post("/", check(RoleModifySchema), async (req: Request, res: Response) => { +router.post("/", route({ body: "RoleModifySchema", permission: "MANAGE_ROLES" }), async (req: Request, res: Response) => { const guild_id = req.params.guild_id; const body = req.body as RoleModifySchema; - const perms = await getPermission(req.user_id, guild_id); - perms.hasThrow("MANAGE_ROLES"); - const role_count = await Role.count({ guild_id }); const { maxRoles } = Config.get().limits.guild; @@ -50,7 +58,7 @@ router.post("/", check(RoleModifySchema), async (req: Request, res: Response) => ...body, guild_id: guild_id, managed: false, - permissions: String(perms.bitfield & (body.permissions || 0n)), + permissions: String(req.permission!.bitfield & (body.permissions || 0n)), tags: undefined }); @@ -69,14 +77,11 @@ router.post("/", check(RoleModifySchema), async (req: Request, res: Response) => res.json(role); }); -router.delete("/:role_id", async (req: Request, res: Response) => { +router.delete("/:role_id", route({ permission: "MANAGE_ROLES" }), async (req: Request, res: Response) => { const guild_id = req.params.guild_id; const { role_id } = req.params; if (role_id === guild_id) throw new HTTPError("You can't delete the @everyone role"); - const permissions = await getPermission(req.user_id, guild_id); - permissions.hasThrow("MANAGE_ROLES"); - await Promise.all([ Role.delete({ id: role_id, @@ -97,14 +102,11 @@ router.delete("/:role_id", async (req: Request, res: Response) => { // TODO: check role hierarchy -router.patch("/:role_id", check(RoleModifySchema), async (req: Request, res: Response) => { +router.patch("/:role_id", route({ body: "RoleModifySchema", permission: "MANAGE_ROLES" }), async (req: Request, res: Response) => { const { role_id, guild_id } = req.params; const body = req.body as RoleModifySchema; - const perms = await getPermission(req.user_id, guild_id); - perms.hasThrow("MANAGE_ROLES"); - - const role = new Role({ ...body, id: role_id, guild_id, permissions: String(perms.bitfield & (body.permissions || 0n)) }); + const role = new Role({ ...body, id: role_id, guild_id, permissions: String(req.permission!.bitfield & (body.permissions || 0n)) }); await Promise.all([ role.save(), @@ -121,7 +123,7 @@ router.patch("/:role_id", check(RoleModifySchema), async (req: Request, res: Res res.json(role); }); -router.patch("/", check(RolePositionUpdateSchema), async (req: Request, res: Response) => { +router.patch("/", route({ body: "RolePositionUpdateSchema" }), async (req: Request, res: Response) => { const { guild_id } = req.params; const body = req.body as RolePositionUpdateSchema; diff --git a/api/src/routes/guilds/#guild_id/templates.ts b/api/src/routes/guilds/#guild_id/templates.ts index e9304e11..5179e761 100644 --- a/api/src/routes/guilds/#guild_id/templates.ts +++ b/api/src/routes/guilds/#guild_id/templates.ts @@ -1,8 +1,7 @@ import { Request, Response, Router } from "express"; -import { Guild, getPermission, Template } from "@fosscord/util"; +import { Guild, Template } from "@fosscord/util"; import { HTTPError } from "lambert-server"; -import { TemplateCreateSchema, TemplateModifySchema } from "../../../schema/Template"; -import { check } from "@fosscord/api"; +import { route } from "@fosscord/api"; import { generateCode } from "@fosscord/api"; const router: Router = Router(); @@ -24,7 +23,17 @@ const TemplateGuildProjection: (keyof Guild)[] = [ "icon" ]; -router.get("/", async (req: Request, res: Response) => { +export interface TemplateCreateSchema { + name: string; + description?: string; +} + +export interface TemplateModifySchema { + name: string; + description?: string; +} + +router.get("/", route({}), async (req: Request, res: Response) => { const { guild_id } = req.params; var templates = await Template.find({ source_guild_id: guild_id }); @@ -32,12 +41,9 @@ router.get("/", async (req: Request, res: Response) => { return res.json(templates); }); -router.post("/", check(TemplateCreateSchema), async (req: Request, res: Response) => { +router.post("/", route({ body: "TemplateCreateSchema", permission: "MANAGE_GUILD" }), async (req: Request, res: Response) => { const { guild_id } = req.params; const guild = await Guild.findOneOrFail({ where: { id: guild_id }, select: TemplateGuildProjection }); - const perms = await getPermission(req.user_id, guild_id); - perms.hasThrow("MANAGE_GUILD"); - const exists = await Template.findOneOrFail({ id: guild_id }).catch((e) => {}); if (exists) throw new HTTPError("Template already exists", 400); @@ -54,44 +60,31 @@ router.post("/", check(TemplateCreateSchema), async (req: Request, res: Response res.json(template); }); -router.delete("/:code", async (req: Request, res: Response) => { - const guild_id = req.params.guild_id; - const { code } = req.params; - - const perms = await getPermission(req.user_id, guild_id); - perms.hasThrow("MANAGE_GUILD"); +router.delete("/:code", route({ permission: "MANAGE_GUILD" }), async (req: Request, res: Response) => { + const { code, guild_id } = req.params; const template = await Template.delete({ - code + code, + source_guild_id: guild_id }); res.json(template); }); -router.put("/:code", async (req: Request, res: Response) => { - // synchronizes the template +router.put("/:code", route({ permission: "MANAGE_GUILD" }), async (req: Request, res: Response) => { const { code, guild_id } = req.params; - const guild = await Guild.findOneOrFail({ where: { id: guild_id }, select: TemplateGuildProjection }); - const perms = await getPermission(req.user_id, guild_id); - perms.hasThrow("MANAGE_GUILD"); - const template = await new Template({ code, serialized_source_guild: guild }).save(); res.json(template); }); -router.patch("/:code", check(TemplateModifySchema), async (req: Request, res: Response) => { - // updates the template description - const { guild_id } = req.params; - const { code } = req.params; +router.patch("/:code", route({ body: "TemplateModifySchema", permission: "MANAGE_GUILD" }), async (req: Request, res: Response) => { + const { code, guild_id } = req.params; const { name, description } = req.body; - const perms = await getPermission(req.user_id, guild_id); - perms.hasThrow("MANAGE_GUILD"); - - const template = await new Template({ code, name: name, description: description }).save(); + const template = await new Template({ code, name: name, description: description, source_guild_id: guild_id }).save(); res.json(template); }); diff --git a/api/src/routes/guilds/#guild_id/vanity-url.ts b/api/src/routes/guilds/#guild_id/vanity-url.ts index f1887cc0..9c0989cc 100644 --- a/api/src/routes/guilds/#guild_id/vanity-url.ts +++ b/api/src/routes/guilds/#guild_id/vanity-url.ts @@ -1,35 +1,37 @@ 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 "@fosscord/api"; +import { check, Length, route } from "@fosscord/api"; const router = Router(); const InviteRegex = /\W/g; -router.get("/", async (req: Request, res: Response) => { +router.get("/", route({ permission: "MANAGE_GUILD" }), async (req: Request, res: Response) => { const { guild_id } = req.params; - const permission = await getPermission(req.user_id, guild_id); - permission.hasThrow("MANAGE_GUILD"); - const guild = await Guild.findOneOrFail({ where: { id: guild_id }, relations: ["vanity_url"] }); if (!guild.vanity_url) return res.json({ code: null }); return res.json({ code: guild.vanity_url_code, uses: guild.vanity_url.uses }); }); +export interface VanityUrlSchema { + /** + * @minLength 1 + * @maxLength 20 + */ + code?: string; +} + // TODO: check if guild is elgible for vanity url -router.patch("/", check({ code: new Length(String, 0, 20) }), async (req: Request, res: Response) => { +router.patch("/", route({ body: "VanityUrlSchema", permission: "MANAGE_GUILD" }), async (req: Request, res: Response) => { const { guild_id } = req.params; - const code = req.body.code.replace(InviteRegex); + const body = req.body as VanityUrlSchema; + const code = body.code?.replace(InviteRegex, ""); await Invite.findOneOrFail({ code }); const guild = await Guild.findOneOrFail({ id: guild_id }); - const permission = await getPermission(req.user_id, guild_id); - permission.hasThrow("MANAGE_GUILD"); - const { id } = await Channel.findOneOrFail({ guild_id, type: ChannelType.GUILD_TEXT }); guild.vanity_url_code = code; 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 447e15c1..3d76938b 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,14 +1,59 @@ -import { check } from "@fosscord/api"; -import { VoiceStateUpdateSchema } from "../../../../../schema"; +import { Channel, ChannelType, DiscordApiErrors, emitEvent, getPermission, VoiceState, VoiceStateUpdateEvent } from "@fosscord/util"; +import { check, route } from "@fosscord/api"; import { Request, Response, Router } from "express"; -import { updateVoiceState } from "@fosscord/api"; const router = Router(); +//TODO need more testing when community guild and voice stage channel are working -router.patch("/", check(VoiceStateUpdateSchema), async (req: Request, res: Response) => { +export interface VoiceStateUpdateSchema { + channel_id: string; + guild_id?: string; + suppress?: boolean; + request_to_speak_timestamp?: Date; + self_mute?: boolean; + self_deaf?: boolean; + self_video?: boolean; +} + +router.patch("/", route({ body: "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); + var { guild_id, user_id } = req.params; + if (user_id === "@me") user_id = req.user_id; + + const perms = await getPermission(req.user_id, guild_id, body.channel_id); + + /* + From https://discord.com/developers/docs/resources/guild#modify-current-user-voice-state + You must have the MUTE_MEMBERS permission to unsuppress others. You can always suppress yourself. + You must have the REQUEST_TO_SPEAK permission to request to speak. You can always clear your own request to speak. + */ + if (body.suppress && user_id !== req.user_id) { + perms.hasThrow("MUTE_MEMBERS"); + } + if (!body.suppress) body.request_to_speak_timestamp = new Date(); + if (body.request_to_speak_timestamp) perms.hasThrow("REQUEST_TO_SPEAK"); + + const voice_state = await VoiceState.findOne({ + guild_id, + channel_id: body.channel_id, + user_id + }); + if (!voice_state) throw DiscordApiErrors.UNKNOWN_VOICE_STATE; + + voice_state.assign(body); + const channel = await Channel.findOneOrFail({ guild_id, id: body.channel_id }); + if (channel.type !== ChannelType.GUILD_STAGE_VOICE) { + throw DiscordApiErrors.CANNOT_EXECUTE_ON_THIS_CHANNEL_TYPE; + } + + await Promise.all([ + voice_state.save(), + emitEvent({ + event: "VOICE_STATE_UPDATE", + data: voice_state, + guild_id + } as VoiceStateUpdateEvent) + ]); return res.sendStatus(204); }); 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 deleted file mode 100644 index b637ff66..00000000 --- a/api/src/routes/guilds/#guild_id/voice-states/@me/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { check } from "@fosscord/api"; -import { VoiceStateUpdateSchema } from "../../../../../schema"; -import { Request, Response, Router } from "express"; -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); - return res.sendStatus(204); -}); - -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 7ca49b4e..7141f17e 100644 --- a/api/src/routes/guilds/#guild_id/welcome_screen.ts +++ b/api/src/routes/guilds/#guild_id/welcome_screen.ts @@ -1,31 +1,36 @@ import { Request, Response, Router } from "express"; import { Guild, getPermission, Snowflake, Member } from "@fosscord/util"; import { HTTPError } from "lambert-server"; - -import { check } from "@fosscord/api"; -import { GuildUpdateWelcomeScreenSchema } from "../../../schema/Guild"; +import { route } from "@fosscord/api"; const router: Router = Router(); -router.get("/", async (req: Request, res: Response) => { +export interface GuildUpdateWelcomeScreenSchema { + welcome_channels?: { + channel_id: string; + description: string; + emoji_id?: string; + emoji_name: string; + }[]; + enabled?: boolean; + description?: string; +} + +router.get("/", route({}), async (req: Request, res: Response) => { const guild_id = req.params.guild_id; const guild = await Guild.findOneOrFail({ id: guild_id }); - await Member.IsInGuildOrFail(req.user_id, guild_id); res.json(guild.welcome_screen); }); -router.patch("/", check(GuildUpdateWelcomeScreenSchema), async (req: Request, res: Response) => { +router.patch("/", route({ body: "GuildUpdateWelcomeScreenSchema", permission: "MANAGE_GUILD" }), async (req: Request, res: Response) => { const guild_id = req.params.guild_id; const body = req.body as GuildUpdateWelcomeScreenSchema; const guild = await Guild.findOneOrFail({ id: guild_id }); - const perms = await getPermission(req.user_id, guild_id); - perms.hasThrow("MANAGE_GUILD"); - if (!guild.welcome_screen.enabled) throw new HTTPError("Welcome screen disabled", 400); if (body.welcome_channels) guild.welcome_screen.welcome_channels = body.welcome_channels; // TODO: check if they exist and are valid if (body.description) guild.welcome_screen.description = body.description; diff --git a/api/src/routes/guilds/#guild_id/widget.json.ts b/api/src/routes/guilds/#guild_id/widget.json.ts index f871fac8..c31519fa 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 "@fosscord/api"; +import { random, route } from "@fosscord/api"; const router: Router = Router(); @@ -14,7 +14,7 @@ const router: Router = Router(); // https://discord.com/developers/docs/resources/guild#get-guild-widget // TODO: Cache the response for a guild for 5 minutes regardless of response -router.get("/", async (req: Request, res: Response) => { +router.get("/", route({}), async (req: Request, res: Response) => { const { guild_id } = req.params; const guild = await Guild.findOneOrFail({ id: guild_id }); diff --git a/api/src/routes/guilds/#guild_id/widget.png.ts b/api/src/routes/guilds/#guild_id/widget.png.ts index 89b31153..4c82b740 100644 --- a/api/src/routes/guilds/#guild_id/widget.png.ts +++ b/api/src/routes/guilds/#guild_id/widget.png.ts @@ -1,6 +1,7 @@ import { Request, Response, Router } from "express"; import { Guild } from "@fosscord/util"; import { HTTPError } from "lambert-server"; +import { route } from "@fosscord/api"; import fs from "fs"; import path from "path"; @@ -10,7 +11,7 @@ const router: Router = Router(); // https://discord.com/developers/docs/resources/guild#get-guild-widget-image // TODO: Cache the response -router.get("/", async (req: Request, res: Response) => { +router.get("/", route({}), async (req: Request, res: Response) => { const { guild_id } = req.params; const guild = await Guild.findOneOrFail({ id: guild_id }); diff --git a/api/src/routes/guilds/#guild_id/widget.ts b/api/src/routes/guilds/#guild_id/widget.ts index d9ce817e..c8caae14 100644 --- a/api/src/routes/guilds/#guild_id/widget.ts +++ b/api/src/routes/guilds/#guild_id/widget.ts @@ -1,31 +1,29 @@ import { Request, Response, Router } from "express"; import { getPermission, Guild } from "@fosscord/util"; import { HTTPError } from "lambert-server"; -import { check } from "@fosscord/api"; -import { WidgetModifySchema } from "../../../schema/Widget"; +import { check, route } from "@fosscord/api"; + +export interface WidgetModifySchema { + enabled: boolean; // whether the widget is enabled + channel_id: string; // the widget channel id +} const router: Router = Router(); // https://discord.com/developers/docs/resources/guild#get-guild-widget-settings -router.get("/", async (req: Request, res: Response) => { +router.get("/", route({}), async (req: Request, res: Response) => { const { guild_id } = req.params; - const perms = await getPermission(req.user_id, guild_id); - perms.hasThrow("MANAGE_GUILD"); - const guild = await Guild.findOneOrFail({ id: guild_id }); return res.json({ enabled: guild.widget_enabled || false, channel_id: guild.widget_channel_id || null }); }); // https://discord.com/developers/docs/resources/guild#modify-guild-widget -router.patch("/", check(WidgetModifySchema), async (req: Request, res: Response) => { +router.patch("/", route({ body: "WidgetModifySchema", permission: "MANAGE_GUILD" }), async (req: Request, res: Response) => { const body = req.body as WidgetModifySchema; const { guild_id } = req.params; - const perms = await getPermission(req.user_id, guild_id); - perms.hasThrow("MANAGE_GUILD"); - await Guild.update({ id: guild_id }, { widget_enabled: body.enabled, widget_channel_id: body.channel_id }); // Widget invite for the widget_channel_id gets created as part of the /guilds/{guild.id}/widget.json request diff --git a/api/src/routes/guilds/index.ts b/api/src/routes/guilds/index.ts index a1b199e7..ba951f96 100644 --- a/api/src/routes/guilds/index.ts +++ b/api/src/routes/guilds/index.ts @@ -1,15 +1,28 @@ 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 "@fosscord/api"; -import { GuildCreateSchema } from "../../schema/Guild"; +import { check, route } from "@fosscord/api"; import { DiscordApiErrors } from "@fosscord/util"; +import { ChannelModifySchema } from "../channels/#channel_id"; const router: Router = Router(); +export interface GuildCreateSchema { + /** + * @maxLength 100 + */ + name: string; + region?: string; + icon?: string; + channels?: ChannelModifySchema[]; + guild_template_code?: string; + system_channel_id?: string; + rules_channel_id?: string; +} + //TODO: create default channel -router.post("/", check(GuildCreateSchema), async (req: Request, res: Response) => { +router.post("/", route({ body: "GuildCreateSchema" }), async (req: Request, res: Response) => { const body = req.body as GuildCreateSchema; const { maxGuilds } = Config.get().limits.user; diff --git a/api/src/routes/guilds/templates/index.ts b/api/src/routes/guilds/templates/index.ts index 1d0f2716..d7a42044 100644 --- a/api/src/routes/guilds/templates/index.ts +++ b/api/src/routes/guilds/templates/index.ts @@ -2,11 +2,15 @@ import { Request, Response, Router } from "express"; 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 "@fosscord/api"; +import { check, route } from "@fosscord/api"; import { DiscordApiErrors } from "@fosscord/util"; -router.get("/:code", async (req: Request, res: Response) => { +export interface GuildTemplateCreateSchema { + name: string; + avatar?: string; +} + +router.get("/:code", route({}), async (req: Request, res: Response) => { const { code } = req.params; const template = await Template.findOneOrFail({ code: code }); @@ -14,7 +18,7 @@ router.get("/:code", async (req: Request, res: Response) => { res.json(template); }); -router.post("/:code", check(GuildTemplateCreateSchema), async (req: Request, res: Response) => { +router.post("/:code", route({ body: "GuildTemplateCreateSchema" }), async (req: Request, res: Response) => { const { code } = req.params; const body = req.body as GuildTemplateCreateSchema; diff --git a/api/src/routes/invites/index.ts b/api/src/routes/invites/index.ts index b8c24c1f..6e77a853 100644 --- a/api/src/routes/invites/index.ts +++ b/api/src/routes/invites/index.ts @@ -1,9 +1,10 @@ import { Router, Request, Response } from "express"; import { getPermission, Guild, Invite, Member, PublicInviteRelation } from "@fosscord/util"; +import { route } from "@fosscord/api"; import { HTTPError } from "lambert-server"; const router: Router = Router(); -router.get("/:code", async (req: Request, res: Response) => { +router.get("/:code", route({}), async (req: Request, res: Response) => { const { code } = req.params; const invite = await Invite.findOneOrFail({ where: { code }, relations: PublicInviteRelation }); @@ -11,7 +12,7 @@ router.get("/:code", async (req: Request, res: Response) => { res.status(200).send(invite); }); -router.post("/:code", async (req: Request, res: Response) => { +router.post("/:code", route({}), async (req: Request, res: Response) => { const { code } = req.params; const invite = await Invite.findOneOrFail({ code }); @@ -23,7 +24,8 @@ router.post("/:code", async (req: Request, res: Response) => { res.status(200).send(invite); }); -router.delete("/:code", async (req: Request, res: Response) => { +// * cant use permission of route() function because path doesn't have guild_id/channel_id +router.delete("/:code", route({}), async (req: Request, res: Response) => { const { code } = req.params; const invite = await Invite.findOneOrFail({ code }); const { guild_id, channel_id } = invite; diff --git a/api/src/routes/ping.ts b/api/src/routes/ping.ts index 38daf81e..5cdea705 100644 --- a/api/src/routes/ping.ts +++ b/api/src/routes/ping.ts @@ -1,8 +1,9 @@ import { Router, Response, Request } from "express"; +import { route } from "@fosscord/api"; const router = Router(); -router.get("/", (req: Request, res: Response) => { +router.get("/", route({}), (req: Request, res: Response) => { res.send("pong"); }); diff --git a/api/src/routes/science.ts b/api/src/routes/science.ts index b16ef783..8556a3ad 100644 --- a/api/src/routes/science.ts +++ b/api/src/routes/science.ts @@ -1,8 +1,9 @@ import { Router, Response, Request } from "express"; +import { route } from "@fosscord/api"; const router = Router(); -router.post("/", (req: Request, res: Response) => { +router.post("/", route({}), (req: Request, res: Response) => { // TODO: res.sendStatus(204); }); diff --git a/api/src/routes/users/#id/index.ts b/api/src/routes/users/#id/index.ts index 07956360..bdb1060f 100644 --- a/api/src/routes/users/#id/index.ts +++ b/api/src/routes/users/#id/index.ts @@ -1,9 +1,10 @@ import { Router, Request, Response } from "express"; import { User } from "@fosscord/util"; +import { route } from "@fosscord/api"; const router: Router = Router(); -router.get("/", async (req: Request, res: Response) => { +router.get("/", route({}), async (req: Request, res: Response) => { const { id } = req.params; res.json(await User.getPublicUser(id)); diff --git a/api/src/routes/users/#id/profile.ts b/api/src/routes/users/#id/profile.ts index 0f43a82f..d60c4f86 100644 --- a/api/src/routes/users/#id/profile.ts +++ b/api/src/routes/users/#id/profile.ts @@ -1,9 +1,17 @@ import { Router, Request, Response } from "express"; import { PublicConnectedAccount, PublicUser, User, UserPublic } from "@fosscord/util"; +import { route } from "@fosscord/api"; const router: Router = Router(); -router.get("/", async (req: Request, res: Response) => { +export interface UserProfileResponse { + user: UserPublic; + connected_accounts: PublicConnectedAccount; + premium_guild_since?: Date; + premium_since?: Date; +} + +router.get("/", route({ response: { body: "UserProfileResponse" } }), async (req: Request, res: Response) => { if (req.params.id === "@me") req.params.id = req.user_id; const user = await User.getPublicUser(req.params.id, { relations: ["connected_accounts"] }); @@ -25,11 +33,4 @@ router.get("/", async (req: Request, res: Response) => { }); }); -export interface UserProfileResponse { - user: UserPublic; - connected_accounts: PublicConnectedAccount; - premium_guild_since?: Date; - premium_since?: Date; -} - export default router; diff --git a/api/src/routes/users/@me/affinities/guilds.ts b/api/src/routes/users/@me/affinities/guilds.ts index fa6be0e7..8d744744 100644 --- a/api/src/routes/users/@me/affinities/guilds.ts +++ b/api/src/routes/users/@me/affinities/guilds.ts @@ -1,8 +1,9 @@ import { Router, Response, Request } from "express"; +import { route } from "@fosscord/api"; const router = Router(); -router.get("/", (req: Request, res: Response) => { +router.get("/", route({}), (req: Request, res: Response) => { // TODO: res.status(200).send({ guild_affinities: [] }); }); diff --git a/api/src/routes/users/@me/affinities/user.ts b/api/src/routes/users/@me/affinities/user.ts index 0790a8a4..6d4e4991 100644 --- a/api/src/routes/users/@me/affinities/user.ts +++ b/api/src/routes/users/@me/affinities/user.ts @@ -1,8 +1,9 @@ import { Router, Response, Request } from "express"; +import { route } from "@fosscord/api"; const router = Router(); -router.get("/", (req: Request, res: Response) => { +router.get("/", route({}), (req: Request, res: Response) => { // TODO: res.status(200).send({ user_affinities: [], inverse_user_affinities: [] }); }); diff --git a/api/src/routes/users/@me/channels.ts b/api/src/routes/users/@me/channels.ts index 77fc8296..5515a217 100644 --- a/api/src/routes/users/@me/channels.ts +++ b/api/src/routes/users/@me/channels.ts @@ -1,19 +1,23 @@ import { Router, Request, Response } from "express"; 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 "@fosscord/api"; +import { route } from "@fosscord/api"; import { In } from "typeorm"; +export interface DmChannelCreateSchema { + name?: string; + recipients: string[]; +} + const router: Router = Router(); -router.get("/", async (req: Request, res: Response) => { +router.get("/", route({}), async (req: Request, res: Response) => { const recipients = await Recipient.find({ where: { user_id: req.user_id }, relations: ["channel"] }); res.json(recipients.map((x) => x.channel)); }); -router.post("/", check(DmChannelCreateSchema), async (req: Request, res: Response) => { +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(); diff --git a/api/src/routes/users/@me/delete.ts b/api/src/routes/users/@me/delete.ts index e5fda948..39ceefd9 100644 --- a/api/src/routes/users/@me/delete.ts +++ b/api/src/routes/users/@me/delete.ts @@ -1,10 +1,12 @@ import { Router, Request, Response } from "express"; import { Guild, Member, User } from "@fosscord/util"; +import { route } from "@fosscord/api"; import bcrypt from "bcrypt"; import { HTTPError } from "lambert-server"; + const router = Router(); -router.post("/", async (req: Request, res: Response) => { +router.post("/", route({}), async (req: Request, res: Response) => { const user = await User.findOneOrFail({ id: req.user_id }); //User object let correctpass = true; diff --git a/api/src/routes/users/@me/devices.ts b/api/src/routes/users/@me/devices.ts index b16ef783..8556a3ad 100644 --- a/api/src/routes/users/@me/devices.ts +++ b/api/src/routes/users/@me/devices.ts @@ -1,8 +1,9 @@ import { Router, Response, Request } from "express"; +import { route } from "@fosscord/api"; const router = Router(); -router.post("/", (req: Request, res: Response) => { +router.post("/", route({}), (req: Request, res: Response) => { // TODO: res.sendStatus(204); }); diff --git a/api/src/routes/users/@me/disable.ts b/api/src/routes/users/@me/disable.ts index 7b8a130c..259ced96 100644 --- a/api/src/routes/users/@me/disable.ts +++ b/api/src/routes/users/@me/disable.ts @@ -1,10 +1,11 @@ import { User } from "@fosscord/util"; import { Router, Response, Request } from "express"; +import { route } from "@fosscord/api"; import bcrypt from "bcrypt"; const router = Router(); -router.post("/", async (req: Request, res: Response) => { +router.post("/", route({}), async (req: Request, res: Response) => { const user = await User.findOneOrFail({ id: req.user_id }); //User object let correctpass = true; diff --git a/api/src/routes/users/@me/guilds.ts b/api/src/routes/users/@me/guilds.ts index fb88281b..4ba03cec 100644 --- a/api/src/routes/users/@me/guilds.ts +++ b/api/src/routes/users/@me/guilds.ts @@ -1,18 +1,18 @@ import { Router, Request, Response } from "express"; import { Guild, Member, User, GuildDeleteEvent, GuildMemberRemoveEvent, emitEvent } from "@fosscord/util"; import { HTTPError } from "lambert-server"; -import { In } from "typeorm"; +import { route } from "@fosscord/api"; const router: Router = Router(); -router.get("/", async (req: Request, res: Response) => { +router.get("/", route({}), async (req: Request, res: Response) => { const members = await Member.find({ relations: ["guild"], where: { id: req.user_id } }); res.json(members.map((x) => x.guild)); }); // user send to leave a certain guild -router.delete("/:id", async (req: Request, res: Response) => { +router.delete("/:id", route({}), async (req: Request, res: Response) => { const guild_id = req.params.id; const guild = await Guild.findOneOrFail({ where: { id: guild_id }, select: ["owner_id"] }); diff --git a/api/src/routes/users/@me/index.ts b/api/src/routes/users/@me/index.ts index 451a657c..68723374 100644 --- a/api/src/routes/users/@me/index.ts +++ b/api/src/routes/users/@me/index.ts @@ -1,16 +1,33 @@ import { Router, Request, Response } from "express"; import { User, PrivateUserProjection } from "@fosscord/util"; -import { UserModifySchema } from "../../../schema/User"; -import { check } from "@fosscord/api"; +import { check, route } from "@fosscord/api"; import { handleFile } from "@fosscord/api"; const router: Router = Router(); +export interface UserModifySchema { + /** + * @minLength 1 + * @maxLength 100 + */ + username?: string; + avatar?: string | null; + /** + * @maxLength 1024 + */ + bio?: string; + accent_color?: number | null; + banner?: string | null; + password?: string; + new_password?: string; + code?: string; +} + router.get("/", async (req: Request, res: Response) => { - res.json(await User.getPublicUser(req.user_id, { select: PrivateUserProjection })); + res.json(await User.findOne({ select: PrivateUserProjection, where: { id: req.user_id } })); }); -router.patch("/", check(UserModifySchema), async (req: Request, res: Response) => { +router.patch("/", route({ body: "UserModifySchema" }), async (req: Request, res: Response) => { const body = req.body as UserModifySchema; if (body.avatar) body.avatar = await handleFile(`/avatars/${req.user_id}`, body.avatar as string); diff --git a/api/src/routes/users/@me/library.ts b/api/src/routes/users/@me/library.ts index d771cb5e..7ac13bae 100644 --- a/api/src/routes/users/@me/library.ts +++ b/api/src/routes/users/@me/library.ts @@ -1,8 +1,9 @@ import { Router, Response, Request } from "express"; +import { route } from "@fosscord/api"; const router = Router(); -router.get("/", (req: Request, res: Response) => { +router.get("/", route({}), (req: Request, res: Response) => { // TODO: res.status(200).send([]); }); diff --git a/api/src/routes/users/@me/relationships.ts b/api/src/routes/users/@me/relationships.ts index 67ca2f35..cc264f3f 100644 --- a/api/src/routes/users/@me/relationships.ts +++ b/api/src/routes/users/@me/relationships.ts @@ -11,19 +11,95 @@ import { import { Router, Response, Request } from "express"; import { HTTPError } from "lambert-server"; import { DiscordApiErrors } from "@fosscord/util"; - -import { check, Length } from "@fosscord/api"; +import { route } from "@fosscord/api"; const router = Router(); const userProjection: (keyof User)[] = ["relationships", ...PublicUserProjection]; -router.get("/", async (req: Request, res: Response) => { +router.get("/", route({}), async (req: Request, res: Response) => { const user = await User.findOneOrFail({ where: { id: req.user_id }, relations: ["relationships"] }); return res.json(user.relationships); }); +export interface RelationshipPutSchema { + type: RelationshipType; +} + +router.put("/:id", route({ body: "RelationshipPutSchema" }), async (req: Request, res: Response) => { + return await updateRelationship( + req, + res, + await User.findOneOrFail({ id: req.params.id }, { relations: ["relationships"], select: userProjection }), + req.body.type + ); +}); + +export interface RelationshipPostSchema { + discriminator: string; + username: string; +} + +router.post("/", route({ body: "RelationshipPostSchema" }), async (req: Request, res: Response) => { + return await updateRelationship( + req, + res, + await User.findOneOrFail({ + relations: ["relationships"], + select: userProjection, + where: req.body as { discriminator: string; username: string } + }), + req.body.type + ); +}); + +router.delete("/:id", route({}), async (req: Request, res: Response) => { + const { id } = req.params; + if (id === req.user_id) throw new HTTPError("You can't remove yourself as a friend"); + + 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); + + 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) + ]); + 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); + + await Promise.all([ + user.save(), + friend.save(), + emitEvent({ + event: "RELATIONSHIP_REMOVE", + data: relationship, + user_id: req.user_id + } as RelationshipRemoveEvent), + emitEvent({ + event: "RELATIONSHIP_REMOVE", + data: friendRequest, + user_id: id + } as RelationshipRemoveEvent) + ]); + + return res.sendStatus(204); +}); + +export default router; + async function updateRelationship(req: Request, res: Response, friend: User, type: RelationshipType) { const id = friend.id; if (id === req.user_id) throw new HTTPError("You can't add yourself as a friend"); @@ -114,71 +190,3 @@ async function updateRelationship(req: Request, res: Response, friend: User, typ return res.sendStatus(204); } - -router.put("/:id", check({ $type: new Length(Number, 1, 4) }), async (req: Request, res: Response) => { - return await updateRelationship( - req, - res, - await User.findOneOrFail({ id: req.params.id }, { relations: ["relationships"], select: userProjection }), - req.body.type - ); -}); - -router.post("/", check({ discriminator: String, username: String }), async (req: Request, res: Response) => { - return await updateRelationship( - req, - res, - await User.findOneOrFail({ - relations: ["relationships"], - select: userProjection, - where: req.body as { discriminator: string; username: string } - }), - req.body.type - ); -}); - -router.delete("/:id", async (req: Request, res: Response) => { - const { id } = req.params; - if (id === req.user_id) throw new HTTPError("You can't remove yourself as a friend"); - - 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); - - 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) - ]); - 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); - - await Promise.all([ - user.save(), - friend.save(), - emitEvent({ - event: "RELATIONSHIP_REMOVE", - data: relationship, - user_id: req.user_id - } as RelationshipRemoveEvent), - emitEvent({ - event: "RELATIONSHIP_REMOVE", - data: friendRequest, - user_id: id - } as RelationshipRemoveEvent) - ]); - - return res.sendStatus(204); -}); - -export default router; diff --git a/api/src/routes/users/@me/settings.ts b/api/src/routes/users/@me/settings.ts index e7db85ed..9d7a2545 100644 --- a/api/src/routes/users/@me/settings.ts +++ b/api/src/routes/users/@me/settings.ts @@ -1,11 +1,12 @@ import { Router, Response, Request } from "express"; import { User, UserSettings } from "@fosscord/util"; -import { check } from "@fosscord/api"; -import { UserSettingsSchema } from "../../../schema/User"; +import { route } from "@fosscord/api"; const router = Router(); -router.patch("/", check(UserSettingsSchema), async (req: Request, res: Response) => { +export interface UserSettingsSchema extends UserSettings {} + +router.patch("/", route({ body: "UserSettingsSchema" }), async (req: Request, res: Response) => { const body = req.body as UserSettings; // only users can update user settings diff --git a/api/src/routes/voice/regions.ts b/api/src/routes/voice/regions.ts index da1aaade..4de304ee 100644 --- a/api/src/routes/voice/regions.ts +++ b/api/src/routes/voice/regions.ts @@ -1,10 +1,10 @@ import { Router, Request, Response } from "express"; -import { getIpAdress } from "@fosscord/api"; +import { getIpAdress, route } from "@fosscord/api"; import { getVoiceRegions } from "@fosscord/api"; const router: Router = Router(); -router.get("/", async (req: Request, res: Response) => { +router.get("/", route({}), async (req: Request, res: Response) => { res.json(await getVoiceRegions(getIpAdress(req), true)); //vip true? }); diff --git a/api/src/schema/Ban.ts b/api/src/schema/Ban.ts deleted file mode 100644 index 947a60ea..00000000 --- a/api/src/schema/Ban.ts +++ /dev/null @@ -1,9 +0,0 @@ -export const BanCreateSchema = { - $delete_message_days: String, - $reason: String, -}; - -export interface BanCreateSchema { - delete_message_days?: string; - reason?: string; -} diff --git a/api/src/schema/Channel.ts b/api/src/schema/Channel.ts deleted file mode 100644 index cfbc7205..00000000 --- a/api/src/schema/Channel.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { ChannelType } from "@fosscord/util"; -import { Length } from "../util/instanceOf"; - -export const ChannelModifySchema = { - name: new Length(String, 2, 100), - type: new Length(Number, 0, 13), - $topic: new Length(String, 0, 1024), - $bitrate: Number, - $user_limit: Number, - $rate_limit_per_user: new Length(Number, 0, 21600), - $position: Number, - $permission_overwrites: [ - { - id: String, - type: new Length(Number, 0, 1), // either 0 (role) or 1 (member) - allow: BigInt, - deny: BigInt - } - ], - $parent_id: String, - $rtc_region: String, - $default_auto_archive_duration: Number, - $id: String, // kept for backwards compatibility does nothing (need for guild create) - $nsfw: Boolean -}; - -export const DmChannelCreateSchema = { - $name: String, - recipients: new Length([String], 1, 10) -}; - -export interface DmChannelCreateSchema { - name?: string; - recipients: string[]; -} - -export interface ChannelModifySchema { - name: string; - type: number; - topic?: string; - bitrate?: number; - user_limit?: number; - rate_limit_per_user?: number; - position?: number; - permission_overwrites?: { - id: string; - type: number; - allow: bigint; - deny: bigint; - }[]; - parent_id?: string; - id?: string; // is not used (only for guild create) - nsfw?: boolean; - rtc_region?: string; - default_auto_archive_duration?: number; -} - -export const ChannelGuildPositionUpdateSchema = [ - { - id: String, - $position: Number - } -]; - -export type ChannelGuildPositionUpdateSchema = { - id: string; - position?: number; -}[]; diff --git a/api/src/schema/Emoji.ts b/api/src/schema/Emoji.ts deleted file mode 100644 index 0406919c..00000000 --- a/api/src/schema/Emoji.ts +++ /dev/null @@ -1,13 +0,0 @@ -// https://discord.com/developers/docs/resources/emoji - -export const EmojiCreateSchema = { - name: String, //name of the emoji - image: String, // image data the 128x128 emoji image uri - $roles: Array //roles allowed to use this emoji -}; - -export interface EmojiCreateSchema { - name: string; // name of the emoji - image: string; // image data the 128x128 emoji image uri - roles?: string[]; //roles allowed to use this emoji -} diff --git a/api/src/schema/Guild.ts b/api/src/schema/Guild.ts deleted file mode 100644 index 29c78ab0..00000000 --- a/api/src/schema/Guild.ts +++ /dev/null @@ -1,106 +0,0 @@ -import { Channel } from "@fosscord/util"; -import { Length } from "../util/instanceOf"; -import { ChannelModifySchema } from "./Channel"; - -export const GuildCreateSchema = { - name: new Length(String, 2, 100), - $region: String, // auto complete voice region of the user - $icon: String, - $channels: [ChannelModifySchema], - $guild_template_code: String, - $system_channel_id: String, - $rules_channel_id: String -}; - -export interface GuildCreateSchema { - name: string; - region?: string; - icon?: string; - channels?: ChannelModifySchema[]; - guild_template_code?: string; - system_channel_id?: string; - rules_channel_id?: string; -} - -export const GuildUpdateSchema = { - ...GuildCreateSchema, - name: undefined, - $name: new Length(String, 2, 100), - $banner: String, - $splash: String, - $description: String, - $features: [String], - $icon: String, - $verification_level: Number, - $default_message_notifications: Number, - $system_channel_flags: Number, - $system_channel_id: String, - $explicit_content_filter: Number, - $public_updates_channel_id: String, - $afk_timeout: Number, - $afk_channel_id: String, - $preferred_locale: String -}; -// @ts-ignore -delete GuildUpdateSchema.$channels; - -export interface GuildUpdateSchema extends Omit { - banner?: string; - splash?: string; - description?: string; - features?: string[]; - verification_level?: number; - default_message_notifications?: number; - system_channel_flags?: number; - explicit_content_filter?: number; - public_updates_channel_id?: string; - afk_timeout?: number; - afk_channel_id?: string; - preferred_locale?: string; -} - -export const GuildTemplateCreateSchema = { - name: String, - $avatar: String -}; - -export interface GuildTemplateCreateSchema { - name: string; - avatar?: string; -} - -export const GuildUpdateWelcomeScreenSchema = { - $welcome_channels: [ - { - channel_id: String, - description: String, - $emoji_id: String, - emoji_name: String - } - ], - $enabled: Boolean, - $description: new Length(String, 0, 140) -}; - -export interface GuildUpdateWelcomeScreenSchema { - welcome_channels?: { - channel_id: string; - description: string; - emoji_id?: string; - emoji_name: string; - }[]; - enabled?: boolean; - description?: string; -} - -export const VoiceStateUpdateSchema = { - channel_id: String, // Snowflake - $suppress: Boolean, - $request_to_speak_timestamp: String // ISO8601 timestamp -}; - -export interface VoiceStateUpdateSchema { - channel_id: string; // Snowflake - suppress?: boolean; - request_to_speak_timestamp?: string // ISO8601 timestamp -} diff --git a/api/src/schema/Invite.ts b/api/src/schema/Invite.ts deleted file mode 100644 index da6192bc..00000000 --- a/api/src/schema/Invite.ts +++ /dev/null @@ -1,22 +0,0 @@ -export const InviteCreateSchema = { - $target_user_id: String, - $target_type: String, - $validate: String, //? wtf is this - $max_age: Number, - $max_uses: Number, - $temporary: Boolean, - $unique: Boolean, - $target_user: String, - $target_user_type: Number -}; -export interface InviteCreateSchema { - target_user_id?: string; - target_type?: string; - validate?: string; //? wtf is this - max_age?: number; - max_uses?: number; - temporary?: boolean; - unique?: boolean; - target_user?: string; - target_user_type?: number; -} diff --git a/api/src/schema/Member.ts b/api/src/schema/Member.ts deleted file mode 100644 index 607d0a06..00000000 --- a/api/src/schema/Member.ts +++ /dev/null @@ -1,29 +0,0 @@ -export const MemberCreateSchema = { - id: String, - nick: String, - guild_id: String, - joined_at: Date -}; - -export interface MemberCreateSchema { - id: string; - nick: string; - guild_id: string; - joined_at: Date; -} - -export const MemberNickChangeSchema = { - nick: String -}; - -export interface MemberNickChangeSchema { - nick: string; -} - -export const MemberChangeSchema = { - $roles: [String] -}; - -export interface MemberChangeSchema { - roles?: string[]; -} diff --git a/api/src/schema/Message.ts b/api/src/schema/Message.ts deleted file mode 100644 index d39f685a..00000000 --- a/api/src/schema/Message.ts +++ /dev/null @@ -1,92 +0,0 @@ -import { Embed } from "@fosscord/util"; -import { Length } from "../util/instanceOf"; - -export const EmbedImage = { - $url: String, - $width: Number, - $height: Number -}; - -const embed = { - $title: new Length(String, 0, 256), //title of embed - $type: String, // type of embed (always "rich" for webhook embeds) - $description: new Length(String, 0, 2048), // description of embed - $url: String, // url of embed - $timestamp: String, // ISO8601 timestamp - $color: Number, // color code of the embed - $footer: { - text: new Length(String, 0, 2048), - icon_url: String, - proxy_icon_url: String - }, // footer object footer information - $image: EmbedImage, // image object image information - $thumbnail: EmbedImage, // thumbnail object thumbnail information - $video: EmbedImage, // video object video information - $provider: { - name: String, - url: String - }, // provider object provider information - $author: { - name: new Length(String, 0, 256), - url: String, - icon_url: String, - proxy_icon_url: String - }, // author object author information - $fields: new Length( - [ - { - name: new Length(String, 0, 256), - value: new Length(String, 0, 1024), - $inline: Boolean - } - ], - 0, - 25 - ) -}; - -export const MessageCreateSchema = { - $content: new Length(String, 0, 2000), - $nonce: String, - $tts: Boolean, - $flags: String, - $embed: embed, - // TODO: ^ embed is deprecated in favor of embeds (https://discord.com/developers/docs/resources/channel#message-object) - // $embeds: [embed], - $allowed_mentions: { - $parse: [String], - $roles: [String], - $users: [String], - $replied_user: Boolean - }, - $message_reference: { - message_id: String, - channel_id: String, - $guild_id: String, - $fail_if_not_exists: Boolean - }, - $payload_json: String, - $file: Object -}; - -export interface MessageCreateSchema { - content?: string; - nonce?: string; - tts?: boolean; - flags?: string; - embed?: Embed & { timestamp?: string }; - allowed_mentions?: { - parse?: string[]; - roles?: string[]; - users?: string[]; - replied_user?: boolean; - }; - message_reference?: { - message_id: string; - channel_id: string; - guild_id?: string; - fail_if_not_exists?: boolean; - }; - payload_json?: string; - file?: any; -} diff --git a/api/src/schema/Roles.ts b/api/src/schema/Roles.ts deleted file mode 100644 index e1a34ae8..00000000 --- a/api/src/schema/Roles.ts +++ /dev/null @@ -1,29 +0,0 @@ -export const RoleModifySchema = { - $name: String, - $permissions: BigInt, - $color: Number, - $hoist: Boolean, // whether the role should be displayed separately in the sidebar - $mentionable: Boolean, // whether the role should be mentionable - $position: Number -}; - -export interface RoleModifySchema { - name?: string; - permissions?: bigint; - color?: number; - hoist?: boolean; // whether the role should be displayed separately in the sidebar - mentionable?: boolean; // whether the role should be mentionable - position?: number; -} - -export const RolePositionUpdateSchema = [ - { - id: String, - position: Number - } -]; - -export type RolePositionUpdateSchema = { - id: string; - position: number; -}[]; diff --git a/api/src/schema/Template.ts b/api/src/schema/Template.ts deleted file mode 100644 index 88e36c53..00000000 --- a/api/src/schema/Template.ts +++ /dev/null @@ -1,19 +0,0 @@ -export const TemplateCreateSchema = { - name: String, - $description: String, -}; - -export interface TemplateCreateSchema { - name: string; - description?: string; -} - -export const TemplateModifySchema = { - name: String, - $description: String, -}; - -export interface TemplateModifySchema { - name: string; - description?: string; -} diff --git a/api/src/schema/User.ts b/api/src/schema/User.ts deleted file mode 100644 index 0d094b9e..00000000 --- a/api/src/schema/User.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { UserSettings } from "../../../util/dist"; -import { Length } from "../util/instanceOf"; - -export const UserModifySchema = { - $username: new Length(String, 2, 32), - $avatar: String, - $bio: new Length(String, 0, 190), - $accent_color: Number, - $banner: String, - $password: String, - $new_password: String, - $code: String // 2fa code -}; - -export interface UserModifySchema { - username?: string; - avatar?: string | null; - bio?: string; - accent_color?: number | null; - banner?: string | null; - password?: string; - new_password?: string; - code?: string; -} - -export const UserSettingsSchema = { - $afk_timeout: Number, - $allow_accessibility_detection: Boolean, - $animate_emoji: Boolean, - $animate_stickers: Number, - $contact_sync_enabled: Boolean, - $convert_emoticons: Boolean, - $custom_status: { - $emoji_id: String, - $emoji_name: String, - $expires_at: Number, - $text: String - }, - $default_guilds_restricted: Boolean, - $detect_platform_accounts: Boolean, - $developer_mode: Boolean, - $disable_games_tab: Boolean, - $enable_tts_command: Boolean, - $explicit_content_filter: Number, - $friend_source_flags: { - all: Boolean - }, - $gateway_connected: Boolean, - $gif_auto_play: Boolean, - $guild_folders: [ - { - color: Number, - guild_ids: [String], - id: Number, - name: String - } - ], - $guild_positions: [String], - $inline_attachment_media: Boolean, - $inline_embed_media: Boolean, - $locale: String, - $message_display_compact: Boolean, - $native_phone_integration_enabled: Boolean, - $render_embeds: Boolean, - $render_reactions: Boolean, - $restricted_guilds: [String], - $show_current_game: Boolean, - $status: String, - $stream_notifications_enabled: Boolean, - $theme: String, - $timezone_offset: Number -}; - -export interface UserSettingsSchema extends UserSettings {} diff --git a/api/src/schema/Widget.ts b/api/src/schema/Widget.ts deleted file mode 100644 index d37a38de..00000000 --- a/api/src/schema/Widget.ts +++ /dev/null @@ -1,10 +0,0 @@ -// https://discord.com/developers/docs/resources/guild#guild-widget-object -export const WidgetModifySchema = { - enabled: Boolean, // whether the widget is enabled - channel_id: String // the widget channel id -}; - -export interface WidgetModifySchema { - enabled: boolean; // whether the widget is enabled - channel_id: string; // the widget channel id -} diff --git a/api/src/schema/index.ts b/api/src/schema/index.ts deleted file mode 100644 index b5f38a2f..00000000 --- a/api/src/schema/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -export * from "./Ban"; -export * from "./Channel"; -export * from "./Emoji"; -export * from "./Guild"; -export * from "./Invite"; -export * from "./Member"; -export * from "./Message"; -export * from "./Roles"; -export * from "./Template"; -export * from "./User"; -export * from "./Widget"; diff --git a/api/src/util/Message.ts b/api/src/util/Message.ts index fea553bc..f8230124 100644 --- a/api/src/util/Message.ts +++ b/api/src/util/Message.ts @@ -22,7 +22,7 @@ import { import { HTTPError } from "lambert-server"; import fetch from "node-fetch"; import cheerio from "cheerio"; -import { MessageCreateSchema } from "../schema/Message"; +import { MessageCreateSchema } from "../routes/channels/#channel_id/messages"; // TODO: check webhook, application, system author diff --git a/api/src/util/Voice.ts b/api/src/util/Voice.ts index 087bdfa8..f06b1aaa 100644 --- a/api/src/util/Voice.ts +++ b/api/src/util/Voice.ts @@ -1,32 +1,32 @@ -import {Config} from "@fosscord/util"; -import {distanceBetweenLocations, IPAnalysis} from "./ipAddress"; +import { Config } from "@fosscord/util"; +import { distanceBetweenLocations, IPAnalysis } from "./ipAddress"; export async function getVoiceRegions(ipAddress: string, vip: boolean) { - const regions = Config.get().regions; - const availableRegions = regions.available.filter(ar => vip ? true : !ar.vip); - let optimalId = regions.default + const regions = Config.get().regions; + const availableRegions = regions.available.filter((ar) => (vip ? true : !ar.vip)); + let optimalId = regions.default; - if(!regions.useDefaultAsOptimal) { - const clientIpAnalysis = await IPAnalysis(ipAddress) + if (!regions.useDefaultAsOptimal) { + const clientIpAnalysis = await IPAnalysis(ipAddress); - let min = Number.POSITIVE_INFINITY + let min = Number.POSITIVE_INFINITY; - for (let ar of availableRegions) { - //TODO the endpoint location should be saved in the database if not already present to prevent IPAnalysis call - const dist = distanceBetweenLocations(clientIpAnalysis, ar.location || (await IPAnalysis(ar.endpoint))) + for (let ar of availableRegions) { + //TODO the endpoint location should be saved in the database if not already present to prevent IPAnalysis call + const dist = distanceBetweenLocations(clientIpAnalysis, ar.location || (await IPAnalysis(ar.endpoint))); - if(dist < min) { - min = dist - optimalId = ar.id - } - } - } + if (dist < min) { + min = dist; + optimalId = ar.id; + } + } + } - return availableRegions.map(ar => ({ - id: ar.id, - name: ar.name, - custom: ar.custom, - deprecated: ar.deprecated, - optimal: ar.id === optimalId - })) -} \ No newline at end of file + return availableRegions.map((ar) => ({ + id: ar.id, + name: ar.name, + custom: ar.custom, + deprecated: ar.deprecated, + optimal: ar.id === optimalId + })); +} diff --git a/api/src/util/VoiceState.ts b/api/src/util/VoiceState.ts deleted file mode 100644 index 07022ec9..00000000 --- a/api/src/util/VoiceState.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { Channel, ChannelType, DiscordApiErrors, emitEvent, getPermission, VoiceState, VoiceStateUpdateEvent } from "@fosscord/util"; -import { VoiceStateUpdateSchema } from "../schema"; - - -//TODO need more testing when community guild and voice stage channel are working -export async function updateVoiceState(vsuSchema: VoiceStateUpdateSchema, guildId: string, userId: string, targetUserId?: string) { - const perms = await getPermission(userId, guildId, vsuSchema.channel_id); - - /* - From https://discord.com/developers/docs/resources/guild#modify-current-user-voice-state - You must have the MUTE_MEMBERS permission to unsuppress yourself. You can always suppress yourself. - You must have the REQUEST_TO_SPEAK permission to request to speak. You can always clear your own request to speak. - */ - if (targetUserId !== undefined || (vsuSchema.suppress !== undefined && !vsuSchema.suppress)) { - perms.hasThrow("MUTE_MEMBERS"); - } - if (vsuSchema.request_to_speak_timestamp !== undefined && vsuSchema.request_to_speak_timestamp !== "") { - perms.hasThrow("REQUEST_TO_SPEAK") - } - - if (!targetUserId) { - targetUserId = userId; - } else { - if (vsuSchema.suppress !== undefined && vsuSchema.suppress) - vsuSchema.request_to_speak_timestamp = "" //Need to check if empty string is the right value - } - - //TODO assumed that empty string means clean, need to test if it's right - let voiceState - try { - voiceState = await VoiceState.findOneOrFail({ - guild_id: guildId, - channel_id: vsuSchema.channel_id, - user_id: targetUserId - }); - } catch (error) { - throw DiscordApiErrors.UNKNOWN_VOICE_STATE; - } - - voiceState.assign(vsuSchema); - const channel = await Channel.findOneOrFail({ guild_id: guildId, id: vsuSchema.channel_id }) - if (channel.type !== ChannelType.GUILD_STAGE_VOICE) { - throw DiscordApiErrors.CANNOT_EXECUTE_ON_THIS_CHANNEL_TYPE; - } - - await Promise.all([ - voiceState.save(), - emitEvent({ - event: "VOICE_STATE_UPDATE", - data: voiceState, - guild_id: guildId - } as VoiceStateUpdateEvent)]); - return; -} \ No newline at end of file diff --git a/api/src/util/index.ts b/api/src/util/index.ts index 43481289..c98784a4 100644 --- a/api/src/util/index.ts +++ b/api/src/util/index.ts @@ -8,4 +8,3 @@ export * from "./RandomInviteID"; export * from "./route"; export * from "./String"; export * from "./Voice"; -export * from "./VoiceState"; diff --git a/api/src/util/route.ts b/api/src/util/route.ts index 0302f3ec..f618a630 100644 --- a/api/src/util/route.ts +++ b/api/src/util/route.ts @@ -5,10 +5,20 @@ import path from "path"; import Ajv from "ajv"; import { AnyValidateFunction } from "ajv/dist/core"; import { FieldErrors } from ".."; +import addFormats from "ajv-formats"; const SchemaPath = path.join(__dirname, "..", "..", "assets", "schemas.json"); const schemas = JSON.parse(fs.readFileSync(SchemaPath, { encoding: "utf8" })); -export const ajv = new Ajv({ allErrors: true, parseDate: true, allowDate: true, schemas, messages: true }); +export const ajv = new Ajv({ + allErrors: true, + parseDate: true, + allowDate: true, + schemas, + messages: true, + strict: true, + strictRequired: true +}); +addFormats(ajv); declare global { namespace Express { @@ -19,7 +29,7 @@ declare global { } export type RouteSchema = string; // typescript interface name -export type RouteResponse = { status: number; body?: RouteSchema; headers?: Record }; +export type RouteResponse = { status?: number; body?: RouteSchema; headers?: Record }; export interface RouteOptions { permission?: PermissionResolvable; -- cgit 1.5.1 From e32bb24fa84e5942168433b16f3b0d86aa455a99 Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Mon, 13 Sep 2021 00:00:11 +0200 Subject: :bug: fix invites: ajv doesn't treat null as undefined --- api/assets/schemas.json | 592 +++++++++++-------------- api/scripts/generate_body_schema.ts | 2 +- api/src/routes/channels/#channel_id/invites.ts | 4 +- api/src/util/route.ts | 1 - 4 files changed, 266 insertions(+), 333 deletions(-) (limited to 'api/assets') diff --git a/api/assets/schemas.json b/api/assets/schemas.json index 59ab4c04..ac7df859 100644 --- a/api/assets/schemas.json +++ b/api/assets/schemas.json @@ -177,7 +177,15 @@ "type": "string" }, "type": { - "$ref": "#/definitions/EmbedType" + "enum": [ + "article", + "gifv", + "image", + "link", + "rich", + "video" + ], + "type": "string" }, "description": { "type": "string" @@ -274,17 +282,6 @@ }, "additionalProperties": false }, - "EmbedType": { - "enum": [ - "article", - "gifv", - "image", - "link", - "rich", - "video" - ], - "type": "string" - }, "EmbedImage": { "type": "object", "properties": { @@ -499,7 +496,15 @@ "type": "string" }, "type": { - "$ref": "#/definitions/EmbedType" + "enum": [ + "article", + "gifv", + "image", + "link", + "rich", + "video" + ], + "type": "string" }, "description": { "type": "string" @@ -596,17 +601,6 @@ }, "additionalProperties": false }, - "EmbedType": { - "enum": [ - "article", - "gifv", - "image", - "link", - "rich", - "video" - ], - "type": "string" - }, "EmbedImage": { "type": "object", "properties": { @@ -718,10 +712,16 @@ "type": "string" }, "target_type": { - "type": "string" + "type": [ + "null", + "string" + ] }, "validate": { - "type": "string" + "type": [ + "null", + "string" + ] }, "max_age": { "type": "integer" @@ -774,7 +774,15 @@ "type": "string" }, "type": { - "$ref": "#/definitions/EmbedType" + "enum": [ + "article", + "gifv", + "image", + "link", + "rich", + "video" + ], + "type": "string" }, "description": { "type": "string" @@ -871,17 +879,6 @@ }, "additionalProperties": false }, - "EmbedType": { - "enum": [ - "article", - "gifv", - "image", - "link", - "rich", - "video" - ], - "type": "string" - }, "EmbedImage": { "type": "object", "properties": { @@ -1028,7 +1025,15 @@ "type": "string" }, "type": { - "$ref": "#/definitions/EmbedType" + "enum": [ + "article", + "gifv", + "image", + "link", + "rich", + "video" + ], + "type": "string" }, "description": { "type": "string" @@ -1125,17 +1130,6 @@ }, "additionalProperties": false }, - "EmbedType": { - "enum": [ - "article", - "gifv", - "image", - "link", - "rich", - "video" - ], - "type": "string" - }, "EmbedImage": { "type": "object", "properties": { @@ -1285,7 +1279,15 @@ "type": "string" }, "type": { - "$ref": "#/definitions/EmbedType" + "enum": [ + "article", + "gifv", + "image", + "link", + "rich", + "video" + ], + "type": "string" }, "description": { "type": "string" @@ -1382,17 +1384,6 @@ }, "additionalProperties": false }, - "EmbedType": { - "enum": [ - "article", - "gifv", - "image", - "link", - "rich", - "video" - ], - "type": "string" - }, "EmbedImage": { "type": "object", "properties": { @@ -1551,7 +1542,15 @@ "type": "string" }, "type": { - "$ref": "#/definitions/EmbedType" + "enum": [ + "article", + "gifv", + "image", + "link", + "rich", + "video" + ], + "type": "string" }, "description": { "type": "string" @@ -1648,17 +1647,6 @@ }, "additionalProperties": false }, - "EmbedType": { - "enum": [ - "article", - "gifv", - "image", - "link", - "rich", - "video" - ], - "type": "string" - }, "EmbedImage": { "type": "object", "properties": { @@ -1810,7 +1798,15 @@ "type": "string" }, "type": { - "$ref": "#/definitions/EmbedType" + "enum": [ + "article", + "gifv", + "image", + "link", + "rich", + "video" + ], + "type": "string" }, "description": { "type": "string" @@ -1907,17 +1903,6 @@ }, "additionalProperties": false }, - "EmbedType": { - "enum": [ - "article", - "gifv", - "image", - "link", - "rich", - "video" - ], - "type": "string" - }, "EmbedImage": { "type": "object", "properties": { @@ -2064,7 +2049,15 @@ "type": "string" }, "type": { - "$ref": "#/definitions/EmbedType" + "enum": [ + "article", + "gifv", + "image", + "link", + "rich", + "video" + ], + "type": "string" }, "description": { "type": "string" @@ -2161,17 +2154,6 @@ }, "additionalProperties": false }, - "EmbedType": { - "enum": [ - "article", - "gifv", - "image", - "link", - "rich", - "video" - ], - "type": "string" - }, "EmbedImage": { "type": "object", "properties": { @@ -2330,7 +2312,15 @@ "type": "string" }, "type": { - "$ref": "#/definitions/EmbedType" + "enum": [ + "article", + "gifv", + "image", + "link", + "rich", + "video" + ], + "type": "string" }, "description": { "type": "string" @@ -2427,17 +2417,6 @@ }, "additionalProperties": false }, - "EmbedType": { - "enum": [ - "article", - "gifv", - "image", - "link", - "rich", - "video" - ], - "type": "string" - }, "EmbedImage": { "type": "object", "properties": { @@ -2606,7 +2585,15 @@ "type": "string" }, "type": { - "$ref": "#/definitions/EmbedType" + "enum": [ + "article", + "gifv", + "image", + "link", + "rich", + "video" + ], + "type": "string" }, "description": { "type": "string" @@ -2703,17 +2690,6 @@ }, "additionalProperties": false }, - "EmbedType": { - "enum": [ - "article", - "gifv", - "image", - "link", - "rich", - "video" - ], - "type": "string" - }, "EmbedImage": { "type": "object", "properties": { @@ -2915,7 +2891,15 @@ "type": "string" }, "type": { - "$ref": "#/definitions/EmbedType" + "enum": [ + "article", + "gifv", + "image", + "link", + "rich", + "video" + ], + "type": "string" }, "description": { "type": "string" @@ -3012,17 +2996,6 @@ }, "additionalProperties": false }, - "EmbedType": { - "enum": [ - "article", - "gifv", - "image", - "link", - "rich", - "video" - ], - "type": "string" - }, "EmbedImage": { "type": "object", "properties": { @@ -3169,7 +3142,15 @@ "type": "string" }, "type": { - "$ref": "#/definitions/EmbedType" + "enum": [ + "article", + "gifv", + "image", + "link", + "rich", + "video" + ], + "type": "string" }, "description": { "type": "string" @@ -3266,17 +3247,6 @@ }, "additionalProperties": false }, - "EmbedType": { - "enum": [ - "article", - "gifv", - "image", - "link", - "rich", - "video" - ], - "type": "string" - }, "EmbedImage": { "type": "object", "properties": { @@ -3423,7 +3393,15 @@ "type": "string" }, "type": { - "$ref": "#/definitions/EmbedType" + "enum": [ + "article", + "gifv", + "image", + "link", + "rich", + "video" + ], + "type": "string" }, "description": { "type": "string" @@ -3520,17 +3498,6 @@ }, "additionalProperties": false }, - "EmbedType": { - "enum": [ - "article", - "gifv", - "image", - "link", - "rich", - "video" - ], - "type": "string" - }, "EmbedImage": { "type": "object", "properties": { @@ -3689,7 +3656,15 @@ "type": "string" }, "type": { - "$ref": "#/definitions/EmbedType" + "enum": [ + "article", + "gifv", + "image", + "link", + "rich", + "video" + ], + "type": "string" }, "description": { "type": "string" @@ -3786,17 +3761,6 @@ }, "additionalProperties": false }, - "EmbedType": { - "enum": [ - "article", - "gifv", - "image", - "link", - "rich", - "video" - ], - "type": "string" - }, "EmbedImage": { "type": "object", "properties": { @@ -3950,7 +3914,15 @@ "type": "string" }, "type": { - "$ref": "#/definitions/EmbedType" + "enum": [ + "article", + "gifv", + "image", + "link", + "rich", + "video" + ], + "type": "string" }, "description": { "type": "string" @@ -4047,17 +4019,6 @@ }, "additionalProperties": false }, - "EmbedType": { - "enum": [ - "article", - "gifv", - "image", - "link", - "rich", - "video" - ], - "type": "string" - }, "EmbedImage": { "type": "object", "properties": { @@ -4207,7 +4168,15 @@ "type": "string" }, "type": { - "$ref": "#/definitions/EmbedType" + "enum": [ + "article", + "gifv", + "image", + "link", + "rich", + "video" + ], + "type": "string" }, "description": { "type": "string" @@ -4304,17 +4273,6 @@ }, "additionalProperties": false }, - "EmbedType": { - "enum": [ - "article", - "gifv", - "image", - "link", - "rich", - "video" - ], - "type": "string" - }, "EmbedImage": { "type": "object", "properties": { @@ -4464,7 +4422,15 @@ "type": "string" }, "type": { - "$ref": "#/definitions/EmbedType" + "enum": [ + "article", + "gifv", + "image", + "link", + "rich", + "video" + ], + "type": "string" }, "description": { "type": "string" @@ -4561,17 +4527,6 @@ }, "additionalProperties": false }, - "EmbedType": { - "enum": [ - "article", - "gifv", - "image", - "link", - "rich", - "video" - ], - "type": "string" - }, "EmbedImage": { "type": "object", "properties": { @@ -4717,7 +4672,15 @@ "type": "string" }, "type": { - "$ref": "#/definitions/EmbedType" + "enum": [ + "article", + "gifv", + "image", + "link", + "rich", + "video" + ], + "type": "string" }, "description": { "type": "string" @@ -4814,17 +4777,6 @@ }, "additionalProperties": false }, - "EmbedType": { - "enum": [ - "article", - "gifv", - "image", - "link", - "rich", - "video" - ], - "type": "string" - }, "EmbedImage": { "type": "object", "properties": { @@ -4990,7 +4942,15 @@ "type": "string" }, "type": { - "$ref": "#/definitions/EmbedType" + "enum": [ + "article", + "gifv", + "image", + "link", + "rich", + "video" + ], + "type": "string" }, "description": { "type": "string" @@ -5087,17 +5047,6 @@ }, "additionalProperties": false }, - "EmbedType": { - "enum": [ - "article", - "gifv", - "image", - "link", - "rich", - "video" - ], - "type": "string" - }, "EmbedImage": { "type": "object", "properties": { @@ -5270,7 +5219,15 @@ "type": "string" }, "type": { - "$ref": "#/definitions/EmbedType" + "enum": [ + "article", + "gifv", + "image", + "link", + "rich", + "video" + ], + "type": "string" }, "description": { "type": "string" @@ -5367,17 +5324,6 @@ }, "additionalProperties": false }, - "EmbedType": { - "enum": [ - "article", - "gifv", - "image", - "link", - "rich", - "video" - ], - "type": "string" - }, "EmbedImage": { "type": "object", "properties": { @@ -5528,7 +5474,15 @@ "type": "string" }, "type": { - "$ref": "#/definitions/EmbedType" + "enum": [ + "article", + "gifv", + "image", + "link", + "rich", + "video" + ], + "type": "string" }, "description": { "type": "string" @@ -5625,17 +5579,6 @@ }, "additionalProperties": false }, - "EmbedType": { - "enum": [ - "article", - "gifv", - "image", - "link", - "rich", - "video" - ], - "type": "string" - }, "EmbedImage": { "type": "object", "properties": { @@ -5785,7 +5728,15 @@ "type": "string" }, "type": { - "$ref": "#/definitions/EmbedType" + "enum": [ + "article", + "gifv", + "image", + "link", + "rich", + "video" + ], + "type": "string" }, "description": { "type": "string" @@ -5882,17 +5833,6 @@ }, "additionalProperties": false }, - "EmbedType": { - "enum": [ - "article", - "gifv", - "image", - "link", - "rich", - "video" - ], - "type": "string" - }, "EmbedImage": { "type": "object", "properties": { @@ -6045,7 +5985,15 @@ "type": "string" }, "type": { - "$ref": "#/definitions/EmbedType" + "enum": [ + "article", + "gifv", + "image", + "link", + "rich", + "video" + ], + "type": "string" }, "description": { "type": "string" @@ -6142,17 +6090,6 @@ }, "additionalProperties": false }, - "EmbedType": { - "enum": [ - "article", - "gifv", - "image", - "link", - "rich", - "video" - ], - "type": "string" - }, "EmbedImage": { "type": "object", "properties": { @@ -6266,17 +6203,26 @@ "type": "string" }, "avatar": { - "type": "string" + "type": [ + "null", + "string" + ] }, "bio": { "maxLength": 1024, "type": "string" }, "accent_color": { - "type": "integer" + "type": [ + "null", + "integer" + ] }, "banner": { - "type": "string" + "type": [ + "null", + "string" + ] }, "password": { "type": "string" @@ -6320,7 +6266,15 @@ "type": "string" }, "type": { - "$ref": "#/definitions/EmbedType" + "enum": [ + "article", + "gifv", + "image", + "link", + "rich", + "video" + ], + "type": "string" }, "description": { "type": "string" @@ -6417,17 +6371,6 @@ }, "additionalProperties": false }, - "EmbedType": { - "enum": [ - "article", - "gifv", - "image", - "link", - "rich", - "video" - ], - "type": "string" - }, "EmbedImage": { "type": "object", "properties": { @@ -6574,7 +6517,15 @@ "type": "string" }, "type": { - "$ref": "#/definitions/EmbedType" + "enum": [ + "article", + "gifv", + "image", + "link", + "rich", + "video" + ], + "type": "string" }, "description": { "type": "string" @@ -6671,17 +6622,6 @@ }, "additionalProperties": false }, - "EmbedType": { - "enum": [ - "article", - "gifv", - "image", - "link", - "rich", - "video" - ], - "type": "string" - }, "EmbedImage": { "type": "object", "properties": { @@ -6832,7 +6772,15 @@ "type": "string" }, "type": { - "$ref": "#/definitions/EmbedType" + "enum": [ + "article", + "gifv", + "image", + "link", + "rich", + "video" + ], + "type": "string" }, "description": { "type": "string" @@ -6929,17 +6877,6 @@ }, "additionalProperties": false }, - "EmbedType": { - "enum": [ - "article", - "gifv", - "image", - "link", - "rich", - "video" - ], - "type": "string" - }, "EmbedImage": { "type": "object", "properties": { @@ -7273,7 +7210,15 @@ "type": "string" }, "type": { - "$ref": "#/definitions/EmbedType" + "enum": [ + "article", + "gifv", + "image", + "link", + "rich", + "video" + ], + "type": "string" }, "description": { "type": "string" @@ -7370,17 +7315,6 @@ }, "additionalProperties": false }, - "EmbedType": { - "enum": [ - "article", - "gifv", - "image", - "link", - "rich", - "video" - ], - "type": "string" - }, "EmbedImage": { "type": "object", "properties": { diff --git a/api/scripts/generate_body_schema.ts b/api/scripts/generate_body_schema.ts index c406cab8..316e5a69 100644 --- a/api/scripts/generate_body_schema.ts +++ b/api/scripts/generate_body_schema.ts @@ -15,7 +15,7 @@ const settings: TJS.PartialArgs = { defaultProps: false }; const compilerOptions: TJS.CompilerOptions = { - strictNullChecks: false + strictNullChecks: true }; const ExcludedSchemas = ["DefaultSchema", "Schema", "EntitySchema"]; diff --git a/api/src/routes/channels/#channel_id/invites.ts b/api/src/routes/channels/#channel_id/invites.ts index 39263185..2edb4fc2 100644 --- a/api/src/routes/channels/#channel_id/invites.ts +++ b/api/src/routes/channels/#channel_id/invites.ts @@ -9,8 +9,8 @@ const router: Router = Router(); export interface InviteCreateSchema { target_user_id?: string; - target_type?: string; - validate?: string; //? wtf is this + target_type?: string | null; + validate?: string | null; // ? what is this max_age?: number; max_uses?: number; temporary?: boolean; diff --git a/api/src/util/route.ts b/api/src/util/route.ts index f618a630..6cd8f622 100644 --- a/api/src/util/route.ts +++ b/api/src/util/route.ts @@ -55,7 +55,6 @@ export function route(opts: RouteOptions) { if (opts.permission) { const required = new Permissions(opts.permission); const permission = await getPermission(req.user_id, req.params.guild_id, req.params.channel_id); - console.log(required.bitfield, permission.bitfield, permission.bitfield & required.bitfield); // bitfield comparison: check if user lacks certain permission if (!permission.has(required)) { -- cgit 1.5.1 From aa1f1a22a4cce0c51d84c10d5a741699f7bbfff2 Mon Sep 17 00:00:00 2001 From: AlTech98 Date: Mon, 13 Sep 2021 17:32:31 +0200 Subject: Delete attachments of deleted messages, fix #273 --- api/assets/schemas.json | 6 +++++- .../channels/#channel_id/messages/#message_id/index.ts | 7 ++++--- api/src/routes/channels/#channel_id/messages/index.ts | 1 + api/src/util/Attachments.ts | 12 ++++++++++++ api/src/util/cdn.ts | 13 +++++++++++++ cdn/src/util/FileStorage.ts | 1 + 6 files changed, 36 insertions(+), 4 deletions(-) create mode 100644 api/src/util/Attachments.ts (limited to 'api/assets') diff --git a/api/assets/schemas.json b/api/assets/schemas.json index ac7df859..94aa0660 100644 --- a/api/assets/schemas.json +++ b/api/assets/schemas.json @@ -462,7 +462,11 @@ "payload_json": { "type": "string" }, - "file": {} + "file": {}, + "attachments": { + "type": "array", + "items": {} + } }, "additionalProperties": false, "definitions": { 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 d0f780db..b5220fab 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,6 +3,7 @@ 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 @@ -11,7 +12,7 @@ router.patch("/", route({ body: "MessageCreateSchema", permission: "SEND_MESSAGE const { message_id, channel_id } = req.params; var body = req.body as MessageCreateSchema; - const message = await Message.findOneOrFail({ id: message_id, channel_id }); + const message = await Message.findOneOrFail({ where: { id: message_id, channel_id }, relations: ["attachments"] }); const permissions = await getPermission(req.user_id, undefined, channel_id); @@ -33,6 +34,7 @@ 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", @@ -46,8 +48,6 @@ router.patch("/", route({ body: "MessageCreateSchema", permission: "SEND_MESSAGE return res.json(message); }); -// TODO: delete attachments in message - // permission check only if deletes messagr from other user router.delete("/", route({}), async (req: Request, res: Response) => { const { message_id, channel_id } = req.params; @@ -60,6 +60,7 @@ 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/routes/channels/#channel_id/messages/index.ts b/api/src/routes/channels/#channel_id/messages/index.ts index 11334367..25ecc1c7 100644 --- a/api/src/routes/channels/#channel_id/messages/index.ts +++ b/api/src/routes/channels/#channel_id/messages/index.ts @@ -51,6 +51,7 @@ export interface MessageCreateSchema { }; payload_json?: string; file?: any; + attachments?: any[]; //TODO we should create an interface for attachments } // https://discord.com/developers/docs/resources/channel#create-message diff --git a/api/src/util/Attachments.ts b/api/src/util/Attachments.ts new file mode 100644 index 00000000..addda97f --- /dev/null +++ b/api/src/util/Attachments.ts @@ -0,0 +1,12 @@ +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/cdn.ts b/api/src/util/cdn.ts index 3c71d980..88b0ea0d 100644 --- a/api/src/util/cdn.ts +++ b/api/src/util/cdn.ts @@ -38,3 +38,16 @@ export async function handleFile(path: string, body?: string): Promise Date: Mon, 13 Sep 2021 19:25:44 +0200 Subject: Fix #356 --- api/assets/schemas.json | 35 +++++++++++++++++++++++++------- api/src/routes/guilds/#guild_id/index.ts | 10 ++++----- api/src/routes/guilds/index.ts | 2 +- 3 files changed, 34 insertions(+), 13 deletions(-) (limited to 'api/assets') diff --git a/api/assets/schemas.json b/api/assets/schemas.json index 94aa0660..3f760c35 100644 --- a/api/assets/schemas.json +++ b/api/assets/schemas.json @@ -2548,7 +2548,10 @@ "type": "string" }, "system_channel_id": { - "type": "string" + "type": [ + "null", + "string" + ] }, "rules_channel_id": { "type": "string" @@ -2802,13 +2805,22 @@ "type": "object", "properties": { "banner": { - "type": "string" + "type": [ + "null", + "string" + ] }, "splash": { - "type": "string" + "type": [ + "null", + "string" + ] }, "description": { - "type": "string" + "type": [ + "null", + "string" + ] }, "features": { "type": "array", @@ -2829,13 +2841,19 @@ "type": "integer" }, "public_updates_channel_id": { - "type": "string" + "type": [ + "null", + "string" + ] }, "afk_timeout": { "type": "integer" }, "afk_channel_id": { - "type": "string" + "type": [ + "null", + "string" + ] }, "preferred_locale": { "type": "string" @@ -2854,7 +2872,10 @@ "type": "string" }, "system_channel_id": { - "type": "string" + "type": [ + "null", + "string" + ] }, "rules_channel_id": { "type": "string" diff --git a/api/src/routes/guilds/#guild_id/index.ts b/api/src/routes/guilds/#guild_id/index.ts index 690d4103..9c67798d 100644 --- a/api/src/routes/guilds/#guild_id/index.ts +++ b/api/src/routes/guilds/#guild_id/index.ts @@ -9,17 +9,17 @@ import { GuildCreateSchema } from "../index"; const router = Router(); export interface GuildUpdateSchema extends Omit { - banner?: string; - splash?: string; - description?: string; + banner?: string | null; + splash?: string | null; + description?: string | null; features?: string[]; verification_level?: number; default_message_notifications?: number; system_channel_flags?: number; explicit_content_filter?: number; - public_updates_channel_id?: string; + public_updates_channel_id?: string | null; afk_timeout?: number; - afk_channel_id?: string; + afk_channel_id?: string | null; preferred_locale?: string; } diff --git a/api/src/routes/guilds/index.ts b/api/src/routes/guilds/index.ts index ba951f96..674dc16b 100644 --- a/api/src/routes/guilds/index.ts +++ b/api/src/routes/guilds/index.ts @@ -16,7 +16,7 @@ export interface GuildCreateSchema { icon?: string; channels?: ChannelModifySchema[]; guild_template_code?: string; - system_channel_id?: string; + system_channel_id?: string | null; rules_channel_id?: string; } -- cgit 1.5.1 From 8f68c4abcf8cb1e15a694795a3a13538bc4f1dcc Mon Sep 17 00:00:00 2001 From: AlTech98 Date: Tue, 14 Sep 2021 09:38:21 +0200 Subject: Fix invites creation --- api/assets/schemas.json | 5 ++++- api/src/routes/channels/#channel_id/invites.ts | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'api/assets') diff --git a/api/assets/schemas.json b/api/assets/schemas.json index 3f760c35..9c34f968 100644 --- a/api/assets/schemas.json +++ b/api/assets/schemas.json @@ -713,7 +713,10 @@ "type": "object", "properties": { "target_user_id": { - "type": "string" + "type": [ + "null", + "string" + ] }, "target_type": { "type": [ diff --git a/api/src/routes/channels/#channel_id/invites.ts b/api/src/routes/channels/#channel_id/invites.ts index 2edb4fc2..71612e31 100644 --- a/api/src/routes/channels/#channel_id/invites.ts +++ b/api/src/routes/channels/#channel_id/invites.ts @@ -8,7 +8,7 @@ import { isTextChannel } from "./messages"; const router: Router = Router(); export interface InviteCreateSchema { - target_user_id?: string; + target_user_id?: string | null; target_type?: string | null; validate?: string | null; // ? what is this max_age?: number; -- cgit 1.5.1 From df2b83ac158be1e7233d8edce59033c15c193599 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 'api/assets') 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 d2d7dd0561e9ccfbf68caccafffa114a45b29fc0 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 df2b83ac158be1e7233d8edce59033c15c193599. --- 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 'api/assets') 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 50ab5e7d490413388a8365a82af43c40b252beec 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 'api/assets') 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 859fdd679b2f42ae4fd90b3a1a7958370fcdccb8 Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Fri, 17 Sep 2021 23:42:40 +0200 Subject: :bug: fix body parse treating null not as undefined (except for icons/avatars) --- api/assets/schemas.json | 63 +++++++++----------------- api/package.json | 3 +- api/scripts/globalSetup.js | 3 +- api/src/routes/auth/register.ts | 30 ++++++------ api/src/routes/channels/#channel_id/invites.ts | 6 +-- api/src/routes/guilds/#guild_id/index.ts | 6 +-- api/src/routes/guilds/index.ts | 4 +- api/src/routes/guilds/templates/index.ts | 2 +- api/src/routes/users/@me/index.ts | 2 +- api/src/util/route.ts | 45 ++++++++++++++---- 10 files changed, 88 insertions(+), 76 deletions(-) (limited to 'api/assets') diff --git a/api/assets/schemas.json b/api/assets/schemas.json index 9c34f968..e27087a9 100644 --- a/api/assets/schemas.json +++ b/api/assets/schemas.json @@ -26,8 +26,7 @@ "type": "string" }, "date_of_birth": { - "type": "string", - "format": "date-time" + "type": "string" }, "gift_code_sku_id": { "type": "string" @@ -713,22 +712,13 @@ "type": "object", "properties": { "target_user_id": { - "type": [ - "null", - "string" - ] + "type": "string" }, "target_type": { - "type": [ - "null", - "string" - ] + "type": "string" }, "validate": { - "type": [ - "null", - "string" - ] + "type": "string" }, "max_age": { "type": "integer" @@ -2539,7 +2529,10 @@ "type": "string" }, "icon": { - "type": "string" + "type": [ + "null", + "string" + ] }, "channels": { "type": "array", @@ -2551,10 +2544,7 @@ "type": "string" }, "system_channel_id": { - "type": [ - "null", - "string" - ] + "type": "string" }, "rules_channel_id": { "type": "string" @@ -2820,10 +2810,7 @@ ] }, "description": { - "type": [ - "null", - "string" - ] + "type": "string" }, "features": { "type": "array", @@ -2844,19 +2831,13 @@ "type": "integer" }, "public_updates_channel_id": { - "type": [ - "null", - "string" - ] + "type": "string" }, "afk_timeout": { "type": "integer" }, "afk_channel_id": { - "type": [ - "null", - "string" - ] + "type": "string" }, "preferred_locale": { "type": "string" @@ -2869,16 +2850,16 @@ "type": "string" }, "icon": { - "type": "string" + "type": [ + "null", + "string" + ] }, "guild_template_code": { "type": "string" }, "system_channel_id": { - "type": [ - "null", - "string" - ] + "type": "string" }, "rules_channel_id": { "type": "string" @@ -5718,7 +5699,10 @@ "type": "string" }, "avatar": { - "type": "string" + "type": [ + "null", + "string" + ] } }, "additionalProperties": false, @@ -6241,10 +6225,7 @@ "type": "string" }, "accent_color": { - "type": [ - "null", - "integer" - ] + "type": "integer" }, "banner": { "type": [ diff --git a/api/package.json b/api/package.json index d93a6269..ad959e57 100644 --- a/api/package.json +++ b/api/package.json @@ -5,7 +5,8 @@ "main": "dist/Server.js", "types": "dist/Server.d.ts", "scripts": { - "test": "npm run build && jest --coverage --verbose --forceExit ./tests", + "test:only": "node -r ./scripts/tsconfig-paths-bootstrap.js node_modules/.bin/jest --coverage --verbose --forceExit ./tests", + "test": "npm run build && npm run test:only", "test:watch": "jest --watch", "start": "npm run build && node -r ./scripts/tsconfig-paths-bootstrap.js dist/start", "build": "npx tsc -b .", diff --git a/api/scripts/globalSetup.js b/api/scripts/globalSetup.js index 76cd8e0d..98e70fb9 100644 --- a/api/scripts/globalSetup.js +++ b/api/scripts/globalSetup.js @@ -1,10 +1,11 @@ const fs = require("fs"); +const path = require("path"); const { FosscordServer } = require("../dist/Server"); const Server = new FosscordServer({ port: 3001 }); global.server = Server; module.exports = async () => { try { - fs.unlinkSync(`${__dirname}/../database.db`); + fs.unlinkSync(path.join(__dirname, "..", "database.db")); } catch {} return await Server.start(); }; diff --git a/api/src/routes/auth/register.ts b/api/src/routes/auth/register.ts index 33f089b2..efe91625 100644 --- a/api/src/routes/auth/register.ts +++ b/api/src/routes/auth/register.ts @@ -27,13 +27,16 @@ export interface RegisterSchema { email?: string; fingerprint?: string; invite?: string; + /** + * @TJS-type string + */ date_of_birth?: Date; // "2000-04-03" gift_code_sku_id?: string; captcha_key?: string; } router.post("/", route({ body: "RegisterSchema" }), async (req: Request, res: Response) => { - const { + let { email, username, password, @@ -61,14 +64,11 @@ router.post("/", route({ body: "RegisterSchema" }), async (req: Request, res: Re // TODO: gift_code_sku_id? // TODO: check password strength - // adjusted_email will be slightly modified version of the user supplied email -> e.g. protection against GMail Trick - let adjusted_email = adjustEmail(email); - - // adjusted_password will be the hash of the password - let adjusted_password = ""; + // email will be slightly modified version of the user supplied email -> e.g. protection against GMail Trick + email = adjustEmail(email); // trim special uf8 control characters -> Backspace, Newline, ... - let adjusted_username = trimSpecial(username); + username = trimSpecial(username); // discriminator will be randomly generated let discriminator = ""; @@ -96,10 +96,10 @@ router.post("/", route({ body: "RegisterSchema" }), async (req: Request, res: Re if (email) { // replace all dots and chars after +, if its a gmail.com email - if (!adjusted_email) throw FieldErrors({ email: { code: "INVALID_EMAIL", message: req.t("auth:register.INVALID_EMAIL") } }); + if (!email) throw FieldErrors({ email: { code: "INVALID_EMAIL", message: req.t("auth:register.INVALID_EMAIL") } }); // check if there is already an account with this email - const exists = await User.findOneOrFail({ email: adjusted_email }).catch((e) => {}); + const exists = await User.findOneOrFail({ email: email }).catch((e) => {}); if (exists) { throw FieldErrors({ @@ -122,6 +122,7 @@ router.post("/", route({ body: "RegisterSchema" }), async (req: Request, res: Re } else if (register.dateOfBirth.minimum) { const minimum = new Date(); minimum.setFullYear(minimum.getFullYear() - register.dateOfBirth.minimum); + date_of_birth = new Date(date_of_birth); // higher is younger if (date_of_birth > minimum) { @@ -162,7 +163,7 @@ router.post("/", route({ body: "RegisterSchema" }), async (req: Request, res: Re } // the salt is saved in the password refer to bcrypt docs - adjusted_password = await bcrypt.hash(password, 12); + password = await bcrypt.hash(password, 12); let exists; // randomly generates a discriminator between 1 and 9999 and checks max five times if it already exists @@ -171,7 +172,7 @@ router.post("/", route({ body: "RegisterSchema" }), async (req: Request, res: Re // TODO: is there any better way to generate a random discriminator only once, without checking if it already exists in the mongodb database? for (let tries = 0; tries < 5; tries++) { discriminator = Math.randomIntBetween(1, 9999).toString().padStart(4, "0"); - exists = await User.findOne({ where: { discriminator, username: adjusted_username }, select: ["id"] }); + exists = await User.findOne({ where: { discriminator, username: username }, select: ["id"] }); if (!exists) break; } @@ -190,7 +191,7 @@ router.post("/", route({ body: "RegisterSchema" }), async (req: Request, res: Re const user = await new User({ created_at: new Date(), - username: adjusted_username, + username: username, discriminator, id: Snowflake.generate(), bot: false, @@ -204,12 +205,12 @@ router.post("/", route({ body: "RegisterSchema" }), async (req: Request, res: Re verified: false, disabled: false, deleted: false, - email: adjusted_email, + email: email, nsfw_allowed: true, // TODO: depending on age public_flags: "0", flags: "0", // TODO: generate data: { - hash: adjusted_password, + hash: password, valid_tokens_since: new Date() }, settings: { ...defaultSettings, locale: req.language || "en-US" }, @@ -220,6 +221,7 @@ router.post("/", route({ body: "RegisterSchema" }), async (req: Request, res: Re }); 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 diff --git a/api/src/routes/channels/#channel_id/invites.ts b/api/src/routes/channels/#channel_id/invites.ts index 71612e31..22420983 100644 --- a/api/src/routes/channels/#channel_id/invites.ts +++ b/api/src/routes/channels/#channel_id/invites.ts @@ -8,9 +8,9 @@ import { isTextChannel } from "./messages"; const router: Router = Router(); export interface InviteCreateSchema { - target_user_id?: string | null; - target_type?: string | null; - validate?: string | null; // ? what is this + target_user_id?: string; + target_type?: string; + validate?: string; // ? what is this max_age?: number; max_uses?: number; temporary?: boolean; diff --git a/api/src/routes/guilds/#guild_id/index.ts b/api/src/routes/guilds/#guild_id/index.ts index 7e4bf28a..63000b84 100644 --- a/api/src/routes/guilds/#guild_id/index.ts +++ b/api/src/routes/guilds/#guild_id/index.ts @@ -11,15 +11,15 @@ const router = Router(); export interface GuildUpdateSchema extends Omit { banner?: string | null; splash?: string | null; - description?: string | null; + description?: string; features?: string[]; verification_level?: number; default_message_notifications?: number; system_channel_flags?: number; explicit_content_filter?: number; - public_updates_channel_id?: string | null; + public_updates_channel_id?: string; afk_timeout?: number; - afk_channel_id?: string | null; + afk_channel_id?: string; preferred_locale?: string; } diff --git a/api/src/routes/guilds/index.ts b/api/src/routes/guilds/index.ts index 2334bb9c..2e68d953 100644 --- a/api/src/routes/guilds/index.ts +++ b/api/src/routes/guilds/index.ts @@ -12,10 +12,10 @@ export interface GuildCreateSchema { */ name: string; region?: string; - icon?: string; + icon?: string | null; channels?: ChannelModifySchema[]; guild_template_code?: string; - system_channel_id?: string | null; + system_channel_id?: string; rules_channel_id?: string; } diff --git a/api/src/routes/guilds/templates/index.ts b/api/src/routes/guilds/templates/index.ts index eb3867c8..b5e243e9 100644 --- a/api/src/routes/guilds/templates/index.ts +++ b/api/src/routes/guilds/templates/index.ts @@ -6,7 +6,7 @@ import { DiscordApiErrors } from "@fosscord/util"; export interface GuildTemplateCreateSchema { name: string; - avatar?: string; + avatar?: string | null; } router.get("/:code", route({}), async (req: Request, res: Response) => { diff --git a/api/src/routes/users/@me/index.ts b/api/src/routes/users/@me/index.ts index c0002d79..da2f3348 100644 --- a/api/src/routes/users/@me/index.ts +++ b/api/src/routes/users/@me/index.ts @@ -16,7 +16,7 @@ export interface UserModifySchema { * @maxLength 1024 */ bio?: string; - accent_color?: number | null; + accent_color?: number; banner?: string | null; password?: string; new_password?: string; diff --git a/api/src/util/route.ts b/api/src/util/route.ts index 6cd8f622..678ca64c 100644 --- a/api/src/util/route.ts +++ b/api/src/util/route.ts @@ -43,10 +43,37 @@ export interface RouteOptions { }; } +// Normalizer is introduced to workaround https://github.com/ajv-validator/ajv/issues/1287 +// this removes null values as ajv doesn't treat them as undefined +// normalizeBody allows to handle circular structures without issues +// taken from https://github.com/serverless/serverless/blob/master/lib/classes/ConfigSchemaHandler/index.js#L30 (MIT license) +const normalizeBody = (body: any = {}) => { + const normalizedObjectsSet = new WeakSet(); + const normalizeObject = (object: any) => { + if (normalizedObjectsSet.has(object)) return; + normalizedObjectsSet.add(object); + if (Array.isArray(object)) { + for (const [index, value] of object.entries()) { + if (typeof value === "object") normalizeObject(value); + } + } else { + for (const [key, value] of Object.entries(object)) { + if (value == null) { + if (key === "icon" || key === "avatar" || key === "banner" || key === "splash") continue; + delete object[key]; + } else if (typeof value === "object") { + normalizeObject(value); + } + } + } + }; + normalizeObject(body); + return body; +}; + export function route(opts: RouteOptions) { - var validate: AnyValidateFunction; + var validate: AnyValidateFunction | undefined; if (opts.body) { - // @ts-ignore validate = ajv.getSchema(opts.body); if (!validate) throw new Error(`Body schema ${opts.body} not found`); } @@ -60,14 +87,14 @@ export function route(opts: RouteOptions) { if (!permission.has(required)) { throw DiscordApiErrors.MISSING_PERMISSIONS.withParams(opts.permission as string); } + } - if (validate) { - const valid = validate(req.body); - if (!valid) { - const fields: Record = {}; - validate.errors?.forEach((x) => (fields[x.instancePath] = { code: x.keyword, message: x.message || "" })); - throw FieldErrors(fields); - } + if (validate) { + const valid = validate(normalizeBody(req.body)); + if (!valid) { + const fields: Record = {}; + validate.errors?.forEach((x) => (fields[x.instancePath.slice(1)] = { code: x.keyword, message: x.message || "" })); + throw FieldErrors(fields); } } next(); -- cgit 1.5.1 From 69550e535e990ded1e6bd8763e4f48299f70584a Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Sat, 18 Sep 2021 01:49:36 +0200 Subject: :sparkles: generate test responses --- api/assets/responses.json | 90 +++++++++++++++++++++++++++++++++ api/scripts/generate_openapi_schema.ts | 41 +++++++-------- api/scripts/generate_test_schema.ts | 68 +++++++++++++++++++++++++ api/scripts/globalSetup.js | 15 ------ api/scripts/tsconfig-paths-bootstrap.js | 10 ---- 5 files changed, 175 insertions(+), 49 deletions(-) create mode 100644 api/assets/responses.json create mode 100644 api/scripts/generate_test_schema.ts delete mode 100644 api/scripts/globalSetup.js delete mode 100644 api/scripts/tsconfig-paths-bootstrap.js (limited to 'api/assets') diff --git a/api/assets/responses.json b/api/assets/responses.json new file mode 100644 index 00000000..35645d73 --- /dev/null +++ b/api/assets/responses.json @@ -0,0 +1,90 @@ +{ + "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/scripts/generate_openapi_schema.ts b/api/scripts/generate_openapi_schema.ts index 329aeaf4..c0995b6c 100644 --- a/api/scripts/generate_openapi_schema.ts +++ b/api/scripts/generate_openapi_schema.ts @@ -48,34 +48,27 @@ function combineSchemas(opts: { program: TJS.Program; generator: TJS.JsonSchemaG 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 = [ - "BanCreateSchema", - "DmChannelCreateSchema", - "ChannelModifySchema", - "ChannelGuildPositionUpdateSchema", - "ChannelGuildPositionUpdateSchema", - "EmojiCreateSchema", - "GuildCreateSchema", - "GuildUpdateSchema", - "GuildTemplateCreateSchema", - "GuildUpdateWelcomeScreenSchema", - "InviteCreateSchema", - "MemberCreateSchema", - "MemberNickChangeSchema", - "MemberChangeSchema", - "MessageCreateSchema", - "RoleModifySchema", - "TemplateCreateSchema", - "TemplateModifySchema", - "UserModifySchema", - "UserSettingsSchema", - "WidgetModifySchema", - "" - ]; + 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 }); diff --git a/api/scripts/generate_test_schema.ts b/api/scripts/generate_test_schema.ts new file mode 100644 index 00000000..eed77738 --- /dev/null +++ b/api/scripts/generate_test_schema.ts @@ -0,0 +1,68 @@ +// 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/scripts/globalSetup.js b/api/scripts/globalSetup.js deleted file mode 100644 index 98e70fb9..00000000 --- a/api/scripts/globalSetup.js +++ /dev/null @@ -1,15 +0,0 @@ -const fs = require("fs"); -const path = require("path"); -const { FosscordServer } = require("../dist/Server"); -const Server = new FosscordServer({ port: 3001 }); -global.server = Server; -module.exports = async () => { - try { - fs.unlinkSync(path.join(__dirname, "..", "database.db")); - } catch {} - return await Server.start(); -}; - -// afterAll(async () => { -// return await Server.stop(); -// }); diff --git a/api/scripts/tsconfig-paths-bootstrap.js b/api/scripts/tsconfig-paths-bootstrap.js deleted file mode 100644 index d6ad3c57..00000000 --- a/api/scripts/tsconfig-paths-bootstrap.js +++ /dev/null @@ -1,10 +0,0 @@ -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/*"] - } -}); -- cgit 1.5.1 From dd9ec0c6a0dc3fb87df635ca64c40fab598f753e 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/routes/auth/register.ts | 36 ++++++++++++++++++++++-------------- api/src/routes/invites/index.ts | 9 ++------- util/src/entities/Config.ts | 10 ++++++---- util/src/entities/Invite.ts | 10 ++++++++++ 6 files changed, 41 insertions(+), 27 deletions(-) (limited to 'api/assets') 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/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 5b3ac6dadbfec8d2a0411858dfdfa715b7ab06ee Mon Sep 17 00:00:00 2001 From: Flam3rboy <34555296+Flam3rboy@users.noreply.github.com> Date: Mon, 20 Sep 2021 21:34:33 +0200 Subject: :bug: fix relationships --- api/assets/schemas.json | 254 +----------------------------- api/src/routes/users/@me/relationships.ts | 14 +- 2 files changed, 14 insertions(+), 254 deletions(-) (limited to 'api/assets') diff --git a/api/assets/schemas.json b/api/assets/schemas.json index da193b28..cc45ebb3 100644 --- a/api/assets/schemas.json +++ b/api/assets/schemas.json @@ -385,15 +385,6 @@ } }, "additionalProperties": false - }, - "RelationshipType": { - "enum": [ - 1, - 2, - 3, - 4 - ], - "type": "number" } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -707,15 +698,6 @@ } }, "additionalProperties": false - }, - "RelationshipType": { - "enum": [ - 1, - 2, - 3, - 4 - ], - "type": "number" } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -978,15 +960,6 @@ } }, "additionalProperties": false - }, - "RelationshipType": { - "enum": [ - 1, - 2, - 3, - 4 - ], - "type": "number" } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -1228,15 +1201,6 @@ } }, "additionalProperties": false - }, - "RelationshipType": { - "enum": [ - 1, - 2, - 3, - 4 - ], - "type": "number" } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -1481,15 +1445,6 @@ } }, "additionalProperties": false - }, - "RelationshipType": { - "enum": [ - 1, - 2, - 3, - 4 - ], - "type": "number" } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -1743,15 +1698,6 @@ } }, "additionalProperties": false - }, - "RelationshipType": { - "enum": [ - 1, - 2, - 3, - 4 - ], - "type": "number" } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -1998,15 +1944,6 @@ } }, "additionalProperties": false - }, - "RelationshipType": { - "enum": [ - 1, - 2, - 3, - 4 - ], - "type": "number" } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -2248,15 +2185,6 @@ } }, "additionalProperties": false - }, - "RelationshipType": { - "enum": [ - 1, - 2, - 3, - 4 - ], - "type": "number" } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -2510,15 +2438,6 @@ } }, "additionalProperties": false - }, - "RelationshipType": { - "enum": [ - 1, - 2, - 3, - 4 - ], - "type": "number" } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -2785,15 +2704,6 @@ } }, "additionalProperties": false - }, - "RelationshipType": { - "enum": [ - 1, - 2, - 3, - 4 - ], - "type": "number" } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -3099,15 +3009,6 @@ } }, "additionalProperties": false - }, - "RelationshipType": { - "enum": [ - 1, - 2, - 3, - 4 - ], - "type": "number" } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -3349,15 +3250,6 @@ } }, "additionalProperties": false - }, - "RelationshipType": { - "enum": [ - 1, - 2, - 3, - 4 - ], - "type": "number" } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -3599,15 +3491,6 @@ } }, "additionalProperties": false - }, - "RelationshipType": { - "enum": [ - 1, - 2, - 3, - 4 - ], - "type": "number" } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -3861,15 +3744,6 @@ } }, "additionalProperties": false - }, - "RelationshipType": { - "enum": [ - 1, - 2, - 3, - 4 - ], - "type": "number" } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -4118,15 +3992,6 @@ } }, "additionalProperties": false - }, - "RelationshipType": { - "enum": [ - 1, - 2, - 3, - 4 - ], - "type": "number" } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -4371,15 +4236,6 @@ } }, "additionalProperties": false - }, - "RelationshipType": { - "enum": [ - 1, - 2, - 3, - 4 - ], - "type": "number" } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -4624,15 +4480,6 @@ } }, "additionalProperties": false - }, - "RelationshipType": { - "enum": [ - 1, - 2, - 3, - 4 - ], - "type": "number" } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -4873,15 +4720,6 @@ } }, "additionalProperties": false - }, - "RelationshipType": { - "enum": [ - 1, - 2, - 3, - 4 - ], - "type": "number" } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -5142,15 +4980,6 @@ } }, "additionalProperties": false - }, - "RelationshipType": { - "enum": [ - 1, - 2, - 3, - 4 - ], - "type": "number" } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -5418,15 +5247,6 @@ } }, "additionalProperties": false - }, - "RelationshipType": { - "enum": [ - 1, - 2, - 3, - 4 - ], - "type": "number" } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -5672,15 +5492,6 @@ } }, "additionalProperties": false - }, - "RelationshipType": { - "enum": [ - 1, - 2, - 3, - 4 - ], - "type": "number" } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -5928,15 +5739,6 @@ } }, "additionalProperties": false - }, - "RelationshipType": { - "enum": [ - 1, - 2, - 3, - 4 - ], - "type": "number" } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -6184,15 +5986,6 @@ } }, "additionalProperties": false - }, - "RelationshipType": { - "enum": [ - 1, - 2, - 3, - 4 - ], - "type": "number" } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -6461,15 +6254,6 @@ } }, "additionalProperties": false - }, - "RelationshipType": { - "enum": [ - 1, - 2, - 3, - 4 - ], - "type": "number" } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -6478,13 +6262,16 @@ "type": "object", "properties": { "type": { - "$ref": "#/definitions/RelationshipType" + "enum": [ + 1, + 2, + 3, + 4 + ], + "type": "number" } }, "additionalProperties": false, - "required": [ - "type" - ], "definitions": { "ChannelPermissionOverwriteType": { "enum": [ @@ -6711,15 +6498,6 @@ } }, "additionalProperties": false - }, - "RelationshipType": { - "enum": [ - 1, - 2, - 3, - 4 - ], - "type": "number" } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -6965,15 +6743,6 @@ } }, "additionalProperties": false - }, - "RelationshipType": { - "enum": [ - 1, - 2, - 3, - 4 - ], - "type": "number" } }, "$schema": "http://json-schema.org/draft-07/schema#" @@ -7402,15 +7171,6 @@ } }, "additionalProperties": false - }, - "RelationshipType": { - "enum": [ - 1, - 2, - 3, - 4 - ], - "type": "number" } }, "$schema": "http://json-schema.org/draft-07/schema#" diff --git a/api/src/routes/users/@me/relationships.ts b/api/src/routes/users/@me/relationships.ts index 6ad873a6..567c734e 100644 --- a/api/src/routes/users/@me/relationships.ts +++ b/api/src/routes/users/@me/relationships.ts @@ -21,20 +21,20 @@ router.get("/", route({}), async (req: Request, res: Response) => { const user = await User.findOneOrFail({ where: { id: req.user_id }, relations: ["relationships", "relationships.to"] }); //TODO DTO - const related_users = user.relationships.map(r => { + const related_users = user.relationships.map((r) => { return { id: r.to.id, type: r.type, nickname: null, - user: r.to.toPublicUser(), - } - }) + user: r.to.toPublicUser() + }; + }); return res.json(related_users); }); export interface RelationshipPutSchema { - type: RelationshipType; + type?: RelationshipType; } router.put("/:id", route({ body: "RelationshipPutSchema" }), async (req: Request, res: Response) => { @@ -42,7 +42,7 @@ router.put("/:id", route({ body: "RelationshipPutSchema" }), async (req: Request req, res, await User.findOneOrFail({ id: req.params.id }, { relations: ["relationships", "relationships.to"], select: userProjection }), - req.body.type + req.body.type ?? RelationshipType.friends ); }); @@ -59,7 +59,7 @@ router.post("/", route({ body: "RelationshipPostSchema" }), async (req: Request, relations: ["relationships", "relationships.to"], select: userProjection, where: { - discriminator: String(req.body.discriminator).padStart(4, '0'), //Discord send the discriminator as integer, we need to add leading zeroes + discriminator: String(req.body.discriminator).padStart(4, "0"), //Discord send the discriminator as integer, we need to add leading zeroes username: req.body.username } }), -- cgit 1.5.1 From 2a094c603a35c7174022ec2d2ffa42fa28508e3b 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 'api/assets') 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 22c744398c043c64ad738cdaa6f503de365de395 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 'api/assets') 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