mirror of
https://github.com/Wojtek242/qobuz-dl.git
synced 2024-11-25 12:35:25 +01:00
mp3 and queue support added
This commit is contained in:
parent
fd1e0b8ed9
commit
f30f75849a
54
main.py
54
main.py
@ -1,6 +1,8 @@
|
|||||||
from qo_utils.search import Search
|
from qo_utils.search import Search
|
||||||
from qo_utils import downloader
|
from qo_utils import downloader
|
||||||
|
from pick import pick
|
||||||
import argparse
|
import argparse
|
||||||
|
import itertools
|
||||||
import re
|
import re
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
@ -15,7 +17,7 @@ def getArgs():
|
|||||||
parser.add_argument("-i", action="store_true",
|
parser.add_argument("-i", action="store_true",
|
||||||
help="run Qo-Dl-curses on URL input mode")
|
help="run Qo-Dl-curses on URL input mode")
|
||||||
parser.add_argument("-q", metavar="int", default=6,
|
parser.add_argument("-q", metavar="int", default=6,
|
||||||
help="FLAC quality (6, 7, 27) (default: 6)")
|
help="audioquality (5, 6, 7, 27) (default: 6)")
|
||||||
parser.add_argument("-l", metavar="int", default=10,
|
parser.add_argument("-l", metavar="int", default=10,
|
||||||
help="limit of search results by type (default: 10)")
|
help="limit of search results by type (default: 10)")
|
||||||
parser.add_argument("-d", metavar="PATH", default='Qobuz Downloads',
|
parser.add_argument("-d", metavar="PATH", default='Qobuz Downloads',
|
||||||
@ -43,14 +45,15 @@ def get_id(url):
|
|||||||
'*-?/|user/library/favorites/)(\w+)', url).group(1)
|
'*-?/|user/library/favorites/)(\w+)', url).group(1)
|
||||||
|
|
||||||
|
|
||||||
def searchSelected(Qz, path, start):
|
def searchSelected(Qz, path, albums, ids, types, quality):
|
||||||
q = ['6', '7', '27']
|
q = ['5', '6', '7', '27']
|
||||||
quality = q[start.quality[1]]
|
quality = q[quality[1]]
|
||||||
for i in start.Selected:
|
for alb, id_, type_ in zip(albums, ids, types):
|
||||||
if start.Types[i[1]]:
|
for i in alb:
|
||||||
downloader.iterateIDs(Qz, start.IDs[i[1]], path, quality, True)
|
if type_[i[1]]:
|
||||||
else:
|
downloader.iterateIDs(Qz, id_[i[1]], path, quality, True)
|
||||||
downloader.iterateIDs(Qz, start.IDs[i[1]], path, quality, False)
|
else:
|
||||||
|
downloader.iterateIDs(Qz, id_[i[1]], path, quality, False)
|
||||||
|
|
||||||
|
|
||||||
def fromUrl(Qz, path, link, quality):
|
def fromUrl(Qz, path, link, quality):
|
||||||
@ -64,13 +67,34 @@ def fromUrl(Qz, path, link, quality):
|
|||||||
|
|
||||||
def interactive(Qz, path, limit, tracks=True):
|
def interactive(Qz, path, limit, tracks=True):
|
||||||
while True:
|
while True:
|
||||||
|
Albums, Types, IDs = [], [], []
|
||||||
try:
|
try:
|
||||||
query = input("\nEnter your search: [Ctrl + c to quit]\n- ")
|
while True:
|
||||||
print('Searching...')
|
query = input("\nEnter your search: [Ctrl + c to quit]\n- ")
|
||||||
start = Search(Qz, query, limit)
|
print('Searching...')
|
||||||
start.getResults(tracks)
|
start = Search(Qz, query, limit)
|
||||||
start.pickResults()
|
start.getResults(tracks)
|
||||||
searchSelected(Qz, path, start)
|
Types.append(start.Types)
|
||||||
|
IDs.append(start.IDs)
|
||||||
|
|
||||||
|
title = ('Select [space] the item(s) you want to download '
|
||||||
|
'(one or more)\nPress Ctrl + c to quit\n')
|
||||||
|
Selected = pick(start.Total, title,
|
||||||
|
multiselect=True, min_selection_count=1)
|
||||||
|
Albums.append(Selected)
|
||||||
|
|
||||||
|
y_n = pick(['Yes', 'No'], 'Items were added to queue to '
|
||||||
|
'be downloaded. Keep searching?')
|
||||||
|
if y_n[0][0] == 'N':
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
|
||||||
|
desc = ('Select [intro] the quality (the quality will be automat'
|
||||||
|
'ically\ndowngraded if the selected is not found)')
|
||||||
|
Qualits = ['320', 'Lossless', 'Hi-res =< 96kHz', 'Hi-Res > 96 kHz']
|
||||||
|
quality = pick(Qualits, desc)
|
||||||
|
searchSelected(Qz, path, Albums, IDs, Types, quality)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
sys.exit('\nBye')
|
sys.exit('\nBye')
|
||||||
|
|
||||||
|
@ -36,11 +36,16 @@ def getCover(i, dirn):
|
|||||||
|
|
||||||
|
|
||||||
# Download and tag a file
|
# Download and tag a file
|
||||||
def downloadItem(dirn, count, parse, meta, album, url, is_track):
|
def downloadItem(dirn, count, parse, meta, album, url, is_track, mp3):
|
||||||
fname = '{}/{:02}.flac'.format(dirn, count)
|
if mp3:
|
||||||
|
fname = '{}/{:02}.mp3'.format(dirn, count)
|
||||||
|
func = metadata.tag_mp3
|
||||||
|
else:
|
||||||
|
fname = '{}/{:02}.flac'.format(dirn, count)
|
||||||
|
func = metadata.tag_flac
|
||||||
desc = getDesc(parse, meta)
|
desc = getDesc(parse, meta)
|
||||||
req_tqdm(url, fname, desc)
|
req_tqdm(url, fname, desc)
|
||||||
metadata.iterateTag(fname, dirn, meta, album, is_track)
|
func(fname, dirn, meta, album, is_track)
|
||||||
|
|
||||||
|
|
||||||
# Iterate over IDs by type calling downloadItem
|
# Iterate over IDs by type calling downloadItem
|
||||||
@ -60,17 +65,20 @@ def iterateIDs(client, id, path, quality, album=False):
|
|||||||
parse = client.get_track_url(i['id'], quality)
|
parse = client.get_track_url(i['id'], quality)
|
||||||
url = parse['url']
|
url = parse['url']
|
||||||
|
|
||||||
if 'sample' not in parse and '.mp3' not in parse:
|
if 'sample' not in parse:
|
||||||
downloadItem(dirn, count, parse, i, meta, url, False)
|
if int(quality) == 5:
|
||||||
|
downloadItem(dirn, count, parse, i, meta, url, False, True)
|
||||||
|
else:
|
||||||
|
downloadItem(dirn, count, parse, i, meta, url, False, False)
|
||||||
else:
|
else:
|
||||||
print('Demo or MP3. Skipping')
|
print('Demo. Skipping')
|
||||||
|
|
||||||
count = count + 1
|
count = count + 1
|
||||||
else:
|
else:
|
||||||
parse = client.get_track_url(id, quality)
|
parse = client.get_track_url(id, quality)
|
||||||
url = parse['url']
|
url = parse['url']
|
||||||
|
|
||||||
if 'sample' not in parse and '.mp3' not in parse:
|
if 'sample' not in parse:
|
||||||
meta = client.get_track_meta(id)
|
meta = client.get_track_meta(id)
|
||||||
print('\nDownloading: {}\n'.format(meta['title']))
|
print('\nDownloading: {}\n'.format(meta['title']))
|
||||||
dirT = (meta['album']['artist']['name'],
|
dirT = (meta['album']['artist']['name'],
|
||||||
@ -79,8 +87,11 @@ def iterateIDs(client, id, path, quality, album=False):
|
|||||||
dirn = path + '{} - {} [{}]'.format(*dirT)
|
dirn = path + '{} - {} [{}]'.format(*dirT)
|
||||||
mkDir(dirn)
|
mkDir(dirn)
|
||||||
getCover(meta['album']['image']['large'], dirn)
|
getCover(meta['album']['image']['large'], dirn)
|
||||||
downloadItem(dirn, count, parse, meta, meta, url, True)
|
if int(quality) == 5:
|
||||||
|
downloadItem(dirn, count, parse, i, meta, url, False, True)
|
||||||
|
else:
|
||||||
|
downloadItem(dirn, count, parse, i, meta, url, False, False)
|
||||||
else:
|
else:
|
||||||
print('Demo or MP3. Skipping')
|
print('Demo. Skipping')
|
||||||
|
|
||||||
print('\nCompleted\n')
|
print('\nCompleted\n')
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
from mutagen.flac import FLAC
|
from mutagen.flac import FLAC
|
||||||
|
from mutagen.mp3 import EasyMP3
|
||||||
from pathvalidate import sanitize_filename
|
from pathvalidate import sanitize_filename
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
def iterateTag(file, path, d, album, istrack=True):
|
def tag_flac(file, path, d, album, istrack=True):
|
||||||
audio = FLAC(file)
|
audio = FLAC(file)
|
||||||
|
|
||||||
audio['TITLE'] = d['title'] # TRACK TITLE
|
audio['TITLE'] = d['title'] # TRACK TITLE
|
||||||
@ -26,7 +27,7 @@ def iterateTag(file, path, d, album, istrack=True):
|
|||||||
audio['ALBUMARTIST'] = d['album']['artist']['name'] # ALBUM ARTIST
|
audio['ALBUMARTIST'] = d['album']['artist']['name'] # ALBUM ARTIST
|
||||||
audio['TRACKTOTAL'] = str(d['album']['tracks_count']) # TRACK TOTAL
|
audio['TRACKTOTAL'] = str(d['album']['tracks_count']) # TRACK TOTAL
|
||||||
audio['ALBUM'] = d['album']['title'] # ALBUM TITLE
|
audio['ALBUM'] = d['album']['title'] # ALBUM TITLE
|
||||||
audio['YEAR'] = d['album']['release_date_original'].split('-')[0] # YEAR
|
audio['YEAR'] = d['album']['release_date_original'].split('-')[0]
|
||||||
else:
|
else:
|
||||||
audio['GENRE'] = ', '.join(album['genres_list']) # GENRE
|
audio['GENRE'] = ', '.join(album['genres_list']) # GENRE
|
||||||
audio['ALBUMARTIST'] = album['artist']['name'] # ALBUM ARTIST
|
audio['ALBUMARTIST'] = album['artist']['name'] # ALBUM ARTIST
|
||||||
@ -37,3 +38,36 @@ def iterateTag(file, path, d, album, istrack=True):
|
|||||||
audio.save()
|
audio.save()
|
||||||
title = sanitize_filename(d['title'])
|
title = sanitize_filename(d['title'])
|
||||||
os.rename(file, '{}/{:02}. {}.flac'.format(path, d['track_number'], title))
|
os.rename(file, '{}/{:02}. {}.flac'.format(path, d['track_number'], title))
|
||||||
|
|
||||||
|
|
||||||
|
def tag_mp3(file, path, d, album, istrack=True):
|
||||||
|
audio = EasyMP3(file)
|
||||||
|
|
||||||
|
audio['title'] = d['title']
|
||||||
|
audio['tracknumber'] = str(d['track_number'])
|
||||||
|
try:
|
||||||
|
audio['composer'] = d['composer']['name']
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
audio['artist'] = d['performer']['name'] # TRACK ARTIST
|
||||||
|
except KeyError:
|
||||||
|
if istrack:
|
||||||
|
audio['artist'] = d['album']['artist']['name'] # TRACK ARTIST
|
||||||
|
else:
|
||||||
|
audio['artist'] = album['artist']['name']
|
||||||
|
|
||||||
|
if istrack:
|
||||||
|
audio['genre'] = ', '.join(d['album']['genres_list']) # GENRE
|
||||||
|
audio['albumartist'] = d['album']['artist']['name'] # ALBUM ARTIST
|
||||||
|
audio['album'] = d['album']['title'] # ALBUM TITLE
|
||||||
|
audio['date'] = d['album']['release_date_original'].split('-')[0]
|
||||||
|
else:
|
||||||
|
audio['GENRE'] = ', '.join(album['genres_list']) # GENRE
|
||||||
|
audio['albumartist'] = album['artist']['name'] # ALBUM ARTIST
|
||||||
|
audio['album'] = album['title'] # ALBUM TITLE
|
||||||
|
audio['date'] = album['release_date_original'].split('-')[0] # YEAR
|
||||||
|
|
||||||
|
audio.save()
|
||||||
|
title = sanitize_filename(d['title'])
|
||||||
|
os.rename(file, '{}/{:02}. {}.mp3'.format(path, d['track_number'], title))
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
import time
|
import time
|
||||||
import sys
|
|
||||||
from pick import pick
|
|
||||||
|
|
||||||
|
|
||||||
class Search:
|
class Search:
|
||||||
@ -41,16 +39,3 @@ class Search:
|
|||||||
self.itResults(self.Albums)
|
self.itResults(self.Albums)
|
||||||
if tracks:
|
if tracks:
|
||||||
self.itResults(self.Tracks)
|
self.itResults(self.Tracks)
|
||||||
|
|
||||||
def pickResults(self):
|
|
||||||
title = ('Select [space] the item(s) you want to download '
|
|
||||||
'(one or more)\nPress Ctrl + c to quit\n')
|
|
||||||
quality = ('Select [intro] the quality (the quality will be automat'
|
|
||||||
'ically\ndowngraded if the selected is not found)')
|
|
||||||
Qualitys = ['Lossless', 'Hi-res =< 96kHz', 'Hi-Res > 96 kHz']
|
|
||||||
try:
|
|
||||||
self.Selected = pick(self.Total, title,
|
|
||||||
multiselect=True, min_selection_count=1)
|
|
||||||
self.quality = pick(Qualitys, quality)
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
sys.exit('Bye')
|
|
||||||
|
Loading…
Reference in New Issue
Block a user