feat(slash): many new things
This commit is contained in:
		
							parent
							
								
									d14fe15d68
								
							
						
					
					
						commit
						6e014b353e
					
				
					 7 changed files with 256 additions and 7 deletions
				
			
		|  | @ -54,6 +54,7 @@ import { | ||||||
|   EveryTextChannelTypes |   EveryTextChannelTypes | ||||||
| } from '../../utils/getChannelByType.ts' | } from '../../utils/getChannelByType.ts' | ||||||
| import { interactionCreate } from './interactionCreate.ts' | import { interactionCreate } from './interactionCreate.ts' | ||||||
|  | import { Interaction } from '../../structures/slash.ts' | ||||||
| 
 | 
 | ||||||
| export const gatewayHandlers: { | export const gatewayHandlers: { | ||||||
|   [eventCode in GatewayEvents]: GatewayEventHandler | undefined |   [eventCode in GatewayEvents]: GatewayEventHandler | undefined | ||||||
|  | @ -328,4 +329,8 @@ export interface ClientEvents extends EventTypes { | ||||||
|    * @param channel Channel of which Webhooks were updated |    * @param channel Channel of which Webhooks were updated | ||||||
|    */ |    */ | ||||||
|   webhooksUpdate: (guild: Guild, channel: GuildTextChannel) => void |   webhooksUpdate: (guild: Guild, channel: GuildTextChannel) => void | ||||||
|  |   /** | ||||||
|  |    * A Slash Command was triggered | ||||||
|  |    */ | ||||||
|  |   interactionCreate: (interaction: Interaction) => void | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,4 +1,6 @@ | ||||||
|  | import { Member } from '../../structures/member.ts' | ||||||
| import { Interaction } from '../../structures/slash.ts' | import { Interaction } from '../../structures/slash.ts' | ||||||
|  | import { GuildTextChannel } from '../../structures/textChannel.ts' | ||||||
| import { InteractionPayload } from '../../types/slash.ts' | import { InteractionPayload } from '../../types/slash.ts' | ||||||
| import { Gateway, GatewayEventHandler } from '../index.ts' | import { Gateway, GatewayEventHandler } from '../index.ts' | ||||||
| 
 | 
 | ||||||
|  | @ -6,6 +8,22 @@ export const interactionCreate: GatewayEventHandler = async ( | ||||||
|   gateway: Gateway, |   gateway: Gateway, | ||||||
|   d: InteractionPayload |   d: InteractionPayload | ||||||
| ) => { | ) => { | ||||||
|   const interaction = new Interaction(gateway.client, d) |   const guild = await gateway.client.guilds.get(d.guild_id) | ||||||
|  |   if (guild === undefined) return | ||||||
|  | 
 | ||||||
|  |   await guild.members.set(d.member.user.id, d.member) | ||||||
|  |   const member = ((await guild.members.get( | ||||||
|  |     d.member.user.id | ||||||
|  |   )) as unknown) as Member | ||||||
|  | 
 | ||||||
|  |   const channel = | ||||||
|  |     (await gateway.client.channels.get<GuildTextChannel>(d.channel_id)) ?? | ||||||
|  |     (await gateway.client.channels.fetch<GuildTextChannel>(d.channel_id)) | ||||||
|  | 
 | ||||||
|  |   const interaction = new Interaction(gateway.client, d, { | ||||||
|  |     member, | ||||||
|  |     guild, | ||||||
|  |     channel | ||||||
|  |   }) | ||||||
|   gateway.client.emit('interactionCreate', interaction) |   gateway.client.emit('interactionCreate', interaction) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -12,6 +12,7 @@ import { EmojisManager } from '../managers/emojis.ts' | ||||||
| import { ActivityGame, ClientActivity } from '../types/presence.ts' | import { ActivityGame, ClientActivity } from '../types/presence.ts' | ||||||
| import { ClientEvents } from '../gateway/handlers/index.ts' | import { ClientEvents } from '../gateway/handlers/index.ts' | ||||||
| import { Extension } from './extensions.ts' | import { Extension } from './extensions.ts' | ||||||
|  | import { SlashClient } from './slashClient.ts' | ||||||
| 
 | 
 | ||||||
| /** OS related properties sent with Gateway Identify */ | /** OS related properties sent with Gateway Identify */ | ||||||
| export interface ClientProperties { | export interface ClientProperties { | ||||||
|  | @ -72,6 +73,8 @@ export class Client extends EventEmitter { | ||||||
|   fetchUncachedReactions: boolean = false |   fetchUncachedReactions: boolean = false | ||||||
|   /** Client Properties */ |   /** Client Properties */ | ||||||
|   clientProperties: ClientProperties |   clientProperties: ClientProperties | ||||||
|  |   /** Slash-Commands Management client */ | ||||||
|  |   slash: SlashClient | ||||||
| 
 | 
 | ||||||
|   users: UsersManager = new UsersManager(this) |   users: UsersManager = new UsersManager(this) | ||||||
|   guilds: GuildManager = new GuildManager(this) |   guilds: GuildManager = new GuildManager(this) | ||||||
|  | @ -133,6 +136,8 @@ export class Client extends EventEmitter { | ||||||
|             device: 'harmony' |             device: 'harmony' | ||||||
|           } |           } | ||||||
|         : options.clientProperties |         : options.clientProperties | ||||||
|  | 
 | ||||||
|  |     this.slash = new SlashClient(this) | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   /** |   /** | ||||||
|  |  | ||||||
							
								
								
									
										144
									
								
								src/models/slashClient.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								src/models/slashClient.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,144 @@ | ||||||
|  | import { Guild } from '../structures/guild.ts' | ||||||
|  | import { Interaction } from '../structures/slash.ts' | ||||||
|  | import { | ||||||
|  |   APPLICATION_COMMAND, | ||||||
|  |   APPLICATION_COMMANDS, | ||||||
|  |   APPLICATION_GUILD_COMMAND, | ||||||
|  |   APPLICATION_GUILD_COMMANDS | ||||||
|  | } from '../types/endpoint.ts' | ||||||
|  | import { | ||||||
|  |   SlashCommandOption, | ||||||
|  |   SlashCommandPartial, | ||||||
|  |   SlashCommandPayload | ||||||
|  | } from '../types/slash.ts' | ||||||
|  | import { Collection } from '../utils/collection.ts' | ||||||
|  | import { Client } from './client.ts' | ||||||
|  | 
 | ||||||
|  | export interface SlashOptions { | ||||||
|  |   enabled?: boolean | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export class SlashCommand { | ||||||
|  |   id: string | ||||||
|  |   applicationID: string | ||||||
|  |   name: string | ||||||
|  |   description: string | ||||||
|  |   options: SlashCommandOption[] | ||||||
|  | 
 | ||||||
|  |   constructor(data: SlashCommandPayload) { | ||||||
|  |     this.id = data.id | ||||||
|  |     this.applicationID = data.application_id | ||||||
|  |     this.name = data.name | ||||||
|  |     this.description = data.description | ||||||
|  |     this.options = data.options | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export class SlashCommands { | ||||||
|  |   client: Client | ||||||
|  |   slash: SlashClient | ||||||
|  | 
 | ||||||
|  |   constructor(client: Client) { | ||||||
|  |     this.client = client | ||||||
|  |     this.slash = client.slash | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   /** Get all Global Slash Commands */ | ||||||
|  |   async all(): Promise<Collection<string, SlashCommand>> { | ||||||
|  |     const col = new Collection<string, SlashCommand>() | ||||||
|  | 
 | ||||||
|  |     const res = (await this.client.rest.get( | ||||||
|  |       APPLICATION_COMMANDS(this.client.user?.id as string) | ||||||
|  |     )) as SlashCommandPayload[] | ||||||
|  |     if (!Array.isArray(res)) return col | ||||||
|  | 
 | ||||||
|  |     for (const raw of res) { | ||||||
|  |       col.set(raw.id, new SlashCommand(raw)) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return col | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   /** Get a Guild's Slash Commands */ | ||||||
|  |   async guild( | ||||||
|  |     guild: Guild | string | ||||||
|  |   ): Promise<Collection<string, SlashCommand>> { | ||||||
|  |     const col = new Collection<string, SlashCommand>() | ||||||
|  | 
 | ||||||
|  |     const res = (await this.client.rest.get( | ||||||
|  |       APPLICATION_GUILD_COMMANDS( | ||||||
|  |         this.client.user?.id as string, | ||||||
|  |         typeof guild === 'string' ? guild : guild.id | ||||||
|  |       ) | ||||||
|  |     )) as SlashCommandPayload[] | ||||||
|  |     if (!Array.isArray(res)) return col | ||||||
|  | 
 | ||||||
|  |     for (const raw of res) { | ||||||
|  |       col.set(raw.id, new SlashCommand(raw)) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return col | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   /** Create a Slash Command (global or Guild) */ | ||||||
|  |   async create( | ||||||
|  |     data: SlashCommandPartial, | ||||||
|  |     guild?: Guild | string | ||||||
|  |   ): Promise<SlashCommand> { | ||||||
|  |     const payload = await this.client.rest.post( | ||||||
|  |       guild === undefined | ||||||
|  |         ? APPLICATION_COMMANDS(this.client.user?.id as string) | ||||||
|  |         : APPLICATION_GUILD_COMMANDS( | ||||||
|  |             this.client.user?.id as string, | ||||||
|  |             typeof guild === 'string' ? guild : guild.id | ||||||
|  |           ), | ||||||
|  |       data | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|  |     return new SlashCommand(payload) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   async edit( | ||||||
|  |     id: string, | ||||||
|  |     data: SlashCommandPayload, | ||||||
|  |     guild?: Guild | ||||||
|  |   ): Promise<SlashCommands> { | ||||||
|  |     await this.client.rest.patch( | ||||||
|  |       guild === undefined | ||||||
|  |         ? APPLICATION_COMMAND(this.client.user?.id as string, id) | ||||||
|  |         : APPLICATION_GUILD_COMMAND( | ||||||
|  |             this.client.user?.id as string, | ||||||
|  |             typeof guild === 'string' ? guild : guild.id, | ||||||
|  |             id | ||||||
|  |           ), | ||||||
|  |       data | ||||||
|  |     ) | ||||||
|  |     return this | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export class SlashClient { | ||||||
|  |   client: Client | ||||||
|  |   enabled: boolean = true | ||||||
|  |   commands: SlashCommands | ||||||
|  | 
 | ||||||
|  |   constructor(client: Client, options?: SlashOptions) { | ||||||
|  |     this.client = client | ||||||
|  |     this.commands = new SlashCommands(client) | ||||||
|  | 
 | ||||||
|  |     if (options !== undefined) { | ||||||
|  |       this.enabled = options.enabled ?? true | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     this.client.on('interactionCreate', (interaction) => | ||||||
|  |       this.process(interaction) | ||||||
|  |     ) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   process(interaction: Interaction): any {} | ||||||
|  | 
 | ||||||
|  |   handle(fn: (interaction: Interaction) => any): SlashClient { | ||||||
|  |     this.process = fn | ||||||
|  |     return this | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | @ -1,6 +1,5 @@ | ||||||
| import { Client } from '../models/client.ts' | import { Client } from '../models/client.ts' | ||||||
| import { INTERACTION_CALLBACK } from '../types/endpoint.ts' | import { INTERACTION_CALLBACK } from '../types/endpoint.ts' | ||||||
| import { MemberPayload } from '../types/guild.ts' |  | ||||||
| import { | import { | ||||||
|   InteractionData, |   InteractionData, | ||||||
|   InteractionPayload, |   InteractionPayload, | ||||||
|  | @ -8,6 +7,10 @@ import { | ||||||
|   InteractionResponseType |   InteractionResponseType | ||||||
| } from '../types/slash.ts' | } from '../types/slash.ts' | ||||||
| import { Embed } from './embed.ts' | import { Embed } from './embed.ts' | ||||||
|  | import { Guild } from './guild.ts' | ||||||
|  | import { Member } from './member.ts' | ||||||
|  | import { GuildTextChannel } from './textChannel.ts' | ||||||
|  | import { User } from './user.ts' | ||||||
| 
 | 
 | ||||||
| export interface InteractionResponse { | export interface InteractionResponse { | ||||||
|   type?: InteractionResponseType |   type?: InteractionResponseType | ||||||
|  | @ -21,17 +24,37 @@ export class Interaction { | ||||||
|   client: Client |   client: Client | ||||||
|   type: number |   type: number | ||||||
|   token: string |   token: string | ||||||
|   member: MemberPayload |  | ||||||
|   id: string |   id: string | ||||||
|   data: InteractionData |   data: InteractionData | ||||||
|  |   channel: GuildTextChannel | ||||||
|  |   guild: Guild | ||||||
|  |   member: Member | ||||||
| 
 | 
 | ||||||
|   constructor(client: Client, data: InteractionPayload) { |   constructor( | ||||||
|  |     client: Client, | ||||||
|  |     data: InteractionPayload, | ||||||
|  |     others: { | ||||||
|  |       channel: GuildTextChannel | ||||||
|  |       guild: Guild | ||||||
|  |       member: Member | ||||||
|  |     } | ||||||
|  |   ) { | ||||||
|     this.client = client |     this.client = client | ||||||
|     this.type = data.type |     this.type = data.type | ||||||
|     this.token = data.token |     this.token = data.token | ||||||
|     this.member = data.member |     this.member = others.member | ||||||
|     this.id = data.id |     this.id = data.id | ||||||
|     this.data = data.data |     this.data = data.data | ||||||
|  |     this.guild = others.guild | ||||||
|  |     this.channel = others.channel | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   get user(): User { | ||||||
|  |     return this.member.user | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   get name(): string { | ||||||
|  |     return this.data.name | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   async respond(data: InteractionResponse): Promise<Interaction> { |   async respond(data: InteractionResponse): Promise<Interaction> { | ||||||
|  |  | ||||||
|  | @ -1,15 +1,62 @@ | ||||||
| import { Client, Intents } from '../../mod.ts' | import { Client, Intents } from '../../mod.ts' | ||||||
|  | import { SlashCommandOptionType } from '../types/slash.ts' | ||||||
| import { TOKEN } from './config.ts' | import { TOKEN } from './config.ts' | ||||||
| 
 | 
 | ||||||
| const client = new Client() | const client = new Client() | ||||||
| 
 | 
 | ||||||
| client.on('ready', () => { | client.on('ready', () => { | ||||||
|   console.log('Logged in!') |   console.log('Logged in!') | ||||||
|  |   client.slash.commands | ||||||
|  |     .create( | ||||||
|  |       { | ||||||
|  |         name: 'eval', | ||||||
|  |         description: 'Run some JS code!', | ||||||
|  |         options: [ | ||||||
|  |           { | ||||||
|  |             name: 'code', | ||||||
|  |             description: 'Code to run', | ||||||
|  |             type: SlashCommandOptionType.STRING, | ||||||
|  |             required: true | ||||||
|  |           } | ||||||
|  |         ] | ||||||
|  |       }, | ||||||
|  |       '783319033205751809' | ||||||
|  |     ) | ||||||
|  |     .then(console.log) | ||||||
| }) | }) | ||||||
| 
 | 
 | ||||||
| client.on('interactionCreate', async (d) => { | client.on('interactionCreate', async (d) => { | ||||||
|  |   if (d.name === 'eval') { | ||||||
|  |     if (d.user.id !== '422957901716652033') { | ||||||
|  |       d.respond({ | ||||||
|  |         content: 'This command can only be used by owner!' | ||||||
|  |       }) | ||||||
|  |     } else { | ||||||
|  |       const code = d.data.options.find((e) => e.name === 'code') | ||||||
|  |         ?.value as string | ||||||
|  |       try { | ||||||
|  |         // eslint-disable-next-line no-eval
 | ||||||
|  |         let evaled = eval(code) | ||||||
|  |         if (evaled instanceof Promise) evaled = await evaled | ||||||
|  |         if (typeof evaled === 'object') evaled = Deno.inspect(evaled) | ||||||
|  |         let res = `${evaled}`.substring(0, 1990) | ||||||
|  |         while (client.token !== undefined && res.includes(client.token)) { | ||||||
|  |           res = res.replace(client.token, '[REMOVED]') | ||||||
|  |         } | ||||||
|  |         d.respond({ | ||||||
|  |           content: '```js\n' + `${res}` + '\n```' | ||||||
|  |         }) | ||||||
|  |       } catch (e) { | ||||||
|  |         d.respond({ | ||||||
|  |           content: '```js\n' + `${e.stack}` + '\n```' | ||||||
|  |         }) | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |     return | ||||||
|  |   } | ||||||
|   await d.respond({ |   await d.respond({ | ||||||
|     content: `Hi, ${d.member.user.username}!` |     content: `Hi, ${d.member.user.username}!`, | ||||||
|  |     flags: 64 | ||||||
|   }) |   }) | ||||||
| }) | }) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -24,6 +24,8 @@ export interface InteractionPayload { | ||||||
|   member: MemberPayload |   member: MemberPayload | ||||||
|   id: string |   id: string | ||||||
|   data: InteractionData |   data: InteractionData | ||||||
|  |   guild_id: string | ||||||
|  |   channel_id: string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export interface SlashCommandChoice { | export interface SlashCommandChoice { | ||||||
|  | @ -50,12 +52,17 @@ export interface SlashCommandOption { | ||||||
|   choices?: SlashCommandChoice[] |   choices?: SlashCommandChoice[] | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export interface SlashCommandPayload { | export interface SlashCommandPartial { | ||||||
|   name: string |   name: string | ||||||
|   description: string |   description: string | ||||||
|   options: SlashCommandOption[] |   options: SlashCommandOption[] | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | export interface SlashCommandPayload extends SlashCommandPartial { | ||||||
|  |   id: string | ||||||
|  |   application_id: string | ||||||
|  | } | ||||||
|  | 
 | ||||||
| export enum InteractionResponseType { | export enum InteractionResponseType { | ||||||
|   PONG = 1, |   PONG = 1, | ||||||
|   ACKNOWLEDGE = 2, |   ACKNOWLEDGE = 2, | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue