diff options
| author | 2019-02-22 11:23:36 +0000 | |
|---|---|---|
| committer | 2019-02-22 11:23:36 +0000 | |
| commit | 47c2cbb0fa93e143c6add4cf1eb4012bbc37f7b2 (patch) | |
| tree | 46b13e38f6f22050db75c6ba65221b3034afda84 /modules/line_handler | |
| parent | Remove unused `threading` import in line_handler.py (diff) | |
| signature | ||
Split line_handler.py out in to different files for different categories
Diffstat (limited to 'modules/line_handler')
| -rw-r--r-- | modules/line_handler/__init__.py | 257 | ||||
| -rw-r--r-- | modules/line_handler/channel.py | 159 | ||||
| -rw-r--r-- | modules/line_handler/core.py | 134 | ||||
| -rw-r--r-- | modules/line_handler/ircv3.py | 74 | ||||
| -rw-r--r-- | modules/line_handler/message.py | 168 | ||||
| -rw-r--r-- | modules/line_handler/user.py | 89 |
6 files changed, 881 insertions, 0 deletions
diff --git a/modules/line_handler/__init__.py b/modules/line_handler/__init__.py new file mode 100644 index 00000000..ef4e617b --- /dev/null +++ b/modules/line_handler/__init__.py @@ -0,0 +1,257 @@ +import enum +from src import ModuleManager, utils +from . import channel, core, ircv3, message, user + +LABELED_BATCH = { + "labeled-response": "label", + "draft/labeled-response": "draft/label" +} + +class Module(ModuleManager.BaseModule): + def _handle(self, server, line): + hooks = self.events.on("raw.received").on(line.command).get_hooks() + default_events = [] + for hook in hooks: + default_events.append(hook.kwargs.get("default_event", False)) + default_event = any(default_events) + + kwargs = {"args": line.args, "tags": line.tags, "server": server, + "prefix": line.prefix, "direction": utils.Direction.RECV} + + self.events.on("raw.received").on(line.command).call_unsafe(**kwargs) + if default_event or not hooks: + self.events.on("received").on(line.command).call(**kwargs) + + @utils.hook("raw.received") + def handle_raw(self, event): + line = utils.irc.parse_line(event["line"]) + if "batch" in line.tags and line.tags["batch"] in event[ + "server"].batches: + server.batches[tag["batch"]].lines.append(line) + else: + self._handle(event["server"], line) + + @utils.hook("raw.send") + def handle_send(self, event): + line = utils.irc.parse_line(event["line"]) + self.events.on("raw.send").on(line.command).call_unsafe( + args=line.args, tags=line.tags, server=event["server"], + direction=utils.Direction.SEND) + + # ping from the server + @utils.hook("raw.received.ping") + def ping(self, event): + core.ping(event) + + @utils.hook("raw.received.error") + def error(self, event): + self.log.error("ERROR received: %s", [event["args"][0]]) + @utils.hook("raw.received.fail") + def fail(self, event): + command = event["args"][0] + error_code = event["args"][1] + context = event["args"][2:-1] + description = event["args"][-1] + + self.log.warn("FAIL (%s %s) received: %s" % + (command, error_code, description)) + self.events.on("received.fail").call(command=command, + error_code=error_code, context=context, description=description) + + # first numeric line the server sends + @utils.hook("raw.received.001", default_event=True) + def handle_001(self, event): + core.handle_001(event) + + # server telling us what it supports + @utils.hook("raw.received.005") + def handle_005(self, event): + core.handle_005(self.events, event) + + # whois respose (nickname, username, realname, hostname) + @utils.hook("raw.received.311", default_event=True) + def handle_311(self, event): + user.handle_311(event) + + # on-join channel topic line + @utils.hook("raw.received.332") + def handle_332(self, event): + channels.handle_332(self.events, event) + + # channel topic changed + @utils.hook("raw.received.topic") + def topic(self, event): + channels.topic(self.events, event) + + # on-join channel topic set by/at + @utils.hook("raw.received.333") + def handle_333(self, event): + channel.handle_333(self.events, event) + + # /names response, also on-join user list + @utils.hook("raw.received.353", default_event=True) + def handle_353(self, event): + channel.handle_353(event) + + # on-join user list has finished + @utils.hook("raw.received.366", default_event=True) + def handle_366(self, event): + channel.handle_366(event) + + @utils.hook("raw.received.375") + def motd_start(self, event): + core.motd_start(event) + + @utils.hook("raw.received.372") + def motd_line(self, event): + core.motd_line(event) + + # on user joining channel + @utils.hook("raw.received.join") + def join(self, event): + channel.join(self.events, event) + + # on user parting channel + @utils.hook("raw.received.part") + def part(self, event): + channel.part(self.events, event) + + # unknown command sent by us, oops! + @utils.hook("raw.received.421", default_event=True) + def handle_421(self, event): + self.bot.log.warn("We sent an unknown command: %s", [event["args"][1]]) + + # a user has disconnected! + @utils.hook("raw.received.quit") + @utils.hook("raw.send.quit") + def quit(self, event): + user.quit(self.events, event) + + # the server is telling us about its capabilities! + @utils.hook("raw.received.cap") + def cap(self, event): + ircv3.cap(self.events, event) + + # the server is asking for authentication + @utils.hook("raw.received.authenticate") + def authenticate(self, event): + ircv3.authenticate(self.events, event) + + # someone has changed their nickname + @utils.hook("raw.received.nick") + def nick(self, event): + user.nick(self.events, event) + + # something's mode has changed + @utils.hook("raw.received.mode") + def mode(self, event): + core.mode(self.events, event) + + # someone (maybe me!) has been invited somewhere + @utils.hook("raw.received.invite") + def invite(self, event): + core.invite(self.events, event) + + # we've received/sent a message + @utils.hook("raw.received.privmsg") + @utils.hook("raw.send.privmsg") + def privmsg(self, event): + message.privmsg(self.events, event) + + # we've received/sent a notice + @utils.hook("raw.received.notice") + @utils.hook("raw.send.notice") + def notice(self, event): + message.notice(self.events, event) + + # IRCv3 TAGMSG, used to send tags without any other information + @utils.hook("raw.received.tagmsg") + def tagmsg(self, event): + message.tagmsg(self.events, event) + + # IRCv3 AWAY, used to notify us that a client we can see has changed /away + @utils.hook("raw.received.away") + def away(self, event): + user.away(self.events, event) + + @utils.hook("raw.received.batch") + def batch(self, event): + identifier = event["args"][0] + modifier, identifier = identifier[0], identifier[1:] + batch_type = event["args"][1] + + if modifier == "+": + event["server"].batches[identifier] = utils.irc.IRCRecvBatch( + identifier, batch_type, event["tags"]) + else: + batch = event["server"].batches[identifier] + del event["server"].batches[identifier] + + add_tags = {} + if batch.type in LABELED_BATCH.keys(): + tag_name = LABELED_BATCH[batch.type] + add_tags[tag_name] = batch.tags[tag_name] + + for line in batch.lines: + if add_tags: + line.tags.update(add_tags) + self._handle(line) + + # IRCv3 CHGHOST, a user's username and/or hostname has changed + @utils.hook("raw.received.chghost") + def chghost(self, event): + user.chghost(event) + + # IRCv3 SETNAME, to change a user's realname + @utils.hook("raw.received.setname") + def setname(self, event): + user.setname(event) + + @utils.hook("raw.received.account") + def account(self, event): + user.account(self.events, event) + + # response to a WHO command for user information + @utils.hook("raw.received.352", default_event=True) + def handle_352(self, event): + core.handle_352(event) + + # response to a WHOX command for user information, including account name + @utils.hook("raw.received.354", default_event=True) + def handle_354(self, event): + core.handle_354(event) + + + # response to an empty mode command + @utils.hook("raw.received.324", default_event=True) + def handle_324(self, event): + channel.handle_324(event) + + # channel creation unix timestamp + @utils.hook("raw.received.329", default_event=True) + def handle_329(self, event): + channel.handle_329(event) + + # nickname already in use + @utils.hook("raw.received.433", default_event=True) + def handle_433(self, event): + core.handle_433(event) + + # we need a registered nickname for this channel + @utils.hook("raw.received.477", default_event=True) + def handle_477(self, event): + channel_name = event["server"].irc_lower(event["args"][1]) + if channel_name in event["server"].channels: + key = event["server"].attempted_join[channel_name] + self.timers.add("rejoin", 5, channel_name=channe_name, key=key, + server_id=event["server"].id) + + # someone's been kicked from a channel + @utils.hook("raw.received.kick") + def kick(self, event): + channel.kick(self.events, event) + + # a channel has been renamed + @utils.hook("raw.received.rename") + def rename(self, event): + channel.rename(self.events, event) diff --git a/modules/line_handler/channel.py b/modules/line_handler/channel.py new file mode 100644 index 00000000..80f42aaa --- /dev/null +++ b/modules/line_handler/channel.py @@ -0,0 +1,159 @@ +from src import utils + +def handle_332(events, event): + channel = event["server"].channels.get(event["args"][1]) + topic = event["args"].get(2) + channel.set_topic(topic) + events.on("received.332").call(channel=channel, server=event["server"], + topic=topic) + +def topic(events, event): + user = event["server"].get_user(event["prefix"].nickname) + channel = event["server"].channels.get(event["args"][0]) + topic = event["args"].get(1) + channel.set_topic(topic) + events.on("received.topic", channel=channel, server=event["server"], + topic=topic, user=user) + +def handle_333(events, event): + channel = event["server"].channels.get(event["args"][1]) + + topic_setter_hostmask = event["args"][2] + topic_setter = utils.irc.seperate_hostmask(topic_setter_hostmask) + topic_time = int(event["args"][3]) if event["args"][3].isdigit() else None + + channel.set_topic_setter(topic_setter.nickname, topic_setter.username, + topic_setter.hostname) + channel.set_topic_time(topic_time) + events.on("received.333", channel=channel, setter=topic_setter.nickname, + set_at=topic_time, server=event["server"]) + +def handle_353(event): + channel = event["server"].channels.get(event["args"][2]) + nicknames = event["args"].get(3).split() + for nickname in nicknames: + modes = set([]) + + while nickname[0] in event["server"].prefix_symbols: + modes.add(event["server"].prefix_symbols[nickname[0]]) + nickname = nickname[1:] + + if "userhost-in-names" in event["server"].agreed_capabilities: + hostmask = utils.irc.seperate_hostmask(nickname) + nickname = hostmask.nickname + user = event["server"].get_user(hostmask.nickname) + user.username = hostmask.username + user.hostname = hostmask.hostname + else: + user = event["server"].get_user(nickname) + user.join_channel(channel) + channel.add_user(user) + + for mode in modes: + channel.add_mode(mode, nickname) + +def handle_366(event): + event["server"].send_whox(event["args"][1], "n", "ahnrtu", "111") + +def join(events, event): + account = None + realname = None + channel_name = event["args"][0] + + if len(event["args"]) == 3: + if not event["args"][1] == "*": + account = event["args"][1] + realname = event["args"][2] + + if not event["server"].is_own_nickname(event["prefix"].nickname): + channel = event["server"].channels.get(channel_name) + user = event["server"].get_user(event["prefix"].nickname) + if not user.username and not user.hostname: + user.username = event["prefix"].username + user.hostname = event["prefix"].hostname + + if account: + user.identified_account = account + user.identified_account_id = event["server"].get_user( + account).get_id() + if realname: + user.realname = realname + + channel.add_user(user) + user.join_channel(channel) + events.on("received.join", channel=channel, user=user, + server=event["server"], account=account, realname=realname) + else: + channel = event["server"].channels.add(channel_name) + if channel.name in event["server"].attempted_join: + del event["server"].attempted_join[channel.name] + events.on("self.join").call(channel=channel, server=event["server"], + account=account, realname=realname) + channel.send_mode() + +def part(events, event): + channel = event["server"].channels.get(event["args"][0]) + reason = event["args"].get(1) + + if not event["server"].is_own_nickname(event["prefix"].nickname): + user = event["server"].get_user(event["prefix"].nickname) + + events.on("received.part", channel=channel, reason=reason, user=user, + server=event["server"]) + + channel.remove_user(user) + user.part_channel(channel) + if not len(user.channels): + event["server"].remove_user(user) + else: + events.on("self.part").call(channel=channel, reason=reason, + server=event["server"]) + event["server"].channels.remove(channel) + +def handle_324(event): + channel = event["server"].channels.get(event["args"][1]) + modes = event["args"][2] + if modes[0] == "+" and modes[1:]: + for mode in modes[1:]: + if mode in event["server"].channel_modes: + channel.add_mode(mode) + +def handle_329(event): + channel = event["server"].channels.get(event["args"][1]) + channel.creation_timestamp = int(event["args"][2]) + +def handle_477(timers, event): + channel_name = event["server"].irc_lower(event["args"][1]) + if channel_name in event["server"].channels: + key = event["server"].attempted_join[channel_name] + timers.add("rejoin", 5, channel_name=channe_name, key=key, + server_id=event["server"].id) + +def kick(events, event): + user = event["server"].get_user(event["prefix"].nickname) + target = event["args"][1] + channel = event["server"].channels.get(event["args"][0]) + reason = event["args"].get(2) + + if not event["server"].is_own_nickname(target): + target_user = event["server"].get_user(target) + events.on("received.kick").call(channel=channel, reason=reason, + target_user=target_user, user=user, server=event["server"]) + + channel.remove_user(target_user) + target_user.part_channel(channel) + if not len(target_user.channels): + event["server"].remove_user(target_user) + else: + event["server"].channels.remove(channel) + events.on("self.kick").call(channel=channel, reason=reason, user=user, + server=event["server"]) + +def rename(events, event): + old_name = event["args"][0] + new_name = event["args"][1] + channel = event["server"].channels.get(old_name) + + event["server"].channels.rename(old_name, new_name) + events.on("received.rename").call(channel=channel, old_name=old_name, + new_name=new_name, reason=event["args"].get(2), server=event["server"]) diff --git a/modules/line_handler/core.py b/modules/line_handler/core.py new file mode 100644 index 00000000..78a0c479 --- /dev/null +++ b/modules/line_handler/core.py @@ -0,0 +1,134 @@ +import codecs, re + +RE_ISUPPORT_ESCAPE = re.compile(r"\\x(\d\d)", re.I) +RE_MODES = re.compile(r"[-+]\w+") + +def ping(event): + event["server"].send_pong(event["args"][0]) + +def handle_001(event): + event["server"].socket.set_write_throttling(True) + event["server"].name = event["prefix"].hostmask + event["server"].set_own_nickname(event["args"][0]) + event["server"].send_whois(event["server"].nickname) + +def handle_005(events, event): + isupport_list = event["args"][1:-1] + isupport = {} + + for i, item in enumerate(isupport_list): + key, sep, value = item.partition("=") + if value: + for match in RE_ISUPPORT_ESCAPE.finditer(value): + char = codecs.decode(match.group(1), "hex").decode("ascii") + value.replace(match.group(0), char) + + if sep: + isupport[key] = value + else: + isupport[key] = None + event["server"].isupport.update(isupport) + + if "NAMESX" in isupport and not "multi-prefix" in event[ + "server"].agreed_capabilities: + event["server"].send("PROTOCTL NAMESX") + + if "PREFIX" in isupport: + modes, symbols = isupport["PREFIX"][1:].split(")", 1) + event["server"].prefix_symbols.clear() + event["server"].prefix_modes.clear() + for symbol, mode in zip(symbols, modes): + event["server"].prefix_symbols[symbol] = mode + event["server"].prefix_modes[mode] = symbol + + if "CHANMODES" in isupport: + modes = isupport["CHANMODES"].split(",", 3) + event["server"].channel_list_modes = list(modes[0]) + event["server"].channel_paramatered_modes = list(modes[1]) + event["server"].channel_setting_modes = list(modes[2]) + event["server"].channel_modes = list(modes[3]) + if "CHANTYPES" in isupport: + event["server"].channel_types = list(isupport["CHANTYPES"]) + if "CASEMAPPING" in isupport: + event["server"].case_mapping = isupport["CASEMAPPING"] + + events.on("received.005").call(isupport=isupport, + server=event["server"]) + +def motd_start(event): + event["server"].motd_lines.clear() + event["server"].motd_lines.append(event["args"][1]) +def motd_line(event): + event["server"].motd_lines.append(event["args"][1]) + +def mode(events, event): + user = event["server"].get_user(event["prefix"].nickname) + target = event["args"][0] + is_channel = target[0] in event["server"].channel_types + if is_channel: + channel = event["server"].channels.get(target) + remove = False + 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=channel, server=event["server"], user=user) + elif event["server"].is_own_nickname(target): + modes = RE_MODES.findall(event["args"][1]) + for chunk in modes: + remove = chunk[0] == "-" + for mode in chunk[1:]: + event["server"].change_own_mode(remove, mode) + events.on("self.mode").call(modes=modes, server=event["server"]) + event["server"].send_who(event["server"].nickname) + +def invite(events, event): + target_channel = event["args"][1] + user = event["server"].get_user(event["prefix"].nickname) + target_user = event["server"].get_user(event["args"][0]) + events.on("received.invite").call(user=user, target_channel=target_channel, + server=event["server"], target_user=target_user) + +def handle_352(event): + nickname = event["args"][5] + if not event["server"].is_own_nickname(nickname): + target = event["server"].get_user(nickname) + else: + target = event["server"] + target.username = event["args"][2] + target.hostname = event["args"][3] + +def handle_354(event): + if event["args"][1] == "111": + nickname = event["args"][4] + + if not event["server"].is_own_nickname(nickname): + target = event["server"].get_user(nickname) + + account = event["args"][5] + if not account == "0": + target.identified_account = account + else: + target.identified_account = None + else: + target = event["server"] + + target.username = event["args"][2] + target.hostname = event["args"][3] + target.realname = event["args"][6] + +def handle_433(event): + new_nick = "%s|" % event["server"].connection_params.nickname + event["server"].send_nick(new_nick) diff --git a/modules/line_handler/ircv3.py b/modules/line_handler/ircv3.py new file mode 100644 index 00000000..077b6ec3 --- /dev/null +++ b/modules/line_handler/ircv3.py @@ -0,0 +1,74 @@ +from src import utils + +CAPABILITIES = {"multi-prefix", "chghost", "invite-notify", "account-tag", + "account-notify", "extended-join", "away-notify", "userhost-in-names", + "draft/message-tags-0.2", "message-tags", "server-time", "cap-notify", + "batch", "draft/labeled-response", "draft/rename", "echo-message", + "draft/setname"} + +def _match_caps(capabilities): + return set(capabilities) & CAPABILITIES + +def cap(events, event): + capabilities = utils.parse.keyvalue(event["args"][-1]) + subcommand = event["args"][1].lower() + is_multiline = len(event["args"]) > 3 and event["args"][2] == "*" + + if subcommand == "ls": + event["server"].cap_started = True + event["server"].server_capabilities.update(capabilities) + if not is_multiline: + matched_caps = _match_caps( + list(event["server"].server_capabilities.keys())) + blacklisted_caps = event["server"].get_setting( + "blacklisted-caps", []) + matched_caps = list( + set(matched_caps)-set(blacklisted_caps)) + + event["server"].queue_capabilities(matched_caps) + + events.on("received.cap.ls").call( + capabilities=event["server"].server_capabilities, + server=event["server"]) + + if event["server"].has_capability_queue(): + event["server"].send_capability_queue() + else: + event["server"].send_capability_end() + elif subcommand == "new": + capabilities_keys = capabilities.keys() + event["server"].server_capabilities.update(capabilities) + + matched_caps = _match_caps(list(capabilities_keys)) + event["server"].queue_capabilities(matched_caps) + + events.on("received.cap.new").call(server=event["server"], + capabilities=capabilities) + + if event["server"].has_capability_queue(): + event["server"].send_capability_queue() + elif subcommand == "del": + for capability in capabilities.keys(): + event["server"].agreed_capabilities.discard(capability) + del event["server"].server_capabilities[capability] + + events.on("received.cap.del").call(server=event["server"], + capabilities=capabilities) + elif subcommand == "ack": + event["server"].agreed_capabilities.update(capabilities) + events.on("received.cap.ack").call(capabilities=capabilities, + server=event["server"]) + + if subcommand == "ack" or subcommand == "nak": + for capability in capabilities: + event["server"].requested_capabilities.remove(capability) + + if (event["server"].cap_started and + not event["server"].requested_capabilities and + not event["server"].waiting_for_capabilities()): + event["server"].cap_started = False + event["server"].send_capability_end() + +def authenticate(events, event): + events.on("received.authenticate").call(message=event["args"][0], + server=event["server"]) diff --git a/modules/line_handler/message.py b/modules/line_handler/message.py new file mode 100644 index 00000000..cdea31c0 --- /dev/null +++ b/modules/line_handler/message.py @@ -0,0 +1,168 @@ +from src import utils + +def _from_self(server, direction, prefix): + if direction == utils.Direction.SEND: + if "echo-message" in server.agreed_capabilities: + return None + else: + return True + else: + if prefix: + return server.is_own_nickname(prefix.nickname) + else: + return False + +def privmsg(events, event): + from_self = _from_self(event["server"], event["direction"], + event.get("prefix", None)) + if from_self == None: + return + + user = None + if "prefix" in event and not from_self: + user = event["server"].get_user(event["prefix"].nickname) + + message = event["args"][1] + target = event["args"][0] + + # strip prefix_symbols from the start of target, for when people use + # e.g. 'PRIVMSG +#channel :hi' which would send a message to only + # voiced-or-above users + statusmsg = [] + while target[0] in event["server"].prefix_symbols.keys(): + statusmsg.append(target[0]) + target = target[1:] + + channel = None + if target[0] in event["server"].channel_types: + if not target in event["server"].channels: + return + channel = event["server"].channels.get(target) + + action = False + event_type = "message" + ctcp_message = utils.irc.parse_ctcp(message) + if ctcp_message: + message = ctcp_message.message + event_type = "ctcp.%s" % ctcp_message.command + if ctcp_message.command == "ACTION": + action = True + message = ctcp_message.message + + if user and "account" in event["tags"]: + user.identified_account = event["tags"]["account"] + user.identified_account_id = event["server"].get_user( + event["tags"]["account"]).get_id() + + kwargs = {"message": message, "message_split": message.split(), + "server": event["server"], "tags": event["tags"], + "action": action} + + direction = "send" if from_self else "received" + context = "channel" if channel else "private" + hook = events.on(direction).on(event_type).on(context) + + user_nickname = None + if user: + user_nickname = None if from_self else user.nickname + + if channel: + hook.call(user=user, channel=channel, statusmsg=statusmsg, **kwargs) + channel.buffer.add_message(user_nickname, message, action, + event["tags"], user==None) + elif event["server"].is_own_nickname(target): + hook.call(user=user, **kwargs) + user.buffer.add_message(user_nickname, message, action, + event["tags"], False) + elif from_self: + # a message we've sent to a user + user = event["server"].get_user(target) + hook.call(user=user, **kwargs) + user.buffer.add_message(user_nickname, message, action, + event["tags"], True) + +def notice(events, event): + from_self = _from_self(event["server"], event["direction"], + event.get("prefix", None)) + if from_self == None: + return + + message = event["args"][1] + message_split = message.split(" ") + target = event["args"][0] + + if "prefix" in event and ( + not event["prefix"] or + not event["server"].name or + event["prefix"].hostmask == event["server"].name or + target == "*"): + if event["prefix"]: + event["server"].name = event["prefix"].hostmask + + events.on("received.server-notice").call(message=message, + message_split=message_split, server=event["server"]) + else: + user = None + if "prefix" in event and not from_self: + user = event["server"].get_user(event["prefix"].nickname) + + channel = None + if target[0] in event["server"].channel_types: + channel = event["server"].channels.get(target) + + direction = "send" if from_self else "received" + context = "channel" if channel else "private" + hook = events.on(direction).on("notice").on(context) + + user_nickname = None + if user: + user_nickname = None if from_self else user.nickname + + kwargs = {"message": message, "message_split": message_split, + "server": event["server"], "tags": event["tags"]} + + if channel: + hook.call(user=user, channel=channel, **kwargs) + channel.buffer.add_notice(user_nickname, message, event["tags"], + user==None) + elif event["server"].is_own_nickname(target): + hook.call(user=user, **kwargs) + user.buffer.add_notice(user_nickname, message, event["tags"], + False) + elif from_self: + # a notice we've sent to a user + user = event["server"].get_user(target) + hook.call(user=user, **kwargs) + user.buffer.add_notice(user_nickname, message, event["tags"], + True) + +# IRCv3 TAGMSG, used to send tags without any other information +@utils.hook("raw.received.tagmsg") +def tagmsg(events, event): + from_self = _from_self(event["server"], event["direction"], + event.get("prefix", None)) + if from_self == None: + return + + user = None + if "prefix" in event and not from_self: + user = event["server"].get_user(event["prefix"].nickname) + + target = event["args"][0] + channel = None + if target[0] in event["server"].channel_types: + channel = event["server"].channels.get(target) + + direction = "send" if from_self else "received" + context = "channel" if channel else "private" + hook = events.on(direction).on("tagmsg").on(context) + + kwargs = {"server": event["server"], "tags": event["tags"]} + + if channel: + hook.call(user=user, channel=channel, **kwargs) + elif event["server"].is_own_nickname(taget): + hook.call(user=user, **kwargs) + elif from_self: + user = event["server"].get_user(target) + hook.call(user=user, **kwargs) diff --git a/modules/line_handler/user.py b/modules/line_handler/user.py new file mode 100644 index 00000000..f9f14af6 --- /dev/null +++ b/modules/line_handler/user.py @@ -0,0 +1,89 @@ +from src import utils + +def handle_311(event): + nickname = event["args"][1] + if event["server"].is_own_nickname(nickname): + target = event["server"] + else: + target = event["server"].get_user(nickname) + target.username = event["args"][2] + target.hostname = event["args"][3] + target.realname = event["args"][4] + +def quit(events, event): + nickname = None + if event["direction"] == utils.Direction.RECV: + nickname = event["prefix"].nickname + reason = event["args"].get(0) + + if event["direction"] == utils.Direction.RECV: + nickname = event["prefix"].nickname + if (not event["server"].is_own_nickname(nickname) and + not event["prefix"].hostmask == "*"): + user = event["server"].get_user(nickname) + event["server"].remove_user(user) + events.on("received.quit").call(reason=reason, user=user, + server=event["server"]) + else: + event["server"].disconnect() + else: + events.on("send.quit").call(reason=reason, server=event["server"]) + +def nick(events, event): + new_nickname = event["args"].get(0) + if not event["server"].is_own_nickname(event["prefix"].nickname): + user = event["server"].get_user(event["prefix"].nickname) + old_nickname = user.nickname + user.set_nickname(new_nickname) + event["server"].change_user_nickname(old_nickname, new_nickname) + + events.on("received.nick").call(new_nickname=new_nickname, + old_nickname=old_nickname, user=user, server=event["server"]) + else: + old_nickname = event["server"].nickname + event["server"].set_own_nickname(new_nickname) + + events.on("self.nick").call(server=event["server"], + new_nickname=new_nickname, old_nickname=old_nickname) + +def away(events, event): + user = event["server"].get_user(event["prefix"].nickname) + message = event["args"].get(0) + if message: + user.away = True + events.on("received.away.on").call(user=user, server=event["server"], + message=message) + else: + user.away = False + events.on("received.away.off").call(user=user, server=event["server"]) + +def chghost(event): + nickname = event["prefix"].nickname + username = event["args"][0] + hostname = event["args"][1] + + if not event["server"].is_own_nickname(nickname): + target = event["server"].get_user(nickname) + else: + target = event["server"] + target.username = username + target.hostname = hostname + +def setname(event): + user = event["server"].get_user(event["prefix"].nickname) + user.realname = event["args"][0] + +def account(events, event): + user = event["server"].get_user(event["prefix"].nickname) + + if not event["args"][0] == "*": + user.identified_account = event["args"][0] + user.identified_account_id = event["server"].get_user( + event["args"][0]).get_id() + events.on("received.account.login").call(user=user, + server=event["server"], account=event["args"][0]) + else: + user.identified_account = None + user.identified_account_id = None + events.on("received.account.logout").call(user=user, + server=event["server"]) |
