diff --git a/.env.example b/.env.example index b112402..943205d 100644 --- a/.env.example +++ b/.env.example @@ -7,8 +7,12 @@ NODE_ENV=development # Put Discord token here TOKEN= + +# Put database type here +DB=mongo # Put MongoDB database URL here MONGO=mongodb://localhost:27017/esmBot + # Put snowflake ID of bot owner here OWNER= diff --git a/app.js b/app.js index c2ee1b4..663411f 100644 --- a/app.js +++ b/app.js @@ -59,9 +59,15 @@ async function init() { handler.unload(command); } 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); + }); + } else if (process.env.DB === "postgres") { + db.connection.end(); process.exit(0); - }); + } }); } diff --git a/commands/ban.js b/commands/ban.js deleted file mode 100644 index aa4eaff..0000000 --- a/commands/ban.js +++ /dev/null @@ -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(/^?$/) && args[0] >= 21154535154122752) { - try { - const id = args[0].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]"; \ No newline at end of file diff --git a/commands/channel.js b/commands/channel.js index d9b6cc3..0fa0721 100644 --- a/commands/channel.js +++ b/commands/channel.js @@ -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 (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!`; - 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") { + let channel; if (args[1] && args[1].match(/^?$/) && args[1] >= 21154535154122752) { const id = args[1].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!`; - guildDB.disabledChannels.push(id); + if (guildDB.disabled.includes(id)) return `${message.author.mention}, I'm already disabled in this channel!`; + channel = message.channel.guild.channels.get(id); } else { - if (guildDB.disabledChannels.includes(message.channel.id)) return `${message.author.mention}, I'm already disabled in this channel!`; - guildDB.disabledChannels.push(message.channel.id); + if (guildDB.disabled.includes(message.channel.id)) return `${message.author.mention}, I'm already disabled in this channel!`; + 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\`.`; } else if (args[0].toLowerCase() === "enable") { + let channel; if (args[1] && args[1].match(/^?$/) && args[1] >= 21154535154122752) { const id = args[1].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!`; - guildDB.disabledChannels = guildDB.disabledChannels.filter(item => item !== id); + if (!guildDB.disabled.includes(id)) return `${message.author.mention}, I'm not disabled in that channel!`; + channel = message.channel.guild.channels.get(id); } else { - if (!guildDB.disabledChannels.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 ); + if (!guildDB.disabled.includes(message.channel.id)) return `${message.author.mention}, I'm not disabled in this channel!`; + channel = message.channel; } - await guildDB.save(); + + await db.enableChannel(channel); return `${message.author.mention}, I have been re-enabled in this channel.`; } }; diff --git a/commands/count.js b/commands/count.js index 61cd79f..e3ef942 100644 --- a/commands/count.js +++ b/commands/count.js @@ -5,9 +5,9 @@ const database = require("../utils/database.js"); 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("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 sortedValues = [...counts.entries()].sort((a, b) => { + const sortedValues = counts.sort((a, b) => { return b[1] - a[1]; }); for (const [key, value] of sortedValues) { diff --git a/commands/help.js b/commands/help.js index fca190d..0238f8b 100644 --- a/commands/help.js +++ b/commands/help.js @@ -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"]; 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 aliases = collections.aliases; 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 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 = { "embed": { "author": { @@ -28,7 +33,7 @@ exports.run = async (message, args) => { "value": info.aliases ? info.aliases.join(", ") : "None" }, { "name": "Times Used", - "value": counts.get(command), + "value": counts[command], "inline": true }, { "name": "Parameters", diff --git a/commands/kick.js b/commands/kick.js deleted file mode 100644 index 1ba0ba9..0000000 --- a/commands/kick.js +++ /dev/null @@ -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]"; \ No newline at end of file diff --git a/commands/prefix.js b/commands/prefix.js index 05cd617..9a2c9ba 100644 --- a/commands/prefix.js +++ b/commands/prefix.js @@ -2,11 +2,10 @@ const database = require("../utils/database.js"); exports.run = async (message, args) => { 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 (!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 guild.save(); + await database.setPrefix(args[0], message.channel.guild); return `The prefix has been changed to ${args[0]}.`; } else { return `${message.author.mention}, the current prefix is \`${guild.prefix}\`.`; diff --git a/commands/purge.js b/commands/purge.js deleted file mode 100644 index 5982c68..0000000 --- a/commands/purge.js +++ /dev/null @@ -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]"; \ No newline at end of file diff --git a/commands/tags.js b/commands/tags.js index fe4da67..3951455 100644 --- a/commands/tags.js +++ b/commands/tags.js @@ -5,45 +5,45 @@ const { random } = require("../utils/misc.js"); exports.run = async (message, args) => { 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 }); - if (guild.tagsDisabled && args[0].toLowerCase() !== ("enable" || "disable")) return; + const guild = await database.getGuild(message.channel.guild.id); + + 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!`; - const tags = guild.tags; - const blacklist = ["add", "edit", "remove", "delete", "list", "random"]; + const tags = guild.tags instanceof Map ? Object.fromEntries(guild.tags) : guild.tags; + const blacklist = ["add", "edit", "remove", "delete", "list", "random", "own", "owner", "enable", "disable"]; switch (args[0].toLowerCase()) { case "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 (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); if (result) return result; return `${message.author.mention}, the tag \`${args[1].toLowerCase()}\` has been added!`; case "delete": case "remove": 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.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!`; - tags.set(args[1].toLowerCase(), undefined); - await guild.save(); + if (!tags[args[1].toLowerCase()]) return `${message.author.mention}, this tag doesn't exist!`; + 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 database.removeTag(args[1].toLowerCase(), message.channel.guild); return `${message.author.mention}, the tag \`${args[1].toLowerCase()}\` has been deleted!`; case "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.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()]) return `${message.author.mention}, this tag doesn't exist!`; + 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); return `${message.author.mention}, the tag \`${args[1].toLowerCase()}\` has been edited!`; case "own": 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 (!tags.has(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}\`).`; + 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[args[1].toLowerCase()].author).username}#${client.users.get(tags[args[1].toLowerCase()].author).discriminator}** (\`${tags[args[1].toLowerCase()].author}\`).`; 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("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 embeds = []; - var groups = [...tags.keys()].map((item, index) => { - return index % pageSize === 0 ? [...tags.keys()].slice(index, index + pageSize) : null; + var groups = Object.keys(tags).map((item, index) => { + return index % pageSize === 0 ? Object.keys(tags).slice(index, index + pageSize) : null; }).filter((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!`; return paginator(message, embeds); case "random": - return random([...tags])[1].content; + return tags[random(Object.keys(tags))].content; case "enable": 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!`; - var status; - if (guild.tagsDisabled) { - 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"}.`; + var toggleResult = await database.toggleTags(message.channel.guild); + 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"}.`; default: - if (!tags.has(args[0].toLowerCase())) return `${message.author.mention}, this tag doesn't exist!`; - return tags.get(args[0].toLowerCase()).content; + if (!tags[args[0].toLowerCase()]) return `${message.author.mention}, this tag doesn't exist!`; + 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 (message.attachments.length !== 0 && content) { - guild.tags.set(name, { content: `${content} ${message.attachments[0].url}`, author: message.author.id }); - await guild.save(); + await database.setTag(name, { content: `${content} ${message.attachments[0].url}`, author: message.author.id }, message.channel.guild); } else if (message.attachments.length !== 0) { - guild.tags.set(name, { content: message.attachments[0].url, author: message.author.id }); - await guild.save(); + await database.setTag(name, { content: message.attachments[0].url, author: message.author.id }, message.channel.guild); } else { - guild.tags.set(name, { content: content, author: message.author.id }); - await guild.save(); + await database.setTag(name, { content: content, author: message.author.id }, message.channel.guild); } return; }; diff --git a/commands/warn.js b/commands/warn.js deleted file mode 100644 index d8810ac..0000000 --- a/commands/warn.js +++ /dev/null @@ -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}"; \ No newline at end of file diff --git a/events/guildCreate.js b/events/guildCreate.js index dfb47f4..8e1b0b1 100644 --- a/events/guildCreate.js +++ b/events/guildCreate.js @@ -1,18 +1,8 @@ const db = require("../utils/database.js"); const logger = require("../utils/logger.js"); -const misc = require("../utils/misc.js"); // run when the bot is added to a guild module.exports = async (guild) => { logger.log("info", `[GUILD JOIN] ${guild.name} (${guild.id}) added the bot.`); - const guildDB = new db.guilds({ - id: guild.id, - tags: misc.tagDefaults, - prefix: process.env.PREFIX, - warns: {}, - disabledChannels: [], - tagsDisabled: false - }); - await guildDB.save(); - return guildDB; + await db.addGuild(guild); }; diff --git a/events/messageCreate.js b/events/messageCreate.js index ebcd08a..cda5c63 100644 --- a/events/messageCreate.js +++ b/events/messageCreate.js @@ -3,7 +3,6 @@ const client = require("../utils/client.js"); const database = require("../utils/database.js"); const logger = require("../utils/logger.js"); const collections = require("../utils/collections.js"); -const guildCreate = require("./guildCreate.js"); const commands = [...collections.aliases.keys(), ...collections.commands.keys()]; // run when someone sends a message @@ -24,13 +23,21 @@ module.exports = async (message) => { } if (!valid) return; - // prefix can be a mention or a set of special characters - let guildDB = message.channel.guild ? await database.guilds.findOne({ id: message.channel.guild.id }).lean().exec() : null; - if (message.channel.guild && !guildDB) { - guildDB = await guildCreate(message.channel.guild); + let prefixCandidate; + if (collections.prefixCache.has(message.channel.guild.id)) { + prefixCandidate = collections.prefixCache.get(message.channel.guild.id); + } 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); + } + prefixCandidate = guildDB.prefix; + collections.prefixCache.set(message.channel.guild.id, guildDB.prefix); } - // there's a 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}> ` : 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 if (message.content.startsWith(prefix) === false) return; @@ -41,7 +48,14 @@ module.exports = async (message) => { const command = args.shift().toLowerCase(); // 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 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 logger.log("info", `${message.author.username} (${message.author.id}) ran command ${command}`); try { - const global = (await database.global.findOne({}).exec()); - 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(); + await database.addCount(collections.aliases.has(command) ? collections.aliases.get(command) : command); 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)) { await client.createMessage(message.channel.id, result); diff --git a/events/ready.js b/events/ready.js index 3ac1392..6c24998 100644 --- a/events/ready.js +++ b/events/ready.js @@ -1,6 +1,5 @@ const client = require("../utils/client.js"); const database = require("../utils/database.js"); -const collections = require("../utils/collections.js"); const logger = require("../utils/logger.js"); const messages = require("../messages.json"); const misc = require("../utils/misc.js"); @@ -16,58 +15,7 @@ module.exports = async () => { // connect to lavalink if (!soundPlayer.status && !soundPlayer.connected) await soundPlayer.connect(); - // make sure settings/tags exist - 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(); - } + await database.handleCounts(); // generate docs if (helpGenerator && first) await helpGenerator(process.env.OUTPUT); @@ -104,16 +52,8 @@ module.exports = async () => { try { const stream = twitter.client.statuses.filter(`@${process.env.HANDLE}`); stream.on("data", async (tweet) => { - if ( - tweet.user.screen_name !== "esmBot_" && - !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}`); - } + if (tweet.user.screen_name !== "esmBot_" && !blocks.ids.includes(tweet.user.id_str)) { + const tweetContent = await misc.getTweet(twitter.tweets, true).replace(/{{user}}/gm, `@${tweet.user.screen_name}`); const payload = { status: `@${tweet.user.screen_name} ${tweetContent}`, in_reply_to_status_id: tweet.id_str, diff --git a/package-lock.json b/package-lock.json index f3c80c0..7b06d0b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -63,11 +63,30 @@ "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.1.1.tgz", "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": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.5.tgz", "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": { "version": "14.11.5", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.11.5.tgz", @@ -238,6 +257,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", + "optional": true, "requires": { "readable-stream": "^2.3.5", "safe-buffer": "^5.1.1" @@ -246,7 +266,8 @@ "bluebird": { "version": "3.5.1", "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": { "version": "1.19.0", @@ -300,7 +321,8 @@ "bson": { "version": "1.1.5", "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": { "version": "5.4.3", @@ -340,6 +362,12 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", "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": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.1.tgz", @@ -476,12 +504,23 @@ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" }, "color": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/color/-/color-3.1.2.tgz", - "integrity": "sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/color/-/color-3.1.3.tgz", + "integrity": "sha512-xgXAcTHa2HeFCGLE9Xs/R82hujGtu9Jd9x4NW3T34+OMs7VoPsjwzRczKHvTAHeJwWFwX5j15+MgAppE8ztObQ==", "requires": { "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": { @@ -663,7 +702,8 @@ "denque": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", - "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==" + "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==", + "optional": true }, "depd": { "version": "1.1.2", @@ -780,9 +820,9 @@ "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" }, "eris": { - "version": "0.13.3", - "resolved": "https://registry.npmjs.org/eris/-/eris-0.13.3.tgz", - "integrity": "sha512-WBtLyknOWZpYZL9yPhez0oKUWvYpunSg43hGxawwjwSf3gFXmbEPYrT8KlmZXtpJnX16eQ7mzIq+MgSh3LarEg==", + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/eris/-/eris-0.13.4.tgz", + "integrity": "sha512-IFA14nasCig8xp8cVCULvzBuJ0qpYqJ3XyEtm9OLdC177DYDCJ9QM2Aq+KOpejIVl7838n9AyRlLI6w9Eu3PiQ==", "requires": { "opusscript": "^0.0.7", "tweetnacl": "^1.0.1", @@ -1606,9 +1646,10 @@ "integrity": "sha512-zCTP6Qd/WwjrpuHFkJuXc5opRdKprUr7eI7+JCCtcetThJt45qptu82MWQ+eET+FtDrMo7+BYjo3iD0XIq1L9Q==" }, "kareem": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.1.tgz", - "integrity": "sha512-l3hLhffs9zqoDe8zjmb/mAN4B8VT3L56EUvKNqLFVs9YlFA+zx7ke1DO8STAdDyYNkeSo1nKmjuvQeI12So8Xw==" + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.2.tgz", + "integrity": "sha512-STHz9P7X2L4Kwn72fA4rGyqyXdmrMSdxqHx9IXon/FXluXieaFA6KJ2upcHAHxQPQ0LeM/OjLrhFxifHewOALQ==", + "optional": true }, "kind-of": { "version": "3.2.2", @@ -1692,6 +1733,14 @@ "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": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -1783,6 +1832,7 @@ "version": "0.5.5", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, "requires": { "minimist": "^1.2.5" }, @@ -1790,7 +1840,8 @@ "minimist": { "version": "1.2.5", "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==" }, "mongodb": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.2.tgz", - "integrity": "sha512-sSZOb04w3HcnrrXC82NEh/YGCmBuRgR+C1hZgmmv4L6dBz4BkRse6Y8/q/neXer9i95fKUBbFi4KgeceXmbsOA==", + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.3.tgz", + "integrity": "sha512-rOZuR0QkodZiM+UbQE5kDsJykBqWi0CL4Ec2i1nrGrUI3KO11r6Fbxskqmq3JK2NH7aW4dcccBuUujAP0ERl5w==", + "optional": true, "requires": { "bl": "^2.2.1", "bson": "^1.1.4", @@ -1823,16 +1875,18 @@ } }, "mongoose": { - "version": "5.10.8", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.10.8.tgz", - "integrity": "sha512-hbpFhOU6rWkWPkekUeSJxqWwzsjVQZ9xPg4WmWA1HJ8YDvjyNye1xbp82fw67BpnyvcjHxyU3/YhujsOCx55yw==", + "version": "5.11.8", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.11.8.tgz", + "integrity": "sha512-RRfrYLg7pyuyx7xu5hwadjIZZJB9W2jqIMkL1CkTmk/uOCX3MX2tl4BVIi2rJUtgMNwn6dy3wBD3soB8I9Nlog==", + "optional": true, "requires": { + "@types/mongodb": "^3.5.27", "bson": "^1.1.4", - "kareem": "2.3.1", - "mongodb": "3.6.2", + "kareem": "2.3.2", + "mongodb": "3.6.3", "mongoose-legacy-pluralize": "1.0.2", - "mpath": "0.7.0", - "mquery": "3.2.2", + "mpath": "0.8.1", + "mquery": "3.2.3", "ms": "2.1.2", "regexp-clone": "1.0.0", "safe-buffer": "5.2.1", @@ -1843,29 +1897,34 @@ "ms": { "version": "2.1.2", "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": { "version": "5.2.1", "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": { "version": "1.0.2", "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": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.7.0.tgz", - "integrity": "sha512-Aiq04hILxhz1L+f7sjGyn7IxYzWm1zLNNXcfhDtx04kZ2Gk7uvFdgZ8ts1cWa/6d0TQmag2yR8zSGZUmp0tFNg==" + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.8.1.tgz", + "integrity": "sha512-norEinle9aFc05McBawVPwqgFZ7npkts9yu17ztIVLwPwO9rq0OTp89kGVTqvv5rNLMz96E5iWHpVORjI411vA==", + "optional": true }, "mquery": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/mquery/-/mquery-3.2.2.tgz", - "integrity": "sha512-XB52992COp0KP230I3qloVUbkLUxJIu328HBP2t2EsxSFtf4W1HPSOBWOXf1bqxK4Xbb66lfMJ+Bpfd9/yZE1Q==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-3.2.3.tgz", + "integrity": "sha512-cIfbP4TyMYX+SkaQ2MntD+F2XbqaBHUYWk3j+kqdDztPWok3tgyssOZxMHMtzbV1w9DaSlvEea0Iocuro41A4g==", + "optional": true, "requires": { "bluebird": "3.5.1", "debug": "3.1.0", @@ -1878,6 +1937,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "optional": true, "requires": { "ms": "2.0.0" } @@ -1885,7 +1945,8 @@ "ms": { "version": "2.0.0", "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 }, "node-abi": { - "version": "2.19.1", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.19.1.tgz", - "integrity": "sha512-HbtmIuByq44yhAzK7b9j/FelKlHYISKQn0mtvcBrU5QBkhoCMp5bu8Hv5AI34DcKfOAcJBcOEMwLlwO62FFu9A==", + "version": "2.19.3", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.19.3.tgz", + "integrity": "sha512-9xZrlyfvKhWme2EXFKQhZRp1yNWT/uI1luYPr3sFl+H4keYY4xR+1jO7mvTTijIsHf1M+QDe9uWuKeEpLInIlg==", "requires": { "semver": "^5.4.1" } @@ -2106,6 +2167,12 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "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": { "version": "1.0.1", "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", "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": { "version": "4.2.0", "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", "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": { - "version": "5.3.5", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.3.5.tgz", - "integrity": "sha512-YmMO7dph9CYKi5IR/BzjOJlRzpxGGVo1EsLSUZ0mt/Mq0HWZIHOKHHcHdT69yG54C9m6i45GpItwRHpk0Py7Uw==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.0.0.tgz", + "integrity": "sha512-h2ZJ1PXHKWZpp1caLw0oX9sagVpL2YTk+ZwInQbQ3QqNd4J03O6MpFNmMTJlkfgPENWqe5kP0WjQLqz5OjLfsw==", "requires": { "detect-libc": "^1.0.3", "expand-template": "^2.0.3", "github-from-package": "0.0.0", "minimist": "^1.2.3", - "mkdirp": "^0.5.1", + "mkdirp-classic": "^0.5.3", "napi-build-utils": "^1.0.1", "node-abi": "^2.7.0", "noop-logger": "^0.1.1", @@ -2452,7 +2613,8 @@ "regexp-clone": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz", - "integrity": "sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw==" + "integrity": "sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw==", + "optional": true }, "regexpp": { "version": "2.0.1", @@ -2474,6 +2636,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", + "optional": true, "requires": { "resolve-from": "^2.0.0", "semver": "^5.1.0" @@ -2482,7 +2645,8 @@ "resolve-from": { "version": "2.0.0", "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": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.26.1.tgz", - "integrity": "sha512-9MhwS4ys8pnwBH7MtnBdLzUv+cb24QC4xbzzQL6A+1MQ4Se2V6oPHEX8TIGIZUPRKi6S1kJPVNzt/Xqqp6/H3Q==", + "version": "0.26.3", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.26.3.tgz", + "integrity": "sha512-NdEJ9S6AMr8Px0zgtFo1TJjMK/ROMU92MkDtYn2BBrDjIx3YfH9TUyGdzPC+I/L619GeYQc690Vbaxc5FPCCWg==", "requires": { - "color": "^3.1.2", + "array-flatten": "^3.0.0", + "color": "^3.1.3", "detect-libc": "^1.0.3", "node-addon-api": "^3.0.2", "npmlog": "^4.1.2", - "prebuild-install": "^5.3.5", + "prebuild-install": "^6.0.0", "semver": "^7.3.2", "simple-get": "^4.0.0", - "tar-fs": "^2.1.0", + "tar-fs": "^2.1.1", "tunnel-agent": "^0.6.0" }, "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": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==" + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "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": { "version": "7.0.1", "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": { "version": "3.0.2", @@ -2756,7 +2941,8 @@ "sliced": { "version": "1.0.1", "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": { "version": "3.0.3", @@ -2767,6 +2953,28 @@ "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": { "version": "1.0.3", "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", "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": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", "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": { "version": "13.3.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", diff --git a/package.json b/package.json index 920a4a4..4b20e43 100644 --- a/package.json +++ b/package.json @@ -29,13 +29,12 @@ "dotenv": "^8.2.0", "duckduckgo-images-api": "github:benpbolton/duckduckgo-images-api", "emoji-regex": "^8.0.0", - "eris": "^0.13.3", + "eris": "^0.13.4", "file-type": "^13.1.2", "jsqr": "^1.3.1", "lavacord": "^1.1.9", "moment": "^2.29.1", "moment-duration-format": "^2.3.2", - "mongoose": "^5.10.8", "node-addon-api": "^3.0.2", "node-emoji": "^1.10.0", "node-fetch": "^2.6.1", @@ -45,7 +44,7 @@ "puppeteer-extra-plugin-stealth": "^2.6.5", "qrcode": "^1.4.4", "retrotext": "github:TheEssem/retrotext", - "sharp": "^0.26.1", + "sharp": "^0.26.3", "winston": "^3.3.3" }, "devDependencies": { @@ -56,6 +55,9 @@ "bufferutil": "^4.0.1", "erlpack": "github:abalabahaha/erlpack", "express": "^4.17.1", + "mongoose": "^5.11.8", + "pg": "^8.5.1", + "pg-cursor": "^2.5.2", "uuid": "^8.3.1", "zlib-sync": "^0.1.6" } diff --git a/utils/collections.js b/utils/collections.js index a8d6415..343f0ce 100644 --- a/utils/collections.js +++ b/utils/collections.js @@ -1,3 +1,6 @@ exports.commands = new Map(); exports.aliases = new Map(); -exports.info = new Map(); \ No newline at end of file +exports.info = new Map(); + +exports.prefixCache = new Map(); +exports.disabledCache = new Map(); \ No newline at end of file diff --git a/utils/convertdb.js b/utils/convertdb.js new file mode 100644 index 0000000..f4cbb85 --- /dev/null +++ b/utils/convertdb.js @@ -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; +})(); \ No newline at end of file diff --git a/utils/database.js b/utils/database.js index 75c7766..c40d052 100644 --- a/utils/database.js +++ b/utils/database.js @@ -1,21 +1,249 @@ // database stuff -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, - warns: Map, - disabledChannels: [String], - tagsDisabled: Boolean -}); -const Guild = mongoose.model("Guild", guildSchema); +const logger = require("./logger.js"); +const collections = require("../utils/collections.js"); +const misc = require("./misc.js"); -const globalSchema = new mongoose.Schema({ - cmdCounts: Map -}); -const Global = mongoose.model("Global", globalSchema); +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, + tags: Map, + prefix: String, + disabled: [String], + tagsDisabled: Boolean + }); + const Guild = mongoose.model("Guild", guildSchema); -exports.guilds = Guild; -exports.global = Global; -exports.connection = mongoose.connection; \ No newline at end of file + const globalSchema = new mongoose.Schema({ + cmdCounts: Map, + }); + const Global = mongoose.model("Global", globalSchema); + + exports.guilds = Guild; + exports.global = Global; + 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]); + } + } + } + } +}; \ No newline at end of file diff --git a/utils/help.js b/utils/help.js index 712c103..d4f1b6f 100644 --- a/utils/help.js +++ b/utils/help.js @@ -15,7 +15,6 @@ Default prefix is \`&\`. ## Table of Contents + [**General**](#💻-general) -+ [**Moderation**](#🔨-moderation) + [**Tags**](#🏷️-tags) + [**Fun**](#👌-fun) + [**Image Editing**](#🖼️-image-editing) @@ -25,7 +24,6 @@ Default prefix is \`&\`. const commands = collections.commands; const categories = { general: ["## 💻 General"], - moderation: ["## 🔨 Moderation"], tags: ["## 🏷️ Tags"], fun: ["## 👌 Fun"], 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}`); } } - 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."); }); }; \ No newline at end of file diff --git a/utils/image.js b/utils/image.js index 7066e51..4ae726f 100644 --- a/utils/image.js +++ b/utils/image.js @@ -65,21 +65,18 @@ exports.run = (object, fromAPI = false) => { const socket = dgram.createSocket("udp4"); const data = Buffer.concat([Buffer.from([0x1]), Buffer.from(JSON.stringify(object))]); - let timeout = setTimeout(() => { + const timeout = setTimeout(() => { reject("Timed out"); }, 25000); let jobID; socket.on("message", (msg) => { - clearTimeout(timeout); const opcode = msg.readUint8(0); const req = msg.slice(37, msg.length); const uuid = msg.slice(1, 36).toString(); if (opcode === 0x0) { + clearTimeout(timeout); jobID = uuid; - timeout = setTimeout(() => { - reject("Timed out"); - }, 300000); } else if (opcode === 0x1) { if (jobID === uuid) { const client = net.createConnection(req.toString(), currentServer);