Delay some channel handling operations
Specifically, the mode handling and the end of list modes are delayed until the end of the WHO reply from the server. When the end of the WHO reply is received, all queued operations on the channel, if any, are triggered at once in the form of relevant events.
This commit is contained in:
parent
b180f99051
commit
074548813f
@ -67,6 +67,7 @@ class Channel(IRCContext):
|
|||||||
self.modes = {}
|
self.modes = {}
|
||||||
self.timestamp = None
|
self.timestamp = None
|
||||||
self.state = _States.NotJoined
|
self.state = _States.NotJoined
|
||||||
|
self._pending = []
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
self.users.clear()
|
self.users.clear()
|
||||||
@ -81,6 +82,12 @@ class Channel(IRCContext):
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "{self.__class__.__name__}({self.name!r})".format(self=self)
|
return "{self.__class__.__name__}({self.name!r})".format(self=self)
|
||||||
|
|
||||||
|
def queue(self, name, params, args):
|
||||||
|
if self._pending is None:
|
||||||
|
Event(name, params).dispatch(*args)
|
||||||
|
else:
|
||||||
|
self._pending.append((name, params, args))
|
||||||
|
|
||||||
def join(self, key=""):
|
def join(self, key=""):
|
||||||
if self.state in (_States.NotJoined, _States.Left):
|
if self.state in (_States.NotJoined, _States.Left):
|
||||||
self.state = _States.PendingJoin
|
self.state = _States.PendingJoin
|
||||||
@ -151,7 +158,7 @@ class Channel(IRCContext):
|
|||||||
|
|
||||||
self.client.send("MODE", self.name, "".join(final))
|
self.client.send("MODE", self.name, "".join(final))
|
||||||
|
|
||||||
def update_modes(self, rawnick, mode, targets):
|
def update_modes(self, actor, mode, targets):
|
||||||
"""Update the channel's mode registry with the new modes.
|
"""Update the channel's mode registry with the new modes.
|
||||||
|
|
||||||
This is called whenever a MODE event is received. All of the
|
This is called whenever a MODE event is received. All of the
|
||||||
@ -184,7 +191,7 @@ class Channel(IRCContext):
|
|||||||
elif c in list_modes: # stuff like bans, quiets, and ban and invite exempts
|
elif c in list_modes: # stuff like bans, quiets, and ban and invite exempts
|
||||||
if c not in self.modes:
|
if c not in self.modes:
|
||||||
self.modes[c] = {}
|
self.modes[c] = {}
|
||||||
self.modes[c][targets[i]] = (rawnick, set_time)
|
self.modes[c][targets[i]] = (actor.rawnick, set_time)
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
22
src/hooks.py
22
src/hooks.py
@ -6,7 +6,7 @@ further in the relevant hook functions.
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from src.decorators import hook
|
from src.decorators import event_listener, hook
|
||||||
from src.context import Features
|
from src.context import Features
|
||||||
from src.events import Event
|
from src.events import Event
|
||||||
from src.logger import plog
|
from src.logger import plog
|
||||||
@ -144,6 +144,16 @@ def end_who(cli, bot_server, bot_nick, target, rest):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
chan = channels.get(target)
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
if chan._pending is not None:
|
||||||
|
for name, params, args in chan._pending:
|
||||||
|
Event(name, params).dispatch(*args)
|
||||||
|
chan._pending = None
|
||||||
|
|
||||||
Event("who_end", {}).dispatch(var, target)
|
Event("who_end", {}).dispatch(var, target)
|
||||||
|
|
||||||
### Server PING handling
|
### Server PING handling
|
||||||
@ -278,9 +288,13 @@ def mode_change(cli, rawnick, chan, mode, *targets):
|
|||||||
return
|
return
|
||||||
|
|
||||||
target = channels.add(chan, cli)
|
target = channels.add(chan, cli)
|
||||||
target.update_modes(rawnick, mode, targets)
|
target.queue("mode_change", {"mode": mode, "targets": targets}, (var, actor, target))
|
||||||
|
|
||||||
Event("mode_change", {}).dispatch(var, actor, target)
|
@event_listener("mode_change", 0) # This should fire before anything else!
|
||||||
|
def apply_mode_changes(evt, var, actor, target):
|
||||||
|
"""Apply all mode changes before any other event."""
|
||||||
|
|
||||||
|
target.update_modes(actor, evt.data.pop("mode"), evt.data.pop("targets"))
|
||||||
|
|
||||||
### List modes handling (bans, quiets, ban and invite exempts)
|
### List modes handling (bans, quiets, ban and invite exempts)
|
||||||
|
|
||||||
@ -369,7 +383,7 @@ def handle_endlistmode(cli, chan, mode):
|
|||||||
"""Handle the end of a list mode listing."""
|
"""Handle the end of a list mode listing."""
|
||||||
|
|
||||||
ch = channels.add(chan, cli)
|
ch = channels.add(chan, cli)
|
||||||
Event("end_listmode", {}).dispatch(var, ch, mode)
|
ch.queue("end_listmode", {}, (var, ch, mode))
|
||||||
|
|
||||||
@hook("endofbanlist")
|
@hook("endofbanlist")
|
||||||
def end_banlist(cli, server, bot_nick, chan, message):
|
def end_banlist(cli, server, bot_nick, chan, message):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user