Compare commits

..
24 Commits
Author SHA1 Message Date
rembo10 833b90ccff Release v0.5.5 2015-05-04 19:43:37 -07:00
rembo10 c27a381286 Update CHANGELOG.md 2015-05-04 19:37:23 -07:00
rembo10 ad29b43836 Needed to capitalize beets recommendation.none 2015-03-20 17:29:43 -07:00
rembo10 5cd9c51410 Move 'checking folder' message to debug level. Show it if forced 2015-03-15 18:28:38 -07:00
rembo10 6476d42371 Return some json when picking a specific download so we can close the dialog box on success/failure 2015-03-14 00:27:59 -07:00
rembo10 a48d9006ad Fix to get size sorting working again when choosing a specific download 2015-03-14 00:04:14 -07:00
rembo10 c5c2057859 Return everything if they're looking for a specific download 2015-03-13 23:43:29 -07:00
rembo10 1889ab4825 Fix for min/max sizes with target bitrate (wrong calculation) 2015-03-12 14:14:06 -07:00
rembo10 0c81560f2c uggh, indentation 2015-03-09 17:05:28 -07:00
rembo10 26005d6584 expose getArtistjson so we can automatically update albums when updating an artist 2015-03-09 17:03:25 -07:00
rembo10 b0b0bcbdb7 Fix for piratebay returning size as 0 bytes for all results 2015-03-06 10:02:04 -08:00
Bas Stottelaar 546099fa2d Updated Changelog.md 2015-02-19 20:15:08 +01:00
Bas Stottelaar c53fde6dca Merge remote-tracking branch 'origin/master' into develop
* origin/master:
  Release v0.5.4
  Added API call getSnatched
  Potential fix for #2055
2015-02-19 20:12:49 +01:00
Jonny c9aeefc67a Update postprocessor.py
Changed ID3 logging to debug
2015-02-19 19:24:35 +01:00
Jonny 37594d3384 Update postprocessor.py
Set-up of beets config to match headphones config of ID3 tag version before writing metadata
2015-02-19 19:24:25 +01:00
Jonny 00dc5d8c38 Update config.py
Added config option for ID3 tag version select
2015-02-19 19:24:18 +01:00
Jonny ff8f6b1d00 Update webserve.py
Added config option for ID3 tag version select
Conflicts:
	headphones/webserve.py
2015-02-19 19:24:09 +01:00
Jonny aa60ba1fb1 Update config.html
Added option to select using ID3v2.3
2015-02-19 19:22:42 +01:00
Bas Stottelaar 3b8341f249 Merge pull request #2125 from drzoidberg33/develop
Allow authentication on custom MusicBrainz servers
2015-02-19 14:06:29 +01:00
Tim a68bcb6ee1 Fix condition that checks if we should disable custom MusicBrainz server authentication. 2015-02-19 11:48:10 +02:00
Tim 24a52a294c Allow authentication on custom MusicBrainz servers using Basic HTTP Authentication. 2015-02-19 00:54:10 +02:00
Bas Stottelaar 03ea67b20b Fix for #2119 2015-02-15 14:02:49 +01:00
Ade 4f20003f9a Email part 2
small fix up
2015-02-06 21:37:41 +13:00
Ade a92d13652d Email notifications
#1045
2015-02-06 20:28:57 +13:00
11 changed files with 246 additions and 26 deletions
+20 -1
View File
@@ -1,5 +1,24 @@
# Changelog # Changelog
## v0.5.5
Released 04 May 2015
Highlights:
* Added: force ID3v2.3 during post processing (#2121)
* Added: MusicBrainz authentication (#2125)
* Added: Email notifications (addresses #1045)
* Fixed: Kickass url updated to kickass.to (#2119)
* Fixed: Piratebay returning 0 bytes for all files
* Fixed: Albums stopped automatically refreshing when adding an artist
* Fixed: Min/max sizes for target bitrate
* Fixed: Don't filter any results if looking for a specific download
* Fixed: Sort by size in the specific download table
* Fixed: Deal with beets recommendation.none correctly
* Improved: Close dialog window automatically when choosing a specific download
* Improved: Move some repetitive log messages to debug level
The full list of commits can be found [here](https://github.com/rembo10/headphones/compare/v0.5.4...v0.5.5).
## v0.5.4 ## v0.5.4
Released 05 February 2015 Released 05 February 2015
@@ -155,4 +174,4 @@ The full list of commits can be found [here](https://github.com/rembo10/headphon
## v0.1 ## v0.1
Released 05 August 2013 Released 05 August 2013
The full list of commits can be found [here](https://github.com/rembo10/headphones/compare/2156e1341405d07c5bcfbe994f6b354b32d94cda...v0.1). The full list of commits can be found [here](https://github.com/rembo10/headphones/compare/2156e1341405d07c5bcfbe994f6b354b32d94cda...v0.1).
+15
View File
@@ -337,6 +337,21 @@
}); });
} }
jQuery.extend( jQuery.fn.dataTableExt.oSort, {
"title-numeric-pre": function ( a ) {
var x = a.match(/title="*(-?[0-9\.]+)/)[1];
return parseFloat( x );
},
"title-numeric-asc": function ( a, b ) {
return ((a < b) ? -1 : ((a > b) ? 1 : 0));
},
"title-numeric-desc": function ( a, b ) {
return ((a < b) ? 1 : ((a > b) ? -1 : 0));
}
} );
$(document).ready(function() { $(document).ready(function() {
getAlbumInfo(); getAlbumInfo();
initThisPage(); initThisPage();
+88
View File
@@ -786,6 +786,10 @@
Embed lyrics Embed lyrics
<input type="checkbox" name="embed_lyrics" value="1" ${config['embed_lyrics']}> <input type="checkbox" name="embed_lyrics" value="1" ${config['embed_lyrics']}>
</label> </label>
<label title="Use ID3v2.3 instead of ID3v2.4">
Tag using ID3v2.3
<input type="checkbox" name="idtag" value="1" ${config['idtag']}>
</label>
</div> </div>
<div class="row"> <div class="row">
<label> <label>
@@ -1104,6 +1108,39 @@
</div> </div>
</fieldset> </fieldset>
<fieldset>
<h3>Email</h3>
<div class="row checkbox">
<input type="checkbox" name="email_enabled" id="email" value="1" ${config['email_enabled']} /><label>Enable Email Notifications</label>
</div>
<div id="email_options">
<div class="row">
<label>From</label><input type="text" name="email_from" value="${config['email_from']}" size="254">
</div>
<div class="row">
<label>To</label><input type="text" name="email_to" value="${config['email_to']}" size="254">
</div>
<div class="row">
<label>SMTP Server</label><input type="text" name="email_smtp_server" value="${config['email_smtp_server']}" size="254">
</div>
<div class="row">
<label>SMTP User</label><input type="text" name="email_smtp_user" value="${config['email_smtp_user']}" size="254">
</div>
<div class="row">
<label>SMTP Password</label><input type="password" name="email_smtp_password" value="${config['email_smtp_password']}" size="50">
</div>
<div class="row checkbox">
<input type="text" class="override-float" name="email_smtp_port" value="${config['email_smtp_port']}" size="4"><label>SMTP Port</label>
</div>
<div class="row checkbox">
<input type="checkbox" name="email_tls" value="1" ${config['email_tls']} /><label>TLS</label>
</div>
<div class="row checkbox">
<input type="checkbox" name="email_onsnatch" value="1" ${config['email_onsnatch']} /><label>Notify on snatch?</label>
</div>
</div>
</fieldset>
<fieldset> <fieldset>
</td> </td>
</tr> </tr>
@@ -1416,6 +1453,17 @@
<div class="row"> <div class="row">
<label>Port</label><input type="text" name="customport" value="${config['customport']}" size="8"> <label>Port</label><input type="text" name="customport" value="${config['customport']}" size="8">
</div> </div>
<div class="row checkbox">
<input type="checkbox" name="customauth" id="customauth" value="1" ${config['customauth']} /><label>Requires Authentication</label>
</div>
<div id="customauth_options">
<div class="row">
<label>Username</label><input type="text" class="customuser" name="customuser" value="${config['customuser']}" size="20">
</div>
<div class="row">
<label>Password</label><input type="password" class="custompass" name="custompass" value="${config['custompass']}" size="15"><br>
</div>
</div>
<div class="row"> <div class="row">
<label>Sleep Interval</label><input type="text" name="customsleep" value="${config['customsleep']}" size="4"> <label>Sleep Interval</label><input type="text" name="customsleep" value="${config['customsleep']}" size="4">
</div> </div>
@@ -1526,6 +1574,25 @@
$('#api_key').val(data); $('#api_key').val(data);
}); });
}); });
if ($("#customauth").is(":checked"))
{
$("#customauth_options").show();
}
else
{
$("#customauth_options").hide();
}
$("#customauth").click(function(){
if ($("#customauth").is(":checked"))
{
$("#customauth_options").slideDown();
}
else
{
$("#customauth_options").slideUp();
}
});
if ($("#enable_https").is(":checked")) if ($("#enable_https").is(":checked"))
{ {
$("#https_options").show(); $("#https_options").show();
@@ -1866,6 +1933,26 @@
} }
}); });
if ($("#email").is(":checked"))
{
$("#email_options").show();
}
else
{
$("#email_options").hide();
}
$("#email").click(function(){
if ($("#email").is(":checked"))
{
$("#email_options").slideDown();
}
else
{
$("#email_options").slideUp();
}
});
if ($("#songkick").is(":checked")) if ($("#songkick").is(":checked"))
{ {
$("#songkickoptions").show(); $("#songkickoptions").show();
@@ -2074,6 +2161,7 @@
initConfigCheckbox("#use_whatcd"); initConfigCheckbox("#use_whatcd");
initConfigCheckbox("#api_enabled"); initConfigCheckbox("#api_enabled");
initConfigCheckbox("#enable_https"); initConfigCheckbox("#enable_https");
initConfigCheckbox("#customauth");
$('#twitterStep1').click(function () { $('#twitterStep1').click(function () {
+13
View File
@@ -44,9 +44,12 @@ _CONFIG_DEFINITIONS = {
'CUE_SPLIT': (int, 'General', 1), 'CUE_SPLIT': (int, 'General', 1),
'CUE_SPLIT_FLAC_PATH': (str, 'General', ''), 'CUE_SPLIT_FLAC_PATH': (str, 'General', ''),
'CUE_SPLIT_SHNTOOL_PATH': (str, 'General', ''), 'CUE_SPLIT_SHNTOOL_PATH': (str, 'General', ''),
'CUSTOMAUTH': (int, 'General', 0),
'CUSTOMHOST': (str, 'General', 'localhost'), 'CUSTOMHOST': (str, 'General', 'localhost'),
'CUSTOMPASS': (str, 'General', ''),
'CUSTOMPORT': (int, 'General', 5000), 'CUSTOMPORT': (int, 'General', 5000),
'CUSTOMSLEEP': (int, 'General', 1), 'CUSTOMSLEEP': (int, 'General', 1),
'CUSTOMUSER': (str, 'General', ''),
'DELETE_LOSSLESS_FILES': (int, 'General', 1), 'DELETE_LOSSLESS_FILES': (int, 'General', 1),
'DESTINATION_DIR': (str, 'General', ''), 'DESTINATION_DIR': (str, 'General', ''),
'DETECT_BITRATE': (int, 'General', 0), 'DETECT_BITRATE': (int, 'General', 0),
@@ -54,6 +57,15 @@ _CONFIG_DEFINITIONS = {
'DOWNLOAD_SCAN_INTERVAL': (int, 'General', 5), 'DOWNLOAD_SCAN_INTERVAL': (int, 'General', 5),
'DOWNLOAD_TORRENT_DIR': (str, 'General', ''), 'DOWNLOAD_TORRENT_DIR': (str, 'General', ''),
'DO_NOT_OVERRIDE_GIT_BRANCH': (int, 'General', 0), 'DO_NOT_OVERRIDE_GIT_BRANCH': (int, 'General', 0),
'EMAIL_ENABLED': (int, 'Email', 0),
'EMAIL_FROM': (str, 'Email', ''),
'EMAIL_TO': (str, 'Email', ''),
'EMAIL_SMTP_SERVER': (str, 'Email', ''),
'EMAIL_SMTP_USER': (str, 'Email', ''),
'EMAIL_SMTP_PASSWORD': (str, 'Email', ''),
'EMAIL_SMTP_PORT': (int, 'Email', 25),
'EMAIL_TLS': (int, 'Email', 0),
'EMAIL_ONSNATCH': (int, 'Email', 0),
'EMBED_ALBUM_ART': (int, 'General', 0), 'EMBED_ALBUM_ART': (int, 'General', 0),
'EMBED_LYRICS': (int, 'General', 0), 'EMBED_LYRICS': (int, 'General', 0),
'ENABLE_HTTPS': (int, 'General', 0), 'ENABLE_HTTPS': (int, 'General', 0),
@@ -92,6 +104,7 @@ _CONFIG_DEFINITIONS = {
'HTTP_PROXY': (int, 'General', 0), 'HTTP_PROXY': (int, 'General', 0),
'HTTP_ROOT': (str, 'General', '/'), 'HTTP_ROOT': (str, 'General', '/'),
'HTTP_USERNAME': (str, 'General', ''), 'HTTP_USERNAME': (str, 'General', ''),
'IDTAG': (int, 'Beets', 0),
'IGNORED_WORDS': (str, 'General', ''), 'IGNORED_WORDS': (str, 'General', ''),
'IGNORED_FOLDERS': (list, 'Advanced', []), 'IGNORED_FOLDERS': (list, 'Advanced', []),
'IGNORED_FILES': (list, 'Advanced', []), 'IGNORED_FILES': (list, 'Advanced', []),
+3 -3
View File
@@ -173,15 +173,15 @@ def piratesize(size):
factor = float(split[0]) factor = float(split[0])
unit = split[1].upper() unit = split[1].upper()
if unit == 'MiB': if unit == 'MIB':
size = factor * 1048576 size = factor * 1048576
elif unit == 'MB': elif unit == 'MB':
size = factor * 1000000 size = factor * 1000000
elif unit == 'GiB': elif unit == 'GIB':
size = factor * 1073741824 size = factor * 1073741824
elif unit == 'GB': elif unit == 'GB':
size = factor * 1000000000 size = factor * 1000000000
elif unit == 'KiB': elif unit == 'KIB':
size = factor * 1024 size = factor * 1024
elif unit == 'KB': elif unit == 'KB':
size = factor * 1000 size = factor * 1000
+9 -3
View File
@@ -47,6 +47,8 @@ def startmb():
elif headphones.CONFIG.MIRROR == "custom": elif headphones.CONFIG.MIRROR == "custom":
mbhost = headphones.CONFIG.CUSTOMHOST mbhost = headphones.CONFIG.CUSTOMHOST
mbport = int(headphones.CONFIG.CUSTOMPORT) mbport = int(headphones.CONFIG.CUSTOMPORT)
mbuser = headphones.CONFIG.CUSTOMUSER
mbpass = headphones.CONFIG.CUSTOMPASS
sleepytime = int(headphones.CONFIG.CUSTOMSLEEP) sleepytime = int(headphones.CONFIG.CUSTOMSLEEP)
elif headphones.CONFIG.MIRROR == "headphones": elif headphones.CONFIG.MIRROR == "headphones":
mbhost = "144.76.94.239" mbhost = "144.76.94.239"
@@ -69,12 +71,16 @@ def startmb():
mb_lock.minimum_delta = sleepytime mb_lock.minimum_delta = sleepytime
# Add headphones credentials # Add headphones credentials
if headphones.CONFIG.MIRROR == "headphones": if headphones.CONFIG.MIRROR == "headphones" or headphones.CONFIG.CUSTOMAUTH:
if not mbuser and mbpass: if not mbuser or not mbpass:
logger.warn("No username or password set for VIP server") logger.warn("No username or password set for MusicBrainz server")
else: else:
musicbrainzngs.hpauth(mbuser, mbpass) musicbrainzngs.hpauth(mbuser, mbpass)
# Let us know if we disable custom authentication
if not headphones.CONFIG.CUSTOMAUTH and headphones.CONFIG.MIRROR == "custom":
musicbrainzngs.disable_hpauth()
logger.debug('Using the following server values: MBHost: %s, MBPort: %i, Sleep Interval: %i', mbhost, mbport, sleepytime) logger.debug('Using the following server values: MBHost: %s, MBPort: %i, Sleep Interval: %i', mbhost, mbport, sleepytime)
return True return True
+33
View File
@@ -34,6 +34,11 @@ import json
import oauth2 as oauth import oauth2 as oauth
import pythontwitter as twitter import pythontwitter as twitter
from email.mime.text import MIMEText
import smtplib
import email.utils
class GROWL(object): class GROWL(object):
""" """
Growl notifications, for OS X. Growl notifications, for OS X.
@@ -827,3 +832,31 @@ class SubSonicNotifier(object):
# Invoke request # Invoke request
request.request_response(self.host + "musicFolderSettings.view?scanNow", request.request_response(self.host + "musicFolderSettings.view?scanNow",
auth=(self.username, self.password)) auth=(self.username, self.password))
class Email(object):
def notify(self, subject, message):
message = MIMEText(message, 'plain', "utf-8")
message['Subject'] = subject
message['From'] = email.utils.formataddr(('Headphones', headphones.CONFIG.EMAIL_FROM))
message['To'] = headphones.CONFIG.EMAIL_TO
try:
mailserver = smtplib.SMTP(headphones.CONFIG.EMAIL_SMTP_SERVER, headphones.CONFIG.EMAIL_SMTP_PORT)
if (headphones.CONFIG.EMAIL_TLS):
mailserver.starttls()
mailserver.ehlo()
if headphones.CONFIG.EMAIL_SMTP_USER:
mailserver.login(headphones.CONFIG.EMAIL_SMTP_USER, headphones.CONFIG.EMAIL_SMTP_PASSWORD)
mailserver.sendmail(headphones.CONFIG.EMAIL_FROM, headphones.CONFIG.EMAIL_TO, message.as_string())
mailserver.quit()
return True
except Exception, e:
logger.warn('Error sending Email: %s' % e)
return False
+20 -3
View File
@@ -23,6 +23,7 @@ import itertools
import headphones import headphones
from beets import autotag from beets import autotag
from beets import config as beetsconfig
from beets.mediafile import MediaFile, FileTypeError, UnreadableFileError from beets.mediafile import MediaFile, FileTypeError, UnreadableFileError
from beetsplug import lyrics as beetslyrics from beetsplug import lyrics as beetslyrics
@@ -34,7 +35,7 @@ postprocessor_lock = threading.Lock()
def checkFolder(): def checkFolder():
logger.info("Checking download folder for completed downloads (only snatched ones).") logger.debug("Checking download folder for completed downloads (only snatched ones).")
with postprocessor_lock: with postprocessor_lock:
myDB = db.DBConnection() myDB = db.DBConnection()
@@ -56,7 +57,7 @@ def checkFolder():
else: else:
logger.info("No folder name found for " + album['Title']) logger.info("No folder name found for " + album['Title'])
logger.info("Checking download folder finished.") logger.debug("Checking download folder finished.")
def verify(albumid, albumpath, Kind=None, forced=False): def verify(albumid, albumpath, Kind=None, forced=False):
@@ -513,6 +514,12 @@ def doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list,
mpc = notifiers.MPC() mpc = notifiers.MPC()
mpc.notify() mpc.notify()
if headphones.CONFIG.EMAIL_ENABLED:
logger.info(u"Sending Email notification")
email = notifiers.Email()
subject = release['ArtistName'] + ' - ' + release['AlbumTitle']
email.notify(subject, "Download and Postprocessing completed")
def embedAlbumArt(artwork, downloaded_track_list): def embedAlbumArt(artwork, downloaded_track_list):
logger.info('Embedding album art') logger.info('Embedding album art')
@@ -858,7 +865,7 @@ def correctMetadata(albumid, release, downloaded_track_list):
except Exception as e: except Exception as e:
logger.error('Error getting recommendation: %s. Not writing metadata', e) logger.error('Error getting recommendation: %s. Not writing metadata', e)
return return
if str(rec) == 'recommendation.none': if str(rec) == 'Recommendation.none':
logger.warn('No accurate album match found for %s, %s - not writing metadata', release['ArtistName'], release['AlbumTitle']) logger.warn('No accurate album match found for %s, %s - not writing metadata', release['ArtistName'], release['AlbumTitle'])
return return
@@ -873,6 +880,14 @@ def correctMetadata(albumid, release, downloaded_track_list):
# TODO: Handle extra_items & extra_tracks # TODO: Handle extra_items & extra_tracks
autotag.apply_metadata(info, mapping) autotag.apply_metadata(info, mapping)
# Set ID3 tag version
if headphones.CONFIG.IDTAG:
beetsconfig['id3v23'] = True
logger.debug("Using ID3v2.3")
else:
beetsconfig['id3v23'] = False
logger.debug("Using ID3v2.4")
for item in items: for item in items:
try: try:
@@ -1053,6 +1068,8 @@ def renameUnprocessedFolder(path, tag):
def forcePostProcess(dir=None, expand_subfolders=True, album_dir=None): def forcePostProcess(dir=None, expand_subfolders=True, album_dir=None):
logger.info('Force checking download folder for completed downloads')
ignored = 0 ignored = 0
if album_dir: if album_dir:
+16 -12
View File
@@ -225,7 +225,7 @@ def do_sorted_search(album, new, losslessOnly, choose_specific_download=False):
myDB = db.DBConnection() myDB = db.DBConnection()
albumlength = myDB.select('SELECT sum(TrackDuration) from tracks WHERE AlbumID=?', [album['AlbumID']])[0][0] albumlength = myDB.select('SELECT sum(TrackDuration) from tracks WHERE AlbumID=?', [album['AlbumID']])[0][0]
if headphones.CONFIG.PREFER_TORRENTS == 0: if headphones.CONFIG.PREFER_TORRENTS == 0 and not choose_specific_download:
if NZB_PROVIDERS and NZB_DOWNLOADERS: if NZB_PROVIDERS and NZB_DOWNLOADERS:
results = searchNZB(album, new, losslessOnly, albumlength) results = searchNZB(album, new, losslessOnly, albumlength)
@@ -233,7 +233,7 @@ def do_sorted_search(album, new, losslessOnly, choose_specific_download=False):
if not results and TORRENT_PROVIDERS: if not results and TORRENT_PROVIDERS:
results = searchTorrent(album, new, losslessOnly, albumlength) results = searchTorrent(album, new, losslessOnly, albumlength)
elif headphones.CONFIG.PREFER_TORRENTS == 1: elif headphones.CONFIG.PREFER_TORRENTS == 1 and not choose_specific_download:
if TORRENT_PROVIDERS: if TORRENT_PROVIDERS:
results = searchTorrent(album, new, losslessOnly, albumlength) results = searchTorrent(album, new, losslessOnly, albumlength)
@@ -247,10 +247,10 @@ def do_sorted_search(album, new, losslessOnly, choose_specific_download=False):
torrent_results = None torrent_results = None
if NZB_PROVIDERS and NZB_DOWNLOADERS: if NZB_PROVIDERS and NZB_DOWNLOADERS:
nzb_results = searchNZB(album, new, losslessOnly, albumlength) nzb_results = searchNZB(album, new, losslessOnly, albumlength, choose_specific_download)
if TORRENT_PROVIDERS: if TORRENT_PROVIDERS:
torrent_results = searchTorrent(album, new, losslessOnly, albumlength) torrent_results = searchTorrent(album, new, losslessOnly, albumlength, choose_specific_download)
if not nzb_results: if not nzb_results:
nzb_results = [] nzb_results = []
@@ -306,9 +306,9 @@ def more_filtering(results, album, albumlength, new):
targetsize = albumlength / 1000 * int(headphones.CONFIG.PREFERRED_BITRATE) * 128 targetsize = albumlength / 1000 * int(headphones.CONFIG.PREFERRED_BITRATE) * 128
logger.info('Target size: %s' % helpers.bytes_to_mb(targetsize)) logger.info('Target size: %s' % helpers.bytes_to_mb(targetsize))
if headphones.CONFIG.PREFERRED_BITRATE_LOW_BUFFER: if headphones.CONFIG.PREFERRED_BITRATE_LOW_BUFFER:
low_size_limit = targetsize - (targetsize * int(headphones.CONFIG.PREFERRED_BITRATE_LOW_BUFFER) / 100) low_size_limit = targetsize * int(headphones.CONFIG.PREFERRED_BITRATE_LOW_BUFFER) / 100
if headphones.CONFIG.PREFERRED_BITRATE_HIGH_BUFFER: if headphones.CONFIG.PREFERRED_BITRATE_HIGH_BUFFER:
high_size_limit = targetsize + (targetsize * int(headphones.CONFIG.PREFERRED_BITRATE_HIGH_BUFFER) / 100) high_size_limit = targetsize * int(headphones.CONFIG.PREFERRED_BITRATE_HIGH_BUFFER) / 100
if headphones.CONFIG.PREFERRED_BITRATE_ALLOW_LOSSLESS: if headphones.CONFIG.PREFERRED_BITRATE_ALLOW_LOSSLESS:
allow_lossless = True allow_lossless = True
@@ -429,7 +429,7 @@ def get_year_from_release_date(release_date):
return year return year
def searchNZB(album, new=False, losslessOnly=False, albumlength=None): def searchNZB(album, new=False, losslessOnly=False, albumlength=None, choose_specific_download=False):
reldate = album['ReleaseDate'] reldate = album['ReleaseDate']
year = get_year_from_release_date(reldate) year = get_year_from_release_date(reldate)
@@ -691,7 +691,7 @@ def searchNZB(album, new=False, losslessOnly=False, albumlength=None):
results = [result for result in resultlist if verifyresult(result[0], artistterm, term, losslessOnly)] results = [result for result in resultlist if verifyresult(result[0], artistterm, term, losslessOnly)]
# Additional filtering for size etc # Additional filtering for size etc
if results: if results and not choose_specific_download:
results = more_filtering(results, album, albumlength, new) results = more_filtering(results, album, albumlength, new)
return results return results
@@ -946,7 +946,11 @@ def send_to_downloader(data, bestqual, album):
b2msg = 'From ' + provider + '<br></br>' + name b2msg = 'From ' + provider + '<br></br>' + name
boxcar = notifiers.BOXCAR() boxcar = notifiers.BOXCAR()
boxcar.notify('Headphones snatched: ' + title, b2msg, rgid) boxcar.notify('Headphones snatched: ' + title, b2msg, rgid)
if headphones.CONFIG.EMAIL_ENABLED and headphones.CONFIG.EMAIL_ONSNATCH:
logger.info(u"Sending Email notification")
email = notifiers.Email()
message = 'Snatched from ' + provider + '. ' + name
email.notify(title, message)
def verifyresult(title, artistterm, term, lossless): def verifyresult(title, artistterm, term, lossless):
@@ -1014,7 +1018,7 @@ def verifyresult(title, artistterm, term, lossless):
return True return True
def searchTorrent(album, new=False, losslessOnly=False, albumlength=None): def searchTorrent(album, new=False, losslessOnly=False, albumlength=None, choose_specific_download=False):
global gazelle # persistent what.cd api object to reduce number of login attempts global gazelle # persistent what.cd api object to reduce number of login attempts
# rutracker login # rutracker login
@@ -1092,7 +1096,7 @@ def searchTorrent(album, new=False, losslessOnly=False, albumlength=None):
if headphones.CONFIG.KAT_PROXY_URL: if headphones.CONFIG.KAT_PROXY_URL:
providerurl = fix_url(set_proxy(headphones.CONFIG.KAT_PROXY_URL)) providerurl = fix_url(set_proxy(headphones.CONFIG.KAT_PROXY_URL))
else: else:
providerurl = fix_url("https://kickass.so") providerurl = fix_url("https://kickass.to")
# Build URL # Build URL
providerurl = providerurl + "/usearch/" + ka_term providerurl = providerurl + "/usearch/" + ka_term
@@ -1521,7 +1525,7 @@ def searchTorrent(album, new=False, losslessOnly=False, albumlength=None):
results = [result for result in resultlist if verifyresult(result[0], artistterm, term, losslessOnly)] results = [result for result in resultlist if verifyresult(result[0], artistterm, term, losslessOnly)]
# Additional filtering for size etc # Additional filtering for size etc
if results: if results and not choose_specific_download:
results = more_filtering(results, album, albumlength, new) results = more_filtering(results, album, albumlength, new)
return results return results
+19 -2
View File
@@ -374,6 +374,9 @@ class WebInterface(object):
myDB = db.DBConnection() myDB = db.DBConnection()
album = myDB.action('SELECT * from albums WHERE AlbumID=?', [AlbumID]).fetchone() album = myDB.action('SELECT * from albums WHERE AlbumID=?', [AlbumID]).fetchone()
searcher.send_to_downloader(data, bestqual, album) searcher.send_to_downloader(data, bestqual, album)
return json.dumps({'result':'success'})
else:
return json.dumps({'result':'failure'})
@cherrypy.expose @cherrypy.expose
def unqueueAlbum(self, AlbumID, ArtistID): def unqueueAlbum(self, AlbumID, ArtistID):
@@ -877,6 +880,7 @@ class WebInterface(object):
cherrypy.response.headers['Content-type'] = 'application/json' cherrypy.response.headers['Content-type'] = 'application/json'
return json_albums return json_albums
@cherrypy.expose
def getArtistjson(self, ArtistID, **kwargs): def getArtistjson(self, ArtistID, **kwargs):
myDB = db.DBConnection() myDB = db.DBConnection()
artist = myDB.action('SELECT * FROM artists WHERE ArtistID=?', [ArtistID]).fetchone() artist = myDB.action('SELECT * FROM artists WHERE ArtistID=?', [ArtistID]).fetchone()
@@ -1142,6 +1146,9 @@ class WebInterface(object):
"customhost": headphones.CONFIG.CUSTOMHOST, "customhost": headphones.CONFIG.CUSTOMHOST,
"customport": headphones.CONFIG.CUSTOMPORT, "customport": headphones.CONFIG.CUSTOMPORT,
"customsleep": headphones.CONFIG.CUSTOMSLEEP, "customsleep": headphones.CONFIG.CUSTOMSLEEP,
"customauth": checked(headphones.CONFIG.CUSTOMAUTH),
"customuser": headphones.CONFIG.CUSTOMUSER,
"custompass": headphones.CONFIG.CUSTOMPASS,
"hpuser": headphones.CONFIG.HPUSER, "hpuser": headphones.CONFIG.HPUSER,
"hppass": headphones.CONFIG.HPPASS, "hppass": headphones.CONFIG.HPPASS,
"songkick_enabled": checked(headphones.CONFIG.SONGKICK_ENABLED), "songkick_enabled": checked(headphones.CONFIG.SONGKICK_ENABLED),
@@ -1151,7 +1158,17 @@ class WebInterface(object):
"cache_sizemb": headphones.CONFIG.CACHE_SIZEMB, "cache_sizemb": headphones.CONFIG.CACHE_SIZEMB,
"file_permissions": headphones.CONFIG.FILE_PERMISSIONS, "file_permissions": headphones.CONFIG.FILE_PERMISSIONS,
"folder_permissions": headphones.CONFIG.FOLDER_PERMISSIONS, "folder_permissions": headphones.CONFIG.FOLDER_PERMISSIONS,
"mpc_enabled": checked(headphones.CONFIG.MPC_ENABLED) "mpc_enabled": checked(headphones.CONFIG.MPC_ENABLED),
"email_enabled": checked(headphones.CONFIG.EMAIL_ENABLED),
"email_from": headphones.CONFIG.EMAIL_FROM,
"email_to": headphones.CONFIG.EMAIL_TO,
"email_smtp_server": headphones.CONFIG.EMAIL_SMTP_SERVER,
"email_smtp_user": headphones.CONFIG.EMAIL_SMTP_USER,
"email_smtp_password": headphones.CONFIG.EMAIL_SMTP_PASSWORD,
"email_smtp_port": int(headphones.CONFIG.EMAIL_SMTP_PORT),
"email_tls": checked(headphones.CONFIG.EMAIL_TLS),
"email_onsnatch": checked(headphones.CONFIG.EMAIL_ONSNATCH),
"idtag": checked(headphones.CONFIG.IDTAG)
} }
# Need to convert EXTRAS to a dictionary we can pass to the config: # Need to convert EXTRAS to a dictionary we can pass to the config:
@@ -1196,7 +1213,7 @@ class WebInterface(object):
"nma_enabled", "nma_onsnatch", "pushalot_enabled", "pushalot_onsnatch", "synoindex_enabled", "pushover_enabled", "nma_enabled", "nma_onsnatch", "pushalot_enabled", "pushalot_onsnatch", "synoindex_enabled", "pushover_enabled",
"pushover_onsnatch", "pushbullet_enabled", "pushbullet_onsnatch", "subsonic_enabled", "twitter_enabled", "twitter_onsnatch", "pushover_onsnatch", "pushbullet_enabled", "pushbullet_onsnatch", "subsonic_enabled", "twitter_enabled", "twitter_onsnatch",
"osx_notify_enabled", "osx_notify_onsnatch", "boxcar_enabled", "boxcar_onsnatch", "songkick_enabled", "songkick_filter_enabled", "osx_notify_enabled", "osx_notify_onsnatch", "boxcar_enabled", "boxcar_onsnatch", "songkick_enabled", "songkick_filter_enabled",
"mpc_enabled" "mpc_enabled", "email_enabled", "email_tls", "email_onsnatch", "customauth", "idtag"
] ]
for checked_config in checked_configs: for checked_config in checked_configs:
if checked_config not in kwargs: if checked_config not in kwargs:
+10 -2
View File
@@ -271,6 +271,7 @@ user = password = ""
hostname = "musicbrainz.org" hostname = "musicbrainz.org"
_client = "" _client = ""
_useragent = "" _useragent = ""
mb_auth = False
def auth(u, p): def auth(u, p):
"""Set the username and password to be used in subsequent queries to """Set the username and password to be used in subsequent queries to
@@ -284,9 +285,16 @@ def hpauth(u, p):
"""Set the username and password to be used in subsequent queries to """Set the username and password to be used in subsequent queries to
the MusicBrainz XML API that require authentication. the MusicBrainz XML API that require authentication.
""" """
global hpuser, hppassword global hpuser, hppassword, mb_auth
hpuser = u hpuser = u
hppassword = p hppassword = p
mb_auth = True
def disable_hpauth():
"""Disable the authentication for MusicBrainz XML API
"""
global mb_auth
mb_auth = False
def set_useragent(app, version, contact=None): def set_useragent(app, version, contact=None):
"""Set the User-Agent to be used for requests to the MusicBrainz webservice. """Set the User-Agent to be used for requests to the MusicBrainz webservice.
@@ -635,7 +643,7 @@ def _mb_request(path, method='GET', auth_required=False, client_required=False,
req.add_header('User-Agent', _useragent) req.add_header('User-Agent', _useragent)
# Add headphones credentials # Add headphones credentials
if hostname == '144.76.94.239:8181': if mb_auth:
base64string = base64.encodestring('%s:%s' % (hpuser, hppassword)).replace('\n', '') base64string = base64.encodestring('%s:%s' % (hpuser, hppassword)).replace('\n', '')
req.add_header("Authorization", "Basic %s" % base64string) req.add_header("Authorization", "Basic %s" % base64string)