From 77200d020b04c93fade2ba00244a8b4c821dd7c4 Mon Sep 17 00:00:00 2001 From: Zack Campbell Date: Mon, 3 Apr 2017 00:42:36 -0500 Subject: [PATCH] Rename Bot -> Client, update documentation and code accordingly --- src/index.ts | 4 +- src/lib/{bot/Bot.ts => client/Client.ts} | 140 +++++++++--------- src/lib/command/Command.ts | 30 ++-- src/lib/command/CommandDispatcher.ts | 60 ++++---- src/lib/command/CommandLoader.ts | 47 +++--- src/lib/command/CommandRegistry.ts | 55 +++---- src/lib/command/base/Eval.ts | 8 +- src/lib/command/base/Help.ts | 32 ++-- src/lib/command/base/Ping.ts | 10 +- src/lib/command/base/Reload.ts | 14 +- src/lib/command/base/SetPrefix.ts | 18 +-- src/lib/command/base/Version.ts | 10 +- src/lib/command/base/blacklist/Blacklist.ts | 18 +-- src/lib/command/base/blacklist/Whitelist.ts | 18 +-- .../command/base/groupcontrol/ClearLimit.ts | 10 +- .../command/base/groupcontrol/DisableGroup.ts | 10 +- .../command/base/groupcontrol/EnableGroup.ts | 10 +- src/lib/command/base/groupcontrol/Limit.ts | 10 +- .../command/base/groupcontrol/ListGroups.ts | 11 +- src/lib/command/middleware/Expect.ts | 4 +- src/lib/command/middleware/Middleware.ts | 6 +- src/lib/command/middleware/ResolveArgs.ts | 6 +- src/lib/storage/GuildSettings.ts | 4 +- src/lib/storage/GuildStorageLoader.ts | 8 +- src/lib/storage/StorageFactory.ts | 8 +- src/lib/types/BotOptions.ts | 36 ----- src/lib/types/DefaultGuildSettings.ts | 2 +- src/lib/types/Message.ts | 2 +- src/lib/types/YAMDBFOptions.ts | 36 +++++ test/commands/test_command.ts | 6 +- test/test_client.ts | 4 +- 31 files changed, 316 insertions(+), 321 deletions(-) rename src/lib/{bot/Bot.ts => client/Client.ts} (83%) delete mode 100644 src/lib/types/BotOptions.ts create mode 100644 src/lib/types/YAMDBFOptions.ts diff --git a/src/index.ts b/src/index.ts index 4e81035e..9e36c574 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,6 @@ import * as path from 'path'; -export { Bot } from './lib/bot/Bot'; +export { Client } from './lib/client/Client'; export { Command } from './lib/command/Command'; export { CommandDispatcher } from './lib/command/CommandDispatcher'; export { CommandLoader } from './lib/command/CommandLoader'; @@ -25,7 +25,7 @@ export { Util } from './lib/Util'; export { ArgOpts } from './lib/types/ArgOpts'; export { BaseCommandName } from './lib/types/BaseCommandName'; -export { BotOptions } from './lib/types/BotOptions'; +export { YAMDBFOptions } from './lib/types/YAMDBFOptions'; export { ClientStorage } from './lib/types/ClientStorage'; export { CommandInfo } from './lib/types/CommandInfo'; export { DefaultGuildSettings } from './lib/types/DefaultGuildSettings'; diff --git a/src/lib/bot/Bot.ts b/src/lib/client/Client.ts similarity index 83% rename from src/lib/bot/Bot.ts rename to src/lib/client/Client.ts index 634eaf4e..c68f0efc 100644 --- a/src/lib/bot/Bot.ts +++ b/src/lib/client/Client.ts @@ -1,4 +1,5 @@ -import { Channel, Client, ClientOptions, Collection, Emoji, Guild, GuildMember, Message, MessageReaction, Role, User, UserResolvable } from 'discord.js'; +import * as Discord from 'discord.js'; +import { Channel, ClientOptions, Collection, Emoji, Guild, GuildMember, Message, MessageReaction, Role, User, UserResolvable } from 'discord.js'; import { Command } from '../command/Command'; import { CommandDispatcher } from '../command/CommandDispatcher'; import { CommandLoader } from '../command/CommandLoader'; @@ -8,19 +9,20 @@ import { GuildStorageLoader } from '../storage/GuildStorageLoader'; import { JSONProvider } from '../storage/JSONProvider'; import { StorageProvider } from '../storage/StorageProvider'; import { StorageFactory } from '../storage/StorageFactory'; -import { BotOptions } from '../types/BotOptions'; +import { YAMDBFOptions } from '../types/YAMDBFOptions'; import { ClientStorage } from '../types/ClientStorage'; import { MiddlewareFunction } from '../types/MiddlewareFunction'; import { StorageProviderConstructor } from '../types/StorageProviderConstructor'; +import { BaseCommandName } from '../types/BaseCommandName'; /** - * The YAMDBF Client through which you can access [storage]{@link Bot#storage} + * The YAMDBF Client through which you can access [storage]{@link Client#storage} * and any of the properties available on a typical Discord.js Client instance * @extends {external:Client} - * @param {BotOptions} botOptions Object containing required bot properties + * @param {YAMDBFOptions} options Object containing required client properties * @param {external:ClientOptions} [clientOptions] Discord.js ClientOptions */ -export class Bot extends Client +export class Client extends Discord.Client { public name: string; public commandsDir: string; @@ -30,7 +32,7 @@ export class Bot extends Client public selfbot: boolean; public passive: boolean; public version: string; - public disableBase: string[]; + public disableBase: BaseCommandName[]; public config: any; public provider: StorageProviderConstructor; public storageFactory: StorageFactory; @@ -47,104 +49,104 @@ export class Bot extends Client private _commandLoader: CommandLoader; private _dispatcher: CommandDispatcher; - public constructor(botOptions: BotOptions, clientOptions?: ClientOptions) + public constructor(options: YAMDBFOptions, clientOptions?: ClientOptions) { super(clientOptions); - this._token = botOptions.token; + this._token = options.token; /** - * The name of the Bot - * @name Bot#name + * The name of the bot this Client is for + * @name Client#name * @type {string} */ - this.name = botOptions.name || 'botname'; + this.name = options.name || 'botname'; /** * Directory to find command class files. Optional - * if bot is passive. See: {@link Bot#passive} - * @name Bot#commandsDir + * if client is passive. See: {@link Client#passive} + * @name Client#commandsDir * @type {string} */ - this.commandsDir = botOptions.commandsDir || null; + this.commandsDir = options.commandsDir || null; /** - * Status text for the bot - * @name Bot#statusText + * Status text for the client + * @name Client#statusText * @type {string} */ - this.statusText = botOptions.statusText || null; + this.statusText = options.statusText || null; /** - * Text to output when the bot is ready - * @name Bot#readyText + * Text to output when the client is ready + * @name Client#readyText * @type {string} */ - this.readyText = botOptions.readyText || 'Ready!'; + this.readyText = options.readyText || 'Ready!'; /** * Whether or not a generic 'command not found' message * should be given in DMs to instruct the user to * use the `help` command. `true` by default - * @name Bot#unknownCommandError + * @name Client#unknownCommandError * @type {string} * @instance */ - this.unknownCommandError = botOptions.unknownCommandError === undefined ? - true : botOptions.unknownCommandError; + this.unknownCommandError = options.unknownCommandError === undefined ? + true : options.unknownCommandError; /** - * Whether or not the bot is a selfbot - * @name Bot#selfbot + * Whether or not the client is a selfbot + * @name Client#selfbot * @type {boolean} */ - this.selfbot = botOptions.selfbot || false; + this.selfbot = options.selfbot || false; /** - * Whether or not this bot is passive. Passive bots + * Whether or not this client is passive. Passive clients * will not register a command dispatcher or a message - * listener. This allows passive bots to be created that + * listener. This allows passive clients to be created that * do not respond to any commands but are able to perform * actions based on whatever the framework user wants - * @name Bot#passive + * @name Client#passive * @type {boolean} */ - this.passive = botOptions.passive || false; + this.passive = options.passive || false; /** - * Bot version, best taken from package.json - * @memberof Bot + * Client version, best taken from package.json + * @memberof Client * @type {string} * @name version * @instance */ - this.version = botOptions.version || '0.0.0'; + this.version = options.version || '0.0.0'; /** * Object containing token and owner ids - * @name Bot#config + * @name Client#config * @type {Object} - * @property {string} token - Discord login token for the bot + * @property {string} token - Discord login token for the client * @property {string[]} owner - Array of owner id strings */ - this.config = botOptions.config || null; + this.config = options.config || null; /** * Array of base command names to skip when loading commands. Base commands * may only be disabled by name, not by alias - * @name Bot#disableBase - * @type {string[]} + * @name Client#disableBase + * @type {BaseCommandName[]} */ - this.disableBase = botOptions.disableBase || []; + this.disableBase = options.disableBase || []; // Create the global RateLimiter instance if a ratelimit is specified - if (botOptions.ratelimit) - this._rateLimiter = new RateLimiter(botOptions.ratelimit, true); + if (options.ratelimit) + this._rateLimiter = new RateLimiter(options.ratelimit, true); - // Middleware function storage for the bot instance + // Middleware function storage for the client instance this._middleware = []; - this.provider = botOptions.provider || JSONProvider; + this.provider = options.provider || JSONProvider; this._guildDataStorage = new this.provider('guild_storage'); this._guildSettingStorage = new this.provider('guild_settings'); @@ -155,14 +157,14 @@ export class Bot extends Client /** * Client-specific storage. Also contains a `guilds` Collection property containing * all GuildStorage instances - * @name Bot#storage + * @name Client#storage * @type {ClientStorage} */ this.storage = this.storageFactory.createClientStorage(); /** * [Collection]{@link external:Collection} containing all loaded commands - * @name Bot#commands + * @name Client#commands * @type {CommandRegistry} */ this.commands = new CommandRegistry>(); @@ -171,7 +173,7 @@ export class Bot extends Client this._dispatcher = !this.passive ? new CommandDispatcher(this) : null; // Make some asserts - if (!this._token) throw new Error('You must provide a token for the bot.'); + if (!this._token) throw new Error('You must provide a token for the client.'); if (!this.commandsDir && !this.passive) throw new Error('You must provide a directory to load commands from via commandDir'); if (!this.config) throw new Error('You must provide a config containing token and owner ids.'); if (!this.config.owner) throw new Error('You must provide config array of owner ids.'); @@ -192,7 +194,7 @@ export class Bot extends Client await this._guildDataStorage.init(); await this._guildSettingStorage.init(); - // Load defaultGuildSettings into storage the first time the bot is run + // Load defaultGuildSettings into storage the first time the client is run if (typeof await this.storage.get('defaultGuildSettings') === 'undefined') await this.storage.set('defaultGuildSettings', require('../storage/defaultGuildSettings.json')); @@ -202,8 +204,8 @@ export class Bot extends Client /** * Returns whether or not the given user is an owner - * of the bot - * @method Bot#isOwner + * of the client/bot + * @method Client#isOwner * @param {User} user User to check * @returns {boolean} */ @@ -214,7 +216,7 @@ export class Bot extends Client /** * Loads/reloads all/specific commands - * @method Bot#loadCommand + * @method Client#loadCommand * @param {string} command The name of a command to reload, or 'all' to load all commands */ public loadCommand(command: string): void @@ -225,9 +227,9 @@ export class Bot extends Client } /** - * Logs the Bot in and registers some event handlers - * @method Bot#start - * @returns {Bot} + * Logs the Client in and registers some event handlers + * @method Client#start + * @returns {Client} */ public start(): this { @@ -262,10 +264,10 @@ export class Bot extends Client * Set the value of a default setting key and push it to all guild * setting storages. Will not overwrite a setting in guild settings * storage if there is already an existing key with the given value - * @method Bot#setDefaultSetting + * @method Client#setDefaultSetting * @param {string} key The key to use in settings storage * @param {any} value The value to use in settings storage - * @returns {Promise} + * @returns {Promise} */ public async setDefaultSetting(key: string, value: any): Promise { @@ -281,9 +283,9 @@ export class Bot extends Client * Remove a defaultGuildSettings item. Will not remove from ALL guild * settings, but will prevent the item from being added to new guild * settings storage upon creation - * @method Bot#removeDefaultSetting + * @method Client#removeDefaultSetting * @param {string} key The key to use in settings storage - * @returns {Promise} + * @returns {Promise} */ public async removeDefaultSetting(key: string): Promise { @@ -293,7 +295,7 @@ export class Bot extends Client /** * See if a default guild setting exists - * @method Bot#defaultSettingsExists + * @method Client#defaultSettingsExists * @param {string} key The key in storage to check * @returns {Promise} */ @@ -304,7 +306,7 @@ export class Bot extends Client /** * Shortcut to return the command prefix for the provided guild - * @method Bot#getPrefix + * @method Client#getPrefix * @param {external:Guild} guild The guild to get the prefix of * @returns {Promise} */ @@ -317,7 +319,7 @@ export class Bot extends Client /** * Clean out any guild storage/settings that no longer have * an associated guild - * @method Bot#sweepStorages + * @method Client#sweepStorages */ public sweepStorages(): void { @@ -346,13 +348,13 @@ export class Bot extends Client * to transform all args to uppercase. This will of course fail if any * of the args are not a string. * - * Note: Middleware functions should only be added to the bot one time each, + * Note: Middleware functions should only be added to the client one time each, * and thus should not be added within any sort of event or loop. * Multiple middleware functions can be added to the via multiple calls * to this method - * @method Bot#use + * @method Client#use * @param {MiddlewareFunction} fn Middleware function. `(message, args) => [message, args]` - * @returns {Bot} + * @returns {Client} */ public use(fn: MiddlewareFunction): this { @@ -415,7 +417,7 @@ export class Bot extends Client /** * Emitted whenever a command is successfully called - * @memberof Bot + * @memberof Client * @event event:command * @param {string} name Name of the called command * @param {any[]} args Args passed to the called command @@ -425,7 +427,7 @@ export class Bot extends Client /** * Emitted whenever a user is blacklisted - * @memberof Bot + * @memberof Client * @event event:blacklistAdd * @param {User} user User who was blacklisted * @param {boolean} global Whether or not blacklisting is global @@ -433,7 +435,7 @@ export class Bot extends Client /** * Emitted whenever a user is removed from the blacklist - * @memberof Bot + * @memberof Client * @event event:blacklistRemove * @param {User} user User who was removed * @param {boolean} global Whether or not removal is global @@ -442,14 +444,14 @@ export class Bot extends Client /** * Emitted when the client is waiting for you to send a `finished` event, * after which `clientReady` will be emitted - * @memberof Bot + * @memberof Client * @event event:waiting */ /** * To be emitted whenever you have finished setting things up that should * be set up before the client is ready for use - * @memberof Bot + * @memberof Client * @event event:finished */ @@ -457,7 +459,7 @@ export class Bot extends Client * Emitted when the client is ready. Should be used instead of Discord.js' * `ready` event, as this is the point that everything is set up within the * YAMDBF Client and it's all ready to go - * @memberof Bot + * @memberof Client * @event event:clientReady */ public on(event: string, listener: Function): this diff --git a/src/lib/command/Command.ts b/src/lib/command/Command.ts index 277ba99b..dd5d861f 100644 --- a/src/lib/command/Command.ts +++ b/src/lib/command/Command.ts @@ -1,5 +1,5 @@ import { PermissionResolvable, Message } from 'discord.js'; -import { Bot } from '../bot/Bot'; +import { Client } from '../client/Client'; import { MiddlewareFunction } from '../types/MiddlewareFunction'; import { CommandInfo } from '../types/CommandInfo'; import { RateLimiter } from './RateLimiter'; @@ -7,12 +7,12 @@ import { ArgOpts } from '../types/ArgOpts'; /** * Command class to extend to create commands users can execute - * @param {Bot} bot - Bot instance + * @param {Client} client - YAMDBF Client instance * @param {CommandInfo} info - Object containing required command properties */ -export class Command +export class Command { - public bot: T; + public client: T; public name: string; public description: string; public usage: string; @@ -31,14 +31,14 @@ export class Command public _rateLimiter: RateLimiter; public _middleware: MiddlewareFunction[]; - public constructor(bot: T, info: CommandInfo = null) + public constructor(client: T, info: CommandInfo = null) { /** * YAMDBF Client instance * @name Command#client * @type {Client} */ - this.bot = bot; + this.client = client; /** * The name of the command, used by the dispatcher @@ -55,16 +55,16 @@ export class Command */ /** - * An example of command usage. The token '<prefix>' will + * An example of command usage. The token `''` will * be replaced by the guild-specific command prefix in the Help command when - * 'help <command>' is called + * `'help '` is called * @name Command#usage * @type {string} */ /** * Extra information about the command to be displayed - * by the Help command when 'help <command>' is called + * by the Help command when `'help '` is called * @name Command#extraHelp * @type {string} */ @@ -121,10 +121,10 @@ export class Command */ /** - * Whether or not the command can be used by the bot owner(s). + * Whether or not the command can be used by the client/bot owner(s).
+ * **See:** [Client#config.owner]{@link Client#config} * @name Command#ownerOnly * @type {boolean} - * @see [Bot#config.owner]{@link Bot#config} */ /** @@ -192,7 +192,7 @@ export class Command { try { - ( this.bot).resolver.resolvePermission(perm); + ( this.client).resolver.resolvePermission(perm); } catch (err) { @@ -247,13 +247,13 @@ export class Command /** * Send provided response text to the command's calling channel * via edit, editCode, send, or sendCode depending on whether - * or not the bot is a selfbot and/or a codeblock language is given + * or not the client is a selfbot and/or a codeblock language is given * @protected */ protected respond(message: Message, response: string, code?: string): Promise { - if (this.bot.selfbot && !code) return message.edit(response); - if (this.bot.selfbot && code) return message.editCode(code, response); + if (this.client.selfbot && !code) return message.edit(response); + if (this.client.selfbot && code) return message.editCode(code, response); if (code) return message.channel.sendCode(code, response); return message.channel.sendMessage(response); } diff --git a/src/lib/command/CommandDispatcher.ts b/src/lib/command/CommandDispatcher.ts index 9c28df1e..cd2b1788 100644 --- a/src/lib/command/CommandDispatcher.ts +++ b/src/lib/command/CommandDispatcher.ts @@ -4,7 +4,7 @@ import { MiddlewareFunction } from '../types/MiddlewareFunction'; import { Message } from '../types/Message'; import { GuildStorage } from '../types/GuildStorage'; import { Command } from '../command/Command'; -import { Bot } from '../bot/Bot'; +import { Client } from '../client/Client'; import { RateLimit } from './RateLimit'; import { Time } from '../Time'; import now = require('performance-now'); @@ -13,15 +13,15 @@ import now = require('performance-now'); * Handles dispatching commands * @private */ -export class CommandDispatcher +export class CommandDispatcher { - private _bot: T; - public constructor(bot: T) + private _client: T; + public constructor(client: T) { - this._bot = bot; + this._client = client; // Register message listener - if (!this._bot.passive) this._bot.on('message', message => this.handleMessage(message)); + if (!this._client.passive) this._client.on('message', message => this.handleMessage(message)); } /** @@ -30,11 +30,11 @@ export class CommandDispatcher private async handleMessage(message: Message): Promise { const dispatchStart: number = now(); - if (this._bot.selfbot && message.author !== this._bot.user) return; + if (this._client.selfbot && message.author !== this._client.user) return; if (message.author.bot) return; const dm: boolean = message.channel.type !== 'text'; - if (!dm) message.guild.storage = this._bot.storage.guilds.get(message.guild.id); + if (!dm) message.guild.storage = this._client.storage.guilds.get(message.guild.id); // Check blacklist if (await this.isBlacklisted(message.author, message, dm)) return; @@ -42,23 +42,23 @@ export class CommandDispatcher const [commandCalled, command, prefix, name]: [boolean, Command, string, string] = await this.isCommandCalled(message); if (!commandCalled) { - if (dm && this._bot.unknownCommandError) + if (dm && this._client.unknownCommandError) message.channel.send(this.unknownCommandError()); return; } - if (command.ownerOnly && !this._bot.isOwner(message.author)) return; + if (command.ownerOnly && !this._client.isOwner(message.author)) return; // Check ratelimits if (!this.checkRateLimits(message, command)) return; - // Remove bot from message.mentions if only mentioned one time as a prefix + // Remove clientuser from message.mentions if only mentioned one time as a prefix if (!(!dm && prefix === await message.guild.storage.settings.get('prefix')) && prefix !== '' - && (message.content.match(new RegExp(`<@!?${this._bot.user.id}>`, 'g')) || []).length === 1) - message.mentions.users.delete(this._bot.user.id); + && (message.content.match(new RegExp(`<@!?${this._client.user.id}>`, 'g')) || []).length === 1) + message.mentions.users.delete(this._client.user.id); let validCaller: boolean = false; try { validCaller = await this.testCommand(command, message); } - catch (err) { message[this._bot.selfbot ? 'channel' : 'author'].send(err); } + catch (err) { message[this._client.selfbot ? 'channel' : 'author'].send(err); } if (!validCaller) return; let args: string[] = message.content @@ -69,7 +69,7 @@ export class CommandDispatcher .filter(a => a !== ''); let middlewarePassed: boolean = true; - let middleware: MiddlewareFunction[] = this._bot._middleware.concat(command._middleware); + let middleware: MiddlewareFunction[] = this._client._middleware.concat(command._middleware); for (let func of middleware) try { @@ -96,7 +96,7 @@ export class CommandDispatcher const dispatchEnd: number = now() - dispatchStart; - this._bot.emit('command', command.name, args, dispatchEnd, message); + this._client.emit('command', command.name, args, dispatchEnd, message); } /** @@ -108,8 +108,8 @@ export class CommandDispatcher { const dm: boolean = message.channel.type !== 'text'; const prefixes: string[] = [ - `<@${this._bot.user.id}>`, - `<@!${this._bot.user.id}>` + `<@${this._client.user.id}>`, + `<@!${this._client.user.id}>` ]; if (!dm) prefixes.push(await message.guild.storage.settings.get('prefix')); @@ -123,7 +123,7 @@ export class CommandDispatcher .slice(prefix.length).trim() .split(' ')[0]; - const command: Command = this._bot.commands.find(c => + const command: Command = this._client.commands.find(c => c.name === commandName || c.aliases.includes(commandName)); if (!command) return [false, null, null, null]; @@ -137,7 +137,7 @@ export class CommandDispatcher private async testCommand(command: Command, message: Message): Promise { const dm: boolean = message.channel.type !== 'text'; - const storage: GuildStorage = !dm ? this._bot.storage.guilds.get(message.guild.id) : null; + const storage: GuildStorage = !dm ? this._client.storage.guilds.get(message.guild.id) : null; if (!dm && typeof await storage.settings.get('disabledGroups') !== 'undefined' && (await storage.settings.get('disabledGroups')).includes(command.group)) return false; @@ -157,7 +157,7 @@ export class CommandDispatcher */ private checkRateLimiter(message: Message, command?: Command): boolean { - const rateLimiter: RateLimiter = command ? command._rateLimiter : this._bot._rateLimiter; + const rateLimiter: RateLimiter = command ? command._rateLimiter : this._client._rateLimiter; if (!rateLimiter) return true; const rateLimit: RateLimit = rateLimiter.get(message); @@ -165,7 +165,7 @@ export class CommandDispatcher if (!rateLimit.wasNotified) { - const globalLimiter: RateLimiter = this._bot._rateLimiter; + const globalLimiter: RateLimiter = this._client._rateLimiter; const globalLimit: RateLimit = globalLimiter ? globalLimiter.get(message) : null; if (globalLimit && globalLimit.isLimited && globalLimit.wasNotified) return; @@ -193,8 +193,8 @@ export class CommandDispatcher if (!this.checkRateLimiter(message, command)) passedCommand = false; if (!passedGlobal || !passedCommand) passedRateLimiters = false; if (passedRateLimiters) - if (!(command && command._rateLimiter && !command._rateLimiter.get(message).call()) && this._bot._rateLimiter) - this._bot._rateLimiter.get(message).call(); + if (!(command && command._rateLimiter && !command._rateLimiter.get(message).call()) && this._client._rateLimiter) + this._client._rateLimiter.get(message).call(); return passedRateLimiters; } @@ -203,7 +203,7 @@ export class CommandDispatcher */ private checkPermissions(command: Command, message: Message, dm: boolean): PermissionResolvable[] { - return this._bot.selfbot || dm ? [] : command.permissions.filter(a => + return this._client.selfbot || dm ? [] : command.permissions.filter(a => !( message.channel).permissionsFor(message.author).hasPermission(a)); } @@ -212,8 +212,8 @@ export class CommandDispatcher */ private async checkLimiter(command: Command, message: Message, dm: boolean): Promise { - if (dm || this._bot.selfbot) return true; - let storage: GuildStorage = this._bot.storage.guilds.get(message.guild.id); + if (dm || this._client.selfbot) return true; + let storage: GuildStorage = this._client.storage.guilds.get(message.guild.id); let limitedCommands: { [name: string]: string[] } = await storage.settings.get('limitedCommands') || {}; if (!limitedCommands[command.name]) return true; if (limitedCommands[command.name].length === 0) return true; @@ -226,7 +226,7 @@ export class CommandDispatcher */ private hasRoles(command: Command, message: Message, dm: boolean): boolean { - return this._bot.selfbot || command.roles.length === 0 || dm + return this._client.selfbot || command.roles.length === 0 || dm || message.member.roles.filter(role => command.roles.includes(role.name)).size > 0; } @@ -236,7 +236,7 @@ export class CommandDispatcher */ private async isBlacklisted(user: User, message: Message, dm: boolean): Promise { - if (await this._bot.storage.get(`blacklist.${user.id}`)) return true; + if (await this._client.storage.get(`blacklist.${user.id}`)) return true; if (!dm && await message.guild.storage.settings.get(`blacklist.${user.id}`)) return true; return false; } @@ -297,7 +297,7 @@ export class CommandDispatcher */ private async failedLimiterError(command: Command, message: Message): Promise { - const storage: GuildStorage = this._bot.storage.guilds.get(message.guild.id); + const storage: GuildStorage = this._client.storage.guilds.get(message.guild.id); let limitedCommands: { [name: string]: string[] } = await storage.settings.get('limitedCommands'); let roles: string[] = limitedCommands[command.name]; return `**You must have ${roles.length > 1 diff --git a/src/lib/command/CommandLoader.ts b/src/lib/command/CommandLoader.ts index e062e1a2..c19d4671 100644 --- a/src/lib/command/CommandLoader.ts +++ b/src/lib/command/CommandLoader.ts @@ -1,33 +1,34 @@ import * as glob from 'glob'; import * as path from 'path'; -import { CommandRegistry } from './CommandRegistry'; -import { Bot } from '../bot/Bot'; +import { Client } from '../client/Client'; import { Command } from './Command'; +import { CommandRegistry } from './CommandRegistry'; +import { BaseCommandName } from '../types/BaseCommandName'; /** - * Handles loading all commands from the given Bot's commandsDir + * Handles loading all commands from the given Client's commandsDir * @private */ -export class CommandLoader +export class CommandLoader { - private _bot: T; - public constructor(bot: T) + private _client: T; + public constructor(client: T) { - this._bot = bot; + this._client = client; } /** * Load or reload all commands from the base commands directory and the - * user-specified {@link Bot#commandsDir} directory and stores them in - * the Bot's {@link CommandRegistry} instance ({@link Bot#commands}) + * user-specified {@link Client#commandsDir} directory and stores them in + * the Client's {@link CommandRegistry} instance ({@link Client#commands}) */ public loadCommands(): void { - if (this._bot.commands.size > 0) this._bot.commands = new CommandRegistry>(); + if (this._client.commands.size > 0) this._client.commands = new CommandRegistry>(); let commandFiles: string[] = []; commandFiles.push(...glob.sync(`${path.join(__dirname, './base')}/**/*.js`)); - commandFiles.push(...glob.sync(`${this._bot.commandsDir}/**/*.js`)); + commandFiles.push(...glob.sync(`${this._client.commandsDir}/**/*.js`)); let loadedCommands: number = 0; for (const fileName of commandFiles) { @@ -35,44 +36,44 @@ export class CommandLoader delete require.cache[require.resolve(commandLocation)]; let loadedCommandClass: any = this.getCommandClass(commandLocation); - const _command: Command = new loadedCommandClass(this._bot); + const _command: Command = new loadedCommandClass(this._client); - if (this._bot.disableBase.includes(_command.name)) continue; + if (this._client.disableBase.includes( _command.name)) continue; _command._classloc = commandLocation; if (_command.overloads) { - if (!this._bot.commands.has(_command.overloads)) + if (!this._client.commands.has(_command.overloads)) throw new Error(`Command "${_command.overloads}" does not exist to be overloaded.`); - this._bot.commands.delete(_command.overloads); - this._bot.commands.register(_command, _command.name); + this._client.commands.delete(_command.overloads); + this._client.commands.register(_command, _command.name); console.log(`Command '${_command.name}' loaded, overloading command '${_command.overloads}'.`); } else { - this._bot.commands.register(_command, _command.name); + this._client.commands.register(_command, _command.name); loadedCommands++; console.log(`Command '${_command.name}' loaded.`); } } - console.log(`Loaded ${loadedCommands} total commands in ${this._bot.commands.groups.length} groups.`); + console.log(`Loaded ${loadedCommands} total commands in ${this._client.commands.groups.length} groups.`); } /** - * Reload the given command in the Bot's {@link CommandRegistry} ({@link Bot#commands}) + * Reload the given command in the Client's {@link CommandRegistry} ({@link Client#commands}) */ public reloadCommand(nameOrAlias: string): boolean { - const name: string = this._bot.commands.findByNameOrAlias(nameOrAlias).name; + const name: string = this._client.commands.findByNameOrAlias(nameOrAlias).name; if (!name) return false; - const commandLocation: string = this._bot.commands.get(name)._classloc; + const commandLocation: string = this._client.commands.get(name)._classloc; delete require.cache[require.resolve(commandLocation)]; const loadedCommandClass: any = this.getCommandClass(commandLocation); - const _command: Command = new loadedCommandClass(this._bot); + const _command: Command = new loadedCommandClass(this._client); _command._classloc = commandLocation; - this._bot.commands.register(_command, _command.name, true); + this._client.commands.register(_command, _command.name, true); console.log(`Command '${_command.name}' reloaded.`); return true; } diff --git a/src/lib/command/CommandRegistry.ts b/src/lib/command/CommandRegistry.ts index ec03748b..5cac1e8c 100644 --- a/src/lib/command/CommandRegistry.ts +++ b/src/lib/command/CommandRegistry.ts @@ -1,26 +1,24 @@ import { Collection, TextChannel, PermissionResolvable } from 'discord.js'; import { Command } from '../command/Command'; -import { Bot } from '../bot/Bot'; +import { Client } from '../client/Client'; import { Message } from '../types/Message'; /** - * Stores loaded Commands as <[name]{@link Command#name}, [Command]{@link Command}> pairs - * @private + * Stores loaded Commands as <[name]{@link Command#name}, [Command]{@link Command}> pairs * @class CommandRegistry * @extends {external:Collection} */ -export class CommandRegistry> extends Collection +export class CommandRegistry> extends Collection { public constructor() { super(); } /** * Complete registration of a command and add to the parent [Collection]{@link external:Collection}, * erroring on duplicate names and aliases - * @memberof CommandRegistry - * @instance - * @param {Command} command - The Command to be registered - * @param {string} key - The key to store the Command at. Will be {@link Command#name} - * @param {boolean} reload - Whether or not the command is being reloaded and + * @method CommandRegistry#register + * @param {Command} command The Command to be registered + * @param {string} key The key to store the Command at. Will be {@link Command#name} + * @param {boolean} reload Whether or not the command is being reloaded and * replaced in the collection */ public register(command: V, key: K, reload?: boolean): void @@ -44,8 +42,7 @@ export class CommandRegistry>} */ - public async filterGuildUsable(bot: T, message: Message): Promise> + public async filterGuildUsable(client: T, message: Message): Promise> { let filtered: Collection = new Collection(); const currentPermissions: (a: PermissionResolvable) => boolean = a => @@ -89,7 +84,7 @@ export class CommandRegistry 0 && message.member.roles.filter(role => c.roles.includes(role.name)).size === 0); const byOwnerOnly: (c: V) => boolean = c => - (( bot.config).owner.includes(message.author.id) && c.ownerOnly) || !c.ownerOnly; + (( client.config).owner.includes(message.author.id) && c.ownerOnly) || !c.ownerOnly; const disabledGroups: string[] = await message.guild.storage.settings.get('disabledGroups') || []; for (const [name, command] of this.filter(byPermissions).filter(byRoles).filter(byOwnerOnly).entries()) @@ -101,30 +96,28 @@ export class CommandRegistry} */ - public filterDMUsable(bot: T, message: Message): Collection + public filterDMUsable(client: T, message: Message): Collection { - return this.filter(c => !c.guildOnly && ((( bot.config).owner + return this.filter(c => !c.guildOnly && ((( client.config).owner .includes(message.author.id) && c.ownerOnly) || !c.ownerOnly)); } /** * Returns all commands that can have their help looked up by the user * in the DM channel the message is in - * @memberof CommandRegistry - * @instance - * @param {Bot} bot - Bot instance - * @param {external:Message} message - Discord.js Message object + * @method CommandRegistry#filterDMHelp + * @param {Client} client YAMDBF Client instance + * @param {external:Message} message Discord.js Message object * @returns {external:Collection} */ - public filterDMHelp(bot: T, message: Message): Collection + public filterDMHelp(client: T, message: Message): Collection { - return this.filter(c => (( bot.config).owner + return this.filter(c => (( client.config).owner .includes(message.author.id) && c.ownerOnly) || !c.ownerOnly); } } diff --git a/src/lib/command/base/Eval.ts b/src/lib/command/base/Eval.ts index 1b3bf63c..42fda5cd 100644 --- a/src/lib/command/base/Eval.ts +++ b/src/lib/command/base/Eval.ts @@ -1,15 +1,15 @@ -import { Bot } from '../../bot/Bot'; +import { Client } from '../../client/Client'; import { Message } from '../../types/Message'; import { Command } from '../Command'; import { inspect } from 'util'; const Discord = require('discord.js'); // tslint:disable-line const Yamdbf = require('../../../index'); // tslint:disable-line -export default class extends Command +export default class extends Command { - public constructor(bot: Bot) + public constructor(client: Client) { - super(bot, { + super(client, { name: 'eval', description: 'Evaluate provided Javascript code', usage: 'eval ', diff --git a/src/lib/command/base/Help.ts b/src/lib/command/base/Help.ts index a807a38a..6205f805 100644 --- a/src/lib/command/base/Help.ts +++ b/src/lib/command/base/Help.ts @@ -1,14 +1,14 @@ -import { Bot } from '../../bot/Bot'; +import { Client } from '../../client/Client'; import { Message } from '../../types/Message'; import { Util } from '../../Util'; import { Command } from '../Command'; import { Collection, RichEmbed } from 'discord.js'; -export default class extends Command +export default class extends Command { - public constructor(bot: Bot) + public constructor(client: Client) { - super(bot, { + super(client, { name: 'help', description: 'Provides information on bot commands', usage: `help [command]`, @@ -18,22 +18,22 @@ export default class extends Command public async action(message: Message, [commandName]: [string]): Promise { - if (this.bot.selfbot) message.delete(); + if (this.client.selfbot) message.delete(); const dm: boolean = message.channel.type !== 'text'; - const mentionName: string = `@${this.bot.user.username}#${this.bot.user.discriminator}`; + const mentionName: string = `@${this.client.user.username}#${this.client.user.discriminator}`; - let command: Command; + let command: Command; let output: string = ''; let embed: RichEmbed = new RichEmbed(); if (!commandName) { const preText: string = `Available commands in ${dm ? 'this DM' : message.channel}\n\`\`\`ldif\n`; - const postText: string = `\`\`\`Use \`help \` ${this.bot.selfbot ? '' : `or \`${ + const postText: string = `\`\`\`Use \`help \` ${this.client.selfbot ? '' : `or \`${ mentionName} help \` `}for more information.\n\n`; - const usableCommands: Collection> = (await this.bot.commands[dm - ? 'filterDMUsable' : 'filterGuildUsable'](this.bot, message)) + const usableCommands: Collection> = (await this.client.commands[dm + ? 'filterDMUsable' : 'filterGuildUsable'](this.client, message)) .filter(c => !c.hidden); const widest: number = usableCommands.map(c => c.name.length).reduce((a, b) => Math.max(a, b)); @@ -55,8 +55,8 @@ export default class extends Command } else { - command = (await this.bot.commands[dm - ? 'filterDMUsable' : 'filterGuildUsable'](this.bot, message)) + command = (await this.client.commands[dm + ? 'filterDMUsable' : 'filterGuildUsable'](this.client, message)) .filter(c => c.name === commandName || c.aliases.includes(commandName)) .first(); @@ -72,14 +72,14 @@ export default class extends Command } output = dm ? output.replace(//g, '') - : output.replace(//g, await this.bot.getPrefix(message.guild) || ''); + : output.replace(//g, await this.client.getPrefix(message.guild) || ''); embed.setColor(11854048).setDescription(output); let outMessage: Message; - if (!dm && !this.bot.selfbot && command) message.reply(`Sent you a DM with command help information.`); - if (!dm && !this.bot.selfbot && !command) message.reply(`Sent you a DM with a list of commands.`); - if (this.bot.selfbot) outMessage = await message.channel.sendEmbed(embed); + if (!dm && !this.client.selfbot && command) message.reply(`Sent you a DM with command help information.`); + if (!dm && !this.client.selfbot && !command) message.reply(`Sent you a DM with a list of commands.`); + if (this.client.selfbot) outMessage = await message.channel.sendEmbed(embed); else message.author.sendEmbed(embed); if (outMessage) outMessage.delete(30e3); diff --git a/src/lib/command/base/Ping.ts b/src/lib/command/base/Ping.ts index ed08a349..054b45f9 100644 --- a/src/lib/command/base/Ping.ts +++ b/src/lib/command/base/Ping.ts @@ -1,12 +1,12 @@ -import { Bot } from '../../bot/Bot'; +import { Client } from '../../client/Client'; import { Message } from '../../types/Message'; import { Command } from '../Command'; -export default class extends Command +export default class extends Command { - public constructor(bot: Bot) + public constructor(client: Client) { - super(bot, { + super(client, { name: 'ping', description: 'Pong!', usage: 'ping' @@ -16,7 +16,7 @@ export default class extends Command public async action(message: Message): Promise { let msg: Message; - if (this.bot.selfbot) msg = await message.edit('Pong!'); + if (this.client.selfbot) msg = await message.edit('Pong!'); else msg = await message.channel.send('Pong!'); msg.edit(`Pong! (${msg.createdTimestamp - message.createdTimestamp}ms)`); } diff --git a/src/lib/command/base/Reload.ts b/src/lib/command/base/Reload.ts index e783bc86..908ef731 100644 --- a/src/lib/command/base/Reload.ts +++ b/src/lib/command/base/Reload.ts @@ -1,13 +1,13 @@ -import { Bot } from '../../bot/Bot'; +import { Client } from '../../client/Client'; import { Message } from '../../types/Message'; import { Command } from '../Command'; import now = require('performance-now'); -export default class extends Command +export default class extends Command { - public constructor(bot: Bot) + public constructor(client: Client) { - super(bot, { + super(client, { name: 'reload', description: 'Reload a command or all commands', usage: 'reload [command]', @@ -19,13 +19,13 @@ export default class extends Command public action(message: Message, [commandName]: [string]): Promise { const start: number = now(); - const command: Command = this.bot.commands.findByNameOrAlias(commandName); + const command: Command = this.client.commands.findByNameOrAlias(commandName); if (commandName && !command) return this.respond(message, `Command "${commandName}" could not be found.`); - if (command) this.bot.loadCommand(command.name); - else this.bot.loadCommand('all'); + if (command) this.client.loadCommand(command.name); + else this.client.loadCommand('all'); const end: number = now(); const name: string = command ? command.name : null; diff --git a/src/lib/command/base/SetPrefix.ts b/src/lib/command/base/SetPrefix.ts index fb6a3803..3fb8feb7 100644 --- a/src/lib/command/base/SetPrefix.ts +++ b/src/lib/command/base/SetPrefix.ts @@ -1,15 +1,15 @@ -import { Bot } from '../../bot/Bot'; +import { Client } from '../../client/Client'; import { Message } from '../../types/Message'; import { Command } from '../Command'; import { Middleware } from '../middleware/Middleware'; import * as CommandDecorators from '../CommandDecorators'; const { using } = CommandDecorators; -export default class extends Command +export default class extends Command { - public constructor(bot: Bot) + public constructor(client: Client) { - super(bot, { + super(client, { name: 'setprefix', description: 'Set or check the bot command prefix for this guild', aliases: ['prefix'], @@ -23,8 +23,8 @@ export default class extends Command public async action(message: Message, [prefix]: [string]): Promise { if (!prefix) - return this.respond(message, `${this.bot.getPrefix(message.guild) - ? `Current prefix is \`${this.bot.getPrefix(message.guild)}\`` + return this.respond(message, `${this.client.getPrefix(message.guild) + ? `Current prefix is \`${this.client.getPrefix(message.guild)}\`` : 'There is currently no prefix.'}`); if (prefix.length > 10) @@ -35,11 +35,11 @@ export default class extends Command if (prefix === 'noprefix') prefix = ''; - if (this.bot.selfbot) - for (const guild of this.bot.storage.guilds.values()) + if (this.client.selfbot) + for (const guild of this.client.storage.guilds.values()) await guild.settings.set('prefix', prefix); - else await this.bot.storage.guilds.get(message.guild.id).settings.set('prefix', prefix); + else await this.client.storage.guilds.get(message.guild.id).settings.set('prefix', prefix); this.respond(message, prefix === '' ? 'Command prefix removed.' : `Command prefix set to \`${prefix}\``); } diff --git a/src/lib/command/base/Version.ts b/src/lib/command/base/Version.ts index aeb5f495..7f9ac19e 100644 --- a/src/lib/command/base/Version.ts +++ b/src/lib/command/base/Version.ts @@ -1,12 +1,12 @@ -import { Bot } from '../../bot/Bot'; +import { Client } from '../../client/Client'; import { Message } from '../../types/Message'; import { Command } from '../Command'; -export default class extends Command +export default class extends Command { - public constructor(bot: Bot) + public constructor(client: Client) { - super(bot, { + super(client, { name: 'version', description: 'Get the version of the bot', usage: `version` @@ -15,6 +15,6 @@ export default class extends Command public action(message: Message): void { - this.respond(message, `Current version is: **${this.bot.version}**`); + this.respond(message, `Current version is: **${this.client.version}**`); } } diff --git a/src/lib/command/base/blacklist/Blacklist.ts b/src/lib/command/base/blacklist/Blacklist.ts index fd843b5a..1fe4971e 100644 --- a/src/lib/command/base/blacklist/Blacklist.ts +++ b/src/lib/command/base/blacklist/Blacklist.ts @@ -1,4 +1,4 @@ -import { Bot } from '../../../bot/Bot'; +import { Client } from '../../../client/Client'; import { Message } from '../../../types/Message'; import { Command } from '../../Command'; import { Middleware } from '../../middleware/Middleware'; @@ -6,11 +6,11 @@ import { User } from 'discord.js'; import * as CommandDecorators from '../../CommandDecorators'; const { using } = CommandDecorators; -export default class extends Command +export default class extends Command { - public constructor(bot: Bot) + public constructor(client: Client) { - super(bot, { + super(client, { name: 'blacklist', description: 'Blacklist a user from calling commands', aliases: ['bl'], @@ -32,15 +32,15 @@ export default class extends Command if (global === 'global') { - if (!this.bot.isOwner(message.author)) + if (!this.client.isOwner(message.author)) return message.channel.send('Only bot owners may blacklist globally.'); - const globalBlacklist: any = await this.bot.storage.get('blacklist') || {}; + const globalBlacklist: any = await this.client.storage.get('blacklist') || {}; if (globalBlacklist[user.id]) return message.channel.send('That user is already globally blacklisted.'); - await this.bot.storage.set(`blacklist.${user.id}`, true); - this.bot.emit('blacklistAdd', user, true); + await this.client.storage.set(`blacklist.${user.id}`, true); + this.client.emit('blacklistAdd', user, true); return message.channel.send(`Added ${user.username}#${user.discriminator} to the global blacklist.`); } @@ -53,7 +53,7 @@ export default class extends Command return message.channel.send('That user is already blacklisted in this server.'); await message.guild.storage.settings.set(`blacklist.${user.id}`, true); - this.bot.emit('blacklistAdd', user, false); + this.client.emit('blacklistAdd', user, false); return message.channel.send(`Added ${user.username}#${user.discriminator} to this server's blacklist.`); } } diff --git a/src/lib/command/base/blacklist/Whitelist.ts b/src/lib/command/base/blacklist/Whitelist.ts index dce290d2..2c562d20 100644 --- a/src/lib/command/base/blacklist/Whitelist.ts +++ b/src/lib/command/base/blacklist/Whitelist.ts @@ -1,4 +1,4 @@ -import { Bot } from '../../../bot/Bot'; +import { Client } from '../../../client/Client'; import { Message } from '../../../types/Message'; import { Command } from '../../Command'; import { Middleware } from '../../middleware/Middleware'; @@ -6,11 +6,11 @@ import { User } from 'discord.js'; import * as CommandDecorators from '../../CommandDecorators'; const { using } = CommandDecorators; -export default class extends Command +export default class extends Command { - public constructor(bot: Bot) + public constructor(client: Client) { - super(bot, { + super(client, { name: 'whitelist', description: 'Remove a user from the command blacklist', aliases: ['wl'], @@ -25,15 +25,15 @@ export default class extends Command { if (global === 'global') { - if (!this.bot.isOwner(message.author)) + if (!this.client.isOwner(message.author)) return message.channel.send('Only bot owners may remove a global blacklisting.'); - const globalBlacklist: any = await this.bot.storage.get('blacklist') || {}; + const globalBlacklist: any = await this.client.storage.get('blacklist') || {}; if (!globalBlacklist[user.id]) return message.channel.send('That user is not currently globally blacklisted.'); - await this.bot.storage.remove(`blacklist.${user.id}`); - this.bot.emit('blacklistRemove', user, true); + await this.client.storage.remove(`blacklist.${user.id}`); + this.client.emit('blacklistRemove', user, true); return message.channel.send(`Removed ${user.username}#${user.discriminator} from the global blacklist.`); } @@ -42,7 +42,7 @@ export default class extends Command return message.channel.send('That user is not currently blacklisted in this server.'); message.guild.storage.settings.remove(`blacklist.${user.id}`); - this.bot.emit('blacklistRemove', user, false); + this.client.emit('blacklistRemove', user, false); return message.channel.send(`Removed ${user.username}#${user.discriminator} from this server's blacklist.`); } } diff --git a/src/lib/command/base/groupcontrol/ClearLimit.ts b/src/lib/command/base/groupcontrol/ClearLimit.ts index 2a1d6102..36481711 100644 --- a/src/lib/command/base/groupcontrol/ClearLimit.ts +++ b/src/lib/command/base/groupcontrol/ClearLimit.ts @@ -1,4 +1,4 @@ -import { Bot } from '../../../bot/Bot'; +import { Client } from '../../../client/Client'; import { Message } from '../../../types/Message'; import { Util } from '../../../Util'; import { Command } from '../../Command'; @@ -7,11 +7,11 @@ import { GuildStorage } from '../../../types/GuildStorage'; import * as CommandDecorators from '../../CommandDecorators'; const { using } = CommandDecorators; -export default class extends Command +export default class extends Command { - public constructor(bot: Bot) + public constructor(client: Client) { - super(bot, { + super(client, { name: 'clearlimit', description: 'Clear role restrictions from a command', usage: 'clearlimit ', @@ -22,7 +22,7 @@ export default class extends Command @using(Middleware.expect({ '': 'String' })) public async action(message: Message, [commandName]: [string]): Promise { - let command: Command = this.bot.commands.find(c => Util.normalize(c.name) === Util.normalize(commandName)); + let command: Command = this.client.commands.find(c => Util.normalize(c.name) === Util.normalize(commandName)); if (!command) return this.respond(message, `Failed to find a command with the name \`${commandName}\``); const storage: GuildStorage = message.guild.storage; diff --git a/src/lib/command/base/groupcontrol/DisableGroup.ts b/src/lib/command/base/groupcontrol/DisableGroup.ts index 5b78dece..cf7eb049 100644 --- a/src/lib/command/base/groupcontrol/DisableGroup.ts +++ b/src/lib/command/base/groupcontrol/DisableGroup.ts @@ -1,15 +1,15 @@ -import { Bot } from '../../../bot/Bot'; +import { Client } from '../../../client/Client'; import { Message } from '../../../types/Message'; import { Command } from '../../Command'; import { Middleware } from '../../middleware/Middleware'; import * as CommandDecorators from '../../CommandDecorators'; const { using } = CommandDecorators; -export default class extends Command +export default class extends Command { - public constructor(bot: Bot) + public constructor(client: Client) { - super(bot, { + super(client, { name: 'disablegroup', description: 'Disable a command group', aliases: ['disable', 'dg'], @@ -27,7 +27,7 @@ export default class extends Command DISABLED: `Command group "${group}" is already disabled or is not allowed to be disabled.` }; - if (!this.bot.commands.groups.includes(group)) return this.respond(message, err.NO_EXIST); + if (!this.client.commands.groups.includes(group)) return this.respond(message, err.NO_EXIST); const disabledGroups: string[] = await message.guild.storage.settings.get('disabledGroups') || []; if (group === 'base' || disabledGroups.includes(group)) return this.respond(message, err.DISABLED); diff --git a/src/lib/command/base/groupcontrol/EnableGroup.ts b/src/lib/command/base/groupcontrol/EnableGroup.ts index d380e1ea..918c47d1 100644 --- a/src/lib/command/base/groupcontrol/EnableGroup.ts +++ b/src/lib/command/base/groupcontrol/EnableGroup.ts @@ -1,15 +1,15 @@ -import { Bot } from '../../../bot/Bot'; +import { Client } from '../../../client/Client'; import { Message } from '../../../types/Message'; import { Command } from '../../Command'; import { Middleware } from '../../middleware/Middleware'; import * as CommandDecorators from '../../CommandDecorators'; const { using } = CommandDecorators; -export default class extends Command +export default class extends Command { - public constructor(bot: Bot) + public constructor(client: Client) { - super(bot, { + super(client, { name: 'enablegroup', description: 'Enable a command group', aliases: ['enable', 'eg'], @@ -27,7 +27,7 @@ export default class extends Command ENABLED: `Command group ${group} is already enabled.` }; - if (!this.bot.commands.groups.includes(group)) return this.respond(message, err.NO_EXIST); + if (!this.client.commands.groups.includes(group)) return this.respond(message, err.NO_EXIST); const disabledGroups: string[] = await message.guild.storage.settings.get('disabledGroups') || []; if (group === 'base' || !disabledGroups.includes(group)) return this.respond(message, err.ENABLED); diff --git a/src/lib/command/base/groupcontrol/Limit.ts b/src/lib/command/base/groupcontrol/Limit.ts index cfacf8b9..8d3f72b0 100644 --- a/src/lib/command/base/groupcontrol/Limit.ts +++ b/src/lib/command/base/groupcontrol/Limit.ts @@ -1,4 +1,4 @@ -import { Bot } from '../../../bot/Bot'; +import { Client } from '../../../client/Client'; import { GuildStorage } from '../../../types/GuildStorage'; import { Message } from '../../../types/Message'; import { Util } from '../../../Util'; @@ -8,11 +8,11 @@ import { Role } from 'discord.js'; import * as CommandDecorators from '../../CommandDecorators'; const { using } = CommandDecorators; -export default class extends Command +export default class extends Command { - public constructor(bot: Bot) + public constructor(client: Client) { - super(bot, { + super(client, { name: 'limit', description: 'Limit a command to the provided roles', usage: 'limit , ', @@ -25,7 +25,7 @@ export default class extends Command @using(Middleware.expect({ '': 'String' })) public async action(message: Message, [commandName, ...roleNames]: [string, string]): Promise { - const command: Command = this.bot.commands.find(c => Util.normalize(commandName) === Util.normalize(c.name)); + const command: Command = this.client.commands.find(c => Util.normalize(commandName) === Util.normalize(c.name)); if (!command) return this.respond(message, `Failed to find a command with the name \`${commandName}\``); if (command.group === 'base') this.respond(message, `Cannot limit base commands.`); diff --git a/src/lib/command/base/groupcontrol/ListGroups.ts b/src/lib/command/base/groupcontrol/ListGroups.ts index e1584de3..643351c0 100644 --- a/src/lib/command/base/groupcontrol/ListGroups.ts +++ b/src/lib/command/base/groupcontrol/ListGroups.ts @@ -1,25 +1,24 @@ -import { Bot } from '../../../bot/Bot'; +import { Client } from '../../../client/Client'; import { Message } from '../../../types/Message'; import { Command } from '../../Command'; -export default class extends Command +export default class extends Command { - public constructor(bot: Bot) + public constructor(client: Client) { - super(bot, { + super(client, { name: 'listgroups', description: 'List all command groups and their status', aliases: ['lg'], usage: 'listgroups', extraHelp: `A '*' denotes a disabled group when listing all command groups.`, - group: 'base', permissions: ['ADMINISTRATOR'] }); } public async action(message: Message): Promise { - let groups: string[] = this.bot.commands.groups; + let groups: string[] = this.client.commands.groups; let disabledGroups: string[] = await message.guild.storage.settings.get('disabledGroups') || []; let output: string = 'Command groups:\n'; diff --git a/src/lib/command/middleware/Expect.ts b/src/lib/command/middleware/Expect.ts index c5115e0d..6bb0e8ee 100644 --- a/src/lib/command/middleware/Expect.ts +++ b/src/lib/command/middleware/Expect.ts @@ -1,11 +1,11 @@ -import { Bot } from '../../bot/Bot'; +import { Client } from '../../client/Client'; import { MiddlewareFunction } from '../../types/MiddlewareFunction'; import { ExpectArgType } from '../../types/ExpectArgType'; import { Message } from '../../types/Message'; import { Command } from '../Command'; import { GuildMember, Role, TextChannel, User } from 'discord.js'; -export function expect>(argTypes: { [name: string]: ExpectArgType }): MiddlewareFunction +export function expect>(argTypes: { [name: string]: ExpectArgType }): MiddlewareFunction { return async function(message, args): Promise<[Message, any[]]> { diff --git a/src/lib/command/middleware/Middleware.ts b/src/lib/command/middleware/Middleware.ts index 5a92a7d6..a46e3298 100644 --- a/src/lib/command/middleware/Middleware.ts +++ b/src/lib/command/middleware/Middleware.ts @@ -1,4 +1,4 @@ -import { Bot } from '../../bot/Bot'; +import { Client } from '../../client/Client'; import { Command } from '../Command'; import { expect } from './Expect'; import { resolveArgs } from './ResolveArgs'; @@ -36,7 +36,7 @@ export class Middleware * (message: Message, args: any[]) => [Message, any[]] * ``` */ - public static resolveArgs: >(argTypes: { [name: string]: ResolveArgType }) => + public static resolveArgs: >(argTypes: { [name: string]: ResolveArgType }) => MiddlewareFunction = resolveArgs; /** @@ -66,6 +66,6 @@ export class Middleware * (message: Message, args: any[]) => [Message, any[]] * ``` */ - public static expect: >(argTypes: { [name: string]: ExpectArgType }) => + public static expect: >(argTypes: { [name: string]: ExpectArgType }) => MiddlewareFunction = expect; } diff --git a/src/lib/command/middleware/ResolveArgs.ts b/src/lib/command/middleware/ResolveArgs.ts index 99282793..74581dff 100644 --- a/src/lib/command/middleware/ResolveArgs.ts +++ b/src/lib/command/middleware/ResolveArgs.ts @@ -1,4 +1,4 @@ -import { Bot } from '../../bot/Bot'; +import { Client } from '../../client/Client'; import { Message } from '../../types/Message'; import { MiddlewareFunction } from '../../types/MiddlewareFunction'; import { ResolveArgType } from '../../types/ResolveArgType'; @@ -6,7 +6,7 @@ import { Util } from '../../Util'; import { Command } from '../Command'; import { Collection, GuildMember, Role, TextChannel, User } from 'discord.js'; -export function resolveArgs>(argTypes: { [name: string]: ResolveArgType }): MiddlewareFunction +export function resolveArgs>(argTypes: { [name: string]: ResolveArgType }): MiddlewareFunction { return async function(message, args): Promise<[Message, any[]]> { @@ -90,7 +90,7 @@ export function resolveArgs>(argTypes: { [na else { const normalized: string = normalizeUser(arg); - let users: Collection = ( this).bot.users.filter(a => normalizeUser(a.username).includes(normalized) + let users: Collection = ( this).client.users.filter(a => normalizeUser(a.username).includes(normalized) || normalizeUser(`${a.username}#${a.discriminator}`).includes(normalized)); if (message.channel.type === 'text') diff --git a/src/lib/storage/GuildSettings.ts b/src/lib/storage/GuildSettings.ts index 12611807..ef311e52 100644 --- a/src/lib/storage/GuildSettings.ts +++ b/src/lib/storage/GuildSettings.ts @@ -1,7 +1,7 @@ import { Guild } from 'discord.js'; import { StorageProvider } from './StorageProvider'; import { Util } from '../Util'; -import { Bot } from '../bot/Bot'; +import { Client } from '../client/Client'; /** * Class containing asynchronous methods for storing, retrieving, and @@ -15,7 +15,7 @@ export class GuildSettings private _id: string; private _client: any; private _cache: { [key: string]: any }; - public constructor(storage: StorageProvider, guild: Guild, client: Bot) + public constructor(storage: StorageProvider, guild: Guild, client: Client) { this._provider = storage; this._guild = guild; diff --git a/src/lib/storage/GuildStorageLoader.ts b/src/lib/storage/GuildStorageLoader.ts index 264a997e..d3026ba6 100644 --- a/src/lib/storage/GuildStorageLoader.ts +++ b/src/lib/storage/GuildStorageLoader.ts @@ -1,5 +1,5 @@ import { Collection, Guild } from 'discord.js'; -import { Bot } from '../bot/Bot'; +import { Client } from '../client/Client'; import { StorageProvider } from './StorageProvider'; /** @@ -7,12 +7,12 @@ import { StorageProvider } from './StorageProvider'; * {@link GuildStorage} objects * @private */ -export class GuildStorageLoader +export class GuildStorageLoader { private _client: T; - public constructor(bot: T) + public constructor(client: T) { - this._client = bot; + this._client = client; } /** diff --git a/src/lib/storage/StorageFactory.ts b/src/lib/storage/StorageFactory.ts index be5627ac..9a8e6da3 100644 --- a/src/lib/storage/StorageFactory.ts +++ b/src/lib/storage/StorageFactory.ts @@ -1,7 +1,7 @@ import { KeyedStorage } from './KeyedStorage'; import { GuildStorage } from '../types/GuildStorage'; import { StorageProvider } from './StorageProvider'; -import { Bot } from '../bot/Bot'; +import { Client } from '../client/Client'; import { GuildSettings } from './GuildSettings'; import { Guild, Collection } from 'discord.js'; import { ClientStorage } from '../types/ClientStorage'; @@ -9,7 +9,7 @@ import { ClientStorage } from '../types/ClientStorage'; /** * Used for creating the different storage class mixins used throughout * and needed by YAMDBF Clients. Used internally, shouldn't ever - * need to be used in your bots + * need to be used directly in a custom client * @private * @class StorageFactory * @param {Client} client The YAMDBF Client instance @@ -18,10 +18,10 @@ import { ClientStorage } from '../types/ClientStorage'; */ export class StorageFactory { - private _client: Bot; + private _client: Client; private _guildDataStorage: StorageProvider; private _guildSettingStorage: StorageProvider; - public constructor(client: Bot, guildDataStorage: StorageProvider, guildSettingStorage: StorageProvider) + public constructor(client: Client, guildDataStorage: StorageProvider, guildSettingStorage: StorageProvider) { this._client = client; this._guildDataStorage = guildDataStorage; diff --git a/src/lib/types/BotOptions.ts b/src/lib/types/BotOptions.ts deleted file mode 100644 index 9b52d0cd..00000000 --- a/src/lib/types/BotOptions.ts +++ /dev/null @@ -1,36 +0,0 @@ -/** - * @typedef {Object} BotOptions Object containing required {@link Bot} properties to be - * passed to a Bot on construction - * @property {string} [name='botname'] See: {@link Bot#name} - * @property {string} token See: {@link Bot#token} - * @property {string} [provider] See: {@link Bot#provider} - * @property {string} [commandsDir] See: {@link Bot#commandsDir} - * @property {string} [statusText=null] See: {@link Bot#statusText} - * @property {string} [readyText='Ready!'] See: {@link Bot#readyText} - * @property {boolean} [unknownCommandError=true] See: {@link Bot#unknownCommandError} - * @property {boolean} [selfbot=false] See: {@link Bot#selfbot} - * @property {boolean} [passive=false] see {@link Bot#passive} - * @property {string} [version='0.0.0'] See: {@link Bot#version} - * @property {Object} config See: {@link Bot#config} - * @property {string[]} [disableBase=[]] See: {@link Bot#disableBase} - * @property {string} [ratelimit] Sets a global rate limit on command calls for every user - */ - -import { StorageProviderConstructor } from './StorageProviderConstructor'; -import { BaseCommandName } from './BaseCommandName'; - -export type BotOptions = { - name: string; - token: string; - provider?: StorageProviderConstructor; - commandsDir?: string; - statusText?: string; - readyText?: string; - unknownCommandError?: boolean; - selfbot?: boolean; - passive?: boolean; - version?: string; - disableBase?: BaseCommandName[]; - ratelimit?: string; - config: any; -}; diff --git a/src/lib/types/DefaultGuildSettings.ts b/src/lib/types/DefaultGuildSettings.ts index 04148a23..38062cda 100644 --- a/src/lib/types/DefaultGuildSettings.ts +++ b/src/lib/types/DefaultGuildSettings.ts @@ -1,6 +1,6 @@ /** * @typedef {Object} DefaultGuildSettings - The default settings to apply to new guilds. - * Stored under the key `'defaultGuildSettings'` in {@link Bot#storage} + * Stored under the key `'defaultGuildSettings'` in {@link Client#storage} * @property {string} prefix='/' Prefix to prepend commands * @property {Array} [disabledGroups=[]] Command groups to ignore */ diff --git a/src/lib/types/Message.ts b/src/lib/types/Message.ts index 00dc8cc6..3e8f371f 100644 --- a/src/lib/types/Message.ts +++ b/src/lib/types/Message.ts @@ -3,7 +3,7 @@ * containing a {@link GuildStorage} for the associated guild, if the message was sent * from within a guild, mixed in by the CommandDispatcher. * - * >**Note:** For bots written in Typescript, you will want to import + * >**Note:** For clients written in Typescript, you will want to import * `Message` from YAMDBF rather than Discord.js to be able to * access `message.guild.storage` within your commands without * compiler errors diff --git a/src/lib/types/YAMDBFOptions.ts b/src/lib/types/YAMDBFOptions.ts new file mode 100644 index 00000000..cc225940 --- /dev/null +++ b/src/lib/types/YAMDBFOptions.ts @@ -0,0 +1,36 @@ +/** + * @typedef {Object} YAMDBFOptions Object containing required {@link Client} properties to be + * passed to a Client on construction + * @property {string} [name='botname'] See: {@link Client#name} + * @property {string} token See: {@link Client#token} + * @property {string} [provider] See: {@link Client#provider} + * @property {string} [commandsDir] See: {@link Client#commandsDir} + * @property {string} [statusText=null] See: {@link Client#statusText} + * @property {string} [readyText='Ready!'] See: {@link Client#readyText} + * @property {boolean} [unknownCommandError=true] See: {@link Client#unknownCommandError} + * @property {boolean} [selfbot=false] See: {@link Client#selfbot} + * @property {boolean} [passive=false] see {@link Client#passive} + * @property {string} [version='0.0.0'] See: {@link Client#version} + * @property {Object} config See: {@link Client#config} + * @property {string[]} [disableBase=[]] See: {@link Client#disableBase} + * @property {string} [ratelimit] Sets a global rate limit on command calls for every user + */ + +import { StorageProviderConstructor } from './StorageProviderConstructor'; +import { BaseCommandName } from './BaseCommandName'; + +export type YAMDBFOptions = { + name: string; + token: string; + provider?: StorageProviderConstructor; + commandsDir?: string; + statusText?: string; + readyText?: string; + unknownCommandError?: boolean; + selfbot?: boolean; + passive?: boolean; + version?: string; + disableBase?: BaseCommandName[]; + ratelimit?: string; + config: any; +}; diff --git a/test/commands/test_command.ts b/test/commands/test_command.ts index e5a18390..4611e56d 100644 --- a/test/commands/test_command.ts +++ b/test/commands/test_command.ts @@ -1,10 +1,10 @@ -import { Bot, Command, Message, CommandDecorators } from '../../bin'; +import { Client, Command, Message, CommandDecorators } from '../../bin'; const { using, guildOnly } = CommandDecorators; @guildOnly -export default class extends Command +export default class extends Command { - public constructor(client: Bot) + public constructor(client: Client) { super(client, { name: 'test', diff --git a/test/test_client.ts b/test/test_client.ts index ffc4f6cf..9e191443 100644 --- a/test/test_client.ts +++ b/test/test_client.ts @@ -1,8 +1,8 @@ -import { Bot } from '../bin'; +import { Client } from '../bin'; import * as path from 'path'; const config: any = require('./config.json'); -const client: Bot = new Bot({ +const client: Client = new Client({ name: 'test', token: config.token, config: config,