summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--plugins/screen_detach.py1
-rw-r--r--plugins/test.py4
-rw-r--r--plugins/translate.py33
-rw-r--r--src/plugin.py26
-rw-r--r--src/plugin_manager.py77
5 files changed, 118 insertions, 23 deletions
diff --git a/plugins/screen_detach.py b/plugins/screen_detach.py
index 6ebc77f2..6ee96896 100644
--- a/plugins/screen_detach.py
+++ b/plugins/screen_detach.py
@@ -1,3 +1,4 @@
+from plugin import BasePlugin
import os
import stat
import pyinotify
diff --git a/plugins/test.py b/plugins/test.py
index fc7aedc6..13ba1e9c 100644
--- a/plugins/test.py
+++ b/plugins/test.py
@@ -1,5 +1,9 @@
+from plugin import BasePlugin
+
class Plugin(BasePlugin):
def init(self):
+ self.add_command('plugintest', self.command_plugintest, 'Test command')
+ self.add_event_handler('message', self.on_message)
self.core.information("Plugin loaded")
def cleanup(self):
diff --git a/plugins/translate.py b/plugins/translate.py
new file mode 100644
index 00000000..625d78e7
--- /dev/null
+++ b/plugins/translate.py
@@ -0,0 +1,33 @@
+from plugin import BasePlugin
+import urllib.request
+from urllib.parse import urlencode
+import xhtml
+import json
+
+TARGET_LANG = 'en'
+
+def translate(s, target=TARGET_LANG, source=''):
+ f = urllib.request.urlopen('http://ajax.googleapis.com/ajax/services/language/translate', urlencode({ 'v': '1.0', 'q': s, 'langpair': '%s|%s' % (source, target) }))
+ response = json.loads(str(f.read(), 'utf-8'))['responseData']
+ return (response['translatedText'], response['detectedSourceLanguage'])
+
+class Plugin(BasePlugin):
+ def init(self):
+ self.add_event_handler('groupchat_message', self.on_groupchat_message)
+
+ def on_groupchat_message(self, message):
+ try:
+ room_from = message.getMucroom()
+ if message['type'] == 'error':
+ return
+
+ if room_from == 'poezio@kikoo.louiz.org':
+ nick_from = message['mucnick']
+ body = xhtml.get_body_from_message_stanza(message)
+ room = self.core.get_room_by_name(room_from)
+ text, lang = translate(body)
+ if lang != TARGET_LANG:
+ room.add_message(text, nickname=nick_from)
+ except Exception as e:
+ import traceback
+ self.core.information("Exception in translator! %s" % (traceback.format_exc(),))
diff --git a/src/plugin.py b/src/plugin.py
index e8386d16..728dfe21 100644
--- a/src/plugin.py
+++ b/src/plugin.py
@@ -1,5 +1,3 @@
-import inspect
-
class BasePlugin(object):
"""
Class that all plugins derive from. Any methods beginning with command_
@@ -7,14 +5,9 @@ class BasePlugin(object):
event handlers
"""
- def __init__(self, core):
+ def __init__(self, plugin_manager, 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.plugin_manager = plugin_manager
self.init()
def init(self):
@@ -24,10 +17,13 @@ class BasePlugin(object):
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()
+
+ def add_command(self, name, handler, help, completion=None):
+ return self.plugin_manager.add_command(self.__module__, name, handler, help, completion)
+
+ def add_event_handler(self, event_name, handler):
+ return self.plugin_manager.add_event_handler(self.__module__, event_name, handler)
+
+ def del_event_handler(self, event_name, handler):
+ return self.plugin_manager.del_event_handler(self.__module__, event_name, handler)
diff --git a/src/plugin_manager.py b/src/plugin_manager.py
index 3f900e39..8301f5f8 100644
--- a/src/plugin_manager.py
+++ b/src/plugin_manager.py
@@ -1,25 +1,86 @@
+import imp
+import os
+import sys
+from config import config
+from gettext import gettext as _
+
+plugins_dir = config.get('plugins_dir', '')
+plugins_dir = plugins_dir or\
+ os.path.join(os.environ.get('XDG_DATA_HOME') or\
+ os.path.join(os.environ.get('HOME'), '.local', 'share'),
+ 'poezio', 'plugins')
+try:
+ os.makedirs(plugins_dir)
+except OSError:
+ pass
+
+sys.path.append(plugins_dir)
+
class PluginManager(object):
def __init__(self, core):
self.core = core
- self.plugins = {}
+ self.modules = {} # module name -> module object
+ self.plugins = {} # module name -> plugin object
+ self.commands = {} # module name -> dict of commands loaded for the module
+ self.event_handlers = {} # module name -> list of event_name/handler pairs loaded for the module
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)
+ if name in self.modules:
+ imp.acquire_lock()
+ module = imp.reload(self.modules[name])
+ imp.release_lock()
+ else:
+ file, filename, info = imp.find_module(name, [plugins_dir])
+ imp.acquire_lock()
+ module = imp.load_module(name, file, filename, info)
+ imp.release_lock()
except Exception as e:
- self.core.information("Could not load plugin: %s" % (e,))
+ import traceback
+ self.core.information(_("Could not load plugin: ") + traceback.format_exc())
+ return
+ finally:
+ if imp.lock_held():
+ imp.release_lock()
+
+ self.modules[name] = module
+ self.commands[name] = {}
+ self.event_handlers[name] = []
+ self.plugins[name] = module.Plugin(self, self.core)
def unload(self, name):
if name in self.plugins:
try:
+ for command in self.commands[name].keys():
+ del self.core.commands[command]
+ for event_name, handler in self.event_handlers[name]:
+ self.core.xmpp.del_event_handler(event_name, handler)
+
self.plugins[name].unload()
del self.plugins[name]
+ del self.commands[name]
+ del self.event_handlers[name]
except Exception as e:
- self.core.information("Could not unload plugin (may not be safe to try again): %s" % (e,))
+ import traceback
+ self.core.information(_("Could not unload plugin (may not be safe to try again): ") + traceback.format_exc())
+
+ def add_command(self, module_name, name, handler, help, completion=None):
+ if name in self.core.commands:
+ raise Exception(_("Command '%s' already exists") % (name,))
+
+ commands = self.commands[module_name]
+ commands[name] = (handler, help, completion)
+ self.core.commands[name] = (handler, help, completion)
+
+ def add_event_handler(self, module_name, event_name, handler):
+ eh = self.event_handlers[module_name]
+ eh.append((event_name, handler))
+ self.core.xmpp.add_event_handler(event_name, handler)
+
+ def del_event_handler(self, module_name, event_name, handler):
+ self.core.xmpp.del_event_handler(event_name, handler)
+ eh = self.event_handlers[module_name]
+ eh = list(filter(lambda e : e != (event_name, handler), eh))