Advertisement
Guest User

Untitled

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