diff --git a/gui/slick/js/newShow.js b/gui/slick/js/newShow.js index ef3a1d31..7efe993a 100644 --- a/gui/slick/js/newShow.js +++ b/gui/slick/js/newShow.js @@ -36,15 +36,15 @@ $(document).ready(function () { return; } - if (searchRequestXhr) searchRequestXhr.abort(); + if (searchRequestXhr) {searchRequestXhr.abort()}; var searchingFor = $('#nameToSearch').val() + ' on ' + $('#providedIndexer option:selected').text() + ' in ' + $('#indexerLangSelect').val(); $('#searchResults').empty().html(' searching ' + searchingFor + '...'); searchRequestXhr = $.ajax({ url: sbRoot + '/home/addShows/searchIndexersForShowName', - data: {'name': $('#nameToSearch').val(), 'lang': $('#indexerLangSelect').val(), 'indexer': $('#providedIndexer').val()}, - timeout: 10000, + data: {'search_term': $('#nameToSearch').val(), 'lang': $('#indexerLangSelect').val(), 'indexer': $('#providedIndexer').val()}, + timeout: 20000, dataType: 'json', error: function () { $('#searchResults').empty().html('search timed out, try again or try another indexer'); diff --git a/lib/tvdb_api/tvdb_api.py b/lib/tvdb_api/tvdb_api.py index 0ca2a2f9..8b59a7a8 100644 --- a/lib/tvdb_api/tvdb_api.py +++ b/lib/tvdb_api/tvdb_api.py @@ -914,9 +914,15 @@ class Tvdb: self._getShowData(key, self.config['language']) return self.shows[key] - key = key.lower() # make key lower case - sids = self._nameToSid(key) - return list(self.shows[sid] for sid in sids) + key = str(key).lower() + self.config['searchterm'] = key + selected_series = self._getSeries(key) + if isinstance(selected_series, dict): + selected_series = [selected_series] + return selected_series + #test = self._getSeries(key) + #sids = self._nameToSid(key) + #return list(self.shows[sid] for sid in sids) def __repr__(self): return str(self.shows) diff --git a/lib/tvrage_api/tvrage_api.py b/lib/tvrage_api/tvrage_api.py index 7c26ab62..de4a77e8 100644 --- a/lib/tvrage_api/tvrage_api.py +++ b/lib/tvrage_api/tvrage_api.py @@ -652,10 +652,16 @@ class TVRage: if key not in self.shows: self._getShowData(key) return self.shows[key] - - key = key.lower() # make key lower case - sids = self._nameToSid(key) - return list(self.shows[sid] for sid in sids) + + key = str(key).lower() + self.config['searchterm'] = key + selected_series = self._getSeries(key) + if isinstance(selected_series, dict): + selected_series = [selected_series] + return selected_series + #test = self._getSeries(key) + #sids = self._nameToSid(key) + #return list(self.shows[sid] for sid in sids) def __repr__(self): return str(self.shows) diff --git a/sickbeard/__init__.py b/sickbeard/__init__.py index 5107ed73..b99e3b45 100644 --- a/sickbeard/__init__.py +++ b/sickbeard/__init__.py @@ -973,7 +973,7 @@ def initialize(consoleLogging=True): runImmediately=False) versionCheckScheduler = scheduler.Scheduler(versionChecker.CheckVersion(), - cycleTime=datetime.timedelta(minutes=5), + cycleTime=datetime.timedelta(hours=12), threadName="CHECKVERSION", runImmediately=True) diff --git a/sickbeard/classes.py b/sickbeard/classes.py index ccc0170b..a34ce0d3 100644 --- a/sickbeard/classes.py +++ b/sickbeard/classes.py @@ -15,8 +15,7 @@ # # You should have received a copy of the GNU General Public License # along with Sick Beard. If not, see . - - +import re import sickbeard @@ -140,7 +139,7 @@ class TorrentSearchResult(SearchResult): class AllShowsListUI: """ - This class is for tvdb-api. Instead of prompting with a UI to pick the + This class is for indexer api. Instead of prompting with a UI to pick the desired result out of a list of shows it tries to be smart about it based on what shows are in SB. """ @@ -150,10 +149,20 @@ class AllShowsListUI: self.log = log def selectSeries(self, allSeries): + searchResults = [] # get all available shows if allSeries: - return allSeries + if 'searchterm' in self.config: + searchterm = self.config['searchterm'] + # try to pick a show that's in my show list + for curShow in allSeries: + if curShow in searchResults: + continue + if re.search(searchterm, curShow['seriesname'], flags=re.I) and 'firstaired' in curShow: + searchResults.append(curShow) + + return searchResults class ShowListUI: """ diff --git a/sickbeard/indexers/test/test.py b/sickbeard/indexers/test/test.py deleted file mode 100644 index f1b279e0..00000000 --- a/sickbeard/indexers/test/test.py +++ /dev/null @@ -1,25 +0,0 @@ -from __future__ import with_statement - -import unittest - -import sys -import datetime -import os.path -import string - -sys.path.append(os.path.abspath('..')) -sys.path.append(os.path.abspath('../../../lib')) - -import sickbeard - -class APICheck(unittest.TestCase): - indexer_id = 2930 - lang = "en" - - lINDEXER_API_PARMS = sickbeard.indexerApi(2).api_params.copy() - t = sickbeard.indexerApi(2).indexer(**lINDEXER_API_PARMS) - epObj = t[2930] - print epObj - - if __name__ == "__main__": - unittest.main() \ No newline at end of file diff --git a/sickbeard/indexers/test/test_lib.py b/sickbeard/indexers/test/test_lib.py deleted file mode 100644 index 1bc2fb94..00000000 --- a/sickbeard/indexers/test/test_lib.py +++ /dev/null @@ -1,228 +0,0 @@ -# coding=UTF-8 -# Author: Dennis Lutter -# URL: http://code.google.com/p/sickbeard/ -# -# This file is part of Sick Beard. -# -# Sick Beard is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Sick Beard is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Sick Beard. If not, see . - -from __future__ import with_statement - -import unittest - -import sqlite3 - -import sys -import os.path - -sys.path.append(os.path.abspath('..')) -sys.path.append(os.path.abspath('../lib')) - -import sickbeard -import shutil - -from sickbeard import encodingKludge as ek, providers, tvcache -from sickbeard import db -from sickbeard.databases import mainDB -from sickbeard.databases import cache_db - -#================= -# test globals -#================= -TESTDIR = os.path.abspath('.') -TESTDBNAME = "sickbeard.db" -TESTCACHEDBNAME = "cache.db" - -SHOWNAME = u"show name" -SEASON = 4 -EPISODE = 2 -FILENAME = u"show name - s0" + str(SEASON) + "e0" + str(EPISODE) + ".mkv" -FILEDIR = os.path.join(TESTDIR, SHOWNAME) -FILEPATH = os.path.join(FILEDIR, FILENAME) - -SHOWDIR = os.path.join(TESTDIR, SHOWNAME + " final") - -#sickbeard.logger.sb_log_instance = sickbeard.logger.SBRotatingLogHandler(os.path.join(TESTDIR, 'sickbeard.log'), sickbeard.logger.NUM_LOGS, sickbeard.logger.LOG_SIZE) -sickbeard.logger.SBRotatingLogHandler.log_file = os.path.join(os.path.join(TESTDIR, 'Logs'), 'test_sickbeard.log') - - -#================= -# prepare env functions -#================= -def createTestLogFolder(): - if not os.path.isdir(sickbeard.LOG_DIR): - os.mkdir(sickbeard.LOG_DIR) - -# call env functions at appropriate time during sickbeard var setup - -#================= -# sickbeard globals -#================= -sickbeard.SYS_ENCODING = 'UTF-8' -sickbeard.showList = [] -sickbeard.QUALITY_DEFAULT = 4 # hdtv -sickbeard.FLATTEN_FOLDERS_DEFAULT = 0 - -sickbeard.NAMING_PATTERN = '' -sickbeard.NAMING_ABD_PATTERN = '' -sickbeard.NAMING_MULTI_EP = 1 - -sickbeard.PROVIDER_ORDER = ["sick_beard_index"] -sickbeard.newznabProviderList = providers.getNewznabProviderList( - "Sick Beard Index|http://lolo.sickbeard.com/|0|5030,5040|0!!!NZBs.org|http://nzbs.org/||5030,5040,5070,5090|0!!!Usenet-Crawler|http://www.usenet-crawler.com/||5030,5040|0") -sickbeard.providerList = providers.makeProviderList() - -sickbeard.PROG_DIR = os.path.abspath('..') -sickbeard.DATA_DIR = sickbeard.PROG_DIR -sickbeard.LOG_DIR = os.path.join(TESTDIR, 'Logs') -createTestLogFolder() -sickbeard.logger.sb_log_instance.initLogging(False) - - -#================= -# dummy functions -#================= -def _dummy_saveConfig(): - return True - -# this overrides the sickbeard save_config which gets called during a db upgrade -# this might be considered a hack -mainDB.sickbeard.save_config = _dummy_saveConfig - - -# the real one tries to contact tvdb just stop it from getting more info on the ep -def _fake_specifyEP(self, season, episode): - pass - - -sickbeard.tv.TVEpisode.specifyEpisode = _fake_specifyEP - - -#================= -# test classes -#================= -class SickbeardTestDBCase(unittest.TestCase): - def setUp(self): - sickbeard.showList = [] - setUp_test_db() - setUp_test_episode_file() - setUp_test_show_dir() - - def tearDown(self): - sickbeard.showList = [] - tearDown_test_db() - tearDown_test_episode_file() - tearDown_test_show_dir() - - -class TestDBConnection(db.DBConnection, object): - def __init__(self, dbFileName=TESTDBNAME): - dbFileName = os.path.join(TESTDIR, dbFileName) - super(TestDBConnection, self).__init__(dbFileName) - - -class TestCacheDBConnection(TestDBConnection, object): - def __init__(self, providerName): - db.DBConnection.__init__(self, os.path.join(TESTDIR, TESTCACHEDBNAME)) - - # Create the table if it's not already there - try: - sql = "CREATE TABLE " + providerName + " (name TEXT, season NUMERIC, episodes TEXT, indexerid NUMERIC, url TEXT, time NUMERIC, quality TEXT);" - self.connection.execute(sql) - self.connection.commit() - except sqlite3.OperationalError, e: - if str(e) != "table " + providerName + " already exists": - raise - - # Create the table if it's not already there - try: - sql = "CREATE TABLE lastUpdate (provider TEXT, time NUMERIC);" - self.connection.execute(sql) - self.connection.commit() - except sqlite3.OperationalError, e: - if str(e) != "table lastUpdate already exists": - raise - -# this will override the normal db connection -sickbeard.db.DBConnection = TestDBConnection -sickbeard.tvcache.CacheDBConnection = TestCacheDBConnection - - -#================= -# test functions -#================= -def setUp_test_db(): - """upgrades the db to the latest version - """ - # upgrading the db - db.upgradeDatabase(db.DBConnection(), mainDB.InitialSchema) - # fix up any db problems - db.sanityCheckDatabase(db.DBConnection(), mainDB.MainSanityCheck) - - #and for cache.b too - db.upgradeDatabase(db.DBConnection("cache.db"), cache_db.InitialSchema) - - -def tearDown_test_db(): - """Deletes the test db - although this seams not to work on my system it leaves me with an zero kb file - """ - # uncomment next line so leave the db intact between test and at the end - #return False - if os.path.exists(os.path.join(TESTDIR, TESTDBNAME)): - os.remove(os.path.join(TESTDIR, TESTDBNAME)) - if os.path.exists(os.path.join(TESTDIR, TESTCACHEDBNAME)): - os.remove(os.path.join(TESTDIR, TESTCACHEDBNAME)) - - -def setUp_test_episode_file(): - if not os.path.exists(FILEDIR): - os.makedirs(FILEDIR) - - try: - with open(FILEPATH, 'w') as f: - f.write("foo bar") - except EnvironmentError: - print "Unable to set up test episode" - raise - - -def tearDown_test_episode_file(): - shutil.rmtree(FILEDIR) - - -def setUp_test_show_dir(): - if not os.path.exists(SHOWDIR): - os.makedirs(SHOWDIR) - - -def tearDown_test_show_dir(): - shutil.rmtree(SHOWDIR) - - -tearDown_test_db() - -if __name__ == '__main__': - print "==================" - print "Dont call this directly" - print "==================" - print "you might want to call" - - dirList = os.listdir(TESTDIR) - for fname in dirList: - if (fname.find("_test") > 0) and (fname.find("pyc") < 0): - print "- " + fname - - print "==================" - print "or just call all_tests.py" diff --git a/sickbeard/tv.py b/sickbeard/tv.py index 19d2e698..e61f413d 100644 --- a/sickbeard/tv.py +++ b/sickbeard/tv.py @@ -1656,7 +1656,7 @@ class TVEpisode(object): """ if not self.dirty and not forceSave: - logger.log(str(self.show.indexeridid) + u": Not creating SQL queue - record is not dirty", logger.DEBUG) + logger.log(str(self.show.indexerid) + u": Not creating SQL queue - record is not dirty", logger.DEBUG) return # use a custom update/insert method to get the data into the DB diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py index 5cdd5468..61de1d87 100644 --- a/sickbeard/webserve.py +++ b/sickbeard/webserve.py @@ -1958,51 +1958,31 @@ class NewHomeAddShows: return helpers.sanitizeFileName(name) @cherrypy.expose - def searchIndexersForShowName(self, name, lang="en", indexer=None): + def searchIndexersForShowName(self, search_term, lang="en", indexer=None): if not lang or lang == 'null': lang = "en" + results = {} final_results = [] - nameUTF8 = name.encode('utf-8') - - # Use each word in the show's name as a possible search term - keywords = nameUTF8.split(' ') - - # Insert the whole show's name as the first search term so best results are first - # ex: keywords = ['Some Show Name', 'Some', 'Show', 'Name'] - if len(keywords) > 1: - keywords.insert(0, nameUTF8) - - # check for indexer preset - indexers = sickbeard.indexerApi().indexers if not int(indexer) else [int(indexer or 0)] - # Query Indexers for each search term and build the list of results - for indexer in indexers: - results = [] - + for indexer in sickbeard.indexerApi().indexers if not int(indexer) else [int(indexer)]: lINDEXER_API_PARMS = sickbeard.indexerApi(indexer).api_params.copy() + lINDEXER_API_PARMS['language'] = lang lINDEXER_API_PARMS['custom_ui'] = classes.AllShowsListUI t = sickbeard.indexerApi(indexer).indexer(**lINDEXER_API_PARMS) - for searchTerm in keywords: - try: - search = t[searchTerm] - if isinstance(search, dict): - search = [search] + 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]) + except:continue - # add search results - results += search - except: - continue - final_results += list([sickbeard.indexerApi(indexer).name, int(sickbeard.indexerApi(indexer).config['id']), - sickbeard.indexerApi(indexer).config["show_url"], int(x['id']), x['seriesname'], - x['firstaired']] for x in results if re.search(keywords[0], x['seriesname'], flags=re.I) and x['firstaired']) - - # remove duplicates and sort by firstaired - final_results = sorted(final_results, reverse=True, key=operator.itemgetter(5)) - final_results = list(final_results for final_results, _ in itertools.groupby(final_results)) + map(final_results.extend, + ([[sickbeard.indexerApi(id).name, id, sickbeard.indexerApi(id).config["show_url"], int(show['id']), + show['seriesname'], show['firstaired']] for show in shows] for id, shows in + results.items())) lang_id = sickbeard.indexerApi().config['langabbv_to_id'][lang] return json.dumps({'results': final_results, 'langid': lang_id}) diff --git a/tests/tests.py b/tests/tests.py new file mode 100644 index 00000000..0c96669e --- /dev/null +++ b/tests/tests.py @@ -0,0 +1,60 @@ +# coding=UTF-8 +# Author: Dennis Lutter +# URL: http://code.google.com/p/sickbeard/ +# +# This file is part of Sick Beard. +# +# Sick Beard is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Sick Beard is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Sick Beard. If not, see . + +from __future__ import with_statement + +import unittest + +import sys, os.path +sys.path.append(os.path.abspath('..')) +sys.path.append(os.path.abspath('../lib')) + +from sickbeard import indexerApi +from sickbeard import classes + +class APICheck(unittest.TestCase): + + lang = "en" + search_term = 'american' + + results = {} + final_results = [] + + for indexer in indexerApi().indexers: + lINDEXER_API_PARMS = indexerApi(indexer).api_params.copy() + lINDEXER_API_PARMS['language'] = lang + lINDEXER_API_PARMS['custom_ui'] = classes.AllShowsListUI + t = indexerApi(indexer).indexer(**lINDEXER_API_PARMS) + + print("Searching for Show with searchterm: %s on Indexer: %s" % (search_term, indexerApi(indexer).name)) + try: + # add search results + results.setdefault(indexer, []).extend(t[search_term]) + except Exception, e: + continue + + + map(final_results.extend, + ([[indexerApi(id).name, id, indexerApi(id).config["show_url"], int(show['id']), + show['seriesname'], show['firstaired']] for show in shows] for id, shows in + results.items())) + + + if __name__ == "__main__": + unittest.main() \ No newline at end of file