Merge pull request #80 from Helloyunho/waitFor
Change the event typing way and add <Client>.waitFor method
This commit is contained in:
commit
8bd59f925b
3 changed files with 130 additions and 68 deletions
|
@ -99,238 +99,248 @@ export const gatewayHandlers: {
|
|||
INTERACTION_CREATE: interactionCreate
|
||||
}
|
||||
|
||||
export interface EventTypes {
|
||||
[name: string]: (...args: any[]) => void
|
||||
}
|
||||
|
||||
export interface VoiceServerUpdateData {
|
||||
token: string
|
||||
endpoint: string
|
||||
guild: Guild
|
||||
}
|
||||
|
||||
export interface ClientEvents extends EventTypes {
|
||||
export interface ClientEvents {
|
||||
/** When Client has successfully connected to Discord */
|
||||
ready: () => void
|
||||
ready: []
|
||||
/** When a successful reconnect has been made */
|
||||
reconnect: () => void
|
||||
reconnect: []
|
||||
/** When a successful session resume has been done */
|
||||
resumed: () => void
|
||||
resumed: []
|
||||
/**
|
||||
* When a new Channel is created
|
||||
* @param channel New Channel object
|
||||
*/
|
||||
channelCreate: (channel: EveryChannelTypes) => void
|
||||
channelCreate: [channel: EveryChannelTypes]
|
||||
/**
|
||||
* When a Channel was deleted
|
||||
* @param channel Channel object which was deleted
|
||||
*/
|
||||
channelDelete: (channel: EveryChannelTypes) => void
|
||||
channelDelete: [channel: EveryChannelTypes]
|
||||
/**
|
||||
* Channel's Pinned Messages were updated
|
||||
* @param before Channel object before update
|
||||
* @param after Channel object after update
|
||||
*/
|
||||
channelPinsUpdate: (
|
||||
channelPinsUpdate: [
|
||||
before: EveryTextChannelTypes,
|
||||
after: EveryTextChannelTypes
|
||||
) => void
|
||||
]
|
||||
/**
|
||||
* A Channel was updated
|
||||
* @param before Channel object before update
|
||||
* @param after Channel object after update
|
||||
*/
|
||||
channelUpdate: (before: EveryChannelTypes, after: EveryChannelTypes) => void
|
||||
channelUpdate: [before: EveryChannelTypes, after: EveryChannelTypes]
|
||||
/**
|
||||
* A User was banned from a Guild
|
||||
* @param guild The Guild from which User was banned
|
||||
* @param user The User who was banned
|
||||
*/
|
||||
guildBanAdd: (guild: Guild, user: User) => void
|
||||
guildBanAdd: [guild: Guild, user: User]
|
||||
/**
|
||||
* A ban from a User in Guild was elevated
|
||||
* @param guild Guild from which ban was removed
|
||||
* @param user User of which ban was elevated
|
||||
*/
|
||||
guildBanRemove: (guild: Guild, user: User) => void
|
||||
guildBanRemove: [guild: Guild, user: User]
|
||||
/**
|
||||
* Client has joined a new Guild.
|
||||
* @param guild The new Guild object
|
||||
*/
|
||||
guildCreate: (guild: Guild) => void
|
||||
guildCreate: [guild: Guild]
|
||||
/**
|
||||
* A Guild in which Client was either deleted, or bot was kicked
|
||||
* @param guild The Guild object
|
||||
*/
|
||||
guildDelete: (guild: Guild) => void
|
||||
guildDelete: [guild: Guild]
|
||||
/**
|
||||
* A new Emoji was added to Guild
|
||||
* @param guild Guild in which Emoji was added
|
||||
* @param emoji The Emoji which was added
|
||||
*/
|
||||
guildEmojiAdd: (guild: Guild, emoji: Emoji) => void
|
||||
guildEmojiAdd: [guild: Guild, emoji: Emoji]
|
||||
/**
|
||||
* An Emoji was deleted from Guild
|
||||
* @param guild Guild from which Emoji was deleted
|
||||
* @param emoji Emoji which was deleted
|
||||
*/
|
||||
guildEmojiDelete: (guild: Guild, emoji: Emoji) => void
|
||||
guildEmojiDelete: [Guild, Emoji]
|
||||
/**
|
||||
* An Emoji in a Guild was updated
|
||||
* @param guild Guild in which Emoji was updated
|
||||
* @param before Emoji object before update
|
||||
* @param after Emoji object after update
|
||||
*/
|
||||
guildEmojiUpdate: (guild: Guild, before: Emoji, after: Emoji) => void
|
||||
guildEmojiUpdate: [guild: Guild, before: Emoji, after: Emoji]
|
||||
/**
|
||||
* Guild's Integrations were updated
|
||||
* @param guild The Guild object
|
||||
*/
|
||||
guildIntegrationsUpdate: (guild: Guild) => void
|
||||
guildIntegrationsUpdate: [guild: Guild]
|
||||
/**
|
||||
* A new Member has joined a Guild
|
||||
* @param member The Member object
|
||||
*/
|
||||
guildMemberAdd: (member: Member) => void
|
||||
guildMemberAdd: [member: Member]
|
||||
/**
|
||||
* A Guild Member has either left or was kicked from Guild
|
||||
* @param member The Member object
|
||||
*/
|
||||
guildMemberRemove: (member: Member) => void
|
||||
guildMemberRemove: [member: Member]
|
||||
/**
|
||||
* A Guild Member was updated. Nickname changed, role assigned, etc.
|
||||
* @param before Member object before update
|
||||
* @param after Meber object after update
|
||||
*/
|
||||
guildMemberUpdate: (before: Member, after: Member) => void
|
||||
guildMemberUpdate: [before: Member, after: Member]
|
||||
/**
|
||||
* A new Role was created in Guild
|
||||
* @param role The new Role object
|
||||
*/
|
||||
guildRoleCreate: (role: Role) => void
|
||||
guildRoleCreate: [role: Role]
|
||||
/**
|
||||
* A Role was deleted from the Guild
|
||||
* @param role The Role object
|
||||
*/
|
||||
guildRoleDelete: (role: Role) => void
|
||||
guildRoleDelete: [role: Role]
|
||||
/**
|
||||
* A Role was updated in a Guild
|
||||
* @param before Role object before update
|
||||
* @param after Role object after updated
|
||||
*/
|
||||
guildRoleUpdate: (before: Role, after: Role) => void
|
||||
guildRoleUpdate: [before: Role, after: Role]
|
||||
/**
|
||||
* A Guild has been updated. For example name, icon, etc.
|
||||
* @param before Guild object before update
|
||||
* @param after Guild object after update
|
||||
*/
|
||||
guildUpdate: (before: Guild, after: Guild) => void
|
||||
guildUpdate: [before: Guild, after: Guild]
|
||||
/**
|
||||
* A new Message was created (sent)
|
||||
* @param message The new Message object
|
||||
*/
|
||||
messageCreate: (message: Message) => void
|
||||
messageCreate: [message: Message]
|
||||
/**
|
||||
* A Message was deleted.
|
||||
* @param message The Message object
|
||||
*/
|
||||
messageDelete: (message: Message) => void
|
||||
messageDelete: [message: Message]
|
||||
/**
|
||||
* Messages were bulk deleted in a Guild Text Channel
|
||||
* @param channel Channel in which Messages were deleted
|
||||
* @param messages Collection of Messages deleted
|
||||
* @param uncached Set of Messages deleted's IDs which were not cached
|
||||
*/
|
||||
messageDeleteBulk: (
|
||||
messageDeleteBulk: [
|
||||
channel: GuildTextChannel,
|
||||
messages: Collection<string, Message>,
|
||||
uncached: Set<string>
|
||||
) => void
|
||||
]
|
||||
/**
|
||||
* A Message was updated. For example content, embed, etc.
|
||||
* @param before Message object before update
|
||||
* @param after Message object after update
|
||||
*/
|
||||
messageUpdate: (before: Message, after: Message) => void
|
||||
messageUpdate: [before: Message, after: Message]
|
||||
/**
|
||||
* Reaction was added to a Message
|
||||
* @param reaction Reaction object
|
||||
* @param user User who added the reaction
|
||||
*/
|
||||
messageReactionAdd: (reaction: MessageReaction, user: User) => void
|
||||
messageReactionAdd: [reaction: MessageReaction, user: User]
|
||||
/**
|
||||
* Reaction was removed fro a Message
|
||||
* @param reaction Reaction object
|
||||
* @param user User to who removed the reaction
|
||||
*/
|
||||
messageReactionRemove: (reaction: MessageReaction, user: User) => void
|
||||
messageReactionRemove: [reaction: MessageReaction, user: User]
|
||||
/**
|
||||
* All reactions were removed from a Message
|
||||
* @param message Message from which reactions were removed
|
||||
*/
|
||||
messageReactionRemoveAll: (message: Message) => void
|
||||
messageReactionRemoveAll: [message: Message]
|
||||
/**
|
||||
* All reactions of a single Emoji were removed
|
||||
* @param message The Message object
|
||||
* @param emoji The Emoji object
|
||||
*/
|
||||
messageReactionRemoveEmoji: (message: Message, emoji: Emoji) => void
|
||||
messageReactionRemoveEmoji: [message: Message, emoji: Emoji]
|
||||
/**
|
||||
* A User has started typing in a Text Channel
|
||||
* @param user User who started typing
|
||||
* @param channel Channel which user started typing in
|
||||
* @param at Date when user started typing
|
||||
* @param guild Guild which user started typing in (can be undefined)
|
||||
*/
|
||||
typingStart: (
|
||||
typingStart: [
|
||||
user: User,
|
||||
channel: TextChannel,
|
||||
at: Date,
|
||||
guildData?: TypingStartGuildData
|
||||
) => void
|
||||
guild: TypingStartGuildData | undefined
|
||||
]
|
||||
/**
|
||||
* A new Invite was created
|
||||
* @param invite New Invite object
|
||||
*/
|
||||
inviteCreate: (invite: Invite) => void
|
||||
inviteCreate: [invite: Invite]
|
||||
/**
|
||||
* An Invite was deleted
|
||||
* @param invite Invite object
|
||||
*/
|
||||
inviteDelete: (invite: Invite) => void
|
||||
inviteDelete: [invite: Invite]
|
||||
/**
|
||||
* A User was updated. For example username, avatar, etc.
|
||||
* @param before The User object before update
|
||||
* @param after The User object after update
|
||||
*/
|
||||
userUpdate: (before: User, after: User) => void
|
||||
userUpdate: [before: User, after: User]
|
||||
/**
|
||||
* Client has received credentials for establishing connection to Voice Server
|
||||
* @param data Updated voice server object
|
||||
*/
|
||||
voiceServerUpdate: (data: VoiceServerUpdateData) => void
|
||||
voiceServerUpdate: [data: VoiceServerUpdateData]
|
||||
/**
|
||||
* A User has joined a Voice Channel
|
||||
* @param state Added voice state object
|
||||
*/
|
||||
voiceStateAdd: (state: VoiceState) => void
|
||||
voiceStateAdd: [state: VoiceState]
|
||||
/**
|
||||
* A User has left a Voice Channel
|
||||
* @param state Removed voice state object
|
||||
*/
|
||||
voiceStateRemove: (state: VoiceState) => void
|
||||
voiceStateRemove: [state: VoiceState]
|
||||
/**
|
||||
* Voice State of a User has been updated
|
||||
* @param before Voice State object before update
|
||||
* @param after Voice State object after update
|
||||
*/
|
||||
voiceStateUpdate: (state: VoiceState, after: VoiceState) => void
|
||||
voiceStateUpdate: [before: VoiceState, after: VoiceState]
|
||||
/**
|
||||
* A User's presence has been updated
|
||||
* @param presence New Presence
|
||||
*/
|
||||
presenceUpdate: (presence: Presence) => void
|
||||
presenceUpdate: [presence: Presence]
|
||||
/**
|
||||
* Webhooks of a Channel in a Guild has been updated
|
||||
* @param guild Guild in which Webhooks were updated
|
||||
* @param channel Channel of which Webhooks were updated
|
||||
*/
|
||||
webhooksUpdate: (guild: Guild, channel: GuildTextChannel) => void
|
||||
webhooksUpdate: [guild: Guild, channel: GuildTextChannel]
|
||||
/**
|
||||
* An Interaction was created
|
||||
* @param interaction Created interaction object
|
||||
*/
|
||||
interactionCreate: (interaction: Interaction) => void
|
||||
interactionCreate: [interaction: Interaction]
|
||||
|
||||
/**
|
||||
* When debug message was made
|
||||
* @param message Debug message
|
||||
*/
|
||||
debug: [message: string]
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable @typescript-eslint/method-signature-style */
|
||||
import { User } from '../structures/user.ts'
|
||||
import { GatewayIntents } from '../types/gateway.ts'
|
||||
import { Gateway } from '../gateway/index.ts'
|
||||
|
@ -10,13 +11,13 @@ import { ChannelsManager } from '../managers/channels.ts'
|
|||
import { ClientPresence } from '../structures/presence.ts'
|
||||
import { EmojisManager } from '../managers/emojis.ts'
|
||||
import { ActivityGame, ClientActivity } from '../types/presence.ts'
|
||||
import { ClientEvents } from '../gateway/handlers/index.ts'
|
||||
import { Extension } from './extensions.ts'
|
||||
import { SlashClient } from './slashClient.ts'
|
||||
import { Interaction } from '../structures/slash.ts'
|
||||
import { SlashModule } from './slashModule.ts'
|
||||
import type { ShardManager } from './shard.ts'
|
||||
import { Application } from '../structures/application.ts'
|
||||
import { ClientEvents } from '../gateway/handlers/index.ts'
|
||||
|
||||
/** OS related properties sent with Gateway Identify */
|
||||
export interface ClientProperties {
|
||||
|
@ -53,6 +54,32 @@ export interface ClientOptions {
|
|||
enableSlash?: boolean
|
||||
}
|
||||
|
||||
export declare interface Client {
|
||||
on<K extends keyof ClientEvents>(
|
||||
event: K,
|
||||
listener: (...args: ClientEvents[K]) => void
|
||||
): this
|
||||
on(event: string | symbol, listener: (...args: any[]) => void): this
|
||||
|
||||
once<K extends keyof ClientEvents>(
|
||||
event: K,
|
||||
listener: (...args: ClientEvents[K]) => void
|
||||
): this
|
||||
once(event: string | symbol, listener: (...args: any[]) => void): this
|
||||
|
||||
emit<K extends keyof ClientEvents>(
|
||||
event: K,
|
||||
...args: ClientEvents[K]
|
||||
): boolean
|
||||
emit(event: string | symbol, ...args: any[]): boolean
|
||||
|
||||
off<K extends keyof ClientEvents>(
|
||||
event: K,
|
||||
listener: (...args: ClientEvents[K]) => void
|
||||
): this
|
||||
off(event: string | symbol, listener: (...args: any[]) => void): this
|
||||
}
|
||||
|
||||
/**
|
||||
* Discord Client.
|
||||
*/
|
||||
|
@ -93,7 +120,10 @@ export class Client extends EventEmitter {
|
|||
canary: boolean = false
|
||||
/** Client's presence. Startup one if set before connecting */
|
||||
presence: ClientPresence = new ClientPresence()
|
||||
_decoratedEvents?: { [name: string]: (...args: any[]) => any }
|
||||
_decoratedEvents?: {
|
||||
[name: string]: (...args: any[]) => void
|
||||
}
|
||||
|
||||
_decoratedSlash?: Array<{
|
||||
name: string
|
||||
guild?: string
|
||||
|
@ -105,18 +135,6 @@ export class Client extends EventEmitter {
|
|||
_decoratedSlashModules?: SlashModule[]
|
||||
_id?: string
|
||||
|
||||
private readonly _untypedOn = this.on
|
||||
|
||||
private readonly _untypedEmit = this.emit
|
||||
|
||||
public on = <K extends string>(event: K, listener: ClientEvents[K]): this =>
|
||||
this._untypedOn(event, listener)
|
||||
|
||||
public emit = <K extends string>(
|
||||
event: K,
|
||||
...args: Parameters<ClientEvents[K]>
|
||||
): boolean => this._untypedEmit(event, ...args)
|
||||
|
||||
/** Shard on which this Client is */
|
||||
shard: number = 0
|
||||
/** Shard Manager of this Client if Sharded */
|
||||
|
@ -233,17 +251,43 @@ export class Client extends EventEmitter {
|
|||
} else throw new Error('No Gateway Intents were provided')
|
||||
this.gateway = new Gateway(this, token, intents)
|
||||
}
|
||||
|
||||
async waitFor<K extends keyof ClientEvents>(
|
||||
event: K,
|
||||
checkFunction: (...args: ClientEvents[K]) => boolean,
|
||||
timeout?: number
|
||||
): Promise<ClientEvents[K] | []> {
|
||||
return await new Promise((resolve) => {
|
||||
let timeoutID: number | undefined
|
||||
if (timeout !== undefined) {
|
||||
timeoutID = setTimeout(() => {
|
||||
this.off(event, eventFunc)
|
||||
resolve([])
|
||||
}, timeout)
|
||||
}
|
||||
const eventFunc = (...args: ClientEvents[K]): void => {
|
||||
if (checkFunction(...args)) {
|
||||
resolve(args)
|
||||
this.off(event, eventFunc)
|
||||
if (timeoutID !== undefined) clearTimeout(timeoutID)
|
||||
}
|
||||
}
|
||||
this.on(event, eventFunc)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export function event(name?: string) {
|
||||
return function (client: Client | Extension, prop: string) {
|
||||
export function event(name?: keyof ClientEvents) {
|
||||
return function (client: Client | Extension, prop: keyof ClientEvents) {
|
||||
const listener = ((client as unknown) as {
|
||||
[name: string]: (...args: any[]) => any
|
||||
[name in keyof ClientEvents]: (...args: ClientEvents[name]) => any
|
||||
})[prop]
|
||||
if (typeof listener !== 'function')
|
||||
throw new Error('@event decorator requires a function')
|
||||
if (client._decoratedEvents === undefined) client._decoratedEvents = {}
|
||||
client._decoratedEvents[name === undefined ? prop : name] = listener
|
||||
const key = name === undefined ? prop : name
|
||||
|
||||
client._decoratedEvents[key] = listener
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -114,6 +114,14 @@ client.on('messageCreate', async (msg: Message) => {
|
|||
}
|
||||
} else if (msg.content === '!react') {
|
||||
msg.addReaction('🤔')
|
||||
} else if (msg.content === '!wait_for') {
|
||||
msg.channel.send('Send anything!')
|
||||
const [receivedMsg] = await client.waitFor(
|
||||
'messageCreate',
|
||||
(message) => message.author.id === msg.author.id
|
||||
)
|
||||
|
||||
msg.channel.send(`Received: ${receivedMsg?.content}`)
|
||||
}
|
||||
})
|
||||
|
||||
|
|
Loading…
Reference in a new issue