-
-
Notifications
You must be signed in to change notification settings - Fork 409
Description
Accidentally submitted the initial issue with only a title… Gotta be careful with that gh CLI.
I was testing some tweaks to #2676 and noticed another little bug in WHO processing, different from #2675: Sopel can theoretically add a channel to bot.channels that it hasn't joined, if the server chooses an arbitrary non-secret channel to put in RPL_WHOREPLY instead of the * placeholder.
Since coretasks can't tell that a RPL_WHOREPLY was initiated by other code, it'll just add that channel to bot.channels—and then Sopel will start periodically sending WHOs for that channel via _periodic_send_who(). (The server might just send back an empty list for channels Sopel hasn't joined, but it still takes up an interval slot that could be used for a channel Sopel cares about.)
Additionally, I have raw logs of at least one IRC network sending back a non-common channel after Sopel sent WHO dgw (through the admin plugin's .raw command), despite being in a common channel. It isn't consistent, but it does happen:
# SopelTest is not joined to ##linux, but:
2025-06-10 18:57:41,232 >> 'WHO dgw\r\n'
2025-06-10 18:57:41,266 << ':irc.rizon.life 352 SopelTest ##linux dgw Portal.desu.yo * dgw Hr*&@ :0 dgw\r\n'
2025-06-10 18:57:41,268 << ':irc.rizon.life 315 SopelTest dgw :End of /WHO list.\r\n'
----
# debug check using sopel-ipython console
[2025-06-10 18:58:00,123] asyncio DEBUG - Using selector: EpollSelector
In [1]: bot.channels
Out[1]:
{Identifier('#my_test_channel'): <sopel.tools.target.Channel at 0x7f3567142da0>,
Identifier('##linux'): <sopel.tools.target.Channel at 0x7f356706fbe0>}
Proposed solution
Sopel should not "learn" new channels from WHO or WHOX replies at all. It should ignore user privilege prefixes for channels that aren't already in bot.channels, and rely on track_join() to create the channel when Sopel itself joins a new channel.
This is slightly related to #2562, which is another case where RPL_WHOREPLY data doesn't match up with the actual state (in that case, because the IRCd may omit optional Flags from the response).
It's also related to the same IRC conversation with dyno10 last month that spawned #2675 re: the * placeholder; I just didn't dive far enough in at the time to find this edge case.