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…
Reference in a new issue