diff --git a/plexpy/api.py b/plexpy/api.py
deleted file mode 100644
index 82fdbf73..00000000
--- a/plexpy/api.py
+++ /dev/null
@@ -1,510 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-
-# This file is part of PlexPy.
-#
-# PlexPy is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# PlexPy is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with PlexPy. If not, see .
-
-import json
-import hashlib
-import os
-import random
-import re
-import traceback
-
-import cherrypy
-import xmltodict
-
-import plexpy
-import database
-import datafactory
-import graphs
-import logger
-import plextv
-import pmsconnect
-import users
-import versioncheck
-
-
-cmd_list = ['getLogs', 'getVersion', 'checkGithub', 'shutdown',
- 'getSettings', 'restart', 'update', 'getApikey', 'getHistory',
- 'getMetadata', 'getUserips', 'getPlayby', 'getSync']
-
-
-class Api(object):
- def __init__(self, out='json'):
-
- self.apikey = None
- self.authenticated = False
- self.cmd = 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.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))
-
- # Set default values or remove them from kwargs
-
- 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 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
-
- 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):
-
- 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:
- 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):
-
- db = database.MonitorDatabase()
- rows = db.select(query)
-
- rows_as_dic = []
-
- for row in rows:
- row_as_dic = dict(zip(row.keys(), row))
- rows_as_dic.append(row_as_dic)
-
- return rows_as_dic
-
- def _getApikey(self, username='', password=''):
- """ Returns api key, requires username and password is active """
-
- 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:
- 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()
-
- 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"
- }
- ]
-
- }
- ]
- """
- logfile = os.path.join(plexpy.CONFIG.LOG_DIR, logger.FILENAME)
- 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:
- 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
-
- if len(line) > 1 and temp_loglevel_and_time is not None and loglvl in line:
-
- d = {
- 'time': temp_loglevel_and_time[0],
- 'loglevel': loglvl,
- 'msg': msg.replace('\n', ''),
- 'thread': thread
- }
- templog.append(d)
-
- 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 = {
- 'git_path': plexpy.CONFIG.GIT_PATH,
- 'install_type': plexpy.INSTALL_TYPE,
- 'current_version': plexpy.CURRENT_VERSION,
- 'latest_version': plexpy.LATEST_VERSION,
- 'commits_behind': plexpy.COMMITS_BEHIND,
- }
- self.result_type = 'success'
-
- def _checkGithub(self, **kwargs):
- versioncheck.checkGithub()
- self._getVersion()
-
- 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_datatables_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),
- "movie_notify_enable": bool(plexpy.CONFIG.MOVIE_NOTIFY_ENABLE),
- "tv_notify_enable": bool(plexpy.CONFIG.TV_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),
- "movie_logging_enable": bool(plexpy.CONFIG.MOVIE_LOGGING_ENABLE),
- "tv_logging_enable": bool(plexpy.CONFIG.TV_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)
diff --git a/plexpy/webserve.py b/plexpy/webserve.py
index 3bf6f234..226de21e 100644
--- a/plexpy/webserve.py
+++ b/plexpy/webserve.py
@@ -4339,9 +4339,8 @@ class WebInterface(object):
if args and 'v2' in args[0]:
return API2()._api_run(**kwargs)
else:
- a = Api()
- a.checkParams(*args, **kwargs)
- return a.fetchData()
+ return json.dumps(API2()._api_responds(result_type='error',
+ msg='Please use the /api/v2 endpoint.'))
@cherrypy.expose
@cherrypy.tools.json_out()