diff --git a/api/assets/openapi.json b/api/assets/openapi.json
new file mode 100644
index 00000000..60a40c8a
--- /dev/null
+++ b/api/assets/openapi.json
@@ -0,0 +1,1625 @@
+{
+ "openapi": "3.0.0",
+ "servers": [
+ {
+ "url": "https://api.fosscord.com/v{version}",
+ "description": "Official fosscord instance",
+ "variables": { "version": { "description": "", "default": "9", "enum": ["8", "9"] } }
+ }
+ ],
+ "info": {
+ "description": "Fosscord is a free open source selfhostable chat, voice and video discord compatible platform",
+ "version": "1.0.0",
+ "title": "Swagger Petstore",
+ "termsOfService": "",
+ "contact": { "name": "Fosscord" },
+ "license": { "name": "AGPLV3", "url": "https://www.gnu.org/licenses/agpl-3.0.en.html" }
+ },
+ "tags": [],
+ "paths": {
+ "/users/{id}": {
+ "get": {
+ "summary": "",
+ "description": "",
+ "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" } } }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
+ },
+ "429": {
+ "description": "Rate limit exceeded",
+ "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } },
+ "headers": {
+ "X-RateLimit-Bucket": {
+ "description": "A unique string denoting the rate limit being encountered (non-inclusive of major parameters in the route path)",
+ "schema": { "type": "string" }
+ },
+ "X-Rate-Limit-Limit": {
+ "description": "The number of allowed requests in the current period",
+ "schema": { "type": "integer" }
+ },
+ "X-Rate-Limit-Remaining": {
+ "description": "The number of remaining requests in the current period",
+ "schema": { "type": "integer" }
+ },
+ "X-Rate-Limit-Reset": {
+ "description": "Date when current period is over in seconds since the Unix epoch",
+ "schema": { "type": "integer" }
+ },
+ "X-Rate-Limit-Reset-After": {
+ "description": "Number of seconds when current period will reset (can have decimal)",
+ "schema": { "type": "number" }
+ },
+ "Retry-After": {
+ "description": "Same as X-Rate-Limit-Reset-After but an integer",
+ "schema": { "type": "integer" }
+ },
+ "X-RateLimit-Global": {
+ "description": "Indicates whether or not all requests from your ip are rate limited",
+ "schema": { "type": "boolean" }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "externalDocs": { "description": "", "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": { "$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"]
+ },
+ "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": { "$ref": "#/components/schemas/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": "#/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": "string" },
+ "avatar": { "type": "string" },
+ "accent_color": { "type": "integer" },
+ "banner": { "type": "string" },
+ "bio": { "type": "string" },
+ "bot": { "type": "boolean" }
+ },
+ "required": ["bio", "bot", "discriminator", "id", "public_flags", "username"]
+ }
+ },
+ "requestBodies": {
+ "BanCreateSchema": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": { "delete_message_days": { "type": "string" }, "reason": { "type": "string" } }
+ }
+ }
+ },
+ "description": ""
+ },
+ "DmChannelCreateSchema": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "name": { "type": "string" },
+ "recipients": { "type": "array", "items": { "type": "string" } }
+ },
+ "required": ["recipients"]
+ }
+ }
+ },
+ "description": ""
+ },
+ "ChannelModifySchema": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "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": "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"]
+ }
+ }
+ },
+ "description": ""
+ },
+ "ChannelGuildPositionUpdateSchema": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": { "id": { "type": "string" }, "position": { "type": "integer" } },
+ "additionalProperties": false,
+ "required": ["id"]
+ }
+ }
+ }
+ },
+ "description": ""
+ },
+ "EmojiCreateSchema": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "name": { "type": "string" },
+ "image": { "type": "string" },
+ "roles": { "type": "array", "items": { "type": "string" } }
+ },
+ "required": ["image", "name"]
+ }
+ }
+ },
+ "description": ""
+ },
+ "GuildCreateSchema": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "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" }
+ },
+ "required": ["name"]
+ }
+ }
+ },
+ "description": ""
+ },
+ "GuildUpdateSchema": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "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" }
+ },
+ "required": ["name"]
+ }
+ }
+ },
+ "description": ""
+ },
+ "GuildTemplateCreateSchema": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": { "name": { "type": "string" }, "avatar": { "type": "string" } },
+ "required": ["name"]
+ }
+ }
+ },
+ "description": ""
+ },
+ "GuildUpdateWelcomeScreenSchema": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "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" }
+ }
+ }
+ }
+ },
+ "description": ""
+ },
+ "Number": { "content": { "application/json": { "schema": { "type": "object" } } }, "description": "" },
+ "Boolean": { "content": { "application/json": { "schema": { "type": "object" } } }, "description": "" },
+ "InviteCreateSchema": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "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" }
+ }
+ }
+ }
+ },
+ "description": ""
+ },
+ "MemberCreateSchema": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "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"]
+ }
+ }
+ },
+ "description": ""
+ },
+ "MemberNickChangeSchema": {
+ "content": {
+ "application/json": {
+ "schema": { "type": "object", "properties": { "nick": { "type": "string" } }, "required": ["nick"] }
+ }
+ },
+ "description": ""
+ },
+ "MemberChangeSchema": {
+ "content": {
+ "application/json": {
+ "schema": { "type": "object", "properties": { "roles": { "type": "array", "items": { "type": "string" } } } }
+ }
+ },
+ "description": ""
+ },
+ "EmbedType": {
+ "content": {
+ "application/json": { "schema": { "enum": ["article", "gifv", "image", "link", "rich", "video"], "type": "string" } }
+ },
+ "description": ""
+ },
+ "EmbedImage": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "url": { "type": "string" },
+ "proxy_url": { "type": "string" },
+ "height": { "type": "integer" },
+ "width": { "type": "integer" }
+ }
+ }
+ }
+ },
+ "description": ""
+ },
+ "MessageCreateSchema": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "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": "#/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
+ },
+ "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": {}
+ }
+ }
+ }
+ },
+ "description": ""
+ },
+ "RoleModifySchema": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": {
+ "name": { "type": "string" },
+ "permissions": { "type": "number" },
+ "color": { "type": "integer" },
+ "hoist": { "type": "boolean" },
+ "mentionable": { "type": "boolean" },
+ "position": { "type": "integer" }
+ }
+ }
+ }
+ },
+ "description": ""
+ },
+ "TemplateCreateSchema": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": { "name": { "type": "string" }, "description": { "type": "string" } },
+ "required": ["name"]
+ }
+ }
+ },
+ "description": ""
+ },
+ "TemplateModifySchema": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": { "name": { "type": "string" }, "description": { "type": "string" } },
+ "required": ["name"]
+ }
+ }
+ },
+ "description": ""
+ },
+ "UserModifySchema": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "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" }
+ }
+ }
+ }
+ },
+ "description": ""
+ },
+ "UserSettingsSchema": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "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"
+ ]
+ }
+ }
+ },
+ "description": ""
+ },
+ "WidgetModifySchema": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object",
+ "properties": { "enabled": { "type": "boolean" }, "channel_id": { "type": "string" } },
+ "required": ["channel_id", "enabled"]
+ }
+ }
+ },
+ "description": ""
+ }
+ },
+ "securitySchemes": { "authorization": { "type": "oauth2" } },
+ "links": {},
+ "callbacks": {}
+ },
+ "security": [{ "authorization": [] }]
+}
diff --git a/api/assets/openapi.yaml b/api/assets/openapi.yaml
deleted file mode 100644
index 06a0b72d..00000000
--- a/api/assets/openapi.yaml
+++ /dev/null
@@ -1,136 +0,0 @@
-openapi: 3.0.3
-info:
- title: Fosscord
- version: '9'
- license:
- name: GNU AGPLv3
- url: https://www.gnu.org/licenses/agpl.txt
- x-last-modified: 1625409195984
- x-logo:
- url: ''
-servers:
- - url: https://api.fosscord.com
- description: ''
- x-last-modified: 1625407844365
-paths:
- /users/:id:
- summary: get user
- description: test
- get:
- tags: []
- responses:
- '200':
- $ref: '#/components/responses/User'
- x-last-modified: 1625409722629
- parameters:
- - name: id
- in: path
- required: true
- deprecated: false
- x-last-modified: 1625409813480
- x-last-modified: 1625409704895
-components:
- schemas:
- User:
- type: object
- properties:
- avatar:
- type: string
- example:
- - d83f330fc30367f859bc6ee358b14319
- bot:
- type: boolean
- example:
- - false
- desktop:
- type: boolean
- example:
- - false
- discriminator:
- type: string
- example:
- - '0001'
- email:
- type: string
- example:
- - example@example.org
- flags:
- type: string
- example:
- - '0'
- id:
- type: string
- example:
- - '732645009894277321'
- mfa_enabled:
- type: boolean
- example:
- - false
- mobile:
- type: boolean
- example:
- - false
- nsfw_allowed:
- type: boolean
- example:
- - true
- premium:
- type: boolean
- example:
- - false
- premium_type:
- type: number
- example:
- - 0
- public_flags:
- type: string
- example:
- - '0'
- username:
- type: string
- example:
- - Example
- verified:
- type: boolean
- example:
- - true
- example:
- avatar: d83f330fc30367f859bc6ee358b14319
- bot: false
- desktop: false
- discriminator: '0001'
- email: example@example.org
- flags: '0'
- id: '732645009894277321'
- mfa_enabled: false
- mobile: false
- nsfw_allowed: true
- premium: false
- premium_type: 0
- public_flags: '0'
- username: Example
- verified: true
- x-last-modified: 1625409630283
- required: []
- description: test
- securitySchemes:
- JWTAuth:
- scheme: bearer
- bearerFormat: JWT
- type: http
- description: |-
- Example:
- > Authorization: Bot <token>
- x-last-modified: 1625407825787
- headers: {}
- responses:
- User:
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/User'
- x-last-modified: 1625409578903
- parameters: {}
-security:
- - JWTAuth: []
-tags: []
diff --git a/api/assets/openapi.yml b/api/assets/openapi.yml
deleted file mode 100644
index 957b6d16..00000000
--- a/api/assets/openapi.yml
+++ /dev/null
@@ -1,526 +0,0 @@
-swagger: "2.0"
-info:
- description: "Fosscord backend api docs"
- version: "1.0.0"
- title: "Fosscord Backend API"
- termsOfService: "https://github.com/fosscord/fosscord/blob/master/LICENSE"
- license:
- name: "AGPL 3.0"
- url: "https://www.gnu.org/licenses/agpl-3.0.html"
-host: "dev.fosscord.com"
-basePath: "/api/v9"
-tags:
- - name: "Audit Log"
- description: "Guild Audit Log resource"
- externalDocs:
- description: "Find out more"
- url: "https://discord.com/developers/docs/resources/audit-log"
- - name: "Channel"
- description: "Channel resource"
- externalDocs:
- description: "Find out more"
- url: "https://discord.com/developers/docs/resources/channel"
-schemes:
- - "https"
- - "http"
-paths:
- /guilds/{guildId}/audit-logs:
- get:
- summary: "Returns an audit log object for the guild. Requires the 'VIEW_AUDIT_LOG' permission."
- tags:
- - Audit Log
- parameters:
- - $ref: "#/definitionsParam/guildId"
- - name: user_id
- in: query
- type: string
- description: "Type of snowflake - Filter the log for actions made by a user"
- - name: action_type
- in: query
- type: integer
- description: "The type of audit log event"
- - name: before
- in: query
- type: string
- description: "Type of snowflake - Filter the log before a certain entry id"
- - name: limit
- in: query
- type: integer
- description: "How many entries are returned (default 50, minimum 1, maximum 100)"
- responses:
- '200':
- description: "Audit Log Object"
- schema:
- $ref: "#/definitions/Audit%20Log"
- /channels/{channelId}:
- get:
- summary: "Get a channel by ID. Returns a channel object. If the channel is a thread, a thread member object is included in the returned result."
- tags:
- - Channel
- parameters:
- - $ref: "#/definitionsParam/channelId"
- responses:
- '200':
- description: "Channel Object"
- schema:
- $ref: "#/definitions/Channel"
- patch:
- summary: "Update a channel's settings. Returns a channel on success, and a 400 BAD REQUEST on invalid parameters. All JSON parameters are optional."
- tags:
- - Channel
- parameters:
- - $ref: "#/definitionsParam/channelId"
- - name: body (Group DM)
- in: body
- description: "The request body when modifying Group DM channels - Fires a Channel Update Gateway event."
- schema:
- type: object
- properties:
- name:
- type: string
- description: "1-100 character channel name"
- icon:
- type: string
- format: byte
- description: "base64 encoded icon"
- - name: body (Guild channel)
- in: body
- description: "Requires the MANAGE_CHANNELS permission for the guild. Fires a Channel Update Gateway event. If modifying a category, individual Channel Update events will fire for each child channel that also changes. If modifying permission overwrites, the MANAGE_ROLES permission is required. 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)."
- schema:
- type: object
- properties:
- name:
- type: string
- description: "1-100 character channel name"
- type:
- type: integer
- description: "The type of channel; only conversion between text and news is supported and only in guilds with the \"NEWS\" feature"
- position:
- type: integer
- default: null
- description: "The position of the channel in the left-hand listing"
- topic:
- type: string
- default: null
- description: "0-1024 character channel topic"
- nsfw:
- type: boolean
- default: null
- description: "Whether the channel is nsfw"
- rate_limit_per_user:
- type: integer
- default: null
- description: "Amount of seconds a user has to wait before sending another message (0-21600); bots, as well as users with the permission manage_messages or manage_channel, are unaffected"
- bitrate:
- type: integer
- default: null
- description: "The bitrate (in bits) of the voice channel; 8000 to 96000 (128000 for VIP servers)"
- user_limit:
- type: integer
- default: null
- description: "The user limit of the voice channel; 0 refers to no limit, 1 to 99 refers to a user limit"
- permission_overwrites:
- type: array
- items:
- $ref: "#/definitions/Overwrite"
- default: null
- description: "Channel or category-specific permissions"
- parent_id:
- $ref: "#/definitions/Snowflake"
- default: null
- description: "Id of the new parent category for a channel"
- rtc_region:
- type: string
- default: null
- description: "Channel voice region id, automatic when set to null"
- video_quality_mode:
- type: integer
- default: null
- description: "The camera video quality mode of the voice channel"
- default_auto_archive_duration:
- type: integer
- default: null
- description: "The default duration for newly created threads in the channel, in minutes, to automatically archive the thread after recent activity"
- - name: body (Thread)
- in: body
- description: "When setting archived to false, when locked is also false, only the SEND_MESSAGES permission is required.Otherwise, requires the MANAGE_THREADS permission. Fires a Thread Update Gateway event. Requires the thread to have archived set to false or be set to false in the request."
- schema:
- type: object
- properties:
- name:
- type: string
- description: "1-100 character channel name"
- archived:
- type: boolean
- description: "Whether the channel is archived"
- auto_archive_duration:
- type: integer
- description: "Duration in minutes to automatically archive the thread after recent activity, can be set to: 60, 1440, 4320, 10080 (The 3 day and 7 day archive durations require the server to be boosted. The guild features will indicate if a server is able to use those settings)"
- locked:
- type: boolean
- description: "When a thread is locked, only users with MANAGE_THREADS can unarchive it"
- rate_limit_per_user:
- type: integer
- default: null
- description: "Amount of seconds a user has to wait before sending another message (0-21600); bots, as well as users with the permission manage_messages, manage_thread, or manage_channel, are unaffected"
- responses:
- '200':
- description: "Channel Object"
- schema:
- $ref: "#/definitions/Channel"
- '400':
- description: "Bad Request due to invalid parameters"
- delete:
- summary: "Delete a channel, or close a private message. Requires the MANAGE_CHANNELS permission for the guild, or MANAGE_THREADS if the channel is a thread. Deleting a category does not delete its child channels; they will have their parent_id removed and a Channel Update Gateway event will fire for each of them. Returns a channel object on success. Fires a Channel Delete Gateway event (or Thread Delete if the channel was a thread)."
- tags:
- - Channel
- parameters:
- - $ref: "#/definitionsParam/channelId"
- responses:
- '200':
- description: "Channel deleted sucessfully"
- /channels/{channelId}/messages:
- get:
- summary: "Returns the messages for a channel. If operating on a guild channel, this endpoint requires the VIEW_CHANNEL permission to be present on the current user. If the current user is missing the 'READ_MESSAGE_HISTORY' permission in the channel then this will return no messages (since they cannot read the message history). Returns an array of message objects on success."
- tags:
- - Channel
- parameters:
- - $ref: "#/definitionsParam/channelId"
- - name: around
- in: query
- type: string
- description: "Type of snowflake - Get messages around this message ID"
- - name: before
- in: query
- type: string
- description: "Type of snowflake - Get messages before this message ID"
- - name: after
- in: query
- type: string
- description: "Type of snowflake - Get messages after this message ID"
- - name: limit
- in: query
- type: integer
- description: "Max number of messages to return (1-100)"
- default: 50
- responses:
- '200':
- description: "Returns an array of message objects on success"
- schema:
- type: array
- items:
- $ref: "#/definitions/Message"
- /channels/{channelId}/messages/{messageId}:
- get:
- summary: "Returns a specific message in the channel. If operating on a guild channel, this endpoint requires the 'READ_MESSAGE_HISTORY' permission to be present on the current user. Returns a message object on success."
- tags:
- - Channel
- parameters:
- - $ref: "#/definitionsParam/channelId"
- - $ref: "#/definitionsParam/messageId"
- responses:
- '200':
- description: "Returns a message object on success"
- schema:
- $ref: "#/definitions/Message"
- post:
- summary: "Post a message to a guild text or DM channel. Returns a message object. Fires a Message Create Gateway event. See message formatting for more information on how to properly format messages."
- tags:
- - Channel
- parameters:
- - $ref: "#/definitionsParam/channelId"
- - $ref: "#/definitionsParam/messageId"
- - name: body
- in: body
- required: true
- description: "Request body that contains the necessary data for creating messages"
- schema:
- type: object
- properties:
- content:
- type: string
- description: "The message contents (up to 2000 characters)"
- tts:
- type: boolean
- description: "True if this is a TTS message"
- default: null
- file:
- type: string
- format: binary
- description: "The contents of the file being sent"
- embeds:
- type: array
- items:
- $ref: "#/definitions/Embed"
- description: "Embedded rich content (up to 6000 characters)"
- payload_json:
- type: string
- description: "JSON encoded body of non-file params"
- default: null
- allowed_mentions:
- $ref: "#/definitions/Allowed%20Mention"
- description: "Allowed mentions for the message"
- default: null
- message_refrence:
- $ref: "#/definitions/Message%20Refrence"
- description: "Include to make your message a reply"
- default: null
- components:
- type: array
- items:
- $ref: "#/definitions/Message%20Component"
- default: null
- responses:
- '200':
- description: "Returns a message object on success"
- schema:
- $ref: "#/definitions/Message"
- patch:
- summary: "Edit a previously sent message. The fields content, embeds, and flags can be edited by the original message author. Other users can only edit flags and only if they have the MANAGE_MESSAGES permission in the corresponding channel. When specifying flags, ensure to include all previously set flags/bits in addition to ones that you are modifying. Only flags documented in the table below may be modified by users (unsupported flag changes are currently ignored without error)."
- tags:
- - Channel
- parameters:
- - $ref: "#/definitionsParam/channelId"
- - $ref: "#/definitionsParam/messageId"
- - name: body
- in: body
- required: true
- description: "Request body that contains the necessary data for editing messages"
- schema:
- type: object
- properties:
- content:
- type: string
- description: "The message contents (up to 2000 characters)"
- embeds:
- type: array
- items:
- $ref: "#/definitions/Embed"
- description: "Embedded rich content (up to 6000 characters)"
- flags:
- type: integer
- description: "Edit the flags of a message (only SUPPRESS_EMBEDS can currently be set/unset)"
- file:
- type: string
- format: binary
- description: "The contents of the file being sent/edited"
- payload_json:
- type: string
- description: "JSON encoded body of non-file params (multipart/form-data only)"
- default: null
- allowed_mentions:
- $ref: "#/definitions/Allowed%20Mention"
- description: "Allowed mentions for the message"
- default: null
- message_refrence:
- $ref: "#/definitions/Message%20Refrence"
- description: "Include to make your message a reply"
- default: null
- components:
- type: array
- items:
- $ref: "#/definitions/Message%20Component"
- default: null
- responses:
- '200':
- description: "Message edited"
- delete:
- summary: "Delete a message. If operating on a guild channel and trying to delete a message that was not sent by the current user, this endpoint requires the MANAGE_MESSAGES permission. Returns a 204 empty response on success. Fires a Message Delete Gateway event."
- tags:
- - Channel
- parameters:
- - $ref: "#/definitionsParam/channelId"
- - $ref: "#/definitionsParam/messageId"
- responses:
- '204':
- description: "Returns a 204 empty response on success."
- /channels/{channelId}/messages/{messageId}/crosspost:
- post:
- summary: "Crosspost a message in a News Channel to following channels. This endpoint requires the 'SEND_MESSAGES' permission, if the current user sent the message, or additionally the 'MANAGE_MESSAGES' permission, for all other messages, to be present for the current user."
- tags:
- - Channel
- parameters:
- - $ref: "#/definitionsParam/channelId"
- - $ref: "#/definitionsParam/messageId"
- responses:
- '200':
- description: "Returns a message object on success"
- schema:
- $ref: "#/definitions/Message"
- /channels/{channelId}/messages/{messageId}/reactions/{emoji}/@me:
- put:
- summary: "Create a reaction for the message. This endpoint requires the 'READ_MESSAGE_HISTORY' permission to be present on the current user. Additionally, if nobody else has reacted to the message using this emoji, this endpoint requires the 'ADD_REACTIONS' permission to be present on the current user. Returns a 204 empty response on success. The emoji must be URL Encoded or the request will fail with 10014: Unknown Emoji. To use custom emoji, you must encode it in the format name:id with the emoji name and emoji id."
- tags:
- - Channel
- parameters:
- - $ref: "#/definitionsParam/channelId"
- - $ref: "#/definitionsParam/messageId"
- - $ref: "#/definitionsParam/emoji"
- responses:
- '204':
- description: "Returns a 204 empty response on success."
- delete:
- summary: "Delete a reaction the current user has made for the message. Returns a 204 empty response on success. The emoji must be URL Encoded or the request will fail with 10014: Unknown Emoji. To use custom emoji, you must encode it in the format name:id with the emoji name and emoji id."
- tags:
- - Channel
- parameters:
- - $ref: "#/definitionsParam/channelId"
- - $ref: "#/definitionsParam/messageId"
- - $ref: "#/definitionsParam/emoji"
- responses:
- '204':
- description: "Returns a 204 empty response on success."
- /channels/{channelId}/messages/{messageId}/reactions/{emoji}/{userId}:
- delete:
- summary: "Deletes another user's reaction. This endpoint requires the 'MANAGE_MESSAGES' permission to be present on the current user. Returns a 204 empty response on success. The emoji must be URL Encoded or the request will fail with 10014: Unknown Emoji. To use custom emoji, you must encode it in the format name:id with the emoji name and emoji id."
- tags:
- - Channel
- parameters:
- - $ref: "#/definitionsParam/channelId"
- - $ref: "#/definitionsParam/messageId"
- - $ref: "#/definitionsParam/emoji"
- - $ref: "#/definitionsParam/userId"
- responses:
- '204':
- description: "Returns a 204 empty response on success."
- /channels/{channelId}/messages/{messageId}/reactions/{emoji}:
- get:
- summary: "Get a list of users that reacted with this emoji. Returns an array of user objects on success. The emoji must be URL Encoded or the request will fail with 10014: Unknown Emoji. To use custom emoji, you must encode it in the format name:id with the emoji name and emoji id."
- tags:
- - Channel
- parameters:
- - $ref: "#/definitionsParam/channelId"
- - $ref: "#/definitionsParam/messageId"
- - $ref: "#/definitionsParam/emoji"
- - name: after
- in: query
- type: string
- description: "Type of snowflake - Get users after this user ID"
- - name: limit
- in: query
- type: integer
- description: "Max number of users to return (1-100)"
- default: 25
- responses:
- '200':
- description: "Returns an array of user objects on success"
- schema:
- type: array
- items:
- $ref: "#/definitions/User"
- delete:
- summary: "Deletes all the reactions for a given emoji on a message. This endpoint requires the MANAGE_MESSAGES permission to be present on the current user. Fires a Message Reaction Remove Emoji Gateway event. The emoji must be URL Encoded or the request will fail with 10014: Unknown Emoji. To use custom emoji, you must encode it in the format name:id with the emoji name and emoji id."
- tags:
- - Channel
- parameters:
- - $ref: "#/definitionsParam/channelId"
- - $ref: "#/definitionsParam/messageId"
- - $ref: "#/definitionsParam/emoji"
- responses:
- '204':
- description: "Returns a 204 empty response on success."
- /channels/{channelId}/messages/{messageId}/reactions:
- delete:
- summary: "Deletes all reactions on a message. This endpoint requires the 'MANAGE_MESSAGES' permission to be present on the current user. Fires a Message Reaction Remove All Gateway event."
- tags:
- - Channel
- parameters:
- - $ref: "#/definitionsParam/channelId"
- - $ref: "#/definitionsParam/messageId"
- responses:
- '204':
- description: "Returns a 204 empty response on success."
- /channels/{channelId}/messages/bulk-delete:
- post:
- summary: "Delete multiple messages in a single request. This endpoint can only be used on guild channels and requires the MANAGE_MESSAGES permission. Returns a 204 empty response on success. Fires a Message Delete Bulk Gateway event."
- tags:
- - Channel
- parameters:
- - $ref: "#/definitionsParam/channelId"
- responses:
- '204':
- description: "Returns a 204 empty response on success."
-definitions:
- Snowflake:
- type: string
- pattern: "^\\d+$"
- Audit Log:
- type: object
- properties:
- webhooks:
- type: array
- items:
- $ref: "#/definitions/Webhook"
- description: "List of webhooks found in the audit log"
- users:
- type: array
- items:
- $ref: "#/definitions/User"
- description: "List of users found in the audit log"
- audit_log_entries:
- type: array
- items:
- $ref: "#/definitions/Audit%20Log%20Entry"
- description: "List of audit log entries"
- integrations:
- type: array
- items:
- $ref: "#/definitions/Integration"
- description: "List of partial integration objects"
- Audit Log Entry:
- type: object
- Webhook:
- type: object
- User:
- type: object
- Integration:
- type: object
- Channel:
- type: object
- Overwrite:
- type: object
- Message:
- type: object
- Embed:
- type: object
- Allowed Mention:
- type: object
- Message Refrence:
- type: object
- Message Component:
- type: object
-definitionsParam:
- channelId:
- name: channelId
- in: path
- required: true
- type: string
- description: "Type of snowflake - A channel Id"
- messageId:
- name: messageId
- in: path
- required: true
- type: string
- description: "Type of snowflake - A message ID"
- guildId:
- name: guildId
- in: path
- required: true
- type: string
- description: "Type of snowflake - A guild ID"
- emoji:
- name: emoji
- in: path
- required: true
- type: string
- format: url
- description: "The emoji ID to use"
- userId:
- name: userId
- in: path
- required: true
- type: string
- description: "Type of snowflake - A user ID"
-externalDocs:
- description: "Discord API"
- url: "https://discord.com/developers/docs/"
diff --git a/api/patches/typescript-json-schema+0.50.1.patch b/api/patches/typescript-json-schema+0.50.1.patch
new file mode 100644
index 00000000..a0d479de
--- /dev/null
+++ b/api/patches/typescript-json-schema+0.50.1.patch
@@ -0,0 +1,14 @@
+diff --git a/node_modules/typescript-json-schema/dist/typescript-json-schema.js b/node_modules/typescript-json-schema/dist/typescript-json-schema.js
+index 47e1598..8397b9d 100644
+--- a/node_modules/typescript-json-schema/dist/typescript-json-schema.js
++++ b/node_modules/typescript-json-schema/dist/typescript-json-schema.js
+@@ -432,6 +432,9 @@ var JsonSchemaGenerator = (function () {
+ else if (flags & ts.TypeFlags.Boolean) {
+ definition.type = "boolean";
+ }
++ else if (flags & ts.TypeFlags.BigInt) {
++ definition.type = "bigint";
++ }
+ else if (flags & ts.TypeFlags.Null) {
+ definition.type = "null";
+ }
diff --git a/api/scripts/config_generator.js b/api/scripts/config_generator.js
deleted file mode 100644
index 5b5c52d4..00000000
--- a/api/scripts/config_generator.js
+++ /dev/null
@@ -1,93 +0,0 @@
-const { Snowflake } = require("@fosscord/server-util");
-const crypto = require('crypto');
-const fs = require('fs');
-
-
-const defaultConfig = {
- // TODO: Get the network interfaces dinamically
- gateway: "ws://localhost",
- general: {
- instance_id: Snowflake.generate(),
- },
- permissions: {
- user: {
- createGuilds: true,
- }
- },
- limits: {
- user: {
- maxGuilds: 100,
- maxUsername: 32,
- maxFriends: 1000,
- },
- guild: {
- maxRoles: 250,
- maxMembers: 250000,
- maxChannels: 500,
- maxChannelsInCategory: 50,
- hideOfflineMember: 1000,
- },
- message: {
- characters: 2000,
- ttsCharacters: 200,
- maxReactions: 20,
- maxAttachmentSize: 8388608,
- maxBulkDelete: 100,
- },
- channel: {
- maxPins: 50,
- maxTopic: 1024,
- },
- rate: {
- ip: {
- enabled: true,
- count: 1000,
- timespan: 1000 * 60 * 10,
- },
- routes: {},
- },
- },
- security: {
- jwtSecret: crypto.randomBytes(256).toString("base64"),
- forwadedFor: null,
- // forwadedFor: "X-Forwarded-For" // nginx/reverse proxy
- // forwadedFor: "CF-Connecting-IP" // cloudflare:
- captcha: {
- enabled: false,
- service: null,
- sitekey: null,
- secret: null,
- },
- },
- login: {
- requireCaptcha: false,
- },
- register: {
- email: {
- necessary: true,
- 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,
- minimum: 13,
- },
- requireInvite: false,
- requireCaptcha: true,
- allowNewRegistration: true,
- allowMultipleAccounts: true,
- password: {
- minLength: 8,
- minNumbers: 2,
- minUpperCase: 2,
- minSymbols: 0,
- blockInsecureCommonPasswords: false,
- },
- },
-}
-
-let data = JSON.stringify(defaultConfig);
-fs.writeFileSync('./.docker/config/api.json', data);
-
diff --git a/api/scripts/generate_openapi_schema.ts b/api/scripts/generate_openapi_schema.ts
new file mode 100644
index 00000000..c45a43eb
--- /dev/null
+++ b/api/scripts/generate_openapi_schema.ts
@@ -0,0 +1,191 @@
+// 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 generateSchemas() {
+ const program = TJS.getProgramFromFiles([path.join(__dirname, "..", "..", "util", "src", "index.ts")], compilerOptions);
+ const generator = TJS.buildGenerator(program, settings);
+
+ const schemas = [
+ "Application",
+ "Attachment",
+ "Message",
+ "AuditLog",
+ "Ban",
+ "Channel",
+ "Emoji",
+ "Guild",
+ "Invite",
+ "ReadState",
+ "Recipient",
+ "Relationship",
+ "Role",
+ "Sticker",
+ "Team",
+ "TeamMember",
+ "Template",
+ "VoiceState",
+ "Webhook",
+ "User",
+ "UserPublic"
+ ];
+
+ // @ts-ignore
+ const definitions = combineSchemas({ schemas, generator, program });
+
+ for (const key in definitions) {
+ specification.components.schemas[key] = definitions[key];
+ delete definitions[key].additionalProperties;
+ }
+}
+
+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, ...part.definitions, [name]: { ...part, definitions: undefined, $schema: undefined } };
+ }
+
+ return definitions;
+}
+
+function generateBodies() {
+ 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"
+ ];
+
+ // @ts-ignore
+ const definitions = combineSchemas({ schemas, generator, program });
+
+ for (const key in definitions) {
+ specification.components.requestBodies[key] = {
+ content: {
+ "application/json": { schema: definitions[key] }
+ },
+ description: ""
+ };
+
+ delete definitions[key].additionalProperties;
+ delete definitions[key].$schema;
+ }
+}
+
+function addDefaultResponses() {
+ Object.values(specification.paths).forEach((path: any) =>
+ Object.values(path).forEach((request: any) => {
+ if (!request.responses?.["401"]) {
+ request.responses["401"] = {
+ description: "Unauthorized",
+ content: { "application/json": { schema: { $ref: "#/components/schemas/Error" } } }
+ };
+ }
+ if (!request.responses?.["429"]) {
+ request.responses["429"] = {
+ description: "Rate limit exceeded",
+ content: { "application/json": { schema: { $ref: "#/components/schemas/Error" } } },
+ headers: {
+ "X-RateLimit-Bucket": {
+ description:
+ "A unique string denoting the rate limit being encountered (non-inclusive of major parameters in the route path)",
+ schema: { type: "string" }
+ },
+ "X-Rate-Limit-Limit": {
+ description: "The number of allowed requests in the current period",
+ schema: {
+ type: "integer"
+ }
+ },
+ "X-Rate-Limit-Remaining": {
+ description: "The number of remaining requests in the current period",
+ schema: {
+ type: "integer"
+ }
+ },
+ "X-Rate-Limit-Reset": {
+ description: "Date when current period is over in seconds since the Unix epoch",
+ schema: {
+ type: "integer"
+ }
+ },
+ "X-Rate-Limit-Reset-After": {
+ description: "Number of seconds when current period will reset (can have decimal)",
+ schema: {
+ type: "number"
+ }
+ },
+ "Retry-After": {
+ description: "Same as X-Rate-Limit-Reset-After but an integer",
+ schema: {
+ type: "integer"
+ }
+ },
+ "X-RateLimit-Global": {
+ description: "Indicates whether or not all requests from your ip are rate limited",
+ schema: {
+ type: "boolean"
+ }
+ }
+ }
+ };
+ }
+ })
+ );
+}
+
+function main() {
+ addDefaultResponses();
+ generateSchemas();
+ specification = JSON.parse(JSON.stringify(specification).replaceAll("#/definitions", "#/components/schemas"));
+
+ generateBodies();
+
+ fs.writeFileSync(
+ openapiPath,
+ JSON.stringify(specification, null, 4).replaceAll("#/definitions", "#/components/requestBodies").replaceAll("bigint", "number")
+ );
+}
+
+main();
diff --git a/api/src/schema/Emoji.ts b/api/src/schema/Emoji.ts
index deaccf5c..0406919c 100644
--- a/api/src/schema/Emoji.ts
+++ b/api/src/schema/Emoji.ts
@@ -1,14 +1,13 @@
// 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
+ $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: []; //roles allowed to use this emoji
+ roles?: string[]; //roles allowed to use this emoji
}
diff --git a/api/src/schema/Guild.ts b/api/src/schema/Guild.ts
index 3e98fe76..0f9fd884 100644
--- a/api/src/schema/Guild.ts
+++ b/api/src/schema/Guild.ts
@@ -48,7 +48,7 @@ export interface GuildUpdateSchema extends Omit<GuildCreateSchema, "channels"> {
banner?: string;
splash?: string;
description?: string;
- features?: [string];
+ features?: string[];
verification_level?: number;
default_message_notifications?: number;
system_channel_flags?: number;
diff --git a/api/src/schema/Invite.ts b/api/src/schema/Invite.ts
index a22449ba..da6192bc 100644
--- a/api/src/schema/Invite.ts
+++ b/api/src/schema/Invite.ts
@@ -10,13 +10,13 @@ export const InviteCreateSchema = {
$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;
+ 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/index.ts b/api/src/schema/index.ts
new file mode 100644
index 00000000..b5f38a2f
--- /dev/null
+++ b/api/src/schema/index.ts
@@ -0,0 +1,11 @@
+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";
|