Skip to content

Commit

Permalink
login to apple music with media-user-token instead of cookie file
Browse files Browse the repository at this point in the history
  • Loading branch information
justin025 committed Dec 24, 2024
1 parent 6aa502c commit 6400162
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 62 deletions.
1 change: 0 additions & 1 deletion src/onthespot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ def main():
account['service'] = 'youtube_music'
config.set_('accounts', cfg_copy)


# Set Application Version
version = "v1.0.5"
logger.info(f'OnTheSpot Version: {version}')
Expand Down
44 changes: 13 additions & 31 deletions src/onthespot/api/apple_music.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import base64
from http.cookiejar import MozillaCookieJar
import json
import m3u8
from pathlib import Path
Expand All @@ -19,46 +18,26 @@
WVN_KEY = base64.b64decode(b'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QrSyZcBqHO0QrdPcU35GBT7S7+IJr2AAXvnjqnb8yrtpPWN2ZW/IWUJN2z4vZ7/HV4aj3OZhkxC1DIMNyvsusUKoQQuf8gwKiEe8cFwbwFSicywlFk9la2IPe8oFShcxAzHLCCn/TIYUAvEL3/4LgaZvqWm80qCPYbgIP5HT8hPYkKWJ4WYknEWK+3InbnkzteFfGrQFCq4CCAESEGnj6Ji7LD+4o7MoHYT4jBQYjtW+kQUijgIwggEKAoIBAQDY9um1ifBRIOmkPtDZTqH+CZUBbb0eK0Cn3NHFf8MFUDzPEz+emK/OTub/hNxCJCao//pP5L8tRNUPFDrrvCBMo7Rn+iUb+mA/2yXiJ6ivqcN9Cu9i5qOU1ygon9SWZRsujFFB8nxVreY5Lzeq0283zn1Cg1stcX4tOHT7utPzFG/ReDFQt0O/GLlzVwB0d1sn3SKMO4XLjhZdncrtF9jljpg7xjMIlnWJUqxDo7TQkTytJmUl0kcM7bndBLerAdJFGaXc6oSY4eNy/IGDluLCQR3KZEQsy/mLeV1ggQ44MFr7XOM+rd+4/314q/deQbjHqjWFuVr8iIaKbq+R63ShAgMBAAEo8CISgAMii2Mw6z+Qs1bvvxGStie9tpcgoO2uAt5Zvv0CDXvrFlwnSbo+qR71Ru2IlZWVSbN5XYSIDwcwBzHjY8rNr3fgsXtSJty425djNQtF5+J2jrAhf3Q2m7EI5aohZGpD2E0cr+dVj9o8x0uJR2NWR8FVoVQSXZpad3M/4QzBLNto/tz+UKyZwa7Sc/eTQc2+ZcDS3ZEO3lGRsH864Kf/cEGvJRBBqcpJXKfG+ItqEW1AAPptjuggzmZEzRq5xTGf6or+bXrKjCpBS9G1SOyvCNF1k5z6lG8KsXhgQxL6ADHMoulxvUIihyPY5MpimdXfUdEQ5HA2EqNiNVNIO4qP007jW51yAeThOry4J22xs8RdkIClOGAauLIl0lLA4flMzW+VfQl5xYxP0E5tuhn0h+844DslU8ZF7U1dU2QprIApffXD9wgAACk26Rggy8e96z8i86/+YYyZQkc9hIdCAERrgEYCEbByzONrdRDs1MrS/ch1moV5pJv63BIKvQHGvLkaFwoMY29tcGFueV9uYW1lEgd1bmtub3duGioKCm1vZGVsX25hbWUSHEFuZHJvaWQgU0RLIGJ1aWx0IGZvciB4ODZfNjQaGwoRYXJjaGl0ZWN0dXJlX25hbWUSBng4Nl82NBodCgtkZXZpY2VfbmFtZRIOZ2VuZXJpY194ODZfNjQaIAoMcHJvZHVjdF9uYW1lEhBzZGtfcGhvbmVfeDg2XzY0GmMKCmJ1aWxkX2luZm8SVUFuZHJvaWQvc2RrX3Bob25lX3g4Nl82NC9nZW5lcmljX3g4Nl82NDo5L1BTUjEuMTgwNzIwLjAxMi80OTIzMjE0OnVzZXJkZWJ1Zy90ZXN0LWtleXMaHgoUd2lkZXZpbmVfY2RtX3ZlcnNpb24SBjE0LjAuMBokCh9vZW1fY3J5cHRvX3NlY3VyaXR5X3BhdGNoX2xldmVsEgEwMg4QASAAKA0wAEAASABQAA==')


def apple_music_add_account(file_path):
with open(file_path, 'r') as file:
first_line = file.readline().strip()
if first_line != '# Netscape HTTP Cookie File':
logger.info("The file is not a valid Netscape cookie file.")
return False

cookie_lines = file.readlines()

def apple_music_add_account(media_user_token):
cfg_copy = config.get('accounts').copy()
login_dict = {}

# Process each line to gather cookies
for line in cookie_lines[1:]: # Skip the header line
parts = line.strip().split('\t')

if len(parts) >= 7: # Ensure there are enough parts
name = parts[5] # Cookie name
value = parts[6] # Cookie value

# Add each cookie name-value pair to the login dictionary
login_dict[name] = value

new_user = {
"uuid": str(uuid.uuid4()),
"service": "apple_music",
"active": True,
"login": login_dict
"login": {
"media-user-token": media_user_token
}
}
cfg_copy.append(new_user)
config.set_('accounts', cfg_copy)
config.update()
return True


def apple_music_login_user(account):
logger.info('Logging into Apple Music account...')
try:
session = requests.Session()
session.cookies.update(account['login'])
session.cookies.update({'media-user-token': account['login']['media-user-token']})
session.headers.update(
{
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0",
Expand All @@ -78,19 +57,22 @@ def apple_music_login_user(account):
)

# Retrieve token from the homepage
home_page = session.get("https://beta.music.apple.com").text
home_page = session.get("https://music.apple.com").text
index_js_uri = re.search(r"/(assets/index-legacy-[^/]+\.js)", home_page).group(1)
index_js_page = session.get(f"https://beta.music.apple.com/{index_js_uri}").text
index_js_page = session.get(f"https://music.apple.com/{index_js_uri}").text
token = re.search('(?=eyJh)(.*?)(?=")', index_js_page).group(1)
session.headers.update({"authorization": f"Bearer {token}"})
session.params = {"l": 'en-US'}

account_data = session.get(f'{BASE_URL}/me/account?meta=subscription&challenge%5BsubscriptionCapabilities%5D=voice%2Cpremium').json()
session.cookies.update({'itua': account_data.get('meta', {}).get('subscription', {}).get('storefront', '')})

account_pool.append({
"uuid": account['uuid'],
"username": account['login']['pltvcid'],
"username": account['login']['media-user-token'],
"service": "apple_music",
"status": "active",
"account_type": "premium",
"account_type": "premium" if account_data.get('meta', {}).get('subscription', {}).get('active', '') else 'free',
"bitrate": "256k",
"login": {
"session": session
Expand All @@ -101,7 +83,7 @@ def apple_music_login_user(account):
logger.error(f"Unknown Exception: {str(e)}")
account_pool.append({
"uuid": account['uuid'],
"username": account['login']['pltvcid'],
"username": account['login']['media-user-token'],
"service": "apple_music",
"status": "error",
"account_type": "N/A",
Expand Down
1 change: 1 addition & 0 deletions src/onthespot/api/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ def generic_get_track_metadata(_, url):

return info


def generic_list_extractors():
extractors = extractor.gen_extractors()
extractor_list = []
Expand Down
42 changes: 12 additions & 30 deletions src/onthespot/gui/mainui.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,12 +252,9 @@ def reset_app_config(self):
self.__show_popup_dialog("The application setting was cleared successfully !\n Please restart the application.")


def select_dir(self, output, file=False):
def select_dir(self, output):
self.setStyleSheet(config.get('theme'))
if file:
path, _ = QFileDialog.getOpenFileName(self, 'OnTheSpot - Select File', os.path.expanduser("~"), "All Files (*)")
else:
path = QFileDialog.getExistingDirectory(self, 'OnTheSpot - Select Directory', os.path.expanduser("~"))
path = QFileDialog.getExistingDirectory(self, 'OnTheSpot - Select Directory', os.path.expanduser("~"))
if path.strip() != '':
output.setText(QDir.toNativeSeparators(path))

Expand Down Expand Up @@ -597,18 +594,22 @@ def set_login_fields(self):

# Apple Music
if self.inp_login_service.currentIndex() == 0:
self.inp_login_password.setDisabled(True)
self.inp_login_password.setDisabled(False)
self.lb_login_username.hide()
self.inp_login_username.hide()
self.lb_login_password.show()
self.inp_login_password.setPlaceholderText("Enter the path to your cookie file")
self.lb_login_password.setText(self.tr("Cookie File"))
self.inp_login_password.setPlaceholderText("Enter your apple music media-user-token")
self.lb_login_password.setText(self.tr("Media User Token"))
self.inp_login_password.show()
self.btn_login_add.clicked.disconnect()
self.btn_login_add.show()
self.btn_login_add.setText('')
self.btn_login_add.setIcon(self.get_icon('folder'))
self.btn_login_add.clicked.connect(self.add_apple_music_account_worker)
self.btn_login_add.setIcon(QIcon())
self.btn_login_add.setText(self.tr("Add Account"))
self.btn_login_add.clicked.connect(lambda:
(self.__show_popup_dialog(self.tr("Account added, please restart the app.")) or True) and
apple_music_add_account(self.inp_login_password.text()) and
self.inp_login_password.clear()
)

# Bandcamp
elif self.inp_login_service.currentIndex() == 1:
Expand Down Expand Up @@ -753,25 +754,6 @@ def set_login_fields(self):
)


def add_apple_music_account_worker(self):
session = None
self.lb_login_password.setDisabled(True)
self.btn_login_add.setDisabled(True)
self.select_dir(self.inp_login_password, file=True)
file_path = self.inp_login_password.text()
if file_path:
session = apple_music_add_account(file_path)

if session:
config.set_('parsing_acc_sn', len(account_pool))
config.update()
self.__show_popup_dialog(self.tr("Account added, please restart the app."))
self.btn_login_add.setDisabled(False)
else:
self.__show_popup_dialog(self.tr("Please enter a valid cookie path."))
self.btn_login_add.setDisabled(False)


def add_spotify_account(self):
logger.info('Add spotify account clicked ')
self.btn_login_add.setText(self.tr("Waiting..."))
Expand Down

0 comments on commit 6400162

Please sign in to comment.