mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-10 15:32:38 -07:00
Update all APIv2 docs
This commit is contained in:
parent
2d10b0748c
commit
e1b61214b7
9 changed files with 3218 additions and 487 deletions
|
@ -194,7 +194,7 @@
|
||||||
var r = confirm("Are you sure you want to clear the PlexPy notification log?");
|
var r = confirm("Are you sure you want to clear the PlexPy notification log?");
|
||||||
if (r == true) {
|
if (r == true) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: 'clearNotifyLogs',
|
url: 'delete_notification_log',
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
notification_log_table.draw();
|
notification_log_table.draw();
|
||||||
|
|
|
@ -200,13 +200,14 @@
|
||||||
function sendTestNotification() {
|
function sendTestNotification() {
|
||||||
if ('${agent["id"]}' != '17') {
|
if ('${agent["id"]}' != '17') {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: 'test_notifier',
|
url: 'send_notification',
|
||||||
data: {
|
data: {
|
||||||
agent_id: '${agent["id"]}',
|
agent_id: '${agent["id"]}',
|
||||||
subject: $('#test_subject').val(),
|
subject: $('#test_subject').val(),
|
||||||
body: $('#test_body').val(),
|
body: $('#test_body').val(),
|
||||||
script: $('#test_script').val(),
|
script: $('#test_script').val(),
|
||||||
script_args: $('#test_script_args').val()
|
script_args: $('#test_script_args').val(),
|
||||||
|
notify_action: 'test'
|
||||||
},
|
},
|
||||||
cache: false,
|
cache: false,
|
||||||
async: true,
|
async: true,
|
||||||
|
|
157
plexpy/api2.py
157
plexpy/api2.py
|
@ -33,6 +33,7 @@ import xmltodict
|
||||||
import plexpy
|
import plexpy
|
||||||
import database
|
import database
|
||||||
import logger
|
import logger
|
||||||
|
import plextv
|
||||||
import pmsconnect
|
import pmsconnect
|
||||||
|
|
||||||
|
|
||||||
|
@ -51,7 +52,7 @@ class API2:
|
||||||
self._api_kwargs = None # Cleaned kwargs
|
self._api_kwargs = None # Cleaned kwargs
|
||||||
|
|
||||||
def _api_docs(self, md=False):
|
def _api_docs(self, md=False):
|
||||||
""" Makes the api docs """
|
""" Makes the api docs. """
|
||||||
|
|
||||||
docs = {}
|
docs = {}
|
||||||
for f, _ in inspect.getmembers(self, predicate=inspect.ismethod):
|
for f, _ in inspect.getmembers(self, predicate=inspect.ismethod):
|
||||||
|
@ -63,17 +64,17 @@ class API2:
|
||||||
return docs
|
return docs
|
||||||
|
|
||||||
def docs_md(self):
|
def docs_md(self):
|
||||||
""" Return a API.md to simplify api docs because of the decorator. """
|
""" Return the api docs formatted with markdown. """
|
||||||
|
|
||||||
return self._api_make_md()
|
return self._api_make_md()
|
||||||
|
|
||||||
def docs(self):
|
def docs(self):
|
||||||
""" Returns a dict where commands are keys, docstring are value. """
|
""" Return the api docs as a dict where commands are keys, docstring are value. """
|
||||||
|
|
||||||
return self._api_docs()
|
return self._api_docs()
|
||||||
|
|
||||||
def _api_validate(self, *args, **kwargs):
|
def _api_validate(self, *args, **kwargs):
|
||||||
""" sets class vars and remove unneeded parameters. """
|
""" Sets class vars and remove unneeded parameters. """
|
||||||
|
|
||||||
if not plexpy.CONFIG.API_ENABLED:
|
if not plexpy.CONFIG.API_ENABLED:
|
||||||
self._api_msg = 'API not enabled'
|
self._api_msg = 'API not enabled'
|
||||||
|
@ -114,37 +115,37 @@ class API2:
|
||||||
self._api_msg = None
|
self._api_msg = None
|
||||||
self._api_kwargs = kwargs
|
self._api_kwargs = kwargs
|
||||||
|
|
||||||
logger.debug(u'PlexPy APIv2 :: Cleaned kwargs %s' % self._api_kwargs)
|
logger.debug(u'PlexPy APIv2 :: Cleaned kwargs: %s' % self._api_kwargs)
|
||||||
|
|
||||||
return self._api_kwargs
|
return self._api_kwargs
|
||||||
|
|
||||||
def get_logs(self, sort='', search='', order='desc', regex='', start=0, end=0, **kwargs):
|
def get_logs(self, sort='', search='', order='desc', regex='', start=0, end=0, **kwargs):
|
||||||
"""
|
"""
|
||||||
Returns the log
|
Get the PlexPy logs.
|
||||||
|
|
||||||
Args:
|
```
|
||||||
sort(string, optional): time, thread, msg, loglevel
|
Required parameters:
|
||||||
search(string, optional): 'string'
|
None
|
||||||
order(string, optional): desc, asc
|
|
||||||
regex(string, optional): 'regexstring'
|
|
||||||
start(int, optional): int
|
|
||||||
end(int, optional): int
|
|
||||||
|
|
||||||
|
Optional parameters:
|
||||||
|
sort (str): "time", "thread", "msg", "loglevel"
|
||||||
|
search (str): A string to search for
|
||||||
|
order (str): "desc" or "asc"
|
||||||
|
regex (str): A regex string to search for
|
||||||
|
start (int): Row number to start from
|
||||||
|
end (int): Row number to end at
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
```{"response":
|
json:
|
||||||
{"msg": "Hey",
|
[{"loglevel": "DEBUG",
|
||||||
"result": "success"},
|
"msg": "Latest version is 2d10b0748c7fa2ee4cf59960c3d3fffc6aa9512b",
|
||||||
"data": [
|
"thread": "MainThread",
|
||||||
{"time": "29-sept.2015",
|
"time": "2016-05-08 09:36:51 "
|
||||||
"thread: "MainThread",
|
},
|
||||||
"msg: "Called x from y",
|
{...},
|
||||||
"loglevel": "DEBUG"
|
{...}
|
||||||
}
|
]
|
||||||
]
|
```
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
logfile = os.path.join(plexpy.CONFIG.LOG_DIR, 'plexpy.log')
|
logfile = os.path.join(plexpy.CONFIG.LOG_DIR, 'plexpy.log')
|
||||||
|
@ -216,17 +217,22 @@ class API2:
|
||||||
return templog
|
return templog
|
||||||
|
|
||||||
def get_settings(self, key=''):
|
def get_settings(self, key=''):
|
||||||
""" Fetches all settings from the config file
|
""" Gets all settings from the config file.
|
||||||
|
|
||||||
Args:
|
```
|
||||||
key(string, optional): 'Run the it without args to see all args'
|
Required parameters:
|
||||||
|
None
|
||||||
|
|
||||||
|
Optional parameters:
|
||||||
|
key (str): Name of a config section to return
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
json:
|
json:
|
||||||
```
|
{"General": {"api_enabled": true, ...}
|
||||||
{General: {api_enabled: true, ...}
|
"Advanced": {"cache_sizemb": "32", ...},
|
||||||
Advanced: {cache_sizemb: "32", ...}}
|
...
|
||||||
```
|
}
|
||||||
|
```
|
||||||
"""
|
"""
|
||||||
|
|
||||||
interface_dir = os.path.join(plexpy.PROG_DIR, 'data/interfaces/')
|
interface_dir = os.path.join(plexpy.PROG_DIR, 'data/interfaces/')
|
||||||
|
@ -256,8 +262,20 @@ class API2:
|
||||||
return config
|
return config
|
||||||
|
|
||||||
def sql(self, query=''):
|
def sql(self, query=''):
|
||||||
""" Query the db with raw sql, makes backup of
|
""" Query the PlexPy database with raw SQL. Automatically makes a backup of
|
||||||
the db if the backup is older then 24h
|
the database if the latest backup is older then 24h. `api_sql` must be
|
||||||
|
manually enabled in the config file.
|
||||||
|
|
||||||
|
```
|
||||||
|
Required parameters:
|
||||||
|
query (str): The SQL query
|
||||||
|
|
||||||
|
Optional parameters:
|
||||||
|
None
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
None
|
||||||
|
```
|
||||||
"""
|
"""
|
||||||
if not plexpy.CONFIG.API_SQL or not query:
|
if not plexpy.CONFIG.API_SQL or not query:
|
||||||
return
|
return
|
||||||
|
@ -277,8 +295,8 @@ class API2:
|
||||||
self.data = rows
|
self.data = rows
|
||||||
return rows
|
return rows
|
||||||
|
|
||||||
def backupdb(self):
|
def backup_db(self):
|
||||||
""" Creates a manual backup of the plexpy.db file """
|
""" Create a manual backup of the `plexpy.db` file. """
|
||||||
|
|
||||||
data = database.make_backup()
|
data = database.make_backup()
|
||||||
|
|
||||||
|
@ -290,33 +308,51 @@ class API2:
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def restart(self, **kwargs):
|
def restart(self, **kwargs):
|
||||||
""" Restarts plexpy """
|
""" Restart PlexPy. """
|
||||||
|
|
||||||
plexpy.SIGNAL = 'restart'
|
plexpy.SIGNAL = 'restart'
|
||||||
self.msg = 'Restarting plexpy'
|
self.msg = 'Restarting plexpy'
|
||||||
self.result_type = 'success'
|
self.result_type = 'success'
|
||||||
|
|
||||||
def update(self, **kwargs):
|
def update(self, **kwargs):
|
||||||
""" Check for updates on Github """
|
""" Check for PlexPy updates on Github. """
|
||||||
|
|
||||||
plexpy.SIGNAL = 'update'
|
plexpy.SIGNAL = 'update'
|
||||||
self.msg = 'Updating plexpy'
|
self.msg = 'Updating plexpy'
|
||||||
self.result_type = 'success'
|
self.result_type = 'success'
|
||||||
|
|
||||||
def refresh_libraries_list(self, **kwargs):
|
def refresh_libraries_list(self, **kwargs):
|
||||||
threading.Thread(target=pmsconnect.refresh_libraries).start()
|
""" Refreshe the PlexPy libraries list. """
|
||||||
self.result_type = 'success'
|
data = pmsconnect.refresh_libraries()
|
||||||
|
|
||||||
|
if data:
|
||||||
|
self.result_type = 'success'
|
||||||
|
else:
|
||||||
|
self.result_type = 'failed'
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
def refresh_users_list(self, **kwargs):
|
||||||
|
""" Refreshe the PlexPy users list. """
|
||||||
|
data = plextv.refresh_users()
|
||||||
|
|
||||||
|
if data:
|
||||||
|
self.result_type = 'success'
|
||||||
|
else:
|
||||||
|
self.result_type = 'failed'
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
def _api_make_md(self):
|
def _api_make_md(self):
|
||||||
""" Tries to make a API.md to simplify the api docs """
|
""" Tries to make a API.md to simplify the api docs. """
|
||||||
|
|
||||||
head = '''# API Reference\n
|
head = '''# API Reference\n
|
||||||
The API is still pretty new and needs some serious cleaning up on the backend but should be reasonably functional. There are no error codes yet.
|
The API is still pretty new and needs some serious cleaning up on the backend but should be reasonably functional. There are no error codes yet.
|
||||||
|
|
||||||
## General structure
|
## General structure
|
||||||
The API endpoint is `http://ip:port + HTTP_ROOT + /api?apikey=$apikey&cmd=$command`
|
The API endpoint is `http://ip:port + HTTP_ROOT + /api/v2?apikey=$apikey&cmd=$command`
|
||||||
|
|
||||||
Response example
|
Response example (default `json`)
|
||||||
```
|
```
|
||||||
{
|
{
|
||||||
"response": {
|
"response": {
|
||||||
|
@ -333,11 +369,13 @@ Response example
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
```
|
||||||
|
General optional parameters:
|
||||||
|
|
||||||
General parameters:
|
out_type: "json" or "xml"
|
||||||
out_type: 'xml',
|
callback: "pong"
|
||||||
callback: 'pong',
|
debug: 1
|
||||||
'debug': 1
|
```
|
||||||
|
|
||||||
## API methods'''
|
## API methods'''
|
||||||
|
|
||||||
|
@ -350,18 +388,23 @@ General parameters:
|
||||||
body += '\n\n'
|
body += '\n\n'
|
||||||
|
|
||||||
result = head + '\n\n' + body
|
result = head + '\n\n' + body
|
||||||
return '<div style="white-space: pre-wrap">' + result + '</div>'
|
return '<pre>' + result + '</pre>'
|
||||||
|
|
||||||
def get_apikey(self, username='', password=''):
|
def get_apikey(self, username='', password=''):
|
||||||
""" Fetches apikey
|
""" Get the apikey. Username and password are required
|
||||||
|
if auth is enabled. Makes and saves the apikey if it does not exist.
|
||||||
|
|
||||||
Args:
|
```
|
||||||
username(string, optional): Your username
|
Required parameters:
|
||||||
password(string, optional): Your password
|
None
|
||||||
|
|
||||||
|
Optional parameters:
|
||||||
|
username (str): Your PlexPy username
|
||||||
|
password (str): Your PlexPy password
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
string: Apikey, args are required if auth is enabled
|
string: "apikey"
|
||||||
makes and saves the apikey it does not exist
|
```
|
||||||
"""
|
"""
|
||||||
|
|
||||||
apikey = hashlib.sha224(str(random.getrandbits(256))).hexdigest()[0:32]
|
apikey = hashlib.sha224(str(random.getrandbits(256))).hexdigest()[0:32]
|
||||||
|
@ -443,7 +486,7 @@ General parameters:
|
||||||
""" handles the stuff from the handler """
|
""" handles the stuff from the handler """
|
||||||
|
|
||||||
result = {}
|
result = {}
|
||||||
logger.debug(u'PlexPy APIv2 :: Original kwargs was %s' % kwargs)
|
logger.debug(u'PlexPy APIv2 :: API called with kwargs: %s' % kwargs)
|
||||||
|
|
||||||
self._api_validate(**kwargs)
|
self._api_validate(**kwargs)
|
||||||
|
|
||||||
|
|
|
@ -591,3 +591,27 @@ def cache_image(url, image=None):
|
||||||
imagetype = 'image/jpeg'
|
imagetype = 'image/jpeg'
|
||||||
|
|
||||||
return imagefile, imagetype
|
return imagefile, imagetype
|
||||||
|
|
||||||
|
def build_datatables_json(kwargs, dt_columns, default_sort_col=None):
|
||||||
|
""" Builds datatables json data
|
||||||
|
|
||||||
|
dt_columns: list of tuples [("column name", "orderable", "searchable"), ...]
|
||||||
|
"""
|
||||||
|
|
||||||
|
columns = [{"data": c[0], "orderable": c[1], "searchable": c[2]} for c in dt_columns]
|
||||||
|
|
||||||
|
if not default_sort_col:
|
||||||
|
default_sort_col = dt_columns[0][0]
|
||||||
|
|
||||||
|
order_column = [c[0] for c in dt_columns].index(kwargs.pop("order_column", default_sort_col))
|
||||||
|
|
||||||
|
# Build json data
|
||||||
|
json_data = {"draw": 1,
|
||||||
|
"columns": columns,
|
||||||
|
"order": [{"column": order_column,
|
||||||
|
"dir": kwargs.pop("order_dir", "desc")}],
|
||||||
|
"start": int(kwargs.pop("start", 0)),
|
||||||
|
"length": int(kwargs.pop("length", 25)),
|
||||||
|
"search": {"value": kwargs.pop("search", "")}
|
||||||
|
}
|
||||||
|
return json.dumps(json_data)
|
||||||
|
|
|
@ -309,10 +309,13 @@ class Libraries(object):
|
||||||
return default_return
|
return default_return
|
||||||
|
|
||||||
if section_id and not str(section_id).isdigit():
|
if section_id and not str(section_id).isdigit():
|
||||||
logger.warn(u"PlexPy Libraries :: Datatable media info called by invalid section_id provided.")
|
logger.warn(u"PlexPy Libraries :: Datatable media info called but invalid section_id provided.")
|
||||||
return default_return
|
return default_return
|
||||||
elif rating_key and not str(rating_key).isdigit():
|
elif rating_key and not str(rating_key).isdigit():
|
||||||
logger.warn(u"PlexPy Libraries :: Datatable media info called by invalid rating_key provided.")
|
logger.warn(u"PlexPy Libraries :: Datatable media info called but invalid rating_key provided.")
|
||||||
|
return default_return
|
||||||
|
elif not section_id and not rating_key:
|
||||||
|
logger.warn(u"PlexPy Libraries :: Datatable media info called but no input provided.")
|
||||||
return default_return
|
return default_return
|
||||||
|
|
||||||
# Get the library details
|
# Get the library details
|
||||||
|
|
|
@ -78,8 +78,10 @@ def refresh_users():
|
||||||
monitor_db.upsert('users', new_value_dict, control_value_dict)
|
monitor_db.upsert('users', new_value_dict, control_value_dict)
|
||||||
|
|
||||||
logger.info(u"PlexPy PlexTV :: Users list refreshed.")
|
logger.info(u"PlexPy PlexTV :: Users list refreshed.")
|
||||||
|
return True
|
||||||
else:
|
else:
|
||||||
logger.warn(u"PlexPy PlexTV :: Unable to refresh users list.")
|
logger.warn(u"PlexPy PlexTV :: Unable to refresh users list.")
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def get_real_pms_url():
|
def get_real_pms_url():
|
||||||
|
|
|
@ -94,8 +94,10 @@ def refresh_libraries():
|
||||||
threading.Thread(target=libraries.update_labels).start()
|
threading.Thread(target=libraries.update_labels).start()
|
||||||
|
|
||||||
logger.info(u"PlexPy Pmsconnect :: Libraries list refreshed.")
|
logger.info(u"PlexPy Pmsconnect :: Libraries list refreshed.")
|
||||||
|
return True
|
||||||
else:
|
else:
|
||||||
logger.warn(u"PlexPy Pmsconnect :: Unable to refresh libraries list.")
|
logger.warn(u"PlexPy Pmsconnect :: Unable to refresh libraries list.")
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
class PmsConnect(object):
|
class PmsConnect(object):
|
||||||
|
|
1948
plexpy/webserve.py
1948
plexpy/webserve.py
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue