|  | 
| 45 | 45 | ) | 
| 46 | 46 | from urllib.parse import parse_qs, urlencode, urlsplit | 
| 47 | 47 | 
 | 
|  | 48 | +import pyaes | 
| 48 | 49 | import requests | 
| 49 | 50 | from requests.exceptions import HTTPError | 
| 50 | 51 | 
 | 
| @@ -111,7 +112,6 @@ class Config: | 
| 111 | 112 |     api_v1_location: str = "https://api.tidal.com/v1/" | 
| 112 | 113 |     api_v2_location: str = "https://api.tidal.com/v2/" | 
| 113 | 114 |     openapi_v2_location: str = "https://openapi.tidal.com/v2/" | 
| 114 |  | -    api_token: str | 
| 115 | 115 |     client_id: str | 
| 116 | 116 |     client_secret: str | 
| 117 | 117 |     image_url: str = "https://resources.tidal.com/images/%s/%ix%i.jpg" | 
| @@ -151,65 +151,25 @@ def __init__( | 
| 151 | 151 |         else: | 
| 152 | 152 |             self.item_limit = item_limit | 
| 153 | 153 | 
 | 
| 154 |  | -        self.api_token = eval("\x67\x6c\x6f\x62\x61\x6c\x73".encode("437"))()[ | 
| 155 |  | -            "\x5f\x5f\x6e\x61\x6d\x65\x5f\x5f".encode( | 
| 156 |  | -                "".join(map(chr, [105, 105, 99, 115, 97][::-1])) | 
| 157 |  | -            ).decode("".join(map(chr, [117, 116, 70, 95, 56]))) | 
| 158 |  | -        ] | 
| 159 |  | -        self.api_token += "." + eval( | 
| 160 |  | -            "\x74\x79\x70\x65\x28\x73\x65\x6c\x66\x29\x2e\x5f\x5f\x6e\x61\x6d\x65\x5f\x5f".encode( | 
| 161 |  | -                "".join(map(chr, [105, 105, 99, 115, 97][::-1])) | 
| 162 |  | -            ).decode( | 
| 163 |  | -                "".join(map(chr, [117, 116, 70, 95, 56])) | 
|  | 154 | +        # OAuth Client Authorization | 
|  | 155 | +        self.client_id = base64.b64decode( | 
|  | 156 | +            base64.b64decode(b"V214bmVWTnVhR3RpVnpVdw==") | 
|  | 157 | +            + base64.b64decode(b"VjJ4a1RFMUhiRFJXUVQwOQ==") | 
|  | 158 | +        ).decode("utf-8") | 
|  | 159 | +        self.client_secret = base64.b64decode( | 
|  | 160 | +            base64.b64decode( | 
|  | 161 | +                b"VFZVMWRVOVZSbTFTUlVaeFpVaEtibE5yV2t0WmEzUlBWakI0YkZGWQ==" | 
| 164 | 162 |             ) | 
| 165 |  | -        ) | 
| 166 |  | -        token = self.api_token | 
| 167 |  | -        token = token[:8] + token[16:] | 
| 168 |  | -        self.api_token = list( | 
| 169 |  | -            (base64.b64decode("d3RjaThkamFfbHlhQnBKaWQuMkMwb3puT2ZtaXhnMA==").decode()) | 
| 170 |  | -        ) | 
| 171 |  | -        tok = "".join(([chr(ord(x) - 2) for x in token[-6:]])) | 
| 172 |  | -        token2 = token | 
| 173 |  | -        token = token[:9] | 
| 174 |  | -        token += tok | 
| 175 |  | -        tok2 = "".join(([chr(ord(x) - 2) for x in token[:-7]])) | 
| 176 |  | -        token = token[8:] | 
| 177 |  | -        token = tok2 + token | 
| 178 |  | -        self.api_token = list( | 
| 179 |  | -            (base64.b64decode("enJVZzRiWF9IalZfVm5rZ2MuMkF0bURsUGRvZzRldA==").decode()) | 
| 180 |  | -        ) | 
| 181 |  | -        for word in token: | 
| 182 |  | -            self.api_token.remove(word) | 
| 183 |  | -        self.api_token = "".join(self.api_token) | 
| 184 |  | -        string = "" | 
| 185 |  | -        save = False | 
| 186 |  | -        if not isinstance(token2, str): | 
| 187 |  | -            save = True | 
| 188 |  | -            string = "".encode("ISO-8859-1") | 
| 189 |  | -            token2 = token2.encode("ISO-8859-1") | 
| 190 |  | -        tok = string.join(([chr(ord(x) + 24) for x in token2[:-7]])) | 
| 191 |  | -        token2 = token2[8:] | 
| 192 |  | -        token2 = tok + token2 | 
| 193 |  | -        tok2 = string.join(([chr(ord(x) + 23) for x in token2[-6:]])) | 
| 194 |  | -        token2 = token2[:9] | 
| 195 |  | -        token2 += tok2 | 
| 196 |  | -        self.client_id = list( | 
| 197 |  | -            ( | 
| 198 |  | -                base64.b64decode( | 
| 199 |  | -                    "VoxKgUt8aHlEhEZ5cYhKgVAucVp2hnOFUH1WgE5+QlY2" | 
| 200 |  | -                    "dWtYVEptd2x2YnR0UDd3bE1scmM3MnNlND0=" | 
| 201 |  | -                ).decode("ISO-8859-1") | 
|  | 163 | +            + base64.b64decode( | 
|  | 164 | +                b"YkV4U01WcElZbFZzVDJSV2FGRlZSWGhKVm14b1FtUnVhRUphZWpBOQ==" | 
| 202 | 165 |             ) | 
| 203 |  | -        ) | 
| 204 |  | -        if save: | 
| 205 |  | -            token2.decode("ISO-8859-1").encode("utf-16") | 
| 206 |  | -            self.client_id = [x.encode("ISO-8859-1") for x in self.client_id] | 
| 207 |  | -        for word in token2: | 
| 208 |  | -            self.client_id.remove(word) | 
| 209 |  | -        self.client_id = "".join(self.client_id) | 
| 210 |  | -        self.client_secret = self.client_id | 
| 211 |  | -        self.client_id = self.api_token | 
| 212 |  | -        # PKCE Authorization. We will keep the former `client_id` as a fallback / will only be used for non PCKE | 
|  | 166 | +        ).decode("utf-8") | 
|  | 167 | + | 
|  | 168 | +        # If client_secret not supplied, fall back to client_id (matching original behavior) | 
|  | 169 | +        if not self.client_secret and self.client_id: | 
|  | 170 | +            self.client_secret = self.client_id | 
|  | 171 | + | 
|  | 172 | +        # PKCE Client Authorization. We will keep the former `client_id` as a fallback / will only be used for non PCKE | 
| 213 | 173 |         # authorizations. | 
| 214 | 174 |         self.client_unique_key = format(random.getrandbits(64), "02x") | 
| 215 | 175 |         self.code_verifier = base64.urlsafe_b64encode(os.urandom(32))[:-1].decode( | 
|  | 
0 commit comments