- Fixed normal username/password login
- Fixed referer on datadome request - Added priority to tidal_token stored in config.json
This commit is contained in:
41
interface.py
41
interface.py
@@ -73,17 +73,10 @@ class ModuleInterface:
|
||||
# load all saved sessions (TV, Mobile Atmos, Mobile Default)
|
||||
saved_sessions = module_controller.temporary_settings_controller.read('sessions')
|
||||
|
||||
tidal_token = module_controller.module_settings.get('tidal_token')
|
||||
|
||||
if not saved_sessions:
|
||||
saved_sessions = {}
|
||||
else:
|
||||
# print available stored sessions and their country code
|
||||
country_codes = set(entry['country_code'] for entry in saved_sessions.values())
|
||||
sessions_list = ' - '.join(saved_sessions.keys())
|
||||
if len(country_codes) == 1:
|
||||
result = f"Using saved sessions: {sessions_list} ({country_codes.pop()})"
|
||||
else:
|
||||
result = "Using saved sessions: " + " - ".join(f"{key} ({entry['country_code']})" for key, entry in saved_sessions.items())
|
||||
print(result)
|
||||
|
||||
if not self.settings['enable_mobile']:
|
||||
self.available_sessions = [SessionType.TV.name]
|
||||
@@ -117,25 +110,25 @@ class ModuleInterface:
|
||||
'tv': SessionType.TV.name,
|
||||
'2': SessionType.MOBILE_DEFAULT.name,
|
||||
'mobile': SessionType.MOBILE_DEFAULT.name,
|
||||
}[input_str.lower()]
|
||||
}[input_str]
|
||||
except KeyError:
|
||||
self.print(f'{module_information.service_name}: Invalid choice, try again')
|
||||
|
||||
# auto use tidal_token if present in config.json else prompt it
|
||||
while True:
|
||||
reply = input(' Use a tidal_token instead of email/password? (Y/n): ').strip().lower()
|
||||
if reply in ["y", "yes"]:
|
||||
tidal_token = module_controller.module_settings['tidal_token']
|
||||
if not tidal_token:
|
||||
tidal_token = input(' No stored tidal_token detected, paste it here: ').strip()
|
||||
break
|
||||
elif reply in ["n", "no"]:
|
||||
tidal_token = None
|
||||
break
|
||||
else:
|
||||
self.print(f'{module_information.service_name}: Reply with (Y)es or (N)o')
|
||||
|
||||
login_session = auth_and_save_session(self.init_session(login_session_type), login_session_type, tidal_token)
|
||||
|
||||
print(f"Account Country: {login_session.country_code}")
|
||||
self.print(f"Account Country: {login_session.country_code}")
|
||||
|
||||
for session_type in self.available_sessions:
|
||||
sessions[session_type] = self.init_session(session_type)
|
||||
@@ -160,20 +153,36 @@ class ModuleInterface:
|
||||
# check for a valid subscription
|
||||
subscription = self.check_subscription(sessions[session_type].get_subscription())
|
||||
if not subscription:
|
||||
confirm = input(' Do you want to relogin? [Y/n]: ')
|
||||
confirm = input(' Do you want to relogin? [Y/n]: ').strip().lower()
|
||||
|
||||
if confirm.upper() == 'N':
|
||||
if confirm in ('n', 'no'):
|
||||
self.print('Exiting...')
|
||||
exit()
|
||||
|
||||
# reset saved sessions and loop back to login
|
||||
saved_sessions = {}
|
||||
relogin_requested = True
|
||||
break
|
||||
|
||||
if not login_session:
|
||||
login_session = sessions[session_type]
|
||||
|
||||
# check if tidal_token in config.json matches any saved refresh_token to swap between them easily
|
||||
if tidal_token and not relogin_requested and tidal_token not in [v.get('refresh_token') for v in saved_sessions.values()]:
|
||||
confirm = input(' Stored tidal_token differs from setting.json - Do you want to relogin? [Y/n]: ').strip().lower()
|
||||
if confirm in ('y', 'yes'):
|
||||
saved_sessions = {}
|
||||
continue # Restart the while loop to re-authenticate
|
||||
|
||||
if saved_sessions:
|
||||
# print available stored sessions and their country code
|
||||
country_codes = set(entry['country_code'] for entry in saved_sessions.values())
|
||||
sessions_list = ' - '.join(saved_sessions.keys())
|
||||
if len(country_codes) == 1:
|
||||
result = f"Using saved sessions: {sessions_list} ({country_codes.pop()})"
|
||||
else:
|
||||
result = "Using saved sessions: " + " - ".join(f"{key} ({entry['country_code']})" for key, entry in saved_sessions.items())
|
||||
self.print(result)
|
||||
break
|
||||
|
||||
# only needed for region locked albums where the track is available but force_album_format is used
|
||||
@@ -221,7 +230,7 @@ class ModuleInterface:
|
||||
def check_subscription(self, subscription: str) -> bool:
|
||||
# returns true if "disable_subscription_checks" is enabled or subscription is HIFI (Plus)
|
||||
if not self.disable_subscription_check and subscription not in {'HIFI', 'PREMIUM', 'PREMIUM_PLUS'}:
|
||||
self.print(f'{module_information.service_name}: Account does not have a HiFi (Plus) subscription, '
|
||||
self.print(f'{module_information.service_name}: Account is expired or does not have a HiFi (Plus) subscription, '
|
||||
f'detected subscription: {subscription}')
|
||||
return False
|
||||
return True
|
||||
|
||||
33
tidal_api.py
33
tidal_api.py
@@ -13,7 +13,7 @@ import requests
|
||||
import urllib3
|
||||
|
||||
import urllib.parse as urlparse
|
||||
from urllib.parse import parse_qs, quote
|
||||
from urllib.parse import parse_qs, quote, urlencode
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from utils.utils import create_requests_session
|
||||
@@ -334,11 +334,25 @@ class TidalMobileSession(TidalSession):
|
||||
def auth(self, username: str, password: str):
|
||||
s = requests.Session()
|
||||
|
||||
params = {
|
||||
'response_type': 'code',
|
||||
'redirect_uri': self.redirect_uri,
|
||||
'lang': 'en_US',
|
||||
'appMode': 'android',
|
||||
'client_id': self.client_id,
|
||||
'client_unique_key': self.client_unique_key,
|
||||
'code_challenge': self.code_challenge,
|
||||
'code_challenge_method': 'S256',
|
||||
'restrict_signup': 'true'
|
||||
}
|
||||
|
||||
full_authorize_url = f"https://login.tidal.com/authorize?{urlencode(params)}"
|
||||
|
||||
# try Tidal DataDome cookie request
|
||||
r = s.post('https://dd.tidal.com/js/', data={
|
||||
'jsData': f'{{"opts":"endpoint,ajaxListenerPath","ua":"{self.user_agent}"}}',
|
||||
'ddk': '1F633CDD8EF22541BD6D9B1B8EF13A', # API Key (required)
|
||||
'Referer': quote(r.url), # Referer authorize link (required)
|
||||
'Referer': quote(full_authorize_url), # Referer authorize link (required)
|
||||
'responsePage': 'origin', # useless?
|
||||
'ddv': '4.17.0' # useless?
|
||||
}, headers={
|
||||
@@ -353,18 +367,6 @@ class TidalMobileSession(TidalSession):
|
||||
dd_cookie = r.json().get('cookie').split(';')[0]
|
||||
s.cookies[dd_cookie.split('=')[0]] = dd_cookie.split('=')[1]
|
||||
|
||||
params = {
|
||||
'response_type': 'code',
|
||||
'redirect_uri': self.redirect_uri,
|
||||
'lang': 'en_US',
|
||||
'appMode': 'android',
|
||||
'client_id': self.client_id,
|
||||
'client_unique_key': self.client_unique_key,
|
||||
'code_challenge': self.code_challenge,
|
||||
'code_challenge_method': 'S256',
|
||||
'restrict_signup': 'true'
|
||||
}
|
||||
|
||||
# retrieve csrf token for subsequent request
|
||||
r = s.get('https://login.tidal.com/authorize', params=params, headers={
|
||||
'user-agent': self.user_agent,
|
||||
@@ -597,6 +599,9 @@ class TidalTvSession(TidalSession):
|
||||
if 'refresh_token' in r.json():
|
||||
self.refresh_token = r.json()['refresh_token']
|
||||
|
||||
elif r.status_code == 401:
|
||||
print('\tERROR: ' + r.json()['userMessage'])
|
||||
|
||||
return r.status_code == 200
|
||||
|
||||
@staticmethod
|
||||
|
||||
Reference in New Issue
Block a user