1
0
mirror of https://github.com/moparisthebest/SickRage synced 2024-08-13 16:53:54 -04:00

Merge remote-tracking branch 'origin/dev'

This commit is contained in:
echel0n 2014-07-03 10:34:23 -07:00
commit c7f3a166a4
58 changed files with 397 additions and 487 deletions

View File

@ -67,7 +67,6 @@ from sickbeard.databases.mainDB import MIN_DB_VERSION
from sickbeard.databases.mainDB import MAX_DB_VERSION from sickbeard.databases.mainDB import MAX_DB_VERSION
from lib.configobj import ConfigObj from lib.configobj import ConfigObj
from daemon import Daemon
signal.signal(signal.SIGINT, sickbeard.sig_handler) signal.signal(signal.SIGINT, sickbeard.sig_handler)
signal.signal(signal.SIGTERM, sickbeard.sig_handler) signal.signal(signal.SIGTERM, sickbeard.sig_handler)
@ -76,43 +75,7 @@ throwaway = datetime.datetime.strptime('20110101', '%Y%m%d')
class SickRage(object): class SickRage(object):
def loadShowsFromDB(self):
"""
Populates the showList with shows from the database
"""
logger.log(u"Loading initial show list")
myDB = db.DBConnection()
sqlResults = myDB.select("SELECT * FROM tv_shows")
sickbeard.showList = []
for sqlShow in sqlResults:
try:
curShow = TVShow(int(sqlShow["indexer"]), int(sqlShow["indexer_id"]))
sickbeard.showList.append(curShow)
except Exception, e:
logger.log(
u"There was an error creating the show in " + sqlShow["location"] + ": " + str(e).decode('utf-8'),
logger.ERROR)
logger.log(traceback.format_exc(), logger.DEBUG)
def restore(self, srcDir, dstDir):
try:
for file in os.listdir(srcDir):
srcFile = os.path.join(srcDir, file)
dstFile = os.path.join(dstDir, file)
bakFile = os.path.join(dstDir, file + '.bak')
shutil.move(dstFile, bakFile)
shutil.move(srcFile, dstFile)
os.rmdir(srcDir)
return True
except:
return False
def __init__(self): def __init__(self):
self.daemon = None
self.webserver = None self.webserver = None
self.runAsDaemon = False self.runAsDaemon = False
self.CREATEPID = False self.CREATEPID = False
@ -288,8 +251,7 @@ class SickRage(object):
sickbeard.initialize(consoleLogging=self.consoleLogging) sickbeard.initialize(consoleLogging=self.consoleLogging)
if self.runAsDaemon: if self.runAsDaemon:
self.daemon = Daemon(self.PIDFILE or os.path.join(sickbeard.DATA_DIR, 'sickbeard.pid')) self.daemonize()
self.daemon.daemonize()
# Get PID # Get PID
sickbeard.PID = os.getpid() sickbeard.PID = os.getpid()
@ -361,6 +323,104 @@ class SickRage(object):
while(sickbeard.started): while(sickbeard.started):
time.sleep(1) time.sleep(1)
def daemonize(self):
"""
Fork off as a daemon
"""
# pylint: disable=E1101
# Make a non-session-leader child process
try:
pid = os.fork() # @UndefinedVariable - only available in UNIX
if pid != 0:
os._exit(0)
except OSError, e:
sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
sys.exit(1)
os.setsid() # @UndefinedVariable - only available in UNIX
# Make sure I can read my own files and shut out others
prev = os.umask(0)
os.umask(prev and int('077', 8))
# Make the child a session-leader by detaching from the terminal
try:
pid = os.fork() # @UndefinedVariable - only available in UNIX
if pid != 0:
os._exit(0)
except OSError, e:
sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
sys.exit(1)
# Write pid
if self.CREATEPID:
pid = str(os.getpid())
logger.log(u"Writing PID: " + pid + " to " + str(self.PIDFILE))
try:
file(self.PIDFILE, 'w').write("%s\n" % pid)
except IOError, e:
logger.log_error_and_exit(
u"Unable to write PID file: " + self.PIDFILE + " Error: " + str(e.strerror) + " [" + str(
e.errno) + "]")
# Redirect all output
sys.stdout.flush()
sys.stderr.flush()
devnull = getattr(os, 'devnull', '/dev/null')
stdin = file(devnull, 'r')
stdout = file(devnull, 'a+')
stderr = file(devnull, 'a+')
os.dup2(stdin.fileno(), sys.stdin.fileno())
os.dup2(stdout.fileno(), sys.stdout.fileno())
os.dup2(stderr.fileno(), sys.stderr.fileno())
def remove_pid_file(self, PIDFILE):
try:
if os.path.exists(PIDFILE):
os.remove(PIDFILE)
except (IOError, OSError):
return False
return True
def loadShowsFromDB(self):
"""
Populates the showList with shows from the database
"""
logger.log(u"Loading initial show list")
myDB = db.DBConnection()
sqlResults = myDB.select("SELECT * FROM tv_shows")
sickbeard.showList = []
for sqlShow in sqlResults:
try:
curShow = TVShow(int(sqlShow["indexer"]), int(sqlShow["indexer_id"]))
sickbeard.showList.append(curShow)
except Exception, e:
logger.log(
u"There was an error creating the show in " + sqlShow["location"] + ": " + str(e).decode('utf-8'),
logger.ERROR)
logger.log(traceback.format_exc(), logger.DEBUG)
def restore(self, srcDir, dstDir):
try:
for file in os.listdir(srcDir):
srcFile = os.path.join(srcDir, file)
dstFile = os.path.join(dstDir, file)
bakFile = os.path.join(dstDir, file + '.bak')
shutil.move(dstFile, bakFile)
shutil.move(srcFile, dstFile)
os.rmdir(srcDir)
return True
except:
return False
if __name__ == "__main__": if __name__ == "__main__":
if sys.hexversion >= 0x020600F0: if sys.hexversion >= 0x020600F0:
freeze_support() freeze_support()
@ -379,8 +439,8 @@ if __name__ == "__main__":
sr.webserver = None sr.webserver = None
# if run as daemon delete the pidfile # if run as daemon delete the pidfile
if sr.runAsDaemon: if sr.runAsDaemon and sr.CREATEPID:
sr.daemon.delpid() sr.remove_pid_file(sr.PIDFILE)
if not sickbeard.shutdown: if not sickbeard.shutdown:
install_type = sickbeard.versionCheckScheduler.action.install_type install_type = sickbeard.versionCheckScheduler.action.install_type

View File

@ -92,13 +92,20 @@
<input type="checkbox" name="auto_update" id="auto_update" #if $sickbeard.AUTO_UPDATE then "checked=\"checked\"" else ""#/> <input type="checkbox" name="auto_update" id="auto_update" #if $sickbeard.AUTO_UPDATE then "checked=\"checked\"" else ""#/>
<label class="clearfix" for="auto_update"> <label class="clearfix" for="auto_update">
<span class="component-title">Automatic Updates</span> <span class="component-title">Automatic Updates</span>
<span class="component-desc">Automatically get and install updates for SickRage when available. These</span> <span class="component-desc">Automatically get and install updates for SickRage when available.</span>
</label> </label>
<label class="nocheck clearfix"> <label class="nocheck clearfix">
<span class="component-title">&nbsp;</span> <span class="component-title">&nbsp;</span>
<span class="component-desc">updates run on startup and in the background on the interval specified above.</span> <span class="component-desc">updates run on startup and in the background on the interval specified above.</span>
</label> </label>
</div> </div>
<div class="field-pair">
<input type="checkbox" name="notify_on_update" id="notify_on_update" #if $sickbeard.NOTIFY_ON_UPDATE then "checked=\"checked\"" else ""#/>
<label class="clearfix" for="notify_on_update">
<span class="component-title">Notify on Update</span>
<span class="component-desc">Sends the notification SickRage has been updated to all enabled notifiers.</span>
</label>
</div>
<div class="field-pair"> <div class="field-pair">
<input type="checkbox" name="sort_article" id="sort_article" #if $sickbeard.SORT_ARTICLE then "checked=\"checked\"" else ""#/> <input type="checkbox" name="sort_article" id="sort_article" #if $sickbeard.SORT_ARTICLE then "checked=\"checked\"" else ""#/>

View File

@ -1,183 +0,0 @@
# Core modules
import atexit
import os
import sys
import time
import signal
class Daemon(object):
"""
A generic daemon class.
Usage: subclass the Daemon class and override the run() method
"""
def __init__(self, pidfile, stdin=os.devnull,
stdout=os.devnull, stderr=os.devnull,
home_dir='.', umask=022, verbose=1):
self.stdin = stdin
self.stdout = stdout
self.stderr = stderr
self.pidfile = pidfile
self.home_dir = home_dir
self.verbose = verbose
self.umask = umask
self.daemon_alive = True
def daemonize(self):
"""
Do the UNIX double-fork magic, see Stevens' "Advanced
Programming in the UNIX Environment" for details (ISBN 0201563177)
http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
"""
try:
pid = os.fork()
if pid > 0:
# Exit first parent
os._exit(0)
except OSError, e:
sys.stderr.write(
"fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
sys.exit(1)
# Decouple from parent environment
os.chdir(self.home_dir)
os.setsid()
os.umask(self.umask)
# Do second fork
try:
pid = os.fork()
if pid > 0:
# Exit from second parent
os._exit(0)
except OSError, e:
sys.stderr.write(
"fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
sys.exit(1)
if sys.platform != 'darwin': # This block breaks on OS X
# Redirect standard file descriptors
sys.stdout.flush()
sys.stderr.flush()
si = file(self.stdin, 'r')
so = file(self.stdout, 'a+')
if self.stderr:
se = file(self.stderr, 'a+', 0)
else:
se = so
os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())
if self.verbose >= 1:
print "Started"
# Write pidfile
atexit.register(
self.delpid) # Make sure pid file is removed if we quit
pid = str(os.getpid())
file(self.pidfile, 'w+').write("%s\n" % pid)
def delpid(self):
os.remove(self.pidfile)
def start(self, *args, **kwargs):
"""
Start the daemon
"""
if self.verbose >= 1:
print "Starting..."
# Check for a pidfile to see if the daemon already runs
try:
pf = file(self.pidfile, 'r')
pid = int(pf.read().strip())
pf.close()
except IOError:
pid = None
except SystemExit:
pid = None
if pid:
message = "pidfile %s already exists. Is it already running?\n"
sys.stderr.write(message % self.pidfile)
sys.exit(1)
# Start the daemon
self.daemonize()
self.run(*args, **kwargs)
def stop(self):
"""
Stop the daemon
"""
if self.verbose >= 1:
print "Stopping..."
# Get the pid from the pidfile
pid = self.get_pid()
if not pid:
message = "pidfile %s does not exist. Not running?\n"
sys.stderr.write(message % self.pidfile)
# Just to be sure. A ValueError might occur if the PID file is
# empty but does actually exist
if os.path.exists(self.pidfile):
os.remove(self.pidfile)
return # Not an error in a restart
# Try killing the daemon process
try:
i = 0
while 1:
os.kill(pid, signal.SIGTERM)
time.sleep(0.1)
i = i + 1
if i % 10 == 0:
os.kill(pid, signal.SIGHUP)
except OSError, err:
err = str(err)
if err.find("No such process") > 0:
if os.path.exists(self.pidfile):
os.remove(self.pidfile)
else:
print str(err)
sys.exit(1)
if self.verbose >= 1:
print "Stopped"
def restart(self):
"""
Restart the daemon
"""
self.stop()
self.start()
def get_pid(self):
try:
pf = file(self.pidfile, 'r')
pid = int(pf.read().strip())
pf.close()
except IOError:
pid = None
except SystemExit:
pid = None
return pid
def is_running(self):
pid = self.get_pid()
print(pid)
return pid and os.path.exists('/proc/%d' % pid)
def run(self):
"""
You should override this method when you subclass Daemon.
It will be called after the process has been
daemonized by start() or restart().
"""

View File

@ -100,6 +100,7 @@ NEWEST_VERSION = None
NEWEST_VERSION_STRING = None NEWEST_VERSION_STRING = None
VERSION_NOTIFY = None VERSION_NOTIFY = None
AUTO_UPDATE = None AUTO_UPDATE = None
NOTIFY_ON_UPDATE = None
CUR_COMMIT_HASH = None CUR_COMMIT_HASH = None
INIT_LOCK = Lock() INIT_LOCK = Lock()
@ -457,7 +458,7 @@ def initialize(consoleLogging=True):
USE_NMA, NMA_NOTIFY_ONSNATCH, NMA_NOTIFY_ONDOWNLOAD, NMA_NOTIFY_ONSUBTITLEDOWNLOAD, NMA_API, NMA_PRIORITY, \ USE_NMA, NMA_NOTIFY_ONSNATCH, NMA_NOTIFY_ONDOWNLOAD, NMA_NOTIFY_ONSUBTITLEDOWNLOAD, NMA_API, NMA_PRIORITY, \
USE_PUSHALOT, PUSHALOT_NOTIFY_ONSNATCH, PUSHALOT_NOTIFY_ONDOWNLOAD, PUSHALOT_NOTIFY_ONSUBTITLEDOWNLOAD, PUSHALOT_AUTHORIZATIONTOKEN, \ USE_PUSHALOT, PUSHALOT_NOTIFY_ONSNATCH, PUSHALOT_NOTIFY_ONDOWNLOAD, PUSHALOT_NOTIFY_ONSUBTITLEDOWNLOAD, PUSHALOT_AUTHORIZATIONTOKEN, \
USE_PUSHBULLET, PUSHBULLET_NOTIFY_ONSNATCH, PUSHBULLET_NOTIFY_ONDOWNLOAD, PUSHBULLET_NOTIFY_ONSUBTITLEDOWNLOAD, PUSHBULLET_API, PUSHBULLET_DEVICE, \ USE_PUSHBULLET, PUSHBULLET_NOTIFY_ONSNATCH, PUSHBULLET_NOTIFY_ONDOWNLOAD, PUSHBULLET_NOTIFY_ONSUBTITLEDOWNLOAD, PUSHBULLET_API, PUSHBULLET_DEVICE, \
versionCheckScheduler, VERSION_NOTIFY, AUTO_UPDATE, PROCESS_AUTOMATICALLY, UNPACK, CPU_PRESET, \ versionCheckScheduler, VERSION_NOTIFY, AUTO_UPDATE, NOTIFY_ON_UPDATE, PROCESS_AUTOMATICALLY, UNPACK, CPU_PRESET, \
KEEP_PROCESSED_DIR, PROCESS_METHOD, TV_DOWNLOAD_DIR, MIN_DAILYSEARCH_FREQUENCY, DEFAULT_UPDATE_FREQUENCY, MIN_UPDATE_FREQUENCY, UPDATE_FREQUENCY, \ KEEP_PROCESSED_DIR, PROCESS_METHOD, TV_DOWNLOAD_DIR, MIN_DAILYSEARCH_FREQUENCY, DEFAULT_UPDATE_FREQUENCY, MIN_UPDATE_FREQUENCY, UPDATE_FREQUENCY, \
showQueueScheduler, searchQueueScheduler, ROOT_DIRS, CACHE_DIR, ACTUAL_CACHE_DIR, TIMEZONE_DISPLAY, \ showQueueScheduler, searchQueueScheduler, ROOT_DIRS, CACHE_DIR, ACTUAL_CACHE_DIR, TIMEZONE_DISPLAY, \
NAMING_PATTERN, NAMING_MULTI_EP, NAMING_FORCE_FOLDERS, NAMING_ABD_PATTERN, NAMING_CUSTOM_ABD, NAMING_SPORTS_PATTERN, NAMING_CUSTOM_SPORTS, 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, \
@ -589,6 +590,7 @@ def initialize(consoleLogging=True):
STATUS_DEFAULT = check_setting_int(CFG, 'General', 'status_default', SKIPPED) STATUS_DEFAULT = check_setting_int(CFG, 'General', 'status_default', SKIPPED)
VERSION_NOTIFY = check_setting_int(CFG, 'General', 'version_notify', 1) VERSION_NOTIFY = check_setting_int(CFG, 'General', 'version_notify', 1)
AUTO_UPDATE = check_setting_int(CFG, 'General', 'auto_update', 0) AUTO_UPDATE = check_setting_int(CFG, 'General', 'auto_update', 0)
NOTIFY_ON_UPDATE = check_setting_int(CFG, 'General', 'notify_on_update', 1)
FLATTEN_FOLDERS_DEFAULT = bool(check_setting_int(CFG, 'General', 'flatten_folders_default', 0)) FLATTEN_FOLDERS_DEFAULT = bool(check_setting_int(CFG, 'General', 'flatten_folders_default', 0))
INDEXER_DEFAULT = check_setting_int(CFG, 'General', 'indexer_default', 0) INDEXER_DEFAULT = check_setting_int(CFG, 'General', 'indexer_default', 0)
INDEXER_TIMEOUT = check_setting_int(CFG, 'General', 'indexer_timeout', 10) INDEXER_TIMEOUT = check_setting_int(CFG, 'General', 'indexer_timeout', 10)
@ -1272,17 +1274,6 @@ def halt():
__INITIALIZED__ = False __INITIALIZED__ = False
started = False started = False
def remove_pid_file(PIDFILE):
try:
if os.path.exists(PIDFILE):
os.remove(PIDFILE)
except (IOError, OSError):
return False
return True
def sig_handler(signum=None, frame=None): def sig_handler(signum=None, frame=None):
if type(signum) != type(None): if type(signum) != type(None):
logger.log(u"Signal %i caught, saving and exiting..." % int(signum)) logger.log(u"Signal %i caught, saving and exiting..." % int(signum))
@ -1388,6 +1379,7 @@ def save_config():
new_config['General']['provider_order'] = ' '.join(PROVIDER_ORDER) new_config['General']['provider_order'] = ' '.join(PROVIDER_ORDER)
new_config['General']['version_notify'] = int(VERSION_NOTIFY) new_config['General']['version_notify'] = int(VERSION_NOTIFY)
new_config['General']['auto_update'] = int(AUTO_UPDATE) new_config['General']['auto_update'] = int(AUTO_UPDATE)
new_config['General']['notify_on_update'] = int(NOTIFY_ON_UPDATE)
new_config['General']['naming_strip_year'] = int(NAMING_STRIP_YEAR) new_config['General']['naming_strip_year'] = int(NAMING_STRIP_YEAR)
new_config['General']['naming_pattern'] = NAMING_PATTERN new_config['General']['naming_pattern'] = NAMING_PATTERN
new_config['General']['naming_custom_abd'] = int(NAMING_CUSTOM_ABD) new_config['General']['naming_custom_abd'] = int(NAMING_CUSTOM_ABD)

View File

@ -50,11 +50,15 @@ SEASON_RESULT = -2
NOTIFY_SNATCH = 1 NOTIFY_SNATCH = 1
NOTIFY_DOWNLOAD = 2 NOTIFY_DOWNLOAD = 2
NOTIFY_SUBTITLE_DOWNLOAD = 3 NOTIFY_SUBTITLE_DOWNLOAD = 3
NOTIFY_SICKRAGE_UPDATE = 4
NOTIFY_SICKRAGE_UPDATE_TEXT = 5
notifyStrings = {} notifyStrings = {}
notifyStrings[NOTIFY_SNATCH] = "Started Download" notifyStrings[NOTIFY_SNATCH] = "Started Download"
notifyStrings[NOTIFY_DOWNLOAD] = "Download Finished" notifyStrings[NOTIFY_DOWNLOAD] = "Download Finished"
notifyStrings[NOTIFY_SUBTITLE_DOWNLOAD] = "Subtitle Download Finished" notifyStrings[NOTIFY_SUBTITLE_DOWNLOAD] = "Subtitle Download Finished"
notifyStrings[NOTIFY_SICKRAGE_UPDATE] = "SickRage Updated"
notifyStrings[NOTIFY_SICKRAGE_UPDATE_TEXT] = "SickRage updated to version: "
### Episode statuses ### Episode statuses
UNKNOWN = -1 # should never happen UNKNOWN = -1 # should never happen

View File

@ -36,9 +36,6 @@ class DailySearcher():
self.amActive = False self.amActive = False
def __del__(self):
pass
def run(self, force=False): def run(self, force=False):
self.amActive = True self.amActive = True
@ -110,9 +107,6 @@ class DailySearcher():
for show in todaysEps: for show in todaysEps:
segment = todaysEps[show] segment = todaysEps[show]
# remove show from name cache if marked invalid
sickbeard.name_cache.clearCache(show)
dailysearch_queue_item = sickbeard.search_queue.DailySearchQueueItem(show, segment) dailysearch_queue_item = sickbeard.search_queue.DailySearchQueueItem(show, segment)
sickbeard.searchQueueScheduler.action.add_item(dailysearch_queue_item) sickbeard.searchQueueScheduler.action.add_item(dailysearch_queue_item)
else: else:

View File

@ -164,6 +164,8 @@ class DBConnection(object):
logger.log(u"Fatal error executing query: " + ex(e), logger.ERROR) logger.log(u"Fatal error executing query: " + ex(e), logger.ERROR)
raise raise
time.sleep(0.05)
return sqlResult return sqlResult
def action(self, query, args=None, fetchall=False, fetchone=False): def action(self, query, args=None, fetchall=False, fetchone=False):
@ -199,6 +201,8 @@ class DBConnection(object):
logger.log(u"Fatal error executing query: " + ex(e), logger.ERROR) logger.log(u"Fatal error executing query: " + ex(e), logger.ERROR)
raise raise
time.sleep(0.05)
return sqlResult return sqlResult
def select(self, query, args=None): def select(self, query, args=None):

View File

@ -730,7 +730,6 @@ def sanitizeSceneName(name, ezrss=False):
""" """
if name: if name:
if not ezrss: if not ezrss:
bad_chars = u",:()'!?\u2019" bad_chars = u",:()'!?\u2019"
# ezrss leaves : and ! in their show names as far as I can tell # ezrss leaves : and ! in their show names as far as I can tell
@ -1066,37 +1065,24 @@ def _check_against_names(nameInQuestion, show, season=-1):
def get_show_by_name(name, useIndexer=False): def get_show_by_name(name, useIndexer=False):
name = full_sanitizeSceneName(name)
try: try:
# check cache for show # check cache for show
showObj = sickbeard.name_cache.retrieveShowFromCache(name) showObj = sickbeard.name_cache.retrieveShowFromCache(name)
if showObj: if showObj:
return showObj return showObj
if not showObj and sickbeard.showList: if useIndexer and sickbeard.showList and not showObj:
db_indexerid = searchDBForShow(name) (sn, idx, id) = searchIndexerForShowID(full_sanitizeSceneName(name), ui=classes.ShowListUI)
if db_indexerid: if id:
showObj = findCertainShow(sickbeard.showList, db_indexerid) showObj = findCertainShow(sickbeard.showList, int(id))
if not showObj:
scene_indexerid, scene_season = sickbeard.scene_exceptions.get_scene_exception_by_name(name)
if scene_indexerid:
showObj = findCertainShow(sickbeard.showList, scene_indexerid)
if useIndexer and not showObj:
(sn, idx, id) = searchIndexerForShowID(name, ui=classes.ShowListUI)
if id:
showObj = findCertainShow(sickbeard.showList, int(id))
# add show to cache # add show to cache
if showObj: if showObj:
sickbeard.name_cache.addNameToCache(name, showObj.indexerid) sickbeard.name_cache.addNameToCache(name, showObj.indexerid)
return showObj
except: except:
showObj = None pass
return showObj
def is_hidden_folder(folder): def is_hidden_folder(folder):
""" """

View File

@ -23,7 +23,7 @@ import sickbeard
from sickbeard import scene_exceptions from sickbeard import scene_exceptions
from sickbeard import failed_history from sickbeard import failed_history
from sickbeard import network_timezones from sickbeard import network_timezones
from sickbeard import name_cache
class Maintenance(): class Maintenance():
def __init__(self): def __init__(self):
@ -31,15 +31,18 @@ class Maintenance():
self.amActive = False self.amActive = False
def __del__(self):
pass
def run(self, force=False): def run(self, force=False):
self.amActive = True self.amActive = True
# clear internal name cache
name_cache.clearCache()
# get and update scene exceptions lists # get and update scene exceptions lists
scene_exceptions.retrieve_exceptions() scene_exceptions.retrieve_exceptions()
# build internal name cache for searches and parsing
name_cache.buildNameCache()
# refresh network timezones # refresh network timezones
network_timezones.update_network_dict() network_timezones.update_network_dict()

View File

@ -22,6 +22,8 @@ from sickbeard import db
from sickbeard.helpers import sanitizeSceneName from sickbeard.helpers import sanitizeSceneName
from sickbeard import logger from sickbeard import logger
nameCache = None
def addNameToCache(name, indexer_id=0): def addNameToCache(name, indexer_id=0):
""" """
Adds the show & tvdb id to the scene_names table in cache.db. Adds the show & tvdb id to the scene_names table in cache.db.
@ -29,11 +31,15 @@ def addNameToCache(name, indexer_id=0):
name: The show name to cache name: The show name to cache
indexer_id: the TVDB and TVRAGE id that this show should be cached with (can be None/0 for unknown) indexer_id: the TVDB and TVRAGE id that this show should be cached with (can be None/0 for unknown)
""" """
global nameCache
cacheDB = db.DBConnection('cache.db')
# standardize the name we're using to account for small differences in providers # standardize the name we're using to account for small differences in providers
name = sanitizeSceneName(name) name = sickbeard.helpers.full_sanitizeSceneName(name)
myDB = db.DBConnection('cache.db') if name not in nameCache:
myDB.action("INSERT INTO scene_names (indexer_id, name) VALUES (?, ?)", [indexer_id, name]) nameCache[name] = int(indexer_id)
cacheDB.action("INSERT OR REPLACE INTO scene_names (indexer_id, name) VALUES (?, ?)", [indexer_id, name])
def retrieveNameFromCache(name): def retrieveNameFromCache(name):
@ -44,33 +50,66 @@ def retrieveNameFromCache(name):
Returns: the TVDB and TVRAGE id that resulted from the cache lookup or None if the show wasn't found in the cache Returns: the TVDB and TVRAGE id that resulted from the cache lookup or None if the show wasn't found in the cache
""" """
global nameCache
cache_results = None name = sickbeard.helpers.full_sanitizeSceneName(name)
if name in nameCache:
# standardize the name we're using to account for small differences in providers return int(nameCache[name])
name = sanitizeSceneName(name)
myDB = db.DBConnection('cache.db')
if myDB.hasTable('scene_names'):
cache_results = myDB.select("SELECT * FROM scene_names WHERE name = ?", [name])
if cache_results:
return int(cache_results[0]["indexer_id"])
def retrieveShowFromCache(name): def retrieveShowFromCache(name):
indexerid = retrieveNameFromCache(name) global nameCache
if indexerid:
return sickbeard.helpers.findCertainShow(sickbeard.showList, int(indexerid))
def clearCache(show=None, season=-1, indexer_id=0): indexer_id = retrieveNameFromCache(name)
if indexer_id:
return sickbeard.helpers.findCertainShow(sickbeard.showList, int(indexer_id))
def clearCache():
""" """
Deletes all "unknown" entries from the cache (names with indexer_id of 0). Deletes all "unknown" entries from the cache (names with indexer_id of 0).
""" """
global nameCache
myDB = db.DBConnection('cache.db') # init name cache
if show: if not nameCache:
showNames = sickbeard.show_name_helpers.allPossibleShowNames(show, season=season) nameCache = {}
for showName in showNames:
myDB.action("DELETE FROM scene_names WHERE name = ? and indexer_id = ?", [showName, indexer_id]) cacheDB = db.DBConnection('cache.db')
else: cacheDB.action("DELETE FROM scene_names WHERE indexer_id = ?", [0])
myDB.action("DELETE FROM scene_names WHERE indexer_id = ?", [indexer_id])
toRemove = [key for key, value in nameCache.iteritems() if value == 0]
for key in toRemove:
del nameCache[key]
def saveNameCacheToDb():
cacheDB = db.DBConnection('cache.db')
for name, indexer_id in nameCache.items():
cacheDB.action("INSERT OR REPLACE INTO scene_names (indexer_id, name) VALUES (?, ?)", [indexer_id, name])
def buildNameCache():
global nameCache
# init name cache
if not nameCache:
nameCache = {}
# clear internal name cache
clearCache()
logger.log(u"Updating internal name cache", logger.MESSAGE)
cacheDB = db.DBConnection('cache.db')
cache_results = cacheDB.select("SELECT * FROM scene_names")
for cache_result in cache_results:
name = sickbeard.helpers.full_sanitizeSceneName(cache_result["name"])
indexer_id = int(cache_result["indexer_id"])
nameCache[name] = indexer_id
for show in sickbeard.showList:
for curSeason in [-1] + sickbeard.scene_exceptions.get_scene_seasons(show.indexerid):
nameCache[sickbeard.helpers.full_sanitizeSceneName(show.name)] = show.indexerid
for name in sickbeard.scene_exceptions.get_scene_exceptions(show.indexerid, season=curSeason):
nameCache[sickbeard.helpers.full_sanitizeSceneName(name)] = show.indexerid
logger.log(u"Updated internal name cache", logger.MESSAGE)
logger.log(u"Internal name cache set to: " + str(nameCache), logger.DEBUG)

View File

@ -45,9 +45,6 @@ class NameParser(object):
self.convert = convert self.convert = convert
self.naming_pattern = naming_pattern self.naming_pattern = naming_pattern
def __del__(self):
pass
def clean_series_name(self, series_name): def clean_series_name(self, series_name):
"""Cleans up series name by removing any . and _ """Cleans up series name by removing any . and _
characters, along with any trailing hyphens. characters, along with any trailing hyphens.
@ -446,9 +443,6 @@ class ParseResult(object):
self.show = show self.show = show
self.score = score self.score = score
def __del__(self):
pass
def __eq__(self, other): def __eq__(self, other):
if not other: if not other:
return False return False
@ -624,11 +618,7 @@ class NameParserCache(object):
logger.log("Using cached parse result for: " + name, logger.DEBUG) logger.log("Using cached parse result for: " + name, logger.DEBUG)
return self._previous_parsed[name] return self._previous_parsed[name]
def __del__(self):
pass
name_parser_cache = NameParserCache() name_parser_cache = NameParserCache()
class InvalidNameException(Exception): class InvalidNameException(Exception):
"The given name is not valid" "The given name is not valid"

View File

@ -101,3 +101,8 @@ def notify_subtitle_download(ep_name, lang):
def notify_snatch(ep_name): def notify_snatch(ep_name):
for n in notifiers: for n in notifiers:
n.notify_snatch(ep_name) n.notify_snatch(ep_name)
def notify_sickrage_update(new_version = ""):
if sickbeard.NOTIFY_ON_UPDATE:
for n in notifiers:
n.notify_sickrage_update(new_version)

View File

@ -23,7 +23,7 @@ import time
import sickbeard import sickbeard
from sickbeard import logger from sickbeard import logger
from sickbeard.common import notifyStrings, NOTIFY_SNATCH, NOTIFY_DOWNLOAD, NOTIFY_SUBTITLE_DOWNLOAD from sickbeard.common import notifyStrings, NOTIFY_SNATCH, NOTIFY_DOWNLOAD, NOTIFY_SUBTITLE_DOWNLOAD, NOTIFY_SICKRAGE_UPDATE, NOTIFY_SICKRAGE_UPDATE_TEXT
from sickbeard.exceptions import ex from sickbeard.exceptions import ex
API_URL = "https://boxcar.io/devices/providers/fWc4sgSmpcN6JujtBmR6/notifications" API_URL = "https://boxcar.io/devices/providers/fWc4sgSmpcN6JujtBmR6/notifications"
@ -123,6 +123,12 @@ class BoxcarNotifier:
if sickbeard.BOXCAR_NOTIFY_ONSUBTITLEDOWNLOAD: if sickbeard.BOXCAR_NOTIFY_ONSUBTITLEDOWNLOAD:
self._notifyBoxcar(title, ep_name + ": " + lang) self._notifyBoxcar(title, ep_name + ": " + lang)
def notify_sickrage_update(self, new_version = "??"):
if sickbeard.USE_BOXCAR:
update_text=notifyStrings[NOTIFY_SICKRAGE_UPDATE_TEXT]
title=notifyStrings[NOTIFY_SICKRAGE_UPDATE]
self._notifyBoxcar(title, update_text + new_version)
def _notifyBoxcar(self, title, message, username=None, force=False): def _notifyBoxcar(self, title, message, username=None, force=False):
""" """
Sends a boxcar notification based on the provided info or SB config Sends a boxcar notification based on the provided info or SB config

View File

@ -24,7 +24,7 @@ import time
import sickbeard import sickbeard
from sickbeard import logger from sickbeard import logger
from sickbeard.common import notifyStrings, NOTIFY_SNATCH, NOTIFY_DOWNLOAD, NOTIFY_SUBTITLE_DOWNLOAD from sickbeard.common import notifyStrings, NOTIFY_SNATCH, NOTIFY_DOWNLOAD, NOTIFY_SUBTITLE_DOWNLOAD, NOTIFY_SICKRAGE_UPDATE, NOTIFY_SICKRAGE_UPDATE_TEXT
from sickbeard.exceptions import ex from sickbeard.exceptions import ex
API_URL = "https://new.boxcar.io/api/notifications" API_URL = "https://new.boxcar.io/api/notifications"
@ -97,6 +97,12 @@ class Boxcar2Notifier:
if sickbeard.BOXCAR2_NOTIFY_ONSUBTITLEDOWNLOAD: if sickbeard.BOXCAR2_NOTIFY_ONSUBTITLEDOWNLOAD:
self._notifyBoxcar2(title, ep_name + ": " + lang) self._notifyBoxcar2(title, ep_name + ": " + lang)
def notify_sickrage_update(self, new_version = "??"):
if sickbeard.USE_BOXCAR2:
update_text=notifyStrings[NOTIFY_SICKRAGE_UPDATE_TEXT]
title=notifyStrings[NOTIFY_SICKRAGE_UPDATE]
self._notifyBoxcar2(title, update_text + new_version)
def _notifyBoxcar2(self, title, message, accesstoken=None): def _notifyBoxcar2(self, title, message, accesstoken=None):
""" """
Sends a boxcar2 notification based on the provided info or SB config Sends a boxcar2 notification based on the provided info or SB config

View File

@ -27,7 +27,7 @@ import re
import sickbeard import sickbeard
from sickbeard import logger from sickbeard import logger, common
from sickbeard import db from sickbeard import db
from sickbeard.exceptions import ex from sickbeard.exceptions import ex
@ -142,6 +142,37 @@ class EmailNotifier:
else: else:
logger.log("Download notification ERROR: %s" % self.last_err, logger.ERROR) logger.log("Download notification ERROR: %s" % self.last_err, logger.ERROR)
def notify_sickrage_update(self, new_version = "??"):
"""
Send a notification that an updated version of SickRage has been installed
"""
if sickbeard.USE_EMAIL:
update_text=common.notifyStrings[common.NOTIFY_SICKRAGE_UPDATE_TEXT]
title=common.notifyStrings[common.NOTIFY_SICKRAGE_UPDATE]
to = self._generate_recepients(show)
if len(to) == 0:
logger.log('Skipping email notify because there are no configured recepients', logger.WARNING)
else:
try:
msg = MIMEMultipart('alternative')
msg.attach(MIMEText(
"<body style='font-family:Helvetica, Arial, sans-serif;'><h3>SickRage Notification - " + title + "</h3>\n<p>" + update_text + new_version + "</p>\n\n<footer style='margin-top: 2.5em; padding: .7em 0; color: #777; border-top: #BBB solid 1px;'>Powered by SickRage.</footer></body>",
'html'))
except:
logger.log("SickRage update notification ERROR: %s" % self.last_err, logger.ERROR)
msg['Subject'] = lang + ' Subtitle Downloaded: ' + ep_name
msg['From'] = sickbeard.EMAIL_FROM
msg['To'] = ','.join(to)
if self._sendmail(sickbeard.EMAIL_HOST, sickbeard.EMAIL_PORT, sickbeard.EMAIL_FROM, sickbeard.EMAIL_TLS,
sickbeard.EMAIL_USER, sickbeard.EMAIL_PASSWORD, to, msg):
logger.log("Download notification sent to [%s] for '%s'" % (to, ep_name), logger.DEBUG)
else:
logger.log("Download notification ERROR: %s" % self.last_err, logger.ERROR)
def _generate_recepients(self, show): def _generate_recepients(self, show):
addrs = [] addrs = []

View File

@ -44,6 +44,12 @@ class GrowlNotifier:
if sickbeard.GROWL_NOTIFY_ONSUBTITLEDOWNLOAD: if sickbeard.GROWL_NOTIFY_ONSUBTITLEDOWNLOAD:
self._sendGrowl(common.notifyStrings[common.NOTIFY_SUBTITLE_DOWNLOAD], ep_name + ": " + lang) self._sendGrowl(common.notifyStrings[common.NOTIFY_SUBTITLE_DOWNLOAD], ep_name + ": " + lang)
def notify_sickrage_update(self, new_version = "??"):
if sickbeard.USE_GROWL:
update_text=common.notifyStrings[common.NOTIFY_SICKRAGE_UPDATE_TEXT]
title=common.notifyStrings[common.NOTIFY_SICKRAGE_UPDATE]
self._sendGrowl(title, update_text + new_version)
def _send_growl(self, options, message=None): def _send_growl(self, options, message=None):
#Send Notification #Send Notification

View File

@ -93,6 +93,11 @@ class LibnotifyNotifier:
if sickbeard.LIBNOTIFY_NOTIFY_ONSUBTITLEDOWNLOAD: if sickbeard.LIBNOTIFY_NOTIFY_ONSUBTITLEDOWNLOAD:
self._notify(common.notifyStrings[common.NOTIFY_SUBTITLE_DOWNLOAD], ep_name + ": " + lang) self._notify(common.notifyStrings[common.NOTIFY_SUBTITLE_DOWNLOAD], ep_name + ": " + lang)
def notify_sickrage_update(self, new_version = "??"):
if sickbeard.USE_LIBNOTIFY:
update_text=common.notifyStrings[common.NOTIFY_SICKRAGE_UPDATE_TEXT], title=common.notifyStrings[common.NOTIFY_SICKRAGE_UPDATE]
self._notify(title, update_text + new_version)
def test_notify(self): def test_notify(self):
return self._notify('Test notification', "This is a test notification from SickRage", force=True) return self._notify('Test notification', "This is a test notification from SickRage", force=True)

View File

@ -24,6 +24,12 @@ class NMA_Notifier:
self._sendNMA(nma_api=None, nma_priority=None, event=common.notifyStrings[common.NOTIFY_SUBTITLE_DOWNLOAD], self._sendNMA(nma_api=None, nma_priority=None, event=common.notifyStrings[common.NOTIFY_SUBTITLE_DOWNLOAD],
message=ep_name + ": " + lang) message=ep_name + ": " + lang)
def notify_sickrage_update(self, new_version = "??"):
if sickbeard.USE_NMA:
update_text=common.notifyStrings[common.NOTIFY_SICKRAGE_UPDATE_TEXT]
title=common.notifyStrings[common.NOTIFY_SICKRAGE_UPDATE]
self._sendNMA(nma_api=None, nma_priority=None, event=title, message=update_text + new_version)
def _sendNMA(self, nma_api=None, nma_priority=None, event=None, message=None, force=False): def _sendNMA(self, nma_api=None, nma_priority=None, event=None, message=None, force=False):
title = 'SickRage' title = 'SickRage'

View File

@ -97,6 +97,10 @@ class NMJNotifier:
if sickbeard.USE_NMJ: if sickbeard.USE_NMJ:
self._notifyNMJ() self._notifyNMJ()
def notify_sickrage_update(self, new_version):
return False
# Not implemented, no reason to start scanner.
def test_notify(self, host, database, mount): def test_notify(self, host, database, mount):
return self._sendNMJ(host, database, mount) return self._sendNMJ(host, database, mount)

View File

@ -43,6 +43,10 @@ class NMJv2Notifier:
def notify_subtitle_download(self, ep_name, lang): def notify_subtitle_download(self, ep_name, lang):
self._notifyNMJ() self._notifyNMJ()
def notify_sickrage_update(self, new_version):
return False
# Not implemented, no reason to start scanner.
def test_notify(self, host): def test_notify(self, host):
return self._sendNMJ(host) return self._sendNMJ(host)

View File

@ -66,6 +66,12 @@ class PLEXNotifier(XBMCNotifier):
if sickbeard.PLEX_NOTIFY_ONSUBTITLEDOWNLOAD: if sickbeard.PLEX_NOTIFY_ONSUBTITLEDOWNLOAD:
self._notify_pmc(ep_name + ": " + lang, common.notifyStrings[common.NOTIFY_SUBTITLE_DOWNLOAD]) self._notify_pmc(ep_name + ": " + lang, common.notifyStrings[common.NOTIFY_SUBTITLE_DOWNLOAD])
def notify_sickrage_update(self, new_version = "??"):
if sickbeard.USE_PLEX:
update_text=common.notifyStrings[common.NOTIFY_SICKRAGE_UPDATE_TEXT]
title=common.notifyStrings[common.NOTIFY_SICKRAGE_UPDATE]
self._notify_pmc(update_text + new_version, title)
def test_notify(self, host, username, password): def test_notify(self, host, username, password):
return self._notify_pmc("Testing Plex notifications from SickRage", "Test Notification", host, username, return self._notify_pmc("Testing Plex notifications from SickRage", "Test Notification", host, username,
password, force=True) password, force=True)

View File

@ -52,6 +52,13 @@ class ProwlNotifier:
self._sendProwl(prowl_api=None, prowl_priority=None, self._sendProwl(prowl_api=None, prowl_priority=None,
event=common.notifyStrings[common.NOTIFY_SUBTITLE_DOWNLOAD], message=ep_name + ": " + lang) event=common.notifyStrings[common.NOTIFY_SUBTITLE_DOWNLOAD], message=ep_name + ": " + lang)
def notify_sickrage_update(self, new_version = "??"):
if sickbeard.USE_PROWL:
update_text=common.notifyStrings[common.NOTIFY_SICKRAGE_UPDATE_TEXT]
title=common.notifyStrings[common.NOTIFY_SICKRAGE_UPDATE]
self._sendProwl(prowl_api=None, prowl_priority=None,
event=title, message=update_text + new_version)
def _sendProwl(self, prowl_api=None, prowl_priority=None, event=None, message=None, force=False): def _sendProwl(self, prowl_api=None, prowl_priority=None, event=None, message=None, force=False):
if not sickbeard.USE_PROWL and not force: if not sickbeard.USE_PROWL and not force:

View File

@ -46,6 +46,14 @@ class PushalotNotifier:
event=common.notifyStrings[common.NOTIFY_SUBTITLE_DOWNLOAD], event=common.notifyStrings[common.NOTIFY_SUBTITLE_DOWNLOAD],
message=ep_name + ": " + lang) message=ep_name + ": " + lang)
def notify_sickrage_update(self, new_version = "??"):
if sickbeard.USE_PUSHALOT:
update_text=common.notifyStrings[common.NOTIFY_SICKRAGE_UPDATE_TEXT]
title=common.notifyStrings[common.NOTIFY_SICKRAGE_UPDATE]
self._sendPushalot(pushalot_authorizationtoken=None,
event=title,
message=update_text + new_version)
def _sendPushalot(self, pushalot_authorizationtoken=None, event=None, message=None, force=False): def _sendPushalot(self, pushalot_authorizationtoken=None, event=None, message=None, force=False):
if not sickbeard.USE_PUSHALOT and not force: if not sickbeard.USE_PUSHALOT and not force:

View File

@ -49,6 +49,12 @@ class PushbulletNotifier:
self._sendPushbullet(pushbullet_api=None, event=common.notifyStrings[common.NOTIFY_SUBTITLE_DOWNLOAD] + " : " + ep_name + " : " + lang, self._sendPushbullet(pushbullet_api=None, event=common.notifyStrings[common.NOTIFY_SUBTITLE_DOWNLOAD] + " : " + ep_name + " : " + lang,
message=ep_name + ": " + lang, notificationType="note", method="POST") message=ep_name + ": " + lang, notificationType="note", method="POST")
def notify_sickrage_update(self, new_version = "??"):
if sickbeard.USE_PUSHBULLET:
update_text=common.notifyStrings[common.NOTIFY_SICKRAGE_UPDATE_TEXT]
title=common.notifyStrings[common.NOTIFY_SICKRAGE_UPDATE]
self._sendPushbullet(pushbullet_api=None, event=title, message=update_text + new_version, method="POST")
def _sendPushbullet(self, pushbullet_api=None, pushbullet_device=None, event=None, message=None, def _sendPushbullet(self, pushbullet_api=None, pushbullet_device=None, event=None, message=None,
notificationType=None, method=None, force=False): notificationType=None, method=None, force=False):

View File

@ -23,7 +23,7 @@ import time
import sickbeard import sickbeard
from sickbeard import logger from sickbeard import logger
from sickbeard.common import notifyStrings, NOTIFY_SNATCH, NOTIFY_DOWNLOAD, NOTIFY_SUBTITLE_DOWNLOAD from sickbeard.common import notifyStrings, NOTIFY_SNATCH, NOTIFY_DOWNLOAD, NOTIFY_SUBTITLE_DOWNLOAD, NOTIFY_SICKRAGE_UPDATE, NOTIFY_SICKRAGE_UPDATE_TEXT
from sickbeard.exceptions import ex from sickbeard.exceptions import ex
API_URL = "https://api.pushover.net/1/messages.json" API_URL = "https://api.pushover.net/1/messages.json"
@ -120,6 +120,12 @@ class PushoverNotifier:
if sickbeard.PUSHOVER_NOTIFY_ONSUBTITLEDOWNLOAD: if sickbeard.PUSHOVER_NOTIFY_ONSUBTITLEDOWNLOAD:
self._notifyPushover(title, ep_name + ": " + lang) self._notifyPushover(title, ep_name + ": " + lang)
def notify_sickrage_update(self, new_version = "??"):
if sickbeard.USE_PUSHOVER:
update_text=notifyStrings[NOTIFY_SICKRAGE_UPDATE_TEXT]
title=notifyStrings[NOTIFY_SICKRAGE_UPDATE]
self._notifyPushover(title, update_text + new_version)
def _notifyPushover(self, title, message, userKey=None, apiKey=None, force=False): def _notifyPushover(self, title, message, userKey=None, apiKey=None, force=False):
""" """
Sends a pushover notification based on the provided info or SB config Sends a pushover notification based on the provided info or SB config

View File

@ -37,6 +37,9 @@ class pyTivoNotifier:
def notify_subtitle_download(self, ep_name, lang): def notify_subtitle_download(self, ep_name, lang):
pass pass
def notify_sickrage_update(self, new_version):
pass
def update_library(self, ep_obj): def update_library(self, ep_obj):
# Values from config # Values from config

View File

@ -38,6 +38,9 @@ class synoIndexNotifier:
def notify_subtitle_download(self, ep_name, lang): def notify_subtitle_download(self, ep_name, lang):
pass pass
def notify_sickrage_update(self, new_version):
pass
def moveFolder(self, old_path, new_path): def moveFolder(self, old_path, new_path):
self.moveObject(old_path, new_path) self.moveObject(old_path, new_path)

View File

@ -41,6 +41,12 @@ class synologyNotifier:
if sickbeard.SYNOLOGYNOTIFIER_NOTIFY_ONSUBTITLEDOWNLOAD: if sickbeard.SYNOLOGYNOTIFIER_NOTIFY_ONSUBTITLEDOWNLOAD:
self._send_synologyNotifier(ep_name + ": " + lang, common.notifyStrings[common.NOTIFY_SUBTITLE_DOWNLOAD]) self._send_synologyNotifier(ep_name + ": " + lang, common.notifyStrings[common.NOTIFY_SUBTITLE_DOWNLOAD])
def notify_sickrage_update(self, new_version = "??"):
if sickbeard.USE_SYNOLOGYNOTIFIER:
update_text=common.notifyStrings[common.NOTIFY_SICKRAGE_UPDATE_TEXT]
title=common.notifyStrings[common.NOTIFY_SICKRAGE_UPDATE]
self._send_synologyNotifier(update_text + new_version, title)
def _send_synologyNotifier(self, message, title): def _send_synologyNotifier(self, message, title):
synodsmnotify_cmd = ["/usr/syno/bin/synodsmnotify", "@administrators", title, message] synodsmnotify_cmd = ["/usr/syno/bin/synodsmnotify", "@administrators", title, message]
logger.log(u"Executing command " + str(synodsmnotify_cmd)) logger.log(u"Executing command " + str(synodsmnotify_cmd))

View File

@ -35,6 +35,9 @@ class TraktNotifier:
def notify_subtitle_download(self, ep_name, lang): def notify_subtitle_download(self, ep_name, lang):
pass pass
def notify_sickrage_update(self, new_version):
pass
def update_library(self, ep_obj): def update_library(self, ep_obj):
""" """
Sends a request to trakt indicating that the given episode is part of our library. Sends a request to trakt indicating that the given episode is part of our library.

View File

@ -52,6 +52,12 @@ class TwitterNotifier:
if sickbeard.TWITTER_NOTIFY_ONSUBTITLEDOWNLOAD: if sickbeard.TWITTER_NOTIFY_ONSUBTITLEDOWNLOAD:
self._notifyTwitter(common.notifyStrings[common.NOTIFY_SUBTITLE_DOWNLOAD] + ' ' + ep_name + ": " + lang) self._notifyTwitter(common.notifyStrings[common.NOTIFY_SUBTITLE_DOWNLOAD] + ' ' + ep_name + ": " + lang)
def notify_sickrage_update(self, new_version = "??"):
if sickbeard.USE_TWITTER:
update_text=common.notifyStrings[common.NOTIFY_SICKRAGE_UPDATE_TEXT]
title=common.notifyStrings[common.NOTIFY_SICKRAGE_UPDATE]
self._notifyTwitter(title + " - " + update_text + new_version)
def test_notify(self): def test_notify(self):
return self._notifyTwitter("This is a test notification from SickRage", force=True) return self._notifyTwitter("This is a test notification from SickRage", force=True)

View File

@ -513,6 +513,12 @@ class XBMCNotifier:
if sickbeard.XBMC_NOTIFY_ONSUBTITLEDOWNLOAD: if sickbeard.XBMC_NOTIFY_ONSUBTITLEDOWNLOAD:
self._notify_xbmc(ep_name + ": " + lang, common.notifyStrings[common.NOTIFY_SUBTITLE_DOWNLOAD]) self._notify_xbmc(ep_name + ": " + lang, common.notifyStrings[common.NOTIFY_SUBTITLE_DOWNLOAD])
def notify_sickrage_update(self, new_version = "??"):
if sickbeard.USE_XBMC:
update_text=common.notifyStrings[common.NOTIFY_SICKRAGE_UPDATE_TEXT]
title=common.notifyStrings[common.NOTIFY_SICKRAGE_UPDATE]
self._notify_xbmc(update_text + new_version, title)
def test_notify(self, host, username, password): def test_notify(self, host, username, password):
return self._notify_xbmc("Testing XBMC notifications from SickRage", "Test Notification", host, username, return self._notify_xbmc("Testing XBMC notifications from SickRage", "Test Notification", host, username,
password, force=True) password, force=True)

View File

@ -49,9 +49,6 @@ class BTNProvider(generic.TorrentProvider):
self.url = "http://api.btnapps.net" self.url = "http://api.btnapps.net"
def __del__(self):
pass
def isEnabled(self): def isEnabled(self):
return self.enabled return self.enabled
@ -318,9 +315,6 @@ class BTNCache(tvcache.TVCache):
# At least 15 minutes between queries # At least 15 minutes between queries
self.minTime = 15 self.minTime = 15
def __del__(self):
pass
def updateCache(self): def updateCache(self):
# delete anything older then 7 days # delete anything older then 7 days
@ -349,8 +343,6 @@ class BTNCache(tvcache.TVCache):
if ci is not None: if ci is not None:
cl.append(ci) cl.append(ci)
time.sleep(.2)
if cl: if cl:
myDB = self._getDB() myDB = self._getDB()
myDB.mass_action(cl) myDB.mass_action(cl)

View File

@ -47,9 +47,6 @@ class EZRSSProvider(generic.TorrentProvider):
self.url = 'https://www.ezrss.it/' self.url = 'https://www.ezrss.it/'
def __del__(self):
pass
def isEnabled(self): def isEnabled(self):
return self.enabled return self.enabled
@ -181,9 +178,6 @@ class EZRSSCache(tvcache.TVCache):
# only poll EZRSS every 15 minutes max # only poll EZRSS every 15 minutes max
self.minTime = 15 self.minTime = 15
def __del__(self):
pass
def _getRSSData(self): def _getRSSData(self):
rss_url = self.provider.url + 'feed/' rss_url = self.provider.url + 'feed/'

View File

@ -45,9 +45,6 @@ class Fanzub(generic.NZBProvider):
self.url = 'http://fanzub.com/' self.url = 'http://fanzub.com/'
def __del__(self):
pass
def isEnabled(self): def isEnabled(self):
return self.enabled return self.enabled
@ -134,9 +131,6 @@ class FanzubCache(tvcache.TVCache):
# we get 100 post each call ! # we get 100 post each call !
self.minTime = 20 self.minTime = 20
def __del__(self):
pass
def _getRSSData(self): def _getRSSData(self):
params = {"cat": "anime".encode('utf-8'), params = {"cat": "anime".encode('utf-8'),

View File

@ -68,9 +68,6 @@ class GenericProvider:
self.session.headers.update({ 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'}) '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 __del__(self):
pass
def getID(self): def getID(self):
return GenericProvider.makeID(self.name) return GenericProvider.makeID(self.name)
@ -409,14 +406,8 @@ class NZBProvider(GenericProvider):
self.providerType = GenericProvider.NZB self.providerType = GenericProvider.NZB
def __del__(self):
pass
class TorrentProvider(GenericProvider): class TorrentProvider(GenericProvider):
def __init__(self, name): def __init__(self, name):
GenericProvider.__init__(self, name) GenericProvider.__init__(self, name)
self.providerType = GenericProvider.TORRENT self.providerType = GenericProvider.TORRENT
def __del__(self):
pass

View File

@ -55,9 +55,6 @@ class HDBitsProvider(generic.TorrentProvider):
self.rss_url = 'http://hdbits.org/api/torrents' self.rss_url = 'http://hdbits.org/api/torrents'
self.download_url = 'http://hdbits.org/download.php?' self.download_url = 'http://hdbits.org/download.php?'
def __del__(self):
pass
def isEnabled(self): def isEnabled(self):
return self.enabled return self.enabled
@ -217,9 +214,6 @@ class HDBitsCache(tvcache.TVCache):
# only poll HDBits every 15 minutes max # only poll HDBits every 15 minutes max
self.minTime = 15 self.minTime = 15
def __del__(self):
pass
def updateCache(self): def updateCache(self):
# delete anything older then 7 days # delete anything older then 7 days
@ -260,7 +254,7 @@ class HDBitsCache(tvcache.TVCache):
if ci is not None: if ci is not None:
ql.append(ci) ql.append(ci)
time.sleep(.2)
if ql: if ql:
myDB = self._getDB() myDB = self._getDB()

View File

@ -73,9 +73,6 @@ class HDTorrentsProvider(generic.TorrentProvider):
self.cookies = None self.cookies = None
def __del__(self):
pass
def isEnabled(self): def isEnabled(self):
return self.enabled return self.enabled
@ -354,9 +351,6 @@ class HDTorrentsCache(tvcache.TVCache):
# only poll HDTorrents every 10 minutes max # only poll HDTorrents every 10 minutes max
self.minTime = 20 self.minTime = 20
def __del__(self):
pass
def updateCache(self): def updateCache(self):
# delete anything older then 7 days # delete anything older then 7 days
@ -382,7 +376,7 @@ class HDTorrentsCache(tvcache.TVCache):
if ci is not None: if ci is not None:
cl.append(ci) cl.append(ci)
time.sleep(.2)
if cl: if cl:
myDB = self._getDB() myDB = self._getDB()

View File

@ -65,9 +65,6 @@ class IPTorrentsProvider(generic.TorrentProvider):
self.categorie = 'l73=1&l78=1&l66=1&l65=1&l79=1&l5=1&l4=1' self.categorie = 'l73=1&l78=1&l66=1&l65=1&l79=1&l5=1&l4=1'
def __del__(self):
pass
def isEnabled(self): def isEnabled(self):
return self.enabled return self.enabled
@ -295,9 +292,6 @@ class IPTorrentsCache(tvcache.TVCache):
# Only poll IPTorrents every 10 minutes max # Only poll IPTorrents every 10 minutes max
self.minTime = 10 self.minTime = 10
def __del__(self):
pass
def updateCache(self): def updateCache(self):
# delete anything older then 7 days # delete anything older then 7 days
@ -323,7 +317,7 @@ class IPTorrentsCache(tvcache.TVCache):
if ci is not None: if ci is not None:
cl.append(ci) cl.append(ci)
time.sleep(.2)
if cl: if cl:
myDB = self._getDB() myDB = self._getDB()

View File

@ -68,9 +68,6 @@ class KATProvider(generic.TorrentProvider):
self.searchurl = self.url + 'usearch/%s/?field=seeders&sorder=desc' #order by seed self.searchurl = self.url + 'usearch/%s/?field=seeders&sorder=desc' #order by seed
def __del__(self):
pass
def isEnabled(self): def isEnabled(self):
return self.enabled return self.enabled
@ -433,9 +430,6 @@ class KATCache(tvcache.TVCache):
# only poll ThePirateBay every 10 minutes max # only poll ThePirateBay every 10 minutes max
self.minTime = 20 self.minTime = 20
def __del__(self):
pass
def updateCache(self): def updateCache(self):
# delete anything older then 7 days # delete anything older then 7 days
@ -460,7 +454,7 @@ class KATCache(tvcache.TVCache):
if ci is not None: if ci is not None:
cl.append(ci) cl.append(ci)
time.sleep(.2)
if cl: if cl:
myDB = self._getDB() myDB = self._getDB()

View File

@ -40,9 +40,6 @@ class NewzbinDownloader(urllib.FancyURLopener):
def __init__(self): def __init__(self):
urllib.FancyURLopener.__init__(self) urllib.FancyURLopener.__init__(self)
def __del__(self):
pass
def http_error_default(self, url, fp, errcode, errmsg, headers): def http_error_default(self, url, fp, errcode, errmsg, headers):
# if newzbin is throttling us, wait seconds and try again # if newzbin is throttling us, wait seconds and try again
@ -76,9 +73,6 @@ class NewzbinProvider(generic.NZBProvider):
self.NEWZBIN_DATE_FORMAT = '%a, %d %b %Y %H:%M:%S %Z' self.NEWZBIN_DATE_FORMAT = '%a, %d %b %Y %H:%M:%S %Z'
def __del__(self):
pass
def isEnabled(self): def isEnabled(self):
return sickbeard.NEWZBIN return sickbeard.NEWZBIN
@ -340,9 +334,6 @@ class NewzbinCache(tvcache.TVCache):
# only poll Newzbin every 10 mins max # only poll Newzbin every 10 mins max
self.minTime = 1 self.minTime = 1
def __del__(self):
pass
def _getRSSData(self): def _getRSSData(self):
return self.provider._getRSSData() return self.provider._getRSSData()

View File

@ -69,9 +69,6 @@ class NewznabProvider(generic.NZBProvider):
self.default = False self.default = False
def __del__(self):
pass
def configStr(self): def configStr(self):
return self.name + '|' + self.url + '|' + self.key + '|' + self.catIDs + '|' + str(int(self.enabled)) + '|' + self.search_mode + '|' + str(int(self.search_fallback)) return self.name + '|' + self.url + '|' + self.key + '|' + self.catIDs + '|' + str(int(self.enabled)) + '|' + self.search_mode + '|' + str(int(self.search_fallback))
@ -295,9 +292,6 @@ class NewznabCache(tvcache.TVCache):
# only poll newznab providers every 15 minutes max # only poll newznab providers every 15 minutes max
self.minTime = 15 self.minTime = 15
def __del__(self):
pass
def _getRSSData(self): def _getRSSData(self):
params = {"t": "tvsearch", params = {"t": "tvsearch",
@ -347,7 +341,7 @@ class NewznabCache(tvcache.TVCache):
if ci is not None: if ci is not None:
ql.append(ci) ql.append(ci)
time.sleep(.2)
if ql: if ql:
myDB = self._getDB() myDB = self._getDB()

View File

@ -71,9 +71,6 @@ class NextGenProvider(generic.TorrentProvider):
self.login_opener = None self.login_opener = None
def __del__(self):
pass
def isEnabled(self): def isEnabled(self):
return self.enabled return self.enabled
@ -344,9 +341,6 @@ class NextGenCache(tvcache.TVCache):
# Only poll NextGen every 10 minutes max # Only poll NextGen every 10 minutes max
self.minTime = 10 self.minTime = 10
def __del__(self):
pass
def updateCache(self): def updateCache(self):
# delete anything older then 7 days # delete anything older then 7 days
@ -372,7 +366,7 @@ class NextGenCache(tvcache.TVCache):
if ci is not None: if ci is not None:
cl.append(ci) cl.append(ci)
time.sleep(.2)
if cl: if cl:
myDB = self._getDB() myDB = self._getDB()

View File

@ -45,9 +45,6 @@ class NyaaProvider(generic.TorrentProvider):
self.url = 'http://www.nyaa.se/' self.url = 'http://www.nyaa.se/'
def __del__(self):
pass
def isEnabled(self): def isEnabled(self):
return self.enabled return self.enabled
@ -130,9 +127,6 @@ class NyaaCache(tvcache.TVCache):
# only poll NyaaTorrents every 15 minutes max # only poll NyaaTorrents every 15 minutes max
self.minTime = 15 self.minTime = 15
def __del__(self):
pass
def _getRSSData(self): def _getRSSData(self):
params = { params = {
"page": 'rss', # Use RSS page "page": 'rss', # Use RSS page

View File

@ -49,9 +49,6 @@ class OmgwtfnzbsProvider(generic.NZBProvider):
self.url = 'https://omgwtfnzbs.org/' self.url = 'https://omgwtfnzbs.org/'
self.supportsBacklog = True self.supportsBacklog = True
def __del__(self):
pass
def isEnabled(self): def isEnabled(self):
return self.enabled return self.enabled
@ -160,9 +157,6 @@ class OmgwtfnzbsCache(tvcache.TVCache):
tvcache.TVCache.__init__(self, provider) tvcache.TVCache.__init__(self, provider)
self.minTime = 20 self.minTime = 20
def __del__(self):
pass
def _getRSSData(self): def _getRSSData(self):
params = {'user': provider.username, params = {'user': provider.username,
'api': provider.api_key, 'api': provider.api_key,

View File

@ -67,9 +67,6 @@ class PublicHDProvider(generic.TorrentProvider):
self.categories = {'Season': ['23'], 'Episode': ['7', '14', '24'], 'RSS': ['7', '14', '23', '24']} self.categories = {'Season': ['23'], 'Episode': ['7', '14', '24'], 'RSS': ['7', '14', '23', '24']}
def __del__(self):
pass
def isEnabled(self): def isEnabled(self):
return self.enabled return self.enabled
@ -317,9 +314,6 @@ class PublicHDCache(tvcache.TVCache):
# only poll ThePirateBay every 10 minutes max # only poll ThePirateBay every 10 minutes max
self.minTime = 20 self.minTime = 20
def __del__(self):
pass
def updateCache(self): def updateCache(self):
# delete anything older then 7 days # delete anything older then 7 days
@ -345,7 +339,7 @@ class PublicHDCache(tvcache.TVCache):
if ci is not None: if ci is not None:
ql.append(ci) ql.append(ci)
time.sleep(.2)
if ql: if ql:
myDB = self._getDB() myDB = self._getDB()

View File

@ -52,9 +52,6 @@ class TorrentRssProvider(generic.TorrentProvider):
else: else:
self.cookies = '' self.cookies = ''
def __del__(self):
pass
def configStr(self): def configStr(self):
return self.name + '|' + self.url + '|' + self.cookies + '|' + str(int(self.enabled)) + '|' + self.search_mode + '|' + str(int(self.search_fallback)) + '|' + str(int(self.backlog_only)) return self.name + '|' + self.url + '|' + self.cookies + '|' + str(int(self.enabled)) + '|' + self.search_mode + '|' + str(int(self.search_fallback)) + '|' + str(int(self.backlog_only))
@ -173,9 +170,6 @@ class TorrentRssCache(tvcache.TVCache):
tvcache.TVCache.__init__(self, provider) tvcache.TVCache.__init__(self, provider)
self.minTime = 15 self.minTime = 15
def __del__(self):
pass
def _getRSSData(self): def _getRSSData(self):
logger.log(u"TorrentRssCache cache update URL: " + self.provider.url, logger.DEBUG) logger.log(u"TorrentRssCache cache update URL: " + self.provider.url, logger.DEBUG)
if self.provider.cookies: if self.provider.cookies:

View File

@ -73,9 +73,6 @@ class SCCProvider(generic.TorrentProvider):
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'} 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 __del__(self):
pass
def isEnabled(self): def isEnabled(self):
return self.enabled return self.enabled
@ -339,9 +336,6 @@ class SCCCache(tvcache.TVCache):
# only poll SCC every 10 minutes max # only poll SCC every 10 minutes max
self.minTime = 20 self.minTime = 20
def __del__(self):
pass
def updateCache(self): def updateCache(self):
# delete anything older then 7 days # delete anything older then 7 days
@ -367,7 +361,7 @@ class SCCCache(tvcache.TVCache):
if ci is not None: if ci is not None:
cl.append(ci) cl.append(ci)
time.sleep(.2)
if cl: if cl:
myDB = self._getDB() myDB = self._getDB()

View File

@ -66,9 +66,6 @@ class SpeedCDProvider(generic.TorrentProvider):
self.categories = {'Season': {'c14': 1}, 'Episode': {'c2': 1, 'c49': 1}, 'RSS': {'c14': 1, 'c2': 1, 'c49': 1}} self.categories = {'Season': {'c14': 1}, 'Episode': {'c2': 1, 'c49': 1}, 'RSS': {'c14': 1, 'c2': 1, 'c49': 1}}
def __del__(self):
pass
def isEnabled(self): def isEnabled(self):
return self.enabled return self.enabled
@ -279,9 +276,6 @@ class SpeedCDCache(tvcache.TVCache):
# only poll Speedcd every 20 minutes max # only poll Speedcd every 20 minutes max
self.minTime = 20 self.minTime = 20
def __del__(self):
pass
def updateCache(self): def updateCache(self):
# delete anything older then 7 days # delete anything older then 7 days
@ -307,7 +301,7 @@ class SpeedCDCache(tvcache.TVCache):
if ci is not None: if ci is not None:
ql.append(ci) ql.append(ci)
time.sleep(.2)
if ql: if ql:
myDB = self._getDB() myDB = self._getDB()

View File

@ -67,9 +67,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.re_title_url = '/torrent/(?P<id>\d+)/(?P<title>.*?)//1".+?(?P<url>magnet.*?)//1".+?(?P<seeders>\d+)</td>.+?(?P<leechers>\d+)</td>'
def __del__(self):
pass
def isEnabled(self): def isEnabled(self):
return self.enabled return self.enabled
@ -410,9 +407,6 @@ class ThePirateBayCache(tvcache.TVCache):
# only poll ThePirateBay every 10 minutes max # only poll ThePirateBay every 10 minutes max
self.minTime = 20 self.minTime = 20
def __del__(self):
pass
def updateCache(self): def updateCache(self):
# delete anything older then 7 days # delete anything older then 7 days
@ -438,7 +432,7 @@ class ThePirateBayCache(tvcache.TVCache):
if ci is not None: if ci is not None:
cl.append(ci) cl.append(ci)
time.sleep(.2)
if cl: if cl:
myDB = self._getDB() myDB = self._getDB()
@ -477,9 +471,6 @@ class ThePirateBayWebproxy:
'Hiload.org (NL)': 'http://hiload.org/', 'Hiload.org (NL)': 'http://hiload.org/',
} }
def __del__(self):
pass
def isEnabled(self): def isEnabled(self):
""" Return True if we Choose to call TPB via Proxy """ """ Return True if we Choose to call TPB via Proxy """
return self.enabled return self.enabled

View File

@ -72,9 +72,6 @@ class TorrentDayProvider(generic.TorrentProvider):
self.categories = {'Season': {'c14': 1}, 'Episode': {'c2': 1, 'c26': 1, 'c7': 1, 'c24': 1}, self.categories = {'Season': {'c14': 1}, 'Episode': {'c2': 1, 'c26': 1, 'c7': 1, 'c24': 1},
'RSS': {'c2': 1, 'c26': 1, 'c7': 1, 'c24': 1, 'c14': 1}} 'RSS': {'c2': 1, 'c26': 1, 'c7': 1, 'c24': 1, 'c14': 1}}
def __del__(self):
pass
def isEnabled(self): def isEnabled(self):
return self.enabled return self.enabled
@ -303,9 +300,6 @@ class TorrentDayCache(tvcache.TVCache):
# Only poll IPTorrents every 10 minutes max # Only poll IPTorrents every 10 minutes max
self.minTime = 10 self.minTime = 10
def __del__(self):
pass
def updateCache(self): def updateCache(self):
# delete anything older then 7 days # delete anything older then 7 days
@ -331,7 +325,7 @@ class TorrentDayCache(tvcache.TVCache):
if ci is not None: if ci is not None:
cl.append(ci) cl.append(ci)
time.sleep(.2)
if cl: if cl:
myDB = self._getDB() myDB = self._getDB()

View File

@ -67,9 +67,6 @@ class TorrentLeechProvider(generic.TorrentProvider):
self.categories = "2,26,27,32" self.categories = "2,26,27,32"
def __del__(self):
pass
def isEnabled(self): def isEnabled(self):
return self.enabled return self.enabled
@ -298,9 +295,6 @@ class TorrentLeechCache(tvcache.TVCache):
# only poll TorrentLeech every 20 minutes max # only poll TorrentLeech every 20 minutes max
self.minTime = 20 self.minTime = 20
def __del__(self):
pass
def updateCache(self): def updateCache(self):
# delete anything older then 7 days # delete anything older then 7 days
@ -326,7 +320,7 @@ class TorrentLeechCache(tvcache.TVCache):
if ci is not None: if ci is not None:
cl.append(ci) cl.append(ci)
time.sleep(.2)
if cl: if cl:
myDB = self._getDB() myDB = self._getDB()

View File

@ -47,9 +47,6 @@ class TvTorrentsProvider(generic.TorrentProvider):
self.url = 'http://www.tvtorrents.com/' self.url = 'http://www.tvtorrents.com/'
def __del__(self):
pass
def isEnabled(self): def isEnabled(self):
return self.enabled return self.enabled
@ -89,9 +86,6 @@ class TvTorrentsCache(tvcache.TVCache):
# only poll TvTorrents every 15 minutes max # only poll TvTorrents every 15 minutes max
self.minTime = 15 self.minTime = 15
def __del__(self):
pass
def _getRSSData(self): def _getRSSData(self):
# These will be ignored on the serverside. # These will be ignored on the serverside.
ignore_regex = "all.month|month.of|season[\s\d]*complete" ignore_regex = "all.month|month.of|season[\s\d]*complete"

View File

@ -32,9 +32,6 @@ class WombleProvider(generic.NZBProvider):
self.cache = WombleCache(self) self.cache = WombleCache(self)
self.url = 'http://newshost.co.za/' self.url = 'http://newshost.co.za/'
def __del__(self):
pass
def isEnabled(self): def isEnabled(self):
return self.enabled return self.enabled
@ -45,9 +42,6 @@ class WombleCache(tvcache.TVCache):
# only poll Womble's Index every 15 minutes max # only poll Womble's Index every 15 minutes max
self.minTime = 15 self.minTime = 15
def __del__(self):
pass
def updateCache(self): def updateCache(self):
# delete anything older then 7 days # delete anything older then 7 days
@ -74,7 +68,7 @@ class WombleCache(tvcache.TVCache):
if ci is not None: if ci is not None:
cl.append(ci) cl.append(ci)
time.sleep(.2)
if cl: if cl:
myDB = self._getDB() myDB = self._getDB()

View File

@ -27,7 +27,8 @@ from sickbeard import name_cache
from sickbeard import logger from sickbeard import logger
from sickbeard import db from sickbeard import db
scene_lock = threading.Lock() exceptionsCache = None
exceptionsSeasonCache = None
def shouldRefresh(list): def shouldRefresh(list):
MAX_REFRESH_AGE_SECS = 86400 # 1 day MAX_REFRESH_AGE_SECS = 86400 # 1 day
@ -51,14 +52,21 @@ def get_scene_exceptions(indexer_id, season=-1):
""" """
Given a indexer_id, return a list of all the scene exceptions. Given a indexer_id, return a list of all the scene exceptions.
""" """
global exceptionsCache
exceptionsList = [] exceptionsList = []
myDB = db.DBConnection('cache.db') if indexer_id not in exceptionsCache or season not in exceptionsCache[indexer_id]:
exceptions = myDB.select("SELECT show_name FROM scene_exceptions WHERE indexer_id = ? and season = ?", myDB = db.DBConnection('cache.db')
[indexer_id, season]) exceptions = myDB.select("SELECT show_name FROM scene_exceptions WHERE indexer_id = ? and season = ?",
if exceptions: [indexer_id, season])
exceptionsList = list(set([cur_exception["show_name"] for cur_exception in exceptions])) if exceptions:
exceptionsList = list(set([cur_exception["show_name"] for cur_exception in exceptions]))
if not indexer_id in exceptionsCache:
exceptionsCache[indexer_id] = {}
exceptionsCache[indexer_id][season] = exceptionsList
else:
exceptionsList = exceptionsCache[indexer_id][season]
if season == 1: # if we where looking for season 1 we can add generic names if season == 1: # if we where looking for season 1 we can add generic names
exceptionsList += get_scene_exceptions(indexer_id, season=-1) exceptionsList += get_scene_exceptions(indexer_id, season=-1)
@ -84,14 +92,24 @@ def get_scene_seasons(indexer_id):
""" """
return a list of season numbers that have scene exceptions return a list of season numbers that have scene exceptions
""" """
global exceptionsSeasonCache
exceptionsSeasonList = []
myDB = db.DBConnection('cache.db') if indexer_id not in exceptionsSeasonCache:
sqlResults = myDB.select("SELECT DISTINCT(season) as season FROM scene_exceptions WHERE indexer_id = ?", myDB = db.DBConnection('cache.db')
[indexer_id]) sqlResults = myDB.select("SELECT DISTINCT(season) as season FROM scene_exceptions WHERE indexer_id = ?",
[indexer_id])
if sqlResults:
exceptionsSeasonList = list(set([int(x["season"]) for x in sqlResults]))
if sqlResults: if not indexer_id in exceptionsSeasonCache:
return [int(x["season"]) for x in sqlResults] exceptionsSeasonCache[indexer_id] = {}
exceptionsSeasonCache[indexer_id] = exceptionsSeasonList
else:
exceptionsSeasonList = exceptionsSeasonCache[indexer_id]
return exceptionsSeasonList
def get_scene_exception_by_name(show_name): def get_scene_exception_by_name(show_name):
return get_scene_exception_by_name_multiple(show_name)[0] return get_scene_exception_by_name_multiple(show_name)[0]
@ -136,7 +154,10 @@ def retrieve_exceptions():
Looks up the exceptions on github, parses them into a dict, and inserts them into the Looks up the exceptions on github, parses them into a dict, and inserts them into the
scene_exceptions table in cache.db. Also clears the scene name cache. scene_exceptions table in cache.db. Also clears the scene name cache.
""" """
global exceptionsCache, exceptionsSeasonCache
exceptionsCache = {}
exceptionsSeasonCache = {}
exception_dict = {} exception_dict = {}
# exceptions are stored on github pages # exceptions are stored on github pages
@ -209,7 +230,6 @@ def retrieve_exceptions():
# since this could invalidate the results of the cache we clear it out after updating # since this could invalidate the results of the cache we clear it out after updating
if changed_exceptions: if changed_exceptions:
logger.log(u"Updated scene exceptions") logger.log(u"Updated scene exceptions")
name_cache.clearCache()
else: else:
logger.log(u"No scene exceptions update needed") logger.log(u"No scene exceptions update needed")
@ -230,8 +250,6 @@ def update_scene_exceptions(indexer_id, scene_exceptions):
myDB.action("INSERT INTO scene_exceptions (indexer_id, show_name, season, custom) VALUES (?,?,?,?)", myDB.action("INSERT INTO scene_exceptions (indexer_id, show_name, season, custom) VALUES (?,?,?,?)",
[indexer_id, cur_exception, cur_season, 1]) [indexer_id, cur_exception, cur_season, 1])
name_cache.clearCache()
def _retrieve_anidb_mainnames(): def _retrieve_anidb_mainnames():
anidb_mainNames = {} anidb_mainNames = {}

View File

@ -279,9 +279,6 @@ class QueueItemAdd(ShowQueueItem):
return return
try: try:
# clear the name cache
name_cache.clearCache()
newShow = TVShow(self.indexer, self.indexer_id, self.lang) newShow = TVShow(self.indexer, self.indexer_id, self.lang)
newShow.loadFromIndexer() newShow.loadFromIndexer()
@ -361,6 +358,9 @@ class QueueItemAdd(ShowQueueItem):
# before we parse local files lets update exceptions # before we parse local files lets update exceptions
sickbeard.scene_exceptions.retrieve_exceptions() sickbeard.scene_exceptions.retrieve_exceptions()
# update internal name cache
name_cache.buildNameCache()
try: try:
self.show.loadEpisodesFromDir() self.show.loadEpisodesFromDir()
except Exception, e: except Exception, e:

View File

@ -128,8 +128,6 @@ class TVCache():
if ci is not None: if ci is not None:
cl.append(ci) cl.append(ci)
time.sleep(.2)
if cl: if cl:
myDB = self._getDB() myDB = self._getDB()
myDB.mass_action(cl) myDB.mass_action(cl)

View File

@ -30,7 +30,7 @@ import gh_api as github
import threading import threading
import sickbeard import sickbeard
from sickbeard import helpers from sickbeard import helpers, notifiers
from sickbeard import version, ui from sickbeard import version, ui
from sickbeard import logger from sickbeard import logger
from sickbeard.exceptions import ex from sickbeard.exceptions import ex
@ -261,6 +261,9 @@ class WindowsUpdateManager(UpdateManager):
logger.log(u"Copying new update.exe file from " + old_update_path + " to " + new_update_path) logger.log(u"Copying new update.exe file from " + old_update_path + " to " + new_update_path)
shutil.move(old_update_path, new_update_path) shutil.move(old_update_path, new_update_path)
# Notify update successful
notifiers.notify_sickrage_update(sickbeard.NEWEST_VERSION_STRING)
except Exception, e: except Exception, e:
logger.log(u"Error while trying to update: " + ex(e), logger.ERROR) logger.log(u"Error while trying to update: " + ex(e), logger.ERROR)
return False return False
@ -412,7 +415,6 @@ class GitUpdateManager(UpdateManager):
commit hash. If there is a newer version it sets _num_commits_behind. commit hash. If there is a newer version it sets _num_commits_behind.
""" """
self._newest_commit_hash = None
self._num_commits_behind = 0 self._num_commits_behind = 0
self._num_commits_ahead = 0 self._num_commits_ahead = 0
@ -510,6 +512,8 @@ class GitUpdateManager(UpdateManager):
output, err, exit_status = self._run_git(self._git_path, 'pull origin ' + self.branch) # @UnusedVariable output, err, exit_status = self._run_git(self._git_path, 'pull origin ' + self.branch) # @UnusedVariable
if exit_status == 0: if exit_status == 0:
# Notify update successful
notifiers.notify_sickrage_update(self._newest_commit_hash[:10])
return True return True
return False return False
@ -715,4 +719,7 @@ class SourceUpdateManager(UpdateManager):
logger.log(u"Traceback: " + traceback.format_exc(), logger.DEBUG) logger.log(u"Traceback: " + traceback.format_exc(), logger.DEBUG)
return False return False
# Notify update successful
notifiers.notify_sickrage_update(sickbeard.NEWEST_VERSION_STRING)
return True return True

View File

@ -1401,7 +1401,7 @@ class ConfigGeneral(MainHandler):
update_shows_on_start=None, update_frequency=None, launch_browser=None, web_username=None, update_shows_on_start=None, update_frequency=None, launch_browser=None, web_username=None,
use_api=None, api_key=None, indexer_default=None, timezone_display=None, cpu_preset=None, use_api=None, api_key=None, indexer_default=None, timezone_display=None, cpu_preset=None,
web_password=None, version_notify=None, enable_https=None, https_cert=None, https_key=None, web_password=None, version_notify=None, enable_https=None, https_cert=None, https_key=None,
handle_reverse_proxy=None, sort_article=None, auto_update=None, proxy_setting=None, 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, 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, fuzzy_dating=None, trim_zero=None, date_preset=None, date_preset_na=None, time_preset=None,
indexer_timeout=None): indexer_timeout=None):
@ -1412,6 +1412,7 @@ class ConfigGeneral(MainHandler):
sickbeard.LAUNCH_BROWSER = config.checkbox_to_value(launch_browser) sickbeard.LAUNCH_BROWSER = config.checkbox_to_value(launch_browser)
config.change_VERSION_NOTIFY(config.checkbox_to_value(version_notify)) config.change_VERSION_NOTIFY(config.checkbox_to_value(version_notify))
sickbeard.AUTO_UPDATE = config.checkbox_to_value(auto_update) sickbeard.AUTO_UPDATE = config.checkbox_to_value(auto_update)
sickbeard.NOTIFY_ON_UPDATE = config.checkbox_to_value(notify_on_update)
# sickbeard.LOG_DIR is set in config.change_LOG_DIR() # sickbeard.LOG_DIR is set in config.change_LOG_DIR()
sickbeard.UPDATE_SHOWS_ON_START = config.checkbox_to_value(update_shows_on_start) sickbeard.UPDATE_SHOWS_ON_START = config.checkbox_to_value(update_shows_on_start)