PESTERCHUM: via TAGMSG (incl. Client Capability Negotiation + Message Tags)
This commit is contained in:
parent
91b09e270d
commit
979173c33d
5 changed files with 79 additions and 4 deletions
41
irc.py
41
irc.py
|
@ -23,6 +23,11 @@ PchumLog = logging.getLogger('pchumLogger')
|
||||||
# Python 3
|
# Python 3
|
||||||
QString = str
|
QString = str
|
||||||
|
|
||||||
|
# Copied from pesterchum.py
|
||||||
|
CUSTOMBOTS = ["CALSPRITE", "RANDOMENCOUNTER"]
|
||||||
|
BOTNAMES = ["NICKSERV", "CHANSERV", "MEMOSERV", "OPERSERV", "HELPSERV", "HOSTSERV", "BOTSERV"]
|
||||||
|
BOTNAMES.extend(CUSTOMBOTS)
|
||||||
|
|
||||||
#if ostools.isOSXBundle():
|
#if ostools.isOSXBundle():
|
||||||
# logging.basicConfig(level=logging.WARNING)
|
# logging.basicConfig(level=logging.WARNING)
|
||||||
#else:
|
#else:
|
||||||
|
@ -400,6 +405,33 @@ class PesterHandler(DefaultCommandHandler):
|
||||||
mood = Mood(int(value))
|
mood = Mood(int(value))
|
||||||
self.parent.moodUpdated.emit(nick, mood)
|
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):
|
def privmsg(self, nick, chan, msg):
|
||||||
handle = nick[0:nick.find("!")]
|
handle = nick[0:nick.find("!")]
|
||||||
if len(msg) == 0:
|
if len(msg) == 0:
|
||||||
|
@ -496,6 +528,8 @@ class PesterHandler(DefaultCommandHandler):
|
||||||
# Backwards compatible moods
|
# Backwards compatible moods
|
||||||
helpers.msg(self.client, "#pesterchum", "MOOD >%d" % (mymood))
|
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):
|
def keyvalue(self, target, handle_us, handle_owner, key, visibility, *value):
|
||||||
# The format of the METADATA server notication is:
|
# The format of the METADATA server notication is:
|
||||||
# METADATA <Target> <Key> <Visibility> <Value>
|
# METADATA <Target> <Key> <Visibility> <Value>
|
||||||
|
@ -734,6 +768,13 @@ class PesterHandler(DefaultCommandHandler):
|
||||||
# Try to get mood via metadata get.
|
# Try to get mood via metadata get.
|
||||||
# If it fails the old code is excecuted.
|
# 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.
|
# 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
|
# Apparently 005 is send after 001 so nvm we gotta wait longer :"3
|
||||||
timeout = 0
|
timeout = 0
|
||||||
|
|
|
@ -234,9 +234,13 @@ class IRCClient:
|
||||||
|
|
||||||
for el in data:
|
for el in data:
|
||||||
PchumLog.debug("el=%s, data=%s" % (el,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:
|
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:
|
except CommandError as e:
|
||||||
PchumLog.debug("CommandError %s" % str(e))
|
PchumLog.debug("CommandError %s" % str(e))
|
||||||
|
|
||||||
|
|
|
@ -71,6 +71,11 @@ def metadata(cli, target, subcommand, *params):
|
||||||
# https://gist.github.com/k4bek4be/92c2937cefd49990fbebd001faf2b237
|
# https://gist.github.com/k4bek4be/92c2937cefd49990fbebd001faf2b237
|
||||||
cli.send("METADATA", target, subcommand, *params)
|
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):
|
def msgrandom(cli, choices, dest, user=None):
|
||||||
o = "%s: " % user if user else ""
|
o = "%s: " % user if user else ""
|
||||||
o += random.choice(choices)
|
o += random.choice(choices)
|
||||||
|
|
|
@ -215,7 +215,8 @@ protocol_events = [
|
||||||
"quit",
|
"quit",
|
||||||
"invite",
|
"invite",
|
||||||
"pong",
|
"pong",
|
||||||
"metadata" # Metadata specification
|
"metadata", # Metadata specification
|
||||||
|
"tagmsg", # IRCv3 message tags extension
|
||||||
]
|
]
|
||||||
|
|
||||||
all_events = generated_events + protocol_events + list(numeric_events.values())
|
all_events = generated_events + protocol_events + list(numeric_events.values())
|
||||||
|
|
|
@ -26,6 +26,7 @@ logging.config.fileConfig(_datadir + "logging.ini")
|
||||||
PchumLog = logging.getLogger('pchumLogger')
|
PchumLog = logging.getLogger('pchumLogger')
|
||||||
|
|
||||||
def parse_raw_irc_command(element):
|
def parse_raw_irc_command(element):
|
||||||
|
print(element)
|
||||||
"""
|
"""
|
||||||
This function parses a raw irc command and returns a tuple
|
This function parses a raw irc command and returns a tuple
|
||||||
of (prefix, command, args).
|
of (prefix, command, args).
|
||||||
|
@ -43,6 +44,21 @@ def parse_raw_irc_command(element):
|
||||||
NUL or CR or LF>
|
NUL or CR or LF>
|
||||||
|
|
||||||
<crlf> ::= CR 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:
|
try:
|
||||||
|
@ -53,10 +69,18 @@ def parse_raw_irc_command(element):
|
||||||
|
|
||||||
parts = element.strip().split(" ")
|
parts = element.strip().split(" ")
|
||||||
if parts[0].startswith(':'):
|
if parts[0].startswith(':'):
|
||||||
|
tags = None
|
||||||
prefix = parts[0][1:]
|
prefix = parts[0][1:]
|
||||||
command = parts[1]
|
command = parts[1]
|
||||||
args = parts[2:]
|
args = parts[2:]
|
||||||
|
elif parts[0].startswith('@'):
|
||||||
|
# Message tag
|
||||||
|
tags = parts[0]
|
||||||
|
prefix = parts[1][1:]
|
||||||
|
command = parts[2]
|
||||||
|
args = parts[3:]
|
||||||
else:
|
else:
|
||||||
|
tags = None
|
||||||
prefix = None
|
prefix = None
|
||||||
command = parts[0]
|
command = parts[0]
|
||||||
args = parts[1:]
|
args = parts[1:]
|
||||||
|
@ -76,7 +100,7 @@ def parse_raw_irc_command(element):
|
||||||
args = args[:idx] + [" ".join(args[idx:])[1:]]
|
args = args[:idx] + [" ".join(args[idx:])[1:]]
|
||||||
break
|
break
|
||||||
|
|
||||||
return (prefix, command, args)
|
return (tags, prefix, command, args)
|
||||||
|
|
||||||
|
|
||||||
def parse_nick(name):
|
def parse_nick(name):
|
||||||
|
|
Loading…
Reference in a new issue