diff options
| -rw-r--r-- | modules/line_handler/channel.py | 5 | ||||
| -rw-r--r-- | modules/line_handler/core.py | 20 | ||||
| -rw-r--r-- | src/IRCChannel.py | 41 |
3 files changed, 47 insertions, 19 deletions
diff --git a/modules/line_handler/channel.py b/modules/line_handler/channel.py index 759fdf45..716877b6 100644 --- a/modules/line_handler/channel.py +++ b/modules/line_handler/channel.py @@ -121,9 +121,8 @@ def handle_324(event): if event["args"][1] in event["server"].channels: channel = event["server"].channels.get(event["args"][1]) modes = event["args"][2] - for mode in modes[1:]: - if mode in event["server"].channel_modes: - channel.add_mode(mode) + args = event["args"][3:] + channel.parse_modes(modes, args[:]) def handle_329(event): channel = event["server"].channels.get(event["args"][1]) diff --git a/modules/line_handler/core.py b/modules/line_handler/core.py index b85a9677..979eaa31 100644 --- a/modules/line_handler/core.py +++ b/modules/line_handler/core.py @@ -80,22 +80,12 @@ def mode(events, event): is_channel = target[0] in event["server"].channel_types if is_channel: channel = event["server"].channels.get(target) + modes = event["args"][1] args = event["args"][2:] - _args = args[:] - modes = RE_MODES.findall(event["args"][1]) - for chunk in modes: - remove = chunk[0] == "-" - for mode in chunk[1:]: - if mode in event["server"].channel_modes: - channel.change_mode(remove, mode) - elif mode in event["server"].prefix_modes and len(args): - channel.change_mode(remove, mode, args.pop(0)) - elif (mode in event["server"].channel_list_modes or - mode in event["server"].channel_paramatered_modes): - args.pop(0) - elif not remove: - args.pop(0) - events.on("received.mode.channel").call(modes=modes, mode_args=_args, + + channel.parse_modes(modes, args[:]) + + events.on("received.mode.channel").call(modes=modes, mode_args=args, channel=channel, server=event["server"], user=user) elif event["server"].is_own_nickname(target): modes = event["args"][1] diff --git a/src/IRCChannel.py b/src/IRCChannel.py index 82f8468d..e195248b 100644 --- a/src/IRCChannel.py +++ b/src/IRCChannel.py @@ -1,7 +1,9 @@ -import typing, uuid +import re, typing, uuid from src import EventManager, IRCBot, IRCBuffer, IRCObject, IRCServer, IRCUser from src import utils +RE_MODES = re.compile(r"[-+]\w+") + class Channel(IRCObject.Object): name = "" def __init__(self, name: str, id, server: "IRCServer.Server", @@ -50,6 +52,26 @@ class Channel(IRCObject.Object): def has_user(self, user: IRCUser.User) -> bool: return user in self.users + def mode_str(self) -> str: + modes = [] # type: typing.List[typing.Tuple[str, typing.List[str]]] + # sorta alphanumerically by mode char + modes_iter = sorted(self.modes.items(), key=lambda mode: mode[0]) + + for mode, args in modes_iter: + # not list mode (e.g. +b) and not prefix mode (e.g. +o) + if (not mode in self.server.channel_list_modes and + not mode in self.server.prefix_modes): + args_list = typing.cast(typing.List[str], list(args)) + modes.append((mode, args_list)) + + # move modes with args to the front + modes.sort(key=lambda mode: not bool(mode[1])) + + out_modes = "".join(mode for mode, args in modes) + out_args = " ".join(args[0] for mode, args in modes if args) + + return "+%s%s" % (out_modes, " %s" % out_args if out_args else "") + def add_mode(self, mode: str, arg: str=None): if not mode in self.modes: self.modes[mode] = set([]) @@ -87,6 +109,23 @@ class Channel(IRCObject.Object): else: self.add_mode(mode, arg) + def parse_modes(self, modes: str, args: typing.List[str]): + for chunk in RE_MODES.findall(modes): + remove = chunk[0] == "-" + for mode in chunk[1:]: + if mode in self.server.channel_list_modes: + args.pop(0) + elif (mode in self.server.channel_paramatered_modes or + mode in self.server.prefix_modes): + self.change_mode(remove, mode, args.pop(0)) + elif mode in self.server.channel_setting_modes: + if remove: + self.change_mode(remove, mode) + else: + self.change_mode(remove, mode, args.pop(0)) + elif mode in self.server.channel_modes: + self.change_mode(remove, mode) + def set_setting(self, setting: str, value: typing.Any): self.bot.database.channel_settings.set(self.id, setting, value) def get_setting(self, setting: str, default: typing.Any=None |
