A bot's say_to message gets passed to message callbacks (and subsequently parsers) now by default and can be disabled by specifying callback=False in the say_to call. Added links module, for relaying channels of the same specified link name. Relays own messages as well as across networks.

This commit is contained in:
Josh K 2018-12-04 08:25:11 -05:00
parent cceb2515eb
commit adcb11debf
5 changed files with 83 additions and 14 deletions

15
bot.py
View File

@ -75,6 +75,7 @@ def parser():
"""
message parser decorator.
decorated function gets passed con, dst, nick, msg on each privmsg
by default, bot's own messages are caught by parsers too
"""
def __deco__( func ):
mod = add_module( func.__module__ )
@ -142,7 +143,8 @@ def _on_priv_message( con, dst, nick, msg ):
# message split into words, first word is command rest are parms list
pfx = bcfg['bot']['prefix']
strp_msg = msg.lstrip()
if strp_msg[0 : len( pfx )] == pfx:
# if prefixed and not from self
if strp_msg[0 : len( pfx )] == pfx and nick != bcfg['user']['nick']:
msg_words = strp_msg.split()
cmd = msg_words[0][len( pfx ):].lower()
parms = msg_words[1:]
@ -163,12 +165,11 @@ def _on_priv_message( con, dst, nick, msg ):
parms, {'con':con,'dst':dst,'nick':nick} ) )
break
# callback registered parsers, not for self messages though
if nick != bcfg['user']['nick']:
# call each registered parser
for v in _MOD_MAP.values():
for p in v['parsers']:
p( con, dst, nick, msg )
# callback registered parsers, self messages too by default
#if nick != bcfg['user']['nick']:
for v in _MOD_MAP.values():
for p in v['parsers']:
p( con, dst, nick, msg )
# core commands

View File

@ -10,7 +10,7 @@
owner = "slipyx"
# nick, user, and real name of bot
nick = "dustbot"
nick = "dustbotomize"
user = "dust"
name = "Me Mow"
@ -19,11 +19,11 @@ name = "Me Mow"
##
[bot]
# command prefix
prefix = ";"
prefix = "::"
# list of module names to import from modules package
# additions are imported on bot reload
modules = ['misc','qdb']
# any additions made are imported on bot reload
modules = ['misc','qdb','links']
##
## networks/servers config
@ -33,7 +33,7 @@ modules = ['misc','qdb']
name = "Tilde"
# host and port of server to connect to
host = "irc.tilde.chat"
host = "team.tilde.chat"
port = 6697
# optional list of channels to join upon connecting

62
modules/links.py Normal file
View File

@ -0,0 +1,62 @@
# links/relays channels to a specified link name
# works cross network. all chans linked to same name are relayed
import asyncio
import bot
# globals
try:
_G
except NameError:
_G = {
'links': {} # strLinkName: [c,c]
}
async def link( c, lname ):
if lname not in _G['links'].keys(): _G['links'][lname] = []
if c not in _G['links'][lname]:
c['con'].say_to( c['dst'], '> Adding this chan to link named \'{}\'...'.format( lname ) )
_G['links'][lname].append( c )
else: c['con'].say_to( c['dst'], '> This chan is already linked to that name...' )
async def unlink( c, lname ):
if lname not in _G['links'].keys():
c['con'].say_to( c['dst'], '> Link name not found.' )
return
if c in _G['links'][lname]:
c['con'].say_to( c['dst'], '> Unlinking this chan from link named \'{}\'...'.format( lname ) )
_G['links'][lname].remove( c )
# if nothing else in link, remove name too
if not _G['links'][lname]: _G['links'].pop( lname, None )
else: c['con'].say_to( c['dst'], '> This chan is not linked to link name \'{}\'...'.format( lname ) )
@bot.parser()
def parse_linked_chat( con, chan, nick, msg ):
for lname in _G['links'].keys():
for c in _G['links'][lname]:
if con == c['con'] and chan == c['dst']:
for ctx in _G['links'][lname]:
if ctx['con'] != con or ctx['dst'] != chan:
# disable callback for recursion prevention!
ctx['con'].say_to( ctx['dst'], '[{}:{}] <{}> {}'.format(
lname, _G['links'][lname].index( c ) + 1, nick, msg ), callback=False )
break
@bot.command( 'link', True )
async def cmd_link( p, c ):
lname = ''
if p: lname = p[0].lower()
else:
c['con'].say_to( c['dst'], '> Please specify a link name.' )
return
await link( c, lname )
@bot.command( 'unlink', True )
async def cmd_unlink( p, c ):
lname = ''
if p: lname = p[0].lower()
else:
c['con'].say_to( c['dst'], '> Please specify a link name.' )
return
await unlink( c, lname )

View File

@ -48,6 +48,9 @@ async def get_quote( parms, ctx ):
con.say_to( dst, 'No QDB known by name \'{}\'!'.format( db_name ) )
return
# implicit spam for tilde server
if sv_name == 'tilde': spam = True
con.say_to( dst, 'Grabbing a quote from QDB \'{}\'...'.format( db_name ) )
req = requests.get( QDB_URLS[db_name] )

View File

@ -167,7 +167,7 @@ class IrcProtocol( asyncio.Protocol ):
#if new in self.names:
self.names[new] = self.names.pop( name, [] )
#else: self.names[new] = []
#self.log( 'NICK {} changed to {} w/now: {}'.format( name, new, self.names[new] ) )
self.log( 'NICK {} changed to {} w/now: {}'.format( name, new, self.names[new] ) )
# callbacks
def add_message_callback( self, cb ):
@ -195,10 +195,13 @@ class IrcProtocol( asyncio.Protocol ):
#if 'PONG' not in msg: self.log( '>> {}'.format( msg ) )
self._trans.write( bytes( msg[:510] + '\r\n', 'utf-8' ) )
# helper func for sending a privmsg to specified destination
def say_to( self, dst, msg ):
# also passes on to callbacks by default if not disabled
def say_to( self, dst, msg, callback=True ):
msg = msg.replace( '\n', ' ' ).replace( '\r', '' )
self.log( '{} >> {}'.format( dst, msg ) )
self.send( 'PRIVMSG {} :{}'.format( dst, msg ) )
if callback:
for cb in self._cb['message']: cb( self, dst, self.cfg['usr']['nick'], msg )
# create connection task
async def do_connect( self, sv_cfg ):