1
0
mirror of https://github.com/moparisthebest/SickRage synced 2024-12-12 11:02:21 -05:00

Merge remote-tracking branch 'origin/develop' into develop

Conflicts:
	sickbeard/webapi.py
This commit is contained in:
echel0n 2014-12-07 13:00:18 -08:00
commit e7de90f688
7 changed files with 320 additions and 358 deletions

View File

@ -45,7 +45,7 @@ function goListGroup(apikey, L7, L6, L5, L4, L3, L2, L1){
html += $.ajax({ html += $.ajax({
url: sbRoot + "/api/" + apikey + "/" + L1 + L2 + L3 + L4 + L5 + L6 + L7 + GlobalOptions, url: sbRoot + "/api/" + apikey + "/" + L1 + L2 + L3 + L4 + L5 + L6 + L7 + GlobalOptions,
async: false, async: false,
dataType: "html", dataType: "html"
}).responseText; }).responseText;
html += '</pre>'; html += '</pre>';

View File

@ -58,7 +58,7 @@ $(document).ready(function(){
$('#api_key').click(function(){ $('#api_key').select() }); $('#api_key').click(function(){ $('#api_key').select() });
$("#generate_new_apikey").click(function(){ $("#generate_new_apikey").click(function(){
$.get(sbRoot + '/config/general/generateKey', $.get(sbRoot + '/config/general/generateApiKey',
function(data){ function(data){
if (data.error != undefined) { if (data.error != undefined) {
alert(data.error); alert(data.error);

View File

@ -145,6 +145,7 @@ ANON_REDIRECT = None
USE_API = False USE_API = False
API_KEY = None API_KEY = None
API_ROOT = None
ENABLE_HTTPS = False ENABLE_HTTPS = False
HTTPS_CERT = None HTTPS_CERT = None
@ -480,7 +481,7 @@ def get_backlog_cycle_time():
def initialize(consoleLogging=True): def initialize(consoleLogging=True):
with INIT_LOCK: with INIT_LOCK:
global BRANCH, GIT_REMOTE, GIT_REMOTE_URL, CUR_COMMIT_HASH, CUR_COMMIT_BRANCH, ACTUAL_LOG_DIR, LOG_DIR, WEB_PORT, WEB_LOG, ENCRYPTION_VERSION, WEB_ROOT, WEB_USERNAME, WEB_PASSWORD, WEB_HOST, WEB_IPV6, USE_API, API_KEY, ENABLE_HTTPS, HTTPS_CERT, HTTPS_KEY, \ global BRANCH, GIT_REMOTE, GIT_REMOTE_URL, CUR_COMMIT_HASH, CUR_COMMIT_BRANCH, ACTUAL_LOG_DIR, LOG_DIR, WEB_PORT, WEB_LOG, ENCRYPTION_VERSION, WEB_ROOT, WEB_USERNAME, WEB_PASSWORD, WEB_HOST, WEB_IPV6, USE_API, API_KEY, API_ROOT, ENABLE_HTTPS, HTTPS_CERT, HTTPS_KEY, \
HANDLE_REVERSE_PROXY, USE_NZBS, USE_TORRENTS, NZB_METHOD, NZB_DIR, DOWNLOAD_PROPERS, RANDOMIZE_PROVIDERS, CHECK_PROPERS_INTERVAL, ALLOW_HIGH_PRIORITY, TORRENT_METHOD, \ HANDLE_REVERSE_PROXY, USE_NZBS, USE_TORRENTS, NZB_METHOD, NZB_DIR, DOWNLOAD_PROPERS, RANDOMIZE_PROVIDERS, CHECK_PROPERS_INTERVAL, ALLOW_HIGH_PRIORITY, TORRENT_METHOD, \
SAB_USERNAME, SAB_PASSWORD, SAB_APIKEY, SAB_CATEGORY, SAB_CATEGORY_ANIME, SAB_HOST, \ SAB_USERNAME, SAB_PASSWORD, SAB_APIKEY, SAB_CATEGORY, SAB_CATEGORY_ANIME, SAB_HOST, \
NZBGET_USERNAME, NZBGET_PASSWORD, NZBGET_CATEGORY, NZBGET_CATEGORY_ANIME, NZBGET_PRIORITY, NZBGET_HOST, NZBGET_USE_HTTPS, backlogSearchScheduler, \ NZBGET_USERNAME, NZBGET_PASSWORD, NZBGET_CATEGORY, NZBGET_CATEGORY_ANIME, NZBGET_PRIORITY, NZBGET_HOST, NZBGET_USE_HTTPS, backlogSearchScheduler, \

View File

@ -20,6 +20,7 @@ from __future__ import with_statement
import getpass import getpass
import os import os
import random
import re import re
import shutil import shutil
import socket import socket
@ -1433,3 +1434,27 @@ def get_size(start_path='.'):
def md5(text): def md5(text):
return hashlib.md5(ek.ss(text)).hexdigest() return hashlib.md5(ek.ss(text)).hexdigest()
def generateApiKey(*args, **kwargs):
""" Return a new randomized API_KEY
"""
try:
from hashlib import md5
except ImportError:
from md5 import md5
# Create some values to seed md5
t = str(time.time())
r = str(random.random())
# Create the md5 instance and give it the current time
m = md5(t)
# Update the md5 instance with the random variable
m.update(r)
# Return a hex digest of the md5, eg 49f68a5c8493ec2c0bf489821c21fc3b
logger.log(u"New API generated")
return m.hexdigest()

View File

@ -28,7 +28,6 @@ import traceback
import sickbeard import sickbeard
from sickbeard.webserve import PageTemplate
from sickbeard import db, logger, exceptions, history, ui, helpers from sickbeard import db, logger, exceptions, history, ui, helpers
from sickbeard import encodingKludge as ek from sickbeard import encodingKludge as ek
from sickbeard import search_queue from sickbeard import search_queue
@ -48,7 +47,6 @@ except ImportError:
from lib import subliminal from lib import subliminal
from tornado.web import RequestHandler from tornado.web import RequestHandler
from tornado.routes import route
indexer_ids = ["indexerid", "tvdbid", "tvrageid"] indexer_ids = ["indexerid", "tvdbid", "tvrageid"]
@ -71,46 +69,32 @@ result_type_map = {RESULT_SUCCESS: "success",
} }
# basically everything except RESULT_SUCCESS / success is bad # basically everything except RESULT_SUCCESS / success is bad
@route('/api/(.*)(/?)')
class ApiHandler(RequestHandler): class ApiHandler(RequestHandler):
""" api class that returns json results """ """ api class that returns json results """
version = 4 # use an int since float-point is unpredictible version = 4 # use an int since float-point is unpredictible
intent = 4 intent = 4
def index(self, *args, **kwargs): def get(self, *args, **kwargs):
self.apiKey = sickbeard.API_KEY
access, accessMsg, args, kwargs = self._grand_access(self.apiKey, args, kwargs)
# set the output callback # set the output callback
# default json # default json
outputCallbackDict = {'default': self._out_as_json, outputCallbackDict = {'default': self._out_as_json,
'image': lambda x: x['image'], 'image': lambda x: x['image'],
} }
# do we have acces ?
if access:
logger.log(accessMsg, logger.DEBUG)
else:
logger.log(accessMsg, logger.WARNING)
return outputCallbackDict['default'](_responds(RESULT_DENIED, msg=accessMsg))
# set the original call_dispatcher as the local _call_dispatcher # set the original call_dispatcher as the local _call_dispatcher
_call_dispatcher = call_dispatcher _call_dispatcher = self.call_dispatcher
# if profile was set wrap "_call_dispatcher" in the profile function # if profile was set wrap "_call_dispatcher" in the profile function
if 'profile' in kwargs: if self.get_argument('profile', None):
from lib.profilehooks import profile from lib.profilehooks import profile
_call_dispatcher = profile(_call_dispatcher, immediate=True) _call_dispatcher = profile(_call_dispatcher, immediate=True)
del kwargs["profile"]
# if debug was set call the "_call_dispatcher" # if debug was set call the "_call_dispatcher"
if 'debug' in kwargs: if self.get_argument('debug', None):
outDict = _call_dispatcher(self, args, outDict = _call_dispatcher(args, kwargs) # this way we can debug the cherry.py traceback in the browser
kwargs) # this way we can debug the cherry.py traceback in the browser
del kwargs["debug"]
else: # if debug was not set we wrap the "call_dispatcher" in a try block to assure a json output else: # if debug was not set we wrap the "call_dispatcher" in a try block to assure a json output
try: try:
outDict = _call_dispatcher(self, args, kwargs) outDict = _call_dispatcher(args, kwargs)
except Exception, e: # real internal error oohhh nooo :( except Exception, e: # real internal error oohhh nooo :(
logger.log(u"API :: " + ex(e), logger.ERROR) logger.log(u"API :: " + ex(e), logger.ERROR)
errorData = {"error_msg": ex(e), errorData = {"error_msg": ex(e),
@ -124,47 +108,7 @@ class ApiHandler(RequestHandler):
else: else:
outputCallback = outputCallbackDict['default'] outputCallback = outputCallbackDict['default']
return outputCallback(outDict) return self.write(outputCallback(outDict))
def builder(self):
""" expose the api-builder template """
t = PageTemplate(headers=self.request.headers, file="apiBuilder.tmpl")
def titler(x):
if not x or sickbeard.SORT_ARTICLE:
return x
if x.lower().startswith('a '):
x = x[2:]
elif x.lower().startswith('an '):
x = x[3:]
elif x.lower().startswith('the '):
x = x[4:]
return x
t.sortedShowList = sorted(sickbeard.showList, lambda x, y: cmp(titler(x.name), titler(y.name)))
seasonSQLResults = {}
episodeSQLResults = {}
myDB = db.DBConnection(row_type="dict")
for curShow in t.sortedShowList:
seasonSQLResults[curShow.indexerid] = myDB.select(
"SELECT DISTINCT season FROM tv_episodes WHERE showid = ? ORDER BY season DESC", [curShow.indexerid])
for curShow in t.sortedShowList:
episodeSQLResults[curShow.indexerid] = myDB.select(
"SELECT DISTINCT season,episode FROM tv_episodes WHERE showid = ? ORDER BY season DESC, episode DESC",
[curShow.indexerid])
t.seasonSQLResults = seasonSQLResults
t.episodeSQLResults = episodeSQLResults
if len(sickbeard.API_KEY) == 32:
t.apikey = sickbeard.API_KEY
else:
t.apikey = "api key not generated"
return t
def _out_as_json(self, dict): def _out_as_json(self, dict):
self.set_header("Content-Type", "application/json;charset=UTF-8'") self.set_header("Content-Type", "application/json;charset=UTF-8'")
@ -179,39 +123,14 @@ class ApiHandler(RequestHandler):
e) + '"}' e) + '"}'
return out return out
def _grand_access(self, realKey, args, kwargs):
""" validate api key and log result """
remoteIp = self.request.remote_ip
apiKey = kwargs.get("apikey", None)
if not apiKey:
if args: # if we have keyless vars we assume first one is the api key, always !
apiKey = args[0]
args = args[1:] # remove the apikey from the args tuple
else:
del kwargs["apikey"]
if not sickbeard.USE_API: def call_dispatcher(self, args, kwargs):
msg = u"API :: " + remoteIp + " - SR API Disabled. ACCESS DENIED"
return False, msg, args, kwargs
elif apiKey == realKey:
msg = u"API :: " + remoteIp + " - gave correct API KEY - [" + apiKey + "] - ACCESS GRANTED"
return True, msg, args, kwargs
elif not apiKey:
msg = u"API :: " + remoteIp + " - gave NO API KEY. ACCESS DENIED"
return False, msg, args, kwargs
else:
msg = u"API :: " + remoteIp + " - gave WRONG API KEY - [" + apiKey + "] - ACCESS DENIED"
return False, msg, args, kwargs
def call_dispatcher(handler, args, kwargs):
""" calls the appropriate CMD class """ calls the appropriate CMD class
looks for a cmd in args and kwargs looks for a cmd in args and kwargs
or calls the TVDBShorthandWrapper when the first args element is a number or calls the TVDBShorthandWrapper when the first args element is a number
or returns an error that there is no such cmd or returns an error that there is no such cmd
""" """
logger.log(u"API :: all args: '" + str(args) + "'", logger.DEBUG) logger.log(u"API :: all args: '" + str(self.get_arguments('cmd')) + "'", logger.DEBUG)
logger.log(u"API :: all kwargs: '" + str(kwargs) + "'", logger.DEBUG)
# logger.log(u"API :: dateFormat: '" + str(dateFormat) + "'", logger.DEBUG) # logger.log(u"API :: dateFormat: '" + str(dateFormat) + "'", logger.DEBUG)
cmds = None cmds = None
@ -228,7 +147,7 @@ def call_dispatcher(handler, args, kwargs):
cmds = cmds.split("|") cmds = cmds.split("|")
multiCmds = bool(len(cmds) > 1) multiCmds = bool(len(cmds) > 1)
for cmd in cmds: for cmd in cmds:
curArgs, curKwargs = filter_params(cmd, args, kwargs) curArgs, curKwargs = self.filter_params(cmd, args, kwargs)
cmdIndex = None cmdIndex = None
if len(cmd.split("_")) > 1: # was a index used for this cmd ? if len(cmd.split("_")) > 1: # was a index used for this cmd ?
cmd, cmdIndex = cmd.split("_") # this gives us the clear cmd and the index cmd, cmdIndex = cmd.split("_") # this gives us the clear cmd and the index
@ -237,10 +156,9 @@ def call_dispatcher(handler, args, kwargs):
if not (multiCmds and cmd in ('show.getposter', 'show.getbanner')): # skip these cmd while chaining if not (multiCmds and cmd in ('show.getposter', 'show.getbanner')): # skip these cmd while chaining
try: try:
if cmd in _functionMaper: if cmd in _functionMaper:
curOutDict = _functionMaper.get(cmd)(handler, curArgs, curOutDict = _functionMaper.get(cmd)(curArgs, curKwargs).run()
curKwargs).run() # get the cmd class, init it and run()
elif _is_int(cmd): elif _is_int(cmd):
curOutDict = TVDBShorthandWrapper(handler, curArgs, curKwargs, cmd).run() curOutDict = TVDBShorthandWrapper(curArgs, curKwargs, cmd).run()
else: else:
curOutDict = _responds(RESULT_ERROR, "No such cmd: '" + cmd + "'") curOutDict = _responds(RESULT_ERROR, "No such cmd: '" + cmd + "'")
except ApiError, e: # Api errors that we raised, they are harmless except ApiError, e: # Api errors that we raised, they are harmless
@ -264,12 +182,12 @@ def call_dispatcher(handler, args, kwargs):
if multiCmds: # if we had multiple cmds we have to wrap it in a response dict if multiCmds: # if we had multiple cmds we have to wrap it in a response dict
outDict = _responds(RESULT_SUCCESS, outDict) outDict = _responds(RESULT_SUCCESS, outDict)
else: # index / no cmd given else: # index / no cmd given
outDict = CMD_SickBeard(handler, args, kwargs).run() outDict = CMD_SickBeard(args, kwargs).run()
return outDict return outDict
def filter_params(cmd, args, kwargs): def filter_params(self, cmd, args, kwargs):
""" return only params kwargs that are for cmd """ return only params kwargs that are for cmd
and rename them to a clean version (remove "<cmd>_") and rename them to a clean version (remove "<cmd>_")
args are shared across all cmds args are shared across all cmds
@ -306,19 +224,17 @@ def filter_params(cmd, args, kwargs):
class ApiCall(ApiHandler): class ApiCall(ApiHandler):
_help = {"desc": "No help message available. Please tell the devs that a help msg is missing for this cmd"} _help = {"desc": "No help message available. Please tell the devs that a help msg is missing for this cmd"}
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# missing # missing
try: try:
if self._missing: if self._missing:
self.run = self.return_missing self.run = self.return_missing
except AttributeError: except AttributeError:
pass pass
# help
if 'help' in kwargs:
self.run = self.return_help
# RequestHandler # help
self.handler = handler if self.get_argument('help', None):
self.run = self.return_help
def run(self): def run(self):
# override with real output function in subclass # override with real output function in subclass
@ -492,8 +408,7 @@ class ApiCall(ApiHandler):
class TVDBShorthandWrapper(ApiCall): class TVDBShorthandWrapper(ApiCall):
_help = {"desc": "this is an internal function wrapper. call the help command directly for more information"} _help = {"desc": "this is an internal function wrapper. call the help command directly for more information"}
def __init__(self, handler, args, kwargs, sid): def __init__(self, args, kwargs, sid):
self.handler = handler
self.origArgs = args self.origArgs = args
self.kwargs = kwargs self.kwargs = kwargs
self.sid = sid self.sid = sid
@ -502,17 +417,17 @@ class TVDBShorthandWrapper(ApiCall):
self.e, args = self.check_params(args, kwargs, "e", None, False, "ignore", []) self.e, args = self.check_params(args, kwargs, "e", None, False, "ignore", [])
self.args = args self.args = args
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" internal function wrapper """ """ internal function wrapper """
args = (self.sid,) + self.origArgs args = (self.sid,) + self.origArgs
if self.e: if self.e:
return CMD_Episode(self.handler, args, self.kwargs).run() return CMD_Episode(args, self.kwargs).run()
elif self.s: elif self.s:
return CMD_ShowSeasons(self.handler, args, self.kwargs).run() return CMD_ShowSeasons(args, self.kwargs).run()
else: else:
return CMD_Show(self.handler, args, self.kwargs).run() return CMD_Show(args, self.kwargs).run()
# ############################### # ###############################
@ -697,12 +612,12 @@ class CMD_Help(ApiCall):
} }
} }
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
# optional # optional
self.subject, args = self.check_params(args, kwargs, "subject", "help", False, "string", self.subject, args = self.check_params(args, kwargs, "subject", "help", False, "string",
_functionMaper.keys()) _functionMaper.keys())
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" display help information for a given subject/command """ """ display help information for a given subject/command """
@ -722,7 +637,7 @@ class CMD_ComingEpisodes(ApiCall):
} }
} }
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
# optional # optional
self.sort, args = self.check_params(args, kwargs, "sort", "date", False, "string", self.sort, args = self.check_params(args, kwargs, "sort", "date", False, "string",
@ -734,7 +649,7 @@ class CMD_ComingEpisodes(ApiCall):
False, "int", False, "int",
[0, 1]) [0, 1])
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" display the coming episodes """ """ display the coming episodes """
@ -847,7 +762,7 @@ class CMD_Episode(ApiCall):
} }
} }
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, True, "int", []) self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, True, "int", [])
self.s, args = self.check_params(args, kwargs, "season", None, True, "int", []) self.s, args = self.check_params(args, kwargs, "season", None, True, "int", [])
@ -855,7 +770,7 @@ class CMD_Episode(ApiCall):
# optional # optional
self.fullPath, args = self.check_params(args, kwargs, "full_path", 0, False, "bool", []) self.fullPath, args = self.check_params(args, kwargs, "full_path", 0, False, "bool", [])
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" display detailed info about an episode """ """ display detailed info about an episode """
@ -911,14 +826,14 @@ class CMD_EpisodeSearch(ApiCall):
} }
} }
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, True, "int", []) self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, True, "int", [])
self.s, args = self.check_params(args, kwargs, "season", None, True, "int", []) self.s, args = self.check_params(args, kwargs, "season", None, True, "int", [])
self.e, args = self.check_params(args, kwargs, "episode", None, True, "int", []) self.e, args = self.check_params(args, kwargs, "episode", None, True, "int", [])
# optional # optional
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" search for an episode """ """ search for an episode """
@ -965,7 +880,7 @@ class CMD_EpisodeSetStatus(ApiCall):
} }
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, True, "int", []) self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, True, "int", [])
self.s, args = self.check_params(args, kwargs, "season", None, True, "int", []) self.s, args = self.check_params(args, kwargs, "season", None, True, "int", [])
@ -975,7 +890,7 @@ class CMD_EpisodeSetStatus(ApiCall):
self.e, args = self.check_params(args, kwargs, "episode", None, False, "int", []) self.e, args = self.check_params(args, kwargs, "episode", None, False, "int", [])
self.force, args = self.check_params(args, kwargs, "force", 0, False, "bool", []) self.force, args = self.check_params(args, kwargs, "force", 0, False, "bool", [])
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" set status of an episode or a season (when no ep is provided) """ """ set status of an episode or a season (when no ep is provided) """
@ -1077,14 +992,14 @@ class CMD_SubtitleSearch(ApiCall):
} }
} }
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, True, "int", []) self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, True, "int", [])
self.s, args = self.check_params(args, kwargs, "season", None, True, "int", []) self.s, args = self.check_params(args, kwargs, "season", None, True, "int", [])
self.e, args = self.check_params(args, kwargs, "episode", None, True, "int", []) self.e, args = self.check_params(args, kwargs, "episode", None, True, "int", [])
# optional # optional
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" search episode subtitles """ """ search episode subtitles """
@ -1130,13 +1045,13 @@ class CMD_Exceptions(ApiCall):
} }
} }
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
# optional # optional
self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, False, "int", []) self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, False, "int", [])
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" display scene exceptions for all or a given show """ """ display scene exceptions for all or a given show """
@ -1173,14 +1088,14 @@ class CMD_History(ApiCall):
} }
} }
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
# optional # optional
self.limit, args = self.check_params(args, kwargs, "limit", 100, False, "int", []) self.limit, args = self.check_params(args, kwargs, "limit", 100, False, "int", [])
self.type, args = self.check_params(args, kwargs, "type", None, False, "string", self.type, args = self.check_params(args, kwargs, "type", None, False, "string",
["downloaded", "snatched"]) ["downloaded", "snatched"])
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" display sickrage downloaded/snatched history """ """ display sickrage downloaded/snatched history """
@ -1231,11 +1146,11 @@ class CMD_HistoryClear(ApiCall):
_help = {"desc": "clear sickrage's history", _help = {"desc": "clear sickrage's history",
} }
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
# optional # optional
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" clear sickrage's history """ """ clear sickrage's history """
@ -1249,11 +1164,11 @@ class CMD_HistoryTrim(ApiCall):
_help = {"desc": "trim sickrage's history by removing entries greater than 30 days old" _help = {"desc": "trim sickrage's history by removing entries greater than 30 days old"
} }
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
# optional # optional
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" trim sickrage's history """ """ trim sickrage's history """
@ -1269,12 +1184,12 @@ class CMD_Failed(ApiCall):
} }
} }
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
# optional # optional
self.limit, args = self.check_params(args, kwargs, "limit", 100, False, "int", []) self.limit, args = self.check_params(args, kwargs, "limit", 100, False, "int", [])
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" display failed downloads """ """ display failed downloads """
@ -1292,11 +1207,11 @@ class CMD_Failed(ApiCall):
class CMD_Backlog(ApiCall): class CMD_Backlog(ApiCall):
_help = {"desc": "display backlogged episodes"} _help = {"desc": "display backlogged episodes"}
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
# optional # optional
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" display backlogged episodes """ """ display backlogged episodes """
@ -1334,13 +1249,13 @@ class CMD_Logs(ApiCall):
"desc": "the minimum level classification of log entries to show, with each level inherting its above level"}} "desc": "the minimum level classification of log entries to show, with each level inherting its above level"}}
} }
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
# optional # optional
self.min_level, args = self.check_params(args, kwargs, "min_level", "error", False, "string", self.min_level, args = self.check_params(args, kwargs, "min_level", "error", False, "string",
["error", "warning", "info", "debug"]) ["error", "warning", "info", "debug"])
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" view sickrage's log """ """ view sickrage's log """
@ -1400,7 +1315,7 @@ class CMD_PostProcess(ApiCall):
} }
} }
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
# optional # optional
self.path, args = self.check_params(args, kwargs, "path", None, False, "string", []) self.path, args = self.check_params(args, kwargs, "path", None, False, "string", [])
@ -1412,7 +1327,7 @@ class CMD_PostProcess(ApiCall):
self.type, args = self.check_params(args, kwargs, "type", "auto", None, "string", self.type, args = self.check_params(args, kwargs, "type", "auto", None, "string",
["auto", "manual"]) ["auto", "manual"])
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" Starts the postprocess """ """ Starts the postprocess """
@ -1437,11 +1352,11 @@ class CMD_PostProcess(ApiCall):
class CMD_SickBeard(ApiCall): class CMD_SickBeard(ApiCall):
_help = {"desc": "display misc sickrage related information"} _help = {"desc": "display misc sickrage related information"}
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
# optional # optional
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" display misc sickrage related information """ """ display misc sickrage related information """
@ -1458,13 +1373,13 @@ class CMD_SickBeardAddRootDir(ApiCall):
} }
} }
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
self.location, args = self.check_params(args, kwargs, "location", None, True, "string", []) self.location, args = self.check_params(args, kwargs, "location", None, True, "string", [])
# optional # optional
self.default, args = self.check_params(args, kwargs, "default", 0, False, "bool", []) self.default, args = self.check_params(args, kwargs, "default", 0, False, "bool", [])
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" add a parent directory to sickrage's config """ """ add a parent directory to sickrage's config """
@ -1511,11 +1426,11 @@ class CMD_SickBeardAddRootDir(ApiCall):
class CMD_SickBeardCheckScheduler(ApiCall): class CMD_SickBeardCheckScheduler(ApiCall):
_help = {"desc": "query the scheduler"} _help = {"desc": "query the scheduler"}
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
# optional # optional
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" query the scheduler """ """ query the scheduler """
@ -1537,12 +1452,12 @@ class CMD_SickBeardDeleteRootDir(ApiCall):
"requiredParameters": {"location": {"desc": "the full path to root (parent) directory"}} "requiredParameters": {"location": {"desc": "the full path to root (parent) directory"}}
} }
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
self.location, args = self.check_params(args, kwargs, "location", None, True, "string", []) self.location, args = self.check_params(args, kwargs, "location", None, True, "string", [])
# optional # optional
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" delete a parent directory from sickrage's config """ """ delete a parent directory from sickrage's config """
@ -1581,11 +1496,11 @@ class CMD_SickBeardDeleteRootDir(ApiCall):
class CMD_SickBeardGetDefaults(ApiCall): class CMD_SickBeardGetDefaults(ApiCall):
_help = {"desc": "get sickrage user defaults"} _help = {"desc": "get sickrage user defaults"}
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
# optional # optional
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" get sickrage user defaults """ """ get sickrage user defaults """
@ -1601,15 +1516,15 @@ class CMD_SickBeardGetDefaults(ApiCall):
class CMD_SickBeardGetMessages(ApiCall): class CMD_SickBeardGetMessages(ApiCall):
_help = {"desc": "get all messages"} _help = {"desc": "get all messages"}
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
# optional # optional
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
messages = [] messages = []
for cur_notification in ui.notifications.get_notifications(self.handler.request.remote_ip): for cur_notification in ui.notifications.get_notifications(self.request.remote_ip):
messages.append({"title": cur_notification.title, messages.append({"title": cur_notification.title,
"message": cur_notification.message, "message": cur_notification.message,
"type": cur_notification.type}) "type": cur_notification.type})
@ -1619,11 +1534,11 @@ class CMD_SickBeardGetMessages(ApiCall):
class CMD_SickBeardGetRootDirs(ApiCall): class CMD_SickBeardGetRootDirs(ApiCall):
_help = {"desc": "get sickrage user parent directories"} _help = {"desc": "get sickrage user parent directories"}
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
# optional # optional
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" get the parent directories defined in sickrage's config """ """ get the parent directories defined in sickrage's config """
@ -1636,12 +1551,12 @@ class CMD_SickBeardPauseBacklog(ApiCall):
"optionalParameters": {"pause ": {"desc": "pause or unpause the global backlog"}} "optionalParameters": {"pause ": {"desc": "pause or unpause the global backlog"}}
} }
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
# optional # optional
self.pause, args = self.check_params(args, kwargs, "pause", 0, False, "bool", []) self.pause, args = self.check_params(args, kwargs, "pause", 0, False, "bool", [])
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" pause the backlog search """ """ pause the backlog search """
@ -1656,15 +1571,15 @@ class CMD_SickBeardPauseBacklog(ApiCall):
class CMD_SickBeardPing(ApiCall): class CMD_SickBeardPing(ApiCall):
_help = {"desc": "check to see if sickrage is running"} _help = {"desc": "check to see if sickrage is running"}
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
# optional # optional
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" check to see if sickrage is running """ """ check to see if sickrage is running """
self.handler.set_header('Cache-Control', "max-age=0,no-cache,no-store") self.set_header('Cache-Control', "max-age=0,no-cache,no-store")
if sickbeard.started: if sickbeard.started:
return _responds(RESULT_SUCCESS, {"pid": sickbeard.PID}, "Pong") return _responds(RESULT_SUCCESS, {"pid": sickbeard.PID}, "Pong")
else: else:
@ -1674,11 +1589,11 @@ class CMD_SickBeardPing(ApiCall):
class CMD_SickBeardRestart(ApiCall): class CMD_SickBeardRestart(ApiCall):
_help = {"desc": "restart sickrage"} _help = {"desc": "restart sickrage"}
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
# optional # optional
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" restart sickrage """ """ restart sickrage """
@ -1702,7 +1617,7 @@ class CMD_SickBeardSearchIndexers(ApiCall):
'de': 14, 'da': 10, 'fi': 11, 'hu': 19, 'ja': 25, 'he': 24, 'ko': 32, 'de': 14, 'da': 10, 'fi': 11, 'hu': 19, 'ja': 25, 'he': 24, 'ko': 32,
'sv': 8, 'sl': 30} 'sv': 8, 'sl': 30}
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
# optional # optional
self.name, args = self.check_params(args, kwargs, "name", None, False, "string", []) self.name, args = self.check_params(args, kwargs, "name", None, False, "string", [])
@ -1711,7 +1626,7 @@ class CMD_SickBeardSearchIndexers(ApiCall):
self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, False, "int", []) self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, False, "int", [])
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" search for show at tvdb with a given string and language """ """ search for show at tvdb with a given string and language """
@ -1789,9 +1704,9 @@ class CMD_SickBeardSearchTVDB(CMD_SickBeardSearchIndexers):
} }
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
self.indexerid, args = self.check_params(args, kwargs, "tvdbid", None, False, "int", []) self.indexerid, args = self.check_params(args, kwargs, "tvdbid", None, False, "int", [])
CMD_SickBeardSearchIndexers.__init__(self, handler, args, kwargs) CMD_SickBeardSearchIndexers.__init__(self, args, kwargs)
class CMD_SickBeardSearchTVRAGE(CMD_SickBeardSearchIndexers): class CMD_SickBeardSearchTVRAGE(CMD_SickBeardSearchIndexers):
@ -1802,9 +1717,9 @@ class CMD_SickBeardSearchTVRAGE(CMD_SickBeardSearchIndexers):
} }
} }
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
self.indexerid, args = self.check_params(args, kwargs, "tvrageid", None, False, "int", []) self.indexerid, args = self.check_params(args, kwargs, "tvrageid", None, False, "int", [])
CMD_SickBeardSearchIndexers.__init__(self, handler, args, kwargs) CMD_SickBeardSearchIndexers.__init__(self, args, kwargs)
class CMD_SickBeardSetDefaults(ApiCall): class CMD_SickBeardSetDefaults(ApiCall):
@ -1816,7 +1731,7 @@ class CMD_SickBeardSetDefaults(ApiCall):
} }
} }
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
# optional # optional
self.initial, args = self.check_params(args, kwargs, "initial", None, False, "list", self.initial, args = self.check_params(args, kwargs, "initial", None, False, "list",
@ -1833,7 +1748,7 @@ class CMD_SickBeardSetDefaults(ApiCall):
self.status, args = self.check_params(args, kwargs, "status", None, False, "string", self.status, args = self.check_params(args, kwargs, "status", None, False, "string",
["wanted", "skipped", "archived", "ignored"]) ["wanted", "skipped", "archived", "ignored"])
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" set sickrage user defaults """ """ set sickrage user defaults """
@ -1888,11 +1803,11 @@ class CMD_SickBeardSetDefaults(ApiCall):
class CMD_SickBeardShutdown(ApiCall): class CMD_SickBeardShutdown(ApiCall):
_help = {"desc": "shutdown sickrage"} _help = {"desc": "shutdown sickrage"}
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
# optional # optional
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" shutdown sickrage """ """ shutdown sickrage """
@ -1912,12 +1827,12 @@ class CMD_Show(ApiCall):
} }
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, True, "int", []) self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, True, "int", [])
# optional # optional
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" display information for a given show """ """ display information for a given show """
@ -1926,8 +1841,8 @@ class CMD_Show(ApiCall):
return _responds(RESULT_FAILURE, msg="Show not found") return _responds(RESULT_FAILURE, msg="Show not found")
showDict = {} showDict = {}
showDict["season_list"] = CMD_ShowSeasonList(self.handler, (), {"indexerid": self.indexerid}).run()["data"] showDict["season_list"] = CMD_ShowSeasonList((), {"indexerid": self.indexerid}).run()["data"]
showDict["cache"] = CMD_ShowCache(self.handler, (), {"indexerid": self.indexerid}).run()["data"] showDict["cache"] = CMD_ShowCache((), {"indexerid": self.indexerid}).run()["data"]
genreList = [] genreList = []
if showObj.genre: if showObj.genre:
@ -2008,7 +1923,7 @@ class CMD_ShowAddExisting(ApiCall):
} }
} }
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, True, "", []) self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, True, "", [])
@ -2027,7 +1942,7 @@ class CMD_ShowAddExisting(ApiCall):
self.subtitles, args = self.check_params(args, kwargs, "subtitles", int(sickbeard.USE_SUBTITLES), self.subtitles, args = self.check_params(args, kwargs, "subtitles", int(sickbeard.USE_SUBTITLES),
False, "int", []) False, "int", [])
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" add a show in sickrage with an existing folder """ """ add a show in sickrage with an existing folder """
@ -2039,8 +1954,7 @@ class CMD_ShowAddExisting(ApiCall):
return _responds(RESULT_FAILURE, msg='Not a valid location') return _responds(RESULT_FAILURE, msg='Not a valid location')
indexerName = None indexerName = None
indexerResult = CMD_SickBeardSearchIndexers(self.handler, [], indexerResult = CMD_SickBeardSearchIndexers([], {indexer_ids[self.indexer]: self.indexerid}).run()
{indexer_ids[self.indexer]: self.indexerid}).run()
if indexerResult['result'] == result_type_map[RESULT_SUCCESS]: if indexerResult['result'] == result_type_map[RESULT_SUCCESS]:
if not indexerResult['data']['results']: if not indexerResult['data']['results']:
@ -2111,7 +2025,7 @@ class CMD_ShowAddNew(ApiCall):
'de': 14, 'da': 10, 'fi': 11, 'hu': 19, 'ja': 25, 'he': 24, 'ko': 32, 'de': 14, 'da': 10, 'fi': 11, 'hu': 19, 'ja': 25, 'he': 24, 'ko': 32,
'sv': 8, 'sl': 30} 'sv': 8, 'sl': 30}
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, True, "int", []) self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, True, "int", [])
@ -2142,7 +2056,7 @@ class CMD_ShowAddNew(ApiCall):
[]) [])
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" add a show in sickrage with an existing folder """ """ add a show in sickrage with an existing folder """
@ -2205,8 +2119,7 @@ class CMD_ShowAddNew(ApiCall):
newStatus = self.status newStatus = self.status
indexerName = None indexerName = None
indexerResult = CMD_SickBeardSearchIndexers(self.handler, [], indexerResult = CMD_SickBeardSearchIndexers([], {indexer_ids[self.indexer]: self.indexerid}).run()
{indexer_ids[self.indexer]: self.indexerid}).run()
if indexerResult['result'] == result_type_map[RESULT_SUCCESS]: if indexerResult['result'] == result_type_map[RESULT_SUCCESS]:
if not indexerResult['data']['results']: if not indexerResult['data']['results']:
@ -2254,12 +2167,12 @@ class CMD_ShowCache(ApiCall):
} }
} }
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, True, "int", []) self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, True, "int", [])
# optional # optional
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" check sickrage's cache to see if the banner or poster image for a show is valid """ """ check sickrage's cache to see if the banner or poster image for a show is valid """
@ -2295,13 +2208,13 @@ class CMD_ShowDelete(ApiCall):
} }
} }
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, True, "int", []) self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, True, "int", [])
# optional # optional
self.removefiles, args = self.check_params(args, kwargs, "removefiles", 0, False, "int", [0,1]) self.removefiles, args = self.check_params(args, kwargs, "removefiles", 0, False, "int", [0,1])
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" delete a show in sickrage """ """ delete a show in sickrage """
@ -2333,12 +2246,12 @@ class CMD_ShowGetQuality(ApiCall):
} }
} }
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, True, "int", []) self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, True, "int", [])
# optional # optional
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" get quality setting for a show in sickrage """ """ get quality setting for a show in sickrage """
@ -2362,16 +2275,16 @@ class CMD_ShowGetPoster(ApiCall):
} }
} }
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, True, "int", []) self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, True, "int", [])
# optional # optional
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" get the poster for a show in sickrage """ """ get the poster for a show in sickrage """
return {'outputType': 'image', 'image': self.handler.showPoster(self.indexerid, 'poster')} return {'outputType': 'image', 'image': self.showPoster(self.indexerid, 'poster')}
class CMD_ShowGetBanner(ApiCall): class CMD_ShowGetBanner(ApiCall):
@ -2385,12 +2298,12 @@ class CMD_ShowGetBanner(ApiCall):
} }
} }
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, True, "int", []) self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, True, "int", [])
# optional # optional
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" get the banner for a show in sickrage """ """ get the banner for a show in sickrage """
@ -2409,13 +2322,13 @@ class CMD_ShowPause(ApiCall):
} }
} }
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, True, "int", []) self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, True, "int", [])
# optional # optional
self.pause, args = self.check_params(args, kwargs, "pause", 0, False, "bool", []) self.pause, args = self.check_params(args, kwargs, "pause", 0, False, "bool", [])
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" set a show's paused state in sickrage """ """ set a show's paused state in sickrage """
@ -2441,12 +2354,12 @@ class CMD_ShowRefresh(ApiCall):
} }
} }
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, True, "int", []) self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, True, "int", [])
# optional # optional
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" refresh a show in sickrage """ """ refresh a show in sickrage """
@ -2474,7 +2387,7 @@ class CMD_ShowSeasonList(ApiCall):
} }
} }
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, True, "int", []) self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, True, "int", [])
# optional # optional
@ -2482,7 +2395,7 @@ class CMD_ShowSeasonList(ApiCall):
["asc", ["asc",
"desc"]) # "asc" and "desc" default and fallback is "desc" "desc"]) # "asc" and "desc" default and fallback is "desc"
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" display the season list for a given show """ """ display the season list for a given show """
@ -2516,13 +2429,13 @@ class CMD_ShowSeasons(ApiCall):
} }
} }
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, True, "int", []) self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, True, "int", [])
# optional # optional
self.season, args = self.check_params(args, kwargs, "season", None, False, "int", []) self.season, args = self.check_params(args, kwargs, "season", None, False, "int", [])
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" display a listing of episodes for all or a given show """ """ display a listing of episodes for all or a given show """
@ -2589,7 +2502,7 @@ class CMD_ShowSetQuality(ApiCall):
} }
} }
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, True, "int", []) self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, True, "int", [])
# optional # optional
@ -2603,7 +2516,7 @@ class CMD_ShowSetQuality(ApiCall):
"fullhdwebdl", "fullhdwebdl",
"hdbluray", "fullhdbluray"]) "hdbluray", "fullhdbluray"])
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" set the quality for a show in sickrage by taking in a deliminated """ set the quality for a show in sickrage by taking in a deliminated
@ -2655,12 +2568,12 @@ class CMD_ShowStats(ApiCall):
} }
} }
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, True, "int", []) self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, True, "int", [])
# optional # optional
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" display episode statistics for a given show """ """ display episode statistics for a given show """
@ -2764,12 +2677,12 @@ class CMD_ShowUpdate(ApiCall):
} }
} }
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, True, "int", []) self.indexerid, args = self.check_params(args, kwargs, "indexerid", None, True, "int", [])
# optional # optional
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" update a show in sickrage """ """ update a show in sickrage """
@ -2793,13 +2706,13 @@ class CMD_Shows(ApiCall):
}, },
} }
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
# optional # optional
self.sort, args = self.check_params(args, kwargs, "sort", "id", False, "string", ["id", "name"]) self.sort, args = self.check_params(args, kwargs, "sort", "id", False, "string", ["id", "name"])
self.paused, args = self.check_params(args, kwargs, "paused", None, False, "bool", []) self.paused, args = self.check_params(args, kwargs, "paused", None, False, "bool", [])
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" display_is_int_multi( self.indexerid )shows in sickrage """ """ display_is_int_multi( self.indexerid )shows in sickrage """
@ -2836,7 +2749,7 @@ class CMD_Shows(ApiCall):
showDict['next_ep_airdate'] = '' showDict['next_ep_airdate'] = ''
showDict["cache"] = \ showDict["cache"] = \
CMD_ShowCache(self.handler, (), {"indexerid": curShow.indexerid}).run()["data"] CMD_ShowCache((), {"indexerid": curShow.indexerid}).run()["data"]
if not showDict["network"]: if not showDict["network"]:
showDict["network"] = "" showDict["network"] = ""
if self.sort == "name": if self.sort == "name":
@ -2851,11 +2764,11 @@ class CMD_ShowsStats(ApiCall):
_help = {"desc": "display the global shows and episode stats" _help = {"desc": "display the global shows and episode stats"
} }
def __init__(self, handler, args, kwargs): def __init__(self, args, kwargs):
# required # required
# optional # optional
# super, missing, help # super, missing, help
ApiCall.__init__(self, handler, args, kwargs) ApiCall.__init__(self, args, kwargs)
def run(self): def run(self):
""" display the global shows and episode stats """ """ display the global shows and episode stats """

View File

@ -17,6 +17,7 @@
# along with SickRage. If not, see <http://www.gnu.org/licenses/>. # along with SickRage. If not, see <http://www.gnu.org/licenses/>.
from __future__ import with_statement from __future__ import with_statement
import random
import traceback import traceback
import os import os
@ -24,7 +25,6 @@ import time
import urllib import urllib
import re import re
import datetime import datetime
import random
import sys import sys
import sickbeard import sickbeard
@ -133,7 +133,7 @@ def haveTORRENT():
return False return False
class Menus: class Menus:
def HomeMenu(self): def HomeMenu(self, *args, **kwargs):
menu = [ menu = [
{'title': 'Add Shows', 'path': 'home/addShows/', }, {'title': 'Add Shows', 'path': 'home/addShows/', },
{'title': 'Manual Post-Processing', 'path': 'home/postprocess/'}, {'title': 'Manual Post-Processing', 'path': 'home/postprocess/'},
@ -146,7 +146,7 @@ class Menus:
return menu return menu
def ConfigMenu(self): def ConfigMenu(self, *args, **kwargs):
menu = [ menu = [
{'title': 'General', 'path': 'config/general/'}, {'title': 'General', 'path': 'config/general/'},
{'title': 'Backup/Restore', 'path': 'config/backuprestore/'}, {'title': 'Backup/Restore', 'path': 'config/backuprestore/'},
@ -160,7 +160,7 @@ class Menus:
return menu return menu
def ManageMenu(self): def ManageMenu(self, *args, **kwargs):
menu = [ menu = [
{'title': 'Backlog Overview', 'path': 'manage/backlogOverview/'}, {'title': 'Backlog Overview', 'path': 'manage/backlogOverview/'},
{'title': 'Manage Searches', 'path': 'manage/manageSearches/'}, {'title': 'Manage Searches', 'path': 'manage/manageSearches/'},
@ -179,7 +179,7 @@ class Menus:
return menu return menu
def ErrorLogsMenu(self): def ErrorLogsMenu(self, *args, **kwargs):
menu = [ menu = [
{'title': 'Clear Errors', 'path': 'errorlogs/clearerrors/'}, {'title': 'Clear Errors', 'path': 'errorlogs/clearerrors/'},
# { 'title': 'View Log', 'path': 'errorlogs/viewlog' }, # { 'title': 'View Log', 'path': 'errorlogs/viewlog' },
@ -236,7 +236,7 @@ class PageTemplate(Template):
return super(PageTemplate, self).compile(*args, **kwargs) return super(PageTemplate, self).compile(*args, **kwargs)
class BaseHandler(RequestHandler): class BaseHandler(RequestHandler):
def get_current_user(self): def get_current_user(self, *args, **kwargs):
if sickbeard.WEB_USERNAME and sickbeard.WEB_PASSWORD: if sickbeard.WEB_USERNAME and sickbeard.WEB_PASSWORD:
return self.get_secure_cookie('user') return self.get_secure_cookie('user')
else: else:
@ -249,7 +249,6 @@ class BaseHandler(RequestHandler):
t.message = message t.message = message
return t return t
# Make non basic auth option to get api key
class KeyHandler(RequestHandler): class KeyHandler(RequestHandler):
def get(self, *args, **kwargs): def get(self, *args, **kwargs):
api_key = None api_key = None
@ -258,8 +257,8 @@ class KeyHandler(RequestHandler):
username = sickbeard.WEB_USERNAME username = sickbeard.WEB_USERNAME
password = sickbeard.WEB_PASSWORD password = sickbeard.WEB_PASSWORD
if (self.get_argument('u') == sickbeard.helpers.md5(username) or not username) \ if (self.get_argument('u', None) == username or not username) \
and (self.get_argument('p') == password or not password): and (self.get_argument('p', None) == password or not password):
api_key = sickbeard.API_KEY api_key = sickbeard.API_KEY
self.write({ self.write({
@ -270,24 +269,6 @@ class KeyHandler(RequestHandler):
logger.log('Failed doing key request: %s' % (traceback.format_exc()), logger.ERROR) logger.log('Failed doing key request: %s' % (traceback.format_exc()), logger.ERROR)
self.write({'success': False, 'error': 'Failed returning results'}) self.write({'success': False, 'error': 'Failed returning results'})
class UIHandler(RequestHandler):
def add_message(self):
ui.notifications.message('Test 1', 'This is test number 1')
ui.notifications.error('Test 2', 'This is test number 2')
return "ok"
def get_messages(self):
messages = {}
cur_notification_num = 1
for cur_notification in ui.notifications.get_notifications(self.request.remote_ip):
messages['notification-' + str(cur_notification_num)] = {'title': cur_notification.title,
'message': cur_notification.message,
'type': cur_notification.type}
cur_notification_num += 1
return json.dumps(messages)
class WebHandler(BaseHandler): class WebHandler(BaseHandler):
def write_error(self, status_code, **kwargs): def write_error(self, status_code, **kwargs):
if status_code == 404: if status_code == 404:
@ -323,7 +304,7 @@ class WebHandler(BaseHandler):
self.write('Could not load webui module') self.write('Could not load webui module')
return return
except: except:
page_not_found(self) page_not_found(self, *args, **kwargs)
return return
try: try:
@ -377,14 +358,53 @@ class LogoutHandler(BaseHandler):
@route('(.*)(/?)') @route('(.*)(/?)')
class WebRoot(WebHandler): class WebRoot(WebHandler):
def index(self): def index(self, *args, **kwargs):
self.redirect('/home/') self.redirect('/home/')
def robots_txt(self): def robots_txt(self, *args, **kwargs):
""" Keep web crawlers out """ """ Keep web crawlers out """
self.set_header('Content-Type', 'text/plain') self.set_header('Content-Type', 'text/plain')
return "User-agent: *\nDisallow: /" return "User-agent: *\nDisallow: /"
def apibuilder(self, *args, **kwargs):
t = PageTemplate(rh=self, file="apiBuilder.tmpl")
def titler(x):
if not x or sickbeard.SORT_ARTICLE:
return x
if x.lower().startswith('a '):
x = x[2:]
elif x.lower().startswith('an '):
x = x[3:]
elif x.lower().startswith('the '):
x = x[4:]
return x
t.sortedShowList = sorted(sickbeard.showList, lambda x, y: cmp(titler(x.name), titler(y.name)))
seasonSQLResults = {}
episodeSQLResults = {}
myDB = db.DBConnection(row_type="dict")
for curShow in t.sortedShowList:
seasonSQLResults[curShow.indexerid] = myDB.select(
"SELECT DISTINCT season FROM tv_episodes WHERE showid = ? ORDER BY season DESC", [curShow.indexerid])
for curShow in t.sortedShowList:
episodeSQLResults[curShow.indexerid] = myDB.select(
"SELECT DISTINCT season,episode FROM tv_episodes WHERE showid = ? ORDER BY season DESC, episode DESC",
[curShow.indexerid])
t.seasonSQLResults = seasonSQLResults
t.episodeSQLResults = episodeSQLResults
if len(sickbeard.API_KEY) == 32:
t.apikey = sickbeard.API_KEY
else:
t.apikey = "api key not generated"
return t
def showPoster(self, show=None, which=None): def showPoster(self, show=None, which=None):
# Redirect initial poster/banner thumb to default images # Redirect initial poster/banner thumb to default images
if which[0:6] == 'poster': if which[0:6] == 'poster':
@ -630,9 +650,28 @@ class WebRoot(WebHandler):
return ical return ical
@route('/ui/(.*)(/?)')
class UIHandler(WebRoot):
def add_message(self, *args, **kwargs):
ui.notifications.message('Test 1', 'This is test number 1')
ui.notifications.error('Test 2', 'This is test number 2')
return "ok"
def get_messages(self, *args, **kwargs):
messages = {}
cur_notification_num = 1
for cur_notification in ui.notifications.get_notifications(self.request.remote_ip):
messages['notification-' + str(cur_notification_num)] = {'title': cur_notification.title,
'message': cur_notification.message,
'type': cur_notification.type}
cur_notification_num += 1
return json.dumps(messages)
@route('/home/(.*)(/?)') @route('/home/(.*)(/?)')
class Home(WebRoot): class Home(WebRoot):
def index(self): def index(self, *args, **kwargs):
t = PageTemplate(rh=self, file="home.tmpl") t = PageTemplate(rh=self, file="home.tmpl")
if sickbeard.ANIME_SPLIT_HOME: if sickbeard.ANIME_SPLIT_HOME:
shows = [] shows = []
@ -3293,6 +3332,10 @@ class ConfigGeneral(Config):
t.submenu = Menus().ConfigMenu() t.submenu = Menus().ConfigMenu()
return t return t
def generateApiKey(self, *args, **kwargs):
return helpers.generateApiKey()
def saveRootDirs(self, rootDirString=None): def saveRootDirs(self, rootDirString=None):
sickbeard.ROOT_DIRS = rootDirString sickbeard.ROOT_DIRS = rootDirString
@ -3322,31 +3365,6 @@ class ConfigGeneral(Config):
sickbeard.save_config() sickbeard.save_config()
def generateKey(self, *args, **kwargs):
""" Return a new randomized API_KEY
"""
try:
from hashlib import md5
except ImportError:
from md5 import md5
# Create some values to seed md5
t = str(time.time())
r = str(random.random())
# Create the md5 instance and give it the current time
m = md5(t)
# Update the md5 instance with the random variable
m.update(r)
# Return a hex digest of the md5, eg 49f68a5c8493ec2c0bf489821c21fc3b
logger.log(u"New API generated")
return m.hexdigest()
def saveGeneral(self, log_dir=None, web_port=None, web_log=None, encryption_version=None, web_ipv6=None, def saveGeneral(self, log_dir=None, web_port=None, web_log=None, encryption_version=None, web_ipv6=None,
update_shows_on_start=None, trash_remove_show=None, trash_rotate_logs=None, update_frequency=None, update_shows_on_start=None, trash_remove_show=None, trash_rotate_logs=None, update_frequency=None,
launch_browser=None, web_username=None, launch_browser=None, web_username=None,
@ -4523,7 +4541,7 @@ class ConfigAnime(Config):
@route('/errorlogs/(.*)(/?)') @route('/errorlogs/(.*)(/?)')
class ErrorLogs(WebRoot): class ErrorLogs(WebRoot):
def index(self): def index(self, *args, **kwargs):
t = PageTemplate(rh=self, file="errorlogs.tmpl") t = PageTemplate(rh=self, file="errorlogs.tmpl")
t.submenu = Menus().ErrorLogsMenu() t.submenu = Menus().ErrorLogsMenu()

View File

@ -1,16 +1,13 @@
import os import os
import socket
import time
import threading import threading
import sys import sys
import sickbeard import sickbeard
import webserve
import webapi
from sickbeard.webserve import LoginHandler, LogoutHandler from sickbeard.webserve import LoginHandler, LogoutHandler, KeyHandler
from sickbeard.webapi import ApiHandler
from sickbeard import logger from sickbeard import logger
from sickbeard.helpers import create_https_certificates from sickbeard.helpers import create_https_certificates, generateApiKey
from tornado.web import Application, StaticFileHandler, HTTPError from tornado.web import Application, StaticFileHandler, HTTPError, RedirectHandler
from tornado.httpserver import HTTPServer from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop from tornado.ioloop import IOLoop
from tornado.routes import route from tornado.routes import route
@ -63,8 +60,13 @@ class SRWebServer(threading.Thread):
self.video_root = None self.video_root = None
# web root # web root
self.options['web_root'] = ('/' + self.options['web_root'].lstrip('/')) if self.options['web_root'] else '/' self.options['web_root'] = ('/' + self.options['web_root'].lstrip('/')).strip('/')
sickbeard.WEB_ROOT = self.options['web_root'].strip('/') sickbeard.WEB_ROOT = self.options['web_root']
# api root
if not sickbeard.API_KEY:
sickbeard.API_KEY = generateApiKey()
self.options['api_root'] = r'%s/api/%s/' % (sickbeard.WEB_ROOT, sickbeard.API_KEY)
# tornado setup # tornado setup
self.enable_https = self.options['enable_https'] self.enable_https = self.options['enable_https']
@ -97,20 +99,23 @@ class SRWebServer(threading.Thread):
# Main Handlers # Main Handlers
self.app.add_handlers(".*$", [ self.app.add_handlers(".*$", [
(r'%slogin(/?)' % self.options['web_root'], LoginHandler), (r'%s(/?)' % self.options['api_root'], ApiHandler),
(r'%slogout(/?)' % self.options['web_root'], LogoutHandler) (r'%s/getkey(/?)' % self.options['web_root'], KeyHandler),
(r'%s/api/builder' % self.options['web_root'], RedirectHandler, {"url": self.options['web_root'] + '/apibuilder/'}),
(r'%s/login(/?)' % self.options['web_root'], LoginHandler),
(r'%s/logout(/?)' % self.options['web_root'], LogoutHandler)
] + route.get_routes()) ] + route.get_routes())
# Static Path Handlers # Static Path Handlers
self.app.add_handlers(".*$", [ self.app.add_handlers(".*$", [
(r'%s(favicon\.ico)' % self.options['web_root'], MultiStaticFileHandler, (r'%s/(favicon\.ico)' % self.options['web_root'], MultiStaticFileHandler,
{'paths': [os.path.join(self.options['data_root'], 'images/ico/favicon.ico')]}), {'paths': [os.path.join(self.options['data_root'], 'images/ico/favicon.ico')]}),
(r'%s%s/(.*)(/?)' % (self.options['web_root'], 'images'), MultiStaticFileHandler, (r'%s/%s/(.*)(/?)' % (self.options['web_root'], 'images'), MultiStaticFileHandler,
{'paths': [os.path.join(self.options['data_root'], 'images'), {'paths': [os.path.join(self.options['data_root'], 'images'),
os.path.join(sickbeard.CACHE_DIR, 'images')]}), os.path.join(sickbeard.CACHE_DIR, 'images')]}),
(r'%s%s/(.*)(/?)' % (self.options['web_root'], 'css'), MultiStaticFileHandler, (r'%s/%s/(.*)(/?)' % (self.options['web_root'], 'css'), MultiStaticFileHandler,
{'paths': [os.path.join(self.options['data_root'], 'css')]}), {'paths': [os.path.join(self.options['data_root'], 'css')]}),
(r'%s%s/(.*)(/?)' % (self.options['web_root'], 'js'), MultiStaticFileHandler, (r'%s/%s/(.*)(/?)' % (self.options['web_root'], 'js'), MultiStaticFileHandler,
{'paths': [os.path.join(self.options['data_root'], 'js')]}), {'paths': [os.path.join(self.options['data_root'], 'js')]}),
]) ])