From 11a8e26ddb73673822c472b3b106e21d4736e8bc Mon Sep 17 00:00:00 2001 From: Dragon Fire Date: Tue, 17 Jul 2018 21:53:48 -0400 Subject: [PATCH] Back to private :) --- README.md | 21 +--- Xiao.js | 18 +-- commands/util/invite.js | 8 +- commands/util/uptime.js | 18 --- package.json | 4 +- providers/Sequelize.js | 244 --------------------------------------- structures/Client.js | 13 --- structures/PostgreSQL.js | 23 ---- util/BotList.js | 20 ---- 9 files changed, 14 insertions(+), 355 deletions(-) delete mode 100644 commands/util/uptime.js delete mode 100644 providers/Sequelize.js delete mode 100644 structures/Client.js delete mode 100644 structures/PostgreSQL.js delete mode 100644 util/BotList.js diff --git a/README.md b/README.md index e4ae09c4..f1964e2d 100644 --- a/README.md +++ b/README.md @@ -4,21 +4,20 @@ [![Donate on Patreon](https://img.shields.io/badge/patreon-donate-orange.svg)](https://www.patreon.com/dragonfire535) [![Donate on PayPal](https://img.shields.io/badge/paypal-donate-blue.svg)](https://www.paypal.me/dragonfire535) +> This bot is not available for invite. + Xiao is a Discord bot coded in JavaScript with [discord.js](https://discord.js.org/) using the [Commando](https://github.com/discordjs/Commando) command framework. With nearly 300 commands, she is one of the most feature-filled bots out there. ## Invite -You can invite the bot to your server using -[this link](https://discordapp.com/oauth2/authorize?client_id=278305350804045834&scope=bot&permissions=372632641). -Be sure to also join the [home server](https://discord.gg/sbMe32W) for -information and support. +The bot is no longer available for invite. You can self-host the bot, or use her +on the [home server](https://discord.gg/sbMe32W). -## Commands (296) +## Commands (288) ### Utility: -* **prefix**: Shows or sets the command prefix. * **eval**: Executes JavaScript code. * **changelog**: Responds with Xiao's latest 10 commits. * **donate**: Responds with Xiao's donation links. @@ -26,16 +25,6 @@ information and support. * **info**: Responds with detailed bot information. * **invite**: Responds with Xiao's invite links. * **ping**: Checks the bot's ping to the Discord server. -* **uptime**: Responds with how long the bot has been active. - -### Command Management: - -* **groups**: Lists all command groups. -* **enable**: Enables a command or command group. -* **disable**: Disables a command or command group. -* **reload**: Reloads a command or command group. -* **load**: Loads a new command. -* **unload**: Unloads a command. ### Discord Information: diff --git a/Xiao.js b/Xiao.js index e5189d78..db4a6dd1 100644 --- a/Xiao.js +++ b/Xiao.js @@ -1,7 +1,7 @@ const { XIAO_TOKEN, OWNERS, XIAO_PREFIX, INVITE } = process.env; const path = require('path'); -const XiaoClient = require('./structures/Client'); -const client = new XiaoClient({ +const { CommandoClient } = require('discord.js-commando'); +const client = new CommandoClient({ commandPrefix: XIAO_PREFIX, owner: OWNERS.split(','), invite: INVITE, @@ -9,8 +9,6 @@ const client = new XiaoClient({ unknownCommandResponse: false, disabledEvents: ['TYPING_START'] }); -const { discordBots } = require('./util/BotList'); -const SequelizeProvider = require('./providers/Sequelize'); const activities = require('./assets/json/activity'); client.registry @@ -18,7 +16,6 @@ client.registry .registerTypesIn(path.join(__dirname, 'types')) .registerGroups([ ['util', 'Utility'], - ['commands', 'Command Management'], ['info', 'Discord Information'], ['random', 'Random Response'], ['single', 'Single Response'], @@ -37,19 +34,18 @@ client.registry ]) .registerDefaultCommands({ help: false, - ping: false + ping: false, + prefix: false, + commandState: false }) .registerCommandsIn(path.join(__dirname, 'commands')); -client.setProvider(new SequelizeProvider(client.database)); - client.on('ready', () => { console.log(`[READY] Logged in as ${client.user.tag}! (${client.user.id})`); client.setInterval(() => { const activity = activities[Math.floor(Math.random() * activities.length)]; client.user.setActivity(activity.text, { type: activity.type }); }, 60000); - discordBots(client); }); client.on('disconnect', event => { @@ -57,10 +53,6 @@ client.on('disconnect', event => { process.exit(0); }); -client.on('guildCreate', () => discordBots(client)); - -client.on('guildDelete', () => discordBots(client)); - client.on('commandRun', command => console.log(`[COMMAND] Ran command ${command.groupID}:${command.memberName}.`)); client.on('error', err => console.error('[ERROR]', err)); diff --git a/commands/util/invite.js b/commands/util/invite.js index 9db14212..a050be54 100644 --- a/commands/util/invite.js +++ b/commands/util/invite.js @@ -13,13 +13,9 @@ module.exports = class InviteCommand extends Command { }); } - async run(msg) { - const invite = await this.client.generateInvite(372632641); + run(msg) { return msg.say(stripIndents` - To invite me to your server, use this link: - <${invite}> - - Or, join my home server: + You cannot invite me to your server, but you can join my home server to use me: ${this.client.options.invite || 'Coming soon...'} `); } diff --git a/commands/util/uptime.js b/commands/util/uptime.js deleted file mode 100644 index 72c2f7b5..00000000 --- a/commands/util/uptime.js +++ /dev/null @@ -1,18 +0,0 @@ -const Command = require('../../structures/Command'); -const { duration } = require('../../util/Util'); - -module.exports = class UptimeCommand extends Command { - constructor(client) { - super(client, { - name: 'uptime', - group: 'util', - memberName: 'uptime', - description: 'Responds with how long the bot has been active.', - guarded: true - }); - } - - run(msg) { - return msg.say(duration(this.client.uptime)); - } -}; diff --git a/package.json b/package.json index 46da8c18..884b9219 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "xiao", - "version": "84.6.0", + "version": "85.0.0", "description": "Your personal server companion.", "main": "Xiao.js", "scripts": { @@ -49,7 +49,7 @@ "zlib-sync": "^0.1.4" }, "devDependencies": { - "eslint": "^5.0.1", + "eslint": "^5.1.0", "eslint-config-amber": "^1.0.3", "eslint-plugin-json": "^1.2.0" }, diff --git a/providers/Sequelize.js b/providers/Sequelize.js deleted file mode 100644 index 1811d38d..00000000 --- a/providers/Sequelize.js +++ /dev/null @@ -1,244 +0,0 @@ -// Credit: https://github.com/iCrawl/Tohru/blob/master/src/providers/Sequelize.js - -const { SettingProvider } = require('discord.js-commando'); -const Sequelize = require('sequelize'); - -/** - * Uses an PostgreSQL database to store settings with guilds - * @extends {SettingProvider} - */ -class SequelizeProvider extends SettingProvider { - /** - * @external PostgreSQLDatabase - * @see {@link https://www.npmjs.com/package/sequelize} - */ - - /** - * @param {SQLDatabase} db - Database for the provider - */ - constructor(db) { - super(); - - /** - * Database that will be used for storing/retrieving settings - * @type {SQLDatabase} - */ - this.db = db; - - /** - * Client that the provider is for (set once the client is ready, after using {@link CommandoClient#setProvider}) - * @name SequelizeProvider#client - * @type {CommandoClient} - * @readonly - */ - Object.defineProperty(this, 'client', { value: null, writable: true }); - - /** - * Settings cached in memory, mapped by guild ID (or 'global') - * @type {Map} - * @private - */ - this.settings = new Map(); - - /** - * Listeners on the Client, mapped by the event name - * @type {Map} - * @private - */ - this.listeners = new Map(); - - /** - * Sequelize Model Object - * @type {SequelizeModel} - * @private - */ - this.model = this.db.define('settings', { - guild: { - type: Sequelize.BIGINT, - allowNull: false, - unique: true, - primaryKey: true - }, - settings: { type: Sequelize.TEXT } - }, { freezeTableName: true, timestamps: false }); - - /** - * @external SequelizeModel - * @see {@link http://docs.sequelizejs.com/en/latest/api/model/} - */ - } - - async init(client) { - this.client = client; - await this.db.sync(); - - // Load all settings - const rows = await this.model.findAll(); - for (const row of rows) { - let settings; - try { - settings = JSON.parse(row.dataValues.settings); - } catch (err) { - client.emit('warn', `SequelizeProvider couldn't parse the settings stored for guild ${row.dataValues.guild}.`); - continue; - } - - const guild = row.dataValues.guild !== '0' ? row.dataValues.guild : 'global'; - - this.settings.set(guild, settings); - if (guild !== 'global' && !client.guilds.has(row.dataValues.guild)) continue; - this.setupGuild(guild, settings); - } - - // Listen for changes - this.listeners - .set('commandPrefixChange', (guild, prefix) => this.set(guild, 'prefix', prefix)) - .set('commandStatusChange', (guild, command, enabled) => this.set(guild, `cmd-${command.name}`, enabled)) - .set('groupStatusChange', (guild, group, enabled) => this.set(guild, `grp-${group.id}`, enabled)) - .set('guildCreate', guild => { - const settings = this.settings.get(guild.id); - if (!settings) return; - this.setupGuild(guild.id, settings); - }) - .set('commandRegister', command => { - for (const [guild, settings] of this.settings) { - if (guild !== 'global' && !client.guilds.has(guild)) continue; - this.setupGuildCommand(client.guilds.get(guild), command, settings); - } - }) - .set('groupRegister', group => { - for (const [guild, settings] of this.settings) { - if (guild !== 'global' && !client.guilds.has(guild)) continue; - this.setupGuildGroup(client.guilds.get(guild), group, settings); - } - }); - for (const [event, listener] of this.listeners) client.on(event, listener); - } - - destroy() { - // Remove all listeners from the client - for (const [event, listener] of this.listeners) this.client.removeListener(event, listener); - this.listeners.clear(); - } - - get(guild, key, defVal) { - const settings = this.settings.get(this.constructor.getGuildID(guild)); - return settings ? typeof settings[key] !== 'undefined' ? settings[key] : defVal : defVal; - } - - async set(guild, key, val) { - guild = this.constructor.getGuildID(guild); - let settings = this.settings.get(guild); - if (!settings) { - settings = {}; - this.settings.set(guild, settings); - } - - settings[key] = val; - await this.model.upsert( - { guild: guild !== 'global' ? guild : '0', settings: JSON.stringify(settings) } - ); - if (guild === 'global') this.updateOtherShards(key, val); - return val; - } - - async remove(guild, key) { - guild = this.constructor.getGuildID(guild); - const settings = this.settings.get(guild); - if (!settings || typeof settings[key] === 'undefined') return undefined; - - const val = settings[key]; - settings[key] = undefined; - await this.model.upsert( - { guild: guild !== 'global' ? guild : '0', settings: JSON.stringify(settings) } - ); - if (guild === 'global') this.updateOtherShards(key, undefined); - return val; - } - - async clear(guild) { - guild = this.constructor.getGuildID(guild); - if (!this.settings.has(guild)) return; - this.settings.delete(guild); - await this.model.destroy({ where: { guild: guild !== 'global' ? guild : '0' } }); - } - - /** - * Loads all settings for a guild - * @param {string} guild - Guild ID to load the settings of (or 'global') - * @param {Object} settings - Settings to load - * @private - */ - setupGuild(guild, settings) { - if (typeof guild !== 'string') throw new TypeError('The guild must be a guild ID or "global".'); - guild = this.client.guilds.get(guild) || null; - - // Load the command prefix - if (typeof settings.prefix !== 'undefined') { - if (guild) guild._commandPrefix = settings.prefix; - else this.client._commandPrefix = settings.prefix; - } - - // Load all command/group statuses - for (const command of this.client.registry.commands.values()) this.setupGuildCommand(guild, command, settings); - for (const group of this.client.registry.groups.values()) this.setupGuildGroup(guild, group, settings); - } - - /** - * Sets up a command's status in a guild from the guild's settings - * @param {?Guild} guild - Guild to set the status in - * @param {Command} command - Command to set the status of - * @param {Object} settings - Settings of the guild - * @private - */ - setupGuildCommand(guild, command, settings) { - if (typeof settings[`cmd-${command.name}`] === 'undefined') return; - if (guild) { - if (!guild._commandsEnabled) guild._commandsEnabled = {}; - guild._commandsEnabled[command.name] = settings[`cmd-${command.name}`]; - } else { - command._globalEnabled = settings[`cmd-${command.name}`]; - } - } - - /** - * Sets up a group's status in a guild from the guild's settings - * @param {?Guild} guild - Guild to set the status in - * @param {CommandGroup} group - Group to set the status of - * @param {Object} settings - Settings of the guild - * @private - */ - setupGuildGroup(guild, group, settings) { - if (typeof settings[`grp-${group.id}`] === 'undefined') return; - if (guild) { - if (!guild._groupsEnabled) guild._groupsEnabled = {}; - guild._groupsEnabled[group.id] = settings[`grp-${group.id}`]; - } else { - group._globalEnabled = settings[`grp-${group.id}`]; - } - } - - /** - * Updates a global setting on all other shards if using the {@link ShardingManager}. - * @param {string} key - Key of the setting to update - * @param {*} val - Value of the setting - * @private - */ - updateOtherShards(key, val) { - if (!this.client.shard) return; - key = JSON.stringify(key); - val = typeof val !== 'undefined' ? JSON.stringify(val) : 'undefined'; - this.client.shard.broadcastEval(` - if(this.shard.id !== ${this.client.shard.id} && this.provider && this.provider.settings) { - let global = this.provider.settings.get('global'); - if (!global) { - global = {}; - this.provider.settings.set('global', global) - } - global[${key}] = ${val}; - } - `); - } -} - -module.exports = SequelizeProvider; diff --git a/structures/Client.js b/structures/Client.js deleted file mode 100644 index aa93b8e0..00000000 --- a/structures/Client.js +++ /dev/null @@ -1,13 +0,0 @@ -const { CommandoClient } = require('discord.js-commando'); -const Database = require('../structures/PostgreSQL'); - -class XiaoClient extends CommandoClient { - constructor(options) { - super(options); - this.database = Database.db; - - Database.start(); - } -} - -module.exports = XiaoClient; diff --git a/structures/PostgreSQL.js b/structures/PostgreSQL.js deleted file mode 100644 index ce89e8fa..00000000 --- a/structures/PostgreSQL.js +++ /dev/null @@ -1,23 +0,0 @@ -const Sequelize = require('sequelize'); -const { DB_URL } = process.env; -const db = new Sequelize(DB_URL, { logging: false, operatorsAliases: false }); - -class PostgreSQL { - static get db() { - return db; - } - - static async start() { - try { - await db.authenticate(); - console.log('[DATABASE] Connection established! Syncing...'); - await db.sync(); - console.log('[DATABASE] Database sync complete!'); - } catch (err) { - console.error('[DATABASE] Unable to connect to database:', err); - setTimeout(() => PostgreSQL.start(), 5000); - } - } -} - -module.exports = PostgreSQL; diff --git a/util/BotList.js b/util/BotList.js deleted file mode 100644 index 8e38cc7f..00000000 --- a/util/BotList.js +++ /dev/null @@ -1,20 +0,0 @@ -const request = require('node-superfetch'); -const { DISCORD_BOTS_TOKEN } = process.env; - -class BotListUtil { - static async discordBots(client) { - try { - const { body } = await request - .post(`https://bots.discord.pw/api/bots/${client.user.id}/stats`) - .set({ Authorization: DISCORD_BOTS_TOKEN }) - .send({ server_count: client.guilds.size }); - console.log('[DISCORD BOTS] Posted to Discord Bots.'); - return body; - } catch (err) { - console.error('[DISCORD BOTS] Failed to post to Discord Bots.', err); - return err; - } - } -} - -module.exports = BotListUtil;