Files
DiscordBot/cogs/informational.py
T
2025-09-16 15:00:16 +02:00

217 lines
8.5 KiB
Python
Executable File

import discord
import time
from discord.ext import commands
import logging
from datetime import datetime
from utils.sql_commands import DatabaseManager
# --- Localization dictionary (expand as needed) ---
LOCALE = {
"en": {
"afk_set": "{user} has gone afk.{reason}",
"afk_reason": " Reason: {reason}",
"afk_notify": "{user} is currently unavailable.{reason}",
"feedback_received": "Feedback received. Thank you!",
"missing_perms": "⚠️ The bot is missing the following permissions in **{guild}**: {perms}",
}
}
LANG = "en" # Set your language code here
def _(key, **kwargs):
return LOCALE[LANG][key].format(**kwargs)
class Informational(commands.Cog):
def __init__(self, client):
self.client = client
self.db = DatabaseManager()
async def cog_load(self):
# Bot Permissions Check at startup
for guild in self.client.guilds:
me = guild.me
missing = []
if not me.guild_permissions.manage_roles:
missing.append("Manage Roles")
if not me.guild_permissions.manage_nicknames:
missing.append("Manage Nicknames")
if missing:
owner = guild.owner
try:
await owner.send(
_("missing_perms", guild=guild.name, perms=", ".join(missing))
)
except Exception:
logging.warning(
f"Could not DM owner of {guild.name} about missing permissions."
)
@commands.command(name="whois")
async def _userinfo(self, ctx, member: discord.Member = None): # type: ignore
if member is None:
member = ctx.message.author
roles = [role for role in member.roles][1:]
embed = discord.Embed(
colour=discord.Colour.purple(),
timestamp=ctx.message.created_at,
title=f"User Info - {member}",
)
embed.set_thumbnail(url=member.display_avatar)
embed.set_footer(text=f"Requested by {ctx.author}")
embed.add_field(name="ID:", value=member.id)
embed.add_field(name="Display Name:", value=member.display_name)
embed.add_field(
name="Created Account On:",
value=member.created_at.strftime("%a, %#d %B %Y, %I:%M %p UTC"),
)
embed.add_field(
name="Joined Server On:",
value=member.joined_at.strftime("%a, %#d %B %Y, %I:%M %p UTC"), # type: ignore
)
embed.add_field(name="Roles:", value="".join([role.mention for role in roles]))
embed.add_field(name="Highest Role:", value=member.top_role.mention)
await ctx.send(embed=embed)
@commands.command(name="serverInfo")
@commands.has_permissions(view_audit_log=True) # Example permission
async def _server(self, ctx):
embed = discord.Embed(
title=f"{ctx.guild.name} Info",
description="Information of this Server",
color=discord.Colour.blue(),
)
embed.add_field(name="🆔Server ID", value=f"{ctx.guild.id}", inline=True)
embed.add_field(
name="📆Created On",
value=ctx.guild.created_at.strftime("%b %d %Y"),
inline=True,
)
embed.add_field(name="👑Owner", value=f"{ctx.guild.owner.mention}", inline=True)
embed.add_field(
name="👥Members", value=f"{ctx.guild.member_count} Members", inline=True
)
embed.add_field(
name="💬Channels",
value=f"{len(ctx.guild.text_channels)} Text | {len(ctx.guild.voice_channels)} Voice",
inline=True,
)
embed.set_thumbnail(url=ctx.guild.icon)
embed.set_footer(text="⭐ • Duo")
embed.set_author(name=f"{ctx.author.name}", icon_url=ctx.message.author.avatar)
await ctx.send(embed=embed)
@commands.command(name="afk")
@commands.cooldown(1, 10, commands.BucketType.user)
async def _afk(self, ctx, *reason):
afk_reason = " ".join(reason)
timestamp = datetime.utcnow().isoformat()
# Store AFK reason and timestamp in DB
self.db.execute_query(
"REPLACE INTO afk_status (USERID, GUILDID, REASON, TIMESTAMP) VALUES (%s, %s, %s, %s)",
(ctx.author.id, ctx.guild.id, afk_reason, timestamp),
)
msg = _(
"afk_set",
user=ctx.author.mention,
reason=_("afk_reason", reason=afk_reason) if afk_reason else "",
)
await ctx.send(msg)
# Prevent stacking [AFK]
try:
current_nick = ctx.author.nick or ctx.author.name
if "[AFK]" not in current_nick:
await ctx.author.edit(nick=f"{current_nick} [AFK]")
except discord.Forbidden:
logging.warning(f"Missing permissions to edit nickname for {ctx.author}")
except Exception as e:
logging.error(f"Error editing nickname: {e}")
guild = ctx.guild
try:
role = discord.utils.get(ctx.guild.roles, name="AFK")
if not role:
role = await guild.create_role(name="AFK", hoist=True)
all_roles = await guild.fetch_roles()
num_roles = len(all_roles)
await role.edit(reason=None, position=num_roles - 2)
await ctx.author.add_roles(role)
except discord.Forbidden:
logging.warning("Missing permissions to create/add AFK role.")
except Exception as e:
logging.error(f"Error handling AFK role: {e}")
try:
await ctx.message.delete()
except discord.Forbidden:
pass
@commands.command(name="afklist")
async def afk_list(self, ctx):
afks = self.db.fetch_all(
"SELECT USERID, REASON, TIMESTAMP FROM afk_status WHERE GUILDID = %s",
(ctx.guild.id,),
)
if not afks:
await ctx.reply("No one is AFK right now.")
return
lines = []
for afk in afks:
member = ctx.guild.get_member(int(afk["USERID"]))
reason = afk["REASON"] or "No reason given."
timestamp = afk.get("TIMESTAMP")
# Convert timestamp string to datetime
if isinstance(timestamp, str):
try:
timestamp = datetime.fromisoformat(timestamp)
except Exception:
timestamp = None
if timestamp:
duration = datetime.utcnow() - timestamp
duration_str = str(duration).split(".")[0]
else:
duration_str = "unknown duration"
lines.append(
f"{member.mention if member else afk['USERID']} - {reason} (AFK for {duration_str})"
)
await ctx.send("\n".join(lines))
@commands.command(name="feedback")
@commands.cooldown(1, 30, commands.BucketType.user)
async def _feedback(self, ctx, *info):
feedback_text = " ".join(info)
timestamp = datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S")
user = f"{ctx.author} ({ctx.author.id})"
# Store feedback in DB
self.db.execute_query(
"INSERT INTO feedback (USER, GUILDID, TIMESTAMP, CONTENT) VALUES (%s, %s, %s, %s)",
(user, ctx.guild.id if ctx.guild else None, timestamp, feedback_text),
)
await ctx.reply(_("feedback_received"))
@commands.Cog.listener()
async def on_command_error(self, ctx, error):
# Notify admin if permissions are missing
if isinstance(
error, (commands.MissingPermissions, commands.BotMissingPermissions)
):
perms = getattr(error, "missing_perms", None)
perms_str = ", ".join(perms) if perms else "Unknown"
owner = ctx.guild.owner if ctx.guild else None
if owner:
try:
await owner.send(
_("missing_perms", guild=ctx.guild.name, perms=perms_str)
)
except Exception:
logging.warning(
f"Could not DM owner of {ctx.guild.name} about missing permissions."
)
raise error # Let default handler run too
async def setup(client):
await client.add_cog(Informational(client))