Added support for using both MongoDB and PostgreSQL, changed image api timeouts, removed all moderation commands

This commit is contained in:
TheEssem 2020-12-17 20:32:19 -06:00
parent 69d8100f23
commit ef945adf09
21 changed files with 683 additions and 371 deletions

View file

@ -7,8 +7,12 @@ NODE_ENV=development
# Put Discord token here # Put Discord token here
TOKEN= TOKEN=
# Put database type here
DB=mongo
# Put MongoDB database URL here # Put MongoDB database URL here
MONGO=mongodb://localhost:27017/esmBot MONGO=mongodb://localhost:27017/esmBot
# Put snowflake ID of bot owner here # Put snowflake ID of bot owner here
OWNER= OWNER=

8
app.js
View file

@ -59,9 +59,15 @@ async function init() {
handler.unload(command); handler.unload(command);
} }
client.disconnect(); client.disconnect();
require("./utils/database.js").connection.close(() => { const db = require("./utils/database.js");
if (process.env.DB === "mongo") {
db.connection.close(() => {
process.exit(0); process.exit(0);
}); });
} else if (process.env.DB === "postgres") {
db.connection.end();
process.exit(0);
}
}); });
} }

View file

@ -1,31 +0,0 @@
const client = require("../utils/client.js");
exports.run = async (message, args) => {
if (!message.channel.guild) return `${message.author.mention}, this command only works in servers!`;
if (!message.member.permission.has("banMembers")) return `${message.author.mention}, you need to have the \`Ban Members\` permission on this server to ban people!`;
if (!message.channel.guild.members.get(client.user.id).permission.has("banMembers") && !message.channel.permissionsOf(client.user.id).has("banMembers")) return `${message.author.mention}, I don't have the \`Ban Members\` permission!`;
const member = message.mentions[0];
if (member) {
try {
await message.channel.guild.banMember(member.id, 0, `Ban command used by @${message.author.username}#${message.author.discriminator}`);
return `Successfully banned ${member.mention}.`;
} catch (e) {
return `${message.author.mention}, I was unable to ban the member. They might not exist or I don't have the permissions to do so.`;
}
} else if (args[0].match(/^<?[@#]?[&!]?\d+>?$/) && args[0] >= 21154535154122752) {
try {
const id = args[0].replace(/@/g, "").replace(/#/g, "").replace(/!/g, "").replace(/&/g, "").replace(/</g, "").replace(/>/g, "");
await message.channel.guild.banMember(id, 0, `Banned by ID, command used by @${message.author.username}#${message.author.discriminator}`);
return `Successfully banned user with ID \`${id}\`.`;
} catch (e) {
return `${message.author.mention}, I was unable to ban the member. They might not exist or I don't have the permissions to do so.`;
}
} else {
return `${message.author.mention}, you need to provide a member to ban!`;
}
};
exports.aliases = ["hackban", "prevent", "preban"];
exports.category = 2;
exports.help = "Bans a server member";
exports.params = "[mention/id]";

View file

@ -5,28 +5,34 @@ exports.run = async (message, args) => {
if (!message.member.permission.has("administrator") && message.member.id !== process.env.OWNER) return `${message.author.mention}, you need to be an administrator to enable/disable me!`; if (!message.member.permission.has("administrator") && message.member.id !== process.env.OWNER) return `${message.author.mention}, you need to be an administrator to enable/disable me!`;
if (args.length === 0) return `${message.author.mention}, you need to provide whether I should be enabled or disabled in this channel!`; if (args.length === 0) return `${message.author.mention}, you need to provide whether I should be enabled or disabled in this channel!`;
if (args[0] !== "disable" && args[0] !== "enable") return `${message.author.mention}, that's not a valid option!`; if (args[0] !== "disable" && args[0] !== "enable") return `${message.author.mention}, that's not a valid option!`;
const guildDB = await db.guilds.findOne({id: message.channel.guild.id});
const guildDB = await db.getGuild(message.channel.guild.id);
if (args[0].toLowerCase() === "disable") { if (args[0].toLowerCase() === "disable") {
let channel;
if (args[1] && args[1].match(/^<?[@#]?[&!]?\d+>?$/) && args[1] >= 21154535154122752) { if (args[1] && args[1].match(/^<?[@#]?[&!]?\d+>?$/) && args[1] >= 21154535154122752) {
const id = args[1].replace(/@/g, "").replace(/#/g, "").replace(/!/g, "").replace(/&/g, "").replace(/</g, "").replace(/>/g, ""); const id = args[1].replace(/@/g, "").replace(/#/g, "").replace(/!/g, "").replace(/&/g, "").replace(/</g, "").replace(/>/g, "");
if (guildDB.disabledChannels.includes(id)) return `${message.author.mention}, I'm already disabled in this channel!`; if (guildDB.disabled.includes(id)) return `${message.author.mention}, I'm already disabled in this channel!`;
guildDB.disabledChannels.push(id); channel = message.channel.guild.channels.get(id);
} else { } else {
if (guildDB.disabledChannels.includes(message.channel.id)) return `${message.author.mention}, I'm already disabled in this channel!`; if (guildDB.disabled.includes(message.channel.id)) return `${message.author.mention}, I'm already disabled in this channel!`;
guildDB.disabledChannels.push(message.channel.id); channel = message.channel;
} }
await guildDB.save();
await db.disableChannel(channel);
return `${message.author.mention}, I have been disabled in this channel. To re-enable me, just run \`${guildDB.prefix}channel enable\`.`; return `${message.author.mention}, I have been disabled in this channel. To re-enable me, just run \`${guildDB.prefix}channel enable\`.`;
} else if (args[0].toLowerCase() === "enable") { } else if (args[0].toLowerCase() === "enable") {
let channel;
if (args[1] && args[1].match(/^<?[@#]?[&!]?\d+>?$/) && args[1] >= 21154535154122752) { if (args[1] && args[1].match(/^<?[@#]?[&!]?\d+>?$/) && args[1] >= 21154535154122752) {
const id = args[1].replace(/@/g, "").replace(/#/g, "").replace(/!/g, "").replace(/&/g, "").replace(/</g, "").replace(/>/g, ""); const id = args[1].replace(/@/g, "").replace(/#/g, "").replace(/!/g, "").replace(/&/g, "").replace(/</g, "").replace(/>/g, "");
if (!guildDB.disabledChannels.includes(id)) return `${message.author.mention}, I'm not disabled in that channel!`; if (!guildDB.disabled.includes(id)) return `${message.author.mention}, I'm not disabled in that channel!`;
guildDB.disabledChannels = guildDB.disabledChannels.filter(item => item !== id); channel = message.channel.guild.channels.get(id);
} else { } else {
if (!guildDB.disabledChannels.includes(message.channel.id)) return `${message.author.mention}, I'm not disabled in this channel!`; if (!guildDB.disabled.includes(message.channel.id)) return `${message.author.mention}, I'm not disabled in this channel!`;
guildDB.disabledChannels = guildDB.disabledChannels.filter(item => item !== message.channel.id ); channel = message.channel;
} }
await guildDB.save();
await db.enableChannel(channel);
return `${message.author.mention}, I have been re-enabled in this channel.`; return `${message.author.mention}, I have been re-enabled in this channel.`;
} }
}; };

View file

@ -5,9 +5,9 @@ const database = require("../utils/database.js");
exports.run = async (message) => { exports.run = async (message) => {
if (message.channel.guild && !message.channel.guild.members.get(client.user.id).permission.has("addReactions") && !message.channel.permissionsOf(client.user.id).has("addReactions")) return `${message.author.mention}, I don't have the \`Add Reactions\` permission!`; if (message.channel.guild && !message.channel.guild.members.get(client.user.id).permission.has("addReactions") && !message.channel.permissionsOf(client.user.id).has("addReactions")) return `${message.author.mention}, I don't have the \`Add Reactions\` permission!`;
if (message.channel.guild && !message.channel.guild.members.get(client.user.id).permission.has("embedLinks") && !message.channel.permissionsOf(client.user.id).has("embedLinks")) return `${message.author.mention}, I don't have the \`Embed Links\` permission!`; if (message.channel.guild && !message.channel.guild.members.get(client.user.id).permission.has("embedLinks") && !message.channel.permissionsOf(client.user.id).has("embedLinks")) return `${message.author.mention}, I don't have the \`Embed Links\` permission!`;
const counts = (await database.global.findOne({})).cmdCounts; const counts = await database.getCounts();
const countArray = []; const countArray = [];
const sortedValues = [...counts.entries()].sort((a, b) => { const sortedValues = counts.sort((a, b) => {
return b[1] - a[1]; return b[1] - a[1];
}); });
for (const [key, value] of sortedValues) { for (const [key, value] of sortedValues) {

View file

@ -6,13 +6,18 @@ const paginator = require("../utils/pagination/pagination.js");
const tips = ["You can change the bot's prefix using the prefix command.", "Image commands also work with images previously posted in that channel.", "You can use the tags commands to save things for later use.", "You can visit https://projectlounge.pw/esmBot/help.html for a web version of this command list.", "You can view a command's aliases by putting the command name after the help command (e.g. help image).", "Parameters wrapped in [] are required, while parameters wrapped in {} are optional.", "esmBot is hosted and paid for completely out-of-pocket by the main developer. If you want to support development, please consider donating! https://patreon.com/TheEssem"]; const tips = ["You can change the bot's prefix using the prefix command.", "Image commands also work with images previously posted in that channel.", "You can use the tags commands to save things for later use.", "You can visit https://projectlounge.pw/esmBot/help.html for a web version of this command list.", "You can view a command's aliases by putting the command name after the help command (e.g. help image).", "Parameters wrapped in [] are required, while parameters wrapped in {} are optional.", "esmBot is hosted and paid for completely out-of-pocket by the main developer. If you want to support development, please consider donating! https://patreon.com/TheEssem"];
exports.run = async (message, args) => { exports.run = async (message, args) => {
const { prefix } = message.channel.guild ? await database.guilds.findOne({ id: message.channel.guild.id }) : "N/A"; const { prefix } = message.channel.guild ? await database.getGuild(message.channel.guild.id) : "N/A";
const commands = collections.commands; const commands = collections.commands;
const aliases = collections.aliases; const aliases = collections.aliases;
if (args.length !== 0 && (commands.has(args[0].toLowerCase()) || aliases.has(args[0].toLowerCase()))) { if (args.length !== 0 && (commands.has(args[0].toLowerCase()) || aliases.has(args[0].toLowerCase()))) {
const command = aliases.has(args[0].toLowerCase()) ? collections.aliases.get(args[0].toLowerCase()) : args[0].toLowerCase(); const command = aliases.has(args[0].toLowerCase()) ? collections.aliases.get(args[0].toLowerCase()) : args[0].toLowerCase();
const info = collections.info.get(command); const info = collections.info.get(command);
const counts = (await database.global.findOne({})).cmdCounts; const countDB = await database.getCounts();
const counts = countDB.reduce((acc, val) => {
const [key, value] = val;
acc[key] = value;
return acc;
}, {});
const embed = { const embed = {
"embed": { "embed": {
"author": { "author": {
@ -28,7 +33,7 @@ exports.run = async (message, args) => {
"value": info.aliases ? info.aliases.join(", ") : "None" "value": info.aliases ? info.aliases.join(", ") : "None"
}, { }, {
"name": "Times Used", "name": "Times Used",
"value": counts.get(command), "value": counts[command],
"inline": true "inline": true
}, { }, {
"name": "Parameters", "name": "Parameters",

View file

@ -1,23 +0,0 @@
const client = require("../utils/client.js");
exports.run = async (message) => {
if (!message.channel.guild) return `${message.author.mention}, this command only works in servers!`;
if (!message.member.permission.has("kickMembers")) return `${message.author.mention}, you need to have the \`Kick Members\` permission on this server to kick people!`;
if (!message.channel.guild.members.get(client.user.id).permission.has("kickMembers") && !message.channel.permissionsOf(client.user.id).has("kickMembers")) return `${message.author.mention}, I don't have the \`Kick Members\` permission!`;
const member = message.mentions[0];
if (member) {
try {
await message.channel.guild.kickMember(member.id, `kick command used by @${message.author.username}#${message.author.discriminator}`);
return `Successfully kicked ${member.mention}.`;
} catch (error) {
throw error;
//return `${message.author.mention}, I was unable to kick the member. Have you given me permissions?`;
}
} else {
return `${message.author.mention}, you need to provide a member to kick!`;
}
};
exports.category = 2;
exports.help = "Kicks a member";
exports.params = "[mention]";

View file

@ -2,11 +2,10 @@ const database = require("../utils/database.js");
exports.run = async (message, args) => { exports.run = async (message, args) => {
if (!message.channel.guild) return `${message.author.mention}, this command only works in servers!`; if (!message.channel.guild) return `${message.author.mention}, this command only works in servers!`;
const guild = await database.guilds.findOne({ id: message.channel.guild.id }); const guild = await database.getGuild(message.channel.guild.id);
if (args.length !== 0) { if (args.length !== 0) {
if (!message.member.permission.has("administrator") && message.member.id !== process.env.OWNER) return `${message.author.mention}, you need to be an administrator to change the bot prefix!`; if (!message.member.permission.has("administrator") && message.member.id !== process.env.OWNER) return `${message.author.mention}, you need to be an administrator to change the bot prefix!`;
guild.set("prefix", args[0]); await database.setPrefix(args[0], message.channel.guild);
await guild.save();
return `The prefix has been changed to ${args[0]}.`; return `The prefix has been changed to ${args[0]}.`;
} else { } else {
return `${message.author.mention}, the current prefix is \`${guild.prefix}\`.`; return `${message.author.mention}, the current prefix is \`${guild.prefix}\`.`;

View file

@ -1,16 +0,0 @@
const client = require("../utils/client.js");
exports.run = async (message, args) => {
if (!message.channel.guild) return `${message.author.mention}, this command only works in servers!`;
if (!message.member.permission.has("manageMessages")) return `${message.author.mention}, you need to have the \`Manage Messages\` permission on this server to purge messages!`;
if (!message.channel.guild.members.get(client.user.id).permission.has("manageMessages") && !message.channel.permissionsOf(client.user.id).has("manageMessages")) return `${message.author.mention}, I don't have the \`Manage Messages\` permission!`;
if (args.length === 0 || !args[0].match(/^\d+$/)) return `${message.author.mention}, you need to provide the number of messages to purge!`;
const numberOfMessages = parseInt(args[0]) + 1;
const number = await message.channel.purge(numberOfMessages);
return `Successfully purged ${number - 1} messages.`;
};
exports.aliases = ["prune"];
exports.category = 2;
exports.help = "Purges messages in a channel";
exports.params = "[number]";

View file

@ -5,45 +5,45 @@ const { random } = require("../utils/misc.js");
exports.run = async (message, args) => { exports.run = async (message, args) => {
if (!message.channel.guild) return `${message.author.mention}, this command only works in servers!`; if (!message.channel.guild) return `${message.author.mention}, this command only works in servers!`;
const guild = await database.guilds.findOne({ id: message.channel.guild.id }); const guild = await database.getGuild(message.channel.guild.id);
if (guild.tagsDisabled && args[0].toLowerCase() !== ("enable" || "disable")) return;
if ((guild.tagsDisabled || guild.tags_disabled) && args[0].toLowerCase() !== ("enable" || "disable")) return;
if (args.length === 0) return `${message.author.mention}, you need to specify the name of the tag you want to view!`; if (args.length === 0) return `${message.author.mention}, you need to specify the name of the tag you want to view!`;
const tags = guild.tags; const tags = guild.tags instanceof Map ? Object.fromEntries(guild.tags) : guild.tags;
const blacklist = ["add", "edit", "remove", "delete", "list", "random"]; const blacklist = ["add", "edit", "remove", "delete", "list", "random", "own", "owner", "enable", "disable"];
switch (args[0].toLowerCase()) { switch (args[0].toLowerCase()) {
case "add": case "add":
if (args[1] === undefined) return `${message.author.mention}, you need to provide the name of the tag you want to add!`; if (args[1] === undefined) return `${message.author.mention}, you need to provide the name of the tag you want to add!`;
if (blacklist.includes(args[1].toLowerCase())) return `${message.author.mention}, you can't make a tag with that name!`; if (blacklist.includes(args[1].toLowerCase())) return `${message.author.mention}, you can't make a tag with that name!`;
if (tags.has(args[1].toLowerCase())) return `${message.author.mention}, this tag already exists!`; if (tags[args[1].toLowerCase()]) return `${message.author.mention}, this tag already exists!`;
var result = await setTag(args.slice(2).join(" "), args[1].toLowerCase(), message, guild); var result = await setTag(args.slice(2).join(" "), args[1].toLowerCase(), message, guild);
if (result) return result; if (result) return result;
return `${message.author.mention}, the tag \`${args[1].toLowerCase()}\` has been added!`; return `${message.author.mention}, the tag \`${args[1].toLowerCase()}\` has been added!`;
case "delete": case "delete":
case "remove": case "remove":
if (args[1] === undefined) return `${message.author.mention}, you need to provide the name of the tag you want to delete!`; if (args[1] === undefined) return `${message.author.mention}, you need to provide the name of the tag you want to delete!`;
if (!tags.has(args[1].toLowerCase())) return `${message.author.mention}, this tag doesn't exist!`; if (!tags[args[1].toLowerCase()]) return `${message.author.mention}, this tag doesn't exist!`;
if (tags.get(args[1].toLowerCase()).author !== message.author.id && !message.member.permission.has("manageMessages") && message.author.id !== process.env.OWNER) return `${message.author.mention}, you don't own this tag!`; if (tags[args[1].toLowerCase()].author !== message.author.id && !message.member.permission.has("manageMessages") && message.author.id !== process.env.OWNER) return `${message.author.mention}, you don't own this tag!`;
tags.set(args[1].toLowerCase(), undefined); await database.removeTag(args[1].toLowerCase(), message.channel.guild);
await guild.save();
return `${message.author.mention}, the tag \`${args[1].toLowerCase()}\` has been deleted!`; return `${message.author.mention}, the tag \`${args[1].toLowerCase()}\` has been deleted!`;
case "edit": case "edit":
if (args[1] === undefined) return `${message.author.mention}, you need to provide the name of the tag you want to edit!`; if (args[1] === undefined) return `${message.author.mention}, you need to provide the name of the tag you want to edit!`;
if (!tags.has(args[1].toLowerCase())) return `${message.author.mention}, this tag doesn't exist!`; if (!tags[args[1].toLowerCase()]) return `${message.author.mention}, this tag doesn't exist!`;
if (tags.get(args[1].toLowerCase()).author !== message.author.id && !message.member.permission.has("manageMessages") && message.author.id !== process.env.OWNER) return `${message.author.mention}, you don't own this tag!`; if (tags[args[1].toLowerCase()].author !== message.author.id && !message.member.permission.has("manageMessages") && message.author.id !== process.env.OWNER) return `${message.author.mention}, you don't own this tag!`;
await setTag(args.slice(2).join(" "), args[1].toLowerCase(), message, guild); await setTag(args.slice(2).join(" "), args[1].toLowerCase(), message, guild);
return `${message.author.mention}, the tag \`${args[1].toLowerCase()}\` has been edited!`; return `${message.author.mention}, the tag \`${args[1].toLowerCase()}\` has been edited!`;
case "own": case "own":
case "owner": case "owner":
if (args[1] === undefined) return `${message.author.mention}, you need to provide the name of the tag you want to check the owner of!`; if (args[1] === undefined) return `${message.author.mention}, you need to provide the name of the tag you want to check the owner of!`;
if (!tags.has(args[1].toLowerCase())) return `${message.author.mention}, this tag doesn't exist!`; if (!tags[args[1].toLowerCase()]) return `${message.author.mention}, this tag doesn't exist!`;
return `${message.author.mention}, this tag is owned by **${client.users.get(tags.get(args[1].toLowerCase()).author).username}#${client.users.get(tags.get(args[1].toLowerCase()).author).discriminator}** (\`${tags.get(args[1].toLowerCase()).author}\`).`; return `${message.author.mention}, this tag is owned by **${client.users.get(tags[args[1].toLowerCase()].author).username}#${client.users.get(tags[args[1].toLowerCase()].author).discriminator}** (\`${tags[args[1].toLowerCase()].author}\`).`;
case "list": case "list":
if (!message.channel.guild.members.get(client.user.id).permission.has("addReactions") && !message.channel.permissionsOf(client.user.id).has("addReactions")) return `${message.author.mention}, I don't have the \`Add Reactions\` permission!`; if (!message.channel.guild.members.get(client.user.id).permission.has("addReactions") && !message.channel.permissionsOf(client.user.id).has("addReactions")) return `${message.author.mention}, I don't have the \`Add Reactions\` permission!`;
if (!message.channel.guild.members.get(client.user.id).permission.has("embedLinks") && !message.channel.permissionsOf(client.user.id).has("embedLinks")) return `${message.author.mention}, I don't have the \`Embed Links\` permission!`; if (!message.channel.guild.members.get(client.user.id).permission.has("embedLinks") && !message.channel.permissionsOf(client.user.id).has("embedLinks")) return `${message.author.mention}, I don't have the \`Embed Links\` permission!`;
var pageSize = 15; var pageSize = 15;
var embeds = []; var embeds = [];
var groups = [...tags.keys()].map((item, index) => { var groups = Object.keys(tags).map((item, index) => {
return index % pageSize === 0 ? [...tags.keys()].slice(index, index + pageSize) : null; return index % pageSize === 0 ? Object.keys(tags).slice(index, index + pageSize) : null;
}).filter((item) => { }).filter((item) => {
return item; return item;
}); });
@ -67,36 +67,26 @@ exports.run = async (message, args) => {
if (embeds.length === 0) return `${message.author.mention}, I couldn't find any tags!`; if (embeds.length === 0) return `${message.author.mention}, I couldn't find any tags!`;
return paginator(message, embeds); return paginator(message, embeds);
case "random": case "random":
return random([...tags])[1].content; return tags[random(Object.keys(tags))].content;
case "enable": case "enable":
case "disable": case "disable":
if (!message.member.permission.has("manageMessages") && message.author.id !== process.env.OWNER) return `${message.author.mention}, you don't have permission to disable tags!`; if (!message.member.permission.has("manageMessages") && message.author.id !== process.env.OWNER) return `${message.author.mention}, you don't have permission to disable tags!`;
var status; var toggleResult = await database.toggleTags(message.channel.guild);
if (guild.tagsDisabled) { return `${message.author.mention}, tags for this guild have been ${toggleResult ? "disabled" : "enabled"}. To ${toggleResult ? "enable" : "disable"} them again, run ${guild.prefix}tags ${toggleResult ? "enable" : "disable"}.`;
status = false;
} else {
status = true;
}
guild.set("tagsDisabled", status);
await guild.save();
return `${message.author.mention}, tags for this guild have been ${status ? "disabled" : "enabled"}. To ${status ? "enable" : "disable"} them again, run ${guild.prefix}tags ${status ? "enable" : "disable"}.`;
default: default:
if (!tags.has(args[0].toLowerCase())) return `${message.author.mention}, this tag doesn't exist!`; if (!tags[args[0].toLowerCase()]) return `${message.author.mention}, this tag doesn't exist!`;
return tags.get(args[0].toLowerCase()).content; return tags[args[0].toLowerCase()].content;
} }
}; };
const setTag = async (content, name, message, guild) => { const setTag = async (content, name, message) => {
if ((!content || content.length === 0) && message.attachments.length === 0) return `${message.author.mention}, you need to provide the content of the tag!`; if ((!content || content.length === 0) && message.attachments.length === 0) return `${message.author.mention}, you need to provide the content of the tag!`;
if (message.attachments.length !== 0 && content) { if (message.attachments.length !== 0 && content) {
guild.tags.set(name, { content: `${content} ${message.attachments[0].url}`, author: message.author.id }); await database.setTag(name, { content: `${content} ${message.attachments[0].url}`, author: message.author.id }, message.channel.guild);
await guild.save();
} else if (message.attachments.length !== 0) { } else if (message.attachments.length !== 0) {
guild.tags.set(name, { content: message.attachments[0].url, author: message.author.id }); await database.setTag(name, { content: message.attachments[0].url, author: message.author.id }, message.channel.guild);
await guild.save();
} else { } else {
guild.tags.set(name, { content: content, author: message.author.id }); await database.setTag(name, { content: content, author: message.author.id }, message.channel.guild);
await guild.save();
} }
return; return;
}; };

View file

@ -1,76 +0,0 @@
const database = require("../utils/database.js");
const client = require("../utils/client.js");
const paginator = require("../utils/pagination/pagination.js");
exports.run = async (message, args) => {
if (!message.channel.guild) return `${message.author.mention}, this command only works in servers!`;
if (!message.member.permission.has("manageMessages")) return `${message.author.mention}, you need to have the \`Manage Messages\` permission on this server to warn people!`;
if (!args[0]) return `${message.author.mention}, you need to provide a member to warn!`;
const memberCheck = message.mentions.length >= 1 ? message.mentions[0] : client.users.get(args[0]);
const member = memberCheck ? memberCheck : client.users.get(args[0].replace(/\D/g, ""));
if (member) {
const guild = await database.guilds.findOne({ id: message.channel.guild.id });
const array = guild.warns.get(member.id) ? guild.warns.get(member.id).warns : [];
if (args[1].toLowerCase() === "list") {
if (!message.channel.guild.members.get(client.user.id).permission.has("addReactions") && !message.channel.permissionsOf(client.user.id).has("addReactions")) return `${message.author.mention}, I don't have the \`Add Reactions\` permission!`;
if (!message.channel.guild.members.get(client.user.id).permission.has("embedLinks") && !message.channel.permissionsOf(client.user.id).has("embedLinks")) return `${message.author.mention}, I don't have the \`Embed Links\` permission!`;
const warnArray = [];
for (const [i, value] of array.entries()) {
warnArray.push(`**${i + 1}: Added by ${message.channel.guild.members.get(value.creator).username}#${message.channel.guild.members.get(value.creator).discriminator}**: ${value.message} (${value.time.toUTCString()})`);
}
const pageSize = 15;
const embeds = [];
const groups = warnArray.map((item, index) => {
return index % pageSize === 0 ? warnArray.slice(index, index + pageSize) : null;
}).filter((item) => {
return item;
});
for (const [i, value] of groups.entries()) {
embeds.push({
"embed": {
"title": "Warn List",
"color": 16711680,
"footer": {
"text": `Page ${i + 1} of ${groups.length}`
},
"description": value.join("\n"),
"author": {
"name": member.username,
"icon_url": member.avatarURL
}
}
});
}
if (embeds.length === 0) return `${message.author.mention}, I couldn't find any warns for this user!`;
return paginator(message, embeds);
} else if (args[1].toLowerCase() === "remove") {
if (args[2] < 1 || !array[args[2] - 1]) return `${message.author.mention}, there aren't any warns with that ID!`;
array.splice(args[2] - 1, 1);
guild.warns.set(member.id, {
count: guild.warns.get(member.id).count - 1,
warns: array
});
await guild.save();
return `Successfully removed the warning for ${member.mention}.`;
} else {
args.shift();
array.push({
message: args.join(" "),
time: new Date(),
creator: message.author.id
});
guild.warns.set(member.id, {
count: (guild.warns.get(member.id) ? guild.warns.get(member.id).count : 0) + 1,
warns: array
});
await guild.save();
return `Successfully warned ${member.mention} for \`${args.join(" ")}\`.`;
}
} else {
return `${message.author.mention}, you need to provide a member to warn!`;
}
};
exports.category = 2;
exports.help = "Warns a server member";
exports.params = "[mention] {reason/list/remove} {number}";

View file

@ -1,18 +1,8 @@
const db = require("../utils/database.js"); const db = require("../utils/database.js");
const logger = require("../utils/logger.js"); const logger = require("../utils/logger.js");
const misc = require("../utils/misc.js");
// run when the bot is added to a guild // run when the bot is added to a guild
module.exports = async (guild) => { module.exports = async (guild) => {
logger.log("info", `[GUILD JOIN] ${guild.name} (${guild.id}) added the bot.`); logger.log("info", `[GUILD JOIN] ${guild.name} (${guild.id}) added the bot.`);
const guildDB = new db.guilds({ await db.addGuild(guild);
id: guild.id,
tags: misc.tagDefaults,
prefix: process.env.PREFIX,
warns: {},
disabledChannels: [],
tagsDisabled: false
});
await guildDB.save();
return guildDB;
}; };

View file

@ -3,7 +3,6 @@ const client = require("../utils/client.js");
const database = require("../utils/database.js"); const database = require("../utils/database.js");
const logger = require("../utils/logger.js"); const logger = require("../utils/logger.js");
const collections = require("../utils/collections.js"); const collections = require("../utils/collections.js");
const guildCreate = require("./guildCreate.js");
const commands = [...collections.aliases.keys(), ...collections.commands.keys()]; const commands = [...collections.aliases.keys(), ...collections.commands.keys()];
// run when someone sends a message // run when someone sends a message
@ -24,13 +23,21 @@ module.exports = async (message) => {
} }
if (!valid) return; if (!valid) return;
// prefix can be a mention or a set of special characters let prefixCandidate;
let guildDB = message.channel.guild ? await database.guilds.findOne({ id: message.channel.guild.id }).lean().exec() : null; if (collections.prefixCache.has(message.channel.guild.id)) {
if (message.channel.guild && !guildDB) { prefixCandidate = collections.prefixCache.get(message.channel.guild.id);
guildDB = await guildCreate(message.channel.guild); } else {
let guildDB = message.channel.guild ? await database.getGuild(message.channel.guild.id) : null;
if (message.channel.guild && !(guildDB && guildDB.disabled)) {
guildDB = await database.fixGuild(message.channel.guild);
} }
// there's a bit of a workaround here due to member.mention not accounting for both mention types prefixCandidate = guildDB.prefix;
const prefix = message.channel.guild ? (message.content.startsWith(message.channel.guild.members.get(client.user.id).mention) ? `${message.channel.guild.members.get(client.user.id).mention} ` : (message.content.startsWith(`<@${client.user.id}>`) ? `<@${client.user.id}> ` : guildDB.prefix)) : ""; collections.prefixCache.set(message.channel.guild.id, guildDB.prefix);
}
// this line be like Pain. Pain. Pain. Pain. Pain. Pain. Pain. Pain. Pain. Pain. Pain. Pain.
// there's also bit of a workaround here due to member.mention not accounting for both mention types
const prefix = message.channel.guild ? (message.content.startsWith(message.channel.guild.members.get(client.user.id).mention) ? `${message.channel.guild.members.get(client.user.id).mention} ` : (message.content.startsWith(`<@${client.user.id}>`) ? `<@${client.user.id}> ` : prefixCandidate)) : "";
// ignore other stuff // ignore other stuff
if (message.content.startsWith(prefix) === false) return; if (message.content.startsWith(prefix) === false) return;
@ -41,7 +48,14 @@ module.exports = async (message) => {
const command = args.shift().toLowerCase(); const command = args.shift().toLowerCase();
// don't run if message is in a disabled channel // don't run if message is in a disabled channel
if (guildDB && guildDB.disabledChannels && guildDB.disabledChannels.includes(message.channel.id) && command != "channel") return; if (collections.disabledCache.has(message.channel.guild.id)) {
const disabled = collections.disabledCache.get(message.channel.guild.id);
if (disabled.includes(message.channel.id) && command != "channel") return;
} else if (message.channel.guild) {
const guildDB = await database.getGuild(message.channel.guild.id);
collections.disabledCache.set(message.channel.guild.id, guildDB.disabled);
if (guildDB.disabled.includes(message.channel.id) && command !== "channel") return;
}
// check if command exists // check if command exists
const cmd = collections.commands.get(command) || collections.commands.get(collections.aliases.get(command)); const cmd = collections.commands.get(command) || collections.commands.get(collections.aliases.get(command));
@ -50,10 +64,7 @@ module.exports = async (message) => {
// actually run the command // actually run the command
logger.log("info", `${message.author.username} (${message.author.id}) ran command ${command}`); logger.log("info", `${message.author.username} (${message.author.id}) ran command ${command}`);
try { try {
const global = (await database.global.findOne({}).exec()); await database.addCount(collections.aliases.has(command) ? collections.aliases.get(command) : command);
const count = global.cmdCounts.get(collections.aliases.has(command) ? collections.aliases.get(command) : command);
global.cmdCounts.set(collections.aliases.has(command) ? collections.aliases.get(command) : command, parseInt(count) + 1);
await global.save();
const result = await cmd(message, args, content.replace(command, "").trim()); // we also provide the message content as a parameter for cases where we need more accuracy const result = await cmd(message, args, content.replace(command, "").trim()); // we also provide the message content as a parameter for cases where we need more accuracy
if (typeof result === "string" || (typeof result === "object" && result.embed)) { if (typeof result === "string" || (typeof result === "object" && result.embed)) {
await client.createMessage(message.channel.id, result); await client.createMessage(message.channel.id, result);

View file

@ -1,6 +1,5 @@
const client = require("../utils/client.js"); const client = require("../utils/client.js");
const database = require("../utils/database.js"); const database = require("../utils/database.js");
const collections = require("../utils/collections.js");
const logger = require("../utils/logger.js"); const logger = require("../utils/logger.js");
const messages = require("../messages.json"); const messages = require("../messages.json");
const misc = require("../utils/misc.js"); const misc = require("../utils/misc.js");
@ -16,58 +15,7 @@ module.exports = async () => {
// connect to lavalink // connect to lavalink
if (!soundPlayer.status && !soundPlayer.connected) await soundPlayer.connect(); if (!soundPlayer.status && !soundPlayer.connected) await soundPlayer.connect();
// make sure settings/tags exist await database.handleCounts();
for (const [id] of client.guilds) {
const guildDB = await database.guilds.findOne({id: id});
if (!guildDB) {
logger.log(`Registering guild database entry for guild ${id}...`);
const newGuild = new database.guilds({
id: id,
tags: misc.tagDefaults,
prefix: process.env.PREFIX,
warns: {},
disabledChannels: [],
tagsDisabled: false
});
await newGuild.save();
} else {
if (!guildDB.warns) {
logger.log(`Creating warn object for guild ${id}...`);
guildDB.set("warns", {});
await guildDB.save();
} else if (!guildDB.disabledChannels) {
logger.log(`Creating disabled channels object for guild ${id}...`);
guildDB.set("disabledChannels", []);
await guildDB.save();
}
}
}
const global = await database.global.findOne({});
if (!global) {
const countObject = {};
for (const command of collections.commands.keys()) {
countObject[command] = 0;
}
const newGlobal = new database.global({
cmdCounts: countObject
});
await newGlobal.save();
} else {
const exists = [];
for (const command of collections.commands.keys()) {
if (!global.cmdCounts.has(command)) {
global.cmdCounts.set(command, 0);
}
exists.push(command);
}
for (const command of global.cmdCounts.keys()) {
if (!exists.includes(command)) {
global.cmdCounts.set(command, undefined);
}
}
await global.save();
}
// generate docs // generate docs
if (helpGenerator && first) await helpGenerator(process.env.OUTPUT); if (helpGenerator && first) await helpGenerator(process.env.OUTPUT);
@ -104,16 +52,8 @@ module.exports = async () => {
try { try {
const stream = twitter.client.statuses.filter(`@${process.env.HANDLE}`); const stream = twitter.client.statuses.filter(`@${process.env.HANDLE}`);
stream.on("data", async (tweet) => { stream.on("data", async (tweet) => {
if ( if (tweet.user.screen_name !== "esmBot_" && !blocks.ids.includes(tweet.user.id_str)) {
tweet.user.screen_name !== "esmBot_" && const tweetContent = await misc.getTweet(twitter.tweets, true).replace(/{{user}}/gm, `@${tweet.user.screen_name}`);
!blocks.ids.includes(tweet.user.id_str)
) {
let tweetContent;
if (new RegExp(["@this_vid", "@DownloaderBot", "GetVideoBot", "@thisvid_"].join("|")).test(tweet.text)) {
tweetContent = await misc.getTweet(twitter.tweets, true, true);
} else {
tweetContent = await misc.getTweet(twitter.tweets, true).replace(/{{user}}/gm, `@${tweet.user.screen_name}`);
}
const payload = { const payload = {
status: `@${tweet.user.screen_name} ${tweetContent}`, status: `@${tweet.user.screen_name} ${tweetContent}`,
in_reply_to_status_id: tweet.id_str, in_reply_to_status_id: tweet.id_str,

327
package-lock.json generated
View file

@ -63,11 +63,30 @@
"resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.1.1.tgz", "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.1.1.tgz",
"integrity": "sha512-XO6INPbZCxdprl+9qa/AAbFFOMzzwqYxpjPgLICrMD6C2FCw6qfJOPcBk6JqqPLSaZ/Qx87qn4rpPmPMwaAK6w==" "integrity": "sha512-XO6INPbZCxdprl+9qa/AAbFFOMzzwqYxpjPgLICrMD6C2FCw6qfJOPcBk6JqqPLSaZ/Qx87qn4rpPmPMwaAK6w=="
}, },
"@types/bson": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.0.3.tgz",
"integrity": "sha512-mVRvYnTOZJz3ccpxhr3wgxVmSeiYinW+zlzQz3SXWaJmD1DuL05Jeq7nKw3SnbKmbleW5qrLG5vdyWe/A9sXhw==",
"optional": true,
"requires": {
"@types/node": "*"
}
},
"@types/debug": { "@types/debug": {
"version": "4.1.5", "version": "4.1.5",
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.5.tgz", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.5.tgz",
"integrity": "sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ==" "integrity": "sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ=="
}, },
"@types/mongodb": {
"version": "3.6.3",
"resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.6.3.tgz",
"integrity": "sha512-6YNqGP1hk5bjUFaim+QoFFuI61WjHiHE1BNeB41TA00Xd2K7zG4lcWyLLq/XtIp36uMavvS5hoAUJ+1u/GcX2Q==",
"optional": true,
"requires": {
"@types/bson": "*",
"@types/node": "*"
}
},
"@types/node": { "@types/node": {
"version": "14.11.5", "version": "14.11.5",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.11.5.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.11.5.tgz",
@ -238,6 +257,7 @@
"version": "2.2.1", "version": "2.2.1",
"resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz",
"integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==",
"optional": true,
"requires": { "requires": {
"readable-stream": "^2.3.5", "readable-stream": "^2.3.5",
"safe-buffer": "^5.1.1" "safe-buffer": "^5.1.1"
@ -246,7 +266,8 @@
"bluebird": { "bluebird": {
"version": "3.5.1", "version": "3.5.1",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz",
"integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==",
"optional": true
}, },
"body-parser": { "body-parser": {
"version": "1.19.0", "version": "1.19.0",
@ -300,7 +321,8 @@
"bson": { "bson": {
"version": "1.1.5", "version": "1.1.5",
"resolved": "https://registry.npmjs.org/bson/-/bson-1.1.5.tgz", "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.5.tgz",
"integrity": "sha512-kDuEzldR21lHciPQAIulLs1LZlCXdLziXI6Mb/TDkwXhb//UORJNPXgcRs2CuO4H0DcMkpfT3/ySsP3unoZjBg==" "integrity": "sha512-kDuEzldR21lHciPQAIulLs1LZlCXdLziXI6Mb/TDkwXhb//UORJNPXgcRs2CuO4H0DcMkpfT3/ySsP3unoZjBg==",
"optional": true
}, },
"buffer": { "buffer": {
"version": "5.4.3", "version": "5.4.3",
@ -340,6 +362,12 @@
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A=="
}, },
"buffer-writer": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz",
"integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==",
"optional": true
},
"bufferutil": { "bufferutil": {
"version": "4.0.1", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.1.tgz", "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.1.tgz",
@ -476,12 +504,23 @@
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
}, },
"color": { "color": {
"version": "3.1.2", "version": "3.1.3",
"resolved": "https://registry.npmjs.org/color/-/color-3.1.2.tgz", "resolved": "https://registry.npmjs.org/color/-/color-3.1.3.tgz",
"integrity": "sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg==", "integrity": "sha512-xgXAcTHa2HeFCGLE9Xs/R82hujGtu9Jd9x4NW3T34+OMs7VoPsjwzRczKHvTAHeJwWFwX5j15+MgAppE8ztObQ==",
"requires": { "requires": {
"color-convert": "^1.9.1", "color-convert": "^1.9.1",
"color-string": "^1.5.2" "color-string": "^1.5.4"
},
"dependencies": {
"color-string": {
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.4.tgz",
"integrity": "sha512-57yF5yt8Xa3czSEW1jfQDE79Idk0+AkN/4KWad6tbdxUmAs3MvjxlWSWD4deYytcRfoZ9nhKyFl1kj5tBvidbw==",
"requires": {
"color-name": "^1.0.0",
"simple-swizzle": "^0.2.2"
}
}
} }
}, },
"color-convert": { "color-convert": {
@ -663,7 +702,8 @@
"denque": { "denque": {
"version": "1.4.1", "version": "1.4.1",
"resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz",
"integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==" "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==",
"optional": true
}, },
"depd": { "depd": {
"version": "1.1.2", "version": "1.1.2",
@ -780,9 +820,9 @@
"integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w=="
}, },
"eris": { "eris": {
"version": "0.13.3", "version": "0.13.4",
"resolved": "https://registry.npmjs.org/eris/-/eris-0.13.3.tgz", "resolved": "https://registry.npmjs.org/eris/-/eris-0.13.4.tgz",
"integrity": "sha512-WBtLyknOWZpYZL9yPhez0oKUWvYpunSg43hGxawwjwSf3gFXmbEPYrT8KlmZXtpJnX16eQ7mzIq+MgSh3LarEg==", "integrity": "sha512-IFA14nasCig8xp8cVCULvzBuJ0qpYqJ3XyEtm9OLdC177DYDCJ9QM2Aq+KOpejIVl7838n9AyRlLI6w9Eu3PiQ==",
"requires": { "requires": {
"opusscript": "^0.0.7", "opusscript": "^0.0.7",
"tweetnacl": "^1.0.1", "tweetnacl": "^1.0.1",
@ -1606,9 +1646,10 @@
"integrity": "sha512-zCTP6Qd/WwjrpuHFkJuXc5opRdKprUr7eI7+JCCtcetThJt45qptu82MWQ+eET+FtDrMo7+BYjo3iD0XIq1L9Q==" "integrity": "sha512-zCTP6Qd/WwjrpuHFkJuXc5opRdKprUr7eI7+JCCtcetThJt45qptu82MWQ+eET+FtDrMo7+BYjo3iD0XIq1L9Q=="
}, },
"kareem": { "kareem": {
"version": "2.3.1", "version": "2.3.2",
"resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.1.tgz", "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.2.tgz",
"integrity": "sha512-l3hLhffs9zqoDe8zjmb/mAN4B8VT3L56EUvKNqLFVs9YlFA+zx7ke1DO8STAdDyYNkeSo1nKmjuvQeI12So8Xw==" "integrity": "sha512-STHz9P7X2L4Kwn72fA4rGyqyXdmrMSdxqHx9IXon/FXluXieaFA6KJ2upcHAHxQPQ0LeM/OjLrhFxifHewOALQ==",
"optional": true
}, },
"kind-of": { "kind-of": {
"version": "3.2.2", "version": "3.2.2",
@ -1692,6 +1733,14 @@
"triple-beam": "^1.3.0" "triple-beam": "^1.3.0"
} }
}, },
"lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"requires": {
"yallist": "^4.0.0"
}
},
"media-typer": { "media-typer": {
"version": "0.3.0", "version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
@ -1783,6 +1832,7 @@
"version": "0.5.5", "version": "0.5.5",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
"integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
"dev": true,
"requires": { "requires": {
"minimist": "^1.2.5" "minimist": "^1.2.5"
}, },
@ -1790,7 +1840,8 @@
"minimist": { "minimist": {
"version": "1.2.5", "version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
"dev": true
} }
} }
}, },
@ -1810,9 +1861,10 @@
"integrity": "sha512-cBMXjSW+fjOb4tyaVHuaVE/A5TqkukDWiOfxxAjY+PEqmmBQlLwn+8OzwPiG3brouXKY5Un4pBjAeB6UToXHaQ==" "integrity": "sha512-cBMXjSW+fjOb4tyaVHuaVE/A5TqkukDWiOfxxAjY+PEqmmBQlLwn+8OzwPiG3brouXKY5Un4pBjAeB6UToXHaQ=="
}, },
"mongodb": { "mongodb": {
"version": "3.6.2", "version": "3.6.3",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.2.tgz", "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.3.tgz",
"integrity": "sha512-sSZOb04w3HcnrrXC82NEh/YGCmBuRgR+C1hZgmmv4L6dBz4BkRse6Y8/q/neXer9i95fKUBbFi4KgeceXmbsOA==", "integrity": "sha512-rOZuR0QkodZiM+UbQE5kDsJykBqWi0CL4Ec2i1nrGrUI3KO11r6Fbxskqmq3JK2NH7aW4dcccBuUujAP0ERl5w==",
"optional": true,
"requires": { "requires": {
"bl": "^2.2.1", "bl": "^2.2.1",
"bson": "^1.1.4", "bson": "^1.1.4",
@ -1823,16 +1875,18 @@
} }
}, },
"mongoose": { "mongoose": {
"version": "5.10.8", "version": "5.11.8",
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.10.8.tgz", "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.11.8.tgz",
"integrity": "sha512-hbpFhOU6rWkWPkekUeSJxqWwzsjVQZ9xPg4WmWA1HJ8YDvjyNye1xbp82fw67BpnyvcjHxyU3/YhujsOCx55yw==", "integrity": "sha512-RRfrYLg7pyuyx7xu5hwadjIZZJB9W2jqIMkL1CkTmk/uOCX3MX2tl4BVIi2rJUtgMNwn6dy3wBD3soB8I9Nlog==",
"optional": true,
"requires": { "requires": {
"@types/mongodb": "^3.5.27",
"bson": "^1.1.4", "bson": "^1.1.4",
"kareem": "2.3.1", "kareem": "2.3.2",
"mongodb": "3.6.2", "mongodb": "3.6.3",
"mongoose-legacy-pluralize": "1.0.2", "mongoose-legacy-pluralize": "1.0.2",
"mpath": "0.7.0", "mpath": "0.8.1",
"mquery": "3.2.2", "mquery": "3.2.3",
"ms": "2.1.2", "ms": "2.1.2",
"regexp-clone": "1.0.0", "regexp-clone": "1.0.0",
"safe-buffer": "5.2.1", "safe-buffer": "5.2.1",
@ -1843,29 +1897,34 @@
"ms": { "ms": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"optional": true
}, },
"safe-buffer": { "safe-buffer": {
"version": "5.2.1", "version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
"optional": true
} }
} }
}, },
"mongoose-legacy-pluralize": { "mongoose-legacy-pluralize": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz", "resolved": "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz",
"integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==" "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==",
"optional": true
}, },
"mpath": { "mpath": {
"version": "0.7.0", "version": "0.8.1",
"resolved": "https://registry.npmjs.org/mpath/-/mpath-0.7.0.tgz", "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.8.1.tgz",
"integrity": "sha512-Aiq04hILxhz1L+f7sjGyn7IxYzWm1zLNNXcfhDtx04kZ2Gk7uvFdgZ8ts1cWa/6d0TQmag2yR8zSGZUmp0tFNg==" "integrity": "sha512-norEinle9aFc05McBawVPwqgFZ7npkts9yu17ztIVLwPwO9rq0OTp89kGVTqvv5rNLMz96E5iWHpVORjI411vA==",
"optional": true
}, },
"mquery": { "mquery": {
"version": "3.2.2", "version": "3.2.3",
"resolved": "https://registry.npmjs.org/mquery/-/mquery-3.2.2.tgz", "resolved": "https://registry.npmjs.org/mquery/-/mquery-3.2.3.tgz",
"integrity": "sha512-XB52992COp0KP230I3qloVUbkLUxJIu328HBP2t2EsxSFtf4W1HPSOBWOXf1bqxK4Xbb66lfMJ+Bpfd9/yZE1Q==", "integrity": "sha512-cIfbP4TyMYX+SkaQ2MntD+F2XbqaBHUYWk3j+kqdDztPWok3tgyssOZxMHMtzbV1w9DaSlvEea0Iocuro41A4g==",
"optional": true,
"requires": { "requires": {
"bluebird": "3.5.1", "bluebird": "3.5.1",
"debug": "3.1.0", "debug": "3.1.0",
@ -1878,6 +1937,7 @@
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
"optional": true,
"requires": { "requires": {
"ms": "2.0.0" "ms": "2.0.0"
} }
@ -1885,7 +1945,8 @@
"ms": { "ms": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
"optional": true
} }
} }
}, },
@ -1930,9 +1991,9 @@
"dev": true "dev": true
}, },
"node-abi": { "node-abi": {
"version": "2.19.1", "version": "2.19.3",
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.19.1.tgz", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.19.3.tgz",
"integrity": "sha512-HbtmIuByq44yhAzK7b9j/FelKlHYISKQn0mtvcBrU5QBkhoCMp5bu8Hv5AI34DcKfOAcJBcOEMwLlwO62FFu9A==", "integrity": "sha512-9xZrlyfvKhWme2EXFKQhZRp1yNWT/uI1luYPr3sFl+H4keYY4xR+1jO7mvTTijIsHf1M+QDe9uWuKeEpLInIlg==",
"requires": { "requires": {
"semver": "^5.4.1" "semver": "^5.4.1"
} }
@ -2106,6 +2167,12 @@
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
}, },
"packet-reader": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz",
"integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==",
"optional": true
},
"parent-module": { "parent-module": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
@ -2167,6 +2234,73 @@
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
"integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA="
}, },
"pg": {
"version": "8.5.1",
"resolved": "https://registry.npmjs.org/pg/-/pg-8.5.1.tgz",
"integrity": "sha512-9wm3yX9lCfjvA98ybCyw2pADUivyNWT/yIP4ZcDVpMN0og70BUWYEGXPCTAQdGTAqnytfRADb7NERrY1qxhIqw==",
"optional": true,
"requires": {
"buffer-writer": "2.0.0",
"packet-reader": "1.0.0",
"pg-connection-string": "^2.4.0",
"pg-pool": "^3.2.2",
"pg-protocol": "^1.4.0",
"pg-types": "^2.1.0",
"pgpass": "1.x"
}
},
"pg-connection-string": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.4.0.tgz",
"integrity": "sha512-3iBXuv7XKvxeMrIgym7njT+HlZkwZqqGX4Bu9cci8xHZNT+Um1gWKqCsAzcC0d95rcKMU5WBg6YRUcHyV0HZKQ==",
"optional": true
},
"pg-cursor": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/pg-cursor/-/pg-cursor-2.5.2.tgz",
"integrity": "sha512-yS0lxXA5WoIVK7BUgJr1uOJDJe5JxVezItTLvqnTXj6bF3di4UtQOrPx8RW3GpFmom2NTQfpEc2N6vvdpopQSw==",
"optional": true
},
"pg-int8": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz",
"integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==",
"optional": true
},
"pg-pool": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.2.2.tgz",
"integrity": "sha512-ORJoFxAlmmros8igi608iVEbQNNZlp89diFVx6yV5v+ehmpMY9sK6QgpmgoXbmkNaBAx8cOOZh9g80kJv1ooyA==",
"optional": true
},
"pg-protocol": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.4.0.tgz",
"integrity": "sha512-El+aXWcwG/8wuFICMQjM5ZSAm6OWiJicFdNYo+VY3QP+8vI4SvLIWVe51PppTzMhikUJR+PsyIFKqfdXPz/yxA==",
"optional": true
},
"pg-types": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz",
"integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==",
"optional": true,
"requires": {
"pg-int8": "1.0.1",
"postgres-array": "~2.0.0",
"postgres-bytea": "~1.0.0",
"postgres-date": "~1.0.4",
"postgres-interval": "^1.1.0"
}
},
"pgpass": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.4.tgz",
"integrity": "sha512-YmuA56alyBq7M59vxVBfPJrGSozru8QAdoNlWuW3cz8l+UX3cWge0vTvjKhsSHSJpo3Bom8/Mm6hf0TR5GY0+w==",
"optional": true,
"requires": {
"split2": "^3.1.1"
}
},
"pkg-dir": { "pkg-dir": {
"version": "4.2.0", "version": "4.2.0",
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
@ -2212,16 +2346,43 @@
"resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz",
"integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==" "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w=="
}, },
"postgres-array": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
"integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==",
"optional": true
},
"postgres-bytea": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz",
"integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=",
"optional": true
},
"postgres-date": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz",
"integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==",
"optional": true
},
"postgres-interval": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz",
"integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==",
"optional": true,
"requires": {
"xtend": "^4.0.0"
}
},
"prebuild-install": { "prebuild-install": {
"version": "5.3.5", "version": "6.0.0",
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.3.5.tgz", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.0.0.tgz",
"integrity": "sha512-YmMO7dph9CYKi5IR/BzjOJlRzpxGGVo1EsLSUZ0mt/Mq0HWZIHOKHHcHdT69yG54C9m6i45GpItwRHpk0Py7Uw==", "integrity": "sha512-h2ZJ1PXHKWZpp1caLw0oX9sagVpL2YTk+ZwInQbQ3QqNd4J03O6MpFNmMTJlkfgPENWqe5kP0WjQLqz5OjLfsw==",
"requires": { "requires": {
"detect-libc": "^1.0.3", "detect-libc": "^1.0.3",
"expand-template": "^2.0.3", "expand-template": "^2.0.3",
"github-from-package": "0.0.0", "github-from-package": "0.0.0",
"minimist": "^1.2.3", "minimist": "^1.2.3",
"mkdirp": "^0.5.1", "mkdirp-classic": "^0.5.3",
"napi-build-utils": "^1.0.1", "napi-build-utils": "^1.0.1",
"node-abi": "^2.7.0", "node-abi": "^2.7.0",
"noop-logger": "^0.1.1", "noop-logger": "^0.1.1",
@ -2452,7 +2613,8 @@
"regexp-clone": { "regexp-clone": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz", "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz",
"integrity": "sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw==" "integrity": "sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw==",
"optional": true
}, },
"regexpp": { "regexpp": {
"version": "2.0.1", "version": "2.0.1",
@ -2474,6 +2636,7 @@
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz",
"integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==",
"optional": true,
"requires": { "requires": {
"resolve-from": "^2.0.0", "resolve-from": "^2.0.0",
"semver": "^5.1.0" "semver": "^5.1.0"
@ -2482,7 +2645,8 @@
"resolve-from": { "resolve-from": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz",
"integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=",
"optional": true
} }
} }
}, },
@ -2657,25 +2821,45 @@
} }
}, },
"sharp": { "sharp": {
"version": "0.26.1", "version": "0.26.3",
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.26.1.tgz", "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.26.3.tgz",
"integrity": "sha512-9MhwS4ys8pnwBH7MtnBdLzUv+cb24QC4xbzzQL6A+1MQ4Se2V6oPHEX8TIGIZUPRKi6S1kJPVNzt/Xqqp6/H3Q==", "integrity": "sha512-NdEJ9S6AMr8Px0zgtFo1TJjMK/ROMU92MkDtYn2BBrDjIx3YfH9TUyGdzPC+I/L619GeYQc690Vbaxc5FPCCWg==",
"requires": { "requires": {
"color": "^3.1.2", "array-flatten": "^3.0.0",
"color": "^3.1.3",
"detect-libc": "^1.0.3", "detect-libc": "^1.0.3",
"node-addon-api": "^3.0.2", "node-addon-api": "^3.0.2",
"npmlog": "^4.1.2", "npmlog": "^4.1.2",
"prebuild-install": "^5.3.5", "prebuild-install": "^6.0.0",
"semver": "^7.3.2", "semver": "^7.3.2",
"simple-get": "^4.0.0", "simple-get": "^4.0.0",
"tar-fs": "^2.1.0", "tar-fs": "^2.1.1",
"tunnel-agent": "^0.6.0" "tunnel-agent": "^0.6.0"
}, },
"dependencies": { "dependencies": {
"array-flatten": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-3.0.0.tgz",
"integrity": "sha512-zPMVc3ZYlGLNk4mpK1NzP2wg0ml9t7fUgDsayR5Y5rSzxQilzR9FGu/EH2jQOcKSAeAfWeylyW8juy3OkWRvNA=="
},
"semver": { "semver": {
"version": "7.3.2", "version": "7.3.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz",
"integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==" "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==",
"requires": {
"lru-cache": "^6.0.0"
}
},
"tar-fs": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
"integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==",
"requires": {
"chownr": "^1.1.1",
"mkdirp-classic": "^0.5.2",
"pump": "^3.0.0",
"tar-stream": "^2.1.4"
}
} }
} }
}, },
@ -2697,7 +2881,8 @@
"sift": { "sift": {
"version": "7.0.1", "version": "7.0.1",
"resolved": "https://registry.npmjs.org/sift/-/sift-7.0.1.tgz", "resolved": "https://registry.npmjs.org/sift/-/sift-7.0.1.tgz",
"integrity": "sha512-oqD7PMJ+uO6jV9EQCl0LrRw1OwsiPsiFQR5AR30heR+4Dl7jBBbDLnNvWiak20tzZlSE1H7RB30SX/1j/YYT7g==" "integrity": "sha512-oqD7PMJ+uO6jV9EQCl0LrRw1OwsiPsiFQR5AR30heR+4Dl7jBBbDLnNvWiak20tzZlSE1H7RB30SX/1j/YYT7g==",
"optional": true
}, },
"signal-exit": { "signal-exit": {
"version": "3.0.2", "version": "3.0.2",
@ -2756,7 +2941,8 @@
"sliced": { "sliced": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz",
"integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=" "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=",
"optional": true
}, },
"sparse-bitfield": { "sparse-bitfield": {
"version": "3.0.3", "version": "3.0.3",
@ -2767,6 +2953,28 @@
"memory-pager": "^1.0.2" "memory-pager": "^1.0.2"
} }
}, },
"split2": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz",
"integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==",
"optional": true,
"requires": {
"readable-stream": "^3.0.0"
},
"dependencies": {
"readable-stream": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
"optional": true,
"requires": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
"util-deprecate": "^1.0.1"
}
}
}
},
"sprintf-js": { "sprintf-js": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
@ -3207,11 +3415,22 @@
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.0.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.0.tgz",
"integrity": "sha512-kyFwXuV/5ymf+IXhS6f0+eAFvydbaBW3zjpT6hUdAh/hbVjTIB5EHBGi0bPoCLSK2wcuz3BrEkB9LrYv1Nm4NQ==" "integrity": "sha512-kyFwXuV/5ymf+IXhS6f0+eAFvydbaBW3zjpT6hUdAh/hbVjTIB5EHBGi0bPoCLSK2wcuz3BrEkB9LrYv1Nm4NQ=="
}, },
"xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
"optional": true
},
"y18n": { "y18n": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
"integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w=="
}, },
"yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
},
"yargs": { "yargs": {
"version": "13.3.0", "version": "13.3.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz",

View file

@ -29,13 +29,12 @@
"dotenv": "^8.2.0", "dotenv": "^8.2.0",
"duckduckgo-images-api": "github:benpbolton/duckduckgo-images-api", "duckduckgo-images-api": "github:benpbolton/duckduckgo-images-api",
"emoji-regex": "^8.0.0", "emoji-regex": "^8.0.0",
"eris": "^0.13.3", "eris": "^0.13.4",
"file-type": "^13.1.2", "file-type": "^13.1.2",
"jsqr": "^1.3.1", "jsqr": "^1.3.1",
"lavacord": "^1.1.9", "lavacord": "^1.1.9",
"moment": "^2.29.1", "moment": "^2.29.1",
"moment-duration-format": "^2.3.2", "moment-duration-format": "^2.3.2",
"mongoose": "^5.10.8",
"node-addon-api": "^3.0.2", "node-addon-api": "^3.0.2",
"node-emoji": "^1.10.0", "node-emoji": "^1.10.0",
"node-fetch": "^2.6.1", "node-fetch": "^2.6.1",
@ -45,7 +44,7 @@
"puppeteer-extra-plugin-stealth": "^2.6.5", "puppeteer-extra-plugin-stealth": "^2.6.5",
"qrcode": "^1.4.4", "qrcode": "^1.4.4",
"retrotext": "github:TheEssem/retrotext", "retrotext": "github:TheEssem/retrotext",
"sharp": "^0.26.1", "sharp": "^0.26.3",
"winston": "^3.3.3" "winston": "^3.3.3"
}, },
"devDependencies": { "devDependencies": {
@ -56,6 +55,9 @@
"bufferutil": "^4.0.1", "bufferutil": "^4.0.1",
"erlpack": "github:abalabahaha/erlpack", "erlpack": "github:abalabahaha/erlpack",
"express": "^4.17.1", "express": "^4.17.1",
"mongoose": "^5.11.8",
"pg": "^8.5.1",
"pg-cursor": "^2.5.2",
"uuid": "^8.3.1", "uuid": "^8.3.1",
"zlib-sync": "^0.1.6" "zlib-sync": "^0.1.6"
} }

View file

@ -1,3 +1,6 @@
exports.commands = new Map(); exports.commands = new Map();
exports.aliases = new Map(); exports.aliases = new Map();
exports.info = new Map(); exports.info = new Map();
exports.prefixCache = new Map();
exports.disabledCache = new Map();

60
utils/convertdb.js Normal file
View file

@ -0,0 +1,60 @@
require("dotenv").config();
const { Pool } = require("pg");
const pool = new Pool({
user: "esmbot",
host: "localhost",
database: "esmbot",
port: 5432
});
const mongoose = require("mongoose");
mongoose.connect(process.env.MONGO, { poolSize: 10, bufferMaxEntries: 0, useNewUrlParser: true, useUnifiedTopology: true });
const guildSchema = new mongoose.Schema({
id: String,
tags: Map,
prefix: String,
disabled: [String],
tagsDisabled: Boolean
});
const Guild = mongoose.model("Guild", guildSchema);
const globalSchema = new mongoose.Schema({
cmdCounts: Map
});
const Global = mongoose.model("Global", globalSchema);
(async () => {
console.log("Migrating guilds...");
const guilds = await Guild.find();
try {
await pool.query("CREATE TABLE guilds ( guild_id VARCHAR(30) NOT NULL, tags json NOT NULL, prefix VARCHAR(15) NOT NULL, warns json NOT NULL, disabled text ARRAY NOT NULL, tags_disabled boolean NOT NULL )");
} catch {
console.log("Skipping table creation due to error...");
}
for (const guild of guilds) {
console.log(guild.tagsDisabled);
if ((await pool.query("SELECT * FROM guilds WHERE guild_id = $1", [guild.id])).rows.length !== 0) {
await pool.query("UPDATE guilds SET tags = $1, prefix = $2, warns = $3, disabled = $4, tags_disabled = $5 WHERE guild_id = $6", [guild.tags, guild.prefix, {}, guild.disabled ? guild.disabled : guild.disabledChannels, guild.tagsDisabled === undefined ? false : guild.tagsDisabled, guild.id]);
} else {
await pool.query("INSERT INTO guilds (guild_id, tags, prefix, warns, disabled, tags_disabled) VALUES ($1, $2, $3, $4, $5, $6)", [guild.id, guild.tags, guild.prefix, {}, guild.disabled ? guild.disabled : guild.disabledChannels, guild.tagsDisabled === undefined ? false : guild.tagsDisabled]);
}
console.log(`Migrated guild with ID ${guild.id}`);
}
console.log("Migrating command counts...");
const global = await Global.findOne();
try {
await pool.query("CREATE TABLE counts ( command VARCHAR NOT NULL, count integer NOT NULL )");
} catch {
console.log("Skipping table creation due to error...");
}
console.log(global);
for (const [key, value] of global.cmdCounts) {
if ((await pool.query("SELECT * FROM counts WHERE command = $1", [key])).rows.length !== 0) {
await pool.query("UPDATE counts SET count = $1 WHERE command = $2", [value, key]);
} else {
await pool.query("INSERT INTO counts (command, count) VALUES ($1, $2)", [key, value]);
}
console.log(`Migrated counts for command ${key}`);
}
console.log("Done!");
return;
})();

View file

@ -1,21 +1,249 @@
// database stuff // database stuff
const mongoose = require("mongoose"); const logger = require("./logger.js");
mongoose.connect(process.env.MONGO, { poolSize: 10, bufferMaxEntries: 0, useNewUrlParser: true, useUnifiedTopology: true }); const collections = require("../utils/collections.js");
const guildSchema = new mongoose.Schema({ const misc = require("./misc.js");
if (process.env.DB === "mongo") {
const mongoose = require("mongoose");
mongoose.connect(process.env.MONGO, {
poolSize: 10,
bufferMaxEntries: 0,
useNewUrlParser: true,
useUnifiedTopology: true,
});
const guildSchema = new mongoose.Schema({
id: String, id: String,
tags: Map, tags: Map,
prefix: String, prefix: String,
warns: Map, disabled: [String],
disabledChannels: [String],
tagsDisabled: Boolean tagsDisabled: Boolean
}); });
const Guild = mongoose.model("Guild", guildSchema); const Guild = mongoose.model("Guild", guildSchema);
const globalSchema = new mongoose.Schema({ const globalSchema = new mongoose.Schema({
cmdCounts: Map cmdCounts: Map,
}); });
const Global = mongoose.model("Global", globalSchema); const Global = mongoose.model("Global", globalSchema);
exports.guilds = Guild; exports.guilds = Guild;
exports.global = Global; exports.global = Global;
exports.connection = mongoose.connection; exports.connection = mongoose.connection;
} else if (process.env.DB === "postgres") {
const { Pool } = require("pg");
const pool = new Pool({
user: "esmbot",
host: "localhost",
database: "esmbot",
port: 5432
});
exports.connection = pool;
}
exports.getGuild = async (query) => {
if (process.env.DB === "mongo") {
return await this.guilds.findOne({ id: query });
} else if (process.env.DB === "postgres") {
return (await this.connection.query("SELECT * FROM guilds WHERE guild_id = $1", [query])).rows[0];
}
};
exports.setPrefix = async (prefix, guild) => {
if (process.env.DB === "mongo") {
const guildDB = await this.getGuild(guild.id);
guildDB.prefix = prefix;
await guildDB.save();
collections.prefixCache.set(guild.id, prefix);
} else if (process.env.DB === "postgres") {
await this.connection.query("UPDATE guilds SET prefix = $1 WHERE guild_id = $2", [prefix, guild.id]);
collections.prefixCache.set(guild.id, prefix);
}
};
exports.setTag = async (name, content, guild) => {
if (process.env.DB === "mongo") {
const guildDB = await this.getGuild(guild.id);
guildDB.tags[name] = content;
await guildDB.save();
} else if (process.env.DB === "postgres") {
const guildDB = await this.getGuild(guild.id);
guildDB.tags[name] = content;
await this.connection.query("UPDATE guilds SET tags = $1 WHERE guild_id = $2", [guildDB.tags, guild.id]);
}
};
exports.removeTag = async (name, guild) => {
if (process.env.DB === "mongo") {
const guildDB = await this.getGuild(guild.id);
delete guildDB.tags[name];
await guildDB.save();
} else if (process.env.DB === "postgres") {
const guildDB = await this.getGuild(guild.id);
delete guildDB.tags[name];
await this.connection.query("UPDATE guilds SET tags = $1 WHERE guild_id = $2", [guildDB.tags, guild.id]);
}
};
exports.toggleTags = async (guild) => {
if (process.env.DB === "mongo") {
const guildDB = await this.getGuild(guild.id);
guildDB.tagsDisabled = !guildDB.tagsDisabled;
await guildDB.save();
return guildDB.tagsDisabled;
} else if (process.env.DB === "postgres") {
const guildDB = await this.getGuild(guild.id);
guildDB.tags_disabled = !guildDB.tags_disabled;
await this.connection.query("UPDATE guilds SET tags_disabled = $1 WHERE guild_id = $2", [guildDB.tags_disabled, guild.id]);
return guildDB.tags_disabled;
}
};
exports.disableChannel = async (channel) => {
if (process.env.DB === "mongo") {
const guildDB = await this.getGuild(channel.guild.id);
guildDB.disabled.push(channel.id);
await guildDB.save();
collections.disabledCache.set(channel.guild.id, guildDB.disabled);
} else if (process.env.DB === "postgres") {
const guildDB = await this.getGuild(channel.guild.id);
await this.connection.query("UPDATE guilds SET disabled = $1 WHERE guild_id = $2", [[...guildDB.disabled, channel.id], channel.guild.id]);
collections.disabledCache.set(channel.guild.id, guildDB.disabled);
}
};
exports.enableChannel = async (channel) => {
if (process.env.DB === "mongo") {
const guildDB = await this.getGuild(channel.guild.id);
guildDB.disabled = guildDB.disabled.filter(item => item !== channel.id);
await guildDB.save();
collections.disabledCache.set(channel.guild.id, guildDB.disabled);
} else if (process.env.DB === "postgres") {
const guildDB = await this.getGuild(channel.guild.id);
const newDisabled = guildDB.disabled.filter(item => item !== channel.id);
await this.connection.query("UPDATE guilds SET disabled = $1 WHERE guild_id = $2", [newDisabled, channel.guild.id]);
collections.disabledCache.set(channel.guild.id, guildDB.disabled);
}
};
exports.getCounts = async () => {
if (process.env.DB === "mongo") {
return [...(await this.global.findOne({})).cmdCounts.entries()];
} else if (process.env.DB === "postgres") {
const counts = await this.connection.query("SELECT * FROM counts");
const countArray = [];
for (const { command, count } of counts.rows) {
countArray.push([command, count]);
}
return countArray;
}
};
exports.addCount = async (command) => {
if (process.env.DB === "mongo") {
const global = await this.global.findOne({});
const count = global.cmdCounts.get(command);
global.cmdCounts.set(command, parseInt(count) + 1);
await global.save();
} else if (process.env.DB === "postgres") {
const count = await this.connection.query("SELECT * FROM counts WHERE command = $1", [command]);
await this.connection.query("UPDATE counts SET count = $1 WHERE command = $2", [count.rows[0].count + 1, command]);
}
};
exports.addGuild = async (guild) => {
if (process.env.DB === "mongo") {
const guildDB = new this.guilds({
id: guild.id,
tags: misc.tagDefaults,
prefix: process.env.PREFIX,
disabled: [],
tagsDisabled: false
});
await guildDB.save();
return guildDB;
} else if (process.env.DB === "postgres") {
await this.connection.query("INSERT INTO guilds (guild_id, tags, prefix, warns, disabled, tags_disabled) VALUES ($1, $2, $3, $4, $5, $6)", [guild.id, misc.tagDefaults, process.env.PREFIX, {}, [], false]);
return await this.getGuild(guild.id);
}
};
exports.fixGuild = async (guild) => {
if (process.env.DB === "mongo") {
const guildDB = await this.guilds.findOne({ id: guild.id });
if (!guildDB) {
logger.log(`Registering guild database entry for guild ${guild.id}...`);
return await this.addGuild(guild);
} else {
if (!guildDB.disabled && guildDB.disabledChannels) {
guildDB.set("disabled", guildDB.disabledChannels);
guildDB.set("disabledChannels", undefined);
await guildDB.save();
return guildDB;
}
}
} else if (process.env.DB === "postgres") {
const guildDB = await this.connection.query("SELECT * FROM guilds WHERE guild_id = $1", [guild.id]);
if (guildDB.rows.length === 0) {
logger.log(`Registering guild database entry for guild ${guild.id}...`);
return await this.addGuild(guild);
}
}
};
exports.handleCounts = async () => {
if (process.env.DB === "mongo") {
const global = await this.global.findOne({});
if (!global) {
const countObject = {};
for (const command of collections.commands.keys()) {
countObject[command] = 0;
}
const newGlobal = new this.global({
cmdCounts: countObject
});
await newGlobal.save();
} else {
const exists = [];
for (const command of collections.commands.keys()) {
if (!global.cmdCounts.has(command)) {
global.cmdCounts.set(command, 0);
}
exists.push(command);
}
for (const command of global.cmdCounts.keys()) {
if (!exists.includes(command)) {
global.cmdCounts.set(command, undefined);
}
}
await global.save();
}
} else if (process.env.DB === "postgres") {
let counts;
try {
counts = await this.connection.query("SELECT * FROM counts");
} catch {
counts = { rows: [] };
}
if (!counts.rows[0]) {
for (const command of collections.commands.keys()) {
await this.connection.query("INSERT INTO counts (command, count) VALUES ($1, $2)", [command, 0]);
}
} else {
const exists = [];
for (const command of collections.commands.keys()) {
const count = await this.connection.query("SELECT * FROM counts WHERE command = $1", [command]);
if (!count.rows[0]) {
await this.connection.query("INSERT INTO counts (command, count) VALUES ($1, $2)", [command, 0]);
}
exists.push(command);
}
for (const { command } of counts.rows) {
if (!exists.includes(command)) {
await this.connection.query("DELETE FROM counts WHERE command = $1", [command]);
}
}
}
}
};

View file

@ -15,7 +15,6 @@ Default prefix is \`&\`.
## Table of Contents ## Table of Contents
+ [**General**](#💻-general) + [**General**](#💻-general)
+ [**Moderation**](#🔨-moderation)
+ [**Tags**](#🏷-tags) + [**Tags**](#🏷-tags)
+ [**Fun**](#👌-fun) + [**Fun**](#👌-fun)
+ [**Image Editing**](#🖼-image-editing) + [**Image Editing**](#🖼-image-editing)
@ -25,7 +24,6 @@ Default prefix is \`&\`.
const commands = collections.commands; const commands = collections.commands;
const categories = { const categories = {
general: ["## 💻 General"], general: ["## 💻 General"],
moderation: ["## 🔨 Moderation"],
tags: ["## 🏷️ Tags"], tags: ["## 🏷️ Tags"],
fun: ["## 👌 Fun"], fun: ["## 👌 Fun"],
images: ["## 🖼️ Image Editing", "> These commands support the PNG, JPEG, WEBP, and GIF formats. (GIF support is currently experimental)"], images: ["## 🖼️ Image Editing", "> These commands support the PNG, JPEG, WEBP, and GIF formats. (GIF support is currently experimental)"],
@ -55,7 +53,7 @@ Default prefix is \`&\`.
categories.music.push(`+ **${command}**${params ? ` ${params}` : ""} - ${description}`); categories.music.push(`+ **${command}**${params ? ` ${params}` : ""} - ${description}`);
} }
} }
fs.writeFile(output, `${template}\n${categories.general.join("\n")}\n\n${categories.moderation.join("\n")}\n\n${categories.tags.join("\n")}\n\n${categories.fun.join("\n")}\n\n${categories.images.join("\n")}\n\n${categories.soundboard.join("\n")}\n\n${categories.music.join("\n")}`, () => { fs.writeFile(output, `${template}\n${categories.general.join("\n")}\n\n${categories.tags.join("\n")}\n\n${categories.fun.join("\n")}\n\n${categories.images.join("\n")}\n\n${categories.soundboard.join("\n")}\n\n${categories.music.join("\n")}`, () => {
logger.log("The help docs have been generated."); logger.log("The help docs have been generated.");
}); });
}; };

View file

@ -65,21 +65,18 @@ exports.run = (object, fromAPI = false) => {
const socket = dgram.createSocket("udp4"); const socket = dgram.createSocket("udp4");
const data = Buffer.concat([Buffer.from([0x1]), Buffer.from(JSON.stringify(object))]); const data = Buffer.concat([Buffer.from([0x1]), Buffer.from(JSON.stringify(object))]);
let timeout = setTimeout(() => { const timeout = setTimeout(() => {
reject("Timed out"); reject("Timed out");
}, 25000); }, 25000);
let jobID; let jobID;
socket.on("message", (msg) => { socket.on("message", (msg) => {
clearTimeout(timeout);
const opcode = msg.readUint8(0); const opcode = msg.readUint8(0);
const req = msg.slice(37, msg.length); const req = msg.slice(37, msg.length);
const uuid = msg.slice(1, 36).toString(); const uuid = msg.slice(1, 36).toString();
if (opcode === 0x0) { if (opcode === 0x0) {
clearTimeout(timeout);
jobID = uuid; jobID = uuid;
timeout = setTimeout(() => {
reject("Timed out");
}, 300000);
} else if (opcode === 0x1) { } else if (opcode === 0x1) {
if (jobID === uuid) { if (jobID === uuid) {
const client = net.createConnection(req.toString(), currentServer); const client = net.createConnection(req.toString(), currentServer);