diff --git a/ArchiSteamFarm/ArchiWebHandler.cs b/ArchiSteamFarm/ArchiWebHandler.cs index 63996608c..ebd678e60 100644 --- a/ArchiSteamFarm/ArchiWebHandler.cs +++ b/ArchiSteamFarm/ArchiWebHandler.cs @@ -21,7 +21,9 @@ limitations under the License. */ - +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System.Linq; using HtmlAgilityPack; using SteamKit2; using System; @@ -371,6 +373,78 @@ namespace ArchiSteamFarm { return response != null; // Steam API doesn't respond with any error code, assume any response is a success } + public class Inventory { + public string id { get; set; } + public string classid { get; set; } + public string instanceid { get; set; } + public string amount { get; set; } + public int pos { get; set; } + } + + internal async Task> GetInventory() { + List result = new List(); + try { + string json = await WebBrowser.UrlGetToContent("http://steamcommunity.com/my/inventory/json/753/6", Cookie).ConfigureAwait(false); + JObject jobj = JObject.Parse(json); + IList results = jobj.SelectTokens("$.rgInventory.*").ToList(); + foreach (JToken res in results) { + result.Add(JsonConvert.DeserializeObject(res.ToString())); + } + } catch (Exception) { + //just return empty list on error + } + return result; + } + + internal async Task SendTradeOffer(List itemsSend, string masterid,string token=null) { + string sessionID; + if (!Cookie.TryGetValue("sessionid", out sessionID)) { + return false; + } + + JObject tradeoffer = + new JObject( + new JProperty("newversion",true), + new JProperty("version",2), + new JProperty("me", + new JObject( + new JProperty("assets", + new JArray( + from item in itemsSend + select new JObject( + new JProperty("appid", 753), + new JProperty("contextid", 6), + new JProperty("amount", Int32.Parse(item.amount)), + new JProperty("assetid", item.id)))), + new JProperty("currency",new JArray()), + new JProperty("ready",false))), + new JProperty("them", + new JObject( + new JProperty("assets",new JArray()), + new JProperty("currency",new JArray()), + new JProperty("ready",false)))); + + string referer = String.Format("https://steamcommunity.com/tradeoffer/new/?partner={0}", ((Int32)Int64.Parse(masterid)).ToString()); + + if (!string.IsNullOrEmpty(token)) { + referer += String.Format("&token={0}",token); + } + + Dictionary postData = new Dictionary() { + {"sessionid", sessionID}, + {"serverid","1" }, + {"partner",masterid }, + {"tradeoffermessage","sent by ASF" }, + {"json_tradeoffer",tradeoffer.ToString() }, + {"trade_offer_create_params",string.IsNullOrEmpty(token)?"":String.Format("{{ \"trade_offer_access_token\":\"{0}\" }}", token) } + }; + HttpResponseMessage response = await WebBrowser.UrlPost("https://steamcommunity.com/tradeoffer/new/send", postData, Cookie, referer).ConfigureAwait(false); + if (response == null) { + return false; + } + return response.IsSuccessStatusCode; + } + internal async Task GetBadgePage(int page) { if (SteamID == 0 || page == 0) { return null; diff --git a/ArchiSteamFarm/Bot.cs b/ArchiSteamFarm/Bot.cs old mode 100755 new mode 100644 index a4b14da98..72314d085 --- a/ArchiSteamFarm/Bot.cs +++ b/ArchiSteamFarm/Bot.cs @@ -31,6 +31,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Security.Cryptography; +using System.Threading; using System.Threading.Tasks; using System.Xml; using System.Text; @@ -56,6 +57,7 @@ namespace ArchiSteamFarm { internal readonly SteamFriends SteamFriends; internal readonly SteamUser SteamUser; internal readonly Trading Trading; + private Timer Timer; private bool KeepRunning = true; private bool InvalidPassword = false; @@ -70,6 +72,7 @@ namespace ArchiSteamFarm { internal string SteamPassword { get; private set; } = "null"; internal string SteamNickname { get; private set; } = "null"; internal string SteamApiKey { get; private set; } = "null"; + internal string SteamTradeToken {get; private set; } = "null"; internal string SteamParentalPIN { get; private set; } = "0"; internal ulong SteamMasterID { get; private set; } = 0; internal ulong SteamMasterClanID { get; private set; } = 0; @@ -79,6 +82,8 @@ namespace ArchiSteamFarm { internal bool ForwardKeysToOtherBots { get; private set; } = false; internal bool UseAsfAsMobileAuthenticator { get; private set; } = false; internal bool ShutdownOnFarmingFinished { get; private set; } = false; + internal bool SendOnFarmingFinished { get; private set; } = false; + internal uint SendTradePeriod {get; private set; } = 0; internal HashSet Blacklist { get; private set; } = new HashSet(); internal bool Statistics { get; private set; } = true; @@ -305,6 +310,9 @@ namespace ArchiSteamFarm { case "SteamApiKey": SteamApiKey = value; break; + case "SteamTradeToken": + SteamTradeToken = value; + break; case "SteamParentalPIN": SteamParentalPIN = value; break; @@ -332,6 +340,12 @@ namespace ArchiSteamFarm { case "ShutdownOnFarmingFinished": ShutdownOnFarmingFinished = bool.Parse(value); break; + case "SendOnFarmingFinished": + SendOnFarmingFinished = bool.Parse(value); + break; + case "SendTradePeriod": + SendTradePeriod = uint.Parse(value); + break; case "Blacklist": Blacklist.Clear(); foreach (string appID in value.Split(',')) { @@ -411,6 +425,9 @@ namespace ArchiSteamFarm { } internal async Task OnFarmingFinished() { + if (SendOnFarmingFinished) { + await ResponseSendTrade(BotName).ConfigureAwait(false); + } if (ShutdownOnFarmingFinished) { await Shutdown().ConfigureAwait(false); } @@ -467,6 +484,35 @@ namespace ArchiSteamFarm { return result.ToString(); } + internal static async Task ResponseSendTrade(string botName) { + Bot bot; + string token=null; + if (string.IsNullOrEmpty(botName)) { + return "Error, no name specified"; + } + if (!Bots.TryGetValue(botName, out bot)) { + return "Couldn't find any bot named " + botName + "!"; + } + if (bot.SendTradePeriod!=0) { + bot.Timer.Change(TimeSpan.FromHours(bot.SendTradePeriod),Timeout.InfiniteTimeSpan); + } + if (bot.SteamMasterID==0) { + return "No master set"; + } + if ((!string.IsNullOrEmpty(bot.SteamTradeToken))&&(!bot.SteamTradeToken.Equals("null"))) { + token=bot.SteamTradeToken; + } + List inv = await bot.ArchiWebHandler.GetInventory().ConfigureAwait(false); + if (inv.Count == 0) { + return "Nothing to send"; + } + if (await bot.ArchiWebHandler.SendTradeOffer(inv, bot.SteamMasterID.ToString(),token).ConfigureAwait(false)) { + await bot.AcceptAllConfirmations().ConfigureAwait(false); + return "Trade offer sent"; + } + return "Error sending trade offer"; + } + internal static string Response2FA(string botName) { if (string.IsNullOrEmpty(botName)) { return null; @@ -673,6 +719,8 @@ namespace ArchiSteamFarm { return ResponseStatusAll(); case "!stop": return await ResponseStop(BotName).ConfigureAwait(false); + case "!loot": + return await ResponseSendTrade(BotName).ConfigureAwait(false); default: return "Unrecognized command: " + message; } @@ -700,6 +748,8 @@ namespace ArchiSteamFarm { return await ResponseStop(args[1]).ConfigureAwait(false); case "!status": return ResponseStatus(args[1]); + case "!loot": + return await ResponseSendTrade(args[1]).ConfigureAwait(false); default: return "Unrecognized command: " + args[0]; } @@ -991,6 +1041,15 @@ namespace ArchiSteamFarm { Trading.CheckTrades(); await CardsFarmer.StartFarming().ConfigureAwait(false); + + if (SendTradePeriod!=0) { + Timer = new Timer( + async e => await ResponseSendTrade(BotName).ConfigureAwait(false), + null, + TimeSpan.FromHours(SendTradePeriod), // Delay + Timeout.InfiniteTimeSpan // Period + ); + } break; case EResult.NoConnection: case EResult.ServiceUnavailable: diff --git a/ArchiSteamFarm/config/example.xml b/ArchiSteamFarm/config/example.xml index 24e98bcd3..a73bbc747 100644 --- a/ArchiSteamFarm/config/example.xml +++ b/ArchiSteamFarm/config/example.xml @@ -1,7 +1,7 @@ - + @@ -104,6 +104,23 @@ + + + + + + + + + + + + + + + + +