commit
f42fecb137
8 changed files with 280 additions and 0 deletions
@ -0,0 +1,3 @@ |
|||
/auth_data/ |
|||
/package-lock.json |
|||
/Facti13.SteamTradeBot.JS.v1.iml |
@ -0,0 +1,11 @@ |
|||
FROM node:18.18-bullseye |
|||
|
|||
RUN git clone https://git.pblr-nyk.pro/gsd/Facti13.SteamTradeBot.JS.v1 && \ |
|||
mv Facti13.SteamTradeBot.JS.v1 /app && chown node:node -R /app && chmod 770 -R /app && \ |
|||
echo "const VERSION = $(date +%s);module.exports = VERSION;" > /app/version.js |
|||
|
|||
USER node |
|||
WORKDIR /app |
|||
RUN npm install |
|||
|
|||
CMD ["nodejs", "tradebot.js"] |
@ -0,0 +1,56 @@ |
|||
const axios = require("axios"); |
|||
class BackendIntegration { |
|||
|
|||
url = ""; |
|||
secret_key = ""; |
|||
|
|||
up = false; |
|||
prices = {}; |
|||
|
|||
constructor() { |
|||
this.url = process.env.BACKEND_URL; |
|||
this.secret_key = process.env.SECRET_KEY; |
|||
} |
|||
|
|||
async pulse() { |
|||
console.log("request pulse"); |
|||
return await axios.get(`${this.url}/api/pulse/db`, {headers:{Cookie:`secretkey=${this.secret_key};`}}).then( |
|||
response => { |
|||
this.up = response.status === 200; |
|||
} |
|||
).catch((e)=>{console.log("pulse failed!")}) |
|||
} |
|||
|
|||
getPrices(tc) { |
|||
axios.get(`${this.url}/api/external/vip`, {headers:{Cookie:`secretkey=${this.secret_key};`}}).then( |
|||
response => { |
|||
if (response.status === 200) { |
|||
tc.setPrices(response.data); |
|||
} else {console.log("cannot get prices"); process.exit(200)} |
|||
} |
|||
).catch(()=>{this.prices = {}; console.log("set prices to null");}); |
|||
} |
|||
|
|||
vip(steam64, amount, extra, uniq) { |
|||
axios.post(`${this.url}/api/external/vip?steam=${steam64}&amount=${amount}&service=steam&extra=${extra}&unique=${uniq}`, {}, {headers:{Cookie:`secretkey=${this.secret_key};`}}).then( |
|||
response => { |
|||
if (response.status === 200) { |
|||
if (response.data === 0) { |
|||
console.log(`[S64:${steam64}] VIP as not be added, maybe permition already exists`) |
|||
return 99; |
|||
} else if (response.data > 0) { |
|||
console.log(`[S64:${steam64}] VIP has be added!`); |
|||
return 100; |
|||
} else if (response.data < 0) { |
|||
console.log(`[S64:${steam64}] VIP has be extends!`); |
|||
return 101; |
|||
} |
|||
} else { |
|||
console.log(`[S64:${steam64}] Cannot add VIP`); |
|||
} |
|||
} |
|||
).catch((e)=>{console.log("cannot add vip"); console.log(e)}); |
|||
} |
|||
} |
|||
|
|||
module.exports = BackendIntegration; |
@ -0,0 +1,5 @@ |
|||
services: |
|||
facti13_steambot_js: |
|||
build: ./ |
|||
container_name: facti13_steambot_js |
|||
restart: always |
@ -0,0 +1,11 @@ |
|||
{ |
|||
"name": "Facti13.SteamTradeBot.JS.v1", |
|||
"version": "1.0.0", |
|||
"dependencies": { |
|||
"axios": "^1.6.0", |
|||
"steam-totp": "^2.1.2", |
|||
"steam-tradeoffer-manager": "^2.10.6", |
|||
"steam-user": "^5.0.4", |
|||
"steamcommunity": "^3.47.1" |
|||
} |
|||
} |
@ -0,0 +1,62 @@ |
|||
class TradeChecker { |
|||
APP_ID = 440; |
|||
MONTH = 2678400; |
|||
WEEK = 604800; |
|||
DAY = 86400; |
|||
|
|||
prices_map = {} |
|||
|
|||
constructor() { |
|||
} |
|||
|
|||
setPrices(prices) { |
|||
for (const pos in prices) { |
|||
if (prices[pos]["money_price"] === 0){ |
|||
continue |
|||
} |
|||
this.prices_map[prices[pos]['period']] = parseInt(prices[pos]["item_price"].split()[0]) |
|||
} |
|||
if (this.prices_map.length === 0) { |
|||
console.log("cannot parse prices"); |
|||
} |
|||
} |
|||
|
|||
mannco_key(items) { |
|||
const class_id = 101785959; |
|||
const instance_id = 11040578; |
|||
let count = 0; |
|||
for (const item_id in items) { |
|||
if (items[item_id].appid === this.APP_ID && parseInt(items[item_id].classid) === class_id && parseInt(items[item_id].instanceid) === instance_id) count++; |
|||
} |
|||
return count; |
|||
} |
|||
|
|||
pure_metal(items) { |
|||
const class_id = 2674; |
|||
const instance_id = 11040547; |
|||
let count = 0; |
|||
for (const item_id in items) { |
|||
if (items[item_id].appid === this.APP_ID && parseInt(items[item_id].classid) === class_id && parseInt(items[item_id].instanceid) === instance_id) count++; |
|||
} |
|||
return count; |
|||
} |
|||
|
|||
Items2Seconds(items) { |
|||
const key_count = this.mannco_key(items); |
|||
const metal_count = this.pure_metal(items); |
|||
let final_amount = 0; |
|||
|
|||
if(key_count >= this.prices_map["month"]) |
|||
final_amount += key_count * this.MONTH |
|||
|
|||
if(metal_count >= this.prices_map["week"]) |
|||
final_amount += (metal_count / self.prices_map["week"]) * this.WEEK; |
|||
else if(metal_count >= this.prices_map["day"]) |
|||
final_amount += (metal_count / this.prices_map["day"]) * this.DAY; |
|||
|
|||
return final_amount; |
|||
} |
|||
|
|||
} |
|||
|
|||
module.exports = TradeChecker; |
@ -0,0 +1,131 @@ |
|||
'use strict'; |
|||
////////////////////////////////////////////////////////////////
|
|||
var backend_integration = require("./backend_integration") |
|||
var trade_checker_imp = require("./trade_checker") |
|||
var backend = new backend_integration(); |
|||
var trade_checker = new trade_checker_imp(); |
|||
const VERSION = require("./version"); |
|||
console.log(`Build date: ${VERSION}`); |
|||
|
|||
async function sync(timeout) { |
|||
let sleep = function sleep (howLong) { |
|||
return new Promise(function (resolve) { |
|||
setTimeout(() => {resolve()}, howLong) |
|||
}) |
|||
} |
|||
while (true) { |
|||
try { |
|||
await backend.pulse().then(() => { |
|||
if (backend.up) { |
|||
backend.getPrices(trade_checker); |
|||
} |
|||
}); |
|||
} catch (e) { |
|||
console.log(e); |
|||
} finally { |
|||
if (!backend.up) {console.log(`wait ${timeout} seconds after destroy, where pulse failed`)} |
|||
await sleep(timeout * 1000); |
|||
if (!backend.up) {process.exit(228);} |
|||
} |
|||
} |
|||
} |
|||
sync(60); |
|||
|
|||
/////////////////////////////////////////////////////////////////
|
|||
var SteamUser = require('steam-user'); |
|||
var SteamCommunity = require('steamcommunity'); |
|||
var SteamTradeOfferManager = require('steam-tradeoffer-manager'); |
|||
var SteamTOTP = require('steam-totp'); |
|||
|
|||
/////////////////////////////////////////////////////////////////
|
|||
var client = new SteamUser(); |
|||
var community = new SteamCommunity(); |
|||
var manager = new SteamTradeOfferManager({ |
|||
steam: client, |
|||
language: 'en' |
|||
}); |
|||
console.log('connecting to steam account...'); |
|||
const config = require("./auth_data/auth.json") |
|||
client.logOn({ |
|||
accountName: config.login, |
|||
password: config.password, |
|||
twoFactorCode: SteamTOTP.getAuthCode(config.shared_secret) |
|||
}); |
|||
/////////////////////////////////////////////////////////////////
|
|||
client.on('loggedOn', function(details, parental) { |
|||
console.log('SteamID64 :', client.steamID.getSteamID64()); |
|||
client.setPersona(SteamUser.EPersonaState.Online); |
|||
}); |
|||
|
|||
client.on('webSession', function(sessionID, cookies) { |
|||
manager.setCookies(cookies, function(err) { |
|||
if (err) { |
|||
console.log(err); |
|||
process.exit(1); // Fatal error since we couldn't get our API key
|
|||
return; |
|||
} |
|||
|
|||
console.log("Got API key: " + manager.apiKey); |
|||
}); |
|||
|
|||
community.setCookies(cookies); |
|||
}); |
|||
|
|||
client.on('error', function(error) { |
|||
|
|||
console.log('connection error\n'); |
|||
console.log(error); |
|||
}); |
|||
////////////////////////////////////////////////////////////////////
|
|||
|
|||
function calculate(offer) { |
|||
|
|||
if (offer.state !== SteamTradeOfferManager.ETradeOfferState.Active) { |
|||
console.log(`[${offer.id}] trade have not active stats`) |
|||
return false; |
|||
} |
|||
|
|||
if (offer.itemsToGive.length>0) { |
|||
console.log(`[${offer.id}] partner wanna get bot items, decine trade`); |
|||
return false; |
|||
} |
|||
|
|||
if (offer.itemsToReceive.length>50) { |
|||
console.log(`[${offer.id}] cannot accept trade with more 50 items`) |
|||
return false; |
|||
} |
|||
|
|||
const seconds = trade_checker.Items2Seconds(offer.itemsToReceive); |
|||
if (seconds === 0) { |
|||
console.log(`[${offer.id}] cannot accept trade not valid items`) |
|||
return false; |
|||
} |
|||
|
|||
return seconds > 0; |
|||
} |
|||
|
|||
manager.on('newOffer', function(offer) { |
|||
console.log(`[${offer.id}] Incoming trade from ${offer.partner.getSteamID64()}`); |
|||
if (calculate(offer)) { |
|||
console.log(`[${offer.id}] Try accept trade`); |
|||
offer.accept(false, function(error, status) {}); |
|||
} else { |
|||
console.log(`[${offer.id}] Try decline trade`); |
|||
offer.decline(function(error, status) {}) |
|||
} |
|||
}) |
|||
|
|||
manager.on('receivedOfferChanged', function(offer, oldState) { |
|||
console.log(`[${offer.id}] changed: ${SteamTradeOfferManager.ETradeOfferState[oldState]} -> ${SteamTradeOfferManager.ETradeOfferState[offer.state]}`); |
|||
if (offer.state === SteamTradeOfferManager.ETradeOfferState.Accepted) { |
|||
offer.getExchangeDetails((err, status, tradeInitTime, receivedItems, sentItems) => { |
|||
const seconds = trade_checker.Items2Seconds(receivedItems); |
|||
if (seconds > 0) { |
|||
const extra = `keys=${trade_checker.mannco_key(receivedItems)};metal=${trade_checker.pure_metal(receivedItems)};`; |
|||
backend.vip(offer.partner.getSteamID64(), seconds, extra, offer.id); |
|||
} else { |
|||
console.log(`[${offer.id}] Trade accepted, but vip not gived!`); |
|||
} |
|||
}) |
|||
} |
|||
}); |
@ -0,0 +1 @@ |
|||
const VERSION = 0;module.exports = VERSION; |
Loading…
Reference in new issue