Implement private branches

Fixes #514
Fixes #620
pull/634/head DepotDownloader_3.2.0
Pavel Djundik 5 months ago
parent 272f5b646a
commit 665f83983b

@ -231,59 +231,62 @@ namespace DepotDownloader
} }
var manifests = depotChild["manifests"]; 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; return INVALID_MANIFEST_ID;
var node = manifests[branch]["gid"]; var node = manifests[branch]["gid"];
if (node == KeyValue.Invalid && !string.Equals(branch, DEFAULT_BRANCH, StringComparison.OrdinalIgnoreCase)) // Non passworded branch, found the manifest
{ if (node.Value != null)
var node_encrypted = manifests_encrypted[branch]; return ulong.Parse(node.Value);
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();
}
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) // Either the branch just doesn't exist, or it has a password
{ var password = Config.BetaPassword;
// Submit the password to Steam now to get encryption keys
await steam3.CheckAppBetaPassword(appId, Config.BetaPassword);
if (!steam3.AppBetaPasswords.TryGetValue(branch, out var appBetaPassword)) if (string.IsNullOrEmpty(password))
{ {
Console.WriteLine("Password was invalid for branch {0}", branch); Console.WriteLine($"Branch {branch} was not found, either it does not exist or it has a password.");
return INVALID_MANIFEST_ID; }
}
var input = Util.DecodeHexString(encrypted_gid.Value); while (string.IsNullOrEmpty(password))
byte[] manifest_bytes; {
try Console.Write($"Please enter the password for branch {branch}: ");
{ Config.BetaPassword = password = Console.ReadLine();
manifest_bytes = Util.SymmetricDecryptECB(input, appBetaPassword); }
}
catch (Exception e)
{
Console.WriteLine("Failed to decrypt branch {0}: {1}", branch, e.Message);
return INVALID_MANIFEST_ID;
}
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; 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; return INVALID_MANIFEST_ID;
}
manifests = depotChild["manifests"];
if (manifests.Children.Count == 0)
return INVALID_MANIFEST_ID;
node = manifests[branch]["gid"];
if (node.Value == null) if (node.Value == null)
return INVALID_MANIFEST_ID; return INVALID_MANIFEST_ID;

@ -4,7 +4,7 @@
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild> <EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<RollForward>LatestMajor</RollForward> <RollForward>LatestMajor</RollForward>
<Version>3.0.0</Version> <Version>3.2.0</Version>
<Description>Steam Downloading Utility</Description> <Description>Steam Downloading Utility</Description>
<Authors>SteamRE Team</Authors> <Authors>SteamRE Team</Authors>
<Copyright>Copyright © SteamRE Team 2025</Copyright> <Copyright>Copyright © SteamRE Team 2025</Copyright>
@ -25,8 +25,8 @@
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="protobuf-net" Version="3.2.46" /> <PackageReference Include="protobuf-net" Version="3.2.52" />
<PackageReference Include="QRCoder" Version="1.6.0" /> <PackageReference Include="QRCoder" Version="1.6.0" />
<PackageReference Include="SteamKit2" Version="3.0.2" /> <PackageReference Include="SteamKit2" Version="3.1.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

@ -249,6 +249,12 @@ namespace DepotDownloader
var branch = GetParameter<string>(args, "-branch") ?? GetParameter<string>(args, "-beta") ?? ContentDownloader.DEFAULT_BRANCH; var branch = GetParameter<string>(args, "-branch") ?? GetParameter<string>(args, "-beta") ?? ContentDownloader.DEFAULT_BRANCH;
ContentDownloader.Config.BetaPassword = GetParameter<string>(args, "-branchpassword") ?? GetParameter<string>(args, "-betapassword"); ContentDownloader.Config.BetaPassword = GetParameter<string>(args, "-branchpassword") ?? GetParameter<string>(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"); ContentDownloader.Config.DownloadAllPlatforms = HasParameter(args, "-all-platforms");
var os = GetParameter<string>(args, "-os"); var os = GetParameter<string>(args, "-os");

@ -310,6 +310,22 @@ namespace DepotDownloader
} }
} }
public async Task<KeyValue> 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<PublishedFileDetails> GetPublishedFileDetails(uint appId, PublishedFileID pubFile) public async Task<PublishedFileDetails> GetPublishedFileDetails(uint appId, PublishedFileID pubFile)
{ {
var pubFileRequest = new CPublishedFile_GetDetails_Request { appid = appId }; var pubFileRequest = new CPublishedFile_GetDetails_Request { appid = appId };

Loading…
Cancel
Save