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