Small changes

This commit is contained in:
R. M
2023-01-03 14:32:52 -03:00
parent ecfdcf434a
commit ecbff9708c
2 changed files with 96 additions and 64 deletions
+91 -59
View File
@@ -3,7 +3,6 @@ import re
import requests
import urllib3
import storefront_ids
import json
import m3u8
from yt_dlp import YoutubeDL
from pywidevine.L3.decrypt.wvdecrypt import WvDecrypt
@@ -22,12 +21,15 @@ import traceback
import subprocess
class Gamdl:
def __init__(self, disable_music_video_skip, cookies_location, temp_path, prefer_hevc, final_path):
def __init__(self, disable_music_video_skip, cookies_location, temp_path, prefer_hevc, final_path, skip_cleanup, print_video_playlist, no_lrc):
self.disable_music_video_skip = disable_music_video_skip
self.cookies_location = Path(cookies_location)
self.temp_path = Path(temp_path)
self.prefer_hevc = prefer_hevc
self.final_path = Path(final_path)
self.skip_cleanup = skip_cleanup
self.print_video_playlist = print_video_playlist
self.no_lrc = no_lrc
self.login()
@@ -103,15 +105,18 @@ class Gamdl:
def get_webplayback(self, track_id):
response = self.session.post(
'https://play.itunes.apple.com/WebObjects/MZPlay.woa/wa/webPlayback',
json.dumps({
json = {
'salableAdamId': track_id
})
}
).json()["songList"][0]
return response
def get_playlist_music_video(self, webplayback):
return m3u8.load(webplayback['hls-playlist-url'])
playlist = m3u8.load(webplayback['hls-playlist-url'])
if self.print_video_playlist:
print(playlist.dumps())
return playlist
def get_stream_url_song(self, webplayback):
@@ -157,14 +162,14 @@ class Gamdl:
def get_license_b64(self, challenge, track_uri, track_id):
return self.session.post(
'https://play.itunes.apple.com/WebObjects/MZPlay.woa/wa/acquireWebPlaybackLicense',
json.dumps({
json = {
'challenge': challenge,
'key-system': 'com.widevine.alpha',
'uri': track_uri,
'adamId': track_id,
'isLibrary': False,
'user-initiated': True
})
}
).json()['license']
@@ -253,7 +258,6 @@ class Gamdl:
'soar': [metadata['sort-artist']],
'soal': [metadata['sort-album']],
'sonm': [metadata['sort-name']],
'\xa9alb': [metadata['playlistName']],
'\xa9ART': [metadata['artistName']],
'geID': [metadata['genreId']],
'atID': [int(metadata['artistId'])],
@@ -363,19 +367,40 @@ class Gamdl:
def fixup_music_video(self, decrypted_location_audio, decrypted_location_video, fixed_location, final_location):
os.makedirs(final_location.parents[0], exist_ok = True)
subprocess.check_output(['MP4Box', '-quiet', '-add', decrypted_location_audio, '-add', decrypted_location_video, '-itags', 'artist=placeholder', '-new', fixed_location])
subprocess.check_output([
'MP4Box',
'-quiet',
'-add',
decrypted_location_audio,
'-add',
decrypted_location_video,
'-itags',
'artist=placeholder',
'-new',
fixed_location
])
shutil.copy(fixed_location, final_location)
def fixup_song(self, decrypted_location, fixed_location, final_location):
os.makedirs(final_location.parents[0], exist_ok = True)
subprocess.check_output(['MP4Box', '-quiet', '-add', decrypted_location, '-itags', 'album=placeholder', '-new', fixed_location])
subprocess.check_output([
'MP4Box',
'-quiet',
'-add',
decrypted_location,
'-itags',
'album=placeholder',
'-new',
fixed_location
])
shutil.copy(fixed_location, final_location)
def make_lrc(self, final_location, lyrics):
with open(final_location.with_suffix('.lrc'), 'w', encoding = 'utf8') as f:
f.write(lyrics[1])
if lyrics and lyrics[1] and not self.no_lrc:
with open(final_location.with_suffix('.lrc'), 'w', encoding = 'utf8') as f:
f.write(lyrics[1])
def apply_tags(self, final_location, tags):
@@ -385,6 +410,11 @@ class Gamdl:
file.save(final_location)
def cleanup(self):
if self.temp_path.exists() and not self.skip_cleanup:
shutil.rmtree(self.temp_path)
if __name__ == '__main__':
if not shutil.which('mp4decrypt'):
raise Exception('mp4decrypt is not on PATH.')
@@ -397,6 +427,13 @@ if __name__ == '__main__':
nargs='*',
metavar = '<url>'
)
parser.add_argument(
'-u',
'--urls-txt',
help = 'Read URLs from a text file.',
nargs = '?',
metavar = '<txt_file>'
)
parser.add_argument(
'-f',
'--final-path',
@@ -454,25 +491,27 @@ if __name__ == '__main__':
action = 'store_true',
help = 'Print Video M3U8 Playlist.'
)
parser.add_argument(
'-u',
'--urls-txt',
help = 'Read URLs from a text file.',
nargs = '?',
metavar = '<txt_file>'
)
args = parser.parse_args()
if not args.url and not args.urls_txt:
parser.error('you must specify an url or a text file using -u/--urls-txt.')
if args.urls_txt:
with open(args.urls_txt, 'r', encoding = 'utf8') as f:
args.url = f.read().splitlines()
gamdl = Gamdl(args.disable_music_video_skip, args.cookies_location, args.temp_path, args.prefer_hevc, args.final_path)
dl = Gamdl(
args.disable_music_video_skip,
args.cookies_location,
args.temp_path,
args.prefer_hevc,
args.final_path,
args.skip_cleanup,
args.print_video_playlist,
args.no_lrc
)
error_count = 0
download_queue = []
for i in range(len(args.url)):
try:
download_queue.append(gamdl.get_download_queue(args.url[i].strip()))
download_queue.append(dl.get_download_queue(args.url[i].strip()))
except KeyboardInterrupt:
exit(1)
except:
@@ -480,48 +519,42 @@ if __name__ == '__main__':
print(f'* Failed to check URL {i + 1}.')
if args.print_exceptions:
traceback.print_exc()
if not download_queue:
print('* Failed to check all URLs.')
exit(1)
for i in range(len(download_queue)):
for j in range(len(download_queue[i])):
print(f'Downloading "{download_queue[i][j]["title"]}" (track {j + 1} from URL {i + 1})...')
track_id = download_queue[i][j]['track_id']
try:
webplayback = gamdl.get_webplayback(track_id)
webplayback = dl.get_webplayback(track_id)
if 'alt_track_id' in download_queue[i][j]:
playlist = gamdl.get_playlist_music_video(webplayback)
if args.print_video_playlist:
print(playlist.dumps())
stream_url_audio = gamdl.get_stream_url_music_video_audio(playlist)
encrypted_location_audio = gamdl.get_encrypted_location('.m4a', track_id)
gamdl.download(encrypted_location_audio, stream_url_audio)
decrypted_location_audio = gamdl.get_decrypted_location('.m4a', track_id)
gamdl.decrypt_music_video(decrypted_location_audio, encrypted_location_audio, stream_url_audio, track_id)
stream_url_video = gamdl.get_stream_url_music_video_video(playlist)
encrypted_location_video = gamdl.get_encrypted_location('.m4v', track_id)
gamdl.download(encrypted_location_video, stream_url_video)
decrypted_location_video = gamdl.get_decrypted_location('.m4v', track_id)
gamdl.decrypt_music_video(decrypted_location_video, encrypted_location_video, stream_url_video, track_id)
tags = gamdl.get_tags_music_video(download_queue[i][j]['alt_track_id'])
fixed_location = gamdl.get_fixed_location('.m4v', track_id)
final_location = gamdl.get_final_location('.m4v', tags)
gamdl.fixup_music_video(decrypted_location_audio, decrypted_location_video, fixed_location, final_location)
gamdl.apply_tags(final_location, tags)
playlist = dl.get_playlist_music_video(webplayback)
stream_url_audio = dl.get_stream_url_music_video_audio(playlist)
encrypted_location_audio = dl.get_encrypted_location('.m4a', track_id)
dl.download(encrypted_location_audio, stream_url_audio)
decrypted_location_audio = dl.get_decrypted_location('.m4a', track_id)
dl.decrypt_music_video(decrypted_location_audio, encrypted_location_audio, stream_url_audio, track_id)
stream_url_video = dl.get_stream_url_music_video_video(playlist)
encrypted_location_video = dl.get_encrypted_location('.m4v', track_id)
dl.download(encrypted_location_video, stream_url_video)
decrypted_location_video = dl.get_decrypted_location('.m4v', track_id)
dl.decrypt_music_video(decrypted_location_video, encrypted_location_video, stream_url_video, track_id)
tags = dl.get_tags_music_video(download_queue[i][j]['alt_track_id'])
fixed_location = dl.get_fixed_location('.m4v', track_id)
final_location = dl.get_final_location('.m4v', tags)
dl.fixup_music_video(decrypted_location_audio, decrypted_location_video, fixed_location, final_location)
dl.apply_tags(final_location, tags)
else:
stream_url = gamdl.get_stream_url_song(webplayback)
encrypted_location = gamdl.get_encrypted_location('.m4a', track_id)
gamdl.download(encrypted_location, stream_url)
decrypted_location = gamdl.get_decrypted_location('.m4a', track_id)
gamdl.decrypt_song(decrypted_location, encrypted_location, stream_url, track_id)
lyrics = gamdl.get_lyrics(track_id)
tags = gamdl.get_tags_song(webplayback, lyrics)
fixed_location = gamdl.get_fixed_location('.m4a', track_id)
final_location = gamdl.get_final_location('.m4a', tags)
gamdl.fixup_song(decrypted_location, fixed_location, final_location)
if not args.no_lrc and lyrics and lyrics[1]:
gamdl.make_lrc(final_location, lyrics)
gamdl.apply_tags(final_location, tags)
stream_url = dl.get_stream_url_song(webplayback)
encrypted_location = dl.get_encrypted_location('.m4a', track_id)
dl.download(encrypted_location, stream_url)
decrypted_location = dl.get_decrypted_location('.m4a', track_id)
dl.decrypt_song(decrypted_location, encrypted_location, stream_url, track_id)
lyrics = dl.get_lyrics(track_id)
tags = dl.get_tags_song(webplayback, lyrics)
fixed_location = dl.get_fixed_location('.m4a', track_id)
final_location = dl.get_final_location('.m4a', tags)
dl.fixup_song(decrypted_location, fixed_location, final_location)
dl.make_lrc(final_location, lyrics)
dl.apply_tags(final_location, tags)
except KeyboardInterrupt:
exit(1)
except:
@@ -529,6 +562,5 @@ if __name__ == '__main__':
print(f'* Failed to download "{download_queue[i][j]["title"]}" (track {j + 1} from URL {i + 1}).')
if args.print_exceptions:
traceback.print_exc()
if not args.skip_cleanup and gamdl.temp_path.exists():
shutil.rmtree(gamdl.temp_path)
print(f'Finished ({error_count} error(s)).')
dl.cleanup()
print(f'Done ({error_count} error(s)).')
+5 -5
View File
@@ -1,7 +1,7 @@
class WvDecryptConfig(object):
def __init__(self, decrypted_download_location, encrypted_download_location, init_data_b64):
self.decrypted_download_location = str(decrypted_download_location)
self.encrypted_download_location = str(encrypted_download_location)
def __init__(self, decrypted_location, encrypted_location, init_data_b64):
self.decrypted_location = str(decrypted_location)
self.encrypted_location = str(encrypted_location)
self.init_data_b64 = init_data_b64
def build_commandline_list(self, keys):
@@ -12,6 +12,6 @@ class WvDecryptConfig(object):
commandline.append('--key')
default_KID = 1
commandline.append('{}:{}'.format(str(default_KID), key.key.hex()))
commandline.append(self.encrypted_download_location)
commandline.append(self.decrypted_download_location)
commandline.append(self.encrypted_location)
commandline.append(self.decrypted_location)
return commandline