3
0
mirror of https://github.com/jlu5/PyLink.git synced 2024-11-27 21:19:31 +01:00

protocols: continue removing to_lower() calls on channels (#372)

This commit is contained in:
James Lu 2017-08-07 21:54:33 -07:00
parent 29458c8e47
commit 9702030bf5
8 changed files with 39 additions and 45 deletions

View File

@ -601,7 +601,7 @@ class ClientbotWrapperProtocol(IRCCommonProtocol):
# <- :charybdis.midnight.vpn 353 ice = #test :ice @GL # <- :charybdis.midnight.vpn 353 ice = #test :ice @GL
# Mark "@"-type channels as secret automatically, per RFC2812. # Mark "@"-type channels as secret automatically, per RFC2812.
channel = self.to_lower(args[2]) channel = args[2]
if args[1] == '@': if args[1] == '@':
self.apply_modes(channel, [('+s', None)]) self.apply_modes(channel, [('+s', None)])
@ -720,7 +720,7 @@ class ClientbotWrapperProtocol(IRCCommonProtocol):
users = self.who_received.copy() users = self.who_received.copy()
self.who_received.clear() self.who_received.clear()
channel = self.to_lower(args[1]) channel = args[1]
c = self.channels[channel] c = self.channels[channel]
c.who_received = True c.who_received = True
@ -755,7 +755,7 @@ class ClientbotWrapperProtocol(IRCCommonProtocol):
Handles incoming JOINs. Handles incoming JOINs.
""" """
# <- :GL|!~GL@127.0.0.1 JOIN #whatever # <- :GL|!~GL@127.0.0.1 JOIN #whatever
channel = self.to_lower(args[0]) channel = args[0]
self.join(source, channel) self.join(source, channel)
return {'channel': channel, 'users': [source], 'modes': self.channels[channel].modes} return {'channel': channel, 'users': [source], 'modes': self.channels[channel].modes}
@ -765,7 +765,7 @@ class ClientbotWrapperProtocol(IRCCommonProtocol):
Handles incoming KICKs. Handles incoming KICKs.
""" """
# <- :GL!~gl@127.0.0.1 KICK #whatever GL| :xd # <- :GL!~gl@127.0.0.1 KICK #whatever GL| :xd
channel = self.to_lower(args[0]) channel = args[0]
target = self.nick_to_uid(args[1]) target = self.nick_to_uid(args[1])
try: try:
@ -805,7 +805,6 @@ class ClientbotWrapperProtocol(IRCCommonProtocol):
# <- :ice MODE ice :+Zi # <- :ice MODE ice :+Zi
target = args[0] target = args[0]
if utils.isChannel(target): if utils.isChannel(target):
target = self.to_lower(target)
oldobj = self.channels[target].deepcopy() oldobj = self.channels[target].deepcopy()
else: else:
target = self.nick_to_uid(target) target = self.nick_to_uid(target)
@ -829,7 +828,7 @@ class ClientbotWrapperProtocol(IRCCommonProtocol):
# -> MODE #test # -> MODE #test
# <- :midnight.vpn 324 GL #test +nt # <- :midnight.vpn 324 GL #test +nt
# <- :midnight.vpn 329 GL #test 1491773459 # <- :midnight.vpn 329 GL #test 1491773459
channel = self.to_lower(args[1]) channel = args[1]
modes = args[2:] modes = args[2:]
log.debug('(%s) Got RPL_CHANNELMODEIS (324) modes %s for %s', self.name, modes, channel) log.debug('(%s) Got RPL_CHANNELMODEIS (324) modes %s for %s', self.name, modes, channel)
changedmodes = self.parse_modes(channel, modes) changedmodes = self.parse_modes(channel, modes)
@ -837,7 +836,7 @@ class ClientbotWrapperProtocol(IRCCommonProtocol):
def handle_329(self, source, command, args): def handle_329(self, source, command, args):
"""Handles TS announcements via RPL_CREATIONTIME.""" """Handles TS announcements via RPL_CREATIONTIME."""
channel = self.to_lower(args[1]) channel = args[1]
ts = int(args[2]) ts = int(args[2])
self.channels[channel].ts = ts self.channels[channel].ts = ts
@ -900,11 +899,9 @@ class ClientbotWrapperProtocol(IRCCommonProtocol):
log.warning('(%s) Received %s to %s being routed the wrong way!', self.name, command, target) log.warning('(%s) Received %s to %s being routed the wrong way!', self.name, command, target)
return return
# We use lowercase channels internally. if not utils.isChannel(target):
if utils.isChannel(target):
target = self.to_lower(target)
else:
target = self.nick_to_uid(target) target = self.nick_to_uid(target)
if target: if target:
return {'target': target, 'text': args[1]} return {'target': target, 'text': args[1]}
handle_notice = handle_privmsg handle_notice = handle_privmsg

View File

@ -210,7 +210,7 @@ class HybridProtocol(TS6Protocol):
def handle_tburst(self, numeric, command, args): def handle_tburst(self, numeric, command, args):
"""Handles incoming topic burst (TBURST) commands.""" """Handles incoming topic burst (TBURST) commands."""
# <- :0UY TBURST 1459308205 #testchan 1459309379 dan!~d@localhost :sdf # <- :0UY TBURST 1459308205 #testchan 1459309379 dan!~d@localhost :sdf
channel = self.to_lower(args[1]) channel = args[1]
ts = args[2] ts = args[2]
setter = args[3] setter = args[3]
topic = args[-1] topic = args[-1]

View File

@ -207,7 +207,7 @@ class InspIRCdProtocol(TS6BaseProtocol):
self.apply_modes(target, modes) self.apply_modes(target, modes)
joinedmodes = self.join_modes(modes) joinedmodes = self.join_modes(modes)
if utils.isChannel(target): if utils.isChannel(target):
ts = ts or self.channels[self.to_lower(target)].ts ts = ts or self.channels[target].ts
self._send_with_prefix(numeric, 'FMODE %s %s %s' % (target, ts, joinedmodes)) self._send_with_prefix(numeric, 'FMODE %s %s %s' % (target, ts, joinedmodes))
else: else:
self._send_with_prefix(numeric, 'MODE %s %s' % (target, joinedmodes)) self._send_with_prefix(numeric, 'MODE %s %s' % (target, joinedmodes))
@ -526,7 +526,7 @@ class InspIRCdProtocol(TS6BaseProtocol):
def handle_fjoin(self, servernumeric, command, args): def handle_fjoin(self, servernumeric, command, args):
"""Handles incoming FJOIN commands (InspIRCd equivalent of JOIN/SJOIN).""" """Handles incoming FJOIN commands (InspIRCd equivalent of JOIN/SJOIN)."""
# :70M FJOIN #chat 1423790411 +AFPfjnt 6:5 7:5 9:5 :o,1SRAABIT4 v,1IOAAF53R <...> # :70M FJOIN #chat 1423790411 +AFPfjnt 6:5 7:5 9:5 :o,1SRAABIT4 v,1IOAAF53R <...>
channel = self.to_lower(args[0]) channel = args[0]
chandata = self.channels[channel].deepcopy() chandata = self.channels[channel].deepcopy()
# InspIRCd sends each channel's users in the form of 'modeprefix(es),UID' # InspIRCd sends each channel's users in the form of 'modeprefix(es),UID'
userlist = args[-1].split() userlist = args[-1].split()
@ -614,7 +614,7 @@ class InspIRCdProtocol(TS6BaseProtocol):
def handle_fmode(self, numeric, command, args): def handle_fmode(self, numeric, command, args):
"""Handles the FMODE command, used for channel mode changes.""" """Handles the FMODE command, used for channel mode changes."""
# <- :70MAAAAAA FMODE #chat 1433653462 +hhT 70MAAAAAA 70MAAAAAD # <- :70MAAAAAA FMODE #chat 1433653462 +hhT 70MAAAAAA 70MAAAAAD
channel = self.to_lower(args[0]) channel = args[0]
oldobj = self.channels[channel].deepcopy() oldobj = self.channels[channel].deepcopy()
modes = args[2:] modes = args[2:]
changedmodes = self.parse_modes(channel, modes) changedmodes = self.parse_modes(channel, modes)
@ -645,7 +645,7 @@ class InspIRCdProtocol(TS6BaseProtocol):
def handle_ftopic(self, numeric, command, args): def handle_ftopic(self, numeric, command, args):
"""Handles incoming FTOPIC (sets topic on burst).""" """Handles incoming FTOPIC (sets topic on burst)."""
# <- :70M FTOPIC #channel 1434510754 GLo|o|!GLolol@escape.the.dreamland.ca :Some channel topic # <- :70M FTOPIC #channel 1434510754 GLo|o|!GLolol@escape.the.dreamland.ca :Some channel topic
channel = self.to_lower(args[0]) channel = args[0]
ts = args[1] ts = args[1]
setter = args[2] setter = args[2]
topic = args[-1] topic = args[-1]
@ -659,7 +659,7 @@ class InspIRCdProtocol(TS6BaseProtocol):
def handle_knock(self, numeric, command, args): def handle_knock(self, numeric, command, args):
"""Handles channel KNOCKs.""" """Handles channel KNOCKs."""
# <- :70MAAAAAA ENCAP * KNOCK #blah :abcdefg # <- :70MAAAAAA ENCAP * KNOCK #blah :abcdefg
channel = self.to_lower(args[0]) channel = args[0]
text = args[1] text = args[1]
return {'channel': channel, 'text': text} return {'channel': channel, 'text': text}
@ -770,7 +770,7 @@ class InspIRCdProtocol(TS6BaseProtocol):
# ENCAP -> SAKICK args: ['#test', '0ALAAAAAB', 'test'] # ENCAP -> SAKICK args: ['#test', '0ALAAAAAB', 'test']
target = args[1] target = args[1]
channel = self.to_lower(args[0]) channel = args[0]
try: try:
reason = args[2] reason = args[2]
except IndexError: except IndexError:

View File

@ -450,8 +450,6 @@ class IRCS2SProtocol(IRCCommonProtocol):
if (not self.is_internal_client(source)) and (not self.is_internal_server(source)): if (not self.is_internal_client(source)) and (not self.is_internal_server(source)):
raise LookupError('No such PyLink client/server exists.') raise LookupError('No such PyLink client/server exists.')
target = self.to_lower(target)
self._send_with_prefix(source, 'TOPIC %s :%s' % (target, text)) self._send_with_prefix(source, 'TOPIC %s :%s' % (target, text))
self.channels[target].topic = text self.channels[target].topic = text
self.channels[target].topicset = True self.channels[target].topicset = True
@ -479,7 +477,7 @@ class IRCS2SProtocol(IRCCommonProtocol):
# Note that the target is a nickname, not a numeric. # Note that the target is a nickname, not a numeric.
target = self._get_UID(args[0]) target = self._get_UID(args[0])
channel = self.to_lower(args[1]) channel = args[1]
curtime = int(time.time()) curtime = int(time.time())
try: try:
@ -494,7 +492,7 @@ class IRCS2SProtocol(IRCCommonProtocol):
def handle_kick(self, source, command, args): def handle_kick(self, source, command, args):
"""Handles incoming KICKs.""" """Handles incoming KICKs."""
# :70MAAAAAA KICK #test 70MAAAAAA :some reason # :70MAAAAAA KICK #test 70MAAAAAA :some reason
channel = self.to_lower(args[0]) channel = args[0]
kicked = self._get_UID(args[1]) kicked = self._get_UID(args[1])
try: try:
@ -588,7 +586,6 @@ class IRCS2SProtocol(IRCCommonProtocol):
# <- ABAAA OM #test +h ABAAA # <- ABAAA OM #test +h ABAAA
target = self._get_UID(args[0]) target = self._get_UID(args[0])
if utils.isChannel(target): if utils.isChannel(target):
target = self.to_lower(target)
channeldata = self.channels[target].deepcopy() channeldata = self.channels[target].deepcopy()
else: else:
channeldata = None channeldata = None
@ -607,7 +604,7 @@ class IRCS2SProtocol(IRCCommonProtocol):
def handle_part(self, source, command, args): def handle_part(self, source, command, args):
"""Handles incoming PART commands.""" """Handles incoming PART commands."""
channels = self.to_lower(args[0]).split(',') channels = args[0].split(',')
for channel in channels.copy(): for channel in channels.copy():
if source not in channel: if source not in channel:
@ -655,7 +652,7 @@ class IRCS2SProtocol(IRCCommonProtocol):
# Note: don't mess with the case of the channel prefix, or ~#channel # Note: don't mess with the case of the channel prefix, or ~#channel
# messages will break on RFC1459 casemapping networks (it becomes ^#channel # messages will break on RFC1459 casemapping networks (it becomes ^#channel
# instead). # instead).
target = '#'.join((split_channel[0], self.to_lower(split_channel[1]))) target = '#'.join((split_channel[0], split_channel[1]))
log.debug('(%s) Normalizing channel target %s to %s', self.name, args[0], target) log.debug('(%s) Normalizing channel target %s to %s', self.name, args[0], target)
return {'target': target, 'text': args[1]} return {'target': target, 'text': args[1]}
@ -674,7 +671,7 @@ class IRCS2SProtocol(IRCCommonProtocol):
def handle_topic(self, numeric, command, args): def handle_topic(self, numeric, command, args):
"""Handles incoming TOPIC changes from clients.""" """Handles incoming TOPIC changes from clients."""
# <- :70MAAAAAA TOPIC #test :test # <- :70MAAAAAA TOPIC #test :test
channel = self.to_lower(args[0]) channel = args[0]
topic = args[1] topic = args[1]
oldtopic = self.channels[channel].topic oldtopic = self.channels[channel].topic

View File

@ -329,7 +329,7 @@ class NgIRCdProtocol(IRCS2SProtocol):
# CHANINFO <channel> +<modes> <key> <limit> <topic> # CHANINFO <channel> +<modes> <key> <limit> <topic>
# If there is no key, the key is "*". If there is no limit, the limit is "0". # If there is no key, the key is "*". If there is no limit, the limit is "0".
channel = self.to_lower(args[0]) channel = args[0]
# Get rid of +l and +k in the initial parsing; we handle that later by looking at the CHANINFO arguments # Get rid of +l and +k in the initial parsing; we handle that later by looking at the CHANINFO arguments
modes = self.parse_modes(channel, args[1].replace('l', '').replace('k', '')) modes = self.parse_modes(channel, args[1].replace('l', '').replace('k', ''))
@ -468,7 +468,7 @@ class NgIRCdProtocol(IRCS2SProtocol):
def handle_njoin(self, source, command, args): def handle_njoin(self, source, command, args):
# <- :ngircd.midnight.local NJOIN #test :tester,@%GL # <- :ngircd.midnight.local NJOIN #test :tester,@%GL
channel = self.to_lower(args[0]) channel = args[0]
chandata = self.channels[channel].deepcopy() chandata = self.channels[channel].deepcopy()
namelist = [] namelist = []

View File

@ -409,7 +409,7 @@ class P10Protocol(IRCS2SProtocol):
is_cmode = utils.isChannel(target) is_cmode = utils.isChannel(target)
if is_cmode: if is_cmode:
# Channel mode changes have a trailing TS. User mode changes do not. # Channel mode changes have a trailing TS. User mode changes do not.
cobj = self.channels[self.to_lower(target)] cobj = self.channels[target]
ts = ts or cobj.ts ts = ts or cobj.ts
# Prevent mode bounces by sending our mode through the server if # Prevent mode bounces by sending our mode through the server if
@ -1003,7 +1003,7 @@ class P10Protocol(IRCS2SProtocol):
# No useful data was sent, ignore. # No useful data was sent, ignore.
return return
channel = self.to_lower(args[0]) channel = args[0]
chandata = self.channels[channel].deepcopy() chandata = self.channels[channel].deepcopy()
bans = [] bans = []
@ -1101,7 +1101,7 @@ class P10Protocol(IRCS2SProtocol):
return {'channels': oldchans, 'text': 'Left all channels.', 'parse_as': 'PART'} return {'channels': oldchans, 'text': 'Left all channels.', 'parse_as': 'PART'}
else: else:
channel = self.to_lower(args[0]) channel = args[0]
if ts: # Only update TS if one was sent. if ts: # Only update TS if one was sent.
self.updateTS(source, channel, ts) self.updateTS(source, channel, ts)
@ -1123,7 +1123,7 @@ class P10Protocol(IRCS2SProtocol):
def handle_kick(self, source, command, args): def handle_kick(self, source, command, args):
"""Handles incoming KICKs.""" """Handles incoming KICKs."""
# <- ABAAA K #TEST AyAAA :PyLink-devel # <- ABAAA K #TEST AyAAA :PyLink-devel
channel = self.to_lower(args[0]) channel = args[0]
kicked = args[1] kicked = args[1]
self.handle_part(kicked, 'KICK', [channel, args[2]]) self.handle_part(kicked, 'KICK', [channel, args[2]])
@ -1137,7 +1137,7 @@ class P10Protocol(IRCS2SProtocol):
def handle_topic(self, source, command, args): def handle_topic(self, source, command, args):
"""Handles TOPIC changes.""" """Handles TOPIC changes."""
# <- ABAAA T #test GL!~gl@nefarious.midnight.vpn 1460852591 1460855795 :blah # <- ABAAA T #test GL!~gl@nefarious.midnight.vpn 1460852591 1460855795 :blah
channel = self.to_lower(args[0]) channel = args[0]
topic = args[-1] topic = args[-1]
oldtopic = self.channels[channel].topic oldtopic = self.channels[channel].topic
@ -1150,7 +1150,7 @@ class P10Protocol(IRCS2SProtocol):
def handle_clearmode(self, numeric, command, args): def handle_clearmode(self, numeric, command, args):
"""Handles CLEARMODE, which is used to clear a channel's modes.""" """Handles CLEARMODE, which is used to clear a channel's modes."""
# <- ABAAA CM #test ovpsmikbl # <- ABAAA CM #test ovpsmikbl
channel = self.to_lower(args[0]) channel = args[0]
modes = args[1] modes = args[1]
# Enumerate a list of our existing modes, including prefix modes. # Enumerate a list of our existing modes, including prefix modes.

View File

@ -178,7 +178,7 @@ class TS6Protocol(TS6BaseProtocol):
modes = list(modes) modes = list(modes)
if utils.isChannel(target): if utils.isChannel(target):
ts = ts or self.channels[self.to_lower(target)].ts ts = ts or self.channels[target].ts
# TMODE: # TMODE:
# parameters: channelTS, channel, cmode changes, opt. cmode parameters... # parameters: channelTS, channel, cmode changes, opt. cmode parameters...
@ -438,7 +438,7 @@ class TS6Protocol(TS6BaseProtocol):
"""Handles incoming SJOIN commands.""" """Handles incoming SJOIN commands."""
# parameters: channelTS, channel, simple modes, opt. mode parameters..., nicklist # parameters: channelTS, channel, simple modes, opt. mode parameters..., nicklist
# <- :0UY SJOIN 1451041566 #channel +nt :@0UYAAAAAB # <- :0UY SJOIN 1451041566 #channel +nt :@0UYAAAAAB
channel = self.to_lower(args[1]) channel = args[1]
chandata = self.channels[channel].deepcopy() chandata = self.channels[channel].deepcopy()
userlist = args[-1].split() userlist = args[-1].split()
@ -501,7 +501,7 @@ class TS6Protocol(TS6BaseProtocol):
self.users[numeric].channels.discard(channel) self.users[numeric].channels.discard(channel)
return {'channels': oldchans, 'text': 'Left all channels.', 'parse_as': 'PART'} return {'channels': oldchans, 'text': 'Left all channels.', 'parse_as': 'PART'}
else: else:
channel = self.to_lower(args[1]) channel = args[1]
self.updateTS(numeric, channel, ts) self.updateTS(numeric, channel, ts)
self.users[numeric].channels.add(channel) self.users[numeric].channels.add(channel)
@ -602,7 +602,7 @@ class TS6Protocol(TS6BaseProtocol):
"""Handles incoming TMODE commands (channel mode change).""" """Handles incoming TMODE commands (channel mode change)."""
# <- :42XAAAAAB TMODE 1437450768 #test -c+lkC 3 agte4 # <- :42XAAAAAB TMODE 1437450768 #test -c+lkC 3 agte4
# <- :0UYAAAAAD TMODE 0 #a +h 0UYAAAAAD # <- :0UYAAAAAD TMODE 0 #a +h 0UYAAAAAD
channel = self.to_lower(args[1]) channel = args[1]
oldobj = self.channels[channel].deepcopy() oldobj = self.channels[channel].deepcopy()
modes = args[2:] modes = args[2:]
changedmodes = self.parse_modes(channel, modes) changedmodes = self.parse_modes(channel, modes)
@ -614,7 +614,7 @@ class TS6Protocol(TS6BaseProtocol):
def handle_tb(self, numeric, command, args): def handle_tb(self, numeric, command, args):
"""Handles incoming topic burst (TB) commands.""" """Handles incoming topic burst (TB) commands."""
# <- :42X TB #chat 1467427448 GL!~gl@127.0.0.1 :test # <- :42X TB #chat 1467427448 GL!~gl@127.0.0.1 :test
channel = self.to_lower(args[0]) channel = args[0]
ts = args[1] ts = args[1]
setter = args[2] setter = args[2]
topic = args[-1] topic = args[-1]
@ -626,7 +626,7 @@ class TS6Protocol(TS6BaseProtocol):
"""Handles extended topic burst (ETB).""" """Handles extended topic burst (ETB)."""
# <- :00AAAAAAC ETB 0 #test 1470021157 GL :test | abcd # <- :00AAAAAAC ETB 0 #test 1470021157 GL :test | abcd
# Same as TB, with extra TS and extensions arguments. # Same as TB, with extra TS and extensions arguments.
channel = self.to_lower(args[1]) channel = args[1]
ts = args[2] ts = args[2]
setter = args[3] setter = args[3]
topic = args[-1] topic = args[-1]
@ -644,7 +644,7 @@ class TS6Protocol(TS6BaseProtocol):
"""Handles incoming BMASK commands (ban propagation on burst).""" """Handles incoming BMASK commands (ban propagation on burst)."""
# <- :42X BMASK 1424222769 #dev b :*!test@*.isp.net *!badident@* # <- :42X BMASK 1424222769 #dev b :*!test@*.isp.net *!badident@*
# This is used for propagating bans, not TMODE! # This is used for propagating bans, not TMODE!
channel = self.to_lower(args[1]) channel = args[1]
mode = args[2] mode = args[2]
ts = int(args[0]) ts = int(args[0])
modes = [] modes = []

View File

@ -217,7 +217,7 @@ class UnrealProtocol(TS6BaseProtocol):
modes[idx] = (mode[0], self._expandPUID(mode[1])) modes[idx] = (mode[0], self._expandPUID(mode[1]))
# The MODE command is used for channel mode changes only # The MODE command is used for channel mode changes only
ts = ts or self.channels[self.to_lower(target)].ts ts = ts or self.channels[target].ts
# 7 characters for "MODE", the space between MODE and the target, the space between the # 7 characters for "MODE", the space between MODE and the target, the space between the
# target and mode list, and the space between the mode list and TS. # target and mode list, and the space between the mode list and TS.
@ -559,7 +559,7 @@ class UnrealProtocol(TS6BaseProtocol):
"""Handles the UnrealIRCd SJOIN command.""" """Handles the UnrealIRCd SJOIN command."""
# <- :001 SJOIN 1444361345 #test :001AAAAAA @001AAAAAB +001AAAAAC # <- :001 SJOIN 1444361345 #test :001AAAAAA @001AAAAAB +001AAAAAC
# <- :001 SJOIN 1483250129 #services +nt :+001OR9V02 @*~001DH6901 &*!*@test "*!*@blah.blah '*!*@yes.no # <- :001 SJOIN 1483250129 #services +nt :+001OR9V02 @*~001DH6901 &*!*@test "*!*@blah.blah '*!*@yes.no
channel = self.to_lower(args[1]) channel = args[1]
chandata = self.channels[channel].deepcopy() chandata = self.channels[channel].deepcopy()
userlist = args[-1].split() userlist = args[-1].split()
@ -685,7 +685,7 @@ class UnrealProtocol(TS6BaseProtocol):
# Also, we need to get rid of that extra space following the +f argument. :| # Also, we need to get rid of that extra space following the +f argument. :|
if utils.isChannel(args[0]): if utils.isChannel(args[0]):
channel = self.to_lower(args[0]) channel = args[0]
oldobj = self.channels[channel].deepcopy() oldobj = self.channels[channel].deepcopy()
modes = [arg for arg in args[1:] if arg] # normalize whitespace modes = [arg for arg in args[1:] if arg] # normalize whitespace
@ -850,7 +850,7 @@ class UnrealProtocol(TS6BaseProtocol):
"""Handles the TOPIC command.""" """Handles the TOPIC command."""
# <- GL TOPIC #services GL 1444699395 :weeee # <- GL TOPIC #services GL 1444699395 :weeee
# <- TOPIC #services devel.relay 1452399682 :test # <- TOPIC #services devel.relay 1452399682 :test
channel = self.to_lower(args[0]) channel = args[0]
topic = args[-1] topic = args[-1]
setter = args[1] setter = args[1]
ts = args[2] ts = args[2]