Auto fetch authorization token

It's not necessary to manually grab the authorization token anymore.
This commit is contained in:
R. M
2022-12-15 22:54:27 -03:00
parent 5b9a047448
commit 00811882a9
2 changed files with 23 additions and 25 deletions
+2 -6
View File
@@ -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
+21 -19
View File
@@ -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 = '<temp_path>'
)
parser.add_argument(
'-a',
'--auth-path',
default = 'login',
help = 'Auth Path.',
metavar = '<auth_path>'
'-c',
'--cookies-location',
default = 'cookies.txt',
help = 'Cookies location.',
metavar = '<cookies_location>'
)
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)).')