From 1b29c92aac3a8a7c55f414dae1b72884fea0489e Mon Sep 17 00:00:00 2001 From: ayntee Date: Mon, 8 Mar 2021 15:42:42 +0400 Subject: [PATCH 01/43] Revert "fix(types/webhook): update interaction response types (#610)" (#635) This reverts commit b511a0d39ff1f0126c969c7e14b95beb598c2e38. --- src/interactions/types/interactions.ts | 10 +++++++--- src/types/webhook.ts | 10 +++++++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/interactions/types/interactions.ts b/src/interactions/types/interactions.ts index e9d291a3c..295015e34 100644 --- a/src/interactions/types/interactions.ts +++ b/src/interactions/types/interactions.ts @@ -66,8 +66,12 @@ export enum InteractionType { export enum InteractionResponseType { /** ACK a `Ping` */ PONG = 1, - /** Respond with a message, showing the user's input */ + /** ACK a command without sending a message, eating the user's input */ + ACKNOWLEDGE = 2, + /** respond with a message, eating the user's input */ + CHANNEL_MESSAGE = 3, + /** respond with a message, showing the user's input */ CHANNEL_MESSAGE_WITH_SOURCE = 4, - /** ACK an interaction and edit to a response later, the user sees a loading state */ - DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE, + /** ACK a command without sending a message, showing the user's input */ + ACK_WITH_SOURCE = 5, } diff --git a/src/types/webhook.ts b/src/types/webhook.ts index 925632135..bc52309f9 100644 --- a/src/types/webhook.ts +++ b/src/types/webhook.ts @@ -198,10 +198,14 @@ export interface SlashCommandCallbackData { export enum InteractionResponseType { /** ACK a `Ping` */ PONG = 1, - /** Respond with a message, showing the user's input */ + /** ACK a command without sending a message, eating the user's input */ + ACKNOWLEDGE = 2, + /** respond with a message, eating the user's input */ + CHANNEL_MESSAGE = 3, + /** respond with a message, showing the user's input */ CHANNEL_MESSAGE_WITH_SOURCE = 4, - /** ACK an interaction and edit to a response later, the user sees a loading state */ - DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE, + /** ACK a command without sending a message, showing the user's input */ + ACK_WITH_SOURCE = 5, } // TODO: remove this interface for v11 From a515765abfae94cfcef309f29c9085e19a919291 Mon Sep 17 00:00:00 2001 From: ayntee Date: Mon, 8 Mar 2021 15:42:51 +0400 Subject: [PATCH 02/43] Revert "fix(handlers/webhook): return Message object instead of raw payload (#611)" (#634) This reverts commit 9c7340f6240841f69db7b5132b4759a977ec48ce. --- src/api/handlers/webhook.ts | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/api/handlers/webhook.ts b/src/api/handlers/webhook.ts index 1d2b56d8e..ba07414c6 100644 --- a/src/api/handlers/webhook.ts +++ b/src/api/handlers/webhook.ts @@ -255,10 +255,9 @@ export async function editWebhookMessage( const result = await RequestManager.patch( endpoints.WEBHOOK_MESSAGE(webhookID, webhookToken, messageID), { ...options, allowed_mentions: options.allowed_mentions }, - ) as MessageCreateOptions; + ); - const message = await structures.createMessage(result); - return message; + return result; } export async function deleteWebhookMessage( @@ -600,11 +599,5 @@ export async function editSlashResponse( options, ); - // If the original message was edited, this will not return a message - if (!options.messageID) return result; - - const message = await structures.createMessage( - result as MessageCreateOptions, - ); - return message; + return result; } From 53bd6c23862551ba1d14f18550fff37165eb4b56 Mon Sep 17 00:00:00 2001 From: Skillz4Killz <23035000+Skillz4Killz@users.noreply.github.com> Date: Mon, 8 Mar 2021 08:37:18 -0500 Subject: [PATCH 03/43] feat(types/member): add permissions in MemberCreatePayload (#641) * add permission * update interaction type --- src/interactions/types/member.ts | 2 ++ src/types/member.ts | 14 +++++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/interactions/types/member.ts b/src/interactions/types/member.ts index 94634a62e..a0bb175c5 100644 --- a/src/interactions/types/member.ts +++ b/src/interactions/types/member.ts @@ -40,4 +40,6 @@ export interface MemberCreatePayload { deaf: boolean; /** Whether the user is muted in voice channels */ mute: boolean; + /** total permissions of the member in the channel, including overrides */ + permissions: string; } diff --git a/src/types/member.ts b/src/types/member.ts index 5b9dc4854..41fe58b40 100644 --- a/src/types/member.ts +++ b/src/types/member.ts @@ -10,7 +10,8 @@ export interface EditMemberOptions { /** Whether the user is deafened in voice channels. Requires DEAFEN_MEMBERS permission. */ deaf?: boolean; /** The id of the channel to move user to if they are connected to voice. To kick the user from their current channel, set to null. Requires MOVE_MEMBERS permission. When moving members to channels, must have permissions to both CONNECT to the channel and have the MOVE_MEMBER permission. */ - "channel_id"?: string | null; + // deno-lint-ignore camelcase + channel_id?: string | null; } export interface MemberCreatePayload { @@ -21,9 +22,11 @@ export interface MemberCreatePayload { /** Array of role ids that the member has */ roles: string[]; /** When the user joined the guild. */ - "joined_at": string; + // deno-lint-ignore camelcase + joined_at: string; /** When the user used their nitro boost on the server. */ - "premium_since"?: string; + // deno-lint-ignore camelcase + premium_since?: string; /** Whether the user is deafened in voice channels */ deaf: boolean; /** Whether the user is muted in voice channels */ @@ -48,3 +51,8 @@ export interface GuildMember { /** Whether the user has passed the guild's Membership Screening requirements */ pending?: boolean; } + +export interface InteractionMember extends GuildMember { + /** total permissions of the member in the channel, including overrides, returned when in the interaction object */ + permissions: string; +} From 5be674e3e83891a1377ef1d763ff58cc93024053 Mon Sep 17 00:00:00 2001 From: Skillz4Killz <23035000+Skillz4Killz@users.noreply.github.com> Date: Mon, 8 Mar 2021 08:41:31 -0500 Subject: [PATCH 04/43] feat(types/message): add fail_if_not_exists to Reference interface (#642) * support fail replies * fmt * fix linter issue * fix condition --- src/api/handlers/channel.ts | 1 + src/api/structures/message.ts | 11 +++++++++-- src/types/channel.ts | 2 ++ src/types/message.ts | 21 +++++++++++++++++---- 4 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/api/handlers/channel.ts b/src/api/handlers/channel.ts index 5e1b772d1..8efaf18e7 100644 --- a/src/api/handlers/channel.ts +++ b/src/api/handlers/channel.ts @@ -244,6 +244,7 @@ export async function sendMessage( ? { message_reference: { message_id: content.replyMessageID, + fail_if_not_exists: content.failReplyIfNotExists === true, }, } : {}), diff --git a/src/api/structures/message.ts b/src/api/structures/message.ts index 47e828cae..629d435c4 100644 --- a/src/api/structures/message.ts +++ b/src/api/structures/message.ts @@ -2,6 +2,7 @@ import { Activity, Application, Attachment, + DiscordReferencePayload, Embed, GuildMember, MessageContent, @@ -85,11 +86,17 @@ const baseMessage: Partial = { }, reply(content) { const contentWithMention = typeof content === "string" - ? { content, mentions: { repliedUser: true }, replyMessageID: this.id } + ? { + content, + mentions: { repliedUser: true }, + replyMessageID: this.id, + failReplyIfNotExists: false, + } : { ...content, mentions: { ...(content.mentions || {}), repliedUser: true }, replyMessageID: this.id, + failReplyIfNotExists: content.failReplyIfNotExists === true, }; if (this.guildID) return sendMessage(this.channelID!, contentWithMention); @@ -216,7 +223,7 @@ export interface Message { /** Applications that sent with Rich Presence related chat embeds. */ applications?: Application; /** The reference data sent with crossposted messages */ - messageReference?: Reference; + messageReference?: DiscordReferencePayload; /** The message flags combined like permission bits describe extra features of the message */ flags?: 1 | 2 | 4 | 8 | 16; /** the stickers sent with the message (bots currently can only receive messages with stickers, not send) */ diff --git a/src/types/channel.ts b/src/types/channel.ts index 3743c2ebc..5c0716f11 100644 --- a/src/types/channel.ts +++ b/src/types/channel.ts @@ -118,6 +118,8 @@ export interface MessageContent { "payload_json"?: string; /** If you want to send a reply message, provide the original message id here */ replyMessageID?: string; + /** When sending a reply to a message that was deleted, should Discord fail and throw an error. By default we make this false to prevent your bot from crashing. */ + failReplyIfNotExists?: boolean; } export interface FileContent { diff --git a/src/types/message.ts b/src/types/message.ts index 86f0e4d63..1d9889921 100644 --- a/src/types/message.ts +++ b/src/types/message.ts @@ -200,11 +200,23 @@ export interface Application { export interface Reference { /** The id of the originating message */ - "message_id"?: string; + // deno-lint-ignore camelcase + message_id?: string; /** The id of the originating message's channel */ - "channel_id": string; + // deno-lint-ignore camelcase + channel_id?: string; /** The id of the originating message's guild */ - "guild_id"?: string; + // deno-lint-ignore camelcase + guild_id?: string; + /** When sending, whether to error if the referenced message doesn't exist instead of sending as a normal (non-reply) message, default false */ + // deno-lint-ignore camelcase + fail_if_not_exists?: boolean; +} + +export interface DiscordReferencePayload extends Reference { + /** The id of the originating message's channel */ + // deno-lint-ignore camelcase + channel_id: string; } export enum MessageFlags { @@ -287,7 +299,8 @@ export interface MessageCreateOptions { /** Applications that sent with Rich Presence related chat embeds. */ applications?: Application; /** The reference data sent with crossposted messages */ - "message_reference"?: Reference; + // deno-lint-ignore camelcase + message_reference?: DiscordReferencePayload; /** The message flags combined like permission bits describe extra features of the message */ flags?: 1 | 2 | 4 | 8 | 16; /** the stickers sent with the message (bots currently can only receive messages with stickers, not send) */ From ed85685d35912d4bbbcdc3668019b00ee2f012a1 Mon Sep 17 00:00:00 2001 From: ITOH <72305210+itohatweb@users.noreply.github.com> Date: Mon, 8 Mar 2021 14:43:30 +0100 Subject: [PATCH 05/43] add type (#619) --- src/types/api/interaction.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/types/api/interaction.ts b/src/types/api/interaction.ts index 993409fc9..177c26802 100644 --- a/src/types/api/interaction.ts +++ b/src/types/api/interaction.ts @@ -59,6 +59,8 @@ export interface DiscordApplicationCommandInteractionDataResolved { export interface DiscordInteractionDataOption { /** the name of the parameter */ name: string; + /** value of ApplicationCommandOptionType */ + type: DiscordApplicationCommandOptionType; /** the value of the pair. present if there was no more options */ value?: string | number; /** present if this option is a group or subcommand */ @@ -70,7 +72,7 @@ export interface DiscordApplicationCommand { /** unique id of the command */ id: string; /** unique id of the parent application */ - "application_id": string; + application_id: string; /** 3-32 character name matching `^[\w-]{3,32}$` */ name: string; /** 1-100 character description */ From 100f7ff9651ade09e99d964daa5bf9060044605a Mon Sep 17 00:00:00 2001 From: ITOH <72305210+itohatweb@users.noreply.github.com> Date: Mon, 8 Mar 2021 14:46:23 +0100 Subject: [PATCH 06/43] fix(handlers/channel): add permission handler for startTyping() (#626) * add perm check * Update src/api/handlers/channel.ts Co-authored-by: Skillz4Killz <23035000+Skillz4Killz@users.noreply.github.com> Co-authored-by: Skillz4Killz <23035000+Skillz4Killz@users.noreply.github.com> --- src/api/handlers/channel.ts | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/api/handlers/channel.ts b/src/api/handlers/channel.ts index 8efaf18e7..b314fbdcf 100644 --- a/src/api/handlers/channel.ts +++ b/src/api/handlers/channel.ts @@ -133,6 +133,30 @@ export async function getPins(channelID: string) { * this endpoint may be called to let the user know that the bot is processing their message. */ export async function startTyping(channelID: string) { + const channel = await cacheHandlers.get("channels", channelID); + // If the channel is cached, we can do extra checks/safety + if (channel) { + if ( + ![ + ChannelTypes.DM, + ChannelTypes.GUILD_NEWS, + ChannelTypes.GUILD_TEXT, + ].includes(channel.type) + ) { + throw new Error(Errors.CHANNEL_NOT_TEXT_BASED); + } + + const hasSendMessagesPerm = await botHasChannelPermissions( + channelID, + ["SEND_MESSAGES"], + ); + if ( + !hasSendMessagesPerm + ) { + throw new Error(Errors.MISSING_SEND_MESSAGES); + } + } + const result = await RequestManager.post(endpoints.CHANNEL_TYPING(channelID)); return result; From bd14075c8a9d6665bd0a1fd06bcb483753023d76 Mon Sep 17 00:00:00 2001 From: ayntee Date: Mon, 8 Mar 2021 18:12:35 +0400 Subject: [PATCH 07/43] fix(types/channel): change FileContent.blob type to Blob (#509) * fix(types/channel): change FileContent.blob type to Blob * idk * change to blob * idk --- src/interactions/types/webhook.ts | 2 +- src/rest/request_manager.ts | 2 +- src/types/api/message.ts | 2 +- src/types/channel.ts | 2 +- src/types/webhook.ts | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/interactions/types/webhook.ts b/src/interactions/types/webhook.ts index 9743bb8b9..0a65112a6 100644 --- a/src/interactions/types/webhook.ts +++ b/src/interactions/types/webhook.ts @@ -12,7 +12,7 @@ export interface ExecuteWebhookOptions { /** true if this is a TTS message */ tts?: boolean; /** file contents the contents of the file being sent one of content, file, embeds */ - file?: { blob: unknown; name: string }; + file?: { blob: Blob; name: string }; /** array of up to 10 embed objects embedded rich content. */ embeds?: Embed[]; /** allowed mentions for the message */ diff --git a/src/rest/request_manager.ts b/src/rest/request_manager.ts index af77cb559..02e12b6a9 100644 --- a/src/rest/request_manager.ts +++ b/src/rest/request_manager.ts @@ -166,7 +166,7 @@ function createRequestBody(body: any, method: RequestMethods) { body.file.map((file: FileContent, index: number) => // The key of the form data item must be unique; otherwise, Discordeno only considers the first item in the form data with the same names - form.append(`file${index + 1}`, file.blob as Blob, file.name) + form.append(`file${index + 1}`, file.blob, file.name) ); form.append("payload_json", JSON.stringify({ ...body, file: undefined })); diff --git a/src/types/api/message.ts b/src/types/api/message.ts index d05de3392..a85eaec80 100644 --- a/src/types/api/message.ts +++ b/src/types/api/message.ts @@ -250,7 +250,7 @@ export interface DiscordCreateMessageParams { /** `true` if this is a TTS message */ tts: boolean; /** the contents of the file being sent */ - file?: { blob: unknown; name: string }; + file?: { blob: Blob; name: string }; /** embedded rich content */ embed?: DiscordEmbed; /** JSON encoded body of any additional request fields. */ diff --git a/src/types/channel.ts b/src/types/channel.ts index 5c0716f11..5113da665 100644 --- a/src/types/channel.ts +++ b/src/types/channel.ts @@ -123,7 +123,7 @@ export interface MessageContent { } export interface FileContent { - blob: unknown; + blob: Blob; name: string; } diff --git a/src/types/webhook.ts b/src/types/webhook.ts index bc52309f9..77932cbea 100644 --- a/src/types/webhook.ts +++ b/src/types/webhook.ts @@ -57,7 +57,7 @@ export interface ExecuteWebhookOptions { /** true if this is a TTS message */ tts?: boolean; /** file contents the contents of the file being sent one of content, file, embeds */ - file?: { blob: unknown; name: string }; + file?: { blob: Blob; name: string }; /** array of up to 10 embed objects embedded rich content. */ embeds?: Embed[]; /** allowed mentions for the message */ From fdab0d93baa602e20ca39c9530a77b71d873f873 Mon Sep 17 00:00:00 2001 From: ayntee Date: Mon, 8 Mar 2021 18:13:01 +0400 Subject: [PATCH 08/43] feat: change Guild.emojis to use collection (#388) * feat(guild): change Guild.emojis to use collection * idk --- src/api/controllers/guilds.ts | 7 +++++-- src/api/handlers/guild.ts | 6 ++++-- src/api/structures/guild.ts | 6 +++++- src/types/options.ts | 5 +++-- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/api/controllers/guilds.ts b/src/api/controllers/guilds.ts index 0f428f597..48d49af19 100644 --- a/src/api/controllers/guilds.ts +++ b/src/api/controllers/guilds.ts @@ -8,6 +8,7 @@ import { UpdateGuildPayload, } from "../../types/mod.ts"; import { cache } from "../../util/cache.ts"; +import { Collection } from "../../util/collection.ts"; import { structures } from "../structures/mod.ts"; import { cacheHandlers } from "./cache.ts"; @@ -115,13 +116,15 @@ export async function handleInternalGuildEmojisUpdate(data: DiscordPayload) { if (!guild) return; const cachedEmojis = guild.emojis; - guild.emojis = payload.emojis; + guild.emojis = new Collection( + payload.emojis.map((emoji) => [emoji.id ?? emoji.name, emoji]), + ); cacheHandlers.set("guilds", payload.guild_id, guild); eventHandlers.guildEmojisUpdate?.( guild, - payload.emojis, + guild.emojis, cachedEmojis, ); } diff --git a/src/api/handlers/guild.ts b/src/api/handlers/guild.ts index 9aff87160..7a9023a9c 100644 --- a/src/api/handlers/guild.ts +++ b/src/api/handlers/guild.ts @@ -402,7 +402,9 @@ export async function getEmojis(guildID: string, addToCache = true) { if (addToCache) { const guild = await cacheHandlers.get("guilds", guildID); if (!guild) throw new Error(Errors.GUILD_NOT_FOUND); - guild.emojis = result; + + result.forEach((emoji) => guild.emojis.set(emoji.id ?? emoji.name, emoji)); + cacheHandlers.set("guilds", guildID, guild); } @@ -426,7 +428,7 @@ export async function getEmoji( if (addToCache) { const guild = await cacheHandlers.get("guilds", guildID); if (!guild) throw new Error(Errors.GUILD_NOT_FOUND); - guild.emojis.push(result); + guild.emojis.set(result.id ?? result.name, result); cacheHandlers.set( "guilds", guildID, diff --git a/src/api/structures/guild.ts b/src/api/structures/guild.ts index f1cc711cb..63e4c9b18 100644 --- a/src/api/structures/guild.ts +++ b/src/api/structures/guild.ts @@ -138,6 +138,7 @@ export async function createGuild(data: CreateGuildPayload, shardID: number) { channels = [], members, presences = [], + emojis, ...rest } = data; @@ -187,6 +188,9 @@ export async function createGuild(data: CreateGuildPayload, shardID: number) { new Collection(presences.map((p: Presence) => [p.user.id, p])), ), memberCount: createNewProp(memberCount), + emojis: createNewProp( + new Collection(emojis.map((emoji) => [emoji.id ?? emoji.name, emoji])), + ), voiceStates: createNewProp( new Collection( voiceStates.map((vs: VoiceState) => [ @@ -229,7 +233,7 @@ export interface Guild { /** Explicit content filter level */ explicitContentFilter: number; /** The custom guild emojis */ - emojis: Emoji[]; + emojis: Collection; /** Enabled guild features */ features: GuildFeatures[]; /** System channel flags */ diff --git a/src/types/options.ts b/src/types/options.ts index 770d031e2..72db39794 100644 --- a/src/types/options.ts +++ b/src/types/options.ts @@ -5,6 +5,7 @@ import { Message, Role, } from "../api/structures/mod.ts"; +import { Collection } from "../util/collection.ts"; import { DiscordPayload, Emoji, @@ -141,8 +142,8 @@ export interface EventHandlers { /** Sent when a guild's emojis have been updated. */ guildEmojisUpdate?: ( guild: Guild, - emojis: Emoji[], - cachedEmojis: Emoji[], + emojis: Collection, + cachedEmojis: Collection, ) => unknown; /** Sent when a new user joins a guild. */ guildMemberAdd?: (guild: Guild, member: Member) => unknown; From 95ac54cee92aac7e959cbc7c4609ade4d78ff7de Mon Sep 17 00:00:00 2001 From: ayntee Date: Mon, 8 Mar 2021 18:13:27 +0400 Subject: [PATCH 09/43] fix(handlers/member): change editMember() to return a Member object (#578) --- src/api/handlers/member.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/api/handlers/member.ts b/src/api/handlers/member.ts index 143e48f9c..c877cf1a6 100644 --- a/src/api/handlers/member.ts +++ b/src/api/handlers/member.ts @@ -7,6 +7,7 @@ import { Errors, ImageFormats, ImageSize, + MemberCreatePayload, MessageContent, } from "../../types/mod.ts"; import { endpoints } from "../../util/constants.ts"; @@ -227,9 +228,10 @@ export async function editMember( const result = await RequestManager.patch( endpoints.GUILD_MEMBER(guildID, memberID), options, - ); + ) as MemberCreatePayload; + const member = await structures.createMember(result, guildID); - return result; + return member; } /** From 544c3c3af21555ec73804e3f6fbe90c5ae73226e Mon Sep 17 00:00:00 2001 From: ayntee Date: Mon, 8 Mar 2021 18:13:55 +0400 Subject: [PATCH 10/43] feat(types/interactions): remove "default" from ApplicationCommandOption interface (#598) --- src/types/interactions.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/types/interactions.ts b/src/types/interactions.ts index dc405be01..5ac126eff 100644 --- a/src/types/interactions.ts +++ b/src/types/interactions.ts @@ -64,8 +64,6 @@ export interface ApplicationCommandOption { name: string; /** 1-100 character description */ description: string; - /** the first `required` option for the user to complete--only one option can be `default` */ - default?: boolean; /** if the parameter is required or optional--default `false` */ required?: boolean; /** choices for `string` and `int` types for the user to pick from */ From 9715ab4274ebb3a810fcea9f9bdb873464618f3a Mon Sep 17 00:00:00 2001 From: Pawan Akhil Date: Mon, 8 Mar 2021 19:51:17 +0530 Subject: [PATCH 11/43] Fixed field name in GuildTemplate Interface (#505) Replaced "user" field name with "creator". Co-authored-by: ayntee --- src/types/guild.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/guild.ts b/src/types/guild.ts index e31b0147f..8350f152c 100644 --- a/src/types/guild.ts +++ b/src/types/guild.ts @@ -683,7 +683,7 @@ export interface GuildTemplate { /** the ID of the user who created the template */ "creator_id": string; /** the user who created the template */ - user: UserPayload; + creator: UserPayload; /** when this template was created */ "created_at": string; /** when this template was last synced to the source guild */ From ebc48156aa3c85fd3f7f9fb3debb836a69156a14 Mon Sep 17 00:00:00 2001 From: ITOH <72305210+itohatweb@users.noreply.github.com> Date: Mon, 8 Mar 2021 15:23:04 +0100 Subject: [PATCH 12/43] feat(handlers/guild): change createGuildChannel() to use guild ID (#528) * guild > guildID * fix(test): createGuildChannel test * Update test/mod.test.ts * Update test/mod.test.ts * fmt Co-authored-by: ayntee --- src/api/handlers/guild.ts | 25 ++++++++++++------------- test/mod.test.ts | 5 +---- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/src/api/handlers/guild.ts b/src/api/handlers/guild.ts index 7a9023a9c..df04dc6b3 100644 --- a/src/api/handlers/guild.ts +++ b/src/api/handlers/guild.ts @@ -112,30 +112,29 @@ export function guildBannerURL( /** Create a channel in your server. Bot needs MANAGE_CHANNEL permissions in the server. */ export async function createGuildChannel( - guild: Guild, + guildID: string, name: string, options?: ChannelCreateOptions, ) { const hasPerm = await botHasPermission( - guild.id, + guildID, ["MANAGE_CHANNELS"], ); if (!hasPerm) { throw new Error(Errors.MISSING_MANAGE_CHANNELS); } - const result = - (await RequestManager.post(endpoints.GUILD_CHANNELS(guild.id), { - ...options, - name, - permission_overwrites: options?.permissionOverwrites?.map((perm) => ({ - ...perm, + const result = (await RequestManager.post(endpoints.GUILD_CHANNELS(guildID), { + ...options, + name, + permission_overwrites: options?.permissionOverwrites?.map((perm) => ({ + ...perm, - allow: calculateBits(perm.allow), - deny: calculateBits(perm.deny), - })), - type: options?.type || ChannelTypes.GUILD_TEXT, - })) as ChannelCreatePayload; + allow: calculateBits(perm.allow), + deny: calculateBits(perm.deny), + })), + type: options?.type || ChannelTypes.GUILD_TEXT, + })) as ChannelCreatePayload; const channelStruct = await structures.createChannel(result); diff --git a/test/mod.test.ts b/test/mod.test.ts index 4cc7aab0b..a5632ea36 100644 --- a/test/mod.test.ts +++ b/test/mod.test.ts @@ -138,10 +138,7 @@ Deno.test({ Deno.test({ name: "[channel] create a channel in a guild", async fn() { - const guild = cache.guilds.get(tempData.guildID); - if (!guild) throw new Error("Guild not found"); - - const channel = await createGuildChannel(guild, "test"); + const channel = await createGuildChannel(tempData.guildID, "test"); // Assertions assertExists(channel); From 42c743421b75109bbf197b7bab1f394da1d3bc3b Mon Sep 17 00:00:00 2001 From: ITOH <72305210+itohatweb@users.noreply.github.com> Date: Mon, 8 Mar 2021 15:51:12 +0100 Subject: [PATCH 13/43] refactor(handlers/guild): rename guild widget functions (#386) * Update guild.ts * Update guild.ts * this should be named getWidgetSettings * update mod imports --- src/api/handlers/guild.ts | 8 ++++---- src/api/handlers/mod.ts | 5 ++++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/api/handlers/guild.ts b/src/api/handlers/guild.ts index df04dc6b3..99f3bcfa5 100644 --- a/src/api/handlers/guild.ts +++ b/src/api/handlers/guild.ts @@ -694,8 +694,8 @@ export async function getAuditLogs( return result; } -/** Returns the guild embed object. Requires the MANAGE_GUILD permission. */ -export async function getEmbed(guildID: string) { +/** Returns the guild widget object. Requires the MANAGE_GUILD permission. */ +export async function getWidgetSettings(guildID: string) { const hasPerm = await botHasPermission(guildID, ["MANAGE_GUILD"]); if (!hasPerm) { throw new Error(Errors.MISSING_MANAGE_GUILD); @@ -706,8 +706,8 @@ export async function getEmbed(guildID: string) { return result; } -/** Modify a guild embed object for the guild. Requires the MANAGE_GUILD permission. */ -export async function editEmbed( +/** Modify a guild widget object for the guild. Requires the MANAGE_GUILD permission. */ +export async function editWidget( guildID: string, enabled: boolean, channelID?: string | null, diff --git a/src/api/handlers/mod.ts b/src/api/handlers/mod.ts index ddd9070a0..cb18f6431 100644 --- a/src/api/handlers/mod.ts +++ b/src/api/handlers/mod.ts @@ -39,6 +39,7 @@ import { editGuildTemplate, editIntegration, editRole, + editWidget, emojiURL, fetchMembers, getAuditLogs, @@ -66,6 +67,7 @@ import { getVanityURL, getVoiceRegions, getWebhooks, + getWidgetSettings, guildBannerURL, guildIconURL, guildSplashURL, @@ -160,7 +162,7 @@ export let handlers = { deleteIntegration, deleteRole, deleteServer, - editEmbed, + editWidget, editEmoji, editGuild, editGuildTemplate, @@ -173,6 +175,7 @@ export let handlers = { getBans, getChannel, getChannels, + getWidgetSettings, getEmbed, getEmoji, getEmojis, From 3a249d91d437824dfcd2a9a0fea7a9d9d77a0b6d Mon Sep 17 00:00:00 2001 From: Skillz4Killz <23035000+Skillz4Killz@users.noreply.github.com> Date: Mon, 8 Mar 2021 09:52:59 -0500 Subject: [PATCH 14/43] Revert "Revert "fix(handlers/webhook): return Message object instead of raw payload (#611)" (#634)" (#643) This reverts commit a515765abfae94cfcef309f29c9085e19a919291. --- src/api/handlers/webhook.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/api/handlers/webhook.ts b/src/api/handlers/webhook.ts index ba07414c6..1d2b56d8e 100644 --- a/src/api/handlers/webhook.ts +++ b/src/api/handlers/webhook.ts @@ -255,9 +255,10 @@ export async function editWebhookMessage( const result = await RequestManager.patch( endpoints.WEBHOOK_MESSAGE(webhookID, webhookToken, messageID), { ...options, allowed_mentions: options.allowed_mentions }, - ); + ) as MessageCreateOptions; - return result; + const message = await structures.createMessage(result); + return message; } export async function deleteWebhookMessage( @@ -599,5 +600,11 @@ export async function editSlashResponse( options, ); - return result; + // If the original message was edited, this will not return a message + if (!options.messageID) return result; + + const message = await structures.createMessage( + result as MessageCreateOptions, + ); + return message; } From 23708cc39db6f54a8780dd32ca99c653cc6ba110 Mon Sep 17 00:00:00 2001 From: Skillz4Killz <23035000+Skillz4Killz@users.noreply.github.com> Date: Mon, 8 Mar 2021 09:55:31 -0500 Subject: [PATCH 15/43] fix(types/webhook): update interaction response types (#644) This reverts commit 1b29c92aac3a8a7c55f414dae1b72884fea0489e. --- src/interactions/types/interactions.ts | 10 +++------- src/types/webhook.ts | 10 +++------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/src/interactions/types/interactions.ts b/src/interactions/types/interactions.ts index 295015e34..e9d291a3c 100644 --- a/src/interactions/types/interactions.ts +++ b/src/interactions/types/interactions.ts @@ -66,12 +66,8 @@ export enum InteractionType { export enum InteractionResponseType { /** ACK a `Ping` */ PONG = 1, - /** ACK a command without sending a message, eating the user's input */ - ACKNOWLEDGE = 2, - /** respond with a message, eating the user's input */ - CHANNEL_MESSAGE = 3, - /** respond with a message, showing the user's input */ + /** Respond with a message, showing the user's input */ CHANNEL_MESSAGE_WITH_SOURCE = 4, - /** ACK a command without sending a message, showing the user's input */ - ACK_WITH_SOURCE = 5, + /** ACK an interaction and edit to a response later, the user sees a loading state */ + DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE, } diff --git a/src/types/webhook.ts b/src/types/webhook.ts index 77932cbea..21e6a99cb 100644 --- a/src/types/webhook.ts +++ b/src/types/webhook.ts @@ -198,14 +198,10 @@ export interface SlashCommandCallbackData { export enum InteractionResponseType { /** ACK a `Ping` */ PONG = 1, - /** ACK a command without sending a message, eating the user's input */ - ACKNOWLEDGE = 2, - /** respond with a message, eating the user's input */ - CHANNEL_MESSAGE = 3, - /** respond with a message, showing the user's input */ + /** Respond with a message, showing the user's input */ CHANNEL_MESSAGE_WITH_SOURCE = 4, - /** ACK a command without sending a message, showing the user's input */ - ACK_WITH_SOURCE = 5, + /** ACK an interaction and edit to a response later, the user sees a loading state */ + DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE, } // TODO: remove this interface for v11 From 419f57ec74a1cd4a427d38bd0ddd6b8ce29cbe17 Mon Sep 17 00:00:00 2001 From: ayntee Date: Mon, 8 Mar 2021 19:09:12 +0400 Subject: [PATCH 16/43] fix(handlers/webhook): change return type of editWebhookMessage() & deleteWebhookMessage() to Message (#636) * fix: change any to message types * Update webhook.ts * Update src/api/handlers/webhook.ts Co-authored-by: ITOH <72305210+itohatweb@users.noreply.github.com> Co-authored-by: Skillz4Killz <23035000+Skillz4Killz@users.noreply.github.com> Co-authored-by: ITOH <72305210+itohatweb@users.noreply.github.com> From 03d66147586d889bc2b505cdd4b126792628f84a Mon Sep 17 00:00:00 2001 From: ayntee Date: Mon, 8 Mar 2021 19:10:19 +0400 Subject: [PATCH 17/43] refactor: rename slowmode to rateLimitPerUser (#645) --- src/api/handlers/channel.ts | 2 +- src/api/structures/channel.ts | 2 +- src/types/channel.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/api/handlers/channel.ts b/src/api/handlers/channel.ts index b314fbdcf..aaaa998f5 100644 --- a/src/api/handlers/channel.ts +++ b/src/api/handlers/channel.ts @@ -514,7 +514,7 @@ export async function editChannel( const payload = { ...options, // deno-lint-ignore camelcase - rate_limit_per_user: options.slowmode, + rate_limit_per_user: options.rateLimitPerUser, // deno-lint-ignore camelcase parent_id: options.parentID, // deno-lint-ignore camelcase diff --git a/src/api/structures/channel.ts b/src/api/structures/channel.ts index f0706c3ab..71bb8ec27 100644 --- a/src/api/structures/channel.ts +++ b/src/api/structures/channel.ts @@ -135,7 +135,7 @@ export interface Channel { lastMessageID?: string; /** The amount of users allowed in this voice channel. */ userLimit?: number; - /** The rate limit(slowmode) in this text channel that users can send messages. */ + /** The rate limit (slowmode) in this text channel that users can send messages. */ rateLimitPerUser?: number; /** The category id for this channel */ parentID?: string; diff --git a/src/types/channel.ts b/src/types/channel.ts index 5113da665..59b361222 100644 --- a/src/types/channel.ts +++ b/src/types/channel.ts @@ -11,7 +11,7 @@ export interface ChannelEditOptions { /** whether the channel is nsfw Text */ nsfw?: boolean; /** 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 Text */ - slowmode?: number; + rateLimitPerUser?: number; /** the bitrate (in bits) of the voice channel; 8000 to 96000 (128000 for VIP servers) Voice */ bitrate?: number; /** the user limit of the voice channel; 0 refers to no limit, 1 to 99 refers to a user limit Voice */ From 45a32463704830c44c5e3507ea58bd67532a25bc Mon Sep 17 00:00:00 2001 From: ayntee Date: Mon, 8 Mar 2021 19:41:20 +0400 Subject: [PATCH 18/43] fix(ws/shard): update status update payload (#559) * fix(ws/shard): update status update payload * :( * Update src/types/discord.ts Co-authored-by: ITOH <72305210+itohatweb@users.noreply.github.com> * it\'s activitypayload * Update src/types/discord.ts * idk * idk Co-authored-by: ITOH <72305210+itohatweb@users.noreply.github.com> --- src/types/discord.ts | 13 +++++++++++++ src/util/utils.ts | 30 ++++++++++++++++-------------- src/ws/shard.ts | 24 +++--------------------- src/ws/shard_manager.ts | 21 +++------------------ 4 files changed, 35 insertions(+), 53 deletions(-) diff --git a/src/types/discord.ts b/src/types/discord.ts index cf5efb255..b4906e373 100644 --- a/src/types/discord.ts +++ b/src/types/discord.ts @@ -6,6 +6,7 @@ import { } from "./guild.ts"; import { MemberCreatePayload } from "./member.ts"; import { Activity, Application } from "./message.ts"; +import { ActivityPayload } from "./mod.ts"; import { ClientStatusPayload } from "./presence.ts"; export interface DiscordPayload { @@ -363,3 +364,15 @@ export interface InviteDeleteEvent { /** the unique invite code */ code: string; } + +/** https://discord.com/developers/docs/topics/gateway#update-status-gateway-status-update-structure */ +export interface GatewayStatusUpdatePayload { + /** unix time (in milliseconds) of when the client went idle, or null if the client is not idle */ + since: number | null; + /** null, or the user's activities */ + activities: Pick[] | null; + /** the user's new status */ + status: StatusType; + /** whether or not the client is afk */ + afk: boolean; +} diff --git a/src/util/utils.ts b/src/util/utils.ts index 1b2bb9b1f..348cfbd5e 100644 --- a/src/util/utils.ts +++ b/src/util/utils.ts @@ -1,30 +1,32 @@ import { encode } from "../../deps.ts"; import { + Activity, ActivityType, + GatewayOpcode, + GatewayStatusUpdatePayload, ImageFormats, ImageSize, StatusType, } from "../types/mod.ts"; -import { sendGatewayCommand } from "../ws/shard_manager.ts"; +import { basicShards, sendWS } from "../ws/shard.ts"; export const sleep = (timeout: number) => { return new Promise((resolve) => setTimeout(resolve, timeout)); }; -export interface BotStatusRequest { - status: StatusType; - game: { - name?: string; - type: ActivityType; - }; -} - -export function editBotsStatus( - status: StatusType, - name?: string, - type = ActivityType.Game, +export function editBotStatus( + data: Pick, ) { - sendGatewayCommand("EDIT_BOTS_STATUS", { status, game: { name, type } }); + basicShards.forEach((shard) => { + sendWS({ + op: GatewayOpcode.StatusUpdate, + d: { + since: null, + afk: false, + ...data, + }, + }, shard.id); + }); } export function chooseRandom(array: T[]) { diff --git a/src/ws/shard.ts b/src/ws/shard.ts index 800348e40..f6627d17a 100644 --- a/src/ws/shard.ts +++ b/src/ws/shard.ts @@ -6,14 +6,15 @@ import { DiscordPayload, FetchMembersOptions, GatewayOpcode, + GatewayStatusUpdatePayload, ReadyPayload, } from "../types/mod.ts"; -import { BotStatusRequest, delay } from "../util/utils.ts"; +import { delay } from "../util/utils.ts"; import { decompressWith } from "./deps.ts"; import { handleDiscordPayload } from "./shard_manager.ts"; import { Collection } from "../util/collection.ts"; -const basicShards = new Collection(); +export const basicShards = new Collection(); const heartbeating = new Map(); const utf8decoder = new TextDecoder(); const RequestMembersQueue: RequestMemberQueuedRequest[] = []; @@ -383,25 +384,6 @@ async function processGatewayQueue() { await processGatewayQueue(); } -export function botGatewayStatusRequest(payload: BotStatusRequest) { - basicShards.forEach((shard) => { - sendWS({ - op: GatewayOpcode.StatusUpdate, - d: { - since: null, - game: payload.game.name - ? { - name: payload.game.name, - type: payload.game.type, - } - : null, - status: payload.status, - afk: false, - }, - }, shard.id); - }); -} - /** Enqueues the specified data to be transmitted to the server over the WebSocket connection, */ export function sendWS(payload: DiscordPayload, shardID = 0) { const shard = basicShards.get(shardID); diff --git a/src/ws/shard_manager.ts b/src/ws/shard_manager.ts index b43a8eaa5..f2b244c75 100644 --- a/src/ws/shard_manager.ts +++ b/src/ws/shard_manager.ts @@ -8,15 +8,12 @@ import { DiscordPayload, FetchMembersOptions, GatewayOpcode, + GatewayStatusUpdatePayload, } from "../types/mod.ts"; import { cache } from "../util/cache.ts"; import { Collection } from "../util/collection.ts"; -import { BotStatusRequest, delay } from "../util/utils.ts"; -import { - botGatewayStatusRequest, - createShard, - requestGuildMembers, -} from "./mod.ts"; +import { delay } from "../util/utils.ts"; +import { createShard, requestGuildMembers } from "./mod.ts"; let createNextShard = true; @@ -108,15 +105,3 @@ export async function requestAllMembers( options, ); } - -export function sendGatewayCommand( - type: "EDIT_BOTS_STATUS", - // deno-lint-ignore no-explicit-any - payload: Record, -) { - if (type === "EDIT_BOTS_STATUS") { - botGatewayStatusRequest(payload as BotStatusRequest); - } - - return; -} From 2c3692810d19f3124edb7669839aef2f5c27db02 Mon Sep 17 00:00:00 2001 From: ITOH <72305210+itohatweb@users.noreply.github.com> Date: Mon, 8 Mar 2021 17:37:06 +0100 Subject: [PATCH 19/43] refactor(structures): rename create* functions (#395) * structures: rename structure create functions * fix: errors occured because of structure rename * fix(controllers): errors occured because of structure rename * fix * fix createServer to createGuild rename * rename create*structure to create*Struct * update docs * Phew * rename createguildrole * fix that * fmt? * idk * why * fixxess * Update member.ts * Update member.ts * ahh found it * revert this * Update mod.ts Co-authored-by: ayntee --- docs/src/advanced/customizations.md | 38 ++++++++++++++--------------- src/api/controllers/channels.ts | 4 +-- src/api/controllers/guilds.ts | 3 +-- src/api/controllers/interactions.ts | 2 +- src/api/controllers/members.ts | 7 +++--- src/api/controllers/messages.ts | 9 +++---- src/api/controllers/misc.ts | 4 +-- src/api/controllers/reactions.ts | 4 +-- src/api/controllers/roles.ts | 4 +-- src/api/handlers/channel.ts | 12 ++++++--- src/api/handlers/guild.ts | 38 ++++++++++++++++------------- src/api/handlers/member.ts | 4 +-- src/api/handlers/message.ts | 4 +-- src/api/handlers/mod.ts | 11 +++------ src/api/handlers/webhook.ts | 6 ++--- src/api/structures/channel.ts | 2 +- src/api/structures/guild.ts | 12 ++++++--- src/api/structures/member.ts | 5 +++- src/api/structures/message.ts | 2 +- src/api/structures/mod.ts | 33 +++++++++++-------------- src/api/structures/role.ts | 2 +- src/api/structures/template.ts | 2 +- test/mod.test.ts | 9 +++---- 23 files changed, 111 insertions(+), 106 deletions(-) diff --git a/docs/src/advanced/customizations.md b/docs/src/advanced/customizations.md index a8a35b385..bffa913b5 100644 --- a/docs/src/advanced/customizations.md +++ b/docs/src/advanced/customizations.md @@ -34,17 +34,17 @@ To begin customizing, create a file in the structures folder called `member.ts`. The name of the file is not important at all. ```ts -async function createMember() { +async function createMemberStruct() { } ``` We start by declaring a function that will be run to create the structure. Once again the name here is not important. The function must take the same arguments -that the internal function takes. In this case the createMember function takes 2 -arguments. `data: MemberCreatePayload, guildID: string` +that the internal function takes. In this case the createMemberStruct function +takes 2 arguments. `data: MemberCreatePayload, guildID: string` ```ts -async function createMember(data: MemberCreatePayload, guildID: string) { +async function createMemberStruct(data: MemberCreatePayload, guildID: string) { } ``` @@ -53,7 +53,7 @@ want. My recommendation is to start by copying the current code from the internal libraries structure. ```ts -async function createMember(data: MemberCreatePayload, guildID: string) { +async function createMemberStruct(data: MemberCreatePayload, guildID: string) { const { joined_at: joinedAt, premium_since: premiumSince, @@ -92,7 +92,7 @@ and `guild` properties to the member. ```ts import { rawAvatarURL } from "../../deps.ts"; -async function createMember(data: MemberCreatePayload, guildID: string) { +async function createMemberStruct(data: MemberCreatePayload, guildID: string) { // Hidden code here to make it easier to see the changes const member = { @@ -116,11 +116,11 @@ async function createMember(data: MemberCreatePayload, guildID: string) { ``` Now we need to use this function and telling Discordeno to override the internal -createMember function. To do this, we will modify the internal functions. This -is where we reassign the value of the function. +createMemberStruct function. To do this, we will modify the internal functions. +This is where we reassign the value of the function. ```ts -structures.createMember = createMember; +structures.createMemberStruct = createMemberStruct; ``` Awesome. Now, we have one more step to complete which is to declare these new @@ -144,7 +144,7 @@ declare module "../../deps.ts" { The code should look like this right now: ```ts -async function createMember(data: MemberCreatePayload, guildID: string) { +async function createMemberStruct(data: MemberCreatePayload, guildID: string) { const { joined_at: joinedAt, premium_since: premiumSince, @@ -184,7 +184,7 @@ async function createMember(data: MemberCreatePayload, guildID: string) { return member; } -structures.createMember = createMember; +structures.createMemberStruct = createMemberStruct; declare module "../../deps.ts" { interface Member { @@ -268,7 +268,7 @@ import { rawAvatarURL, } from "../../deps.ts"; -async function createMember(data: MemberCreatePayload, guildID: string) { +async function createMemberStruct(data: MemberCreatePayload, guildID: string) { const { id, bot, @@ -291,7 +291,7 @@ async function createMember(data: MemberCreatePayload, guildID: string) { }; } -structures.createMember = createMember; +structures.createMemberStruct = createMemberStruct; declare module "../../deps.ts" { interface Member { @@ -304,15 +304,15 @@ declare module "../../deps.ts" { } ``` -You might be seeing an error on `structures.createMember`. This is happening -because our new member structures is modifying/removing existing properties that -the lib internally said it would have. To solve this, simply just add a -ts-ignore above it as you know better than TS that the typings are being -overwritten. +You might be seeing an error on `structures.createMemberStruct`. This is +happening because our new member structures is modifying/removing existing +properties that the lib internally said it would have. To solve this, simply +just add a ts-ignore above it as you know better than TS that the typings are +being overwritten. ```ts // @ts-ignore -structures.createMember = createMember; +structures.createMemberStruct = createMemberStruct; ``` ## Custom Cache diff --git a/src/api/controllers/channels.ts b/src/api/controllers/channels.ts index 455d13bc7..7b2711cc6 100644 --- a/src/api/controllers/channels.ts +++ b/src/api/controllers/channels.ts @@ -11,8 +11,8 @@ export async function handleInternalChannelCreate(data: DiscordPayload) { if (data.t !== "CHANNEL_CREATE") return; const payload = data.d as ChannelCreatePayload; - const channelStruct = await structures.createChannel(payload); + const channelStruct = await structures.createChannelStruct(payload); await cacheHandlers.set("channels", channelStruct.id, channelStruct); eventHandlers.channelCreate?.(channelStruct); @@ -58,8 +58,8 @@ export async function handleInternalChannelUpdate(data: DiscordPayload) { const payload = data.d as ChannelCreatePayload; const cachedChannel = await cacheHandlers.get("channels", payload.id); - const channelStruct = await structures.createChannel(payload); + const channelStruct = await structures.createChannelStruct(payload); await cacheHandlers.set("channels", channelStruct.id, channelStruct); if (!cachedChannel) return; diff --git a/src/api/controllers/guilds.ts b/src/api/controllers/guilds.ts index 48d49af19..c15337181 100644 --- a/src/api/controllers/guilds.ts +++ b/src/api/controllers/guilds.ts @@ -22,11 +22,10 @@ export async function handleInternalGuildCreate( // When shards resume they emit GUILD_CREATE again. if (await cacheHandlers.has("guilds", payload.id)) return; - const guildStruct = await structures.createGuild( + const guildStruct = await structures.createGuildStruct( data.d as CreateGuildPayload, shardID, ); - await cacheHandlers.set("guilds", guildStruct.id, guildStruct); if (await cacheHandlers.has("unavailableGuilds", payload.id)) { diff --git a/src/api/controllers/interactions.ts b/src/api/controllers/interactions.ts index b6feca382..f1ee04c4e 100644 --- a/src/api/controllers/interactions.ts +++ b/src/api/controllers/interactions.ts @@ -11,7 +11,7 @@ export async function handleInternalInteractionCreate(data: DiscordPayload) { if (data.t !== "INTERACTION_CREATE") return; const payload = data.d as InteractionCommandPayload; - const memberStruct = await structures.createMember( + const memberStruct = await structures.createMemberStruct( payload.member, payload.guild_id, ); diff --git a/src/api/controllers/members.ts b/src/api/controllers/members.ts index 9c2c83aca..0f940203f 100644 --- a/src/api/controllers/members.ts +++ b/src/api/controllers/members.ts @@ -19,7 +19,7 @@ export async function handleInternalGuildMemberAdd(data: DiscordPayload) { if (!guild) return; guild.memberCount++; - const memberStruct = await structures.createMember( + const memberStruct = await structures.createMemberStruct( payload, payload.guild_id, ); @@ -66,7 +66,7 @@ export async function handleInternalGuildMemberUpdate(data: DiscordPayload) { mute: guildMember?.mute || false, roles: payload.roles, }; - const memberStruct = await structures.createMember( + const memberStruct = await structures.createMemberStruct( newMemberData, payload.guild_id, ); @@ -109,11 +109,10 @@ export async function handleInternalGuildMembersChunk(data: DiscordPayload) { const members = await Promise.all( payload.members.map(async (member) => { - const memberStruct = await structures.createMember( + const memberStruct = await structures.createMemberStruct( member, payload.guild_id, ); - await cacheHandlers.set("members", memberStruct.id, memberStruct); return memberStruct; diff --git a/src/api/controllers/messages.ts b/src/api/controllers/messages.ts index cc4a319a4..7f74a9713 100644 --- a/src/api/controllers/messages.ts +++ b/src/api/controllers/messages.ts @@ -21,18 +21,17 @@ export async function handleInternalMessageCreate(data: DiscordPayload) { if (payload.member && guild) { // If in a guild cache the author as a member - const memberStruct = await structures.createMember( + const memberStruct = await structures.createMemberStruct( { ...payload.member, user: payload.author }, guild.id, ); - await cacheHandlers.set("members", memberStruct.id, memberStruct); } await Promise.all(payload.mentions.map(async (mention) => { // Cache the member if its a valid member if (mention.member && guild) { - const memberStruct = await structures.createMember( + const memberStruct = await structures.createMemberStruct( { ...mention.member, user: mention }, guild.id, ); @@ -41,7 +40,7 @@ export async function handleInternalMessageCreate(data: DiscordPayload) { } })); - const message = await structures.createMessage(payload); + const message = await structures.createMessageStruct(payload); // Cache the message await cacheHandlers.set("messages", payload.id, message); @@ -106,7 +105,7 @@ export async function handleInternalMessageUpdate(data: DiscordPayload) { return; } - const message = await structures.createMessage(payload); + const message = await structures.createMessageStruct(payload); await cacheHandlers.set("messages", payload.id, message); diff --git a/src/api/controllers/misc.ts b/src/api/controllers/misc.ts index 3a4a87dd6..95bdc58d0 100644 --- a/src/api/controllers/misc.ts +++ b/src/api/controllers/misc.ts @@ -54,7 +54,7 @@ export async function handleInternalReady( for (const [guildID, members] of initialMemberLoadQueue.entries()) { await Promise.all( members.map(async (member) => { - const memberStruct = await structures.createMember( + const memberStruct = await structures.createMemberStruct( member, guildID, ); @@ -125,7 +125,7 @@ export async function handleInternalVoiceStateUpdate(data: DiscordPayload) { if (!guild) return; const member = payload.member - ? await structures.createMember(payload.member, guild.id) + ? await structures.createMemberStruct(payload.member, guild.id) : await cacheHandlers.get("members", payload.user_id); if (!member) return; diff --git a/src/api/controllers/reactions.ts b/src/api/controllers/reactions.ts index 50e83d0bb..761eb6d65 100644 --- a/src/api/controllers/reactions.ts +++ b/src/api/controllers/reactions.ts @@ -39,7 +39,7 @@ export async function handleInternalMessageReactionAdd(data: DiscordPayload) { if (payload.member && payload.guild_id) { const guild = await cacheHandlers.get("guilds", payload.guild_id); if (guild) { - const memberStruct = await structures.createMember( + const memberStruct = await structures.createMemberStruct( payload.member, guild.id, ); @@ -95,7 +95,7 @@ export async function handleInternalMessageReactionRemove( if (payload.member && payload.guild_id) { const guild = await cacheHandlers.get("guilds", payload.guild_id); if (guild) { - const memberStruct = await structures.createMember( + const memberStruct = await structures.createMemberStruct( payload.member, guild.id, ); diff --git a/src/api/controllers/roles.ts b/src/api/controllers/roles.ts index 63292058e..6debe7372 100644 --- a/src/api/controllers/roles.ts +++ b/src/api/controllers/roles.ts @@ -14,7 +14,7 @@ export async function handleInternalGuildRoleCreate(data: DiscordPayload) { const guild = await cacheHandlers.get("guilds", payload.guild_id); if (!guild) return; - const role = await structures.createRole(payload.role); + const role = await structures.createRoleStruct(payload.role); guild.roles = guild.roles.set(payload.role.id, role); await cacheHandlers.set("guilds", payload.guild_id, guild); @@ -58,7 +58,7 @@ export async function handleInternalGuildRoleUpdate(data: DiscordPayload) { const cachedRole = guild.roles.get(payload.role.id); if (!cachedRole) return; - const role = await structures.createRole(payload.role); + const role = await structures.createRoleStruct(payload.role); guild.roles.set(payload.role.id, role); await cacheHandlers.set("guilds", guild.id, guild); diff --git a/src/api/handlers/channel.ts b/src/api/handlers/channel.ts index aaaa998f5..16c687859 100644 --- a/src/api/handlers/channel.ts +++ b/src/api/handlers/channel.ts @@ -76,7 +76,7 @@ export async function getMessage( endpoints.CHANNEL_MESSAGE(channelID, id), ) as MessageCreateOptions; - return structures.createMessage(result); + return structures.createMessageStruct(result); } /** Fetches between 2-100 messages. Requires VIEW_CHANNEL and READ_MESSAGE_HISTORY */ @@ -115,7 +115,9 @@ export async function getMessages( options, )) as MessageCreateOptions[]; - return Promise.all(result.map((res) => structures.createMessage(res))); + return Promise.all( + result.map((res) => structures.createMessageStruct(res)), + ); } /** Get pinned messages in this channel. */ @@ -124,7 +126,9 @@ export async function getPins(channelID: string) { endpoints.CHANNEL_PINS(channelID), )) as MessageCreateOptions[]; - return Promise.all(result.map((res) => structures.createMessage(res))); + return Promise.all( + result.map((res) => structures.createMessageStruct(res)), + ); } /** @@ -275,7 +279,7 @@ export async function sendMessage( }, ) as MessageCreateOptions; - return structures.createMessage(result); + return structures.createMessageStruct(result as MessageCreateOptions); } /** Delete messages from the channel. 2-100. Requires the MANAGE_MESSAGES permission */ diff --git a/src/api/handlers/guild.ts b/src/api/handlers/guild.ts index 99f3bcfa5..e0795a526 100644 --- a/src/api/handlers/guild.ts +++ b/src/api/handlers/guild.ts @@ -44,13 +44,13 @@ import { cacheHandlers } from "../controllers/cache.ts"; import { Guild, Member, structures } from "../structures/mod.ts"; /** Create a new guild. Returns a guild object on success. Fires a Guild Create Gateway event. This endpoint can be used only by bots in less than 10 guilds. */ -export async function createServer(options: CreateServerOptions) { +export async function createGuild(options: CreateServerOptions) { const guild = await RequestManager.post( endpoints.GUILDS, options, ) as CreateGuildPayload; - return structures.createGuild(guild, 0); + return structures.createGuildStruct(guild, 0); } /** Delete a guild permanently. User must be owner. Returns 204 No Content on success. Fires a Guild Delete Gateway event. @@ -136,8 +136,7 @@ export async function createGuildChannel( type: options?.type || ChannelTypes.GUILD_TEXT, })) as ChannelCreatePayload; - const channelStruct = await structures.createChannel(result); - + const channelStruct = await structures.createChannelStruct(result); await cacheHandlers.set("channels", channelStruct.id, channelStruct); return channelStruct; @@ -186,7 +185,7 @@ export async function getChannels(guildID: string, addToCache = true) { ) as ChannelCreatePayload[]; return Promise.all(result.map(async (res) => { - const channelStruct = await structures.createChannel(res, guildID); + const channelStruct = await structures.createChannelStruct(res, guildID); if (addToCache) { await cacheHandlers.set("channels", channelStruct.id, channelStruct); } @@ -204,7 +203,10 @@ export async function getChannel(channelID: string, addToCache = true) { endpoints.CHANNEL_BASE(channelID), ) as ChannelCreatePayload; - const channelStruct = await structures.createChannel(result, result.guild_id); + const channelStruct = await structures.createChannelStruct( + result, + result.guild_id, + ); if (addToCache) { await cacheHandlers.set("channels", channelStruct.id, channelStruct); } @@ -293,8 +295,7 @@ export async function getMember( endpoints.GUILD_MEMBER(guildID, id), ) as MemberCreatePayload; - const memberStruct = await structures.createMember(data, guildID); - + const memberStruct = await structures.createMemberStruct(data, guildID); await cacheHandlers.set("members", memberStruct.id, memberStruct); return memberStruct; @@ -439,7 +440,7 @@ export async function getEmoji( } /** Create a new role for the guild. Requires the MANAGE_ROLES permission. */ -export async function createGuildRole( +export async function createRole( guildID: string, options: CreateRoleOptions, reason?: string, @@ -459,7 +460,7 @@ export async function createGuildRole( ); const roleData = result as RoleData; - const role = await structures.createRole(roleData); + const role = await structures.createRoleStruct(roleData); const guild = await cacheHandlers.get("guilds", guildID); guild?.roles.set(role.id, role); @@ -646,7 +647,10 @@ export async function getMembers( const memberStructures = await Promise.all( result.map(async (member) => { - const memberStruct = await structures.createMember(member, guildID); + const memberStruct = await structures.createMemberStruct( + member, + guildID, + ); await cacheHandlers.set("members", memberStruct.id, memberStruct); @@ -962,7 +966,7 @@ export async function getTemplate(templateCode: string) { const result = await RequestManager.get( endpoints.GUILD_TEMPLATE(templateCode), ) as GuildTemplate; - const template = await structures.createTemplate(result); + const template = await structures.createTemplateStruct(result); return template; } @@ -1016,7 +1020,7 @@ export async function getGuildTemplates(guildID: string) { endpoints.GUILD_TEMPLATES(guildID), ) as GuildTemplate[]; - return templates.map((template) => structures.createTemplate(template)); + return templates.map((template) => structures.createTemplateStruct(template)); } /** @@ -1034,7 +1038,7 @@ export async function deleteGuildTemplate( `${endpoints.GUILD_TEMPLATES(guildID)}/${templateCode}`, ) as GuildTemplate; - return structures.createTemplate(deletedTemplate); + return structures.createTemplateStruct(deletedTemplate); } /** @@ -1066,7 +1070,7 @@ export async function createGuildTemplate( data, ) as GuildTemplate; - return structures.createTemplate(template); + return structures.createTemplateStruct(template); } /** @@ -1081,7 +1085,7 @@ export async function syncGuildTemplate(guildID: string, templateCode: string) { `${endpoints.GUILD_TEMPLATES(guildID)}/${templateCode}`, ) as GuildTemplate; - return structures.createTemplate(template); + return structures.createTemplateStruct(template); } /** @@ -1112,5 +1116,5 @@ export async function editGuildTemplate( data, ) as GuildTemplate; - return structures.createTemplate(template); + return structures.createTemplateStruct(template); } diff --git a/src/api/handlers/member.ts b/src/api/handlers/member.ts index c877cf1a6..b28170a3c 100644 --- a/src/api/handlers/member.ts +++ b/src/api/handlers/member.ts @@ -132,7 +132,7 @@ export async function sendDirectMessage( endpoints.USER_DM, { recipient_id: memberID }, ) as DMChannelCreatePayload; - const channelStruct = await structures.createChannel( + const channelStruct = await structures.createChannelStruct( dmChannelData as unknown as ChannelCreatePayload, ); // Recreate the channel and add it undert he users id @@ -229,7 +229,7 @@ export async function editMember( endpoints.GUILD_MEMBER(guildID, memberID), options, ) as MemberCreatePayload; - const member = await structures.createMember(result, guildID); + const member = await structures.createMemberStruct(result, guildID); return member; } diff --git a/src/api/handlers/message.ts b/src/api/handlers/message.ts index 24c6579bb..7c6bf553b 100644 --- a/src/api/handlers/message.ts +++ b/src/api/handlers/message.ts @@ -324,7 +324,7 @@ export async function editMessage( content, ); - return structures.createMessage(result as MessageCreateOptions); + return structures.createMessageStruct(result as MessageCreateOptions); } /** Crosspost a message in a News Channel to following channels. */ @@ -333,5 +333,5 @@ export async function publishMessage(channelID: string, messageID: string) { endpoints.CHANNEL_MESSAGE_CROSSPOST(channelID, messageID), ) as MessageCreateOptions; - return structures.createMessage(data); + return structures.createMessageStruct(data); } diff --git a/src/api/handlers/mod.ts b/src/api/handlers/mod.ts index cb18f6431..c291ab020 100644 --- a/src/api/handlers/mod.ts +++ b/src/api/handlers/mod.ts @@ -20,11 +20,11 @@ import { ban, categoryChildrenIDs, createEmoji, + createGuild, createGuildChannel, createGuildFromTemplate, - createGuildRole, createGuildTemplate, - createServer, + createRole, deleteChannel, deleteChannelOverwrite, deleteEmoji, @@ -33,7 +33,6 @@ import { deleteRole, deleteServer, editChannelOverwrite, - editEmbed, editEmoji, editGuild, editGuildTemplate, @@ -48,7 +47,6 @@ import { getBans, getChannel, getChannels, - getEmbed, getEmoji, getEmojis, getGuild, @@ -153,9 +151,9 @@ export let handlers = { createEmoji, createGuildChannel, createGuildFromTemplate, - createGuildRole, + createRole, createGuildTemplate, - createServer, + createGuild, deleteChannel, deleteEmoji, deleteGuildTemplate, @@ -176,7 +174,6 @@ export let handlers = { getChannel, getChannels, getWidgetSettings, - getEmbed, getEmoji, getEmojis, getGuild, diff --git a/src/api/handlers/webhook.ts b/src/api/handlers/webhook.ts index 1d2b56d8e..6047f0114 100644 --- a/src/api/handlers/webhook.ts +++ b/src/api/handlers/webhook.ts @@ -203,7 +203,7 @@ export async function executeWebhook( ); if (!options.wait) return; - return structures.createMessage(result as MessageCreateOptions); + return structures.createMessageStruct(result as MessageCreateOptions); } export async function editWebhookMessage( @@ -257,7 +257,7 @@ export async function editWebhookMessage( { ...options, allowed_mentions: options.allowed_mentions }, ) as MessageCreateOptions; - const message = await structures.createMessage(result); + const message = await structures.createMessageStruct(result); return message; } @@ -603,7 +603,7 @@ export async function editSlashResponse( // If the original message was edited, this will not return a message if (!options.messageID) return result; - const message = await structures.createMessage( + const message = await structures.createMessageStruct( result as MessageCreateOptions, ); return message; diff --git a/src/api/structures/channel.ts b/src/api/structures/channel.ts index 71bb8ec27..35eeb9c53 100644 --- a/src/api/structures/channel.ts +++ b/src/api/structures/channel.ts @@ -77,7 +77,7 @@ const baseChannel: Partial = { }; // deno-lint-ignore require-await -export async function createChannel( +export async function createChannelStruct( data: ChannelCreatePayload, guildID?: string, ) { diff --git a/src/api/structures/guild.ts b/src/api/structures/guild.ts index 63e4c9b18..e7b8f19f9 100644 --- a/src/api/structures/guild.ts +++ b/src/api/structures/guild.ts @@ -107,7 +107,10 @@ const baseGuild: Partial = { }, }; -export async function createGuild(data: CreateGuildPayload, shardID: number) { +export async function createGuildStruct( + data: CreateGuildPayload, + shardID: number, +) { const { disovery_splash: discoverySplash, default_message_notifications: defaultMessageNotifications, @@ -143,11 +146,14 @@ export async function createGuild(data: CreateGuildPayload, shardID: number) { } = data; const roles = await Promise.all( - data.roles.map((role) => structures.createRole(role)), + data.roles.map((role) => structures.createRoleStruct(role)), ); await Promise.all(channels.map(async (channel) => { - const channelStruct = await structures.createChannel(channel, rest.id); + const channelStruct = await structures.createChannelStruct( + channel, + rest.id, + ); return cacheHandlers.set("channels", channelStruct.id, channelStruct); })); diff --git a/src/api/structures/member.ts b/src/api/structures/member.ts index 3b385172f..df18dfa29 100644 --- a/src/api/structures/member.ts +++ b/src/api/structures/member.ts @@ -72,7 +72,10 @@ const baseMember: Partial = { }, }; -export async function createMember(data: MemberCreatePayload, guildID: string) { +export async function createMemberStruct( + data: MemberCreatePayload, + guildID: string, +) { const { joined_at: joinedAt, premium_since: premiumSince, diff --git a/src/api/structures/message.ts b/src/api/structures/message.ts index 629d435c4..c6e0240cc 100644 --- a/src/api/structures/message.ts +++ b/src/api/structures/message.ts @@ -133,7 +133,7 @@ const baseMessage: Partial = { }, }; -export async function createMessage(data: MessageCreateOptions) { +export async function createMessageStruct(data: MessageCreateOptions) { const { guild_id: guildID = "", channel_id: channelID, diff --git a/src/api/structures/mod.ts b/src/api/structures/mod.ts index 8a2896232..8c3e44724 100644 --- a/src/api/structures/mod.ts +++ b/src/api/structures/mod.ts @@ -1,20 +1,22 @@ -import { createChannel } from "./channel.ts"; -import { createGuild } from "./guild.ts"; -import { createMember } from "./member.ts"; -import { createMessage } from "./message.ts"; -import { createRole } from "./role.ts"; -import { createTemplate } from "./template.ts"; +import { Channel, createChannelStruct } from "./channel.ts"; +import { createGuildStruct, Guild } from "./guild.ts"; +import { createMemberStruct, Member } from "./member.ts"; +import { createMessageStruct, Message } from "./message.ts"; +import { createRoleStruct, Role } from "./role.ts"; +import { createTemplateStruct, Template } from "./template.ts"; /** This is the placeholder where the structure creation functions are kept. */ export let structures = { - createChannel, - createGuild, - createMember, - createMessage, - createRole, - createTemplate, + createChannelStruct, + createGuildStruct, + createMemberStruct, + createMessageStruct, + createRoleStruct, + createTemplateStruct, }; +export type { Channel, Guild, Member, Message, Role, Template }; + export type Structures = typeof structures; /** This function is used to update/reload/customize the internal structures of Discordeno. @@ -28,10 +30,3 @@ export function updateStructures(newStructures: Structures) { ...newStructures, }; } - -export type { Channel } from "./channel.ts"; -export type { Guild } from "./guild.ts"; -export type { Member } from "./member.ts"; -export type { Message } from "./message.ts"; -export type { Role } from "./role.ts"; -export type { Template } from "./template.ts"; diff --git a/src/api/structures/role.ts b/src/api/structures/role.ts index ca09e60fd..1b2282cdb 100644 --- a/src/api/structures/role.ts +++ b/src/api/structures/role.ts @@ -67,7 +67,7 @@ const baseRole: Partial = { }; // deno-lint-ignore require-await -export async function createRole({ tags = {}, ...rest }: RoleData) { +export async function createRoleStruct({ tags = {}, ...rest }: RoleData) { const restProps: Record> = {}; for (const key of Object.keys(rest)) { // @ts-ignore index signature diff --git a/src/api/structures/template.ts b/src/api/structures/template.ts index 77e574651..79b45d38e 100644 --- a/src/api/structures/template.ts +++ b/src/api/structures/template.ts @@ -11,7 +11,7 @@ const baseTemplate: Partial