Add support for replies to help snippets#3538
Conversation
|
For various reasons we probably don't want to add this functionality to It is not users responsibility to moderate others and the rule command serves as a reference rather than a tool for non-staff members. |
ShaharNaveh
left a comment
There was a problem hiding this comment.
I approve if it's worth anything
Invalidated by push of d50401d
…d include else in the try block for clarity.
Invalidated by push of a94def3
| async def get_reference_message(ctx: Context) -> Message | None: | ||
| """Return a message reference if the reference exists and it does not refer to the author of the message.""" | ||
| if ctx.message.reference is None: | ||
| return None | ||
| try: | ||
| referenced_message = ctx.message.reference.resolved | ||
| except (discord.Forbidden, discord.NotFound): | ||
| return None | ||
| else: | ||
| if referenced_message is None or isinstance(referenced_message, DeletedReferencedMessage): | ||
| return None | ||
| if referenced_message.author == ctx.author: | ||
| return None | ||
| return referenced_message |
There was a problem hiding this comment.
sorry if wasn't very clear,
it should look something like this
| async def get_reference_message(ctx: Context) -> Message | None: | |
| """Return a message reference if the reference exists and it does not refer to the author of the message.""" | |
| if ctx.message.reference is None: | |
| return None | |
| try: | |
| referenced_message = ctx.message.reference.resolved | |
| except (discord.Forbidden, discord.NotFound): | |
| return None | |
| else: | |
| if referenced_message is None or isinstance(referenced_message, DeletedReferencedMessage): | |
| return None | |
| if referenced_message.author == ctx.author: | |
| return None | |
| return referenced_message | |
| async def get_reference_message(ctx: Context) -> Message | None: | |
| """Return a message reference if the reference exists and it does not refer to the author of the message.""" | |
| if ctx.message.reference is None: | |
| return None | |
| try: | |
| referenced_message = .resolved or .cached_message or await fetch_message(...) | |
| except (discord.Forbidden, discord.NotFound): | |
| return None | |
| else: | |
| if isinstance(referenced_message, DeletedReferencedMessage): | |
| return None | |
| if referenced_message.author == ctx.author: | |
| return None | |
| return referenced_message |
NotFound and Forbidden won't ever be raised unless an API call is made.
Basically the idea is to check the data in resolved, if empty, check cached_message, if also empty finally make an api call.
…t, and now referenced_message can be taken from cache or fetched
| except (discord.Forbidden, discord.NotFound): | ||
| return None | ||
| else: | ||
| if referenced_message is None or isinstance(referenced_message, DeletedReferencedMessage): |
There was a problem hiding this comment.
Yes this looks gud now, just one minor nit: referenced_message can never be None here as if resolved or cached_message is None, we will fetch using the API, which will raise NotFound etc. if the message can't be fetched.
| If the callers message does not have a reference, the bot messsage is sent without reply | ||
| """ | ||
| if message_reference := await get_reference_message(ctx): | ||
| return await message_reference.reply(embed=embed) |
There was a problem hiding this comment.
This can fail if the referenced message is deleted between the fetch and send.
This is undesirable behavior since the bot will just fail to respond in that case. The command has been invoked, a reply being deleted shouldn't cause the bot to not reply either.
One of two options:
- You'll need to construct a new reference with
fail_if_not_existsset to False and provide that to .send() - try, except a failure, try again without the reference.
There was a problem hiding this comment.
reference = None
if message_reference := await get_reference_message(ctx):
reference = message_reference
return await ctx.send(embed=embed, reference=reference)Would this approach work? I tested the None case by commenting the line that sets the message_reference and it's sent as a normal message. This is the simplest solution I came across.
Actually, looking at how you reconstruct references, the first approach you mentioned is better, mine would fail anyways since an exception is raised.
if message_reference := await get_reference_message(ctx):
reference = message_reference.to_reference(fail_if_not_exists=False)
return await ctx.send(embed=embed, reference=reference)
return await ctx.send(embed=embed)I don't like the duplication, but this avoids what you mentioned.
…n't succesfuly get the reference

PR for issue #3537
This implementation makes the bot reply to the same message that the caller replies, and if the command invoke isn't a reply, the bot maintains its current behavior, sending the snippet without replying to the caller.
If the caller replies to himself, the bot also maintains the no-reply behavior.
It is currently implemented for (all aliases of):
Due to the use of

LinePaginator.paginatein!rulecommand, I wasn't able to implement it for all of its variants, so I left it untouched for consistency. (I'll open an issue about it if the PR gets merged)