diff --git a/cogs/events.py b/cogs/events.py index 7e95bb9..b1ff4b6 100644 --- a/cogs/events.py +++ b/cogs/events.py @@ -1,4 +1,5 @@ from data import constants +from data.snipe import Snipe, Action import datetime import discord from discord.ext import commands @@ -6,14 +7,15 @@ from functions import checks, easterEggResponses from functions.database import stats, muttn, custom_commands, commands as command_stats import pytz from settings import READY_MESSAGE, SANDBOX, STATUS_MESSAGE +from startup.didier import Didier import time import traceback class Events(commands.Cog): - def __init__(self, client): - self.client = client + def __init__(self, client: Didier): + self.client: Didier = client self.utilsCog = self.client.get_cog("Utils") self.failedChecksCog = self.client.get_cog("FailedChecks") self.lastFeatureRequest = 0 @@ -263,7 +265,7 @@ class Events(commands.Cog): await msg.add_reaction("✅") @commands.Cog.listener() - async def on_message_edit(self, before, after): + async def on_message_edit(self, before: discord.Message, after: discord.Message): """ Function called when a message is edited, so people can't edit messages in FreeGames to cheat the system. @@ -272,7 +274,17 @@ class Events(commands.Cog): """ # Run the message through the checks again if not checks.freeGamesCheck(after): - await self.failedChecksCog.freeGames(after) + return await self.failedChecksCog.freeGames(after) + + if before.guild is not None and not before.author.bot: + self.client.snipe[before.channel.id] = Snipe(before.author.id, before.channel.id, before.guild.id, Action.Edit, + before.content, after.content) + + @commands.Cog.listener() + async def on_message_delete(self, message: discord.Message): + if message.guild is not None and not message.author.bot: + self.client.snipe[message.channel.id] = Snipe(message.author.id, message.channel.id, message.guild.id, + Action.Remove, message.content) async def sendErrorEmbed(self, ctx, error: Exception, trace): """ diff --git a/cogs/other.py b/cogs/other.py index 3e0bfd7..0c62b8d 100644 --- a/cogs/other.py +++ b/cogs/other.py @@ -1,18 +1,23 @@ from discord.ext import commands + +from data.embeds.snipe import EditSnipe, DeleteSnipe from data.menus import custom_commands +from data.snipe import Action, Snipe from decorators import help from enums.help_categories import Category from functions.database.custom_commands import get_all from functions.stringFormatters import capitalize +from startup.didier import Didier class Other(commands.Cog): - def __init__(self, client): - self.client = client + def __init__(self, client: Didier): + self.client: Didier = client - # Don't allow any commands to work when locked - def cog_check(self, ctx): - return not self.client.locked + # TODO add locked field to Didier instead of client + # # Don't allow any commands to work when locked + # def cog_check(self, ctx): + # return not self.client.locked @commands.command(name="Custom") @help.Category(category=Category.Didier) @@ -25,6 +30,25 @@ class Other(commands.Cog): src = custom_commands.CommandsList(formatted) await custom_commands.Pages(source=src, clear_reactions_after=True).start(ctx) + @commands.command(name="Snipe") + @help.Category(category=Category.Other) + async def snipe(self, ctx): + """ + Shame people for editing & removing messages. + The dict is stored in memory so it will be cleared whenever the bot restarts. + """ + if ctx.guild is None: + return + + if ctx.channel.id not in self.client.snipe: + return await ctx.send("Er is hier niemand om uit te lachen.") + + s: Snipe = self.client.snipe[ctx.channel.id] + + embed_class = (EditSnipe(s) if s.action == Action.Edit else DeleteSnipe(s)) + + return await ctx.send(embed=embed_class.to_embed(self.client)) + def setup(client): client.add_cog(Other(client)) diff --git a/data/embeds/snipe.py b/data/embeds/snipe.py new file mode 100644 index 0000000..9e03474 --- /dev/null +++ b/data/embeds/snipe.py @@ -0,0 +1,40 @@ +from data.snipe import Snipe +import discord +from startup.didier import Didier + + +class EditSnipe: + """ + Creates an Embed to snipe people that edited a message + """ + def __init__(self, snipe: Snipe): + self.snipe = snipe + + def to_embed(self, client: Didier) -> discord.Embed: + guild: discord.Guild = client.get_guild(self.snipe.guild) + member: discord.Member = guild.get_member(self.snipe.user) + + embed = discord.Embed(title="Edit Snipe", colour=discord.Colour.blue()) + embed.set_author(name=member.display_name, icon_url=member.avatar_url) + embed.add_field(name="Voor", value=self.snipe.old, inline=False) + embed.add_field(name="Na", value=self.snipe.new, inline=False) + + return embed + + +class DeleteSnipe: + """ + Creates an Embed to snipe people that removed a message + """ + def __init__(self, snipe: Snipe): + self.snipe = snipe + + def to_embed(self, client: Didier) -> discord.Embed: + guild: discord.Guild = client.get_guild(self.snipe.guild) + member: discord.Member = guild.get_member(self.snipe.user) + + embed = discord.Embed(title="Delete Snipe", colour=discord.Colour.blue()) + embed.set_author(name=member.display_name, icon_url=member.avatar_url) + embed.add_field(name="Message", value=self.snipe.old) + + return embed diff --git a/data/snipe.py b/data/snipe.py new file mode 100644 index 0000000..41b7b22 --- /dev/null +++ b/data/snipe.py @@ -0,0 +1,24 @@ +from enum import Enum + +from attr import dataclass + + +class Action(Enum): + """ + Enum to indicate what action was performed by the user + """ + Edit = 0 + Remove = 1 + + +@dataclass +class Snipe: + """ + Dataclass to store Snipe info + """ + user: int + channel: int + guild: int + action: Action + old: str + new: str = None diff --git a/files/help.json b/files/help.json index b099ac3..058ba7e 100644 --- a/files/help.json +++ b/files/help.json @@ -103,6 +103,7 @@ "sell": "Verkoop [Aantal] van [Item id]. Je krijgt maar 80% van je aankoop terugbetaald.", "slots": "Speel met een Gokautomaat.", "slots chart": "Bekijk de winstverdeling van Didier Slots.", + "snipe": "Lach mensen uit die messages editen en removen.", "stalin": "Stuurt een motivational quote van Stalin.", "stats": "Bekijk de verhoudingen voor jouw gekozen categorie.\nIndien je geen categorie opgeeft, krijg je je persoonlijke stats.", "stats channels": "Bekijk de stats van [Channel].\nIndien je geen channel opgeeft, krijg je een lijst van alle channels in deze server.", diff --git a/startup/didier.py b/startup/didier.py index 9cd9874..90ddef7 100644 --- a/startup/didier.py +++ b/startup/didier.py @@ -1,13 +1,19 @@ +from data.snipe import Snipe from discord.ext import commands, ipc +import os from settings import HOST_IPC from startup.init_files import check_all -import os +from typing import Dict class Didier(commands.Bot): """ Main Bot class for Didier """ + + # Dict to store the most recent Snipe info per channel + snipe: Dict[int, Snipe] = {} + def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs)