mirror of
				https://github.com/jlu5/PyLink.git
				synced 2025-11-04 00:47:21 +01:00 
			
		
		
		
	Move (un|re)?load, identify commands to coreplugin
This is so the commands plugin, which includes other generic (but not essential) commands, can be more easily reloaded.
This commit is contained in:
		
							parent
							
								
									1b8f1ff95e
								
							
						
					
					
						commit
						d14cf3c7cf
					
				
							
								
								
									
										153
									
								
								coreplugin.py
									
									
									
									
									
								
							
							
						
						
									
										153
									
								
								coreplugin.py
									
									
									
									
									
								
							@ -1,4 +1,7 @@
 | 
			
		||||
## coreplugin.py - Core PyLink plugin
 | 
			
		||||
# coreplugin.py - Implements core PyLink functions as a plugin
 | 
			
		||||
 | 
			
		||||
import gc
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
import utils
 | 
			
		||||
from log import log
 | 
			
		||||
@ -107,3 +110,151 @@ def handle_mode(irc, source, command, args):
 | 
			
		||||
        if ('-o', None) in modes and (target == irc.pseudoclient.uid or not utils.isManipulatableClient(irc, target)):
 | 
			
		||||
            irc.proto.modeServer(irc.sid, target, {('+o', None)})
 | 
			
		||||
utils.add_hook(handle_mode, 'MODE')
 | 
			
		||||
 | 
			
		||||
# Essential, core commands go here so that the "commands" plugin with less-important,
 | 
			
		||||
# but still generic functions can be reloaded.
 | 
			
		||||
 | 
			
		||||
@utils.add_cmd
 | 
			
		||||
def identify(irc, source, args):
 | 
			
		||||
    """<username> <password>
 | 
			
		||||
 | 
			
		||||
    Logs in to PyLink using the configured administrator account."""
 | 
			
		||||
    if utils.isChannel(irc.called_by):
 | 
			
		||||
        irc.msg(irc.called_by, 'Error: This command must be sent in private. '
 | 
			
		||||
                '(Would you really type a password inside a channel?)')
 | 
			
		||||
        return
 | 
			
		||||
    try:
 | 
			
		||||
        username, password = args[0], args[1]
 | 
			
		||||
    except IndexError:
 | 
			
		||||
        irc.msg(source, 'Error: Not enough arguments.')
 | 
			
		||||
        return
 | 
			
		||||
    # Usernames are case-insensitive, passwords are NOT.
 | 
			
		||||
    if username.lower() == irc.conf['login']['user'].lower() and password == irc.conf['login']['password']:
 | 
			
		||||
        realuser = irc.conf['login']['user']
 | 
			
		||||
        irc.users[source].identified = realuser
 | 
			
		||||
        irc.msg(source, 'Successfully logged in as %s.' % realuser)
 | 
			
		||||
        log.info("(%s) Successful login to %r by %s.",
 | 
			
		||||
                 irc.name, username, utils.getHostmask(irc, source))
 | 
			
		||||
    else:
 | 
			
		||||
        irc.msg(source, 'Error: Incorrect credentials.')
 | 
			
		||||
        u = irc.users[source]
 | 
			
		||||
        log.warning("(%s) Failed login to %r from %s.",
 | 
			
		||||
                    irc.name, username, utils.getHostmask(irc, source))
 | 
			
		||||
 | 
			
		||||
@utils.add_cmd
 | 
			
		||||
def shutdown(irc, source, args):
 | 
			
		||||
    """takes no arguments.
 | 
			
		||||
 | 
			
		||||
    Exits PyLink by disconnecting all networks."""
 | 
			
		||||
    utils.checkAuthenticated(irc, source, allowOper=False)
 | 
			
		||||
    u = irc.users[source]
 | 
			
		||||
    log.info('(%s) SHUTDOWN requested by "%s!%s@%s", exiting...', irc.name, u.nick,
 | 
			
		||||
             u.ident, u.host)
 | 
			
		||||
    for ircobj in world.networkobjects.values():
 | 
			
		||||
        # Disable auto-connect first by setting the time to negative.
 | 
			
		||||
        ircobj.serverdata['autoconnect'] = -1
 | 
			
		||||
        ircobj.aborted.set()
 | 
			
		||||
 | 
			
		||||
def load(irc, source, args):
 | 
			
		||||
    """<plugin name>.
 | 
			
		||||
 | 
			
		||||
    Loads a plugin from the plugin folder."""
 | 
			
		||||
    utils.checkAuthenticated(irc, source, allowOper=False)
 | 
			
		||||
    try:
 | 
			
		||||
        name = args[0]
 | 
			
		||||
    except IndexError:
 | 
			
		||||
        irc.msg(irc.called_by, "Error: Not enough arguments. Needs 1: plugin name.")
 | 
			
		||||
        return
 | 
			
		||||
    if name in world.plugins:
 | 
			
		||||
        irc.msg(irc.called_by, "Error: %r is already loaded." % name)
 | 
			
		||||
        return
 | 
			
		||||
    try:
 | 
			
		||||
        world.plugins[name] = pl = utils.loadModuleFromFolder(name, world.plugins_folder)
 | 
			
		||||
    except ImportError as e:
 | 
			
		||||
        if str(e) == ('No module named %r' % name):
 | 
			
		||||
            log.exception('Failed to load plugin %r: The plugin could not be found.', name)
 | 
			
		||||
        else:
 | 
			
		||||
            log.exception('Failed to load plugin %r: ImportError.', name)
 | 
			
		||||
        raise
 | 
			
		||||
    else:
 | 
			
		||||
        if hasattr(pl, 'main'):
 | 
			
		||||
            log.debug('Calling main() function of plugin %r', pl)
 | 
			
		||||
            pl.main(irc)
 | 
			
		||||
    irc.msg(irc.called_by, "Loaded plugin %r." % name)
 | 
			
		||||
utils.add_cmd(load)
 | 
			
		||||
 | 
			
		||||
def unload(irc, source, args):
 | 
			
		||||
    """<plugin name>.
 | 
			
		||||
 | 
			
		||||
    Unloads a currently loaded plugin."""
 | 
			
		||||
    utils.checkAuthenticated(irc, source, allowOper=False)
 | 
			
		||||
    try:
 | 
			
		||||
        name = args[0]
 | 
			
		||||
    except IndexError:
 | 
			
		||||
        irc.msg(irc.called_by, "Error: Not enough arguments. Needs 1: plugin name.")
 | 
			
		||||
        return
 | 
			
		||||
    if name in world.plugins:
 | 
			
		||||
        pl = world.plugins[name]
 | 
			
		||||
        log.debug('sys.getrefcount of plugin %s is %s', pl, sys.getrefcount(pl))
 | 
			
		||||
        # Remove any command functions set by the plugin.
 | 
			
		||||
        for cmdname, cmdfuncs in world.commands.copy().items():
 | 
			
		||||
            log.debug('cmdname=%s, cmdfuncs=%s', cmdname, cmdfuncs)
 | 
			
		||||
            for cmdfunc in cmdfuncs:
 | 
			
		||||
                log.debug('__module__ of cmdfunc %s is %s', cmdfunc, cmdfunc.__module__)
 | 
			
		||||
                if cmdfunc.__module__ == name:
 | 
			
		||||
                    log.debug('Removing %s from world.commands[%s]', cmdfunc, cmdname)
 | 
			
		||||
                    world.commands[cmdname].remove(cmdfunc)
 | 
			
		||||
                    # If the cmdfunc list is empty, remove it.
 | 
			
		||||
                    if not cmdfuncs:
 | 
			
		||||
                        log.debug("Removing world.commands[%s] (it's empty now)", cmdname)
 | 
			
		||||
                        del world.commands[cmdname]
 | 
			
		||||
 | 
			
		||||
        # Remove any command hooks set by the plugin.
 | 
			
		||||
        for hookname, hookfuncs in world.hooks.copy().items():
 | 
			
		||||
            for hookfunc in hookfuncs:
 | 
			
		||||
                if hookfunc.__module__ == name:
 | 
			
		||||
                    world.hooks[hookname].remove(hookfunc)
 | 
			
		||||
                    # If the hookfuncs list is empty, remove it.
 | 
			
		||||
                    if not hookfuncs:
 | 
			
		||||
                        del world.hooks[hookname]
 | 
			
		||||
 | 
			
		||||
        # Remove whois handlers too.
 | 
			
		||||
        for f in world.whois_handlers:
 | 
			
		||||
            if f.__module__ == name:
 | 
			
		||||
                world.whois_handlers.remove(f)
 | 
			
		||||
 | 
			
		||||
        # Call the die() function in the plugin, if present.
 | 
			
		||||
        if hasattr(pl, 'die'):
 | 
			
		||||
            try:
 | 
			
		||||
                pl.die(irc)
 | 
			
		||||
            except:  # But don't allow it to crash the server.
 | 
			
		||||
                log.exception('(%s) Error occurred in die() of plugin %s, skipping...', irc.name, pl)
 | 
			
		||||
 | 
			
		||||
        # Delete it from memory (hopefully).
 | 
			
		||||
        del world.plugins[name]
 | 
			
		||||
        if name in sys.modules:
 | 
			
		||||
            del sys.modules[name]
 | 
			
		||||
        if name in globals():
 | 
			
		||||
            del globals()[name]
 | 
			
		||||
 | 
			
		||||
        # Garbage collect.
 | 
			
		||||
        gc.collect()
 | 
			
		||||
 | 
			
		||||
        irc.msg(irc.called_by, "Unloaded plugin %r." % name)
 | 
			
		||||
        return True  # We succeeded, make it clear (this status is used by reload() below)
 | 
			
		||||
    else:
 | 
			
		||||
        irc.msg(irc.called_by, "Unknown plugin %r." % name)
 | 
			
		||||
utils.add_cmd(unload)
 | 
			
		||||
 | 
			
		||||
@utils.add_cmd
 | 
			
		||||
def reload(irc, source, args):
 | 
			
		||||
    """<plugin name>.
 | 
			
		||||
 | 
			
		||||
    Loads a plugin from the plugin folder."""
 | 
			
		||||
    try:
 | 
			
		||||
        name = args[0]
 | 
			
		||||
    except IndexError:
 | 
			
		||||
        irc.msg(irc.called_by, "Error: Not enough arguments. Needs 1: plugin name.")
 | 
			
		||||
        return
 | 
			
		||||
    if unload(irc, source, args):
 | 
			
		||||
        load(irc, source, args)
 | 
			
		||||
 | 
			
		||||
@ -2,8 +2,6 @@
 | 
			
		||||
import sys
 | 
			
		||||
import os
 | 
			
		||||
from time import ctime
 | 
			
		||||
import itertools
 | 
			
		||||
import gc
 | 
			
		||||
 | 
			
		||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
 | 
			
		||||
import utils
 | 
			
		||||
@ -24,33 +22,6 @@ def status(irc, source, args):
 | 
			
		||||
        irc.msg(irc.called_by, 'You are not identified as anyone.')
 | 
			
		||||
    irc.msg(irc.called_by, 'Operator access: \x02%s\x02' % bool(utils.isOper(irc, source)))
 | 
			
		||||
 | 
			
		||||
@utils.add_cmd
 | 
			
		||||
def identify(irc, source, args):
 | 
			
		||||
    """<username> <password>
 | 
			
		||||
 | 
			
		||||
    Logs in to PyLink using the configured administrator account."""
 | 
			
		||||
    if utils.isChannel(irc.called_by):
 | 
			
		||||
        irc.msg(irc.called_by, 'Error: This command must be sent in private. '
 | 
			
		||||
                '(Would you really type a password inside a channel?)')
 | 
			
		||||
        return
 | 
			
		||||
    try:
 | 
			
		||||
        username, password = args[0], args[1]
 | 
			
		||||
    except IndexError:
 | 
			
		||||
        irc.msg(source, 'Error: Not enough arguments.')
 | 
			
		||||
        return
 | 
			
		||||
    # Usernames are case-insensitive, passwords are NOT.
 | 
			
		||||
    if username.lower() == irc.conf['login']['user'].lower() and password == irc.conf['login']['password']:
 | 
			
		||||
        realuser = irc.conf['login']['user']
 | 
			
		||||
        irc.users[source].identified = realuser
 | 
			
		||||
        irc.msg(source, 'Successfully logged in as %s.' % realuser)
 | 
			
		||||
        log.info("(%s) Successful login to %r by %s.",
 | 
			
		||||
                 irc.name, username, utils.getHostmask(irc, source))
 | 
			
		||||
    else:
 | 
			
		||||
        irc.msg(source, 'Error: Incorrect credentials.')
 | 
			
		||||
        u = irc.users[source]
 | 
			
		||||
        log.warning("(%s) Failed login to %r from %s.",
 | 
			
		||||
                    irc.name, username, utils.getHostmask(irc, source))
 | 
			
		||||
 | 
			
		||||
def listcommands(irc, source, args):
 | 
			
		||||
    """takes no arguments.
 | 
			
		||||
 | 
			
		||||
@ -179,20 +150,6 @@ def showchan(irc, source, args):
 | 
			
		||||
            f('\x02User list\x02: %s' % ' '.join(nicklist[:20]))
 | 
			
		||||
            nicklist = nicklist[20:]
 | 
			
		||||
 | 
			
		||||
@utils.add_cmd
 | 
			
		||||
def shutdown(irc, source, args):
 | 
			
		||||
    """takes no arguments.
 | 
			
		||||
 | 
			
		||||
    Exits PyLink by disconnecting all networks."""
 | 
			
		||||
    utils.checkAuthenticated(irc, source, allowOper=False)
 | 
			
		||||
    u = irc.users[source]
 | 
			
		||||
    log.info('(%s) SHUTDOWN requested by "%s!%s@%s", exiting...', irc.name, u.nick,
 | 
			
		||||
             u.ident, u.host)
 | 
			
		||||
    for ircobj in world.networkobjects.values():
 | 
			
		||||
        # Disable auto-connect first by setting the time to negative.
 | 
			
		||||
        ircobj.serverdata['autoconnect'] = -1
 | 
			
		||||
        ircobj.aborted.set()
 | 
			
		||||
 | 
			
		||||
@utils.add_cmd
 | 
			
		||||
def version(irc, source, args):
 | 
			
		||||
    """takes no arguments.
 | 
			
		||||
@ -208,113 +165,6 @@ def echo(irc, source, args):
 | 
			
		||||
    Echoes the text given."""
 | 
			
		||||
    irc.msg(irc.called_by, ' '.join(args))
 | 
			
		||||
 | 
			
		||||
def load(irc, source, args):
 | 
			
		||||
    """<plugin name>.
 | 
			
		||||
 | 
			
		||||
    Loads a plugin from the plugin folder."""
 | 
			
		||||
    utils.checkAuthenticated(irc, source, allowOper=False)
 | 
			
		||||
    try:
 | 
			
		||||
        name = args[0]
 | 
			
		||||
    except IndexError:
 | 
			
		||||
        irc.msg(irc.called_by, "Error: Not enough arguments. Needs 1: plugin name.")
 | 
			
		||||
        return
 | 
			
		||||
    if name in world.plugins:
 | 
			
		||||
        irc.msg(irc.called_by, "Error: %r is already loaded." % name)
 | 
			
		||||
        return
 | 
			
		||||
    try:
 | 
			
		||||
        world.plugins[name] = pl = utils.loadModuleFromFolder(name, world.plugins_folder)
 | 
			
		||||
    except ImportError as e:
 | 
			
		||||
        if str(e) == ('No module named %r' % name):
 | 
			
		||||
            log.exception('Failed to load plugin %r: The plugin could not be found.', name)
 | 
			
		||||
        else:
 | 
			
		||||
            log.exception('Failed to load plugin %r: ImportError.', name)
 | 
			
		||||
        raise
 | 
			
		||||
    else:
 | 
			
		||||
        if hasattr(pl, 'main'):
 | 
			
		||||
            log.debug('Calling main() function of plugin %r', pl)
 | 
			
		||||
            pl.main(irc)
 | 
			
		||||
    irc.msg(irc.called_by, "Loaded plugin %r." % name)
 | 
			
		||||
utils.add_cmd(load)
 | 
			
		||||
 | 
			
		||||
def unload(irc, source, args):
 | 
			
		||||
    """<plugin name>.
 | 
			
		||||
 | 
			
		||||
    Unloads a currently loaded plugin."""
 | 
			
		||||
    utils.checkAuthenticated(irc, source, allowOper=False)
 | 
			
		||||
    try:
 | 
			
		||||
        name = args[0]
 | 
			
		||||
    except IndexError:
 | 
			
		||||
        irc.msg(irc.called_by, "Error: Not enough arguments. Needs 1: plugin name.")
 | 
			
		||||
        return
 | 
			
		||||
    if name == 'commands':
 | 
			
		||||
        irc.msg(irc.called_by, "Error: Cannot unload the commands plugin!")
 | 
			
		||||
        return
 | 
			
		||||
    elif name in world.plugins:
 | 
			
		||||
        pl = world.plugins[name]
 | 
			
		||||
        log.debug('sys.getrefcount of plugin %s is %s', pl, sys.getrefcount(pl))
 | 
			
		||||
        # Remove any command functions set by the plugin.
 | 
			
		||||
        for cmdname, cmdfuncs in world.commands.copy().items():
 | 
			
		||||
            log.debug('cmdname=%s, cmdfuncs=%s', cmdname, cmdfuncs)
 | 
			
		||||
            for cmdfunc in cmdfuncs:
 | 
			
		||||
                log.debug('__module__ of cmdfunc %s is %s', cmdfunc, cmdfunc.__module__)
 | 
			
		||||
                if cmdfunc.__module__ == name:
 | 
			
		||||
                    log.debug('Removing %s from world.commands[%s]', cmdfunc, cmdname)
 | 
			
		||||
                    world.commands[cmdname].remove(cmdfunc)
 | 
			
		||||
                    # If the cmdfunc list is empty, remove it.
 | 
			
		||||
                    if not cmdfuncs:
 | 
			
		||||
                        log.debug("Removing world.commands[%s] (it's empty now)", cmdname)
 | 
			
		||||
                        del world.commands[cmdname]
 | 
			
		||||
 | 
			
		||||
        # Remove any command hooks set by the plugin.
 | 
			
		||||
        for hookname, hookfuncs in world.hooks.copy().items():
 | 
			
		||||
            for hookfunc in hookfuncs:
 | 
			
		||||
                if hookfunc.__module__ == name:
 | 
			
		||||
                    world.hooks[hookname].remove(hookfunc)
 | 
			
		||||
                    # If the hookfuncs list is empty, remove it.
 | 
			
		||||
                    if not hookfuncs:
 | 
			
		||||
                        del world.hooks[hookname]
 | 
			
		||||
 | 
			
		||||
        # Remove whois handlers too.
 | 
			
		||||
        for f in world.whois_handlers:
 | 
			
		||||
            if f.__module__ == name:
 | 
			
		||||
                world.whois_handlers.remove(f)
 | 
			
		||||
 | 
			
		||||
        # Call the die() function in the plugin, if present.
 | 
			
		||||
        if hasattr(pl, 'die'):
 | 
			
		||||
            try:
 | 
			
		||||
                pl.die(irc)
 | 
			
		||||
            except:  # But don't allow it to crash the server.
 | 
			
		||||
                log.exception('(%s) Error occurred in die() of plugin %s, skipping...', irc.name, pl)
 | 
			
		||||
 | 
			
		||||
        # Delete it from memory (hopefully).
 | 
			
		||||
        del world.plugins[name]
 | 
			
		||||
        if name in sys.modules:
 | 
			
		||||
            del sys.modules[name]
 | 
			
		||||
        if name in globals():
 | 
			
		||||
            del globals()[name]
 | 
			
		||||
 | 
			
		||||
        # Garbage collect.
 | 
			
		||||
        gc.collect()
 | 
			
		||||
 | 
			
		||||
        irc.msg(irc.called_by, "Unloaded plugin %r." % name)
 | 
			
		||||
        return True  # We succeeded, make it clear (this status is used by reload() below)
 | 
			
		||||
    else:
 | 
			
		||||
        irc.msg(irc.called_by, "Unknown plugin %r." % name)
 | 
			
		||||
utils.add_cmd(unload)
 | 
			
		||||
 | 
			
		||||
@utils.add_cmd
 | 
			
		||||
def reload(irc, source, args):
 | 
			
		||||
    """<plugin name>.
 | 
			
		||||
 | 
			
		||||
    Loads a plugin from the plugin folder."""
 | 
			
		||||
    try:
 | 
			
		||||
        name = args[0]
 | 
			
		||||
    except IndexError:
 | 
			
		||||
        irc.msg(irc.called_by, "Error: Not enough arguments. Needs 1: plugin name.")
 | 
			
		||||
        return
 | 
			
		||||
    if unload(irc, source, args):
 | 
			
		||||
        load(irc, source, args)
 | 
			
		||||
 | 
			
		||||
@utils.add_cmd
 | 
			
		||||
def rehash(irc, source, args):
 | 
			
		||||
    """takes no arguments.
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user