1
0
mirror of https://github.com/moparisthebest/SickRage synced 2024-12-12 11:02:21 -05:00

Merge remote-tracking branch 'origin/dev'

This commit is contained in:
echel0n 2014-07-08 15:33:43 -07:00
commit 004e82e459
20 changed files with 216 additions and 242 deletions

View File

@ -21,6 +21,7 @@
from __future__ import with_statement from __future__ import with_statement
import time import time
import signal
import sys import sys
import shutil import shutil
import subprocess import subprocess
@ -52,15 +53,15 @@ if sys.hexversion >= 0x020600F0:
import locale import locale
import datetime import datetime
import threading import threading
import signal
import traceback import traceback
import getopt import getopt
import sickbeard import sickbeard
from sickbeard.event_queue import Events
from sickbeard import db from sickbeard import db
from sickbeard.tv import TVShow from sickbeard.tv import TVShow
from sickbeard import logger from sickbeard import logger, network_timezones, failed_history, name_cache
from sickbeard.webserveInit import SRWebServer from sickbeard.webserveInit import SRWebServer
from sickbeard.version import SICKBEARD_VERSION from sickbeard.version import SICKBEARD_VERSION
from sickbeard.databases.mainDB import MIN_DB_VERSION from sickbeard.databases.mainDB import MIN_DB_VERSION
@ -68,14 +69,16 @@ from sickbeard.databases.mainDB import MAX_DB_VERSION
from lib.configobj import ConfigObj from lib.configobj import ConfigObj
throwaway = datetime.datetime.strptime('20110101', '%Y%m%d')
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)
throwaway = datetime.datetime.strptime('20110101', '%Y%m%d')
class SickRage(object): class SickRage(object):
def __init__(self): def __init__(self):
sickbeard.events = Events(self.shutdown)
self.webserver = None self.webserver = None
self.runAsDaemon = False self.runAsDaemon = False
self.CREATEPID = False self.CREATEPID = False
@ -313,6 +316,16 @@ class SickRage(object):
# Fire up all our threads # Fire up all our threads
sickbeard.start() sickbeard.start()
# Build internal name cache
name_cache.buildNameCache()
# refresh network timezones
network_timezones.update_network_dict()
# sure, why not?
if sickbeard.USE_FAILED_DOWNLOADS:
failed_history.trimHistory()
# Start an update if we're supposed to # Start an update if we're supposed to
if self.forceUpdate or sickbeard.UPDATE_SHOWS_ON_START: if self.forceUpdate or sickbeard.UPDATE_SHOWS_ON_START:
sickbeard.showUpdateScheduler.action.run(force=True) # @UndefinedVariable sickbeard.showUpdateScheduler.action.run(force=True) # @UndefinedVariable
@ -320,7 +333,8 @@ class SickRage(object):
if sickbeard.LAUNCH_BROWSER and not (self.noLaunch or self.runAsDaemon): if sickbeard.LAUNCH_BROWSER and not (self.noLaunch or self.runAsDaemon):
sickbeard.launchBrowser(self.startPort) sickbeard.launchBrowser(self.startPort)
while(sickbeard.started): # main loop
while(True):
time.sleep(1) time.sleep(1)
def daemonize(self): def daemonize(self):
@ -421,56 +435,54 @@ class SickRage(object):
except: except:
return False return False
def shutdown(self, type):
if sickbeard.started:
# stop all tasks
sickbeard.halt()
# shutdown web server
if self.webserver:
self.webserver.shutDown()
self.webserver = None
# save all shows to DB
sickbeard.saveAll()
# if run as daemon delete the pidfile
if self.runAsDaemon and self.CREATEPID:
self.remove_pid_file(self.PIDFILE)
if type == sickbeard.events.SystemEvent.RESTART:
install_type = sickbeard.versionCheckScheduler.action.install_type
popen_list = []
if install_type in ('git', 'source'):
popen_list = [sys.executable, sickbeard.MY_FULLNAME]
elif install_type == 'win':
if hasattr(sys, 'frozen'):
# c:\dir\to\updater.exe 12345 c:\dir\to\sickbeard.exe
popen_list = [os.path.join(sickbeard.PROG_DIR, 'updater.exe'), str(sickbeard.PID), sys.executable]
else:
logger.log(u"Unknown SB launch method, please file a bug report about this", logger.ERROR)
popen_list = [sys.executable, os.path.join(sickbeard.PROG_DIR, 'updater.py'), str(sickbeard.PID),
sys.executable,
sickbeard.MY_FULLNAME]
if popen_list:
popen_list += sickbeard.MY_ARGS
if '--nolaunch' not in popen_list:
popen_list += ['--nolaunch']
logger.log(u"Restarting SickRage with " + str(popen_list))
logger.close()
subprocess.Popen(popen_list, cwd=os.getcwd())
# system exit
os._exit(0)
if __name__ == "__main__": if __name__ == "__main__":
if sys.hexversion >= 0x020600F0: if sys.hexversion >= 0x020600F0:
freeze_support() freeze_support()
sr = None # start sickrage
try: SickRage().start()
# init sickrage
sr = SickRage()
# start sickrage
sr.start()
# shutdown web server
sr.webserver.shutDown()
sr.webserver.join()
sr.webserver = None
# if run as daemon delete the pidfile
if sr.runAsDaemon and sr.CREATEPID:
sr.remove_pid_file(sr.PIDFILE)
if not sickbeard.shutdown:
install_type = sickbeard.versionCheckScheduler.action.install_type
popen_list = []
if install_type in ('git', 'source'):
popen_list = [sys.executable, sickbeard.MY_FULLNAME]
elif install_type == 'win':
if hasattr(sys, 'frozen'):
# c:\dir\to\updater.exe 12345 c:\dir\to\sickbeard.exe
popen_list = [os.path.join(sickbeard.PROG_DIR, 'updater.exe'), str(sickbeard.PID), sys.executable]
else:
logger.log(u"Unknown SB launch method, please file a bug report about this", logger.ERROR)
popen_list = [sys.executable, os.path.join(sickbeard.PROG_DIR, 'updater.py'), str(sickbeard.PID), sys.executable,
sickbeard.MY_FULLNAME]
if popen_list:
popen_list += sickbeard.MY_ARGS
if '--nolaunch' not in popen_list:
popen_list += ['--nolaunch']
logger.log(u"Restarting SickRage with " + str(popen_list))
logger.close()
subprocess.Popen(popen_list, cwd=os.getcwd())
# exit process
os._exit(0)
except:
if sr:
logger.log(traceback.format_exc(), logger.ERROR)
else:
print(traceback.format_exc())
sys.exit(1)

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 932 B

View File

@ -229,7 +229,7 @@ $myShowList.sort(lambda x, y: cmp(x.name, y.name))
#set $den = $curShowAll[0] #set $den = $curShowAll[0]
#end if #end if
#else #else
#set $dlStat = "0" #set $dlStat = "0 / 0"
#set $nom = 0 #set $nom = 0
#set $den = 1 #set $den = 1
#end if #end if

View File

@ -39,7 +39,7 @@
<input type="hidden" id="providedName" value="$provided_indexer_name" /> <input type="hidden" id="providedName" value="$provided_indexer_name" />
<input type="hidden" id="providedIndexer" value="$provided_indexer" /> <input type="hidden" id="providedIndexer" value="$provided_indexer" />
#else: #else:
<input type="text" id="nameToSearch" value="$default_show_name" style="margin-top: 1px;" /> <input type="text" id="nameToSearch" value="$default_show_name" style="height: 16px;margin-top: 2px;" />
<select name="indexerLang" id="indexerLangSelect" style="height: 26px;margin-top: 1px;"> <select name="indexerLang" id="indexerLangSelect" style="height: 26px;margin-top: 1px;">
<option value="en" selected="selected">en</option> <option value="en" selected="selected">en</option>
</select><b>*</b> </select><b>*</b>
@ -50,7 +50,7 @@
<option value="$indexer" #if $provided_indexer == $indexer then "selected=\"selected\"" else ""#>$indexers[$indexer]</option> <option value="$indexer" #if $provided_indexer == $indexer then "selected=\"selected\"" else ""#>$indexers[$indexer]</option>
#end for #end for
</select> </select>
<input class="btn" type="button" id="searchName" value="Search" style="height: 26px;position:relative;top:-1px;" /><br /><br /> <input class="btn" type="button" id="searchName" value="Search" style="height: 26px;margin-top: 1px;" /><br /><br />
<b>*</b> This will only affect the language of the retrieved metadata file contents and episode filenames.<br /> <b>*</b> This will only affect the language of the retrieved metadata file contents and episode filenames.<br />
This <b>DOES NOT</b> allow SickRage to download non-english TV episodes!<br /> This <b>DOES NOT</b> allow SickRage to download non-english TV episodes!<br />

View File

@ -41,7 +41,6 @@ from sickbeard import helpers, db, exceptions, show_queue, search_queue, schedul
from sickbeard import logger from sickbeard import logger
from sickbeard import naming from sickbeard import naming
from sickbeard import dailysearcher from sickbeard import dailysearcher
from sickbeard import maintenance
from sickbeard import scene_numbering, scene_exceptions, name_cache from sickbeard import scene_numbering, scene_exceptions, name_cache
from indexers.indexer_api import indexerApi from indexers.indexer_api import indexerApi
from indexers.indexer_exceptions import indexer_shownotfound, indexer_exception, indexer_error, indexer_episodenotfound, \ from indexers.indexer_exceptions import indexer_shownotfound, indexer_exception, indexer_error, indexer_episodenotfound, \
@ -50,7 +49,6 @@ from sickbeard.common import SD, SKIPPED, NAMING_REPEAT
from sickbeard.databases import mainDB, cache_db, failed_db from sickbeard.databases import mainDB, cache_db, failed_db
from lib.configobj import ConfigObj from lib.configobj import ConfigObj
from tornado.ioloop import IOLoop
import xml.etree.ElementTree as ElementTree import xml.etree.ElementTree as ElementTree
PID = None PID = None
@ -76,7 +74,9 @@ PIDFILE = ''
DAEMON = None DAEMON = None
NO_RESIZE = False NO_RESIZE = False
maintenanceScheduler = None # system events
events = None
dailySearchScheduler = None dailySearchScheduler = None
backlogSearchScheduler = None backlogSearchScheduler = None
showUpdateScheduler = None showUpdateScheduler = None
@ -105,7 +105,6 @@ CUR_COMMIT_HASH = None
INIT_LOCK = Lock() INIT_LOCK = Lock()
started = False started = False
shutdown = False
ACTUAL_LOG_DIR = None ACTUAL_LOG_DIR = None
LOG_DIR = None LOG_DIR = None
@ -479,7 +478,7 @@ def initialize(consoleLogging=True):
USE_FAILED_DOWNLOADS, DELETE_FAILED, ANON_REDIRECT, LOCALHOST_IP, TMDB_API_KEY, DEBUG, PROXY_SETTING, \ USE_FAILED_DOWNLOADS, DELETE_FAILED, ANON_REDIRECT, LOCALHOST_IP, TMDB_API_KEY, DEBUG, PROXY_SETTING, \
AUTOPOSTPROCESSER_FREQUENCY, DEFAULT_AUTOPOSTPROCESSER_FREQUENCY, MIN_AUTOPOSTPROCESSER_FREQUENCY, \ AUTOPOSTPROCESSER_FREQUENCY, DEFAULT_AUTOPOSTPROCESSER_FREQUENCY, MIN_AUTOPOSTPROCESSER_FREQUENCY, \
ANIME_DEFAULT, NAMING_ANIME, ANIMESUPPORT, USE_ANIDB, ANIDB_USERNAME, ANIDB_PASSWORD, ANIDB_USE_MYLIST, \ ANIME_DEFAULT, NAMING_ANIME, ANIMESUPPORT, USE_ANIDB, ANIDB_USERNAME, ANIDB_PASSWORD, ANIDB_USE_MYLIST, \
ANIME_SPLIT_HOME, maintenanceScheduler, SCENE_DEFAULT ANIME_SPLIT_HOME, SCENE_DEFAULT
if __INITIALIZED__: if __INITIALIZED__:
return False return False
@ -872,7 +871,7 @@ def initialize(consoleLogging=True):
USE_ANIDB = check_setting_str(CFG, 'ANIDB', 'use_anidb', '') USE_ANIDB = check_setting_str(CFG, 'ANIDB', 'use_anidb', '')
ANIDB_USERNAME = check_setting_str(CFG, 'ANIDB', 'anidb_username', '') ANIDB_USERNAME = check_setting_str(CFG, 'ANIDB', 'anidb_username', '')
ANIDB_PASSWORD = check_setting_str(CFG, 'ANIDB', 'anidb_password', '') ANIDB_PASSWORD = check_setting_str(CFG, 'ANIDB', 'anidb_password', '')
ANIDB_USE_MYLIST = check_setting_str(CFG, 'ANIDB', 'anidb_use_mylist', '') ANIDB_USE_MYLIST = bool(check_setting_int(CFG, 'ANIDB', 'anidb_use_mylist', 0))
ANIME_SPLIT_HOME = bool(check_setting_int(CFG, 'ANIME', 'anime_split_home', 0)) ANIME_SPLIT_HOME = bool(check_setting_int(CFG, 'ANIME', 'anime_split_home', 0))
METADATA_XBMC = check_setting_str(CFG, 'General', 'metadata_xbmc', '0|0|0|0|0|0|0|0|0|0') METADATA_XBMC = check_setting_str(CFG, 'General', 'metadata_xbmc', '0|0|0|0|0|0|0|0|0|0')
@ -957,10 +956,6 @@ def initialize(consoleLogging=True):
threadName="CHECKVERSION", threadName="CHECKVERSION",
silent=False) silent=False)
maintenanceScheduler = scheduler.Scheduler(maintenance.Maintenance(),
cycleTime=datetime.timedelta(hours=1),
threadName="MAINTENANCE")
showQueueScheduler = scheduler.Scheduler(show_queue.ShowQueue(), showQueueScheduler = scheduler.Scheduler(show_queue.ShowQueue(),
cycleTime=datetime.timedelta(seconds=3), cycleTime=datetime.timedelta(seconds=3),
threadName="SHOWQUEUE") threadName="SHOWQUEUE")
@ -1123,7 +1118,7 @@ def initialize(consoleLogging=True):
def start(): def start():
global __INITIALIZED__, maintenanceScheduler, backlogSearchScheduler, \ global __INITIALIZED__, backlogSearchScheduler, \
showUpdateScheduler, versionCheckScheduler, showQueueScheduler, \ showUpdateScheduler, versionCheckScheduler, showQueueScheduler, \
properFinderScheduler, autoPostProcesserScheduler, searchQueueScheduler, \ properFinderScheduler, autoPostProcesserScheduler, searchQueueScheduler, \
subtitlesFinderScheduler, USE_SUBTITLES,traktCheckerScheduler, \ subtitlesFinderScheduler, USE_SUBTITLES,traktCheckerScheduler, \
@ -1133,9 +1128,6 @@ def start():
if __INITIALIZED__: if __INITIALIZED__:
# start the maintenance scheduler
maintenanceScheduler.thread.start()
# start the daily search scheduler # start the daily search scheduler
dailySearchScheduler.thread.start() dailySearchScheduler.thread.start()
@ -1171,11 +1163,11 @@ def start():
def halt(): def halt():
global __INITIALIZED__, maintenanceScheduler, backlogSearchScheduler, \ global __INITIALIZED__, backlogSearchScheduler, \
showUpdateScheduler, versionCheckScheduler, showQueueScheduler, \ showUpdateScheduler, versionCheckScheduler, showQueueScheduler, \
properFinderScheduler, autoPostProcesserScheduler, searchQueueScheduler, \ properFinderScheduler, autoPostProcesserScheduler, searchQueueScheduler, \
subtitlesFinderScheduler, traktCheckerScheduler, \ subtitlesFinderScheduler, traktCheckerScheduler, \
dailySearchScheduler, started dailySearchScheduler, events, started
with INIT_LOCK: with INIT_LOCK:
@ -1183,12 +1175,10 @@ def halt():
logger.log(u"Aborting all threads") logger.log(u"Aborting all threads")
# abort all the threads events.alive = False
logger.log(u"Waiting for the EVENTS thread to exit")
maintenanceScheduler.abort = True
logger.log(u"Waiting for the MAINTENANCE scheduler thread to exit")
try: try:
maintenanceScheduler.thread.join(10) events.join(10)
except: except:
pass pass
@ -1277,7 +1267,7 @@ def halt():
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))
saveAndShutdown() events.put(events.SystemEvent.SHUTDOWN)
def saveAll(): def saveAll():
global showList global showList
@ -1291,32 +1281,6 @@ def saveAll():
logger.log(u"Saving config file to disk") logger.log(u"Saving config file to disk")
save_config() save_config()
def saveAndShutdown(restart=False):
global shutdown, started
# flag restart/shutdown
if not restart:
shutdown = True
# proceed with shutdown
started = False
def invoke_command(to_call, *args, **kwargs):
def delegate():
to_call(*args, **kwargs)
logger.log(u"Placed invoked command: " + repr(delegate) + " for " + repr(to_call) + " with " + repr(
args) + " and " + repr(kwargs), logger.DEBUG)
IOLoop.current().add_callback(delegate)
def invoke_restart(soft=True):
invoke_command(restart, soft=soft)
def invoke_shutdown():
invoke_command(saveAndShutdown, False)
def restart(soft=True): def restart(soft=True):
if soft: if soft:
halt() halt()
@ -1324,7 +1288,7 @@ def restart(soft=True):
logger.log(u"Re-initializing all data") logger.log(u"Re-initializing all data")
initialize() initialize()
else: else:
saveAndShutdown(True) events.put(events.SystemEvent.RESTART)
def save_config(): def save_config():

View File

@ -222,13 +222,9 @@ class Quality:
return Quality.RAWHDTV return Quality.RAWHDTV
elif checkName(["1080p", "hdtv", "x264"], all): elif checkName(["1080p", "hdtv", "x264"], all):
return Quality.FULLHDTV return Quality.FULLHDTV
elif checkName(["720p", "web.dl", "h.?264"], all) or checkName(["720p", "itunes", "h.?264"], all): elif checkName(["720p", "web.dl|webrip"], all) or checkName(["720p", "itunes", "h.?264"], all):
return Quality.HDWEBDL return Quality.HDWEBDL
elif checkName(["1080p", "web.dl", "h.?264"], all) or checkName(["1080p", "itunes", "h.?264"], all): elif checkName(["1080p", "web.dl|webrip"], all) or checkName(["1080p", "itunes", "h.?264"], all):
return Quality.FULLHDWEBDL
elif checkName(["720p", "webrip", "x264"], all):
return Quality.HDWEBDL
elif checkName(["1080p", "webrip", "x264"], all):
return Quality.FULLHDWEBDL return Quality.FULLHDWEBDL
elif checkName(["720p", "bluray|hddvd|b[r|d]rip", "x264"], all): elif checkName(["720p", "bluray|hddvd|b[r|d]rip", "x264"], all):
return Quality.HDBLURAY return Quality.HDBLURAY

View File

@ -44,7 +44,7 @@ class DailySearcher():
for curProviderCount, curProvider in enumerate(providers): for curProviderCount, curProvider in enumerate(providers):
try: try:
logger.log(u"Updating [" + curProvider.name + "} RSS cache ...") logger.log(u"Updating [" + curProvider.name + "] RSS cache ...")
curProvider.cache.updateCache() curProvider.cache.updateCache()
except exceptions.AuthException, e: except exceptions.AuthException, e:
logger.log(u"Authentication error: " + ex(e), logger.ERROR) logger.log(u"Authentication error: " + ex(e), logger.ERROR)

45
sickbeard/event_queue.py Normal file
View File

@ -0,0 +1,45 @@
from threading import Thread
from Queue import Queue, Empty
from tornado.ioloop import IOLoop
class Event:
def __init__(self, type):
self._type = type
@property
def type(self):
return self._type
class Events(Thread):
def __init__(self, callback):
super(Events, self).__init__()
self.queue = Queue()
self.daemon = True
self.alive = True
self.callback = callback
self.name = "EVENT-QUEUE"
# auto-start
self.start()
def put(self, type):
self.queue.put_nowait(type)
def run(self):
while(self.alive):
try:
# get event type
type = self.queue.get(True, 1)
# perform callback if we got a event type
self.callback(type)
# event completed
self.queue.task_done()
except Empty:
type = None
# System Events
class SystemEvent(Event):
RESTART = "RESTART"
SHUTDOWN = "SHUTDOWN"

View File

@ -1,53 +0,0 @@
# Author: Nic Wolfe <nic@wolfeden.ca>
# URL: http://code.google.com/p/sickbeard/
#
# 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 <http://www.gnu.org/licenses/>.
from __future__ import with_statement
import threading
import sickbeard
from sickbeard import scene_exceptions
from sickbeard import failed_history
from sickbeard import network_timezones
from sickbeard import name_cache
class Maintenance():
def __init__(self):
self.lock = threading.Lock()
self.amActive = False
def run(self, force=False):
self.amActive = True
# clear internal name cache
name_cache.clearCache()
# get and update scene exceptions lists
scene_exceptions.retrieve_exceptions()
# build internal name cache for searches and parsing
name_cache.buildNameCache()
# refresh network timezones
network_timezones.update_network_dict()
# sure, why not?
if sickbeard.USE_FAILED_DOWNLOADS:
failed_history.trimHistory()
self.amActive = False

View File

@ -96,7 +96,10 @@ def buildNameCache():
# clear internal name cache # clear internal name cache
clearCache() clearCache()
logger.log(u"Updating internal name cache", logger.MESSAGE) # update scene exception names
sickbeard.scene_exceptions.retrieve_exceptions()
logger.log(u"Building internal name cache", logger.MESSAGE)
cacheDB = db.DBConnection('cache.db') cacheDB = db.DBConnection('cache.db')
cache_results = cacheDB.select("SELECT * FROM scene_names") cache_results = cacheDB.select("SELECT * FROM scene_names")
@ -111,5 +114,4 @@ def buildNameCache():
for name in sickbeard.scene_exceptions.get_scene_exceptions(show.indexerid, season=curSeason): for name in sickbeard.scene_exceptions.get_scene_exceptions(show.indexerid, season=curSeason):
nameCache[sickbeard.helpers.full_sanitizeSceneName(name)] = show.indexerid 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) logger.log(u"Internal name cache set to: " + str(nameCache), logger.DEBUG)

View File

@ -16,6 +16,7 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with SickRage. If not, see <http://www.gnu.org/licenses/>. # along with SickRage. If not, see <http://www.gnu.org/licenses/>.
import time
import re import re
import datetime import datetime
import os.path import os.path
@ -123,8 +124,8 @@ class NameParser(object):
if not self.showObj and not self.naming_pattern: if not self.showObj and not self.naming_pattern:
# Regex pattern to return the Show / Series Name regardless of the file pattern tossed at it, matched 53 show name examples from regexes.py # Regex pattern to return the Show / Series Name regardless of the file pattern tossed at it, matched 53 show name examples from regexes.py
show_patterns = [ show_patterns = [
'''^(?P<show_name>.*?)\W+(?:(?:S\d[\dE._ -])|(?:\d\d?x)|(?:\d{4}\W\d\d\W\d\d)|(?:(?:part|pt)[\._ -]?(\d|[ivx]))|Season\W+\d+\W+|E\d+\W+|(?:\d{1,3}.+\d{1,}[a-zA-Z]{2}\W+[a-zA-Z]{3,}\W+\d{4}.+))''', '''^(?P<show_name>.*)\W+(?:(?:S\d[\dE._ -])|(?:\d\d?x)|(?:\d{4}\W\d\d\W\d\d)|(?:(?:part|pt)[\._ -]?(\d|[ivx]))|Season\W+\d+\W+|E\d+\W+|(?:\d{1,3}.+\d{1,}[a-zA-Z]{2}\W+[a-zA-Z]{3,}\W+\d{4}.+))''',
'''^((\[.*?\])|(\d+[\.-]))*[ _\.]*(?P<show_name>.*?)(([ ._-]+\d+)|([ ._-]+s\d{2})).*''' '''^((\[.*?\])|(\d+[\.-]))*[ _\.]*(?P<show_name>.*)(([ ._-]+\d+)|([ ._-]+s\d{2})).*'''
] ]
# find show object # find show object
@ -133,6 +134,8 @@ class NameParser(object):
if self.showObj: if self.showObj:
break break
else: else:
time.sleep(0.05)
raise InvalidShowException( raise InvalidShowException(
"Unable to parse " + name.encode(sickbeard.SYS_ENCODING, 'xmlcharrefreplace')) "Unable to parse " + name.encode(sickbeard.SYS_ENCODING, 'xmlcharrefreplace'))
@ -251,6 +254,8 @@ class NameParser(object):
result.score += 1 result.score += 1
matches.append(result) matches.append(result)
time.sleep(0.05)
if len(matches): if len(matches):
result = max(sorted(matches, reverse=True, key=lambda x: x.which_regex), key=lambda x: x.score) result = max(sorted(matches, reverse=True, key=lambda x: x.which_regex), key=lambda x: x.score)

View File

@ -41,6 +41,7 @@ class TorrentRssProvider(generic.TorrentProvider):
self.url = re.sub('\/$', '', url) self.url = re.sub('\/$', '', url)
self.url = url self.url = url
self.enabled = True self.enabled = True
self.ratio = None
self.supportsBacklog = False self.supportsBacklog = False
self.search_mode = search_mode self.search_mode = search_mode
@ -164,6 +165,8 @@ class TorrentRssProvider(generic.TorrentProvider):
logger.log(u"Saved custom_torrent html dump " + dumpName + " ", logger.MESSAGE) logger.log(u"Saved custom_torrent html dump " + dumpName + " ", logger.MESSAGE)
return True return True
def seedRatio(self):
return self.ratio
class TorrentRssCache(tvcache.TVCache): class TorrentRssCache(tvcache.TVCache):
def __init__(self, provider): def __init__(self, provider):
@ -186,4 +189,4 @@ class TorrentRssCache(tvcache.TVCache):
return None return None
logger.log(u"Attempting to add item to cache: " + title, logger.DEBUG) logger.log(u"Attempting to add item to cache: " + title, logger.DEBUG)
return self._addCacheEntry(title, url) return self._addCacheEntry(title, url)

View File

@ -43,9 +43,6 @@ class SearchQueue(generic_queue.GenericQueue):
generic_queue.GenericQueue.__init__(self) generic_queue.GenericQueue.__init__(self)
self.queue_name = "SEARCHQUEUE" self.queue_name = "SEARCHQUEUE"
def __del__(self):
pass
def is_in_queue(self, show, segment): def is_in_queue(self, show, segment):
for cur_item in self.queue: for cur_item in self.queue:
if isinstance(cur_item, BacklogQueueItem) and cur_item.show == show and cur_item.segment == segment: if isinstance(cur_item, BacklogQueueItem) and cur_item.show == show and cur_item.segment == segment:
@ -77,17 +74,20 @@ class SearchQueue(generic_queue.GenericQueue):
def add_item(self, item): def add_item(self, item):
if isinstance(item, DailySearchQueueItem) and not self.is_in_queue(item.show, item.segment): if isinstance(item, DailySearchQueueItem) and not self.is_in_queue(item.show, item.segment):
sickbeard.name_cache.buildNameCache()
generic_queue.GenericQueue.add_item(self, item) generic_queue.GenericQueue.add_item(self, item)
elif isinstance(item, BacklogQueueItem) and not self.is_in_queue(item.show, item.segment): elif isinstance(item, BacklogQueueItem) and not self.is_in_queue(item.show, item.segment):
sickbeard.name_cache.buildNameCache()
generic_queue.GenericQueue.add_item(self, item) generic_queue.GenericQueue.add_item(self, item)
elif isinstance(item, ManualSearchQueueItem) and not self.is_in_queue(item.show, item.segment): elif isinstance(item, ManualSearchQueueItem) and not self.is_in_queue(item.show, item.segment):
sickbeard.name_cache.buildNameCache()
generic_queue.GenericQueue.add_item(self, item) generic_queue.GenericQueue.add_item(self, item)
elif isinstance(item, FailedQueueItem) and not self.is_in_queue(item.show, item.segment): elif isinstance(item, FailedQueueItem) and not self.is_in_queue(item.show, item.segment):
sickbeard.name_cache.buildNameCache()
generic_queue.GenericQueue.add_item(self, item) generic_queue.GenericQueue.add_item(self, item)
else: else:
logger.log(u"Not adding item, it's already in the queue", logger.DEBUG) logger.log(u"Not adding item, it's already in the queue", logger.DEBUG)
class DailySearchQueueItem(generic_queue.QueueItem): class DailySearchQueueItem(generic_queue.QueueItem):
def __init__(self, show, segment): def __init__(self, show, segment):
generic_queue.QueueItem.__init__(self, 'Daily Search', DAILY_SEARCH) generic_queue.QueueItem.__init__(self, 'Daily Search', DAILY_SEARCH)

View File

@ -37,6 +37,13 @@ class ShowUpdater():
update_datetime = datetime.datetime.now() update_datetime = datetime.datetime.now()
update_date = update_datetime.date() update_date = update_datetime.date()
# refresh network timezones
network_timezones.update_network_dict()
# sure, why not?
if sickbeard.USE_FAILED_DOWNLOADS:
failed_history.trimHistory()
logger.log(u"Doing full update on all shows") logger.log(u"Doing full update on all shows")
# clean out cache directory, remove everything > 12 hours old # clean out cache directory, remove everything > 12 hours old

View File

@ -66,7 +66,6 @@ class TVShow(object):
self._indexerid = int(indexerid) self._indexerid = int(indexerid)
self._indexer = int(indexer) self._indexer = int(indexer)
self._name = "" self._name = ""
self._location = ""
self._imdbid = "" self._imdbid = ""
self._network = "" self._network = ""
self._genre = "" self._genre = ""
@ -93,6 +92,7 @@ class TVShow(object):
self.dirty = True self.dirty = True
self._location = ""
self.lock = threading.Lock() self.lock = threading.Lock()
self.isDirGood = False self.isDirGood = False
self.episodes = {} self.episodes = {}
@ -103,9 +103,6 @@ class TVShow(object):
self.loadFromDB() self.loadFromDB()
def __del__(self):
pass
name = property(lambda self: self._name, dirty_setter("_name")) name = property(lambda self: self._name, dirty_setter("_name"))
indexerid = property(lambda self: self._indexerid, dirty_setter("_indexerid")) indexerid = property(lambda self: self._indexerid, dirty_setter("_indexerid"))
indexer = property(lambda self: self._indexer, dirty_setter("_indexer")) indexer = property(lambda self: self._indexer, dirty_setter("_indexer"))
@ -172,7 +169,7 @@ class TVShow(object):
logger.log(u"Setter sets location to " + newLocation, logger.DEBUG) logger.log(u"Setter sets location to " + newLocation, logger.DEBUG)
# Don't validate dir if user wants to add shows without creating a dir # Don't validate dir if user wants to add shows without creating a dir
if sickbeard.ADD_SHOWS_WO_DIR or ek.ek(os.path.isdir, newLocation): if sickbeard.ADD_SHOWS_WO_DIR or ek.ek(os.path.isdir, newLocation):
self._location = newLocation dirty_setter("_location")(self, newLocation)
self._isDirGood = True self._isDirGood = True
else: else:
raise exceptions.NoNFOException("Invalid folder for the show!") raise exceptions.NoNFOException("Invalid folder for the show!")
@ -834,7 +831,7 @@ class TVShow(object):
self.flatten_folders = int(sqlResults[0]["flatten_folders"]) self.flatten_folders = int(sqlResults[0]["flatten_folders"])
self.paused = int(sqlResults[0]["paused"]) self.paused = int(sqlResults[0]["paused"])
self._location = sqlResults[0]["location"] self.location = sqlResults[0]["location"]
if not self.lang: if not self.lang:
self.lang = sqlResults[0]["lang"] self.lang = sqlResults[0]["lang"]

View File

@ -64,7 +64,7 @@ class CheckVersion():
if sickbeard.versionCheckScheduler.action.update(): if sickbeard.versionCheckScheduler.action.update():
logger.log(u"Update was successful!") logger.log(u"Update was successful!")
ui.notifications.message('Update was successful') ui.notifications.message('Update was successful')
threading.Timer(2, sickbeard.invoke_restart, [False]).start() sickbeard.events.put(sickbeard.events.SystemEvent.RESTART)
def find_install_type(self): def find_install_type(self):
""" """

View File

@ -1524,7 +1524,7 @@ class CMD_SickBeardRestart(ApiCall):
def run(self): def run(self):
""" restart sickbeard """ """ restart sickbeard """
threading.Timer(2, sickbeard.invoke_restart, [False]).start() sickbeard.events.put(sickbeard.events.SystemEvent.RESTART)
return _responds(RESULT_SUCCESS, msg="SickRage is restarting...") return _responds(RESULT_SUCCESS, msg="SickRage is restarting...")
@ -1701,7 +1701,7 @@ class CMD_SickBeardShutdown(ApiCall):
def run(self): def run(self):
""" shutdown sickbeard """ """ shutdown sickbeard """
threading.Timer(2, sickbeard.invoke_shutdown).start() sickbeard.events.put(sickbeard.events.SystemEvent.SHUTDOWN)
return _responds(RESULT_SUCCESS, msg="SickRage is shutting down...") return _responds(RESULT_SUCCESS, msg="SickRage is shutting down...")

View File

@ -487,7 +487,8 @@ class MainHandler(RequestHandler):
class PageTemplate(Template): class PageTemplate(Template):
def __init__(self, headers, *args, **KWs): def __init__(self, headers, *args, **KWs):
KWs['file'] = os.path.join(sickbeard.PROG_DIR, "gui/" + sickbeard.GUI_NAME + "/interfaces/default/",KWs['file']) KWs['file'] = os.path.join(sickbeard.PROG_DIR, "gui/" + sickbeard.GUI_NAME + "/interfaces/default/",
KWs['file'])
super(PageTemplate, self).__init__(*args, **KWs) super(PageTemplate, self).__init__(*args, **KWs)
self.sbRoot = sickbeard.WEB_ROOT self.sbRoot = sickbeard.WEB_ROOT
@ -531,6 +532,7 @@ class PageTemplate(Template):
kwargs['cacheDirForModuleFiles'] = os.path.join(sickbeard.CACHE_DIR, 'cheetah') kwargs['cacheDirForModuleFiles'] = os.path.join(sickbeard.CACHE_DIR, 'cheetah')
return super(PageTemplate, self).compile(*args, **kwargs) return super(PageTemplate, self).compile(*args, **kwargs)
class IndexerWebUI(MainHandler): class IndexerWebUI(MainHandler):
def __init__(self, config, log=None): def __init__(self, config, log=None):
self.config = config self.config = config
@ -3432,7 +3434,7 @@ class Home(MainHandler):
if str(pid) != str(sickbeard.PID): if str(pid) != str(sickbeard.PID):
redirect("/home/") redirect("/home/")
threading.Timer(2, sickbeard.invoke_shutdown).start() sickbeard.events.put(sickbeard.events.SystemEvent.SHUTDOWN)
title = "Shutting down" title = "Shutting down"
message = "SickRage is shutting down..." message = "SickRage is shutting down..."
@ -3448,7 +3450,7 @@ class Home(MainHandler):
t.submenu = HomeMenu() t.submenu = HomeMenu()
# restart # restart
threading.Timer(5, sickbeard.invoke_restart, [False]).start() sickbeard.events.put(sickbeard.events.SystemEvent.RESTART)
return _munge(t) return _munge(t)
@ -3460,7 +3462,7 @@ class Home(MainHandler):
updated = sickbeard.versionCheckScheduler.action.update() # @UndefinedVariable updated = sickbeard.versionCheckScheduler.action.update() # @UndefinedVariable
if updated: if updated:
# do a hard restart # do a hard restart
threading.Timer(2, sickbeard.invoke_restart, [False]).start() sickbeard.events.put(sickbeard.events.SystemEvent.RESTART)
t = PageTemplate(headers=self.request.headers, file="restart_bare.tmpl") t = PageTemplate(headers=self.request.headers, file="restart_bare.tmpl")
return _munge(t) return _munge(t)
@ -3643,8 +3645,6 @@ class Home(MainHandler):
else: else:
return self._genericMessage("Error", errString) return self._genericMessage("Error", errString)
showObj.exceptions = scene_exceptions.get_scene_exceptions(showObj.indexerid)
if not location and not anyQualities and not bestQualities and not flatten_folders: if not location and not anyQualities and not bestQualities and not flatten_folders:
t = PageTemplate(headers=self.request.headers, file="editShow.tmpl") t = PageTemplate(headers=self.request.headers, file="editShow.tmpl")
t.submenu = HomeMenu() t.submenu = HomeMenu()
@ -3727,54 +3727,56 @@ class Home(MainHandler):
else: else:
do_update_exceptions = True do_update_exceptions = True
bwl = BlackAndWhiteList(showObj.indexerid) # If directCall from mass_edit_update no scene exceptions handling
if whitelist: if not directCall:
whitelist = whitelist.split(",") bwl = BlackAndWhiteList(showObj.indexerid)
shortWhiteList = [] if whitelist:
if helpers.set_up_anidb_connection(): whitelist = whitelist.split(",")
for groupName in whitelist: shortWhiteList = []
group = sickbeard.ADBA_CONNECTION.group(gname=groupName) if helpers.set_up_anidb_connection():
for line in group.datalines: for groupName in whitelist:
if line["shortname"]: group = sickbeard.ADBA_CONNECTION.group(gname=groupName)
shortWhiteList.append(line["shortname"]) for line in group.datalines:
else: if line["shortname"]:
if not groupName in shortWhiteList: shortWhiteList.append(line["shortname"])
shortWhiteList.append(groupName) else:
if not groupName in shortWhiteList:
shortWhiteList.append(groupName)
else:
shortWhiteList = whitelist
bwl.set_white_keywords_for("release_group", shortWhiteList)
else: else:
shortWhiteList = whitelist bwl.set_white_keywords_for("release_group", [])
bwl.set_white_keywords_for("release_group", shortWhiteList)
else:
bwl.set_white_keywords_for("release_group", [])
if blacklist: if blacklist:
blacklist = blacklist.split(",") blacklist = blacklist.split(",")
shortBlacklist = [] shortBlacklist = []
if helpers.set_up_anidb_connection(): if helpers.set_up_anidb_connection():
for groupName in blacklist: for groupName in blacklist:
group = sickbeard.ADBA_CONNECTION.group(gname=groupName) group = sickbeard.ADBA_CONNECTION.group(gname=groupName)
for line in group.datalines: for line in group.datalines:
if line["shortname"]: if line["shortname"]:
shortBlacklist.append(line["shortname"]) shortBlacklist.append(line["shortname"])
else: else:
if not groupName in shortBlacklist: if not groupName in shortBlacklist:
shortBlacklist.append(groupName) shortBlacklist.append(groupName)
else:
shortBlacklist = blacklist
bwl.set_black_keywords_for("release_group", shortBlacklist)
else: else:
shortBlacklist = blacklist bwl.set_black_keywords_for("release_group", [])
bwl.set_black_keywords_for("release_group", shortBlacklist)
else:
bwl.set_black_keywords_for("release_group", [])
if whiteWords: if whiteWords:
whiteWords = [x.strip() for x in whiteWords.split(",")] whiteWords = [x.strip() for x in whiteWords.split(",")]
bwl.set_white_keywords_for("global", whiteWords) bwl.set_white_keywords_for("global", whiteWords)
else: else:
bwl.set_white_keywords_for("global", []) bwl.set_white_keywords_for("global", [])
if blackWords: if blackWords:
blackWords = [x.strip() for x in blackWords.split(",")] blackWords = [x.strip() for x in blackWords.split(",")]
bwl.set_black_keywords_for("global", blackWords) bwl.set_black_keywords_for("global", blackWords)
else: else:
bwl.set_black_keywords_for("global", []) bwl.set_black_keywords_for("global", [])
errors = [] errors = []
with showObj.lock: with showObj.lock:
@ -3825,14 +3827,14 @@ class Home(MainHandler):
# if we change location clear the db of episodes, change it, write to db, and rescan # if we change location clear the db of episodes, change it, write to db, and rescan
if os.path.normpath(showObj._location) != os.path.normpath(location): if os.path.normpath(showObj._location) != os.path.normpath(location):
logger.log(os.path.normpath(showObj._location) + " != " + os.path.normpath(location), logger.DEBUG) logger.log(os.path.normpath(showObj._location) + " != " + os.path.normpath(location), logger.DEBUG)
if not ek.ek(os.path.isdir, location): if not ek.ek(os.path.isdir, location) and not sickbeard.CREATE_MISSING_SHOW_DIRS:
errors.append("New location <tt>%s</tt> does not exist" % location) errors.append("New location <tt>%s</tt> does not exist" % location)
# don't bother if we're going to update anyway # don't bother if we're going to update anyway
elif not do_update: elif not do_update:
# change it # change it
try: try:
showObj.location = location showObj._location = location
try: try:
sickbeard.showQueueScheduler.action.refreshShow(showObj) # @UndefinedVariable sickbeard.showQueueScheduler.action.refreshShow(showObj) # @UndefinedVariable
except exceptions.CantRefreshException, e: except exceptions.CantRefreshException, e:
@ -3858,6 +3860,7 @@ class Home(MainHandler):
if do_update_exceptions: if do_update_exceptions:
try: try:
scene_exceptions.update_scene_exceptions(showObj.indexerid, exceptions_list) # @UndefinedVariable scene_exceptions.update_scene_exceptions(showObj.indexerid, exceptions_list) # @UndefinedVariable
showObj.exceptions = scene_exceptions.get_scene_exceptions(showObj.indexerid)
time.sleep(cpu_presets[sickbeard.CPU_PRESET]) time.sleep(cpu_presets[sickbeard.CPU_PRESET])
except exceptions.CantUpdateException, e: except exceptions.CantUpdateException, e:
errors.append("Unable to force an update on scene exceptions of the show.") errors.append("Unable to force an update on scene exceptions of the show.")

View File

@ -122,13 +122,6 @@ class SRWebServer(threading.Thread):
try: try:
self.io_loop.start() self.io_loop.start()
self.io_loop.close(True) self.io_loop.close(True)
# stop all tasks
sickbeard.halt()
# save all shows to DB
sickbeard.saveAll()
except ValueError: except ValueError:
# Ignore errors like "ValueError: I/O operation on closed kqueue fd". These might be thrown during a reload. # Ignore errors like "ValueError: I/O operation on closed kqueue fd". These might be thrown during a reload.
pass pass