feat: slash builde
This commit is contained in:
		
							parent
							
								
									cac3c5c9e3
								
							
						
					
					
						commit
						da0bfc12c7
					
				
					 6 changed files with 220 additions and 49 deletions
				
			
		|  | @ -247,6 +247,7 @@ export function event(name?: string) { | |||
|   } | ||||
| } | ||||
| 
 | ||||
| /** Decorator to create a Slash Command handler */ | ||||
| export function slash(name?: string, guild?: string) { | ||||
|   return function (client: Client | SlashModule, prop: string) { | ||||
|     if (client._decoratedSlash === undefined) client._decoratedSlash = [] | ||||
|  | @ -262,6 +263,7 @@ export function slash(name?: string, guild?: string) { | |||
|   } | ||||
| } | ||||
| 
 | ||||
| /** Decorator to create a Sub-Slash Command handler */ | ||||
| export function subslash(parent: string, name?: string, guild?: string) { | ||||
|   return function (client: Client | SlashModule, prop: string) { | ||||
|     if (client._decoratedSlash === undefined) client._decoratedSlash = [] | ||||
|  | @ -279,6 +281,7 @@ export function subslash(parent: string, name?: string, guild?: string) { | |||
|   } | ||||
| } | ||||
| 
 | ||||
| /** Decorator to create a Grouped Slash Command handler */ | ||||
| export function groupslash( | ||||
|   parent: string, | ||||
|   group: string, | ||||
|  | @ -303,6 +306,7 @@ export function groupslash( | |||
|   } | ||||
| } | ||||
| 
 | ||||
| /** Decorator to add a Slash Module to Client */ | ||||
| export function slashModule() { | ||||
|   return function (client: Client, prop: string) { | ||||
|     if (client._decoratedSlashModules === undefined) | ||||
|  |  | |||
|  | @ -97,6 +97,7 @@ export interface RESTOptions { | |||
|   token?: string | ||||
|   headers?: { [name: string]: string | undefined } | ||||
|   canary?: boolean | ||||
|   version?: 6 | 7 | 8 | ||||
| } | ||||
| 
 | ||||
| export class RESTManager { | ||||
|  | @ -111,6 +112,7 @@ export class RESTManager { | |||
|   constructor(client?: RESTOptions) { | ||||
|     this.client = client | ||||
|     this.api = builder(this) | ||||
|     if (client?.version !== undefined) this.version = client.version | ||||
|     // eslint-disable-next-line @typescript-eslint/no-floating-promises
 | ||||
|     this.handleRateLimits() | ||||
|   } | ||||
|  |  | |||
|  | @ -1,14 +1,10 @@ | |||
| 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 { | ||||
|   InteractionType, | ||||
|   SlashCommandChoice, | ||||
|   SlashCommandOption, | ||||
|   SlashCommandOptionType, | ||||
|   SlashCommandPartial, | ||||
|   SlashCommandPayload | ||||
| } from '../types/slash.ts' | ||||
|  | @ -43,6 +39,147 @@ export class SlashCommand { | |||
|   } | ||||
| } | ||||
| 
 | ||||
| export interface CreateOptions { | ||||
|   name: string | ||||
|   description?: string | ||||
|   options?: Array<SlashCommandOption | SlashOptionCallable> | ||||
|   choices?: Array<SlashCommandChoice | string> | ||||
| } | ||||
| 
 | ||||
| function createSlashOption( | ||||
|   type: SlashCommandOptionType, | ||||
|   data: CreateOptions | ||||
| ): SlashCommandOption { | ||||
|   return { | ||||
|     name: data.name, | ||||
|     type, | ||||
|     description: | ||||
|       type === 0 || type === 1 | ||||
|         ? undefined | ||||
|         : data.description ?? 'No description.', | ||||
|     options: data.options?.map((e) => | ||||
|       typeof e === 'function' ? e(SlashOptionCallableBuilder) : e | ||||
|     ), | ||||
|     choices: | ||||
|       data.choices === undefined | ||||
|         ? undefined | ||||
|         : data.choices.map((e) => | ||||
|             typeof e === 'string' ? { name: e, value: e } : e | ||||
|           ) | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| // eslint-disable-next-line @typescript-eslint/no-extraneous-class
 | ||||
| export class SlashOptionCallableBuilder { | ||||
|   static string(data: CreateOptions): SlashCommandOption { | ||||
|     return createSlashOption(SlashCommandOptionType.STRING, data) | ||||
|   } | ||||
| 
 | ||||
|   static bool(data: CreateOptions): SlashCommandOption { | ||||
|     return createSlashOption(SlashCommandOptionType.BOOLEAN, data) | ||||
|   } | ||||
| 
 | ||||
|   static subCommand(data: CreateOptions): SlashCommandOption { | ||||
|     return createSlashOption(SlashCommandOptionType.SUB_COMMAND, data) | ||||
|   } | ||||
| 
 | ||||
|   static subCommandGroup(data: CreateOptions): SlashCommandOption { | ||||
|     return createSlashOption(SlashCommandOptionType.SUB_COMMAND_GROUP, data) | ||||
|   } | ||||
| 
 | ||||
|   static role(data: CreateOptions): SlashCommandOption { | ||||
|     return createSlashOption(SlashCommandOptionType.ROLE, data) | ||||
|   } | ||||
| 
 | ||||
|   static channel(data: CreateOptions): SlashCommandOption { | ||||
|     return createSlashOption(SlashCommandOptionType.CHANNEL, data) | ||||
|   } | ||||
| 
 | ||||
|   static user(data: CreateOptions): SlashCommandOption { | ||||
|     return createSlashOption(SlashCommandOptionType.USER, data) | ||||
|   } | ||||
| 
 | ||||
|   static number(data: CreateOptions): SlashCommandOption { | ||||
|     return createSlashOption(SlashCommandOptionType.INTEGER, data) | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| export type SlashOptionCallable = ( | ||||
|   o: typeof SlashOptionCallableBuilder | ||||
| ) => SlashCommandOption | ||||
| 
 | ||||
| export type SlashBuilderOptionsData = | ||||
|   | Array<SlashCommandOption | SlashOptionCallable> | ||||
|   | { | ||||
|       [name: string]: | ||||
|         | { | ||||
|             description: string | ||||
|             type: SlashCommandOptionType | ||||
|             options?: SlashCommandOption[] | ||||
|             choices?: SlashCommandChoice[] | ||||
|           } | ||||
|         | SlashOptionCallable | ||||
|     } | ||||
| 
 | ||||
| function buildOptionsArray( | ||||
|   options: SlashBuilderOptionsData | ||||
| ): SlashCommandOption[] { | ||||
|   return Array.isArray(options) | ||||
|     ? options.map((op) => | ||||
|         typeof op === 'function' ? op(SlashOptionCallableBuilder) : op | ||||
|       ) | ||||
|     : Object.entries(options).map((entry) => | ||||
|         typeof entry[1] === 'function' | ||||
|           ? entry[1](SlashOptionCallableBuilder) | ||||
|           : Object.assign(entry[1], { name: entry[0] }) | ||||
|       ) | ||||
| } | ||||
| 
 | ||||
| export class SlashBuilder { | ||||
|   data: SlashCommandPartial | ||||
| 
 | ||||
|   constructor( | ||||
|     name?: string, | ||||
|     description?: string, | ||||
|     options?: SlashBuilderOptionsData | ||||
|   ) { | ||||
|     this.data = { | ||||
|       name: name ?? '', | ||||
|       description: description ?? 'No description.', | ||||
|       options: options === undefined ? [] : buildOptionsArray(options) | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   name(name: string): SlashBuilder { | ||||
|     this.data.name = name | ||||
|     return this | ||||
|   } | ||||
| 
 | ||||
|   description(desc: string): SlashBuilder { | ||||
|     this.data.description = desc | ||||
|     return this | ||||
|   } | ||||
| 
 | ||||
|   option(option: SlashOptionCallable | SlashCommandOption): SlashBuilder { | ||||
|     if (this.data.options === undefined) this.data.options = [] | ||||
|     this.data.options.push( | ||||
|       typeof option === 'function' ? option(SlashOptionCallableBuilder) : option | ||||
|     ) | ||||
|     return this | ||||
|   } | ||||
| 
 | ||||
|   options(options: SlashBuilderOptionsData): SlashBuilder { | ||||
|     this.data.options = buildOptionsArray(options) | ||||
|     return this | ||||
|   } | ||||
| 
 | ||||
|   export(): SlashCommandPartial { | ||||
|     if (this.data.name === '') | ||||
|       throw new Error('Name was not provided in Slash Builder') | ||||
|     return this.data | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| export class SlashCommandsManager { | ||||
|   slash: SlashClient | ||||
| 
 | ||||
|  | @ -58,9 +195,9 @@ export class SlashCommandsManager { | |||
|   async all(): Promise<Collection<string, SlashCommand>> { | ||||
|     const col = new Collection<string, SlashCommand>() | ||||
| 
 | ||||
|     const res = (await this.rest.get( | ||||
|       APPLICATION_COMMANDS(this.slash.getID()) | ||||
|     )) as SlashCommandPayload[] | ||||
|     const res = (await this.rest.api.applications[ | ||||
|       this.slash.getID() | ||||
|     ].commands.get()) as SlashCommandPayload[] | ||||
|     if (!Array.isArray(res)) return col | ||||
| 
 | ||||
|     for (const raw of res) { | ||||
|  | @ -77,12 +214,9 @@ export class SlashCommandsManager { | |||
|   ): Promise<Collection<string, SlashCommand>> { | ||||
|     const col = new Collection<string, SlashCommand>() | ||||
| 
 | ||||
|     const res = (await this.rest.get( | ||||
|       APPLICATION_GUILD_COMMANDS( | ||||
|         this.slash.getID(), | ||||
|     const res = (await this.rest.api.applications[this.slash.getID()].guilds[ | ||||
|       typeof guild === 'string' ? guild : guild.id | ||||
|       ) | ||||
|     )) as SlashCommandPayload[] | ||||
|     ].commands.get()) as SlashCommandPayload[] | ||||
|     if (!Array.isArray(res)) return col | ||||
| 
 | ||||
|     for (const raw of res) { | ||||
|  | @ -99,15 +233,14 @@ export class SlashCommandsManager { | |||
|     data: SlashCommandPartial, | ||||
|     guild?: Guild | string | ||||
|   ): Promise<SlashCommand> { | ||||
|     const payload = await this.rest.post( | ||||
|     const route = | ||||
|       guild === undefined | ||||
|         ? APPLICATION_COMMANDS(this.slash.getID()) | ||||
|         : APPLICATION_GUILD_COMMANDS( | ||||
|             this.slash.getID(), | ||||
|         ? this.rest.api.applications[this.slash.getID()].commands | ||||
|         : this.rest.api.applications[this.slash.getID()].guilds[ | ||||
|             typeof guild === 'string' ? guild : guild.id | ||||
|           ), | ||||
|       data | ||||
|     ) | ||||
|           ].commands | ||||
| 
 | ||||
|     const payload = await route.post(data) | ||||
| 
 | ||||
|     const cmd = new SlashCommand(this, payload) | ||||
|     cmd._guild = | ||||
|  | @ -122,16 +255,14 @@ export class SlashCommandsManager { | |||
|     data: SlashCommandPartial, | ||||
|     guild?: Guild | string | ||||
|   ): Promise<SlashCommandsManager> { | ||||
|     await this.rest.patch( | ||||
|     const route = | ||||
|       guild === undefined | ||||
|         ? APPLICATION_COMMAND(this.slash.getID(), id) | ||||
|         : APPLICATION_GUILD_COMMAND( | ||||
|             this.slash.getID(), | ||||
|             typeof guild === 'string' ? guild : guild.id, | ||||
|             id | ||||
|           ), | ||||
|       data | ||||
|     ) | ||||
|         ? this.rest.api.applications[this.slash.getID()].commands[id] | ||||
|         : this.rest.api.applications[this.slash.getID()].guilds[ | ||||
|             typeof guild === 'string' ? guild : guild.id | ||||
|           ].commands[id] | ||||
| 
 | ||||
|     await route.patch(data) | ||||
|     return this | ||||
|   } | ||||
| 
 | ||||
|  | @ -140,29 +271,28 @@ export class SlashCommandsManager { | |||
|     id: string, | ||||
|     guild?: Guild | string | ||||
|   ): Promise<SlashCommandsManager> { | ||||
|     await this.rest.delete( | ||||
|     const route = | ||||
|       guild === undefined | ||||
|         ? APPLICATION_COMMAND(this.slash.getID(), id) | ||||
|         : APPLICATION_GUILD_COMMAND( | ||||
|             this.slash.getID(), | ||||
|             typeof guild === 'string' ? guild : guild.id, | ||||
|             id | ||||
|           ) | ||||
|     ) | ||||
|         ? this.rest.api.applications[this.slash.getID()].commands[id] | ||||
|         : this.rest.api.applications[this.slash.getID()].guilds[ | ||||
|             typeof guild === 'string' ? guild : guild.id | ||||
|           ].commands[id] | ||||
| 
 | ||||
|     await route.delete() | ||||
|     return this | ||||
|   } | ||||
| 
 | ||||
|   /** Get a Slash Command (global or Guild) */ | ||||
|   async get(id: string, guild?: Guild | string): Promise<SlashCommand> { | ||||
|     const data = await this.rest.get( | ||||
|     const route = | ||||
|       guild === undefined | ||||
|         ? APPLICATION_COMMAND(this.slash.getID(), id) | ||||
|         : APPLICATION_GUILD_COMMAND( | ||||
|             this.slash.getID(), | ||||
|             typeof guild === 'string' ? guild : guild.id, | ||||
|             id | ||||
|           ) | ||||
|     ) | ||||
|         ? this.rest.api.applications[this.slash.getID()].commands[id] | ||||
|         : this.rest.api.applications[this.slash.getID()].guilds[ | ||||
|             typeof guild === 'string' ? guild : guild.id | ||||
|           ].commands[id] | ||||
| 
 | ||||
|     const data = await route.get() | ||||
| 
 | ||||
|     return new SlashCommand(this, data) | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -205,6 +205,10 @@ class VCExtension extends Extension { | |||
| 
 | ||||
| const client = new MyClient() | ||||
| 
 | ||||
| client.on('raw', (e, d) => { | ||||
|   if (e === 'READY') console.log(d) | ||||
| }) | ||||
| 
 | ||||
| client.extensions.load(VCExtension) | ||||
| 
 | ||||
| client.connect(TOKEN, Intents.None) | ||||
|  |  | |||
|  | @ -1,6 +1,36 @@ | |||
| import { SlashClient } from '../models/slashClient.ts' | ||||
| import { SlashClient, SlashBuilder } from '../models/slashClient.ts' | ||||
| import { TOKEN } from './config.ts' | ||||
| 
 | ||||
| const slash = new SlashClient({ token: TOKEN }) | ||||
| 
 | ||||
| slash.commands.all().then(console.log) | ||||
| 
 | ||||
| const cmd = new SlashBuilder() | ||||
|   .name('searchmusic') | ||||
|   .description('Search for music.') | ||||
|   .option((o) => | ||||
|     o.string({ name: 'query', description: 'Query to search with.' }) | ||||
|   ) | ||||
|   .option((o) => | ||||
|     o.string({ | ||||
|       name: 'engine', | ||||
|       description: 'Search engine to use.', | ||||
|       choices: [{ name: 'YouTube', value: 'youtube' }, 'Spotify'] | ||||
|     }) | ||||
|   ) | ||||
|   .options({ | ||||
|     query: { | ||||
|       description: 'Query UWU', | ||||
|       type: 3 | ||||
|     }, | ||||
|     engine: { | ||||
|       description: 'Engine UWU', | ||||
|       type: 3, | ||||
|       choices: [ | ||||
|         { name: 'YouTube', value: 'youtube' }, | ||||
|         { name: 'Spotify', value: 'spotify' } | ||||
|       ] | ||||
|     } | ||||
|   }) | ||||
| 
 | ||||
| console.log(JSON.stringify(cmd.export())) | ||||
|  |  | |||
|  | @ -66,7 +66,8 @@ export enum SlashCommandOptionType { | |||
| 
 | ||||
| export interface SlashCommandOption { | ||||
|   name: string | ||||
|   description: string | ||||
|   /** Description not required in Sub-Command or Sub-Command-Group */ | ||||
|   description?: string | ||||
|   type: SlashCommandOptionType | ||||
|   required?: boolean | ||||
|   default?: boolean | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue