Created
January 4, 2017 05:12
-
-
Save appellation/b9c8d54209affc0e5d0fb43dcfabf156 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const {SettingProvider} = require('discord.js-commando'); | |
const bluebird = require('bluebird'); | |
const redis = require('redis'); | |
const erlpack = require('erlpack'); | |
const mergeOptions = require('merge-options'); | |
bluebird.promisifyAll(redis.RedisClient.prototype); | |
bluebird.promisifyAll(redis.Multi.prototype); | |
module.exports = class RedisProvider extends SettingProvider { | |
constructor(options = {}) { | |
super(); | |
this.options = mergeOptions(options, { | |
return_buffers: true | |
}); | |
this.listeners = new Map(); | |
} | |
async init(client) { | |
this.client = client; | |
this.db = redis.createClient(this.options); | |
const finished = new Promise((resolve, reject) => { | |
this.db.once('ready', resolve); | |
this.db.once('error', reject); | |
}); | |
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.name}`, enabled)) | |
.set('guildCreate', async guild => { | |
const settings = await this.getAll(guild); | |
if(!settings) return; | |
this.setupGuild(guild.id, settings); | |
}); | |
for(const [event, listener] of this.listeners) this.client.on(event, listener); | |
for(const [, guild] of this.client.guilds) this.setupGuild(guild.id, await this.getAll(guild)) | |
return finished; | |
} | |
async get(guild, key) { | |
try { | |
return erlpack.unpack(await this.db.hgetAsync(`settings:${SettingProvider.getGuildID(guild)}`, key)); | |
} catch (e) { | |
return null; | |
} | |
} | |
async getAll(guild) { | |
return new Promise((resolve, reject) => { | |
this.db.hgetall(`settings:${SettingProvider.getGuildID(guild)}`, (err, res) => { | |
if(err) return reject(err); | |
if(res === null) return resolve({}); | |
const out = {}; | |
for(const key of Object.keys(res)) { | |
out[key] = erlpack.unpack(res[key]); | |
} | |
return resolve(out); | |
}); | |
}); | |
} | |
async set(guild, key, value) { | |
return this.db.hsetAsync(`settings:${SettingProvider.getGuildID(guild)}`, key, erlpack.pack(value)); | |
} | |
async remove(guild, key) { | |
return this.db.hdelAsync(`settings:${SettingProvider.getGuildID(guild)}`, key); | |
} | |
async clear(guild) { | |
return this.db.delAsync(`settings:${SettingProvider.getGuildID(guild)}`); | |
} | |
async incr(guild, key, count = 1) { | |
return this.db.hincrbyAsync(`settings:${SettingProvider.getGuildID(guild)}`, key, count); | |
} | |
async decr(guild, key, count = 1) { | |
return this.db.hdecrbyAsync(`settings:${SettingProvider.getGuildID(guild)}`, key, count); | |
} | |
async keys(guild) { | |
return this.db.hkeysAsync(`settings:${SettingProvider.getGuildID(guild)}`); | |
} | |
async vals(guild) { | |
const vals = await this.db.hvalsAsync(`settings:${SettingProvider.getGuildID(guild)}`); | |
return vals.map(v => erlpack.unpack(v)); | |
} | |
async exists(guild, key) { | |
return this.db.hexistsAsync(`settings:${SettingProvider.getGuildID(guild)}`, key); | |
} | |
async addWarn(guild, user) { | |
return this.incr(guild, `warns:${user.id}`); | |
} | |
async removeWarn(guild, user) { | |
return this.decr(guild, `warns:${user.id}`); | |
} | |
destroy() { | |
for(const [event, listener] of this.listeners) this.client.removeListener(event, listener); | |
this.listeners.clear(); | |
this.client.quit(); | |
} | |
/** | |
* 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.name}`] === 'undefined') return; | |
if(guild) { | |
if(!guild._groupsEnabled) guild._groupsEnabled = {}; | |
guild._groupsEnabled[group.name] = settings[`grp:${group.name}`]; | |
} else { | |
group._globalEnabled = settings[`grp:${group.name}`]; | |
} | |
} | |
/** | |
* 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) { | |
this.provider.settings.global[${key}] = ${val}; | |
} | |
`); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment