Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

added mail config code

  • Loading branch information...
commit d59d40df970a5df4489447ddf4e91a401b367de1 1 parent 955ebb1
@basti1 authored
View
333 data/interfaces/default/config_notifications.tmpl
@@ -1,150 +1,185 @@
-#import sickbeard
-#set global $title="Config - Notifications"
-#set global $header="Notifications"
-
-#set global $sbPath="../.."
-
-<!--#set global $topmenu="config"#-->
-#include $os.path.join($sickbeard.PROG_DIR, "data/interfaces/default/inc_top.tmpl")
-
-<script>
-\$(document).ready(function(){
-
- \$('#testGrowl').click(function(){
-
- var growl_host = \$("#growl_host").val();
- var growl_password = \$("#growl_password").val();
- \$.get("$sbRoot/home/testGrowl", {'host': growl_host, 'password': growl_password});
-
- });
-
- \$('#testXBMC').click(function(){
-
- var xbmc_host = \$("#xbmc_host").val();
- var xbmc_username = \$("#xbmc_username").val();
- var xbmc_password = \$("#xbmc_password").val();
-
- \$.get("$sbRoot/home/testXBMC", {'host': xbmc_host, 'username': xbmc_username, 'password': xbmc_password});
-
- });
-});
-
-</script>
-
-<form action="saveNotifications" method="POST">
-
-<div class="EntryBlock">
-<fieldset class="EntryFieldSet">
-
-<legend>XBMC</legend>
-
-#if $sickbeard.XBMC_NOTIFY_ONSNATCH == True:
-#set $xbmc_notify_onsnatch = "CHECKED"
-#else
-#set $xbmc_notify_onsnatch = ""
-#end if
-#if $sickbeard.XBMC_NOTIFY_ONDOWNLOAD == True:
-#set $xbmc_notify_ondownload = "CHECKED"
-#else
-#set $xbmc_notify_ondownload = ""
-#end if
-#if $sickbeard.XBMC_UPDATE_LIBRARY == True:
-#set $xbmc_update_library = "CHECKED"
-#else
-#set $xbmc_update_library = ""
-#end if
-
-<input type="checkbox" name="xbmc_notify_onsnatch" #if $sickbeard.XBMC_NOTIFY_ONSNATCH then "CHECKED" else ""#> <strong>Notify XBMC on NZB retrieval</strong><br />
-Send XBMC a notification when we find an NZB?<br />
-<br />
-
-<input type="checkbox" name="xbmc_notify_ondownload" #if $sickbeard.XBMC_NOTIFY_ONDOWNLOAD then "CHECKED" else ""#> <strong>Notify XBMC on episode download</strong><br />
-Send XBMC a notification when we finish a download?<br />
-<br />
-
-<input type="checkbox" name="xbmc_update_library" #if $sickbeard.XBMC_UPDATE_LIBRARY then "CHECKED" else ""#> <strong>Update XBMC library</strong><br />
-Update XBMC library when we finish a download?<br />
-<br />
-
-<strong>XBMC host:</strong><br />
-XBMC HTTP API address (IP:port, eg. 192.168.1.100:8080)<br />
-(multiple host strings can be separated by commas)<br />
-<input type="text" name="xbmc_host" id="xbmc_host" value="$sickbeard.XBMC_HOST" size="35"><br />
-<br />
-<strong>XBMC Username:</strong><br />
-Username of your XBMC server (blank for none)<br />
-<input type="text" name="xbmc_username" id="xbmc_username" value="$sickbeard.XBMC_USERNAME" size="35"><br />
-<br />
-<strong>XBMC Password:</strong><br />
-Password of your XBMC server (blank for none)<br />
-<input type="text" name="xbmc_password" id="xbmc_password" value="$sickbeard.XBMC_PASSWORD" size="35"><br />
-<br />
-
-<input type="button" value="Test XBMC" id="testXBMC">
-
-</fieldset>
-</div>
-
-<div class="EntryBlock">
-<fieldset class="EntryFieldSet">
-
-<legend>Growl</legend>
-
-<input type="checkbox" name="use_growl" #if $sickbeard.USE_GROWL then "CHECKED" else ""#> <strong>Enable Growl Notifications</strong><br />
-Should Sick Beard send Growl notifications?<br />
-<br />
-
-<strong>Growl Host:</strong><br />
-IP:Port of the host running Growl (eg. 192.168.1.100:2222)<br />
-If no port is given the default 23053 will be used.<br />
-<input type="text" name="growl_host" id="growl_host" value="$sickbeard.GROWL_HOST" size="35"><br />
-<br />
-
-<strong>Growl Password:</strong><br />
-If Growl is running no the same host as Sick Beard you may leave this<br />
-blank, but if the hosts are different Growl <b>requires</b> a password.<br />
-<input type="text" name="growl_password" id="growl_password" value="$sickbeard.GROWL_PASSWORD" size="35"><br />
-<br />
-
-<input type="button" value="Test Growl" id="testGrowl">
-
-</fieldset>
-</div>
-
-<div class="EntryBlock">
-<fieldset class="EntryFieldSet">
-
-<legend>Email</legend>
-
-Not Implemented<br />
-<br />
-<br />
-<br />
-<br />
-<br />
-
-</fieldset>
-</div>
-
-<div class="EntryBlock">
-<fieldset class="EntryFieldSet">
-
-<legend>Twitter</legend>
-
-Not Implemented<br />
-<br />
-<br />
-<br />
-<br />
-<br />
-
-</fieldset>
-</div>
-
-<p>
-<input type="submit" value="Save Changes">
-</p>
-</form>
-
-
+#import sickbeard
+#set global $title="Config - Notifications"
+#set global $header="Notifications"
+
+#set global $sbPath="../.."
+
+<!--#set global $topmenu="config"#-->
+#include $os.path.join($sickbeard.PROG_DIR, "data/interfaces/default/inc_top.tmpl")
+
+<script>
+\$(document).ready(function(){
+
+ \$('#testGrowl').click(function(){
+
+ var growl_host = \$("#growl_host").val();
+ var growl_password = \$("#growl_password").val();
+ \$.get("$sbRoot/home/testGrowl", {'host': growl_host, 'password': growl_password});
+
+ });
+
+ \$('#testXBMC').click(function(){
+
+ var xbmc_host = \$("#xbmc_host").val();
+ var xbmc_username = \$("#xbmc_username").val();
+ var xbmc_password = \$("#xbmc_password").val();
+
+ \$.get("$sbRoot/home/testXBMC", {'host': xbmc_host, 'username': xbmc_username, 'password': xbmc_password});
+
+ });
+
+ \$('#testMail').click(function(){
+ var smtp_server = \$("#smtp_server").val();
+ var smtp_user = \$("#smtp_user").val();
+ var smtp_password = \$("#smtp_password").val();
+ var smtp_sender = \$("#smtp_sender").val();
+ var smtp_receiver = \$("#smtp_receiver").val();
+
+ \$.get("$sbRoot/home/testMail", {'server': smtp_server, 'user': smtp_user, 'password': smtp_password, 'sender': smtp_sender, 'receiver': smtp_receiver});
+ });
+});
+
+</script>
+
+<form action="saveNotifications" method="POST">
+
+<div class="EntryBlock">
+<fieldset class="EntryFieldSet">
+
+<legend>XBMC</legend>
+
+#if $sickbeard.XBMC_NOTIFY_ONSNATCH == True:
+#set $xbmc_notify_onsnatch = "CHECKED"
+#else
+#set $xbmc_notify_onsnatch = ""
+#end if
+#if $sickbeard.XBMC_NOTIFY_ONDOWNLOAD == True:
+#set $xbmc_notify_ondownload = "CHECKED"
+#else
+#set $xbmc_notify_ondownload = ""
+#end if
+#if $sickbeard.XBMC_UPDATE_LIBRARY == True:
+#set $xbmc_update_library = "CHECKED"
+#else
+#set $xbmc_update_library = ""
+#end if
+
+<input type="checkbox" name="xbmc_notify_onsnatch" #if $sickbeard.XBMC_NOTIFY_ONSNATCH then "CHECKED" else ""#> <strong>Notify XBMC on NZB retrieval</strong><br />
+Send XBMC a notification when we find an NZB?<br />
+<br />
+
+<input type="checkbox" name="xbmc_notify_ondownload" #if $sickbeard.XBMC_NOTIFY_ONDOWNLOAD then "CHECKED" else ""#> <strong>Notify XBMC on episode download</strong><br />
+Send XBMC a notification when we finish a download?<br />
+<br />
+
+<input type="checkbox" name="xbmc_update_library" #if $sickbeard.XBMC_UPDATE_LIBRARY then "CHECKED" else ""#> <strong>Update XBMC library</strong><br />
+Update XBMC library when we finish a download?<br />
+<br />
+
+<strong>XBMC host:</strong><br />
+XBMC HTTP API address (IP:port, eg. 192.168.1.100:8080)<br />
+(multiple host strings can be separated by commas)<br />
+<input type="text" name="xbmc_host" id="xbmc_host" value="$sickbeard.XBMC_HOST" size="35"><br />
+<br />
+<strong>XBMC Username:</strong><br />
+Username of your XBMC server (blank for none)<br />
+<input type="text" name="xbmc_username" id="xbmc_username" value="$sickbeard.XBMC_USERNAME" size="35"><br />
+<br />
+<strong>XBMC Password:</strong><br />
+Password of your XBMC server (blank for none)<br />
+<input type="text" name="xbmc_password" id="xbmc_password" value="$sickbeard.XBMC_PASSWORD" size="35"><br />
+<br />
+
+<input type="button" value="Test XBMC" id="testXBMC">
+
+</fieldset>
+</div>
+
+<div class="EntryBlock">
+<fieldset class="EntryFieldSet">
+
+<legend>Growl</legend>
+
+<input type="checkbox" name="use_growl" #if $sickbeard.USE_GROWL then "CHECKED" else ""#> <strong>Enable Growl Notifications</strong><br />
+Should Sick Beard send Growl notifications?<br />
+<br />
+
+<strong>Growl Host:</strong><br />
+IP:Port of the host running Growl (eg. 192.168.1.100:2222)<br />
+If no port is given the default 23053 will be used.<br />
+<input type="text" name="growl_host" id="growl_host" value="$sickbeard.GROWL_HOST" size="35"><br />
+<br />
+
+<strong>Growl Password:</strong><br />
+If Growl is running no the same host as Sick Beard you may leave this<br />
+blank, but if the hosts are different Growl <b>requires</b> a password.<br />
+<input type="text" name="growl_password" id="growl_password" value="$sickbeard.GROWL_PASSWORD" size="35"><br />
+<br />
+
+<input type="button" value="Test Growl" id="testGrowl">
+
+</fieldset>
+</div>
+
+<div class="EntryBlock">
+<fieldset class="EntryFieldSet">
+
+<legend>Email</legend>
+
+<input type="checkbox" name="use_mail" #if $sickbeard.USE_MAIL then "CHECKED" else ""#> <strong>Enable Email Notifications</strong><br />
+Should Sick Beard send an email notification after a successfull download?<br />
+<br />
+
+<strong>SMTP Server:</strong><br />
+SMTP Host name (eg. smtp.myhost.com)<br />
+If no host is given, the notification wont work<br />
+<input type="text" name="smtp_server" id="smtp_server" value="$sickbeard.SMTP_SERVER" size="35"><br />
+<br />
+
+<strong>SMTP User:</strong><br />
+Valid user to log on to your SMTP Server<br />
+<input type="text" name="smtp_user" id="smtp_user" value="$sickbeard.SMTP_USER" size="35"><br />
+<br />
+
+<strong>SMTP Password:</strong><br />
+User Password to log on to your SMTP Server<br />
+<input type="password" name="smtp_password" id="smtp_password" value="$sickbeard.SMTP_PASSWORD" size="35"><br />
+<br />
+
+<strong>Sender</strong><br />
+This will be the sender's address in the email header.<br/>
+<input type="text" name="smtp_sender" id="smtp_sender" value="$sickbeard.SMTP_SENDER" size="35"><br />
+<br />
+
+<strong>Receipient</strong><br />
+The address where the email will be send to. This one must be valid!<br />
+<input type="text" name="smtp_receiver" id="smtp_receiver" value="$sickbeard.SMTP_RECEIVER" size="35"><br />
+<br />
+
+<input type="button" value="Test Email" id="testMail">
+
+</fieldset>
+</div>
+
+<div class="EntryBlock">
+<fieldset class="EntryFieldSet">
+
+<legend>Twitter</legend>
+
+Not Implemented<br />
+<br />
+<br />
+<br />
+<br />
+<br />
+
+</fieldset>
+</div>
+
+<p>
+<input type="submit" value="Save Changes">
+</p>
+</form>
+
+
#include $os.path.join($sickbeard.PROG_DIR, "data/interfaces/default/inc_bottom.tmpl")
View
1,558 sickbeard/__init__.py
@@ -1,769 +1,789 @@
-# Author: Nic Wolfe <nic@wolfeden.ca>
-# URL: http://code.google.com/p/sickbeard/
-#
-# This file is part of Sick Beard.
-#
-# Sick Beard is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Sick Beard is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Sick Beard. If not, see <http://www.gnu.org/licenses/>.
-
-from __future__ import with_statement
-
-import cherrypy
-import webbrowser
-import sqlite3
-import datetime
-import socket
-import os
-
-from threading import Lock
-
-# apparently py2exe won't build these unless they're imported somewhere
-from providers import eztv, nzbs, nzbmatrix, newzbin, tvnzb, tvbinz
-
-from sickbeard import searchCurrent, searchBacklog, showUpdater, versionChecker, properFinder, autoPostProcesser
-from sickbeard import helpers, db, exceptions, queue, scheduler
-from sickbeard import logger
-
-from sickbeard.common import *
-
-from sickbeard.databases import mainDB
-
-SOCKET_TIMEOUT = 30
-
-CFG = None
-
-PROG_DIR = None
-MY_FULLNAME = None
-MY_NAME = None
-
-backlogSearchScheduler = None
-currentSearchScheduler = None
-showUpdateScheduler = None
-versionCheckScheduler = None
-showQueueScheduler = None
-properFinderScheduler = None
-autoPostProcesserScheduler = None
-
-showList = None
-loadingShowList = None
-
-missingList = None
-airingList = None
-comingList = None
-
-NEWEST_VERSION = None
-VERSION_NOTIFY = None
-
-INIT_LOCK = Lock()
-__INITIALIZED__ = False
-
-LOG_DIR = None
-
-WEB_PORT = None
-WEB_LOG = None
-WEB_ROOT = None
-WEB_USERNAME = None
-WEB_PASSWORD = None
-LAUNCH_BROWSER = None
-CREATE_METADATA = None
-CACHE_DIR = None
-
-QUALITY_DEFAULT = None
-SEASON_FOLDERS_DEFAULT = None
-PROVIDER_ORDER = None
-
-NAMING_SHOW_NAME = None
-NAMING_EP_TYPE = None
-NAMING_MULTI_EP_TYPE = None
-
-TVDB_API_KEY = '9DAF49C96CBF8DAC'
-TVDB_BASE_URL = None
-TVDB_API_PARMS = {}
-
-USE_NZB = False
-NZB_METHOD = None
-NZB_DIR = None
-USENET_RETENTION = None
-
-SEARCH_FREQUENCY = None
-BACKLOG_SEARCH_FREQUENCY = None
-
-MIN_SEARCH_FREQUENCY = 30
-MIN_BACKLOG_SEARCH_FREQUENCY = 7
-
-DEFAULT_SEARCH_FREQUENCY = 60
-DEFAULT_BACKLOG_SEARCH_FREQUENCY = 21
-
-USE_TORRENT = False
-TORRENT_DIR = None
-
-RENAME_EPISODES = False
-PROCESS_AUTOMATICALLY = False
-KEEP_PROCESSED_DIR = False
-KEEP_PROCESSED_FILE = False
-TV_DOWNLOAD_DIR = None
-
-NEWZBIN = False
-NEWZBIN_USERNAME = None
-NEWZBIN_PASSWORD = None
-
-TVBINZ = False
-TVBINZ_UID = None
-TVBINZ_SABUID = None
-TVBINZ_HASH = None
-TVBINZ_AUTH = None
-
-NZBS = False
-NZBS_UID = None
-NZBS_HASH = None
-
-NZBMATRIX = False
-NZBMATRIX_USERNAME = None
-NZBMATRIX_APIKEY = None
-
-TVNZB = False
-
-SAB_USERNAME = None
-SAB_PASSWORD = None
-SAB_APIKEY = None
-SAB_CATEGORY = None
-SAB_HOST = None
-
-XBMC_NOTIFY_ONSNATCH = False
-XBMC_NOTIFY_ONDOWNLOAD = False
-XBMC_UPDATE_LIBRARY = False
-XBMC_HOST = None
-XBMC_USERNAME = None
-XBMC_PASSWORD = None
-
-USE_GROWL = False
-GROWL_HOST = None
-GROWL_PASSWORD = None
-
-__INITIALIZED__ = False
-
-def CheckSection(sec):
- """ Check if INI section exists, if not create it """
- try:
- CFG[sec]
- return True
- except:
- CFG[sec] = {}
- return False
-
-################################################################################
-# Check_setting_int #
-################################################################################
-def minimax(val, low, high):
- """ Return value forced within range """
- try:
- val = int(val)
- except:
- val = 0
- if val < low:
- return low
- if val > high:
- return high
- return val
-
-################################################################################
-# Check_setting_int #
-################################################################################
-def check_setting_int(config, cfg_name, item_name, def_val):
- try:
- my_val = int(config[cfg_name][item_name])
- except:
- my_val = def_val
- try:
- config[cfg_name][item_name] = my_val
- except:
- config[cfg_name] = {}
- config[cfg_name][item_name] = my_val
- logger.log(item_name + " -> " + str(my_val), logger.DEBUG)
- return my_val
-
-################################################################################
-# Check_setting_float #
-################################################################################
-def check_setting_float(config, cfg_name, item_name, def_val):
- try:
- my_val = float(config[cfg_name][item_name])
- except:
- my_val = def_val
- try:
- config[cfg_name][item_name] = my_val
- except:
- config[cfg_name] = {}
- config[cfg_name][item_name] = my_val
-
- logger.log(item_name + " -> " + str(my_val), logger.DEBUG)
- return my_val
-
-################################################################################
-# Check_setting_str #
-################################################################################
-def check_setting_str(config, cfg_name, item_name, def_val, log=True):
- try:
- my_val = config[cfg_name][item_name]
- except:
- my_val = def_val
- try:
- config[cfg_name][item_name] = my_val
- except:
- config[cfg_name] = {}
- config[cfg_name][item_name] = my_val
-
- if log:
- logger.log(item_name + " -> " + my_val, logger.DEBUG)
- else:
- logger.log(item_name + " -> ******", logger.DEBUG)
- return my_val
-
-
-def initialize(consoleLogging=True):
-
- with INIT_LOCK:
-
- global LOG_DIR, WEB_PORT, WEB_LOG, WEB_ROOT, WEB_USERNAME, WEB_PASSWORD, NZB_METHOD, NZB_DIR, \
- NEWZBIN, NEWZBIN_USERNAME, NEWZBIN_PASSWORD, TVBINZ, TVBINZ_UID, TVBINZ_HASH, \
- SAB_USERNAME, SAB_PASSWORD, SAB_APIKEY, SAB_CATEGORY, SAB_HOST, \
- XBMC_NOTIFY_ONSNATCH, XBMC_NOTIFY_ONDOWNLOAD, \
- XBMC_UPDATE_LIBRARY, XBMC_HOST, XBMC_USERNAME, XBMC_PASSWORD, currentSearchScheduler, backlogSearchScheduler, \
- showUpdateScheduler, __INITIALIZED__, LAUNCH_BROWSER, showList, missingList, \
- airingList, comingList, loadingShowList, CREATE_METADATA, SOCKET_TIMEOUT, \
- NZBS, NZBS_UID, NZBS_HASH, USE_NZB, USE_TORRENT, TORRENT_DIR, USENET_RETENTION, \
- SEARCH_FREQUENCY, DEFAULT_SEARCH_FREQUENCY, BACKLOG_SEARCH_FREQUENCY, \
- DEFAULT_BACKLOG_SEARCH_FREQUENCY, QUALITY_DEFAULT, SEASON_FOLDERS_DEFAULT, \
- USE_GROWL, GROWL_HOST, GROWL_PASSWORD, PROG_DIR, NZBMATRIX, NZBMATRIX_USERNAME, \
- NZBMATRIX_APIKEY, versionCheckScheduler, VERSION_NOTIFY, PROCESS_AUTOMATICALLY, \
- KEEP_PROCESSED_DIR, TV_DOWNLOAD_DIR, TVNZB, TVDB_BASE_URL, MIN_SEARCH_FREQUENCY, \
- MIN_BACKLOG_SEARCH_FREQUENCY, TVBINZ_AUTH, TVBINZ_SABUID, showQueueScheduler, \
- NAMING_SHOW_NAME, NAMING_EP_TYPE, NAMING_MULTI_EP_TYPE, CACHE_DIR, TVDB_API_PARMS, \
- RENAME_EPISODES, properFinderScheduler, PROVIDER_ORDER, autoPostProcesserScheduler, \
- KEEP_PROCESSED_FILE
-
-
- if __INITIALIZED__:
- return False
-
- socket.setdefaulttimeout(SOCKET_TIMEOUT)
-
- CheckSection('General')
- CheckSection('Blackhole')
- CheckSection('Newzbin')
- CheckSection('TVBinz')
- CheckSection('SABnzbd')
- CheckSection('XBMC')
- CheckSection('Growl')
-
- LOG_DIR = check_setting_str(CFG, 'General', 'log_dir', 'Logs')
- if not helpers.makeDir(LOG_DIR):
- logger.log("!!! No log folder, logging to screen only!", logger.ERROR)
-
- try:
- WEB_PORT = check_setting_int(CFG, 'General', 'web_port', 8081)
- except:
- WEB_PORT = 8081
-
- if WEB_PORT < 21 or WEB_PORT > 65535:
- WEB_PORT = 8081
-
- WEB_ROOT = check_setting_str(CFG, 'General', 'web_root', '').rstrip("/")
- WEB_LOG = bool(check_setting_int(CFG, 'General', 'web_log', 0))
- WEB_USERNAME = check_setting_str(CFG, 'General', 'web_username', '')
- WEB_PASSWORD = check_setting_str(CFG, 'General', 'web_password', '')
- LAUNCH_BROWSER = bool(check_setting_int(CFG, 'General', 'launch_browser', 1))
- CREATE_METADATA = bool(check_setting_int(CFG, 'General', 'create_metadata', 1))
-
- CACHE_DIR = check_setting_str(CFG, 'General', 'cache_dir', 'cache')
- if not helpers.makeDir(CACHE_DIR):
- logger.log("!!! Creating local cache dir failed, using system default", logger.ERROR)
- CACHE_DIR = None
-
- # Set our common tvdb_api options here
- TVDB_API_PARMS = {'cache': True,
- 'apikey': TVDB_API_KEY,
- 'language': 'en',
- '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))
-
- PROVIDER_ORDER = check_setting_str(CFG, 'General', 'provider_order', '').split()
-
- NAMING_SHOW_NAME = bool(check_setting_int(CFG, 'General', 'naming_show_name', 1))
- NAMING_EP_TYPE = check_setting_int(CFG, 'General', 'naming_ep_type', 0)
- NAMING_MULTI_EP_TYPE = check_setting_int(CFG, 'General', 'naming_multi_ep_type', 0)
-
- TVDB_BASE_URL = 'http://www.thetvdb.com/api/' + TVDB_API_KEY
-
- NZB_METHOD = check_setting_str(CFG, 'General', 'nzb_method', 'blackhole')
- if NZB_METHOD not in ('blackhole', 'sabnzbd'):
- NZB_METHOD = 'blackhole'
-
- 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', 200)
-
- SEARCH_FREQUENCY = check_setting_int(CFG, 'General', 'search_frequency', DEFAULT_SEARCH_FREQUENCY)
- if SEARCH_FREQUENCY < MIN_SEARCH_FREQUENCY:
- SEARCH_FREQUENCY = MIN_SEARCH_FREQUENCY
-
- BACKLOG_SEARCH_FREQUENCY = check_setting_int(CFG, 'General', 'backlog_search_frequency', DEFAULT_BACKLOG_SEARCH_FREQUENCY)
- if BACKLOG_SEARCH_FREQUENCY < MIN_BACKLOG_SEARCH_FREQUENCY:
- BACKLOG_SEARCH_FREQUENCY = MIN_BACKLOG_SEARCH_FREQUENCY
-
- 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', 0)
- KEEP_PROCESSED_FILE = check_setting_int(CFG, 'General', 'keep_processed_file', 0)
-
- 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', '')
-
- TVBINZ = bool(check_setting_int(CFG, 'TVBinz', 'tvbinz', 0))
- TVBINZ_UID = check_setting_str(CFG, 'TVBinz', 'tvbinz_uid', '')
- TVBINZ_SABUID = check_setting_str(CFG, 'TVBinz', 'tvbinz_sabuid', '')
- 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', '')
-
- 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', '')
-
- TVNZB = bool(check_setting_int(CFG, 'TVNZB', 'tvnzb', 0))
-
- SAB_USERNAME = check_setting_str(CFG, 'SABnzbd', 'sab_username', '')
- SAB_PASSWORD = check_setting_str(CFG, 'SABnzbd', 'sab_password', '')
- SAB_APIKEY = check_setting_str(CFG, 'SABnzbd', 'sab_apikey', '')
- SAB_CATEGORY = check_setting_str(CFG, 'SABnzbd', 'sab_category', 'tv')
- SAB_HOST = check_setting_str(CFG, 'SABnzbd', 'sab_host', '')
-
- XBMC_NOTIFY_ONSNATCH = bool(check_setting_int(CFG, 'XBMC', 'xbmc_notify_onsnatch', 0))
- XBMC_NOTIFY_ONDOWNLOAD = bool(check_setting_int(CFG, 'XBMC', 'xbmc_notify_ondownload', 0))
- XBMC_UPDATE_LIBRARY = bool(check_setting_int(CFG, 'XBMC', 'xbmc_update_library', 0))
- XBMC_HOST = check_setting_str(CFG, 'XBMC', 'xbmc_host', '')
- XBMC_USERNAME = check_setting_str(CFG, 'XBMC', 'xbmc_username', '')
- XBMC_PASSWORD = check_setting_str(CFG, 'XBMC', 'xbmc_password', '')
-
-
- USE_GROWL = bool(check_setting_int(CFG, 'Growl', 'use_growl', 0))
- GROWL_HOST = check_setting_str(CFG, 'Growl', 'growl_host', '')
- GROWL_PASSWORD = check_setting_str(CFG, 'Growl', 'growl_password', '')
-
- logger.initLogging(consoleLogging=consoleLogging)
-
- # initialize the main SB database
- db.upgradeDatabase(db.DBConnection(), mainDB.InitialSchema)
-
- currentSearchScheduler = scheduler.Scheduler(searchCurrent.CurrentSearcher(),
- cycleTime=datetime.timedelta(minutes=SEARCH_FREQUENCY),
- threadName="SEARCH",
- runImmediately=True)
-
- backlogSearchScheduler = searchBacklog.BacklogSearchScheduler(searchBacklog.BacklogSearcher(),
- cycleTime=datetime.timedelta(hours=1),
- 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,
- cycleTime=showUpdaterInstance.updateInterval,
- threadName="SHOWUPDATER",
- runImmediately=False)
-
- versionCheckScheduler = scheduler.Scheduler(versionChecker.CheckVersion(),
- cycleTime=datetime.timedelta(hours=12),
- threadName="CHECKVERSION",
- runImmediately=True)
-
- showQueueScheduler = scheduler.Scheduler(queue.ShowQueue(),
- cycleTime=datetime.timedelta(seconds=3),
- threadName="SHOWQUEUE",
- silent=True)
-
- properFinderInstance = properFinder.ProperFinder()
- properFinderScheduler = scheduler.Scheduler(properFinderInstance,
- cycleTime=properFinderInstance.updateInterval,
- threadName="FINDPROPERS",
- runImmediately=False)
-
- autoPostProcesserScheduler = scheduler.Scheduler(autoPostProcesser.PostProcesser(),
- cycleTime=datetime.timedelta(minutes=10),
- threadName="POSTPROCESSER",
- runImmediately=True)
-
-
- showList = []
- loadingShowList = {}
-
- missingList = []
- airingList = []
- comingList = []
-
- __INITIALIZED__ = 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()
-
- # start the version checker
- versionCheckScheduler.thread.start()
-
- # start the queue checker
- showQueueScheduler.thread.start()
-
- # start the queue checker
- properFinderScheduler.thread.start()
-
- # start the proper finder
- autoPostProcesserScheduler.thread.start()
-
-def halt ():
-
- global __INITIALIZED__, currentSearchScheduler, backlogSearchScheduler, showUpdateScheduler, \
- showQueueScheduler, properFinderScheduler, autoPostProcesserScheduler
-
- with INIT_LOCK:
-
- if __INITIALIZED__:
-
- logger.log("Aborting all threads")
-
- # abort all the threads
-
- currentSearchScheduler.abort = True
- logger.log("Waiting for the SEARCH thread to exit")
- try:
- currentSearchScheduler.thread.join(10)
- except:
- pass
-
- backlogSearchScheduler.abort = True
- logger.log("Waiting for the BACKLOG thread to exit")
- try:
- backlogSearchScheduler.thread.join(10)
- except:
- pass
-
- showUpdateScheduler.abort = True
- logger.log("Waiting for the SHOWUPDATER thread to exit")
- try:
- showUpdateScheduler.thread.join(10)
- except:
- pass
-
- versionCheckScheduler.abort = True
- logger.log("Waiting for the VERSIONCHECKER thread to exit")
- try:
- versionCheckScheduler.thread.join(10)
- except:
- pass
-
- showQueueScheduler.abort = True
- logger.log("Waiting for the SHOWQUEUE thread to exit")
- try:
- showQueueScheduler.thread.join(10)
- except:
- pass
-
- autoPostProcesserScheduler.abort = True
- logger.log("Waiting for the POSTPROCESSER thread to exit")
- try:
- autoPostProcesserScheduler.thread.join(10)
- except:
- pass
-
- properFinderScheduler.abort = True
- logger.log("Waiting for the PROPERFINDER thread to exit")
- try:
- properFinderScheduler.thread.join(10)
- except:
- pass
-
-
- __INITIALIZED__ = False
-
-
-def sig_handler(signum=None, frame=None):
- if type(signum) != type(None):
- #logging.warning('[%s] Signal %s caught, saving and exiting...', __NAME__, signum)
- logger.log("Signal %i caught, saving and exiting..." % int(signum))
- cherrypy.engine.exit()
- saveAndShutdown()
-
-
-def saveAll():
-
- global showList
-
- # write all shows
- logger.log("Saving all shows to the database")
- for show in showList:
- show.saveToDB()
-
- # save config
- logger.log("Saving config file to disk")
- save_config()
-
-
-def saveAndShutdown():
-
- halt()
-
- saveAll()
-
- os._exit(0)
-
-
-
-def save_config():
- global LOG_DIR, WEB_PORT, WEB_LOG, WEB_USERNAME, WEB_PASSWORD, NZB_METHOD, NZB_DIR, \
- NEWZBIN, NEWZBIN_USERNAME, NEWZBIN_PASSWORD, TVBINZ, TVBINZ_UID, TVBINZ_HASH, \
- SAB_USERNAME, SAB_PASSWORD, SAB_APIKEY, SAB_CATEGORY, SAB_HOST, \
- XBMC_NOTIFY_ONSNATCH, XBMC_NOTIFY_ONDOWNLOAD, \
- XBMC_UPDATE_LIBRARY, XBMC_HOST, XBMC_PASSWORD, XBMC_USERNAME, CFG, LAUNCH_BROWSER, CREATE_METADATA, USE_NZB, \
- USE_TORRENT, TORRENT_DIR, USENET_RETENTION, SEARCH_FREQUENCY, BACKLOG_SEARCH_FREQUENCY, \
- QUALITY_DEFAULT, SEASON_FOLDERS_DEFAULT, USE_GROWL, GROWL_HOST, GROWL_PASSWORD, \
- NZBMATRIX, NZBMATRIX_USERNAME, NZBMATRIX_APIKEY, VERSION_NOTIFY, TV_DOWNLOAD_DIR, \
- PROCESS_AUTOMATICALLY, KEEP_PROCESSED_DIR, TVNZB, TVBINZ_AUTH, TVBINZ_SABUID, \
- NAMING_SHOW_NAME, NAMING_EP_TYPE, NAMING_MULTI_EP_TYPE, CACHE_DIR, RENAME_EPISODES, PROVIDER_ORDER, \
- KEEP_PROCESSED_FILE
-
-
-
- CFG['General']['log_dir'] = LOG_DIR
- CFG['General']['web_port'] = WEB_PORT
- CFG['General']['web_log'] = int(WEB_LOG)
- CFG['General']['web_root'] = WEB_ROOT
- CFG['General']['web_username'] = WEB_USERNAME
- CFG['General']['web_password'] = WEB_PASSWORD
- CFG['General']['nzb_method'] = NZB_METHOD
- CFG['General']['usenet_retention'] = int(USENET_RETENTION)
- CFG['General']['search_frequency'] = int(SEARCH_FREQUENCY)
- CFG['General']['backlog_search_frequency'] = int(BACKLOG_SEARCH_FREQUENCY)
- CFG['General']['use_nzb'] = int(USE_NZB)
- CFG['General']['quality_default'] = int(QUALITY_DEFAULT)
- CFG['General']['season_folders_default'] = int(SEASON_FOLDERS_DEFAULT)
- CFG['General']['provider_order'] = ' '.join(PROVIDER_ORDER)
- CFG['General']['version_notify'] = int(VERSION_NOTIFY)
- CFG['General']['naming_show_name'] = int(NAMING_SHOW_NAME)
- CFG['General']['naming_ep_type'] = int(NAMING_EP_TYPE)
- CFG['General']['naming_multi_ep_type'] = int(NAMING_MULTI_EP_TYPE)
- CFG['General']['use_torrent'] = int(USE_TORRENT)
- CFG['General']['launch_browser'] = int(LAUNCH_BROWSER)
- CFG['General']['create_metadata'] = int(CREATE_METADATA)
- CFG['General']['cache_dir'] = CACHE_DIR
- CFG['General']['tv_download_dir'] = TV_DOWNLOAD_DIR
- CFG['General']['keep_processed_dir'] = int(KEEP_PROCESSED_DIR)
- CFG['General']['keep_processed_file'] = int(KEEP_PROCESSED_FILE)
- CFG['General']['process_automatically'] = int(PROCESS_AUTOMATICALLY)
- CFG['General']['rename_episodes'] = int(RENAME_EPISODES)
- CFG['Blackhole']['nzb_dir'] = NZB_DIR
- CFG['Blackhole']['torrent_dir'] = TORRENT_DIR
- CFG['Newzbin']['newzbin'] = int(NEWZBIN)
- CFG['Newzbin']['newzbin_username'] = NEWZBIN_USERNAME
- CFG['Newzbin']['newzbin_password'] = NEWZBIN_PASSWORD
- CFG['TVBinz']['tvbinz'] = int(TVBINZ)
- CFG['TVBinz']['tvbinz_uid'] = TVBINZ_UID
- CFG['TVBinz']['tvbinz_sabuid'] = TVBINZ_SABUID
- CFG['TVBinz']['tvbinz_hash'] = TVBINZ_HASH
- CFG['TVBinz']['tvbinz_auth'] = TVBINZ_AUTH
- CFG['NZBs']['nzbs'] = int(NZBS)
- CFG['NZBs']['nzbs_uid'] = NZBS_UID
- CFG['NZBs']['nzbs_hash'] = NZBS_HASH
- CFG['NZBMatrix']['nzbmatrix'] = int(NZBMATRIX)
- CFG['NZBMatrix']['nzbmatrix_username'] = NZBMATRIX_USERNAME
- CFG['NZBMatrix']['nzbmatrix_apikey'] = NZBMATRIX_APIKEY
- CFG['TVNZB']['tvnzb'] = int(TVNZB)
- CFG['SABnzbd']['sab_username'] = SAB_USERNAME
- CFG['SABnzbd']['sab_password'] = SAB_PASSWORD
- CFG['SABnzbd']['sab_apikey'] = SAB_APIKEY
- CFG['SABnzbd']['sab_category'] = SAB_CATEGORY
- CFG['SABnzbd']['sab_host'] = SAB_HOST
- CFG['XBMC']['xbmc_notify_onsnatch'] = int(XBMC_NOTIFY_ONSNATCH)
- CFG['XBMC']['xbmc_notify_ondownload'] = int(XBMC_NOTIFY_ONDOWNLOAD)
- CFG['XBMC']['xbmc_update_library'] = int(XBMC_UPDATE_LIBRARY)
- CFG['XBMC']['xbmc_host'] = XBMC_HOST
- CFG['XBMC']['xbmc_username'] = XBMC_USERNAME
- CFG['XBMC']['xbmc_password'] = XBMC_PASSWORD
- CFG['Growl']['use_growl'] = int(USE_GROWL)
- CFG['Growl']['growl_host'] = GROWL_HOST
- CFG['Growl']['growl_password'] = GROWL_PASSWORD
-
- CFG.write()
-
-
-def restart():
-
- halt()
-
- saveAll()
-
- INIT_OK = initialize()
- if INIT_OK:
- start()
-
-def launchBrowser():
- browserURL = 'http://localhost:%d%s' % (WEB_PORT, WEB_ROOT)
- try:
- webbrowser.open(browserURL, 2, 1)
- except:
- try:
- webbrowser.open(browserURL, 1, 1)
- except:
- logger.log("Unable to launch a browser", logger.ERROR)
-
-
-def updateMissingList():
-
- logger.log("Searching DB and building list of MISSED episodes")
-
- myDB = db.DBConnection()
- sqlResults = myDB.select("SELECT * FROM tv_episodes WHERE status=" + str(MISSED))
-
- epList = []
-
- for sqlEp in sqlResults:
-
- try:
- show = helpers.findCertainShow (sickbeard.showList, int(sqlEp["showid"]))
- except exceptions.MultipleShowObjectsException:
- logger.log("ERROR: expected to find a single show matching " + sqlEp["showid"])
- return None
-
- # 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("Somehow "+show.name+" - "+str(sqlEp["season"])+"x"+str(sqlEp["episode"])+" is None", logger.ERROR)
- else:
- epList.append(ep)
-
- sickbeard.missingList = epList
-
-
-def updateAiringList():
-
- logger.log("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 IN (" + str(UNAIRED) + ", " + str(PREDOWNLOADED) + ") AND airdate <= " + str(curDate))
-
- epList = []
-
- for sqlEp in sqlResults:
-
- try:
- show = helpers.findCertainShow (sickbeard.showList, int(sqlEp["showid"]))
- except exceptions.MultipleShowObjectsException:
- logger.log("ERROR: expected to find a single show matching " + sqlEp["showid"])
- return None
- except exceptions.SickBeardException, e:
- logger.log("Unexpected exception: "+str(e), logger.ERROR)
- continue
-
- # 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("Somehow "+show.name+" - "+str(sqlEp["season"])+"x"+str(sqlEp["episode"])+" is None", logger.ERROR)
- else:
- epList.append(ep)
-
- sickbeard.airingList = epList
-
-def updateComingList():
-
- epList = []
-
- for curShow in sickbeard.showList:
-
- curEps = None
-
- try:
- curEps = curShow.nextEpisode()
- except exceptions.NoNFOException, e:
- logger.log("Unable to retrieve episode from show: "+str(e), logger.ERROR)
-
- for myEp in curEps:
- if myEp.season != 0:
- epList.append(myEp)
-
- sickbeard.comingList = epList
-
-def getEpList(epIDs, showid=None):
-
- if epIDs == None or len(epIDs) == 0:
- return []
-
- if showid != None:
- showStr = " AND showid = "+str(showid)
- else:
- showStr = ""
-
- myDB = db.DBConnection()
- sqlResults = myDB.select("SELECT * FROM tv_episodes WHERE tvdbid in (" + ",".join([str(x) for x in epIDs]) + ")"+showStr)
-
- epList = []
-
- for curEp in sqlResults:
- curShowObj = helpers.findCertainShow(sickbeard.showList, int(curEp["showid"]))
- curEpObj = curShowObj.getEpisode(int(curEp["season"]), int(curEp["episode"]))
- epList.append(curEpObj)
-
- return epList
+# Author: Nic Wolfe <nic@wolfeden.ca>
+# URL: http://code.google.com/p/sickbeard/
+#
+# This file is part of Sick Beard.
+#
+# Sick Beard is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Sick Beard is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Sick Beard. If not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import with_statement
+
+import cherrypy
+import webbrowser
+import sqlite3
+import datetime
+import socket
+import os
+
+from threading import Lock
+
+# apparently py2exe won't build these unless they're imported somewhere
+from providers import eztv, nzbs, nzbmatrix, newzbin, tvnzb, tvbinz
+
+from sickbeard import searchCurrent, searchBacklog, showUpdater, versionChecker, properFinder, autoPostProcesser
+from sickbeard import helpers, db, exceptions, queue, scheduler
+from sickbeard import logger
+
+from sickbeard.common import *
+
+from sickbeard.databases import mainDB
+
+SOCKET_TIMEOUT = 30
+
+CFG = None
+
+PROG_DIR = None
+MY_FULLNAME = None
+MY_NAME = None
+
+backlogSearchScheduler = None
+currentSearchScheduler = None
+showUpdateScheduler = None
+versionCheckScheduler = None
+showQueueScheduler = None
+properFinderScheduler = None
+autoPostProcesserScheduler = None
+
+showList = None
+loadingShowList = None
+
+missingList = None
+airingList = None
+comingList = None
+
+NEWEST_VERSION = None
+VERSION_NOTIFY = None
+
+INIT_LOCK = Lock()
+__INITIALIZED__ = False
+
+LOG_DIR = None
+
+WEB_PORT = None
+WEB_LOG = None
+WEB_ROOT = None
+WEB_USERNAME = None
+WEB_PASSWORD = None
+LAUNCH_BROWSER = None
+CREATE_METADATA = None
+CACHE_DIR = None
+
+QUALITY_DEFAULT = None
+SEASON_FOLDERS_DEFAULT = None
+PROVIDER_ORDER = None
+
+NAMING_SHOW_NAME = None
+NAMING_EP_TYPE = None
+NAMING_MULTI_EP_TYPE = None
+
+TVDB_API_KEY = '9DAF49C96CBF8DAC'
+TVDB_BASE_URL = None
+TVDB_API_PARMS = {}
+
+USE_NZB = False
+NZB_METHOD = None
+NZB_DIR = None
+USENET_RETENTION = None
+
+SEARCH_FREQUENCY = None
+BACKLOG_SEARCH_FREQUENCY = None
+
+MIN_SEARCH_FREQUENCY = 30
+MIN_BACKLOG_SEARCH_FREQUENCY = 7
+
+DEFAULT_SEARCH_FREQUENCY = 60
+DEFAULT_BACKLOG_SEARCH_FREQUENCY = 21
+
+USE_TORRENT = False
+TORRENT_DIR = None
+
+RENAME_EPISODES = False
+PROCESS_AUTOMATICALLY = False
+KEEP_PROCESSED_DIR = False
+KEEP_PROCESSED_FILE = False
+TV_DOWNLOAD_DIR = None
+
+NEWZBIN = False
+NEWZBIN_USERNAME = None
+NEWZBIN_PASSWORD = None
+
+TVBINZ = False
+TVBINZ_UID = None
+TVBINZ_SABUID = None
+TVBINZ_HASH = None
+TVBINZ_AUTH = None
+
+NZBS = False
+NZBS_UID = None
+NZBS_HASH = None
+
+NZBMATRIX = False
+NZBMATRIX_USERNAME = None
+NZBMATRIX_APIKEY = None
+
+TVNZB = False
+
+SAB_USERNAME = None
+SAB_PASSWORD = None
+SAB_APIKEY = None
+SAB_CATEGORY = None
+SAB_HOST = None
+
+XBMC_NOTIFY_ONSNATCH = False
+XBMC_NOTIFY_ONDOWNLOAD = False
+XBMC_UPDATE_LIBRARY = False
+XBMC_HOST = None
+XBMC_USERNAME = None
+XBMC_PASSWORD = None
+
+USE_GROWL = False
+GROWL_HOST = None
+GROWL_PASSWORD = None
+
+USE_MAIL = False
+SMTP_SERVER = None
+SMTP_USER = None
+SMTP_PASSWORD = None
+SMTP_SENDER = None
+SMTP_RECEIVER = None
+
+__INITIALIZED__ = False
+
+def CheckSection(sec):
+ """ Check if INI section exists, if not create it """
+ try:
+ CFG[sec]
+ return True
+ except:
+ CFG[sec] = {}
+ return False
+
+################################################################################
+# Check_setting_int #
+################################################################################
+def minimax(val, low, high):
+ """ Return value forced within range """
+ try:
+ val = int(val)
+ except:
+ val = 0
+ if val < low:
+ return low
+ if val > high:
+ return high
+ return val
+
+################################################################################
+# Check_setting_int #
+################################################################################
+def check_setting_int(config, cfg_name, item_name, def_val):
+ try:
+ my_val = int(config[cfg_name][item_name])
+ except:
+ my_val = def_val
+ try:
+ config[cfg_name][item_name] = my_val
+ except:
+ config[cfg_name] = {}
+ config[cfg_name][item_name] = my_val
+ logger.log(item_name + " -> " + str(my_val), logger.DEBUG)
+ return my_val
+
+################################################################################
+# Check_setting_float #
+################################################################################
+def check_setting_float(config, cfg_name, item_name, def_val):
+ try:
+ my_val = float(config[cfg_name][item_name])
+ except:
+ my_val = def_val
+ try:
+ config[cfg_name][item_name] = my_val
+ except:
+ config[cfg_name] = {}
+ config[cfg_name][item_name] = my_val
+
+ logger.log(item_name + " -> " + str(my_val), logger.DEBUG)
+ return my_val
+
+################################################################################
+# Check_setting_str #
+################################################################################
+def check_setting_str(config, cfg_name, item_name, def_val, log=True):
+ try:
+ my_val = config[cfg_name][item_name]
+ except:
+ my_val = def_val
+ try:
+ config[cfg_name][item_name] = my_val
+ except:
+ config[cfg_name] = {}
+ config[cfg_name][item_name] = my_val
+
+ if log:
+ logger.log(item_name + " -> " + my_val, logger.DEBUG)
+ else:
+ logger.log(item_name + " -> ******", logger.DEBUG)
+ return my_val
+
+
+def initialize(consoleLogging=True):
+
+ with INIT_LOCK:
+
+ global LOG_DIR, WEB_PORT, WEB_LOG, WEB_ROOT, WEB_USERNAME, WEB_PASSWORD, NZB_METHOD, NZB_DIR, \
+ NEWZBIN, NEWZBIN_USERNAME, NEWZBIN_PASSWORD, TVBINZ, TVBINZ_UID, TVBINZ_HASH, \
+ SAB_USERNAME, SAB_PASSWORD, SAB_APIKEY, SAB_CATEGORY, SAB_HOST, \
+ XBMC_NOTIFY_ONSNATCH, XBMC_NOTIFY_ONDOWNLOAD, \
+ XBMC_UPDATE_LIBRARY, XBMC_HOST, XBMC_USERNAME, XBMC_PASSWORD, currentSearchScheduler, backlogSearchScheduler, \
+ showUpdateScheduler, __INITIALIZED__, LAUNCH_BROWSER, showList, missingList, \
+ airingList, comingList, loadingShowList, CREATE_METADATA, SOCKET_TIMEOUT, \
+ NZBS, NZBS_UID, NZBS_HASH, USE_NZB, USE_TORRENT, TORRENT_DIR, USENET_RETENTION, \
+ SEARCH_FREQUENCY, DEFAULT_SEARCH_FREQUENCY, BACKLOG_SEARCH_FREQUENCY, \
+ DEFAULT_BACKLOG_SEARCH_FREQUENCY, QUALITY_DEFAULT, SEASON_FOLDERS_DEFAULT, \
+ USE_GROWL, GROWL_HOST, GROWL_PASSWORD, PROG_DIR, NZBMATRIX, NZBMATRIX_USERNAME, \
+ NZBMATRIX_APIKEY, versionCheckScheduler, VERSION_NOTIFY, PROCESS_AUTOMATICALLY, \
+ KEEP_PROCESSED_DIR, TV_DOWNLOAD_DIR, TVNZB, TVDB_BASE_URL, MIN_SEARCH_FREQUENCY, \
+ MIN_BACKLOG_SEARCH_FREQUENCY, TVBINZ_AUTH, TVBINZ_SABUID, showQueueScheduler, \
+ NAMING_SHOW_NAME, NAMING_EP_TYPE, NAMING_MULTI_EP_TYPE, CACHE_DIR, TVDB_API_PARMS, \
+ RENAME_EPISODES, properFinderScheduler, PROVIDER_ORDER, autoPostProcesserScheduler, \
+ KEEP_PROCESSED_FILE
+
+
+ if __INITIALIZED__:
+ return False
+
+ socket.setdefaulttimeout(SOCKET_TIMEOUT)
+
+ CheckSection('General')
+ CheckSection('Blackhole')
+ CheckSection('Newzbin')
+ CheckSection('TVBinz')
+ CheckSection('SABnzbd')
+ CheckSection('XBMC')
+ CheckSection('Growl')
+
+ LOG_DIR = check_setting_str(CFG, 'General', 'log_dir', 'Logs')
+ if not helpers.makeDir(LOG_DIR):
+ logger.log("!!! No log folder, logging to screen only!", logger.ERROR)
+
+ try:
+ WEB_PORT = check_setting_int(CFG, 'General', 'web_port', 8081)
+ except:
+ WEB_PORT = 8081
+
+ if WEB_PORT < 21 or WEB_PORT > 65535:
+ WEB_PORT = 8081
+
+ WEB_ROOT = check_setting_str(CFG, 'General', 'web_root', '').rstrip("/")
+ WEB_LOG = bool(check_setting_int(CFG, 'General', 'web_log', 0))
+ WEB_USERNAME = check_setting_str(CFG, 'General', 'web_username', '')
+ WEB_PASSWORD = check_setting_str(CFG, 'General', 'web_password', '')
+ LAUNCH_BROWSER = bool(check_setting_int(CFG, 'General', 'launch_browser', 1))
+ CREATE_METADATA = bool(check_setting_int(CFG, 'General', 'create_metadata', 1))
+
+ CACHE_DIR = check_setting_str(CFG, 'General', 'cache_dir', 'cache')
+ if not helpers.makeDir(CACHE_DIR):
+ logger.log("!!! Creating local cache dir failed, using system default", logger.ERROR)
+ CACHE_DIR = None
+
+ # Set our common tvdb_api options here
+ TVDB_API_PARMS = {'cache': True,
+ 'apikey': TVDB_API_KEY,
+ 'language': 'en',
+ '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))
+
+ PROVIDER_ORDER = check_setting_str(CFG, 'General', 'provider_order', '').split()
+
+ NAMING_SHOW_NAME = bool(check_setting_int(CFG, 'General', 'naming_show_name', 1))
+ NAMING_EP_TYPE = check_setting_int(CFG, 'General', 'naming_ep_type', 0)
+ NAMING_MULTI_EP_TYPE = check_setting_int(CFG, 'General', 'naming_multi_ep_type', 0)
+
+ TVDB_BASE_URL = 'http://www.thetvdb.com/api/' + TVDB_API_KEY
+
+ NZB_METHOD = check_setting_str(CFG, 'General', 'nzb_method', 'blackhole')
+ if NZB_METHOD not in ('blackhole', 'sabnzbd'):
+ NZB_METHOD = 'blackhole'
+
+ 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', 200)
+
+ SEARCH_FREQUENCY = check_setting_int(CFG, 'General', 'search_frequency', DEFAULT_SEARCH_FREQUENCY)
+ if SEARCH_FREQUENCY < MIN_SEARCH_FREQUENCY:
+ SEARCH_FREQUENCY = MIN_SEARCH_FREQUENCY
+
+ BACKLOG_SEARCH_FREQUENCY = check_setting_int(CFG, 'General', 'backlog_search_frequency', DEFAULT_BACKLOG_SEARCH_FREQUENCY)
+ if BACKLOG_SEARCH_FREQUENCY < MIN_BACKLOG_SEARCH_FREQUENCY:
+ BACKLOG_SEARCH_FREQUENCY = MIN_BACKLOG_SEARCH_FREQUENCY
+
+ 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', 0)
+ KEEP_PROCESSED_FILE = check_setting_int(CFG, 'General', 'keep_processed_file', 0)
+
+ 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', '')
+
+ TVBINZ = bool(check_setting_int(CFG, 'TVBinz', 'tvbinz', 0))
+ TVBINZ_UID = check_setting_str(CFG, 'TVBinz', 'tvbinz_uid', '')
+ TVBINZ_SABUID = check_setting_str(CFG, 'TVBinz', 'tvbinz_sabuid', '')
+ 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', '')
+
+ 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', '')
+
+ TVNZB = bool(check_setting_int(CFG, 'TVNZB', 'tvnzb', 0))
+
+ SAB_USERNAME = check_setting_str(CFG, 'SABnzbd', 'sab_username', '')
+ SAB_PASSWORD = check_setting_str(CFG, 'SABnzbd', 'sab_password', '')
+ SAB_APIKEY = check_setting_str(CFG, 'SABnzbd', 'sab_apikey', '')
+ SAB_CATEGORY = check_setting_str(CFG, 'SABnzbd', 'sab_category', 'tv')
+ SAB_HOST = check_setting_str(CFG, 'SABnzbd', 'sab_host', '')
+
+ XBMC_NOTIFY_ONSNATCH = bool(check_setting_int(CFG, 'XBMC', 'xbmc_notify_onsnatch', 0))
+ XBMC_NOTIFY_ONDOWNLOAD = bool(check_setting_int(CFG, 'XBMC', 'xbmc_notify_ondownload', 0))
+ XBMC_UPDATE_LIBRARY = bool(check_setting_int(CFG, 'XBMC', 'xbmc_update_library', 0))
+ XBMC_HOST = check_setting_str(CFG, 'XBMC', 'xbmc_host', '')
+ XBMC_USERNAME = check_setting_str(CFG, 'XBMC', 'xbmc_username', '')
+ XBMC_PASSWORD = check_setting_str(CFG, 'XBMC', 'xbmc_password', '')
+
+
+ USE_GROWL = bool(check_setting_int(CFG, 'Growl', 'use_growl', 0))
+ GROWL_HOST = check_setting_str(CFG, 'Growl', 'growl_host', '')
+ GROWL_PASSWORD = check_setting_str(CFG, 'Growl', 'growl_password', '')
+
+ USE_MAIL = bool(check_setting_int(CFG, 'Mail', 'use_mail', 0))
+ SMTP_SERVER = check_setting_str(CFG, 'Mail', 'smtp_server', '')
+ SMTP_USER = check_setting_str(CFG, 'Mail', 'smtp_user', '')
+ SMTP_PASSWORD = check_setting_str(CFG, 'Mail', 'smtp_password', '')
+ SMTP_SENDER = check_setting_str(CFG, 'Mail', 'smtp_sender', '')
+ SMTP_RECEIVER = check_setting_str(CFG, 'Mail', 'smtp_receiver', '')
+
+ logger.initLogging(consoleLogging=consoleLogging)
+
+ # initialize the main SB database
+ db.upgradeDatabase(db.DBConnection(), mainDB.InitialSchema)
+
+ currentSearchScheduler = scheduler.Scheduler(searchCurrent.CurrentSearcher(),
+ cycleTime=datetime.timedelta(minutes=SEARCH_FREQUENCY),
+ threadName="SEARCH",
+ runImmediately=True)
+
+ backlogSearchScheduler = searchBacklog.BacklogSearchScheduler(searchBacklog.BacklogSearcher(),
+ cycleTime=datetime.timedelta(hours=1),
+ 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,
+ cycleTime=showUpdaterInstance.updateInterval,
+ threadName="SHOWUPDATER",
+ runImmediately=False)
+
+ versionCheckScheduler = scheduler.Scheduler(versionChecker.CheckVersion(),
+ cycleTime=datetime.timedelta(hours=12),
+ threadName="CHECKVERSION",
+ runImmediately=True)
+
+ showQueueScheduler = scheduler.Scheduler(queue.ShowQueue(),
+ cycleTime=datetime.timedelta(seconds=3),
+ threadName="SHOWQUEUE",
+ silent=True)
+
+ properFinderInstance = properFinder.ProperFinder()
+ properFinderScheduler = scheduler.Scheduler(properFinderInstance,
+ cycleTime=properFinderInstance.updateInterval,
+ threadName="FINDPROPERS",
+ runImmediately=False)
+
+ autoPostProcesserScheduler = scheduler.Scheduler(autoPostProcesser.PostProcesser(),
+ cycleTime=datetime.timedelta(minutes=10),
+ threadName="POSTPROCESSER",
+ runImmediately=True)
+
+
+ showList = []
+ loadingShowList = {}
+
+ missingList = []
+ airingList = []
+ comingList = []
+
+ __INITIALIZED__ = 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()
+
+ # start the version checker
+ versionCheckScheduler.thread.start()
+
+ # start the queue checker
+ showQueueScheduler.thread.start()
+
+ # start the queue checker
+ properFinderScheduler.thread.start()
+
+ # start the proper finder
+ autoPostProcesserScheduler.thread.start()
+
+def halt ():
+
+ global __INITIALIZED__, currentSearchScheduler, backlogSearchScheduler, showUpdateScheduler, \
+ showQueueScheduler, properFinderScheduler, autoPostProcesserScheduler
+
+ with INIT_LOCK:
+
+ if __INITIALIZED__:
+
+ logger.log("Aborting all threads")
+
+ # abort all the threads
+
+ currentSearchScheduler.abort = True
+ logger.log("Waiting for the SEARCH thread to exit")
+ try:
+ currentSearchScheduler.thread.join(10)
+ except:
+ pass
+
+ backlogSearchScheduler.abort = True
+ logger.log("Waiting for the BACKLOG thread to exit")
+ try:
+ backlogSearchScheduler.thread.join(10)
+ except:
+ pass
+
+ showUpdateScheduler.abort = True
+ logger.log("Waiting for the SHOWUPDATER thread to exit")
+ try:
+ showUpdateScheduler.thread.join(10)
+ except:
+ pass
+
+ versionCheckScheduler.abort = True
+ logger.log("Waiting for the VERSIONCHECKER thread to exit")
+ try:
+ versionCheckScheduler.thread.join(10)
+ except:
+ pass
+
+ showQueueScheduler.abort = True
+ logger.log("Waiting for the SHOWQUEUE thread to exit")
+ try:
+ showQueueScheduler.thread.join(10)
+ except:
+ pass
+
+ autoPostProcesserScheduler.abort = True
+ logger.log("Waiting for the POSTPROCESSER thread to exit")
+ try:
+ autoPostProcesserScheduler.thread.join(10)
+ except:
+ pass
+
+ properFinderScheduler.abort = True
+ logger.log("Waiting for the PROPERFINDER thread to exit")
+ try:
+ properFinderScheduler.thread.join(10)
+ except:
+ pass
+
+
+ __INITIALIZED__ = False
+
+
+def sig_handler(signum=None, frame=None):
+ if type(signum) != type(None):
+ #logging.warning('[%s] Signal %s caught, saving and exiting...', __NAME__, signum)
+ logger.log("Signal %i caught, saving and exiting..." % int(signum))
+ cherrypy.engine.exit()
+ saveAndShutdown()
+
+
+def saveAll():
+
+ global showList
+
+ # write all shows
+ logger.log("Saving all shows to the database")
+ for show in showList:
+ show.saveToDB()
+
+ # save config
+ logger.log("Saving config file to disk")
+ save_config()
+
+
+def saveAndShutdown():
+
+ halt()
+
+ saveAll()
+
+ os._exit(0)
+
+
+
+def save_config():
+ global LOG_DIR, WEB_PORT, WEB_LOG, WEB_USERNAME, WEB_PASSWORD, NZB_METHOD, NZB_DIR, \
+ NEWZBIN, NEWZBIN_USERNAME, NEWZBIN_PASSWORD, TVBINZ, TVBINZ_UID, TVBINZ_HASH, \
+ SAB_USERNAME, SAB_PASSWORD, SAB_APIKEY, SAB_CATEGORY, SAB_HOST, \
+ XBMC_NOTIFY_ONSNATCH, XBMC_NOTIFY_ONDOWNLOAD, \
+ XBMC_UPDATE_LIBRARY, XBMC_HOST, XBMC_PASSWORD, XBMC_USERNAME, CFG, LAUNCH_BROWSER, CREATE_METADATA, USE_NZB, \
+ USE_TORRENT, TORRENT_DIR, USENET_RETENTION, SEARCH_FREQUENCY, BACKLOG_SEARCH_FREQUENCY, \
+ QUALITY_DEFAULT, SEASON_FOLDERS_DEFAULT, USE_GROWL, GROWL_HOST, GROWL_PASSWORD, \
+ NZBMATRIX, NZBMATRIX_USERNAME, NZBMATRIX_APIKEY, VERSION_NOTIFY, TV_DOWNLOAD_DIR, \
+ PROCESS_AUTOMATICALLY, KEEP_PROCESSED_DIR, TVNZB, TVBINZ_AUTH, TVBINZ_SABUID, \
+ NAMING_SHOW_NAME, NAMING_EP_TYPE, NAMING_MULTI_EP_TYPE, CACHE_DIR, RENAME_EPISODES, PROVIDER_ORDER, \
+ KEEP_PROCESSED_FILE
+
+
+
+ CFG['General']['log_dir'] = LOG_DIR
+ CFG['General']['web_port'] = WEB_PORT
+ CFG['General']['web_log'] = int(WEB_LOG)
+ CFG['General']['web_root'] = WEB_ROOT
+ CFG['General']['web_username'] = WEB_USERNAME
+ CFG['General']['web_password'] = WEB_PASSWORD
+ CFG['General']['nzb_method'] = NZB_METHOD
+ CFG['General']['usenet_retention'] = int(USENET_RETENTION)
+ CFG['General']['search_frequency'] = int(SEARCH_FREQUENCY)
+ CFG['General']['backlog_search_frequency'] = int(BACKLOG_SEARCH_FREQUENCY)
+ CFG['General']['use_nzb'] = int(USE_NZB)
+ CFG['General']['quality_default'] = int(QUALITY_DEFAULT)
+ CFG['General']['season_folders_default'] = int(SEASON_FOLDERS_DEFAULT)
+ CFG['General']['provider_order'] = ' '.join(PROVIDER_ORDER)
+ CFG['General']['version_notify'] = int(VERSION_NOTIFY)
+ CFG['General']['naming_show_name'] = int(NAMING_SHOW_NAME)
+ CFG['General']['naming_ep_type'] = int(NAMING_EP_TYPE)
+ CFG['General']['naming_multi_ep_type'] = int(NAMING_MULTI_EP_TYPE)
+ CFG['General']['use_torrent'] = int(USE_TORRENT)
+ CFG['General']['launch_browser'] = int(LAUNCH_BROWSER)
+ CFG['General']['create_metadata'] = int(CREATE_METADATA)
+ CFG['General']['cache_dir'] = CACHE_DIR
+ CFG['General']['tv_download_dir'] = TV_DOWNLOAD_DIR
+ CFG['General']['keep_processed_dir'] = int(KEEP_PROCESSED_DIR)
+ CFG['General']['keep_processed_file'] = int(KEEP_PROCESSED_FILE)
+ CFG['General']['process_automatically'] = int(PROCESS_AUTOMATICALLY)
+ CFG['General']['rename_episodes'] = int(RENAME_EPISODES)
+ CFG['Blackhole']['nzb_dir'] = NZB_DIR
+ CFG['Blackhole']['torrent_dir'] = TORRENT_DIR
+ CFG['Newzbin']['newzbin'] = int(NEWZBIN)
+ CFG['Newzbin']['newzbin_username'] = NEWZBIN_USERNAME
+ CFG['Newzbin']['newzbin_password'] = NEWZBIN_PASSWORD
+ CFG['TVBinz']['tvbinz'] = int(TVBINZ)
+ CFG['TVBinz']['tvbinz_uid'] = TVBINZ_UID
+ CFG['TVBinz']['tvbinz_sabuid'] = TVBINZ_SABUID
+ CFG['TVBinz']['tvbinz_hash'] = TVBINZ_HASH
+ CFG['TVBinz']['tvbinz_auth'] = TVBINZ_AUTH
+ CFG['NZBs']['nzbs'] = int(NZBS)
+ CFG['NZBs']['nzbs_uid'] = NZBS_UID
+ CFG['NZBs']['nzbs_hash'] = NZBS_HASH
+ CFG['NZBMatrix']['nzbmatrix'] = int(NZBMATRIX)
+ CFG['NZBMatrix']['nzbmatrix_username'] = NZBMATRIX_USERNAME
+ CFG['NZBMatrix']['nzbmatrix_apikey'] = NZBMATRIX_APIKEY
+ CFG['TVNZB']['tvnzb'] = int(TVNZB)
+ CFG['SABnzbd']['sab_username'] = SAB_USERNAME
+ CFG['SABnzbd']['sab_password'] = SAB_PASSWORD
+ CFG['SABnzbd']['sab_apikey'] = SAB_APIKEY
+ CFG['SABnzbd']['sab_category'] = SAB_CATEGORY
+ CFG['SABnzbd']['sab_host'] = SAB_HOST
+ CFG['XBMC']['xbmc_notify_onsnatch'] = int(XBMC_NOTIFY_ONSNATCH)
+ CFG['XBMC']['xbmc_notify_ondownload'] = int(XBMC_NOTIFY_ONDOWNLOAD)
+ CFG['XBMC']['xbmc_update_library'] = int(XBMC_UPDATE_LIBRARY)
+ CFG['XBMC']['xbmc_host'] = XBMC_HOST
+ CFG['XBMC']['xbmc_username'] = XBMC_USERNAME
+ CFG['XBMC']['xbmc_password'] = XBMC_PASSWORD
+ CFG['Growl']['use_growl'] = int(USE_GROWL)
+ CFG['Growl']['growl_host'] = GROWL_HOST
+ CFG['Growl']['growl_password'] = GROWL_PASSWORD
+ CFG['Mail']['use_mail'] = int(USE_MAIL)
+ CFG['Mail']['smtp_server'] = SMTP_SERVER
+ CFG['Mail']['smtp_user'] = SMTP_USER
+ CFG['Mail']['smtp_password'] = SMTP_PASSWORD
+ CFG['Mail']['smtp_sender'] = SMTP_SENDER
+ CFG['Mail']['smtp_receiver'] = SMTP_RECEIVER
+
+ CFG.write()
+
+
+def restart():
+
+ halt()
+
+ saveAll()
+
+ INIT_OK = initialize()
+ if INIT_OK:
+ start()
+
+def launchBrowser():
+ browserURL = 'http://localhost:%d%s' % (WEB_PORT, WEB_ROOT)
+ try:
+ webbrowser.open(browserURL, 2, 1)
+ except:
+ try:
+ webbrowser.open(browserURL, 1, 1)
+ except:
+ logger.log("Unable to launch a browser", logger.ERROR)
+
+
+def updateMissingList():
+
+ logger.log("Searching DB and building list of MISSED episodes")
+
+ myDB = db.DBConnection()
+ sqlResults = myDB.select("SELECT * FROM tv_episodes WHERE status=" + str(MISSED))
+
+ epList = []
+
+ for sqlEp in sqlResults:
+
+ try:
+ show = helpers.findCertainShow (sickbeard.showList, int(sqlEp["showid"]))
+ except exceptions.MultipleShowObjectsException:
+ logger.log("ERROR: expected to find a single show matching " + sqlEp["showid"])
+ return None
+
+ # 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("Somehow "+show.name+" - "+str(sqlEp["season"])+"x"+str(sqlEp["episode"])+" is None", logger.ERROR)
+ else:
+ epList.append(ep)
+
+ sickbeard.missingList = epList
+
+
+def updateAiringList():
+
+ logger.log("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 IN (" + str(UNAIRED) + ", " + str(PREDOWNLOADED) + ") AND airdate <= " + str(curDate))
+
+ epList = []
+
+ for sqlEp in sqlResults:
+
+ try:
+ show = helpers.findCertainShow (sickbeard.showList, int(sqlEp["showid"]))
+ except exceptions.MultipleShowObjectsException:
+ logger.log("ERROR: expected to find a single show matching " + sqlEp["showid"])
+ return None
+ except exceptions.SickBeardException, e:
+ logger.log("Unexpected exception: "+str(e), logger.ERROR)
+ continue
+
+ # 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("Somehow "+show.name+" - "+str(sqlEp["season"])+"x"+str(sqlEp["episode"])+" is None", logger.ERROR)
+ else:
+ epList.append(ep)
+
+ sickbeard.airingList = epList
+
+def updateComingList():
+
+ epList = []
+
+ for curShow in sickbeard.showList:
+
+ curEps = None
+
+ try:
+ curEps = curShow.nextEpisode()
+ except exceptions.NoNFOException, e:
+ logger.log("Unable to retrieve episode from show: "+str(e), logger.ERROR)
+
+ for myEp in curEps:
+ if myEp.season != 0:
+ epList.append(myEp)
+
+ sickbeard.comingList = epList
+
+def getEpList(epIDs, showid=None):
+
+ if epIDs == None or len(epIDs) == 0:
+ return []
+
+ if showid != None:
+ showStr = " AND showid = "+str(showid)
+ else:
+ showStr = ""
+
+ myDB = db.DBConnection()
+ sqlResults = myDB.select("SELECT * FROM tv_episodes WHERE tvdbid in (" + ",".join([str(x) for x in epIDs]) + ")"+showStr)
+
+ epList = []
+
+ for curEp in sqlResults:
+ curShowObj = helpers.findCertainShow(sickbeard.showList, int(curEp["showid"]))
+ curEpObj = curShowObj.getEpisode(int(curEp["season"]), int(curEp["episode"]))
+ epList.append(curEpObj)
+
+ return epList
View
50 sickbeard/notifiers/__init__.py
@@ -1,23 +1,27 @@
-import sickbeard
-
-import xbmc
-import growl
-
-from sickbeard.common import *
-
-
-def testGrowl(host, password):
- growl.sendGrowl("Test Growl", "Testing Growl settings from Sick Beard", "Test", host, password)
-
-def testXBMC(host, username, password):
- xbmc.notifyXBMC("Testing XBMC notifications from Sick Beard", "Test Notification", host, username, password)
-
-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])
-
- growl.sendGrowl(notifyStrings[type], message)
+import sickbeard
+
+import xbmc
+import growl
+import mail
+
+from sickbeard.common import *
+
+
+def testGrowl(host, password):
+ growl.sendGrowl("Test Growl", "Testing Growl settings from Sick Beard", "Test", host, password)
+
+def testXBMC(host, username, password):
+ xbmc.notifyXBMC("Testing XBMC notifications from Sick Beard", "Test Notification", host, username, password)
+
+def testMail(server, user, password, sender, receiver):
+ mail._send("Email notification test", server, user, password, sender, receiver)
+
+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])
+
+ growl.sendGrowl(notifyStrings[type], message)
View
2,529 sickbeard/webserve.py
@@ -1,1258 +1,1271 @@
-# Author: Nic Wolfe <nic@wolfeden.ca>
-# URL: http://code.google.com/p/sickbeard/
-#
-# This file is part of Sick Beard.
-#
-# Sick Beard is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Sick Beard is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Sick Beard. If not, see <http://www.gnu.org/licenses/>.
-
-from __future__ import with_statement
-
-import os.path
-
-import gc
-import cgi
-import sqlite3
-import time
-
-from Cheetah.Template import Template
-import cherrypy
-
-from sickbeard import config
-from sickbeard import db
-from sickbeard import history
-from sickbeard import notifiers
-from sickbeard import processTV
-from sickbeard import search
-from sickbeard import ui
-
-from sickbeard import providers
-
-from sickbeard.notifiers import xbmc
-from sickbeard.tv import *
-
-from lib.tvdb_api import tvdb_exceptions
-
-import sickbeard
-import sickbeard.helpers
-from sickbeard import browser
-
-
-class Flash:
- _messages = []
- _errors = []
-
- def message(self, title, detail=''):
- Flash._messages.append((title, detail))
-
- def error(self, title, detail=''):
- Flash._errors.append((title, detail))
-
- def messages(self):
- tempMessages = Flash._messages
- Flash._messages = []
- return tempMessages
-
- def errors(self):
- tempErrors = Flash._errors
- Flash._errors = []
- return tempErrors
-
-flash = Flash()
-
-class PageTemplate (Template):
- def __init__(self, *args, **KWs):
- KWs['file'] = os.path.join(sickbeard.PROG_DIR, "data/interfaces/default/", KWs['file'])
- super(PageTemplate, self).__init__(*args, **KWs)
- self.sbRoot = sickbeard.WEB_ROOT
- self.projectHomePage = "http://code.google.com/p/sickbeard/"
- self.menu = [
- { 'title': 'Home', 'key': 'home' },
- { 'title': 'Coming Episodes', 'key': 'comingEpisodes' },
- { 'title': 'History', 'key': 'history' },
- { 'title': 'Backlog', 'key': 'backlog' },
- { 'title': 'Config', 'key': 'config' },
- ]
- self.flash = Flash()
-
-def redirect(abspath, *args, **KWs):
- assert abspath[0] == '/'
- raise cherrypy.HTTPRedirect(sickbeard.WEB_ROOT + abspath, *args, **KWs)
-
-class TVDBWebUI:
- def __init__(self, config, log=None):
- self.config = config
- self.log = log
-
- def selectSeries(self, allSeries):
-
- searchList = ",".join([x['id'] for x in allSeries])
- showDirList = ""
- for curShowDir in self.config['_showDir']:
- showDirList += "showDir="+curShowDir+"&"
- redirect("/home/addShows/addShow?" + showDirList + "seriesList=" + searchList)
-
-def _munge(string):
- return unicode(string).encode('ascii', 'xmlcharrefreplace')
-
-def _genericMessage(subject, message):
- t = PageTemplate(file="genericMessage.tmpl")
- t.submenu = HomeMenu
- t.subject = subject
- t.message = message
- return _munge(t)
-
-def _getEpisode(show, season, episode):
-
- if show == None or season == None or episode == None:
- return "Invalid parameters"
-
- showObj = sickbeard.helpers.findCertainShow(sickbeard.showList, int(show))
-
- if showObj == None:
- return "Show not in show list"
-
- epObj = showObj.getEpisode(int(season), int(episode))
-
- if epObj == None:
- return "Episode couldn't be retrieved"
-
- return epObj
-
-
-class Backlog:
-
- @cherrypy.expose
- def index(self):
-
- myDB = db.DBConnection()
- sqlResults = myDB.select("SELECT e.*, show_name FROM tv_shows s, tv_episodes e WHERE s.tvdb_id=e.showid AND e.status IN ("+str(BACKLOG)+","+str(DISCBACKLOG)+")")
-
- t = PageTemplate(file="backlog.tmpl")
- t.backlogResults = sqlResults
- t.submenu = [
- { 'title': 'Force Backlog', 'path': 'backlog/forceBacklog' }
- ]
-
- return _munge(t)
-
-
- @cherrypy.expose
- def forceBacklog(self):
-
- # force it to run the next time it looks
- sickbeard.backlogSearchScheduler.forceSearch()
- logger.log("Backlog set to run in background")
- flash.message('Backlog search started',
- 'The backlog search has begun and will run in the background')
-
- redirect("/backlog")
-
-
-
-class History:
-
- @cherrypy.expose
- def index(self):
-
- myDB = db.DBConnection()
-
-# sqlResults = myDB.select("SELECT h.*, show_name, name FROM history h, tv_shows s, tv_episodes e WHERE h.showid=s.tvdb_id AND h.showid=e.showid AND h.season=e.season AND h.episode=e.episode ORDER BY date DESC LIMIT "+str(numPerPage*(p-1))+", "+str(numPerPage))
- sqlResults = myDB.select("SELECT h.*, show_name FROM history h, tv_shows s WHERE h.showid=s.tvdb_id ORDER BY date DESC")
-
- t = PageTemplate(file="history.tmpl")
- t.historyResults = sqlResults
- t.submenu = [
- { 'title': 'Clear History', 'path': 'history/clearHistory' },
- { 'title': 'Trim History', 'path': 'history/trimHistory' },
- ]
-
- return _munge(t)
-
-
- @cherrypy.expose
- def clearHistory(self):
-
- myDB = db.DBConnection()
- myDB.action("DELETE FROM history WHERE 1=1")
- flash.message('History cleared')
- redirect("/history")
-
-
- @cherrypy.expose
- def trimHistory(self):
-
- myDB = db.DBConnection()
- myDB.action("DELETE FROM history WHERE date < "+str((datetime.datetime.today()-datetime.timedelta(days=30)).strftime(history.dateFormat)))
- flash.message('Removed all history entries greater than 30 days old')
- redirect("/history")
-
-
-ConfigMenu = [
- { 'title': 'General', 'path': 'config/general/' },
- { 'title': 'Episode Downloads', 'path': 'config/episodedownloads/' },
- { 'title': 'Search Providers', 'path': 'config/providers/' },
- { 'title': 'Notifications', 'path': 'config/notifications/' },
-]
-
-class ConfigGeneral:
-
- @cherrypy.expose
- def index(self):
-
- t = PageTemplate(file="config_general.tmpl")
- t.submenu = ConfigMenu
- return _munge(t)
-
- @cherrypy.expose
- def saveGeneral(self, log_dir=None, web_port=None, web_log=None,
- launch_browser=None, create_metadata=None, web_username=None,
- web_password=None, quality_default=None, season_folders_default=None,
- version_notify=None, naming_show_name=None, naming_ep_type=None,
- naming_multi_ep_type=None):
-
- results = []
-
- if web_log == "on":
- web_log = 1
- else:
- web_log = 0
-
- if launch_browser == "on":
- launch_browser = 1
- else:
- launch_browser = 0
-
- if create_metadata == "on":
- create_metadata = 1
- else:
- create_metadata = 0
-
- if season_folders_default == "on":
- season_folders_default = 1
- else:
- season_folders_default = 0
-
- if version_notify == "on":
- version_notify = 1
- else:
- version_notify = 0
-
- if naming_show_name == "on":
- naming_show_name = 1
- else:
- naming_show_name = 0
-
- if not config.change_LOG_DIR(log_dir):
- results += ["Unable to create directory " + os.path.normpath(log_dir) + ", log dir not changed."]
-
- sickbeard.LAUNCH_BROWSER = launch_browser
- sickbeard.CREATE_METADATA = create_metadata
- sickbeard.SEASON_FOLDERS_DEFAULT = int(season_folders_default)
- sickbeard.QUALITY_DEFAULT = int(quality_default)
-
- sickbeard.NAMING_SHOW_NAME = naming_show_name
- sickbeard.NAMING_EP_TYPE = int(naming_ep_type)
- sickbeard.NAMING_MULTI_EP_TYPE = int(naming_multi_ep_type)
-
- sickbeard.WEB_PORT = int(web_port)
- sickbeard.WEB_LOG = web_log
- sickbeard.WEB_USERNAME = web_username
- sickbeard.WEB_PASSWORD = web_password
-
- config.change_VERSION_NOTIFY(version_notify)
-
- sickbeard.save_config()
-
- if len(results) > 0:
- for x in results:
- logger.log(x, logger.ERROR)
- flash.error('Error(s) Saving Configuration',
- '<br />\n'.join(results))
- else:
- flash.message('Configuration Saved')
-
- redirect("/config/general/")
-
-class ConfigEpisodeDownloads:
-
- @cherrypy.expose
- def index(self):
-
- t = PageTemplate(file="config_episodedownloads.tmpl")
- t.submenu = ConfigMenu
- return _munge(t)
-
- @cherrypy.expose
- def saveEpisodeDownloads(self, nzb_dir=None, sab_username=None, sab_password=None,
- sab_apikey=None, sab_category=None, sab_host=None, use_nzb=None,
- use_torrent=None, torrent_dir=None, nzb_method=None, usenet_retention=None,
- search_frequency=None, backlog_search_frequency=None, tv_download_dir=None,
- keep_processed_dir=None, process_automatically=None, rename_episodes=None,
- keep_processed_file=None):
-
- results = []
-
- if not config.change_TV_DOWNLOAD_DIR(tv_download_dir):
- results += ["Unable to create directory " + os.path.normpath(tv_download_dir) + ", dir not changed."]
-
- if not config.change_NZB_DIR(nzb_dir):
- results += ["Unable to create directory " + os.path.normpath(nzb_dir) + ", dir not changed."]
-
- if not config.change_TORRENT_DIR(torrent_dir):
- results += ["Unable to create directory " + os.path.normpath(torrent_dir) + ", dir not changed."]
-
- config.change_SEARCH_FREQUENCY(search_frequency)
-
- config.change_BACKLOG_SEARCH_FREQUENCY(backlog_search_frequency)
-
- if process_automatically == "on":
- process_automatically = 1
- else:
- process_automatically = 0
-
- if rename_episodes == "on":
- rename_episodes = 1
- else:
- rename_episodes = 0
-
- if keep_processed_dir == "on":
- keep_processed_dir = 1
- else:
- keep_processed_dir = 0
-
- if keep_processed_file == "on":
- keep_processed_file = 1
- else:
- keep_processed_file = 0
-
- if use_nzb == "on":
- use_nzb = 1
- else:
- use_nzb = 0
-
- if use_torrent == "on":
- use_torrent = 1
- else:
- use_torrent = 0
-
- if usenet_retention == None:
- usenet_retention = 200
-
- sickbeard.PROCESS_AUTOMATICALLY = process_automatically
- sickbeard.KEEP_PROCESSED_DIR = keep_processed_dir
- sickbeard.KEEP_PROCESSED_FILE = keep_processed_file
- sickbeard.RENAME_EPISODES = rename_episodes
-
- sickbeard.NZB_METHOD = nzb_method
- sickbeard.USENET_RETENTION = int(usenet_retention)
- sickbeard.SEARCH_FREQUENCY = int(search_frequency)
-
- sickbeard.USE_NZB = use_nzb
- sickbeard.USE_TORRENT = use_torrent
-
- sickbeard.SAB_USERNAME = sab_username
- sickbeard.SAB_PASSWORD = sab_password
- sickbeard.SAB_APIKEY = sab_apikey
- sickbeard.SAB_CATEGORY = sab_category
- sickbeard.SAB_HOST = sab_host
-
- sickbeard.save_config()
-
- if len(results) > 0:
- for x in results:
- logger.log(x, logger.ERROR)
- flash.error('Error(s) Saving Configuration',
- '<br />\n'.join(results))
- else:
- flash.message('Configuration Saved')
-
- redirect("/config/episodedownloads/")
-
-class ConfigProviders:
-
- @cherrypy.expose
- def index(self):
- t = PageTemplate(file="config_providers.tmpl")
- t.submenu = ConfigMenu
- return _munge(t)
-
-
- @cherrypy.expose
- def saveProviders(self, newzbin=None, newzbin_username=None, newzbin_password=None, tvbinz=None,
- tvbinz_uid=None, tvbinz_hash=None, nzbs=None, nzbs_uid=None, nzbs_hash=None,
- nzbmatrix=None, nzbmatrix_username=None, nzbmatrix_apikey=None, tvnzb=None,
- tvbinz_auth=None, tvbinz_sabuid=None, provider_order=None):
-
- results = []
-
- if newzbin == "on":
- newzbin = 1
- else:
- newzbin = 0
-
- if tvbinz == "on":
- tvbinz = 1
- else:
- tvbinz = 0
-
- if nzbs == "on":
- nzbs = 1
- else:
- nzbs = 0
-
- if nzbmatrix == "on":
- nzbmatrix = 1
- else:
- nzbmatrix = 0
-
- if tvnzb == "on":
- tvnzb = 1
- else:
- tvnzb = 0
-
- sickbeard.NEWZBIN = newzbin
- sickbeard.NEWZBIN_USERNAME = newzbin_username
- sickbeard.NEWZBIN_PASSWORD = newzbin_password
-
- sickbeard.TVBINZ = tvbinz
- sickbeard.TVBINZ_UID = tvbinz_uid
- sickbeard.TVBINZ_SABUID = tvbinz_sabuid
- sickbeard.TVBINZ_HASH = tvbinz_hash
- sickbeard.TVBINZ_AUTH = tvbinz_auth
-
- sickbeard.NZBS = nzbs
- sickbeard.NZBS_UID = nzbs_uid
- sickbeard.NZBS_HASH = nzbs_hash
-
- sickbeard.NZBMATRIX = nzbmatrix
- sickbeard.NZBMATRIX_USERNAME = nzbmatrix_username
- sickbeard.NZBMATRIX_APIKEY = nzbmatrix_apikey
-
- sickbeard.TVNZB = tvnzb
-
- sickbeard.PROVIDER_ORDER = provider_order.split()
-
- sickbeard.save_config()
-
- if len(results) > 0:
- for x in results:
- logger.log(x, logger.ERROR)
- flash.error('Error(s) Saving Configuration',
- '<br />\n'.join(results))
- else:
- flash.message('Configuration Saved')
-
- redirect("/config/providers/")
-
-class ConfigNotifications:
-
- @cherrypy.expose
- def index(self):
- t = PageTemplate(file="config_notifications.tmpl")
- t.submenu = ConfigMenu
- return _munge(t)
-