Merge pull request #85 from DjDeveloperr/slash
new options & collectors
This commit is contained in:
commit
556a3c5e2f
9 changed files with 381 additions and 39 deletions
4
mod.ts
4
mod.ts
|
@ -4,7 +4,9 @@ export { Gateway } from './src/gateway/index.ts'
|
|||
export type { ClientEvents } from './src/gateway/handlers/index.ts'
|
||||
export * from './src/models/client.ts'
|
||||
export * from './src/models/slashClient.ts'
|
||||
export { RESTManager } from './src/models/rest.ts'
|
||||
export { RESTManager, TokenType, HttpResponseCode } from './src/models/rest.ts'
|
||||
export type { RequestHeaders } from './src/models/rest.ts'
|
||||
export type { RESTOptions } from './src/models/rest.ts'
|
||||
export * from './src/models/cacheAdapter.ts'
|
||||
export {
|
||||
Command,
|
||||
|
|
|
@ -348,4 +348,11 @@ export interface ClientEvents {
|
|||
* @param message Debug message
|
||||
*/
|
||||
debug: [message: string]
|
||||
|
||||
/**
|
||||
* Raw event which gives you access to raw events DISPATCH'd from Gateway
|
||||
* @param evt Event name string
|
||||
* @param payload Payload JSON of the event
|
||||
*/
|
||||
raw: [evt: string, payload: any]
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import { User } from '../structures/user.ts'
|
||||
import { GatewayIntents } from '../types/gateway.ts'
|
||||
import { Gateway } from '../gateway/index.ts'
|
||||
import { RESTManager } from './rest.ts'
|
||||
import { RESTManager, RESTOptions, TokenType } from './rest.ts'
|
||||
import { EventEmitter } from '../../deps.ts'
|
||||
import { DefaultCacheAdapter, ICacheAdapter } from './cacheAdapter.ts'
|
||||
import { UsersManager } from '../managers/users.ts'
|
||||
|
@ -20,6 +20,7 @@ import { Application } from '../structures/application.ts'
|
|||
import { Invite } from '../structures/invite.ts'
|
||||
import { INVITE } from '../types/endpoint.ts'
|
||||
import { ClientEvents } from '../gateway/handlers/index.ts'
|
||||
import type { Collector } from './collectors.ts'
|
||||
|
||||
/** OS related properties sent with Gateway Identify */
|
||||
export interface ClientProperties {
|
||||
|
@ -54,6 +55,10 @@ export interface ClientOptions {
|
|||
clientProperties?: ClientProperties
|
||||
/** Enable/Disable Slash Commands Integration (enabled by default) */
|
||||
enableSlash?: boolean
|
||||
/** Disable taking token from env if not provided (token is taken from env if present by default) */
|
||||
disableEnvToken?: boolean
|
||||
/** Override REST Options */
|
||||
restOptions?: RESTOptions
|
||||
}
|
||||
|
||||
export declare interface Client {
|
||||
|
@ -89,7 +94,7 @@ export class Client extends EventEmitter {
|
|||
/** Gateway object */
|
||||
gateway?: Gateway
|
||||
/** REST Manager - used to make all requests */
|
||||
rest: RESTManager = new RESTManager(this)
|
||||
rest: RESTManager
|
||||
/** User which Client logs in to, undefined until logs in */
|
||||
user?: User
|
||||
/** WebSocket ping of Client */
|
||||
|
@ -118,8 +123,6 @@ export class Client extends EventEmitter {
|
|||
channels: ChannelsManager = new ChannelsManager(this)
|
||||
emojis: EmojisManager = new EmojisManager(this)
|
||||
|
||||
/** Whether the REST Manager will use Canary API or not */
|
||||
canary: boolean = false
|
||||
/** Client's presence. Startup one if set before connecting */
|
||||
presence: ClientPresence = new ClientPresence()
|
||||
_decoratedEvents?: {
|
||||
|
@ -140,6 +143,7 @@ export class Client extends EventEmitter {
|
|||
shard: number = 0
|
||||
/** Shard Manager of this Client if Sharded */
|
||||
shardManager?: ShardManager
|
||||
collectors: Set<Collector> = new Set()
|
||||
|
||||
constructor(options: ClientOptions = {}) {
|
||||
super()
|
||||
|
@ -153,7 +157,6 @@ export class Client extends EventEmitter {
|
|||
options.presence instanceof ClientPresence
|
||||
? options.presence
|
||||
: new ClientPresence(options.presence)
|
||||
if (options.canary === true) this.canary = true
|
||||
if (options.messageCacheLifetime !== undefined)
|
||||
this.messageCacheLifetime = options.messageCacheLifetime
|
||||
if (options.reactionCacheLifetime !== undefined)
|
||||
|
@ -185,6 +188,27 @@ export class Client extends EventEmitter {
|
|||
client: this,
|
||||
enabled: options.enableSlash
|
||||
})
|
||||
|
||||
if (this.token === undefined) {
|
||||
try {
|
||||
const token = Deno.env.get('DISCORD_TOKEN')
|
||||
if (token !== undefined) {
|
||||
this.token = token
|
||||
this.debug('Info', 'Found token in ENV')
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
const restOptions: RESTOptions = {
|
||||
token: () => this.token,
|
||||
tokenType: TokenType.Bot,
|
||||
canary: options.canary,
|
||||
client: this
|
||||
}
|
||||
|
||||
if (options.restOptions !== undefined)
|
||||
Object.assign(restOptions, options.restOptions)
|
||||
this.rest = new RESTManager(restOptions)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -244,8 +268,8 @@ export class Client extends EventEmitter {
|
|||
|
||||
/**
|
||||
* This function is used for connecting to discord.
|
||||
* @param token Your token. This is required.
|
||||
* @param intents Gateway intents in array. This is required.
|
||||
* @param token Your token. This is required if not given in ClientOptions.
|
||||
* @param intents Gateway intents in array. This is required if not given in ClientOptions.
|
||||
*/
|
||||
connect(token?: string, intents?: GatewayIntents[]): void {
|
||||
if (token === undefined && this.token !== undefined) token = this.token
|
||||
|
@ -262,9 +286,40 @@ export class Client extends EventEmitter {
|
|||
} else if (intents !== undefined && this.intents === undefined) {
|
||||
this.intents = intents
|
||||
} else throw new Error('No Gateway Intents were provided')
|
||||
|
||||
this.rest.token = token
|
||||
this.gateway = new Gateway(this, token, intents)
|
||||
}
|
||||
|
||||
/** Add a new Collector */
|
||||
addCollector(collector: Collector): boolean {
|
||||
if (this.collectors.has(collector)) return false
|
||||
else {
|
||||
this.collectors.add(collector)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
/** Remove a Collector */
|
||||
removeCollector(collector: Collector): boolean {
|
||||
if (!this.collectors.has(collector)) return false
|
||||
else {
|
||||
this.collectors.delete(collector)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
emit(event: keyof ClientEvents, ...args: any[]): boolean {
|
||||
const collectors: Collector[] = []
|
||||
for (const collector of this.collectors.values()) {
|
||||
if (collector.event === event) collectors.push(collector)
|
||||
}
|
||||
if (collectors.length !== 0) {
|
||||
this.collectors.forEach((collector) => collector._fire(...args))
|
||||
}
|
||||
return super.emit(event, ...args)
|
||||
}
|
||||
|
||||
/** Wait for an Event (optionally satisfying an event) to occur */
|
||||
async waitFor<K extends keyof ClientEvents>(
|
||||
event: K,
|
||||
|
@ -293,10 +348,13 @@ export class Client extends EventEmitter {
|
|||
|
||||
/** Event decorator to create an Event handler from function */
|
||||
export function event(name?: keyof ClientEvents) {
|
||||
return function (client: Client | Extension, prop: keyof ClientEvents) {
|
||||
return function (
|
||||
client: Client | Extension,
|
||||
prop: keyof ClientEvents | string
|
||||
) {
|
||||
const listener = ((client as unknown) as {
|
||||
[name in keyof ClientEvents]: (...args: ClientEvents[name]) => any
|
||||
})[prop]
|
||||
})[name ?? ((prop as unknown) as keyof ClientEvents)]
|
||||
if (typeof listener !== 'function')
|
||||
throw new Error('@event decorator requires a function')
|
||||
if (client._decoratedEvents === undefined) client._decoratedEvents = {}
|
||||
|
|
162
src/models/collectors.ts
Normal file
162
src/models/collectors.ts
Normal file
|
@ -0,0 +1,162 @@
|
|||
import { Collection } from '../utils/collection.ts'
|
||||
import { EventEmitter } from '../../deps.ts'
|
||||
import type { Client } from './client.ts'
|
||||
|
||||
export type CollectorFilter = (...args: any[]) => boolean | Promise<boolean>
|
||||
|
||||
export interface CollectorOptions {
|
||||
/** Event name to listen for */
|
||||
event: string
|
||||
/** Optionally Client object for deinitOnEnd functionality */
|
||||
client?: Client
|
||||
/** Filter function */
|
||||
filter?: CollectorFilter
|
||||
/** Max entries to collect */
|
||||
max?: number
|
||||
/** Whether or not to de-initialize on end */
|
||||
deinitOnEnd?: boolean
|
||||
/** Timeout to end the Collector if not fulfilled if any filter or max */
|
||||
timeout?: number
|
||||
}
|
||||
|
||||
export class Collector extends EventEmitter {
|
||||
client?: Client
|
||||
private _started: boolean = false
|
||||
event: string
|
||||
filter: CollectorFilter = () => true
|
||||
collected: Collection<string, any[]> = new Collection()
|
||||
max?: number
|
||||
deinitOnEnd: boolean = false
|
||||
timeout?: number
|
||||
private _timer?: number
|
||||
|
||||
get started(): boolean {
|
||||
return this._started
|
||||
}
|
||||
|
||||
set started(d: boolean) {
|
||||
if (d !== this._started) {
|
||||
this._started = d
|
||||
if (d) this.emit('start')
|
||||
else {
|
||||
if (this.deinitOnEnd && this.client !== undefined)
|
||||
this.deinit(this.client)
|
||||
this.emit('end')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constructor(options: CollectorOptions | string) {
|
||||
super()
|
||||
if (typeof options === 'string') this.event = options
|
||||
else {
|
||||
this.event = options.event
|
||||
this.client = options.client
|
||||
this.filter = options.filter ?? (() => true)
|
||||
this.max = options.max
|
||||
this.deinitOnEnd = options.deinitOnEnd ?? false
|
||||
this.timeout = options.timeout
|
||||
}
|
||||
}
|
||||
|
||||
/** Start collecting */
|
||||
collect(): Collector {
|
||||
this.started = true
|
||||
if (this.client !== undefined) this.init(this.client)
|
||||
if (this._timer !== undefined) clearTimeout(this._timer)
|
||||
if (this.timeout !== undefined) {
|
||||
this._timer = setTimeout(() => {
|
||||
this.end()
|
||||
}, this.timeout)
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
/** End collecting */
|
||||
end(): Collector {
|
||||
this.started = false
|
||||
if (this._timer !== undefined) clearTimeout(this._timer)
|
||||
return this
|
||||
}
|
||||
|
||||
/** Reset collector and start again */
|
||||
reset(): Collector {
|
||||
this.collected = new Collection()
|
||||
this.collect()
|
||||
return this
|
||||
}
|
||||
|
||||
/** Init the Collector on Client */
|
||||
init(client: Client): Collector {
|
||||
this.client = client
|
||||
client.addCollector(this)
|
||||
return this
|
||||
}
|
||||
|
||||
/** De initialize the Collector i.e. remove cleanly */
|
||||
deinit(client: Client): Collector {
|
||||
client.removeCollector(this)
|
||||
return this
|
||||
}
|
||||
|
||||
/** Checks we may want to perform on an extended version of Collector */
|
||||
protected check(..._args: any[]): boolean | Promise<boolean> {
|
||||
return true
|
||||
}
|
||||
|
||||
/** Fire the Collector */
|
||||
async _fire(...args: any[]): Promise<void> {
|
||||
if (!this.started) return
|
||||
const check = await this.check(...args)
|
||||
if (!check) return
|
||||
const filter = await this.filter(...args)
|
||||
if (!filter) return
|
||||
this.collected.set((Number(this.collected.size) + 1).toString(), args)
|
||||
this.emit('collect', ...args)
|
||||
if (
|
||||
this.max !== undefined &&
|
||||
// linter: send help
|
||||
this.max < Number(this.collected.size) + 1
|
||||
) {
|
||||
this.end()
|
||||
}
|
||||
}
|
||||
|
||||
/** Set filter of the Collector */
|
||||
when(filter: CollectorFilter): Collector {
|
||||
this.filter = filter
|
||||
return this
|
||||
}
|
||||
|
||||
/** Add a new listener for 'collect' event */
|
||||
each(handler: CallableFunction): Collector {
|
||||
this.on('collect', () => handler())
|
||||
return this
|
||||
}
|
||||
|
||||
/** Returns a Promise resolved when Collector ends or a timeout occurs */
|
||||
async wait(timeout: number = this.timeout ?? 0): Promise<Collector> {
|
||||
return await new Promise((resolve, reject) => {
|
||||
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
||||
if (!timeout)
|
||||
throw new Error(
|
||||
'Timeout is required parameter if not given in CollectorOptions'
|
||||
)
|
||||
|
||||
let done = false
|
||||
const onend = (): void => {
|
||||
done = true
|
||||
this.removeListener('end', onend)
|
||||
resolve(this)
|
||||
}
|
||||
|
||||
this.on('end', onend)
|
||||
setTimeout(() => {
|
||||
if (!done) {
|
||||
this.removeListener('end', onend)
|
||||
reject(new Error('Timeout'))
|
||||
}
|
||||
}, timeout)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
import * as baseEndpoints from '../consts/urlsAndVersions.ts'
|
||||
import { Collection } from '../utils/collection.ts'
|
||||
import { Client } from './client.ts'
|
||||
|
||||
export type RequestMethods =
|
||||
| 'get'
|
||||
|
@ -60,15 +61,23 @@ export type MethodFunction = (
|
|||
) => Promise<any>
|
||||
|
||||
export interface APIMap extends MethodFunction {
|
||||
/** Make a GET request to current route */
|
||||
get: APIMap
|
||||
/** Make a POST request to current route */
|
||||
post: APIMap
|
||||
/** Make a PATCH request to current route */
|
||||
patch: APIMap
|
||||
/** Make a PUT request to current route */
|
||||
put: APIMap
|
||||
/** Make a DELETE request to current route */
|
||||
delete: APIMap
|
||||
/** Make a HEAD request to current route */
|
||||
head: APIMap
|
||||
/** Continue building API Route */
|
||||
[name: string]: APIMap
|
||||
}
|
||||
|
||||
/** API Route builder function */
|
||||
export const builder = (rest: RESTManager, acum = '/'): APIMap => {
|
||||
const routes = {}
|
||||
const proxy = new Proxy(routes, {
|
||||
|
@ -94,25 +103,76 @@ export const builder = (rest: RESTManager, acum = '/'): APIMap => {
|
|||
}
|
||||
|
||||
export interface RESTOptions {
|
||||
token?: string
|
||||
/** Token to use for authorization */
|
||||
token?: string | (() => string | undefined)
|
||||
/** Headers to patch with if any */
|
||||
headers?: { [name: string]: string | undefined }
|
||||
/** Whether to use Canary instance of Discord API or not */
|
||||
canary?: boolean
|
||||
/** Discord REST API version to use */
|
||||
version?: 6 | 7 | 8
|
||||
/** Token Type to use for Authorization */
|
||||
tokenType?: TokenType
|
||||
/** User Agent to use (Header) */
|
||||
userAgent?: string
|
||||
/** Optional Harmony client */
|
||||
client?: Client
|
||||
}
|
||||
|
||||
/** Token Type for REST API. */
|
||||
export enum TokenType {
|
||||
/** Token type for Bot User */
|
||||
Bot = 'Bot',
|
||||
/** Token Type for OAuth2 */
|
||||
Bearer = 'Bearer',
|
||||
/** No Token Type. Can be used for User accounts. */
|
||||
None = ''
|
||||
}
|
||||
|
||||
/** An easier to use interface for interacting with Discord REST API. */
|
||||
export class RESTManager {
|
||||
client?: RESTOptions
|
||||
queues: { [key: string]: QueuedItem[] } = {}
|
||||
rateLimits = new Collection<string, RateLimit>()
|
||||
/** Whether we are globally ratelimited or not */
|
||||
globalRateLimit: boolean = false
|
||||
/** Whether requests are being processed or not */
|
||||
processing: boolean = false
|
||||
/** API Version being used by REST Manager */
|
||||
version: number = 8
|
||||
/**
|
||||
* API Map - easy to use way for interacting with Discord API.
|
||||
*
|
||||
* Examples:
|
||||
* * ```ts
|
||||
* rest.api.users['123'].get().then(userPayload => doSomething)
|
||||
* ```
|
||||
* * ```ts
|
||||
* rest.api.guilds['123'].channels.post({ name: 'my-channel', type: 0 }).then(channelPayload => {})
|
||||
* ```
|
||||
*/
|
||||
api: APIMap
|
||||
/** Token being used for Authorization */
|
||||
token?: string | (() => string | undefined)
|
||||
/** Token Type of the Token if any */
|
||||
tokenType: TokenType = TokenType.Bot
|
||||
/** Headers object which patch the current ones */
|
||||
headers: any = {}
|
||||
/** Optional custom User Agent (header) */
|
||||
userAgent?: string
|
||||
/** Whether REST Manager is using Canary API */
|
||||
canary?: boolean
|
||||
/** Optional Harmony Client object */
|
||||
client?: Client
|
||||
|
||||
constructor(client?: RESTOptions) {
|
||||
this.client = client
|
||||
constructor(options?: RESTOptions) {
|
||||
this.api = builder(this)
|
||||
if (client?.version !== undefined) this.version = client.version
|
||||
if (options?.token !== undefined) this.token = options.token
|
||||
if (options?.version !== undefined) this.version = options.version
|
||||
if (options?.headers !== undefined) this.headers = options.headers
|
||||
if (options?.tokenType !== undefined) this.tokenType = options.tokenType
|
||||
if (options?.userAgent !== undefined) this.userAgent = options.userAgent
|
||||
if (options?.canary !== undefined) this.canary = options.canary
|
||||
if (options?.client !== undefined) this.client = options.client
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
this.handleRateLimits()
|
||||
}
|
||||
|
@ -193,13 +253,16 @@ export class RESTManager {
|
|||
|
||||
private prepare(body: any, method: RequestMethods): { [key: string]: any } {
|
||||
const headers: RequestHeaders = {
|
||||
'User-Agent': `DiscordBot (harmony, https://github.com/harmony-org/harmony)`
|
||||
'User-Agent':
|
||||
this.userAgent ??
|
||||
`DiscordBot (harmony, https://github.com/harmony-org/harmony)`
|
||||
}
|
||||
|
||||
if (this.client !== undefined)
|
||||
headers.Authorization = `Bot ${this.client.token}`
|
||||
|
||||
if (this.client?.token === undefined) delete headers.Authorization
|
||||
if (this.token !== undefined) {
|
||||
const token = typeof this.token === 'string' ? this.token : this.token()
|
||||
if (token !== undefined)
|
||||
headers.Authorization = `${this.tokenType} ${token}`.trim()
|
||||
}
|
||||
|
||||
if (method === 'get' || method === 'head' || method === 'delete')
|
||||
body = undefined
|
||||
|
@ -220,9 +283,7 @@ export class RESTManager {
|
|||
headers['Content-Type'] = 'application/json'
|
||||
}
|
||||
|
||||
if (this.client?.headers !== undefined)
|
||||
Object.assign(headers, this.client.headers)
|
||||
|
||||
if (this.headers !== undefined) Object.assign(headers, this.headers)
|
||||
const data: { [name: string]: any } = {
|
||||
headers,
|
||||
body: body?.file ?? JSON.stringify(body),
|
||||
|
@ -305,13 +366,25 @@ export class RESTManager {
|
|||
body: any,
|
||||
data: { [key: string]: any },
|
||||
reject: CallableFunction
|
||||
): Promise<undefined> {
|
||||
): Promise<void> {
|
||||
const status = response.status
|
||||
|
||||
// We have hit ratelimit - this should not happen
|
||||
if (status === HttpResponseCode.TooManyRequests) {
|
||||
if (this.client !== undefined)
|
||||
this.client.emit('rateLimit', {
|
||||
method: data.method,
|
||||
url: response.url,
|
||||
body
|
||||
})
|
||||
reject(new Error('RateLimited'))
|
||||
return
|
||||
}
|
||||
|
||||
// It's a normal status code... just continue
|
||||
if (
|
||||
(status >= 200 && status < 400) ||
|
||||
status === HttpResponseCode.NoContent ||
|
||||
status === HttpResponseCode.TooManyRequests
|
||||
status === HttpResponseCode.NoContent
|
||||
)
|
||||
return
|
||||
|
||||
|
@ -322,9 +395,7 @@ export class RESTManager {
|
|||
|
||||
if (status === HttpResponseCode.Unauthorized)
|
||||
reject(
|
||||
new DiscordAPIError(
|
||||
`Request was not successful (Unauthorized). Invalid Token.\n${text}`
|
||||
)
|
||||
new DiscordAPIError(`Request was Unauthorized. Invalid Token.\n${text}`)
|
||||
)
|
||||
|
||||
// At this point we know it is error
|
||||
|
@ -342,7 +413,7 @@ export class RESTManager {
|
|||
}
|
||||
}) ?? {}
|
||||
).map((entry) => {
|
||||
return [entry[0], entry[1]._errors]
|
||||
return [entry[0], entry[1]._errors ?? []]
|
||||
})
|
||||
)
|
||||
}
|
||||
|
@ -379,7 +450,7 @@ export class RESTManager {
|
|||
}
|
||||
|
||||
/**
|
||||
* Makes a Request to Discord API
|
||||
* Makes a Request to Discord API.
|
||||
* @param method HTTP Method to use
|
||||
* @param url URL of the Request
|
||||
* @param body Body to send with Request
|
||||
|
@ -422,7 +493,18 @@ export class RESTManager {
|
|||
let urlToUse =
|
||||
method === 'get' && query !== '' ? `${url}?${query}` : url
|
||||
|
||||
if (this.client?.canary === true) {
|
||||
// It doesn't start with HTTP, that means it's an incomplete URL
|
||||
if (!urlToUse.startsWith('http')) {
|
||||
if (!urlToUse.startsWith('/')) urlToUse = `/${urlToUse}`
|
||||
urlToUse =
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
|
||||
baseEndpoints.DISCORD_API_URL +
|
||||
'/v' +
|
||||
baseEndpoints.DISCORD_API_VERSION +
|
||||
urlToUse
|
||||
}
|
||||
|
||||
if (this.canary === true && urlToUse.startsWith('http')) {
|
||||
const split = urlToUse.split('//')
|
||||
urlToUse = split[0] + '//canary.' + split[1]
|
||||
}
|
||||
|
|
|
@ -47,7 +47,9 @@ export class Webhook {
|
|||
rest: RESTManager
|
||||
|
||||
get url(): string {
|
||||
return `${DISCORD_API_URL}/v${DISCORD_API_VERSION}/webhooks/${this.id}/${this.token}`
|
||||
return `${DISCORD_API_URL}/v${
|
||||
this.rest.version ?? DISCORD_API_VERSION
|
||||
}/webhooks/${this.id}/${this.token}`
|
||||
}
|
||||
|
||||
constructor(data: WebhookPayload, client?: Client, rest?: RESTManager) {
|
||||
|
@ -170,7 +172,7 @@ export class Webhook {
|
|||
* @param options Options to edit the Webhook.
|
||||
*/
|
||||
async edit(options: WebhookEditOptions): Promise<Webhook> {
|
||||
if (options.channelID !== undefined && this.rest.client === undefined)
|
||||
if (options.channelID !== undefined && this.client === undefined)
|
||||
throw new Error('Authentication is required for editing Webhook Channel')
|
||||
if (
|
||||
options.avatar !== undefined &&
|
||||
|
|
|
@ -11,6 +11,7 @@ import {
|
|||
ChannelTypes,
|
||||
GuildTextChannel
|
||||
} from '../../mod.ts'
|
||||
import { Collector } from '../models/collectors.ts'
|
||||
import { TOKEN } from './config.ts'
|
||||
|
||||
const client = new Client({
|
||||
|
@ -122,6 +123,26 @@ client.on('messageCreate', async (msg: Message) => {
|
|||
)
|
||||
|
||||
msg.channel.send(`Received: ${receivedMsg?.content}`)
|
||||
} else if (msg.content.startsWith('!collect') === true) {
|
||||
let count = parseInt(msg.content.replace(/\D/g, ''))
|
||||
if (isNaN(count)) count = 5
|
||||
await msg.channel.send(`Collecting ${count} messages for 5s`)
|
||||
const coll = new Collector({
|
||||
event: 'messageCreate',
|
||||
filter: (m) => m.author.id === msg.author.id,
|
||||
deinitOnEnd: true,
|
||||
max: count,
|
||||
timeout: 5000
|
||||
})
|
||||
coll.init(client)
|
||||
coll.collect()
|
||||
coll.on('start', () => msg.channel.send('[COL] Started'))
|
||||
coll.on('end', () =>
|
||||
msg.channel.send(`[COL] Ended. Collected Size: ${coll.collected.size}`)
|
||||
)
|
||||
coll.on('collect', (msg) =>
|
||||
msg.channel.send(`[COL] Collect: ${msg.content}`)
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
@ -11,10 +11,7 @@ import {
|
|||
GuildTextChannel
|
||||
} from '../../mod.ts'
|
||||
import { LL_IP, LL_PASS, LL_PORT, TOKEN } from './config.ts'
|
||||
import {
|
||||
Manager,
|
||||
Player
|
||||
} from '../../deps.ts'
|
||||
import { Manager, Player } from 'https://deno.land/x/lavadeno/mod.ts'
|
||||
import { Interaction } from '../structures/slash.ts'
|
||||
import { slash } from '../models/client.ts'
|
||||
// import { SlashCommandOptionType } from '../types/slash.ts'
|
||||
|
|
|
@ -9,6 +9,11 @@ export class MyClient extends Client {
|
|||
console.log(`Logged in as ${this.user?.tag}!`)
|
||||
}
|
||||
|
||||
@event('debug')
|
||||
debugEvt(txt: string): void {
|
||||
console.log(txt)
|
||||
}
|
||||
|
||||
@slash()
|
||||
send(d: Interaction): void {
|
||||
d.respond({
|
||||
|
@ -92,5 +97,11 @@ export class MyClient extends Client {
|
|||
}
|
||||
}
|
||||
|
||||
const client = new MyClient()
|
||||
const client = new MyClient({
|
||||
presence: {
|
||||
status: 'dnd',
|
||||
activity: { name: 'Slash Commands', type: 'LISTENING' }
|
||||
}
|
||||
})
|
||||
|
||||
client.connect(TOKEN, Intents.None)
|
||||
|
|
Loading…
Reference in a new issue