message component interactions
This commit is contained in:
		
							parent
							
								
									17e74dce45
								
							
						
					
					
						commit
						b97ec3c225
					
				
					 18 changed files with 461 additions and 86 deletions
				
			
		
							
								
								
									
										4
									
								
								mod.ts
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								mod.ts
									
										
									
									
									
								
							|  | @ -39,8 +39,11 @@ export { GuildChannelsManager } from './src/managers/guildChannels.ts' | ||||||
| export { GuildManager } from './src/managers/guilds.ts' | export { GuildManager } from './src/managers/guilds.ts' | ||||||
| export * from './src/structures/base.ts' | export * from './src/structures/base.ts' | ||||||
| export * from './src/structures/slash.ts' | export * from './src/structures/slash.ts' | ||||||
|  | export * from './src/structures/interactions.ts' | ||||||
|  | export * from './src/structures/messageComponents.ts' | ||||||
| export * from './src/types/slashCommands.ts' | export * from './src/types/slashCommands.ts' | ||||||
| export * from './src/types/interactions.ts' | export * from './src/types/interactions.ts' | ||||||
|  | export * from './src/types/messageComponents.ts' | ||||||
| export { GuildEmojisManager } from './src/managers/guildEmojis.ts' | export { GuildEmojisManager } from './src/managers/guildEmojis.ts' | ||||||
| export { MembersManager } from './src/managers/members.ts' | export { MembersManager } from './src/managers/members.ts' | ||||||
| export { MessageReactionsManager } from './src/managers/messageReactions.ts' | export { MessageReactionsManager } from './src/managers/messageReactions.ts' | ||||||
|  | @ -192,3 +195,4 @@ export { | ||||||
|   isVoiceChannel, |   isVoiceChannel, | ||||||
|   default as getChannelByType |   default as getChannelByType | ||||||
| } from './src/utils/channel.ts' | } from './src/utils/channel.ts' | ||||||
|  | export * from './src/utils/interactions.ts' | ||||||
|  |  | ||||||
|  | @ -12,7 +12,6 @@ import { EmojisManager } from '../managers/emojis.ts' | ||||||
| import { ActivityGame, ClientActivity } from '../types/presence.ts' | import { ActivityGame, ClientActivity } from '../types/presence.ts' | ||||||
| import type { Extension } from '../commands/extension.ts' | import type { Extension } from '../commands/extension.ts' | ||||||
| import { SlashClient } from '../interactions/slashClient.ts' | import { SlashClient } from '../interactions/slashClient.ts' | ||||||
| import type { Interaction } from '../structures/slash.ts' |  | ||||||
| import { ShardManager } from './shard.ts' | import { ShardManager } from './shard.ts' | ||||||
| import { Application } from '../structures/application.ts' | import { Application } from '../structures/application.ts' | ||||||
| import { Invite } from '../structures/invite.ts' | import { Invite } from '../structures/invite.ts' | ||||||
|  | @ -113,17 +112,6 @@ export class Client extends HarmonyEventEmitter<ClientEvents> { | ||||||
| 
 | 
 | ||||||
|   /** Client's presence. Startup one if set before connecting */ |   /** Client's presence. Startup one if set before connecting */ | ||||||
|   presence: ClientPresence = new ClientPresence() |   presence: ClientPresence = new ClientPresence() | ||||||
|   _decoratedEvents?: { |  | ||||||
|     [name: string]: (...args: any[]) => void |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   _decoratedSlash?: Array<{ |  | ||||||
|     name: string |  | ||||||
|     guild?: string |  | ||||||
|     parent?: string |  | ||||||
|     group?: string |  | ||||||
|     handler: (interaction: Interaction) => any |  | ||||||
|   }> |  | ||||||
| 
 | 
 | ||||||
|   _id?: string |   _id?: string | ||||||
| 
 | 
 | ||||||
|  | @ -175,13 +163,13 @@ export class Client extends HarmonyEventEmitter<ClientEvents> { | ||||||
|       this.fetchUncachedReactions = true |       this.fetchUncachedReactions = true | ||||||
| 
 | 
 | ||||||
|     if ( |     if ( | ||||||
|       this._decoratedEvents !== undefined && |       (this as any)._decoratedEvents !== undefined && | ||||||
|       Object.keys(this._decoratedEvents).length !== 0 |       Object.keys((this as any)._decoratedEvents).length !== 0 | ||||||
|     ) { |     ) { | ||||||
|       Object.entries(this._decoratedEvents).forEach((entry) => { |       Object.entries((this as any)._decoratedEvents).forEach((entry) => { | ||||||
|         this.on(entry[0] as keyof ClientEvents, entry[1].bind(this)) |         this.on(entry[0] as keyof ClientEvents, (entry as any)[1].bind(this)) | ||||||
|       }) |       }) | ||||||
|       this._decoratedEvents = undefined |       ;(this as any)._decoratedEvents = undefined | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     this.clientProperties = |     this.clientProperties = | ||||||
|  | @ -422,19 +410,23 @@ export class Client extends HarmonyEventEmitter<ClientEvents> { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /** Event decorator to create an Event handler from function */ | /** Event decorator to create an Event handler from function */ | ||||||
|  | // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
 | ||||||
| export function event(name?: keyof ClientEvents) { | export function event(name?: keyof ClientEvents) { | ||||||
|   return function ( |   return function ( | ||||||
|     client: Client | Extension, |     client: Client | Extension, | ||||||
|     prop: keyof ClientEvents | string |     prop: keyof ClientEvents | string | ||||||
|   ) { |   ) { | ||||||
|  |     // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
 | ||||||
|  |     const c = client as any | ||||||
|     const listener = ((client as unknown) as { |     const listener = ((client as unknown) as { | ||||||
|       [name in keyof ClientEvents]: (...args: ClientEvents[name]) => any |       [name in keyof ClientEvents]: (...args: ClientEvents[name]) => any | ||||||
|     })[(prop as unknown) as keyof ClientEvents] |     })[(prop as unknown) as keyof ClientEvents] | ||||||
|     if (typeof listener !== 'function') |     if (typeof listener !== 'function') | ||||||
|       throw new Error('@event decorator requires a function') |       throw new Error('@event decorator requires a function') | ||||||
|     if (client._decoratedEvents === undefined) client._decoratedEvents = {} | 
 | ||||||
|  |     if (c._decoratedEvents === undefined) c._decoratedEvents = {} | ||||||
|     const key = name === undefined ? prop : name |     const key = name === undefined ? prop : name | ||||||
| 
 | 
 | ||||||
|     client._decoratedEvents[key] = listener |     c._decoratedEvents[key] = listener | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -73,27 +73,25 @@ export class Extension { | ||||||
|   /** Events registered by this Extension */ |   /** Events registered by this Extension */ | ||||||
|   events: { [name: string]: (...args: any[]) => {} } = {} |   events: { [name: string]: (...args: any[]) => {} } = {} | ||||||
| 
 | 
 | ||||||
|   _decoratedCommands?: { [name: string]: Command } |  | ||||||
|   _decoratedEvents?: { [name: string]: (...args: any[]) => any } |  | ||||||
| 
 |  | ||||||
|   constructor(client: CommandClient) { |   constructor(client: CommandClient) { | ||||||
|     this.client = client |     this.client = client | ||||||
|     if (this._decoratedCommands !== undefined) { |     const self = this as any | ||||||
|       Object.entries(this._decoratedCommands).forEach((entry) => { |     if (self._decoratedCommands !== undefined) { | ||||||
|  |       Object.entries(self._decoratedCommands).forEach((entry: any) => { | ||||||
|         entry[1].extension = this |         entry[1].extension = this | ||||||
|         this.commands.add(entry[1]) |         this.commands.add(entry[1]) | ||||||
|       }) |       }) | ||||||
|       this._decoratedCommands = undefined |       self._decoratedCommands = undefined | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if ( |     if ( | ||||||
|       this._decoratedEvents !== undefined && |       self._decoratedEvents !== undefined && | ||||||
|       Object.keys(this._decoratedEvents).length !== 0 |       Object.keys(self._decoratedEvents).length !== 0 | ||||||
|     ) { |     ) { | ||||||
|       Object.entries(this._decoratedEvents).forEach((entry) => { |       Object.entries(self._decoratedEvents).forEach((entry: any) => { | ||||||
|         this.listen(entry[0] as keyof ClientEvents, entry[1].bind(this)) |         this.listen(entry[0] as keyof ClientEvents, entry[1].bind(this)) | ||||||
|       }) |       }) | ||||||
|       this._decoratedEvents = undefined |       self._decoratedEvents = undefined | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -18,6 +18,11 @@ import { Permissions } from '../../utils/permissions.ts' | ||||||
| import type { Gateway, GatewayEventHandler } from '../mod.ts' | import type { Gateway, GatewayEventHandler } from '../mod.ts' | ||||||
| import { User } from '../../structures/user.ts' | import { User } from '../../structures/user.ts' | ||||||
| import { Role } from '../../structures/role.ts' | import { Role } from '../../structures/role.ts' | ||||||
|  | import { RolePayload } from '../../types/role.ts' | ||||||
|  | import { InteractionChannelPayload } from '../../types/slashCommands.ts' | ||||||
|  | import { Message } from '../../structures/message.ts' | ||||||
|  | import { TextChannel } from '../../structures/textChannel.ts' | ||||||
|  | import { MessageComponentInteraction } from '../../structures/messageComponents.ts' | ||||||
| 
 | 
 | ||||||
| export const interactionCreate: GatewayEventHandler = async ( | export const interactionCreate: GatewayEventHandler = async ( | ||||||
|   gateway: Gateway, |   gateway: Gateway, | ||||||
|  | @ -32,13 +37,22 @@ export const interactionCreate: GatewayEventHandler = async ( | ||||||
|   const guild = |   const guild = | ||||||
|     d.guild_id === undefined |     d.guild_id === undefined | ||||||
|       ? 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) |   if (d.member !== undefined) | ||||||
|     await guild?.members.set(d.member.user.id, d.member) |     await guild?.members.set(d.member.user.id, d.member) | ||||||
|   const member = |   const member = | ||||||
|     d.member !== undefined |     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 |       : undefined | ||||||
|   if (d.user !== undefined) await gateway.client.users.set(d.user.id, d.user) |   if (d.user !== undefined) await gateway.client.users.set(d.user.id, d.user) | ||||||
|   const dmUser = |   const dmUser = | ||||||
|  | @ -47,9 +61,9 @@ export const interactionCreate: GatewayEventHandler = async ( | ||||||
|   const user = member !== undefined ? member.user : dmUser |   const user = member !== undefined ? member.user : dmUser | ||||||
|   if (user === undefined) return |   if (user === undefined) return | ||||||
| 
 | 
 | ||||||
|   const channel = |   const channel = await gateway.client.channels.get<GuildTextBasedChannel>( | ||||||
|     (await gateway.client.channels.get<GuildTextBasedChannel>(d.channel_id)) ?? |     d.channel_id | ||||||
|     (await gateway.client.channels.fetch<GuildTextBasedChannel>(d.channel_id)) |   ) | ||||||
| 
 | 
 | ||||||
|   const resolved: InteractionApplicationCommandResolved = { |   const resolved: InteractionApplicationCommandResolved = { | ||||||
|     users: {}, |     users: {}, | ||||||
|  | @ -58,9 +72,11 @@ export const interactionCreate: GatewayEventHandler = async ( | ||||||
|     roles: {} |     roles: {} | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   if (d.data?.resolved !== undefined) { |   if ((d.data as any)?.resolved !== undefined) { | ||||||
|     for (const [id, data] of Object.entries(d.data.resolved.users ?? {})) { |     for (const [id, data] of Object.entries( | ||||||
|       await gateway.client.users.set(id, data) |       (d.data as any)?.resolved.users ?? {} | ||||||
|  |     )) { | ||||||
|  |       await gateway.client.users.set(id, data as UserPayload) | ||||||
|       resolved.users[id] = ((await gateway.client.users.get( |       resolved.users[id] = ((await gateway.client.users.get( | ||||||
|         id |         id | ||||||
|       )) as unknown) as User |       )) as unknown) as User | ||||||
|  | @ -68,43 +84,69 @@ export const interactionCreate: GatewayEventHandler = async ( | ||||||
|         resolved.users[id].member = resolved.members[id] |         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 any)?.resolved.members ?? {} | ||||||
|  |     )) { | ||||||
|       const roles = await guild?.roles.array() |       const roles = await guild?.roles.array() | ||||||
|       let permissions = new Permissions(Permissions.DEFAULT) |       let permissions = new Permissions(Permissions.DEFAULT) | ||||||
|       if (roles !== undefined) { |       if (roles !== undefined) { | ||||||
|         const mRoles = roles.filter( |         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)) |         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( |       resolved.members[id] = new Member( | ||||||
|         gateway.client, |         gateway.client, | ||||||
|         data, |         data as any, | ||||||
|         resolved.users[id], |         resolved.users[id], | ||||||
|         guild as Guild, |         guild as Guild, | ||||||
|         permissions |         permissions | ||||||
|       ) |       ) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     for (const [id, data] of Object.entries(d.data.resolved.roles ?? {})) { |     for (const [id, data] of Object.entries( | ||||||
|  |       (d.data as any).resolved.roles ?? {} | ||||||
|  |     )) { | ||||||
|       if (guild !== undefined) { |       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 |         resolved.roles[id] = ((await guild.roles.get(id)) as unknown) as Role | ||||||
|       } else { |       } else { | ||||||
|         resolved.roles[id] = new Role( |         resolved.roles[id] = new Role( | ||||||
|           gateway.client, |           gateway.client, | ||||||
|           data, |           data as any, | ||||||
|           (guild as unknown) as Guild |           (guild as unknown) as Guild | ||||||
|         ) |         ) | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     for (const [id, data] of Object.entries(d.data.resolved.channels ?? {})) { |     for (const [id, data] of Object.entries( | ||||||
|       resolved.channels[id] = new InteractionChannel(gateway.client, data) |       (d.data as any).resolved.channels ?? {} | ||||||
|  |     )) { | ||||||
|  |       resolved.channels[id] = new InteractionChannel( | ||||||
|  |         gateway.client, | ||||||
|  |         data as InteractionChannelPayload | ||||||
|  |       ) | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   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 |   let interaction | ||||||
|   if (d.type === InteractionType.APPLICATION_COMMAND) { |   if (d.type === InteractionType.APPLICATION_COMMAND) { | ||||||
|     interaction = new SlashCommandInteraction(gateway.client, d, { |     interaction = new SlashCommandInteraction(gateway.client, d, { | ||||||
|  | @ -114,12 +156,21 @@ export const interactionCreate: GatewayEventHandler = async ( | ||||||
|       user, |       user, | ||||||
|       resolved |       resolved | ||||||
|     }) |     }) | ||||||
|  |   } else if (d.type === InteractionType.MESSAGE_COMPONENT) { | ||||||
|  |     interaction = new MessageComponentInteraction(gateway.client, d, { | ||||||
|  |       member, | ||||||
|  |       guild, | ||||||
|  |       channel, | ||||||
|  |       user, | ||||||
|  |       message | ||||||
|  |     }) | ||||||
|   } else { |   } else { | ||||||
|     interaction = new Interaction(gateway.client, d, { |     interaction = new Interaction(gateway.client, d, { | ||||||
|       member, |       member, | ||||||
|       guild, |       guild, | ||||||
|       channel, |       channel, | ||||||
|       user |       user, | ||||||
|  |       message | ||||||
|     }) |     }) | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -69,6 +69,7 @@ import { applicationCommandCreate } from './applicationCommandCreate.ts' | ||||||
| import { applicationCommandDelete } from './applicationCommandDelete.ts' | import { applicationCommandDelete } from './applicationCommandDelete.ts' | ||||||
| import { applicationCommandUpdate } from './applicationCommandUpdate.ts' | import { applicationCommandUpdate } from './applicationCommandUpdate.ts' | ||||||
| import type { SlashCommand } from '../../interactions/slashCommand.ts' | import type { SlashCommand } from '../../interactions/slashCommand.ts' | ||||||
|  | import { MessageComponentInteraction } from '../../structures/messageComponents.ts' | ||||||
| 
 | 
 | ||||||
| export const gatewayHandlers: { | export const gatewayHandlers: { | ||||||
|   [eventCode in GatewayEvents]: GatewayEventHandler | undefined |   [eventCode in GatewayEvents]: GatewayEventHandler | undefined | ||||||
|  | @ -364,7 +365,12 @@ export type ClientEvents = { | ||||||
|    * An Interaction was created |    * An Interaction was created | ||||||
|    * @param interaction Created interaction object |    * @param interaction Created interaction object | ||||||
|    */ |    */ | ||||||
|   interactionCreate: [interaction: Interaction | SlashCommandInteraction] |   interactionCreate: [ | ||||||
|  |     interaction: | ||||||
|  |       | Interaction | ||||||
|  |       | SlashCommandInteraction | ||||||
|  |       | MessageComponentInteraction | ||||||
|  |   ] | ||||||
| 
 | 
 | ||||||
|   /** |   /** | ||||||
|    * When debug message was made |    * When debug message was made | ||||||
|  |  | ||||||
|  | @ -17,6 +17,7 @@ import { User } from '../structures/user.ts' | ||||||
| import { HarmonyEventEmitter } from '../utils/events.ts' | import { HarmonyEventEmitter } from '../utils/events.ts' | ||||||
| import { encodeText, decodeText } from '../utils/encoding.ts' | import { encodeText, decodeText } from '../utils/encoding.ts' | ||||||
| import { SlashCommandsManager } from './slashCommand.ts' | import { SlashCommandsManager } from './slashCommand.ts' | ||||||
|  | import { MessageComponentInteraction } from '../structures/messageComponents.ts' | ||||||
| 
 | 
 | ||||||
| export type SlashCommandHandlerCallback = (interaction: Interaction) => unknown | export type SlashCommandHandlerCallback = (interaction: Interaction) => unknown | ||||||
| export interface SlashCommandHandler { | export interface SlashCommandHandler { | ||||||
|  | @ -77,8 +78,10 @@ export class SlashClient extends HarmonyEventEmitter<SlashClientEvents> { | ||||||
| 
 | 
 | ||||||
|     this.enabled = options.enabled ?? true |     this.enabled = options.enabled ?? true | ||||||
| 
 | 
 | ||||||
|     if (this.client?._decoratedSlash !== undefined) { |     // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
 | ||||||
|       this.client._decoratedSlash.forEach((e) => { |     const client = this.client as any | ||||||
|  |     if (client?._decoratedSlash !== undefined) { | ||||||
|  |       client._decoratedSlash.forEach((e: any) => { | ||||||
|         e.handler = e.handler.bind(this.client) |         e.handler = e.handler.bind(this.client) | ||||||
|         this.handlers.push(e) |         this.handlers.push(e) | ||||||
|       }) |       }) | ||||||
|  | @ -205,7 +208,10 @@ export class SlashClient extends HarmonyEventEmitter<SlashClientEvents> { | ||||||
| 
 | 
 | ||||||
|   /** Process an incoming Interaction */ |   /** Process an incoming Interaction */ | ||||||
|   private async _process( |   private async _process( | ||||||
|     interaction: Interaction | SlashCommandInteraction |     interaction: | ||||||
|  |       | Interaction | ||||||
|  |       | SlashCommandInteraction | ||||||
|  |       | MessageComponentInteraction | ||||||
|   ): Promise<void> { |   ): Promise<void> { | ||||||
|     if (!this.enabled) return |     if (!this.enabled) return | ||||||
| 
 | 
 | ||||||
|  | @ -282,7 +288,7 @@ export class SlashClient extends HarmonyEventEmitter<SlashClientEvents> { | ||||||
|           member: payload.member as any, |           member: payload.member as any, | ||||||
|           guild: payload.guild_id as any, |           guild: payload.guild_id as any, | ||||||
|           channel: payload.channel_id as any, |           channel: payload.channel_id as any, | ||||||
|           resolved: ((payload.data |           resolved: (((payload.data as any) | ||||||
|             ?.resolved as unknown) as InteractionApplicationCommandResolved) ?? { |             ?.resolved as unknown) as InteractionApplicationCommandResolved) ?? { | ||||||
|             users: {}, |             users: {}, | ||||||
|             members: {}, |             members: {}, | ||||||
|  | @ -400,12 +406,14 @@ export class SlashClient extends HarmonyEventEmitter<SlashClientEvents> { | ||||||
| /** Decorator to create a Slash Command handler */ | /** Decorator to create a Slash Command handler */ | ||||||
| export function slash(name?: string, guild?: string) { | export function slash(name?: string, guild?: string) { | ||||||
|   return function (client: Client | SlashClient | SlashModule, prop: string) { |   return function (client: Client | SlashClient | SlashModule, prop: string) { | ||||||
|     if (client._decoratedSlash === undefined) client._decoratedSlash = [] |     // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
 | ||||||
|  |     const c = client as any | ||||||
|  |     if (c._decoratedSlash === undefined) c._decoratedSlash = [] | ||||||
|     const item = (client as { [name: string]: any })[prop] |     const item = (client as { [name: string]: any })[prop] | ||||||
|     if (typeof item !== 'function') { |     if (typeof item !== 'function') { | ||||||
|       throw new Error('@slash decorator requires a function') |       throw new Error('@slash decorator requires a function') | ||||||
|     } else |     } else | ||||||
|       client._decoratedSlash.push({ |       c._decoratedSlash.push({ | ||||||
|         name: name ?? prop, |         name: name ?? prop, | ||||||
|         guild, |         guild, | ||||||
|         handler: item |         handler: item | ||||||
|  | @ -416,12 +424,14 @@ export function slash(name?: string, guild?: string) { | ||||||
| /** Decorator to create a Sub-Slash Command handler */ | /** Decorator to create a Sub-Slash Command handler */ | ||||||
| export function subslash(parent: string, name?: string, guild?: string) { | export function subslash(parent: string, name?: string, guild?: string) { | ||||||
|   return function (client: Client | SlashModule | SlashClient, prop: string) { |   return function (client: Client | SlashModule | SlashClient, prop: string) { | ||||||
|     if (client._decoratedSlash === undefined) client._decoratedSlash = [] |     // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
 | ||||||
|  |     const c = client as any | ||||||
|  |     if (c._decoratedSlash === undefined) c._decoratedSlash = [] | ||||||
|     const item = (client as { [name: string]: any })[prop] |     const item = (client as { [name: string]: any })[prop] | ||||||
|     if (typeof item !== 'function') { |     if (typeof item !== 'function') { | ||||||
|       throw new Error('@subslash decorator requires a function') |       throw new Error('@subslash decorator requires a function') | ||||||
|     } else |     } else | ||||||
|       client._decoratedSlash.push({ |       c._decoratedSlash.push({ | ||||||
|         parent, |         parent, | ||||||
|         name: name ?? prop, |         name: name ?? prop, | ||||||
|         guild, |         guild, | ||||||
|  | @ -438,12 +448,14 @@ export function groupslash( | ||||||
|   guild?: string |   guild?: string | ||||||
| ) { | ) { | ||||||
|   return function (client: Client | SlashModule | SlashClient, prop: string) { |   return function (client: Client | SlashModule | SlashClient, prop: string) { | ||||||
|     if (client._decoratedSlash === undefined) client._decoratedSlash = [] |     // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
 | ||||||
|  |     const c = client as any | ||||||
|  |     if (c._decoratedSlash === undefined) c._decoratedSlash = [] | ||||||
|     const item = (client as { [name: string]: any })[prop] |     const item = (client as { [name: string]: any })[prop] | ||||||
|     if (typeof item !== 'function') { |     if (typeof item !== 'function') { | ||||||
|       throw new Error('@groupslash decorator requires a function') |       throw new Error('@groupslash decorator requires a function') | ||||||
|     } else |     } else | ||||||
|       client._decoratedSlash.push({ |       c._decoratedSlash.push({ | ||||||
|         group, |         group, | ||||||
|         parent, |         parent, | ||||||
|         name: name ?? prop, |         name: name ?? prop, | ||||||
|  |  | ||||||
							
								
								
									
										19
									
								
								src/managers/_util.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/managers/_util.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,19 @@ | ||||||
|  | import { | ||||||
|  |   MessageComponentData, | ||||||
|  |   MessageComponentPayload | ||||||
|  | } from '../types/messageComponents.ts' | ||||||
|  | 
 | ||||||
|  | export function transformComponent( | ||||||
|  |   d: MessageComponentData[] | ||||||
|  | ): MessageComponentPayload[] { | ||||||
|  |   return d.map((e: any) => { | ||||||
|  |     if (e.customID !== undefined) { | ||||||
|  |       e.custom_id = e.customID | ||||||
|  |       delete e.customID | ||||||
|  |     } | ||||||
|  |     if (e.components !== undefined) { | ||||||
|  |       e.components = transformComponent(e.components) | ||||||
|  |     } | ||||||
|  |     return e | ||||||
|  |   }) | ||||||
|  | } | ||||||
|  | @ -11,6 +11,7 @@ import type { | ||||||
| import { CHANNEL } from '../types/endpoint.ts' | import { CHANNEL } from '../types/endpoint.ts' | ||||||
| import getChannelByType from '../utils/channel.ts' | import getChannelByType from '../utils/channel.ts' | ||||||
| import { BaseManager } from './base.ts' | import { BaseManager } from './base.ts' | ||||||
|  | import { transformComponent } from './_util.ts' | ||||||
| 
 | 
 | ||||||
| export type AllMessageOptions = MessageOptions | Embed | export type AllMessageOptions = MessageOptions | Embed | ||||||
| 
 | 
 | ||||||
|  | @ -100,7 +101,10 @@ export class ChannelsManager extends BaseManager<ChannelPayload, Channel> { | ||||||
|       content: content, |       content: content, | ||||||
|       embed: option?.embed, |       embed: option?.embed, | ||||||
|       file: option?.file, |       file: option?.file, | ||||||
|       components: option?.components, |       components: | ||||||
|  |         option?.components !== undefined | ||||||
|  |           ? transformComponent(option.components) | ||||||
|  |           : undefined, | ||||||
|       files: option?.files, |       files: option?.files, | ||||||
|       tts: option?.tts, |       tts: option?.tts, | ||||||
|       allowed_mentions: option?.allowedMentions, |       allowed_mentions: option?.allowedMentions, | ||||||
|  | @ -168,6 +172,10 @@ export class ChannelsManager extends BaseManager<ChannelPayload, Channel> { | ||||||
|       embed: option?.embed !== undefined ? option.embed.toJSON() : undefined, |       embed: option?.embed !== undefined ? option.embed.toJSON() : undefined, | ||||||
|       // Cannot upload new files with Message
 |       // Cannot upload new files with Message
 | ||||||
|       // file: option?.file,
 |       // file: option?.file,
 | ||||||
|  |       components: | ||||||
|  |         option?.components !== undefined | ||||||
|  |           ? transformComponent(option.components) | ||||||
|  |           : undefined, | ||||||
|       tts: option?.tts, |       tts: option?.tts, | ||||||
|       allowed_mentions: option?.allowedMentions |       allowed_mentions: option?.allowedMentions | ||||||
|     }) |     }) | ||||||
|  |  | ||||||
|  | @ -13,7 +13,7 @@ export class DiscordAPIError extends Error { | ||||||
|     this.message = |     this.message = | ||||||
|       typeof error === 'string' |       typeof error === 'string' | ||||||
|         ? `${error} ` |         ? `${error} ` | ||||||
|         : `\n${error.method.toUpperCase()} ${error.url.slice(7)} returned ${ |         : `\n${error.method.toUpperCase()} ${error.url} returned ${ | ||||||
|             error.status |             error.status | ||||||
|           }\n(${error.code ?? 'unknown'}) ${error.message}${ |           }\n(${error.code ?? 'unknown'}) ${error.message}${ | ||||||
|             fmt.length === 0 |             fmt.length === 0 | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| import type { Client } from '../client/client.ts' | import type { Client } from '../client/client.ts' | ||||||
|  | import { transformComponent } from '../managers/_util.ts' | ||||||
| import { | import { | ||||||
|   AllowedMentionsPayload, |   AllowedMentionsPayload, | ||||||
|   ChannelTypes, |   ChannelTypes, | ||||||
|  | @ -13,11 +14,14 @@ import { | ||||||
|   InteractionResponseType, |   InteractionResponseType, | ||||||
|   InteractionType |   InteractionType | ||||||
| } from '../types/interactions.ts' | } from '../types/interactions.ts' | ||||||
|  | import { | ||||||
|  |   InteractionMessageComponentData, | ||||||
|  |   MessageComponentData | ||||||
|  | } from '../types/messageComponents.ts' | ||||||
| import { | import { | ||||||
|   InteractionApplicationCommandData, |   InteractionApplicationCommandData, | ||||||
|   InteractionChannelPayload |   InteractionChannelPayload | ||||||
| } from '../types/slashCommands.ts' | } from '../types/slashCommands.ts' | ||||||
| import { Dict } from '../utils/dict.ts' |  | ||||||
| import { Permissions } from '../utils/permissions.ts' | import { Permissions } from '../utils/permissions.ts' | ||||||
| import { SnowflakeBase } from './base.ts' | import { SnowflakeBase } from './base.ts' | ||||||
| import { Channel } from './channel.ts' | import { Channel } from './channel.ts' | ||||||
|  | @ -26,7 +30,6 @@ import { Guild } from './guild.ts' | ||||||
| import { GuildTextChannel } from './guildTextChannel.ts' | import { GuildTextChannel } from './guildTextChannel.ts' | ||||||
| import { Member } from './member.ts' | import { Member } from './member.ts' | ||||||
| import { Message } from './message.ts' | import { Message } from './message.ts' | ||||||
| import { Role } from './role.ts' |  | ||||||
| import { TextChannel } from './textChannel.ts' | import { TextChannel } from './textChannel.ts' | ||||||
| import { User } from './user.ts' | import { User } from './user.ts' | ||||||
| 
 | 
 | ||||||
|  | @ -47,6 +50,7 @@ export interface InteractionMessageOptions { | ||||||
|   allowedMentions?: AllowedMentionsPayload |   allowedMentions?: AllowedMentionsPayload | ||||||
|   /** Whether the Message Response should be Ephemeral (only visible to User) or not */ |   /** Whether the Message Response should be Ephemeral (only visible to User) or not */ | ||||||
|   ephemeral?: boolean |   ephemeral?: boolean | ||||||
|  |   components?: MessageComponentData[] | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export interface InteractionResponse extends InteractionMessageOptions { | export interface InteractionResponse extends InteractionMessageOptions { | ||||||
|  | @ -76,13 +80,6 @@ export class InteractionChannel extends SnowflakeBase { | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export interface InteractionApplicationCommandResolved { |  | ||||||
|   users: Dict<InteractionUser> |  | ||||||
|   members: Dict<Member> |  | ||||||
|   channels: Dict<InteractionChannel> |  | ||||||
|   roles: Dict<Role> |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export class InteractionUser extends User { | export class InteractionUser extends User { | ||||||
|   member?: Member |   member?: Member | ||||||
| } | } | ||||||
|  | @ -110,7 +107,8 @@ export class Interaction extends SnowflakeBase { | ||||||
|   _httpResponded?: boolean |   _httpResponded?: boolean | ||||||
|   applicationID: string |   applicationID: string | ||||||
|   /** Data sent with Interaction. Only applies to Application Command */ |   /** Data sent with Interaction. Only applies to Application Command */ | ||||||
|   data?: InteractionApplicationCommandData |   data?: InteractionApplicationCommandData | InteractionMessageComponentData | ||||||
|  |   message?: Message | ||||||
| 
 | 
 | ||||||
|   constructor( |   constructor( | ||||||
|     client: Client, |     client: Client, | ||||||
|  | @ -120,6 +118,7 @@ export class Interaction extends SnowflakeBase { | ||||||
|       guild?: Guild |       guild?: Guild | ||||||
|       member?: Member |       member?: Member | ||||||
|       user: User |       user: User | ||||||
|  |       message?: Message | ||||||
|     } |     } | ||||||
|   ) { |   ) { | ||||||
|     super(client) |     super(client) | ||||||
|  | @ -132,6 +131,7 @@ export class Interaction extends SnowflakeBase { | ||||||
|     this.data = data.data |     this.data = data.data | ||||||
|     this.guild = others.guild |     this.guild = others.guild | ||||||
|     this.channel = others.channel |     this.channel = others.channel | ||||||
|  |     this.message = others.message | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   /** Respond to an Interaction */ |   /** Respond to an Interaction */ | ||||||
|  | @ -154,7 +154,11 @@ export class Interaction extends SnowflakeBase { | ||||||
|               embeds: data.embeds, |               embeds: data.embeds, | ||||||
|               tts: data.tts ?? false, |               tts: data.tts ?? false, | ||||||
|               flags, |               flags, | ||||||
|               allowed_mentions: data.allowedMentions ?? undefined |               allowed_mentions: data.allowedMentions ?? undefined, | ||||||
|  |               components: | ||||||
|  |                 data.components === undefined | ||||||
|  |                   ? undefined | ||||||
|  |                   : transformComponent(data.components) | ||||||
|             } |             } | ||||||
|           : undefined |           : undefined | ||||||
|     } |     } | ||||||
|  | @ -227,6 +231,7 @@ export class Interaction extends SnowflakeBase { | ||||||
|     embeds?: Array<Embed | EmbedPayload> |     embeds?: Array<Embed | EmbedPayload> | ||||||
|     flags?: number | number[] |     flags?: number | number[] | ||||||
|     allowedMentions?: AllowedMentionsPayload |     allowedMentions?: AllowedMentionsPayload | ||||||
|  |     components?: MessageComponentData[] | ||||||
|   }): Promise<Interaction> { |   }): Promise<Interaction> { | ||||||
|     const url = WEBHOOK_MESSAGE(this.applicationID, this.token, '@original') |     const url = WEBHOOK_MESSAGE(this.applicationID, this.token, '@original') | ||||||
|     await this.client.rest.patch(url, { |     await this.client.rest.patch(url, { | ||||||
|  | @ -236,7 +241,11 @@ export class Interaction extends SnowflakeBase { | ||||||
|         typeof data.flags === 'object' |         typeof data.flags === 'object' | ||||||
|           ? data.flags.reduce((p, a) => p | a, 0) |           ? data.flags.reduce((p, a) => p | a, 0) | ||||||
|           : data.flags, |           : data.flags, | ||||||
|       allowed_mentions: data.allowedMentions |       allowed_mentions: data.allowedMentions, | ||||||
|  |       components: | ||||||
|  |         data.components === undefined | ||||||
|  |           ? undefined | ||||||
|  |           : transformComponent(data.components) | ||||||
|     }) |     }) | ||||||
|     return this |     return this | ||||||
|   } |   } | ||||||
|  |  | ||||||
							
								
								
									
										42
									
								
								src/structures/messageComponents.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								src/structures/messageComponents.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,42 @@ | ||||||
|  | import { | ||||||
|  |   InteractionMessageComponentData, | ||||||
|  |   MessageComponentType | ||||||
|  | } from '../types/messageComponents.ts' | ||||||
|  | import { Interaction } from './interactions.ts' | ||||||
|  | import type { Client } from '../client/mod.ts' | ||||||
|  | import { InteractionPayload } from '../types/interactions.ts' | ||||||
|  | import type { Guild } from './guild.ts' | ||||||
|  | import type { GuildTextChannel } from './guildTextChannel.ts' | ||||||
|  | import type { Member } from './member.ts' | ||||||
|  | import type { TextChannel } from './textChannel.ts' | ||||||
|  | import { User } from './user.ts' | ||||||
|  | import { Message } from './message.ts' | ||||||
|  | 
 | ||||||
|  | export class MessageComponentInteraction extends Interaction { | ||||||
|  |   data: InteractionMessageComponentData | ||||||
|  |   declare message: Message | ||||||
|  | 
 | ||||||
|  |   constructor( | ||||||
|  |     client: Client, | ||||||
|  |     data: InteractionPayload, | ||||||
|  |     others: { | ||||||
|  |       channel?: TextChannel | GuildTextChannel | ||||||
|  |       guild?: Guild | ||||||
|  |       member?: Member | ||||||
|  |       user: User | ||||||
|  |       message?: Message | ||||||
|  |     } | ||||||
|  |   ) { | ||||||
|  |     super(client, data, others) | ||||||
|  |     // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
 | ||||||
|  |     this.data = data.data as InteractionMessageComponentData | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   get customID(): string { | ||||||
|  |     return this.data.custom_id | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   get componentType(): MessageComponentType { | ||||||
|  |     return this.data.component_type | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | @ -7,7 +7,10 @@ import type { EmojiPayload } from './emoji.ts' | ||||||
| import type { MemberPayload } from './guild.ts' | import type { MemberPayload } from './guild.ts' | ||||||
| import type { InteractionType } from './interactions.ts' | import type { InteractionType } from './interactions.ts' | ||||||
| import type { UserPayload } from './user.ts' | import type { UserPayload } from './user.ts' | ||||||
| import type { MessageComponentPayload } from './messageComponents.ts' | import type { | ||||||
|  |   MessageComponentData, | ||||||
|  |   MessageComponentPayload | ||||||
|  | } from './messageComponents.ts' | ||||||
| 
 | 
 | ||||||
| export interface ChannelPayload { | export interface ChannelPayload { | ||||||
|   id: string |   id: string | ||||||
|  | @ -189,6 +192,7 @@ export interface MessagePayload { | ||||||
|   flags?: number |   flags?: number | ||||||
|   stickers?: MessageStickerPayload[] |   stickers?: MessageStickerPayload[] | ||||||
|   interaction?: MessageInteractionPayload |   interaction?: MessageInteractionPayload | ||||||
|  |   components?: MessageComponentPayload[] | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export enum AllowedMentionType { | export enum AllowedMentionType { | ||||||
|  | @ -211,7 +215,7 @@ export interface MessageOptions { | ||||||
|   files?: MessageAttachment[] |   files?: MessageAttachment[] | ||||||
|   allowedMentions?: AllowedMentionsPayload |   allowedMentions?: AllowedMentionsPayload | ||||||
|   reply?: Message | MessageReference | string |   reply?: Message | MessageReference | string | ||||||
|   components?: MessageComponentPayload[] |   components?: MessageComponentData[] | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export interface ChannelMention { | export interface ChannelMention { | ||||||
|  | @ -395,6 +399,7 @@ export interface EditMessagePayload { | ||||||
|   embed?: EmbedPayload |   embed?: EmbedPayload | ||||||
|   allowed_mentions?: AllowedMentionsPayload |   allowed_mentions?: AllowedMentionsPayload | ||||||
|   flags?: number |   flags?: number | ||||||
|  |   components?: MessageComponentPayload[] | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export interface CreateMessagePayload extends EditMessagePayload { | export interface CreateMessagePayload extends EditMessagePayload { | ||||||
|  |  | ||||||
|  | @ -1,5 +1,13 @@ | ||||||
| import { AllowedMentionsPayload, EmbedPayload } from './channel.ts' | import { | ||||||
|  |   AllowedMentionsPayload, | ||||||
|  |   EmbedPayload, | ||||||
|  |   MessagePayload | ||||||
|  | } from './channel.ts' | ||||||
| import type { MemberPayload } from './guild.ts' | import type { MemberPayload } from './guild.ts' | ||||||
|  | import { | ||||||
|  |   InteractionMessageComponentData, | ||||||
|  |   MessageComponentData | ||||||
|  | } from './messageComponents.ts' | ||||||
| import type { InteractionApplicationCommandData } from './slashCommands.ts' | import type { InteractionApplicationCommandData } from './slashCommands.ts' | ||||||
| import type { UserPayload } from './user.ts' | import type { UserPayload } from './user.ts' | ||||||
| 
 | 
 | ||||||
|  | @ -7,7 +15,9 @@ export enum InteractionType { | ||||||
|   /** Ping sent by the API (HTTP-only) */ |   /** Ping sent by the API (HTTP-only) */ | ||||||
|   PING = 1, |   PING = 1, | ||||||
|   /** Slash Command Interaction */ |   /** Slash Command Interaction */ | ||||||
|   APPLICATION_COMMAND = 2 |   APPLICATION_COMMAND = 2, | ||||||
|  |   /** Message Component Interaction */ | ||||||
|  |   MESSAGE_COMPONENT = 3 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export interface InteractionMemberPayload extends MemberPayload { | export interface InteractionMemberPayload extends MemberPayload { | ||||||
|  | @ -27,14 +37,17 @@ export interface InteractionPayload { | ||||||
|   /** ID of the Interaction */ |   /** ID of the Interaction */ | ||||||
|   id: string |   id: string | ||||||
|   /** |   /** | ||||||
|    * Data sent with the interaction. Undefined only when Interaction is not Slash Command.* |    * Data sent with the interaction. Undefined only when Interaction is PING (http-only).* | ||||||
|    */ |    */ | ||||||
|   data?: InteractionApplicationCommandData |   data?: InteractionApplicationCommandData | InteractionMessageComponentData | ||||||
|   /** ID of the Guild in which Interaction was invoked */ |   /** ID of the Guild in which Interaction was invoked */ | ||||||
|   guild_id?: string |   guild_id?: string | ||||||
|   /** ID of the Channel in which Interaction was invoked */ |   /** ID of the Channel in which Interaction was invoked */ | ||||||
|   channel_id?: string |   channel_id?: string | ||||||
|  |   /** Application ID of the Client who received interaction */ | ||||||
|   application_id: string |   application_id: string | ||||||
|  |   /** Message ID if the Interaction was of type MESSAGE_COMPONENT */ | ||||||
|  |   message?: MessagePayload | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export enum InteractionResponseType { | export enum InteractionResponseType { | ||||||
|  | @ -62,6 +75,7 @@ export interface InteractionResponseDataPayload { | ||||||
|   /** Allowed Mentions object */ |   /** Allowed Mentions object */ | ||||||
|   allowed_mentions?: AllowedMentionsPayload |   allowed_mentions?: AllowedMentionsPayload | ||||||
|   flags?: number |   flags?: number | ||||||
|  |   components?: MessageComponentData[] | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export enum InteractionResponseFlags { | export enum InteractionResponseFlags { | ||||||
|  |  | ||||||
|  | @ -17,4 +17,19 @@ export interface MessageComponentPayload { | ||||||
|   label?: string |   label?: string | ||||||
|   style?: ButtonStyle |   style?: ButtonStyle | ||||||
|   url?: string |   url?: string | ||||||
|  |   custom_id?: string | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export interface MessageComponentData { | ||||||
|  |   type: MessageComponentType | ||||||
|  |   components?: MessageComponentData[] | ||||||
|  |   label?: string | ||||||
|  |   style?: ButtonStyle | ||||||
|  |   url?: string | ||||||
|  |   customID?: string | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export interface InteractionMessageComponentData { | ||||||
|  |   custom_id: string | ||||||
|  |   component_type: MessageComponentType | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -12,7 +12,7 @@ export function simplifyAPIError(errors: any): SimplifiedError { | ||||||
|         const arrayIndex = !isNaN(Number(obj[0])) |         const arrayIndex = !isNaN(Number(obj[0])) | ||||||
|         if (arrayIndex) obj[0] = `[${obj[0]}]` |         if (arrayIndex) obj[0] = `[${obj[0]}]` | ||||||
|         if (acum !== '' && !arrayIndex) acum += '.' |         if (acum !== '' && !arrayIndex) acum += '.' | ||||||
|         fmt(obj[1], (acum += obj[0])) |         fmt(obj[1], acum + obj[0]) | ||||||
|       }) |       }) | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
							
								
								
									
										16
									
								
								src/utils/interactions.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/utils/interactions.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,16 @@ | ||||||
|  | import { InteractionType } from '../../mod.ts' | ||||||
|  | import { Interaction } from '../structures/interactions.ts' | ||||||
|  | import { MessageComponentInteraction } from '../structures/messageComponents.ts' | ||||||
|  | import { SlashCommandInteraction } from '../structures/slash.ts' | ||||||
|  | 
 | ||||||
|  | export function isSlashCommandInteraction( | ||||||
|  |   d: Interaction | ||||||
|  | ): d is SlashCommandInteraction { | ||||||
|  |   return d.type === InteractionType.APPLICATION_COMMAND | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export function isMessageComponentInteraction( | ||||||
|  |   d: Interaction | ||||||
|  | ): d is MessageComponentInteraction { | ||||||
|  |   return d.type === InteractionType.MESSAGE_COMPONENT | ||||||
|  | } | ||||||
							
								
								
									
										184
									
								
								test/components.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										184
									
								
								test/components.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,184 @@ | ||||||
|  | import { | ||||||
|  |   CommandClient, | ||||||
|  |   Command, | ||||||
|  |   CommandContext, | ||||||
|  |   ButtonStyle, | ||||||
|  |   MessageComponentType, | ||||||
|  |   isMessageComponentInteraction, | ||||||
|  |   MessageComponentInteraction, | ||||||
|  |   Message | ||||||
|  | } from '../mod.ts' | ||||||
|  | import { TOKEN } from './config.ts' | ||||||
|  | 
 | ||||||
|  | const client = new CommandClient({ | ||||||
|  |   prefix: '.', | ||||||
|  |   spacesAfterPrefix: true | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | enum Choice { | ||||||
|  |   Rock, | ||||||
|  |   Paper, | ||||||
|  |   Scissor | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const games = new Map< | ||||||
|  |   string, | ||||||
|  |   { user: number; bot: number; msg: Message; txt: string } | ||||||
|  | >() | ||||||
|  | const components = [ | ||||||
|  |   { | ||||||
|  |     type: MessageComponentType.ActionRow, | ||||||
|  |     components: [ | ||||||
|  |       { | ||||||
|  |         type: MessageComponentType.Button, | ||||||
|  |         style: ButtonStyle.Primary, | ||||||
|  |         label: 'Rock', | ||||||
|  |         customID: 'rps::Rock' | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         type: MessageComponentType.Button, | ||||||
|  |         style: ButtonStyle.Primary, | ||||||
|  |         label: 'Paper', | ||||||
|  |         customID: 'rps::Paper' | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         type: MessageComponentType.Button, | ||||||
|  |         style: ButtonStyle.Primary, | ||||||
|  |         label: 'Scissor', | ||||||
|  |         customID: 'rps::Scissor' | ||||||
|  |       } | ||||||
|  |     ] | ||||||
|  |   } | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | client.once('ready', () => { | ||||||
|  |   console.log('Ready!') | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | client.commands.add( | ||||||
|  |   class extends Command { | ||||||
|  |     name = 'button' | ||||||
|  | 
 | ||||||
|  |     execute(ctx: CommandContext): void { | ||||||
|  |       ctx.channel.send('Test Buttons', { | ||||||
|  |         components: [ | ||||||
|  |           { | ||||||
|  |             type: MessageComponentType.ActionRow, | ||||||
|  |             components: [ | ||||||
|  |               { | ||||||
|  |                 type: MessageComponentType.Button, | ||||||
|  |                 label: 'Primary', | ||||||
|  |                 style: ButtonStyle.Primary, | ||||||
|  |                 customID: '1' | ||||||
|  |               }, | ||||||
|  |               { | ||||||
|  |                 type: MessageComponentType.Button, | ||||||
|  |                 label: 'Secondary', | ||||||
|  |                 style: ButtonStyle.Secondary, | ||||||
|  |                 customID: '2' | ||||||
|  |               }, | ||||||
|  |               { | ||||||
|  |                 type: MessageComponentType.Button, | ||||||
|  |                 label: 'Destructive', | ||||||
|  |                 style: ButtonStyle.Destructive, | ||||||
|  |                 customID: '3' | ||||||
|  |               }, | ||||||
|  |               { | ||||||
|  |                 type: MessageComponentType.Button, | ||||||
|  |                 label: 'Success', | ||||||
|  |                 style: ButtonStyle.Success, | ||||||
|  |                 customID: '4' | ||||||
|  |               }, | ||||||
|  |               { | ||||||
|  |                 type: MessageComponentType.Button, | ||||||
|  |                 label: 'Link', | ||||||
|  |                 style: ButtonStyle.Link, | ||||||
|  |                 url: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' | ||||||
|  |               } | ||||||
|  |             ] | ||||||
|  |           } | ||||||
|  |         ] | ||||||
|  |       }) | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | client.commands.add( | ||||||
|  |   class extends Command { | ||||||
|  |     name = 'play' | ||||||
|  | 
 | ||||||
|  |     execute(ctx: CommandContext): any { | ||||||
|  |       if (games.has(ctx.author.id)) | ||||||
|  |         return ctx.message.reply('You are already playing!') | ||||||
|  |       ctx.channel | ||||||
|  |         .send('Game starts now!', { | ||||||
|  |           components | ||||||
|  |         }) | ||||||
|  |         .then((msg) => { | ||||||
|  |           games.set(ctx.author.id, { | ||||||
|  |             user: 0, | ||||||
|  |             bot: 0, | ||||||
|  |             msg, | ||||||
|  |             txt: 'Game starts now!' | ||||||
|  |           }) | ||||||
|  |         }) | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // client.on('raw', (e, d) => {
 | ||||||
|  | //   if (e === 'INTERACTION_CREATE') console.log(e, d)
 | ||||||
|  | // })
 | ||||||
|  | 
 | ||||||
|  | client.on('interactionCreate', (i) => { | ||||||
|  |   if (isMessageComponentInteraction(i) === true) { | ||||||
|  |     const d = i as MessageComponentInteraction | ||||||
|  | 
 | ||||||
|  |     if (d.customID.startsWith('rps::') === true) { | ||||||
|  |       const game = games.get(d.user.id) | ||||||
|  |       if (game === undefined) return | ||||||
|  |       const choice = d.customID.split('::')[1] | ||||||
|  |       const c: number = Number(Choice[choice as any]) | ||||||
|  |       const rand = Math.floor(Math.random() * 2) | ||||||
|  | 
 | ||||||
|  |       game.txt += '\n\n' | ||||||
|  |       game.txt += `You: ${choice}, Bot: ${Choice[rand]}` | ||||||
|  |       let msg | ||||||
|  |       if (rand === c) { | ||||||
|  |         msg = 'Both chose ' + Choice[rand] + '!' | ||||||
|  |       } else if ( | ||||||
|  |         (rand === 0 && c === 2) || | ||||||
|  |         (rand === 1 && c === 0) || | ||||||
|  |         (rand === 2 && c === 1) | ||||||
|  |       ) { | ||||||
|  |         msg = 'Bot got one point!' | ||||||
|  |         game.bot++ | ||||||
|  |       } else { | ||||||
|  |         msg = 'You got one point!' | ||||||
|  |         game.user++ | ||||||
|  |       } | ||||||
|  |       game.txt += '\nInfo: ' + msg | ||||||
|  | 
 | ||||||
|  |       if (game.bot === 5 || game.user === 5) { | ||||||
|  |         const won = game.bot === 5 ? 'Bot' : 'You' | ||||||
|  |         game.msg.edit( | ||||||
|  |           `${won} won!\n\n**Points:** You: ${game.user} | Bot: ${game.bot}`, | ||||||
|  |           { | ||||||
|  |             components: [] | ||||||
|  |           } | ||||||
|  |         ) | ||||||
|  |         games.delete(d.user.id) | ||||||
|  |       } else { | ||||||
|  |         game.msg.edit( | ||||||
|  |           `${game.txt}\n\n**Points:** You: ${game.user} | Bot: ${game.bot}`, | ||||||
|  |           { | ||||||
|  |             components | ||||||
|  |           } | ||||||
|  |         ) | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | console.log('Connecting...') | ||||||
|  | client.connect(TOKEN, ['GUILDS', 'GUILD_MESSAGES', 'DIRECT_MESSAGES']) | ||||||
|  | @ -8,12 +8,12 @@ import { | ||||||
|   CommandContext, |   CommandContext, | ||||||
|   Extension, |   Extension, | ||||||
|   Collection, |   Collection, | ||||||
|   GuildTextChannel |   GuildTextChannel, | ||||||
| } from '../../mod.ts' |   slash, | ||||||
|  |   SlashCommandInteraction | ||||||
|  | } from '../mod.ts' | ||||||
| import { LL_IP, LL_PASS, LL_PORT, TOKEN } from './config.ts' | import { LL_IP, LL_PASS, LL_PORT, TOKEN } from './config.ts' | ||||||
| import { Manager, Player } from 'https://deno.land/x/lavadeno/mod.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'
 | // import { SlashCommandOptionType } from '../types/slash.ts'
 | ||||||
| 
 | 
 | ||||||
| export const nodes = [ | export const nodes = [ | ||||||
|  | @ -58,12 +58,12 @@ class MyClient extends CommandClient { | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   @subslash('cmd', 'sub-cmd-no-grp') |   @subslash('cmd', 'sub-cmd-no-grp') | ||||||
|   subCmdNoGroup(d: Interaction): void { |   subCmdNoGroup(d: SlashCommandInteraction): void { | ||||||
|     d.respond({ content: 'sub-cmd-no-group worked' }) |     d.respond({ content: 'sub-cmd-no-group worked' }) | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   @groupslash('cmd', 'sub-cmd-group', 'sub-cmd') |   @groupslash('cmd', 'sub-cmd-group', 'sub-cmd') | ||||||
|   subCmdGroup(d: Interaction): void { |   subCmdGroup(d: SlashCommandInteraction): void { | ||||||
|     d.respond({ content: 'sub-cmd-group worked' }) |     d.respond({ content: 'sub-cmd-group worked' }) | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  | @ -79,7 +79,7 @@ class MyClient extends CommandClient { | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   @slash() |   @slash() | ||||||
|   run(d: Interaction): void { |   run(d: SlashCommandInteraction): void { | ||||||
|     console.log(d.name) |     console.log(d.name) | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue