Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 51 additions & 4 deletions DepotDownloader/AccountSettingsStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,16 @@ class AccountSettingsStore

string FileName;

AccountSettingsStore()
public string DefaultUsername { get; private set; }

public bool LoadedFromEnv { get; private set; }

AccountSettingsStore(bool loadedFromEnv = false)
{
ContentServerPenalty = new ConcurrentDictionary<string, int>();
LoginTokens = new(StringComparer.OrdinalIgnoreCase);
GuardData = new(StringComparer.OrdinalIgnoreCase);
LoadedFromEnv = loadedFromEnv;
}

static bool Loaded
Expand All @@ -49,7 +54,28 @@ public static void LoadFromFile(string filename)
if (Loaded)
throw new Exception("Config already loaded");

if (IsolatedStorage.FileExists(filename))
var env = System.Environment.GetEnvironmentVariable("DEPOTDOWNLOADER_TOKEN");
if (!string.IsNullOrWhiteSpace(env))
{
Instance = new AccountSettingsStore(true);
var pieces = env.Trim().Split(":", 3);
if (pieces.Length == 2 || pieces.Length == 3)
{
var username = pieces[0];
var token = pieces[1];
Instance.DefaultUsername = username;
Instance.LoginTokens[username] = token;
if (pieces.Length == 3 && !string.IsNullOrWhiteSpace(pieces[2]))
{
Instance.GuardData[username] = pieces[2];
}
}
else
{
Console.Error.WriteLine("Failed to parse DEPOTDOWNLOADER_TOKEN");
}
}
else if (IsolatedStorage.FileExists(filename))
{
try
{
Expand All @@ -59,7 +85,7 @@ public static void LoadFromFile(string filename)
}
catch (IOException ex)
{
Console.WriteLine("Failed to load account settings: {0}", ex.Message);
Console.Error.WriteLine("Failed to load account settings: {0}", ex.Message);
Instance = new AccountSettingsStore();
}
}
Expand All @@ -76,6 +102,9 @@ public static void Save()
if (!Loaded)
throw new Exception("Saved config before loading");

if (Instance.LoadedFromEnv)
return; // don't save credentials loaded from env vars; the whole point is that the user is managing the storage, not the program.

try
{
using var fs = IsolatedStorage.OpenFile(Instance.FileName, FileMode.Create, FileAccess.Write);
Expand All @@ -84,7 +113,25 @@ public static void Save()
}
catch (IOException ex)
{
Console.WriteLine("Failed to save account settings: {0}", ex.Message);
Console.Error.WriteLine("Failed to save account settings: {0}", ex.Message);
}
}

public static void PrintToConsole()
{
if (!Loaded)
throw new Exception("Printed config before loading");

foreach (var (username, token) in Instance.LoginTokens)
{
_ = Instance.GuardData.TryGetValue(username, out var guard);
if (guard == null) guard = "";
Console.WriteLine($"{username}:{token}:{guard}");
}

if (Instance.LoginTokens.Count == 0)
{
Console.Error.WriteLine("warn: no accounts saved");
}
}
}
Expand Down
37 changes: 30 additions & 7 deletions DepotDownloader/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,19 @@ static async Task<int> Main(string[] args)

AccountSettingsStore.LoadFromFile("account.config");

if (HasParameter(args, "-show-tokens") || HasParameter(args, "-show-token"))
{
if (args.Length != 1)
{
Console.Error.WriteLine("Error: -show-tokens must be used by itself");
return 1;
}

AccountSettingsStore.PrintToConsole();

return 0;
}

#region Common Options

// Not using HasParameter because it is case insensitive
Expand All @@ -58,29 +71,29 @@ static async Task<int> Main(string[] args)
DebugLog.Enabled = true;
DebugLog.AddListener((category, message) =>
{
Console.WriteLine("[{0}] {1}", category, message);
Console.Error.WriteLine("[{0}] {1}", category, message);
});

var httpEventListener = new HttpDiagnosticEventListener();
}

var username = GetParameter<string>(args, "-username") ?? GetParameter<string>(args, "-user");
var username = GetParameter<string>(args, "-username") ?? GetParameter<string>(args, "-user") ?? AccountSettingsStore.Instance.DefaultUsername;
var password = GetParameter<string>(args, "-password") ?? GetParameter<string>(args, "-pass");
ContentDownloader.Config.RememberPassword = HasParameter(args, "-remember-password");
ContentDownloader.Config.RememberPassword = HasParameter(args, "-remember-password") || AccountSettingsStore.Instance.LoadedFromEnv;
ContentDownloader.Config.UseQrCode = HasParameter(args, "-qr");
ContentDownloader.Config.SkipAppConfirmation = HasParameter(args, "-no-mobile");

if (username == null)
{
if (ContentDownloader.Config.RememberPassword && !ContentDownloader.Config.UseQrCode)
{
Console.WriteLine("Error: -remember-password can not be used without -username or -qr.");
Console.Error.WriteLine("Error: -remember-password can not be used without -username or -qr.");
return 1;
}
}
else if (ContentDownloader.Config.UseQrCode)
{
Console.WriteLine("Error: -qr can not be used with -username.");
Console.Error.WriteLine("Error: -qr can not be used with -username.");
return 1;
}

Expand Down Expand Up @@ -490,10 +503,12 @@ static void PrintUsage()
Console.WriteLine(" depotdownloader -app <id> [-depot <id> [-manifest <id>]]");
Console.WriteLine(" [-username <username> [-password <password>]] [other options]");
Console.WriteLine();
Console.WriteLine("Usage: downloading a workshop item using pubfile id");
Console.WriteLine("Usage: downloading a workshop item using pubfile id:");
Console.WriteLine(" depotdownloader -app <id> -pubfile <id> [-username <username> [-password <password>]]");
Console.WriteLine("Usage: downloading a workshop item using ugc id");
Console.WriteLine("Usage: downloading a workshop item using ugc id:");
Console.WriteLine(" depotdownloader -app <id> -ugc <id> [-username <username> [-password <password>]]");
Console.WriteLine("Usage: show currently stored tokens for use in DEPOTDOWNLOADER_TOKEN:");
Console.WriteLine(" depotdownloader -show-tokens");
Console.WriteLine();
Console.WriteLine("Parameters:");
Console.WriteLine(" -app <#> - the AppID to download.");
Expand All @@ -516,6 +531,7 @@ static void PrintUsage()
Console.WriteLine(" -password <pass> - 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 <username> -remember-password as login credentials.");
Console.WriteLine(" note: this actually saves a login token, same as the steam client.");
Console.WriteLine(" -qr - display a login QR code to be scanned with the Steam mobile app");
Console.WriteLine(" -no-mobile - prefer entering a 2FA code instead of prompting to accept in the Steam mobile app");
Console.WriteLine();
Expand All @@ -530,8 +546,15 @@ static void PrintUsage()
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();
Console.WriteLine(" -show-tokens - show token data saved by a previous -remember-password, for DEPOTDOWNLOADER_TOKEN");
Console.WriteLine(" must be used by itself");
Console.WriteLine();
Console.WriteLine(" -debug - enable verbose debug logging.");
Console.WriteLine(" -V or --version - print version and runtime.");
Console.WriteLine();
Console.WriteLine("Env vars:");
Console.WriteLine(" DEPOTDOWNLOADER_TOKEN - a username, token, and optional guard data separated by colons ':'.");
Console.WriteLine(" if provided, it is equivalent to setting -username <username> -remember-password");
}

static void PrintVersion(bool printExtra = false)
Expand Down
38 changes: 38 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ Parameter | Description
`-qr` | display a login QR code to be scanned with the Steam mobile app
`-no-mobile` | prefer entering a 2FA code instead of prompting to accept in the Steam mobile app.
`-loginid <#>` | a unique 32-bit integer Steam LogonID in decimal, required if running multiple instances of DepotDownloader concurrently.
`-show-tokens` | print out tokens previously saved by a `-remember-password` call, for use in `DEPOTDOWNLOADER_TOKEN`.

#### Downloading

Expand Down Expand Up @@ -110,6 +111,43 @@ Parameter | Description
`-debug` | enable verbose debug logging.
`-V` or `--version` | print version and runtime.

## How to use saved token on another machine

First, run a command to log in, making sure to use `-remember-password`:

```powershell
./DepotDownloader -app 730 -manifest-only -username <username> -qr -remember-password
```

Then use `-show-tokens`:

```powershell
./DepotDownloader -show-tokens
```

This will show something starting with your username and a colon, like `GabeN:eyAid`...

Use like:

(windows powershell)
```powershell
$env:DEPOTDOWNLOADER_TOKEN='GabeN:eyAid...'
./DepotDownloader <args>
./DepotDownloader <args>
```

(linux shell, single command)
```bash
DEPOTDOWNLOADER_TOKEN="GabeN:eyAid..." ./DepotDownloader <args>
```

(linux shell, multiple commands)
```bash
export DEPOTDOWNLOADER_TOKEN="GabeN:eyAid..."
./DepotDownloader <args>
./DepotDownloader <args>
```

## Frequently Asked Questions

### Why am I prompted to enter a 2-factor code every time I run the app?
Expand Down
Loading