Browse Source

Change anime "Available groups" to display "No groups listed..." when API is fine with no results instead of blank.

Change improve clarity of anime group lists by using terms Allow list and Block list.
tags/release_0.25.1
JackDandy 5 years ago
parent
commit
dec65748db
  1. 2
      CHANGES.md
  2. 79
      gui/slick/css/style.css
  3. 2
      gui/slick/interfaces/default/config_general.tmpl
  4. 8
      gui/slick/interfaces/default/displayShow.tmpl
  5. 4
      gui/slick/interfaces/default/editShow.tmpl
  6. 2
      gui/slick/interfaces/default/home_newShow.tmpl
  7. 2
      gui/slick/interfaces/default/inc_addShowOptions.tmpl
  8. 68
      gui/slick/interfaces/default/inc_anigrouplists.tmpl
  9. 68
      gui/slick/interfaces/default/inc_blackwhitelist.tmpl
  10. 10
      gui/slick/js/anigrouplists.js
  11. 12
      gui/slick/js/editShow.js
  12. 14
      gui/slick/js/newShow.js
  13. 54
      sickbeard/anime.py
  14. 60
      sickbeard/databases/mainDB.py
  15. 3
      sickbeard/db.py
  16. 4
      sickbeard/providers/horriblesubs.py
  17. 2
      sickbeard/search.py
  18. 20
      sickbeard/show_name_helpers.py
  19. 38
      sickbeard/show_queue.py
  20. 14
      sickbeard/tv.py
  21. 54
      sickbeard/webserve.py
  22. 2
      tests/migration_tests.py

2
CHANGES.md

@ -45,6 +45,8 @@
* Add overall failure monitoring to History/Connect fails (renamed from "Provider fails")
* Change log exception during updateCache in newznab
* Change make Py3.9 preparations
* Change anime "Available groups" to display "No groups listed..." when API is fine with no results instead of blank
* Change improve clarity of anime group lists by using terms Allow list and Block list
[develop changelog]

79
gui/slick/css/style.css

@ -1317,16 +1317,16 @@ div.formpaginate{
font-weight:900
}
#addShowForm #blackwhitelist{
#addShowForm #anigrouplists{
padding:0 0 0 15px
}
#edit-show #blackwhitelist,
#edit-show #blackwhitelist h4,
#edit-show #blackwhitelist p,
#addShowForm #blackwhitelist,
#addShowForm #blackwhitelist h4,
#addShowForm #blackwhitelist p{
#edit-show #anigrouplists,
#edit-show #anigrouplists h4,
#edit-show #anigrouplists p,
#addShowForm #anigrouplists,
#addShowForm #anigrouplists h4,
#addShowForm #anigrouplists p{
font-size:13px
}
@ -3042,21 +3042,21 @@ select .selected:before{
border:1px transparent
}
#addShowForm #add-white,
#addShowForm #add-black{
#addShowForm #add-allow,
#addShowForm #add-block{
margin:0 0 10px 30px !important
}
#addShowForm #remove-white,
#addShowForm #remove-black{
#addShowForm #remove-allow,
#addShowForm #remove-block{
margin:0 0 0 30px !important
}
#edit-show #add-white,
#edit-show #add-black{
#edit-show #add-allow,
#edit-show #add-block{
margin:0 0 10px !important
}
#edit-show #remove-white,
#edit-show #remove-black{
#edit-show #remove-allow,
#edit-show #remove-block{
margin:0 !important
}
@ -3636,7 +3636,7 @@ option.flag{
}
/* Anime section for editShow */
.bwlWrapper{
.anigrouplists-wrapper{
height:auto;
margin:0 auto
}
@ -3658,62 +3658,69 @@ option.flag{
width:95%
}
div.blackwhitelist h4{
div.anigrouplists h4{
margin-top:0
}
div.blackwhitelist{
#addShowForm .anigrouplists.pool h4{
margin-right:20px !important
}
div.anigrouplists{
text-align:center
}
div.blackwhitelist.white input,
div.blackwhitelist.black input,
div.blackwhitelist.pool input{
div.anigrouplists.allow input,
div.anigrouplists.block input,
div.anigrouplists.pool input{
margin:5px 0 !important
}
div.blackwhitelist select{
div.anigrouplists select{
margin:0 !important
}
div.blackwhitelist .inuse{
div.anigrouplists .inuse{
margin-right:5px;
width:243px;
float:left
}
div.blackwhitelist.white,
div.blackwhitelist.black{
div.anigrouplists.allow,
div.anigrouplists.block{
width:243px
}
div.blackwhitelist.white select,
div.blackwhitelist.black select{
div.anigrouplists.allow select,
div.anigrouplists.block select{
margin:0;
width:215px
/* clear:both*/
}
div.blackwhitelist.white select,
div.blackwhitelist.black select{
div.anigrouplists.allow select,
div.anigrouplists.block select{
height:110px
}
#edit-show div.blackwhitelist.pool{
#edit-show div.anigrouplists.pool{
width:330px;
height:265px;
margin-left:248px;
float:none
}
#edit-show div.blackwhitelist.pool select,
div.blackwhitelist.pool,
div.blackwhitelist.pool select{
#edit-show div.anigrouplists.pool select,
div.anigrouplists.pool,
div.anigrouplists.pool select{
width:330px;
height:265px;
float:right
}
#addShowForm #pool{
width:310px;
margin-right:20px !important
}
div.blackwhitelist span{
div.anigrouplists span{
text-align:center
}
div#blackwhitelist,
div.blackwhitelist.manual{
div#anigrouplists,
div.anigrouplists.manual{
margin:7px 0
}

2
gui/slick/interfaces/default/config_general.tmpl

@ -632,7 +632,7 @@
<span class="component-desc">
<input type="text" name="allowed_hosts" id="allowed-hosts" value="$sg_str('ALLOWED_HOSTS')" class="form-control input-sm input300">
<p>blank for insecure allow all</p>
<div class="clear-left"><p>whitelist names that browse the interface (e.g. $request_host, my_hostname)</p></div>
<div class="clear-left"><p>allowed names that browse the interface (e.g. $request_host, my_hostname)</p></div>
</span>
</label>
</div>

8
gui/slick/interfaces/default/displayShow.tmpl

@ -380,11 +380,11 @@
#if int($show_obj.is_anime)
<span class="label">Anime</span>
#end if
#if $bwl and $bwl.whitelist
<span class="label addQTip" title="#echo ', '.join($bwl.whitelist).replace(',', '<br />')#">Wanted group$maybe_plural(len($bwl.whitelist))</span>
#if $anigroups and $anigroups.allowlist
<span class="label addQTip" title="#echo ', '.join($anigroups.allowlist).replace(',', '<br />')#">Wanted group$maybe_plural(len($anigroups.allowlist))</span>
#end if
#if $bwl and $bwl.blacklist
<span class="label addQTip" title="#echo ', '.join($bwl.blacklist).replace(',', '<br />')#">Unwanted group$maybe_plural(len($bwl.blacklist))</span>
#if $anigroups and $anigroups.blocklist
<span class="label addQTip" title="#echo ', '.join($anigroups.blocklist).replace(',', '<br />')#">Unwanted group$maybe_plural(len($anigroups.blocklist))</span>
#end if
</div>
</div>

4
gui/slick/interfaces/default/editShow.tmpl

@ -275,8 +275,8 @@
#if $show_obj.is_anime
#import sickbeard.anime
#include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_blackwhitelist.tmpl')
<script type="text/javascript" src="$sbRoot/js/blackwhite.js?v=$sbPID"></script>
#include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_anigrouplists.tmpl')
<script type="text/javascript" src="$sbRoot/js/anigrouplists.js?v=$sbPID"></script>
#end if
</div><!-- /component-group2 //-->

2
gui/slick/interfaces/default/home_newShow.tmpl

@ -153,7 +153,7 @@
</div>
<script type="text/javascript" src="$sbRoot/js/rootDirs.js?v=$sbPID"></script>
<script type="text/javascript" src="$sbRoot/js/blackwhite.js?v=$sbPID"></script>
<script type="text/javascript" src="$sbRoot/js/anigrouplists.js?v=$sbPID"></script>
</div>

2
gui/slick/interfaces/default/inc_addShowOptions.tmpl

@ -135,7 +135,7 @@
#if $enable_anime_options
#import sickbeard.anime
#include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_blackwhitelist.tmpl')
#include $os.path.join($sg_str('PROG_DIR'), 'gui/slick/interfaces/default/inc_anigrouplists.tmpl')
#else
<input type="hidden" name="anime" id="anime" value="0" />
#end if

68
gui/slick/interfaces/default/inc_anigrouplists.tmpl

@ -0,0 +1,68 @@
<div class="field-pair alt" id="anigrouplists">
<input type="hidden" name="allowlist" id="allowlist">
<input type="hidden" name="blocklist" id="blocklist">
<span class="component-title">Fansub groups</span>
<span class="component-desc">
<div class="anigrouplists-wrapper">
<div class="anigrouplists all">
<div class="anigrouplists anidb">
<div class="inuse" style="padding:0">
<div class="anigrouplists allow" style="margin-bottom:10px">
<h4 style="margin:0 41px 6px 0">Allow list<br /><span class="grey-text">Only snatch releases by group(s)</span></h4>
<div style="width:243px; height:110px">
<select style="width:202px" class="pull-left" id="allow" multiple="multiple" size="12">
#for $keyword in sorted($allowlist, key=lambda x: x.lower()):
<option value="$keyword">$keyword</option>
#end for
</select>
<div style="position:relative; width:36px; height:64px; margin: -32px 0 0; top: 50%;" class="pull-right">
<input id="add-allow" class="btn" value="<<" type="button">
<input id="remove-allow" class="btn clear:right" value=">>" type="button">
</div>
</div>
</div>
<div class="anigrouplists block" style="position:relative; bottom: -1px">
<h4 style="margin:0 41px 6px 0">Block list<br /><span class="grey-text">Ignore releases by group(s)</span></h4>
<div style="width:243px; height:110px">
<select style="width:202px" class="pull-left" id="block" multiple="multiple" size="12">
#for $keyword in sorted($blocklist, key=lambda x: x.lower()):
<option value="$keyword">$keyword</option>
#end for
</select>
<div style="position:relative; width:36px; height:64px; margin: -32px 0 0; top: 50%;" class="pull-right">
<input id="add-block" class="btn" value="<<" type="button">
<input id="remove-block" class="btn clear:right" value=">>" type="button">
</div>
</div>
</div>
</div>
<div class="anigrouplists pool">
<h4 style="margin:0 0 6px 0">Available groups<br /><span class="grey-text">Name (Rating) Number of subbed episodes</span></h4>
<select id="pool" multiple="multiple" size="12">
#for $group in sorted($groups, key=lambda x: x['name'].lower())
#if $group['name'] not in $allowlist and $group['name'] not in $blocklist:
<option value="$group['name']">$group['name'] #if len($group['rating'])# ($group['rating'])#end if# $group['range']</option>
#end if
#end for
</select>
</div>
</div>
<div style="clear:both">&nbsp;</div>
<div class="anigrouplists manual">
<div class="pull-left">
<input type="text" id="addToPoolText" class="form-control form-control-inline input-sm input200" style="width:202px">
<input class="btn btn-inline" type="button" value="Add to Allow list" id="new-allow">
<input style="margin-right:0" class="btn btn-inline" type="button" value="Add to Block list" id="new-block">
</div>
<span class="pull-left">add a custom item to either the allow or block list</span>
<div style="clear:both">&nbsp;</div>
</div>
</div>
</div>
</span>
</div><!-- /anigrouplists -->

68
gui/slick/interfaces/default/inc_blackwhitelist.tmpl

@ -1,68 +0,0 @@
<div class="field-pair alt" id="blackwhitelist">
<input type="hidden" name="whitelist" id="whitelist">
<input type="hidden" name="blacklist" id="blacklist">
<span class="component-title">Fansub groups</span>
<span class="component-desc">
<div class="bwlWrapper">
<div class="blackwhitelist all">
<div class="blackwhitelist anidb">
<div class="inuse" style="padding:0">
<div class="blackwhitelist white" style="margin-bottom:10px">
<h4 style="margin:0 41px 6px 0">Whitelist<br /><span class="grey-text">Only snatch releases by group(s)</span></h4>
<div style="width:243px; height:110px">
<select style="width:202px" class="pull-left" id="white" multiple="multiple" size="12">
#for $keyword in sorted($whitelist, key=lambda x: x.lower()):
<option value="$keyword">$keyword</option>
#end for
</select>
<div style="position:relative; width:36px; height:64px; margin: -32px 0 0; top: 50%;" class="pull-right">
<input id="add-white" class="btn" value="<<" type="button">
<input id="remove-white" class="btn clear:right" value=">>" type="button">
</div>
</div>
</div>
<div class="blackwhitelist black" style="position:relative; bottom: -1px">
<h4 style="margin:0 41px 6px 0">Blacklist<br /><span class="grey-text">Ignore releases by group(s)</span></h4>
<div style="width:243px; height:110px">
<select style="width:202px" class="pull-left" id="black" multiple="multiple" size="12">
#for $keyword in sorted($blacklist, key=lambda x: x.lower()):
<option value="$keyword">$keyword</option>
#end for
</select>
<div style="position:relative; width:36px; height:64px; margin: -32px 0 0; top: 50%;" class="pull-right">
<input id="add-black" class="btn" value="<<" type="button">
<input id="remove-black" class="btn clear:right" value=">>" type="button">
</div>
</div>
</div>
</div>
<div class="blackwhitelist pool">
<h4 style="margin:0 0 6px 0">Available groups<br /><span class="grey-text">Name (Rating) Number of subbed episodes</span></h4>
<select id="pool" multiple="multiple" size="12">
#for $group in sorted($groups, key=lambda x: x['name'].lower())
#if $group['name'] not in $whitelist and $group['name'] not in $blacklist:
<option value="$group['name']">$group['name'] ($group['rating']) $group['range']</option>
#end if
#end for
</select>
</div>
</div>
<div style="clear:both">&nbsp;</div>
<div class="blackwhitelist manual">
<div class="pull-left">
<input type="text" id="addToPoolText" class="form-control form-control-inline input-sm input200" style="width:202px">
<input class="btn btn-inline" type="button" value="Add to Whitelist" id="new-white">
<input style="margin-right:0" class="btn btn-inline" type="button" value="Add to Blacklist" id="new-black">
</div>
<span class="pull-left">add a custom item to either the whitelist or blacklist</span>
<div style="clear:both">&nbsp;</div>
</div>
</div>
</div>
</span>
</div><!-- /blackwhitelist -->

10
gui/slick/js/blackwhite.js → gui/slick/js/anigrouplists.js

@ -1,5 +1,5 @@
function generate_bwlist() {
$.each(['white', 'black'], function(i, list) {
function generateAniGroupList() {
$.each(['allow', 'block'], function(i, list) {
var group_list = [];
$('#' + list + ' option').each(function(i, option) {
@ -10,15 +10,15 @@ function generate_bwlist() {
});
}
$('#add-white, #add-black').click(function() {
$('#add-allow, #add-block').click(function() {
!$('#pool option:selected').remove().appendTo('#' + $(this).attr('id').replace(/add[-]/i, ''));
});
$('#remove-white, #remove-black').click(function() {
$('#remove-allow, #remove-block').click(function() {
!$('#' + $(this).attr('id').replace(/remove[-]/i, '') + ' option:selected').remove().appendTo('#pool');
});
$('#new-white, #new-black').click(function() {
$('#new-allow, #new-block').click(function() {
var group = $('#addToPoolText').val();
if ('' != group) {
var option = $('<option>');

12
gui/slick/js/editShow.js

@ -2,7 +2,7 @@
/** @namespace config.showLang */
/** @namespace config.showIsAnime */
/** @namespace config.expandIds */
/*globals $, config, sbRoot, generate_bwlist*/
/*globals $, config, sbRoot, generateAniGroupList*/
$(document).ready(function () {
@ -52,7 +52,7 @@ $(document).ready(function () {
$('#submit').on('click', function () {
$('#exceptions_list').val(getExceptions());
if (config.showIsAnime)
generate_bwlist();
generateAniGroupList();
});
$('#addSceneName').on('click', function () {
@ -101,10 +101,10 @@ $(document).ready(function () {
function isAnime() {
uncheck(elABD); uncheck(elSports);
if (config.showIsAnime) { $('#blackwhitelist').fadeIn('fast', 'linear'); } return !0; }
if (config.showIsAnime) { $('#anigrouplists').fadeIn('fast', 'linear'); } return !0; }
function isScene() { uncheck(elABD); uncheck(elSports); }
function isABD() { uncheck(elAnime); uncheck(elScene); $('#blackwhitelist, #anime-options').fadeOut('fast', 'linear'); }
function isSports() { uncheck(elAnime); uncheck(elScene); $('#blackwhitelist, #anime-options').fadeOut('fast', 'linear'); }
function isABD() { uncheck(elAnime); uncheck(elScene); $('#anigrouplists, #anime-options').fadeOut('fast', 'linear'); }
function isSports() { uncheck(elAnime); uncheck(elScene); $('#anigrouplists, #anime-options').fadeOut('fast', 'linear'); }
if (checked(elAnime)) { isAnime(); }
if (checked(elScene)) { isScene(); }
@ -115,7 +115,7 @@ $(document).ready(function () {
if (checked(elAnime))
isAnime() && !config.showIsAnime && $('#anime-options').fadeIn('fast', 'linear');
else
$('#blackwhitelist, #anime-options').fadeOut('fast', 'linear');
$('#anigrouplists, #anime-options').fadeOut('fast', 'linear');
});
elIdMap.on('click', function() {
var elMapOptions = $('#idmapping-options'), anim = {fast: 'linear'};

14
gui/slick/js/newShow.js

@ -282,7 +282,7 @@ $(document).ready(function () {
alert('You must choose a show to continue');
return !1;
}
generate_bwlist();
generateAniGroupList();
}
$('#addShowForm').submit();
});
@ -352,7 +352,7 @@ $(document).ready(function () {
else if (elInput.length && elInput.val().length) {
showName = $('#provided-show-name').val();
}
update_bwlist(showName);
updateAniGrouplist(showName);
var sample_text = '<p>Adding show <span class="show-name">' + cleanseText(showName, !0) + '</span>'
+ ('' == showName ? 'into<br />' : '<br />into')
+ ' <span class="show-dest">';
@ -455,19 +455,19 @@ $(document).ready(function () {
option.appendTo('#pool');
}
function update_bwlist (show_name) {
function updateAniGrouplist (show_name) {
$('#black, #white, #pool').children().remove();
$('#allow, #block, #pool').children().remove();
if ($('#anime').prop('checked')) {
$('#blackwhitelist').show();
$('#anigrouplists').show();
if (show_name) {
$.getJSON(sbRoot + '/home/fetch-releasegroups', {'show_name': cleanseText(show_name, !1)}, function (data) {
if ('success' == data['result']) {
var groups = [];
$.each(data.groups, function (i, group) {
if ('' != group.name) {
groups.push(group.name + '#<3SG#' + ' (' + group.rating + ') ' + group.range)
groups.push(group.name + '#<3SG#' + ('' === group.rating ? '' : ' (' + group.rating + ') ') + group.range)
}
});
if (0 < groups.length) {
@ -488,7 +488,7 @@ $(document).ready(function () {
});
}
} else {
$('#blackwhitelist').hide();
$('#anigrouplists').hide();
}
}
});

54
sickbeard/anime.py

@ -34,30 +34,30 @@ if False:
from typing import Any, AnyStr, List, Optional, Tuple
class BlackWhitelistNoShowIDException(Exception):
class AllowBlockNoShowIDException(Exception):
"""
No prodid or tvid was given
"""
class BlackAndWhiteList(object):
blacklist = [] # type: List[AnyStr]
whitelist = [] # type: List[AnyStr]
class AniGroupList(object):
allowlist = [] # type: List[AnyStr]
blocklist = [] # type: List[AnyStr]
def __init__(self, tvid, prodid, tvid_prodid=None):
# type: (int, int, AnyStr) -> None
if not tvid or not prodid:
raise BlackWhitelistNoShowIDException()
raise AllowBlockNoShowIDException()
self.tvid = tvid # type: int
self.prodid = prodid # type: int
self.tvid_prodid = tvid_prodid # type: AnyStr
self.load()
def load(self):
logger.log(u'Building black and white list for %s' % self.tvid_prodid, logger.DEBUG)
self.blacklist = self._load_list('blacklist')
self.whitelist = self._load_list('whitelist')
logger.log(u'Building allow amd block list for %s' % self.tvid_prodid, logger.DEBUG)
self.allowlist = self._load_list('allowlist')
self.blocklist = self._load_list('blocklist')
def _load_list(self, table):
# type: (AnyStr) -> List[AnyStr]
@ -77,32 +77,32 @@ class BlackAndWhiteList(object):
for cur_result in sql_result:
groups.append(cur_result['keyword'])
logger.log('BWL: %s loaded keywords from %s: %s' % (self.tvid_prodid, table, groups),
logger.log('AniPermsList: %s loaded keywords from %s: %s' % (self.tvid_prodid, table, groups),
logger.DEBUG)
return groups
def set_black_keywords(self, values):
def set_allow_keywords(self, values):
# type: (List[AnyStr]) -> None
"""
:param values: list of words
"""
self._del_all_keywords('blacklist')
self._add_keywords('blacklist', values)
self.blacklist = values
logger.log('Blacklist set to: %s' % self.blacklist, logger.DEBUG)
self._del_all_keywords('allowlist')
self._add_keywords('allowlist', values)
self.allowlist = values
logger.log('Allowlist set to: %s' % self.allowlist, logger.DEBUG)
def set_white_keywords(self, values):
def set_block_keywords(self, values):
# type: (List[AnyStr]) -> None
"""
:param values: list of words
"""
self._del_all_keywords('whitelist')
self._add_keywords('whitelist', values)
self.whitelist = values
logger.log('Whitelist set to: %s' % self.whitelist, logger.DEBUG)
self._del_all_keywords('blocklist')
self._add_keywords('blocklist', values)
self.blocklist = values
logger.log('Blocklist set to: %s' % self.blocklist, logger.DEBUG)
def _del_all_keywords(self, table):
# type: (AnyStr) -> None
@ -139,20 +139,12 @@ class BlackAndWhiteList(object):
logger.log('Failed to detect release group, invalid result', logger.DEBUG)
return False
if result.release_group.lower() in [x.lower() for x in self.whitelist] or not self.whitelist:
white_result = True
else:
white_result = False
if result.release_group.lower() in [x.lower() for x in self.blacklist]:
black_result = False
else:
black_result = True
allowed = result.release_group.lower() in [x.lower() for x in self.allowlist] or not self.allowlist
blocked = result.release_group.lower() in [x.lower() for x in self.blocklist]
logger.log('Whitelist check passed: %s. Blacklist check passed: %s' % (white_result, black_result),
logger.DEBUG)
logger.log('Allow list valid: %s. Block list valid: %s' % (allowed, blocked), logger.DEBUG)
return white_result and black_result
return allowed and blocked
def short_group_names(groups):

60
sickbeard/databases/mainDB.py

@ -28,7 +28,7 @@ import encodingKludge as ek
from six import iteritems
MIN_DB_VERSION = 9 # oldest db version we support migrating from
MAX_DB_VERSION = 20012
MAX_DB_VERSION = 20013
TEST_BASE_VERSION = None # the base production db version, only needed for TEST db versions (>=100000)
@ -174,8 +174,9 @@ class MainSanityCheck(db.DBSanityCheck):
self.connection.action('CREATE UNIQUE INDEX idx_tv_episodes_unique ON '
'tv_episodes(indexer,showid,season,episode)')
for t in [('blacklist', 'show_id'), ('history', 'showid'), ('scene_exceptions', 'indexer_id'),
('whitelist', 'show_id')]:
allowtbl, blocktbl = (('allow', 'block'), ('white', 'black'))[not self.connection.hasTable('blocklist')]
for t in [('%slist' % allowtbl, 'show_id'), ('%slist' % blocktbl, 'show_id'),
('history', 'showid'), ('scene_exceptions', 'indexer_id')]:
if not self.connection.hasIndex('%s' % t[0], 'idx_id_indexer_%s' % t[0]):
# noinspection SqlResolve
self.connection.action('CREATE INDEX idx_id_indexer_%s ON %s (indexer, %s)' % (t[0], t[0], t[1]))
@ -243,8 +244,9 @@ class InitialSchema(db.SchemaUpgrade):
if not self.hasTable('tv_shows') and not self.hasTable('db_version'):
queries = [
# blacklist
'CREATE TABLE blacklist (show_id INTEGER, range TEXT, keyword TEXT)',
# anime allow and block list
'CREATE TABLE allowlist (show_id INTEGER, range TEXT, keyword TEXT, indexer NUMERIC)',
'CREATE TABLE blocklist (show_id INTEGER, range TEXT, keyword TEXT, indexer NUMERIC)',
# db_version
'CREATE TABLE db_version (db_version INTEGER)',
'INSERT INTO db_version (db_version) VALUES (20008)',
@ -305,8 +307,6 @@ class InitialSchema(db.SchemaUpgrade):
' PRIMARY KEY (indexer_id, indexer))',
# webdl_types
'CREATE TABLE webdl_types (dname TEXT NOT NULL, regex TEXT NOT NULL)',
# whitelist
'CREATE TABLE whitelist (show_id INTEGER, range TEXT, keyword TEXT)',
# xem_refresh
'CREATE TABLE xem_refresh (indexer TEXT, indexer_id INTEGER PRIMARY KEY, last_refreshed INTEGER)',
]
@ -1089,13 +1089,13 @@ class AddSceneAbsoluteNumbering(db.SchemaUpgrade):
# 34 -> 35
class AddAnimeBlacklistWhitelist(db.SchemaUpgrade):
class AddAnimeAllowlistBlocklist(db.SchemaUpgrade):
def execute(self):
db.backup_database('sickbeard.db', self.checkDBVersion())
cl = [['CREATE TABLE blacklist (show_id INTEGER, range TEXT, keyword TEXT)'],
['CREATE TABLE whitelist (show_id INTEGER, range TEXT, keyword TEXT)']]
self.upgrade_log(u'Creating table blacklist whitelist')
cl = [['CREATE TABLE allowlist (show_id INTEGER, range TEXT, keyword TEXT, indexer NUMERIC)'],
['CREATE TABLE blocklist (show_id INTEGER, range TEXT, keyword TEXT, indexer NUMERIC)']]
self.upgrade_log(u'Creating tables for anime allow and block lists')
self.connection.mass_action(cl)
self.incDBVersion()
@ -1396,9 +1396,10 @@ class ChangeMapIndexer(db.SchemaUpgrade):
except (BaseException, Exception):
pass
keep_tables = {'scene_exceptions', 'scene_exceptions_refresh', 'info', 'indexer_mapping', 'blacklist',
keep_tables = {'allowlist', 'blocklist', 'whitelist', 'blacklist',
'scene_exceptions', 'scene_exceptions_refresh', 'info', 'indexer_mapping',
'db_version', 'history', 'imdb_info', 'lastUpdate', 'scene_numbering', 'tv_episodes', 'tv_shows',
'whitelist', 'xem_refresh'}
'xem_refresh'}
current_tables = set(self.listTables())
remove_tables = list(current_tables - keep_tables)
for table in remove_tables:
@ -1504,14 +1505,15 @@ class AddIndexerToTables(db.SchemaUpgrade):
show_ids = {s['prod_id']: s['tv_id'] for s in
self.connection.select('SELECT indexer AS tv_id, indexer_id AS prod_id FROM tv_shows')}
columns = {'blacklist': 'show_id, range, keyword, indexer',
allowtbl, blocktbl = (('allow', 'block'), ('white', 'black'))[not self.connection.hasTable('blocklist')]
columns = {'%slist' % allowtbl: 'show_id, range, keyword, indexer',
'%slist' % blocktbl: 'show_id, range, keyword, indexer',
'history': 'action, date, showid, season, episode, quality, resource, provider, version, indexer',
'scene_exceptions': 'exception_id , indexer_id, show_name, season, custom, indexer',
'whitelist': 'show_id, range, keyword, indexer'}
'scene_exceptions': 'exception_id , indexer_id, show_name, season, custom, indexer'}
# add missing indexer column
for t in [('blacklist', 'show_id'), ('history', 'showid'), ('scene_exceptions', 'indexer_id'),
('whitelist', 'show_id')]:
for t in [(allowtbl, 'show_id'), (blocktbl, 'show_id'),
('history', 'showid'), ('scene_exceptions', 'indexer_id')]:
if not self.hasColumn(t[0], 'indexer'):
self.upgrade_log(u'Adding TV info support to %s table' % t[0])
self.addColumn(t[0], 'indexer')
@ -1670,3 +1672,25 @@ class AddShowExludeGlobals(db.SchemaUpgrade):
self.setDBVersion(20012)
return self.checkDBVersion()
# 20012 -> 20013
class RenameAllowBlockListTables(db.SchemaUpgrade):
def execute(self):
db.backup_database('sickbeard.db', self.checkDBVersion())
if not self.connection.hasTable('blocklist'):
self.upgrade_log('Renaming allow/block list tables')
for old, new in (('black', 'block'), ('white', 'allow')):
# noinspection SqlResolve
self.connection.mass_action([
['ALTER TABLE %slist RENAME TO tmp_%slist' % (old, new)],
['CREATE TABLE %slist (show_id INTEGER, range TEXT, keyword TEXT, indexer NUMERIC)' % new],
['INSERT INTO %slist(show_id, range, keyword, indexer)'
' SELECT show_id, range, keyword, indexer FROM tmp_%slist' % (new, new)],
['DROP TABLE tmp_%slist' % new]
])
self.setDBVersion(20013)
return self.checkDBVersion()

3
sickbeard/db.py

@ -581,7 +581,7 @@ def MigrationCode(my_db):
31: sickbeard.mainDB.AddAnimeTVShow,
32: sickbeard.mainDB.AddAbsoluteNumbering,
33: sickbeard.mainDB.AddSceneAbsoluteNumbering,
34: sickbeard.mainDB.AddAnimeBlacklistWhitelist,
34: sickbeard.mainDB.AddAnimeAllowlistBlocklist,
35: sickbeard.mainDB.AddSceneAbsoluteNumbering2,
36: sickbeard.mainDB.AddXemRefresh,
37: sickbeard.mainDB.AddSceneToTvShows,
@ -619,6 +619,7 @@ def MigrationCode(my_db):
20009: sickbeard.mainDB.AddPrune,
20010: sickbeard.mainDB.AddIndexerToTables,
20011: sickbeard.mainDB.AddShowExludeGlobals,
20012: sickbeard.mainDB.RenameAllowBlockListTables,
# 20002: sickbeard.mainDB.AddCoolSickGearFeature3,
}

4
sickbeard/providers/horriblesubs.py

@ -102,11 +102,11 @@ class HorribleSubsProvider(generic.TorrentProvider):
def _season_strings(self, *args, **kwargs):
return [{'Season': show_name_helpers.makeSceneSeasonSearchString(
self.show_obj, *args, ignore_wl=True, **kwargs)}]
self.show_obj, *args, ignore_allowlist=True, **kwargs)}]
def _episode_strings(self, *args, **kwargs):
return [{'Episode': show_name_helpers.makeSceneSearchString(
self.show_obj, *args, ignore_wl=True, **kwargs)}]
self.show_obj, *args, ignore_allowlist=True, **kwargs)}]
def get_data(self, url):
result = None

2
sickbeard/search.py

@ -387,7 +387,7 @@ def is_final_result(result):
if best_qualities and max(best_qualities) > result.quality:
return False
# if it does not match the shows black and white list its no good
# if it does not match the shows block and allow list its no good
elif show_obj.is_anime and show_obj.release_groups.is_valid(result):
return False

20
sickbeard/show_name_helpers.py

@ -251,14 +251,14 @@ def get_show_names_all_possible(show_obj, season=-1, scenify=True, spacer='.'):
def makeSceneSeasonSearchString(show_obj, # type: sickbeard.tv.TVShow
ep_obj, # type: sickbeard.tv.TVEpisode
ignore_wl=False, # type: bool
ignore_allowlist=False, # type: bool
extra_search_type=None
): # type: (...) -> List[AnyStr]
"""
:param show_obj: show object
:param ep_obj: episode object
:param ignore_wl:
:param ignore_allowlist:
:param extra_search_type:
:return: list of search strings
"""
@ -321,9 +321,9 @@ def makeSceneSeasonSearchString(show_obj, # type: sickbeard.tv.TVShow
# for providers that don't allow multiple searches in one request we only search for Sxx style stuff
else:
for cur_season in seasonStrings:
if not ignore_wl and show_obj.is_anime \
and None is not show_obj.release_groups and show_obj.release_groups.whitelist:
for keyword in show_obj.release_groups.whitelist:
if not ignore_allowlist and show_obj.is_anime \
and None is not show_obj.release_groups and show_obj.release_groups.allowlist:
for keyword in show_obj.release_groups.allowlist:
to_return.append(keyword + '.' + cur_name + "." + cur_season)
else:
@ -334,13 +334,13 @@ def makeSceneSeasonSearchString(show_obj, # type: sickbeard.tv.TVShow
def makeSceneSearchString(show_obj, # type: sickbeard.tv.TVShow
ep_obj, # type: sickbeard.tv.TVEpisode
ignore_wl=False # type: bool
ignore_allowlist=False # type: bool
): # type: (...) -> List[AnyStr]
"""
:param show_obj: show object
:param ep_obj: episode object
:param ignore_wl:
:param ignore_allowlist:
:return: list or search strings
"""
my_db = db.DBConnection()
@ -372,9 +372,9 @@ def makeSceneSearchString(show_obj, # type: sickbeard.tv.TVShow
for cur_show_obj in show_names:
for cur_ep_string in ep_strings:
if not ignore_wl and ep_obj.show_obj.is_anime and \
None is not ep_obj.show_obj.release_groups and ep_obj.show_obj.release_groups.whitelist:
for keyword in ep_obj.show_obj.release_groups.whitelist:
if not ignore_allowlist and ep_obj.show_obj.is_anime and \
None is not ep_obj.show_obj.release_groups and ep_obj.show_obj.release_groups.allowlist:
for keyword in ep_obj.show_obj.release_groups.allowlist:
to_return.append(keyword + '.' + cur_show_obj + '.' + cur_ep_string)
else:
to_return.append(cur_show_obj + '.' + cur_ep_string)

38
sickbeard/show_queue.py

@ -29,7 +29,7 @@ from exceptions_helper import ex
import sickbeard
from . import logger, ui, db, generic_queue, name_cache
from .anime import BlackAndWhiteList
from .anime import AniGroupList
from .common import SKIPPED, WANTED, UNAIRED, Quality, statusStrings
from .helpers import should_delete_episode
from .indexermapper import map_indexers_to_show
@ -343,7 +343,7 @@ class ShowQueue(generic_queue.GenericQueue):
return queue_item_obj
def addShow(self, tvid, prodid, show_dir, default_status=None, quality=None, flatten_folders=None,
lang='en', subtitles=None, anime=None, scene=None, paused=None, blacklist=None, whitelist=None,
lang='en', subtitles=None, anime=None, scene=None, paused=None, blocklist=None, allowlist=None,
wanted_begin=None, wanted_latest=None, prune=None, tag=None,
new_show=False, show_name=None, upgrade_once=False):
"""
@ -370,10 +370,10 @@ class ShowQueue(generic_queue.GenericQueue):
:type scene: int or None
:param paused:
:type paused: None or int
:param blacklist:
:type blacklist: AnyStr or None
:param whitelist:
:type whitelist: AnyStr or None
:param blocklist:
:type blocklist: AnyStr or None
:param allowlist:
:type allowlist: AnyStr or None
:param wanted_begin:
:type wanted_begin: int or None
:param wanted_latest:
@ -392,7 +392,7 @@ class ShowQueue(generic_queue.GenericQueue):
:rtype: QueueItemAdd
"""
queue_item_obj = QueueItemAdd(tvid, prodid, show_dir, default_status, quality, flatten_folders, lang,
subtitles, anime, scene, paused, blacklist, whitelist,
subtitles, anime, scene, paused, blocklist, allowlist,
wanted_begin, wanted_latest, prune, tag,
new_show=new_show, show_name=show_name, upgrade_once=upgrade_once)
@ -468,7 +468,7 @@ class ShowQueueItem(generic_queue.QueueItem):
class QueueItemAdd(ShowQueueItem):
def __init__(self, tvid, prodid, show_dir, default_status, quality, flatten_folders, lang, subtitles, anime,
scene, paused, blacklist, whitelist, default_wanted_begin, default_wanted_latest, prune, tag,
scene, paused, blocklist, allowlist, default_wanted_begin, default_wanted_latest, prune, tag,
scheduled_update=False, new_show=False, show_name=None, upgrade_once=False):
"""
@ -494,10 +494,10 @@ class QueueItemAdd(ShowQueueItem):
:type scene:
:param paused:
:type paused:
:param blacklist:
:type blacklist:
:param whitelist:
:type whitelist:
:param blocklist:
:type blocklist:
:param allowlist:
:type allowlist:
:param default_wanted_begin:
:type default_wanted_begin:
:param default_wanted_latest:
@ -529,8 +529,8 @@ class QueueItemAdd(ShowQueueItem):
self.anime = anime
self.scene = scene
self.paused = paused
self.blacklist = blacklist
self.whitelist = whitelist
self.blocklist = blocklist
self.allowlist = allowlist
self.prune = prune
self.tag = tag
self.new_show = new_show
@ -706,13 +706,13 @@ class QueueItemAdd(ShowQueueItem):
self.show_obj.tag = self.tag if None is not self.tag else 'Show List'
if self.show_obj.anime:
self.show_obj.release_groups = BlackAndWhiteList(self.show_obj.tvid,
self.show_obj.release_groups = AniGroupList(self.show_obj.tvid,
self.show_obj.prodid,
self.show_obj.tvid_prodid)
if self.blacklist:
self.show_obj.release_groups.set_black_keywords(self.blacklist)
if self.whitelist:
self.show_obj.release_groups.set_white_keywords(self.whitelist)
if self.allowlist:
self.show_obj.release_groups.set_allow_keywords(self.allowlist)
if self.blocklist:
self.show_obj.release_groups.set_block_keywords(self.blocklist)
# be smartish about this
if self.show_obj.genre and 'talk show' in self.show_obj.genre.lower():

14
sickbeard/tv.py

@ -45,7 +45,7 @@ from exceptions_helper import ex
import sickbeard
from . import db, helpers, history, image_cache, indexermapper, logger, \
name_cache, network_timezones, notifiers, postProcessor, subtitles
from .anime import BlackAndWhiteList
from .anime import AniGroupList
from .common import Quality, statusStrings, \
ARCHIVED, DOWNLOADED, FAILED, IGNORED, SNATCHED, SNATCHED_PROPER, SNATCHED_ANY, SKIPPED, UNAIRED, UNKNOWN, WANTED, \
NAMING_DUPLICATE, NAMING_EXTEND, NAMING_LIMITED_EXTEND, NAMING_LIMITED_EXTEND_E_PREFIXED, NAMING_SEPARATED_REPEAT
@ -228,7 +228,7 @@ class TVShow(TVShowBase):
# noinspection added so that None _can_ be excluded from type annotation
# so that this property evaluates directly to the class on ctrl+hover instead of "multiple implementations"
# noinspection PyTypeChecker
self.release_groups = None # type: BlackAndWhiteList
self.release_groups = None # type: AniGroupList
show_obj = helpers.find_show_by_id(self.sid_int, check_multishow=True)
if None is not show_obj:
@ -1219,7 +1219,7 @@ class TVShow(TVShowBase):
self._imdbid = ('', imdbid)[2 < len(imdbid)]
if self._anime:
self.release_groups = BlackAndWhiteList(self.tvid, self.prodid, self.tvid_prodid)
self.release_groups = AniGroupList(self.tvid, self.prodid, self.tvid_prodid)
if not self._overview:
self._overview = sql_result[0]['overview']
@ -1505,8 +1505,8 @@ class TVShow(TVShowBase):
["DELETE FROM imdb_info WHERE indexer = ? AND indexer_id = ?", [self.tvid, self.prodid]],
["DELETE FROM xem_refresh WHERE indexer = ? AND indexer_id = ?", [self.tvid, self.prodid]],
["DELETE FROM scene_numbering WHERE indexer = ? AND indexer_id = ?", [self.tvid, self.prodid]],
["DELETE FROM whitelist WHERE indexer = ? AND show_id = ?", [self.tvid, self.prodid]],
["DELETE FROM blacklist WHERE indexer = ? AND show_id = ?", [self.tvid, self.prodid]],
["DELETE FROM allowlist WHERE indexer = ? AND show_id = ?", [self.tvid, self.prodid]],
["DELETE FROM blocklist WHERE indexer = ? AND show_id = ?", [self.tvid, self.prodid]],
["DELETE FROM indexer_mapping WHERE indexer = ? AND indexer_id = ?", [self.tvid, self.prodid]],
["DELETE FROM tv_shows_not_found WHERE indexer = ? AND indexer_id = ?", [self.tvid, self.prodid]]]
@ -1713,7 +1713,7 @@ class TVShow(TVShowBase):
[self.tvid, self.prodid, old_tvid, old_prodid]],
['UPDATE tv_episodes SET indexer = ?, showid = ?, indexerid = 0 WHERE indexer = ? AND showid = ?',
[self.tvid, self.prodid, old_tvid, old_prodid]],
['UPDATE blacklist SET indexer = ?, show_id = ? WHERE indexer = ? AND show_id = ?',
['UPDATE blocklist SET indexer = ?, show_id = ? WHERE indexer = ? AND show_id = ?',
[self.tvid, self.prodid, old_tvid, old_prodid]],
['UPDATE history SET indexer = ?, showid = ? WHERE indexer = ? AND showid = ?',
[self.tvid, self.prodid, old_tvid, old_prodid]],
@ -1723,7 +1723,7 @@ class TVShow(TVShowBase):
[self.tvid, self.prodid, old_tvid, old_prodid]],
['UPDATE scene_numbering SET indexer = ?, indexer_id = ? WHERE indexer = ? AND indexer_id = ?',
[self.tvid, self.prodid, old_tvid, old_prodid]],
['UPDATE whitelist SET indexer = ?, show_id = ? WHERE indexer = ? AND show_id = ?',
['UPDATE allowlist SET indexer = ?, show_id = ? WHERE indexer = ? AND show_id = ?',
[self.tvid, self.prodid, old_tvid, old_prodid]],
['UPDATE xem_refresh SET indexer = ?, indexer_id = ? WHERE indexer = ? AND indexer_id = ?',
[self.tvid, self.prodid, old_tvid, old_prodid]],

54
sickbeard/webserve.py

@ -48,7 +48,7 @@ import sg_helpers
import sickbeard
from . import classes, clients, config, db, helpers, history, image_cache, logger, naming, \
network_timezones, notifiers, nzbget, processTV, sab, scene_exceptions, search_queue, subtitles, ui
from .anime import BlackAndWhiteList, pull_anidb_groups, short_group_names
from .anime import AniGroupList, pull_anidb_groups, short_group_names
from .browser import folders_at_path
from .common import ARCHIVED, DOWNLOADED, FAILED, IGNORED, SKIPPED, SNATCHED, SNATCHED_ANY, UNAIRED, UNKNOWN, WANTED, \
SD, HD720p, HD1080p, UHD2160p, Overview, Quality, qualityPresetStrings, statusStrings
@ -2165,9 +2165,9 @@ class Home(MainHandler):
t.prev_title = 'Prev show, %s' % tvshow_names[(cur_sel - 2, last_item - 1)[1 == cur_sel]]
t.next_title = 'Next show, %s' % tvshow_names[(cur_sel, 0)[last_item == cur_sel]]
t.bwl = None
t.anigroups = None
if show_obj.is_anime:
t.bwl = show_obj.release_groups
t.anigroups = show_obj.release_groups
t.fanart = []
cache_obj = image_cache.ImageCache()
@ -2458,7 +2458,7 @@ class Home(MainHandler):
any_qualities=None, best_qualities=None, exceptions_list=None,
flatten_folders=None, paused=None, direct_call=False, air_by_date=None, sports=None, dvdorder=None,
tvinfo_lang=None, subs=None, upgrade_once=None, rls_ignore_words=None,
rls_require_words=None, anime=None, blacklist=None, whitelist=None,
rls_require_words=None, anime=None, allowlist=None, blocklist=None,
scene=None, prune=None, tag=None, quality_preset=None, reset_fanart=None,
rls_global_exclude_ignore=None, rls_global_exclude_require=None, **kwargs):
@ -2503,15 +2503,17 @@ class Home(MainHandler):
if show_obj.is_anime:
if not show_obj.release_groups:
show_obj.release_groups = BlackAndWhiteList(show_obj.tvid, show_obj.prodid, show_obj.tvid_prodid)
t.whitelist = show_obj.release_groups.whitelist
t.blacklist = show_obj.release_groups.blacklist
show_obj.release_groups = AniGroupList(show_obj.tvid, show_obj.prodid, show_obj.tvid_prodid)
t.allowlist = show_obj.release_groups.allowlist
t.blocklist = show_obj.release_groups.blocklist
t.groups = pull_anidb_groups(show_obj.name)
if None is t.groups:
t.groups = [dict(name='Did not initialise AniDB. Check debug log if reqd.', rating='', range='')]
elif False is t.groups:
t.groups = [dict(name='Fail: AniDB connect. Restart SG else check debug log', rating='', range='')]
elif isinstance(t.groups, list) and 0 == len(t.groups):
t.groups = [dict(name='No groups listed in API response', rating='', range='')]
with show_obj.lock:
t.show_obj = show_obj
@ -2579,7 +2581,7 @@ class Home(MainHandler):
if type(exceptions_list) != list:
exceptions_list = [exceptions_list]
# If direct call from mass_edit_update no scene exceptions handling or blackandwhite list handling or tags
# If direct call from mass_edit_update no scene exceptions handling or blockandallow list handling or tags
if direct_call:
do_update_exceptions = False
else:
@ -2588,19 +2590,19 @@ class Home(MainHandler):
with show_obj.lock:
if anime:
if not show_obj.release_groups:
show_obj.release_groups = BlackAndWhiteList(
show_obj.release_groups = AniGroupList(
show_obj.tvid, show_obj.prodid, show_obj.tvid_prodid)
if whitelist:
shortwhitelist = short_group_names(whitelist)
show_obj.release_groups.set_white_keywords(shortwhitelist)
if allowlist:
shortallowlist = short_group_names(allowlist)
show_obj.release_groups.set_allow_keywords(shortallowlist)
else:
show_obj.release_groups.set_white_keywords([])
show_obj.release_groups.set_allow_keywords([])
if blacklist:
shortblacklist = short_group_names(blacklist)
show_obj.release_groups.set_black_keywords(shortblacklist)
if blocklist:
shortblocklist = short_group_names(blocklist)
show_obj.release_groups.set_block_keywords(shortblocklist)
else:
show_obj.release_groups.set_black_keywords([])
show_obj.release_groups.set_block_keywords([])
errors = []
with show_obj.lock:
@ -3244,6 +3246,8 @@ class Home(MainHandler):
result = dict(result='fail', resp='init')
elif False is result:
result = dict(result='fail', resp='connect')
elif isinstance(result, list) and 0 == len(result):
result = dict(result='success', groups=[dict(name='No groups fetched in API response', rating='', range='')])
else:
result = dict(result='success', groups=result)
return json.dumps(result)
@ -3751,8 +3755,8 @@ class AddShows(Home):
t.provided_tvid = int(tvid or sickbeard.TVINFO_DEFAULT)
t.infosrc = sickbeard.TVInfoAPI().search_sources
t.meta_lang = sickbeard.ADD_SHOWS_METALANG
t.whitelist = []
t.blacklist = []
t.allowlist = []
t.blocklist = []
t.groups = []
t.show_scene_maps = list(*itervalues(sickbeard.scene_exceptions.xem_ids_list))
@ -4880,7 +4884,7 @@ class AddShows(Home):
quality_preset=None, any_qualities=None, best_qualities=None, upgrade_once=None,
flatten_folders=None, subs=None,
full_show_path=None, other_shows=None, skip_show=None, provided_tvid=None, anime=None,
scene=None, blacklist=None, whitelist=None, wanted_begin=None, wanted_latest=None,
scene=None, allowlist=None, blocklist=None, wanted_begin=None, wanted_latest=None,
prune=None, tag=None, return_to=None, cancel_form=None, **kwargs):
"""
Receive tvdb id, dir, and other options and create a show from them. If extra show dirs are
@ -4973,10 +4977,10 @@ class AddShows(Home):
flatten_folders = config.checkbox_to_value(flatten_folders)
subs = config.checkbox_to_value(subs)
if whitelist:
whitelist = short_group_names(whitelist)
if blacklist:
blacklist = short_group_names(blacklist)
if allowlist:
allowlist = short_group_names(allowlist)
if blocklist:
blocklist = short_group_names(blocklist)
if not any_qualities:
any_qualities = []
@ -4996,7 +5000,7 @@ class AddShows(Home):
# add the show
sickbeard.showQueueScheduler.action.addShow(tvid, prodid, show_dir, int(default_status), newQuality,
flatten_folders, tvinfo_lang, subs, anime,
scene, None, blacklist, whitelist,
scene, None, allowlist, blocklist,
wanted_begin, wanted_latest, prune, tag, new_show=new_show,
show_name=show_name, upgrade_once=upgrade_once)
# ui.notifications.message('Show added', 'Adding the specified show into ' + show_dir)

2
tests/migration_tests.py

@ -27,7 +27,7 @@ class MigrationBasicTests(test.SickbeardTestDBCase):
31: sickbeard.mainDB.AddAnimeTVShow,
32: sickbeard.mainDB.AddAbsoluteNumbering,
33: sickbeard.mainDB.AddSceneAbsoluteNumbering,
34: sickbeard.mainDB.AddAnimeBlacklistWhitelist,
34: sickbeard.mainDB.AddAnimeAllowlistBlocklist,
35: sickbeard.mainDB.AddSceneAbsoluteNumbering2,
36: sickbeard.mainDB.AddXemRefresh,
37: sickbeard.mainDB.AddSceneToTvShows,

Loading…
Cancel
Save