From 6aa149752b4a2c08e4b34d8b1ebce4d4bf58ef3a Mon Sep 17 00:00:00 2001 From: Mark Rawson Date: Thu, 3 Jul 2014 07:43:48 +0100 Subject: [PATCH 1/4] Send notifications to all enabled notifiers upon SickRage update. --- sickbeard/common.py | 4 +++ sickbeard/notifiers/__init__.py | 4 +++ sickbeard/notifiers/boxcar.py | 8 +++++- sickbeard/notifiers/boxcar2.py | 8 +++++- sickbeard/notifiers/emailnotify.py | 33 ++++++++++++++++++++++++- sickbeard/notifiers/growl.py | 6 +++++ sickbeard/notifiers/libnotify.py | 5 ++++ sickbeard/notifiers/nma.py | 6 +++++ sickbeard/notifiers/nmj.py | 4 +++ sickbeard/notifiers/nmjv2.py | 4 +++ sickbeard/notifiers/plex.py | 6 +++++ sickbeard/notifiers/prowl.py | 7 ++++++ sickbeard/notifiers/pushalot.py | 8 ++++++ sickbeard/notifiers/pushbullet.py | 6 +++++ sickbeard/notifiers/pushover.py | 8 +++++- sickbeard/notifiers/pytivo.py | 3 +++ sickbeard/notifiers/synoindex.py | 3 +++ sickbeard/notifiers/synologynotifier.py | 6 +++++ sickbeard/notifiers/trakt.py | 3 +++ sickbeard/notifiers/tweet.py | 6 +++++ sickbeard/notifiers/xbmc.py | 6 +++++ sickbeard/versionChecker.py | 11 +++++++-- 22 files changed, 149 insertions(+), 6 deletions(-) diff --git a/sickbeard/common.py b/sickbeard/common.py index fbbf8341..a572926d 100644 --- a/sickbeard/common.py +++ b/sickbeard/common.py @@ -50,11 +50,15 @@ SEASON_RESULT = -2 NOTIFY_SNATCH = 1 NOTIFY_DOWNLOAD = 2 NOTIFY_SUBTITLE_DOWNLOAD = 3 +NOTIFY_SICKRAGE_UPDATE = 4 +NOTIFY_SICKRAGE_UPDATE_TEXT = 5 notifyStrings = {} notifyStrings[NOTIFY_SNATCH] = "Started Download" notifyStrings[NOTIFY_DOWNLOAD] = "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 UNKNOWN = -1 # should never happen diff --git a/sickbeard/notifiers/__init__.py b/sickbeard/notifiers/__init__.py index 99ece634..683cb72c 100644 --- a/sickbeard/notifiers/__init__.py +++ b/sickbeard/notifiers/__init__.py @@ -101,3 +101,7 @@ def notify_subtitle_download(ep_name, lang): def notify_snatch(ep_name): for n in notifiers: n.notify_snatch(ep_name) + +def notify_sickrage_update(new_version = ""): + for n in notifiers: + n.notify_sickrage_update(new_version) diff --git a/sickbeard/notifiers/boxcar.py b/sickbeard/notifiers/boxcar.py index 3787e344..e65b9068 100644 --- a/sickbeard/notifiers/boxcar.py +++ b/sickbeard/notifiers/boxcar.py @@ -23,7 +23,7 @@ import time import sickbeard 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 API_URL = "https://boxcar.io/devices/providers/fWc4sgSmpcN6JujtBmR6/notifications" @@ -122,6 +122,12 @@ class BoxcarNotifier: def notify_subtitle_download(self, ep_name, lang, title=notifyStrings[NOTIFY_SUBTITLE_DOWNLOAD]): if sickbeard.BOXCAR_NOTIFY_ONSUBTITLEDOWNLOAD: 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): """ diff --git a/sickbeard/notifiers/boxcar2.py b/sickbeard/notifiers/boxcar2.py index 07f9cf00..0a727f8f 100755 --- a/sickbeard/notifiers/boxcar2.py +++ b/sickbeard/notifiers/boxcar2.py @@ -24,7 +24,7 @@ import time import sickbeard 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 API_URL = "https://new.boxcar.io/api/notifications" @@ -96,6 +96,12 @@ class Boxcar2Notifier: def notify_subtitle_download(self, ep_name, lang, title=notifyStrings[NOTIFY_SUBTITLE_DOWNLOAD]): if sickbeard.BOXCAR2_NOTIFY_ONSUBTITLEDOWNLOAD: 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): """ diff --git a/sickbeard/notifiers/emailnotify.py b/sickbeard/notifiers/emailnotify.py index 7ad93488..2358d461 100644 --- a/sickbeard/notifiers/emailnotify.py +++ b/sickbeard/notifiers/emailnotify.py @@ -27,7 +27,7 @@ import re import sickbeard -from sickbeard import logger +from sickbeard import logger, common from sickbeard import db from sickbeard.exceptions import ex @@ -141,6 +141,37 @@ class EmailNotifier: 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 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( + "

SickRage Notification - " + title + "

\n

" + update_text + new_version + "

\n\n", + '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): addrs = [] diff --git a/sickbeard/notifiers/growl.py b/sickbeard/notifiers/growl.py index a40141a0..08ff6776 100644 --- a/sickbeard/notifiers/growl.py +++ b/sickbeard/notifiers/growl.py @@ -43,6 +43,12 @@ class GrowlNotifier: def notify_subtitle_download(self, ep_name, lang): if sickbeard.GROWL_NOTIFY_ONSUBTITLEDOWNLOAD: 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): diff --git a/sickbeard/notifiers/libnotify.py b/sickbeard/notifiers/libnotify.py index 2b39db72..c4c72499 100644 --- a/sickbeard/notifiers/libnotify.py +++ b/sickbeard/notifiers/libnotify.py @@ -92,6 +92,11 @@ class LibnotifyNotifier: def notify_subtitle_download(self, ep_name, lang): if sickbeard.LIBNOTIFY_NOTIFY_ONSUBTITLEDOWNLOAD: 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): return self._notify('Test notification', "This is a test notification from SickRage", force=True) diff --git a/sickbeard/notifiers/nma.py b/sickbeard/notifiers/nma.py index 1593e468..25f7d5a6 100644 --- a/sickbeard/notifiers/nma.py +++ b/sickbeard/notifiers/nma.py @@ -23,6 +23,12 @@ class NMA_Notifier: if sickbeard.NMA_NOTIFY_ONSUBTITLEDOWNLOAD: self._sendNMA(nma_api=None, nma_priority=None, event=common.notifyStrings[common.NOTIFY_SUBTITLE_DOWNLOAD], 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): diff --git a/sickbeard/notifiers/nmj.py b/sickbeard/notifiers/nmj.py index 75746ef5..807b36bd 100644 --- a/sickbeard/notifiers/nmj.py +++ b/sickbeard/notifiers/nmj.py @@ -96,6 +96,10 @@ class NMJNotifier: def notify_subtitle_download(self, ep_name, lang): if sickbeard.USE_NMJ: 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): return self._sendNMJ(host, database, mount) diff --git a/sickbeard/notifiers/nmjv2.py b/sickbeard/notifiers/nmjv2.py index 6b9b53f8..fc2f16a0 100644 --- a/sickbeard/notifiers/nmjv2.py +++ b/sickbeard/notifiers/nmjv2.py @@ -42,6 +42,10 @@ class NMJv2Notifier: def notify_subtitle_download(self, ep_name, lang): self._notifyNMJ() + + def notify_sickrage_update(self, new_version): + return False + # Not implemented, no reason to start scanner. def test_notify(self, host): return self._sendNMJ(host) diff --git a/sickbeard/notifiers/plex.py b/sickbeard/notifiers/plex.py index 1e5cbb62..f5be0ba4 100644 --- a/sickbeard/notifiers/plex.py +++ b/sickbeard/notifiers/plex.py @@ -65,6 +65,12 @@ class PLEXNotifier(XBMCNotifier): def notify_subtitle_download(self, ep_name, lang): if sickbeard.PLEX_NOTIFY_ONSUBTITLEDOWNLOAD: 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): return self._notify_pmc("Testing Plex notifications from SickRage", "Test Notification", host, username, diff --git a/sickbeard/notifiers/prowl.py b/sickbeard/notifiers/prowl.py index ce2ecbad..19355839 100644 --- a/sickbeard/notifiers/prowl.py +++ b/sickbeard/notifiers/prowl.py @@ -51,6 +51,13 @@ class ProwlNotifier: if sickbeard.PROWL_NOTIFY_ONSUBTITLEDOWNLOAD: self._sendProwl(prowl_api=None, prowl_priority=None, 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): diff --git a/sickbeard/notifiers/pushalot.py b/sickbeard/notifiers/pushalot.py index b9cf86eb..e0003b49 100644 --- a/sickbeard/notifiers/pushalot.py +++ b/sickbeard/notifiers/pushalot.py @@ -45,6 +45,14 @@ class PushalotNotifier: self._sendPushalot(pushalot_authorizationtoken=None, event=common.notifyStrings[common.NOTIFY_SUBTITLE_DOWNLOAD], 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): diff --git a/sickbeard/notifiers/pushbullet.py b/sickbeard/notifiers/pushbullet.py index d6bed96c..4c0bd84e 100644 --- a/sickbeard/notifiers/pushbullet.py +++ b/sickbeard/notifiers/pushbullet.py @@ -48,6 +48,12 @@ class PushbulletNotifier: if sickbeard.PUSHBULLET_NOTIFY_ONSUBTITLEDOWNLOAD: self._sendPushbullet(pushbullet_api=None, event=common.notifyStrings[common.NOTIFY_SUBTITLE_DOWNLOAD] + " : " + ep_name + " : " + lang, 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, notificationType=None, method=None, force=False): diff --git a/sickbeard/notifiers/pushover.py b/sickbeard/notifiers/pushover.py index 39accd83..9458b18f 100644 --- a/sickbeard/notifiers/pushover.py +++ b/sickbeard/notifiers/pushover.py @@ -23,7 +23,7 @@ import time import sickbeard 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 API_URL = "https://api.pushover.net/1/messages.json" @@ -119,6 +119,12 @@ class PushoverNotifier: def notify_subtitle_download(self, ep_name, lang, title=notifyStrings[NOTIFY_SUBTITLE_DOWNLOAD]): if sickbeard.PUSHOVER_NOTIFY_ONSUBTITLEDOWNLOAD: 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): """ diff --git a/sickbeard/notifiers/pytivo.py b/sickbeard/notifiers/pytivo.py index 4b9aafb2..14a60268 100644 --- a/sickbeard/notifiers/pytivo.py +++ b/sickbeard/notifiers/pytivo.py @@ -36,6 +36,9 @@ class pyTivoNotifier: def notify_subtitle_download(self, ep_name, lang): pass + + def notify_sickrage_update(self, new_version): + pass def update_library(self, ep_obj): diff --git a/sickbeard/notifiers/synoindex.py b/sickbeard/notifiers/synoindex.py index 96ff111f..10c46636 100644 --- a/sickbeard/notifiers/synoindex.py +++ b/sickbeard/notifiers/synoindex.py @@ -37,6 +37,9 @@ class synoIndexNotifier: def notify_subtitle_download(self, ep_name, lang): pass + + def notify_sickrage_update(self, new_version): + pass def moveFolder(self, old_path, new_path): self.moveObject(old_path, new_path) diff --git a/sickbeard/notifiers/synologynotifier.py b/sickbeard/notifiers/synologynotifier.py index 54fc45ca..cb722e85 100644 --- a/sickbeard/notifiers/synologynotifier.py +++ b/sickbeard/notifiers/synologynotifier.py @@ -40,6 +40,12 @@ class synologyNotifier: def notify_subtitle_download(self, ep_name, lang): if sickbeard.SYNOLOGYNOTIFIER_NOTIFY_ONSUBTITLEDOWNLOAD: 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): synodsmnotify_cmd = ["/usr/syno/bin/synodsmnotify", "@administrators", title, message] diff --git a/sickbeard/notifiers/trakt.py b/sickbeard/notifiers/trakt.py index 1e79fa25..890856a6 100644 --- a/sickbeard/notifiers/trakt.py +++ b/sickbeard/notifiers/trakt.py @@ -34,6 +34,9 @@ class TraktNotifier: def notify_subtitle_download(self, ep_name, lang): pass + + def notify_sickrage_update(self, new_version): + pass def update_library(self, ep_obj): """ diff --git a/sickbeard/notifiers/tweet.py b/sickbeard/notifiers/tweet.py index e010f7c0..ebfd2251 100644 --- a/sickbeard/notifiers/tweet.py +++ b/sickbeard/notifiers/tweet.py @@ -51,6 +51,12 @@ class TwitterNotifier: def notify_subtitle_download(self, ep_name, lang): if sickbeard.TWITTER_NOTIFY_ONSUBTITLEDOWNLOAD: 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): return self._notifyTwitter("This is a test notification from SickRage", force=True) diff --git a/sickbeard/notifiers/xbmc.py b/sickbeard/notifiers/xbmc.py index d1ce8adc..a433402b 100644 --- a/sickbeard/notifiers/xbmc.py +++ b/sickbeard/notifiers/xbmc.py @@ -512,6 +512,12 @@ class XBMCNotifier: def notify_subtitle_download(self, ep_name, lang): if sickbeard.XBMC_NOTIFY_ONSUBTITLEDOWNLOAD: 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): return self._notify_xbmc("Testing XBMC notifications from SickRage", "Test Notification", host, username, diff --git a/sickbeard/versionChecker.py b/sickbeard/versionChecker.py index 59215eff..2aea8e25 100644 --- a/sickbeard/versionChecker.py +++ b/sickbeard/versionChecker.py @@ -30,7 +30,7 @@ import gh_api as github import threading import sickbeard -from sickbeard import helpers +from sickbeard import helpers, notifiers from sickbeard import version, ui from sickbeard import logger from sickbeard.exceptions import ex @@ -260,6 +260,9 @@ class WindowsUpdateManager(UpdateManager): new_update_path = os.path.join(sickbeard.PROG_DIR, u'updater.exe') logger.log(u"Copying new update.exe file from " + old_update_path + " to " + 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: logger.log(u"Error while trying to update: " + ex(e), logger.ERROR) @@ -412,7 +415,6 @@ class GitUpdateManager(UpdateManager): 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_ahead = 0 @@ -510,6 +512,8 @@ class GitUpdateManager(UpdateManager): output, err, exit_status = self._run_git(self._git_path, 'pull origin ' + self.branch) # @UnusedVariable if exit_status == 0: + # Notify update successful + notifiers.notify_sickrage_update(self._newest_commit_hash[:10]) return True return False @@ -715,4 +719,7 @@ class SourceUpdateManager(UpdateManager): logger.log(u"Traceback: " + traceback.format_exc(), logger.DEBUG) return False + # Notify update successful + notifiers.notify_sickrage_update(sickbeard.NEWEST_VERSION_STRING) + return True From 8f19e84a8011eeda13080990814e31b37381a2bf Mon Sep 17 00:00:00 2001 From: Mark Rawson Date: Thu, 3 Jul 2014 08:16:15 +0100 Subject: [PATCH 2/4] Add global option to disable SickRage update notifications via notifiers. --- gui/slick/interfaces/default/config_general.tmpl | 9 ++++++++- sickbeard/__init__.py | 5 ++++- sickbeard/notifiers/__init__.py | 5 +++-- sickbeard/webserve.py | 3 ++- 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/gui/slick/interfaces/default/config_general.tmpl b/gui/slick/interfaces/default/config_general.tmpl index ab63a537..4973f89b 100644 --- a/gui/slick/interfaces/default/config_general.tmpl +++ b/gui/slick/interfaces/default/config_general.tmpl @@ -92,13 +92,20 @@ +
+ + +
diff --git a/sickbeard/__init__.py b/sickbeard/__init__.py index 70ccffab..46491d9a 100644 --- a/sickbeard/__init__.py +++ b/sickbeard/__init__.py @@ -100,6 +100,7 @@ NEWEST_VERSION = None NEWEST_VERSION_STRING = None VERSION_NOTIFY = None AUTO_UPDATE = None +NOTIFY_ON_UPDATE = None CUR_COMMIT_HASH = None 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_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, \ - 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, \ 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, \ @@ -589,6 +590,7 @@ def initialize(consoleLogging=True): STATUS_DEFAULT = check_setting_int(CFG, 'General', 'status_default', SKIPPED) VERSION_NOTIFY = check_setting_int(CFG, 'General', 'version_notify', 1) 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)) INDEXER_DEFAULT = check_setting_int(CFG, 'General', 'indexer_default', 0) INDEXER_TIMEOUT = check_setting_int(CFG, 'General', 'indexer_timeout', 10) @@ -1388,6 +1390,7 @@ def save_config(): new_config['General']['provider_order'] = ' '.join(PROVIDER_ORDER) new_config['General']['version_notify'] = int(VERSION_NOTIFY) 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_pattern'] = NAMING_PATTERN new_config['General']['naming_custom_abd'] = int(NAMING_CUSTOM_ABD) diff --git a/sickbeard/notifiers/__init__.py b/sickbeard/notifiers/__init__.py index 683cb72c..702e4100 100644 --- a/sickbeard/notifiers/__init__.py +++ b/sickbeard/notifiers/__init__.py @@ -103,5 +103,6 @@ def notify_snatch(ep_name): n.notify_snatch(ep_name) def notify_sickrage_update(new_version = ""): - for n in notifiers: - n.notify_sickrage_update(new_version) + if sickbeard.NOTIFY_ON_UPDATE: + for n in notifiers: + n.notify_sickrage_update(new_version) diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py index d76199fd..a97b8304 100644 --- a/sickbeard/webserve.py +++ b/sickbeard/webserve.py @@ -1401,7 +1401,7 @@ class ConfigGeneral(MainHandler): 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, 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, fuzzy_dating=None, trim_zero=None, date_preset=None, date_preset_na=None, time_preset=None, indexer_timeout=None): @@ -1412,6 +1412,7 @@ class ConfigGeneral(MainHandler): sickbeard.LAUNCH_BROWSER = config.checkbox_to_value(launch_browser) config.change_VERSION_NOTIFY(config.checkbox_to_value(version_notify)) sickbeard.AUTO_UPDATE = config.checkbox_to_value(auto_update) + sickbeard.NOTIFY_ON_UPDATE = config.checkbox_to_value(notify_on_update) # sickbeard.LOG_DIR is set in config.change_LOG_DIR() sickbeard.UPDATE_SHOWS_ON_START = config.checkbox_to_value(update_shows_on_start) From f0146f728e69282dc22b6d32b53cd0fb2960cca8 Mon Sep 17 00:00:00 2001 From: echel0n Date: Thu, 3 Jul 2014 07:07:07 -0700 Subject: [PATCH 3/4] Lowered CPU usage even further, re-wrote daemonizer code for startups, removed misc unrequired functions from providers. --- SickBeard.py | 142 ++++++++++++++------- lib/daemon.py | 183 ---------------------------- sickbeard/__init__.py | 11 -- sickbeard/dailysearcher.py | 3 - sickbeard/name_parser/parser.py | 10 -- sickbeard/providers/btn.py | 8 +- sickbeard/providers/ezrss.py | 6 - sickbeard/providers/fanzub.py | 6 - sickbeard/providers/generic.py | 11 +- sickbeard/providers/hdbits.py | 8 +- sickbeard/providers/hdtorrents.py | 8 +- sickbeard/providers/iptorrents.py | 8 +- sickbeard/providers/kat.py | 8 +- sickbeard/providers/newzbin.py | 9 -- sickbeard/providers/newznab.py | 8 +- sickbeard/providers/nextgen.py | 8 +- sickbeard/providers/nyaatorrents.py | 6 - sickbeard/providers/omgwtfnzbs.py | 6 - sickbeard/providers/publichd.py | 8 +- sickbeard/providers/rsstorrent.py | 6 - sickbeard/providers/scc.py | 8 +- sickbeard/providers/speedcd.py | 8 +- sickbeard/providers/thepiratebay.py | 11 +- sickbeard/providers/torrentday.py | 8 +- sickbeard/providers/torrentleech.py | 8 +- sickbeard/providers/tvtorrents.py | 6 - sickbeard/providers/womble.py | 8 +- 27 files changed, 116 insertions(+), 404 deletions(-) delete mode 100644 lib/daemon.py diff --git a/SickBeard.py b/SickBeard.py index 64876036..00d0a84d 100755 --- a/SickBeard.py +++ b/SickBeard.py @@ -67,7 +67,6 @@ from sickbeard.databases.mainDB import MIN_DB_VERSION from sickbeard.databases.mainDB import MAX_DB_VERSION from lib.configobj import ConfigObj -from daemon import Daemon signal.signal(signal.SIGINT, 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): - 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): - self.daemon = None self.webserver = None self.runAsDaemon = False self.CREATEPID = False @@ -288,8 +251,7 @@ class SickRage(object): sickbeard.initialize(consoleLogging=self.consoleLogging) if self.runAsDaemon: - self.daemon = Daemon(self.PIDFILE or os.path.join(sickbeard.DATA_DIR, 'sickbeard.pid')) - self.daemon.daemonize() + self.daemonize() # Get PID sickbeard.PID = os.getpid() @@ -361,6 +323,104 @@ class SickRage(object): while(sickbeard.started): 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 sys.hexversion >= 0x020600F0: freeze_support() @@ -379,8 +439,8 @@ if __name__ == "__main__": sr.webserver = None # if run as daemon delete the pidfile - if sr.runAsDaemon: - sr.daemon.delpid() + if sr.runAsDaemon and sr.CREATEPID: + sr.remove_pid_file(sr.PIDFILE) if not sickbeard.shutdown: install_type = sickbeard.versionCheckScheduler.action.install_type diff --git a/lib/daemon.py b/lib/daemon.py deleted file mode 100644 index 77c435b1..00000000 --- a/lib/daemon.py +++ /dev/null @@ -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(). - """ \ No newline at end of file diff --git a/sickbeard/__init__.py b/sickbeard/__init__.py index 46491d9a..218466b8 100644 --- a/sickbeard/__init__.py +++ b/sickbeard/__init__.py @@ -1274,17 +1274,6 @@ def halt(): __INITIALIZED__ = 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): if type(signum) != type(None): logger.log(u"Signal %i caught, saving and exiting..." % int(signum)) diff --git a/sickbeard/dailysearcher.py b/sickbeard/dailysearcher.py index 3559f371..967d3a47 100644 --- a/sickbeard/dailysearcher.py +++ b/sickbeard/dailysearcher.py @@ -36,9 +36,6 @@ class DailySearcher(): self.amActive = False - def __del__(self): - pass - def run(self, force=False): self.amActive = True diff --git a/sickbeard/name_parser/parser.py b/sickbeard/name_parser/parser.py index b1565dc2..055cf9f0 100644 --- a/sickbeard/name_parser/parser.py +++ b/sickbeard/name_parser/parser.py @@ -45,9 +45,6 @@ class NameParser(object): self.convert = convert self.naming_pattern = naming_pattern - def __del__(self): - pass - def clean_series_name(self, series_name): """Cleans up series name by removing any . and _ characters, along with any trailing hyphens. @@ -446,9 +443,6 @@ class ParseResult(object): self.show = show self.score = score - def __del__(self): - pass - def __eq__(self, other): if not other: return False @@ -624,11 +618,7 @@ class NameParserCache(object): logger.log("Using cached parse result for: " + name, logger.DEBUG) return self._previous_parsed[name] - def __del__(self): - pass - name_parser_cache = NameParserCache() - class InvalidNameException(Exception): "The given name is not valid" \ No newline at end of file diff --git a/sickbeard/providers/btn.py b/sickbeard/providers/btn.py index 1fd17210..5dca36ea 100644 --- a/sickbeard/providers/btn.py +++ b/sickbeard/providers/btn.py @@ -49,9 +49,6 @@ class BTNProvider(generic.TorrentProvider): self.url = "http://api.btnapps.net" - def __del__(self): - pass - def isEnabled(self): return self.enabled @@ -318,9 +315,6 @@ class BTNCache(tvcache.TVCache): # At least 15 minutes between queries self.minTime = 15 - def __del__(self): - pass - def updateCache(self): # delete anything older then 7 days @@ -349,7 +343,7 @@ class BTNCache(tvcache.TVCache): if ci is not None: cl.append(ci) - time.sleep(.2) + if cl: myDB = self._getDB() diff --git a/sickbeard/providers/ezrss.py b/sickbeard/providers/ezrss.py index 4d594c5f..316f83e0 100644 --- a/sickbeard/providers/ezrss.py +++ b/sickbeard/providers/ezrss.py @@ -47,9 +47,6 @@ class EZRSSProvider(generic.TorrentProvider): self.url = 'https://www.ezrss.it/' - def __del__(self): - pass - def isEnabled(self): return self.enabled @@ -181,9 +178,6 @@ class EZRSSCache(tvcache.TVCache): # only poll EZRSS every 15 minutes max self.minTime = 15 - def __del__(self): - pass - def _getRSSData(self): rss_url = self.provider.url + 'feed/' diff --git a/sickbeard/providers/fanzub.py b/sickbeard/providers/fanzub.py index 27c61bbb..0f58825c 100644 --- a/sickbeard/providers/fanzub.py +++ b/sickbeard/providers/fanzub.py @@ -45,9 +45,6 @@ class Fanzub(generic.NZBProvider): self.url = 'http://fanzub.com/' - def __del__(self): - pass - def isEnabled(self): return self.enabled @@ -134,9 +131,6 @@ class FanzubCache(tvcache.TVCache): # we get 100 post each call ! self.minTime = 20 - def __del__(self): - pass - def _getRSSData(self): params = {"cat": "anime".encode('utf-8'), diff --git a/sickbeard/providers/generic.py b/sickbeard/providers/generic.py index 599d0233..a103364e 100644 --- a/sickbeard/providers/generic.py +++ b/sickbeard/providers/generic.py @@ -68,9 +68,6 @@ class GenericProvider: 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'}) - def __del__(self): - pass - def getID(self): return GenericProvider.makeID(self.name) @@ -409,14 +406,8 @@ class NZBProvider(GenericProvider): self.providerType = GenericProvider.NZB - def __del__(self): - pass - class TorrentProvider(GenericProvider): def __init__(self, name): GenericProvider.__init__(self, name) - self.providerType = GenericProvider.TORRENT - - def __del__(self): - pass + self.providerType = GenericProvider.TORRENT \ No newline at end of file diff --git a/sickbeard/providers/hdbits.py b/sickbeard/providers/hdbits.py index 8821f0e2..6dd79c92 100644 --- a/sickbeard/providers/hdbits.py +++ b/sickbeard/providers/hdbits.py @@ -55,9 +55,6 @@ class HDBitsProvider(generic.TorrentProvider): self.rss_url = 'http://hdbits.org/api/torrents' self.download_url = 'http://hdbits.org/download.php?' - def __del__(self): - pass - def isEnabled(self): return self.enabled @@ -217,9 +214,6 @@ class HDBitsCache(tvcache.TVCache): # only poll HDBits every 15 minutes max self.minTime = 15 - def __del__(self): - pass - def updateCache(self): # delete anything older then 7 days @@ -260,7 +254,7 @@ class HDBitsCache(tvcache.TVCache): if ci is not None: ql.append(ci) - time.sleep(.2) + if ql: myDB = self._getDB() diff --git a/sickbeard/providers/hdtorrents.py b/sickbeard/providers/hdtorrents.py index 9f9fa2e9..d17d1129 100644 --- a/sickbeard/providers/hdtorrents.py +++ b/sickbeard/providers/hdtorrents.py @@ -73,9 +73,6 @@ class HDTorrentsProvider(generic.TorrentProvider): self.cookies = None - def __del__(self): - pass - def isEnabled(self): return self.enabled @@ -354,9 +351,6 @@ class HDTorrentsCache(tvcache.TVCache): # only poll HDTorrents every 10 minutes max self.minTime = 20 - def __del__(self): - pass - def updateCache(self): # delete anything older then 7 days @@ -382,7 +376,7 @@ class HDTorrentsCache(tvcache.TVCache): if ci is not None: cl.append(ci) - time.sleep(.2) + if cl: myDB = self._getDB() diff --git a/sickbeard/providers/iptorrents.py b/sickbeard/providers/iptorrents.py index 39ec76d0..74fbe79a 100644 --- a/sickbeard/providers/iptorrents.py +++ b/sickbeard/providers/iptorrents.py @@ -65,9 +65,6 @@ class IPTorrentsProvider(generic.TorrentProvider): self.categorie = 'l73=1&l78=1&l66=1&l65=1&l79=1&l5=1&l4=1' - def __del__(self): - pass - def isEnabled(self): return self.enabled @@ -295,9 +292,6 @@ class IPTorrentsCache(tvcache.TVCache): # Only poll IPTorrents every 10 minutes max self.minTime = 10 - def __del__(self): - pass - def updateCache(self): # delete anything older then 7 days @@ -323,7 +317,7 @@ class IPTorrentsCache(tvcache.TVCache): if ci is not None: cl.append(ci) - time.sleep(.2) + if cl: myDB = self._getDB() diff --git a/sickbeard/providers/kat.py b/sickbeard/providers/kat.py index 69080ca9..55278376 100644 --- a/sickbeard/providers/kat.py +++ b/sickbeard/providers/kat.py @@ -68,9 +68,6 @@ class KATProvider(generic.TorrentProvider): self.searchurl = self.url + 'usearch/%s/?field=seeders&sorder=desc' #order by seed - def __del__(self): - pass - def isEnabled(self): return self.enabled @@ -433,9 +430,6 @@ class KATCache(tvcache.TVCache): # only poll ThePirateBay every 10 minutes max self.minTime = 20 - def __del__(self): - pass - def updateCache(self): # delete anything older then 7 days @@ -460,7 +454,7 @@ class KATCache(tvcache.TVCache): if ci is not None: cl.append(ci) - time.sleep(.2) + if cl: myDB = self._getDB() diff --git a/sickbeard/providers/newzbin.py b/sickbeard/providers/newzbin.py index 685afc4b..bdf4b31e 100644 --- a/sickbeard/providers/newzbin.py +++ b/sickbeard/providers/newzbin.py @@ -40,9 +40,6 @@ class NewzbinDownloader(urllib.FancyURLopener): def __init__(self): urllib.FancyURLopener.__init__(self) - def __del__(self): - pass - def http_error_default(self, url, fp, errcode, errmsg, headers): # 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' - def __del__(self): - pass - def isEnabled(self): return sickbeard.NEWZBIN @@ -340,9 +334,6 @@ class NewzbinCache(tvcache.TVCache): # only poll Newzbin every 10 mins max self.minTime = 1 - def __del__(self): - pass - def _getRSSData(self): return self.provider._getRSSData() diff --git a/sickbeard/providers/newznab.py b/sickbeard/providers/newznab.py index b40fab34..a3ed5abe 100755 --- a/sickbeard/providers/newznab.py +++ b/sickbeard/providers/newznab.py @@ -69,9 +69,6 @@ class NewznabProvider(generic.NZBProvider): self.default = False - def __del__(self): - pass - def configStr(self): 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 self.minTime = 15 - def __del__(self): - pass - def _getRSSData(self): params = {"t": "tvsearch", @@ -347,7 +341,7 @@ class NewznabCache(tvcache.TVCache): if ci is not None: ql.append(ci) - time.sleep(.2) + if ql: myDB = self._getDB() diff --git a/sickbeard/providers/nextgen.py b/sickbeard/providers/nextgen.py index 79430263..96dc225d 100644 --- a/sickbeard/providers/nextgen.py +++ b/sickbeard/providers/nextgen.py @@ -71,9 +71,6 @@ class NextGenProvider(generic.TorrentProvider): self.login_opener = None - def __del__(self): - pass - def isEnabled(self): return self.enabled @@ -344,9 +341,6 @@ class NextGenCache(tvcache.TVCache): # Only poll NextGen every 10 minutes max self.minTime = 10 - def __del__(self): - pass - def updateCache(self): # delete anything older then 7 days @@ -372,7 +366,7 @@ class NextGenCache(tvcache.TVCache): if ci is not None: cl.append(ci) - time.sleep(.2) + if cl: myDB = self._getDB() diff --git a/sickbeard/providers/nyaatorrents.py b/sickbeard/providers/nyaatorrents.py index 719feaee..23580ba9 100644 --- a/sickbeard/providers/nyaatorrents.py +++ b/sickbeard/providers/nyaatorrents.py @@ -45,9 +45,6 @@ class NyaaProvider(generic.TorrentProvider): self.url = 'http://www.nyaa.se/' - def __del__(self): - pass - def isEnabled(self): return self.enabled @@ -130,9 +127,6 @@ class NyaaCache(tvcache.TVCache): # only poll NyaaTorrents every 15 minutes max self.minTime = 15 - def __del__(self): - pass - def _getRSSData(self): params = { "page": 'rss', # Use RSS page diff --git a/sickbeard/providers/omgwtfnzbs.py b/sickbeard/providers/omgwtfnzbs.py index 7da7fdf3..d3fc8f1e 100644 --- a/sickbeard/providers/omgwtfnzbs.py +++ b/sickbeard/providers/omgwtfnzbs.py @@ -49,9 +49,6 @@ class OmgwtfnzbsProvider(generic.NZBProvider): self.url = 'https://omgwtfnzbs.org/' self.supportsBacklog = True - def __del__(self): - pass - def isEnabled(self): return self.enabled @@ -160,9 +157,6 @@ class OmgwtfnzbsCache(tvcache.TVCache): tvcache.TVCache.__init__(self, provider) self.minTime = 20 - def __del__(self): - pass - def _getRSSData(self): params = {'user': provider.username, 'api': provider.api_key, diff --git a/sickbeard/providers/publichd.py b/sickbeard/providers/publichd.py index c280e43e..38aa9b24 100644 --- a/sickbeard/providers/publichd.py +++ b/sickbeard/providers/publichd.py @@ -67,9 +67,6 @@ class PublicHDProvider(generic.TorrentProvider): self.categories = {'Season': ['23'], 'Episode': ['7', '14', '24'], 'RSS': ['7', '14', '23', '24']} - def __del__(self): - pass - def isEnabled(self): return self.enabled @@ -317,9 +314,6 @@ class PublicHDCache(tvcache.TVCache): # only poll ThePirateBay every 10 minutes max self.minTime = 20 - def __del__(self): - pass - def updateCache(self): # delete anything older then 7 days @@ -345,7 +339,7 @@ class PublicHDCache(tvcache.TVCache): if ci is not None: ql.append(ci) - time.sleep(.2) + if ql: myDB = self._getDB() diff --git a/sickbeard/providers/rsstorrent.py b/sickbeard/providers/rsstorrent.py index 3aac4d8d..64d6e64d 100644 --- a/sickbeard/providers/rsstorrent.py +++ b/sickbeard/providers/rsstorrent.py @@ -52,9 +52,6 @@ class TorrentRssProvider(generic.TorrentProvider): else: self.cookies = '' - def __del__(self): - pass - 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)) @@ -173,9 +170,6 @@ class TorrentRssCache(tvcache.TVCache): tvcache.TVCache.__init__(self, provider) self.minTime = 15 - def __del__(self): - pass - def _getRSSData(self): logger.log(u"TorrentRssCache cache update URL: " + self.provider.url, logger.DEBUG) if self.provider.cookies: diff --git a/sickbeard/providers/scc.py b/sickbeard/providers/scc.py index b056e3e4..f8f71d73 100644 --- a/sickbeard/providers/scc.py +++ b/sickbeard/providers/scc.py @@ -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'} - def __del__(self): - pass - def isEnabled(self): return self.enabled @@ -339,9 +336,6 @@ class SCCCache(tvcache.TVCache): # only poll SCC every 10 minutes max self.minTime = 20 - def __del__(self): - pass - def updateCache(self): # delete anything older then 7 days @@ -367,7 +361,7 @@ class SCCCache(tvcache.TVCache): if ci is not None: cl.append(ci) - time.sleep(.2) + if cl: myDB = self._getDB() diff --git a/sickbeard/providers/speedcd.py b/sickbeard/providers/speedcd.py index 0809620d..bb0c385b 100644 --- a/sickbeard/providers/speedcd.py +++ b/sickbeard/providers/speedcd.py @@ -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}} - def __del__(self): - pass - def isEnabled(self): return self.enabled @@ -279,9 +276,6 @@ class SpeedCDCache(tvcache.TVCache): # only poll Speedcd every 20 minutes max self.minTime = 20 - def __del__(self): - pass - def updateCache(self): # delete anything older then 7 days @@ -307,7 +301,7 @@ class SpeedCDCache(tvcache.TVCache): if ci is not None: ql.append(ci) - time.sleep(.2) + if ql: myDB = self._getDB() diff --git a/sickbeard/providers/thepiratebay.py b/sickbeard/providers/thepiratebay.py index 5e4c2653..7478e6da 100644 --- a/sickbeard/providers/thepiratebay.py +++ b/sickbeard/providers/thepiratebay.py @@ -67,9 +67,6 @@ class ThePirateBayProvider(generic.TorrentProvider): self.re_title_url = '/torrent/(?P\d+)/(?P.*?)//1".+?(?P<url>magnet.*?)//1".+?(?P<seeders>\d+)</td>.+?(?P<leechers>\d+)</td>' - def __del__(self): - pass - def isEnabled(self): return self.enabled @@ -410,9 +407,6 @@ class ThePirateBayCache(tvcache.TVCache): # only poll ThePirateBay every 10 minutes max self.minTime = 20 - def __del__(self): - pass - def updateCache(self): # delete anything older then 7 days @@ -438,7 +432,7 @@ class ThePirateBayCache(tvcache.TVCache): if ci is not None: cl.append(ci) - time.sleep(.2) + if cl: myDB = self._getDB() @@ -477,9 +471,6 @@ class ThePirateBayWebproxy: 'Hiload.org (NL)': 'http://hiload.org/', } - def __del__(self): - pass - def isEnabled(self): """ Return True if we Choose to call TPB via Proxy """ return self.enabled diff --git a/sickbeard/providers/torrentday.py b/sickbeard/providers/torrentday.py index 3e7da459..bc19d1ee 100644 --- a/sickbeard/providers/torrentday.py +++ b/sickbeard/providers/torrentday.py @@ -72,9 +72,6 @@ class TorrentDayProvider(generic.TorrentProvider): 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}} - def __del__(self): - pass - def isEnabled(self): return self.enabled @@ -303,9 +300,6 @@ class TorrentDayCache(tvcache.TVCache): # Only poll IPTorrents every 10 minutes max self.minTime = 10 - def __del__(self): - pass - def updateCache(self): # delete anything older then 7 days @@ -331,7 +325,7 @@ class TorrentDayCache(tvcache.TVCache): if ci is not None: cl.append(ci) - time.sleep(.2) + if cl: myDB = self._getDB() diff --git a/sickbeard/providers/torrentleech.py b/sickbeard/providers/torrentleech.py index 56e33227..90fece4d 100644 --- a/sickbeard/providers/torrentleech.py +++ b/sickbeard/providers/torrentleech.py @@ -67,9 +67,6 @@ class TorrentLeechProvider(generic.TorrentProvider): self.categories = "2,26,27,32" - def __del__(self): - pass - def isEnabled(self): return self.enabled @@ -298,9 +295,6 @@ class TorrentLeechCache(tvcache.TVCache): # only poll TorrentLeech every 20 minutes max self.minTime = 20 - def __del__(self): - pass - def updateCache(self): # delete anything older then 7 days @@ -326,7 +320,7 @@ class TorrentLeechCache(tvcache.TVCache): if ci is not None: cl.append(ci) - time.sleep(.2) + if cl: myDB = self._getDB() diff --git a/sickbeard/providers/tvtorrents.py b/sickbeard/providers/tvtorrents.py index c743dc30..fbbc17dd 100644 --- a/sickbeard/providers/tvtorrents.py +++ b/sickbeard/providers/tvtorrents.py @@ -47,9 +47,6 @@ class TvTorrentsProvider(generic.TorrentProvider): self.url = 'http://www.tvtorrents.com/' - def __del__(self): - pass - def isEnabled(self): return self.enabled @@ -89,9 +86,6 @@ class TvTorrentsCache(tvcache.TVCache): # only poll TvTorrents every 15 minutes max self.minTime = 15 - def __del__(self): - pass - def _getRSSData(self): # These will be ignored on the serverside. ignore_regex = "all.month|month.of|season[\s\d]*complete" diff --git a/sickbeard/providers/womble.py b/sickbeard/providers/womble.py index 10f38e45..afc93741 100644 --- a/sickbeard/providers/womble.py +++ b/sickbeard/providers/womble.py @@ -32,9 +32,6 @@ class WombleProvider(generic.NZBProvider): self.cache = WombleCache(self) self.url = 'http://newshost.co.za/' - def __del__(self): - pass - def isEnabled(self): return self.enabled @@ -45,9 +42,6 @@ class WombleCache(tvcache.TVCache): # only poll Womble's Index every 15 minutes max self.minTime = 15 - def __del__(self): - pass - def updateCache(self): # delete anything older then 7 days @@ -74,7 +68,7 @@ class WombleCache(tvcache.TVCache): if ci is not None: cl.append(ci) - time.sleep(.2) + if cl: myDB = self._getDB() From 56e2c28badd787ed33c93712e253b499bf8a27c4 Mon Sep 17 00:00:00 2001 From: echel0n <justin.tabish@gmail.com> Date: Thu, 3 Jul 2014 10:30:15 -0700 Subject: [PATCH 4/4] SickRage now uses a internal name cache comprised of (showlist, scene exceptions, scene names) used to search and create show objects from which is needed for parsing search results. Scene exceptions now uses a internal cache for scene exceptions and scene season exceptions, helps reduce overhead to DB and performs faster lookups when making scene exception requests. --- sickbeard/dailysearcher.py | 3 -- sickbeard/db.py | 4 ++ sickbeard/helpers.py | 28 +++-------- sickbeard/maintenance.py | 11 +++-- sickbeard/name_cache.py | 89 +++++++++++++++++++++++++---------- sickbeard/providers/btn.py | 2 - sickbeard/scene_exceptions.py | 48 +++++++++++++------ sickbeard/show_queue.py | 6 +-- sickbeard/tvcache.py | 2 - 9 files changed, 118 insertions(+), 75 deletions(-) diff --git a/sickbeard/dailysearcher.py b/sickbeard/dailysearcher.py index 967d3a47..ac528d1e 100644 --- a/sickbeard/dailysearcher.py +++ b/sickbeard/dailysearcher.py @@ -107,9 +107,6 @@ class DailySearcher(): for show in todaysEps: 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) sickbeard.searchQueueScheduler.action.add_item(dailysearch_queue_item) else: diff --git a/sickbeard/db.py b/sickbeard/db.py index 92f6d917..c42c675c 100644 --- a/sickbeard/db.py +++ b/sickbeard/db.py @@ -164,6 +164,8 @@ class DBConnection(object): logger.log(u"Fatal error executing query: " + ex(e), logger.ERROR) raise + time.sleep(0.05) + return sqlResult 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) raise + time.sleep(0.05) + return sqlResult def select(self, query, args=None): diff --git a/sickbeard/helpers.py b/sickbeard/helpers.py index 18f1133a..e1b943a0 100644 --- a/sickbeard/helpers.py +++ b/sickbeard/helpers.py @@ -730,7 +730,6 @@ def sanitizeSceneName(name, ezrss=False): """ if name: - if not ezrss: bad_chars = u",:()'!?\u2019" # 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): - name = full_sanitizeSceneName(name) - try: # check cache for show showObj = sickbeard.name_cache.retrieveShowFromCache(name) if showObj: return showObj - if not showObj and sickbeard.showList: - db_indexerid = searchDBForShow(name) - if db_indexerid: - showObj = findCertainShow(sickbeard.showList, db_indexerid) - - 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)) + if useIndexer and sickbeard.showList and not showObj: + (sn, idx, id) = searchIndexerForShowID(full_sanitizeSceneName(name), ui=classes.ShowListUI) + if id: + showObj = findCertainShow(sickbeard.showList, int(id)) # add show to cache if showObj: sickbeard.name_cache.addNameToCache(name, showObj.indexerid) + + return showObj except: - showObj = None - - return showObj - + pass def is_hidden_folder(folder): """ diff --git a/sickbeard/maintenance.py b/sickbeard/maintenance.py index 9bce6481..ccc3f871 100644 --- a/sickbeard/maintenance.py +++ b/sickbeard/maintenance.py @@ -23,7 +23,7 @@ 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): @@ -31,15 +31,18 @@ class Maintenance(): self.amActive = False - def __del__(self): - pass - 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() diff --git a/sickbeard/name_cache.py b/sickbeard/name_cache.py index cdcd351a..6661b89d 100644 --- a/sickbeard/name_cache.py +++ b/sickbeard/name_cache.py @@ -22,6 +22,8 @@ from sickbeard import db from sickbeard.helpers import sanitizeSceneName from sickbeard import logger +nameCache = None + def addNameToCache(name, indexer_id=0): """ 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 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 - name = sanitizeSceneName(name) - myDB = db.DBConnection('cache.db') - myDB.action("INSERT INTO scene_names (indexer_id, name) VALUES (?, ?)", [indexer_id, name]) + name = sickbeard.helpers.full_sanitizeSceneName(name) + if name not in nameCache: + nameCache[name] = int(indexer_id) + cacheDB.action("INSERT OR REPLACE INTO scene_names (indexer_id, name) VALUES (?, ?)", [indexer_id, 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 """ + global nameCache - cache_results = None - - # standardize the name we're using to account for small differences in providers - 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"]) + name = sickbeard.helpers.full_sanitizeSceneName(name) + if name in nameCache: + return int(nameCache[name]) def retrieveShowFromCache(name): - indexerid = retrieveNameFromCache(name) - if indexerid: - return sickbeard.helpers.findCertainShow(sickbeard.showList, int(indexerid)) + global nameCache -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). """ + global nameCache - myDB = db.DBConnection('cache.db') - if show: - showNames = sickbeard.show_name_helpers.allPossibleShowNames(show, season=season) - for showName in showNames: - myDB.action("DELETE FROM scene_names WHERE name = ? and indexer_id = ?", [showName, indexer_id]) - else: - myDB.action("DELETE FROM scene_names WHERE indexer_id = ?", [indexer_id]) \ No newline at end of file + # init name cache + if not nameCache: + nameCache = {} + + cacheDB = db.DBConnection('cache.db') + cacheDB.action("DELETE FROM scene_names WHERE indexer_id = ?", [0]) + + 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) \ No newline at end of file diff --git a/sickbeard/providers/btn.py b/sickbeard/providers/btn.py index 5dca36ea..71c69c48 100644 --- a/sickbeard/providers/btn.py +++ b/sickbeard/providers/btn.py @@ -343,8 +343,6 @@ class BTNCache(tvcache.TVCache): if ci is not None: cl.append(ci) - - if cl: myDB = self._getDB() myDB.mass_action(cl) diff --git a/sickbeard/scene_exceptions.py b/sickbeard/scene_exceptions.py index 5168548d..f59370b7 100644 --- a/sickbeard/scene_exceptions.py +++ b/sickbeard/scene_exceptions.py @@ -27,7 +27,8 @@ from sickbeard import name_cache from sickbeard import logger from sickbeard import db -scene_lock = threading.Lock() +exceptionsCache = None +exceptionsSeasonCache = None def shouldRefresh(list): 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. """ - + global exceptionsCache exceptionsList = [] - myDB = db.DBConnection('cache.db') - exceptions = myDB.select("SELECT show_name FROM scene_exceptions WHERE indexer_id = ? and season = ?", - [indexer_id, season]) - if exceptions: - exceptionsList = list(set([cur_exception["show_name"] for cur_exception in exceptions])) + if indexer_id not in exceptionsCache or season not in exceptionsCache[indexer_id]: + myDB = db.DBConnection('cache.db') + exceptions = myDB.select("SELECT show_name FROM scene_exceptions WHERE indexer_id = ? and season = ?", + [indexer_id, season]) + 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 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 """ + global exceptionsSeasonCache + exceptionsSeasonList = [] - myDB = db.DBConnection('cache.db') - sqlResults = myDB.select("SELECT DISTINCT(season) as season FROM scene_exceptions WHERE indexer_id = ?", - [indexer_id]) + if indexer_id not in exceptionsSeasonCache: + myDB = db.DBConnection('cache.db') + 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: - return [int(x["season"]) for x in sqlResults] + if not indexer_id in exceptionsSeasonCache: + exceptionsSeasonCache[indexer_id] = {} + exceptionsSeasonCache[indexer_id] = exceptionsSeasonList + else: + exceptionsSeasonList = exceptionsSeasonCache[indexer_id] + + return exceptionsSeasonList def get_scene_exception_by_name(show_name): 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 scene_exceptions table in cache.db. Also clears the scene name cache. """ + global exceptionsCache, exceptionsSeasonCache + exceptionsCache = {} + exceptionsSeasonCache = {} exception_dict = {} # 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 if changed_exceptions: logger.log(u"Updated scene exceptions") - name_cache.clearCache() else: 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 (?,?,?,?)", [indexer_id, cur_exception, cur_season, 1]) - name_cache.clearCache() - def _retrieve_anidb_mainnames(): anidb_mainNames = {} diff --git a/sickbeard/show_queue.py b/sickbeard/show_queue.py index 35e9f13b..f85f39e2 100644 --- a/sickbeard/show_queue.py +++ b/sickbeard/show_queue.py @@ -279,9 +279,6 @@ class QueueItemAdd(ShowQueueItem): return try: - # clear the name cache - name_cache.clearCache() - newShow = TVShow(self.indexer, self.indexer_id, self.lang) newShow.loadFromIndexer() @@ -361,6 +358,9 @@ class QueueItemAdd(ShowQueueItem): # before we parse local files lets update exceptions sickbeard.scene_exceptions.retrieve_exceptions() + # update internal name cache + name_cache.buildNameCache() + try: self.show.loadEpisodesFromDir() except Exception, e: diff --git a/sickbeard/tvcache.py b/sickbeard/tvcache.py index da350e0b..d3905fbc 100644 --- a/sickbeard/tvcache.py +++ b/sickbeard/tvcache.py @@ -128,8 +128,6 @@ class TVCache(): if ci is not None: cl.append(ci) - time.sleep(.2) - if cl: myDB = self._getDB() myDB.mass_action(cl)