PESTERCHUM: via TAGMSG (incl. Client Capability Negotiation + Message Tags)

This commit is contained in:
Dpeta 2022-06-06 02:05:00 +02:00
parent 91b09e270d
commit 979173c33d
5 changed files with 79 additions and 4 deletions

41
irc.py
View file

@ -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 <Target> <Key> <Visibility> <Value>
@ -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

View file

@ -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))

View file

@ -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)

View file

@ -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())

View file

@ -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>
<crlf> ::= CR LF
"""
"""
When message-tags are enabled, the message pseudo-BNF,
as defined in RFC 1459, section 2.3.1 is extended as follows:
<message> ::= ['@' <tags> <SPACE>] [':' <prefix> <SPACE> ] <command> [params] <crlf>
<tags> ::= <tag> [';' <tag>]*
<tag> ::= <key> ['=' <escaped_value>]
<key> ::= [ <client_prefix> ] [ <vendor> '/' ] <key_name>
<client_prefix> ::= '+'
<key_name> ::= <non-empty sequence of ascii letters, digits, hyphens ('-')>
<escaped_value> ::= <sequence of zero or more utf8 characters except NUL, CR, LF, semicolon (`;`) and SPACE>
<vendor> ::= <host>
"""
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):