Skip to content

Commit

Permalink
coretasks: fix bad WHO loop, update querytype
Browse files Browse the repository at this point in the history
who_reqs, which is used to track WHO requests to the server, had flipped
keys/values and was never getting cleared upon RPL_ENDOFWHO.
Eventually, this would lead to an endless loop while the bot tried to
get an unused "querytype" (randint) in order to track WHO replies.

This unneccessary loop/check to ensure unique values for the query type was
removed. A RPL_WHOREPLY includes the channel name in the response, so
confirming that the querytype for a channel matched is sufficient.

querytype should be unique _per purpose_. So, now a constant querytype
is used for `coretasks` WHO(X) requests.

Notes:
According to [the closest thing to] official specs:
ircv3/ircv3-specifications#81 (comment)
querytypes should be useful to:
> simplify scripting, in example one could pass a certain value in the query
> and have that value "signal" back what is to be done with those replies.

Also see:
https://github.com/quakenet/snircd/blob/17c92003d376c70db674821e92f2880ba1587132/doc/readme.who#L154
https://github.com/quakenet/snircd/blob/17c92003d376c70db674821e92f2880ba1587132/doc/readme.who#L105
  • Loading branch information
HumorBaby committed Jun 12, 2021
1 parent e2d8439 commit f11dca5
Showing 1 changed file with 14 additions and 21 deletions.
35 changes: 14 additions & 21 deletions sopel/coretasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import datetime
import functools
import logging
from random import randint
import re
import sys
import time
Expand All @@ -45,8 +44,13 @@

LOGGER = logging.getLogger(__name__)

CORE_QUERYTYPE = '999'
"""WHOX querytype to indicate requests/responses from coretasks.
Other plugins should use a different querytype.
"""

batched_caps = {}
who_reqs = {} # Keeps track of reqs coming from this plugin, rather than others


def setup(bot):
Expand Down Expand Up @@ -698,14 +702,12 @@ def _remove_from_channel(bot, nick, channel):
def _send_who(bot, channel):
if 'WHOX' in bot.isupport:
# WHOX syntax, see http://faerion.sourceforge.net/doc/irc/whox.var
# Needed for accounts in WHO replies. The random integer is a param
# to identify the reply as one from this command, because if someone
# else sent it, we have no fucking way to know what the format is.
rand = str(randint(0, 999))
while rand in who_reqs:
rand = str(randint(0, 999))
who_reqs[rand] = channel
bot.write(['WHO', channel, 'a%nuachtf,' + rand])
# Needed for accounts in WHO replies. The `CORE_QUERYTYPE` parameter
# for WHO is used to identify the reply from the server and confirm
# that it has the requested format. WHO replies with different
# querytypes in the response were initiated elsewhere and will be
# ignored.
bot.write(['WHO', channel, 'a%nuachtf,' + CORE_QUERYTYPE])
else:
# We might be on an old network, but we still care about keeping our
# user list updated
Expand Down Expand Up @@ -1243,8 +1245,9 @@ def account_notify(bot, trigger):
@plugin.priority('medium')
def recv_whox(bot, trigger):
"""Track ``WHO`` responses when ``WHOX`` is enabled."""
if len(trigger.args) < 2 or trigger.args[1] not in who_reqs:
if len(trigger.args) < 2 or trigger.args[1] != CORE_QUERYTYPE:
# Ignored, some plugin probably called WHO
LOGGER.debug("Ignoring WHO reply for channel '%s'; not queried by coretasks", trigger.args[1])
return
if len(trigger.args) != 8:
LOGGER.warning(
Expand Down Expand Up @@ -1307,16 +1310,6 @@ def recv_who(bot, trigger):
_record_who(bot, channel, user, host, nick, away=away, modes=modes)


@module.event(events.RPL_ENDOFWHO)
@plugin.thread(False)
@module.unblockable
@plugin.priority('medium')
def end_who(bot, trigger):
"""Handle the end of a response to a ``WHO`` command (if needed)."""
if 'WHOX' in bot.isupport:
who_reqs.pop(trigger.args[1], None)


@module.event('AWAY')
@module.thread(False)
@module.unblockable
Expand Down

0 comments on commit f11dca5

Please sign in to comment.