From 11fad1c270f84cb981c6623af3266de50d2a705c Mon Sep 17 00:00:00 2001 From: "Nyeki.py" <84998222+Nekidev@users.noreply.github.com> Date: Thu, 26 Dec 2024 01:00:35 -0300 Subject: [PATCH] Upload to GitLab --- k8s/bot.yml | 2 +- k8s/tasks.yml | 4 +-- payphone/bot.py | 8 +++++- payphone/cogs/admin/cog.py | 44 +++++++++++++++++++++++++------- payphone/cogs/admin/embeds.py | 6 +++-- payphone/cogs/admin/views.py | 43 ++++++++++++++++---------------- payphone/cogs/calls/cog.py | 47 ++++++++++++++++++++++------------- payphone/core/checks.py | 7 ++++++ payphone/core/exceptions.py | 6 +++++ payphone/db/models.py | 2 +- pyproject.toml | 2 +- scripts/deploy.py | 8 +++--- scripts/update.py | 4 +-- uv.lock | 2 +- 14 files changed, 123 insertions(+), 62 deletions(-) diff --git a/k8s/bot.yml b/k8s/bot.yml index 1b038a9..4386ef7 100644 --- a/k8s/bot.yml +++ b/k8s/bot.yml @@ -17,7 +17,7 @@ spec: spec: containers: - name: bot - image: git.nyeki.dev/payphone/payphone-shard:latest + image: registry.nyeki.dev/payphone/payphone/shard:latest imagePullPolicy: "Always" envFrom: - configMapRef: diff --git a/k8s/tasks.yml b/k8s/tasks.yml index 344f2f5..f786609 100644 --- a/k8s/tasks.yml +++ b/k8s/tasks.yml @@ -5,7 +5,7 @@ metadata: spec: containers: - name: connect - image: git.nyeki.dev/payphone/payphone-tasks:latest + image: registry.nyeki.dev/payphone/payphone/tasks:latest command: ["uv", "run", "--no-dev", "tasks.py", "connect"] envFrom: - secretRef: @@ -20,7 +20,7 @@ spec: memory: "1Gi" cpu: "1" # - name: expire - # image: git.nyeki.dev/payphone/payphone-tasks:latest + # image: registry.nyeki.dev/payphone/payphone/tasks:latest # command: ["uv", "run", "--no-dev", "tasks.py", "expire"] # envFrom: # - secretRef: diff --git a/payphone/bot.py b/payphone/bot.py index 640f90f..b030659 100644 --- a/payphone/bot.py +++ b/payphone/bot.py @@ -30,7 +30,7 @@ class Payphone(commands.AutoShardedBot): super().__init__( intents=intents, - command_prefix="p.", + command_prefix=self.get_prefix, strip_after_prefix=True, case_insensitive=True, help_command=help_command.HelpCommand(), @@ -358,6 +358,12 @@ class Payphone(commands.AutoShardedBot): elif isinstance(exception, errors.NotOwner): await context.send("❌ You're not the owner of this bot.") + elif isinstance(exception, exceptions.AccountTooYoungError): + await context.send( + "❌ Your account is too young to use Payphone. It must be at least " + f"{exception.days} days old to be able to run commands." + ) + elif isinstance(exception, errors.CommandNotFound): return diff --git a/payphone/cogs/admin/cog.py b/payphone/cogs/admin/cog.py index df36da3..f42956f 100644 --- a/payphone/cogs/admin/cog.py +++ b/payphone/cogs/admin/cog.py @@ -30,7 +30,7 @@ class Admin(base.Cog): self, ctx: commands.Context, user: discord.User, toggle: bool = True ) -> None: """Gives the user the Moderator role. - + Options: - ``: The user to give the role. - `[toggle]`: Whether to give or remove the role. @@ -48,6 +48,26 @@ class Admin(base.Cog): f"Toggled the moderator role {'on' if toggle else 'off'} for {user.mention}." ) + @commands.command(aliases=["b"]) + @checks.is_moderator() + async def ban( + self, ctx: commands.Context, user: discord.User | int | None = None + ) -> None: + """Bans the user from the bot. + + Options: + - `[user]`: The user to ban or their ID. If none is provided, the author will be banned. + + Permissions: + - Bot Moderator + """ + + user_id = user if isinstance(user, int) else user.id if user else ctx.author.id + + await self.bot.ban(user_id, None, None, ctx.author.id) + + await ctx.send(f"<@!{user_id}> was banned from Payphone.") + @commands.command(aliases=["ub"]) @checks.is_moderator() async def unban( @@ -77,13 +97,13 @@ class Admin(base.Cog): @commands.command(aliases=["sup"]) @commands.is_owner() async def supporter( - self, ctx: commands.Context, user: discord.User, toggle: bool = True + self, ctx: commands.Context, user: discord.User, months: int = 1 ) -> None: """Gives the user the Supporter role. - + Options: - ``: The user to give the role. - - `[toggle]`: Whether to give or remove the role. + - `[months]`: The number of months to give the role. Permissions: - Bot Owner @@ -93,21 +113,27 @@ class Admin(base.Cog): id=user.id, defaults={ "is_supporter_until": ( - datetime.now(timezone.utc) + timedelta(days=30) if toggle else None + datetime.now(timezone.utc) + timedelta(days=30 * months) + if months > 0 + else None ) }, ) await instance.set_cache(self.bot.redis) - await ctx.send( - f"Gave the Supporter role to {ctx.author.mention} until in one month." - ) + if months: + await ctx.send( + f"Gave the Supporter role to {ctx.author.mention} for {months} months." + ) + + else: + await ctx.send(f"Removed the Supporter role from {ctx.author.mention}.") @commands.command() @checks.is_moderator() async def reports(self, ctx: commands.Context) -> None: """Shows the reports. - + Permissions: - Bot Moderator """ diff --git a/payphone/cogs/admin/embeds.py b/payphone/cogs/admin/embeds.py index 4294d86..e0f4829 100644 --- a/payphone/cogs/admin/embeds.py +++ b/payphone/cogs/admin/embeds.py @@ -1,7 +1,7 @@ import discord from payphone.db import models -from payphone.core import constants +from payphone.core import constants, formatting def report_embed(report: models.Report) -> discord.Embed: @@ -26,7 +26,9 @@ def report_embed(report: models.Report) -> discord.Embed: ), fields=[ discord.EmbedField( - name="Message Content", value=report.message_content, inline=False + name="Message Content", + value=formatting.trim(report.message_content, 1024), + inline=False, ) ], thumbnail=report.user_avatar_url, diff --git a/payphone/cogs/admin/views.py b/payphone/cogs/admin/views.py index a712d27..ceec9be 100644 --- a/payphone/cogs/admin/views.py +++ b/payphone/cogs/admin/views.py @@ -4,7 +4,7 @@ import discord from payphone.db import models from payphone.bot import Payphone -from payphone.core import constants +from payphone.core import constants, formatting from payphone.cogs.admin import embeds @@ -49,6 +49,25 @@ class ReportView(discord.ui.View): ) -> None: """Handles the action select.""" + self.report.resolved = True + await self.report.save() + + report = await models.Report.filter(resolved=False).first() + + if report is None: + self.stop() + + await interaction.response.edit_message( + content="✅ No reports left, have this cookie 🍪 !!", + embeds=[], + view=None, + ) + + else: + await interaction.response.edit_message( + embed=embeds.report_embed(report), view=ReportView(self.bot, report) + ) + user = await models.User.get_cache_or_db(self.bot.redis, self.report.user_id) if select.values[0] == "warn": @@ -63,7 +82,7 @@ class ReportView(discord.ui.View): fields=[ discord.EmbedField( name="Message Content", - value=f"You sent the following message in a call:\n> {self.report.message_content}", + value=f"You sent the following message in a call:\n> {formatting.trim(self.report.message_content, 900)}", ), discord.EmbedField( name="User Name", @@ -117,7 +136,7 @@ class ReportView(discord.ui.View): fields=[ discord.EmbedField( name="Message Content", - value=f"You sent the following message in a call:\n> {self.report.message_content}", + value=f"You sent the following message in a call:\n> {formatting.trim(self.report.message_content, 900)}", ), discord.EmbedField( name="User Name", @@ -154,24 +173,6 @@ class ReportView(discord.ui.View): except discord.Forbidden: pass - self.report.resolved = True - await self.report.save() - - report = await models.Report.filter(resolved=False).first() - - if report is None: - self.stop() - - return await interaction.response.edit_message( - content="✅ No reports left, have this cookie 🍪 !!", - embeds=[], - view=None, - ) - - await interaction.response.edit_message( - embed=embeds.report_embed(report), view=ReportView(self.bot, report) - ) - @discord.ui.button(label="Skip", style=discord.ButtonStyle.gray) async def skip_callback( self, _button: discord.ui.Button, interaction: discord.Interaction diff --git a/payphone/cogs/calls/cog.py b/payphone/cogs/calls/cog.py index 24f5215..e50409b 100644 --- a/payphone/cogs/calls/cog.py +++ b/payphone/cogs/calls/cog.py @@ -163,6 +163,31 @@ class Calls(base.Cog): return await ctx.send(message) + @commands.command(aliases=["r"]) + @checks.is_not_banned() + async def report(self, ctx: commands.Context) -> None: + """ + Report a message in a call. + """ + + embed = discord.Embed( + color=constants.MASK_COLOR, + title="Reporting has been moved!", + description="📝 This command has been replaced! Payphone has switched to per-message reporting due to the high amount of reports.", + fields=[ + discord.EmbedField( + name="Reporting on Desktop", + value="Right click the message you want to report and, in the opened menu, press `Apps > Report Message`.", + ), + discord.EmbedField( + name="Reporting on Mobile", + value="Press and hold the message you want to report and, in the opened menu, press `Apps > Report Message`.", + ), + ], + ) + + await ctx.send(embed=embed) + @commands.Cog.listener() async def on_message(self, message: discord.Message) -> None: """ @@ -435,7 +460,9 @@ class Calls(base.Cog): await webhook.edit_message(propagation_id, content=payload.data["content"]) - @commands.message_command(name="Report Message" if not constants.IS_DEBUG else "(Dev) Report Message") + @commands.message_command( + name="Report Message" if not constants.IS_DEBUG else "(Dev) Report Message" + ) async def report_message( self, ctx: discord.ApplicationContext, message: discord.Message ) -> None: @@ -448,7 +475,8 @@ class Calls(base.Cog): "❌ You're banned from using Payphone.", ephemeral=True ) - author_id = await self.bot.call_handler.get_message_author_id(message.id) + message_id = await self.bot.call_handler.get_original_message_id(message.id) + author_id = await self.bot.call_handler.get_message_author_id(message_id) if author_id is None: return await ctx.send_response( @@ -461,21 +489,6 @@ class Calls(base.Cog): await ctx.send_response("✅ The message has been reported.", ephemeral=True) - message_id: int - - if message.author.bot: - message_id = await self.bot.call_handler.get_original_message_id(message.id) - - else: - message_id = message.id - - if message_id != message.id: - cached_message = await self.bot.call_handler.get_message(message_id) - - message = await self.bot.get_partial_messageable( - cached_message.channel_id - ).fetch_message(message_id) - await models.Report.update_or_create( message_id=message_id, defaults={ diff --git a/payphone/core/checks.py b/payphone/core/checks.py index 938acc1..956f028 100644 --- a/payphone/core/checks.py +++ b/payphone/core/checks.py @@ -1,3 +1,5 @@ +from datetime import datetime, timezone, timedelta + from discord.ext import commands from payphone.core import exceptions @@ -22,6 +24,11 @@ def is_not_banned(): """Checks that the user is not banned.""" async def predicate(ctx: commands.Context) -> bool: + if ctx.author.created_at > datetime.now(timezone.utc) - timedelta( + days=exceptions.AccountTooYoungError.days + ): + raise exceptions.AccountTooYoungError() + if await ctx.bot.is_banned(ctx.author.id): raise exceptions.BannedError() diff --git a/payphone/core/exceptions.py b/payphone/core/exceptions.py index 1b02823..12c69cc 100644 --- a/payphone/core/exceptions.py +++ b/payphone/core/exceptions.py @@ -15,3 +15,9 @@ class ChannelDisabledError(errors.CheckFailure): class NotOnCallError(errors.CheckFailure): """Raised when the user is not on a call.""" + + +class AccountTooYoungError(errors.CheckFailure): + """Raised when the user's account is too young.""" + + days: int = 14 diff --git a/payphone/db/models.py b/payphone/db/models.py index e4468e1..88bc3b0 100644 --- a/payphone/db/models.py +++ b/payphone/db/models.py @@ -94,7 +94,7 @@ class User(models.Model): instance.is_masked = cache["is_masked"] instance.is_moderator = cache["is_moderator"] instance.is_supporter_until = ( - datetime.fromisoformat(cache["is_supporter_until"]) + datetime.fromtimestamp(cache["is_supporter_until"], timezone.utc) if cache["is_supporter_until"] is not None else None ) diff --git a/pyproject.toml b/pyproject.toml index 55c375e..924bf1f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "payphone" -version = "0.22.0" +version = "0.29.0" description = "Add your description here" readme = "README.md" requires-python = ">=3.12" diff --git a/scripts/deploy.py b/scripts/deploy.py index 6320c07..c5ef9e3 100644 --- a/scripts/deploy.py +++ b/scripts/deploy.py @@ -16,7 +16,7 @@ username = input("Username for git.nyeki.dev: ") password = getpass.getpass("Password for git.nyeki.dev: ") tags = requests.get( - "https://git.nyeki.dev/v2/payphone/payphone-shard/tags/list", + "https://registry.nyeki.dev/v2/payphone/payphone-shard/tags/list", auth=(username, password), ).json()["tags"] @@ -35,12 +35,12 @@ print(f"Updating to tag v{latest_version}...") os.system(f"git pull https://{username}:{password}@git.nyeki.dev/payphone/payphone") os.system( - f"microk8s kubectl set image sts/bot bot=git.nyeki.dev/payphone/payphone-shard:v{latest_version}" + f"microk8s kubectl set image sts/bot bot=registry.nyeki.dev/payphone/payphone/shard:v{latest_version}" ) os.system( f""" microk8s kubectl set image pod/tasks \ - connect=git.nyeki.dev/payphone/payphone-shard:v{latest_version} \ - expire=git.nyeki.dev/payphone/payphone-shard:v{latest_version} \ + connect=registry.nyeki.dev/payphone/payphone/shard:v{latest_version} \ + expire=registry.nyeki.dev/payphone/payphone/shard:v{latest_version} \ """ ) diff --git a/scripts/update.py b/scripts/update.py index 6362056..ea86014 100644 --- a/scripts/update.py +++ b/scripts/update.py @@ -20,12 +20,12 @@ version_num = version[1] targets = ["tasks", "shard"] for t in targets: - tag = f"git.nyeki.dev/payphone/payphone-{t}:v{version_num}" + tag = f"registry.nyeki.dev/payphone/payphone/{t}:v{version_num}" os.system(f"docker build --target {t} --tag {tag} .") os.system(f"docker push {tag}") - tag = f"git.nyeki.dev/payphone/payphone-{t}:latest" + tag = f"registry.nyeki.dev/payphone/payphone/{t}:latest" os.system(f"docker build --target {t} --tag {tag} .") os.system(f"docker push {tag}") diff --git a/uv.lock b/uv.lock index 76cd3e1..a637b1d 100644 --- a/uv.lock +++ b/uv.lock @@ -353,7 +353,7 @@ wheels = [ [[package]] name = "payphone" -version = "0.21.0" +version = "0.26.0" source = { virtual = "." } dependencies = [ { name = "aerich" },