mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-13 08:42:59 -07:00
commit
be4e8985b7
3 changed files with 471 additions and 142 deletions
57
API.md
57
API.md
|
@ -4,24 +4,77 @@ The API is still pretty new and needs some serious cleaning up on the backend bu
|
|||
## General structure
|
||||
The API endpoint is `http://ip:port + HTTP_ROOT + /api?apikey=$apikey&cmd=$command`
|
||||
|
||||
Data response in JSON formatted.
|
||||
Response example
|
||||
```
|
||||
{
|
||||
"response": {
|
||||
"data": [
|
||||
{
|
||||
"loglevel": "INFO",
|
||||
"msg": "Signal 2 caught, saving and exiting...",
|
||||
"thread": "MainThread",
|
||||
"time": "22-sep-2015 01:42:56 "
|
||||
}
|
||||
],
|
||||
"message": null,
|
||||
"result": "success"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
General parameters:
|
||||
out_type: 'xml',
|
||||
callback: 'pong',
|
||||
'debug': 1
|
||||
|
||||
|
||||
## API methods
|
||||
|
||||
### getLogs
|
||||
Not working yet
|
||||
Possible params: sort='', search='', order='desc', regex='', start=0, end=0
|
||||
Returns the plexpy log
|
||||
|
||||
### getApikey
|
||||
Possible params: username='', password='' (required if auth is enabled)
|
||||
Returns the apikey
|
||||
|
||||
### getSettings
|
||||
No params
|
||||
Returns the config file
|
||||
|
||||
### getVersion
|
||||
No params
|
||||
Returns some version information: git_path, install_type, current_version, installed_version, commits_behind
|
||||
|
||||
### getHistory
|
||||
possible params: user=None, user_id=None, ,rating_key='', parent_rating_key='', grandparent_rating_key='', start_date=''
|
||||
Returns
|
||||
|
||||
### getMetadata
|
||||
Required params: rating_key
|
||||
Returns metadata about a file
|
||||
|
||||
### getSync
|
||||
Possible params: machine_id=None, user_id=None,
|
||||
Returns
|
||||
|
||||
### getUserips
|
||||
Possible params: user_id=None, user=None
|
||||
|
||||
### getPlayby
|
||||
Possible params: time_range=30, y_axis='plays', playtype='total_plays_per_month'
|
||||
|
||||
### checkGithub
|
||||
Updates the version information above and returns getVersion data
|
||||
|
||||
### shutdown
|
||||
No params
|
||||
Shut down plexpy
|
||||
|
||||
### restart
|
||||
No params
|
||||
Restart plexpy
|
||||
|
||||
### update
|
||||
No params
|
||||
Update plexpy - you may want to check the install type in get version and not allow this if type==exe
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This file is part of PlexPy.
|
||||
#
|
||||
# PlexPy is free software: you can redistribute it and/or modify
|
||||
|
|
546
plexpy/api.py
546
plexpy/api.py
|
@ -1,3 +1,6 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This file is part of PlexPy.
|
||||
#
|
||||
# PlexPy is free software: you can redistribute it and/or modify
|
||||
|
@ -13,86 +16,143 @@
|
|||
# You should have received a copy of the GNU General Public License
|
||||
# along with PlexPy. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from plexpy import db, cache, versioncheck, logger, helpers
|
||||
|
||||
from plexpy import versioncheck, logger, plextv, pmsconnect, datafactory, graphs, users
|
||||
import os
|
||||
import plexpy
|
||||
import json
|
||||
from xml.dom import minidom
|
||||
import traceback
|
||||
import cherrypy
|
||||
import re
|
||||
import hashlib
|
||||
import random
|
||||
import xmltodict
|
||||
|
||||
cmd_list = ['getHistory', 'getLogs', 'getVersion', 'checkGithub', 'shutdown', 'restart', 'update']
|
||||
cmd_list = ['getLogs', 'getVersion', 'checkGithub', 'shutdown',
|
||||
'getSettings', 'restart', 'update', 'getApikey', 'getHistory',
|
||||
'getMetadata', 'getUserips', 'getPlayby', 'getSync']
|
||||
|
||||
|
||||
class Api(object):
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, out='json'):
|
||||
|
||||
self.apikey = None
|
||||
self.authenticated = False
|
||||
self.cmd = None
|
||||
self.id = None
|
||||
|
||||
self.kwargs = None
|
||||
|
||||
# For the responses
|
||||
self.data = None
|
||||
|
||||
self.msg = None
|
||||
self.result_type = 'error'
|
||||
# Possible general params
|
||||
self.callback = None
|
||||
self.out_type = out
|
||||
self.debug = None
|
||||
|
||||
def checkParams(self, *args, **kwargs):
|
||||
|
||||
if not plexpy.CONFIG.API_ENABLED:
|
||||
self.data = 'API not enabled'
|
||||
return
|
||||
if not plexpy.CONFIG.API_KEY:
|
||||
self.data = 'API key not generated'
|
||||
return
|
||||
if len(plexpy.CONFIG.API_KEY) != 32:
|
||||
self.data = 'API key not generated correctly'
|
||||
return
|
||||
self.msg = 'API not enabled'
|
||||
elif not plexpy.CONFIG.API_KEY:
|
||||
self.msg = 'API key not generated'
|
||||
elif len(plexpy.CONFIG.API_KEY) != 32:
|
||||
self.msg = 'API key not generated correctly'
|
||||
elif 'apikey' not in kwargs:
|
||||
self.msg = 'Parameter apikey is required'
|
||||
elif kwargs.get('apikey', '') != plexpy.CONFIG.API_KEY:
|
||||
self.msg = 'Invalid apikey'
|
||||
elif 'cmd' not in kwargs:
|
||||
self.msg = 'Parameter %s required. possible commands are: %s' % ', '.join(cmd_list)
|
||||
elif 'cmd' in kwargs and kwargs.get('cmd') not in cmd_list:
|
||||
self.msg = 'Unknown command, %s possible commands are: %s' % (kwargs.get('cmd', ''), ', '.join(cmd_list))
|
||||
|
||||
if 'apikey' not in kwargs:
|
||||
self.data = 'Missing api key'
|
||||
return
|
||||
# Set default values or remove them from kwargs
|
||||
|
||||
if kwargs['apikey'] != plexpy.CONFIG.API_KEY:
|
||||
self.data = 'Incorrect API key'
|
||||
return
|
||||
else:
|
||||
self.apikey = kwargs.pop('apikey')
|
||||
self.callback = kwargs.pop('callback', None)
|
||||
self.apikey = kwargs.pop('apikey', None)
|
||||
self.cmd = kwargs.pop('cmd', None)
|
||||
self.debug = kwargs.pop('debug', False)
|
||||
# Allow override for the api.
|
||||
self.out_type = kwargs.pop('out_type', 'json')
|
||||
|
||||
if 'cmd' not in kwargs:
|
||||
self.data = 'Missing parameter: cmd'
|
||||
return
|
||||
|
||||
if kwargs['cmd'] not in cmd_list:
|
||||
self.data = 'Unknown command: %s' % kwargs['cmd']
|
||||
return
|
||||
else:
|
||||
self.cmd = kwargs.pop('cmd')
|
||||
if self.apikey == plexpy.CONFIG.API_KEY and plexpy.CONFIG.API_ENABLED and self.cmd in cmd_list:
|
||||
self.authenticated = True
|
||||
self.msg = None
|
||||
elif self.cmd == 'getApikey' and plexpy.CONFIG.API_ENABLED:
|
||||
self.authenticated = True
|
||||
# Remove the old error msg
|
||||
self.msg = None
|
||||
|
||||
self.kwargs = kwargs
|
||||
self.data = 'OK'
|
||||
|
||||
def _responds(self, result_type='success', data=None, msg=''):
|
||||
|
||||
if data is None:
|
||||
data = {}
|
||||
return {"response": {"result": result_type, "message": msg, "data": data}}
|
||||
|
||||
def _out_as(self, out):
|
||||
|
||||
if self.out_type == 'json':
|
||||
cherrypy.response.headers['Content-Type'] = 'application/json;charset=UTF-8'
|
||||
try:
|
||||
out = json.dumps(out, indent=4, sort_keys=True)
|
||||
if self.callback is not None:
|
||||
cherrypy.response.headers['Content-Type'] = 'application/javascript'
|
||||
# wrap with JSONP call if requested
|
||||
out = self.callback + '(' + out + ');'
|
||||
# if we fail to generate the output fake an error
|
||||
except Exception as e:
|
||||
logger.info(u"API :: " + traceback.format_exc())
|
||||
out['message'] = traceback.format_exc()
|
||||
out['result'] = 'error'
|
||||
if self.out_type == 'xml':
|
||||
cherrypy.response.headers['Content-Type'] = 'application/xml'
|
||||
try:
|
||||
out = xmltodict.unparse(out, pretty=True)
|
||||
except ValueError as e:
|
||||
logger.error('Failed to parse xml result')
|
||||
try:
|
||||
out['message'] = e
|
||||
out['result'] = 'error'
|
||||
out = xmltodict.unparse(out, pretty=True)
|
||||
|
||||
except Exception as e:
|
||||
logger.error('Failed to parse xml result error message')
|
||||
out = '''<?xml version="1.0" encoding="utf-8"?>
|
||||
<response>
|
||||
<message>%s</message>
|
||||
<data></data>
|
||||
<result>error</result>
|
||||
</response>
|
||||
''' % e
|
||||
|
||||
return out
|
||||
|
||||
def fetchData(self):
|
||||
|
||||
if self.data == 'OK':
|
||||
logger.info('Recieved API command: %s', self.cmd)
|
||||
methodToCall = getattr(self, "_" + self.cmd)
|
||||
methodToCall(**self.kwargs)
|
||||
if 'callback' not in self.kwargs:
|
||||
if isinstance(self.data, basestring):
|
||||
return self.data
|
||||
logger.info('Recieved API command: %s' % self.cmd)
|
||||
if self.cmd and self.authenticated:
|
||||
methodtocall = getattr(self, "_" + self.cmd)
|
||||
# Let the traceback hit cherrypy so we can
|
||||
# see the traceback there
|
||||
if self.debug:
|
||||
methodtocall(**self.kwargs)
|
||||
else:
|
||||
return json.dumps(self.data)
|
||||
else:
|
||||
self.callback = self.kwargs['callback']
|
||||
self.data = json.dumps(self.data)
|
||||
self.data = self.callback + '(' + self.data + ');'
|
||||
return self.data
|
||||
else:
|
||||
return self.data
|
||||
try:
|
||||
methodtocall(**self.kwargs)
|
||||
except Exception as e:
|
||||
logger.error(traceback.format_exc())
|
||||
|
||||
# Im just lazy, fix me plx
|
||||
if self.data or isinstance(self.data, (dict, list)):
|
||||
if len(self.data):
|
||||
self.result_type = 'success'
|
||||
|
||||
return self._out_as(self._responds(result_type=self.result_type, msg=self.msg, data=self.data))
|
||||
|
||||
def _dic_from_query(self, query):
|
||||
|
||||
myDB = db.DBConnection()
|
||||
myDB = database.DBConnection()
|
||||
rows = myDB.select(query)
|
||||
|
||||
rows_as_dic = []
|
||||
|
@ -103,104 +163,115 @@ class Api(object):
|
|||
|
||||
return rows_as_dic
|
||||
|
||||
def _getHistory(self, iDisplayStart=0, iDisplayLength=100, sSearch="", iSortCol_0='0', sSortDir_0='asc', **kwargs):
|
||||
iDisplayStart = int(iDisplayStart)
|
||||
iDisplayLength = int(iDisplayLength)
|
||||
filtered = []
|
||||
totalcount = 0
|
||||
myDB = db.DBConnection()
|
||||
db_table = db.DBConnection().get_history_table_name()
|
||||
def _getApikey(self, username='', password=''):
|
||||
""" Returns api key, requires username and password is active """
|
||||
|
||||
sortcolumn = 'time'
|
||||
sortbyhavepercent = False
|
||||
if iSortCol_0 == '1':
|
||||
sortcolumn = 'user'
|
||||
if iSortCol_0 == '2':
|
||||
sortcolumn = 'platform'
|
||||
elif iSortCol_0 == '3':
|
||||
sortcolumn = 'ip_address'
|
||||
elif iSortCol_0 == '4':
|
||||
sortcolumn = 'title'
|
||||
elif iSortCol_0 == '5':
|
||||
sortcolumn = 'time'
|
||||
elif iSortCol_0 == '6':
|
||||
sortcolumn = 'paused_counter'
|
||||
elif iSortCol_0 == '7':
|
||||
sortcolumn = 'stopped'
|
||||
elif iSortCol_0 == '8':
|
||||
sortbyhavepercent = True
|
||||
|
||||
if sSearch == "":
|
||||
query = 'SELECT * from %s order by %s COLLATE NOCASE %s' % (db_table, sortcolumn, sSortDir_0)
|
||||
filtered = myDB.select(query)
|
||||
totalcount = len(filtered)
|
||||
apikey = hashlib.sha224(str(random.getrandbits(256))).hexdigest()[0:32]
|
||||
if plexpy.CONFIG.HTTP_USERNAME and plexpy.CONFIG.HTTP_PASSWORD:
|
||||
if username == plexpy.HTTP_USERNAME and password == plexpy.CONFIG.HTTP_PASSWORD:
|
||||
if plexpy.CONFIG.API_KEY:
|
||||
self.data = plexpy.CONFIG.API_KEY
|
||||
else:
|
||||
query = 'SELECT * from ' + db_table + ' WHERE user LIKE "%' + sSearch + \
|
||||
'%" OR title LIKE "%' + sSearch + '%"' + 'ORDER BY %s COLLATE NOCASE %s' % (sortcolumn, sSortDir_0)
|
||||
filtered = myDB.select(query)
|
||||
totalcount = myDB.select('SELECT COUNT(*) from processed')[0][0]
|
||||
self.data = apikey
|
||||
plexpy.CONFIG.API_KEY = apikey
|
||||
plexpy.CONFIG.write()
|
||||
else:
|
||||
self.msg = 'Authentication is enabled, please add the correct username and password to the parameters'
|
||||
else:
|
||||
if plexpy.CONFIG.API_KEY:
|
||||
self.data = plexpy.CONFIG.API_KEY
|
||||
else:
|
||||
# Make a apikey if the doesn't exist
|
||||
self.data = apikey
|
||||
plexpy.CONFIG.API_KEY = apikey
|
||||
plexpy.CONFIG.write()
|
||||
|
||||
history = filtered[iDisplayStart:(iDisplayStart + iDisplayLength)]
|
||||
rows = []
|
||||
for item in history:
|
||||
row = {"date": item['time'],
|
||||
"user": item["user"],
|
||||
"platform": item["platform"],
|
||||
"ip_address": item["ip_address"],
|
||||
"title": item["title"],
|
||||
"started": item["time"],
|
||||
"paused": item["paused_counter"],
|
||||
"stopped": item["stopped"],
|
||||
"duration": "",
|
||||
"percent_complete": 0,
|
||||
return self.data
|
||||
|
||||
def _getLogs(self, sort='', search='', order='desc', regex='', **kwargs):
|
||||
"""
|
||||
Returns the log
|
||||
|
||||
Returns [{"response":
|
||||
{"msg": "Hey",
|
||||
"result": "success"},
|
||||
"data": [{"time": "29-sept.2015",
|
||||
"thread: "MainThread",
|
||||
"msg: "Called x from y",
|
||||
"loglevel": "DEBUG"
|
||||
}
|
||||
]
|
||||
|
||||
if item['paused_counter'] > 0:
|
||||
row['paused'] = item['paused_counter']
|
||||
else:
|
||||
row['paused'] = 0
|
||||
}
|
||||
]
|
||||
"""
|
||||
logfile = os.path.join(plexpy.CONFIG.LOG_DIR, 'plexpy.log')
|
||||
templog = []
|
||||
start = int(kwargs.get('start', 0))
|
||||
end = int(kwargs.get('end', 0))
|
||||
|
||||
if item['time']:
|
||||
if item['stopped'] > 0:
|
||||
stopped = item['stopped']
|
||||
else:
|
||||
stopped = 0
|
||||
if item['paused_counter'] > 0:
|
||||
paused_counter = item['paused_counter']
|
||||
else:
|
||||
paused_counter = 0
|
||||
if regex:
|
||||
logger.debug('Filtering log using regex %s' % regex)
|
||||
reg = re.compile('u' + regex, flags=re.I)
|
||||
|
||||
row['duration'] = stopped - item['time'] + paused_counter
|
||||
for line in open(logfile, 'r').readlines():
|
||||
temp_loglevel_and_time = None
|
||||
|
||||
try:
|
||||
xml_parse = minidom.parseString(helpers.latinToAscii(item['xml']))
|
||||
except IOError, e:
|
||||
logger.warn("Error parsing XML in PlexWatch db: %s" % e)
|
||||
|
||||
xml_head = xml_parse.getElementsByTagName('opt')
|
||||
if not xml_head:
|
||||
logger.warn("Error parsing XML in PlexWatch db: %s" % e)
|
||||
|
||||
for s in xml_head:
|
||||
if s.getAttribute('duration') and s.getAttribute('viewOffset'):
|
||||
view_offset = helpers.cast_to_float(s.getAttribute('viewOffset'))
|
||||
duration = helpers.cast_to_float(s.getAttribute('duration'))
|
||||
if duration > 0:
|
||||
row['percent_complete'] = (view_offset / duration)*100
|
||||
temp_loglevel_and_time = line.split('- ')
|
||||
loglvl = temp_loglevel_and_time[1].split(' :')[0].strip()
|
||||
tl_tread = line.split(' :: ')
|
||||
if loglvl is None:
|
||||
msg = line.replace('\n', '')
|
||||
else:
|
||||
row['percent_complete'] = 0
|
||||
msg = line.split(' : ')[1].replace('\n', '')
|
||||
thread = tl_tread[1].split(' : ')[0]
|
||||
except IndexError:
|
||||
# We assume this is a traceback
|
||||
tl = (len(templog) - 1)
|
||||
templog[tl]['msg'] += line.replace('\n', '')
|
||||
continue
|
||||
|
||||
rows.append(row)
|
||||
if len(line) > 1 and temp_loglevel_and_time is not None and loglvl in line:
|
||||
|
||||
dict = {'iTotalDisplayRecords': len(filtered),
|
||||
'iTotalRecords': totalcount,
|
||||
'aaData': rows,
|
||||
d = {
|
||||
'time': temp_loglevel_and_time[0],
|
||||
'loglevel': loglvl,
|
||||
'msg': msg.replace('\n', ''),
|
||||
'thread': thread
|
||||
}
|
||||
self.data = json.dumps(dict)
|
||||
#cherrypy.response.headers['Content-type'] = 'application/json'
|
||||
templog.append(d)
|
||||
|
||||
def _getLogs(self, **kwargs):
|
||||
pass
|
||||
if end > 0:
|
||||
logger.debug('Slicing the log from %s to %s' % (start, end))
|
||||
templog = templog[start:end]
|
||||
|
||||
if sort:
|
||||
logger.debug('Sorting log based on %s' % sort)
|
||||
templog = sorted(templog, key=lambda k: k[sort])
|
||||
|
||||
if search:
|
||||
logger.debug('Searching log values for %s' % search)
|
||||
tt = [d for d in templog for k, v in d.items() if search.lower() in v.lower()]
|
||||
|
||||
if len(tt):
|
||||
templog = tt
|
||||
|
||||
if regex:
|
||||
tt = []
|
||||
for l in templog:
|
||||
stringdict = ' '.join('{}{}'.format(k, v) for k, v in l.items())
|
||||
if reg.search(stringdict):
|
||||
tt.append(l)
|
||||
|
||||
if len(tt):
|
||||
templog = tt
|
||||
|
||||
if order == 'desc':
|
||||
templog = templog[::-1]
|
||||
|
||||
self.data = templog
|
||||
return templog
|
||||
|
||||
def _getVersion(self, **kwargs):
|
||||
self.data = {
|
||||
|
@ -210,6 +281,7 @@ class Api(object):
|
|||
'latest_version': plexpy.LATEST_VERSION,
|
||||
'commits_behind': plexpy.COMMITS_BEHIND,
|
||||
}
|
||||
self.result_type = 'success'
|
||||
|
||||
def _checkGithub(self, **kwargs):
|
||||
versioncheck.checkGithub()
|
||||
|
@ -217,9 +289,211 @@ class Api(object):
|
|||
|
||||
def _shutdown(self, **kwargs):
|
||||
plexpy.SIGNAL = 'shutdown'
|
||||
self.msg = 'Shutting down plexpy'
|
||||
self.result_type = 'success'
|
||||
|
||||
def _restart(self, **kwargs):
|
||||
plexpy.SIGNAL = 'restart'
|
||||
self.msg = 'Restarting plexpy'
|
||||
self.result_type = 'success'
|
||||
|
||||
def _update(self, **kwargs):
|
||||
plexpy.SIGNAL = 'update'
|
||||
self.msg = 'Updating plexpy'
|
||||
self.result_type = 'success'
|
||||
|
||||
def _getHistory(self, user=None, user_id=None, rating_key='', parent_rating_key='', grandparent_rating_key='', start_date='', **kwargs):
|
||||
|
||||
custom_where = []
|
||||
if user_id:
|
||||
custom_where = [['user_id', user_id]]
|
||||
elif user:
|
||||
custom_where = [['user', user]]
|
||||
if 'rating_key' in kwargs:
|
||||
rating_key = kwargs.get('rating_key', "")
|
||||
custom_where = [['rating_key', rating_key]]
|
||||
if 'parent_rating_key' in kwargs:
|
||||
rating_key = kwargs.get('parent_rating_key', "")
|
||||
custom_where = [['parent_rating_key', rating_key]]
|
||||
if 'grandparent_rating_key' in kwargs:
|
||||
rating_key = kwargs.get('grandparent_rating_key', "")
|
||||
custom_where = [['grandparent_rating_key', rating_key]]
|
||||
if 'start_date' in kwargs:
|
||||
start_date = kwargs.get('start_date', "")
|
||||
custom_where = [['strftime("%Y-%m-%d", datetime(date, "unixepoch", "localtime"))', start_date]]
|
||||
|
||||
data_factory = datafactory.DataFactory()
|
||||
history = data_factory.get_history(kwargs=kwargs, custom_where=custom_where)
|
||||
|
||||
self.data = history
|
||||
return self.data
|
||||
|
||||
def _getSync(self, machine_id=None, user_id=None, **kwargs):
|
||||
|
||||
pms_connect = pmsconnect.PmsConnect()
|
||||
server_id = pms_connect.get_server_identity()
|
||||
|
||||
plex_tv = plextv.PlexTV()
|
||||
if not machine_id:
|
||||
result = plex_tv.get_synced_items(machine_id=server_id['machine_identifier'], user_id=user_id)
|
||||
else:
|
||||
result = plex_tv.get_synced_items(machine_id=machine_id, user_id=user_id)
|
||||
|
||||
if result:
|
||||
self.data = result
|
||||
return result
|
||||
else:
|
||||
self.msg = 'Unable to retrieve sync data for user'
|
||||
logger.warn('Unable to retrieve sync data for user.')
|
||||
|
||||
def _getMetadata(self, rating_key='', **kwargs):
|
||||
|
||||
pms_connect = pmsconnect.PmsConnect()
|
||||
result = pms_connect.get_metadata(rating_key, 'dict')
|
||||
|
||||
if result:
|
||||
self.data = result
|
||||
return result
|
||||
else:
|
||||
self.msg = 'Unable to retrive metadata %s' % rating_key
|
||||
logger.warn('Unable to retrieve data.')
|
||||
|
||||
def _getSettings(self):
|
||||
interface_dir = os.path.join(plexpy.PROG_DIR, 'data/interfaces/')
|
||||
interface_list = [name for name in os.listdir(interface_dir) if
|
||||
os.path.isdir(os.path.join(interface_dir, name))]
|
||||
|
||||
config = {
|
||||
"http_host": plexpy.CONFIG.HTTP_HOST,
|
||||
"http_username": plexpy.CONFIG.HTTP_USERNAME,
|
||||
"http_port": plexpy.CONFIG.HTTP_PORT,
|
||||
"http_password": plexpy.CONFIG.HTTP_PASSWORD,
|
||||
"launch_browser": bool(plexpy.CONFIG.LAUNCH_BROWSER),
|
||||
"enable_https": bool(plexpy.CONFIG.ENABLE_HTTPS),
|
||||
"https_cert": plexpy.CONFIG.HTTPS_CERT,
|
||||
"https_key": plexpy.CONFIG.HTTPS_KEY,
|
||||
"api_enabled": plexpy.CONFIG.API_ENABLED,
|
||||
"api_key": plexpy.CONFIG.API_KEY,
|
||||
"update_db_interval": plexpy.CONFIG.UPDATE_DB_INTERVAL,
|
||||
"freeze_db": bool(plexpy.CONFIG.FREEZE_DB),
|
||||
"log_dir": plexpy.CONFIG.LOG_DIR,
|
||||
"cache_dir": plexpy.CONFIG.CACHE_DIR,
|
||||
"check_github": bool(plexpy.CONFIG.CHECK_GITHUB),
|
||||
"interface_list": interface_list,
|
||||
"cache_sizemb": plexpy.CONFIG.CACHE_SIZEMB,
|
||||
"pms_identifier": plexpy.CONFIG.PMS_IDENTIFIER,
|
||||
"pms_ip": plexpy.CONFIG.PMS_IP,
|
||||
"pms_logs_folder": plexpy.CONFIG.PMS_LOGS_FOLDER,
|
||||
"pms_port": plexpy.CONFIG.PMS_PORT,
|
||||
"pms_token": plexpy.CONFIG.PMS_TOKEN,
|
||||
"pms_ssl": bool(plexpy.CONFIG.PMS_SSL),
|
||||
"pms_use_bif": bool(plexpy.CONFIG.PMS_USE_BIF),
|
||||
"pms_uuid": plexpy.CONFIG.PMS_UUID,
|
||||
"date_format": plexpy.CONFIG.DATE_FORMAT,
|
||||
"time_format": plexpy.CONFIG.TIME_FORMAT,
|
||||
"grouping_global_history": bool(plexpy.CONFIG.GROUPING_GLOBAL_HISTORY),
|
||||
"grouping_user_history": bool(plexpy.CONFIG.GROUPING_USER_HISTORY),
|
||||
"grouping_charts": bool(plexpy.CONFIG.GROUPING_CHARTS),
|
||||
"tv_notify_enable": bool(plexpy.CONFIG.TV_NOTIFY_ENABLE),
|
||||
"movie_notify_enable": bool(plexpy.CONFIG.MOVIE_NOTIFY_ENABLE),
|
||||
"music_notify_enable": bool(plexpy.CONFIG.MUSIC_NOTIFY_ENABLE),
|
||||
"tv_notify_on_start": bool(plexpy.CONFIG.TV_NOTIFY_ON_START),
|
||||
"movie_notify_on_start": bool(plexpy.CONFIG.MOVIE_NOTIFY_ON_START),
|
||||
"music_notify_on_start": bool(plexpy.CONFIG.MUSIC_NOTIFY_ON_START),
|
||||
"tv_notify_on_stop": bool(plexpy.CONFIG.TV_NOTIFY_ON_STOP),
|
||||
"movie_notify_on_stop": bool(plexpy.CONFIG.MOVIE_NOTIFY_ON_STOP),
|
||||
"music_notify_on_stop": bool(plexpy.CONFIG.MUSIC_NOTIFY_ON_STOP),
|
||||
"tv_notify_on_pause": bool(plexpy.CONFIG.TV_NOTIFY_ON_PAUSE),
|
||||
"movie_notify_on_pause": bool(plexpy.CONFIG.MOVIE_NOTIFY_ON_PAUSE),
|
||||
"music_notify_on_pause": bool(plexpy.CONFIG.MUSIC_NOTIFY_ON_PAUSE),
|
||||
"monitoring_interval": plexpy.CONFIG.MONITORING_INTERVAL,
|
||||
"refresh_users_interval": plexpy.CONFIG.REFRESH_USERS_INTERVAL,
|
||||
"refresh_users_on_startup": bool(plexpy.CONFIG.REFRESH_USERS_ON_STARTUP),
|
||||
"ip_logging_enable": bool(plexpy.CONFIG.IP_LOGGING_ENABLE),
|
||||
"video_logging_enable": bool(plexpy.CONFIG.VIDEO_LOGGING_ENABLE),
|
||||
"music_logging_enable": bool(plexpy.CONFIG.MUSIC_LOGGING_ENABLE),
|
||||
"logging_ignore_interval": plexpy.CONFIG.LOGGING_IGNORE_INTERVAL,
|
||||
"pms_is_remote": bool(plexpy.CONFIG.PMS_IS_REMOTE),
|
||||
"notify_watched_percent": plexpy.CONFIG.NOTIFY_WATCHED_PERCENT,
|
||||
"notify_on_start_subject_text": plexpy.CONFIG.NOTIFY_ON_START_SUBJECT_TEXT,
|
||||
"notify_on_start_body_text": plexpy.CONFIG.NOTIFY_ON_START_BODY_TEXT,
|
||||
"notify_on_stop_subject_text": plexpy.CONFIG.NOTIFY_ON_STOP_SUBJECT_TEXT,
|
||||
"notify_on_stop_body_text": plexpy.CONFIG.NOTIFY_ON_STOP_BODY_TEXT,
|
||||
"notify_on_pause_subject_text": plexpy.CONFIG.NOTIFY_ON_PAUSE_SUBJECT_TEXT,
|
||||
"notify_on_pause_body_text": plexpy.CONFIG.NOTIFY_ON_PAUSE_BODY_TEXT,
|
||||
"notify_on_resume_subject_text": plexpy.CONFIG.NOTIFY_ON_RESUME_SUBJECT_TEXT,
|
||||
"notify_on_resume_body_text": plexpy.CONFIG.NOTIFY_ON_RESUME_BODY_TEXT,
|
||||
"notify_on_buffer_subject_text": plexpy.CONFIG.NOTIFY_ON_BUFFER_SUBJECT_TEXT,
|
||||
"notify_on_buffer_body_text": plexpy.CONFIG.NOTIFY_ON_BUFFER_BODY_TEXT,
|
||||
"notify_on_watched_subject_text": plexpy.CONFIG.NOTIFY_ON_WATCHED_SUBJECT_TEXT,
|
||||
"notify_on_watched_body_text": plexpy.CONFIG.NOTIFY_ON_WATCHED_BODY_TEXT,
|
||||
"home_stats_length": plexpy.CONFIG.HOME_STATS_LENGTH,
|
||||
"home_stats_type": bool(plexpy.CONFIG.HOME_STATS_TYPE),
|
||||
"home_stats_count": plexpy.CONFIG.HOME_STATS_COUNT,
|
||||
"home_stats_cards": plexpy.CONFIG.HOME_STATS_CARDS,
|
||||
"home_library_cards": plexpy.CONFIG.HOME_LIBRARY_CARDS,
|
||||
"buffer_threshold": plexpy.CONFIG.BUFFER_THRESHOLD,
|
||||
"buffer_wait": plexpy.CONFIG.BUFFER_WAIT
|
||||
}
|
||||
|
||||
self.data = config
|
||||
return config
|
||||
|
||||
def _getUserips(self, user_id=None, user=None, **kwargs):
|
||||
custom_where = []
|
||||
if user_id:
|
||||
custom_where = [['user_id', user_id]]
|
||||
elif user:
|
||||
custom_where = [['user', user]]
|
||||
|
||||
user_data = users.Users()
|
||||
history = user_data.get_user_unique_ips(kwargs=kwargs,
|
||||
custom_where=custom_where)
|
||||
|
||||
if history:
|
||||
self.data = history
|
||||
return history
|
||||
else:
|
||||
self.msg = 'Failed to find users ips'
|
||||
|
||||
def _getPlayby(self, time_range='30', y_axis='plays', playtype='total_plays_per_month', **kwargs):
|
||||
|
||||
graph = graphs.Graphs()
|
||||
if playtype == 'total_plays_per_month':
|
||||
result = graph.get_total_plays_per_month(y_axis=y_axis)
|
||||
|
||||
elif playtype == 'total_plays_per_day':
|
||||
result = graph.get_total_plays_per_day(time_range=time_range, y_axis=y_axis)
|
||||
|
||||
elif playtype == 'total_plays_per_hourofday':
|
||||
result = graph.get_total_plays_per_hourofday(time_range=time_range, y_axis=y_axis)
|
||||
|
||||
elif playtype == 'total_plays_per_dayofweek':
|
||||
result = graph.get_total_plays_per_dayofweek(time_range=time_range, y_axis=y_axis)
|
||||
|
||||
elif playtype == 'stream_type_by_top_10_users':
|
||||
result = graph.get_stream_type_by_top_10_users(time_range=time_range, y_axis=y_axis)
|
||||
|
||||
elif playtype == 'stream_type_by_top_10_platforms':
|
||||
result = graph.get_stream_type_by_top_10_platforms(time_range=time_range, y_axis=y_axis)
|
||||
|
||||
elif playtype == 'total_plays_by_stream_resolution':
|
||||
result = graph.get_total_plays_by_stream_resolution(time_range=time_range, y_axis=y_axis)
|
||||
|
||||
elif playtype == 'total_plays_by_source_resolution':
|
||||
result = graph.get_total_plays_by_source_resolution(time_range=time_range, y_axis=y_axis)
|
||||
|
||||
elif playtype == 'total_plays_per_stream_type':
|
||||
result = graph.get_total_plays_per_stream_type(time_range=time_range, y_axis=y_axis)
|
||||
|
||||
elif playtype == 'total_plays_by_top_10_users':
|
||||
result = graph.get_total_plays_by_top_10_users(time_range=time_range, y_axis=y_axis)
|
||||
|
||||
elif playtype == 'total_plays_by_top_10_platforms':
|
||||
result = graph.get_total_plays_by_top_10_platforms(time_range=time_range, y_axis=y_axis)
|
||||
|
||||
if result:
|
||||
self.data = result
|
||||
return result
|
||||
else:
|
||||
logger.warn('Unable to retrieve %s from db' % playtype)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue