Api doc base
This commit is contained in:
1 parent
adc755dbd5
commit
7df24643ac
11 files changed
+280
-22
No files matched your search
+15
-6
@@ -1,21 +1,30 @@
|
|||||||
from couchpotato.core.helpers.request import jsonified
|
|
||||||
from flask.blueprints import Blueprint
|
from flask.blueprints import Blueprint
|
||||||
|
from flask.templating import render_template
|
||||||
|
|
||||||
api = Blueprint('api', __name__)
|
api = Blueprint('api', __name__)
|
||||||
|
api_docs = {}
|
||||||
|
api_docs_missing = []
|
||||||
|
|
||||||
def addApiView(route, func, static = False):
|
def addApiView(route, func, static = False, docs = None):
|
||||||
api.add_url_rule(route + ('' if static else '/'), endpoint = route.replace('.', '-') if route else 'index', view_func = func)
|
api.add_url_rule(route + ('' if static else '/'), endpoint = route.replace('.', '::') if route else 'index', view_func = func)
|
||||||
|
if docs:
|
||||||
|
api_docs[route[4:] if route[0:4] == 'api.' else route] = docs
|
||||||
|
else:
|
||||||
|
api_docs_missing.append(route)
|
||||||
|
|
||||||
""" Api view """
|
""" Api view """
|
||||||
def index():
|
def index():
|
||||||
from couchpotato import app
|
|
||||||
|
|
||||||
|
from couchpotato import app
|
||||||
routes = []
|
routes = []
|
||||||
for route, x in sorted(app.view_functions.iteritems()):
|
for route, x in sorted(app.view_functions.iteritems()):
|
||||||
if route[0:4] == 'api.':
|
if route[0:4] == 'api.':
|
||||||
routes += [route[4:]]
|
routes += [route[4:].replace('::', '.')]
|
||||||
|
|
||||||
return jsonified({'routes': routes})
|
if api_docs.get(''):
|
||||||
|
del api_docs['']
|
||||||
|
del api_docs_missing['']
|
||||||
|
return render_template('api.html', routes = sorted(routes), api_docs = api_docs, api_docs_missing = sorted(api_docs_missing))
|
||||||
|
|
||||||
addApiView('', index)
|
addApiView('', index)
|
||||||
addApiView('default', index)
|
addApiView('default', index)
|
||||||
@@ -24,9 +24,17 @@ class Core(Plugin):
|
|||||||
shutdown_started = False
|
shutdown_started = False
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
addApiView('app.shutdown', self.shutdown)
|
addApiView('app.shutdown', self.shutdown, docs = {
|
||||||
addApiView('app.restart', self.restart)
|
'desc': 'Shutdown the app.',
|
||||||
addApiView('app.available', self.available)
|
'return': {'type': 'string: shutdown'}
|
||||||
|
})
|
||||||
|
addApiView('app.restart', self.restart, docs = {
|
||||||
|
'desc': 'Restart the app.',
|
||||||
|
'return': {'type': 'string: restart'}
|
||||||
|
})
|
||||||
|
addApiView('app.available', self.available, docs = {
|
||||||
|
'desc': 'Check if app available.'
|
||||||
|
})
|
||||||
|
|
||||||
addEvent('app.crappy_shutdown', self.crappyShutdown)
|
addEvent('app.crappy_shutdown', self.crappyShutdown)
|
||||||
addEvent('app.crappy_restart', self.crappyRestart)
|
addEvent('app.crappy_restart', self.crappyRestart)
|
||||||
|
|||||||
@@ -29,9 +29,25 @@ class Updater(Plugin):
|
|||||||
|
|
||||||
addEvent('app.load', self.check)
|
addEvent('app.load', self.check)
|
||||||
|
|
||||||
addApiView('updater.info', self.getInfo)
|
addApiView('updater.info', self.getInfo, docs = {
|
||||||
|
'desc': 'Get updater information',
|
||||||
|
'return': {
|
||||||
|
'type': 'object',
|
||||||
|
'example': """
|
||||||
|
{
|
||||||
|
'repo_name': "Name of used repository",
|
||||||
|
'last_check': "last checked for update",
|
||||||
|
'update_version': "available update version or empty",
|
||||||
|
'version': current_cp_version
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
})
|
||||||
addApiView('updater.update', self.doUpdateView)
|
addApiView('updater.update', self.doUpdateView)
|
||||||
addApiView('updater.check', self.checkView)
|
addApiView('updater.check', self.checkView, docs = {
|
||||||
|
'desc': 'Check for available update',
|
||||||
|
'return': {'type': 'see updater.info'}
|
||||||
|
})
|
||||||
|
|
||||||
def getInfo(self):
|
def getInfo(self):
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,18 @@ if os.name == 'nt':
|
|||||||
class FileBrowser(Plugin):
|
class FileBrowser(Plugin):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
addApiView('directory.list', self.view)
|
addApiView('directory.list', self.view, docs = {
|
||||||
|
'desc': 'Return the directory list of a given directory',
|
||||||
|
'params': {
|
||||||
|
'path': {'desc': 'The directory to scan'},
|
||||||
|
'show_hidden': {'desc': 'Also show hidden files'}
|
||||||
|
},
|
||||||
|
'return': {'type': 'object', 'example': """{
|
||||||
|
'is_root': bool, //is top most folder
|
||||||
|
'empty': bool, //directory is empty
|
||||||
|
'dirs': array, //directory names
|
||||||
|
}"""}
|
||||||
|
})
|
||||||
|
|
||||||
def getDirectories(self, path = '/', show_hidden = True):
|
def getDirectories(self, path = '/', show_hidden = True):
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,13 @@ class FileManager(Plugin):
|
|||||||
addEvent('file.download', self.download)
|
addEvent('file.download', self.download)
|
||||||
addEvent('file.types', self.getTypes)
|
addEvent('file.types', self.getTypes)
|
||||||
|
|
||||||
addApiView('file.cache/<path:filename>', self.showCacheFile, static = True)
|
addApiView('file.cache/<path:filename>', self.showCacheFile, static = True, docs = {
|
||||||
|
'desc': 'Return a file from the cp_data/cache directory',
|
||||||
|
'params': {
|
||||||
|
'filename': {'desc': 'path/filename of the wanted file'}
|
||||||
|
},
|
||||||
|
'return': {'type': 'file'}
|
||||||
|
})
|
||||||
|
|
||||||
def showCacheFile(self, filename = ''):
|
def showCacheFile(self, filename = ''):
|
||||||
|
|
||||||
|
|||||||
@@ -12,9 +12,27 @@ log = CPLog(__name__)
|
|||||||
class Logging(Plugin):
|
class Logging(Plugin):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
addApiView('logging.get', self.get)
|
addApiView('logging.get', self.get, docs = {
|
||||||
addApiView('logging.clear', self.clear)
|
'desc': 'Get the full log file by number',
|
||||||
addApiView('logging.log', self.log)
|
'params': {
|
||||||
|
'nr': {'desc': 'Number of the log to get.'}
|
||||||
|
},
|
||||||
|
'return': {'type': 'object', 'example': """{
|
||||||
|
'success': True,
|
||||||
|
'log': string, //Log file
|
||||||
|
'total': int, //Total log files available
|
||||||
|
}"""}
|
||||||
|
})
|
||||||
|
addApiView('logging.clear', self.clear, docs = {
|
||||||
|
'desc': 'Remove all the log files'
|
||||||
|
})
|
||||||
|
addApiView('logging.log', self.log, docs = {
|
||||||
|
'desc': 'Get the full log file by number',
|
||||||
|
'params': {
|
||||||
|
'type': {'desc': 'Type of logging, default "error"'},
|
||||||
|
'**kwargs': {'type':'object', 'desc': 'All other params will be printed in the log string.'},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
def get(self):
|
def get(self):
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,12 @@ class Manage(Plugin):
|
|||||||
fireEvent('scheduler.interval', identifier = 'manage.update_library', handle = self.updateLibrary, hours = 2)
|
fireEvent('scheduler.interval', identifier = 'manage.update_library', handle = self.updateLibrary, hours = 2)
|
||||||
|
|
||||||
addEvent('manage.update', self.updateLibrary)
|
addEvent('manage.update', self.updateLibrary)
|
||||||
addApiView('manage.update', self.updateLibraryView)
|
addApiView('manage.update', self.updateLibraryView, docs = {
|
||||||
|
'desc': 'Update the library by scanning for new movies',
|
||||||
|
'params': {
|
||||||
|
'full': {'desc': 'Do a full update or just recently changed/added movies.'},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
if not Env.get('dev'):
|
if not Env.get('dev'):
|
||||||
addEvent('app.load', self.updateLibrary)
|
addEvent('app.load', self.updateLibrary)
|
||||||
|
|||||||
@@ -26,9 +26,37 @@ class MoviePlugin(Plugin):
|
|||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
addApiView('movie.search', self.search)
|
addApiView('movie.search', self.search, docs = {
|
||||||
addApiView('movie.list', self.listView)
|
'desc': 'Search the movie providers for a movie',
|
||||||
addApiView('movie.refresh', self.refresh)
|
'params': {
|
||||||
|
'q': {'desc': 'The (partial) movie name you want to search for'},
|
||||||
|
},
|
||||||
|
'return': {'type': 'object', 'example': """{
|
||||||
|
'success': True,
|
||||||
|
'empty': bool, any movies returned or not,
|
||||||
|
'movies': array, movies found,
|
||||||
|
}"""}
|
||||||
|
})
|
||||||
|
addApiView('movie.list', self.listView, docs = {
|
||||||
|
'desc': 'List movies in wanted list',
|
||||||
|
'params': {
|
||||||
|
'status': {'type': 'array or csv', 'desc': 'Filter movie by status. Example:"active,done"'},
|
||||||
|
'limit_offset': {'desc': 'Limit the movie list. Examples: "50", "50,30"'},
|
||||||
|
'starts_with': {'desc': 'Starts with these characters. Example: "a" returns all movies starting with the letter "a"'},
|
||||||
|
'search': {'desc': 'Search movie title'},
|
||||||
|
},
|
||||||
|
'return': {'type': 'object', 'example': """{
|
||||||
|
'success': True,
|
||||||
|
'empty': bool, any movies returned or not,
|
||||||
|
'movies': array, movies found,
|
||||||
|
}"""}
|
||||||
|
})
|
||||||
|
addApiView('movie.refresh', self.refresh, docs = {
|
||||||
|
'desc': 'Refresh a movie by id',
|
||||||
|
'params': {
|
||||||
|
'id': {'desc': 'The id of the movie that needs to be refreshed'},
|
||||||
|
}
|
||||||
|
})
|
||||||
addApiView('movie.available_chars', self.charView)
|
addApiView('movie.available_chars', self.charView)
|
||||||
|
|
||||||
addApiView('movie.add', self.addView)
|
addApiView('movie.add', self.addView)
|
||||||
|
|||||||
@@ -16,8 +16,41 @@ class Settings(object):
|
|||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
addApiView('settings', self.view)
|
addApiView('settings', self.view, docs = {
|
||||||
addApiView('settings.save', self.saveView)
|
'desc': 'Return the options and its values of settings.conf. Including the default values and group ordering used on the settings page.',
|
||||||
|
'return': {'type': 'object', 'example': """{
|
||||||
|
// objects like in __init__.py of plugin
|
||||||
|
"options": {
|
||||||
|
"moovee" : {
|
||||||
|
"groups" : [{
|
||||||
|
"description" : "SD movies only",
|
||||||
|
"name" : "#alt.binaries.moovee",
|
||||||
|
"options" : [{
|
||||||
|
"default" : false,
|
||||||
|
"name" : "enabled",
|
||||||
|
"type" : "enabler"
|
||||||
|
}],
|
||||||
|
"tab" : "providers"
|
||||||
|
}],
|
||||||
|
"name" : "moovee"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// object structured like settings.conf
|
||||||
|
"values": {
|
||||||
|
"moovee": {
|
||||||
|
"enabled": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}"""}
|
||||||
|
})
|
||||||
|
addApiView('settings.save', self.saveView, docs = {
|
||||||
|
'desc': 'Save setting to config file (settings.conf)',
|
||||||
|
'params': {
|
||||||
|
'section': {'desc': 'The section name in settings.conf'},
|
||||||
|
'option': {'desc': 'The option name'},
|
||||||
|
'value': {'desc': 'The value you want to save'},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
def setFile(self, config_file):
|
def setFile(self, config_file):
|
||||||
self.file = config_file
|
self.file = config_file
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
html {
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.5;
|
||||||
|
font-family: "Helvetica Neue", Helvetica, Arial, Geneva, sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3, h4, h5 {
|
||||||
|
clear: both;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
background: #ccc;
|
||||||
|
font-family: monospace;
|
||||||
|
margin: 0;
|
||||||
|
padding: 2%;
|
||||||
|
width: 96%;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.api {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.api .description {
|
||||||
|
color: #333;
|
||||||
|
padding: 0 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.api .params {
|
||||||
|
background: #f5f5f5;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.api h3 {
|
||||||
|
clear: both;
|
||||||
|
float: left;
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.api .params {
|
||||||
|
float: left;
|
||||||
|
width: 700px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.api .params .param {
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.api .params .param th {
|
||||||
|
text-align: left;
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.api .param .type {
|
||||||
|
font-style: italic;
|
||||||
|
margin-right: 10px;
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.api .return {
|
||||||
|
float: left;
|
||||||
|
width: 700px;
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<link rel="stylesheet" href="{{ url_for('web.static', filename='style/api.css') }}" type="text/css">
|
||||||
|
<title>API documentation</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<h1>API</h1>
|
||||||
|
{% for route in routes %}
|
||||||
|
{% if api_docs.get(route) %}
|
||||||
|
<div class="api">
|
||||||
|
<h2>{{route}}</h2>
|
||||||
|
<div class="description">{{api_docs[route].get('desc', '')}}</div>
|
||||||
|
|
||||||
|
{% if api_docs[route].get('params') %}
|
||||||
|
<h3>Params</h3>
|
||||||
|
<table class="params">
|
||||||
|
{% for param in api_docs[route]['params'] %}
|
||||||
|
<tr class="param">
|
||||||
|
<th>{{param}}</th>
|
||||||
|
<td class="type">{{ api_docs[route]['params'][param].get('type', 'string') }}</td>
|
||||||
|
<td class="description">{{ api_docs[route]['params'][param]['desc'] }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if api_docs[route].get('return') %}
|
||||||
|
<h3>Return</h3>
|
||||||
|
<div class="return">
|
||||||
|
<div class="type">{{ api_docs[route]['return'].get('type', '{"success": True}') }}</div>
|
||||||
|
{% if api_docs[route]['return'].get('example') %}
|
||||||
|
<div class="example">
|
||||||
|
<h4>Example</h4>
|
||||||
|
<pre>{{ api_docs[route]['return'].get('example', '')|safe }}</pre>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
<h1>Missing documentation</h1>
|
||||||
|
<div class="missing">{{', '.join(api_docs_missing)}}</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in new issue
Block a user