Mode mode (and mode arg) parsing to IRCChannel.py, add IRCChannel.mode_str

This commit is contained in:
jesopo 2019-06-13 11:53:47 +01:00
parent 675c510223
commit 795f6afbeb
3 changed files with 47 additions and 19 deletions

View file

@ -121,9 +121,8 @@ def handle_324(event):
if event["args"][1] in event["server"].channels: if event["args"][1] in event["server"].channels:
channel = event["server"].channels.get(event["args"][1]) channel = event["server"].channels.get(event["args"][1])
modes = event["args"][2] modes = event["args"][2]
for mode in modes[1:]: args = event["args"][3:]
if mode in event["server"].channel_modes: channel.parse_modes(modes, args[:])
channel.add_mode(mode)
def handle_329(event): def handle_329(event):
channel = event["server"].channels.get(event["args"][1]) channel = event["server"].channels.get(event["args"][1])

View file

@ -80,22 +80,12 @@ def mode(events, event):
is_channel = target[0] in event["server"].channel_types is_channel = target[0] in event["server"].channel_types
if is_channel: if is_channel:
channel = event["server"].channels.get(target) channel = event["server"].channels.get(target)
modes = event["args"][1]
args = event["args"][2:] args = event["args"][2:]
_args = args[:]
modes = RE_MODES.findall(event["args"][1]) channel.parse_modes(modes, args[:])
for chunk in modes:
remove = chunk[0] == "-" events.on("received.mode.channel").call(modes=modes, mode_args=args,
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=channel, server=event["server"], user=user) channel=channel, server=event["server"], user=user)
elif event["server"].is_own_nickname(target): elif event["server"].is_own_nickname(target):
modes = event["args"][1] modes = event["args"][1]

View file

@ -1,7 +1,9 @@
import typing, uuid import re, typing, uuid
from src import EventManager, IRCBot, IRCBuffer, IRCObject, IRCServer, IRCUser from src import EventManager, IRCBot, IRCBuffer, IRCObject, IRCServer, IRCUser
from src import utils from src import utils
RE_MODES = re.compile(r"[-+]\w+")
class Channel(IRCObject.Object): class Channel(IRCObject.Object):
name = "" name = ""
def __init__(self, name: str, id, server: "IRCServer.Server", 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: def has_user(self, user: IRCUser.User) -> bool:
return user in self.users 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): def add_mode(self, mode: str, arg: str=None):
if not mode in self.modes: if not mode in self.modes:
self.modes[mode] = set([]) self.modes[mode] = set([])
@ -87,6 +109,23 @@ class Channel(IRCObject.Object):
else: else:
self.add_mode(mode, arg) 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): def set_setting(self, setting: str, value: typing.Any):
self.bot.database.channel_settings.set(self.id, setting, value) self.bot.database.channel_settings.set(self.id, setting, value)
def get_setting(self, setting: str, default: typing.Any=None def get_setting(self, setting: str, default: typing.Any=None