mirror of
https://github.com/JustArchiNET/ArchiSteamFarm.git
synced 2025-12-16 14:30:31 +00:00
Compare commits
59 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d11e141ece | ||
|
|
9ff3834ed7 | ||
|
|
9806703cfa | ||
|
|
ca0857abd1 | ||
|
|
d32d3bfd36 | ||
|
|
6efb07eada | ||
|
|
2b28f01b1c | ||
|
|
fb350fe792 | ||
|
|
5e73d18cd2 | ||
|
|
3ff95995b9 | ||
|
|
17b2bc2259 | ||
|
|
4a36345635 | ||
|
|
e9d8f271a2 | ||
|
|
6c84f8eb4f | ||
|
|
54ad58a22d | ||
|
|
790e6baf46 | ||
|
|
c8fb715558 | ||
|
|
2ab5e6013d | ||
|
|
3e0c34e62c | ||
|
|
65b31e5537 | ||
|
|
62a6e38e47 | ||
|
|
0b50a45336 | ||
|
|
8d1d162b02 | ||
|
|
dbe13a1965 | ||
|
|
fc13633f5e | ||
|
|
d0cc10f3c6 | ||
|
|
567931a4cc | ||
|
|
396dc17ab2 | ||
|
|
288cc29338 | ||
|
|
844ca7da94 | ||
|
|
b14b9f87c7 | ||
|
|
8aa086cc27 | ||
|
|
cf00989d84 | ||
|
|
8f2f85282c | ||
|
|
fa12ffd9d0 | ||
|
|
ecb27adedd | ||
|
|
6e9be09944 | ||
|
|
6a79a89a10 | ||
|
|
d67be4f092 | ||
|
|
a8e1039e32 | ||
|
|
2ad9d9e197 | ||
|
|
fd6e2c72d7 | ||
|
|
1eed0f7647 | ||
|
|
c018c08260 | ||
|
|
72fa98cb89 | ||
|
|
71215d695e | ||
|
|
75b785d4b6 | ||
|
|
12e32692cb | ||
|
|
6158a9268d | ||
|
|
a48e53585a | ||
|
|
33383633ea | ||
|
|
3f7359c608 | ||
|
|
d8b59c6889 | ||
|
|
0f71b788cb | ||
|
|
d012255a21 | ||
|
|
8fc39a44cd | ||
|
|
c6fe424fcc | ||
|
|
12488dafd3 | ||
|
|
3b53491567 |
@@ -12,6 +12,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConfigGenerator", "ConfigGe
|
||||
{35AF7887-08B9-40E8-A5EA-797D8B60B30C} = {35AF7887-08B9-40E8-A5EA-797D8B60B30C}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GUI", "GUI\GUI.csproj", "{599121A9-5887-4522-A3D6-61470B90BAD4}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{35AF7887-08B9-40E8-A5EA-797D8B60B30C} = {35AF7887-08B9-40E8-A5EA-797D8B60B30C}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -30,6 +35,10 @@ Global
|
||||
{C3F6FE68-5E75-415E-BEA1-1E7C16D6A433}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C3F6FE68-5E75-415E-BEA1-1E7C16D6A433}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C3F6FE68-5E75-415E-BEA1-1E7C16D6A433}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{599121A9-5887-4522-A3D6-61470B90BAD4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{599121A9-5887-4522-A3D6-61470B90BAD4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{599121A9-5887-4522-A3D6-61470B90BAD4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{599121A9-5887-4522-A3D6-61470B90BAD4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -32,6 +32,16 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
internal sealed class ArchiHandler : ClientMsgHandler {
|
||||
private readonly Bot Bot;
|
||||
|
||||
internal ArchiHandler(Bot bot) {
|
||||
if (bot == null) {
|
||||
throw new ArgumentNullException("bot");
|
||||
}
|
||||
|
||||
Bot = bot;
|
||||
}
|
||||
|
||||
/*
|
||||
____ _ _ _ _
|
||||
/ ___| __ _ | || || |__ __ _ ___ | | __ ___
|
||||
@@ -257,10 +267,11 @@ namespace ArchiSteamFarm {
|
||||
request.Body.key = key;
|
||||
|
||||
Client.Send(request);
|
||||
|
||||
try {
|
||||
return await new AsyncJob<PurchaseResponseCallback>(Client, request.SourceJobID);
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(e);
|
||||
Logging.LogGenericException(e, Bot.BotName);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,21 +32,22 @@ using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
using System.Threading;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
internal sealed class ArchiWebHandler {
|
||||
private const string SteamCommunity = "steamcommunity.com";
|
||||
private const byte MinSessionTTL = 15; // Assume session is valid for at least that amount of seconds
|
||||
|
||||
private static string SteamCommunityURL = "https://" + SteamCommunity;
|
||||
|
||||
private static int Timeout = 30 * 1000;
|
||||
private static int Timeout = GlobalConfig.DefaultHttpTimeout * 1000;
|
||||
|
||||
private readonly Bot Bot;
|
||||
private readonly Dictionary<string, string> Cookie = new Dictionary<string, string>(4);
|
||||
private readonly SemaphoreSlim SessionSemaphore = new SemaphoreSlim(1);
|
||||
private readonly WebBrowser WebBrowser;
|
||||
|
||||
internal bool IsInitialized { get; private set; }
|
||||
|
||||
private ulong SteamID;
|
||||
private DateTime LastSessionRefreshCheck = DateTime.MinValue;
|
||||
|
||||
internal static void Init() {
|
||||
Timeout = Program.GlobalConfig.HttpTimeout * 1000;
|
||||
@@ -55,24 +56,22 @@ namespace ArchiSteamFarm {
|
||||
|
||||
internal ArchiWebHandler(Bot bot) {
|
||||
if (bot == null) {
|
||||
return;
|
||||
throw new ArgumentNullException("bot");
|
||||
}
|
||||
|
||||
Bot = bot;
|
||||
|
||||
WebBrowser = new WebBrowser(bot.BotName);
|
||||
}
|
||||
|
||||
internal void OnDisconnected() {
|
||||
IsInitialized = false;
|
||||
}
|
||||
|
||||
internal async Task<bool> Init(SteamClient steamClient, string webAPIUserNonce, string parentalPin) {
|
||||
if (steamClient == null || steamClient.SteamID == null || string.IsNullOrEmpty(webAPIUserNonce) || IsInitialized) {
|
||||
internal bool Init(SteamClient steamClient, string webAPIUserNonce, string parentalPin) {
|
||||
if (steamClient == null || steamClient.SteamID == null || string.IsNullOrEmpty(webAPIUserNonce)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SteamID = steamClient.SteamID;
|
||||
ulong steamID = steamClient.SteamID;
|
||||
|
||||
string sessionID = Convert.ToBase64String(Encoding.UTF8.GetBytes(SteamID.ToString()));
|
||||
string sessionID = Convert.ToBase64String(Encoding.UTF8.GetBytes(steamID.ToString()));
|
||||
|
||||
// Generate an AES session key
|
||||
byte[] sessionKey = CryptoHelper.GenerateRandomBlock(32);
|
||||
@@ -99,7 +98,7 @@ namespace ArchiSteamFarm {
|
||||
|
||||
try {
|
||||
authResult = iSteamUserAuth.AuthenticateUser(
|
||||
steamid: SteamID,
|
||||
steamid: steamID,
|
||||
sessionkey: Encoding.ASCII.GetString(WebUtility.UrlEncodeToBytes(cryptedSessionKey, 0, cryptedSessionKey.Length)),
|
||||
encrypted_loginkey: Encoding.ASCII.GetString(WebUtility.UrlEncodeToBytes(cryptedLoginKey, 0, cryptedLoginKey.Length)),
|
||||
method: WebRequestMethods.Http.Post,
|
||||
@@ -117,30 +116,26 @@ namespace ArchiSteamFarm {
|
||||
|
||||
Logging.LogGenericInfo("Success!", Bot.BotName);
|
||||
|
||||
string steamLogin = authResult["token"].AsString();
|
||||
string steamLoginSecure = authResult["tokensecure"].AsString();
|
||||
WebBrowser.CookieContainer.Add(new Cookie("sessionid", sessionID, "/", "." + SteamCommunity));
|
||||
|
||||
Cookie["sessionid"] = sessionID;
|
||||
Cookie["steamLogin"] = steamLogin;
|
||||
Cookie["steamLoginSecure"] = steamLoginSecure;
|
||||
string steamLogin = authResult["token"].Value;
|
||||
WebBrowser.CookieContainer.Add(new Cookie("steamLogin", steamLogin, "/", "." + SteamCommunity));
|
||||
|
||||
// The below is used for display purposes only
|
||||
Cookie["webTradeEligibility"] = "{\"allowed\":0,\"reason\":0,\"allowed_at_time\":0,\"steamguard_required_days\":0,\"sales_this_year\":0,\"max_sales_per_year\":0,\"forms_requested\":0}";
|
||||
string steamLoginSecure = authResult["tokensecure"].Value;
|
||||
WebBrowser.CookieContainer.Add(new Cookie("steamLoginSecure", steamLoginSecure, "/", "." + SteamCommunity));
|
||||
|
||||
await UnlockParentalAccount(parentalPin).ConfigureAwait(false);
|
||||
if (!UnlockParentalAccount(parentalPin).Result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
IsInitialized = true;
|
||||
LastSessionRefreshCheck = DateTime.Now;
|
||||
return true;
|
||||
}
|
||||
|
||||
internal async Task<bool?> IsLoggedIn() {
|
||||
if (SteamID == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HtmlDocument htmlDocument = null;
|
||||
for (byte i = 0; i < WebBrowser.MaxRetries && htmlDocument == null; i++) {
|
||||
htmlDocument = await WebBrowser.UrlGetToHtmlDocument(SteamCommunityURL + "/my/profile", Cookie).ConfigureAwait(false);
|
||||
htmlDocument = await WebBrowser.UrlGetToHtmlDocument(SteamCommunityURL + "/my/profile").ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (htmlDocument == null) {
|
||||
@@ -152,27 +147,46 @@ namespace ArchiSteamFarm {
|
||||
return htmlNode != null;
|
||||
}
|
||||
|
||||
internal async Task<bool> ReconnectIfNeeded() {
|
||||
bool? isLoggedIn = await IsLoggedIn().ConfigureAwait(false);
|
||||
if (isLoggedIn.HasValue && !isLoggedIn.Value) {
|
||||
Logging.LogGenericInfo("Reconnecting because our sessionID expired!", Bot.BotName);
|
||||
Bot.RestartIfRunning().Forget();
|
||||
internal async Task<bool> RefreshSessionIfNeeded() {
|
||||
DateTime now = DateTime.Now;
|
||||
if (now.Subtract(LastSessionRefreshCheck).TotalSeconds < MinSessionTTL) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
await SessionSemaphore.WaitAsync().ConfigureAwait(false);
|
||||
|
||||
now = DateTime.Now;
|
||||
if (now.Subtract(LastSessionRefreshCheck).TotalSeconds < MinSessionTTL) {
|
||||
SessionSemaphore.Release();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool result;
|
||||
|
||||
bool? isLoggedIn = await IsLoggedIn().ConfigureAwait(false);
|
||||
if (isLoggedIn.GetValueOrDefault(true)) {
|
||||
result = true;
|
||||
now = DateTime.Now;
|
||||
LastSessionRefreshCheck = now;
|
||||
} else {
|
||||
Logging.LogGenericInfo("Refreshing our session!", Bot.BotName);
|
||||
result = await Bot.RefreshSession().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
SessionSemaphore.Release();
|
||||
return result;
|
||||
}
|
||||
|
||||
internal async Task<Dictionary<uint, string>> GetOwnedGames() {
|
||||
if (SteamID == 0) {
|
||||
if (!await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
string request = SteamCommunityURL + "/profiles/" + SteamID + "/games/?xml=1";
|
||||
string request = SteamCommunityURL + "/my/games/?xml=1";
|
||||
|
||||
XmlDocument response = null;
|
||||
for (byte i = 0; i < WebBrowser.MaxRetries && response == null; i++) {
|
||||
response = await WebBrowser.UrlGetToXML(request, Cookie).ConfigureAwait(false);
|
||||
response = await WebBrowser.UrlGetToXML(request).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (response == null) {
|
||||
@@ -273,8 +287,13 @@ namespace ArchiSteamFarm {
|
||||
return false;
|
||||
}
|
||||
|
||||
string sessionID;
|
||||
if (!Cookie.TryGetValue("sessionid", out sessionID)) {
|
||||
if (!await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
string sessionID = WebBrowser.CookieContainer.GetCookieValue(SteamCommunityURL, "sessionid");
|
||||
if (string.IsNullOrEmpty(sessionID)) {
|
||||
Logging.LogNullError("sessionID");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -285,12 +304,12 @@ namespace ArchiSteamFarm {
|
||||
{"action", "join"}
|
||||
};
|
||||
|
||||
HttpResponseMessage response = null;
|
||||
for (byte i = 0; i < WebBrowser.MaxRetries && response == null; i++) {
|
||||
response = await WebBrowser.UrlPost(request, data, Cookie).ConfigureAwait(false);
|
||||
bool result = false;
|
||||
for (byte i = 0; i < WebBrowser.MaxRetries && !result; i++) {
|
||||
result = await WebBrowser.UrlPost(request, data).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (response == null) {
|
||||
if (!result) {
|
||||
Logging.LogGenericWTF("Request failed even after " + WebBrowser.MaxRetries + " tries", Bot.BotName);
|
||||
return false;
|
||||
}
|
||||
@@ -303,8 +322,13 @@ namespace ArchiSteamFarm {
|
||||
return false;
|
||||
}
|
||||
|
||||
string sessionID;
|
||||
if (!Cookie.TryGetValue("sessionid", out sessionID)) {
|
||||
if (!await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
string sessionID = WebBrowser.CookieContainer.GetCookieValue(SteamCommunityURL, "sessionid");
|
||||
if (string.IsNullOrEmpty(sessionID)) {
|
||||
Logging.LogNullError("sessionID");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -317,42 +341,12 @@ namespace ArchiSteamFarm {
|
||||
{"tradeofferid", tradeID.ToString()}
|
||||
};
|
||||
|
||||
HttpResponseMessage response = null;
|
||||
for (byte i = 0; i < WebBrowser.MaxRetries && response == null; i++) {
|
||||
response = await WebBrowser.UrlPost(request, data, Cookie, referer).ConfigureAwait(false);
|
||||
bool result = false;
|
||||
for (byte i = 0; i < WebBrowser.MaxRetries && !result; i++) {
|
||||
result = await WebBrowser.UrlPost(request, data, referer).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (response == null) {
|
||||
Logging.LogGenericWTF("Request failed even after " + WebBrowser.MaxRetries + " tries", Bot.BotName);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
internal bool DeclineTradeOffer(ulong tradeID) {
|
||||
if (tradeID == 0 || string.IsNullOrEmpty(Bot.BotConfig.SteamApiKey)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
KeyValue response = null;
|
||||
using (dynamic iEconService = WebAPI.GetInterface("IEconService", Bot.BotConfig.SteamApiKey)) {
|
||||
iEconService.Timeout = Timeout;
|
||||
|
||||
for (byte i = 0; i < WebBrowser.MaxRetries && response == null; i++) {
|
||||
try {
|
||||
response = iEconService.DeclineTradeOffer(
|
||||
tradeofferid: tradeID.ToString(),
|
||||
method: WebRequestMethods.Http.Post,
|
||||
secure: !Program.GlobalConfig.ForceHttp
|
||||
);
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(e, Bot.BotName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (response == null) {
|
||||
if (!result) {
|
||||
Logging.LogGenericWTF("Request failed even after " + WebBrowser.MaxRetries + " tries", Bot.BotName);
|
||||
return false;
|
||||
}
|
||||
@@ -361,9 +355,13 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
internal async Task<List<Steam.Item>> GetMyTradableInventory() {
|
||||
if (!await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
JObject jObject = null;
|
||||
for (byte i = 0; i < WebBrowser.MaxRetries && jObject == null; i++) {
|
||||
jObject = await WebBrowser.UrlGetToJObject(SteamCommunityURL + "/my/inventory/json/753/6?trading=1", Cookie).ConfigureAwait(false);
|
||||
jObject = await WebBrowser.UrlGetToJObject(SteamCommunityURL + "/my/inventory/json/753/6?trading=1").ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (jObject == null) {
|
||||
@@ -394,8 +392,13 @@ namespace ArchiSteamFarm {
|
||||
return false;
|
||||
}
|
||||
|
||||
string sessionID;
|
||||
if (!Cookie.TryGetValue("sessionid", out sessionID)) {
|
||||
if (!await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
string sessionID = WebBrowser.CookieContainer.GetCookieValue(SteamCommunityURL, "sessionid");
|
||||
if (string.IsNullOrEmpty(sessionID)) {
|
||||
Logging.LogNullError("sessionID");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -434,12 +437,12 @@ namespace ArchiSteamFarm {
|
||||
{"trade_offer_create_params", string.IsNullOrEmpty(token) ? "" : $"{{\"trade_offer_access_token\":\"{token}\"}}"}
|
||||
};
|
||||
|
||||
HttpResponseMessage response = null;
|
||||
for (byte i = 0; i < WebBrowser.MaxRetries && response == null; i++) {
|
||||
response = await WebBrowser.UrlPost(request, data, Cookie, referer).ConfigureAwait(false);
|
||||
bool result = false;
|
||||
for (byte i = 0; i < WebBrowser.MaxRetries && !result; i++) {
|
||||
result = await WebBrowser.UrlPost(request, data, referer).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (response == null) {
|
||||
if (!result) {
|
||||
Logging.LogGenericWTF("Request failed even after " + WebBrowser.MaxRetries + " tries", Bot.BotName);
|
||||
return false;
|
||||
}
|
||||
@@ -449,13 +452,17 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
internal async Task<HtmlDocument> GetBadgePage(byte page) {
|
||||
if (page == 0 || SteamID == 0) {
|
||||
if (page == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
HtmlDocument htmlDocument = null;
|
||||
for (byte i = 0; i < WebBrowser.MaxRetries && htmlDocument == null; i++) {
|
||||
htmlDocument = await WebBrowser.UrlGetToHtmlDocument(SteamCommunityURL + "/profiles/" + SteamID + "/badges?l=english&p=" + page, Cookie).ConfigureAwait(false);
|
||||
htmlDocument = await WebBrowser.UrlGetToHtmlDocument(SteamCommunityURL + "/my/badges?p=" + page).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (htmlDocument == null) {
|
||||
@@ -467,13 +474,17 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
internal async Task<HtmlDocument> GetGameCardsPage(ulong appID) {
|
||||
if (appID == 0 || SteamID == 0) {
|
||||
if (appID == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
HtmlDocument htmlDocument = null;
|
||||
for (byte i = 0; i < WebBrowser.MaxRetries && htmlDocument == null; i++) {
|
||||
htmlDocument = await WebBrowser.UrlGetToHtmlDocument(SteamCommunityURL + "/profiles/" + SteamID + "/gamecards/" + appID + "?l=english", Cookie).ConfigureAwait(false);
|
||||
htmlDocument = await WebBrowser.UrlGetToHtmlDocument(SteamCommunityURL + "/my/gamecards/" + appID).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (htmlDocument == null) {
|
||||
@@ -485,16 +496,16 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
internal async Task<bool> MarkInventory() {
|
||||
if (SteamID == 0) {
|
||||
if (!await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HttpResponseMessage response = null;
|
||||
for (byte i = 0; i < WebBrowser.MaxRetries && response == null; i++) {
|
||||
response = await WebBrowser.UrlGet(SteamCommunityURL + "/profiles/" + SteamID + "/inventory", Cookie).ConfigureAwait(false);
|
||||
bool result = false;
|
||||
for (byte i = 0; i < WebBrowser.MaxRetries && !result; i++) {
|
||||
result = await WebBrowser.UrlGet(SteamCommunityURL + "/my/inventory").ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (response == null) {
|
||||
if (!result) {
|
||||
Logging.LogGenericWTF("Request failed even after " + WebBrowser.MaxRetries + " tries", Bot.BotName);
|
||||
return false;
|
||||
}
|
||||
@@ -507,8 +518,13 @@ namespace ArchiSteamFarm {
|
||||
return false;
|
||||
}
|
||||
|
||||
string sessionID;
|
||||
if (!Cookie.TryGetValue("sessionid", out sessionID)) {
|
||||
if (!await RefreshSessionIfNeeded().ConfigureAwait(false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
string sessionID = WebBrowser.CookieContainer.GetCookieValue(SteamCommunityURL, "sessionid");
|
||||
if (string.IsNullOrEmpty(sessionID)) {
|
||||
Logging.LogNullError("sessionID");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -517,12 +533,12 @@ namespace ArchiSteamFarm {
|
||||
{ "sessionid", sessionID }
|
||||
};
|
||||
|
||||
HttpResponseMessage response = null;
|
||||
for (byte i = 0; i < WebBrowser.MaxRetries && response == null; i++) {
|
||||
response = await WebBrowser.UrlPost(request, data, Cookie).ConfigureAwait(false);
|
||||
bool result = false;
|
||||
for (byte i = 0; i < WebBrowser.MaxRetries && !result; i++) {
|
||||
result = await WebBrowser.UrlPost(request, data).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (response == null) {
|
||||
if (!result) {
|
||||
Logging.LogGenericWTF("Request failed even after " + WebBrowser.MaxRetries + " tries", Bot.BotName);
|
||||
return false;
|
||||
}
|
||||
@@ -530,9 +546,9 @@ namespace ArchiSteamFarm {
|
||||
return true;
|
||||
}
|
||||
|
||||
private async Task UnlockParentalAccount(string parentalPin) {
|
||||
private async Task<bool> UnlockParentalAccount(string parentalPin) {
|
||||
if (string.IsNullOrEmpty(parentalPin) || parentalPin.Equals("0")) {
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
Logging.LogGenericInfo("Unlocking parental account...", Bot.BotName);
|
||||
@@ -543,40 +559,18 @@ namespace ArchiSteamFarm {
|
||||
string referer = SteamCommunityURL;
|
||||
string request = referer + "/parental/ajaxunlock";
|
||||
|
||||
HttpResponseMessage response = null;
|
||||
for (byte i = 0; i < WebBrowser.MaxRetries && response == null; i++) {
|
||||
response = await WebBrowser.UrlPost(request, data, Cookie, referer).ConfigureAwait(false);
|
||||
bool result = false;
|
||||
for (byte i = 0; i < WebBrowser.MaxRetries && !result; i++) {
|
||||
result = await WebBrowser.UrlPost(request, data, referer).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (response == null) {
|
||||
if (!result) {
|
||||
Logging.LogGenericWTF("Request failed even after " + WebBrowser.MaxRetries + " tries", Bot.BotName);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
IEnumerable<string> setCookieValues;
|
||||
if (!response.Headers.TryGetValues("Set-Cookie", out setCookieValues)) {
|
||||
Logging.LogNullError("setCookieValues", Bot.BotName);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (string setCookieValue in setCookieValues) {
|
||||
if (!setCookieValue.Contains("steamparental=")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
string setCookie = setCookieValue.Substring(setCookieValue.IndexOf("steamparental=", StringComparison.Ordinal) + 14);
|
||||
|
||||
int index = setCookie.IndexOf(';');
|
||||
if (index > 0) {
|
||||
setCookie = setCookie.Substring(0, index);
|
||||
}
|
||||
|
||||
Cookie["steamparental"] = setCookie;
|
||||
Logging.LogGenericInfo("Success!", Bot.BotName);
|
||||
return;
|
||||
}
|
||||
|
||||
Logging.LogGenericWarning("Failed to unlock parental account!", Bot.BotName);
|
||||
Logging.LogGenericInfo("Success!", Bot.BotName);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ namespace ArchiSteamFarm {
|
||||
internal sealed class Bot {
|
||||
private const ulong ArchiSCFarmGroup = 103582791440160998;
|
||||
private const ushort CallbackSleep = 500; // In miliseconds
|
||||
private const ushort MaxSteamMessageLength = 2048;
|
||||
|
||||
internal static readonly Dictionary<string, Bot> Bots = new Dictionary<string, Bot>();
|
||||
|
||||
@@ -63,7 +64,7 @@ namespace ArchiSteamFarm {
|
||||
internal bool KeepRunning { get; private set; }
|
||||
|
||||
private bool InvalidPassword, LoggedInElsewhere;
|
||||
private string AuthCode, TwoFactorAuth;
|
||||
private string AuthCode, TwoFactorCode;
|
||||
|
||||
internal static async Task RefreshCMs(uint cellID) {
|
||||
bool initialized = false;
|
||||
@@ -106,7 +107,7 @@ namespace ArchiSteamFarm {
|
||||
|
||||
internal Bot(string botName) {
|
||||
if (string.IsNullOrEmpty(botName)) {
|
||||
return;
|
||||
throw new ArgumentNullException("botName");
|
||||
}
|
||||
|
||||
BotName = botName;
|
||||
@@ -163,7 +164,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
}
|
||||
|
||||
ArchiHandler = new ArchiHandler();
|
||||
ArchiHandler = new ArchiHandler(this);
|
||||
SteamClient.AddHandler(ArchiHandler);
|
||||
|
||||
CallbackManager = new CallbackManager(SteamClient);
|
||||
@@ -187,6 +188,7 @@ namespace ArchiSteamFarm {
|
||||
CallbackManager.Subscribe<SteamUser.LoggedOnCallback>(OnLoggedOn);
|
||||
CallbackManager.Subscribe<SteamUser.LoginKeyCallback>(OnLoginKey);
|
||||
CallbackManager.Subscribe<SteamUser.UpdateMachineAuthCallback>(OnMachineAuth);
|
||||
CallbackManager.Subscribe<SteamUser.WebAPIUserNonceCallback>(OnWebAPIUserNonce);
|
||||
|
||||
CallbackManager.Subscribe<ArchiHandler.NotificationsCallback>(OnNotifications);
|
||||
CallbackManager.Subscribe<ArchiHandler.OfflineMessageCallback>(OnOfflineMessage);
|
||||
@@ -196,16 +198,16 @@ namespace ArchiSteamFarm {
|
||||
CardsFarmer = new CardsFarmer(this);
|
||||
Trading = new Trading(this);
|
||||
|
||||
if (BotConfig.AcceptConfirmationsPeriod > 0) {
|
||||
if (AcceptConfirmationsTimer == null && BotConfig.AcceptConfirmationsPeriod > 0) {
|
||||
AcceptConfirmationsTimer = new Timer(
|
||||
async e => await AcceptConfirmations().ConfigureAwait(false),
|
||||
async e => await AcceptConfirmations(true).ConfigureAwait(false),
|
||||
null,
|
||||
TimeSpan.FromMinutes(BotConfig.AcceptConfirmationsPeriod), // Delay
|
||||
TimeSpan.FromMinutes(BotConfig.AcceptConfirmationsPeriod) // Period
|
||||
);
|
||||
}
|
||||
|
||||
if (BotConfig.SendTradePeriod > 0) {
|
||||
if (SendItemsTimer == null && BotConfig.SendTradePeriod > 0) {
|
||||
SendItemsTimer = new Timer(
|
||||
async e => await ResponseSendTrade(BotConfig.SteamMasterID).ConfigureAwait(false),
|
||||
null,
|
||||
@@ -222,7 +224,7 @@ namespace ArchiSteamFarm {
|
||||
Start().Forget();
|
||||
}
|
||||
|
||||
internal async Task AcceptConfirmations(Confirmation.ConfirmationType allowedConfirmationType = Confirmation.ConfirmationType.Unknown) {
|
||||
internal async Task AcceptConfirmations(bool confirm, Confirmation.ConfirmationType allowedConfirmationType = Confirmation.ConfirmationType.Unknown) {
|
||||
if (BotDatabase.SteamGuardAccount == null) {
|
||||
return;
|
||||
}
|
||||
@@ -242,10 +244,14 @@ namespace ArchiSteamFarm {
|
||||
continue;
|
||||
}
|
||||
|
||||
BotDatabase.SteamGuardAccount.AcceptConfirmation(confirmation);
|
||||
if (confirm) {
|
||||
BotDatabase.SteamGuardAccount.AcceptConfirmation(confirmation);
|
||||
} else {
|
||||
BotDatabase.SteamGuardAccount.DenyConfirmation(confirmation);
|
||||
}
|
||||
}
|
||||
} catch (SteamGuardAccount.WGTokenInvalidException) {
|
||||
Logging.LogGenericWarning("Accepting confirmation: Failed!", BotName);
|
||||
Logging.LogGenericWarning("Handling confirmation: Failed!", BotName);
|
||||
Logging.LogGenericWarning("Confirmation could not be accepted because of invalid token exception", BotName);
|
||||
Logging.LogGenericWarning("If issue persists, consider removing and readding ASF 2FA", BotName);
|
||||
} catch (Exception e) {
|
||||
@@ -261,12 +267,32 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
}
|
||||
|
||||
internal async Task RestartIfRunning() {
|
||||
internal async Task<bool> RefreshSession() {
|
||||
if (!SteamClient.IsConnected) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
await Start().ConfigureAwait(false);
|
||||
SteamUser.WebAPIUserNonceCallback callback;
|
||||
|
||||
try {
|
||||
callback = await SteamUser.RequestWebAPIUserNonce();
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(e, BotName);
|
||||
Start().Forget();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (callback == null || callback.Result != EResult.OK || string.IsNullOrEmpty(callback.Nonce)) {
|
||||
Start().Forget();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ArchiWebHandler.Init(SteamClient, callback.Nonce, BotConfig.SteamParentalPIN)) {
|
||||
Start().Forget();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
internal async Task OnFarmingFinished(bool farmedSomething) {
|
||||
@@ -285,17 +311,19 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
if (!message.StartsWith("!")) {
|
||||
return await ResponseRedeem(steamID, BotName, message, true).ConfigureAwait(false);
|
||||
return await ResponseRedeem(steamID, message.Replace(",", Environment.NewLine), true).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (!message.Contains(" ")) {
|
||||
switch (message) {
|
||||
case "!2fa":
|
||||
return Response2FA(steamID);
|
||||
case "!2fano":
|
||||
return await Response2FAConfirm(steamID, false).ConfigureAwait(false);
|
||||
case "!2faoff":
|
||||
return Response2FAOff(steamID);
|
||||
case "!2faok":
|
||||
return await Response2FAOK(steamID).ConfigureAwait(false);
|
||||
return await Response2FAConfirm(steamID, true).ConfigureAwait(false);
|
||||
case "!exit":
|
||||
return ResponseExit(steamID);
|
||||
case "!farm":
|
||||
@@ -326,10 +354,12 @@ namespace ArchiSteamFarm {
|
||||
switch (args[0]) {
|
||||
case "!2fa":
|
||||
return Response2FA(steamID, args[1]);
|
||||
case "!2fano":
|
||||
return await Response2FAConfirm(steamID, args[1], false).ConfigureAwait(false);
|
||||
case "!2faoff":
|
||||
return Response2FAOff(steamID, args[1]);
|
||||
case "!2faok":
|
||||
return await Response2FAOK(steamID, args[1]).ConfigureAwait(false);
|
||||
return await Response2FAConfirm(steamID, args[1], true).ConfigureAwait(false);
|
||||
case "!addlicense":
|
||||
if (args.Length > 2) {
|
||||
return await ResponseAddLicense(steamID, args[1], args[2]).ConfigureAwait(false);
|
||||
@@ -358,9 +388,9 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
case "!redeem":
|
||||
if (args.Length > 2) {
|
||||
return await ResponseRedeem(steamID, args[1], args[2], false).ConfigureAwait(false);
|
||||
return await ResponseRedeem(steamID, args[1], args[2].Replace(",", Environment.NewLine), false).ConfigureAwait(false);
|
||||
} else {
|
||||
return await ResponseRedeem(steamID, BotName, args[1], false).ConfigureAwait(false);
|
||||
return await ResponseRedeem(steamID, BotName, args[1].Replace(",", Environment.NewLine), false).ConfigureAwait(false);
|
||||
}
|
||||
case "!start":
|
||||
return await ResponseStart(steamID, args[1]).ConfigureAwait(false);
|
||||
@@ -381,7 +411,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
// 2FA tokens are expiring soon, use limiter only when we don't have any pending
|
||||
if (TwoFactorAuth == null) {
|
||||
if (TwoFactorCode == null) {
|
||||
await Program.LimitSteamRequestsAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@@ -432,7 +462,9 @@ namespace ArchiSteamFarm {
|
||||
// But here we're dealing with WinAuth authenticator
|
||||
Logging.LogGenericInfo("ASF requires a few more steps to complete authenticator import...", BotName);
|
||||
|
||||
InitializeLoginAndPassword();
|
||||
if (!InitializeLoginAndPassword()) {
|
||||
return;
|
||||
}
|
||||
|
||||
UserLogin userLogin = new UserLogin(BotConfig.SteamLogin, BotConfig.SteamPassword);
|
||||
LoginResult loginResult;
|
||||
@@ -440,6 +472,9 @@ namespace ArchiSteamFarm {
|
||||
switch (loginResult) {
|
||||
case LoginResult.Need2FA:
|
||||
userLogin.TwoFactorCode = Program.GetUserInput(Program.EUserInputType.TwoFactorAuthentication, BotName);
|
||||
if (string.IsNullOrEmpty(userLogin.TwoFactorCode)) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Logging.LogGenericError("Unhandled situation: " + loginResult, BotName);
|
||||
@@ -560,7 +595,7 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
if (await ArchiWebHandler.SendTradeOffer(inventory, BotConfig.SteamMasterID, BotConfig.SteamTradeToken).ConfigureAwait(false)) {
|
||||
await AcceptConfirmations(Confirmation.ConfirmationType.Trade).ConfigureAwait(false);
|
||||
await AcceptConfirmations(true, Confirmation.ConfirmationType.Trade).ConfigureAwait(false);
|
||||
return "Trade offer sent successfully!";
|
||||
} else {
|
||||
return "Trade offer failed due to error!";
|
||||
@@ -635,7 +670,7 @@ namespace ArchiSteamFarm {
|
||||
return bot.Response2FAOff(steamID);
|
||||
}
|
||||
|
||||
private async Task<string> Response2FAOK(ulong steamID) {
|
||||
private async Task<string> Response2FAConfirm(ulong steamID, bool confirm) {
|
||||
if (steamID == 0 || !IsMaster(steamID)) {
|
||||
return null;
|
||||
}
|
||||
@@ -644,11 +679,11 @@ namespace ArchiSteamFarm {
|
||||
return "That bot doesn't have ASF 2FA enabled!";
|
||||
}
|
||||
|
||||
await AcceptConfirmations().ConfigureAwait(false);
|
||||
await AcceptConfirmations(confirm).ConfigureAwait(false);
|
||||
return "Done!";
|
||||
}
|
||||
|
||||
private static async Task<string> Response2FAOK(ulong steamID, string botName) {
|
||||
private static async Task<string> Response2FAConfirm(ulong steamID, string botName, bool confirm) {
|
||||
if (steamID == 0 || string.IsNullOrEmpty(botName)) {
|
||||
return null;
|
||||
}
|
||||
@@ -658,7 +693,7 @@ namespace ArchiSteamFarm {
|
||||
return "Couldn't find any bot named " + botName + "!";
|
||||
}
|
||||
|
||||
return await bot.Response2FAOK(steamID).ConfigureAwait(false);
|
||||
return await bot.Response2FAConfirm(steamID, confirm).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private static string ResponseExit(ulong steamID) {
|
||||
@@ -670,8 +705,13 @@ namespace ArchiSteamFarm {
|
||||
return null;
|
||||
}
|
||||
|
||||
Environment.Exit(0);
|
||||
return null;
|
||||
// Schedule the task after some time so user can receive response
|
||||
Task.Run(async () => {
|
||||
await Utilities.SleepAsync(1000).ConfigureAwait(false);
|
||||
Program.Exit();
|
||||
}).Forget();
|
||||
|
||||
return "Done!";
|
||||
}
|
||||
|
||||
private string ResponseFarm(ulong steamID) {
|
||||
@@ -727,130 +767,82 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
StringBuilder response = new StringBuilder();
|
||||
using (StringReader reader = new StringReader(message)) {
|
||||
using (StringReader reader = new StringReader(message))
|
||||
using (IEnumerator<Bot> iterator = Bots.Values.GetEnumerator()) {
|
||||
string key = reader.ReadLine();
|
||||
IEnumerator<Bot> iterator = Bots.Values.GetEnumerator();
|
||||
Bot currentBot = this;
|
||||
while (key != null) {
|
||||
if (currentBot == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
while (!string.IsNullOrEmpty(key) && currentBot != null) {
|
||||
if (validate && !IsValidCdKey(key)) {
|
||||
key = reader.ReadLine();
|
||||
continue;
|
||||
key = reader.ReadLine(); // Next key
|
||||
continue; // Without changing the bot
|
||||
}
|
||||
|
||||
ArchiHandler.PurchaseResponseCallback result;
|
||||
try {
|
||||
result = await currentBot.ArchiHandler.RedeemKey(key).ConfigureAwait(false);
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(e, currentBot.BotName);
|
||||
break;
|
||||
if (currentBot.SteamClient.IsConnected) {
|
||||
ArchiHandler.PurchaseResponseCallback result = await currentBot.ArchiHandler.RedeemKey(key).ConfigureAwait(false);
|
||||
if (result != null) {
|
||||
switch (result.PurchaseResult) {
|
||||
case ArchiHandler.PurchaseResponseCallback.EPurchaseResult.DuplicatedKey:
|
||||
case ArchiHandler.PurchaseResponseCallback.EPurchaseResult.InvalidKey:
|
||||
case ArchiHandler.PurchaseResponseCallback.EPurchaseResult.OK:
|
||||
response.Append(Environment.NewLine + "<" + currentBot.BotName + "> Key: " + key + " | Status: " + result.PurchaseResult + " | Items: " + string.Join("", result.Items));
|
||||
|
||||
key = reader.ReadLine(); // Next key
|
||||
break; // Next bot (if needed)
|
||||
case ArchiHandler.PurchaseResponseCallback.EPurchaseResult.AlreadyOwned:
|
||||
case ArchiHandler.PurchaseResponseCallback.EPurchaseResult.BaseGameRequired:
|
||||
case ArchiHandler.PurchaseResponseCallback.EPurchaseResult.OnCooldown:
|
||||
case ArchiHandler.PurchaseResponseCallback.EPurchaseResult.RegionLocked:
|
||||
response.Append(Environment.NewLine + "<" + currentBot.BotName + "> Key: " + key + " | Status: " + result.PurchaseResult + " | Items: " + string.Join("", result.Items));
|
||||
|
||||
if (!BotConfig.ForwardKeysToOtherBots) {
|
||||
key = reader.ReadLine(); // Next key
|
||||
break; // Next bot (if needed)
|
||||
}
|
||||
|
||||
if (BotConfig.DistributeKeys) {
|
||||
break; // Next bot, without changing key
|
||||
}
|
||||
|
||||
bool alreadyHandled = false;
|
||||
foreach (Bot bot in Bots.Values) {
|
||||
if (bot == this || !bot.SteamClient.IsConnected) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ArchiHandler.PurchaseResponseCallback otherResult = await bot.ArchiHandler.RedeemKey(key).ConfigureAwait(false);
|
||||
if (otherResult == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (otherResult.PurchaseResult) {
|
||||
case ArchiHandler.PurchaseResponseCallback.EPurchaseResult.DuplicatedKey:
|
||||
case ArchiHandler.PurchaseResponseCallback.EPurchaseResult.InvalidKey:
|
||||
case ArchiHandler.PurchaseResponseCallback.EPurchaseResult.OK:
|
||||
alreadyHandled = true; // This key is already handled, as we either redeemed it or we're sure it's dupe/invalid
|
||||
break;
|
||||
}
|
||||
|
||||
response.Append(Environment.NewLine + "<" + bot.BotName + "> Key: " + key + " | Status: " + otherResult.PurchaseResult + " | Items: " + string.Join("", otherResult.Items));
|
||||
|
||||
if (alreadyHandled) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
key = reader.ReadLine(); // Next key
|
||||
break; // Next bot (if needed)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
var purchaseResult = result.PurchaseResult;
|
||||
var items = result.Items;
|
||||
|
||||
switch (purchaseResult) {
|
||||
case ArchiHandler.PurchaseResponseCallback.EPurchaseResult.AlreadyOwned:
|
||||
case ArchiHandler.PurchaseResponseCallback.EPurchaseResult.BaseGameRequired:
|
||||
case ArchiHandler.PurchaseResponseCallback.EPurchaseResult.OnCooldown:
|
||||
case ArchiHandler.PurchaseResponseCallback.EPurchaseResult.RegionLocked:
|
||||
response.Append(Environment.NewLine + "<" + currentBot.BotName + "> Key: " + key + " | Status: " + purchaseResult + " | Items: " + string.Join("", items));
|
||||
if (BotConfig.DistributeKeys) {
|
||||
do {
|
||||
if (iterator.MoveNext()) {
|
||||
currentBot = iterator.Current;
|
||||
} else {
|
||||
currentBot = null;
|
||||
}
|
||||
} while (currentBot == this);
|
||||
|
||||
if (!BotConfig.ForwardKeysToOtherBots) {
|
||||
key = reader.ReadLine();
|
||||
}
|
||||
break;
|
||||
if (BotConfig.DistributeKeys) {
|
||||
do {
|
||||
if (iterator.MoveNext()) {
|
||||
currentBot = iterator.Current;
|
||||
} else {
|
||||
currentBot = null;
|
||||
}
|
||||
|
||||
if (!BotConfig.ForwardKeysToOtherBots) {
|
||||
key = reader.ReadLine();
|
||||
break;
|
||||
}
|
||||
|
||||
bool alreadyHandled = false;
|
||||
foreach (Bot bot in Bots.Values) {
|
||||
if (alreadyHandled) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (bot == this) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ArchiHandler.PurchaseResponseCallback otherResult;
|
||||
try {
|
||||
otherResult = await bot.ArchiHandler.RedeemKey(key).ConfigureAwait(false);
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(e, bot.BotName);
|
||||
break; // We're done with this key
|
||||
}
|
||||
|
||||
if (otherResult == null) {
|
||||
break; // We're done with this key
|
||||
}
|
||||
|
||||
var otherPurchaseResult = otherResult.PurchaseResult;
|
||||
var otherItems = otherResult.Items;
|
||||
|
||||
switch (otherPurchaseResult) {
|
||||
case ArchiHandler.PurchaseResponseCallback.EPurchaseResult.OK:
|
||||
alreadyHandled = true; // We're done with this key
|
||||
response.Append(Environment.NewLine + "<" + bot.BotName + "> Key: " + key + " | Status: " + otherPurchaseResult + " | Items: " + string.Join("", otherItems));
|
||||
break;
|
||||
case ArchiHandler.PurchaseResponseCallback.EPurchaseResult.DuplicatedKey:
|
||||
case ArchiHandler.PurchaseResponseCallback.EPurchaseResult.InvalidKey:
|
||||
alreadyHandled = true; // This key doesn't work, don't try to redeem it anymore
|
||||
response.Append(Environment.NewLine + "<" + bot.BotName + "> Key: " + key + " | Status: " + otherPurchaseResult + " | Items: " + string.Join("", otherItems));
|
||||
break;
|
||||
default:
|
||||
response.Append(Environment.NewLine + "<" + bot.BotName + "> Key: " + key + " | Status: " + otherPurchaseResult + " | Items: " + string.Join("", otherItems));
|
||||
break;
|
||||
}
|
||||
}
|
||||
key = reader.ReadLine();
|
||||
break;
|
||||
case ArchiHandler.PurchaseResponseCallback.EPurchaseResult.OK:
|
||||
response.Append(Environment.NewLine + "<" + currentBot.BotName + "> Key: " + key + " | Status: " + purchaseResult + " | Items: " + string.Join("", items));
|
||||
if (BotConfig.DistributeKeys) {
|
||||
do {
|
||||
if (iterator.MoveNext()) {
|
||||
currentBot = iterator.Current;
|
||||
} else {
|
||||
currentBot = null;
|
||||
}
|
||||
} while (currentBot == this);
|
||||
}
|
||||
key = reader.ReadLine();
|
||||
break;
|
||||
case ArchiHandler.PurchaseResponseCallback.EPurchaseResult.DuplicatedKey:
|
||||
case ArchiHandler.PurchaseResponseCallback.EPurchaseResult.InvalidKey:
|
||||
response.Append(Environment.NewLine + "<" + currentBot.BotName + "> Key: " + key + " | Status: " + purchaseResult + " | Items: " + string.Join("", items));
|
||||
if (BotConfig.DistributeKeys && !BotConfig.ForwardKeysToOtherBots) {
|
||||
do {
|
||||
if (iterator.MoveNext()) {
|
||||
currentBot = iterator.Current;
|
||||
} else {
|
||||
currentBot = null;
|
||||
}
|
||||
} while (currentBot == this);
|
||||
}
|
||||
key = reader.ReadLine();
|
||||
break;
|
||||
} while (currentBot == this || (currentBot != null && !currentBot.SteamClient.IsConnected));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -900,8 +892,13 @@ namespace ArchiSteamFarm {
|
||||
return null;
|
||||
}
|
||||
|
||||
Program.Restart();
|
||||
return null;
|
||||
// Schedule the task after some time so user can receive response
|
||||
Task.Run(async () => {
|
||||
await Utilities.SleepAsync(1000).ConfigureAwait(false);
|
||||
Program.Restart();
|
||||
}).Forget();
|
||||
|
||||
return "Done!";
|
||||
}
|
||||
|
||||
private async Task<string> ResponseAddLicense(ulong steamID, HashSet<uint> gameIDs) {
|
||||
@@ -911,11 +908,8 @@ namespace ArchiSteamFarm {
|
||||
|
||||
StringBuilder result = new StringBuilder();
|
||||
foreach (uint gameID in gameIDs) {
|
||||
SteamApps.FreeLicenseCallback callback;
|
||||
try {
|
||||
callback = await SteamApps.RequestFreeLicense(gameID);
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(e, BotName);
|
||||
SteamApps.FreeLicenseCallback callback = await SteamApps.RequestFreeLicense(gameID);
|
||||
if (callback == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -953,8 +947,8 @@ namespace ArchiSteamFarm {
|
||||
return await bot.ResponseAddLicense(steamID, gamesToRedeem).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task<string> ResponseOwns(ulong steamID, string games) {
|
||||
if (steamID == 0 || string.IsNullOrEmpty(games) || !IsMaster(steamID)) {
|
||||
private async Task<string> ResponseOwns(ulong steamID, string query) {
|
||||
if (steamID == 0 || string.IsNullOrEmpty(query) || !IsMaster(steamID)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -963,37 +957,42 @@ namespace ArchiSteamFarm {
|
||||
return "List of owned games is empty!";
|
||||
}
|
||||
|
||||
// Check if this is uint
|
||||
uint appID;
|
||||
if (uint.TryParse(games, out appID)) {
|
||||
string ownedName;
|
||||
if (ownedGames.TryGetValue(appID, out ownedName)) {
|
||||
return "Owned already: " + appID + " | " + ownedName;
|
||||
} else {
|
||||
return "Not owned yet: " + appID;
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder response = new StringBuilder();
|
||||
|
||||
// This is a string
|
||||
foreach (KeyValuePair<uint, string> game in ownedGames) {
|
||||
if (game.Value.IndexOf(games, StringComparison.OrdinalIgnoreCase) < 0) {
|
||||
string[] games = query.Split(',');
|
||||
foreach (string game in games) {
|
||||
// Check if this is appID
|
||||
uint appID;
|
||||
if (uint.TryParse(game, out appID)) {
|
||||
string ownedName;
|
||||
if (ownedGames.TryGetValue(appID, out ownedName)) {
|
||||
response.Append(Environment.NewLine + "Owned already: " + appID + " | " + ownedName);
|
||||
} else {
|
||||
response.Append(Environment.NewLine + "Not owned yet: " + appID);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
response.AppendLine(Environment.NewLine + "Owned already: " + game.Key + " | " + game.Value);
|
||||
// This is a string, so check our entire library
|
||||
foreach (KeyValuePair<uint, string> ownedGame in ownedGames) {
|
||||
if (ownedGame.Value.IndexOf(game, StringComparison.OrdinalIgnoreCase) < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
response.Append(Environment.NewLine + "Owned already: " + ownedGame.Key + " | " + ownedGame.Value);
|
||||
}
|
||||
}
|
||||
|
||||
if (response.Length > 0) {
|
||||
return response.ToString();
|
||||
} else {
|
||||
return "Not owned yet: " + games;
|
||||
return "Not owned yet: " + query;
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task<string> ResponseOwns(ulong steamID, string botName, string games) {
|
||||
if (steamID == 0 || string.IsNullOrEmpty(botName) || string.IsNullOrEmpty(games)) {
|
||||
private static async Task<string> ResponseOwns(ulong steamID, string botName, string query) {
|
||||
if (steamID == 0 || string.IsNullOrEmpty(botName) || string.IsNullOrEmpty(query)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1002,7 +1001,7 @@ namespace ArchiSteamFarm {
|
||||
return "Couldn't find any bot named " + botName + "!";
|
||||
}
|
||||
|
||||
return await bot.ResponseOwns(steamID, games).ConfigureAwait(false);
|
||||
return await bot.ResponseOwns(steamID, query).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task<string> ResponsePlay(ulong steamID, HashSet<uint> gameIDs) {
|
||||
@@ -1129,7 +1128,11 @@ namespace ArchiSteamFarm {
|
||||
private void HandleCallbacks() {
|
||||
TimeSpan timeSpan = TimeSpan.FromMilliseconds(CallbackSleep);
|
||||
while (KeepRunning || SteamClient.IsConnected) {
|
||||
CallbackManager.RunWaitCallbacks(timeSpan);
|
||||
try {
|
||||
CallbackManager.RunWaitCallbacks(timeSpan);
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(e, BotName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1147,9 +1150,31 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
if (new SteamID(steamID).IsChatAccount) {
|
||||
SteamFriends.SendChatRoomMessage(steamID, EChatEntryType.ChatMsg, message);
|
||||
SendMessageToChannel(steamID, message);
|
||||
} else {
|
||||
SteamFriends.SendChatMessage(steamID, EChatEntryType.ChatMsg, message);
|
||||
SendMessageToUser(steamID, message);
|
||||
}
|
||||
}
|
||||
|
||||
private void SendMessageToChannel(ulong steamID, string message) {
|
||||
if (steamID == 0 || string.IsNullOrEmpty(message)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < message.Length; i += MaxSteamMessageLength - 6) {
|
||||
string messagePart = (i > 0 ? "..." : "") + message.Substring(i, Math.Min(MaxSteamMessageLength - 6, message.Length - i)) + (MaxSteamMessageLength - 6 < message.Length - i ? "..." : "");
|
||||
SteamFriends.SendChatRoomMessage(steamID, EChatEntryType.ChatMsg, messagePart);
|
||||
}
|
||||
}
|
||||
|
||||
private void SendMessageToUser(ulong steamID, string message) {
|
||||
if (steamID == 0 || string.IsNullOrEmpty(message)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < message.Length; i += MaxSteamMessageLength - 6) {
|
||||
string messagePart = (i > 0 ? "..." : "") + message.Substring(i, Math.Min(MaxSteamMessageLength - 6, message.Length - i)) + (MaxSteamMessageLength - 6 < message.Length - i ? "..." : "");
|
||||
SteamFriends.SendChatMessage(steamID, EChatEntryType.ChatMsg, messagePart);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1160,7 +1185,9 @@ namespace ArchiSteamFarm {
|
||||
|
||||
Logging.LogGenericInfo("Linking new ASF MobileAuthenticator...", BotName);
|
||||
|
||||
InitializeLoginAndPassword();
|
||||
if (!InitializeLoginAndPassword()) {
|
||||
return;
|
||||
}
|
||||
|
||||
UserLogin userLogin = new UserLogin(BotConfig.SteamLogin, BotConfig.SteamPassword);
|
||||
LoginResult loginResult;
|
||||
@@ -1168,6 +1195,9 @@ namespace ArchiSteamFarm {
|
||||
switch (loginResult) {
|
||||
case LoginResult.NeedEmail:
|
||||
userLogin.EmailCode = Program.GetUserInput(Program.EUserInputType.SteamGuard, BotName);
|
||||
if (string.IsNullOrEmpty(userLogin.EmailCode)) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Logging.LogGenericError("Unhandled situation: " + loginResult, BotName);
|
||||
@@ -1182,6 +1212,9 @@ namespace ArchiSteamFarm {
|
||||
switch (linkResult) {
|
||||
case AuthenticatorLinker.LinkResult.MustProvidePhoneNumber:
|
||||
authenticatorLinker.PhoneNumber = Program.GetUserInput(Program.EUserInputType.PhoneNumber, BotName);
|
||||
if (string.IsNullOrEmpty(authenticatorLinker.PhoneNumber)) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Logging.LogGenericError("Unhandled situation: " + linkResult, BotName);
|
||||
@@ -1191,13 +1224,21 @@ namespace ArchiSteamFarm {
|
||||
|
||||
BotDatabase.SteamGuardAccount = authenticatorLinker.LinkedAccount;
|
||||
|
||||
AuthenticatorLinker.FinalizeResult finalizeResult = authenticatorLinker.FinalizeAddAuthenticator(Program.GetUserInput(Program.EUserInputType.SMS, BotName));
|
||||
string sms = Program.GetUserInput(Program.EUserInputType.SMS, BotName);
|
||||
if (string.IsNullOrEmpty(sms)) {
|
||||
return;
|
||||
}
|
||||
|
||||
AuthenticatorLinker.FinalizeResult finalizeResult = authenticatorLinker.FinalizeAddAuthenticator(sms);
|
||||
if (finalizeResult != AuthenticatorLinker.FinalizeResult.Success) {
|
||||
Logging.LogGenericError("Unhandled situation: " + finalizeResult, BotName);
|
||||
DelinkMobileAuthenticator();
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure that we also save changes made by finalization step (if any)
|
||||
BotDatabase.Save();
|
||||
|
||||
Logging.LogGenericInfo("Successfully linked ASF as new mobile authenticator for this account!", BotName);
|
||||
Program.GetUserInput(Program.EUserInputType.RevocationCode, BotName, BotDatabase.SteamGuardAccount.RevocationCode);
|
||||
}
|
||||
@@ -1224,14 +1265,22 @@ namespace ArchiSteamFarm {
|
||||
SteamFriends.JoinChat(BotConfig.SteamMasterClanID);
|
||||
}
|
||||
|
||||
private void InitializeLoginAndPassword() {
|
||||
private bool InitializeLoginAndPassword() {
|
||||
if (string.IsNullOrEmpty(BotConfig.SteamLogin)) {
|
||||
BotConfig.SteamLogin = Program.GetUserInput(Program.EUserInputType.Login, BotName);
|
||||
if (string.IsNullOrEmpty(BotConfig.SteamLogin)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(BotConfig.SteamPassword) && string.IsNullOrEmpty(BotDatabase.LoginKey)) {
|
||||
BotConfig.SteamPassword = Program.GetUserInput(Program.EUserInputType.Password, BotName);
|
||||
if (string.IsNullOrEmpty(BotConfig.SteamPassword)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void OnConnected(SteamClient.ConnectedCallback callback) {
|
||||
@@ -1262,10 +1311,18 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
}
|
||||
|
||||
InitializeLoginAndPassword();
|
||||
if (!InitializeLoginAndPassword()) {
|
||||
Stop();
|
||||
return;
|
||||
}
|
||||
|
||||
Logging.LogGenericInfo("Logging in...", BotName);
|
||||
|
||||
// If we have ASF 2FA enabled, we can always provide TwoFactorCode, and save a request
|
||||
if (BotDatabase.SteamGuardAccount != null) {
|
||||
TwoFactorCode = BotDatabase.SteamGuardAccount.GenerateSteamGuardCode();
|
||||
}
|
||||
|
||||
// TODO: Please remove me immediately after https://github.com/SteamRE/SteamKit/issues/254 gets fixed
|
||||
if (Program.GlobalConfig.HackIgnoreMachineID) {
|
||||
Logging.LogGenericWarning("Using workaround for broken GenerateMachineID()!", BotName);
|
||||
@@ -1275,7 +1332,7 @@ namespace ArchiSteamFarm {
|
||||
AuthCode = AuthCode,
|
||||
LoginID = LoginID,
|
||||
LoginKey = BotDatabase.LoginKey,
|
||||
TwoFactorCode = TwoFactorAuth,
|
||||
TwoFactorCode = TwoFactorCode,
|
||||
SentryFileHash = sentryHash,
|
||||
ShouldRememberPassword = true
|
||||
});
|
||||
@@ -1288,7 +1345,7 @@ namespace ArchiSteamFarm {
|
||||
AuthCode = AuthCode,
|
||||
LoginID = LoginID,
|
||||
LoginKey = BotDatabase.LoginKey,
|
||||
TwoFactorCode = TwoFactorAuth,
|
||||
TwoFactorCode = TwoFactorCode,
|
||||
SentryFileHash = sentryHash,
|
||||
ShouldRememberPassword = true
|
||||
});
|
||||
@@ -1300,7 +1357,6 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
Logging.LogGenericInfo("Disconnected from Steam!", BotName);
|
||||
ArchiWebHandler.OnDisconnected();
|
||||
CardsFarmer.StopFarming().Forget();
|
||||
|
||||
// If we initiated disconnect, do not attempt to reconnect
|
||||
@@ -1336,7 +1392,7 @@ namespace ArchiSteamFarm {
|
||||
Logging.LogGenericInfo("Reconnecting...", BotName);
|
||||
|
||||
// 2FA tokens are expiring soon, use limiter only when we don't have any pending
|
||||
if (TwoFactorAuth == null) {
|
||||
if (TwoFactorCode == null) {
|
||||
await Program.LimitSteamRequestsAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@@ -1354,15 +1410,6 @@ namespace ArchiSteamFarm {
|
||||
return;
|
||||
}
|
||||
|
||||
for (byte i = 0; i < WebBrowser.MaxRetries && !ArchiWebHandler.IsInitialized; i++) {
|
||||
await Utilities.SleepAsync(1000).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (!ArchiWebHandler.IsInitialized) {
|
||||
Logging.LogGenericWarning("Reached timeout while waiting for ArchiWebHandler to initialize!");
|
||||
return;
|
||||
}
|
||||
|
||||
bool acceptedSomething = false;
|
||||
foreach (KeyValue guestPass in callback.GuestPasses) {
|
||||
ulong gid = guestPass["gid"].AsUnsignedLong();
|
||||
@@ -1500,12 +1547,20 @@ namespace ArchiSteamFarm {
|
||||
switch (callback.Result) {
|
||||
case EResult.AccountLogonDenied:
|
||||
AuthCode = Program.GetUserInput(Program.EUserInputType.SteamGuard, BotName);
|
||||
if (string.IsNullOrEmpty(AuthCode)) {
|
||||
Stop();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case EResult.AccountLoginDeniedNeedTwoFactor:
|
||||
if (BotDatabase.SteamGuardAccount == null) {
|
||||
TwoFactorAuth = Program.GetUserInput(Program.EUserInputType.TwoFactorAuthentication, BotName);
|
||||
TwoFactorCode = Program.GetUserInput(Program.EUserInputType.TwoFactorAuthentication, BotName);
|
||||
if (string.IsNullOrEmpty(TwoFactorCode)) {
|
||||
Stop();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
TwoFactorAuth = BotDatabase.SteamGuardAccount.GenerateSteamGuardCode();
|
||||
Logging.LogGenericWarning("2FA code was invalid despite of using ASF 2FA. Invalid authenticator or bad timing?", BotName);
|
||||
}
|
||||
break;
|
||||
case EResult.InvalidPassword:
|
||||
@@ -1524,23 +1579,28 @@ namespace ArchiSteamFarm {
|
||||
string maFilePath = Path.Combine(Program.ConfigDirectory, callback.ClientSteamID.ConvertToUInt64() + ".maFile");
|
||||
if (File.Exists(maFilePath)) {
|
||||
ImportAuthenticator(maFilePath);
|
||||
} else if (TwoFactorAuth == null && BotConfig.UseAsfAsMobileAuthenticator) {
|
||||
} else if (TwoFactorCode == null && BotConfig.UseAsfAsMobileAuthenticator) {
|
||||
LinkMobileAuthenticator();
|
||||
}
|
||||
}
|
||||
|
||||
// Reset one-time-only access tokens
|
||||
AuthCode = TwoFactorAuth = null;
|
||||
AuthCode = TwoFactorCode = null;
|
||||
|
||||
ResetGamesPlayed();
|
||||
|
||||
if (string.IsNullOrEmpty(BotConfig.SteamParentalPIN)) {
|
||||
BotConfig.SteamParentalPIN = Program.GetUserInput(Program.EUserInputType.SteamParentalPIN, BotName);
|
||||
if (string.IsNullOrEmpty(BotConfig.SteamParentalPIN)) {
|
||||
Stop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!await ArchiWebHandler.Init(SteamClient, callback.WebAPIUserNonce, BotConfig.SteamParentalPIN).ConfigureAwait(false)) {
|
||||
await RestartIfRunning().ConfigureAwait(false);
|
||||
return;
|
||||
if (!ArchiWebHandler.Init(SteamClient, callback.WebAPIUserNonce, BotConfig.SteamParentalPIN)) {
|
||||
if (!await RefreshSession().ConfigureAwait(false)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (BotConfig.DismissInventoryNotifications) {
|
||||
@@ -1592,35 +1652,37 @@ namespace ArchiSteamFarm {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
int fileSize;
|
||||
byte[] sentryHash;
|
||||
int fileSize;
|
||||
byte[] sentryHash;
|
||||
|
||||
using (FileStream fileStream = File.Open(SentryFile, FileMode.OpenOrCreate, FileAccess.ReadWrite)) {
|
||||
fileStream.Seek(callback.Offset, SeekOrigin.Begin);
|
||||
fileStream.Write(callback.Data, 0, callback.BytesToWrite);
|
||||
fileSize = (int) fileStream.Length;
|
||||
using (FileStream fileStream = File.Open(SentryFile, FileMode.OpenOrCreate, FileAccess.ReadWrite)) {
|
||||
fileStream.Seek(callback.Offset, SeekOrigin.Begin);
|
||||
fileStream.Write(callback.Data, 0, callback.BytesToWrite);
|
||||
fileSize = (int) fileStream.Length;
|
||||
|
||||
fileStream.Seek(0, SeekOrigin.Begin);
|
||||
using (SHA1CryptoServiceProvider sha = new SHA1CryptoServiceProvider()) {
|
||||
sentryHash = sha.ComputeHash(fileStream);
|
||||
}
|
||||
fileStream.Seek(0, SeekOrigin.Begin);
|
||||
using (SHA1CryptoServiceProvider sha = new SHA1CryptoServiceProvider()) {
|
||||
sentryHash = sha.ComputeHash(fileStream);
|
||||
}
|
||||
}
|
||||
|
||||
// Inform the steam servers that we're accepting this sentry file
|
||||
SteamUser.SendMachineAuthResponse(new SteamUser.MachineAuthDetails {
|
||||
JobID = callback.JobID,
|
||||
FileName = callback.FileName,
|
||||
BytesWritten = callback.BytesToWrite,
|
||||
FileSize = fileSize,
|
||||
Offset = callback.Offset,
|
||||
Result = EResult.OK,
|
||||
LastError = 0,
|
||||
OneTimePassword = callback.OneTimePassword,
|
||||
SentryFileHash = sentryHash,
|
||||
});
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(e, BotName);
|
||||
// Inform the steam servers that we're accepting this sentry file
|
||||
SteamUser.SendMachineAuthResponse(new SteamUser.MachineAuthDetails {
|
||||
JobID = callback.JobID,
|
||||
FileName = callback.FileName,
|
||||
BytesWritten = callback.BytesToWrite,
|
||||
FileSize = fileSize,
|
||||
Offset = callback.Offset,
|
||||
Result = EResult.OK,
|
||||
LastError = 0,
|
||||
OneTimePassword = callback.OneTimePassword,
|
||||
SentryFileHash = sentryHash
|
||||
});
|
||||
}
|
||||
|
||||
private void OnWebAPIUserNonce(SteamUser.WebAPIUserNonceCallback callback) {
|
||||
if (callback == null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -99,14 +99,14 @@ namespace ArchiSteamFarm {
|
||||
internal HashSet<uint> GamesPlayedWhileIdle { get; private set; } = new HashSet<uint>() { 0 };
|
||||
|
||||
|
||||
internal static BotConfig Load(string path) {
|
||||
if (string.IsNullOrEmpty(path) || !File.Exists(path)) {
|
||||
internal static BotConfig Load(string filePath) {
|
||||
if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
BotConfig botConfig;
|
||||
try {
|
||||
botConfig = JsonConvert.DeserializeObject<BotConfig>(File.ReadAllText(path));
|
||||
botConfig = JsonConvert.DeserializeObject<BotConfig>(File.ReadAllText(filePath));
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(e);
|
||||
return null;
|
||||
|
||||
@@ -92,6 +92,10 @@ namespace ArchiSteamFarm {
|
||||
|
||||
// This constructor is used when creating new database
|
||||
private BotDatabase(string filePath) {
|
||||
if (string.IsNullOrEmpty(filePath)) {
|
||||
throw new ArgumentNullException("filePath");
|
||||
}
|
||||
|
||||
FilePath = filePath;
|
||||
Save();
|
||||
}
|
||||
|
||||
@@ -48,12 +48,12 @@ namespace ArchiSteamFarm {
|
||||
|
||||
internal CardsFarmer(Bot bot) {
|
||||
if (bot == null) {
|
||||
return;
|
||||
throw new ArgumentNullException("bot");
|
||||
}
|
||||
|
||||
Bot = bot;
|
||||
|
||||
if (Program.GlobalConfig.IdleFarmingPeriod > 0) {
|
||||
if (Timer == null && Program.GlobalConfig.IdleFarmingPeriod > 0) {
|
||||
Timer = new Timer(
|
||||
async e => await CheckGamesForFarming().ConfigureAwait(false),
|
||||
null,
|
||||
@@ -94,6 +94,7 @@ namespace ArchiSteamFarm {
|
||||
if (!await IsAnythingToFarm().ConfigureAwait(false)) {
|
||||
Semaphore.Release(); // We have nothing to do, don't forget to release semaphore
|
||||
Logging.LogGenericInfo("We don't have anything to farm on this account!", Bot.BotName);
|
||||
await Bot.OnFarmingFinished(false).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -103,56 +104,51 @@ namespace ArchiSteamFarm {
|
||||
|
||||
bool farmedSomething = false;
|
||||
|
||||
// Now the algorithm used for farming depends on whether account is restricted or not
|
||||
if (Bot.BotConfig.CardDropsRestricted) { // If we have restricted card drops, we use complex algorithm
|
||||
Logging.LogGenericInfo("Chosen farming algorithm: Complex", Bot.BotName);
|
||||
while (GamesToFarm.Count > 0) {
|
||||
HashSet<uint> gamesToFarmSolo = GetGamesToFarmSolo(GamesToFarm);
|
||||
if (gamesToFarmSolo.Count > 0) {
|
||||
while (gamesToFarmSolo.Count > 0) {
|
||||
uint appID = gamesToFarmSolo.First();
|
||||
if (await FarmSolo(appID).ConfigureAwait(false)) {
|
||||
farmedSomething = true;
|
||||
gamesToFarmSolo.Remove(appID);
|
||||
gamesToFarmSolo.TrimExcess();
|
||||
do {
|
||||
// Now the algorithm used for farming depends on whether account is restricted or not
|
||||
if (Bot.BotConfig.CardDropsRestricted) { // If we have restricted card drops, we use complex algorithm
|
||||
Logging.LogGenericInfo("Chosen farming algorithm: Complex", Bot.BotName);
|
||||
while (GamesToFarm.Count > 0) {
|
||||
HashSet<uint> gamesToFarmSolo = GetGamesToFarmSolo(GamesToFarm);
|
||||
if (gamesToFarmSolo.Count > 0) {
|
||||
while (gamesToFarmSolo.Count > 0) {
|
||||
uint appID = gamesToFarmSolo.First();
|
||||
if (await FarmSolo(appID).ConfigureAwait(false)) {
|
||||
farmedSomething = true;
|
||||
gamesToFarmSolo.Remove(appID);
|
||||
gamesToFarmSolo.TrimExcess();
|
||||
} else {
|
||||
NowFarming = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (FarmMultiple()) {
|
||||
Logging.LogGenericInfo("Done farming: " + string.Join(", ", GamesToFarm.Keys), Bot.BotName);
|
||||
} else {
|
||||
NowFarming = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (FarmMultiple()) {
|
||||
Logging.LogGenericInfo("Done farming: " + string.Join(", ", GamesToFarm.Keys), Bot.BotName);
|
||||
}
|
||||
} else { // If we have unrestricted card drops, we use simple algorithm
|
||||
Logging.LogGenericInfo("Chosen farming algorithm: Simple", Bot.BotName);
|
||||
while (GamesToFarm.Count > 0) {
|
||||
uint appID = GamesToFarm.Keys.FirstOrDefault();
|
||||
if (await FarmSolo(appID).ConfigureAwait(false)) {
|
||||
farmedSomething = true;
|
||||
} else {
|
||||
NowFarming = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { // If we have unrestricted card drops, we use simple algorithm
|
||||
Logging.LogGenericInfo("Chosen farming algorithm: Simple", Bot.BotName);
|
||||
while (GamesToFarm.Count > 0) {
|
||||
uint appID = GamesToFarm.Keys.FirstOrDefault();
|
||||
if (await FarmSolo(appID).ConfigureAwait(false)) {
|
||||
farmedSomething = true;
|
||||
} else {
|
||||
NowFarming = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (await IsAnythingToFarm().ConfigureAwait(false));
|
||||
|
||||
CurrentGamesFarming.Clear();
|
||||
CurrentGamesFarming.TrimExcess();
|
||||
NowFarming = false;
|
||||
|
||||
// We finished our queue for now, make sure that everything is indeed farmed before proceeding further
|
||||
// Some games could be added in the meantime
|
||||
if (await IsAnythingToFarm().ConfigureAwait(false)) {
|
||||
StartFarming().Forget();
|
||||
return;
|
||||
}
|
||||
|
||||
Logging.LogGenericInfo("Farming finished!", Bot.BotName);
|
||||
await Bot.OnFarmingFinished(farmedSomething).ConfigureAwait(false);
|
||||
}
|
||||
@@ -207,14 +203,6 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
private async Task<bool> IsAnythingToFarm() {
|
||||
if (NowFarming) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (await Bot.ArchiWebHandler.ReconnectIfNeeded().ConfigureAwait(false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Logging.LogGenericInfo("Checking badges...", Bot.BotName);
|
||||
|
||||
// Find the number of badge pages
|
||||
@@ -229,8 +217,11 @@ namespace ArchiSteamFarm {
|
||||
HtmlNodeCollection htmlNodeCollection = htmlDocument.DocumentNode.SelectNodes("//a[@class='pagelink']");
|
||||
if (htmlNodeCollection != null && htmlNodeCollection.Count > 0) {
|
||||
HtmlNode htmlNode = htmlNodeCollection[htmlNodeCollection.Count - 1];
|
||||
if (!byte.TryParse(htmlNode.InnerText, out maxPages)) {
|
||||
maxPages = 1; // Should never happen
|
||||
string lastPage = htmlNode.InnerText;
|
||||
if (!string.IsNullOrEmpty(lastPage)) {
|
||||
if (!byte.TryParse(lastPage, out maxPages)) {
|
||||
maxPages = 1; // Should never happen
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,17 +233,13 @@ namespace ArchiSteamFarm {
|
||||
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
|
||||
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);
|
||||
}
|
||||
|
||||
if (GamesToFarm.Count == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return GamesToFarm.Count > 0;
|
||||
}
|
||||
|
||||
private void CheckPage(HtmlDocument htmlDocument) {
|
||||
@@ -362,7 +349,6 @@ namespace ArchiSteamFarm {
|
||||
|
||||
HtmlNode htmlNode = htmlDocument.DocumentNode.SelectSingleNode("//span[@class='progress_info_bold']");
|
||||
if (htmlNode == null) {
|
||||
await Bot.ArchiWebHandler.ReconnectIfNeeded().ConfigureAwait(false);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,9 +36,10 @@ namespace ArchiSteamFarm {
|
||||
Experimental
|
||||
}
|
||||
|
||||
internal const byte DefaultHttpTimeout = 60;
|
||||
|
||||
private const byte DefaultMaxFarmingTime = 10;
|
||||
private const byte DefaultFarmingDelay = 5;
|
||||
private const byte DefaultHttpTimeout = 60;
|
||||
private const ushort DefaultWCFPort = 1242;
|
||||
private const ProtocolType DefaultSteamProtocol = ProtocolType.Tcp;
|
||||
|
||||
@@ -48,6 +49,9 @@ namespace ArchiSteamFarm {
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal bool Debug { get; private set; } = false;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal bool Headless { get; private set; } = false;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal bool AutoUpdates { get; private set; } = true;
|
||||
|
||||
@@ -103,8 +107,11 @@ namespace ArchiSteamFarm {
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
internal HashSet<uint> Blacklist { get; private set; } = new HashSet<uint>(GlobalBlacklist);
|
||||
|
||||
internal static GlobalConfig Load() {
|
||||
string filePath = Path.Combine(Program.ConfigDirectory, Program.GlobalConfigFile);
|
||||
internal static GlobalConfig Load(string filePath) {
|
||||
if (string.IsNullOrEmpty(filePath)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!File.Exists(filePath)) {
|
||||
return null;
|
||||
}
|
||||
@@ -117,6 +124,10 @@ namespace ArchiSteamFarm {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (globalConfig == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// SK2 supports only TCP and UDP steam protocols
|
||||
// Ensure that user can't screw this up
|
||||
switch (globalConfig.SteamProtocol) {
|
||||
|
||||
@@ -28,8 +28,6 @@ using System.IO;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
internal sealed class GlobalDatabase {
|
||||
private static readonly string FilePath = Path.Combine(Program.ConfigDirectory, Program.GlobalDatabaseFile);
|
||||
|
||||
internal uint CellID {
|
||||
get {
|
||||
return _CellID;
|
||||
@@ -47,22 +45,43 @@ namespace ArchiSteamFarm {
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
private uint _CellID;
|
||||
|
||||
internal static GlobalDatabase Load() {
|
||||
if (!File.Exists(FilePath)) {
|
||||
return new GlobalDatabase();
|
||||
private string FilePath;
|
||||
|
||||
internal static GlobalDatabase Load(string filePath) {
|
||||
if (string.IsNullOrEmpty(filePath)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!File.Exists(filePath)) {
|
||||
return new GlobalDatabase(filePath);
|
||||
}
|
||||
|
||||
GlobalDatabase globalDatabase;
|
||||
try {
|
||||
globalDatabase = JsonConvert.DeserializeObject<GlobalDatabase>(File.ReadAllText(FilePath));
|
||||
globalDatabase = JsonConvert.DeserializeObject<GlobalDatabase>(File.ReadAllText(filePath));
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(e);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (globalDatabase == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
globalDatabase.FilePath = filePath;
|
||||
return globalDatabase;
|
||||
}
|
||||
|
||||
// This constructor is used when creating new database
|
||||
private GlobalDatabase(string filePath) {
|
||||
if (string.IsNullOrEmpty(filePath)) {
|
||||
throw new ArgumentNullException("filePath");
|
||||
}
|
||||
|
||||
FilePath = filePath;
|
||||
Save();
|
||||
}
|
||||
|
||||
// This constructor is used only by deserializer
|
||||
private GlobalDatabase() { }
|
||||
|
||||
|
||||
@@ -82,17 +82,21 @@ namespace ArchiSteamFarm {
|
||||
|
||||
private static Timer AutoUpdatesTimer;
|
||||
private static EMode Mode = EMode.Normal;
|
||||
private static WebBrowser WebBrowser;
|
||||
|
||||
internal static async Task CheckForUpdate() {
|
||||
string oldExeFile = ExecutableFile + ".old";
|
||||
|
||||
// We booted successfully so we can now remove old exe file
|
||||
if (File.Exists(oldExeFile)) {
|
||||
// It's entirely possible that old process is still running, allow at least a second before trying to remove the file
|
||||
await Utilities.SleepAsync(1000).ConfigureAwait(false);
|
||||
|
||||
try {
|
||||
File.Delete(oldExeFile);
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(e);
|
||||
return;
|
||||
Logging.LogGenericError("Could not remove old ASF binary, please remove " + oldExeFile + " manually in order for update function to work!");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,6 +174,11 @@ namespace ArchiSteamFarm {
|
||||
return;
|
||||
}
|
||||
|
||||
if (File.Exists(oldExeFile)) {
|
||||
Logging.LogGenericWarning("Refusing to proceed with auto update as old " + oldExeFile + " binary could not be removed, please remove it manually");
|
||||
return;
|
||||
}
|
||||
|
||||
// Auto update logic starts here
|
||||
if (releaseResponse.Assets == null) {
|
||||
Logging.LogGenericWarning("Could not proceed with update because that version doesn't include assets!");
|
||||
@@ -247,13 +256,19 @@ namespace ArchiSteamFarm {
|
||||
Restart();
|
||||
}
|
||||
|
||||
internal static void Exit(int exitCode = 0) {
|
||||
WCF.StopServer();
|
||||
Environment.Exit(exitCode);
|
||||
}
|
||||
|
||||
internal static void Restart() {
|
||||
try {
|
||||
Process.Start(ExecutableFile, string.Join(" ", Environment.GetCommandLineArgs().Skip(1)));
|
||||
Environment.Exit(0);
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(e);
|
||||
}
|
||||
|
||||
Exit();
|
||||
}
|
||||
|
||||
internal static async Task LimitSteamRequestsAsync() {
|
||||
@@ -269,6 +284,11 @@ namespace ArchiSteamFarm {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (GlobalConfig.Headless) {
|
||||
Logging.LogGenericWarning("Received a request for user input, but process is running in headless mode!");
|
||||
return null;
|
||||
}
|
||||
|
||||
string result;
|
||||
lock (ConsoleLock) {
|
||||
ConsoleIsBusy = true;
|
||||
@@ -295,7 +315,7 @@ namespace ArchiSteamFarm {
|
||||
Console.Write((string.IsNullOrEmpty(botName) ? "" : "<" + botName + "> ") + "Please enter steam parental PIN: ");
|
||||
break;
|
||||
case EUserInputType.RevocationCode:
|
||||
Console.Write((string.IsNullOrEmpty(botName) ? "" : "<" + botName + "> ") + "PLEASE WRITE DOWN YOUR REVOCATION CODE: " + extraInformation);
|
||||
Console.WriteLine((string.IsNullOrEmpty(botName) ? "" : "<" + botName + "> ") + "PLEASE WRITE DOWN YOUR REVOCATION CODE: " + extraInformation);
|
||||
Console.Write("Hit enter once ready...");
|
||||
break;
|
||||
case EUserInputType.TwoFactorAuthentication:
|
||||
@@ -309,7 +329,9 @@ namespace ArchiSteamFarm {
|
||||
break;
|
||||
}
|
||||
result = Console.ReadLine();
|
||||
Console.Clear(); // For security purposes
|
||||
if (!Console.IsOutputRedirected) {
|
||||
Console.Clear(); // For security purposes
|
||||
}
|
||||
ConsoleIsBusy = false;
|
||||
}
|
||||
|
||||
@@ -333,23 +355,25 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
|
||||
private static void InitServices() {
|
||||
GlobalConfig = GlobalConfig.Load();
|
||||
GlobalConfig = GlobalConfig.Load(Path.Combine(ConfigDirectory, GlobalConfigFile));
|
||||
if (GlobalConfig == null) {
|
||||
Logging.LogGenericError("Global config could not be loaded, please make sure that ASF.json exists and is valid!");
|
||||
Thread.Sleep(5000);
|
||||
Environment.Exit(1);
|
||||
Exit(1);
|
||||
}
|
||||
|
||||
GlobalDatabase = GlobalDatabase.Load();
|
||||
GlobalDatabase = GlobalDatabase.Load(Path.Combine(ConfigDirectory, GlobalDatabaseFile));
|
||||
if (GlobalDatabase == null) {
|
||||
Logging.LogGenericError("Global database could not be loaded!");
|
||||
Thread.Sleep(5000);
|
||||
Environment.Exit(1);
|
||||
Exit(1);
|
||||
}
|
||||
|
||||
ArchiWebHandler.Init();
|
||||
WebBrowser.Init();
|
||||
WCF.Init();
|
||||
|
||||
WebBrowser = new WebBrowser("Main");
|
||||
}
|
||||
|
||||
private static void ParseArgs(string[] args) {
|
||||
@@ -445,7 +469,7 @@ namespace ArchiSteamFarm {
|
||||
|
||||
// If we ran ASF as a client, we're done by now
|
||||
if (Mode == EMode.Client) {
|
||||
Environment.Exit(0);
|
||||
Exit();
|
||||
}
|
||||
|
||||
// From now on it's server mode
|
||||
@@ -454,7 +478,7 @@ namespace ArchiSteamFarm {
|
||||
if (!Directory.Exists(ConfigDirectory)) {
|
||||
Logging.LogGenericError("Config directory doesn't exist!");
|
||||
Thread.Sleep(5000);
|
||||
Environment.Exit(1);
|
||||
Exit(1);
|
||||
}
|
||||
|
||||
CheckForUpdate().Wait();
|
||||
@@ -494,7 +518,7 @@ namespace ArchiSteamFarm {
|
||||
ShutdownResetEvent.WaitOne();
|
||||
|
||||
// We got a signal to shutdown
|
||||
Environment.Exit(0);
|
||||
Exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ using System.Runtime.InteropServices;
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("ArchiSteamFarm")]
|
||||
[assembly: AssemblyCopyright("Copyright © Łukasz Domeradzki 2015-2016")]
|
||||
[assembly: AssemblyCopyright("Copyright © ArchiSteamFarm 2015-2016")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("2.0.2.1")]
|
||||
[assembly: AssemblyFileVersion("2.0.2.1")]
|
||||
[assembly: AssemblyVersion("2.0.3.0")]
|
||||
[assembly: AssemblyFileVersion("2.0.3.0")]
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
*/
|
||||
|
||||
using SteamAuth;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@@ -49,7 +50,7 @@ namespace ArchiSteamFarm {
|
||||
|
||||
internal Trading(Bot bot) {
|
||||
if (bot == null) {
|
||||
return;
|
||||
throw new ArgumentNullException("bot");
|
||||
}
|
||||
|
||||
Bot = bot;
|
||||
@@ -84,19 +85,12 @@ namespace ArchiSteamFarm {
|
||||
return;
|
||||
}
|
||||
|
||||
List<Task> tasks = new List<Task>();
|
||||
foreach (Steam.TradeOffer tradeOffer in tradeOffers) {
|
||||
if (tradeOffer.trade_offer_state == Steam.TradeOffer.ETradeOfferState.Active) {
|
||||
tasks.Add(Task.Run(async () => await ParseTrade(tradeOffer).ConfigureAwait(false)));
|
||||
}
|
||||
}
|
||||
|
||||
await Task.WhenAll(tasks).ConfigureAwait(false);
|
||||
await Bot.AcceptConfirmations(Confirmation.ConfirmationType.Trade).ConfigureAwait(false);
|
||||
await tradeOffers.ForEachAsync(ParseTrade).ConfigureAwait(false);
|
||||
await Bot.AcceptConfirmations(true, Confirmation.ConfirmationType.Trade).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async Task ParseTrade(Steam.TradeOffer tradeOffer) {
|
||||
if (tradeOffer == null) {
|
||||
if (tradeOffer == null || tradeOffer.trade_offer_state != Steam.TradeOffer.ETradeOfferState.Active) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -105,12 +99,34 @@ namespace ArchiSteamFarm {
|
||||
return;
|
||||
}
|
||||
|
||||
if (tradeOffer.items_to_give.Count == 0 || tradeOffer.OtherSteamID64 == Bot.BotConfig.SteamMasterID) {
|
||||
if (ShouldAcceptTrade(tradeOffer)) {
|
||||
Logging.LogGenericInfo("Accepting trade: " + tradeID, Bot.BotName);
|
||||
await Bot.ArchiWebHandler.AcceptTradeOffer(tradeID).ConfigureAwait(false);
|
||||
} else {
|
||||
Logging.LogGenericInfo("Ignoring trade: " + tradeID, Bot.BotName);
|
||||
}
|
||||
}
|
||||
|
||||
private bool ShouldAcceptTrade(Steam.TradeOffer tradeOffer) {
|
||||
if (tradeOffer == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Always accept trades when we're not losing anything
|
||||
if (tradeOffer.items_to_give.Count == 0) {
|
||||
// Unless it's steam fuckup and we're dealing with broken trade
|
||||
return tradeOffer.items_to_receive.Count > 0;
|
||||
}
|
||||
|
||||
// Always accept trades from SteamMasterID
|
||||
if (tradeOffer.OtherSteamID64 != 0 && tradeOffer.OtherSteamID64 == Bot.BotConfig.SteamMasterID) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: Add optional SteamTradeMatcher integration here
|
||||
|
||||
// If no rule above matched this trade, reject it
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,14 +22,47 @@
|
||||
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
internal static class Utilities {
|
||||
internal static void Forget(this Task task) { }
|
||||
|
||||
internal static async Task SleepAsync(int miliseconds) {
|
||||
await Task.Delay(miliseconds).ConfigureAwait(false);
|
||||
internal static Task ForEachAsync<T>(this IEnumerable<T> sequence, Func<T, Task> 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)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
CookieCollection cookies = cookieContainer.GetCookies(new Uri(URL));
|
||||
if (cookies == null || cookies.Count == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
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 uint GetCharCountInString(string s, char c) {
|
||||
|
||||
@@ -44,6 +44,9 @@ namespace ArchiSteamFarm {
|
||||
internal static void Init() {
|
||||
if (string.IsNullOrEmpty(Program.GlobalConfig.WCFHostname)) {
|
||||
Program.GlobalConfig.WCFHostname = Program.GetUserInput(Program.EUserInputType.WCFHostname);
|
||||
if (string.IsNullOrEmpty(Program.GlobalConfig.WCFHostname)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
URL = "http://" + Program.GlobalConfig.WCFHostname + ":" + Program.GlobalConfig.WCFPort + "/ASF";
|
||||
|
||||
@@ -23,37 +23,31 @@
|
||||
*/
|
||||
|
||||
using HtmlAgilityPack;
|
||||
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.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
internal static class WebBrowser {
|
||||
internal sealed class WebBrowser {
|
||||
internal const byte MaxRetries = 5; // Defines maximum number of retries, UrlRequest() does not handle retry by itself (it's app responsibility)
|
||||
|
||||
private const byte MaxConnections = 10; // Defines maximum number of connections per ServicePoint. Be careful, as it also defines maximum number of sockets in CLOSE_WAIT state
|
||||
private const byte MaxIdleTime = 15; // In seconds, how long socket is allowed to stay in CLOSE_WAIT state after there are no connections to it
|
||||
|
||||
private static readonly string DefaultUserAgent = "ArchiSteamFarm/" + Program.Version;
|
||||
private static readonly HttpClient HttpClient = new HttpClient(new HttpClientHandler {
|
||||
UseCookies = false
|
||||
}) {
|
||||
Timeout = TimeSpan.FromSeconds(60)
|
||||
};
|
||||
|
||||
internal readonly CookieContainer CookieContainer = new CookieContainer();
|
||||
|
||||
private readonly HttpClient HttpClient;
|
||||
private readonly string Identifier;
|
||||
|
||||
internal static void Init() {
|
||||
HttpClient.Timeout = TimeSpan.FromSeconds(Program.GlobalConfig.HttpTimeout);
|
||||
|
||||
// Most web services expect that UserAgent is set, so we declare it globally
|
||||
// Any request can override that on as-needed basis (see: RequestOptions.FakeUserAgent)
|
||||
HttpClient.DefaultRequestHeaders.UserAgent.ParseAdd(DefaultUserAgent);
|
||||
|
||||
// Set max connection limit from default of 2 to desired value
|
||||
ServicePointManager.DefaultConnectionLimit = MaxConnections;
|
||||
|
||||
@@ -63,67 +57,114 @@ namespace ArchiSteamFarm {
|
||||
// Don't use Expect100Continue, we're sure about our POSTs, save some TCP packets
|
||||
ServicePointManager.Expect100Continue = false;
|
||||
|
||||
// Reuse ports if possible
|
||||
// TODO: Mono doesn't support that feature yet
|
||||
#if !__MonoCS__
|
||||
// Reuse ports if possible (since .NET 4.6+)
|
||||
//ServicePointManager.ReusePort = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
internal static async Task<HttpResponseMessage> UrlGet(string request, Dictionary<string, string> cookies = null, string referer = null) {
|
||||
internal WebBrowser(string identifier) {
|
||||
if (string.IsNullOrEmpty(identifier)) {
|
||||
throw new ArgumentNullException("identifier");
|
||||
}
|
||||
|
||||
Identifier = identifier;
|
||||
|
||||
HttpClientHandler httpClientHandler = new HttpClientHandler {
|
||||
AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip,
|
||||
CookieContainer = CookieContainer
|
||||
};
|
||||
|
||||
HttpClient = new HttpClient(httpClientHandler) {
|
||||
Timeout = TimeSpan.FromSeconds(Program.GlobalConfig.HttpTimeout)
|
||||
};
|
||||
|
||||
// Most web services expect that UserAgent is set, so we declare it globally
|
||||
HttpClient.DefaultRequestHeaders.UserAgent.ParseAdd(DefaultUserAgent);
|
||||
}
|
||||
|
||||
internal async Task<bool> UrlGet(string request, string referer = null) {
|
||||
if (string.IsNullOrEmpty(request)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HttpResponseMessage response = await UrlGetToResponse(request, referer).ConfigureAwait(false);
|
||||
if (response == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
response.Dispose();
|
||||
return true;
|
||||
}
|
||||
|
||||
internal async Task<bool> UrlPost(string request, Dictionary<string, string> data = null, string referer = null) {
|
||||
if (string.IsNullOrEmpty(request)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HttpResponseMessage response = await UrlPostToResponse(request, data, referer).ConfigureAwait(false);
|
||||
if (response == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
response.Dispose();
|
||||
return true;
|
||||
}
|
||||
|
||||
internal async Task<HttpResponseMessage> UrlGetToResponse(string request, string referer = null) {
|
||||
if (string.IsNullOrEmpty(request)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return await UrlRequest(request, HttpMethod.Get, null, cookies, referer).ConfigureAwait(false);
|
||||
return await UrlRequest(request, HttpMethod.Get, null, referer).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
internal static async Task<HttpResponseMessage> UrlPost(string request, Dictionary<string, string> data = null, Dictionary<string, string> cookies = null, string referer = null) {
|
||||
internal async Task<HttpResponseMessage> UrlPostToResponse(string request, Dictionary<string, string> data = null, string referer = null) {
|
||||
if (string.IsNullOrEmpty(request)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return await UrlRequest(request, HttpMethod.Post, data, cookies, referer).ConfigureAwait(false);
|
||||
return await UrlRequest(request, HttpMethod.Post, data, referer).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
internal static async Task<string> UrlGetToContent(string request, Dictionary<string, string> cookies = null, string referer = null) {
|
||||
internal async Task<string> UrlGetToContent(string request, string referer = null) {
|
||||
if (string.IsNullOrEmpty(request)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
HttpResponseMessage httpResponse = await UrlGet(request, cookies, referer).ConfigureAwait(false);
|
||||
HttpResponseMessage httpResponse = await UrlGetToResponse(request, referer).ConfigureAwait(false);
|
||||
if (httpResponse == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (httpResponse.Content == null) {
|
||||
return null;
|
||||
}
|
||||
string result = await httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
httpResponse.Dispose();
|
||||
|
||||
return await httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static async Task<Stream> UrlGetToStream(string request, Dictionary<string, string> cookies = null, string referer = null) {
|
||||
internal async Task<Stream> UrlGetToStream(string request, string referer = null) {
|
||||
if (string.IsNullOrEmpty(request)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
HttpResponseMessage httpResponse = await UrlGet(request, cookies, referer).ConfigureAwait(false);
|
||||
HttpResponseMessage httpResponse = await UrlGetToResponse(request, referer).ConfigureAwait(false);
|
||||
if (httpResponse == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (httpResponse.Content == null) {
|
||||
return null;
|
||||
}
|
||||
Stream result = await httpResponse.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
||||
httpResponse.Dispose();
|
||||
|
||||
return await httpResponse.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static async Task<HtmlDocument> UrlGetToHtmlDocument(string request, Dictionary<string, string> cookies = null, string referer = null) {
|
||||
internal async Task<HtmlDocument> UrlGetToHtmlDocument(string request, string referer = null) {
|
||||
if (string.IsNullOrEmpty(request)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
string content = await UrlGetToContent(request, cookies, referer).ConfigureAwait(false);
|
||||
string content = await UrlGetToContent(request, referer).ConfigureAwait(false);
|
||||
if (string.IsNullOrEmpty(content)) {
|
||||
return null;
|
||||
}
|
||||
@@ -135,12 +176,12 @@ namespace ArchiSteamFarm {
|
||||
return htmlDocument;
|
||||
}
|
||||
|
||||
internal static async Task<JObject> UrlGetToJObject(string request, Dictionary<string, string> cookies = null, string referer = null) {
|
||||
internal async Task<JObject> UrlGetToJObject(string request, string referer = null) {
|
||||
if (string.IsNullOrEmpty(request)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
string content = await UrlGetToContent(request, cookies, referer).ConfigureAwait(false);
|
||||
string content = await UrlGetToContent(request, referer).ConfigureAwait(false);
|
||||
if (string.IsNullOrEmpty(content)) {
|
||||
return null;
|
||||
}
|
||||
@@ -149,20 +190,20 @@ namespace ArchiSteamFarm {
|
||||
|
||||
try {
|
||||
jObject = JObject.Parse(content);
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(e);
|
||||
} catch (JsonException e) {
|
||||
Logging.LogGenericException(e, Identifier);
|
||||
return null;
|
||||
}
|
||||
|
||||
return jObject;
|
||||
}
|
||||
|
||||
internal static async Task<XmlDocument> UrlGetToXML(string request, Dictionary<string, string> cookies = null, string referer = null) {
|
||||
internal async Task<XmlDocument> UrlGetToXML(string request, string referer = null) {
|
||||
if (string.IsNullOrEmpty(request)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
string content = await UrlGetToContent(request, cookies, referer).ConfigureAwait(false);
|
||||
string content = await UrlGetToContent(request, referer).ConfigureAwait(false);
|
||||
if (string.IsNullOrEmpty(content)) {
|
||||
return null;
|
||||
}
|
||||
@@ -172,37 +213,33 @@ namespace ArchiSteamFarm {
|
||||
try {
|
||||
xmlDocument.LoadXml(content);
|
||||
} catch (XmlException e) {
|
||||
Logging.LogGenericException(e);
|
||||
Logging.LogGenericException(e, Identifier);
|
||||
return null;
|
||||
}
|
||||
|
||||
return xmlDocument;
|
||||
}
|
||||
|
||||
private static async Task<HttpResponseMessage> UrlRequest(string request, HttpMethod httpMethod, Dictionary<string, string> data = null, Dictionary<string, string> cookies = null, string referer = null) {
|
||||
private async Task<HttpResponseMessage> UrlRequest(string request, HttpMethod httpMethod, Dictionary<string, string> data = null, string referer = null) {
|
||||
if (string.IsNullOrEmpty(request) || httpMethod == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (request.StartsWith("https://") && Program.GlobalConfig.ForceHttp) {
|
||||
return null;
|
||||
}
|
||||
|
||||
HttpResponseMessage responseMessage;
|
||||
using (HttpRequestMessage requestMessage = new HttpRequestMessage(httpMethod, request)) {
|
||||
if (data != null && data.Count > 0) {
|
||||
try {
|
||||
requestMessage.Content = new FormUrlEncodedContent(data);
|
||||
} catch (UriFormatException e) {
|
||||
Logging.LogGenericException(e);
|
||||
Logging.LogGenericException(e, Identifier);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (cookies != null && cookies.Count > 0) {
|
||||
StringBuilder cookieHeader = new StringBuilder();
|
||||
foreach (KeyValuePair<string, string> cookie in cookies) {
|
||||
cookieHeader.Append(cookie.Key + "=" + cookie.Value + ";");
|
||||
}
|
||||
requestMessage.Headers.Add("Cookie", cookieHeader.ToString());
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(referer)) {
|
||||
requestMessage.Headers.Referrer = new Uri(referer);
|
||||
}
|
||||
@@ -214,15 +251,14 @@ namespace ArchiSteamFarm {
|
||||
}
|
||||
}
|
||||
|
||||
if (responseMessage == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!responseMessage.IsSuccessStatusCode) {
|
||||
if (responseMessage == null || !responseMessage.IsSuccessStatusCode) {
|
||||
if (Debugging.IsDebugBuild || Program.GlobalConfig.Debug) {
|
||||
Logging.LogGenericError("Request: " + request + "failed!");
|
||||
Logging.LogGenericError("Status code: " + responseMessage.StatusCode);
|
||||
Logging.LogGenericError("Content: " + Environment.NewLine + await responseMessage.Content.ReadAsStringAsync().ConfigureAwait(false));
|
||||
Logging.LogGenericError("Request: " + request + " failed!", Identifier);
|
||||
if (responseMessage != null) {
|
||||
Logging.LogGenericError("Status code: " + responseMessage.StatusCode, Identifier);
|
||||
Logging.LogGenericError("Content: " + Environment.NewLine + await responseMessage.Content.ReadAsStringAsync().ConfigureAwait(false), Identifier);
|
||||
responseMessage.Dispose();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"Debug": false,
|
||||
"Headless": false,
|
||||
"AutoUpdates": true,
|
||||
"UpdateChannel": 1,
|
||||
"SteamProtocol": 6,
|
||||
|
||||
@@ -38,6 +38,10 @@ namespace ConfigGenerator {
|
||||
}
|
||||
|
||||
protected ASFConfig(string filePath) : this() {
|
||||
if (string.IsNullOrEmpty(filePath)) {
|
||||
throw new ArgumentNullException("filePath");
|
||||
}
|
||||
|
||||
FilePath = filePath;
|
||||
}
|
||||
|
||||
@@ -54,9 +58,9 @@ namespace ConfigGenerator {
|
||||
internal virtual void Remove() {
|
||||
string queryPath = Path.GetFileNameWithoutExtension(FilePath);
|
||||
lock (FilePath) {
|
||||
foreach (var configFile in Directory.EnumerateFiles(Program.ConfigDirectory, queryPath + ".*")) {
|
||||
foreach (string botFile in Directory.EnumerateFiles(Program.ConfigDirectory, queryPath + ".*")) {
|
||||
try {
|
||||
File.Delete(configFile);
|
||||
File.Delete(botFile);
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(e);
|
||||
}
|
||||
@@ -72,9 +76,9 @@ namespace ConfigGenerator {
|
||||
|
||||
string queryPath = Path.GetFileNameWithoutExtension(FilePath);
|
||||
lock (FilePath) {
|
||||
foreach (var file in Directory.EnumerateFiles(Program.ConfigDirectory, queryPath + ".*")) {
|
||||
foreach (string botFile in Directory.EnumerateFiles(Program.ConfigDirectory, queryPath + ".*")) {
|
||||
try {
|
||||
File.Move(file, Path.Combine(Program.ConfigDirectory, botName + Path.GetExtension(file)));
|
||||
File.Move(botFile, Path.Combine(Program.ConfigDirectory, botName + Path.GetExtension(botFile)));
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(e);
|
||||
}
|
||||
|
||||
@@ -98,7 +98,6 @@ namespace ConfigGenerator {
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
public List<uint> GamesPlayedWhileIdle { get; set; } = new List<uint>();
|
||||
|
||||
|
||||
internal static BotConfig Load(string filePath) {
|
||||
if (string.IsNullOrEmpty(filePath)) {
|
||||
return null;
|
||||
@@ -116,6 +115,10 @@ namespace ConfigGenerator {
|
||||
return new BotConfig(filePath);
|
||||
}
|
||||
|
||||
if (botConfig == null) {
|
||||
return new BotConfig(filePath);
|
||||
}
|
||||
|
||||
botConfig.FilePath = filePath;
|
||||
|
||||
return botConfig;
|
||||
@@ -125,7 +128,10 @@ namespace ConfigGenerator {
|
||||
private BotConfig() { }
|
||||
|
||||
private BotConfig(string filePath) : base(filePath) {
|
||||
FilePath = filePath;
|
||||
if (string.IsNullOrEmpty(filePath)) {
|
||||
throw new ArgumentNullException("filePath");
|
||||
}
|
||||
|
||||
GamesPlayedWhileIdle.Add(0);
|
||||
Save();
|
||||
}
|
||||
|
||||
@@ -104,12 +104,12 @@
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent Condition=" '$(OS)' != 'Unix' AND '$(ConfigurationName)' == 'Release' ">
|
||||
"$(SolutionDir)tools\ILRepack\ILRepack.exe" /ndebug /internalize /parallel /targetplatform:v4 /wildcards /out:"$(SolutionDir)out\ASF-GUI.exe" "$(TargetDir)$(TargetName).exe" "$(TargetDir)*.dll"
|
||||
del "$(SolutionDir)out\ASF-GUI.exe.config"
|
||||
"$(SolutionDir)tools\ILRepack\ILRepack.exe" /ndebug /internalize /parallel /targetplatform:v4 /wildcards /out:"$(SolutionDir)out\ASF-ConfigGenerator.exe" "$(TargetDir)$(TargetName).exe" "$(TargetDir)*.dll"
|
||||
del "$(SolutionDir)out\ASF-ConfigGenerator.exe.config"
|
||||
</PostBuildEvent>
|
||||
<PostBuildEvent Condition=" '$(OS)' == 'Unix' AND '$(ConfigurationName)' == 'Release' ">
|
||||
mono -O=all "$(SolutionDir)tools/ILRepack/ILRepack.exe" /ndebug /internalize /parallel /targetplatform:v4 /wildcards /out:"$(SolutionDir)out/ASF-GUI.exe" "$(TargetDir)$(TargetName).exe" "$(TargetDir)*.dll"
|
||||
rm "$(SolutionDir)out/ASF-GUI.exe.config"
|
||||
mono -O=all "$(SolutionDir)tools/ILRepack/ILRepack.exe" /ndebug /internalize /parallel /targetplatform:v4 /wildcards /out:"$(SolutionDir)out/ASF-ConfigGenerator.exe" "$(TargetDir)$(TargetName).exe" "$(TargetDir)*.dll"
|
||||
rm "$(SolutionDir)out/ASF-ConfigGenerator.exe.config"
|
||||
</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace ConfigGenerator {
|
||||
@@ -30,7 +31,7 @@ namespace ConfigGenerator {
|
||||
|
||||
internal EnhancedPropertyGrid(ASFConfig config) {
|
||||
if (config == null) {
|
||||
return;
|
||||
throw new ArgumentNullException("config");
|
||||
}
|
||||
|
||||
ASFConfig = config;
|
||||
@@ -68,5 +69,14 @@ namespace ConfigGenerator {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnGotFocus(EventArgs e) {
|
||||
if (e == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
base.OnGotFocus(e);
|
||||
ASFConfig.Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,9 @@ namespace ConfigGenerator {
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
public bool Debug { get; set; } = false;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
public bool Headless { get; set; } = false;
|
||||
|
||||
[JsonProperty(Required = Required.DisallowNull)]
|
||||
public bool AutoUpdates { get; set; } = true;
|
||||
|
||||
@@ -120,6 +123,10 @@ namespace ConfigGenerator {
|
||||
return new GlobalConfig(filePath);
|
||||
}
|
||||
|
||||
if (globalConfig == null) {
|
||||
return new GlobalConfig(filePath);
|
||||
}
|
||||
|
||||
globalConfig.FilePath = filePath;
|
||||
|
||||
// SK2 supports only TCP and UDP steam protocols
|
||||
@@ -163,7 +170,10 @@ namespace ConfigGenerator {
|
||||
private GlobalConfig() { }
|
||||
|
||||
private GlobalConfig(string filePath) : base(filePath) {
|
||||
FilePath = filePath;
|
||||
if (string.IsNullOrEmpty(filePath)) {
|
||||
throw new ArgumentNullException("filePath");
|
||||
}
|
||||
|
||||
Blacklist.AddRange(GlobalBlacklist);
|
||||
Save();
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ using System;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace ConfigGenerator {
|
||||
@@ -121,6 +122,9 @@ namespace ConfigGenerator {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get rid of any potential whitespaces in bot name
|
||||
input = Regex.Replace(input, @"\s+", "");
|
||||
|
||||
configPage.ASFConfig.Rename(input);
|
||||
configPage.RefreshText();
|
||||
} else if (e.TabPage == NewTab) {
|
||||
@@ -144,6 +148,9 @@ namespace ConfigGenerator {
|
||||
return;
|
||||
}
|
||||
|
||||
// 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)) {
|
||||
Logging.LogGenericError("Bot with such name exists already!");
|
||||
|
||||
@@ -10,7 +10,7 @@ using System.Runtime.InteropServices;
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("ConfigGenerator")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2016")]
|
||||
[assembly: AssemblyCopyright("Copyright © ArchiSteamFarm 2015-2016")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace ConfigGenerator {
|
||||
BotEnabled,
|
||||
BotReady,
|
||||
GlobalConfigOpened,
|
||||
GlobalConfigReady,
|
||||
GlobalConfigReady
|
||||
}
|
||||
|
||||
internal static bool Enabled { get; set; } = true;
|
||||
@@ -61,20 +61,20 @@ namespace ConfigGenerator {
|
||||
Logging.LogGenericInfo("Please click the help button to continue.");
|
||||
break;
|
||||
case EPhase.Help:
|
||||
Logging.LogGenericInfo("That's right! On ASF wiki you can find detailed help about every config property you're going to configure in a moment.");
|
||||
Logging.LogGenericInfo("Well done! On ASF wiki you can find detailed help about every config property you're going to configure in a moment.");
|
||||
break;
|
||||
case EPhase.HelpFinished:
|
||||
Logging.LogGenericInfo("Alright, let's start configuring our ASF. Click on the plus [+] button to add your first steam account to ASF!");
|
||||
break;
|
||||
case EPhase.BotNickname:
|
||||
Logging.LogGenericInfo("That's right! You'll be asked for your bot name now. A good example would be a nickname that you're using for the steam account you're configuring right now, or any other name of your choice which will be easy for you to connect with bot instance that is being configured.");
|
||||
Logging.LogGenericInfo("Good job! You'll be asked for your bot name now. A good example would be a nickname that you're using for the steam account you're configuring right now, or any other name of your choice which will be easy for you to connect with bot instance that is being configured. Please don't use spaces in the name.");
|
||||
break;
|
||||
case EPhase.BotNicknameFinished:
|
||||
Logging.LogGenericInfo("As you can see your bot config is now ready to configure!");
|
||||
Logging.LogGenericInfo("First thing that you want to do is switching \"Enabled\" property from False to True, try it!");
|
||||
break;
|
||||
case EPhase.BotEnabled:
|
||||
Logging.LogGenericInfo("That's right! Now your bot instance is enabled. You need to configure at least 2 more config properties - \"SteamLogin\" and \"SteamPassword\". The tutorial will continue after you're done with it. Remember to visit ASF wiki by clicking the help icon if you're unsure how given property should be configured!");
|
||||
Logging.LogGenericInfo("Excellent! Now your bot instance is enabled. You need to configure at least 2 more config properties - \"SteamLogin\" and \"SteamPassword\". The tutorial will continue after you're done with it. Remember to visit ASF wiki by clicking the help icon if you're unsure how given property should be configured!");
|
||||
break;
|
||||
case EPhase.BotReady:
|
||||
Logging.LogGenericInfo("If the data you put is proper, then your bot is ready to run! We need to do only one more thing now. Visit global ASF config, which is labelled as \"ASF\" on your config tab.");
|
||||
@@ -86,7 +86,7 @@ namespace ConfigGenerator {
|
||||
case EPhase.GlobalConfigReady:
|
||||
Logging.LogGenericInfo("Your ASF is now ready! Simply launch ASF process by double-clicking ASF.exe binary and if you did everything properly, you should now notice that ASF logs in on your account and starts farming. If you have SteamGuard or 2FA authorization enabled, ASF will ask you for that once");
|
||||
Logging.LogGenericInfo("Congratulations! You've done everything that is needed in order to make ASF \"work\". I highly recommend reading the wiki now, as ASF offers some really neat features for you to configure, such as offline farming or deciding upon most efficient cards farming algorithm.");
|
||||
Logging.LogGenericInfo("If you'd like to add another steam account for farming, simply click the plus [+] button and add another instance. You can also rename bots and remove them with 2 other buttons. Good luck!");
|
||||
Logging.LogGenericInfo("If you'd like to add another steam account for farming, simply click the plus [+] button and add another instance. You can also rename bots [~] and remove them [-]. Good luck!");
|
||||
Enabled = false;
|
||||
break;
|
||||
}
|
||||
|
||||
6
GUI/App.config
Normal file
6
GUI/App.config
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1"/>
|
||||
</startup>
|
||||
</configuration>
|
||||
35
GUI/Debugging.cs
Normal file
35
GUI/Debugging.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
_ _ _ ____ _ _____
|
||||
/ \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___
|
||||
/ _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \
|
||||
/ ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | |
|
||||
/_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_|
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
namespace GUI {
|
||||
internal static class Debugging {
|
||||
#if DEBUG
|
||||
internal static readonly bool IsDebugBuild = true;
|
||||
#else
|
||||
internal static readonly bool IsDebugBuild = false;
|
||||
#endif
|
||||
|
||||
internal static bool IsReleaseBuild => !IsDebugBuild;
|
||||
}
|
||||
}
|
||||
513
GUI/Form1.Designer.cs
generated
Normal file
513
GUI/Form1.Designer.cs
generated
Normal file
@@ -0,0 +1,513 @@
|
||||
namespace GUI {
|
||||
partial class Form1 {
|
||||
/// <summary>
|
||||
/// Erforderliche Designervariable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Verwendete Ressourcen bereinigen.
|
||||
/// </summary>
|
||||
/// <param name="disposing">True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False.</param>
|
||||
protected override void Dispose(bool disposing) {
|
||||
if (disposing && (components != null)) {
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Vom Windows Form-Designer generierter Code
|
||||
|
||||
/// <summary>
|
||||
/// Erforderliche Methode für die Designerunterstützung.
|
||||
/// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
|
||||
/// </summary>
|
||||
private void InitializeComponent() {
|
||||
this.components = new System.ComponentModel.Container();
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
|
||||
this.button5 = new System.Windows.Forms.Button();
|
||||
this.button4 = new System.Windows.Forms.Button();
|
||||
this.button3 = new System.Windows.Forms.Button();
|
||||
this.button2 = new System.Windows.Forms.Button();
|
||||
this.button1 = new System.Windows.Forms.Button();
|
||||
this.label2 = new System.Windows.Forms.Label();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.textBox2 = new System.Windows.Forms.TextBox();
|
||||
this.textBox1 = new System.Windows.Forms.TextBox();
|
||||
this.comboBox1 = new System.Windows.Forms.ComboBox();
|
||||
this.checkBox3 = new System.Windows.Forms.CheckBox();
|
||||
this.checkBox2 = new System.Windows.Forms.CheckBox();
|
||||
this.checkBox1 = new System.Windows.Forms.CheckBox();
|
||||
this.textBox3 = new System.Windows.Forms.TextBox();
|
||||
this.ASFGUI = new System.Windows.Forms.NotifyIcon(this.components);
|
||||
this.checkBox4 = new System.Windows.Forms.CheckBox();
|
||||
this.button6 = new System.Windows.Forms.Button();
|
||||
this.button7 = new System.Windows.Forms.Button();
|
||||
this.button8 = new System.Windows.Forms.Button();
|
||||
this.button9 = new System.Windows.Forms.Button();
|
||||
this.button10 = new System.Windows.Forms.Button();
|
||||
this.button11 = new System.Windows.Forms.Button();
|
||||
this.button12 = new System.Windows.Forms.Button();
|
||||
this.button13 = new System.Windows.Forms.Button();
|
||||
this.button14 = new System.Windows.Forms.Button();
|
||||
this.button15 = new System.Windows.Forms.Button();
|
||||
this.button16 = new System.Windows.Forms.Button();
|
||||
this.button17 = new System.Windows.Forms.Button();
|
||||
this.button18 = new System.Windows.Forms.Button();
|
||||
this.button19 = new System.Windows.Forms.Button();
|
||||
this.label3 = new System.Windows.Forms.Label();
|
||||
this.label4 = new System.Windows.Forms.Label();
|
||||
this.button20 = new System.Windows.Forms.Button();
|
||||
this.label5 = new System.Windows.Forms.Label();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// button5
|
||||
//
|
||||
this.button5.Location = new System.Drawing.Point(86, 204);
|
||||
this.button5.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
|
||||
this.button5.Name = "button5";
|
||||
this.button5.Size = new System.Drawing.Size(56, 19);
|
||||
this.button5.TabIndex = 27;
|
||||
this.button5.Text = "2fa ok";
|
||||
this.button5.UseVisualStyleBackColor = true;
|
||||
this.button5.Click += new System.EventHandler(this.button5_Click);
|
||||
//
|
||||
// button4
|
||||
//
|
||||
this.button4.Location = new System.Drawing.Point(26, 204);
|
||||
this.button4.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
|
||||
this.button4.Name = "button4";
|
||||
this.button4.Size = new System.Drawing.Size(56, 19);
|
||||
this.button4.TabIndex = 26;
|
||||
this.button4.Text = "2fa code";
|
||||
this.button4.UseVisualStyleBackColor = true;
|
||||
this.button4.Click += new System.EventHandler(this.button4_Click);
|
||||
//
|
||||
// button3
|
||||
//
|
||||
this.button3.Location = new System.Drawing.Point(26, 286);
|
||||
this.button3.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
|
||||
this.button3.Name = "button3";
|
||||
this.button3.Size = new System.Drawing.Size(56, 19);
|
||||
this.button3.TabIndex = 24;
|
||||
this.button3.Text = "Redeem";
|
||||
this.button3.UseVisualStyleBackColor = true;
|
||||
this.button3.Click += new System.EventHandler(this.button3_Click);
|
||||
//
|
||||
// button2
|
||||
//
|
||||
this.button2.Location = new System.Drawing.Point(26, 171);
|
||||
this.button2.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
|
||||
this.button2.Name = "button2";
|
||||
this.button2.Size = new System.Drawing.Size(56, 19);
|
||||
this.button2.TabIndex = 23;
|
||||
this.button2.Text = "Loot";
|
||||
this.button2.UseVisualStyleBackColor = true;
|
||||
this.button2.Click += new System.EventHandler(this.button2_Click);
|
||||
//
|
||||
// button1
|
||||
//
|
||||
this.button1.Location = new System.Drawing.Point(169, 130);
|
||||
this.button1.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
|
||||
this.button1.Name = "button1";
|
||||
this.button1.Size = new System.Drawing.Size(56, 19);
|
||||
this.button1.TabIndex = 22;
|
||||
this.button1.Text = "Send";
|
||||
this.button1.UseVisualStyleBackColor = true;
|
||||
this.button1.Click += new System.EventHandler(this.button1_Click);
|
||||
//
|
||||
// label2
|
||||
//
|
||||
this.label2.AutoSize = true;
|
||||
this.label2.Location = new System.Drawing.Point(579, 13);
|
||||
this.label2.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
|
||||
this.label2.Name = "label2";
|
||||
this.label2.Size = new System.Drawing.Size(39, 13);
|
||||
this.label2.TabIndex = 21;
|
||||
this.label2.Text = "Output";
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Location = new System.Drawing.Point(258, 39);
|
||||
this.label1.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(31, 13);
|
||||
this.label1.TabIndex = 20;
|
||||
this.label1.Text = "Input";
|
||||
//
|
||||
// textBox2
|
||||
//
|
||||
this.textBox2.Location = new System.Drawing.Point(413, 34);
|
||||
this.textBox2.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
|
||||
this.textBox2.Multiline = true;
|
||||
this.textBox2.Name = "textBox2";
|
||||
this.textBox2.ReadOnly = true;
|
||||
this.textBox2.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
|
||||
this.textBox2.Size = new System.Drawing.Size(432, 370);
|
||||
this.textBox2.TabIndex = 19;
|
||||
//
|
||||
// textBox1
|
||||
//
|
||||
this.textBox1.Location = new System.Drawing.Point(169, 61);
|
||||
this.textBox1.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
|
||||
this.textBox1.Multiline = true;
|
||||
this.textBox1.Name = "textBox1";
|
||||
this.textBox1.Size = new System.Drawing.Size(223, 65);
|
||||
this.textBox1.TabIndex = 18;
|
||||
//
|
||||
// comboBox1
|
||||
//
|
||||
this.comboBox1.FormattingEnabled = true;
|
||||
this.comboBox1.Location = new System.Drawing.Point(26, 116);
|
||||
this.comboBox1.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
|
||||
this.comboBox1.Name = "comboBox1";
|
||||
this.comboBox1.Size = new System.Drawing.Size(92, 21);
|
||||
this.comboBox1.TabIndex = 17;
|
||||
this.comboBox1.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged);
|
||||
//
|
||||
// checkBox3
|
||||
//
|
||||
this.checkBox3.AutoSize = true;
|
||||
this.checkBox3.Location = new System.Drawing.Point(26, 94);
|
||||
this.checkBox3.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
|
||||
this.checkBox3.Name = "checkBox3";
|
||||
this.checkBox3.Size = new System.Drawing.Size(102, 17);
|
||||
this.checkBox3.TabIndex = 16;
|
||||
this.checkBox3.Text = "Send to specific";
|
||||
this.checkBox3.UseVisualStyleBackColor = true;
|
||||
this.checkBox3.CheckedChanged += new System.EventHandler(this.checkBox3_CheckedChanged);
|
||||
//
|
||||
// checkBox2
|
||||
//
|
||||
this.checkBox2.AutoSize = true;
|
||||
this.checkBox2.Location = new System.Drawing.Point(26, 72);
|
||||
this.checkBox2.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
|
||||
this.checkBox2.Name = "checkBox2";
|
||||
this.checkBox2.Size = new System.Drawing.Size(100, 17);
|
||||
this.checkBox2.TabIndex = 15;
|
||||
this.checkBox2.Text = "Send to all Bots";
|
||||
this.checkBox2.UseVisualStyleBackColor = true;
|
||||
this.checkBox2.CheckedChanged += new System.EventHandler(this.checkBox2_CheckedChanged);
|
||||
//
|
||||
// checkBox1
|
||||
//
|
||||
this.checkBox1.AutoSize = true;
|
||||
this.checkBox1.Location = new System.Drawing.Point(107, 11);
|
||||
this.checkBox1.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
|
||||
this.checkBox1.Name = "checkBox1";
|
||||
this.checkBox1.Size = new System.Drawing.Size(74, 17);
|
||||
this.checkBox1.TabIndex = 14;
|
||||
this.checkBox1.Text = "Safemode";
|
||||
this.checkBox1.UseVisualStyleBackColor = true;
|
||||
this.checkBox1.CheckedChanged += new System.EventHandler(this.checkBox1_CheckedChanged);
|
||||
//
|
||||
// textBox3
|
||||
//
|
||||
this.textBox3.Location = new System.Drawing.Point(26, 387);
|
||||
this.textBox3.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
|
||||
this.textBox3.Name = "textBox3";
|
||||
this.textBox3.Size = new System.Drawing.Size(366, 20);
|
||||
this.textBox3.TabIndex = 28;
|
||||
this.textBox3.TextChanged += new System.EventHandler(this.textBox3_TextChanged);
|
||||
//
|
||||
// ASFGUI
|
||||
//
|
||||
this.ASFGUI.Text = "notifyIcon1";
|
||||
this.ASFGUI.Visible = true;
|
||||
this.ASFGUI.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.ASFGUI_MouseDoubleClick);
|
||||
//
|
||||
// checkBox4
|
||||
//
|
||||
this.checkBox4.AutoSize = true;
|
||||
this.checkBox4.Location = new System.Drawing.Point(26, 11);
|
||||
this.checkBox4.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
|
||||
this.checkBox4.Name = "checkBox4";
|
||||
this.checkBox4.Size = new System.Drawing.Size(83, 17);
|
||||
this.checkBox4.TabIndex = 29;
|
||||
this.checkBox4.Text = "Send to any";
|
||||
this.checkBox4.UseVisualStyleBackColor = true;
|
||||
this.checkBox4.CheckedChanged += new System.EventHandler(this.checkBox4_CheckedChanged);
|
||||
//
|
||||
// button6
|
||||
//
|
||||
this.button6.Location = new System.Drawing.Point(26, 41);
|
||||
this.button6.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
|
||||
this.button6.Name = "button6";
|
||||
this.button6.Size = new System.Drawing.Size(94, 27);
|
||||
this.button6.TabIndex = 30;
|
||||
this.button6.Text = "generate Botlist";
|
||||
this.button6.UseVisualStyleBackColor = true;
|
||||
this.button6.Click += new System.EventHandler(this.button6_Click);
|
||||
//
|
||||
// button7
|
||||
//
|
||||
this.button7.Location = new System.Drawing.Point(147, 204);
|
||||
this.button7.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
|
||||
this.button7.Name = "button7";
|
||||
this.button7.Size = new System.Drawing.Size(56, 19);
|
||||
this.button7.TabIndex = 31;
|
||||
this.button7.Text = "2fano";
|
||||
this.button7.UseVisualStyleBackColor = true;
|
||||
this.button7.Click += new System.EventHandler(this.button7_Click);
|
||||
//
|
||||
// button8
|
||||
//
|
||||
this.button8.Location = new System.Drawing.Point(87, 286);
|
||||
this.button8.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
|
||||
this.button8.Name = "button8";
|
||||
this.button8.Size = new System.Drawing.Size(56, 19);
|
||||
this.button8.TabIndex = 32;
|
||||
this.button8.Text = "2faoff";
|
||||
this.button8.UseVisualStyleBackColor = true;
|
||||
this.button8.Click += new System.EventHandler(this.button8_Click);
|
||||
//
|
||||
// button9
|
||||
//
|
||||
this.button9.Location = new System.Drawing.Point(148, 286);
|
||||
this.button9.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
|
||||
this.button9.Name = "button9";
|
||||
this.button9.Size = new System.Drawing.Size(56, 19);
|
||||
this.button9.TabIndex = 33;
|
||||
this.button9.Text = "exit";
|
||||
this.button9.UseVisualStyleBackColor = true;
|
||||
this.button9.Click += new System.EventHandler(this.button9_Click);
|
||||
//
|
||||
// button10
|
||||
//
|
||||
this.button10.Location = new System.Drawing.Point(86, 171);
|
||||
this.button10.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
|
||||
this.button10.Name = "button10";
|
||||
this.button10.Size = new System.Drawing.Size(56, 19);
|
||||
this.button10.TabIndex = 34;
|
||||
this.button10.Text = "farm";
|
||||
this.button10.UseVisualStyleBackColor = true;
|
||||
this.button10.Click += new System.EventHandler(this.button10_Click);
|
||||
//
|
||||
// button11
|
||||
//
|
||||
this.button11.Location = new System.Drawing.Point(147, 171);
|
||||
this.button11.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
|
||||
this.button11.Name = "button11";
|
||||
this.button11.Size = new System.Drawing.Size(56, 19);
|
||||
this.button11.TabIndex = 35;
|
||||
this.button11.Text = "help";
|
||||
this.button11.UseVisualStyleBackColor = true;
|
||||
this.button11.Click += new System.EventHandler(this.button11_Click);
|
||||
//
|
||||
// button12
|
||||
//
|
||||
this.button12.Location = new System.Drawing.Point(208, 171);
|
||||
this.button12.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
|
||||
this.button12.Name = "button12";
|
||||
this.button12.Size = new System.Drawing.Size(56, 19);
|
||||
this.button12.TabIndex = 36;
|
||||
this.button12.Text = "start";
|
||||
this.button12.UseVisualStyleBackColor = true;
|
||||
this.button12.Click += new System.EventHandler(this.button12_Click);
|
||||
//
|
||||
// button13
|
||||
//
|
||||
this.button13.Location = new System.Drawing.Point(268, 171);
|
||||
this.button13.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
|
||||
this.button13.Name = "button13";
|
||||
this.button13.Size = new System.Drawing.Size(56, 19);
|
||||
this.button13.TabIndex = 37;
|
||||
this.button13.Text = "stop";
|
||||
this.button13.UseVisualStyleBackColor = true;
|
||||
this.button13.Click += new System.EventHandler(this.button13_Click);
|
||||
//
|
||||
// button14
|
||||
//
|
||||
this.button14.Location = new System.Drawing.Point(329, 171);
|
||||
this.button14.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
|
||||
this.button14.Name = "button14";
|
||||
this.button14.Size = new System.Drawing.Size(56, 19);
|
||||
this.button14.TabIndex = 38;
|
||||
this.button14.Text = "pause";
|
||||
this.button14.UseVisualStyleBackColor = true;
|
||||
this.button14.Click += new System.EventHandler(this.button14_Click);
|
||||
//
|
||||
// button15
|
||||
//
|
||||
this.button15.Location = new System.Drawing.Point(268, 204);
|
||||
this.button15.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
|
||||
this.button15.Name = "button15";
|
||||
this.button15.Size = new System.Drawing.Size(56, 19);
|
||||
this.button15.TabIndex = 39;
|
||||
this.button15.Text = "status";
|
||||
this.button15.UseVisualStyleBackColor = true;
|
||||
this.button15.Click += new System.EventHandler(this.button15_Click);
|
||||
//
|
||||
// button16
|
||||
//
|
||||
this.button16.Location = new System.Drawing.Point(329, 204);
|
||||
this.button16.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
|
||||
this.button16.Name = "button16";
|
||||
this.button16.Size = new System.Drawing.Size(56, 19);
|
||||
this.button16.TabIndex = 40;
|
||||
this.button16.Text = "status all";
|
||||
this.button16.UseVisualStyleBackColor = true;
|
||||
this.button16.Click += new System.EventHandler(this.button16_Click);
|
||||
//
|
||||
// button17
|
||||
//
|
||||
this.button17.Location = new System.Drawing.Point(26, 318);
|
||||
this.button17.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
|
||||
this.button17.Name = "button17";
|
||||
this.button17.Size = new System.Drawing.Size(56, 19);
|
||||
this.button17.TabIndex = 41;
|
||||
this.button17.Text = "owns";
|
||||
this.button17.UseVisualStyleBackColor = true;
|
||||
this.button17.Click += new System.EventHandler(this.button17_Click);
|
||||
//
|
||||
// button18
|
||||
//
|
||||
this.button18.Location = new System.Drawing.Point(147, 318);
|
||||
this.button18.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
|
||||
this.button18.Name = "button18";
|
||||
this.button18.Size = new System.Drawing.Size(56, 19);
|
||||
this.button18.TabIndex = 42;
|
||||
this.button18.Text = "addlicense";
|
||||
this.button18.UseVisualStyleBackColor = true;
|
||||
this.button18.Click += new System.EventHandler(this.button18_Click);
|
||||
//
|
||||
// button19
|
||||
//
|
||||
this.button19.Location = new System.Drawing.Point(87, 318);
|
||||
this.button19.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
|
||||
this.button19.Name = "button19";
|
||||
this.button19.Size = new System.Drawing.Size(56, 19);
|
||||
this.button19.TabIndex = 43;
|
||||
this.button19.Text = "play";
|
||||
this.button19.UseVisualStyleBackColor = true;
|
||||
this.button19.Click += new System.EventHandler(this.button19_Click);
|
||||
//
|
||||
// label3
|
||||
//
|
||||
this.label3.AutoSize = true;
|
||||
this.label3.Location = new System.Drawing.Point(24, 245);
|
||||
this.label3.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
|
||||
this.label3.Name = "label3";
|
||||
this.label3.Size = new System.Drawing.Size(235, 13);
|
||||
this.label3.TabIndex = 44;
|
||||
this.label3.Text = "The following do not work with \"Send to all\" and";
|
||||
//
|
||||
// label4
|
||||
//
|
||||
this.label4.AutoSize = true;
|
||||
this.label4.Location = new System.Drawing.Point(24, 259);
|
||||
this.label4.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
|
||||
this.label4.Name = "label4";
|
||||
this.label4.Size = new System.Drawing.Size(224, 13);
|
||||
this.label4.TabIndex = 45;
|
||||
this.label4.Text = "require confirmation even without \"Safemode\"";
|
||||
//
|
||||
// button20
|
||||
//
|
||||
this.button20.Location = new System.Drawing.Point(231, 130);
|
||||
this.button20.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
|
||||
this.button20.Name = "button20";
|
||||
this.button20.Size = new System.Drawing.Size(56, 19);
|
||||
this.button20.TabIndex = 46;
|
||||
this.button20.Text = "clear";
|
||||
this.button20.UseVisualStyleBackColor = true;
|
||||
this.button20.Click += new System.EventHandler(this.button20_Click);
|
||||
//
|
||||
// label5
|
||||
//
|
||||
this.label5.AutoSize = true;
|
||||
this.label5.Location = new System.Drawing.Point(29, 370);
|
||||
this.label5.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
|
||||
this.label5.Name = "label5";
|
||||
this.label5.Size = new System.Drawing.Size(221, 13);
|
||||
this.label5.TabIndex = 47;
|
||||
this.label5.Text = "If you don\'t know what this is... Don\'t touch it!";
|
||||
//
|
||||
// Form1
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(854, 414);
|
||||
this.Controls.Add(this.label5);
|
||||
this.Controls.Add(this.button20);
|
||||
this.Controls.Add(this.label4);
|
||||
this.Controls.Add(this.label3);
|
||||
this.Controls.Add(this.button19);
|
||||
this.Controls.Add(this.button18);
|
||||
this.Controls.Add(this.button17);
|
||||
this.Controls.Add(this.button16);
|
||||
this.Controls.Add(this.button15);
|
||||
this.Controls.Add(this.button14);
|
||||
this.Controls.Add(this.button13);
|
||||
this.Controls.Add(this.button12);
|
||||
this.Controls.Add(this.button11);
|
||||
this.Controls.Add(this.button10);
|
||||
this.Controls.Add(this.button9);
|
||||
this.Controls.Add(this.button8);
|
||||
this.Controls.Add(this.button7);
|
||||
this.Controls.Add(this.button6);
|
||||
this.Controls.Add(this.checkBox4);
|
||||
this.Controls.Add(this.textBox3);
|
||||
this.Controls.Add(this.button5);
|
||||
this.Controls.Add(this.button4);
|
||||
this.Controls.Add(this.button3);
|
||||
this.Controls.Add(this.button2);
|
||||
this.Controls.Add(this.button1);
|
||||
this.Controls.Add(this.label2);
|
||||
this.Controls.Add(this.label1);
|
||||
this.Controls.Add(this.textBox2);
|
||||
this.Controls.Add(this.textBox1);
|
||||
this.Controls.Add(this.comboBox1);
|
||||
this.Controls.Add(this.checkBox3);
|
||||
this.Controls.Add(this.checkBox2);
|
||||
this.Controls.Add(this.checkBox1);
|
||||
this.Icon = ((System.Drawing.Icon) (resources.GetObject("$this.Icon")));
|
||||
this.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
|
||||
this.Name = "Form1";
|
||||
this.Text = "Form1";
|
||||
this.Load += new System.EventHandler(this.Form1_Load);
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.Button button5;
|
||||
private System.Windows.Forms.Button button4;
|
||||
private System.Windows.Forms.Button button3;
|
||||
private System.Windows.Forms.Button button2;
|
||||
private System.Windows.Forms.Button button1;
|
||||
private System.Windows.Forms.Label label2;
|
||||
private System.Windows.Forms.Label label1;
|
||||
private System.Windows.Forms.TextBox textBox2;
|
||||
private System.Windows.Forms.TextBox textBox1;
|
||||
private System.Windows.Forms.ComboBox comboBox1;
|
||||
private System.Windows.Forms.CheckBox checkBox3;
|
||||
private System.Windows.Forms.CheckBox checkBox2;
|
||||
private System.Windows.Forms.CheckBox checkBox1;
|
||||
private System.Windows.Forms.TextBox textBox3;
|
||||
private System.Windows.Forms.NotifyIcon ASFGUI;
|
||||
private System.Windows.Forms.CheckBox checkBox4;
|
||||
private System.Windows.Forms.Button button6;
|
||||
private System.Windows.Forms.Button button7;
|
||||
private System.Windows.Forms.Button button8;
|
||||
private System.Windows.Forms.Button button9;
|
||||
private System.Windows.Forms.Button button10;
|
||||
private System.Windows.Forms.Button button11;
|
||||
private System.Windows.Forms.Button button12;
|
||||
private System.Windows.Forms.Button button13;
|
||||
private System.Windows.Forms.Button button14;
|
||||
private System.Windows.Forms.Button button15;
|
||||
private System.Windows.Forms.Button button16;
|
||||
private System.Windows.Forms.Button button17;
|
||||
private System.Windows.Forms.Button button18;
|
||||
private System.Windows.Forms.Button button19;
|
||||
private System.Windows.Forms.Label label3;
|
||||
private System.Windows.Forms.Label label4;
|
||||
private System.Windows.Forms.Button button20;
|
||||
private System.Windows.Forms.Label label5;
|
||||
}
|
||||
}
|
||||
|
||||
310
GUI/Form1.cs
Normal file
310
GUI/Form1.cs
Normal file
@@ -0,0 +1,310 @@
|
||||
/*
|
||||
_ _ _ ____ _ _____
|
||||
/ \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___
|
||||
/ _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \
|
||||
/ ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | |
|
||||
/_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_|
|
||||
|
||||
Copyright 2015-2016 Florian "KlappPC" Lang
|
||||
Contact: ichhoeremusik@gmx.net
|
||||
|
||||
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.Windows.Forms;
|
||||
using System.ServiceModel;
|
||||
using System.IO;
|
||||
|
||||
namespace GUI {
|
||||
|
||||
public partial class Form1 : Form {
|
||||
private bool safeMode = false;
|
||||
private bool sendAll = false;
|
||||
private bool sendAny = true;
|
||||
private bool sendOne = false;
|
||||
private string botName = "";
|
||||
string[] botList;
|
||||
private string URL = "";
|
||||
ServerProcess proc;
|
||||
private Client Client;
|
||||
public Form1() {
|
||||
InitializeComponent();
|
||||
|
||||
// So either the ASF.exe is in the same directory, or we assume development environment.
|
||||
string ASF = "ASF.exe";
|
||||
if (!File.Exists(ASF)) {
|
||||
ASF = "../../../ArchiSteamFarm/bin/" + (Debugging.IsDebugBuild ? "Debug" : "Release") + "/ArchiSteamFarm.exe";
|
||||
if (!File.Exists(ASF)) {
|
||||
Logging.LogGenericError("ASF binary could not be found!");
|
||||
Environment.Exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
proc = new ServerProcess(ASF, "--server", textBox2);
|
||||
proc.Start();
|
||||
}
|
||||
|
||||
|
||||
protected override void OnFormClosing(FormClosingEventArgs e) {
|
||||
proc.Stop();
|
||||
base.OnFormClosing(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a single command. can be lead by a ! but it does not have to.
|
||||
*/
|
||||
private string sendCommand(string command) {
|
||||
if (command.StartsWith("!")) {
|
||||
command = command.Substring(1);
|
||||
}
|
||||
if (Client == null) {
|
||||
Client = new Client(new BasicHttpBinding(), new EndpointAddress(URL));
|
||||
}
|
||||
return Client.HandleCommand(command);
|
||||
}
|
||||
|
||||
/**
|
||||
* Maximize again when double clicked on tray icon
|
||||
*/
|
||||
private void ASFGUI_MouseDoubleClick(object sender, MouseEventArgs e) {
|
||||
this.Show();
|
||||
this.WindowState = FormWindowState.Normal;
|
||||
}
|
||||
|
||||
private void Form1_Load(object sender, System.EventArgs e) {
|
||||
this.Resize += new System.EventHandler(this.Form1_Resize);
|
||||
textBox2.ScrollBars = ScrollBars.Vertical;
|
||||
textBox1.ScrollBars = ScrollBars.Vertical;
|
||||
checkBox4.Checked = true;
|
||||
textBox3.Text = "http://localhost:1242/ASF";
|
||||
URL = "http://localhost:1242/ASF";
|
||||
textBox2.Anchor = (AnchorStyles.Right | AnchorStyles.Left);
|
||||
}
|
||||
/**
|
||||
* Minimize to tray instead of taskbar
|
||||
*/
|
||||
private void Form1_Resize(object sender, EventArgs e) {
|
||||
if (FormWindowState.Minimized == this.WindowState) {
|
||||
ASFGUI.Visible = true;
|
||||
this.Hide();
|
||||
} else if (FormWindowState.Normal == this.WindowState) {
|
||||
ASFGUI.Visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* generate a command from a simple command
|
||||
* That means, adds a botName or makes multiple commands for multiple bots.
|
||||
*/
|
||||
private string generateCommand(string command, string arg = "") {
|
||||
if (sendOne)
|
||||
return command + " " + botName + " " + arg;
|
||||
if (sendAll) {
|
||||
string ret = "";
|
||||
foreach (string str in botList) {
|
||||
ret = ret + command + " " + str + " " + arg + "\r\n";
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
return command + arg;
|
||||
}
|
||||
/**
|
||||
* One of the simple buttons got pressed
|
||||
*/
|
||||
private void buttonPressed(string command) {
|
||||
textBox1.Text = generateCommand(command);
|
||||
if (!safeMode)
|
||||
button1_Click(this, null);
|
||||
}
|
||||
/**
|
||||
* One of the complicated buttons was pressed
|
||||
* We get an argumentlist
|
||||
*/
|
||||
private void multiCommand(string command) {
|
||||
if (sendAll)
|
||||
return;
|
||||
string[] arr = textBox1.Lines;
|
||||
string cmd = "";
|
||||
for (int i = 0; i < arr.Length; i++) {
|
||||
if (!String.IsNullOrEmpty(arr[i].Trim())) {
|
||||
cmd = cmd + generateCommand(command, arr[i].Trim()) + "\r\n";
|
||||
}
|
||||
}
|
||||
textBox1.Text = cmd;
|
||||
}
|
||||
|
||||
/**
|
||||
* updates the WCF URL in case of custom URL
|
||||
*/
|
||||
private void textBox3_TextChanged(object sender, EventArgs e) {
|
||||
URL = textBox3.Text;
|
||||
}
|
||||
|
||||
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) {
|
||||
botName = comboBox1.SelectedItem.ToString();
|
||||
}
|
||||
//Ok, radiobuttons would have been better I guess, to lazy to change now.
|
||||
private void checkBox3_CheckedChanged(object sender, EventArgs e) {
|
||||
//specific
|
||||
if (checkBox3.Checked) {
|
||||
sendAll = false;
|
||||
sendAny = false;
|
||||
sendOne = true;
|
||||
checkBox2.Checked = false;
|
||||
checkBox4.Checked = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void checkBox2_CheckedChanged(object sender, EventArgs e) {
|
||||
//all
|
||||
if (checkBox2.Checked) {
|
||||
sendAll = true;
|
||||
sendAny = false;
|
||||
sendOne = false;
|
||||
checkBox3.Checked = false;
|
||||
checkBox4.Checked = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void checkBox4_CheckedChanged(object sender, EventArgs e) {
|
||||
//any
|
||||
if (checkBox4.Checked) {
|
||||
sendAll = false;
|
||||
sendAny = true;
|
||||
sendOne = false;
|
||||
checkBox2.Checked = false;
|
||||
checkBox3.Checked = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void checkBox1_CheckedChanged(object sender, EventArgs e) {
|
||||
safeMode = checkBox1.Checked;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send command button.
|
||||
*/
|
||||
private void button1_Click(object sender, System.EventArgs e) {
|
||||
for (int i = 0; i < textBox1.Lines.Length; i++) {
|
||||
string command = textBox1.Lines[i];
|
||||
if (!String.IsNullOrEmpty(command.Trim())) {
|
||||
sendCommand(command);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* Update /Generate Botlist button
|
||||
*/
|
||||
private void button6_Click(object sender, EventArgs e) {
|
||||
string ret = sendCommand("statusall");
|
||||
string[] arr = ret.Split('\n');
|
||||
int botAmount = Convert.ToInt16(arr[arr.Length - 1].Split('/')[1].Trim().Split(' ')[0]);
|
||||
botList = new string[botAmount];
|
||||
for (int i = 0; i < botAmount; i++) {
|
||||
botList[i] = arr[arr.Length - 2 - i].Substring(3).Trim().Split(' ')[0];
|
||||
}
|
||||
comboBox1.Items.AddRange(botList);
|
||||
}
|
||||
|
||||
//The Rest are simple buttons.
|
||||
private void button3_Click(object sender, EventArgs e) {
|
||||
multiCommand("redeem");
|
||||
}
|
||||
private void button2_Click(object sender, EventArgs e) {
|
||||
textBox1.Text = generateCommand("loot");
|
||||
if (!safeMode)
|
||||
button1_Click(this, null);
|
||||
}
|
||||
private void button4_Click(object sender, EventArgs e) {
|
||||
//2fa
|
||||
textBox1.Text = generateCommand("2fa");
|
||||
if (!safeMode)
|
||||
button1_Click(this, null);
|
||||
}
|
||||
private void button5_Click(object sender, EventArgs e) {
|
||||
buttonPressed("2faok");
|
||||
}
|
||||
private void button7_Click(object sender, EventArgs e) {
|
||||
buttonPressed("2fano");
|
||||
}
|
||||
private void button8_Click(object sender, EventArgs e) {
|
||||
if (sendAll)
|
||||
return;
|
||||
textBox1.Text = generateCommand("2faoff");
|
||||
}
|
||||
private void button9_Click(object sender, EventArgs e) {
|
||||
textBox1.Text = "exit";
|
||||
}
|
||||
private void button10_Click(object sender, EventArgs e) {
|
||||
buttonPressed("farm");
|
||||
}
|
||||
private void button11_Click(object sender, EventArgs e) {
|
||||
buttonPressed("help");
|
||||
}
|
||||
private void button12_Click(object sender, EventArgs e) {
|
||||
buttonPressed("start");
|
||||
}
|
||||
private void button13_Click(object sender, EventArgs e) {
|
||||
buttonPressed("stop");
|
||||
}
|
||||
private void button14_Click(object sender, EventArgs e) {
|
||||
buttonPressed("pause");
|
||||
}
|
||||
private void button15_Click(object sender, EventArgs e) {
|
||||
buttonPressed("status");
|
||||
}
|
||||
private void button16_Click(object sender, EventArgs e) {
|
||||
textBox1.Text = "statusall";
|
||||
if (!safeMode)
|
||||
button1_Click(this, null);
|
||||
}
|
||||
private void button17_Click(object sender, EventArgs e) {
|
||||
multiCommand("owns");
|
||||
}
|
||||
private void button18_Click(object sender, EventArgs e) {
|
||||
multiCommand("addlicense");
|
||||
}
|
||||
private void button19_Click(object sender, EventArgs e) {
|
||||
multiCommand("play");
|
||||
}
|
||||
private void button20_Click(object sender, EventArgs e) {
|
||||
textBox1.Text = "";
|
||||
}
|
||||
}
|
||||
|
||||
//############### After this point copied from Archie's WCF ###################
|
||||
[ServiceContract]
|
||||
interface IWCF {
|
||||
[OperationContract]
|
||||
string HandleCommand(string input);
|
||||
}
|
||||
class Client : ClientBase<IWCF>, IWCF {
|
||||
internal Client(System.ServiceModel.Channels.Binding binding, EndpointAddress address) : base(binding, address) { }
|
||||
|
||||
public string HandleCommand(string input) {
|
||||
try {
|
||||
return Channel.HandleCommand(input);
|
||||
} catch (Exception e) {
|
||||
//Logging.LogGenericException(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
6296
GUI/Form1.resx
Normal file
6296
GUI/Form1.resx
Normal file
File diff suppressed because it is too large
Load Diff
84
GUI/Form2.Designer.cs
generated
Normal file
84
GUI/Form2.Designer.cs
generated
Normal file
@@ -0,0 +1,84 @@
|
||||
namespace GUI {
|
||||
partial class Form2 {
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing) {
|
||||
if (disposing && (components != null)) {
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent() {
|
||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form2));
|
||||
this.button1 = new System.Windows.Forms.Button();
|
||||
this.textBox1 = new System.Windows.Forms.TextBox();
|
||||
this.label1 = new System.Windows.Forms.Label();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// button1
|
||||
//
|
||||
this.button1.Location = new System.Drawing.Point(134, 93);
|
||||
this.button1.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
|
||||
this.button1.Name = "button1";
|
||||
this.button1.Size = new System.Drawing.Size(87, 28);
|
||||
this.button1.TabIndex = 0;
|
||||
this.button1.Text = "OK";
|
||||
this.button1.UseVisualStyleBackColor = true;
|
||||
this.button1.Click += new System.EventHandler(this.button1_Click);
|
||||
//
|
||||
// textBox1
|
||||
//
|
||||
this.textBox1.Location = new System.Drawing.Point(12, 63);
|
||||
this.textBox1.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
|
||||
this.textBox1.Name = "textBox1";
|
||||
this.textBox1.Size = new System.Drawing.Size(336, 20);
|
||||
this.textBox1.TabIndex = 1;
|
||||
//
|
||||
// label1
|
||||
//
|
||||
this.label1.AutoSize = true;
|
||||
this.label1.Location = new System.Drawing.Point(10, 7);
|
||||
this.label1.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
|
||||
this.label1.Name = "label1";
|
||||
this.label1.Size = new System.Drawing.Size(35, 13);
|
||||
this.label1.TabIndex = 2;
|
||||
this.label1.Text = "label1";
|
||||
//
|
||||
// Form2
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(356, 132);
|
||||
this.Controls.Add(this.label1);
|
||||
this.Controls.Add(this.textBox1);
|
||||
this.Controls.Add(this.button1);
|
||||
this.Icon = ((System.Drawing.Icon) (resources.GetObject("$this.Icon")));
|
||||
this.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
|
||||
this.Name = "Form2";
|
||||
this.Text = "Input";
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private System.Windows.Forms.Button button1;
|
||||
private System.Windows.Forms.TextBox textBox1;
|
||||
private System.Windows.Forms.Label label1;
|
||||
}
|
||||
}
|
||||
44
GUI/Form2.cs
Normal file
44
GUI/Form2.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
_ _ _ ____ _ _____
|
||||
/ \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___
|
||||
/ _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \
|
||||
/ ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | |
|
||||
/_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_|
|
||||
|
||||
Copyright 2015-2016 Florian "KlappPC" Lang
|
||||
Contact: ichhoeremusik@gmx.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.Windows.Forms;
|
||||
|
||||
namespace GUI {
|
||||
/**
|
||||
* popup Message when Input is required
|
||||
*/
|
||||
public partial class Form2 : Form {
|
||||
ServerProcess proc;
|
||||
public Form2(ServerProcess proc, string msg) {
|
||||
this.proc = proc;
|
||||
InitializeComponent();
|
||||
label1.Text = msg;
|
||||
button1.DialogResult = DialogResult.OK;
|
||||
}
|
||||
|
||||
private void button1_Click(object sender, EventArgs e) {
|
||||
proc.Write(textBox1.Text);
|
||||
}
|
||||
}
|
||||
}
|
||||
6293
GUI/Form2.resx
Normal file
6293
GUI/Form2.resx
Normal file
File diff suppressed because it is too large
Load Diff
154
GUI/GUI.csproj
Normal file
154
GUI/GUI.csproj
Normal file
@@ -0,0 +1,154 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{599121A9-5887-4522-A3D6-61470B90BAD4}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>GUI</RootNamespace>
|
||||
<AssemblyName>GUI</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<PublishUrl>publish\</PublishUrl>
|
||||
<Install>true</Install>
|
||||
<InstallFrom>Disk</InstallFrom>
|
||||
<UpdateEnabled>false</UpdateEnabled>
|
||||
<UpdateMode>Foreground</UpdateMode>
|
||||
<UpdateInterval>7</UpdateInterval>
|
||||
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||
<UpdatePeriodically>false</UpdatePeriodically>
|
||||
<UpdateRequired>false</UpdateRequired>
|
||||
<MapFileExtensions>true</MapFileExtensions>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
<TargetFrameworkProfile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>none</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>
|
||||
</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>cirno.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.ServiceModel" />
|
||||
<Reference Include="System.ServiceModel.Web" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Debugging.cs" />
|
||||
<Compile Include="Form1.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Form1.Designer.cs">
|
||||
<DependentUpon>Form1.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Form2.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Form2.Designer.cs">
|
||||
<DependentUpon>Form2.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Logging.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="ServerProcess.cs" />
|
||||
<EmbeddedResource Include="Form1.resx">
|
||||
<DependentUpon>Form1.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Form2.resx">
|
||||
<DependentUpon>Form2.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
</Compile>
|
||||
<None Include="app.manifest" />
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<WCFMetadata Include="Service References\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include=".NETFramework,Version=v4.5">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>Microsoft .NET Framework 4.5 %28x86 and x64%29</ProductName>
|
||||
<Install>true</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="cirno.ico" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent Condition=" '$(OS)' != 'Unix' AND '$(ConfigurationName)' == 'Release' ">
|
||||
"$(SolutionDir)tools\ILRepack\ILRepack.exe" /ndebug /internalize /parallel /targetplatform:v4 /wildcards /out:"$(SolutionDir)out\ASF-GUI.exe" "$(TargetDir)$(TargetName).exe" "$(TargetDir)*.dll"
|
||||
del "$(SolutionDir)out\ASF-GUI.exe.config"
|
||||
</PostBuildEvent>
|
||||
<PostBuildEvent Condition=" '$(OS)' == 'Unix' AND '$(ConfigurationName)' == 'Release' ">
|
||||
mono -O=all "$(SolutionDir)tools/ILRepack/ILRepack.exe" /ndebug /internalize /parallel /targetplatform:v4 /wildcards /out:"$(SolutionDir)out/ASF-GUI.exe" "$(TargetDir)$(TargetName).exe" "$(TargetDir)*.dll"
|
||||
rm "$(SolutionDir)out/ASF-GUI.exe.config"
|
||||
</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
93
GUI/Logging.cs
Normal file
93
GUI/Logging.cs
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
_ _ _ ____ _ _____
|
||||
/ \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___
|
||||
/ _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \
|
||||
/ ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | |
|
||||
/_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_|
|
||||
|
||||
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.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace GUI {
|
||||
internal static class Logging {
|
||||
internal static void LogGenericInfo(string message) {
|
||||
if (string.IsNullOrEmpty(message)) {
|
||||
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);
|
||||
}
|
||||
|
||||
internal static void LogGenericError(string message, [CallerMemberName] string previousMethodName = "") {
|
||||
if (string.IsNullOrEmpty(message)) {
|
||||
return;
|
||||
}
|
||||
|
||||
MessageBox.Show(previousMethodName + "() " + message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
|
||||
internal static void LogGenericException(Exception exception, [CallerMemberName] string previousMethodName = "") {
|
||||
if (exception == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
MessageBox.Show(previousMethodName + "() " + exception.Message + Environment.NewLine + exception.StackTrace, "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
|
||||
if (exception.InnerException != null) {
|
||||
LogGenericException(exception.InnerException, previousMethodName);
|
||||
}
|
||||
}
|
||||
|
||||
internal static void LogGenericWarning(string message, [CallerMemberName] string previousMethodName = "") {
|
||||
if (string.IsNullOrEmpty(message)) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
16
GUI/Program.cs
Normal file
16
GUI/Program.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace GUI {
|
||||
static class Program {
|
||||
/// <summary>
|
||||
/// Der Haupteinstiegspunkt für die Anwendung.
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
static void Main() {
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
Application.Run(new Form1());
|
||||
}
|
||||
}
|
||||
}
|
||||
36
GUI/Properties/AssemblyInfo.cs
Normal file
36
GUI/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// Allgemeine Informationen über eine Assembly werden über die folgenden
|
||||
// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
|
||||
// die mit einer Assembly verknüpft sind.
|
||||
[assembly: AssemblyTitle("GUI")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("GUI")]
|
||||
[assembly: AssemblyCopyright("Copyright © ArchiSteamFarm 2015-2016")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar
|
||||
// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von
|
||||
// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
|
||||
[assembly: Guid("18b85645-1c80-4e25-9dcb-e01684a48fca")]
|
||||
|
||||
// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
|
||||
//
|
||||
// Hauptversion
|
||||
// Nebenversion
|
||||
// Buildnummer
|
||||
// Revision
|
||||
//
|
||||
// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern
|
||||
// übernehmen, indem Sie "*" eingeben:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
63
GUI/Properties/Resources.Designer.cs
generated
Normal file
63
GUI/Properties/Resources.Designer.cs
generated
Normal file
@@ -0,0 +1,63 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace GUI.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("GUI.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
117
GUI/Properties/Resources.resx
Normal file
117
GUI/Properties/Resources.resx
Normal file
@@ -0,0 +1,117 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
26
GUI/Properties/Settings.Designer.cs
generated
Normal file
26
GUI/Properties/Settings.Designer.cs
generated
Normal file
@@ -0,0 +1,26 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace GUI.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default {
|
||||
get {
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
7
GUI/Properties/Settings.settings
Normal file
7
GUI/Properties/Settings.settings
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
</SettingsFile>
|
||||
180
GUI/ServerProcess.cs
Normal file
180
GUI/ServerProcess.cs
Normal file
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
_ _ _ ____ _ _____
|
||||
/ \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___
|
||||
/ _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \
|
||||
/ ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | |
|
||||
/_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_|
|
||||
|
||||
Copyright 2015-2016 Florian "KlappPC" Lang
|
||||
Contact: ichhoeremusik@gmx.net
|
||||
This file is mostly done by a friend who explicitly does not want to get mentioned in any way.
|
||||
|
||||
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.Threading;
|
||||
using System.Diagnostics;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace GUI {
|
||||
/*basically a class to run executables as controlled prozess in the background*/
|
||||
public class ServerProcess {
|
||||
//ASF.exe in our case
|
||||
protected Process process;
|
||||
//handling the output.
|
||||
protected Thread outputThread;
|
||||
protected bool stopping;
|
||||
|
||||
//the textbox from our Form, where we want to display output.
|
||||
private TextBox output;
|
||||
|
||||
private object lockObj = new object();
|
||||
|
||||
/**
|
||||
* New SeverProcess for filename with arguments and output to textBox.
|
||||
* Console is hidden and IO redirected.
|
||||
*/
|
||||
public ServerProcess(string fileName, string argumants, TextBox textBox) {
|
||||
|
||||
|
||||
output = textBox;
|
||||
process = new System.Diagnostics.Process();
|
||||
|
||||
process.StartInfo.FileName = fileName;
|
||||
process.StartInfo.Arguments = argumants;
|
||||
process.StartInfo.UseShellExecute = false;
|
||||
process.StartInfo.RedirectStandardInput = true;
|
||||
process.StartInfo.RedirectStandardError = true;
|
||||
process.StartInfo.RedirectStandardOutput = true;
|
||||
process.StartInfo.CreateNoWindow = true;
|
||||
|
||||
}
|
||||
//needed for realizing when input is needed.
|
||||
private int dotcounter = 0;
|
||||
|
||||
/**
|
||||
* I'm not quite happy with this. I could not figure a way to notice when input is required
|
||||
* besides reading char by char and searching for keywords. Will stop working, if the "Please enter"
|
||||
* lines gets changed.
|
||||
* Only tested for "Enter Password."
|
||||
*/
|
||||
private void NewOutput(object sender, char e) {
|
||||
MethodInvoker mi = delegate {
|
||||
output.AppendText(e.ToString());
|
||||
};
|
||||
|
||||
if (e == '.') {
|
||||
dotcounter++;
|
||||
} else if (e == ':') {
|
||||
dotcounter = 3;
|
||||
} else {
|
||||
dotcounter = 0;
|
||||
}
|
||||
if (dotcounter == 3) {
|
||||
string[] arr = output.Lines;
|
||||
string str = arr[arr.Length - 1];
|
||||
if (str.Contains("Hit enter")) {
|
||||
str = arr[arr.Length - 2] + " | " + str;
|
||||
Form f = new Form2(this, str);
|
||||
f.ShowDialog();
|
||||
mi = delegate { output.AppendText(e.ToString() + "\n"); };
|
||||
}
|
||||
if (str.Contains("Please enter")) {
|
||||
Form f = new Form2(this, str);
|
||||
f.ShowDialog();
|
||||
mi = delegate { output.AppendText(e.ToString() + "\n"); };
|
||||
}
|
||||
|
||||
dotcounter = 0;
|
||||
}
|
||||
output.Invoke(mi);
|
||||
|
||||
}
|
||||
|
||||
private void NewOutput(object sender, string e) {
|
||||
MethodInvoker mi = delegate {
|
||||
output.AppendText(e + "\n");
|
||||
};
|
||||
output.Invoke(mi);
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void printOutPut() {
|
||||
char str;
|
||||
int i;
|
||||
string s;
|
||||
while (!stopping) {
|
||||
//thats ugly, but when using readline we can't catch input.
|
||||
while (((i = process.StandardOutput.Read()) != 0)) {
|
||||
str = System.Convert.ToChar(i);
|
||||
NewOutput(this, str);
|
||||
if (stopping)
|
||||
break;
|
||||
}
|
||||
|
||||
while (((s = process.StandardError.ReadLine()) != null)) {
|
||||
NewOutput(this, s);
|
||||
if (stopping)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Write(string msg) {
|
||||
process.StandardInput.WriteLine(msg);
|
||||
process.StandardInput.Flush();
|
||||
}
|
||||
|
||||
public void Stop() {
|
||||
Thread stopThread = new Thread(StopProcess);
|
||||
stopThread.Start();
|
||||
}
|
||||
|
||||
private void StopProcess() {
|
||||
|
||||
if (process == null)
|
||||
return;
|
||||
stopping = true;
|
||||
|
||||
outputThread.Abort();
|
||||
|
||||
Thread.Sleep(1000);
|
||||
|
||||
if (process == null)
|
||||
return;
|
||||
|
||||
if (process.HasExited)
|
||||
process.Close();
|
||||
else
|
||||
process.Kill();
|
||||
|
||||
process = null;
|
||||
}
|
||||
/**
|
||||
* starts the process and a second thread to listen for output.
|
||||
*/
|
||||
public void Start() {
|
||||
outputThread = new Thread(printOutPut);
|
||||
process.Start();
|
||||
outputThread.Start();
|
||||
}
|
||||
|
||||
public Process Process {
|
||||
get {
|
||||
return process;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
58
GUI/app.manifest
Normal file
58
GUI/app.manifest
Normal file
@@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
|
||||
<security>
|
||||
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<!-- UAC-Manifestoptionen
|
||||
Wenn Sie die Zugangsebene für das Windows-Benutzerkonto ändern möchten, ersetzen Sie den
|
||||
requestedExecutionLevel-Knoten durch eines der folgenden Elemente.
|
||||
|
||||
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
|
||||
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
|
||||
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
|
||||
|
||||
Durch Angeben des requestedExecutionLevel-Knotens wird die Datei- und Registrierungsvirtualisierung deaktiviert.
|
||||
Wenn Sie Datei- und Registrierungsvirtualisierung für Abwärts-
|
||||
kompatibilität verwenden möchten, löschen Sie den requestedExecutionLevel-Knoten.
|
||||
-->
|
||||
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||
<application>
|
||||
<!-- Eine Liste aller Windows-Versionen, mit denen die Anwendung kompatibel ist.
|
||||
Windows wählt automatisch die am stärksten kompatible Umgebung aus.-->
|
||||
|
||||
<!-- Wenn die Anwendung mit Windows Vista kompatibel ist, heben Sie die Auskommentierung des folgenden supportedOS-Knotens auf-->
|
||||
<!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"></supportedOS>-->
|
||||
|
||||
<!-- Wenn die Anwendung mit Windows 7 kompatibel ist, heben Sie die Kommentierung des folgenden supportedOS-Knotens auf.-->
|
||||
<!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>-->
|
||||
|
||||
<!-- Wenn die Anwendung mit Windows 8 kompatibel ist, heben Sie die Auskommentierung des folgenden supportedOS-Knotens auf-->
|
||||
<!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"></supportedOS>-->
|
||||
|
||||
<!-- Wenn die Anwendung mit Windows 8.1 kompatibel ist, die Kommentierung des folgenden supportedOS-Knotens aufheben.-->
|
||||
<!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>-->
|
||||
|
||||
</application>
|
||||
</compatibility>
|
||||
|
||||
<!-- Designs für allgemeine Windows-Steuerelemente und -Dialogfelder (Windows XP und höher) aktivieren -->
|
||||
<!-- <dependency>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity
|
||||
type="win32"
|
||||
name="Microsoft.Windows.Common-Controls"
|
||||
version="6.0.0.0"
|
||||
processorArchitecture="*"
|
||||
publicKeyToken="6595b64144ccf1df"
|
||||
language="*"
|
||||
/>
|
||||
</dependentAssembly>
|
||||
</dependency>-->
|
||||
|
||||
</asmv1:assembly>
|
||||
BIN
GUI/cirno.ico
Normal file
BIN
GUI/cirno.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 361 KiB |
66
cc.sh
Executable file
66
cc.sh
Executable file
@@ -0,0 +1,66 @@
|
||||
#!/bin/bash
|
||||
set -eu
|
||||
|
||||
BUILD="Release"
|
||||
CLEAN=0
|
||||
|
||||
MONO_ARGS=("--aot" "--llvm" "--server" "-O=all")
|
||||
XBUILD_ARGS=("/nologo")
|
||||
BINARIES=("ArchiSteamFarm/bin/Release/ArchiSteamFarm.exe")
|
||||
SOLUTION="ArchiSteamFarm.sln"
|
||||
|
||||
PRINT_USAGE() {
|
||||
echo "Usage: $0 [--clean] [debug/release]"
|
||||
exit 1
|
||||
}
|
||||
|
||||
for ARG in "$@"; do
|
||||
case "$ARG" in
|
||||
release|Release) BUILD="Release" ;;
|
||||
debug|Debug) BUILD="Debug" ;;
|
||||
--clean) CLEAN=1 ;;
|
||||
*) PRINT_USAGE
|
||||
esac
|
||||
done
|
||||
|
||||
XBUILD_ARGS+=("/p:Configuration=$BUILD")
|
||||
|
||||
cd "$(dirname "$(readlink -f "$0")")"
|
||||
|
||||
if [[ -d ".git" ]] && hash git &>/dev/null; then
|
||||
git pull
|
||||
fi
|
||||
|
||||
if [[ ! -f "$SOLUTION" ]]; then
|
||||
echo "ERROR: $SOLUTION could not be found!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if hash nuget &>/dev/null; then
|
||||
nuget restore "$SOLUTION"
|
||||
fi
|
||||
|
||||
if [[ "$CLEAN" -eq 1 ]]; then
|
||||
rm -rf out
|
||||
xbuild "${XBUILD_ARGS[@]}" "/t:Clean" "$SOLUTION"
|
||||
fi
|
||||
|
||||
xbuild "${XBUILD_ARGS[@]}" "$SOLUTION"
|
||||
|
||||
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
|
||||
for BINARY in "${BINARIES[@]}"; do
|
||||
if [[ ! -f "$BINARY" ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
mono "${MONO_ARGS[@]}" "$BINARY"
|
||||
done
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "Compilation finished successfully! :)"
|
||||
28
run.sh
Executable file
28
run.sh
Executable file
@@ -0,0 +1,28 @@
|
||||
#!/bin/bash
|
||||
set -eu
|
||||
|
||||
BUILD="Release"
|
||||
|
||||
MONO_ARGS=("--llvm" "--server" "-O=all")
|
||||
|
||||
PRINT_USAGE() {
|
||||
echo "Usage: $0 [debug/release]"
|
||||
exit 1
|
||||
}
|
||||
|
||||
for ARG in "$@"; do
|
||||
case "$ARG" in
|
||||
release|Release) BUILD="Release" ;;
|
||||
debug|Debug) BUILD="Debug" ;;
|
||||
*) PRINT_USAGE
|
||||
esac
|
||||
done
|
||||
|
||||
BINARY="ArchiSteamFarm/bin/$BUILD/ArchiSteamFarm.exe"
|
||||
|
||||
if [[ ! -f "$BINARY" ]]; then
|
||||
echo "ERROR: $BINARY could not be found!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mono "${MONO_ARGS[@]}" "$BINARY"
|
||||
Reference in New Issue
Block a user