mirror of
https://github.com/jlu5/PyLink.git
synced 2024-12-25 12:12:53 +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
|
import utils
|
||||||
from log import log
|
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)):
|
if ('-o', None) in modes and (target == irc.pseudoclient.uid or not utils.isManipulatableClient(irc, target)):
|
||||||
irc.proto.modeServer(irc.sid, target, {('+o', None)})
|
irc.proto.modeServer(irc.sid, target, {('+o', None)})
|
||||||
utils.add_hook(handle_mode, 'MODE')
|
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 sys
|
||||||
import os
|
import os
|
||||||
from time import ctime
|
from time import ctime
|
||||||
import itertools
|
|
||||||
import gc
|
|
||||||
|
|
||||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
import utils
|
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, 'You are not identified as anyone.')
|
||||||
irc.msg(irc.called_by, 'Operator access: \x02%s\x02' % bool(utils.isOper(irc, source)))
|
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):
|
def listcommands(irc, source, args):
|
||||||
"""takes no arguments.
|
"""takes no arguments.
|
||||||
|
|
||||||
@ -179,20 +150,6 @@ def showchan(irc, source, args):
|
|||||||
f('\x02User list\x02: %s' % ' '.join(nicklist[:20]))
|
f('\x02User list\x02: %s' % ' '.join(nicklist[:20]))
|
||||||
nicklist = 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
|
@utils.add_cmd
|
||||||
def version(irc, source, args):
|
def version(irc, source, args):
|
||||||
"""takes no arguments.
|
"""takes no arguments.
|
||||||
@ -208,113 +165,6 @@ def echo(irc, source, args):
|
|||||||
Echoes the text given."""
|
Echoes the text given."""
|
||||||
irc.msg(irc.called_by, ' '.join(args))
|
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
|
@utils.add_cmd
|
||||||
def rehash(irc, source, args):
|
def rehash(irc, source, args):
|
||||||
"""takes no arguments.
|
"""takes no arguments.
|
||||||
|
Loading…
Reference in New Issue
Block a user