Advertisement
Guest User

paste code

a guest
Oct 27th, 2017
26
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.28 KB | None | 0 0
  1. var config = require('./config');
  2.  
  3. var SteamTotp = require("steam-totp");
  4. var TradeOfferManager = require("steam-tradeoffer-manager");
  5. var SteamCommunity = require("steamcommunity");
  6. var SteamUser = require("steam-user");
  7.  
  8. var fs = require("fs");
  9. var request = require("request");
  10.  
  11. var client = new SteamUser();
  12. var community = new SteamCommunity();
  13. var manager = new TradeOfferManager({
  14. "steam": client,
  15. "language": "en",
  16. "pollInterval": 2000 // Poll offers every 2 seconds (2000 ms).
  17. });
  18.  
  19. client.setOption("promptSteamGuardCode", false);
  20.  
  21. console.log("Selling CS:GO keys for " + rateAsText(false) + " or " + convertRateToKeysAndMetal(getRate(false)) + ", buying CS:GO keys for " + rateAsText(true) + " or " + convertRateToKeysAndMetal(getRate(true)));
  22.  
  23. login();
  24.  
  25. function login() {
  26. SteamTotp.getTimeOffset(function(err, offset) {
  27. if (err) {
  28. console.log("An error occurred getting the time offset, retrying in 10 seconds...");
  29. return setTimeout(login, 1000 * 10); // Wait 1 minut
  30. }
  31.  
  32. var logOnDetails = getLoginDetails(offset);
  33. client.logOn(logOnDetails);
  34. });
  35. }
  36.  
  37. client.on("loggedOn", loggedOn);
  38.  
  39. client.on('webSession', function(sessionID, cookies) {
  40. manager.setCookies(cookies, function(err) {
  41. if (err) {
  42. console.log("An error occurred setting the cookies, retrying...");
  43. return client.webLogOn();
  44. }
  45. });
  46. community.setCookies(cookies);
  47.  
  48. community.profileSettings({
  49. profile: 3,
  50. comments: 3,
  51. inventory: 3
  52. }, function(err, response) {
  53. if (err) {
  54. console.log("An error occurred while trying to update the privacy settings...");
  55. }
  56. });
  57. /*
  58. community.editProfile({
  59. name: config.name,
  60. }, function(err) {
  61. if (err) return console.log("An error occurred while trying to edit the profile...");
  62. });
  63. */
  64. });
  65.  
  66. community.on("sessionExpired", function(err) {
  67. console.log("The session expired, logging in again...");
  68. client.webLogOn();
  69. });
  70.  
  71. client.on('friendRelationship', function(steamID, relationship) {
  72. // If the user send us a friend request, we will continue.
  73. if (relationship == SteamUser.Steam.EFriendRelationship.RequestRecipient) {
  74. addFriend(steamID);
  75. }
  76. });
  77.  
  78. client.on("friendsList", function() {
  79. for (var steamID in client.myFriends) {
  80. var relationship = client.myFriends[steamID];
  81. if (relationship == SteamUser.Steam.EFriendRelationship.RequestRecipient) {
  82. addFriend(steamID);
  83. }
  84. }
  85. });
  86.  
  87. function addFriend(steamID) {
  88. client.addFriend(steamID, function(err, name) {
  89. if (err) return console.log("An error occurred while trying to add a friend...");
  90. console.log("I am now friends with " + name);
  91. });
  92. }
  93.  
  94. community.on('confKeyNeeded', function(tag, callback) {
  95. var time = Math.floor(Date.now() / 1000);
  96. callback(null, time, SteamTotp.getConfirmationKey(config.identity_secret, time, tag));
  97. });
  98.  
  99. manager.on("newOffer", handleOffer);
  100.  
  101. manager.on("receivedOfferChanged", offerStateChanged);
  102.  
  103. function loggedOn() {
  104. client.setPersona(SteamUser.EPersonaState.Online);
  105. console.log("Logged onto Steam");
  106. client.gamesPlayed(["CS:GO & TF2 KEYS EXCHANGE ♦SEND A TRADE OFFER ♦24/7 ACCEPT"]);
  107. if (config.notify && config.admin) client.chatMessage(config.admin, "Selling CS:GO keys for " + rateAsText(false) + " or " + convertRateToKeysAndMetal(getRate(false)) + ", buying CS:GO keys for " + rateAsText(true) + " or " + convertRateToKeysAndMetal(getRate(true)));
  108. }
  109.  
  110. function handleOffer(offer) {
  111. console.log("Incoming offer from " + offer.partner.getSteamID64());
  112. if (offer.isGlitched()) {
  113. console.log("The offer appears to be glitched, declining...");
  114. return declineOffer(offer);
  115. }
  116. if (offer.partner.getSteamID64() == config.admin) {
  117. console.log("The offer is from an admin (" + config.admin + "), accepting...");
  118. return acceptOffer(offer);
  119. }
  120. if (offer.itemsToGive.length == 0) {
  121. console.log("The offer is a donation (we are not offering any items), accepting...");
  122. return acceptOffer(offer);
  123. }
  124. if (offer.itemsToReceive.length == 0) {
  125. console.log("The user is only taking items (they are not offering any items), declining...");
  126. return declineOffer(offer);
  127. }
  128. isEscrow(offer, function(err, escrow) {
  129. if (err) {
  130. console.log("An error occurred while checking for escrow, skipping the offer...");
  131. process.exit(0);
  132. return;
  133. }
  134. if (escrow) {
  135. console.log("Offer will be in escrow, declining...");
  136. return declineOffer(offer);
  137. }
  138. isScammer(offer.partner.getSteamID64(), function(err, isScammer) {
  139. if (err) console.log("An error occurred while checking if the user is a scammer: " + err);
  140. // If an error occurred, isScammer will be undefinded and this will return false. Keep it simple ;)
  141. if (isScammer) {
  142. console.log("The partner is marked as a scammer on SteamRep, declining...");
  143. return declineOffer(offer);
  144. }
  145. var accept = verifyOffer(offer.itemsToGive, offer.itemsToReceive);
  146. if (accept) {
  147. acceptOffer(offer);
  148. } else {
  149. declineOffer(offer)
  150. }
  151. });
  152. });
  153. }
  154.  
  155. function verifyOffer(ourItems, theirItems) {
  156. var ourAppID = null;
  157.  
  158. // This is offered together, or it is not a valid offer.
  159. var csgoKeys = 0;
  160. var change = 0;
  161.  
  162. // Same as above, just with these values.
  163. var tf2Keys = 0;
  164. var metal = 0;
  165.  
  166. // The bot buy csgo keys at a rate of 8 csgo for 9 tf2 + 4.22 refined.
  167.  
  168. // The bot does not have 4.22 refined, but it has 5 refined.
  169.  
  170. // We offer the bot 8 csgo keys and 0.77 refined for 9 tf2 keys and 5 refined
  171.  
  172. // That's the same as 8 csgo keys for 9 tf2 keys and 4.22 refined
  173.  
  174. // Also accept metal as tf2 / csgo keys.
  175.  
  176. /*
  177.  
  178. Nicklason: I offer the bot 10 csgo keys and metal for x tf2 keys
  179. Nicklason: Use the metal as change
  180. Nicklason: And only in that situation
  181.  
  182. dont use metal as tf2 keys as the bot will get full quickly.
  183.  
  184.  
  185. */
  186.  
  187. // Loop our items.
  188. for (var i = 0; i < ourItems.length; i++) {
  189. var item = ourItems[i];
  190. // If we are offering an item which is from csgo (item.appid is 730), and that is appid as the other items we hace checked, or the appid is null.
  191. if (item.appid == "730" && (ourAppID == item.appid || ourAppID == null)) {
  192. // We will then check if the item is a "valid" key, which i just a way to say that we accept this item as a csgo key.
  193. if (isValidKey(item.market_name)) {
  194. if (ourAppID == null) ourAppID = item.appid; // Set our appid if it has not been set yet.
  195. csgoKeys++;
  196. } else {
  197. return false; // Return false as the offer is not valid and it should be declined.
  198. }
  199. } else if (item.appid == "440" && (ourAppID == item.appid || ourAppID == null)) {
  200. if (item.market_name === "Mann Co. Supply Crate Key") {
  201. if (ourAppID == null) ourAppID = item.appid; // Set our appid if it has not been set yet.
  202. tf2Keys++;
  203. } else {
  204. // If the item is not a key, we will check if it is metal.
  205. var _isMetal = isMetal(item.market_name);
  206. // isMetal will return false if it is not metal, and it will return the amount in scrap if it is.
  207. if (_isMetal) {
  208. metal += _isMetal;
  209. } else {
  210. return false;
  211. }
  212. }
  213. // If the appid of the currently looped item is 440, and our appid is 730, we will take this as change (but only if it is metal).
  214. } else if (item.appid == "440" && (ourAppID == "730")) {
  215. var _isMetal = isMetal(item.market_name);
  216. if (_isMetal) {
  217. change += _isMetal;
  218. } else {
  219. return false;
  220. }
  221. } else {
  222. return false; // Return false if it is not the appid of tf2 or csgo, and if we offer items from different appids.
  223. }
  224. }
  225.  
  226. for (var i = 0; i < theirItems.length; i++) {
  227. var item = theirItems[i];
  228. // Same as before, just the other way around. I am not checking if ourAppID is null because it should always have a value here.
  229. // The bot will always decline offers where the user is not offering anything, and accept if the bot is not offering anything,
  230. // it will therefore always contain items on both sides.
  231. if (item.appid == "730" && (ourAppID != item.appid)) {
  232. if (isValidKey(item.market_name)) {
  233. csgoKeys++;
  234. } else {
  235. return false;
  236. }
  237. } else if (item.appid == "440" && (ourAppID != item.appid)) {
  238. if (item.market_name === "Mann Co. Supply Crate Key") {
  239. tf2Keys++;
  240. } else {
  241. var _isMetal = isMetal(item.market_name);
  242. if (_isMetal) {
  243. metal += _isMetal;
  244. } else {
  245. return false;
  246. }
  247. }
  248. // If they offer an item from tf2, but we are not offering items from csgo (we are offering tf2), we will take this as change.
  249. } else if (item.appid == "440" && ourAppID != "730") {
  250. var _isMetal = isMetal(item.market_name);
  251. if (_isMetal) {
  252. change += _isMetal;
  253. } else {
  254. return false;
  255. }
  256. }
  257. }
  258.  
  259. if (change > 8) {
  260. console.log("offering more change than allowed");
  261. return false; // Since one refined is 9 scrap, we will decline offers with more change than 8 scrap worth of metal.
  262. }
  263. metal = metal - change;
  264. if (metal < 0) {
  265. console.log("Metal is less than 0, declining...");
  266. return false;
  267. }
  268.  
  269. if (metal >= refinedToScrap(config.rate.keyPrice)) {
  270. console.log("The user offers more or the same amount as the value of a key, declining...");
  271. return false; // We will not accept metal as keys.
  272. }
  273. var actualRate = getRate(ourAppID == "440");
  274. var offeredRate = calculateRate(csgoKeys, tf2Keys, metal);
  275.  
  276. console.log(actualRate, offeredRate);
  277.  
  278. if (offeredRate <= actualRate && ourAppID == "440") {
  279. console.log("We are offering tf2 items, user is offering csgo. Price is right, accepting.");
  280. return true;
  281. } else if (offeredRate >= actualRate && ourAppID == "730") {
  282. console.log("We are offering csgo items, user is offering tf2. Price is right, accepting.");
  283. return true;
  284. } else {
  285. console.log("The offer is not valid, declining...");
  286. return false;
  287. }
  288. /*
  289. if (offeredRate <= actualRate) {
  290. console.log("The user is offering me a rate of " + offeredRate + ", the actual rate is " + actualRate + ", accepting...");
  291. return true;
  292. } else {
  293. console.log("The offer is not valid, declining...");
  294. return false;
  295. }
  296. */
  297. }
  298.  
  299. function isEscrow(offer, callback) {
  300. offer.getUserDetails(function(err, me, them) {
  301. if (err) {
  302. client.webLogOn();
  303. return callback(err);
  304. }
  305. if (them.escrowDays > 0) return callback(null, true);
  306. if (me.escrowDays > 0) return callback(null, true);
  307.  
  308. return callback(null, false);
  309. });
  310. }
  311.  
  312. function scrapToRefined(scrap) {
  313. var refined = parseFloat((scrap / 9).toString().match(/^-?\d+(?:\.\d{0,2})?/)[0]);
  314. return refined;
  315. }
  316.  
  317. function refinedToScrap(refined) {
  318. var scrap = parseInt(Math.round(refined * 9));
  319. return scrap;
  320. }
  321.  
  322. function keysAndMetalAsText(keys, refined) {
  323. var text = "0 keys & 0 refined";
  324. if (keys != 0) {
  325. text = keys + " " + (keys > 1 ? "keys" : "key");
  326. }
  327. if (refined != 0) {
  328. if (text == "0 keys & 0 refined") {
  329. text = refined + ' refined';
  330. } else {
  331. text += ' & ' + refined + ' refined';
  332. }
  333. }
  334. return text.toUpperCase();
  335. }
  336.  
  337. function rateAsText(weBuyCSGO) {
  338. var intent = weBuyCSGO ? "buy" : "sell";
  339. var tf2Price = config.rate[intent].metal == 0 ? config.rate[intent].tf2 : config.rate[intent].tf2 + "+" + config.rate[intent].metal + " refined";
  340. return config.rate[intent].csgo + ":" + tf2Price;
  341. }
  342.  
  343. /*
  344. function summary() {
  345. var sellRate = getRate(false);
  346. var buyRate = getRate(true);
  347.  
  348. return "[h1][b]★Buy [u]My CS:GO Keys[/u] ➨ " + rateAsText(false) + " Or " + convertRateToKeysAndMetal(sellRate) + "\n★Sell [u]Your CS:GO Keys[/u] ➨ " + rateAsText(true) + " Or " + convertRateToKeysAndMetal(buyRate) + "[/b][/h1]\n[b][url=" + config.tradeoffer_url + "][h1][b]:crate:TRADE OFFER LINK[/b][/h1][/url][/b][b][url=https://steamcommunity.com/id/junglibunny/][h1][b]:spycon:Owner[/b][/h1][/url][/b] [b][url=http://steamcommunity.com/groups/Bunnykeyswap][h1][b]:csgoglobe:Steam Group[/b][/h1][/url][/b]";
  349. }
  350. */
  351.  
  352. function calculateRate(csgoKeys, tf2Keys, metal) {
  353. var metalInKeys = metal / refinedToScrap(config.rate.keyPrice);
  354. var rate = (tf2Keys + metalInKeys) / csgoKeys;
  355.  
  356. return rate.toString().match(/^-?\d+(?:\.\d{0,3})?/)[0];
  357. }
  358.  
  359. function convertRateToKeysAndMetal(rate) {
  360. var keys = Math.floor(rate);
  361. var metal = scrapToRefined(refinedToScrap((rate - keys) * config.rate.keyPrice));
  362. return keysAndMetalAsText(keys, metal);
  363. }
  364.  
  365. function getRate(weBuyCSGO) {
  366. if (weBuyCSGO) {
  367. return ((config.rate.buy.tf2 + (refinedToScrap(config.rate.buy.metal) / refinedToScrap(config.rate.keyPrice))) / config.rate.buy.csgo).toString().match(/^-?\d+(?:\.\d{0,3})?/)[0];
  368. } else {
  369. return ((config.rate.sell.tf2 + (refinedToScrap(config.rate.sell.metal) / refinedToScrap(config.rate.keyPrice))) / config.rate.sell.csgo).toString().match(/^-?\d+(?:\.\d{0,3})?/)[0];
  370. }
  371. }
  372.  
  373. function isValidKey(name) {
  374. // If the name is in the acceptedKeys array, this will return true. If not, false ofc.
  375. return config.acceptedKeys.some(function(key) {
  376. if (key == name) return true;
  377. });
  378. }
  379.  
  380. function isMetal(name) {
  381. // Return the value of the metal in scrap if it is metal. It will return false if not.
  382. if (name == "Refined Metal") return 9;
  383. if (name == "Reclaimed Metal") return 3;
  384. if (name == "Scrap Metal") return 1;
  385.  
  386. return false;
  387. }
  388.  
  389. function declineOffer(offer) {
  390. offer.decline(function (err) {
  391. if (err) {
  392. client.webLogOn();
  393. console.log("An error occurred when trying to decline offer #" + offer.id);
  394. }
  395. });
  396. }
  397.  
  398. function acceptOffer(offer) {
  399. offer.accept(function(err, status) {
  400. if (err) {
  401. //client.webLogOn();
  402. console.log("Unable to accept offer #" + offer.id + ": " + err);
  403. process.exit(0);
  404. return;
  405. }
  406. // If the offer status is pending, that means that we have to accept a mobile confirmation for the offer.
  407. if (status == "pending") {
  408. community.acceptConfirmationForObject(config.identity_secret, offer.id, function(err) {
  409. if (err) return console.log("An error occurred while trying to accept the mobile confirmation for offer #" + offer.id);
  410. });
  411. }
  412. });
  413. }
  414.  
  415. function offerStateChanged(offer, oldState) {
  416. console.log("Offer #" + offer.id + " changed: " + TradeOfferManager.ETradeOfferState[oldState] + " (" + oldState + ") -> " + TradeOfferManager.ETradeOfferState[offer.state] + " (" + offer.state + ")");
  417. if (config.notify && config.admin) {
  418. if (offer.state == TradeOfferManager.ETradeOfferState.Accepted) {
  419. inviteToGroup(offer.partner);
  420. return client.chatMessage(config.admin, "I've accepted a trade from " + offer.partner.getSteamID64());
  421. }
  422. if (offer.state == TradeOfferManager.ETradeOfferState.Declined) {
  423. return client.chatMessage(config.admin, "I've declined a trade from " + offer.partner.getSteamID64());
  424. }
  425. }
  426. }
  427.  
  428.  
  429. function inviteToGroup(steamID) {
  430. try {
  431. client.inviteToGroup(steamID, config.groupId);
  432. } catch (err) {
  433. console.log("An error occurred while trying to invite a user to our group: " + err.message);
  434. }
  435. }
  436.  
  437.  
  438. /*
  439. function inviteToGroup(steamID) {
  440. console.log(steamID);
  441. community.getSteamUser(steamID, function(err, cmt) {
  442. if (err) {
  443. console.log(err);
  444. } else {
  445. cmt.inviteToGroup(config.groupId);
  446. }
  447. });
  448. }
  449. */
  450.  
  451.  
  452. function getSteamRepSummary(steamid64, callback) {
  453. request({
  454. "method": "GET",
  455. "url": "http://steamrep.com/api/beta4/reputation/" + steamid64 + "?json=1"
  456. }, function(err, response, body) {
  457. if (err) return callback(err);
  458. if (!response.statusCode.toString().startsWith("2")) return callback("Statuscode: " + response.statusCode);
  459. if (!(response.headers['content-type'].indexOf("application/json") > -1)) return callback("Not a JSON response");
  460. var data = JSON.parse(body);
  461. return callback(null, data);
  462. });
  463. }
  464.  
  465. function isScammer(steamid64, callback) {
  466. getSteamRepSummary(steamid64, function(err, steamrep) {
  467. if (err) return callback(err);
  468. return callback(null, steamrep.steamrep.reputation.summary.toLowerCase().indexOf("scammer") > -1); // Returns true if their summary contains scammer.
  469. });
  470. }
  471.  
  472. function getLoginDetails(offset) {
  473. var logOnDetails = {
  474. "accountName": config.username,
  475. "password": config.password,
  476. "twoFactorCode": SteamTotp.getAuthCode(config.shared_secret, offset)
  477. };
  478. return logOnDetails;
  479. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement