195 lines
7.2 KiB
Python
195 lines
7.2 KiB
Python
from llama import Llama
|
|
from . import _util as util
|
|
|
|
import discord
|
|
from discord.ext import commands
|
|
|
|
import datetime
|
|
|
|
|
|
class Logging(commands.Cog):
|
|
def __init__(self, bot):
|
|
self.bot: Llama = bot
|
|
|
|
self.log_edit = True
|
|
self.remember_how_many = 3 # how many messages it will remember
|
|
|
|
# {CHANNEL_ID: [MSG_UPDATE, ...], ..}
|
|
self.edits: dict[int, list[discord.RawMessageUpdateEvent]] = dict()
|
|
# {CHANNEL_ID: [[DELETE_TIME, MSG_DELETE], ...], ...}
|
|
self.deletes: dict[
|
|
int, list[list[datetime.datetime, discord.RawMessageDeleteEvent]]
|
|
] = dict()
|
|
# {CHANNEL_ID: [[DELETE_TIME, MSG_BULK_DELETE], ...], ...}
|
|
self.bulk_deletes: dict[
|
|
int, list[list[datetime.datetime, discord.RawBulkMessageDeleteEvent]]
|
|
] = dict()
|
|
# {AUTHOR_ID: {CHANNEL_ID: [MSG_UPDATE, ...], ...}, ...}
|
|
|
|
# {AUTHOR_ID: {CHANNEL_ID: [MSG_UPDATE, ...], ...}, ...}
|
|
self.edits_per_user: dict[
|
|
int, dict[int, list[discord.RawMessageUpdateEvent]]
|
|
] = dict()
|
|
# {AUTHOR_ID: {CHANNEL_ID: [MSG_DELETE, ...], ...}, ...}
|
|
self.deletes_per_user: dict[
|
|
int, dict[int, list[discord.RawMessageDeleteEvent]]
|
|
] = dict()
|
|
|
|
async def cog_check(self, ctx: commands.Context):
|
|
if exception_or_bool := await util.on_pm(ctx.message, self.bot):
|
|
raise exception_or_bool
|
|
return not exception_or_bool
|
|
|
|
@commands.Cog.listener()
|
|
async def on_raw_message_edit(self, payload: discord.RawMessageUpdateEvent):
|
|
# channel level
|
|
if payload.channel_id not in self.edits.keys():
|
|
self.edits[payload.channel_id] = []
|
|
|
|
self.edits[payload.channel_id].append(payload)
|
|
|
|
if len(self.edits[payload.channel_id]) > self.remember_how_many:
|
|
del self.edits[payload.channel_id][0]
|
|
|
|
# user level
|
|
try:
|
|
author_id: int = int(payload.data["author"]["id"])
|
|
except KeyError:
|
|
return
|
|
|
|
if author_id not in self.edits_per_user.keys():
|
|
self.edits_per_user[author_id] = dict()
|
|
|
|
if payload.channel_id not in self.edits_per_user[author_id].keys():
|
|
self.edits_per_user[author_id][payload.channel_id] = []
|
|
|
|
self.edits_per_user[author_id][payload.channel_id].append(payload)
|
|
|
|
if (
|
|
len(self.edits_per_user[author_id][payload.channel_id])
|
|
> self.remember_how_many
|
|
):
|
|
# todo: queue task to prevent timing issue causing the deletion of the same message
|
|
del self.edits_per_user[author_id][payload.channel_id][0]
|
|
|
|
@commands.Cog.listener()
|
|
async def on_raw_message_delete(self, payload: discord.RawMessageDeleteEvent):
|
|
# channel level
|
|
if payload.channel_id not in self.deletes.keys():
|
|
self.deletes[payload.channel_id] = []
|
|
|
|
self.deletes[payload.channel_id].append([datetime.datetime.utcnow(), payload])
|
|
|
|
if len(self.deletes[payload.channel_id]) > self.remember_how_many:
|
|
del self.deletes[payload.channel_id][0]
|
|
|
|
# user level
|
|
if payload.cached_message:
|
|
author_id = payload.cached_message.author.id
|
|
if author_id not in self.deletes_per_user.keys():
|
|
self.deletes_per_user[author_id] = dict()
|
|
|
|
if payload.channel_id not in self.deletes_per_user[author_id].keys():
|
|
self.deletes_per_user[author_id][payload.channel_id] = []
|
|
|
|
self.deletes_per_user[author_id][payload.channel_id].append(payload)
|
|
|
|
if (
|
|
len(self.deletes_per_user[author_id][payload.channel_id])
|
|
> self.remember_how_many
|
|
):
|
|
# todo: queue task to prevent timing issue causing the deletion of the same message
|
|
del self.deletes_per_user[author_id][payload.channel_id][0]
|
|
|
|
@commands.Cog.listener()
|
|
async def on_raw_bulk_message_delete(
|
|
self, payload: discord.RawBulkMessageDeleteEvent
|
|
):
|
|
if payload.channel_id not in self.bulk_deletes.keys():
|
|
self.bulk_deletes[payload.channel_id] = []
|
|
|
|
self.bulk_deletes[payload.channel_id].append(
|
|
[datetime.datetime.utcnow(), payload]
|
|
)
|
|
|
|
if len(self.bulk_deletes[payload.channel_id]) > self.remember_how_many:
|
|
del self.bulk_deletes[0]
|
|
|
|
async def log_edit(
|
|
self, channel: discord.TextChannel, payload: discord.RawMessageUpdateEvent
|
|
):
|
|
await channel.send(
|
|
embed=discord.Embed(
|
|
title="Message Edited",
|
|
description=f"""**@<PLAYER> Edited their message in: <#CHANNEL>
|
|
[jump to message](URL)**""",
|
|
)
|
|
.add_field(
|
|
name="before", value=payload.cached_message.content, inline=False
|
|
)
|
|
.add_field(name="after", value=payload.data["content"], inline=False)
|
|
)
|
|
|
|
async def log_delete(
|
|
self, channel: discord.TextChannel, payload: discord.RawMessageDeleteEvent
|
|
):
|
|
await channel.send(embed=discord.Embed(title="Message Deleted", description=""))
|
|
|
|
async def log_bulk_delete(
|
|
self, channel: discord.TextChannel, payload: discord.RawBulkMessageDeleteEvent
|
|
):
|
|
await channel.send(
|
|
embed=discord.Embed(title="Bulk Message Deletion", description="")
|
|
)
|
|
|
|
|
|
'''
|
|
@commands.command(
|
|
help="Shows recently deleted messages and its content. Memory does NOT get wiped after some time.",
|
|
usage="""> {prefix}{command} {?depth}
|
|
Use it after someone deleted their message.
|
|
|
|
Show most recently deleted message
|
|
> {prefix}{command}
|
|
|
|
Show second most recently deleted message
|
|
> {prefix}{command} 2"""
|
|
)
|
|
async def snipe(self, ctx, depth=1):
|
|
if not self.last_del_message:
|
|
await ctx.send(f"There's no message deleted since last reboot!")
|
|
return
|
|
|
|
author = self.last_del_message.author
|
|
await ctx.send(
|
|
embed=discord.Embed(description=f"**Message deleted in:** <#{self.last_del_message.channel.id}> [Jump to Message]({self.last_del_message.jump_url})")
|
|
.set_thumbnail(url=author.avatar_url)
|
|
.add_field(name="Author", value=f"{author.mention} ({author})", inline=False)
|
|
.add_field(name="Content", value=self.last_del_message.content, inline=False)
|
|
.set_footer(text=f"Deleted at: {self.last_del_time.strftime('%Y-%m-%d %H:%M:%S')} UTC")
|
|
)
|
|
|
|
@commands.command(
|
|
help="Shows most recently edited message and it's content before and after the edit. Memory gets wiped after some time.",
|
|
usage="""> {prefix}{command} {?depth}
|
|
Use it after someone edited their message."""
|
|
)
|
|
async def editsnipe(self, ctx, depth=1):
|
|
if not self.last_edit_after:
|
|
await ctx.send(f"There's no message edited since last reboot!")
|
|
return
|
|
|
|
author = self.last_edit_after.author
|
|
await ctx.send(
|
|
embed=discord.Embed(description=f"**Message Edited in:** <#{self.last_edit_after.channel.id}> [Jump to Message]({self.last_edit_after.jump_url})")
|
|
.set_thumbnail(url=author.avatar_url)
|
|
.add_field(name="Author", value=f"{author.mention} ({author})", inline=False)
|
|
.add_field(name="Before", value=self.last_edit_before.content, inline=False)
|
|
.add_field(name="After", value=self.last_edit_after.content, inline=False)
|
|
.set_footer(text=f"Edited at: {self.last_edit_after.edited_at.strftime('%Y-%m-%d %H:%M:%S')} UTC")
|
|
)
|
|
'''
|
|
|
|
|
|
def setup(bot):
|
|
bot.add_cog(Logging(bot))
|