From: Jaroslav Kysela Date: Thu, 31 Aug 2017 13:00:19 +0000 (+0200) Subject: tvh-json: more updates, added README.md X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=64fa5c4228dae8b63e450dd5dbb409eff9a075d3;p=thirdparty%2Ftvheadend.git tvh-json: more updates, added README.md --- diff --git a/lib/api/python/README.md b/lib/api/python/README.md new file mode 100644 index 000000000..e521ed15d --- /dev/null +++ b/lib/api/python/README.md @@ -0,0 +1,86 @@ +tvh-json.py +================================= +(c) 2017 Tvheadend Foundation CIC + +The json import / export tool written in the python language. + + +Background +---------- + +TVHeadend uses internal database called idnode. This database uses +unique identifier (UUID) for each entry. The entries may be linked +(thus some nodes may refer to another). The each entry belongs +to a class which defines the meta data (type, description). + + +Environment variables +--------------------- + +Name | Description +----------------------------------------------------------- +TVH_URL_API | URL like http://localhost:9981/api +TVH_USER | username for HTTP API +TVH_PASS | password for HTTP API + + +Command 'get' +------------- + +This is basic command which allows the elementary operation through +the HTTP API. Basically, almost all other commands uses this internally. + +Arguments: +* path +* json string (arguments) + + +Command 'pathlist' +------------------ + +Returns all path names. + + +Command 'classes' +----------------- + +Returns all class names. + + +Command 'import' +---------------- + +Imports the json data and updates the internal structure in TVHeadend's +database. The structure must be identical to data printed with the 'export' +command. + +Arguments: +* uuid +* filename (optional - otherwise standard input is used) + + +Command 'export' +---------------- + +Exports the json data from TVHeadend's database. + +Arguments: +* uuid + + +Command 'exportcls' +------------------- + +Exports the json data from TVHeadend's database for all idnodes which +belongs to the specified class. + +Arguments: +* class + + +Examples: +--------- + +`TVH_USER=admin TVH_PASS=admin ./tvh-json.py exportcls dvb_mux_dvbs` +`TVH_USER=admin TVH_PASS=admin ./tvh-json.py export 6dbdb849bd8eae9c1fecf684f773baca > a.json` +`TVH_USER=admin TVH_PASS=admin ./tvh-json.py import 6dbdb849bd8eae9c1fecf684f773baca < a.json` diff --git a/lib/api/python/tvh-json.py b/lib/api/python/tvh-json.py index d04baa1a0..fd5f67025 100755 --- a/lib/api/python/tvh-json.py +++ b/lib/api/python/tvh-json.py @@ -1,7 +1,7 @@ #! /usr/bin/env python # -# TVH bintray tool, compatible with both python2 and python3 +# TVH json import/export tool, compatible with both python2 and python3 # import os @@ -12,23 +12,21 @@ import traceback try: # Python 3 import urllib.request as urllib - from urllib.parse import urlencode + from urllib.parse import urlencode, quote except ImportError: # Python 2 import urllib2 as urllib - from urllib import urlencode + from urllib import urlencode, quote -def env(key): +def env(key, deflt): if key in os.environ: return os.environ[key] - return None + return deflt DEBUG=False -TVH_API=env('TVH_API_URL') or 'http://localhost:9981/api' -TVH_USER=env('TVH_USER') -TVH_PASS=env('TVH_PASS') - -PACKAGE_DESC='Tvheadend is a TV streaming server and recorder for Linux, FreeBSD and Android' +TVH_API=env('TVH_API_URL', 'http://localhost:9981/api') +TVH_USER=env('TVH_USER', None) +TVH_PASS=env('TVH_PASS', None) class Response(object): def __init__(self, response): @@ -71,7 +69,7 @@ class TVHeadend(object): if binary: content_type = 'application/binary' else: - data = data and urlencode(data) or None + data = data and urlencode(data).encode('utf-8') or None opener = self.opener() path = self._path if path[0] != '/': path = '/' + path @@ -92,10 +90,14 @@ class TVHeadend(object): def post(self, data): return self._push(data, method='POST') -def do_get(*args): +def do_get0(*args): if len(args) < 1: error(1, 'get [path] [json_query]') path = args[0] - query = len(args) > 1 and json.loads(args[1]) or None + query = None + if len(args) > 1: + query = args[1] + if type(query) != type({}): + query = json.loads(query.decode('utf-8')) if query: for q in query: r = query[q] @@ -104,16 +106,69 @@ def do_get(*args): resp = TVHeadend(path).post(query) if resp.code != 200 and resp.code != 201: error(10, 'HTTP ERROR "%s" %s %s', resp.url, resp.code, resp.reason) - if type(resp.body) == type({}) or type(resp.body) == type([]): - print(json.dumps(resp.body, indent=4, separators=(',', ': '))) + return resp.body + +def do_get(*args): + body = do_get0(*args) + if type(body) == type({}) or type(body) == type([]): + print(json.dumps(body, indent=4, separators=(',', ': '))) + else: + print(body) + +def do_export(*args): + if len(args) < 1: error(1, 'get [uuid]') + body = do_get0('raw/export', {'uuid':args[0]}) + if type(body) != type({}): + error(11, 'Unknown data') + if 'entries' in body: + body = body['entries'] + if len(body) == 1: + body = body[0] + if not 'uuid' in body: + body['uuid'] = args[0].strip() + print(json.dumps(body, indent=4, separators=(',', ': '))) + +def do_exportcls(*args): + if len(args) < 1: error(1, 'get [class]') + body = do_get0('raw/export', {'class':args[0]}) + if type(body) != type({}) and type(body) != type([]): + error(11, 'Unknown data') + if 'entries' in body: + body = body['entries'] + if len(body) == 1: + body = body[0] + print(json.dumps(body, indent=4, separators=(',', ': '))) + +def do_import(*args): + if len(args) < 1: + jdata = sys.stdin.read() else: - print(resp.body) + fp = open(args[0]) + jdata = fp.read() + fp.close() + jdata = json.loads(jdata.decode('utf-8')) + body = do_get0('raw/import', {'node':jdata}) + if body and type(body) != type({}): + error(11, 'Unknown data / response') + +def do_paths(*args): + do_get('pathlist') + +def do_classes(*args): + do_get('classes') + +def do_unknown(*args): + r = 'Please, specify a valid command:\n' + for n in globals(): + if n.startswith('do_') and n != 'do_unknown': + r += ' ' + n[3:] + '\n' + error(1, r[:-1]) def main(argv): global DEBUG if not TVH_USER or not TVH_PASS: error(2, 'No credentals') - if argv[1] == '--debug': + if len(argv) > 1 and argv[1] == '--debug': DEBUG=1 argv.pop(0) cmd = 'do_' + (len(argv) > 1 and argv[1] or 'unknown')