mirror of
https://github.com/JustArchiNET/ArchiSteamFarm.git
synced 2025-12-28 12:10:47 +00:00
Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
51abdfb899 | ||
|
|
658d6129a7 | ||
|
|
55c1674309 | ||
|
|
9efae3edae | ||
|
|
d1e047edf8 | ||
|
|
8742ace3d7 | ||
|
|
feb3fbfe59 | ||
|
|
0b06df4352 | ||
|
|
10b1d02a95 | ||
|
|
7731360f09 | ||
|
|
02d3454d1b | ||
|
|
54b8d3e6f3 | ||
|
|
0b65e1d9a1 | ||
|
|
1f5005f14d | ||
|
|
6414f375fd | ||
|
|
b930f513b4 | ||
|
|
84419bec2a | ||
|
|
deed19e732 | ||
|
|
7e9844edab | ||
|
|
ce4733547c | ||
|
|
561fb66e7a | ||
|
|
77413f13e2 | ||
|
|
1ca31ee33e | ||
|
|
4059a2cd11 | ||
|
|
23af6efb4b | ||
|
|
09b2b29ff4 | ||
|
|
412028eff7 | ||
|
|
a5c85a73bc | ||
|
|
b40e87b25e |
@@ -10,6 +10,7 @@
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=FS/@EntryIndexedValue">FS</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=HTML/@EntryIndexedValue">HTML</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=ID/@EntryIndexedValue">ID</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=IP/@EntryIndexedValue">IP</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=OK/@EntryIndexedValue">OK</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=PIN/@EntryIndexedValue">PIN</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SC/@EntryIndexedValue">SC</s:String>
|
||||
|
||||
@@ -159,7 +159,7 @@ namespace ArchiSteamFarm {
|
||||
Items = new Dictionary<uint, string>(lineItems.Count);
|
||||
|
||||
foreach (KeyValue lineItem in lineItems) {
|
||||
uint appID = (uint) lineItem["PackageID"].AsUnsignedLong();
|
||||
uint appID = lineItem["PackageID"].AsUnsignedInteger();
|
||||
string gameName = lineItem["ItemDescription"].Value;
|
||||
gameName = WebUtility.HtmlDecode(gameName); // Apparently steam expects client to decode sent HTML
|
||||
Items[appID] = gameName;
|
||||
@@ -177,6 +177,44 @@ namespace ArchiSteamFarm {
|
||||
|
||||
*/
|
||||
|
||||
// TODO: Remove me once https://github.com/SteamRE/SteamKit/issues/305 is fixed
|
||||
internal void LogOnWithoutMachineID(SteamUser.LogOnDetails details) {
|
||||
ClientMsgProtobuf<CMsgClientLogon> logon = new ClientMsgProtobuf<CMsgClientLogon>(EMsg.ClientLogon);
|
||||
|
||||
SteamID steamId = new SteamID(details.AccountID, details.AccountInstance, Client.ConnectedUniverse, EAccountType.Individual);
|
||||
|
||||
if (details.LoginID != null) {
|
||||
logon.Body.obfustucated_private_ip = details.LoginID.Value;
|
||||
}
|
||||
|
||||
logon.ProtoHeader.client_sessionid = 0;
|
||||
logon.ProtoHeader.steamid = steamId.ConvertToUInt64();
|
||||
|
||||
logon.Body.account_name = details.Username;
|
||||
logon.Body.password = details.Password;
|
||||
logon.Body.should_remember_password = details.ShouldRememberPassword;
|
||||
|
||||
logon.Body.protocol_version = MsgClientLogon.CurrentProtocol;
|
||||
logon.Body.client_os_type = (uint) details.ClientOSType;
|
||||
logon.Body.client_language = details.ClientLanguage;
|
||||
logon.Body.cell_id = details.CellID;
|
||||
|
||||
logon.Body.steam2_ticket_request = details.RequestSteam2Ticket;
|
||||
|
||||
logon.Body.client_package_version = 1771;
|
||||
|
||||
logon.Body.auth_code = details.AuthCode;
|
||||
logon.Body.two_factor_code = details.TwoFactorCode;
|
||||
|
||||
logon.Body.login_key = details.LoginKey;
|
||||
|
||||
logon.Body.sha_sentryfile = details.SentryFileHash;
|
||||
logon.Body.eresult_sentryfile = (int) (details.SentryFileHash != null ? EResult.OK : EResult.FileNotFound);
|
||||
|
||||
|
||||
Client.Send(logon);
|
||||
}
|
||||
|
||||
internal void PlayGame(string gameName) {
|
||||
if (!Client.IsConnected) {
|
||||
return;
|
||||
@@ -250,39 +288,6 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Please remove me immediately after https://github.com/SteamRE/SteamKit/issues/254 gets fixed
|
||||
internal void HackedLogOn(SteamUser.LogOnDetails details) {
|
||||
if (!Client.IsConnected) {
|
||||
return;
|
||||
}
|
||||
|
||||
SteamID steamID = new SteamID(details.AccountID, details.AccountInstance, Client.ConnectedUniverse, EAccountType.Individual);
|
||||
|
||||
ClientMsgProtobuf<CMsgClientLogon> logon = new ClientMsgProtobuf<CMsgClientLogon>(EMsg.ClientLogon);
|
||||
if (details.LoginID != null) {
|
||||
logon.Body.obfustucated_private_ip = details.LoginID.Value;
|
||||
}
|
||||
|
||||
logon.ProtoHeader.client_sessionid = 0;
|
||||
logon.ProtoHeader.steamid = steamID.ConvertToUInt64();
|
||||
logon.Body.account_name = details.Username;
|
||||
logon.Body.password = details.Password;
|
||||
logon.Body.should_remember_password = details.ShouldRememberPassword;
|
||||
logon.Body.protocol_version = MsgClientLogon.CurrentProtocol;
|
||||
logon.Body.client_os_type = (uint) details.ClientOSType;
|
||||
logon.Body.client_language = details.ClientLanguage;
|
||||
logon.Body.cell_id = details.CellID;
|
||||
logon.Body.steam2_ticket_request = details.RequestSteam2Ticket;
|
||||
logon.Body.client_package_version = 1771;
|
||||
logon.Body.auth_code = details.AuthCode;
|
||||
logon.Body.two_factor_code = details.TwoFactorCode;
|
||||
logon.Body.login_key = details.LoginKey;
|
||||
logon.Body.sha_sentryfile = details.SentryFileHash;
|
||||
logon.Body.eresult_sentryfile = (int) (details.SentryFileHash != null ? EResult.OK : EResult.FileNotFound);
|
||||
|
||||
Client.Send(logon);
|
||||
}
|
||||
|
||||
/*
|
||||
_ _ _ _
|
||||
| | | | __ _ _ __ __| || | ___ _ __ ___
|
||||
|
||||
@@ -46,6 +46,8 @@ namespace ArchiSteamFarm {
|
||||
// System account, requires admin privilege to install
|
||||
serviceProcessInstaller.Account = ServiceAccount.LocalSystem;
|
||||
|
||||
serviceInstaller.Installers.Clear();
|
||||
|
||||
EventLogInstaller logInstaller = new EventLogInstaller {
|
||||
Log = SharedInfo.EventLog,
|
||||
Source = SharedInfo.EventLogSource
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>3</WarningLevel>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
@@ -89,8 +90,8 @@
|
||||
<HintPath>..\packages\protobuf-net.2.0.0.668\lib\net40\protobuf-net.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="SteamKit2, Version=1.7.0.33680, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SteamKit2.1.7.0\lib\net45\SteamKit2.dll</HintPath>
|
||||
<Reference Include="SteamKit2, Version=1.8.0.26737, Culture=neutral, PublicKeyToken=ed3ce47ed5aad940, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SteamKit2.1.8.0\lib\net45\SteamKit2.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
@@ -124,12 +125,14 @@
|
||||
<Compile Include="CardsFarmer.cs" />
|
||||
<Compile Include="Debugging.cs" />
|
||||
<Compile Include="GlobalConfig.cs" />
|
||||
<Compile Include="IPAddressConverter.cs" />
|
||||
<Compile Include="IPEndPointConverter.cs" />
|
||||
<Compile Include="JSON\GitHub.cs" />
|
||||
<Compile Include="JSON\Steam.cs" />
|
||||
<Compile Include="Logging.cs" />
|
||||
<Compile Include="InMemoryServerListProvider.cs" />
|
||||
<Compile Include="MobileAuthenticator.cs" />
|
||||
<Compile Include="Runtime.cs" />
|
||||
<Compile Include="ObsoleteSteamGuardAccount.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SharedInfo.cs" />
|
||||
|
||||
@@ -36,7 +36,7 @@ using System.Threading;
|
||||
using ArchiSteamFarm.JSON;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
internal sealed class ArchiWebHandler {
|
||||
internal sealed class ArchiWebHandler : IDisposable {
|
||||
private const string SteamCommunityHost = "steamcommunity.com";
|
||||
private const byte MinSessionTTL = 15; // Assume session is valid for at least that amount of seconds
|
||||
|
||||
@@ -111,7 +111,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
foreach (KeyValue item in input) {
|
||||
uint appID = (uint) item["appid"].AsUnsignedLong();
|
||||
uint appID = item["appid"].AsUnsignedInteger();
|
||||
if (appID == 0) {
|
||||
Logging.LogNullError(nameof(appID));
|
||||
return false;
|
||||
@@ -129,7 +129,7 @@ namespace ArchiSteamFarm {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint amount = (uint) item["amount"].AsUnsignedLong();
|
||||
uint amount = item["amount"].AsUnsignedInteger();
|
||||
if (amount == 0) {
|
||||
Logging.LogNullError(nameof(amount));
|
||||
return false;
|
||||
@@ -161,6 +161,8 @@ namespace ArchiSteamFarm {
|
||||
WebBrowser = new WebBrowser(bot.BotName);
|
||||
}
|
||||
|
||||
public void Dispose() => SessionSemaphore.Dispose();
|
||||
|
||||
internal void OnDisconnected() => Ready = false;
|
||||
|
||||
internal async Task<bool> Init(ulong steamID, EUniverse universe, string webAPIUserNonce, string parentalPin) {
|
||||
@@ -375,11 +377,8 @@ namespace ArchiSteamFarm {
|
||||
string request = SteamCommunityURL + "/my/games/?xml=1";
|
||||
|
||||
XmlDocument response = await WebBrowser.UrlGetToXMLRetry(request).ConfigureAwait(false);
|
||||
if (response == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
XmlNodeList xmlNodeList = response.SelectNodes("gamesList/games/game");
|
||||
XmlNodeList xmlNodeList = response?.SelectNodes("gamesList/games/game");
|
||||
if ((xmlNodeList == null) || (xmlNodeList.Count == 0)) {
|
||||
return null;
|
||||
}
|
||||
@@ -440,7 +439,7 @@ namespace ArchiSteamFarm {
|
||||
|
||||
Dictionary<uint, string> result = new Dictionary<uint, string>(response["games"].Children.Count);
|
||||
foreach (KeyValue game in response["games"].Children) {
|
||||
uint appID = (uint) game["appid"].AsUnsignedLong();
|
||||
uint appID = game["appid"].AsUnsignedInteger();
|
||||
if (appID == 0) {
|
||||
Logging.LogNullError(nameof(appID), Bot.BotName);
|
||||
return null;
|
||||
@@ -470,7 +469,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
if (response != null) {
|
||||
return (uint) response["server_time"].AsUnsignedLong();
|
||||
return response["server_time"].AsUnsignedInteger();
|
||||
}
|
||||
|
||||
Logging.LogGenericWarning("Request failed even after " + WebBrowser.MaxRetries + " tries", Bot.BotName);
|
||||
@@ -490,11 +489,8 @@ namespace ArchiSteamFarm {
|
||||
string request = SteamCommunityURL + "/tradeoffer/" + tradeID + "?l=english";
|
||||
|
||||
HtmlDocument htmlDocument = await WebBrowser.UrlGetToHtmlDocumentRetry(request).ConfigureAwait(false);
|
||||
if (htmlDocument == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
HtmlNode htmlNode = htmlDocument.DocumentNode.SelectSingleNode("//div[@class='pagecontent']/script");
|
||||
HtmlNode htmlNode = htmlDocument?.DocumentNode.SelectSingleNode("//div[@class='pagecontent']/script");
|
||||
if (htmlNode == null) { // Trade can be no longer valid
|
||||
return null;
|
||||
}
|
||||
@@ -580,7 +576,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
if (appID == 0) {
|
||||
appID = (uint) description["appid"].AsUnsignedLong();
|
||||
appID = description["appid"].AsUnsignedInteger();
|
||||
}
|
||||
|
||||
Steam.Item.EType type = Steam.Item.EType.Unknown;
|
||||
@@ -611,7 +607,7 @@ namespace ArchiSteamFarm {
|
||||
return null;
|
||||
}
|
||||
|
||||
uint otherSteamID3 = (uint) trade["accountid_other"].AsUnsignedLong();
|
||||
uint otherSteamID3 = trade["accountid_other"].AsUnsignedInteger();
|
||||
if (otherSteamID3 == 0) {
|
||||
Logging.LogNullError(nameof(otherSteamID3));
|
||||
return null;
|
||||
@@ -711,11 +707,8 @@ namespace ArchiSteamFarm {
|
||||
string request = SteamCommunityURL + "/my/inventory/json/" + Steam.Item.SteamAppID + "/" + Steam.Item.SteamContextID + "?trading=" + (tradable ? "1" : "0") + "&start=" + currentPage;
|
||||
|
||||
JObject jObject = await WebBrowser.UrlGetToJObjectRetry(request).ConfigureAwait(false);
|
||||
if (jObject == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
IEnumerable<JToken> descriptions = jObject.SelectTokens("$.rgDescriptions.*");
|
||||
IEnumerable<JToken> descriptions = jObject?.SelectTokens("$.rgDescriptions.*");
|
||||
if (descriptions == null) {
|
||||
return null; // OK, empty inventory
|
||||
}
|
||||
@@ -911,11 +904,7 @@ namespace ArchiSteamFarm {
|
||||
string request = SteamCommunityURL + "/my/videos";
|
||||
|
||||
Uri uri = await WebBrowser.UrlHeadToUriRetry(request).ConfigureAwait(false);
|
||||
if (uri == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return !uri.AbsolutePath.StartsWith("/login", StringComparison.Ordinal);
|
||||
return !uri?.AbsolutePath.StartsWith("/login", StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
private async Task<bool> RefreshSessionIfNeeded() {
|
||||
|
||||
@@ -35,9 +35,10 @@ using System.Threading.Tasks;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using ArchiSteamFarm.JSON;
|
||||
using SteamKit2.Discovery;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
internal sealed class Bot {
|
||||
internal sealed class Bot : IDisposable {
|
||||
private const ulong ArchiSCFarmGroup = 103582791440160998;
|
||||
private const ushort CallbackSleep = 500; // In miliseconds
|
||||
private const ushort MaxSteamMessageLength = 2048;
|
||||
@@ -76,24 +77,14 @@ namespace ArchiSteamFarm {
|
||||
private bool FirstTradeSent, InvalidPassword, SkipFirstShutdown;
|
||||
private string AuthCode, TwoFactorCode;
|
||||
|
||||
internal static async Task RefreshCMs(uint cellID) {
|
||||
bool initialized = false;
|
||||
for (byte i = 0; (i < WebBrowser.MaxRetries) && !initialized; i++) {
|
||||
try {
|
||||
Logging.LogGenericInfo("Refreshing list of CMs...");
|
||||
await SteamDirectory.Initialize(cellID).ConfigureAwait(false);
|
||||
initialized = true;
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(e);
|
||||
await Task.Delay(1000).ConfigureAwait(false);
|
||||
}
|
||||
internal static void InitializeCMs(uint cellID, IServerListProvider serverListProvider) {
|
||||
if (serverListProvider == null) {
|
||||
Logging.LogNullError(nameof(serverListProvider));
|
||||
return;
|
||||
}
|
||||
|
||||
if (initialized) {
|
||||
Logging.LogGenericInfo("Success!");
|
||||
} else {
|
||||
Logging.LogGenericWarning("Failed to initialize list of CMs after " + WebBrowser.MaxRetries + " tries, ASF will use built-in SK2 list, it may take a while to connect");
|
||||
}
|
||||
CMClient.Servers.CellID = cellID;
|
||||
CMClient.Servers.ServerListProvider = serverListProvider;
|
||||
}
|
||||
|
||||
private static bool IsOwner(ulong steamID) {
|
||||
@@ -161,15 +152,6 @@ namespace ArchiSteamFarm {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Converter code will be removed soon
|
||||
if (BotDatabase.SteamGuardAccount != null) {
|
||||
Logging.LogGenericWarning("Converting old ASF 2FA V2.0 format into new ASF 2FA V2.1 format...", botName);
|
||||
BotDatabase.MobileAuthenticator = MobileAuthenticator.LoadFromSteamGuardAccount(BotDatabase.SteamGuardAccount);
|
||||
Logging.LogGenericInfo("Done! If you didn't make a copy of your revocation code yet, then it's a good moment to do so: " + BotDatabase.SteamGuardAccount.RevocationCode, botName);
|
||||
Logging.LogGenericWarning("ASF will not keep this code anymore!", botName);
|
||||
BotDatabase.SteamGuardAccount = null;
|
||||
}
|
||||
|
||||
if (BotDatabase.MobileAuthenticator != null) {
|
||||
BotDatabase.MobileAuthenticator.Init(this);
|
||||
} else {
|
||||
@@ -256,6 +238,18 @@ namespace ArchiSteamFarm {
|
||||
Start().Forget();
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
GiftsSemaphore.Dispose();
|
||||
LoginSemaphore.Dispose();
|
||||
HandledGifts.Dispose();
|
||||
|
||||
AcceptConfirmationsTimer?.Dispose();
|
||||
ArchiWebHandler?.Dispose();
|
||||
CardsFarmer?.Dispose();
|
||||
SendItemsTimer?.Dispose();
|
||||
Trading?.Dispose();
|
||||
}
|
||||
|
||||
internal async Task AcceptConfirmations(bool accept, Steam.ConfirmationDetails.EType acceptedType = Steam.ConfirmationDetails.EType.Unknown, ulong acceptedSteamID = 0, HashSet<ulong> acceptedTradeIDs = null) {
|
||||
if (BotDatabase.MobileAuthenticator == null) {
|
||||
return;
|
||||
@@ -268,7 +262,6 @@ namespace ArchiSteamFarm {
|
||||
|
||||
if (acceptedType != Steam.ConfirmationDetails.EType.Unknown) {
|
||||
if (confirmations.RemoveWhere(confirmation => (confirmation.Type != acceptedType) && (confirmation.Type != Steam.ConfirmationDetails.EType.Other)) > 0) {
|
||||
confirmations.TrimExcess();
|
||||
if (confirmations.Count == 0) {
|
||||
return;
|
||||
}
|
||||
@@ -288,7 +281,6 @@ namespace ArchiSteamFarm {
|
||||
|
||||
if (ignoredConfirmationIDs.Count > 0) {
|
||||
if (confirmations.RemoveWhere(confirmation => ignoredConfirmationIDs.Contains(confirmation.ID)) > 0) {
|
||||
confirmations.TrimExcess();
|
||||
if (confirmations.Count == 0) {
|
||||
return;
|
||||
}
|
||||
@@ -318,7 +310,7 @@ namespace ArchiSteamFarm {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((callback == null) || string.IsNullOrEmpty(callback.Nonce)) {
|
||||
if (string.IsNullOrEmpty(callback?.Nonce)) {
|
||||
Start().Forget();
|
||||
return false;
|
||||
}
|
||||
@@ -717,7 +709,6 @@ namespace ArchiSteamFarm {
|
||||
|
||||
// Remove from our pending inventory all items that are not steam cards and boosters
|
||||
inventory.RemoveWhere(item => (item.Type != Steam.Item.EType.TradingCard) && (item.Type != Steam.Item.EType.FoilTradingCard) && (item.Type != Steam.Item.EType.BoosterPack));
|
||||
inventory.TrimExcess();
|
||||
|
||||
if (inventory.Count == 0) {
|
||||
return "Nothing to send, inventory seems empty!";
|
||||
@@ -1530,46 +1521,23 @@ namespace ArchiSteamFarm {
|
||||
TwoFactorCode = await BotDatabase.MobileAuthenticator.GenerateToken().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (Program.GlobalConfig.HackIgnoreMachineID) {
|
||||
Logging.LogGenericWarning("Using workaround for broken GenerateMachineID()!", BotName);
|
||||
ArchiHandler.HackedLogOn(new SteamUser.LogOnDetails {
|
||||
Username = BotConfig.SteamLogin,
|
||||
Password = BotConfig.SteamPassword,
|
||||
AuthCode = AuthCode,
|
||||
CellID = Program.GlobalDatabase.CellID,
|
||||
LoginID = LoginID,
|
||||
LoginKey = BotDatabase.LoginKey,
|
||||
TwoFactorCode = TwoFactorCode,
|
||||
SentryFileHash = sentryHash,
|
||||
ShouldRememberPassword = true
|
||||
});
|
||||
return;
|
||||
}
|
||||
SteamUser.LogOnDetails logOnDetails = new SteamUser.LogOnDetails {
|
||||
Username = BotConfig.SteamLogin,
|
||||
Password = BotConfig.SteamPassword,
|
||||
AuthCode = AuthCode,
|
||||
CellID = Program.GlobalDatabase.CellID,
|
||||
LoginID = LoginID,
|
||||
LoginKey = BotDatabase.LoginKey,
|
||||
TwoFactorCode = TwoFactorCode,
|
||||
SentryFileHash = sentryHash,
|
||||
ShouldRememberPassword = true
|
||||
};
|
||||
|
||||
try {
|
||||
SteamUser.LogOn(new SteamUser.LogOnDetails {
|
||||
Username = BotConfig.SteamLogin,
|
||||
Password = BotConfig.SteamPassword,
|
||||
AuthCode = AuthCode,
|
||||
CellID = Program.GlobalDatabase.CellID,
|
||||
LoginID = LoginID,
|
||||
LoginKey = BotDatabase.LoginKey,
|
||||
TwoFactorCode = TwoFactorCode,
|
||||
SentryFileHash = sentryHash,
|
||||
ShouldRememberPassword = true
|
||||
});
|
||||
} catch (Exception) {
|
||||
ArchiHandler.HackedLogOn(new SteamUser.LogOnDetails {
|
||||
Username = BotConfig.SteamLogin,
|
||||
Password = BotConfig.SteamPassword,
|
||||
AuthCode = AuthCode,
|
||||
CellID = Program.GlobalDatabase.CellID,
|
||||
LoginID = LoginID,
|
||||
LoginKey = BotDatabase.LoginKey,
|
||||
TwoFactorCode = TwoFactorCode,
|
||||
SentryFileHash = sentryHash,
|
||||
ShouldRememberPassword = true
|
||||
});
|
||||
SteamUser.LogOn(logOnDetails);
|
||||
} catch {
|
||||
// TODO: Remove me once https://github.com/SteamRE/SteamKit/issues/305 is fixed
|
||||
ArchiHandler.LogOnWithoutMachineID(logOnDetails);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1625,7 +1593,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
private async void OnGuestPassList(SteamApps.GuestPassListCallback callback) {
|
||||
if ((callback == null) || (callback.GuestPasses == null)) {
|
||||
if (callback?.GuestPasses == null) {
|
||||
Logging.LogNullError(nameof(callback) + " || " + nameof(callback.GuestPasses), BotName);
|
||||
return;
|
||||
}
|
||||
@@ -1663,7 +1631,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
private void OnChatInvite(SteamFriends.ChatInviteCallback callback) {
|
||||
if ((callback == null) || (callback.ChatRoomID == null) || (callback.PatronID == null)) {
|
||||
if ((callback?.ChatRoomID == null) || (callback.PatronID == null)) {
|
||||
Logging.LogNullError(nameof(callback) + " || " + nameof(callback.ChatRoomID) + " || " + nameof(callback.PatronID), BotName);
|
||||
return;
|
||||
}
|
||||
@@ -1705,7 +1673,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
private void OnFriendsList(SteamFriends.FriendsListCallback callback) {
|
||||
if ((callback == null) || (callback.FriendList == null)) {
|
||||
if (callback?.FriendList == null) {
|
||||
Logging.LogNullError(nameof(callback) + " || " + nameof(callback.FriendList), BotName);
|
||||
return;
|
||||
}
|
||||
@@ -1738,7 +1706,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
private async void OnFriendMsgHistory(SteamFriends.FriendMsgHistoryCallback callback) {
|
||||
if ((callback == null) || (callback.Messages == null) || (callback.SteamID == null)) {
|
||||
if ((callback?.Messages == null) || (callback.SteamID == null)) {
|
||||
Logging.LogNullError(nameof(callback) + " || " + nameof(callback.Messages) + " || " + nameof(callback.SteamID), BotName);
|
||||
return;
|
||||
}
|
||||
@@ -1811,7 +1779,7 @@ namespace ArchiSteamFarm {
|
||||
break;
|
||||
case EResult.InvalidPassword:
|
||||
InvalidPassword = true;
|
||||
Logging.LogGenericWarning("Unable to login to Steam: " + callback.Result, BotName);
|
||||
Logging.LogGenericWarning("Unable to login to Steam: " + callback.Result + " / " + callback.ExtendedResult, BotName);
|
||||
break;
|
||||
case EResult.OK:
|
||||
Logging.LogGenericInfo("Successfully logged on!", BotName);
|
||||
@@ -1871,17 +1839,17 @@ namespace ArchiSteamFarm {
|
||||
case EResult.ServiceUnavailable:
|
||||
case EResult.Timeout:
|
||||
case EResult.TryAnotherCM:
|
||||
Logging.LogGenericWarning("Unable to login to Steam: " + callback.Result, BotName);
|
||||
Logging.LogGenericWarning("Unable to login to Steam: " + callback.Result + " / " + callback.ExtendedResult, BotName);
|
||||
break;
|
||||
default: // Unexpected result, shutdown immediately
|
||||
Logging.LogGenericError("Unable to login to Steam: " + callback.Result, BotName);
|
||||
Logging.LogGenericError("Unable to login to Steam: " + callback.Result + " / " + callback.ExtendedResult, BotName);
|
||||
Stop();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLoginKey(SteamUser.LoginKeyCallback callback) {
|
||||
if ((callback == null) || string.IsNullOrEmpty(callback.LoginKey)) {
|
||||
if (string.IsNullOrEmpty(callback?.LoginKey)) {
|
||||
Logging.LogNullError(nameof(callback) + " || " + nameof(callback.LoginKey), BotName);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -64,23 +64,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Converter code will be removed soon
|
||||
[JsonProperty]
|
||||
private ObsoleteSteamGuardAccount _SteamGuardAccount;
|
||||
|
||||
internal ObsoleteSteamGuardAccount SteamGuardAccount {
|
||||
get {
|
||||
return _SteamGuardAccount;
|
||||
}
|
||||
set {
|
||||
if (_SteamGuardAccount == value) {
|
||||
return;
|
||||
}
|
||||
|
||||
_SteamGuardAccount = value;
|
||||
Save();
|
||||
}
|
||||
}
|
||||
private readonly object FileLock = new object();
|
||||
|
||||
private string FilePath;
|
||||
|
||||
@@ -133,7 +117,7 @@ namespace ArchiSteamFarm {
|
||||
return;
|
||||
}
|
||||
|
||||
lock (FilePath) {
|
||||
lock (FileLock) {
|
||||
for (byte i = 0; i < 5; i++) {
|
||||
try {
|
||||
File.WriteAllText(FilePath, json);
|
||||
|
||||
@@ -34,7 +34,7 @@ using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
internal sealed class CardsFarmer {
|
||||
internal sealed class CardsFarmer : IDisposable {
|
||||
internal const byte MaxGamesPlayedConcurrently = 32; // This is limit introduced by Steam Network
|
||||
|
||||
[JsonProperty]
|
||||
@@ -70,6 +70,14 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
CurrentGamesFarming.Dispose();
|
||||
FarmResetEvent.Dispose();
|
||||
FarmingSemaphore.Dispose();
|
||||
|
||||
Timer?.Dispose();
|
||||
}
|
||||
|
||||
internal async Task SwitchToManualMode(bool manualMode) {
|
||||
if (ManualMode == manualMode) {
|
||||
return;
|
||||
@@ -128,7 +136,6 @@ namespace ArchiSteamFarm {
|
||||
uint appID = gamesToFarmSolo.First();
|
||||
if (await FarmSolo(appID).ConfigureAwait(false)) {
|
||||
gamesToFarmSolo.Remove(appID);
|
||||
gamesToFarmSolo.TrimExcess();
|
||||
} else {
|
||||
NowFarming = false;
|
||||
return;
|
||||
|
||||
@@ -50,10 +50,6 @@ namespace ArchiSteamFarm {
|
||||
public bool MoveNext() => Enumerator.MoveNext();
|
||||
public void Reset() => Enumerator.Reset();
|
||||
|
||||
public void Dispose() {
|
||||
if (Lock != null) {
|
||||
Lock.ExitReadLock();
|
||||
}
|
||||
}
|
||||
public void Dispose() => Lock?.ExitReadLock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,11 +100,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
if (Lock != null) {
|
||||
Lock.Dispose();
|
||||
}
|
||||
}
|
||||
public void Dispose() => Lock?.Dispose();
|
||||
|
||||
public void CopyTo(T[] array, int arrayIndex) {
|
||||
Lock.EnterReadLock();
|
||||
|
||||
@@ -40,6 +40,7 @@ namespace ArchiSteamFarm {
|
||||
internal static bool NetHookAlreadyInitialized { get; set; }
|
||||
|
||||
internal sealed class DebugListener : IDebugListener {
|
||||
private readonly object FileLock = new object();
|
||||
private readonly string FilePath;
|
||||
|
||||
internal DebugListener(string filePath) {
|
||||
@@ -56,7 +57,7 @@ namespace ArchiSteamFarm {
|
||||
return;
|
||||
}
|
||||
|
||||
lock (FilePath) {
|
||||
lock (FileLock) {
|
||||
try {
|
||||
File.AppendAllText(FilePath, category + " | " + msg + Environment.NewLine);
|
||||
} catch (Exception e) {
|
||||
|
||||
@@ -107,10 +107,6 @@ namespace ArchiSteamFarm {
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal bool Statistics { get; private set; } = true;
|
||||
|
||||
// TODO: Please remove me immediately after https://github.com/SteamRE/SteamKit/issues/254 gets fixed
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal bool HackIgnoreMachineID { get; private set; } = false;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal HashSet<uint> Blacklist { get; private set; } = new HashSet<uint>(GlobalBlacklist);
|
||||
|
||||
|
||||
@@ -24,18 +24,29 @@
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
internal sealed class GlobalDatabase {
|
||||
private static readonly JsonSerializerSettings CustomSerializerSettings = new JsonSerializerSettings {
|
||||
Converters = new List<JsonConverter> {
|
||||
new IPAddressConverter(),
|
||||
new IPEndPointConverter()
|
||||
}
|
||||
};
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
private uint _CellID;
|
||||
|
||||
internal uint CellID {
|
||||
get {
|
||||
return _CellID;
|
||||
}
|
||||
set {
|
||||
if (_CellID == value) {
|
||||
if ((value == 0) || (_CellID == value)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -45,7 +56,10 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
private uint _CellID;
|
||||
[SuppressMessage("ReSharper", "AutoPropertyCanBeMadeGetOnly.Local")]
|
||||
internal InMemoryServerListProvider ServerListProvider { get; private set; } = new InMemoryServerListProvider();
|
||||
|
||||
private readonly object FileLock = new object();
|
||||
|
||||
private string FilePath;
|
||||
|
||||
@@ -62,7 +76,7 @@ namespace ArchiSteamFarm {
|
||||
GlobalDatabase globalDatabase;
|
||||
|
||||
try {
|
||||
globalDatabase = JsonConvert.DeserializeObject<GlobalDatabase>(File.ReadAllText(filePath));
|
||||
globalDatabase = JsonConvert.DeserializeObject<GlobalDatabase>(File.ReadAllText(filePath), CustomSerializerSettings);
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(e);
|
||||
return null;
|
||||
@@ -77,8 +91,10 @@ namespace ArchiSteamFarm {
|
||||
return globalDatabase;
|
||||
}
|
||||
|
||||
private void OnServerListUpdated(object sender, EventArgs e) => Save();
|
||||
|
||||
// This constructor is used when creating new database
|
||||
private GlobalDatabase(string filePath) {
|
||||
private GlobalDatabase(string filePath) : this() {
|
||||
if (string.IsNullOrEmpty(filePath)) {
|
||||
throw new ArgumentNullException(nameof(filePath));
|
||||
}
|
||||
@@ -89,16 +105,18 @@ namespace ArchiSteamFarm {
|
||||
|
||||
// This constructor is used only by deserializer
|
||||
[SuppressMessage("ReSharper", "UnusedMember.Local")]
|
||||
private GlobalDatabase() { }
|
||||
private GlobalDatabase() {
|
||||
ServerListProvider.ServerListUpdated += OnServerListUpdated;
|
||||
}
|
||||
|
||||
private void Save() {
|
||||
string json = JsonConvert.SerializeObject(this);
|
||||
string json = JsonConvert.SerializeObject(this, CustomSerializerSettings);
|
||||
if (string.IsNullOrEmpty(json)) {
|
||||
Logging.LogNullError(nameof(json));
|
||||
return;
|
||||
}
|
||||
|
||||
lock (FilePath) {
|
||||
lock (FileLock) {
|
||||
for (byte i = 0; i < 5; i++) {
|
||||
try {
|
||||
File.WriteAllText(FilePath, json);
|
||||
|
||||
44
ArchiSteamFarm/IPAddressConverter.cs
Normal file
44
ArchiSteamFarm/IPAddressConverter.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
_ _ _ ____ _ _____
|
||||
/ \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___
|
||||
/ _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \
|
||||
/ ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | |
|
||||
/_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_|
|
||||
|
||||
Copyright 2015-2016 Łukasz "JustArchi" Domeradzki
|
||||
Contact: JustArchi@JustArchi.net
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
internal sealed class IPAddressConverter : JsonConverter {
|
||||
public override bool CanConvert(Type objectType) => objectType == typeof(IPAddress);
|
||||
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
|
||||
JToken token = JToken.Load(reader);
|
||||
return IPAddress.Parse(token.Value<string>());
|
||||
}
|
||||
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
|
||||
IPAddress ip = (IPAddress) value;
|
||||
writer.WriteValue(ip.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
51
ArchiSteamFarm/IPEndPointConverter.cs
Normal file
51
ArchiSteamFarm/IPEndPointConverter.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
_ _ _ ____ _ _____
|
||||
/ \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___
|
||||
/ _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \
|
||||
/ ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | |
|
||||
/_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_|
|
||||
|
||||
Copyright 2015-2016 Łukasz "JustArchi" Domeradzki
|
||||
Contact: JustArchi@JustArchi.net
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
internal sealed class IPEndPointConverter : JsonConverter {
|
||||
public override bool CanConvert(Type objectType) => objectType == typeof(IPEndPoint);
|
||||
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
|
||||
JObject jo = JObject.Load(reader);
|
||||
IPAddress address = jo["Address"].ToObject<IPAddress>(serializer);
|
||||
ushort port = jo["Port"].Value<ushort>();
|
||||
return new IPEndPoint(address, port);
|
||||
}
|
||||
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
|
||||
IPEndPoint ep = (IPEndPoint) value;
|
||||
writer.WriteStartObject();
|
||||
writer.WritePropertyName("Address");
|
||||
serializer.Serialize(writer, ep.Address);
|
||||
writer.WritePropertyName("Port");
|
||||
writer.WriteValue(ep.Port);
|
||||
writer.WriteEndObject();
|
||||
}
|
||||
}
|
||||
}
|
||||
59
ArchiSteamFarm/InMemoryServerListProvider.cs
Normal file
59
ArchiSteamFarm/InMemoryServerListProvider.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
_ _ _ ____ _ _____
|
||||
/ \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___
|
||||
/ _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \
|
||||
/ ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | |
|
||||
/_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_|
|
||||
|
||||
Copyright 2015-2016 Łukasz "JustArchi" Domeradzki
|
||||
Contact: JustArchi@JustArchi.net
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
using SteamKit2.Discovery;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
internal sealed class InMemoryServerListProvider : IServerListProvider {
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
[SuppressMessage("ReSharper", "FieldCanBeMadeReadOnly.Local")]
|
||||
private HashSet<IPEndPoint> Servers = new HashSet<IPEndPoint>();
|
||||
|
||||
internal event EventHandler ServerListUpdated = delegate { };
|
||||
|
||||
public Task<IEnumerable<IPEndPoint>> FetchServerListAsync() => Task.FromResult<IEnumerable<IPEndPoint>>(Servers);
|
||||
|
||||
public Task UpdateServerListAsync(IEnumerable<IPEndPoint> endpoints) {
|
||||
if (endpoints == null) {
|
||||
Logging.LogNullError(nameof(endpoints));
|
||||
return Task.Delay(0);
|
||||
}
|
||||
|
||||
Servers.Clear();
|
||||
foreach (IPEndPoint endpoint in endpoints) {
|
||||
Servers.Add(endpoint);
|
||||
}
|
||||
|
||||
ServerListUpdated(this, EventArgs.Empty);
|
||||
|
||||
return Task.Delay(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,6 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
@@ -38,16 +37,17 @@ namespace ArchiSteamFarm {
|
||||
private const string GeneralLayout = @"${date:format=yyyy-MM-dd HH\:mm\:ss}|${level:uppercase=true}|" + LayoutMessage;
|
||||
private const string EventLogLayout = LayoutMessage;
|
||||
|
||||
private static readonly HashSet<LoggingRule> ConsoleLoggingRules = new HashSet<LoggingRule>();
|
||||
private static readonly ConcurrentHashSet<LoggingRule> ConsoleLoggingRules = new ConcurrentHashSet<LoggingRule>();
|
||||
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
private static bool IsUsingCustomConfiguration;
|
||||
private static bool IsUsingCustomConfiguration, IsWaitingForUserInput;
|
||||
|
||||
internal static void InitCoreLoggers() {
|
||||
if (LogManager.Configuration != null) {
|
||||
// User provided custom NLog config, or we have it set already, so don't override it
|
||||
IsUsingCustomConfiguration = true;
|
||||
InitConsoleLoggers();
|
||||
LogManager.ConfigurationChanged += OnConfigurationChanged;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -94,6 +94,8 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
internal static void OnUserInputStart() {
|
||||
IsWaitingForUserInput = true;
|
||||
|
||||
if (ConsoleLoggingRules.Count == 0) {
|
||||
return;
|
||||
}
|
||||
@@ -106,11 +108,13 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
internal static void OnUserInputEnd() {
|
||||
IsWaitingForUserInput = false;
|
||||
|
||||
if (ConsoleLoggingRules.Count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (LoggingRule consoleLoggingRule in ConsoleLoggingRules) {
|
||||
foreach (LoggingRule consoleLoggingRule in ConsoleLoggingRules.Where(consoleLoggingRule => !LogManager.Configuration.LoggingRules.Contains(consoleLoggingRule))) {
|
||||
LogManager.Configuration.LoggingRules.Add(consoleLoggingRule);
|
||||
}
|
||||
|
||||
@@ -183,9 +187,23 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
private static void InitConsoleLoggers() {
|
||||
ConsoleLoggingRules.Clear();
|
||||
foreach (LoggingRule loggingRule in from loggingRule in LogManager.Configuration.LoggingRules from target in loggingRule.Targets where target is ColoredConsoleTarget || target is ConsoleTarget select loggingRule) {
|
||||
ConsoleLoggingRules.Add(loggingRule);
|
||||
}
|
||||
}
|
||||
|
||||
private static void OnConfigurationChanged(object sender, LoggingConfigurationChangedEventArgs e) {
|
||||
if ((sender == null) || (e == null)) {
|
||||
LogNullError(nameof(sender) + " || " + nameof(e));
|
||||
return;
|
||||
}
|
||||
|
||||
InitConsoleLoggers();
|
||||
|
||||
if (IsWaitingForUserInput) {
|
||||
OnUserInputStart();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
@@ -33,6 +34,8 @@ using HtmlAgilityPack;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
[SuppressMessage("ReSharper", "ClassCannotBeInstantiated")]
|
||||
[SuppressMessage("ReSharper", "ClassNeverInstantiated.Global")]
|
||||
internal sealed class MobileAuthenticator {
|
||||
internal sealed class Confirmation {
|
||||
internal readonly uint ID;
|
||||
@@ -57,30 +60,19 @@ namespace ArchiSteamFarm {
|
||||
|
||||
internal bool HasDeviceID => !string.IsNullOrEmpty(DeviceID);
|
||||
|
||||
#pragma warning disable 649
|
||||
[JsonProperty(PropertyName = "shared_secret", Required = Required.DisallowNull)]
|
||||
private string SharedSecret;
|
||||
|
||||
[JsonProperty(PropertyName = "identity_secret", Required = Required.DisallowNull)]
|
||||
private string IdentitySecret;
|
||||
#pragma warning restore 649
|
||||
|
||||
[JsonProperty(PropertyName = "device_id")]
|
||||
private string DeviceID;
|
||||
|
||||
private Bot Bot;
|
||||
|
||||
internal static MobileAuthenticator LoadFromSteamGuardAccount(ObsoleteSteamGuardAccount sga) {
|
||||
if (sga != null) {
|
||||
return new MobileAuthenticator {
|
||||
SharedSecret = sga.SharedSecret,
|
||||
IdentitySecret = sga.IdentitySecret,
|
||||
DeviceID = sga.DeviceID
|
||||
};
|
||||
}
|
||||
|
||||
Logging.LogNullError(nameof(sga));
|
||||
return null;
|
||||
}
|
||||
|
||||
private MobileAuthenticator() {
|
||||
|
||||
}
|
||||
@@ -173,11 +165,8 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
HtmlDocument htmlDocument = await Bot.ArchiWebHandler.GetConfirmations(DeviceID, confirmationHash, time).ConfigureAwait(false);
|
||||
if (htmlDocument == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
HtmlNodeCollection confirmationNodes = htmlDocument.DocumentNode.SelectNodes("//div[@class='mobileconf_list_entry']");
|
||||
HtmlNodeCollection confirmationNodes = htmlDocument?.DocumentNode.SelectNodes("//div[@class='mobileconf_list_entry']");
|
||||
if (confirmationNodes == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
// TODO: This will be completely removed soon
|
||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||
[SuppressMessage("ReSharper", "UnusedMember.Global")]
|
||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||
[SuppressMessage("ReSharper", "ClassNeverInstantiated.Global")]
|
||||
[SuppressMessage("ReSharper", "UnusedAutoPropertyAccessor.Global")]
|
||||
public class ObsoleteSteamGuardAccount {
|
||||
[JsonProperty("shared_secret")]
|
||||
public string SharedSecret { get; set; }
|
||||
|
||||
[JsonProperty("serial_number")]
|
||||
public string SerialNumber { get; set; }
|
||||
|
||||
[JsonProperty("revocation_code")]
|
||||
public string RevocationCode { get; set; }
|
||||
|
||||
[JsonProperty("uri")]
|
||||
public string URI { get; set; }
|
||||
|
||||
[JsonProperty("server_time")]
|
||||
public long ServerTime { get; set; }
|
||||
|
||||
[JsonProperty("account_name")]
|
||||
public string AccountName { get; set; }
|
||||
|
||||
[JsonProperty("token_gid")]
|
||||
public string TokenGID { get; set; }
|
||||
|
||||
[JsonProperty("identity_secret")]
|
||||
public string IdentitySecret { get; set; }
|
||||
|
||||
[JsonProperty("secret_1")]
|
||||
public string Secret1 { get; set; }
|
||||
|
||||
[JsonProperty("status")]
|
||||
public int Status { get; set; }
|
||||
|
||||
[JsonProperty("device_id")]
|
||||
public string DeviceID { get; set; }
|
||||
|
||||
[JsonProperty("fully_enrolled")]
|
||||
public bool FullyEnrolled { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -437,8 +437,8 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
private static void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs args) {
|
||||
if ((sender == null) || (args == null) || (args.ExceptionObject == null)) {
|
||||
Logging.LogNullError(nameof(sender) + " || " + nameof(args) + " || " + nameof(args.ExceptionObject));
|
||||
if (args?.ExceptionObject == null) {
|
||||
Logging.LogNullError(nameof(args) + " || " + nameof(args.ExceptionObject));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -446,8 +446,8 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
private static void UnobservedTaskExceptionHandler(object sender, UnobservedTaskExceptionEventArgs args) {
|
||||
if ((sender == null) || (args == null) || (args.Exception == null)) {
|
||||
Logging.LogNullError(nameof(sender) + " || " + nameof(args) + " || " + nameof(args.Exception));
|
||||
if (args?.Exception == null) {
|
||||
Logging.LogNullError(nameof(args) + " || " + nameof(args.Exception));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -462,7 +462,6 @@ namespace ArchiSteamFarm {
|
||||
Logging.LogGenericInfo("ASF V" + Version);
|
||||
|
||||
Directory.SetCurrentDirectory(ExecutableDirectory);
|
||||
InitServices();
|
||||
|
||||
// Allow loading configs from source tree if it's a debug build
|
||||
if (Debugging.IsDebugBuild) {
|
||||
@@ -481,6 +480,8 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
}
|
||||
|
||||
InitServices();
|
||||
|
||||
// If debugging is on, we prepare debug directory prior to running
|
||||
if (GlobalConfig.Debug) {
|
||||
if (Directory.Exists(DebugDirectory)) {
|
||||
@@ -515,7 +516,7 @@ namespace ArchiSteamFarm {
|
||||
CheckForUpdate().Wait();
|
||||
|
||||
// Before attempting to connect, initialize our list of CMs
|
||||
Bot.RefreshCMs(GlobalDatabase.CellID).Wait();
|
||||
Bot.InitializeCMs(GlobalDatabase.CellID, GlobalDatabase.ServerListProvider);
|
||||
|
||||
bool isRunning = false;
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
internal static class SharedInfo {
|
||||
internal const string Version = "2.1.2.2";
|
||||
internal const string Version = "2.1.2.5";
|
||||
internal const string Copyright = "Copyright © ArchiSteamFarm 2015-2016";
|
||||
|
||||
internal const string GithubRepo = "JustArchi/ArchiSteamFarm";
|
||||
|
||||
@@ -31,7 +31,7 @@ using System.Threading.Tasks;
|
||||
using ArchiSteamFarm.JSON;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
internal sealed class Trading {
|
||||
internal sealed class Trading : IDisposable {
|
||||
private enum ParseTradeResult : byte {
|
||||
[SuppressMessage("ReSharper", "UnusedMember.Local")]
|
||||
Unknown,
|
||||
@@ -69,6 +69,11 @@ namespace ArchiSteamFarm {
|
||||
Bot = bot;
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
IgnoredTrades.Dispose();
|
||||
TradesSemaphore.Dispose();
|
||||
}
|
||||
|
||||
internal void OnDisconnected() => IgnoredTrades.ClearAndTrim();
|
||||
|
||||
internal async Task CheckTrades() {
|
||||
@@ -101,7 +106,6 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
if (tradeOffers.RemoveWhere(tradeoffer => IgnoredTrades.Contains(tradeoffer.TradeOfferID)) > 0) {
|
||||
tradeOffers.TrimExcess();
|
||||
if (tradeOffers.Count == 0) {
|
||||
return;
|
||||
}
|
||||
@@ -211,7 +215,6 @@ namespace ArchiSteamFarm {
|
||||
|
||||
// Now remove from our inventory all items we're NOT interested in
|
||||
inventory.RemoveWhere(item => !appIDs.Contains(item.RealAppID));
|
||||
inventory.TrimExcess();
|
||||
|
||||
// If for some reason Valve is talking crap and we can't find mentioned items, assume OK
|
||||
if (inventory.Count == 0) {
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace ArchiSteamFarm {
|
||||
string HandleCommand(string input);
|
||||
}
|
||||
|
||||
internal sealed class WCF : IWCF {
|
||||
internal sealed class WCF : IWCF, IDisposable {
|
||||
|
||||
private static string URL = "http://localhost:1242/ASF";
|
||||
|
||||
@@ -52,6 +52,33 @@ namespace ArchiSteamFarm {
|
||||
URL = "http://" + Program.GlobalConfig.WCFHostname + ":" + Program.GlobalConfig.WCFPort + "/ASF";
|
||||
}
|
||||
|
||||
public string HandleCommand(string input) {
|
||||
if (string.IsNullOrEmpty(input)) {
|
||||
Logging.LogNullError(nameof(input));
|
||||
return null;
|
||||
}
|
||||
|
||||
Bot bot = Bot.Bots.Values.FirstOrDefault();
|
||||
if (bot == null) {
|
||||
return "ERROR: No bots are enabled!";
|
||||
}
|
||||
|
||||
if (Program.GlobalConfig.SteamOwnerID == 0) {
|
||||
return "Refusing to handle request because SteamOwnerID is not set!";
|
||||
}
|
||||
|
||||
string command = "!" + input;
|
||||
string output = bot.Response(Program.GlobalConfig.SteamOwnerID, command).Result; // TODO: This should be asynchronous
|
||||
|
||||
Logging.LogGenericInfo("Answered to command: " + input + " with: " + output);
|
||||
return output;
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
ServiceHost?.Close();
|
||||
Client?.Close();
|
||||
}
|
||||
|
||||
internal bool IsServerRunning() => ServiceHost != null;
|
||||
|
||||
internal void StartServer() {
|
||||
@@ -98,28 +125,6 @@ namespace ArchiSteamFarm {
|
||||
|
||||
return Client.HandleCommand(input);
|
||||
}
|
||||
|
||||
public string HandleCommand(string input) {
|
||||
if (string.IsNullOrEmpty(input)) {
|
||||
Logging.LogNullError(nameof(input));
|
||||
return null;
|
||||
}
|
||||
|
||||
Bot bot = Bot.Bots.Values.FirstOrDefault();
|
||||
if (bot == null) {
|
||||
return "ERROR: No bots are enabled!";
|
||||
}
|
||||
|
||||
if (Program.GlobalConfig.SteamOwnerID == 0) {
|
||||
return "Refusing to handle request because SteamOwnerID is not set!";
|
||||
}
|
||||
|
||||
string command = "!" + input;
|
||||
string output = bot.Response(Program.GlobalConfig.SteamOwnerID, command).Result; // TODO: This should be asynchronous
|
||||
|
||||
Logging.LogGenericInfo("Answered to command: " + input + " with: " + output);
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class Client : ClientBase<IWCF>, IWCF {
|
||||
|
||||
@@ -365,7 +365,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
using (HttpResponseMessage response = await UrlHeadToResponse(request, referer).ConfigureAwait(false)) {
|
||||
return response == null ? null : response.RequestMessage.RequestUri;
|
||||
return response?.RequestMessage.RequestUri;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
"WCFHostname": "localhost",
|
||||
"WCFPort": 1242,
|
||||
"Statistics": true,
|
||||
"HackIgnoreMachineID": false,
|
||||
"Blacklist": [
|
||||
267420,
|
||||
303700,
|
||||
|
||||
@@ -6,5 +6,5 @@
|
||||
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net461" />
|
||||
<package id="NLog" version="4.4.0-beta13" targetFramework="net461" />
|
||||
<package id="protobuf-net" version="2.0.0.668" targetFramework="net45" />
|
||||
<package id="SteamKit2" version="1.7.0" targetFramework="net452" />
|
||||
<package id="SteamKit2" version="1.8.0" targetFramework="net461" />
|
||||
</packages>
|
||||
@@ -107,9 +107,6 @@ namespace ConfigGenerator {
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
public bool Statistics { get; set; } = true;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
public bool HackIgnoreMachineID { get; set; } = false;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
public List<uint> Blacklist { get; set; } = new List<uint>();
|
||||
|
||||
|
||||
@@ -6,4 +6,4 @@ If my issue is not meeting contributing guidelines specified above, especially i
|
||||
|
||||
-----
|
||||
|
||||
Feel free to remove everything made up to this point, after all you're not being in a primary school.
|
||||
Now that you read and understood the notice, feel free to remove it and fill with real issue.
|
||||
|
||||
8
cc.sh
8
cc.sh
@@ -2,6 +2,7 @@
|
||||
set -eu
|
||||
|
||||
BUILD="Release"
|
||||
AOT=0
|
||||
CLEAN=0
|
||||
|
||||
MONO_ARGS=("--aot" "--llvm" "--server" "-O=all")
|
||||
@@ -10,7 +11,7 @@ BINARIES=("ArchiSteamFarm/bin/Release/ArchiSteamFarm.exe")
|
||||
SOLUTION="ArchiSteamFarm.sln"
|
||||
|
||||
PRINT_USAGE() {
|
||||
echo "Usage: $0 [--clean] [debug/release]"
|
||||
echo "Usage: $0 [--clean] [--aot] [debug/release]"
|
||||
exit 1
|
||||
}
|
||||
|
||||
@@ -18,6 +19,7 @@ for ARG in "$@"; do
|
||||
case "$ARG" in
|
||||
release|Release) BUILD="Release" ;;
|
||||
debug|Debug) BUILD="Debug" ;;
|
||||
--aot) AOT=1 ;;
|
||||
--clean) CLEAN=1 ;;
|
||||
*) PRINT_USAGE
|
||||
esac
|
||||
@@ -51,8 +53,8 @@ if [[ ! -f "${BINARIES[0]}" ]]; then
|
||||
echo "ERROR: ${BINARIES[0]} binary could not be found!"
|
||||
fi
|
||||
|
||||
# If it's release build, use Mono AOT for output binaries
|
||||
if [[ "$BUILD" = "Release" ]]; then
|
||||
# Use Mono AOT for output binaries if needed
|
||||
if [[ "$AOT" -eq 1 && "$BUILD" = "Release" ]]; then
|
||||
for BINARY in "${BINARIES[@]}"; do
|
||||
if [[ ! -f "$BINARY" ]]; then
|
||||
continue
|
||||
|
||||
BIN
packages/SteamKit2.1.7.0/SteamKit2.1.7.0.nupkg
vendored
BIN
packages/SteamKit2.1.7.0/SteamKit2.1.7.0.nupkg
vendored
Binary file not shown.
BIN
packages/SteamKit2.1.7.0/lib/net45/SteamKit2.dll
vendored
BIN
packages/SteamKit2.1.7.0/lib/net45/SteamKit2.dll
vendored
Binary file not shown.
BIN
packages/SteamKit2.1.8.0/SteamKit2.1.8.0.nupkg
vendored
Normal file
BIN
packages/SteamKit2.1.8.0/SteamKit2.1.8.0.nupkg
vendored
Normal file
Binary file not shown.
BIN
packages/SteamKit2.1.8.0/lib/net45/SteamKit2.dll
vendored
Normal file
BIN
packages/SteamKit2.1.8.0/lib/net45/SteamKit2.dll
vendored
Normal file
Binary file not shown.
@@ -1478,81 +1478,174 @@
|
||||
</summary>
|
||||
<returns>The data.</returns>
|
||||
</member>
|
||||
<member name="T:SteamKit2.ServerQuality">
|
||||
<member name="T:SteamKit2.Discovery.FileStorageServerListProvider">
|
||||
<summary>
|
||||
A server list provider that uses a file to persist the server list using protobuf
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:SteamKit2.Discovery.FileStorageServerListProvider.#ctor(System.String)">
|
||||
<summary>
|
||||
Initialize a new instance of FileStorageServerListProvider
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:SteamKit2.Discovery.FileStorageServerListProvider.FetchServerListAsync">
|
||||
<summary>
|
||||
Read the stored list of servers from the file
|
||||
</summary>
|
||||
<returns>List of servers if persisted, otherwise an empty list</returns>
|
||||
</member>
|
||||
<member name="M:SteamKit2.Discovery.FileStorageServerListProvider.UpdateServerListAsync(System.Collections.Generic.IEnumerable{System.Net.IPEndPoint})">
|
||||
<summary>
|
||||
Writes the supplied list of servers to persistent storage
|
||||
</summary>
|
||||
<param name="endpoints">List of server endpoints</param>
|
||||
<returns>Awaitable task for write completion</returns>
|
||||
</member>
|
||||
<member name="T:SteamKit2.Discovery.NullServerListProvider">
|
||||
<summary>
|
||||
A server list provider that returns an empty list, for consumers that populate the server list themselves
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:SteamKit2.Discovery.NullServerListProvider.FetchServerListAsync">
|
||||
<summary>
|
||||
No-op implementation that returns an empty server list
|
||||
</summary>
|
||||
<returns>Empty server list</returns>
|
||||
</member>
|
||||
<member name="M:SteamKit2.Discovery.NullServerListProvider.UpdateServerListAsync(System.Collections.Generic.IEnumerable{System.Net.IPEndPoint})">
|
||||
<summary>
|
||||
No-op implementation that does not persist server list
|
||||
</summary>
|
||||
<param name="endpoints">Server list</param>
|
||||
<returns>Completed task</returns>
|
||||
</member>
|
||||
<member name="T:SteamKit2.Discovery.ServerQuality">
|
||||
<summary>
|
||||
Currently marked quality of a server. All servers start off as Undetermined.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:SteamKit2.ServerQuality.Good">
|
||||
<member name="F:SteamKit2.Discovery.ServerQuality.Good">
|
||||
<summary>
|
||||
Known good server.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:SteamKit2.ServerQuality.Bad">
|
||||
<member name="F:SteamKit2.Discovery.ServerQuality.Bad">
|
||||
<summary>
|
||||
Known bad server.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:SteamKit2.SmartCMServerList">
|
||||
<member name="T:SteamKit2.Discovery.SmartCMServerList">
|
||||
<summary>
|
||||
Smart list of CM servers.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:SteamKit2.SmartCMServerList.BadConnectionMemoryTimeSpan">
|
||||
<member name="M:SteamKit2.Discovery.SmartCMServerList.#ctor(SteamKit2.Discovery.IServerListProvider,System.Boolean)">
|
||||
<summary>
|
||||
Initialize SmartCMServerList with a given server list provider
|
||||
</summary>
|
||||
<param name="provider">The ServerListProvider to persist servers</param>
|
||||
<param name="allowDirectoryFetch">Specifies if we can query SteamDirectory to discover more servers</param>
|
||||
</member>
|
||||
<member name="M:SteamKit2.Discovery.SmartCMServerList.#ctor">
|
||||
<summary>
|
||||
Initialize SmartCMServerList with the default <see cref="T:SteamKit2.Discovery.NullServerListProvider"/> server list provider
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:SteamKit2.Discovery.SmartCMServerList.ServerListProvider">
|
||||
<summary>
|
||||
The server list provider chosen to provide a persistent list of servers to connect to
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:SteamKit2.Discovery.SmartCMServerList.CellID">
|
||||
<summary>
|
||||
The preferred cell id for retrieving the list of servers from the Steam directory
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:SteamKit2.Discovery.SmartCMServerList.BadConnectionMemoryTimeSpan">
|
||||
<summary>
|
||||
Determines how long a server's bad connection state is remembered for.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:SteamKit2.SmartCMServerList.ResetOldScores">
|
||||
<member name="M:SteamKit2.Discovery.SmartCMServerList.ResetOldScores">
|
||||
<summary>
|
||||
Resets the scores of all servers which has a last bad connection more than <see cref="P:SteamKit2.SmartCMServerList.BadConnectionMemoryTimeSpan"/> ago.
|
||||
Resets the scores of all servers which has a last bad connection more than <see cref="P:SteamKit2.Discovery.SmartCMServerList.BadConnectionMemoryTimeSpan"/> ago.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:SteamKit2.SmartCMServerList.TryAdd(System.Net.IPEndPoint)">
|
||||
<member name="M:SteamKit2.Discovery.SmartCMServerList.ReplaceList(System.Collections.Generic.IEnumerable{System.Net.IPEndPoint})">
|
||||
<summary>
|
||||
Adds an <see cref="T:System.Net.IPEndPoint" /> to the server list.
|
||||
Replace the list with a new list of servers provided to us by the Steam servers.
|
||||
</summary>
|
||||
<param name="endPoint">The <see cref="T:System.Net.IPEndPoint"/> to add.</param>
|
||||
<returns>false if the server is already in the list, true otherwise.</returns>
|
||||
<param name="endpointList">The <see cref="T:System.Net.IPEndPoint"/>s to use for this <see cref="T:SteamKit2.Discovery.SmartCMServerList"/>.</param>
|
||||
</member>
|
||||
<member name="M:SteamKit2.SmartCMServerList.TryAddRange(System.Collections.Generic.IEnumerable{System.Net.IPEndPoint})">
|
||||
<summary>
|
||||
Adds the elements of the specified collection of <see cref="T:System.Net.IPEndPoint" />s to the server list.
|
||||
</summary>
|
||||
<param name="endPoints">The collection of <see cref="T:System.Net.IPEndPoint"/>s to add.</param>
|
||||
<returns>false if any of the specified servers are already in the list, true otherwise.</returns>
|
||||
</member>
|
||||
<member name="M:SteamKit2.SmartCMServerList.MergeWithList(System.Collections.Generic.IEnumerable{System.Net.IPEndPoint})">
|
||||
<summary>
|
||||
Merges the list with a new list of servers provided to us by the Steam servers.
|
||||
This adds the new list of <see cref="T:System.Net.IPEndPoint"/>s to the beginning of the list,
|
||||
ensuring that any pre-existing servers are moved into their new place in order near
|
||||
the beginning of the list.
|
||||
</summary>
|
||||
<param name="listToMerge">The <see cref="T:System.Net.IPEndPoint"/>s to merge into this <see cref="T:SteamKit2.SmartCMServerList"/>.</param>
|
||||
</member>
|
||||
<member name="M:SteamKit2.SmartCMServerList.ResetBadServers">
|
||||
<member name="M:SteamKit2.Discovery.SmartCMServerList.ResetBadServers">
|
||||
<summary>
|
||||
Explicitly resets the known state of all servers.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:SteamKit2.SmartCMServerList.Clear">
|
||||
<member name="M:SteamKit2.Discovery.SmartCMServerList.GetNextServerCandidateInternal">
|
||||
<summary>
|
||||
Removes all servers from the list.
|
||||
Perform the actual score lookup of the server list and return the candidate
|
||||
</summary>
|
||||
<returns>IPEndPoint candidate</returns>
|
||||
</member>
|
||||
<member name="M:SteamKit2.SmartCMServerList.GetNextServerCandidate">
|
||||
<member name="M:SteamKit2.Discovery.SmartCMServerList.GetNextServerCandidate">
|
||||
<summary>
|
||||
Get the next server in the list.
|
||||
</summary>
|
||||
<returns>An <see cref="T:System.Net.IPEndPoint"/>, or null if the list is empty.</returns>
|
||||
</member>
|
||||
<member name="M:SteamKit2.SmartCMServerList.GetAllEndPoints">
|
||||
<member name="M:SteamKit2.Discovery.SmartCMServerList.GetNextServerCandidateAsync">
|
||||
<summary>
|
||||
Get the next server in the list.
|
||||
</summary>
|
||||
<returns>An <see cref="T:System.Net.IPEndPoint"/>, or null if the list is empty.</returns>
|
||||
</member>
|
||||
<member name="M:SteamKit2.Discovery.SmartCMServerList.GetAllEndPoints">
|
||||
<summary>
|
||||
Gets the <see cref="T:System.Net.IPEndPoint"/>s of all servers in the server list.
|
||||
</summary>
|
||||
<returns>An <see cref="T:System.Net.IPEndPoint[]"/> array contains the <see cref="T:System.Net.IPEndPoint"/>s of the servers in the list</returns>
|
||||
</member>
|
||||
<member name="T:SteamKit2.Discovery.IsolatedStorageServerListProvider">
|
||||
<summary>
|
||||
A server list provider that uses IsolatedStorage to persist the server list
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:SteamKit2.Discovery.IsolatedStorageServerListProvider.#ctor">
|
||||
<summary>
|
||||
Initialize a new instance of IsolatedStorageServerListProvider using <see cref="M:System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForAssembly"/>
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:SteamKit2.Discovery.IsolatedStorageServerListProvider.FetchServerListAsync">
|
||||
<summary>
|
||||
Read the stored list of servers from IsolatedStore
|
||||
</summary>
|
||||
<returns>List of servers if persisted, otherwise an empty list</returns>
|
||||
</member>
|
||||
<member name="M:SteamKit2.Discovery.IsolatedStorageServerListProvider.UpdateServerListAsync(System.Collections.Generic.IEnumerable{System.Net.IPEndPoint})">
|
||||
<summary>
|
||||
Writes the supplied list of servers to persistent storage
|
||||
</summary>
|
||||
<param name="endpoints">List of server endpoints</param>
|
||||
<returns>Awaitable task for write completion</returns>
|
||||
</member>
|
||||
<member name="T:SteamKit2.Discovery.IServerListProvider">
|
||||
<summary>
|
||||
An interface for persisting the server list for connection discovery
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:SteamKit2.Discovery.IServerListProvider.FetchServerListAsync">
|
||||
<summary>
|
||||
Ask a provider to fetch any servers that it has available
|
||||
</summary>
|
||||
<returns>A list of IPEndPoints representing servers</returns>
|
||||
</member>
|
||||
<member name="M:SteamKit2.Discovery.IServerListProvider.UpdateServerListAsync(System.Collections.Generic.IEnumerable{System.Net.IPEndPoint})">
|
||||
<summary>
|
||||
Update the persistent list of endpoints
|
||||
</summary>
|
||||
<param name="endpoints">List of endpoints</param>
|
||||
</member>
|
||||
<member name="T:SteamKit2.CDNClient">
|
||||
<summary>
|
||||
The CDNClient class is used for downloading game content from the Steam servers.
|
||||
@@ -2788,6 +2881,14 @@
|
||||
<param name="gameId">The GameID to request the number of players for.</param>
|
||||
<returns>The Job ID of the request. This can be used to find the appropriate <see cref="T:SteamKit2.SteamUserStats.NumberOfPlayersCallback"/>.</returns>
|
||||
</member>
|
||||
<member name="M:SteamKit2.SteamUserStats.GetNumberOfCurrentPlayers(System.UInt32)">
|
||||
<summary>
|
||||
Retrieves the number of current players for a given app id.
|
||||
Results are returned in a <see cref="T:SteamKit2.SteamUserStats.NumberOfPlayersCallback"/>.
|
||||
</summary>
|
||||
<param name="appId">The app id to request the number of players for.</param>
|
||||
<returns>The Job ID of the request. This can be used to find the appropriate <see cref="T:SteamKit2.SteamUserStats.NumberOfPlayersCallback"/>.</returns>
|
||||
</member>
|
||||
<member name="M:SteamKit2.SteamUserStats.FindLeaderboard(System.UInt32,System.String)">
|
||||
<summary>
|
||||
Asks the Steam back-end for a leaderboard by name for a given appid.
|
||||
@@ -2831,7 +2932,7 @@
|
||||
</member>
|
||||
<member name="T:SteamKit2.SteamUserStats.NumberOfPlayersCallback">
|
||||
<summary>
|
||||
This callback is fired in response to <see cref="M:SteamKit2.SteamUserStats.GetNumberOfCurrentPlayers(SteamKit2.GameID)" />.
|
||||
This callback is fired in response to <see cref="M:SteamKit2.SteamUserStats.GetNumberOfCurrentPlayers(System.UInt32)" />.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:SteamKit2.SteamUserStats.NumberOfPlayersCallback.Result">
|
||||
@@ -3074,6 +3175,13 @@
|
||||
</summary>
|
||||
<param name="timeout">The length of time to block.</param>
|
||||
</member>
|
||||
<member name="M:SteamKit2.CallbackManager.RunWaitAllCallbacks(System.TimeSpan)">
|
||||
<summary>
|
||||
Blocks the current thread to run all queued callbacks.
|
||||
If no callback is queued, the method will block for the given timeout.
|
||||
</summary>
|
||||
<param name="timeout">The length of time to block.</param>
|
||||
</member>
|
||||
<member name="M:SteamKit2.CallbackManager.RunWaitCallbacks">
|
||||
<summary>
|
||||
Blocks the current thread to run a single queued callback.
|
||||
@@ -6322,8 +6430,8 @@
|
||||
<summary>
|
||||
Gets or sets the LoginID. This number is used for identifying logon session.
|
||||
The purpose of this field is to allow multiple sessions to the same steam account from the same machine.
|
||||
This is because Steam Network doesn't allow more than one session with the same LoginID to access given account at the same time.
|
||||
If you want to establish more than one active session to given account, you must make sure that every session (to that account) has unique LoginID.
|
||||
This is because Steam Network doesn't allow more than one session with the same LoginID to access given account at the same time from the same public IP.
|
||||
If you want to establish more than one active session to given account, you must make sure that every session (to that account) from the same public IP has a unique LoginID.
|
||||
By default LoginID is automatically generated based on machine's primary bind address, which is the same for all sessions.
|
||||
Null value will cause this property to be automatically generated based on default behaviour.
|
||||
If in doubt, set this property to null.
|
||||
@@ -6734,6 +6842,14 @@
|
||||
<param name="timeout">The length of time to block.</param>
|
||||
<returns>A callback object from the queue if a callback has been posted, or null if the timeout has elapsed.</returns>
|
||||
</member>
|
||||
<member name="M:SteamKit2.SteamClient.GetAllCallbacks(System.Boolean,System.TimeSpan)">
|
||||
<summary>
|
||||
Blocks the calling thread until the queue contains a callback object. Returns all callbacks, and optionally frees them.
|
||||
</summary>
|
||||
<param name="freeLast">if set to <c>true</c> this function also frees all callbacks.</param>
|
||||
<param name="timeout">The length of time to block.</param>
|
||||
<returns>All current callback objects in the queue.</returns>
|
||||
</member>
|
||||
<member name="M:SteamKit2.SteamClient.FreeLastCallback">
|
||||
<summary>
|
||||
Frees the last callback in the queue.
|
||||
@@ -7031,6 +7147,22 @@
|
||||
</summary>
|
||||
<returns>The value of this instance as a string.</returns>
|
||||
</member>
|
||||
<member name="M:SteamKit2.KeyValue.AsUnsignedByte(System.Byte)">
|
||||
<summary>
|
||||
Attempts to convert and return the value of this instance as an unsigned byte.
|
||||
If the conversion is invalid, the default value is returned.
|
||||
</summary>
|
||||
<param name="defaultValue">The default value to return if the conversion is invalid.</param>
|
||||
<returns>The value of this instance as an unsigned byte.</returns>
|
||||
</member>
|
||||
<member name="M:SteamKit2.KeyValue.AsUnsignedShort(System.UInt16)">
|
||||
<summary>
|
||||
Attempts to convert and return the value of this instance as an unsigned short.
|
||||
If the conversion is invalid, the default value is returned.
|
||||
</summary>
|
||||
<param name="defaultValue">The default value to return if the conversion is invalid.</param>
|
||||
<returns>The value of this instance as an unsigned short.</returns>
|
||||
</member>
|
||||
<member name="M:SteamKit2.KeyValue.AsInteger(System.Int32)">
|
||||
<summary>
|
||||
Attempts to convert and return the value of this instance as an integer.
|
||||
@@ -7039,6 +7171,14 @@
|
||||
<param name="defaultValue">The default value to return if the conversion is invalid.</param>
|
||||
<returns>The value of this instance as an integer.</returns>
|
||||
</member>
|
||||
<member name="M:SteamKit2.KeyValue.AsUnsignedInteger(System.UInt32)">
|
||||
<summary>
|
||||
Attempts to convert and return the value of this instance as an unsigned integer.
|
||||
If the conversion is invalid, the default value is returned.
|
||||
</summary>
|
||||
<param name="defaultValue">The default value to return if the conversion is invalid.</param>
|
||||
<returns>The value of this instance as an unsigned integer.</returns>
|
||||
</member>
|
||||
<member name="M:SteamKit2.KeyValue.AsLong(System.Int64)">
|
||||
<summary>
|
||||
Attempts to convert and return the value of this instance as a long.
|
||||
@@ -7325,11 +7465,11 @@
|
||||
<param name="protobuf">if set to <c>true</c>, the message is protobuf flagged.</param>
|
||||
<returns>A crafted EMsg, flagged if requested.</returns>
|
||||
</member>
|
||||
<member name="M:SteamKit2.TcpConnection.Connect(System.Net.IPEndPoint,System.Int32)">
|
||||
<member name="M:SteamKit2.TcpConnection.Connect(System.Threading.Tasks.Task{System.Net.IPEndPoint},System.Int32)">
|
||||
<summary>
|
||||
Connects to the specified end point.
|
||||
</summary>
|
||||
<param name="endPoint">The end point.</param>
|
||||
<param name="endPointTask">Task returning the end point.</param>
|
||||
<param name="timeout">Timeout in milliseconds</param>
|
||||
</member>
|
||||
<member name="M:SteamKit2.TcpConnection.NetLoop">
|
||||
@@ -7394,11 +7534,11 @@
|
||||
The highest sequence number we've processed.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:SteamKit2.UdpConnection.Connect(System.Net.IPEndPoint,System.Int32)">
|
||||
<member name="M:SteamKit2.UdpConnection.Connect(System.Threading.Tasks.Task{System.Net.IPEndPoint},System.Int32)">
|
||||
<summary>
|
||||
Connects to the specified CM server.
|
||||
</summary>
|
||||
<param name="endPoint">The CM server.</param>
|
||||
<param name="endPointTask">Task returning the CM server.</param>
|
||||
<param name="timeout">Timeout in milliseconds</param>
|
||||
</member>
|
||||
<member name="M:SteamKit2.UdpConnection.Disconnect">
|
||||
@@ -7460,7 +7600,7 @@
|
||||
</summary>
|
||||
<returns>True if a message was dispatched, false otherwise</returns>
|
||||
</member>
|
||||
<member name="M:SteamKit2.UdpConnection.NetLoop">
|
||||
<member name="M:SteamKit2.UdpConnection.NetLoop(System.Object)">
|
||||
<summary>
|
||||
Processes incoming packets, maintains connection consistency, and oversees outgoing packets.
|
||||
</summary>
|
||||
@@ -7528,11 +7668,11 @@
|
||||
Occurs when the physical connection is broken.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:SteamKit2.Connection.Connect(System.Net.IPEndPoint,System.Int32)">
|
||||
<member name="M:SteamKit2.Connection.Connect(System.Threading.Tasks.Task{System.Net.IPEndPoint},System.Int32)">
|
||||
<summary>
|
||||
Connects to the specified end point.
|
||||
</summary>
|
||||
<param name="endPoint">The end point.</param>
|
||||
<param name="endPointTask">Task returning the end point.</param>
|
||||
<param name="timeout">Timeout in milliseconds</param>
|
||||
</member>
|
||||
<member name="M:SteamKit2.Connection.Disconnect">
|
||||
@@ -1,3 +1,25 @@
|
||||
------------------------------------------------------------------------------
|
||||
v 1.8.0 Jul 8, 2016
|
||||
------------------------------------------------------------------------------
|
||||
* Added `CallbackManager.RunWaitAllCallbacks` (pr #292)
|
||||
* Added `KeyValue.AsUnsignedByte`. (pr #270)
|
||||
* Added `KeyValue.AsUnsignedInteger`. (pr #255)
|
||||
* Added `KeyValue.AsUnsignedShort`. (pr #270)
|
||||
* Added `SteamUserStats.GetNumberOfCurrentPlayers(GameID)`. (pr #234)
|
||||
* Added the ability to persist the server list to Isolated Storage. (pr #293)
|
||||
* Added the ability to persist the server list to a file. (pr #293)
|
||||
* Added support for fetching server list from the Steam Directory API. (pr #293)
|
||||
* Fixed a crash on Windows if WMI is unavailable.
|
||||
* Fixed a memory leak when reconnecting to Steam with the same `SteamClient` instance (pr #292)
|
||||
* Updated `SteamUserStats.GetNumberOfCurrentPlayers` to use messages that Steam continues to respond to. (pr #234)
|
||||
* Updated Steam enums and protobufs. (pr #271, pr #274, pr #296)
|
||||
* Updated game-related GC messages and protobufs.
|
||||
* Removed the hardcoded list of Steam server addresses. (pr #293)
|
||||
|
||||
BREAKING CHANGES
|
||||
* `SmartCMServerList` APIs have changed to accomodate new server management behaviour.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
v 1.7.0 Dec 21, 2015
|
||||
------------------------------------------------------------------------------
|
||||
@@ -13,7 +35,7 @@ v 1.7.0 Dec 21, 2015
|
||||
* Server List will now maintain ordering from Steam, increasing the chances of a successful and geographically local connection. (pr #218)
|
||||
* After calling `SteamUser.LogOff` or `SteamGameServer.LogOff`, `SteamClient.DisconnectedCallback.UserInitiated` will be `true`. (pr #205)
|
||||
* Fixed a crash when parsing a Steam ID of the format '[i:1:234]'.
|
||||
* Fixed a crash when logging on in an enviromnent where the hard disk has no serial ID, such as Hyper-V.
|
||||
* Fixed a crash when logging on in an environment where the hard disk has no serial ID, such as Hyper-V.
|
||||
* Fixed a bug when parsing a KeyValue file that contains a `/` followed by a newline. (pr #187)
|
||||
* Updated Steam enums and protobufs.
|
||||
* Updated game-related GC messages and protobufs.
|
||||
16
run.sh
16
run.sh
@@ -2,11 +2,12 @@
|
||||
set -eu
|
||||
|
||||
BUILD="Release"
|
||||
UNTIL_CLEAN_EXIT=0
|
||||
|
||||
MONO_ARGS=("--llvm" "--server" "-O=all")
|
||||
|
||||
PRINT_USAGE() {
|
||||
echo "Usage: $0 [debug/release]"
|
||||
echo "Usage: $0 [--until-clean-exit] [debug/release]"
|
||||
exit 1
|
||||
}
|
||||
|
||||
@@ -14,6 +15,7 @@ for ARG in "$@"; do
|
||||
case "$ARG" in
|
||||
release|Release) BUILD="Release" ;;
|
||||
debug|Debug) BUILD="Debug" ;;
|
||||
--until-clean-exit) UNTIL_CLEAN_EXIT=1 ;;
|
||||
*) PRINT_USAGE
|
||||
esac
|
||||
done
|
||||
@@ -31,4 +33,14 @@ if [[ ! -f "$BINARY" ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mono "${MONO_ARGS[@]}" "$BINARY"
|
||||
if [[ "$UNTIL_CLEAN_EXIT" -eq 0 ]]; then
|
||||
mono "${MONO_ARGS[@]}" "$BINARY"
|
||||
exit $?
|
||||
fi
|
||||
|
||||
while [[ -f "$BINARY" ]]; do
|
||||
if mono "${MONO_ARGS[@]}" "$BINARY"; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
Reference in New Issue
Block a user