#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Function to decode JSON object key
char * decode_json( const char * json, const char * key) {
sprintf ( command
, "echo '%s' | jq -r '.%s'" , json
, key
) ;
FILE* fp = popen( command, "r" ) ;
if ( fp == NULL) {
return NULL;
}
char * result = NULL;
size_t bufsize = 0 ;
getline( & result, & bufsize, fp) ;
pclose( fp) ;
// Trim newline character from the result
if ( result
!= NULL
&& strlen ( result
) > 0 && result
[ strlen ( result
) - 1 ] == '\n ' ) { result
[ strlen ( result
) - 1 ] = '\0 ' ; }
return result;
}
// Function to fetch and download a track by ID
void fetch_track_by_id( const char * trackId, const char * dstDir) {
char command[ 512 ] ;
sprintf ( command
, "curl -s 'http://m...content-available-to-author-only...a.com/v1/track/baseInfo?device=iPhone&trackId=%s'" , trackId
) ;
FILE* fp = popen( command, "r" ) ;
if ( fp == NULL) {
printf ( "Failed to fetch the track.\n " ) ; return ;
}
char response[ 4096 ] ;
fread ( response
, sizeof ( char ) , sizeof ( response
) , fp
) ;
pclose( fp) ;
char * uid = decode_json( response, "uid" ) ;
char * title = decode_json( response, "title" ) ;
char * url64 = decode_json( response, "playUrl64" ) ;
if ( url64 != NULL) {
char filename[ 512 ] ;
sprintf ( filename
, "%s/%s.mp3" , dstDir
, title
) ; char wgetCommand[ 1024 ] ;
sprintf ( wgetCommand
, "wget '%s' -O '%s'" , url64
, filename
) ; } else {
printf ( "Failed to fetch the track, may be a paid resource.\n " ) ; }
}
// Function to fetch and download tracks by page number
void fetch_tracks_by_page( const char * albumId, int pageNum, const char * dstDir) {
char command[ 512 ] ;
sprintf ( command
, "curl -s 'https://w...content-available-to-author-only...a.com/revision/album/v1/getTracksList?albumId=%s&pageNum=%d&pageSize=30'" , albumId
, pageNum
) ;
FILE* fp = popen( command, "r" ) ;
if ( fp == NULL) {
printf ( "Failed to fetch the tracks.\n " ) ; return ;
}
char response[ 8192 ] ;
fread ( response
, sizeof ( char ) , sizeof ( response
) , fp
) ;
pclose( fp) ;
char * trackIds = decode_json( response, "data.tracks[].trackId" ) ;
if ( trackIds == NULL) {
return ;
}
char * token
= strtok ( trackIds
, " \n " ) ; while ( token != NULL) {
fetch_track_by_id( token, dstDir) ;
}
}
// Function to fetch and download tracks by multiple page numbers
void fetch_tracks_by_pages( const char * albumId, const char * pageNumbers, const char * dstDir) {
char * pages = strdup( pageNumbers) ;
char * token
= strtok ( pages
, " \n " ) ; while ( token != NULL) {
int pageNum
= atoi ( token
) ; fetch_tracks_by_page( albumId, pageNum, dstDir) ;
}
}
// Main function
int main( ) {
char albumUrl[ 512 ] ;
printf ( "Enter the album URL (e.g., https://w...content-available-to-author-only...a.com/album/30945784): " ) ; fgets ( albumUrl
, sizeof ( albumUrl
) , stdin
) ;
// Remove newline character from the input
if ( strlen ( albumUrl
) > 0 && albumUrl
[ strlen ( albumUrl
) - 1 ] == '\n ' ) { albumUrl
[ strlen ( albumUrl
) - 1 ] = '\0 ' ; }
// Extract album ID from the URL
char * albumId
= strstr ( albumUrl
, "/album/" ) ; if ( albumId == NULL) {
printf ( "Invalid album URL.\n " ) ; return 1 ;
}
const char * dstDir = "." ;
printf ( "Downloading all files...\n " ) ;
// Fetch all tracks
char command[ 512 ] ;
sprintf ( command
, "curl -s 'https://w...content-available-to-author-only...a.com/revision/album/v1/getTracksList?albumId=%s&pageNum=0&pageSize=1'" , albumId
) ;
FILE* fp = popen( command, "r" ) ;
if ( fp == NULL) {
printf ( "Failed to fetch the album track count.\n " ) ; return 1 ;
}
char response[ 4096 ] ;
fread ( response
, sizeof ( char ) , sizeof ( response
) , fp
) ;
pclose( fp) ;
char * countStr = decode_json( response, "data.trackTotalCount" ) ;
if ( countStr == NULL) {
printf ( "Failed to fetch the album track count.\n " ) ; return 1 ;
}
int count
= atoi ( countStr
) ;
int pageCount = ( count / 30 ) + 1 ;
printf ( "Total count is %d\n " , count
) ;
for ( int i = 0 ; i < pageCount; i++ ) {
fetch_tracks_by_page( albumId, i, dstDir) ;
}
printf ( "All files downloaded successfully.\n " ) ;
return 0 ;
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPHN0cmluZy5oPgoKLy8gRnVuY3Rpb24gdG8gZGVjb2RlIEpTT04gb2JqZWN0IGtleQpjaGFyKiBkZWNvZGVfanNvbihjb25zdCBjaGFyKiBqc29uLCBjb25zdCBjaGFyKiBrZXkpIHsKICAgIGNoYXIqIGNvbW1hbmQgPSBtYWxsb2Moc3RybGVuKGpzb24pICsgc3RybGVuKGtleSkgKyAxMDApOwogICAgc3ByaW50Zihjb21tYW5kLCAiZWNobyAnJXMnIHwganEgLXIgJy4lcyciLCBqc29uLCBrZXkpOwoKICAgIEZJTEUqIGZwID0gcG9wZW4oY29tbWFuZCwgInIiKTsKICAgIGlmIChmcCA9PSBOVUxMKSB7CiAgICAgICAgZnJlZShjb21tYW5kKTsKICAgICAgICByZXR1cm4gTlVMTDsKICAgIH0KCiAgICBjaGFyKiByZXN1bHQgPSBOVUxMOwogICAgc2l6ZV90IGJ1ZnNpemUgPSAwOwogICAgZ2V0bGluZSgmcmVzdWx0LCAmYnVmc2l6ZSwgZnApOwoKICAgIHBjbG9zZShmcCk7CiAgICBmcmVlKGNvbW1hbmQpOwoKICAgIC8vIFRyaW0gbmV3bGluZSBjaGFyYWN0ZXIgZnJvbSB0aGUgcmVzdWx0CiAgICBpZiAocmVzdWx0ICE9IE5VTEwgJiYgc3RybGVuKHJlc3VsdCkgPiAwICYmIHJlc3VsdFtzdHJsZW4ocmVzdWx0KSAtIDFdID09ICdcbicpIHsKICAgICAgICByZXN1bHRbc3RybGVuKHJlc3VsdCkgLSAxXSA9ICdcMCc7CiAgICB9CgogICAgcmV0dXJuIHJlc3VsdDsKfQoKLy8gRnVuY3Rpb24gdG8gZmV0Y2ggYW5kIGRvd25sb2FkIGEgdHJhY2sgYnkgSUQKdm9pZCBmZXRjaF90cmFja19ieV9pZChjb25zdCBjaGFyKiB0cmFja0lkLCBjb25zdCBjaGFyKiBkc3REaXIpIHsKICAgIGNoYXIgY29tbWFuZFs1MTJdOwogICAgc3ByaW50Zihjb21tYW5kLCAiY3VybCAtcyAnaHR0cDovL20uLi5jb250ZW50LWF2YWlsYWJsZS10by1hdXRob3Itb25seS4uLmEuY29tL3YxL3RyYWNrL2Jhc2VJbmZvP2RldmljZT1pUGhvbmUmdHJhY2tJZD0lcyciLCB0cmFja0lkKTsKCiAgICBGSUxFKiBmcCA9IHBvcGVuKGNvbW1hbmQsICJyIik7CiAgICBpZiAoZnAgPT0gTlVMTCkgewogICAgICAgIHByaW50ZigiRmFpbGVkIHRvIGZldGNoIHRoZSB0cmFjay5cbiIpOwogICAgICAgIHJldHVybjsKICAgIH0KCiAgICBjaGFyIHJlc3BvbnNlWzQwOTZdOwogICAgZnJlYWQocmVzcG9uc2UsIHNpemVvZihjaGFyKSwgc2l6ZW9mKHJlc3BvbnNlKSwgZnApOwoKICAgIHBjbG9zZShmcCk7CgogICAgY2hhciogdWlkID0gZGVjb2RlX2pzb24ocmVzcG9uc2UsICJ1aWQiKTsKICAgIGNoYXIqIHRpdGxlID0gZGVjb2RlX2pzb24ocmVzcG9uc2UsICJ0aXRsZSIpOwogICAgY2hhciogdXJsNjQgPSBkZWNvZGVfanNvbihyZXNwb25zZSwgInBsYXlVcmw2NCIpOwoKICAgIGlmICh1cmw2NCAhPSBOVUxMKSB7CiAgICAgICAgY2hhciBmaWxlbmFtZVs1MTJdOwogICAgICAgIHNwcmludGYoZmlsZW5hbWUsICIlcy8lcy5tcDMiLCBkc3REaXIsIHRpdGxlKTsKICAgICAgICBjaGFyIHdnZXRDb21tYW5kWzEwMjRdOwogICAgICAgIHNwcmludGYod2dldENvbW1hbmQsICJ3Z2V0ICclcycgLU8gJyVzJyIsIHVybDY0LCBmaWxlbmFtZSk7CiAgICAgICAgc3lzdGVtKHdnZXRDb21tYW5kKTsKICAgICAgICBmcmVlKHVybDY0KTsKICAgIH0gZWxzZSB7CiAgICAgICAgcHJpbnRmKCJGYWlsZWQgdG8gZmV0Y2ggdGhlIHRyYWNrLCBtYXkgYmUgYSBwYWlkIHJlc291cmNlLlxuIik7CiAgICB9CgogICAgZnJlZSh1aWQpOwogICAgZnJlZSh0aXRsZSk7Cn0KCi8vIEZ1bmN0aW9uIHRvIGZldGNoIGFuZCBkb3dubG9hZCB0cmFja3MgYnkgcGFnZSBudW1iZXIKdm9pZCBmZXRjaF90cmFja3NfYnlfcGFnZShjb25zdCBjaGFyKiBhbGJ1bUlkLCBpbnQgcGFnZU51bSwgY29uc3QgY2hhciogZHN0RGlyKSB7CiAgICBjaGFyIGNvbW1hbmRbNTEyXTsKICAgIHNwcmludGYoY29tbWFuZCwgImN1cmwgLXMgJ2h0dHBzOi8vdy4uLmNvbnRlbnQtYXZhaWxhYmxlLXRvLWF1dGhvci1vbmx5Li4uYS5jb20vcmV2aXNpb24vYWxidW0vdjEvZ2V0VHJhY2tzTGlzdD9hbGJ1bUlkPSVzJnBhZ2VOdW09JWQmcGFnZVNpemU9MzAnIiwgYWxidW1JZCwgcGFnZU51bSk7CgogICAgRklMRSogZnAgPSBwb3Blbihjb21tYW5kLCAiciIpOwogICAgaWYgKGZwID09IE5VTEwpIHsKICAgICAgICBwcmludGYoIkZhaWxlZCB0byBmZXRjaCB0aGUgdHJhY2tzLlxuIik7CiAgICAgICAgcmV0dXJuOwogICAgfQoKICAgIGNoYXIgcmVzcG9uc2VbODE5Ml07CiAgICBmcmVhZChyZXNwb25zZSwgc2l6ZW9mKGNoYXIpLCBzaXplb2YocmVzcG9uc2UpLCBmcCk7CgogICAgcGNsb3NlKGZwKTsKCiAgICBjaGFyKiB0cmFja0lkcyA9IGRlY29kZV9qc29uKHJlc3BvbnNlLCAiZGF0YS50cmFja3NbXS50cmFja0lkIik7CiAgICBpZiAodHJhY2tJZHMgPT0gTlVMTCkgewogICAgICAgIHByaW50ZigiTm8gdHJhY2tzIGZvdW5kLlxuIik7CiAgICAgICAgcmV0dXJuOwogICAgfQoKICAgIGNoYXIqIHRva2VuID0gc3RydG9rKHRyYWNrSWRzLCAiIFxuIik7CiAgICB3aGlsZSAodG9rZW4gIT0gTlVMTCkgewogICAgICAgIGZldGNoX3RyYWNrX2J5X2lkKHRva2VuLCBkc3REaXIpOwogICAgICAgIHRva2VuID0gc3RydG9rKE5VTEwsICIgXG4iKTsKICAgIH0KCiAgICBmcmVlKHRyYWNrSWRzKTsKfQoKLy8gRnVuY3Rpb24gdG8gZmV0Y2ggYW5kIGRvd25sb2FkIHRyYWNrcyBieSBtdWx0aXBsZSBwYWdlIG51bWJlcnMKdm9pZCBmZXRjaF90cmFja3NfYnlfcGFnZXMoY29uc3QgY2hhciogYWxidW1JZCwgY29uc3QgY2hhciogcGFnZU51bWJlcnMsIGNvbnN0IGNoYXIqIGRzdERpcikgewogICAgY2hhciogcGFnZXMgPSBzdHJkdXAocGFnZU51bWJlcnMpOwogICAgY2hhciogdG9rZW4gPSBzdHJ0b2socGFnZXMsICIgXG4iKTsKICAgIHdoaWxlICh0b2tlbiAhPSBOVUxMKSB7CiAgICAgICAgaW50IHBhZ2VOdW0gPSBhdG9pKHRva2VuKTsKICAgICAgICBmZXRjaF90cmFja3NfYnlfcGFnZShhbGJ1bUlkLCBwYWdlTnVtLCBkc3REaXIpOwogICAgICAgIHRva2VuID0gc3RydG9rKE5VTEwsICIgXG4iKTsKICAgIH0KICAgIGZyZWUocGFnZXMpOwp9CgovLyBNYWluIGZ1bmN0aW9uCmludCBtYWluKCkgewogICAgY2hhciBhbGJ1bVVybFs1MTJdOwogICAgcHJpbnRmKCJFbnRlciB0aGUgYWxidW0gVVJMIChlLmcuLCBodHRwczovL3cuLi5jb250ZW50LWF2YWlsYWJsZS10by1hdXRob3Itb25seS4uLmEuY29tL2FsYnVtLzMwOTQ1Nzg0KTogIik7CiAgICBmZ2V0cyhhbGJ1bVVybCwgc2l6ZW9mKGFsYnVtVXJsKSwgc3RkaW4pOwoKICAgIC8vIFJlbW92ZSBuZXdsaW5lIGNoYXJhY3RlciBmcm9tIHRoZSBpbnB1dAogICAgaWYgKHN0cmxlbihhbGJ1bVVybCkgPiAwICYmIGFsYnVtVXJsW3N0cmxlbihhbGJ1bVVybCkgLSAxXSA9PSAnXG4nKSB7CiAgICAgICAgYWxidW1Vcmxbc3RybGVuKGFsYnVtVXJsKSAtIDFdID0gJ1wwJzsKICAgIH0KCiAgICAvLyBFeHRyYWN0IGFsYnVtIElEIGZyb20gdGhlIFVSTAogICAgY2hhciogYWxidW1JZCA9IHN0cnN0cihhbGJ1bVVybCwgIi9hbGJ1bS8iKTsKICAgIGlmIChhbGJ1bUlkID09IE5VTEwpIHsKICAgICAgICBwcmludGYoIkludmFsaWQgYWxidW0gVVJMLlxuIik7CiAgICAgICAgcmV0dXJuIDE7CiAgICB9CiAgICBhbGJ1bUlkICs9IHN0cmxlbigiL2FsYnVtLyIpOwoKICAgIGNvbnN0IGNoYXIqIGRzdERpciA9ICIuIjsKCiAgICBwcmludGYoIkRvd25sb2FkaW5nIGFsbCBmaWxlcy4uLlxuIik7CgogICAgLy8gRmV0Y2ggYWxsIHRyYWNrcwogICAgY2hhciBjb21tYW5kWzUxMl07CiAgICBzcHJpbnRmKGNvbW1hbmQsICJjdXJsIC1zICdodHRwczovL3cuLi5jb250ZW50LWF2YWlsYWJsZS10by1hdXRob3Itb25seS4uLmEuY29tL3JldmlzaW9uL2FsYnVtL3YxL2dldFRyYWNrc0xpc3Q/YWxidW1JZD0lcyZwYWdlTnVtPTAmcGFnZVNpemU9MSciLCBhbGJ1bUlkKTsKCiAgICBGSUxFKiBmcCA9IHBvcGVuKGNvbW1hbmQsICJyIik7CiAgICBpZiAoZnAgPT0gTlVMTCkgewogICAgICAgIHByaW50ZigiRmFpbGVkIHRvIGZldGNoIHRoZSBhbGJ1bSB0cmFjayBjb3VudC5cbiIpOwogICAgICAgIHJldHVybiAxOwogICAgfQoKICAgIGNoYXIgcmVzcG9uc2VbNDA5Nl07CiAgICBmcmVhZChyZXNwb25zZSwgc2l6ZW9mKGNoYXIpLCBzaXplb2YocmVzcG9uc2UpLCBmcCk7CgogICAgcGNsb3NlKGZwKTsKCiAgICBjaGFyKiBjb3VudFN0ciA9IGRlY29kZV9qc29uKHJlc3BvbnNlLCAiZGF0YS50cmFja1RvdGFsQ291bnQiKTsKICAgIGlmIChjb3VudFN0ciA9PSBOVUxMKSB7CiAgICAgICAgcHJpbnRmKCJGYWlsZWQgdG8gZmV0Y2ggdGhlIGFsYnVtIHRyYWNrIGNvdW50LlxuIik7CiAgICAgICAgcmV0dXJuIDE7CiAgICB9CgogICAgaW50IGNvdW50ID0gYXRvaShjb3VudFN0cik7CiAgICBmcmVlKGNvdW50U3RyKTsKCiAgICBpbnQgcGFnZUNvdW50ID0gKGNvdW50IC8gMzApICsgMTsKICAgIHByaW50ZigiVG90YWwgY291bnQgaXMgJWRcbiIsIGNvdW50KTsKCiAgICBmb3IgKGludCBpID0gMDsgaSA8IHBhZ2VDb3VudDsgaSsrKSB7CiAgICAgICAgZmV0Y2hfdHJhY2tzX2J5X3BhZ2UoYWxidW1JZCwgaSwgZHN0RGlyKTsKICAgIH0KCiAgICBwcmludGYoIkFsbCBmaWxlcyBkb3dubG9hZGVkIHN1Y2Nlc3NmdWxseS5cbiIpOwoKICAgIHJldHVybiAwOwp9Cg==