This commit is contained in:
Skillz
2023-03-26 11:32:21 -05:00
158 changed files with 4452 additions and 136 deletions

View File

@@ -10,11 +10,19 @@ on:
paths:
- "website/**"
- ".github/workflows/site.yml"
- "jsdoc2md.json"
- "typedoc.json"
- "package.json"
- "packages/**"
pull_request:
branches: ["main"]
paths:
- "website/**"
- ".github/workflows/site.yml"
- "jsdoc2md.json"
- "typedoc.json"
- "package.json"
- "packages/**"
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:

View File

@@ -1,57 +1,29 @@
import type { CreateGatewayManagerOptions, GatewayManager } from '@discordeno/gateway'
import { ShardSocketCloseCodes, createGatewayManager } from '@discordeno/gateway'
import { createGatewayManager, ShardSocketCloseCodes } from '@discordeno/gateway'
import type { CreateRestManagerOptions, RestManager } from '@discordeno/rest'
import { createRestManager } from '@discordeno/rest'
import type {
Camelize,
DiscordAuditLogEntry,
DiscordAutoModerationActionExecution,
DiscordAutoModerationRule,
DiscordChannel,
DiscordChannelPinsUpdate,
DiscordGatewayPayload,
DiscordGuild,
DiscordGuildApplicationCommandPermissions,
DiscordGuildBanAddRemove,
DiscordGuildEmojisUpdate,
DiscordGuildMemberAdd,
DiscordGuildMemberRemove,
DiscordGuildMemberUpdate,
DiscordGuildMembersChunk,
DiscordGuildRoleCreate,
DiscordGuildRoleDelete,
DiscordGuildRoleUpdate,
DiscordGuildStickersUpdate,
DiscordIntegrationCreateUpdate,
DiscordIntegrationDelete,
DiscordInteraction,
DiscordInviteCreate,
DiscordInviteDelete,
DiscordMessage,
DiscordMessageDelete,
DiscordMessageDeleteBulk,
DiscordMessageReactionAdd,
DiscordMessageReactionRemove,
DiscordMessageReactionRemoveAll,
DiscordMessageReactionRemoveEmoji,
DiscordPresenceUpdate,
DiscordReady,
DiscordScheduledEvent,
DiscordScheduledEventUserAdd,
DiscordScheduledEventUserRemove,
DiscordStageInstance,
DiscordThreadListSync,
DiscordThreadMemberUpdate,
DiscordThreadMembersUpdate,
DiscordTypingStart,
DiscordUnavailableGuild,
DiscordUser,
DiscordVoiceServerUpdate,
DiscordVoiceState,
DiscordWebhookUpdate,
GatewayIntents,
} from '@discordeno/types'
import { createLogger } from '@discordeno/utils'
import type { DiscordEmoji, DiscordGatewayPayload, DiscordReady, GatewayIntents } from '@discordeno/types'
import { createLogger, getBotIdFromToken, type Collection } from '@discordeno/utils'
import { createBotGatewayHandlers } from './handlers.js'
import { createTransformers, type Transformers } from './transformers.js'
import type { ApplicationCommandPermission } from './transformers/applicationCommandPermission.js'
import type { AuditLogEntry } from './transformers/auditLogEntry.js'
import type { AutoModerationActionExecution } from './transformers/automodActionExecution.js'
import type { AutoModerationRule } from './transformers/automodRule.js'
import type { Channel } from './transformers/channel.js'
import type { Emoji } from './transformers/emoji.js'
import type { Guild } from './transformers/guild.js'
import type { Integration } from './transformers/integration.js'
import type { Interaction } from './transformers/interaction.js'
import type { Invite } from './transformers/invite.js'
import type { Member, User } from './transformers/member.js'
import type { Message } from './transformers/message.js'
import type { PresenceUpdate } from './transformers/presence.js'
import type { Role } from './transformers/role.js'
import type { ScheduledEvent } from './transformers/scheduledEvent.js'
import type { Sticker } from './transformers/sticker.js'
import type { ThreadMember } from './transformers/threadMember.js'
import type { VoiceState } from './transformers/voiceState.js'
/**
* Create a bot object that will maintain the rest and gateway connection.
@@ -83,7 +55,13 @@ export function createBot(options: CreateBotOptions): Bot {
options.rest.token = options.token
options.gateway.intents = options.intents
const id = getBotIdFromToken(options.token)
const bot: Bot = {
id,
applicationId: id,
transformers: createTransformers({}),
handlers: createBotGatewayHandlers({}),
rest: createRestManager(options.rest),
gateway: createGatewayManager(options.gateway),
events: options.events ?? {},
@@ -118,6 +96,10 @@ export interface CreateBotOptions {
}
export interface Bot {
/** The id of the bot. */
id: bigint
/** The application id of the bot. This is usually the same as id but in the case of old bots can be different. */
applicationId: bigint
/** The rest manager. */
rest: RestManager
/** The gateway manager. */
@@ -126,6 +108,10 @@ export interface Bot {
events: Partial<EventHandlers>
/** A logger utility to make it easy to log nice and useful things in the bot code. */
logger: ReturnType<typeof createLogger>
/** The functions that should transform discord objects to discordeno shaped objects. */
transformers: Transformers
/** The handler functions that should handle incoming discord payloads from gateway and call an event. */
handlers: ReturnType<typeof createBotGatewayHandlers>
/** Start the bot connection to the gateway. */
start: () => Promise<void>
/** Shuts down all the bot connections to the gateway. */
@@ -133,69 +119,85 @@ export interface Bot {
}
export interface EventHandlers {
// Custom events here
dispatchRequirements: (payload: Camelize<DiscordGatewayPayload>, shardId: number) => unknown
raw: (payload: Camelize<DiscordGatewayPayload>, shardId: number) => unknown
// Gateway events below this
applicationCommandPermissionsUpdate: (payload: Camelize<DiscordGuildApplicationCommandPermissions>, shardId: number) => unknown
auditLogEntryCreate: (payload: Camelize<DiscordAuditLogEntry>, shardId: number) => unknown
autoModerationRuleCreate: (payload: Camelize<DiscordAutoModerationRule>, shardId: number) => unknown
autoModerationRuleUpdate: (payload: Camelize<DiscordAutoModerationRule>, shardId: number) => unknown
autoModerationRuleDelete: (payload: Camelize<DiscordAutoModerationRule>, shardId: number) => unknown
autoModerationActionExecution: (payload: Camelize<DiscordAutoModerationActionExecution>, shardId: number) => unknown
channelCreate: (payload: Camelize<DiscordChannel>, shardId: number) => unknown
channelUpdate: (payload: Camelize<DiscordChannel>, shardId: number) => unknown
channelDelete: (payload: Camelize<DiscordChannel>, shardId: number) => unknown
channelPinsUpdate: (payload: Camelize<DiscordChannelPinsUpdate>, shardId: number) => unknown
threadCreate: (payload: Camelize<DiscordChannel>, shardId: number) => unknown
threadUpdate: (payload: Camelize<DiscordChannel>, shardId: number) => unknown
threadDelete: (payload: Camelize<DiscordChannel>, shardId: number) => unknown
threadListSync: (payload: Camelize<DiscordThreadListSync>, shardId: number) => unknown
threadMemberUpdate: (payload: Camelize<DiscordThreadMemberUpdate>, shardId: number) => unknown
threadMembersUpdate: (payload: Camelize<DiscordThreadMembersUpdate>, shardId: number) => unknown
guildCreate: (payload: Camelize<DiscordGuild>, shardId: number) => unknown
guildUpdate: (payload: Camelize<DiscordGuild>, shardId: number) => unknown
guildDelete: (payload: Camelize<DiscordUnavailableGuild>, shardId: number) => unknown
guildBanAdd: (payload: Camelize<DiscordGuildBanAddRemove>, shardId: number) => unknown
guildBanRemove: (payload: Camelize<DiscordGuildBanAddRemove>, shardId: number) => unknown
guildEmojisUpdate: (payload: Camelize<DiscordGuildEmojisUpdate>, shardId: number) => unknown
guildStickersUpdate: (payload: Camelize<DiscordGuildStickersUpdate>, shardId: number) => unknown
guildIntegrationsUpdate: (payload: Camelize<DiscordIntegrationCreateUpdate>, shardId: number) => unknown
guildMemberAdd: (payload: Camelize<DiscordGuildMemberAdd>, shardId: number) => unknown
guildMemberRemove: (payload: Camelize<DiscordGuildMemberRemove>, shardId: number) => unknown
guildMemberUpdate: (payload: Camelize<DiscordGuildMemberUpdate>, shardId: number) => unknown
guildMembersChunk: (payload: Camelize<DiscordGuildMembersChunk>, shardId: number) => unknown
guildRoleCreate: (payload: Camelize<DiscordGuildRoleCreate>, shardId: number) => unknown
guildRoleUpdate: (payload: Camelize<DiscordGuildRoleUpdate>, shardId: number) => unknown
guildRoleDelete: (payload: Camelize<DiscordGuildRoleDelete>, shardId: number) => unknown
guildScheduledEventCreate: (payload: Camelize<DiscordScheduledEvent>, shardId: number) => unknown
guildScheduledEventUpdate: (payload: Camelize<DiscordScheduledEvent>, shardId: number) => unknown
guildScheduledEventDelete: (payload: Camelize<DiscordScheduledEvent>, shardId: number) => unknown
guildScheduledEventUserAdd: (payload: Camelize<DiscordScheduledEventUserAdd>, shardId: number) => unknown
guildScheduledEventUserRemove: (payload: Camelize<DiscordScheduledEventUserRemove>, shardId: number) => unknown
integrationCreate: (payload: Camelize<DiscordIntegrationCreateUpdate>, shardId: number) => unknown
integrationUpdate: (payload: Camelize<DiscordIntegrationCreateUpdate>, shardId: number) => unknown
integrationDelete: (payload: Camelize<DiscordIntegrationDelete>, shardId: number) => unknown
interactionCreate: (payload: Camelize<DiscordInteraction>, shardId: number) => unknown
inviteCreate: (payload: Camelize<DiscordInviteCreate>, shardId: number) => unknown
inviteDelete: (payload: Camelize<DiscordInviteDelete>, shardId: number) => unknown
messageCreate: (payload: Camelize<DiscordMessage>, shardId: number) => unknown
messageUpdate: (payload: Camelize<DiscordMessage>, shardId: number) => unknown
messageDelete: (payload: Camelize<DiscordMessageDelete>, shardId: number) => unknown
messageDeleteBulk: (payload: Camelize<DiscordMessageDeleteBulk>, shardId: number) => unknown
messageReactionAdd: (payload: Camelize<DiscordMessageReactionAdd>, shardId: number) => unknown
messageReactionRemove: (payload: Camelize<DiscordMessageReactionRemove>, shardId: number) => unknown
messageReactionRemoveAll: (payload: Camelize<DiscordMessageReactionRemoveAll>, shardId: number) => unknown
messageReactionRemoveEmoji: (payload: Camelize<DiscordMessageReactionRemoveEmoji>, shardId: number) => unknown
presenceUpdate: (payload: Camelize<DiscordPresenceUpdate>, shardId: number) => unknown
ready: (payload: Camelize<DiscordReady>, shardId: number) => unknown
stageInstanceCreate: (payload: Camelize<DiscordStageInstance>, shardId: number) => unknown
stageInstanceUpdate: (payload: Camelize<DiscordStageInstance>, shardId: number) => unknown
stageInstanceDelete: (payload: Camelize<DiscordStageInstance>, shardId: number) => unknown
typingStart: (payload: Camelize<DiscordTypingStart>, shardId: number) => unknown
userUpdate: (payload: Camelize<DiscordUser>, shardId: number) => unknown
voiceStateUpdate: (payload: Camelize<DiscordVoiceState>, shardId: number) => unknown
voiceServerUpdate: (payload: Camelize<DiscordVoiceServerUpdate>, shardId: number) => unknown
webhooksUpdate: (payload: Camelize<DiscordWebhookUpdate>, shardId: number) => unknown
debug: (text: string, ...args: any[]) => unknown
applicationCommandPermissionsUpdate: (command: ApplicationCommandPermission) => unknown
auditLogEntryCreate: (log: AuditLogEntry, guildId: bigint) => unknown
automodRuleCreate: (rule: AutoModerationRule) => unknown
automodRuleUpdate: (rule: AutoModerationRule) => unknown
automodRuleDelete: (rule: AutoModerationRule) => unknown
automodActionExecution: (payload: AutoModerationActionExecution) => unknown
threadCreate: (thread: Channel) => unknown
threadDelete: (thread: Channel) => unknown
threadMemberUpdate: (payload: { id: bigint; guildId: bigint; joinedAt: number; flags: number }) => unknown
threadMembersUpdate: (payload: { id: bigint; guildId: bigint; addedMembers?: ThreadMember[]; removedMemberIds?: bigint[] }) => unknown
threadUpdate: (thread: Channel) => unknown
scheduledEventCreate: (event: ScheduledEvent) => unknown
scheduledEventUpdate: (event: ScheduledEvent) => unknown
scheduledEventDelete: (event: ScheduledEvent) => unknown
/** Sent when a user has subscribed to a guild scheduled event. EXPERIMENTAL! */
scheduledEventUserAdd: (payload: { guildScheduledEventId: bigint; guildId: bigint; userId: bigint }) => unknown
/** Sent when a user has unsubscribed to a guild scheduled event. EXPERIMENTAL! */
scheduledEventUserRemove: (payload: { guildScheduledEventId: bigint; guildId: bigint; userId: bigint }) => unknown
ready: (
payload: {
shardId: number
v: number
user: User
guilds: bigint[]
sessionId: string
shard?: number[]
applicationId: bigint
},
rawPayload: DiscordReady,
) => unknown
interactionCreate: (interaction: Interaction) => unknown
integrationCreate: (integration: Integration) => unknown
integrationDelete: (payload: { id: bigint; guildId: bigint; applicationId?: bigint }) => unknown
integrationUpdate: (payload: { guildId: bigint }) => unknown
inviteCreate: (invite: Invite) => unknown
inviteDelete: (payload: { channelId: bigint; guildId?: bigint; code: string }) => unknown
guildMemberAdd: (member: Member, user: User) => unknown
guildMemberRemove: (user: User, guildId: bigint) => unknown
guildMemberUpdate: (member: Member, user: User) => unknown
guildStickersUpdate: (stickers: Sticker[]) => unknown
messageCreate: (message: Message) => unknown
messageDelete: (payload: { id: bigint; channelId: bigint; guildId?: bigint }, message?: Message) => unknown
messageDeleteBulk: (payload: { ids: bigint[]; channelId: bigint; guildId?: bigint }) => unknown
messageUpdate: (message: Message, oldMessage?: Message) => unknown
reactionAdd: (payload: {
userId: bigint
channelId: bigint
messageId: bigint
guildId?: bigint
member?: Member
user?: User
emoji: Emoji
}) => unknown
reactionRemove: (payload: { userId: bigint; channelId: bigint; messageId: bigint; guildId?: bigint; emoji: Emoji }) => unknown
reactionRemoveEmoji: (payload: { channelId: bigint; messageId: bigint; guildId?: bigint; emoji: Emoji }) => unknown
reactionRemoveAll: (payload: { channelId: bigint; messageId: bigint; guildId?: bigint }) => unknown
presenceUpdate: (presence: PresenceUpdate, oldPresence?: PresenceUpdate) => unknown
voiceServerUpdate: (payload: { token: string; endpoint?: string; guildId: bigint }) => unknown
voiceStateUpdate: (voiceState: VoiceState) => unknown
channelCreate: (channel: Channel) => unknown
dispatchRequirements: (data: DiscordGatewayPayload, shardId: number) => unknown
channelDelete: (channel: Channel) => unknown
channelPinsUpdate: (data: { guildId?: bigint; channelId: bigint; lastPinTimestamp?: number }) => unknown
channelUpdate: (channel: Channel) => unknown
stageInstanceCreate: (data: { id: bigint; guildId: bigint; channelId: bigint; topic: string }) => unknown
stageInstanceDelete: (data: { id: bigint; guildId: bigint; channelId: bigint; topic: string }) => unknown
stageInstanceUpdate: (data: { id: bigint; guildId: bigint; channelId: bigint; topic: string }) => unknown
guildEmojisUpdate: (payload: { guildId: bigint; emojis: Collection<bigint, DiscordEmoji> }) => unknown
guildBanAdd: (user: User, guildId: bigint) => unknown
guildBanRemove: (user: User, guildId: bigint) => unknown
guildCreate: (guild: Guild) => unknown
guildDelete: (id: bigint, shardId: number) => unknown
guildUpdate: (guild: Guild) => unknown
raw: (data: DiscordGatewayPayload, shardId: number) => unknown
roleCreate: (role: Role) => unknown
roleDelete: (payload: { guildId: bigint; roleId: bigint }) => unknown
roleUpdate: (role: Role) => unknown
webhooksUpdate: (payload: { channelId: bigint; guildId: bigint }) => unknown
botUpdate: (user: User) => unknown
typingStart: (payload: { guildId: bigint | undefined; channelId: bigint; userId: bigint; timestamp: number; member: Member | undefined }) => unknown
}

View File

@@ -0,0 +1,4 @@
export const SLASH_COMMANDS_NAME_REGEX = /^[-_\p{L}\p{N}\p{sc=Deva}\p{sc=Thai}]{1,32}$/u
export const CONTEXT_MENU_COMMANDS_NAME_REGEX = /^[\w-\s]{1,32}$/
export const CHANNEL_MENTION_REGEX = /<#[0-9]+>/g
export const DISCORD_SNOWFLAKE_REGEX = /^(?<id>\d{17,19})$/

View File

@@ -0,0 +1,72 @@
import * as handlers from './handlers/index.js'
import type { Bot, DiscordGatewayPayload, GatewayDispatchEventNames } from './index.js'
import type { BotGatewayHandlerOptions } from './typings.js'
export function createBotGatewayHandlers(
options: Partial<BotGatewayHandlerOptions>,
): Record<GatewayDispatchEventNames, (bot: Bot, data: DiscordGatewayPayload, shardId: number) => any> {
return {
APPLICATION_COMMAND_PERMISSIONS_UPDATE: options.APPLICATION_COMMAND_PERMISSIONS_UPDATE ?? handlers.handleApplicationCommandPermissionsUpdate,
AUTO_MODERATION_ACTION_EXECUTION: options.AUTO_MODERATION_ACTION_EXECUTION ?? handlers.handleAutoModerationActionExecution,
AUTO_MODERATION_RULE_CREATE: options.AUTO_MODERATION_RULE_CREATE ?? handlers.handleAutoModerationRuleCreate,
AUTO_MODERATION_RULE_DELETE: options.AUTO_MODERATION_RULE_DELETE ?? handlers.handleAutoModerationRuleDelete,
AUTO_MODERATION_RULE_UPDATE: options.AUTO_MODERATION_RULE_UPDATE ?? handlers.handleAutoModerationRuleUpdate,
CHANNEL_CREATE: options.CHANNEL_CREATE ?? handlers.handleChannelCreate,
CHANNEL_DELETE: options.CHANNEL_DELETE ?? handlers.handleChannelDelete,
CHANNEL_PINS_UPDATE: options.CHANNEL_PINS_UPDATE ?? handlers.handleChannelPinsUpdate,
CHANNEL_UPDATE: options.CHANNEL_UPDATE ?? handlers.handleChannelUpdate,
GUILD_AUDIT_LOG_ENTRY_CREATE: options.GUILD_AUDIT_LOG_ENTRY_CREATE ?? handlers.handleGuildAuditLogEntryCreate,
GUILD_BAN_ADD: options.GUILD_BAN_ADD ?? handlers.handleGuildBanAdd,
GUILD_BAN_REMOVE: options.GUILD_BAN_REMOVE ?? handlers.handleGuildBanRemove,
GUILD_CREATE: options.GUILD_CREATE ?? handlers.handleGuildCreate,
GUILD_DELETE: options.GUILD_DELETE ?? handlers.handleGuildDelete,
GUILD_EMOJIS_UPDATE: options.GUILD_EMOJIS_UPDATE ?? handlers.handleGuildEmojisUpdate,
GUILD_INTEGRATIONS_UPDATE: options.GUILD_INTEGRATIONS_UPDATE ?? handlers.handleGuildIntegrationsUpdate,
GUILD_MEMBER_ADD: options.GUILD_MEMBER_ADD ?? handlers.handleGuildMemberAdd,
GUILD_MEMBER_REMOVE: options.GUILD_MEMBER_REMOVE ?? handlers.handleGuildMemberRemove,
GUILD_MEMBER_UPDATE: options.GUILD_MEMBER_UPDATE ?? handlers.handleGuildMemberUpdate,
GUILD_MEMBERS_CHUNK: options.GUILD_MEMBERS_CHUNK ?? handlers.handleGuildMembersChunk,
GUILD_ROLE_CREATE: options.GUILD_ROLE_CREATE ?? handlers.handleGuildRoleCreate,
GUILD_ROLE_DELETE: options.GUILD_ROLE_DELETE ?? handlers.handleGuildRoleDelete,
GUILD_ROLE_UPDATE: options.GUILD_ROLE_UPDATE ?? handlers.handleGuildRoleUpdate,
GUILD_SCHEDULED_EVENT_CREATE: options.GUILD_SCHEDULED_EVENT_CREATE ?? handlers.handleGuildScheduledEventCreate,
GUILD_SCHEDULED_EVENT_DELETE: options.GUILD_SCHEDULED_EVENT_DELETE ?? handlers.handleGuildScheduledEventDelete,
GUILD_SCHEDULED_EVENT_UPDATE: options.GUILD_SCHEDULED_EVENT_UPDATE ?? handlers.handleGuildScheduledEventUpdate,
GUILD_SCHEDULED_EVENT_USER_ADD: options.GUILD_SCHEDULED_EVENT_USER_ADD ?? handlers.handleGuildScheduledEventUserAdd,
GUILD_SCHEDULED_EVENT_USER_REMOVE: options.GUILD_SCHEDULED_EVENT_USER_REMOVE ?? handlers.handleGuildScheduledEventUserRemove,
GUILD_STICKERS_UPDATE: options.GUILD_STICKERS_UPDATE ?? handlers.handleGuildStickersUpdate,
GUILD_UPDATE: options.GUILD_UPDATE ?? handlers.handleGuildUpdate,
INTERACTION_CREATE: options.INTERACTION_CREATE ?? handlers.handleInteractionCreate,
INTEGRATION_CREATE: options.INTEGRATION_CREATE ?? handlers.handleIntegrationCreate,
INTEGRATION_UPDATE: options.INTEGRATION_UPDATE ?? handlers.handleIntegrationUpdate,
INTEGRATION_DELETE: options.INTEGRATION_DELETE ?? handlers.handleIntegrationDelete,
INVITE_CREATE: options.INVITE_CREATE ?? handlers.handleInviteCreate,
INVITE_DELETE: options.INVITE_DELETE ?? handlers.handleInviteCreate,
MESSAGE_CREATE: options.MESSAGE_CREATE ?? handlers.handleMessageCreate,
MESSAGE_DELETE_BULK: options.MESSAGE_DELETE_BULK ?? handlers.handleMessageDeleteBulk,
MESSAGE_DELETE: options.MESSAGE_DELETE ?? handlers.handleMessageDelete,
MESSAGE_REACTION_ADD: options.MESSAGE_REACTION_ADD ?? handlers.handleMessageReactionAdd,
MESSAGE_REACTION_REMOVE_ALL: options.MESSAGE_REACTION_REMOVE_ALL ?? handlers.handleMessageReactionRemoveAll,
MESSAGE_REACTION_REMOVE_EMOJI: options.MESSAGE_REACTION_REMOVE_EMOJI ?? handlers.handleMessageReactionRemoveEmoji,
MESSAGE_REACTION_REMOVE: options.MESSAGE_REACTION_REMOVE ?? handlers.handleMessageReactionRemove,
MESSAGE_UPDATE: options.MESSAGE_UPDATE ?? handlers.handleMessageUpdate,
PRESENCE_UPDATE: options.PRESENCE_UPDATE ?? handlers.handlePresenceUpdate,
READY: options.READY ?? handlers.handleReady,
STAGE_INSTANCE_CREATE: options.STAGE_INSTANCE_CREATE ?? handlers.handleStageInstanceCreate,
STAGE_INSTANCE_DELETE: options.STAGE_INSTANCE_DELETE ?? handlers.handleStageInstanceDelete,
STAGE_INSTANCE_UPDATE: options.STAGE_INSTANCE_UPDATE ?? handlers.handleStageInstanceUpdate,
THREAD_CREATE: options.THREAD_CREATE ?? handlers.handleThreadCreate,
THREAD_DELETE: options.THREAD_DELETE ?? handlers.handleThreadDelete,
THREAD_UPDATE: options.THREAD_UPDATE ?? handlers.handleThreadUpdate,
THREAD_LIST_SYNC: options.THREAD_LIST_SYNC ?? handlers.handleThreadListSync,
THREAD_MEMBER_UPDATE: options.THREAD_MEMBERS_UPDATE ?? handlers.handleThreadMembersUpdate,
THREAD_MEMBERS_UPDATE: options.THREAD_MEMBERS_UPDATE ?? handlers.handleThreadMembersUpdate,
TYPING_START: options.TYPING_START ?? handlers.handleTypingStart,
USER_UPDATE: options.USER_UPDATE ?? handlers.handleUserUpdate,
VOICE_SERVER_UPDATE: options.VOICE_SERVER_UPDATE ?? handlers.handleVoiceServerUpdate,
VOICE_STATE_UPDATE: options.VOICE_STATE_UPDATE ?? handlers.handleVoiceStateUpdate,
WEBHOOKS_UPDATE: options.WEBHOOKS_UPDATE ?? handlers.handleWebhooksUpdate,
}
}
export interface GatewayHandlers extends ReturnType<typeof createBotGatewayHandlers> {}

View File

@@ -0,0 +1,10 @@
import type { DiscordChannel, DiscordGatewayPayload } from '@discordeno/bot'
import type { Bot } from '../../index.js'
export async function handleChannelCreate(bot: Bot, payload: DiscordGatewayPayload, shardId: number): Promise<void> {
const channel = bot.transformers.channel(bot, {
channel: payload.d as DiscordChannel,
})
bot.events.channelCreate?.(channel)
}

View File

@@ -0,0 +1,14 @@
import type { DiscordChannel, DiscordGatewayPayload } from '@discordeno/types'
import type { Bot } from '../../bot.js'
export async function handleChannelDelete(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
const payload = data.d as DiscordChannel
if (!payload.guild_id) return
bot.events.channelDelete?.(
bot.transformers.channel(bot, {
channel: payload,
guildId: payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined,
}),
)
}

View File

@@ -0,0 +1,12 @@
import type { DiscordChannelPinsUpdate, DiscordGatewayPayload } from '@discordeno/types'
import type { Bot } from '../../bot.js'
export async function handleChannelPinsUpdate(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
const payload = data.d as DiscordChannelPinsUpdate
bot.events.channelPinsUpdate?.({
guildId: payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined,
channelId: bot.transformers.snowflake(payload.channel_id),
lastPinTimestamp: payload.last_pin_timestamp ? Date.parse(payload.last_pin_timestamp) : undefined,
})
}

View File

@@ -0,0 +1,9 @@
import type { DiscordChannel, DiscordGatewayPayload } from '@discordeno/types'
import type { Bot } from '../../bot.js'
export async function handleChannelUpdate(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
const payload = data.d as DiscordChannel
const channel = bot.transformers.channel(bot, { channel: payload })
bot.events.channelUpdate?.(channel)
}

View File

@@ -0,0 +1,13 @@
import type { DiscordGatewayPayload, DiscordStageInstance } from '@discordeno/types'
import type { Bot } from '../../bot.js'
export async function handleStageInstanceCreate(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
const payload = data.d as DiscordStageInstance
bot.events.stageInstanceCreate?.({
id: bot.transformers.snowflake(payload.id),
guildId: bot.transformers.snowflake(payload.guild_id),
channelId: bot.transformers.snowflake(payload.channel_id),
topic: payload.topic,
})
}

View File

@@ -0,0 +1,13 @@
import type { DiscordGatewayPayload, DiscordStageInstance } from '@discordeno/types'
import type { Bot } from '../../bot.js'
export async function handleStageInstanceDelete(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
const payload = data.d as DiscordStageInstance
bot.events.stageInstanceDelete?.({
id: bot.transformers.snowflake(payload.id),
guildId: bot.transformers.snowflake(payload.guild_id),
channelId: bot.transformers.snowflake(payload.channel_id),
topic: payload.topic,
})
}

View File

@@ -0,0 +1,13 @@
import type { DiscordGatewayPayload, DiscordStageInstance } from '@discordeno/types'
import type { Bot } from '../../bot.js'
export async function handleStageInstanceUpdate(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
const payload = data.d as DiscordStageInstance
bot.events.stageInstanceUpdate?.({
id: bot.transformers.snowflake(payload.id),
guildId: bot.transformers.snowflake(payload.guild_id),
channelId: bot.transformers.snowflake(payload.channel_id),
topic: payload.topic,
})
}

View File

@@ -0,0 +1,8 @@
import type { DiscordChannel, DiscordGatewayPayload } from '@discordeno/types'
import type { Bot } from '../../index.js'
export async function handleThreadCreate(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
const payload = data.d as DiscordChannel
bot.events.threadCreate?.(bot.transformers.channel(bot, { channel: payload }))
}

View File

@@ -0,0 +1,8 @@
import type { DiscordChannel, DiscordGatewayPayload } from '@discordeno/types'
import type { Bot } from '../../index.js'
export async function handleThreadDelete(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
const payload = data.d as DiscordChannel
bot.events.threadDelete?.(bot.transformers.channel(bot, { channel: payload }))
}

View File

@@ -0,0 +1,19 @@
import type { DiscordGatewayPayload, DiscordThreadListSync } from '@discordeno/types'
import type { Bot } from '../../index.js'
export async function handleThreadListSync(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
const payload = data.d as DiscordThreadListSync
const guildId = bot.transformers.snowflake(payload.guild_id)
return {
guildId,
channelIds: payload.channel_ids?.map((id) => bot.transformers.snowflake(id)),
threads: payload.threads.map((thread) => bot.transformers.channel(bot, { channel: thread, guildId })),
members: payload.members.map((member) => ({
id: member.id ? bot.transformers.snowflake(member.id) : undefined,
userId: member.user_id ? bot.transformers.snowflake(member.user_id) : undefined,
joinTimestamp: Date.parse(member.join_timestamp),
})),
}
}

View File

@@ -0,0 +1,13 @@
import type { DiscordGatewayPayload, DiscordThreadMembersUpdate } from '@discordeno/types'
import type { Bot } from '../../index.js'
export async function handleThreadMembersUpdate(bot: Bot, data: DiscordGatewayPayload, shardId: number): Promise<void> {
const payload = data.d as DiscordThreadMembersUpdate
bot.events.threadMembersUpdate?.({
id: bot.transformers.snowflake(payload.id),
guildId: bot.transformers.snowflake(payload.guild_id),
addedMembers: payload.added_members?.map((member) => bot.transformers.threadMember?.(bot, member)),
removedMemberIds: payload.removed_member_ids?.map((id) => bot.transformers.snowflake(id)),
})
}

View File

@@ -0,0 +1,13 @@
import type { DiscordGatewayPayload, DiscordThreadMemberUpdate } from '@discordeno/types'
import type { Bot } from '../../index.js'
export async function handleThreadMemberUpdate(bot: Bot, data: DiscordGatewayPayload, shardId: number): Promise<void> {
const payload = data.d as DiscordThreadMemberUpdate
bot.events.threadMemberUpdate?.({
id: bot.transformers.snowflake(payload.id),
guildId: bot.transformers.snowflake(payload.guild_id),
joinedAt: Date.parse(payload.joined_at),
flags: payload.flags,
})
}

View File

@@ -0,0 +1,8 @@
import type { DiscordChannel, DiscordGatewayPayload } from '@discordeno/types'
import type { Bot } from '../../index.js'
export async function handleThreadUpdate(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
const payload = data.d as DiscordChannel
bot.events.threadUpdate?.(bot.transformers.channel(bot, { channel: payload }))
}

View File

@@ -0,0 +1,12 @@
export * from "./CHANNEL_CREATE.js";
export * from "./CHANNEL_DELETE.js";
export * from "./CHANNEL_PINS_UPDATE.js";
export * from "./CHANNEL_UPDATE.js";
export * from "./STAGE_INSTANCE_CREATE.js";
export * from "./STAGE_INSTANCE_DELETE.js";
export * from "./STAGE_INSTANCE_UPDATE.js";
export * from "./THREAD_CREATE.js";
export * from "./THREAD_DELETE.js";
export * from "./THREAD_LIST_SYNC.js";
export * from "./THREAD_MEMBERS_UPDATE.js";
export * from "./THREAD_UPDATE.js";

View File

@@ -0,0 +1,12 @@
import type { DiscordGatewayPayload, DiscordGuildEmojisUpdate } from '@discordeno/types'
import { Collection } from '@discordeno/utils'
import type { Bot } from '../../bot.js'
export async function handleGuildEmojisUpdate(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
const payload = data.d as DiscordGuildEmojisUpdate
bot.events.guildEmojisUpdate?.({
guildId: bot.transformers.snowflake(payload.guild_id),
emojis: new Collection(payload.emojis.map((emoji) => [bot.transformers.snowflake(emoji.id!), emoji])),
})
}

View File

@@ -0,0 +1 @@
export * from "./GUILD_EMOJIS_UPDATE.js";

View File

@@ -0,0 +1,8 @@
import type { DiscordAuditLogEntry, DiscordGatewayPayload } from '@discordeno/types'
import type { Bot } from '../../bot.js'
export async function handleGuildAuditLogEntryCreate(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
// TODO: better type here
const payload = data.d as DiscordAuditLogEntry & { guild_id: string }
bot.events.auditLogEntryCreate?.(bot.transformers.auditLogEntry(bot, payload), bot.transformers.snowflake(payload.guild_id))
}

View File

@@ -0,0 +1,7 @@
import type { DiscordGatewayPayload, DiscordGuildBanAddRemove } from '@discordeno/types'
import type { Bot } from '../../bot.js'
export async function handleGuildBanAdd(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
const payload = data.d as DiscordGuildBanAddRemove
bot.events.guildBanAdd?.(bot.transformers.user(bot, payload.user), bot.transformers.snowflake(payload.guild_id))
}

View File

@@ -0,0 +1,8 @@
import type { DiscordGatewayPayload, DiscordGuildBanAddRemove } from '@discordeno/types'
import type { Bot } from '../../bot.js'
export async function handleGuildBanRemove(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
const payload = data.d as DiscordGuildBanAddRemove
await bot.events.guildBanRemove?.(bot.transformers.user(bot, payload.user), bot.transformers.snowflake(payload.guild_id))
}

View File

@@ -0,0 +1,7 @@
import type { DiscordGatewayPayload, DiscordGuild } from '@discordeno/types'
import type { Bot } from '../../bot.js'
export async function handleGuildCreate(bot: Bot, data: DiscordGatewayPayload, shardId: number): Promise<void> {
const payload = data.d as DiscordGuild
bot.events.guildCreate?.(bot.transformers.guild(bot, { guild: payload, shardId }))
}

View File

@@ -0,0 +1,7 @@
import type { DiscordGatewayPayload, DiscordUnavailableGuild } from '@discordeno/types'
import type { Bot } from '../../bot.js'
export async function handleGuildDelete(bot: Bot, data: DiscordGatewayPayload, shardId: number): Promise<void> {
const payload = data.d as DiscordUnavailableGuild
bot.events.guildDelete?.(bot.transformers.snowflake(payload.id), shardId)
}

View File

@@ -0,0 +1,10 @@
import type { DiscordGatewayPayload, DiscordGuildIntegrationsUpdate } from '@discordeno/types'
import type { Bot } from '../../bot.js'
export async function handleGuildIntegrationsUpdate(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
const payload = data.d as DiscordGuildIntegrationsUpdate
bot.events.integrationUpdate?.({
guildId: bot.transformers.snowflake(payload.guild_id),
})
}

View File

@@ -0,0 +1,12 @@
import type { Bot, DiscordGatewayPayload, DiscordGuildStickersUpdate } from '../..'
export async function handleGuildStickersUpdate(bot: Bot, data: DiscordGatewayPayload, shardId: number): Promise<void> {
const payload = data.d as DiscordGuildStickersUpdate
bot.events.guildStickersUpdate?.(
payload.stickers.map((sticker) => {
sticker.guild_id = payload.guild_id
return bot.transformers.sticker(bot, sticker)
})
)
}

View File

@@ -0,0 +1,8 @@
import type { DiscordGatewayPayload, DiscordGuild } from '@discordeno/types'
import type { Bot } from '../../bot.js'
export async function handleGuildUpdate(bot: Bot, data: DiscordGatewayPayload, shardId: number): Promise<void> {
const payload = data.d as DiscordGuild
bot.events.guildUpdate?.(bot.transformers.guild(bot, { guild: payload, shardId }))
}

View File

@@ -0,0 +1,8 @@
import type { DiscordAutoModerationActionExecution, DiscordGatewayPayload } from '@discordeno/types'
import type { Bot } from '../../../bot.js'
/** Requires the MANAGE_GUILD permission. */
export async function handleAutoModerationActionExecution(bot: Bot, data: DiscordGatewayPayload, shardId: number): Promise<void> {
const payload = data.d as DiscordAutoModerationActionExecution
bot.events.automodActionExecution?.(bot.transformers.automodActionExecution(bot, payload))
}

View File

@@ -0,0 +1,8 @@
import type { DiscordAutoModerationRule, DiscordGatewayPayload } from '@discordeno/types'
import type { Bot } from '../../../bot.js'
/** Requires the MANAGE_GUILD permission. */
export async function handleAutoModerationRuleCreate(bot: Bot, data: DiscordGatewayPayload, shardId: number): Promise<void> {
const payload = data.d as DiscordAutoModerationRule
bot.events.automodRuleCreate?.(bot.transformers.automodRule(bot, payload))
}

View File

@@ -0,0 +1,8 @@
import type { DiscordAutoModerationRule, DiscordGatewayPayload } from '@discordeno/types'
import type { Bot } from '../../../bot.js'
/** Requires the MANAGE_GUILD permission. */
export async function handleAutoModerationRuleDelete(bot: Bot, data: DiscordGatewayPayload, shardId: number): Promise<void> {
const payload = data.d as DiscordAutoModerationRule
bot.events.automodRuleDelete?.(bot.transformers.automodRule(bot, payload))
}

View File

@@ -0,0 +1,8 @@
import type { DiscordAutoModerationRule, DiscordGatewayPayload } from '@discordeno/types'
import type { Bot } from '../../../bot.js'
/** Requires the MANAGE_GUILD permission. */
export async function handleAutoModerationRuleUpdate(bot: Bot, data: DiscordGatewayPayload, shardId: number): Promise<void> {
const payload = data.d as DiscordAutoModerationRule
bot.events.automodRuleUpdate?.(bot.transformers.automodRule(bot, payload))
}

View File

@@ -0,0 +1,4 @@
export * from './AUTO_MODERATION_ACTION_EXECUTION.js'
export * from './AUTO_MODERATION_RULE_CREATE.js'
export * from './AUTO_MODERATION_RULE_DELETE.js'
export * from './AUTO_MODERATION_RULE_UPDATE.js'

View File

@@ -0,0 +1,11 @@
export * from "./automod/index.js";
export * from "./scheduledEvents/index.js";
export * from "./GUILD_AUDIT_LOG_ENTRY_CREATE.js";
export * from "./GUILD_BAN_ADD.js";
export * from "./GUILD_BAN_REMOVE.js";
export * from "./GUILD_CREATE.js";
export * from "./GUILD_DELETE.js";
export * from "./GUILD_INTEGRATIONS_UPDATE.js";
export * from "./GUILD_STICKERS_UPDATE.js";
export * from "./GUILD_UPDATE.js";

View File

@@ -0,0 +1,7 @@
import type { DiscordGatewayPayload, DiscordScheduledEvent } from '@discordeno/types'
import type { Bot } from '../../../bot.js'
export async function handleGuildScheduledEventCreate(bot: Bot, data: DiscordGatewayPayload, shardId: number): Promise<void> {
const payload = data.d as DiscordScheduledEvent
bot.events.scheduledEventCreate?.(bot.transformers.scheduledEvent(bot, payload))
}

View File

@@ -0,0 +1,7 @@
import type { DiscordGatewayPayload, DiscordScheduledEvent } from '@discordeno/types'
import type { Bot } from '../../../bot.js'
export async function handleGuildScheduledEventDelete(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
const payload = data.d as DiscordScheduledEvent
bot.events.scheduledEventDelete?.(bot.transformers.scheduledEvent(bot, payload))
}

View File

@@ -0,0 +1,7 @@
import type { DiscordGatewayPayload, DiscordScheduledEvent } from '@discordeno/types'
import type { Bot } from '../../../bot.js'
export async function handleGuildScheduledEventUpdate(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
const payload = data.d as DiscordScheduledEvent
bot.events.scheduledEventUpdate?.(bot.transformers.scheduledEvent(bot, payload))
}

View File

@@ -0,0 +1,12 @@
import type { DiscordGatewayPayload, DiscordScheduledEventUserAdd } from '@discordeno/types'
import type { Bot } from '../../../bot.js'
export async function handleGuildScheduledEventUserAdd(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
const payload = data.d as DiscordScheduledEventUserAdd
bot.events.scheduledEventUserAdd?.({
guildScheduledEventId: bot.transformers.snowflake(payload.guild_scheduled_event_id),
userId: bot.transformers.snowflake(payload.user_id),
guildId: bot.transformers.snowflake(payload.guild_id),
})
}

View File

@@ -0,0 +1,12 @@
import type { DiscordGatewayPayload, DiscordScheduledEventUserRemove } from '@discordeno/types'
import type { Bot } from '../../../bot.js'
export async function handleGuildScheduledEventUserRemove(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
const payload = data.d as DiscordScheduledEventUserRemove
bot.events.scheduledEventUserRemove?.({
guildScheduledEventId: bot.transformers.snowflake(payload.guild_scheduled_event_id),
userId: bot.transformers.snowflake(payload.user_id),
guildId: bot.transformers.snowflake(payload.guild_id),
})
}

View File

@@ -0,0 +1,5 @@
export * from "./GUILD_SCHEDULED_EVENT_CREATE.js";
export * from "./GUILD_SCHEDULED_EVENT_DELETE.js";
export * from "./GUILD_SCHEDULED_EVENT_UPDATE.js";
export * from "./GUILD_SCHEDULED_EVENT_USER_ADD.js";
export * from "./GUILD_SCHEDULED_EVENT_USER_REMOVE.js";

View File

@@ -0,0 +1,12 @@
export * from './channels/index.js'
export * from './emojis/index.js'
export * from './guilds/index.js'
export * from './integrations/index.js'
export * from './interactions/index.js'
export * from './invites/index.js'
export * from './members/index.js'
export * from './messages/index.js'
export * from './misc/index.js'
export * from './roles/index.js'
export * from './voice/index.js'
export * from './webhooks/index.js'

View File

@@ -0,0 +1,6 @@
import type { DiscordGatewayPayload, DiscordIntegrationCreateUpdate } from '@discordeno/types'
import type { Bot } from '../../index.js'
export async function handleIntegrationCreate(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
bot.events.integrationCreate?.(bot.transformers.integration(bot, data.d as DiscordIntegrationCreateUpdate))
}

View File

@@ -0,0 +1,12 @@
import type { DiscordGatewayPayload, DiscordIntegrationDelete } from '@discordeno/types'
import type { Bot } from '../../index.js'
export async function handleIntegrationDelete(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
const payload = data.d as DiscordIntegrationDelete
bot.events.integrationDelete?.({
id: bot.transformers.snowflake(payload.id),
guildId: bot.transformers.snowflake(payload.guild_id),
applicationId: payload.application_id ? bot.transformers.snowflake(payload.application_id) : undefined,
})
}

View File

@@ -0,0 +1,6 @@
import type { DiscordGatewayPayload, DiscordIntegrationCreateUpdate } from '@discordeno/types'
import type { Bot } from '../../index.js'
export async function handleIntegrationUpdate(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
bot.events.integrationUpdate?.(bot.transformers.integration(bot, data.d as DiscordIntegrationCreateUpdate))
}

View File

@@ -0,0 +1,3 @@
export * from "./INTEGRATION_CREATE.js";
export * from "./INTEGRATION_DELETE.js";
export * from "./INTEGRATION_UPDATE.js";

View File

@@ -0,0 +1,6 @@
import type { Bot, DiscordGatewayPayload, DiscordGuildApplicationCommandPermissions } from "../..";
export async function handleApplicationCommandPermissionsUpdate(bot: Bot, data: DiscordGatewayPayload, shardId: number): Promise<void> {
const payload = data.d as DiscordGuildApplicationCommandPermissions
bot.events.applicationCommandPermissionsUpdate?.(bot.transformers.applicationCommandPermission(bot, payload))
}

View File

@@ -0,0 +1,6 @@
import type { DiscordGatewayPayload, DiscordInteraction } from '@discordeno/types'
import type { Bot } from '../../index.js'
export async function handleInteractionCreate(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
bot.events.interactionCreate?.(bot.transformers.interaction(bot, data.d as DiscordInteraction))
}

View File

@@ -0,0 +1,2 @@
export * from './APPLICATION_COMMAND_PERMISSIONS_UPDATE.js'
export * from './INTERACTION_CREATE.js'

View File

@@ -0,0 +1,6 @@
import type { DiscordGatewayPayload, DiscordInviteCreate } from '@discordeno/types'
import type { Bot } from '../../index.js'
export async function handleInviteCreate(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
bot.events.inviteCreate?.(bot.transformers.invite(bot, data.d as DiscordInviteCreate))
}

View File

@@ -0,0 +1,15 @@
import type { DiscordGatewayPayload, DiscordInviteDelete } from '@discordeno/types'
import type { Bot } from '../../index.js'
export async function handleInviteDelete(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
const payload = data.d as DiscordInviteDelete
bot.events.inviteDelete?.({
/** The channel of the invite */
channelId: bot.transformers.snowflake(payload.channel_id),
/** The guild of the invite */
guildId: payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined,
/** The unique invite code */
code: payload.code,
})
}

View File

@@ -0,0 +1,2 @@
export * from "./INVITE_CREATE.js";
export * from "./INVITE_DELETE.js";

View File

@@ -0,0 +1,29 @@
import type { DiscordGatewayPayload, DiscordGuildMembersChunk } from '@discordeno/types'
import { PresenceStatus } from '@discordeno/types'
import type { Bot } from '../../index.js'
export async function handleGuildMembersChunk(bot: Bot, data: DiscordGatewayPayload): Promise<any> {
const payload = data.d as DiscordGuildMembersChunk
const guildId = bot.transformers.snowflake(payload.guild_id)
return {
guildId,
members: payload.members.map((m) => bot.transformers.member(bot, m, guildId, bot.transformers.snowflake(m.user.id))),
chunkIndex: payload.chunk_index,
chunkCount: payload.chunk_count,
notFound: payload.not_found?.map((id) => bot.transformers.snowflake(id)),
presences: payload.presences?.map((presence) => ({
user: bot.transformers.user(bot, presence.user),
guildId,
status: PresenceStatus[presence.status],
activities: presence.activities.map((activity) => bot.transformers.activity(bot, activity)),
clientStatus: {
desktop: presence.client_status.desktop,
mobile: presence.client_status.mobile,
web: presence.client_status.web,
},
})),
nonce: payload.nonce,
}
}

View File

@@ -0,0 +1,10 @@
import type { DiscordGatewayPayload, DiscordGuildMemberAdd } from '@discordeno/types'
import type { Bot } from '../../index.js'
export async function handleGuildMemberAdd(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
const payload = data.d as DiscordGuildMemberAdd
const guildId = bot.transformers.snowflake(payload.guild_id)
const user = bot.transformers.user(bot, payload.user)
const member = bot.transformers.member(bot, payload, guildId, user.id)
bot.events.guildMemberAdd?.(member, user)
}

View File

@@ -0,0 +1,10 @@
import type { DiscordGatewayPayload, DiscordGuildMemberRemove } from '@discordeno/types'
import type { Bot } from '../../index.js'
export async function handleGuildMemberRemove(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
const payload = data.d as DiscordGuildMemberRemove
const guildId = bot.transformers.snowflake(payload.guild_id)
const user = bot.transformers.user(bot, payload.user)
bot.events.guildMemberRemove?.(user, guildId)
}

View File

@@ -0,0 +1,9 @@
import type { DiscordGatewayPayload, DiscordGuildMemberUpdate } from '@discordeno/types'
import type { Bot } from '../../index.js'
export async function handleGuildMemberUpdate(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
const payload = data.d as DiscordGuildMemberUpdate
const user = bot.transformers.user(bot, payload.user)
bot.events.guildMemberUpdate?.(bot.transformers.member(bot, payload, bot.transformers.snowflake(payload.guild_id), user.id), user)
}

View File

@@ -0,0 +1,4 @@
export * from "./GUILD_MEMBER_ADD.js";
export * from "./GUILD_MEMBER_REMOVE.js";
export * from "./GUILD_MEMBER_UPDATE.js";
export * from "./GUILD_MEMBERS_CHUNK.js";

View File

@@ -0,0 +1,8 @@
import type { DiscordGatewayPayload, DiscordMessage } from '@discordeno/types'
import type { Bot } from '../../index.js'
export async function handleMessageCreate(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
const payload = data.d as DiscordMessage
bot.events.messageCreate?.(bot.transformers.message(bot, payload))
}

View File

@@ -0,0 +1,12 @@
import type { DiscordGatewayPayload, DiscordMessageDelete } from '@discordeno/types'
import type { Bot } from '../../index.js'
export async function handleMessageDelete(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
const payload = data.d as DiscordMessageDelete
bot.events.messageDelete?.({
id: bot.transformers.snowflake(payload.id),
channelId: bot.transformers.snowflake(payload.channel_id),
guildId: payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined,
})
}

View File

@@ -0,0 +1,15 @@
import type { DiscordGatewayPayload, DiscordMessageDeleteBulk } from '@discordeno/types'
import type { Bot } from '../../index.js'
export async function handleMessageDeleteBulk(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
const payload = data.d as DiscordMessageDeleteBulk
const channelId = bot.transformers.snowflake(payload.channel_id)
const guildId = payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined
bot.events.messageDeleteBulk?.({
ids: payload.ids.map((id) => bot.transformers.snowflake(id)),
channelId,
guildId,
})
}

View File

@@ -0,0 +1,18 @@
import type { DiscordGatewayPayload, DiscordMessageReactionAdd } from '@discordeno/types'
import type { Bot } from '../../index.js'
export async function handleMessageReactionAdd(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
const payload = data.d as DiscordMessageReactionAdd
const guildId = payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined
const userId = bot.transformers.snowflake(payload.user_id)
bot.events.reactionAdd?.({
userId,
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, userId) : undefined,
user: payload.member ? bot.transformers.user(bot, payload.member.user) : undefined,
emoji: bot.transformers.emoji(bot, payload.emoji),
})
}

View File

@@ -0,0 +1,14 @@
import type { DiscordGatewayPayload, DiscordMessageReactionRemove } from '@discordeno/types'
import type { Bot } from '../../index.js'
export async function handleMessageReactionRemove(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
const payload = data.d as DiscordMessageReactionRemove
bot.events.reactionRemove?.({
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),
})
}

View File

@@ -0,0 +1,12 @@
import type { DiscordGatewayPayload, DiscordMessageReactionRemoveAll } from '@discordeno/types'
import type { Bot } from '../../index.js'
export async function handleMessageReactionRemoveAll(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
const payload = data.d as DiscordMessageReactionRemoveAll
bot.events.reactionRemoveAll?.({
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,
})
}

View File

@@ -0,0 +1,13 @@
import type { DiscordGatewayPayload, DiscordMessageReactionRemoveEmoji } from '@discordeno/types'
import type { Bot } from '../../index.js'
export async function handleMessageReactionRemoveEmoji(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
const payload = data.d as DiscordMessageReactionRemoveEmoji
bot.events.reactionRemoveEmoji?.({
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),
})
}

View File

@@ -0,0 +1,9 @@
import type { DiscordGatewayPayload, DiscordMessage } from '@discordeno/types'
import type { Bot } from '../../index.js'
export async function handleMessageUpdate(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
const payload = data.d as DiscordMessage
if (!payload.edited_timestamp) return
bot.events.messageUpdate?.(bot.transformers.message(bot, payload))
}

View File

@@ -0,0 +1,8 @@
export * from "./MESSAGE_CREATE.js";
export * from "./MESSAGE_DELETE_BULK.js";
export * from "./MESSAGE_DELETE.js";
export * from "./MESSAGE_REACTION_ADD.js";
export * from "./MESSAGE_REACTION_REMOVE_ALL.js";
export * from "./MESSAGE_REACTION_REMOVE_EMOJI.js";
export * from "./MESSAGE_REACTION_REMOVE.js";
export * from "./MESSAGE_UPDATE.js";

View File

@@ -0,0 +1,6 @@
import type { DiscordGatewayPayload, DiscordPresenceUpdate } from '@discordeno/types'
import type { Bot } from '../../index.js'
export async function handlePresenceUpdate(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
bot.events.presenceUpdate?.(bot.transformers.presence(bot, data.d as DiscordPresenceUpdate))
}

View File

@@ -0,0 +1,22 @@
import type { DiscordGatewayPayload, DiscordReady } from '@discordeno/types'
import type { Bot } from '../../index.js'
export async function handleReady(bot: Bot, data: DiscordGatewayPayload, shardId: number): Promise<void> {
const payload = data.d as DiscordReady
// Triggered on each shard
bot.events.ready?.(
{
shardId,
v: payload.v,
user: bot.transformers.user(bot, payload.user),
guilds: payload.guilds.map((p) => bot.transformers.snowflake(p.id)),
sessionId: payload.session_id,
shard: payload.shard,
applicationId: bot.transformers.snowflake(payload.application.id),
},
payload,
)
bot.id = bot.transformers.snowflake(payload.user.id)
bot.applicationId = bot.transformers.snowflake(payload.application.id)
}

View File

@@ -0,0 +1,17 @@
import type { DiscordGatewayPayload, DiscordTypingStart } from '@discordeno/types'
import type { Bot } from '../../index.js'
export async function handleTypingStart(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
const payload = data.d as DiscordTypingStart
const guildId = payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined
const userId = bot.transformers.snowflake(payload.user_id)
bot.events.typingStart?.({
guildId,
channelId: bot.transformers.snowflake(payload.channel_id),
userId,
timestamp: payload.timestamp,
member: payload.member && guildId ? bot.transformers.member(bot, payload.member, guildId, userId) : undefined,
})
}

View File

@@ -0,0 +1,7 @@
import type { DiscordGatewayPayload, DiscordUser } from '@discordeno/types'
import type { Bot } from '../../index.js'
export async function handleUserUpdate(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
const payload = data.d as DiscordUser
bot.events.botUpdate?.(bot.transformers.user(bot, payload))
}

View File

@@ -0,0 +1,4 @@
export * from "./PRESENCE_UPDATE.js";
export * from "./READY.js";
export * from "./TYPING_START.js";
export * from "./USER_UPDATE.js";

View File

@@ -0,0 +1,12 @@
import type { DiscordGatewayPayload, DiscordGuildRoleCreate } from '@discordeno/types'
import type { Bot } from '../../index.js'
export async function handleGuildRoleCreate(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
const payload = data.d as DiscordGuildRoleCreate
bot.events.roleCreate?.(
bot.transformers.role(bot, {
role: payload.role,
guildId: bot.transformers.snowflake(payload.guild_id),
}),
)
}

View File

@@ -0,0 +1,10 @@
import type { DiscordGatewayPayload, DiscordGuildRoleDelete } from '@discordeno/types'
import type { Bot } from '../../index.js'
export async function handleGuildRoleDelete(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
const payload = data.d as DiscordGuildRoleDelete
bot.events.roleDelete?.({
roleId: bot.transformers.snowflake(payload.role_id),
guildId: bot.transformers.snowflake(payload.guild_id),
})
}

View File

@@ -0,0 +1,13 @@
import type { DiscordGatewayPayload, DiscordGuildRoleUpdate } from '@discordeno/types'
import type { Bot } from '../../index.js'
export async function handleGuildRoleUpdate(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
const payload = data.d as DiscordGuildRoleUpdate
bot.events.roleUpdate?.(
bot.transformers.role(bot, {
role: payload.role,
guildId: bot.transformers.snowflake(payload.guild_id),
}),
)
}

View File

@@ -0,0 +1,3 @@
export * from "./GUILD_ROLE_CREATE.js";
export * from "./GUILD_ROLE_DELETE.js";
export * from "./GUILD_ROLE_UPDATE.js";

View File

@@ -0,0 +1,12 @@
import type { DiscordGatewayPayload, DiscordVoiceServerUpdate } from '@discordeno/types'
import type { Bot } from '../../index.js'
export async function handleVoiceServerUpdate(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
const payload = data.d as DiscordVoiceServerUpdate
bot.events.voiceServerUpdate?.({
token: payload.token,
guildId: bot.transformers.snowflake(payload.guild_id),
endpoint: payload.endpoint ?? undefined,
})
}

View File

@@ -0,0 +1,11 @@
import type { DiscordGatewayPayload, DiscordVoiceState } from '@discordeno/types'
import type { Bot } from '../../index.js'
export async function handleVoiceStateUpdate(bot: Bot, data: DiscordGatewayPayload): Promise<void> {
const payload = data.d as DiscordVoiceState
if (!payload.guild_id) return
const guildId = bot.transformers.snowflake(payload.guild_id)
bot.events.voiceStateUpdate?.(bot.transformers.voiceState(bot, { voiceState: payload, guildId }))
}

View File

@@ -0,0 +1,2 @@
export * from "./VOICE_SERVER_UPDATE.js";
export * from "./VOICE_STATE_UPDATE.js";

View File

@@ -0,0 +1,10 @@
import type { DiscordGatewayPayload, DiscordWebhookUpdate } from '@discordeno/types'
import type { Bot } from '../../index.js'
export async function handleWebhooksUpdate(bot: Bot, data: DiscordGatewayPayload, shardId: number) : Promise<void> {
const payload = data.d as DiscordWebhookUpdate
bot.events.webhooksUpdate?.({
channelId: bot.transformers.snowflake(payload.channel_id),
guildId: bot.transformers.snowflake(payload.guild_id),
})
}

View File

@@ -0,0 +1 @@
export * from "./WEBHOOKS_UPDATE.js";

View File

@@ -3,3 +3,6 @@ export * from '@discordeno/rest'
export * from '@discordeno/types'
export * from '@discordeno/utils'
export * from './bot.js'
export * from './handlers.js'
export * from './transformers.js'
export * from './utils.js'

View File

@@ -0,0 +1,79 @@
type OptionalizeAux<T extends object> = Id<
& {
[K in KeysWithUndefined<T>]?: Optionalize<T[K]>;
}
& {
[K in Exclude<keyof T, KeysWithUndefined<T>>]: T[K] extends ObjectLiteral ? Optionalize<T[K]> : T[K];
}
>;
/**
* Makes all of properties in T optional when they're null | undefined
* it is recursive
*/
export type Optionalize<T> = T extends object
? T extends Array<unknown> ? number extends T["length"] ? T[number] extends object ? Array<OptionalizeAux<T[number]>>
: T
: Partial<T>
: OptionalizeAux<T>
: T;
export type KeysWithUndefined<T> = {
[K in keyof T]-?: undefined extends T[K] ? K
: null extends T[K] ? K
: never;
}[keyof T];
/**
* alternative to 'object' or '{}'
* @example:
* export const o: ObjectLiteral = [] as object; // error
* export const o: object = []; // no error
*/
export type ObjectLiteral<T = unknown> = {
[K in PropertyKey]: T;
};
/**
* object identity type
*/
export type Id<T> = T extends infer U ? {
[K in keyof U]: U[K];
}
: never;
/** Array with no utilty methods, aka Object.create(null) */
export type ArrayWithNoPrototype<T> = {
[index: number]: T | ArrayWithNoPrototype<T>;
};
/**
* Allows any type but T
* it is recursive
* @example
* export type RequestData = Record<string, AnythingBut<bigint>>;
*/
export type AnythingBut<T> = Exclude<
| Primitive
| {
[K in PropertyKey]: AnythingBut<T>;
}
| ArrayWithNoPrototype<
| Primitive
| {
[K in PropertyKey]: AnythingBut<T>;
}
>,
T
>;
/** Non object primitives */
export type Primitive =
| string
| number
| symbol
| bigint
| boolean
| undefined
| null;
// | object <- don't make object a primitive

View File

@@ -0,0 +1,220 @@
import type {
AllowedMentions,
ApplicationCommandOption,
ApplicationCommandOptionChoice,
BigString,
CreateApplicationCommand,
DiscordActivity,
DiscordAllowedMentions,
DiscordApplication,
DiscordApplicationCommand,
DiscordApplicationCommandOption,
DiscordApplicationCommandOptionChoice,
DiscordAttachment,
DiscordAuditLogEntry,
DiscordAutoModerationActionExecution,
DiscordAutoModerationRule,
DiscordChannel,
DiscordCreateApplicationCommand,
DiscordEmbed,
DiscordEmoji,
DiscordGetGatewayBot,
DiscordGuild,
DiscordGuildApplicationCommandPermissions,
DiscordGuildWidget,
DiscordGuildWidgetSettings,
DiscordIntegrationCreateUpdate,
DiscordInteraction,
DiscordInteractionDataOption,
DiscordInviteCreate,
DiscordMember,
DiscordMessage,
DiscordPresenceUpdate,
DiscordRole,
DiscordScheduledEvent,
DiscordStageInstance,
DiscordSticker,
DiscordStickerPack,
DiscordTeam,
DiscordTemplate,
DiscordThreadMember,
DiscordUser,
DiscordVoiceRegion,
DiscordVoiceState,
DiscordWebhook,
DiscordWelcomeScreen,
} from '@discordeno/types'
import { bigintToSnowflake, snowflakeToBigint, type Bot } from './index.js'
import { transformActivity, type Activity } from './transformers/activity.js'
import { transformApplication, type Application } from './transformers/application.js'
import { transformApplicationCommand, type ApplicationCommand } from './transformers/applicationCommand.js'
import { transformApplicationCommandOption } from './transformers/applicationCommandOption.js'
import { transformApplicationCommandOptionChoice } from './transformers/applicationCommandOptionChoice.js'
import { transformApplicationCommandPermission, type ApplicationCommandPermission } from './transformers/applicationCommandPermission.js'
import { transformAttachment, type Attachment } from './transformers/attachment.js'
import { transformAuditLogEntry, type AuditLogEntry } from './transformers/auditLogEntry.js'
import { transformAutoModerationActionExecution, type AutoModerationActionExecution } from './transformers/automodActionExecution.js'
import { transformAutoModerationRule, type AutoModerationRule } from './transformers/automodRule.js'
import { transformChannel, type Channel } from './transformers/channel.js'
import { transformComponent, type Component } from './transformers/component.js'
import { transformEmbed, type Embed } from './transformers/embed.js'
import { transformEmoji, type Emoji } from './transformers/emoji.js'
import { transformGatewayBot, type GetGatewayBot } from './transformers/gatewayBot.js'
import { transformGuild, type Guild } from './transformers/guild.js'
import { transformIntegration, type Integration } from './transformers/integration.js'
import { transformInteraction, transformInteractionDataOption, type Interaction, type InteractionDataOption } from './transformers/interaction.js'
import { transformInvite, type Invite } from './transformers/invite.js'
import { transformMember, transformUser, type Member, type User } from './transformers/member.js'
import { transformMessage, type Message } from './transformers/message.js'
import {
transformActivityToDiscordActivity,
transformApplicationCommandOptionChoiceToDiscordApplicationCommandOptionChoice,
transformApplicationCommandOptionToDiscordApplicationCommandOption,
transformApplicationCommandToDiscordApplicationCommand,
transformApplicationToDiscordApplication,
transformAttachmentToDiscordAttachment,
transformComponentToDiscordComponent,
transformEmbedToDiscordEmbed,
transformMemberToDiscordMember,
transformTeamToDiscordTeam,
transformUserToDiscordUser,
} from './transformers/index.js'
import { transformPresence, type PresenceUpdate } from './transformers/presence.js'
import { transformAllowedMentionsToDiscordAllowedMentions } from './transformers/reverse/allowedMentions.js'
import { transformCreateApplicationCommandToDiscordCreateApplicationCommand } from './transformers/reverse/createApplicationCommand.js'
import { transformInteractionResponseToDiscordInteractionResponse } from './transformers/reverse/interactionResponse.js'
import { transformRole, type Role } from './transformers/role.js'
import { transformScheduledEvent, type ScheduledEvent } from './transformers/scheduledEvent.js'
import { transformStageInstance, type StageInstance } from './transformers/stageInstance.js'
import { transformSticker, transformStickerPack, type Sticker, type StickerPack } from './transformers/sticker.js'
import { transformTeam, type Team } from './transformers/team.js'
import { transformTemplate, type Template } from './transformers/template.js'
import { transformThreadMember, type ThreadMember } from './transformers/threadMember.js'
import { transformVoiceRegion, type VoiceRegions } from './transformers/voiceRegion.js'
import { transformVoiceState, type VoiceState } from './transformers/voiceState.js'
import { transformWebhook, type Webhook } from './transformers/webhook.js'
import { transformWelcomeScreen, type WelcomeScreen } from './transformers/welcomeScreen.js'
import { transformWidget, type GuildWidget } from './transformers/widget.js'
import { transformWidgetSettings, type GuildWidgetSettings } from './transformers/widgetSettings.js'
import type { BotInteractionResponse, DiscordComponent, DiscordInteractionResponse } from './typings.js'
export interface Transformers {
reverse: {
allowedMentions: (bot: Bot, payload: AllowedMentions) => DiscordAllowedMentions
embed: (bot: Bot, payload: Embed) => DiscordEmbed
component: (bot: Bot, payload: Component) => DiscordComponent
activity: (bot: Bot, payload: Activity) => DiscordActivity
member: (bot: Bot, payload: Member) => DiscordMember
user: (bot: Bot, payload: User) => DiscordUser
team: (bot: Bot, payload: Team) => DiscordTeam
application: (bot: Bot, payload: Application) => DiscordApplication
snowflake: (snowflake: BigString) => string
createApplicationCommand: (bot: Bot, payload: CreateApplicationCommand) => DiscordCreateApplicationCommand
applicationCommand: (bot: Bot, payload: ApplicationCommand) => DiscordApplicationCommand
applicationCommandOption: (bot: Bot, payload: ApplicationCommandOption) => DiscordApplicationCommandOption
applicationCommandOptionChoice: (bot: Bot, payload: ApplicationCommandOptionChoice) => DiscordApplicationCommandOptionChoice
interactionResponse: (bot: Bot, payload: BotInteractionResponse) => DiscordInteractionResponse
attachment: (bot: Bot, payload: Attachment) => DiscordAttachment
}
snowflake: (snowflake: BigString) => bigint
gatewayBot: (payload: DiscordGetGatewayBot) => GetGatewayBot
automodRule: (bot: Bot, payload: DiscordAutoModerationRule) => AutoModerationRule
automodActionExecution: (bot: Bot, payload: DiscordAutoModerationActionExecution) => AutoModerationActionExecution
channel: (bot: Bot, payload: { channel: DiscordChannel } & { guildId?: bigint }) => Channel
guild: (bot: Bot, payload: { guild: DiscordGuild } & { shardId: number }) => Guild
user: (bot: Bot, payload: DiscordUser) => User
member: (bot: Bot, payload: DiscordMember, guildId: bigint, userId: bigint) => Member
message: (bot: Bot, payload: DiscordMessage) => Message
role: (bot: Bot, payload: { role: DiscordRole } & { guildId: bigint }) => Role
voiceState: (bot: Bot, payload: { voiceState: DiscordVoiceState } & { guildId: bigint }) => VoiceState
interaction: (bot: Bot, payload: DiscordInteraction) => Interaction
interactionDataOptions: (bot: Bot, payload: DiscordInteractionDataOption) => InteractionDataOption
integration: (bot: Bot, payload: DiscordIntegrationCreateUpdate) => Integration
invite: (bot: Bot, invite: DiscordInviteCreate) => Invite
application: (bot: Bot, payload: DiscordApplication) => Application
team: (bot: Bot, payload: DiscordTeam) => Team
emoji: (bot: Bot, payload: DiscordEmoji) => Emoji
activity: (bot: Bot, payload: DiscordActivity) => Activity
presence: (bot: Bot, payload: DiscordPresenceUpdate) => PresenceUpdate
attachment: (bot: Bot, payload: DiscordAttachment) => Attachment
embed: (bot: Bot, payload: DiscordEmbed) => Embed
component: (bot: Bot, payload: DiscordComponent) => Component
webhook: (bot: Bot, payload: DiscordWebhook) => Webhook
auditLogEntry: (bot: Bot, payload: DiscordAuditLogEntry) => AuditLogEntry
applicationCommand: (bot: Bot, payload: DiscordApplicationCommand) => ApplicationCommand
applicationCommandOption: (bot: Bot, payload: DiscordApplicationCommandOption) => ApplicationCommandOption
applicationCommandPermission: (bot: Bot, payload: DiscordGuildApplicationCommandPermissions) => ApplicationCommandPermission
scheduledEvent: (bot: Bot, payload: DiscordScheduledEvent) => ScheduledEvent
threadMember: (bot: Bot, payload: DiscordThreadMember) => ThreadMember
welcomeScreen: (bot: Bot, payload: DiscordWelcomeScreen) => WelcomeScreen
voiceRegion: (bot: Bot, payload: DiscordVoiceRegion) => VoiceRegions
widget: (bot: Bot, payload: DiscordGuildWidget) => GuildWidget
widgetSettings: (bot: Bot, payload: DiscordGuildWidgetSettings) => GuildWidgetSettings
stageInstance: (bot: Bot, payload: DiscordStageInstance) => StageInstance
sticker: (bot: Bot, payload: DiscordSticker) => Sticker
stickerPack: (bot: Bot, payload: DiscordStickerPack) => StickerPack
applicationCommandOptionChoice: (bot: Bot, payload: DiscordApplicationCommandOptionChoice) => ApplicationCommandOptionChoice
template: (bot: Bot, payload: DiscordTemplate) => Template
}
export function createTransformers(options: Partial<Transformers>): Transformers {
return {
reverse: {
allowedMentions: options.reverse?.allowedMentions ?? transformAllowedMentionsToDiscordAllowedMentions,
embed: options.reverse?.embed ?? transformEmbedToDiscordEmbed,
component: options.reverse?.component ?? transformComponentToDiscordComponent,
activity: options.reverse?.activity ?? transformActivityToDiscordActivity,
member: options.reverse?.member ?? transformMemberToDiscordMember,
user: options.reverse?.user ?? transformUserToDiscordUser,
team: options.reverse?.team ?? transformTeamToDiscordTeam,
application: options.reverse?.application ?? transformApplicationToDiscordApplication,
snowflake: options.reverse?.snowflake ?? bigintToSnowflake,
createApplicationCommand: options.reverse?.createApplicationCommand ?? transformCreateApplicationCommandToDiscordCreateApplicationCommand,
applicationCommand: options.reverse?.applicationCommand ?? transformApplicationCommandToDiscordApplicationCommand,
applicationCommandOption: options.reverse?.applicationCommandOption ?? transformApplicationCommandOptionToDiscordApplicationCommandOption,
applicationCommandOptionChoice:
options.reverse?.applicationCommandOptionChoice ?? transformApplicationCommandOptionChoiceToDiscordApplicationCommandOptionChoice,
interactionResponse: options.reverse?.interactionResponse ?? transformInteractionResponseToDiscordInteractionResponse,
attachment: options.reverse?.attachment ?? transformAttachmentToDiscordAttachment,
},
automodRule: options.automodRule ?? transformAutoModerationRule,
automodActionExecution: options.automodActionExecution ?? transformAutoModerationActionExecution,
activity: options.activity ?? transformActivity,
application: options.application ?? transformApplication,
attachment: options.attachment ?? transformAttachment,
channel: options.channel ?? transformChannel,
component: options.component ?? transformComponent,
embed: options.embed ?? transformEmbed,
emoji: options.emoji ?? transformEmoji,
guild: options.guild ?? transformGuild,
integration: options.integration ?? transformIntegration,
interaction: options.interaction ?? transformInteraction,
interactionDataOptions: options.interactionDataOptions ?? transformInteractionDataOption,
invite: options.invite ?? transformInvite,
member: options.member ?? transformMember,
message: options.message ?? transformMessage,
presence: options.presence ?? transformPresence,
role: options.role ?? transformRole,
user: options.user ?? transformUser,
team: options.team ?? transformTeam,
voiceState: options.voiceState ?? transformVoiceState,
snowflake: options.snowflake ?? snowflakeToBigint,
webhook: options.webhook ?? transformWebhook,
auditLogEntry: options.auditLogEntry ?? transformAuditLogEntry,
applicationCommand: options.applicationCommand ?? transformApplicationCommand,
applicationCommandOption: options.applicationCommandOption ?? transformApplicationCommandOption,
applicationCommandPermission: options.applicationCommandPermission ?? transformApplicationCommandPermission,
scheduledEvent: options.scheduledEvent ?? transformScheduledEvent,
threadMember: options.threadMember ?? transformThreadMember,
welcomeScreen: options.welcomeScreen ?? transformWelcomeScreen,
voiceRegion: options.voiceRegion ?? transformVoiceRegion,
widget: options.widget ?? transformWidget,
widgetSettings: options.widgetSettings ?? transformWidgetSettings,
stageInstance: options.stageInstance ?? transformStageInstance,
sticker: options.sticker ?? transformSticker,
stickerPack: options.stickerPack ?? transformStickerPack,
gatewayBot: options.gatewayBot ?? transformGatewayBot,
applicationCommandOptionChoice: options.applicationCommandOptionChoice ?? transformApplicationCommandOptionChoice,
template: options.template ?? transformTemplate,
}
}

View File

@@ -0,0 +1,42 @@
import type { DiscordActivity } from '@discordeno/bot'
import type { Bot } from '../index.js'
import type { Optionalize } from '../optionalize.js'
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
export function transformActivity(bot: Bot, payload: DiscordActivity) {
const activity = {
name: payload.name,
type: payload.type,
url: payload.url ?? undefined,
createdAt: payload.created_at,
startedAt: payload.timestamps?.start,
endedAt: payload.timestamps?.end,
applicationId: payload.application_id ? bot.transformers.snowflake(payload.application_id) : undefined,
details: payload.details ?? undefined,
state: payload.state ?? undefined,
emoji: payload.emoji
? {
name: payload.emoji.name,
animated: payload.emoji.animated,
id: payload.emoji.id ? bot.transformers.snowflake(payload.emoji.id) : undefined,
}
: undefined,
partyId: payload.party?.id,
partyCurrentSize: payload.party?.size?.[0],
partyMaxSize: payload.party?.size?.[1],
largeImage: payload.assets?.large_image,
largeText: payload.assets?.large_text,
smallImage: payload.assets?.small_image,
smallText: payload.assets?.small_text,
join: payload.secrets?.join,
spectate: payload.secrets?.spectate,
match: payload.secrets?.match,
instance: payload.instance,
flags: payload.flags,
buttons: payload.buttons,
}
return activity as Optionalize<typeof activity>
}
export interface Activity extends ReturnType<typeof transformActivity> {}

View File

@@ -0,0 +1,34 @@
import { iconHashToBigInt, type DiscordApplication } from '@discordeno/bot'
import type { Bot } from '../index.js'
import type { Optionalize } from '../optionalize.js'
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
export function transformApplication(bot: Bot, payload: DiscordApplication) {
const application = {
name: payload.name,
description: payload.description,
rpcOrigins: payload.rpc_origins,
botPublic: payload.bot_public,
botRequireCodeGrant: payload.bot_require_code_grant,
termsOfServiceUrl: payload.terms_of_service_url,
privacyPolicyUrl: payload.privacy_policy_url,
verifyKey: payload.verify_key,
primarySkuId: payload.primary_sku_id,
slug: payload.slug,
coverImage: payload.cover_image ? iconHashToBigInt(payload.cover_image) : undefined,
flags: payload.flags,
id: bot.transformers.snowflake(payload.id),
icon: payload.icon ? iconHashToBigInt(payload.icon) : undefined,
owner: payload.owner
? // @ts-expect-error the partial here wont break anything
bot.transformers.user(bot, payload.owner)
: undefined,
team: payload.team ? bot.transformers.team(bot, payload.team) : undefined,
guildId: payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined,
}
return application as Optionalize<typeof application>
}
export interface Application extends ReturnType<typeof transformApplication> {}

View File

@@ -0,0 +1,26 @@
import type { DiscordApplicationCommand } from '@discordeno/types'
import type { Bot } from '../index.js'
import type { Optionalize } from '../optionalize.js'
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
export function transformApplicationCommand(bot: Bot, payload: DiscordApplicationCommand) {
const applicationCommand = {
id: bot.transformers.snowflake(payload.id),
applicationId: bot.transformers.snowflake(payload.application_id),
guildId: payload.guild_id ? bot.transformers.snowflake(payload.guild_id) : undefined,
name: payload.name,
nameLocalizations: payload.name_localizations ?? undefined,
description: payload.description,
descriptionLocalizations: payload.description_localizations ?? undefined,
defaultMemberPermissions: payload.default_member_permissions ? bot.transformers.snowflake(payload.default_member_permissions) : undefined,
dmPermission: payload.dm_permission ?? false,
type: payload.type,
version: payload.version,
options: payload.options?.map((option) => bot.transformers.applicationCommandOption(bot, option)),
}
return applicationCommand as Optionalize<typeof applicationCommand>
}
export interface ApplicationCommand extends ReturnType<typeof transformApplicationCommand> {}

View File

@@ -0,0 +1,55 @@
import type { ApplicationCommandOptionTypes, ChannelTypes, DiscordApplicationCommandOption, Localization } from '@discordeno/types'
import type { Bot } from '../index.js'
import type { ApplicationCommandOptionChoice } from './applicationCommandOptionChoice.js'
export function transformApplicationCommandOption(bot: Bot, payload: DiscordApplicationCommandOption): ApplicationCommandOption {
return {
type: payload.type,
name: payload.name,
nameLocalizations: payload.name_localizations ?? undefined,
description: payload.description,
descriptionLocalizations: payload.description_localizations ?? undefined,
required: payload.required ?? false,
choices: payload.choices?.map((choice) => bot.transformers.applicationCommandOptionChoice(bot, choice)),
autocomplete: payload.autocomplete,
channelTypes: payload.channel_types,
minValue: payload.min_value,
maxValue: payload.max_value,
minLength: payload.min_length,
maxLength: payload.max_length,
options: payload.options?.map((option) => bot.transformers.applicationCommandOption(bot, option)),
}
}
// THIS TRANSFORMER HAS A CIRCULAR REFERENCE TO CALL ITSELF FOR OPTIONS SO AN AUTOMATED TYPE CAN NOT BE CREATED!
export interface ApplicationCommandOption {
/** Value of Application Command Option Type */
type: ApplicationCommandOptionTypes
/** 1-32 character name matching lowercase `^[\w-]{1,32}$` */
name: string
/** Localization object for the `name` field. Values follow the same restrictions as `name` */
nameLocalizations?: Localization
/** 1-100 character description */
description: string
/** Localization object for the `description` field. Values follow the same restrictions as `description` */
descriptionLocalizations?: Localization
/** If the parameter is required or optional--default `false` */
required?: boolean
/** Choices for `string` and `int` types for the user to pick from */
choices?: ApplicationCommandOptionChoice[]
/** If the option is a subcommand or subcommand group type, this nested options will be the parameters */
options?: ApplicationCommandOption[]
/** If the option is a channel type, the channels shown will be restricted to these types */
channelTypes?: ChannelTypes[]
/** Minimum number desired. */
minValue?: number
/** Maximum number desired. */
maxValue?: number
/** Minimum length desired. */
minLength?: number
/** Maximum length desired. */
maxLength?: number
/** if autocomplete interactions are enabled for this `String`, `Integer`, or `Number` type option */
autocomplete?: boolean
}

View File

@@ -0,0 +1,16 @@
import type { DiscordApplicationCommandOptionChoice } from '@discordeno/types'
import type { Bot } from '../index.js'
import type { Optionalize } from '../optionalize.js'
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
export function transformApplicationCommandOptionChoice(bot: Bot, payload: DiscordApplicationCommandOptionChoice) {
const applicationCommandChoice = {
name: payload.name,
nameLocalizations: payload.name_localizations ?? undefined,
value: payload.value,
}
return applicationCommandChoice as Optionalize<typeof applicationCommandChoice>
}
export interface ApplicationCommandOptionChoice extends ReturnType<typeof transformApplicationCommandOptionChoice> {}

View File

@@ -0,0 +1,21 @@
import type { DiscordGuildApplicationCommandPermissions } from '@discordeno/types'
import type { Bot } from '../index.js'
import type { Optionalize } from '../optionalize.js'
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
export function transformApplicationCommandPermission(bot: Bot, payload: DiscordGuildApplicationCommandPermissions) {
const applicationCommandPermission = {
id: bot.transformers.snowflake(payload.id),
applicationId: bot.transformers.snowflake(payload.application_id),
guildId: bot.transformers.snowflake(payload.guild_id),
permissions: payload.permissions.map((perm) => ({
id: bot.transformers.snowflake(perm.id),
type: perm.type,
permission: perm.permission,
})),
}
return applicationCommandPermission as Optionalize<typeof applicationCommandPermission>
}
export interface ApplicationCommandPermission extends ReturnType<typeof transformApplicationCommandPermission> {}

View File

@@ -0,0 +1,23 @@
import type { DiscordAttachment } from '@discordeno/types'
import type { Bot } from '../index.js'
import type { Optionalize } from '../optionalize.js'
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
export function transformAttachment(bot: Bot, payload: DiscordAttachment) {
const attachment = {
id: bot.transformers.snowflake(payload.id),
filename: payload.filename,
contentType: payload.content_type,
size: payload.size,
url: payload.url,
proxyUrl: payload.proxy_url,
height: payload.height ?? undefined,
width: payload.width ?? undefined,
ephemeral: payload.ephemeral,
description: payload.description,
}
return attachment as Optionalize<typeof attachment>
}
export interface Attachment extends ReturnType<typeof transformAttachment> {}

View File

@@ -0,0 +1,136 @@
import type { DiscordAuditLogEntry } from '@discordeno/types'
import type { Bot } from '../index.js'
import type { Optionalize } from '../optionalize.js'
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
export function transformAuditLogEntry(bot: Bot, payload: DiscordAuditLogEntry) {
const auditLogEntry = {
id: bot.transformers.snowflake(payload.id),
changes: payload.changes?.map((change) => {
switch (change.key) {
case '$add':
case '$remove':
return {
key: change.key,
new: change.new_value?.map((val) => ({
id: val.id ? bot.transformers.snowflake(val.id) : undefined,
name: val.name,
})),
old: change.old_value?.map((val) => ({
id: val?.id ? bot.transformers.snowflake(val.id) : undefined,
name: val?.name,
})),
}
case 'discovery_splash_hash':
case 'banner_hash':
case 'rules_channel_id':
case 'public_updates_channel_id':
case 'icon_hash':
case 'image_hash':
case 'splash_hash':
case 'owner_id':
case 'widget_channel_id':
case 'system_channel_id':
case 'application_id':
case 'permissions':
case 'allow':
case 'deny':
case 'channel_id':
case 'inviter_id':
case 'avatar_hash':
case 'id':
return {
key: change.key,
old: change.old_value ? bot.transformers.snowflake(change.old_value) : undefined,
new: change.new_value ? bot.transformers.snowflake(change.new_value) : undefined,
}
case 'name':
case 'description':
case 'preferred_locale':
case 'region':
case 'afk_channel_id':
case 'vanity_url_code':
case 'topic':
case 'code':
case 'nick':
case 'location':
return {
key: change.key,
old: change.old_value,
new: change.new_value,
}
case 'afk_timeout':
case 'mfa_level':
case 'verification_level':
case 'explicit_content_filter':
case 'default_message_notifications':
case 'prune_delete_days':
case 'position':
case 'bitrate':
case 'rate_limit_per_user':
case 'color':
case 'max_uses':
case 'uses':
case 'max_age':
case 'expire_behavior':
case 'expire_grace_period':
case 'user_limit':
case 'privacy_level':
case 'entity_type':
case 'status':
return {
key: change.key,
old: change.old_value ? Number(change.old_value) : undefined,
new: change.new_value ? Number(change.new_value) : undefined,
}
case 'widget_enabled':
case 'nsfw':
case 'hoist':
case 'mentionable':
case 'temporary':
case 'deaf':
case 'mute':
case 'enable_emoticons':
return {
key: change.key,
old: change.old_value ?? false,
new: change.new_value ?? false,
}
case 'permission_overwrites':
return {
key: change.key,
old: change.old_value,
new: change.new_value,
}
default:
return {
key: change.key,
old: change.old_value,
new: change.new_value,
}
}
}),
userId: payload.user_id ? bot.transformers.snowflake(payload.user_id) : undefined,
targetId: payload.target_id ? bot.transformers.snowflake(payload.target_id) : undefined,
actionType: payload.action_type,
options: payload.options
? {
deleteMemberDays: payload.options.delete_member_days ? Number(payload.options.delete_member_days) : 0,
membersRemoved: payload.options.members_removed ? Number(payload.options.members_removed) : 0,
channelId: payload.options.channel_id ? bot.transformers.snowflake(payload.options.channel_id) : undefined,
messageId: payload.options.message_id ? bot.transformers.snowflake(payload.options.message_id) : undefined,
count: payload.options.count ? Number(payload.options.count) : 0,
id: payload.options.id ? bot.transformers.snowflake(payload.options.id) : undefined,
type: Number(payload.options.type),
roleName: payload.options.role_name,
autoModerationRuleName: payload.options.auto_moderation_rule_name,
autoModerationRuleTriggerType: payload.options.auto_moderation_rule_trigger_type,
}
: undefined,
reason: payload.reason,
}
return auditLogEntry as Optionalize<typeof auditLogEntry>
}
export interface AuditLogEntry extends ReturnType<typeof transformAuditLogEntry> {}

View File

@@ -0,0 +1,30 @@
import type { DiscordAutoModerationActionExecution } from '@discordeno/types'
import type { Bot } from '../index.js'
import type { Optionalize } from '../optionalize.js'
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
export function transformAutoModerationActionExecution(bot: Bot, payload: DiscordAutoModerationActionExecution) {
const rule = {
content: payload.content,
ruleTriggerType: payload.rule_trigger_type,
guildId: bot.transformers.snowflake(payload.guild_id),
ruleId: bot.transformers.snowflake(payload.rule_id),
userId: bot.transformers.snowflake(payload.user_id),
channelId: payload.channel_id ? bot.transformers.snowflake(payload.channel_id) : undefined,
messageId: payload.message_id ? bot.transformers.snowflake(payload.message_id) : undefined,
alertSystemMessageId: payload.alert_system_message_id ? bot.transformers.snowflake(payload.alert_system_message_id) : undefined,
matchedKeyword: payload.matched_keyword ?? '',
matchedContent: payload.matched_content ?? '',
action: {
type: payload.action.type,
metadata: {
durationSeconds: payload.action.metadata.duration_seconds,
channelId: payload.action.metadata.channel_id ? bot.transformers.snowflake(payload.action.metadata.channel_id) : undefined,
},
},
}
return rule as Optionalize<typeof rule>
}
export interface AutoModerationActionExecution extends ReturnType<typeof transformAutoModerationActionExecution> {}

View File

@@ -0,0 +1,39 @@
import type { DiscordAutoModerationRule } from '@discordeno/types'
import type { Bot } from '../index.js'
import type { Optionalize } from '../optionalize.js'
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
export function transformAutoModerationRule(bot: Bot, payload: DiscordAutoModerationRule) {
const rule = {
name: payload.name,
eventType: payload.event_type,
triggerType: payload.trigger_type,
enabled: payload.enabled,
id: bot.transformers.snowflake(payload.id),
guildId: bot.transformers.snowflake(payload.guild_id),
creatorId: bot.transformers.snowflake(payload.creator_id),
exemptRoles: payload.exempt_roles.map((id) => bot.transformers.snowflake(id)),
exemptChannels: payload.exempt_channels.map((id) => bot.transformers.snowflake(id)),
triggerMetadata: payload.trigger_metadata
? {
keywordFilter: payload.trigger_metadata.keyword_filter,
presets: payload.trigger_metadata.presets,
allowList: payload.trigger_metadata.allow_list,
mentionTotalLimit: payload.trigger_metadata.mention_total_limit,
}
: undefined,
actions: payload.actions.map((action) => ({
type: action.type,
metadata: action.metadata
? {
channelId: action.metadata.channel_id ? bot.transformers.snowflake(action.metadata.channel_id) : undefined,
durationSeconds: action.metadata.duration_seconds,
}
: undefined,
})),
}
return rule as Optionalize<typeof rule>
}
export interface AutoModerationRule extends ReturnType<typeof transformAutoModerationRule> {}

View File

@@ -0,0 +1,65 @@
import type { DiscordChannel } from '@discordeno/types'
import type { Bot } from '../index.js'
import type { Optionalize } from '../optionalize.js'
const Mask = (1n << 64n) - 1n
export function packOverwrites(allow: string, deny: string, id: string, type: number): bigint {
return pack64(allow, 0) | pack64(deny, 1) | pack64(id, 2) | pack64(type, 3)
}
function unpack64(v: bigint, shift: number): bigint {
return (v >> BigInt(shift * 64)) & Mask
}
function pack64(v: string | number, shift: number): bigint {
const b = BigInt(v)
if (b < 0 || b > Mask) throw new Error('should have been a 64 bit unsigned integer: ' + v.toString())
return b << BigInt(shift * 64)
}
export function separateOverwrites(v: bigint): [number, bigint, bigint, bigint] {
return [Number(unpack64(v, 3)), unpack64(v, 2), unpack64(v, 0), unpack64(v, 1)] as [number, bigint, bigint, bigint]
}
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
export function transformChannel(bot: Bot, payload: { channel: DiscordChannel } & { guildId?: bigint }) {
const channel = {
// UNTRANSFORMED STUFF HERE
type: payload.channel.type,
position: payload.channel.position,
name: payload.channel.name,
topic: payload.channel.topic ?? undefined,
nsfw: payload.channel.nsfw,
bitrate: payload.channel.bitrate,
userLimit: payload.channel.user_limit,
rateLimitPerUser: payload.channel.rate_limit_per_user,
// recipients: payload.channel.recipients?.map((r) => bot.transformers.user(bot, r)),
rtcRegion: payload.channel.rtc_region ?? undefined,
videoQualityMode: payload.channel.video_quality_mode,
guildId: payload.guildId ?? (payload.channel.guild_id ? bot.transformers.snowflake(payload.channel.guild_id) : 0n),
lastPinTimestamp: payload.channel.last_pin_timestamp ? Date.parse(payload.channel.last_pin_timestamp) : undefined,
permissionOverwrites: payload.channel.permission_overwrites
? payload.channel.permission_overwrites.map((o) => packOverwrites(o.allow ?? '0', o.deny ?? '0', o.id, o.type))
: [],
id: bot.transformers.snowflake(payload.channel.id),
permissions: payload.channel.permissions ? bot.transformers.snowflake(payload.channel.permissions) : undefined,
lastMessageId: payload.channel.last_message_id ? bot.transformers.snowflake(payload.channel.last_message_id) : undefined,
ownerId: payload.channel.owner_id ? bot.transformers.snowflake(payload.channel.owner_id) : undefined,
applicationId: payload.channel.application_id ? bot.transformers.snowflake(payload.channel.application_id) : undefined,
parentId: payload.channel.parent_id ? bot.transformers.snowflake(payload.channel.parent_id) : undefined,
memberCount: payload.channel.member_count,
messageCount: payload.channel.message_count,
archiveTimestamp: payload.channel.thread_metadata?.archive_timestamp ? Date.parse(payload.channel.thread_metadata.archive_timestamp) : undefined,
autoArchiveDuration: payload.channel.thread_metadata?.auto_archive_duration,
botIsMember: Boolean(payload.channel.member),
archived: payload.channel.thread_metadata?.archived,
locked: payload.channel.thread_metadata?.locked,
invitable: payload.channel.thread_metadata?.invitable,
createTimestamp: payload.channel.thread_metadata?.create_timestamp ? Date.parse(payload.channel.thread_metadata.create_timestamp) : undefined,
newlyCreated: payload.channel.newly_created,
flags: payload.channel.flags,
}
return channel as Optionalize<typeof channel>
}
export interface Channel extends ReturnType<typeof transformChannel> {}

View File

@@ -0,0 +1,85 @@
import type { ButtonStyles, MessageComponentTypes, SelectOption, TextStyles } from '@discordeno/types'
import type { Bot } from '../index.js'
import type { DiscordComponent } from '../typings.js'
export function transformComponent(bot: Bot, payload: DiscordComponent): Component {
return {
type: payload.type,
customId: payload.custom_id,
disabled: payload.disabled,
style: payload.style,
label: payload.label,
emoji: payload.emoji
? {
id: payload.emoji.id ? bot.transformers.snowflake(payload.emoji.id) : undefined,
name: payload.emoji.name,
animated: payload.emoji.animated,
}
: undefined,
url: payload.url,
options: payload.options?.map((option) => ({
label: option.label,
value: option.value,
description: option.description,
emoji: option.emoji
? {
id: option.emoji.id ? bot.transformers.snowflake(option.emoji.id) : undefined,
name: option.emoji.name,
animated: option.emoji.animated,
}
: undefined,
default: option.default,
})),
placeholder: payload.placeholder,
minValues: payload.min_values,
maxValues: payload.max_values,
minLength: payload.min_length,
maxLength: payload.max_length,
value: payload.value,
components: payload.components?.map((component) => bot.transformers.component(bot, component)),
}
}
// THIS TRANSFORMER HAS A CIRCULAR REFERENCE TO CALL ITSELF FOR COMPONENTS SO AN AUTOMATED TYPE CAN NOT BE CREATED!
export interface Component {
/** component type */
type: MessageComponentTypes
/** a developer-defined identifier for the component, max 100 characters */
customId?: string
/** whether this component is required to be filled, default true */
required?: boolean
/** whether the component is disabled, default false */
disabled?: boolean
/** For different styles/colors of the buttons */
style?: ButtonStyles | TextStyles
/** text that appears on the button (max 80 characters) */
label?: string
/** the dev-define value of the option, max 100 characters for select or 4000 for input. */
value?: string
/** Emoji object that includes fields of name, id, and animated supporting unicode and custom emojis. */
emoji?: {
/** Emoji id */
id?: bigint
/** Emoji name */
name?: string
/** Whether this emoji is animated */
animated?: boolean
}
/** optional url for link-style buttons that can navigate a user to the web. Only type 5 Link buttons can have a url */
url?: string
/** The choices! Maximum of 25 items. */
options?: SelectOption[]
/** A custom placeholder text if nothing is selected. Maximum 150 characters. */
placeholder?: string
/** The minimum number of items that must be selected. Default 1. Between 1-25. */
minValues?: number
/** The maximum number of items that can be selected. Default 1. Between 1-25. */
maxValues?: number
/** The minimum input length for a text input. Between 0-4000. */
minLength?: number
/** The maximum input length for a text input. Between 1-4000. */
maxLength?: number
/** a list of child components */
components?: Component[]
}

View File

@@ -0,0 +1,60 @@
import type { DiscordEmbed } from '@discordeno/types'
import type { Bot } from '../index.js'
import type { Optionalize } from '../optionalize.js'
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
export function transformEmbed(bot: Bot, payload: DiscordEmbed) {
const embed = {
title: payload.title,
type: payload.type,
description: payload.description,
url: payload.url,
timestamp: payload.timestamp ? Date.parse(payload.timestamp) : undefined,
color: payload.color,
footer: payload.footer
? {
text: payload.footer.text,
iconUrl: payload.footer.icon_url,
proxyIconUrl: payload.footer.proxy_icon_url,
}
: undefined,
image: payload.image
? {
url: payload.image.url,
proxyUrl: payload.image.proxy_url,
height: payload.image.height,
width: payload.image.width,
}
: undefined,
thumbnail: payload.thumbnail
? {
url: payload.thumbnail.url,
proxyUrl: payload.thumbnail.proxy_url,
height: payload.thumbnail.height,
width: payload.thumbnail.width,
}
: undefined,
video: payload.video
? {
url: payload.video.url,
proxyUrl: payload.video.proxy_url,
height: payload.video.height,
width: payload.video.width,
}
: undefined,
provider: payload.provider,
author: payload.author
? {
name: payload.author.name,
url: payload.author.url,
iconUrl: payload.author.icon_url,
proxyIconUrl: payload.author.proxy_icon_url,
}
: undefined,
fields: payload.fields,
}
return embed as Optionalize<typeof embed>
}
export interface Embed extends ReturnType<typeof transformEmbed> {}

View File

@@ -0,0 +1,19 @@
import type { DiscordEmoji } from '@discordeno/types'
import type { Bot } from '../index.js'
import type { Optionalize } from '../optionalize.js'
import { EmojiToggles } from './toggles/emoji.js'
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
export function transformEmoji(bot: Bot, payload: DiscordEmoji) {
const emoji = {
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,
toggles: new EmojiToggles(payload),
}
return emoji as Optionalize<typeof emoji>
}
export interface Emoji extends ReturnType<typeof transformEmoji> {}

View File

@@ -0,0 +1,20 @@
import type { DiscordGetGatewayBot } from '@discordeno/types'
import type { Optionalize } from '../optionalize.js'
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
export function transformGatewayBot(payload: DiscordGetGatewayBot) {
const gatewayBot = {
url: payload.url,
shards: payload.shards,
sessionStartLimit: {
total: payload.session_start_limit.total,
remaining: payload.session_start_limit.remaining,
resetAfter: payload.session_start_limit.reset_after,
maxConcurrency: payload.session_start_limit.max_concurrency,
},
}
return gatewayBot as Optionalize<typeof gatewayBot>
}
export interface GetGatewayBot extends ReturnType<typeof transformGatewayBot> {}

View File

@@ -0,0 +1,105 @@
import type { DiscordGuild } from '@discordeno/types'
import { Collection, iconHashToBigInt } from '@discordeno/utils'
import type { Bot } from '../index.js'
import type { Optionalize } from '../optionalize.js'
import type { Emoji } from '../transformers/emoji.js'
import { GuildToggles } from './toggles/guild.js'
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
export function transformGuild(bot: Bot, payload: { guild: DiscordGuild } & { shardId: number }) {
const guildId = bot.transformers.snowflake(payload.guild.id)
const guild = {
afkTimeout: payload.guild.afk_timeout,
approximateMemberCount: payload.guild.approximate_member_count,
approximatePresenceCount: payload.guild.approximate_presence_count,
defaultMessageNotifications: payload.guild.default_message_notifications,
description: payload.guild.description,
explicitContentFilter: payload.guild.explicit_content_filter,
toggles: new GuildToggles(payload.guild),
maxMembers: payload.guild.max_members,
maxPresences: payload.guild.max_presences ?? undefined,
maxVideoChannelUsers: payload.guild.max_video_channel_users,
mfaLevel: payload.guild.mfa_level,
name: payload.guild.name,
nsfwLevel: payload.guild.nsfw_level,
preferredLocale: payload.guild.preferred_locale,
premiumSubscriptionCount: payload.guild.premium_subscription_count,
premiumTier: payload.guild.premium_tier,
stageInstances: payload.guild.stage_instances?.map((si) => ({
/** The id of this Stage instance */
id: bot.transformers.snowflake(si.id),
/** The guild id of the associated Stage channel */
guildId,
/** The id of the associated Stage channel */
channelId: bot.transformers.snowflake(si.channel_id),
/** The topic of the Stage instance (1-120 characters) */
topic: si.topic,
})),
systemChannelFlags: payload.guild.system_channel_flags,
vanityUrlCode: payload.guild.vanity_url_code,
verificationLevel: payload.guild.verification_level,
welcomeScreen: payload.guild.welcome_screen
? {
description: payload.guild.welcome_screen.description ?? undefined,
welcomeChannels: payload.guild.welcome_screen.welcome_channels.map((wc) => ({
channelId: bot.transformers.snowflake(wc.channel_id),
description: wc.description,
emojiId: wc.emoji_id ? bot.transformers.snowflake(wc.emoji_id) : undefined,
emojiName: wc.emoji_name ?? undefined,
})),
}
: undefined,
discoverySplash: payload.guild.discovery_splash ? iconHashToBigInt(payload.guild.discovery_splash) : undefined,
joinedAt: payload.guild.joined_at ? Date.parse(payload.guild.joined_at) : undefined,
memberCount: payload.guild.member_count ?? 0,
shardId: payload.shardId,
icon: payload.guild.icon ? iconHashToBigInt(payload.guild.icon) : undefined,
banner: payload.guild.banner ? iconHashToBigInt(payload.guild.banner) : undefined,
splash: payload.guild.splash ? iconHashToBigInt(payload.guild.splash) : undefined,
channels: new Collection(
payload.guild.channels?.map((channel) => {
const result = bot.transformers.channel(bot, { channel, guildId })
return [result.id, result]
}),
),
members: new Collection(
payload.guild.members?.map((member) => {
const result = bot.transformers.member(bot, member, guildId, bot.transformers.snowflake(member.user!.id))
return [result.id, result]
}),
),
roles: new Collection(
payload.guild.roles?.map((role) => {
const result = bot.transformers.role(bot, { role, guildId })
return [result.id, result]
}),
),
emojis: new Collection(
(payload.guild.emojis || []).map((emoji) => {
const em: Emoji = bot.transformers.emoji(bot, emoji)
return [em.id!, em]
}),
),
voiceStates: new Collection(
(payload.guild.voice_states ?? []).map((vs) => bot.transformers.voiceState(bot, { voiceState: vs, guildId })).map((vs) => [vs.userId, vs]),
),
id: guildId,
// WEIRD EDGE CASE WITH BOT CREATED SERVERS
ownerId: payload.guild.owner_id ? bot.transformers.snowflake(payload.guild.owner_id) : 0n,
permissions: payload.guild.permissions ? bot.transformers.snowflake(payload.guild.permissions) : 0n,
afkChannelId: payload.guild.afk_channel_id ? bot.transformers.snowflake(payload.guild.afk_channel_id) : undefined,
widgetChannelId: payload.guild.widget_channel_id ? bot.transformers.snowflake(payload.guild.widget_channel_id) : undefined,
applicationId: payload.guild.application_id ? bot.transformers.snowflake(payload.guild.application_id) : undefined,
systemChannelId: payload.guild.system_channel_id ? bot.transformers.snowflake(payload.guild.system_channel_id) : undefined,
rulesChannelId: payload.guild.rules_channel_id ? bot.transformers.snowflake(payload.guild.rules_channel_id) : undefined,
publicUpdatesChannelId: payload.guild.public_updates_channel_id ? bot.transformers.snowflake(payload.guild.public_updates_channel_id) : undefined,
premiumProgressBarEnabled: payload.guild.premium_progress_bar_enabled,
}
return guild as Optionalize<typeof guild>
}
export interface Guild extends ReturnType<typeof transformGuild> {}

View File

@@ -0,0 +1,36 @@
export * from './activity.js'
export * from './application.js'
export * from './applicationCommand.js'
export * from './applicationCommandOption.js'
export * from './applicationCommandOptionChoice.js'
export * from './applicationCommandPermission.js'
export * from './attachment.js'
export * from './auditLogEntry.js'
export * from './automodRule.js'
export * from './channel.js'
export * from './component.js'
export * from './embed.js'
export * from './emoji.js'
export * from './gatewayBot.js'
export * from './guild.js'
export * from './integration.js'
export * from './interaction.js'
export * from './invite.js'
export * from './member.js'
export * from './message.js'
export * from './presence.js'
export * from './reverse/index.js'
export * from './role.js'
export * from './scheduledEvent.js'
export * from './stageInstance.js'
export * from './sticker.js'
export * from './team.js'
export * from './template.js'
export * from './threadMember.js'
export * from './toggles/index.js'
export * from './voiceRegion.js'
export * from './voiceState.js'
export * from './webhook.js'
export * from './welcomeScreen.js'
export * from './widget.js'
export * from './widgetSettings.js'

View File

@@ -0,0 +1,41 @@
import type { DiscordIntegrationCreateUpdate } from '@discordeno/types'
import { iconHashToBigInt, type Bot } from '../index.js'
import type { Optionalize } from '../optionalize.js'
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
export function transformIntegration(bot: Bot, payload: DiscordIntegrationCreateUpdate) {
const integration = {
guildId: bot.transformers.snowflake(payload.guild_id),
id: bot.transformers.snowflake(payload.id),
name: payload.name,
type: payload.type,
enabled: payload.enabled,
syncing: payload.syncing,
roleId: payload.role_id ? bot.transformers.snowflake(payload.role_id) : undefined,
enableEmoticons: payload.enable_emoticons,
expireBehavior: payload.expire_behavior,
expireGracePeriod: payload.expire_grace_period,
user: payload.user ? bot.transformers.user(bot, payload.user) : undefined,
account: {
id: bot.transformers.snowflake(payload.account.id),
name: payload.account.name,
},
syncedAt: payload.synced_at ? Date.parse(payload.synced_at) : undefined,
subscriberCount: payload.subscriber_count,
revoked: payload.revoked,
application: payload.application
? {
id: bot.transformers.snowflake(payload.application.id),
name: payload.application.name,
icon: payload.application.icon ? iconHashToBigInt(payload.application.icon) : undefined,
description: payload.application.description,
bot: payload.application.bot ? bot.transformers.user(bot, payload.application.bot) : undefined,
}
: undefined,
scopes: payload.scopes,
}
return integration as Optionalize<typeof integration>
}
export interface Integration extends ReturnType<typeof transformIntegration> {}

Some files were not shown because too many files have changed in this diff Show More