Bot->Master trades

This commit is contained in:
Ryzhehvost
2016-01-13 11:17:58 +02:00
parent 74e416394a
commit e0d944efc5
3 changed files with 152 additions and 2 deletions

View File

@@ -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<List<Inventory>> GetInventory() {
List<Inventory> result = new List<Inventory>();
try {
string json = await WebBrowser.UrlGetToContent("http://steamcommunity.com/my/inventory/json/753/6", Cookie).ConfigureAwait(false);
JObject jobj = JObject.Parse(json);
IList<JToken> results = jobj.SelectTokens("$.rgInventory.*").ToList();
foreach (JToken res in results) {
result.Add(JsonConvert.DeserializeObject<Inventory>(res.ToString()));
}
} catch (Exception) {
//just return empty list on error
}
return result;
}
internal async Task<bool> SendTradeOffer(List<Inventory> 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 <string, string> postData = new Dictionary<string, string>() {
{"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<HtmlDocument> GetBadgePage(int page) {
if (SteamID == 0 || page == 0) {
return null;

59
ArchiSteamFarm/Bot.cs Executable file → Normal file
View File

@@ -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<uint> Blacklist { get; private set; } = new HashSet<uint>();
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<string> 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<ArchiWebHandler.Inventory> 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:

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<!-- This is full-fledged example config, you may be also interested in minimal.xml for bare minimum one -->
<!-- This config includes all user-switchable properties that you may want to change on per-bot basis -->
<!-- Default values used in config match default ASF values when given config property is not found -->
<!-- In other words, if given property is not defined, ASF will assume default pre-programmed value -->
@@ -104,6 +104,23 @@
<!-- Personally I suggest leaving it at "false", unless you have a reason to close the process after all bots finished farming -->
<ShutdownOnFarmingFinished type="bool" value="false"/>
<!-- if this switch set to "true",the bot would try to send trade offer with all cards to master after farming is finished -->
<!-- for sucessfull trade offer bot needs SteamMasterID to be set properly -->
<!-- if the master is not a friend of this bot, SteamTradeToken would be needed also -->
<SendOnFarmingFinished type="bool" value="false"/>
<!-- If you bot has a lot of cards to farm, and you don't want to wait till it farm them all, you can use this parameter -->
<!-- this setting is the time period of auto-sending bot->master trades in hours-->
<!-- for example, if you want bot to send you trade offers once a day, set this to 24 -->
<!-- if value is "0" no automatic trade offers would be sent -->
<SendTradePeriod type="uint" value="0"/>
<!-- This is needed to send bot->master trades, only if master is not a friend of bot -->
<!-- To get this token go (as master!) here: http://steamcommunity.com/id/ryzhehvost/tradeoffers/privacy -->
<!-- the token is last part of link in the field "TradeURL", starting after "&token=" -->
<SteamTradeToken type="string" value="null"/>
<!-- This is comma-separated list of IDs that should not be considered for farming -->
<!-- Default value includes appIDs that are wrongly appearing on the profile, e.g. Summer Sale, Winter Sale or Monster Summer Game -->
<!-- In addition to blacklist defined here, ASF also has global blacklist, which is being updated on as-needed basis, so you don't need to update this entry -->