fork download
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. // Function to decode JSON object key
  6. char* decode_json(const char* json, const char* key) {
  7. char* command = malloc(strlen(json) + strlen(key) + 100);
  8. sprintf(command, "echo '%s' | jq -r '.%s'", json, key);
  9.  
  10. FILE* fp = popen(command, "r");
  11. if (fp == NULL) {
  12. free(command);
  13. return NULL;
  14. }
  15.  
  16. char* result = NULL;
  17. size_t bufsize = 0;
  18. getline(&result, &bufsize, fp);
  19.  
  20. pclose(fp);
  21. free(command);
  22.  
  23. // Trim newline character from the result
  24. if (result != NULL && strlen(result) > 0 && result[strlen(result) - 1] == '\n') {
  25. result[strlen(result) - 1] = '\0';
  26. }
  27.  
  28. return result;
  29. }
  30.  
  31. // Function to fetch and download a track by ID
  32. void fetch_track_by_id(const char* trackId, const char* dstDir) {
  33. char command[512];
  34. sprintf(command, "curl -s 'http://m...content-available-to-author-only...a.com/v1/track/baseInfo?device=iPhone&trackId=%s'", trackId);
  35.  
  36. FILE* fp = popen(command, "r");
  37. if (fp == NULL) {
  38. printf("Failed to fetch the track.\n");
  39. return;
  40. }
  41.  
  42. char response[4096];
  43. fread(response, sizeof(char), sizeof(response), fp);
  44.  
  45. pclose(fp);
  46.  
  47. char* uid = decode_json(response, "uid");
  48. char* title = decode_json(response, "title");
  49. char* url64 = decode_json(response, "playUrl64");
  50.  
  51. if (url64 != NULL) {
  52. char filename[512];
  53. sprintf(filename, "%s/%s.mp3", dstDir, title);
  54. char wgetCommand[1024];
  55. sprintf(wgetCommand, "wget '%s' -O '%s'", url64, filename);
  56. system(wgetCommand);
  57. free(url64);
  58. } else {
  59. printf("Failed to fetch the track, may be a paid resource.\n");
  60. }
  61.  
  62. free(uid);
  63. free(title);
  64. }
  65.  
  66. // Function to fetch and download tracks by page number
  67. void fetch_tracks_by_page(const char* albumId, int pageNum, const char* dstDir) {
  68. char command[512];
  69. 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);
  70.  
  71. FILE* fp = popen(command, "r");
  72. if (fp == NULL) {
  73. printf("Failed to fetch the tracks.\n");
  74. return;
  75. }
  76.  
  77. char response[8192];
  78. fread(response, sizeof(char), sizeof(response), fp);
  79.  
  80. pclose(fp);
  81.  
  82. char* trackIds = decode_json(response, "data.tracks[].trackId");
  83. if (trackIds == NULL) {
  84. printf("No tracks found.\n");
  85. return;
  86. }
  87.  
  88. char* token = strtok(trackIds, " \n");
  89. while (token != NULL) {
  90. fetch_track_by_id(token, dstDir);
  91. token = strtok(NULL, " \n");
  92. }
  93.  
  94. free(trackIds);
  95. }
  96.  
  97. // Function to fetch and download tracks by multiple page numbers
  98. void fetch_tracks_by_pages(const char* albumId, const char* pageNumbers, const char* dstDir) {
  99. char* pages = strdup(pageNumbers);
  100. char* token = strtok(pages, " \n");
  101. while (token != NULL) {
  102. int pageNum = atoi(token);
  103. fetch_tracks_by_page(albumId, pageNum, dstDir);
  104. token = strtok(NULL, " \n");
  105. }
  106. free(pages);
  107. }
  108.  
  109. // Main function
  110. int main() {
  111. char albumUrl[512];
  112. printf("Enter the album URL (e.g., https://w...content-available-to-author-only...a.com/album/30945784): ");
  113. fgets(albumUrl, sizeof(albumUrl), stdin);
  114.  
  115. // Remove newline character from the input
  116. if (strlen(albumUrl) > 0 && albumUrl[strlen(albumUrl) - 1] == '\n') {
  117. albumUrl[strlen(albumUrl) - 1] = '\0';
  118. }
  119.  
  120. // Extract album ID from the URL
  121. char* albumId = strstr(albumUrl, "/album/");
  122. if (albumId == NULL) {
  123. printf("Invalid album URL.\n");
  124. return 1;
  125. }
  126. albumId += strlen("/album/");
  127.  
  128. const char* dstDir = ".";
  129.  
  130. printf("Downloading all files...\n");
  131.  
  132. // Fetch all tracks
  133. char command[512];
  134. sprintf(command, "curl -s 'https://w...content-available-to-author-only...a.com/revision/album/v1/getTracksList?albumId=%s&pageNum=0&pageSize=1'", albumId);
  135.  
  136. FILE* fp = popen(command, "r");
  137. if (fp == NULL) {
  138. printf("Failed to fetch the album track count.\n");
  139. return 1;
  140. }
  141.  
  142. char response[4096];
  143. fread(response, sizeof(char), sizeof(response), fp);
  144.  
  145. pclose(fp);
  146.  
  147. char* countStr = decode_json(response, "data.trackTotalCount");
  148. if (countStr == NULL) {
  149. printf("Failed to fetch the album track count.\n");
  150. return 1;
  151. }
  152.  
  153. int count = atoi(countStr);
  154. free(countStr);
  155.  
  156. int pageCount = (count / 30) + 1;
  157. printf("Total count is %d\n", count);
  158.  
  159. for (int i = 0; i < pageCount; i++) {
  160. fetch_tracks_by_page(albumId, i, dstDir);
  161. }
  162.  
  163. printf("All files downloaded successfully.\n");
  164.  
  165. return 0;
  166. }
  167.  
Success #stdin #stdout #stderr 0.05s 11516KB
stdin
https://w...content-available-to-author-only...a.com/album/56788761
stdout
Enter the album URL (e.g., https://w...content-available-to-author-only...a.com/album/30945784): Downloading all files...
Total count is 0
All files downloaded successfully.
stderr
sh: 1: jq: not found
sh: 1: jq: not found
sh: 1: jq: not found
sh: 1: jq: not found
sh: 1: jq: not found
./.mp3: Permission denied