Skip to content

Instantly share code, notes, and snippets.

@alex7kom
Last active July 15, 2022 16:15
Show Gist options
  • Star 19 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save alex7kom/d764ef2925060c4e7c27 to your computer and use it in GitHub Desktop.
Save alex7kom/d764ef2925060c4e7c27 to your computer and use it in GitHub Desktop.
Steam Donation Bot

Steam Donation Bot

A Steam bot that accepts item donations.

Basically, it accepts any offer that doesn't ask for any items from its inventory.

Feel free to use if you want to accept item donations for your project, or modify it as you see fit.

This bot does not support mobile auth as of yet.

Install and run

  1. Install the latest Node.js.
  2. Click 'Download ZIP' button on the top of this page.
  3. Unpack this ZIP file wherever you like.
  4. Switch to the resulting directory in a command line or a terminal.
  5. Do npm install in the directory.
  6. Edit donation_bot.js to put your account credentials. Leave authCode as is for now.
  7. Run node donation_bot.js. It will 'crash' shortly, and you'll receive an email with Steam Guard code.
  8. Edit donation_bot.js again to put Steam Guard code into authCode, then run node donation_bot.js again. A sentry file will be created in the same directory with the bot. From now on you can run node donation_bot.js to launch the bot.

Note: After sentry file is created, you'll need to wait for 7-15 days due to Steam Guard trade restrictions. Do NOT delete sentry file!

License

MIT

/* START EDITING */
// Put your 64-bit SteamID here so the bot can accept your offers
var admin = '';
var logOnOptions = {
account_name: '',
password: ''
};
var authCode = ''; // Code received by email
/* STOP EDITING */
var fs = require('fs');
var crypto = require('crypto');
var Steam = require('steam');
var SteamWebLogOn = require('steam-weblogon');
var getSteamAPIKey = require('steam-web-api-key');
var SteamTradeOffers = require('steam-tradeoffers');
var sentryFileName = 'sentry'; // steam guard data file name
try {
logOnOptions.sha_sentryfile = getSHA1(fs.readFileSync(sentryFileName));
} catch (e) {
if (authCode !== '') {
logOnOptions.auth_code = authCode;
}
}
// if we've saved a server list, use it
if (fs.existsSync('servers')) {
Steam.servers = JSON.parse(fs.readFileSync('servers'));
}
var steamClient = new Steam.SteamClient();
var steamUser = new Steam.SteamUser(steamClient);
var steamFriends = new Steam.SteamFriends(steamClient);
var steamWebLogOn = new SteamWebLogOn(steamClient, steamUser);
var offers = new SteamTradeOffers();
steamClient.connect();
steamClient.on('connected', function() {
steamUser.logOn(logOnOptions);
});
steamClient.on('logOnResponse', function(logonResp) {
if (logonResp.eresult === Steam.EResult.OK) {
console.log('Logged in!');
steamFriends.setPersonaState(Steam.EPersonaState.Online);
steamWebLogOn.webLogOn(function(sessionID, newCookie) {
getSteamAPIKey({
sessionID: sessionID,
webCookie: newCookie
}, function(err, APIKey) {
offers.setup({
sessionID: sessionID,
webCookie: newCookie,
APIKey: APIKey
});
handleOffers();
});
});
}
});
steamClient.on('servers', function(servers) {
fs.writeFile('servers', JSON.stringify(servers));
});
steamUser.on('updateMachineAuth', function(sentry, callback) {
fs.writeFileSync(sentryFileName, sentry.bytes);
callback({ sha_file: getSHA1(sentry.bytes) });
});
steamUser.on('tradeOffers', function(number) {
if (number > 0) {
handleOffers();
}
});
function handleOffers() {
offers.getOffers({
get_received_offers: 1,
active_only: 1,
time_historical_cutoff: Math.round(Date.now() / 1000),
get_descriptions: 1
}, function(error, body) {
if (error) {
return log(error);
}
if (
body
&& body.response
&& body.response.trade_offers_received
) {
var descriptions = {};
body.response.descriptions = body.response.descriptions || [];
body.response.descriptions.forEach(function (desc) {
descriptions[
desc.appid + ';' + desc.classid + ';' + desc.instanceid
] = desc;
});
body.response.trade_offers_received.forEach(function (offer) {
if (offer.trade_offer_state !== 2) {
return;
}
var offerMessage = 'Got an offer ' + offer.tradeofferid +
' from ' + offer.steamid_other + '\n';
if (offer.items_to_receive) {
offerMessage += 'Items to receive: ' +
offer.items_to_receive.map(function (item) {
var desc = descriptions[
item.appid + ';' + item.classid + ';' + item.instanceid
];
return desc.name + ' (' + desc.type + ')';
}).join(', ') + '\n';
}
if (offer.items_to_give) {
offerMessage += 'Items to give: ' +
offer.items_to_give.map(function (item) {
var desc = descriptions[
item.appid + ';' + item.classid + ';' + item.instanceid
];
return desc.name + ' (' + desc.type + ')';
}).join(', ') + '\n';
}
if (offer.message && offer.message !== '') {
offerMessage += 'Message: ' + offer.message;
}
log(offerMessage);
if (offer.steamid_other === admin || !offer.items_to_give) {
offers.acceptOffer({
tradeOfferId: offer.tradeofferid,
partnerSteamId: offer.steamid_other
}, function (error, result) {
if (error) {
return log(error);
}
log('Offer ' + offer.tradeofferid + ' accepted');
offers.getOffer({
tradeofferid: offer.tradeofferid
}, function (error, result) {
if (error) {
return log(error);
}
if (result
&& result.response
&& result.response.offer
&& result.response.offer.tradeid
) {
offers.getItems({
tradeId: result.response.offer.tradeid
}, function (error, result) {
if (error) {
return log(error);
}
var items = 'Got items:\n' +
result.map(function (item) {
return 'http://steamcommunity.com/profiles/' +
item.owner + '/inventory/#' +
item.appid + '_' + item.contextid + '_' + item.id;
}).join('\n');
log(items);
});
}
});
});
} else {
offers.declineOffer({
tradeOfferId: offer.tradeofferid
}, function (error, result) {
if (error) {
return log(error);
}
log('Offer ' + offer.tradeofferid + ' declined');
});
}
});
}
});
}
function log (message) {
console.log(new Date().toString() + ' - ' + message);
steamFriends.sendMessage(admin, message.toString());
}
function getSHA1 (bytes) {
var shasum = crypto.createHash('sha1');
shasum.end(bytes);
return shasum.read();
}
{
"name": "donation-bot",
"description": "A Steam bot that accepts item donations.",
"version": "0.0.2",
"author": "Alex7Kom",
"dependencies": {
"steam": "*",
"steam-tradeoffers": "*",
"steam-web-api-key": "*",
"steam-weblogon": "*"
}
}
@BKrow
Copy link

BKrow commented Oct 18, 2015

Update the steam guard variable:

var authCode = ''; // Code received by email

Then retry.

    root@server2 [/home/x/www/bidcsgo.io]# node bots/donations.js
events.js:85
      throw er; // Unhandled 'error' event
            ^
Error: Disconnected
    at SteamClient._disconnected (/home/x/public_html/x.io/node_modules/steam/lib/steam_client.js:186:24)
    at Connection.emit (events.js:107:17)
    at TCP.close (net.js:485:12)
root@server2 [/home/x/www/x.io]# node bots/donations.js
Logged in!

Everything is working on my end.

Sun Oct 18 2015 19:23:27 GMT-0400 (EDT) - Got an offer 780668628 from 76561197973808748
Items to receive: Mann Co. Supply Crate Series #76 (Level 13 Supply Crate)

Sun Oct 18 2015 19:23:28 GMT-0400 (EDT) - Error: There was an error accepting this trade offer.  Please try again later. (24)

This is the error you'll receive for logging into a new device (It's 7 days)
There's clues here man, read. Win. <3

@adaptivedev
Copy link

@onlywaydie
Copy link

I got this error, after i updated steam guard variable.

C:\Program Files\donation bot>node donation_bot.js
Logged in!
Wed Nov 11 2015 08:45:56 GMT-0800 (Pacific Standard Time) - Error: 403
C:\Program Files\donation bot\node_modules\long\dist\long.js:204
throw Error('number format error: empty string');
^
Error: number format error: empty string
at Error (native)
at Function.fromString (C:\Program Files\donation bot\node_modules\long\dist
\long.js:204:19)
at Function.fromValue (C:\Program Files\donation bot\node_modules\long\dist
long.js:252:25)
at Function.SteamID.decode (C:\Program Files\donation bot\node_modules\steam
\lib\steamID.js:19:18)
at SteamFriends.sendMessage (C:\Program Files\donation bot\node_modules\stea
m\lib\handlers\friends\index.js:59:20)
at log (C:\Program Files\donation bot\donation_bot.js:202:16)
at C:\Program Files\donation bot\donation_bot.js:94:14
at Object.doAPICall.bind.callback (C:\Program Files\donation bot\node_module
s\steam-tradeoffers\index.js:112:16)
at SteamTradeOffers. (C:\Program Files\donation bot\node_modules
steam-tradeoffers\index.js:432:17)
at Request.self.callback (C:\Program Files\donation bot\node_modules\request
\request.js:198:22)

@onlywaydie
Copy link

After a week, when i send offers, bot sees them, but do nothing
C:\Program Files\donation bot>node donation_bot.js
Logged in!
Thu Nov 19 2015 04:43:00 GMT-0800 (Pacific Standard Time) - Error: 403
Thu Nov 19 2015 04:43:32 GMT-0800 (Pacific Standard Time) - Error: 403
Thu Nov 19 2015 04:44:06 GMT-0800 (Pacific Standard Time) - Error: 403

@stackbasher
Copy link

if i do "node donation_bot.js", nothing happens. Not even "logged in!" is popping up in the cmd. There is no reponse, just a cursor wich is blinking, wich is saying me that the script is running. im not even getting an error code. after like 30 seconds the script stops. im don't even get an error code. im pretty sad right now. does anyone know what im doing wrong?

@ElishaDev
Copy link

How can I check, if someone has installed the mobile authenticator?
Like:
if(offer.mobile_authenticator) {
//some code
}

@Cj1m
Copy link

Cj1m commented Feb 12, 2016

Any plans on adding mobile authentication support?

@Mr0Inka
Copy link

Mr0Inka commented Jun 3, 2016

I am getting this error after node donation_bot.js

events.js:141
      throw er; // Unhandled 'error' event
      ^

Error: Disconnected
    at SteamClient._disconnected (C:\Users\Thomas\Desktop\TradeBot\node_modules\steam\lib\steam_client.js:186:24)
    at emitOne (events.js:77:13)
    at Connection.emit (events.js:169:7)
    at TCP._onclose (net.js:477:12)

What am I doing wrong?

@seniv
Copy link

seniv commented Jun 3, 2016

Mr0Inka, check your email, and paste code from email here:
var authCode = 'code here';
then save file and run again

@EmmyLouise
Copy link

EmmyLouise commented Jul 11, 2016

I have almost the exact same error as Mr0Inka but have not received any emails to copy codes across. Any ideas?
Edit: Scrap that. Ran it a second time and it succeeded.

@Govind13100
Copy link

Can anyone explain here what is the use of sentry file??????

And the wait for 7-15 days are mandatory for all devices or only for new devices????

@F1zzzy
Copy link

F1zzzy commented Dec 12, 2017

Ребят кто русские помогите!!!
P.S.
Проблема с другим ботом
Error: Cannot find module '@protobufjs/aspromise'
at Function.Module._resolveFilename (module.js:536:15)
at Function.Module._load (module.js:466:25)
at Module.require (module.js:579:17)
at require (internal/module.js:11:18)
at Object. (C:\Users\Евгений\Desktop\node_modules\protobufjs\src\util\minimal.js:5:18)
at Module._compile (module.js:635:30)
at Object.Module._extensions..js (module.js:646:10)
at Module.load (module.js:554:32)
at tryModuleLoad (module.js:497:12)
at Function.Module._load (module.js:489:3)

@iSize1ce
Copy link

iSize1ce commented Feb 21, 2018

This bot does not support mobile auth as of yet.

Only email? Auth code from mobile app same as email, isn't?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment