feat(bot): Everything.

This commit is contained in:
Nyeki.py
2024-10-16 13:21:04 -03:00
parent 3059ec8446
commit 5011ab5f90
34 changed files with 3444 additions and 39 deletions
+210
View File
@@ -0,0 +1,210 @@
from datetime import datetime, timezone
import discord
from discord import errors
from discord.ext import commands
from tortoise import transactions
from payphone import bot
from payphone.db import models, utils
from payphone.cogs import base
from payphone.cogs.mods import embeds, views
from payphone.core import checks, converters, constants
class Mods(base.Cog):
show_in_help = False
def __init__(self, bot_instance: bot.Payphone):
self.bot = bot_instance
@commands.command(extras={"reply_argument": "user"})
@checks.is_moderator()
@transactions.atomic()
async def ban(
self,
ctx: commands.Context,
user: discord.User | discord.Member | converters.DiscordUser,
time: converters.Timedelta | None = None,
*,
reason: str | None = "",
) -> None:
"""
Ban a user by their ID, pinging them, or replying to their message.
Options:
- `<user>`: The user to ban or their ID.
- `[<time>]`: The amount of time to ban the user for. For example, `1d 5h`.
- `[<reason>]`: The reason of their ban.
"""
user_id = None
if isinstance(user, (discord.User, discord.Member)):
user_id = user.id
else:
user_id = user
profile = await models.Profile.filter(user_id=user_id).limit(1).first()
row = await self.bot.ban(
user_id,
(datetime.now(timezone.utc) + time) if time is not None else None,
reason,
ctx.author,
)
message = f"✅ {f"**{profile.name}**" if profile is not None else f"`ID: {user_id}`"} was banned"
if row.expires_at:
message += f" until <t:{int(row.expires_at.timestamp())}:F> (<t:{int(row.expires_at.timestamp())}:R>)"
message += "."
await ctx.send(message)
try:
notification_message = await (
await self.bot.get_or_fetch_user(user_id)
).send(
embed=embeds.BanNotificationEmbed(self.bot, row),
view=views.BanNotificationView(self.bot, row),
)
row.notification_message_id = notification_message.id
await row.save()
except errors.DiscordException:
pass
@commands.command(extras={"reply_argument": "user"})
@checks.is_moderator()
@transactions.atomic()
async def unban(
self,
ctx: commands.Context,
user: discord.User | discord.Member | converters.DiscordUser,
) -> None:
"""
Unbans a user by their ID, pinging them, or replying to their message. The user will be
attempted to get notified of the unban.
Options:
- `<user>`: The user to unban or their ID.
"""
user_id = user if isinstance(user, int) else user.id
await self.bot.unban(user_id)
profile = await models.Profile.filter(user_id=user_id).limit(1).first()
await ctx.send(
f"✅ {f"**{profile.name}**" if profile is not None else f"`ID: {user_id}`"} was unbanned."
)
try:
await (await self.bot.get_or_fetch_user(user_id)).send(
"🔔 You have been unbanned from Payphone."
)
except errors.DiscordException:
pass
@commands.command(extras={"reply_argument": "user"})
@checks.is_moderator()
@transactions.atomic()
async def warn(
self,
ctx: commands.Context,
user: discord.User | discord.Member | converters.DiscordUser,
*,
reason: str,
) -> None:
"""
Warn a user by their ID or mention.
Options:
- `<user>`: The user's mention or their ID.
- `<reason>`: The reason of the warn.
"""
user_id = user if isinstance(user, int) else user.id
user = None
try:
user = await self.bot.get_or_fetch_user(user_id)
except errors.DiscordError:
await ctx.send(
"❌ Could not find this user. It may be because the user has left all servers with Payphone in them."
)
return
embed = discord.Embed(
color=constants.EMBED_COLOR,
title="You've been warned",
description=reason,
timestamp=datetime.now(timezone.utc),
author=self.bot.embed_author,
footer=discord.EmbedFooter(
text="Ignoring this warning will result in a ban."
),
thumbnail=self.bot.user.display_avatar.url,
)
profile = await models.Profile.filter(user_id=user_id).limit(1).first()
try:
await user.send(embed=embed)
except errors.DiscordException:
await ctx.send(
f"❌ Could not send the warning to {f"**{profile.name}**" if profile is not None else "the user"}, probably because they have their DMs closed."
)
return
await ctx.send(
f"✅ {f"**{profile.name}**" if profile is not None else "the user"} has been warned."
)
@commands.command()
@commands.is_owner()
@transactions.atomic()
async def moderator(
self,
ctx: commands.Context,
user: discord.User | discord.Member,
toggle: bool | None = None,
) -> None:
"""
Toggles a user's moderator status. It can only be ran by Payphone's owner.
Options:
- `<user>`: The user to toggle the moderation status for.
- `[<toggle>]`: The moderator status to set to the user.
"""
user_row, profile_row = await utils.get_user(user)
if toggle is not None:
user_row.is_moderator = toggle
else:
user_row.is_moderator = not user_row.is_moderator
await user_row.save()
await ctx.send(
f"✅ **{profile_row.name}**'s moderator status was set to `{"on" if user_row.is_moderator else "off"}`."
)
def setup(b: bot.Payphone) -> None:
"""Load the cog into the bot.
Args:
b (bot.Payphone): The bot instance to load the cog into.
"""
b.add_cog(Mods(b))