From 872d6d49b338712a910bd4243d939c53d2fbf3dc Mon Sep 17 00:00:00 2001 From: Elara Services <43923163+Elara-Discord-Bots@users.noreply.github.com> Date: Sun, 14 Apr 2024 19:25:22 -0700 Subject: [PATCH 01/13] cleanup --- .env.example | 1 + .eslintrc.json | 17 +++++ index.js | 2 +- package.json | 2 +- src/bot/commands/archive.js | 35 ++++------ src/bot/commands/getcpu.js | 6 +- src/bot/commands/reindexcommands.js | 2 +- src/bot/commands/reset.js | 2 +- src/bot/commands/setchannel.js | 4 +- src/bot/events/channelCreate.js | 2 +- src/bot/events/channelDelete.js | 2 +- src/bot/events/channelUpdate.js | 1 - src/bot/events/disconnect.js | 2 +- src/bot/events/guildMemberRemove.js | 1 - src/bot/events/guildUpdate.js | 4 +- src/bot/events/interactionCreate.js | 2 +- src/bot/events/messageDelete.js | 28 +++----- src/bot/events/messageDeleteBulk.js | 78 +++++++++------------- src/bot/events/messageUpdate.js | 29 +++----- src/bot/events/ready.js | 10 +-- src/bot/events/shardDisconnect.js | 1 - src/bot/events/shardResume.js | 1 - src/bot/index.js | 10 +-- src/bot/modules/bulkqueue.js | 6 +- src/bot/modules/commandhandler.js | 2 +- src/bot/modules/guildWebhookCacher.js | 4 +- src/bot/modules/prunecache.js | 64 ------------------ src/bot/modules/webhooksender.js | 26 ++++++-- src/bot/slashcommands/archive.js | 92 ++++++++++++-------------- src/bot/slashcommands/ignorechannel.js | 2 +- src/bot/slashcommands/ping.js | 4 +- src/bot/slashcommands/setup.js | 2 +- src/bot/utils/cacheGuildSettings.js | 11 +-- src/bot/utils/constants.js | 41 ++++++++++++ src/bot/utils/createHaste.js | 28 ++++++++ src/bot/utils/recoverSettings.js | 6 +- src/bot/utils/slashcommandconstants.js | 2 +- src/db/clients/postgres.js | 2 +- src/db/interfaces/postgres/create.js | 32 ++------- src/db/interfaces/postgres/read.js | 28 ++------ src/db/interfaces/postgres/update.js | 85 ++++-------------------- src/db/messageBatcher.js | 11 +-- src/miscellaneous/bezerk.js | 3 +- src/miscellaneous/generateDB.js | 9 +-- src/miscellaneous/workerlistener.js | 2 +- 45 files changed, 294 insertions(+), 410 deletions(-) create mode 100644 .eslintrc.json delete mode 100644 src/bot/modules/prunecache.js create mode 100644 src/bot/utils/createHaste.js diff --git a/.env.example b/.env.example index 299f53f..e9a869c 100644 --- a/.env.example +++ b/.env.example @@ -8,6 +8,7 @@ DISCORD_SUPPORT_SERVER=discord.gg/WYTxVjzHnc # Discord invite for your support DISCORD_WEBHOOK_URL=yourWebhookUrl # Webhook URL that's used for sending certain dev-logs to Discord. ENABLE_TEXT_COMMANDS=true # Whether to allow users to utilise prefix/text commands. 'true' or 'false'. Recommend true. GLOBAL_BOT_PREFIX=% # Prefix to use for prefix/text commands. +MESSAGE_ARCHIVE_SIZE=1000 # How many messages to fetch for the archive commands MESSAGE_BATCH_SIZE=100 # How many messages to store in 'cache' before dumping into database. Defaults to 1000. MESSAGE_HISTORY_DAYS=2 # Maximum age of messages stored in the database. Note that you have to manually setup clearing, e.g. via pg_cron https://github.com/citusdata/pg_cron. PASTE_SITE_ROOT_URL=https://my-paste-site.com # URL of your selfhosted [haste-server](https://github.com/toptal/haste-server). Used in archive commands and messageDeleteBulk event. diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..7041597 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,17 @@ +{ + "env": { + "node": true, + "commonjs": true, + "es2021": true + }, + "extends": "eslint:recommended", + "overrides": [ + ], + "parserOptions": { + "ecmaVersion": "latest" + }, + "rules": { + "no-useless-escape": "off", + "no-prototype-builtins": "off" + } +} diff --git a/index.js b/index.js index 4372d3f..1c957bd 100644 --- a/index.js +++ b/index.js @@ -3,7 +3,7 @@ global.webhook = require('./src/miscellaneous/webhooklogger') global.cluster = require('cluster') require('./src/miscellaneous/logger') require('dotenv').config() -if (cluster.isMaster) { +if (global.cluster.isMaster) { global.logger.startup('Master node init') require('./primary') } else { diff --git a/package.json b/package.json index 2a90477..437af10 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "index.js", "scripts": { "test": "standard", - "lint": "node_modules/.bin/eslint . --ext .js" + "lint": "eslint . --ext .js" }, "keywords": [ "logging", diff --git a/src/bot/commands/archive.js b/src/bot/commands/archive.js index 89563c6..da7c410 100644 --- a/src/bot/commands/archive.js +++ b/src/bot/commands/archive.js @@ -1,33 +1,26 @@ -const sa = require('superagent') +const { createHaste } = require('../utils/createHaste') module.exports = { func: async (message, suffix) => { if (!process.env.PASTE_SITE_ROOT_URL) return message.channel.createMessage('The bot owner hasn\'t yet configured the paste site, so this command is unavailable.') - if (!suffix || isNaN(suffix)) return message.channel.createMessage('That isn\'t a valid suffix! Please provide any number between 5 and 1000 (10,000 if Patreon).') + const limit = parseInt(process.env.MESSAGE_ARCHIVE_SIZE || 1000); + if (!suffix || isNaN(suffix)) return message.channel.createMessage(`That isn't a valid suffix! Please provide any number between 5 and ${limit}.`) const num = parseInt(suffix) - if (num < 5 || num > 1000) return message.channel.createMessage('That number is invalid! Please provide any number between 5 and 1000 (10,000 if Patreon)') - message.channel.getMessages({ limit: num }).then(messages => { - const pasteString = messages.reverse().filter(m => !m.applicationID).map(m => `${m.author.username}${m.author.discriminator === '0' ? '' : `#${m.author.discriminator}`} (${m.author.id}) | ${new Date(m.timestamp).toUTCString()}: ${m.content ? m.content : ''} ${m.embeds.length === 0 ? '' : `| {"embeds": [${m.embeds.map(e => JSON.stringify(e))}]}`} | ${m.attachments.length === 0 ? '' : ` =====> Attachment: ${m.attachments[0].filename}:${m.attachments[0].url}`}`).join('\r\n') - sa - .post(`${process.env.PASTE_SITE_ROOT_URL.endsWith("/") ? process.env.PASTE_SITE_ROOT_URL.slice(0, -1) : process.env.PASTE_SITE_ROOT_URL}/documents`) - .set('Authorization', process.env.PASTE_SITE_TOKEN ?? '') - .set('Content-Type', 'text/plain') - .send(pasteString || 'No messages were able to be archived') - .end((err, res) => { - if (!err && res.statusCode === 200 && res.body.key) { - message.channel.createMessage(`<@${message.author.id}>, **${messages.length}** message(s) could be archived. Link: ${process.env.PASTE_SITE_ROOT_URL.endsWith("/") ? process.env.PASTE_SITE_ROOT_URL.slice(0, -1) : process.env.PASTE_SITE_ROOT_URL}/${res.body.key}.txt`) - } else { - global.logger.error(err, res.body) - global.webhook.error('An error has occurred while posting to the paste website. Check logs for more.') - } - }) - }) + if (num < 5 || num > limit) return message.channel.createMessage(`That number is invalid! Please provide any number between 5 and ${limit}`) + + const messages = await message.channel.getMessages({ limit: num }) + const pasteString = messages.reverse().filter(m => !m.applicationID).map(m => `${m.author.username}${m.author.discriminator === '0' ? '' : `#${m.author.discriminator}`} (${m.author.id}) | ${new Date(m.timestamp).toUTCString()}: ${m.content ? m.content : ''} ${m.embeds.length === 0 ? '' : `| {"embeds": [${m.embeds.map(e => JSON.stringify(e))}]}`} | ${m.attachments.length === 0 ? '' : ` =====> Attachment: ${m.attachments[0].filename}:${m.attachments[0].url}`}`).join('\r\n') + const link = await createHaste(pasteString) + if (!link) { + return message.channel.createMessage('Unable to get the archive haste link') + } + message.channel.createMessage(`<@${message.author.id}>, **${messages.length}** message(s) could be archived. Link: ${link}`) }, name: 'archive', category: 'Utility', perm: 'manageMessages', - quickHelp: 'Makes a log online of up to the last 1000 messages in a channel. Does NOT delete any messages. Patreon bot only: fetch 10,000 messages & [upgraded log site](https://logs.discord.website/logs/W9NbmmULEpxMFMoiBuKrYG)', + quickHelp: `Makes a log online of up to the last ${process.env.MESSAGE_ARCHIVE_SIZE || 100} messages in a channel. Does NOT delete any messages.`, examples: `\`${process.env.GLOBAL_BOT_PREFIX}archive 5\` <- lowest amount possible - \`${process.env.GLOBAL_BOT_PREFIX}archive 1000\` <- maximum count of messages to archive + \`${process.env.GLOBAL_BOT_PREFIX}archive ${process.env.MESSAGE_ARCHIVE_SIZE || 1000}\` <- maximum count of messages to archive \`${process.env.GLOBAL_BOT_PREFIX}archive 25\` <- create a log of the last 25 messages in the channel` } diff --git a/src/bot/commands/getcpu.js b/src/bot/commands/getcpu.js index 85f5a47..d076268 100644 --- a/src/bot/commands/getcpu.js +++ b/src/bot/commands/getcpu.js @@ -1,12 +1,12 @@ module.exports = { - func: async (message, suffix) => { + func: async (message) => { const os = require('os-utils') os.cpuUsage(async v => { - await message.channel.createMessage(`[${cluster.worker.rangeForShard}] CPU usage: ${v * 100}%`) + await message.channel.createMessage(`[${global.cluster.worker.rangeForShard}] CPU usage: ${v * 100}%`) }) os.cpuFree(async v => { - await message.channel.createMessage(`[${cluster.worker.rangeForShard}] CPU free: ${v * 100}%`) + await message.channel.createMessage(`[${global.cluster.worker.rangeForShard}] CPU free: ${v * 100}%`) }) }, name: 'getcpu', diff --git a/src/bot/commands/reindexcommands.js b/src/bot/commands/reindexcommands.js index 314f366..9d84cdb 100644 --- a/src/bot/commands/reindexcommands.js +++ b/src/bot/commands/reindexcommands.js @@ -1,7 +1,7 @@ const commandIndexer = require('../../miscellaneous/commandIndexer') module.exports = { - func: async function (message, suffix) { + func: async function (message) { try { global.bot.commands = {} commandIndexer() diff --git a/src/bot/commands/reset.js b/src/bot/commands/reset.js index ae20b5a..226fd59 100644 --- a/src/bot/commands/reset.js +++ b/src/bot/commands/reset.js @@ -23,7 +23,7 @@ module.exports = { let complete = false global.bot.on('messageCreate', async function temp (m) { if (i === 0) { - const timeout = setTimeout(() => { + setTimeout(() => { global.bot.removeListener('messageCreate', temp) if (!complete) { message.channel.createMessage({ diff --git a/src/bot/commands/setchannel.js b/src/bot/commands/setchannel.js index 82f20b3..215add8 100644 --- a/src/bot/commands/setchannel.js +++ b/src/bot/commands/setchannel.js @@ -33,8 +33,8 @@ module.exports = { func: async (message, suffix) => { const botPerms = message.channel.permissionsOf(global.bot.user.id).json if (!botPerms.manageWebhooks || !botPerms.viewAuditLogs) { - message.channel.createMessage('I need manage webhooks and view audit logs permissions to run setchannel! This is necessary for me to send messages to your configured logging channel.').catch(_ => {}) - message.addReaction('āŒ').catch(_ => {}) + message.channel.createMessage('I need manage webhooks and view audit logs permissions to run setchannel! This is necessary for me to send messages to your configured logging channel.').catch(() => {}) + message.addReaction('āŒ').catch(() => {}) return } let events = suffix.split(', ') diff --git a/src/bot/events/channelCreate.js b/src/bot/events/channelCreate.js index ea587ca..53f06dd 100644 --- a/src/bot/events/channelCreate.js +++ b/src/bot/events/channelCreate.js @@ -21,7 +21,7 @@ module.exports = { name: 'Unknown User', icon_url: 'https://logger.bot/staticfiles/red-x.png' }, - description: `${CHANNEL_TYPE_MAP[newChannel.type] ? CHANNEL_TYPE_MAP[newChannel.type] : 'Unsupported channel type'} created <#${newChannel.id}>`, + description: `${CHANNEL_TYPE_MAP[newChannel.type] || 'Unsupported channel type'} created <#${newChannel.id}>`, fields: [{ name: 'Name', value: newChannel.name diff --git a/src/bot/events/channelDelete.js b/src/bot/events/channelDelete.js index d2868be..b042508 100644 --- a/src/bot/events/channelDelete.js +++ b/src/bot/events/channelDelete.js @@ -21,7 +21,7 @@ module.exports = { name: 'Unknown User', icon_url: 'https://logger.bot/staticfiles/red-x.png' }, - description: `${CHANNEL_TYPE_MAP[channel.type] ? CHANNEL_TYPE_MAP[channel.type] : 'Unsupported channel type'} deleted (${channel.name})`, + description: `${CHANNEL_TYPE_MAP[channel.type] || 'Unsupported channel type'} deleted (${channel.name})`, fields: [{ name: 'Name', value: channel.name diff --git a/src/bot/events/channelUpdate.js b/src/bot/events/channelUpdate.js index 2a26cdb..844f19d 100644 --- a/src/bot/events/channelUpdate.js +++ b/src/bot/events/channelUpdate.js @@ -1,4 +1,3 @@ -const { Permission } = require('eris') const send = require('../modules/webhooksender') const escape = require('markdown-escape') const CHANNEL_TYPE_MAP = { diff --git a/src/bot/events/disconnect.js b/src/bot/events/disconnect.js index 18f0f4b..b184ea8 100644 --- a/src/bot/events/disconnect.js +++ b/src/bot/events/disconnect.js @@ -7,7 +7,7 @@ module.exports = { handle: () => { statAggregator.incrementMisc('disconnect') reconnects++ - global.logger.error(`Worker instance hosting ${cluster.worker.rangeForShard} on id ${cluster.worker.id} disconnected from the gateway. ${reconnects} out of 20.`) + global.logger.error(`Worker instance hosting ${global.cluster.worker.rangeForShard} on id ${global.cluster.worker.id} disconnected from the gateway. ${reconnects} out of 20.`) if (reconnects >= 20) { global.bot.disconnect({ reconnect: true }) // Disconnect the bot but don't destroy member caches } diff --git a/src/bot/events/guildMemberRemove.js b/src/bot/events/guildMemberRemove.js index c6bc097..d83d117 100644 --- a/src/bot/events/guildMemberRemove.js +++ b/src/bot/events/guildMemberRemove.js @@ -1,5 +1,4 @@ const send = require('../modules/webhooksender') -const prunecache = require('../modules/prunecache') const { User } = require('eris') module.exports = { diff --git a/src/bot/events/guildUpdate.js b/src/bot/events/guildUpdate.js index 92838bf..46ad834 100644 --- a/src/bot/events/guildUpdate.js +++ b/src/bot/events/guildUpdate.js @@ -25,7 +25,7 @@ const explicitContentLevels = { module.exports = { name: 'guildUpdate', type: 'on', - handle: async (newGuild, oldGuild) => { + handle: async (newGuild) => { const fields = [] newGuild.getAuditLogs({ actionType: 1, limit: 1 }).then((log) => { if (!log || !log.entries || log.entries.length === 0 || new Date().getTime() - new Date((log.entries[0].id / 4194304) + 1420070400000).getTime() > 3000) return // this could be null coalesced but why not make it backwards compatible @@ -99,7 +99,9 @@ module.exports = { value: `ā–ŗ Now: **${after}**\nā–ŗ Was: **${before}**` } case 'afk_channel_id': + // eslint-disable-next-line no-case-declarations const beforeChannel = logEntry.before && newGuild.channels.get(logEntry.before.afk_channel_id) + // eslint-disable-next-line no-case-declarations const afterChannel = logEntry.after && newGuild.channels.get(logEntry.after.afk_channel_id) if (!beforeChannel) { before = 'None' diff --git a/src/bot/events/interactionCreate.js b/src/bot/events/interactionCreate.js index 8d90767..29e18b1 100644 --- a/src/bot/events/interactionCreate.js +++ b/src/bot/events/interactionCreate.js @@ -16,7 +16,7 @@ module.exports = { name: 'interactionCreate', type: 'on', handle (interaction) { - return new Promise((resolve, reject) => { // why use a promise? awaitCustomID and handle are still sync and can share the timeout/callback maps nicely? + return new Promise((resolve) => { // why use a promise? awaitCustomID and handle are still sync and can share the timeout/callback maps nicely? if (interaction.applicationID !== global.bot.user.id) { resolve() } diff --git a/src/bot/events/messageDelete.js b/src/bot/events/messageDelete.js index 1af6309..4ee8d94 100644 --- a/src/bot/events/messageDelete.js +++ b/src/bot/events/messageDelete.js @@ -1,8 +1,9 @@ const send = require('../modules/webhooksender') -const getMessageFromDB = require('../../db/interfaces/postgres/read').getMessageById -const getMessageFromBatch = require('../../db/messageBatcher').getMessage -const deleteMessage = require('../../db/interfaces/postgres/delete').deleteMessage +const { getMessageById } = require('../../db/interfaces/postgres/read') +const { getMessage } = require('../../db/messageBatcher') +const { deleteMessage } = require('../../db/interfaces/postgres/delete') const cacheGuild = require('../utils/cacheGuild') +const { chunkify } = require('../utils/constants') module.exports = { name: 'messageDelete', @@ -12,10 +13,7 @@ module.exports = { const guildSettings = global.bot.guildSettingsCache[message.channel.guild.id] if (!guildSettings) await cacheGuild(message.channel.guild.id) if (global.bot.guildSettingsCache[message.channel.guild.id].isChannelIgnored(message.channel.id)) return - let cachedMessage = getMessageFromBatch(message.id) - if (!cachedMessage) { - cachedMessage = await getMessageFromDB(message.id) - } + const cachedMessage = getMessage(message.id) || await getMessageById(message.id); if (!cachedMessage) return await deleteMessage(message.id) let cachedUser = global.bot.users.get(cachedMessage.author_id) @@ -44,7 +42,7 @@ module.exports = { let messageChunks = [] if (cachedMessage.content) { if (cachedMessage.content.length > 1000) { - messageChunks = chunkify(cachedMessage.content.replace(/\"/g, '"').replace(/`/g, '')) + messageChunks = chunkify(cachedMessage.content.replace(/"/g, '"').replace(/`/g, '')) } else { messageChunks.push(cachedMessage.content) } @@ -66,7 +64,7 @@ module.exports = { }) if (cachedMessage.attachment_b64) { - attachment_b64urls = cachedMessage.attachment_b64.split("|") + let attachment_b64urls = cachedMessage.attachment_b64.split("|") attachment_b64urls.forEach( (base64url, indx) => messageDeleteEvent.embeds[indx] = { ...messageDeleteEvent.embeds[indx], @@ -77,14 +75,4 @@ module.exports = { } await send(messageDeleteEvent) } -} - -function chunkify (toChunk) { - const lenChunks = Math.ceil(toChunk.length / 1000) - const chunksToReturn = [] - for (let i = 0; i < lenChunks; i++) { - const chunkedStr = toChunk.substring((1000 * i), i === 0 ? 1000 : 1000 * (i + 1)) - chunksToReturn.push(chunkedStr) - } - return chunksToReturn -} +} \ No newline at end of file diff --git a/src/bot/events/messageDeleteBulk.js b/src/bot/events/messageDeleteBulk.js index a33d708..5474134 100644 --- a/src/bot/events/messageDeleteBulk.js +++ b/src/bot/events/messageDeleteBulk.js @@ -1,71 +1,53 @@ -const sa = require('superagent') -const getMessagesByIds = require('../../db/interfaces/postgres/read').getMessagesByIds +const { getMessagesByIds } = require('../../db/interfaces/postgres/read') const send = require('../modules/webhooksender') -const { EMBED_COLORS } = require('../utils/constants') +const { createHaste } = require('../utils/createHaste') module.exports = { name: 'messageDeleteBulk', type: 'on', handle: async messages => { - if (messages.length === 0) return // TODO: TEST! - - if (!process.env.PASTE_SITE_ROOT_URL) { - if (!messages[0].guildId) return; - - return send({ - guildID: messages[0].guildId, - eventName: 'messageDeleteBulk', - embeds: [{ - description: `${messages.length} messages were bulk deleted. :warning: The bot owner hasn't configured a paste site so contents of deleted messages not shown. :warning:`, - color: EMBED_COLORS.YELLOW_ORANGE, - }] - }); - } - + if (!messages.length) return // TODO: TEST! + if (!messages[0].guildId) return; const dbMessages = await getMessagesByIds(messages.map(m => m.id)) - await paste(dbMessages, messages[0].channel.guild.id) + await paste(dbMessages, messages[0].guildId) } } -async function paste (messages, guildID) { +async function paste(messages, guildID) { if (!messages) return - const messageDeleteBulkEvent = { - guildID: guildID, - eventName: 'messageDeleteBulk', - embeds: [{ - description: `**${messages.length}** message(s) were deleted and known in cache.`, - fields: [], - color: 15550861 - }] - } const pasteString = messages.reverse().map(m => { let globalUser = global.bot.users.get(m.author_id) if (!globalUser) { globalUser = { username: 'Unknown', - discriminator: '0000', + discriminator: '0', avatarURL: '' } } return `${globalUser.username}${globalUser.discriminator === '0' ? '' : `#${globalUser.discriminator}`} (${m.author_id}) | (${globalUser.avatarURL}) | ${new Date(m.ts).toUTCString()}: ${m.content}` }).join('\r\n') - if (pasteString) { - sa - .post(`${process.env.PASTE_SITE_ROOT_URL.endsWith("/") ? process.env.PASTE_SITE_ROOT_URL.slice(0, -1) : process.env.PASTE_SITE_ROOT_URL}/documents`) - .set('Authorization', process.env.PASTE_SITE_TOKEN ?? '') - .set('Content-Type', 'text/plain') - .send(pasteString || 'An error has occurred while fetching pastes. Please contact the bot author.') - .end((err, res) => { - if (!err && res.body && res.statusCode === 200 && res.body.key) { - messageDeleteBulkEvent.embeds[0].fields.push({ - name: 'Link', - value: `${process.env.PASTE_SITE_ROOT_URL.endsWith("/") ? process.env.PASTE_SITE_ROOT_URL.slice(0, -1) : process.env.PASTE_SITE_ROOT_URL}/${res.body.key}.txt` - }) - send(messageDeleteBulkEvent) - } else { - global.logger.error(err) - global.webhook.error('An error has occurred while posting to the paste website. Check logs for more.') - } - }) + if (!pasteString) { + return + } + const messageDeleteBulkEvent = { + guildID: guildID, + eventName: 'messageDeleteBulk', + embeds: [{ + description: `**${messages.length}** message(s) were deleted and known in cache.`, + fields: [], + color: 15550861 + }], + file: [ + // Send a messages.txt file to the channel. + { name: `messages.txt`, file: Buffer.from(pasteString) } + ] + } + const link = await createHaste(pasteString) + if (link) { + messageDeleteBulkEvent.embeds[0].fields.push({ + name: 'Link', + value: link + }) } + send(messageDeleteBulkEvent) } diff --git a/src/bot/events/messageUpdate.js b/src/bot/events/messageUpdate.js index 6a5fa1d..40f3707 100644 --- a/src/bot/events/messageUpdate.js +++ b/src/bot/events/messageUpdate.js @@ -1,8 +1,9 @@ const send = require('../modules/webhooksender') -const updateMessageByID = require('../../db/interfaces/postgres/update').updateMessageByID -const getMessageFromDB = require('../../db/interfaces/postgres/read').getMessageById -const getMessageFromBatch = require('../../db/messageBatcher').getMessage +const { updateMessageByID } = require('../../db/interfaces/postgres/update') +const { getMessageById } = require('../../db/interfaces/postgres/read') +const { getMessage } = require('../../db/messageBatcher') const escape = require('markdown-escape') +const { chunkify } = require('../utils/constants') // markdown-escape is a single exported function, I probably don't need it as a node module lol @@ -13,16 +14,16 @@ module.exports = { if (!newMessage.channel.guild || !newMessage.author) return if (newMessage.author.id === global.bot.user.id) return const member = newMessage.channel.guild.members.get(newMessage.author.id) // this member "should" be in cache at all times - oldMessage = getMessageFromBatch(newMessage.id) + let oldMessage = getMessage(newMessage.id) if (!oldMessage) { - oldMessage = await getMessageFromDB(newMessage.id) + oldMessage = await getMessageById(newMessage.id) } if (!oldMessage) return if (newMessage.author.bot && !global.bot.global.guildSettingsCache[newMessage.channel.guild.id].isLogBots()) return if ((newMessage.content === oldMessage.content) && (newMessage.attachments.length === oldMessage.attachment_b64.split("|").filter(Boolean).length)) return // content/attachments didn't change so don't process await processMessage(newMessage, oldMessage) - async function processMessage (newMessage, oldMessage) { + async function processMessage(newMessage, oldMessage) { const messageUpdateEvent = { guildID: newMessage.channel.guild.id, eventName: 'messageUpdate', @@ -96,12 +97,12 @@ module.exports = { let newUrls = []; if (oldMessage.attachment_b64) { const oldImageUrls = oldMessage.attachment_b64.split("|").map(base64url => Buffer.from(base64url, "base64url").toString("utf-8")).filter(Boolean) - newAttachmentImages = newMessage.attachments.filter(attachment => attachment.content_type.startsWith("image")) + let newAttachmentImages = newMessage.attachments.filter(attachment => attachment.content_type.startsWith("image")) if (oldImageUrls.length > newAttachmentImages.length) { // Removed at least one image from the message newUrls = newAttachmentImages.map(img => img.url) const removedImageUrls = oldImageUrls.filter(url => !newUrls.includes(url)) - removedImageUrls.forEach( (url, indx) => messageUpdateEvent.embeds[indx] = { + removedImageUrls.forEach((url, indx) => messageUpdateEvent.embeds[indx] = { ...messageUpdateEvent.embeds[indx], image: { url }, url: "https://example.com" @@ -125,14 +126,4 @@ module.exports = { } } } -} - -function chunkify (toChunk) { - const lenChunks = Math.ceil(toChunk.length / 1000) - const chunksToReturn = [] - for (let i = 0; i < lenChunks; i++) { - const chunkedStr = toChunk.substring((1000 * i), i === 0 ? 1000 : 1000 * (i + 1)) - chunksToReturn.push(chunkedStr) - } - return chunksToReturn -} +} \ No newline at end of file diff --git a/src/bot/events/ready.js b/src/bot/events/ready.js index a0f9a0b..5389360 100644 --- a/src/bot/events/ready.js +++ b/src/bot/events/ready.js @@ -1,6 +1,7 @@ const cluster = require('cluster') const checkForMissingSettings = require('../utils/recoverSettings') const statAggregator = require('../modules/statAggregator') +const cacheGuildSettings = require('../utils/cacheGuildSettings') let failedHealthCheckCount = 0 @@ -8,6 +9,7 @@ module.exports = { name: 'ready', type: 'once', handle: async () => { + await cacheGuildSettings(); statAggregator.incrementMisc('ready') global.logger.info(`Worker instance hosting ${cluster.worker.rangeForShard} on id ${cluster.worker.id} is now ready to serve requests. This shard or shard range has ${global.bot.guilds.size} guilds and ${global.bot.users.size} users cached.`) global.webhook.generic(`Worker instance hosting ${cluster.worker.rangeForShard} on id ${cluster.worker.id} is now ready to serve requests. This shard or shard range has ${global.bot.guilds.size} guilds and ${global.bot.users.size} users cached.`) @@ -18,14 +20,14 @@ module.exports = { await checkForMissingSettings() } setInterval(() => { - if (bot.shards.filter(shard => shard.latency == Infinity && shard.status === 'disconnected').length !== 0) { + if (global.bot.shards.filter(shard => shard.latency == Infinity && shard.status === 'disconnected').length !== 0) { failedHealthCheckCount++ - global.logger.warn(`[${cluster.worker.rangeForShard}] Found disconnected shards ${bot.shards.filter(shard => shard.latency == Infinity && shard.status === 'disconnected').map(s => s.id).join(', ')}, failure count is ${failedHealthCheckCount}`) + global.logger.warn(`[${cluster.worker.rangeForShard}] Found disconnected shards ${global.bot.shards.filter(shard => shard.latency == Infinity && shard.status === 'disconnected').map(s => s.id).join(', ')}, failure count is ${failedHealthCheckCount}`) if (failedHealthCheckCount >= 5) { global.logger.warn(`[${cluster.worker.rangeForShard}] Shard health check failed 5 times in a row, hard resetting shards`) global.webhook.error(`[${cluster.worker.rangeForShard}] Shard health check failed 5 times in a row, hard resetting shards`) failedHealthCheckCount = 0 - bot.shards.forEach(shard => { + global.bot.shards.forEach(shard => { shard.hardReset() shard.connect() }) @@ -33,7 +35,7 @@ module.exports = { } else if (failedHealthCheckCount > 0) { failedHealthCheckCount-- } - }, 1000 * 60) + }, 60_000) } } diff --git a/src/bot/events/shardDisconnect.js b/src/bot/events/shardDisconnect.js index 987b92e..222fc23 100644 --- a/src/bot/events/shardDisconnect.js +++ b/src/bot/events/shardDisconnect.js @@ -4,7 +4,6 @@ module.exports = { name: 'shardDisconnect', type: 'on', handle: async (err, shardID) => { - const cachedShard = global.bot.shards.get(shardID) global.logger.info(`[${cluster.worker.rangeForShard}] Shard ${shardID} disconnected with error`, err) // global.webhook.warn(`[${cluster.worker.rangeForShard}] Shard ${shardID} disconnected with error: ${err?.message ?? 'no error message'}\n\nResume -> ${cachedShard.resumeURL}\nStatus -> ${cachedShard.status}\nReconnecting? -> ${cachedShard.connecting ? 'yes' : 'no'}\nLast heartbeat sent: \nLast heartbeat received: `) } diff --git a/src/bot/events/shardResume.js b/src/bot/events/shardResume.js index 3974c2e..84ae1c2 100644 --- a/src/bot/events/shardResume.js +++ b/src/bot/events/shardResume.js @@ -4,7 +4,6 @@ module.exports = { name: 'shardResume', type: 'on', handle: async (shardID) => { - const cachedShard = global.bot.shards.get(shardID) global.logger.info(`[${cluster.worker.rangeForShard}] Shard ${shardID} has resumed`) // global.webhook.warn(`[${cluster.worker.rangeForShard}] Shard ${shardID} has resumed\n\nResume -> ${cachedShard.resumeURL}\nStatus -> ${cachedShard.status}\nReconnecting? -> ${cachedShard.connecting ? 'yes' : 'no'}\nLast heartbeat sent: \nLast heartbeat received: `) } diff --git a/src/bot/index.js b/src/bot/index.js index 1c61b8e..9e98523 100644 --- a/src/bot/index.js +++ b/src/bot/index.js @@ -3,7 +3,6 @@ const cluster = require('cluster') const Sentry = require('@sentry/node') const redisLock = require('../db/interfaces/redis/redislock') const indexCommands = require('../miscellaneous/commandIndexer') -const cacheGuildInfo = require('./utils/cacheGuildSettings') const addBotListeners = require('./utils/addbotlisteners') require('dotenv').config() @@ -26,10 +25,8 @@ function connect () { global.logger.warn(cluster.worker.rangeForShard + ' could not unlock, waiting') }) }) - }).catch(e => { - setTimeout(() => { - connect() - }, 10000) + }).catch(() => { + setTimeout(() => connect(), 10_000) }) // throw out not being able to obtain a lock. } @@ -51,7 +48,7 @@ async function init () { domain: process.env.TWILIGHT_HOST || 'localhost', baseURL: '/api/v9', port: process.env.TWILIGHT_PORT || 8080, - requestTimeout: 1000 * 60 * 30 // 1h time + requestTimeout: 1_800_000 // 1h time } : {}) }, restMode: true, @@ -83,7 +80,6 @@ async function init () { } indexCommands() // yes, block the thread while we read commands. - await cacheGuildInfo() addBotListeners() diff --git a/src/bot/modules/bulkqueue.js b/src/bot/modules/bulkqueue.js index 58d6165..1126606 100644 --- a/src/bot/modules/bulkqueue.js +++ b/src/bot/modules/bulkqueue.js @@ -71,9 +71,9 @@ function getEmbedCharLens (embeds) { function sendBulkLog (senderPkg, embeds, guildSettings) { global.bot.executeWebhook(senderPkg.webhookID, senderPkg.webhookToken, { file: senderPkg.file ? senderPkg.file : '', - username: global.bot.user.username, - avatarURL: global.bot.user.avatarURL, - embeds: embeds, + username: senderPkg.username || global.bot.user.username, + avatarURL: senderPkg.avatarURL || global.bot.user.avatarURL, + embeds, allowedMentions: { // even though this is an embed and cannot ping, why not everyone: false, roles: false, diff --git a/src/bot/modules/commandhandler.js b/src/bot/modules/commandhandler.js index 2a114a9..a457dc1 100644 --- a/src/bot/modules/commandhandler.js +++ b/src/bot/modules/commandhandler.js @@ -29,7 +29,7 @@ function processCommand (message, commandName, suffix) { } else if (command.type === 'creator' && !process.env.CREATOR_IDS.split(",").includes(message.author.id)) { message.channel.createMessage('This command is creator only!') return - } else if (command.type === 'admin' && !(message.member.permissions.has('administrator' || message.author.id === message.channel.guild.ownerID))) { + } else if (command.type === 'admin' && !(message.member.permissions.has('administrator') || message.author.id === message.channel.guild.ownerID)) { message.channel.createMessage('That\'s an admin only command. You need the administrator permission to use it.') return } else if (command.perm && !(message.member.permissions.has(command.perm) || message.author.id === message.channel.guild.ownerID)) { diff --git a/src/bot/modules/guildWebhookCacher.js b/src/bot/modules/guildWebhookCacher.js index 058e5e2..4f45587 100644 --- a/src/bot/modules/guildWebhookCacher.js +++ b/src/bot/modules/guildWebhookCacher.js @@ -1,5 +1,5 @@ const webhookCache = require('./webhookcache') -const clearEventByID = require('../../db/interfaces/postgres/update').clearEventByID +const { clearEventByID } = require('../../db/interfaces/postgres/update') const statAggregator = require('./statAggregator') const cacheGuild = require('../utils/cacheGuild') @@ -65,7 +65,7 @@ module.exports = async (guildID, channelID) => { const newHook = await logChannel.createWebhook({ name: 'Loggerbot Utility Webhook', avatar: ' data:image/png;base64,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' - }, 'Automated webhook creation.').catch((e) => { + }, 'Automated webhook creation.').catch(() => { // With permission checking, this can only trigger if Discord sends a 500 error code OR // the user hit the guild webhook limit. The best action is to leave because the bot // doesn't know who to contact when this occurs (owner? staff?) diff --git a/src/bot/modules/prunecache.js b/src/bot/modules/prunecache.js deleted file mode 100644 index 8404b69..0000000 --- a/src/bot/modules/prunecache.js +++ /dev/null @@ -1,64 +0,0 @@ -const send = require('../modules/webhooksender') -const request = require('superagent') - -module.exports = { - cache: {}, - handle (logID, guild, member, perp) { - if (!this.cache.hasOwnProperty(logID)) { - this.cache[logID] = { - count: 0, - guild, - list: `${new Date((logID / 4194304) + 1420070400000).toUTCString()}\n`, - perp - } - setTimeout(async () => { - this.send(logID) - }, 10000) - } - this.cache[logID].list += `\n${member.username}${member.discriminator === '0' ? '' : `#${member.discriminator}`} (${member.id})` - this.cache[logID].count++ - }, - async send (logID) { - // const log = this.cache[logID] - // delete this.cache[logID] - // let res - // try { - // res = await request - // .post('https://paste.lemonmc.com/api/json/create') - // .send({ - // data: log.list, - // language: 'text', - // private: true, - // title: log.guild.name.slice(0, 29), - // expire: '2592000' - // }) - - // if (res.statusCode === 200 && res.body.result.id) { - // res = `[${log.count} members](https://paste.lemonmc.com/${res.body.result.id}/${res.body.result.hash})` - // } else { - // console.error(res) - // res = `${log.count} members` - // } - // } catch (err) { - // console.error(err) - // res = `${log.count} members` - // } - // const event = { - // guildID: log.guild.id, - // eventName: 'guildMemberKick', - // embed: { - // author: { - // name: `${log.perp.username}#${log.perp.discriminator}`, - // icon_url: log.perp.avatarURL - // }, - // color: 16711680, - // description: `${res} were pruned`, - // fields: [{ - // name: 'ID', - // value: `\`\`\`ini\nPerpetrator = ${log.perp.id}\`\`\`` - // }] - // } - // } - // await send(event) - } -} diff --git a/src/bot/modules/webhooksender.js b/src/bot/modules/webhooksender.js index 3fb96e3..e3981e9 100644 --- a/src/bot/modules/webhooksender.js +++ b/src/bot/modules/webhooksender.js @@ -4,7 +4,7 @@ const guildWebhookCacher = require('./guildWebhookCacher') const cacheGuild = require('../utils/cacheGuild') const statAggregator = require('./statAggregator') const enqueue = require('./bulkqueue') -const setEventsByChannelID = require('../../db/interfaces/postgres/update').setEventsLogId +const { setEventsLogId } = require('../../db/interfaces/postgres/update') // const doNotAggregate = ['voiceStateUpdate', 'voiceChannelLeave', 'voiceChannelSwitch', 'guildMemberVerify'] // these three events could possibly be an audit log fetch in the future, so they must be recorded together @@ -19,7 +19,21 @@ const doNotAggregate = [ 'warn' ] -module.exports = async pkg => { +/** + * @typedef {Object} Data + * @property {string} guildID + * @property {string} eventName + * @property {string} [username] + * @property {string} [avatarURL] + * @property {import("eris").WebhookPayload['embeds']} [embeds] + * @property {boolean} [noFooter] + * @property {import("eris").WebhookPayload['file']} [file] + */ + +/** + * @param {Data} pkg + */ +module.exports = async (pkg) => { if (!pkg.guildID) return global.logger.error('No guildID was provided in an embed!') if (!pkg.embeds[0].color) pkg.embeds[0].color = 3553599 // todo: make a function to check all the following logic for EACH embed, not just the first const guild = global.bot.guilds.get(pkg.guildID) @@ -36,7 +50,7 @@ module.exports = async pkg => { if (!guildSettings.getEventByName(pkg.eventName)) return if (!global.bot.getChannel(guildSettings.getEventByName(pkg.eventName))) { await global.redis.del(`webhook-${guildSettings.getEventByName(pkg.eventName)}`) - await setEventsByChannelID(pkg.guildID, '', [pkg.eventName]) + await setEventsLogId(pkg.guildID, '', [pkg.eventName]) await cacheGuild(pkg.guildID) } if (!global.bot.getChannel(guildSettings.getEventByName(pkg.eventName))?.permissionsOf(global.bot.user.id).json.manageWebhooks || !global.bot.getChannel(guildSettings.getEventByName(pkg.eventName)).permissionsOf(global.bot.user.id).json.viewAuditLog) return @@ -72,8 +86,8 @@ module.exports = async pkg => { if (guild.memberCount < 10000 && guild.voiceStates.size < 100) { global.bot.executeWebhook(webhookID, webhookToken, { file: pkg.file ? pkg.file : '', - username: global.bot.user.username, - avatarURL: global.bot.user.avatarURL, + username: pkg.username || global.bot.user.username, + avatarURL: pkg.avatarURL || global.bot.user.avatarURL, embeds: pkg.embeds, allowedMentions: { // even though this is an embed and cannot ping, why not everyone: false, @@ -83,7 +97,7 @@ module.exports = async pkg => { }).catch(async e => { if (e && e.message && (e.message.includes('Request timed out') || e.message.includes('503 Service Temporarily') || e.message.includes('Internal Server Error'))) return if (e && e.code && !(e.code == '50035' || e.code == '10015' || e.code == '500' || e.code == '503' || (e && e.message && e.message.includes('Internal Server Error')))) { - global.logger.warn(`Got ${e.code} while sending webhook to ${pkg.guildID} (${global.bot.guilds.get(pkg.guildID) ? global.bot.guilds.get(pkg.guildID).name : 'Could not find guild!'})`) + global.logger.warn(`Got ${e.code} while sending webhook to ${pkg.guildID} (${global.bot.guilds.get(pkg.guildID)?.name || 'Could not find guild!'})`) // global.webhook.warn(`Got ${e.code} while sending webhook to ${pkg.guildID} (${global.bot.guilds.get(pkg.guildID) ? global.bot.guilds.get(pkg.guildID).name : 'Could not find guild!'})`) } if (e.code == '10015') { // Webhook doesn't exist anymore. diff --git a/src/bot/slashcommands/archive.js b/src/bot/slashcommands/archive.js index 831b775..b33beb3 100644 --- a/src/bot/slashcommands/archive.js +++ b/src/bot/slashcommands/archive.js @@ -1,6 +1,6 @@ -const sa = require('superagent') const { EMBED_COLORS } = require('../utils/constants.js') const { getEmbedFooter, getAuthorField } = require('../utils/embeds.js') +const { createHaste } = require('../utils/createHaste.js') module.exports = { name: 'archive', @@ -18,12 +18,13 @@ module.exports = { footer: getEmbedFooter(global.bot.user), author: getAuthorField(interaction.member.user) }] - }).catch(() => {}) - if (!interaction.data.options || !interaction.data.options[0] || interaction.data.options[0].value > 1000 || interaction.data.options[0].value < 5) { + }).catch(() => { }) + const limit = parseInt(process.env.MESSAGE_ARCHIVE_SIZE || 1000) + if (!interaction.data.options || !interaction.data.options[0] || interaction.data.options[0].value > limit || interaction.data.options[0].value < 5) { interaction.createMessage({ embeds: [{ title: 'Unsuccessful', - description: 'Amount must be 5 <= amount < 1000', + description: `Amount must be 5 <= amount < ${limit}`, thumbnail: { url: interaction.member.user.dynamicAvatarURL(null, 64) }, @@ -31,58 +32,47 @@ module.exports = { footer: getEmbedFooter(global.bot.user), author: getAuthorField(interaction.member.user) }] - }).catch(() => {}) + }).catch(() => { }) } const fetchedMessages = await global.bot.getChannel(interaction.channel.id).getMessages({ limit: interaction.data.options[0].value }) - const pasteString = fetchedMessages.reverse().filter(m => !m.applicationID).map(m => `${m.author.username}${m.author.discriminator === '0' ? '' : `#${m.author.discriminator}`} (${m.author.id}) | ${new Date(m.timestamp)}: ${m.content ? m.content : ''} | ${m.embeds.length === 0 ? '' : `{"embeds": [${m.embeds.map(e => JSON.stringify(e))}]}`} | ${m.attachments.length === 0 ? '' : ` =====> Attachment: ${m.attachments[0].filename}:${m.attachments[0].url}`}`).join('\r\n') - try { - await interaction.createMessage({ - embeds: [{ // make sure followup message is created before doing any more work - title: 'Processing', - description: `Processing request from ${interaction.member.username}${interaction.member.discriminator === '0' ? '' : `#${interaction.member.discriminator}`} for an archive of ${interaction.data.options[0].value} messages`, + const pasteString = fetchedMessages.reverse().filter(m => !m.applicationID).map(m => `${m.author.username}${m.author.discriminator === '0' ? '' : `#${m.author.discriminator}`} (${m.author.id}) | ${new Date(m.timestamp)}: ${m.content || ''} | ${m.embeds.length === 0 ? '' : `{"embeds": [${m.embeds.map(e => JSON.stringify(e))}]}`} | ${m.attachments.length === 0 ? '' : ` ${m.attachments.map((c) => `=====> Attachment: ${c.filename}: ${m.url}`).join(" | ")}`}`).join('\r\n') + await interaction.createMessage({ + embeds: [{ // make sure followup message is created before doing any more work + title: 'Processing', + description: `Processing request from ${interaction.member.username}${interaction.member.discriminator === '0' ? '' : `#${interaction.member.discriminator}`} for an archive of ${interaction.data.options[0].value} messages`, + thumbnail: { + url: interaction.member.user.dynamicAvatarURL(null, 64) + }, + color: EMBED_COLORS.YELLOW_ORANGE, + footer: getEmbedFooter(global.bot.user), + author: getAuthorField(interaction.member.user) + }] + }).catch(() => null); + const link = await createHaste(pasteString); + if (!link) { + return interaction.editOriginalMessage({ + embeds: [{ + title: 'Error', + description: 'The archive service returned an error, please try again later!', thumbnail: { url: interaction.member.user.dynamicAvatarURL(null, 64) }, - color: EMBED_COLORS.YELLOW_ORANGE, - footer: getEmbedFooter(global.bot.user), - author: getAuthorField(interaction.member.user) + color: EMBED_COLORS.RED, + footer: getEmbedFooter(global.bot.user) }] - }) - } catch (_) {} - sa - .post(`${process.env.PASTE_SITE_ROOT_URL.endsWith("/") ? process.env.PASTE_SITE_ROOT_URL.slice(0, -1) : process.env.PASTE_SITE_ROOT_URL}/documents`) - .set('Authorization', process.env.PASTE_SITE_TOKEN ?? '') - .set('Content-Type', 'text/plain') - .send(pasteString || 'No messages were able to be archived') - .end((err, res) => { - if (!err && res.statusCode === 200 && res.body.key) { - interaction.editOriginalMessage({ - embeds: [{ - title: 'Success', - description: `Archived ${fetchedMessages.length} messages: ${process.env.PASTE_SITE_ROOT_URL.endsWith("/") ? process.env.PASTE_SITE_ROOT_URL.slice(0, -1) : process.env.PASTE_SITE_ROOT_URL}/${res.body.key}.txt`, - thumbnail: { - url: interaction.member.user.dynamicAvatarURL(null, 64) - }, - color: EMBED_COLORS.GREEN, - footer: getEmbedFooter(global.bot.user), - author: getAuthorField(interaction.member.user) - }] - }).catch(() => {}) - } else { - interaction.editOriginalMessage({ - embeds: [{ - title: 'Error', - description: 'The archive service returned an error, please try again later!', - thumbnail: { - url: interaction.member.user.dynamicAvatarURL(null, 64) - }, - color: EMBED_COLORS.RED, - footer: getEmbedFooter(global.bot.user) - }] - }).catch(() => {}) - global.logger.error(err, res.body) - global.webhook.error('An error has occurred while posting to the paste website. Check logs for more.') - } - }) + }).catch(() => { }) + } + interaction.editOriginalMessage({ + embeds: [{ + title: 'Success', + description: `Archived ${fetchedMessages.length} messages: ${link}`, + thumbnail: { + url: interaction.member.user.dynamicAvatarURL(null, 64) + }, + color: EMBED_COLORS.GREEN, + footer: getEmbedFooter(global.bot.user), + author: getAuthorField(interaction.member.user) + }] + }).catch(() => { }) } } diff --git a/src/bot/slashcommands/ignorechannel.js b/src/bot/slashcommands/ignorechannel.js index e8a82d1..f9cd79d 100644 --- a/src/bot/slashcommands/ignorechannel.js +++ b/src/bot/slashcommands/ignorechannel.js @@ -44,7 +44,7 @@ module.exports = { }, color: EMBED_COLORS.RED }] - }).catch(_ => {}) + }).catch(() => {}) } const isDisabled = await ignoreChannel(interaction.guildID, channelOption?.value || interaction.channel.id) interaction.createMessage({ diff --git a/src/bot/slashcommands/ping.js b/src/bot/slashcommands/ping.js index 70482da..af971e9 100644 --- a/src/bot/slashcommands/ping.js +++ b/src/bot/slashcommands/ping.js @@ -26,6 +26,8 @@ module.exports = { color: EMBED_COLORS.GREEN }] }) - } catch (_) {} + } catch (_) { + return + } } } diff --git a/src/bot/slashcommands/setup.js b/src/bot/slashcommands/setup.js index 60b52cd..f07e1f3 100644 --- a/src/bot/slashcommands/setup.js +++ b/src/bot/slashcommands/setup.js @@ -4,7 +4,7 @@ const { setEventsLogId } = require('../../db/interfaces/postgres/update') const { EMBED_COLORS, PRESET_EVENT_MAP, ALL_EVENTS } = require('../utils/constants') const { getEmbedFooter, getAuthorField } = require('../utils/embeds') -async function returnMissingPerms (channelID, userID, events) { +async function returnMissingPerms (channelID, userID) { const requiredPerms = ['manageWebhooks', 'viewAuditLog', 'viewChannel', 'sendMessages', 'embedLinks', 'readMessageHistory', 'useExternalEmojis'] let logChannelPerms try { diff --git a/src/bot/utils/cacheGuildSettings.js b/src/bot/utils/cacheGuildSettings.js index 613ff37..785402a 100644 --- a/src/bot/utils/cacheGuildSettings.js +++ b/src/bot/utils/cacheGuildSettings.js @@ -1,9 +1,12 @@ -const getAllGuilds = require('../../db/interfaces/postgres/read').getAllGuilds +const { getAllGuilds } = require('../../db/interfaces/postgres/read') const GuildSettings = require('../bases/GuildSettings') module.exports = async () => { const allDBGuilds = await getAllGuilds() - allDBGuilds.forEach(guild => { - global.bot.guildSettingsCache[guild.id] = new GuildSettings(guild) - }) + for (const guild of allDBGuilds) { + if (!global.bot.guilds.has(guild.id)) { // If the server isn't handled by this shard, don't add it to the cache. + continue; + } + global.bot.guildSettingsCache[guild.id] = new GuildSettings(guild); + } } diff --git a/src/bot/utils/constants.js b/src/bot/utils/constants.js index 42fdaea..e04c2a2 100644 --- a/src/bot/utils/constants.js +++ b/src/bot/utils/constants.js @@ -89,3 +89,44 @@ exports.PRESET_EVENT_MAP = { channel: ['channelCreate', 'channelUpdate', 'channelDelete'], all: this.ALL_EVENTS } + +// Define the events once in this file vs in multiple files. +exports.eventLogs = { + channelCreate: '', + channelUpdate: '', + channelDelete: '', + guildBanAdd: '', + guildBanRemove: '', + guildRoleCreate: '', + guildRoleDelete: '', + guildRoleUpdate: '', + guildUpdate: '', + messageDelete: '', + messageDeleteBulk: '', + messageUpdate: '', + guildMemberAdd: '', + guildMemberKick: '', + guildMemberRemove: '', + guildMemberUpdate: '', + guildMemberVerify: '', + voiceChannelLeave: '', + voiceChannelJoin: '', + voiceStateUpdate: '', + voiceChannelSwitch: '', + guildEmojisUpdate: '', + guildMemberNickUpdate: '', + guildMemberBoostUpdate: '' +} + + +function chunkify(toChunk) { + const lenChunks = Math.ceil(toChunk.length / 1000) + const chunksToReturn = [] + for (let i = 0; i < lenChunks; i++) { + const chunkedStr = toChunk.substring((1000 * i), i === 0 ? 1000 : 1000 * (i + 1)) + chunksToReturn.push(chunkedStr) + } + return chunksToReturn +} + +exports.chunkify = chunkify; \ No newline at end of file diff --git a/src/bot/utils/createHaste.js b/src/bot/utils/createHaste.js new file mode 100644 index 0000000..a3b956e --- /dev/null +++ b/src/bot/utils/createHaste.js @@ -0,0 +1,28 @@ +const { post } = require("superagent") + +/** + * @description Creates a hastebin link for archive and messageBulkDelete event + * @param {string} str + * @returns {Promise} + */ +module.exports.createHaste = async (str = `No data provided`) => { + if (!process.env.PASTE_SITE_ROOT_URL) { // If there is no haste set, just ignore. + return null; + } + const url = `${process.env.PASTE_SITE_ROOT_URL.endsWith("/") ? process.env.PASTE_SITE_ROOT_URL.slice(0, -1) : process.env.PASTE_SITE_ROOT_URL}`; + return new Promise((r) => { + post(`${url}/documents`) + .set('Authorization', process.env.PASTE_SITE_TOKEN ?? '') + .set('Content-Type', 'text/plain') + .send(str) + .end((err, res) => { + if (!err && res.statusCode === 200 && res.body.key) { + return r(`${url}/${res.body.key}.txt`); + } else { + global.logger.error(err, res.body) + global.webhook.error('An error has occurred while posting to the paste website. Check logs for more.') + return r(null); + } + }) + }) +} \ No newline at end of file diff --git a/src/bot/utils/recoverSettings.js b/src/bot/utils/recoverSettings.js index 2dd732e..7e1683b 100644 --- a/src/bot/utils/recoverSettings.js +++ b/src/bot/utils/recoverSettings.js @@ -1,8 +1,8 @@ -const getAllDBGuilds = require('../../db/interfaces/postgres/read').getAllGuilds -const createGuild = require('../../db/interfaces/postgres/create').createGuild +const { getAllGuilds } = require('../../db/interfaces/postgres/read') +const {createGuild} = require('../../db/interfaces/postgres/create') module.exports = async () => { // If the bot sees a guild that the DB doesn't know, create a record for it - const allGuilds = await getAllDBGuilds() + const allGuilds = await getAllGuilds() global.bot.guilds.forEach(async guild => { if (!allGuilds.find(g => g.id === guild.id)) { await createGuild(guild) diff --git a/src/bot/utils/slashcommandconstants.js b/src/bot/utils/slashcommandconstants.js index 6d178ec..056a4db 100644 --- a/src/bot/utils/slashcommandconstants.js +++ b/src/bot/utils/slashcommandconstants.js @@ -1,4 +1,4 @@ -const ERIS_CONSTANTS = require('eris').Constants +const { Constants: ERIS_CONSTANTS } = require('eris'); exports.commands = [ { diff --git a/src/db/clients/postgres.js b/src/db/clients/postgres.js index 0167694..dccde14 100644 --- a/src/db/clients/postgres.js +++ b/src/db/clients/postgres.js @@ -1,4 +1,4 @@ -const { Client, Pool } = require('pg') // PREREQUISITE: Have postgres installed and your user can connect +const { Pool } = require('pg') // PREREQUISITE: Have postgres installed and your user can connect require('dotenv').config() const pool = new Pool({ diff --git a/src/db/interfaces/postgres/create.js b/src/db/interfaces/postgres/create.js index 146fe45..6a3d5fe 100644 --- a/src/db/interfaces/postgres/create.js +++ b/src/db/interfaces/postgres/create.js @@ -3,39 +3,15 @@ const aes = require('../../aes') const cacheGuild = require('../../../bot/utils/cacheGuild') const batchHandler = require('../../messageBatcher') const escape = require('markdown-escape') - -const eventLogs = { - channelCreate: '', - channelUpdate: '', - channelDelete: '', - guildBanAdd: '', - guildBanRemove: '', - guildRoleCreate: '', - guildRoleDelete: '', - guildRoleUpdate: '', - guildUpdate: '', - messageDelete: '', - messageDeleteBulk: '', - messageUpdate: '', - guildMemberAdd: '', - guildMemberKick: '', - guildMemberRemove: '', - guildMemberUpdate: '', - guildMemberVerify: '', - voiceChannelLeave: '', - voiceChannelJoin: '', - voiceStateUpdate: '', - voiceChannelSwitch: '', - guildEmojisUpdate: '', - guildMemberNickUpdate: '', - guildMemberBoostUpdate: '' -} +const { eventLogs } = require("../../../bot/utils/constants") async function createGuild (guild) { try { await pool.query('INSERT INTO guilds (id, owner_id, ignored_channels, disabled_events, event_logs, log_bots, custom_settings) VALUES ($1, $2, $3, $4, $5, $6, $7)', [guild.id, guild.ownerID, [], [], eventLogs, false, { }]) // Regenerate the document if a user kicks and reinvites the bot. await cacheGuild(guild.id) - } catch (e) { } + } catch (e) { + return + } } async function cacheMessage (message) { diff --git a/src/db/interfaces/postgres/read.js b/src/db/interfaces/postgres/read.js index 0589352..5830a05 100644 --- a/src/db/interfaces/postgres/read.js +++ b/src/db/interfaces/postgres/read.js @@ -1,13 +1,13 @@ const pool = require('../../clients/postgres') -const createGuild = require('./create').createGuild +const { createGuild } = require('./create') const aes = require('../../aes') -async function getAllGuilds () { +async function getAllGuilds() { const doc = await pool.query('SELECT * FROM guilds;') return doc.rows } -async function getGuild (guildID) { +async function getGuild(guildID) { const doc = await pool.query('SELECT * FROM guilds WHERE id=$1;', [guildID]) if (doc.rows.length === 0) { if (global.bot.guilds.get(guildID)) { @@ -18,35 +18,20 @@ async function getGuild (guildID) { return doc.rows[0] } -async function getMessagesByAuthor (userID) { - const resp = await pool.query('SELECT * FROM messages WHERE author_id=$1', [userID]) - const promiseArray = resp.rows.map(m => { - const decryptedMessage = decryptMessageDoc(m) - return decryptedMessage - }) - const done = await Promise.all(promiseArray) - return done -} - -async function getMessageById (messageID) { +async function getMessageById(messageID) { let message = await pool.query('SELECT * FROM messages WHERE id=$1', [messageID]) if (message.rows.length === 0) return null message = await decryptMessageDoc(message.rows[0]) return message } -async function decryptUserDoc (userDoc) { - userDoc.names = JSON.parse(aes.decrypt(userDoc.names)) - return userDoc -} - -async function decryptMessageDoc (message) { +async function decryptMessageDoc(message) { message.content = aes.decrypt(message.content) if (message.attachment_b64) message.attachment_b64 = message.attachment_b64.split("|").map(encrypted_img_url => aes.decrypt(encrypted_img_url)).join("|") return message } -async function getMessagesByIds (messageIds) { +async function getMessagesByIds(messageIds) { const message = await pool.query('SELECT * FROM messages WHERE id = ANY ($1)', [messageIds]) if (message.rows.length === 0) return null const decryptedMessages = [] @@ -57,7 +42,6 @@ async function getMessagesByIds (messageIds) { } exports.getMessageById = getMessageById -exports.getMessagesByAuthor = getMessagesByAuthor exports.getAllGuilds = getAllGuilds exports.getGuild = getGuild exports.getMessagesByIds = getMessagesByIds diff --git a/src/db/interfaces/postgres/update.js b/src/db/interfaces/postgres/update.js index e34ec97..6668464 100644 --- a/src/db/interfaces/postgres/update.js +++ b/src/db/interfaces/postgres/update.js @@ -1,71 +1,18 @@ const pool = require('../../clients/postgres') -const escape = require('markdown-escape') -const getDoc = require('./read').getGuild -const getMessageById = require('./read').getMessageById +const { getGuild } = require('./read') const cacheGuild = require('../../../bot/utils/cacheGuild') -const getMessageFromBatch = require('../../messageBatcher').getMessage -const updateBatchMessage = require('../../messageBatcher').updateMessage +const { eventLogs } = require("../../../bot/utils/constants") +const { getMessage } = require('../../messageBatcher') +const { updateMessage } = require('../../messageBatcher') const aes = require('../../aes') -const eventList = [ - 'channelCreate', - 'channelUpdate', - 'channelDelete', - 'guildBanAdd', - 'guildBanRemove', - 'guildRoleCreate', - 'guildRoleDelete', - 'guildRoleUpdate', - 'guildUpdate', - 'messageDelete', - 'messageDeleteBulk', - 'messageUpdate', - 'guildMemberAdd', - 'guildMemberKick', - 'guildMemberRemove', - 'guildMemberUpdate', - 'voiceChannelLeave', - 'voiceChannelJoin', - 'voiceStateUpdate', - 'voiceChannelSwitch', - 'guildEmojisUpdate', - 'guildMemberNickUpdate' -] - -const eventLogs = { - channelCreate: '', - channelUpdate: '', - channelDelete: '', - guildBanAdd: '', - guildBanRemove: '', - guildRoleCreate: '', - guildRoleDelete: '', - guildRoleUpdate: '', - guildUpdate: '', - messageDelete: '', - messageDeleteBulk: '', - messageUpdate: '', - guildMemberAdd: '', - guildMemberKick: '', - guildMemberRemove: '', - guildMemberUpdate: '', - voiceChannelLeave: '', - voiceChannelJoin: '', - voiceStateUpdate: '', - voiceChannelSwitch: '', - guildEmojisUpdate: '', - guildMemberNickUpdate: '', - guildMemberBoostUpdate: '', - guildMemberVerify: '' // I am a moron for having an object representing -} // default event settings in multiple places instead of in constants.js - async function clearEventLog (guildID) { await cacheGuild(guildID) return await pool.query('UPDATE guilds SET event_logs=$1 WHERE id=$2', [eventLogs, guildID]) } async function clearEventByID (guildID, channelID) { - const doc = await getDoc(guildID) + const doc = await getGuild(guildID) const eventLogs = doc.event_logs Object.keys(eventLogs).forEach(event => { if (eventLogs[event] === channelID) { @@ -77,7 +24,7 @@ async function clearEventByID (guildID, channelID) { } async function setAllEventsOneId (guildID, channelID) { - const doc = await getDoc(guildID) + const doc = await getGuild(guildID) const eventLogs = doc.event_logs Object.keys(eventLogs).forEach(event => { eventLogs[event] = channelID @@ -87,7 +34,7 @@ async function setAllEventsOneId (guildID, channelID) { } async function setEventsLogId (guildID, channelID, events) { - const doc = await getDoc(guildID) + const doc = await getGuild(guildID) events.forEach(event => { doc.event_logs[event] = channelID }) @@ -95,15 +42,8 @@ async function setEventsLogId (guildID, channelID, events) { await cacheGuild(guildID) } -// async function setEventsRawLogs (guildID, channelID, events) { -// const doc = await getDoc(guildID) -// doc.event_logs = { ...doc.event_logs, ...events } -// await pool.query('UPDATE guilds SET event_logs=$1 WHERE id=$2', [doc.event_logs, guildID]) -// await cacheGuild(guildID) -// } - async function disableEvent (guildID, event) { - const doc = await getDoc(guildID) + const doc = await getGuild(guildID) let disabled = true if (doc.disabled_events.includes(event)) { doc.disabled_events.splice(doc.disabled_events.indexOf(event), 1) @@ -118,7 +58,7 @@ async function disableEvent (guildID, event) { } async function ignoreChannel (guildID, channelID) { - const doc = await getDoc(guildID) + const doc = await getGuild(guildID) let disabled = true if (doc.ignored_channels.includes(channelID)) { const index = doc.ignored_channels.indexOf(channelID) @@ -138,14 +78,14 @@ async function clearIgnoredChannels (guildID) { } async function toggleLogBots (guildID) { - const doc = await getDoc(guildID) + const doc = await getGuild(guildID) await pool.query('UPDATE guilds SET log_bots=$1 WHERE id=$2', [!doc.log_bots, guildID]) global.bot.guildSettingsCache[guildID].logBots = !doc.log_bots return !doc.log_bots } async function updateMessageByID (id, changedAttrs) { - const batchMessage = getMessageFromBatch(id) + const batchMessage = getMessage(id) if (!batchMessage) { if ('imageUrls' in changedAttrs) { const newAttachmentB64 = changedAttrs.imageUrls.map(url => aes.encrypt(Buffer.from(url).toString("base64url"))).join("|") @@ -164,7 +104,7 @@ async function updateMessageByID (id, changedAttrs) { global.webhook.warn(msg); } } else { - updateBatchMessage(id, changedAttrs) + updateMessage(id, changedAttrs) } } @@ -176,5 +116,4 @@ exports.clearEventByID = clearEventByID exports.setAllEventsOneId = setAllEventsOneId exports.setEventsLogId = setEventsLogId exports.clearIgnoredChannels = clearIgnoredChannels -// exports.setEventsRawLogs = setEventsRawLogs exports.updateMessageByID = updateMessageByID diff --git a/src/db/messageBatcher.js b/src/db/messageBatcher.js index 0f1fec7..cfe5c11 100644 --- a/src/db/messageBatcher.js +++ b/src/db/messageBatcher.js @@ -3,8 +3,9 @@ const format = require('pg-format') const pool = require('./clients/postgres') const aes = require('./aes') const batch = [] -global.timesSubmitted = 0 -global.totalMessagesSubmitted = 0 +// Change these out to use let instead of populating 'global' with something that is only used in this file. +let timesSubmitted = 0 +let totalMessagesSubmitted = 0 function getBatchSize() { return +process.env.MESSAGE_BATCH_SIZE || 1000 @@ -23,10 +24,10 @@ async function submitBatch (batchSize) { const poolClient = await pool.getPostgresClient() await poolClient.query(format('INSERT INTO messages (id, author_id, content, attachment_b64, ts) VALUES %L ON CONFLICT DO NOTHING', toSubmit)) poolClient.release() - global.timesSubmitted += 1 - global.totalMessagesSubmitted += batchSize + timesSubmitted += 1 + totalMessagesSubmitted += batchSize - const msg = `Submitted ${toSubmit.length} messages within batch #${global.timesSubmitted} (${global.totalMessagesSubmitted} total).`; + const msg = `Submitted ${toSubmit.length} messages within batch #${timesSubmitted} (${totalMessagesSubmitted} total).`; global.logger.info(msg) global.webhook.generic(msg) diff --git a/src/miscellaneous/bezerk.js b/src/miscellaneous/bezerk.js index bbb6ea1..981e137 100644 --- a/src/miscellaneous/bezerk.js +++ b/src/miscellaneous/bezerk.js @@ -33,7 +33,7 @@ function start () { op: '1003', // IDENTIFY_SUPPLY c: { secret: secret, - shard: cluster.worker.rangeForShard + shard: global.cluster.worker.rangeForShard } }) } @@ -47,6 +47,7 @@ function start () { break } case '2001': { // REQUEST + // eslint-disable-next-line no-unused-vars const bot = global.bot try { if (msg.c.startsWith('recache')) { diff --git a/src/miscellaneous/generateDB.js b/src/miscellaneous/generateDB.js index 258863d..c102190 100644 --- a/src/miscellaneous/generateDB.js +++ b/src/miscellaneous/generateDB.js @@ -15,16 +15,17 @@ pool.on('error', e => { }) async function generate () { - await pool.query('CREATE DATABASE logger') // create db + await pool.query(`CREATE DATABASE ${process.env.PGDATABASE || 'logger'}`) // create db const loggerDB = new Pool({ user: process.env.PGUSER, host: process.env.PGHOST, - database: 'logger', + database: process.env.PGDATABASE || 'logger', password: process.env.PGPASSWORD, port: process.env.PGPORT ?? 5432 }) - await loggerDB.query('CREATE TABLE messages ( id TEXT PRIMARY KEY, author_id TEXT NOT NULL, content TEXT, attachment_b64 TEXT, ts TIMESTAMPTZ )') // establish messages table - await loggerDB.query('CREATE TABLE guilds ( id TEXT PRIMARY KEY, owner_id TEXT NOT NULL, ignored_channels TEXT[], disabled_events TEXT[], event_logs JSON, log_bots BOOL, custom_settings JSON )') // establish guilds table + // Only create these if it doesn't exist already. + await loggerDB.query('CREATE TABLE IF NOT EXISTS messages ( id TEXT PRIMARY KEY, author_id TEXT NOT NULL, content TEXT, attachment_b64 TEXT, ts TIMESTAMPTZ )') // establish messages table + await loggerDB.query('CREATE TABLE IF NOT EXISTS guilds ( id TEXT PRIMARY KEY, owner_id TEXT NOT NULL, ignored_channels TEXT[], disabled_events TEXT[], event_logs JSON, log_bots BOOL, custom_settings JSON )') // establish guilds table console.log('DB Generated!') } diff --git a/src/miscellaneous/workerlistener.js b/src/miscellaneous/workerlistener.js index c3b7c78..188dc85 100644 --- a/src/miscellaneous/workerlistener.js +++ b/src/miscellaneous/workerlistener.js @@ -12,7 +12,7 @@ if (process.env.STAT_SUBMISSION_INTERVAL && !isNaN(parseInt(process.env.STAT_SUB allWorkers.forEach(w => { w.send({ type: 'sendStats' }) }) - await new Promise((resolve, reject) => { + await new Promise((resolve) => { setTimeout(() => { resolve('ok') }, 2000) From 9551a5d2b67b75af4a6d5b82a2410aa806abe4e3 Mon Sep 17 00:00:00 2001 From: Elara Services <43923163+Elara-Discord-Bots@users.noreply.github.com> Date: Sun, 14 Apr 2024 20:08:15 -0700 Subject: [PATCH 02/13] move to displayUser function --- src/bot/commands/archive.js | 3 ++- src/bot/commands/clearmydata.js | 6 ++++-- src/bot/commands/help.js | 6 ++++-- src/bot/commands/ignorechannel.js | 6 ++++-- src/bot/commands/info.js | 6 ++++-- src/bot/commands/invite.js | 6 ++++-- src/bot/commands/logbots.js | 5 +++-- src/bot/commands/reset.js | 15 ++++++++------- src/bot/commands/serverinfo.js | 3 ++- src/bot/commands/stoplogging.js | 5 +++-- src/bot/commands/togglemodule.js | 9 +++++---- src/bot/commands/userinfo.js | 4 +++- src/bot/events/channelCreate.js | 3 ++- src/bot/events/channelDelete.js | 5 +++-- src/bot/events/channelUpdate.js | 5 +++-- src/bot/events/guildBanAdd.js | 9 +++++---- src/bot/events/guildBanRemove.js | 9 +++++---- src/bot/events/guildEmojisUpdate.js | 3 ++- src/bot/events/guildMemberAdd.js | 5 +++-- src/bot/events/guildMemberRemove.js | 15 ++++++++------- src/bot/events/guildMemberUpdate.js | 21 +++++++++++---------- src/bot/events/guildRoleCreate.js | 3 ++- src/bot/events/guildRoleDelete.js | 3 ++- src/bot/events/guildRoleUpdate.js | 3 ++- src/bot/events/guildUpdate.js | 3 ++- src/bot/events/interactionCreate.js | 4 ++-- src/bot/events/messageDelete.js | 4 ++-- src/bot/events/messageDeleteBulk.js | 3 ++- src/bot/events/messageUpdate.js | 6 +++--- src/bot/events/voiceChannelJoin.js | 5 +++-- src/bot/events/voiceChannelLeave.js | 5 +++-- src/bot/events/voiceChannelSwitch.js | 5 +++-- src/bot/events/voiceStateUpdate.js | 7 ++++--- src/bot/modules/commandhandler.js | 5 +++-- src/bot/modules/webhooksender.js | 4 ++-- src/bot/slashcommands/archive.js | 6 +++--- src/bot/slashcommands/clearmydata.js | 3 ++- src/bot/slashcommands/serverinfo.js | 4 +++- src/bot/slashcommands/userinfo.js | 4 ++-- src/bot/utils/constants.js | 15 +++++++++------ src/bot/utils/embeds.js | 6 ++++-- 41 files changed, 146 insertions(+), 101 deletions(-) diff --git a/src/bot/commands/archive.js b/src/bot/commands/archive.js index da7c410..1f0af1d 100644 --- a/src/bot/commands/archive.js +++ b/src/bot/commands/archive.js @@ -1,3 +1,4 @@ +const { displayUser } = require('../utils/constants'); const { createHaste } = require('../utils/createHaste') module.exports = { @@ -9,7 +10,7 @@ module.exports = { if (num < 5 || num > limit) return message.channel.createMessage(`That number is invalid! Please provide any number between 5 and ${limit}`) const messages = await message.channel.getMessages({ limit: num }) - const pasteString = messages.reverse().filter(m => !m.applicationID).map(m => `${m.author.username}${m.author.discriminator === '0' ? '' : `#${m.author.discriminator}`} (${m.author.id}) | ${new Date(m.timestamp).toUTCString()}: ${m.content ? m.content : ''} ${m.embeds.length === 0 ? '' : `| {"embeds": [${m.embeds.map(e => JSON.stringify(e))}]}`} | ${m.attachments.length === 0 ? '' : ` =====> Attachment: ${m.attachments[0].filename}:${m.attachments[0].url}`}`).join('\r\n') + const pasteString = messages.reverse().filter(m => !m.applicationID).map(m => `${displayUser(m.author)} (${m.author.id}) | ${new Date(m.timestamp).toUTCString()}: ${m.content ? m.content : ''} ${m.embeds.length === 0 ? '' : `| {"embeds": [${m.embeds.map(e => JSON.stringify(e))}]}`} | ${m.attachments.length === 0 ? '' : ` =====> Attachment: ${m.attachments[0].filename}:${m.attachments[0].url}`}`).join('\r\n') const link = await createHaste(pasteString) if (!link) { return message.channel.createMessage('Unable to get the archive haste link') diff --git a/src/bot/commands/clearmydata.js b/src/bot/commands/clearmydata.js index cf6b8eb..134e6d9 100644 --- a/src/bot/commands/clearmydata.js +++ b/src/bot/commands/clearmydata.js @@ -1,3 +1,5 @@ +const { displayUser } = require("../utils/constants") + module.exports = { func: async message => { await message.channel.createMessage({ @@ -8,10 +10,10 @@ module.exports = { timestamp: new Date(), footer: { icon_url: global.bot.user.avatarURL, - text: `${global.bot.user.username}#${global.bot.user.discriminator}` + text: displayUser(global.bot.user) }, author: { - name: `${message.author.username}${message.author.discriminator === '0' ? '' : `#${message.author.discriminator}`}`, + name: displayUser(message.author), icon_url: message.author.avatarURL }, fields: [] diff --git a/src/bot/commands/help.js b/src/bot/commands/help.js index 57e354a..59dc70d 100644 --- a/src/bot/commands/help.js +++ b/src/bot/commands/help.js @@ -1,3 +1,5 @@ +const { displayUser } = require("../utils/constants") + module.exports = { func: async (message, suffix) => { let DMC @@ -30,13 +32,13 @@ module.exports = { timestamp: new Date(), footer: { icon_url: global.bot.user.avatarURL, - text: `${global.bot.user.username}#${global.bot.user.discriminator}` + text: displayUser(global.bot.user) }, thumbnail: { url: global.bot.user.avatarURL }, author: { - name: `${message.author.username}${message.author.discriminator === '0' ? '' : `#${message.author.discriminator}`}`, + name: displayUser(message.author), icon_url: message.author.avatarURL }, fields: [] diff --git a/src/bot/commands/ignorechannel.js b/src/bot/commands/ignorechannel.js index 0352b4e..b0a7bd3 100644 --- a/src/bot/commands/ignorechannel.js +++ b/src/bot/commands/ignorechannel.js @@ -1,3 +1,5 @@ +const { displayUser } = require('../utils/constants') + const ignoreChannel = require('../../db/interfaces/postgres/update').ignoreChannel module.exports = { @@ -17,10 +19,10 @@ module.exports = { timestamp: new Date(), footer: { icon_url: global.bot.user.avatarURL, - text: `${global.bot.user.username}#${global.bot.user.discriminator}` + text: displayUser(global.bot.user) }, author: { - name: `${message.author.username}${message.author.discriminator === '0' ? '' : `#${message.author.discriminator}`}`, + name: displayUser(message.author), icon_url: message.author.avatarURL } }] diff --git a/src/bot/commands/info.js b/src/bot/commands/info.js index 5c2fe18..bfe4e8e 100644 --- a/src/bot/commands/info.js +++ b/src/bot/commands/info.js @@ -1,3 +1,5 @@ +const { displayUser } = require("../utils/constants") + module.exports = { func: async message => { await message.channel.createMessage({ @@ -8,13 +10,13 @@ module.exports = { timestamp: new Date(), footer: { icon_url: global.bot.user.avatarURL, - text: `${global.bot.user.username}#${global.bot.user.discriminator}` + text: displayUser(global.bot.user) }, thumbnail: { url: global.bot.user.avatarURL }, author: { - name: `${message.author.username}${message.author.discriminator === '0' ? '' : `#${message.author.discriminator}`}`, + name: displayUser(message.author), icon_url: message.author.avatarURL }, fields: [ diff --git a/src/bot/commands/invite.js b/src/bot/commands/invite.js index 554baad..d95680f 100644 --- a/src/bot/commands/invite.js +++ b/src/bot/commands/invite.js @@ -1,3 +1,5 @@ +const { displayUser } = require("../utils/constants") + module.exports = { func: async message => { message.channel.createMessage({ @@ -7,10 +9,10 @@ module.exports = { timestamp: new Date(), footer: { icon_url: global.bot.user.avatarURL, - text: `${global.bot.user.username}#${global.bot.user.discriminator}` + text: displayUser(global.bot.user) }, author: { - name: `${message.author.username}${message.author.discriminator === '0' ? '' : `#${message.author.discriminator}`}`, + name: displayUser(message.author), icon_url: message.author.avatarURL } }] diff --git a/src/bot/commands/logbots.js b/src/bot/commands/logbots.js index e77cd29..f001515 100644 --- a/src/bot/commands/logbots.js +++ b/src/bot/commands/logbots.js @@ -1,4 +1,5 @@ const { toggleLogBots } = require('../../db/interfaces/postgres/update') +const { displayUser } = require('../utils/constants') module.exports = { func: async message => { @@ -10,10 +11,10 @@ module.exports = { timestamp: new Date(), footer: { icon_url: global.bot.user.avatarURL, - text: `${global.bot.user.username}#${global.bot.user.discriminator}` + text: displayUser(global.bot.user) }, author: { - name: `${message.author.username}${message.author.discriminator === '0' ? '' : `#${message.author.discriminator}`}`, + name: displayUser(message.author), icon_url: message.author.avatarURL }, fields: [] diff --git a/src/bot/commands/reset.js b/src/bot/commands/reset.js index 226fd59..0740d35 100644 --- a/src/bot/commands/reset.js +++ b/src/bot/commands/reset.js @@ -1,4 +1,5 @@ const cacheGuild = require('../utils/cacheGuild') +const { displayUser } = require('../utils/constants') const deleteGuild = require('../../db/interfaces/postgres/delete').deleteGuild const createGuild = require('../../db/interfaces/postgres/create').createGuild @@ -6,15 +7,15 @@ module.exports = { func: async message => { const msg = await message.channel.createMessage({ embeds: [{ - description: `Are you absolutely sure, ${message.author.username}${message.author.discriminator === '0' ? '' : `#${message.author.discriminator}`} (${message.author.id})? Reply *yes* if so.`, + description: `Are you absolutely sure, ${displayUser(message.author)} (${message.author.id})? Reply *yes* if so.`, color: 3553599, timestamp: new Date(), footer: { icon_url: global.bot.user.avatarURL, - text: `${global.bot.user.username}#${global.bot.user.discriminator}` + text: displayUser(global.bot.user) }, author: { - name: `${message.author.username}${message.author.discriminator === '0' ? '' : `#${message.author.discriminator}`}`, + name: displayUser(message.author), icon_url: message.author.avatarURL } }] @@ -33,10 +34,10 @@ module.exports = { timestamp: new Date(), footer: { icon_url: global.bot.user.avatarURL, - text: `${global.bot.user.username}#${global.bot.user.discriminator}` + text: displayUser(global.bot.user) }, author: { - name: `${message.author.username}${message.author.discriminator === '0' ? '' : `#${message.author.discriminator}`}`, + name: displayUser(message.author), icon_url: message.author.avatarURL } }] @@ -53,10 +54,10 @@ module.exports = { timestamp: new Date(), footer: { icon_url: global.bot.user.avatarURL, - text: `${global.bot.user.username}#${global.bot.user.discriminator}` + text: displayUser(global.bot.user) }, author: { - name: `${message.author.username}${message.author.discriminator === '0' ? '' : `#${message.author.discriminator}`}`, + name: displayUser(message.author), icon_url: message.author.avatarURL } }] diff --git a/src/bot/commands/serverinfo.js b/src/bot/commands/serverinfo.js index 2803ad9..a92caff 100644 --- a/src/bot/commands/serverinfo.js +++ b/src/bot/commands/serverinfo.js @@ -1,4 +1,5 @@ const escape = require('markdown-escape') +const { displayUser } = require('../utils/constants') module.exports = { func: async message => { @@ -15,7 +16,7 @@ module.exports = { value: `${message.channel.guild.verificationLevel}` }, { name: 'Owner', - value: `${owner ? `**${owner.username}${owner.discriminator === '0' ? '' : `#${owner.discriminator}`}** ` : ''}(${message.channel.guild.ownerID})` + value: `${owner ? `**${displayUser(owner)}** ` : ''}(${message.channel.guild.ownerID})` }, { name: 'Features', value: message.channel.guild.features.length !== 0 ? message.channel.guild.features.join(', ') : 'No Guild Features' diff --git a/src/bot/commands/stoplogging.js b/src/bot/commands/stoplogging.js index 9d08967..d38b0dd 100644 --- a/src/bot/commands/stoplogging.js +++ b/src/bot/commands/stoplogging.js @@ -1,5 +1,6 @@ const clearEventByID = require('../../db/interfaces/postgres/update').clearEventByID const cacheGuild = require('../utils/cacheGuild') +const { displayUser } = require('../utils/constants') const setEventLogs = require('../../db/interfaces/postgres/update').setEventsLogId const eventList = require('../utils/constants').ALL_EVENTS @@ -27,10 +28,10 @@ module.exports = { timestamp: new Date(), footer: { icon_url: global.bot.user.avatarURL, - text: `${global.bot.user.username}#${global.bot.user.discriminator}` + text: displayUser(global.bot.user) }, author: { - name: `${message.author.username}${message.author.discriminator === '0' ? '' : `#${message.author.discriminator}`}`, + name: displayUser(message.author), icon_url: message.author.avatarURL }, fields: [] diff --git a/src/bot/commands/togglemodule.js b/src/bot/commands/togglemodule.js index 7aab566..762b948 100644 --- a/src/bot/commands/togglemodule.js +++ b/src/bot/commands/togglemodule.js @@ -1,3 +1,4 @@ +const { displayUser } = require('../utils/constants') const disableEvent = require('../../db/interfaces/postgres/update').disableEvent const eventList = require('../utils/constants').ALL_EVENTS @@ -12,10 +13,10 @@ module.exports = { timestamp: new Date(), footer: { icon_url: global.bot.user.avatarURL, - text: `${global.bot.user.username}#${global.bot.user.discriminator}` + text: displayUser(global.bot.user) }, author: { - name: `${message.author.username}${message.author.discriminator === '0' ? '' : `#${message.author.discriminator}`}`, + name: displayUser(message.author), icon_url: message.author.avatarURL } }] @@ -30,10 +31,10 @@ module.exports = { timestamp: new Date(), footer: { icon_url: global.bot.user.avatarURL, - text: `${global.bot.user.username}#${global.bot.user.discriminator}` + text: displayUser(global.bot.user) }, author: { - name: `${message.author.username}${message.author.discriminator === '0' ? '' : `#${message.author.discriminator}`}`, + name: displayUser(message.author), icon_url: message.author.avatarURL } }] diff --git a/src/bot/commands/userinfo.js b/src/bot/commands/userinfo.js index bfcfc1e..ab3b914 100644 --- a/src/bot/commands/userinfo.js +++ b/src/bot/commands/userinfo.js @@ -1,3 +1,5 @@ +const { displayUser } = require("../utils/constants") + const notablePermissions = [ 'kickMembers', 'banMembers', @@ -25,7 +27,7 @@ module.exports = { const roles = member.roles.map(r => message.channel.guild.roles.get(r)).sort((a, b) => b.position - a.position) fields.push({ name: 'Name', - value: `${member.username}${member.discriminator === '0' ? '' : `#${member.discriminator}`} ${member.nick ? `(**${member.nick}**)` : ''} (${member.id})` + value: `${displayUser(member)} ${member.nick ? `(**${member.nick}**)` : ''} (${member.id})` }, { name: 'Join Date', value: ` ()` diff --git a/src/bot/events/channelCreate.js b/src/bot/events/channelCreate.js index 53f06dd..aa9365d 100644 --- a/src/bot/events/channelCreate.js +++ b/src/bot/events/channelCreate.js @@ -1,4 +1,5 @@ const send = require('../modules/webhooksender') +const { displayUser } = require('../utils/constants') const CHANNEL_TYPE_MAP = { 0: 'Text channel', 2: 'Voice channel', @@ -52,7 +53,7 @@ module.exports = { if (user && user?.bot && !global.bot.guildSettingsCache[newChannel.guild.id].isLogBots()) return if (user) { const member = newChannel.guild.members.get(user.id) - channelCreateEvent.embeds[0].author.name = `${user.username}${user.discriminator === '0' ? '' : `#${user.discriminator}`} ${member && member.nick ? `(${member.nick})` : ''}` + channelCreateEvent.embeds[0].author.name = `${displayUser(user)} ${member && member.nick ? `(${member.nick})` : ''}` channelCreateEvent.embeds[0].author.icon_url = user.avatarURL channelCreateEvent.embeds[0].fields[1].value = `\`\`\`ini\nUser = ${user.id}\nChannel = ${newChannel.id}\`\`\`` } diff --git a/src/bot/events/channelDelete.js b/src/bot/events/channelDelete.js index b042508..2f8b0ac 100644 --- a/src/bot/events/channelDelete.js +++ b/src/bot/events/channelDelete.js @@ -1,4 +1,5 @@ const send = require('../modules/webhooksender') +const { displayUser } = require('../utils/constants') const CHANNEL_TYPE_MAP = { 0: 'Text channel', 2: 'Voice channel', @@ -45,7 +46,7 @@ module.exports = { const user = global.bot.users.get(lastCachedMessage.userID) channelDeleteEvent.embeds[0].fields.push({ name: 'Last message', - value: `Author: **${user.username}${user.discriminator === '0' ? '' : `#${user.discriminator}`}**\n${lastCachedMessage.content}` + value: `Author: **${displayUser(user)}**\n${lastCachedMessage.content}` }) } if (channel.permissionOverwrites.size !== 0) { @@ -68,7 +69,7 @@ module.exports = { if (user && user?.bot && !global.bot.guildSettingsCache[channel.guild.id].isLogBots()) return if (user) { const member = channel.guild.members.get(user.id) - channelDeleteEvent.embeds[0].author.name = `${user.username}${user.discriminator === '0' ? '' : `#${user.discriminator}`} ${member && member.nick ? `(${member.nick})` : ''}` + channelDeleteEvent.embeds[0].author.name = `${displayUser(user)} ${member && member.nick ? `(${member.nick})` : ''}` channelDeleteEvent.embeds[0].author.icon_url = user.avatarURL channelDeleteEvent.embeds[0].fields[3].value = `\`\`\`ini\nUser = ${user.id}\nChannel = ${channel.id}\`\`\`` } diff --git a/src/bot/events/channelUpdate.js b/src/bot/events/channelUpdate.js index 844f19d..193f1d1 100644 --- a/src/bot/events/channelUpdate.js +++ b/src/bot/events/channelUpdate.js @@ -1,5 +1,6 @@ const send = require('../modules/webhooksender') const escape = require('markdown-escape') +const { displayUser } = require('../utils/constants') const CHANNEL_TYPE_MAP = { 0: 'Text channel', 2: 'Voice channel', @@ -35,7 +36,7 @@ module.exports = { icon_url: 'https://logger.bot/staticfiles/red-x.png' }, color: 0x03d3fc, - description: `${CHANNEL_TYPE_MAP[channel.type] ? CHANNEL_TYPE_MAP[channel.type] : 'unsupported channel'} <#${channel.id}> was updated (${escape(channel.name)})`, + description: `${CHANNEL_TYPE_MAP[channel.type] || 'unsupported channel'} <#${channel.id}> was updated (${escape(channel.name)})`, fields: [{ name: 'Creation date', value: ``, @@ -201,7 +202,7 @@ module.exports = { } if (log && user) { - channelUpdateEvent.embeds[0].author.name = `${user.username}${user.discriminator === '0' ? '' : `#${user.discriminator}`}` + channelUpdateEvent.embeds[0].author.name = `${displayUser(user)}` channelUpdateEvent.embeds[0].author.icon_url = user.avatarURL if (channel.type === 13) { channelUpdateEvent.embeds[0].description = `Stage Channel **${channel.name}** was ${channel.topic === null ? 'closed' : 'opened'}` diff --git a/src/bot/events/guildBanAdd.js b/src/bot/events/guildBanAdd.js index 5abb832..4a6c58c 100644 --- a/src/bot/events/guildBanAdd.js +++ b/src/bot/events/guildBanAdd.js @@ -1,4 +1,5 @@ const send = require('../modules/webhooksender') +const { displayUser } = require('../utils/constants') module.exports = { name: 'guildBanAdd', @@ -9,13 +10,13 @@ module.exports = { eventName: 'guildBanAdd', embeds: [{ author: { - name: `${user.username}${user.discriminator === '0' ? '' : `#${user.discriminator}`}`, + name: `${displayUser(user)}`, icon_url: user.avatarURL }, - description: `${user.username}${user.discriminator === '0' ? '' : `#${user.discriminator}`} was banned`, + description: `${displayUser(user)} was banned`, fields: [{ name: 'User Information', - value: `${user.username}${user.discriminator === '0' ? '' : `#${user.discriminator}`} (${user.id}) ${user.mention} ${user.bot ? '\nIs a bot' : ''}` + value: `${displayUser(user)} (${user.id}) ${user.mention} ${user.bot ? '\nIs a bot' : ''}` }, { name: 'Reason', value: 'None provided' @@ -50,7 +51,7 @@ module.exports = { if (log.reason) guildBanAddEvent.embeds[0].fields[1].value = log.reason guildBanAddEvent.embeds[0].fields[2].value = `\`\`\`ini\nUser = ${user.id}\nPerpetrator = ${perp.id}\`\`\`` guildBanAddEvent.embeds[0].footer = { - text: `${perp.username}${perp.discriminator === '0' ? '' : `#${perp.discriminator}`}`, + text: displayUser(perp), icon_url: perp.avatarURL } await send(guildBanAddEvent) diff --git a/src/bot/events/guildBanRemove.js b/src/bot/events/guildBanRemove.js index baae382..86a4574 100644 --- a/src/bot/events/guildBanRemove.js +++ b/src/bot/events/guildBanRemove.js @@ -1,4 +1,5 @@ const send = require('../modules/webhooksender') +const { displayUser } = require('../utils/constants') module.exports = { name: 'guildBanRemove', @@ -9,13 +10,13 @@ module.exports = { eventName: 'guildBanRemove', embeds: [{ author: { - name: `${user.username}${user.discriminator === '0' ? '' : `#${user.discriminator}`}`, + name: `${displayUser(user)}`, icon_url: user.avatarURL }, - description: `${user.username}${user.discriminator === '0' ? '' : `#${user.discriminator}`} was unbanned`, + description: `${displayUser(user)} was unbanned`, fields: [{ name: 'User Information', - value: `${user.username}${user.discriminator === '0' ? '' : `#${user.discriminator}`} (${user.id}) ${user.mention} ${user.bot ? '\nIs a bot' : ''}` + value: `${displayUser(user)} (${user.id}) ${user.mention} ${user.bot ? '\nIs a bot' : ''}` }, { name: 'Reason', value: 'None provided' @@ -34,7 +35,7 @@ module.exports = { if (log.reason) guildBanRemoveEvent.embeds[0].fields[1].value = log.reason guildBanRemoveEvent.embeds[0].fields[2].value = `\`\`\`ini\nUser = ${user.id}\nPerpetrator = ${perp.id}\`\`\`` guildBanRemoveEvent.embeds[0].footer = { - text: `${perp.username}${perp.discriminator === '0' ? '' : `#${perp.discriminator}`}`, + text: displayUser(perp), icon_url: perp.avatarURL } await send(guildBanRemoveEvent) diff --git a/src/bot/events/guildEmojisUpdate.js b/src/bot/events/guildEmojisUpdate.js index 7c3e59d..b40c185 100644 --- a/src/bot/events/guildEmojisUpdate.js +++ b/src/bot/events/guildEmojisUpdate.js @@ -1,4 +1,5 @@ const send = require('../modules/webhooksender') +const { displayUser } = require('../utils/constants') const AUDIT_ID = { added: 60, removed: 62, @@ -69,7 +70,7 @@ module.exports = { if (log && log.user) { // if the audit log is less than 3 seconds off const user = log.user guildEmojisUpdateEvent.embeds[0].author = { - name: `${user.username}${user.discriminator === '0' ? '' : `#${user.discriminator}`}`, + name: displayUser(user), icon_url: user.avatarURL } guildEmojisUpdateEvent.embeds[0].fields[1].value = `\`\`\`ini\nUser = ${user.id}\nEmoji = ${emoji.id}\`\`\`` diff --git a/src/bot/events/guildMemberAdd.js b/src/bot/events/guildMemberAdd.js index 18204e7..6094cb4 100644 --- a/src/bot/events/guildMemberAdd.js +++ b/src/bot/events/guildMemberAdd.js @@ -1,5 +1,6 @@ const send = require('../modules/webhooksender') const inviteCache = require('../modules/invitecache') +const { displayUser } = require('../utils/constants') module.exports = { name: 'guildMemberAdd', @@ -10,13 +11,13 @@ module.exports = { eventName: 'guildMemberAdd', embeds: [{ author: { - name: `${member.username}${member.discriminator === '0' ? '' : `#${member.discriminator}`}`, + name: displayUser(member), icon_url: member.avatarURL }, description: `<@${member.id}> joined `, fields: [{ name: 'Name', - value: `${member.username}${member.discriminator === '0' ? '' : `#${member.discriminator}`} (${member.id}) ${member.mention}` + value: `${displayUser(member)} (${member.id}) ${member.mention}` }, { name: 'Joined At', value: `` diff --git a/src/bot/events/guildMemberRemove.js b/src/bot/events/guildMemberRemove.js index d83d117..57b9878 100644 --- a/src/bot/events/guildMemberRemove.js +++ b/src/bot/events/guildMemberRemove.js @@ -1,5 +1,6 @@ const send = require('../modules/webhooksender') const { User } = require('eris') +const { displayUser } = require('../utils/constants') module.exports = { name: 'guildMemberRemove', @@ -35,17 +36,17 @@ module.exports = { event.eventName = 'guildMemberKick' event.embeds = [{ author: { - name: `${member.username}${member.discriminator === '0' ? '' : `#${member.discriminator}`} ${member.nick ? `(${member.nick})` : ''}`, + name: `${displayUser(member)} ${member.nick ? `(${member.nick})` : ''}`, icon_url: member.avatarURL }, color: 16711680, - description: `${member.username}${member.discriminator === '0' ? '' : `#${member.discriminator}`} ${member.nick ? `(${member.nick})` : ''} was kicked`, + description: `${displayUser(member)} ${member.nick ? `(${member.nick})` : ''} was kicked`, fields: [{ name: 'User Information', - value: `${member.username}${member.discriminator === '0' ? '' : `#${member.discriminator}`} (${member.id}) ${member.mention} ${member.bot ? '\nIs a bot' : ''}` + value: `${displayUser(member)} (${member.id}) ${member.mention} ${member.bot ? '\nIs a bot' : ''}` }], footer: { - text: `${user.username}${user.discriminator === '0' ? '' : `#${user.discriminator}`}`, + text: `${displayUser(user)}`, icon_url: user.avatarURL } }] @@ -70,14 +71,14 @@ module.exports = { // TODO: redo purge audit log stuff eventually (update: copy from patron bot eventually) event.embeds = [{ author: { - name: `${member.username}${member.discriminator === '0' ? '' : `#${member.discriminator}`}`, + name: `${displayUser(member)}`, icon_url: member.avatarURL }, color: 16711680, - description: `${member.username}${member.discriminator === '0' ? '' : `#${member.discriminator}`} left the server`, + description: `${displayUser(member)} left the server`, fields: [{ name: 'User Information', - value: `${member.username}${member.discriminator === '0' ? '' : `#${member.discriminator}`} (${member.id}) ${member.mention} ${member.bot ? '\nIs a bot' : ''}` + value: `${displayUser(member)} (${member.id}) ${member.mention} ${member.bot ? '\nIs a bot' : ''}` }] }] if (member.roles) { diff --git a/src/bot/events/guildMemberUpdate.js b/src/bot/events/guildMemberUpdate.js index ddefa62..95d6776 100644 --- a/src/bot/events/guildMemberUpdate.js +++ b/src/bot/events/guildMemberUpdate.js @@ -2,6 +2,7 @@ const send = require('../modules/webhooksender') const cacheGuild = require('../utils/cacheGuild') const arrayCompare = require('../utils/arraycompare') const markdownEscape = require('markdown-escape') +const { displayUser } = require('../utils/constants') const canUseExternal = guild => { const logChannelID = global.bot.guildSettingsCache[guild.id].event_logs.guildMemberUpdate @@ -25,10 +26,10 @@ module.exports = { eventName: 'guildMemberUpdate', embeds: [{ author: { - name: `${member.username}${member.discriminator === '0' ? '' : `#${member.discriminator}`}`, + name: `${displayUser(member)}`, icon_url: member.avatarURL }, - description: `${member.username}${member.discriminator === '0' ? '' : `#${member.discriminator}`} ${member.mention} ${member.nick ? `(${member.nick})` : ''} was updated`, + description: `${displayUser(member)} ${member.mention} ${member.nick ? `(${member.nick})` : ''} was updated`, fields: [{ name: 'Changes', value: 'Unknown. Look at the footer to see who updated the affected user.' @@ -59,9 +60,9 @@ module.exports = { await send(guildMemberUpdate) } else if (oldMember?.pending && !member.pending && guild.features.includes('MEMBER_VERIFICATION_GATE_ENABLED')) { guildMemberUpdate.eventName = 'guildMemberVerify' - guildMemberUpdate.embeds[0].description = `${member.mention} (${member.username}${member.discriminator === '0' ? '' : `#${member.discriminator}`}: \`${member.id}\`) has verified.` + guildMemberUpdate.embeds[0].description = `${member.mention} (${displayUser(member)}: \`${member.id}\`) has verified.` guildMemberUpdate.embeds[0].author = { - name: `${member.username}${member.discriminator === '0' ? '' : `#${member.discriminator}`}`, + name: `${displayUser(member)}`, icon_url: member.avatarURL } guildMemberUpdate.embeds[0].color = 0x1ced9a @@ -77,7 +78,7 @@ module.exports = { embedCopy.eventName = 'guildMemberBoostUpdate' embedCopy.embeds[0].description = `${member.mention} has ${newMemberHasBoostRole ? 'boosted' : 'stopped boosting'} the server.` embedCopy.embeds[0].author = { - name: `${member.username}${member.discriminator === '0' ? '' : `#${member.discriminator}`}`, + name: `${displayUser(member)}`, icon_url: member.avatarURL } embedCopy.embeds[0].color = member.premiumSince ? 0x15cc12 : 0xeb4034 @@ -120,7 +121,7 @@ module.exports = { } guildMemberUpdate.embeds[0].color = roleColor guildMemberUpdate.embeds[0].footer = { - text: `${user.username}${user.discriminator === '0' ? '' : `#${user.discriminator}`}`, + text: `${displayUser(user)}`, icon_url: user.avatarURL } guildMemberUpdate.embeds[0].fields.push({ @@ -130,19 +131,19 @@ module.exports = { if (!guildMemberUpdate.embeds[0].fields[0].value) return await send(guildMemberUpdate) } else if (possibleTimeoutLog) { - guildMemberUpdate.embeds[0].description = `${member.username}${member.discriminator === '0' ? '' : `#${member.discriminator}`} (${member.mention}) ${member.communicationDisabledUntil ? 'was timed out' : 'had their timeout removed'}` + guildMemberUpdate.embeds[0].description = `${displayUser(member)} (${member.mention}) ${member.communicationDisabledUntil ? 'was timed out' : 'had their timeout removed'}` guildMemberUpdate.embeds[0].author = { - name: `${member.username}${member.discriminator === '0' ? '' : `#${member.discriminator}`}`, + name: `${displayUser(member)}`, icon_url: member.avatarURL } guildMemberUpdate.embeds[0].footer = { - text: `${possibleTimeoutLog.user.username}${possibleTimeoutLog.user.discriminator === '0' ? '' : `#${possibleTimeoutLog.user.discriminator}`}`, + text: displayUser(possibleTimeoutLog.user), icon_url: possibleTimeoutLog.user.avatarURL } guildMemberUpdate.embeds[0].fields = [] guildMemberUpdate.embeds[0].fields.push({ name: 'Timeout Creator', - value: `${possibleTimeoutLog.user.username}${possibleTimeoutLog.user.discriminator === '0' ? '' : `#${possibleTimeoutLog.user.discriminator}`}` + value: displayUser(possibleTimeoutLog.user) }) if (possibleTimeoutLog.reason) { guildMemberUpdate.embeds[0].fields.push({ diff --git a/src/bot/events/guildRoleCreate.js b/src/bot/events/guildRoleCreate.js index ffea2cf..338af4a 100644 --- a/src/bot/events/guildRoleCreate.js +++ b/src/bot/events/guildRoleCreate.js @@ -1,4 +1,5 @@ const send = require('../modules/webhooksender') +const { displayUser } = require('../utils/constants') module.exports = { name: 'guildRoleCreate', @@ -34,7 +35,7 @@ module.exports = { if (log.reason) guildRoleCreateEvent.embeds[0].fields[1].value = log.reason guildRoleCreateEvent.embeds[0].fields[2].value = `\`\`\`ini\nRole = ${role.id}\nPerpetrator = ${perp.id}\`\`\`` guildRoleCreateEvent.embeds[0].author = { - name: `${perp.username}${perp.discriminator === '0' ? '' : `#${perp.discriminator}`}`, + name: displayUser(perp), icon_url: perp.avatarURL } await send(guildRoleCreateEvent) diff --git a/src/bot/events/guildRoleDelete.js b/src/bot/events/guildRoleDelete.js index b54c1bf..8dad786 100644 --- a/src/bot/events/guildRoleDelete.js +++ b/src/bot/events/guildRoleDelete.js @@ -1,4 +1,5 @@ const send = require('../modules/webhooksender') +const { displayUser } = require('../utils/constants') module.exports = { name: 'guildRoleDelete', @@ -31,7 +32,7 @@ module.exports = { if (log.reason) guildRoleDeleteEvent.embeds[0].fields[1].value = log.reason guildRoleDeleteEvent.embeds[0].fields[2].value = `\`\`\`ini\nRole = ${role.id}\nPerpetrator = ${perp.id}\`\`\`` guildRoleDeleteEvent.embeds[0].author = { - name: `${perp.username}${perp.discriminator === '0' ? '' : `#${perp.discriminator}`}`, + name: displayUser(perp), icon_url: perp.avatarURL } await send(guildRoleDeleteEvent) diff --git a/src/bot/events/guildRoleUpdate.js b/src/bot/events/guildRoleUpdate.js index fdbe91a..31988ad 100644 --- a/src/bot/events/guildRoleUpdate.js +++ b/src/bot/events/guildRoleUpdate.js @@ -1,4 +1,5 @@ const send = require('../modules/webhooksender') +const { displayUser } = require('../utils/constants') module.exports = { name: 'guildRoleUpdate', @@ -66,7 +67,7 @@ module.exports = { value: `\`\`\`ini\nRole = ${role.id}\nPerpetrator = ${log.user.id}\`\`\`` }) guildRoleUpdateEvent.embeds[0].author = { - name: `${log.user.username}${log.user.discriminator === '0' ? '' : `#${log.user.discriminator}`}`, + name: displayUser(log.user), icon_url: log.user.avatarURL } if (guildRoleUpdateEvent.embeds[0].fields.length === 1) return diff --git a/src/bot/events/guildUpdate.js b/src/bot/events/guildUpdate.js index 46ad834..a7088f2 100644 --- a/src/bot/events/guildUpdate.js +++ b/src/bot/events/guildUpdate.js @@ -1,5 +1,6 @@ const escape = require('markdown-escape') const send = require('../modules/webhooksender') +const { displayUser } = require('../utils/constants') const checkExempt = [ 'afk_channel_id', @@ -51,7 +52,7 @@ module.exports = { eventName: 'guildUpdate', embeds: [{ author: { - name: `${user.username}${user.discriminator === '0' ? '' : `#${user.discriminator}`} ${member && member.nick ? `(${member.nick})` : ''}`, + name: `${displayUser(user)} ${member && member.nick ? `(${member.nick})` : ''}`, icon_url: user.avatarURL }, description: 'The guild was updated', diff --git a/src/bot/events/interactionCreate.js b/src/bot/events/interactionCreate.js index 29e18b1..8f425d1 100644 --- a/src/bot/events/interactionCreate.js +++ b/src/bot/events/interactionCreate.js @@ -1,7 +1,7 @@ const fs = require('fs') const path = require('path') const Eris = require('eris') -const { EMBED_COLORS } = require('../utils/constants') +const { EMBED_COLORS, displayUser } = require('../utils/constants') const { getEmbedFooter, getAuthorField } = require('../utils/embeds') const { NewsThreadChannel, PrivateThreadChannel, PublicThreadChannel } = require('eris') @@ -105,7 +105,7 @@ module.exports = { } const guild = global.bot.guilds.get(interaction.guildID) if (guild) { - global.logger.info(`${interaction.member.username}${interaction.member.discriminator === '0' ? '' : `#${interaction.member.discriminator}`} (${interaction.member.id}) in ${interaction.channel.id} sent /${command.name}. The guild is called "${guild.name}", owned by ${guild.ownerID} and has ${guild.memberCount} members.`) + global.logger.info(`${displayUser(interaction.member)} (${interaction.member.id}) in ${interaction.channel.id} sent /${command.name}. The guild is called "${guild.name}", owned by ${guild.ownerID} and has ${guild.memberCount} members.`) try { command.func(interaction) } catch (commandError) { diff --git a/src/bot/events/messageDelete.js b/src/bot/events/messageDelete.js index 4ee8d94..39656d1 100644 --- a/src/bot/events/messageDelete.js +++ b/src/bot/events/messageDelete.js @@ -3,7 +3,7 @@ const { getMessageById } = require('../../db/interfaces/postgres/read') const { getMessage } = require('../../db/messageBatcher') const { deleteMessage } = require('../../db/interfaces/postgres/delete') const cacheGuild = require('../utils/cacheGuild') -const { chunkify } = require('../utils/constants') +const { chunkify, displayUser } = require('../utils/constants') module.exports = { name: 'messageDelete', @@ -31,7 +31,7 @@ module.exports = { eventName: 'messageDelete', embeds: [{ author: { - name: cachedUser ? `${cachedUser.username}${cachedUser.discriminator === '0' ? '' : `#${cachedUser.discriminator}`} ${member && member.nick ? `(${member.nick})` : ''}` : `Unknown User <@${cachedMessage.author_id}>`, + name: cachedUser ? `${displayUser(cachedUser)} ${member && member.nick ? `(${member.nick})` : ''}` : `Unknown User <@${cachedMessage.author_id}>`, icon_url: cachedUser ? cachedUser.avatarURL : 'https://logger.bot/staticfiles/red-x.png' }, description: `Message deleted in <#${message.channel.id}>`, diff --git a/src/bot/events/messageDeleteBulk.js b/src/bot/events/messageDeleteBulk.js index 5474134..dbc9881 100644 --- a/src/bot/events/messageDeleteBulk.js +++ b/src/bot/events/messageDeleteBulk.js @@ -1,5 +1,6 @@ const { getMessagesByIds } = require('../../db/interfaces/postgres/read') const send = require('../modules/webhooksender') +const { displayUser } = require('../utils/constants') const { createHaste } = require('../utils/createHaste') module.exports = { @@ -24,7 +25,7 @@ async function paste(messages, guildID) { avatarURL: '' } } - return `${globalUser.username}${globalUser.discriminator === '0' ? '' : `#${globalUser.discriminator}`} (${m.author_id}) | (${globalUser.avatarURL}) | ${new Date(m.ts).toUTCString()}: ${m.content}` + return `${displayUser(globalUser)} (${m.author_id}) | (${globalUser.avatarURL}) | ${new Date(m.ts).toUTCString()}: ${m.content}` }).join('\r\n') if (!pasteString) { return diff --git a/src/bot/events/messageUpdate.js b/src/bot/events/messageUpdate.js index 40f3707..562a1c8 100644 --- a/src/bot/events/messageUpdate.js +++ b/src/bot/events/messageUpdate.js @@ -3,7 +3,7 @@ const { updateMessageByID } = require('../../db/interfaces/postgres/update') const { getMessageById } = require('../../db/interfaces/postgres/read') const { getMessage } = require('../../db/messageBatcher') const escape = require('markdown-escape') -const { chunkify } = require('../utils/constants') +const { chunkify, displayUser } = require('../utils/constants') // markdown-escape is a single exported function, I probably don't need it as a node module lol @@ -29,10 +29,10 @@ module.exports = { eventName: 'messageUpdate', embeds: [{ author: { - name: `${newMessage.author.username}${newMessage.author.discriminator === '0' ? '' : `#${newMessage.author.discriminator}`} ${member && member.nick ? `(${member.nick})` : ''}`, + name: `${displayUser(newMessage.author)} ${member && member.nick ? `(${member.nick})` : ''}`, icon_url: newMessage.author.avatarURL }, - description: `**${newMessage.author.username}${newMessage.author.discriminator === '0' ? '' : `#${newMessage.author.discriminator}`}** ${member && member.nick ? `(${member.nick})` : ''} updated their message in: ${newMessage.channel.name}.`, + description: `**${displayUser(newMessage.author)}** ${member && member.nick ? `(${member.nick})` : ''} updated their message in: ${newMessage.channel.name}.`, fields: [ { name: `${newMessage.channel.type === 10 || newMessage.channel.type === 11 || newMessage.channel.type === 12 ? 'Thread' : 'Channel'}`, diff --git a/src/bot/events/voiceChannelJoin.js b/src/bot/events/voiceChannelJoin.js index 494897f..5a9b64e 100644 --- a/src/bot/events/voiceChannelJoin.js +++ b/src/bot/events/voiceChannelJoin.js @@ -1,4 +1,5 @@ const send = require('../modules/webhooksender') +const { displayUser } = require('../utils/constants') module.exports = { name: 'voiceChannelJoin', @@ -10,10 +11,10 @@ module.exports = { eventName: 'voiceChannelJoin', embeds: [{ author: { - name: `${member.username}${member.discriminator === '0' ? '' : `#${member.discriminator}`} ${member.nick ? `(${member.nick})` : ''}`, + name: `${displayUser(member)} ${member.nick ? `(${member.nick})` : ''}`, icon_url: member.avatarURL }, - description: `**${member.username}${member.discriminator === '0' ? '' : `#${member.discriminator}`}** joined ${channel.type !== 13 ? 'voice' : 'stage'} channel: ${channel.name}.`, + description: `**${displayUser(member)}** joined ${channel.type !== 13 ? 'voice' : 'stage'} channel: ${channel.name}.`, fields: [{ name: 'Channel', value: `<#${channel.id}> (${channel.name})` diff --git a/src/bot/events/voiceChannelLeave.js b/src/bot/events/voiceChannelLeave.js index b26943a..ed9b3df 100644 --- a/src/bot/events/voiceChannelLeave.js +++ b/src/bot/events/voiceChannelLeave.js @@ -1,4 +1,5 @@ const send = require('../modules/webhooksender') +const { displayUser } = require('../utils/constants') module.exports = { name: 'voiceChannelLeave', @@ -11,10 +12,10 @@ module.exports = { eventName: 'voiceChannelLeave', embeds: [{ author: { - name: `${member.username}${member.discriminator === '0' ? '' : `#${member.discriminator}`} ${member.nick ? `(${member.nick})` : ''}`, + name: `${displayUser(member)} ${member.nick ? `(${member.nick})` : ''}`, icon_url: member.avatarURL }, - description: `**${member.username}${member.discriminator === '0' ? '' : `#${member.discriminator}`}** ${member.nick ? `(${member.nick})` : ''} left ${channel.type !== 13 ? 'voice' : 'stage'} channel: ${channel.name}.`, + description: `**${displayUser(member)}** ${member.nick ? `(${member.nick})` : ''} left ${channel.type !== 13 ? 'voice' : 'stage'} channel: ${channel.name}.`, fields: [{ name: 'Channel', value: `<#${channel.id}> (${channel.name})` diff --git a/src/bot/events/voiceChannelSwitch.js b/src/bot/events/voiceChannelSwitch.js index 5504e9f..2fc7300 100644 --- a/src/bot/events/voiceChannelSwitch.js +++ b/src/bot/events/voiceChannelSwitch.js @@ -1,4 +1,5 @@ const send = require('../modules/webhooksender') +const { displayUser } = require('../utils/constants') module.exports = { name: 'voiceChannelSwitch', @@ -10,10 +11,10 @@ module.exports = { eventName: 'voiceChannelSwitch', embeds: [{ author: { - name: `${member.username}${member.discriminator === '0' ? '' : `#${member.discriminator}`} ${member.nick ? `(${member.nick})` : ''}`, + name: `${displayUser(member)} ${member.nick ? `(${member.nick})` : ''}`, icon_url: member.avatarURL }, - description: `**${member.username}${member.discriminator === '0' ? '' : `#${member.discriminator}`}** ${member.nick ? `(${member.nick})` : ''} moved from <#${oldChannel.id}> (${oldChannel.name}) to <#${channel.id}> (${channel.name}).`, + description: `**${displayUser(member)}** ${member.nick ? `(${member.nick})` : ''} moved from <#${oldChannel.id}> (${oldChannel.name}) to <#${channel.id}> (${channel.name}).`, fields: [{ name: 'Current channel they are in', value: `<#${channel.id}> (${channel.name})` diff --git a/src/bot/events/voiceStateUpdate.js b/src/bot/events/voiceStateUpdate.js index 52f4037..ca114cc 100644 --- a/src/bot/events/voiceStateUpdate.js +++ b/src/bot/events/voiceStateUpdate.js @@ -1,4 +1,5 @@ const send = require('../modules/webhooksender') +const { displayUser } = require('../utils/constants') module.exports = { name: 'voiceStateUpdate', @@ -14,10 +15,10 @@ module.exports = { eventName: 'voiceStateUpdate', embeds: [{ author: { - name: `${member.username}${member.discriminator === '0' ? '' : `#${member.discriminator}`} ${member.nick ? `(${member.nick})` : ''}`, + name: `${displayUser(member)} ${member.nick ? `(${member.nick})` : ''}`, icon_url: member.avatarURL }, - description: `**${member.username}${member.discriminator === '0' ? '' : `#${member.discriminator}`}** ${member.nick ? `(${member.nick})` : ''} had their voice state updated.`, + description: `**${displayUser(member)}** ${member.nick ? `(${member.nick})` : ''} had their voice state updated.`, fields: [{ name: 'Voice Channel', value: `<#${channel.id}> (${channel.name})` @@ -43,7 +44,7 @@ module.exports = { if (user && user.id && user.username) { voiceStateUpdateEvent.embeds[0].fields[voiceStateUpdateEvent.embeds[0].fields.length - 1].value += `Perpetrator = ${user.id}\`\`\`` voiceStateUpdateEvent.embeds[0].footer = { - text: `${user.username}${user.discriminator === '0' ? '' : `#${user.discriminator}`}`, + text: `${displayUser(user)}`, icon_url: user.avatarURL } } diff --git a/src/bot/modules/commandhandler.js b/src/bot/modules/commandhandler.js index a457dc1..0402fb1 100644 --- a/src/bot/modules/commandhandler.js +++ b/src/bot/modules/commandhandler.js @@ -1,5 +1,6 @@ const Eris = require('eris') const statAggregator = require('./statAggregator') +const { displayUser } = require('../utils/constants') module.exports = async message => { if (message.author.bot || !message.member || message.channel instanceof Eris.TextVoiceChannel) return @@ -23,7 +24,7 @@ function processCommand (message, commandName, suffix) { message.channel.createMessage('You cannot use this command in a thread!') return } else if (process.env.CREATOR_IDS.split(",").includes(message.author.id)) { - global.logger.info(`Developer override by ${message.author.username}${message.author.discriminator === '0' ? '' : `#${message.author.discriminator}`} at ${new Date().toUTCString()}`) + global.logger.info(`Developer override by ${displayUser(message.author)} at ${new Date().toUTCString()}`) command.func(message, suffix) return } else if (command.type === 'creator' && !process.env.CREATOR_IDS.split(",").includes(message.author.id)) { @@ -39,7 +40,7 @@ function processCommand (message, commandName, suffix) { message.channel.createMessage(`This command requires you to be the owner of the server, or have the following permissions: ${command.perms.join(', ')}`) return } - global.logger.info(`${message.author.username}${message.author.discriminator === '0' ? '' : `#${message.author.discriminator}`} (${message.author.id}) in ${message.channel.id} sent ${commandName} with the args "${suffix}". The guild is called "${message.channel.guild.name}", owned by ${message.channel.guild.ownerID} and has ${message.channel.guild.memberCount} members.`) + global.logger.info(`${displayUser(message.author)} (${message.author.id}) in ${message.channel.id} sent ${commandName} with the args "${suffix}". The guild is called "${message.channel.guild.name}", owned by ${message.channel.guild.ownerID} and has ${message.channel.guild.memberCount} members.`) statAggregator.incrementCommand(command.name) command.func(message, suffix) } diff --git a/src/bot/modules/webhooksender.js b/src/bot/modules/webhooksender.js index e3981e9..b9194c2 100644 --- a/src/bot/modules/webhooksender.js +++ b/src/bot/modules/webhooksender.js @@ -1,4 +1,4 @@ -const { EVENTS_USING_AUDITLOGS } = require('../utils/constants') +const { EVENTS_USING_AUDITLOGS, displayUser } = require('../utils/constants') const webhookCache = require('./webhookcache') const guildWebhookCacher = require('./guildWebhookCacher') const cacheGuild = require('../utils/cacheGuild') @@ -66,7 +66,7 @@ module.exports = async (pkg) => { } else if (webhook && !guildSettings.eventIsDisabled(pkg.eventName)) { if (!pkg.embeds[0].footer && !pkg.noFooter) { pkg.embeds[0].footer = { - text: `${global.bot.user.username}#${global.bot.user.discriminator}`, + text: displayUser(global.bot.user), icon_url: global.bot.user.avatarURL } } diff --git a/src/bot/slashcommands/archive.js b/src/bot/slashcommands/archive.js index b33beb3..7651e7f 100644 --- a/src/bot/slashcommands/archive.js +++ b/src/bot/slashcommands/archive.js @@ -1,4 +1,4 @@ -const { EMBED_COLORS } = require('../utils/constants.js') +const { EMBED_COLORS, displayUser } = require('../utils/constants.js') const { getEmbedFooter, getAuthorField } = require('../utils/embeds.js') const { createHaste } = require('../utils/createHaste.js') @@ -35,11 +35,11 @@ module.exports = { }).catch(() => { }) } const fetchedMessages = await global.bot.getChannel(interaction.channel.id).getMessages({ limit: interaction.data.options[0].value }) - const pasteString = fetchedMessages.reverse().filter(m => !m.applicationID).map(m => `${m.author.username}${m.author.discriminator === '0' ? '' : `#${m.author.discriminator}`} (${m.author.id}) | ${new Date(m.timestamp)}: ${m.content || ''} | ${m.embeds.length === 0 ? '' : `{"embeds": [${m.embeds.map(e => JSON.stringify(e))}]}`} | ${m.attachments.length === 0 ? '' : ` ${m.attachments.map((c) => `=====> Attachment: ${c.filename}: ${m.url}`).join(" | ")}`}`).join('\r\n') + const pasteString = fetchedMessages.reverse().filter(m => !m.applicationID).map(m => `${displayUser(m.author)} (${m.author.id}) | ${new Date(m.timestamp)}: ${m.content || ''} | ${m.embeds.length === 0 ? '' : `{"embeds": [${m.embeds.map(e => JSON.stringify(e))}]}`} | ${m.attachments.length === 0 ? '' : ` ${m.attachments.map((c) => `=====> Attachment: ${c.filename}: ${m.url}`).join(" | ")}`}`).join('\r\n') await interaction.createMessage({ embeds: [{ // make sure followup message is created before doing any more work title: 'Processing', - description: `Processing request from ${interaction.member.username}${interaction.member.discriminator === '0' ? '' : `#${interaction.member.discriminator}`} for an archive of ${interaction.data.options[0].value} messages`, + description: `Processing request from ${displayUser(interaction.member)} for an archive of ${interaction.data.options[0].value} messages`, thumbnail: { url: interaction.member.user.dynamicAvatarURL(null, 64) }, diff --git a/src/bot/slashcommands/clearmydata.js b/src/bot/slashcommands/clearmydata.js index 86c4737..8a9a07b 100644 --- a/src/bot/slashcommands/clearmydata.js +++ b/src/bot/slashcommands/clearmydata.js @@ -1,5 +1,6 @@ const Eris = require('eris') const { getAuthorField } = require('../utils/embeds.js') +const { displayUser } = require('../utils/constants.js') module.exports = { name: 'clearmydata', @@ -12,7 +13,7 @@ module.exports = { timestamp: new Date(), footer: { icon_url: global.bot.user.avatarURL, - text: `${global.bot.user.username}#${global.bot.user.discriminator}` + text: displayUser(global.bot.user) }, author: getAuthorField(interaction.member.user), fields: [] diff --git a/src/bot/slashcommands/serverinfo.js b/src/bot/slashcommands/serverinfo.js index 50beffa..fc26675 100644 --- a/src/bot/slashcommands/serverinfo.js +++ b/src/bot/slashcommands/serverinfo.js @@ -1,3 +1,5 @@ +const { displayUser } = require("../utils/constants") + module.exports = { name: 'serverinfo', func: async interaction => { @@ -26,7 +28,7 @@ module.exports = { value: `${guild.verificationLevel}` }, { name: 'Owner', - value: `${owner ? `**${owner.username}${owner.discriminator === '0' ? '' : `#${owner.discriminator}`}** ` : ''}(${guild.ownerID})` + value: `${owner ? `**${displayUser(owner)}** ` : ''}(${guild.ownerID})` }, { name: 'Features', value: guild.features.length !== 0 ? guild.features.join(', ') : 'No Guild Features' diff --git a/src/bot/slashcommands/userinfo.js b/src/bot/slashcommands/userinfo.js index 1f07abd..922fc63 100644 --- a/src/bot/slashcommands/userinfo.js +++ b/src/bot/slashcommands/userinfo.js @@ -1,4 +1,4 @@ -const { EMBED_COLORS } = require('../utils/constants') +const { EMBED_COLORS, displayUser } = require('../utils/constants') const notablePermissions = [ 'kickMembers', @@ -40,7 +40,7 @@ module.exports = { const roles = member.roles.map(r => guild.roles.get(r)).sort((a, b) => b.position - a.position) const fields = [{ name: 'Name', - value: `${member.username}${member.discriminator === '0' ? '' : `#${member.discriminator}`} ${member.nick ? `(**${member.nick}**)` : ''} (${member.id})` + value: `${displayUser(member)} ${member.nick ? `(**${member.nick}**)` : ''} (${member.id})` }, { name: 'Join Date', value: ` ()` diff --git a/src/bot/utils/constants.js b/src/bot/utils/constants.js index e04c2a2..0168ae5 100644 --- a/src/bot/utils/constants.js +++ b/src/bot/utils/constants.js @@ -118,15 +118,18 @@ exports.eventLogs = { guildMemberBoostUpdate: '' } - -function chunkify(toChunk) { - const lenChunks = Math.ceil(toChunk.length / 1000) +exports.chunkify = (toChunk, maxCharacters = 1000) => { + const lenChunks = Math.ceil(toChunk.length / maxCharacters) const chunksToReturn = [] for (let i = 0; i < lenChunks; i++) { - const chunkedStr = toChunk.substring((1000 * i), i === 0 ? 1000 : 1000 * (i + 1)) + const chunkedStr = toChunk.substring((maxCharacters * i), i === 0 ? maxCharacters : maxCharacters * (i + 1)) chunksToReturn.push(chunkedStr) } return chunksToReturn -} +}; -exports.chunkify = chunkify; \ No newline at end of file +/** + * @param {import("eris").Member | import("eris").User}) user + * @returns {string} + */ +exports.displayUser = (user) => `${user.username}${user.discriminator !== "0" ? `#${user.discriminator}` : ""}`; \ No newline at end of file diff --git a/src/bot/utils/embeds.js b/src/bot/utils/embeds.js index 3b891f7..ab5640a 100644 --- a/src/bot/utils/embeds.js +++ b/src/bot/utils/embeds.js @@ -1,13 +1,15 @@ +const { displayUser } = require("./constants") + module.exports = { getEmbedFooter (user) { return { - text: `${user.username}${user.discriminator === '0' ? '' : `#${user.discriminator}`}`, + text: `${displayUser(user)}`, icon_url: user.dynamicAvatarURL(null, 64) } }, getAuthorField (user) { return { - name: `${user.username}${user.discriminator === '0' ? '' : `#${user.discriminator}`}`, + name: `${displayUser(user)}`, icon_url: user.avatarURL } } From 68a291e131761657e1600c1c2997c79637c733c0 Mon Sep 17 00:00:00 2001 From: Elara Services <43923163+Elara-Discord-Bots@users.noreply.github.com> Date: Sun, 14 Apr 2024 20:26:45 -0700 Subject: [PATCH 03/13] cleanup --- src/bot/commands/ignorechannel.js | 3 +- src/bot/commands/reset.js | 6 +- src/bot/commands/setcmd.js | 2 +- src/bot/commands/stoplogging.js | 10 +-- src/bot/commands/togglemodule.js | 5 +- src/bot/events/guildCreate.js | 8 +- src/bot/events/guildDelete.js | 2 +- src/bot/events/messageCreate.js | 2 +- src/bot/modules/bulkqueue.js | 4 +- src/bot/utils/cacheGuild.js | 4 +- src/miscellaneous/webhooklogger.js | 138 +++++++++++------------------ 11 files changed, 74 insertions(+), 110 deletions(-) diff --git a/src/bot/commands/ignorechannel.js b/src/bot/commands/ignorechannel.js index b0a7bd3..dc06ecd 100644 --- a/src/bot/commands/ignorechannel.js +++ b/src/bot/commands/ignorechannel.js @@ -1,6 +1,5 @@ const { displayUser } = require('../utils/constants') - -const ignoreChannel = require('../../db/interfaces/postgres/update').ignoreChannel +const { ignoreChannel } = require('../../db/interfaces/postgres/update') module.exports = { func: async (message, suffix) => { diff --git a/src/bot/commands/reset.js b/src/bot/commands/reset.js index 0740d35..9f47dd0 100644 --- a/src/bot/commands/reset.js +++ b/src/bot/commands/reset.js @@ -1,7 +1,7 @@ const cacheGuild = require('../utils/cacheGuild') const { displayUser } = require('../utils/constants') -const deleteGuild = require('../../db/interfaces/postgres/delete').deleteGuild -const createGuild = require('../../db/interfaces/postgres/create').createGuild +const { deleteGuild } = require('../../db/interfaces/postgres/delete') +const { createGuild } = require('../../db/interfaces/postgres/create') module.exports = { func: async message => { @@ -22,7 +22,7 @@ module.exports = { }) let i = 0 let complete = false - global.bot.on('messageCreate', async function temp (m) { + global.bot.on('messageCreate', async function temp(m) { if (i === 0) { setTimeout(() => { global.bot.removeListener('messageCreate', temp) diff --git a/src/bot/commands/setcmd.js b/src/bot/commands/setcmd.js index 9c6dbcb..f908503 100644 --- a/src/bot/commands/setcmd.js +++ b/src/bot/commands/setcmd.js @@ -1,4 +1,4 @@ -const ERIS_CONSTANTS = require('eris').Constants +const { Constants: ERIS_CONSTANTS } = require('eris') module.exports = { func: async (message, suffix) => { diff --git a/src/bot/commands/stoplogging.js b/src/bot/commands/stoplogging.js index d38b0dd..537b017 100644 --- a/src/bot/commands/stoplogging.js +++ b/src/bot/commands/stoplogging.js @@ -1,8 +1,6 @@ -const clearEventByID = require('../../db/interfaces/postgres/update').clearEventByID +const { clearEventByID, setEventsLogId } = require('../../db/interfaces/postgres/update') +const { displayUser, ALL_EVENTS: eventList } = require('../utils/constants') const cacheGuild = require('../utils/cacheGuild') -const { displayUser } = require('../utils/constants') -const setEventLogs = require('../../db/interfaces/postgres/update').setEventsLogId -const eventList = require('../utils/constants').ALL_EVENTS module.exports = { func: async (message, suffix) => { @@ -15,7 +13,7 @@ module.exports = { if (events.length === 0 && suffix) { message.channel.createMessage(`<@${message.author.id}>, none of the provided events are valid to be unset. Look at ${process.env.GLOBAL_BOT_PREFIX}help to see what is valid.`) } else if (suffix && events.length !== 0) { - await setEventLogs(message.channel.guild.id, '', events) + await setEventsLogId(message.channel.guild.id, '', events) await cacheGuild(message.channel.guild.id) message.channel.createMessage(`<@${message.author.id}>, your selected events will not be logged here anymore.`) } else if (!suffix) { @@ -49,7 +47,7 @@ module.exports = { category: 'Logging' } -function cleanArray (events) { +function cleanArray(events) { const tempEvents = [] events.forEach(event => { if (eventList.includes(event)) { diff --git a/src/bot/commands/togglemodule.js b/src/bot/commands/togglemodule.js index 762b948..39f3505 100644 --- a/src/bot/commands/togglemodule.js +++ b/src/bot/commands/togglemodule.js @@ -1,6 +1,5 @@ -const { displayUser } = require('../utils/constants') -const disableEvent = require('../../db/interfaces/postgres/update').disableEvent -const eventList = require('../utils/constants').ALL_EVENTS +const { displayUser, ALL_EVENTS: eventList } = require('../utils/constants') +const { disableEvent } = require('../../db/interfaces/postgres/update') module.exports = { func: async (message, suffix) => { diff --git a/src/bot/events/guildCreate.js b/src/bot/events/guildCreate.js index f12d0cd..918fb93 100644 --- a/src/bot/events/guildCreate.js +++ b/src/bot/events/guildCreate.js @@ -1,4 +1,4 @@ -const createGuild = require('../../db/interfaces/postgres/create').createGuild +const { createGuild } = require('../../db/interfaces/postgres/create') const cacheGuild = require('../utils/cacheGuild') const statAggregator = require('../modules/statAggregator') @@ -6,8 +6,8 @@ module.exports = { name: 'guildCreate', type: 'on', handle: async guild => { - await createGuild(guild) // Create guild document in database - await cacheGuild(guild.id) // Create a guildsettings object and cache it - statAggregator.incrementEvent('guildCreate') + await createGuild(guild) // Create guild document in database + await cacheGuild(guild.id) // Create a guildsettings object and cache it + statAggregator.incrementEvent('guildCreate') } } diff --git a/src/bot/events/guildDelete.js b/src/bot/events/guildDelete.js index 71a0223..ed0af43 100644 --- a/src/bot/events/guildDelete.js +++ b/src/bot/events/guildDelete.js @@ -1,4 +1,4 @@ -const deleteGuild = require('../../db/interfaces/postgres/delete').deleteGuild +const { deleteGuild } = require('../../db/interfaces/postgres/delete') const statAggregator = require('../modules/statAggregator') module.exports = { diff --git a/src/bot/events/messageCreate.js b/src/bot/events/messageCreate.js index 3ddf3ed..daf9cc8 100644 --- a/src/bot/events/messageCreate.js +++ b/src/bot/events/messageCreate.js @@ -1,5 +1,5 @@ const commandHandler = require('../modules/commandhandler') -const cacheMessage = require('../../db/interfaces/postgres/create').cacheMessage +const { cacheMessage } = require('../../db/interfaces/postgres/create') const cacheGuild = require('../utils/cacheGuild') module.exports = { diff --git a/src/bot/modules/bulkqueue.js b/src/bot/modules/bulkqueue.js index 1126606..5a191fc 100644 --- a/src/bot/modules/bulkqueue.js +++ b/src/bot/modules/bulkqueue.js @@ -1,6 +1,6 @@ const cacheGuild = require('../utils/cacheGuild') const guildWebhookCacher = require('./guildWebhookCacher') -const setEventsByChannelID = require('../../db/interfaces/postgres/update').setEventsLogId +const { setEventsLogId } = require('../../db/interfaces/postgres/update') const webhookIDToQueue = new Map() const webhookIDToTimeout = new Map() @@ -87,7 +87,7 @@ function sendBulkLog (senderPkg, embeds, guildSettings) { } if (e.code == '10015') { // Webhook doesn't exist anymore. await global.redis.del(`webhook-${guildSettings.getEventByName(senderPkg.eventName)}`) - await setEventsByChannelID(senderPkg.guildID, '', [senderPkg.eventName]) + await setEventsLogId(senderPkg.guildID, '', [senderPkg.eventName]) await cacheGuild(senderPkg.guildID) return await guildWebhookCacher(senderPkg.guildID, guildSettings.getEventByName(senderPkg.eventName)) } else { diff --git a/src/bot/utils/cacheGuild.js b/src/bot/utils/cacheGuild.js index 8d86550..22809ea 100644 --- a/src/bot/utils/cacheGuild.js +++ b/src/bot/utils/cacheGuild.js @@ -1,6 +1,6 @@ module.exports = async guildID => { - const getGuildDocument = require('../../db/interfaces/postgres/read').getGuild + const { getGuild } = require('../../db/interfaces/postgres/read') const GuildSettings = require('../bases/GuildSettings') // GuildSettings will NOT resolve if you require it outside of this function(?) - const doc = await getGuildDocument(guildID) + const doc = await getGuild(guildID) global.bot.guildSettingsCache[guildID] = new GuildSettings(doc) } diff --git a/src/miscellaneous/webhooklogger.js b/src/miscellaneous/webhooklogger.js index ea8fc78..d047775 100644 --- a/src/miscellaneous/webhooklogger.js +++ b/src/miscellaneous/webhooklogger.js @@ -1,4 +1,4 @@ -const sa = require('superagent') +const { post } = require('superagent') require('dotenv').config() let globalHookErrors = 0 @@ -7,99 +7,67 @@ setInterval(() => { globalHookErrors-- // This timeout exists so that if the shard manager starts to spew errors, I don't get IP banned from Discord. }, 5000) -function fatal (message) { - if (globalHookErrors < 5) { - sa - .post(process.env.DISCORD_WEBHOOK_URL) - .send({ - avatar_url: 'https://cdn4.iconfinder.com/data/icons/ionicons/512/icon-ios7-bell-512.png', - username: `Fatal Error LoggerBot Webhook Notification`, - embeds: [{ - title: 'Fatal', - description: message, - color: 16777215 - }] - }) - .end(err => { - if (err) globalHookErrors = globalHookErrors + 1 - }) +function send(type = "Generic", embeds = [], username = null, avatar_url = null) { + if (globalHookErrors > 5) { + return } + post(process.env.DISCORD_WEBHOOK_URL) + .send({ + avatar_url: avatar_url || 'https://cdn4.iconfinder.com/data/icons/ionicons/512/icon-ios7-bell-512.png', + username: username || `${type} LoggerBot Webhook Notification`, + embeds, + }) + .end(err => { + if (err) globalHookErrors = globalHookErrors + 1 + }) } -function error (message) { - if (globalHookErrors < 5) { - sa - .post(process.env.DISCORD_WEBHOOK_URL) - .send({ - avatar_url: 'https://cdn4.iconfinder.com/data/icons/ionicons/512/icon-ios7-bell-512.png', - username: `Error LoggerBot Webhook Notification`, - embeds: [{ - title: 'Error', - description: message, - color: 16711680 - }] - }) - .end(err => { - if (err) globalHookErrors = globalHookErrors + 1 - }) - } +function fatal(message) { + send("Fatal Error", [{ + title: 'Fatal', + description: message, + color: 16777215 + }]) } -function warn (message) { - if (globalHookErrors < 5) { - sa - .post(process.env.DISCORD_WEBHOOK_URL) - .send({ - avatar_url: 'https://cdn4.iconfinder.com/data/icons/ionicons/512/icon-ios7-bell-512.png', - username: `Warning LoggerBot Webhook Notification`, - embeds: [{ - title: 'Warning', - description: message, - color: 15466375 - }] - }) - .end(err => { - if (err) globalHookErrors = globalHookErrors + 1 - }) - } +function error(message) { + send("Error", [ + { + title: 'Error', + description: message, + color: 16711680 + } + ]) } -function generic (message) { - if (globalHookErrors < 5) { - sa - .post(process.env.DISCORD_WEBHOOK_URL) - .send({ - avatar_url: 'https://cdn4.iconfinder.com/data/icons/ionicons/512/icon-ios7-bell-512.png', - username: `Generic LoggerBot Webhook Notification`, - embeds: [{ - title: 'Generic', - description: message, - color: 6052351 - }] - }) - .end(err => { - if (err) globalHookErrors = globalHookErrors + 1 - }) - } +function warn(message) { + send(`Warning`, [ + { + title: 'Warning', + description: message, + color: 15466375 + } + ]) } -function custom (message) { - if (globalHookErrors < 5) { - sa - .post(process.env.DISCORD_WEBHOOK_URL) - .send({ - avatar_url: message.avatar_url || 'https://cdn4.iconfinder.com/data/icons/ionicons/512/icon-ios7-bell-512.png', - embeds: [{ - title: message.title || 'Custom Notification', - color: message.color || 6052351, - description: message.description || 'No message description provided.' - }], - timestamp: new Date() - }) - .end(err => { - if (err) globalHookErrors = globalHookErrors + 1 - }) - } +function generic(message) { + send("Generic", [ + { + title: 'Generic', + description: message, + color: 6052351 + } + ]) +} + +function custom(message) { + send("Custom", [ + { + title: message.title || 'Custom Notification', + color: message.color || 6052351, + description: message.description || 'No message description provided.' + } + ], message.title, message.avatar_url); } exports.error = error From 99534fc9988c950417e56eb4cc4b066802f2ae36 Mon Sep 17 00:00:00 2001 From: Elara Services <43923163+Elara-Discord-Bots@users.noreply.github.com> Date: Sun, 14 Apr 2024 20:31:54 -0700 Subject: [PATCH 04/13] formatting --- src/miscellaneous/webhooklogger.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/miscellaneous/webhooklogger.js b/src/miscellaneous/webhooklogger.js index d047775..2624ad3 100644 --- a/src/miscellaneous/webhooklogger.js +++ b/src/miscellaneous/webhooklogger.js @@ -23,11 +23,13 @@ function send(type = "Generic", embeds = [], username = null, avatar_url = null) } function fatal(message) { - send("Fatal Error", [{ - title: 'Fatal', - description: message, - color: 16777215 - }]) + send("Fatal Error", [ + { + title: 'Fatal', + description: message, + color: 16777215 + } + ]) } function error(message) { From 371f8fd3dcc01e2b751020e1166aadfda58e4c85 Mon Sep 17 00:00:00 2001 From: Elara Services <43923163+Elara-Discord-Bots@users.noreply.github.com> Date: Sun, 14 Apr 2024 20:40:55 -0700 Subject: [PATCH 05/13] ... --- src/bot/commands/eval.js | 14 +++++++------- src/bot/commands/logbots.js | 3 +-- src/bot/events/channelCreate.js | 10 +--------- src/bot/events/channelDelete.js | 11 +---------- src/bot/events/channelUpdate.js | 12 ++---------- src/bot/events/guildRoleUpdate.js | 2 +- src/bot/modules/commandhandler.js | 2 +- src/bot/utils/constants.js | 20 +++++++++++++++++++- 8 files changed, 33 insertions(+), 41 deletions(-) diff --git a/src/bot/commands/eval.js b/src/bot/commands/eval.js index 0a0312c..2b0bbb9 100644 --- a/src/bot/commands/eval.js +++ b/src/bot/commands/eval.js @@ -1,33 +1,33 @@ -const util = require('util') +const { inspect } = require('util') module.exports = { func: async (message, suffix) => { try { // This eval command is from https://github.com/TheSharks/WildBeast/ because I really like their method const returned = eval(suffix) - let str = util.inspect(returned, { + let str = inspect(returned, { depth: 1 }) if (str.length > 1900) { - str = `${str.substr(0, 1897)}...` + str = `${str.substring(0, 1897)}...` } str = str.replace(new RegExp(process.env.BOT_TOKEN, 'gi'), '( ͔° ĶœŹ– ͔°)') message.channel.createMessage('```xl\n' + str + '\n```').then(ms => { if (returned !== undefined && returned !== null && typeof returned.then === 'function') { returned.then(() => { - str = util.inspect(returned, { + str = inspect(returned, { depth: 1 }) if (str.length > 1900) { - str = str.substr(0, 1897) + str = str.substring(0, 1897) str = str + '...' } ms.edit('```xl\n' + str + '\n```') }, e => { - str = util.inspect(e, { + str = inspect(e, { depth: 1 }) if (str.length > 1900) { - str = str.substr(0, 1897) + str = str.substring(0, 1897) str = str + '...' } ms.edit('```xl\n' + str + '\n```') diff --git a/src/bot/commands/logbots.js b/src/bot/commands/logbots.js index f001515..4fb8271 100644 --- a/src/bot/commands/logbots.js +++ b/src/bot/commands/logbots.js @@ -16,8 +16,7 @@ module.exports = { author: { name: displayUser(message.author), icon_url: message.author.avatarURL - }, - fields: [] + } }] }) }, diff --git a/src/bot/events/channelCreate.js b/src/bot/events/channelCreate.js index aa9365d..77c5ea7 100644 --- a/src/bot/events/channelCreate.js +++ b/src/bot/events/channelCreate.js @@ -1,13 +1,5 @@ const send = require('../modules/webhooksender') -const { displayUser } = require('../utils/constants') -const CHANNEL_TYPE_MAP = { - 0: 'Text channel', - 2: 'Voice channel', - 4: 'Category channel', - 5: 'Announcement channel', - 13: 'Stage channel', - 15: 'Forum channel' -} +const { displayUser, CHANNEL_TYPE_MAP } = require('../utils/constants') module.exports = { name: 'channelCreate', diff --git a/src/bot/events/channelDelete.js b/src/bot/events/channelDelete.js index 2f8b0ac..578b341 100644 --- a/src/bot/events/channelDelete.js +++ b/src/bot/events/channelDelete.js @@ -1,14 +1,5 @@ const send = require('../modules/webhooksender') -const { displayUser } = require('../utils/constants') -const CHANNEL_TYPE_MAP = { - 0: 'Text channel', - 2: 'Voice channel', - 4: 'Category', - 5: 'Announcement', - 13: 'Stage Channel', - 15: 'Forum channel' -} - +const { displayUser, CHANNEL_TYPE_MAP } = require('../utils/constants') module.exports = { name: 'channelDelete', type: 'on', diff --git a/src/bot/events/channelUpdate.js b/src/bot/events/channelUpdate.js index 193f1d1..12a4ba5 100644 --- a/src/bot/events/channelUpdate.js +++ b/src/bot/events/channelUpdate.js @@ -1,14 +1,6 @@ const send = require('../modules/webhooksender') const escape = require('markdown-escape') -const { displayUser } = require('../utils/constants') -const CHANNEL_TYPE_MAP = { - 0: 'Text channel', - 2: 'Voice channel', - 4: 'Category channel', - 5: 'Announcement channel', - 13: 'Stage channel', - 15: 'Forum channel' -} +const { displayUser, CHANNEL_TYPE_MAP } = require('../utils/constants') const canUseExternal = guild => { const logChannelID = global.bot.guildSettingsCache[guild.id].event_logs.channelUpdate @@ -220,7 +212,7 @@ module.exports = { } function toTitleCase (str) { - return str.replace(/_/g, ' ').replace(/\w\S*/g, function (txt) { return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase() }) + return str.replace(/_/g, ' ').replace(/\w\S*/g, function (txt) { return txt.charAt(0).toUpperCase() + txt.substring(1).toLowerCase() }) } function getDifference (array1, array2) { diff --git a/src/bot/events/guildRoleUpdate.js b/src/bot/events/guildRoleUpdate.js index 31988ad..02308a1 100644 --- a/src/bot/events/guildRoleUpdate.js +++ b/src/bot/events/guildRoleUpdate.js @@ -93,7 +93,7 @@ function intToHex (num) { } function toTitleCase (str) { - return str.replace(/\w\S*/g, function (txt) { return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase() }) + return str.replace(/\w\S*/g, function (txt) { return txt.charAt(0).toUpperCase() + txt.substring(1).toLowerCase() }) } function rgbToHex (r, g, b) { // bitwise math is black magic diff --git a/src/bot/modules/commandhandler.js b/src/bot/modules/commandhandler.js index 0402fb1..08afa17 100644 --- a/src/bot/modules/commandhandler.js +++ b/src/bot/modules/commandhandler.js @@ -6,7 +6,7 @@ module.exports = async message => { if (message.author.bot || !message.member || message.channel instanceof Eris.TextVoiceChannel) return if (message.content.startsWith(process.env.GLOBAL_BOT_PREFIX)) { const cmd = message.content.substring(process.env.GLOBAL_BOT_PREFIX.length).split(' ')[0].toLowerCase() - const splitSuffix = message.content.substr(process.env.GLOBAL_BOT_PREFIX).split(' ') + const splitSuffix = message.content.substring(process.env.GLOBAL_BOT_PREFIX).split(' ') const suffix = splitSuffix.slice(1, splitSuffix.length).join(' ') processCommand(message, cmd, suffix) } diff --git a/src/bot/utils/constants.js b/src/bot/utils/constants.js index 0168ae5..e5e1dba 100644 --- a/src/bot/utils/constants.js +++ b/src/bot/utils/constants.js @@ -132,4 +132,22 @@ exports.chunkify = (toChunk, maxCharacters = 1000) => { * @param {import("eris").Member | import("eris").User}) user * @returns {string} */ -exports.displayUser = (user) => `${user.username}${user.discriminator !== "0" ? `#${user.discriminator}` : ""}`; \ No newline at end of file +exports.displayUser = (user) => `${user.username}${user.discriminator !== "0" ? `#${user.discriminator}` : ""}`; + +// All channel types from: https://discord.com/developers/docs/resources/channel#channel-object-channel-types +// Used for the channel* events. +exports.CHANNEL_TYPE_MAP = { + 0: 'Text channel', + 1: 'DM channel', + 2: 'Voice channel', + 3: 'Group DM channel', + 4: 'Category channel', + 5: 'Announcement channel', + 10: 'Announcement thread channel', + 11: 'Public Thread channel', + 12: 'Private Thread channel', + 13: 'Stage channel', + 14: 'Directory channel', + 15: 'Forum channel', + 16: 'Media channel' +} \ No newline at end of file From d09d4a486040755e7cb8a6ddea4f2811a4ab2ccf Mon Sep 17 00:00:00 2001 From: Elara Services <43923163+Elara-Discord-Bots@users.noreply.github.com> Date: Sun, 14 Apr 2024 21:04:16 -0700 Subject: [PATCH 06/13] more cleanup --- primary.js | 90 ++++++++++++++-------------- replica.js | 4 +- src/bot/commands/archive.js | 10 ++-- src/bot/commands/setchannel.js | 28 +-------- src/bot/events/interactionCreate.js | 33 +++++----- src/bot/index.js | 2 +- src/bot/modules/commandhandler.js | 6 +- src/bot/slashcommands/archive.js | 42 ++++--------- src/bot/slashcommands/help.js | 8 +-- src/bot/slashcommands/invite.js | 4 +- src/bot/slashcommands/setcmds.js | 6 +- src/bot/slashcommands/setup.js | 24 ++++---- src/bot/slashcommands/stoplogging.js | 8 +-- src/bot/utils/recoverSettings.js | 2 +- src/db/clients/rethink.js | 15 ----- src/db/interfaces/redis/redislock.js | 10 ++-- src/miscellaneous/commandIndexer.js | 12 ++-- src/miscellaneous/listenerIndexer.js | 12 ++-- 18 files changed, 130 insertions(+), 186 deletions(-) delete mode 100644 src/db/clients/rethink.js diff --git a/primary.js b/primary.js index e39096a..2766a3e 100644 --- a/primary.js +++ b/primary.js @@ -1,5 +1,5 @@ const cluster = require('cluster') -const sa = require('superagent') +const { get } = require('superagent') const addListeners = require('./src/miscellaneous/workerlistener') require('dotenv').config() @@ -7,53 +7,55 @@ require('dotenv').config() const staggerLaunchQueue = [] let staggerInterval -async function init () { - sa.get('https://discord.com/api/gateway/bot').set('Authorization', `Bot ${process.env.BOT_TOKEN}`).then(async b => { - const totalShards = b.body.shards // get recommended shard count - let shardsPerWorker - if (process.env.USE_MAX_CONCURRENCY === 'true') { // eslint-disable-line eqeqeq - if (b.body.session_start_limit.max_concurrency === 1) { - global.logger.warn(`Use max concurrency was specified, but observed gateway concurrency is ${b.body.session_start_limit.max_concurrency}`) +async function init() { + get('https://discord.com/api/gateway/bot') + .set('Authorization', `Bot ${process.env.BOT_TOKEN}`) + .then(async b => { + const totalShards = b.body.shards // get recommended shard count + let shardsPerWorker + if (process.env.USE_MAX_CONCURRENCY === 'true') { // eslint-disable-line eqeqeq + if (b.body.session_start_limit.max_concurrency === 1) { + global.logger.warn(`Use max concurrency was specified, but observed gateway concurrency is ${b.body.session_start_limit.max_concurrency}`) + } + if (b.body.shards % 16 !== 0) { + global.logger.warn('Max concurrency mode is enabled and set on Discord, but the shard count is not a multiple of 16!') + } + global.logger.info(`Using max concurrency of ${b.body.session_start_limit.max_concurrency}. Cluster starting will be delayed!`) // shardsPerWorker is set to 16 below } - if (b.body.shards % 16 !== 0) { - global.logger.warn('Max concurrency mode is enabled and set on Discord, but the shard count is not a multiple of 16!') - } - global.logger.info(`Using max concurrency of ${b.body.session_start_limit.max_concurrency}. Cluster starting will be delayed!`) // shardsPerWorker is set to 16 below - } - const coreCount = require('os').cpus().length - if (coreCount > totalShards) shardsPerWorker = 1 - else shardsPerWorker = process.env.USE_MAX_CONCURRENCY === 'true' ? 16 : Math.ceil(totalShards / coreCount) + 2 // eslint-disable-line eqeqeq - // if max concurrency isn't enabled this will work - const workerCount = Math.ceil(totalShards / shardsPerWorker) // if max concurrency is 16, shard count / 16 will be an integer for how many workers are needed - global.webhook.generic(`Shard manager is booting up. Discord recommends ${totalShards} shards. With the core count being ${coreCount}, there will be ${shardsPerWorker} shards per worker, and ${workerCount} workers.${process.env.USE_MAX_CONCURRENCY === 'true' ? ' Max concurrency is enabled.' : ''}`) // eslint-disable-line eqeqeq - global.logger.startup(`[SHARDER]: TOTAL SHARDS: ${totalShards}\nCore count: ${coreCount}\nShards per worker: ${shardsPerWorker}\nWorker count: ${workerCount}${process.env.USE_MAX_CONCURRENCY === 'true' ? '\nMax concurrency is enabled.' : ''}`) - for (let i = 0; i < workerCount; i++) { - const shardStart = i * shardsPerWorker - let shardEnd = ((i + 1) * shardsPerWorker) - 1 - if (shardEnd > totalShards - 1) shardEnd = totalShards - 1 - let rangeForShard - if (shardStart === shardEnd) { - rangeForShard = `shard ${shardStart}` - } else { - rangeForShard = `shards ${shardStart}-${shardEnd}` - } - if (process.env.CUSTOM_CLUSTER_LAUNCH == 'true' && i === 0 && process.env.USE_MAX_CONCURRENCY !== 'true') { // eslint-disable-line eqeqeq - global.logger.info(`Custom launch mode specified, use range: ${rangeForShard} (start ${shardStart} end ${shardEnd})`) - global.webhook.generic(`Custom launch mode specified, use range: ${rangeForShard} (start ${shardStart} end ${shardEnd})`) - continue - } - if (process.env.USE_MAX_CONCURRENCY === 'true') { - staggerLaunch({ type: 'bot', shardStart, shardEnd, rangeForShard, totalShards }) - continue + const coreCount = require('os').cpus().length + if (coreCount > totalShards) shardsPerWorker = 1 + else shardsPerWorker = process.env.USE_MAX_CONCURRENCY === 'true' ? 16 : Math.ceil(totalShards / coreCount) + 2 // eslint-disable-line eqeqeq + // if max concurrency isn't enabled this will work + const workerCount = Math.ceil(totalShards / shardsPerWorker) // if max concurrency is 16, shard count / 16 will be an integer for how many workers are needed + global.webhook.generic(`Shard manager is booting up. Discord recommends ${totalShards} shards. With the core count being ${coreCount}, there will be ${shardsPerWorker} shards per worker, and ${workerCount} workers.${process.env.USE_MAX_CONCURRENCY === 'true' ? ' Max concurrency is enabled.' : ''}`) // eslint-disable-line eqeqeq + global.logger.startup(`[SHARDER]: TOTAL SHARDS: ${totalShards}\nCore count: ${coreCount}\nShards per worker: ${shardsPerWorker}\nWorker count: ${workerCount}${process.env.USE_MAX_CONCURRENCY === 'true' ? '\nMax concurrency is enabled.' : ''}`) + for (let i = 0; i < workerCount; i++) { + const shardStart = i * shardsPerWorker + let shardEnd = ((i + 1) * shardsPerWorker) - 1 + if (shardEnd > totalShards - 1) shardEnd = totalShards - 1 + let rangeForShard + if (shardStart === shardEnd) { + rangeForShard = `shard ${shardStart}` + } else { + rangeForShard = `shards ${shardStart}-${shardEnd}` + } + if (process.env.CUSTOM_CLUSTER_LAUNCH == 'true' && i === 0 && process.env.USE_MAX_CONCURRENCY !== 'true') { // eslint-disable-line eqeqeq + global.logger.info(`Custom launch mode specified, use range: ${rangeForShard} (start ${shardStart} end ${shardEnd})`) + global.webhook.generic(`Custom launch mode specified, use range: ${rangeForShard} (start ${shardStart} end ${shardEnd})`) + continue + } + if (process.env.USE_MAX_CONCURRENCY === 'true') { + staggerLaunch({ type: 'bot', shardStart, shardEnd, rangeForShard, totalShards }) + continue + } + const worker = cluster.fork() + Object.assign(worker, { type: 'bot', shardStart, shardEnd, rangeForShard, totalShards }) + addListeners(worker) } - const worker = cluster.fork() - Object.assign(worker, { type: 'bot', shardStart, shardEnd, rangeForShard, totalShards }) - addListeners(worker) - } - }).catch(console.error) + }).catch(console.error) } -function staggerLaunch (info) { +function staggerLaunch(info) { // WARNING: 16x sharding won't work on default eris as of today, you will need a fork (mine works!) staggerLaunchQueue.push(info) if (!staggerInterval) { diff --git a/replica.js b/replica.js index faac16a..40e5eaf 100644 --- a/replica.js +++ b/replica.js @@ -1,5 +1,5 @@ const cluster = require('cluster') -const path = require('path') +const { resolve } = require('path') async function assignWorkerInfo (info) { if (info.type !== 'startup') { @@ -9,7 +9,7 @@ async function assignWorkerInfo (info) { if (info.processType === 'bot') { Object.assign(cluster.worker, info) - require(path.resolve('src', 'bot', 'index')) + require(resolve('src', 'bot', 'index')) } } diff --git a/src/bot/commands/archive.js b/src/bot/commands/archive.js index 1f0af1d..ed270d8 100644 --- a/src/bot/commands/archive.js +++ b/src/bot/commands/archive.js @@ -12,10 +12,12 @@ module.exports = { const messages = await message.channel.getMessages({ limit: num }) const pasteString = messages.reverse().filter(m => !m.applicationID).map(m => `${displayUser(m.author)} (${m.author.id}) | ${new Date(m.timestamp).toUTCString()}: ${m.content ? m.content : ''} ${m.embeds.length === 0 ? '' : `| {"embeds": [${m.embeds.map(e => JSON.stringify(e))}]}`} | ${m.attachments.length === 0 ? '' : ` =====> Attachment: ${m.attachments[0].filename}:${m.attachments[0].url}`}`).join('\r\n') const link = await createHaste(pasteString) - if (!link) { - return message.channel.createMessage('Unable to get the archive haste link') - } - message.channel.createMessage(`<@${message.author.id}>, **${messages.length}** message(s) could be archived. Link: ${link}`) + message.channel.createMessage({ + content: `<@${message.author.id}>, **${messages.length}** message(s) could be archived. Link: ${link || "View the messages.txt file!"}`, + }, { + name: "messages.txt", + file: Buffer.from(pasteString) + }) }, name: 'archive', category: 'Utility', diff --git a/src/bot/commands/setchannel.js b/src/bot/commands/setchannel.js index 215add8..c3125c6 100644 --- a/src/bot/commands/setchannel.js +++ b/src/bot/commands/setchannel.js @@ -1,34 +1,8 @@ const { setEventsLogId } = require('../../db/interfaces/postgres/update') const guildWebhookCacher = require('../modules/guildWebhookCacher') +const { ALL_EVENTS: eventList } = require("../utils/constants") const cacheGuild = require('../utils/cacheGuild') -const eventList = [ - 'channelCreate', - 'channelUpdate', - 'channelDelete', - 'guildBanAdd', - 'guildBanRemove', - 'guildRoleCreate', - 'guildRoleDelete', - 'guildRoleUpdate', - 'guildUpdate', - 'messageDelete', - 'messageDeleteBulk', - 'messageUpdate', - 'guildMemberAdd', - 'guildMemberKick', - 'guildMemberRemove', - 'guildMemberUpdate', - 'voiceChannelLeave', - 'voiceChannelJoin', - 'voiceStateUpdate', - 'voiceChannelSwitch', - 'guildMemberNickUpdate', - 'guildMemberVerify', - 'guildEmojisUpdate', - 'guildMemberBoostUpdate' -] - module.exports = { func: async (message, suffix) => { const botPerms = message.channel.permissionsOf(global.bot.user.id).json diff --git a/src/bot/events/interactionCreate.js b/src/bot/events/interactionCreate.js index 8f425d1..e9835be 100644 --- a/src/bot/events/interactionCreate.js +++ b/src/bot/events/interactionCreate.js @@ -1,12 +1,11 @@ -const fs = require('fs') -const path = require('path') -const Eris = require('eris') +const { readdirSync } = require('fs') +const { resolve } = require('path') const { EMBED_COLORS, displayUser } = require('../utils/constants') const { getEmbedFooter, getAuthorField } = require('../utils/embeds') -const { NewsThreadChannel, PrivateThreadChannel, PublicThreadChannel } = require('eris') +const { NewsThreadChannel, PrivateThreadChannel, PublicThreadChannel, ComponentInteraction, Constants, CommandInteraction, VoiceChannel } = require('eris') -let slashCommands = fs.readdirSync(path.resolve('src', 'bot', 'slashcommands')).map(filename => { - return require(path.resolve('src', 'bot', 'slashcommands', filename)) +let slashCommands = readdirSync(resolve('src', 'bot', 'slashcommands')).map(filename => { + return require(resolve('src', 'bot', 'slashcommands', filename)) }) const waitingCustomIDs = new Map() @@ -20,7 +19,7 @@ module.exports = { if (interaction.applicationID !== global.bot.user.id) { resolve() } - if (interaction instanceof Eris.ComponentInteraction) { + if (interaction instanceof ComponentInteraction) { if (interaction.data.custom_id && waitingCustomIDs.has(interaction.data.custom_id)) { if (interaction.member.user.id === waitingCustomIDs.get(interaction.data.custom_id).userID) { interaction.acknowledge().catch(() => {}).then(() => { @@ -29,17 +28,17 @@ module.exports = { }) } } - } else if (interaction instanceof Eris.CommandInteraction) { + } else if (interaction instanceof CommandInteraction) { const channel = global.bot.getChannel(interaction.channel.id) - if (!channel || channel instanceof Eris.VoiceChannel) return // no need to check send messages because replies are made using webhooks + if (!channel || channel instanceof VoiceChannel) return // no need to check send messages because replies are made using webhooks if (interaction.data.name === 'reloadinteractions' && process.env.CREATOR_IDS.split(",").includes(interaction.member.user.id)) { - fs.readdirSync(path.resolve('src', 'bot', 'slashcommands')).forEach(filename => { - delete require.cache[require.resolve(path.resolve('src', 'bot', 'slashcommands', filename))] + readdirSync(resolve('src', 'bot', 'slashcommands')).forEach(filename => { + delete require.cache[require.resolve(resolve('src', 'bot', 'slashcommands', filename))] }) - slashCommands = fs.readdirSync(path.resolve('src', 'bot', 'slashcommands')).map(filename => { - return require(path.resolve('src', 'bot', 'slashcommands', filename)) + slashCommands = readdirSync(resolve('src', 'bot', 'slashcommands')).map(filename => { + return require(resolve('src', 'bot', 'slashcommands', filename)) }) - interaction.createMessage({ content: 'šŸ†— reloaded slash commands', flags: Eris.Constants.MessageFlags.EPHEMERAL }).catch(() => {}) + interaction.createMessage({ content: 'šŸ†— reloaded slash commands', flags: Constants.MessageFlags.EPHEMERAL }).catch(() => {}) resolve() } const command = slashCommands.find(c => c.name === interaction.data.name) @@ -59,7 +58,7 @@ module.exports = { url: interaction.member.user.dynamicAvatarURL(null, 64) } }], - flags: Eris.Constants.MessageFlags.EPHEMERAL + flags: Constants.MessageFlags.EPHEMERAL }).catch(() => {}) return } @@ -78,7 +77,7 @@ module.exports = { url: interaction.member.user.dynamicAvatarURL(null, 64) } }], - flags: Eris.Constants.MessageFlags.EPHEMERAL + flags: Constants.MessageFlags.EPHEMERAL }).catch(() => {}) return } @@ -98,7 +97,7 @@ module.exports = { url: global.bot.user.dynamicAvatarURL(null, 64) } }], - flags: Eris.Constants.MessageFlags.EPHEMERAL + flags: Constants.MessageFlags.EPHEMERAL }).catch(() => {}) return } diff --git a/src/bot/index.js b/src/bot/index.js index 9e98523..8ef2162 100644 --- a/src/bot/index.js +++ b/src/bot/index.js @@ -61,7 +61,7 @@ async function init () { 'guildInvites', 'guildMembers', 'guildMessages', - 'guildBans' + 'guildBans', ], defaultImageFormat: 'png', ...(process.env.USE_MAX_CONCURRENCY === 'true' ? { useMaxConcurrency: true } : {}) diff --git a/src/bot/modules/commandhandler.js b/src/bot/modules/commandhandler.js index 08afa17..4e376cd 100644 --- a/src/bot/modules/commandhandler.js +++ b/src/bot/modules/commandhandler.js @@ -1,9 +1,9 @@ -const Eris = require('eris') +const { TextVoiceChannel } = require('eris') const statAggregator = require('./statAggregator') const { displayUser } = require('../utils/constants') module.exports = async message => { - if (message.author.bot || !message.member || message.channel instanceof Eris.TextVoiceChannel) return + if (message.author.bot || !message.member || message.channel instanceof TextVoiceChannel) return if (message.content.startsWith(process.env.GLOBAL_BOT_PREFIX)) { const cmd = message.content.substring(process.env.GLOBAL_BOT_PREFIX.length).split(' ')[0].toLowerCase() const splitSuffix = message.content.substring(process.env.GLOBAL_BOT_PREFIX).split(' ') @@ -12,7 +12,7 @@ module.exports = async message => { } } -function processCommand (message, commandName, suffix) { +function processCommand(message, commandName, suffix) { const command = global.bot.commands[commandName] if (!command) return const bp = message.channel.permissionsOf(global.bot.user.id).json diff --git a/src/bot/slashcommands/archive.js b/src/bot/slashcommands/archive.js index 7651e7f..51d661a 100644 --- a/src/bot/slashcommands/archive.js +++ b/src/bot/slashcommands/archive.js @@ -6,21 +6,13 @@ module.exports = { name: 'archive', botPerms: ['readMessageHistory'], userPerms: ['readMessageHistory', 'manageMessages'], + /** + * @param {import("eris").CommandInteraction} interaction + */ func: async interaction => { - if (!process.env.PASTE_SITE_ROOT_URL) return interaction.createMessage({ - embeds: [{ - title: 'Unsuccessful', - description: 'The bot owner hasn\'t yet configured the paste site, so this command is unavailable.', - thumbnail: { - url: interaction.member.user.dynamicAvatarURL(null, 64) - }, - color: EMBED_COLORS.RED, - footer: getEmbedFooter(global.bot.user), - author: getAuthorField(interaction.member.user) - }] - }).catch(() => { }) const limit = parseInt(process.env.MESSAGE_ARCHIVE_SIZE || 1000) - if (!interaction.data.options || !interaction.data.options[0] || interaction.data.options[0].value > limit || interaction.data.options[0].value < 5) { + const num = interaction.data.options?.[0]?.value || 0; + if (!num || num > limit || num < 5) { interaction.createMessage({ embeds: [{ title: 'Unsuccessful', @@ -34,12 +26,12 @@ module.exports = { }] }).catch(() => { }) } - const fetchedMessages = await global.bot.getChannel(interaction.channel.id).getMessages({ limit: interaction.data.options[0].value }) + const fetchedMessages = await global.bot.getChannel(interaction.channel.id).getMessages({ limit: num }) const pasteString = fetchedMessages.reverse().filter(m => !m.applicationID).map(m => `${displayUser(m.author)} (${m.author.id}) | ${new Date(m.timestamp)}: ${m.content || ''} | ${m.embeds.length === 0 ? '' : `{"embeds": [${m.embeds.map(e => JSON.stringify(e))}]}`} | ${m.attachments.length === 0 ? '' : ` ${m.attachments.map((c) => `=====> Attachment: ${c.filename}: ${m.url}`).join(" | ")}`}`).join('\r\n') await interaction.createMessage({ embeds: [{ // make sure followup message is created before doing any more work title: 'Processing', - description: `Processing request from ${displayUser(interaction.member)} for an archive of ${interaction.data.options[0].value} messages`, + description: `Processing request from ${displayUser(interaction.member)} for an archive of ${num} messages`, thumbnail: { url: interaction.member.user.dynamicAvatarURL(null, 64) }, @@ -49,30 +41,20 @@ module.exports = { }] }).catch(() => null); const link = await createHaste(pasteString); - if (!link) { - return interaction.editOriginalMessage({ - embeds: [{ - title: 'Error', - description: 'The archive service returned an error, please try again later!', - thumbnail: { - url: interaction.member.user.dynamicAvatarURL(null, 64) - }, - color: EMBED_COLORS.RED, - footer: getEmbedFooter(global.bot.user) - }] - }).catch(() => { }) - } interaction.editOriginalMessage({ embeds: [{ title: 'Success', - description: `Archived ${fetchedMessages.length} messages: ${link}`, + description: `Archived ${fetchedMessages.length} messages: ${link || "View the messages.txt file!"}`, thumbnail: { url: interaction.member.user.dynamicAvatarURL(null, 64) }, color: EMBED_COLORS.GREEN, footer: getEmbedFooter(global.bot.user), author: getAuthorField(interaction.member.user) - }] + }], + }, { + name: "messages.txt", + file: Buffer.from(pasteString) }).catch(() => { }) } } diff --git a/src/bot/slashcommands/help.js b/src/bot/slashcommands/help.js index 92524c0..d0ebf94 100644 --- a/src/bot/slashcommands/help.js +++ b/src/bot/slashcommands/help.js @@ -1,4 +1,4 @@ -const Eris = require('eris') +const { Constants } = require('eris') const { EMBED_COLORS, ALL_EVENTS, EVENT_HELP } = require('../utils/constants') const { getEmbedFooter, getAuthorField } = require('../utils/embeds') @@ -38,7 +38,7 @@ module.exports = { }], footer: getEmbedFooter(global.bot.user) }], - flags: Eris.Constants.MessageFlags.EPHEMERAL + flags: Constants.MessageFlags.EPHEMERAL }).catch(() => {}) } else if (interaction.data.options?.find(o => o.name === 'guide')) { interaction.createMessage({ @@ -61,7 +61,7 @@ module.exports = { url: interaction.member.user.dynamicAvatarURL(null, 64) } }], - flags: Eris.Constants.MessageFlags.EPHEMERAL + flags: Constants.MessageFlags.EPHEMERAL }).catch(() => {}) } else if (interaction.data.options?.find(o => o.name === 'event')) { const eventName = interaction.data.options?.find(o => o.name === 'event').value @@ -76,7 +76,7 @@ module.exports = { author: getAuthorField(interaction.member.user), description: `__**Description**__\n${EVENT_HELP[eventName]}\n\n*Not what you're looking for? Join [my support server](${process.env.DISCORD_SUPPORT_SERVER})*.` }], - flags: Eris.Constants.MessageFlags.EPHEMERAL + flags: Constants.MessageFlags.EPHEMERAL }) } } diff --git a/src/bot/slashcommands/invite.js b/src/bot/slashcommands/invite.js index c05942f..4fab21d 100644 --- a/src/bot/slashcommands/invite.js +++ b/src/bot/slashcommands/invite.js @@ -1,4 +1,4 @@ -const Eris = require('eris') +const { Constants } = require('eris') const { EMBED_COLORS } = require('../utils/constants.js') const { getEmbedFooter } = require('../utils/embeds') @@ -22,7 +22,7 @@ module.exports = { }], footer: getEmbedFooter(global.bot.user) }], - flags: Eris.Constants.MessageFlags.EPHEMERAL + flags: Constants.MessageFlags.EPHEMERAL }) } } diff --git a/src/bot/slashcommands/setcmds.js b/src/bot/slashcommands/setcmds.js index e386a8b..b029500 100644 --- a/src/bot/slashcommands/setcmds.js +++ b/src/bot/slashcommands/setcmds.js @@ -1,11 +1,11 @@ -const path = require('path') +const { resolve } = require('path') module.exports = { name: 'setcmds', type: 'creator', func: async interaction => { - if (require.cache[path.resolve('src', 'bot', 'utils', 'slashcommandconstants.js')]) { - delete require.cache[path.resolve('src', 'bot', 'utils', 'slashcommandconstants.js')] + if (require.cache[resolve('src', 'bot', 'utils', 'slashcommandconstants.js')]) { + delete require.cache[resolve('src', 'bot', 'utils', 'slashcommandconstants.js')] } const { developerCommands, commands } = require('../utils/slashcommandconstants') try { diff --git a/src/bot/slashcommands/setup.js b/src/bot/slashcommands/setup.js index f07e1f3..f982de0 100644 --- a/src/bot/slashcommands/setup.js +++ b/src/bot/slashcommands/setup.js @@ -1,4 +1,4 @@ -const Eris = require('eris') +const { Constants } = require('eris') const { v4: uuidv4 } = require('uuid') const { setEventsLogId } = require('../../db/interfaces/postgres/update') const { EMBED_COLORS, PRESET_EVENT_MAP, ALL_EVENTS } = require('../utils/constants') @@ -23,9 +23,9 @@ async function handlePresetSetup (interaction, recursionUUID) { const followupUUID = recursionUUID || uuidv4() try { const components = [{ - type: Eris.Constants.ComponentTypes.ACTION_ROW, + type: Constants.ComponentTypes.ACTION_ROW, components: [{ - type: Eris.Constants.ComponentTypes.SELECT_MENU, + type: Constants.ComponentTypes.SELECT_MENU, custom_id: followupUUID, max_values: 9, min_values: 0, @@ -86,9 +86,9 @@ async function handlePresetSetup (interaction, recursionUUID) { } } if (recursionUUID) { - await interaction.editOriginalMessage({ embeds: [setupEmbed], flags: Eris.Constants.MessageFlags.EPHEMERAL, components }) + await interaction.editOriginalMessage({ embeds: [setupEmbed], flags: Constants.MessageFlags.EPHEMERAL, components }) } else { - await interaction.createMessage({ embeds: [setupEmbed], flags: Eris.Constants.MessageFlags.EPHEMERAL, components }) + await interaction.createMessage({ embeds: [setupEmbed], flags: Constants.MessageFlags.EPHEMERAL, components }) } } catch (e) { global.logger.error('error handling preset menu', e) @@ -135,7 +135,7 @@ async function handlePresetSetup (interaction, recursionUUID) { footer: getEmbedFooter(global.bot.user), author: getAuthorField(interaction.member.user) }], - flags: Eris.Constants.MessageFlags.EPHEMERAL + flags: Constants.MessageFlags.EPHEMERAL }) return } @@ -156,9 +156,9 @@ async function handleIndividualSetup (interaction, recursionUUID) { const followupUUID = recursionUUID || uuidv4() try { const components = [{ - type: Eris.Constants.ComponentTypes.ACTION_ROW, + type: Constants.ComponentTypes.ACTION_ROW, components: [{ - type: Eris.Constants.ComponentTypes.SELECT_MENU, + type: Constants.ComponentTypes.SELECT_MENU, custom_id: followupUUID, max_values: 24, min_values: 0, @@ -375,9 +375,9 @@ async function handleIndividualSetup (interaction, recursionUUID) { } } if (recursionUUID) { - await interaction.editOriginalMessage({ embeds: [setupEmbed], flags: Eris.Constants.MessageFlags.EPHEMERAL, components }) + await interaction.editOriginalMessage({ embeds: [setupEmbed], flags: Constants.MessageFlags.EPHEMERAL, components }) } else { - await interaction.createMessage({ embeds: [setupEmbed], flags: Eris.Constants.MessageFlags.EPHEMERAL, components }) + await interaction.createMessage({ embeds: [setupEmbed], flags: Constants.MessageFlags.EPHEMERAL, components }) } } catch (e) { global.logger.error('Error handling preset menu', e) @@ -421,7 +421,7 @@ async function handleIndividualSetup (interaction, recursionUUID) { footer: getEmbedFooter(global.bot.user), author: getAuthorField(interaction.member.user) }], - flags: Eris.Constants.MessageFlags.EPHEMERAL + flags: Constants.MessageFlags.EPHEMERAL }) return } @@ -451,7 +451,7 @@ async function handleListLogSetup (interaction) { description: logLines.length !== 0 ? logLines.join('\n') : 'I am not logging any events to this server, see `/setup` or `/help` for setup help.', color: EMBED_COLORS.PURPLED_BLUE }], - flags: Eris.Constants.MessageFlags.EPHEMERAL + flags: Constants.MessageFlags.EPHEMERAL }).catch(() => {}) } diff --git a/src/bot/slashcommands/stoplogging.js b/src/bot/slashcommands/stoplogging.js index 49adecb..135a7b9 100644 --- a/src/bot/slashcommands/stoplogging.js +++ b/src/bot/slashcommands/stoplogging.js @@ -1,4 +1,4 @@ -const Eris = require('eris') +const { Constants } = require('eris') const { clearEventByID, setAllEventsOneId } = require('../../db/interfaces/postgres/update') const { EMBED_COLORS } = require('../utils/constants.js') const { getAuthorField, getEmbedFooter } = require('../utils/embeds.js') @@ -24,7 +24,7 @@ module.exports = { author: getAuthorField(interaction.member.user), footer: getEmbedFooter(global.bot.user) }], - flags: Eris.Constants.MessageFlags.EPHEMERAL + flags: Constants.MessageFlags.EPHEMERAL }).catch(() => {}) } else { const eventsLoggingHere = global.bot.guildSettingsCache[interaction.guildID].eventLogByNames(channelToStopLogging || interaction.channel.id) @@ -40,7 +40,7 @@ module.exports = { author: getAuthorField(interaction.member.user), footer: getEmbedFooter(global.bot.user) }], - flags: Eris.Constants.MessageFlags.EPHEMERAL + flags: Constants.MessageFlags.EPHEMERAL }).catch(() => {}) return } @@ -59,7 +59,7 @@ module.exports = { author: getAuthorField(interaction.member.user), footer: getEmbedFooter(global.bot.user) }], - flags: Eris.Constants.MessageFlags.EPHEMERAL + flags: Constants.MessageFlags.EPHEMERAL }).catch(() => {}) } } diff --git a/src/bot/utils/recoverSettings.js b/src/bot/utils/recoverSettings.js index 7e1683b..b54ffb7 100644 --- a/src/bot/utils/recoverSettings.js +++ b/src/bot/utils/recoverSettings.js @@ -1,5 +1,5 @@ const { getAllGuilds } = require('../../db/interfaces/postgres/read') -const {createGuild} = require('../../db/interfaces/postgres/create') +const { createGuild } = require('../../db/interfaces/postgres/create') module.exports = async () => { // If the bot sees a guild that the DB doesn't know, create a record for it const allGuilds = await getAllGuilds() diff --git a/src/db/clients/rethink.js b/src/db/clients/rethink.js deleted file mode 100644 index b31fdf9..0000000 --- a/src/db/clients/rethink.js +++ /dev/null @@ -1,15 +0,0 @@ -// const Dash = require('rethinkdbdash') - -// require('dotenv').config() - -// const r = new Dash({ -// user: process.env.RETHINK_USERNAME, -// password: process.env.RETHINK_PASSWORD || '', -// silent: true, -// servers: [{ -// host: 'localhost', -// port: '28015' -// }] -// }) - -// module.exports = r diff --git a/src/db/interfaces/redis/redislock.js b/src/db/interfaces/redis/redislock.js index c645c85..cf8a61f 100644 --- a/src/db/interfaces/redis/redislock.js +++ b/src/db/interfaces/redis/redislock.js @@ -2,11 +2,11 @@ const redisClient = require('../../clients/redis') const Redlock = require('redlock') const redlock = new Redlock([redisClient], { - driftFactor: 0.01, // time in ms - retryCount: 10, - retryDelay: 200, // time in ms - retryJitter: 200 // time in ms - } + driftFactor: 0.01, // time in ms + retryCount: 10, + retryDelay: 200, // time in ms + retryJitter: 200 // time in ms +} ) module.exports = redlock \ No newline at end of file diff --git a/src/miscellaneous/commandIndexer.js b/src/miscellaneous/commandIndexer.js index 716d01b..f74a13c 100644 --- a/src/miscellaneous/commandIndexer.js +++ b/src/miscellaneous/commandIndexer.js @@ -1,14 +1,14 @@ -const fs = require('fs') -const path = require('path') +const { readdirSync } = require('fs') +const { resolve } = require('path') const GenericCommand = require('../bot/bases/GenericCommand') module.exports = () => { - const files = fs.readdirSync(path.resolve('src', 'bot', 'commands')) + const files = readdirSync(resolve('src', 'bot', 'commands')) files.forEach(filename => { - if (require.cache[path.resolve('src', 'bot', 'commands', filename)]) { - delete require.cache[path.resolve('src', 'bot', 'commands', filename)] + if (require.cache[resolve('src', 'bot', 'commands', filename)]) { + delete require.cache[resolve('src', 'bot', 'commands', filename)] } // truly gross code that should be remade eventually - new GenericCommand(require(path.resolve('src', 'bot', 'commands', filename))) + new GenericCommand(require(resolve('src', 'bot', 'commands', filename))) }) } diff --git a/src/miscellaneous/listenerIndexer.js b/src/miscellaneous/listenerIndexer.js index 2cee718..91e8c01 100644 --- a/src/miscellaneous/listenerIndexer.js +++ b/src/miscellaneous/listenerIndexer.js @@ -1,15 +1,15 @@ -const fs = require('fs') -const path = require('path') +const { readdirSync } = require('fs') +const { resolve } = require('path') module.exports = () => { - const files = fs.readdirSync(path.resolve('src', 'bot', 'events')) + const files = readdirSync(resolve('src', 'bot', 'events')) const once = [] const on = [] files.forEach(filename => { - if (require.cache[path.resolve('src', 'bot', 'events', filename)]) { - delete require.cache[path.resolve('src', 'bot', 'events', filename)] + if (require.cache[resolve('src', 'bot', 'events', filename)]) { + delete require.cache[resolve('src', 'bot', 'events', filename)] } - const event = require(path.resolve('src', 'bot', 'events', filename)) + const event = require(resolve('src', 'bot', 'events', filename)) event.name = event.name.replace('.js', '') if (event.type === 'once') { once.push({ name: event.name, handle: event.handle }) From aa7542e40afa32ad83f3a409369dff73ea4e5297 Mon Sep 17 00:00:00 2001 From: Elara Services <43923163+Elara-Discord-Bots@users.noreply.github.com> Date: Sun, 14 Apr 2024 21:19:37 -0700 Subject: [PATCH 07/13] changes --- .env.example | 49 ++++++++++++++++-------------- README.md | 16 +++++----- package.json | 3 +- src/miscellaneous/webhooklogger.js | 14 ++++----- 4 files changed, 42 insertions(+), 40 deletions(-) diff --git a/.env.example b/.env.example index e9a869c..830d05a 100644 --- a/.env.example +++ b/.env.example @@ -1,24 +1,27 @@ -AES_KEY=yourAESKey # The key used for AES encryption. Can be any ASCII string of any length. -BEZERK_URI=ws://localhost:1234 # URI for Bezerk https://github.com/thesharks/bezerk. Leave blank if not using (it's NOT required). -BEZERK_SECRET=yourBezerkSecret # Secret for Bezerk. Leave blank if not using (it's NOT required). -BOT_CREATOR_NAME=TizzySaurus # Your discord username. Used in certain messages to ping you (@{BOT_CREATOR_NAME}). -BOT_TOKEN=yourBotToken # The token of your bot, retrieved from the Developer Portal. -CREATOR_IDS=442244135840382978 # User IDs of the bot developer(s), separated by commas (NO spaces). -DISCORD_SUPPORT_SERVER=discord.gg/WYTxVjzHnc # Discord invite for your support server. Used in a number of message ouputs. Currently required. +# REQUIRED +AES_KEY="RANDOM_STRING_HERE" # The key used for AES encryption. Can be any ASCII string of any length. +BOT_CREATOR_NAME="TizzySaurus" # Your discord username. Used in certain messages to ping you (@{BOT_CREATOR_NAME}). +BOT_TOKEN="YOUR_DISCORD_BOT_TOKEN" # The token of your bot, retrieved from the Developer Portal. +CREATOR_IDS="442244135840382978" # User IDs of the bot developer(s), separated by commas (NO spaces). +DISCORD_SUPPORT_SERVER="discord.gg/WYTxVjzHnc" # Discord invite for your support server. Used in a number of message ouputs. Currently required. DISCORD_WEBHOOK_URL=yourWebhookUrl # Webhook URL that's used for sending certain dev-logs to Discord. -ENABLE_TEXT_COMMANDS=true # Whether to allow users to utilise prefix/text commands. 'true' or 'false'. Recommend true. -GLOBAL_BOT_PREFIX=% # Prefix to use for prefix/text commands. -MESSAGE_ARCHIVE_SIZE=1000 # How many messages to fetch for the archive commands -MESSAGE_BATCH_SIZE=100 # How many messages to store in 'cache' before dumping into database. Defaults to 1000. -MESSAGE_HISTORY_DAYS=2 # Maximum age of messages stored in the database. Note that you have to manually setup clearing, e.g. via pg_cron https://github.com/citusdata/pg_cron. -PASTE_SITE_ROOT_URL=https://my-paste-site.com # URL of your selfhosted [haste-server](https://github.com/toptal/haste-server). Used in archive commands and messageDeleteBulk event. -PASTE_SITE_TOKEN=yourHasteServerToken # Optional token to pass in the Authorization header of requests to your self-hosted haste-server. -PGDATABASE=logger # Name of the database that data is stored within. -PGHOST=localhost # Server that PostgreSQL is running on. -PGPASSWORD=postgresPassword # Password of the `PGUSER` user. -PGPORT=5432 # Port that PostgreSQL is running on. Defaults to 5432. -PGUSER=postgresUsername # Name of the user (role) to use when connecting to the database. -RAVEN_URI=sentryUri # Sentry URI obtained from sentry.io. Leave blank if not using sentry. -REDIS_LOCK_TTL=2000 # Time to Live (TTL) for Redis requests. -STAT_SUBMISSION_INTERVAL= # How often to submit stats to Zabbix. Leave blank to not submit stats. -ZABBIX_HOST= # Server that Zabbix is running on. Leave blank if not submitting stats. \ No newline at end of file +ENABLE_TEXT_COMMANDS="true" # Whether to allow users to utilise prefix/text commands. 'true' or 'false'. Recommend true. +GLOBAL_BOT_PREFIX="%" # Prefix to use for prefix/text commands. +MESSAGE_ARCHIVE_SIZE="1000" # How many messages to fetch for the archive commands +MESSAGE_BATCH_SIZE="100" # How many messages to store in 'cache' before dumping into database. Defaults to 1000. +MESSAGE_HISTORY_DAYS="2" # Maximum age of messages stored in the database. Note that you have to manually setup clearing, e.g. via pg_cron https://github.com/citusdata/pg_cron. +PASTE_SITE_ROOT_URL="https://my-paste-site.com" # URL of your selfhosted [haste-server](https://github.com/toptal/haste-server). Used in archive commands and messageDeleteBulk event. +PGDATABASE="logger" # Name of the database that data is stored within. +PGHOST="localhost" # Server that PostgreSQL is running on. +PGPASSWORD="postgresPassword" # Password of the `PGUSER` user. +PGPORT="5432" # Port that PostgreSQL is running on. Defaults to 5432. +PGUSER="postgresUsername" # Name of the user (role) to use when connecting to the database. +REDIS_LOCK_TTL="2000" # Time to Live (TTL) for Redis requests. + +# OPTIONAL +BEZERK_URI="" # URI for Bezerk https://github.com/thesharks/bezerk. (example: ws://localhost:1234) +BEZERK_SECRET="" # Secret for Bezerk. Leave blank if not using (it's NOT required). +PASTE_SITE_TOKEN="" # Token to pass in the Authorization header of requests to your self-hosted haste-server. +RAVEN_URI="" # Sentry URI obtained from sentry.io. +STAT_SUBMISSION_INTERVAL="" # How often to submit stats to Zabbix. +ZABBIX_HOST="" # Server that Zabbix is running on. \ No newline at end of file diff --git a/README.md b/README.md index 4a7dd85..f2b7ef4 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,22 @@ -
- - Logger - +
+
-Logger is a powerful [Discord](https://discordapp.com) bot meant to give staff members oversight over the various actions taking place in their server. Come talk about me with my creator at [Logger's Lounge](https://discord.gg/ed7Gaa3). +TizzyLog is a powerful [Discord](https://discord.com) bot meant to give staff members oversight over the various actions taking place in their server. Come talk about me with my creator at [TizzyLog server](https://discord.gg/WYTxVjzHnc). ## Installation You are mostly on your own selfhosting this version. Required applications: -- PostgreSQL 11 +- PostgreSQL - Redis -- NodeJS 14+ (14.5.0) +- NodeJS 16+ 1. Setup Postgres and add a superuser (default user works) 2. Clone bot repo and enter the created folder 3. Copy .env.example into .env 4. Fill out **all** fields in it (even Sentry unless you hotpatch it out) 5. `npm install` -6. `node src/miscellaneous/generateDB.js` +6. `npm run genDB` 7. Set `ENABLE_TEXT_COMMANDS="true"` in .env 8. `node index.js` 9. Use your prefix to set the bot's commands. If yours is %, then you'd do `%setcmd global` to globally set commands, and `%setcmd guild` to quickly set server-specific slash commands @@ -34,6 +32,6 @@ Pull requests are welcome as long as it follows the following guidelines: 1. Is your idea really one that a large group of moderators would like? 2. Is your idea scalable? 3. Will your idea cause the bot to hit it's global ratelimit? -4. Have you proposed it to *piero#5432* in my [support server?](https://discord.gg/ed7Gaa3) +4. Have you proposed it to *tizzysaurus* in my [support server?](https://discord.gg/WYTxVjzHnc) If you have done all of the above steps, then open a pull request and I will review it. Style guide and testing will be implemented in a later update. diff --git a/package.json b/package.json index 437af10..e31eda0 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ "main": "index.js", "scripts": { "test": "standard", - "lint": "eslint . --ext .js" + "lint": "eslint . --ext .js", + "genDB": "node src/miscellaneous/generateDB.js" }, "keywords": [ "logging", diff --git a/src/miscellaneous/webhooklogger.js b/src/miscellaneous/webhooklogger.js index 2624ad3..09495d2 100644 --- a/src/miscellaneous/webhooklogger.js +++ b/src/miscellaneous/webhooklogger.js @@ -7,7 +7,7 @@ setInterval(() => { globalHookErrors-- // This timeout exists so that if the shard manager starts to spew errors, I don't get IP banned from Discord. }, 5000) -function send(type = "Generic", embeds = [], username = null, avatar_url = null) { +function send(type = 'Generic', embeds = [], username = null, avatar_url = null) { if (globalHookErrors > 5) { return } @@ -23,7 +23,7 @@ function send(type = "Generic", embeds = [], username = null, avatar_url = null) } function fatal(message) { - send("Fatal Error", [ + send('Fatal Error', [ { title: 'Fatal', description: message, @@ -33,7 +33,7 @@ function fatal(message) { } function error(message) { - send("Error", [ + send('Error', [ { title: 'Error', description: message, @@ -43,7 +43,7 @@ function error(message) { } function warn(message) { - send(`Warning`, [ + send('Warning', [ { title: 'Warning', description: message, @@ -53,7 +53,7 @@ function warn(message) { } function generic(message) { - send("Generic", [ + send('Generic', [ { title: 'Generic', description: message, @@ -63,13 +63,13 @@ function generic(message) { } function custom(message) { - send("Custom", [ + send('Custom', [ { title: message.title || 'Custom Notification', color: message.color || 6052351, description: message.description || 'No message description provided.' } - ], message.title, message.avatar_url); + ], message.title, message.avatar_url) } exports.error = error From 99f55ce342bf2bd4787572fae74d1b0601462b58 Mon Sep 17 00:00:00 2001 From: Elara Services <43923163+Elara-Discord-Bots@users.noreply.github.com> Date: Sun, 14 Apr 2024 21:23:13 -0700 Subject: [PATCH 08/13] bop --- README.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f2b7ef4..755ea04 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,9 @@ +
+ This is a fork of [Logger v3](https://github.com/curtisf/logger) + This fork includes some improvements and features the main code doesn't have. + - Image/File logs for messageDelete / messageBulkDelete events. +
+
@@ -17,9 +23,8 @@ You are mostly on your own selfhosting this version. Required applications: 4. Fill out **all** fields in it (even Sentry unless you hotpatch it out) 5. `npm install` 6. `npm run genDB` -7. Set `ENABLE_TEXT_COMMANDS="true"` in .env -8. `node index.js` -9. Use your prefix to set the bot's commands. If yours is %, then you'd do `%setcmd global` to globally set commands, and `%setcmd guild` to quickly set server-specific slash commands +7. `node index.js` +8. Use your prefix to set the bot's commands. If yours is %, then you'd do `%setcmd global` to globally set commands, and `%setcmd guild` to quickly set server-specific slash commands ## Usage From 26fbf6c31a41a0eb040e61007c1ddffb9c20b7fa Mon Sep 17 00:00:00 2001 From: Elara Services <43923163+Elara-Discord-Bots@users.noreply.github.com> Date: Sun, 14 Apr 2024 21:24:45 -0700 Subject: [PATCH 09/13] bop --- README.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 755ea04..ee50e91 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,14 @@ -
- This is a fork of [Logger v3](https://github.com/curtisf/logger) - This fork includes some improvements and features the main code doesn't have. - - Image/File logs for messageDelete / messageBulkDelete events. -
-
TizzyLog is a powerful [Discord](https://discord.com) bot meant to give staff members oversight over the various actions taking place in their server. Come talk about me with my creator at [TizzyLog server](https://discord.gg/WYTxVjzHnc). +## Fork Details: +- This is a fork of [Logger v3](https://github.com/curtisf/logger) + - This fork includes some improvements and features the main repo doesn't have. + - Image/File logs for messageUpdate, messageDelete, messageBulkDelete events. + ## Installation You are mostly on your own selfhosting this version. Required applications: From 25b45854c91df7b03edb6cd028dcbbfbcd77ed85 Mon Sep 17 00:00:00 2001 From: Elara Services <43923163+Elara-Discord-Bots@users.noreply.github.com> Date: Sun, 14 Apr 2024 21:27:00 -0700 Subject: [PATCH 10/13] readme --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ee50e91..3b100e3 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,10 @@ TizzyLog is a powerful [Discord](https://discord.com) bot meant to give staff members oversight over the various actions taking place in their server. Come talk about me with my creator at [TizzyLog server](https://discord.gg/WYTxVjzHnc). ## Fork Details: -- This is a fork of [Logger v3](https://github.com/curtisf/logger) - - This fork includes some improvements and features the main repo doesn't have. - - Image/File logs for messageUpdate, messageDelete, messageBulkDelete events. +**This is a fork of [Logger v3](https://github.com/curtisf/logger)** +- Public Instance: [Invite](https://discord.com/oauth2/authorize?client_id=1223274176786206853) +- This fork includes some improvements and features the main repo doesn't have. +> - Image/File logs for `messageUpdate`, `messageDelete`, `messageBulkDelete` events. ## Installation From a00b5f23100fe2a7a988a7576a31292a180f87ee Mon Sep 17 00:00:00 2001 From: Elara Services <43923163+Elara-Discord-Bots@users.noreply.github.com> Date: Sun, 14 Apr 2024 21:29:51 -0700 Subject: [PATCH 11/13] add links for postgres, redis, nodejs --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3b100e3..bea25b3 100644 --- a/README.md +++ b/README.md @@ -13,18 +13,19 @@ TizzyLog is a powerful [Discord](https://discord.com) bot meant to give staff me ## Installation You are mostly on your own selfhosting this version. Required applications: -- PostgreSQL -- Redis -- NodeJS 16+ +- [PostgreSQL](https://www.postgresql.org/download/) +- [Redis](https://redis.io/downloads/) +- [NodeJS](https://nodejs.org/en/download) 1. Setup Postgres and add a superuser (default user works) 2. Clone bot repo and enter the created folder 3. Copy .env.example into .env -4. Fill out **all** fields in it (even Sentry unless you hotpatch it out) +4. Fill out **all** of the **required** fields in `.env` 5. `npm install` 6. `npm run genDB` 7. `node index.js` 8. Use your prefix to set the bot's commands. If yours is %, then you'd do `%setcmd global` to globally set commands, and `%setcmd guild` to quickly set server-specific slash commands +> NOTE: You'll need to restart your Discord client in order for them to show up! ## Usage From 84aec6ad9eeb46f1198c72675029a504d65568e2 Mon Sep 17 00:00:00 2001 From: Elara Services <43923163+Elara-Discord-Bots@users.noreply.github.com> Date: Mon, 15 Apr 2024 11:34:52 -0700 Subject: [PATCH 12/13] slight improvement --- src/db/interfaces/postgres/read.js | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/db/interfaces/postgres/read.js b/src/db/interfaces/postgres/read.js index 5830a05..5f32f8b 100644 --- a/src/db/interfaces/postgres/read.js +++ b/src/db/interfaces/postgres/read.js @@ -20,12 +20,12 @@ async function getGuild(guildID) { async function getMessageById(messageID) { let message = await pool.query('SELECT * FROM messages WHERE id=$1', [messageID]) - if (message.rows.length === 0) return null - message = await decryptMessageDoc(message.rows[0]) - return message + if (!message.rows.length) return null + return decryptMessageDoc(message.rows[0]) } -async function decryptMessageDoc(message) { +// Doesn't need to be async +function decryptMessageDoc(message) { message.content = aes.decrypt(message.content) if (message.attachment_b64) message.attachment_b64 = message.attachment_b64.split("|").map(encrypted_img_url => aes.decrypt(encrypted_img_url)).join("|") return message @@ -33,11 +33,8 @@ async function decryptMessageDoc(message) { async function getMessagesByIds(messageIds) { const message = await pool.query('SELECT * FROM messages WHERE id = ANY ($1)', [messageIds]) - if (message.rows.length === 0) return null - const decryptedMessages = [] - message.rows.forEach(async row => { - decryptedMessages.push(await decryptMessageDoc(row)) - }) + if (!message.rows.length) return null + const decryptedMessages = message.rows.map((c) => decryptMessageDoc(c)) return decryptedMessages } From 4e1db04ddcf9e6927ca7f85446764d4ed5319556 Mon Sep 17 00:00:00 2001 From: Elara Services <43923163+Elara-Discord-Bots@users.noreply.github.com> Date: Mon, 15 Apr 2024 13:45:26 -0700 Subject: [PATCH 13/13] switch to just slashcommandconstants --- src/bot/commands/setcmd.js | 266 +------------------------------------ 1 file changed, 2 insertions(+), 264 deletions(-) diff --git a/src/bot/commands/setcmd.js b/src/bot/commands/setcmd.js index f908503..dde9790 100644 --- a/src/bot/commands/setcmd.js +++ b/src/bot/commands/setcmd.js @@ -1,269 +1,7 @@ -const { Constants: ERIS_CONSTANTS } = require('eris') - +const { commands } = require("../utils/slashcommandconstants") + module.exports = { func: async (message, suffix) => { - const commands = [ - { - name: 'ping', - description: 'Is the bot still alive? Find out using this!' - }, - { - name: 'serverinfo', - description: 'Shows you information about the server (role count, member count, features)' - }, - { - name: 'setup', - description: 'Start setting Logger up', - options: [ - { - type: ERIS_CONSTANTS.ApplicationCommandOptionTypes.SUB_COMMAND, - name: 'via_presets', - description: 'Use this option to enable multiple events at once (joinlog, role, channel, etc)' - }, - { - type: ERIS_CONSTANTS.ApplicationCommandOptionTypes.SUB_COMMAND, - name: 'via_individual_event', - description: 'Use this option to enable events one-by-one, for finer control' - }, - { - type: ERIS_CONSTANTS.ApplicationCommandOptionTypes.SUB_COMMAND, - name: 'list', - description: 'Use this option to list channels used for logging (and /stoplogging to stop them)' - } - ] - }, - { - name: 'archive', - description: 'Creates a paste entry with this number of channel messages (auto-deletes in 2 weeks)', - options: [ - { - type: ERIS_CONSTANTS.ApplicationCommandOptionTypes.INTEGER, - name: 'amount', - description: 'The number of messages to create a paste entry with (must be >= 5 or <= 100, 10,000 for patreon bot)', - required: true, - autocomplete: true, - max_value: 100, - min_value: 5 - } - ] - }, - { - name: 'userinfo', - description: 'See information about you (joined at, creation date, roles)', - options: [ - { - type: ERIS_CONSTANTS.ApplicationCommandOptionTypes.USER, - name: 'user', - description: 'If the bot knows the given user, it presents info for them' - } - ] - }, - { - name: 'clearmydata', - description: 'Get information about how to clear your data' - }, - { - name: 'ignorechannel', - description: 'Toggles logging most events from the channel you choose', - options: [ - { - type: ERIS_CONSTANTS.ApplicationCommandOptionTypes.CHANNEL, - name: 'channel-to-ignore', - description: 'The channel to toggle ignoring', - channel_types: [0, 2, 4] // text, voice, category - }, - { - type: ERIS_CONSTANTS.ApplicationCommandOptionTypes.STRING, - name: 'optional', - description: 'Select to see other ignorechannel options', - choices: [ - { - type: ERIS_CONSTANTS.ApplicationCommandOptionTypes.STRING, - name: 'list ignored channels', - value: 'list' - }, - { - type: ERIS_CONSTANTS.ApplicationCommandOptionTypes.STRING, - name: 'reset ignored channels', - value: 'reset' - } - ] - } - ] - }, - { - name: 'stoplogging', - description: 'Turns off bot logging in the specified channel (or everything)', - options: [ - { - type: ERIS_CONSTANTS.ApplicationCommandOptionTypes.CHANNEL, - name: 'channel', - description: 'Stop logging any events in the given channel', - channel_types: [0, 2, 4] // text, voice, category - }, - { - type: ERIS_CONSTANTS.ApplicationCommandOptionTypes.STRING, - name: 'other', - description: 'Other stoplogging options', - choices: [ - { - type: ERIS_CONSTANTS.ApplicationCommandOptionTypes.STRING, - name: 'stop logging anything anywhere (everything)', - value: 'everything' - } - ] - } - ] - }, - { - name: 'invite', - description: 'Receive an embed with customized invite links for your logging purpose' - }, - { - name: 'logbots', - description: 'Toggle whether I log other bot actions (DEFAULT: disabled). Does NOT ignore bots deleting messages!' - }, - { - name: 'help', - description: 'Use to get general bot help (support server, technology)', - options: [ - { - type: ERIS_CONSTANTS.ApplicationCommandOptionTypes.STRING, - name: 'event', - description: 'Get information about a given command', - choices: [ - { - type: ERIS_CONSTANTS.ApplicationCommandOptionTypes.STRING, - name: 'Channel Create', - value: 'channelCreate' - }, - { - type: ERIS_CONSTANTS.ApplicationCommandOptionTypes.STRING, - name: 'Channel Update', - value: 'channelUpdate' - }, - { - type: ERIS_CONSTANTS.ApplicationCommandOptionTypes.STRING, - name: 'Channel Delete', - value: 'channelDelete' - }, - { - type: ERIS_CONSTANTS.ApplicationCommandOptionTypes.STRING, - name: 'Member Banned', - value: 'guildBanAdd' - }, - { - type: ERIS_CONSTANTS.ApplicationCommandOptionTypes.STRING, - name: 'Member Unbanned', - value: 'guildBanRemove' - }, - { - type: ERIS_CONSTANTS.ApplicationCommandOptionTypes.STRING, - name: 'Role Create', - value: 'guildRoleCreate' - }, - { - type: ERIS_CONSTANTS.ApplicationCommandOptionTypes.STRING, - name: 'Role Delete', - value: 'guildRoleDelete' - }, - { - type: ERIS_CONSTANTS.ApplicationCommandOptionTypes.STRING, - name: 'Role Update', - value: 'guildRoleUpdate' - }, - { - type: ERIS_CONSTANTS.ApplicationCommandOptionTypes.STRING, - name: 'Server Settings Change', - value: 'guildUpdate' - }, - { - type: ERIS_CONSTANTS.ApplicationCommandOptionTypes.STRING, - name: 'Server Emojis Change', - value: 'guildEmojisUpdate' - }, - { - type: ERIS_CONSTANTS.ApplicationCommandOptionTypes.STRING, - name: 'Message Delete', - value: 'messageDelete' - }, - { - type: ERIS_CONSTANTS.ApplicationCommandOptionTypes.STRING, - name: 'Bulk Message Delete', - value: 'messageDeleteBulk' - }, - { - type: ERIS_CONSTANTS.ApplicationCommandOptionTypes.STRING, - name: 'Message Edit', - value: 'messageUpdate' - }, - { - type: ERIS_CONSTANTS.ApplicationCommandOptionTypes.STRING, - name: 'Member Join', - value: 'guildMemberAdd' - }, - { - type: ERIS_CONSTANTS.ApplicationCommandOptionTypes.STRING, - name: 'Member Kick', - value: 'guildMemberKick' - }, - { - type: ERIS_CONSTANTS.ApplicationCommandOptionTypes.STRING, - name: 'Member Leave', - value: 'guildMemberRemove' - }, - { - type: ERIS_CONSTANTS.ApplicationCommandOptionTypes.STRING, - name: 'Member Nickname Update', - value: 'guildMemberNickUpdate' - }, - { - type: ERIS_CONSTANTS.ApplicationCommandOptionTypes.STRING, - name: 'Member Role Add/Remove', - value: 'guildMemberUpdate' - }, - { - type: ERIS_CONSTANTS.ApplicationCommandOptionTypes.STRING, - name: 'Member Gate Verify', - value: 'guildMemberVerify' - }, - { - type: ERIS_CONSTANTS.ApplicationCommandOptionTypes.STRING, - name: 'Voice Channel Leave', - value: 'voiceChannelLeave' - }, - { - type: ERIS_CONSTANTS.ApplicationCommandOptionTypes.STRING, - name: 'Voice Channel Join', - value: 'voiceChannelJoin' - }, - { - type: ERIS_CONSTANTS.ApplicationCommandOptionTypes.STRING, - name: 'Voice Channel Moved', - value: 'voiceChannelSwitch' - }, - { - type: ERIS_CONSTANTS.ApplicationCommandOptionTypes.STRING, - name: 'Member Voice Muted/Deafened', - value: 'voiceStateUpdate' - } - ] - }, - { - type: ERIS_CONSTANTS.ApplicationCommandOptionTypes.STRING, - name: 'guide', - description: 'Get information on how to set the bot up', - choices: [ - { - type: ERIS_CONSTANTS.ApplicationCommandOptionTypes.STRING, - name: 'Usage', - value: 'usage' - } - ] - } - ] - } - ] try { if (suffix === 'guild') { await global.bot.bulkEditGuildCommands(message.channel.guild.id, commands)