Verified Commit 66bbbca6 authored by recette lemonweed's avatar recette lemonweed 🇮🇸

redid config system, added aliases

parent bcc232b9
module.exports = {
name: "Config",
triggers: ["config"],
description: "Sets server variables.",
description: "Sets settings for servers and users.",
category: "moderation",
arguments: {
positional: ["key", "values to set"],
flags: {
keys: [false, "k"],
view: [false, "v"]
user: [false, "u"],
remove: [false, "r"],
}
},
func: func
};
var keys = [
"muterole",
"disabledcommands"
];
function assignMuteRole(id, message, args, str){
let role = message.guild.roles.get(str);
if(!role){
str = str.toLowerCase();
role = message.guild.roles.find(role => {
return role.name.toLowerCase() === str;
});
}
if(!role)
return message.reply("Role not found.");
Configs.get(id).set("muterole", role.id);
Configs.get(id).get("raw").set(args.setting, str);
message.reply("Set "+role.name+" as mute role.");
}
function func(message, args){
if(args.keys)
return message.reply(keys.join(", "));
function assignDisabledCommands(id, message, args, str){
let incommands = str.split(",").map(a=>a.trim().toLowerCase());
let commands = new Set();
for(let ic of incommands){
for(let trigger in Commands){
let command = Commands[trigger];
if(ic === trigger || ic === command.name.toLowerCase())
commands.add(command.name);
}
}
if(commands.has(module.exports.name))
return message.reply("You're not allowed to brick this command.");
commands = Array.from(commands);
if(!commands.length)
return message.reply("No command found.");
Configs.get(id).set("disabledcommands", commands);
Configs.get(id).get("raw").set(args.setting, str);
message.reply("Disabled "+commands.join(", ")+".");
}
if(!message.member.permissions.has("MANAGE_GUILD"))
return message.reply("You don't have manage guild perms.");
function assignAliases(id, message, args){
let inaliases = message.content.split("\n").slice(1).map(a=>a.trim());
let aliases = {};
if(!inaliases.length)
return message.reply("Need some aliases.");
for(let alias of inaliases){
let [trigger, command] = alias.split("=");
if(!(trigger && command))
return message.reply("Syntax is:\n```??config --aliases\nsaynice=say nice\nddg=g --ddg```");
if(trigger.match(/[^\w]/))
return message.reply("Triggers need to be regular characters.");
trigger = trigger.toLowerCase();
command = command.replace(/\\(?=-)/, "").split(" ");
if(trigger === module.exports.name)
return message.reply("You're not allowed to brick this command.");
aliases[trigger] = command;
}
Configs.get(id).set("aliases", aliases);
Configs.get(id).get("raw").set(args.setting, "\n"+inaliases.join("\n"));
message.reply("Set "+(Object.keys(aliases).length)+" aliases.");
}
let key = args._[0];
let values = args._.length < 3 ? args._[1] : args._.slice(1);
let settings = {
muterole: {
assign: assignMuteRole,
server: true,
user: false,
flag: [false, "mr"]
},
disabledcommands: {
assign: assignDisabledCommands,
server: true,
user: false,
flag: [false, "dc"]
},
aliases: {
assign: assignAliases,
server: true,
user: true,
flag: [false, "alias", "al"]
}
};
key = key.toLowerCase();
module.exports.arguments.flags.setting = Object.fromEntries(
Object.entries(settings).map(e => [e[0], e[1].flag])
);
if(keys.indexOf(key) === -1)
return message.reply("That's not a valid key. Use --keys for a list.");
function func(message, args){
let setting = settings[args.setting];
if(!setting)
return message.reply("Key not found. --help for a list.");
if(args.view)
return message.reply(guildConfigs[message.guild.id][key] || "Not defined.");
// check that user/server is allowed
if((!setting.user && args.user))
return message.reply("This setting isnt settable for users.");
if((!setting.server && !args.user))
return message.reply("This setting isnt settable for servers.");
if(key === "disabledcommands" && values && (typeof(values) === "object" ? values.map((v)=>{return v.toLowerCase()}) : values.toLowerCase()).includes("config"))
return message.reply("Nah, I'm too mommy to let you brick this command. :)");
// check permissions for servers
if(!message.member.permissions.has("MANAGE_GUILD") && setting.server)
return message.reply("You don't have manage guild perms.");
if(!values)
delete guildConfigs[message.guild.id][key];
// get user/server id
let id;
if(args.user || !message.guild)
id = message.author.id;
else
guildConfigs[message.guild.id][key] = values;
message.reply("Set.");
id = message.guild.id;
let config = Configs.get(id);
// remove if it exists and remove flag
if(args.remove){
if(config.exists(args.setting)){
config.delete(args.setting);
config.get("raw").delete(args.setting);
return message.reply("Removed.");
} else {
return message.reply("Not set.");
}
}
// if nothing is given, reply with current setting.
let str = args._.join(" ");
if(!str && !message.content.includes("\n")){
let out = config.get("raw").exists(args.setting) ? config.get("raw").get(args.setting) : "Nothing set.";
return message.reply(out);
}
setting.assign(id, message, args, str);
}
......@@ -28,35 +28,39 @@ function parseTime(str){
function unmute(user, role, mutes){
user.removeRole(role).catch();
delete mutes[user.id];
mutes.delete(user.id);
}
function func(message, args){
// check permissions
if(!message.member.permissions.has("MANAGE_ROLES"))
return message.reply("You don't have manage role perms.");
if(!guildConfigs[message.guild.id].muterole)
// check mute role exists
if(!Configs.get(message.guild.id).get("muterole"))
return message.reply("Mute role not set. Use the config command.");
let user = message.mentions.members.first(),
time = args._[0] ? Utility.clamp(parseTime((args._[0][0] === "<" ? args._[1]:args._[0]) || 600), 604800, 0) : null,
roleP = guildConfigs[message.guild.id].muterole,
role = message.guild.roles.get(roleP) || message.guild.roles.find((r) => r.name.toLowerCase() === (Array.isArray(roleP)?roleP.join(" "):roleP).toLowerCase());
// set up vars
let guildConfig = Configs.get(message.guild.id);
let user = message.mentions.members.first();
let time = args._[0] ? Utility.clamp(parseTime((args._[0][0] === "<" ? args._[1]:args._[0]) || 600), 604800, 0) : null;
let role = message.guild.roles.get(guildConfig.get("muterole"));
// remaining output block
if(args.remaining){
let users;
if(user){
users = [user.id];
if(!guildConfigs[message.guild.id].mutes[user.id])
if(!guildConfig.get("mutes").get(user.id))
return message.reply("Not muted.");
} else {
users = Object.keys(guildConfigs[message.guild.id].mutes);
users = Object.keys(guildConfig.get("mutes"));
}
let out = users.map(u => {
let user = Bot.users.get(u);
if(!user) return;
let mute = guildConfigs[message.guild.id].mutes[u];
let mute = guildConfig.get("mutes").get(u);
let r = mute.time - Math.round(((new Date()).getTime() - mute.start) / 1000);
return user.tag + ": " + Utility.toHHMMSS(r) + " of " + Utility.toHHMMSS(mute.time);
}).join("\n");
......@@ -67,27 +71,31 @@ function func(message, args){
return message.reply(out);
}
// check role and user exist
if(!(user && role))
return message.reply("Need a mention and length, in that order, and a valid role id/name set.");
// check heirarchy
if(user.highestRole.comparePositionTo(message.member.highestRole) >= 0)
return message.reply("You arent higher than them in the role list.");
if(args.unmute){
unmute(user, role, guildConfigs[message.guild.id].mutes);
unmute(user, role, guildConfig.get("mutes"));
return message.reply("User unmuted.");
}
guildConfigs[message.guild.id].mutes[user.id] = {
// save mute in config
guildConfig.get("mutes").set(user.id, {
time,
start: (new Date()).getTime(),
role: role.id
};
});
// mute and set up timeout
user.addRole(role).then(() => {
message.reply("User muted for " + Utility.toHHMMSS(time));
setTimeout(() => {
unmute(user, role, guildConfigs[message.guild.id].mutes);
unmute(user, role, guildConfig.get("mutes"));
}, time * 1000);
}).catch(() => {
message.reply("Failed to add role. Probably don't have perms.");
......
module.exports = {
name: "Say",
triggers: ["say"],
triggers: ["say", "echo"],
description: "Says things you give it.",
category: "general",
arguments: {
......
let Minimist = require("minimist");
module.exports.parseMessage = function(message){
if(!message.content.startsWith(Config.trigger) || message.author.bot)
return;
let [args, cmd, command] = parseArguments(message.content);
let [args, cmd, command] = parseArguments(message);
if(!cmd)
return;
if(args.h || args.help){
return message.reply({embed: Utility.getHelpEmbed(cmd)});
}
if(args.h || args.help)
return message.reply({embed: getHelpEmbed(cmd)});
if(cmd.category === "owner" && message.author.id != Config.ownerId)
return;
if(message.guild && guildConfigs[message.guild.id].disabledcommands && guildConfigs[message.guild.id].disabledcommands.includes(cmd.name.toLowerCase()) && cmd.category !== "owner")
if(message.guild && Configs.get(message.guild.id).exists("disabledcommands") && Configs.get(message.guild.id).get("disabledcommands").indexOf(cmd.name) !== -1)
return;
try{
cmd.func(message, args, command);
} catch(err){
console.error(command, args, err);
message.reply({embed: Utility.errorEmbed});
console.log(args, err);
message.reply({embed: errorEmbed});
}
};
......@@ -31,12 +32,23 @@ function parseArg(arg, a, opts){
opts.default[a] = arg[0];
}
function parseArguments(content){
let args = content.split(" ");
function parseArguments(message){
let args = message.content.split(" ");
if(!args.length)
return [null,null,null];
let command = args.shift().slice(Config.trigger.length).toLowerCase();
args[0] = args[0].slice(Config.trigger.length);
if(Configs.get(message.author.id).get("aliases").exists(args[0])){
let userAlias = Configs.get(message.author.id).get("aliases").get(args[0]);
args = userAlias.concat(args.slice(1));
} else
if(message.guild && Configs.get(message.guild.id).get("aliases").exists(args[0])){
let guildAlias = Configs.get(message.guild.id).get("aliases").get(args[0]);
args = guildAlias.concat(args.slice(1));
}
let command = args.shift().toLowerCase();
let cmd = Commands[command];
if(!cmd)
......@@ -63,7 +75,7 @@ function parseArguments(content){
}
}
args = require("minimist")(args, opts);
args = Minimist(args, opts);
for(let pool in pools){
for(let arg in pools[pool]){
......@@ -77,15 +89,15 @@ function parseArguments(content){
}
return [args, cmd, command];
};
}
function getFlagString(arg, k){
return [k].concat(arg.slice(1)).sort((a,b)=>{
return b.length-a.length;
}).map(a => (a.length === 1 ? ("-"+a) : ("--"+a))).join(" ");
}).map(a => (a.length === 1 ? ("-"+a) : ("--"+a))).sort((a,b)=>a.length-b.length).join(" ");
}
module.exports.getHelpEmbed = function(cmd){
function getHelpEmbed(cmd){
let embed = new Discord.RichEmbed({
title: cmd.name+" ["+cmd.category+"]",
description: cmd.description,
......@@ -93,7 +105,6 @@ module.exports.getHelpEmbed = function(cmd){
});
embed.addField(Config.trigger+"Triggers", cmd.triggers.sort().join(", "), true);
if(cmd.arguments.positional)
embed.addField("Arguments", cmd.arguments.positional.sort().join(" | "), true);
if(cmd.arguments.flags){
......@@ -108,11 +119,11 @@ module.exports.getHelpEmbed = function(cmd){
}
return embed;
};
}
module.exports.errorEmbed = new Discord.RichEmbed({
let errorEmbed = new Discord.RichEmbed({
title: "Whoops, got an error...",
description: "Either you did the inputs wrong, or its just a feature.",
description: "Either you did the inputs wrong, or its just a feature.\nTry appending --help for help.",
color: Config.embedColour,
thumbnail: {
url: "https://i.imgur.com/GuIhCoQ.png"
......
let Fs = require("fs");
function saveGuildProperties(id, obj){
DB.run("REPLACE INTO config (guild, config) VALUES (?, ?)", id, JSON.stringify(obj));
}
function guildConfigProxyListener(gobj, id){
return {
set: function(obj, prop, value){
obj[prop] = value;
saveGuildProperties(id, gobj);
},
deleteProperty: function(obj, prop){
delete obj[prop];
saveGuildProperties(id, gobj);
return true;
}
};
}
function unmute(guild, user, role){
guild = Bot.guilds.get(guild);
if(!guild)
......@@ -31,67 +13,142 @@ function unmute(guild, user, role){
user.removeRole(role);
}
function guildConfigProxy(gobj, id){
gobj.mutes = new Proxy(gobj.mutes||{}, guildConfigProxyListener(gobj, id));
return new Proxy(gobj, guildConfigProxyListener(gobj, id));
}
let checkUserMute = module.exports.checkUserMute = function(mute, guildId, userId){
let checkUserMute = module.exports.checkUserMute = function(guildId, userId){
let mute = Configs.get(guildId).get("mutes").get(userId);
if(!mute.start)
return;
let member = Bot.guilds.get(guildId).members.get(userId),
timeSince = ((new Date()).getTime() - mute.start) / 1000;
if(timeSince >= mute.time){
unmute(guildId, userId, mute.role);
delete guildConfigs[guildId].mutes[userId];
Configs.get(guildId).get("mutes").delete(userId);
return;
}
if(!member.roles.has(mute.role))
member.addRole(mute.role).catch();
console.log("unmuting", member.user.username, "in", (mute.time - timeSince));
setTimeout(() => {
unmute(guildId, userId, mute.role);
delete guildConfigs[guildId].mutes[userId];
Configs.get(guildId).get("mutes").delete(userId);
}, (mute.time - timeSince) * 1000);
};
function initGuildConfig(){
guildConfigs = new Proxy({}, {
get: function(obj, prop){
if(!obj[prop])
obj[prop] = guildConfigProxy({}, prop);
return obj[prop];
module.exports.checkMutes = function(){
console.log("Checking mutes.");
for(let g in Configs){
for(let u in Configs.get(g).get("mutes")){
checkUserMute(g, u);
}
});
}
};
function saveConfigProperties(id, obj){
DB.run("REPLACE INTO config (id, config) VALUES (?, ?)", id, JSON.stringify(obj));
}
DB.all("SELECT * FROM config").then((res) => {
for(let r of res){
let g = guildConfigs[r.guild] = guildConfigProxy(JSON.parse(r.config), r.guild);
for(let u of Object.keys(g.mutes)){
checkUserMute(g.mutes[u], r.guild, u);
}
class Config{
get(id){
if(!this[id]){
this[id] = new ConfigProperty(this);
}
});
return this[id];
}
set(prop, val){
if(typeof(val) === "object" && !Array.isArray(val))
val = Object.assign(new ConfigProperty(this), val);
this[prop] = val;
this._save();
}
exists(prop){
return this[prop] !== undefined;
}
delete(prop){
delete this[prop];
this._save();
}
_save(){
saveConfigProperties(this._id, this);
}
}
function createBlankDB(){
DB.run('CREATE TABLE "compass" ("id" TEXT, "x" INTEGER,"y" INTEGER, PRIMARY KEY("id"))').then(() => {
DB.run('CREATE TABLE "headpats" ("id" TEXT, "pats" INTEGER, "last" INTEGER, PRIMARY KEY("id"))').then(() => {
DB.run('CREATE TABLE "config" ("guild" TEXT NOT NULL UNIQUE, "config" TEXT NOT NULL, PRIMARY KEY("guild"))').then(initGuildConfig);
class ConfigProperty extends Config{
constructor(parent){
super();
Object.defineProperty(this, "_parent", {
enumerable: false,
value: parent
});
Object.defineProperty(this, "_id", {
enumerable: false,
value: this._parent._id
});
}
_save(){
this._parent._save();
}
}
class ConfigsContainer{
get(id){
if(!this[id]){
this[id] = new Config();
Object.defineProperty(this[id], "_id", {
enumerable: false,
value: id
});
}
return this[id];
}
}
function recurApplyConfigProp(parent){
for(let key in parent){
let child = parent[key];
if(typeof(child) === "object" && !Array.isArray(child) && child){
parent[key] = Object.assign(new ConfigProperty(parent), child);
recurApplyConfigProp(child);
}
}
}
function initConfig(){
console.log("Loading up configs.");
DB.all("SELECT * FROM config").then((results) => {
for(let result of results){
Configs[result.id] = new Config(result.id);
Object.defineProperty(Configs[result.id], "_id", {
enumerable: false,
value: result.id
});
Object.assign(Configs[result.id], JSON.parse(result.config));
recurApplyConfigProp(Configs[result.id]);
}
});
}
module.exports.initDB = function(){
function createBlankDB(){
console.log("Creating blank DB.");
let tables = [
'CREATE TABLE "compass" ("id" TEXT, "x" INTEGER,"y" INTEGER, PRIMARY KEY("id"))',
'CREATE TABLE "headpats" ("id" TEXT, "pats" INTEGER, "last" INTEGER, PRIMARY KEY("id"))',
'CREATE TABLE "config" ("id" TEXT NOT NULL UNIQUE, "config" TEXT NOT NULL, PRIMARY KEY("id"))'
];
for(var i = 0; i < tables.length; i++){
tables[i] = DB.run(tables[i]);
}
}
function initDB(){
console.log("Setting up DB.");
if(!Fs.existsSync("./ika-db.sqlite"))
var init = true;
require("sqlite").open("./ika-db.sqlite").then((m) => {
DB = m;
if(init){
global.DB = m;
global.Configs = new ConfigsContainer();
if(init)
return createBlankDB();
}
initGuildConfig();
initConfig();
});
};
}
initDB();
......@@ -6,6 +6,7 @@ function loadUtility(){
if(file == "index.js")
continue;
delete require.cache[require.resolve("./"+file)];
Object.assign(functions, require("./"+file));
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment