Created
          May 19, 2025 06:26 
        
      - 
      
- 
        Save Lewiscowles1986/d509fce754bfa154659a2b8e98aeaa94 to your computer and use it in GitHub Desktop. 
    Forgecraft-manifest-downloader PHP
  
        
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | <?php | |
| function relativeDirectory($path) { | |
| return __DIR__ . "/" . $path; | |
| } | |
| $manifestPath = relativeDirectory("manifest.json"); | |
| $downloadDir = relativeDirectory("mods"); | |
| $userAgent = "CurseForge/Downloader+1.0"; | |
| $cookieFile = relativeDirectory("cookies.txt"); // Optional. Comment this line out if not using cookies. | |
| if (!file_exists($manifestPath)) { | |
| die("manifest.json not found\n"); | |
| } | |
| $manifest = json_decode(file_get_contents($manifestPath), true); | |
| if (!is_array($manifest) || !isset($manifest['files'])) { | |
| die("Invalid manifest.json format\n"); | |
| } | |
| // Create downloads directory | |
| if (!is_dir($downloadDir)) { | |
| mkdir($downloadDir, 0777, true); | |
| } | |
| foreach ($manifest['files'] as $file) { | |
| $projectID = $file['projectID']; | |
| $fileID = $file['fileID']; | |
| $metaUrl = "https://www.curseforge.com/api/v1/mods/$projectID/files/$fileID"; | |
| $downloadUrl = "https://www.curseforge.com/api/v1/mods/$projectID/files/$fileID/download"; | |
| echo "Fetching metadata for project $projectID, file $fileID...\n"; | |
| $meta = curlGetJson($metaUrl, $userAgent, $cookieFile); | |
| if (!$meta || !isset($meta['data']['fileName'])) { | |
| echo "Failed to retrieve fileName\n"; | |
| continue; | |
| } | |
| $fileName = $meta['data']['fileName']; | |
| $outputPath = "$downloadDir/$fileName"; | |
| echo "Downloading $fileName...\n"; | |
| $success = curlDownload($downloadUrl, $outputPath, $userAgent, $cookieFile); | |
| if ($success) { | |
| echo "Downloaded to $outputPath\n"; | |
| } else { | |
| echo "Failed to download $fileName\n"; | |
| } | |
| } | |
| function curlGetJson($url, $userAgent, $cookieFile = null) | |
| { | |
| $ch = curl_init($url); | |
| curl_setopt_array($ch, [ | |
| CURLOPT_RETURNTRANSFER => true, | |
| CURLOPT_USERAGENT => $userAgent, | |
| CURLOPT_FOLLOWLOCATION => true, | |
| ]); | |
| if ($cookieFile) { | |
| curl_setopt($ch, CURLOPT_COOKIEFILE, $cookieFile); | |
| curl_setopt($ch, CURLOPT_COOKIEJAR, $cookieFile); | |
| } | |
| $response = curl_exec($ch); | |
| curl_close($ch); | |
| return json_decode($response, true); | |
| } | |
| function curlDownload($url, $savePath, $userAgent, $cookieFile = null) | |
| { | |
| $fp = fopen($savePath, 'w'); | |
| if (!$fp) return false; | |
| $ch = curl_init($url); | |
| curl_setopt_array($ch, [ | |
| CURLOPT_FILE => $fp, | |
| CURLOPT_USERAGENT => $userAgent, | |
| CURLOPT_FOLLOWLOCATION => true, | |
| ]); | |
| if ($cookieFile) { | |
| curl_setopt($ch, CURLOPT_COOKIEFILE, $cookieFile); | |
| curl_setopt($ch, CURLOPT_COOKIEJAR, $cookieFile); | |
| } | |
| $success = curl_exec($ch); | |
| curl_close($ch); | |
| fclose($fp); | |
| return $success; | |
| } | 
2025 may php 8.4.7 used to test this on the all the mods 10-2.47 modpack
  
    Sign up for free
    to join this conversation on GitHub.
    Already have an account?
    Sign in to comment
  
            
relativeDirectory could change.
What Might be a better option would be to build a separate script which can do the download, and then sub-process / thread that part... IDK, I like simplicity of a <100 line file today.