diff --git a/locales/de.json b/locales/de.json index 0c28eff4..04c2668e 100644 --- a/locales/de.json +++ b/locales/de.json @@ -298,7 +298,8 @@ "manage-suggestion-comment-description": "Erkläre, warum du diese Entscheidung getroffen hast" }, "auto-delete": { - "could-not-fetch-channel": "Der Kanal mit der ID %c konnte nicht gefunden werden" + "could-not-fetch-channel": "Der Kanal mit der ID %c konnte nicht gefunden werden", + "could-not-fetch-messages": "Die Nachrichten im Kanal mit der ID %c konnten nicht gefunden werden" }, "auto-thread": { "thread-create-reason": "Dieser Thread wurde aufgrund der Einstellungen von auto-thread erstellt" diff --git a/locales/en.json b/locales/en.json index 1b557936..48b54b61 100644 --- a/locales/en.json +++ b/locales/en.json @@ -301,7 +301,8 @@ "manage-suggestion-comment-description": "Explain why you made this choice" }, "auto-delete": { - "could-not-fetch-channel": "Could not fetch channel with ID %c" + "could-not-fetch-channel": "Could not fetch channel with ID %c", + "could-not-fetch-messages": "Could not fetch messages from channel with ID %c" }, "auto-thread": { "thread-create-reason": "This thread got created, because you configured auto-thread to do so" diff --git a/modules/auto-delete/channels.json b/modules/auto-delete/channels.json index f3bbb70c..03f18858 100644 --- a/modules/auto-delete/channels.json +++ b/modules/auto-delete/channels.json @@ -8,19 +8,28 @@ "field_name": "channelID", "default": "", "type": "channelID", - "description": "ID of the (text) channel" + "humanname-de": "Sprachkanal", + "humanname-en": "Voice-Channel", + "description-en": "The Voice-Channel you want the auto-deleter to clear if there are no channel members left.", + "description-de": "Wähle den Sprachkanal aus, den der Bot leeren soll, sobald keine Mitglieder mehr im Sprachkanal sind." }, { "field_name": "timeout", "default": "5", "type": "integer", - "description": "Timeout after which messages sent (if not pinned) in this channel get deleted automatically (in minutes, at least 2 minutes)" + "humanname-de": "Timeout", + "humanname-en": "Timeout", + "description-en": "Timeout (in minutes) after which the messages in a channel will be deleted.", + "description-de": "Timeout (in Minuten), nachdem die Nachrichten in einem Kanal automatisch gelöscht werden sollen." }, { "field_name": "purgeOnStart", "default": false, "type": "boolean", - "description": "If enabled every (excluding pinned) message (max 100) in this channel gets deleted when the bot starts" + "humanname-de": "Kanal leeren beim Bot Start", + "humanname-en": "Purge On Start", + "description-en": "If enabled every (excluding pinned) message (max 100) in this channel gets deleted when the bot starts.", + "description-de": "Wenn aktiviert, werden alle (außer angepinnte) Nachrichten (max 100) aus dem gewälten Kanal, beim Start des Bots, gelöscht." } ] } \ No newline at end of file diff --git a/modules/auto-delete/events/botReady.js b/modules/auto-delete/events/botReady.js index b1b5e282..3a4c6761 100644 --- a/modules/auto-delete/events/botReady.js +++ b/modules/auto-delete/events/botReady.js @@ -1,11 +1,60 @@ const {localize} = require('../../../src/functions/localize'); module.exports.run = async function (client) { const channels = client.configurations['auto-delete']['channels']; - for (const channel of channels) { + const voiceChannels = client.configurations['auto-delete']['voice-channels']; + + const uniqueConfigChannels = findUniqueChannels(channels); + const uniqueConfigVoiceChannels = findUniqueChannels(voiceChannels); + + client.modules['auto-delete'].uniqueChannels = uniqueConfigChannels.filter((channel) => { + const channelConfigObject = uniqueConfigVoiceChannels.find((voiceChannel) => voiceChannel.channelID === channel.channelID); + return !channelConfigObject; + }); + + for (const channel of client.modules['auto-delete'].uniqueChannels) { if (!channel.purgeOnStart) continue; - const dcChannel = await client.channels.fetch(channel.channelID).catch(() => { - }); + + const dcChannel = await client.channels.fetch(channel.channelID).catch(() => {}); if (!dcChannel) return client.logger.error(`[auto-delete] ${localize('auto-delete', 'could-not-fetch-channel', {c: channel.channelID})}`); - dcChannel.bulkDelete((await dcChannel.messages.fetch()).filter(m => !m.pinned && m.deletable), true); + + const channelMessages = await dcChannel.messages.fetch().catch(() => {}); + if (!channelMessages) { + return client.logger.error(`[auto-delete] ${localize('auto-delete', 'could-not-fetch-messages', {c: channel.channelID})}`); + } + if (channelMessages.size === 0) continue; + + dcChannel.bulkDelete(channelMessages.filter(m => !m.pinned && m.deletable), true); } -}; \ No newline at end of file + + for (const voiceChannel of uniqueConfigVoiceChannels) { + if (!voiceChannel.purgeOnStart) continue; + + const dcVoiceChannel = await client.channels.fetch(voiceChannel.channelID).catch(() => {}); + if (!dcVoiceChannel) return client.logger.error(`[auto-delete] ${localize('auto-delete', 'could-not-fetch-channel', {c: voiceChannel.channelID})}`); + if (dcVoiceChannel.members.size > 0) continue; + + const channelMessages = await dcVoiceChannel.messages.fetch().catch(() => {}); + if (!channelMessages) { + return client.logger.error(`[auto-delete] ${localize('auto-delete', 'could-not-fetch-messages', {c: voiceChannel.channelID})}`); + } + if (channelMessages.size === 0) continue; + + dcVoiceChannel.bulkDelete(channelMessages, true); + } +}; + +/** + * Finds and deletes duplicates in Array (Last Writer wins) + * @param {String} arrayToFilter Array of Channels + * @returns {Array} Filtered Array of Channels + * @private + */ +function findUniqueChannels(arrayToFilter) { + const uniqueConfigChannelIds = {}; + + for (let i = 0; i < arrayToFilter.length; i++) { + uniqueConfigChannelIds[arrayToFilter[i].channelID] = i; + } + + return arrayToFilter.filter((channel, index) => uniqueConfigChannelIds[channel.channelID] === index); +} \ No newline at end of file diff --git a/modules/auto-delete/events/messageCreate.js b/modules/auto-delete/events/messageCreate.js index 46a4f2d5..563db3a9 100644 --- a/modules/auto-delete/events/messageCreate.js +++ b/modules/auto-delete/events/messageCreate.js @@ -3,9 +3,9 @@ module.exports.run = async function (client, msg) { if (!msg.guild) return; if (msg.guild.id !== client.guildID) return; if (!msg.member) return; + if (!client.modules['auto-delete'].uniqueChannels) return; - const channels = client.configurations['auto-delete']['channels']; - const channel = channels.find(c => c.channelID === msg.channel.id); + const channel = client.modules['auto-delete'].uniqueChannels.find(c => c.channelID === msg.channel.id); if (!channel) return; setTimeout(() => { if (msg.deletable && !msg.pinned) msg.delete().catch(() => { diff --git a/modules/auto-delete/events/voiceStateUpdate.js b/modules/auto-delete/events/voiceStateUpdate.js new file mode 100644 index 00000000..aa9dcfbf --- /dev/null +++ b/modules/auto-delete/events/voiceStateUpdate.js @@ -0,0 +1,26 @@ +const {localize} = require('../../../src/functions/localize'); +module.exports.run = async function (client, oldState) { + if (!client.botReadyAt) return; + + const voiceChannels = client.configurations['auto-delete']['voice-channels']; + + const channelConfigEntry = voiceChannels.find((vc) => oldState.channelId === vc.channelID); + if (!channelConfigEntry) return; + + const channel = await client.channels.fetch(channelConfigEntry.channelID).catch(() => {}); + if (!channel) { + return client.logger.error(`[auto-delete] ${localize('auto-delete', 'could-not-fetch-channel', {c: channelConfigEntry.channelID})}`); + } + if (channel.type !== 'GUILD_VOICE') return; + if (channel.members.size > 0) return; + + const channelMessages = await channel.messages.fetch().catch(() => {}); + if (!channelMessages) { + return client.logger.error(`[auto-delete] ${localize('auto-delete', 'could-not-fetch-messages', {c: channelConfigEntry.channelID})}`); + } + if (channelMessages.size === 0) return; + + setTimeout(async() => { + channel.bulkDelete(channelMessages, true).catch(() => {}); + }, parseInt(channelConfigEntry.timeout) * 1000 * 60); +}; \ No newline at end of file diff --git a/modules/auto-delete/module.json b/modules/auto-delete/module.json index 4d1d7f1c..2ce07a5f 100644 --- a/modules/auto-delete/module.json +++ b/modules/auto-delete/module.json @@ -2,7 +2,7 @@ "name": "auto-delete", "humanReadableName-en": "Auto-Message-Delete", "humanReadableName-de": "Automatisches Löschen", - "description-en": "This module allows you to delete messages in a channel after a specified timeout to keep your channel clean", + "description-en": "This module allows you to delete messages from a channel after a specified timeout to keep your channel clean", "description-de": "Halte deine Channel sauber, in dem du alle Nachrichten nach einem bestimmten Intervall in einem Channel löschst", "author": { "scnxOrgID": "1", @@ -13,7 +13,8 @@ "openSourceURL": "https://github.com/SCNetwork/CustomDCBot/tree/main/modules/auto-delete", "events-dir": "/events", "config-example-files": [ - "channels.json" + "channels.json", + "voice-channels.json" ], "tags": [ "administration" diff --git a/modules/auto-delete/voice-channels.json b/modules/auto-delete/voice-channels.json new file mode 100644 index 00000000..56dbb054 --- /dev/null +++ b/modules/auto-delete/voice-channels.json @@ -0,0 +1,36 @@ +{ + "filename": "voice-channels.json", + "humanname-de": "Voice-Channel", + "humanname-en": "Voice-Channels", + "configElements": true, + "content": [ + { + "field_name": "channelID", + "default": "", + "type": "channelID", + "content": "GUILD_VOICE", + "humanname-de": "Sprachkanal", + "humanname-en": "Voice-Channel", + "description-en": "The Voice-Channel you want the auto-deleter to clear if there are no channel members left.", + "description-de": "Wähle den Sprachkanal aus, den der Bot leeren soll, sobald keine Mitglieder mehr im Sprachkanal sind." + }, + { + "field_name": "timeout", + "default": "5", + "type": "integer", + "humanname-de": "Timeout", + "humanname-en": "Timeout", + "description-en": "Timeout (in minutes) after which the messages in a Voice-Channel are deleted after the last member left the channel. Entering '0' will result in an instant deletion.", + "description-de": "Timeout (in Minuten), nachdem die Nachrichten gelöscht werden, wenn das letzte Mitglied den Sprachkanal verlassen hat. Wenn du eine '0' verwendest, werden die Nachrichten sofort gelöscht." + }, + { + "field_name": "purgeOnStart", + "default": false, + "type": "boolean", + "humanname-de": "Kanal leeren beim Bot Start", + "humanname-en": "Purge On Start", + "description-en": "If enabled every message (max 100) in this channel gets deleted when the bot starts and no members are left in the channel", + "description-de": "Wenn aktiviert, werden alle Nachrichten (max 100) aus dem gewälten Sprachkanal gelöscht (beim Start des Bots), sofern keine Mitglieder in dem Sprachkanal sind." + } + ] +} \ No newline at end of file