Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More placeholders in rate-limit messages #2325

Closed
dgw opened this issue Jul 17, 2022 · 2 comments · Fixed by #2434
Closed

More placeholders in rate-limit messages #2325

dgw opened this issue Jul 17, 2022 · 2 comments · Fixed by #2434

Comments

@dgw
Copy link
Member

dgw commented Jul 17, 2022

Requested Feature

We discussed a bit in #2290 what other things might be useful to have as placeholders in the optional message sent when a command is blocked by rate limiting. Some ideas from that, plus a bit of reflection just now:

  • {time_left} — a tools.time.seconds_to_human() of the time left until the rate limit expires
  • {seconds_left} — the raw version of {time_left}
  • {limit} — what the actual rate limit is, probably in seconds_to_human() format
  • {limit_type} — especially for the default message, useful to differentiate why a command was blocked
  • {command} — the name of the command that was rate-limited
  • {plugin} — the name of the plugin in which the limited feature lives

Names subject to change, as always, if better ideas come up.

Problems Solved

The time-related placeholders are good for games and such, where players can only perform a given action every n seconds, and would want to know how long until they can use it again.

Command and plugin names could be useful if the message needs to include some usage info, and would reduce code duplication (and later, l10n workload) by allowing a given plugin the use of just one templatized rate-limit string in place of many.

Alternatives

There are no alternatives to the remaining-time placeholders. Plugin code can't otherwise insert those values. (Same for the existing nick and channel placeholders defined in the current code. The values are only available at runtime to the dispatcher.)

The plugin author obviously knows what the rate limit is, in simple cases, but if multiple types of rate limit are in effect on a single callable a hard-coded value in the message isn't always going to work.

Notes

No response

@dgw dgw added this to the 8.0.0 milestone Jul 17, 2022
@SnoopJ
Copy link
Contributor

SnoopJ commented Mar 26, 2023

So, I've been looking at this issue and discussed a few things on IRC, and we seem to be in agreement that implementing this is going to require some plumbing changes.

In particular, implementing the time-related fields suggested is going to require some changes to the way data flows between Sopel and Rule, because currently Sopel calls boolean functions on Rule to determine if something should be rate-limited and then gets the associated message from another Rule function before calling notice()

@Exirel suggested the possibility of a RateLimitInfo object that could be passed across the class boundary, and I'm inclined to think that encapsulation of some sort may make sense here. Will keep thinking about it…

@dgw
Copy link
Member Author

dgw commented Mar 26, 2023

At the risk of sounding a little insane, because what I'm about to suggest can be seen as breaking the separation of concerns that the existing interface appears designed to enforce:
Why not have the get_*_rate_message() methods take advantage of the fact that they live in the object (Rule) that is also charged with hanging onto its own RuleMetrics for each scope (user, channel, global)?

The _metrics_nick, _metrics_sender, and _metrics_global fields live inside the Rule, as do the _user_rate_limit, _channel_rate_limit, and _global_rate_limit fields. The remaining time can be calculated from those, inside the message formatting method, without having to pass it back to the bot (forcing the bot to pass yet another value to the next method call).

Possible sticking point: The logic isn't super clear-cut because of checks like this one in RuleMetrics.is_limited():

if self.ended_at and self.started_at < self.ended_at:

Nonetheless, it's certainly possible to implement the time-related placeholders without modifying the data flow, if you'd like to explore that route instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants