3
0
mirror of https://github.com/jlu5/PyLink.git synced 2024-11-24 03:29:28 +01:00

ServiceBot: work out basic command handling

This copies callCommand from the IRC object into ServiceBot.call_cmd. The former will be removed once the main PyLink client is migrated to a service bot.
This commit is contained in:
James Lu 2016-05-14 10:17:40 -07:00
parent 0c7faed213
commit 924172291f
2 changed files with 51 additions and 9 deletions

View File

@ -53,9 +53,17 @@ utils.add_hook(handle_kick, 'KICK')
def handle_commands(irc, source, command, args): def handle_commands(irc, source, command, args):
"""Handle commands sent to the PyLink client (PRIVMSG).""" """Handle commands sent to the PyLink client (PRIVMSG)."""
if args['target'] == irc.pseudoclient.uid and not irc.isInternalClient(source): target = args['target']
text = args['text']
if target == irc.pseudoclient.uid and not irc.isInternalClient(source):
irc.called_by = source irc.called_by = source
irc.callCommand(source, args['text']) irc.callCommand(source, text)
else:
for sbot in world.services.values():
if target == sbot.uids.get(irc.name):
sbot.call_cmd(irc, source, text)
return
utils.add_hook(handle_commands, 'PRIVMSG') utils.add_hook(handle_commands, 'PRIVMSG')
@ -204,12 +212,12 @@ def handle_newservice(irc, source, command, args):
# Track the service's UIDs on each network. # Track the service's UIDs on each network.
service = world.services[name] service = world.services[name]
service.uids[irc.name] = u = irc.proto.spawnClient(name, name, service.uids[irc.name] = u = irc.proto.spawnClient(name, name,
irc.serverdata['hostname'], modes=modes, opertype="PyLink Service") irc.serverdata['hostname'], modes=modes, opertype="PyLink Service").uid
# TODO: channels should be tracked in a central database, not hardcoded # TODO: channels should be tracked in a central database, not hardcoded
# in conf. # in conf.
for chan in irc.serverdata['channels']: for chan in irc.serverdata['channels']:
irc.proto.join(u.uid, chan) irc.proto.join(u, chan)
utils.add_hook(handle_newservice, 'PYLINK_NEW_SERVICE') utils.add_hook(handle_newservice, 'PYLINK_NEW_SERVICE')
@ -227,7 +235,7 @@ utils.add_hook(handle_disconnect, 'PYLINK_DISCONNECT')
def handle_endburst(irc, source, command, args): def handle_endburst(irc, source, command, args):
"""Handles network bursts.""" """Handles network bursts."""
if source == irc.uplink: if source == irc.uplink:
log.debug('(%s): spawning service bots now.') log.debug('(%s): spawning service bots now.', irc.name)
# We just connected. Burst all our registered services. # We just connected. Burst all our registered services.
for name, sbot in world.services.items(): for name, sbot in world.services.items():

View File

@ -153,6 +153,7 @@ def getDatabaseName(dbname):
class ServiceBot(): class ServiceBot():
def __init__(self, name, default_help=True, default_request=True, default_list=True): def __init__(self, name, default_help=True, default_request=True, default_list=True):
self.name = name self.name = name
# We make the command definitions a dict of lists of functions. Multiple # We make the command definitions a dict of lists of functions. Multiple
# plugins are actually allowed to bind to one function name; this just causes # plugins are actually allowed to bind to one function name; this just causes
# them to be called in the order that they are bound. # them to be called in the order that they are bound.
@ -181,6 +182,39 @@ class ServiceBot():
else: else:
raise NotImplementedError("Network specific plugins not supported yet.") raise NotImplementedError("Network specific plugins not supported yet.")
def reply(self, irc, text, notice=True):
"""Replies to a message using the right service UID."""
servuid = self.uids.get(irc.name)
if not servuid:
log.warning("(%s) Possible desync? UID for service %s doesn't exist!", irc.name, self.name)
return
irc.reply(text, notice=notice, source=servuid)
def call_cmd(self, irc, source, text):
"""
Calls a PyLink bot command. source is the caller's UID, and text is the
full, unparsed text of the message.
"""
irc.called_by = source
cmd_args = text.strip().split(' ')
cmd = cmd_args[0].lower()
cmd_args = cmd_args[1:]
if cmd not in self.commands:
self.reply(irc, 'Error: Unknown command %r.' % cmd)
log.info('(%s/%s) Received unknown command %r from %s', irc.name, self.name, cmd, irc.getHostmask(source))
return
log.info('(%s/%s) Calling command %r for %s', irc.name, self.name, cmd, irc.getHostmask(source))
for func in self.commands[cmd]:
try:
func(irc, source, cmd_args)
except NotAuthenticatedError:
self.reply(irc, 'Error: You are not authorized to perform this operation.')
except Exception as e:
log.exception('Unhandled exception caught in command %r', cmd)
self.reply(irc, 'Uncaught exception in command %r: %s: %s' % (cmd, type(e).__name__, str(e)))
def add_cmd(self, func, name=None): def add_cmd(self, func, name=None):
"""Binds an IRC command function to the given command name.""" """Binds an IRC command function to the given command name."""
@ -192,16 +226,16 @@ class ServiceBot():
return func return func
def help(self, irc, source, args): def help(self, irc, source, args):
irc.reply("Help command stub called.") self.reply(irc, "Help command stub called.")
def request(self, irc, source, args): def request(self, irc, source, args):
irc.reply("Request command stub called.") self.reply(irc, "Request command stub called.")
def remove(self, irc, source, args): def remove(self, irc, source, args):
irc.reply("Remove command stub called.") self.reply(irc, "Remove command stub called.")
def listcommands(self, irc, source, args): def listcommands(self, irc, source, args):
irc.reply("List command stub called.") self.reply(irc, "List command stub called.")
def registerService(name, *args, **kwargs): def registerService(name, *args, **kwargs):
name = name.lower() name = name.lower()