diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 05fc2e783..d0fd93ce4 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -45,6 +45,7 @@ redbot/cogs/trivia/* @Tobotimus redbot/cogs/dataconverter/* @mikeshardmind redbot/cogs/reports/* @mikeshardmind redbot/cogs/permissions/* @mikeshardmind +redbot/cogs/warnings/* @palmtree5 # Docs docs/* @tekulvw @palmtree5 diff --git a/redbot/cogs/warnings/helpers.py b/redbot/cogs/warnings/helpers.py index 25c248203..2ea504878 100644 --- a/redbot/cogs/warnings/helpers.py +++ b/redbot/cogs/warnings/helpers.py @@ -22,7 +22,7 @@ async def warning_points_add_check( act = a else: break - if act: # some action needs to be taken + if act and act["exceed_command"] is not None: # some action needs to be taken await create_and_invoke_context(ctx, act["exceed_command"], user) @@ -38,7 +38,7 @@ async def warning_points_remove_check( act = a else: break - if act: # some action needs to be taken + if act and act["drop_command"] is not None: # some action needs to be taken await create_and_invoke_context(ctx, act["drop_command"], user) @@ -81,10 +81,11 @@ async def get_command_for_exceeded_points(ctx: commands.Context): the points threshold for the action""" await ctx.send( _( - "Enter the command to be run when the user exceeds the points for " - "this action to occur.\nEnter it exactly as you would if you were " + "Enter the command to be run when the user **exceeds the points for " + "this action to occur.**\n**If you do not wish to have a command run, enter** " + "`none`.\n\nEnter it exactly as you would if you were " "actually trying to run the command, except don't put a prefix and " - "use {user} in place of any user/member arguments\n\n" + "use `{user}` in place of any user/member arguments\n\n" "WARNING: The command entered will be run without regard to checks or cooldowns. " "Commands requiring bot owner are not allowed for security reasons.\n\n" "Please wait 15 seconds before entering your response." @@ -100,8 +101,10 @@ async def get_command_for_exceeded_points(ctx: commands.Context): try: msg = await ctx.bot.wait_for("message", check=same_author_check, timeout=30) except asyncio.TimeoutError: - await ctx.send(_("Ok then.")) return None + else: + if msg.content == "none": + return None command, m = get_command_from_input(ctx.bot, msg.content) if command is None: @@ -121,12 +124,13 @@ async def get_command_for_dropping_points(ctx: commands.Context): """ await ctx.send( _( - "Enter the command to be run when the user returns to a value below " - "the points for this action to occur. Please note that this is " + "Enter the command to be run when the user **returns to a value below " + "the points for this action to occur.** Please note that this is " "intended to be used for reversal of the action taken when the user " - "exceeded the action's point value\nEnter it exactly as you would " + "exceeded the action's point value.\n**If you do not wish to have a command run " + "on dropping points, enter** `none`.\n\nEnter it exactly as you would " "if you were actually trying to run the command, except don't put a prefix " - "and use {user} in place of any user/member arguments\n\n" + "and use `{user}` in place of any user/member arguments\n\n" "WARNING: The command entered will be run without regard to checks or cooldowns. " "Commands requiring bot owner are not allowed for security reasons.\n\n" "Please wait 15 seconds before entering your response." @@ -142,9 +146,10 @@ async def get_command_for_dropping_points(ctx: commands.Context): try: msg = await ctx.bot.wait_for("message", check=same_author_check, timeout=30) except asyncio.TimeoutError: - await ctx.send(_("Ok then.")) return None - + else: + if msg.content == "none": + return None command, m = get_command_from_input(ctx.bot, msg.content) if command is None: await ctx.send(m) diff --git a/redbot/cogs/warnings/warnings.py b/redbot/cogs/warnings/warnings.py index 1284ad1c0..7d840cecf 100644 --- a/redbot/cogs/warnings/warnings.py +++ b/redbot/cogs/warnings/warnings.py @@ -14,6 +14,7 @@ from redbot.core.bot import Red from redbot.core.i18n import Translator, cog_i18n from redbot.core.utils.mod import is_admin_or_superior from redbot.core.utils.chat_formatting import warning, pagify +from redbot.core.utils.menus import menu, DEFAULT_CONTROLS _ = Translator("Warnings", __file__) @@ -74,27 +75,9 @@ class Warnings: """ guild = ctx.guild - await ctx.send("Would you like to enter commands to be run? (y/n)") + exceed_command = await get_command_for_exceeded_points(ctx) + drop_command = await get_command_for_dropping_points(ctx) - def same_author_check(m): - return m.author == ctx.author - - try: - msg = await ctx.bot.wait_for("message", check=same_author_check, timeout=30) - except asyncio.TimeoutError: - await ctx.send(_("Ok then.")) - return - - if msg.content.lower() == "y": - exceed_command = await get_command_for_exceeded_points(ctx) - if exceed_command is None: - return - drop_command = await get_command_for_dropping_points(ctx) - if drop_command is None: - return - else: - exceed_command = None - drop_command = None to_add = { "action_name": name, "points": points, @@ -114,7 +97,7 @@ class Warnings: # Sort in descending order by point count for ease in # finding the highest possible action to take registered_actions.sort(key=lambda a: a["points"], reverse=True) - await ctx.tick() + await ctx.send(_("Action {name} has been added.").format(name=name)) @warnaction.command(name="del") @commands.guild_only() @@ -182,13 +165,20 @@ class Warnings: msg_list = [] async with guild_settings.reasons() as registered_reasons: for r, v in registered_reasons.items(): - msg_list.append( - "Name: {}\nPoints: {}\nDescription: {}".format( - r, v["points"], v["description"] + if ctx.embed_requested(): + em = discord.Embed( + title=_("Reason: {name}").format(name=r), description=v["description"] + ) + em.add_field(name=_("Points"), value=str(v["points"])) + msg_list.append(em) + else: + msg_list.append( + "Name: {}\nPoints: {}\nDescription: {}".format( + r, v["points"], v["description"] + ) ) - ) if msg_list: - await ctx.send_interactive(msg_list) + await menu(ctx, msg_list, DEFAULT_CONTROLS) else: await ctx.send(_("There are no reasons configured!")) @@ -202,14 +192,21 @@ class Warnings: msg_list = [] async with guild_settings.actions() as registered_actions: for r in registered_actions: - msg_list.append( - "Name: {}\nPoints: {}\nExceed command: {}\n" - "Drop command: {}".format( - r["action_name"], r["points"], r["exceed_command"], r["drop_command"] + if await ctx.embed_requested(): + em = discord.Embed(title=_("Action: {name}").format(name=r["action_name"])) + em.add_field(name=_("Points"), value="{}".format(r["points"]), inline=False) + em.add_field(name=_("Exceed command"), value=r["exceed_command"], inline=False) + em.add_field(name=_("Drop command"), value=r["drop_command"], inline=False) + msg_list.append(em) + else: + msg_list.append( + "Name: {}\nPoints: {}\nExceed command: {}\n" + "Drop command: {}".format( + r["action_name"], r["points"], r["exceed_command"], r["drop_command"] + ) ) - ) if msg_list: - await ctx.send_interactive(msg_list) + await menu(ctx, msg_list, DEFAULT_CONTROLS) else: await ctx.send(_("There are no actions configured!")) @@ -221,6 +218,9 @@ class Warnings: Reason must be a registered reason, or "custom" if custom reasons are allowed """ + if user == ctx.author: + await ctx.send(_("You cannot warn yourself.")) + return if reason.lower() == "custom": custom_allowed = await self.config.guild(ctx.guild).allow_custom_reasons() if not custom_allowed: @@ -256,7 +256,27 @@ class Warnings: await member_settings.total_points.set(current_point_count) await warning_points_add_check(self.config, ctx, user, current_point_count) - await ctx.tick() + try: + em = discord.Embed( + title=_("Warning from {mod_name}#{mod_discrim}").format( + mod_name=ctx.author.display_name, mod_discrim=ctx.author.discriminator + ), + description=reason_type["description"], + ) + em.add_field(name=_("Points"), value=str(reason_type["points"])) + await user.send( + _("You have received a warning in {guild_name}.").format( + guild_name=ctx.guild.name + ), + embed=em, + ) + except discord.HTTPException: + pass + await ctx.send( + _("User {user_name}#{user_discrim} has been warned.").format( + user_name=user.display_name, user_discrim=user.discriminator + ) + ) @commands.command() @commands.guild_only() @@ -303,6 +323,9 @@ class Warnings: @checks.admin_or_permissions(ban_members=True) async def unwarn(self, ctx: commands.Context, user_id: int, warn_id: str): """Removes the specified warning from the user specified""" + if user_id == ctx.author.id: + await ctx.send(_("You cannot remove warnings from yourself.")) + return guild = ctx.guild member = guild.get_member(user_id) if member is None: # no longer in guild, but need a "member" object