From 670e30efda8352ce0f1340b6d30363ec835f56cf Mon Sep 17 00:00:00 2001 From: JackDandy Date: Sat, 14 Nov 2015 13:49:54 +0000 Subject: [PATCH] Change increase show search capability when using plain text and also add TVDB id, IMDb id and IMDb url search. Change improve existing show page and the handling when an attempt to add a show to an existing location --- CHANGES.md | 2 + gui/slick/css/dark.css | 5 +- gui/slick/css/light.css | 41 ++++--- .../default/home_addExistingShow.tmpl | 63 ++++++---- .../interfaces/default/home_massAddTable.tmpl | 105 +++++++++------- .../interfaces/default/home_newShow.tmpl | 4 +- gui/slick/js/addExistingShow.js | 5 +- sickbeard/webserve.py | 115 +++++++++++++++--- 8 files changed, 227 insertions(+), 113 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 70137352..e04cbb26 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -63,6 +63,8 @@ * Change replace trakt with libtrakt for API v2 * Change Trakt notification config to only handle PIN authentication with the service * Remove all other Trakt deprecated API V1 service features pending reconsideration +* Change increase show search capability when using plain text and also add TVDB id, IMDb id and IMDb url search +* Change improve existing show page and the handling when an attempt to add a show to an existing location [develop changelog] Enable Alpha Ratio again now that the secure login page over https is fixed diff --git a/gui/slick/css/dark.css b/gui/slick/css/dark.css index a4a38cd0..84c469bb 100644 --- a/gui/slick/css/dark.css +++ b/gui/slick/css/dark.css @@ -526,7 +526,7 @@ h2.day, h2.network{ .carousel-indicators .active{ background:#8DBEEE; border-color:#8DBEEE -} +} /* ======================================================================= config*.tmpl @@ -655,6 +655,7 @@ span.path{ background-color:#333 } +#addRootDirTable td label .filepath.red-text, .red-text{ color:#d33 } @@ -1444,4 +1445,4 @@ jquery.confirm.css #confirmBox .red:hover{ background-color:#A13331 -} \ No newline at end of file +} diff --git a/gui/slick/css/light.css b/gui/slick/css/light.css index f44be5e6..f3906ddb 100644 --- a/gui/slick/css/light.css +++ b/gui/slick/css/light.css @@ -23,12 +23,12 @@ inc_top.tmpl background:url("../css/lib/images/animated-overlay.gif") } -.ui-dialog, +.ui-dialog, .ui-dialog-buttonpane{ background:#eceadf url("../css/lib/images/ui-bg_fine-grain_10_eceadf_60x60.png") 50% 50% repeat !important } -.ui-accordion-content, +.ui-accordion-content, .ui-tabs-panel{ background:#ededed !important; background-image:none !important @@ -50,41 +50,41 @@ inc_top.tmpl background:#fff url("../css/lib/images/ui-bg_flat_0_ffffff_40x100.png") 50% 50% repeat-x } -.ui-state-default, -.ui-widget-content .ui-state-default, +.ui-state-default, +.ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default{ background:#fff; border:1px solid #CCC } -.ui-state-hover, -.ui-widget-content .ui-state-hover, -.ui-widget-header .ui-state-hover, -.ui-state-focus, -.ui-widget-content .ui-state-focus, +.ui-state-hover, +.ui-widget-content .ui-state-hover, +.ui-widget-header .ui-state-hover, +.ui-state-focus, +.ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus{ background:#fff } -.ui-state-active, -.ui-widget-content .ui-state-active, +.ui-state-active, +.ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active{ background:#F7F7F7 } -.ui-state-highlight, -.ui-widget-content .ui-state-highlight, +.ui-state-highlight, +.ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight{ background:#fbf9ee url("../css/lib/images/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x } -.ui-state-error, -.ui-widget-content .ui-state-error, +.ui-state-error, +.ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error{ background:#fef1ec url("../css/lib/images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x } -.ui-icon, +.ui-icon, .ui-widget-content .ui-icon{ background-image:url("../css/lib/images/ui-icons_222222_256x240.png") } @@ -97,7 +97,7 @@ inc_top.tmpl background-image:url("../css/lib/images/ui-icons_8c291d_256x240.png") } -.ui-state-hover .ui-icon, +.ui-state-hover .ui-icon, .ui-state-focus .ui-icon{ background-image:url("../css/lib/images/ui-icons_222222_256x240.png") } @@ -110,7 +110,7 @@ inc_top.tmpl background-image:url("../css/lib/images/ui-icons_2e83ff_256x240.png") } -.ui-state-error .ui-icon, +.ui-state-error .ui-icon, .ui-state-error-text .ui-icon{ background-image:url("../css/lib/images/ui-icons_cd0a0a_256x240.png") } @@ -345,7 +345,7 @@ home_postprocess.tmpl /* ======================================================================= -displayShow.tmpl +displayShow.tmpl ========================================================================== */ tr.seasonheader{ @@ -508,7 +508,7 @@ h2.day, h2.network{ .carousel-indicators .active{ background:#C7DB40; border-color:#C7DB40 -} +} /* ======================================================================= config*.tmpl @@ -630,6 +630,7 @@ span.path{ background-color:#f5f1e4 } +#addRootDirTable td label .filepath.red-text, .red-text{ color:#d33 } diff --git a/gui/slick/interfaces/default/home_addExistingShow.tmpl b/gui/slick/interfaces/default/home_addExistingShow.tmpl index 9b0a213f..d3784e83 100644 --- a/gui/slick/interfaces/default/home_addExistingShow.tmpl +++ b/gui/slick/interfaces/default/home_addExistingShow.tmpl @@ -10,14 +10,11 @@ #import os.path #include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_top.tmpl') - - - - - + + + + #if $varExists('header')

$header

@@ -36,48 +37,56 @@
-

Tip: shows are added quicker when usable show nfo and xml metadata is found

+ +

Tip: shows are added quicker when usable show nfo and xml metadata is found

-

- - -

+

+ + +

-
- -
-
+
+ +
+
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_rootDirs.tmpl') +
-
-
-
+
+
#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_addShowOptions.tmpl') +
-
-
-
+
+
+ -

The following parent folder(s) are scanned for existing shows. Toggle a folder to display shows

+

The following parent folder$multi_parents scanned for + #if not $kwargs.get('hash_dir', None)#existing shows. Toggle a folder to display shows#else#the existing show...#end if# +

+#if not $kwargs.get('hash_dir', None)

shows not known to SickGear are listed below...

+#end if

+#if not $kwargs.get('hash_dir', None)

If you tried to add a show, arrived here and can't see the folder, then that show may already be in your show list.

+#end if - + -#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_bottom.tmpl') \ No newline at end of file +#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_bottom.tmpl') diff --git a/gui/slick/interfaces/default/home_massAddTable.tmpl b/gui/slick/interfaces/default/home_massAddTable.tmpl index 1f0faf79..96aa8246 100644 --- a/gui/slick/interfaces/default/home_massAddTable.tmpl +++ b/gui/slick/interfaces/default/home_massAddTable.tmpl @@ -2,48 +2,67 @@ #from sickbeard.helpers import anon_url - - - - - - - -#for $curDir in $dirList: -#if $curDir['added_already']: -#continue -#end if - -#set $show_id = $curDir['dir'] -#if $curDir['existing_info'][0]: -#set $show_id = $show_id + '|' + $str($curDir['existing_info'][0]) + '|' + $str($curDir['existing_info'][1]) -#set $indexer = $curDir['existing_info'][2] -#end if - -#set $indexer = 0 -#if $curDir['existing_info'][0]: - #set $indexer = $curDir['existing_info'][2] -#elif $sickbeard.INDEXER_DEFAULT > 0: - #set $indexer = $sickbeard.INDEXER_DEFAULT -#end if - - - - - #if $curDir['existing_info'][1] and $indexer > 0: - - #else: - + + + + + + + + + + + + + + +#for $curDir in $dirList + #if $curDir['added_already'] and None is $curDir.get('highlight') + #continue #end if - - + + #set $show_id = $curDir['dir'] + #if $curDir['existing_info'][0] + #set $show_id = $show_id + '|' + $str($curDir['existing_info'][0]) + '|' + $str($curDir['existing_info'][1]) + #set $indexer = $curDir['existing_info'][2] + #end if + + #set $indexer = 0 + #if $curDir['existing_info'][0] + #set $indexer = $curDir['existing_info'][2] + #elif 0 < $sickbeard.INDEXER_DEFAULT + #set $indexer = $sickbeard.INDEXER_DEFAULT + #end if + + + + + #if $curDir['existing_info'][1] and $indexer > 0 + + #else + + #end if + + #end for - - -
Parent\show folderShow name
(tvshow.nfo)
TV database
Manage Directories
$curDir['existing_info'][1]?
+ + Parent\show folderShow name
(tvshow.nfo)
TV info source
+ Manage Directories +
- -
+ + + + + $curDir['existing_info'][1] + ? + +
\ No newline at end of file + + diff --git a/gui/slick/interfaces/default/home_newShow.tmpl b/gui/slick/interfaces/default/home_newShow.tmpl index 3a3da7d0..b92008c4 100644 --- a/gui/slick/interfaces/default/home_newShow.tmpl +++ b/gui/slick/interfaces/default/home_newShow.tmpl @@ -65,7 +65,7 @@
-

* SickGear supports english episodes. The language choice is used for fetching show data and episode filenames

+

Enter show name, TVDB ID, IMDb Url, or IMDb ID.  *SickGear supports english, language is used for show/episode data

#end if @@ -116,4 +116,4 @@
-#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_bottom.tmpl') \ No newline at end of file +#include $os.path.join($sickbeard.PROG_DIR, 'gui/slick/interfaces/default/inc_bottom.tmpl') diff --git a/gui/slick/js/addExistingShow.js b/gui/slick/js/addExistingShow.js index 1b08f888..98d2dfe2 100644 --- a/gui/slick/js/addExistingShow.js +++ b/gui/slick/js/addExistingShow.js @@ -28,6 +28,7 @@ $(document).ready(function(){ window.location.href = sbRoot + '/home/addShows/addExistingShows' + '?promptForSettings=' + ($('#promptForSettings').prop('checked') ? 'on' : 'off') + + (undefined !== $.sgSid && 0 < $.sgSid.length ? '&sid=' + $.sgSid : '') + '&shows_to_add=' + dirArr.join('&shows_to_add='); }); @@ -47,7 +48,7 @@ $(document).ready(function(){ + ' height="32" width="32" />' + ' scanning parent folders...'); - $.get(sbRoot + '/home/addShows/massAddTable', + $.get(sbRoot + '/home/addShows/massAddTable' + (undefined !== $.sgHashDir && 0 < $.sgHashDir.length ? '?hash_dir=' + $.sgHashDir : ''), url, function(data){ $('#tableDiv').html(data); @@ -90,4 +91,4 @@ $(document).ready(function(){ $('html,body').animate({scrollTop: 0}, 1000); }); -}); \ No newline at end of file +}); diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py index a714e55f..60a694f9 100644 --- a/sickbeard/webserve.py +++ b/sickbeard/webserve.py @@ -40,6 +40,7 @@ from sickbeard.common import SNATCHED, UNAIRED, IGNORED, ARCHIVED, WANTED, FAILE from sickbeard.common import SD, HD720p, HD1080p from sickbeard.exceptions import ex from sickbeard.helpers import remove_article, starify +from sickbeard.indexers.indexer_config import INDEXER_TVDB, INDEXER_TVRAGE from sickbeard.scene_exceptions import get_scene_exceptions from sickbeard.scene_numbering import get_scene_numbering, set_scene_numbering, get_scene_numbering_for_show, \ get_xem_numbering_for_show, get_scene_absolute_numbering_for_show, get_xem_absolute_numbering_for_show, \ @@ -2052,6 +2053,16 @@ class NewHomeAddShows(Home): results = {} final_results = [] + search_id, indexer_id = '', None + search_id = '' + try: + search_id = re.search(r'(?m)((?:tt\d{4,})|^\d{4,}$)', search_term).group(1) + resp = self.getTrakt('/search?id_type=%s&id=%s' % (('tvdb', 'imdb')['tt' in search_id], search_id))[0] + search_term = resp['show']['title'] + indexer_id = resp['show']['ids']['tvdb'] + except: + search_term = (search_term, '')['tt' in search_id] + # Query Indexers for each search term and build the list of results for indexer in sickbeard.indexerApi().indexers if not int(indexer) else [int(indexer)]: lINDEXER_API_PARMS = sickbeard.indexerApi(indexer).api_params.copy() @@ -2059,24 +2070,64 @@ class NewHomeAddShows(Home): lINDEXER_API_PARMS['custom_ui'] = classes.AllShowsListUI t = sickbeard.indexerApi(indexer).indexer(**lINDEXER_API_PARMS) - logger.log('Searching for Show with searchterm: %s on Indexer: %s' % ( - search_term, sickbeard.indexerApi(indexer).name), logger.DEBUG) try: # add search results - results.setdefault(indexer, []).extend(t[search_term]) + if bool(indexer_id): + logger.log('Fetching show using id: %s (%s) from tv datasource %s' % ( + search_id, search_term, sickbeard.indexerApi(indexer).name), logger.DEBUG) + results.setdefault('tt' in search_id and 3 or indexer, []).extend( + [{'id': indexer_id, 'seriesname': t[indexer_id]['seriesname'], 'firstaired': t[indexer_id]['firstaired']}]) + break + else: + logger.log('Searching for shows using search term: %s from tv datasource %s' % ( + search_term, sickbeard.indexerApi(indexer).name), logger.DEBUG) + results.setdefault(indexer, []).extend(t[search_term]) except Exception as e: - continue + pass + # Query trakt for tvdb ids + try: + logger.log('Searching for show using search term: %s from tv datasource Trakt' % search_term, logger.DEBUG) + resp = self.getTrakt('/search?query=%s&type=show' % search_term) + tvdb_ids = [] + for tvdb_item in results[INDEXER_TVDB]: + tvdb_ids.append(int(tvdb_item['id'])) + results_trakt = [] + for item in resp: + if 'tvdb' in item['show']['ids'] and item['show']['ids']['tvdb'] and \ + item['show']['ids']['tvdb'] not in tvdb_ids: + results_trakt.append({'id': item['show']['ids']['tvdb'], 'seriesname': item['show']['title'], + 'firstaired': item['show']['year']}) + results.update({3: results_trakt}) + except: + pass + + id_names = [None, sickbeard.indexerApi(INDEXER_TVDB).name, sickbeard.indexerApi(INDEXER_TVRAGE).name, + '%s via Trakt' % sickbeard.indexerApi(INDEXER_TVDB).name] map(final_results.extend, - ([[sickbeard.indexerApi(id).name, id, sickbeard.indexerApi(id).config['show_url'], int(show['id']), + ([['%s%s' % (id_names[id], helpers.findCertainShow(sickbeard.showList, int(show['id'])) and ' - exists in db' or ''), + (id, INDEXER_TVDB)[id == 3], sickbeard.indexerApi((id, INDEXER_TVDB)[id == 3]).config['show_url'], int(show['id']), 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}) - def massAddTable(self, rootDir=None): + def getTrakt(self, url, *args, **kwargs): + + filtered = [] + try: + resp = TraktAPI(ssl_verify=sickbeard.TRAKT_VERIFY, timeout=sickbeard.TRAKT_TIMEOUT).trakt_request(url) + if len(resp): + filtered = resp + except traktException as e: + logger.log(u'Could not connect to Trakt service: %s' % ex(e), logger.WARNING) + + return filtered + + def massAddTable(self, rootDir=None, **kwargs): t = PageTemplate(headers=self.request.headers, file='home_massAddTable.tmpl') t.submenu = self.HomeMenu() + t.kwargs = kwargs if not rootDir: return 'No folders selected.' @@ -2100,12 +2151,34 @@ class NewHomeAddShows(Home): dir_list = [] + display_one_dir = file_list = None + if kwargs.get('hash_dir'): + try: + for root_dir in sickbeard.ROOT_DIRS.split('|')[1:]: + try: + file_list = ek.ek(os.listdir, root_dir) + except: + continue + + for cur_file in file_list: + + cur_path = ek.ek(os.path.normpath, ek.ek(os.path.join, root_dir, cur_file)) + if not ek.ek(os.path.isdir, cur_path): + continue + + display_one_dir = kwargs.get('hash_dir') == str(abs(hash(cur_path))) + if display_one_dir: + raise ValueError('hash matched') + except ValueError: + pass + myDB = db.DBConnection() for root_dir in root_dirs: - try: - file_list = ek.ek(os.listdir, root_dir) - except: - continue + if not file_list: + try: + file_list = ek.ek(os.listdir, root_dir) + except: + continue for cur_file in file_list: @@ -2113,11 +2186,14 @@ class NewHomeAddShows(Home): if not ek.ek(os.path.isdir, cur_path): continue + highlight = kwargs.get('hash_dir') == str(abs(hash(cur_path))) + if display_one_dir and not highlight: + continue cur_dir = { 'dir': cur_path, - 'display_dir': '' + ek.ek(os.path.dirname, cur_path) + os.sep + '' + ek.ek( - os.path.basename, - cur_path), + 'highlight': highlight, + 'name': ek.ek(os.path.basename, cur_path), + 'path': '%s%s' % (ek.ek(os.path.dirname, cur_path), os.sep) } # see if the folder is in XBMC already @@ -2311,6 +2387,8 @@ class NewHomeAddShows(Home): t = PageTemplate(headers=self.request.headers, file='home_addExistingShow.tmpl') t.submenu = self.HomeMenu() t.enable_anime_options = False + t.kwargs = kwargs + t.multi_parents = helpers.maybe_plural(len(sickbeard.ROOT_DIRS.split('|')[1:])) and 's are' or ' is' return t.respond() @@ -2385,7 +2463,7 @@ class NewHomeAddShows(Home): # blanket policy - if the dir exists you should have used 'add existing show' numbnuts if ek.ek(os.path.isdir, show_dir) and not fullShowPath: ui.notifications.error('Unable to add show', u'Found existing folder: ' + show_dir) - return self.redirect('/home/addShows/existingShows/') + return self.redirect('/home/addShows/existingShows?sid=%s&hash_dir=%s' % (indexer_id, abs(hash(show_dir)))) # don't create show dir if config says not to if sickbeard.ADD_SHOWS_WO_DIR: @@ -2448,12 +2526,16 @@ class NewHomeAddShows(Home): return (indexer, show_dir, indexer_id, show_name) - def addExistingShows(self, shows_to_add=None, promptForSettings=None): + def addExistingShows(self, shows_to_add=None, promptForSettings=None, **kwargs): """ Receives a dir list and add them. Adds the ones with given TVDB IDs first, then forwards along to the newShow page. """ + if kwargs.get('sid', None): + return self.redirect('/home/addShows/newShow?show_to_add=%s&use_show_name=True' % + '|'.join(['', '', '', kwargs.get('sid', '')])) + # grab a list of other shows to add, if provided if not shows_to_add: shows_to_add = [] @@ -2470,7 +2552,7 @@ class NewHomeAddShows(Home): split_vals = cur_dir.split('|') if len(split_vals) < 3: dirs_only.append(cur_dir) - if not '|' in cur_dir: + if '|' not in cur_dir: dirs_only.append(cur_dir) else: indexer, show_dir, indexer_id, show_name = self.split_extra_show(cur_dir) @@ -2480,7 +2562,6 @@ class NewHomeAddShows(Home): indexer_id_given.append((int(indexer), show_dir, int(indexer_id), show_name)) - # if they want me to prompt for settings then I will just carry on to the newShow page if promptForSettings and shows_to_add: return self.newShow(shows_to_add[0], shows_to_add[1:])