From 34a2baa799f92b93bc481cb9514b7f5c14e0047f Mon Sep 17 00:00:00 2001 From: Skillz4Killz <23035000+Skillz4Killz@users.noreply.github.com> Date: Sun, 24 Oct 2021 12:15:11 +0000 Subject: [PATCH] more events --- src/bot.ts | 583 +++++++++++++++++- src/handlers/messages/MESSAGE_CREATE.ts | 47 +- src/handlers/messages/MESSAGE_DELETE.ts | 24 +- src/handlers/messages/MESSAGE_DELETE_BULK.ts | 31 +- src/handlers/messages/MESSAGE_REACTION_ADD.ts | 47 +- .../messages/MESSAGE_REACTION_REMOVE.ts | 36 +- .../messages/MESSAGE_REACTION_REMOVE_ALL.ts | 22 +- .../messages/MESSAGE_REACTION_REMOVE_EMOJI.ts | 36 +- src/handlers/messages/MESSAGE_UPDATE.ts | 30 +- src/handlers/mod.ts | 5 +- src/helpers/misc/get_gateway_bot.ts | 15 +- src/helpers/mod.ts | 174 ------ src/transformers/emoji.ts | 37 ++ src/types/emojis/emoji.ts | 4 +- src/ws/handle_on_message.ts | 18 + 15 files changed, 732 insertions(+), 377 deletions(-) create mode 100644 src/transformers/emoji.ts diff --git a/src/bot.ts b/src/bot.ts index 8a0cae9af..7d0357d8e 100644 --- a/src/bot.ts +++ b/src/bot.ts @@ -14,7 +14,6 @@ import { requireBotChannelPermissions, requireBotGuildPermissions, } from "./util/permissions.ts"; -import { getGatewayBot } from "./helpers/misc/get_gateway_bot.ts"; import { checkRateLimits, processQueue, @@ -45,6 +44,7 @@ import { transformRole, DiscordenoVoiceState, transformVoiceState, + DiscordenoMessage, } from "./transformers/mod.ts"; import { baseEndpoints, @@ -125,14 +125,174 @@ import { handleIntegrationCreate, handleIntegrationUpdate, handleIntegrationDelete, - handleGuildLoaded + handleGuildLoaded, } from "./handlers/mod.ts"; import { DiscordenoInteraction, transformInteraction } from "./transformers/interaction.ts"; import { DiscordenoIntegration, transformIntegration } from "./transformers/integration.ts"; -import {Emoji} from "./types/emojis/emoji.ts"; +import { Emoji } from "./types/emojis/emoji.ts"; import { transformApplication } from "./transformers/application.ts"; import { transformTeam } from "./transformers/team.ts"; import { DiscordenoInvite, transformInvite } from "./transformers/invite.ts"; +import { + addDiscoverySubcategory, + addReaction, + addReactions, + addRole, + addToThread, + archiveThread, + avatarURL, + ban, + banMember, + batchEditSlashCommandPermissions, + categoryChildren, + channelOverwriteHasPermission, + connectToVoiceChannel, + createChannel, + createEmoji, + createGuild, + createGuildFromTemplate, + createGuildTemplate, + createInvite, + createRole, + createSlashCommand, + createStageInstance, + createWebhook, + deleteChannel, + deleteChannelOverwrite, + deleteEmoji, + deleteGuild, + deleteGuildTemplate, + deleteIntegration, + deleteInvite, + deleteMessage, + deleteMessages, + deleteRole, + deleteSlashCommand, + deleteSlashResponse, + deleteStageInstance, + deleteThread, + deleteWebhook, + deleteWebhookMessage, + deleteWebhookWithToken, + disconnectMember, + editBotNickname, + editBotProfile, + editBotStatus, + editChannel, + editChannelOverwrite, + editDiscovery, + editEmoji, + editGuild, + editGuildTemplate, + editMember, + editMessage, + editRole, + editSlashCommandPermissions, + editSlashResponse, + editThread, + editWebhook, + editWebhookMessage, + editWebhookWithToken, + editWelcomeScreen, + editWidget, + emojiURL, + fetchMembers, + followChannel, + getActiveThreads, + getApplicationInfo, + getArchivedThreads, + getAuditLogs, + getAvailableVoiceRegions, + getBan, + getBans, + getChannel, + getChannelInvites, + getChannels, + getChannelWebhooks, + getDiscoveryCategories, + getEmoji, + getEmojis, + getGatewayBot, + getGuild, + getGuildPreview, + getGuildTemplates, + getIntegrations, + getInvite, + getInvites, + getMember, + getMembers, + getMessage, + getMessages, + getOriginalInteractionResponse, + getPins, + getPruneCount, + getReactions, + getRoles, + getSlashCommand, + getSlashCommandPermission, + getSlashCommandPermissions, + getSlashCommands, + getStageInstance, + getTemplate, + getThreadMembers, + getUser, + getVanityURL, + getVoiceRegions, + getWebhook, + getWebhookMessage, + getWebhooks, + getWebhookWithToken, + getWelcomeScreen, + getWidget, + getWidgetImageURL, + getWidgetSettings, + guildBannerURL, + guildIconURL, + guildSplashURL, + isButton, + isChannelSynced, + isSelectMenu, + isSlashCommand, + joinThread, + kick, + kickMember, + leaveGuild, + leaveThread, + lockThread, + moveMember, + pin, + pinMessage, + pruneMembers, + publishMessage, + removeAllReactions, + removeDiscoverySubcategory, + removeReaction, + removeReactionEmoji, + removeRole, + removeThreadMember, + sendDirectMessage, + sendInteractionResponse, + sendMessage, + sendWebhook, + startPrivateThread, + startThread, + startTyping, + suppressEmbeds, + swapChannels, + syncGuildTemplate, + unarchiveThread, + unban, + unbanMember, + unlockThread, + unpin, + unpinMessage, + updateBotVoiceState, + updateStageInstance, + upsertSlashCommand, + upsertSlashCommands, + validDiscoveryTerm, +} from "./helpers/mod.ts"; +import { DiscordenoEmoji, transformEmoji } from "./transformers/emoji.ts"; export async function createBot(options: CreateBotOptions) { return { @@ -141,7 +301,7 @@ export async function createBot(options: CreateBotOptions) { token: `Bot ${options.token}`, events: options.events, intents: options.intents.reduce((bits, next) => (bits |= DiscordGatewayIntents[next]), 0), - botGatewayData: options.botGatewayData || (await getGatewayBot()), + botGatewayData: options.botGatewayData, isReady: false, activeGuildIds: new Set(), constants: createBotConstants(), @@ -158,6 +318,20 @@ export async function createBot(options: CreateBotOptions) { options: Record ) {}, fetchAllMembersProcessingRequests: new Collection(), + messages: { + get: async function (id: bigint): Promise { + return {} as any as DiscordenoMessage; + }, + has: async function (id: bigint): Promise { + return false; + }, + set: async function (id: bigint, guild: DiscordenoMessage): Promise { + return; + }, + delete: async function (id: bigint): Promise { + return; + }, + }, guilds: { get: async function (id: bigint): Promise { return {} as any as DiscordenoGuild; @@ -248,7 +422,6 @@ export function createEventHandlers(events: Partial): EventHandle function ignore() {} return { - channelCreate: events.channelCreate ?? ignore, debug: events.debug ?? ignore, dispatchRequirements: events.dispatchRequirements ?? ignore, integrationCreate: events.integrationCreate ?? ignore, @@ -260,6 +433,13 @@ export function createEventHandlers(events: Partial): EventHandle guildMemberAdd: events.guildMemberAdd ?? ignore, guildMemberRemove: events.guildMemberRemove ?? ignore, guildMemberUpdate: events.guildMemberUpdate ?? ignore, + messageCreate: events.messageCreate ?? ignore, + messageDelete: events.messageDelete ?? ignore, + messageUpdate: events.messageUpdate ?? ignore, + reactionAdd: events.reactionAdd ?? ignore, + reactionRemove: events.reactionRemove ?? ignore, + reactionRemoveAll: events.reactionRemoveAll ?? ignore, + reactionRemoveEmoji: events.reactionRemoveEmoji ?? ignore, channelCreate: events.channelCreate ?? ignore, voiceChannelLeave: events.voiceChannelLeave ?? ignore, channelDelete: events.channelDelete ?? ignore, @@ -339,16 +519,18 @@ export function createRestManager(options: CreateRestManagerOptions) { } export async function startBot(bot: Bot) { - const transformers = createTransformers(bot.transformers); - - // SETUP UTILS + // SETUP bot.utils = createUtils({}); + bot.transformers = createTransformers(bot.transformers); + bot.helpers = createHelpers(bot.helpers); // START REST bot.rest = createRestManager({ token: bot.token }); // START WS bot.gateway = createGatewayManager({}); + + if (!bot.botGatewayData) bot.botGatewayData = await bot.helpers.getGatewayBot(bot); } export function createUtils(options: Partial) { @@ -413,6 +595,7 @@ export function createGatewayManager(options: Partial): GatewayM cache: { guildIds: new Set(), loadingGuildIds: new Set(), + editedMessages: new Collection(), }, secretKey: options.secretKey ?? "", url: options.url ?? "", @@ -495,8 +678,331 @@ export type Bot = CreatedBot & { rest: RestManager; gateway: GatewayManager; transformers: Transformers; + helpers: Helpers; }; +export interface Helpers { + addDiscoverySubcategory: typeof addDiscoverySubcategory; + addReaction: typeof addReaction; + addReactions: typeof addReactions; + addRole: typeof addRole; + avatarURL: typeof avatarURL; + ban: typeof ban; + banMember: typeof banMember; + batchEditSlashCommandPermissions: typeof batchEditSlashCommandPermissions; + categoryChildren: typeof categoryChildren; + channelOverwriteHasPermission: typeof channelOverwriteHasPermission; + connectToVoiceChannel: typeof connectToVoiceChannel; + createChannel: typeof createChannel; + createEmoji: typeof createEmoji; + createGuild: typeof createGuild; + createGuildFromTemplate: typeof createGuildFromTemplate; + createGuildTemplate: typeof createGuildTemplate; + createInvite: typeof createInvite; + createRole: typeof createRole; + createSlashCommand: typeof createSlashCommand; + createStageInstance: typeof createStageInstance; + createWebhook: typeof createWebhook; + deleteChannel: typeof deleteChannel; + deleteChannelOverwrite: typeof deleteChannelOverwrite; + deleteEmoji: typeof deleteEmoji; + deleteGuild: typeof deleteGuild; + deleteGuildTemplate: typeof deleteGuildTemplate; + deleteIntegration: typeof deleteIntegration; + deleteInvite: typeof deleteInvite; + deleteMessage: typeof deleteMessage; + deleteMessages: typeof deleteMessages; + deleteRole: typeof deleteRole; + deleteSlashCommand: typeof deleteSlashCommand; + deleteSlashResponse: typeof deleteSlashResponse; + deleteStageInstance: typeof deleteStageInstance; + deleteWebhook: typeof deleteWebhook; + deleteWebhookMessage: typeof deleteWebhookMessage; + deleteWebhookWithToken: typeof deleteWebhookWithToken; + disconnectMember: typeof disconnectMember; + editBotNickname: typeof editBotNickname; + editBotProfile: typeof editBotProfile; + editBotStatus: typeof editBotStatus; + editChannel: typeof editChannel; + editChannelOverwrite: typeof editChannelOverwrite; + editDiscovery: typeof editDiscovery; + editEmoji: typeof editEmoji; + editGuild: typeof editGuild; + editGuildTemplate: typeof editGuildTemplate; + editMember: typeof editMember; + editMessage: typeof editMessage; + editRole: typeof editRole; + editSlashResponse: typeof editSlashResponse; + editSlashCommandPermissions: typeof editSlashCommandPermissions; + editWebhook: typeof editWebhook; + editWebhookMessage: typeof editWebhookMessage; + editWebhookWithToken: typeof editWebhookWithToken; + editWelcomeScreen: typeof editWelcomeScreen; + editWidget: typeof editWidget; + emojiURL: typeof emojiURL; + fetchMembers: typeof fetchMembers; + followChannel: typeof followChannel; + getAuditLogs: typeof getAuditLogs; + getAvailableVoiceRegions: typeof getAvailableVoiceRegions; + getBan: typeof getBan; + getBans: typeof getBans; + getChannel: typeof getChannel; + getChannelInvites: typeof getChannelInvites; + getChannels: typeof getChannels; + getChannelWebhooks: typeof getChannelWebhooks; + getDiscoveryCategories: typeof getDiscoveryCategories; + getEmoji: typeof getEmoji; + getEmojis: typeof getEmojis; + getGatewayBot: typeof getGatewayBot; + getGuild: typeof getGuild; + getGuildPreview: typeof getGuildPreview; + getGuildTemplates: typeof getGuildTemplates; + getIntegrations: typeof getIntegrations; + getInvite: typeof getInvite; + getInvites: typeof getInvites; + getMember: typeof getMember; + getMembers: typeof getMembers; + getMessage: typeof getMessage; + getMessages: typeof getMessages; + getOriginalInteractionResponse: typeof getOriginalInteractionResponse; + getPins: typeof getPins; + getPruneCount: typeof getPruneCount; + getReactions: typeof getReactions; + getRoles: typeof getRoles; + getSlashCommand: typeof getSlashCommand; + getSlashCommandPermission: typeof getSlashCommandPermission; + getSlashCommandPermissions: typeof getSlashCommandPermissions; + getSlashCommands: typeof getSlashCommands; + getStageInstance: typeof getStageInstance; + getTemplate: typeof getTemplate; + getUser: typeof getUser; + getApplicationInfo: typeof getApplicationInfo; + getVanityURL: typeof getVanityURL; + getVoiceRegions: typeof getVoiceRegions; + getWebhook: typeof getWebhook; + getWebhookMessage: typeof getWebhookMessage; + getWebhooks: typeof getWebhooks; + getWebhookWithToken: typeof getWebhookWithToken; + getWelcomeScreen: typeof getWelcomeScreen; + getWidget: typeof getWidget; + getWidgetImageURL: typeof getWidgetImageURL; + getWidgetSettings: typeof getWidgetSettings; + guildBannerURL: typeof guildBannerURL; + guildIconURL: typeof guildIconURL; + guildSplashURL: typeof guildSplashURL; + isButton: typeof isButton; + isSelectMenu: typeof isSelectMenu; + isSlashCommand: typeof isSlashCommand; + isChannelSynced: typeof isChannelSynced; + kick: typeof kick; + kickMember: typeof kickMember; + leaveGuild: typeof leaveGuild; + moveMember: typeof moveMember; + pin: typeof pin; + pinMessage: typeof pinMessage; + pruneMembers: typeof pruneMembers; + publishMessage: typeof publishMessage; + removeAllReactions: typeof removeAllReactions; + removeDiscoverySubcategory: typeof removeDiscoverySubcategory; + removeReaction: typeof removeReaction; + removeReactionEmoji: typeof removeReactionEmoji; + removeRole: typeof removeRole; + sendDirectMessage: typeof sendDirectMessage; + sendInteractionResponse: typeof sendInteractionResponse; + sendMessage: typeof sendMessage; + sendWebhook: typeof sendWebhook; + startTyping: typeof startTyping; + swapChannels: typeof swapChannels; + syncGuildTemplate: typeof syncGuildTemplate; + unban: typeof unban; + unbanMember: typeof unbanMember; + unpin: typeof unpin; + unpinMessage: typeof unpinMessage; + updateBotVoiceState: typeof updateBotVoiceState; + updateStageInstance: typeof updateStageInstance; + upsertSlashCommand: typeof upsertSlashCommand; + upsertSlashCommands: typeof upsertSlashCommands; + validDiscoveryTerm: typeof validDiscoveryTerm; + addToThread: typeof addToThread; + archiveThread: typeof archiveThread; + deleteThread: typeof deleteThread; + editThread: typeof editThread; + getActiveThreads: typeof getActiveThreads; + getArchivedThreads: typeof getArchivedThreads; + getThreadMembers: typeof getThreadMembers; + joinThread: typeof joinThread; + leaveThread: typeof leaveThread; + lockThread: typeof lockThread; + removeThreadMember: typeof removeThreadMember; + startPrivateThread: typeof startPrivateThread; + startThread: typeof startThread; + unarchiveThread: typeof unarchiveThread; + unlockThread: typeof unlockThread; + suppressEmbeds: typeof suppressEmbeds; +} + +export function createHelpers(options: Partial) { + return { + addDiscoverySubcategory: options.addDiscoverySubcategory || addDiscoverySubcategory, + addReaction: options.addReaction || addReaction, + addReactions: options.addReactions || addReactions, + addRole: options.addRole || addRole, + avatarURL: options.avatarURL || avatarURL, + ban: options.ban || ban, + banMember: options.banMember || banMember, + batchEditSlashCommandPermissions: options.batchEditSlashCommandPermissions || batchEditSlashCommandPermissions, + categoryChildren: options.categoryChildren || categoryChildren, + channelOverwriteHasPermission: options.channelOverwriteHasPermission || channelOverwriteHasPermission, + connectToVoiceChannel: options.connectToVoiceChannel || connectToVoiceChannel, + createChannel: options.createChannel || createChannel, + createEmoji: options.createEmoji || createEmoji, + createGuild: options.createGuild || createGuild, + createGuildFromTemplate: options.createGuildFromTemplate || createGuildFromTemplate, + createGuildTemplate: options.createGuildTemplate || createGuildTemplate, + createInvite: options.createInvite || createInvite, + createRole: options.createRole || createRole, + createSlashCommand: options.createSlashCommand || createSlashCommand, + createStageInstance: options.createStageInstance || createStageInstance, + createWebhook: options.createWebhook || createWebhook, + deleteChannel: options.deleteChannel || deleteChannel, + deleteChannelOverwrite: options.deleteChannelOverwrite || deleteChannelOverwrite, + deleteEmoji: options.deleteEmoji || deleteEmoji, + deleteGuild: options.deleteGuild || deleteGuild, + deleteGuildTemplate: options.deleteGuildTemplate || deleteGuildTemplate, + deleteIntegration: options.deleteIntegration || deleteIntegration, + deleteInvite: options.deleteInvite || deleteInvite, + deleteMessage: options.deleteMessage || deleteMessage, + deleteMessages: options.deleteMessages || deleteMessages, + deleteRole: options.deleteRole || deleteRole, + deleteSlashCommand: options.deleteSlashCommand || deleteSlashCommand, + deleteSlashResponse: options.deleteSlashResponse || deleteSlashResponse, + deleteStageInstance: options.deleteStageInstance || deleteStageInstance, + deleteWebhook: options.deleteWebhook || deleteWebhook, + deleteWebhookMessage: options.deleteWebhookMessage || deleteWebhookMessage, + deleteWebhookWithToken: options.deleteWebhookWithToken || deleteWebhookWithToken, + disconnectMember: options.disconnectMember || disconnectMember, + editBotNickname: options.editBotNickname || editBotNickname, + editBotProfile: options.editBotProfile || editBotProfile, + editBotStatus: options.editBotStatus || editBotStatus, + editChannel: options.editChannel || editChannel, + editChannelOverwrite: options.editChannelOverwrite || editChannelOverwrite, + editDiscovery: options.editDiscovery || editDiscovery, + editEmoji: options.editEmoji || editEmoji, + editGuild: options.editGuild || editGuild, + editGuildTemplate: options.editGuildTemplate || editGuildTemplate, + editMember: options.editMember || editMember, + editMessage: options.editMessage || editMessage, + editRole: options.editRole || editRole, + editSlashResponse: options.editSlashResponse || editSlashResponse, + editSlashCommandPermissions: options.editSlashCommandPermissions || editSlashCommandPermissions, + editWebhook: options.editWebhook || editWebhook, + editWebhookMessage: options.editWebhookMessage || editWebhookMessage, + editWebhookWithToken: options.editWebhookWithToken || editWebhookWithToken, + editWelcomeScreen: options.editWelcomeScreen || editWelcomeScreen, + editWidget: options.editWidget || editWidget, + emojiURL: options.emojiURL || emojiURL, + fetchMembers: options.fetchMembers || fetchMembers, + followChannel: options.followChannel || followChannel, + getAuditLogs: options.getAuditLogs || getAuditLogs, + getAvailableVoiceRegions: options.getAvailableVoiceRegions || getAvailableVoiceRegions, + getBan: options.getBan || getBan, + getBans: options.getBans || getBans, + getChannel: options.getChannel || getChannel, + getChannelInvites: options.getChannelInvites || getChannelInvites, + getChannels: options.getChannels || getChannels, + getChannelWebhooks: options.getChannelWebhooks || getChannelWebhooks, + getDiscoveryCategories: options.getDiscoveryCategories || getDiscoveryCategories, + getEmoji: options.getEmoji || getEmoji, + getEmojis: options.getEmojis || getEmojis, + getGatewayBot: options.getGatewayBot || getGatewayBot, + getGuild: options.getGuild || getGuild, + getGuildPreview: options.getGuildPreview || getGuildPreview, + getGuildTemplates: options.getGuildTemplates || getGuildTemplates, + getIntegrations: options.getIntegrations || getIntegrations, + getInvite: options.getInvite || getInvite, + getInvites: options.getInvites || getInvites, + getMember: options.getMember || getMember, + getMembers: options.getMembers || getMembers, + getMessage: options.getMessage || getMessage, + getMessages: options.getMessages || getMessages, + getOriginalInteractionResponse: options.getOriginalInteractionResponse || getOriginalInteractionResponse, + getPins: options.getPins || getPins, + getPruneCount: options.getPruneCount || getPruneCount, + getReactions: options.getReactions || getReactions, + getRoles: options.getRoles || getRoles, + getSlashCommand: options.getSlashCommand || getSlashCommand, + getSlashCommandPermission: options.getSlashCommandPermission || getSlashCommandPermission, + getSlashCommandPermissions: options.getSlashCommandPermissions || getSlashCommandPermissions, + getSlashCommands: options.getSlashCommands || getSlashCommands, + getStageInstance: options.getStageInstance || getStageInstance, + getTemplate: options.getTemplate || getTemplate, + getUser: options.getUser || getUser, + getApplicationInfo: options.getApplicationInfo || getApplicationInfo, + getVanityURL: options.getVanityURL || getVanityURL, + getVoiceRegions: options.getVoiceRegions || getVoiceRegions, + getWebhook: options.getWebhook || getWebhook, + getWebhookMessage: options.getWebhookMessage || getWebhookMessage, + getWebhooks: options.getWebhooks || getWebhooks, + getWebhookWithToken: options.getWebhookWithToken || getWebhookWithToken, + getWelcomeScreen: options.getWelcomeScreen || getWelcomeScreen, + getWidget: options.getWidget || getWidget, + getWidgetImageURL: options.getWidgetImageURL || getWidgetImageURL, + getWidgetSettings: options.getWidgetSettings || getWidgetSettings, + guildBannerURL: options.guildBannerURL || guildBannerURL, + guildIconURL: options.guildIconURL || guildIconURL, + guildSplashURL: options.guildSplashURL || guildSplashURL, + isButton: options.isButton || isButton, + isSelectMenu: options.isSelectMenu || isSelectMenu, + isSlashCommand: options.isSlashCommand || isSlashCommand, + isChannelSynced: options.isChannelSynced || isChannelSynced, + kick: options.kick || kick, + kickMember: options.kickMember || kickMember, + leaveGuild: options.leaveGuild || leaveGuild, + moveMember: options.moveMember || moveMember, + pin: options.pin || pin, + pinMessage: options.pinMessage || pinMessage, + pruneMembers: options.pruneMembers || pruneMembers, + publishMessage: options.publishMessage || publishMessage, + removeAllReactions: options.removeAllReactions || removeAllReactions, + removeDiscoverySubcategory: options.removeDiscoverySubcategory || removeDiscoverySubcategory, + removeReaction: options.removeReaction || removeReaction, + removeReactionEmoji: options.removeReactionEmoji || removeReactionEmoji, + removeRole: options.removeRole || removeRole, + sendDirectMessage: options.sendDirectMessage || sendDirectMessage, + sendInteractionResponse: options.sendInteractionResponse || sendInteractionResponse, + sendMessage: options.sendMessage || sendMessage, + sendWebhook: options.sendWebhook || sendWebhook, + startTyping: options.startTyping || startTyping, + swapChannels: options.swapChannels || swapChannels, + syncGuildTemplate: options.syncGuildTemplate || syncGuildTemplate, + unban: options.unban || unban, + unbanMember: options.unbanMember || unbanMember, + unpin: options.unpin || unpin, + unpinMessage: options.unpinMessage || unpinMessage, + updateBotVoiceState: options.updateBotVoiceState || updateBotVoiceState, + updateStageInstance: options.updateStageInstance || updateStageInstance, + upsertSlashCommand: options.upsertSlashCommand || upsertSlashCommand, + upsertSlashCommands: options.upsertSlashCommands || upsertSlashCommands, + validDiscoveryTerm: options.validDiscoveryTerm || validDiscoveryTerm, + addToThread: options.addToThread || addToThread, + archiveThread: options.archiveThread || archiveThread, + deleteThread: options.deleteThread || deleteThread, + editThread: options.editThread || editThread, + getActiveThreads: options.getActiveThreads || getActiveThreads, + getArchivedThreads: options.getArchivedThreads || getArchivedThreads, + getThreadMembers: options.getThreadMembers || getThreadMembers, + joinThread: options.joinThread || joinThread, + leaveThread: options.leaveThread || leaveThread, + lockThread: options.lockThread || lockThread, + removeThreadMember: options.removeThreadMember || removeThreadMember, + startPrivateThread: options.startPrivateThread || startPrivateThread, + startThread: options.startThread || startThread, + unarchiveThread: options.unarchiveThread || unarchiveThread, + unlockThread: options.unlockThread || unlockThread, + suppressEmbeds: options.suppressEmbeds || suppressEmbeds, + }; +} + export interface Transformers { snowflake: typeof snowflakeToBigint; channel: typeof transformChannel; @@ -511,22 +1017,25 @@ export interface Transformers { invite: typeof transformInvite; application: typeof transformApplication; team: typeof transformTeam; + emoji: typeof transformEmoji; } export function createTransformers(options: Partial) { return { - snowflake: options.snowflake || snowflakeToBigint, + application: options.application || transformApplication, channel: options.channel || transformChannel, + emoji: options.emoji || transformEmoji, guild: options.guild || transformGuild, - user: options.user || transformUser, + integration: options.integration || transformIntegration, + interaction: options.interaction || transformInteraction, + invite: options.invite || transformInvite, member: options.member || transformMember, message: options.message || transformMessage, role: options.role || transformRole, - voiceState: options.voiceState || transformVoiceState, - integration: options.integration || transformIntegration, - invite: options.invite || transformInvite, - application: options.application || transformApplication, + user: options.user || transformUser, team: options.team || transformTeam, + voiceState: options.voiceState || transformVoiceState, + snowflake: options.snowflake || snowflakeToBigint, }; } @@ -600,6 +1109,7 @@ export interface GatewayManager { cache: { guildIds: Set; loadingGuildIds: Set; + editedMessages: Collection; }; // METHODS @@ -652,6 +1162,51 @@ export interface EventHandlers { guildMemberAdd: (bot: Bot, member: DiscordenoMember, user: DiscordenoUser) => any; guildMemberRemove: (bot: Bot, user: DiscordenoUser, guildId: bigint) => any; guildMemberUpdate: (bot: Bot, member: DiscordenoMember, user: DiscordenoUser) => any; + messageCreate: (bot: Bot, message: DiscordenoMessage) => any; + messageDelete: ( + bot: Bot, + payload: { id: bigint; channelId: bigint; guildId?: bigint }, + message?: DiscordenoMessage + ) => any; + messageUpdate: (bot: Bot, message: DiscordenoMessage, oldMessage?: DiscordenoMessage) => any; + reactionAdd: ( + bot: Bot, + payload: { + userId: bigint; + channelId: bigint; + messageId: bigint; + guildId?: bigint; + member?: DiscordenoMember; + emoji: DiscordenoEmoji; + } + ) => any; + reactionRemove: ( + bot: Bot, + payload: { + userId: bigint; + channelId: bigint; + messageId: bigint; + guildId?: bigint; + emoji: DiscordenoEmoji; + } + ) => any; + reactionRemoveEmoji: ( + bot: Bot, + payload: { + channelId: bigint; + messageId: bigint; + guildId?: bigint; + emoji: DiscordenoEmoji; + } + ) => any; + reactionRemoveAll: ( + bot: Bot, + payload: { + channelId: bigint; + messageId: bigint; + guildId?: bigint; + } + ) => any; channelCreate: (bot: Bot, channel: DiscordenoChannel) => any; dispatchRequirements: (bot: Bot, data: GatewayPayload, shardId: number) => any; voiceChannelLeave: (bot: Bot, voiceState: DiscordenoVoiceState, channel: DiscordenoChannel) => any; diff --git a/src/handlers/messages/MESSAGE_CREATE.ts b/src/handlers/messages/MESSAGE_CREATE.ts index b8c541c1c..dc985d5ff 100644 --- a/src/handlers/messages/MESSAGE_CREATE.ts +++ b/src/handlers/messages/MESSAGE_CREATE.ts @@ -1,46 +1,13 @@ -import { eventHandlers } from "../../bot.ts"; -import { cacheHandlers } from "../../cache.ts"; -import { structures } from "../../structures/mod.ts"; +import { Bot } from "../../bot.ts"; import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; -import type { GuildMemberWithUser } from "../../types/members/guild_member.ts"; import type { Message } from "../../types/messages/message.ts"; -import { snowflakeToBigint } from "../../util/bigint.ts"; +import { SnakeCasedPropertiesDeep } from "../../types/util.ts"; -export async function handleMessageCreate(data: DiscordGatewayPayload) { - const payload = data.d as Message; - const channel = await cacheHandlers.get("channels", snowflakeToBigint(payload.channelId)); - if (channel) channel.lastMessageId = snowflakeToBigint(payload.id); +export async function handleMessageCreate(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as SnakeCasedPropertiesDeep; - const guild = payload.guildId ? await cacheHandlers.get("guilds", snowflakeToBigint(payload.guildId)) : undefined; + const message = bot.transformers.message(bot, payload); + await bot.cache.messages.set(message.id, message); - if (payload.member && guild) { - // If in a guild cache the author as a member - const discordenoMember = await structures.createDiscordenoMember( - { ...payload.member, user: payload.author } as GuildMemberWithUser, - guild.id - ); - await cacheHandlers.set("members", discordenoMember.id, discordenoMember); - } - - if (payload.mentions && guild) { - await Promise.all( - payload.mentions.map(async (mention) => { - // Cache the member if its a valid member - if (mention.member) { - const discordenoMember = await structures.createDiscordenoMember( - { ...mention.member, user: mention } as GuildMemberWithUser, - guild.id - ); - - return cacheHandlers.set("members", snowflakeToBigint(mention.id), discordenoMember); - } - }) - ); - } - - const message = await structures.createDiscordenoMessage(data.d as Message); - // Cache the message - await cacheHandlers.set("messages", snowflakeToBigint(payload.id), message); - - eventHandlers.messageCreate?.(message); + bot.events.messageCreate(bot, message); } diff --git a/src/handlers/messages/MESSAGE_DELETE.ts b/src/handlers/messages/MESSAGE_DELETE.ts index afbfc20a0..e4a1c061f 100644 --- a/src/handlers/messages/MESSAGE_DELETE.ts +++ b/src/handlers/messages/MESSAGE_DELETE.ts @@ -1,18 +1,20 @@ -import { eventHandlers } from "../../bot.ts"; -import { cacheHandlers } from "../../cache.ts"; +import { Bot } from "../../bot.ts"; import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; import type { MessageDelete } from "../../types/messages/message_delete.ts"; -import { snowflakeToBigint } from "../../util/bigint.ts"; +import { SnakeCasedPropertiesDeep } from "../../types/util.ts"; -export async function handleMessageDelete(data: DiscordGatewayPayload) { - const payload = data.d as MessageDelete; - const channel = await cacheHandlers.get("channels", snowflakeToBigint(payload.channelId)); - if (!channel) return; +export async function handleMessageDelete(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as SnakeCasedPropertiesDeep; + const id = bot.transformers.snowflake(payload.id); - eventHandlers.messageDelete?.( - { id: payload.id, channel }, - await cacheHandlers.get("messages", snowflakeToBigint(payload.id)) + bot.events.messageDelete(bot, + { + id, + channelId: bot.transformers.snowflake(payload.channel_id), + guildId: payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined, + }, + await bot.cache.messages.get(id) ); - await cacheHandlers.delete("messages", snowflakeToBigint(payload.id)); + await bot.cache.messages.delete(id); } diff --git a/src/handlers/messages/MESSAGE_DELETE_BULK.ts b/src/handlers/messages/MESSAGE_DELETE_BULK.ts index 64987feeb..9e3c839fa 100644 --- a/src/handlers/messages/MESSAGE_DELETE_BULK.ts +++ b/src/handlers/messages/MESSAGE_DELETE_BULK.ts @@ -1,18 +1,23 @@ -import { eventHandlers } from "../../bot.ts"; -import { cacheHandlers } from "../../cache.ts"; +import { Bot } from "../../bot.ts"; import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; import type { MessageDeleteBulk } from "../../types/messages/message_delete_bulk.ts"; -import { snowflakeToBigint } from "../../util/bigint.ts"; +import { SnakeCasedPropertiesDeep } from "../../types/util.ts"; -export async function handleMessageDeleteBulk(data: DiscordGatewayPayload) { - const payload = data.d as MessageDeleteBulk; - const channel = await cacheHandlers.get("channels", snowflakeToBigint(payload.channelId)); - if (!channel) return; +export async function handleMessageDeleteBulk(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as SnakeCasedPropertiesDeep; - return Promise.all( - payload.ids.map(async (id) => { - eventHandlers.messageDelete?.({ id, channel }, await cacheHandlers.get("messages", snowflakeToBigint(id))); - await cacheHandlers.delete("messages", snowflakeToBigint(id)); - }) - ); + const ids = payload.ids.map((id) => bot.transformers.snowflake(id)); + const messages = await bot.cache.execute("BULK_DELETE_MESSAGES", { messageIds: ids }); + + ids.forEach((id) => { + bot.events.messageDelete( + bot, + { + id, + channelId: bot.transformers.snowflake(payload.channel_id), + guildId: payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined, + }, + messages.find((m) => m.id === id) + ); + }); } diff --git a/src/handlers/messages/MESSAGE_REACTION_ADD.ts b/src/handlers/messages/MESSAGE_REACTION_ADD.ts index 1dffcaf89..5fac56c22 100644 --- a/src/handlers/messages/MESSAGE_REACTION_ADD.ts +++ b/src/handlers/messages/MESSAGE_REACTION_ADD.ts @@ -1,39 +1,18 @@ -import { botId, eventHandlers } from "../../bot.ts"; -import { cacheHandlers } from "../../cache.ts"; -import { structures } from "../../structures/mod.ts"; +import { Bot } from "../../bot.ts"; import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; import type { MessageReactionAdd } from "../../types/messages/message_reaction_add.ts"; -import { snowflakeToBigint } from "../../util/bigint.ts"; +import { SnakeCasedPropertiesDeep } from "../../types/util.ts"; -export async function handleMessageReactionAdd(data: DiscordGatewayPayload) { - const payload = data.d as MessageReactionAdd; - const message = await cacheHandlers.get("messages", snowflakeToBigint(payload.messageId)); +export async function handleMessageReactionAdd(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as SnakeCasedPropertiesDeep; - if (message) { - const reactionExisted = message.reactions?.find( - (reaction) => reaction.emoji.id === payload.emoji.id && reaction.emoji.name === payload.emoji.name - ); - - if (reactionExisted) reactionExisted.count++; - else { - const newReaction = { - count: 1, - me: snowflakeToBigint(payload.userId) === botId, - emoji: { ...payload.emoji, id: payload.emoji.id || undefined }, - }; - message.reactions = message.reactions ? [...message.reactions, newReaction] : [newReaction]; - } - - await cacheHandlers.set("messages", snowflakeToBigint(payload.messageId), message); - } - - if (payload.member && payload.guildId) { - const guild = await cacheHandlers.get("guilds", snowflakeToBigint(payload.guildId)); - if (guild) { - const discordenoMember = await structures.createDiscordenoMember(payload.member, guild.id); - await cacheHandlers.set("members", discordenoMember.id, discordenoMember); - } - } - - eventHandlers.reactionAdd?.(payload, message); + const guildId = payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined; + bot.events.reactionAdd(bot, { + userId: bot.transformers.snowflake(payload.user_id), + channelId: bot.transformers.snowflake(payload.channel_id), + messageId: bot.transformers.snowflake(payload.message_id), + guildId, + member: payload.member && guildId ? bot.transformers.member(bot, payload.member, guildId) : undefined, + emoji: bot.transformers.emoji(bot, payload.emoji), + }); } diff --git a/src/handlers/messages/MESSAGE_REACTION_REMOVE.ts b/src/handlers/messages/MESSAGE_REACTION_REMOVE.ts index 603568af7..c44b65c98 100644 --- a/src/handlers/messages/MESSAGE_REACTION_REMOVE.ts +++ b/src/handlers/messages/MESSAGE_REACTION_REMOVE.ts @@ -1,30 +1,16 @@ -import { eventHandlers } from "../../bot.ts"; -import { cacheHandlers } from "../../cache.ts"; +import { Bot, } from "../../bot.ts"; import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; import type { MessageReactionRemove } from "../../types/messages/message_reaction_remove.ts"; -import { snowflakeToBigint } from "../../util/bigint.ts"; +import { SnakeCasedPropertiesDeep } from "../../types/util.ts"; -export async function handleMessageReactionRemove(data: DiscordGatewayPayload) { - const payload = data.d as MessageReactionRemove; - const message = await cacheHandlers.get("messages", snowflakeToBigint(payload.messageId)); +export async function handleMessageReactionRemove(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as SnakeCasedPropertiesDeep; - if (message) { - const reaction = message.reactions?.find( - (reaction) => - // MUST USE == because discord sends null and we use undefined - reaction.emoji.id == payload.emoji.id && reaction.emoji.name === payload.emoji.name - ); - - if (reaction) { - reaction.count--; - if (reaction.count === 0) { - message.reactions = message.reactions?.filter((r) => r.count !== 0); - } - if (!message.reactions?.length) message.reactions = undefined; - - await cacheHandlers.set("messages", message.id, message); - } - } - - eventHandlers.reactionRemove?.(payload, message); + bot.events.reactionRemove(bot, { + userId: bot.transformers.snowflake(payload.user_id), + channelId: bot.transformers.snowflake(payload.channel_id), + messageId: bot.transformers.snowflake(payload.message_id), + guildId: payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined, + emoji: bot.transformers.emoji(bot, payload.emoji), + }); } diff --git a/src/handlers/messages/MESSAGE_REACTION_REMOVE_ALL.ts b/src/handlers/messages/MESSAGE_REACTION_REMOVE_ALL.ts index 79d84995e..1a7e5e35b 100644 --- a/src/handlers/messages/MESSAGE_REACTION_REMOVE_ALL.ts +++ b/src/handlers/messages/MESSAGE_REACTION_REMOVE_ALL.ts @@ -1,18 +1,14 @@ -import { eventHandlers } from "../../bot.ts"; -import { cacheHandlers } from "../../cache.ts"; +import { Bot } from "../../bot.ts"; import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; import type { MessageReactionRemoveAll } from "../../types/messages/message_reaction_remove_all.ts"; -import { snowflakeToBigint } from "../../util/bigint.ts"; +import { SnakeCasedPropertiesDeep } from "../../types/util.ts"; -export async function handleMessageReactionRemoveAll(data: DiscordGatewayPayload) { - const payload = data.d as MessageReactionRemoveAll; - const message = await cacheHandlers.get("messages", snowflakeToBigint(payload.messageId)); +export async function handleMessageReactionRemoveAll(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as SnakeCasedPropertiesDeep; - if (message?.reactions) { - message.reactions = undefined; - - await cacheHandlers.set("messages", snowflakeToBigint(payload.messageId), message); - } - - eventHandlers.reactionRemoveAll?.(payload, message); + bot.events.reactionRemoveAll(bot, { + channelId: bot.transformers.snowflake(payload.channel_id), + messageId: bot.transformers.snowflake(payload.message_id), + guildId: payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined, + }); } diff --git a/src/handlers/messages/MESSAGE_REACTION_REMOVE_EMOJI.ts b/src/handlers/messages/MESSAGE_REACTION_REMOVE_EMOJI.ts index 422ab74be..6a63e970c 100644 --- a/src/handlers/messages/MESSAGE_REACTION_REMOVE_EMOJI.ts +++ b/src/handlers/messages/MESSAGE_REACTION_REMOVE_EMOJI.ts @@ -1,31 +1,15 @@ -import { eventHandlers } from "../../bot.ts"; -import { cacheHandlers } from "../../cache.ts"; +import { Bot } from "../../bot.ts"; import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; import type { MessageReactionRemoveEmoji } from "../../types/messages/message_reaction_remove_emoji.ts"; -import { snowflakeToBigint } from "../../util/bigint.ts"; +import { SnakeCasedPropertiesDeep } from "../../types/util.ts"; -export async function handleMessageReactionRemoveEmoji(data: DiscordGatewayPayload) { - const payload = data.d as MessageReactionRemoveEmoji; - const message = await cacheHandlers.get("messages", snowflakeToBigint(payload.messageId)); +export async function handleMessageReactionRemoveEmoji(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as SnakeCasedPropertiesDeep; - if (message?.reactions) { - message.reactions = message.reactions.filter( - (reaction) => - !( - // MUST USE == because discord sends null and we use undefined - (reaction.emoji.id == payload.emoji.id && reaction.emoji.name === payload.emoji.name) - ) - ); - - if (!message.reactions.length) message.reactions = undefined; - - await cacheHandlers.set("messages", message.id, message); - } - - eventHandlers.reactionRemoveEmoji?.( - payload.emoji, - snowflakeToBigint(payload.messageId), - snowflakeToBigint(payload.channelId), - payload.guildId ? snowflakeToBigint(payload.guildId) : undefined - ); + bot.events.reactionRemoveEmoji(bot, { + channelId: bot.transformers.snowflake(payload.channel_id), + messageId: bot.transformers.snowflake(payload.message_id), + guildId: payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined, + emoji: bot.transformers.emoji(bot, payload.emoji), + }); } diff --git a/src/handlers/messages/MESSAGE_UPDATE.ts b/src/handlers/messages/MESSAGE_UPDATE.ts index 32a6b21c0..6662fd4ff 100644 --- a/src/handlers/messages/MESSAGE_UPDATE.ts +++ b/src/handlers/messages/MESSAGE_UPDATE.ts @@ -1,26 +1,18 @@ -import { eventHandlers } from "../../bot.ts"; -import { cacheHandlers } from "../../cache.ts"; -import { structures } from "../../structures/mod.ts"; +import { Bot } from "../../bot.ts"; import type { DiscordGatewayPayload } from "../../types/gateway/gateway_payload.ts"; import type { Message } from "../../types/messages/message.ts"; -import { snowflakeToBigint } from "../../util/bigint.ts"; +import { SnakeCasedPropertiesDeep } from "../../types/util.ts"; -export async function handleMessageUpdate(data: DiscordGatewayPayload) { - const payload = data.d as Message; - const channel = await cacheHandlers.get("channels", snowflakeToBigint(payload.channelId)); - if (!channel) return; +export async function handleMessageUpdate(bot: Bot, data: DiscordGatewayPayload) { + const payload = data.d as SnakeCasedPropertiesDeep; + if (!payload.edited_timestamp) return; - const oldMessage = await cacheHandlers.get("messages", snowflakeToBigint(payload.id)); - if (!oldMessage) return; + const message = bot.transformers.message(bot, payload); - // Messages with embeds can trigger update but they wont have edited_timestamp - if (!payload.editedTimestamp || oldMessage.content === payload.content) { - return; - } + // GET OLD CACHED MESSAGE IF ONE WAS CACHED + const oldMessage = await bot.cache.messages.get(message.id); + if (oldMessage?.content === message.content) return; - const message = await structures.createDiscordenoMessage(payload); - - await cacheHandlers.set("messages", snowflakeToBigint(payload.id), message); - - eventHandlers.messageUpdate?.(message, oldMessage); + await bot.cache.messages.set(message.id, message); + bot.events.messageUpdate(bot, message, oldMessage); } diff --git a/src/handlers/mod.ts b/src/handlers/mod.ts index 6a108e792..7535358e6 100644 --- a/src/handlers/mod.ts +++ b/src/handlers/mod.ts @@ -56,6 +56,7 @@ export { handleGuildBanRemove, handleGuildCreate, handleGuildDelete, + handleGuildLoaded, handleGuildEmojisUpdate, handleGuildIntegrationsUpdate, handleGuildMemberAdd, @@ -96,7 +97,3 @@ export { handleVoiceStateUpdate, handleWebhooksUpdate, }; - -export const handlers = { - -}; diff --git a/src/helpers/misc/get_gateway_bot.ts b/src/helpers/misc/get_gateway_bot.ts index 1281d08e5..f93d618f4 100644 --- a/src/helpers/misc/get_gateway_bot.ts +++ b/src/helpers/misc/get_gateway_bot.ts @@ -3,10 +3,21 @@ import type { Bot } from "../../bot.ts"; import { SnakeCasedPropertiesDeep } from "../../types/util.ts"; /** Get the bots Gateway metadata that can help during the operation of large or sharded bots. */ -export async function getGatewayBot(bot: Bot) { - return await bot.rest.runMethod>( +export async function getGatewayBot(bot: Bot): Promise { + const result = await bot.rest.runMethod>( bot.rest, "get", bot.constants.endpoints.GATEWAY_BOT ); + + return { + url: result.url, + shards: result.shards, + sessionStartLimit: { + total: result.session_start_limit.total, + remaining: result.session_start_limit.remaining, + resetAfter: result.session_start_limit.reset_after, + maxConcurrency: result.session_start_limit.max_concurrency, + }, + }; } diff --git a/src/helpers/mod.ts b/src/helpers/mod.ts index 3c7a37fde..37baae052 100644 --- a/src/helpers/mod.ts +++ b/src/helpers/mod.ts @@ -313,177 +313,3 @@ export { unlockThread, suppressEmbeds, }; - -export let helpers = { - // channels - channelOverwriteHasPermission, - createChannel, - deleteChannelOverwrite, - deleteChannel, - editChannelOverwrite, - editChannel, - followChannel, - getChannelWebhooks, - getChannel, - getChannels, - getPins, - isChannelSynced, - startTyping, - swapChannels, - updateBotVoiceState, - createStageInstance, - getStageInstance, - updateStageInstance, - deleteStageInstance, - // commands - createSlashCommand, - deleteSlashCommand, - deleteSlashResponse, - editSlashResponse, - getSlashCommandPermission, - getSlashCommandPermissions, - batchEditSlashCommandPermissions, - editSlashCommandPermissions, - sendInteractionResponse, - getSlashCommand, - getSlashCommands, - upsertSlashCommand, - upsertSlashCommands, - getOriginalInteractionResponse, - // emojis - createEmoji, - deleteEmoji, - editEmoji, - getEmoji, - getEmojis, - // guilds - categoryChildren, - createGuild, - deleteGuild, - editGuild, - editWidget, - editWelcomeScreen, - emojiURL, - getAuditLogs, - getAvailableVoiceRegions, - getBan, - getBans, - getGuildPreview, - getGuild, - getWelcomeScreen, - getPruneCount, - getVanityURL, - getVoiceRegions, - getWidgetImageURL, - getWidgetSettings, - getWidget, - guildBannerURL, - guildIconURL, - guildSplashURL, - leaveGuild, - // discovery - addDiscoverySubcategory, - editDiscovery, - getDiscoveryCategories, - removeDiscoverySubcategory, - validDiscoveryTerm, - // integrations - deleteIntegration, - getIntegrations, - // invites - createInvite, - deleteInvite, - getChannelInvites, - getInvite, - getInvites, - // members - avatarURL, - banMember, - disconnectMember, - editBotNickname, - editBotProfile, - editMember, - fetchMembers, - getMember, - getMembers, - kickMember, - moveMember, - pruneMembers, - sendDirectMessage, - unbanMember, - // messages - addReaction, - addReactions, - deleteMessage, - deleteMessages, - editMessage, - getMessage, - getMessages, - getReactions, - pinMessage, - publishMessage, - removeAllReactions, - removeReactionEmoji, - removeReaction, - sendMessage, - unpinMessage, - // misc - getGatewayBot, - getUser, - // roles - addRole, - createRole, - deleteRole, - editRole, - getRoles, - removeRole, - // templates - createGuildFromTemplate, - createGuildTemplate, - deleteGuildTemplate, - editGuildTemplate, - getGuildTemplates, - getTemplate, - syncGuildTemplate, - // voice - connectToVoiceChannel, - // webhooks - createWebhook, - deleteWebhookMessage, - deleteWebhookWithToken, - deleteWebhook, - editWebhookMessage, - editWebhookWithToken, - editWebhook, - sendWebhook, - getWebhookWithToken, - getWebhook, - getWebhooks, - getWebhookMessage, - // threads - addToThread, - archiveThread, - deleteThread, - editThread, - getActiveThreads, - getArchivedThreads, - getThreadMembers, - joinThread, - leaveThread, - lockThread, - removeThreadMember, - startPrivateThread, - startThread, - unarchiveThread, - unlockThread, - suppressEmbeds, -}; - -export type Helpers = typeof helpers; - -export function updateHelpers(newHelpers: Partial) { - helpers = { - ...helpers, - ...newHelpers, - }; -} diff --git a/src/transformers/emoji.ts b/src/transformers/emoji.ts new file mode 100644 index 000000000..52021e398 --- /dev/null +++ b/src/transformers/emoji.ts @@ -0,0 +1,37 @@ +import { Bot } from "../bot.ts"; +import { Emoji } from "../types/emojis/emoji.ts"; +import { SnakeCasedPropertiesDeep } from "../types/util.ts"; +import { DiscordenoUser } from "./member.ts"; + +export function transformEmoji(bot: Bot, payload: SnakeCasedPropertiesDeep): DiscordenoEmoji { + return { + id: payload.id ? bot.transformers.snowflake(payload.id) : undefined, + name: payload.name || undefined, + roles: payload.roles?.map((id) => bot.transformers.snowflake(id)), + user: payload.user ? bot.transformers.user(bot, payload.user) : undefined, + // TODO: change to bitfield? + requireColons: payload.require_colons, + managed: payload.managed, + animated: payload.animated, + available: payload.available, + }; +} + +export interface DiscordenoEmoji { + /** Emoji id */ + id?: bigint; + /** Emoji name (can only be null in reaction emoji objects) */ + name?: string; + /** Roles allowed to use this emoji */ + roles?: bigint[]; + /** User that created this emoji */ + user?: DiscordenoUser; + /** Whether this emoji must be wrapped in colons */ + requireColons?: boolean; + /** Whether this emoji is managed */ + managed?: boolean; + /** Whether this emoji is animated */ + animated?: boolean; + /** Whether this emoji can be used, may be false due to loss of Server Boosts */ + available?: boolean; +} diff --git a/src/types/emojis/emoji.ts b/src/types/emojis/emoji.ts index 5609db102..2c12acca4 100644 --- a/src/types/emojis/emoji.ts +++ b/src/types/emojis/emoji.ts @@ -3,9 +3,9 @@ import { User } from "../users/user.ts"; /** https://discord.com/developers/docs/resources/emoji#emoji-object-emoji-structure */ export interface Emoji { /** Emoji id */ - id: string | null; + id?: string; /** Emoji name (can only be null in reaction emoji objects) */ - name: string | null; + name?: string; /** Roles allowed to use this emoji */ roles?: string[]; /** User that created this emoji */ diff --git a/src/ws/handle_on_message.ts b/src/ws/handle_on_message.ts index d0b8faa46..9a4a215bb 100644 --- a/src/ws/handle_on_message.ts +++ b/src/ws/handle_on_message.ts @@ -5,6 +5,7 @@ import type { DiscordHello } from "../types/gateway/hello.ts"; import type { DiscordReady } from "../types/gateway/ready.ts"; import { Guild } from "../types/guilds/guild.ts"; import { UnavailableGuild } from "../types/guilds/unavailable_guild.ts"; +import { Message } from "../types/messages/mod.ts"; import { SnakeCasedPropertiesDeep } from "../types/util.ts"; import { snowflakeToBigint } from "../util/bigint.ts"; import { delay } from "../util/utils.ts"; @@ -135,6 +136,23 @@ export async function handleOnMessage(gateway: GatewayManager, message: any, sha gateway.cache.guildIds.add(id); } + // MESSAGE_UPDATE CAN SPAM FOR NO REASON USE THIS TO IGNORE + if (messageData.t === "MESSAGE_UPDATE") { + const payload = messageData.d as SnakeCasedPropertiesDeep; + + const id = snowflakeToBigint(payload.id); + const content = payload.content || ""; + const cached = gateway.cache.editedMessages.get(id); + + if (cached === content) return; + else { + // ADD TO LOCAL CACHE FOR FUTURE EVENTS. + gateway.cache.editedMessages.set(id, content); + // REMOVE AFTER 10 SECONDS FROM CACHE + setTimeout(() => gateway.cache.editedMessages.delete(id), 10000); + } + } + // MUST HANDLE GUILD_DELETE EVENTS FOR UNAVAILABLE if (messageData.t === "GUILD_DELETE") { if ((messageData.d as UnavailableGuild).unavailable) return;