Skip to content

Commit 640d963

Browse files
authored
Merge pull request #355 from rHomelab/fix/report_cmds_handle_missing_msg
2 parents 86c09e7 + 499568f commit 640d963

File tree

2 files changed

+69
-30
lines changed

2 files changed

+69
-30
lines changed

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ select = ["F", "E", "W", "I", "ASYNC", "PL", "RUF"]
66

77
[tool.ruff]
88
line-length = 127
9+
target-version = "py311"
910

1011
[tool.pyright]
1112
venvPath = "."

report/report.py

Lines changed: 68 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ async def reports_status(self, ctx: commands.GuildContext):
135135
async def cmd_report(self, ctx: commands.GuildContext, *, message: str):
136136
"""Send a report to the mods.
137137
138+
⚠️ `message` is required.
139+
138140
Example:
139141
- `[p]report <message>`
140142
"""
@@ -148,29 +150,39 @@ async def cmd_report(self, ctx: commands.GuildContext, *, message: str):
148150

149151
@cmd_report.error
150152
async def on_cmd_report_error(self, ctx: commands.GuildContext, error):
153+
if isinstance(error, commands.MissingRequiredArgument):
154+
logger.debug(
155+
f"Emergency command missing required argument for {ctx.author.name} ({ctx.author.id}) in guild "
156+
f"{ctx.guild.name} ({ctx.guild.id})"
157+
)
158+
await self._send_cmd_error_response(
159+
ctx, error, f"Missing required argument in report command: `{error.param.name}`."
160+
)
161+
return
162+
151163
if isinstance(error, commands.CommandOnCooldown):
152164
logger.debug(
153165
f"Report command on cooldown for {ctx.author.name} ({ctx.author.id}) in guild "
154166
f"{ctx.guild.name} ({ctx.guild.id}), ends in {error.retry_after:.1f}s"
155167
)
156-
if ctx.interaction is not None and not ctx.interaction.response.is_done():
157-
await ctx.interaction.response.send_message(str(error), ephemeral=True)
158-
else:
159-
await ctx.message.delete()
160-
await ctx.author.send(f"You are on cooldown. Try again in <t:{error.retry_after}:R>")
161-
else:
162-
logger.error(f"Unexpected error occurred: {error}")
163-
try:
164-
await ctx.bot.send_to_owners(error)
165-
except Exception as e:
166-
logger.error(f"Failed to send error to owners: {e}")
168+
retry_timestamp = int(error.retry_after + ctx.message.created_at.timestamp())
169+
await self._send_cmd_error_response(ctx, error, f"You are on cooldown. Try again in <t:{retry_timestamp}:R>")
170+
return
171+
172+
logger.error(f"Unexpected error occurred: {error}")
173+
try:
174+
await ctx.bot.send_to_owners(error)
175+
except Exception as e:
176+
logger.error(f"Failed to send error to owners: {e}")
167177

168178
@commands.hybrid_command("emergency")
169179
@commands.cooldown(1, 30.0, commands.BucketType.user)
170180
@commands.guild_only()
171181
async def cmd_emergency(self, ctx: commands.GuildContext, *, message: str):
172182
"""Pings the mods with a high-priority report.
173183
184+
⚠️ `message` is required.
185+
174186
Example:
175187
- `[p]emergency <message>`
176188
"""
@@ -182,24 +194,32 @@ async def cmd_emergency(self, ctx: commands.GuildContext, *, message: str):
182194
logger.debug(f"Emergency report content length: {len(message)} characters")
183195
await self.do_report(ctx.channel, ctx.message, message, True, ctx.interaction)
184196

185-
@cmd_report.error
197+
@cmd_emergency.error
186198
async def on_cmd_emergency_error(self, ctx: commands.GuildContext, error):
199+
if isinstance(error, commands.MissingRequiredArgument):
200+
logger.debug(
201+
f"Emergency command missing required argument for {ctx.author.name} ({ctx.author.id}) in guild "
202+
f"{ctx.guild.name} ({ctx.guild.id})"
203+
)
204+
await self._send_cmd_error_response(
205+
ctx, error, f"Missing required argument in emergency command: `{error.param.name}`."
206+
)
207+
return
208+
187209
if isinstance(error, commands.CommandOnCooldown):
188210
logger.debug(
189211
f"Emergency command on cooldown for {ctx.author.name} ({ctx.author.id}) in guild "
190212
f"{ctx.guild.name} ({ctx.guild.id}), ends in {error.retry_after:.1f}s"
191213
)
192-
if ctx.interaction is not None and not ctx.interaction.response.is_done():
193-
await ctx.interaction.response.send_message(str(error), ephemeral=True)
194-
else:
195-
await ctx.message.delete()
196-
await ctx.author.send(f"You are on cooldown. Try again in <t:{error.retry_after}:R>")
197-
else:
198-
logger.error(f"Unexpected error occurred: {error}")
199-
try:
200-
await ctx.bot.send_to_owners(error)
201-
except Exception as e:
202-
logger.error(f"Failed to send error to owners: {e}")
214+
retry_timestamp = int(error.retry_after + ctx.message.created_at.timestamp())
215+
await self._send_cmd_error_response(ctx, error, f"You are on cooldown. Try again in <t:{retry_timestamp}:R>")
216+
return
217+
218+
logger.error(f"Unexpected error occurred: {error}")
219+
try:
220+
await ctx.bot.send_to_owners(error)
221+
except Exception as e:
222+
logger.error(f"Failed to send error to owners: {e}")
203223

204224
async def get_log_channel(self, guild: discord.Guild) -> TextLikeChannel | None:
205225
"""Gets the log channel for the guild"""
@@ -285,7 +305,7 @@ async def send_emergency_report(self, log_channel: TextLikeChannel, embed: disco
285305

286306
async def do_report(
287307
self,
288-
channel: "discord.guild.GuildChannel | discord.Thread",
308+
channel: GuildChannelOrThread,
289309
message: discord.Message,
290310
report_body: str,
291311
emergency: bool,
@@ -335,7 +355,7 @@ async def do_report(
335355
await interaction.response.send_message(embed=report_reply, ephemeral=True)
336356

337357
# Else send a DM if DM confirmations are enabled
338-
elif self.config.guild(channel.guild).confirmations():
358+
elif await self.config.guild(channel.guild).confirmations():
339359
logger.debug("Sending confirmation via DM")
340360
try:
341361
await message.author.send(embed=report_reply)
@@ -357,10 +377,10 @@ async def make_report_embed(
357377
)
358378

359379
if isinstance(channel, TextLikeChannel):
360-
last_msg = [msg async for msg in channel.history(limit=1, before=message.created_at)][0] # noqa: RUF015
380+
last_msg = await anext(channel.history(limit=1, before=message.created_at), None)
361381
embed.add_field(name="Context Region", value=last_msg.jump_url if last_msg else "No messages found")
362382
else:
363-
embed.add_field(name="Channel", value=message.channel.mention) # type: ignore
383+
embed.add_field(name="Channel", value=channel.mention)
364384

365385
embed.add_field(name="Report Content", value=escape(report_body or "<no message>"))
366386
return embed
@@ -398,9 +418,7 @@ async def notify_truncation(
398418
except discord.Forbidden as exc:
399419
logger.error(f"Failed to notify {message.author.global_name} ({message.author.id}) about report truncation: {exc}")
400420

401-
async def notify_guild_owner_config_error(
402-
self, channel: "discord.guild.GuildChannel | discord.Thread", message: discord.Message, report_body: str
403-
):
421+
async def notify_guild_owner_config_error(self, channel: GuildChannelOrThread, message: discord.Message, report_body: str):
404422
"""Notify guild owner about misconfigured report log channel."""
405423
if channel.guild.owner is None:
406424
logger.warning(
@@ -433,3 +451,23 @@ async def notify_guild_owner_config_error(
433451
logger.info("Successfully notified guild owner about config error")
434452
except discord.Forbidden:
435453
logger.error("Failed to send config error notification to guild owner - no DM permissions")
454+
455+
async def _send_cmd_error_response(self, ctx: commands.GuildContext, error, response: str):
456+
"""
457+
Sends a command error response to the user.
458+
459+
If the context has an unresponded interaction, sends an ephemeral error message.
460+
Otherwise, deletes the original message and sends the response directly to the user.
461+
462+
Parameters:
463+
ctx (commands.GuildContext): The command context containing guild information
464+
error: The error object to be sent as a message
465+
response (str): The response message to send to the user
466+
Returns:
467+
None
468+
"""
469+
if ctx.interaction is not None and not ctx.interaction.response.is_done():
470+
await ctx.interaction.response.send_message(str(error), ephemeral=True)
471+
else:
472+
await ctx.message.delete()
473+
await ctx.author.send(response)

0 commit comments

Comments
 (0)