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)