mirror of
https://github.com/jlu5/PyLink.git
synced 2024-12-25 12:12:53 +01:00
Begin work on service bot abstraction (#216)
- State-keeping is done by coreplugin - utils.registerService() introduced - new PYLINK_NEW_SERVICE hook introduced
This commit is contained in:
parent
ce95e15897
commit
7d11f8c7e0
@ -186,6 +186,55 @@ def handle_version(irc, source, command, args):
|
||||
irc.proto.numeric(irc.sid, 351, source, fullversion)
|
||||
utils.add_hook(handle_version, 'VERSION')
|
||||
|
||||
def handle_newservice(irc, source, command, args):
|
||||
"""Handles new service bot introductions."""
|
||||
|
||||
if not irc.connected.is_set():
|
||||
return
|
||||
|
||||
name = args['name']
|
||||
ident = irc.botdata.get('ident') or 'pylink'
|
||||
host = irc.serverdata["hostname"]
|
||||
modes = []
|
||||
for mode in ('oper', 'hideoper', 'hidechans'):
|
||||
mode = irc.cmodes.get(mode)
|
||||
if mode:
|
||||
modes.append((mode, None))
|
||||
|
||||
# Track the service's UIDs on each network.
|
||||
service = world.services[name]
|
||||
service.uids[irc.name] = u = irc.proto.spawnClient(name, name,
|
||||
irc.serverdata['hostname'], modes=modes, opertype="PyLink Service")
|
||||
|
||||
# TODO: channels should be tracked in a central database, not hardcoded
|
||||
# in conf.
|
||||
for chan in irc.serverdata['channels']:
|
||||
irc.proto.join(u.uid, chan)
|
||||
|
||||
utils.add_hook(handle_newservice, 'PYLINK_NEW_SERVICE')
|
||||
|
||||
def handle_disconnect(irc, source, command, args):
|
||||
"""Handles network disconnections."""
|
||||
for name, sbot in world.services.items():
|
||||
try:
|
||||
del sbot.uids[irc.name]
|
||||
log.debug("coreplugin: removing uids[%s] from service bot %s", irc.name, sbot.name)
|
||||
except KeyError:
|
||||
continue
|
||||
|
||||
utils.add_hook(handle_disconnect, 'PYLINK_DISCONNECT')
|
||||
|
||||
def handle_endburst(irc, source, command, args):
|
||||
"""Handles network bursts."""
|
||||
if source == irc.uplink:
|
||||
log.debug('(%s): spawning service bots now.')
|
||||
|
||||
# We just connected. Burst all our registered services.
|
||||
for name, sbot in world.services.items():
|
||||
handle_newservice(irc, source, command, {'name': name})
|
||||
|
||||
utils.add_hook(handle_endburst, 'ENDBURST')
|
||||
|
||||
# Essential, core commands go here so that the "commands" plugin with less-important,
|
||||
# but still generic functions can be reloaded.
|
||||
|
||||
|
62
utils.py
62
utils.py
@ -9,6 +9,7 @@ import string
|
||||
import re
|
||||
import importlib
|
||||
import os
|
||||
import collections
|
||||
|
||||
from log import log
|
||||
import world
|
||||
@ -141,3 +142,64 @@ def getDatabaseName(dbname):
|
||||
dbname += '-%s' % conf.confname
|
||||
dbname += '.db'
|
||||
return dbname
|
||||
|
||||
class ServiceBot():
|
||||
def __init__(self, name, default_help=True, default_request=True, default_list=True):
|
||||
self.name = name
|
||||
# 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
|
||||
# them to be called in the order that they are bound.
|
||||
self.commands = collections.defaultdict(list)
|
||||
|
||||
# This tracks the UIDs of the service bot on different networks, as they are
|
||||
# spawned.
|
||||
self.uids = {}
|
||||
|
||||
if default_help:
|
||||
self.add_cmd(self.help)
|
||||
|
||||
if default_request:
|
||||
self.add_cmd(self.request)
|
||||
self.add_cmd(self.remove)
|
||||
|
||||
if default_list:
|
||||
self.add_cmd(self.listcommands, 'list')
|
||||
|
||||
def spawn(self, irc=None):
|
||||
# Spawn the new service by calling the PYLINK_NEW_SERVICE hook,
|
||||
# which is handled by coreplugin.
|
||||
if irc is None:
|
||||
for irc in world.networkobjects.values():
|
||||
irc.callHooks([None, 'PYLINK_NEW_SERVICE', {'name': self.name}])
|
||||
else:
|
||||
raise NotImplementedError("Network specific plugins not supported yet.")
|
||||
|
||||
|
||||
def add_cmd(self, func, name=None):
|
||||
"""Binds an IRC command function to the given command name."""
|
||||
if name is None:
|
||||
name = func.__name__
|
||||
name = name.lower()
|
||||
|
||||
self.commands[name].append(func)
|
||||
return func
|
||||
|
||||
def help(self, irc, source, args):
|
||||
irc.reply("Help command stub called.")
|
||||
|
||||
def request(self, irc, source, args):
|
||||
irc.reply("Request command stub called.")
|
||||
|
||||
def remove(self, irc, source, args):
|
||||
irc.reply("Remove command stub called.")
|
||||
|
||||
def listcommands(self, irc, source, args):
|
||||
irc.reply("List command stub called.")
|
||||
|
||||
def registerService(name, *args, **kwargs):
|
||||
name = name.lower()
|
||||
if name in world.services:
|
||||
raise ValueError("Service name %s is already bound!" % name)
|
||||
|
||||
world.services[name] = sbot = ServiceBot(name, *args, **kwargs)
|
||||
sbot.spawn()
|
||||
|
5
world.py
5
world.py
@ -14,13 +14,14 @@ testing = True
|
||||
# Sets the default protocol module to use with tests.
|
||||
testing_ircd = 'inspircd'
|
||||
|
||||
global commands, hooks
|
||||
# This should be a mapping of command names to functions
|
||||
|
||||
commands = defaultdict(list)
|
||||
hooks = defaultdict(list)
|
||||
networkobjects = {}
|
||||
plugins = {}
|
||||
whois_handlers = []
|
||||
services = {}
|
||||
|
||||
started = threading.Event()
|
||||
|
||||
plugins_folder = os.path.join(os.getcwd(), 'plugins')
|
||||
|
Loading…
Reference in New Issue
Block a user