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

Fixed issues with network timezone downloads crashing on a empty return.

Changed version checker url and moved code to Home class.
Fixed WebUI issues caused by calling redirect method.
Fixed update checking issues, added no cache header.
Fixed WebAPI builder issues with show.delete cmd.
Fixed article sorting for both WebAPI and WebUI.
This commit is contained in:
echel0n 2014-12-12 17:52:32 -08:00
parent 6c4bedcec0
commit 0209852af5
7 changed files with 124 additions and 267 deletions

View File

@ -1,20 +1,23 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" <!DOCTYPE HTML>
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head> <head>
<title>API Builder</title> <meta charset="utf-8">
<title>SickRage - API Builder</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width">
<meta name="robots" content="noindex">
<script type="text/javascript" charset="utf-8"> <script type="text/javascript" charset="utf-8">
<!-- <!--
sbRoot = "$sbRoot"; sbRoot = "$sbRoot";
//--> //-->
</script> </script>
<script type="text/javascript" src="$sbRoot/js/lib/jquery-1.8.3.min.js?$sbPID"></script> <script type="text/javascript" src="$sbRoot/js/lib/jquery-1.7.2.min.js?$sbPID"></script>
<script type="text/javascript" src="$sbRoot/js/apibuilder.js?$sbPID"></script> <script type="text/javascript" src="$sbRoot/js/apibuilder.js?$sbPID"></script>
<style type="text/css"> <style type="text/css">
<!-- <!--
#apibuilder select { padding: 2px 2px 2px 6px; display: block; float: left; margin: auto 8px 4px auto; #apibuilder select { padding: 2px 2px 2px 6px; display: block; float: left; margin: auto 8px 4px auto; }
}
#apibuilder select option { padding: 1px 6px; line-height: 1.2em; } #apibuilder select option { padding: 1px 6px; line-height: 1.2em; }
#apibuilder .disabled { color: #ccc; } #apibuilder .disabled { color: #ccc; }
#apibuilder .action { background-color: #efefef; } #apibuilder .action { background-color: #efefef; }
@ -27,22 +30,20 @@ var disable_empty_list=true;
addListGroup("api", "Command"); addListGroup("api", "Command");
addOption("Command", "SickBeard", "?cmd=sb", 1); //make default addOption("Command", "SickRage", "?cmd=sb", 1); //make default
addList("Command", "SickBeard.AddRootDir", "?cmd=sb.addrootdir", "sb.addrootdir", "", "", "action"); addList("Command", "SickRage.AddRootDir", "?cmd=sb.addrootdir", "sb.addrootdir", "", "", "action");
addOption("Command", "SickBeard.CheckScheduler", "?cmd=sb.checkscheduler", "", "", "action"); addOption("Command", "SickRage.CheckScheduler", "?cmd=sb.checkscheduler", "", "", "action");
addList("Command", "SickBeard.DeleteRootDir", "?cmd=sb.deleterootdir", "sb.deleterootdir", "", "", "action"); addList("Command", "SickRage.DeleteRootDir", "?cmd=sb.deleterootdir", "sb.deleterootdir", "", "", "action");
addOption("Command", "SickBeard.ForceSearch", "?cmd=sb.forcesearch", "", "", "action"); addOption("Command", "SickRage.ForceSearch", "?cmd=sb.forcesearch", "", "", "action");
addOption("Command", "SickBeard.GetDefaults", "?cmd=sb.getdefaults", "", "", "action"); addOption("Command", "SickRage.GetDefaults", "?cmd=sb.getdefaults", "", "", "action");
addOption("Command", "SickBeard.GetMessages", "?cmd=sb.getmessages", "", "", "action"); addOption("Command", "SickRage.GetMessages", "?cmd=sb.getmessages", "", "", "action");
addOption("Command", "SickBeard.GetRootDirs", "?cmd=sb.getrootdirs", "", "", "action"); addOption("Command", "SickRage.GetRootDirs", "?cmd=sb.getrootdirs", "", "", "action");
addList("Command", "SickBeard.PauseBacklog", "?cmd=sb.pausebacklog", "sb.pausebacklog", "", "", "action"); addList("Command", "SickRage.PauseBacklog", "?cmd=sb.pausebacklog", "sb.pausebacklog", "", "", "action");
addOption("Command", "SickBeard.Ping", "?cmd=sb.ping", "", "", "action"); addOption("Command", "SickRage.Ping", "?cmd=sb.ping", "", "", "action");
addOption("Command", "SickBeard.Restart", "?cmd=sb.restart", "", "", "action"); addOption("Command", "SickRage.Restart", "?cmd=sb.restart", "", "", "action");
addList("Command", "SickBeard.SearchAllIndexers", "?cmd=sb.searchindexers", "sb.searchindexers", "", "", "action"); addList("Command", "SickRage.searchindexers", "?cmd=sb.searchindexers", "sb.searchindexers", "", "", "action");
addList("Command", "SickBeard.SearchTVDB", "?cmd=sb.searchtvdb&indexer=1", "sb.searchindexers", "", "", "action"); addList("Command", "SickRage.SetDefaults", "?cmd=sb.setdefaults", "sb.setdefaults", "", "", "action");
addList("Command", "SickBeard.SearchTVRage", "?cmd=sb.searchtvrage&indexer=2", "sb.searchindexers", "", "", "action"); addOption("Command", "SickRage.Shutdown", "?cmd=sb.shutdown", "", "", "action");
addList("Command", "SickBeard.SetDefaults", "?cmd=sb.setdefaults", "sb.setdefaults", "", "", "action");
addOption("Command", "SickBeard.Shutdown", "?cmd=sb.shutdown", "", "", "action");
addList("Command", "Coming Episodes", "?cmd=future", "future"); addList("Command", "Coming Episodes", "?cmd=future", "future");
addList("Command", "Episode", "?cmd=episode", "episode"); addList("Command", "Episode", "?cmd=episode", "episode");
addList("Command", "Episode.Search", "?cmd=episode.search", "episode.search", "", "", "action"); addList("Command", "Episode.Search", "?cmd=episode.search", "episode.search", "", "", "action");
@ -51,16 +52,12 @@ addList("Command", "Scene Exceptions", "?cmd=exceptions", "exceptions");
addList("Command", "History", "?cmd=history", "history"); addList("Command", "History", "?cmd=history", "history");
addOption("Command", "History.Clear", "?cmd=history.clear", "", "", "action"); addOption("Command", "History.Clear", "?cmd=history.clear", "", "", "action");
addOption("Command", "History.Trim", "?cmd=history.trim", "", "", "action"); addOption("Command", "History.Trim", "?cmd=history.trim", "", "", "action");
addList("Command", "Failed", "?cmd=failed", "failed");
addOption("Command", "Backlog", "?cmd=backlog");
addList("Command", "PostProcess", "?cmd=postprocess", "postprocess", "", "","action");
addList("Command", "Logs", "?cmd=logs", "logs"); addList("Command", "Logs", "?cmd=logs", "logs");
addList("Command", "Show", "?cmd=show", "indexerid"); addList("Command", "Show", "?cmd=show", "indexerid");
addList("Command", "Show.AddExisting", "?cmd=show.addexisting", "show.addexisting", "", "", "action"); addList("Command", "Show.AddExisting", "?cmd=show.addexisting", "show.addexisting", "", "", "action");
addList("Command", "Show.AddNew", "?cmd=show.addnew", "show.addnew", "", "", "action"); addList("Command", "Show.AddNew", "?cmd=show.addnew", "show.addnew", "", "", "action");
addList("Command", "Show.Cache", "?cmd=show.cache", "indexerid", "", "", "action"); addList("Command", "Show.Cache", "?cmd=show.cache", "indexerid", "", "", "action");
addList("Command", "Show.Delete", "?cmd=show.delete", "indexerid", "", "", "action"); addList("Command", "Show.Delete", "?cmd=show.delete", "show.delete", "", "", "action");
addList("Command", "Show.GetBanner", "?cmd=show.getbanner", "indexerid", "", "", "action"); addList("Command", "Show.GetBanner", "?cmd=show.getbanner", "indexerid", "", "", "action");
addList("Command", "Show.GetPoster", "?cmd=show.getposter", "indexerid", "", "", "action"); addList("Command", "Show.GetPoster", "?cmd=show.getposter", "indexerid", "", "", "action");
addList("Command", "Show.GetQuality", "?cmd=show.getquality", "indexerid", "", "", "action"); addList("Command", "Show.GetQuality", "?cmd=show.getquality", "indexerid", "", "", "action");
@ -85,18 +82,6 @@ addOption("logs", "Info", "&min_level=info");
addOption("logs", "Warning", "&min_level=warning"); addOption("logs", "Warning", "&min_level=warning");
addOption("logs", "Error", "&min_level=error"); addOption("logs", "Error", "&min_level=error");
addOption("show.delete", "Optional Param", "", 1);
addOption("show.delete", "removefiles", "&removefiles=0");
addOption("show.delete", "removefiles", "&removefiles=1");
addOption("postprocess", "Optional Param", "", 1);
addOption("postprocess", "C:\\PATH\\TO\\DIR", "&path=C:\\Temp");
addOption("postprocess", "return_data", "&return_data=1");
addOption("postprocess", "force_replace", "&force_replace=1");
addOption("postprocess", "is_priority", "&is_priority=1");
addOption("postprocess", "process_method", "&process_method=copy");
addOption("postprocess", "type", "&type=manual")
addOption("sb.setdefaults", "Optional Param", "", 1); addOption("sb.setdefaults", "Optional Param", "", 1);
addList("sb.setdefaults", "Exclude Paused Shows on ComingEps", "&future_show_paused=0", "sb.setdefaults-status"); addList("sb.setdefaults", "Exclude Paused Shows on ComingEps", "&future_show_paused=0", "sb.setdefaults-status");
addList("sb.setdefaults", "Include Paused Shows on ComingEps", "&future_show_paused=1", "sb.setdefaults-status"); addList("sb.setdefaults", "Include Paused Shows on ComingEps", "&future_show_paused=1", "sb.setdefaults-status");
@ -108,14 +93,14 @@ addList("sb.setdefaults-status", "Archived", "&status=archived", "sb.setdefaults
addList("sb.setdefaults-status", "Ignored", "&status=ignored", "sb.setdefaults-opt"); addList("sb.setdefaults-status", "Ignored", "&status=ignored", "sb.setdefaults-opt");
addOption("sb.setdefaults-opt", "Optional Param", "", 1); addOption("sb.setdefaults-opt", "Optional Param", "", 1);
addList("sb.setdefaults-opt", "No Season Folder", "&season_folder=0", "quality"); addList("sb.setdefaults-opt", "Flatten (No Season Folder)", "&flatten_folders=1", "quality");
addList("sb.setdefaults-opt", "Use Season Folder", "&season_folder=1", "quality"); addList("sb.setdefaults-opt", "Use Season Folder", "&flatten_folders=0", "quality");
addOption("shows", "Optional Param", "", 1); addOption("shows", "Optional Param", "", 1);
addOption("shows", "Show Only Paused", "&paused=1"); addOption("shows", "Show Only Paused", "&paused=1");
addOption("shows", "Show Only Not Paused", "&paused=0"); addOption("shows", "Show Only Not Paused", "&paused=0");
addOption("shows", "Sort by Show Name", "&sort=name"); addOption("shows", "Sort by Show Name", "&sort=name");
addOption("shows", "Sort by TVDB ID", "&sort=id"); addOption("shows", "Sort by INDEXER ID", "&sort=id");
addList("show.addexisting", "C:\\temp\\show1", "&location=C:\\temp\\show1", "show.addexisting-indexerid"); addList("show.addexisting", "C:\\temp\\show1", "&location=C:\\temp\\show1", "show.addexisting-indexerid");
addList("show.addexisting", "D:\\Temp\\show2", "&location=D:\\Temp\\show2", "show.addexisting-indexerid"); addList("show.addexisting", "D:\\Temp\\show2", "&location=D:\\Temp\\show2", "show.addexisting-indexerid");
@ -126,8 +111,8 @@ addList("show.addexisting-indexerid", "101501 (Ancient Aliens)", "&indexerid=101
addList("show.addexisting-indexerid", "80348 (Chuck)", "&indexerid=80348", "show.addexisting-opt"); addList("show.addexisting-indexerid", "80348 (Chuck)", "&indexerid=80348", "show.addexisting-opt");
addOption("show.addexisting-opt", "Optional Param", "", 1); addOption("show.addexisting-opt", "Optional Param", "", 1);
addList("show.addexisting-opt", "No Season Folder", "&season_folder=0", "quality"); addList("show.addexisting-opt", "Flatten (No Season Folder)", "&flatten_folders=1", "quality");
addList("show.addexisting-opt", "Use Season Folder", "&season_folder=1", "quality"); addList("show.addexisting-opt", "Use Season Folder", "&flatten_folders=0", "quality");
addList("show.addnew", "101501 (Ancient Aliens)", "&indexerid=101501", "show.addnew-loc"); addList("show.addnew", "101501 (Ancient Aliens)", "&indexerid=101501", "show.addnew-loc");
addList("show.addnew", "80348 (Chuck)", "&indexerid=80348", "show.addnew-loc"); addList("show.addnew", "80348 (Chuck)", "&indexerid=80348", "show.addnew-loc");
@ -145,8 +130,8 @@ addList("show.addnew-status", "Archived", "&status=archived", "show.addnew-opt")
addList("show.addnew-status", "Ignored", "&status=ignored", "show.addnew-opt"); addList("show.addnew-status", "Ignored", "&status=ignored", "show.addnew-opt");
addOption("show.addnew-opt", "Optional Param", "", 1); addOption("show.addnew-opt", "Optional Param", "", 1);
addList("show.addnew-opt", "No Season Folder", "&season_folder=0", "quality"); addList("show.addnew-opt", "Flatten (No Season Folder)", "&flatten_folders=1", "quality");
addList("show.addnew-opt", "Use Season Folder", "&season_folder=1", "quality"); addList("show.addnew-opt", "Use Season Folder", "&flatten_folders=0", "quality");
addOptGroup("sb.searchindexers", "Search by Name"); addOptGroup("sb.searchindexers", "Search by Name");
addList("sb.searchindexers", "Lost", "&name=Lost", "sb.searchindexers-lang"); addList("sb.searchindexers", "Lost", "&name=Lost", "sb.searchindexers-lang");
@ -283,15 +268,25 @@ addList("episode.setstatus", "$curShow.name", "&indexerid=$curShow.indexerid", "
// build out each show's season+episode list for episode.setstatus cmd // build out each show's season+episode list for episode.setstatus cmd
#for $curShow in $episodeSQLResults: #for $curShow in $episodeSQLResults:
#set $curSeason = -1
#for $curShowSeason in $episodeSQLResults[$curShow]: #for $curShowSeason in $episodeSQLResults[$curShow]:
#if $curShowSeason.season != $curSeason and $curShowSeason.season != 0:
// insert just the season as the ep number is now optional
addList("episode.setstatus-$curShow", "Season $curShowSeason.season", "&season=$curShowSeason.season", "episode-status-$curShow");
#end if
#set $curSeason = int($curShowSeason.season)
addList("episode.setstatus-$curShow", "$curShowSeason.season x $curShowSeason.episode", "&season=$curShowSeason.season&episode=$curShowSeason.episode", "episode-status-$curShow"); addList("episode.setstatus-$curShow", "$curShowSeason.season x $curShowSeason.episode", "&season=$curShowSeason.season&episode=$curShowSeason.episode", "episode-status-$curShow");
#end for #end for
addOption("episode-status-$curShow", "Wanted", "&status=wanted"); addList("episode-status-$curShow", "Wanted", "&status=wanted", "force");
addOption("episode-status-$curShow", "Skipped", "&status=skipped"); addList("episode-status-$curShow", "Skipped", "&status=skipped", "force");
addOption("episode-status-$curShow", "Archived", "&status=archived"); addList("episode-status-$curShow", "Archived", "&status=archived", "force");
addOption("episode-status-$curShow", "Ignored", "&status=ignored"); addList("episode-status-$curShow", "Ignored", "&status=ignored", "force");
#end for #end for
addOption("force", "Optional Param", "", 1);
addOption("force", "Replace Downloaded EP", "&force=1");
addOption("force", "Skip Downloaded EP", "&force=0");
addOption("future", "Optional Param", "", 1); addOption("future", "Optional Param", "", 1);
addList("future", "Sort by Date", "&sort=date", "future-type"); addList("future", "Sort by Date", "&sort=date", "future-type");
addList("future", "Sort by Network", "&sort=network", "future-type"); addList("future", "Sort by Network", "&sort=network", "future-type");
@ -327,15 +322,6 @@ addOption("history-limit", "Optional Param", "", 1);
addOption("history-limit", "Show Only Downloaded", "&type=downloaded"); addOption("history-limit", "Show Only Downloaded", "&type=downloaded");
addOption("history-limit", "Show Only Snatched", "&type=snatched"); addOption("history-limit", "Show Only Snatched", "&type=snatched");
addOption("failed", "Optional Param", "", 1);
//addOptGroup("failed", "Limit Results");
addList("failed", "Limit Results (2)", "&limit=2", "failed-limit");
addList("failed", "Limit Results (25)", "&limit=25", "failed-limit");
addList("failed", "Limit Results (50)", "&limit=50", "failed-limit");
//endOptGroup("failed");
addOption("failed-limit", "Optional Param", "", 1);
addOption("exceptions", "Optional Param", "", 1); addOption("exceptions", "Optional Param", "", 1);
#for $curShow in $sortedShowList: #for $curShow in $sortedShowList:
addOption("exceptions", "$curShow.name", "&indexerid=$curShow.indexerid"); addOption("exceptions", "$curShow.name", "&indexerid=$curShow.indexerid");
@ -364,6 +350,13 @@ addOption("show.pause-opt", "Optional Param", "", 1);
addOption("show.pause-opt", "Unpause", "&pause=0"); addOption("show.pause-opt", "Unpause", "&pause=0");
addOption("show.pause-opt", "Pause", "&pause=1"); addOption("show.pause-opt", "Pause", "&pause=1");
#for $curShow in $sortedShowList:
addList("show.delete", "$curShow.name", "&indexerid=$curShow.indexerid", "show.delete-opt");
#end for
addOption("show.delete-opt", "Optional Param", "", 1);
addOption("show.delete-opt", "Remove Files", "&removefiles=1");
addOption("show.delete-opt", "Don't Remove Files", "&removefiles=0");
</script> </script>
</head> </head>
@ -390,8 +383,8 @@ addOption("show.pause-opt", "Pause", "&pause=1");
<select name="sixthlevel"><option></option></select> <select name="sixthlevel"><option></option></select>
<select name="seventhlevel"><option></option></select> <select name="seventhlevel"><option></option></select>
<div style="float: left; "> <div style="float: left; ">
<input class="btn" type="button" value="Reset" onclick="resetListGroup('api',1)" /> <input type="button" value="Reset" onclick="resetListGroup('api',1)" />
<input class="btn" type="button" value="Go" onclick="goListGroup(this.form['apikey'].value, this.form['seventhlevel'].value, this.form['sixthlevel'].value, this.form['fifthlevel'].value, this.form['forthlevel'].value, this.form['thirdlevel'].value, this.form['secondlevel'].value, this.form['firstlevel'].value)" /> <input type="button" value="Go" onclick="goListGroup(this.form['apikey'].value, this.form['seventhlevel'].value, this.form['sixthlevel'].value, this.form['fifthlevel'].value, this.form['forthlevel'].value, this.form['thirdlevel'].value, this.form['secondlevel'].value, this.form['firstlevel'].value)" />
</div> </div>
</td> </td>
</tr> </tr>

View File

@ -244,7 +244,7 @@
</tr> </tr>
#end if #end if
<tr><td class="showLegend">Size:</td><td>$sickbeard.helpers.human(sickbeard.helpers.get_size($showLoc[0]))</td></tr> <tr><td class="showLegend">Size:</td><td>$sickbeard.helpers.pretty_filesize(sickbeard.helpers.get_size($showLoc[0]))</td></tr>
</table> </table>

View File

@ -11,7 +11,7 @@ var _disable_empty_list=false;
var _hide_empty_list=false; var _hide_empty_list=false;
function goListGroup(apikey, L7, L6, L5, L4, L3, L2, L1){ function goListGroup(apikey, L7, L6, L5, L4, L3, L2, L1){
var GlobalOptions = ""; var html, GlobalOptions = "";
$('.global').each(function(){ $('.global').each(function(){
var checked = $(this).prop('checked'); var checked = $(this).prop('checked');
if(checked) { if(checked) {
@ -28,7 +28,7 @@ function goListGroup(apikey, L7, L6, L5, L4, L3, L2, L1){
// handle the show.getposter / show.getbanner differently as they return an image and not json // handle the show.getposter / show.getbanner differently as they return an image and not json
if (L1 == "?cmd=show.getposter" || L1 == "?cmd=show.getbanner") { if (L1 == "?cmd=show.getposter" || L1 == "?cmd=show.getbanner") {
var imgcache = sbRoot + "/api/" + apikey + "/" + L1 + L2 + GlobalOptions; var imgcache = sbRoot + "/api/" + apikey + "/" + L1 + L2 + GlobalOptions;
var html = imgcache + '<br/><br/><img src="' + sbRoot + '/images/loading16.gif" id="imgcache">'; html = imgcache + '<br/><br/><img src="' + sbRoot + '/images/loading16.gif" id="imgcache">';
$('#apiResponse').html(html); $('#apiResponse').html(html);
$.ajax({ $.ajax({
url: sbRoot + "/api/" + apikey + "/" + L1 + L2 + GlobalOptions, url: sbRoot + "/api/" + apikey + "/" + L1 + L2 + GlobalOptions,
@ -38,10 +38,10 @@ function goListGroup(apikey, L7, L6, L5, L4, L3, L2, L1){
success: function (img) { success: function (img) {
$('#imgcache').attr('src', imgcache); $('#imgcache').attr('src', imgcache);
} }
}) });
} }
else { else {
var html = sbRoot + "/api/" + apikey + "/" + L1 + L2 + L3 + L4 + L5 + L6 + L7 + GlobalOptions + "<br/><pre>"; html = sbRoot + "/api/" + apikey + "/" + L1 + L2 + L3 + L4 + L5 + L6 + L7 + GlobalOptions + "<br/><pre>";
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,
@ -189,13 +189,13 @@ function cs_getCookie(name) {
function cs_optionOBJ(type,text,value,label,css) { this.type=type; this.text=text; this.value=value; this.label=label; this.css=css; } function cs_optionOBJ(type,text,value,label,css) { this.type=type; this.text=text; this.value=value; this.label=label; this.css=css; }
function cs_getOptions(menu,list) { function cs_getOptions(menu,list) {
var opt=new Array(); var opt=[];
for (var i=0; i<menu.items.length; i++) { for (var i=0; i<menu.items.length; i++) {
opt[i]=new cs_optionOBJ(menu.items[i].type, menu.items[i].dis, menu.items[i].link, menu.items[i].label, menu.items[i].css); opt[i]=new cs_optionOBJ(menu.items[i].type, menu.items[i].dis, menu.items[i].link, menu.items[i].label, menu.items[i].css);
} }
if (opt.length==0 && menu.name!="") { if (opt.length==0 && menu.name!="") {
cs_getSubList(menu.name,list); cs_getSubList(menu.name,list);
opt[0]=new cs_optionOBJ(cs_L, "loading ...", "", "", ""); //opt[0]=new cs_optionOBJ(cs_L, "loading ...", "", "", "");
} }
return opt; return opt;
} }

View File

@ -43,18 +43,6 @@ import adba
import requests import requests
import requests.exceptions import requests.exceptions
try:
import json
except ImportError:
from lib import simplejson as json
try:
import xml.etree.cElementTree as etree
except ImportError:
import elementtree.ElementTree as etree
from xml.dom.minidom import Node
from sickbeard.exceptions import MultipleShowObjectsException, ex from sickbeard.exceptions import MultipleShowObjectsException, ex
from sickbeard import logger, classes from sickbeard import logger, classes
from sickbeard.common import USER_AGENT, mediaExtensions, subtitleExtensions from sickbeard.common import USER_AGENT, mediaExtensions, subtitleExtensions
@ -659,8 +647,7 @@ def get_all_episodes_from_absolute_number(show, absolute_numbers, indexer_id=Non
if not show and indexer_id: if not show and indexer_id:
show = findCertainShow(sickbeard.showList, indexer_id) show = findCertainShow(sickbeard.showList, indexer_id)
if show: for absolute_number in absolute_numbers if show else []:
for absolute_number in absolute_numbers:
ep = show.getEpisode(None, None, absolute_number=absolute_number) ep = show.getEpisode(None, None, absolute_number=absolute_number)
if ep: if ep:
episodes.append(ep.episode) episodes.append(ep.episode)
@ -733,79 +720,6 @@ def create_https_certificates(ssl_cert, ssl_key):
return True return True
if __name__ == '__main__':
import doctest
doctest.testmod()
def parse_json(data):
"""
Parse json data into a python object
data: data string containing json
Returns: parsed data as json or None
"""
try:
parsedJSON = json.loads(data)
except ValueError, e:
logger.log(u"Error trying to decode json data. Error: " + ex(e), logger.DEBUG)
return None
return parsedJSON
def parse_xml(data, del_xmlns=False):
"""
Parse data into an xml elementtree.ElementTree
data: data string containing xml
del_xmlns: if True, removes xmlns namesspace from data before parsing
Returns: parsed data as elementtree or None
"""
if del_xmlns:
data = re.sub(' xmlns="[^"]+"', '', data)
try:
parsedXML = etree.fromstring(data)
except Exception, e:
logger.log(u"Error trying to parse xml data. Error: " + ex(e), logger.DEBUG)
parsedXML = None
return parsedXML
def get_xml_text(element, mini_dom=False):
"""
Get all text inside a xml element
element: A xml element either created with elementtree.ElementTree or xml.dom.minidom
mini_dom: Default False use elementtree, True use minidom
Returns: text
"""
text = ""
if mini_dom:
node = element
for child in node.childNodes:
if child.nodeType in (Node.CDATA_SECTION_NODE, Node.TEXT_NODE):
text += child.data
else:
if element is not None:
for child in [element] + element.findall('.//*'):
if child.text:
text += child.text
return text.strip()
def backupVersionedFile(old_file, version): def backupVersionedFile(old_file, version):
numTries = 0 numTries = 0
@ -1397,32 +1311,6 @@ def clearCache(force=False):
logger.WARNING) logger.WARNING)
break break
def human(size):
"""
format a size in bytes into a 'human' file size, e.g. bytes, KB, MB, GB, TB, PB
Note that bytes/KB will be reported in whole numbers but MB and above will have greater precision
e.g. 1 byte, 43 bytes, 443 KB, 4.3 MB, 4.43 GB, etc
"""
if size == 1:
# because I really hate unnecessary plurals
return "1 byte"
suffixes_table = [('bytes', 0), ('KB', 0), ('MB', 1), ('GB', 2),('TB', 2), ('PB', 2)]
num = float(size)
for suffix, precision in suffixes_table:
if num < 1024.0:
break
num /= 1024.0
if precision == 0:
formatted_size = "%d" % num
else:
formatted_size = str(round(num, ndigits=precision))
return "%s %s" % (formatted_size, suffix)
def get_size(start_path='.'): def get_size(start_path='.'):
total_size = 0 total_size = 0
@ -1432,11 +1320,7 @@ def get_size(start_path='.'):
total_size += ek.ek(os.path.getsize, fp) total_size += ek.ek(os.path.getsize, fp)
return total_size return total_size
def md5(text): def generateApiKey():
return hashlib.md5(ek.ss(text)).hexdigest()
def generateApiKey(*args, **kwargs):
""" Return a new randomized API_KEY """ Return a new randomized API_KEY
""" """
@ -1475,4 +1359,12 @@ def pretty_filesize(file_bytes):
size = '%.2f KB' % kilobytes size = '%.2f KB' % kilobytes
else: else:
size = '%.2f b' % file_bytes size = '%.2f b' % file_bytes
return size return size
if __name__ == '__main__':
import doctest
doctest.testmod()
def remove_article(text=''):
return re.sub(r'(?i)/^(?:(?:A(?!\s+to)n?)|The)\s(\w)', r'\1', text)

View File

@ -120,14 +120,14 @@ class NewznabProvider(generic.NZBProvider):
params['apikey'] = self.key params['apikey'] = self.key
try: try:
categories = self.getURL("%s/api" % (self.url), params=params, timeout=10) xml_categories = self.getURL("%s/api" % (self.url), params=params, timeout=10, json=True)
except: except:
logger.log(u"Error getting html for [%s]" % logger.log(u"Error getting html for [%s]" %
("%s/api?%s" % (self.url, '&'.join("%s=%s" % (x,y) for x,y in params.items())) ), logger.DEBUG) ("%s/api?%s" % (self.url, '&'.join("%s=%s" % (x,y) for x,y in params.items())) ), logger.DEBUG)
return (False, return_categories, "Error getting html for [%s]" % return (False, return_categories, "Error getting html for [%s]" %
("%s/api?%s" % (self.url, '&'.join("%s=%s" % (x,y) for x,y in params.items()) ))) ("%s/api?%s" % (self.url, '&'.join("%s=%s" % (x,y) for x,y in params.items()) )))
xml_categories = helpers.parse_xml(categories) #xml_categories = helpers.parse_xml(categories)
if not xml_categories: if not xml_categories:
logger.log(u"Error parsing xml for [%s]" % (self.name), logger.log(u"Error parsing xml for [%s]" % (self.name),

View File

@ -36,8 +36,8 @@ from sickbeard import classes
from sickbeard import processTV from sickbeard import processTV
from sickbeard import network_timezones, sbdatetime from sickbeard import network_timezones, sbdatetime
from sickbeard.exceptions import ex from sickbeard.exceptions import ex
from sickbeard.common import SNATCHED, SNATCHED_PROPER, DOWNLOADED, SKIPPED, UNAIRED, IGNORED, ARCHIVED, WANTED, UNKNOWN from sickbeard.common import Quality, Overview, qualityPresetStrings, statusStrings, SNATCHED, SNATCHED_PROPER, DOWNLOADED, SKIPPED, UNAIRED, IGNORED, ARCHIVED, WANTED, UNKNOWN
from common import Quality, Overview, qualityPresetStrings, statusStrings from sickbeard.webserve import WebRoot
try: try:
import json import json
@ -322,12 +322,12 @@ class ApiCall(ApiHandler):
if required: if required:
try: try:
self._missing self._missing
self._requiredParams.append(key) self._requiredParams += [key]
except AttributeError: except AttributeError:
self._missing = [] self._missing = []
self._requiredParams = {} self._requiredParams = {key: {"allowedValues": allowedValues,
self._requiredParams[key] = {"allowedValues": allowedValues, "defaultValue": orgDefault}}
"defaultValue": orgDefault}
if missing and key not in self._missing: if missing and key not in self._missing:
self._missing.append(key) self._missing.append(key)
else: else:
@ -2291,7 +2291,7 @@ class CMD_ShowGetPoster(ApiCall):
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.showPoster(self.indexerid, 'poster')} return {'outputType': 'image', 'image': WebRoot().showPoster(self.indexerid, 'poster')}
class CMD_ShowGetBanner(ApiCall): class CMD_ShowGetBanner(ApiCall):
@ -2314,7 +2314,7 @@ class CMD_ShowGetBanner(ApiCall):
def run(self): def run(self):
""" get the banner for a show in sickrage """ """ get the banner for a show in sickrage """
return {'outputType': 'image', 'image': self.handler.showPoster(self.indexerid, 'banner')} return {'outputType': 'image', 'image': WebRoot().showPoster(self.indexerid, 'banner')}
class CMD_ShowPause(ApiCall): class CMD_ShowPause(ApiCall):

View File

@ -17,7 +17,6 @@
# 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 inspect
import traceback import traceback
import os import os
@ -27,7 +26,6 @@ import re
import datetime import datetime
import sickbeard import sickbeard
from sickbeard import config, sab from sickbeard import config, sab
from sickbeard import clients from sickbeard import clients
from sickbeard import history, notifiers, processTV from sickbeard import history, notifiers, processTV
@ -41,7 +39,6 @@ from sickbeard import scene_exceptions
from sickbeard import subtitles from sickbeard import subtitles
from sickbeard import network_timezones from sickbeard import network_timezones
from sickbeard import sbdatetime from sickbeard import sbdatetime
from sickbeard.providers import newznab, rsstorrent from sickbeard.providers import newznab, rsstorrent
from sickbeard.common import Quality, Overview, statusStrings, qualityPresetStrings, cpu_presets from sickbeard.common import Quality, Overview, statusStrings, qualityPresetStrings, cpu_presets
from sickbeard.common import SNATCHED, UNAIRED, IGNORED, ARCHIVED, WANTED, FAILED from sickbeard.common import SNATCHED, UNAIRED, IGNORED, ARCHIVED, WANTED, FAILED
@ -56,9 +53,7 @@ from sickbeard.scene_numbering import get_scene_numbering, set_scene_numbering,
from lib.dateutil import tz from lib.dateutil import tz
from lib.unrar2 import RarFile from lib.unrar2 import RarFile
from lib import adba, subliminal from lib import adba, subliminal
from lib.trakt import TraktAPI from lib.trakt import TraktAPI
from lib.trakt.exceptions import traktException, traktAuthException, traktServerBusy from lib.trakt.exceptions import traktException, traktAuthException, traktServerBusy
@ -75,14 +70,12 @@ except ImportError:
from Cheetah.Template import Template from Cheetah.Template import Template
from tornado.routes import route from tornado.routes import route
from tornado.web import RequestHandler, HTTPError, authenticated, asynchronous, addslash from tornado.web import RequestHandler, HTTPError, authenticated, asynchronous
from tornado.gen import coroutine from tornado.gen import coroutine
from tornado.ioloop import IOLoop from tornado.ioloop import IOLoop
from tornado.concurrent import run_on_executor from tornado.concurrent import run_on_executor
from concurrent.futures import ThreadPoolExecutor from concurrent.futures import ThreadPoolExecutor
from bug_tracker import BugTracker
route_locks = {} route_locks = {}
class PageTemplate(Template): class PageTemplate(Template):
@ -135,6 +128,9 @@ class PageTemplate(Template):
class BaseHandler(RequestHandler): class BaseHandler(RequestHandler):
def __init__(self, *args, **kwargs):
super(BaseHandler, self).__init__(*args, **kwargs)
def write_error(self, status_code, **kwargs): def write_error(self, status_code, **kwargs):
# handle 404 http errors # handle 404 http errors
if status_code == 404: if status_code == 404:
@ -186,33 +182,24 @@ class WebHandler(BaseHandler):
@authenticated @authenticated
def get(self, route, *args, **kwargs): def get(self, route, *args, **kwargs):
try: try:
# route -> method obj
route = route.strip('/').replace('.', '_') or 'index' route = route.strip('/').replace('.', '_') or 'index'
# get route
#try:
method = getattr(self, route) method = getattr(self, route)
#except:
#try:
# subclasses = self.__class__.__subclasses__()
# method = [getattr(cls, route) for cls in subclasses if getattr(cls, route, None)][0]
#except:
# raise
# query params
params = self.request.arguments
for arg, value in params.items():
if len(value) == 1:
params[arg] = value[0]
# process request async # process request async
self.async_call(method, callback=self.async_done, **params) self.async_call(method, callback=self.async_done)
except: except:
logger.log('Failed doing webui request "%s": %s' % (route, traceback.format_exc()), logger.ERROR) logger.log('Failed doing webui request "%s": %s' % (route, traceback.format_exc()), logger.ERROR)
raise HTTPError(404) raise HTTPError(404)
@run_on_executor @run_on_executor
def async_call(self, function, callback=None, **kwargs): def async_call(self, function, callback=None):
try: try:
kwargs = self.request.arguments
for arg, value in kwargs.items():
if len(value) == 1:
kwargs[arg] = value[0]
result = function(**kwargs) result = function(**kwargs)
if callback: if callback:
callback(result) callback(result)
@ -236,7 +223,7 @@ class WebHandler(BaseHandler):
def _genericMessage(self, subject, message): def _genericMessage(self, subject, message):
t = PageTemplate(rh=self, file="genericMessage.tmpl") t = PageTemplate(rh=self, file="genericMessage.tmpl")
t.submenu = self.HomeMenu() t.submenu = Home().HomeMenu()
t.subject = subject t.subject = subject
t.message = message t.message = message
return t return t
@ -347,22 +334,15 @@ class WebRoot(WebHandler):
t = PageTemplate(rh=self, file="apiBuilder.tmpl") t = PageTemplate(rh=self, file="apiBuilder.tmpl")
def titler(x): def titler(x):
if not x or sickbeard.SORT_ARTICLE: return (helpers.remove_article(x), x)[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))) t.sortedShowList = sorted(sickbeard.showList, lambda x, y: cmp(titler(x.name), titler(y.name)))
myDB = db.DBConnection(row_type="dict")
seasonSQLResults = {} seasonSQLResults = {}
episodeSQLResults = {} episodeSQLResults = {}
myDB = db.DBConnection(row_type="dict")
for curShow in t.sortedShowList: for curShow in t.sortedShowList:
seasonSQLResults[curShow.indexerid] = myDB.select( seasonSQLResults[curShow.indexerid] = myDB.select(
"SELECT DISTINCT season FROM tv_episodes WHERE showid = ? ORDER BY season DESC", [curShow.indexerid]) "SELECT DISTINCT season FROM tv_episodes WHERE showid = ? ORDER BY season DESC", [curShow.indexerid])
@ -1117,15 +1097,7 @@ class Home(WebRoot):
epCounts[curEpCat] += 1 epCounts[curEpCat] += 1
def titler(x): def titler(x):
if not x or sickbeard.SORT_ARTICLE: return (helpers.remove_article(x), x)[not x or sickbeard.SORT_ARTICLE]
return x
if x.lower().startswith('a '):
x = x[2:]
if x.lower().startswith('an '):
x = x[3:]
elif x.lower().startswith('the '):
x = x[4:]
return x
if sickbeard.ANIME_SPLIT_HOME: if sickbeard.ANIME_SPLIT_HOME:
shows = [] shows = []
@ -3155,7 +3127,7 @@ class Manage(WebRoot):
if re.search('localhost', sickbeard.TORRENT_HOST): if re.search('localhost', sickbeard.TORRENT_HOST):
if not sickbeard.LOCALHOST_IP: if sickbeard.LOCALHOST_IP == '':
t.webui_url = re.sub('localhost', helpers.get_lan_ip(), sickbeard.TORRENT_HOST) t.webui_url = re.sub('localhost', helpers.get_lan_ip(), sickbeard.TORRENT_HOST)
else: else:
t.webui_url = re.sub('localhost', sickbeard.LOCALHOST_IP, sickbeard.TORRENT_HOST) t.webui_url = re.sub('localhost', sickbeard.LOCALHOST_IP, sickbeard.TORRENT_HOST)