Merge remote-tracking branch 'remotes/Supremicus/feature/UpdatePushbullet' into develop

This commit is contained in:
Adam 2015-02-24 15:32:45 +08:00
commit 6414377c9c
7 changed files with 177 additions and 152 deletions

View file

@ -5,6 +5,7 @@
* Change webserve code to a logical layout and PEP8
* Add text to explain params passed to extra scripts on Config/Post Processing
* Remove unused SickBeardURLOpener and AuthURLOpener classes
* Update Pushbullet notifier (port from midgetspy/sickbeard)
[develop changelog]

View file

@ -1118,7 +1118,7 @@
<div class="component-group-desc">
<img class="notifier-icon" src="$sbRoot/images/notifiers/pushbullet.png" alt="" title="Pushbullet" />
<h3><a href="<%= anon_url('https://www.pushbullet.com') %>" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false;">Pushbullet</a></h3>
<p>Pushbullet is a platform for receiving custom push notifications to connected devices running Android and desktop Chrome browsers.</p>
<p>Pushbullet allows you to send push notifications to Android, iOS and supported browsers.</p>
</div>
<fieldset class="component-group-list">
<div class="field-pair">
@ -1160,25 +1160,26 @@
</label>
</div>
<div class="field-pair">
<label for="pushbullet_api">
<span class="component-title">Pushbullet API key</span>
<input type="text" name="pushbullet_api" id="pushbullet_api" value="$sickbeard.PUSHBULLET_API" class="form-control input-sm input350" />
<label for="pushbullet_access_token">
<span class="component-title">Pushbullet access token</span>
<input type="text" name="pushbullet_access_token" id="pushbullet_access_token" value="$sickbeard.PUSHBULLET_ACCESS_TOKEN" class="form-control input-sm input250" />
</label>
<label>
<span class="component-title">&nbsp;</span>
<span class="component-desc">API key of your Pushbullet account</span>
<span class="component-desc">get your token at: <a href="<%= anon_url('https://www.pushbullet.com/account') %>" rel="noreferrer" onclick="window.open('${sickbeard.ANON_REDIRECT}' + this.href, '_blank'); return false;">https://www.pushbullet.com/account</a></span>
</label>
</div>
<div class="field-pair">
<label for="pushbullet_device_list">
<span class="component-title">Pushbullet devices</span>
<select name="pushbullet_device_list" id="pushbullet_device_list" class="form-control input-sm"></select>
<input type="hidden" id="pushbullet_device" value="$sickbeard.PUSHBULLET_DEVICE">
<input type="button" class="btn btn-inline" value="Update device list" id="getPushbulletDevices" />
<label for="pushbullet_device_iden">
<span class="component-title">Pushbullet device</span>
<input type="hidden" name="pushbullet_device_iden" id="pushbullet_device_iden" value="$sickbeard.PUSHBULLET_DEVICE_IDEN" size="35" />
<select id="pushbullet_device_list" name="pushbullet_device_list" class="pull-left form-control input-sm" style="margin-right: 5px;">
</select>
<input type="button" class="btn btn-inline" value="Refresh Devices" id="getPushbulletDevices" />
</label>
<label>
<span class="component-title">&nbsp;</span>
<span class="component-desc">select device you wish to push to.</span>
<span class="component-desc">which device do you want to push to?</span>
</label>
</div>
<div class="testNotification" id="testPushbullet-result">Click below to test.</div>

View file

@ -377,68 +377,73 @@ $(document).ready(function(){
});
$('#testPushbullet').click(function () {
var pushbullet_api = $.trim($('#pushbullet_api').val());
if (!pushbullet_api) {
var pushbullet_access_token = $.trim($('#pushbullet_access_token').val());
var pushbullet_device_iden = $('#pushbullet_device_iden').val();
if (!pushbullet_access_token) {
$('#testPushbullet-result').html('Please fill out the necessary fields above.');
$('#pushbullet_api').addClass('warning');
$('#pushbullet_access_token').addClass('warning');
return;
}
$('#pushbullet_api').removeClass('warning');
$('#pushbullet_access_token').removeClass('warning');
$(this).prop('disabled', true);
$('#testPushbullet-result').html(loading);
$.get(sbRoot + '/home/testPushbullet', {'api': pushbullet_api})
$.get(sbRoot + '/home/testPushbullet', {'accessToken': pushbullet_access_token, 'device_iden': pushbullet_device_iden})
.done(function (data) {
$('#testPushbullet-result').html(data);
$('#testPushbullet').prop('disabled', false);
});
});
function get_pushbullet_devices(msg){
if(msg){
function get_pushbullet_devices (msg) {
var pushbullet_access_token = $.trim($('#pushbullet_access_token').val());
if (!pushbullet_access_token) {
$('#testPushbullet-result').html('Please fill out the necessary fields above.');
$('#pushbullet_access_token').addClass('warning');
return;
}
$(this).prop("disabled", true);
if (msg) {
$('#testPushbullet-result').html(loading);
}
var pushbullet_api = $("#pushbullet_api").val();
if(!pushbullet_api) {
$('#testPushbullet-result').html("You didn't supply a Pushbullet api key");
$("#pushbullet_api").focus();
return false;
}
var current_pushbullet_device = $("#pushbullet_device").val();
$.get(sbRoot + "/home/getPushbulletDevices", {'api': pushbullet_api},
function (data) {
var devices = jQuery.parseJSON(data).devices;
$("#pushbullet_device_list").html('');
for (var i = 0; i < devices.length; i++) {
if(devices[i].active == true) {
if(current_pushbullet_device == devices[i].iden) {
$("#pushbullet_device_list").append('<option value="'+devices[i].iden+'" selected>' + devices[i].nickname + '</option>')
} else {
$("#pushbullet_device_list").append('<option value="'+devices[i].iden+'">' + devices[i].nickname + '</option>')
var current_pushbullet_device = $('#pushbullet_device_iden').val();
$.get(sbRoot + '/home/getPushbulletDevices', {'accessToken': pushbullet_access_token})
.done(function (data) {
var devices = jQuery.parseJSON(data || '{}').devices;
$('#pushbullet_device_list').html('');
// add default option to send to all devices
$('#pushbullet_device_list').append('<option value="" selected="selected">-- All Devices --</option>');
if (devices) {
for (var i = 0; i < devices.length; i++) {
// only list active device targets
if (devices[i].active == true) {
// if a device in the list matches our current iden, select it
if (current_pushbullet_device == devices[i].iden) {
$('#pushbullet_device_list').append('<option value="' + devices[i].iden + '" selected="selected">' + devices[i].manufacturer + ' ' + devices[i].nickname + '</option>');
} else {
$('#pushbullet_device_list').append('<option value="' + devices[i].iden + '">' + devices[i].manufacturer + ' ' + devices[i].nickname + '</option>');
}
}
}
}
if(msg) {
$('#getPushbulletDevices').prop('disabled', false);
if (msg) {
$('#testPushbullet-result').html(msg);
}
}
);
});
$("#pushbullet_device_list").change(function(){
$("#pushbullet_device").val($("#pushbullet_device_list").val());
$('#testPushbullet-result').html("Don't forget to save your new pushbullet settings.");
$('#pushbullet_device_list').change(function () {
$('#pushbullet_device_iden').val($('#pushbullet_device_list').val());
$('#testPushbullet-result').html('Don\'t forget to save your new Pushbullet settings.');
});
};
}
$('#getPushbulletDevices').click(function(){
get_pushbullet_devices("Device list updated. Please choose a device to push to.");
$('#getPushbulletDevices').click(function () {
get_pushbullet_devices('Device list updated. Select specific device to use.');
});
// we have to call this function on dom ready to create the devices select
get_pushbullet_devices();
if ($('#use_pushbullet').prop('checked')) {
get_pushbullet_devices();
}
$('#email_show').change(function () {
var key = parseInt($('#email_show').val(), 10);

View file

@ -60,7 +60,7 @@ CFG = None
CONFIG_FILE = None
# This is the version of the config we EXPECT to find
CONFIG_VERSION = 8
CONFIG_VERSION = 9
# Default encryption version (0 for None)
ENCRYPTION_VERSION = 0
@ -396,8 +396,8 @@ USE_PUSHBULLET = False
PUSHBULLET_NOTIFY_ONSNATCH = False
PUSHBULLET_NOTIFY_ONDOWNLOAD = False
PUSHBULLET_NOTIFY_ONSUBTITLEDOWNLOAD = False
PUSHBULLET_API = None
PUSHBULLET_DEVICE = None
PUSHBULLET_ACCESS_TOKEN = None
PUSHBULLET_DEVICE_IDEN = None
USE_EMAIL = False
EMAIL_NOTIFY_ONSNATCH = False
@ -481,7 +481,7 @@ def initialize(consoleLogging=True):
USE_PYTIVO, PYTIVO_NOTIFY_ONSNATCH, PYTIVO_NOTIFY_ONDOWNLOAD, PYTIVO_NOTIFY_ONSUBTITLEDOWNLOAD, PYTIVO_UPDATE_LIBRARY, PYTIVO_HOST, PYTIVO_SHARE_NAME, PYTIVO_TIVO_NAME, \
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, \
USE_PUSHBULLET, PUSHBULLET_NOTIFY_ONSNATCH, PUSHBULLET_NOTIFY_ONDOWNLOAD, PUSHBULLET_NOTIFY_ONSUBTITLEDOWNLOAD, PUSHBULLET_ACCESS_TOKEN, PUSHBULLET_DEVICE_IDEN, \
versionCheckScheduler, VERSION_NOTIFY, AUTO_UPDATE, NOTIFY_ON_UPDATE, PROCESS_AUTOMATICALLY, UNPACK, CPU_PRESET, \
KEEP_PROCESSED_DIR, PROCESS_METHOD, TV_DOWNLOAD_DIR, MIN_RECENTSEARCH_FREQUENCY, DEFAULT_UPDATE_FREQUENCY, MIN_UPDATE_FREQUENCY, UPDATE_FREQUENCY, \
showQueueScheduler, searchQueueScheduler, ROOT_DIRS, CACHE_DIR, ACTUAL_CACHE_DIR, TIMEZONE_DISPLAY, \
@ -875,8 +875,8 @@ def initialize(consoleLogging=True):
PUSHBULLET_NOTIFY_ONDOWNLOAD = bool(check_setting_int(CFG, 'Pushbullet', 'pushbullet_notify_ondownload', 0))
PUSHBULLET_NOTIFY_ONSUBTITLEDOWNLOAD = bool(
check_setting_int(CFG, 'Pushbullet', 'pushbullet_notify_onsubtitledownload', 0))
PUSHBULLET_API = check_setting_str(CFG, 'Pushbullet', 'pushbullet_api', '')
PUSHBULLET_DEVICE = check_setting_str(CFG, 'Pushbullet', 'pushbullet_device', '')
PUSHBULLET_ACCESS_TOKEN = check_setting_str(CFG, 'Pushbullet', 'pushbullet_access_token', '')
PUSHBULLET_DEVICE_IDEN = check_setting_str(CFG, 'Pushbullet', 'pushbullet_device_iden', '')
USE_EMAIL = bool(check_setting_int(CFG, 'Email', 'use_email', 0))
EMAIL_NOTIFY_ONSNATCH = bool(check_setting_int(CFG, 'Email', 'email_notify_onsnatch', 0))
@ -1724,8 +1724,8 @@ def save_config():
new_config['Pushbullet']['pushbullet_notify_onsnatch'] = int(PUSHBULLET_NOTIFY_ONSNATCH)
new_config['Pushbullet']['pushbullet_notify_ondownload'] = int(PUSHBULLET_NOTIFY_ONDOWNLOAD)
new_config['Pushbullet']['pushbullet_notify_onsubtitledownload'] = int(PUSHBULLET_NOTIFY_ONSUBTITLEDOWNLOAD)
new_config['Pushbullet']['pushbullet_api'] = PUSHBULLET_API
new_config['Pushbullet']['pushbullet_device'] = PUSHBULLET_DEVICE
new_config['Pushbullet']['pushbullet_access_token'] = PUSHBULLET_ACCESS_TOKEN
new_config['Pushbullet']['pushbullet_device_iden'] = PUSHBULLET_DEVICE_IDEN
new_config['Email'] = {}
new_config['Email']['use_email'] = int(USE_EMAIL)

View file

@ -449,8 +449,9 @@ class ConfigMigrator():
4: 'Add newznab catIDs',
5: 'Metadata update',
6: 'Rename daily search to recent search',
7: 'Rename coming episodes to episode view'
}
7: 'Rename coming episodes to episode view',
8: 'Disable searches on start',
9: 'Rename pushbullet variables',}
def migrate_config(self):
"""
@ -745,3 +746,7 @@ class ConfigMigrator():
# removing settings from gui and making it a hidden debug option
sickbeard.RECENTSEARCH_STARTUP = False
sickbeard.BACKLOG_STARTUP = False
def _migrate_v9(self):
sickbeard.PUSHBULLET_ACCESS_TOKEN = check_setting_str(self.config_obj, 'Pushbullet', 'pushbullet_api', '')
sickbeard.PUSHBULLET_DEVICE_IDEN = check_setting_str(self.config_obj, 'Pushbullet', 'pushbullet_device', '')

View file

@ -1,5 +1,4 @@
# Author: Pedro Correia (http://github.com/pedrocorreia/)
# Based on pushalot.py by Nic Wolfe <nic@wolfeden.ca>
# Author: Nic Wolfe <nic@wolfeden.ca>
# URL: http://code.google.com/p/sickbeard/
#
# This file is part of SickGear.
@ -17,109 +16,123 @@
# You should have received a copy of the GNU General Public License
# along with SickGear. If not, see <http://www.gnu.org/licenses/>.
import urllib
import urllib2
import socket
import base64
from httplib import HTTPSConnection, HTTPException
import json
from ssl import SSLError
import sickbeard
from sickbeard import logger, common
from sickbeard import logger
from sickbeard.common import notifyStrings, NOTIFY_SNATCH, NOTIFY_DOWNLOAD, NOTIFY_SUBTITLE_DOWNLOAD, NOTIFY_GIT_UPDATE, NOTIFY_GIT_UPDATE_TEXT
from sickbeard.exceptions import ex
PUSHAPI_ENDPOINT = 'https://api.pushbullet.com/v2/pushes'
DEVICEAPI_ENDPOINT = 'https://api.pushbullet.com/v2/devices'
class PushbulletNotifier:
def test_notify(self, pushbullet_api):
return self._sendPushbullet(pushbullet_api, event="Test", message="Testing Pushbullet settings from SickGear",
method="POST", notificationType="note", force=True)
def get_devices(self, pushbullet_api):
return self._sendPushbullet(pushbullet_api, method="GET", force=True)
def get_devices(self, accessToken=None):
# fill in omitted parameters
if not accessToken:
accessToken = sickbeard.PUSHBULLET_ACCESS_TOKEN
def notify_snatch(self, ep_name):
if sickbeard.PUSHBULLET_NOTIFY_ONSNATCH:
self._sendPushbullet(pushbullet_api=None, event=common.notifyStrings[common.NOTIFY_SNATCH] + " : " + ep_name, message=ep_name,
notificationType="note", method="POST")
# get devices from pushbullet
try:
req = urllib2.Request(DEVICEAPI_ENDPOINT)
base64string = base64.encodestring('%s:%s' % (accessToken, ''))[:-1]
req.add_header('Authorization', 'Basic %s' % base64string)
handle = urllib2.urlopen(req)
if handle:
result = handle.read()
handle.close()
return result
except urllib2.URLError:
return None
except socket.timeout:
return None
def notify_download(self, ep_name):
if sickbeard.PUSHBULLET_NOTIFY_ONDOWNLOAD:
self._sendPushbullet(pushbullet_api=None, event=common.notifyStrings[common.NOTIFY_DOWNLOAD] + " : " + ep_name,
message=ep_name, notificationType="note", method="POST")
def _sendPushbullet(self, title, body, accessToken, device_iden):
def notify_subtitle_download(self, ep_name, lang):
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_git_update(self, new_version = "??"):
if sickbeard.USE_PUSHBULLET:
update_text=common.notifyStrings[common.NOTIFY_GIT_UPDATE_TEXT]
title=common.notifyStrings[common.NOTIFY_GIT_UPDATE]
self._sendPushbullet(pushbullet_api=None, event=title, message=update_text + new_version, method="POST")
# build up the URL and parameters
body = body.strip().encode('utf-8')
def _sendPushbullet(self, pushbullet_api=None, pushbullet_device=None, event=None, message=None,
notificationType=None, method=None, force=False):
data = urllib.urlencode({
'type': 'note',
'title': title,
'body': body,
'device_iden': device_iden
})
# send the request to pushbullet
try:
req = urllib2.Request(PUSHAPI_ENDPOINT)
base64string = base64.encodestring('%s:%s' % (accessToken, ''))[:-1]
req.add_header('Authorization', 'Basic %s' % base64string)
handle = urllib2.urlopen(req, data)
handle.close()
except socket.timeout:
return False
except urllib2.URLError, e:
if e.code == 404:
logger.log(u'PUSHBULLET: Access token is wrong/not associated to a device.', logger.ERROR)
elif e.code == 401:
logger.log(u'PUSHBULLET: Unauthorized, not a valid access token.', logger.ERROR)
elif e.code == 400:
logger.log(u'PUSHBULLET: Bad request, missing required parameter.', logger.ERROR)
elif e.code == 503:
logger.log(u'PUSHBULLET: Pushbullet server to busy to handle the request at this time.', logger.WARNING)
return False
logger.log(u'PUSHBULLET: Notification successful.', logger.MESSAGE)
return True
def _notifyPushbullet(self, title, body, accessToken=None, device_iden=None, force=False):
"""
Sends a pushbullet notification based on the provided info or SG config
title: The title of the notification to send
body: The body string to send
accessToken: The access token to grant access
device_iden: The iden of a specific target, if none provided send to all devices
force: If True then the notification will be sent even if Pushbullet is disabled in the config
"""
# suppress notifications if the notifier is disabled but the notify options are checked
if not sickbeard.USE_PUSHBULLET and not force:
return False
if pushbullet_api == None:
pushbullet_api = sickbeard.PUSHBULLET_API
if pushbullet_device == None:
pushbullet_device = sickbeard.PUSHBULLET_DEVICE
# fill in omitted parameters
if not accessToken:
accessToken = sickbeard.PUSHBULLET_ACCESS_TOKEN
if not device_iden:
device_iden = sickbeard.PUSHBULLET_DEVICE_IDEN
if method == 'POST':
uri = '/v2/pushes'
else:
uri = '/v2/devices'
logger.log(u'PUSHBULLET: Sending notice with details: \"%s - %s\", device_iden: %s' % (title, body, device_iden), logger.DEBUG)
logger.log(u"Pushbullet event: " + str(event), logger.DEBUG)
logger.log(u"Pushbullet message: " + str(message), logger.DEBUG)
logger.log(u"Pushbullet api: " + str(pushbullet_api), logger.DEBUG)
logger.log(u"Pushbullet devices: " + str(pushbullet_device), logger.DEBUG)
logger.log(u"Pushbullet notification type: " + str(notificationType), logger.DEBUG)
return self._sendPushbullet(title, body, accessToken, device_iden)
http_handler = HTTPSConnection("api.pushbullet.com")
def notify_snatch(self, ep_name):
if sickbeard.PUSHBULLET_NOTIFY_ONSNATCH:
self._notifyPushbullet(notifyStrings[NOTIFY_SNATCH], ep_name)
if notificationType == None:
testMessage = True
try:
logger.log(u"Testing Pushbullet authentication and retrieving the device list.", logger.DEBUG)
http_handler.request(method, uri, None, headers={'Authorization': 'Bearer %s' % pushbullet_api})
except (SSLError, HTTPException, socket.error):
logger.log(u"Pushbullet notification failed.", logger.ERROR)
return False
else:
testMessage = False
try:
data = {
'title': event.encode('utf-8'),
'body': message.encode('utf-8'),
'device_iden': pushbullet_device,
'type': notificationType}
data = json.dumps(data)
http_handler.request(method, uri, body=data,
headers={'Content-Type': 'application/json', 'Authorization': 'Bearer %s' % pushbullet_api})
pass
except (SSLError, HTTPException, socket.error):
return False
def notify_download(self, ep_name):
if sickbeard.PUSHBULLET_NOTIFY_ONDOWNLOAD:
self._notifyPushbullet(notifyStrings[NOTIFY_DOWNLOAD], ep_name)
response = http_handler.getresponse()
request_body = response.read()
request_status = response.status
logger.log(u"Pushbullet response: %s" % request_body, logger.DEBUG)
def notify_subtitle_download(self, ep_name, lang):
if sickbeard.PUSHBULLET_NOTIFY_ONSUBTITLEDOWNLOAD:
self._notifyPushbullet(notifyStrings[NOTIFY_SUBTITLE_DOWNLOAD], ep_name + ': ' + lang)
if request_status == 200:
if testMessage:
return request_body
else:
logger.log(u"Pushbullet notifications sent.", logger.DEBUG)
return True
elif request_status == 410:
logger.log(u"Pushbullet authentication failed: %s" % response.reason, logger.ERROR)
return False
else:
logger.log(u"Pushbullet notification failed.", logger.ERROR)
return False
def notify_git_update(self, new_version = '??'):
if sickbeard.USE_PUSHBULLET:
update_text=notifyStrings[NOTIFY_GIT_UPDATE_TEXT]
title=notifyStrings[NOTIFY_GIT_UPDATE]
self._notifyPushbullet(title, update_text + new_version)
def test_notify(self, accessToken, device_iden):
return self._notifyPushbullet('Test', 'This is a test notification from SickGear', accessToken, device_iden, force=True)
notifier = PushbulletNotifier

View file

@ -817,19 +817,19 @@ class Home(MainHandler):
else:
return 'Error sending Pushalot notification'
def testPushbullet(self, api=None):
def testPushbullet(self, accessToken=None, device_iden=None):
self.set_header('Cache-Control', 'max-age=0,no-cache,no-store')
result = notifiers.pushbullet_notifier.test_notify(api)
result = notifiers.pushbullet_notifier.test_notify(accessToken, device_iden)
if result:
return 'Pushbullet notification succeeded. Check your device to make sure it worked'
else:
return 'Error sending Pushbullet notification'
def getPushbulletDevices(self, api=None):
def getPushbulletDevices(self, accessToken=None):
self.set_header('Cache-Control', 'max-age=0,no-cache,no-store')
result = notifiers.pushbullet_notifier.get_devices(api)
result = notifiers.pushbullet_notifier.get_devices(accessToken)
if result:
return result
else:
@ -4067,8 +4067,8 @@ class ConfigNotifications(Config):
use_pushalot=None, pushalot_notify_onsnatch=None, pushalot_notify_ondownload=None,
pushalot_notify_onsubtitledownload=None, pushalot_authorizationtoken=None,
use_pushbullet=None, pushbullet_notify_onsnatch=None, pushbullet_notify_ondownload=None,
pushbullet_notify_onsubtitledownload=None, pushbullet_api=None, pushbullet_device=None,
pushbullet_device_list=None,
pushbullet_notify_onsubtitledownload=None, pushbullet_access_token=None,
pushbullet_device_iden=None, pushbullet_device_list=None,
use_email=None, email_notify_onsnatch=None, email_notify_ondownload=None,
email_notify_onsubtitledownload=None, email_host=None, email_port=25, email_from=None,
email_tls=None, email_user=None, email_password=None, email_list=None, email_show_list=None,
@ -4210,8 +4210,8 @@ class ConfigNotifications(Config):
sickbeard.PUSHBULLET_NOTIFY_ONSNATCH = config.checkbox_to_value(pushbullet_notify_onsnatch)
sickbeard.PUSHBULLET_NOTIFY_ONDOWNLOAD = config.checkbox_to_value(pushbullet_notify_ondownload)
sickbeard.PUSHBULLET_NOTIFY_ONSUBTITLEDOWNLOAD = config.checkbox_to_value(pushbullet_notify_onsubtitledownload)
sickbeard.PUSHBULLET_API = pushbullet_api
sickbeard.PUSHBULLET_DEVICE = pushbullet_device_list
sickbeard.PUSHBULLET_ACCESS_TOKEN = pushbullet_access_token
sickbeard.PUSHBULLET_DEVICE_IDEN = pushbullet_device_iden
sickbeard.save_config()