diff --git a/gui/slick/interfaces/default/config_general.tmpl b/gui/slick/interfaces/default/config_general.tmpl index 8b15b25e..fa104de0 100644 --- a/gui/slick/interfaces/default/config_general.tmpl +++ b/gui/slick/interfaces/default/config_general.tmpl @@ -27,6 +27,7 @@ +
@@ -176,7 +177,26 @@
- +
+
+ + +
+ +
+ +
+ +
+
+ +
+
diff --git a/gui/slick/interfaces/default/inc_imdbWatchlists.tmpl b/gui/slick/interfaces/default/inc_imdbWatchlists.tmpl new file mode 100644 index 00000000..9fef9865 --- /dev/null +++ b/gui/slick/interfaces/default/inc_imdbWatchlists.tmpl @@ -0,0 +1,33 @@ +#import sickbeard + + +#if $sickbeard.IMDB_WATCHLISTCSV: +#set $backend_pieces = $sickbeard.IMDB_WATCHLISTCSV.split('|') +#else: +#set $backend_pieces = [] +#end if + + +
+ +
+
+ + + + +
+ + +
+ +
+ + +
diff --git a/gui/slick/js/imdbWatchlist.js b/gui/slick/js/imdbWatchlist.js new file mode 100644 index 00000000..ad2749fc --- /dev/null +++ b/gui/slick/js/imdbWatchlist.js @@ -0,0 +1,170 @@ +// Avoid `console` errors in browsers that lack a console. +(function() { + var method; + var noop = function noop() {}; + var methods = [ + 'assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error', + 'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log', + 'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd', + 'timeStamp', 'trace', 'warn' + ]; + var length = methods.length; + var console = (window.console = window.console || {}); + + while (length--) { + method = methods[length]; + + // Only stub undefined methods. + if (!console[method]) { + console[method] = noop; + } + } +}()); + +$(document).ready(function() { + + function addImdbWl(path) { + + if (!path.length) + return; + + $('#imdbWl').append(''); + refreshImdbUrls(); + $.get(sbRoot+'/config/general/saveImdbWatchlists', { imdbWatchlistString: $('#ImdbWlText').val() }); + } + + function editImdbWl(path) { + + if (!path.length) + return; + + // as long as something is selected + if ($("#imdbWl option:selected").length) { + + $("#imdbWl option:selected").text(path); + $("#imdbWl option:selected").val(path); + } + + refreshImdbUrls(); + $.get(sbRoot+'/config/general/saveRootDirs', {rootDirString: $('#ImdbWlText').val()}); + } + + $('#addImdbWl').click(function(){editText()}); + $('#editImdbWl').click(function(){editText({selectedWl: $("#imdbWl option:selected").val()})}); + + $('#deleteImdbWl').click(function() { + if ($("#imdbWl option:selected").length) { + + var toDelete = $("#imdbWl option:selected"); + + toDelete.remove(); + syncOptionIDs(); + + }; + + refreshImdbUrls(); + $.get(sbRoot+'/config/general/saveImdbWatchlists', {imdbWatchlistString: $('#ImdbWlText').val()}); + }); + + function syncOptionIDs() { + // re-sync option ids + var i = 0; + $('#imdbWl option').each(function() { + $(this).attr('id', 'wl-'+(i++)); + }); + } + + function refreshImdbUrls() { + // Rebuild the string in #ImdbWlText as url|url|url + + if (!$("#imdbWl").length) + return; + + var do_disable = 'true'; + + // if something's selected then we have some behavior to figure out + if ($("#imdbWl option:selected").length) { + do_disable = ''; + } + + // update the elements + $('#deleteImdbWl').prop('disabled', do_disable); + $('#editImdbWl').prop('disabled', do_disable); + + var log_str = ''; + var dir_text = ''; + + $('#imdbWl option').each(function() { + log_str += $(this).val(); + //Check if this is a valid IMDB link before adding it + + if (checkIMDBUrl(log_str)) { + if (dir_text == '') { + dir_text = $(this).val() + } + else { + dir_text += '|' + $(this).val(); + } + } + }); + + //console.log(log_str); + + $('#ImdbWlText').val(dir_text); + $('#ImdbWlText').change(); + //console.log('ImdbWlText: '+$('#ImdbWlText').val()); + } + + function checkIMDBUrl(url) { + if (url.match(/http.*:\/\/www\.imdb\.com\/.*/gi) && + url.match(/ls[0-9]+/gi) && + url.match(/ur[0-9]+/gi)) { + return true; + } + else { + alert(url + ' is not a valid IMDB csv export!'); + return false; + }; + }; + + $('#imdbWl').click(refreshImdbUrls); + + // set up buttons on page load + refreshImdbUrls(); + + function editText(optionid) { + var updateVal = ""; + if (optionid) { + updateVal = 'update-' + optionid.selectedWl; + $('#editImdbWlText').val(optionid.selectedWl); + } + else { + updateVal = 'add'; + $('#editImdbWlText').val(""); + } + $('#updateImdbWl').attr('action', updateVal); + $('#editImdbWlText').attr('style','display: block; width: 100%; margin-top: 4px; margin-bottom: 4px;'); + $('#imdbWl').prop('disabled', 'true'); + $('#updateImdbWl').attr('style','display: block;'); + $('#editImdbWlText').select(); + } + + $('#updateImdbWl').click(function(){ + // Update the Multiselect after clicking on the Update button + var updateText = $('#editImdbWlText').val(); + if (checkIMDBUrl(updateText)) { + if ($('#updateImdbWl').attr('action') == 'add') { + addImdbWl(updateText); + } + else { + editImdbWl(updateText); + }; + }; + + + $('#editImdbWlText').attr('style','display: none; width: 100%'); + $('#imdbWl').prop('disabled', ''); + $('#updateImdbWl').attr('style','display: none;'); + }); + +}); \ No newline at end of file diff --git a/lib/tvdb_api/tests/test_tvdb_api.py b/lib/tvdb_api/tests/test_tvdb_api.py index c1fc66b1..ad817267 100644 --- a/lib/tvdb_api/tests/test_tvdb_api.py +++ b/lib/tvdb_api/tests/test_tvdb_api.py @@ -8,18 +8,27 @@ """Unittests for tvdb_api """ -import os +import os,os.path import sys +print sys.path import datetime import unittest # Force parent directory onto path -sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) +#sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) -import tvdb_api +sys.path.append(os.path.abspath('../../tests')) + + +import sickbeard + + +from tvdb_api import Tvdb import tvdb_ui from tvdb_api import (tvdb_shownotfound, tvdb_seasonnotfound, tvdb_episodenotfound, tvdb_attributenotfound) +from lib import xmltodict +import lib class test_tvdb_basic(unittest.TestCase): # Used to store the cached instance of Tvdb() diff --git a/lib/tvdb_api/tvdb_api.py b/lib/tvdb_api/tvdb_api.py index 6b64c82d..ac03cc5f 100644 --- a/lib/tvdb_api/tvdb_api.py +++ b/lib/tvdb_api/tvdb_api.py @@ -522,10 +522,14 @@ class Tvdb: if self.config['search_all_languages']: self.config['url_getSeries'] = u"%(base_url)s/api/GetSeries.php" % self.config + self.config['url_getSeriesImdb'] = u"%(base_url)s/api/GetSeriesByRemoteID.php" % self.config self.config['params_getSeries'] = {"seriesname": "", "language": "all"} + self.config['params_getSeriesByImdb'] = {"imdbid": "", "language": "all"} else: self.config['url_getSeries'] = u"%(base_url)s/api/GetSeries.php" % self.config + self.config['url_getSeriesImdb'] = u"%(base_url)s/api/GetSeriesByRemoteID.php" % self.config self.config['params_getSeries'] = {"seriesname": "", "language": self.config['language']} + self.config['params_getSeriesByImdb'] = {"imdbid": "", "language": self.config['language']} self.config['url_epInfo'] = u"%(base_url)s/api/%(apikey)s/series/%%s/all/%%s.xml" % self.config self.config['url_epInfo_zip'] = u"%(base_url)s/api/%(apikey)s/series/%%s/all/%%s.zip" % self.config @@ -674,16 +678,20 @@ class Tvdb: data = data.strip() return data - def search(self, series): + def search(self, series, imdbid=None): """This searches TheTVDB.com for the series name and returns the result list """ series = series.encode("utf-8") log().debug("Searching for show %s" % series) self.config['params_getSeries']['seriesname'] = series + self.config['params_getSeriesByImdb']['imdbid'] = imdbid try: - seriesFound = self._getetsrc(self.config['url_getSeries'], self.config['params_getSeries']).values()[0] + if imdbid: + seriesFound = self._getetsrc(self.config['url_getSeriesImdb'], self.config['params_getSeriesByImdb']).values()[0] + else: + seriesFound = self._getetsrc(self.config['url_getSeries'], self.config['params_getSeries']).values()[0] return seriesFound except: return [] diff --git a/sickbeard/__init__.py b/sickbeard/__init__.py index ffb7439c..53ea01fd 100755 --- a/sickbeard/__init__.py +++ b/sickbeard/__init__.py @@ -39,6 +39,7 @@ from sickbeard.config import CheckSection, check_setting_int, check_setting_str, naming_ep_type from sickbeard import searchBacklog, showUpdater, versionChecker, properFinder, autoPostProcesser, \ subtitles, traktChecker +from sickbeard.automations import imdbChecker from sickbeard import helpers, db, exceptions, show_queue, search_queue, scheduler, show_name_helpers from sickbeard import logger from sickbeard import naming @@ -465,6 +466,7 @@ def initialize(consoleLogging=True): USE_XBMC, XBMC_ALWAYS_ON, XBMC_NOTIFY_ONSNATCH, XBMC_NOTIFY_ONDOWNLOAD, XBMC_NOTIFY_ONSUBTITLEDOWNLOAD, XBMC_UPDATE_FULL, XBMC_UPDATE_ONLYFIRST, \ XBMC_UPDATE_LIBRARY, XBMC_HOST, XBMC_USERNAME, XBMC_PASSWORD, BACKLOG_FREQUENCY, \ USE_TRAKT, TRAKT_USERNAME, TRAKT_PASSWORD, TRAKT_API, TRAKT_REMOVE_WATCHLIST, TRAKT_USE_WATCHLIST, TRAKT_METHOD_ADD, TRAKT_START_PAUSED, traktCheckerScheduler, TRAKT_USE_RECOMMENDED, TRAKT_SYNC, TRAKT_DEFAULT_INDEXER, TRAKT_REMOVE_SERIESLIST, \ + USE_IMDBWATCHLIST, IMDB_WATCHLISTCSV, imdbWatchlistScheduler, \ USE_PLEX, PLEX_NOTIFY_ONSNATCH, PLEX_NOTIFY_ONDOWNLOAD, PLEX_NOTIFY_ONSUBTITLEDOWNLOAD, PLEX_UPDATE_LIBRARY, \ PLEX_SERVER_HOST, PLEX_HOST, PLEX_USERNAME, PLEX_PASSWORD, DEFAULT_BACKLOG_FREQUENCY, MIN_BACKLOG_FREQUENCY, BACKLOG_STARTUP, SKIP_REMOVED_FILES, \ showUpdateScheduler, __INITIALIZED__, LAUNCH_BROWSER, UPDATE_SHOWS_ON_START, SORT_ARTICLE, showList, loadingShowList, \ @@ -523,6 +525,7 @@ def initialize(consoleLogging=True): CheckSection(CFG, 'Pushalot') CheckSection(CFG, 'Pushbullet') CheckSection(CFG, 'Subtitles') + CheckSection(CFG, 'IMDBWatchlist') # wanted branch BRANCH = check_setting_str(CFG, 'General', 'branch', '') @@ -572,7 +575,7 @@ def initialize(consoleLogging=True): if WEB_PORT < 21 or WEB_PORT > 65535: WEB_PORT = 8081 - + WEB_HOST = check_setting_str(CFG, 'General', 'web_host', '0.0.0.0') WEB_IPV6 = bool(check_setting_int(CFG, 'General', 'web_ipv6', 0)) WEB_ROOT = check_setting_str(CFG, 'General', 'web_root', '').rstrip("/") @@ -834,7 +837,11 @@ def initialize(consoleLogging=True): TRAKT_USE_RECOMMENDED = bool(check_setting_int(CFG, 'Trakt', 'trakt_use_recommended', 0)) TRAKT_SYNC = bool(check_setting_int(CFG, 'Trakt', 'trakt_sync', 0)) TRAKT_DEFAULT_INDEXER = check_setting_int(CFG, 'Trakt', 'trakt_default_indexer', 1) - + + ### IMDB Watchlist set default values for config + USE_IMDBWATCHLIST = bool(check_setting_int(CFG, 'IMDBWatchlist', 'use_imdbwatchlist', 0)) + IMDB_WATCHLISTCSV = check_setting_str(CFG, 'IMDBWatchlist', 'imdb_watchlistcsv', '') + CheckSection(CFG, 'pyTivo') USE_PYTIVO = bool(check_setting_int(CFG, 'pyTivo', 'use_pytivo', 0)) PYTIVO_NOTIFY_ONSNATCH = bool(check_setting_int(CFG, 'pyTivo', 'pytivo_notify_onsnatch', 0)) @@ -1147,6 +1154,11 @@ def initialize(consoleLogging=True): cycleTime=datetime.timedelta(hours=SUBTITLES_FINDER_FREQUENCY), threadName="FINDSUBTITLES", silent=not USE_SUBTITLES) + + imdbWatchlistScheduler = scheduler.Scheduler(imdbChecker.IMDB(), + cycleTime=datetime.timedelta(hours=1), + threadName="IMDBWATCHLIST", + silent=not USE_IMDBWATCHLIST) showList = [] loadingShowList = {} @@ -1159,7 +1171,7 @@ def start(): global __INITIALIZED__, backlogSearchScheduler, \ showUpdateScheduler, versionCheckScheduler, showQueueScheduler, \ properFinderScheduler, autoPostProcesserScheduler, searchQueueScheduler, \ - subtitlesFinderScheduler, USE_SUBTITLES, traktCheckerScheduler, \ + subtitlesFinderScheduler, USE_SUBTITLES, traktCheckerScheduler, imdbWatchlistScheduler, \ dailySearchScheduler, events, started with INIT_LOCK: @@ -1200,7 +1212,10 @@ def start(): # start the trakt checker if USE_TRAKT: traktCheckerScheduler.start() - + + if USE_IMDBWATCHLIST: + imdbWatchlistScheduler.start() + started = True @@ -1208,7 +1223,7 @@ def halt(): global __INITIALIZED__, backlogSearchScheduler, \ showUpdateScheduler, versionCheckScheduler, showQueueScheduler, \ properFinderScheduler, autoPostProcesserScheduler, searchQueueScheduler, \ - subtitlesFinderScheduler, traktCheckerScheduler, \ + subtitlesFinderScheduler, traktCheckerScheduler, imdbWatchlistScheduler, \ dailySearchScheduler, events, started with INIT_LOCK: @@ -1281,6 +1296,14 @@ def halt(): traktCheckerScheduler.join(10) except: pass + + if USE_IMDBWATCHLIST: + imdbWatchlistScheduler.stop.set() + logger.log(u"Waiting for the IMDBWATCHLIST thread to exit") + try: + imdbWatchlistScheduler.join(10) + except: + pass if DOWNLOAD_PROPERS: properFinderScheduler.stop.set() @@ -1680,7 +1703,11 @@ def save_config(): new_config['Trakt']['trakt_use_recommended'] = int(TRAKT_USE_RECOMMENDED) new_config['Trakt']['trakt_sync'] = int(TRAKT_SYNC) new_config['Trakt']['trakt_default_indexer'] = int(TRAKT_DEFAULT_INDEXER) - + + new_config['IMDBWatchlist'] = {} + new_config['IMDBWatchlist']['use_imdbwatchlist'] = int(USE_IMDBWATCHLIST) + new_config['IMDBWatchlist']['imdb_watchlistcsv'] = IMDB_WATCHLISTCSV + new_config['pyTivo'] = {} new_config['pyTivo']['use_pytivo'] = int(USE_PYTIVO) new_config['pyTivo']['pytivo_notify_onsnatch'] = int(PYTIVO_NOTIFY_ONSNATCH) diff --git a/sickbeard/automations/__init__.py b/sickbeard/automations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/sickbeard/automations/imdbChecker.py b/sickbeard/automations/imdbChecker.py new file mode 100644 index 00000000..27820452 --- /dev/null +++ b/sickbeard/automations/imdbChecker.py @@ -0,0 +1,230 @@ +# Author: KontiSR +# URL: https://github.com/echel0n/SickRage +# +# This file is part of SickRage. +# +# SickRage 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. +# +# SickRage 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 SickRage. If not, see . + +import urllib2, urllib +import shutil +import urlparse +import os, datetime +import requests +import cookielib +import re +from urllib2 import HTTPError, URLError + +import sickbeard +from sickbeard import encodingKludge as ek +from sickbeard import logger +from sickbeard import helpers +from sickbeard import search_queue +from sickbeard.common import SKIPPED, WANTED +from lib.tvdb_api.tvdb_api import * + +class ImdbBase(): + def _download(self, baseurl, querystring=""): + fullurl = baseurl + urllib.urlencode(querystring) + + req = urllib2.Request(fullurl) + try: + response = urllib2.urlopen(req) + except HTTPError as e: + logger.log('Could not download IMDB watchlist', logger.DEBUG) + #print 'Error code: ', e.code + return False + except URLError as e: + logger.log('Could not download IMDB watchlist', logger.DEBUG) + #print 'Reason: ', e.reason + return False + + redirurl = response.geturl() + htmlResponse = response.read() + + validHtml = True#BeautifulSoup(htmlResponse, 'html.parser') + if validHtml: + return htmlResponse + + return False + + +class IMDB(ImdbBase): + listOfImdbIds = [] + def __init__(self): + self.listOfImdbIds = [] + + def run(self, force=False): + try: + # add shows from trakt.tv watchlist + if sickbeard.USE_IMDBWATCHLIST: + self.listOfImdbIds = [] # its about to all get re-added + self.checkWatchlist() # Check the | separated watchlists (csv) urls + if len(self.listOfImdbIds): + self.updateShowsInDb() # Update the db with possible new shows + + except Exception: + logger.log(traceback.format_exc(), logger.DEBUG) + + def _getTTs(self, html): + nrAddedTTs = 0 + ### Get the tt's (shows) from the ajax html. E.a. [ tt1958961|imdb|8.1|8.1|list, tt1958961|imdb|8.1|8.1|list ] + if not html: + return False + + parsedshows = re.findall("(tt[0-9]+)\\|imdb\\|([.0-9]+)", html) + if not parsedshows: + return False + + for show in parsedshows: + if show[0] not in [x['imdbid'] for x in self.listOfImdbIds]: + self.listOfImdbIds.append({"imdbid" : show[0], "score" : show[1]}) + nrAddedTTs += 1 + + if nrAddedTTs > 0: + return nrAddedTTs + + return False + + def checkWatchlist(self): + + ### Get imdbListId from the csv url's + AjaxUrls = self._getImdbAjaxUrls(sickbeard.IMDB_WATCHLISTCSV) + + ### Get imdbUserId from the csv url's + for url in AjaxUrls: + getImdbHtml = self._download(url) + nrAdded = self._getTTs(getImdbHtml) + + if self.listOfImdbIds: + return self.listOfImdbIds + + return False + + ''' + Tries to use the csvUrls as a comma separated list of imdb csv urls, + to retrieve a userid and listid for each of the csv url. + For each csv url an Ajax url is created. Thats used to get the list of Tvshows. + ''' + def _getImdbAjaxUrls(self, csvUrls): + ajaxUrls = [] + ajaxUrlBase = u"http://www.imdb.com/list/_ajax/list_filter?" + + reUserId = re.compile(".*(ur[0-9]+)") + reListId = re.compile(".*(ls[0-9]+)") + + #if "|" in csvUrls: + #print "Multiple Watchlists detected" + csvurl = csvUrls.split("|") + for url in csvurl: + userIdMatch = reUserId.match(url) + listIdMatch = reListId.match(url) + + if userIdMatch and listIdMatch: + query = {"list_id" : listIdMatch.groups()[0], + "list_class" : "WATCHLIST", + "view" : "compact", + "list_type" : "Titles", + "filter" : '{"title_type":["tv_series"]}', + "sort_field" : "created", + "sort_direction" : "desc", + "user_id" : userIdMatch.groups()[0] } + ajaxUrls.append(ajaxUrlBase + urllib.urlencode(query)) + if ajaxUrls: + return ajaxUrls + + return False + + def updateShowsInDb(self): + nrOfaddedShows = 0 + # Get list with thetvdb and imdbIds from DB (tt1234324) + + + # Get thetvdb indexer_id, showname from tvdb using the IMDB id. ttxxxxx + # Use "[{listOfImdbIds}]" for updating the db, if the show isn't in it + tvdb_instance = Tvdb(cache = True, useZip = True) + for watchlistShow in self.listOfImdbIds: + if watchlistShow['imdbid'] not in [x.imdbid for x in sickbeard.showList ]: + TvdbShow = tvdb_instance.search('',imdbid=watchlistShow['imdbid']) + if TvdbShow: + self._addDefaultShow(1, TvdbShow['id'], TvdbShow['seriesname'], False) + nrOfaddedShows += 1 + + return nrOfaddedShows if nrOfaddedShows > 0 else False + + return False + + + def _addDefaultShow(self, indexer, indexer_id, name, status): + """ + Adds a new show with the default settings + """ + if not helpers.findCertainShow(sickbeard.showList, int(indexer_id)): + logger.log(u"Adding show " + str(indexer_id)) + root_dirs = sickbeard.ROOT_DIRS.split('|') + + try: + location = root_dirs[int(root_dirs[0]) + 1] + except: + location = None + + if location: + showPath = ek.ek(os.path.join, location, helpers.sanitizeFileName(name)) + dir_exists = helpers.makeDir(showPath) + if not dir_exists: + logger.log(u"Unable to create the folder " + showPath + ", can't add the show", logger.ERROR) + return + else: + helpers.chmodAsParent(showPath) + + sickbeard.showQueueScheduler.action.addShow(int(indexer), int(indexer_id), showPath, status, + int(sickbeard.QUALITY_DEFAULT), + int(sickbeard.FLATTEN_FOLDERS_DEFAULT), + paused=False, anime = False) + else: + logger.log(u"There was an error creating the show, no root directory setting found", logger.ERROR) + return + +# imdbWatchlistTv = "http://www.imdb.com/user/%s/watchlist?ref_=wl_ref_typ&sort=list_order,asc&mode=simple&page=%s&title_type=tvSeries" +# imdbWatchlistTv2 = "http://www.imdb.com/list/export?list_id=ls009966268&author_id=ur35235230&ref_=wl_exp" +# imdbUserId = "ur5968686" +# imdbListId = "ls005547625" +# imdbWlPage = "1" +# ajaxUrlBase = u"http://www.imdb.com/list/_ajax/list_filter?" +# ajaxUrlQueryString = u"list_id=%s&list_class=WATCHLIST&view=compact&list_type=Titles&filter={\"title_type\":[\"tv_series\"]}&sort_field=created&sort_direction=desc&user_id=%s" % (imdbListId, imdbUserId) +# +# query = {"list_id" : imdbListId, +# "list_class" : "WATCHLIST", +# "view" : "compact", +# "list_type" : "Titles", +# "filter" : '{"title_type":["tv_series"]}', +# "sort_field" : "created", +# "sort_direction" : "desc", +# "user_id" : imdbUserId } +# +# imdbwatchlistcsv = "http://www.imdb.com/list/export?list_id=ls005547625&author_id=ur5968686&ref_=wl_exp" +# imdbWatchListTvFullURL = ajaxUrlBase + urllib.urlencode(query) +# # /download("%s%s" % (baseurl, searchurl), "test.csv") +# +# IMDBobj = IMDB() +# +# #Test one csv +# imdbIds = IMDBobj.checkWatchlist(imdbwatchlistcsv) +# print IMDBobj.listOfImdbIds +# +# # Test two csv's +# imdbIds = IMDBobj.checkWatchlist(imdbwatchlistcsv + "|" + imdbWatchlistTv2) +# print IMDBobj.listOfImdbIds +# +# print imdbIds + diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py index bd6d9ce7..5b3b29f9 100644 --- a/sickbeard/webserve.py +++ b/sickbeard/webserve.py @@ -1425,7 +1425,9 @@ class ConfigGeneral(MainHandler): def saveRootDirs(self, rootDirString=None): sickbeard.ROOT_DIRS = rootDirString - + + def saveImdbWatchlists(self, imdbWatchlistString=None): + sickbeard.IMDB_WATCHLISTCSV = imdbWatchlistString def saveAddShowDefaults(self, defaultStatus, anyQualities, bestQualities, defaultFlattenFolders, subtitles=False, anime=False, scene=False): @@ -1485,7 +1487,7 @@ class ConfigGeneral(MainHandler): handle_reverse_proxy=None, sort_article=None, auto_update=None, notify_on_update=None, proxy_setting=None, anon_redirect=None, git_path=None, calendar_unprotected=None, fuzzy_dating=None, trim_zero=None, date_preset=None, date_preset_na=None, time_preset=None, - indexer_timeout=None, play_videos=None, rootDir=None): + indexer_timeout=None, play_videos=None, rootDir=None, use_imdbwl=None, imdbWatchlistCsv=None): results = [] @@ -1495,6 +1497,7 @@ class ConfigGeneral(MainHandler): config.change_VERSION_NOTIFY(config.checkbox_to_value(version_notify)) sickbeard.AUTO_UPDATE = config.checkbox_to_value(auto_update) sickbeard.NOTIFY_ON_UPDATE = config.checkbox_to_value(notify_on_update) + sickbeard.USE_IMDBWATCHLIST = config.checkbox_to_value(use_imdbwl) # sickbeard.LOG_DIR is set in config.change_LOG_DIR() sickbeard.UPDATE_SHOWS_ON_START = config.checkbox_to_value(update_shows_on_start) diff --git a/tests/test_lib.py b/tests/test_lib.py index 9ab53e69..07a7820c 100644 --- a/tests/test_lib.py +++ b/tests/test_lib.py @@ -206,7 +206,8 @@ def setUp_test_episode_file(): def tearDown_test_episode_file(): - shutil.rmtree(FILEDIR) + if os.path.exists(FILEDIR): + shutil.rmtree(FILEDIR) def setUp_test_show_dir(): @@ -215,7 +216,8 @@ def setUp_test_show_dir(): def tearDown_test_show_dir(): - shutil.rmtree(SHOWDIR) + if os.path.exists(SHOWDIR): + shutil.rmtree(SHOWDIR) tearDown_test_db() diff --git a/tests/test_tvdb_api.py b/tests/test_tvdb_api.py new file mode 100644 index 00000000..4ca60445 --- /dev/null +++ b/tests/test_tvdb_api.py @@ -0,0 +1,152 @@ +"""Unittests for tvdb_api +""" +import unittest +import test_lib as test + +import sys, os.path +sys.path.append(os.path.abspath('..')) +sys.path.append(os.path.abspath('../lib')) + +print sys.path + +from sickbeard import show_name_helpers, scene_exceptions, common, name_cache + +import sickbeard +from sickbeard import db +from sickbeard.databases import cache_db +from sickbeard.tv import TVShow as Show + +from lib.tvdb_api.tvdb_api import * +#import tvdb_api as tvdb_api +import tvdb_api + + + +# class test_tvdb_basic(test.SickbeardTestDBCase): +# # Used to store the cached instance of Tvdb() +# t = None +# +# def setUp(self): +# if self.t is None: +# self.__class__.t = Tvdb(cache = True, banners = False) +# +# def test_different_case(self): +# """Checks the auto-correction of show names is working. +# It should correct the weirdly capitalised 'sCruBs' to 'Scrubs' +# """ +# self.assertEquals(self.t['scrubs'][1][4]['episodename'], 'My Old Lady') +# self.assertEquals(self.t['sCruBs']['seriesname'], 'Scrubs') +# +# def test_spaces(self): +# """Checks shownames with spaces +# """ +# self.assertEquals(self.t['My Name Is Earl']['seriesname'], 'My Name Is Earl') +# self.assertEquals(self.t['My Name Is Earl'][1][4]['episodename'], 'Faked His Own Death') +# +# def test_numeric(self): +# """Checks numeric show names +# """ +# self.assertEquals(self.t['24'][2][20]['episodename'], 'Day 2: 3:00 A.M.-4:00 A.M.') +# self.assertEquals(self.t['24']['seriesname'], '24') +# +# def test_show_iter(self): +# """Iterating over a show returns each seasons +# """ +# self.assertEquals( +# len( +# [season for season in self.t['Life on Mars']] +# ), +# 2 +# ) +# +# def test_season_iter(self): +# """Iterating over a show returns episodes +# """ +# self.assertEquals( +# len( +# [episode for episode in self.t['Life on Mars'][1]] +# ), +# 8 +# ) +# +# def test_get_episode_overview(self): +# """Checks episode overview is retrieved correctly. +# """ +# self.assertEquals( +# self.t['Battlestar Galactica (2003)'][1][6]['overview'].startswith( +# 'When a new copy of Doral, a Cylon who had been previously'), +# True +# ) +# +# def test_get_parent(self): +# """Check accessing series from episode instance +# """ +# show = self.t['Battlestar Galactica (2003)'] +# season = show[1] +# episode = show[1][1] +# +# self.assertEquals( +# season.show, +# show +# ) +# +# self.assertEquals( +# episode.season, +# season +# ) +# +# self.assertEquals( +# episode.season.show, +# show +# ) +# +# def test_no_season(self): +# show = self.t['Katekyo Hitman Reborn'] +# print tvdb_api +# print show[1][1] + + +class searchTvdbImdbid(test.SickbeardTestDBCase): + # Used to store the cached instance of Tvdb() + t = None + + def setUp(self): + if self.t is None: + self.__class__.t = Tvdb(cache = True, useZip = True) + + def test_search(self): + """Test Tvdb.search method + """ + results = self.t.search("",imdbid='tt0903747') + all_ids = results['seriesid'] + self.assertTrue('81189' in all_ids) + + +class test_tvdb_show_search(test.SickbeardTestDBCase): + # Used to store the cached instance of Tvdb() + t = None + + def setUp(self): + if self.t is None: + self.__class__.t = Tvdb(cache = True, useZip = True) + + def test_search(self): + """Test Tvdb.search method + """ + results = self.t.search("my name is earl") + all_ids = results['seriesid'] + self.assertTrue('75397' in all_ids) + + +if __name__ == '__main__': + print "==================" + print "STARTING - PostProcessor TESTS" + print "==================" + print "######################################################################" + print "###Test Search Tvdb for show breaking bad, using the imdb id" + suite = unittest.TestLoader().loadTestsFromTestCase(searchTvdbImdbid) + unittest.TextTestRunner(verbosity=2).run(suite) + print "######################################################################" + print "###Test Search Tvdb for show my name is earl, using the show name" + suite = unittest.TestLoader().loadTestsFromTestCase(test_tvdb_show_search) + unittest.TextTestRunner(verbosity=2).run(suite)