bot
bot copied to clipboard
Prevent a help channel from going dormant if a user is typing in it
The bot can detect when someone is in the middle of typing a message and prevent the channel from going dormant if it was otherwise about to become dormant. This may prevent situations in which a user was trying to answer a question but the channel goes dormant and their WIP message is lost.
The bot could extend the dormant timer by a few minutes (rather than a full 30). Of course, should a message get sent, that would extend it by the normal 30 minutes. The extension of a few minutes would just be to address situations in which someone types but never ends up sending anything and the few minutes should still give someone enough time to finish typing. If that isn't enough time, then if it sees someone is still typing, it will extend it once more.
What are people's thoughts on this suggestion?
Original suggestion:
Timo | rigged Coinflip: I really like the new system of help channels. But there is 1 thing I REALLY HATE. I now 2 times had the situation where I was writing an answer to an unanswered question. While I was writing, the channel turned dormant, deleting all the text I had already written, but not sent.
Suggestion: Instead of turning dormant instantly, warn users that it will turn dormant soon. Maybe react to the message to keep it open gdude: It might be nice if it was able to react to the "x is typing" gdude: add a couple extra minutes if it times out while someone is typing
I like the suggestion, I'm less clear on what the proper way to implement this is. We can't "simply" check for an ongoing typing event when the timer runs out, as typing events time-out rather quickly and people tend to pause when typing longer replies; it would be rather easy to miss the typing event.
We could use an on_typing event listener and keep track of the most recent typing event for that channel happened. The event includes a timestamp by default (when), so it should not be that difficult to do that.
It is yet another thing that could benefit from persistent caching, though. Maybe it's time to look into redis, as @lemonsaurus suggested.
whenever on_typing is triggered, if there's less than 5 minutes left, we set the timeout to 5 minutes. that should keep it from timing out if someone is working on a long message.
That sounds like a reasonable implementation to me. What do you think @SebastiaanZ? We can remove the planning label if there's going to be a consensus that 1. this should be a feature and 2. there's a reasonable way to implement it.
- this should be a feature
- there's a reasonable way to implement it.
I like the feature, but I'm less sure about the implementation.
whenever on_typing is triggered, if there's less than 5 minutes left, we set the timeout to 5 minutes. that should keep it from timing out if someone is working on a long message.
If a Task is currently pending because it's awaiting an asyncio.sleep, is there an easy way to introspect the time that's left? I think we'll have to investigate that. Ideally, it's a really cheap operation, as "in use" help channels get a lot of typing events.
Another option would be to keep track of whenever the last typing operation for a channel was received in a simple dict (future: Redis cached dict). When the original timer runs out, we optionally set a new time-out based on that stored last typing event time. Rinse and repeat for multiple extensions.
Switching to a scheduler instead of asyncio.sleep calls would be the smartest here IMO, you could simply reschedule the deletion task of 5 minutes if someone is typing, plus you can know if there's less than 5 minutes less.
I think that would mean a lot of rescheduling if people start having a conversation in those last five minutes. Each typing event would reschedule the task for just a few seconds. If you keep track of typing event times, you reschedule a maximum of once per five minutes and keeping track of a time int is minimal work.
Well, we could do so if someone types during the last 4 minutes, it schedules back to 6 minutes or so. Re-sleeping, when the timer runs out, sounds a bit messy IMO, but I guess that works :grin:.
I don't see why we'd need the added complexity and added work.
Our on_typing could be as simple as
@Cog.listener()
async def on_typing(self, channel, user, when):
if in_category(channel.id, Category.in_use):
self._last_typing_event[channel.id] = when
The comparison in the time-out deletion task would be trivial with datetime.datetime.now() and datetime.timedelta, and the channel move_to_dormant only needs to delete a key from that dict (even we even care; with a max of 50 mappings, we could also not bother).
I just don't see the benefit of switching to an entirely different approach that is more resource havy for something as simple as this.
I like @SebastiaanZ's suggested implementation. Let's do that.
!dormant or !close should also be declined in this case.
Maybe just add a check to dormant command.
Also when this command is cancelled it should mention the user who owns that help channel
in case he types !close and alt tab instantly without noticing the message that his !close request was declined
Mention will show a ping sign on the app icon grabbing the attention that something didn't went right.
Is this still blocked by pydis not receiving typing events?
@MarkKoz Do we still want this now that the help system has been migrated to posts and there are no '' race conditions '' between users.
If not, we can close it as completed