mirror of
https://github.com/SickGear/SickGear.git
synced 2024-12-02 17:33:37 +00:00
Change refactor manual search processing.
Change reduce browser I/O on displayShow. Fix displayShow bug where click holding on a season btn and then dragging away leaves 50% white. Devel: Change sets and lists are assigned by reference, so snatched_eps are deep copied in base_info(). Change comment out BaseSearchQueueItem::copy() as deprecated for base_info(). Change improve ajax consumer to reduce polling. Simplify SimpleNamespace init in base_info(). Use base info instead of thread object for MANUAL_SEARCH_HISTORY in (ManualSearchQueueItem + FailedQueueItem) to streamline the finished search processing in webserve, this means add_dt has to be moved to BaseSearchQueueItem for base_info(). SimpleNameSpace Ref error is now in PYC, not sure if this is valid tho.
This commit is contained in:
parent
89905fc94d
commit
ac6d1f69d9
10 changed files with 319 additions and 276 deletions
|
@ -24,6 +24,10 @@
|
||||||
* Add search results sort by oldest aired
|
* Add search results sort by oldest aired
|
||||||
* Change requirements.txt Cheetah >= 3.1.0
|
* Change requirements.txt Cheetah >= 3.1.0
|
||||||
* Add Snowfl torrent provider
|
* Add Snowfl torrent provider
|
||||||
|
* Fix manual search button on displayShow and episode view page
|
||||||
|
* Change feedback result of manual search on the clicked button image/tooltip
|
||||||
|
* Change reduce browser I/O on displayShow
|
||||||
|
* Fix displayShow bug where click holding on a season btn and then dragging away leaves 50% white
|
||||||
|
|
||||||
|
|
||||||
[develop changelog]
|
[develop changelog]
|
||||||
|
|
|
@ -1060,6 +1060,7 @@ fieldset[disabled] .navbar-default .btn-link:focus{
|
||||||
outline:thin dotted #333;
|
outline:thin dotted #333;
|
||||||
outline:5px auto -webkit-focus-ring-color;
|
outline:5px auto -webkit-focus-ring-color;
|
||||||
outline-offset:-2px;
|
outline-offset:-2px;
|
||||||
|
background-position:0;
|
||||||
color:#ddd
|
color:#ddd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2130,6 +2130,19 @@ td.col-search{
|
||||||
width:46px
|
width:46px
|
||||||
}
|
}
|
||||||
|
|
||||||
|
td.col-search{
|
||||||
|
font-size:10px
|
||||||
|
}
|
||||||
|
|
||||||
|
.ep-search,
|
||||||
|
.ep-retry,
|
||||||
|
.ep-search img[src=""],
|
||||||
|
.ep-retry img[src=""]{
|
||||||
|
display:inline-block;
|
||||||
|
width:16px;
|
||||||
|
height:16px
|
||||||
|
}
|
||||||
|
|
||||||
#testRenameTable tbody td.col-checkbox,
|
#testRenameTable tbody td.col-checkbox,
|
||||||
#testRenameTable tbody td.col-ep{width:1%;vertical-align:middle}
|
#testRenameTable tbody td.col-ep{width:1%;vertical-align:middle}
|
||||||
#testRenameTable tbody td.col-name{
|
#testRenameTable tbody td.col-name{
|
||||||
|
|
|
@ -50,11 +50,11 @@
|
||||||
<script type="text/javascript" src="$sbRoot/js/lib/jquery.collapser.min.js?v=$sbPID"></script>
|
<script type="text/javascript" src="$sbRoot/js/lib/jquery.collapser.min.js?v=$sbPID"></script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.bfr{position:absolute;left:-999px;top:-999px}.bfr img{width:16px;height:16px}.spinner{display:inline-block;width:16px;height:16px;background:url(${sbRoot}/images/loading16${theme_suffix}.gif) no-repeat 0 0}
|
.bfr{position:absolute;left:-999px;top:-999px}.bfr img,img.spinner,img.queued,img.search{display:inline-block;width:16px;height:16px}img.spinner{background:url(${sbRoot}/images/loading16${theme_suffix}.gif) no-repeat 0 0}img.queued{background:url(${sbRoot}/images/queued.png) no-repeat 0 0}img.search{background:url(${sbRoot}/images/search16.png) no-repeat 0 0}
|
||||||
.images i{margin-right:6px;margin-top:5px}.hide{display:none}
|
.images i{margin-right:6px;margin-top:5px}.hide{display:none}
|
||||||
.tvshowImg {border:1px solid transparent;min-width:226px;min-hieght:332px}
|
.tvshowImg {border:1px solid transparent;min-width:226px;min-hieght:332px}
|
||||||
</style>
|
</style>
|
||||||
<div class="bfr"><img src="$sbRoot/images/loading16${theme_suffix}.gif" /></div>
|
<div class="bfr"><img src="$sbRoot/images/loading16${theme_suffix}.gif"><img src="$sbRoot/images/queued.png"><img src="$sbRoot/images/search16.png"><img src="$sbRoot/images/no16.png"><img src="$sbRoot/images/yes16.png"></div>
|
||||||
|
|
||||||
<div id="background-container">
|
<div id="background-container">
|
||||||
#if $has_art
|
#if $has_art
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#set $restart = 'Restart SickGear for new features on this page'
|
#set $restart = 'Restart SickGear for new features on this page'
|
||||||
#set $show_message = (None, $restart)[not $varExists('fanart')]
|
#set $show_message = (None, $restart)[not $varExists('fanart')]
|
||||||
#set global $page_body_attr = 'episode-view" class="' + $css
|
#set global $page_body_attr = 'episode-view" class="' + $css
|
||||||
|
#set theme_suffix = ('', '-dark')['dark' == $sg_str('THEME_NAME', 'dark')]
|
||||||
##
|
##
|
||||||
#import os.path
|
#import os.path
|
||||||
#include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_top.tmpl')
|
#include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_top.tmpl')
|
||||||
|
@ -176,7 +177,9 @@
|
||||||
.asc{border-top:0; border-bottom:8px solid}
|
.asc{border-top:0; border-bottom:8px solid}
|
||||||
.desc{border-top:8px solid; border-bottom:0}
|
.desc{border-top:8px solid; border-bottom:0}
|
||||||
#end if
|
#end if
|
||||||
|
.bfr{position:absolute;left:-999px;top:-999px}.bfr img,img.spinner,img.queued,img.search{display:inline-block;width:16px;height:16px}img.spinner{background:url(${sbRoot}/images/loading16${theme_suffix}.gif) no-repeat 0 0}img.queued{background:url(${sbRoot}/images/queued.png) no-repeat 0 0}img.search{background:url(${sbRoot}/images/search16.png) no-repeat 0 0}
|
||||||
</style>
|
</style>
|
||||||
|
<div class="bfr"><img src="$sbRoot/images/loading16${theme_suffix}.gif"><img src="$sbRoot/images/queued.png"><img src="$sbRoot/images/search16.png"><img src="$sbRoot/images/no16.png"><img src="$sbRoot/images/yes16.png"></div>
|
||||||
#if $show_message
|
#if $show_message
|
||||||
|
|
||||||
<div class="alert alert-info" style="margin:-40px 0 50px">
|
<div class="alert alert-info" style="margin:-40px 0 50px">
|
||||||
|
@ -293,9 +296,9 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
$(document).ready(function(){
|
$(document).ready(function(){
|
||||||
|
#end raw
|
||||||
sortList = [[$table_sort_header_codes[$sort], 0]];
|
var sortList = [[$table_sort_header_codes[$sort], 0]];
|
||||||
|
#raw
|
||||||
$('#showListTable:has(tbody tr)').tablesorter({
|
$('#showListTable:has(tbody tr)').tablesorter({
|
||||||
widgets: ['stickyHeaders'],
|
widgets: ['stickyHeaders'],
|
||||||
sortList: sortList,
|
sortList: sortList,
|
||||||
|
@ -381,9 +384,10 @@
|
||||||
#end if
|
#end if
|
||||||
#end if
|
#end if
|
||||||
|
|
||||||
#set $show_id = '%s_%sx%s' % (str($cur_result['showid']), str($cur_result['season']), str($cur_result['episode']))
|
#set $show_id = '%s_%sx%s' % ($cur_result['showid'], $cur_result['season'], $cur_result['episode'])
|
||||||
|
#set $id_sxe = '%s_%s' % ($cur_result['indexer'], $show_id)
|
||||||
<!-- start $cur_result['show_name'] //-->
|
<!-- start $cur_result['show_name'] //-->
|
||||||
<tr id="show-${show_id}" class="$show_div" data-rawname="$cur_result['show_name']">
|
<tr id="show-${show_id}" class="$show_div" data-rawname="$cur_result['show_name']" data-show-id="$id_sxe">
|
||||||
## forced to use a div to wrap airdate, the column sort went crazy with a span
|
## forced to use a div to wrap airdate, the column sort went crazy with a span
|
||||||
<td align="center" class="nowrap">
|
<td align="center" class="nowrap">
|
||||||
<div class="${fuzzydate}">$sbdatetime.sbdatetime.sbfdatetime($cur_result['localtime']).decode($sickbeard.SYS_ENCODING)</div><span class="sort-data">$cur_result['localtime'].strftime('%Y%m%d%H%M')</span>
|
<div class="${fuzzydate}">$sbdatetime.sbdatetime.sbfdatetime($cur_result['localtime']).decode($sickbeard.SYS_ENCODING)</div><span class="sort-data">$cur_result['localtime'].strftime('%Y%m%d%H%M')</span>
|
||||||
|
@ -428,7 +432,7 @@
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td align="center">
|
<td align="center">
|
||||||
<a href="$sbRoot/home/searchEpisode?show=${cur_result['showid']}&season=$cur_result['season']&episode=$cur_result['episode']" title="Manual Search" id="forceUpdate-${cur_result['showid']}" class="forceUpdate epSearch"><img alt="[search]" height="16" width="16" src="$sbRoot/images/search16.png" id="forceUpdateImage-${cur_result['showid']}" /></a>
|
<a class="ep-search" href="$sbRoot/home/episode_search?show=${cur_result['showid']}&season=$cur_result['season']&episode=$cur_result['episode']" title="Manual Search"><img title="[search]" alt="[search]" height="16" width="16" src="$sbRoot/images/search16.png" /></a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<!-- end $cur_result['show_name'] //-->
|
<!-- end $cur_result['show_name'] //-->
|
||||||
|
@ -455,7 +459,7 @@
|
||||||
<!--
|
<!--
|
||||||
#raw
|
#raw
|
||||||
$(document).ready(function(){
|
$(document).ready(function(){
|
||||||
$('#sbRoot').ajaxEpSearch({'size': 16, 'loadingImage': 'loading16' + themeSpinner + '.gif'});
|
$('#sbRoot').ajaxEpSearch();
|
||||||
$('.ep_summary').hide();
|
$('.ep_summary').hide();
|
||||||
$('.ep_summaryTrigger').click(function() {
|
$('.ep_summaryTrigger').click(function() {
|
||||||
$(this).next('.ep_summary').slideToggle('normal', function() {
|
$(this).next('.ep_summary').slideToggle('normal', function() {
|
||||||
|
@ -588,7 +592,8 @@
|
||||||
#end if
|
#end if
|
||||||
#slurp
|
#slurp
|
||||||
<!-- start $cur_result['show_name'] //-->
|
<!-- start $cur_result['show_name'] //-->
|
||||||
<div class="$show_div" id="listing-${cur_result['showid']}">
|
#set $id_sxe = '%s_%s_%sx%s' % ($cur_result['indexer'], $cur_result['showid'], $cur_result['season'], $cur_result['episode'])
|
||||||
|
<div class="$show_div" id="listing-${cur_result['showid']}" data-show-id="$id_sxe">
|
||||||
<div class="tvshowDiv">
|
<div class="tvshowDiv">
|
||||||
<table width="100%" border="0" cellpadding="0" cellspacing="0">
|
<table width="100%" border="0" cellpadding="0" cellspacing="0">
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -614,7 +619,7 @@
|
||||||
<a href="<%= anon_url(cur_result['imdb_url']) %>" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false" title="${cur_result['imdb_url']}"><img alt="[$sickbeard.indexerApi(INDEXER_IMDB).name]" height="16" width="16" src="$sbRoot/images/$sickbeard.indexerApi(INDEXER_IMDB).config.get('icon')" /></a>
|
<a href="<%= anon_url(cur_result['imdb_url']) %>" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false" title="${cur_result['imdb_url']}"><img alt="[$sickbeard.indexerApi(INDEXER_IMDB).name]" height="16" width="16" src="$sbRoot/images/$sickbeard.indexerApi(INDEXER_IMDB).config.get('icon')" /></a>
|
||||||
#end if
|
#end if
|
||||||
<a href="<%= anon_url(sickbeard.indexerApi(cur_indexer).config['show_url'] % cur_result['showid']) %>" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false" title="${sickbeard.indexerApi($cur_indexer).config['show_url'] % cur_result['showid']}"><img alt="$sickbeard.indexerApi($cur_indexer).name" height="16" width="16" src="$sbRoot/images/$sickbeard.indexerApi($cur_indexer).config['icon']" /></a>
|
<a href="<%= anon_url(sickbeard.indexerApi(cur_indexer).config['show_url'] % cur_result['showid']) %>" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false" title="${sickbeard.indexerApi($cur_indexer).config['show_url'] % cur_result['showid']}"><img alt="$sickbeard.indexerApi($cur_indexer).name" height="16" width="16" src="$sbRoot/images/$sickbeard.indexerApi($cur_indexer).config['icon']" /></a>
|
||||||
<span><a href="$sbRoot/home/searchEpisode?show=${cur_result['showid']}&season=$cur_result['season']&episode=$cur_result['episode']" title="Manual Search" id="forceUpdate-${cur_result['showid']}" class="epSearch forceUpdate"><img alt="[search]" height="16" width="16" src="$sbRoot/images/search16.png" id="forceUpdateImage-${cur_result['showid']}" /></a></span>
|
<span><a class="ep-search" href="$sbRoot/home/episode_search?show=${cur_result['showid']}&season=$cur_result['season']&episode=$cur_result['episode']" title="Manual Search"><img title="[search]" alt="[search]" height="16" width="16" src="$sbRoot/images/search16.png" /></a></span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -101,7 +101,7 @@
|
||||||
#slurp
|
#slurp
|
||||||
#set $curStatus, $curQuality = $Quality.splitCompositeStatus(int($ep['status']))
|
#set $curStatus, $curQuality = $Quality.splitCompositeStatus(int($ep['status']))
|
||||||
#if Quality.NONE != $curQuality
|
#if Quality.NONE != $curQuality
|
||||||
<td class="col-status">#if $SUBTITLED == $curStatus#<span class="addQTip" title="$statusStrings[$curStatus]"><i class="sgicon-subtitles" style="vertical-align:middle"></i></span>#else#$statusStrings[$curStatus].replace('Downloaded', '')#end if# <span class="quality $Quality.get_quality_css($curQuality)#if $downloaded# addQTip" title="$downloaded#end if#">$Quality.get_quality_ui($curQuality)</span></td>
|
<td class="col-status">#if $SUBTITLED == $curStatus#<span class="addQTip" title="$statusStrings[$curStatus]"><i class="sgicon-subtitles" style="vertical-align:middle"></i></span>#else#$statusStrings[$curStatus].replace('Downloaded', '')#end if# #if 'Unknown' != $statusStrings[$curStatus]#<span class="quality $Quality.get_quality_css($curQuality)#if $downloaded# addQTip" title="$downloaded#end if#">$Quality.get_quality_ui($curQuality)</span>#end if#</td>
|
||||||
#else
|
#else
|
||||||
<td class="col-status">$statusStrings[$curStatus].replace('SD DVD', 'SD DVD/BR/BD')</td>
|
<td class="col-status">$statusStrings[$curStatus].replace('SD DVD', 'SD DVD/BR/BD')</td>
|
||||||
#end if
|
#end if
|
||||||
|
@ -109,9 +109,9 @@
|
||||||
#if 0 != int($ep['season'])
|
#if 0 != int($ep['season'])
|
||||||
#set $status = $Quality.splitCompositeStatus(int($ep['status']))[0]
|
#set $status = $Quality.splitCompositeStatus(int($ep['status']))[0]
|
||||||
#if ($status in $SNATCHED_ANY + [$DOWNLOADED, $ARCHIVED]) and $sg_var('USE_FAILED_DOWNLOADS')
|
#if ($status in $SNATCHED_ANY + [$DOWNLOADED, $ARCHIVED]) and $sg_var('USE_FAILED_DOWNLOADS')
|
||||||
<a class="epRetry" id="$ep_str" name="$ep_str" href="$sbRoot/home/retryEpisode?show=$show.indexerid&season=$ep['season']&episode=$ep['episode']"><img src="$sbRoot/images/search16.png" height="16" alt="retry" title="Retry download"></a>
|
<a class="ep-retry" href="$sbRoot/home/episode_retry?show=$show.indexerid&season=$ep['season']&episode=$ep['episode']"><img src="$sbRoot/images/search16.png" height="16" alt="retry" title="Retry download"></a>
|
||||||
#else
|
#else
|
||||||
<a class="epSearch" id="$ep_str" name="$ep_str" href="$sbRoot/home/searchEpisode?show=$show.indexerid&season=$ep['season']&episode=$ep['episode']"><img src="$sbRoot/images/search16.png" width="16" height="16" alt="search" title="Manual search"></a>
|
<a class="ep-search" href="$sbRoot/home/episode_search?show=$show.indexerid&season=$ep['season']&episode=$ep['episode']"><img src="$sbRoot/images/search16.png" width="16" height="16" alt="search" title="Manual search"></a>
|
||||||
#end if
|
#end if
|
||||||
#end if
|
#end if
|
||||||
#slurp
|
#slurp
|
||||||
|
|
|
@ -1,194 +1,235 @@
|
||||||
var search_status_url = sbRoot + '/home/getManualSearchStatus';
|
/** @namespace $.SickGear.Root */
|
||||||
|
/** @namespace data.episodes */
|
||||||
|
/** @namespace ep.showindexer */
|
||||||
|
/** @namespace ep.showindexid */
|
||||||
|
/** @namespace ep.season */
|
||||||
|
/** @namespace ep.episode */
|
||||||
|
/** @namespace ep.searchstate */
|
||||||
|
/** @namespace ep.status */
|
||||||
|
/** @namespace ep.quality */
|
||||||
|
/** @namespace ep.retrystate */
|
||||||
|
/** @namespace ep.statusoverview */
|
||||||
|
|
||||||
|
var dev = !1,
|
||||||
|
logInfo = dev ? console.info.bind(window.console) : function() {},
|
||||||
|
logErr = dev ? console.error.bind(window.console) : function() {};
|
||||||
|
|
||||||
PNotify.prototype.options.maxonscreen = 5;
|
PNotify.prototype.options.maxonscreen = 5;
|
||||||
|
|
||||||
$.fn.manualSearches = [];
|
|
||||||
|
|
||||||
function check_manual_searches() {
|
|
||||||
var poll_interval = 5000;
|
|
||||||
$.ajax({
|
|
||||||
url: search_status_url + '?show=' + $('#showID').val(),
|
|
||||||
success: function (data) {
|
|
||||||
if (data.episodes) {
|
|
||||||
poll_interval = 5000;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
poll_interval = 15000;
|
|
||||||
}
|
|
||||||
|
|
||||||
updateImages(data);
|
|
||||||
//cleanupManualSearches(data);
|
|
||||||
},
|
|
||||||
error: function () {
|
|
||||||
poll_interval = 30000;
|
|
||||||
},
|
|
||||||
type: "GET",
|
|
||||||
dataType: "json",
|
|
||||||
complete: function () {
|
|
||||||
setTimeout(check_manual_searches, poll_interval);
|
|
||||||
},
|
|
||||||
timeout: 15000 // timeout every 15 secs
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function updateImages(data) {
|
|
||||||
$.each(data.episodes, function (name, ep) {
|
|
||||||
console.debug(ep.searchstatus);
|
|
||||||
// Get td element for current ep
|
|
||||||
var loadingImage = 'loading16.gif';
|
|
||||||
var queuedImage = 'queued.png';
|
|
||||||
var searchImage = 'search16.png';
|
|
||||||
var status = null;
|
|
||||||
//Try to get the <a> Element
|
|
||||||
el=$('a[id=' + ep.season + 'x' + ep.episode+']');
|
|
||||||
img=el.children('img');
|
|
||||||
parent=el.parent();
|
|
||||||
if (el) {
|
|
||||||
if (ep.searchstatus == 'searching') {
|
|
||||||
//el=$('td#' + ep.season + 'x' + ep.episode + '.search img');
|
|
||||||
img.attr('title','Searching');
|
|
||||||
img.prop('alt','searching');
|
|
||||||
img.attr('src',sbRoot+'/images/' + loadingImage);
|
|
||||||
disableLink(el);
|
|
||||||
// Update Status and Quality
|
|
||||||
var rSearchTerm = /(\w+)\s\((.+?)\)/;
|
|
||||||
HtmlContent = ep.searchstatus;
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (ep.searchstatus == 'queued') {
|
|
||||||
//el=$('td#' + ep.season + 'x' + ep.episode + '.search img');
|
|
||||||
img.attr('title','Queued');
|
|
||||||
img.prop('alt','queued');
|
|
||||||
img.attr('src',sbRoot+'/images/' + queuedImage );
|
|
||||||
disableLink(el);
|
|
||||||
HtmlContent = ep.searchstatus;
|
|
||||||
}
|
|
||||||
else if (ep.searchstatus == 'finished') {
|
|
||||||
//el=$('td#' + ep.season + 'x' + ep.episode + '.search img');
|
|
||||||
var imgParent = img.parent();
|
|
||||||
if (ep.retrystatus) {
|
|
||||||
imgParent.attr('class','epRetry');
|
|
||||||
imgParent.attr('href', imgParent.attr('href').replace('/home/searchEpisode?', '/home/retryEpisode?'));
|
|
||||||
img.attr('title','Retry download');
|
|
||||||
img.prop('alt', 'retry download');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
imgParent.attr('class','epSearch');
|
|
||||||
imgParent.attr('href', imgParent.attr('href').replace('/home/retryEpisode?', '/home/searchEpisode?'));
|
|
||||||
img.attr('title','Manual search');
|
|
||||||
img.prop('alt', 'manual search');
|
|
||||||
}
|
|
||||||
img.attr('src',sbRoot+'/images/' + searchImage);
|
|
||||||
enableLink(el);
|
|
||||||
|
|
||||||
// Update Status and Quality
|
|
||||||
parent.closest('tr').removeClass('skipped wanted qual good unaired snatched').addClass(ep.statusoverview);
|
|
||||||
var rSearchTerm = /(\w+)\s\((.+?)\)/;
|
|
||||||
HtmlContent = ep.status.replace(rSearchTerm,"$1"+' <span class="quality '+ep.quality+'">'+"$2"+'</span>');
|
|
||||||
|
|
||||||
}
|
|
||||||
// update the status column if it exists
|
|
||||||
parent.siblings('.col-status').html(HtmlContent)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
|
|
||||||
check_manual_searches();
|
ajaxConsumer.checkManualSearches();
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function enableLink(el) {
|
var ajaxConsumer = function () {
|
||||||
el.on('click.disabled', false);
|
var that = this;
|
||||||
el.attr('enableClick', '1');
|
that.timeoutId = 0;
|
||||||
el.fadeTo("fast", 1)
|
that.pollInterval = 0;
|
||||||
|
logInfo('init ajaxConsumer');
|
||||||
|
|
||||||
|
return {
|
||||||
|
checkManualSearches : function () {
|
||||||
|
logInfo('ajaxConsumer.checkManualSearches()');
|
||||||
|
var showId = $('#showID').val();
|
||||||
|
$.getJSON({
|
||||||
|
url: $.SickGear.Root + '/home/search_q_progress' + (/undefined/i.test(showId) ? '' : '?show=' + showId),
|
||||||
|
timeout: 15000 // timeout request after 15 secs
|
||||||
|
})
|
||||||
|
.done(function (data) {
|
||||||
|
logInfo('search_q_progress.success(data)', data);
|
||||||
|
if (!data.episodes || 0 === data.episodes.length) {
|
||||||
|
imgRestore();
|
||||||
|
}
|
||||||
|
// using 5s as a reasonable max. when updating images from historical statuses after a page refresh
|
||||||
|
that.pollInterval = data.episodes && data.episodes.length
|
||||||
|
? (uiUpdateComplete(data) ? 5000 : 1000) : 10000; // 10000/0
|
||||||
|
})
|
||||||
|
.fail(function () {
|
||||||
|
logErr('search_q_progress.error()');
|
||||||
|
that.pollInterval = 30000;
|
||||||
|
})
|
||||||
|
.always(function (jqXHR, textStatus) {
|
||||||
|
logInfo('search_q_progress.complete(textStatus)', '\'' + textStatus + '\'.');
|
||||||
|
clearTimeout(that.timeoutId);
|
||||||
|
if (that.pollInterval)
|
||||||
|
that.timeoutId = setTimeout(ajaxConsumer.checkManualSearches, that.pollInterval);
|
||||||
|
logInfo(that.pollInterval ? '^-- ' + that.pollInterval/1000 + 's to next work' : '^-- no more work');
|
||||||
|
logInfo('====');
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}();
|
||||||
|
|
||||||
|
function uiUpdateComplete(data) {
|
||||||
|
var isFinished = !0;
|
||||||
|
$.each(data.episodes, function (name, ep) {
|
||||||
|
|
||||||
|
var sxe = ep.season + 'x' + ep.episode,
|
||||||
|
displayShow$ = $('#' + sxe).closest('tr'),
|
||||||
|
episodeView$ = $('[data-show-id="' + ep.showindexer + '_' + ep.showindexid + '_' + sxe + '"]'),
|
||||||
|
link$ = (displayShow$.length ? displayShow$ : episodeView$).find('.ep-search, .ep-retry'),
|
||||||
|
uiOptions = $.ajaxEpSearch.defaults;
|
||||||
|
|
||||||
|
logInfo('^-- data item', name, ep.searchstate, ep.showindexid, sxe, ep.statusoverview);
|
||||||
|
|
||||||
|
if (link$.length) {
|
||||||
|
var htmlContent = '', imgTip, imgCls;
|
||||||
|
|
||||||
|
switch (ep.searchstate) {
|
||||||
|
case 'searching':
|
||||||
|
isFinished = !1;
|
||||||
|
imgUpdate(link$, 'Searching', uiOptions.loadingImage);
|
||||||
|
disableLink(link$);
|
||||||
|
htmlContent = '[' + ep.searchstate + ']';
|
||||||
|
break;
|
||||||
|
case 'queued':
|
||||||
|
isFinished = !1;
|
||||||
|
imgUpdate(link$, 'Queued', uiOptions.queuedImage);
|
||||||
|
disableLink(link$);
|
||||||
|
htmlContent = '[' + ep.searchstate + ']';
|
||||||
|
break;
|
||||||
|
case 'finished':
|
||||||
|
var attrName = !!getAttr(link$, 'href') ? 'href' : 'data-href', href = getAttr(link$, attrName);
|
||||||
|
if (ep.retrystate) {
|
||||||
|
imgTip = 'Click to retry download';
|
||||||
|
link$.attr('class', 'ep-retry').attr(attrName, href.replace('search', 'retry'));
|
||||||
|
} else {
|
||||||
|
imgTip = 'Click for manual search';
|
||||||
|
link$.attr('class', 'ep-search').attr(attrName, href.replace('retry', 'search'));
|
||||||
|
}
|
||||||
|
if (/good/i.test(ep.statusoverview)) {
|
||||||
|
imgCls = uiOptions.searchImage;
|
||||||
|
} else if (/snatched/i.test(ep.statusoverview)) {
|
||||||
|
imgCls = uiOptions.imgYes;
|
||||||
|
} else {
|
||||||
|
imgTip = 'Last manual search failed. Click to try again';
|
||||||
|
imgCls = uiOptions.imgNo;
|
||||||
|
}
|
||||||
|
imgUpdate(link$, imgTip, imgCls);
|
||||||
|
enableLink(link$);
|
||||||
|
|
||||||
|
// update row status
|
||||||
|
if (ep.statusoverview) {
|
||||||
|
link$.closest('tr')
|
||||||
|
.removeClass('skipped wanted qual good unaired snatched')
|
||||||
|
.addClass(ep.statusoverview);
|
||||||
|
}
|
||||||
|
// update quality text for status column
|
||||||
|
var rSearchTerm = /(\w+)\s\((.+?)\)/;
|
||||||
|
htmlContent = ep.status.replace(rSearchTerm,
|
||||||
|
'$1' + ' <span class="quality ' + ep.quality + '">' + '$2' + '</span>');
|
||||||
|
|
||||||
|
// remove backed vars
|
||||||
|
link$.removeAttr('data-status data-imgclass');
|
||||||
|
}
|
||||||
|
|
||||||
|
// update the status area
|
||||||
|
link$.closest('.col-search').siblings('.col-status').html(htmlContent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return isFinished;
|
||||||
}
|
}
|
||||||
|
|
||||||
function disableLink(el) {
|
function enableLink(el$) {
|
||||||
el.off('click.disabled');
|
el$.attr('href', el$.attr('data-href')).removeAttr('data-href').fadeTo('fast', 1);
|
||||||
el.attr('enableClick', '0');
|
|
||||||
el.fadeTo("fast", .5)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
(function(){
|
function disableLink(el$) {
|
||||||
|
el$.attr('data-href', el$.attr('href')).removeAttr('href').fadeTo('fast', .7);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAttr(el$, name) {
|
||||||
|
return el$.is('[' + name + ']') ? el$.attr(name) : !1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function imgUpdate(link$, tip, cls) {
|
||||||
|
link$.find('img').attr('src', '').attr('title', tip).prop('alt', '')
|
||||||
|
.removeClass('spinner queued search no yes').addClass(cls);
|
||||||
|
}
|
||||||
|
|
||||||
|
function imgRestore() {
|
||||||
|
$('a[data-status]').each(function() {
|
||||||
|
$(this).closest('.col-search').siblings('.col-status').html($(this).attr('data-status'));
|
||||||
|
imgUpdate($(this),
|
||||||
|
getAttr($(this), 'data-imgtitle'),
|
||||||
|
getAttr($(this), 'data-imgclass') || $.ajaxEpSearch.defaults.searchImage);
|
||||||
|
$(this).removeAttr('data-status data-imgclass data-imgtitle');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
|
||||||
$.ajaxEpSearch = {
|
$.ajaxEpSearch = {
|
||||||
defaults: {
|
defaults: {
|
||||||
size: 16,
|
size: 16,
|
||||||
colorRow: false,
|
colorRow: !1,
|
||||||
loadingImage: 'loading16.gif',
|
loadingImage: 'spinner',
|
||||||
queuedImage: 'queued.png',
|
queuedImage: 'queued',
|
||||||
noImage: 'no16.png',
|
searchImage: 'search',
|
||||||
yesImage: 'yes16.png'
|
imgNo: 'no',
|
||||||
|
imgYes: 'yes'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
$.fn.ajaxEpSearch = function(options){
|
$.fn.ajaxEpSearch = function(uiOptions) {
|
||||||
options = $.extend({}, $.ajaxEpSearch.defaults, options);
|
uiOptions = $.extend( {}, $.ajaxEpSearch.defaults, uiOptions);
|
||||||
|
|
||||||
$('.epSearch, .epRetry').click(function(event){
|
$('.ep-search, .ep-retry').on('click', function(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
logInfo(($(this).hasClass('ep-search') ? 'Search' : 'Retry') + ' clicked');
|
||||||
|
|
||||||
// Check if we have disabled the click
|
// check if we have disabled the click
|
||||||
if ( $(this).attr('enableClick') == '0' ) {
|
if (!!getAttr($(this), 'data-href')) {
|
||||||
console.debug("Already queued, not downloading!");
|
logInfo('Already queued, not downloading!');
|
||||||
return false;
|
return !1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( $(this).attr('class') == "epRetry" ) {
|
if ($(this).hasClass('ep-retry')
|
||||||
if ( !confirm("Mark download as bad and retry?") )
|
&& !confirm('Mark download as bad and retry?')) {
|
||||||
return false;
|
return !1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var link$ = $(this), img$ = link$.find('img'), img = ['Failed', uiOptions.imgNo], imgCls;
|
||||||
|
// backup ui vars
|
||||||
|
if (link$.closest('.col-search') && link$.closest('.col-search').siblings('.col-status')) {
|
||||||
|
link$.attr('data-status', link$.closest('.col-search').siblings('.col-status').html().trim());
|
||||||
|
}
|
||||||
|
link$.attr('data-imgtitle', getAttr(img$, 'title'));
|
||||||
|
if (imgCls = getAttr(img$, 'class')) {
|
||||||
|
link$.attr('data-imgclass', imgCls.trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
imgUpdate(link$, 'Loading', uiOptions.loadingImage);
|
||||||
|
|
||||||
|
$.getJSON({url: $(this).attr('href'), timeout: 15000})
|
||||||
|
.done(function(data) {
|
||||||
|
logInfo('getJSON() data...', data);
|
||||||
|
|
||||||
|
// if failed, replace success/queued with initiated red X/No
|
||||||
|
if ('failure' !== data.result) {
|
||||||
|
// otherwise, queued successfully
|
||||||
|
|
||||||
|
// update ui status
|
||||||
|
link$.closest('.col-search').siblings('.col-status').html('[' + data.result + ']');
|
||||||
|
|
||||||
|
// prevent further interaction
|
||||||
|
disableLink(link$);
|
||||||
|
|
||||||
|
img = 'queueing' === data.result
|
||||||
|
? ['Queueing', uiOptions.queuedImage]
|
||||||
|
: ['Searching', uiOptions.loadingImage];
|
||||||
|
}
|
||||||
|
|
||||||
|
// update ui image
|
||||||
|
imgUpdate(link$, img[0], img[1]);
|
||||||
|
ajaxConsumer.checkManualSearches();
|
||||||
|
})
|
||||||
|
.fail(function() { imgRestore(); });
|
||||||
|
|
||||||
|
// prevent following the clicked link
|
||||||
|
return !1;
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
var parent = $(this).parent();
|
|
||||||
|
|
||||||
// Create var for anchor
|
|
||||||
link = $(this);
|
|
||||||
|
|
||||||
// Create var for img under anchor and set options for the loading gif
|
|
||||||
img=$(this).children('img');
|
|
||||||
img.attr('title','loading');
|
|
||||||
img.prop('alt','');
|
|
||||||
img.attr('src',sbRoot+'/images/' + options.loadingImage);
|
|
||||||
|
|
||||||
|
|
||||||
$.getJSON($(this).attr('href'), function(data){
|
|
||||||
|
|
||||||
// if they failed then just put the red X
|
|
||||||
if (data.result == 'failure') {
|
|
||||||
img_name = options.noImage;
|
|
||||||
img_result = 'failed';
|
|
||||||
|
|
||||||
// if the snatch was successful then apply the corresponding class and fill in the row appropriately
|
|
||||||
} else {
|
|
||||||
img_name = options.loadingImage;
|
|
||||||
img_result = 'success';
|
|
||||||
// color the row
|
|
||||||
if (options.colorRow)
|
|
||||||
parent.parent().removeClass('skipped wanted qual good unaired').addClass('snatched');
|
|
||||||
// applying the quality class
|
|
||||||
var rSearchTerm = /(\w+)\s\((.+?)\)/;
|
|
||||||
HtmlContent = data.result.replace(rSearchTerm,"$1"+' <span class="quality '+data.quality+'">'+"$2"+'</span>');
|
|
||||||
// update the status column if it exists
|
|
||||||
parent.siblings('.col-status').html(HtmlContent)
|
|
||||||
// Only if the queing was succesfull, disable the onClick event of the loading image
|
|
||||||
disableLink(link);
|
|
||||||
}
|
|
||||||
|
|
||||||
// put the corresponding image as the result of queuing of the manual search
|
|
||||||
img.attr('title',img_result);
|
|
||||||
img.prop('alt',img_result);
|
|
||||||
img.attr('height', options.size);
|
|
||||||
img.attr('src',sbRoot+"/images/"+img_name);
|
|
||||||
});
|
|
||||||
//
|
|
||||||
|
|
||||||
// don't follow the link
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
|
|
@ -173,7 +173,7 @@ $(document).ready(function() {
|
||||||
qTips($('.addQTip'));
|
qTips($('.addQTip'));
|
||||||
|
|
||||||
function table_init(table$) {
|
function table_init(table$) {
|
||||||
$('#sbRoot').ajaxEpSearch({'colorRow': true});
|
$('#sbRoot').ajaxEpSearch();
|
||||||
$('#sbRoot').ajaxEpSubtitlesSearch();
|
$('#sbRoot').ajaxEpSubtitlesSearch();
|
||||||
|
|
||||||
if ($.SickGear.config.useFuzzy) {
|
if ($.SickGear.config.useFuzzy) {
|
||||||
|
|
|
@ -22,6 +22,7 @@ import traceback
|
||||||
import threading
|
import threading
|
||||||
import datetime
|
import datetime
|
||||||
import re
|
import re
|
||||||
|
import copy
|
||||||
|
|
||||||
import sickbeard
|
import sickbeard
|
||||||
from sickbeard import db, logger, common, exceptions, helpers, network_timezones, generic_queue, search, \
|
from sickbeard import db, logger, common, exceptions, helpers, network_timezones, generic_queue, search, \
|
||||||
|
@ -91,7 +92,7 @@ class SearchQueue(generic_queue.GenericQueue):
|
||||||
|
|
||||||
def get_queued_manual(self, show):
|
def get_queued_manual(self, show):
|
||||||
"""
|
"""
|
||||||
Returns None or List of copies of all show related items in manual or failed queue
|
Returns None or List of base info items of all show related items in manual or failed queue
|
||||||
:param show: show indexerid or None for all q items
|
:param show: show indexerid or None for all q items
|
||||||
:type show: String or None
|
:type show: String or None
|
||||||
:return: List with 0 or more items
|
:return: List with 0 or more items
|
||||||
|
@ -107,10 +108,10 @@ class SearchQueue(generic_queue.GenericQueue):
|
||||||
|
|
||||||
def get_current_manual_item(self, show):
|
def get_current_manual_item(self, show):
|
||||||
"""
|
"""
|
||||||
Returns a static copy of the currently active manual search item
|
Returns a base info item of the currently active manual search item
|
||||||
:param show: show indexerid or None for all q items
|
:param show: show indexerid or None for all q items
|
||||||
:type show: String or None
|
:type show: String or None
|
||||||
:return: copy of ManualSearchQueueItem or FailedQueueItem or None
|
:return: base info item of ManualSearchQueueItem or FailedQueueItem or None
|
||||||
"""
|
"""
|
||||||
with self.lock:
|
with self.lock:
|
||||||
if self.currentItem and isinstance(self.currentItem, (ManualSearchQueueItem, FailedQueueItem)) \
|
if self.currentItem and isinstance(self.currentItem, (ManualSearchQueueItem, FailedQueueItem)) \
|
||||||
|
@ -412,46 +413,38 @@ class BaseSearchQueueItem(generic_queue.QueueItem):
|
||||||
super(BaseSearchQueueItem, self).__init__(name, action_id)
|
super(BaseSearchQueueItem, self).__init__(name, action_id)
|
||||||
self.segment = segment
|
self.segment = segment
|
||||||
self.show = show
|
self.show = show
|
||||||
|
self.added_dt = None
|
||||||
self.success = None
|
self.success = None
|
||||||
self.snatched_eps = set([])
|
self.snatched_eps = set([])
|
||||||
|
|
||||||
def base_info(self):
|
def base_info(self):
|
||||||
o = SimpleNamespace()
|
return SimpleNamespace(
|
||||||
o.success = self.success
|
success=self.success,
|
||||||
o.show = SimpleNamespace()
|
added_dt=self.added_dt,
|
||||||
o.show.indexer = self.show.indexer
|
snatched_eps=copy.deepcopy(self.snatched_eps),
|
||||||
o.show.indexerid = self.show.indexerid
|
show=SimpleNamespace(
|
||||||
o.show.quality = self.show.quality
|
indexer=self.show.indexer, indexerid=self.show.indexerid,
|
||||||
o.show.upgrade_once = self.show.upgrade_once
|
quality=self.show.quality, upgrade_once=self.show.upgrade_once),
|
||||||
sl = []
|
segment=[SimpleNamespace(
|
||||||
for s in ([self.segment], self.segment)[isinstance(self.segment, list)]:
|
season=s.season, episode=s.episode, status=s.status,
|
||||||
eo = SimpleNamespace()
|
show=SimpleNamespace(
|
||||||
eo.episode = s.episode
|
indexer=s.show.indexer, indexerid=s.show.indexerid,
|
||||||
eo.season = s.season
|
quality=s.show.quality, upgrade_once=s.show.upgrade_once
|
||||||
eo.status = s.status
|
)) for s in ([self.segment], self.segment)[isinstance(self.segment, list)]])
|
||||||
eo.show = SimpleNamespace()
|
|
||||||
eo.show.indexer = s.show.indexer
|
|
||||||
eo.show.indexerid = s.show.indexerid
|
|
||||||
eo.show.quality = s.show.quality
|
|
||||||
eo.show.upgrade_once = s.show.upgrade_once
|
|
||||||
sl.append(eo)
|
|
||||||
o.segment = sl
|
|
||||||
|
|
||||||
return o
|
# def copy(self, deepcopy_obj=None):
|
||||||
|
# if not isinstance(deepcopy_obj, list):
|
||||||
def copy(self, deepcopy_obj=None):
|
# deepcopy_obj = []
|
||||||
if not isinstance(deepcopy_obj, list):
|
# deepcopy_obj += ['segment']
|
||||||
deepcopy_obj = []
|
# same_show = True
|
||||||
deepcopy_obj += ['segment']
|
# if (isinstance(self.segment, list) and getattr(self.segment[0], 'show') is not self.show) \
|
||||||
same_show = True
|
# or getattr(self.segment, 'show') is not self.show:
|
||||||
if (isinstance(self.segment, list) and getattr(self.segment[0], 'show') is not self.show) \
|
# same_show = False
|
||||||
or getattr(self.segment, 'show') is not self.show:
|
# deepcopy_obj += ['show']
|
||||||
same_show = False
|
# n_o = super(BaseSearchQueueItem, self).copy(deepcopy_obj)
|
||||||
deepcopy_obj += ['show']
|
# if same_show:
|
||||||
n_o = super(BaseSearchQueueItem, self).copy(deepcopy_obj)
|
# n_o.show = (getattr(n_o.segment, 'show'), getattr(n_o.segment[0], 'show'))[isinstance(n_o.segment, list)]
|
||||||
if same_show:
|
# return n_o
|
||||||
n_o.show = (getattr(n_o.segment, 'show'), getattr(n_o.segment[0], 'show'))[isinstance(n_o.segment, list)]
|
|
||||||
return n_o
|
|
||||||
|
|
||||||
|
|
||||||
class ManualSearchQueueItem(BaseSearchQueueItem):
|
class ManualSearchQueueItem(BaseSearchQueueItem):
|
||||||
|
@ -460,7 +453,6 @@ class ManualSearchQueueItem(BaseSearchQueueItem):
|
||||||
self.priority = generic_queue.QueuePriorities.HIGH
|
self.priority = generic_queue.QueuePriorities.HIGH
|
||||||
self.name = 'MANUAL-%s' % show.indexerid
|
self.name = 'MANUAL-%s' % show.indexerid
|
||||||
self.started = None
|
self.started = None
|
||||||
self.added_dt = None
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
generic_queue.QueueItem.run(self)
|
generic_queue.QueueItem.run(self)
|
||||||
|
@ -494,7 +486,7 @@ class ManualSearchQueueItem(BaseSearchQueueItem):
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
# Keep a list with the last executed searches
|
# Keep a list with the last executed searches
|
||||||
fifo(MANUAL_SEARCH_HISTORY, self)
|
fifo(MANUAL_SEARCH_HISTORY, self.base_info())
|
||||||
|
|
||||||
if self.success is None:
|
if self.success is None:
|
||||||
self.success = False
|
self.success = False
|
||||||
|
@ -554,7 +546,6 @@ class FailedQueueItem(BaseSearchQueueItem):
|
||||||
self.priority = generic_queue.QueuePriorities.HIGH
|
self.priority = generic_queue.QueuePriorities.HIGH
|
||||||
self.name = 'RETRY-%s' % show.indexerid
|
self.name = 'RETRY-%s' % show.indexerid
|
||||||
self.started = None
|
self.started = None
|
||||||
self.added_dt = None
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
generic_queue.QueueItem.run(self)
|
generic_queue.QueueItem.run(self)
|
||||||
|
@ -596,7 +587,7 @@ class FailedQueueItem(BaseSearchQueueItem):
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
# Keep a list with the last executed searches
|
# Keep a list with the last executed searches
|
||||||
fifo(MANUAL_SEARCH_HISTORY, self)
|
fifo(MANUAL_SEARCH_HISTORY, self.base_info())
|
||||||
|
|
||||||
if self.success is None:
|
if self.success is None:
|
||||||
self.success = False
|
self.success = False
|
||||||
|
|
|
@ -2797,69 +2797,57 @@ class Home(MainHandler):
|
||||||
seen_eps = set([])
|
seen_eps = set([])
|
||||||
|
|
||||||
# Queued searches
|
# Queued searches
|
||||||
queued_items = sickbeard.searchQueueScheduler.action.get_queued_manual(show)
|
queued = sickbeard.searchQueueScheduler.action.get_queued_manual(show)
|
||||||
|
|
||||||
# Active search
|
# Active search
|
||||||
active_item = sickbeard.searchQueueScheduler.action.get_current_manual_item(show)
|
active = sickbeard.searchQueueScheduler.action.get_current_manual_item(show)
|
||||||
|
|
||||||
# Finished searches
|
# Finished searches
|
||||||
sickbeard.search_queue.remove_old_fifo(sickbeard.search_queue.MANUAL_SEARCH_HISTORY)
|
sickbeard.search_queue.remove_old_fifo(sickbeard.search_queue.MANUAL_SEARCH_HISTORY)
|
||||||
finished_items = sickbeard.search_queue.MANUAL_SEARCH_HISTORY
|
results = sickbeard.search_queue.MANUAL_SEARCH_HISTORY
|
||||||
|
|
||||||
progress = 'queued'
|
for item in filter(lambda q: hasattr(q, 'segment'), queued):
|
||||||
for thread in queued_items:
|
for ep_base in item.segment:
|
||||||
if hasattr(thread, 'segment'):
|
ep, uniq_sxe = self.prepare_episode(ep_base, 'queued')
|
||||||
for ep_obj in thread.segment:
|
|
||||||
ep, uniq_sxe = self.prepare_episode(ep_obj.show, ep_obj, progress)
|
|
||||||
episodes.append(ep)
|
episodes.append(ep)
|
||||||
seen_eps.add(uniq_sxe)
|
seen_eps.add(uniq_sxe)
|
||||||
|
|
||||||
if active_item:
|
if active and hasattr(active, 'segment'):
|
||||||
thread = active_item
|
|
||||||
episode_params = dict(([('searchstate', 'finished'), ('statusoverview', True)],
|
episode_params = dict(([('searchstate', 'finished'), ('statusoverview', True)],
|
||||||
[('searchstate', 'searching'), ('statusoverview', False)])[None is thread.success],
|
[('searchstate', 'searching'), ('statusoverview', False)])[None is active.success],
|
||||||
retrystate=True)
|
retrystate=True)
|
||||||
if hasattr(thread, 'segment'):
|
for ep_base in active.segment:
|
||||||
for ep_obj in thread.segment:
|
ep, uniq_sxe = self.prepare_episode(ep_base, **episode_params)
|
||||||
ep, uniq_sxe = self.prepare_episode(ep_obj.show, ep_obj, **episode_params)
|
|
||||||
episodes.append(ep)
|
episodes.append(ep)
|
||||||
seen_eps.add(uniq_sxe)
|
seen_eps.add(uniq_sxe)
|
||||||
|
|
||||||
episode_params = dict(searchstate='finished', retrystate=True, statusoverview=True)
|
episode_params = dict(searchstate='finished', retrystate=True, statusoverview=True)
|
||||||
for thread in finished_items:
|
for item in filter(lambda r: hasattr(r, 'segment') and (not show or show == str(r.show.indexerid)), results):
|
||||||
if not isinstance(getattr(thread, 'segment'), list):
|
for ep_base in filter(
|
||||||
if (not show or show == str(thread.show.indexerid)) and \
|
lambda e: (e.show.indexer, e.show.indexerid, e.season, e.episode) not in seen_eps, item.segment):
|
||||||
(thread.show.indexer, thread.show.indexerid, thread.segment.season, thread.segment.episode) \
|
ep, uniq_sxe = self.prepare_episode(ep_base, **episode_params)
|
||||||
not in seen_eps:
|
|
||||||
ep, uniq_sxe = self.prepare_episode(thread.show, thread.segment, **episode_params)
|
|
||||||
episodes.append(ep)
|
episodes.append(ep)
|
||||||
seen_eps.add(uniq_sxe)
|
seen_eps.add(uniq_sxe)
|
||||||
|
|
||||||
# These are only Failed Downloads/Retry SearchThreadItems.. lets loop through the segment/episodes
|
for snatched in filter(lambda s: (s not in seen_eps), item.snatched_eps):
|
||||||
elif hasattr(thread, 'segment') and show == str(thread.show.indexerid):
|
try:
|
||||||
for ep_obj in thread.segment:
|
show = helpers.find_show_by_id(sickbeard.showList, dict({snatched[0]: snatched[1]}))
|
||||||
if (ep_obj.show.indexer, ep_obj.show.indexerid, ep_obj.season, ep_obj.episode) not in seen_eps:
|
ep_obj = show.getEpisode(season=snatched[2], episode=snatched[3])
|
||||||
ep, uniq_sxe = self.prepare_episode(ep_obj.show, ep_obj, **episode_params)
|
except (StandardError, Exception):
|
||||||
episodes.append(ep)
|
continue
|
||||||
seen_eps.add(uniq_sxe)
|
ep, uniq_sxe = self.prepare_episode(ep_obj, **episode_params)
|
||||||
|
|
||||||
for snatched in filter(lambda v: v not in seen_eps, thread.snatched_eps):
|
|
||||||
ep_obj = thread.show.getEpisode(season=snatched[2], episode=snatched[3])
|
|
||||||
ep, uniq_sxe = self.prepare_episode(thread.show, ep_obj, **episode_params)
|
|
||||||
episodes.append(ep)
|
episodes.append(ep)
|
||||||
seen_eps.add(uniq_sxe)
|
seen_eps.add(uniq_sxe)
|
||||||
|
|
||||||
return json.dumps(dict(episodes=episodes))
|
return json.dumps(dict(episodes=episodes))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def prepare_episode(show, ep, searchstate, retrystate=False, statusoverview=False):
|
def prepare_episode(ep, searchstate, retrystate=False, statusoverview=False):
|
||||||
"""
|
"""
|
||||||
Prepare episode data and its unique id
|
Prepare episode data and its unique id
|
||||||
|
|
||||||
:param show: Show object
|
:param ep: Episode structure containing the show that it relates to
|
||||||
:type show: TVShow object
|
:type ep: TVEpisode object or Episode Base Namespace
|
||||||
:param ep: Episode object
|
|
||||||
:type ep: TVEpisode object
|
|
||||||
:param searchstate: Progress of search
|
:param searchstate: Progress of search
|
||||||
:type searchstate: string
|
:type searchstate: string
|
||||||
:param retrystate: True to add retrystate to data
|
:param retrystate: True to add retrystate to data
|
||||||
|
@ -2877,7 +2865,7 @@ class Home(MainHandler):
|
||||||
quality_class = qualityPresetStrings[x]
|
quality_class = qualityPresetStrings[x]
|
||||||
break
|
break
|
||||||
|
|
||||||
ep_data = dict(showindexer=show.indexer, showindexid=show.indexerid,
|
ep_data = dict(showindexer=ep.show.indexer, showindexid=ep.show.indexerid,
|
||||||
season=ep.season, episode=ep.episode, quality=quality_class,
|
season=ep.season, episode=ep.episode, quality=quality_class,
|
||||||
searchstate=searchstate, status=statusStrings[ep.status])
|
searchstate=searchstate, status=statusStrings[ep.status])
|
||||||
if retrystate:
|
if retrystate:
|
||||||
|
@ -2885,9 +2873,9 @@ class Home(MainHandler):
|
||||||
ep_data.update(dict(retrystate=sickbeard.USE_FAILED_DOWNLOADS and ep_status in retry_statuses))
|
ep_data.update(dict(retrystate=sickbeard.USE_FAILED_DOWNLOADS and ep_status in retry_statuses))
|
||||||
if statusoverview:
|
if statusoverview:
|
||||||
ep_data.update(dict(statusoverview=Overview.overviewStrings[
|
ep_data.update(dict(statusoverview=Overview.overviewStrings[
|
||||||
helpers.getOverview(ep.status, show.quality, show.upgrade_once)]))
|
helpers.getOverview(ep.status, ep.show.quality, ep.show.upgrade_once)]))
|
||||||
|
|
||||||
return ep_data, (show.indexer, show.indexerid, ep.season, ep.episode)
|
return ep_data, (ep.show.indexer, ep.show.indexerid, ep.season, ep.episode)
|
||||||
|
|
||||||
def searchEpisodeSubtitles(self, show=None, season=None, episode=None):
|
def searchEpisodeSubtitles(self, show=None, season=None, episode=None):
|
||||||
# retrieve the episode object and fail if we can't get one
|
# retrieve the episode object and fail if we can't get one
|
||||||
|
|
Loading…
Reference in a new issue