diff --git a/irc.py b/irc.py index 9c1e10c..6bd4d98 100644 --- a/irc.py +++ b/irc.py @@ -23,6 +23,11 @@ PchumLog = logging.getLogger('pchumLogger') # Python 3 QString = str +# Copied from pesterchum.py +CUSTOMBOTS = ["CALSPRITE", "RANDOMENCOUNTER"] +BOTNAMES = ["NICKSERV", "CHANSERV", "MEMOSERV", "OPERSERV", "HELPSERV", "HOSTSERV", "BOTSERV"] +BOTNAMES.extend(CUSTOMBOTS) + #if ostools.isOSXBundle(): # logging.basicConfig(level=logging.WARNING) #else: @@ -399,6 +404,33 @@ class PesterHandler(DefaultCommandHandler): if key == "mood": mood = Mood(int(value)) self.parent.moodUpdated.emit(nick, mood) + + def tagmsg(self, prefix, tags, *args): + PchumLog.info('TAGMSG: %s %s %s' % (prefix, tags, str(args))) + message_tags = tags[1:].split(';') + for m in message_tags: + if m.startswith("+pesterchum"): + # Pesterchum tag + try: + key, value = m.split('=') + except ValueError: + return + PchumLog.info('Pesterchum tag: %s=%s' % (key, value)) + # Uses PESTERCHUM: syntax? + if ((value.upper().startswith("BEGIN") == False) + & (value.upper().startswith("BLOCK") == False) + & (value.upper().startswith("CEASE") == False) + & (value.upper().startswith("TIME") == False)): + # Invalid syntax + PchumLog.warning("TAGMSG with invalid syntax.") + return + + # Process like it's a PESTERCHUM: message + # Easiest option since we gotta be backwards compatible anyway :"3 + msg = "PESTERCHUM:" + value + self.privmsg(prefix, args[0], msg) + + def privmsg(self, nick, chan, msg): handle = nick[0:nick.find("!")] @@ -496,6 +528,8 @@ class PesterHandler(DefaultCommandHandler): # Backwards compatible moods helpers.msg(self.client, "#pesterchum", "MOOD >%d" % (mymood)) + helpers.cap(self.client, "REQ", "message-tags") + def keyvalue(self, target, handle_us, handle_owner, key, visibility, *value): # The format of the METADATA server notication is: # METADATA @@ -734,6 +768,13 @@ class PesterHandler(DefaultCommandHandler): # Try to get mood via metadata get. # If it fails the old code is excecuted. + # If services/bot, assume mood 18. + for c in chums: + if c.handle.upper() in BOTNAMES: + print("True") + print(c.handle) + PchumLog.info("%s is a bot, setting mood to 18." % (c.handle)) + self.parent.moodUpdated.emit(c.handle, Mood(18)) # Wait for server to send welcome to verify RPL_ISUPPORT has been send. # Apparently 005 is send after 001 so nvm we gotta wait longer :"3 timeout = 0 diff --git a/oyoyo/client.py b/oyoyo/client.py index 34a3146..4992ad6 100644 --- a/oyoyo/client.py +++ b/oyoyo/client.py @@ -234,9 +234,13 @@ class IRCClient: for el in data: PchumLog.debug("el=%s, data=%s" % (el,data)) - prefix, command, args = parse_raw_irc_command(el) + tags, prefix, command, args = parse_raw_irc_command(el) try: - self.command_handler.run(command, prefix, *args) + # Only need tags with tagmsg + if command.upper() == "TAGMSG": + self.command_handler.run(command, prefix, tags, *args) + else: + self.command_handler.run(command, prefix, *args) except CommandError as e: PchumLog.debug("CommandError %s" % str(e)) diff --git a/oyoyo/helpers.py b/oyoyo/helpers.py index e991b6f..1012aee 100644 --- a/oyoyo/helpers.py +++ b/oyoyo/helpers.py @@ -71,6 +71,11 @@ def metadata(cli, target, subcommand, *params): # https://gist.github.com/k4bek4be/92c2937cefd49990fbebd001faf2b237 cli.send("METADATA", target, subcommand, *params) +def cap(cli, subcommand, *params): + # Capability Negotiation + # https://ircv3.net/specs/extensions/capability-negotiation.html + cli.send("CAP", subcommand, *params) + def msgrandom(cli, choices, dest, user=None): o = "%s: " % user if user else "" o += random.choice(choices) diff --git a/oyoyo/ircevents.py b/oyoyo/ircevents.py index 10dabd0..d4150ae 100644 --- a/oyoyo/ircevents.py +++ b/oyoyo/ircevents.py @@ -215,7 +215,8 @@ protocol_events = [ "quit", "invite", "pong", - "metadata" # Metadata specification + "metadata", # Metadata specification + "tagmsg", # IRCv3 message tags extension ] all_events = generated_events + protocol_events + list(numeric_events.values()) diff --git a/oyoyo/parse.py b/oyoyo/parse.py index 4edc6df..15525aa 100644 --- a/oyoyo/parse.py +++ b/oyoyo/parse.py @@ -26,6 +26,7 @@ logging.config.fileConfig(_datadir + "logging.ini") PchumLog = logging.getLogger('pchumLogger') def parse_raw_irc_command(element): + print(element) """ This function parses a raw irc command and returns a tuple of (prefix, command, args). @@ -43,6 +44,21 @@ def parse_raw_irc_command(element): NUL or CR or LF> ::= CR LF + """ + """ + When message-tags are enabled, the message pseudo-BNF, + as defined in RFC 1459, section 2.3.1 is extended as follows: + + ::= ['@' ] [':' ] [params] + ::= [';' ]* + ::= ['=' ] + ::= [ ] [ '/' ] + ::= '+' + ::= + ::= + ::= + + """ try: @@ -53,10 +69,18 @@ def parse_raw_irc_command(element): parts = element.strip().split(" ") if parts[0].startswith(':'): + tags = None prefix = parts[0][1:] command = parts[1] args = parts[2:] + elif parts[0].startswith('@'): + # Message tag + tags = parts[0] + prefix = parts[1][1:] + command = parts[2] + args = parts[3:] else: + tags = None prefix = None command = parts[0] args = parts[1:] @@ -76,7 +100,7 @@ def parse_raw_irc_command(element): args = args[:idx] + [" ".join(args[idx:])[1:]] break - return (prefix, command, args) + return (tags, prefix, command, args) def parse_nick(name):