Major rewrite for more modularity and maintanability
This commit is contained in:
parent
13023b660e
commit
bbb8bd9020
6 changed files with 136 additions and 24 deletions
|
@ -1,4 +1,30 @@
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import yaml
|
||||||
|
|
||||||
class Plugin(object):
|
class Plugin(object):
|
||||||
|
def __init__(self):
|
||||||
|
for cls in reversed(self.__class__.mro()):
|
||||||
|
if cls is not object:
|
||||||
|
try:
|
||||||
|
cls._init(self)
|
||||||
|
except AttributeError as e:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def _init(self):
|
||||||
|
module_dir = os.path.dirname(sys.modules[self.__module__].__file__)
|
||||||
|
config_file = module_dir + os.sep + 'config.yaml'
|
||||||
|
|
||||||
|
config = {}
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(config_file, 'r') as f:
|
||||||
|
self.config = yaml.load(f)
|
||||||
|
except FileNotFoundError as e:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def run(self, args):
|
def run(self, args):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
28
lib/plugins/music/__init__.py
Normal file
28
lib/plugins/music/__init__.py
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
from .. import Plugin
|
||||||
|
|
||||||
|
class MusicPlugin(Plugin):
|
||||||
|
def run(self, args):
|
||||||
|
if 'play' in args and self.status()['state'] != 'play':
|
||||||
|
self.play()
|
||||||
|
elif 'pause' in args and self.status()['state'] != 'pause':
|
||||||
|
self.pause()
|
||||||
|
elif 'stop' in args:
|
||||||
|
self.stop()
|
||||||
|
|
||||||
|
return self.status()
|
||||||
|
|
||||||
|
def play(self):
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def pause(self):
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def status(self):
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
|
# vim:sw=4:ts=4:et:
|
||||||
|
|
23
lib/plugins/music/mpd/__init__.py
Normal file
23
lib/plugins/music/mpd/__init__.py
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
import mpd
|
||||||
|
|
||||||
|
from .. import MusicPlugin
|
||||||
|
|
||||||
|
class MusicMpdPlugin(MusicPlugin):
|
||||||
|
def _init(self):
|
||||||
|
self.client = mpd.MPDClient(use_unicode=True)
|
||||||
|
self.client.connect(self.config['host'], self.config['port'])
|
||||||
|
|
||||||
|
def play(self):
|
||||||
|
self.client.play()
|
||||||
|
|
||||||
|
def pause(self):
|
||||||
|
self.client.pause()
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self.client.stop()
|
||||||
|
|
||||||
|
def status(self):
|
||||||
|
return self.client.status()
|
||||||
|
|
||||||
|
# vim:sw=4:ts=4:et:
|
||||||
|
|
6
lib/plugins/music/mpd/config.yaml
Normal file
6
lib/plugins/music/mpd/config.yaml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
host: localhost
|
||||||
|
port: 6600
|
||||||
|
|
||||||
|
_deps:
|
||||||
|
- python-mpd2
|
||||||
|
|
|
@ -18,7 +18,7 @@ class ShellPlugin(Plugin):
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
error = e.output
|
error = e.output
|
||||||
|
|
||||||
return output, error
|
return [output, error]
|
||||||
|
|
||||||
# vim:sw=4:ts=4:et:
|
# vim:sw=4:ts=4:et:
|
||||||
|
|
||||||
|
|
75
notifier.py
75
notifier.py
|
@ -50,38 +50,67 @@ def on_error(ws, error):
|
||||||
logging.error(error)
|
logging.error(error)
|
||||||
|
|
||||||
|
|
||||||
def _exec_func(body):
|
def _init_plugin(plugin, reload=False):
|
||||||
module_name = 'plugins.{}'.format(body['plugin'])
|
module_name = 'plugins.{}'.format(plugin)
|
||||||
if module_name in modules:
|
if module_name not in modules or reload:
|
||||||
module = modules[module_name]
|
|
||||||
else:
|
|
||||||
try:
|
try:
|
||||||
module = importlib.import_module(module_name)
|
modules[module_name] = importlib.import_module(module_name)
|
||||||
modules[module_name] = module
|
|
||||||
except ModuleNotFoundError as e:
|
except ModuleNotFoundError as e:
|
||||||
logging.warn('No such plugin: {}'.format(body['plugin']))
|
logging.warn('No such plugin: {}'.format(plugin))
|
||||||
return
|
raise RuntimeError(e)
|
||||||
|
|
||||||
logging.info('Received push addressed to me: {}'.format(body))
|
|
||||||
|
|
||||||
args = body['args'] if 'args' in body else {}
|
|
||||||
cls_name = functools.reduce(
|
cls_name = functools.reduce(
|
||||||
lambda a,b: a.title() + b.title(),
|
lambda a,b: a.title() + b.title(),
|
||||||
(body['plugin'].title().split('.'))
|
(plugin.title().split('.'))
|
||||||
) + 'Plugin'
|
) + 'Plugin'
|
||||||
|
|
||||||
if cls_name in plugins:
|
if cls_name not in plugins or reload:
|
||||||
instance = plugins[cls_name]
|
try:
|
||||||
else:
|
plugins[cls_name] = getattr(modules[module_name], cls_name)()
|
||||||
cls = getattr(module, cls_name)
|
except AttributeError as e:
|
||||||
instance = cls()
|
logging.warn('No such class in {}: {}'.format(
|
||||||
plugins[cls_name] = cls
|
module_name, cls_name))
|
||||||
|
raise RuntimeError(e)
|
||||||
|
|
||||||
out, err = instance.run(args)
|
return plugins[cls_name]
|
||||||
|
|
||||||
logging.info('Command output: {}'.format(out))
|
|
||||||
if err:
|
def _exec_func(body, retry=True):
|
||||||
logging.warn('Command error: {}'.format(err))
|
try:
|
||||||
|
logging.info('Received push addressed to me: {}'.format(body))
|
||||||
|
args = body['args'] if 'args' in body else {}
|
||||||
|
if 'plugin' not in body:
|
||||||
|
logging.warn('No plugin specified')
|
||||||
|
return
|
||||||
|
|
||||||
|
plugin_name = body['plugin']
|
||||||
|
|
||||||
|
try:
|
||||||
|
plugin = _init_plugin(plugin_name)
|
||||||
|
except RuntimeError as e: # Module/class not found
|
||||||
|
return
|
||||||
|
|
||||||
|
ret = plugin.run(args)
|
||||||
|
out = None
|
||||||
|
err = None
|
||||||
|
|
||||||
|
if isinstance(ret, list):
|
||||||
|
out = ret[0]
|
||||||
|
err = ret[1] if len(ret) > 1 else None
|
||||||
|
elif ret is not None:
|
||||||
|
out = ret
|
||||||
|
|
||||||
|
if out:
|
||||||
|
logging.info('Command output: {}'.format(out))
|
||||||
|
|
||||||
|
if err:
|
||||||
|
logging.warn('Command error: {}'.format(err))
|
||||||
|
except Exception as e:
|
||||||
|
logging.exception(e)
|
||||||
|
if retry:
|
||||||
|
logging.info('Reloading plugin {} and retrying'.format(plugin_name))
|
||||||
|
_init_plugin(plugin_name, reload=True)
|
||||||
|
_exec_func(body, retry=False)
|
||||||
|
|
||||||
|
|
||||||
def _on_push(ws, data):
|
def _on_push(ws, data):
|
||||||
|
|
Loading…
Reference in a new issue