diff --git a/DepotDownloader/ContentDownloader.cs b/DepotDownloader/ContentDownloader.cs index caa50eba..c7dd46cf 100644 --- a/DepotDownloader/ContentDownloader.cs +++ b/DepotDownloader/ContentDownloader.cs @@ -231,59 +231,62 @@ namespace DepotDownloader } var manifests = depotChild["manifests"]; - var manifests_encrypted = depotChild["encryptedmanifests"]; - if (manifests.Children.Count == 0 && manifests_encrypted.Children.Count == 0) + if (manifests.Children.Count == 0) return INVALID_MANIFEST_ID; var node = manifests[branch]["gid"]; - if (node == KeyValue.Invalid && !string.Equals(branch, DEFAULT_BRANCH, StringComparison.OrdinalIgnoreCase)) - { - var node_encrypted = manifests_encrypted[branch]; - if (node_encrypted != KeyValue.Invalid) - { - var password = Config.BetaPassword; - while (string.IsNullOrEmpty(password)) - { - Console.Write("Please enter the password for branch {0}: ", branch); - Config.BetaPassword = password = Console.ReadLine(); - } + // Non passworded branch, found the manifest + if (node.Value != null) + return ulong.Parse(node.Value); - var encrypted_gid = node_encrypted["gid"]; + // If we requested public branch and it had no manifest, nothing to do + if (string.Equals(branch, DEFAULT_BRANCH, StringComparison.OrdinalIgnoreCase)) + return INVALID_MANIFEST_ID; - if (encrypted_gid != KeyValue.Invalid) - { - // Submit the password to Steam now to get encryption keys - await steam3.CheckAppBetaPassword(appId, Config.BetaPassword); + // Either the branch just doesn't exist, or it has a password + var password = Config.BetaPassword; - if (!steam3.AppBetaPasswords.TryGetValue(branch, out var appBetaPassword)) - { - Console.WriteLine("Password was invalid for branch {0}", branch); - return INVALID_MANIFEST_ID; - } + if (string.IsNullOrEmpty(password)) + { + Console.WriteLine($"Branch {branch} was not found, either it does not exist or it has a password."); + } - var input = Util.DecodeHexString(encrypted_gid.Value); - byte[] manifest_bytes; - try - { - manifest_bytes = Util.SymmetricDecryptECB(input, appBetaPassword); - } - catch (Exception e) - { - Console.WriteLine("Failed to decrypt branch {0}: {1}", branch, e.Message); - return INVALID_MANIFEST_ID; - } + while (string.IsNullOrEmpty(password)) + { + Console.Write($"Please enter the password for branch {branch}: "); + Config.BetaPassword = password = Console.ReadLine(); + } - return BitConverter.ToUInt64(manifest_bytes, 0); - } + if (!steam3.AppBetaPasswords.ContainsKey(branch)) + { + // Submit the password to Steam now to get encryption keys + await steam3.CheckAppBetaPassword(appId, Config.BetaPassword); - Console.WriteLine("Unhandled depot encryption for depotId {0}", depotId); + if (!steam3.AppBetaPasswords.TryGetValue(branch, out var appBetaPassword)) + { + Console.WriteLine($"Error: Password was invalid for branch {branch} (or the branch does not exist)"); return INVALID_MANIFEST_ID; } + } + + // Got the password, request private depot section + // TODO: We're probably repeating this request for every depot? + var privateDepotSection = await steam3.GetPrivateBetaDepotSection(appId, branch); + // Now repeat the same code to get the manifest gid from depot section + depotChild = privateDepotSection[depotId.ToString()]; + + if (depotChild == KeyValue.Invalid) return INVALID_MANIFEST_ID; - } + + manifests = depotChild["manifests"]; + + if (manifests.Children.Count == 0) + return INVALID_MANIFEST_ID; + + node = manifests[branch]["gid"]; if (node.Value == null) return INVALID_MANIFEST_ID; diff --git a/DepotDownloader/DepotDownloader.csproj b/DepotDownloader/DepotDownloader.csproj index 1dfcf0ff..976d7740 100644 --- a/DepotDownloader/DepotDownloader.csproj +++ b/DepotDownloader/DepotDownloader.csproj @@ -4,7 +4,7 @@ net9.0 true LatestMajor - 3.0.0 + 3.2.0 Steam Downloading Utility SteamRE Team Copyright © SteamRE Team 2025 @@ -25,8 +25,8 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + - + diff --git a/DepotDownloader/Program.cs b/DepotDownloader/Program.cs index 475c20ba..ae9be3bf 100644 --- a/DepotDownloader/Program.cs +++ b/DepotDownloader/Program.cs @@ -249,6 +249,12 @@ namespace DepotDownloader var branch = GetParameter(args, "-branch") ?? GetParameter(args, "-beta") ?? ContentDownloader.DEFAULT_BRANCH; ContentDownloader.Config.BetaPassword = GetParameter(args, "-branchpassword") ?? GetParameter(args, "-betapassword"); + if (!string.IsNullOrEmpty(ContentDownloader.Config.BetaPassword) && string.IsNullOrEmpty(branch)) + { + Console.WriteLine("Error: Cannot specify -branchpassword when -branch is not specified."); + return 1; + } + ContentDownloader.Config.DownloadAllPlatforms = HasParameter(args, "-all-platforms"); var os = GetParameter(args, "-os"); diff --git a/DepotDownloader/Steam3Session.cs b/DepotDownloader/Steam3Session.cs index 9ebfe536..0155b6a8 100644 --- a/DepotDownloader/Steam3Session.cs +++ b/DepotDownloader/Steam3Session.cs @@ -310,6 +310,22 @@ namespace DepotDownloader } } + public async Task GetPrivateBetaDepotSection(uint appid, string branch) + { + if (!AppBetaPasswords.TryGetValue(branch, out var branchPassword)) // Should be filled by CheckAppBetaPassword + { + return new KeyValue(); + } + + AppTokens.TryGetValue(appid, out var accessToken); // Should be filled by RequestAppInfo + + var privateBeta = await steamApps.PICSGetPrivateBeta(appid, accessToken, branch, branchPassword); + + Console.WriteLine($"Retrieved private beta depot section for {appid} with result: {privateBeta.Result}"); + + return privateBeta.DepotSection; + } + public async Task GetPublishedFileDetails(uint appId, PublishedFileID pubFile) { var pubFileRequest = new CPublishedFile_GetDetails_Request { appid = appId };