Message callbacks from protocol are now only on PRIVMSG. Callbacks receive the connection, message destination, nick, and message. Modified bot class's callback appropriately.

This commit is contained in:
Josh K 2018-09-05 07:27:44 -04:00
parent 7744e6c267
commit 84f11b9ddf
2 changed files with 41 additions and 47 deletions

67
bot.py
View File

@ -60,45 +60,39 @@ class Bot:
# create and connect all servers in config
for s in self.cfg['server']:
ncon = IrcProtocol( self._loop, self.cfg['user'] )
# add message callback to the connections
ncon.add_message_callback( self._on_irc_message )
# add priv message callback to the connections
ncon.add_message_callback( self._on_priv_message )
self._con.append( ncon )
self._loop.create_task( ncon.do_connect( s ) )
# called when a connected connection receives a full message
# passes the connection that sent and raw string message
# TODO: use a privmsg callback from protocol instead
def _on_irc_message( self, con, raw_msg ):
words = raw_msg.split()
if words[1] == 'PRIVMSG':
chan = words[2]
raw_user = words[0]
nick = raw_user[1 : words[0].find( '!' )]
msg = raw_msg[raw_msg.find( ':' , 1 ) + 1 :]
# check for command-like message
# message split into words, first word is command rest are parms list
pfx = self.cfg['bot']['prefix']
strp_msg = msg.lstrip()
if strp_msg[0 : len( pfx )] == pfx:
msg_words = strp_msg.split()
cmd = msg_words[0][len( pfx ):].lower()
parms = msg_words[1:]
# check if command is in a registered module
for k, m in _MOD_MAP.items():
if cmd in m['cmds'].keys():
cmd_func = m['cmds'][cmd]
con.log( '::CMD:: \'{}\' run by <{}> in ({}) with parms: {}'.format(
cmd, nick, chan, parms ) )
# if msg was sent as pm,
# change dst to nick so say_to's can respond in pm
if chan == self.cfg['user']['nick']: chan = nick
# check for admin
if 'admin' in cmd_func.__dict__.keys() and nick != con.cfg['usr']['owner']:
con.say_to( chan, '> You do not have permission to execute this command.' )
break
self._loop.create_task( cmd_func(
self, parms, {'con': con,'dst': chan,'nick': nick} ) )
# called when a connected connection receives a priv message
# passes the connection that sent, destination of message,
# the nick that sent, and the message
def _on_priv_message( self, con, dst, nick, msg ):
# check for command-like message
# message split into words, first word is command rest are parms list
pfx = self.cfg['bot']['prefix']
strp_msg = msg.lstrip()
if strp_msg[0 : len( pfx )] == pfx:
msg_words = strp_msg.split()
cmd = msg_words[0][len( pfx ):].lower()
parms = msg_words[1:]
# check if command is in a registered module
for k, m in _MOD_MAP.items():
if cmd in m['cmds'].keys():
cmd_func = m['cmds'][cmd]
con.log( '::CMD:: \'{}\' run by <{}> in ({}) with parms: {}'.format(
cmd, nick, dst, parms ) )
# if msg was sent as pm,
# change dst to nick so say_to's can respond in pm
if dst == self.cfg['user']['nick']: dst = nick
# check for admin
if 'admin' in cmd_func.__dict__.keys() and nick != con.cfg['usr']['owner']:
con.say_to( dst, '> You do not have permission to execute this command.' )
break
self._loop.create_task( cmd_func(
self, parms, {'con':con,'dst':dst,'nick':nick} ) )
break
# core commands
@ -107,8 +101,6 @@ class Bot:
async def cmd_join( bot, parms, ctx ):
""" Joins a channel. """
nick = ctx['nick']
#dst = ctx['dst']
con = ctx['con']
if parms \
and not (parms[0] in con.cfg['sv']['channels']) and parms[0][0] == '#':
@ -119,7 +111,6 @@ async def cmd_join( bot, parms, ctx ):
async def cmd_part( bot, parms, ctx ):
""" Leaves a channel. """
nick = ctx['nick']
con = ctx['con']
if parms \
and parms[0] in con.cfg['sv']['channels']:

View File

@ -43,7 +43,7 @@ class IrcProtocol( asyncio.Protocol ):
self._trans = None # protocol's transport
self._stop = False # True if doing a manual stop and dont try to reconnect
self.cfg = {'usr':user_cfg,'sv':{}} # server config set on first connect
self._msg_cb = [] # list of raw message callbacks
self._msg_cb = [] # list of priv message callbacks
self.names = {} # map of names on server to list of channels they're visible in
def connection_made( self, transport ):
@ -68,9 +68,9 @@ class IrcProtocol( asyncio.Protocol ):
# buffer data, then strip off and parse each line within
self._dat += data
while b'\r\n' in self._dat:
raw_msg = self._dat[:self._dat.index( b'\r\n' )]
raw_msg = self._dat[:self._dat.index( b'\r\n' )].decode()
self._dat = self._dat[self._dat.index( b'\r\n' ) + 2:]
words = raw_msg.decode().split()
words = raw_msg.split()
if words[0] == 'PING': self.send( 'PONG ' + words[1] )
# register success, join initial channels
@ -80,8 +80,13 @@ class IrcProtocol( asyncio.Protocol ):
for c in self.cfg['sv']['channels']:
self.send( 'JOIN {}'.format( c ) )
else: self.cfg['sv']['channels'] = []
# on privmsg
elif words[1] == 'PRIVMSG': pass
# on privmsg, callbacks get self, chan, nick, and message
elif words[1] == 'PRIVMSG':
dst = words[2]
raw_user = words[0]
nick = raw_user[1 : words[0].find( '!' )]
msg = raw_msg[raw_msg.find( ':' , 1 ) + 1 :]
for cb in self._msg_cb: cb( self, dst, nick, msg )
# on names
elif words[1] == '353':
#self.log( '::NAMES:: {}'.format( raw_msg.decode() ) )
@ -116,8 +121,6 @@ class IrcProtocol( asyncio.Protocol ):
if words[3] == self.cfg['usr']['nick']:
self.log( '::KICK:: {} has been kicked from {}.'.format( words[3], words[2] ) )
self.part_name( words[3], words[2] )
# send raw message to all added callbacks
for c in self._msg_cb: c( self, raw_msg.decode() )
# manual stop
#self._stop = True
#self.send('QUIT :stopped' )
@ -156,8 +159,8 @@ class IrcProtocol( asyncio.Protocol ):
# callbacks
def add_message_callback( self, cb ):
"""
Adds a function to callback when a raw message is received.
Passes in self and the message
Adds a function to callback when a priv message is received.
Passes in self, dst, nick, and the message
"""
self._msg_cb.append( cb )