mirror of
https://github.com/JustArchiNET/ArchiSteamFarm.git
synced 2025-12-18 23:40:30 +00:00
Gigantic code review (with ReSharper)
This commit is contained in:
BIN
ArchiSteamFarm/ASF-ConfigGenerator.exe
Normal file
BIN
ArchiSteamFarm/ASF-ConfigGenerator.exe
Normal file
Binary file not shown.
@@ -26,7 +26,9 @@ using SteamKit2;
|
||||
using SteamKit2.Internal;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -36,7 +38,7 @@ namespace ArchiSteamFarm {
|
||||
|
||||
internal ArchiHandler(Bot bot) {
|
||||
if (bot == null) {
|
||||
throw new ArgumentNullException("bot");
|
||||
throw new ArgumentNullException(nameof(bot));
|
||||
}
|
||||
|
||||
Bot = bot;
|
||||
@@ -53,6 +55,7 @@ namespace ArchiSteamFarm {
|
||||
|
||||
internal sealed class NotificationsCallback : CallbackMsg {
|
||||
internal enum ENotification : byte {
|
||||
[SuppressMessage("ReSharper", "UnusedMember.Global")]
|
||||
Unknown = 0,
|
||||
Trading = 1,
|
||||
// Only custom below, different than ones available as user_notification_type
|
||||
@@ -62,21 +65,21 @@ namespace ArchiSteamFarm {
|
||||
internal readonly HashSet<ENotification> Notifications;
|
||||
|
||||
internal NotificationsCallback(JobID jobID, CMsgClientUserNotifications msg) {
|
||||
if (jobID == null || msg == null) {
|
||||
throw new ArgumentNullException("jobID || msg");
|
||||
if ((jobID == null) || (msg == null)) {
|
||||
throw new ArgumentNullException(nameof(jobID) + " || " + nameof(msg));
|
||||
}
|
||||
|
||||
JobID = jobID;
|
||||
|
||||
Notifications = new HashSet<ENotification>();
|
||||
foreach (var notification in msg.notifications) {
|
||||
foreach (CMsgClientUserNotifications.Notification notification in msg.notifications) {
|
||||
Notifications.Add((ENotification) notification.user_notification_type);
|
||||
}
|
||||
}
|
||||
|
||||
internal NotificationsCallback(JobID jobID, CMsgClientItemAnnouncements msg) {
|
||||
if (jobID == null || msg == null) {
|
||||
throw new ArgumentNullException("jobID || msg");
|
||||
if ((jobID == null) || (msg == null)) {
|
||||
throw new ArgumentNullException(nameof(jobID) + " || " + nameof(msg));
|
||||
}
|
||||
|
||||
JobID = jobID;
|
||||
@@ -93,8 +96,8 @@ namespace ArchiSteamFarm {
|
||||
internal readonly uint OfflineMessagesCount;
|
||||
|
||||
internal OfflineMessageCallback(JobID jobID, CMsgClientOfflineMessageNotification msg) {
|
||||
if (jobID == null || msg == null) {
|
||||
throw new ArgumentNullException("jobID || msg");
|
||||
if ((jobID == null) || (msg == null)) {
|
||||
throw new ArgumentNullException(nameof(jobID) + " || " + nameof(msg));
|
||||
}
|
||||
|
||||
JobID = jobID;
|
||||
@@ -104,6 +107,7 @@ namespace ArchiSteamFarm {
|
||||
|
||||
internal sealed class PurchaseResponseCallback : CallbackMsg {
|
||||
internal enum EPurchaseResult : sbyte {
|
||||
[SuppressMessage("ReSharper", "UnusedMember.Global")]
|
||||
Unknown = -1,
|
||||
OK = 0,
|
||||
AlreadyOwned = 9,
|
||||
@@ -114,31 +118,28 @@ namespace ArchiSteamFarm {
|
||||
OnCooldown = 53
|
||||
}
|
||||
|
||||
internal readonly EResult Result;
|
||||
internal readonly EPurchaseResult PurchaseResult;
|
||||
internal readonly KeyValue ReceiptInfo;
|
||||
internal readonly Dictionary<uint, string> Items;
|
||||
|
||||
internal PurchaseResponseCallback(JobID jobID, CMsgClientPurchaseResponse msg) {
|
||||
if (jobID == null || msg == null) {
|
||||
throw new ArgumentNullException("jobID || msg");
|
||||
if ((jobID == null) || (msg == null)) {
|
||||
throw new ArgumentNullException(nameof(jobID) + " || " + nameof(msg));
|
||||
}
|
||||
|
||||
JobID = jobID;
|
||||
Result = (EResult) msg.eresult;
|
||||
PurchaseResult = (EPurchaseResult) msg.purchase_result_details;
|
||||
|
||||
if (msg.purchase_receipt_info == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ReceiptInfo = new KeyValue();
|
||||
KeyValue receiptInfo = new KeyValue();
|
||||
using (MemoryStream ms = new MemoryStream(msg.purchase_receipt_info)) {
|
||||
if (!ReceiptInfo.TryReadAsBinary(ms)) {
|
||||
if (!receiptInfo.TryReadAsBinary(ms)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var lineItems = ReceiptInfo["lineitems"].Children;
|
||||
List<KeyValue> lineItems = receiptInfo["lineitems"].Children;
|
||||
Items = new Dictionary<uint, string>(lineItems.Count);
|
||||
|
||||
foreach (KeyValue lineItem in lineItems) {
|
||||
@@ -165,11 +166,11 @@ namespace ArchiSteamFarm {
|
||||
return;
|
||||
}
|
||||
|
||||
var request = new ClientMsgProtobuf<CMsgClientGamesPlayed>(EMsg.ClientGamesPlayed);
|
||||
ClientMsgProtobuf<CMsgClientGamesPlayed> request = new ClientMsgProtobuf<CMsgClientGamesPlayed>(EMsg.ClientGamesPlayed);
|
||||
if (!string.IsNullOrEmpty(gameName)) {
|
||||
request.Body.games_played.Add(new CMsgClientGamesPlayed.GamePlayed {
|
||||
game_extra_info = gameName,
|
||||
game_id = new GameID() {
|
||||
game_id = new GameID {
|
||||
AppType = GameID.GameType.Shortcut,
|
||||
ModID = uint.MaxValue
|
||||
}
|
||||
@@ -188,18 +189,14 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
internal void PlayGames(HashSet<uint> gameIDs) {
|
||||
if (gameIDs == null || !Client.IsConnected) {
|
||||
if ((gameIDs == null) || !Client.IsConnected) {
|
||||
return;
|
||||
}
|
||||
|
||||
var request = new ClientMsgProtobuf<CMsgClientGamesPlayed>(EMsg.ClientGamesPlayed);
|
||||
foreach (uint gameID in gameIDs) {
|
||||
if (gameID == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ClientMsgProtobuf<CMsgClientGamesPlayed> request = new ClientMsgProtobuf<CMsgClientGamesPlayed>(EMsg.ClientGamesPlayed);
|
||||
foreach (uint gameID in gameIDs.Where(gameID => gameID != 0)) {
|
||||
request.Body.games_played.Add(new CMsgClientGamesPlayed.GamePlayed {
|
||||
game_id = new GameID(gameID),
|
||||
game_id = new GameID(gameID)
|
||||
});
|
||||
}
|
||||
|
||||
@@ -211,7 +208,7 @@ namespace ArchiSteamFarm {
|
||||
return null;
|
||||
}
|
||||
|
||||
var request = new ClientMsgProtobuf<CMsgClientRegisterKey>(EMsg.ClientRegisterKey) {
|
||||
ClientMsgProtobuf<CMsgClientRegisterKey> request = new ClientMsgProtobuf<CMsgClientRegisterKey>(EMsg.ClientRegisterKey) {
|
||||
SourceJobID = Client.GetNextJobID()
|
||||
};
|
||||
|
||||
@@ -235,8 +232,11 @@ namespace ArchiSteamFarm {
|
||||
|
||||
SteamID steamID = new SteamID(details.AccountID, details.AccountInstance, Client.ConnectedUniverse, EAccountType.Individual);
|
||||
|
||||
var logon = new ClientMsgProtobuf<CMsgClientLogon>(EMsg.ClientLogon);
|
||||
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;
|
||||
@@ -292,7 +292,7 @@ namespace ArchiSteamFarm {
|
||||
return;
|
||||
}
|
||||
|
||||
var response = new ClientMsgProtobuf<CMsgClientOfflineMessageNotification>(packetMsg);
|
||||
ClientMsgProtobuf<CMsgClientOfflineMessageNotification> response = new ClientMsgProtobuf<CMsgClientOfflineMessageNotification>(packetMsg);
|
||||
Client.PostCallback(new OfflineMessageCallback(packetMsg.TargetJobID, response.Body));
|
||||
}
|
||||
|
||||
@@ -301,7 +301,7 @@ namespace ArchiSteamFarm {
|
||||
return;
|
||||
}
|
||||
|
||||
var response = new ClientMsgProtobuf<CMsgClientItemAnnouncements>(packetMsg);
|
||||
ClientMsgProtobuf<CMsgClientItemAnnouncements> response = new ClientMsgProtobuf<CMsgClientItemAnnouncements>(packetMsg);
|
||||
Client.PostCallback(new NotificationsCallback(packetMsg.TargetJobID, response.Body));
|
||||
}
|
||||
|
||||
@@ -310,7 +310,7 @@ namespace ArchiSteamFarm {
|
||||
return;
|
||||
}
|
||||
|
||||
var response = new ClientMsgProtobuf<CMsgClientPurchaseResponse>(packetMsg);
|
||||
ClientMsgProtobuf<CMsgClientPurchaseResponse> response = new ClientMsgProtobuf<CMsgClientPurchaseResponse>(packetMsg);
|
||||
Client.PostCallback(new PurchaseResponseCallback(packetMsg.TargetJobID, response.Body));
|
||||
}
|
||||
|
||||
@@ -319,7 +319,7 @@ namespace ArchiSteamFarm {
|
||||
return;
|
||||
}
|
||||
|
||||
var response = new ClientMsgProtobuf<CMsgClientUserNotifications>(packetMsg);
|
||||
ClientMsgProtobuf<CMsgClientUserNotifications> response = new ClientMsgProtobuf<CMsgClientUserNotifications>(packetMsg);
|
||||
Client.PostCallback(new NotificationsCallback(packetMsg.TargetJobID, response.Body));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
using System.Threading;
|
||||
using ArchiSteamFarm.JSON;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
internal sealed class ArchiWebHandler {
|
||||
@@ -63,11 +64,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
uint appID;
|
||||
if (!uint.TryParse(hashName.Substring(0, index), out appID)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return appID;
|
||||
return !uint.TryParse(hashName.Substring(0, index), out appID) ? 0 : appID;
|
||||
}
|
||||
|
||||
private static Steam.Item.EType GetItemType(string name) {
|
||||
@@ -87,21 +84,23 @@ namespace ArchiSteamFarm {
|
||||
default:
|
||||
if (name.EndsWith("Emoticon", StringComparison.Ordinal)) {
|
||||
return Steam.Item.EType.Emoticon;
|
||||
} else if (name.EndsWith("Foil Trading Card", StringComparison.Ordinal)) {
|
||||
return Steam.Item.EType.FoilTradingCard;
|
||||
} else if (name.EndsWith("Profile Background", StringComparison.Ordinal)) {
|
||||
return Steam.Item.EType.ProfileBackground;
|
||||
} else if (name.EndsWith("Trading Card", StringComparison.Ordinal)) {
|
||||
return Steam.Item.EType.TradingCard;
|
||||
} else {
|
||||
return Steam.Item.EType.Unknown;
|
||||
}
|
||||
|
||||
if (name.EndsWith("Foil Trading Card", StringComparison.Ordinal)) {
|
||||
return Steam.Item.EType.FoilTradingCard;
|
||||
}
|
||||
|
||||
if (name.EndsWith("Profile Background", StringComparison.Ordinal)) {
|
||||
return Steam.Item.EType.ProfileBackground;
|
||||
}
|
||||
|
||||
return name.EndsWith("Trading Card", StringComparison.Ordinal) ? Steam.Item.EType.TradingCard : Steam.Item.EType.Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
internal ArchiWebHandler(Bot bot) {
|
||||
if (bot == null) {
|
||||
throw new ArgumentNullException("bot");
|
||||
throw new ArgumentNullException(nameof(bot));
|
||||
}
|
||||
|
||||
Bot = bot;
|
||||
@@ -110,11 +109,14 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
internal bool Init(SteamClient steamClient, string webAPIUserNonce, string parentalPin) {
|
||||
if (steamClient == null || steamClient.SteamID == null || string.IsNullOrEmpty(webAPIUserNonce)) {
|
||||
if ((steamClient == null) || string.IsNullOrEmpty(webAPIUserNonce)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ulong steamID = steamClient.SteamID;
|
||||
if (steamID == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
string sessionID = Convert.ToBase64String(Encoding.UTF8.GetBytes(steamID.ToString()));
|
||||
|
||||
@@ -198,16 +200,16 @@ namespace ArchiSteamFarm {
|
||||
};
|
||||
|
||||
bool result = false;
|
||||
for (byte i = 0; i < WebBrowser.MaxRetries && !result; i++) {
|
||||
for (byte i = 0; (i < WebBrowser.MaxRetries) && !result; i++) {
|
||||
result = await WebBrowser.UrlPost(request, data).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
Logging.LogGenericWTF("Request failed even after " + WebBrowser.MaxRetries + " tries", Bot.BotName);
|
||||
return false;
|
||||
if (result) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
Logging.LogGenericWTF("Request failed even after " + WebBrowser.MaxRetries + " tries", Bot.BotName);
|
||||
return false;
|
||||
}
|
||||
|
||||
internal async Task<bool> JoinGroup(ulong groupID) {
|
||||
@@ -232,16 +234,16 @@ namespace ArchiSteamFarm {
|
||||
};
|
||||
|
||||
bool result = false;
|
||||
for (byte i = 0; i < WebBrowser.MaxRetries && !result; i++) {
|
||||
for (byte i = 0; (i < WebBrowser.MaxRetries) && !result; i++) {
|
||||
result = await WebBrowser.UrlPost(request, data).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
Logging.LogGenericWTF("Request failed even after " + WebBrowser.MaxRetries + " tries", Bot.BotName);
|
||||
return false;
|
||||
if (result) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
Logging.LogGenericWTF("Request failed even after " + WebBrowser.MaxRetries + " tries", Bot.BotName);
|
||||
return false;
|
||||
}
|
||||
|
||||
internal async Task<Dictionary<uint, string>> GetOwnedGames() {
|
||||
@@ -252,7 +254,7 @@ namespace ArchiSteamFarm {
|
||||
string request = SteamCommunityURL + "/my/games/?xml=1";
|
||||
|
||||
XmlDocument response = null;
|
||||
for (byte i = 0; i < WebBrowser.MaxRetries && response == null; i++) {
|
||||
for (byte i = 0; (i < WebBrowser.MaxRetries) && (response == null); i++) {
|
||||
response = await WebBrowser.UrlGetToXML(request).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@@ -262,7 +264,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
XmlNodeList xmlNodeList = response.SelectNodes("gamesList/games/game");
|
||||
if (xmlNodeList == null || xmlNodeList.Count == 0) {
|
||||
if ((xmlNodeList == null) || (xmlNodeList.Count == 0)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -290,7 +292,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
internal Dictionary<uint, string> GetOwnedGames(ulong steamID) {
|
||||
if (steamID == 0 || string.IsNullOrEmpty(Bot.BotConfig.SteamApiKey)) {
|
||||
if ((steamID == 0) || string.IsNullOrEmpty(Bot.BotConfig.SteamApiKey)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -298,7 +300,7 @@ namespace ArchiSteamFarm {
|
||||
using (dynamic iPlayerService = WebAPI.GetInterface("IPlayerService", Bot.BotConfig.SteamApiKey)) {
|
||||
iPlayerService.Timeout = Timeout;
|
||||
|
||||
for (byte i = 0; i < WebBrowser.MaxRetries && response == null; i++) {
|
||||
for (byte i = 0; (i < WebBrowser.MaxRetries) && (response == null); i++) {
|
||||
try {
|
||||
response = iPlayerService.GetOwnedGames(
|
||||
steamid: steamID,
|
||||
@@ -338,7 +340,7 @@ namespace ArchiSteamFarm {
|
||||
using (dynamic iEconService = WebAPI.GetInterface("IEconService", Bot.BotConfig.SteamApiKey)) {
|
||||
iEconService.Timeout = Timeout;
|
||||
|
||||
for (byte i = 0; i < WebBrowser.MaxRetries && response == null; i++) {
|
||||
for (byte i = 0; (i < WebBrowser.MaxRetries) && (response == null); i++) {
|
||||
try {
|
||||
response = iEconService.GetTradeOffers(
|
||||
get_received_offers: 1,
|
||||
@@ -389,7 +391,6 @@ namespace ArchiSteamFarm {
|
||||
|
||||
HashSet<Steam.TradeOffer> result = new HashSet<Steam.TradeOffer>();
|
||||
foreach (KeyValue trade in response["trade_offers_received"].Children) {
|
||||
// TODO: Correct some of these when SK2 with https://github.com/SteamRE/SteamKit/pull/255 gets released
|
||||
Steam.TradeOffer tradeOffer = new Steam.TradeOffer {
|
||||
TradeOfferID = trade["tradeofferid"].AsUnsignedLong(),
|
||||
OtherSteamID3 = (uint) trade["accountid_other"].AsUnsignedLong(),
|
||||
@@ -468,16 +469,16 @@ namespace ArchiSteamFarm {
|
||||
};
|
||||
|
||||
bool result = false;
|
||||
for (byte i = 0; i < WebBrowser.MaxRetries && !result; i++) {
|
||||
for (byte i = 0; (i < WebBrowser.MaxRetries) && !result; i++) {
|
||||
result = await WebBrowser.UrlPost(request, data, referer).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
Logging.LogGenericWTF("Request failed even after " + WebBrowser.MaxRetries + " tries", Bot.BotName);
|
||||
return false;
|
||||
if (result) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
Logging.LogGenericWTF("Request failed even after " + WebBrowser.MaxRetries + " tries", Bot.BotName);
|
||||
return false;
|
||||
}
|
||||
|
||||
internal async Task<HashSet<Steam.Item>> GetMyTradableInventory() {
|
||||
@@ -492,7 +493,7 @@ namespace ArchiSteamFarm {
|
||||
string request = SteamCommunityURL + "/my/inventory/json/" + Steam.Item.SteamAppID + "/" + Steam.Item.SteamContextID + "?trading=1&start=" + nextPage;
|
||||
|
||||
JObject jObject = null;
|
||||
for (byte i = 0; i < WebBrowser.MaxRetries && jObject == null; i++) {
|
||||
for (byte i = 0; (i < WebBrowser.MaxRetries) && (jObject == null); i++) {
|
||||
jObject = await WebBrowser.UrlGetToJObject(request).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@@ -514,7 +515,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
ulong classID;
|
||||
if (!ulong.TryParse(classIDString, out classID) || classID == 0) {
|
||||
if (!ulong.TryParse(classIDString, out classID) || (classID == 0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -550,7 +551,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
IEnumerable<JToken> items = jObject.SelectTokens("$.rgInventory.*");
|
||||
if (descriptions == null) {
|
||||
if (items == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -594,7 +595,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
internal async Task<bool> SendTradeOffer(HashSet<Steam.Item> inventory, ulong partnerID, string token = null) {
|
||||
if (inventory == null || inventory.Count == 0 || partnerID == 0) {
|
||||
if ((inventory == null) || (inventory.Count == 0) || (partnerID == 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -608,13 +609,12 @@ namespace ArchiSteamFarm {
|
||||
return false;
|
||||
}
|
||||
|
||||
HashSet<Steam.TradeOfferRequest> trades = new HashSet<Steam.TradeOfferRequest>();
|
||||
|
||||
Steam.TradeOfferRequest singleTrade = null;
|
||||
Steam.TradeOfferRequest singleTrade = new Steam.TradeOfferRequest();
|
||||
HashSet<Steam.TradeOfferRequest> trades = new HashSet<Steam.TradeOfferRequest> { singleTrade };
|
||||
|
||||
byte itemID = 0;
|
||||
foreach (Steam.Item item in inventory) {
|
||||
if (itemID % Trading.MaxItemsPerTrade == 0) {
|
||||
if (itemID >= Trading.MaxItemsPerTrade) {
|
||||
if (trades.Count >= Trading.MaxTradesPerAccount) {
|
||||
break;
|
||||
}
|
||||
@@ -624,7 +624,7 @@ namespace ArchiSteamFarm {
|
||||
itemID = 0;
|
||||
}
|
||||
|
||||
singleTrade.ItemsToGive.Assets.Add(new Steam.Item() {
|
||||
singleTrade.ItemsToGive.Assets.Add(new Steam.Item {
|
||||
AppID = Steam.Item.SteamAppID,
|
||||
ContextID = Steam.Item.SteamContextID,
|
||||
Amount = item.Amount,
|
||||
@@ -647,15 +647,17 @@ namespace ArchiSteamFarm {
|
||||
};
|
||||
|
||||
bool result = false;
|
||||
for (byte i = 0; i < WebBrowser.MaxRetries && !result; i++) {
|
||||
for (byte i = 0; (i < WebBrowser.MaxRetries) && !result; i++) {
|
||||
result = await WebBrowser.UrlPost(request, data, referer).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
if (result) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Logging.LogGenericWTF("Request failed even after " + WebBrowser.MaxRetries + " tries", Bot.BotName);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -672,16 +674,16 @@ namespace ArchiSteamFarm {
|
||||
string request = SteamCommunityURL + "/my/badges?p=" + page;
|
||||
|
||||
HtmlDocument htmlDocument = null;
|
||||
for (byte i = 0; i < WebBrowser.MaxRetries && htmlDocument == null; i++) {
|
||||
for (byte i = 0; (i < WebBrowser.MaxRetries) && (htmlDocument == null); i++) {
|
||||
htmlDocument = await WebBrowser.UrlGetToHtmlDocument(request).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (htmlDocument == null) {
|
||||
Logging.LogGenericWTF("Request failed even after " + WebBrowser.MaxRetries + " tries", Bot.BotName);
|
||||
return null;
|
||||
if (htmlDocument != null) {
|
||||
return htmlDocument;
|
||||
}
|
||||
|
||||
return htmlDocument;
|
||||
Logging.LogGenericWTF("Request failed even after " + WebBrowser.MaxRetries + " tries", Bot.BotName);
|
||||
return null;
|
||||
}
|
||||
|
||||
internal async Task<HtmlDocument> GetGameCardsPage(ulong appID) {
|
||||
@@ -696,16 +698,16 @@ namespace ArchiSteamFarm {
|
||||
string request = SteamCommunityURL + "/my/gamecards/" + appID;
|
||||
|
||||
HtmlDocument htmlDocument = null;
|
||||
for (byte i = 0; i < WebBrowser.MaxRetries && htmlDocument == null; i++) {
|
||||
for (byte i = 0; (i < WebBrowser.MaxRetries) && (htmlDocument == null); i++) {
|
||||
htmlDocument = await WebBrowser.UrlGetToHtmlDocument(request).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (htmlDocument == null) {
|
||||
Logging.LogGenericWTF("Request failed even after " + WebBrowser.MaxRetries + " tries", Bot.BotName);
|
||||
return null;
|
||||
if (htmlDocument != null) {
|
||||
return htmlDocument;
|
||||
}
|
||||
|
||||
return htmlDocument;
|
||||
Logging.LogGenericWTF("Request failed even after " + WebBrowser.MaxRetries + " tries", Bot.BotName);
|
||||
return null;
|
||||
}
|
||||
|
||||
internal async Task<bool> MarkInventory() {
|
||||
@@ -716,32 +718,32 @@ namespace ArchiSteamFarm {
|
||||
string request = SteamCommunityURL + "/my/inventory";
|
||||
|
||||
bool result = false;
|
||||
for (byte i = 0; i < WebBrowser.MaxRetries && !result; i++) {
|
||||
for (byte i = 0; (i < WebBrowser.MaxRetries) && !result; i++) {
|
||||
result = await WebBrowser.UrlHead(request).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
Logging.LogGenericWTF("Request failed even after " + WebBrowser.MaxRetries + " tries", Bot.BotName);
|
||||
return false;
|
||||
if (result) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
Logging.LogGenericWTF("Request failed even after " + WebBrowser.MaxRetries + " tries", Bot.BotName);
|
||||
return false;
|
||||
}
|
||||
|
||||
private async Task<bool?> IsLoggedIn() {
|
||||
string request = SteamCommunityURL + "/my/profile";
|
||||
|
||||
Uri uri = null;
|
||||
for (byte i = 0; i < WebBrowser.MaxRetries && uri == null; i++) {
|
||||
for (byte i = 0; (i < WebBrowser.MaxRetries) && (uri == null); i++) {
|
||||
uri = await WebBrowser.UrlHeadToUri(request).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (uri == null) {
|
||||
Logging.LogGenericWTF("Request failed even after " + WebBrowser.MaxRetries + " tries", Bot.BotName);
|
||||
return null;
|
||||
if (uri != null) {
|
||||
return !uri.AbsolutePath.StartsWith("/login", StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
return !uri.AbsolutePath.StartsWith("/login", StringComparison.Ordinal);
|
||||
Logging.LogGenericWTF("Request failed even after " + WebBrowser.MaxRetries + " tries", Bot.BotName);
|
||||
return null;
|
||||
}
|
||||
|
||||
private async Task<bool> RefreshSessionIfNeeded() {
|
||||
@@ -784,7 +786,7 @@ namespace ArchiSteamFarm {
|
||||
};
|
||||
|
||||
bool result = false;
|
||||
for (byte i = 0; i < WebBrowser.MaxRetries && !result; i++) {
|
||||
for (byte i = 0; (i < WebBrowser.MaxRetries) && !result; i++) {
|
||||
result = await WebBrowser.UrlPost(request, data, SteamCommunityURL).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -28,6 +28,8 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
// ReSharper disable once ClassCannotBeInstantiated
|
||||
// ReSharper disable once ClassNeverInstantiated.Global
|
||||
internal sealed class BotConfig {
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal bool Enabled { get; private set; } = false;
|
||||
@@ -36,10 +38,10 @@ namespace ArchiSteamFarm {
|
||||
internal bool StartOnLaunch { get; private set; } = true;
|
||||
|
||||
[JsonProperty]
|
||||
internal string SteamLogin { get; set; } = null;
|
||||
internal string SteamLogin { get; set; }
|
||||
|
||||
[JsonProperty]
|
||||
internal string SteamPassword { get; set; } = null;
|
||||
internal string SteamPassword { get; set; }
|
||||
|
||||
[JsonProperty]
|
||||
internal string SteamParentalPIN { get; set; } = "0";
|
||||
@@ -99,7 +101,7 @@ namespace ArchiSteamFarm {
|
||||
internal string CustomGamePlayedWhileIdle { get; private set; } = null;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal HashSet<uint> GamesPlayedWhileIdle { get; private set; } = new HashSet<uint>() { 0 };
|
||||
internal HashSet<uint> GamesPlayedWhileIdle { get; private set; } = new HashSet<uint> { 0 };
|
||||
|
||||
|
||||
internal static BotConfig Load(string filePath) {
|
||||
|
||||
@@ -93,7 +93,7 @@ namespace ArchiSteamFarm {
|
||||
// This constructor is used when creating new database
|
||||
private BotDatabase(string filePath) {
|
||||
if (string.IsNullOrEmpty(filePath)) {
|
||||
throw new ArgumentNullException("filePath");
|
||||
throw new ArgumentNullException(nameof(filePath));
|
||||
}
|
||||
|
||||
FilePath = filePath;
|
||||
@@ -101,6 +101,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
// This constructor is used only by deserializer
|
||||
// ReSharper disable once UnusedMember.Local
|
||||
private BotDatabase() { }
|
||||
|
||||
internal void Save() {
|
||||
|
||||
@@ -48,12 +48,12 @@ namespace ArchiSteamFarm {
|
||||
|
||||
internal CardsFarmer(Bot bot) {
|
||||
if (bot == null) {
|
||||
throw new ArgumentNullException("bot");
|
||||
throw new ArgumentNullException(nameof(bot));
|
||||
}
|
||||
|
||||
Bot = bot;
|
||||
|
||||
if (Timer == null && Program.GlobalConfig.IdleFarmingPeriod > 0) {
|
||||
if ((Timer == null) && (Program.GlobalConfig.IdleFarmingPeriod > 0)) {
|
||||
Timer = new Timer(
|
||||
async e => await CheckGamesForFarming().ConfigureAwait(false),
|
||||
null,
|
||||
@@ -132,12 +132,14 @@ namespace ArchiSteamFarm {
|
||||
Logging.LogGenericInfo("Chosen farming algorithm: Simple", Bot.BotName);
|
||||
while (GamesToFarm.Count > 0) {
|
||||
uint appID = GamesToFarm.Keys.FirstOrDefault();
|
||||
if (!await FarmSolo(appID).ConfigureAwait(false)) {
|
||||
if (await FarmSolo(appID).ConfigureAwait(false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
NowFarming = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (await IsAnythingToFarm().ConfigureAwait(false));
|
||||
|
||||
CurrentGamesFarming.Clear();
|
||||
@@ -164,7 +166,7 @@ namespace ArchiSteamFarm {
|
||||
FarmResetEvent.Set();
|
||||
|
||||
Logging.LogGenericInfo("Waiting for reaction...", Bot.BotName);
|
||||
for (byte i = 0; i < Program.GlobalConfig.HttpTimeout && NowFarming; i++) {
|
||||
for (byte i = 0; (i < Program.GlobalConfig.HttpTimeout) && NowFarming; i++) {
|
||||
await Utilities.SleepAsync(1000).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@@ -188,11 +190,9 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
HashSet<uint> result = new HashSet<uint>();
|
||||
foreach (KeyValuePair<uint, float> keyValue in gamesToFarm) {
|
||||
if (keyValue.Value >= 2) {
|
||||
foreach (KeyValuePair<uint, float> keyValue in gamesToFarm.Where(keyValue => keyValue.Value >= 2)) {
|
||||
result.Add(keyValue.Key);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -210,7 +210,7 @@ namespace ArchiSteamFarm {
|
||||
|
||||
byte maxPages = 1;
|
||||
HtmlNodeCollection htmlNodeCollection = htmlDocument.DocumentNode.SelectNodes("//a[@class='pagelink']");
|
||||
if (htmlNodeCollection != null && htmlNodeCollection.Count > 0) {
|
||||
if ((htmlNodeCollection != null) && (htmlNodeCollection.Count > 0)) {
|
||||
HtmlNode htmlNode = htmlNodeCollection[htmlNodeCollection.Count - 1];
|
||||
string lastPage = htmlNode.InnerText;
|
||||
if (!string.IsNullOrEmpty(lastPage)) {
|
||||
@@ -224,16 +224,19 @@ namespace ArchiSteamFarm {
|
||||
|
||||
CheckPage(htmlDocument);
|
||||
|
||||
if (maxPages > 1) {
|
||||
if (maxPages <= 1) {
|
||||
return GamesToFarm.Count > 0;
|
||||
}
|
||||
|
||||
Logging.LogGenericInfo("Checking other pages...", Bot.BotName);
|
||||
|
||||
List<Task> tasks = new List<Task>(maxPages - 1);
|
||||
for (byte page = 2; page <= maxPages; page++) {
|
||||
byte currentPage = page; // We need a copy of variable being passed when in for loops, as loop will proceed before task is launched
|
||||
tasks.Add(CheckPage(currentPage));
|
||||
}
|
||||
await Task.WhenAll(tasks).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
await Task.WhenAll(tasks).ConfigureAwait(false);
|
||||
return GamesToFarm.Count > 0;
|
||||
}
|
||||
|
||||
@@ -370,15 +373,11 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
Logging.LogGenericInfo("Now farming: " + string.Join(", ", CurrentGamesFarming), Bot.BotName);
|
||||
if (FarmHours(maxHour, CurrentGamesFarming)) {
|
||||
|
||||
bool result = FarmHours(maxHour, CurrentGamesFarming);
|
||||
CurrentGamesFarming.Clear();
|
||||
CurrentGamesFarming.TrimExcess();
|
||||
return true;
|
||||
} else {
|
||||
CurrentGamesFarming.Clear();
|
||||
CurrentGamesFarming.TrimExcess();
|
||||
return false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private async Task<bool> FarmSolo(uint appID) {
|
||||
@@ -389,20 +388,23 @@ namespace ArchiSteamFarm {
|
||||
CurrentGamesFarming.Add(appID);
|
||||
|
||||
Logging.LogGenericInfo("Now farming: " + appID, Bot.BotName);
|
||||
if (await Farm(appID).ConfigureAwait(false)) {
|
||||
CurrentGamesFarming.Clear();
|
||||
CurrentGamesFarming.TrimExcess();
|
||||
float hours;
|
||||
if (GamesToFarm.TryRemove(appID, out hours)) {
|
||||
TimeSpan timeSpan = TimeSpan.FromHours(hours);
|
||||
Logging.LogGenericInfo("Done farming: " + appID + " after " + timeSpan.ToString(@"hh\:mm") + " hours of playtime!", Bot.BotName);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
|
||||
bool result = await Farm(appID).ConfigureAwait(false);
|
||||
CurrentGamesFarming.Clear();
|
||||
CurrentGamesFarming.TrimExcess();
|
||||
|
||||
if (!result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
float hours;
|
||||
if (!GamesToFarm.TryRemove(appID, out hours)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TimeSpan timeSpan = TimeSpan.FromHours(hours);
|
||||
Logging.LogGenericInfo("Done farming: " + appID + " after " + timeSpan.ToString(@"hh\:mm") + " hours of playtime!", Bot.BotName);
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task<bool> Farm(uint appID) {
|
||||
@@ -415,7 +417,7 @@ namespace ArchiSteamFarm {
|
||||
bool success = true;
|
||||
|
||||
bool? keepFarming = await ShouldFarm(appID).ConfigureAwait(false);
|
||||
for (ushort farmingTime = 0; farmingTime <= 60 * Program.GlobalConfig.MaxFarmingTime && keepFarming.GetValueOrDefault(true); farmingTime += Program.GlobalConfig.FarmingDelay) {
|
||||
for (ushort farmingTime = 0; (farmingTime <= 60 * Program.GlobalConfig.MaxFarmingTime) && keepFarming.GetValueOrDefault(true); farmingTime += Program.GlobalConfig.FarmingDelay) {
|
||||
if (FarmResetEvent.Wait(60 * 1000 * Program.GlobalConfig.FarmingDelay)) {
|
||||
success = false;
|
||||
break;
|
||||
@@ -435,7 +437,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
private bool FarmHours(float maxHour, HashSet<uint> appIDs) {
|
||||
if (maxHour < 0 || appIDs == null || appIDs.Count == 0) {
|
||||
if ((maxHour < 0) || (appIDs == null) || (appIDs.Count == 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,14 +29,14 @@ using System.IO;
|
||||
namespace ArchiSteamFarm {
|
||||
internal static class Debugging {
|
||||
#if DEBUG
|
||||
// ReSharper disable once ConvertToConstant.Global
|
||||
internal static readonly bool IsDebugBuild = true;
|
||||
#else
|
||||
// ReSharper disable once ConvertToConstant.Global
|
||||
internal static readonly bool IsDebugBuild = false;
|
||||
#endif
|
||||
|
||||
internal static bool IsReleaseBuild => !IsDebugBuild;
|
||||
|
||||
internal static bool NetHookAlreadyInitialized { get; set; } = false;
|
||||
internal static bool NetHookAlreadyInitialized { get; set; }
|
||||
|
||||
internal sealed class DebugListener : IDebugListener {
|
||||
private readonly string FilePath;
|
||||
|
||||
@@ -25,11 +25,15 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
// ReSharper disable once ClassCannotBeInstantiated
|
||||
// ReSharper disable once ClassNeverInstantiated.Global
|
||||
internal sealed class GlobalConfig {
|
||||
[SuppressMessage("ReSharper", "UnusedMember.Global")]
|
||||
internal enum EUpdateChannel : byte {
|
||||
Unknown,
|
||||
Stable,
|
||||
@@ -160,10 +164,12 @@ namespace ArchiSteamFarm {
|
||||
globalConfig.HttpTimeout = DefaultHttpTimeout;
|
||||
}
|
||||
|
||||
if (globalConfig.WCFPort == 0) {
|
||||
if (globalConfig.WCFPort != 0) {
|
||||
return globalConfig;
|
||||
}
|
||||
|
||||
Logging.LogGenericWarning("Configured WCFPort is invalid: " + globalConfig.WCFPort + ". Value of " + DefaultWCFPort + " will be used instead");
|
||||
globalConfig.WCFPort = DefaultWCFPort;
|
||||
}
|
||||
|
||||
return globalConfig;
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace ArchiSteamFarm {
|
||||
// This constructor is used when creating new database
|
||||
private GlobalDatabase(string filePath) {
|
||||
if (string.IsNullOrEmpty(filePath)) {
|
||||
throw new ArgumentNullException("filePath");
|
||||
throw new ArgumentNullException(nameof(filePath));
|
||||
}
|
||||
|
||||
FilePath = filePath;
|
||||
@@ -83,6 +83,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
// This constructor is used only by deserializer
|
||||
// ReSharper disable once UnusedMember.Local
|
||||
private GlobalDatabase() { }
|
||||
|
||||
private void Save() {
|
||||
|
||||
@@ -22,12 +22,16 @@
|
||||
|
||||
*/
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
namespace ArchiSteamFarm.JSON {
|
||||
internal static class GitHub {
|
||||
// ReSharper disable once ClassNeverInstantiated.Global
|
||||
[SuppressMessage("ReSharper", "UnusedAutoPropertyAccessor.Local")]
|
||||
internal sealed class ReleaseResponse {
|
||||
// ReSharper disable once ClassNeverInstantiated.Global
|
||||
internal sealed class Asset {
|
||||
[JsonProperty(PropertyName = "name", Required = Required.Always)]
|
||||
internal string Name { get; private set; }
|
||||
|
||||
@@ -22,11 +22,13 @@
|
||||
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using SteamKit2;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
namespace ArchiSteamFarm.JSON {
|
||||
internal static class Steam {
|
||||
internal sealed class Item { // REF: https://developer.valvesoftware.com/wiki/Steam_Web_API/IEconService#CEcon_Asset
|
||||
internal const ushort SteamAppID = 753;
|
||||
@@ -48,11 +50,13 @@ namespace ArchiSteamFarm {
|
||||
|
||||
internal uint AppID { get; set; }
|
||||
|
||||
// ReSharper disable once UnusedMember.Local
|
||||
[JsonProperty(PropertyName = "appid", Required = Required.DisallowNull)]
|
||||
internal string AppIDString {
|
||||
private string AppIDString {
|
||||
get {
|
||||
return AppID.ToString();
|
||||
}
|
||||
|
||||
set {
|
||||
if (string.IsNullOrEmpty(value)) {
|
||||
return;
|
||||
@@ -69,11 +73,13 @@ namespace ArchiSteamFarm {
|
||||
|
||||
internal ulong ContextID { get; set; }
|
||||
|
||||
// ReSharper disable once UnusedMember.Local
|
||||
[JsonProperty(PropertyName = "contextid", Required = Required.DisallowNull)]
|
||||
internal string ContextIDString {
|
||||
private string ContextIDString {
|
||||
get {
|
||||
return ContextID.ToString();
|
||||
}
|
||||
|
||||
set {
|
||||
if (string.IsNullOrEmpty(value)) {
|
||||
return;
|
||||
@@ -91,10 +97,11 @@ namespace ArchiSteamFarm {
|
||||
internal ulong AssetID { get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "assetid", Required = Required.DisallowNull)]
|
||||
internal string AssetIDString {
|
||||
private string AssetIDString {
|
||||
get {
|
||||
return AssetID.ToString();
|
||||
}
|
||||
|
||||
set {
|
||||
if (string.IsNullOrEmpty(value)) {
|
||||
return;
|
||||
@@ -109,19 +116,22 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
}
|
||||
|
||||
// ReSharper disable once UnusedMember.Local
|
||||
[JsonProperty(PropertyName = "id", Required = Required.DisallowNull)]
|
||||
internal string ID {
|
||||
private string ID {
|
||||
get { return AssetIDString; }
|
||||
set { AssetIDString = value; }
|
||||
}
|
||||
|
||||
internal ulong ClassID { get; set; }
|
||||
|
||||
// ReSharper disable once UnusedMember.Local
|
||||
[JsonProperty(PropertyName = "classid", Required = Required.DisallowNull)]
|
||||
internal string ClassIDString {
|
||||
private string ClassIDString {
|
||||
get {
|
||||
return ClassID.ToString();
|
||||
}
|
||||
|
||||
set {
|
||||
if (string.IsNullOrEmpty(value)) {
|
||||
return;
|
||||
@@ -138,11 +148,13 @@ namespace ArchiSteamFarm {
|
||||
|
||||
internal ulong InstanceID { get; set; }
|
||||
|
||||
// ReSharper disable once UnusedMember.Local
|
||||
[JsonProperty(PropertyName = "instanceid", Required = Required.DisallowNull)]
|
||||
internal string InstanceIDString {
|
||||
private string InstanceIDString {
|
||||
get {
|
||||
return InstanceID.ToString();
|
||||
}
|
||||
|
||||
set {
|
||||
if (string.IsNullOrEmpty(value)) {
|
||||
return;
|
||||
@@ -159,11 +171,13 @@ namespace ArchiSteamFarm {
|
||||
|
||||
internal uint Amount { get; set; }
|
||||
|
||||
// ReSharper disable once UnusedMember.Local
|
||||
[JsonProperty(PropertyName = "amount", Required = Required.Always)]
|
||||
internal string AmountString {
|
||||
private string AmountString {
|
||||
get {
|
||||
return Amount.ToString();
|
||||
}
|
||||
|
||||
set {
|
||||
if (string.IsNullOrEmpty(value)) {
|
||||
return;
|
||||
@@ -183,6 +197,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
internal sealed class TradeOffer { // REF: https://developer.valvesoftware.com/wiki/Steam_Web_API/IEconService#CEcon_TradeOffer
|
||||
[SuppressMessage("ReSharper", "UnusedMember.Global")]
|
||||
internal enum ETradeOfferState : byte {
|
||||
Unknown,
|
||||
Invalid,
|
||||
@@ -200,11 +215,13 @@ namespace ArchiSteamFarm {
|
||||
|
||||
internal ulong TradeOfferID { get; set; }
|
||||
|
||||
// ReSharper disable once UnusedMember.Local
|
||||
[JsonProperty(PropertyName = "tradeofferid", Required = Required.Always)]
|
||||
internal string TradeOfferIDString {
|
||||
private string TradeOfferIDString {
|
||||
get {
|
||||
return TradeOfferID.ToString();
|
||||
}
|
||||
|
||||
set {
|
||||
if (string.IsNullOrEmpty(value)) {
|
||||
return;
|
||||
@@ -220,7 +237,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
[JsonProperty(PropertyName = "accountid_other", Required = Required.Always)]
|
||||
internal uint OtherSteamID3 { get; set; }
|
||||
internal uint OtherSteamID3 { private get; set; }
|
||||
|
||||
[JsonProperty(PropertyName = "trade_offer_state", Required = Required.Always)]
|
||||
internal ETradeOfferState State { get; set; }
|
||||
@@ -232,82 +249,57 @@ namespace ArchiSteamFarm {
|
||||
internal HashSet<Item> ItemsToReceive { get; } = new HashSet<Item>();
|
||||
|
||||
// Extra
|
||||
internal ulong OtherSteamID64 {
|
||||
get {
|
||||
if (OtherSteamID3 == 0) {
|
||||
return 0;
|
||||
}
|
||||
internal ulong OtherSteamID64 => OtherSteamID3 == 0 ? 0 : new SteamID(OtherSteamID3, EUniverse.Public, EAccountType.Individual);
|
||||
|
||||
return new SteamID(OtherSteamID3, EUniverse.Public, EAccountType.Individual);
|
||||
}
|
||||
set {
|
||||
if (value == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
OtherSteamID3 = new SteamID(value).AccountID;
|
||||
}
|
||||
}
|
||||
|
||||
internal bool IsSteamCardsOnlyTradeForUs() {
|
||||
foreach (Item item in ItemsToGive) {
|
||||
if (item.AppID != Item.SteamAppID || item.ContextID != Item.SteamContextID || (item.Type != Item.EType.FoilTradingCard && item.Type != Item.EType.TradingCard)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
internal bool IsSteamCardsOnlyTradeForUs() => ItemsToGive.All(item => (item.AppID == Item.SteamAppID) && (item.ContextID == Item.SteamContextID) && ((item.Type == Item.EType.FoilTradingCard) || (item.Type == Item.EType.TradingCard)));
|
||||
|
||||
internal bool IsPotentiallyDupesTradeForUs() {
|
||||
Dictionary<uint, Dictionary<Item.EType, uint>> ItemsToGivePerGame = new Dictionary<uint, Dictionary<Item.EType, uint>>();
|
||||
Dictionary<uint, Dictionary<Item.EType, uint>> itemsToGivePerGame = new Dictionary<uint, Dictionary<Item.EType, uint>>();
|
||||
foreach (Item item in ItemsToGive) {
|
||||
Dictionary<Item.EType, uint> ItemsPerType;
|
||||
if (!ItemsToGivePerGame.TryGetValue(item.RealAppID, out ItemsPerType)) {
|
||||
ItemsPerType = new Dictionary<Item.EType, uint>();
|
||||
ItemsPerType[item.Type] = item.Amount;
|
||||
ItemsToGivePerGame[item.RealAppID] = ItemsPerType;
|
||||
Dictionary<Item.EType, uint> itemsPerType;
|
||||
if (!itemsToGivePerGame.TryGetValue(item.RealAppID, out itemsPerType)) {
|
||||
itemsPerType = new Dictionary<Item.EType, uint> { [item.Type] = item.Amount };
|
||||
itemsToGivePerGame[item.RealAppID] = itemsPerType;
|
||||
} else {
|
||||
uint amount;
|
||||
if (ItemsPerType.TryGetValue(item.Type, out amount)) {
|
||||
ItemsPerType[item.Type] = amount + item.Amount;
|
||||
if (itemsPerType.TryGetValue(item.Type, out amount)) {
|
||||
itemsPerType[item.Type] = amount + item.Amount;
|
||||
} else {
|
||||
ItemsPerType[item.Type] = item.Amount;
|
||||
itemsPerType[item.Type] = item.Amount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Dictionary<uint, Dictionary<Item.EType, uint>> ItemsToReceivePerGame = new Dictionary<uint, Dictionary<Item.EType, uint>>();
|
||||
Dictionary<uint, Dictionary<Item.EType, uint>> itemsToReceivePerGame = new Dictionary<uint, Dictionary<Item.EType, uint>>();
|
||||
foreach (Item item in ItemsToReceive) {
|
||||
Dictionary<Item.EType, uint> ItemsPerType;
|
||||
if (!ItemsToReceivePerGame.TryGetValue(item.RealAppID, out ItemsPerType)) {
|
||||
ItemsPerType = new Dictionary<Item.EType, uint>();
|
||||
ItemsPerType[item.Type] = item.Amount;
|
||||
ItemsToReceivePerGame[item.RealAppID] = ItemsPerType;
|
||||
Dictionary<Item.EType, uint> itemsPerType;
|
||||
if (!itemsToReceivePerGame.TryGetValue(item.RealAppID, out itemsPerType)) {
|
||||
itemsPerType = new Dictionary<Item.EType, uint> { [item.Type] = item.Amount };
|
||||
itemsToReceivePerGame[item.RealAppID] = itemsPerType;
|
||||
} else {
|
||||
uint amount;
|
||||
if (ItemsPerType.TryGetValue(item.Type, out amount)) {
|
||||
ItemsPerType[item.Type] = amount + item.Amount;
|
||||
if (itemsPerType.TryGetValue(item.Type, out amount)) {
|
||||
itemsPerType[item.Type] = amount + item.Amount;
|
||||
} else {
|
||||
ItemsPerType[item.Type] = item.Amount;
|
||||
itemsPerType[item.Type] = item.Amount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that amount of items to give is at least amount of items to receive (per game and per type)
|
||||
foreach (KeyValuePair<uint, Dictionary<Item.EType, uint>> ItemsPerGame in ItemsToGivePerGame) {
|
||||
foreach (KeyValuePair<uint, Dictionary<Item.EType, uint>> itemsPerGame in itemsToGivePerGame) {
|
||||
Dictionary<Item.EType, uint> otherItemsPerType;
|
||||
if (!ItemsToReceivePerGame.TryGetValue(ItemsPerGame.Key, out otherItemsPerType)) {
|
||||
if (!itemsToReceivePerGame.TryGetValue(itemsPerGame.Key, out otherItemsPerType)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<Item.EType, uint> ItemsPerType in ItemsPerGame.Value) {
|
||||
foreach (KeyValuePair<Item.EType, uint> itemsPerType in itemsPerGame.Value) {
|
||||
uint otherAmount;
|
||||
if (!otherItemsPerType.TryGetValue(ItemsPerType.Key, out otherAmount)) {
|
||||
if (!otherItemsPerType.TryGetValue(itemsPerType.Key, out otherAmount)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ItemsPerType.Value > otherAmount) {
|
||||
if (itemsPerType.Value > otherAmount) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -317,6 +309,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "UnusedMember.Global")]
|
||||
internal sealed class TradeOfferRequest {
|
||||
internal sealed class ItemList {
|
||||
[JsonProperty(PropertyName = "assets", Required = Required.Always)]
|
||||
|
||||
@@ -36,7 +36,10 @@ namespace ArchiSteamFarm {
|
||||
internal static void Init() {
|
||||
LogToFile = Program.GlobalConfig.LogToFile;
|
||||
|
||||
if (LogToFile) {
|
||||
if (!LogToFile) {
|
||||
return;
|
||||
}
|
||||
|
||||
lock (FileLock) {
|
||||
if (!LogToFile) {
|
||||
return;
|
||||
@@ -50,7 +53,6 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static void LogGenericWTF(string message, string botName = "Main", [CallerMemberName] string previousMethodName = null) {
|
||||
if (string.IsNullOrEmpty(message)) {
|
||||
@@ -69,6 +71,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
internal static void LogGenericException(Exception exception, string botName = "Main", [CallerMemberName] string previousMethodName = null) {
|
||||
while (true) {
|
||||
if (exception == null) {
|
||||
return;
|
||||
}
|
||||
@@ -77,7 +80,11 @@ namespace ArchiSteamFarm {
|
||||
Log("[!] StackTrace:" + Environment.NewLine + exception.StackTrace);
|
||||
|
||||
if (exception.InnerException != null) {
|
||||
LogGenericException(exception.InnerException, botName, previousMethodName);
|
||||
exception = exception.InnerException;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,9 +109,11 @@ namespace ArchiSteamFarm {
|
||||
return;
|
||||
}
|
||||
|
||||
// ReSharper disable once ExplicitCallerInfoArgument
|
||||
LogGenericError(nullObjectName + " is null!", botName, previousMethodName);
|
||||
}
|
||||
|
||||
// ReSharper disable once UnusedMember.Global
|
||||
[Conditional("DEBUG")]
|
||||
internal static void LogGenericDebug(string message, string botName = "Main", [CallerMemberName] string previousMethodName = null) {
|
||||
if (string.IsNullOrEmpty(message)) {
|
||||
@@ -125,10 +134,16 @@ namespace ArchiSteamFarm {
|
||||
if (!Program.ConsoleIsBusy) {
|
||||
try {
|
||||
Console.Write(loggedMessage);
|
||||
} catch { }
|
||||
}
|
||||
catch {
|
||||
// Ignored
|
||||
}
|
||||
}
|
||||
|
||||
if (!LogToFile) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (LogToFile) {
|
||||
lock (FileLock) {
|
||||
if (!LogToFile) {
|
||||
return;
|
||||
@@ -143,5 +158,4 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,11 +26,13 @@ using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using ArchiSteamFarm.JSON;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
internal static class Program {
|
||||
@@ -49,21 +51,22 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
private enum EMode : byte {
|
||||
[SuppressMessage("ReSharper", "UnusedMember.Local")]
|
||||
Unknown,
|
||||
Normal, // Standard most common usage
|
||||
Client, // WCF client only
|
||||
Server // Normal + WCF server
|
||||
}
|
||||
|
||||
internal const string ASF = "ASF";
|
||||
internal const string ConfigDirectory = "config";
|
||||
internal const string DebugDirectory = "debug";
|
||||
internal const string LogFile = "log.txt";
|
||||
internal const string GithubRepo = "JustArchi/ArchiSteamFarm";
|
||||
internal const string GlobalConfigFile = ASF + ".json";
|
||||
internal const string GlobalDatabaseFile = ASF + ".db";
|
||||
|
||||
private const string ASF = "ASF";
|
||||
private const string GithubReleaseURL = "https://api.github.com/repos/" + GithubRepo + "/releases"; // GitHub API is HTTPS only
|
||||
private const string GlobalConfigFile = ASF + ".json";
|
||||
private const string GlobalDatabaseFile = ASF + ".db";
|
||||
|
||||
internal static readonly Version Version = Assembly.GetEntryAssembly().GetName().Version;
|
||||
|
||||
@@ -76,7 +79,7 @@ namespace ArchiSteamFarm {
|
||||
|
||||
internal static GlobalConfig GlobalConfig { get; private set; }
|
||||
internal static GlobalDatabase GlobalDatabase { get; private set; }
|
||||
internal static bool ConsoleIsBusy { get; private set; } = false;
|
||||
internal static bool ConsoleIsBusy { get; private set; }
|
||||
|
||||
private static Timer AutoUpdatesTimer;
|
||||
private static EMode Mode = EMode.Normal;
|
||||
@@ -109,7 +112,7 @@ namespace ArchiSteamFarm {
|
||||
|
||||
string response = null;
|
||||
Logging.LogGenericInfo("Checking new version...");
|
||||
for (byte i = 0; i < WebBrowser.MaxRetries && string.IsNullOrEmpty(response); i++) {
|
||||
for (byte i = 0; (i < WebBrowser.MaxRetries) && string.IsNullOrEmpty(response); i++) {
|
||||
response = await WebBrowser.UrlGetToContent(releaseURL).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@@ -135,7 +138,7 @@ namespace ArchiSteamFarm {
|
||||
return;
|
||||
}
|
||||
|
||||
if (releases == null || releases.Count == 0) {
|
||||
if ((releases == null) || (releases.Count == 0)) {
|
||||
Logging.LogGenericWarning("Could not check latest version!");
|
||||
return;
|
||||
}
|
||||
@@ -153,15 +156,19 @@ namespace ArchiSteamFarm {
|
||||
Logging.LogGenericInfo("Local version: " + Version + " | Remote version: " + newVersion);
|
||||
|
||||
if (Version.CompareTo(newVersion) >= 0) { // If local version is the same or newer than remote version
|
||||
if (AutoUpdatesTimer == null && GlobalConfig.AutoUpdates) {
|
||||
if ((AutoUpdatesTimer != null) || !GlobalConfig.AutoUpdates) {
|
||||
return;
|
||||
}
|
||||
|
||||
Logging.LogGenericInfo("ASF will automatically check for new versions every 24 hours");
|
||||
|
||||
AutoUpdatesTimer = new Timer(
|
||||
async e => await CheckForUpdate().ConfigureAwait(false),
|
||||
null,
|
||||
TimeSpan.FromDays(1), // Delay
|
||||
TimeSpan.FromDays(1) // Period
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -183,15 +190,7 @@ namespace ArchiSteamFarm {
|
||||
return;
|
||||
}
|
||||
|
||||
GitHub.ReleaseResponse.Asset binaryAsset = null;
|
||||
foreach (var asset in releaseResponse.Assets) {
|
||||
if (string.IsNullOrEmpty(asset.Name) || !asset.Name.Equals(ExecutableName, StringComparison.OrdinalIgnoreCase)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
binaryAsset = asset;
|
||||
break;
|
||||
}
|
||||
GitHub.ReleaseResponse.Asset binaryAsset = releaseResponse.Assets.FirstOrDefault(asset => !string.IsNullOrEmpty(asset.Name) && asset.Name.Equals(ExecutableName, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (binaryAsset == null) {
|
||||
Logging.LogGenericWarning("Could not proceed with update because there is no asset that relates to currently running binary!");
|
||||
@@ -204,7 +203,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
byte[] result = null;
|
||||
for (byte i = 0; i < WebBrowser.MaxRetries && result == null; i++) {
|
||||
for (byte i = 0; (i < WebBrowser.MaxRetries) && (result == null); i++) {
|
||||
Logging.LogGenericInfo("Downloading new version...");
|
||||
result = await WebBrowser.UrlGetToBytes(binaryAsset.DownloadURL).ConfigureAwait(false);
|
||||
}
|
||||
@@ -232,7 +231,9 @@ namespace ArchiSteamFarm {
|
||||
try {
|
||||
// Cleanup
|
||||
File.Delete(newExeFile);
|
||||
} catch { }
|
||||
} catch {
|
||||
// Ignored
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -245,7 +246,9 @@ namespace ArchiSteamFarm {
|
||||
// Cleanup
|
||||
File.Move(oldExeFile, ExecutableFile);
|
||||
File.Delete(newExeFile);
|
||||
} catch { }
|
||||
} catch {
|
||||
// Ignored
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -326,6 +329,7 @@ namespace ArchiSteamFarm {
|
||||
Console.Write((string.IsNullOrEmpty(botName) ? "" : "<" + botName + "> ") + "Please enter not documented yet value of \"" + userInputType + "\": ");
|
||||
break;
|
||||
}
|
||||
|
||||
result = Console.ReadLine();
|
||||
if (!Console.IsOutputRedirected) {
|
||||
Console.Clear(); // For security purposes
|
||||
@@ -337,11 +341,9 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
internal static void OnBotShutdown() {
|
||||
foreach (Bot bot in Bot.Bots.Values) {
|
||||
if (bot.KeepRunning) {
|
||||
if (Bot.Bots.Values.Any(bot => bot.KeepRunning)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (WCF.IsServerRunning()) {
|
||||
return;
|
||||
@@ -374,7 +376,11 @@ namespace ArchiSteamFarm {
|
||||
WebBrowser = new WebBrowser("Main");
|
||||
}
|
||||
|
||||
private static void ParseArgs(string[] args) {
|
||||
private static void ParseArgs(IEnumerable<string> args) {
|
||||
if (args == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (string arg in args) {
|
||||
switch (arg) {
|
||||
case "--client":
|
||||
@@ -385,7 +391,7 @@ namespace ArchiSteamFarm {
|
||||
WCF.StartServer();
|
||||
break;
|
||||
default:
|
||||
if (arg.StartsWith("--")) {
|
||||
if (arg.StartsWith("--", StringComparison.Ordinal)) {
|
||||
Logging.LogGenericWarning("Unrecognized parameter: " + arg);
|
||||
continue;
|
||||
}
|
||||
@@ -410,7 +416,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
private static void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs args) {
|
||||
if (sender == null || args == null) {
|
||||
if ((sender == null) || (args == null)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -418,14 +424,14 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
private static void UnobservedTaskExceptionHandler(object sender, UnobservedTaskExceptionEventArgs args) {
|
||||
if (sender == null || args == null) {
|
||||
if ((sender == null) || (args == null)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Logging.LogGenericException(args.Exception);
|
||||
}
|
||||
|
||||
private static void Init(string[] args) {
|
||||
private static void Init(IEnumerable<string> args) {
|
||||
AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionHandler;
|
||||
TaskScheduler.UnobservedTaskException += UnobservedTaskExceptionHandler;
|
||||
|
||||
@@ -437,7 +443,7 @@ namespace ArchiSteamFarm {
|
||||
if (Debugging.IsDebugBuild) {
|
||||
|
||||
// Common structure is bin/(x64/)Debug/ArchiSteamFarm.exe, so we allow up to 4 directories up
|
||||
for (var i = 0; i < 4; i++) {
|
||||
for (byte i = 0; i < 4; i++) {
|
||||
Directory.SetCurrentDirectory("..");
|
||||
if (Directory.Exists(ConfigDirectory)) {
|
||||
break;
|
||||
@@ -458,7 +464,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
Directory.CreateDirectory(DebugDirectory);
|
||||
|
||||
SteamKit2.DebugLog.AddListener(new Debugging.DebugListener(Path.Combine(Program.DebugDirectory, "debug.txt")));
|
||||
SteamKit2.DebugLog.AddListener(new Debugging.DebugListener(Path.Combine(DebugDirectory, "debug.txt")));
|
||||
SteamKit2.DebugLog.Enabled = true;
|
||||
}
|
||||
|
||||
@@ -486,8 +492,7 @@ namespace ArchiSteamFarm {
|
||||
|
||||
bool isRunning = false;
|
||||
|
||||
foreach (var configFile in Directory.EnumerateFiles(ConfigDirectory, "*.json")) {
|
||||
string botName = Path.GetFileNameWithoutExtension(configFile);
|
||||
foreach (string botName in Directory.EnumerateFiles(ConfigDirectory, "*.json").Select(Path.GetFileNameWithoutExtension)) {
|
||||
switch (botName) {
|
||||
case ASF:
|
||||
case "example":
|
||||
@@ -496,7 +501,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
Bot bot = new Bot(botName);
|
||||
if (bot.BotConfig != null && bot.BotConfig.Enabled) {
|
||||
if ((bot.BotConfig != null) && bot.BotConfig.Enabled) {
|
||||
if (bot.BotConfig.StartOnLaunch) {
|
||||
isRunning = true;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
|
||||
@@ -25,8 +25,10 @@
|
||||
using SteamAuth;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using ArchiSteamFarm.JSON;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
internal sealed class Trading {
|
||||
@@ -50,7 +52,7 @@ namespace ArchiSteamFarm {
|
||||
|
||||
internal Trading(Bot bot) {
|
||||
if (bot == null) {
|
||||
throw new ArgumentNullException("bot");
|
||||
throw new ArgumentNullException(nameof(bot));
|
||||
}
|
||||
|
||||
Bot = bot;
|
||||
@@ -77,7 +79,7 @@ namespace ArchiSteamFarm {
|
||||
|
||||
private async Task ParseActiveTrades() {
|
||||
HashSet<Steam.TradeOffer> tradeOffers = Bot.ArchiWebHandler.GetTradeOffers();
|
||||
if (tradeOffers == null || tradeOffers.Count == 0) {
|
||||
if ((tradeOffers == null) || (tradeOffers.Count == 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -86,7 +88,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
private async Task ParseTrade(Steam.TradeOffer tradeOffer) {
|
||||
if (tradeOffer == null || tradeOffer.State != Steam.TradeOffer.ETradeOfferState.Active) {
|
||||
if ((tradeOffer == null) || (tradeOffer.State != Steam.TradeOffer.ETradeOfferState.Active)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -110,7 +112,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
// Always accept trades from SteamMasterID
|
||||
if (tradeOffer.OtherSteamID64 != 0 && tradeOffer.OtherSteamID64 == Bot.BotConfig.SteamMasterID) {
|
||||
if ((tradeOffer.OtherSteamID64 != 0) && (tradeOffer.OtherSteamID64 == Bot.BotConfig.SteamMasterID)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -132,7 +134,7 @@ namespace ArchiSteamFarm {
|
||||
// At this point we're sure that STM trade is valid
|
||||
// Now check if it's worth for us to do the trade
|
||||
HashSet<Steam.Item> inventory = await Bot.ArchiWebHandler.GetMyTradableInventory().ConfigureAwait(false);
|
||||
if (inventory == null || inventory.Count == 0) {
|
||||
if ((inventory == null) || (inventory.Count == 0)) {
|
||||
return true; // OK, assume that this trade is valid, we can't check our EQ
|
||||
}
|
||||
|
||||
@@ -166,9 +168,7 @@ namespace ArchiSteamFarm {
|
||||
|
||||
// Calculate our value of items to give
|
||||
List<uint> amountsToGive = new List<uint>(tradeOffer.ItemsToGive.Count);
|
||||
foreach (Steam.Item item in tradeOffer.ItemsToGive) {
|
||||
Tuple<ulong, ulong> key = new Tuple<ulong, ulong>(item.ClassID, item.InstanceID);
|
||||
|
||||
foreach (Tuple<ulong, ulong> key in tradeOffer.ItemsToGive.Select(item => new Tuple<ulong, ulong>(item.ClassID, item.InstanceID))) {
|
||||
uint amount;
|
||||
if (!amountMap.TryGetValue(key, out amount)) {
|
||||
amountsToGive.Add(0);
|
||||
@@ -183,9 +183,7 @@ namespace ArchiSteamFarm {
|
||||
|
||||
// Calculate our value of items to receive
|
||||
List<uint> amountsToReceive = new List<uint>(tradeOffer.ItemsToReceive.Count);
|
||||
foreach (Steam.Item item in tradeOffer.ItemsToReceive) {
|
||||
Tuple<ulong, ulong> key = new Tuple<ulong, ulong>(item.ClassID, item.InstanceID);
|
||||
|
||||
foreach (Tuple<ulong, ulong> key in tradeOffer.ItemsToReceive.Select(item => new Tuple<ulong, ulong>(item.ClassID, item.InstanceID))) {
|
||||
uint amount;
|
||||
if (!amountMap.TryGetValue(key, out amount)) {
|
||||
amountsToReceive.Add(0);
|
||||
@@ -199,10 +197,7 @@ namespace ArchiSteamFarm {
|
||||
amountsToReceive.Sort();
|
||||
|
||||
// Check actual difference
|
||||
int difference = 0;
|
||||
for (int i = 0; i < amountsToGive.Count; i++) {
|
||||
difference += (int) (amountsToGive[i] - amountsToReceive[i]);
|
||||
}
|
||||
int difference = amountsToGive.Select((t, i) => (int) (t - amountsToReceive[i])).Sum();
|
||||
|
||||
// Trade is worth for us if the difference is greater than 0
|
||||
return difference > 0;
|
||||
|
||||
@@ -30,43 +30,20 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
internal static class Utilities {
|
||||
// ReSharper disable once UnusedParameter.Global
|
||||
internal static void Forget(this Task task) { }
|
||||
|
||||
internal static Task ForEachAsync<T>(this IEnumerable<T> sequence, Func<T, Task> action) {
|
||||
if (action == null) {
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
internal static Task ForEachAsync<T>(this IEnumerable<T> sequence, Func<T, Task> action) => action == null ? Task.FromResult(true) : Task.WhenAll(sequence.Select(action));
|
||||
|
||||
return Task.WhenAll(sequence.Select(action));
|
||||
}
|
||||
|
||||
internal static string GetCookieValue(this CookieContainer cookieContainer, string URL, string name) {
|
||||
if (string.IsNullOrEmpty(URL) || string.IsNullOrEmpty(name)) {
|
||||
internal static string GetCookieValue(this CookieContainer cookieContainer, string url, string name) {
|
||||
if (string.IsNullOrEmpty(url) || string.IsNullOrEmpty(name)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
CookieCollection cookies = cookieContainer.GetCookies(new Uri(URL));
|
||||
if (cookies == null || cookies.Count == 0) {
|
||||
return null;
|
||||
CookieCollection cookies = cookieContainer.GetCookies(new Uri(url));
|
||||
return cookies.Count == 0 ? null : (from Cookie cookie in cookies where cookie.Name.Equals(name, StringComparison.Ordinal) select cookie.Value).FirstOrDefault();
|
||||
}
|
||||
|
||||
foreach (Cookie cookie in cookies) {
|
||||
if (!cookie.Name.Equals(name, StringComparison.Ordinal)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return cookie.Value;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
internal static Task SleepAsync(int miliseconds) {
|
||||
if (miliseconds < 0) {
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
return Task.Delay(miliseconds);
|
||||
}
|
||||
internal static Task SleepAsync(int miliseconds) => miliseconds < 0 ? Task.FromResult(true) : Task.Delay(miliseconds);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,9 +52,7 @@ namespace ArchiSteamFarm {
|
||||
URL = "http://" + Program.GlobalConfig.WCFHostname + ":" + Program.GlobalConfig.WCFPort + "/ASF";
|
||||
}
|
||||
|
||||
internal bool IsServerRunning() {
|
||||
return ServiceHost != null;
|
||||
}
|
||||
internal bool IsServerRunning() => ServiceHost != null;
|
||||
|
||||
internal void StartServer() {
|
||||
if (ServiceHost != null) {
|
||||
|
||||
@@ -27,7 +27,6 @@ using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
@@ -65,7 +64,7 @@ namespace ArchiSteamFarm {
|
||||
|
||||
internal WebBrowser(string identifier) {
|
||||
if (string.IsNullOrEmpty(identifier)) {
|
||||
throw new ArgumentNullException("identifier");
|
||||
throw new ArgumentNullException(nameof(identifier));
|
||||
}
|
||||
|
||||
Identifier = identifier;
|
||||
@@ -99,11 +98,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
using (HttpResponseMessage response = await UrlHeadToResponse(request, referer).ConfigureAwait(false)) {
|
||||
if (response == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return response.RequestMessage.RequestUri;
|
||||
return response == null ? null : response.RequestMessage.RequestUri;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,7 +224,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
private async Task<HttpResponseMessage> UrlRequest(string request, HttpMethod httpMethod, Dictionary<string, string> data = null, string referer = null) {
|
||||
if (string.IsNullOrEmpty(request) || httpMethod == null) {
|
||||
if (string.IsNullOrEmpty(request) || (httpMethod == null)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -239,7 +234,7 @@ namespace ArchiSteamFarm {
|
||||
|
||||
HttpResponseMessage responseMessage;
|
||||
using (HttpRequestMessage requestMessage = new HttpRequestMessage(httpMethod, request)) {
|
||||
if (data != null && data.Count > 0) {
|
||||
if ((data != null) && (data.Count > 0)) {
|
||||
try {
|
||||
requestMessage.Content = new FormUrlEncodedContent(data);
|
||||
} catch (UriFormatException e) {
|
||||
@@ -263,17 +258,18 @@ namespace ArchiSteamFarm {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!responseMessage.IsSuccessStatusCode) {
|
||||
if (responseMessage.IsSuccessStatusCode) {
|
||||
return responseMessage;
|
||||
}
|
||||
|
||||
if (Debugging.IsDebugBuild || Program.GlobalConfig.Debug) {
|
||||
Logging.LogGenericError("Request: " + request + " failed!", Identifier);
|
||||
Logging.LogGenericError("Status code: " + responseMessage.StatusCode, Identifier);
|
||||
Logging.LogGenericError("Content: " + Environment.NewLine + await responseMessage.Content.ReadAsStringAsync().ConfigureAwait(false), Identifier);
|
||||
}
|
||||
|
||||
responseMessage.Dispose();
|
||||
return null;
|
||||
}
|
||||
|
||||
return responseMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,13 +39,13 @@ namespace ConfigGenerator {
|
||||
|
||||
protected ASFConfig(string filePath) : this() {
|
||||
if (string.IsNullOrEmpty(filePath)) {
|
||||
throw new ArgumentNullException("filePath");
|
||||
throw new ArgumentNullException(nameof(filePath));
|
||||
}
|
||||
|
||||
FilePath = filePath;
|
||||
}
|
||||
|
||||
internal virtual void Save() {
|
||||
internal void Save() {
|
||||
lock (FilePath) {
|
||||
try {
|
||||
File.WriteAllText(FilePath, JsonConvert.SerializeObject(this, Formatting.Indented));
|
||||
@@ -55,7 +55,7 @@ namespace ConfigGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
internal virtual void Remove() {
|
||||
internal void Remove() {
|
||||
string queryPath = Path.GetFileNameWithoutExtension(FilePath);
|
||||
lock (FilePath) {
|
||||
foreach (string botFile in Directory.EnumerateFiles(Program.ConfigDirectory, queryPath + ".*")) {
|
||||
@@ -66,10 +66,11 @@ namespace ConfigGenerator {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ASFConfigs.Remove(this);
|
||||
}
|
||||
|
||||
internal virtual void Rename(string botName) {
|
||||
internal void Rename(string botName) {
|
||||
if (string.IsNullOrEmpty(botName)) {
|
||||
return;
|
||||
}
|
||||
@@ -83,6 +84,7 @@ namespace ConfigGenerator {
|
||||
Logging.LogGenericException(e);
|
||||
}
|
||||
}
|
||||
|
||||
FilePath = Path.Combine(Program.ConfigDirectory, botName + ".json");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,9 +26,11 @@ using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
|
||||
namespace ConfigGenerator {
|
||||
[SuppressMessage("ReSharper", "AutoPropertyCanBeMadeGetOnly.Global"), SuppressMessage("ReSharper", "CollectionNeverQueried.Global"), SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "UnusedMember.Global")]
|
||||
internal sealed class BotConfig : ASFConfig {
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
public bool Enabled { get; set; } = false;
|
||||
@@ -39,8 +41,7 @@ namespace ConfigGenerator {
|
||||
[JsonProperty]
|
||||
public string SteamLogin { get; set; } = null;
|
||||
|
||||
[JsonProperty]
|
||||
[PasswordPropertyText(true)]
|
||||
[JsonProperty, PasswordPropertyText(true)]
|
||||
public string SteamPassword { get; set; } = null;
|
||||
|
||||
[JsonProperty]
|
||||
@@ -130,11 +131,12 @@ namespace ConfigGenerator {
|
||||
}
|
||||
|
||||
// This constructor is used only by deserializer
|
||||
// ReSharper disable once UnusedMember.Local
|
||||
private BotConfig() { }
|
||||
|
||||
private BotConfig(string filePath) : base(filePath) {
|
||||
if (string.IsNullOrEmpty(filePath)) {
|
||||
throw new ArgumentNullException("filePath");
|
||||
throw new ArgumentNullException(nameof(filePath));
|
||||
}
|
||||
|
||||
GamesPlayedWhileIdle.Add(0);
|
||||
|
||||
@@ -83,6 +83,7 @@
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
</Compile>
|
||||
<None Include="packages.config" />
|
||||
<None Include="Properties\Settings.settings">
|
||||
|
||||
@@ -42,8 +42,6 @@ namespace ConfigGenerator {
|
||||
Controls.Add(enhancedPropertyGrid);
|
||||
}
|
||||
|
||||
internal void RefreshText() {
|
||||
Text = Path.GetFileNameWithoutExtension(ASFConfig.FilePath);
|
||||
}
|
||||
internal void RefreshText() => Text = Path.GetFileNameWithoutExtension(ASFConfig.FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,11 +25,11 @@
|
||||
namespace ConfigGenerator {
|
||||
internal static class Debugging {
|
||||
#if DEBUG
|
||||
// ReSharper disable once ConvertToConstant.Global
|
||||
internal static readonly bool IsDebugBuild = true;
|
||||
#else
|
||||
// ReSharper disable once ConvertToConstant.Global
|
||||
internal static readonly bool IsDebugBuild = false;
|
||||
#endif
|
||||
|
||||
internal static bool IsReleaseBuild => !IsDebugBuild;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,50 +25,53 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
using ConfigGenerator.Properties;
|
||||
|
||||
namespace ConfigGenerator {
|
||||
internal sealed class DialogBox {
|
||||
internal static class DialogBox {
|
||||
internal static DialogResult InputBox(string title, string promptText, out string value) {
|
||||
if (string.IsNullOrEmpty(title) || string.IsNullOrEmpty(promptText)) {
|
||||
value = null;
|
||||
return DialogResult.Abort;
|
||||
}
|
||||
|
||||
Form form = new Form();
|
||||
Label label = new Label();
|
||||
TextBox textBox = new TextBox();
|
||||
TextBox textBox = new TextBox {
|
||||
Anchor = AnchorStyles.Right,
|
||||
Bounds = new Rectangle(12, 36, 372, 20),
|
||||
Width = 1000
|
||||
};
|
||||
|
||||
textBox.Width = 1000;
|
||||
Button buttonOk = new Button();
|
||||
Button buttonCancel = new Button();
|
||||
Button buttonOk = new Button {
|
||||
Anchor = AnchorStyles.Bottom | AnchorStyles.Right,
|
||||
Bounds = new Rectangle(228, 72, 75, 23),
|
||||
DialogResult = DialogResult.OK,
|
||||
Text = Resources.OK
|
||||
};
|
||||
|
||||
form.Text = title;
|
||||
label.Text = promptText;
|
||||
Button buttonCancel = new Button {
|
||||
Anchor = AnchorStyles.Bottom | AnchorStyles.Right,
|
||||
Bounds = new Rectangle(309, 72, 75, 23),
|
||||
DialogResult = DialogResult.Cancel,
|
||||
Text = Resources.Cancel
|
||||
};
|
||||
|
||||
buttonOk.Text = "OK";
|
||||
buttonCancel.Text = "Cancel";
|
||||
buttonOk.DialogResult = DialogResult.OK;
|
||||
buttonCancel.DialogResult = DialogResult.Cancel;
|
||||
Label label = new Label {
|
||||
AutoSize = true,
|
||||
Bounds = new Rectangle(9, 20, 372, 13),
|
||||
Text = promptText
|
||||
};
|
||||
|
||||
label.SetBounds(9, 20, 372, 13);
|
||||
textBox.SetBounds(12, 36, 372, 20);
|
||||
buttonOk.SetBounds(228, 72, 75, 23);
|
||||
buttonCancel.SetBounds(309, 72, 75, 23);
|
||||
|
||||
label.AutoSize = true;
|
||||
textBox.Anchor = textBox.Anchor | AnchorStyles.Right;
|
||||
buttonOk.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
|
||||
buttonCancel.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
|
||||
|
||||
form.ClientSize = new Size(396, 107);
|
||||
form.Controls.AddRange(new Control[] { label, textBox, buttonOk, buttonCancel });
|
||||
form.ClientSize = new Size(Math.Max(300, label.Right + 10), form.ClientSize.Height);
|
||||
form.FormBorderStyle = FormBorderStyle.FixedDialog;
|
||||
form.StartPosition = FormStartPosition.CenterScreen;
|
||||
form.MinimizeBox = false;
|
||||
form.MaximizeBox = false;
|
||||
form.AcceptButton = buttonOk;
|
||||
form.CancelButton = buttonCancel;
|
||||
Form form = new Form {
|
||||
AcceptButton = buttonOk,
|
||||
CancelButton = buttonCancel,
|
||||
ClientSize = new Size(Math.Max(300, label.Right + 10), 107),
|
||||
Controls = { label, textBox, buttonOk, buttonCancel },
|
||||
FormBorderStyle = FormBorderStyle.FixedDialog,
|
||||
MinimizeBox = false,
|
||||
MaximizeBox = false,
|
||||
StartPosition = FormStartPosition.CenterScreen,
|
||||
Text = title
|
||||
};
|
||||
|
||||
DialogResult dialogResult = form.ShowDialog();
|
||||
value = textBox.Text;
|
||||
@@ -80,37 +83,37 @@ namespace ConfigGenerator {
|
||||
return DialogResult.Abort;
|
||||
}
|
||||
|
||||
Form form = new Form();
|
||||
Label label = new Label();
|
||||
Button buttonYes = new Button {
|
||||
Anchor = AnchorStyles.Bottom | AnchorStyles.Right,
|
||||
Bounds = new Rectangle(228, 72, 75, 23),
|
||||
DialogResult = DialogResult.Yes,
|
||||
Text = Resources.Yes
|
||||
};
|
||||
|
||||
Button buttonOk = new Button();
|
||||
Button buttonCancel = new Button();
|
||||
Button buttonNo = new Button {
|
||||
Anchor = AnchorStyles.Bottom | AnchorStyles.Right,
|
||||
Bounds = new Rectangle(309, 72, 75, 23),
|
||||
DialogResult = DialogResult.No,
|
||||
Text = Resources.No
|
||||
};
|
||||
|
||||
form.Text = title;
|
||||
label.Text = promptText;
|
||||
Label label = new Label {
|
||||
AutoSize = true,
|
||||
Bounds = new Rectangle(9, 20, 372, 13),
|
||||
Text = promptText
|
||||
};
|
||||
|
||||
buttonOk.Text = "Yes";
|
||||
buttonCancel.Text = "No";
|
||||
buttonOk.DialogResult = DialogResult.Yes;
|
||||
buttonCancel.DialogResult = DialogResult.No;
|
||||
|
||||
label.SetBounds(9, 20, 372, 13);
|
||||
buttonOk.SetBounds(228, 50, 75, 23);
|
||||
buttonCancel.SetBounds(309, 50, 75, 23);
|
||||
|
||||
label.AutoSize = true;
|
||||
buttonOk.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
|
||||
buttonCancel.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
|
||||
|
||||
form.ClientSize = new Size(396, 80);
|
||||
form.Controls.AddRange(new Control[] { label, buttonOk, buttonCancel });
|
||||
form.ClientSize = new Size(Math.Max(300, label.Right + 10), form.ClientSize.Height);
|
||||
form.FormBorderStyle = FormBorderStyle.FixedDialog;
|
||||
form.StartPosition = FormStartPosition.CenterScreen;
|
||||
form.MinimizeBox = false;
|
||||
form.MaximizeBox = false;
|
||||
form.AcceptButton = buttonOk;
|
||||
form.CancelButton = buttonCancel;
|
||||
Form form = new Form {
|
||||
AcceptButton = buttonYes,
|
||||
CancelButton = buttonNo,
|
||||
ClientSize = new Size(Math.Max(300, label.Right + 10), 107),
|
||||
Controls = { label, buttonYes, buttonNo },
|
||||
FormBorderStyle = FormBorderStyle.FixedDialog,
|
||||
MinimizeBox = false,
|
||||
MaximizeBox = false,
|
||||
StartPosition = FormStartPosition.CenterScreen,
|
||||
Text = title
|
||||
};
|
||||
|
||||
DialogResult dialogResult = form.ShowDialog();
|
||||
return dialogResult;
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace ConfigGenerator {
|
||||
|
||||
internal EnhancedPropertyGrid(ASFConfig config) {
|
||||
if (config == null) {
|
||||
throw new ArgumentNullException("config");
|
||||
throw new ArgumentNullException(nameof(config));
|
||||
}
|
||||
|
||||
ASFConfig = config;
|
||||
@@ -53,22 +53,26 @@ namespace ConfigGenerator {
|
||||
|
||||
BotConfig botConfig = ASFConfig as BotConfig;
|
||||
if (botConfig != null) {
|
||||
if (botConfig.Enabled) {
|
||||
if (!botConfig.Enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
Tutorial.OnAction(Tutorial.EPhase.BotEnabled);
|
||||
if (!string.IsNullOrEmpty(botConfig.SteamLogin) && !string.IsNullOrEmpty(botConfig.SteamPassword)) {
|
||||
Tutorial.OnAction(Tutorial.EPhase.BotReady);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
GlobalConfig globalConfig = ASFConfig as GlobalConfig;
|
||||
if (globalConfig != null) {
|
||||
if (globalConfig == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (globalConfig.SteamOwnerID != 0) {
|
||||
Tutorial.OnAction(Tutorial.EPhase.GlobalConfigReady);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnGotFocus(EventArgs e) {
|
||||
if (e == null) {
|
||||
|
||||
@@ -25,11 +25,14 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace ConfigGenerator {
|
||||
[SuppressMessage("ReSharper", "AutoPropertyCanBeMadeGetOnly.Global"), SuppressMessage("ReSharper", "CollectionNeverQueried.Global"), SuppressMessage("ReSharper", "MemberCanBePrivate.Global"), SuppressMessage("ReSharper", "UnusedMember.Global")]
|
||||
internal sealed class GlobalConfig : ASFConfig {
|
||||
[SuppressMessage("ReSharper", "UnusedMember.Global")]
|
||||
internal enum EUpdateChannel : byte {
|
||||
Unknown,
|
||||
Stable,
|
||||
@@ -43,7 +46,7 @@ namespace ConfigGenerator {
|
||||
private const ProtocolType DefaultSteamProtocol = ProtocolType.Tcp;
|
||||
|
||||
// This is hardcoded blacklist which should not be possible to change
|
||||
internal static readonly HashSet<uint> GlobalBlacklist = new HashSet<uint> { 267420, 303700, 335590, 368020, 425280 };
|
||||
private static readonly HashSet<uint> GlobalBlacklist = new HashSet<uint> { 267420, 303700, 335590, 368020, 425280 };
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
public bool Debug { get; set; } = false;
|
||||
@@ -102,7 +105,6 @@ namespace ConfigGenerator {
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
public bool Statistics { get; set; } = true;
|
||||
|
||||
// TODO: Please remove me immediately after https://github.com/SteamRE/SteamKit/issues/254 gets fixed
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
public bool HackIgnoreMachineID { get; set; } = false;
|
||||
|
||||
@@ -161,20 +163,22 @@ namespace ConfigGenerator {
|
||||
globalConfig.HttpTimeout = DefaultHttpTimeout;
|
||||
}
|
||||
|
||||
if (globalConfig.WCFPort == 0) {
|
||||
if (globalConfig.WCFPort != 0) {
|
||||
return globalConfig;
|
||||
}
|
||||
|
||||
Logging.LogGenericWarning("Configured WCFPort is invalid: " + globalConfig.WCFPort + ". Value of " + DefaultWCFPort + " will be used instead");
|
||||
globalConfig.WCFPort = DefaultWCFPort;
|
||||
}
|
||||
|
||||
return globalConfig;
|
||||
}
|
||||
|
||||
// This constructor is used only by deserializer
|
||||
// ReSharper disable once UnusedMember.Local
|
||||
private GlobalConfig() { }
|
||||
|
||||
private GlobalConfig(string filePath) : base(filePath) {
|
||||
if (string.IsNullOrEmpty(filePath)) {
|
||||
throw new ArgumentNullException("filePath");
|
||||
throw new ArgumentNullException(nameof(filePath));
|
||||
}
|
||||
|
||||
Blacklist.AddRange(GlobalBlacklist);
|
||||
|
||||
@@ -23,9 +23,9 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Windows.Forms;
|
||||
using ConfigGenerator.Properties;
|
||||
|
||||
namespace ConfigGenerator {
|
||||
internal static class Logging {
|
||||
@@ -34,15 +34,7 @@ namespace ConfigGenerator {
|
||||
return;
|
||||
}
|
||||
|
||||
MessageBox.Show(message, "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
}
|
||||
|
||||
internal static void LogGenericWTF(string message, [CallerMemberName] string previousMethodName = "") {
|
||||
if (string.IsNullOrEmpty(message)) {
|
||||
return;
|
||||
}
|
||||
|
||||
MessageBox.Show(previousMethodName + "() " + message, "WTF", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
MessageBox.Show(message, Resources.Information, MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
}
|
||||
|
||||
internal static void LogGenericError(string message, [CallerMemberName] string previousMethodName = "") {
|
||||
@@ -50,18 +42,23 @@ namespace ConfigGenerator {
|
||||
return;
|
||||
}
|
||||
|
||||
MessageBox.Show(previousMethodName + "() " + message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
MessageBox.Show(previousMethodName + @"() " + message, Resources.Error, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
|
||||
internal static void LogGenericException(Exception exception, [CallerMemberName] string previousMethodName = "") {
|
||||
while (true) {
|
||||
if (exception == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
MessageBox.Show(previousMethodName + "() " + exception.Message + Environment.NewLine + exception.StackTrace, "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
MessageBox.Show(previousMethodName + @"() " + exception.Message + Environment.NewLine + exception.StackTrace, Resources.Exception, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
|
||||
if (exception.InnerException != null) {
|
||||
LogGenericException(exception.InnerException, previousMethodName);
|
||||
exception = exception.InnerException;
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,24 +67,7 @@ namespace ConfigGenerator {
|
||||
return;
|
||||
}
|
||||
|
||||
MessageBox.Show(previousMethodName + "() " + message, "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
}
|
||||
|
||||
internal static void LogNullError(string nullObjectName, [CallerMemberName] string previousMethodName = "") {
|
||||
if (string.IsNullOrEmpty(nullObjectName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
LogGenericError(nullObjectName + " is null!", previousMethodName);
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
internal static void LogGenericDebug(string message, [CallerMemberName] string previousMethodName = "") {
|
||||
if (string.IsNullOrEmpty(message)) {
|
||||
return;
|
||||
}
|
||||
|
||||
MessageBox.Show(previousMethodName + "() " + message, "Debug", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
MessageBox.Show(previousMethodName + @"() " + message, Resources.Warning, MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ using System;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows.Forms;
|
||||
|
||||
@@ -33,9 +34,9 @@ namespace ConfigGenerator {
|
||||
internal sealed partial class MainForm : Form {
|
||||
private const byte ReservedTabs = 3;
|
||||
|
||||
private readonly TabPage NewTab = new TabPage { Text = "+" };
|
||||
private readonly TabPage RemoveTab = new TabPage { Text = "-" };
|
||||
private readonly TabPage RenameTab = new TabPage { Text = "~" };
|
||||
private readonly TabPage NewTab = new TabPage { Text = @"+" };
|
||||
private readonly TabPage RemoveTab = new TabPage { Text = @"-" };
|
||||
private readonly TabPage RenameTab = new TabPage { Text = @"~" };
|
||||
|
||||
private ConfigPage ASFTab;
|
||||
private TabPage OldTab;
|
||||
@@ -45,7 +46,7 @@ namespace ConfigGenerator {
|
||||
}
|
||||
|
||||
private void MainForm_Load(object sender, EventArgs e) {
|
||||
if (sender == null || e == null) {
|
||||
if ((sender == null) || (e == null)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -53,7 +54,7 @@ namespace ConfigGenerator {
|
||||
|
||||
MainTab.TabPages.Add(ASFTab);
|
||||
|
||||
foreach (var configFile in Directory.EnumerateFiles(Program.ConfigDirectory, "*.json")) {
|
||||
foreach (string configFile in Directory.EnumerateFiles(Program.ConfigDirectory, "*.json")) {
|
||||
string botName = Path.GetFileNameWithoutExtension(configFile);
|
||||
switch (botName) {
|
||||
case Program.ASF:
|
||||
@@ -71,7 +72,7 @@ namespace ConfigGenerator {
|
||||
}
|
||||
|
||||
private void MainTab_Selected(object sender, TabControlEventArgs e) {
|
||||
if (sender == null || e == null) {
|
||||
if ((sender == null) || (e == null)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -151,12 +152,10 @@ namespace ConfigGenerator {
|
||||
// Get rid of any potential whitespaces in bot name
|
||||
input = Regex.Replace(input, @"\s+", "");
|
||||
|
||||
foreach (ASFConfig config in ASFConfig.ASFConfigs) {
|
||||
if (Path.GetFileNameWithoutExtension(config.FilePath).Equals(input)) {
|
||||
if (ASFConfig.ASFConfigs.Select(config => Path.GetFileNameWithoutExtension(config.FilePath)).Any(fileNameWithoutExtension => (fileNameWithoutExtension == null) || fileNameWithoutExtension.Equals(input))) {
|
||||
Logging.LogGenericError("Bot with such name exists already!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
input = Path.Combine(Program.ConfigDirectory, input + ".json");
|
||||
|
||||
@@ -170,7 +169,7 @@ namespace ConfigGenerator {
|
||||
}
|
||||
|
||||
private void MainTab_Deselecting(object sender, TabControlCancelEventArgs e) {
|
||||
if (sender == null || e == null) {
|
||||
if ((sender == null) || (e == null)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -178,7 +177,7 @@ namespace ConfigGenerator {
|
||||
}
|
||||
|
||||
private void MainForm_Shown(object sender, EventArgs e) {
|
||||
if (sender == null || e == null) {
|
||||
if ((sender == null) || (e == null)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -186,7 +185,7 @@ namespace ConfigGenerator {
|
||||
}
|
||||
|
||||
private void MainForm_HelpButtonClicked(object sender, CancelEventArgs e) {
|
||||
if (sender == null || e == null) {
|
||||
if ((sender == null) || (e == null)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -61,11 +61,13 @@ namespace ConfigGenerator {
|
||||
// Common structure is bin/(x64/)Debug/ArchiSteamFarm.exe, so we allow up to 4 directories up
|
||||
for (byte i = 0; i < 4; i++) {
|
||||
Directory.SetCurrentDirectory("..");
|
||||
if (Directory.Exists(ASFDirectory)) {
|
||||
if (!Directory.Exists(ASFDirectory)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Directory.SetCurrentDirectory(ASFDirectory);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If config directory doesn't exist after our adjustment, abort all of that
|
||||
if (!Directory.Exists(ConfigDirectory)) {
|
||||
@@ -73,14 +75,16 @@ namespace ConfigGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
if (!Directory.Exists(ConfigDirectory)) {
|
||||
if (Directory.Exists(ConfigDirectory)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Logging.LogGenericError("Config directory could not be found!");
|
||||
Environment.Exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
private static void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs args) {
|
||||
if (sender == null || args == null) {
|
||||
if ((sender == null) || (args == null)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -88,7 +92,7 @@ namespace ConfigGenerator {
|
||||
}
|
||||
|
||||
private static void UnobservedTaskExceptionHandler(object sender, UnobservedTaskExceptionEventArgs args) {
|
||||
if (sender == null || args == null) {
|
||||
if ((sender == null) || (args == null)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
|
||||
75
ConfigGenerator/Properties/Resources.Designer.cs
generated
75
ConfigGenerator/Properties/Resources.Designer.cs
generated
@@ -9,6 +9,7 @@
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace ConfigGenerator.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
@@ -37,7 +38,7 @@ namespace ConfigGenerator.Properties {
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if ((resourceMan == null)) {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ConfigGenerator.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
@@ -58,5 +59,77 @@ namespace ConfigGenerator.Properties {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Cancel.
|
||||
/// </summary>
|
||||
internal static string Cancel {
|
||||
get {
|
||||
return ResourceManager.GetString("Cancel", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Error.
|
||||
/// </summary>
|
||||
internal static string Error {
|
||||
get {
|
||||
return ResourceManager.GetString("Error", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Exception.
|
||||
/// </summary>
|
||||
internal static string Exception {
|
||||
get {
|
||||
return ResourceManager.GetString("Exception", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Information.
|
||||
/// </summary>
|
||||
internal static string Information {
|
||||
get {
|
||||
return ResourceManager.GetString("Information", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to No.
|
||||
/// </summary>
|
||||
internal static string No {
|
||||
get {
|
||||
return ResourceManager.GetString("No", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to OK.
|
||||
/// </summary>
|
||||
internal static string OK {
|
||||
get {
|
||||
return ResourceManager.GetString("OK", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Warning.
|
||||
/// </summary>
|
||||
internal static string Warning {
|
||||
get {
|
||||
return ResourceManager.GetString("Warning", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Yes.
|
||||
/// </summary>
|
||||
internal static string Yes {
|
||||
get {
|
||||
return ResourceManager.GetString("Yes", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,4 +114,28 @@
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="Information" xml:space="preserve">
|
||||
<value>Information</value>
|
||||
</data>
|
||||
<data name="Error" xml:space="preserve">
|
||||
<value>Error</value>
|
||||
</data>
|
||||
<data name="Exception" xml:space="preserve">
|
||||
<value>Exception</value>
|
||||
</data>
|
||||
<data name="Warning" xml:space="preserve">
|
||||
<value>Warning</value>
|
||||
</data>
|
||||
<data name="OK" xml:space="preserve">
|
||||
<value>OK</value>
|
||||
</data>
|
||||
<data name="Cancel" xml:space="preserve">
|
||||
<value>Cancel</value>
|
||||
</data>
|
||||
<data name="Yes" xml:space="preserve">
|
||||
<value>Yes</value>
|
||||
</data>
|
||||
<data name="No" xml:space="preserve">
|
||||
<value>No</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -38,12 +38,12 @@ namespace ConfigGenerator {
|
||||
GlobalConfigReady
|
||||
}
|
||||
|
||||
internal static bool Enabled { get; set; } = true;
|
||||
internal static bool Enabled { private get; set; } = true;
|
||||
|
||||
private static EPhase NextPhase = EPhase.Start;
|
||||
|
||||
internal static void OnAction(EPhase phase) {
|
||||
if (!Enabled || phase != NextPhase) {
|
||||
if (!Enabled || (phase != NextPhase)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user