mirror of
https://github.com/rembo10/headphones.git
synced 2026-07-21 00:14:02 +01:00
Fix travis errors
This commit is contained in:
+841
-957
File diff suppressed because it is too large
Load Diff
+65
-52
@@ -26,7 +26,6 @@ import binascii
|
|||||||
from beets.mediafile import MediaFile
|
from beets.mediafile import MediaFile
|
||||||
from headphones import logger, request, helpers
|
from headphones import logger, request, helpers
|
||||||
import headphones
|
import headphones
|
||||||
from twisted.conch.insults import helper
|
|
||||||
|
|
||||||
# Public constants
|
# Public constants
|
||||||
PROVIDER_NAME = 'Deezer'
|
PROVIDER_NAME = 'Deezer'
|
||||||
@@ -53,6 +52,7 @@ __cookies = None
|
|||||||
__tracks_cache = {}
|
__tracks_cache = {}
|
||||||
__albums_cache = {}
|
__albums_cache = {}
|
||||||
|
|
||||||
|
|
||||||
def __getApiToken():
|
def __getApiToken():
|
||||||
global __cookies
|
global __cookies
|
||||||
response = request.request_response(url="http://www.deezer.com/", headers=__HTTP_HEADERS)
|
response = request.request_response(url="http://www.deezer.com/", headers=__HTTP_HEADERS)
|
||||||
@@ -67,39 +67,42 @@ def __getApiToken():
|
|||||||
|
|
||||||
if not token:
|
if not token:
|
||||||
logger.error(u"Deezloader: Unable to get api token")
|
logger.error(u"Deezloader: Unable to get api token")
|
||||||
|
|
||||||
|
|
||||||
def getAlbumByLink(album_link):
|
def getAlbumByLink(album_link):
|
||||||
"""Returns deezer album infos using album link url
|
"""Returns deezer album infos using album link url
|
||||||
|
|
||||||
:param str album_link: deezer album link url (eg: 'http://www.deezer.com/album/1234567/')
|
:param str album_link: deezer album link url (eg: 'http://www.deezer.com/album/1234567/')
|
||||||
"""
|
"""
|
||||||
matches = re.search(r"album\/([0-9]+)\/?$", album_link)
|
matches = re.search(r"album\/([0-9]+)\/?$", album_link)
|
||||||
if matches:
|
if matches:
|
||||||
return getAlbum(matches.group(1))
|
return getAlbum(matches.group(1))
|
||||||
|
|
||||||
|
|
||||||
def getAlbum(album_id):
|
def getAlbum(album_id):
|
||||||
"""Returns deezer album infos
|
"""Returns deezer album infos
|
||||||
|
|
||||||
:param int album_id: deezer album id
|
:param int album_id: deezer album id
|
||||||
"""
|
"""
|
||||||
global __albums_cache
|
global __albums_cache
|
||||||
|
|
||||||
if str(album_id) in __albums_cache:
|
if str(album_id) in __albums_cache:
|
||||||
return __albums_cache[str(album_id)]
|
return __albums_cache[str(album_id)]
|
||||||
|
|
||||||
url = __API_INFO_URL + "album/" + str(album_id)
|
url = __API_INFO_URL + "album/" + str(album_id)
|
||||||
data = request.request_json(url=url, headers=__HTTP_HEADERS, cookies=__cookies)
|
data = request.request_json(url=url, headers=__HTTP_HEADERS, cookies=__cookies)
|
||||||
|
|
||||||
if data and 'error' not in data:
|
if data and 'error' not in data:
|
||||||
__albums_cache[str(album_id)] = data
|
__albums_cache[str(album_id)] = data
|
||||||
return data
|
return data
|
||||||
else:
|
else:
|
||||||
logger.debug("Deezloader: Can't load album infos")
|
logger.debug("Deezloader: Can't load album infos")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def searchAlbums(search_term):
|
def searchAlbums(search_term):
|
||||||
"""Search for deezer albums using search term
|
"""Search for deezer albums using search term
|
||||||
|
|
||||||
:param str search_term: search term to search album for
|
:param str search_term: search term to search album for
|
||||||
"""
|
"""
|
||||||
logger.info(u'Searching Deezer using term: "%s"' % search_term)
|
logger.info(u'Searching Deezer using term: "%s"' % search_term)
|
||||||
@@ -108,7 +111,7 @@ def searchAlbums(search_term):
|
|||||||
data = request.request_json(url=url, headers=__HTTP_HEADERS, cookies=__cookies)
|
data = request.request_json(url=url, headers=__HTTP_HEADERS, cookies=__cookies)
|
||||||
|
|
||||||
albums = []
|
albums = []
|
||||||
|
|
||||||
# Process content
|
# Process content
|
||||||
if data and 'total' in data and data['total'] > 0 and 'data' in data:
|
if data and 'total' in data and data['total'] > 0 and 'data' in data:
|
||||||
for item in data['data']:
|
for item in data['data']:
|
||||||
@@ -121,13 +124,14 @@ def searchAlbums(search_term):
|
|||||||
|
|
||||||
return albums
|
return albums
|
||||||
|
|
||||||
|
|
||||||
def __matchAlbums(albums, artist_name, album_title, album_length):
|
def __matchAlbums(albums, artist_name, album_title, album_length):
|
||||||
resultlist = []
|
resultlist = []
|
||||||
|
|
||||||
for album in albums:
|
for album in albums:
|
||||||
total_size = 0
|
total_size = 0
|
||||||
tracks_found = 0
|
tracks_found = 0
|
||||||
|
|
||||||
for track in album['tracks']['data']:
|
for track in album['tracks']['data']:
|
||||||
t = getTrack(track['id'])
|
t = getTrack(track['id'])
|
||||||
if t:
|
if t:
|
||||||
@@ -139,29 +143,29 @@ def __matchAlbums(albums, artist_name, album_title, album_length):
|
|||||||
size = t["FILESIZE_MP3_128"]
|
size = t["FILESIZE_MP3_128"]
|
||||||
else:
|
else:
|
||||||
size = t["FILESIZE_MP3_64"]
|
size = t["FILESIZE_MP3_64"]
|
||||||
|
|
||||||
size = int(size)
|
size = int(size)
|
||||||
total_size += size
|
total_size += size
|
||||||
tracks_found += 1
|
tracks_found += 1
|
||||||
logger.debug(u'Found song "%s". Size: %s' % (t['SNG_TITLE'], helpers.bytes_to_mb(size)))
|
logger.debug(u'Found song "%s". Size: %s' % (t['SNG_TITLE'], helpers.bytes_to_mb(size)))
|
||||||
|
|
||||||
matched = True
|
matched = True
|
||||||
mismatch_reason = 'matched!'
|
mismatch_reason = 'matched!'
|
||||||
|
|
||||||
if album_length > 0 and abs(int(album['duration']) - album_length) > 240:
|
if album_length > 0 and abs(int(album['duration']) - album_length) > 240:
|
||||||
matched = False
|
matched = False
|
||||||
mismatch_reason = (u'duration mismatch: %i not in [%i, %i]' % (int(album['duration']), (album_length - 240), (album_length + 240)))
|
mismatch_reason = (u'duration mismatch: %i not in [%i, %i]' % (int(album['duration']), (album_length - 240), (album_length + 240)))
|
||||||
|
|
||||||
elif (helpers.latinToAscii(re.sub(r"\W", "", album_title, 0, re.UNICODE)).lower() !=
|
elif (helpers.latinToAscii(re.sub(r"\W", "", album_title, 0, re.UNICODE)).lower() !=
|
||||||
helpers.latinToAscii(re.sub(r"\W", "", album['title'], 0, re.UNICODE)).lower()):
|
helpers.latinToAscii(re.sub(r"\W", "", album['title'], 0, re.UNICODE)).lower()):
|
||||||
matched = False
|
matched = False
|
||||||
mismatch_reason = (u'album name mismatch: %s != %s' % (album['title'], album_title))
|
mismatch_reason = (u'album name mismatch: %s != %s' % (album['title'], album_title))
|
||||||
|
|
||||||
elif (helpers.latinToAscii(re.sub(r"\W", "", artist_name, 0, re.UNICODE)).lower() !=
|
elif (helpers.latinToAscii(re.sub(r"\W", "", artist_name, 0, re.UNICODE)).lower() !=
|
||||||
helpers.latinToAscii(re.sub(r"\W", "", album['artist']['name'], 0, re.UNICODE)).lower()):
|
helpers.latinToAscii(re.sub(r"\W", "", album['artist']['name'], 0, re.UNICODE)).lower()):
|
||||||
matched = False
|
matched = False
|
||||||
mismatch_reason = (u'artist name mismatch: %s != %s' % (album['artist']['name'], artist_name))
|
mismatch_reason = (u'artist name mismatch: %s != %s' % (album['artist']['name'], artist_name))
|
||||||
|
|
||||||
resultlist.append(
|
resultlist.append(
|
||||||
(album['artist']['name'] + ' - ' + album['title'] + ' [' + album['release_date'][:4] + '] (' + str(tracks_found) + '/' + str(album['nb_tracks']) + ')',
|
(album['artist']['name'] + ' - ' + album['title'] + ' [' + album['release_date'][:4] + '] (' + str(tracks_found) + '/' + str(album['nb_tracks']) + ')',
|
||||||
total_size, album['link'], PROVIDER_NAME, "ddl", matched)
|
total_size, album['link'], PROVIDER_NAME, "ddl", matched)
|
||||||
@@ -170,6 +174,7 @@ def __matchAlbums(albums, artist_name, album_title, album_length):
|
|||||||
|
|
||||||
return resultlist
|
return resultlist
|
||||||
|
|
||||||
|
|
||||||
def searchAlbum(artist_name, album_title, user_search_term=None, album_length=None):
|
def searchAlbum(artist_name, album_title, user_search_term=None, album_length=None):
|
||||||
"""Search for deezer specific album.
|
"""Search for deezer specific album.
|
||||||
This will iterate over deezer albums and try to find best matches
|
This will iterate over deezer albums and try to find best matches
|
||||||
@@ -182,7 +187,7 @@ def searchAlbum(artist_name, album_title, user_search_term=None, album_length=No
|
|||||||
# User search term by-pass normal search
|
# User search term by-pass normal search
|
||||||
if user_search_term:
|
if user_search_term:
|
||||||
return __matchAlbums(searchAlbums(user_search_term), artist_name, album_title, album_length)
|
return __matchAlbums(searchAlbums(user_search_term), artist_name, album_title, album_length)
|
||||||
|
|
||||||
resultlist = __matchAlbums(searchAlbums((artist_name + ' ' + album_title).strip()), artist_name, album_title, album_length)
|
resultlist = __matchAlbums(searchAlbums((artist_name + ' ' + album_title).strip()), artist_name, album_title, album_length)
|
||||||
if resultlist:
|
if resultlist:
|
||||||
return resultlist
|
return resultlist
|
||||||
@@ -190,35 +195,36 @@ def searchAlbum(artist_name, album_title, user_search_term=None, album_length=No
|
|||||||
# Deezer API supports unicode, so just remove non alphanumeric characters
|
# Deezer API supports unicode, so just remove non alphanumeric characters
|
||||||
clean_artist_name = re.sub(r"[^\w\s]", " ", artist_name, 0, re.UNICODE).strip()
|
clean_artist_name = re.sub(r"[^\w\s]", " ", artist_name, 0, re.UNICODE).strip()
|
||||||
clean_album_name = re.sub(r"[^\w\s]", " ", album_title, 0, re.UNICODE).strip()
|
clean_album_name = re.sub(r"[^\w\s]", " ", album_title, 0, re.UNICODE).strip()
|
||||||
|
|
||||||
resultlist = __matchAlbums(searchAlbums((clean_artist_name + ' ' + clean_album_name).strip()), artist_name, album_title, album_length)
|
resultlist = __matchAlbums(searchAlbums((clean_artist_name + ' ' + clean_album_name).strip()), artist_name, album_title, album_length)
|
||||||
if resultlist:
|
if resultlist:
|
||||||
return resultlist
|
return resultlist
|
||||||
|
|
||||||
resultlist = __matchAlbums(searchAlbums(clean_artist_name), artist_name, album_title, album_length)
|
resultlist = __matchAlbums(searchAlbums(clean_artist_name), artist_name, album_title, album_length)
|
||||||
if resultlist:
|
if resultlist:
|
||||||
return resultlist
|
return resultlist
|
||||||
|
|
||||||
return resultlist
|
return resultlist
|
||||||
|
|
||||||
|
|
||||||
def getTrack(sng_id, try_reload_api=True):
|
def getTrack(sng_id, try_reload_api=True):
|
||||||
"""Returns deezer track infos
|
"""Returns deezer track infos
|
||||||
|
|
||||||
:param int sng_id: deezer song id
|
:param int sng_id: deezer song id
|
||||||
:param bool try_reload_api: whether or not try reloading API if session expired
|
:param bool try_reload_api: whether or not try reloading API if session expired
|
||||||
"""
|
"""
|
||||||
global __tracks_cache
|
global __tracks_cache
|
||||||
|
|
||||||
if str(sng_id) in __tracks_cache:
|
if str(sng_id) in __tracks_cache:
|
||||||
return __tracks_cache[str(sng_id)]
|
return __tracks_cache[str(sng_id)]
|
||||||
|
|
||||||
data = "[{\"method\":\"song.getListData\",\"params\":{\"sng_ids\":[" + str(sng_id) + "]}}]"
|
data = "[{\"method\":\"song.getListData\",\"params\":{\"sng_ids\":[" + str(sng_id) + "]}}]"
|
||||||
json = request.request_json(url=__API_URL, headers=__HTTP_HEADERS, method='post', params=__api_queries, data=data, cookies=__cookies)
|
json = request.request_json(url=__API_URL, headers=__HTTP_HEADERS, method='post', params=__api_queries, data=data, cookies=__cookies)
|
||||||
|
|
||||||
results = []
|
results = []
|
||||||
error = None
|
error = None
|
||||||
invalid_token = False
|
invalid_token = False
|
||||||
|
|
||||||
if json:
|
if json:
|
||||||
# Check for errors
|
# Check for errors
|
||||||
if 'error' in json:
|
if 'error' in json:
|
||||||
@@ -230,7 +236,7 @@ def getTrack(sng_id, try_reload_api=True):
|
|||||||
error = json[0]['error']
|
error = json[0]['error']
|
||||||
if 'VALID_TOKEN_REQUIRED' in json[0]['error'] and json[0]['error']['VALID_TOKEN_REQUIRED'] == u"Invalid CSRF token":
|
if 'VALID_TOKEN_REQUIRED' in json[0]['error'] and json[0]['error']['VALID_TOKEN_REQUIRED'] == u"Invalid CSRF token":
|
||||||
invalid_token = True
|
invalid_token = True
|
||||||
|
|
||||||
# Got invalid token error
|
# Got invalid token error
|
||||||
if error:
|
if error:
|
||||||
if invalid_token and try_reload_api:
|
if invalid_token and try_reload_api:
|
||||||
@@ -245,26 +251,27 @@ def getTrack(sng_id, try_reload_api=True):
|
|||||||
if 'token' in item:
|
if 'token' in item:
|
||||||
logger.error(u"An unknown error occurred in the Deezer parser: Uploaded Files are currently not supported")
|
logger.error(u"An unknown error occurred in the Deezer parser: Uploaded Files are currently not supported")
|
||||||
return
|
return
|
||||||
|
|
||||||
sng_id = item["SNG_ID"]
|
sng_id = item["SNG_ID"]
|
||||||
md5Origin = item["MD5_ORIGIN"]
|
md5Origin = item["MD5_ORIGIN"]
|
||||||
sng_format = 3
|
sng_format = 3
|
||||||
|
|
||||||
if item["FILESIZE_MP3_320"] <= 0:
|
if item["FILESIZE_MP3_320"] <= 0:
|
||||||
if item["FILESIZE_MP3_256"] > 0:
|
if item["FILESIZE_MP3_256"] > 0:
|
||||||
sng_format = 5
|
sng_format = 5
|
||||||
else:
|
else:
|
||||||
sng_format = 1
|
sng_format = 1
|
||||||
|
|
||||||
mediaVersion = int(item["MEDIA_VERSION"])
|
mediaVersion = int(item["MEDIA_VERSION"])
|
||||||
item['downloadUrl'] = __getDownloadUrl(md5Origin, sng_id, sng_format, mediaVersion)
|
item['downloadUrl'] = __getDownloadUrl(md5Origin, sng_id, sng_format, mediaVersion)
|
||||||
|
|
||||||
__tracks_cache[sng_id] = item
|
__tracks_cache[sng_id] = item
|
||||||
return item
|
return item
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(u"An unknown error occurred in the Deezer parser: %s" % e)
|
logger.error(u"An unknown error occurred in the Deezer parser: %s" % e)
|
||||||
|
|
||||||
|
|
||||||
def __getDownloadUrl(md5Origin, sng_id, sng_format, mediaVersion):
|
def __getDownloadUrl(md5Origin, sng_id, sng_format, mediaVersion):
|
||||||
urlPart = md5Origin.encode('utf-8') + b'\xa4' + str(sng_format) + b'\xa4' + str(sng_id) + b'\xa4' + str(mediaVersion)
|
urlPart = md5Origin.encode('utf-8') + b'\xa4' + str(sng_format) + b'\xa4' + str(sng_id) + b'\xa4' + str(mediaVersion)
|
||||||
md5val = md5(urlPart).hexdigest()
|
md5val = md5(urlPart).hexdigest()
|
||||||
@@ -273,6 +280,7 @@ def __getDownloadUrl(md5Origin, sng_id, sng_format, mediaVersion):
|
|||||||
ciphertext = cipher.encrypt(__pad(urlPart, AES.block_size))
|
ciphertext = cipher.encrypt(__pad(urlPart, AES.block_size))
|
||||||
return "http://e-cdn-proxy-" + md5Origin[:1] + ".deezer.com/mobile/1/" + binascii.hexlify(ciphertext).lower()
|
return "http://e-cdn-proxy-" + md5Origin[:1] + ".deezer.com/mobile/1/" + binascii.hexlify(ciphertext).lower()
|
||||||
|
|
||||||
|
|
||||||
def __pad(raw, block_size):
|
def __pad(raw, block_size):
|
||||||
if (len(raw) % block_size == 0):
|
if (len(raw) % block_size == 0):
|
||||||
return raw
|
return raw
|
||||||
@@ -281,10 +289,11 @@ def __pad(raw, block_size):
|
|||||||
data = raw + padding_required * padChar
|
data = raw + padding_required * padChar
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
def __tagTrack(path, track):
|
def __tagTrack(path, track):
|
||||||
try:
|
try:
|
||||||
album = getAlbum(track['ALB_ID'])
|
album = getAlbum(track['ALB_ID'])
|
||||||
|
|
||||||
f = MediaFile(path)
|
f = MediaFile(path)
|
||||||
f.artist = track['ART_NAME']
|
f.artist = track['ART_NAME']
|
||||||
f.album = track['ALB_TITLE']
|
f.album = track['ALB_TITLE']
|
||||||
@@ -295,22 +304,23 @@ def __tagTrack(path, track):
|
|||||||
f.bpm = track['BPM']
|
f.bpm = track['BPM']
|
||||||
f.date = datetime.strptime(album['release_date'], '%Y-%m-%d').date()
|
f.date = datetime.strptime(album['release_date'], '%Y-%m-%d').date()
|
||||||
f.albumartist = album['artist']['name']
|
f.albumartist = album['artist']['name']
|
||||||
if u'genres' in album and u'data' in album['genres']:
|
if u'genres' in album and u'data' in album['genres']:
|
||||||
f.genres = [genre['name'] for genre in album['genres']['data']]
|
f.genres = [genre['name'] for genre in album['genres']['data']]
|
||||||
|
|
||||||
f.save()
|
f.save()
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(u'Unable to tag deezer track "%s": %s' % (path, e))
|
logger.error(u'Unable to tag deezer track "%s": %s' % (path, e))
|
||||||
|
|
||||||
|
|
||||||
def decryptTracks(paths):
|
def decryptTracks(paths):
|
||||||
"""Decrypt downloaded deezer tracks.
|
"""Decrypt downloaded deezer tracks.
|
||||||
|
|
||||||
:param paths: list of path to deezer tracks (*.dzr files).
|
:param paths: list of path to deezer tracks (*.dzr files).
|
||||||
"""
|
"""
|
||||||
# Note: tracks can be from different albums
|
# Note: tracks can be from different albums
|
||||||
decrypted_tracks = {}
|
decrypted_tracks = {}
|
||||||
|
|
||||||
# First pass: load tracks data
|
# First pass: load tracks data
|
||||||
for path in paths:
|
for path in paths:
|
||||||
try:
|
try:
|
||||||
@@ -322,15 +332,15 @@ def decryptTracks(paths):
|
|||||||
|
|
||||||
if album_folder not in decrypted_tracks:
|
if album_folder not in decrypted_tracks:
|
||||||
decrypted_tracks[album_folder] = {}
|
decrypted_tracks[album_folder] = {}
|
||||||
|
|
||||||
if disk_number not in decrypted_tracks[album_folder]:
|
if disk_number not in decrypted_tracks[album_folder]:
|
||||||
decrypted_tracks[album_folder][disk_number] = {}
|
decrypted_tracks[album_folder][disk_number] = {}
|
||||||
|
|
||||||
decrypted_tracks[album_folder][disk_number][track_number] = track
|
decrypted_tracks[album_folder][disk_number][track_number] = track
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(u'Unable to load deezer track infos "%s": %s' % (path, e))
|
logger.error(u'Unable to load deezer track infos "%s": %s' % (path, e))
|
||||||
|
|
||||||
# Second pass: decrypt tracks
|
# Second pass: decrypt tracks
|
||||||
for album_folder in decrypted_tracks:
|
for album_folder in decrypted_tracks:
|
||||||
multi_disks = len(decrypted_tracks[album_folder]) > 1
|
multi_disks = len(decrypted_tracks[album_folder]) > 1
|
||||||
@@ -339,12 +349,12 @@ def decryptTracks(paths):
|
|||||||
try:
|
try:
|
||||||
filename = helpers.replace_illegal_chars(track['SNG_TITLE']).strip()
|
filename = helpers.replace_illegal_chars(track['SNG_TITLE']).strip()
|
||||||
filename = ('{:02d}'.format(track_number) + '_' + filename + '.mp3')
|
filename = ('{:02d}'.format(track_number) + '_' + filename + '.mp3')
|
||||||
|
|
||||||
# Add a 'cd x' sub-folder if album has more than one disk
|
# Add a 'cd x' sub-folder if album has more than one disk
|
||||||
disk_folder = os.path.join(album_folder, 'cd ' + str(disk_number)) if multi_disks else album_folder
|
disk_folder = os.path.join(album_folder, 'cd ' + str(disk_number)) if multi_disks else album_folder
|
||||||
|
|
||||||
dest = os.path.join(disk_folder, filename).encode(headphones.SYS_ENCODING, 'replace')
|
dest = os.path.join(disk_folder, filename).encode(headphones.SYS_ENCODING, 'replace')
|
||||||
|
|
||||||
# Decrypt track if not already done
|
# Decrypt track if not already done
|
||||||
if not os.path.exists(dest):
|
if not os.path.exists(dest):
|
||||||
try:
|
try:
|
||||||
@@ -358,12 +368,13 @@ def decryptTracks(paths):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
decrypted_tracks[album_folder][disk_number][track_number]['path'] = dest
|
decrypted_tracks[album_folder][disk_number][track_number]['path'] = dest
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(u'Unable to decrypt deezer track "%s": %s' % (path, e))
|
logger.error(u'Unable to decrypt deezer track "%s": %s' % (path, e))
|
||||||
|
|
||||||
return decrypted_tracks
|
return decrypted_tracks
|
||||||
|
|
||||||
|
|
||||||
def __decryptDownload(source, sng_id, dest):
|
def __decryptDownload(source, sng_id, dest):
|
||||||
interval_chunk = 3
|
interval_chunk = 3
|
||||||
chunk_size = 2048
|
chunk_size = 2048
|
||||||
@@ -383,7 +394,7 @@ def __decryptDownload(source, sng_id, dest):
|
|||||||
if(i % interval_chunk == 0):
|
if(i % interval_chunk == 0):
|
||||||
cipher = Blowfish.new(blowFishKey, Blowfish.MODE_CBC, iv)
|
cipher = Blowfish.new(blowFishKey, Blowfish.MODE_CBC, iv)
|
||||||
chunk = cipher.decrypt(__pad(chunk, Blowfish.block_size))
|
chunk = cipher.decrypt(__pad(chunk, Blowfish.block_size))
|
||||||
|
|
||||||
fout.write(chunk)
|
fout.write(chunk)
|
||||||
i += 1
|
i += 1
|
||||||
chunk = f.read(chunk_size)
|
chunk = f.read(chunk_size)
|
||||||
@@ -391,6 +402,7 @@ def __decryptDownload(source, sng_id, dest):
|
|||||||
f.close()
|
f.close()
|
||||||
fout.close()
|
fout.close()
|
||||||
|
|
||||||
|
|
||||||
def __getBlowFishKey(encryptionKey):
|
def __getBlowFishKey(encryptionKey):
|
||||||
if encryptionKey < 1:
|
if encryptionKey < 1:
|
||||||
encryptionKey *= -1
|
encryptionKey *= -1
|
||||||
@@ -402,14 +414,15 @@ def __getBlowFishKey(encryptionKey):
|
|||||||
|
|
||||||
return __xorHex(parts)
|
return __xorHex(parts)
|
||||||
|
|
||||||
|
|
||||||
def __xorHex(parts):
|
def __xorHex(parts):
|
||||||
data = ""
|
data = ""
|
||||||
for i in range(0, 16):
|
for i in range(0, 16):
|
||||||
character = ord(parts[0][i])
|
character = ord(parts[0][i])
|
||||||
|
|
||||||
for j in range(1, len(parts)):
|
for j in range(1, len(parts)):
|
||||||
character ^= ord(parts[j][i])
|
character ^= ord(parts[j][i])
|
||||||
|
|
||||||
data += chr(character)
|
data += chr(character)
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ class HelpersTest(TestCase):
|
|||||||
u'Symphonęy Nº9': 'Symphoney No.9',
|
u'Symphonęy Nº9': 'Symphoney No.9',
|
||||||
u'ÆæßðÞIJij': u'AeaessdThIJıj',
|
u'ÆæßðÞIJij': u'AeaessdThIJıj',
|
||||||
u'Obsessió (Cerebral Apoplexy remix)': 'obsessio cerebral '
|
u'Obsessió (Cerebral Apoplexy remix)': 'obsessio cerebral '
|
||||||
'apoplexy remix',
|
'apoplexy remix',
|
||||||
u'Doktór Hałabała i siedmiu zbojów': 'doktor halabala i siedmiu '
|
u'Doktór Hałabała i siedmiu zbojów': 'doktor halabala i siedmiu '
|
||||||
'zbojow',
|
'zbojow',
|
||||||
u'Arbetets Söner och Döttrar': 'arbetets soner och dottrar',
|
u'Arbetets Söner och Döttrar': 'arbetets soner och dottrar',
|
||||||
u'Björk Guðmundsdóttir': 'bjork gudmundsdottir',
|
u'Björk Guðmundsdóttir': 'bjork gudmundsdottir',
|
||||||
u'L\'Arc~en~Ciel': 'larc en ciel',
|
u'L\'Arc~en~Ciel': 'larc en ciel',
|
||||||
|
|||||||
@@ -261,7 +261,7 @@ def verify(albumid, albumpath, Kind=None, forced=False, keep_original_folder=Fal
|
|||||||
if downloaded_deezer_list:
|
if downloaded_deezer_list:
|
||||||
logger.info('Decrypting deezer tracks')
|
logger.info('Decrypting deezer tracks')
|
||||||
decrypted_deezer_list = deezloader.decryptTracks(downloaded_deezer_list)
|
decrypted_deezer_list = deezloader.decryptTracks(downloaded_deezer_list)
|
||||||
|
|
||||||
# Check if album is complete based on album duration only
|
# Check if album is complete based on album duration only
|
||||||
# (total track numbers is not determinant enough due to hidden tracks for eg)
|
# (total track numbers is not determinant enough due to hidden tracks for eg)
|
||||||
db_track_duration = 0
|
db_track_duration = 0
|
||||||
@@ -271,7 +271,7 @@ def verify(albumid, albumpath, Kind=None, forced=False, keep_original_folder=Fal
|
|||||||
db_track_duration += track['TrackDuration'] / 1000
|
db_track_duration += track['TrackDuration'] / 1000
|
||||||
except:
|
except:
|
||||||
downloaded_track_duration = False
|
downloaded_track_duration = False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
for disk_number in decrypted_deezer_list[albumpath]:
|
for disk_number in decrypted_deezer_list[albumpath]:
|
||||||
for track in decrypted_deezer_list[albumpath][disk_number].values():
|
for track in decrypted_deezer_list[albumpath][disk_number].values():
|
||||||
@@ -279,14 +279,14 @@ def verify(albumid, albumpath, Kind=None, forced=False, keep_original_folder=Fal
|
|||||||
downloaded_track_duration += int(track['DURATION'])
|
downloaded_track_duration += int(track['DURATION'])
|
||||||
except:
|
except:
|
||||||
downloaded_track_duration = False
|
downloaded_track_duration = False
|
||||||
|
|
||||||
if not downloaded_track_duration or not db_track_duration or abs(downloaded_track_duration - db_track_duration) > 240:
|
if not downloaded_track_duration or not db_track_duration or abs(downloaded_track_duration - db_track_duration) > 240:
|
||||||
logger.info("Looks like " +
|
logger.info("Looks like " +
|
||||||
os.path.basename(albumpath).decode(headphones.SYS_ENCODING, 'replace') +
|
os.path.basename(albumpath).decode(headphones.SYS_ENCODING, 'replace') +
|
||||||
" isn't complete yet (duration mismatch). Will try again on the next run")
|
" isn't complete yet (duration mismatch). Will try again on the next run")
|
||||||
return
|
return
|
||||||
|
|
||||||
downloaded_track_list = list(set(downloaded_track_list)) # Remove duplicates
|
downloaded_track_list = list(set(downloaded_track_list)) # Remove duplicates
|
||||||
|
|
||||||
# test #1: metadata - usually works
|
# test #1: metadata - usually works
|
||||||
logger.debug('Verifying metadata...')
|
logger.debug('Verifying metadata...')
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ redobj = None
|
|||||||
# Persistent Aria2 RPC object
|
# Persistent Aria2 RPC object
|
||||||
__aria2rpc_obj = None
|
__aria2rpc_obj = None
|
||||||
|
|
||||||
|
|
||||||
def getAria2RPC():
|
def getAria2RPC():
|
||||||
global __aria2rpc_obj
|
global __aria2rpc_obj
|
||||||
if not __aria2rpc_obj:
|
if not __aria2rpc_obj:
|
||||||
@@ -67,10 +68,12 @@ def getAria2RPC():
|
|||||||
)
|
)
|
||||||
return __aria2rpc_obj
|
return __aria2rpc_obj
|
||||||
|
|
||||||
|
|
||||||
def reconfigure():
|
def reconfigure():
|
||||||
global __aria2rpc_obj
|
global __aria2rpc_obj
|
||||||
__aria2rpc_obj = None
|
__aria2rpc_obj = None
|
||||||
|
|
||||||
|
|
||||||
def fix_url(s, charset="utf-8"):
|
def fix_url(s, charset="utf-8"):
|
||||||
"""
|
"""
|
||||||
Fix the URL so it is proper formatted and encoded.
|
Fix the URL so it is proper formatted and encoded.
|
||||||
@@ -896,7 +899,7 @@ def send_to_downloader(data, bestqual, album):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(u'Error sending torrent to Aria2. Are you sure it\'s running? (%s)' % e)
|
logger.error(u'Error sending torrent to Aria2. Are you sure it\'s running? (%s)' % e)
|
||||||
return
|
return
|
||||||
|
|
||||||
else:
|
else:
|
||||||
folder_name = '%s - %s [%s]' % (
|
folder_name = '%s - %s [%s]' % (
|
||||||
helpers.latinToAscii(album['ArtistName']).encode('UTF-8').replace('/', '_'),
|
helpers.latinToAscii(album['ArtistName']).encode('UTF-8').replace('/', '_'),
|
||||||
@@ -1274,6 +1277,7 @@ def verifyresult(title, artistterm, term, lossless):
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def searchDdl(album, new=False, losslessOnly=False, albumlength=None,
|
def searchDdl(album, new=False, losslessOnly=False, albumlength=None,
|
||||||
choose_specific_download=False):
|
choose_specific_download=False):
|
||||||
reldate = album['ReleaseDate']
|
reldate = album['ReleaseDate']
|
||||||
@@ -1313,7 +1317,7 @@ def searchDdl(album, new=False, losslessOnly=False, albumlength=None,
|
|||||||
logger.debug(u'Using search term: "%s"' % helpers.latinToAscii(term))
|
logger.debug(u'Using search term: "%s"' % helpers.latinToAscii(term))
|
||||||
|
|
||||||
resultlist = []
|
resultlist = []
|
||||||
|
|
||||||
# Deezer only provides lossy
|
# Deezer only provides lossy
|
||||||
if headphones.CONFIG.DEEZLOADER and not losslessOnly:
|
if headphones.CONFIG.DEEZLOADER and not losslessOnly:
|
||||||
resultlist += deezloader.searchAlbum(album['ArtistName'], album['AlbumTitle'], album['SearchTerm'], int(albumlength / 1000))
|
resultlist += deezloader.searchAlbum(album['ArtistName'], album['AlbumTitle'], album['SearchTerm'], int(albumlength / 1000))
|
||||||
|
|||||||
@@ -1587,7 +1587,7 @@ class WebInterface(object):
|
|||||||
|
|
||||||
# Reconfigure musicbrainz database connection with the new values
|
# Reconfigure musicbrainz database connection with the new values
|
||||||
mb.startmb()
|
mb.startmb()
|
||||||
|
|
||||||
# Reconfigure Aria2
|
# Reconfigure Aria2
|
||||||
searcher.reconfigure()
|
searcher.reconfigure()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user