Merge remote-tracking branch 'origin/master' into dotnet-core

# Conflicts:
#	DepotDownloader/ContentDownloader.cs
#	DepotDownloader/Program.cs
pull/19/head
Netshroud 9 years ago
commit 0da80d9601

@ -18,6 +18,9 @@ namespace DepotDownloader
[ProtoMember(4, IsRequired = false)] [ProtoMember(4, IsRequired = false)]
public System.Collections.Concurrent.ConcurrentDictionary<string, int> ContentServerPenalty { get; private set; } public System.Collections.Concurrent.ConcurrentDictionary<string, int> ContentServerPenalty { get; private set; }
[ProtoMember(5, IsRequired = false)]
public Dictionary<string, string> LoginKeys { get; private set; }
string FileName = null; string FileName = null;
ConfigStore() ConfigStore()
@ -25,6 +28,7 @@ namespace DepotDownloader
LastManifests = new Dictionary<uint, ulong>(); LastManifests = new Dictionary<uint, ulong>();
SentryData = new Dictionary<string, byte[]>(); SentryData = new Dictionary<string, byte[]>();
ContentServerPenalty = new System.Collections.Concurrent.ConcurrentDictionary<string, int>(); ContentServerPenalty = new System.Collections.Concurrent.ConcurrentDictionary<string, int>();
LoginKeys = new Dictionary<string, string>();
} }
static bool Loaded static bool Loaded

@ -1,4 +1,5 @@
using System; using SteamKit2;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@ -6,7 +7,6 @@ using System.Net;
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading; using System.Threading;
using SteamKit2;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace DepotDownloader namespace DepotDownloader
@ -332,11 +332,20 @@ namespace DepotDownloader
public static bool InitializeSteam3( string username, string password ) public static bool InitializeSteam3( string username, string password )
{ {
string loginKey = null;
if ( username != null && Config.RememberPassword )
{
_ = ConfigStore.TheConfig.LoginKeys.TryGetValue( username, out loginKey );
}
steam3 = new Steam3Session( steam3 = new Steam3Session(
new SteamUser.LogOnDetails() new SteamUser.LogOnDetails()
{ {
Username = username, Username = username,
Password = password, Password = loginKey == null ? password : null,
ShouldRememberPassword = Config.RememberPassword,
LoginKey = loginKey,
} }
); );
@ -357,10 +366,11 @@ namespace DepotDownloader
if ( steam3 == null ) if ( steam3 == null )
return; return;
steam3.TryWaitForLoginKey();
steam3.Disconnect(); steam3.Disconnect();
} }
public static async Task DownloadAppAsync(uint appId, uint depotId, string branch, bool forceDepot = false) public static async Task DownloadAppAsync( uint appId, uint depotId, string branch, string os = null, bool forceDepot = false )
{ {
if ( steam3 != null ) if ( steam3 != null )
steam3.RequestAppInfo( appId ); steam3.RequestAppInfo( appId );
@ -411,7 +421,7 @@ namespace DepotDownloader
if ( depotConfig != KeyValue.Invalid && depotConfig[ "oslist" ] != KeyValue.Invalid && !string.IsNullOrWhiteSpace( depotConfig[ "oslist" ].Value ) ) if ( depotConfig != KeyValue.Invalid && depotConfig[ "oslist" ] != KeyValue.Invalid && !string.IsNullOrWhiteSpace( depotConfig[ "oslist" ].Value ) )
{ {
var oslist = depotConfig[ "oslist" ].Value.Split( ',' ); var oslist = depotConfig[ "oslist" ].Value.Split( ',' );
if (Array.IndexOf(oslist, Util.GetSteamOS()) == -1) if ( Array.IndexOf( oslist, os ?? Util.GetSteamOS() ) == -1 )
continue; continue;
} }
} }
@ -580,7 +590,8 @@ namespace DepotDownloader
while ( depotManifest == null ) while ( depotManifest == null )
{ {
CDNClient client = null; CDNClient client = null;
try { try
{
client = await cdnPool.GetConnectionForDepotAsync( appId, depot.id, depot.depotKey, CancellationToken.None ).ConfigureAwait( false ); client = await cdnPool.GetConnectionForDepotAsync( appId, depot.id, depot.depotKey, CancellationToken.None ).ConfigureAwait( false );
depotManifest = await client.DownloadManifestAsync( depot.id, depot.manifestId ).ConfigureAwait( false ); depotManifest = await client.DownloadManifestAsync( depot.id, depot.manifestId ).ConfigureAwait( false );
@ -687,8 +698,6 @@ namespace DepotDownloader
try try
{ {
await semaphore.WaitAsync().ConfigureAwait(false);
string fileFinalPath = Path.Combine( depot.installDir, file.FileName ); string fileFinalPath = Path.Combine( depot.installDir, file.FileName );
string fileStagingPath = Path.Combine( stagingDir, file.FileName ); string fileStagingPath = Path.Combine( stagingDir, file.FileName );

@ -24,5 +24,8 @@ namespace DepotDownloader
public int MaxServers { get; set; } public int MaxServers { get; set; }
public int MaxDownloads { get; set; } public int MaxDownloads { get; set; }
public string SuppliedPassword { get; set; }
public bool RememberPassword { get; set; }
} }
} }

@ -91,17 +91,25 @@ namespace DepotDownloader
string username = GetParameter<string>( args, "-username" ) ?? GetParameter<string>( args, "-user" ); string username = GetParameter<string>( args, "-username" ) ?? GetParameter<string>( args, "-user" );
string password = GetParameter<string>( args, "-password" ) ?? GetParameter<string>( args, "-pass" ); string password = GetParameter<string>( args, "-password" ) ?? GetParameter<string>( args, "-pass" );
ContentDownloader.Config.RememberPassword = HasParameter( args, "-remember-password" );
ContentDownloader.Config.InstallDirectory = GetParameter<string>( args, "-dir" ); ContentDownloader.Config.InstallDirectory = GetParameter<string>( args, "-dir" );
ContentDownloader.Config.DownloadAllPlatforms = HasParameter( args, "-all-platforms" ); ContentDownloader.Config.DownloadAllPlatforms = HasParameter( args, "-all-platforms" );
ContentDownloader.Config.VerifyAll = HasParameter( args, "-verify-all" ) || HasParameter( args, "-verify_all" ) || HasParameter( args, "-validate" ); ContentDownloader.Config.VerifyAll = HasParameter( args, "-verify-all" ) || HasParameter( args, "-verify_all" ) || HasParameter( args, "-validate" );
ContentDownloader.Config.MaxServers = GetParameter<int>( args, "-max-servers", 20 ); ContentDownloader.Config.MaxServers = GetParameter<int>( args, "-max-servers", 20 );
ContentDownloader.Config.MaxDownloads = GetParameter<int>( args, "-max-downloads", 4 ); ContentDownloader.Config.MaxDownloads = GetParameter<int>( args, "-max-downloads", 4 );
string branch = GetParameter<string>( args, "-branch" ) ?? GetParameter<string>( args, "-beta" ) ?? "Public"; string branch = GetParameter<string>( args, "-branch" ) ?? GetParameter<string>( args, "-beta" ) ?? "Public";
var forceDepot = HasParameter(args, "-force-depot"); bool forceDepot = HasParameter( args, "-force-depot" );
string os = GetParameter<string>( args, "-os", null );
if ( ContentDownloader.Config.DownloadAllPlatforms && !String.IsNullOrEmpty( os ) )
{
Console.WriteLine( "Error: Cannot specify -os when -all-platforms is specified." );
return;
}
ContentDownloader.Config.MaxServers = Math.Max( ContentDownloader.Config.MaxServers, ContentDownloader.Config.MaxDownloads ); ContentDownloader.Config.MaxServers = Math.Max( ContentDownloader.Config.MaxServers, ContentDownloader.Config.MaxDownloads );
if (username != null && password == null) if ( username != null && password == null && ( !ContentDownloader.Config.RememberPassword || !ConfigStore.TheConfig.LoginKeys.ContainsKey( username ) ) )
{ {
Console.Write( "Enter account password for \"{0}\": ", username ); Console.Write( "Enter account password for \"{0}\": ", username );
password = Util.ReadPassword(); password = Util.ReadPassword();
@ -112,9 +120,12 @@ namespace DepotDownloader
Console.WriteLine( "No username given. Using anonymous account with dedicated server subscription." ); Console.WriteLine( "No username given. Using anonymous account with dedicated server subscription." );
} }
// capture the supplied password in case we need to re-use it after checking the login key
ContentDownloader.Config.SuppliedPassword = password;
if ( ContentDownloader.InitializeSteam3( username, password ) ) if ( ContentDownloader.InitializeSteam3( username, password ) )
{ {
await ContentDownloader.DownloadAppAsync(appId, depotId, branch, forceDepot).ConfigureAwait(false); await ContentDownloader.DownloadAppAsync( appId, depotId, branch, os, forceDepot ).ConfigureAwait( false );
ContentDownloader.ShutdownSteam3(); ContentDownloader.ShutdownSteam3();
} }
} }
@ -164,7 +175,9 @@ namespace DepotDownloader
Console.WriteLine( "\t-cellid <#>\t\t\t- the overridden CellID of the content server to download from." ); Console.WriteLine( "\t-cellid <#>\t\t\t- the overridden CellID of the content server to download from." );
Console.WriteLine( "\t-username <user>\t\t\t- the username of the account to login to for restricted content." ); Console.WriteLine( "\t-username <user>\t\t\t- the username of the account to login to for restricted content." );
Console.WriteLine( "\t-password <pass>\t\t\t- the password of the account to login to for restricted content." ); Console.WriteLine( "\t-password <pass>\t\t\t- the password of the account to login to for restricted content." );
Console.WriteLine( "\t-remember-password\t\t\t- if set, remember the password for subsequent logins of this user." );
Console.WriteLine( "\t-dir <installdir>\t\t\t- the directory in which to place downloaded files." ); Console.WriteLine( "\t-dir <installdir>\t\t\t- the directory in which to place downloaded files." );
Console.WriteLine( "\t-os <os>\t\t\t- the operating system for which to download the game (windows, macos or linux, default: OS the program is currently running on)" );
Console.WriteLine( "\t-filelist <filename.txt>\t\t- a list of files to download (from the manifest). Can optionally use regex to download only certain files." ); Console.WriteLine( "\t-filelist <filename.txt>\t\t- a list of files to download (from the manifest). Can optionally use regex to download only certain files." );
Console.WriteLine( "\t-all-platforms\t\t\t- downloads all platform-specific depots when -app is used." ); Console.WriteLine( "\t-all-platforms\t\t\t- downloads all platform-specific depots when -app is used." );
Console.WriteLine( "\t-manifest-only\t\t\t- downloads a human readable manifest for any depots that would be downloaded." ); Console.WriteLine( "\t-manifest-only\t\t\t- downloads a human readable manifest for any depots that would be downloaded." );

@ -94,6 +94,7 @@ namespace DepotDownloader
this.callbacks.Subscribe<SteamUser.SessionTokenCallback>( SessionTokenCallback ); this.callbacks.Subscribe<SteamUser.SessionTokenCallback>( SessionTokenCallback );
this.callbacks.Subscribe<SteamApps.LicenseListCallback>( LicenseListCallback ); this.callbacks.Subscribe<SteamApps.LicenseListCallback>( LicenseListCallback );
this.callbacks.Subscribe<SteamUser.UpdateMachineAuthCallback>( UpdateMachineAuthCallback ); this.callbacks.Subscribe<SteamUser.UpdateMachineAuthCallback>( UpdateMachineAuthCallback );
this.callbacks.Subscribe<SteamUser.LoginKeyCallback>( LoginKeyCallback );
Console.Write( "Connecting to Steam3..." ); Console.Write( "Connecting to Steam3..." );
@ -164,7 +165,8 @@ namespace DepotDownloader
} }
}; };
WaitUntilCallback(() => { WaitUntilCallback( () =>
{
callbacks.Subscribe( steamApps.PICSGetAccessTokens( new List<uint>() { appId }, new List<uint>() { } ), cbMethodTokens ); callbacks.Subscribe( steamApps.PICSGetAccessTokens( new List<uint>() { appId }, new List<uint>() { } ), cbMethodTokens );
}, () => { return completed; } ); }, () => { return completed; } );
@ -194,7 +196,8 @@ namespace DepotDownloader
request.Public = false; request.Public = false;
} }
WaitUntilCallback(() => { WaitUntilCallback( () =>
{
callbacks.Subscribe( steamApps.PICSGetProductInfo( new List<SteamApps.PICSRequest>() { request }, new List<SteamApps.PICSRequest>() { } ), cbMethod ); callbacks.Subscribe( steamApps.PICSGetProductInfo( new List<SteamApps.PICSRequest>() { request }, new List<SteamApps.PICSRequest>() { } ), cbMethod );
}, () => { return completed; } ); }, () => { return completed; } );
} }
@ -224,7 +227,8 @@ namespace DepotDownloader
} }
}; };
WaitUntilCallback(() => { WaitUntilCallback( () =>
{
callbacks.Subscribe( steamApps.PICSGetProductInfo( new List<uint>(), packages ), cbMethod ); callbacks.Subscribe( steamApps.PICSGetProductInfo( new List<uint>(), packages ), cbMethod );
}, () => { return completed; } ); }, () => { return completed; } );
} }
@ -239,7 +243,8 @@ namespace DepotDownloader
success = resultInfo.GrantedApps.Contains( appId ); success = resultInfo.GrantedApps.Contains( appId );
}; };
WaitUntilCallback(() => { WaitUntilCallback( () =>
{
callbacks.Subscribe( steamApps.RequestFreeLicense( appId ), cbMethod ); callbacks.Subscribe( steamApps.RequestFreeLicense( appId ), cbMethod );
}, () => { return completed; } ); }, () => { return completed; } );
@ -275,7 +280,8 @@ namespace DepotDownloader
} }
}; };
WaitUntilCallback(() => { WaitUntilCallback( () =>
{
callbacks.Subscribe( steamApps.GetAppOwnershipTicket( appId ), cbMethod ); callbacks.Subscribe( steamApps.GetAppOwnershipTicket( appId ), cbMethod );
}, () => { return completed; } ); }, () => { return completed; } );
} }
@ -391,6 +397,22 @@ namespace DepotDownloader
} }
} }
public void TryWaitForLoginKey()
{
if ( logonDetails.Username == null || !ContentDownloader.Config.RememberPassword ) return;
DateTime waitUntil = new DateTime().AddSeconds( 10 );
while ( true )
{
DateTime now = new DateTime();
if ( now >= waitUntil ) break;
if ( ConfigStore.TheConfig.LoginKeys.ContainsKey( logonDetails.Username ) ) break;
callbacks.RunWaitAllCallbacks( TimeSpan.FromMilliseconds( 100 ) );
}
}
private void WaitForCallbacks() private void WaitForCallbacks()
{ {
@ -442,7 +464,8 @@ namespace DepotDownloader
if ( bConnecting ) if ( bConnecting )
{ {
Console.WriteLine( "Connection to Steam failed. Trying again" ); Console.WriteLine( "Connection to Steam failed. Trying again" );
} else }
else
{ {
Console.WriteLine( "Lost connection to Steam. Reconnecting" ); Console.WriteLine( "Lost connection to Steam. Reconnecting" );
} }
@ -456,19 +479,41 @@ namespace DepotDownloader
{ {
bool isSteamGuard = loggedOn.Result == EResult.AccountLogonDenied; bool isSteamGuard = loggedOn.Result == EResult.AccountLogonDenied;
bool is2FA = loggedOn.Result == EResult.AccountLoginDeniedNeedTwoFactor; bool is2FA = loggedOn.Result == EResult.AccountLoginDeniedNeedTwoFactor;
bool isLoginKey = ContentDownloader.Config.RememberPassword && logonDetails.LoginKey != null && loggedOn.Result == EResult.InvalidPassword;
if (isSteamGuard || is2FA) if ( isSteamGuard || is2FA || isLoginKey )
{ {
bExpectingDisconnectRemote = true; bExpectingDisconnectRemote = true;
Abort( false ); Abort( false );
if ( !isLoginKey )
{
Console.WriteLine( "This account is protected by Steam Guard." ); Console.WriteLine( "This account is protected by Steam Guard." );
}
if ( is2FA ) if ( is2FA )
{ {
Console.Write( "Please enter your 2 factor auth code from your authenticator app: " ); Console.Write( "Please enter your 2 factor auth code from your authenticator app: " );
logonDetails.TwoFactorCode = Console.ReadLine(); logonDetails.TwoFactorCode = Console.ReadLine();
} }
else if ( isLoginKey )
{
ConfigStore.TheConfig.LoginKeys.Remove( logonDetails.Username );
ConfigStore.Save();
logonDetails.LoginKey = null;
if ( ContentDownloader.Config.SuppliedPassword != null )
{
Console.WriteLine( "Login key was expired. Connecting with supplied password." );
logonDetails.Password = ContentDownloader.Config.SuppliedPassword;
}
else
{
Console.WriteLine( "Login key was expired. Please enter your password: " );
logonDetails.Password = Util.ReadPassword();
}
}
else else
{ {
Console.Write( "Please enter the authentication code sent to your email address: " ); Console.Write( "Please enter the authentication code sent to your email address: " );
@ -563,6 +608,16 @@ namespace DepotDownloader
steamUser.SendMachineAuthResponse( authResponse ); steamUser.SendMachineAuthResponse( authResponse );
} }
private void LoginKeyCallback( SteamUser.LoginKeyCallback loginKey )
{
Console.WriteLine( "Accepted new login key for account {0}", logonDetails.Username );
ConfigStore.TheConfig.LoginKeys[ logonDetails.Username ] = loginKey.LoginKey;
ConfigStore.Save();
steamUser.AcceptNewLoginKey( loginKey );
}
} }
} }

@ -14,7 +14,9 @@ Optional Parameters:
-cellid <#> - the overridden CellID of the content server to download from. -cellid <#> - the overridden CellID of the content server to download from.
-username <user> - the username of the account to login to for restricted content. -username <user> - the username of the account to login to for restricted content.
-password <pass> - the password of the account to login to for restricted content. -password <pass> - the password of the account to login to for restricted content.
-remember-password - if set, remember the password for subsequent logins of this user.
-dir <installdir> - the directory in which to place downloaded files. -dir <installdir> - the directory in which to place downloaded files.
-os <os> - the operating system for which to download the game (windows, macos or linux, default: OS the program is currently running on)
-filelist <file.txt> - a list of files to download (from the manifest). -filelist <file.txt> - a list of files to download (from the manifest).
Can optionally use regex to download only certain files. Can optionally use regex to download only certain files.
-all-platforms - downloads all platform-specific depots when -app is used. -all-platforms - downloads all platform-specific depots when -app is used.

Loading…
Cancel
Save