Merge pull request #66 from DjDeveloperr/slash
SlashClient & RESTManager can run alone and added APIMap
This commit is contained in:
commit
3695b81de6
6 changed files with 192 additions and 43 deletions
|
@ -18,6 +18,7 @@ import { GatewayCache } from '../managers/gatewayCache.ts'
|
||||||
import { delay } from '../utils/delay.ts'
|
import { delay } from '../utils/delay.ts'
|
||||||
import { VoiceChannel } from '../structures/guildVoiceChannel.ts'
|
import { VoiceChannel } from '../structures/guildVoiceChannel.ts'
|
||||||
import { Guild } from '../structures/guild.ts'
|
import { Guild } from '../structures/guild.ts'
|
||||||
|
import EventEmitter from 'https://deno.land/std@0.74.0/node/events.ts'
|
||||||
|
|
||||||
export interface RequestMembersOptions {
|
export interface RequestMembersOptions {
|
||||||
limit?: number
|
limit?: number
|
||||||
|
@ -34,11 +35,11 @@ export interface VoiceStateOptions {
|
||||||
export const RECONNECT_REASON = 'harmony-reconnect'
|
export const RECONNECT_REASON = 'harmony-reconnect'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles Discord gateway connection.
|
* Handles Discord Gateway connection.
|
||||||
*
|
*
|
||||||
* You should not use this and rather use Client class.
|
* You should not use this and rather use Client class.
|
||||||
*/
|
*/
|
||||||
class Gateway {
|
export class Gateway extends EventEmitter {
|
||||||
websocket: WebSocket
|
websocket: WebSocket
|
||||||
token: string
|
token: string
|
||||||
intents: GatewayIntents[]
|
intents: GatewayIntents[]
|
||||||
|
@ -55,6 +56,7 @@ class Gateway {
|
||||||
private timedIdentify: number | null = null
|
private timedIdentify: number | null = null
|
||||||
|
|
||||||
constructor(client: Client, token: string, intents: GatewayIntents[]) {
|
constructor(client: Client, token: string, intents: GatewayIntents[]) {
|
||||||
|
super()
|
||||||
this.token = token
|
this.token = token
|
||||||
this.intents = intents
|
this.intents = intents
|
||||||
this.client = client
|
this.client = client
|
||||||
|
@ -74,6 +76,7 @@ class Gateway {
|
||||||
private onopen(): void {
|
private onopen(): void {
|
||||||
this.connected = true
|
this.connected = true
|
||||||
this.debug('Connected to Gateway!')
|
this.debug('Connected to Gateway!')
|
||||||
|
this.emit('connect')
|
||||||
}
|
}
|
||||||
|
|
||||||
private async onmessage(event: MessageEvent): Promise<void> {
|
private async onmessage(event: MessageEvent): Promise<void> {
|
||||||
|
@ -112,6 +115,7 @@ class Gateway {
|
||||||
case GatewayOpcodes.HEARTBEAT_ACK:
|
case GatewayOpcodes.HEARTBEAT_ACK:
|
||||||
this.heartbeatServerResponded = true
|
this.heartbeatServerResponded = true
|
||||||
this.client.ping = Date.now() - this.lastPingTimestamp
|
this.client.ping = Date.now() - this.lastPingTimestamp
|
||||||
|
this.emit('ping', this.client.ping)
|
||||||
this.debug(
|
this.debug(
|
||||||
`Received Heartbeat Ack. Ping Recognized: ${this.client.ping}ms`
|
`Received Heartbeat Ack. Ping Recognized: ${this.client.ping}ms`
|
||||||
)
|
)
|
||||||
|
@ -142,6 +146,7 @@ class Gateway {
|
||||||
await this.cache.set('seq', s)
|
await this.cache.set('seq', s)
|
||||||
}
|
}
|
||||||
if (t !== null && t !== undefined) {
|
if (t !== null && t !== undefined) {
|
||||||
|
this.emit(t, d)
|
||||||
this.client.emit('raw', t, d)
|
this.client.emit('raw', t, d)
|
||||||
|
|
||||||
const handler = gatewayHandlers[t]
|
const handler = gatewayHandlers[t]
|
||||||
|
@ -158,9 +163,11 @@ class Gateway {
|
||||||
this.sequenceID = d.seq
|
this.sequenceID = d.seq
|
||||||
await this.cache.set('seq', d.seq)
|
await this.cache.set('seq', d.seq)
|
||||||
await this.cache.set('session_id', this.sessionID)
|
await this.cache.set('session_id', this.sessionID)
|
||||||
|
this.emit('resume')
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case GatewayOpcodes.RECONNECT: {
|
case GatewayOpcodes.RECONNECT: {
|
||||||
|
this.emit('reconnectRequired')
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
this.reconnect()
|
this.reconnect()
|
||||||
break
|
break
|
||||||
|
@ -172,6 +179,7 @@ class Gateway {
|
||||||
|
|
||||||
private async onclose(event: CloseEvent): Promise<void> {
|
private async onclose(event: CloseEvent): Promise<void> {
|
||||||
if (event.reason === RECONNECT_REASON) return
|
if (event.reason === RECONNECT_REASON) return
|
||||||
|
this.emit('close', event.code, event.reason)
|
||||||
this.debug(`Connection Closed with code: ${event.code}`)
|
this.debug(`Connection Closed with code: ${event.code}`)
|
||||||
|
|
||||||
if (event.code === GatewayCloseCodes.UNKNOWN_ERROR) {
|
if (event.code === GatewayCloseCodes.UNKNOWN_ERROR) {
|
||||||
|
@ -223,7 +231,7 @@ class Gateway {
|
||||||
|
|
||||||
private onerror(event: Event | ErrorEvent): void {
|
private onerror(event: Event | ErrorEvent): void {
|
||||||
const eventError = event as ErrorEvent
|
const eventError = event as ErrorEvent
|
||||||
console.log(eventError)
|
this.emit('error', eventError)
|
||||||
}
|
}
|
||||||
|
|
||||||
private async sendIdentify(forceNewSession?: boolean): Promise<void> {
|
private async sendIdentify(forceNewSession?: boolean): Promise<void> {
|
||||||
|
@ -266,6 +274,7 @@ class Gateway {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.debug('Sending Identify payload...')
|
this.debug('Sending Identify payload...')
|
||||||
|
this.emit('sentIdentify')
|
||||||
this.send({
|
this.send({
|
||||||
op: GatewayOpcodes.IDENTIFY,
|
op: GatewayOpcodes.IDENTIFY,
|
||||||
d: payload
|
d: payload
|
||||||
|
@ -291,6 +300,7 @@ class Gateway {
|
||||||
seq: this.sequenceID ?? null
|
seq: this.sequenceID ?? null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.emit('sentResume')
|
||||||
this.debug('Sending Resume payload...')
|
this.debug('Sending Resume payload...')
|
||||||
this.send(resumePayload)
|
this.send(resumePayload)
|
||||||
}
|
}
|
||||||
|
@ -341,6 +351,7 @@ class Gateway {
|
||||||
}
|
}
|
||||||
|
|
||||||
async reconnect(forceNew?: boolean): Promise<void> {
|
async reconnect(forceNew?: boolean): Promise<void> {
|
||||||
|
this.emit('reconnecting')
|
||||||
clearInterval(this.heartbeatIntervalID)
|
clearInterval(this.heartbeatIntervalID)
|
||||||
if (forceNew === true) {
|
if (forceNew === true) {
|
||||||
await this.cache.delete('session_id')
|
await this.cache.delete('session_id')
|
||||||
|
@ -351,6 +362,7 @@ class Gateway {
|
||||||
}
|
}
|
||||||
|
|
||||||
initWebsocket(): void {
|
initWebsocket(): void {
|
||||||
|
this.emit('init')
|
||||||
this.debug('Initializing WebSocket...')
|
this.debug('Initializing WebSocket...')
|
||||||
this.websocket = new WebSocket(
|
this.websocket = new WebSocket(
|
||||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
||||||
|
@ -414,5 +426,3 @@ class Gateway {
|
||||||
}
|
}
|
||||||
|
|
||||||
export type GatewayEventHandler = (gateway: Gateway, d: any) => void
|
export type GatewayEventHandler = (gateway: Gateway, d: any) => void
|
||||||
|
|
||||||
export { Gateway }
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ import { SlashClient } from './slashClient.ts'
|
||||||
import { Interaction } from '../structures/slash.ts'
|
import { Interaction } from '../structures/slash.ts'
|
||||||
import { SlashModule } from './slashModule.ts'
|
import { SlashModule } from './slashModule.ts'
|
||||||
import type { ShardManager } from './shard.ts'
|
import type { ShardManager } from './shard.ts'
|
||||||
|
import { Application } from '../structures/application.ts'
|
||||||
|
|
||||||
/** OS related properties sent with Gateway Identify */
|
/** OS related properties sent with Gateway Identify */
|
||||||
export interface ClientProperties {
|
export interface ClientProperties {
|
||||||
|
@ -26,6 +27,8 @@ export interface ClientProperties {
|
||||||
|
|
||||||
/** Some Client Options to modify behaviour */
|
/** Some Client Options to modify behaviour */
|
||||||
export interface ClientOptions {
|
export interface ClientOptions {
|
||||||
|
/** ID of the Client/Application to initialize Slash Client REST */
|
||||||
|
id?: string
|
||||||
/** Token of the Bot/User */
|
/** Token of the Bot/User */
|
||||||
token?: string
|
token?: string
|
||||||
/** Gateway Intents */
|
/** Gateway Intents */
|
||||||
|
@ -100,6 +103,7 @@ export class Client extends EventEmitter {
|
||||||
}>
|
}>
|
||||||
|
|
||||||
_decoratedSlashModules?: SlashModule[]
|
_decoratedSlashModules?: SlashModule[]
|
||||||
|
_id?: string
|
||||||
|
|
||||||
private readonly _untypedOn = this.on
|
private readonly _untypedOn = this.on
|
||||||
|
|
||||||
|
@ -120,6 +124,7 @@ export class Client extends EventEmitter {
|
||||||
|
|
||||||
constructor(options: ClientOptions = {}) {
|
constructor(options: ClientOptions = {}) {
|
||||||
super()
|
super()
|
||||||
|
this._id = options.id
|
||||||
this.token = options.token
|
this.token = options.token
|
||||||
this.intents = options.intents
|
this.intents = options.intents
|
||||||
this.forceNewSession = options.forceNewSession
|
this.forceNewSession = options.forceNewSession
|
||||||
|
@ -156,7 +161,9 @@ export class Client extends EventEmitter {
|
||||||
}
|
}
|
||||||
: options.clientProperties
|
: options.clientProperties
|
||||||
|
|
||||||
this.slash = new SlashClient(this, {
|
this.slash = new SlashClient({
|
||||||
|
id: () => this.getEstimatedID(),
|
||||||
|
client: this,
|
||||||
enabled: options.enableSlash
|
enabled: options.enableSlash
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -185,8 +192,24 @@ export class Client extends EventEmitter {
|
||||||
this.emit('debug', `[${tag}] ${msg}`)
|
this.emit('debug', `[${tag}] ${msg}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(DjDeveloperr): Implement this
|
getEstimatedID(): string {
|
||||||
// fetchApplication(): Promise<Application>
|
if (this.user !== undefined) return this.user.id
|
||||||
|
else if (this.token !== undefined) {
|
||||||
|
try {
|
||||||
|
return atob(this.token.split('.')[0])
|
||||||
|
} catch (e) {
|
||||||
|
return this._id ?? 'unknown'
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return this._id ?? 'unknown'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Fetch Application of the Client */
|
||||||
|
async fetchApplication(): Promise<Application> {
|
||||||
|
const app = await this.rest.api.oauth2.applications['@me'].get()
|
||||||
|
return new Application(this, app)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function is used for connecting to discord.
|
* This function is used for connecting to discord.
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import * as baseEndpoints from '../consts/urlsAndVersions.ts'
|
import * as baseEndpoints from '../consts/urlsAndVersions.ts'
|
||||||
import { Client } from './client.ts'
|
|
||||||
import { Collection } from '../utils/collection.ts'
|
import { Collection } from '../utils/collection.ts'
|
||||||
|
|
||||||
export type RequestMethods =
|
export type RequestMethods =
|
||||||
|
@ -51,15 +50,67 @@ export interface RateLimit {
|
||||||
bucket: string | null
|
bucket: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const METHODS = ['get', 'post', 'patch', 'put', 'delete', 'head']
|
||||||
|
|
||||||
|
export type MethodFunction = (
|
||||||
|
body?: unknown,
|
||||||
|
maxRetries?: number,
|
||||||
|
bucket?: string | null,
|
||||||
|
rawResponse?: boolean
|
||||||
|
) => Promise<any>
|
||||||
|
|
||||||
|
export interface APIMap extends MethodFunction {
|
||||||
|
get: APIMap
|
||||||
|
post: APIMap
|
||||||
|
patch: APIMap
|
||||||
|
put: APIMap
|
||||||
|
delete: APIMap
|
||||||
|
head: APIMap
|
||||||
|
[name: string]: APIMap
|
||||||
|
}
|
||||||
|
|
||||||
|
export const builder = (rest: RESTManager, acum = '/'): APIMap => {
|
||||||
|
const routes = {}
|
||||||
|
const proxy = new Proxy(routes, {
|
||||||
|
get: (_, p, __) => {
|
||||||
|
if (p === 'toString') return () => acum
|
||||||
|
if (METHODS.includes(String(p))) {
|
||||||
|
const method = ((rest as unknown) as {
|
||||||
|
[name: string]: MethodFunction
|
||||||
|
})[String(p)]
|
||||||
|
return async (...args: any[]) =>
|
||||||
|
await method.bind(rest)(
|
||||||
|
`${baseEndpoints.DISCORD_API_URL}/v${rest.version}${acum.substring(
|
||||||
|
0,
|
||||||
|
acum.length - 1
|
||||||
|
)}`,
|
||||||
|
...args
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return builder(rest, acum + String(p) + '/')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return (proxy as unknown) as APIMap
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RESTOptions {
|
||||||
|
token?: string
|
||||||
|
headers?: { [name: string]: string | undefined }
|
||||||
|
canary?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
export class RESTManager {
|
export class RESTManager {
|
||||||
client?: Client
|
client?: RESTOptions
|
||||||
queues: { [key: string]: QueuedItem[] } = {}
|
queues: { [key: string]: QueuedItem[] } = {}
|
||||||
rateLimits = new Collection<string, RateLimit>()
|
rateLimits = new Collection<string, RateLimit>()
|
||||||
globalRateLimit: boolean = false
|
globalRateLimit: boolean = false
|
||||||
processing: boolean = false
|
processing: boolean = false
|
||||||
|
version: number = 8
|
||||||
|
api: APIMap
|
||||||
|
|
||||||
constructor(client?: Client) {
|
constructor(client?: RESTOptions) {
|
||||||
this.client = client
|
this.client = client
|
||||||
|
this.api = builder(this)
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
this.handleRateLimits()
|
this.handleRateLimits()
|
||||||
}
|
}
|
||||||
|
@ -160,10 +211,16 @@ export class RESTManager {
|
||||||
form.append('file', body.file.blob, body.file.name)
|
form.append('file', body.file.blob, body.file.name)
|
||||||
form.append('payload_json', JSON.stringify({ ...body, file: undefined }))
|
form.append('payload_json', JSON.stringify({ ...body, file: undefined }))
|
||||||
body.file = form
|
body.file = form
|
||||||
} else if (body !== undefined && !['get', 'delete'].includes(method)) {
|
} else if (
|
||||||
|
body !== undefined &&
|
||||||
|
!['get', 'delete'].includes(method.toLowerCase())
|
||||||
|
) {
|
||||||
headers['Content-Type'] = 'application/json'
|
headers['Content-Type'] = 'application/json'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.client?.headers !== undefined)
|
||||||
|
Object.assign(headers, this.client.headers)
|
||||||
|
|
||||||
const data: { [name: string]: any } = {
|
const data: { [name: string]: any } = {
|
||||||
headers,
|
headers,
|
||||||
body: body?.file ?? JSON.stringify(body),
|
body: body?.file ?? JSON.stringify(body),
|
||||||
|
|
|
@ -14,10 +14,7 @@ import {
|
||||||
} from '../types/slash.ts'
|
} from '../types/slash.ts'
|
||||||
import { Collection } from '../utils/collection.ts'
|
import { Collection } from '../utils/collection.ts'
|
||||||
import { Client } from './client.ts'
|
import { Client } from './client.ts'
|
||||||
|
import { RESTManager } from './rest.ts'
|
||||||
export interface SlashOptions {
|
|
||||||
enabled?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
export class SlashCommand {
|
export class SlashCommand {
|
||||||
slash: SlashCommandsManager
|
slash: SlashCommandsManager
|
||||||
|
@ -47,20 +44,22 @@ export class SlashCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SlashCommandsManager {
|
export class SlashCommandsManager {
|
||||||
client: Client
|
|
||||||
slash: SlashClient
|
slash: SlashClient
|
||||||
|
|
||||||
constructor(client: Client) {
|
get rest(): RESTManager {
|
||||||
this.client = client
|
return this.slash.rest
|
||||||
this.slash = client.slash
|
}
|
||||||
|
|
||||||
|
constructor(client: SlashClient) {
|
||||||
|
this.slash = client
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get all Global Slash Commands */
|
/** Get all Global Slash Commands */
|
||||||
async all(): Promise<Collection<string, SlashCommand>> {
|
async all(): Promise<Collection<string, SlashCommand>> {
|
||||||
const col = new Collection<string, SlashCommand>()
|
const col = new Collection<string, SlashCommand>()
|
||||||
|
|
||||||
const res = (await this.client.rest.get(
|
const res = (await this.rest.get(
|
||||||
APPLICATION_COMMANDS(this.client.user?.id as string)
|
APPLICATION_COMMANDS(this.slash.getID())
|
||||||
)) as SlashCommandPayload[]
|
)) as SlashCommandPayload[]
|
||||||
if (!Array.isArray(res)) return col
|
if (!Array.isArray(res)) return col
|
||||||
|
|
||||||
|
@ -78,9 +77,9 @@ export class SlashCommandsManager {
|
||||||
): Promise<Collection<string, SlashCommand>> {
|
): Promise<Collection<string, SlashCommand>> {
|
||||||
const col = new Collection<string, SlashCommand>()
|
const col = new Collection<string, SlashCommand>()
|
||||||
|
|
||||||
const res = (await this.client.rest.get(
|
const res = (await this.rest.get(
|
||||||
APPLICATION_GUILD_COMMANDS(
|
APPLICATION_GUILD_COMMANDS(
|
||||||
this.client.user?.id as string,
|
this.slash.getID(),
|
||||||
typeof guild === 'string' ? guild : guild.id
|
typeof guild === 'string' ? guild : guild.id
|
||||||
)
|
)
|
||||||
)) as SlashCommandPayload[]
|
)) as SlashCommandPayload[]
|
||||||
|
@ -100,11 +99,11 @@ export class SlashCommandsManager {
|
||||||
data: SlashCommandPartial,
|
data: SlashCommandPartial,
|
||||||
guild?: Guild | string
|
guild?: Guild | string
|
||||||
): Promise<SlashCommand> {
|
): Promise<SlashCommand> {
|
||||||
const payload = await this.client.rest.post(
|
const payload = await this.rest.post(
|
||||||
guild === undefined
|
guild === undefined
|
||||||
? APPLICATION_COMMANDS(this.client.user?.id as string)
|
? APPLICATION_COMMANDS(this.slash.getID())
|
||||||
: APPLICATION_GUILD_COMMANDS(
|
: APPLICATION_GUILD_COMMANDS(
|
||||||
this.client.user?.id as string,
|
this.slash.getID(),
|
||||||
typeof guild === 'string' ? guild : guild.id
|
typeof guild === 'string' ? guild : guild.id
|
||||||
),
|
),
|
||||||
data
|
data
|
||||||
|
@ -123,11 +122,11 @@ export class SlashCommandsManager {
|
||||||
data: SlashCommandPartial,
|
data: SlashCommandPartial,
|
||||||
guild?: Guild | string
|
guild?: Guild | string
|
||||||
): Promise<SlashCommandsManager> {
|
): Promise<SlashCommandsManager> {
|
||||||
await this.client.rest.patch(
|
await this.rest.patch(
|
||||||
guild === undefined
|
guild === undefined
|
||||||
? APPLICATION_COMMAND(this.client.user?.id as string, id)
|
? APPLICATION_COMMAND(this.slash.getID(), id)
|
||||||
: APPLICATION_GUILD_COMMAND(
|
: APPLICATION_GUILD_COMMAND(
|
||||||
this.client.user?.id as string,
|
this.slash.getID(),
|
||||||
typeof guild === 'string' ? guild : guild.id,
|
typeof guild === 'string' ? guild : guild.id,
|
||||||
id
|
id
|
||||||
),
|
),
|
||||||
|
@ -141,17 +140,31 @@ export class SlashCommandsManager {
|
||||||
id: string,
|
id: string,
|
||||||
guild?: Guild | string
|
guild?: Guild | string
|
||||||
): Promise<SlashCommandsManager> {
|
): Promise<SlashCommandsManager> {
|
||||||
await this.client.rest.delete(
|
await this.rest.delete(
|
||||||
guild === undefined
|
guild === undefined
|
||||||
? APPLICATION_COMMAND(this.client.user?.id as string, id)
|
? APPLICATION_COMMAND(this.slash.getID(), id)
|
||||||
: APPLICATION_GUILD_COMMAND(
|
: APPLICATION_GUILD_COMMAND(
|
||||||
this.client.user?.id as string,
|
this.slash.getID(),
|
||||||
typeof guild === 'string' ? guild : guild.id,
|
typeof guild === 'string' ? guild : guild.id,
|
||||||
id
|
id
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Get a Slash Command (global or Guild) */
|
||||||
|
async get(id: string, guild?: Guild | string): Promise<SlashCommand> {
|
||||||
|
const data = await this.rest.get(
|
||||||
|
guild === undefined
|
||||||
|
? APPLICATION_COMMAND(this.slash.getID(), id)
|
||||||
|
: APPLICATION_GUILD_COMMAND(
|
||||||
|
this.slash.getID(),
|
||||||
|
typeof guild === 'string' ? guild : guild.id,
|
||||||
|
id
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return new SlashCommand(this, data)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SlashCommandHandlerCallback = (interaction: Interaction) => any
|
export type SlashCommandHandlerCallback = (interaction: Interaction) => any
|
||||||
|
@ -163,31 +176,61 @@ export interface SlashCommandHandler {
|
||||||
handler: SlashCommandHandlerCallback
|
handler: SlashCommandHandlerCallback
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SlashOptions {
|
||||||
|
id?: string | (() => string)
|
||||||
|
client?: Client
|
||||||
|
enabled?: boolean
|
||||||
|
token?: string
|
||||||
|
rest?: RESTManager
|
||||||
|
}
|
||||||
|
|
||||||
export class SlashClient {
|
export class SlashClient {
|
||||||
client: Client
|
id: string | (() => string)
|
||||||
|
client?: Client
|
||||||
|
token?: string
|
||||||
enabled: boolean = true
|
enabled: boolean = true
|
||||||
commands: SlashCommandsManager
|
commands: SlashCommandsManager
|
||||||
handlers: SlashCommandHandler[] = []
|
handlers: SlashCommandHandler[] = []
|
||||||
|
rest: RESTManager
|
||||||
|
|
||||||
constructor(client: Client, options?: SlashOptions) {
|
constructor(options: SlashOptions) {
|
||||||
this.client = client
|
let id = options.id
|
||||||
this.commands = new SlashCommandsManager(client)
|
if (options.token !== undefined) id = atob(options.token?.split('.')[0])
|
||||||
|
if (id === undefined)
|
||||||
|
throw new Error('ID could not be found. Pass at least client or token')
|
||||||
|
this.id = id
|
||||||
|
this.client = options.client
|
||||||
|
this.token = options.token
|
||||||
|
this.commands = new SlashCommandsManager(this)
|
||||||
|
|
||||||
if (options !== undefined) {
|
if (options !== undefined) {
|
||||||
this.enabled = options.enabled ?? true
|
this.enabled = options.enabled ?? true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.client._decoratedSlash !== undefined) {
|
if (this.client?._decoratedSlash !== undefined) {
|
||||||
this.client._decoratedSlash.forEach((e) => {
|
this.client._decoratedSlash.forEach((e) => {
|
||||||
this.handlers.push(e)
|
this.handlers.push(e)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
this.client.on('interactionCreate', (interaction) =>
|
this.rest =
|
||||||
|
options.client === undefined
|
||||||
|
? options.rest === undefined
|
||||||
|
? new RESTManager({
|
||||||
|
token: this.token
|
||||||
|
})
|
||||||
|
: options.rest
|
||||||
|
: options.client.rest
|
||||||
|
|
||||||
|
this.client?.on('interactionCreate', (interaction) =>
|
||||||
this._process(interaction)
|
this._process(interaction)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getID(): string {
|
||||||
|
return typeof this.id === 'string' ? this.id : this.id()
|
||||||
|
}
|
||||||
|
|
||||||
/** Adds a new Slash Command Handler */
|
/** Adds a new Slash Command Handler */
|
||||||
handle(handler: SlashCommandHandler): SlashClient {
|
handle(handler: SlashCommandHandler): SlashClient {
|
||||||
this.handlers.push(handler)
|
this.handlers.push(handler)
|
||||||
|
|
|
@ -60,12 +60,12 @@ class MyClient extends CommandClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
@subslash('cmd', 'sub-cmd-no-grp')
|
@subslash('cmd', 'sub-cmd-no-grp')
|
||||||
subCmdNoGrp(d: Interaction): void {
|
subCmdNoGroup(d: Interaction): 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')
|
||||||
subCmdGrp(d: Interaction): void {
|
subCmdGroup(d: Interaction): void {
|
||||||
d.respond({ content: 'sub-cmd-group worked' })
|
d.respond({ content: 'sub-cmd-group worked' })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,14 +74,23 @@ class MyClient extends CommandClient {
|
||||||
console.log(d.name)
|
console.log(d.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@event()
|
||||||
|
raw(evt: string, d: any): void {
|
||||||
|
if (!evt.startsWith('APPLICATION')) return
|
||||||
|
console.log(evt, d)
|
||||||
|
}
|
||||||
|
|
||||||
@event()
|
@event()
|
||||||
ready(): void {
|
ready(): void {
|
||||||
console.log(`Logged in as ${this.user?.tag}!`)
|
console.log(`Logged in as ${this.user?.tag}!`)
|
||||||
this.manager.init(this.user?.id as string)
|
this.manager.init(this.user?.id as string)
|
||||||
|
this.slash.commands.all().then(console.log)
|
||||||
|
|
||||||
|
// this.rest.api.users['422957901716652033'].get().then(console.log)
|
||||||
// client.slash.commands.create(
|
// client.slash.commands.create(
|
||||||
// {
|
// {
|
||||||
// name: 'cmd',
|
// name: 'cmd',
|
||||||
// description: 'Parent command',
|
// description: 'Parent command!',
|
||||||
// options: [
|
// options: [
|
||||||
// {
|
// {
|
||||||
// name: 'sub-cmd-group',
|
// name: 'sub-cmd-group',
|
||||||
|
@ -121,6 +130,7 @@ class MyClient extends CommandClient {
|
||||||
// },
|
// },
|
||||||
// '783319033205751809'
|
// '783319033205751809'
|
||||||
// )
|
// )
|
||||||
|
// client.slash.commands.delete('788719077329207296', '783319033205751809')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,7 +176,7 @@ class VCExtension extends Extension {
|
||||||
|
|
||||||
await player.play(track)
|
await player.play(track)
|
||||||
|
|
||||||
ctx.channel.send(`Now playing ${info.title}!`)
|
ctx.channel.send(`Now playing ${info.title}!\nDebug Track: ${track}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
@command()
|
@command()
|
||||||
|
|
6
src/test/slash-only.ts
Normal file
6
src/test/slash-only.ts
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
import { SlashClient } from '../models/slashClient.ts'
|
||||||
|
import { TOKEN } from './config.ts'
|
||||||
|
|
||||||
|
const slash = new SlashClient({ token: TOKEN })
|
||||||
|
|
||||||
|
slash.commands.all().then(console.log)
|
Loading…
Reference in a new issue