mirror of
https://github.com/SickGear/SickGear.git
synced 2025-01-05 17:43:37 +00:00
Lightning fast indexer searches now!
Version checks reverted back to every 12 hours.
This commit is contained in:
parent
c945726f05
commit
f8ec897010
10 changed files with 110 additions and 302 deletions
|
@ -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('<img id="searchingAnim" src="' + sbRoot + '/images/loading32.gif" height="32" width="32" /> 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');
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -15,8 +15,7 @@
|
|||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Sick Beard. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
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:
|
||||
"""
|
||||
|
|
|
@ -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()
|
|
@ -1,228 +0,0 @@
|
|||
# coding=UTF-8
|
||||
# Author: Dennis Lutter <lad1337@gmail.com>
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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"
|
|
@ -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
|
||||
|
|
|
@ -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})
|
||||
|
|
60
tests/tests.py
Normal file
60
tests/tests.py
Normal file
|
@ -0,0 +1,60 @@
|
|||
# coding=UTF-8
|
||||
# Author: Dennis Lutter <lad1337@gmail.com>
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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()
|
Loading…
Reference in a new issue