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(),
|
||||
typeof guild === 'string' ? guild : guild.id
|
||||
)
|
||||
)) as SlashCommandPayload[]
|
||||
const res = (await this.rest.api.applications[this.slash.getID()].guilds[
|
||||
typeof guild === 'string' ? guild : guild.id
|
||||
].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…
Reference in a new issue