From 00811882a9b4ed4ffe9d91f31802943a98019d49 Mon Sep 17 00:00:00 2001 From: "R. M" <50295204+glomatico@users.noreply.github.com> Date: Thu, 15 Dec 2022 22:54:27 -0300 Subject: [PATCH] Auto fetch authorization token It's not necessary to manually grab the authorization token anymore. --- README.md | 8 ++------ gamdl.py | 40 +++++++++++++++++++++------------------- 2 files changed, 23 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index cf224b5..af91c96 100644 --- a/README.md +++ b/README.md @@ -30,12 +30,8 @@ Some new features that I added: * mp4decrypt (Windows): https://drive.google.com/open?id=1K6Y98zSfHowALq4FJ6MYrhg1oFBltci9 * MP4Box (Linux): TBD * mp4decrypt (Linux): https://drive.google.com/open?id=16qZfStVibIGgH3xSKmAE1Wuf17DTDR8q -4. Create a folder called `login` on the same folder as the script and put your `cookies.txt` and `token.txt` files there - * You can get your cookies by using this Google Chrome extension on Apple Music website: https://chrome.google.com/webstore/detail/cookies-txt/njabckikapfpffapmjgojcnbfjonfjfg. Make sure to export it as `cookies.txt` and put it on the `login` folder as described above. - * You can get your token by looking at the network requests on Apple Music website. - * On Google Chrome, you can do this by pressing F12 on Apple Music website and clicking on the "Network" tab. Then, start navigating throught Apple Music website, filter the requests by "amp-api" and click on one that has `authorization` on the "Request Headers" section. Copy the value of the `authorization` header, paste it on a text file and save it as `token.txt` on the `login` folder. - ![Google Chrome token grab example](https://i.imgur.com/9YyfGn4.png) - * If you have previously used the old version of this script, you can just copy your `cookies.txt` and `token.txt` files from the old version to the `login` folder. You will have to add `Bearer ` before your token on the `token.txt` file. +4. Export your Apple Music cookies as `cookies.txt` and put it in the same folder as the script + * You can export your cookies by using this Google Chrome extension on Apple Music website: https://chrome.google.com/webstore/detail/cookies-txt/njabckikapfpffapmjgojcnbfjonfjfg. Make sure to be logged in. 5. Put your L3 CDM (`device_client_id_blob` and `device_private_key` files) on `pywidevine/L3/cdm/devices/android_generic` folder * You can get your L3 CDM by using wvdumper: https://github.com/wvdumper/dumper diff --git a/gamdl.py b/gamdl.py index 8ee1a4d..ed15fcf 100644 --- a/gamdl.py +++ b/gamdl.py @@ -22,24 +22,22 @@ import traceback import subprocess class Gamdl: - def __init__(self, disable_music_video_skip, auth_path, temp_path, prefer_hevc, final_path): + def __init__(self, disable_music_video_skip, cookies_location, temp_path, prefer_hevc, final_path): self.disable_music_video_skip = disable_music_video_skip - self.auth_path = auth_path - self.temp_path = temp_path + self.cookies_location = Path(cookies_location) + self.temp_path = Path(temp_path) self.prefer_hevc = prefer_hevc - self.final_path = final_path + self.final_path = Path(final_path) self.login() def login(self): cookies = {} - with open(Path(self.auth_path) / 'cookies.txt', 'r') as f: + with open(self.cookies_location, 'r') as f: for l in f: if not re.match(r"^#", l) and not re.match(r"^\n", l): line_fields = l.strip().replace('"', '"').split('\t') cookies[line_fields[5]] = line_fields[6] - with open(Path(self.auth_path) / 'token.txt', 'r') as f: - token = f.read() self.session = requests.Session() self.session.verify = False urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) @@ -49,7 +47,6 @@ class Gamdl: "Accept": "application/json", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate, br", - "authorization": token, "content-type": "application/json", "Media-User-Token": self.session.cookies.get_dict()["media-user-token"], "x-apple-renewal": "true", @@ -60,6 +57,11 @@ class Gamdl: "Sec-Fetch-Site": "same-site", 'origin': 'https://beta.music.apple.com' }) + r = self.session.get('https://beta.music.apple.com') + index_js = re.search('(?<=index\.)(.*?)(?=\.js")', r.text).group(1) + r = self.session.get(f'https://beta.music.apple.com/assets/index.{index_js}.js') + access_token = re.search('(?=eyJh)(.*?)(?=")', r.text).group(1) + self.session.headers.update({"authorization": f'Bearer {access_token}'}) self.country = cookies['itua'].lower() self.storefront = getattr(storefront_ids, self.country.upper()) @@ -128,15 +130,15 @@ class Gamdl: def get_encrypted_location(self, extension, track_id,): - return Path(self.temp_path) / f'{track_id}_encrypted{extension}' + return self.temp_path / f'{track_id}_encrypted{extension}' def get_decrypted_location(self, extension, track_id): - return Path(self.temp_path) / f'{track_id}_decrypted{extension}' + return self.temp_path / f'{track_id}_decrypted{extension}' def get_fixed_location(self, extension, track_id): - return Path(self.temp_path) / f'{track_id}_fixed{extension}' + return self.temp_path / f'{track_id}_fixed{extension}' def download(self, encrypted_location, stream_url): @@ -337,7 +339,7 @@ class Gamdl: def get_final_location(self, file_extension, tags): - final_location = Path(self.final_path) + final_location = self.final_path if 'plID' in tags.keys(): if 'cpil' in tags.keys() and tags['cpil']: final_location /= f'Compilations/{self.get_sanizated_string(tags["©alb"][0], True)}' @@ -412,11 +414,11 @@ if __name__ == '__main__': metavar = '' ) parser.add_argument( - '-a', - '--auth-path', - default = 'login', - help = 'Auth Path.', - metavar = '' + '-c', + '--cookies-location', + default = 'cookies.txt', + help = 'Cookies location.', + metavar = '' ) parser.add_argument( '-m', @@ -467,7 +469,7 @@ if __name__ == '__main__': 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.auth_path, args.temp_path, args.prefer_hevc, args.final_path) + gamdl = Gamdl(args.disable_music_video_skip, args.cookies_location, args.temp_path, args.prefer_hevc, args.final_path) error_count = 0 download_queue = [] for i in range(len(args.url)): @@ -529,6 +531,6 @@ 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: + if not args.skip_cleanup and gamdl.temp_path.exists(): shutil.rmtree(gamdl.temp_path) print(f'Finished ({error_count} error(s)).')