1
0
Fork 0
llama-bot/bot/cogs/_logging.py

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))