Skip to content

Commit

Permalink
Adding admin log inspection
Browse files Browse the repository at this point in the history
  • Loading branch information
rukasudev committed Jan 13, 2025
1 parent c6ad931 commit d5ae8dd
Show file tree
Hide file tree
Showing 6 changed files with 188 additions and 4 deletions.
30 changes: 30 additions & 0 deletions app/cogs/base/log.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import discord
from discord import app_commands

from app import bot
from app.bot import DiscordBot
from app.services.log_inspection import parse_log_message_to_embed
from app.types.cogs import Cog


class Log(Cog):
def __init__(self, bot: DiscordBot) -> None:
self.bot = bot
super().__init__()

async def log_inspection(self, interaction: discord.Interaction, message: discord.Message) -> None:
await parse_log_message_to_embed(interaction, message)


async def setup(bot: DiscordBot) -> None:
log = Log(bot)

context_menu = app_commands.ContextMenu(
name="Log Inspection",
callback=log.log_inspection,
type=discord.AppCommandType.message,
guild_ids=[bot.config.ADMIN_GUILD_ID],
)
bot.tree.add_command(context_menu)

await bot.add_cog(log)
8 changes: 8 additions & 0 deletions app/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@ class Commands:

NOTIFICATIONS_YOUTUBE_VIDEO_KEY: Final[str] = "notifications_youtube_video"

COMMANDS_LIST: Final[List[str]] = [
BLOCK_LINKS_KEY,
DEFAULT_ROLES_KEY,
NOTIFICATIONS_TWITCH_KEY,
NOTIFICATIONS_YOUTUBE_VIDEO_KEY,
WELCOME_MESSAGES_KEY,
]

COMMAND_KEY_TO_COMPOSITION_KEY: Final[Dict[str, str]] = {
NOTIFICATIONS_TWITCH_KEY: NOTIFICATIONS_KEY,
NOTIFICATIONS_YOUTUBE_VIDEO_KEY: NOTIFICATIONS_KEY,
Expand Down
7 changes: 7 additions & 0 deletions app/languages/commands/commands.en-us.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,45 +98,52 @@ en-us:
description: "Command **$command_name** enabled on $date by $user 🚀\n\n
If you want to make changes or disable the command, simply run the command again 🔄"
short-description: ✅ Enabled by $user
short-description-with-cog: ✅ **$cog_name** enabled by $user

paused:
title: ⏸️ Command paused successfully!
key: Paused
action: Pause
description: Command **$command_name** paused on $date by $user
short-description: ⏸️ Paused by $user
short-description-with-cog: ⏸️ **$cog_name** paused by $user

unpaused:
title: ▶️ Command unpaused successfully!
key: Unpaused
action: Unpause
description: Command **$command_name** unpaused on $date by $user
short-description: ▶️ Unpaused by $user
short-description-with-cog: ▶️ **$cog_name** unpaused by $user

disabled:
title: 🚫 Command disabled successfully!
action: Disable
description: Command **$command_name** disabled on $date by $user
short-description: 🚫 Disabled by $user
short-description-with-cog: 🚫 **$cog_name** disabled by $user

edited:
title: 📝 Command edited successfully!
description: Command **$command_name** edited on $date by $user
placeholder: Select the settings you want to edit
short-description: 📝 Edited by $user
short-description-with-cog: 📝 **$cog_name** edited by $user

added:
title: ➕ Item added to **$command_name** successfully!
action: Add
description: A item was added to **$command_name** on $date by $user
short-description: ➕ Item added by $user
short-description-with-cog: ➕ **$cog_name** added by $user

removed:
title: 🗑️ Item removed from **$command_name** successfully!
action: Remove
description: A item was removed from **$command_name** on $date by $user
placeholder: Select the item you want to remove
short-description: 🗑️ Item removed by $user
short-description-with-cog: 🗑️ **$cog_name** removed by $user

system:
description: That is a default action taken by Keiko when leaving the server
Expand Down
27 changes: 27 additions & 0 deletions app/services/log_inspection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import discord

from app import bot
from app.views.log_inspection import LogInspectionView


def get_guild(guild_id: int) -> discord.Guild:
guild = bot.get_guild(int(guild_id))
return guild

def get_user(user_id: int) -> discord.Member:
user = bot.get_user(int(user_id))
return user

async def parse_log_message_to_embed(interaction: discord.Interaction, message: discord.Message) -> discord.Embed:
for item in message.embeds[0].fields:
if item.name == "Guild ID":
guild_id = item.value
elif item.name == "User ID":
user_id = item.value.replace("<@", "").replace(">", "")

guild = get_guild(guild_id)
user = get_user(user_id)

view = LogInspectionView(user, guild)

await view.send(interaction)
11 changes: 7 additions & 4 deletions app/services/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,23 @@


def parse_history_data(
data: List[Dict[str, Any]], interaction: discord.Interaction
data: List[Dict[str, Any]], interaction: discord.Interaction, guild: discord.Guild=None, with_cog: bool = None
) -> Dict[str, Any]:
system_desc = ml(
"commands.command-events.system.description", locale=interaction.locale
)

response = {}
guild = guild or interaction.guild
for item in data:
key = item["datetime"].strftime("%Y-%m-%d %H:%M:%S") + " UTC"
user = interaction.guild.get_member(int(item["user_id"]))
user = guild.get_member(int(item["user_id"]))

command = "short-description" if not with_cog else "short-description-with-cog"
desc = ml(
f"commands.command-events.{item['event']}.short-description",
f"commands.command-events.{item['event']}.{command}",
locale=interaction.locale,
).replace("$user", user.mention)
).replace("$user", user.mention).replace("$cog_name", item["cog_key"])

if user.id == interaction.client.user.id:
desc += f" _({system_desc})_"
Expand Down
109 changes: 109 additions & 0 deletions app/views/log_inspection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import discord

from app import bot
from app.components.buttons import GenericButton, HistoryButton
from app.constants import Commands as constants
from app.data import moderations as moderations_data
from app.services.cogs import find_cog_events_by_guild
from app.services.manager import parse_history_data
from app.services.utils import ml
from app.views.pagination import PaginationView


class LogInspectionView(discord.ui.View):
def __init__(self, user: discord.User, guild: discord.Guild):
self.user = user
self.guild = guild
self.actual_page = 0
super().__init__(timeout=None)
self.add_item(GenericButton("Next", self.callback, style=discord.ButtonStyle.primary))

async def get_user_info_embed(self) -> discord.Embed:
embed = discord.Embed(
title=self.user.name,
description=f"User ID: {self.user.id}",
color=discord.Color.green(),
)

embed.add_field(name="Display Name", value=self.user.display_name, inline=False)
embed.add_field(name="Date Created", value=self.parse_if_time(self.user.created_at), inline=False)
embed.set_thumbnail(url=self.user.avatar.url)

return embed

async def get_guild_info_embed(self) -> discord.Embed:
embed = discord.Embed(
title=self.guild.name,
color=discord.Color.green(),
)

embed.add_field(name="guild_id", value=self.guild.id, inline=False)
embed.add_field(name="guild_created_at", value=self.parse_if_time(self.guild.created_at), inline=False)

moderations = moderations_data.find_moderations_by_guild(self.guild.id)
for key, value in moderations.items():
if not value:
continue

if key == "created_at":
key = "added_at"

if key in ["guild_id", "_id"]:
continue

embed.add_field(name=key, value=self.parse_if_time(value), inline=False)


integrations = await self.guild.integrations()
for integration in integrations:
if not isinstance(integration, discord.BotIntegration):
continue

if not integration.application.user.name == bot.user.name:
continue

bot_inviter = integration.user
embed.add_field(name="invited_by", value=bot_inviter.name)

embed.set_thumbnail(url=self.guild.icon.url)

return embed

async def history_callback(self, interaction: discord.Interaction):
raw_data = []

for cog_key in constants.COMMANDS_LIST:
raw_data += find_cog_events_by_guild(self.guild.id, cog_key)

data = parse_history_data(raw_data, interaction, with_cog=True)

title = ml("buttons.changes-history.label", locale=interaction.locale)
pagination_view = PaginationView(interaction, title, "", data, sep=4)

await pagination_view.send(ephemeral=True)

def parse_if_time(self, value):
try:
return value.strftime("%Y-%m-%d %H:%M:%S")
except AttributeError:
return value

async def send(self, interaction: discord.Interaction):
embed = await self.get_user_info_embed()
await interaction.response.send_message(embed=embed, view=self, ephemeral=True)

async def callback(self, interaction: discord.Interaction):
self.interaction = interaction

page_index_to_embed = {
0: self.get_user_info_embed,
1: self.get_guild_info_embed,
}
self.actual_page = (self.actual_page + 1) % len(page_index_to_embed)
if self.actual_page == 1:
self.add_item(HistoryButton(callback=self.history_callback, locale=interaction.locale))

new_embed = await page_index_to_embed[self.actual_page]()

await interaction.response.edit_message(embed=new_embed, view=self)

0 comments on commit d5ae8dd

Please sign in to comment.