Skip to content

Commit 665f839

Browse files
committed
Implement private branches
Fixes #514 Fixes #620
1 parent 272f5b6 commit 665f839

File tree

4 files changed

+66
-41
lines changed

4 files changed

+66
-41
lines changed

DepotDownloader/ContentDownloader.cs

Lines changed: 41 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -231,59 +231,62 @@ static async Task<ulong> GetSteam3DepotManifest(uint depotId, uint appId, string
231231
}
232232

233233
var manifests = depotChild["manifests"];
234-
var manifests_encrypted = depotChild["encryptedmanifests"];
235234

236-
if (manifests.Children.Count == 0 && manifests_encrypted.Children.Count == 0)
235+
if (manifests.Children.Count == 0)
237236
return INVALID_MANIFEST_ID;
238237

239238
var node = manifests[branch]["gid"];
240239

241-
if (node == KeyValue.Invalid && !string.Equals(branch, DEFAULT_BRANCH, StringComparison.OrdinalIgnoreCase))
242-
{
243-
var node_encrypted = manifests_encrypted[branch];
244-
if (node_encrypted != KeyValue.Invalid)
245-
{
246-
var password = Config.BetaPassword;
247-
while (string.IsNullOrEmpty(password))
248-
{
249-
Console.Write("Please enter the password for branch {0}: ", branch);
250-
Config.BetaPassword = password = Console.ReadLine();
251-
}
240+
// Non passworded branch, found the manifest
241+
if (node.Value != null)
242+
return ulong.Parse(node.Value);
252243

253-
var encrypted_gid = node_encrypted["gid"];
244+
// If we requested public branch and it had no manifest, nothing to do
245+
if (string.Equals(branch, DEFAULT_BRANCH, StringComparison.OrdinalIgnoreCase))
246+
return INVALID_MANIFEST_ID;
254247

255-
if (encrypted_gid != KeyValue.Invalid)
256-
{
257-
// Submit the password to Steam now to get encryption keys
258-
await steam3.CheckAppBetaPassword(appId, Config.BetaPassword);
248+
// Either the branch just doesn't exist, or it has a password
249+
var password = Config.BetaPassword;
259250

260-
if (!steam3.AppBetaPasswords.TryGetValue(branch, out var appBetaPassword))
261-
{
262-
Console.WriteLine("Password was invalid for branch {0}", branch);
263-
return INVALID_MANIFEST_ID;
264-
}
251+
if (string.IsNullOrEmpty(password))
252+
{
253+
Console.WriteLine($"Branch {branch} was not found, either it does not exist or it has a password.");
254+
}
265255

266-
var input = Util.DecodeHexString(encrypted_gid.Value);
267-
byte[] manifest_bytes;
268-
try
269-
{
270-
manifest_bytes = Util.SymmetricDecryptECB(input, appBetaPassword);
271-
}
272-
catch (Exception e)
273-
{
274-
Console.WriteLine("Failed to decrypt branch {0}: {1}", branch, e.Message);
275-
return INVALID_MANIFEST_ID;
276-
}
256+
while (string.IsNullOrEmpty(password))
257+
{
258+
Console.Write($"Please enter the password for branch {branch}: ");
259+
Config.BetaPassword = password = Console.ReadLine();
260+
}
277261

278-
return BitConverter.ToUInt64(manifest_bytes, 0);
279-
}
262+
if (!steam3.AppBetaPasswords.ContainsKey(branch))
263+
{
264+
// Submit the password to Steam now to get encryption keys
265+
await steam3.CheckAppBetaPassword(appId, Config.BetaPassword);
280266

281-
Console.WriteLine("Unhandled depot encryption for depotId {0}", depotId);
267+
if (!steam3.AppBetaPasswords.TryGetValue(branch, out var appBetaPassword))
268+
{
269+
Console.WriteLine($"Error: Password was invalid for branch {branch} (or the branch does not exist)");
282270
return INVALID_MANIFEST_ID;
283271
}
272+
}
273+
274+
// Got the password, request private depot section
275+
// TODO: We're probably repeating this request for every depot?
276+
var privateDepotSection = await steam3.GetPrivateBetaDepotSection(appId, branch);
284277

278+
// Now repeat the same code to get the manifest gid from depot section
279+
depotChild = privateDepotSection[depotId.ToString()];
280+
281+
if (depotChild == KeyValue.Invalid)
285282
return INVALID_MANIFEST_ID;
286-
}
283+
284+
manifests = depotChild["manifests"];
285+
286+
if (manifests.Children.Count == 0)
287+
return INVALID_MANIFEST_ID;
288+
289+
node = manifests[branch]["gid"];
287290

288291
if (node.Value == null)
289292
return INVALID_MANIFEST_ID;

DepotDownloader/DepotDownloader.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<TargetFramework>net9.0</TargetFramework>
55
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
66
<RollForward>LatestMajor</RollForward>
7-
<Version>3.0.0</Version>
7+
<Version>3.2.0</Version>
88
<Description>Steam Downloading Utility</Description>
99
<Authors>SteamRE Team</Authors>
1010
<Copyright>Copyright © SteamRE Team 2025</Copyright>
@@ -25,8 +25,8 @@
2525
<PrivateAssets>all</PrivateAssets>
2626
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
2727
</PackageReference>
28-
<PackageReference Include="protobuf-net" Version="3.2.46" />
28+
<PackageReference Include="protobuf-net" Version="3.2.52" />
2929
<PackageReference Include="QRCoder" Version="1.6.0" />
30-
<PackageReference Include="SteamKit2" Version="3.0.2" />
30+
<PackageReference Include="SteamKit2" Version="3.1.0" />
3131
</ItemGroup>
3232
</Project>

DepotDownloader/Program.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,12 @@ ex is ContentDownloaderException
249249
var branch = GetParameter<string>(args, "-branch") ?? GetParameter<string>(args, "-beta") ?? ContentDownloader.DEFAULT_BRANCH;
250250
ContentDownloader.Config.BetaPassword = GetParameter<string>(args, "-branchpassword") ?? GetParameter<string>(args, "-betapassword");
251251

252+
if (!string.IsNullOrEmpty(ContentDownloader.Config.BetaPassword) && string.IsNullOrEmpty(branch))
253+
{
254+
Console.WriteLine("Error: Cannot specify -branchpassword when -branch is not specified.");
255+
return 1;
256+
}
257+
252258
ContentDownloader.Config.DownloadAllPlatforms = HasParameter(args, "-all-platforms");
253259

254260
var os = GetParameter<string>(args, "-os");

DepotDownloader/Steam3Session.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,22 @@ public async Task CheckAppBetaPassword(uint appid, string password)
310310
}
311311
}
312312

313+
public async Task<KeyValue> GetPrivateBetaDepotSection(uint appid, string branch)
314+
{
315+
if (!AppBetaPasswords.TryGetValue(branch, out var branchPassword)) // Should be filled by CheckAppBetaPassword
316+
{
317+
return new KeyValue();
318+
}
319+
320+
AppTokens.TryGetValue(appid, out var accessToken); // Should be filled by RequestAppInfo
321+
322+
var privateBeta = await steamApps.PICSGetPrivateBeta(appid, accessToken, branch, branchPassword);
323+
324+
Console.WriteLine($"Retrieved private beta depot section for {appid} with result: {privateBeta.Result}");
325+
326+
return privateBeta.DepotSection;
327+
}
328+
313329
public async Task<PublishedFileDetails> GetPublishedFileDetails(uint appId, PublishedFileID pubFile)
314330
{
315331
var pubFileRequest = new CPublishedFile_GetDetails_Request { appid = appId };

0 commit comments

Comments
 (0)