diff --git a/API.md b/API.md
index 808bb35a..ecdc127b 100644
--- a/API.md
+++ b/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
diff --git a/PlexPy.py b/PlexPy.py
index 4d8d953f..cafb7804 100755
--- a/PlexPy.py
+++ b/PlexPy.py
@@ -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
diff --git a/plexpy/api.py b/plexpy/api.py
index 72ef82f8..38714b35 100644
--- a/plexpy/api.py
+++ b/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 .
-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 = '''
+
+ %s
+
+ error
+
+ ''' % 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
- else:
- return json.dumps(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:
- 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)
- 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]
-
- 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,
- }
-
- if item['paused_counter'] > 0:
- row['paused'] = item['paused_counter']
+ 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:
+ self.data = apikey
+ plexpy.CONFIG.API_KEY = apikey
+ plexpy.CONFIG.write()
else:
- row['paused'] = 0
+ 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()
- 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
+ return self.data
- row['duration'] = stopped - item['time'] + paused_counter
+ 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"
+ }
+ ]
+
+ }
+ ]
+ """
+ logfile = os.path.join(plexpy.CONFIG.LOG_DIR, 'plexpy.log')
+ templog = []
+ start = int(kwargs.get('start', 0))
+ end = int(kwargs.get('end', 0))
+
+ if regex:
+ logger.debug('Filtering log using regex %s' % regex)
+ reg = re.compile('u' + regex, flags=re.I)
+
+ 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)
+ 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:
+ 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
- xml_head = xml_parse.getElementsByTagName('opt')
- if not xml_head:
- logger.warn("Error parsing XML in PlexWatch db: %s" % e)
+ if len(line) > 1 and temp_loglevel_and_time is not None and loglvl in line:
- 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
- else:
- row['percent_complete'] = 0
-
- rows.append(row)
-
- 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)