Merge pull request #54 from DjDeveloperr/decorators
feat(decorators): added support for decorated events and commands
This commit is contained in:
commit
e403a62a0b
9 changed files with 304 additions and 48 deletions
4
mod.ts
4
mod.ts
|
@ -12,13 +12,13 @@ export {
|
||||||
CommandsManager,
|
CommandsManager,
|
||||||
CategoriesManager
|
CategoriesManager
|
||||||
} from './src/models/command.ts'
|
} from './src/models/command.ts'
|
||||||
export type { CommandContext } from './src/models/command.ts'
|
export type { CommandContext, CommandOptions } from './src/models/command.ts'
|
||||||
export {
|
export {
|
||||||
Extension,
|
Extension,
|
||||||
ExtensionCommands,
|
ExtensionCommands,
|
||||||
ExtensionsManager
|
ExtensionsManager
|
||||||
} from './src/models/extensions.ts'
|
} from './src/models/extensions.ts'
|
||||||
export { CommandClient } from './src/models/commandClient.ts'
|
export { CommandClient, command } from './src/models/commandClient.ts'
|
||||||
export type { CommandClientOptions } from './src/models/commandClient.ts'
|
export type { CommandClientOptions } from './src/models/commandClient.ts'
|
||||||
export { BaseManager } from './src/managers/base.ts'
|
export { BaseManager } from './src/managers/base.ts'
|
||||||
export { BaseChildManager } from './src/managers/baseChild.ts'
|
export { BaseChildManager } from './src/managers/baseChild.ts'
|
||||||
|
|
|
@ -9,6 +9,7 @@ export const ready: GatewayEventHandler = async (
|
||||||
) => {
|
) => {
|
||||||
await gateway.client.guilds.flush()
|
await gateway.client.guilds.flush()
|
||||||
|
|
||||||
|
await gateway.client.users.set(d.user.id, d.user)
|
||||||
gateway.client.user = new User(gateway.client, d.user)
|
gateway.client.user = new User(gateway.client, d.user)
|
||||||
gateway.sessionID = d.session_id
|
gateway.sessionID = d.session_id
|
||||||
gateway.debug(`Received READY. Session: ${gateway.sessionID}`)
|
gateway.debug(`Received READY. Session: ${gateway.sessionID}`)
|
||||||
|
|
|
@ -11,6 +11,7 @@ import { ClientPresence } from '../structures/presence.ts'
|
||||||
import { EmojisManager } from '../managers/emojis.ts'
|
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'
|
||||||
|
|
||||||
/** Some Client Options to modify behaviour */
|
/** Some Client Options to modify behaviour */
|
||||||
export interface ClientOptions {
|
export interface ClientOptions {
|
||||||
|
@ -70,6 +71,7 @@ export class Client extends EventEmitter {
|
||||||
canary: boolean = false
|
canary: boolean = false
|
||||||
/** Client's presence. Startup one if set before connecting */
|
/** Client's presence. Startup one if set before connecting */
|
||||||
presence: ClientPresence = new ClientPresence()
|
presence: ClientPresence = new ClientPresence()
|
||||||
|
_decoratedEvents?: { [name: string]: (...args: any[]) => any }
|
||||||
|
|
||||||
private readonly _untypedOn = this.on
|
private readonly _untypedOn = this.on
|
||||||
|
|
||||||
|
@ -101,6 +103,16 @@ export class Client extends EventEmitter {
|
||||||
this.reactionCacheLifetime = options.reactionCacheLifetime
|
this.reactionCacheLifetime = options.reactionCacheLifetime
|
||||||
if (options.fetchUncachedReactions === true)
|
if (options.fetchUncachedReactions === true)
|
||||||
this.fetchUncachedReactions = true
|
this.fetchUncachedReactions = true
|
||||||
|
|
||||||
|
if (
|
||||||
|
this._decoratedEvents !== undefined &&
|
||||||
|
Object.keys(this._decoratedEvents).length !== 0
|
||||||
|
) {
|
||||||
|
Object.entries(this._decoratedEvents).forEach((entry) => {
|
||||||
|
this.on(entry[0], entry[1])
|
||||||
|
})
|
||||||
|
this._decoratedEvents = undefined
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -153,3 +165,13 @@ export class Client extends EventEmitter {
|
||||||
this.gateway = new Gateway(this, token, intents)
|
this.gateway = new Gateway(this, token, intents)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function event(name?: string) {
|
||||||
|
return function (client: Client | Extension, prop: string) {
|
||||||
|
const listener = ((client as unknown) as {
|
||||||
|
[name: string]: (...args: any[]) => any
|
||||||
|
})[prop]
|
||||||
|
if (client._decoratedEvents === undefined) client._decoratedEvents = {}
|
||||||
|
client._decoratedEvents[name === undefined ? prop : name] = listener
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { User } from '../structures/user.ts'
|
||||||
import { Collection } from '../utils/collection.ts'
|
import { Collection } from '../utils/collection.ts'
|
||||||
import { CommandClient } from './commandClient.ts'
|
import { CommandClient } from './commandClient.ts'
|
||||||
import { Extension } from './extensions.ts'
|
import { Extension } from './extensions.ts'
|
||||||
|
import { parse } from 'https://deno.land/x/mutil@0.1.2/mod.ts'
|
||||||
|
|
||||||
export interface CommandContext {
|
export interface CommandContext {
|
||||||
/** The Client object */
|
/** The Client object */
|
||||||
|
@ -29,9 +30,9 @@ export interface CommandContext {
|
||||||
guild?: Guild
|
guild?: Guild
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Command {
|
export interface CommandOptions {
|
||||||
/** Name of the Command */
|
/** Name of the Command */
|
||||||
name: string = ''
|
name?: string
|
||||||
/** Description of the Command */
|
/** Description of the Command */
|
||||||
description?: string
|
description?: string
|
||||||
/** Category of the Command */
|
/** Category of the Command */
|
||||||
|
@ -60,12 +61,36 @@ export class Command {
|
||||||
whitelistedChannels?: string | string[]
|
whitelistedChannels?: string | string[]
|
||||||
/** Whitelisted Users. Command can be executed only by these Users (List or one of IDs) */
|
/** Whitelisted Users. Command can be executed only by these Users (List or one of IDs) */
|
||||||
whitelistedUsers?: string | string[]
|
whitelistedUsers?: string | string[]
|
||||||
|
/** Whether the Command can only be used in NSFW channel or not */
|
||||||
|
nsfw?: boolean
|
||||||
/** Whether the Command can only be used in Guild (if allowed in DMs) */
|
/** Whether the Command can only be used in Guild (if allowed in DMs) */
|
||||||
guildOnly?: boolean
|
guildOnly?: boolean
|
||||||
/** Whether the Command can only be used in Bot's DMs (if allowed) */
|
/** Whether the Command can only be used in Bot's DMs (if allowed) */
|
||||||
dmOnly?: boolean
|
dmOnly?: boolean
|
||||||
/** Whether the Command can only be used by Bot Owners */
|
/** Whether the Command can only be used by Bot Owners */
|
||||||
ownerOnly?: boolean
|
ownerOnly?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Command implements CommandOptions {
|
||||||
|
name: string = ''
|
||||||
|
description?: string
|
||||||
|
category?: string
|
||||||
|
aliases?: string | string[]
|
||||||
|
extension?: Extension
|
||||||
|
usage?: string | string[]
|
||||||
|
examples?: string | string[]
|
||||||
|
args?: number | boolean | string[]
|
||||||
|
permissions?: string | string[]
|
||||||
|
userPermissions?: string | string[]
|
||||||
|
botPermissions?: string | string[]
|
||||||
|
roles?: string | string[]
|
||||||
|
whitelistedGuilds?: string | string[]
|
||||||
|
whitelistedChannels?: string | string[]
|
||||||
|
whitelistedUsers?: string | string[]
|
||||||
|
nsfw?: boolean
|
||||||
|
guildOnly?: boolean
|
||||||
|
dmOnly?: boolean
|
||||||
|
ownerOnly?: boolean
|
||||||
|
|
||||||
/** Method executed before executing actual command. Returns bool value - whether to continue or not (optional) */
|
/** Method executed before executing actual command. Returns bool value - whether to continue or not (optional) */
|
||||||
beforeExecute(ctx: CommandContext): boolean | Promise<boolean> {
|
beforeExecute(ctx: CommandContext): boolean | Promise<boolean> {
|
||||||
|
@ -79,7 +104,7 @@ export class Command {
|
||||||
|
|
||||||
toString(): string {
|
toString(): string {
|
||||||
return `Command: ${this.name}${
|
return `Command: ${this.name}${
|
||||||
this.extension !== undefined
|
this.extension !== undefined && this.extension.name !== ''
|
||||||
? ` [${this.extension.name}]`
|
? ` [${this.extension.name}]`
|
||||||
: this.category !== undefined
|
: this.category !== undefined
|
||||||
? ` [${this.category}]`
|
? ` [${this.category}]`
|
||||||
|
@ -231,6 +256,11 @@ export class CommandBuilder extends Command {
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setNSFW(value: boolean = true): CommandBuilder {
|
||||||
|
this.nsfw = value
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
setOwnerOnly(value: boolean = true): CommandBuilder {
|
setOwnerOnly(value: boolean = true): CommandBuilder {
|
||||||
this.ownerOnly = value
|
this.ownerOnly = value
|
||||||
return this
|
return this
|
||||||
|
@ -268,38 +298,86 @@ export class CommandsManager {
|
||||||
return this.list.size
|
return this.list.size
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Find a Command by name/alias */
|
/** Filter out Commands by name/alias */
|
||||||
find(search: string): Command | undefined {
|
filter(search: string, subPrefix?: string): Collection<string, Command> {
|
||||||
if (this.client.caseSensitive === false) search = search.toLowerCase()
|
if (this.client.caseSensitive === false) search = search.toLowerCase()
|
||||||
return this.list.find((cmd: Command): boolean => {
|
return this.list.filter((cmd: Command): boolean => {
|
||||||
|
if (subPrefix !== undefined) {
|
||||||
|
if (
|
||||||
|
this.client.caseSensitive === true
|
||||||
|
? subPrefix !== cmd.extension?.subPrefix
|
||||||
|
: subPrefix.toLowerCase() !==
|
||||||
|
cmd.extension?.subPrefix?.toLowerCase()
|
||||||
|
) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} else if (
|
||||||
|
subPrefix === undefined &&
|
||||||
|
cmd.extension?.subPrefix !== undefined
|
||||||
|
) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
const name =
|
const name =
|
||||||
this.client.caseSensitive === true ? cmd.name : cmd.name.toLowerCase()
|
this.client.caseSensitive === true ? cmd.name : cmd.name.toLowerCase()
|
||||||
if (name === search) return true
|
if (name === search) {
|
||||||
else if (cmd.aliases !== undefined) {
|
return true
|
||||||
|
} else if (cmd.aliases !== undefined) {
|
||||||
let aliases: string[]
|
let aliases: string[]
|
||||||
if (typeof cmd.aliases === 'string') aliases = [cmd.aliases]
|
if (typeof cmd.aliases === 'string') aliases = [cmd.aliases]
|
||||||
else aliases = cmd.aliases
|
else aliases = cmd.aliases
|
||||||
if (this.client.caseSensitive === false)
|
if (this.client.caseSensitive === false)
|
||||||
aliases = aliases.map((e) => e.toLowerCase())
|
aliases = aliases.map((e) => e.toLowerCase())
|
||||||
|
|
||||||
return aliases.includes(search)
|
return aliases.includes(search)
|
||||||
} else return false
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Fetch a Command including disable checks */
|
/** Find a Command by name/alias */
|
||||||
fetch(name: string, bypassDisable?: boolean): Command | undefined {
|
find(search: string, subPrefix?: string): Command | undefined {
|
||||||
const cmd = this.find(name)
|
const filtered = this.filter(search, subPrefix)
|
||||||
|
return filtered.first()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Fetch a Command including disable checks and subPrefix implementation */
|
||||||
|
fetch(parsed: ParsedCommand, bypassDisable?: boolean): Command | undefined {
|
||||||
|
let cmd = this.find(parsed.name)
|
||||||
|
if (cmd?.extension?.subPrefix !== undefined) cmd = undefined
|
||||||
|
|
||||||
|
if (cmd === undefined && parsed.args.length > 0) {
|
||||||
|
cmd = this.find(parsed.args[0], parsed.name)
|
||||||
|
if (cmd === undefined || cmd.extension?.subPrefix === undefined) return
|
||||||
|
if (
|
||||||
|
this.client.caseSensitive === true
|
||||||
|
? cmd.extension.subPrefix !== parsed.name
|
||||||
|
: cmd.extension.subPrefix.toLowerCase() !== parsed.name.toLowerCase()
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
parsed.args.shift()
|
||||||
|
}
|
||||||
|
|
||||||
if (cmd === undefined) return
|
if (cmd === undefined) return
|
||||||
if (this.isDisabled(cmd) && bypassDisable !== true) return
|
if (this.isDisabled(cmd) && bypassDisable !== true) return
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Check whether a Command exists or not */
|
/** Check whether a Command exists or not */
|
||||||
exists(search: Command | string): boolean {
|
exists(search: Command | string, subPrefix?: string): boolean {
|
||||||
let exists = false
|
let exists = false
|
||||||
if (typeof search === 'string') return this.find(search) !== undefined
|
|
||||||
|
if (typeof search === 'string')
|
||||||
|
return this.find(search, subPrefix) !== undefined
|
||||||
else {
|
else {
|
||||||
exists = this.find(search.name) !== undefined
|
exists =
|
||||||
|
this.find(
|
||||||
|
search.name,
|
||||||
|
subPrefix === undefined ? search.extension?.subPrefix : subPrefix
|
||||||
|
) !== undefined
|
||||||
|
|
||||||
if (search.aliases !== undefined) {
|
if (search.aliases !== undefined) {
|
||||||
const aliases: string[] =
|
const aliases: string[] =
|
||||||
typeof search.aliases === 'string' ? [search.aliases] : search.aliases
|
typeof search.aliases === 'string' ? [search.aliases] : search.aliases
|
||||||
|
@ -308,6 +386,7 @@ export class CommandsManager {
|
||||||
.map((alias) => this.find(alias) !== undefined)
|
.map((alias) => this.find(alias) !== undefined)
|
||||||
.find((e) => e) ?? false
|
.find((e) => e) ?? false
|
||||||
}
|
}
|
||||||
|
|
||||||
return exists
|
return exists
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -316,11 +395,20 @@ export class CommandsManager {
|
||||||
add(cmd: Command | typeof Command): boolean {
|
add(cmd: Command | typeof Command): boolean {
|
||||||
// eslint-disable-next-line new-cap
|
// eslint-disable-next-line new-cap
|
||||||
if (!(cmd instanceof Command)) cmd = new cmd()
|
if (!(cmd instanceof Command)) cmd = new cmd()
|
||||||
if (this.exists(cmd))
|
if (this.exists(cmd, cmd.extension?.subPrefix))
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Failed to add Command '${cmd.toString()}' with name/alias already exists.`
|
`Failed to add Command '${cmd.toString()}' with name/alias already exists.`
|
||||||
)
|
)
|
||||||
this.list.set(cmd.name, cmd)
|
this.list.set(
|
||||||
|
`${cmd.name}-${
|
||||||
|
this.list.filter((e) =>
|
||||||
|
this.client.caseSensitive === true
|
||||||
|
? e.name === cmd.name
|
||||||
|
: e.name.toLowerCase() === cmd.name.toLowerCase()
|
||||||
|
).size
|
||||||
|
}`,
|
||||||
|
cmd
|
||||||
|
)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -418,7 +506,8 @@ export const parseCommand = (
|
||||||
): ParsedCommand => {
|
): ParsedCommand => {
|
||||||
let content = msg.content.slice(prefix.length)
|
let content = msg.content.slice(prefix.length)
|
||||||
if (client.spacesAfterPrefix === true) content = content.trim()
|
if (client.spacesAfterPrefix === true) content = content.trim()
|
||||||
const args = content.split(client.betterArgs === true ? /[\S\s]*/ : / +/)
|
const args = parse(content)._.map((e) => e.toString())
|
||||||
|
|
||||||
const name = args.shift() as string
|
const name = args.shift() as string
|
||||||
const argString = content.slice(name.length).trim()
|
const argString = content.slice(name.length).trim()
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
import { Message } from '../structures/message.ts'
|
import { Message } from '../structures/message.ts'
|
||||||
|
import { GuildTextChannel } from '../structures/textChannel.ts'
|
||||||
import { awaitSync } from '../utils/mixedPromise.ts'
|
import { awaitSync } from '../utils/mixedPromise.ts'
|
||||||
import { Client, ClientOptions } from './client.ts'
|
import { Client, ClientOptions } from './client.ts'
|
||||||
import {
|
import {
|
||||||
CategoriesManager,
|
CategoriesManager,
|
||||||
|
Command,
|
||||||
CommandContext,
|
CommandContext,
|
||||||
|
CommandOptions,
|
||||||
CommandsManager,
|
CommandsManager,
|
||||||
parseCommand
|
parseCommand
|
||||||
} from './command.ts'
|
} from './command.ts'
|
||||||
import { ExtensionsManager } from './extensions.ts'
|
import { Extension, ExtensionsManager } from './extensions.ts'
|
||||||
|
|
||||||
type PrefixReturnType = string | string[] | Promise<string | string[]>
|
type PrefixReturnType = string | string[] | Promise<string | string[]>
|
||||||
|
|
||||||
|
@ -21,6 +24,8 @@ export interface CommandClientOptions extends ClientOptions {
|
||||||
getGuildPrefix?: (guildID: string) => PrefixReturnType
|
getGuildPrefix?: (guildID: string) => PrefixReturnType
|
||||||
/** Method to get a User's custom prefix(s). */
|
/** Method to get a User's custom prefix(s). */
|
||||||
getUserPrefix?: (userID: string) => PrefixReturnType
|
getUserPrefix?: (userID: string) => PrefixReturnType
|
||||||
|
/** Method to get a Channel's custom prefix(s). */
|
||||||
|
getChannelPrefix?: (channelID: string) => PrefixReturnType
|
||||||
/** Method to check if certain Guild is blacklisted from using Commands. */
|
/** Method to check if certain Guild is blacklisted from using Commands. */
|
||||||
isGuildBlacklisted?: (guildID: string) => boolean | Promise<boolean>
|
isGuildBlacklisted?: (guildID: string) => boolean | Promise<boolean>
|
||||||
/** Method to check if certain User is blacklisted from using Commands. */
|
/** Method to check if certain User is blacklisted from using Commands. */
|
||||||
|
@ -29,8 +34,6 @@ export interface CommandClientOptions extends ClientOptions {
|
||||||
isChannelBlacklisted?: (guildID: string) => boolean | Promise<boolean>
|
isChannelBlacklisted?: (guildID: string) => boolean | Promise<boolean>
|
||||||
/** Allow spaces after prefix? Recommended with Mention Prefix ON. */
|
/** Allow spaces after prefix? Recommended with Mention Prefix ON. */
|
||||||
spacesAfterPrefix?: boolean
|
spacesAfterPrefix?: boolean
|
||||||
/** Better Arguments regex to split at every whitespace. */
|
|
||||||
betterArgs?: boolean
|
|
||||||
/** List of Bot's Owner IDs whom can access `ownerOnly` commands. */
|
/** List of Bot's Owner IDs whom can access `ownerOnly` commands. */
|
||||||
owners?: string[]
|
owners?: string[]
|
||||||
/** Whether to allow Bots to use Commands or not, not allowed by default. */
|
/** Whether to allow Bots to use Commands or not, not allowed by default. */
|
||||||
|
@ -44,26 +47,33 @@ export interface CommandClientOptions extends ClientOptions {
|
||||||
export class CommandClient extends Client implements CommandClientOptions {
|
export class CommandClient extends Client implements CommandClientOptions {
|
||||||
prefix: string | string[]
|
prefix: string | string[]
|
||||||
mentionPrefix: boolean
|
mentionPrefix: boolean
|
||||||
|
|
||||||
getGuildPrefix: (guildID: string) => PrefixReturnType
|
getGuildPrefix: (guildID: string) => PrefixReturnType
|
||||||
getUserPrefix: (userID: string) => PrefixReturnType
|
getUserPrefix: (userID: string) => PrefixReturnType
|
||||||
|
getChannelPrefix: (channelID: string) => PrefixReturnType
|
||||||
|
|
||||||
isGuildBlacklisted: (guildID: string) => boolean | Promise<boolean>
|
isGuildBlacklisted: (guildID: string) => boolean | Promise<boolean>
|
||||||
isUserBlacklisted: (guildID: string) => boolean | Promise<boolean>
|
isUserBlacklisted: (guildID: string) => boolean | Promise<boolean>
|
||||||
isChannelBlacklisted: (guildID: string) => boolean | Promise<boolean>
|
isChannelBlacklisted: (guildID: string) => boolean | Promise<boolean>
|
||||||
|
|
||||||
spacesAfterPrefix: boolean
|
spacesAfterPrefix: boolean
|
||||||
betterArgs: boolean
|
|
||||||
owners: string[]
|
owners: string[]
|
||||||
allowBots: boolean
|
allowBots: boolean
|
||||||
allowDMs: boolean
|
allowDMs: boolean
|
||||||
caseSensitive: boolean
|
caseSensitive: boolean
|
||||||
|
|
||||||
extensions: ExtensionsManager = new ExtensionsManager(this)
|
extensions: ExtensionsManager = new ExtensionsManager(this)
|
||||||
commands: CommandsManager = new CommandsManager(this)
|
commands: CommandsManager = new CommandsManager(this)
|
||||||
categories: CategoriesManager = new CategoriesManager(this)
|
categories: CategoriesManager = new CategoriesManager(this)
|
||||||
|
|
||||||
|
_decoratedCommands?: { [name: string]: Command }
|
||||||
|
|
||||||
constructor(options: CommandClientOptions) {
|
constructor(options: CommandClientOptions) {
|
||||||
super(options)
|
super(options)
|
||||||
this.prefix = options.prefix
|
this.prefix = options.prefix
|
||||||
this.mentionPrefix =
|
this.mentionPrefix =
|
||||||
options.mentionPrefix === undefined ? false : options.mentionPrefix
|
options.mentionPrefix === undefined ? false : options.mentionPrefix
|
||||||
|
|
||||||
this.getGuildPrefix =
|
this.getGuildPrefix =
|
||||||
options.getGuildPrefix === undefined
|
options.getGuildPrefix === undefined
|
||||||
? (id: string) => this.prefix
|
? (id: string) => this.prefix
|
||||||
|
@ -72,6 +82,12 @@ export class CommandClient extends Client implements CommandClientOptions {
|
||||||
options.getUserPrefix === undefined
|
options.getUserPrefix === undefined
|
||||||
? (id: string) => this.prefix
|
? (id: string) => this.prefix
|
||||||
: options.getUserPrefix
|
: options.getUserPrefix
|
||||||
|
|
||||||
|
this.getChannelPrefix =
|
||||||
|
options.getChannelPrefix === undefined
|
||||||
|
? (id: string) => this.prefix
|
||||||
|
: options.getChannelPrefix
|
||||||
|
|
||||||
this.isUserBlacklisted =
|
this.isUserBlacklisted =
|
||||||
options.isUserBlacklisted === undefined
|
options.isUserBlacklisted === undefined
|
||||||
? (id: string) => false
|
? (id: string) => false
|
||||||
|
@ -84,18 +100,25 @@ export class CommandClient extends Client implements CommandClientOptions {
|
||||||
options.isChannelBlacklisted === undefined
|
options.isChannelBlacklisted === undefined
|
||||||
? (id: string) => false
|
? (id: string) => false
|
||||||
: options.isChannelBlacklisted
|
: options.isChannelBlacklisted
|
||||||
|
|
||||||
this.spacesAfterPrefix =
|
this.spacesAfterPrefix =
|
||||||
options.spacesAfterPrefix === undefined
|
options.spacesAfterPrefix === undefined
|
||||||
? false
|
? false
|
||||||
: options.spacesAfterPrefix
|
: options.spacesAfterPrefix
|
||||||
this.betterArgs =
|
|
||||||
options.betterArgs === undefined ? false : options.betterArgs
|
|
||||||
this.owners = options.owners === undefined ? [] : options.owners
|
this.owners = options.owners === undefined ? [] : options.owners
|
||||||
this.allowBots = options.allowBots === undefined ? false : options.allowBots
|
this.allowBots = options.allowBots === undefined ? false : options.allowBots
|
||||||
this.allowDMs = options.allowDMs === undefined ? true : options.allowDMs
|
this.allowDMs = options.allowDMs === undefined ? true : options.allowDMs
|
||||||
this.caseSensitive =
|
this.caseSensitive =
|
||||||
options.caseSensitive === undefined ? false : options.caseSensitive
|
options.caseSensitive === undefined ? false : options.caseSensitive
|
||||||
|
|
||||||
|
if (this._decoratedCommands !== undefined) {
|
||||||
|
Object.values(this._decoratedCommands).forEach((entry) => {
|
||||||
|
this.commands.add(entry)
|
||||||
|
})
|
||||||
|
this._decoratedCommands = undefined
|
||||||
|
}
|
||||||
|
|
||||||
this.on(
|
this.on(
|
||||||
'messageCreate',
|
'messageCreate',
|
||||||
async (msg: Message) => await this.processMessage(msg)
|
async (msg: Message) => await this.processMessage(msg)
|
||||||
|
@ -123,43 +146,48 @@ export class CommandClient extends Client implements CommandClientOptions {
|
||||||
if (isGuildBlacklisted === true) return
|
if (isGuildBlacklisted === true) return
|
||||||
}
|
}
|
||||||
|
|
||||||
let prefix: string | string[] = await awaitSync(
|
let prefix: string | string[] = []
|
||||||
this.getUserPrefix(msg.author.id)
|
if (typeof this.prefix === 'string') prefix = [...prefix, this.prefix]
|
||||||
)
|
else prefix = [...prefix, ...this.prefix]
|
||||||
|
|
||||||
|
const userPrefix = await awaitSync(this.getUserPrefix(msg.author.id))
|
||||||
|
if (userPrefix !== undefined) {
|
||||||
|
if (typeof userPrefix === 'string') prefix = [...prefix, userPrefix]
|
||||||
|
else prefix = [...prefix, ...userPrefix]
|
||||||
|
}
|
||||||
|
|
||||||
if (msg.guild !== undefined) {
|
if (msg.guild !== undefined) {
|
||||||
prefix = await awaitSync(this.getGuildPrefix(msg.guild.id))
|
const guildPrefix = await awaitSync(this.getGuildPrefix(msg.guild.id))
|
||||||
|
if (guildPrefix !== undefined) {
|
||||||
|
if (typeof guildPrefix === 'string') prefix = [...prefix, guildPrefix]
|
||||||
|
else prefix = [...prefix, ...guildPrefix]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prefix = [...new Set(prefix)]
|
||||||
|
|
||||||
let mentionPrefix = false
|
let mentionPrefix = false
|
||||||
|
|
||||||
if (typeof prefix === 'string') {
|
let usedPrefix = prefix
|
||||||
if (msg.content.startsWith(prefix) === false) {
|
.filter((v) => msg.content.startsWith(v))
|
||||||
if (this.mentionPrefix) mentionPrefix = true
|
.sort((b, a) => a.length - b.length)[0]
|
||||||
else return
|
if (usedPrefix === undefined && this.mentionPrefix) mentionPrefix = true
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const usedPrefix = prefix.find((v) => msg.content.startsWith(v))
|
|
||||||
if (usedPrefix === undefined) {
|
|
||||||
if (this.mentionPrefix) mentionPrefix = true
|
|
||||||
else return
|
|
||||||
} else prefix = usedPrefix
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mentionPrefix) {
|
if (mentionPrefix) {
|
||||||
if (msg.content.startsWith(this.user?.mention as string) === true)
|
if (msg.content.startsWith(this.user?.mention as string) === true)
|
||||||
prefix = this.user?.mention as string
|
usedPrefix = this.user?.mention as string
|
||||||
else if (
|
else if (
|
||||||
msg.content.startsWith(this.user?.nickMention as string) === true
|
msg.content.startsWith(this.user?.nickMention as string) === true
|
||||||
)
|
)
|
||||||
prefix = this.user?.nickMention as string
|
usedPrefix = this.user?.nickMention as string
|
||||||
else return
|
else return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof prefix !== 'string') return
|
if (typeof usedPrefix !== 'string') return
|
||||||
|
prefix = usedPrefix
|
||||||
|
|
||||||
const parsed = parseCommand(this, msg, prefix)
|
const parsed = parseCommand(this, msg, prefix)
|
||||||
const command = this.commands.find(parsed.name)
|
const command = this.commands.fetch(parsed)
|
||||||
|
|
||||||
if (command === undefined) return
|
if (command === undefined) return
|
||||||
const category =
|
const category =
|
||||||
|
@ -250,6 +278,13 @@ export class CommandClient extends Client implements CommandClientOptions {
|
||||||
)
|
)
|
||||||
return this.emit('commandDmOnly', ctx, command)
|
return this.emit('commandDmOnly', ctx, command)
|
||||||
|
|
||||||
|
if (
|
||||||
|
command.nsfw === true &&
|
||||||
|
(msg.guild === undefined ||
|
||||||
|
((msg.channel as unknown) as GuildTextChannel).nsfw !== true)
|
||||||
|
)
|
||||||
|
return this.emit('commandNSFW', ctx, command)
|
||||||
|
|
||||||
const allPermissions =
|
const allPermissions =
|
||||||
command.permissions !== undefined
|
command.permissions !== undefined
|
||||||
? command.permissions
|
? command.permissions
|
||||||
|
@ -345,3 +380,21 @@ export class CommandClient extends Client implements CommandClientOptions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function command(options?: CommandOptions) {
|
||||||
|
return function (target: CommandClient | Extension, name: string) {
|
||||||
|
const command = new Command()
|
||||||
|
|
||||||
|
command.name = name
|
||||||
|
command.execute = ((target as unknown) as {
|
||||||
|
[name: string]: (ctx: CommandContext) => any
|
||||||
|
})[name]
|
||||||
|
|
||||||
|
if (options !== undefined) Object.assign(command, options)
|
||||||
|
|
||||||
|
if (target instanceof Extension) command.extension = target
|
||||||
|
|
||||||
|
if (target._decoratedCommands === undefined) target._decoratedCommands = {}
|
||||||
|
target._decoratedCommands[command.name] = command
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -67,11 +67,33 @@ export class Extension {
|
||||||
description?: string
|
description?: string
|
||||||
/** Extensions's Commands Manager */
|
/** Extensions's Commands Manager */
|
||||||
commands: ExtensionCommands = new ExtensionCommands(this)
|
commands: ExtensionCommands = new ExtensionCommands(this)
|
||||||
|
/** Sub-Prefix to be used for ALL of Extenion's Commands. */
|
||||||
|
subPrefix?: string
|
||||||
/** Events registered by this Extension */
|
/** Events registered by this Extension */
|
||||||
events: { [name: string]: (...args: any[]) => {} } = {}
|
events: { [name: string]: (...args: any[]) => {} } = {}
|
||||||
|
|
||||||
|
_decoratedCommands?: { [name: string]: Command }
|
||||||
|
_decoratedEvents?: { [name: string]: (...args: any[]) => any }
|
||||||
|
|
||||||
constructor(client: CommandClient) {
|
constructor(client: CommandClient) {
|
||||||
this.client = client
|
this.client = client
|
||||||
|
if (this._decoratedCommands !== undefined) {
|
||||||
|
Object.entries(this._decoratedCommands).forEach((entry) => {
|
||||||
|
entry[1].extension = this
|
||||||
|
this.commands.add(entry[1])
|
||||||
|
})
|
||||||
|
this._decoratedCommands = undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
this._decoratedEvents !== undefined &&
|
||||||
|
Object.keys(this._decoratedEvents).length !== 0
|
||||||
|
) {
|
||||||
|
Object.entries(this._decoratedEvents).forEach((entry) => {
|
||||||
|
this.listen(entry[0], entry[1])
|
||||||
|
})
|
||||||
|
this._decoratedEvents = undefined
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Listens for an Event through Extension. */
|
/** Listens for an Event through Extension. */
|
||||||
|
|
|
@ -42,7 +42,7 @@ export class VoiceChannel extends Channel {
|
||||||
if (state.channel?.id !== this.id) return
|
if (state.channel?.id !== this.id) return
|
||||||
this.client.removeListener('voiceStateAdd', onVoiceStateAdd)
|
this.client.removeListener('voiceStateAdd', onVoiceStateAdd)
|
||||||
done++
|
done++
|
||||||
if (done >= 2) resolve(vcdata)
|
if (done >= 2) resolve((vcdata as unknown) as VoiceServerUpdateData)
|
||||||
}
|
}
|
||||||
|
|
||||||
const onVoiceServerUpdate = (data: VoiceServerUpdateData): void => {
|
const onVoiceServerUpdate = (data: VoiceServerUpdateData): void => {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { Base } from './base.ts'
|
import { Base } from './base.ts'
|
||||||
import {
|
import {
|
||||||
Attachment,
|
Attachment,
|
||||||
ChannelMention,
|
|
||||||
MessageActivity,
|
MessageActivity,
|
||||||
MessageApplication,
|
MessageApplication,
|
||||||
MessageOption,
|
MessageOption,
|
||||||
|
|
70
src/test/class.ts
Normal file
70
src/test/class.ts
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
import {
|
||||||
|
CommandClient,
|
||||||
|
event,
|
||||||
|
Intents,
|
||||||
|
command,
|
||||||
|
CommandContext,
|
||||||
|
Extension,
|
||||||
|
CommandBuilder
|
||||||
|
} from '../../mod.ts'
|
||||||
|
import { TOKEN } from './config.ts'
|
||||||
|
|
||||||
|
class MyClient extends CommandClient {
|
||||||
|
constructor() {
|
||||||
|
super({
|
||||||
|
prefix: ['!', '!!'],
|
||||||
|
caseSensitive: false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
@event()
|
||||||
|
ready(): void {
|
||||||
|
console.log(`Logged in as ${this.user?.tag}!`)
|
||||||
|
}
|
||||||
|
|
||||||
|
@command({ aliases: 'pong' })
|
||||||
|
Ping(ctx: CommandContext): void {
|
||||||
|
ctx.message.reply('Pong!')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class VCExtension extends Extension {
|
||||||
|
name = 'VC'
|
||||||
|
subPrefix = 'vc'
|
||||||
|
|
||||||
|
@command()
|
||||||
|
async join(ctx: CommandContext): Promise<void> {
|
||||||
|
const userVS = await ctx.guild?.voiceStates.get(ctx.author.id)
|
||||||
|
if (userVS === undefined) {
|
||||||
|
ctx.message.reply("You're not in VC.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
await userVS.channel?.join()
|
||||||
|
ctx.message.reply(`Joined VC channel - ${userVS.channel?.name}!`)
|
||||||
|
}
|
||||||
|
|
||||||
|
@command()
|
||||||
|
async leave(ctx: CommandContext): Promise<void> {
|
||||||
|
const userVS = await ctx.guild?.voiceStates.get(
|
||||||
|
(ctx.client.user?.id as unknown) as string
|
||||||
|
)
|
||||||
|
if (userVS === undefined) {
|
||||||
|
ctx.message.reply("I'm not in VC.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
userVS.channel?.leave()
|
||||||
|
ctx.message.reply(`Left VC channel - ${userVS.channel?.name}!`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const client = new MyClient()
|
||||||
|
|
||||||
|
client.extensions.load(VCExtension)
|
||||||
|
|
||||||
|
client.commands.add(
|
||||||
|
new CommandBuilder()
|
||||||
|
.setName('join')
|
||||||
|
.onExecute((ctx) => ctx.message.reply('haha'))
|
||||||
|
)
|
||||||
|
|
||||||
|
client.connect(TOKEN, Intents.All)
|
Loading…
Reference in a new issue