@@ -30,19 +30,19 @@ class TidalAPI {
30
30
public $ fixSSLcertificate = false ;
31
31
public $ deviceCode ;
32
32
public $ apiKey ;
33
- //DEL:
34
- public $ sessionId ;
35
33
36
34
const AUTH_URL = 'https://auth.tidal.com/v1/oauth2 ' ;
37
35
const TOKEN_VERIFY_URL = 'https://api.tidal.com/v1/sessions ' ;
38
36
const LOGOUT_URL = 'https://api.tidal.com/v1/logout ' ;
39
- const API_URL = "https://api.tidalhifi.com/v1/ " ;
37
+ const API_URL = "https://api.tidal.com/v1/ " ;
38
+ const API_V2_URL = "https://api.tidal.com/v2/ " ;
40
39
const RESOURCES_URL = "https://resources.tidal.com/images/ " ;
41
40
42
41
43
42
public function __construct (){
44
43
$ this ->apiKey = array ('clientId ' => base64_decode ('YVI3Z1VhVEsxaWhwWE9FUA== ' ), 'clientSecret ' => base64_decode ('ZVZXQkVrdUwyRkNqeGdqT2tSM3lLMFJZWkViY3JNWFJjMmw4ZlUzWkNkRT0= ' ));
45
-
44
+ //$this->apiKey = array('clientId' => '', 'clientSecret' => '');
45
+
46
46
$ this ->curl = curl_init ();
47
47
curl_setopt ($ this ->curl , CURLOPT_RETURNTRANSFER , true );
48
48
//to fix "SSL certificate problem: unable to get local issuer certificate" under Windows uncomment below lines or use function fixSSLcertificate():
@@ -51,7 +51,6 @@ public function __construct(){
51
51
}
52
52
53
53
public function __destruct (){
54
- //$this->logout($this->sessionId);
55
54
curl_close ($ this ->curl );
56
55
}
57
56
@@ -163,63 +162,73 @@ function logout() {
163
162
164
163
function search ($ type , $ query , $ limit = 50 ) {
165
164
$ query = urlencode ($ query );
166
- curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "search/ " . $ type . "?sessionId= " . $ this -> sessionId . " & query= " . $ query . "&countryCode= " . $ this ->countryCode . "&limit= " . $ limit );
165
+ curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "search/ " . $ type . "?query= " . $ query . "&countryCode= " . $ this ->countryCode . "&limit= " . $ limit );
167
166
return $ this ->request ();
168
167
}
169
168
170
169
function searchAll ($ query , $ limit = 50 ) {
171
170
$ query = urlencode ($ query );
172
- curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "search?sessionId= " . $ this -> sessionId . " & query= " . $ query . "&countryCode= " . $ this ->countryCode . "&limit= " . $ limit . "&types=ARTISTS,ALBUMS,TRACKS,PLAYLISTS " );
171
+ curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "search?query= " . $ query . "&countryCode= " . $ this ->countryCode . "&limit= " . $ limit . "&types=ARTISTS,ALBUMS,TRACKS,PLAYLISTS " );
173
172
return $ this ->request ();
174
173
}
175
174
176
175
function getTrack ($ track_id ) {
177
- curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "tracks/ " . $ track_id . "?sessionId= " . $ this -> sessionId . " & countryCode= " . $ this ->countryCode );
176
+ curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "tracks/ " . $ track_id . "?countryCode= " . $ this ->countryCode );
178
177
return $ this ->request ();
179
178
}
180
179
181
180
function getAlbum ($ album_id ) {
182
- curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "albums/ " . $ album_id . "?sessionId= " . $ this -> sessionId . " & countryCode= " . $ this ->countryCode );
181
+ curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "albums/ " . $ album_id . "?countryCode= " . $ this ->countryCode );
183
182
return $ this ->request ();
184
183
}
185
184
186
185
function getAlbumTracks ($ album_id ) {
187
- curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "albums/ " . $ album_id . "/tracks?sessionId= " . $ this -> sessionId . " & countryCode= " . $ this ->countryCode );
186
+ curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "albums/ " . $ album_id . "/tracks?countryCode= " . $ this ->countryCode );
188
187
return $ this ->request ();
189
188
}
190
189
191
190
function getAlbumInfo ($ album_id ) {
192
- curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "pages/album?albumId= " . $ album_id . "&deviceType=BROWSER&sessionId= " . $ this ->sessionId . "&countryCode= " . $ this ->countryCode );
191
+ curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "pages/album?albumId= " . $ album_id . "&deviceType=BROWSER&countryCode= " . $ this ->countryCode );
192
+ return $ this ->request ();
193
+ }
194
+
195
+ function getAlbumReview ($ album_id ) {
196
+ curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "albums/ " . $ album_id . "/review?countryCode= " . $ this ->countryCode );
193
197
return $ this ->request ();
194
198
}
195
199
196
200
function getArtistAll ($ artist_id ) {
197
- curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "pages/artist?artistId= " . $ artist_id . "&sessionId= " . $ this -> sessionId . " & countryCode= " . $ this ->countryCode . "&deviceType=BROWSER " );
201
+ curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "pages/artist?artistId= " . $ artist_id . "&countryCode= " . $ this ->countryCode . "&deviceType=BROWSER " );
198
202
return $ this ->request ();
199
203
}
200
204
201
205
function getArtistAlbums ($ artist_id , $ limit = 50 ) {
202
- curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "artists/ " . $ artist_id . "/albums?sessionId= " . $ this -> sessionId . " & countryCode= " . $ this ->countryCode . "&limit= " . $ limit );
206
+ curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "artists/ " . $ artist_id . "/albums?countryCode= " . $ this ->countryCode . "&limit= " . $ limit );
203
207
return $ this ->request ();
204
208
}
205
209
206
210
function getArtistEPsAndSingles ($ artist_id , $ limit = 50 ) {
207
- curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "artists/ " . $ artist_id . "/albums?filter=EPSANDSINGLES&sessionId= " . $ this -> sessionId . " & countryCode= " . $ this ->countryCode . "&limit= " . $ limit );
211
+ curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "artists/ " . $ artist_id . "/albums?filter=EPSANDSINGLES&countryCode= " . $ this ->countryCode . "&limit= " . $ limit );
208
212
return $ this ->request ();
209
213
}
210
214
211
215
function getArtistTopTracks ($ artist_id , $ limit = 10 ) {
212
- curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "artists/ " . $ artist_id . "/toptracks?filter=ALL&sessionId= " . $ this ->sessionId . "&countryCode= " . $ this ->countryCode . "&limit= " . $ limit );
216
+ curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "artists/ " . $ artist_id . "/toptracks?filter=ALL&countryCode= " . $ this ->countryCode . "&limit= " . $ limit );
217
+ return $ this ->request ();
218
+ }
219
+
220
+ function getArtistBio ($ artist_id , $ limit = 10 ) {
221
+ curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "artists/ " . $ artist_id . "/bio?countryCode= " . $ this ->countryCode . "&limit= " . $ limit );
213
222
return $ this ->request ();
214
223
}
215
224
216
- function getArtistBio ($ artist_id ) {
217
- curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "artists/ " . $ artist_id . "/bio?sessionId= " . $ this -> sessionId . " & countryCode= " . $ this ->countryCode . "&limit= " . $ limit );
225
+ function getArtistLinks ($ artist_id, $ limit = 20 ) {
226
+ curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "artists/ " . $ artist_id . "/links? countryCode= " . $ this ->countryCode . "&limit= " . $ limit );
218
227
return $ this ->request ();
219
228
}
220
229
221
230
function getRelatedArtists ($ artist_id ) {
222
- curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "pages/artist?artistId= " . $ artist_id . "&sessionId= " . $ this -> sessionId . " & countryCode= " . $ this ->countryCode . "&deviceType=BROWSER " );
231
+ curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "pages/artist?artistId= " . $ artist_id . "&countryCode= " . $ this ->countryCode . "&deviceType=BROWSER " );
223
232
$ artistAll = $ this ->request ();
224
233
foreach ($ artistAll ["rows " ] as $ module ){
225
234
if ($ module ["modules " ][0 ]["type " ]=='ARTIST_LIST ' ) {
@@ -229,30 +238,30 @@ function getRelatedArtists($artist_id) {
229
238
}
230
239
231
240
function getNewAlbums ($ limit = 100 ) {
232
- curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "pages/show_more_featured_albums?sessionId= " . $ this -> sessionId . " & countryCode= " . $ this ->countryCode . "&limit= " . $ limit . "&deviceType=BROWSER " );
241
+ curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "pages/show_more_featured_albums?countryCode= " . $ this ->countryCode . "&limit= " . $ limit . "&deviceType=BROWSER " );
233
242
$ res = $ this ->request ();
234
243
return $ res ;
235
244
$ s = array_search ("featured-new " ,array_column ($ res ["rows " ][0 ]["modules " ][0 ]["tabs " ],"key " ));
236
245
return $ res ["rows " ][0 ]["modules " ][0 ]["tabs " ][$ s ]["pagedList " ]["items " ];
237
246
}
238
247
239
248
function getFeatured ($ limit = 100 , $ offset = 0 ) {
240
- curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "featured/new/albums?sessionId= " . $ this -> sessionId . " & countryCode= " . $ this ->countryCode . "&limit= " . $ limit . "&offset= " . $ offset );
249
+ curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "featured/new/albums?countryCode= " . $ this ->countryCode . "&limit= " . $ limit . "&offset= " . $ offset );
241
250
return $ this ->request ();
242
251
}
243
252
244
253
function getFeaturedRecommended ($ limit = 100 , $ offset = 0 ) {
245
- curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "featured/recommended/albums?sessionId= " . $ this -> sessionId . " & countryCode= " . $ this ->countryCode . "&limit= " . $ limit . "&offset= " . $ offset );
254
+ curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "featured/recommended/albums?countryCode= " . $ this ->countryCode . "&limit= " . $ limit . "&offset= " . $ offset );
246
255
return $ this ->request ();
247
256
}
248
257
249
258
function getFeaturedTop ($ limit = 100 , $ offset = 0 ) {
250
- curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "featured/top/albums?sessionId= " . $ this -> sessionId . " & countryCode= " . $ this ->countryCode . "&limit= " . $ limit . "&offset= " . $ offset );
259
+ curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "featured/top/albums?countryCode= " . $ this ->countryCode . "&limit= " . $ limit . "&offset= " . $ offset );
251
260
return $ this ->request ();
252
261
}
253
262
254
263
function getFeaturedLocal ($ limit = 100 , $ offset = 0 ) {
255
- curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "featured/local/albums?sessionId= " . $ this -> sessionId . " & countryCode= " . $ this ->countryCode . "&limit= " . $ limit . "&offset= " . $ offset );
264
+ curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "featured/local/albums?countryCode= " . $ this ->countryCode . "&limit= " . $ limit . "&offset= " . $ offset );
256
265
return $ this ->request ();
257
266
}
258
267
@@ -343,33 +352,59 @@ function getSuggestedNewTracks($limit = 50, $offset = 0, $getMore = false) {
343
352
344
353
function getByApiPath ($ limit , $ offset , $ apiPath ) {
345
354
if ($ limit > 50 ) $ limit = 50 ; //Tidal API limitation
346
- curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . $ apiPath ."?sessionId= " . $ this -> sessionId . " & locale=en_US&deviceType=BROWSER&countryCode= " . $ this ->countryCode . "&limit= " . $ limit . "&offset= " . $ offset );
355
+ curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . $ apiPath ."?locale=en_US&deviceType=BROWSER&countryCode= " . $ this ->countryCode . "&limit= " . $ limit . "&offset= " . $ offset );
347
356
return $ this ->request ();
348
357
}
349
358
350
- function getStreamURL ($ track_id ) {
351
- curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "tracks/ " . $ track_id . "/streamUrl?soundQuality= " . $ this ->audioQuality . "&sessionId= " . $ this -> sessionId . " & countryCode= " . $ this ->countryCode );
359
+ function getStreamURL_old ($ track_id ) {
360
+ curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "tracks/ " . $ track_id . "/streamUrl?soundQuality= " . $ this ->audioQuality . "&countryCode= " . $ this ->countryCode );
352
361
return $ this ->request ();
353
362
}
354
363
364
+ function getStreamURL ($ track_id ) {
365
+ curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "tracks/ " . $ track_id . "/playbackinfopostpaywall?audioquality= " . $ this ->audioQuality . "&countryCode= " . $ this ->countryCode . "&playbackmode=STREAM&assetpresentation=FULL " );
366
+ $ res = $ this ->request ();
367
+ if (strpos ($ res ['manifestMimeType ' ],"vnd.tidal.bt " ) !== false ) {
368
+ $ manifest = json_decode (base64_decode ($ res ['manifest ' ]),true );
369
+ $ res ['manifest_b64_decoded ' ] = $ manifest ;
370
+ $ res ['url ' ] = $ manifest ['urls ' ][0 ];
371
+ }
372
+ return $ res ;
373
+ }
374
+
355
375
function getUserPlaylists () {
356
- curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "users/ " . $ this ->userId . "/playlists?sessionId= " . $ this -> sessionId . " & countryCode= " . $ this ->countryCode . "&limit= " . $ limit );
376
+ curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "users/ " . $ this ->userId . "/playlists?countryCode= " . $ this ->countryCode . "&limit= " . $ limit );
357
377
return $ this ->request ();
358
378
}
359
379
360
380
function getUserPlaylistTracks ($ playlist_id , $ limit = 1000 ) {
361
- curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "playlists/ " . $ playlist_id . "/tracks?sessionId= " . $ this -> sessionId . " & countryCode= " . $ this ->countryCode . "&limit= " . $ limit );
381
+ curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . "playlists/ " . $ playlist_id . "/tracks?countryCode= " . $ this ->countryCode . "&limit= " . $ limit );
362
382
return $ this ->request ();
363
383
}
364
384
365
385
function getHomePage () {
366
- //curl_setopt($this->curl, CURLOPT_URL, self::API_URL . " pages/home?locale=en_US&deviceType=DESKTOP&sessionId=" . $this->sessionId . "&countryCode=" . $this->countryCode);
367
- curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . " pages/home?locale=en_US&deviceType=BROWSER&sessionId= " . $ this ->sessionId . "&countryCode= " . $ this ->countryCode );
386
+ //curl_setopt($this->curl, CURLOPT_URL, self::API_URL . " pages/home?locale=en_US&deviceType=DESKTOP&countryCode=" . $this->countryCode);
387
+ curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . " pages/home?locale=en_US&deviceType=BROWSER&countryCode= " . $ this ->countryCode );
388
+ return $ this ->request ();
389
+ }
390
+
391
+ function getUserClients () {
392
+ curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . " users/ " . $ this ->userId . "/clients?countryCode= " . $ this ->countryCode );
393
+ return $ this ->request ();
394
+ }
395
+
396
+ function getUserSubscription () {
397
+ curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . " users/ " . $ this ->userId . "/subscription?countryCode= " . $ this ->countryCode );
398
+ return $ this ->request ();
399
+ }
400
+
401
+ function getUserFeedActivities () {
402
+ curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_V2_URL . " feed/activities/?userId= " . $ this ->userId . "&countryCode= " . $ this ->countryCode . '&locale=en-us ' );
368
403
return $ this ->request ();
369
404
}
370
405
371
406
function getExplorePage () {
372
- curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . " pages/explore?locale=en_US&deviceType=BROWSER&sessionId= " . $ this -> sessionId . " & countryCode= " . $ this ->countryCode );
407
+ curl_setopt ($ this ->curl , CURLOPT_URL , self ::API_URL . " pages/explore?locale=en_US&deviceType=BROWSER&countryCode= " . $ this ->countryCode );
373
408
return $ this ->request ();
374
409
}
375
410
@@ -404,7 +439,12 @@ static function albumCoverToURL($pic,$quality = 'hq') {
404
439
function request () {
405
440
curl_setopt ($ this ->curl , CURLOPT_POST , 0 );
406
441
curl_setopt ($ this ->curl , CURLOPT_HTTPHEADER , array ('authorization: Bearer ' . $ this ->token ));
407
- $ server_output = curl_exec ($ this ->curl );
442
+ for ($ i =0 ; $ i <3 ; $ i ++) {
443
+ $ server_output = curl_exec ($ this ->curl );
444
+ if (curl_errno ($ this ->curl ) == 0 ) {
445
+ break ;
446
+ }
447
+ }
408
448
$ res_json = json_decode ($ server_output , true );
409
449
if (isset ($ res_json ['status ' ]) && ($ res_json ['status ' ]) != 200 ) {
410
450
$ res_json ['return ' ] = 1 ;
0 commit comments