Add -output-json option to output -manifest-only as JSON

Adds the System.Text.Json Nuget package
Option alias -json
Readme and help updated
Verified through tests of deep matching original output with JSON output across 1000+ depots (until I got ratelimited)
pull/665/head
Andreas Aronsson 1 month ago
parent d5afc41b97
commit cd1f042c7a

@ -5,9 +5,11 @@ using System;
using System.Buffers; using System.Buffers;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data.SqlTypes;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Text.Json.Nodes;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using SteamKit2; using SteamKit2;
@ -864,7 +866,7 @@ namespace DepotDownloader
if (Config.DownloadManifestOnly) if (Config.DownloadManifestOnly)
{ {
DumpManifestToTextFile(depot, newManifest); DumpManifestToTextFile(depot, newManifest, Config.OutputJson);
return null; return null;
} }
@ -1352,18 +1354,17 @@ namespace DepotDownloader
} }
} }
static void DumpManifestToTextFile(DepotDownloadInfo depot, DepotManifest manifest) static void DumpManifestToTextFile(DepotDownloadInfo depot, DepotManifest manifest, bool asJson)
{ {
var txtManifest = Path.Combine(depot.InstallDir, $"manifest_{depot.DepotId}_{depot.ManifestId}.txt"); var outputFileExtension = asJson ? "json" : "txt";
var txtManifest = Path.Combine(depot.InstallDir, $"manifest_{depot.DepotId}_{depot.ManifestId}.{outputFileExtension}");
using var sw = new StreamWriter(txtManifest); using var sw = new StreamWriter(txtManifest);
sw.WriteLine($"Content Manifest for Depot {depot.DepotId} "); var manifestFiles = manifest.Files ?? [];
sw.WriteLine();
sw.WriteLine($"Manifest ID / date : {depot.ManifestId} / {manifest.CreationTime} ");
var uniqueChunks = new HashSet<byte[]>(new ChunkIdComparer()); var uniqueChunks = new HashSet<byte[]>(new ChunkIdComparer());
foreach (var file in manifest.Files) foreach (var file in manifestFiles)
{ {
foreach (var chunk in file.Chunks) foreach (var chunk in file.Chunks)
{ {
@ -1371,18 +1372,56 @@ namespace DepotDownloader
} }
} }
sw.WriteLine($"Total number of files : {manifest.Files.Count} "); if (asJson)
sw.WriteLine($"Total number of chunks : {uniqueChunks.Count} "); {
sw.WriteLine($"Total bytes on disk : {manifest.TotalUncompressedSize} "); var filesArray = new JsonArray();
sw.WriteLine($"Total bytes compressed : {manifest.TotalCompressedSize} "); foreach (var file in manifestFiles)
sw.WriteLine(); {
sw.WriteLine(); var sha1Hash = Convert.ToHexString(file.FileHash).ToLower();
sw.WriteLine(" Size Chunks File SHA Flags Name"); var fileObject = new JsonObject
{
{ "size", file.TotalSize },
{ "chunks", file.Chunks.Count },
{ "sha", sha1Hash },
{ "flags", Convert.ToString((int) file.Flags, 16) },
{ "name", file.FileName }
};
filesArray.Add(fileObject);
}
foreach (var file in manifest.Files) var manifestObject = new JsonObject
{
{ "description", $"Content Manifest for Depot {depot.DepotId}" },
{ "depotId", depot.DepotId },
{ "manifestId", depot.ManifestId },
{ "manifestCreationTime", manifest.CreationTime },
{ "totalFiles", manifestFiles.Count },
{ "totalChunks", uniqueChunks.Count },
{ "totalBytesOnDisk", manifest.TotalUncompressedSize },
{ "totalBytesCompressed", manifest.TotalCompressedSize },
{ "files", filesArray }
};
sw.WriteLine(manifestObject.ToJsonString());
}
else
{ {
var sha1Hash = Convert.ToHexString(file.FileHash).ToLower(); sw.WriteLine($"Content Manifest for Depot {depot.DepotId} ");
sw.WriteLine($"{file.TotalSize,14:d} {file.Chunks.Count,6:d} {sha1Hash} {(int)file.Flags,5:x} {file.FileName}"); sw.WriteLine();
sw.WriteLine($"Manifest ID / date : {depot.ManifestId} / {manifest.CreationTime} ");
sw.WriteLine($"Total number of files : {manifestFiles.Count} ");
sw.WriteLine($"Total number of chunks : {uniqueChunks.Count} ");
sw.WriteLine($"Total bytes on disk : {manifest.TotalUncompressedSize} ");
sw.WriteLine($"Total bytes compressed : {manifest.TotalCompressedSize} ");
sw.WriteLine();
sw.WriteLine();
sw.WriteLine(" Size Chunks File SHA Flags Name");
foreach (var file in manifestFiles)
{
var sha1Hash = Convert.ToHexString(file.FileHash).ToLower();
sw.WriteLine($"{file.TotalSize,14:d} {file.Chunks.Count,6:d} {sha1Hash} {(int)file.Flags,5:x} {file.FileName}");
}
} }
} }
} }

@ -28,5 +28,6 @@
<PackageReference Include="protobuf-net" Version="3.2.56" /> <PackageReference Include="protobuf-net" Version="3.2.56" />
<PackageReference Include="QRCoder" Version="1.7.0" /> <PackageReference Include="QRCoder" Version="1.7.0" />
<PackageReference Include="SteamKit2" Version="3.3.0" /> <PackageReference Include="SteamKit2" Version="3.3.0" />
<PackageReference Include="System.Text.Json" Version="9.0.10" />
</ItemGroup> </ItemGroup>
</Project> </Project>

@ -32,5 +32,6 @@ namespace DepotDownloader
public bool UseQrCode { get; set; } public bool UseQrCode { get; set; }
public bool SkipAppConfirmation { get; set; } public bool SkipAppConfirmation { get; set; }
public bool OutputJson { get; set; }
} }
} }

@ -156,6 +156,7 @@ namespace DepotDownloader
ContentDownloader.Config.MaxDownloads = GetParameter(args, "-max-downloads", 8); ContentDownloader.Config.MaxDownloads = GetParameter(args, "-max-downloads", 8);
ContentDownloader.Config.LoginID = HasParameter(args, "-loginid") ? GetParameter<uint>(args, "-loginid") : null; ContentDownloader.Config.LoginID = HasParameter(args, "-loginid") ? GetParameter<uint>(args, "-loginid") : null;
ContentDownloader.Config.OutputJson = HasParameter(args, "-output-json") || HasParameter(args, "-json");
#endregion #endregion
@ -529,6 +530,7 @@ namespace DepotDownloader
Console.WriteLine(" -max-downloads <#> - maximum number of chunks to download concurrently. (default: 8)."); 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(" -loginid <#> - a unique 32-bit integer Steam LogonID in decimal, required if running multiple instances of DepotDownloader concurrently.");
Console.WriteLine(" -use-lancache - forces downloads over the local network via a Lancache instance."); Console.WriteLine(" -use-lancache - forces downloads over the local network via a Lancache instance.");
Console.WriteLine(" -output-json - outputs -manifest-only manifest as JSON.");
Console.WriteLine(); Console.WriteLine();
Console.WriteLine(" -debug - enable verbose debug logging."); Console.WriteLine(" -debug - enable verbose debug logging.");
Console.WriteLine(" -V or --version - print version and runtime."); Console.WriteLine(" -V or --version - print version and runtime.");

@ -102,6 +102,7 @@ Parameter | Description
`-cellid <#>` | the overridden CellID of the content server to download from. `-cellid <#>` | the overridden CellID of the content server to download from.
`-max-downloads <#>` | maximum number of chunks to download concurrently. (default: 8). `-max-downloads <#>` | maximum number of chunks to download concurrently. (default: 8).
`-use-lancache` | forces downloads over the local network via a Lancache instance. `-use-lancache` | forces downloads over the local network via a Lancache instance.
`-output-json` | outputs -manifest-only manifest as JSON.
#### Other #### Other

Loading…
Cancel
Save