[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/DigitalPulseSoftware/NotaBot/master/module_prune.lua [Back]  [Original]

-- Copyright (C) 2023 Mjllnir#3515
-- This file is part of the "Not a Bot" application
-- For conditions of distribution and use, see copyright notice in LICENSE

-- API limitations on bulk deletion:
-- It is not possible to delete less than 2 messages or more than 100 messages at a time
-- It is not possible to delete messages older than 14 days
-- getMessagesBefore and getMessagesAfter have also a limitation to 100 messages at a time

local Date = Discordia.Date
local Enums = Discordia.enums

local MSG_TIME_LIMIT    = 1209600 -- seconds
local NB_MSG_MAX_LIMIT  = 100

Module.Name = "prune"


local function bulkDeleteChunks(channel, messagesChunks)
	local nbDeletedMessages = 0

	for _, chunk in ipairs(messagesChunks) do
		if #chunk > 1 then
			channel:bulkDelete(chunk)
			nbDeletedMessages = nbDeletedMessages + #chunk
		else
			chunk[1]:delete()
			nbDeletedMessages = nbDeletedMessages + 1
		end
	end

	return nbDeletedMessages
end

local function hasValidDate(message)
	local messageTimestamp = Date.fromSnowflake(message.id):toSeconds()
	return os.difftime(os.time(), messageTimestamp) < MSG_TIME_LIMIT
end

local function hasManagePermission(member)
	return member:hasPermission(Enums.permission.manageMessages)
end

function Module:bulkDeleteByNumber(commandMessage, nbMessages)
	local channel = commandMessage.channel
	local currentMessageId = commandMessage.id

	local messagesToDelete = {}
	local quotient = math.floor(nbMessages / NB_MSG_MAX_LIMIT)
	local remainder = nbMessages - quotient * NB_MSG_MAX_LIMIT
	for _ = 1, quotient do
		local messages = channel:getMessagesBefore(currentMessageId, NB_MSG_MAX_LIMIT):toArray("id", hasValidDate)

		if next(messages) ~= nil then
			table.insert(messagesToDelete, messages)
			currentMessageId = messages[1].id
		end
	end

	if remainder > 0 then
		table.insert(messagesToDelete, channel:getMessagesBefore(currentMessageId, remainder):toArray("id", hasValidDate))
	end

	return bulkDeleteChunks(channel, messagesToDelete)
end

function Module:bulkDeleteById(commandMessage, targetMessage)
	local channel = commandMessage.channel
	local currentMessageId = targetMessage.id

	local messagesToDelete = {}
	local messages
	repeat
		messages = channel:getMessagesAfter(currentMessageId, NB_MSG_MAX_LIMIT):toArray("id", hasValidDate)
		if next(messages) ~= nil then
			table.insert(messagesToDelete, messages)
			currentMessageId = messages[#messages].id
		end
	until next(messages) == nil

	-- This command is silent so we don't have to remove the command message here
	table.remove(messagesToDelete[#messagesToDelete], #messagesToDelete[#messagesToDelete])

	-- Delete also the selected message
	if hasValidDate(targetMessage) then
		table.insert(messagesToDelete[#messagesToDelete], targetMessage)
	end

	return bulkDeleteChunks(channel, messagesToDelete)
end

function Module:OnLoaded()
	self:RegisterCommand({
		Name = "prune",
		Args = {
			{ Name = "", Type = Bot.ConfigType.Integer }
		},
		PrivilegeCheck = hasManagePermission,
		Help = function (guild) return Bot:Format(guild, "PRUNE_HELP") end,
		Silent = true,
		Func = function (commandMessage, nbMessages)
			local guild = commandMessage.guild

			local nbDeletedMessages = self:bulkDeleteByNumber(commandMessage, nbMessages)
			local response = "";
			if nbDeletedMessages ~= nbMessages then
				response = string.format("%s\n", Bot:Format(guild, "PRUNE_CANNOT_DELETE"))
			end
			response = response .. Bot:Format(guild, "PRUNE_RESULT", nbDeletedMessages)

			return commandMessage:reply(response)
		end
	})

	self:RegisterCommand({
		Name = "prunefrom",
		Args = {
			{ Name = "", Type = Bot.ConfigType.Message }
		},
		PrivilegeCheck = hasManagePermission,
		Help = function (guild) return Bot:Format(guild, "PRUNEFROM_HELP") end,
		Silent = true,
		Func = function (commandMessage, targetMessage)
			local guild = commandMessage.guild
			local nbDeletedMessages = self:bulkDeleteById(commandMessage, targetMessage)

			local response = "";
			if not hasValidDate(targetMessage) then
				response = string.format("%s\n", Bot:Format(guild, "PRUNE_CANNOT_DELETE"))
			end

			response = response .. Bot:Format(guild, "PRUNE_RESULT", nbDeletedMessages)

			return commandMessage:reply(response)
		end
	})

	return true
end

Web Proxy Viewer  |  New URL  |  Original Page