Created
April 16, 2018 06:46
-
-
Save xkisu/f0490a8e6e10a35a8cede4d956feba73 to your computer and use it in GitHub Desktop.
MongoProvider for discord.js Commando
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/src/providers/base') | |
const mongoose = require('mongoose') | |
const Settings = mongoose.model('Setting', new mongoose.Schema({ | |
guild: { | |
type: String, | |
required: true, | |
unique: true, | |
index: true | |
}, | |
settings: { | |
type: Object, | |
default: {} | |
} | |
})) | |
/** | |
* Uses a Mongo database to store settings with guilds | |
* @extends {SettingProvider} | |
*/ | |
class MongoProvider extends SettingProvider { | |
/** | |
* @param {String} url - Mongodb URL | |
*/ | |
constructor (url) { | |
super() | |
/** | |
* Database url that will be used by mongoose | |
* @type {String} | |
*/ | |
this.url = url | |
/** | |
* Client that the provider is for (set once the client is ready, after using {@link CommandoClient#setProvider}) | |
* @name MongoProvider#client | |
* @type {CommandoClient} | |
* @readonly | |
*/ | |
Object.defineProperty(this, 'client', { value: null, writable: true }) | |
/** | |
* Listeners on the Client, mapped by the event name | |
* @type {Map} | |
* @private | |
*/ | |
this.listeners = new Map() | |
} | |
async init(client) { | |
this.client = client | |
console.log('init') | |
const settings = await Settings.find({}).exec() | |
console.log(settings) | |
console.log(client.guilds) | |
for(let i = 0; i < settings.length; ++i) { | |
const guildid = settings[i].guild | |
const guildSettings = settings[i].settings || {} | |
console.log(`${guildid} !== 'global' = ` + (guildid !== 'global')) | |
console.log(`!client.guilds.has(${guildid}) = ` + (!client.guilds.has(''+guildid))) | |
if(guildid !== 'global' && !client.guilds.has(''+guildid)) continue | |
console.log('setting up guild ' + guildid) | |
console.log(guildSettings) | |
this.setupGuild(guildid, guildSettings) | |
} | |
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', async (guild) => { | |
const settingsDocument = await Settings.findOne({ guild: guild }).exec() | |
if(!settingsDocument) return | |
this.setupGuild(guild.id, settingsDocument.settings) | |
}) | |
.set('commandRegister', async (command) => { | |
const settings = await Settings.find({}).exec() | |
for(let i = 0; i < settings.length; ++i) { | |
const guild = settings[i].guild | |
const guildSettings = settings[i].settings || {} | |
if(guild !== 'global' && !client.guilds.has(guild)) continue | |
this.setupGuildCommand(client.guilds.get(guild), command, guildSettings) | |
} | |
}) | |
.set('groupRegister', async (group) => { | |
const settings = await Settings.find({}).exec() | |
for(let i = 0; i < settings.length; ++i) { | |
const guild = settings[i].guild | |
const guildSettings = settings[i].settings || {} | |
if(guild !== 'global' && !client.guilds.has(guild)) continue; | |
this.setupGuildGroup(client.guilds.get(guild), group, guildSettings) | |
} | |
}) | |
for(const [event, listener] of this.listeners) client.on(event, listener) | |
} | |
destroy () { | |
for(const [event, listener] of this.listeners) this.client.removeListener(event, listener); | |
this.listeners.clear() | |
} | |
async get (guild, key, defaultVal) { | |
const guildid = this.constructor.getGuildID(guild) | |
const settingsDocument = await Settings.findOne({ guild: guildid }).exec() | |
if(!settingsDocument.settings) | |
settingsDocument.settings = {} | |
return settingsDocument ? typeof settingsDocument.settings[key] !== 'undefined' ? settingsDocument.settings[key] : defVal : defVal | |
} | |
async set (guild, key, val) { | |
console.log(`${guild} ${key} ${val}`) | |
const guildid = this.constructor.getGuildID(guild) | |
const settingsDocument = await this.getOrCreateGuild(guildid) | |
if(settingsDocument.settings == undefined) | |
settingsDocument.settings = {} | |
settingsDocument.set('settings.'+key, val) | |
await settingsDocument.save() | |
console.log(settingsDocument) | |
if(guildid === 'global') this.updateOtherShards(key, val) | |
return val | |
} | |
async remove (guild, key) { | |
const guildid = this.constructor.getGuildID(guild) | |
const settingsDocument = await Settings.findOne({ guild: guildid }).exec() | |
if(!settingsDocument || typeof settingsDocument.settings[key] === 'undefined') return undefined | |
const val = settingsDocument[key] | |
settingsDocument[key] = undefined | |
await settingsDocument.save() | |
if(guildid === 'global') this.updateOtherShards(key, undefined) | |
return val | |
} | |
async clear (guild) { | |
const guildid = this.constructor.getGuildID(guild) | |
const settingsDocument = await Settings.findOne({ guild: guildid }).exec() | |
if(!settingsDocument) return | |
await settingsDocument.remove() | |
} | |
async getOrCreateGuild (guildid) { | |
const settingsDocument = await Settings.findOne({ guild: guildid }).exec() | |
if(!settingsDocument) { | |
const guildSettings = new Settings() | |
guildSettings.guild = guildid | |
guildSettings.settings = {} | |
await guildSettings.save() | |
return guildSettings | |
} else { | |
return settingsDocument | |
} | |
} | |
/** | |
* 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 {?CommandoGuild} 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 command group's status in a guild from the guild's settings | |
* @param {?CommandoGuild} 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 = MongoProvider |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This assumes that you have made the mongoose connection before initializing Commando and creating the provider