mirror of
https://github.com/moparisthebest/SickRage
synced 2024-11-11 03:45:01 -05:00
Merge branch 'origin/dev'
This commit is contained in:
commit
0b5c9e9c38
@ -270,9 +270,7 @@
|
||||
#end for
|
||||
|
||||
<div class="clearfix" style="clear:left;"></div><br/>
|
||||
|
||||
<input type="submit" class="btn config_submitter" value="Save Changes" /><br/>
|
||||
|
||||
</fieldset>
|
||||
</div><!-- /component-group2 //-->
|
||||
|
||||
@ -292,7 +290,7 @@
|
||||
<select id="name_presets">
|
||||
#set is_custom = True
|
||||
#for $cur_preset in $naming.name_presets:
|
||||
#set $tmp = $naming.test_name($cur_preset)
|
||||
#set $tmp = $naming.test_name($cur_preset, anime_type=3)
|
||||
#if $cur_preset == $sickbeard.NAMING_PATTERN:
|
||||
#set is_custom = False
|
||||
#end if
|
||||
@ -452,7 +450,7 @@
|
||||
</div>
|
||||
|
||||
<div id="naming_example_div">
|
||||
<h2>Sample:</h2>
|
||||
<h2>Single-EP Sample:</h2>
|
||||
<div class="example">
|
||||
<span class="jumbo" id="naming_example"> </span>
|
||||
</div>
|
||||
@ -467,6 +465,22 @@
|
||||
<br/>
|
||||
</div>
|
||||
|
||||
<div id="naming_example_anime_div">
|
||||
<h2>Single-EP Anime Sample:</h2>
|
||||
<div class="example">
|
||||
<span class="jumbo" id="naming_example_anime"> </span>
|
||||
</div>
|
||||
<br/>
|
||||
</div>
|
||||
|
||||
<div id="naming_example_multi_anime_div">
|
||||
<h2>Multi-EP Anime sample:</h2>
|
||||
<div class="example">
|
||||
<span class="jumbo" id="naming_example_multi_anime"> </span>
|
||||
</div>
|
||||
<br/>
|
||||
</div>
|
||||
|
||||
<div class="field-pair">
|
||||
<input type="radio" name="naming_anime" id="naming_anime" value="1" #if $sickbeard.NAMING_ANIME == 1 then "checked=\"checked\"" else ""#/>
|
||||
<label class="clearfix" for="naming_anime">
|
||||
|
@ -10,11 +10,11 @@
|
||||
#set $myDB = $db.DBConnection()
|
||||
#set $today = str($datetime.date.today().toordinal())
|
||||
#set $numShows = len($sickbeard.showList)
|
||||
#set $numGoodShows = len([x for x in $sickbeard.showList if x.paused == 0 and x.status != "Ended"])
|
||||
#set $numGoodShows = len([x for x in $sickbeard.showList if x.paused == 0 and "Ended" not in x.status])
|
||||
#set $numDLEpisodes = $myDB.select("SELECT COUNT(*) FROM tv_episodes WHERE status IN ("+",".join([str(x) for x in $Quality.DOWNLOADED + [$ARCHIVED]])+") AND season != 0 and episode != 0 AND airdate <= "+$today+"")[0][0]
|
||||
#set $numEpisodes = $myDB.select("SELECT COUNT(*) FROM tv_episodes WHERE season != 0 and episode != 0 AND (airdate != 1 OR status IN ("+",".join([str(x) for x in ($Quality.DOWNLOADED + $Quality.SNATCHED + $Quality.SNATCHED_PROPER) + [$ARCHIVED]])+")) AND airdate <= "+$today+" AND status != "+str($IGNORED)+"")[0][0]
|
||||
<b>$numShows shows</b> ($numGoodShows active) | <b>$numDLEpisodes/$numEpisodes</b> episodes downloaded |
|
||||
<b>Daily Search</b>: <%=str(sickbeard.dailySearchScheduler.timeLeft()).split('.')[0]%> |
|
||||
<b>Search</b>: <%=str(sickbeard.dailySearchScheduler.timeLeft()).split('.')[0]%> |
|
||||
<b>Backlog</b>: $sbdatetime.sbdatetime.sbfdate($sickbeard.backlogSearchScheduler.nextRun())
|
||||
</div>
|
||||
<ul style="float:right;">
|
||||
|
@ -29,8 +29,9 @@ $(document).ready(function () {
|
||||
function fill_examples() {
|
||||
var pattern = $('#naming_pattern').val();
|
||||
var multi = $('#naming_multi_ep :selected').val();
|
||||
var anime_type = $('input[name="naming_anime"]:checked').val();
|
||||
|
||||
$.get(sbRoot + '/config/postProcessing/testNaming', {pattern: pattern},
|
||||
$.get(sbRoot + '/config/postProcessing/testNaming', {pattern: pattern, anime_type: 3},
|
||||
function (data) {
|
||||
if (data) {
|
||||
$('#naming_example').text(data + '.ext');
|
||||
@ -40,7 +41,7 @@ $(document).ready(function () {
|
||||
}
|
||||
});
|
||||
|
||||
$.get(sbRoot + '/config/postProcessing/testNaming', {pattern: pattern, multi: multi},
|
||||
$.get(sbRoot + '/config/postProcessing/testNaming', {pattern: pattern, multi: multi, anime_type: 3},
|
||||
function (data) {
|
||||
if (data) {
|
||||
$('#naming_example_multi').text(data + '.ext');
|
||||
@ -50,7 +51,27 @@ $(document).ready(function () {
|
||||
}
|
||||
});
|
||||
|
||||
$.get(sbRoot + '/config/postProcessing/isNamingValid', {pattern: pattern, multi: multi},
|
||||
$.get(sbRoot + '/config/postProcessing/testNaming', {pattern: pattern, anime_type: anime_type},
|
||||
function (data) {
|
||||
if (data) {
|
||||
$('#naming_example_anime').text(data + '.ext');
|
||||
$('#naming_example_anime_div').show();
|
||||
} else {
|
||||
$('#naming_example_anime_div').hide();
|
||||
}
|
||||
});
|
||||
|
||||
$.get(sbRoot + '/config/postProcessing/testNaming', {pattern: pattern, multi: multi, anime_type: anime_type},
|
||||
function (data) {
|
||||
if (data) {
|
||||
$('#naming_example_multi_anime').text(data + '.ext');
|
||||
$('#naming_example_multi_anime_div').show();
|
||||
} else {
|
||||
$('#naming_example_multi_anime_div').hide();
|
||||
}
|
||||
});
|
||||
|
||||
$.get(sbRoot + '/config/postProcessing/isNamingValid', {pattern: pattern, multi: multi, anime_type: anime_type},
|
||||
function (data) {
|
||||
if (data == "invalid") {
|
||||
$('#naming_pattern').qtip('option', {
|
||||
@ -221,6 +242,10 @@ $(document).ready(function () {
|
||||
setup_sports_naming();
|
||||
});
|
||||
|
||||
$('input[name="naming_anime"]').click(function(){
|
||||
setup_naming();
|
||||
});
|
||||
|
||||
$('#naming_multi_ep').change(fill_examples);
|
||||
$('#naming_pattern').focusout(fill_examples);
|
||||
$('#naming_pattern').keyup(function () {
|
||||
|
@ -29,7 +29,7 @@
|
||||
|
||||
[imdbpy]
|
||||
## Default.
|
||||
accessSystem = http
|
||||
accessSystem = httpThin
|
||||
|
||||
## Optional (options common to every data access system):
|
||||
# Activate adult searches (on, by default).
|
||||
@ -69,7 +69,7 @@ accessSystem = http
|
||||
## Set the threshold for logging messages.
|
||||
# Can be one of "debug", "info", "warning", "error", "critical" (default:
|
||||
# "warning").
|
||||
#loggingLevel = debug
|
||||
loggingLevel = debug
|
||||
|
||||
## Path to a configuration file for the logging facility;
|
||||
# see: http://docs.python.org/library/logging.html#configuring-logging
|
||||
|
@ -598,11 +598,11 @@ class Tvdb:
|
||||
zipdata = StringIO.StringIO()
|
||||
zipdata.write(resp.content)
|
||||
myzipfile = zipfile.ZipFile(zipdata)
|
||||
return xmltodict.parse(myzipfile.read('%s.xml' % language).strip(), postprocessor=process)
|
||||
return xmltodict.parse(myzipfile.read('%s.xml' % language), postprocessor=process)
|
||||
except zipfile.BadZipfile:
|
||||
raise tvdb_error("Bad zip file received from thetvdb.com, could not read it")
|
||||
else:
|
||||
return xmltodict.parse(resp.content.strip(), postprocessor=process)
|
||||
return xmltodict.parse(resp.content.strip().encode('utf-8'), postprocessor=process)
|
||||
|
||||
def _getetsrc(self, url, params=None, language=None):
|
||||
"""Loads a URL using caching, returns an ElementTree of the source
|
||||
|
@ -462,7 +462,7 @@ class TVRage:
|
||||
return (key, value)
|
||||
|
||||
if resp.ok:
|
||||
return xmltodict.parse(resp.content.strip(), postprocessor=remap_keys)
|
||||
return xmltodict.parse(resp.content.strip().encode('utf-8'), postprocessor=remap_keys)
|
||||
|
||||
def _getetsrc(self, url, params=None):
|
||||
"""Loads a URL using caching, returns an ElementTree of the source
|
||||
@ -527,6 +527,7 @@ class TVRage:
|
||||
if not isinstance(data, dict or list):
|
||||
data = data.replace(u"&", u"&")
|
||||
data = data.strip()
|
||||
|
||||
return data
|
||||
|
||||
def search(self, series):
|
||||
@ -597,7 +598,7 @@ class TVRage:
|
||||
self.config['params_epInfo']['sid'] = sid
|
||||
epsEt = self._getetsrc(self.config['url_epInfo'], self.config['params_epInfo'])
|
||||
|
||||
for season in epsEt['episodelist']['season']:
|
||||
for season in epsEt['episodelist'].values():
|
||||
episodes = season['episode']
|
||||
if not isinstance(episodes, list):
|
||||
episodes = [episodes]
|
||||
|
2
setup.py
2
setup.py
@ -179,7 +179,7 @@ for curFile in auto_process_files:
|
||||
setup(
|
||||
options = {'py2exe': {'bundle_files': 1}},
|
||||
zipfile = None,
|
||||
console = ['updater.py'],
|
||||
console = ['updater.py'], requires=['Cheetah']
|
||||
)
|
||||
|
||||
if 'test' in oldArgs:
|
||||
|
@ -597,13 +597,12 @@ def initialize(consoleLogging=True):
|
||||
NAMING_PATTERN = check_setting_str(CFG, 'General', 'naming_pattern', 'Season %0S/%SN - S%0SE%0E - %EN')
|
||||
NAMING_ABD_PATTERN = check_setting_str(CFG, 'General', 'naming_abd_pattern', '%Y/%0M/%SN - %A.D - %EN')
|
||||
NAMING_CUSTOM_ABD = check_setting_int(CFG, 'General', 'naming_custom_abd', 0)
|
||||
NAMING_SPORTS_PATTERN = check_setting_str(CFG, 'General', 'naming_sports_pattern',
|
||||
'Season %0S/%SN - S%0SE%0E - %EN')
|
||||
NAMING_SPORTS_PATTERN = check_setting_str(CFG, 'General', 'naming_sports_pattern', '%Y/%0M/%SN - %A.D - %EN')
|
||||
NAMING_ANIME = check_setting_int(CFG, 'General', 'naming_anime', 3)
|
||||
NAMING_CUSTOM_SPORTS = check_setting_int(CFG, 'General', 'naming_custom_sports', 0)
|
||||
NAMING_MULTI_EP = check_setting_int(CFG, 'General', 'naming_multi_ep', 1)
|
||||
NAMING_FORCE_FOLDERS = naming.check_force_season_folders()
|
||||
NAMING_STRIP_YEAR = bool(check_setting_int(CFG, 'General', 'naming_strip_year', 0))
|
||||
NAMING_ANIME = check_setting_int(CFG, 'General', 'naming_anime', 3)
|
||||
|
||||
USE_NZBS = bool(check_setting_int(CFG, 'General', 'use_nzbs', 0))
|
||||
USE_TORRENTS = bool(check_setting_int(CFG, 'General', 'use_torrents', 1))
|
||||
|
@ -163,9 +163,9 @@ class AllShowsListUI:
|
||||
continue
|
||||
|
||||
if 'seriesname' in curShow:
|
||||
seriesnames.append(str(curShow['seriesname']))
|
||||
seriesnames.append(curShow['seriesname'])
|
||||
if 'aliasnames' in curShow:
|
||||
seriesnames.extend(str(curShow['aliasnames']).split('|'))
|
||||
seriesnames.extend(curShow['aliasnames'].split('|'))
|
||||
|
||||
for name in seriesnames:
|
||||
if searchterm.lower() in name.lower():
|
||||
|
@ -29,7 +29,7 @@ class rTorrentAPI(GenericClient):
|
||||
super(rTorrentAPI, self).__init__('rTorrent', host, username, password)
|
||||
|
||||
def _get_auth(self):
|
||||
auth = None
|
||||
self.auth = None
|
||||
|
||||
if self.auth is not None:
|
||||
return self.auth
|
||||
|
@ -50,7 +50,7 @@ class DBConnection:
|
||||
def __init__(self, filename="sickbeard.db", suffix=None, row_type=None):
|
||||
|
||||
self.filename = filename
|
||||
self.connection = sqlite3.connect(dbFilename(filename), 20)
|
||||
self.connection = sqlite3.connect(dbFilename(filename, suffix), 20)
|
||||
if row_type == "dict":
|
||||
self.connection.row_factory = self._dict_factory
|
||||
else:
|
||||
|
@ -23,7 +23,7 @@ import threading
|
||||
import regexes
|
||||
import sickbeard
|
||||
|
||||
from sickbeard import logger, helpers, scene_numbering
|
||||
from sickbeard import logger, helpers, scene_numbering, common
|
||||
from dateutil import parser
|
||||
|
||||
nameparser_lock = threading.Lock()
|
||||
@ -136,9 +136,7 @@ class NameParser(object):
|
||||
|
||||
if 'season_num' in named_groups:
|
||||
tmp_season = int(match.group('season_num'))
|
||||
if cur_regex_name == 'bare' and tmp_season in (19, 20):
|
||||
continue
|
||||
|
||||
if not (cur_regex_name == 'bare' and tmp_season in (19, 20)):
|
||||
result.season_number = tmp_season
|
||||
result.score += 1
|
||||
|
||||
@ -198,10 +196,8 @@ class NameParser(object):
|
||||
tmp_extra_info = match.group('extra_info')
|
||||
|
||||
# Show.S04.Special or Show.S05.Part.2.Extras is almost certainly not every episode in the season
|
||||
if tmp_extra_info and cur_regex_name == 'season_only' and re.search(
|
||||
r'([. _-]|^)(special|extra)s?\w*([. _-]|$)', tmp_extra_info, re.I):
|
||||
continue
|
||||
|
||||
if not (tmp_extra_info and cur_regex_name == 'season_only' and re.search(
|
||||
r'([. _-]|^)(special|extra)s?\w*([. _-]|$)', tmp_extra_info, re.I)):
|
||||
result.extra_info = tmp_extra_info
|
||||
result.score += 1
|
||||
|
||||
@ -211,6 +207,14 @@ class NameParser(object):
|
||||
|
||||
cur_show = helpers.get_show_by_name(result.series_name, useIndexer=self.useIndexers)
|
||||
if not cur_show:
|
||||
if self.showObj:
|
||||
if self.showObj.air_by_date and result.air_date:
|
||||
result.score += 1
|
||||
elif self.showObj.sports and result.sports_event_date:
|
||||
result.score += 1
|
||||
elif self.showObj.anime and len(result.ab_episode_numbers):
|
||||
result.score += 1
|
||||
|
||||
matches.append(result)
|
||||
continue
|
||||
|
||||
@ -231,6 +235,10 @@ class NameParser(object):
|
||||
if len(matches):
|
||||
result = max(matches, key=lambda x: x.score)
|
||||
|
||||
# get quality
|
||||
if result.show:
|
||||
result.quality = common.Quality.nameQuality(name, bool(result.show and result.show.is_anime))
|
||||
|
||||
return result
|
||||
|
||||
def _combine_results(self, first, second, attr):
|
||||
@ -352,6 +360,7 @@ class NameParser(object):
|
||||
final_result.which_regex += dir_name_result.which_regex
|
||||
|
||||
final_result.show = self._combine_results(file_name_result, dir_name_result, 'show')
|
||||
final_result.quality = self._combine_results(file_name_result, dir_name_result, 'quality')
|
||||
|
||||
# if there's no useful info in it then raise an exception
|
||||
if final_result.season_number == None and not final_result.episode_numbers and final_result.air_date == None and not final_result.series_name:
|
||||
@ -377,7 +386,8 @@ class ParseResult(object):
|
||||
air_date=None,
|
||||
ab_episode_numbers=None,
|
||||
show=None,
|
||||
score=None
|
||||
score=None,
|
||||
quality=None
|
||||
):
|
||||
|
||||
self.original_name = original_name
|
||||
@ -394,6 +404,11 @@ class ParseResult(object):
|
||||
else:
|
||||
self.ab_episode_numbers = ab_episode_numbers
|
||||
|
||||
if not quality:
|
||||
self.quality = common.Quality.UNKNOWN
|
||||
else:
|
||||
self.quality = quality
|
||||
|
||||
self.extra_info = extra_info
|
||||
self.release_group = release_group
|
||||
|
||||
@ -435,6 +450,8 @@ class ParseResult(object):
|
||||
return False
|
||||
if self.score != other.score:
|
||||
return False
|
||||
if self.quality != other.quality:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
@ -59,7 +59,7 @@ normal_regexes = {'normal':[
|
||||
s(?P<season_num>\d+)[. _-]* # S01 and optional separator
|
||||
e(?P<ep_num>\d+) # E02 and separator
|
||||
(([. _-]*e|-) # linking e/- char
|
||||
(?P<extra_ep_num>(?!(1080|720)[pi])\d+))* # additional E03/etc
|
||||
(?P<extra_ep_num>(?!(1080|720|480)[pi])\d+))* # additional E03/etc
|
||||
[. _-]*((?P<extra_info>.+?) # Source_Quality_Etc-
|
||||
((?<![. _-])(?<!WEB) # Make sure this is really the release group
|
||||
-(?P<release_group>[^- ]+))?)?$ # Group
|
||||
@ -76,7 +76,7 @@ normal_regexes = {'normal':[
|
||||
(?P<ep_num>\d+) # 02 and separator
|
||||
(([. _-]*x|-) # linking x/- char
|
||||
(?P<extra_ep_num>
|
||||
(?!(1080|720)[pi])(?!(?<=x)264) # ignore obviously wrong multi-eps
|
||||
(?!(1080|720|480)[pi])(?!(?<=x)264) # ignore obviously wrong multi-eps
|
||||
\d+))* # additional x03/etc
|
||||
[\]. _-]*((?P<extra_info>.+?) # Source_Quality_Etc-
|
||||
((?<![. _-])(?<!WEB) # Make sure this is really the release group
|
||||
@ -136,7 +136,7 @@ normal_regexes = {'normal':[
|
||||
(e(p(isode)?)?|part|pt)[. _-]? # e, ep, episode, or part
|
||||
(?P<ep_num>(\d+|[ivx]+)) # first ep num
|
||||
((([. _-]+(and|&|to)[. _-]+)|-) # and/&/to joiner
|
||||
(?P<extra_ep_num>(?!(1080|720)[pi])(\d+|[ivx]+))[. _-]) # second ep num
|
||||
(?P<extra_ep_num>(?!(1080|720|480)[pi])(\d+|[ivx]+))[. _-]) # second ep num
|
||||
([. _-]*(?P<extra_info>.+?) # Source_Quality_Etc-
|
||||
((?<![. _-])(?<!WEB) # Make sure this is really the release group
|
||||
-(?P<release_group>[^- ]+))?)?$ # Group
|
||||
@ -153,7 +153,7 @@ normal_regexes = {'normal':[
|
||||
(?P<ep_num>(\d+|([ivx]+(?=[. _-])))) # first ep num
|
||||
([. _-]+((and|&|to)[. _-]+)? # and/&/to joiner
|
||||
((e(p(isode)?)?|part|pt)[. _-]?) # e, ep, episode, or part
|
||||
(?P<extra_ep_num>(?!(1080|720)[pi])
|
||||
(?P<extra_ep_num>(?!(1080|720|480)[pi])
|
||||
(\d+|([ivx]+(?=[. _-]))))[. _-])* # second ep num
|
||||
([. _-]*(?P<extra_info>.+?) # Source_Quality_Etc-
|
||||
((?<![. _-])(?<!WEB) # Make sure this is really the release group
|
||||
@ -200,6 +200,20 @@ sports_regexs = {'sports':[
|
||||
-(?P<release_group>[^- ]+))?)?$
|
||||
'''
|
||||
),
|
||||
|
||||
('sports_bare',
|
||||
# Sports.Name.2010.11.23.Source.Quality.Etc-Group
|
||||
# Sports.Name.23rd.Nov.2010.Source.Quality.Etc-Group
|
||||
'''
|
||||
^(?P<series_name>.+?)[. _-]+
|
||||
((?P<sports_event_id>\d{3})[. _-]+)?
|
||||
((?P<sports_event_name>\.+)[. _-]+)?
|
||||
(?P<sports_event_date>(\d{4}[. _-]+\d{1,2}[. _-]+\d{1,2})|(\d{1,2}\w{2}[. _-]+\w+[. _-]+\d{4}))
|
||||
[. _-]*((?P<extra_info>.+?)((?<![. _-])(?<!WEB)
|
||||
-(?P<release_group>[^- ]+))?)?$
|
||||
'''
|
||||
),
|
||||
|
||||
]}
|
||||
|
||||
anime_regexes = {'anime':[
|
||||
@ -208,8 +222,8 @@ anime_regexes = {'anime':[
|
||||
"""
|
||||
^(?:\[(?P<release_group>.+?)\][ ._-]*)
|
||||
(?P<series_name>.+?)[ ._-]+
|
||||
(?P<ep_ab_num>\d{1,3})
|
||||
(-(?P<extra_ab_ep_num>\d{1,3}))?[ ._-]+?
|
||||
(?P<ep_ab_num>(?!(1080|720|480)[pi])\d+)
|
||||
(-(?P<extra_ab_ep_num>(?!(1080|720|480)[pi])\d+))?[ ._-]+?
|
||||
(?:v(?P<version>[0-9]))?
|
||||
(?:[\w\.]*)
|
||||
(?:(?:(?:[\[\(])(?P<extra_info>\d{3,4}[xp]?\d{0,4}[\.\w\s-]*)(?:[\]\)]))|(?:\d{3,4}[xp]))
|
||||
@ -227,8 +241,8 @@ anime_regexes = {'anime':[
|
||||
'''
|
||||
^(\[(?P<release_group>.+?)\][ ._-]*)? # Release Group and separator
|
||||
(?P<series_name>.+?)[ ._-]+ # Show_Name and separator
|
||||
(?P<ep_ab_num>\d{1,3}) # E01
|
||||
(-(?P<extra_ab_ep_num>\d{1,3}))? # E02
|
||||
(?P<ep_ab_num>(?!(1080|720|480)[pi])\d+) # E01
|
||||
(-(?P<extra_ab_ep_num>(?!(1080|720|480)[pi])\d+))? # E02
|
||||
(v(?P<version>[0-9]))? # version
|
||||
[ ._-]+\[(?P<extra_info>\d{3,4}[xp]?\d{0,4}[\.\w\s-]*)\] # Source_Quality_Etc-
|
||||
(\[(?P<crc>\w{8})\])? # CRC
|
||||
@ -242,8 +256,8 @@ anime_regexes = {'anime':[
|
||||
'''
|
||||
^(\[(?P<release_group>.+?)\][ ._-]*)? # Release Group and separator
|
||||
(?P<series_name>.+?)[ ._-]+ # Show_Name and separator
|
||||
(?P<ep_ab_num>\d{1,3}) # E01
|
||||
(-(?P<extra_ab_ep_num>\d{1,3}))? # E02
|
||||
(?P<ep_ab_num>(?!(1080|720|480)[pi])\d+) # E01
|
||||
(-(?P<extra_ab_ep_num>(?!(1080|720|480)[pi])\d+))? # E02
|
||||
(v(?P<version>[0-9]))? # version
|
||||
[ ._-]+\((?P<extra_info>(CX[ ._-]?)?\d{3,4}[xp]?\d{0,4}[\.\w\s-]*)\) # Source_Quality_Etc-
|
||||
(\[(?P<crc>\w{8})\])? # CRC
|
||||
@ -255,8 +269,8 @@ anime_regexes = {'anime':[
|
||||
'''
|
||||
^(\[(?P<release_group>.+?)\][ ._-]*)? # Release Group and separator
|
||||
(?P<series_name>.+?)[ ._-]+ # Show_Name and separator
|
||||
(?P<ep_ab_num>\d{1,3}) # E01
|
||||
(-(?P<extra_ab_ep_num>\d{1,3}))? # E02
|
||||
(?P<ep_ab_num>(?!(1080|720|480)[pi])\d+) # E01
|
||||
(-(?P<extra_ab_ep_num>(?!(1080|720|480)[pi])\d+))? # E02
|
||||
(v(?P<version>[0-9]))? # version
|
||||
[ ._-]+\[(?P<extra_info>\d{3,4}p) # Source_Quality_Etc-
|
||||
(\[(?P<crc>\w{8})\])? # CRC
|
||||
@ -271,8 +285,8 @@ anime_regexes = {'anime':[
|
||||
^(\[(?P<release_group>.+?)\][ ._-]*)? # Release Group and separator
|
||||
(?P<series_name>.+?)[ ._]* # Show_Name and separator
|
||||
([ ._-]+-[ ._-]+[A-Z]+[ ._-]+)?[ ._-]+ # funny stuff, this is sooo nuts ! this will kick me in the butt one day
|
||||
(?P<ep_ab_num>\d{1,3}) # E01
|
||||
(-(?P<extra_ab_ep_num>\d{1,3}))? # E02
|
||||
(?P<ep_ab_num>(?!(1080|720|480)[pi])\d+) # E01
|
||||
(-(?P<extra_ab_ep_num>(?!(1080|720|480)[pi])\d+))? # E02
|
||||
(v(?P<version>[0-9]))? # version
|
||||
([ ._-](\[\w{1,2}\])?\[[a-z][.]?\w{2,4}\])? #codec
|
||||
[ ._-]*\[(?P<extra_info>(\d{3,4}[xp]?\d{0,4})?[\.\w\s-]*)\] # Source_Quality_Etc-
|
||||
@ -301,13 +315,14 @@ anime_regexes = {'anime':[
|
||||
(([. _-]*e|-) # linking e/- char
|
||||
(?P<extra_ep_num>\d+))* # additional E03/etc
|
||||
([ ._-]{2,}|[ ._]+) # if "-" is used to separate at least something else has to be there(->{2,}) "s16e03-04-313-314" would make sens any way
|
||||
(?P<ep_ab_num>\d{1,3}) # absolute number
|
||||
(-(?P<extra_ab_ep_num>\d{1,3}))? # "-" as separator and anditional absolute number, all optinal
|
||||
(?P<ep_ab_num>(?!(1080|720|480)[pi])\d+) # absolute number
|
||||
(-(?P<extra_ab_ep_num>(?!(1080|720|480)[pi])\d+))? # "-" as separator and anditional absolute number, all optinal
|
||||
(v(?P<version>[0-9]))? # the version e.g. "v2"
|
||||
.*?
|
||||
'''
|
||||
|
||||
),
|
||||
|
||||
('anime_and_normal_x',
|
||||
# Bleach - s16e03-04 - 313-314
|
||||
# Bleach.s16e03-04.313-314
|
||||
@ -319,8 +334,8 @@ anime_regexes = {'anime':[
|
||||
(([. _-]*e|-) # linking e/- char
|
||||
(?P<extra_ep_num>\d+))* # additional E03/etc
|
||||
([ ._-]{2,}|[ ._]+) # if "-" is used to separate at least something else has to be there(->{2,}) "s16e03-04-313-314" would make sens any way
|
||||
(?P<ep_ab_num>\d{1,3}) # absolute number
|
||||
(-(?P<extra_ab_ep_num>\d{1,3}))? # "-" as separator and anditional absolute number, all optinal
|
||||
(?P<ep_ab_num>(?!(1080|720|480)[pi])\d+) # absolute number
|
||||
(-(?P<extra_ab_ep_num>(?!(1080|720|480)[pi])\d+))? # "-" as separator and anditional absolute number, all optinal
|
||||
(v(?P<version>[0-9]))? # the version e.g. "v2"
|
||||
.*?
|
||||
'''
|
||||
@ -331,8 +346,8 @@ anime_regexes = {'anime':[
|
||||
# Bleach - 313-314 - s16e03-04
|
||||
'''
|
||||
^(?P<series_name>.+?)[ ._-]+ # start of string and series name and non optinal separator
|
||||
(?P<ep_ab_num>\d{1,3}) # absolute number
|
||||
(-(?P<extra_ab_ep_num>\d{1,3}))? # "-" as separator and anditional absolute number, all optinal
|
||||
(?P<ep_ab_num>(?!(1080|720|480)[pi])\d+) # absolute number
|
||||
(-(?P<extra_ab_ep_num>(?!(1080|720|480)[pi])\d+))? # "-" as separator and anditional absolute number, all optinal
|
||||
(v(?P<version>[0-9]))? # the version e.g. "v2"
|
||||
([ ._-]{2,}|[ ._]+) # if "-" is used to separate at least something else has to be there(->{2,}) "s16e03-04-313-314" would make sens any way
|
||||
[sS](?P<season_num>\d+)[. _-]* # S01 and optional separator
|
||||
@ -346,8 +361,8 @@ anime_regexes = {'anime':[
|
||||
('anime_and_normal_front',
|
||||
# 165.Naruto Shippuuden.s08e014
|
||||
'''
|
||||
^(?P<ep_ab_num>\d{1,3}) # start of string and absolute number
|
||||
(-(?P<extra_ab_ep_num>\d{1,3}))? # "-" as separator and anditional absolute number, all optinal
|
||||
^(?P<ep_ab_num>(?!(1080|720|480)[pi])\d+) # start of string and absolute number
|
||||
(-(?P<extra_ab_ep_num>(?!(1080|720|480)[pi])\d+))? # "-" as separator and anditional absolute number, all optinal
|
||||
(v(?P<version>[0-9]))?[ ._-]+ # the version e.g. "v2"
|
||||
(?P<series_name>.+?)[ ._-]+
|
||||
[sS](?P<season_num>\d+)[. _-]* # S01 and optional separator
|
||||
@ -357,18 +372,19 @@ anime_regexes = {'anime':[
|
||||
.*?
|
||||
'''
|
||||
),
|
||||
|
||||
('anime_ep_name',
|
||||
"""
|
||||
'''
|
||||
^(?:\[(?P<release_group>.+?)\][ ._-]*)
|
||||
(?P<series_name>.+?)[ ._-]+
|
||||
(?P<ep_ab_num>\d{1,3})
|
||||
(-(?P<extra_ab_ep_num>\d{1,3}))?[ ._-]*?
|
||||
(?P<ep_ab_num>(?!(1080|720|480)[pi])\d+)
|
||||
(-(?P<extra_ab_ep_num>(?!(1080|720|480)[pi])\d+))?[ ._-]*?
|
||||
(?:v(?P<version>[0-9])[ ._-]+?)?
|
||||
(?:.+?[ ._-]+?)?
|
||||
\[(?P<extra_info>\w+)\][ ._-]?
|
||||
(?:\[(?P<crc>\w{8})\])?
|
||||
.*?
|
||||
"""
|
||||
'''
|
||||
),
|
||||
|
||||
('anime_bare',
|
||||
@ -377,8 +393,8 @@ anime_regexes = {'anime':[
|
||||
'''
|
||||
^(\[(?P<release_group>.+?)\][ ._-]*)?
|
||||
(?P<series_name>.+?)[ ._-]+ # Show_Name and separator
|
||||
(?P<ep_ab_num>\d{3}) # E01
|
||||
(-(?P<extra_ab_ep_num>\d{3}))? # E02
|
||||
(?P<ep_ab_num>(?!(1080|720|480)[pi])\d+) # E01
|
||||
(-(?P<extra_ab_ep_num>(?!(1080|720|480)[pi])\d+))? # E02
|
||||
(v(?P<version>[0-9]))? # v2
|
||||
.*? # Separator and EOL
|
||||
''')
|
||||
|
@ -40,11 +40,9 @@ name_abd_presets = ('%SN - %A-D - %EN',
|
||||
'%Y/%0M/%S.N.%A.D.%E.N-%RG'
|
||||
)
|
||||
|
||||
name_sports_presets = ('%SN - %Sx%0E - %EN',
|
||||
'%S.N.S%0SE%0E.%E.N',
|
||||
'%Sx%0E - %EN',
|
||||
'S%0SE%0E - %EN',
|
||||
'Season %0S/%S.N.S%0SE%0E.%Q.N-%RG'
|
||||
name_sports_presets = ('%SN - %A-D - %EN',
|
||||
'%S.N.%A.D.%E.N.%Q.N',
|
||||
'%Y/%0M/%S.N.%A.D.%E.N-%RG'
|
||||
)
|
||||
|
||||
class TVShow():
|
||||
@ -98,7 +96,7 @@ class TVEpisode(tv.TVEpisode):
|
||||
self._is_proper = True
|
||||
|
||||
|
||||
def check_force_season_folders(pattern=None, multi=None):
|
||||
def check_force_season_folders(pattern=None, multi=None, anime_type=None):
|
||||
"""
|
||||
Checks if the name can still be parsed if you strip off the folders to determine if we need to force season folders
|
||||
to be enabled or not.
|
||||
@ -108,15 +106,18 @@ def check_force_season_folders(pattern=None, multi=None):
|
||||
if pattern == None:
|
||||
pattern = sickbeard.NAMING_PATTERN
|
||||
|
||||
valid = not validate_name(pattern, None, file_only=True)
|
||||
if anime_type == None:
|
||||
anime_type = sickbeard.NAMING_ANIME
|
||||
|
||||
valid = not validate_name(pattern, None, anime_type, file_only=True)
|
||||
|
||||
if multi != None:
|
||||
valid = valid or not validate_name(pattern, multi, file_only=True)
|
||||
valid = valid or not validate_name(pattern, multi, anime_type, file_only=True)
|
||||
|
||||
return valid
|
||||
|
||||
|
||||
def check_valid_naming(pattern=None, multi=None):
|
||||
def check_valid_naming(pattern=None, multi=None, anime_type=None):
|
||||
"""
|
||||
Checks if the name is can be parsed back to its original form for both single and multi episodes.
|
||||
|
||||
@ -125,12 +126,15 @@ def check_valid_naming(pattern=None, multi=None):
|
||||
if pattern == None:
|
||||
pattern = sickbeard.NAMING_PATTERN
|
||||
|
||||
if anime_type == None:
|
||||
anime_type = sickbeard.NAMING_ANIME
|
||||
|
||||
logger.log(u"Checking whether the pattern " + pattern + " is valid for a single episode", logger.DEBUG)
|
||||
valid = validate_name(pattern, None)
|
||||
valid = validate_name(pattern, None, anime_type)
|
||||
|
||||
if multi != None:
|
||||
logger.log(u"Checking whether the pattern " + pattern + " is valid for a multi episode", logger.DEBUG)
|
||||
valid = valid and validate_name(pattern, multi)
|
||||
valid = valid and validate_name(pattern, multi, anime_type)
|
||||
|
||||
return valid
|
||||
|
||||
@ -163,10 +167,10 @@ def check_valid_sports_naming(pattern=None):
|
||||
|
||||
return valid
|
||||
|
||||
def validate_name(pattern, multi=None, file_only=False, abd=False, sports=False):
|
||||
ep = generate_sample_ep(multi, abd, sports)
|
||||
def validate_name(pattern, multi=None, anime_type=None, file_only=False, abd=False, sports=False):
|
||||
ep = generate_sample_ep(multi, abd, sports, anime_type)
|
||||
|
||||
new_name = ep.formatted_filename(pattern, multi) + '.ext'
|
||||
new_name = ep.formatted_filename(pattern, multi, anime_type) + '.ext'
|
||||
new_path = ep.formatted_dir(pattern, multi)
|
||||
if not file_only:
|
||||
new_name = ek.ek(os.path.join, new_path, new_name)
|
||||
@ -177,7 +181,7 @@ def validate_name(pattern, multi=None, file_only=False, abd=False, sports=False)
|
||||
|
||||
logger.log(u"Trying to parse " + new_name, logger.DEBUG)
|
||||
|
||||
parser = NameParser(True)
|
||||
parser = NameParser(True, showObj=ep.show)
|
||||
|
||||
try:
|
||||
result = parser.parse(new_name)
|
||||
@ -191,18 +195,26 @@ def validate_name(pattern, multi=None, file_only=False, abd=False, sports=False)
|
||||
if result.air_date != ep.airdate:
|
||||
logger.log(u"Air date incorrect in parsed episode, pattern isn't valid", logger.DEBUG)
|
||||
return False
|
||||
elif sports:
|
||||
if result.sports_event_date != ep.airdate:
|
||||
logger.log(u"Sports event date incorrect in parsed episode, pattern isn't valid", logger.DEBUG)
|
||||
return False
|
||||
elif anime_type != 3:
|
||||
if len(result.ab_episode_numbers) and result.ab_episode_numbers != [x.absolute_number for x in [ep] + ep.relatedEps]:
|
||||
logger.log(u"Absolute numbering incorrect in parsed episode, pattern isn't valid", logger.DEBUG)
|
||||
return False
|
||||
else:
|
||||
if result.season_number != ep.season:
|
||||
logger.log(u"Season incorrect in parsed episode, pattern isn't valid", logger.DEBUG)
|
||||
logger.log(u"Season number incorrect in parsed episode, pattern isn't valid", logger.DEBUG)
|
||||
return False
|
||||
if result.episode_numbers != [x.episode for x in [ep] + ep.relatedEps]:
|
||||
logger.log(u"Episode incorrect in parsed episode, pattern isn't valid", logger.DEBUG)
|
||||
logger.log(u"Episode numbering incorrect in parsed episode, pattern isn't valid", logger.DEBUG)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def generate_sample_ep(multi=None, abd=False, sports=False, anime=False):
|
||||
def generate_sample_ep(multi=None, abd=False, sports=False, anime_type=None):
|
||||
# make a fake episode object
|
||||
ep = TVEpisode(2, 3, 3, "Ep Name")
|
||||
|
||||
@ -215,14 +227,27 @@ def generate_sample_ep(multi=None, abd=False, sports=False, anime=False):
|
||||
elif sports:
|
||||
ep._release_name = 'Show.Name.100.Fighter.vs.Fighter.HDTV.XviD-RLSGROUP'
|
||||
ep.show.sports = 1
|
||||
elif anime:
|
||||
ep._release_name = 'Show.Name.S02E03.HDTV.XviD-RLSGROUP'
|
||||
else:
|
||||
if anime_type != 3:
|
||||
ep.show.anime = 1
|
||||
ep._release_name = 'Show.Name.003.HDTV.XviD-RLSGROUP'
|
||||
else:
|
||||
ep._release_name = 'Show.Name.S02E03.HDTV.XviD-RLSGROUP'
|
||||
|
||||
if multi != None:
|
||||
ep._name = "Ep Name (1)"
|
||||
|
||||
if anime_type != 3:
|
||||
ep.show.anime = 1
|
||||
|
||||
ep._release_name = 'Show.Name.003-004.HDTV.XviD-RLSGROUP'
|
||||
|
||||
secondEp = TVEpisode(2, 4, 4, "Ep Name (2)")
|
||||
secondEp._status = Quality.compositeStatus(DOWNLOADED, Quality.HDTV)
|
||||
secondEp._release_name = ep._release_name
|
||||
|
||||
ep.relatedEps.append(secondEp)
|
||||
else:
|
||||
ep._release_name = 'Show.Name.S02E03E04E05.HDTV.XviD-RLSGROUP'
|
||||
|
||||
secondEp = TVEpisode(2, 4, 4, "Ep Name (2)")
|
||||
@ -239,7 +264,7 @@ def generate_sample_ep(multi=None, abd=False, sports=False, anime=False):
|
||||
return ep
|
||||
|
||||
|
||||
def test_name(pattern, multi=None, abd=False, sports=False, anime=False):
|
||||
ep = generate_sample_ep(multi, abd, sports, anime)
|
||||
def test_name(pattern, multi=None, abd=False, sports=False, anime_type=None):
|
||||
ep = generate_sample_ep(multi, abd, sports, anime_type)
|
||||
|
||||
return {'name': ep.formatted_filename(pattern, multi), 'dir': ep.formatted_dir(pattern, multi)}
|
||||
return {'name': ep.formatted_filename(pattern, multi, anime_type), 'dir': ep.formatted_dir(pattern, multi)}
|
@ -498,7 +498,7 @@ class PostProcessor(object):
|
||||
season = parse_result.season_number
|
||||
episodes = parse_result.episode_numbers
|
||||
|
||||
to_return = (parse_result.show, season, episodes, None)
|
||||
to_return = (parse_result.show, season, episodes, parse_result.quality)
|
||||
|
||||
self._finalize(parse_result)
|
||||
return to_return
|
||||
|
@ -284,7 +284,7 @@ class GenericProvider:
|
||||
logger.log(u"Unable to parse the filename " + title + " into a valid episode", logger.WARNING)
|
||||
continue
|
||||
|
||||
quality = self.getQuality(item, parse_result.is_anime)
|
||||
quality = parse_result.quality
|
||||
|
||||
if not (self.show.air_by_date or self.show.sports):
|
||||
if search_mode == 'sponly' and len(parse_result.episode_numbers):
|
||||
|
@ -99,8 +99,7 @@ def get_scene_absolute_numbering(indexer_id, indexer, absolute_number, fallback_
|
||||
(so the return values will always be set)
|
||||
|
||||
@param indexer_id: int
|
||||
@param season: int
|
||||
@param episode: int
|
||||
@param absolute_number: int
|
||||
@param fallback_to_xem: bool If set (the default), check xem for matches if there is no local scene numbering
|
||||
@return: (int, int) a tuple with (season, episode)
|
||||
"""
|
||||
@ -258,9 +257,8 @@ def find_xem_absolute_numbering(indexer_id, indexer, absolute_number):
|
||||
Refreshes/Loads as needed.
|
||||
|
||||
@param indexer_id: int
|
||||
@param season: int
|
||||
@param episode: int
|
||||
@return: (int, int) a tuple of scene_season, scene_episode, or None if there is no special mapping.
|
||||
@param absolute_number: int
|
||||
@return: int
|
||||
"""
|
||||
if indexer_id is None or absolute_number is None:
|
||||
return absolute_number
|
||||
@ -313,9 +311,8 @@ def get_indexer_absolute_numbering_for_xem(indexer_id, indexer, sceneAbsoluteNum
|
||||
Reverse of find_xem_numbering: lookup a tvdb season and episode using scene numbering
|
||||
|
||||
@param indexer_id: int
|
||||
@param sceneSeason: int
|
||||
@param sceneEpisode: int
|
||||
@return: (int, int) a tuple of (season, episode)
|
||||
@param sceneAbsoluteNumber: int
|
||||
@return: int
|
||||
"""
|
||||
if indexer_id is None or sceneAbsoluteNumber is None:
|
||||
return sceneAbsoluteNumber
|
||||
|
@ -52,6 +52,7 @@ from common import DOWNLOADED, SNATCHED, SNATCHED_PROPER, SNATCHED_BEST, ARCHIVE
|
||||
from common import NAMING_DUPLICATE, NAMING_EXTEND, NAMING_LIMITED_EXTEND, NAMING_SEPARATED_REPEAT, \
|
||||
NAMING_LIMITED_EXTEND_E_PREFIXED
|
||||
|
||||
|
||||
class TVShow(object):
|
||||
def __init__(self, indexer, indexerid, lang=""):
|
||||
|
||||
@ -200,7 +201,7 @@ class TVShow(object):
|
||||
ep = None
|
||||
|
||||
# if we get an anime get the real season and episode
|
||||
if self.is_anime and not self.is_scene and absolute_number and not season and not episode:
|
||||
if self.is_anime and absolute_number and not season and not episode:
|
||||
myDB = db.DBConnection()
|
||||
sql = "SELECT * FROM tv_episodes WHERE showid = ? and absolute_number = ? and season != 0"
|
||||
sqlResults = myDB.select(sql, [self.indexerid, absolute_number])
|
||||
@ -891,21 +892,11 @@ class TVShow(object):
|
||||
imdb_info[key] = imdbTv.get(key.replace('_', ' '))
|
||||
|
||||
# Filter only the value
|
||||
if imdb_info['runtimes']:
|
||||
imdb_info['runtimes'] = re.search('\d+', imdb_info['runtimes']).group(0)
|
||||
else:
|
||||
imdb_info['runtimes'] = self.runtime
|
||||
|
||||
if imdb_info['akas']:
|
||||
imdb_info['akas'] = '|'.join(imdb_info['akas'])
|
||||
else:
|
||||
imdb_info['akas'] = ''
|
||||
imdb_info['runtimes'] = re.search('\d+', imdb_info['runtimes']).group(0) or self.runtime
|
||||
imdb_info['akas'] = '|'.join(imdb_info['akas']) or ''
|
||||
|
||||
# Join all genres in a string
|
||||
if imdb_info['genres']:
|
||||
imdb_info['genres'] = '|'.join(imdb_info['genres'])
|
||||
else:
|
||||
imdb_info['genres'] = ''
|
||||
imdb_info['genres'] = '|'.join(imdb_info['genres']) or ''
|
||||
|
||||
# Get only the production country certificate if any
|
||||
if imdb_info['certificates'] and imdb_info['countries']:
|
||||
@ -921,11 +912,7 @@ class TVShow(object):
|
||||
else:
|
||||
imdb_info['certificates'] = ''
|
||||
|
||||
if imdb_info['country_codes']:
|
||||
imdb_info['country_codes'] = '|'.join(imdb_info['country_codes'])
|
||||
else:
|
||||
imdb_info['country_codes'] = ''
|
||||
|
||||
imdb_info['country_codes'] = '|'.join(imdb_info['country_codes']) or ''
|
||||
imdb_info['last_update'] = datetime.date.today().toordinal()
|
||||
|
||||
# Rename dict keys without spaces for DB upsert
|
||||
@ -1513,13 +1500,13 @@ class TVEpisode(object):
|
||||
|
||||
# does one now a better way to test for NULL in the db field ?
|
||||
if sqlResults[0]["scene_season"]:
|
||||
self.scene_season = int(sqlResults[0]["scene_season"])
|
||||
self.scene_season = int(sqlResults[0]["scene_season"] or 0)
|
||||
|
||||
if sqlResults[0]["scene_episode"]:
|
||||
self.scene_episode = int(sqlResults[0]["scene_episode"])
|
||||
self.scene_episode = int(sqlResults[0]["scene_episode"] or 0)
|
||||
|
||||
if sqlResults[0]["scene_absolute_number"]:
|
||||
self.scene_absolute_number = int(sqlResults[0]["scene_absolute_number"])
|
||||
self.scene_absolute_number = int(sqlResults[0]["scene_absolute_number"] or 0)
|
||||
|
||||
if sqlResults[0]["release_name"] is not None:
|
||||
self.release_name = sqlResults[0]["release_name"]
|
||||
@ -1855,7 +1842,8 @@ class TVEpisode(object):
|
||||
"location = ?, file_size = ?, release_name = ?, is_proper = ?, showid = ?, season = ?, episode = ?, "
|
||||
"absolute_number = ? WHERE episode_id = ?",
|
||||
[self.indexerid, self.indexer, self.name, self.description, ",".join([sub for sub in self.subtitles]),
|
||||
self.subtitles_searchcount, self.subtitles_lastsearch, self.airdate.toordinal(), self.hasnfo, self.hastbn,
|
||||
self.subtitles_searchcount, self.subtitles_lastsearch, self.airdate.toordinal(), self.hasnfo,
|
||||
self.hastbn,
|
||||
self.status, self.location, self.file_size, self.release_name, self.is_proper, self.show.indexerid,
|
||||
self.season, self.episode, self.absolute_number, epID]]
|
||||
else:
|
||||
@ -1863,10 +1851,12 @@ class TVEpisode(object):
|
||||
return [
|
||||
"INSERT OR IGNORE INTO tv_episodes (episode_id, indexerid, indexer, name, description, subtitles, subtitles_searchcount, subtitles_lastsearch, airdate, hasnfo, hastbn, status, location, file_size, release_name, is_proper, showid, season, episode, absolute_number) VALUES "
|
||||
"((SELECT episode_id FROM tv_episodes WHERE showid = ? AND season = ? AND episode = ?),?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?);",
|
||||
[self.show.indexerid, self.season, self.episode, self.indexerid, self.indexer, self.name, self.description,
|
||||
[self.show.indexerid, self.season, self.episode, self.indexerid, self.indexer, self.name,
|
||||
self.description,
|
||||
",".join([sub for sub in self.subtitles]), self.subtitles_searchcount, self.subtitles_lastsearch,
|
||||
self.airdate.toordinal(), self.hasnfo, self.hastbn, self.status, self.location, self.file_size,
|
||||
self.release_name, self.is_proper, self.show.indexerid, self.season, self.episode, self.absolute_number]]
|
||||
self.release_name, self.is_proper, self.show.indexerid, self.season, self.episode,
|
||||
self.absolute_number]]
|
||||
|
||||
def saveToDB(self, forceSave=False):
|
||||
"""
|
||||
@ -2054,7 +2044,7 @@ class TVEpisode(object):
|
||||
'%XE': str(self.scene_episode),
|
||||
'%0XE': '%02d' % self.scene_episode,
|
||||
'%AB': '%(#)03d' % {'#': self.absolute_number},
|
||||
'%XA': '%(#)03d' % {'#': self.scene_absolute_number},
|
||||
'%XAB': '%(#)03d' % {'#': self.scene_absolute_number},
|
||||
'%RN': release_name(self.release_name),
|
||||
'%RG': release_group(self.release_name),
|
||||
'%AD': str(self.airdate).replace('-', ' '),
|
||||
@ -2084,7 +2074,7 @@ class TVEpisode(object):
|
||||
|
||||
return result_name
|
||||
|
||||
def _format_pattern(self, pattern=None, multi=None):
|
||||
def _format_pattern(self, pattern=None, multi=None, anime_type=None):
|
||||
"""
|
||||
Manipulates an episode naming pattern and then fills the template in
|
||||
"""
|
||||
@ -2095,6 +2085,9 @@ class TVEpisode(object):
|
||||
if multi == None:
|
||||
multi = sickbeard.NAMING_MULTI_EP
|
||||
|
||||
if anime_type == None:
|
||||
anime_type = sickbeard.NAMING_ANIME
|
||||
|
||||
replace_map = self._replace_map()
|
||||
|
||||
result_name = pattern
|
||||
@ -2104,9 +2097,9 @@ class TVEpisode(object):
|
||||
if self.show.air_by_date or self.show.sports:
|
||||
result_name = result_name.replace('%RN', '%S.N.%A.D.%E.N-SiCKRAGE')
|
||||
result_name = result_name.replace('%rn', '%s.n.%A.D.%e.n-sickrage')
|
||||
elif self.show.is_anime:
|
||||
result_name = result_name.replace('%RN', '%S.N.%AN.%E.N-SiCKRAGE')
|
||||
result_name = result_name.replace('%rn', '%s.n.%an.%e.n-sickrage')
|
||||
elif self.show.anime:
|
||||
result_name = result_name.replace('%RN', '%S.N.%AB.%E.N-SiCKRAGE')
|
||||
result_name = result_name.replace('%rn', '%s.n.%ab.%e.n-sickrage')
|
||||
else:
|
||||
result_name = result_name.replace('%RN', '%S.N.S%0SE%0E.%E.N-SiCKRAGE')
|
||||
result_name = result_name.replace('%rn', '%s.n.s%0se%0e.%e.n-sickrage')
|
||||
@ -2195,11 +2188,34 @@ class TVEpisode(object):
|
||||
|
||||
ep_string += other_ep._format_string(ep_format.upper(), other_ep._replace_map())
|
||||
|
||||
if season_ep_match:
|
||||
if self.show.anime and anime_type != 3:
|
||||
if self.absolute_number == 0:
|
||||
curAbsolute_number = self.episode
|
||||
else:
|
||||
curAbsolute_number = self.absolute_number
|
||||
|
||||
if self.season != 0: # dont set absolute numbers if we are on specials !
|
||||
if anime_type == 1: # this crazy person wants both ! (note: +=)
|
||||
ep_string += sep + "%(#)03d" % {
|
||||
"#": curAbsolute_number}
|
||||
elif anime_type == 2: # total anime freak only need the absolute number ! (note: =)
|
||||
ep_string = "%(#)03d" % {"#": curAbsolute_number}
|
||||
|
||||
for relEp in self.relatedEps:
|
||||
if relEp.absolute_number != 0:
|
||||
ep_string += '-' + "%(#)03d" % {"#": relEp.absolute_number}
|
||||
else:
|
||||
ep_string += '-' + "%(#)03d" % {"#": relEp.episode}
|
||||
|
||||
regex_replacement = None
|
||||
if anime_type == 2:
|
||||
regex_replacement = r'\g<pre_sep>' + ep_string + r'\g<post_sep>'
|
||||
elif season_ep_match:
|
||||
regex_replacement = r'\g<pre_sep>\g<2>\g<3>' + ep_string + r'\g<post_sep>'
|
||||
elif ep_only_match:
|
||||
regex_replacement = ep_string
|
||||
|
||||
if regex_replacement:
|
||||
# fill out the template for this piece and then insert this piece into the actual pattern
|
||||
cur_name_group_result = re.sub('(?i)(?x)' + regex_used, regex_replacement, cur_name_group)
|
||||
# cur_name_group_result = cur_name_group.replace(ep_format, ep_string)
|
||||
@ -2251,7 +2267,7 @@ class TVEpisode(object):
|
||||
else:
|
||||
return self._format_pattern(os.sep.join(name_groups[:-1]), multi)
|
||||
|
||||
def formatted_filename(self, pattern=None, multi=None):
|
||||
def formatted_filename(self, pattern=None, multi=None, anime_type=None):
|
||||
"""
|
||||
Just the filename of the episode, formatted based on the naming settings
|
||||
"""
|
||||
@ -2268,7 +2284,7 @@ class TVEpisode(object):
|
||||
# split off the dirs only, if they exist
|
||||
name_groups = re.split(r'[\\/]', pattern)
|
||||
|
||||
return self._format_pattern(name_groups[-1], multi)
|
||||
return self._format_pattern(name_groups[-1], multi, anime_type)
|
||||
|
||||
def rename(self):
|
||||
"""
|
||||
|
@ -28,6 +28,7 @@ import datetime
|
||||
import random
|
||||
|
||||
from Cheetah.Template import Template
|
||||
from cherrypy.lib.static import serve_fileobj
|
||||
import cherrypy
|
||||
import cherrypy.lib
|
||||
import cherrypy.lib.cptools
|
||||
@ -82,8 +83,10 @@ def _handle_reverse_proxy():
|
||||
if sickbeard.HANDLE_REVERSE_PROXY:
|
||||
cherrypy.lib.cptools.proxy()
|
||||
|
||||
|
||||
cherrypy.tools.handle_reverse_proxy = cherrypy.Tool('before_handler', _handle_reverse_proxy)
|
||||
|
||||
|
||||
class PageTemplate(Template):
|
||||
def __init__(self, *args, **KWs):
|
||||
KWs['file'] = os.path.join(sickbeard.PROG_DIR, "gui/" + sickbeard.GUI_NAME + "/interfaces/default/",
|
||||
@ -638,7 +641,8 @@ class Manage:
|
||||
return _munge(t)
|
||||
|
||||
@cherrypy.expose
|
||||
def massEditSubmit(self, paused=None, anime=None, scene=None, flatten_folders=None, quality_preset=False, subtitles=None,
|
||||
def massEditSubmit(self, paused=None, anime=None, scene=None, flatten_folders=None, quality_preset=False,
|
||||
subtitles=None,
|
||||
anyQualities=[], bestQualities=[], toEdit=None, *args, **kwargs):
|
||||
|
||||
dir_map = {}
|
||||
@ -1267,7 +1271,6 @@ class ConfigPostProcessing:
|
||||
sickbeard.NAMING_CUSTOM_ABD = config.checkbox_to_value(naming_custom_abd)
|
||||
sickbeard.NAMING_CUSTOM_SPORTS = config.checkbox_to_value(naming_custom_sports)
|
||||
sickbeard.NAMING_STRIP_YEAR = config.checkbox_to_value(naming_strip_year)
|
||||
sickbeard.NAMING_ANIME = config.checkbox_to_value(naming_anime)
|
||||
sickbeard.USE_FAILED_DOWNLOADS = config.checkbox_to_value(use_failed_downloads)
|
||||
sickbeard.DELETE_FAILED = config.checkbox_to_value(delete_failed)
|
||||
sickbeard.SKIP_REMOVED_FILES = config.checkbox_to_value(skip_removed_files)
|
||||
@ -1288,10 +1291,14 @@ class ConfigPostProcessing:
|
||||
sickbeard.metadata_provider_dict['TIVO'].set_config(sickbeard.METADATA_TIVO)
|
||||
sickbeard.metadata_provider_dict['Mede8er'].set_config(sickbeard.METADATA_MEDE8ER)
|
||||
|
||||
if self.isNamingValid(naming_pattern, naming_multi_ep) != "invalid":
|
||||
if self.isNamingValid(naming_pattern, naming_multi_ep, anime_type=naming_anime) != "invalid":
|
||||
sickbeard.NAMING_PATTERN = naming_pattern
|
||||
sickbeard.NAMING_MULTI_EP = int(naming_multi_ep)
|
||||
sickbeard.NAMING_ANIME = int(naming_anime)
|
||||
sickbeard.NAMING_FORCE_FOLDERS = naming.check_force_season_folders()
|
||||
else:
|
||||
if int(naming_anime) in [1, 2]:
|
||||
results.append("You tried saving an invalid anime naming config, not saving your naming settings")
|
||||
else:
|
||||
results.append("You tried saving an invalid naming config, not saving your naming settings")
|
||||
|
||||
@ -1320,22 +1327,31 @@ class ConfigPostProcessing:
|
||||
redirect("/config/postProcessing/")
|
||||
|
||||
@cherrypy.expose
|
||||
def testNaming(self, pattern=None, multi=None, abd=False, sports=False, anime=None):
|
||||
def testNaming(self, pattern=None, multi=None, abd=False, sports=False, anime_type=None):
|
||||
|
||||
if multi is not None:
|
||||
multi = int(multi)
|
||||
|
||||
result = naming.test_name(pattern, multi, abd, sports, anime)
|
||||
if anime_type is not None:
|
||||
anime_type = int(anime_type)
|
||||
|
||||
result = naming.test_name(pattern, multi, abd, sports, anime_type)
|
||||
|
||||
result = ek.ek(os.path.join, result['dir'], result['name'])
|
||||
|
||||
return result
|
||||
|
||||
@cherrypy.expose
|
||||
def isNamingValid(self, pattern=None, multi=None, abd=False, sports=False):
|
||||
def isNamingValid(self, pattern=None, multi=None, abd=False, sports=False, anime_type=None):
|
||||
if pattern is None:
|
||||
return "invalid"
|
||||
|
||||
if multi is not None:
|
||||
multi = int(multi)
|
||||
|
||||
if anime_type is not None:
|
||||
anime_type = int(anime_type)
|
||||
|
||||
# air by date shows just need one check, we don't need to worry about season folders
|
||||
if abd:
|
||||
is_valid = naming.check_valid_abd_naming(pattern)
|
||||
@ -1348,10 +1364,10 @@ class ConfigPostProcessing:
|
||||
|
||||
else:
|
||||
# check validity of single and multi ep cases for the whole path
|
||||
is_valid = naming.check_valid_naming(pattern, multi)
|
||||
is_valid = naming.check_valid_naming(pattern, multi, anime_type)
|
||||
|
||||
# check validity of single and multi ep cases for only the file name
|
||||
require_season_folders = naming.check_force_season_folders(pattern, multi)
|
||||
require_season_folders = naming.check_force_season_folders(pattern, multi, anime_type)
|
||||
|
||||
if is_valid and not require_season_folders:
|
||||
return "valid"
|
||||
@ -1584,7 +1600,8 @@ class ConfigProviders:
|
||||
curProvider, curEnabled = curProviderStr.split(':')
|
||||
curEnabled = config.to_int(curEnabled)
|
||||
|
||||
curProvObj = [x for x in sickbeard.providers.sortedProviderList() if x.getID() == curProvider and hasattr(x, 'enabled')]
|
||||
curProvObj = [x for x in sickbeard.providers.sortedProviderList() if
|
||||
x.getID() == curProvider and hasattr(x, 'enabled')]
|
||||
if curProvObj:
|
||||
curProvObj[0].enabled = bool(curEnabled)
|
||||
|
||||
@ -2013,8 +2030,8 @@ class ConfigSubtitles:
|
||||
|
||||
redirect("/config/subtitles/")
|
||||
|
||||
class ConfigAnime:
|
||||
|
||||
class ConfigAnime:
|
||||
@cherrypy.expose
|
||||
def index(self):
|
||||
|
||||
@ -2023,7 +2040,8 @@ class ConfigAnime:
|
||||
return _munge(t)
|
||||
|
||||
@cherrypy.expose
|
||||
def saveAnime(self, use_anidb=None, anidb_username=None, anidb_password=None, anidb_use_mylist=None, split_home=None):
|
||||
def saveAnime(self, use_anidb=None, anidb_username=None, anidb_password=None, anidb_use_mylist=None,
|
||||
split_home=None):
|
||||
|
||||
results = []
|
||||
|
||||
@ -2060,6 +2078,7 @@ class ConfigAnime:
|
||||
|
||||
redirect("/config/anime/")
|
||||
|
||||
|
||||
class Config:
|
||||
@cherrypy.expose
|
||||
def index(self):
|
||||
@ -2082,6 +2101,7 @@ class Config:
|
||||
|
||||
anime = ConfigAnime()
|
||||
|
||||
|
||||
def haveXBMC():
|
||||
return sickbeard.USE_XBMC and sickbeard.XBMC_UPDATE_LIBRARY
|
||||
|
||||
@ -2179,6 +2199,8 @@ class NewHomeAddShows:
|
||||
if not lang or lang == 'null':
|
||||
lang = "en"
|
||||
|
||||
search_term = search_term.encode('utf-8')
|
||||
|
||||
results = {}
|
||||
final_results = []
|
||||
|
||||
@ -2199,8 +2221,7 @@ class NewHomeAddShows:
|
||||
|
||||
map(final_results.extend,
|
||||
([[sickbeard.indexerApi(id).name, id, sickbeard.indexerApi(id).config["show_url"], int(show['id']),
|
||||
show['seriesname'], show['firstaired']] for show in shows] for id, shows in
|
||||
results.items()))
|
||||
show['seriesname'], show['firstaired']] for show in shows] for id, shows in results.items()))
|
||||
|
||||
lang_id = sickbeard.indexerApi().config['langabbv_to_id'][lang]
|
||||
return json.dumps({'results': final_results, 'langid': lang_id})
|
||||
@ -2440,7 +2461,8 @@ class NewHomeAddShows:
|
||||
|
||||
# add the show
|
||||
sickbeard.showQueueScheduler.action.addShow(indexer, indexer_id, show_dir, int(defaultStatus), newQuality,
|
||||
flatten_folders, subtitles, indexerLang, anime, scene) # @UndefinedVariable
|
||||
flatten_folders, subtitles, indexerLang, anime,
|
||||
scene) # @UndefinedVariable
|
||||
ui.notifications.message('Show added', 'Adding the specified show into ' + show_dir)
|
||||
|
||||
return finishAddShow()
|
||||
@ -2625,7 +2647,6 @@ class Home:
|
||||
def index(self):
|
||||
|
||||
t = PageTemplate(file="home.tmpl")
|
||||
|
||||
if sickbeard.ANIME_SPLIT_HOME:
|
||||
shows = []
|
||||
anime = []
|
||||
@ -3074,7 +3095,8 @@ class Home:
|
||||
t.sortedShowLists = [["Shows", sorted(shows, lambda x, y: cmp(titler(x.name), titler(y.name)))],
|
||||
["Anime", sorted(anime, lambda x, y: cmp(titler(x.name), titler(y.name)))]]
|
||||
else:
|
||||
t.sortedShowLists = [["Shows",sorted(sickbeard.showList, lambda x, y: cmp(titler(x.name), titler(y.name)))]]
|
||||
t.sortedShowLists = [
|
||||
["Shows", sorted(sickbeard.showList, lambda x, y: cmp(titler(x.name), titler(y.name)))]]
|
||||
|
||||
t.bwl = BlackAndWhiteList(showObj.indexerid)
|
||||
|
||||
@ -3746,7 +3768,8 @@ class Home:
|
||||
return json.dumps({'result': status, 'subtitles': ','.join([x for x in ep_obj.subtitles])})
|
||||
|
||||
@cherrypy.expose
|
||||
def setSceneNumbering(self, show, indexer, forSeason=None, forEpisode=None, forAbsolute=None, sceneSeason=None, sceneEpisode=None, sceneAbsolute=None):
|
||||
def setSceneNumbering(self, show, indexer, forSeason=None, forEpisode=None, forAbsolute=None, sceneSeason=None,
|
||||
sceneEpisode=None, sceneAbsolute=None):
|
||||
|
||||
# sanitize:
|
||||
if forSeason in ['null', '']: forSeason = None
|
||||
@ -3800,7 +3823,8 @@ class Home:
|
||||
if sceneSeason is not None: sceneSeason = int(sceneSeason)
|
||||
if sceneEpisode is not None: sceneEpisode = int(sceneEpisode)
|
||||
|
||||
set_scene_numbering(show, indexer, season=forSeason, episode=forEpisode, sceneSeason=sceneSeason, sceneEpisode=sceneEpisode)
|
||||
set_scene_numbering(show, indexer, season=forSeason, episode=forEpisode, sceneSeason=sceneSeason,
|
||||
sceneEpisode=sceneEpisode)
|
||||
|
||||
if showObj.is_anime:
|
||||
sn = get_scene_absolute_numbering(show, indexer, forAbsolute)
|
||||
|
Loading…
Reference in New Issue
Block a user