diff --git a/Main.js b/Main.js index 8e6d641..9439b33 100644 --- a/Main.js +++ b/Main.js @@ -22,6 +22,7 @@ const getColor = require("./resources/getColor"); const requireAll = require("require-all"); const { chatAnswer } = require("./resources/shaChat"); const { init } = require("./cmds/moderation/src/createSchedule"); +const { dbClient } = require("./database/mongo"); const lgr = requireAll({ dirname: join(__dirname, "resources/eventsLogger"), recursive: true }); client.functions = requireAll({ dirname: join(__dirname, "resources"), recursive: true }); @@ -219,6 +220,10 @@ process.on("uncaughtException", e => { process.on("unhandledRejection", e => { console.error(e); errLog(e, null, client); + if (/MongoError: Topology is closed, please connect/.test(e.message)) { + console.log("Trying reconnecting..."); + return dbClient.connect(); + } }); process.on("warning", e => { console.error(e); diff --git a/resources/eventsLogger/guildBanAdd.js b/resources/eventsLogger/guildBanAdd.js index 37ed22b..b475955 100644 --- a/resources/eventsLogger/guildBanAdd.js +++ b/resources/eventsLogger/guildBanAdd.js @@ -10,6 +10,9 @@ const getColor = require("../getColor"); * @returns */ module.exports = async (GUILD, USER) => { + if (!GUILD.DB) await GUILD.dbLoad(); + GUILD.updateCached("systemChannelID", GUILD.systemChannelID); + GUILD.updateCached("iconURL", GUILD.iconURL({ size: 4096, format: "png", dynamic: true })); if (GUILD.DB.eventChannels?.ban) { if (USER.partial) USER = await USER.fetch(); const log = getChannel(GUILD, GUILD.DB.eventChannels.ban); diff --git a/resources/eventsLogger/guildBanRemove.js b/resources/eventsLogger/guildBanRemove.js index f88aaa8..b577aa2 100644 --- a/resources/eventsLogger/guildBanRemove.js +++ b/resources/eventsLogger/guildBanRemove.js @@ -10,6 +10,9 @@ const getColor = require("../getColor"); * @returns */ module.exports = async (GUILD, USER) => { + if (!GUILD.DB) await GUILD.dbLoad(); + GUILD.updateCached("systemChannelID", GUILD.systemChannelID); + GUILD.updateCached("iconURL", GUILD.iconURL({ size: 4096, format: "png", dynamic: true })); if (GUILD.DB.eventChannels?.unban) { if (USER.partial) USER = await USER.fetch(); const log = getChannel(GUILD, GUILD.DB.eventChannels.unban); diff --git a/resources/eventsLogger/guildMemberAdd.js b/resources/eventsLogger/guildMemberAdd.js index fe8dcb4..fc8a51b 100644 --- a/resources/eventsLogger/guildMemberAdd.js +++ b/resources/eventsLogger/guildMemberAdd.js @@ -12,6 +12,9 @@ const { GuildMember } = require("discord.js"), * @returns */ module.exports = async (member) => { + if (!member.guild.DB) await member.guild.dbLoad(); + member.guild.updateCached("systemChannelID", member.guild.systemChannelID); + member.guild.updateCached("iconURL", member.guild.iconURL({ size: 4096, format: "png", dynamic: true })); if (!member.DB) await member.dbLoad(); if (member.DB.leaveRoles?.length && member.guild.me.hasPermission("MANAGE_ROLES")) { await member.roles.add(member.DB.leaveRoles, "Automatic roles recovery").then(() => console.log("AUTO ROLES RECOVERY:", diff --git a/resources/eventsLogger/guildMemberRemove.js b/resources/eventsLogger/guildMemberRemove.js index c8cab61..a1869cf 100644 --- a/resources/eventsLogger/guildMemberRemove.js +++ b/resources/eventsLogger/guildMemberRemove.js @@ -12,6 +12,9 @@ Settings.defaultZone = "utc"; * @returns */ module.exports = async (member) => { + if (!member.guild.DB) await member.guild.dbLoad(); + member.guild.updateCached("systemChannelID", member.guild.systemChannelID); + member.guild.updateCached("iconURL", member.guild.iconURL({ size: 4096, format: "png", dynamic: true })); const RO = member.roles.cache.sort((a, b) => b.position - a.position).map(r => r.id).slice(0, -1); if (member.guild.DB.eventChannels?.leave) { const log = getChannel(member, member.guild.DB.eventChannels.leave); diff --git a/resources/eventsLogger/guildMemberUpdate.js b/resources/eventsLogger/guildMemberUpdate.js index 4a557ad..a28f11d 100644 --- a/resources/eventsLogger/guildMemberUpdate.js +++ b/resources/eventsLogger/guildMemberUpdate.js @@ -10,6 +10,9 @@ const getColor = require("../getColor"); * @returns */ module.exports = async (memberold, membernew) => { + if (!membernew.guild.DB) await membernew.guild.dbLoad(); + membernew.guild.updateCached("systemChannelID", membernew.guild.systemChannelID); + membernew.guild.updateCached("iconURL", membernew.guild.iconURL({ size: 4096, format: "png", dynamic: true })); const NEWAV = membernew.user.displayAvatarURL({ format: "png", size: 4096, dynamic: true }); if (!membernew.guild.DB.eventChannels?.memberRole && !membernew.guild.DB.eventChannels?.member) { if (membernew.user.DB.cachedAvatarURL != NEWAV) { @@ -49,8 +52,10 @@ module.exports = async (memberold, membernew) => { .setDescription(`**Current role${use2.length > 2 ? "s" : ""}**\n` + (membernew.roles.cache.size > 1 ? "<@&" + use2.slice(0, 80).join(">, <@&") + ">" + (use2.length > 80 ? ` and ${use2.slice(80).length} more...` : "") : "`[NONE]`")); } - if (audit.executor) + if (audit.executor) { + if (!audit.executor.bot) nullReason = true; emb.setAuthor(emb.author.name, audit.executor.displayAvatarURL({ size: 128, format: "png", dynamic: true })); + } } if (membernew.guild.DB.eventChannels?.member && membernew.roles.cache.size === memberold.roles.cache.size) { log = getChannel(membernew, membernew.guild.DB.eventChannels.member); @@ -64,8 +69,10 @@ module.exports = async (memberold, membernew) => { } emb.addField("Current Nickname", "`" + membernew.displayName + "`") .addField("Original Nickname", "`" + memberold.displayName + "`"); - if (audit.executor) + if (audit.executor) { + if (!audit.executor.bot) nullReason = true; emb.setAuthor(emb.author.name, audit.executor.displayAvatarURL({ size: 128, format: "png", dynamic: true })); + } } if (membernew.user.DB.cachedAvatarURL !== NEWAV) { nullReason = true; diff --git a/resources/eventsLogger/guildUpdate.js b/resources/eventsLogger/guildUpdate.js index 99b82ec..23d3948 100644 --- a/resources/eventsLogger/guildUpdate.js +++ b/resources/eventsLogger/guildUpdate.js @@ -1,6 +1,6 @@ 'use strict'; -const { Guild } = require("discord.js"); +const { Guild, MessageEmbed } = require("discord.js"); const { Interval } = require("luxon"); const { intervalToDuration } = require("../../cmds/moderation/src/duration"); const { defaultEventLogEmbed, trySend } = require("../functions"); @@ -12,18 +12,27 @@ const getColor = require("../getColor"); */ module.exports = async (oldGuild, newGuild) => { if (!newGuild.DB) await newGuild.dbLoad(); + const newIcon = newGuild.iconURL({ size: 4096, format: "png", dynamic: true }); if (newGuild.DB.eventChannels.guild) { const logChannel = newGuild.channels.cache.get(newGuild.DB.eventChannels.guild); if (!logChannel) return; - let audit = {}; + let audit = {}, newBanner, oldBanner, newSplash, oldSplash, newSDisc, oldSDisc; + const cached = newGuild.DB.cached; if (newGuild.me.hasPermission("VIEW_AUDIT_LOG")) { audit = (await newGuild.fetchAuditLogs({ "limit": 1, "type": "GUILD_UPDATE" })).entries.first(); } else audit.reason = "Unknown reason"; + const emb = defaultEventLogEmbed(newGuild).setColor(getColor("cyan")); + + if (oldGuild.name !== newGuild.name) { + emb.addField("Name", `Changed from \`${oldGuild.name}\` to \`${newGuild.name}\``); + }; + if (oldGuild.afkChannelID !== newGuild.afkChannelID) { emb.addField("Inactive Channel", "Changed from " + (oldGuild.afkChannelID ? "<#" + oldGuild.afkChannelID + ">" : "`[NONE]`") + " to " + (newGuild.afkChannelID ? "<#" + newGuild.afkChannelID + ">" : "`[NONE]`")); }; + if (oldGuild.afkTimeout !== newGuild.afkTimeout) { const newAfkTDuration = intervalToDuration(Interval.after(new Date(), newGuild.afkTimeout * 1000)).strings.join(" "); @@ -32,10 +41,109 @@ module.exports = async (oldGuild, newGuild) => { emb.addField("Inactive Timeout", "Changed from `" + oldAfkTDuration + "` to `" + newAfkTDuration + "`"); }; - emb.setTitle(`Guild Settings Updated ${audit.executor ? "by `" + audit.executor.tag + "`" : ""}`) - .setDescription(audit.reason || "No reason provided"); - if (audit.executor) + const sysCID = oldGuild.systemChannelID || cached.systemChannelID; + if (sysCID !== newGuild.systemChannelID) { + emb.addField("System Messages Channel", "Changed from " + ( + sysCID ? + "<#" + sysCID + ">" : + "`[NONE]`" + ) + " to " + ( + newGuild.systemChannelID ? + "<#" + newGuild.systemChannelID + ">" : + "`[NONE]`" + ) + ) + }; + + if (oldGuild.systemChannelFlags !== newGuild.systemChannelFlags) { + const oldSCF = oldGuild.systemChannelFlags.serialize(), + newSCF = newGuild.systemChannelFlags.serialize(); + let boostMes = "", welcomeMes = ""; + if (oldSCF.WELCOME_MESSAGE_DISABLED !== newSCF.WELCOME_MESSAGE_DISABLED) + welcomeMes += `\`${newSCF.WELCOME_MESSAGE_DISABLED ? "Disabled" : "Enabled"}\` join notifications\n`; + if (oldSCF.BOOST_MESSAGE_DISABLED !== newSCF.BOOST_MESSAGE_DISABLED) + boostMes += `\`${newSCF.BOOST_MESSAGE_DISABLED ? "Disabled" : "Enabled"}\` boost notifications\n`; + if ((welcomeMes + boostMes).length) emb.addField("System Messages Channel Notifications", (welcomeMes + boostMes).slice(0, -1)); + }; + + if (newGuild.defaultMessageNotifications !== oldGuild.defaultMessageNotifications) { + let oldstr, newstr; + switch (oldGuild.defaultMessageNotifications) { + case "ALL": oldstr = "All Messages"; break; + case "MENTIONS": oldstr = "Only @mentions"; break; + default: console.log("NOT ALL OR MENTIONS:", oldGuild.defaultMessageNotifications); + }; + + switch (newGuild.defaultMessageNotifications) { + case "ALL": newstr = "All Messages"; break; + case "MENTIONS": newstr = "Only @mentions"; break; + default: console.log("NOT ALL OR MENTIONS:", newGuild.defaultMessageNotifications); + }; + + emb.addField("Default Notifications Setting", `Changed from \`${oldstr}\` to \`${newstr}\``); + }; + + if (newGuild.rulesChannelID !== oldGuild.rulesChannelID) { + emb.addField("Rules or Guidelines Channel", `Changed from <#${oldGuild.rulesChannelID}> to <#${newGuild.rulesChannelID}>`); + }; + + if (oldGuild.banner !== newGuild.banner) { + oldBanner = oldGuild.bannerURL({ size: 4096, format: "png" }); + newBanner = newGuild.bannerURL({ size: 4096, format: "png" }); + }; + + if (oldGuild.splash !== newGuild.splash) { + oldSplash = oldGuild.splashURL({ size: 4096, format: "png" }); + newSplash = newGuild.splashURL({ size: 4096, format: "png" }); + }; + + if (oldGuild.discoverySplash !== newGuild.discoverySplash) { + oldSDisc = oldGuild.discoverySplashURL({ size: 4096, format: "png" }); + newSDisc = newGuild.discoverySplashURL({ size: 4096, format: "png" }); + }; + + emb.setTitle(`Server Settings Updated ${audit.executor ? "by `" + audit.executor.tag + "`" : ""}`); + if (audit.executor) { + if (audit.executor.bot) + emb.setDescription(audit.reason || "No reason provided"); emb.setAuthor(emb.author.name, audit.executor.displayAvatarURL({ size: 128, format: "png", dynamic: true })); + }; + + if (cached.iconURL && cached.iconURL !== newIcon) { + const newEmb = new MessageEmbed(emb); + await elseImageEmbed(logChannel, newEmb, "Icon", "This embed's thumbnail is the server's old icon.\nThe image below is the server's new icon.", cached.iconURL, newIcon); + }; + + if (oldBanner || newBanner) { + const newEmb = new MessageEmbed(emb); + await elseImageEmbed(logChannel, newEmb, "Banner", "This embed's thumbnail is the server's old banner.\nThe image below is the server's new banner.", oldBanner, newBanner); + }; + + if (oldSplash || newSplash) { + const newEmb = new MessageEmbed(emb); + await elseImageEmbed(logChannel, newEmb, "Splash Invite", "This embed's thumbnail is the server's old splash invite.\nThe image below is the server's new splash invite.", oldSplash, newSplash); + }; + + if (oldSDisc || newSDisc) { + const newEmb = new MessageEmbed(emb); + await elseImageEmbed(logChannel, newEmb, "Splash Discovery", "This embed's thumbnail is the server's old splash discovery.\nThe image below is the server's new splash discovery.", oldSDisc, newSDisc); + }; + + if (!emb.fields.length) return; + + newGuild.updateCached("systemChannelID", newGuild.systemChannelID); + newGuild.updateCached("iconURL", newIcon); return trySend(newGuild.client, logChannel, emb); } + + newGuild.updateCached("systemChannelID", newGuild.systemChannelID); + newGuild.updateCached("iconURL", newIcon); +} + +async function elseImageEmbed(channel, embed, fieldName, fieldValue, thumbnail, image) { + embed.fields = []; + embed.addField(fieldName, fieldValue) + .setThumbnail(thumbnail) + .setImage(image); + return trySend(channel.client, channel, embed); } \ No newline at end of file diff --git a/resources/eventsLogger/message.js b/resources/eventsLogger/message.js index 3fb2413..00f37fc 100644 --- a/resources/eventsLogger/message.js +++ b/resources/eventsLogger/message.js @@ -28,8 +28,13 @@ async function letsChat(msg) { } } -function run(msg) { +async function run(msg) { msg.channel.pushLastMessagesID(); + if (msg.guild) { + if (!msg.guild.DB) await msg.guild.dbLoad(); + msg.guild.updateCached("systemChannelID", msg.guild.systemChannelID); + msg.guild.updateCached("iconURL", msg.guild.iconURL({ size: 4096, format: "png", dynamic: true })); + } } module.exports = { letsChat, giveNickHeart, run } \ No newline at end of file diff --git a/resources/eventsLogger/messageDelete.js b/resources/eventsLogger/messageDelete.js index cf28828..70defeb 100644 --- a/resources/eventsLogger/messageDelete.js +++ b/resources/eventsLogger/messageDelete.js @@ -11,6 +11,11 @@ const getColor = require("../getColor"); */ module.exports = async (msg) => { if (msg.partial) return; + if (msg.guild) { + if (!msg.guild.DB) await msg.guild.dbLoad(); + msg.guild.updateCached("systemChannelID", msg.guild.systemChannelID); + msg.guild.updateCached("iconURL", msg.guild.iconURL({ size: 4096, format: "png", dynamic: true })); + } const ignored = msg.guild.DB.eventChannels.mesDel?.ignore?.includes(msg.channel.id) ?? false; let check = false; if (msg.channel.id === msg.guild.DB.eventChannels.mesDel?.channel && msg.author ? msg.author !== msg.client.user : false && ignored === false) check = true; @@ -18,7 +23,7 @@ module.exports = async (msg) => { const log = getChannel(msg, msg.guild.DB.eventChannels.mesDel?.channel); if (!log || !msg.author) return; const emb = defaultEventLogEmbed(msg.guild); - let audit; + let audit = {}; if (msg.guild.member(msg.client.user).hasPermission("VIEW_AUDIT_LOG")) { const the = (await msg.guild.fetchAuditLogs({ limit: 1, type: "MESSAGE_DELETE" })).entries.first(); if (the.target.id === msg.id) audit = the; @@ -26,8 +31,6 @@ module.exports = async (msg) => { emb.setColor(getColor("yellow")) .setTitle((!msg.webhookID ? "Message " + msg.id : "Webhook " + msg.webhookID) + " deleted" + (audit?.executor ? ` by \`${audit.executor.tag}\`` : "")) .setDescription(msg.content.length > 0 ? msg.content : "`[EMPTY]`") - .addField("Author", `<@!${msg.author?.id}>\n\`${msg.author?.tag}\`\n(${msg.author?.id})`, true) - .addField("Channel", `<#${msg.channel?.id}>\n\`${msg.channel?.name}\`\n(${msg.channel?.id})`, true) .setURL(msg.url) .setFooter(emb.footer.text, msg.author.displayAvatarURL({ size: 128, format: "png", dynamic: true })); if (audit.executor) @@ -42,6 +45,9 @@ module.exports = async (msg) => { const toField = splitOnLength(arr, 1010, ",\n"); for (let i = 0; i < toField.length; i++) emb.addField(i === 0 ? "Embed" : "​", "```js\n" + toField[i].join(",") + ((i !== toField.length - 1) ? "," : "") + "```"); } + emb.addField("Author", `<@!${msg.author?.id}>\n\`${msg.author?.tag}\`\n(${msg.author?.id})`, true) + .addField("Channel", `<#${msg.channel?.id}>\n\`${msg.channel?.name}\`\n(${msg.channel?.id})`, true); + if (audit.executor?.bot) emb.addField("Reason", audit.reason || "No reason provided"); return trySend(msg.client, log, emb); } } diff --git a/resources/eventsLogger/messageUpdate.js b/resources/eventsLogger/messageUpdate.js index 6444e57..0e62668 100644 --- a/resources/eventsLogger/messageUpdate.js +++ b/resources/eventsLogger/messageUpdate.js @@ -13,6 +13,11 @@ const getColor = require("../getColor"); module.exports = async (msgold, msgnew) => { if (msgnew.partial) msgnew = await msgnew.fetch(); if (msgnew.partial) return; + if (msgnew.guild) { + if (!msgnew.guild.DB) await msgnew.guild.dbLoad(); + msgnew.guild.updateCached("systemChannelID", msgnew.guild.systemChannelID); + msgnew.guild.updateCached("iconURL", msgnew.guild.iconURL({ size: 4096, format: "png", dynamic: true })); + } if (msgnew.content === msgold.content) return; const ignored = msgnew.guild.DB.eventChannels.mesEd?.ignore?.includes(msgnew.channel.id) || false; let check = false; diff --git a/resources/functions.js b/resources/functions.js index fd01b13..18ad116 100644 --- a/resources/functions.js +++ b/resources/functions.js @@ -74,7 +74,7 @@ async function getChannelMessage(msg, MainID, SecondID) { if (SecondID && !/\D/.test(SecondID)) { try { const meschannel = (msg.client.owners.includes(msg.author) ? msg.client : msg.guild).channels.cache.get(MainID); - return meschannel.messages.fetch(SecondID, true); + return meschannel.messages.fetch(SecondID, true).catch(() => { }); } catch { return; } diff --git a/resources/structures.js b/resources/structures.js index 5dd3ed4..801dcd7 100644 --- a/resources/structures.js +++ b/resources/structures.js @@ -19,6 +19,7 @@ Structures.extend("Guild", u => { if (!r) r = {}; if (!r.eventChannels) r.eventChannels = {}; if (!r.settings) r.settings = {}; + if (!r.cached) r.cached = {}; let infractions = new Map(), timedPunishments = new Map(); if (r.infractions) @@ -137,6 +138,24 @@ Structures.extend("Guild", u => { console.log("REMOVED TIMEDPUNISHMENT"); return ret; } + + async setCached(key, value) { + this.DB.cached[key] = value; + await this.setDb("cached", this.DB.cached); + console.log("SET CACHED", key, value); + return this.DB.cached; + } + + getCached(key) { + return this.DB.cached[key]; + } + + async updateCached(key, value) { + const cached = this.getCached(key); + if (cached === value) return false; + console.log("UPDATE CACHED", key, cached); + return this.setCached(key, value); + } } });