summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core.py27
-rw-r--r--src/plugin.py33
-rw-r--r--src/plugin_manager.py25
3 files changed, 85 insertions, 0 deletions
diff --git a/src/core.py b/src/core.py
index 3cdc7592..d644c19b 100644
--- a/src/core.py
+++ b/src/core.py
@@ -36,6 +36,8 @@ import windows
import connection
import timed_events
+from plugin_manager import PluginManager
+
from data_forms import DataFormsTab
from config import config, options
from logger import logger
@@ -125,6 +127,8 @@ class Core(object):
'server_cycle': (self.command_server_cycle, _('Usage: /server_cycle [domain] [message]\nServer Cycle: disconnect and reconnects in all the rooms in domain.'), None),
'bind': (self.command_bind, _('Usage: /bind <key> <equ>\nBind: bind a key to an other key or to a “command”. For example "/bind ^H KEY_UP" makes Control + h do the same same than the Up key.'), None),
'pubsub': (self.command_pubsub, _('Usage: /pubsub <domain>\nPubsub: Open a pubsub browser on the given domain'), None),
+ 'load': (self.command_load, _('Usage: /load <script.py>\nLoad: Load the specified python script'), None),
+ 'unload': (self.command_unload, _('Usage: /unload <script.py>\nUnload: Unload the specified python script'), None),
}
self.key_func = {
@@ -169,6 +173,7 @@ class Core(object):
self.xmpp.add_event_handler("chatstate_inactive", self.on_chatstate_inactive)
self.timed_events = set()
+ self.plugin_manager = PluginManager(self)
def coucou(self):
self.command_pubsub('pubsub.louiz.org')
@@ -1121,6 +1126,28 @@ class Core(object):
def completion_status(self, the_input):
return the_input.auto_completion([status for status in possible_show], ' ')
+ def command_load(self, arg):
+ """
+ /load <script.py>
+ """
+ args = arg.split()
+ if len(args) != 1:
+ self.command_help('load')
+ return
+ filename = args[0]
+ self.plugin_manager.load(filename)
+
+ def command_unload(self, arg):
+ """
+ /unload <script.py>
+ """
+ args = arg.split()
+ if len(args) != 1:
+ self.command_help('unload')
+ return
+ filename = args[0]
+ self.plugin_manager.unload(filename)
+
def command_message(self, arg):
"""
/message <jid> [message]
diff --git a/src/plugin.py b/src/plugin.py
new file mode 100644
index 00000000..e8386d16
--- /dev/null
+++ b/src/plugin.py
@@ -0,0 +1,33 @@
+import inspect
+
+class BasePlugin(object):
+ """
+ Class that all plugins derive from. Any methods beginning with command_
+ are interpreted as a command and beginning with on_ are interpreted as
+ event handlers
+ """
+
+ def __init__(self, core):
+ self.core = core
+ for k, v in inspect.getmembers(self, inspect.ismethod):
+ if k.startswith('on_'):
+ core.xmpp.add_event_handler(k[3:], v)
+ elif k.startswith('command_'):
+ command = k[len('command_'):]
+ core.commands[command] = (v, v.__doc__, None)
+ self.init()
+
+ def init(self):
+ pass
+
+ def cleanup(self):
+ pass
+
+ def unload(self):
+ for k, v in inspect.getmembers(self, inspect.ismethod):
+ if k.startswith('on_'):
+ self.core.xmpp.del_event_handler(k[3:], v)
+ elif k.startswith('command_'):
+ command = k[len('command_'):]
+ del self.core.commands[command]
+ self.cleanup()
diff --git a/src/plugin_manager.py b/src/plugin_manager.py
new file mode 100644
index 00000000..3f900e39
--- /dev/null
+++ b/src/plugin_manager.py
@@ -0,0 +1,25 @@
+class PluginManager(object):
+ def __init__(self, core):
+ self.core = core
+ self.plugins = {}
+
+ def load(self, name):
+ if name in self.plugins:
+ self.plugins[name].unload()
+
+ try:
+ code = compile(open(name).read(), name, 'exec')
+ from plugin import BasePlugin
+ globals = { 'BasePlugin' : BasePlugin }
+ exec(code, globals)
+ self.plugins[name] = globals['Plugin'](self.core)
+ except Exception as e:
+ self.core.information("Could not load plugin: %s" % (e,))
+
+ def unload(self, name):
+ if name in self.plugins:
+ try:
+ self.plugins[name].unload()
+ del self.plugins[name]
+ except Exception as e:
+ self.core.information("Could not unload plugin (may not be safe to try again): %s" % (e,))