Added sports feature, acts just like air_by_date except allows us to control the date pattern to match events that air_by_date could not.

Custome sports naming patterns can be set now as well.

Fixed issues with FINDPROPERS.

Fixed issues with session connections.

Cleaned up code.
This commit is contained in:
echel0n 2014-04-28 02:15:29 -07:00
parent d4263e1b03
commit 5e38813a73
49 changed files with 805 additions and 288 deletions

View file

@ -627,6 +627,183 @@
</div><!-- /naming_abd_different -->
<div class="field-pair clearfix">
<input type="checkbox" class="enabler" id="naming_custom_sports" name="naming_custom_sports" #if $sickbeard.NAMING_CUSTOM_SPORTS then "checked=\"checked\"" else ""#/>
<label class="clearfix" for="naming_custom_sports">
<span class="component-title">Custom Sports</span>
<span class="component-desc">Name Sports shows differently than regular shows?</span>
</label>
</div>
<div id="content_naming_custom_sports">
<div class="field-pair">
<label class="nocheck clearfix" for="name_sports_presets">
<span class="component-title">Name Pattern:</span>
<span class="component-desc">
<select id="name_sports_presets">
#set is_sports_custom = True
#for $cur_preset in $naming.name_sports_presets:
#set $tmp = $naming.test_name($cur_preset)
#if $cur_preset == $sickbeard.NAMING_SPORTS_PATTERN:
#set is_sports_custom = False
#end if
<option id="$cur_preset" #if $cur_preset == $sickbeard.NAMING_SPORTS_PATTERN then "selected=\"selected\"" else ""#>$os.path.join($tmp['dir'], $tmp['name'])</option>
#end for
<option id="$sickbeard.NAMING_SPORTS_PATTERN" #if $is_sports_custom then "selected=\"selected\"" else ""#>Custom...</option>
</select>
</span>
</label>
</div>
<div id="naming_sports_custom">
<div class="field-pair clearfix" style="padding-top: 0;">
<label class="nocheck clearfix">
<span class="component-title">
&nbsp;
</span>
<span class="component-desc">
<input type="text" size="45" name="naming_sports_pattern" id="naming_sports_pattern" class="custom-pattern" value="$sickbeard.NAMING_SPORTS_PATTERN" style="font-size: 13px; height: 18px; margin-top: -8px"/>
<img src="$sbRoot/images/legend16.png" width="16" height="16" alt="[Toggle Key]" id="show_naming_sports_key" title="Toggle sports Naming Legend" style="padding: 0 0 0 3px; margin-top: -2px;" />
</span>
</label>
</div>
<div id="naming_sports_key" class="nocheck clearfix" style="display: none;">
<table class="Key">
<thead>
<tr>
<th class="align-right">Meaning</th>
<th>Pattern</th>
<th width="60%">Result</th>
</tr>
</thead>
<tfoot>
<tr>
<th colspan="3">Use lower case if you want lower case names (eg. %sn, %e.n, %q_n etc)</th>
</tr>
</tfoot>
<tbody>
<tr>
<td class="align-right"><b>Show Name:</b></td>
<td>%SN</td>
<td>Show Name</td>
</tr>
<tr class="even">
<td>&nbsp;</td>
<td>%S.N</td>
<td>Show.Name</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>%S_N</td>
<td>Show_Name</td>
</tr>
<tr class="even">
<td class="align-right"><b>Sports:</b></td>
<td>%AD</td>
<td>9th Mar 2010</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>%A.D</td>
<td>9th.Mar.2010</td>
</tr>
<tr class="even">
<td>&nbsp;</td>
<td>%A_D</td>
<td>9th_Mar_2010</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>%A-D</td>
<td>9th-Mar-2010</td>
</tr>
<tr class="even">
<td class="align-right"><b>Episode Name:</b></td>
<td>%EN</td>
<td>Episode Name</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>%E.N</td>
<td>Episode.Name</td>
</tr>
<tr class="even">
<td>&nbsp;</td>
<td>%E_N</td>
<td>Episode_Name</td>
</tr>
<tr>
<td class="align-right"><b>Quality:</b></td>
<td>%QN</td>
<td>720p BluRay</td>
</tr>
<tr class="even">
<td>&nbsp;</td>
<td>%Q.N</td>
<td>720p.BluRay</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>%Q_N</td>
<td>720p_BluRay</td>
</tr>
<tr class="even">
<td class="align-right"><b>Year:</b></td>
<td>%Y</td>
<td>2010</td>
</tr>
<tr>
<td class="align-right"><b>Month:</b></td>
<td>%M</td>
<td>3</td>
</tr>
<tr class="even">
<td class="align-right">&nbsp;</td>
<td>%0M</td>
<td>03</td>
</tr>
<tr>
<td class="align-right"><b>Day:</b></td>
<td>%D</td>
<td>9</td>
</tr>
<tr class="even">
<td class="align-right">&nbsp;</td>
<td>%0D</td>
<td>09</td>
</tr>
<tr>
<td class="align-right"><i class="icon-info-sign" title="Multi-EP style is ignored"></i> <b>Release Name:</b></td>
<td>%RN</td>
<td>Show.Name.9th.Mar.2010.HDTV.XviD-RLSGROUP</td>
</tr>
<tr class="even">
<td class="align-right"><i class="icon-info-sign" title="'SiCKBEARD' is used in place of RLSGROUP if it could not be properly detected"></i> <b>Release Group:</b></td>
<td>%RG</td>
<td>RLSGROUP</td>
</tr>
<tr>
<td class="align-right"><i class="icon-info-sign" title="If episode is proper/repack add 'proper' to name."></i> <b>Release Type:</b></td>
<td>%RT</td>
<td>PROPER</td>
</tr>
</tbody>
</table>
<br/>
</div>
</div><!-- /naming_sports_custom -->
<div id="naming_sports_example_div">
<h2>Sample:</h2>
<div class="example">
<span class="jumbo" id="naming_sports_example">&nbsp;</span>
</div>
<br/>
</div>
</div><!-- /naming_sports_different -->
<div class="clearfix"></div>
<input type="submit" class="btn config_submitter" value="Save Changes" /><br/>

View file

@ -154,6 +154,7 @@
<tr><td class="showLegend">Flat Folders: </td><td><img src="$sbRoot/images/#if $show.flatten_folders == 1 or $sickbeard.NAMING_FORCE_FOLDERS then "yes16.png\" alt=\"Y" else "no16.png\" alt=\"N"#" width="16" height="16" /></td></tr>
<tr><td class="showLegend">Paused: </td><td><img src="$sbRoot/images/#if int($show.paused) == 1 then "yes16.png\" alt=\"Y" else "no16.png\" alt=\"N"#" width="16" height="16" /></td></tr>
<tr><td class="showLegend">Air-by-Date: </td><td><img src="$sbRoot/images/#if int($show.air_by_date) == 1 then "yes16.png\" alt=\"Y" else "no16.png\" alt=\"N"#" width="16" height="16" /></td></tr>
<tr><td class="showLegend">Sports: </td><td><img src="$sbRoot/images/#if int($show.sports) == 1 then "yes16.png\" alt=\"Y" else "no16.png\" alt=\"N"#" width="16" height="16" /></td></tr>
<tr><td class="showLegend">DVD Order: </td><td><img src="$sbRoot/images/#if int($show.dvdorder) == 1 then "yes16.png\" alt=\"Y" else "no16.png\" alt=\"N"#" width="16" height="16" /></td></tr>
#if $bestQualities
<tr><td class="showLegend">Archive First Match: </td><td><img src="$sbRoot/images/#if int($show.archive_firstmatch) == 1 then "yes16.png\" alt=\"Y" else "no16.png\" alt=\"N"#" width="16" height="16" /></td></tr>
@ -239,7 +240,7 @@
<td align="center"><img src="$sbRoot/images/#if $epResult["hastbn"] == 1 then "tbn.gif\" alt=\"Y" else "tbn-no.gif\" alt=\"N"#" width="23" height="11" /></td>
<td align="center">$epResult["episode"]</td>
<td align="center">
#if int($show.air_by_date) != 1
#if int($show.air_by_date) != 1 and int($show.sports) != 1
#if (epResult["season"], epResult["episode"]) in $xem_numbering:
#set ($dfltSeas, $dfltEpis) = $xem_numbering[(epResult["season"], epResult["episode"])]
#else

View file

@ -108,6 +108,10 @@ This <b>DOES NOT</b> allow Sick Beard to download non-english TV episodes!<br />
<input type="checkbox" name="air_by_date" #if $show.air_by_date == 1 then "checked=\"checked\"" else ""# /><br />
(check this if the show is released as Show.03.02.2010 rather than Show.S02E03)
<br /><br />
<b>Sports: </b>
<input type="checkbox" name="sports" #if $show.sports == 1 then "checked=\"checked\"" else ""# /><br />
(check this if the show is a sporting or MMA event)
<br /><br />
<b>DVD Order: </b>
<input type="checkbox" name="dvdorder" #if $show.dvdorder == 1 then "checked=\"checked\"" else ""# /><br/>
(check this if you wish to use the DVD order instead of the Airing order)

View file

@ -23,6 +23,8 @@
<blockquote style="margin-bottom: 0; color: #3A87AD;">
#if int($show.air_by_date) == 1 and $sickbeard.NAMING_CUSTOM_ABD:
$sickbeard.NAMING_ABD_PATTERN
#elif int($show.sports) == 1 and $sickbeard.NAMING_CUSTOM_SPORTS:
$sickbeard.NAMING_SPORTS_PATTERN
#else
$sickbeard.NAMING_PATTERN
#end if

View file

@ -119,6 +119,47 @@ $(document).ready(function () {
}
function fill_sports_examples() {
var pattern = $('#naming_sports_pattern').val();
$.get(sbRoot + '/config/postProcessing/testNaming', {pattern: pattern, sports: 'True'},
function (data) {
if (data) {
$('#naming_sports_example').text(data + '.ext');
$('#naming_sports_example_div').show();
} else {
$('#naming_sports_example_div').hide();
}
});
$.get(sbRoot + '/config/postProcessing/isNamingValid', {pattern: pattern, sports: 'True'},
function (data) {
if (data == "invalid") {
$('#naming_sports_pattern').qtip('option', {
'content.text': 'This pattern is invalid.',
'style.classes': 'qtip-rounded qtip-shadow qtip-red'
});
$('#naming_sports_pattern').qtip('toggle', true);
$('#naming_sports_pattern').css('background-color', '#FFDDDD');
} else if (data == "seasonfolders") {
$('#naming_sports_pattern').qtip('option', {
'content.text': 'This pattern would be invalid without the folders, using it will force "Flatten" off for all shows.',
'style.classes': 'qtip-rounded qtip-shadow qtip-red'
});
$('#naming_sports_pattern').qtip('toggle', true);
$('#naming_sports_pattern').css('background-color', '#FFFFDD');
} else {
$('#naming_sports_pattern').qtip('option', {
'content.text': 'This pattern is valid.',
'style.classes': 'qtip-rounded qtip-shadow qtip-green'
});
$('#naming_sports_pattern').qtip('toggle', false);
$('#naming_sports_pattern').css('background-color', '#FFFFFF');
}
});
}
function setup_naming() {
// if it is a custom selection then show the text box
if ($('#name_presets :selected').val() == "Custom...") {
@ -141,6 +182,17 @@ $(document).ready(function () {
fill_abd_examples();
}
function setup_sports_naming() {
// if it is a custom selection then show the text box
if ($('#name_sports_presets :selected').val() == "Custom...") {
$('#naming_sports_custom').show();
} else {
$('#naming_sports_custom').hide();
$('#naming_sports_pattern').val($('#name_sports_presets :selected').attr('id'));
}
fill_sports_examples();
}
$('#unpack').change(function () {
if(this.checked) {
israr_supported();
@ -161,6 +213,14 @@ $(document).ready(function () {
setup_abd_naming();
});
$('#name_sports_presets').change(function () {
setup_sports_naming();
});
$('#naming_custom_sports').change(function () {
setup_sports_naming();
});
$('#naming_multi_ep').change(fill_examples);
$('#naming_pattern').focusout(fill_examples);
$('#naming_pattern').keyup(function () {
@ -176,12 +236,22 @@ $(document).ready(function () {
}, 500);
});
$('#naming_sports_pattern').focusout(fill_examples);
$('#naming_sports_pattern').keyup(function () {
typewatch(function () {
fill_sports_examples();
}, 500);
});
$('#show_naming_key').click(function () {
$('#naming_key').toggle();
});
$('#show_naming_abd_key').click(function () {
$('#naming_abd_key').toggle();
});
$('#show_naming_sports_key').click(function () {
$('#naming_sports_key').toggle();
});
$('#do_custom').click(function () {
$('#naming_pattern').val($('#name_presets :selected').attr('id'));
$('#naming_custom').show();
@ -189,6 +259,7 @@ $(document).ready(function () {
});
setup_naming();
setup_abd_naming();
setup_sports_naming();
// -- start of metadata options div toggle code --
$('#metadataType').on('change keyup', function () {
@ -295,7 +366,7 @@ $(document).ready(function () {
position: {
viewport: $(window),
at: 'top center',
my: 'bottom center',
my: 'bottom center'
},
style: {
tip: {
@ -315,7 +386,7 @@ $(document).ready(function () {
position: {
viewport: $(window),
at: 'center left',
my: 'center right',
my: 'center right'
},
style: {
tip: {

View file

@ -151,6 +151,8 @@ NAMING_MULTI_EP = None
NAMING_PATTERN = None
NAMING_ABD_PATTERN = None
NAMING_CUSTOM_ABD = None
NAMING_SPORTS_PATTERN = None
NAMING_CUSTOM_SPORTS = None
NAMING_FORCE_FOLDERS = False
NAMING_STRIP_YEAR = None
@ -480,7 +482,7 @@ def initialize(consoleLogging=True):
versionCheckScheduler, VERSION_NOTIFY, AUTO_UPDATE, PROCESS_AUTOMATICALLY, UNPACK, \
KEEP_PROCESSED_DIR, PROCESS_METHOD, TV_DOWNLOAD_DIR, MIN_SEARCH_FREQUENCY, DEFAULT_UPDATE_FREQUENCY,MIN_UPDATE_FREQUENCY,UPDATE_FREQUENCY,\
showQueueScheduler, searchQueueScheduler, ROOT_DIRS, CACHE_DIR, ACTUAL_CACHE_DIR, \
NAMING_PATTERN, NAMING_MULTI_EP, NAMING_FORCE_FOLDERS, NAMING_ABD_PATTERN, NAMING_CUSTOM_ABD, NAMING_STRIP_YEAR, \
NAMING_PATTERN, NAMING_MULTI_EP, NAMING_FORCE_FOLDERS, NAMING_ABD_PATTERN, NAMING_CUSTOM_ABD, NAMING_SPORTS_PATTERN, NAMING_CUSTOM_SPORTS, NAMING_STRIP_YEAR, \
RENAME_EPISODES, properFinderScheduler, PROVIDER_ORDER, autoPostProcesserScheduler, \
WOMBLE, OMGWTFNZBS, OMGWTFNZBS_USERNAME, OMGWTFNZBS_APIKEY, providerList, newznabProviderList, torrentRssProviderList, \
EXTRA_SCRIPTS, USE_TWITTER, TWITTER_USERNAME, TWITTER_PASSWORD, TWITTER_PREFIX, \
@ -602,6 +604,8 @@ 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', '%Y/%0M/%SN - %A.D - %EN')
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))
@ -1315,6 +1319,8 @@ def save_config():
new_config['General']['naming_pattern'] = NAMING_PATTERN
new_config['General']['naming_custom_abd'] = int(NAMING_CUSTOM_ABD)
new_config['General']['naming_abd_pattern'] = NAMING_ABD_PATTERN
new_config['General']['naming_custom_sports'] = int(NAMING_CUSTOM_SPORTS)
new_config['General']['naming_sports_pattern'] = NAMING_SPORTS_PATTERN
new_config['General']['naming_multi_ep'] = int(NAMING_MULTI_EP)
new_config['General']['launch_browser'] = int(LAUNCH_BROWSER)
new_config['General']['update_shows_on_start'] = int(UPDATE_SHOWS_ON_START)

View file

@ -27,8 +27,7 @@ from sickbeard import encodingKludge as ek
from sickbeard.name_parser.parser import NameParser, InvalidNameException
MIN_DB_VERSION = 9 # oldest db version we support migrating from
MAX_DB_VERSION = 29
MAX_DB_VERSION = 30
class MainSanityCheck(db.DBSanityCheck):
def check(self):
@ -657,7 +656,6 @@ class ConvertInfoToIndexerScheme(ConvertIMDBInfoToIndexerScheme):
self.incDBVersion()
class AddArchiveFirstMatchOption(ConvertInfoToIndexerScheme):
def test(self):
return self.checkDBVersion() >= 26
@ -671,7 +669,6 @@ class AddArchiveFirstMatchOption(ConvertInfoToIndexerScheme):
self.incDBVersion()
class AddSceneNumbering(AddArchiveFirstMatchOption):
def test(self):
return self.checkDBVersion() >= 27
@ -726,3 +723,26 @@ class AddRequireAndIgnoreWords(ConvertIndexerToInteger):
self.addColumn("tv_shows", "rls_ignore_words", "TEXT", "")
self.incDBVersion()
class AddSportsOption(AddRequireAndIgnoreWords):
def test(self):
return self.checkDBVersion() >= 30
def execute(self):
backupDatabase(30)
logger.log(u"Adding column sports to tvshows")
if not self.hasColumn("tv_shows", "sports"):
self.addColumn("tv_shows", "sports", "NUMERIC", "0")
if self.hasColumn("tv_shows", "air_by_date") and self.hasColumn("tv_shows", "sports"):
# update sports column
logger.log(u"[4/4] Updating tv_shows to reflect the correct sports value...", logger.MESSAGE)
ql = []
historyQuality = self.connection.select("SELECT * FROM tv_shows WHERE LOWER(classification) = 'sports' AND air_by_date = 1 AND sports = 0")
for cur_entry in historyQuality:
ql.append(["UPDATE tv_shows SET sports = ? WHERE show_id = ?", [cur_entry["air_by_date"], cur_entry["show_id"]]])
ql.append(["UPDATE tv_shows SET air_by_date = 0 WHERE show_id = ?", [cur_entry["show_id"]]])
self.connection.mass_action(ql)
self.incDBVersion()

View file

@ -974,14 +974,6 @@ def get_show_by_name(name, showList, useIndexer=False):
return None
def suffix(d):
return 'th' if 11 <= d <= 13 else {1: 'st', 2: 'nd', 3: 'rd'}.get(d % 10, 'th')
def custom_strftime(format, t):
return t.strftime(format).replace('{S}', str(t.day) + suffix(t.day))
def is_hidden_folder(folder):
"""
Returns True if folder is hidden.

View file

@ -98,7 +98,7 @@ class SBRotatingLogHandler(object):
# define a Handler which writes INFO messages or higher to the sys.stderr
console = logging.StreamHandler()
console.setLevel(logging.INFO)
console.setLevel(logging.DEBUG)
# set a format which is simpler for console use
console.setFormatter(DispatchingFormatter(

View file

@ -33,11 +33,16 @@ from time import strptime
class NameParser(object):
def __init__(self, file_name=True):
ALL_REGEX = -1
NORMAL_REGEX = 0
SPORTS_REGEX = 1
def __init__(self, file_name=True, regexMode=0):
self.file_name = file_name
self.regexMode = regexMode
self.compiled_regexes = []
self._compile_regexes()
self._compile_regexes(regexMode)
def clean_series_name(self, series_name):
"""Cleans up series name by removing any . and _
@ -63,8 +68,24 @@ class NameParser(object):
series_name = re.sub("^\[.*\]", "", series_name)
return series_name.strip()
def _compile_regexes(self):
for (cur_pattern_name, cur_pattern) in regexes.ep_regexes:
def _compile_regexes(self, regexMode):
if regexMode <= self.ALL_REGEX:
logger.log(u"Using ALL regexs" , logger.DEBUG)
uncompiled_regex = regexes.sports_regexs+regexes.ep_regexes
elif regexMode == self.NORMAL_REGEX:
logger.log(u"Using NORMAL regexs" , logger.DEBUG)
uncompiled_regex = regexes.ep_regexes
elif regexMode == self.SPORTS_REGEX:
logger.log(u"Using SPORTS regexs" , logger.DEBUG)
uncompiled_regex = regexes.sports_regexs
else:
logger.log(u"This is a programing ERROR. Fallback Using NORMAL regexs" , logger.ERROR)
uncompiled_regex = regexes.ep_regexes
for (cur_pattern_name, cur_pattern) in uncompiled_regex:
try:
cur_regex = re.compile(cur_pattern, re.VERBOSE | re.IGNORECASE)
except re.error, errormsg:
@ -107,16 +128,20 @@ class NameParser(object):
result.episode_numbers = [ep_num]
if 'air_year' in named_groups and 'air_month' in named_groups and 'air_day' in named_groups:
if 'scene_sports_date_format' in cur_regex_name:
year = match.group('air_year')
month = strptime(match.group('air_month')[:3], '%b').tm_mon
day = re.sub("(st|nd|rd|th)", "", match.group('air_day'))
if 'sports' in cur_regex_name:
year = int(match.group('air_year'))
month = match.group('air_month')
day = int(re.sub("(st|nd|rd|th)", "", match.group('air_day')))
else:
year = int(match.group('air_year'))
month = int(match.group('air_month'))
day = int(match.group('air_day'))
try:
if 'sports' in cur_regex_name:
dtStr = '%s-%s-%s' % (day, month, year)
result.air_date = result.sports_date = datetime.datetime.strptime(dtStr, "%d-%b-%Y").date()
else:
dtStr = '%s-%s-%s' % (year, month, day)
result.air_date = datetime.datetime.strptime(dtStr, "%Y-%m-%d").date()
except ValueError, e:
@ -220,6 +245,7 @@ class NameParser(object):
# build the ParseResult object
final_result.air_date = self._combine_results(file_name_result, dir_name_result, 'air_date')
final_result.sports_date = self._combine_results(file_name_result, dir_name_result, 'sports_date')
if not final_result.air_date:
final_result.season_number = self._combine_results(file_name_result, dir_name_result, 'season_number')
@ -255,71 +281,19 @@ class NameParser(object):
return final_result
@classmethod
def series_name_to_indexer_id(cls, series_name, check_scene_exceptions=True, check_database=True,
check_indexer=False):
"""
Given a series name, return it's tvdbd_id.
Returns None if not found.
This is mostly robbed from postProcessor._analyze_name
"""
def series_name_to_indexer_id(cls, series_name):
# do a scene reverse-lookup to get a list of all possible names
name_list = sickbeard.show_name_helpers.sceneToNormalShowNames(series_name)
# for each possible interpretation of that scene name
if check_scene_exceptions:
for cur_name in name_list:
logger.log(u"Checking scene exceptions for a match on " + cur_name, logger.DEBUG)
logger.log(u"Checking scene exceptions and database for a match on " + cur_name, logger.DEBUG)
scene_id = sickbeard.scene_exceptions.get_scene_exception_by_name(cur_name)
if scene_id: return scene_id
# see if we can find the name directly in the DB, if so use it
if check_database:
for cur_name in name_list:
logger.log(u"Looking up " + str(cur_name) + " in the DB", logger.DEBUG)
db_result = sickbeard.helpers.searchDBForShow(cur_name)
if db_result: return db_result[1]
# see if we can find the name with a TVDB lookup
if check_indexer:
for cur_name in name_list:
for indexer in sickbeard.indexerApi().indexers:
try:
lINDEXER_API_PARMS = sickbeard.indexerApi(indexer).api_params.copy()
lINDEXER_API_PARMS['custom_ui'] = classes.ShowListUI
t = sickbeard.indexerApi(indexer).indexer(**lINDEXER_API_PARMS)
logger.log(u"Looking up name " + str(cur_name) + " on " + sickbeard.indexerApi(indexer).name,
logger.DEBUG)
showObj = t[cur_name]
except (sickbeard.indexer_exception):
# if none found, search on all languages
try:
lINDEXER_API_PARMS = sickbeard.indexerApi(indexer).api_params.copy()
lINDEXER_API_PARMS['custom_ui'] = classes.ShowListUI
lINDEXER_API_PARMS['search_all_languages'] = True
t = sickbeard.indexerApi(indexer).indexer(**lINDEXER_API_PARMS)
logger.log(
u"Looking up name " + str(cur_name) + " in all languages on " + sickbeard.indexerApi(
indexer).name, logger.DEBUG)
showObj = t[cur_name]
except (sickbeard.indexer_exception, IOError):
pass
continue
except (IOError):
continue
return showObj["id"]
return None
if scene_id:
return scene_id
elif db_result:
return db_result[1]
class ParseResult(object):
def __init__(self,
@ -329,7 +303,8 @@ class ParseResult(object):
episode_numbers=None,
extra_info=None,
release_group=None,
air_date=None
air_date=None,
sports_date=None
):
self.original_name = original_name
@ -345,6 +320,7 @@ class ParseResult(object):
self.release_group = release_group
self.air_date = air_date
self.sports_date = sports_date
self.which_regex = None
@ -364,6 +340,8 @@ class ParseResult(object):
return False
if self.air_date != other.air_date:
return False
if self.sports_date != other.sports_date:
return False
return True
@ -380,6 +358,8 @@ class ParseResult(object):
if self.air_by_date:
to_return += str(self.air_date)
if self.sports:
to_return += str(self.sports_date)
if self.extra_info:
to_return += ' - ' + self.extra_info
@ -387,26 +367,33 @@ class ParseResult(object):
to_return += ' (' + self.release_group + ')'
to_return += ' [ABD: ' + str(self.air_by_date) + ']'
to_return += ' [SPORTS: ' + str(self.sports) + ']'
to_return += ' [whichReg: ' + str(self.which_regex) + ']'
return to_return.encode('utf-8')
def _is_air_by_date(self):
if self.season_number == None and len(self.episode_numbers) == 0 and self.air_date:
if self.season_number == None and len(self.episode_numbers) == 0 and self.air_date and not self.sports_date:
return True
return False
air_by_date = property(_is_air_by_date)
def _is_sports(self):
if self.season_number == None and len(self.episode_numbers) == 0 and self.sports_date:
return True
return False
sports = property(_is_sports)
def fix_scene_numbering(self):
"""
The changes the parsed result (which is assumed to be scene numbering) to
tvdb numbering, if necessary.
"""
if self.air_by_date: return self # scene numbering does not apply to air-by-date
if self.air_by_date or self.sports: return self # scene numbering does not apply to air-by-date
if self.season_number == None: return self # can't work without a season
if len(self.episode_numbers) == 0: return self # need at least one episode
indexer_id = NameParser.series_name_to_indexer_id(self.series_name, True, True, False)
indexer_id = NameParser.series_name_to_indexer_id(self.series_name)
new_episode_numbers = []
new_season_numbers = []

View file

@ -96,19 +96,6 @@ ep_regexes = [
-(?P<release_group>[^- ]+))?)?$ # Group
'''),
('scene_sports_date_format',
# Show.Name.2010.Nov.23rd.Source.Quality.Etc-Group
# Show Name - 2010-Nov-23rd - Ep Name
'''
^(?P<series_name>.*?(UEFA|MLB|ESPN|WWE|MMA|UFC|TNA|EPL|NASCAR|NBA|NFL|NHL|NRL|PGA|SUPER LEAGUE|FORMULA|FIFA|NETBALL|MOTOGP).*?)[. _-]+
(?P<parts>\d{1,3}\d{1,3}.*?)[. _-]+ # Parts
(?P<air_day>\d{1,2}[a-zA-Z]{2})[. _-]+ # 23rd and seperator
(?P<air_month>[a-zA-Z]{3,})[. _-]+ # Nov and seperator
(?P<air_year>\d{4})[. _-]+ # 2010
(?P<extra_info>.*?(?<![. _-])(?<!WEB))[. _-]+ # Make sure this is really the release group
(?P<release_group>.*?)$ # Group
'''),
('stupid',
# tpz-abc102
'''
@ -198,3 +185,30 @@ ep_regexes = [
'''
),
]
sports_regexs = [
('sports_event',
# Show.Name.123.Event.Nov.23rd.2010.Source.Quality.Etc-Group
'''
^(?P<series_name>.*?(UEFA|MLB|ESPN|WWE|MMA|UFC|TNA|EPL|NASCAR|NBA|NFL|NHL|NRL|PGA|SUPER LEAGUE|FORMULA|FIFA|NETBALL|MOTOGP).*?)[. _-]+
(?P<parts>\d{1,3}\d{1,3}.*?)[. _-]+
(?P<event>.*?)[. _-]+
(?P<air_day>\d{1,2}[a-zA-Z]{2})[. _-]+
(?P<air_month>[a-zA-Z]{3,})[. _-]+
(?P<air_year>\d{4})[. _-]+
(?P<extra_info>.*?(?<![. _-])(?<!WEB))[. _-]+
(?P<release_group>.*?)$
'''),
('sports_event_without_parts',
# Show.Name.Event.Nov.23rd.2010.Source.Quality.Etc-Group
'''
^(?P<series_name>.*?(UEFA|MLB|ESPN|WWE|MMA|UFC|TNA|EPL|NASCAR|NBA|NFL|NHL|NRL|PGA|SUPER LEAGUE|FORMULA|FIFA|NETBALL|MOTOGP).*?)[. _-]+
(?P<event>.*?)[. _-]+
(?P<air_day>\d{1,2}[a-zA-Z]{2})[. _-]+
(?P<air_month>[a-zA-Z]{3,})[. _-]+
(?P<air_year>\d{4})[. _-]+
(?P<extra_info>.*?(?<![. _-])(?<!WEB))[. _-]+
(?P<release_group>.*?)$
'''),
]

View file

@ -40,13 +40,17 @@ name_abd_presets = ('%SN - %A-D - %EN',
'%Y/%0M/%S.N.%A.D.%E.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():
def __init__(self):
self.name = "Show Name"
self.genre = "Comedy"
self.air_by_date = 0
self.sports = 0
class TVEpisode(tv.TVEpisode):
def __init__(self, season, episode, name):
@ -114,11 +118,28 @@ def check_valid_abd_naming(pattern=None):
return valid
def check_valid_sports_naming(pattern=None):
"""
Checks if the name is can be parsed back to its original form for an sports format.
def validate_name(pattern, multi=None, file_only=False, abd=False):
ep = _generate_sample_ep(multi, abd)
Returns true if the naming is valid, false if not.
"""
if pattern == None:
pattern = sickbeard.NAMING_PATTERN
parser = NameParser(True)
logger.log(u"Checking whether the pattern " + pattern + " is valid for an sports episode", logger.DEBUG)
valid = validate_name(pattern, sports=True)
return valid
def validate_name(pattern, multi=None, file_only=False, abd=False, sports=False):
ep = _generate_sample_ep(multi, abd, sports)
regexMode = 0
if sports:
regexMode = 1
parser = NameParser(True, regexMode)
new_name = ep.formatted_filename(pattern, multi) + '.ext'
new_path = ep.formatted_dir(pattern, multi)
@ -143,6 +164,10 @@ def validate_name(pattern, multi=None, file_only=False, abd=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_date != ep.airdate:
logger.log(u"Sports air date 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)
@ -154,13 +179,16 @@ def validate_name(pattern, multi=None, file_only=False, abd=False):
return True
def _generate_sample_ep(multi=None, abd=False):
def _generate_sample_ep(multi=None, abd=False, sports=False):
# make a fake episode object
ep = TVEpisode(2, 3, "Ep Name")
ep._status = Quality.compositeStatus(DOWNLOADED, Quality.HDTV)
ep._airdate = datetime.date(2011, 3, 9)
if abd:
ep._release_name = 'Show.Name.2011.03.09.HDTV.XviD-RLSGROUP'
elif sports:
ep._release_name = 'Show.Name.09.03.2011.HDTV.XviD-RLSGROUP'
else:
ep._release_name = 'Show.Name.S02E03.HDTV.XviD-RLSGROUP'
@ -182,7 +210,7 @@ def _generate_sample_ep(multi=None, abd=False):
return ep
def test_name(pattern, multi=None, abd=False):
ep = _generate_sample_ep(multi, abd)
def test_name(pattern, multi=None, abd=False, sports=False):
ep = _generate_sample_ep(multi, abd, sports)
return {'name': ep.formatted_filename(pattern, multi), 'dir': ep.formatted_dir(pattern, multi)}

View file

@ -464,6 +464,9 @@ class PostProcessor(object):
if parse_result.air_by_date:
season = -1
episodes = [parse_result.air_date]
elif parse_result.sports:
season = -1
episodes = [parse_result.sports_date]
else:
season = parse_result.season_number
episodes = parse_result.episode_numbers
@ -585,7 +588,7 @@ class PostProcessor(object):
# for air-by-date shows we need to look up the season/episode from tvdb
if season == -1 and indexer_id and episodes:
self._log(u"Looks like this is an air-by-date show, attempting to convert the date to season/episode",
self._log(u"Looks like this is an air-by-date or sports show, attempting to convert the date to season/episode",
logger.DEBUG)
# try to get language set for this show

View file

@ -115,6 +115,9 @@ class ProperFinder():
if parse_result.air_by_date:
curProper.season = -1
curProper.episode = parse_result.air_date
elif parse_result.sports:
curProper.season = -1
curProper.episode = parse_result.sports_date
else:
curProper.season = parse_result.season_number if parse_result.season_number != None else 1
curProper.episode = parse_result.episode_numbers[0]

View file

@ -191,7 +191,7 @@ class BTNProvider(generic.TorrentProvider):
return (title, url)
def _get_season_search_strings(self, show, season, episode, abd=False):
def _get_season_search_strings(self, show, season, episode):
if not show:
return []
@ -215,15 +215,14 @@ class BTNProvider(generic.TorrentProvider):
# Search for entire seasons: no need to do special things for air by date shows
whole_season_params['category'] = 'Season'
whole_season_params['name'] = 'Season ' + str(season)
search_params.append(whole_season_params)
# Search for episodes in the season
search_params.append(self._get_episode_search_strings(show, season, episode, abd)[0])
search_params.append(self._get_episode_search_strings(show, season, episode)[0])
return search_params
def _get_episode_search_strings(self, show, season, episode, abd=False):
def _get_episode_search_strings(self, show, season, episode, add_string=''):
if not episode:
return [{}]
@ -237,13 +236,18 @@ class BTNProvider(generic.TorrentProvider):
else:
search_params['series'] = sanitizeSceneName(show.name)
if abd:
if show.air_by_date:
date_str = str(episode)
# BTN uses dots in dates, we just search for the date since that
# combined with the series identifier should result in just one episode
search_params['name'] = date_str.replace('-', '.')
if show.sports:
date_str = str(episode)
# BTN uses dots in dates, we just search for the date since that
# combined with the series identifier should result in just one episode
search_params['name'] = date_str.replace('-', '.')
else:
# Do a general name search for the episode, formatted like SXXEYY
search_params['name'] = "S%02dE%02d" % (season, episode)

View file

@ -52,7 +52,7 @@ class DTTProvider(generic.TorrentProvider):
def _dtt_show_id(self, show_name):
return sanitizeSceneName(show_name).replace('.', '-').lower()
def _get_season_search_strings(self, show, season, episode, abd=False):
def _get_season_search_strings(self, show, season, episode):
search_string = []
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
@ -61,8 +61,8 @@ class DTTProvider(generic.TorrentProvider):
return search_string
def _get_episode_search_strings(self, show, season, episode, abd=False):
return self._get_season_search_strings(show, season, episode, abd)
def _get_episode_search_strings(self, show, season, episode, add_string=''):
return self._get_season_search_strings(show, season, episode)
def _doSearch(self, search_params, show=None, age=None):

View file

@ -61,8 +61,8 @@ class EZRSSProvider(generic.TorrentProvider):
results = {}
if show.air_by_date:
logger.log(self.name + u" doesn't support air-by-date backlog because of limitations on their RSS search.",
if show.air_by_date or show.sports:
logger.log(self.name + u" doesn't support air-by-date or sports backloging because of limitations on their RSS search.",
logger.WARNING)
return results
@ -70,7 +70,7 @@ class EZRSSProvider(generic.TorrentProvider):
return results
def _get_season_search_strings(self, show, season, episode, abd=False):
def _get_season_search_strings(self, show, season, episode):
params = {}
@ -81,11 +81,11 @@ class EZRSSProvider(generic.TorrentProvider):
params['season'] = season
params['episode'] = self._get_episode_search_strings(show, season, episode, abd)[0]['episode']
params['episode'] = self._get_episode_search_strings(show, season, episode)[0]['episode']
return [params]
def _get_episode_search_strings(self, show, season, episode, abd=False):
def _get_episode_search_strings(self, show, season, episode, add_string=''):
params = {}
@ -94,7 +94,9 @@ class EZRSSProvider(generic.TorrentProvider):
params['show_name'] = helpers.sanitizeSceneName(show.name, ezrss=True).replace('.', ' ').encode('utf-8')
if abd:
if show.air_by_date:
params['date'] = str(episode)
if show.sports:
params['date'] = str(episode)
else:
params['season'] = season

View file

@ -30,10 +30,11 @@ import itertools
import operator
import collections
import urlparse
from lib.feedparser import feedparser
import sickbeard
from lib import requests
from lib.feedparser import feedparser
from sickbeard import helpers, classes, logger, db
from sickbeard.common import Quality, MULTI_EP_RESULT, SEASON_RESULT #, SEED_POLICY_TIME, SEED_POLICY_RATIO
from sickbeard import tvcache
@ -54,11 +55,16 @@ class GenericProvider:
self.providerType = None
self.name = name
self.url = ''
self.session = None
self.supportsBacklog = False
self.cache = tvcache.TVCache(self)
self.session = requests.session()
self.session.verify = False
self.session.headers.update({'user-agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36'})
def getID(self):
return GenericProvider.makeID(self.name)
@ -214,10 +220,10 @@ class GenericProvider:
def _doSearch(self, search_params, show=None, age=None):
return []
def _get_season_search_strings(self, show, season, episode, abd=False):
def _get_season_search_strings(self, show, season, episode):
return []
def _get_episode_search_strings(self, show, season, episode, abd=False):
def _get_episode_search_strings(self, show, season, episode, add_string=''):
return []
def _get_title_and_url(self, item):
@ -245,11 +251,15 @@ class GenericProvider:
self._checkAuth()
regexMethod = 0
if show.sports:
regexMethod = 1
for ep_obj in ep_objs:
# get scene season/episode info
scene_season = ep_obj.scene_season
scene_episode = ep_obj.scene_episode
if show.air_by_date:
if show.air_by_date or show.sports:
scene_episode = ep_obj.airdate
if not seasonSearch:
@ -268,10 +278,10 @@ class GenericProvider:
return results
if seasonSearch:
for curString in self._get_season_search_strings(show, scene_season, scene_episode, show.air_by_date):
for curString in self._get_season_search_strings(show, scene_season, scene_episode):
itemList += self._doSearch(curString, show=show)
else:
for curString in self._get_episode_search_strings(show, scene_season, scene_episode, show.air_by_date):
for curString in self._get_episode_search_strings(show, scene_season, scene_episode):
itemList += self._doSearch(curString, show=show)
for item in itemList:
@ -282,13 +292,13 @@ class GenericProvider:
# parse the file name
try:
myParser = NameParser(False)
myParser = NameParser(False, regexMethod)
parse_result = myParser.parse(title, True)
except InvalidNameException:
logger.log(u"Unable to parse the filename " + title + " into a valid episode", logger.WARNING)
continue
if not show.air_by_date:
if not show.air_by_date and not show.sports:
# this check is meaningless for non-season searches
if (parse_result.season_number != None and parse_result.season_number != season) or (
parse_result.season_number == None and season != 1):
@ -301,15 +311,25 @@ class GenericProvider:
actual_episodes = parse_result.episode_numbers
else:
if not parse_result.air_by_date:
if show.air_by_date and not parse_result.air_by_date:
logger.log(
u"This is supposed to be an air-by-date search but the result " + title + " didn't parse as one, skipping it",
logger.DEBUG)
continue
if show.sports and not parse_result.sports:
logger.log(
u"This is supposed to be an sports search but the result " + title + " didn't parse as one, skipping it",
logger.DEBUG)
continue
myDB = db.DBConnection()
if parse_result.air_by_date:
sql_results = myDB.select("SELECT season, episode FROM tv_episodes WHERE showid = ? AND airdate = ?",
[show.indexerid, parse_result.air_date.toordinal()])
elif parse_result.sports:
sql_results = myDB.select("SELECT season, episode FROM tv_episodes WHERE showid = ? AND airdate = ?",
[show.indexerid, parse_result.sports_date.toordinal()])
if len(sql_results) != 1:
logger.log(

View file

@ -122,7 +122,7 @@ class HDBitsProvider(generic.TorrentProvider):
logger.log(u"Unable to parse the filename " + title + " into a valid episode", logger.WARNING)
continue
if episode.show.air_by_date:
if episode.show.air_by_date or episode.sports:
if parse_result.air_date != episode.airdate:
logger.log(u"Episode " + title + " didn't air on " + str(episode.airdate) + ", skipping it",
logger.DEBUG)

View file

@ -61,8 +61,6 @@ class HDTorrentsProvider(generic.TorrentProvider):
self.categories = "&category[]=59&category[]=60&category[]=30&category[]=38"
self.session = requests.Session()
self.cookies = None
def isEnabled(self):
@ -112,7 +110,7 @@ class HDTorrentsProvider(generic.TorrentProvider):
return True
def _get_season_search_strings(self, show, season, episode, abd=False):
def _get_season_search_strings(self, show, season, episode):
if not show:
return []
@ -121,21 +119,27 @@ class HDTorrentsProvider(generic.TorrentProvider):
ep_string = show_name + ' S%02d' % int(season) #1) ShowName SXX
search_string['Season'].append(ep_string)
search_string['Episode'] = self._get_episode_search_strings(show, season, episode, abd)[0]['Episode']
search_string['Episode'] = self._get_episode_search_strings(show, season, episode)[0]['Episode']
return [search_string]
def _get_episode_search_strings(self, show, season, episode, abd=False, add_string=''):
def _get_episode_search_strings(self, show, season, episode, add_string=''):
search_string = {'Episode': []}
if not episode:
return []
if abd:
if show.air_by_date:
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
ep_string = sanitizeSceneName(show_name) + ' ' + \
str(episode).replace('-', '|') + '|' + \
helpers.custom_strftime('%b', str(episode))
episode.strftime('%b')
search_string['Episode'].append(ep_string)
elif show.sports:
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
ep_string = sanitizeSceneName(show_name) + ' ' + \
str(episode).replace('-', '|') + '|' + \
episode.strftime('%b')
search_string['Episode'].append(ep_string)
else:
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
@ -273,7 +277,6 @@ class HDTorrentsProvider(generic.TorrentProvider):
if not headers:
headers = []
try:
parsed = list(urlparse.urlparse(url))
parsed[2] = re.sub("/{2,}", "/", parsed[2]) # replace two or more / with one
@ -307,7 +310,13 @@ class HDTorrentsProvider(generic.TorrentProvider):
for sqlShow in sqlResults:
curShow = helpers.findCertainShow(sickbeard.showList, int(sqlShow["showid"]))
curEp = curShow.getEpisode(int(sqlShow["season"]), int(sqlShow["episode"]))
searchString = self._get_episode_search_strings(curShow, curEp.scene_season, curEp.scene_episode, curShow.air_by_date, add_string='PROPER|REPACK')
season = curEp.scene_season
episode = curEp.scene_episode
if curShow.air_by_date or curShow.sports:
episode = curEp.airdate
searchString = self._get_episode_search_strings(curShow, season, episode, add_string='PROPER|REPACK')
for item in self._doSearch(searchString[0], show=curShow):
title, url = self._get_title_and_url(item)

View file

@ -37,6 +37,7 @@ from lib.requests import exceptions
from bs4 import BeautifulSoup
from lib.unidecode import unidecode
from sickbeard.helpers import sanitizeSceneName
from sickbeard.show_name_helpers import allPossibleShowNames
class IPTorrentsProvider(generic.TorrentProvider):
@ -55,8 +56,6 @@ class IPTorrentsProvider(generic.TorrentProvider):
self.url = self.urls['base_url']
self.session = None
self.categorie = 'l73=1&l78=1&l66=1&l65=1&l79=1&l5=1&l4=1'
def isEnabled(self):
@ -93,7 +92,7 @@ class IPTorrentsProvider(generic.TorrentProvider):
return True
def _get_season_search_strings(self, show, season, episode, abd=False):
def _get_season_search_strings(self, show, season, episode):
if not show:
return []
@ -102,22 +101,28 @@ class IPTorrentsProvider(generic.TorrentProvider):
ep_string = show_name + ' S%02d' % int(season) #1) ShowName SXX
search_string['Season'].append(ep_string)
search_string['Episode'] = self._get_episode_search_strings(show, season, episode, abd)[0]['Episode']
search_string['Episode'] = self._get_episode_search_strings(show, season, episode)[0]['Episode']
return [search_string]
def _get_episode_search_strings(self, show, season, episode, abd=False, add_string=''):
def _get_episode_search_strings(self, show, season, episode, add_string=''):
search_string = {'Episode': []}
if not episode:
return []
if abd:
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
if show.air_by_date:
for show_name in set(allPossibleShowNames(show)):
ep_string = sanitizeSceneName(show_name) + ' ' + \
str(episode).replace('-', '|') + '|' + \
helpers.custom_strftime('%b', str(episode))
episode.strftime('%b')
search_string['Episode'].append(ep_string)
if show.sports:
for show_name in set(allPossibleShowNames(show)):
ep_string = sanitizeSceneName(show_name) + ' ' + \
str(episode).replace('-', '|') + '|' + \
episode.strftime('%b')
search_string['Episode'].append(ep_string)
else:
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
@ -254,7 +259,7 @@ class IPTorrentsProvider(generic.TorrentProvider):
for sqlShow in sqlResults:
curShow = helpers.findCertainShow(sickbeard.showList, int(sqlShow["showid"]))
curEp = curShow.getEpisode(int(sqlShow["season"]), int(sqlShow["episode"]))
searchString = self._get_episode_search_strings(curShow, curEp.scene_season, curEp.scene_episode, curShow.air_by_date, add_string='PROPER|REPACK')
searchString = self._get_episode_search_strings(curShow, curEp.scene_season, curEp.scene_episode, curShow.air_by_date or curShow.sports, add_string='PROPER|REPACK')
for item in self._doSearch(searchString[0], show=curShow):
title, url = self._get_title_and_url(item)

View file

@ -61,8 +61,6 @@ class KATProvider(generic.TorrentProvider):
self.searchurl = self.url + 'usearch/%s/?field=seeders&sorder=desc' #order by seed
self.session = requests.Session()
def isEnabled(self):
return sickbeard.KAT
@ -166,7 +164,7 @@ class KATProvider(generic.TorrentProvider):
logger.log(u"Failed parsing " + self.name + " Traceback: " + traceback.format_exc(), logger.ERROR)
def _get_season_search_strings(self, show, season, episode, abd=False):
def _get_season_search_strings(self, show, season, episode):
search_string = {'Season': [], 'Episode': []}
if not show:
@ -181,9 +179,9 @@ class KATProvider(generic.TorrentProvider):
ep_string = show_name + ' Season ' + str(season) + ' -Ep*' + ' category:tv' #2) ShowName Season X
search_string['Season'].append(ep_string)
search_string['Episode'] = self._get_episode_search_strings(show, season, episode, abd)[0]['Episode']
search_string['Episode'] = self._get_episode_search_strings(show, season, episode)[0]['Episode']
def _get_episode_search_strings(self, show, season, episode, abd=False, add_string=''):
def _get_episode_search_strings(self, show, season, episode, add_string=''):
search_string = {'Episode': []}
if not show:
@ -191,12 +189,18 @@ class KATProvider(generic.TorrentProvider):
self.show = show
if abd:
if show.air_by_date:
for show_name in set(allPossibleShowNames(show)):
ep_string = sanitizeSceneName(show_name) + ' ' + \
str(episode).replace('-','|') + '|' + \
helpers.custom_strftime('%b', str(episode))
episode.strftime('%b')
search_string['Episode'].append(ep_string)
if show.sports:
for show_name in set(allPossibleShowNames(show)):
ep_string = sanitizeSceneName(show_name) + ' ' + \
str(episode).replace('-', '|') + '|' + \
episode.strftime('%b')
search_string['Episode'].append(ep_string)
else:
for show_name in set(allPossibleShowNames(show)):
@ -388,7 +392,13 @@ class KATProvider(generic.TorrentProvider):
for sqlShow in sqlResults:
curShow = helpers.findCertainShow(sickbeard.showList, int(sqlShow["showid"]))
curEp = curShow.getEpisode(int(sqlShow["season"]), int(sqlShow["episode"]))
searchString = self._get_episode_search_strings(curShow, curEp.scene_season, curEp.scene_episode, curShow.air_by_date, add_string='PROPER|REPACK')
season = curEp.scene_season
episode = curEp.scene_episode
if curShow.air_by_date or curShow.sports:
episode = curEp.airdate
searchString = self._get_episode_search_strings(curShow, season, episode, add_string='PROPER|REPACK')
for item in self._doSearch(searchString[0], show=curShow):
title, url = self._get_title_and_url(item)

View file

@ -251,11 +251,11 @@ class NewzbinProvider(generic.NZBProvider):
return data
def _get_season_search_strings(self, show, season, episode, abd=False):
return ['^' + x for x in show_name_helpers.makeSceneSeasonSearchString(show, season, episode, abd)]
def _get_season_search_strings(self, show, season, episode):
return ['^' + x for x in show_name_helpers.makeSceneSeasonSearchString(show, season, episode)]
def _get_episode_search_strings(self, show, season, episode, abd=False):
return ['^' + x for x in show_name_helpers.makeSceneSearchString(show, season, episode, abd)]
def _get_episode_search_strings(self, show, season, episode, add_string=''):
return ['^' + x for x in show_name_helpers.makeSceneSearchString(show, season, episode)]
def _doSearch(self, searchStr, show=None, age=None):

View file

@ -80,7 +80,7 @@ class NewznabProvider(generic.NZBProvider):
def isEnabled(self):
return self.enabled
def _get_season_search_strings(self, show, season, episode, abd=False):
def _get_season_search_strings(self, show, season, episode):
if not show:
return [{}]
@ -100,13 +100,13 @@ class NewznabProvider(generic.NZBProvider):
cur_params['season'] = str(season)
# episode
cur_params['episode'] = self._get_episode_search_strings(show, season, episode, abd)[0]['ep']
cur_params['episode'] = self._get_episode_search_strings(show, season, episode)[0]['ep']
to_return.append(cur_params)
return to_return
def _get_episode_search_strings(self, show, season, episode, abd=False):
def _get_episode_search_strings(self, show, season, episode, add_string=''):
params = {}
@ -116,7 +116,12 @@ class NewznabProvider(generic.NZBProvider):
# search
params['q'] = helpers.sanitizeSceneName(show.name)
if abd:
if show.air_by_date:
date_str = str(episode)
params['season'] = date_str.partition('-')[0]
params['ep'] = date_str.partition('-')[2].replace('-', '/')
elif show.sports:
date_str = str(episode)
params['season'] = date_str.partition('-')[0]

View file

@ -63,6 +63,7 @@ class NextGenProvider(generic.TorrentProvider):
self.categories = '&c7=1&c24=1&c17=1&c22=1&c42=1&c46=1&c26=1&c28=1&c43=1&c4=1&c31=1&c45=1&c33=1'
self.last_login_check = None
self.login_opener = None
def isEnabled(self):
@ -130,7 +131,7 @@ class NextGenProvider(generic.TorrentProvider):
logger.log(u'Failed to login:' + str(error), logger.ERROR)
return False
def _get_season_search_strings(self, show, season, episode, abd=False):
def _get_season_search_strings(self, show, season, episode):
if not show:
return []
@ -140,22 +141,28 @@ class NextGenProvider(generic.TorrentProvider):
ep_string = show_name + ' S%02d' % int(season) #1) ShowName SXX
search_string['Season'].append(ep_string)
search_string['Episode'] = self._get_episode_search_strings(show, season, episode, abd)[0]['Episode']
search_string['Episode'] = self._get_episode_search_strings(show, season, episode)[0]['Episode']
return [search_string]
def _get_episode_search_strings(self, show, season, episode, abd=False, add_string=''):
def _get_episode_search_strings(self, show, season, episode, add_string=''):
search_string = {'Episode': []}
if not episode:
return []
if abd:
if show.air_by_date:
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
ep_string = sanitizeSceneName(show_name) + ' ' + \
str(episode).replace('-', '|') + '|' + \
helpers.custom_strftime('%b', str(episode))
episode.strftime('%b')
search_string['Episode'].append(ep_string)
elif show.sports:
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
ep_string = sanitizeSceneName(show_name) + ' ' + \
str(episode).replace('-', '|') + '|' + \
episode.strftime('%b')
search_string['Episode'].append(ep_string)
else:
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
@ -301,7 +308,7 @@ class NextGenProvider(generic.TorrentProvider):
for sqlShow in sqlResults:
curShow = helpers.findCertainShow(sickbeard.showList, int(sqlShow["showid"]))
curEp = curShow.getEpisode(int(sqlShow["season"]), int(sqlShow["episode"]))
searchString = self._get_episode_search_strings(curShow, curEp.scene_season, curEp.scene_episode, curShow.air_by_date, add_string='PROPER|REPACK')
searchString = self._get_episode_search_strings(curShow, curEp.scene_season, curEp.scene_episode, add_string='PROPER|REPACK')
for item in self._doSearch(searchString[0], show=curShow):
title, url = self._get_title_and_url(item)

View file

@ -58,13 +58,13 @@ class NyaaProvider(generic.TorrentProvider):
results = generic.TorrentProvider.getSearchResults(self, show, season, ep_objs, seasonSearch, manualSearch)
return results
def _get_season_search_strings(self, show, season, episode, abd=False):
def _get_season_search_strings(self, show, season, episode):
names = []
names.extend(show_name_helpers.makeSceneShowSearchStrings(show))
return names
def _get_episode_search_strings(self, show, season, episode, abd=False):
return self._get_season_search_strings(show, season, episode, abd)
def _get_episode_search_strings(self, show, season, episode, add_string=''):
return self._get_season_search_strings(show, season, episode)
def _doSearch(self, search_string, show=None, age=None):

View file

@ -53,11 +53,11 @@ class NZBsProvider(generic.NZBProvider):
if sickbeard.NZBS_UID in (None, "") or sickbeard.NZBS_HASH in (None, ""):
raise exceptions.AuthException("NZBs.org authentication details are empty, check your config")
def _get_season_search_strings(self, show, season, episode, abd=False):
return ['^' + x for x in show_name_helpers.makeSceneSeasonSearchString(show, season, episode, abd)]
def _get_season_search_strings(self, show, season, episode):
return ['^' + x for x in show_name_helpers.makeSceneSeasonSearchString(show, season, episode)]
def _get_episode_search_strings(self, show, season, episode, abd=False):
return ['^' + x for x in show_name_helpers.makeSceneSearchString(show, season, episode, abd)]
def _get_episode_search_strings(self, show, season, episode, add_string=''):
return ['^' + x for x in show_name_helpers.makeSceneSearchString(show, season, episode)]
def _doSearch(self, curString, show=None, age=None):

View file

@ -42,11 +42,11 @@ class NZBsRUSProvider(generic.NZBProvider):
if sickbeard.NZBSRUS_UID in (None, "") or sickbeard.NZBSRUS_HASH in (None, ""):
raise exceptions.AuthException("NZBs'R'US authentication details are empty, check your config")
def _get_season_search_strings(self, show, season, episode, abd=False):
return ['^' + x for x in show_name_helpers.makeSceneSeasonSearchString(show, season, episode, abd)]
def _get_season_search_strings(self, show, season, episode):
return ['^' + x for x in show_name_helpers.makeSceneSeasonSearchString(show, season, episode)]
def _get_episode_search_strings(self, show, season, episode, abd=False):
return ['^' + x for x in show_name_helpers.makeSceneSearchString(show, season, episode, abd)]
def _get_episode_search_strings(self, show, season, episode, add_string=''):
return ['^' + x for x in show_name_helpers.makeSceneSearchString(show, season, episode)]
def _doSearch(self, search, show=None, age=None):
params = {'uid': sickbeard.NZBSRUS_UID,

View file

@ -85,11 +85,11 @@ class OmgwtfnzbsProvider(generic.NZBProvider):
return True
def _get_season_search_strings(self, show, season, episode, abd=False):
return [x for x in show_name_helpers.makeSceneSeasonSearchString(show, season, episode, abd)]
def _get_season_search_strings(self, show, season, episode):
return [x for x in show_name_helpers.makeSceneSeasonSearchString(show, season, episode)]
def _get_episode_search_strings(self, show, season, episode, abd=False):
return [x for x in show_name_helpers.makeSceneSearchString(show, season, episode, abd)]
def _get_episode_search_strings(self, show, season, episode, add_string=''):
return [x for x in show_name_helpers.makeSceneSearchString(show, season, episode)]
def _get_title_and_url(self, item):
return (item['release'], item['getnzb'])

View file

@ -61,8 +61,6 @@ class PublicHDProvider(generic.TorrentProvider):
self.categories = {'Season': ['23'], 'Episode': ['7', '14', '24'], 'RSS': ['7', '14', '23', '24']}
self.session = requests.Session()
def isEnabled(self):
return sickbeard.PUBLICHD
@ -74,7 +72,7 @@ class PublicHDProvider(generic.TorrentProvider):
quality = Quality.sceneQuality(item[0])
return quality
def _get_season_search_strings(self, show, season, episode, abd=False):
def _get_season_search_strings(self, show, season, episode):
if not show:
return []
@ -87,22 +85,28 @@ class PublicHDProvider(generic.TorrentProvider):
ep_string = show_name + ' Season ' + str(season) #2) ShowName Season X
search_string['Season'].append(ep_string)
search_string['Episode'] = self._get_episode_search_strings(show, season, episode, abd)[0]['Episode']
search_string['Episode'] = self._get_episode_search_strings(show, season, episode)[0]['Episode']
return [search_string]
def _get_episode_search_strings(self, show, season, episode, abd=False, add_string=''):
def _get_episode_search_strings(self, show, season, episode, add_string=''):
search_string = {'Episode': []}
if not episode:
return []
if abd:
if show.air_by_date:
for show_name in set(allPossibleShowNames(show)):
ep_string = sanitizeSceneName(show_name) + ' ' + \
str(episode).replace('-', '|') + '|' + \
helpers.custom_strftime('%b', str(episode))
episode.strftime('%b')
search_string['Episode'].append(ep_string)
elif show.sports:
for show_name in set(allPossibleShowNames(show)):
ep_string = sanitizeSceneName(show_name) + ' ' + \
str(episode).replace('-', '|') + '|' + \
episode.strftime('%b')
search_string['Episode'].append(ep_string)
else:
for show_name in set(allPossibleShowNames(show)):
@ -276,7 +280,13 @@ class PublicHDProvider(generic.TorrentProvider):
for sqlShow in sqlResults:
curShow = helpers.findCertainShow(sickbeard.showList, int(sqlShow["showid"]))
curEp = curShow.getEpisode(int(sqlShow["season"]), int(sqlShow["episode"]))
searchString = self._get_episode_search_strings(curShow, curEp.scene_season, curEp.scene_episode, curShow.air_by_date, add_string='PROPER|REPACK')
season = curEp.scene_season
episode = curEp.scene_episode
if curShow.air_by_date or curShow.sports:
episode = curEp.airdate
searchString = self._get_episode_search_strings(curShow, season, episode, add_string='PROPER|REPACK')
for item in self._doSearch(searchString[0], show=curShow):
title, url = self._get_title_and_url(item)

View file

@ -42,7 +42,6 @@ class TorrentRssProvider(generic.TorrentProvider):
self.url = re.sub('\/$', '', url)
self.enabled = True
self.supportsBacklog = False
self.session = requests.Session()
def configStr(self):
return self.name + '|' + self.url + '|' + str(int(self.enabled))

View file

@ -63,8 +63,6 @@ class SCCProvider(generic.TorrentProvider):
self.categories = "c27=27&c17=17&c11=11"
self.session = None
self.headers = {'user-agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36'}
def isEnabled(self):
@ -101,7 +99,7 @@ class SCCProvider(generic.TorrentProvider):
return True
def _get_season_search_strings(self, show, season, episode, abd=False):
def _get_season_search_strings(self, show, season, episode):
if not show:
return []
@ -111,22 +109,28 @@ class SCCProvider(generic.TorrentProvider):
ep_string = show_name + ' S%02d' % int(season) #1) ShowName SXX
search_string['Season'].append(ep_string)
search_string['Episode'] = self._get_episode_search_strings(show, season, episode, abd)[0]['Episode']
search_string['Episode'] = self._get_episode_search_strings(show, season, episode)[0]['Episode']
return [search_string]
def _get_episode_search_strings(self, show, season, episode, abd=False, add_string=''):
def _get_episode_search_strings(self, show, season, episode, add_string=''):
search_string = {'Episode': []}
if not episode:
return []
if abd:
if show.air_by_date:
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
ep_string = sanitizeSceneName(show_name) + ' ' + \
str(episode).replace('-', '|') + '|' + \
helpers.custom_strftime('%b', str(episode))
episode.strftime('%b')
search_string['Episode'].append(ep_string)
elif show.sports:
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
ep_string = sanitizeSceneName(show_name) + ' ' + \
str(episode).replace('-', '|') + '|' + \
episode.strftime('%b')
search_string['Episode'].append(ep_string)
else:
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
@ -278,7 +282,13 @@ class SCCProvider(generic.TorrentProvider):
for sqlShow in sqlResults:
curShow = helpers.findCertainShow(sickbeard.showList, int(sqlShow["showid"]))
curEp = curShow.getEpisode(int(sqlShow["season"]), int(sqlShow["episode"]))
searchString = self._get_episode_search_strings(curShow, curEp.scene_season, curEp.scene_episode, curShow.air_by_date, add_string='PROPER|REPACK')
season = curEp.scene_season
episode = curEp.scene_episode
if curShow.air_by_date or curShow.sports:
episode = curEp.airdate
searchString = self._get_episode_search_strings(curShow, season, episode, add_string='PROPER|REPACK')
for item in self._doSearch(searchString[0], show=curShow):
title, url = self._get_title_and_url(item)

View file

@ -58,10 +58,6 @@ class SpeedCDProvider(generic.TorrentProvider):
self.categories = {'Season': {'c14':1}, 'Episode': {'c2':1, 'c49':1}, 'RSS': {'c14':1, 'c2':1, 'c49':1}}
self.session = requests.Session()
self.headers = {'user-agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36'}
def isEnabled(self):
return sickbeard.SPEEDCD
@ -80,7 +76,6 @@ class SpeedCDProvider(generic.TorrentProvider):
}
self.session = requests.Session()
self.session.headers.update(self.headers)
try:
response = self.session.post(self.urls['login'], data=login_params, timeout=30, verify=False)
@ -95,7 +90,7 @@ class SpeedCDProvider(generic.TorrentProvider):
return True
def _get_season_search_strings(self, show, season, episode, abd=False):
def _get_season_search_strings(self, show, season, episode):
if not show:
return []
@ -107,22 +102,28 @@ class SpeedCDProvider(generic.TorrentProvider):
search_string['Season'].append(ep_string)
#Building the search string with the episodes we need
search_string['Episode'] = self._get_episode_search_strings(show, season, episode, abd)[0]['Episode']
search_string['Episode'] = self._get_episode_search_strings(show, season, episode)[0]['Episode']
return [search_string]
def _get_episode_search_strings(self, show, season, episode, abd=False, add_string=''):
def _get_episode_search_strings(self, show, season, episode, add_string=''):
search_string = {'Episode': []}
if not episode:
return []
if abd:
if show.air_by_date:
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
ep_string = sanitizeSceneName(show_name) + ' ' + \
str(episode).replace('-', '|') + '|' + \
helpers.custom_strftime('%b', str(episode))
episode.strftime('%b')
search_string['Episode'].append(ep_string)
elif show.sports:
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
ep_string = sanitizeSceneName(show_name) + ' ' + \
str(episode).replace('-', '|') + '|' + \
episode.strftime('%b')
search_string['Episode'].append(ep_string)
else:
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
@ -237,7 +238,13 @@ class SpeedCDProvider(generic.TorrentProvider):
for sqlShow in sqlResults:
curShow = helpers.findCertainShow(sickbeard.showList, int(sqlShow["showid"]))
curEp = curShow.getEpisode(int(sqlShow["season"]), int(sqlShow["episode"]))
searchString = self._get_episode_search_strings(curShow, curEp.scene_season, curEp.scene_episode, curShow.air_by_date, add_string='PROPER|REPACK')
season = curEp.scene_season
episode = curEp.scene_episode
if curShow.air_by_date or curShow.sports:
episode = curEp.airdate
searchString = self._get_episode_search_strings(curShow, season, episode,add_string='PROPER|REPACK')
for item in self._doSearch(searchString[0], show=curShow):
title, url = self._get_title_and_url(item)

View file

@ -72,8 +72,6 @@ class ThePirateBayProvider(generic.TorrentProvider):
self.re_title_url = '/torrent/(?P<id>\d+)/(?P<title>.*?)//1".+?(?P<url>magnet.*?)//1".+?(?P<seeders>\d+)</td>.+?(?P<leechers>\d+)</td>'
self.session = requests.Session()
def isEnabled(self):
return sickbeard.THEPIRATEBAY
@ -172,7 +170,7 @@ class ThePirateBayProvider(generic.TorrentProvider):
return title
def _get_season_search_strings(self, show, season, episode, abd=False):
def _get_season_search_strings(self, show, season, episode):
if not show:
return []
@ -187,11 +185,11 @@ class ThePirateBayProvider(generic.TorrentProvider):
ep_string = show_name + ' Season ' + str(season) + ' -Ep*' #2) ShowName Season X
search_string['Season'].append(ep_string)
search_string['Episode'] = self._get_episode_search_strings(show, season, episode, abd)[0]['Episode']
search_string['Episode'] = self._get_episode_search_strings(show, season, episode)[0]['Episode']
return [search_string]
def _get_episode_search_strings(self, show, season, episode, abd=False, add_string=''):
def _get_episode_search_strings(self, show, season, episode, add_string=''):
search_string = {'Episode': []}
@ -200,11 +198,17 @@ class ThePirateBayProvider(generic.TorrentProvider):
self.show = show
if abd:
if show.air_by_date:
for show_name in set(allPossibleShowNames(show)):
ep_string = sanitizeSceneName(show_name) + ' ' + \
str(episode).replace('-', '|') + '|' + \
helpers.custom_strftime('%b', str(episode))
episode.strftime('%b')
search_string['Episode'].append(ep_string)
elif show.sports:
for show_name in set(allPossibleShowNames(show)):
ep_string = sanitizeSceneName(show_name) + ' ' + \
str(episode).replace('-', '|') + '|' + \
episode.strftime('%b')
search_string['Episode'].append(ep_string)
else:
for show_name in set(allPossibleShowNames(show)):
@ -382,7 +386,13 @@ class ThePirateBayProvider(generic.TorrentProvider):
for sqlShow in sqlResults:
curShow = helpers.findCertainShow(sickbeard.showList, int(sqlShow["showid"]))
curEp = curShow.getEpisode(int(sqlShow["season"]), int(sqlShow["episode"]))
searchString = self._get_episode_search_strings(curShow, curEp.scene_season, curEp.scene_episode, curShow.air_by_date, add_string='PROPER|REPACK')
season = curEp.scene_season
episode = curEp.scene_episode
if curShow.air_by_date or curShow.sports:
episode = curEp.airdate
searchString = self._get_episode_search_strings(curShow, season, episode, add_string='PROPER|REPACK')
for item in self._doSearch(searchString[0], show=curShow):
title, url = self._get_title_and_url(item)

View file

@ -56,8 +56,6 @@ class TorrentDayProvider(generic.TorrentProvider):
self.url = self.urls['base_url']
self.session = requests.Session()
self.cookies = None
self.categories = {'Season': {'c14': 1}, 'Episode': {'c2': 1, 'c26': 1, 'c7': 1, 'c24': 1},
@ -114,7 +112,7 @@ class TorrentDayProvider(generic.TorrentProvider):
return True
def _get_season_search_strings(self, show, season, episode, abd=False):
def _get_season_search_strings(self, show, season, episode):
if not show:
return []
@ -124,22 +122,28 @@ class TorrentDayProvider(generic.TorrentProvider):
ep_string = show_name + ' S%02d' % int(season) #1) ShowName SXX
search_string['Season'].append(ep_string)
search_string['Episode'] = self._get_episode_search_strings(show, season, episode, abd)[0]['Episode']
search_string['Episode'] = self._get_episode_search_strings(show, season, episode)[0]['Episode']
return [search_string]
def _get_episode_search_strings(self, show, season, episode, abd=False, add_string=''):
def _get_episode_search_strings(self, show, season, episode, add_string=''):
search_string = {'Episode': []}
if not episode:
return []
if abd:
if show.air_by_date:
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
ep_string = sanitizeSceneName(show_name) + ' ' + \
str(episode).replace('-', '|') + '|' + \
helpers.custom_strftime('%b', str(episode))
episode.strftime('%b')
search_string['Episode'].append(ep_string)
if show.sports:
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
ep_string = sanitizeSceneName(show_name) + ' ' + \
str(episode).replace('-', '|') + '|' + \
episode.strftime('%b')
search_string['Episode'].append(ep_string)
else:
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
@ -250,7 +254,13 @@ class TorrentDayProvider(generic.TorrentProvider):
for sqlShow in sqlResults:
curShow = helpers.findCertainShow(sickbeard.showList, int(sqlShow["showid"]))
curEp = curShow.getEpisode(int(sqlShow["season"]), int(sqlShow["episode"]))
searchString = self._get_episode_search_strings(curShow, curEp.scene_season, curEp.scene_episode, curShow.air_by_date, add_string='PROPER|REPACK')
season = curEp.scene_season
episode = curEp.scene_episode
if curShow.air_by_date or curShow.sports:
episode = curEp.airdate
searchString = self._get_episode_search_strings(curShow, season, episode, add_string='PROPER|REPACK')
for item in self._doSearch(searchString[0], show=curShow):
title, url = self._get_title_and_url(item)

View file

@ -59,8 +59,6 @@ class TorrentLeechProvider(generic.TorrentProvider):
self.categories = "2,26,27,32"
self.session = None
def isEnabled(self):
return sickbeard.TORRENTLEECH
@ -96,7 +94,7 @@ class TorrentLeechProvider(generic.TorrentProvider):
return True
def _get_season_search_strings(self, show, season, episode, abd=False):
def _get_season_search_strings(self, show, season, episode):
if not show:
return []
@ -106,22 +104,28 @@ class TorrentLeechProvider(generic.TorrentProvider):
ep_string = show_name + ' S%02d' % int(season) #1) ShowName SXX
search_string['Season'].append(ep_string)
search_string['Episode'] = self._get_episode_search_strings(show, season, episode, abd)[0]['Episode']
search_string['Episode'] = self._get_episode_search_strings(show, season, episode)[0]['Episode']
return [search_string]
def _get_episode_search_strings(self, show, season, episode, abd=False, add_string=''):
def _get_episode_search_strings(self, show, season, episode, add_string=''):
search_string = {'Episode': []}
if not episode:
return []
if abd:
if show.air_by_date:
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
ep_string = sanitizeSceneName(show_name) + ' ' + \
str(episode).replace('-', '|') + '|' + \
helpers.custom_strftime('%b', str(episode))
episode.strftime('%b')
search_string['Episode'].append(ep_string)
if show.sports:
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
ep_string = sanitizeSceneName(show_name) + ' ' + \
str(episode).replace('-', '|') + '|' + \
episode.strftime('%b')
search_string['Episode'].append(ep_string)
else:
for show_name in set(show_name_helpers.allPossibleShowNames(show)):
@ -254,7 +258,13 @@ class TorrentLeechProvider(generic.TorrentProvider):
for sqlShow in sqlResults:
curShow = helpers.findCertainShow(sickbeard.showList, int(sqlShow["showid"]))
curEp = curShow.getEpisode(int(sqlShow["season"]), int(sqlShow["episode"]))
searchString = self._get_episode_search_strings(curShow, curEp.scene_season, curEp.scene_episode, curShow.air_by_date, add_string='PROPER|REPACK')
season = curEp.scene_season
episode = curEp.scene_episode
if curShow.air_by_date or curShow.sports:
episode = curEp.airdate
searchString = self._get_episode_search_strings(curShow, season, episode, add_string='PROPER|REPACK')
for item in self._doSearch(searchString[0], show=curShow):
title, url = self._get_title_and_url(item)

View file

@ -380,9 +380,7 @@ def searchProviders(show, season, episode=None, manualSearch=False):
# skip non-tv crap
curResults[curEp] = filter(
lambda x: show_name_helpers.filterBadReleases(x.name) and show_name_helpers.isGoodResult(x.name,
show),
curResults[curEp])
lambda x: show_name_helpers.filterBadReleases(x.name) and show_name_helpers.isGoodResult(x.name,show),curResults[curEp])
if curEp in foundResults:
foundResults[curEp] += curResults[curEp]

View file

@ -96,6 +96,7 @@ class BacklogSearcher:
# get separate lists of the season/date shows
#season_shows = [x for x in show_list if not x.air_by_date]
air_by_date_shows = [x for x in show_list if x.air_by_date]
sports_shows = [x for x in show_list if x.sports]
# figure out how many segments of air by date shows we're going to do
air_by_date_segments = []
@ -104,6 +105,12 @@ class BacklogSearcher:
logger.log(u"Air-by-date segments: " + str(air_by_date_segments), logger.DEBUG)
sports_segments = []
for cur_id in [x.indexerid for x in sports_shows]:
sports_segments += self._get_sports_segments(cur_id, fromDate)
logger.log(u"Sports segments: " + str(sports_segments), logger.DEBUG)
#totalSeasons = float(len(numSeasonResults) + len(air_by_date_segments))
#numSeasonsDone = 0.0
@ -115,6 +122,8 @@ class BacklogSearcher:
if curShow.air_by_date:
segments = [x[1] for x in self._get_air_by_date_segments(curShow.indexerid, fromDate)]
elif curShow.sports:
segments = [x[1] for x in self._get_sports_segments(curShow.indexerid, fromDate)]
else:
segments = self._get_season_segments(curShow.indexerid, fromDate)
@ -169,7 +178,7 @@ class BacklogSearcher:
# query the DB for all dates for this show
myDB = db.DBConnection()
num_air_by_date_results = myDB.select(
"SELECT airdate, showid FROM tv_episodes ep, tv_shows show WHERE season != 0 AND ep.showid = show.indexer_id AND show.paused = 0 ANd ep.airdate > ? AND ep.showid = ?",
"SELECT airdate, showid FROM tv_episodes ep, tv_shows show WHERE season != 0 AND ep.showid = show.indexer_id AND show.paused = 0 ANd ep.airdate > ? AND ep.showid = ? AND show.air_by_date = 1",
[fromDate.toordinal(), indexer_id])
# break them apart into month/year strings
@ -185,6 +194,26 @@ class BacklogSearcher:
return air_by_date_segments
def _get_sports_segments(self, indexer_id, fromDate):
# query the DB for all dates for this show
myDB = db.DBConnection()
num_sports_results = myDB.select(
"SELECT airdate, showid FROM tv_episodes ep, tv_shows show WHERE season != 0 AND ep.showid = show.indexer_id AND show.paused = 0 ANd ep.airdate > ? AND ep.showid = ? AND show.sports = 1",
[fromDate.toordinal(), indexer_id])
# break them apart into month/year strings
sports_segments = []
for cur_result in num_sports_results:
cur_date = datetime.date.fromordinal(int(cur_result["airdate"]))
cur_date_str = str(cur_date)[:7]
cur_indexer_id = int(cur_result["showid"])
cur_result_tuple = (cur_indexer_id, cur_date_str)
if cur_result_tuple not in sports_segments:
sports_segments.append(cur_result_tuple)
return sports_segments
def _set_lastBacklog(self, when):
logger.log(u"Setting the last backlog in the DB to " + str(when), logger.DEBUG)

View file

@ -192,7 +192,7 @@ class BacklogQueueItem(generic_queue.QueueItem):
myDB = db.DBConnection()
# see if there is anything in this season worth searching for
if not self.show.air_by_date:
if not self.show.air_by_date and not self.show.sports:
statusResults = myDB.select("SELECT status FROM tv_episodes WHERE showid = ? AND season = ?",
[self.show.indexerid, self.segment])
else:

View file

@ -119,7 +119,7 @@ def makeSceneShowSearchStrings(show):
return map(sanitizeSceneName, showNames)
def makeSceneSeasonSearchString(show, season, episode, abd=False, extraSearchType=None):
def makeSceneSeasonSearchString(show, season, episode, extraSearchType=None):
myDB = db.DBConnection()
if show.air_by_date:
@ -127,7 +127,11 @@ def makeSceneSeasonSearchString(show, season, episode, abd=False, extraSearchTyp
# the search string for air by date shows is just
seasonStrings = [season]
elif show.sports:
numseasons = 0
# the search string for air by date shows is just
seasonStrings = [season]
else:
numseasonsSQlResult = myDB.select(
"SELECT COUNT(DISTINCT season) as numseasons FROM tv_episodes WHERE showid = ? and season != 0",
@ -153,12 +157,12 @@ def makeSceneSeasonSearchString(show, season, episode, abd=False, extraSearchTyp
toReturn.append(curShow + "." + cur_season)
# episode
toReturn.extend(makeSceneSearchString(show, season, episode, abd))
toReturn.extend(makeSceneSearchString(show, season, episode))
return toReturn
def makeSceneSearchString(show, season, episode, abd=False):
def makeSceneSearchString(show, season, episode):
myDB = db.DBConnection()
numseasonsSQlResult = myDB.select(
"SELECT COUNT(DISTINCT season) as numseasons FROM tv_episodes WHERE showid = ? and season != 0",
@ -170,8 +174,10 @@ def makeSceneSearchString(show, season, episode, abd=False):
numepisodes = int(numepisodesSQlResult[0][0])
# see if we should use dates instead of episodes
if abd and episode != datetime.date.fromordinal(1):
epStrings = [str(episode.airdate)]
if show.air_by_date and episode != datetime.date.fromordinal(1):
epStrings = [str(episode)]
if show.sports and episode != datetime.date.fromordinal(1):
epStrings = [str(episode)]
else:
epStrings = ["S%02iE%02i" % (int(season), int(episode)),
"%ix%02i" % (int(season), int(episode))]

View file

@ -294,8 +294,11 @@ class QueueItemAdd(ShowQueueItem):
self.show.paused = False
# be smartish about this
if self.show.genre and "talk show" in self.show.genre.lower() or "sports" in self.show.classification.lower():
if self.show.genre and "talk show" in self.show.genre.lower():
self.show.air_by_date = 1
elif self.show.genre and "sports" in self.show.genre.lower():
self.show.sports = 1
except sickbeard.indexer_exception, e:
logger.log(

View file

@ -118,7 +118,7 @@ class TraktChecker():
return
logger.log(u"Setting episode s" + str(s) + "e" + str(e) + " of show " + show.name + " to wanted")
# figure out what segment the episode is in and remember it so we can backlog it
if epObj.show.air_by_date:
if epObj.show.air_by_date or epObj.show.sports:
ep_segment = str(epObj.airdate)[:7]
else:
ep_segment = epObj.season

View file

@ -76,6 +76,7 @@ class TVShow(object):
self.startyear = 0
self.paused = 0
self.air_by_date = 0
self.sports = 0
self.subtitles = int(sickbeard.SUBTITLES_DEFAULT if sickbeard.SUBTITLES_DEFAULT else 0)
self.dvdorder = 0
self.archive_firstmatch = 0
@ -138,7 +139,7 @@ class TVShow(object):
sql_selection = sql_selection + " FROM tv_episodes tve WHERE showid = " + str(self.indexerid)
if season is not None:
if not self.air_by_date:
if not self.air_by_date and not self.sports:
sql_selection = sql_selection + " AND season = " + str(season)
else:
segment_year, segment_month = map(int, str(season).split('-'))
@ -552,7 +553,7 @@ class TVShow(object):
logger.log(u"Unable to parse the filename " + file + " into a valid episode", logger.ERROR)
return None
if len(parse_result.episode_numbers) == 0 and not parse_result.air_by_date:
if len(parse_result.episode_numbers) == 0 and not (parse_result.air_by_date or parse_result.sports):
logger.log("parse_result: " + str(parse_result))
logger.log(u"No episode number found in " + file + ", ignoring it", logger.ERROR)
return None
@ -563,7 +564,7 @@ class TVShow(object):
rootEp = None
# if we have an air-by-date show then get the real season/episode numbers
if parse_result.air_by_date:
if parse_result.air_by_date or parse_result.sports:
try:
lINDEXER_API_PARMS = sickbeard.indexerApi(self.indexer).api_params.copy()
@ -575,7 +576,12 @@ class TVShow(object):
t = sickbeard.indexerApi(self.indexer).indexer(**lINDEXER_API_PARMS)
epObj = None
if parse_result.air_by_date:
epObj = t[self.indexerid].airedOn(parse_result.air_date)[0]
elif parse_result.sports:
epObj = t[self.indexerid].airedOn(parse_result.sports_date)[0]
season = int(epObj["seasonnumber"])
episodes = [int(epObj["episodenumber"])]
except sickbeard.indexer_episodenotfound:
@ -730,6 +736,10 @@ class TVShow(object):
if not self.air_by_date:
self.air_by_date = 0
self.sports = sqlResults[0]["sports"]
if not self.sports:
self.sports = 0
self.subtitles = sqlResults[0]["subtitles"]
if self.subtitles:
self.subtitles = 1
@ -1023,6 +1033,7 @@ class TVShow(object):
"flatten_folders": self.flatten_folders,
"paused": self.paused,
"air_by_date": self.air_by_date,
"sports": self.sports,
"subtitles": self.subtitles,
"dvdorder": self.dvdorder,
"archive_firstmatch": self.archive_firstmatch,
@ -1935,7 +1946,7 @@ class TVEpisode(object):
# if there's no release group then replace it with a reasonable facsimile
if not replace_map['%RN']:
if self.show.air_by_date:
if self.show.air_by_date or self.show.sports:
result_name = result_name.replace('%RN', '%S.N.%A.D.%E.N-SiCKBEARD')
result_name = result_name.replace('%rn', '%s.n.%A.D.%e.n-sickbeard')
else:
@ -2066,6 +2077,8 @@ class TVEpisode(object):
# we only use ABD if it's enabled, this is an ABD show, AND this is not a multi-ep
if self.show.air_by_date and sickbeard.NAMING_CUSTOM_ABD and not self.relatedEps:
pattern = sickbeard.NAMING_ABD_PATTERN
elif self.show.sports and sickbeard.NAMING_CUSTOM_SPORTS and not self.relatedEps:
pattern = sickbeard.NAMING_SPORTS_PATTERN
else:
pattern = sickbeard.NAMING_PATTERN
@ -2086,6 +2099,8 @@ class TVEpisode(object):
# we only use ABD if it's enabled, this is an ABD show, AND this is not a multi-ep
if self.show.air_by_date and sickbeard.NAMING_CUSTOM_ABD and not self.relatedEps:
pattern = sickbeard.NAMING_ABD_PATTERN
elif self.show.sports and sickbeard.NAMING_CUSTOM_SPORTS and not self.relatedEps:
pattern = sickbeard.NAMING_CUSTOM_SPORTS
else:
pattern = sickbeard.NAMING_PATTERN

View file

@ -281,7 +281,7 @@ class TVCache():
episodes = parse_result.episode_numbers
# if we have an air-by-date show then get the real season/episode numbers
if parse_result.air_by_date and indexer_id:
if (parse_result.air_by_date or parse_result.sports) and indexer_id:
try:
lINDEXER_API_PARMS = sickbeard.indexerApi(self.indexer).api_params.copy()
if not (indexer_lang == "" or indexer_lang == "en" or indexer_lang == None):
@ -289,7 +289,15 @@ class TVCache():
t = sickbeard.indexerApi(self.indexer).indexer(**lINDEXER_API_PARMS)
epObj = None
if parse_result.air_by_date:
epObj = t[indexer_id].airedOn(parse_result.air_date)[0]
elif parse_result.sports:
epObj = t[indexer_id].airedOn(parse_result.sports_date)[0]
if epObj is None:
return None
season = int(epObj["seasonnumber"])
episodes = [int(epObj["episodenumber"])]
except sickbeard.indexer_episodenotfound:

View file

@ -975,7 +975,7 @@ class CMD_EpisodeSetStatus(ApiCall):
for epObj in ep_list:
if ep_segment == None and self.status == WANTED:
# figure out what segment the episode is in and remember it so we can backlog it
if showObj.air_by_date:
if showObj.air_by_date or showObj.sports:
ep_segment = str(epObj.airdate)[:7]
else:
ep_segment = epObj.season
@ -1764,6 +1764,7 @@ class CMD_Show(ApiCall):
showDict["show_name"] = showObj.name
showDict["paused"] = showObj.paused
showDict["air_by_date"] = showObj.air_by_date
showDict["sports"] = showObj.sports
showDict["flatten_folders"] = showObj.flatten_folders
#clean up tvdb horrible airs field
showDict["airs"] = str(showObj.airs).replace('am', ' AM').replace('pm', ' PM').replace(' ', ' ')
@ -2526,6 +2527,7 @@ class CMD_Shows(ApiCall):
"quality": _get_quality_string(curShow.quality),
"language": curShow.lang,
"air_by_date": curShow.air_by_date,
"sports": curShow.sports,
"indexerid": curShow.indexerid,
"network": curShow.network,
"show_name": curShow.name,

View file

@ -1134,7 +1134,8 @@ class ConfigPostProcessing:
rename_episodes=None, unpack=None,
move_associated_files=None, tv_download_dir=None, naming_custom_abd=None,
naming_abd_pattern=None, naming_strip_year=None, use_failed_downloads=None,
delete_failed=None, extra_scripts=None):
delete_failed=None, extra_scripts=None,
naming_custom_sports=None, naming_sports_pattern=None):
results = []
@ -1163,17 +1164,11 @@ class ConfigPostProcessing:
sickbeard.RENAME_EPISODES = config.checkbox_to_value(rename_episodes)
sickbeard.MOVE_ASSOCIATED_FILES = config.checkbox_to_value(move_associated_files)
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.USE_FAILED_DOWNLOADS = config.checkbox_to_value(use_failed_downloads)
sickbeard.DELETE_FAILED = config.checkbox_to_value(delete_failed)
sickbeard.METADATA_XBMC = xbmc_data
sickbeard.METADATA_XBMC_12PLUS = xbmc_12plus_data
sickbeard.METADATA_MEDIABROWSER = mediabrowser_data
sickbeard.METADATA_PS3 = sony_ps3_data
sickbeard.METADATA_WDTV = wdtv_data
sickbeard.METADATA_TIVO = tivo_data
sickbeard.metadata_provider_dict['XBMC'].set_config(sickbeard.METADATA_XBMC)
sickbeard.metadata_provider_dict['XBMC 12+'].set_config(sickbeard.METADATA_XBMC_12PLUS)
sickbeard.metadata_provider_dict['MediaBrowser'].set_config(sickbeard.METADATA_MEDIABROWSER)
@ -1188,12 +1183,18 @@ class ConfigPostProcessing:
else:
results.append("You tried saving an invalid naming config, not saving your naming settings")
if self.isNamingValid(naming_abd_pattern, None, True) != "invalid":
if self.isNamingValid(naming_abd_pattern, None, abd=True) != "invalid":
sickbeard.NAMING_ABD_PATTERN = naming_abd_pattern
else:
results.append(
"You tried saving an invalid air-by-date naming config, not saving your air-by-date settings")
if self.isNamingValid(naming_sports_pattern, None, sports=True) != "invalid":
sickbeard.NAMING_SPORTS_PATTERN = naming_sports_pattern
else:
results.append(
"You tried saving an invalid sports naming config, not saving your sports settings")
sickbeard.save_config()
if len(results) > 0:
@ -1207,19 +1208,19 @@ class ConfigPostProcessing:
redirect("/config/postProcessing/")
@cherrypy.expose
def testNaming(self, pattern=None, multi=None, abd=False):
def testNaming(self, pattern=None, multi=None, abd=False, sports=False):
if multi is not None:
multi = int(multi)
result = naming.test_name(pattern, multi, abd)
result = naming.test_name(pattern, multi, abd, sports)
result = ek.ek(os.path.join, result['dir'], result['name'])
return result
@cherrypy.expose
def isNamingValid(self, pattern=None, multi=None, abd=False):
def isNamingValid(self, pattern=None, multi=None, abd=False, sports=False):
if pattern is None:
return "invalid"
@ -1228,6 +1229,11 @@ class ConfigPostProcessing:
is_valid = naming.check_valid_abd_naming(pattern)
require_season_folders = False
# sport shows just need one check, we don't need to worry about season folders
elif sports:
is_valid = naming.check_valid_sports_naming(pattern)
require_season_folders = False
else:
# check validity of single and multi ep cases for the whole path
is_valid = naming.check_valid_naming(pattern, multi)
@ -2829,13 +2835,13 @@ class Home:
def plotDetails(self, show, season, episode):
result = db.DBConnection().action(
"SELECT description FROM tv_episodes WHERE showid = ? AND season = ? AND episode = ?",
(show, season, episode)).fetchone()
(int(show), int(season), int(episode))).fetchone()
return result['description'] if result else 'Episode not found.'
@cherrypy.expose
def editShow(self, show=None, location=None, anyQualities=[], bestQualities=[], exceptions_list=[],
flatten_folders=None, paused=None, directCall=False, air_by_date=None, dvdorder=None, indexerLang=None,
subtitles=None, archive_firstmatch=None, rls_ignore_words=None, rls_require_words=None):
flatten_folders=None, paused=None, directCall=False, air_by_date=None, sports=None, dvdorder=None,
indexerLang=None,subtitles=None, archive_firstmatch=None, rls_ignore_words=None, rls_require_words=None):
if show is None:
errString = "Invalid show ID: " + str(show)
@ -2872,6 +2878,7 @@ class Home:
archive_firstmatch = config.checkbox_to_value(archive_firstmatch)
paused = config.checkbox_to_value(paused)
air_by_date = config.checkbox_to_value(air_by_date)
sports = config.checkbox_to_value(sports)
subtitles = config.checkbox_to_value(subtitles)
indexer_lang = indexerLang
@ -2915,6 +2922,7 @@ class Home:
showObj.paused = paused
showObj.air_by_date = air_by_date
showObj.sports = sports
showObj.subtitles = subtitles
showObj.lang = indexer_lang
showObj.dvdorder = dvdorder
@ -3129,7 +3137,7 @@ class Home:
if int(status) == WANTED:
# figure out what episodes are wanted so we can backlog them
if epObj.show.air_by_date:
if epObj.show.air_by_date or epObj.show.sports:
segment = str(epObj.airdate)[:7]
else:
segment = epObj.season
@ -3406,7 +3414,7 @@ class Home:
return json.dumps({'result': 'failure'})
# figure out what segment the episode is in and remember it so we can backlog it
if ep_obj.show.air_by_date:
if ep_obj.show.air_by_date or ep_obj.show.sports:
segment = str(ep_obj.airdate)[:7]
else:
segment = ep_obj.season

View file

@ -238,6 +238,7 @@ class BasicTests(unittest.TestCase):
if DEBUG or verbose:
print 'air_by_date:', test_result.air_by_date, 'air_date:', test_result.air_date
print 'sports:', test_result.sports, 'air_date:', test_result.air_date
print test_result
print result
self.assertEqual(test_result.which_regex, [section])

View file

@ -76,6 +76,7 @@ sickbeard.FLATTEN_FOLDERS_DEFAULT = 0
sickbeard.NAMING_PATTERN = ''
sickbeard.NAMING_ABD_PATTERN = ''
sickbeard.NAMING_SPORTS_PATTERN = ''
sickbeard.NAMING_MULTI_EP = 1

View file

@ -28,8 +28,9 @@ sys.path.append(os.path.abspath('../lib'))
import test_lib as test
import sickbeard
from sickbeard.helpers import sanitizeSceneName, custom_strftime
from sickbeard.helpers import sanitizeSceneName
from sickbeard.tv import TVShow
from sickbeard.name_parser.parser import NameParser, InvalidNameException
class XEMBasicTests(test.SickbeardTestDBCase):
def loadFromDB(self):
@ -53,12 +54,31 @@ class XEMBasicTests(test.SickbeardTestDBCase):
ep = show.getEpisode(21, 17)
ep.airdate = datetime.datetime.now()
ep_date_formated = ep.airdate.strftime('%b')
show_name = 'UFC'
if show_name.lower() in sickbeard.showList:
print 'good'
else:
print 'bad'
# parse the file name
parse_result = None
title = u'UFC 155 Dos Santos vs Velasquez 29th Dec 2012 HDTV x264-Sir Paul'
try:
myParser = NameParser(False, 1)
parse_result = myParser.parse(title, True)
except InvalidNameException:
print(u"Unable to parse the filename " + title + " into a valid episode")
print parse_result
search_string = {'Episode':[]}
episode = ep.airdate
str(episode).replace('-', '|')
ep_string = sanitizeSceneName(show.name) + ' ' + \
str(episode).replace('-', '|') + '|' + \
sickbeard.helpers.custom_strftime('%b', episode)
episode.strftime('%b')
search_string['Episode'].append(ep_string)