128 lines
4.2 KiB
Python
Executable file
128 lines
4.2 KiB
Python
Executable file
#!python
|
|
|
|
import argparse
|
|
import json
|
|
import os
|
|
import re
|
|
import sys
|
|
import yaml
|
|
|
|
from pushbullet import Pushbullet
|
|
from runbullet import parse_config_file
|
|
from runbullet.backend.kafka import KafkaBackend
|
|
from runbullet.backend.local import LocalBackend
|
|
|
|
|
|
def print_usage():
|
|
print ('''Usage: {} [-h|--help] <-t|--target <target name>> <-a|--action <action name>> payload
|
|
-h, --help:\t\tShow this help and exit
|
|
-b, --backend:\tBackend to deliver the message [pushbullet|kafka] (default: whatever specified in your config with pusher=True)
|
|
-t, --target:\tName of the target device/host
|
|
-a, --action\tAction to run, it includes both the package name and the method (e.g. shell.exec or music.mpd.play)
|
|
payload:\t\tArguments to the action
|
|
'''.format(sys.argv[0]))
|
|
|
|
def get_pb_device_by_name(pb, name):
|
|
devices = [
|
|
_ for _ in pb.devices if _.nickname == name
|
|
]
|
|
|
|
return devices[0] if devices else None
|
|
|
|
def send_pb_message(pb, device_name, msg):
|
|
device = get_pb_device_by_name(pb, name=device_name)
|
|
if not device:
|
|
print('Device {} not found - please create a virtual device on ' +
|
|
'your PushBullet account'.format(config['backend.pushbullet']['device']))
|
|
return
|
|
|
|
pb.push_note('', json.dumps(msg), device)
|
|
|
|
def send_kafka_message(backend, msg):
|
|
backend.send_msg(msg)
|
|
|
|
def send_local_message(backend, msg):
|
|
backend.send_msg(msg)
|
|
|
|
def get_backend(config):
|
|
# TODO Refactor this as something better and reuse the same
|
|
# backend classes from the runbullet consumer module
|
|
if 'backend.local' in config \
|
|
and 'pusher' in config['backend.local'] \
|
|
and config['backend.local']['pusher']:
|
|
c = config['backend.local']
|
|
return LocalBackend({'fifo': c['fifo']})
|
|
elif 'backend.pushbullet' in config \
|
|
and 'pusher' in config['backend.pushbullet'] \
|
|
and config['backend.pushbullet']['pusher']:
|
|
API_KEY = config['backend.pushbullet']['token']
|
|
return Pushbullet(API_KEY)
|
|
elif 'backend.kafka' in config \
|
|
and 'pusher' in config['backend.kafka'] \
|
|
and config['backend.kafka']['pusher']:
|
|
c = config['backend.kafka']
|
|
return KafkaBackend({'server':c['server'], 'topic':c['topic']})
|
|
|
|
def main():
|
|
config = parse_config_file()
|
|
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('--target', '-t', dest='target', required=True,
|
|
help="Destination of the command")
|
|
|
|
parser.add_argument('--action', '-a', dest='action', required=True,
|
|
help="Action to execute, as package.method")
|
|
|
|
parser.add_argument('--backend', '-b', dest='backend', required=False,
|
|
help="Backend to deliver the message " +
|
|
"[pushbullet|kafka|local] (default: whatever " +
|
|
"specified in your config with pusher=True)")
|
|
|
|
opts, args = parser.parse_known_args(sys.argv[1:])
|
|
payload = {}
|
|
|
|
if len(args) % 2 != 0:
|
|
raise RuntimeError('Odd number of key-value options passed: {}'.
|
|
format(args))
|
|
|
|
if opts.target == 'localhost' and 'backend.local' in config:
|
|
cfg = config['backend.local']
|
|
cfg['pusher'] = True
|
|
config = { 'backend.local': cfg }
|
|
|
|
if opts.backend:
|
|
backend_cfg_name = 'backend.' + opts.backend
|
|
if backend_cfg_name not in config:
|
|
raise RuntimeError('{} backend specified, but no configuration ' +
|
|
'for it available'.format(backend_cfg_name))
|
|
|
|
cfg = config[backend_cfg_name]
|
|
cfg['pusher'] = True
|
|
config = { backend_cfg_name: cfg }
|
|
|
|
backend = get_backend(config)
|
|
|
|
for i in range(0, len(args), 2):
|
|
payload[re.sub('^-+', '', args[i])] = args[i+1]
|
|
|
|
msg = {
|
|
'target': opts.target,
|
|
'action': opts.action,
|
|
**payload,
|
|
}
|
|
|
|
print('msg: {}'.format(msg))
|
|
|
|
if isinstance(backend, Pushbullet):
|
|
send_pb_message(backend, config['backend.pushbullet']['device'], msg)
|
|
elif isinstance(backend, KafkaBackend):
|
|
send_kafka_message(backend, msg)
|
|
elif isinstance(backend, LocalBackend):
|
|
send_local_message(backend, msg)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|
|
|
|
# vim:sw=4:ts=4:et:
|
|
|