From 341b8b05e1983350b231a470988604f1a97e4690 Mon Sep 17 00:00:00 2001 From: Alstruit <34786806+Alstruit@users.noreply.github.com> Date: Tue, 3 Dec 2024 10:28:35 -0600 Subject: [PATCH] Add support for multiple appids. --- DepotDownloader/ContentDownloader.cs | 9 +- DepotDownloader/Program.cs | 192 ++++++++++++++++++--------- 2 files changed, 132 insertions(+), 69 deletions(-) diff --git a/DepotDownloader/ContentDownloader.cs b/DepotDownloader/ContentDownloader.cs index a089f122..efb4e623 100644 --- a/DepotDownloader/ContentDownloader.cs +++ b/DepotDownloader/ContentDownloader.cs @@ -47,7 +47,7 @@ namespace DepotDownloader public byte[] DepotKey { get; } = depotKey; } - static bool CreateDirectories(uint depotId, uint depotVersion, out string installDir) + static bool CreateDirectories(uint appId, uint depotId, uint depotVersion, out string installDir) { installDir = null; try @@ -56,6 +56,9 @@ namespace DepotDownloader { Directory.CreateDirectory(DEFAULT_DOWNLOAD_DIR); + var appPath = Path.Combine(DEFAULT_DOWNLOAD_DIR, appId.ToString()); + Directory.CreateDirectory(appPath); + var depotPath = Path.Combine(DEFAULT_DOWNLOAD_DIR, depotId.ToString()); Directory.CreateDirectory(depotPath); @@ -388,7 +391,7 @@ namespace DepotDownloader private static async Task DownloadWebFile(uint appId, string fileName, string url) { - if (!CreateDirectories(appId, 0, out var installDir)) + if (!CreateDirectories(appId, appId, 0, out var installDir)) { Console.WriteLine("Error: Unable to create install directories!"); return; @@ -603,7 +606,7 @@ namespace DepotDownloader var uVersion = GetSteam3AppBuildNumber(appId, branch); - if (!CreateDirectories(depotId, uVersion, out var installDir)) + if (!CreateDirectories(appId, depotId, uVersion, out var installDir)) { Console.WriteLine("Error: Unable to create install directories!"); return null; diff --git a/DepotDownloader/Program.cs b/DepotDownloader/Program.cs index ea65385b..9cb99c30 100644 --- a/DepotDownloader/Program.cs +++ b/DepotDownloader/Program.cs @@ -124,24 +124,36 @@ namespace DepotDownloader #endregion - var appId = GetParameter(args, "-app", ContentDownloader.INVALID_APP_ID); - if (appId == ContentDownloader.INVALID_APP_ID) + var appIdList = GetParameterList(args, "-app"); + if (appIdList.Count == 0) { Console.WriteLine("Error: -app not specified!"); return 1; } - var pubFile = GetParameter(args, "-pubfile", ContentDownloader.INVALID_MANIFEST_ID); - var ugcId = GetParameter(args, "-ugc", ContentDownloader.INVALID_MANIFEST_ID); - if (pubFile != ContentDownloader.INVALID_MANIFEST_ID) + + var pubFileList = GetParameterList(args, "-pubfile"); + var ugcIdList = GetParameterList(args, "-ugc"); + + if (pubFileList.Count > 0) { - #region Pubfile Downloading + if (pubFileList.Count != appIdList.Count) + { + Console.WriteLine("Error: Number of -pubfile arguments does not match number of -app arguments."); + return 1; + } if (InitializeSteam(username, password)) { try { - await ContentDownloader.DownloadPubfileAsync(appId, pubFile).ConfigureAwait(false); + for (var i = 0; i < appIdList.Count; i++) + { + var appId = appIdList[i]; + var pubFile = pubFileList[i]; + + await ContentDownloader.DownloadPubfileAsync(appId, pubFile).ConfigureAwait(false); + } } catch (Exception ex) when ( ex is ContentDownloaderException @@ -152,7 +164,7 @@ namespace DepotDownloader } catch (Exception e) { - Console.WriteLine("Download failed to due to an unhandled exception: {0}", e.Message); + Console.WriteLine("Download failed due to an unhandled exception: {0}", e.Message); throw; } finally @@ -165,18 +177,27 @@ namespace DepotDownloader Console.WriteLine("Error: InitializeSteam failed"); return 1; } - - #endregion } - else if (ugcId != ContentDownloader.INVALID_MANIFEST_ID) + + else if (ugcIdList.Count > 0) { - #region UGC Downloading + if (ugcIdList.Count != appIdList.Count) + { + Console.WriteLine("Error: Number of -ugc arguments does not match number of -app arguments."); + return 1; + } if (InitializeSteam(username, password)) { try { - await ContentDownloader.DownloadUGCAsync(appId, ugcId).ConfigureAwait(false); + for (var i = 0; i < appIdList.Count; i++) + { + var appId = appIdList[i]; + var ugcId = ugcIdList[i]; + + await ContentDownloader.DownloadUGCAsync(appId, ugcId).ConfigureAwait(false); + } } catch (Exception ex) when ( ex is ContentDownloaderException @@ -187,7 +208,7 @@ namespace DepotDownloader } catch (Exception e) { - Console.WriteLine("Download failed to due to an unhandled exception: {0}", e.Message); + Console.WriteLine("Download failed due to an unhandled exception: {0}", e.Message); throw; } finally @@ -200,9 +221,8 @@ namespace DepotDownloader Console.WriteLine("Error: InitializeSteam failed"); return 1; } - - #endregion } + else { #region App downloading @@ -241,32 +261,60 @@ namespace DepotDownloader var lv = HasParameter(args, "-lowviolence"); - var depotManifestIds = new List<(uint, ulong)>(); - var isUGC = false; var depotIdList = GetParameterList(args, "-depot"); var manifestIdList = GetParameterList(args, "-manifest"); - if (manifestIdList.Count > 0) - { - if (depotIdList.Count != manifestIdList.Count) - { - Console.WriteLine("Error: -manifest requires one id for every -depot specified"); - return 1; - } - var zippedDepotManifest = depotIdList.Zip(manifestIdList, (depotId, manifestId) => (depotId, manifestId)); - depotManifestIds.AddRange(zippedDepotManifest); - } - else - { - depotManifestIds.AddRange(depotIdList.Select(depotId => (depotId, ContentDownloader.INVALID_MANIFEST_ID))); - } if (InitializeSteam(username, password)) { try { - await ContentDownloader.DownloadAppAsync(appId, depotManifestIds, branch, os, arch, language, lv, isUGC).ConfigureAwait(false); + foreach (var appId in appIdList) + + { + + var depotManifestIds = new List<(uint, ulong)>(); + + var isUGC = false; + + + + if (manifestIdList.Count > 0) + + { + + if (depotIdList.Count != manifestIdList.Count) + + { + + Console.WriteLine("Error: -manifest requires one id for every -depot specified"); + + return 1; + + } + + + + var zippedDepotManifest = depotIdList.Zip(manifestIdList, (depotId, manifestId) => (depotId, manifestId)); + + depotManifestIds.AddRange(zippedDepotManifest); + + } + + else + + { + + depotManifestIds.AddRange(depotIdList.Select(depotId => (depotId, ContentDownloader.INVALID_MANIFEST_ID))); + + } + + + + await ContentDownloader.DownloadAppAsync(appId, depotManifestIds, branch, os, arch, language, lv, isUGC).ConfigureAwait(false); + + } } catch (Exception ex) when ( ex is ContentDownloaderException @@ -394,47 +442,59 @@ namespace DepotDownloader { // Do not use tabs to align parameters here because tab size may differ Console.WriteLine(); - Console.WriteLine("Usage: downloading one or all depots for an app:"); - Console.WriteLine(" depotdownloader -app [-depot [-manifest ]]"); + Console.WriteLine("Usage: downloading depots for one or more apps:"); + Console.WriteLine(" depotdownloader -app [-depot [-manifest ]]"); Console.WriteLine(" [-username [-password ]] [other options]"); Console.WriteLine(); - Console.WriteLine("Usage: downloading a workshop item using pubfile id"); - Console.WriteLine(" depotdownloader -app -pubfile [-username [-password ]]"); - Console.WriteLine("Usage: downloading a workshop item using ugc id"); - Console.WriteLine(" depotdownloader -app -ugc [-username [-password ]]"); + Console.WriteLine("Examples:"); + Console.WriteLine(" Single list format:"); + Console.WriteLine(" depotdownloader -app \"10 20 30\" -depot \"11 22 33\" -manifest \"1111 2222 3333\""); + Console.WriteLine(); + Console.WriteLine(" Group list format:"); + Console.WriteLine(" depotdownloader -app 10 -depot 11 -manifest 1111 -app 20 -depot 22 -manifest 2222"); + Console.WriteLine(" -app 30 -depot 33 -manifest 3333"); + Console.WriteLine(); + Console.WriteLine("Usage: downloading a workshop item using pubfile id:"); + Console.WriteLine(" depotdownloader -app -pubfile [-username [-password ]]"); + Console.WriteLine("Usage: downloading a workshop item using ugc id:"); + Console.WriteLine(" depotdownloader -app -ugc [-username [-password ]]"); Console.WriteLine(); Console.WriteLine("Parameters:"); - Console.WriteLine(" -app <#> - the AppID to download."); - Console.WriteLine(" -depot <#> - the DepotID to download."); - Console.WriteLine(" -manifest - manifest id of content to download (requires -depot, default: current for branch)."); - Console.WriteLine($" -beta - download from specified branch if available (default: {ContentDownloader.DEFAULT_BRANCH})."); - Console.WriteLine(" -betapassword - branch password if applicable."); - Console.WriteLine(" -all-platforms - downloads all platform-specific depots when -app is used."); - Console.WriteLine(" -all-archs - download all architecture-specific depots when -app is used."); - Console.WriteLine(" -os - the operating system for which to download the game (windows, macos or linux, default: OS the program is currently running on)"); - Console.WriteLine(" -osarch - the architecture for which to download the game (32 or 64, default: the host's architecture)"); - Console.WriteLine(" -all-languages - download all language-specific depots when -app is used."); - Console.WriteLine(" -language - the language for which to download the game (default: english)"); - Console.WriteLine(" -lowviolence - download low violence depots when -app is used."); + Console.WriteLine(" -app <# or \"# # ...\"> - the AppID(s) to download. Provide multiple IDs separated by spaces."); + Console.WriteLine(" -depot <# or \"# # ...\"> - the DepotID(s) to download. Must correspond to the provided AppIDs."); + Console.WriteLine(" -manifest <# or \"# # ...\"> - manifest ID(s) of content to download (requires -depot). Must correspond to the provided DepotIDs."); + Console.WriteLine($" -beta - download from specified branch if available (default: {ContentDownloader.DEFAULT_BRANCH})."); + Console.WriteLine(" -betapassword - branch password if applicable."); + Console.WriteLine(" -all-platforms - downloads all platform-specific depots when -app is used."); + Console.WriteLine(" -all-archs - download all architecture-specific depots when -app is used."); + Console.WriteLine(" -os - the operating system for which to download the game (windows, macos, or linux)."); + Console.WriteLine(" (default: OS the program is currently running on)"); + Console.WriteLine(" -osarch - the architecture for which to download the game (32 or 64)."); + Console.WriteLine(" (default: the host's architecture)"); + Console.WriteLine(" -all-languages - download all language-specific depots when -app is used."); + Console.WriteLine(" -language - the language for which to download the game (default: english)"); + Console.WriteLine(" -lowviolence - download low violence depots when -app is used."); Console.WriteLine(); - Console.WriteLine(" -ugc <#> - the UGC ID to download."); - Console.WriteLine(" -pubfile <#> - the PublishedFileId to download. (Will automatically resolve to UGC id)"); + Console.WriteLine(" -ugc <# or \"# # ...\"> - the UGC ID(s) to download. Must correspond to the provided AppIDs."); + Console.WriteLine(" -pubfile <# or \"# # ...\"> - the PublishedFileId(s) to download. Will automatically resolve to UGC IDs."); Console.WriteLine(); - Console.WriteLine(" -username - the username of the account to login to for restricted content."); - Console.WriteLine(" -password - the password of the account to login to for restricted content."); - Console.WriteLine(" -remember-password - if set, remember the password for subsequent logins of this user."); - Console.WriteLine(" use -username -remember-password as login credentials."); + Console.WriteLine(" -username - the username of the account to login to for restricted content."); + Console.WriteLine(" -password - the password of the account to login to for restricted content."); + Console.WriteLine(" -remember-password - if set, remember the password for subsequent logins of this user."); + Console.WriteLine(" Use -username -remember-password as login credentials."); Console.WriteLine(); - Console.WriteLine(" -dir - the directory in which to place downloaded files."); - Console.WriteLine(" -filelist - the name of a local file that contains a list of files to download (from the manifest)."); - Console.WriteLine(" prefix file path with `regex:` if you want to match with regex. each file path should be on their own line."); + Console.WriteLine(" -dir - the directory in which to place downloaded files."); + Console.WriteLine(" -filelist - the name of a local file that contains a list of files to download (from the manifest)."); + Console.WriteLine(" Prefix file path with `regex:` if you want to match with regex."); + Console.WriteLine(" Each file path should be on its own line."); Console.WriteLine(); - Console.WriteLine(" -validate - include checksum verification of files already downloaded"); - Console.WriteLine(" -manifest-only - downloads a human readable manifest for any depots that would be downloaded."); - Console.WriteLine(" -cellid <#> - the overridden CellID of the content server to download from."); - Console.WriteLine(" -max-servers <#> - maximum number of content servers to use. (default: 20)."); - Console.WriteLine(" -max-downloads <#> - maximum number of chunks to download concurrently. (default: 8)."); - Console.WriteLine(" -loginid <#> - a unique 32-bit integer Steam LogonID in decimal, required if running multiple instances of DepotDownloader concurrently."); + Console.WriteLine(" -validate - include checksum verification of files already downloaded."); + Console.WriteLine(" -manifest-only - downloads a human-readable manifest for any depots that would be downloaded."); + Console.WriteLine(" -cellid <#> - the overridden CellID of the content server to download from."); + Console.WriteLine(" -max-servers <#> - maximum number of content servers to use (default: 20)."); + Console.WriteLine(" -max-downloads <#> - maximum number of chunks to download concurrently (default: 8)."); + Console.WriteLine(" -loginid <#> - a unique 32-bit integer Steam LogonID in decimal, required if running"); + Console.WriteLine(" multiple instances of DepotDownloader concurrently."); } static void PrintVersion(bool printExtra = false)