Merge pull request #138 from DjDeveloperr/design-fix
BREAKING: Split up Interaction structure into different types
This commit is contained in:
commit
b686c02cdc
20 changed files with 636 additions and 477 deletions
30
deploy.ts
30
deploy.ts
|
@ -1,15 +1,20 @@
|
|||
import { Interaction } from './mod.ts'
|
||||
import {
|
||||
SlashCommandsManager,
|
||||
SlashClient,
|
||||
SlashCommandHandlerCallback,
|
||||
SlashCommandHandler
|
||||
} from './src/interactions/mod.ts'
|
||||
import { InteractionResponseType, InteractionType } from './src/types/slash.ts'
|
||||
import {
|
||||
InteractionResponseType,
|
||||
InteractionType
|
||||
} from './src/types/interactions.ts'
|
||||
|
||||
export interface DeploySlashInitOptions {
|
||||
env?: boolean
|
||||
publicKey?: string
|
||||
token?: string
|
||||
path?: string
|
||||
}
|
||||
|
||||
/** Current Slash Client being used to handle commands */
|
||||
|
@ -37,8 +42,12 @@ let commands: SlashCommandsManager
|
|||
*
|
||||
* @param options Initialization options
|
||||
*/
|
||||
export function init(options: { env: boolean }): void
|
||||
export function init(options: { publicKey: string; token?: string }): void
|
||||
export function init(options: { env: boolean; path?: string }): void
|
||||
export function init(options: {
|
||||
publicKey: string
|
||||
token?: string
|
||||
path?: string
|
||||
}): void
|
||||
export function init(options: DeploySlashInitOptions): void {
|
||||
if (client !== undefined) throw new Error('Already initialized')
|
||||
if (options.env === true) {
|
||||
|
@ -60,6 +69,9 @@ export function init(options: DeploySlashInitOptions): void {
|
|||
respondWith: CallableFunction
|
||||
request: Request
|
||||
}): Promise<void> => {
|
||||
if (options.path !== undefined) {
|
||||
if (new URL(evt.request.url).pathname !== options.path) return
|
||||
}
|
||||
try {
|
||||
// we have to wrap because there are some weird scope errors
|
||||
const d = await client.verifyFetchEvent({
|
||||
|
@ -124,8 +136,18 @@ export function handle(
|
|||
client.handle(cmd, handler)
|
||||
}
|
||||
|
||||
export function interactions(cb: (i: Interaction) => any): void {
|
||||
client.on('interaction', cb)
|
||||
}
|
||||
|
||||
export { commands, client }
|
||||
export * from './src/types/slash.ts'
|
||||
export * from './src/types/slashCommands.ts'
|
||||
export * from './src/types/interactions.ts'
|
||||
export * from './src/structures/slash.ts'
|
||||
export * from './src/interactions/mod.ts'
|
||||
export * from './src/types/channel.ts'
|
||||
export * from './src/types/messageComponents.ts'
|
||||
export * from './src/structures/interactions.ts'
|
||||
export * from './src/structures/messageComponents.ts'
|
||||
export * from './src/structures/message.ts'
|
||||
export * from './src/structures/embed.ts'
|
||||
|
|
7
mod.ts
7
mod.ts
|
@ -39,7 +39,9 @@ export { GuildChannelsManager } from './src/managers/guildChannels.ts'
|
|||
export { GuildManager } from './src/managers/guilds.ts'
|
||||
export * from './src/structures/base.ts'
|
||||
export * from './src/structures/slash.ts'
|
||||
export * from './src/types/slash.ts'
|
||||
export * from './src/structures/interactions.ts'
|
||||
export * from './src/types/slashCommands.ts'
|
||||
export * from './src/types/interactions.ts'
|
||||
export { GuildEmojisManager } from './src/managers/guildEmojis.ts'
|
||||
export { MembersManager } from './src/managers/members.ts'
|
||||
export { MessageReactionsManager } from './src/managers/messageReactions.ts'
|
||||
|
@ -191,4 +193,5 @@ export {
|
|||
isVoiceChannel,
|
||||
default as getChannelByType
|
||||
} from './src/utils/channel.ts'
|
||||
export * from "./src/utils/command.ts"
|
||||
export * from './src/utils/interactions.ts'
|
||||
export * from "./src/utils/command.ts"
|
||||
|
|
|
@ -1,17 +1,31 @@
|
|||
/* eslint-disable @typescript-eslint/no-unnecessary-type-assertion */
|
||||
import { Guild } from '../../structures/guild.ts'
|
||||
import { Member } from '../../structures/member.ts'
|
||||
import {
|
||||
Interaction,
|
||||
InteractionApplicationCommandResolved,
|
||||
InteractionChannel
|
||||
SlashCommandInteraction
|
||||
} from '../../structures/slash.ts'
|
||||
import {
|
||||
Interaction,
|
||||
InteractionChannel
|
||||
} from '../../structures/interactions.ts'
|
||||
import { GuildTextBasedChannel } from '../../structures/guildTextChannel.ts'
|
||||
import { InteractionPayload } from '../../types/slash.ts'
|
||||
import {
|
||||
InteractionPayload,
|
||||
InteractionType
|
||||
} from '../../types/interactions.ts'
|
||||
import { UserPayload } from '../../types/user.ts'
|
||||
import { Permissions } from '../../utils/permissions.ts'
|
||||
import type { Gateway, GatewayEventHandler } from '../mod.ts'
|
||||
import { User } from '../../structures/user.ts'
|
||||
import { Role } from '../../structures/role.ts'
|
||||
import { RolePayload } from '../../types/role.ts'
|
||||
import {
|
||||
InteractionApplicationCommandData,
|
||||
InteractionChannelPayload
|
||||
} from '../../types/slashCommands.ts'
|
||||
import { Message } from '../../structures/message.ts'
|
||||
import { TextChannel } from '../../structures/textChannel.ts'
|
||||
|
||||
export const interactionCreate: GatewayEventHandler = async (
|
||||
gateway: Gateway,
|
||||
|
@ -26,13 +40,22 @@ export const interactionCreate: GatewayEventHandler = async (
|
|||
const guild =
|
||||
d.guild_id === undefined
|
||||
? undefined
|
||||
: await gateway.client.guilds.get(d.guild_id)
|
||||
: (await gateway.client.guilds.get(d.guild_id)) ??
|
||||
new Guild(gateway.client, { unavailable: true, id: d.guild_id } as any)
|
||||
|
||||
if (d.member !== undefined)
|
||||
await guild?.members.set(d.member.user.id, d.member)
|
||||
const member =
|
||||
d.member !== undefined
|
||||
? (((await guild?.members.get(d.member.user.id)) as unknown) as Member)
|
||||
? (await guild?.members.get(d.member.user.id))! ??
|
||||
new Member(
|
||||
gateway.client,
|
||||
d.member!,
|
||||
new User(gateway.client, d.member.user),
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
guild!,
|
||||
new Permissions(d.member.permissions)
|
||||
)
|
||||
: undefined
|
||||
if (d.user !== undefined) await gateway.client.users.set(d.user.id, d.user)
|
||||
const dmUser =
|
||||
|
@ -41,9 +64,9 @@ export const interactionCreate: GatewayEventHandler = async (
|
|||
const user = member !== undefined ? member.user : dmUser
|
||||
if (user === undefined) return
|
||||
|
||||
const channel =
|
||||
(await gateway.client.channels.get<GuildTextBasedChannel>(d.channel_id)) ??
|
||||
(await gateway.client.channels.fetch<GuildTextBasedChannel>(d.channel_id))
|
||||
const channel = await gateway.client.channels.get<GuildTextBasedChannel>(
|
||||
d.channel_id
|
||||
)
|
||||
|
||||
const resolved: InteractionApplicationCommandResolved = {
|
||||
users: {},
|
||||
|
@ -52,9 +75,11 @@ export const interactionCreate: GatewayEventHandler = async (
|
|||
roles: {}
|
||||
}
|
||||
|
||||
if (d.data?.resolved !== undefined) {
|
||||
for (const [id, data] of Object.entries(d.data.resolved.users ?? {})) {
|
||||
await gateway.client.users.set(id, data)
|
||||
if ((d.data as InteractionApplicationCommandData)?.resolved !== undefined) {
|
||||
for (const [id, data] of Object.entries(
|
||||
(d.data as any)?.resolved.users ?? {}
|
||||
)) {
|
||||
await gateway.client.users.set(id, data as UserPayload)
|
||||
resolved.users[id] = ((await gateway.client.users.get(
|
||||
id
|
||||
)) as unknown) as User
|
||||
|
@ -62,49 +87,87 @@ export const interactionCreate: GatewayEventHandler = async (
|
|||
resolved.users[id].member = resolved.members[id]
|
||||
}
|
||||
|
||||
for (const [id, data] of Object.entries(d.data.resolved.members ?? {})) {
|
||||
for (const [id, data] of Object.entries(
|
||||
(d.data as InteractionApplicationCommandData)?.resolved?.members ?? {}
|
||||
)) {
|
||||
const roles = await guild?.roles.array()
|
||||
let permissions = new Permissions(Permissions.DEFAULT)
|
||||
if (roles !== undefined) {
|
||||
const mRoles = roles.filter(
|
||||
(r) => (data?.roles?.includes(r.id) as boolean) || r.id === guild?.id
|
||||
(r) =>
|
||||
((data as any)?.roles?.includes(r.id) as boolean) ||
|
||||
r.id === guild?.id
|
||||
)
|
||||
permissions = new Permissions(mRoles.map((r) => r.permissions))
|
||||
}
|
||||
data.user = (d.data.resolved.users?.[id] as unknown) as UserPayload
|
||||
;(data as any).user = ((d.data as any).resolved.users?.[
|
||||
id
|
||||
] as unknown) as UserPayload
|
||||
resolved.members[id] = new Member(
|
||||
gateway.client,
|
||||
data,
|
||||
data as any,
|
||||
resolved.users[id],
|
||||
guild as Guild,
|
||||
permissions
|
||||
)
|
||||
}
|
||||
|
||||
for (const [id, data] of Object.entries(d.data.resolved.roles ?? {})) {
|
||||
for (const [id, data] of Object.entries(
|
||||
(d.data as InteractionApplicationCommandData).resolved?.roles ?? {}
|
||||
)) {
|
||||
if (guild !== undefined) {
|
||||
await guild.roles.set(id, data)
|
||||
await guild.roles.set(id, data as RolePayload)
|
||||
resolved.roles[id] = ((await guild.roles.get(id)) as unknown) as Role
|
||||
} else {
|
||||
resolved.roles[id] = new Role(
|
||||
gateway.client,
|
||||
data,
|
||||
data as any,
|
||||
(guild as unknown) as Guild
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
for (const [id, data] of Object.entries(d.data.resolved.channels ?? {})) {
|
||||
resolved.channels[id] = new InteractionChannel(gateway.client, data)
|
||||
for (const [id, data] of Object.entries(
|
||||
(d.data as InteractionApplicationCommandData).resolved?.channels ?? {}
|
||||
)) {
|
||||
resolved.channels[id] = new InteractionChannel(
|
||||
gateway.client,
|
||||
data as InteractionChannelPayload
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const interaction = new Interaction(gateway.client, d, {
|
||||
member,
|
||||
guild,
|
||||
channel,
|
||||
user,
|
||||
resolved
|
||||
})
|
||||
let message: Message | undefined
|
||||
if (d.message !== undefined) {
|
||||
const channel = (await gateway.client.channels.get<TextChannel>(
|
||||
d.message.channel_id
|
||||
))!
|
||||
message = new Message(
|
||||
gateway.client,
|
||||
d.message,
|
||||
channel,
|
||||
new User(gateway.client, d.message.author)
|
||||
)
|
||||
}
|
||||
|
||||
let interaction
|
||||
if (d.type === InteractionType.APPLICATION_COMMAND) {
|
||||
interaction = new SlashCommandInteraction(gateway.client, d, {
|
||||
member,
|
||||
guild,
|
||||
channel,
|
||||
user,
|
||||
resolved
|
||||
})
|
||||
} else {
|
||||
interaction = new Interaction(gateway.client, d, {
|
||||
member,
|
||||
guild,
|
||||
channel,
|
||||
user,
|
||||
message
|
||||
})
|
||||
}
|
||||
|
||||
gateway.client.emit('interactionCreate', interaction)
|
||||
}
|
||||
|
|
|
@ -59,7 +59,8 @@ import type {
|
|||
EveryTextChannelTypes
|
||||
} from '../../utils/channel.ts'
|
||||
import { interactionCreate } from './interactionCreate.ts'
|
||||
import type { Interaction } from '../../structures/slash.ts'
|
||||
import type { Interaction } from '../../structures/interactions.ts'
|
||||
import type { SlashCommandInteraction } from '../../structures/slash.ts'
|
||||
import type { CommandContext } from '../../commands/command.ts'
|
||||
import type { RequestMethods } from '../../rest/types.ts'
|
||||
import type { PartialInvitePayload } from '../../types/invite.ts'
|
||||
|
@ -358,11 +359,12 @@ export type ClientEvents = {
|
|||
* @param channel Channel of which Webhooks were updated
|
||||
*/
|
||||
webhooksUpdate: [guild: Guild, channel: GuildTextBasedChannel]
|
||||
|
||||
/**
|
||||
* An Interaction was created
|
||||
* @param interaction Created interaction object
|
||||
*/
|
||||
interactionCreate: [interaction: Interaction]
|
||||
interactionCreate: [interaction: Interaction | SlashCommandInteraction]
|
||||
|
||||
/**
|
||||
* When debug message was made
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
import {
|
||||
Interaction,
|
||||
SlashCommandInteraction,
|
||||
InteractionApplicationCommandResolved
|
||||
} from '../structures/slash.ts'
|
||||
import { Interaction } from '../structures/interactions.ts'
|
||||
import {
|
||||
InteractionPayload,
|
||||
InteractionResponsePayload,
|
||||
InteractionType,
|
||||
SlashCommandOptionType
|
||||
} from '../types/slash.ts'
|
||||
InteractionType
|
||||
} from '../types/interactions.ts'
|
||||
import { SlashCommandOptionType } from '../types/slashCommands.ts'
|
||||
import type { Client } from '../client/mod.ts'
|
||||
import { RESTManager } from '../rest/mod.ts'
|
||||
import { SlashModule } from './slashModule.ts'
|
||||
|
@ -17,7 +18,9 @@ import { HarmonyEventEmitter } from '../utils/events.ts'
|
|||
import { encodeText, decodeText } from '../utils/encoding.ts'
|
||||
import { SlashCommandsManager } from './slashCommand.ts'
|
||||
|
||||
export type SlashCommandHandlerCallback = (interaction: Interaction) => unknown
|
||||
export type SlashCommandHandlerCallback = (
|
||||
interaction: SlashCommandInteraction
|
||||
) => unknown
|
||||
export interface SlashCommandHandler {
|
||||
name: string
|
||||
guild?: string
|
||||
|
@ -165,7 +168,9 @@ export class SlashClient extends HarmonyEventEmitter<SlashClientEvents> {
|
|||
}
|
||||
|
||||
/** Get Handler for an Interaction. Supports nested sub commands and sub command groups. */
|
||||
private _getCommand(i: Interaction): SlashCommandHandler | undefined {
|
||||
private _getCommand(
|
||||
i: SlashCommandInteraction
|
||||
): SlashCommandHandler | undefined {
|
||||
return this.getHandlers().find((e) => {
|
||||
const hasGroupOrParent = e.group !== undefined || e.parent !== undefined
|
||||
const groupMatched =
|
||||
|
@ -196,28 +201,28 @@ export class SlashClient extends HarmonyEventEmitter<SlashClientEvents> {
|
|||
}
|
||||
|
||||
/** Process an incoming Interaction */
|
||||
private async _process(interaction: Interaction): Promise<void> {
|
||||
private async _process(
|
||||
interaction: Interaction | SlashCommandInteraction
|
||||
): Promise<void> {
|
||||
if (!this.enabled) return
|
||||
|
||||
if (
|
||||
interaction.type !== InteractionType.APPLICATION_COMMAND ||
|
||||
interaction.data === undefined
|
||||
)
|
||||
return
|
||||
if (interaction.type !== InteractionType.APPLICATION_COMMAND) return
|
||||
|
||||
const cmd =
|
||||
this._getCommand(interaction) ??
|
||||
this._getCommand(interaction as SlashCommandInteraction) ??
|
||||
this.getHandlers().find((e) => e.name === '*')
|
||||
if (cmd?.group !== undefined)
|
||||
interaction.data.options = interaction.data.options[0].options ?? []
|
||||
(interaction as SlashCommandInteraction).data.options =
|
||||
(interaction as SlashCommandInteraction).data.options[0].options ?? []
|
||||
if (cmd?.parent !== undefined)
|
||||
interaction.data.options = interaction.data.options[0].options ?? []
|
||||
(interaction as SlashCommandInteraction).data.options =
|
||||
(interaction as SlashCommandInteraction).data.options[0].options ?? []
|
||||
|
||||
if (cmd === undefined) return
|
||||
|
||||
await this.emit('interaction', interaction)
|
||||
try {
|
||||
await cmd.handler(interaction)
|
||||
await cmd.handler(interaction as SlashCommandInteraction)
|
||||
} catch (e) {
|
||||
await this.emit('interactionError', e)
|
||||
}
|
||||
|
@ -266,20 +271,31 @@ export class SlashClient extends HarmonyEventEmitter<SlashClientEvents> {
|
|||
const payload: InteractionPayload = JSON.parse(decodeText(rawbody))
|
||||
|
||||
// TODO: Maybe fix all this hackery going on here?
|
||||
const res = new Interaction(this as any, payload, {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
user: new User(this as any, (payload.member?.user ?? payload.user)!),
|
||||
member: payload.member as any,
|
||||
guild: payload.guild_id as any,
|
||||
channel: payload.channel_id as any,
|
||||
resolved: ((payload.data
|
||||
?.resolved as unknown) as InteractionApplicationCommandResolved) ?? {
|
||||
users: {},
|
||||
members: {},
|
||||
roles: {},
|
||||
channels: {}
|
||||
}
|
||||
})
|
||||
let res
|
||||
if (payload.type === InteractionType.APPLICATION_COMMAND) {
|
||||
res = new SlashCommandInteraction(this as any, payload, {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
user: new User(this as any, (payload.member?.user ?? payload.user)!),
|
||||
member: payload.member as any,
|
||||
guild: payload.guild_id as any,
|
||||
channel: payload.channel_id as any,
|
||||
resolved: (((payload.data as any)
|
||||
?.resolved as unknown) as InteractionApplicationCommandResolved) ?? {
|
||||
users: {},
|
||||
members: {},
|
||||
roles: {},
|
||||
channels: {}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
res = new Interaction(this as any, payload, {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
user: new User(this as any, (payload.member?.user ?? payload.user)!),
|
||||
member: payload.member as any,
|
||||
guild: payload.guild_id as any,
|
||||
channel: payload.channel_id as any
|
||||
})
|
||||
}
|
||||
res._httpRespond = async (d: InteractionResponsePayload | FormData) =>
|
||||
await req.respond({
|
||||
status: 200,
|
||||
|
|
|
@ -6,7 +6,7 @@ import {
|
|||
SlashCommandOptionType,
|
||||
SlashCommandPartial,
|
||||
SlashCommandPayload
|
||||
} from '../types/slash.ts'
|
||||
} from '../types/slashCommands.ts'
|
||||
import { Collection } from '../utils/collection.ts'
|
||||
import type { SlashClient, SlashCommandHandlerCallback } from './slashClient.ts'
|
||||
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
export {}
|
|
@ -12,8 +12,6 @@ import type {
|
|||
import { CHANNEL } from '../types/endpoint.ts'
|
||||
import getChannelByType from '../utils/channel.ts'
|
||||
import { BaseManager } from './base.ts'
|
||||
// Deno is bugged
|
||||
import {} from './_util.ts'
|
||||
|
||||
export type AllMessageOptions = MessageOptions | Embed
|
||||
|
||||
|
|
|
@ -30,11 +30,11 @@ import type {
|
|||
InviteWithMetadataPayload
|
||||
} from '../types/invite.ts'
|
||||
import type { RoleModifyPayload, RolePayload } from '../types/role.ts'
|
||||
import type { InteractionResponsePayload } from '../types/interactions.ts'
|
||||
import type {
|
||||
InteractionResponsePayload,
|
||||
SlashCommandPartial,
|
||||
SlashCommandPayload
|
||||
} from '../types/slash.ts'
|
||||
} from '../types/slashCommands.ts'
|
||||
import type { TemplatePayload } from '../types/template.ts'
|
||||
import type { UserPayload } from '../types/user.ts'
|
||||
import type { VoiceRegion } from '../types/voice.ts'
|
||||
|
|
|
@ -13,7 +13,7 @@ export class DiscordAPIError extends Error {
|
|||
this.message =
|
||||
typeof error === 'string'
|
||||
? `${error} `
|
||||
: `\n${error.method.toUpperCase()} ${error.url.slice(7)} returned ${
|
||||
: `\n${error.method.toUpperCase()} ${error.url} returned ${
|
||||
error.status
|
||||
}\n(${error.code ?? 'unknown'}) ${error.message}${
|
||||
fmt.length === 0
|
||||
|
|
348
src/structures/interactions.ts
Normal file
348
src/structures/interactions.ts
Normal file
|
@ -0,0 +1,348 @@
|
|||
import type { Client } from '../client/client.ts'
|
||||
import {
|
||||
AllowedMentionsPayload,
|
||||
ChannelTypes,
|
||||
EmbedPayload,
|
||||
MessageOptions
|
||||
} from '../types/channel.ts'
|
||||
import { INTERACTION_CALLBACK, WEBHOOK_MESSAGE } from '../types/endpoint.ts'
|
||||
import {
|
||||
InteractionPayload,
|
||||
InteractionResponseFlags,
|
||||
InteractionResponsePayload,
|
||||
InteractionResponseType,
|
||||
InteractionType
|
||||
} from '../types/interactions.ts'
|
||||
import {
|
||||
InteractionApplicationCommandData,
|
||||
InteractionChannelPayload
|
||||
} from '../types/slashCommands.ts'
|
||||
import { Permissions } from '../utils/permissions.ts'
|
||||
import { SnowflakeBase } from './base.ts'
|
||||
import { Channel } from './channel.ts'
|
||||
import { Embed } from './embed.ts'
|
||||
import { Guild } from './guild.ts'
|
||||
import { GuildTextChannel } from './guildTextChannel.ts'
|
||||
import { Member } from './member.ts'
|
||||
import { Message } from './message.ts'
|
||||
import { TextChannel } from './textChannel.ts'
|
||||
import { User } from './user.ts'
|
||||
|
||||
interface WebhookMessageOptions extends MessageOptions {
|
||||
embeds?: Array<Embed | EmbedPayload>
|
||||
name?: string
|
||||
avatar?: string
|
||||
}
|
||||
|
||||
type AllWebhookMessageOptions = string | WebhookMessageOptions
|
||||
|
||||
/** Interaction Message related Options */
|
||||
export interface InteractionMessageOptions {
|
||||
content?: string
|
||||
embeds?: Array<Embed | EmbedPayload>
|
||||
tts?: boolean
|
||||
flags?: number | InteractionResponseFlags[]
|
||||
allowedMentions?: AllowedMentionsPayload
|
||||
/** Whether the Message Response should be Ephemeral (only visible to User) or not */
|
||||
ephemeral?: boolean
|
||||
}
|
||||
|
||||
export interface InteractionResponse extends InteractionMessageOptions {
|
||||
/** Type of Interaction Response */
|
||||
type?: InteractionResponseType
|
||||
}
|
||||
|
||||
/** Represents a Channel Object for an Option in Slash Command */
|
||||
export class InteractionChannel extends SnowflakeBase {
|
||||
/** Name of the Channel */
|
||||
name: string
|
||||
/** Channel Type */
|
||||
type: ChannelTypes
|
||||
permissions: Permissions
|
||||
|
||||
constructor(client: Client, data: InteractionChannelPayload) {
|
||||
super(client)
|
||||
this.id = data.id
|
||||
this.name = data.name
|
||||
this.type = data.type
|
||||
this.permissions = new Permissions(data.permissions)
|
||||
}
|
||||
|
||||
/** Resolve to actual Channel object if present in Cache */
|
||||
async resolve<T = Channel>(): Promise<T | undefined> {
|
||||
return this.client.channels.get<T>(this.id)
|
||||
}
|
||||
}
|
||||
|
||||
export class InteractionUser extends User {
|
||||
member?: Member
|
||||
}
|
||||
|
||||
export class Interaction extends SnowflakeBase {
|
||||
/** Type of Interaction */
|
||||
type: InteractionType
|
||||
/** Interaction Token */
|
||||
token: string
|
||||
/** Interaction ID */
|
||||
id: string
|
||||
/** Channel in which Interaction was initiated */
|
||||
channel?: TextChannel | GuildTextChannel
|
||||
/** Guild in which Interaction was initiated */
|
||||
guild?: Guild
|
||||
/** Member object of who initiated the Interaction */
|
||||
member?: Member
|
||||
/** User object of who invoked Interaction */
|
||||
user: User
|
||||
/** Whether we have responded to Interaction or not */
|
||||
responded: boolean = false
|
||||
/** Whether response was deferred or not */
|
||||
deferred: boolean = false
|
||||
_httpRespond?: (d: InteractionResponsePayload) => unknown
|
||||
_httpResponded?: boolean
|
||||
applicationID: string
|
||||
/** Data sent with Interaction. Only applies to Application Command */
|
||||
data?: InteractionApplicationCommandData
|
||||
message?: Message
|
||||
|
||||
constructor(
|
||||
client: Client,
|
||||
data: InteractionPayload,
|
||||
others: {
|
||||
channel?: TextChannel | GuildTextChannel
|
||||
guild?: Guild
|
||||
member?: Member
|
||||
user: User
|
||||
message?: Message
|
||||
}
|
||||
) {
|
||||
super(client)
|
||||
this.type = data.type
|
||||
this.token = data.token
|
||||
this.member = others.member
|
||||
this.id = data.id
|
||||
this.applicationID = data.application_id
|
||||
this.user = others.user
|
||||
this.data = data.data
|
||||
this.guild = others.guild
|
||||
this.channel = others.channel
|
||||
this.message = others.message
|
||||
}
|
||||
|
||||
/** Respond to an Interaction */
|
||||
async respond(data: InteractionResponse): Promise<Interaction> {
|
||||
if (this.responded) throw new Error('Already responded to Interaction')
|
||||
let flags = 0
|
||||
if (data.ephemeral === true) flags |= InteractionResponseFlags.EPHEMERAL
|
||||
if (data.flags !== undefined) {
|
||||
if (Array.isArray(data.flags))
|
||||
flags = data.flags.reduce((p, a) => p | a, flags)
|
||||
else if (typeof data.flags === 'number') flags |= data.flags
|
||||
}
|
||||
const payload: InteractionResponsePayload = {
|
||||
type: data.type ?? InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE,
|
||||
data:
|
||||
data.type === undefined ||
|
||||
data.type === InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE
|
||||
? {
|
||||
content: data.content ?? '',
|
||||
embeds: data.embeds,
|
||||
tts: data.tts ?? false,
|
||||
flags,
|
||||
allowed_mentions: data.allowedMentions ?? undefined
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
|
||||
if (this._httpRespond !== undefined && this._httpResponded !== true) {
|
||||
this._httpResponded = true
|
||||
await this._httpRespond(payload)
|
||||
} else
|
||||
await this.client.rest.post(
|
||||
INTERACTION_CALLBACK(this.id, this.token),
|
||||
payload
|
||||
)
|
||||
this.responded = true
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
/** Defer the Interaction i.e. let the user know bot is processing and will respond later. You only have 15 minutes to edit the response! */
|
||||
async defer(ephemeral = false): Promise<Interaction> {
|
||||
await this.respond({
|
||||
type: InteractionResponseType.DEFERRED_CHANNEL_MESSAGE,
|
||||
flags: ephemeral ? 1 << 6 : 0
|
||||
})
|
||||
this.deferred = true
|
||||
return this
|
||||
}
|
||||
|
||||
/** Reply with a Message to the Interaction */
|
||||
async reply(content: string): Promise<Interaction>
|
||||
async reply(options: InteractionMessageOptions): Promise<Interaction>
|
||||
async reply(
|
||||
content: string,
|
||||
options: InteractionMessageOptions
|
||||
): Promise<Interaction>
|
||||
async reply(
|
||||
content: string | InteractionMessageOptions,
|
||||
messageOptions?: InteractionMessageOptions
|
||||
): Promise<Interaction> {
|
||||
let options: InteractionMessageOptions | undefined =
|
||||
typeof content === 'object' ? content : messageOptions
|
||||
if (
|
||||
typeof content === 'object' &&
|
||||
messageOptions !== undefined &&
|
||||
options !== undefined
|
||||
)
|
||||
Object.assign(options, messageOptions)
|
||||
if (options === undefined) options = {}
|
||||
if (typeof content === 'string') Object.assign(options, { content })
|
||||
|
||||
if (this.deferred && this.responded) {
|
||||
await this.editResponse({
|
||||
content: options.content,
|
||||
embeds: options.embeds,
|
||||
flags: options.flags,
|
||||
allowedMentions: options.allowedMentions
|
||||
})
|
||||
} else
|
||||
await this.respond(
|
||||
Object.assign(options, {
|
||||
type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE
|
||||
})
|
||||
)
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
/** Edit the original Interaction response */
|
||||
async editResponse(data: {
|
||||
content?: string
|
||||
embeds?: Array<Embed | EmbedPayload>
|
||||
flags?: number | number[]
|
||||
allowedMentions?: AllowedMentionsPayload
|
||||
}): Promise<Interaction> {
|
||||
const url = WEBHOOK_MESSAGE(this.applicationID, this.token, '@original')
|
||||
await this.client.rest.patch(url, {
|
||||
content: data.content ?? '',
|
||||
embeds: data.embeds ?? [],
|
||||
flags:
|
||||
typeof data.flags === 'object'
|
||||
? data.flags.reduce((p, a) => p | a, 0)
|
||||
: data.flags,
|
||||
allowed_mentions: data.allowedMentions
|
||||
})
|
||||
return this
|
||||
}
|
||||
|
||||
/** Delete the original Interaction Response */
|
||||
async deleteResponse(): Promise<Interaction> {
|
||||
const url = WEBHOOK_MESSAGE(this.applicationID, this.token, '@original')
|
||||
await this.client.rest.delete(url)
|
||||
return this
|
||||
}
|
||||
|
||||
get url(): string {
|
||||
return `https://discord.com/api/v8/webhooks/${this.applicationID}/${this.token}`
|
||||
}
|
||||
|
||||
/** Send a followup message */
|
||||
async send(
|
||||
text?: string | AllWebhookMessageOptions,
|
||||
option?: AllWebhookMessageOptions
|
||||
): Promise<Message> {
|
||||
if (typeof text === 'object') {
|
||||
option = text
|
||||
text = undefined
|
||||
}
|
||||
|
||||
if (text === undefined && option === undefined) {
|
||||
throw new Error('Either text or option is necessary.')
|
||||
}
|
||||
|
||||
if (option instanceof Embed)
|
||||
option = {
|
||||
embeds: [option]
|
||||
}
|
||||
|
||||
const payload: any = {
|
||||
content: text,
|
||||
embeds:
|
||||
(option as WebhookMessageOptions)?.embed !== undefined
|
||||
? [(option as WebhookMessageOptions).embed]
|
||||
: (option as WebhookMessageOptions)?.embeds !== undefined
|
||||
? (option as WebhookMessageOptions).embeds
|
||||
: undefined,
|
||||
file: (option as WebhookMessageOptions)?.file,
|
||||
files: (option as WebhookMessageOptions)?.files,
|
||||
tts: (option as WebhookMessageOptions)?.tts,
|
||||
allowed_mentions: (option as WebhookMessageOptions)?.allowedMentions
|
||||
}
|
||||
|
||||
if ((option as WebhookMessageOptions)?.name !== undefined) {
|
||||
payload.username = (option as WebhookMessageOptions)?.name
|
||||
}
|
||||
|
||||
if ((option as WebhookMessageOptions)?.avatar !== undefined) {
|
||||
payload.avatar = (option as WebhookMessageOptions)?.avatar
|
||||
}
|
||||
|
||||
if (
|
||||
payload.embeds !== undefined &&
|
||||
payload.embeds instanceof Array &&
|
||||
payload.embeds.length > 10
|
||||
)
|
||||
throw new Error(
|
||||
`Cannot send more than 10 embeds through Interaction Webhook`
|
||||
)
|
||||
|
||||
const resp = await this.client.rest.post(`${this.url}?wait=true`, payload)
|
||||
|
||||
const res = new Message(
|
||||
this.client,
|
||||
resp,
|
||||
(this as unknown) as TextChannel,
|
||||
(this as unknown) as User
|
||||
)
|
||||
await res.mentions.fromPayload(resp)
|
||||
return res
|
||||
}
|
||||
|
||||
/** Edit a Followup message */
|
||||
async editMessage(
|
||||
msg: Message | string,
|
||||
data: {
|
||||
content?: string
|
||||
embeds?: Array<Embed | EmbedPayload>
|
||||
file?: any
|
||||
allowed_mentions?: {
|
||||
parse?: string
|
||||
roles?: string[]
|
||||
users?: string[]
|
||||
everyone?: boolean
|
||||
}
|
||||
}
|
||||
): Promise<Interaction> {
|
||||
await this.client.rest.patch(
|
||||
WEBHOOK_MESSAGE(
|
||||
this.applicationID,
|
||||
this.token ?? this.client.token,
|
||||
typeof msg === 'string' ? msg : msg.id
|
||||
),
|
||||
data
|
||||
)
|
||||
return this
|
||||
}
|
||||
|
||||
/** Delete a follow-up Message */
|
||||
async deleteMessage(msg: Message | string): Promise<Interaction> {
|
||||
await this.client.rest.delete(
|
||||
WEBHOOK_MESSAGE(
|
||||
this.applicationID,
|
||||
this.token ?? this.client.token,
|
||||
typeof msg === 'string' ? msg : msg.id
|
||||
)
|
||||
)
|
||||
return this
|
||||
}
|
||||
}
|
|
@ -20,7 +20,7 @@ import type { Guild } from './guild.ts'
|
|||
import { MessageReactionsManager } from '../managers/messageReactions.ts'
|
||||
import { MessageSticker } from './messageSticker.ts'
|
||||
import type { Emoji } from './emoji.ts'
|
||||
import type { InteractionType } from '../types/slash.ts'
|
||||
import type { InteractionType } from '../types/interactions.ts'
|
||||
import { encodeText } from '../utils/encoding.ts'
|
||||
|
||||
type AllMessageOptions = MessageOptions | Embed
|
||||
|
|
|
@ -1,80 +1,22 @@
|
|||
import type { Client } from '../client/mod.ts'
|
||||
import type {
|
||||
AllowedMentionsPayload,
|
||||
ChannelTypes,
|
||||
EmbedPayload,
|
||||
MessageOptions
|
||||
} from '../types/channel.ts'
|
||||
import { INTERACTION_CALLBACK, WEBHOOK_MESSAGE } from '../types/endpoint.ts'
|
||||
import { InteractionPayload } from '../types/interactions.ts'
|
||||
import {
|
||||
InteractionApplicationCommandData,
|
||||
InteractionApplicationCommandOption,
|
||||
InteractionChannelPayload,
|
||||
InteractionPayload,
|
||||
InteractionResponseFlags,
|
||||
InteractionResponsePayload,
|
||||
InteractionResponseType,
|
||||
InteractionType,
|
||||
SlashCommandOptionType
|
||||
} from '../types/slash.ts'
|
||||
} from '../types/slashCommands.ts'
|
||||
import type { Dict } from '../utils/dict.ts'
|
||||
import { Permissions } from '../utils/permissions.ts'
|
||||
import { SnowflakeBase } from './base.ts'
|
||||
import type { Channel } from './channel.ts'
|
||||
import { Embed } from './embed.ts'
|
||||
import type { Guild } from './guild.ts'
|
||||
import type { GuildTextChannel } from './guildTextChannel.ts'
|
||||
import type { Member } from './member.ts'
|
||||
import { Message } from './message.ts'
|
||||
import type { Role } from './role.ts'
|
||||
import type { TextChannel } from './textChannel.ts'
|
||||
import { User } from './user.ts'
|
||||
|
||||
interface WebhookMessageOptions extends MessageOptions {
|
||||
embeds?: Array<Embed | EmbedPayload>
|
||||
name?: string
|
||||
avatar?: string
|
||||
}
|
||||
|
||||
type AllWebhookMessageOptions = string | WebhookMessageOptions
|
||||
|
||||
/** Interaction Message related Options */
|
||||
export interface InteractionMessageOptions {
|
||||
content?: string
|
||||
embeds?: Array<Embed | EmbedPayload>
|
||||
tts?: boolean
|
||||
flags?: number | InteractionResponseFlags[]
|
||||
allowedMentions?: AllowedMentionsPayload
|
||||
/** Whether the Message Response should be Ephemeral (only visible to User) or not */
|
||||
ephemeral?: boolean
|
||||
}
|
||||
|
||||
export interface InteractionResponse extends InteractionMessageOptions {
|
||||
/** Type of Interaction Response */
|
||||
type?: InteractionResponseType
|
||||
}
|
||||
|
||||
/** Represents a Channel Object for an Option in Slash Command */
|
||||
export class InteractionChannel extends SnowflakeBase {
|
||||
/** Name of the Channel */
|
||||
name: string
|
||||
/** Channel Type */
|
||||
type: ChannelTypes
|
||||
permissions: Permissions
|
||||
|
||||
constructor(client: Client, data: InteractionChannelPayload) {
|
||||
super(client)
|
||||
this.id = data.id
|
||||
this.name = data.name
|
||||
this.type = data.type
|
||||
this.permissions = new Permissions(data.permissions)
|
||||
}
|
||||
|
||||
/** Resolve to actual Channel object if present in Cache */
|
||||
async resolve<T = Channel>(): Promise<T | undefined> {
|
||||
return this.client.channels.get<T>(this.id)
|
||||
}
|
||||
}
|
||||
import {
|
||||
InteractionUser,
|
||||
InteractionChannel,
|
||||
Interaction
|
||||
} from './interactions.ts'
|
||||
|
||||
export interface InteractionApplicationCommandResolved {
|
||||
users: Dict<InteractionUser>
|
||||
|
@ -83,36 +25,11 @@ export interface InteractionApplicationCommandResolved {
|
|||
roles: Dict<Role>
|
||||
}
|
||||
|
||||
export class InteractionUser extends User {
|
||||
member?: Member
|
||||
}
|
||||
|
||||
export class Interaction extends SnowflakeBase {
|
||||
/** Type of Interaction */
|
||||
type: InteractionType
|
||||
/** Interaction Token */
|
||||
token: string
|
||||
/** Interaction ID */
|
||||
id: string
|
||||
export class SlashCommandInteraction extends Interaction {
|
||||
/** Data sent with Interaction. Only applies to Application Command */
|
||||
data?: InteractionApplicationCommandData
|
||||
/** Channel in which Interaction was initiated */
|
||||
channel?: TextChannel | GuildTextChannel
|
||||
/** Guild in which Interaction was initiated */
|
||||
guild?: Guild
|
||||
/** Member object of who initiated the Interaction */
|
||||
member?: Member
|
||||
/** User object of who invoked Interaction */
|
||||
user: User
|
||||
/** Whether we have responded to Interaction or not */
|
||||
responded: boolean = false
|
||||
data: InteractionApplicationCommandData
|
||||
/** Resolved data for Snowflakes in Slash Command Arguments */
|
||||
resolved: InteractionApplicationCommandResolved
|
||||
/** Whether response was deferred or not */
|
||||
deferred: boolean = false
|
||||
_httpRespond?: (d: InteractionResponsePayload) => unknown
|
||||
_httpResponded?: boolean
|
||||
applicationID: string
|
||||
|
||||
constructor(
|
||||
client: Client,
|
||||
|
@ -125,26 +42,19 @@ export class Interaction extends SnowflakeBase {
|
|||
resolved: InteractionApplicationCommandResolved
|
||||
}
|
||||
) {
|
||||
super(client)
|
||||
this.type = data.type
|
||||
this.token = data.token
|
||||
this.member = others.member
|
||||
this.id = data.id
|
||||
this.applicationID = data.application_id
|
||||
this.user = others.user
|
||||
this.data = data.data
|
||||
this.guild = others.guild
|
||||
this.channel = others.channel
|
||||
super(client, data, others)
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
this.data = data.data as InteractionApplicationCommandData
|
||||
this.resolved = others.resolved
|
||||
}
|
||||
|
||||
/** Name of the Command Used (may change with future additions to Interactions!) */
|
||||
get name(): string | undefined {
|
||||
return this.data?.name
|
||||
get name(): string {
|
||||
return this.data.name
|
||||
}
|
||||
|
||||
get options(): InteractionApplicationCommandOption[] {
|
||||
return this.data?.options ?? []
|
||||
return this.data.options ?? []
|
||||
}
|
||||
|
||||
/** Get an option by name */
|
||||
|
@ -162,222 +72,4 @@ export class Interaction extends SnowflakeBase {
|
|||
return this.resolved.channels[op.value] as any
|
||||
else return op.value
|
||||
}
|
||||
|
||||
/** Respond to an Interaction */
|
||||
async respond(data: InteractionResponse): Promise<Interaction> {
|
||||
if (this.responded) throw new Error('Already responded to Interaction')
|
||||
let flags = 0
|
||||
if (data.ephemeral === true) flags |= InteractionResponseFlags.EPHEMERAL
|
||||
if (data.flags !== undefined) {
|
||||
if (Array.isArray(data.flags))
|
||||
flags = data.flags.reduce((p, a) => p | a, flags)
|
||||
else if (typeof data.flags === 'number') flags |= data.flags
|
||||
}
|
||||
const payload: InteractionResponsePayload = {
|
||||
type: data.type ?? InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE,
|
||||
data:
|
||||
data.type === undefined ||
|
||||
data.type === InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE
|
||||
? {
|
||||
content: data.content ?? '',
|
||||
embeds: data.embeds,
|
||||
tts: data.tts ?? false,
|
||||
flags,
|
||||
allowed_mentions: data.allowedMentions ?? undefined
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
|
||||
if (this._httpRespond !== undefined && this._httpResponded !== true) {
|
||||
this._httpResponded = true
|
||||
await this._httpRespond(payload)
|
||||
} else
|
||||
await this.client.rest.post(
|
||||
INTERACTION_CALLBACK(this.id, this.token),
|
||||
payload
|
||||
)
|
||||
this.responded = true
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
/** Defer the Interaction i.e. let the user know bot is processing and will respond later. You only have 15 minutes to edit the response! */
|
||||
async defer(ephemeral = false): Promise<Interaction> {
|
||||
await this.respond({
|
||||
type: InteractionResponseType.DEFERRED_CHANNEL_MESSAGE,
|
||||
flags: ephemeral ? 1 << 6 : 0
|
||||
})
|
||||
this.deferred = true
|
||||
return this
|
||||
}
|
||||
|
||||
/** Reply with a Message to the Interaction */
|
||||
async reply(content: string): Promise<Interaction>
|
||||
async reply(options: InteractionMessageOptions): Promise<Interaction>
|
||||
async reply(
|
||||
content: string,
|
||||
options: InteractionMessageOptions
|
||||
): Promise<Interaction>
|
||||
async reply(
|
||||
content: string | InteractionMessageOptions,
|
||||
messageOptions?: InteractionMessageOptions
|
||||
): Promise<Interaction> {
|
||||
let options: InteractionMessageOptions | undefined =
|
||||
typeof content === 'object' ? content : messageOptions
|
||||
if (
|
||||
typeof content === 'object' &&
|
||||
messageOptions !== undefined &&
|
||||
options !== undefined
|
||||
)
|
||||
Object.assign(options, messageOptions)
|
||||
if (options === undefined) options = {}
|
||||
if (typeof content === 'string') Object.assign(options, { content })
|
||||
|
||||
if (this.deferred && this.responded) {
|
||||
await this.editResponse({
|
||||
content: options.content,
|
||||
embeds: options.embeds,
|
||||
flags: options.flags,
|
||||
allowedMentions: options.allowedMentions
|
||||
})
|
||||
} else
|
||||
await this.respond(
|
||||
Object.assign(options, {
|
||||
type: InteractionResponseType.CHANNEL_MESSAGE_WITH_SOURCE
|
||||
})
|
||||
)
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
/** Edit the original Interaction response */
|
||||
async editResponse(data: {
|
||||
content?: string
|
||||
embeds?: Array<Embed | EmbedPayload>
|
||||
flags?: number | number[]
|
||||
allowedMentions?: AllowedMentionsPayload
|
||||
}): Promise<Interaction> {
|
||||
const url = WEBHOOK_MESSAGE(this.applicationID, this.token, '@original')
|
||||
await this.client.rest.patch(url, {
|
||||
content: data.content ?? '',
|
||||
embeds: data.embeds ?? [],
|
||||
flags:
|
||||
typeof data.flags === 'object'
|
||||
? data.flags.reduce((p, a) => p | a, 0)
|
||||
: data.flags,
|
||||
allowed_mentions: data.allowedMentions
|
||||
})
|
||||
return this
|
||||
}
|
||||
|
||||
/** Delete the original Interaction Response */
|
||||
async deleteResponse(): Promise<Interaction> {
|
||||
const url = WEBHOOK_MESSAGE(this.applicationID, this.token, '@original')
|
||||
await this.client.rest.delete(url)
|
||||
return this
|
||||
}
|
||||
|
||||
get url(): string {
|
||||
return `https://discord.com/api/v8/webhooks/${this.applicationID}/${this.token}`
|
||||
}
|
||||
|
||||
/** Send a followup message */
|
||||
async send(
|
||||
text?: string | AllWebhookMessageOptions,
|
||||
option?: AllWebhookMessageOptions
|
||||
): Promise<Message> {
|
||||
if (typeof text === 'object') {
|
||||
option = text
|
||||
text = undefined
|
||||
}
|
||||
|
||||
if (text === undefined && option === undefined) {
|
||||
throw new Error('Either text or option is necessary.')
|
||||
}
|
||||
|
||||
if (option instanceof Embed)
|
||||
option = {
|
||||
embeds: [option]
|
||||
}
|
||||
|
||||
const payload: any = {
|
||||
content: text,
|
||||
embeds:
|
||||
(option as WebhookMessageOptions)?.embed !== undefined
|
||||
? [(option as WebhookMessageOptions).embed]
|
||||
: (option as WebhookMessageOptions)?.embeds !== undefined
|
||||
? (option as WebhookMessageOptions).embeds
|
||||
: undefined,
|
||||
file: (option as WebhookMessageOptions)?.file,
|
||||
files: (option as WebhookMessageOptions)?.files,
|
||||
tts: (option as WebhookMessageOptions)?.tts,
|
||||
allowed_mentions: (option as WebhookMessageOptions)?.allowedMentions
|
||||
}
|
||||
|
||||
if ((option as WebhookMessageOptions)?.name !== undefined) {
|
||||
payload.username = (option as WebhookMessageOptions)?.name
|
||||
}
|
||||
|
||||
if ((option as WebhookMessageOptions)?.avatar !== undefined) {
|
||||
payload.avatar = (option as WebhookMessageOptions)?.avatar
|
||||
}
|
||||
|
||||
if (
|
||||
payload.embeds !== undefined &&
|
||||
payload.embeds instanceof Array &&
|
||||
payload.embeds.length > 10
|
||||
)
|
||||
throw new Error(
|
||||
`Cannot send more than 10 embeds through Interaction Webhook`
|
||||
)
|
||||
|
||||
const resp = await this.client.rest.post(`${this.url}?wait=true`, payload)
|
||||
|
||||
const res = new Message(
|
||||
this.client,
|
||||
resp,
|
||||
(this as unknown) as TextChannel,
|
||||
(this as unknown) as User
|
||||
)
|
||||
await res.mentions.fromPayload(resp)
|
||||
return res
|
||||
}
|
||||
|
||||
/** Edit a Followup message */
|
||||
async editMessage(
|
||||
msg: Message | string,
|
||||
data: {
|
||||
content?: string
|
||||
embeds?: Array<Embed | EmbedPayload>
|
||||
file?: any
|
||||
allowed_mentions?: {
|
||||
parse?: string
|
||||
roles?: string[]
|
||||
users?: string[]
|
||||
everyone?: boolean
|
||||
}
|
||||
}
|
||||
): Promise<Interaction> {
|
||||
await this.client.rest.patch(
|
||||
WEBHOOK_MESSAGE(
|
||||
this.applicationID,
|
||||
this.token ?? this.client.token,
|
||||
typeof msg === 'string' ? msg : msg.id
|
||||
),
|
||||
data
|
||||
)
|
||||
return this
|
||||
}
|
||||
|
||||
/** Delete a follow-up Message */
|
||||
async deleteMessage(msg: Message | string): Promise<Interaction> {
|
||||
await this.client.rest.delete(
|
||||
WEBHOOK_MESSAGE(
|
||||
this.applicationID,
|
||||
this.token ?? this.client.token,
|
||||
typeof msg === 'string' ? msg : msg.id
|
||||
)
|
||||
)
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import type { Role } from '../structures/role.ts'
|
|||
import type { Permissions } from '../utils/permissions.ts'
|
||||
import type { EmojiPayload } from './emoji.ts'
|
||||
import type { MemberPayload } from './guild.ts'
|
||||
import type { InteractionType } from './slash.ts'
|
||||
import type { InteractionType } from './interactions.ts'
|
||||
import type { UserPayload } from './user.ts'
|
||||
|
||||
export interface ChannelPayload {
|
||||
|
|
|
@ -11,7 +11,7 @@ import type {
|
|||
ClientStatus
|
||||
} from './presence.ts'
|
||||
import type { RolePayload } from './role.ts'
|
||||
import type { SlashCommandPayload } from './slash.ts'
|
||||
import type { SlashCommandPayload } from './slashCommands.ts'
|
||||
import type { UserPayload } from './user.ts'
|
||||
|
||||
/**
|
||||
|
|
77
src/types/interactions.ts
Normal file
77
src/types/interactions.ts
Normal file
|
@ -0,0 +1,77 @@
|
|||
import {
|
||||
AllowedMentionsPayload,
|
||||
EmbedPayload,
|
||||
MessagePayload
|
||||
} from './channel.ts'
|
||||
import type { MemberPayload } from './guild.ts'
|
||||
import type { InteractionApplicationCommandData } from './slashCommands.ts'
|
||||
import type { UserPayload } from './user.ts'
|
||||
|
||||
export enum InteractionType {
|
||||
/** Ping sent by the API (HTTP-only) */
|
||||
PING = 1,
|
||||
/** Slash Command Interaction */
|
||||
APPLICATION_COMMAND = 2
|
||||
}
|
||||
|
||||
export interface InteractionMemberPayload extends MemberPayload {
|
||||
/** Permissions of the Member who initiated Interaction (Guild-only) */
|
||||
permissions: string
|
||||
}
|
||||
|
||||
export interface InteractionPayload {
|
||||
/** Type of the Interaction */
|
||||
type: InteractionType
|
||||
/** Token of the Interaction to respond */
|
||||
token: string
|
||||
/** Member object of user who invoked */
|
||||
member?: InteractionMemberPayload
|
||||
/** User who initiated Interaction (only in DMs) */
|
||||
user?: UserPayload
|
||||
/** ID of the Interaction */
|
||||
id: string
|
||||
/**
|
||||
* Data sent with the interaction. Undefined only when Interaction is PING (http-only).*
|
||||
*/
|
||||
data?: InteractionApplicationCommandData
|
||||
/** ID of the Guild in which Interaction was invoked */
|
||||
guild_id?: string
|
||||
/** ID of the Channel in which Interaction was invoked */
|
||||
channel_id?: string
|
||||
/** Application ID of the Client who received interaction */
|
||||
application_id: string
|
||||
/** Message ID if the Interaction was of type MESSAGE_COMPONENT */
|
||||
message?: MessagePayload
|
||||
}
|
||||
|
||||
export enum InteractionResponseType {
|
||||
/** Just ack a ping, Http-only. */
|
||||
PONG = 1,
|
||||
/** Send a channel message as response. */
|
||||
CHANNEL_MESSAGE_WITH_SOURCE = 4,
|
||||
/** Let the user know bot is processing ("thinking") and you can edit the response later */
|
||||
DEFERRED_CHANNEL_MESSAGE = 5
|
||||
}
|
||||
|
||||
export interface InteractionResponsePayload {
|
||||
/** Type of the response */
|
||||
type: InteractionResponseType
|
||||
/** Data to be sent with response. Optional for types: Pong, Acknowledge, Ack with Source */
|
||||
data?: InteractionResponseDataPayload
|
||||
}
|
||||
|
||||
export interface InteractionResponseDataPayload {
|
||||
tts?: boolean
|
||||
/** Text content of the Response (Message) */
|
||||
content: string
|
||||
/** Upto 10 Embed Objects to send with Response */
|
||||
embeds?: EmbedPayload[]
|
||||
/** Allowed Mentions object */
|
||||
allowed_mentions?: AllowedMentionsPayload
|
||||
flags?: number
|
||||
}
|
||||
|
||||
export enum InteractionResponseFlags {
|
||||
/** A Message which is only visible to Interaction User. */
|
||||
EPHEMERAL = 1 << 6
|
||||
}
|
|
@ -1,9 +1,5 @@
|
|||
import type { Dict } from '../utils/dict.ts'
|
||||
import type {
|
||||
AllowedMentionsPayload,
|
||||
ChannelTypes,
|
||||
EmbedPayload
|
||||
} from './channel.ts'
|
||||
import type { ChannelTypes } from './channel.ts'
|
||||
import type { MemberPayload } from './guild.ts'
|
||||
import type { RolePayload } from './role.ts'
|
||||
import type { UserPayload } from './user.ts'
|
||||
|
@ -44,40 +40,6 @@ export interface InteractionApplicationCommandData {
|
|||
resolved?: InteractionApplicationCommandResolvedPayload
|
||||
}
|
||||
|
||||
export enum InteractionType {
|
||||
/** Ping sent by the API (HTTP-only) */
|
||||
PING = 1,
|
||||
/** Slash Command Interaction */
|
||||
APPLICATION_COMMAND = 2
|
||||
}
|
||||
|
||||
export interface InteractionMemberPayload extends MemberPayload {
|
||||
/** Permissions of the Member who initiated Interaction (Guild-only) */
|
||||
permissions: string
|
||||
}
|
||||
|
||||
export interface InteractionPayload {
|
||||
/** Type of the Interaction */
|
||||
type: InteractionType
|
||||
/** Token of the Interaction to respond */
|
||||
token: string
|
||||
/** Member object of user who invoked */
|
||||
member?: InteractionMemberPayload
|
||||
/** User who initiated Interaction (only in DMs) */
|
||||
user?: UserPayload
|
||||
/** ID of the Interaction */
|
||||
id: string
|
||||
/**
|
||||
* Data sent with the interaction. Undefined only when Interaction is not Slash Command.*
|
||||
*/
|
||||
data?: InteractionApplicationCommandData
|
||||
/** ID of the Guild in which Interaction was invoked */
|
||||
guild_id?: string
|
||||
/** ID of the Channel in which Interaction was invoked */
|
||||
channel_id?: string
|
||||
application_id: string
|
||||
}
|
||||
|
||||
export interface SlashCommandChoice {
|
||||
/** (Display) name of the Choice */
|
||||
name: string
|
||||
|
@ -131,35 +93,3 @@ export interface SlashCommandPayload extends SlashCommandPartial {
|
|||
/** Application ID */
|
||||
application_id: string
|
||||
}
|
||||
|
||||
export enum InteractionResponseType {
|
||||
/** Just ack a ping, Http-only. */
|
||||
PONG = 1,
|
||||
/** Send a channel message as response. */
|
||||
CHANNEL_MESSAGE_WITH_SOURCE = 4,
|
||||
/** Let the user know bot is processing ("thinking") and you can edit the response later */
|
||||
DEFERRED_CHANNEL_MESSAGE = 5
|
||||
}
|
||||
|
||||
export interface InteractionResponsePayload {
|
||||
/** Type of the response */
|
||||
type: InteractionResponseType
|
||||
/** Data to be sent with response. Optional for types: Pong, Acknowledge, Ack with Source */
|
||||
data?: InteractionResponseDataPayload
|
||||
}
|
||||
|
||||
export interface InteractionResponseDataPayload {
|
||||
tts?: boolean
|
||||
/** Text content of the Response (Message) */
|
||||
content: string
|
||||
/** Upto 10 Embed Objects to send with Response */
|
||||
embeds?: EmbedPayload[]
|
||||
/** Allowed Mentions object */
|
||||
allowed_mentions?: AllowedMentionsPayload
|
||||
flags?: number
|
||||
}
|
||||
|
||||
export enum InteractionResponseFlags {
|
||||
/** A Message which is only visible to Interaction User. */
|
||||
EPHEMERAL = 1 << 6
|
||||
}
|
|
@ -12,7 +12,7 @@ export function simplifyAPIError(errors: any): SimplifiedError {
|
|||
const arrayIndex = !isNaN(Number(obj[0]))
|
||||
if (arrayIndex) obj[0] = `[${obj[0]}]`
|
||||
if (acum !== '' && !arrayIndex) acum += '.'
|
||||
fmt(obj[1], (acum += obj[0]))
|
||||
fmt(obj[1], acum + obj[0])
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
9
src/utils/interactions.ts
Normal file
9
src/utils/interactions.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
import { InteractionType } from '../../mod.ts'
|
||||
import { Interaction } from '../structures/interactions.ts'
|
||||
import { SlashCommandInteraction } from '../structures/slash.ts'
|
||||
|
||||
export function isSlashCommandInteraction(
|
||||
d: Interaction
|
||||
): d is SlashCommandInteraction {
|
||||
return d.type === InteractionType.APPLICATION_COMMAND
|
||||
}
|
|
@ -8,12 +8,12 @@ import {
|
|||
CommandContext,
|
||||
Extension,
|
||||
Collection,
|
||||
GuildTextChannel
|
||||
} from '../../mod.ts'
|
||||
GuildTextChannel,
|
||||
slash,
|
||||
SlashCommandInteraction
|
||||
} from '../mod.ts'
|
||||
import { LL_IP, LL_PASS, LL_PORT, TOKEN } from './config.ts'
|
||||
import { Manager, Player } from 'https://deno.land/x/lavadeno/mod.ts'
|
||||
import { Interaction } from '../structures/slash.ts'
|
||||
import { slash } from '../client/mod.ts'
|
||||
// import { SlashCommandOptionType } from '../types/slash.ts'
|
||||
|
||||
export const nodes = [
|
||||
|
@ -58,12 +58,12 @@ class MyClient extends CommandClient {
|
|||
}
|
||||
|
||||
@subslash('cmd', 'sub-cmd-no-grp')
|
||||
subCmdNoGroup(d: Interaction): void {
|
||||
subCmdNoGroup(d: SlashCommandInteraction): void {
|
||||
d.respond({ content: 'sub-cmd-no-group worked' })
|
||||
}
|
||||
|
||||
@groupslash('cmd', 'sub-cmd-group', 'sub-cmd')
|
||||
subCmdGroup(d: Interaction): void {
|
||||
subCmdGroup(d: SlashCommandInteraction): void {
|
||||
d.respond({ content: 'sub-cmd-group worked' })
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ class MyClient extends CommandClient {
|
|||
}
|
||||
|
||||
@slash()
|
||||
run(d: Interaction): void {
|
||||
run(d: SlashCommandInteraction): void {
|
||||
console.log(d.name)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue