Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Removed trailing whitespaces

  • Loading branch information...
commit 7aea0d339d5dc7397404e086f0d14c8989dd0d19 1 parent 7cfcf9f
@midgetspy authored
Showing with 1,673 additions and 1,675 deletions.
  1. +15 −15 SickBeard.py
  2. +75 −75 sickbeard/__init__.py
  3. +5 −5 sickbeard/autoPostProcesser.py
  4. +11 −11 sickbeard/classes.py
  5. +13 −13 sickbeard/common.py
  6. +15 −15 sickbeard/config.py
  7. +16 −16 sickbeard/databases/mainDB.py
  8. +13 −13 sickbeard/db.py
  9. +2 −2 sickbeard/encodingKludge.py
  10. +5 −5 sickbeard/exceptions.py
  11. +27 −27 sickbeard/helpers.py
  12. +11 −12 sickbeard/history.py
  13. +10 −10 sickbeard/logger.py
  14. +11 −11 sickbeard/metadata.py
  15. +3 −3 sickbeard/notifiers/__init__.py
  16. +10 −10 sickbeard/notifiers/growl.py
  17. +1 −1  sickbeard/notifiers/tweet.py
  18. +16 −16 sickbeard/notifiers/xbmc.py
  19. +12 −12 sickbeard/nzbSplitter.py
  20. +55 −55 sickbeard/processTV.py
  21. +32 −32 sickbeard/properFinder.py
  22. +14 −14 sickbeard/providers/__init__.py
  23. +10 −10 sickbeard/providers/binreq.py
  24. +15 −15 sickbeard/providers/eztv.py
  25. +33 −33 sickbeard/providers/generic.py
  26. +88 −88 sickbeard/providers/newzbin.py
  27. +64 −64 sickbeard/providers/newznab.py
  28. +67 −67 sickbeard/providers/nzbmatrix.py
  29. +63 −63 sickbeard/providers/nzbs_org.py
  30. +14 −14 sickbeard/providers/nzbsrus.py
  31. +18 −18 sickbeard/providers/tvbinz.py
  32. +13 −13 sickbeard/providers/womble.py
  33. +54 −55 sickbeard/queue.py
  34. +12 −12 sickbeard/sab.py
  35. +15 −15 sickbeard/sceneHelpers.py
  36. +13 −13 sickbeard/scheduler.py
  37. +50 −50 sickbeard/search.py
  38. +25 −25 sickbeard/searchBacklog.py
  39. +19 −19 sickbeard/searchCurrent.py
  40. +10 −10 sickbeard/showUpdater.py
  41. +265 −265 sickbeard/tv.py
  42. +66 −66 sickbeard/tvcache.py
  43. +66 −66 sickbeard/tvrage.py
  44. +9 −9 sickbeard/ui.py
  45. +80 −80 sickbeard/versionChecker.py
  46. +232 −232 sickbeard/webserve.py
View
30 SickBeard.py
@@ -13,7 +13,7 @@
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-#
+#
# You should have received a copy of the GNU General Public License
# along with Sick Beard. If not, see <http://www.gnu.org/licenses/>.
@@ -52,7 +52,7 @@ def loadShowsFromDB():
myDB = db.DBConnection()
sqlResults = myDB.select("SELECT * FROM tv_shows")
-
+
for sqlShow in sqlResults:
try:
curShow = TVShow(int(sqlShow["tvdb_id"]))
@@ -60,7 +60,7 @@ def loadShowsFromDB():
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)
-
+
#TODO: make it update the existing shows if the showlist has something in it
def main():
@@ -84,10 +84,10 @@ def main():
except getopt.GetoptError:
print "Available options: --quiet, --forceupdate, --port"
sys.exit()
-
+
forceUpdate = False
forcedPort = None
-
+
for o, a in opts:
# for now we'll just silence the logging
if (o in ('-q', '--quiet')):
@@ -95,18 +95,18 @@ def main():
# for now we'll just silence the logging
if (o in ('--tvbinz')):
sickbeard.SHOW_TVBINZ = True
-
+
# should we update right away?
if (o in ('-f', '--forceupdate')):
forceUpdate = True
-
+
# should we update right away?
if (o in ('-p', '--port')):
forcedPort = int(a)
-
+
if consoleLogging:
print "Starting up Sick Beard "+SICKBEARD_VERSION+" from " + config_file
-
+
# load the config and publish it to the sickbeard package
if not os.path.isfile(config_file):
logger.log(u"Unable to find config.ini, all settings will be default", logger.ERROR)
@@ -117,13 +117,13 @@ def main():
sickbeard.initialize(consoleLogging=consoleLogging)
sickbeard.showList = []
-
+
if forcedPort:
logger.log(u"Forcing web server to port "+str(forcedPort))
startPort = forcedPort
else:
startPort = sickbeard.WEB_PORT
-
+
logger.log(u"Starting Sick Beard on http://localhost:"+str(startPort))
if sickbeard.WEB_LOG:
@@ -155,7 +155,7 @@ def main():
# set up the lists
sickbeard.updateAiringList()
sickbeard.updateComingList()
-
+
# fire up all our threads
sickbeard.start()
@@ -169,11 +169,11 @@ def main():
# stay alive while my threads do the work
while (True):
-
+
time.sleep(1)
-
+
return
-
+
if __name__ == "__main__":
if sys.hexversion >= 0x020600F0:
freeze_support()
View
150 sickbeard/__init__.py
@@ -12,7 +12,7 @@
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-#
+#
# You should have received a copy of the GNU General Public License
# along with Sick Beard. If not, see <http://www.gnu.org/licenses/>.
@@ -28,7 +28,7 @@
from threading import Lock
# apparently py2exe won't build these unless they're imported somewhere
-from sickbeard import providers
+from sickbeard import providers
from providers import eztv, nzbs_org, nzbmatrix, tvbinz, nzbsrus, binreq, newznab, womble, newzbin
from sickbeard import searchCurrent, searchBacklog, showUpdater, versionChecker, properFinder, autoPostProcesser
@@ -78,7 +78,7 @@
WEB_LOG = None
WEB_ROOT = None
WEB_USERNAME = None
-WEB_PASSWORD = None
+WEB_PASSWORD = None
WEB_HOST = None
LAUNCH_BROWSER = None
@@ -104,7 +104,7 @@
TVDB_API_PARMS = {}
USE_NZB = False
-NZB_METHOD = None
+NZB_METHOD = None
NZB_DIR = None
USENET_RETENTION = None
DOWNLOAD_PROPERS = None
@@ -173,7 +173,7 @@
USE_TWITTER = False
TWITTER_USERNAME = None
TWITTER_PASSWORD = None
-TWITTER_PREFIX = None
+TWITTER_PREFIX = None
EXTRA_SCRIPTS = []
@@ -265,9 +265,9 @@ def get_backlog_cycle_time():
def initialize(consoleLogging=True):
-
+
with INIT_LOCK:
-
+
global LOG_DIR, WEB_PORT, WEB_LOG, WEB_ROOT, WEB_USERNAME, WEB_PASSWORD, WEB_HOST, \
NZB_METHOD, NZB_DIR, TVBINZ, TVBINZ_UID, TVBINZ_HASH, DOWNLOAD_PROPERS, \
SAB_USERNAME, SAB_PASSWORD, SAB_APIKEY, SAB_CATEGORY, SAB_HOST, \
@@ -289,12 +289,12 @@ def initialize(consoleLogging=True):
NAMING_DATES, EXTRA_SCRIPTS, USE_TWITTER, TWITTER_USERNAME, TWITTER_PASSWORD, TWITTER_PREFIX, \
NEWZBIN, NEWZBIN_USERNAME, NEWZBIN_PASSWORD, GIT_PATH
-
+
if __INITIALIZED__:
return False
-
+
socket.setdefaulttimeout(SOCKET_TIMEOUT)
-
+
CheckSection('General')
CheckSection('Blackhole')
CheckSection('Newzbin')
@@ -303,7 +303,7 @@ def initialize(consoleLogging=True):
CheckSection('XBMC')
CheckSection('Growl')
CheckSection('Twitter')
-
+
LOG_DIR = check_setting_str(CFG, 'General', 'log_dir', 'Logs')
if not helpers.makeDir(LOG_DIR):
logger.log(u"!!! No log folder, logging to screen only!", logger.ERROR)
@@ -337,7 +337,7 @@ def initialize(consoleLogging=True):
'cache_dir': False}
if CACHE_DIR:
TVDB_API_PARMS['cache_dir'] = os.path.join(CACHE_DIR, 'tvdb')
-
+
QUALITY_DEFAULT = check_setting_int(CFG, 'General', 'quality_default', SD)
VERSION_NOTIFY = check_setting_int(CFG, 'General', 'version_notify', 1)
SEASON_FOLDERS_DEFAULT = bool(check_setting_int(CFG, 'General', 'season_folders_default', 0))
@@ -360,11 +360,11 @@ def initialize(consoleLogging=True):
NZB_METHOD = 'blackhole'
DOWNLOAD_PROPERS = bool(check_setting_int(CFG, 'General', 'download_propers', 1))
-
+
USE_NZB = bool(check_setting_int(CFG, 'General', 'use_nzb', 1))
USE_TORRENT = bool(check_setting_int(CFG, 'General', 'use_torrent', 0))
USENET_RETENTION = check_setting_int(CFG, 'General', 'usenet_retention', 500)
-
+
SEARCH_FREQUENCY = check_setting_int(CFG, 'General', 'search_frequency', DEFAULT_SEARCH_FREQUENCY)
if SEARCH_FREQUENCY < MIN_SEARCH_FREQUENCY:
SEARCH_FREQUENCY = MIN_SEARCH_FREQUENCY
@@ -375,33 +375,33 @@ def initialize(consoleLogging=True):
NZB_DIR = check_setting_str(CFG, 'Blackhole', 'nzb_dir', '')
TORRENT_DIR = check_setting_str(CFG, 'Blackhole', 'torrent_dir', '')
-
+
TV_DOWNLOAD_DIR = check_setting_str(CFG, 'General', 'tv_download_dir', '')
PROCESS_AUTOMATICALLY = check_setting_int(CFG, 'General', 'process_automatically', 0)
RENAME_EPISODES = check_setting_int(CFG, 'General', 'rename_episodes', 1)
KEEP_PROCESSED_DIR = check_setting_int(CFG, 'General', 'keep_processed_dir', 1)
-
+
TVBINZ = bool(check_setting_int(CFG, 'TVBinz', 'tvbinz', 0))
TVBINZ_UID = check_setting_str(CFG, 'TVBinz', 'tvbinz_uid', '')
TVBINZ_HASH = check_setting_str(CFG, 'TVBinz', 'tvbinz_hash', '')
TVBINZ_AUTH = check_setting_str(CFG, 'TVBinz', 'tvbinz_auth', '')
-
+
NZBS = bool(check_setting_int(CFG, 'NZBs', 'nzbs', 0))
NZBS_UID = check_setting_str(CFG, 'NZBs', 'nzbs_uid', '')
NZBS_HASH = check_setting_str(CFG, 'NZBs', 'nzbs_hash', '')
-
+
NZBSRUS = bool(check_setting_int(CFG, 'NZBsRUS', 'nzbsrus', 0))
NZBSRUS_UID = check_setting_str(CFG, 'NZBsRUS', 'nzbsrus_uid', '')
NZBSRUS_HASH = check_setting_str(CFG, 'NZBsRUS', 'nzbsrus_hash', '')
-
+
NZBMATRIX = bool(check_setting_int(CFG, 'NZBMatrix', 'nzbmatrix', 0))
NZBMATRIX_USERNAME = check_setting_str(CFG, 'NZBMatrix', 'nzbmatrix_username', '')
NZBMATRIX_APIKEY = check_setting_str(CFG, 'NZBMatrix', 'nzbmatrix_apikey', '')
-
+
NEWZBIN = bool(check_setting_int(CFG, 'Newzbin', 'newzbin', 0))
NEWZBIN_USERNAME = check_setting_str(CFG, 'Newzbin', 'newzbin_username', '')
NEWZBIN_PASSWORD = check_setting_str(CFG, 'Newzbin', 'newzbin_password', '')
-
+
BINREQ = bool(check_setting_int(CFG, 'Bin-Req', 'binreq', 1))
WOMBLE = bool(check_setting_int(CFG, 'Womble', 'womble', 1))
@@ -435,9 +435,9 @@ def initialize(consoleLogging=True):
newznabData = check_setting_str(CFG, 'Newznab', 'newznab_data', '')
newznabProviderList = providers.getNewznabProviderList(newznabData)
-
+
providerList = providers.makeProviderList()
-
+
logger.initLogging(consoleLogging=consoleLogging)
# initialize the main SB database
@@ -447,13 +447,13 @@ def initialize(consoleLogging=True):
cycleTime=datetime.timedelta(minutes=SEARCH_FREQUENCY),
threadName="SEARCH",
runImmediately=True)
-
+
backlogSearchScheduler = searchBacklog.BacklogSearchScheduler(searchBacklog.BacklogSearcher(),
cycleTime=datetime.timedelta(minutes=get_backlog_cycle_time()),
threadName="BACKLOG",
runImmediately=False)
backlogSearchScheduler.action.cycleTime = BACKLOG_SEARCH_FREQUENCY
-
+
# the interval for this is stored inside the ShowUpdater class
showUpdaterInstance = showUpdater.ShowUpdater()
showUpdateScheduler = scheduler.Scheduler(showUpdaterInstance,
@@ -465,7 +465,7 @@ def initialize(consoleLogging=True):
cycleTime=datetime.timedelta(hours=12),
threadName="CHECKVERSION",
runImmediately=True)
-
+
showQueueScheduler = scheduler.Scheduler(queue.ShowQueue(),
cycleTime=datetime.timedelta(seconds=3),
threadName="SHOWQUEUE",
@@ -476,16 +476,16 @@ def initialize(consoleLogging=True):
cycleTime=properFinderInstance.updateInterval,
threadName="FINDPROPERS",
runImmediately=False)
-
+
autoPostProcesserScheduler = scheduler.Scheduler(autoPostProcesser.PostProcesser(),
cycleTime=datetime.timedelta(minutes=10),
threadName="POSTPROCESSER",
runImmediately=True)
-
-
+
+
showList = []
loadingShowList = {}
-
+
airingList = []
comingList = []
@@ -493,21 +493,21 @@ def initialize(consoleLogging=True):
return True
def start():
-
+
global __INITIALIZED__, currentSearchScheduler, backlogSearchScheduler, \
showUpdateScheduler, versionCheckScheduler, showQueueScheduler, \
properFinderScheduler, autoPostProcesserScheduler
-
+
with INIT_LOCK:
-
+
if __INITIALIZED__:
-
+
# start the search scheduler
currentSearchScheduler.thread.start()
-
+
# start the backlog scheduler
backlogSearchScheduler.thread.start()
-
+
# start the show updater
showUpdateScheduler.thread.start()
@@ -524,16 +524,16 @@ def start():
autoPostProcesserScheduler.thread.start()
def halt ():
-
+
global __INITIALIZED__, currentSearchScheduler, backlogSearchScheduler, showUpdateScheduler, \
showQueueScheduler, properFinderScheduler, autoPostProcesserScheduler
-
+
with INIT_LOCK:
-
+
if __INITIALIZED__:
logger.log(u"Aborting all threads")
-
+
# abort all the threads
currentSearchScheduler.abort = True
@@ -542,7 +542,7 @@ def halt ():
currentSearchScheduler.thread.join(10)
except:
pass
-
+
backlogSearchScheduler.abort = True
logger.log(u"Waiting for the BACKLOG thread to exit")
try:
@@ -556,36 +556,36 @@ def halt ():
showUpdateScheduler.thread.join(10)
except:
pass
-
+
versionCheckScheduler.abort = True
logger.log(u"Waiting for the VERSIONCHECKER thread to exit")
try:
versionCheckScheduler.thread.join(10)
except:
pass
-
+
showQueueScheduler.abort = True
logger.log(u"Waiting for the SHOWQUEUE thread to exit")
try:
showQueueScheduler.thread.join(10)
except:
pass
-
+
autoPostProcesserScheduler.abort = True
logger.log(u"Waiting for the POSTPROCESSER thread to exit")
try:
autoPostProcesserScheduler.thread.join(10)
except:
pass
-
+
properFinderScheduler.abort = True
logger.log(u"Waiting for the PROPERFINDER thread to exit")
try:
properFinderScheduler.thread.join(10)
except:
pass
-
-
+
+
__INITIALIZED__ = False
@@ -594,27 +594,27 @@ def sig_handler(signum=None, frame=None):
logger.log(u"Signal %i caught, saving and exiting..." % int(signum))
cherrypy.engine.exit()
saveAndShutdown()
-
+
def saveAll():
-
+
global showList
-
+
# write all shows
logger.log(u"Saving all shows to the database")
for show in showList:
show.saveToDB()
-
+
# save config
logger.log(u"Saving config file to disk")
save_config()
-
+
def saveAndShutdown(restart=False):
logger.log(u"Killing cherrypy")
cherrypy.engine.exit()
-
+
halt()
saveAll()
@@ -623,7 +623,7 @@ def saveAndShutdown(restart=False):
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':
@@ -638,12 +638,12 @@ def saveAndShutdown(restart=False):
popen_list += sickbeard.MY_ARGS
logger.log(u"Restarting Sick Beard with " + str(popen_list))
subprocess.Popen(popen_list, cwd=os.getcwd())
-
+
os._exit(0)
def restart(soft=True):
-
+
if soft:
halt()
saveAll()
@@ -651,14 +651,14 @@ def restart(soft=True):
#cherrypy.engine.restart()
logger.log(u"Re-initializing all data")
initialize()
-
+
else:
saveAndShutdown(restart=True)
def save_config():
-
+
CFG['General']['log_dir'] = LOG_DIR
CFG['General']['web_port'] = WEB_PORT
CFG['General']['web_host'] = WEB_HOST
@@ -732,9 +732,9 @@ def save_config():
CFG['Twitter']['twitter_username'] = TWITTER_USERNAME
CFG['Twitter']['twitter_password'] = TWITTER_PASSWORD
CFG['Twitter']['twitter_prefix'] = TWITTER_PREFIX
-
+
CFG['Newznab']['newznab_data'] = '!!!'.join([x.configStr() for x in newznabProviderList])
-
+
CFG.write()
@@ -750,22 +750,22 @@ def launchBrowser():
def updateAiringList():
-
+
logger.log(u"Searching DB and building list of airing episodes")
-
+
curDate = datetime.date.today().toordinal()
myDB = db.DBConnection()
sqlResults = myDB.select("SELECT * FROM tv_episodes WHERE status == ? AND airdate <= ?", [UNAIRED, curDate])
-
+
epList = []
for sqlEp in sqlResults:
-
+
try:
show = helpers.findCertainShow (sickbeard.showList, int(sqlEp["showid"]))
except exceptions.MultipleShowObjectsException:
- logger.log(u"ERROR: expected to find a single show matching " + sqlEp["showid"])
+ logger.log(u"ERROR: expected to find a single show matching " + sqlEp["showid"])
return None
except exceptions.SickBeardException, e:
logger.log(u"Unexpected exception: "+str(e).decode('utf-8'), logger.ERROR)
@@ -774,12 +774,12 @@ def updateAiringList():
# we aren't ever downloading specials
if int(sqlEp["season"]) == 0:
continue
-
+
if show == None:
continue
-
+
ep = show.getEpisode(sqlEp["season"], sqlEp["episode"])
-
+
if ep == None:
logger.log(u"Somehow "+show.name+" - "+str(sqlEp["season"])+"x"+str(sqlEp["episode"])+" is None", logger.ERROR)
else:
@@ -790,7 +790,7 @@ def updateAiringList():
def updateComingList():
epList = []
-
+
for curShow in sickbeard.showList:
curEps = None
@@ -799,7 +799,7 @@ def updateComingList():
curEps = curShow.nextEpisode()
except exceptions.NoNFOException, e:
logger.log(u"Unable to retrieve episode from show: "+str(e).decode('utf-8'), logger.ERROR)
-
+
for myEp in curEps:
if myEp.season != 0:
epList.append(myEp)
@@ -807,17 +807,17 @@ def updateComingList():
sickbeard.comingList = epList
def getEpList(epIDs, showid=None):
-
+
if epIDs == None or len(epIDs) == 0:
return []
query = "SELECT * FROM tv_episodes WHERE tvdbid in (%s)" % (",".join(["?" for x in epIDs]),)
params = epIDs
-
+
if showid != None:
query += " AND showid = ?"
params.append(showid)
-
+
myDB = db.DBConnection()
sqlResults = myDB.select(query, params)
@@ -827,5 +827,5 @@ def getEpList(epIDs, showid=None):
curShowObj = helpers.findCertainShow(sickbeard.showList, int(curEp["showid"]))
curEpObj = curShowObj.getEpisode(int(curEp["season"]), int(curEp["episode"]))
epList.append(curEpObj)
-
- return epList
+
+ return epList
View
10 sickbeard/autoPostProcesser.py
@@ -12,7 +12,7 @@
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-#
+#
# You should have received a copy of the GNU General Public License
# along with Sick Beard. If not, see <http://www.gnu.org/licenses/>.
@@ -28,7 +28,7 @@
class PostProcesser():
-
+
def run(self):
if not sickbeard.PROCESS_AUTOMATICALLY:
return
@@ -36,13 +36,13 @@ def run(self):
if not ek.ek(os.path.isdir, sickbeard.TV_DOWNLOAD_DIR):
logger.log(u"Automatic post-processing attempted but dir "+sickbeard.TV_DOWNLOAD_DIR+" doesn't exist", logger.ERROR)
return
-
+
if not ek.ek(os.path.isabs, sickbeard.TV_DOWNLOAD_DIR):
logger.log(u"Automatic post-processing attempted but dir "+sickbeard.TV_DOWNLOAD_DIR+" is relative (and probably not what you really want to process)", logger.ERROR)
return
-
+
myDB = db.DBConnection()
- sqlResults = myDB.select("SELECT * FROM tv_shows WHERE location = ? OR location LIKE ?",
+ sqlResults = myDB.select("SELECT * FROM tv_shows WHERE location = ? OR location LIKE ?",
[os.path.abspath(sickbeard.TV_DOWNLOAD_DIR),
ek.ek(os.path.join, os.path.abspath(sickbeard.TV_DOWNLOAD_DIR), '%')])
View
22 sickbeard/classes.py
@@ -12,7 +12,7 @@
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-#
+#
# You should have received a copy of the GNU General Public License
# along with Sick Beard. If not, see <http://www.gnu.org/licenses/>.
@@ -36,7 +36,7 @@ def __init__(self, user, pw):
self.password = pw
self.numTries = 0
urllib.FancyURLopener.__init__(self)
-
+
def prompt_user_passwd(self, host, realm):
if self.numTries == 0:
self.numTries = 1
@@ -60,10 +60,10 @@ def __init__(self, episodes):
self.name = ""
def __str__(self):
-
+
if self.provider == None:
return "Invalid provider, unable to print self"
-
+
myString = self.provider.name + " @ " + self.url + "\n"
myString += "Extra Info:\n"
for extra in self.extraInfo:
@@ -95,7 +95,7 @@ def selectSeries(self, allSeries):
for curShow in allSeries:
if int(curShow['id']) in idList:
return curShow
-
+
# if nothing matches then just go with the first match I guess
return allSeries[0]
@@ -106,19 +106,19 @@ def __init__(self, name, url, date):
self.date = date
self.provider = None
self.quality = -1
-
+
self.tvdbid = -1
self.season = -1
self.episode = -1
-
+
def __str__(self):
return str(self.date)+" "+self.name+" "+str(self.season)+"x"+str(self.episode)+" of "+str(self.tvdbid)
-
-
+
+
class ErrorViewer():
-
+
errors = []
-
+
def __init__(self):
ErrorViewer.errors = []
View
26 sickbeard/common.py
@@ -12,7 +12,7 @@
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-#
+#
# You should have received a copy of the GNU General Public License
# along with Sick Beard. If not, see <http://www.gnu.org/licenses/>.
@@ -63,7 +63,7 @@ class Quality:
# put these bits at the other end of the spectrum, far enough out that they shouldn't interfere
UNKNOWN = 1<<15
-
+
qualityStrings = {NONE: "N/A",
UNKNOWN: "Unknown",
SDTV: "SD TV",
@@ -102,15 +102,15 @@ def splitQuality(quality):
anyQualities.append(curQual)
if curQual<<16 & quality:
bestQualities.append(curQual)
-
+
return (anyQualities, bestQualities)
@staticmethod
def nameQuality(name):
-
+
name = os.path.basename(name)
-
- # if we have our exact text then assume we put it there
+
+ # if we have our exact text then assume we put it there
for x in Quality.qualityStrings:
if x == Quality.UNKNOWN:
continue
@@ -119,9 +119,9 @@ def nameQuality(name):
regex_match = re.search(regex, name, re.I)
if regex_match:
return x
-
+
checkName = lambda list, func: func([re.search(x, name, re.I) for x in list])
-
+
if checkName(["pdtv.xvid", "hdtv.xvid", "dsr.xvid"], any):
return Quality.SDTV
elif checkName(["dvdrip.xvid", "bdrip.xvid"], any):
@@ -139,7 +139,7 @@ def nameQuality(name):
@staticmethod
def assumeQuality(name):
-
+
if name.endswith(".avi"):
return Quality.SDTV
elif name.endswith(".mkv"):
@@ -161,7 +161,7 @@ def splitCompositeStatus(status):
for x in sorted(Quality.qualityStrings.keys(), reverse=True):
if status > x*100:
return (status-x*100, x)
-
+
return (Quality.NONE, status)
@staticmethod
@@ -176,7 +176,7 @@ def statusFromName(name, assume=True):
Quality.SNATCHED = [Quality.compositeStatus(SNATCHED, x) for x in Quality.qualityStrings.keys()]
Quality.SNATCHED_PROPER = [Quality.compositeStatus(SNATCHED_PROPER, x) for x in Quality.qualityStrings.keys()]
-HD = Quality.combineQualities([Quality.HDTV, Quality.HDWEBDL, Quality.HDBLURAY], [])
+HD = Quality.combineQualities([Quality.HDTV, Quality.HDWEBDL, Quality.HDBLURAY], [])
SD = Quality.combineQualities([Quality.SDTV, Quality.SDDVD], [])
ANY = Quality.combineQualities([Quality.SDTV, Quality.SDDVD, Quality.HDTV, Quality.HDWEBDL, Quality.HDBLURAY], [])
BEST = Quality.combineQualities([Quality.SDTV, Quality.HDTV], [Quality.SDTV, Quality.HDTV])
@@ -220,7 +220,7 @@ class Overview:
QUAL = 3
GOOD = 4
UNAIRED = 5
-
+
overviewStrings = {SKIPPED: "skipped",
WANTED: "wanted",
QUAL: "qual",
@@ -228,7 +228,7 @@ class Overview:
UNAIRED: "unaired"}
# Get our xml namespaces correct for lxml
-XML_NSMAP = {'xsi': 'http://www.w3.org/2001/XMLSchema-instance',
+XML_NSMAP = {'xsi': 'http://www.w3.org/2001/XMLSchema-instance',
'xsd': 'http://www.w3.org/2001/XMLSchema'}
View
30 sickbeard/config.py
@@ -12,7 +12,7 @@
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-#
+#
# You should have received a copy of the GNU General Public License
# along with Sick Beard. If not, see <http://www.gnu.org/licenses/>.
@@ -39,7 +39,7 @@
naming_multi_ep_type_text = ("extend", "duplicate", "repeat")
naming_sep_type = (" - ", " ")
-naming_sep_type_text = (" - ", "space")
+naming_sep_type_text = (" - ", "space")
def change_LOG_DIR(log_dir):
@@ -51,9 +51,9 @@ def change_LOG_DIR(log_dir):
cherry_log = os.path.join(sickbeard.LOG_DIR, "cherrypy.log")
cherrypy.config.update({'log.access_file': cherry_log})
-
+
logger.log(u"Changed cherry log file to " + cherry_log)
-
+
else:
return False
@@ -108,39 +108,39 @@ def change_TV_DOWNLOAD_DIR(tv_download_dir):
def change_SEARCH_FREQUENCY(freq):
-
+
if freq == None:
freq = sickbeard.DEFAULT_SEARCH_FREQUENCY
else:
freq = int(freq)
-
+
if freq < sickbeard.MIN_SEARCH_FREQUENCY:
freq = sickbeard.MIN_SEARCH_FREQUENCY
-
+
sickbeard.SEARCH_FREQUENCY = freq
-
+
sickbeard.currentSearchScheduler.cycleTime = datetime.timedelta(minutes=sickbeard.SEARCH_FREQUENCY)
sickbeard.backlogSearchScheduler.cycleTime = datetime.timedelta(minutes=sickbeard.get_backlog_cycle_time())
-
+
def change_BACKLOG_SEARCH_FREQUENCY(freq):
-
+
if freq == None:
freq = sickbeard.DEFAULT_BACKLOG_SEARCH_FREQUENCY
else:
freq = int(freq)
-
+
if freq < sickbeard.MIN_BACKLOG_SEARCH_FREQUENCY:
freq = sickbeard.MIN_BACKLOG_SEARCH_FREQUENCY
-
+
sickbeard.BACKLOG_SEARCH_FREQUENCY = freq
-
+
sickbeard.backlogSearchScheduler.action.cycleTime = sickbeard.BACKLOG_SEARCH_FREQUENCY
-
+
def change_VERSION_NOTIFY(version_notify):
oldSetting = sickbeard.VERSION_NOTIFY
- sickbeard.VERSION_NOTIFY = version_notify
+ sickbeard.VERSION_NOTIFY = version_notify
if oldSetting == False and version_notify == True:
sickbeard.versionCheckScheduler.action.run()
View
32 sickbeard/databases/mainDB.py
@@ -82,7 +82,7 @@ def test(self):
return self.hasTable("db_version")
def execute(self):
-
+
numTries = 0
while not ek.ek(os.path.isfile, ek.ek(os.path.join, sickbeard.PROG_DIR, 'sickbeard.db.v0')):
if not ek.ek(os.path.isfile, ek.ek(os.path.join, sickbeard.PROG_DIR, 'sickbeard.db')):
@@ -98,11 +98,11 @@ def execute(self):
numTries += 1
time.sleep(1)
logger.log(u"Trying again.")
-
+
if numTries >= 10:
logger.log(u"Unable to back up your sickbeard.db file, please do it manually.")
sys.exit(1)
-
+
# old stuff that's been removed from common but we need it to upgrade
HD = 1
SD = 3
@@ -147,7 +147,7 @@ def execute(self):
if newStatus != None:
self.connection.action("UPDATE tv_episodes SET status = ? WHERE episode_id = ? ", [newStatus, curUpdate["episode_id"]])
continue
-
+
# if we get here status should be == DOWNLOADED
if not curUpdate["location"]:
continue
@@ -163,12 +163,12 @@ def execute(self):
### Update show qualities
toUpdate = self.connection.select("SELECT * FROM tv_shows")
for curUpdate in toUpdate:
-
+
if not curUpdate["quality"]:
continue
-
+
if int(curUpdate["quality"]) == HD:
- newQuality = common.HD
+ newQuality = common.HD
elif int(curUpdate["quality"]) == SD:
newQuality = common.SD
elif int(curUpdate["quality"]) == ANY:
@@ -178,15 +178,15 @@ def execute(self):
else:
logger.log(u"Unknown show quality: "+str(curUpdate["quality"]), logger.WARNING)
newQuality = None
-
+
if newQuality:
self.connection.action("UPDATE tv_shows SET quality = ? WHERE show_id = ?", [newQuality, curUpdate["show_id"]])
-
-
+
+
### Update history
toUpdate = self.connection.select("SELECT * FROM history")
for curUpdate in toUpdate:
-
+
newAction = None
newStatus = None
if int(curUpdate["action"] == ACTION_SNATCHED):
@@ -223,23 +223,23 @@ def execute(self):
class UpgradeHistoryForGenericProviders(DropOldHistoryTable):
def test(self):
return self.checkDBVersion() >= 3
-
+
def execute(self):
-
+
providerMap = {'NZBs': 'NZBs.org',
'BinReq': 'Bin-Req',
'NZBsRUS': '''NZBs'R'US''',
'EZTV': 'EZTV@BT-Chat'}
-
+
for oldProvider in providerMap:
self.connection.action("UPDATE history SET provider = ? WHERE provider = ?", [providerMap[oldProvider], oldProvider])
-
+
self.incDBVersion()
class AddAirByDateOption(UpgradeHistoryForGenericProviders):
def test(self):
return self.checkDBVersion() >= 4
-
+
def execute(self):
self.connection.action("ALTER TABLE tv_shows ADD air_by_date NUMERIC")
self.incDBVersion()
View
26 sickbeard/db.py
@@ -12,7 +12,7 @@
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-#
+#
# You should have received a copy of the GNU General Public License
# along with Sick Beard. If not, see <http://www.gnu.org/licenses/>.
@@ -27,14 +27,14 @@
class DBConnection:
def __init__(self, dbFileName="sickbeard.db"):
-
+
self.dbFileName = dbFileName
-
+
self.connection = sqlite3.connect(os.path.join(sickbeard.PROG_DIR, self.dbFileName), 20)
self.connection.row_factory = sqlite3.Row
def action(self, query, args=None):
-
+
if query == None:
return
@@ -63,9 +63,9 @@ def action(self, query, args=None):
except sqlite3.DatabaseError, e:
logger.log(u"Fatal error executing query: " + str(e), logger.ERROR)
raise
-
+
return sqlResult
-
+
def select(self, query, args=None):
@@ -73,22 +73,22 @@ def select(self, query, args=None):
if sqlResults == None:
return []
-
+
return sqlResults
-
+
def upsert(self, tableName, valueDict, keyDict):
-
+
changesBefore = self.connection.total_changes
-
+
genParams = lambda myDict : [x + " = ?" for x in myDict.keys()]
-
+
query = "UPDATE "+tableName+" SET " + ", ".join(genParams(valueDict)) + " WHERE " + " AND ".join(genParams(keyDict))
-
+
self.action(query, valueDict.values() + keyDict.values())
if self.connection.total_changes == changesBefore:
query = "INSERT INTO "+tableName+" (" + ", ".join(valueDict.keys() + keyDict.keys()) + ")" + \
- " VALUES (" + ", ".join(["?"] * len(valueDict.keys() + keyDict.keys())) + ")"
+ " VALUES (" + ", ".join(["?"] * len(valueDict.keys() + keyDict.keys())) + ")"
self.action(query, valueDict.values() + keyDict.values())
def tableInfo(self, tableName):
View
4 sickbeard/encodingKludge.py
@@ -21,7 +21,7 @@ def fixStupidEncodings(x):
return None
return None
-
+
def fixListEncodings(x):
if type(x) != list:
return x
@@ -36,7 +36,7 @@ def ek(func, *args):
result = func(*args)
else:
result = func(*[x.encode('UTF-8') for x in args])
-
+
if type(result) == list:
return fixListEncodings(result)
elif type(result) == str:
View
10 sickbeard/exceptions.py
@@ -12,7 +12,7 @@
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-#
+#
# You should have received a copy of the GNU General Public License
# along with Sick Beard. If not, see <http://www.gnu.org/licenses/>.
@@ -50,10 +50,10 @@ class WrongShowException(SickBeardException):
class ShowNotFoundException(SickBeardException):
"The show wasn't found on theTVDB"
-
+
class EpisodeNotFoundException(SickBeardException):
"The episode wasn't found on theTVDB"
-
+
class NewzbinAPIThrottled(SickBeardException):
"Newzbin has throttled us, deal with it"
@@ -62,10 +62,10 @@ class TVRageException(SickBeardException):
class ShowDirNotFoundException(SickBeardException):
"The show dir doesn't exist"
-
+
class AuthException(SickBeardException):
"Your authentication information is incorrect"
-
+
class EpisodeDeletedException(SickBeardException):
"This episode has been deleted"
View
54 sickbeard/helpers.py
@@ -12,7 +12,7 @@
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-#
+#
# You should have received a copy of the GNU General Public License
# along with Sick Beard. If not, see <http://www.gnu.org/licenses/>.
@@ -81,7 +81,7 @@ def isMediaFile (file):
# ignore samples
if re.search('(^|[\W_])sample\d*[\W_]', file):
return False
-
+
sepFile = file.rpartition(".")
if sepFile[2].lower() in mediaExtensions:
return True
@@ -102,10 +102,10 @@ def sanitizeFileName (name):
for x in ":\"<>|?":
name = name.replace(x, "")
return name
-
+
def getURL (url, headers=[]):
-
+
opener = urllib2.build_opener()
opener.addheaders = [('User-Agent', USER_AGENT), ('Accept-Encoding', 'gzip,deflate')]
for cur_header in headers:
@@ -137,7 +137,7 @@ def findCertainShow (showList, tvdbid):
raise MultipleShowObjectsException()
else:
return results[0]
-
+
def findCertainTVRageShow (showList, tvrid):
if tvrid == 0:
@@ -151,8 +151,8 @@ def findCertainTVRageShow (showList, tvrid):
raise MultipleShowObjectsException()
else:
return results[0]
-
-
+
+
def makeDir (dir):
if not ek.ek(os.path.isdir, dir):
try:
@@ -170,7 +170,7 @@ def makeShowNFO(showID, showDir):
return False
t = tvdb_api.Tvdb(actors=True, **sickbeard.TVDB_API_PARMS)
-
+
try:
myShow = t[int(showID)]
except tvdb_exceptions.tvdb_shownotfound:
@@ -203,7 +203,7 @@ def makeShowNFO(showID, showDir):
nfo.write( nfo_fh, encoding="utf-8" )
return True
-
+
def buildNFOXML(myShow):
'''
Build an etree.Element of the root node of an NFO file with the
@@ -231,7 +231,7 @@ def buildNFOXML(myShow):
title = etree.SubElement( tvNode, "title" )
if myShow["seriesname"] != None:
title.text = myShow["seriesname"]
-
+
rating = etree.SubElement( tvNode, "rating" )
if myShow["rating"] != None:
rating.text = myShow["rating"]
@@ -245,7 +245,7 @@ def buildNFOXML(myShow):
if myShow["id"] != None:
showurl = sickbeard.TVDB_BASE_URL + '/series/' + myShow["id"] + '/all/en.zip'
episodeguideurl.text = showurl
-
+
mpaa = etree.SubElement( tvNode, "mpaa" )
if myShow["contentrating"] != None:
mpaa.text = myShow["contentrating"]
@@ -253,19 +253,19 @@ def buildNFOXML(myShow):
tvdbid = etree.SubElement( tvNode, "id" )
if myShow["id"] != None:
tvdbid.text = myShow["id"]
-
+
genre = etree.SubElement( tvNode, "genre" )
if myShow["genre"] != None:
genre.text = " / ".join([x for x in myShow["genre"].split('|') if x != ''])
-
+
premiered = etree.SubElement( tvNode, "premiered" )
if myShow["firstaired"] != None:
premiered.text = myShow["firstaired"]
-
+
studio = etree.SubElement( tvNode, "studio" )
if myShow["network"] != None:
studio.text = myShow["network"]
-
+
for actor in myShow['_actors']:
cur_actor = etree.SubElement( tvNode, "actor" )
@@ -288,29 +288,29 @@ def buildNFOXML(myShow):
def searchDBForShow(regShowName):
-
+
showNames = set([regShowName+'%', regShowName.replace(' ','_')+'%'])
-
+
# if tvdb fails then try looking it up in the db
myDB = db.DBConnection()
yearRegex = "(.*?)\s*([(]?)(\d{4})(?(2)[)]?).*"
for showName in showNames:
-
+
sqlResults = myDB.select("SELECT * FROM tv_shows WHERE show_name LIKE ? OR tvr_name LIKE ?", [showName, showName])
-
+
if len(sqlResults) == 1:
return (int(sqlResults[0]["tvdb_id"]), sqlResults[0]["show_name"])
else:
-
+
# if we didn't get exactly one result then try again with the year stripped off if possible
match = re.match(yearRegex, showName)
if match:
logger.log(u"Unable to match original name but trying to manually strip and specify show year", logger.DEBUG)
sqlResults = myDB.select("SELECT * FROM tv_shows WHERE (show_name LIKE ? OR tvr_name LIKE ?) AND startyear = ?", [match.group(1)+'%', match.group(1)+'%', match.group(3)])
-
+
if len(sqlResults) == 0:
logger.log(u"Unable to match a record in the DB for "+showName, logger.DEBUG)
continue
@@ -320,17 +320,17 @@ def searchDBForShow(regShowName):
else:
return (int(sqlResults[0]["tvdb_id"]), sqlResults[0]["show_name"])
-
+
return None
def getShowImage(url, imgNum=None):
-
+
imgFile = None
imgData = None
-
+
if url == None:
return None
-
+
# if they provided a fanart number try to use it instead
if imgNum != None:
tempURL = url.split('-')[0] + "-" + str(imgNum) + ".jpg"
@@ -354,7 +354,7 @@ def getShowImage(url, imgNum=None):
# get the image
try:
- imgData = imgFile.read()
+ imgData = imgFile.read()
except (urllib2.URLError, urllib2.HTTPError), e:
logger.log(u"There was an error trying to retrieve the image, skipping download: " + str(e), logger.ERROR)
return None
@@ -392,7 +392,7 @@ def listMediaFiles(dir):
# if it's a dir do it recursively
if ek.ek(os.path.isdir, fullCurFile) and not curFile.startswith('.') and not curFile == 'Extras':
files += listMediaFiles(fullCurFile)
-
+
elif isMediaFile(curFile):
files.append(fullCurFile)
View
23 sickbeard/history.py
@@ -11,44 +11,43 @@
def _logHistoryItem(action, showid, season, episode, quality, resource, provider):
logDate = datetime.datetime.today().strftime(dateFormat)
-
+
myDB = db.DBConnection()
myDB.action("INSERT INTO history (action, date, showid, season, episode, quality, resource, provider) VALUES (?,?,?,?,?,?,?,?)",
[action, logDate, showid, season, episode, quality, resource, provider])
-
+
def logSnatch(searchResult):
-
+
for curEpObj in searchResult.episodes:
showid = int(curEpObj.show.tvdbid)
season = int(curEpObj.season)
episode = int(curEpObj.episode)
quality = searchResult.quality
-
+
providerClass = searchResult.provider
if providerClass != None:
provider = providerClass.name
else:
provider = "unknown"
-
+
action = Quality.compositeStatus(SNATCHED, searchResult.quality)
-
+
resource = searchResult.name
-
+
_logHistoryItem(action, showid, season, episode, quality, resource, provider)
def logDownload(episode, filename):
-
+
showid = int(episode.show.tvdbid)
season = int(episode.season)
epNum = int(episode.episode)
-
+
quality = -1
provider = -1
-
+
action = episode.status
-
+
_logHistoryItem(action, showid, season, epNum, quality, filename, provider)
-
View
20 sickbeard/logger.py
@@ -12,7 +12,7 @@
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-#
+#
# You should have received a copy of the GNU General Public License
# along with Sick Beard. If not, see <http://www.gnu.org/licenses/>.
@@ -47,7 +47,7 @@ def initLogging(consoleLogging=True):
global logFile
logFile = os.path.join(sickbeard.LOG_DIR, 'sickbeard.log')
-
+
fileHandler = logging.handlers.RotatingFileHandler(
logFile,
maxBytes=25000000,
@@ -57,26 +57,26 @@ def initLogging(consoleLogging=True):
fileHandler.setFormatter(logging.Formatter('%(asctime)s %(levelname)-8s %(message)s', '%b-%d %H:%M:%S'))
logging.getLogger('sickbeard').addHandler(fileHandler)
-
+
# define a Handler which writes INFO messages or higher to the sys.stderr
if consoleLogging:
console = logging.StreamHandler()
-
+
console.setLevel(logging.INFO)
-
+
# set a format which is simpler for console use
console.setFormatter(logging.Formatter('%(asctime)s %(levelname)s::%(message)s', '%H:%M:%S'))
-
+
# add the handler to the root logger
logging.getLogger('sickbeard').addHandler(console)
logging.getLogger('sickbeard').setLevel(logging.DEBUG)
-
+
def log(toLog, logLevel=MESSAGE):
-
+
meThread = threading.currentThread().getName()
message = meThread + " :: " + toLog
-
+
outLine = message.encode('utf-8')
sbLogger = logging.getLogger('sickbeard')
@@ -89,7 +89,7 @@ def log(toLog, logLevel=MESSAGE):
sbLogger.warning(outLine)
elif logLevel == ERROR:
sbLogger.error(outLine)
-
+
# add errors to the UI logger
classes.ErrorViewer.add(classes.UIError(message))
else:
View
22 sickbeard/metadata.py
@@ -14,7 +14,7 @@
def makeShowNFO(showID):
t = tvdb_api.Tvdb(actors=True, **sickbeard.TVDB_API_PARMS)
-
+
tvNode = etree.Element( "tvshow" )
for ns in XML_NSMAP.keys():
tvNode.set(ns, XML_NSMAP[ns])
@@ -39,11 +39,11 @@ def makeShowNFO(showID):
logger.log(u"Incomplete info for show with id " + str(showID) + " on tvdb, skipping it", logger.ERROR)
return False
-
+
title = etree.SubElement( tvNode, "title" )
if myShow["seriesname"] != None:
title.text = myShow["seriesname"]
-
+
rating = etree.SubElement( tvNode, "rating" )
if myShow["rating"] != None:
rating.text = myShow["rating"]
@@ -59,7 +59,7 @@ def makeShowNFO(showID):
showurl = sickbeard.TVDB_BASE_URL + '/series/' + myShow["id"] + '/all/en.zip'
episodeguideurl.text = showurl
episodeguideurl2.text = showurl
-
+
mpaa = etree.SubElement( tvNode, "mpaa" )
if myShow["contentrating"] != None:
mpaa.text = myShow["contentrating"]
@@ -67,19 +67,19 @@ def makeShowNFO(showID):
tvdbid = etree.SubElement( tvNode, "id" )
if myShow["id"] != None:
tvdbid.text = myShow["id"]
-
+
genre = etree.SubElement( tvNode, "genre" )
if myShow["genre"] != None:
genre.text = " / ".join([x for x in myShow["genre"].split('|') if x])
-
+
premiered = etree.SubElement( tvNode, "premiered" )
if myShow["firstaired"] != None:
premiered.text = myShow["firstaired"]
-
+
studio = etree.SubElement( tvNode, "studio" )
if myShow["network"] != None:
studio.text = myShow["network"]
-
+
for actor in myShow['_actors']:
cur_actor = etree.SubElement( tvNode, "actor" )
@@ -106,11 +106,11 @@ def getTVDBIDFromNFO(dir):
if not ek.ek(os.path.isdir, dir):
logger.log(u"Show dir doesn't exist, can't load NFO")
raise exceptions.NoNFOException("The show dir doesn't exist, no NFO could be loaded")
-
+
logger.log(u"Loading show info from NFO")
xmlFile = ek.ek(os.path.join, dir, "tvshow.nfo")
-
+
try:
xmlFileObj = ek.ek(open, xmlFile, 'r')
showXML = etree.ElementTree(file = xmlFileObj)
@@ -120,7 +120,7 @@ def getTVDBIDFromNFO(dir):
+ str(showXML.findtext('title')) + " " \
+ str(showXML.findtext('tvdbid')) + " " \
+ str(showXML.findtext('id')))
-
+
name = showXML.findtext('title')
if showXML.findtext('tvdbid') != None:
tvdb_id = int(showXML.findtext('tvdbid'))
View
6 sickbeard/notifiers/__init__.py
@@ -4,7 +4,7 @@
import growl
import tweet
-from sickbeard.common import *
+from sickbeard.common import *
def testGrowl(host, password):
@@ -23,10 +23,10 @@ def testTwitter():
return tweet.notifyTwitter("This is a test notification from Sick Beard", force=True)
def notify(type, message):
-
+
if type == NOTIFY_DOWNLOAD and sickbeard.XBMC_NOTIFY_ONDOWNLOAD == True:
xbmc.notifyXBMC(message, notifyStrings[type])
-
+
if type == NOTIFY_SNATCH and sickbeard.XBMC_NOTIFY_ONSNATCH:
xbmc.notifyXBMC(message, notifyStrings[type])
View
20 sickbeard/notifiers/growl.py
@@ -13,20 +13,20 @@ def send_growl(options,message=None):
register = gntp.GNTPRegister()
register.add_header('Application-Name',options['app'])
register.add_notification(options['name'],True)
-
+
if options['password']:
register.set_password(options['password'])
-
+
_send(options['host'],options['port'],register.encode(),options['debug'])
-
+
#Send Notification
notice = gntp.GNTPNotice()
-
+
#Required
notice.add_header('Application-Name',options['app'])
notice.add_header('Notification-Name',options['name'])
notice.add_header('Notification-Title',options['title'])
-
+
if options['password']:
notice.set_password(options['password'])
@@ -37,21 +37,21 @@ def send_growl(options,message=None):
notice.add_header('Notification-Priority',options['priority'])
if options['icon']:
notice.add_header('Notification-Icon',options['icon'])
-
+
if message:
notice.add_header('Notification-Text',message)
-
+
_send(options['host'],options['port'],notice.encode(),options['debug'])
def _send(host,port,data,debug=False):
if debug: print '<Sending>\n',data,'\n</Sending>'
-
+
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host,port))
s.send(data)
response = gntp.parse_gntp(s.recv(1024))
s.close()
-
+
if debug: print '<Recieved>\n',response,'\n</Recieved>'
def sendGrowl(title="Sick Beard Notification", message=None, name=None, host=None, password=None):
@@ -77,7 +77,7 @@ def sendGrowl(title="Sick Beard Notification", message=None, name=None, host=Non
opts = {}
opts['name'] = name
-
+
opts['title'] = title
opts['app'] = 'SickBeard'
View
2  sickbeard/notifiers/tweet.py
@@ -39,7 +39,7 @@ def get_authorization():
sickbeard.TWITTER_USERNAME = request_token['oauth_token']
sickbeard.TWITTER_PASSWORD = request_token['oauth_token_secret']
-
+
return AUTHORIZATION_URL+"?oauth_token="+ request_token['oauth_token']
def get_credentials(key):
View
32 sickbeard/notifiers/xbmc.py
@@ -12,7 +12,7 @@
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-#
+#
# You should have received a copy of the GNU General Public License
# along with Sick Beard. If not, see <http://www.gnu.org/licenses/>.
@@ -41,13 +41,13 @@ def sendToXBMC(command, host, username=None, password=None):
command - Dictionary of field/data pairs, encoded via urllib.urlencode and
passed to /xbmcCmds/xbmcHttp
- host - host/ip + port (foo:8080)
+ host - host/ip + port (foo:8080)
'''
if not username:
username = sickbeard.XBMC_USERNAME
if not password:
- password = sickbeard.XBMC_PASSWORD
+ password = sickbeard.XBMC_PASSWORD
for key in command:
if type(command[key]) == unicode:
@@ -87,23 +87,23 @@ def notifyXBMC(input, title="midgetPVR", host=None, username=None, password=None
if not username:
username = sickbeard.XBMC_USERNAME
if not password:
- password = sickbeard.XBMC_PASSWORD
+ password = sickbeard.XBMC_PASSWORD
logger.log(u"Sending notification for " + input, logger.DEBUG)
-
+
fileString = title + "," + input
-
+
for curHost in [x.strip() for x in host.split(",")]:
command = {'command': 'ExecBuiltIn', 'parameter': 'Notification(' +fileString + ')' }
logger.log(u"Sending notification to XBMC via host: "+ curHost +"username: "+ username + " password: " + password, logger.DEBUG)
request = sendToXBMC(command, curHost, username, password)
-
+
def updateLibrary(host, showName=None):
global XBMC_TIMEOUT
logger.log(u"Updating library in XBMC", logger.DEBUG)
-
+
if not host:
logger.log('No host specified, no updates done', logger.DEBUG)
return False
@@ -120,7 +120,7 @@ def updateLibrary(host, showName=None):
sqlCommand = {'command': 'QueryVideoDatabase(%s)' % (pathSql)}
# Set output back to default
resetCommand = {'command': 'SetResponseFormat()'}
-
+
# Set xml response format, if this fails then don't bother with the rest
request = sendToXBMC(xmlCommand, host)
if not request:
@@ -136,11 +136,11 @@ def updateLibrary(host, showName=None):
encSqlXML = urllib.quote(sqlXML,':\\/<>')
et = etree.fromstring(encSqlXML)
paths = et.findall('.//field')
-
+
if not paths:
logger.log(u"No valid paths found for " + showName + " on " + host, logger.DEBUG)
return False
-
+
for path in paths:
# Don't need it double-encoded, gawd this is dumb
unEncPath = urllib.unquote(path.text)
@@ -160,7 +160,7 @@ def updateLibrary(host, showName=None):
if not request:
return False
-
+
return True
# Wake function
@@ -172,16 +172,16 @@ def wakeOnLan(ethernet_address):
int(addr_byte[3], 16),
int(addr_byte[4], 16),
int(addr_byte[5], 16))
-
+
# Build the Wake-On-LAN "Magic Packet"...
msg = '\xff' * 6 + hw_addr * 16
-
+
# ...and send it to the broadcast address using UDP
ss = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
ss.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
ss.sendto(msg, ('<broadcast>', 9))
ss.close()
-
+
# Test Connection function
def isHostUp(host,port):
@@ -199,7 +199,7 @@ def checkHost(host, port):
# we should try to get this programmatically from the IP
mac = ""
-
+
i=1
while isHostUp(host,port)=="Down" and i<4:
wakeOnLan(mac)
View
24 sickbeard/nzbSplitter.py
@@ -4,7 +4,7 @@
import xml.etree
import re
-from lib.tvnamer.utils import FileParser
+from lib.tvnamer.utils import FileParser
from lib.tvnamer import tvnamer_exceptions
from sickbeard import logger, classes, helpers
@@ -21,22 +21,22 @@ def getSeasonNZBs(name, urlData, season):
filename = name.replace(".nzb", "")
nzbElement = showXML.getroot()
-
+
regex = '([\w\._\ ]+)[\. ]S%02d[\. ]([\w\._\-\ ]+)[\- ]([\w_\-\ ]+?)' % season
-
+
sceneNameMatch = re.search(regex, filename, re.I)
- if sceneNameMatch:
+ if sceneNameMatch:
showName, qualitySection, groupName = sceneNameMatch.groups()
else:
logger.log(u"Unable to parse "+name+" into a scene name. If it's a valid one log a bug.", logger.ERROR)
return ({},'')
-
+
regex = '(' + re.escape(showName) + '\.S%02d(?:[E0-9]+)\.[\w\._]+\-\w+' % season + ')'
regex = regex.replace(' ', '.')
epFiles = {}
xmlns = None
-
+
for curFile in nzbElement.getchildren():
xmlnsMatch = re.match("\{(http:\/\/[A-Za-z0-9_\.\/]+\/nzb)\}file", curFile.tag)
if not xmlnsMatch:
@@ -53,14 +53,14 @@ def getSeasonNZBs(name, urlData, season):
else:
epFiles[curEp].append(curFile)
- return (epFiles, xmlns)
+ return (epFiles, xmlns)
def createNZBString(fileElements, xmlns):
rootElement = etree.Element("nzb")
if xmlns:
rootElement.set("xmlns", xmlns)
-
+
for curFile in fileElements:
rootElement.append(stripNS(curFile, xmlns))
@@ -77,7 +77,7 @@ def stripNS(element, ns):
element.tag = element.tag.replace("{"+ns+"}", "")
for curChild in element.getchildren():
stripNS(curChild, ns)
-
+
return element
@@ -88,7 +88,7 @@ def splitResult(result):
except urllib2.URLError, e:
logger.log(u"Unable to load url "+result.url+", can't download season NZB", logger.ERROR)
return False
-
+
# parse the season ep name
try:
fp = FileParser(result.name)
@@ -99,11 +99,11 @@ def splitResult(result):
# bust it up
season = epInfo.seasonnumber if epInfo.seasonnumber != None else 1
-
+
separateNZBs, xmlns = getSeasonNZBs(result.name, urlData, season)
resultList = []
-
+
for newNZB in separateNZBs:
logger.log(u"Split out "+newNZB+" from "+result.name, logger.DEBUG)
View
110 sickbeard/processTV.py
@@ -12,7 +12,7 @@
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-#
+#
# You should have received a copy of the GNU General Public License
# along with Sick Beard. If not, see <http://www.gnu.org/licenses/>.
@@ -78,7 +78,7 @@ def moveFile(srcFile, destFile):
os.unlink(srcFile)
def deleteAssociatedFiles(file):
-
+
if not ek.ek(os.path.isfile, file):
return
@@ -91,19 +91,19 @@ def deleteAssociatedFiles(file):
continue
logger.log(u"Deleting file "+associatedFilePath+" because it is associated with "+file, logger.DEBUG)
ek.ek(os.remove, associatedFilePath)
-
+
def _checkForExistingFile(renamedFilePath, oldFile):
# if the new file exists, return the appropriate code depending on the size
if ek.ek(os.path.isfile, renamedFilePath):
-
+
# see if it's bigger than our old file
if ek.ek(os.path.getsize, renamedFilePath) >= ek.ek(os.path.getsize, oldFile):
return 1
-
+
else:
return -1
-
+
else:
return 0
@@ -111,20 +111,20 @@ def _checkForExistingFile(renamedFilePath, oldFile):
def findInHistory(nzbName):
names = [nzbName, nzbName.rpartition(".")[0]]
-
+
if not nzbName:
return None
-
+
myDB = db.DBConnection()
-
+
for curName in names:
sqlResults = myDB.select("SELECT * FROM history WHERE resource LIKE ?", [re.sub("[\.\-\ ]", "_", curName)])
-
+
if len(sqlResults) == 1:
return (int(sqlResults[0]["showid"]), int(sqlResults[0]["season"]), int(sqlResults[0]["episode"]))
return None
-
+
def logHelper (logMessage, logLevel=logger.MESSAGE):
logger.log(logMessage, logLevel)
@@ -140,7 +140,7 @@ def processDir (dirName, nzbName=None, recurse=False):
# if they passed us a real dir then assume it's the one we want
if ek.ek(os.path.isdir, dirName):
dirName = ek.ek(os.path.realpath, dirName)
-
+
# if they've got a download dir configured then use it
elif sickbeard.TV_DOWNLOAD_DIR and os.path.isdir(sickbeard.TV_DOWNLOAD_DIR) \
and os.path.normpath(dirName) != os.path.normpath(sickbeard.TV_DOWNLOAD_DIR):
@@ -172,7 +172,7 @@ def processDir (dirName, nzbName=None, recurse=False):
return returnStr
fileList = ek.ek(os.listdir, dirName)
-
+
# split the list into video files and folders
folders = filter(lambda x: ek.ek(os.path.isdir, ek.ek(os.path.join, dirName, x)), fileList)
videoFiles = filter(helpers.isMediaFile, fileList)
@@ -186,9 +186,9 @@ def processDir (dirName, nzbName=None, recurse=False):
# process any files in the dir
for movedFilePath in videoFiles:
-
+
movedFilePath = ek.ek(os.path.join, dirName, movedFilePath)
-
+
# if there's only one video file in the dir we can use the dirname to process too
if len(videoFiles) == 1:
returnStr += logHelper("Auto processing file: "+movedFilePath+" ("+dirName+")")
@@ -201,9 +201,9 @@ def processDir (dirName, nzbName=None, recurse=False):
if not sickbeard.KEEP_PROCESSED_DIR and \
os.path.normpath(dirName) != os.path.normpath(sickbeard.TV_DOWNLOAD_DIR) and \
len(remainingFolders) == 0:
-
+
returnStr += logHelper("Deleting folder " + dirName, logger.DEBUG)
-
+
try:
shutil.rmtree(dirName)
except (OSError, IOError), e:
@@ -214,7 +214,7 @@ def processDir (dirName, nzbName=None, recurse=False):
else:
returnStr += result
returnStr += logHelper("Processing failed for "+movedFilePath)
-
+
else:
returnStr += logHelper("Auto processing file: "+movedFilePath)
result = processFile(movedFilePath, None, nzbName)
@@ -226,7 +226,7 @@ def processDir (dirName, nzbName=None, recurse=False):
returnStr += logHelper("Processing failed for "+movedFilePath)
return returnStr
-
+
def processFile(fileName, downloadDir=None, nzbName=None):
@@ -235,7 +235,7 @@ def processFile(fileName, downloadDir=None, nzbName=None):
folderName = None
if downloadDir != None:
folderName = downloadDir.split(os.path.sep)[-1]
-
+
returnStr += logHelper("Processing file "+fileName+" (with folder name "+str(folderName)+" and NZB name "+str(nzbName)+")", logger.DEBUG)
finalNameList = []
@@ -248,11 +248,11 @@ def processFile(fileName, downloadDir=None, nzbName=None):
showResults = None
result = None
-
+
tvdb_id = None
season = None
episodes = []
-
+
# first try looking up every name in our history
for curName in finalNameList:
@@ -266,7 +266,7 @@ def processFile(fileName, downloadDir=None, nzbName=None):
# if that didn't work then try manually parsing and searching them on TVDB
for curName in finalNameList: