Advertisement
Guest User

Bot.cs

a guest
Apr 9th, 2016
52
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 51.59 KB | None | 0 0
  1. using System;
  2. using System.Threading.Tasks;
  3. using System.Web;
  4. using System.Net;
  5. using System.Text;
  6. using System.IO;
  7. using System.Threading;
  8. using System.Collections.Generic;
  9. using System.Security.Cryptography;
  10. using System.ComponentModel;
  11. using SteamBot.SteamGroups;
  12. using SteamKit2;
  13. using SteamTrade;
  14. using SteamKit2.Internal;
  15. using SteamTrade.TradeOffer;
  16. using System.Globalization;
  17. using System.Text.RegularExpressions;
  18.  
  19. namespace SteamBot
  20. {
  21.     public class Bot : IDisposable
  22.     {
  23.         #region Bot delegates
  24.         public delegate UserHandler UserHandlerCreator(Bot bot, SteamID id);
  25.         #endregion
  26.  
  27.         #region Private readonly variables
  28.         private readonly SteamUser.LogOnDetails logOnDetails;
  29.         private readonly string schemaLang;
  30.         private readonly string logFile;
  31.         private readonly Dictionary<SteamID, UserHandler> userHandlers;
  32.         private readonly Log.LogLevel consoleLogLevel;
  33.         private readonly Log.LogLevel fileLogLevel;
  34.         private readonly UserHandlerCreator createHandler;
  35.         private readonly bool isProccess;
  36.         private readonly BackgroundWorker botThread;
  37.         #endregion
  38.  
  39.         #region Private variables
  40.         private Task<Inventory> myInventoryTask;
  41.         private TradeManager tradeManager;
  42.         private TradeOfferManager tradeOfferManager;
  43.         private int tradePollingInterval;
  44.         private string myUserNonce;
  45.         private string myUniqueId;
  46.         private bool cookiesAreInvalid = true;
  47.         private List<SteamID> friends;
  48.         private bool disposed = false;
  49.         private string consoleInput;
  50.         #endregion
  51.  
  52.         #region Public readonly variables
  53.         /// <summary>
  54.         /// Userhandler class bot is running.
  55.         /// </summary>
  56.         public readonly string BotControlClass;
  57.         /// <summary>
  58.         /// The display name of bot to steam.
  59.         /// </summary>
  60.         public readonly string DisplayName;
  61.         /// <summary>
  62.         /// The chat response from the config file.
  63.         /// </summary>
  64.         public readonly string ChatResponse;
  65.         /// <summary>
  66.         /// An array of admins for bot.
  67.         /// </summary>
  68.         public readonly IEnumerable<SteamID> Admins;
  69.         public readonly SteamClient SteamClient;
  70.         public readonly SteamUser SteamUser;
  71.         public readonly SteamFriends SteamFriends;
  72.         public readonly SteamTrading SteamTrade;
  73.         public readonly SteamGameCoordinator SteamGameCoordinator;
  74.         public readonly SteamNotifications SteamNotifications;
  75.         /// <summary>
  76.         /// The amount of time the bot will trade for.
  77.         /// </summary>
  78.         public readonly int MaximumTradeTime;
  79.         /// <summary>
  80.         /// The amount of time the bot will wait between user interactions with trade.
  81.         /// </summary>
  82.         public readonly int MaximumActionGap;
  83.         /// <summary>
  84.         /// The api key of bot.
  85.         /// </summary>
  86.         public readonly string ApiKey;
  87.         public readonly SteamWeb SteamWeb;
  88.         /// <summary>
  89.         /// The prefix shown before bot's display name.
  90.         /// </summary>
  91.         public readonly string DisplayNamePrefix;
  92.         /// <summary>
  93.         /// The instance of the Logger for the bot.
  94.         /// </summary>
  95.         public readonly Log Log;
  96.         #endregion
  97.  
  98.         #region Public variables
  99.         public string AuthCode;
  100.         public bool IsRunning;
  101.         /// <summary>
  102.         /// Is bot fully Logged in.
  103.         /// Set only when bot did successfully Log in.
  104.         /// </summary>
  105.         public bool IsLoggedIn { get; private set; }
  106.  
  107.         /// <summary>
  108.         /// The current trade the bot is in.
  109.         /// </summary>
  110.         public Trade CurrentTrade { get; private set; }
  111.  
  112.         /// <summary>
  113.         /// The current game bot is in.
  114.         /// Default: 0 = No game.
  115.         /// </summary>
  116.         public int CurrentGame { get; private set; }
  117.  
  118.         public SteamAuth.SteamGuardAccount SteamGuardAccount;
  119.         #endregion
  120.  
  121.         public IEnumerable<SteamID> FriendsList
  122.         {
  123.             get
  124.             {
  125.                 CreateFriendsListIfNecessary();
  126.                 return friends;
  127.             }
  128.         }
  129.  
  130.         public Inventory MyInventory
  131.         {
  132.             get
  133.             {
  134.                 myInventoryTask.Wait();
  135.                 return myInventoryTask.Result;
  136.             }
  137.         }
  138.  
  139.         /// <summary>
  140.         /// Compatibility sanity.
  141.         /// </summary>
  142.         [Obsolete("Refactored to be Log instead of log")]
  143.         public Log log { get { return Log; } }
  144.  
  145.         public Bot(Configuration.BotInfo config, string apiKey, UserHandlerCreator handlerCreator, bool debug = false, bool process = false)
  146.         {
  147.             userHandlers = new Dictionary<SteamID, UserHandler>();
  148.             logOnDetails = new SteamUser.LogOnDetails
  149.             {
  150.                 Username = config.Username,
  151.                 Password = config.Password
  152.             };
  153.             DisplayName = config.DisplayName;
  154.             ChatResponse = config.ChatResponse;
  155.             MaximumTradeTime = config.MaximumTradeTime;
  156.             MaximumActionGap = config.MaximumActionGap;
  157.             DisplayNamePrefix = config.DisplayNamePrefix;
  158.             tradePollingInterval = config.TradePollingInterval <= 100 ? 800 : config.TradePollingInterval;
  159.             schemaLang = config.SchemaLang != null && config.SchemaLang.Length == 2 ? config.SchemaLang.ToLower() : "en";
  160.             Admins = config.Admins;
  161.             ApiKey = !String.IsNullOrEmpty(config.ApiKey) ? config.ApiKey : apiKey;
  162.             isProccess = process;
  163.             try
  164.             {
  165.                 if (config.LogLevel != null)
  166.                 {
  167.                     consoleLogLevel = (Log.LogLevel)Enum.Parse(typeof(Log.LogLevel), config.LogLevel, true);
  168.                     Console.WriteLine(@"(Console) LogLevel configuration parameter used in bot {0} is depreciated and may be removed in future versions. Please use ConsoleLogLevel instead.", DisplayName);
  169.                 }
  170.                 else consoleLogLevel = (Log.LogLevel)Enum.Parse(typeof(Log.LogLevel), config.ConsoleLogLevel, true);
  171.             }
  172.             catch (ArgumentException)
  173.             {
  174.                 Console.WriteLine(@"(Console) ConsoleLogLevel invalid or unspecified for bot {0}. Defaulting to ""Info""", DisplayName);
  175.                 consoleLogLevel = Log.LogLevel.Info;
  176.             }
  177.  
  178.             try
  179.             {
  180.                 fileLogLevel = (Log.LogLevel)Enum.Parse(typeof(Log.LogLevel), config.FileLogLevel, true);
  181.             }
  182.             catch (ArgumentException)
  183.             {
  184.                 Console.WriteLine(@"(Console) FileLogLevel invalid or unspecified for bot {0}. Defaulting to ""Info""", DisplayName);
  185.                 fileLogLevel = Log.LogLevel.Info;
  186.             }
  187.  
  188.             logFile = config.LogFile;
  189.             Log = new Log(logFile, DisplayName, consoleLogLevel, fileLogLevel);
  190.             createHandler = handlerCreator;
  191.             BotControlClass = config.BotControlClass;
  192.             SteamWeb = new SteamWeb();
  193.  
  194.             // Hacking around https
  195.             ServicePointManager.ServerCertificateValidationCallback += SteamWeb.ValidateRemoteCertificate;
  196.  
  197.             Log.Debug("Initializing Steam Bot...");
  198.             SteamClient = new SteamClient();
  199.             SteamClient.AddHandler(new SteamNotifications());
  200.             SteamTrade = SteamClient.GetHandler<SteamTrading>();
  201.             SteamUser = SteamClient.GetHandler<SteamUser>();
  202.             SteamFriends = SteamClient.GetHandler<SteamFriends>();
  203.             SteamGameCoordinator = SteamClient.GetHandler<SteamGameCoordinator>();
  204.             SteamNotifications = SteamClient.GetHandler<SteamNotifications>();
  205.  
  206.             botThread = new BackgroundWorker { WorkerSupportsCancellation = true };
  207.             botThread.DoWork += BackgroundWorkerOnDoWork;
  208.             botThread.RunWorkerCompleted += BackgroundWorkerOnRunWorkerCompleted;
  209.             botThread.RunWorkerAsync();
  210.         }
  211.  
  212.         ~Bot()
  213.         {
  214.             Dispose(false);
  215.         }
  216.  
  217.         private void CreateFriendsListIfNecessary()
  218.         {
  219.             if (friends != null)
  220.                 return;
  221.  
  222.             friends = new List<SteamID>();
  223.             for (int i = 0; i < SteamFriends.GetFriendCount(); i++)
  224.                 friends.Add(SteamFriends.GetFriendByIndex(i));
  225.         }
  226.  
  227.         /// <summary>
  228.         /// Occurs when the bot needs the SteamGuard authentication code.
  229.         /// </summary>
  230.         /// <remarks>
  231.         /// Return the code in <see cref="SteamGuardRequiredEventArgs.SteamGuard"/>
  232.         /// </remarks>
  233.         public event EventHandler<SteamGuardRequiredEventArgs> OnSteamGuardRequired;
  234.  
  235.         /// <summary>
  236.         /// Starts the callback thread and connects to Steam via SteamKit2.
  237.         /// </summary>
  238.         /// <remarks>
  239.         /// THIS NEVER RETURNS.
  240.         /// </remarks>
  241.         /// <returns><c>true</c>. See remarks</returns>
  242.         public bool StartBot()
  243.         {
  244.             IsRunning = true;
  245.             Log.Info("Connecting...");
  246.             if (!botThread.IsBusy)
  247.                 botThread.RunWorkerAsync();
  248.             SteamClient.Connect();
  249.             Log.Success("Done Loading Bot!");
  250.             return true; // never get here
  251.         }
  252.  
  253.         /// <summary>
  254.         /// Disconnect from the Steam network and stop the callback
  255.         /// thread.
  256.         /// </summary>
  257.         public void StopBot()
  258.         {
  259.             IsRunning = false;
  260.             Log.Debug("Trying to shut down bot thread.");
  261.             SteamClient.Disconnect();
  262.             botThread.CancelAsync();
  263.             while (botThread.IsBusy)
  264.                 Thread.Yield();
  265.             userHandlers.Clear();
  266.         }
  267.  
  268.         /// <summary>
  269.         /// Creates a new trade with the given partner.
  270.         /// </summary>
  271.         /// <returns>
  272.         /// <c>true</c>, if trade was opened,
  273.         /// <c>false</c> if there is another trade that must be closed first.
  274.         /// </returns>
  275.         public bool OpenTrade(SteamID other)
  276.         {
  277.             if (CurrentTrade != null || CheckCookies() == false)
  278.                 return false;
  279.             SteamTrade.Trade(other);
  280.             return true;
  281.         }
  282.  
  283.         /// <summary>
  284.         /// Closes the current active trade.
  285.         /// </summary>
  286.         public void CloseTrade()
  287.         {
  288.             if (CurrentTrade == null)
  289.                 return;
  290.             UnsubscribeTrade(GetUserHandler(CurrentTrade.OtherSID), CurrentTrade);
  291.             tradeManager.StopTrade();
  292.             CurrentTrade = null;
  293.         }
  294.  
  295.         void OnTradeTimeout(object sender, EventArgs args)
  296.         {
  297.             // ignore event params and just null out the trade.
  298.             GetUserHandler(CurrentTrade.OtherSID).OnTradeTimeout();
  299.         }
  300.  
  301.         /// <summary>
  302.         /// Create a new trade offer with the specified partner
  303.         /// </summary>
  304.         /// <param name="other">SteamId of the partner</param>
  305.         /// <returns></returns>
  306.         public TradeOffer NewTradeOffer(SteamID other)
  307.         {
  308.             return tradeOfferManager.NewOffer(other);
  309.         }
  310.  
  311.         /// <summary>
  312.         /// Try to get a specific trade offer using the offerid
  313.         /// </summary>
  314.         /// <param name="offerId"></param>
  315.         /// <param name="tradeOffer"></param>
  316.         /// <returns></returns>
  317.         public bool TryGetTradeOffer(string offerId, out TradeOffer tradeOffer)
  318.         {
  319.             return tradeOfferManager.GetOffer(offerId, out tradeOffer);
  320.         }
  321.  
  322.         public void HandleBotCommand(string command)
  323.         {
  324.             try
  325.             {
  326.                 if (command == "linkauth")
  327.                 {
  328.                     LinkMobileAuth();
  329.                 }
  330.                 else if (command == "getauth")
  331.                 {
  332.                     try
  333.                     {
  334.                         Log.Success("Generated Steam Guard code: " + SteamGuardAccount.GenerateSteamGuardCode());
  335.                     }
  336.                     catch (NullReferenceException)
  337.                     {
  338.                         Log.Error("Unable to generate Steam Guard code.");
  339.                     }
  340.                 }
  341.                 else if (command == "unlinkauth")
  342.                 {
  343.                     if (SteamGuardAccount == null)
  344.                     {
  345.                         Log.Error("Mobile authenticator is not active on this bot.");
  346.                     }
  347.                     else if (SteamGuardAccount.DeactivateAuthenticator())
  348.                     {
  349.                         Log.Success("Deactivated authenticator on this account.");
  350.                     }
  351.                     else
  352.                     {
  353.                         Log.Error("Failed to deactivate authenticator on this account.");
  354.                     }
  355.                 }
  356.                 else
  357.                 {
  358.                     GetUserHandler(SteamClient.SteamID).OnBotCommand(command);
  359.                 }
  360.             }
  361.             catch (ObjectDisposedException e)
  362.             {
  363.                 // Writing to console because odds are the error was caused by a disposed Log.
  364.                 Console.WriteLine(string.Format("Exception caught in BotCommand Thread: {0}", e));
  365.                 if (!this.IsRunning)
  366.                 {
  367.                     Console.WriteLine("The Bot is no longer running and could not write to the Log. Try Starting this bot first.");
  368.                 }
  369.             }
  370.             catch (Exception e)
  371.             {
  372.                 Console.WriteLine(string.Format("Exception caught in BotCommand Thread: {0}", e));
  373.             }
  374.         }
  375.  
  376.         public void HandleInput(string input)
  377.         {
  378.             consoleInput = input;
  379.         }
  380.  
  381.         public string WaitForInput()
  382.         {
  383.             consoleInput = null;
  384.             while (true)
  385.             {
  386.                 if (consoleInput != null)
  387.                 {
  388.                     return consoleInput;
  389.                 }
  390.                 Thread.Sleep(5);
  391.             }
  392.         }
  393.  
  394.         bool HandleTradeSessionStart(SteamID other)
  395.         {
  396.             if (CurrentTrade != null)
  397.                 return false;
  398.             try
  399.             {
  400.                 tradeManager.InitializeTrade(SteamUser.SteamID, other);
  401.                 CurrentTrade = tradeManager.CreateTrade(SteamUser.SteamID, other);
  402.                 CurrentTrade.OnClose += CloseTrade;
  403.                 SubscribeTrade(CurrentTrade, GetUserHandler(other));
  404.                 tradeManager.StartTradeThread(CurrentTrade);
  405.                 return true;
  406.             }
  407.             catch (SteamTrade.Exceptions.InventoryFetchException)
  408.             {
  409.                 // we shouldn't get here because the inv checks are also
  410.                 // done in the TradeProposedCallback handler.
  411.                 /*string response = String.Empty;
  412.                 if (ie.FailingSteamId.ConvertToUInt64() == other.ConvertToUInt64())
  413.                 {
  414.                     response = "Trade failed. Could not correctly fetch your backpack. Either the inventory is inaccessible or your backpack is private.";
  415.                 }
  416.                 else
  417.                 {
  418.                     response = "Trade failed. Could not correctly fetch my backpack.";
  419.                 }
  420.                
  421.                 SteamFriends.SendChatMessage(other,
  422.                                              EChatEntryType.ChatMsg,
  423.                                              response);
  424.  
  425.                 Log.Info ("Bot sent other: {0}", response);
  426.                
  427.                 CurrentTrade = null;*/
  428.                 return false;
  429.             }
  430.         }
  431.  
  432.         public void SetGamePlaying(int id)
  433.         {
  434.             var gamePlaying = new SteamKit2.ClientMsgProtobuf<CMsgClientGamesPlayed>(EMsg.ClientGamesPlayed);
  435.             if (id != 0)
  436.                 gamePlaying.Body.games_played.Add(new CMsgClientGamesPlayed.GamePlayed
  437.                 {
  438.                     game_id = new GameID(id),
  439.                 });
  440.             SteamClient.Send(gamePlaying);
  441.             CurrentGame = id;
  442.         }
  443.  
  444.         void HandleSteamMessage(ICallbackMsg msg)
  445.         {
  446.             Log.Debug(msg.ToString());
  447.             #region Login
  448.             msg.Handle<SteamClient.ConnectedCallback>(callback =>
  449.             {
  450.                 Log.Debug("Connection Callback: {0}", callback.Result);
  451.  
  452.                 if (callback.Result == EResult.OK)
  453.                 {
  454.                     UserLogOn();
  455.                 }
  456.                 else
  457.                 {
  458.                     Log.Error("Failed to connect to Steam Community, trying again...");
  459.                     SteamClient.Connect();
  460.                 }
  461.  
  462.             });
  463.  
  464.             msg.Handle<SteamUser.LoggedOnCallback>(callback =>
  465.             {
  466.                 Log.Debug("Logged On Callback: {0}", callback.Result);
  467.  
  468.                 if (callback.Result == EResult.OK)
  469.                 {
  470.                     myUserNonce = callback.WebAPIUserNonce;
  471.                 }
  472.                 else
  473.                 {
  474.                     Log.Error("Login Error: {0}", callback.Result);
  475.                 }
  476.  
  477.                 if (callback.Result == EResult.AccountLogonDeniedNeedTwoFactorCode)
  478.                 {
  479.                     var mobileAuthCode = GetMobileAuthCode();
  480.                     if (string.IsNullOrEmpty(mobileAuthCode))
  481.                     {
  482.                         Log.Error("Failed to generate 2FA code. Make sure you have linked the authenticator via SteamBot.");
  483.                     }
  484.                     else
  485.                     {
  486.                         logOnDetails.TwoFactorCode = mobileAuthCode;
  487.                         Log.Success("Generated 2FA code.");
  488.                     }
  489.                 }
  490.                 else if (callback.Result == EResult.TwoFactorCodeMismatch)
  491.                 {
  492.                     SteamAuth.TimeAligner.AlignTime();
  493.                     logOnDetails.TwoFactorCode = SteamGuardAccount.GenerateSteamGuardCode();
  494.                     Log.Success("Regenerated 2FA code.");
  495.                 }
  496.                 else if (callback.Result == EResult.AccountLogonDenied)
  497.                 {
  498.                     Log.Interface("This account is SteamGuard enabled. Enter the code via the `auth' command.");
  499.  
  500.                     // try to get the steamguard auth code from the event callback
  501.                     var eva = new SteamGuardRequiredEventArgs();
  502.                     FireOnSteamGuardRequired(eva);
  503.                     if (!String.IsNullOrEmpty(eva.SteamGuard))
  504.                         logOnDetails.AuthCode = eva.SteamGuard;
  505.                     else
  506.                         logOnDetails.AuthCode = Console.ReadLine();
  507.                 }
  508.                 else if (callback.Result == EResult.InvalidLoginAuthCode)
  509.                 {
  510.                     Log.Interface("The given SteamGuard code was invalid. Try again using the `auth' command.");
  511.                     logOnDetails.AuthCode = Console.ReadLine();
  512.                 }
  513.             });
  514.  
  515.             msg.Handle<SteamUser.LoginKeyCallback>(callback =>
  516.             {
  517.                 myUniqueId = callback.UniqueID.ToString();
  518.  
  519.                 UserWebLogOn();
  520.  
  521.                 if (Trade.CurrentSchema == null)
  522.                 {
  523.                     Log.Info("Downloading Schema...");
  524.                     Trade.CurrentSchema = Schema.FetchSchema(ApiKey, schemaLang);
  525.                     Log.Success("Schema Downloaded!");
  526.                 }
  527.  
  528.                 SteamFriends.SetPersonaName(DisplayNamePrefix + DisplayName);
  529.                 SteamFriends.SetPersonaState(EPersonaState.Online);
  530.  
  531.                 Log.Success("Steam Bot Logged In Completely!");
  532.  
  533.                 GetUserHandler(SteamClient.SteamID).OnLoginCompleted();
  534.             });
  535.  
  536.             msg.Handle<SteamUser.WebAPIUserNonceCallback>(webCallback =>
  537.             {
  538.                 Log.Debug("Received new WebAPIUserNonce.");
  539.  
  540.                 if (webCallback.Result == EResult.OK)
  541.                 {
  542.                     myUserNonce = webCallback.Nonce;
  543.                     UserWebLogOn();
  544.                 }
  545.                 else
  546.                 {
  547.                     Log.Error("WebAPIUserNonce Error: " + webCallback.Result);
  548.                 }
  549.             });
  550.  
  551.             msg.Handle<SteamUser.UpdateMachineAuthCallback>(
  552.                 authCallback => OnUpdateMachineAuthCallback(authCallback)
  553.             );
  554.             #endregion
  555.  
  556.             #region Friends
  557.             msg.Handle<SteamFriends.FriendsListCallback>(callback =>
  558.             {
  559.                 foreach (SteamFriends.FriendsListCallback.Friend friend in callback.FriendList)
  560.                 {
  561.                     switch (friend.SteamID.AccountType)
  562.                     {
  563.                         case EAccountType.Clan:
  564.                             if (friend.Relationship == EFriendRelationship.RequestRecipient)
  565.                             {
  566.                                 if (GetUserHandler(friend.SteamID).OnGroupAdd())
  567.                                 {
  568.                                     AcceptGroupInvite(friend.SteamID);
  569.                                 }
  570.                                 else
  571.                                 {
  572.                                     DeclineGroupInvite(friend.SteamID);
  573.                                 }
  574.                             }
  575.                             break;
  576.                         default:
  577.                             CreateFriendsListIfNecessary();
  578.                             if (friend.Relationship == EFriendRelationship.None)
  579.                             {
  580.                                 friends.Remove(friend.SteamID);
  581.                                 GetUserHandler(friend.SteamID).OnFriendRemove();
  582.                                 RemoveUserHandler(friend.SteamID);
  583.                             }
  584.                             else if (friend.Relationship == EFriendRelationship.RequestRecipient)
  585.                             {
  586.                                 if (GetUserHandler(friend.SteamID).OnFriendAdd())
  587.                                 {
  588.                                     if (!friends.Contains(friend.SteamID))
  589.                                     {
  590.                                         friends.Add(friend.SteamID);
  591.                                     }
  592.                                     else
  593.                                     {
  594.                                         Log.Error("Friend was added who was already in friends list: " + friend.SteamID);
  595.                                     }
  596.                                     SteamFriends.AddFriend(friend.SteamID);
  597.                                 }
  598.                                 else
  599.                                 {
  600.                                     SteamFriends.RemoveFriend(friend.SteamID);
  601.                                     RemoveUserHandler(friend.SteamID);
  602.                                 }
  603.                             }
  604.                             break;
  605.                     }
  606.                 }
  607.             });
  608.  
  609.  
  610.             msg.Handle<SteamFriends.FriendMsgCallback>(callback =>
  611.             {
  612.                 EChatEntryType type = callback.EntryType;
  613.  
  614.                 if (callback.EntryType == EChatEntryType.ChatMsg)
  615.                 {
  616.                     Log.Info("Chat Message from {0}: {1}",
  617.                                          SteamFriends.GetFriendPersonaName(callback.Sender),
  618.                                          callback.Message
  619.                                          );
  620.                     GetUserHandler(callback.Sender).OnMessageHandler(callback.Message, type);
  621.                 }
  622.             });
  623.             #endregion
  624.  
  625.             #region Group Chat
  626.             msg.Handle<SteamFriends.ChatMsgCallback>(callback =>
  627.             {
  628.                 GetUserHandler(callback.ChatterID).OnChatRoomMessage(callback.ChatRoomID, callback.ChatterID, callback.Message);
  629.             });
  630.             #endregion
  631.  
  632.             #region Trading
  633.             msg.Handle<SteamTrading.SessionStartCallback>(callback =>
  634.             {
  635.                 bool started = HandleTradeSessionStart(callback.OtherClient);
  636.  
  637.                 if (!started)
  638.                     Log.Error("Could not start the trade session.");
  639.                 else
  640.                     Log.Debug("SteamTrading.SessionStartCallback handled successfully. Trade Opened.");
  641.             });
  642.  
  643.             msg.Handle<SteamTrading.TradeProposedCallback>(callback =>
  644.             {
  645.                 if (CheckCookies() == false)
  646.                 {
  647.                     SteamTrade.RespondToTrade(callback.TradeID, false);
  648.                     return;
  649.                 }
  650.  
  651.                 try
  652.                 {
  653.                     tradeManager.InitializeTrade(SteamUser.SteamID, callback.OtherClient);
  654.                 }
  655.                 catch (WebException we)
  656.                 {
  657.                     SteamFriends.SendChatMessage(callback.OtherClient,
  658.                              EChatEntryType.ChatMsg,
  659.                              "Trade error: " + we.Message);
  660.  
  661.                     SteamTrade.RespondToTrade(callback.TradeID, false);
  662.                     return;
  663.                 }
  664.                 catch (Exception)
  665.                 {
  666.                     SteamFriends.SendChatMessage(callback.OtherClient,
  667.                              EChatEntryType.ChatMsg,
  668.                              "Trade declined. Could not correctly fetch your backpack.");
  669.  
  670.                     SteamTrade.RespondToTrade(callback.TradeID, false);
  671.                     return;
  672.                 }
  673.  
  674.                 //if (tradeManager.OtherInventory.IsPrivate)
  675.                 //{
  676.                 //    SteamFriends.SendChatMessage(callback.OtherClient,
  677.                 //                                 EChatEntryType.ChatMsg,
  678.                 //                                 "Trade declined. Your backpack cannot be private.");
  679.  
  680.                 //    SteamTrade.RespondToTrade (callback.TradeID, false);
  681.                 //    return;
  682.                 //}
  683.  
  684.                 if (CurrentTrade == null && GetUserHandler(callback.OtherClient).OnTradeRequest())
  685.                     SteamTrade.RespondToTrade(callback.TradeID, true);
  686.                 else
  687.                     SteamTrade.RespondToTrade(callback.TradeID, false);
  688.             });
  689.  
  690.             msg.Handle<SteamTrading.TradeResultCallback>(callback =>
  691.             {
  692.                 if (callback.Response == EEconTradeResponse.Accepted)
  693.                 {
  694.                     Log.Debug("Trade Status: {0}", callback.Response);
  695.                     Log.Info("Trade Accepted!");
  696.                     GetUserHandler(callback.OtherClient).OnTradeRequestReply(true, callback.Response.ToString());
  697.                 }
  698.                 else
  699.                 {
  700.                     Log.Warn("Trade failed: {0}", callback.Response);
  701.                     CloseTrade();
  702.                     GetUserHandler(callback.OtherClient).OnTradeRequestReply(false, callback.Response.ToString());
  703.                 }
  704.  
  705.             });
  706.             #endregion
  707.  
  708.             #region Disconnect
  709.             msg.Handle<SteamUser.LoggedOffCallback>(callback =>
  710.             {
  711.                 IsLoggedIn = false;
  712.                 Log.Warn("Logged off Steam.  Reason: {0}", callback.Result);
  713.             });
  714.  
  715.             msg.Handle<SteamClient.DisconnectedCallback>(callback =>
  716.             {
  717.                 if (IsLoggedIn)
  718.                 {
  719.                     IsLoggedIn = false;
  720.                     CloseTrade();
  721.                     Log.Warn("Disconnected from Steam Network!");
  722.                 }
  723.  
  724.                 SteamClient.Connect();
  725.             });
  726.             #endregion
  727.  
  728.             #region Notifications
  729.             msg.Handle<SteamBot.SteamNotifications.NotificationCallback>(callback =>
  730.             {
  731.                 //currently only appears to be of trade offer
  732.                 if (callback.Notifications.Count != 0)
  733.                 {
  734.                     foreach (var notification in callback.Notifications)
  735.                     {
  736.                         Log.Info(notification.UserNotificationType + " notification");
  737.                     }
  738.                 }
  739.  
  740.                 // Get offers only if cookies are valid
  741.                 if (CheckCookies())
  742.                     tradeOfferManager.GetOffers();
  743.             });
  744.  
  745.             msg.Handle<SteamBot.SteamNotifications.CommentNotificationCallback>(callback =>
  746.             {
  747.                 //various types of comment notifications on profile/activity feed etc
  748.                 //Log.Info("received CommentNotificationCallback");
  749.                 //Log.Info("New Commments " + callback.CommentNotifications.CountNewComments);
  750.                 //Log.Info("New Commments Owners " + callback.CommentNotifications.CountNewCommentsOwner);
  751.                 //Log.Info("New Commments Subscriptions" + callback.CommentNotifications.CountNewCommentsSubscriptions);
  752.             });
  753.             #endregion
  754.         }
  755.  
  756.         string GetMobileAuthCode()
  757.         {
  758.             var authFile = Path.Combine("authfiles", String.Format("{0}.auth", logOnDetails.Username));
  759.             if (File.Exists(authFile))
  760.             {
  761.                 SteamGuardAccount = Newtonsoft.Json.JsonConvert.DeserializeObject<SteamAuth.SteamGuardAccount>(File.ReadAllText(authFile));
  762.                 return SteamGuardAccount.GenerateSteamGuardCode();
  763.             }
  764.             return string.Empty;
  765.         }
  766.  
  767.         /// <summary>
  768.         /// Link a mobile authenticator to bot account, using SteamTradeOffersBot as the authenticator.
  769.         /// Called from bot manager console. Usage: "exec [index] linkauth"
  770.         /// If successful, 2FA will be required upon the next login.
  771.         /// Use "exec [index] getauth" if you need to get a Steam Guard code for the account.
  772.         /// To deactivate the authenticator, use "exec [index] unlinkauth".
  773.         /// </summary>
  774.         void LinkMobileAuth()
  775.         {
  776.             new Thread(() =>
  777.             {
  778.                 var login = new SteamAuth.UserLogin(logOnDetails.Username, logOnDetails.Password);
  779.                 var loginResult = login.DoLogin();
  780.                 if (loginResult == SteamAuth.LoginResult.NeedEmail)
  781.                 {
  782.                     while (loginResult == SteamAuth.LoginResult.NeedEmail)
  783.                     {
  784.                         Log.Interface("Enter Steam Guard code from email (type \"input [index] [code]\"):");
  785.                         var emailCode = WaitForInput();
  786.                         login.EmailCode = emailCode;
  787.                         loginResult = login.DoLogin();
  788.                     }
  789.                 }
  790.                 if (loginResult == SteamAuth.LoginResult.LoginOkay)
  791.                 {
  792.                     Log.Info("Linking mobile authenticator...");
  793.                     var authLinker = new SteamAuth.AuthenticatorLinker(login.Session);
  794.                     var addAuthResult = authLinker.AddAuthenticator();
  795.                     if (addAuthResult == SteamAuth.AuthenticatorLinker.LinkResult.MustProvidePhoneNumber)
  796.                     {
  797.                         while (addAuthResult == SteamAuth.AuthenticatorLinker.LinkResult.MustProvidePhoneNumber)
  798.                         {
  799.                             Log.Interface("Enter phone number with country code, e.g. +1XXXXXXXXXXX (type \"input [index] [number]\"):");
  800.                             var phoneNumber = WaitForInput();
  801.                             authLinker.PhoneNumber = phoneNumber;
  802.                             addAuthResult = authLinker.AddAuthenticator();
  803.                         }
  804.                     }
  805.                     if (addAuthResult == SteamAuth.AuthenticatorLinker.LinkResult.AwaitingFinalization)
  806.                     {
  807.                         SteamGuardAccount = authLinker.LinkedAccount;
  808.                         try
  809.                         {
  810.                             var authFile = Path.Combine("authfiles", String.Format("{0}.auth", logOnDetails.Username));
  811.                             Directory.CreateDirectory(Path.Combine(System.Windows.Forms.Application.StartupPath, "authfiles"));
  812.                             File.WriteAllText(authFile, Newtonsoft.Json.JsonConvert.SerializeObject(SteamGuardAccount));
  813.                             Log.Interface("Enter SMS code (type \"input [index] [code]\"):");
  814.                             var smsCode = WaitForInput();
  815.                             var authResult = authLinker.FinalizeAddAuthenticator(smsCode);
  816.                             if (authResult == SteamAuth.AuthenticatorLinker.FinalizeResult.Success)
  817.                             {
  818.                                 Log.Success("Linked authenticator.");
  819.                             }
  820.                             else
  821.                             {
  822.                                 Log.Error("Error linking authenticator: " + authResult);
  823.                             }
  824.                         }
  825.                         catch (IOException)
  826.                         {
  827.                             Log.Error("Failed to save auth file. Aborting authentication.");
  828.                         }
  829.                     }
  830.                     else
  831.                     {
  832.                         Log.Error("Error adding authenticator: " + addAuthResult);
  833.                     }
  834.                 }
  835.                 else
  836.                 {
  837.                     if (loginResult == SteamAuth.LoginResult.Need2FA)
  838.                     {
  839.                         Log.Error("Mobile authenticator has already been linked!");
  840.                     }
  841.                     else
  842.                     {
  843.                         Log.Error("Error performing mobile login: " + loginResult);
  844.                     }
  845.                 }
  846.             }).Start();
  847.         }
  848.  
  849.         void UserLogOn()
  850.         {
  851.             // get sentry file which has the machine hw info saved
  852.             // from when a steam guard code was entered
  853.             Directory.CreateDirectory(System.IO.Path.Combine(System.Windows.Forms.Application.StartupPath, "sentryfiles"));
  854.             FileInfo fi = new FileInfo(System.IO.Path.Combine("sentryfiles", String.Format("{0}.sentryfile", logOnDetails.Username)));
  855.  
  856.             if (fi.Exists && fi.Length > 0)
  857.                 logOnDetails.SentryFileHash = SHAHash(File.ReadAllBytes(fi.FullName));
  858.             else
  859.                 logOnDetails.SentryFileHash = null;
  860.  
  861.             SteamUser.LogOn(logOnDetails);
  862.         }
  863.  
  864.         void UserWebLogOn()
  865.         {
  866.             do
  867.             {
  868.                 IsLoggedIn = SteamWeb.Authenticate(myUniqueId, SteamClient, myUserNonce);
  869.  
  870.                 if (!IsLoggedIn)
  871.                 {
  872.                     Log.Warn("Authentication failed, retrying in 2s...");
  873.                     Thread.Sleep(2000);
  874.                 }
  875.             } while (!IsLoggedIn);
  876.  
  877.             Log.Success("User Authenticated!");
  878.  
  879.             tradeManager = new TradeManager(ApiKey, SteamWeb);
  880.             tradeManager.SetTradeTimeLimits(MaximumTradeTime, MaximumActionGap, tradePollingInterval);
  881.             tradeManager.OnTimeout += OnTradeTimeout;
  882.             tradeOfferManager = new TradeOfferManager(ApiKey, SteamWeb);
  883.             SubscribeTradeOffer(tradeOfferManager);
  884.             cookiesAreInvalid = false;
  885.             // Success, check trade offers which we have received while we were offline
  886.             tradeOfferManager.GetOffers();
  887.         }
  888.  
  889.         /// <summary>
  890.         /// Checks if sessionId and token cookies are still valid.
  891.         /// Sets cookie flag if they are invalid.
  892.         /// </summary>
  893.         /// <returns>true if cookies are valid; otherwise false</returns>
  894.         bool CheckCookies()
  895.         {
  896.             // We still haven't re-authenticated
  897.             if (cookiesAreInvalid)
  898.                 return false;
  899.  
  900.             try
  901.             {
  902.                 if (!SteamWeb.VerifyCookies())
  903.                 {
  904.                     // Cookies are no longer valid
  905.                     Log.Warn("Cookies are invalid. Need to re-authenticate.");
  906.                     cookiesAreInvalid = true;
  907.                     SteamUser.RequestWebAPIUserNonce();
  908.                     return false;
  909.                 }
  910.             }
  911.             catch
  912.             {
  913.                 // Even if exception is caught, we should still continue.
  914.                 Log.Warn("Cookie check failed. http://steamcommunity.com is possibly down.");
  915.             }
  916.  
  917.             return true;
  918.         }
  919.  
  920.         UserHandler GetUserHandler(SteamID sid)
  921.         {
  922.             if (!userHandlers.ContainsKey(sid))
  923.                 userHandlers[sid] = createHandler(this, sid);
  924.             return userHandlers[sid];
  925.         }
  926.  
  927.         void RemoveUserHandler(SteamID sid)
  928.         {
  929.             if (userHandlers.ContainsKey(sid))
  930.                 userHandlers.Remove(sid);
  931.         }
  932.  
  933.         static byte[] SHAHash(byte[] input)
  934.         {
  935.             SHA1Managed sha = new SHA1Managed();
  936.  
  937.             byte[] output = sha.ComputeHash(input);
  938.  
  939.             sha.Clear();
  940.  
  941.             return output;
  942.         }
  943.  
  944.         void OnUpdateMachineAuthCallback(SteamUser.UpdateMachineAuthCallback machineAuth)
  945.         {
  946.             byte[] hash = SHAHash(machineAuth.Data);
  947.  
  948.             Directory.CreateDirectory(System.IO.Path.Combine(System.Windows.Forms.Application.StartupPath, "sentryfiles"));
  949.  
  950.             File.WriteAllBytes(System.IO.Path.Combine("sentryfiles", String.Format("{0}.sentryfile", logOnDetails.Username)), machineAuth.Data);
  951.  
  952.             var authResponse = new SteamUser.MachineAuthDetails
  953.             {
  954.                 BytesWritten = machineAuth.BytesToWrite,
  955.                 FileName = machineAuth.FileName,
  956.                 FileSize = machineAuth.BytesToWrite,
  957.                 Offset = machineAuth.Offset,
  958.  
  959.                 SentryFileHash = hash, // should be the sha1 hash of the sentry file we just wrote
  960.  
  961.                 OneTimePassword = machineAuth.OneTimePassword, // not sure on this one yet, since we've had no examples of steam using OTPs
  962.  
  963.                 LastError = 0, // result from win32 GetLastError
  964.                 Result = EResult.OK, // if everything went okay, otherwise ~who knows~
  965.                 JobID = machineAuth.JobID, // so we respond to the correct server job
  966.             };
  967.  
  968.             // send off our response
  969.             SteamUser.SendMachineAuthResponse(authResponse);
  970.         }
  971.  
  972.         /// <summary>
  973.         /// Gets the bot's inventory and stores it in MyInventory.
  974.         /// </summary>
  975.         /// <example> This sample shows how to find items in the bot's inventory from a user handler.
  976.         /// <code>
  977.         /// Bot.GetInventory(); // Get the inventory first
  978.         /// foreach (var item in Bot.MyInventory.Items)
  979.         /// {
  980.         ///     if (item.Defindex == 5021)
  981.         ///     {
  982.         ///         // Bot has a key in its inventory
  983.         ///     }
  984.         /// }
  985.         /// </code>
  986.         /// </example>
  987.         public void GetInventory()
  988.         {
  989.             myInventoryTask = Task.Factory.StartNew((Func<Inventory>)FetchBotsInventory);
  990.         }
  991.  
  992.         public void TradeOfferRouter(TradeOffer offer)
  993.         {
  994.             if (offer.OfferState == TradeOfferState.TradeOfferStateActive)
  995.             {
  996.                 GetUserHandler(offer.PartnerSteamId).OnNewTradeOffer(offer);
  997.             }
  998.         }
  999.         public void SubscribeTradeOffer(TradeOfferManager tradeOfferManager)
  1000.         {
  1001.             tradeOfferManager.OnNewTradeOffer += TradeOfferRouter;
  1002.         }
  1003.  
  1004.         //todo: should unsubscribe eventually...
  1005.         public void UnsubscribeTradeOffer(TradeOfferManager tradeOfferManager)
  1006.         {
  1007.             tradeOfferManager.OnNewTradeOffer -= TradeOfferRouter;
  1008.         }
  1009.  
  1010.         /// <summary>
  1011.         /// Subscribes all listeners of this to the trade.
  1012.         /// </summary>
  1013.         public void SubscribeTrade(Trade trade, UserHandler handler)
  1014.         {
  1015.             trade.OnSuccess += handler.OnTradeSuccess;
  1016.             trade.OnAwaitingConfirmation += handler._OnTradeAwaitingConfirmation;
  1017.             trade.OnClose += handler.OnTradeClose;
  1018.             trade.OnError += handler.OnTradeError;
  1019.             trade.OnStatusError += handler.OnStatusError;
  1020.             //trade.OnTimeout += OnTradeTimeout;
  1021.             trade.OnAfterInit += handler.OnTradeInit;
  1022.             trade.OnUserAddItem += handler.OnTradeAddItem;
  1023.             trade.OnUserRemoveItem += handler.OnTradeRemoveItem;
  1024.             trade.OnMessage += handler.OnTradeMessageHandler;
  1025.             trade.OnUserSetReady += handler.OnTradeReadyHandler;
  1026.             trade.OnUserAccept += handler.OnTradeAcceptHandler;
  1027.         }
  1028.  
  1029.         /// <summary>
  1030.         /// Unsubscribes all listeners of this from the current trade.
  1031.         /// </summary>
  1032.         public void UnsubscribeTrade(UserHandler handler, Trade trade)
  1033.         {
  1034.             trade.OnSuccess -= handler.OnTradeSuccess;
  1035.             trade.OnAwaitingConfirmation -= handler._OnTradeAwaitingConfirmation;
  1036.             trade.OnClose -= handler.OnTradeClose;
  1037.             trade.OnError -= handler.OnTradeError;
  1038.             trade.OnStatusError -= handler.OnStatusError;
  1039.             //Trade.OnTimeout -= OnTradeTimeout;
  1040.             trade.OnAfterInit -= handler.OnTradeInit;
  1041.             trade.OnUserAddItem -= handler.OnTradeAddItem;
  1042.             trade.OnUserRemoveItem -= handler.OnTradeRemoveItem;
  1043.             trade.OnMessage -= handler.OnTradeMessageHandler;
  1044.             trade.OnUserSetReady -= handler.OnTradeReadyHandler;
  1045.             trade.OnUserAccept -= handler.OnTradeAcceptHandler;
  1046.         }
  1047.  
  1048.         /// <summary>
  1049.         /// Fetch the Bot's inventory and log a warning if it's private
  1050.         /// </summary>
  1051.         private Inventory FetchBotsInventory()
  1052.         {
  1053.             var inventory = Inventory.FetchInventory(SteamUser.SteamID, ApiKey, SteamWeb);
  1054.             if (inventory.IsPrivate)
  1055.             {
  1056.                 log.Warn("The bot's backpack is private! If your bot adds any items it will fail! Your bot's backpack should be Public.");
  1057.             }
  1058.             return inventory;
  1059.         }
  1060.  
  1061.         public void AcceptAllMobileTradeConfirmations()
  1062.         {
  1063.             if (SteamGuardAccount == null)
  1064.             {
  1065.                 Log.Warn("Bot account does not have 2FA enabled.");
  1066.             }
  1067.             else
  1068.             {
  1069.                 SteamGuardAccount.Session.SteamLogin = SteamWeb.Token;
  1070.                 SteamGuardAccount.Session.SteamLoginSecure = SteamWeb.TokenSecure;
  1071.                 try
  1072.                 {
  1073.                     foreach (var confirmation in SteamGuardAccount.FetchConfirmations())
  1074.                     {
  1075.                         if (SteamGuardAccount.AcceptConfirmation(confirmation))
  1076.                         {
  1077.                             Log.Success("Confirmed {0}. (Confirmation ID #{1})", confirmation.ConfirmationDescription, confirmation.ConfirmationID);
  1078.                         }
  1079.                     }
  1080.                 }
  1081.                 catch (SteamAuth.SteamGuardAccount.WGTokenInvalidException)
  1082.                 {
  1083.                     Log.Error("Invalid session when trying to fetch trade confirmations.");
  1084.                 }
  1085.             }
  1086.         }
  1087.  
  1088.         /// <summary>
  1089.         /// Get duration of escrow in days. Call this before sending a trade offer.
  1090.         /// Credit to: https://www.reddit.com/r/SteamBot/comments/3w8j7c/code_getescrowduration_for_c/
  1091.         /// </summary>
  1092.         /// <param name="steamId">Steam ID of user you want to send a trade offer to</param>
  1093.         /// <param name="token">User's trade token. Can be an empty string if user is on bot's friends list.</param>
  1094.         /// <exception cref="NullReferenceException">Thrown when Steam returns an empty response.</exception>
  1095.         /// <exception cref="TradeOfferEscrowDurationParseException">Thrown when the user is unavailable for trade or Steam returns invalid data.</exception>
  1096.         /// <returns>TradeOfferEscrowDuration</returns>
  1097.         public TradeOfferEscrowDuration GetEscrowDuration(SteamID steamId, string token)
  1098.         {
  1099.             var url = "https://steamcommunity.com/tradeoffer/new/";
  1100.  
  1101.             var data = new System.Collections.Specialized.NameValueCollection();
  1102.             data.Add("partner", steamId.AccountID.ToString());
  1103.             if (!string.IsNullOrEmpty(token))
  1104.             {
  1105.                 data.Add("token", token);
  1106.             }
  1107.  
  1108.             var resp = SteamWeb.Fetch(url, "GET", data, false);
  1109.             if (string.IsNullOrWhiteSpace(resp))
  1110.             {
  1111.                 throw new NullReferenceException("Empty response from Steam when trying to retrieve escrow duration.");
  1112.             }
  1113.  
  1114.             return ParseEscrowResponse(resp);
  1115.         }
  1116.  
  1117.         /// <summary>
  1118.         /// Get duration of escrow in days. Call this after receiving a trade offer.
  1119.         /// </summary>
  1120.         /// <param name="tradeOfferId">The ID of the trade offer</param>
  1121.         /// <exception cref="NullReferenceException">Thrown when Steam returns an empty response.</exception>
  1122.         /// <exception cref="TradeOfferEscrowDurationParseException">Thrown when the user is unavailable for trade or Steam returns invalid data.</exception>
  1123.         /// <returns>TradeOfferEscrowDuration</returns>
  1124.         public TradeOfferEscrowDuration GetEscrowDuration(string tradeOfferId)
  1125.         {
  1126.             var url = "http://steamcommunity.com/tradeoffer/" + tradeOfferId;
  1127.  
  1128.             var resp = SteamWeb.Fetch(url, "GET", null, false);
  1129.             if (string.IsNullOrWhiteSpace(resp))
  1130.             {
  1131.                 throw new NullReferenceException("Empty response from Steam when trying to retrieve escrow duration.");
  1132.             }
  1133.  
  1134.             return ParseEscrowResponse(resp);
  1135.         }
  1136.  
  1137.         private TradeOfferEscrowDuration ParseEscrowResponse(string resp)
  1138.         {
  1139.             var myM = Regex.Match(resp, @"g_daysMyEscrow(?:[\s=]+)(?<days>[\d]+);", RegexOptions.IgnoreCase);
  1140.             var theirM = Regex.Match(resp, @"g_daysTheirEscrow(?:[\s=]+)(?<days>[\d]+);", RegexOptions.IgnoreCase);
  1141.             if (!myM.Groups["days"].Success || !theirM.Groups["days"].Success)
  1142.             {
  1143.                 var steamErrorM = Regex.Match(resp, @"<div id=""error_msg"">([^>]+)<\/div>", RegexOptions.IgnoreCase);
  1144.                 if (steamErrorM.Groups.Count > 1)
  1145.                 {
  1146.                     var steamError = Regex.Replace(steamErrorM.Groups[1].Value.Trim(), @"\t|\n|\r", ""); ;
  1147.                     throw new TradeOfferEscrowDurationParseException(steamError);
  1148.                 }
  1149.                 else
  1150.                 {
  1151.                     throw new TradeOfferEscrowDurationParseException(string.Empty);
  1152.                 }
  1153.             }
  1154.  
  1155.             return new TradeOfferEscrowDuration()
  1156.             {
  1157.                 DaysMyEscrow = int.Parse(myM.Groups["days"].Value),
  1158.                 DaysTheirEscrow = int.Parse(theirM.Groups["days"].Value)
  1159.             };
  1160.         }
  1161.  
  1162.         public class TradeOfferEscrowDuration
  1163.         {
  1164.             public int DaysMyEscrow { get; set; }
  1165.             public int DaysTheirEscrow { get; set; }
  1166.         }
  1167.         public class TradeOfferEscrowDurationParseException : Exception
  1168.         {
  1169.             public TradeOfferEscrowDurationParseException() : base() { }
  1170.             public TradeOfferEscrowDurationParseException(string message) : base(message) { }
  1171.         }
  1172.  
  1173.         #region Background Worker Methods
  1174.  
  1175.         private void BackgroundWorkerOnRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs runWorkerCompletedEventArgs)
  1176.         {
  1177.             if (runWorkerCompletedEventArgs.Error != null)
  1178.             {
  1179.                 Exception ex = runWorkerCompletedEventArgs.Error;
  1180.  
  1181.                 Log.Error("Unhandled exceptions in bot {0} callback thread: {1} {2}",
  1182.                       DisplayName,
  1183.                       Environment.NewLine,
  1184.                       ex);
  1185.  
  1186.                 Log.Info("This bot died. Stopping it..");
  1187.                 //backgroundWorker.RunWorkerAsync();
  1188.                 //Thread.Sleep(10000);
  1189.                 StopBot();
  1190.                 //StartBot();
  1191.             }
  1192.         }
  1193.  
  1194.         private void BackgroundWorkerOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs)
  1195.         {
  1196.             ICallbackMsg msg;
  1197.  
  1198.             while (!botThread.CancellationPending)
  1199.             {
  1200.                 try
  1201.                 {
  1202.                     msg = SteamClient.WaitForCallback(true);
  1203.                     HandleSteamMessage(msg);
  1204.                 }
  1205.                 catch (WebException e)
  1206.                 {
  1207.                     Log.Error("URI: {0} >> {1}", (e.Response != null && e.Response.ResponseUri != null ? e.Response.ResponseUri.ToString() : "unknown"), e.ToString());
  1208.                     System.Threading.Thread.Sleep(45000);//Steam is down, retry in 45 seconds.
  1209.                 }
  1210.                 catch (Exception e)
  1211.                 {
  1212.                     Log.Error(e.ToString());
  1213.                     Log.Warn("Restarting bot...");
  1214.                 }
  1215.             }
  1216.         }
  1217.  
  1218.         #endregion Background Worker Methods
  1219.  
  1220.         private void FireOnSteamGuardRequired(SteamGuardRequiredEventArgs e)
  1221.         {
  1222.             // Set to null in case this is another attempt
  1223.             this.AuthCode = null;
  1224.  
  1225.             EventHandler<SteamGuardRequiredEventArgs> handler = OnSteamGuardRequired;
  1226.             if (handler != null)
  1227.                 handler(this, e);
  1228.             else
  1229.             {
  1230.                 while (true)
  1231.                 {
  1232.                     if (this.AuthCode != null)
  1233.                     {
  1234.                         e.SteamGuard = this.AuthCode;
  1235.                         break;
  1236.                     }
  1237.  
  1238.                     Thread.Sleep(5);
  1239.                 }
  1240.             }
  1241.         }
  1242.  
  1243.         #region Group Methods
  1244.  
  1245.         /// <summary>
  1246.         /// Accepts the invite to a Steam Group
  1247.         /// </summary>
  1248.         /// <param name="group">SteamID of the group to accept the invite from.</param>
  1249.         private void AcceptGroupInvite(SteamID group)
  1250.         {
  1251.             var AcceptInvite = new ClientMsg<CMsgGroupInviteAction>((int)EMsg.ClientAcknowledgeClanInvite);
  1252.  
  1253.             AcceptInvite.Body.GroupID = group.ConvertToUInt64();
  1254.             AcceptInvite.Body.AcceptInvite = true;
  1255.  
  1256.             this.SteamClient.Send(AcceptInvite);
  1257.  
  1258.         }
  1259.  
  1260.         /// <summary>
  1261.         /// Declines the invite to a Steam Group
  1262.         /// </summary>
  1263.         /// <param name="group">SteamID of the group to decline the invite from.</param>
  1264.         private void DeclineGroupInvite(SteamID group)
  1265.         {
  1266.             var DeclineInvite = new ClientMsg<CMsgGroupInviteAction>((int)EMsg.ClientAcknowledgeClanInvite);
  1267.  
  1268.             DeclineInvite.Body.GroupID = group.ConvertToUInt64();
  1269.             DeclineInvite.Body.AcceptInvite = false;
  1270.  
  1271.             this.SteamClient.Send(DeclineInvite);
  1272.         }
  1273.  
  1274.         /// <summary>
  1275.         /// Invites a use to the specified Steam Group
  1276.         /// </summary>
  1277.         /// <param name="user">SteamID of the user to invite.</param>
  1278.         /// <param name="groupId">SteamID of the group to invite the user to.</param>
  1279.         public void InviteUserToGroup(SteamID user, SteamID groupId)
  1280.         {
  1281.             var InviteUser = new ClientMsg<CMsgInviteUserToGroup>((int)EMsg.ClientInviteUserToClan);
  1282.  
  1283.             InviteUser.Body.GroupID = groupId.ConvertToUInt64();
  1284.             InviteUser.Body.Invitee = user.ConvertToUInt64();
  1285.             InviteUser.Body.UnknownInfo = true;
  1286.  
  1287.             this.SteamClient.Send(InviteUser);
  1288.         }
  1289.  
  1290.         #endregion
  1291.  
  1292.         public void Dispose()
  1293.         {
  1294.             Dispose(true);
  1295.             GC.SuppressFinalize(this);
  1296.         }
  1297.  
  1298.         private void Dispose(bool disposing)
  1299.         {
  1300.             if (disposed)
  1301.                 return;
  1302.             StopBot();
  1303.             if (disposing)
  1304.                 Log.Dispose();
  1305.             disposed = true;
  1306.         }
  1307.     }
  1308. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement