Merge pull request #1955 from jmullan/feature/refactor_config

Reduce headphones module-level variables and reduce usage of globals, refactor processing of config from web form.
This commit is contained in:
AdeHub
2014-10-27 18:48:04 +13:00
33 changed files with 1178 additions and 1863 deletions

View File

@@ -21,8 +21,6 @@ sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'lib/'))
from headphones import webstart, logger
from configobj import ConfigObj
import locale
import time
import signal
@@ -114,9 +112,9 @@ def main():
headphones.DATA_DIR = headphones.PROG_DIR
if args.config:
headphones.CONFIG_FILE = args.config
config_file = args.config
else:
headphones.CONFIG_FILE = os.path.join(headphones.DATA_DIR, 'config.ini')
config_file = os.path.join(headphones.DATA_DIR, 'config.ini')
# Try to create the DATA_DIR if it doesn't exist
if not os.path.exists(headphones.DATA_DIR):
@@ -131,10 +129,9 @@ def main():
# Put the database in the DATA_DIR
headphones.DB_FILE = os.path.join(headphones.DATA_DIR, 'headphones.db')
headphones.CFG = ConfigObj(headphones.CONFIG_FILE, encoding='utf-8')
# Read config and start logging
headphones.initialize()
headphones.initialize(config_file)
if headphones.DAEMON:
headphones.daemonize()
@@ -147,24 +144,25 @@ def main():
http_port = args.port
logger.info('Using forced web server port: %i', http_port)
else:
http_port = int(headphones.HTTP_PORT)
http_port = int(headphones.CONFIG.HTTP_PORT)
# Try to start the server. Will exit here is address is already in use.
webstart.initialize({
web_config = {
'http_port': http_port,
'http_host': headphones.HTTP_HOST,
'http_root': headphones.HTTP_ROOT,
'http_proxy': headphones.HTTP_PROXY,
'enable_https': headphones.ENABLE_HTTPS,
'https_cert': headphones.HTTPS_CERT,
'https_key': headphones.HTTPS_KEY,
'http_username': headphones.HTTP_USERNAME,
'http_password': headphones.HTTP_PASSWORD,
})
'http_host': headphones.CONFIG.HTTP_HOST,
'http_root': headphones.CONFIG.HTTP_ROOT,
'http_proxy': headphones.CONFIG.HTTP_PROXY,
'enable_https': headphones.CONFIG.ENABLE_HTTPS,
'https_cert': headphones.CONFIG.HTTPS_CERT,
'https_key': headphones.CONFIG.HTTPS_KEY,
'http_username': headphones.CONFIG.HTTP_USERNAME,
'http_password': headphones.CONFIG.HTTP_PASSWORD,
}
webstart.initialize(web_config)
if headphones.LAUNCH_BROWSER and not args.nolaunch:
headphones.launch_browser(headphones.HTTP_HOST, http_port,
headphones.HTTP_ROOT)
if headphones.CONFIG.LAUNCH_BROWSER and not args.nolaunch:
headphones.launch_browser(headphones.CONFIG.HTTP_HOST, http_port,
headphones.CONFIG.HTTP_ROOT)
# Start the background threads
headphones.start()
@@ -190,4 +188,4 @@ def main():
# Call main()
if __name__ == "__main__":
main()
main()

View File

@@ -163,21 +163,21 @@
}
<%
if headphones.SONGKICK_FILTER_ENABLED:
if headphones.CONFIG.SONGKICK_FILTER_ENABLED:
songkick_filter_enabled = "true"
else:
songkick_filter_enabled = "false"
if not headphones.SONGKICK_LOCATION:
if not headphones.CONFIG.SONGKICK_LOCATION:
songkick_location = "none"
else:
songkick_location = headphones.SONGKICK_LOCATION
if headphones.SONGKICK_ENABLED:
songkick_location = headphones.CONFIG.SONGKICK_LOCATION
if headphones.CONFIG.SONGKICK_ENABLED:
songkick_enabled = "true"
else:
songkick_enabled = "false"
%>
function getArtistsCalendar() {
var template, calendarDomNode;
@@ -186,16 +186,16 @@
template = '<li><a target="_blank" href="URI"><span class="sk-name">NAME</span><span class="sk-location">LOC</span></a></li>';
$.getJSON("https://api.songkick.com/api/3.0/artists/mbid:${artist['ArtistID']}/calendar.json?apikey=${headphones.SONGKICK_APIKEY}&jsoncallback=?",
$.getJSON("https://api.songkick.com/api/3.0/artists/mbid:${artist['ArtistID']}/calendar.json?apikey=${headphones.CONFIG.SONGKICK_APIKEY}&jsoncallback=?",
function(data){
if (data['resultsPage'].totalEntries >= 1) {
if (data['resultsPage'].totalEntries >= 1) {
if( ${songkick_filter_enabled} ) {
data.resultsPage.results.event = $.grep(data.resultsPage.results.event, function(element,index){
return element.venue.metroArea.id == ${songkick_location};
});
}
var tourDate;
calendarDomNode.show();
@@ -211,7 +211,7 @@
});
calendarDomNode.append('<li><img src="interfaces/default/images/songkick.png" alt="concerts by songkick" class="sk-logo" /></li>');
$(function() {
$("#artistCalendar").each(function() {
$("li:gt(4)", this).hide(); /* :gt() is zero-indexed */
@@ -269,7 +269,7 @@
$('#dialog').dialog();
event.preventDefault();
});
$('#menu_link_modifyextra').click(function() {
$('#menu_link_modifyextra').click(function(event) {
$('#dialog').dialog();
event.preventDefault();
});

View File

@@ -38,7 +38,7 @@
</div>
% elif headphones.CURRENT_VERSION != headphones.LATEST_VERSION and headphones.COMMITS_BEHIND > 0 and headphones.INSTALL_TYPE != 'win':
<div id="updatebar">
A <a href="https://github.com/${headphones.GIT_USER}/headphones/compare/${headphones.CURRENT_VERSION}...${headphones.LATEST_VERSION}"> newer version</a> is available. You're ${headphones.COMMITS_BEHIND} commits behind. <a href="update">Update</a> or <a href="#" onclick="$('#updatebar').slideUp('slow');">Close</a>
A <a href="https://github.com/${headphones.CONFIG.GIT_USER}/headphones/compare/${headphones.CURRENT_VERSION}...${headphones.LATEST_VERSION}"> newer version</a> is available. You're ${headphones.COMMITS_BEHIND} commits behind. <a href="update">Update</a> or <a href="#" onclick="$('#updatebar').slideUp('slow');">Close</a>
</div>
% endif
@@ -96,8 +96,8 @@
%if version.HEADPHONES_VERSION != 'master':
(${version.HEADPHONES_VERSION})
%endif
%if headphones.GIT_BRANCH != 'master':
(${headphones.GIT_BRANCH})
%if headphones.CONFIG.GIT_BRANCH != 'master':
(${headphones.CONFIG.GIT_BRANCH})
%endif
</div>
</footer>

View File

@@ -414,7 +414,7 @@
<fieldset>
<legend>Headphones Indexer</legend>
<div class="row checkbox">
<input id="use_headphones_indexer" type="checkbox" name="use_headphones_indexer" onclick="initConfigCheckbox($(this));" value="1" ${config['use_headphones_indexer']} /><label>Use Headphones Indexer</label>
<input id="headphones_indexer" type="checkbox" name="headphones_indexer" onclick="initConfigCheckbox($(this));" value="1" ${config['headphones_indexer']} /><label>Use Headphones Indexer</label>
</div>
<div class="config">
<div class="row">
@@ -1320,7 +1320,7 @@
<select name="interface"><h3>
%for interface in config['interface_list']:
<%
if interface == headphones.INTERFACE:
if interface == headphones.CONFIG.INTERFACE:
selected = 'selected="selected"'
else:
selected = ''
@@ -1369,7 +1369,7 @@
<select name="mirror" id="mirror">
%for mirror in config['mirror_list']:
<%
if mirror == headphones.MIRROR:
if mirror == headphones.CONFIG.MIRROR:
selected = 'selected="selected"'
else:
selected = ''
@@ -2030,7 +2030,7 @@
$( "#tabs" ).tabs();
});
initActions();
initConfigCheckbox("#use_headphones_indexer");
initConfigCheckbox("#headphones_indexer");
initConfigCheckbox("#usenewznab");
initConfigCheckbox("#usenzbsorg");
initConfigCheckbox("#useomgwtfnzbs");

View File

@@ -20,7 +20,7 @@
</div>
</div>
<a class="menu_link_edit" href="manageArtists"><i class="fa fa-pencil"></i> Manage Artists</a>
%if not headphones.ADD_ARTISTS:
%if not headphones.CONFIG.AUTO_ADD_ARTISTS:
<a class="menu_link_edit" href="manageNew"><i class="fa fa-pencil"></i> Manage New Artists</a>
%endif
<a class="menu_link_edit" href="manageUnmatched"><i class="fa fa-pencil"></i> Manage Unmatched</a>
@@ -53,18 +53,18 @@
<br/>
<div class="row">
<label for="">Path to directory</label>
%if headphones.MUSIC_DIR:
<input type="text" value="${headphones.MUSIC_DIR}" name="path" size="70" />
%if headphones.CONFIG.MUSIC_DIR:
<input type="text" value="${headphones.CONFIG.MUSIC_DIR}" name="path" size="70" />
%else:
<input type="text" value="Enter a Music Directory to scan" onfocus="if
(this.value==this.defaultValue) this.value='';" name="path" size="70" />
%endif
</div>
<div class="row checkbox">
<input type="checkbox" name="libraryscan" id="libraryscan" value="1" ${checked(headphones.LIBRARYSCAN)}><label>Automatically scan library</label>
<input type="checkbox" name="libraryscan" id="libraryscan" value="1" ${checked(headphones.CONFIG.LIBRARYSCAN)}><label>Automatically scan library</label>
</div>
<div class="row checkbox">
<input type="checkbox" name="autoadd" id="autoadd" value="1" ${checked(headphones.ADD_ARTISTS)}><label>Auto-add new artists</label>
<input type="checkbox" name="autoadd" id="autoadd" value="1" ${checked(headphones.CONFIG.AUTO_ADD_ARTISTS)}><label>Auto-add new artists</label>
</div>
</fieldset>
@@ -83,8 +83,8 @@
<div class="row">
<label for="">Username</label>
<%
if headphones.LASTFM_USERNAME:
lastfmvalue = headphones.LASTFM_USERNAME
if headphones.CONFIG.LASTFM_USERNAME:
lastfmvalue = headphones.CONFIG.LASTFM_USERNAME
else:
lastfmvalue = ''
%>

View File

@@ -6,7 +6,7 @@
<%def name="headerIncludes()">
<div id="subhead_container">
<div id="subhead_menu">
<a id="menu_link_scan" onclick="doAjaxCall('musicScan?path=${headphones.MUSIC_DIR}&redirect=manageNew',$(this))" data-success="Music library is getting scanned">Scan Music Library</a>
<a id="menu_link_scan" onclick="doAjaxCall('musicScan?path=${headphones.CONFIG.MUSIC_DIR}&redirect=manageNew',$(this))" data-success="Music library is getting scanned">Scan Music Library</a>
</div>
</div>
<a href="manage" class="back">&laquo; Back to manage overview</a>

File diff suppressed because it is too large Load Diff

View File

@@ -72,7 +72,7 @@ def switch(AlbumID, ReleaseID):
total_track_count = len(newtrackdata)
have_track_count = len(myDB.select('SELECT * from tracks WHERE AlbumID=? AND Location IS NOT NULL', [AlbumID]))
if oldalbumdata['Status'] == 'Skipped' and ((have_track_count/float(total_track_count)) >= (headphones.ALBUM_COMPLETION_PCT/100.0)):
if oldalbumdata['Status'] == 'Skipped' and ((have_track_count/float(total_track_count)) >= (headphones.CONFIG.ALBUM_COMPLETION_PCT/100.0)):
myDB.action('UPDATE albums SET Status=? WHERE AlbumID=?', ['Downloaded', AlbumID])
# Update have track counts on index

View File

@@ -44,13 +44,13 @@ class Api(object):
def checkParams(self,*args,**kwargs):
if not headphones.API_ENABLED:
if not headphones.CONFIG.API_ENABLED:
self.data = 'API not enabled'
return
if not headphones.API_KEY:
if not headphones.CONFIG.API_KEY:
self.data = 'API key not generated'
return
if len(headphones.API_KEY) != 32:
if len(headphones.CONFIG.API_KEY) != 32:
self.data = 'API key not generated correctly'
return
@@ -58,7 +58,7 @@ class Api(object):
self.data = 'Missing api key'
return
if kwargs['apikey'] != headphones.API_KEY:
if kwargs['apikey'] != headphones.CONFIG.API_KEY:
self.data = 'Incorrect API key'
return
else:
@@ -314,7 +314,7 @@ class Api(object):
def _getVersion(self, **kwargs):
self.data = {
'git_path' : headphones.GIT_PATH,
'git_path' : headphones.CONFIG.GIT_PATH,
'install_type' : headphones.INSTALL_TYPE,
'current_version' : headphones.CURRENT_VERSION,
'latest_version' : headphones.LATEST_VERSION,

View File

@@ -40,7 +40,7 @@ class Cache(object):
and for info it is <musicbrainzid>.<date>.txt
"""
path_to_art_cache = os.path.join(headphones.CACHE_DIR, 'artwork')
path_to_art_cache = os.path.join(headphones.CONFIG.CACHE_DIR, 'artwork')
def __init__(self):
self.id = None

426
headphones/config.py Normal file
View File

@@ -0,0 +1,426 @@
import headphones.logger
import itertools
import os
import re
from configobj import ConfigObj
def bool_int(value):
"""
Casts a config value into a 0 or 1
"""
if isinstance(value, basestring):
if value.lower() in ('', '0', 'false', 'f', 'no', 'n', 'off'):
value = 0
return int(bool(value))
_config_definitions = {
'ADD_ALBUM_ART': (int, 'General', 0),
'ADVANCEDENCODER': (str, 'General', ''),
'ALBUM_ART_FORMAT': (str, 'General', 'folder'),
'ALBUM_COMPLETION_PCT': (int, 'Advanced', 80), # This is used in importer.py to determine how complete an album needs to be - to be considered "downloaded". Percentage from 0-100
'API_ENABLED': (int, 'General', 0),
'API_KEY': (str, 'General', ''),
'AUTOWANT_ALL': (int, 'General', 0),
'AUTOWANT_MANUALLY_ADDED': (int, 'General', 1),
'AUTOWANT_UPCOMING': (int, 'General', 1),
'AUTO_ADD_ARTISTS': (int, 'General', 1),
'BITRATE': (int, 'General', 192),
'BLACKHOLE': (int, 'General', 0),
'BLACKHOLE_DIR': (str, 'General', ''),
'BOXCAR_ENABLED': (int, 'Boxcar', 0),
'BOXCAR_ONSNATCH': (int, 'Boxcar', 0),
'BOXCAR_TOKEN': (str, 'Boxcar', ''),
'CACHE_DIR': (str, 'General', ''),
'CACHE_SIZEMB': (int, 'Advanced', 32),
'CHECK_GITHUB': (int, 'General', 1),
'CHECK_GITHUB_INTERVAL': (int, 'General', 360),
'CHECK_GITHUB_ON_STARTUP': (int, 'General', 1),
'CLEANUP_FILES': (int, 'General', 0),
'CONFIG_VERSION': (str, 'General', '0'),
'CORRECT_METADATA': (int, 'General', 0),
'CUSTOMHOST': (str, 'General', 'localhost'),
'CUSTOMPORT': (int, 'General', 5000),
'CUSTOMSLEEP': (int, 'General', 1),
'DELETE_LOSSLESS_FILES': (int, 'General', 1),
'DESTINATION_DIR': (str, 'General', ''),
'DETECT_BITRATE': (int, 'General', 0),
'DOWNLOAD_DIR': (str, 'General', ''),
'DOWNLOAD_SCAN_INTERVAL': (int, 'General', 5),
'DOWNLOAD_TORRENT_DIR': (str, 'General', ''),
'DO_NOT_OVERRIDE_GIT_BRANCH': (int, 'General', 0),
'EMBED_ALBUM_ART': (int, 'General', 0),
'EMBED_LYRICS': (int, 'General', 0),
'ENABLE_HTTPS': (int, 'General', 0),
'ENCODER': (str, 'General', 'ffmpeg'),
'ENCODERFOLDER': (str, 'General', ''),
'ENCODERLOSSLESS': (int, 'General', 1),
'ENCODEROUTPUTFORMAT': (str, 'General', 'mp3'),
'ENCODERQUALITY': (int, 'General', 2),
'ENCODERVBRCBR': (str, 'General', 'cbr'),
'ENCODER_MULTICORE': (int, 'General', 0),
'ENCODER_MULTICORE_COUNT': (int, 'General', 0),
'ENCODER_PATH': (str, 'General', ''),
'EXTRAS': (str, 'General', ''),
'EXTRA_NEWZNABS': (list, 'Newznab', ''),
'FILE_FORMAT': (str, 'General', 'Track Artist - Album [Year] - Title'),
'FILE_PERMISSIONS': (str, 'General', '0644'),
'FILE_UNDERSCORES': (int, 'General', 0),
'FOLDER_FORMAT': (str, 'General', 'Artist/Album [Year]'),
'FOLDER_PERMISSIONS': (str, 'General', '0755'),
'FREEZE_DB': (int, 'General', 0),
'GIT_BRANCH': (str, 'General', 'master'),
'GIT_PATH': (str, 'General', ''),
'GIT_USER': (str, 'General', 'rembo10'),
'GROWL_ENABLED': (int, 'Growl', 0),
'GROWL_HOST': (str, 'Growl', ''),
'GROWL_ONSNATCH': (int, 'Growl', 0),
'GROWL_PASSWORD': (str, 'Growl', ''),
'HEADPHONES_INDEXER': (bool_int, 'General', False),
'HPPASS': (str, 'General', ''),
'HPUSER': (str, 'General', ''),
'HTTPS_CERT': (str, 'General', ''),
'HTTPS_KEY': (str, 'General', ''),
'HTTP_HOST': (str, 'General', '0.0.0.0'),
'HTTP_PASSWORD': (str, 'General', ''),
'HTTP_PORT': (int, 'General', 8181),
'HTTP_PROXY': (int, 'General', 0),
'HTTP_ROOT': (str, 'General', '/'),
'HTTP_USERNAME': (str, 'General', ''),
'IGNORED_WORDS': (str, 'General', ''),
'INCLUDE_EXTRAS': (int, 'General', 0),
'INTERFACE': (str, 'General', 'default'),
'JOURNAL_MODE': (str, 'Advanced', 'wal'),
'KAT': (int, 'Kat', 0),
'KAT_PROXY_URL': (str, 'Kat', ''),
'KAT_RATIO': (str, 'Kat', ''),
'KEEP_NFO': (int, 'General', 0),
'KEEP_TORRENT_FILES': (int, 'General', 0),
'LASTFM_USERNAME': (str, 'General', ''),
'LAUNCH_BROWSER': (int, 'General', 1),
'LIBRARYSCAN': (int, 'General', 1),
'LIBRARYSCAN_INTERVAL': (int, 'General', 300),
'LMS_ENABLED': (int, 'LMS', 0),
'LMS_HOST': (str, 'LMS', ''),
'LOG_DIR': (str, 'General', ''),
'LOSSLESS_BITRATE_FROM': (int, 'General', 0),
'LOSSLESS_BITRATE_TO': (int, 'General', 0),
'LOSSLESS_DESTINATION_DIR': (str, 'General', ''),
'MB_IGNORE_AGE': (int, 'General', 365),
'MININOVA': (int, 'Mininova', 0),
'MININOVA_RATIO': (str, 'Mininova', ''),
'MIRROR': (str, 'General', 'musicbrainz.org'),
'MOVE_FILES': (int, 'General', 0),
'MPC_ENABLED': (bool_int, 'MPC', False),
'MUSIC_DIR': (str, 'General', ''),
'MUSIC_ENCODER': (int, 'General', 0),
'NEWZNAB': (int, 'Newznab', 0),
'NEWZNAB_APIKEY': (str, 'Newznab', ''),
'NEWZNAB_ENABLED': (int, 'Newznab', 1),
'NEWZNAB_HOST': (str, 'Newznab', ''),
'NMA_APIKEY': (str, 'NMA', ''),
'NMA_ENABLED': (int, 'NMA', 0),
'NMA_ONSNATCH': (int, 'NMA', 0),
'NMA_PRIORITY': (int, 'NMA', 0),
'NUMBEROFSEEDERS': (str, 'General', '10'),
'NZBGET_CATEGORY': (str, 'NZBget', ''),
'NZBGET_HOST': (str, 'NZBget', ''),
'NZBGET_PASSWORD': (str, 'NZBget', ''),
'NZBGET_PRIORITY': (int, 'NZBget', 0),
'NZBGET_USERNAME': (str, 'NZBget', 'nzbget'),
'NZBSORG': (int, 'NZBsorg', 0),
'NZBSORG_HASH': (str, 'NZBsorg', ''),
'NZBSORG_UID': (str, 'NZBsorg', ''),
'NZB_DOWNLOADER': (int, 'General', 0),
'OMGWTFNZBS': (int, 'omgwtfnzbs', 0),
'OMGWTFNZBS_APIKEY': (str, 'omgwtfnzbs', ''),
'OMGWTFNZBS_UID': (str, 'omgwtfnzbs', ''),
'OPEN_MAGNET_LINKS': (int, 'General', 0), # 0: Ignore, 1: Open, 2: Convert
'MAGNET_LINKS': (int, 'General', 0),
'OSX_NOTIFY_APP': (str, 'OSX_Notify', '/Applications/Headphones'),
'OSX_NOTIFY_ENABLED': (int, 'OSX_Notify', 0),
'OSX_NOTIFY_ONSNATCH': (int, 'OSX_Notify', 0),
'PIRATEBAY': (int, 'Piratebay', 0),
'PIRATEBAY_PROXY_URL': (str, 'Piratebay', ''),
'PIRATEBAY_RATIO': (str, 'Piratebay', ''),
'PLEX_CLIENT_HOST': (str, 'Plex', ''),
'PLEX_ENABLED': (int, 'Plex', 0),
'PLEX_NOTIFY': (int, 'Plex', 0),
'PLEX_PASSWORD': (str, 'Plex', ''),
'PLEX_SERVER_HOST': (str, 'Plex', ''),
'PLEX_UPDATE': (int, 'Plex', 0),
'PLEX_USERNAME': (str, 'Plex', ''),
'PREFERRED_BITRATE': (str, 'General', ''),
'PREFERRED_BITRATE_ALLOW_LOSSLESS': (int, 'General', 0),
'PREFERRED_BITRATE_HIGH_BUFFER': (int, 'General', 0),
'PREFERRED_BITRATE_LOW_BUFFER': (int, 'General', 0),
'PREFERRED_QUALITY': (int, 'General', 0),
'PREFERRED_WORDS': (str, 'General', ''),
'PREFER_TORRENTS': (int, 'General', 0),
'PROWL_ENABLED': (int, 'Prowl', 0),
'PROWL_KEYS': (str, 'Prowl', ''),
'PROWL_ONSNATCH': (int, 'Prowl', 0),
'PROWL_PRIORITY': (int, 'Prowl', 0),
'PUSHALOT_APIKEY': (str, 'Pushalot', ''),
'PUSHALOT_ENABLED': (int, 'Pushalot', 0),
'PUSHALOT_ONSNATCH': (int, 'Pushalot', 0),
'PUSHBULLET_APIKEY': (str, 'PushBullet', ''),
'PUSHBULLET_DEVICEID': (str, 'PushBullet', ''),
'PUSHBULLET_ENABLED': (int, 'PushBullet', 0),
'PUSHBULLET_ONSNATCH': (int, 'PushBullet', 0),
'PUSHOVER_APITOKEN': (str, 'Pushover', ''),
'PUSHOVER_ENABLED': (int, 'Pushover', 0),
'PUSHOVER_KEYS': (str, 'Pushover', ''),
'PUSHOVER_ONSNATCH': (int, 'Pushover', 0),
'PUSHOVER_PRIORITY': (int, 'Pushover', 0),
'RENAME_FILES': (int, 'General', 0),
'REPLACE_EXISTING_FOLDERS': (int, 'General', 0),
'REQUIRED_WORDS': (str, 'General', ''),
'RUTRACKER': (int, 'Rutracker', 0),
'RUTRACKER_PASSWORD': (str, 'Rutracker', ''),
'RUTRACKER_RATIO': (str, 'Rutracker', ''),
'RUTRACKER_USER': (str, 'Rutracker', ''),
'SAB_APIKEY': (str, 'SABnzbd', ''),
'SAB_CATEGORY': (str, 'SABnzbd', ''),
'SAB_HOST': (str, 'SABnzbd', ''),
'SAB_PASSWORD': (str, 'SABnzbd', ''),
'SAB_USERNAME': (str, 'SABnzbd', ''),
'SAMPLINGFREQUENCY': (int, 'General', 44100),
'SEARCH_INTERVAL': (int, 'General', 1440),
'SONGKICK_APIKEY': (str, 'Songkick', 'nd1We7dFW2RqxPw8'),
'SONGKICK_ENABLED': (int, 'Songkick', 1),
'SONGKICK_FILTER_ENABLED': (int, 'Songkick', 0),
'SONGKICK_LOCATION': (str, 'Songkick', ''),
'SUBSONIC_ENABLED': (int, 'Subsonic', 0),
'SUBSONIC_HOST': (str, 'Subsonic', ''),
'SUBSONIC_PASSWORD': (str, 'Subsonic', ''),
'SUBSONIC_USERNAME': (str, 'Subsonic', ''),
'SYNOINDEX_ENABLED': (int, 'Synoindex', 0),
'TORRENTBLACKHOLE_DIR': (str, 'General', ''),
'TORRENT_DOWNLOADER': (int, 'General', 0),
'TORRENT_REMOVAL_INTERVAL': (int, 'General', 720),
'TRANSMISSION_HOST': (str, 'Transmission', ''),
'TRANSMISSION_PASSWORD': (str, 'Transmission', ''),
'TRANSMISSION_USERNAME': (str, 'Transmission', ''),
'TWITTER_ENABLED': (int, 'Twitter', 0),
'TWITTER_ONSNATCH': (int, 'Twitter', 0),
'TWITTER_PASSWORD': (str, 'Twitter', ''),
'TWITTER_PREFIX': (str, 'Twitter', 'Headphones'),
'TWITTER_USERNAME': (str, 'Twitter', ''),
'UPDATE_DB_INTERVAL': (int, 'General', 24),
'USENET_RETENTION': (int, 'General', '1500'),
'UTORRENT_HOST': (str, 'uTorrent', ''),
'UTORRENT_LABEL': (str, 'uTorrent', ''),
'UTORRENT_PASSWORD': (str, 'uTorrent', ''),
'UTORRENT_USERNAME': (str, 'uTorrent', ''),
'VERIFY_SSL_CERT': (bool_int, 'Advanced', 1),
'WAFFLES': (int, 'Waffles', 0),
'WAFFLES_PASSKEY': (str, 'Waffles', ''),
'WAFFLES_RATIO': (str, 'Waffles', ''),
'WAFFLES_UID': (str, 'Waffles', ''),
'WHATCD': (int, 'What.cd', 0),
'WHATCD_PASSWORD': (str, 'What.cd', ''),
'WHATCD_RATIO': (str, 'What.cd', ''),
'WHATCD_USERNAME': (str, 'What.cd', ''),
'XBMC_ENABLED': (int, 'XBMC', 0),
'XBMC_HOST': (str, 'XBMC', ''),
'XBMC_NOTIFY': (int, 'XBMC', 0),
'XBMC_PASSWORD': (str, 'XBMC', ''),
'XBMC_UPDATE': (int, 'XBMC', 0),
'XBMC_USERNAME': (str, 'XBMC', ''),
'XLDPROFILE': (str, 'General', '')
}
class Config(object):
""" Wraps access to particular values in a config file """
def __init__(self, config_file):
""" Initialize the config with values from a file """
self._config_file = config_file
self._config = ConfigObj(self._config_file, encoding='utf-8')
for key in _config_definitions.keys():
self.check_setting(key)
self.ENCODER_MULTICORE_COUNT = max(0, self.ENCODER_MULTICORE_COUNT)
self._upgrade()
def _define(self, name):
key = name.upper()
ini_key = name.lower()
definition = _config_definitions[key]
if len(definition) == 3:
definition_type, section, default = definition
else:
definition_type, section, _, default = definition
return key, definition_type, section, ini_key, default
def check_section(self, section):
""" Check if INI section exists, if not create it """
if section not in self._config:
self._config[section] = {}
return True
else:
return False
def check_setting(self, key):
""" Cast any value in the config to the right type or use the default """
key, definition_type, section, ini_key, default = self._define(key)
self.check_section(section)
try:
my_val = definition_type(self._config[section][ini_key])
except Exception:
my_val = definition_type(default)
self._config[section][ini_key] = my_val
return my_val
def write(self):
""" Make a copy of the stored config and write it to the configured file """
new_config = ConfigObj(encoding="UTF-8")
new_config.filename = self._config_file
# first copy over everything from the old config, even if it is not correctly
# defined to keep from losing data
for key, subkeys in self._config.items():
if key not in new_config:
new_config[key] = {}
for subkey, value in subkeys.items():
new_config[key][subkey] = value
# next make sure that everything we expect to have defined is so
for key in _config_definitions.keys():
key, definition_type, section, ini_key, default = self._define(key)
self.check_setting(key)
if section not in new_config:
new_config[section] = {}
new_config[section][ini_key] = self._config[section][ini_key]
# Write it to file
headphones.logger.info("Writing configuration to file")
try:
new_config.write()
except IOError as e:
headphones.logger.error("Error writing configuration file: %s", e)
def get_extra_newznabs(self):
""" Return the extra newznab tuples """
extra_newznabs = list(
itertools.izip(*[itertools.islice(self.EXTRA_NEWZNABS, i, None, 3)
for i in range(3)])
)
return extra_newznabs
def clear_extra_newznabs(self):
""" Forget about the configured extra newznabs """
self.EXTRA_NEWZNABS = []
def add_extra_newznab(self, newznab):
""" Add a new extra newznab """
for item in newznab:
self.EXTRA_NEWZNABS.append(item)
def __getattr__(self, name):
"""
Returns something from the ini unless it is a real property
of the configuration object or is not all caps.
"""
if not re.match(r'[A-Z_]+$', name):
return super(Config, self).__getattr__(name)
else:
return self.check_setting(name)
def __setattr__(self, name, value):
"""
Maps all-caps properties to ini values unless they exist on the
configuration object.
"""
if not re.match(r'[A-Z_]+$', name):
super(Config, self).__setattr__(name, value)
return value
else:
key, definition_type, section, ini_key, default = self._define(name)
self._config[section][ini_key] = definition_type(value)
return self._config[section][ini_key]
def process_kwargs(self, kwargs):
"""
Given a big bunch of key value pairs, apply them to the ini.
"""
for name, value in kwargs.items():
key, definition_type, section, ini_key, default = self._define(name)
self._config[section][ini_key] = definition_type(value)
def _upgrade(self):
""" Update folder formats in the config & bump up config version """
if self.CONFIG_VERSION == '0':
from headphones.helpers import replace_all
file_values = {
'tracknumber': 'Track',
'title': 'Title',
'artist': 'Artist',
'album': 'Album',
'year': 'Year'
}
folder_values = {
'artist': 'Artist',
'album': 'Album',
'year': 'Year',
'releasetype': 'Type',
'first': 'First',
'lowerfirst': 'first'
}
self.FILE_FORMAT = replace_all(self.FILE_FORMAT, file_values)
self.FOLDER_FORMAT = replace_all(self.FOLDER_FORMAT, folder_values)
self.CONFIG_VERSION = '1'
if self.CONFIG_VERSION == '1':
from headphones.helpers import replace_all
file_values = {
'Track': '$Track',
'Title': '$Title',
'Artist': '$Artist',
'Album': '$Album',
'Year': '$Year',
'track': '$track',
'title': '$title',
'artist': '$artist',
'album': '$album',
'year': '$year'
}
folder_values = {
'Artist': '$Artist',
'Album': '$Album',
'Year': '$Year',
'Type': '$Type',
'First': '$First',
'artist': '$artist',
'album': '$album',
'year': '$year',
'type': '$type',
'first': '$first'
}
self.FILE_FORMAT = replace_all(self.FILE_FORMAT, file_values)
self.FOLDER_FORMAT = replace_all(self.FOLDER_FORMAT, folder_values)
self.CONFIG_VERSION = '2'
if self.CONFIG_VERSION == '2':
# Update the config to use direct path to the encoder rather than the encoder folder
if self.ENCODERFOLDER:
self.ENCODER_PATH = os.path.join(self.ENCODERFOLDER, self.ENCODER)
self.CONFIG_VERSION = '3'
if self.CONFIG_VERSION == '3':
# Update the BLACKHOLE option to the NZB_DOWNLOADER format
if self.BLACKHOLE:
self.NZB_DOWNLOADER = 2
self.CONFIG_VERSION = '4'
# Enable Headphones Indexer if they have a VIP account
if self.CONFIG_VERSION == '4':
if self.HPUSER and self.HPPASS:
self.HEADPHONES_INDEXER = True
self.CONFIG_VERSION = '5'
if self.CONFIG_VERSION == '5':
if self.OPEN_MAGNET_LINKS:
self.MAGNET_LINKS = 2
self.CONFIG_VERSION = '5'

View File

@@ -574,14 +574,14 @@ def split(albumpath):
xldprofile = None
# use xld profile to split cue
if headphones.ENCODER == 'xld' and headphones.MUSIC_ENCODER and headphones.XLDPROFILE:
if headphones.CONFIG.ENCODER == 'xld' and headphones.CONFIG.MUSIC_ENCODER and headphones.CONFIG.XLDPROFILE:
import getXldProfile
xldprofile, xldformat, _ = getXldProfile.getXldProfile(headphones.XLDPROFILE)
xldprofile, xldformat, _ = getXldProfile.getXldProfile(headphones.CONFIG.XLDPROFILE)
if not xldformat:
raise ValueError('Details for xld profile "%s" not found, cannot split cue' % (xldprofile))
else:
if headphones.ENCODERFOLDER:
splitter = os.path.join(headphones.ENCODERFOLDER, 'xld')
if headphones.CONFIG.ENCODERFOLDER:
splitter = os.path.join(headphones.CONFIG.ENCODERFOLDER, 'xld')
else:
splitter = 'xld'
# use standard xld command to split cue

View File

@@ -34,10 +34,10 @@ def dbFilename(filename="headphones.db"):
def getCacheSize():
#this will protect against typecasting problems produced by empty string and None settings
if not headphones.CACHE_SIZEMB:
if not headphones.CONFIG.CACHE_SIZEMB:
#sqlite will work with this (very slowly)
return 0
return int(headphones.CACHE_SIZEMB)
return int(headphones.CONFIG.CACHE_SIZEMB)
class DBConnection:
@@ -48,7 +48,7 @@ class DBConnection:
#don't wait for the disk to finish writing
self.connection.execute("PRAGMA synchronous = OFF")
#journal disabled since we never do rollbacks
self.connection.execute("PRAGMA journal_mode = %s" % headphones.JOURNAL_MODE)
self.connection.execute("PRAGMA journal_mode = %s" % headphones.CONFIG.JOURNAL_MODE)
#64mb of cache memory,probably need to make it user configurable
self.connection.execute("PRAGMA cache_size=-%s" % (getCacheSize()*1024))
self.connection.row_factory = sqlite3.Row

View File

@@ -520,11 +520,11 @@ def extract_logline(s):
def extract_song_data(s):
#headphones default format
music_dir = headphones.MUSIC_DIR
folder_format = headphones.FOLDER_FORMAT
file_format = headphones.FILE_FORMAT
music_dir = headphones.CONFIG.MUSIC_DIR
folder_format = headphones.CONFIG.FOLDER_FORMAT
file_format = headphones.CONFIG.FILE_FORMAT
full_format = os.path.join(headphones.MUSIC_DIR)
full_format = os.path.join(headphones.CONFIG.MUSIC_DIR)
pattern = re.compile(r'(?P<name>.*?)\s\-\s(?P<album>.*?)\s\[(?P<year>.*?)\]', re.VERBOSE)
match = pattern.match(s)

View File

@@ -140,8 +140,8 @@ def addArtisttoDB(artistid, extrasonly=False, forcefull=False):
if not dbartist:
newValueDict = {"ArtistName": "Artist ID: %s" % (artistid),
"Status": "Loading",
"IncludeExtras": headphones.INCLUDE_EXTRAS,
"Extras": headphones.EXTRAS }
"IncludeExtras": headphones.CONFIG.INCLUDE_EXTRAS,
"Extras": headphones.CONFIG.EXTRAS }
else:
newValueDict = {"Status": "Loading"}
@@ -227,7 +227,7 @@ def addArtisttoDB(artistid, extrasonly=False, forcefull=False):
rgid = rg['id']
skip_log = 0
#Make a user configurable variable to skip update of albums with release dates older than this date (in days)
pause_delta = headphones.MB_IGNORE_AGE
pause_delta = headphones.CONFIG.MB_IGNORE_AGE
rg_exists = myDB.action("SELECT * from albums WHERE AlbumID=?", [rg['id']]).fetchone()
@@ -414,13 +414,13 @@ def addArtisttoDB(artistid, extrasonly=False, forcefull=False):
newValueDict['DateAdded'] = today
if headphones.AUTOWANT_ALL:
if headphones.CONFIG.AUTOWANT_ALL:
newValueDict['Status'] = "Wanted"
elif album['ReleaseDate'] > today and headphones.AUTOWANT_UPCOMING:
elif album['ReleaseDate'] > today and headphones.CONFIG.AUTOWANT_UPCOMING:
newValueDict['Status'] = "Wanted"
# Sometimes "new" albums are added to musicbrainz after their release date, so let's try to catch these
# The first test just makes sure we have year-month-day
elif helpers.get_age(album['ReleaseDate']) and helpers.get_age(today) - helpers.get_age(album['ReleaseDate']) < 21 and headphones.AUTOWANT_UPCOMING:
elif helpers.get_age(album['ReleaseDate']) and helpers.get_age(today) - helpers.get_age(album['ReleaseDate']) < 21 and headphones.CONFIG.AUTOWANT_UPCOMING:
newValueDict['Status'] = "Wanted"
else:
newValueDict['Status'] = "Skipped"
@@ -464,11 +464,11 @@ def addArtisttoDB(artistid, extrasonly=False, forcefull=False):
marked_as_downloaded = False
if rg_exists:
if rg_exists['Status'] == 'Skipped' and ((have_track_count/float(total_track_count)) >= (headphones.ALBUM_COMPLETION_PCT/100.0)):
if rg_exists['Status'] == 'Skipped' and ((have_track_count/float(total_track_count)) >= (headphones.CONFIG.ALBUM_COMPLETION_PCT/100.0)):
myDB.action('UPDATE albums SET Status=? WHERE AlbumID=?', ['Downloaded', rg['id']])
marked_as_downloaded = True
else:
if ((have_track_count/float(total_track_count)) >= (headphones.ALBUM_COMPLETION_PCT/100.0)):
if ((have_track_count/float(total_track_count)) >= (headphones.CONFIG.ALBUM_COMPLETION_PCT/100.0)):
myDB.action('UPDATE albums SET Status=? WHERE AlbumID=?', ['Downloaded', rg['id']])
marked_as_downloaded = True
@@ -478,7 +478,7 @@ def addArtisttoDB(artistid, extrasonly=False, forcefull=False):
# Start a search for the album if it's new, hasn't been marked as
# downloaded and autowant_all is selected. This search is deferred,
# in case the search failes and the rest of the import will halt.
if not rg_exists and not marked_as_downloaded and headphones.AUTOWANT_ALL:
if not rg_exists and not marked_as_downloaded and headphones.CONFIG.AUTOWANT_ALL:
album_searches.append(rg['id'])
else:
if skip_log == 0:
@@ -596,9 +596,9 @@ def addReleaseById(rid, rgid=None):
"DateAdded": helpers.today(),
"Status": "Paused"}
if headphones.INCLUDE_EXTRAS:
if headphones.CONFIG.INCLUDE_EXTRAS:
newValueDict['IncludeExtras'] = 1
newValueDict['Extras'] = headphones.EXTRAS
newValueDict['Extras'] = headphones.CONFIG.EXTRAS
myDB.upsert("artists", newValueDict, controlValueDict)
@@ -670,14 +670,14 @@ def addReleaseById(rid, rgid=None):
# Reset status
if status == 'Loading':
controlValueDict = {"AlbumID": rgid}
if headphones.AUTOWANT_MANUALLY_ADDED:
if headphones.CONFIG.AUTOWANT_MANUALLY_ADDED:
newValueDict = {"Status": "Wanted"}
else:
newValueDict = {"Status": "Skipped"}
myDB.upsert("albums", newValueDict, controlValueDict)
# Start a search for the album
if headphones.AUTOWANT_MANUALLY_ADDED:
if headphones.CONFIG.AUTOWANT_MANUALLY_ADDED:
import searcher
searcher.searchforalbum(rgid, False)

View File

@@ -111,12 +111,12 @@ def getArtists():
myDB = db.DBConnection()
results = myDB.select("SELECT ArtistID from artists")
if not headphones.LASTFM_USERNAME:
if not headphones.CONFIG.LASTFM_USERNAME:
logger.warn("Last.FM username not set, not importing artists.")
return
logger.info("Fetching artists from Last.FM for username: %s", headphones.LASTFM_USERNAME)
data = request_lastfm("library.getartists", limit=10000, user=headphones.LASTFM_USERNAME)
logger.info("Fetching artists from Last.FM for username: %s", headphones.CONFIG.LASTFM_USERNAME)
data = request_lastfm("library.getartists", limit=10000, user=headphones.CONFIG.LASTFM_USERNAME)
if data and "artists" in data:
artistlist = []

View File

@@ -25,14 +25,14 @@ from headphones import db, logger, helpers, importer, lastfm
def libraryScan(dir=None, append=False, ArtistID=None, ArtistName=None, cron=False):
if cron and not headphones.LIBRARYSCAN:
if cron and not headphones.CONFIG.LIBRARYSCAN:
return
if not dir:
if not headphones.MUSIC_DIR:
if not headphones.CONFIG.MUSIC_DIR:
return
else:
dir = headphones.MUSIC_DIR
dir = headphones.CONFIG.MUSIC_DIR
# If we're appending a dir, it's coming from the post processor which is
# already bytestring
@@ -205,7 +205,6 @@ def libraryScan(dir=None, append=False, ArtistID=None, ArtistName=None, cron=Fal
elif latest_artist[song_count] != latest_artist[song_count-1] and song_count !=0:
logger.info("Now matching songs by %s" % song['ArtistName'])
#print song['ArtistName']+' - '+song['AlbumTitle']+' - '+song['TrackTitle']
song_count += 1
completion_percentage = float(song_count)/total_number_of_songs * 100
@@ -319,7 +318,7 @@ def libraryScan(dir=None, append=False, ArtistID=None, ArtistName=None, cron=Fal
logger.info('Found %i new artists' % len(artist_list))
if len(artist_list):
if headphones.ADD_ARTISTS:
if headphones.CONFIG.AUTO_ADD_ARTISTS:
logger.info('Importing %i new artists' % len(artist_list))
importer.artistlist_to_mbids(artist_list)
else:
@@ -328,8 +327,8 @@ def libraryScan(dir=None, append=False, ArtistID=None, ArtistName=None, cron=Fal
for artist in artist_list:
myDB.action('INSERT OR IGNORE INTO newartists VALUES (?)', [artist])
if headphones.DETECT_BITRATE:
headphones.PREFERRED_BITRATE = sum(bitrates)/len(bitrates)/1000
if headphones.CONFIG.DETECT_BITRATE:
headphones.CONFIG.PREFERRED_BITRATE = sum(bitrates)/len(bitrates)/1000
else:
# If we're appending a new album to the database, update the artists total track counts
@@ -365,7 +364,7 @@ def update_album_status(AlbumID=None):
album_completion = 0
logger.info('Album %s does not have any tracks in database' % album['AlbumTitle'])
if album_completion >= headphones.ALBUM_COMPLETION_PCT and album['Status'] == 'Skipped':
if album_completion >= headphones.CONFIG.ALBUM_COMPLETION_PCT and album['Status'] == 'Skipped':
new_album_status = "Downloaded"
# I don't think we want to change Downloaded->Skipped.....

View File

@@ -136,7 +136,7 @@ def initLogger(console=False, verbose=False):
logger.setLevel(logging.DEBUG if verbose else logging.INFO)
# Setup file logger
filename = os.path.join(headphones.LOG_DIR, FILENAME)
filename = os.path.join(headphones.CONFIG.LOG_DIR, FILENAME)
file_formatter = logging.Formatter('%(asctime)s - %(levelname)-7s :: %(threadName)s : %(message)s', '%d-%b-%Y %H:%M:%S')
file_handler = handlers.RotatingFileHandler(filename, maxBytes=MAX_SIZE, backupCount=MAX_FILES)

View File

@@ -37,19 +37,19 @@ def startmb():
mbuser = None
mbpass = None
if headphones.MIRROR == "musicbrainz.org":
if headphones.CONFIG.MIRROR == "musicbrainz.org":
mbhost = "musicbrainz.org"
mbport = 80
sleepytime = 1
elif headphones.MIRROR == "custom":
mbhost = headphones.CUSTOMHOST
mbport = int(headphones.CUSTOMPORT)
sleepytime = int(headphones.CUSTOMSLEEP)
elif headphones.MIRROR == "headphones":
elif headphones.CONFIG.MIRROR == "custom":
mbhost = headphones.CONFIG.CUSTOMHOST
mbport = int(headphones.CONFIG.CUSTOMPORT)
sleepytime = int(headphones.CONFIG.CUSTOMSLEEP)
elif headphones.CONFIG.MIRROR == "headphones":
mbhost = "144.76.94.239"
mbport = 8181
mbuser = headphones.HPUSER
mbpass = headphones.HPPASS
mbuser = headphones.CONFIG.HPUSER
mbpass = headphones.CONFIG.HPPASS
sleepytime = 0
else:
return False
@@ -63,7 +63,7 @@ def startmb():
musicbrainzngs.set_rate_limit(limit_or_interval=float(sleepytime))
# Add headphones credentials
if headphones.MIRROR == "headphones":
if headphones.CONFIG.MIRROR == "headphones":
if not mbuser and mbpass:
logger.warn("No username or password set for VIP server")
else:
@@ -278,7 +278,7 @@ def getArtist(artistid, extrasonly=False):
extras = map(int, db_artist['Extras'].split(','))
else:
extras = []
extras_list = ["single", "ep", "compilation", "soundtrack", "live", "remix", "spokenword", "audiobook", "other", "dj-mix", "mixtape/street", "broadcast", "interview", "demo"]
extras_list = headphones.POSSIBLE_EXTRAS
includes = []
@@ -558,8 +558,6 @@ def get_new_releases(rgid,includeExtras=False,forcefull=False):
myDB.upsert("alltracks", newValueDict, controlValueDict)
num_new_releases = num_new_releases + 1
#print releasedata['title']
#print num_new_releases
if album_checker:
logger.info('[%s] Existing release %s (%s) updated' % (release['ArtistName'], release['AlbumTitle'], rel_id_check))
else:

View File

@@ -24,7 +24,7 @@ from headphones import logger
from beets.mediafile import MediaFile
# xld
if headphones.ENCODER == 'xld':
if headphones.CONFIG.ENCODER == 'xld':
import getXldProfile
XLD = True
else:
@@ -35,7 +35,7 @@ def encode(albumPath):
# Return if xld details not found
if XLD:
global xldProfile
(xldProfile, xldFormat, xldBitrate) = getXldProfile.getXldProfile(headphones.XLDPROFILE)
(xldProfile, xldFormat, xldBitrate) = getXldProfile.getXldProfile(headphones.CONFIG.XLDPROFILE)
if not xldFormat:
logger.error('Details for xld profile \'%s\' not found, files will not be re-encoded', xldProfile)
return None
@@ -61,13 +61,13 @@ def encode(albumPath):
for music in f:
if any(music.lower().endswith('.' + x.lower()) for x in headphones.MEDIA_FORMATS):
if not XLD:
encoderFormat = headphones.ENCODEROUTPUTFORMAT.encode(headphones.SYS_ENCODING)
encoderFormat = headphones.CONFIG.ENCODEROUTPUTFORMAT.encode(headphones.SYS_ENCODING)
else:
xldMusicFile = os.path.join(r, music)
xldInfoMusic = MediaFile(xldMusicFile)
encoderFormat = xldFormat
if (headphones.ENCODERLOSSLESS):
if (headphones.CONFIG.ENCODERLOSSLESS):
ext = os.path.normpath(os.path.splitext(music)[1].lstrip(".")).lower()
if not XLD and ext == 'flac' or XLD and (ext != xldFormat and (xldInfoMusic.bitrate / 1000 > 400)):
musicFiles.append(os.path.join(r, music))
@@ -80,23 +80,23 @@ def encode(albumPath):
musicTemp = os.path.normpath(os.path.splitext(music)[0] + '.' + encoderFormat)
musicTempFiles.append(os.path.join(tempDirEncode, musicTemp))
if headphones.ENCODER_PATH:
encoder = headphones.ENCODER_PATH.encode(headphones.SYS_ENCODING)
if headphones.CONFIG.ENCODER_PATH:
encoder = headphones.CONFIG.ENCODER_PATH.encode(headphones.SYS_ENCODING)
else:
if XLD:
encoder = os.path.join('/Applications', 'xld')
elif headphones.ENCODER =='lame':
elif headphones.CONFIG.ENCODER =='lame':
if headphones.SYS_PLATFORM == "win32":
## NEED THE DEFAULT LAME INSTALL ON WIN!
encoder = "C:/Program Files/lame/lame.exe"
else:
encoder="lame"
elif headphones.ENCODER =='ffmpeg':
elif headphones.CONFIG.ENCODER =='ffmpeg':
if headphones.SYS_PLATFORM == "win32":
encoder = "C:/Program Files/ffmpeg/bin/ffmpeg.exe"
else:
encoder="ffmpeg"
elif headphones.ENCODER == 'libav':
elif headphones.CONFIG.ENCODER == 'libav':
if headphones.SYS_PLATFORM == "win32":
encoder = "C:/Program Files/libav/bin/avconv.exe"
else:
@@ -115,23 +115,23 @@ def encode(albumPath):
logger.info('%s has bitrate <= %skb, will not be re-encoded', music.decode(headphones.SYS_ENCODING, 'replace'), xldBitrate)
else:
encode = True
elif headphones.ENCODER == 'lame':
elif headphones.CONFIG.ENCODER == 'lame':
if not any(music.decode(headphones.SYS_ENCODING, 'replace').lower().endswith('.' + x) for x in ["mp3", "wav"]):
logger.warn('Lame cannot encode %s format for %s, use ffmpeg', os.path.splitext(music)[1], music)
else:
if (music.decode(headphones.SYS_ENCODING, 'replace').lower().endswith('.mp3') and (int(infoMusic.bitrate / 1000) <= headphones.BITRATE)):
logger.info('%s has bitrate <= %skb, will not be re-encoded', music, headphones.BITRATE)
if (music.decode(headphones.SYS_ENCODING, 'replace').lower().endswith('.mp3') and (int(infoMusic.bitrate / 1000) <= headphones.CONFIG.BITRATE)):
logger.info('%s has bitrate <= %skb, will not be re-encoded', music, headphones.CONFIG.BITRATE)
else:
encode = True
else:
if headphones.ENCODEROUTPUTFORMAT=='ogg':
if headphones.CONFIG.ENCODEROUTPUTFORMAT=='ogg':
if music.decode(headphones.SYS_ENCODING, 'replace').lower().endswith('.ogg'):
logger.warn('Cannot re-encode .ogg %s', music.decode(headphones.SYS_ENCODING, 'replace'))
else:
encode = True
elif (headphones.ENCODEROUTPUTFORMAT=='mp3' or headphones.ENCODEROUTPUTFORMAT=='m4a'):
if (music.decode(headphones.SYS_ENCODING, 'replace').lower().endswith('.'+headphones.ENCODEROUTPUTFORMAT) and (int(infoMusic.bitrate / 1000 ) <= headphones.BITRATE)):
logger.info('%s has bitrate <= %skb, will not be re-encoded', music, headphones.BITRATE)
elif (headphones.CONFIG.ENCODEROUTPUTFORMAT=='mp3' or headphones.CONFIG.ENCODEROUTPUTFORMAT=='m4a'):
if (music.decode(headphones.SYS_ENCODING, 'replace').lower().endswith('.'+headphones.CONFIG.ENCODEROUTPUTFORMAT) and (int(infoMusic.bitrate / 1000 ) <= headphones.CONFIG.BITRATE)):
logger.info('%s has bitrate <= %skb, will not be re-encoded', music, headphones.CONFIG.BITRATE)
else:
encode = True
# encode
@@ -149,11 +149,11 @@ def encode(albumPath):
processes = 1
# Use multicore if enabled
if headphones.ENCODER_MULTICORE:
if headphones.ENCODER_MULTICORE_COUNT == 0:
if headphones.CONFIG.ENCODER_MULTICORE:
if headphones.CONFIG.ENCODER_MULTICORE_COUNT == 0:
processes = multiprocessing.cpu_count()
else:
processes = headphones.ENCODER_MULTICORE_COUNT
processes = headphones.CONFIG.ENCODER_MULTICORE_COUNT
logger.debug("Multi-core encoding enabled, spawning %d processes",
processes)
@@ -194,7 +194,7 @@ def encode(albumPath):
for dest in musicTempFiles:
if os.path.exists(dest):
source = musicFiles[i]
if headphones.DELETE_LOSSLESS_FILES:
if headphones.CONFIG.DELETE_LOSSLESS_FILES:
os.remove(source)
check_dest = os.path.join(albumPath, os.path.split(dest)[1])
if os.path.exists(check_dest):
@@ -212,7 +212,7 @@ def encode(albumPath):
# Return with error if any encoding errors
if encoder_failed:
logger.error("One or more files failed to encode. Ensure you have the latest version of %s installed.", headphones.ENCODER)
logger.error("One or more files failed to encode. Ensure you have the latest version of %s installed.", headphones.CONFIG.ENCODER)
return None
time.sleep(1)
@@ -263,17 +263,17 @@ def command(encoder, musicSource, musicDest, albumPath):
cmd.extend([xldDestDir])
# Lame
elif headphones.ENCODER == 'lame':
elif headphones.CONFIG.ENCODER == 'lame':
cmd = [encoder]
opts = []
if not headphones.ADVANCEDENCODER:
if not headphones.CONFIG.ADVANCEDENCODER:
opts.extend(['-h'])
if headphones.ENCODERVBRCBR=='cbr':
opts.extend(['--resample', str(headphones.SAMPLINGFREQUENCY), '-b', str(headphones.BITRATE)])
elif headphones.ENCODERVBRCBR=='vbr':
opts.extend(['-v', str(headphones.ENCODERQUALITY)])
if headphones.CONFIG.ENCODERVBRCBR=='cbr':
opts.extend(['--resample', str(headphones.CONFIG.SAMPLINGFREQUENCY), '-b', str(headphones.CONFIG.BITRATE)])
elif headphones.CONFIG.ENCODERVBRCBR=='vbr':
opts.extend(['-v', str(headphones.CONFIG.ENCODERQUALITY)])
else:
advanced = (headphones.ADVANCEDENCODER.split())
advanced = (headphones.CONFIG.ADVANCEDENCODER.split())
for tok in advanced:
opts.extend([tok.encode(headphones.SYS_ENCODING)])
opts.extend([musicSource])
@@ -281,42 +281,42 @@ def command(encoder, musicSource, musicDest, albumPath):
cmd.extend(opts)
# FFmpeg
elif headphones.ENCODER == 'ffmpeg':
elif headphones.CONFIG.ENCODER == 'ffmpeg':
cmd = [encoder, '-i', musicSource]
opts = []
if not headphones.ADVANCEDENCODER:
if headphones.ENCODEROUTPUTFORMAT=='ogg':
if not headphones.CONFIG.ADVANCEDENCODER:
if headphones.CONFIG.ENCODEROUTPUTFORMAT=='ogg':
opts.extend(['-acodec', 'libvorbis'])
if headphones.ENCODEROUTPUTFORMAT=='m4a':
if headphones.CONFIG.ENCODEROUTPUTFORMAT=='m4a':
opts.extend(['-strict', 'experimental'])
if headphones.ENCODERVBRCBR=='cbr':
opts.extend(['-ar', str(headphones.SAMPLINGFREQUENCY), '-ab', str(headphones.BITRATE) + 'k'])
elif headphones.ENCODERVBRCBR=='vbr':
opts.extend(['-aq', str(headphones.ENCODERQUALITY)])
if headphones.CONFIG.ENCODERVBRCBR=='cbr':
opts.extend(['-ar', str(headphones.CONFIG.SAMPLINGFREQUENCY), '-ab', str(headphones.CONFIG.BITRATE) + 'k'])
elif headphones.CONFIG.ENCODERVBRCBR=='vbr':
opts.extend(['-aq', str(headphones.CONFIG.ENCODERQUALITY)])
opts.extend(['-y', '-ac', '2', '-vn'])
else:
advanced = (headphones.ADVANCEDENCODER.split())
advanced = (headphones.CONFIG.ADVANCEDENCODER.split())
for tok in advanced:
opts.extend([tok.encode(headphones.SYS_ENCODING)])
opts.extend([musicDest])
cmd.extend(opts)
# Libav
elif headphones.ENCODER == "libav":
elif headphones.CONFIG.ENCODER == "libav":
cmd = [encoder, '-i', musicSource]
opts = []
if not headphones.ADVANCEDENCODER:
if headphones.ENCODEROUTPUTFORMAT=='ogg':
if not headphones.CONFIG.ADVANCEDENCODER:
if headphones.CONFIG.ENCODEROUTPUTFORMAT=='ogg':
opts.extend(['-acodec', 'libvorbis'])
if headphones.ENCODEROUTPUTFORMAT=='m4a':
if headphones.CONFIG.ENCODEROUTPUTFORMAT=='m4a':
opts.extend(['-strict', 'experimental'])
if headphones.ENCODERVBRCBR=='cbr':
opts.extend(['-ar', str(headphones.SAMPLINGFREQUENCY), '-ab', str(headphones.BITRATE) + 'k'])
elif headphones.ENCODERVBRCBR=='vbr':
opts.extend(['-aq', str(headphones.ENCODERQUALITY)])
if headphones.CONFIG.ENCODERVBRCBR=='cbr':
opts.extend(['-ar', str(headphones.CONFIG.SAMPLINGFREQUENCY), '-ab', str(headphones.CONFIG.BITRATE) + 'k'])
elif headphones.CONFIG.ENCODERVBRCBR=='vbr':
opts.extend(['-aq', str(headphones.CONFIG.ENCODERQUALITY)])
opts.extend(['-y', '-ac', '2', '-vn'])
else:
advanced = (headphones.ADVANCEDENCODER.split())
advanced = (headphones.CONFIG.ADVANCEDENCODER.split())
for tok in advanced:
opts.extend([tok.encode(headphones.SYS_ENCODING)])
opts.extend([musicDest])
@@ -339,7 +339,7 @@ def command(encoder, musicSource, musicDest, albumPath):
process = subprocess.Popen(cmd, startupinfo=startupinfo,
stdin=open(os.devnull, 'rb'), stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout, stderr = process.communicate(headphones.ENCODER)
stdout, stderr = process.communicate(headphones.CONFIG.ENCODER)
# Error if return code not zero
if process.returncode:
@@ -347,7 +347,7 @@ def command(encoder, musicSource, musicDest, albumPath):
out = stdout if stdout else stderr
out = out.decode(headphones.SYS_ENCODING, 'replace')
outlast2lines = '\n'.join(out.splitlines()[-2:])
logger.error('%s error details: %s' % (headphones.ENCODER, outlast2lines))
logger.error('%s error details: %s' % (headphones.CONFIG.ENCODER, outlast2lines))
out = out.rstrip("\n")
logger.debug(out)
encoded = False

View File

@@ -45,9 +45,9 @@ class GROWL(object):
"""
def __init__(self):
self.enabled = headphones.GROWL_ENABLED
self.host = headphones.GROWL_HOST
self.password = headphones.GROWL_PASSWORD
self.enabled = headphones.CONFIG.GROWL_ENABLED
self.host = headphones.CONFIG.GROWL_HOST
self.password = headphones.CONFIG.GROWL_PASSWORD
def conf(self, options):
return cherrypy.config['config'].get('Growl', options)
@@ -130,24 +130,24 @@ class PROWL(object):
"""
def __init__(self):
self.enabled = headphones.PROWL_ENABLED
self.keys = headphones.PROWL_KEYS
self.priority = headphones.PROWL_PRIORITY
self.enabled = headphones.CONFIG.PROWL_ENABLED
self.keys = headphones.CONFIG.PROWL_KEYS
self.priority = headphones.CONFIG.PROWL_PRIORITY
def conf(self, options):
return cherrypy.config['config'].get('Prowl', options)
def notify(self, message, event):
if not headphones.PROWL_ENABLED:
if not headphones.CONFIG.PROWL_ENABLED:
return
http_handler = HTTPSConnection("api.prowlapp.com")
data = {'apikey': headphones.PROWL_KEYS,
data = {'apikey': headphones.CONFIG.PROWL_KEYS,
'application': 'Headphones',
'event': event,
'description': message.encode("utf-8"),
'priority': headphones.PROWL_PRIORITY }
'priority': headphones.CONFIG.PROWL_PRIORITY }
http_handler.request("POST",
"/publicapi/add",
@@ -197,9 +197,9 @@ class XBMC(object):
def __init__(self):
self.hosts = headphones.XBMC_HOST
self.username = headphones.XBMC_USERNAME
self.password = headphones.XBMC_PASSWORD
self.hosts = headphones.CONFIG.XBMC_HOST
self.username = headphones.CONFIG.XBMC_USERNAME
self.password = headphones.CONFIG.XBMC_PASSWORD
def _sendhttp(self, host, command):
url_command = urllib.urlencode(command)
@@ -270,7 +270,7 @@ class LMS(object):
"""
def __init__(self):
self.hosts = headphones.LMS_HOST
self.hosts = headphones.CONFIG.LMS_HOST
def _sendjson(self, host):
data = {'id': 1, 'method': 'slim.request', 'params': ["",["rescan"]]}
@@ -308,10 +308,10 @@ class LMS(object):
class Plex(object):
def __init__(self):
self.server_hosts = headphones.PLEX_SERVER_HOST
self.client_hosts = headphones.PLEX_CLIENT_HOST
self.username = headphones.PLEX_USERNAME
self.password = headphones.PLEX_PASSWORD
self.server_hosts = headphones.CONFIG.PLEX_SERVER_HOST
self.client_hosts = headphones.CONFIG.PLEX_CLIENT_HOST
self.username = headphones.CONFIG.PLEX_USERNAME
self.password = headphones.CONFIG.PLEX_PASSWORD
def _sendhttp(self, host, command):
@@ -394,8 +394,8 @@ class Plex(object):
class NMA(object):
def notify(self, artist=None, album=None, snatched=None):
title = 'Headphones'
api = headphones.NMA_APIKEY
nma_priority = headphones.NMA_PRIORITY
api = headphones.CONFIG.NMA_APIKEY
nma_priority = headphones.CONFIG.NMA_PRIORITY
logger.debug(u"NMA title: " + title)
logger.debug(u"NMA API: " + api)
@@ -430,19 +430,19 @@ class NMA(object):
class PUSHBULLET(object):
def __init__(self):
self.apikey = headphones.PUSHBULLET_APIKEY
self.deviceid = headphones.PUSHBULLET_DEVICEID
self.apikey = headphones.CONFIG.PUSHBULLET_APIKEY
self.deviceid = headphones.CONFIG.PUSHBULLET_DEVICEID
def conf(self, options):
return cherrypy.config['config'].get('PUSHBULLET', options)
def notify(self, message, event):
if not headphones.PUSHBULLET_ENABLED:
if not headphones.CONFIG.PUSHBULLET_ENABLED:
return
http_handler = HTTPSConnection("api.pushbullet.com")
data = {'device_iden': headphones.PUSHBULLET_DEVICEID,
data = {'device_iden': headphones.CONFIG.PUSHBULLET_DEVICEID,
'type': "note",
'title': "Headphones",
'body': message.encode("utf-8") }
@@ -450,7 +450,7 @@ class PUSHBULLET(object):
http_handler.request("POST",
"/api/pushes",
headers = {'Content-type': "application/x-www-form-urlencoded",
'Authorization' : 'Basic %s' % base64.b64encode(headphones.PUSHBULLET_APIKEY + ":") },
'Authorization' : 'Basic %s' % base64.b64encode(headphones.CONFIG.PUSHBULLET_APIKEY + ":") },
body = urlencode(data))
response = http_handler.getresponse()
request_status = response.status
@@ -483,10 +483,10 @@ class PUSHBULLET(object):
class PUSHALOT(object):
def notify(self, message, event):
if not headphones.PUSHALOT_ENABLED:
if not headphones.CONFIG.PUSHALOT_ENABLED:
return
pushalot_authorizationtoken = headphones.PUSHALOT_APIKEY
pushalot_authorizationtoken = headphones.CONFIG.PUSHALOT_APIKEY
logger.debug(u"Pushalot event: " + event)
logger.debug(u"Pushalot message: " + message)
@@ -558,12 +558,12 @@ class Synoindex(object):
class PUSHOVER(object):
def __init__(self):
self.enabled = headphones.PUSHOVER_ENABLED
self.keys = headphones.PUSHOVER_KEYS
self.priority = headphones.PUSHOVER_PRIORITY
self.enabled = headphones.CONFIG.PUSHOVER_ENABLED
self.keys = headphones.CONFIG.PUSHOVER_KEYS
self.priority = headphones.CONFIG.PUSHOVER_PRIORITY
if headphones.PUSHOVER_APITOKEN:
self.application_token = headphones.PUSHOVER_APITOKEN
if headphones.CONFIG.PUSHOVER_APITOKEN:
self.application_token = headphones.CONFIG.PUSHOVER_APITOKEN
else:
self.application_token = "LdPCoy0dqC21ktsbEyAVCcwvQiVlsz"
@@ -571,16 +571,16 @@ class PUSHOVER(object):
return cherrypy.config['config'].get('Pushover', options)
def notify(self, message, event):
if not headphones.PUSHOVER_ENABLED:
if not headphones.CONFIG.PUSHOVER_ENABLED:
return
http_handler = HTTPSConnection("api.pushover.net")
data = {'token': self.application_token,
'user': headphones.PUSHOVER_KEYS,
'user': headphones.CONFIG.PUSHOVER_KEYS,
'title': event,
'message': message.encode("utf-8"),
'priority': headphones.PUSHOVER_PRIORITY }
'priority': headphones.CONFIG.PUSHOVER_PRIORITY }
http_handler.request("POST",
"/1/messages.json",
@@ -625,11 +625,11 @@ class TwitterNotifier(object):
self.consumer_secret = "A4Xkw9i5SjHbTk7XT8zzOPqivhj9MmRDR9Qn95YA9sk"
def notify_snatch(self, title):
if headphones.TWITTER_ONSNATCH:
if headphones.CONFIG.TWITTER_ONSNATCH:
self._notifyTwitter(common.notifyStrings[common.NOTIFY_SNATCH]+': '+title+' at '+helpers.now())
def notify_download(self, title):
if headphones.TWITTER_ENABLED:
if headphones.CONFIG.TWITTER_ENABLED:
self._notifyTwitter(common.notifyStrings[common.NOTIFY_DOWNLOAD]+': '+title+' at '+helpers.now())
def test_notify(self):
@@ -650,16 +650,16 @@ class TwitterNotifier(object):
else:
request_token = dict(parse_qsl(content))
headphones.TWITTER_USERNAME = request_token['oauth_token']
headphones.TWITTER_PASSWORD = request_token['oauth_token_secret']
headphones.CONFIG.TWITTER_USERNAME = request_token['oauth_token']
headphones.CONFIG.TWITTER_PASSWORD = request_token['oauth_token_secret']
return self.AUTHORIZATION_URL+"?oauth_token="+ request_token['oauth_token']
def _get_credentials(self, key):
request_token = {}
request_token['oauth_token'] = headphones.TWITTER_USERNAME
request_token['oauth_token_secret'] = headphones.TWITTER_PASSWORD
request_token['oauth_token'] = headphones.CONFIG.TWITTER_USERNAME
request_token['oauth_token_secret'] = headphones.CONFIG.TWITTER_PASSWORD
request_token['oauth_callback_confirmed'] = 'true'
token = oauth.Token(request_token['oauth_token'], request_token['oauth_token_secret'])
@@ -685,8 +685,8 @@ class TwitterNotifier(object):
else:
logger.info('Your Twitter Access Token key: %s' % access_token['oauth_token'])
logger.info('Access Token secret: %s' % access_token['oauth_token_secret'])
headphones.TWITTER_USERNAME = access_token['oauth_token']
headphones.TWITTER_PASSWORD = access_token['oauth_token_secret']
headphones.CONFIG.TWITTER_USERNAME = access_token['oauth_token']
headphones.CONFIG.TWITTER_PASSWORD = access_token['oauth_token_secret']
return True
@@ -694,8 +694,8 @@ class TwitterNotifier(object):
username=self.consumer_key
password=self.consumer_secret
access_token_key=headphones.TWITTER_USERNAME
access_token_secret=headphones.TWITTER_PASSWORD
access_token_key=headphones.CONFIG.TWITTER_USERNAME
access_token_secret=headphones.CONFIG.TWITTER_PASSWORD
logger.info(u"Sending tweet: "+message)
@@ -710,9 +710,9 @@ class TwitterNotifier(object):
return True
def _notifyTwitter(self, message='', force=False):
prefix = headphones.TWITTER_PREFIX
prefix = headphones.CONFIG.TWITTER_PREFIX
if not headphones.TWITTER_ENABLED and not force:
if not headphones.CONFIG.TWITTER_ENABLED and not force:
return False
return self._send_tweet(prefix+": "+message)
@@ -783,7 +783,7 @@ class BOXCAR(object):
message += '<br></br><a href="http://musicbrainz.org/release-group/%s">MusicBrainz</a>' % rgid
data = urllib.urlencode({
'user_credentials': headphones.BOXCAR_TOKEN,
'user_credentials': headphones.CONFIG.BOXCAR_TOKEN,
'notification[title]': title.encode('utf-8'),
'notification[long_message]': message.encode('utf-8'),
'notification[sound]': "done"
@@ -801,9 +801,9 @@ class BOXCAR(object):
class SubSonicNotifier(object):
def __init__(self):
self.host = headphones.SUBSONIC_HOST
self.username = headphones.SUBSONIC_USERNAME
self.password = headphones.SUBSONIC_PASSWORD
self.host = headphones.CONFIG.SUBSONIC_HOST
self.username = headphones.CONFIG.SUBSONIC_USERNAME
self.password = headphones.CONFIG.SUBSONIC_PASSWORD
def notify(self, albumpaths):
# Correct URL

View File

@@ -37,19 +37,19 @@ def sendNZB(nzb):
addToTop = False
nzbgetXMLrpc = "%(username)s:%(password)s@%(host)s/xmlrpc"
if headphones.NZBGET_HOST == None:
if headphones.CONFIG.NZBGET_HOST == None:
logger.error(u"No NZBget host found in configuration. Please configure it.")
return False
if headphones.NZBGET_HOST.startswith('https://'):
if headphones.CONFIG.NZBGET_HOST.startswith('https://'):
nzbgetXMLrpc = 'https://' + nzbgetXMLrpc
headphones.NZBGET_HOST.replace('https://','',1)
headphones.CONFIG.NZBGET_HOST.replace('https://','',1)
else:
nzbgetXMLrpc = 'http://' + nzbgetXMLrpc
headphones.NZBGET_HOST.replace('http://','',1)
headphones.CONFIG.NZBGET_HOST.replace('http://','',1)
url = nzbgetXMLrpc % {"host": headphones.NZBGET_HOST, "username": headphones.NZBGET_USERNAME, "password": headphones.NZBGET_PASSWORD}
url = nzbgetXMLrpc % {"host": headphones.CONFIG.NZBGET_HOST, "username": headphones.CONFIG.NZBGET_USERNAME, "password": headphones.CONFIG.NZBGET_PASSWORD}
nzbGetRPC = xmlrpclib.ServerProxy(url)
try:
@@ -86,7 +86,7 @@ def sendNZB(nzb):
nzbget_version = int(nzbget_version_str[:nzbget_version_str.find(".")])
if nzbget_version == 0:
if nzbcontent64 is not None:
nzbget_result = nzbGetRPC.append(nzb.name + ".nzb", headphones.NZBGET_CATEGORY, addToTop, nzbcontent64)
nzbget_result = nzbGetRPC.append(nzb.name + ".nzb", headphones.CONFIG.NZBGET_CATEGORY, addToTop, nzbcontent64)
else:
if nzb.resultType == "nzb":
genProvider = GenericProvider("")
@@ -94,27 +94,27 @@ def sendNZB(nzb):
if (data == None):
return False
nzbcontent64 = standard_b64encode(data)
nzbget_result = nzbGetRPC.append(nzb.name + ".nzb", headphones.NZBGET_CATEGORY, addToTop, nzbcontent64)
nzbget_result = nzbGetRPC.append(nzb.name + ".nzb", headphones.CONFIG.NZBGET_CATEGORY, addToTop, nzbcontent64)
elif nzbget_version == 12:
if nzbcontent64 is not None:
nzbget_result = nzbGetRPC.append(nzb.name + ".nzb", headphones.NZBGET_CATEGORY, headphones.NZBGET_PRIORITY, False,
nzbget_result = nzbGetRPC.append(nzb.name + ".nzb", headphones.CONFIG.NZBGET_CATEGORY, headphones.CONFIG.NZBGET_PRIORITY, False,
nzbcontent64, False, dupekey, dupescore, "score")
else:
nzbget_result = nzbGetRPC.appendurl(nzb.name + ".nzb", headphones.NZBGET_CATEGORY, headphones.NZBGET_PRIORITY, False,
nzbget_result = nzbGetRPC.appendurl(nzb.name + ".nzb", headphones.CONFIG.NZBGET_CATEGORY, headphones.CONFIG.NZBGET_PRIORITY, False,
nzb.url, False, dupekey, dupescore, "score")
# v13+ has a new combined append method that accepts both (url and content)
# also the return value has changed from boolean to integer
# (Positive number representing NZBID of the queue item. 0 and negative numbers represent error codes.)
elif nzbget_version >= 13:
nzbget_result = True if nzbGetRPC.append(nzb.name + ".nzb", nzbcontent64 if nzbcontent64 is not None else nzb.url,
headphones.NZBGET_CATEGORY, headphones.NZBGET_PRIORITY, False, False, dupekey, dupescore,
headphones.CONFIG.NZBGET_CATEGORY, headphones.CONFIG.NZBGET_PRIORITY, False, False, dupekey, dupescore,
"score") > 0 else False
else:
if nzbcontent64 is not None:
nzbget_result = nzbGetRPC.append(nzb.name + ".nzb", headphones.NZBGET_CATEGORY, headphones.NZBGET_PRIORITY, False,
nzbget_result = nzbGetRPC.append(nzb.name + ".nzb", headphones.CONFIG.NZBGET_CATEGORY, headphones.CONFIG.NZBGET_PRIORITY, False,
nzbcontent64)
else:
nzbget_result = nzbGetRPC.appendurl(nzb.name + ".nzb", headphones.NZBGET_CATEGORY, headphones.NZBGET_PRIORITY, False,
nzbget_result = nzbGetRPC.appendurl(nzb.name + ".nzb", headphones.CONFIG.NZBGET_CATEGORY, headphones.CONFIG.NZBGET_PRIORITY, False,
nzb.url)
if nzbget_result:

View File

@@ -44,9 +44,9 @@ def checkFolder():
if album['FolderName']:
if album['Kind'] == 'nzb':
download_dir = headphones.DOWNLOAD_DIR
download_dir = headphones.CONFIG.DOWNLOAD_DIR
else:
download_dir = headphones.DOWNLOAD_TORRENT_DIR
download_dir = headphones.CONFIG.DOWNLOAD_TORRENT_DIR
album_path = os.path.join(download_dir, album['FolderName']).encode(headphones.SYS_ENCODING,'replace')
logger.info("Checking if %s exists" % album_path)
@@ -90,7 +90,7 @@ def verify(albumid, albumpath, Kind=None, forced=False):
# frozen during post processing, new artists will not be processed. This
# prevents new artists from appearing suddenly. In case forced is True,
# this check is skipped, since it is assumed the user wants this.
if headphones.FREEZE_DB and not forced:
if headphones.CONFIG.FREEZE_DB and not forced:
artist = myDB.select("SELECT ArtistName, ArtistID FROM artists WHERE ArtistId=? OR ArtistName=?", [release_dict['artist_id'], release_dict['artist_name']])
if not artist:
@@ -115,9 +115,9 @@ def verify(albumid, albumpath, Kind=None, forced=False):
logger.info("ArtistID: " + release_dict['artist_id'] + " , ArtistName: " + release_dict['artist_name'])
if headphones.INCLUDE_EXTRAS:
if headphones.CONFIG.INCLUDE_EXTRAS:
newValueDict['IncludeExtras'] = 1
newValueDict['Extras'] = headphones.EXTRAS
newValueDict['Extras'] = headphones.CONFIG.EXTRAS
myDB.upsert("artists", newValueDict, controlValueDict)
@@ -180,7 +180,7 @@ def verify(albumid, albumpath, Kind=None, forced=False):
# Split cue
if downloaded_cuecount and downloaded_cuecount >= len(downloaded_track_list):
if headphones.KEEP_TORRENT_FILES and Kind=="torrent":
if headphones.CONFIG.KEEP_TORRENT_FILES and Kind=="torrent":
albumpath = helpers.preserve_torrent_direcory(albumpath)
if albumpath and helpers.cue_split(albumpath):
downloaded_track_list = helpers.get_downloaded_track_list(albumpath)
@@ -280,7 +280,7 @@ def doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list,
logger.info('Starting post-processing for: %s - %s' % (release['ArtistName'], release['AlbumTitle']))
# Check to see if we're preserving the torrent dir
if headphones.KEEP_TORRENT_FILES and Kind=="torrent" and 'headphones-modified' not in albumpath:
if headphones.CONFIG.KEEP_TORRENT_FILES and Kind=="torrent" and 'headphones-modified' not in albumpath:
new_folder = os.path.join(albumpath, 'headphones-modified'.encode(headphones.SYS_ENCODING, 'replace'))
logger.info("Copying files to 'headphones-modified' subfolder to preserve downloaded files for seeding")
try:
@@ -318,10 +318,10 @@ def doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list,
# If one of the options below is set, it will access/touch/modify the
# files, which requires write permissions. This step just check this, so
# it will not try and fail lateron, with strange exceptions.
if headphones.EMBED_ALBUM_ART or headphones.CLEANUP_FILES or \
headphones.ADD_ALBUM_ART or headphones.CORRECT_METADATA or \
headphones.EMBED_LYRICS or headphones.RENAME_FILES or \
headphones.MOVE_FILES:
if headphones.CONFIG.EMBED_ALBUM_ART or headphones.CONFIG.CLEANUP_FILES or \
headphones.CONFIG.ADD_ALBUM_ART or headphones.CONFIG.CORRECT_METADATA or \
headphones.CONFIG.EMBED_LYRICS or headphones.CONFIG.RENAME_FILES or \
headphones.CONFIG.MOVE_FILES:
try:
with open(downloaded_track, "a+b"):
@@ -333,7 +333,7 @@ def doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list,
return
#start encoding
if headphones.MUSIC_ENCODER:
if headphones.CONFIG.MUSIC_ENCODER:
downloaded_track_list=music_encoder.encode(albumpath)
if not downloaded_track_list:
@@ -341,7 +341,7 @@ def doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list,
artwork = None
album_art_path = albumart.getAlbumArt(albumid)
if headphones.EMBED_ALBUM_ART or headphones.ADD_ALBUM_ART:
if headphones.CONFIG.EMBED_ALBUM_ART or headphones.CONFIG.ADD_ALBUM_ART:
if album_art_path:
artwork = request.request_content(album_art_path)
@@ -355,31 +355,31 @@ def doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list,
artwork = False
logger.info("No suitable album art found from Last.FM. Not adding album art")
if headphones.EMBED_ALBUM_ART and artwork:
if headphones.CONFIG.EMBED_ALBUM_ART and artwork:
embedAlbumArt(artwork, downloaded_track_list)
if headphones.CLEANUP_FILES:
if headphones.CONFIG.CLEANUP_FILES:
cleanupFiles(albumpath)
if headphones.KEEP_NFO:
if headphones.CONFIG.KEEP_NFO:
renameNFO(albumpath)
if headphones.ADD_ALBUM_ART and artwork:
if headphones.CONFIG.ADD_ALBUM_ART and artwork:
addAlbumArt(artwork, albumpath, release)
if headphones.CORRECT_METADATA:
if headphones.CONFIG.CORRECT_METADATA:
correctMetadata(albumid, release, downloaded_track_list)
if headphones.EMBED_LYRICS:
if headphones.CONFIG.EMBED_LYRICS:
embedLyrics(downloaded_track_list)
if headphones.RENAME_FILES:
if headphones.CONFIG.RENAME_FILES:
renameFiles(albumpath, downloaded_track_list, release)
if headphones.MOVE_FILES and not headphones.DESTINATION_DIR:
if headphones.CONFIG.MOVE_FILES and not headphones.CONFIG.DESTINATION_DIR:
logger.error('No DESTINATION_DIR has been set. Set "Destination Directory" to the parent directory you want to move the files to')
albumpaths = [albumpath]
elif headphones.MOVE_FILES and headphones.DESTINATION_DIR:
elif headphones.CONFIG.MOVE_FILES and headphones.CONFIG.DESTINATION_DIR:
albumpaths = moveFiles(albumpath, release, tracks)
else:
albumpaths = [albumpath]
@@ -391,13 +391,13 @@ def doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list,
myDB.action('UPDATE snatched SET status = "Processed" WHERE Status NOT LIKE "Seed%" and AlbumID=?', [albumid])
# Check if torrent has finished seeding
if headphones.TORRENT_DOWNLOADER == 1 or headphones.TORRENT_DOWNLOADER == 2:
if headphones.CONFIG.TORRENT_DOWNLOADER == 1 or headphones.CONFIG.TORRENT_DOWNLOADER == 2:
seed_snatched = myDB.action('SELECT * from snatched WHERE Status="Seed_Snatched" and AlbumID=?', [albumid]).fetchone()
if seed_snatched:
hash = seed_snatched['FolderName']
torrent_removed = False
logger.info(u'%s - %s. Checking if torrent has finished seeding and can be removed' % (release['ArtistName'], release['AlbumTitle']))
if headphones.TORRENT_DOWNLOADER == 1:
if headphones.CONFIG.TORRENT_DOWNLOADER == 1:
torrent_removed = transmission.removeTorrent(hash, True)
else:
torrent_removed = utorrent.removeTorrent(hash, True)
@@ -417,86 +417,86 @@ def doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list,
pushmessage = release['ArtistName'] + ' - ' + release['AlbumTitle']
statusmessage = "Download and Postprocessing completed"
if headphones.GROWL_ENABLED:
if headphones.CONFIG.GROWL_ENABLED:
logger.info(u"Growl request")
growl = notifiers.GROWL()
growl.notify(pushmessage, statusmessage)
if headphones.PROWL_ENABLED:
if headphones.CONFIG.PROWL_ENABLED:
logger.info(u"Prowl request")
prowl = notifiers.PROWL()
prowl.notify(pushmessage, statusmessage)
if headphones.XBMC_ENABLED:
if headphones.CONFIG.XBMC_ENABLED:
xbmc = notifiers.XBMC()
if headphones.XBMC_UPDATE:
if headphones.CONFIG.XBMC_UPDATE:
xbmc.update()
if headphones.XBMC_NOTIFY:
if headphones.CONFIG.XBMC_NOTIFY:
xbmc.notify(release['ArtistName'],
release['AlbumTitle'],
album_art_path)
if headphones.LMS_ENABLED:
if headphones.CONFIG.LMS_ENABLED:
lms = notifiers.LMS()
lms.update()
if headphones.PLEX_ENABLED:
if headphones.CONFIG.PLEX_ENABLED:
plex = notifiers.Plex()
if headphones.PLEX_UPDATE:
if headphones.CONFIG.PLEX_UPDATE:
plex.update()
if headphones.PLEX_NOTIFY:
if headphones.CONFIG.PLEX_NOTIFY:
plex.notify(release['ArtistName'],
release['AlbumTitle'],
album_art_path)
if headphones.NMA_ENABLED:
if headphones.CONFIG.NMA_ENABLED:
nma = notifiers.NMA()
nma.notify(release['ArtistName'], release['AlbumTitle'])
if headphones.PUSHALOT_ENABLED:
if headphones.CONFIG.PUSHALOT_ENABLED:
logger.info(u"Pushalot request")
pushalot = notifiers.PUSHALOT()
pushalot.notify(pushmessage, statusmessage)
if headphones.SYNOINDEX_ENABLED:
if headphones.CONFIG.SYNOINDEX_ENABLED:
syno = notifiers.Synoindex()
for albumpath in albumpaths:
syno.notify(albumpath)
if headphones.PUSHOVER_ENABLED:
if headphones.CONFIG.PUSHOVER_ENABLED:
logger.info(u"Pushover request")
pushover = notifiers.PUSHOVER()
pushover.notify(pushmessage, "Headphones")
if headphones.PUSHBULLET_ENABLED:
if headphones.CONFIG.PUSHBULLET_ENABLED:
logger.info(u"PushBullet request")
pushbullet = notifiers.PUSHBULLET()
pushbullet.notify(pushmessage, "Download and Postprocessing completed")
if headphones.TWITTER_ENABLED:
if headphones.CONFIG.TWITTER_ENABLED:
logger.info(u"Sending Twitter notification")
twitter = notifiers.TwitterNotifier()
twitter.notify_download(pushmessage)
if headphones.OSX_NOTIFY_ENABLED:
if headphones.CONFIG.OSX_NOTIFY_ENABLED:
logger.info(u"Sending OS X notification")
osx_notify = notifiers.OSX_NOTIFY()
osx_notify.notify(release['ArtistName'],
release['AlbumTitle'],
statusmessage)
if headphones.BOXCAR_ENABLED:
if headphones.CONFIG.BOXCAR_ENABLED:
logger.info(u"Sending Boxcar2 notification")
boxcar = notifiers.BOXCAR()
boxcar.notify('Headphones processed: ' + pushmessage,
statusmessage, release['AlbumID'])
if headphones.SUBSONIC_ENABLED:
if headphones.CONFIG.SUBSONIC_ENABLED:
logger.info(u"Sending Subsonic update")
subsonic = notifiers.SubSonicNotifier()
subsonic.notify(albumpaths)
if headphones.MPC_ENABLED:
if headphones.CONFIG.MPC_ENABLED:
mpc = notifiers.MPC()
mpc.notify()
@@ -535,11 +535,11 @@ def addAlbumArt(artwork, albumpath, release):
'$year': year
}
album_art_name = helpers.replace_all(headphones.ALBUM_ART_FORMAT.strip(), values) + ".jpg"
album_art_name = helpers.replace_all(headphones.CONFIG.ALBUM_ART_FORMAT.strip(), values) + ".jpg"
album_art_name = helpers.replace_illegal_chars(album_art_name).encode(headphones.SYS_ENCODING, 'replace')
if headphones.FILE_UNDERSCORES:
if headphones.CONFIG.FILE_UNDERSCORES:
album_art_name = album_art_name.replace(' ', '_')
if album_art_name.startswith('.'):
@@ -586,7 +586,7 @@ def moveFiles(albumpath, release, tracks):
artist = release['ArtistName'].replace('/', '_')
album = release['AlbumTitle'].replace('/', '_')
if headphones.FILE_UNDERSCORES:
if headphones.CONFIG.FILE_UNDERSCORES:
artist = artist.replace(' ', '_')
album = album.replace(' ', '_')
@@ -624,7 +624,7 @@ def moveFiles(albumpath, release, tracks):
'$originalfolder': origfolder.lower()
}
folder = helpers.replace_all(headphones.FOLDER_FORMAT.strip(), values, normalize=True)
folder = helpers.replace_all(headphones.CONFIG.FOLDER_FORMAT.strip(), values, normalize=True)
folder = helpers.replace_illegal_chars(folder, type="folder")
folder = folder.replace('./', '_/').replace('/.','/_')
@@ -653,11 +653,11 @@ def moveFiles(albumpath, release, tracks):
make_lossy_folder = False
make_lossless_folder = False
lossy_destination_path = os.path.normpath(os.path.join(headphones.DESTINATION_DIR, folder)).encode(headphones.SYS_ENCODING, 'replace')
lossless_destination_path = os.path.normpath(os.path.join(headphones.LOSSLESS_DESTINATION_DIR, folder)).encode(headphones.SYS_ENCODING, 'replace')
lossy_destination_path = os.path.normpath(os.path.join(headphones.CONFIG.DESTINATION_DIR, folder)).encode(headphones.SYS_ENCODING, 'replace')
lossless_destination_path = os.path.normpath(os.path.join(headphones.CONFIG.LOSSLESS_DESTINATION_DIR, folder)).encode(headphones.SYS_ENCODING, 'replace')
# If they set a destination dir for lossless media, only create the lossy folder if there is lossy media
if headphones.LOSSLESS_DESTINATION_DIR:
if headphones.CONFIG.LOSSLESS_DESTINATION_DIR:
if lossy_media:
make_lossy_folder = True
if lossless_media:
@@ -666,7 +666,7 @@ def moveFiles(albumpath, release, tracks):
else:
make_lossy_folder = True
last_folder = headphones.FOLDER_FORMAT.strip().split('/')[-1]
last_folder = headphones.CONFIG.FOLDER_FORMAT.strip().split('/')[-1]
if make_lossless_folder:
# Only rename the folder if they use the album name, otherwise merge into existing folder
@@ -674,20 +674,20 @@ def moveFiles(albumpath, release, tracks):
create_duplicate_folder = False
if headphones.REPLACE_EXISTING_FOLDERS:
if headphones.CONFIG.REPLACE_EXISTING_FOLDERS:
try:
shutil.rmtree(lossless_destination_path)
except Exception, e:
logger.error("Error deleting existing folder: %s. Creating duplicate folder. Error: %s" % (lossless_destination_path.decode(headphones.SYS_ENCODING, 'replace'), e))
create_duplicate_folder = True
if not headphones.REPLACE_EXISTING_FOLDERS or create_duplicate_folder:
if not headphones.CONFIG.REPLACE_EXISTING_FOLDERS or create_duplicate_folder:
temp_folder = folder
i = 1
while True:
newfolder = temp_folder + '[%i]' % i
lossless_destination_path = os.path.normpath(os.path.join(headphones.LOSSLESS_DESTINATION_DIR, newfolder)).encode(headphones.SYS_ENCODING, 'replace')
lossless_destination_path = os.path.normpath(os.path.join(headphones.CONFIG.LOSSLESS_DESTINATION_DIR, newfolder)).encode(headphones.SYS_ENCODING, 'replace')
if os.path.exists(lossless_destination_path):
i += 1
else:
@@ -707,20 +707,20 @@ def moveFiles(albumpath, release, tracks):
create_duplicate_folder = False
if headphones.REPLACE_EXISTING_FOLDERS:
if headphones.CONFIG.REPLACE_EXISTING_FOLDERS:
try:
shutil.rmtree(lossy_destination_path)
except Exception, e:
logger.error("Error deleting existing folder: %s. Creating duplicate folder. Error: %s" % (lossy_destination_path.decode(headphones.SYS_ENCODING, 'replace'), e))
create_duplicate_folder = True
if not headphones.REPLACE_EXISTING_FOLDERS or create_duplicate_folder:
if not headphones.CONFIG.REPLACE_EXISTING_FOLDERS or create_duplicate_folder:
temp_folder = folder
i = 1
while True:
newfolder = temp_folder + '[%i]' % i
lossy_destination_path = os.path.normpath(os.path.join(headphones.DESTINATION_DIR, newfolder)).encode(headphones.SYS_ENCODING, 'replace')
lossy_destination_path = os.path.normpath(os.path.join(headphones.CONFIG.DESTINATION_DIR, newfolder)).encode(headphones.SYS_ENCODING, 'replace')
if os.path.exists(lossy_destination_path):
i += 1
else:
@@ -778,10 +778,10 @@ def moveFiles(albumpath, release, tracks):
temp_fs = []
if make_lossless_folder:
temp_fs.append(headphones.LOSSLESS_DESTINATION_DIR)
temp_fs.append(headphones.CONFIG.LOSSLESS_DESTINATION_DIR)
if make_lossy_folder:
temp_fs.append(headphones.DESTINATION_DIR)
temp_fs.append(headphones.CONFIG.DESTINATION_DIR)
for temp_f in temp_fs:
@@ -790,7 +790,7 @@ def moveFiles(albumpath, release, tracks):
temp_f = os.path.join(temp_f, f)
try:
os.chmod(os.path.normpath(temp_f).encode(headphones.SYS_ENCODING, 'replace'), int(headphones.FOLDER_PERMISSIONS, 8))
os.chmod(os.path.normpath(temp_f).encode(headphones.SYS_ENCODING, 'replace'), int(headphones.CONFIG.FOLDER_PERMISSIONS, 8))
except Exception, e:
logger.error("Error trying to change permissions on folder: %s. %s", temp_f, e)
@@ -973,12 +973,12 @@ def renameFiles(albumpath, downloaded_track_list, release):
ext = os.path.splitext(downloaded_track)[1]
new_file_name = helpers.replace_all(headphones.FILE_FORMAT.strip(), values).replace('/','_') + ext
new_file_name = helpers.replace_all(headphones.CONFIG.FILE_FORMAT.strip(), values).replace('/','_') + ext
new_file_name = helpers.replace_illegal_chars(new_file_name).encode(headphones.SYS_ENCODING, 'replace')
if headphones.FILE_UNDERSCORES:
if headphones.CONFIG.FILE_UNDERSCORES:
new_file_name = new_file_name.replace(' ', '_')
if new_file_name.startswith('.'):
@@ -1005,7 +1005,7 @@ def updateFilePermissions(albumpaths):
for files in f:
full_path = os.path.join(r, files)
try:
os.chmod(full_path, int(headphones.FILE_PERMISSIONS, 8))
os.chmod(full_path, int(headphones.CONFIG.FILE_PERMISSIONS, 8))
except:
logger.error("Could not change permissions for file: %s", full_path)
continue
@@ -1035,10 +1035,10 @@ def forcePostProcess(dir=None, expand_subfolders=True, album_dir=None):
download_dirs = []
if dir:
download_dirs.append(dir.encode(headphones.SYS_ENCODING, 'replace'))
if headphones.DOWNLOAD_DIR and not dir:
download_dirs.append(headphones.DOWNLOAD_DIR.encode(headphones.SYS_ENCODING, 'replace'))
if headphones.DOWNLOAD_TORRENT_DIR and not dir:
download_dirs.append(headphones.DOWNLOAD_TORRENT_DIR.encode(headphones.SYS_ENCODING, 'replace'))
if headphones.CONFIG.DOWNLOAD_DIR and not dir:
download_dirs.append(headphones.CONFIG.DOWNLOAD_DIR.encode(headphones.SYS_ENCODING, 'replace'))
if headphones.CONFIG.DOWNLOAD_TORRENT_DIR and not dir:
download_dirs.append(headphones.CONFIG.DOWNLOAD_TORRENT_DIR.encode(headphones.SYS_ENCODING, 'replace'))
# If DOWNLOAD_DIR and DOWNLOAD_TORRENT_DIR are the same, remove the duplicate to prevent us from trying to process the same folder twice.
download_dirs = list(set(download_dirs))
@@ -1086,7 +1086,7 @@ def forcePostProcess(dir=None, expand_subfolders=True, album_dir=None):
snatched = myDB.action('SELECT AlbumID, Title, Kind, Status from snatched WHERE FolderName LIKE ?', [folder_basename]).fetchone()
if snatched:
if headphones.KEEP_TORRENT_FILES and snatched['Kind'] == 'torrent' and snatched['Status'] == 'Processed':
if headphones.CONFIG.KEEP_TORRENT_FILES and snatched['Kind'] == 'torrent' and snatched['Status'] == 'Processed':
logger.info('%s is a torrent folder being preserved for seeding and has already been processed. Skipping.', folder_basename)
continue
else:

View File

@@ -47,7 +47,7 @@ def request_response(url, method="get", auto_raise=True,
# Disable verification of SSL certificates if requested. Note: this could
# pose a security issue!
kwargs["verify"] = headphones.VERIFY_SSL_CERT
kwargs["verify"] = headphones.CONFIG.VERIFY_SSL_CERT
# Map method to the request.XXX method. This is a simple hack, but it allows
# requests to apply more magic per method. See lib/requests/api.py.

View File

@@ -34,14 +34,14 @@ def sendNZB(nzb):
params = {}
if headphones.SAB_USERNAME:
params['ma_username'] = headphones.SAB_USERNAME
if headphones.SAB_PASSWORD:
params['ma_password'] = headphones.SAB_PASSWORD
if headphones.SAB_APIKEY:
params['apikey'] = headphones.SAB_APIKEY
if headphones.SAB_CATEGORY:
params['cat'] = headphones.SAB_CATEGORY
if headphones.CONFIG.SAB_USERNAME:
params['ma_username'] = headphones.CONFIG.SAB_USERNAME
if headphones.CONFIG.SAB_PASSWORD:
params['ma_password'] = headphones.CONFIG.SAB_PASSWORD
if headphones.CONFIG.SAB_APIKEY:
params['apikey'] = headphones.CONFIG.SAB_APIKEY
if headphones.CONFIG.SAB_CATEGORY:
params['cat'] = headphones.CONFIG.SAB_CATEGORY
# if it's a normal result we just pass SAB the URL
if nzb.resultType == "nzb":
@@ -64,13 +64,13 @@ def sendNZB(nzb):
params['mode'] = 'addfile'
multiPartParams = {"nzbfile": (helpers.latinToAscii(nzb.name)+".nzb", nzbdata)}
if not headphones.SAB_HOST.startswith('http'):
headphones.SAB_HOST = 'http://' + headphones.SAB_HOST
if not headphones.CONFIG.SAB_HOST.startswith('http'):
headphones.CONFIG.SAB_HOST = 'http://' + headphones.CONFIG.SAB_HOST
if headphones.SAB_HOST.endswith('/'):
headphones.SAB_HOST = headphones.SAB_HOST[0:len(headphones.SAB_HOST)-1]
if headphones.CONFIG.SAB_HOST.endswith('/'):
headphones.CONFIG.SAB_HOST = headphones.CONFIG.SAB_HOST[0:len(headphones.CONFIG.SAB_HOST)-1]
url = headphones.SAB_HOST + "/" + "api?" + urllib.urlencode(params)
url = headphones.CONFIG.SAB_HOST + "/" + "api?" + urllib.urlencode(params)
try:
@@ -92,7 +92,7 @@ def sendNZB(nzb):
return False
except httplib.InvalidURL, e:
logger.error(u"Invalid SAB host, check your config. Current host: %s" % headphones.SAB_HOST)
logger.error(u"Invalid SAB host, check your config. Current host: %s" % headphones.CONFIG.SAB_HOST)
return False
except Exception, e:
@@ -133,20 +133,20 @@ def checkConfig():
'section' : 'misc'
}
if headphones.SAB_USERNAME:
params['ma_username'] = headphones.SAB_USERNAME
if headphones.SAB_PASSWORD:
params['ma_password'] = headphones.SAB_PASSWORD
if headphones.SAB_APIKEY:
params['apikey'] = headphones.SAB_APIKEY
if headphones.CONFIG.SAB_USERNAME:
params['ma_username'] = headphones.CONFIG.SAB_USERNAME
if headphones.CONFIG.SAB_PASSWORD:
params['ma_password'] = headphones.CONFIG.SAB_PASSWORD
if headphones.CONFIG.SAB_APIKEY:
params['apikey'] = headphones.CONFIG.SAB_APIKEY
if not headphones.SAB_HOST.startswith('http'):
headphones.SAB_HOST = 'http://' + headphones.SAB_HOST
if not headphones.CONFIG.SAB_HOST.startswith('http'):
headphones.CONFIG.SAB_HOST = 'http://' + headphones.CONFIG.SAB_HOST
if headphones.SAB_HOST.endswith('/'):
headphones.SAB_HOST = headphones.SAB_HOST[0:len(headphones.SAB_HOST)-1]
if headphones.CONFIG.SAB_HOST.endswith('/'):
headphones.CONFIG.SAB_HOST = headphones.CONFIG.SAB_HOST[0:len(headphones.CONFIG.SAB_HOST)-1]
url = headphones.SAB_HOST + "/" + "api?" + urllib.urlencode(params)
url = headphones.CONFIG.SAB_HOST + "/" + "api?" + urllib.urlencode(params)
try:
f = urllib.urlopen(url).read()

View File

@@ -206,15 +206,15 @@ def searchforalbum(albumid=None, new=False, losslessOnly=False, choose_specific_
def do_sorted_search(album, new, losslessOnly, choose_specific_download=False):
NZB_PROVIDERS = (headphones.HEADPHONES_INDEXER or headphones.NEWZNAB or headphones.NZBSORG or headphones.OMGWTFNZBS)
NZB_DOWNLOADERS = (headphones.SAB_HOST or headphones.BLACKHOLE_DIR or headphones.NZBGET_HOST)
TORRENT_PROVIDERS = (headphones.KAT or headphones.PIRATEBAY or headphones.MININOVA or headphones.WAFFLES or headphones.RUTRACKER or headphones.WHATCD)
NZB_PROVIDERS = (headphones.CONFIG.HEADPHONES_INDEXER or headphones.CONFIG.NEWZNAB or headphones.CONFIG.NZBSORG or headphones.CONFIG.OMGWTFNZBS)
NZB_DOWNLOADERS = (headphones.CONFIG.SAB_HOST or headphones.CONFIG.BLACKHOLE_DIR or headphones.CONFIG.NZBGET_HOST)
TORRENT_PROVIDERS = (headphones.CONFIG.KAT or headphones.CONFIG.PIRATEBAY or headphones.CONFIG.MININOVA or headphones.CONFIG.WAFFLES or headphones.CONFIG.RUTRACKER or headphones.CONFIG.WHATCD)
results = []
myDB = db.DBConnection()
albumlength = myDB.select('SELECT sum(TrackDuration) from tracks WHERE AlbumID=?', [album['AlbumID']])[0][0]
if headphones.PREFER_TORRENTS == 0:
if headphones.CONFIG.PREFER_TORRENTS == 0:
if NZB_PROVIDERS and NZB_DOWNLOADERS:
results = searchNZB(album, new, losslessOnly, albumlength)
@@ -222,7 +222,7 @@ def do_sorted_search(album, new, losslessOnly, choose_specific_download=False):
if not results and TORRENT_PROVIDERS:
results = searchTorrent(album, new, losslessOnly, albumlength)
elif headphones.PREFER_TORRENTS == 1:
elif headphones.CONFIG.PREFER_TORRENTS == 1:
if TORRENT_PROVIDERS:
results = searchTorrent(album, new, losslessOnly, albumlength)
@@ -277,23 +277,23 @@ def more_filtering(results, album, albumlength, new):
myDB = db.DBConnection()
# Lossless - ignore results if target size outside bitrate range
if headphones.PREFERRED_QUALITY == 3 and albumlength and (headphones.LOSSLESS_BITRATE_FROM or headphones.LOSSLESS_BITRATE_TO):
if headphones.LOSSLESS_BITRATE_FROM:
low_size_limit = albumlength/1000 * int(headphones.LOSSLESS_BITRATE_FROM) * 128
if headphones.LOSSLESS_BITRATE_TO:
high_size_limit = albumlength/1000 * int(headphones.LOSSLESS_BITRATE_TO) * 128
if headphones.CONFIG.PREFERRED_QUALITY == 3 and albumlength and (headphones.CONFIG.LOSSLESS_BITRATE_FROM or headphones.CONFIG.LOSSLESS_BITRATE_TO):
if headphones.CONFIG.LOSSLESS_BITRATE_FROM:
low_size_limit = albumlength/1000 * int(headphones.CONFIG.LOSSLESS_BITRATE_FROM) * 128
if headphones.CONFIG.LOSSLESS_BITRATE_TO:
high_size_limit = albumlength/1000 * int(headphones.CONFIG.LOSSLESS_BITRATE_TO) * 128
# Preferred Bitrate - ignore results if target size outside % buffer
elif headphones.PREFERRED_QUALITY == 2 and headphones.PREFERRED_BITRATE:
logger.debug('Target bitrate: %s kbps' % headphones.PREFERRED_BITRATE)
elif headphones.CONFIG.PREFERRED_QUALITY == 2 and headphones.CONFIG.PREFERRED_BITRATE:
logger.debug('Target bitrate: %s kbps' % headphones.CONFIG.PREFERRED_BITRATE)
if albumlength:
targetsize = albumlength/1000 * int(headphones.PREFERRED_BITRATE) * 128
targetsize = albumlength/1000 * int(headphones.CONFIG.PREFERRED_BITRATE) * 128
logger.info('Target size: %s' % helpers.bytes_to_mb(targetsize))
if headphones.PREFERRED_BITRATE_LOW_BUFFER:
low_size_limit = targetsize - (targetsize * int(headphones.PREFERRED_BITRATE_LOW_BUFFER)/100)
if headphones.PREFERRED_BITRATE_HIGH_BUFFER:
high_size_limit = targetsize + (targetsize * int(headphones.PREFERRED_BITRATE_HIGH_BUFFER)/100)
if headphones.PREFERRED_BITRATE_ALLOW_LOSSLESS:
if headphones.CONFIG.PREFERRED_BITRATE_LOW_BUFFER:
low_size_limit = targetsize - (targetsize * int(headphones.CONFIG.PREFERRED_BITRATE_LOW_BUFFER)/100)
if headphones.CONFIG.PREFERRED_BITRATE_HIGH_BUFFER:
high_size_limit = targetsize + (targetsize * int(headphones.CONFIG.PREFERRED_BITRATE_HIGH_BUFFER)/100)
if headphones.CONFIG.PREFERRED_BITRATE_ALLOW_LOSSLESS:
allow_lossless = True
newlist = []
@@ -341,8 +341,8 @@ def sort_search_results(resultlist, album, new, albumlength):
# Add a priority if it has any of the preferred words
temp_list = []
preferred_words = None
if headphones.PREFERRED_WORDS:
preferred_words = helpers.split_string(headphones.PREFERRED_WORDS)
if headphones.CONFIG.PREFERRED_WORDS:
preferred_words = helpers.split_string(headphones.CONFIG.PREFERRED_WORDS)
for result in resultlist:
priority = 0
if preferred_words:
@@ -357,10 +357,10 @@ def sort_search_results(resultlist, album, new, albumlength):
resultlist = temp_list
if headphones.PREFERRED_QUALITY == 2 and headphones.PREFERRED_BITRATE:
if headphones.CONFIG.PREFERRED_QUALITY == 2 and headphones.CONFIG.PREFERRED_BITRATE:
try:
targetsize = albumlength/1000 * int(headphones.PREFERRED_BITRATE) * 128
targetsize = albumlength/1000 * int(headphones.CONFIG.PREFERRED_BITRATE) * 128
if not targetsize:
logger.info('No track information for %s - %s. Defaulting to highest quality' % (album['ArtistName'], album['AlbumTitle']))
@@ -382,7 +382,7 @@ def sort_search_results(resultlist, album, new, albumlength):
finallist = sorted(newlist, key=lambda title: (-title[5], title[6]))
if not len(finallist) and len(flac_list) and headphones.PREFERRED_BITRATE_ALLOW_LOSSLESS:
if not len(finallist) and len(flac_list) and headphones.CONFIG.PREFERRED_BITRATE_ALLOW_LOSSLESS:
logger.info("Since there were no appropriate lossy matches (and at least one lossless match, going to use lossless instead")
finallist = sorted(flac_list, key=lambda title: (title[5], int(title[1])), reverse=True)
except Exception as e:
@@ -440,7 +440,7 @@ def searchNZB(album, new=False, losslessOnly=False, albumlength=None):
artistterm = re.sub('[\.\-\/]', ' ', cleanartist).encode('utf-8')
# If Preferred Bitrate and High Limit and Allow Lossless then get both lossy and lossless
if headphones.PREFERRED_QUALITY == 2 and headphones.PREFERRED_BITRATE and headphones.PREFERRED_BITRATE_HIGH_BUFFER and headphones.PREFERRED_BITRATE_ALLOW_LOSSLESS:
if headphones.CONFIG.PREFERRED_QUALITY == 2 and headphones.CONFIG.PREFERRED_BITRATE and headphones.CONFIG.PREFERRED_BITRATE_HIGH_BUFFER and headphones.CONFIG.PREFERRED_BITRATE_ALLOW_LOSSLESS:
allow_lossless = True
else:
allow_lossless = False
@@ -449,12 +449,12 @@ def searchNZB(album, new=False, losslessOnly=False, albumlength=None):
resultlist = []
if headphones.HEADPHONES_INDEXER:
if headphones.CONFIG.HEADPHONES_INDEXER:
provider = "headphones"
if headphones.PREFERRED_QUALITY == 3 or losslessOnly:
if headphones.CONFIG.PREFERRED_QUALITY == 3 or losslessOnly:
categories = "3040"
elif headphones.PREFERRED_QUALITY == 1 or allow_lossless:
elif headphones.CONFIG.PREFERRED_QUALITY == 1 or allow_lossless:
categories = "3040,3010"
else:
categories = "3010"
@@ -471,14 +471,14 @@ def searchNZB(album, new=False, losslessOnly=False, albumlength=None):
"t": "search",
"cat": categories,
"apikey": '964d601959918a578a670984bdee9357',
"maxage": headphones.USENET_RETENTION,
"maxage": headphones.CONFIG.USENET_RETENTION,
"q": term
}
data = request.request_feed(
url="http://indexer.codeshy.com/api",
params=params, headers=headers,
auth=(headphones.HPUSER, headphones.HPPASS)
auth=(headphones.CONFIG.HPUSER, headphones.CONFIG.HPPASS)
)
# Process feed
@@ -498,21 +498,20 @@ def searchNZB(album, new=False, losslessOnly=False, albumlength=None):
except Exception as e:
logger.error(u"An unknown error occurred trying to parse the feed: %s" % e)
if headphones.NEWZNAB:
if headphones.CONFIG.NEWZNAB:
provider = "newznab"
newznab_hosts = []
if headphones.NEWZNAB_HOST and headphones.NEWZNAB_ENABLED:
if headphones.CONFIG.NEWZNAB_HOST and headphones.CONFIG.NEWZNAB_ENABLED:
newznab_hosts.append((headphones.CONFIG.NEWZNAB_HOST, headphones.CONFIG.NEWZNAB_APIKEY, headphones.CONFIG.NEWZNAB_ENABLED))
newznab_hosts.append((headphones.NEWZNAB_HOST, headphones.NEWZNAB_APIKEY, headphones.NEWZNAB_ENABLED))
for newznab_host in headphones.EXTRA_NEWZNABS:
for newznab_host in headphones.CONFIG.get_extra_newznabs():
if newznab_host[2] == '1' or newznab_host[2] == 1:
newznab_hosts.append(newznab_host)
if headphones.PREFERRED_QUALITY == 3 or losslessOnly:
if headphones.CONFIG.PREFERRED_QUALITY == 3 or losslessOnly:
categories = "3040"
elif headphones.PREFERRED_QUALITY == 1 or allow_lossless:
elif headphones.CONFIG.PREFERRED_QUALITY == 1 or allow_lossless:
categories = "3040,3010"
else:
categories = "3010"
@@ -544,7 +543,7 @@ def searchNZB(album, new=False, losslessOnly=False, albumlength=None):
"t": "search",
"apikey": newznab_host[1],
"cat": categories,
"maxage": headphones.USENET_RETENTION,
"maxage": headphones.CONFIG.USENET_RETENTION,
"q": term
}
@@ -572,11 +571,11 @@ def searchNZB(album, new=False, losslessOnly=False, albumlength=None):
except Exception as e:
logger.exception("An unknown error occurred trying to parse the feed: %s" % e)
if headphones.NZBSORG:
if headphones.CONFIG.NZBSORG:
provider = "nzbsorg"
if headphones.PREFERRED_QUALITY == 3 or losslessOnly:
if headphones.CONFIG.PREFERRED_QUALITY == 3 or losslessOnly:
categories = "3040"
elif headphones.PREFERRED_QUALITY == 1 or allow_lossless:
elif headphones.CONFIG.PREFERRED_QUALITY == 1 or allow_lossless:
categories = "3040,3010"
else:
categories = "3010"
@@ -591,9 +590,9 @@ def searchNZB(album, new=False, losslessOnly=False, albumlength=None):
headers = { 'User-Agent': USER_AGENT }
params = {
"t": "search",
"apikey": headphones.NZBSORG_HASH,
"apikey": headphones.CONFIG.NZBSORG_HASH,
"cat": categories,
"maxage": headphones.USENET_RETENTION,
"maxage": headphones.CONFIG.USENET_RETENTION,
"q": term
}
@@ -618,12 +617,12 @@ def searchNZB(album, new=False, losslessOnly=False, albumlength=None):
except Exception as e:
logger.exception("Unhandled exception while parsing feed")
if headphones.OMGWTFNZBS:
if headphones.CONFIG.OMGWTFNZBS:
provider = "omgwtfnzbs"
if headphones.PREFERRED_QUALITY == 3 or losslessOnly:
if headphones.CONFIG.PREFERRED_QUALITY == 3 or losslessOnly:
categories = "22"
elif headphones.PREFERRED_QUALITY == 1 or allow_lossless:
elif headphones.CONFIG.PREFERRED_QUALITY == 1 or allow_lossless:
categories = "22,7"
else:
categories = "7"
@@ -637,10 +636,10 @@ def searchNZB(album, new=False, losslessOnly=False, albumlength=None):
headers = { 'User-Agent': USER_AGENT }
params = {
"user": headphones.OMGWTFNZBS_UID,
"api": headphones.OMGWTFNZBS_APIKEY,
"user": headphones.CONFIG.OMGWTFNZBS_UID,
"api": headphones.CONFIG.OMGWTFNZBS_APIKEY,
"catid": categories,
"retention": headphones.USENET_RETENTION,
"retention": headphones.CONFIG.USENET_RETENTION,
"search": term
}
@@ -690,7 +689,7 @@ def send_to_downloader(data, bestqual, album):
if kind == 'nzb':
folder_name = helpers.sab_sanitize_foldername(bestqual[0])
if headphones.NZB_DOWNLOADER == 1:
if headphones.CONFIG.NZB_DOWNLOADER == 1:
nzb = classes.NZBDataSearchResult()
nzb.extraInfo.append(data)
@@ -698,7 +697,7 @@ def send_to_downloader(data, bestqual, album):
if not nzbget.sendNZB(nzb):
return
elif headphones.NZB_DOWNLOADER == 0:
elif headphones.CONFIG.NZB_DOWNLOADER == 0:
nzb = classes.NZBDataSearchResult()
nzb.extraInfo.append(data)
@@ -716,7 +715,7 @@ def send_to_downloader(data, bestqual, album):
else:
nzb_name = folder_name + '.nzb'
download_path = os.path.join(headphones.BLACKHOLE_DIR, nzb_name)
download_path = os.path.join(headphones.CONFIG.BLACKHOLE_DIR, nzb_name)
try:
prev = os.umask(headphones.UMASK)
@@ -733,14 +732,14 @@ def send_to_downloader(data, bestqual, album):
folder_name = '%s - %s [%s]' % (helpers.latinToAscii(album['ArtistName']).encode('UTF-8').replace('/', '_'), helpers.latinToAscii(album['AlbumTitle']).encode('UTF-8').replace('/', '_'), get_year_from_release_date(album['ReleaseDate']))
# Blackhole
if headphones.TORRENT_DOWNLOADER == 0:
if headphones.CONFIG.TORRENT_DOWNLOADER == 0:
# Get torrent name from .torrent, this is usually used by the torrent client as the folder name
torrent_name = helpers.replace_illegal_chars(folder_name) + '.torrent'
download_path = os.path.join(headphones.TORRENTBLACKHOLE_DIR, torrent_name)
download_path = os.path.join(headphones.CONFIG.TORRENTBLACKHOLE_DIR, torrent_name)
if bestqual[2].lower().startswith("magnet:"):
if headphones.MAGNET_LINKS == 1:
if headphones.CONFIG.MAGNET_LINKS == 1:
try:
if headphones.SYS_PLATFORM == 'win32':
os.startfile(bestqual[2])
@@ -768,7 +767,6 @@ def send_to_downloader(data, bestqual, album):
if data and "torcache" in data:
if not torrent_to_file(download_path, data):
return
# Extract folder name from torrent
folder_name = read_torrent_name(download_path,
bestqual[0])
@@ -800,7 +798,7 @@ def send_to_downloader(data, bestqual, album):
# Extract folder name from torrent
folder_name = read_torrent_name(download_path, bestqual[0])
elif headphones.TORRENT_DOWNLOADER == 1:
elif headphones.CONFIG.TORRENT_DOWNLOADER == 1:
logger.info("Sending torrent to Transmission")
# rutracker needs cookies to be set, pass the .torrent file instead of url
@@ -834,7 +832,7 @@ def send_to_downloader(data, bestqual, album):
if seed_ratio is not None:
transmission.setSeedRatio(torrentid, seed_ratio)
else:# if headphones.TORRENT_DOWNLOADER == 2:
else:# if headphones.CONFIG.TORRENT_DOWNLOADER == 2:
logger.info("Sending torrent to uTorrent")
# rutracker needs cookies to be set, pass the .torrent file instead of url
@@ -884,39 +882,39 @@ def send_to_downloader(data, bestqual, album):
provider = provider.split("//")[1]
name = folder_name if folder_name else None
if headphones.GROWL_ENABLED and headphones.GROWL_ONSNATCH:
if headphones.CONFIG.GROWL_ENABLED and headphones.CONFIG.GROWL_ONSNATCH:
logger.info(u"Sending Growl notification")
growl = notifiers.GROWL()
growl.notify(name,"Download started")
if headphones.PROWL_ENABLED and headphones.PROWL_ONSNATCH:
if headphones.CONFIG.PROWL_ENABLED and headphones.CONFIG.PROWL_ONSNATCH:
logger.info(u"Sending Prowl notification")
prowl = notifiers.PROWL()
prowl.notify(name,"Download started")
if headphones.PUSHOVER_ENABLED and headphones.PUSHOVER_ONSNATCH:
if headphones.CONFIG.PUSHOVER_ENABLED and headphones.CONFIG.PUSHOVER_ONSNATCH:
logger.info(u"Sending Pushover notification")
prowl = notifiers.PUSHOVER()
prowl.notify(name,"Download started")
if headphones.PUSHBULLET_ENABLED and headphones.PUSHBULLET_ONSNATCH:
if headphones.CONFIG.PUSHBULLET_ENABLED and headphones.CONFIG.PUSHBULLET_ONSNATCH:
logger.info(u"Sending PushBullet notification")
pushbullet = notifiers.PUSHBULLET()
pushbullet.notify(name + " has been snatched!", "Download started")
if headphones.TWITTER_ENABLED and headphones.TWITTER_ONSNATCH:
if headphones.CONFIG.TWITTER_ENABLED and headphones.CONFIG.TWITTER_ONSNATCH:
logger.info(u"Sending Twitter notification")
twitter = notifiers.TwitterNotifier()
twitter.notify_snatch(name)
if headphones.NMA_ENABLED and headphones.NMA_ONSNATCH:
if headphones.CONFIG.NMA_ENABLED and headphones.CONFIG.NMA_ONSNATCH:
logger.info(u"Sending NMA notification")
nma = notifiers.NMA()
nma.notify(snatched=name)
if headphones.PUSHALOT_ENABLED and headphones.PUSHALOT_ONSNATCH:
if headphones.CONFIG.PUSHALOT_ENABLED and headphones.CONFIG.PUSHALOT_ONSNATCH:
logger.info(u"Sending Pushalot notification")
pushalot = notifiers.PUSHALOT()
pushalot.notify(name,"Download started")
if headphones.OSX_NOTIFY_ENABLED and headphones.OSX_NOTIFY_ONSNATCH:
if headphones.CONFIG.OSX_NOTIFY_ENABLED and headphones.CONFIG.OSX_NOTIFY_ONSNATCH:
logger.info(u"Sending OS X notification")
osx_notify = notifiers.OSX_NOTIFY()
osx_notify.notify(artist, albumname, 'Snatched: ' + provider + '. ' + name)
if headphones.BOXCAR_ENABLED and headphones.BOXCAR_ONSNATCH:
if headphones.CONFIG.BOXCAR_ENABLED and headphones.CONFIG.BOXCAR_ONSNATCH:
logger.info(u"Sending Boxcar2 notification")
b2msg = 'From ' + provider + '<br></br>' + name
boxcar = notifiers.BOXCAR()
@@ -946,18 +944,18 @@ def verifyresult(title, artistterm, term, lossless):
return False
# Filter out FLAC if we're not specifically looking for it
if headphones.PREFERRED_QUALITY == (0 or '0') and 'flac' in title.lower() and not lossless:
if headphones.CONFIG.PREFERRED_QUALITY == (0 or '0') and 'flac' in title.lower() and not lossless:
logger.info("Removed %s from results because it's a lossless album and we're not looking for a lossless album right now.", title)
return False
if headphones.IGNORED_WORDS:
for each_word in helpers.split_string(headphones.IGNORED_WORDS):
if headphones.CONFIG.IGNORED_WORDS:
for each_word in helpers.split_string(headphones.CONFIG.IGNORED_WORDS):
if each_word.lower() in title.lower():
logger.info("Removed '%s' from results because it contains ignored word: '%s'", title, each_word)
return False
if headphones.REQUIRED_WORDS:
for each_word in helpers.split_string(headphones.REQUIRED_WORDS):
if headphones.CONFIG.REQUIRED_WORDS:
for each_word in helpers.split_string(headphones.CONFIG.REQUIRED_WORDS):
if ' OR ' in each_word:
or_words = helpers.split_string(each_word, 'OR')
if any(word.lower() in title.lower() for word in or_words):
@@ -992,8 +990,8 @@ def searchTorrent(album, new=False, losslessOnly=False, albumlength=None):
# rutracker login
if headphones.RUTRACKER and album:
rulogin = rutracker.login(headphones.RUTRACKER_USER, headphones.RUTRACKER_PASSWORD)
if headphones.CONFIG.RUTRACKER and album:
rulogin = rutracker.login(headphones.CONFIG.RUTRACKER_USER, headphones.CONFIG.RUTRACKER_PASSWORD)
if not rulogin:
logger.info(u'Could not login to rutracker, search results will exclude this provider')
@@ -1040,7 +1038,7 @@ def searchTorrent(album, new=False, losslessOnly=False, albumlength=None):
albumterm = re.sub('[\.\-\/]', ' ', cleanalbum).encode('utf-8', 'replace')
# If Preferred Bitrate and High Limit and Allow Lossless then get both lossy and lossless
if headphones.PREFERRED_QUALITY == 2 and headphones.PREFERRED_BITRATE and headphones.PREFERRED_BITRATE_HIGH_BUFFER and headphones.PREFERRED_BITRATE_ALLOW_LOSSLESS:
if headphones.CONFIG.PREFERRED_QUALITY == 2 and headphones.CONFIG.PREFERRED_BITRATE and headphones.CONFIG.PREFERRED_BITRATE_HIGH_BUFFER and headphones.CONFIG.PREFERRED_BITRATE_ALLOW_LOSSLESS:
allow_lossless = True
else:
allow_lossless = False
@@ -1049,7 +1047,7 @@ def searchTorrent(album, new=False, losslessOnly=False, albumlength=None):
resultlist = []
pre_sorted_results = False
minimumseeders = int(headphones.NUMBEROFSEEDERS) - 1
minimumseeders = int(headphones.CONFIG.NUMBEROFSEEDERS) - 1
def set_proxy(proxy_url):
if not proxy_url.startswith('http'):
@@ -1060,13 +1058,13 @@ def searchTorrent(album, new=False, losslessOnly=False, albumlength=None):
return proxy_url
if headphones.KAT:
if headphones.CONFIG.KAT:
provider = "Kick Ass Torrents"
ka_term = term.replace("!", "")
# Use proxy if specified
if headphones.KAT_PROXY_URL:
providerurl = fix_url(set_proxy(headphones.KAT_PROXY_URL))
if headphones.CONFIG.KAT_PROXY_URL:
providerurl = fix_url(set_proxy(headphones.CONFIG.KAT_PROXY_URL))
else:
providerurl = fix_url("https://kickass.to")
@@ -1074,11 +1072,11 @@ def searchTorrent(album, new=False, losslessOnly=False, albumlength=None):
providerurl = providerurl + "/usearch/" + ka_term
# Pick category for torrents
if headphones.PREFERRED_QUALITY == 3 or losslessOnly:
if headphones.CONFIG.PREFERRED_QUALITY == 3 or losslessOnly:
categories = "7" # Music
format = "2" # FLAC
maxsize = 10000000000
elif headphones.PREFERRED_QUALITY == 1 or allow_lossless:
elif headphones.CONFIG.PREFERRED_QUALITY == 1 or allow_lossless:
categories = "7" # Music
format = "10" # MP3 and FLAC
maxsize = 10000000000
@@ -1124,16 +1122,16 @@ def searchTorrent(album, new=False, losslessOnly=False, albumlength=None):
except Exception as e:
logger.exception("Unhandled exception in the KAT parser")
if headphones.WAFFLES:
if headphones.CONFIG.WAFFLES:
provider = "Waffles.fm"
providerurl = fix_url("https://www.waffles.fm/browse.php")
bitrate = None
if headphones.PREFERRED_QUALITY == 3 or losslessOnly:
if headphones.CONFIG.PREFERRED_QUALITY == 3 or losslessOnly:
format = "FLAC"
bitrate = "(Lossless)"
maxsize = 10000000000
elif headphones.PREFERRED_QUALITY == 1 or allow_lossless:
elif headphones.CONFIG.PREFERRED_QUALITY == 1 or allow_lossless:
format = "FLAC OR MP3"
maxsize = 10000000000
else:
@@ -1158,8 +1156,8 @@ def searchTorrent(album, new=False, losslessOnly=False, albumlength=None):
logger.info('Parsing results from Waffles')
params = {
"uid": headphones.WAFFLES_UID,
"passkey": headphones.WAFFLES_PASSKEY,
"uid": headphones.CONFIG.WAFFLES_UID,
"passkey": headphones.CONFIG.WAFFLES_PASSKEY,
"rss": "1",
"c0": "1",
"s": "seeders", # sort by
@@ -1190,7 +1188,7 @@ def searchTorrent(album, new=False, losslessOnly=False, albumlength=None):
logger.error(u"An error occurred while trying to parse the response from Waffles.fm: %s", e)
# rutracker.org
if headphones.RUTRACKER and rulogin:
if headphones.CONFIG.RUTRACKER and rulogin:
provider = "rutracker.org"
@@ -1199,10 +1197,10 @@ def searchTorrent(album, new=False, losslessOnly=False, albumlength=None):
logger.info(u'Release date not specified, ignoring for rutracker.org')
else:
if headphones.PREFERRED_QUALITY == 3 or losslessOnly:
if headphones.CONFIG.PREFERRED_QUALITY == 3 or losslessOnly:
format = 'lossless'
maxsize = 10000000000
elif headphones.PREFERRED_QUALITY == 1 or allow_lossless:
elif headphones.CONFIG.PREFERRED_QUALITY == 1 or allow_lossless:
format = 'lossless+mp3'
maxsize = 10000000000
else:
@@ -1231,19 +1229,19 @@ def searchTorrent(album, new=False, losslessOnly=False, albumlength=None):
else:
logger.info(u"No valid results found from %s" % (provider))
if headphones.WHATCD:
if headphones.CONFIG.WHATCD:
provider = "What.cd"
providerurl = "http://what.cd/"
bitrate = None
bitrate_string = bitrate
if headphones.PREFERRED_QUALITY == 3 or losslessOnly: # Lossless Only mode
if headphones.CONFIG.PREFERRED_QUALITY == 3 or losslessOnly: # Lossless Only mode
search_formats = [gazelleformat.FLAC]
maxsize = 10000000000
elif headphones.PREFERRED_QUALITY == 2: # Preferred quality mode
elif headphones.CONFIG.PREFERRED_QUALITY == 2: # Preferred quality mode
search_formats = [None] # should return all
bitrate = headphones.PREFERRED_BITRATE
bitrate = headphones.CONFIG.PREFERRED_BITRATE
if bitrate:
for encoding_string in gazelleencoding.ALL_ENCODINGS:
if re.search(bitrate, encoding_string, flags=re.I):
@@ -1251,7 +1249,7 @@ def searchTorrent(album, new=False, losslessOnly=False, albumlength=None):
if bitrate_string not in gazelleencoding.ALL_ENCODINGS:
logger.info(u"Your preferred bitrate is not one of the available What.cd filters, so not using it as a search parameter.")
maxsize = 10000000000
elif headphones.PREFERRED_QUALITY == 1 or allow_lossless: # Highest quality including lossless
elif headphones.CONFIG.PREFERRED_QUALITY == 1 or allow_lossless: # Highest quality including lossless
search_formats = [gazelleformat.FLAC, gazelleformat.MP3]
maxsize = 10000000000
else: # Highest quality excluding lossless
@@ -1261,7 +1259,7 @@ def searchTorrent(album, new=False, losslessOnly=False, albumlength=None):
if not gazelle or not gazelle.logged_in():
try:
logger.info(u"Attempting to log in to What.cd...")
gazelle = gazelleapi.GazelleAPI(headphones.WHATCD_USERNAME, headphones.WHATCD_PASSWORD)
gazelle = gazelleapi.GazelleAPI(headphones.CONFIG.WHATCD_USERNAME, headphones.CONFIG.WHATCD_PASSWORD)
gazelle._login()
except Exception as e:
gazelle = None
@@ -1311,13 +1309,13 @@ def searchTorrent(album, new=False, losslessOnly=False, albumlength=None):
'torrent'))
# Pirate Bay
if headphones.PIRATEBAY:
if headphones.CONFIG.PIRATEBAY:
provider = "The Pirate Bay"
tpb_term = term.replace("!", "")
# Use proxy if specified
if headphones.PIRATEBAY_PROXY_URL:
providerurl = fix_url(set_proxy(headphones.PIRATEBAY_PROXY_URL))
if headphones.CONFIG.PIRATEBAY_PROXY_URL:
providerurl = fix_url(set_proxy(headphones.CONFIG.PIRATEBAY_PROXY_URL))
else:
providerurl = fix_url("https://thepiratebay.se")
@@ -1325,10 +1323,10 @@ def searchTorrent(album, new=False, losslessOnly=False, albumlength=None):
providerurl = providerurl + "/search/" + tpb_term + "/0/7/" # 7 is sort by seeders
# Pick category for torrents
if headphones.PREFERRED_QUALITY == 3 or losslessOnly:
if headphones.CONFIG.PREFERRED_QUALITY == 3 or losslessOnly:
category = '104' # FLAC
maxsize = 10000000000
elif headphones.PREFERRED_QUALITY == 1 or allow_lossless:
elif headphones.CONFIG.PREFERRED_QUALITY == 1 or allow_lossless:
category = '100' # General audio category
maxsize = 10000000000
else:
@@ -1355,7 +1353,7 @@ def searchTorrent(album, new=False, losslessOnly=False, albumlength=None):
title = ''.join(item.find("a", {"class" : "detLink"}))
seeds = int(''.join(item.find("td", {"align" : "right"})))
if headphones.TORRENT_DOWNLOADER == 0:
if headphones.CONFIG.TORRENT_DOWNLOADER == 0:
try:
url = item.find("a", {"title":"Download this torrent"})['href']
except TypeError:
@@ -1381,15 +1379,15 @@ def searchTorrent(album, new=False, losslessOnly=False, albumlength=None):
except Exception as e:
logger.error(u"An unknown error occurred in the Pirate Bay parser: %s" % e)
if headphones.MININOVA:
if headphones.CONFIG.MININOVA:
provider = "Mininova"
providerurl = fix_url("http://www.mininova.org/rss/" + term + "/5")
if headphones.PREFERRED_QUALITY == 3 or losslessOnly:
if headphones.CONFIG.PREFERRED_QUALITY == 3 or losslessOnly:
categories = "7" #music
format = "2" #flac
maxsize = 10000000000
elif headphones.PREFERRED_QUALITY == 1 or allow_lossless:
elif headphones.CONFIG.PREFERRED_QUALITY == 1 or allow_lossless:
categories = "7" #music
format = "10" #mp3+flac
maxsize = 10000000000
@@ -1453,7 +1451,7 @@ def preprocess(resultlist):
for result in resultlist:
if result[4] == 'torrent':
#Get out of here if we're using Transmission
if headphones.TORRENT_DOWNLOADER == 1: ## if not a magnet link still need the .torrent to generate hash... uTorrent support labeling
if headphones.CONFIG.TORRENT_DOWNLOADER == 1: ## if not a magnet link still need the .torrent to generate hash... uTorrent support labeling
return True, result
# get outta here if rutracker
if result[3] == 'rutracker.org':
@@ -1477,6 +1475,6 @@ def preprocess(resultlist):
headers = {'User-Agent': USER_AGENT}
if result[3] == 'headphones':
return request.request_content(url=result[2], headers=headers, auth=(headphones.HPUSER, headphones.HPPASS)), result
return request.request_content(url=result[2], headers=headers, auth=(headphones.CONFIG.HPUSER, headphones.CONFIG.HPPASS)), result
else:
return request.request_content(url=result[2], headers=headers), result
return request.request_content(url=result[2], headers=headers), result

View File

@@ -294,7 +294,7 @@ class Rutracker():
os.umask(prev)
# Add file to utorrent
if headphones.TORRENT_DOWNLOADER == 2:
if headphones.CONFIG.TORRENT_DOWNLOADER == 2:
self.utorrent_add_file(download_path)
except Exception as e:
@@ -306,7 +306,7 @@ class Rutracker():
#TODO get this working in utorrent.py
def utorrent_add_file(self, filename):
host = headphones.UTORRENT_HOST
host = headphones.CONFIG.UTORRENT_HOST
if not host.startswith('http'):
host = 'http://' + host
if host.endswith('/'):
@@ -315,8 +315,8 @@ class Rutracker():
host = host[:-4]
base_url = host
username = headphones.UTORRENT_USERNAME
password = headphones.UTORRENT_PASSWORD
username = headphones.CONFIG.UTORRENT_USERNAME
password = headphones.CONFIG.UTORRENT_PASSWORD
session = requests.Session()
url = base_url + '/gui/'

View File

@@ -33,7 +33,7 @@ def checkTorrentFinished():
hash = album['FolderName']
albumid = album['AlbumID']
torrent_removed = False
if headphones.TORRENT_DOWNLOADER == 1:
if headphones.CONFIG.TORRENT_DOWNLOADER == 1:
torrent_removed = transmission.removeTorrent(hash, True)
else:
torrent_removed = utorrent.removeTorrent(hash, True)

View File

@@ -33,9 +33,9 @@ def addTorrent(link):
if link.endswith('.torrent'):
with open(link, 'rb') as f:
metainfo = str(base64.b64encode(f.read()))
arguments = {'metainfo': metainfo, 'download-dir':headphones.DOWNLOAD_TORRENT_DIR}
arguments = {'metainfo': metainfo, 'download-dir':headphones.CONFIG.DOWNLOAD_TORRENT_DIR}
else:
arguments = {'filename': link, 'download-dir': headphones.DOWNLOAD_TORRENT_DIR}
arguments = {'filename': link, 'download-dir': headphones.CONFIG.DOWNLOAD_TORRENT_DIR}
response = torrentAction(method,arguments)
@@ -122,9 +122,9 @@ def removeTorrent(torrentid, remove_data = False):
def torrentAction(method, arguments):
host = headphones.TRANSMISSION_HOST
username = headphones.TRANSMISSION_USERNAME
password = headphones.TRANSMISSION_PASSWORD
host = headphones.CONFIG.TRANSMISSION_HOST
username = headphones.CONFIG.TRANSMISSION_USERNAME
password = headphones.CONFIG.TRANSMISSION_PASSWORD
sessionid = None
if not host.startswith('http'):

View File

@@ -28,7 +28,7 @@ class utorrentclient(object):
def __init__(self, base_url = None, username = None, password = None,):
host = headphones.UTORRENT_HOST
host = headphones.CONFIG.UTORRENT_HOST
if not host.startswith('http'):
host = 'http://' + host
@@ -39,8 +39,8 @@ class utorrentclient(object):
host = host[:-4]
self.base_url = host
self.username = headphones.UTORRENT_USERNAME
self.password = headphones.UTORRENT_PASSWORD
self.username = headphones.CONFIG.UTORRENT_USERNAME
self.password = headphones.CONFIG.UTORRENT_PASSWORD
self.opener = self._make_opener('uTorrent', self.base_url, self.username, self.password)
self.token = self._get_token()
#TODO refresh token, when necessary
@@ -157,7 +157,7 @@ class utorrentclient(object):
logger.debug('uTorrent webUI raised the following error: ' + str(err))
def labelTorrent(hash):
label = headphones.UTORRENT_LABEL
label = headphones.CONFIG.UTORRENT_LABEL
uTorrentClient = utorrentclient()
if label:
uTorrentClient.setprops(hash,'label',label)

View File

@@ -24,8 +24,8 @@ from headphones import logger, version, request
def runGit(args):
if headphones.GIT_PATH:
git_locations = ['"'+headphones.GIT_PATH+'"']
if headphones.CONFIG.GIT_PATH:
git_locations = ['"'+headphones.CONFIG.GIT_PATH+'"']
else:
git_locations = ['git']
@@ -82,16 +82,16 @@ def getVersion():
logger.error('Output doesn\'t look like a hash, not using it')
cur_commit_hash = None
if headphones.DO_NOT_OVERRIDE_GIT_BRANCH and headphones.GIT_BRANCH:
branch_name = headphones.GIT_BRANCH
if headphones.CONFIG.DO_NOT_OVERRIDE_GIT_BRANCH and headphones.CONFIG.GIT_BRANCH:
branch_name = headphones.CONFIG.GIT_BRANCH
else:
branch_name, err = runGit('rev-parse --abbrev-ref HEAD')
branch_name = branch_name
if not branch_name and headphones.GIT_BRANCH:
logger.error('Could not retrieve branch name from git. Falling back to %s' % headphones.GIT_BRANCH)
branch_name = headphones.GIT_BRANCH
if not branch_name and headphones.CONFIG.GIT_BRANCH:
logger.error('Could not retrieve branch name from git. Falling back to %s' % headphones.CONFIG.GIT_BRANCH)
branch_name = headphones.CONFIG.GIT_BRANCH
if not branch_name:
logger.error('Could not retrieve branch name from git. Defaulting to master')
branch_name = 'master'
@@ -111,7 +111,7 @@ def getVersion():
current_version = f.read().strip(' \n\r')
if current_version:
return current_version, headphones.GIT_BRANCH
return current_version, headphones.CONFIG.GIT_BRANCH
else:
return None, 'master'
@@ -120,7 +120,7 @@ def checkGithub():
# Get the latest version available from github
logger.info('Retrieving latest version information from GitHub')
url = 'https://api.github.com/repos/%s/headphones/commits/%s' % (headphones.GIT_USER, headphones.GIT_BRANCH)
url = 'https://api.github.com/repos/%s/headphones/commits/%s' % (headphones.CONFIG.GIT_USER, headphones.CONFIG.GIT_BRANCH)
version = request.request_json(url, timeout=20, validator=lambda x: type(x) == dict)
if version is None:
@@ -140,7 +140,7 @@ def checkGithub():
return headphones.LATEST_VERSION
logger.info('Comparing currently installed version with latest GitHub version')
url = 'https://api.github.com/repos/%s/headphones/compare/%s...%s' % (headphones.GIT_USER, headphones.LATEST_VERSION, headphones.CURRENT_VERSION)
url = 'https://api.github.com/repos/%s/headphones/compare/%s...%s' % (headphones.CONFIG.GIT_USER, headphones.LATEST_VERSION, headphones.CURRENT_VERSION)
commits = request.request_json(url, timeout=20, whitelist_status_code=404, validator=lambda x: type(x) == dict)
if commits is None:
@@ -166,7 +166,7 @@ def update():
logger.info('Windows .exe updating not supported yet.')
elif headphones.INSTALL_TYPE == 'git':
output, err = runGit('pull origin ' + headphones.GIT_BRANCH)
output, err = runGit('pull origin ' + headphones.CONFIG.GIT_BRANCH)
if not output:
logger.error('Couldn\'t download latest version')
@@ -181,7 +181,7 @@ def update():
logger.info('Output: ' + str(output))
else:
tar_download_url = 'https://github.com/%s/headphones/tarball/%s' % (headphones.GIT_USER, headphones.GIT_BRANCH)
tar_download_url = 'https://github.com/%s/headphones/tarball/%s' % (headphones.CONFIG.GIT_USER, headphones.CONFIG.GIT_BRANCH)
update_dir = os.path.join(headphones.PROG_DIR, 'update')
version_path = os.path.join(headphones.PROG_DIR, 'version.txt')
@@ -192,7 +192,7 @@ def update():
logger.error("Unable to retrieve new version from '%s', can't update", tar_download_url)
return
download_name = headphones.GIT_BRANCH + '-github'
download_name = headphones.CONFIG.GIT_BRANCH + '-github'
tar_download_path = os.path.join(headphones.PROG_DIR, download_name)
# Save tar to disk

View File

@@ -16,9 +16,8 @@
# NZBGet support added by CurlyMo <curlymoo1@gmail.com> as a part of XBian - XBMC on the Raspberry Pi
from headphones import logger, searcher, db, importer, mb, lastfm, librarysync, helpers, notifiers
from headphones.helpers import checked, radio,today, cleanName
from headphones.helpers import checked, radio, today, cleanName
from mako.template import Template
from mako.lookup import TemplateLookup
from mako import exceptions
@@ -28,7 +27,6 @@ import os
import sys
import json
import time
import string
import cherrypy
import threading
import headphones
@@ -42,7 +40,7 @@ except ImportError:
def serve_template(templatename, **kwargs):
interface_dir = os.path.join(str(headphones.PROG_DIR), 'data/interfaces/')
template_dir = os.path.join(str(interface_dir), headphones.INTERFACE)
template_dir = os.path.join(str(interface_dir), headphones.CONFIG.INTERFACE)
_hplookup = TemplateLookup(directories=[template_dir])
@@ -85,7 +83,7 @@ class WebInterface(object):
raise cherrypy.HTTPRedirect("home")
# Serve the extras up as a dict to make things easier for new templates (append new extras to the end)
extras_list = ["single", "ep", "compilation", "soundtrack", "live", "remix", "spokenword", "audiobook", "other", "djmix", "mixtape_street", "broadcast", "interview", "demo"]
extras_list = headphones.POSSIBLE_EXTRAS
if artist['Extras']:
artist_extras = map(int, artist['Extras'].split(','))
else:
@@ -159,9 +157,8 @@ class WebInterface(object):
extras = "1,2,3,4,5,6,7,8,9,10,11,12,13,14"
else:
temp_extras_list = []
# TODO: Put these extras as a global variable
i = 1
for extra in ["single", "ep", "compilation", "soundtrack", "live", "remix", "spokenword", "audiobook", "other", "djmix", "mixtape_street", "broadcast", "interview", "demo"]:
for extra in headphones.POSSIBLE_EXTRAS:
if extra in kwargs:
temp_extras_list.append(i)
i += 1
@@ -661,7 +658,7 @@ class WebInterface(object):
markArtists.exposed = True
def importLastFM(self, username):
headphones.LASTFM_USERNAME = username
headphones.CONFIG.LASTFM_USERNAME = username
headphones.config_write()
threading.Thread(target=lastfm.getArtists).start()
raise cherrypy.HTTPRedirect("home")
@@ -673,7 +670,7 @@ class WebInterface(object):
importLastFMTag.exposed = True
def importItunes(self, path):
headphones.PATH_TO_XML = path
headphones.CONFIG.PATH_TO_XML = path
headphones.config_write()
threading.Thread(target=importer.itunesImport, args=[path]).start()
time.sleep(10)
@@ -681,9 +678,9 @@ class WebInterface(object):
importItunes.exposed = True
def musicScan(self, path, scan=0, redirect=None, autoadd=0, libraryscan=0):
headphones.LIBRARYSCAN = libraryscan
headphones.ADD_ARTISTS = autoadd
headphones.MUSIC_DIR = path
headphones.CONFIG.LIBRARYSCAN = libraryscan
headphones.CONFIG.AUTO_ADD_ARTISTS = autoadd
headphones.CONFIG.MUSIC_DIR = path
headphones.config_write()
if scan:
try:
@@ -939,214 +936,219 @@ class WebInterface(object):
interface_list = [ name for name in os.listdir(interface_dir) if os.path.isdir(os.path.join(interface_dir, name)) ]
config = {
"http_host" : headphones.HTTP_HOST,
"http_user" : headphones.HTTP_USERNAME,
"http_port" : headphones.HTTP_PORT,
"http_pass" : headphones.HTTP_PASSWORD,
"launch_browser" : checked(headphones.LAUNCH_BROWSER),
"enable_https" : checked(headphones.ENABLE_HTTPS),
"https_cert" : headphones.HTTPS_CERT,
"https_key" : headphones.HTTPS_KEY,
"api_enabled" : checked(headphones.API_ENABLED),
"api_key" : headphones.API_KEY,
"download_scan_interval" : headphones.DOWNLOAD_SCAN_INTERVAL,
"update_db_interval" : headphones.UPDATE_DB_INTERVAL,
"mb_ignore_age" : headphones.MB_IGNORE_AGE,
"search_interval" : headphones.SEARCH_INTERVAL,
"libraryscan_interval" : headphones.LIBRARYSCAN_INTERVAL,
"sab_host" : headphones.SAB_HOST,
"sab_user" : headphones.SAB_USERNAME,
"sab_api" : headphones.SAB_APIKEY,
"sab_pass" : headphones.SAB_PASSWORD,
"sab_cat" : headphones.SAB_CATEGORY,
"nzbget_host" : headphones.NZBGET_HOST,
"nzbget_user" : headphones.NZBGET_USERNAME,
"nzbget_pass" : headphones.NZBGET_PASSWORD,
"nzbget_cat" : headphones.NZBGET_CATEGORY,
"nzbget_priority" : headphones.NZBGET_PRIORITY,
"transmission_host" : headphones.TRANSMISSION_HOST,
"transmission_user" : headphones.TRANSMISSION_USERNAME,
"transmission_pass" : headphones.TRANSMISSION_PASSWORD,
"utorrent_host" : headphones.UTORRENT_HOST,
"utorrent_user" : headphones.UTORRENT_USERNAME,
"utorrent_pass" : headphones.UTORRENT_PASSWORD,
"utorrent_label" : headphones.UTORRENT_LABEL,
"nzb_downloader_sabnzbd" : radio(headphones.NZB_DOWNLOADER, 0),
"nzb_downloader_nzbget" : radio(headphones.NZB_DOWNLOADER, 1),
"nzb_downloader_blackhole" : radio(headphones.NZB_DOWNLOADER, 2),
"torrent_downloader_blackhole" : radio(headphones.TORRENT_DOWNLOADER, 0),
"torrent_downloader_transmission" : radio(headphones.TORRENT_DOWNLOADER, 1),
"torrent_downloader_utorrent" : radio(headphones.TORRENT_DOWNLOADER, 2),
"download_dir" : headphones.DOWNLOAD_DIR,
"use_blackhole" : checked(headphones.BLACKHOLE),
"blackhole_dir" : headphones.BLACKHOLE_DIR,
"usenet_retention" : headphones.USENET_RETENTION,
"use_headphones_indexer" : checked(headphones.HEADPHONES_INDEXER),
"use_newznab" : checked(headphones.NEWZNAB),
"newznab_host" : headphones.NEWZNAB_HOST,
"newznab_api" : headphones.NEWZNAB_APIKEY,
"newznab_enabled" : checked(headphones.NEWZNAB_ENABLED),
"extra_newznabs" : headphones.EXTRA_NEWZNABS,
"use_nzbsorg" : checked(headphones.NZBSORG),
"nzbsorg_uid" : headphones.NZBSORG_UID,
"nzbsorg_hash" : headphones.NZBSORG_HASH,
"use_omgwtfnzbs" : checked(headphones.OMGWTFNZBS),
"omgwtfnzbs_uid" : headphones.OMGWTFNZBS_UID,
"omgwtfnzbs_apikey" : headphones.OMGWTFNZBS_APIKEY,
"preferred_words" : headphones.PREFERRED_WORDS,
"ignored_words" : headphones.IGNORED_WORDS,
"required_words" : headphones.REQUIRED_WORDS,
"torrentblackhole_dir" : headphones.TORRENTBLACKHOLE_DIR,
"download_torrent_dir" : headphones.DOWNLOAD_TORRENT_DIR,
"numberofseeders" : headphones.NUMBEROFSEEDERS,
"use_kat" : checked(headphones.KAT),
"kat_proxy_url" : headphones.KAT_PROXY_URL,
"kat_ratio": headphones.KAT_RATIO,
"use_piratebay" : checked(headphones.PIRATEBAY),
"piratebay_proxy_url" : headphones.PIRATEBAY_PROXY_URL,
"piratebay_ratio": headphones.PIRATEBAY_RATIO,
"use_mininova" : checked(headphones.MININOVA),
"mininova_ratio": headphones.MININOVA_RATIO,
"use_waffles" : checked(headphones.WAFFLES),
"waffles_uid" : headphones.WAFFLES_UID,
"waffles_passkey": headphones.WAFFLES_PASSKEY,
"waffles_ratio": headphones.WAFFLES_RATIO,
"use_rutracker" : checked(headphones.RUTRACKER),
"rutracker_user" : headphones.RUTRACKER_USER,
"rutracker_password": headphones.RUTRACKER_PASSWORD,
"rutracker_ratio": headphones.RUTRACKER_RATIO,
"use_whatcd" : checked(headphones.WHATCD),
"whatcd_username" : headphones.WHATCD_USERNAME,
"whatcd_password": headphones.WHATCD_PASSWORD,
"whatcd_ratio": headphones.WHATCD_RATIO,
"pref_qual_0" : radio(headphones.PREFERRED_QUALITY, 0),
"pref_qual_1" : radio(headphones.PREFERRED_QUALITY, 1),
"pref_qual_3" : radio(headphones.PREFERRED_QUALITY, 3),
"pref_qual_2" : radio(headphones.PREFERRED_QUALITY, 2),
"pref_bitrate" : headphones.PREFERRED_BITRATE,
"pref_bitrate_high" : headphones.PREFERRED_BITRATE_HIGH_BUFFER,
"pref_bitrate_low" : headphones.PREFERRED_BITRATE_LOW_BUFFER,
"pref_bitrate_allow_lossless" : checked(headphones.PREFERRED_BITRATE_ALLOW_LOSSLESS),
"detect_bitrate" : checked(headphones.DETECT_BITRATE),
"lossless_bitrate_from" : headphones.LOSSLESS_BITRATE_FROM,
"lossless_bitrate_to" : headphones.LOSSLESS_BITRATE_TO,
"freeze_db" : checked(headphones.FREEZE_DB),
"move_files" : checked(headphones.MOVE_FILES),
"rename_files" : checked(headphones.RENAME_FILES),
"correct_metadata" : checked(headphones.CORRECT_METADATA),
"cleanup_files" : checked(headphones.CLEANUP_FILES),
"keep_nfo" : checked(headphones.KEEP_NFO),
"add_album_art" : checked(headphones.ADD_ALBUM_ART),
"album_art_format" : headphones.ALBUM_ART_FORMAT,
"embed_album_art" : checked(headphones.EMBED_ALBUM_ART),
"embed_lyrics" : checked(headphones.EMBED_LYRICS),
"replace_existing_folders" : checked(headphones.REPLACE_EXISTING_FOLDERS),
"dest_dir" : headphones.DESTINATION_DIR,
"lossless_dest_dir" : headphones.LOSSLESS_DESTINATION_DIR,
"folder_format" : headphones.FOLDER_FORMAT,
"file_format" : headphones.FILE_FORMAT,
"file_underscores" : checked(headphones.FILE_UNDERSCORES),
"include_extras" : checked(headphones.INCLUDE_EXTRAS),
"autowant_upcoming" : checked(headphones.AUTOWANT_UPCOMING),
"autowant_all" : checked(headphones.AUTOWANT_ALL),
"autowant_manually_added" : checked(headphones.AUTOWANT_MANUALLY_ADDED),
"keep_torrent_files" : checked(headphones.KEEP_TORRENT_FILES),
"prefer_torrents_0" : radio(headphones.PREFER_TORRENTS, 0),
"prefer_torrents_1" : radio(headphones.PREFER_TORRENTS, 1),
"prefer_torrents_2" : radio(headphones.PREFER_TORRENTS, 2),
"magnet_links_0" : radio(headphones.MAGNET_LINKS, 0),
"magnet_links_1" : radio(headphones.MAGNET_LINKS, 1),
"magnet_links_2" : radio(headphones.MAGNET_LINKS, 2),
"log_dir" : headphones.LOG_DIR,
"cache_dir" : headphones.CACHE_DIR,
"interface_list" : interface_list,
"music_encoder": checked(headphones.MUSIC_ENCODER),
"encoder": headphones.ENCODER,
"xldprofile": headphones.XLDPROFILE,
"bitrate": int(headphones.BITRATE),
"encoderfolder": headphones.ENCODER_PATH,
"advancedencoder": headphones.ADVANCEDENCODER,
"encoderoutputformat": headphones.ENCODEROUTPUTFORMAT,
"samplingfrequency": headphones.SAMPLINGFREQUENCY,
"encodervbrcbr": headphones.ENCODERVBRCBR,
"encoderquality": headphones.ENCODERQUALITY,
"encoderlossless": checked(headphones.ENCODERLOSSLESS),
"encoder_multicore": checked(headphones.ENCODER_MULTICORE),
"encoder_multicore_count": int(headphones.ENCODER_MULTICORE_COUNT),
"delete_lossless_files": checked(headphones.DELETE_LOSSLESS_FILES),
"growl_enabled": checked(headphones.GROWL_ENABLED),
"growl_onsnatch": checked(headphones.GROWL_ONSNATCH),
"growl_host": headphones.GROWL_HOST,
"growl_password": headphones.GROWL_PASSWORD,
"prowl_enabled": checked(headphones.PROWL_ENABLED),
"prowl_onsnatch": checked(headphones.PROWL_ONSNATCH),
"prowl_keys": headphones.PROWL_KEYS,
"prowl_priority": headphones.PROWL_PRIORITY,
"xbmc_enabled": checked(headphones.XBMC_ENABLED),
"xbmc_host": headphones.XBMC_HOST,
"xbmc_username": headphones.XBMC_USERNAME,
"xbmc_password": headphones.XBMC_PASSWORD,
"xbmc_update": checked(headphones.XBMC_UPDATE),
"xbmc_notify": checked(headphones.XBMC_NOTIFY),
"lms_enabled": checked(headphones.LMS_ENABLED),
"lms_host": headphones.LMS_HOST,
"plex_enabled": checked(headphones.PLEX_ENABLED),
"plex_server_host": headphones.PLEX_SERVER_HOST,
"plex_client_host": headphones.PLEX_CLIENT_HOST,
"plex_username": headphones.PLEX_USERNAME,
"plex_password": headphones.PLEX_PASSWORD,
"plex_update": checked(headphones.PLEX_UPDATE),
"plex_notify": checked(headphones.PLEX_NOTIFY),
"nma_enabled": checked(headphones.NMA_ENABLED),
"nma_apikey": headphones.NMA_APIKEY,
"nma_priority": int(headphones.NMA_PRIORITY),
"nma_onsnatch": checked(headphones.NMA_ONSNATCH),
"pushalot_enabled": checked(headphones.PUSHALOT_ENABLED),
"pushalot_apikey": headphones.PUSHALOT_APIKEY,
"pushalot_onsnatch": checked(headphones.PUSHALOT_ONSNATCH),
"synoindex_enabled": checked(headphones.SYNOINDEX_ENABLED),
"pushover_enabled": checked(headphones.PUSHOVER_ENABLED),
"pushover_onsnatch": checked(headphones.PUSHOVER_ONSNATCH),
"pushover_keys": headphones.PUSHOVER_KEYS,
"pushover_apitoken": headphones.PUSHOVER_APITOKEN,
"pushover_priority": headphones.PUSHOVER_PRIORITY,
"pushbullet_enabled": checked(headphones.PUSHBULLET_ENABLED),
"pushbullet_onsnatch": checked(headphones.PUSHBULLET_ONSNATCH),
"pushbullet_apikey": headphones.PUSHBULLET_APIKEY,
"pushbullet_deviceid": headphones.PUSHBULLET_DEVICEID,
"subsonic_enabled": checked(headphones.SUBSONIC_ENABLED),
"subsonic_host": headphones.SUBSONIC_HOST,
"subsonic_username": headphones.SUBSONIC_USERNAME,
"subsonic_password": headphones.SUBSONIC_PASSWORD,
"twitter_enabled": checked(headphones.TWITTER_ENABLED),
"twitter_onsnatch": checked(headphones.TWITTER_ONSNATCH),
"osx_notify_enabled": checked(headphones.OSX_NOTIFY_ENABLED),
"osx_notify_onsnatch": checked(headphones.OSX_NOTIFY_ONSNATCH),
"osx_notify_app": headphones.OSX_NOTIFY_APP,
"boxcar_enabled": checked(headphones.BOXCAR_ENABLED),
"boxcar_onsnatch": checked(headphones.BOXCAR_ONSNATCH),
"boxcar_token": headphones.BOXCAR_TOKEN,
"mirror_list": headphones.MIRRORLIST,
"mirror": headphones.MIRROR,
"customhost": headphones.CUSTOMHOST,
"customport": headphones.CUSTOMPORT,
"customsleep": headphones.CUSTOMSLEEP,
"hpuser": headphones.HPUSER,
"hppass": headphones.HPPASS,
"songkick_enabled": checked(headphones.SONGKICK_ENABLED),
"songkick_apikey": headphones.SONGKICK_APIKEY,
"songkick_location": headphones.SONGKICK_LOCATION,
"songkick_filter_enabled": checked(headphones.SONGKICK_FILTER_ENABLED),
"cache_sizemb": headphones.CACHE_SIZEMB,
"file_permissions": headphones.FILE_PERMISSIONS,
"folder_permissions": headphones.FOLDER_PERMISSIONS,
"mpc_enabled": checked(headphones.MPC_ENABLED)
}
"http_host" : headphones.CONFIG.HTTP_HOST,
"http_user" : headphones.CONFIG.HTTP_USERNAME,
"http_port" : headphones.CONFIG.HTTP_PORT,
"http_pass" : headphones.CONFIG.HTTP_PASSWORD,
"launch_browser" : checked(headphones.CONFIG.LAUNCH_BROWSER),
"enable_https" : checked(headphones.CONFIG.ENABLE_HTTPS),
"https_cert" : headphones.CONFIG.HTTPS_CERT,
"https_key" : headphones.CONFIG.HTTPS_KEY,
"api_enabled" : checked(headphones.CONFIG.API_ENABLED),
"api_key" : headphones.CONFIG.API_KEY,
"download_scan_interval" : headphones.CONFIG.DOWNLOAD_SCAN_INTERVAL,
"update_db_interval" : headphones.CONFIG.UPDATE_DB_INTERVAL,
"mb_ignore_age" : headphones.CONFIG.MB_IGNORE_AGE,
"search_interval" : headphones.CONFIG.SEARCH_INTERVAL,
"libraryscan_interval" : headphones.CONFIG.LIBRARYSCAN_INTERVAL,
"sab_host" : headphones.CONFIG.SAB_HOST,
"sab_user" : headphones.CONFIG.SAB_USERNAME,
"sab_api" : headphones.CONFIG.SAB_APIKEY,
"sab_pass" : headphones.CONFIG.SAB_PASSWORD,
"sab_cat" : headphones.CONFIG.SAB_CATEGORY,
"nzbget_host" : headphones.CONFIG.NZBGET_HOST,
"nzbget_user" : headphones.CONFIG.NZBGET_USERNAME,
"nzbget_pass" : headphones.CONFIG.NZBGET_PASSWORD,
"nzbget_cat" : headphones.CONFIG.NZBGET_CATEGORY,
"nzbget_priority" : headphones.CONFIG.NZBGET_PRIORITY,
"transmission_host" : headphones.CONFIG.TRANSMISSION_HOST,
"transmission_user" : headphones.CONFIG.TRANSMISSION_USERNAME,
"transmission_pass" : headphones.CONFIG.TRANSMISSION_PASSWORD,
"utorrent_host" : headphones.CONFIG.UTORRENT_HOST,
"utorrent_user" : headphones.CONFIG.UTORRENT_USERNAME,
"utorrent_pass" : headphones.CONFIG.UTORRENT_PASSWORD,
"utorrent_label" : headphones.CONFIG.UTORRENT_LABEL,
"nzb_downloader_sabnzbd" : radio(headphones.CONFIG.NZB_DOWNLOADER, 0),
"nzb_downloader_nzbget" : radio(headphones.CONFIG.NZB_DOWNLOADER, 1),
"nzb_downloader_blackhole" : radio(headphones.CONFIG.NZB_DOWNLOADER, 2),
"torrent_downloader_blackhole" : radio(headphones.CONFIG.TORRENT_DOWNLOADER, 0),
"torrent_downloader_transmission" : radio(headphones.CONFIG.TORRENT_DOWNLOADER, 1),
"torrent_downloader_utorrent" : radio(headphones.CONFIG.TORRENT_DOWNLOADER, 2),
"download_dir" : headphones.CONFIG.DOWNLOAD_DIR,
"use_blackhole" : checked(headphones.CONFIG.BLACKHOLE),
"blackhole_dir" : headphones.CONFIG.BLACKHOLE_DIR,
"usenet_retention" : headphones.CONFIG.USENET_RETENTION,
"headphones_indexer" : checked(headphones.CONFIG.HEADPHONES_INDEXER),
"use_newznab" : checked(headphones.CONFIG.NEWZNAB),
"newznab_host" : headphones.CONFIG.NEWZNAB_HOST,
"newznab_api" : headphones.CONFIG.NEWZNAB_APIKEY,
"newznab_enabled" : checked(headphones.CONFIG.NEWZNAB_ENABLED),
"extra_newznabs" : headphones.CONFIG.get_extra_newznabs(),
"use_nzbsorg" : checked(headphones.CONFIG.NZBSORG),
"nzbsorg_uid" : headphones.CONFIG.NZBSORG_UID,
"nzbsorg_hash" : headphones.CONFIG.NZBSORG_HASH,
"use_omgwtfnzbs" : checked(headphones.CONFIG.OMGWTFNZBS),
"omgwtfnzbs_uid" : headphones.CONFIG.OMGWTFNZBS_UID,
"omgwtfnzbs_apikey" : headphones.CONFIG.OMGWTFNZBS_APIKEY,
"preferred_words" : headphones.CONFIG.PREFERRED_WORDS,
"ignored_words" : headphones.CONFIG.IGNORED_WORDS,
"required_words" : headphones.CONFIG.REQUIRED_WORDS,
"torrentblackhole_dir" : headphones.CONFIG.TORRENTBLACKHOLE_DIR,
"download_torrent_dir" : headphones.CONFIG.DOWNLOAD_TORRENT_DIR,
"numberofseeders" : headphones.CONFIG.NUMBEROFSEEDERS,
"use_kat" : checked(headphones.CONFIG.KAT),
"kat_proxy_url" : headphones.CONFIG.KAT_PROXY_URL,
"kat_ratio": headphones.CONFIG.KAT_RATIO,
"use_piratebay" : checked(headphones.CONFIG.PIRATEBAY),
"piratebay_proxy_url" : headphones.CONFIG.PIRATEBAY_PROXY_URL,
"piratebay_ratio": headphones.CONFIG.PIRATEBAY_RATIO,
"use_mininova" : checked(headphones.CONFIG.MININOVA),
"mininova_ratio": headphones.CONFIG.MININOVA_RATIO,
"use_waffles" : checked(headphones.CONFIG.WAFFLES),
"waffles_uid" : headphones.CONFIG.WAFFLES_UID,
"waffles_passkey": headphones.CONFIG.WAFFLES_PASSKEY,
"waffles_ratio": headphones.CONFIG.WAFFLES_RATIO,
"use_rutracker" : checked(headphones.CONFIG.RUTRACKER),
"rutracker_user" : headphones.CONFIG.RUTRACKER_USER,
"rutracker_password": headphones.CONFIG.RUTRACKER_PASSWORD,
"rutracker_ratio": headphones.CONFIG.RUTRACKER_RATIO,
"use_whatcd" : checked(headphones.CONFIG.WHATCD),
"whatcd_username" : headphones.CONFIG.WHATCD_USERNAME,
"whatcd_password": headphones.CONFIG.WHATCD_PASSWORD,
"whatcd_ratio": headphones.CONFIG.WHATCD_RATIO,
"pref_qual_0" : radio(headphones.CONFIG.PREFERRED_QUALITY, 0),
"pref_qual_1" : radio(headphones.CONFIG.PREFERRED_QUALITY, 1),
"pref_qual_2" : radio(headphones.CONFIG.PREFERRED_QUALITY, 2),
"pref_qual_3" : radio(headphones.CONFIG.PREFERRED_QUALITY, 3),
"pref_bitrate" : headphones.CONFIG.PREFERRED_BITRATE,
"pref_bitrate_high" : headphones.CONFIG.PREFERRED_BITRATE_HIGH_BUFFER,
"pref_bitrate_low" : headphones.CONFIG.PREFERRED_BITRATE_LOW_BUFFER,
"pref_bitrate_allow_lossless" : checked(headphones.CONFIG.PREFERRED_BITRATE_ALLOW_LOSSLESS),
"detect_bitrate" : checked(headphones.CONFIG.DETECT_BITRATE),
"lossless_bitrate_from" : headphones.CONFIG.LOSSLESS_BITRATE_FROM,
"lossless_bitrate_to" : headphones.CONFIG.LOSSLESS_BITRATE_TO,
"freeze_db" : checked(headphones.CONFIG.FREEZE_DB),
"move_files" : checked(headphones.CONFIG.MOVE_FILES),
"rename_files" : checked(headphones.CONFIG.RENAME_FILES),
"correct_metadata" : checked(headphones.CONFIG.CORRECT_METADATA),
"cleanup_files" : checked(headphones.CONFIG.CLEANUP_FILES),
"keep_nfo" : checked(headphones.CONFIG.KEEP_NFO),
"add_album_art" : checked(headphones.CONFIG.ADD_ALBUM_ART),
"album_art_format" : headphones.CONFIG.ALBUM_ART_FORMAT,
"embed_album_art" : checked(headphones.CONFIG.EMBED_ALBUM_ART),
"embed_lyrics" : checked(headphones.CONFIG.EMBED_LYRICS),
"replace_existing_folders" : checked(headphones.CONFIG.REPLACE_EXISTING_FOLDERS),
"dest_dir" : headphones.CONFIG.DESTINATION_DIR,
"lossless_dest_dir" : headphones.CONFIG.LOSSLESS_DESTINATION_DIR,
"folder_format" : headphones.CONFIG.FOLDER_FORMAT,
"file_format" : headphones.CONFIG.FILE_FORMAT,
"file_underscores" : checked(headphones.CONFIG.FILE_UNDERSCORES),
"include_extras" : checked(headphones.CONFIG.INCLUDE_EXTRAS),
"autowant_upcoming" : checked(headphones.CONFIG.AUTOWANT_UPCOMING),
"autowant_all" : checked(headphones.CONFIG.AUTOWANT_ALL),
"autowant_manually_added" : checked(headphones.CONFIG.AUTOWANT_MANUALLY_ADDED),
"keep_torrent_files" : checked(headphones.CONFIG.KEEP_TORRENT_FILES),
"prefer_torrents_0" : radio(headphones.CONFIG.PREFER_TORRENTS, 0),
"prefer_torrents_1" : radio(headphones.CONFIG.PREFER_TORRENTS, 1),
"prefer_torrents_2" : radio(headphones.CONFIG.PREFER_TORRENTS, 2),
"magnet_links_0" : radio(headphones.CONFIG.MAGNET_LINKS, 0),
"magnet_links_1" : radio(headphones.CONFIG.MAGNET_LINKS, 1),
"magnet_links_2" : radio(headphones.CONFIG.MAGNET_LINKS, 2),
"log_dir" : headphones.CONFIG.LOG_DIR,
"cache_dir" : headphones.CONFIG.CACHE_DIR,
"interface_list" : interface_list,
"music_encoder": checked(headphones.CONFIG.MUSIC_ENCODER),
"encoder": headphones.CONFIG.ENCODER,
"xldprofile": headphones.CONFIG.XLDPROFILE,
"bitrate": int(headphones.CONFIG.BITRATE),
"encoderfolder": headphones.CONFIG.ENCODER_PATH,
"advancedencoder": headphones.CONFIG.ADVANCEDENCODER,
"encoderoutputformat": headphones.CONFIG.ENCODEROUTPUTFORMAT,
"samplingfrequency": headphones.CONFIG.SAMPLINGFREQUENCY,
"encodervbrcbr": headphones.CONFIG.ENCODERVBRCBR,
"encoderquality": headphones.CONFIG.ENCODERQUALITY,
"encoderlossless": checked(headphones.CONFIG.ENCODERLOSSLESS),
"encoder_multicore": checked(headphones.CONFIG.ENCODER_MULTICORE),
"encoder_multicore_count": int(headphones.CONFIG.ENCODER_MULTICORE_COUNT),
"delete_lossless_files": checked(headphones.CONFIG.DELETE_LOSSLESS_FILES),
"growl_enabled": checked(headphones.CONFIG.GROWL_ENABLED),
"growl_onsnatch": checked(headphones.CONFIG.GROWL_ONSNATCH),
"growl_host": headphones.CONFIG.GROWL_HOST,
"growl_password": headphones.CONFIG.GROWL_PASSWORD,
"prowl_enabled": checked(headphones.CONFIG.PROWL_ENABLED),
"prowl_onsnatch": checked(headphones.CONFIG.PROWL_ONSNATCH),
"prowl_keys": headphones.CONFIG.PROWL_KEYS,
"prowl_priority": headphones.CONFIG.PROWL_PRIORITY,
"xbmc_enabled": checked(headphones.CONFIG.XBMC_ENABLED),
"xbmc_host": headphones.CONFIG.XBMC_HOST,
"xbmc_username": headphones.CONFIG.XBMC_USERNAME,
"xbmc_password": headphones.CONFIG.XBMC_PASSWORD,
"xbmc_update": checked(headphones.CONFIG.XBMC_UPDATE),
"xbmc_notify": checked(headphones.CONFIG.XBMC_NOTIFY),
"lms_enabled": checked(headphones.CONFIG.LMS_ENABLED),
"lms_host": headphones.CONFIG.LMS_HOST,
"plex_enabled": checked(headphones.CONFIG.PLEX_ENABLED),
"plex_server_host": headphones.CONFIG.PLEX_SERVER_HOST,
"plex_client_host": headphones.CONFIG.PLEX_CLIENT_HOST,
"plex_username": headphones.CONFIG.PLEX_USERNAME,
"plex_password": headphones.CONFIG.PLEX_PASSWORD,
"plex_update": checked(headphones.CONFIG.PLEX_UPDATE),
"plex_notify": checked(headphones.CONFIG.PLEX_NOTIFY),
"nma_enabled": checked(headphones.CONFIG.NMA_ENABLED),
"nma_apikey": headphones.CONFIG.NMA_APIKEY,
"nma_priority": int(headphones.CONFIG.NMA_PRIORITY),
"nma_onsnatch": checked(headphones.CONFIG.NMA_ONSNATCH),
"pushalot_enabled": checked(headphones.CONFIG.PUSHALOT_ENABLED),
"pushalot_apikey": headphones.CONFIG.PUSHALOT_APIKEY,
"pushalot_onsnatch": checked(headphones.CONFIG.PUSHALOT_ONSNATCH),
"synoindex_enabled": checked(headphones.CONFIG.SYNOINDEX_ENABLED),
"pushover_enabled": checked(headphones.CONFIG.PUSHOVER_ENABLED),
"pushover_onsnatch": checked(headphones.CONFIG.PUSHOVER_ONSNATCH),
"pushover_keys": headphones.CONFIG.PUSHOVER_KEYS,
"pushover_apitoken": headphones.CONFIG.PUSHOVER_APITOKEN,
"pushover_priority": headphones.CONFIG.PUSHOVER_PRIORITY,
"pushbullet_enabled": checked(headphones.CONFIG.PUSHBULLET_ENABLED),
"pushbullet_onsnatch": checked(headphones.CONFIG.PUSHBULLET_ONSNATCH),
"pushbullet_apikey": headphones.CONFIG.PUSHBULLET_APIKEY,
"pushbullet_deviceid": headphones.CONFIG.PUSHBULLET_DEVICEID,
"subsonic_enabled": checked(headphones.CONFIG.SUBSONIC_ENABLED),
"subsonic_host": headphones.CONFIG.SUBSONIC_HOST,
"subsonic_username": headphones.CONFIG.SUBSONIC_USERNAME,
"subsonic_password": headphones.CONFIG.SUBSONIC_PASSWORD,
"twitter_enabled": checked(headphones.CONFIG.TWITTER_ENABLED),
"twitter_onsnatch": checked(headphones.CONFIG.TWITTER_ONSNATCH),
"osx_notify_enabled": checked(headphones.CONFIG.OSX_NOTIFY_ENABLED),
"osx_notify_onsnatch": checked(headphones.CONFIG.OSX_NOTIFY_ONSNATCH),
"osx_notify_app": headphones.CONFIG.OSX_NOTIFY_APP,
"boxcar_enabled": checked(headphones.CONFIG.BOXCAR_ENABLED),
"boxcar_onsnatch": checked(headphones.CONFIG.BOXCAR_ONSNATCH),
"boxcar_token": headphones.CONFIG.BOXCAR_TOKEN,
"mirror_list": headphones.MIRRORLIST,
"mirror": headphones.CONFIG.MIRROR,
"customhost": headphones.CONFIG.CUSTOMHOST,
"customport": headphones.CONFIG.CUSTOMPORT,
"customsleep": headphones.CONFIG.CUSTOMSLEEP,
"hpuser": headphones.CONFIG.HPUSER,
"hppass": headphones.CONFIG.HPPASS,
"songkick_enabled": checked(headphones.CONFIG.SONGKICK_ENABLED),
"songkick_apikey": headphones.CONFIG.SONGKICK_APIKEY,
"songkick_location": headphones.CONFIG.SONGKICK_LOCATION,
"songkick_filter_enabled": checked(headphones.CONFIG.SONGKICK_FILTER_ENABLED),
"cache_sizemb": headphones.CONFIG.CACHE_SIZEMB,
"file_permissions": headphones.CONFIG.FILE_PERMISSIONS,
"folder_permissions": headphones.CONFIG.FOLDER_PERMISSIONS,
"mpc_enabled": checked(headphones.CONFIG.MPC_ENABLED)
}
# Need to convert EXTRAS to a dictionary we can pass to the config: it'll come in as a string like 2,5,6,8 (append new extras to the end)
extras_list = ["single", "ep", "compilation", "soundtrack", "live", "remix", "spokenword", "audiobook", "other", "djmix", "mixtape_street", "broadcast", "interview", "demo"]
if headphones.EXTRAS:
extras = map(int, headphones.EXTRAS.split(','))
extra_munges = {
"dj-mix": "dj_mix",
"mixtape/street": "mixtape_street"
}
extras_list = [extra_munges.get(x, x) for x in headphones.POSSIBLE_EXTRAS]
if headphones.CONFIG.EXTRAS:
extras = map(int, headphones.CONFIG.EXTRAS.split(','))
else:
extras = []
@@ -1165,237 +1167,31 @@ class WebInterface(object):
return serve_template(templatename="config.html", title="Settings", config=config)
config.exposed = True
def configUpdate(self, http_host='0.0.0.0', http_username=None, http_port=8181, http_password=None, launch_browser=0, api_enabled=0, api_key=None,
download_scan_interval=None, update_db_interval=None, mb_ignore_age=None, search_interval=None, libraryscan_interval=None, sab_host=None, sab_username=None, sab_apikey=None, sab_password=None,
sab_category=None, nzbget_host=None, nzbget_username=None, nzbget_password=None, nzbget_category=None, nzbget_priority=0, transmission_host=None, transmission_username=None, transmission_password=None,
utorrent_host=None, utorrent_username=None, utorrent_password=None, utorrent_label=None,nzb_downloader=0, torrent_downloader=0, download_dir=None, blackhole_dir=None, usenet_retention=None,
use_headphones_indexer=0, newznab=0, newznab_host=None, newznab_apikey=None, newznab_enabled=0, nzbsorg=0, nzbsorg_uid=None, nzbsorg_hash=None, omgwtfnzbs=0, omgwtfnzbs_uid=None, omgwtfnzbs_apikey=None,
preferred_words=None, required_words=None, ignored_words=None, preferred_quality=0, preferred_bitrate=None, detect_bitrate=0, freeze_db=0, move_files=0, torrentblackhole_dir=None, download_torrent_dir=None,
numberofseeders=None, use_piratebay=0, piratebay_proxy_url=None, piratebay_ratio=None, use_kat=0, kat_proxy_url=None, kat_ratio=None, use_mininova=0, mininova_ratio=None, waffles=0, waffles_uid=None, waffles_passkey=None, waffles_ratio=None, whatcd=0, whatcd_username=None, whatcd_password=None, whatcd_ratio=None,
rutracker=0, rutracker_user=None, rutracker_password=None, rutracker_ratio=None, rename_files=0, correct_metadata=0, cleanup_files=0, keep_nfo=0, add_album_art=0, album_art_format=None, embed_album_art=0, embed_lyrics=0, replace_existing_folders=False,
destination_dir=None, lossless_destination_dir=None, folder_format=None, file_format=None, file_underscores=0, include_extras=0, single=0, ep=0, compilation=0, soundtrack=0, live=0, remix=0, spokenword=0, audiobook=0, other=0, djmix=0, mixtape_street=0, broadcast=0, interview=0, demo=0,
autowant_upcoming=False, autowant_all=False, autowant_manually_added=False, keep_torrent_files=False, prefer_torrents=0, magnet_links=0, interface=None, log_dir=None, cache_dir=None, music_encoder=0, encoder=None, xldprofile=None,
bitrate=None, samplingfrequency=None, encoderfolder=None, advancedencoder=None, encoderoutputformat=None, encodervbrcbr=None, encoderquality=None, encoderlossless=0, subsonic_enabled=False, subsonic_host=None, subsonic_username=None, subsonic_password=None,
delete_lossless_files=0, growl_enabled=0, growl_onsnatch=0, growl_host=None, growl_password=None, prowl_enabled=0, prowl_onsnatch=0, prowl_keys=None, prowl_priority=0, xbmc_enabled=0, xbmc_host=None, xbmc_username=None, xbmc_password=None,
xbmc_update=0, xbmc_notify=0, nma_enabled=False, nma_apikey=None, nma_priority=0, nma_onsnatch=0, pushalot_enabled=False, pushalot_apikey=None, pushalot_onsnatch=0, synoindex_enabled=False, lms_enabled=0, lms_host=None,
pushover_enabled=0, pushover_onsnatch=0, pushover_keys=None, pushover_priority=0, pushover_apitoken=None, pushbullet_enabled=0, pushbullet_onsnatch=0, pushbullet_apikey=None, pushbullet_deviceid=None, twitter_enabled=0, twitter_onsnatch=0,
osx_notify_enabled=0, osx_notify_onsnatch=0, osx_notify_app=None, boxcar_enabled=0, boxcar_onsnatch=0, boxcar_token=None, mirror=None, customhost=None, customport=None, customsleep=None, hpuser=None, hppass=None,
preferred_bitrate_high_buffer=None, preferred_bitrate_low_buffer=None, preferred_bitrate_allow_lossless=0, lossless_bitrate_from=None, lossless_bitrate_to=None, cache_sizemb=None, enable_https=0, https_cert=None, https_key=None,
file_permissions=None, folder_permissions=None, plex_enabled=0, plex_server_host=None, plex_client_host=None, plex_username=None, plex_password=None, plex_update=0, plex_notify=0,
songkick_enabled=0, songkick_apikey=None, songkick_location=None, songkick_filter_enabled=0, encoder_multicore=False, encoder_multicore_count=0, mpc_enabled=False, **kwargs ):
headphones.HTTP_HOST = http_host
headphones.HTTP_PORT = http_port
headphones.HTTP_USERNAME = http_username
headphones.HTTP_PASSWORD = http_password
headphones.LAUNCH_BROWSER = launch_browser
headphones.ENABLE_HTTPS = enable_https
headphones.HTTPS_CERT = https_cert
headphones.HTTPS_KEY = https_key
headphones.API_ENABLED = api_enabled
headphones.API_KEY = api_key
headphones.DOWNLOAD_SCAN_INTERVAL = download_scan_interval
headphones.UPDATE_DB_INTERVAL = update_db_interval
headphones.MB_IGNORE_AGE = mb_ignore_age
headphones.SEARCH_INTERVAL = search_interval
headphones.LIBRARYSCAN_INTERVAL = libraryscan_interval
headphones.SAB_HOST = sab_host
headphones.SAB_USERNAME = sab_username
headphones.SAB_PASSWORD = sab_password
headphones.SAB_APIKEY = sab_apikey
headphones.SAB_CATEGORY = sab_category
headphones.NZBGET_HOST = nzbget_host
headphones.NZBGET_USERNAME = nzbget_username
headphones.NZBGET_PASSWORD = nzbget_password
headphones.NZBGET_CATEGORY = nzbget_category
headphones.NZBGET_PRIORITY = int(nzbget_priority)
headphones.TRANSMISSION_HOST = transmission_host
headphones.TRANSMISSION_USERNAME = transmission_username
headphones.TRANSMISSION_PASSWORD = transmission_password
headphones.UTORRENT_HOST = utorrent_host
headphones.UTORRENT_USERNAME = utorrent_username
headphones.UTORRENT_PASSWORD = utorrent_password
headphones.UTORRENT_LABEL = utorrent_label
headphones.NZB_DOWNLOADER = int(nzb_downloader)
headphones.TORRENT_DOWNLOADER = int(torrent_downloader)
headphones.DOWNLOAD_DIR = download_dir
headphones.BLACKHOLE_DIR = blackhole_dir
headphones.USENET_RETENTION = usenet_retention
headphones.HEADPHONES_INDEXER = use_headphones_indexer
headphones.NEWZNAB = newznab
headphones.NEWZNAB_HOST = newznab_host
headphones.NEWZNAB_APIKEY = newznab_apikey
headphones.NEWZNAB_ENABLED = newznab_enabled
headphones.NZBSORG = nzbsorg
headphones.NZBSORG_UID = nzbsorg_uid
headphones.NZBSORG_HASH = nzbsorg_hash
headphones.OMGWTFNZBS = omgwtfnzbs
headphones.OMGWTFNZBS_UID = omgwtfnzbs_uid
headphones.OMGWTFNZBS_APIKEY = omgwtfnzbs_apikey
headphones.PREFERRED_WORDS = preferred_words
headphones.IGNORED_WORDS = ignored_words
headphones.REQUIRED_WORDS = required_words
headphones.TORRENTBLACKHOLE_DIR = torrentblackhole_dir
headphones.NUMBEROFSEEDERS = numberofseeders
headphones.DOWNLOAD_TORRENT_DIR = download_torrent_dir
headphones.KAT = use_kat
headphones.KAT_PROXY_URL = kat_proxy_url
headphones.KAT_RATIO = kat_ratio
headphones.PIRATEBAY = use_piratebay
headphones.PIRATEBAY_PROXY_URL = piratebay_proxy_url
headphones.PIRATEBAY_RATIO = piratebay_ratio
headphones.MININOVA = use_mininova
headphones.MININOVA_RATIO = mininova_ratio
headphones.WAFFLES = waffles
headphones.WAFFLES_UID = waffles_uid
headphones.WAFFLES_PASSKEY = waffles_passkey
headphones.WAFFLES_RATIO = waffles_ratio
headphones.RUTRACKER = rutracker
headphones.RUTRACKER_USER = rutracker_user
headphones.RUTRACKER_PASSWORD = rutracker_password
headphones.RUTRACKER_RATIO = rutracker_ratio
headphones.WHATCD = whatcd
headphones.WHATCD_USERNAME = whatcd_username
headphones.WHATCD_PASSWORD = whatcd_password
headphones.WHATCD_RATIO = whatcd_ratio
headphones.PREFERRED_QUALITY = int(preferred_quality)
headphones.PREFERRED_BITRATE = preferred_bitrate
headphones.PREFERRED_BITRATE_HIGH_BUFFER = preferred_bitrate_high_buffer
headphones.PREFERRED_BITRATE_LOW_BUFFER = preferred_bitrate_low_buffer
headphones.PREFERRED_BITRATE_ALLOW_LOSSLESS = preferred_bitrate_allow_lossless
headphones.DETECT_BITRATE = detect_bitrate
headphones.LOSSLESS_BITRATE_FROM = lossless_bitrate_from
headphones.LOSSLESS_BITRATE_TO = lossless_bitrate_to
headphones.FREEZE_DB = freeze_db
headphones.MOVE_FILES = move_files
headphones.CORRECT_METADATA = correct_metadata
headphones.RENAME_FILES = rename_files
headphones.CLEANUP_FILES = cleanup_files
headphones.KEEP_NFO = keep_nfo
headphones.ADD_ALBUM_ART = add_album_art
headphones.ALBUM_ART_FORMAT = album_art_format
headphones.EMBED_ALBUM_ART = embed_album_art
headphones.EMBED_LYRICS = embed_lyrics
headphones.REPLACE_EXISTING_FOLDERS = replace_existing_folders
headphones.DESTINATION_DIR = destination_dir
headphones.LOSSLESS_DESTINATION_DIR = lossless_destination_dir
headphones.FOLDER_FORMAT = folder_format
headphones.FILE_FORMAT = file_format
headphones.FILE_UNDERSCORES = file_underscores
headphones.INCLUDE_EXTRAS = include_extras
headphones.AUTOWANT_UPCOMING = autowant_upcoming
headphones.AUTOWANT_ALL = autowant_all
headphones.AUTOWANT_MANUALLY_ADDED = autowant_manually_added
headphones.KEEP_TORRENT_FILES = keep_torrent_files
headphones.PREFER_TORRENTS = int(prefer_torrents)
headphones.MAGNET_LINKS = int(magnet_links)
headphones.INTERFACE = interface
headphones.LOG_DIR = log_dir
headphones.CACHE_DIR = cache_dir
headphones.MUSIC_ENCODER = music_encoder
headphones.ENCODER = encoder
headphones.XLDPROFILE = xldprofile
headphones.BITRATE = int(bitrate)
headphones.SAMPLINGFREQUENCY = int(samplingfrequency)
headphones.ENCODER_PATH = encoderfolder
headphones.ADVANCEDENCODER = advancedencoder
headphones.ENCODEROUTPUTFORMAT = encoderoutputformat
headphones.ENCODERVBRCBR = encodervbrcbr
headphones.ENCODERQUALITY = int(encoderquality)
headphones.ENCODERLOSSLESS = int(encoderlossless)
headphones.ENCODER_MULTICORE = encoder_multicore
headphones.ENCODER_MULTICORE_COUNT = max(0, int(encoder_multicore_count))
headphones.DELETE_LOSSLESS_FILES = int(delete_lossless_files)
headphones.GROWL_ENABLED = growl_enabled
headphones.GROWL_ONSNATCH = growl_onsnatch
headphones.GROWL_HOST = growl_host
headphones.GROWL_PASSWORD = growl_password
headphones.PROWL_ENABLED = prowl_enabled
headphones.PROWL_ONSNATCH = prowl_onsnatch
headphones.PROWL_KEYS = prowl_keys
headphones.PROWL_PRIORITY = prowl_priority
headphones.XBMC_ENABLED = xbmc_enabled
headphones.XBMC_HOST = xbmc_host
headphones.XBMC_USERNAME = xbmc_username
headphones.XBMC_PASSWORD = xbmc_password
headphones.XBMC_UPDATE = xbmc_update
headphones.XBMC_NOTIFY = xbmc_notify
headphones.LMS_ENABLED = lms_enabled
headphones.LMS_HOST = lms_host
headphones.PLEX_ENABLED = plex_enabled
headphones.PLEX_SERVER_HOST = plex_server_host
headphones.PLEX_CLIENT_HOST = plex_client_host
headphones.PLEX_USERNAME = plex_username
headphones.PLEX_PASSWORD = plex_password
headphones.PLEX_UPDATE = plex_update
headphones.PLEX_NOTIFY = plex_notify
headphones.NMA_ENABLED = nma_enabled
headphones.NMA_APIKEY = nma_apikey
headphones.NMA_PRIORITY = nma_priority
headphones.NMA_ONSNATCH = nma_onsnatch
headphones.PUSHALOT_ENABLED = pushalot_enabled
headphones.PUSHALOT_APIKEY = pushalot_apikey
headphones.PUSHALOT_ONSNATCH = pushalot_onsnatch
headphones.SYNOINDEX_ENABLED = synoindex_enabled
headphones.PUSHOVER_ENABLED = pushover_enabled
headphones.PUSHOVER_ONSNATCH = pushover_onsnatch
headphones.PUSHOVER_KEYS = pushover_keys
headphones.PUSHOVER_PRIORITY = pushover_priority
headphones.PUSHOVER_APITOKEN = pushover_apitoken
headphones.PUSHBULLET_ENABLED = pushbullet_enabled
headphones.PUSHBULLET_ONSNATCH = pushbullet_onsnatch
headphones.PUSHBULLET_APIKEY = pushbullet_apikey
headphones.PUSHBULLET_DEVICEID = pushbullet_deviceid
headphones.SUBSONIC_ENABLED = subsonic_enabled
headphones.SUBSONIC_HOST = subsonic_host
headphones.SUBSONIC_USERNAME = subsonic_username
headphones.SUBSONIC_PASSWORD = subsonic_password
headphones.SONGKICK_ENABLED = songkick_enabled
headphones.SONGKICK_APIKEY = songkick_apikey
headphones.SONGKICK_LOCATION = songkick_location
headphones.SONGKICK_FILTER_ENABLED = songkick_filter_enabled
headphones.TWITTER_ENABLED = twitter_enabled
headphones.TWITTER_ONSNATCH = twitter_onsnatch
headphones.OSX_NOTIFY_ENABLED = osx_notify_enabled
headphones.OSX_NOTIFY_ONSNATCH = osx_notify_onsnatch
headphones.OSX_NOTIFY_APP = osx_notify_app
headphones.BOXCAR_ENABLED = boxcar_enabled
headphones.BOXCAR_ONSNATCH = boxcar_onsnatch
headphones.BOXCAR_TOKEN = boxcar_token
headphones.MPC_ENABLED = mpc_enabled
headphones.MIRROR = mirror
headphones.CUSTOMHOST = customhost
headphones.CUSTOMPORT = customport
headphones.CUSTOMSLEEP = customsleep
headphones.HPUSER = hpuser
headphones.HPPASS = hppass
headphones.CACHE_SIZEMB = int(cache_sizemb)
headphones.FILE_PERMISSIONS = file_permissions
headphones.FOLDER_PERMISSIONS = folder_permissions
def configUpdate(self, **kwargs):
# Handle the variable config options. Note - keys with False values aren't getting passed
headphones.EXTRA_NEWZNABS = []
headphones.CONFIG.clear_extra_newznabs()
for kwarg in kwargs:
if kwarg.startswith('newznab_host'):
newznab_number = kwarg[12:]
newznab_host = kwargs['newznab_host' + newznab_number]
newznab_api = kwargs['newznab_api' + newznab_number]
try:
newznab_enabled = int(kwargs['newznab_enabled' + newznab_number])
except KeyError:
newznab_enabled = 0
headphones.EXTRA_NEWZNABS.append((newznab_host, newznab_api, newznab_enabled))
if len(newznab_number):
newznab_host = kwargs.get('newznab_host' + newznab_number)
newznab_api = kwargs.get('newznab_api' + newznab_number)
try:
newznab_enabled = int(kwargs.get('newznab_enabled' + newznab_number))
except KeyError:
newznab_enabled = 0
headphones.CONFIG.add_extra_newznab((newznab_host, newznab_api, newznab_enabled))
# Convert the extras to list then string. Coming in as 0 or 1 (append new extras to the end)
temp_extras_list = []
extras_list = [single, ep, compilation, soundtrack, live, remix, spokenword, audiobook, other, djmix, mixtape_street, broadcast, interview, demo]
extra_munges = {
"dj-mix": "dj_mix",
"mixtape/street": "mixtape_street"
}
expected_extras = [extra_munges.get(x, x) for x in headphones.POSSIBLE_EXTRAS]
extras_list = [kwargs.get(x, 0) for x in expected_extras]
i = 1
for extra in extras_list:
@@ -1403,15 +1199,24 @@ class WebInterface(object):
temp_extras_list.append(i)
i+=1
headphones.EXTRAS = ','.join(str(n) for n in temp_extras_list)
for extra in expected_extras:
temp = '%s_temp' % extra
if temp in kwargs:
del kwargs[temp]
if extra in kwargs:
del kwargs[extra]
headphones.CONFIG.EXTRAS = ','.join(str(n) for n in temp_extras_list)
headphones.CONFIG.process_kwargs(kwargs)
# Sanity checking
if headphones.SEARCH_INTERVAL < 360:
if headphones.CONFIG.SEARCH_INTERVAL < 360:
logger.info("Search interval too low. Resetting to 6 hour minimum")
headphones.SEARCH_INTERVAL = 360
headphones.CONFIG.SEARCH_INTERVAL = 360
# Write the config
headphones.config_write()
headphones.CONFIG.write()
#reconfigure musicbrainz database connection with the new values
mb.startmb()
@@ -1442,7 +1247,6 @@ class WebInterface(object):
myDB = db.DBConnection()
cloudlist = myDB.select('SELECT * from lastfmcloud')
return serve_template(templatename="extras.html", title="Extras", cloudlist=cloudlist)
return page
extras.exposed = True
def addReleaseById(self, rid, rgid=None):
@@ -1582,7 +1386,7 @@ class Artwork(object):
cherrypy.response.headers['Cache-Control'] = 'no-cache'
else:
relpath = relpath.replace('cache/','',1)
path = os.path.join(headphones.CACHE_DIR,relpath)
path = os.path.join(headphones.CONFIG.CACHE_DIR,relpath)
fileext = os.path.splitext(relpath)[1][1::]
cherrypy.response.headers['Content-type'] = 'image/' + fileext
cherrypy.response.headers['Cache-Control'] = 'max-age=31556926'
@@ -1615,7 +1419,7 @@ class Artwork(object):
cherrypy.response.headers['Cache-Control'] = 'no-cache'
else:
relpath = relpath.replace('cache/','',1)
path = os.path.join(headphones.CACHE_DIR,relpath)
path = os.path.join(headphones.CONFIG.CACHE_DIR,relpath)
fileext = os.path.splitext(relpath)[1][1::]
cherrypy.response.headers['Content-type'] = 'image/' + fileext
cherrypy.response.headers['Cache-Control'] = 'max-age=31556926'

View File

@@ -36,12 +36,12 @@ def initialize(options=None):
if not (https_cert and os.path.exists(https_cert)) or not (https_key and os.path.exists(https_key)):
if not create_https_certificates(https_cert, https_key):
logger.warn(u"Unable to create cert/key files, disabling HTTPS")
headphones.ENABLE_HTTPS = False
headphones.CONFIG.ENABLE_HTTPS = False
enable_https = False
if not (os.path.exists(https_cert) and os.path.exists(https_key)):
logger.warn(u"Disabled HTTPS because of missing CERT and KEY files")
headphones.ENABLE_HTTPS = False
headphones.CONFIG.ENABLE_HTTPS = False
enable_https = False
options_dict = {
@@ -94,7 +94,7 @@ def initialize(options=None):
},
'/cache':{
'tools.staticdir.on': True,
'tools.staticdir.dir': headphones.CACHE_DIR
'tools.staticdir.dir': headphones.CONFIG.CACHE_DIR
}
}