sergey.peshkov Posted December 11, 2016 Report Posted December 11, 2016 I'm writing a SteamBot to send offers to different accounts and to automatically confirm these offers after this. But I'm getting 'Error: Could not act on confirmation' when trying to respond to every confirmation. Can you suggest what am I doing wrong? Here is how I'm using steamcommunity (I'm using babel to transpile all of this into ES5): class SteamBot { // this class has a login function, which logs bot in, // and also some fields like 'shared' and 'identity' // this.community is a SteamCommunity object confirmAll() { return new Promise((res, rej) => { const time = Math.floor(Date.now() / 1000) const key = SteamTotp.getConfirmationKey(this.identity, time, 'conf') this.community.getConfirmations(time, key, async (err, confirmations) => { if (err) return rej(err) log(confirmations.map(JSON.stringify).join(', ')) // just for debugging for (let confirmation of confirmations) { try { const confirmRes = await this.confirmConfirmation(confirmation) log(`Confirmed ${confirmation.creator}`, true, true) } catch (e) { log(`Confirmation failed: ${e}`, true, true) return rej(e) } } return res(confirmations) }); }) } confirmConfirmation(confirmation) { return new Promise((res, rej) => { const time = Math.floor(Date.now() / 1000) const key = SteamTotp.getConfirmationKey(this.identity, time, 'allow') console.log(this.identity) // for debugging purposes console.log(confirmation) // also for this confirmation.respond(time, key, true, (err) => { if (err) return rej(err) return res() }) }) } constructor(login, password, shared, identity) { this.login = login this.password = password this.shared = shared this.identity = identity this.loginBot() // logging in, not necessary for now, since it's working okay } } var bot = new SteamBot(login, password, shared, identity) // and after logging in and sending tradeoffer, I'm trying to do this: bot.confirmAll()I've tried to send offer to my other account and to confirm it immediately, and after that call bot.confirmAll(). It shows that I have confirmations, but when I try to respond to them, it shows an error: 'Could not act on confirmation'. I'm pretty sure that I'm using the right identity_secret (since I've used it with startConfirmationChecker() and everything worked fine, also I console.log()'ed it inside a function just to make sure it's the right one and yes, it's the right one). I'm not sure what I did wrong, I've seen an example that worked pretty much the same (well, without Promises and ES6 stuff, but still), so if you know what could I do wrong, can you suggest me? Thanks in advance. Quote
Dr. McKay Posted December 11, 2016 Report Posted December 11, 2016 I believe your problem is stemming from the fact that you're trying to confirm all your pending confirmations at once. A key can only be used once, so if you try to confirm multiple confirmations in the same second, you'll generate the same key so it won't work. Quote
sergey.peshkov Posted December 11, 2016 Author Report Posted December 11, 2016 I've tried this when there was only one confirmation, it also didn't work and the error was the same so I don't think that's why it's not working. I'll still try to check it once more, just to make sure. Anyway, if this is indeed the cause of the problem, how can I avoid this? I know that I can do something like confirmations[0].respond(...), but is there a way to confirm all confirmation at once? Quote
Dr. McKay Posted December 12, 2016 Report Posted December 12, 2016 You can use this to accept all outstanding confirmations at once, but the entire request will fail if any one confirmation fails to be confirmed. EthanBOT 1 Quote
sergey.peshkov Posted December 12, 2016 Author Report Posted December 12, 2016 I've tried to rewrite confirmAll() this way: confirmAll() { return new Promise((res, rej) => { const time = Math.floor(Date.now() / 1000) const confKey = SteamTotp.getConfirmationKey(this.identity, time, 'conf') const allowKey = SteamTotp.getConfirmationKey(this.identity, time, 'allow') this.community.acceptAllConfirmations(time, confKey, allowKey, (err, confirmations) => { if (err) return rej(err) return res(confirmations) }) }) }And it still shows 'Error: Could not act on confirmation' What can cause this? I think it's not time-related issue (I tried to set the wrong time for this function, the error was different). Also I'm pretty sure it's not the wrong identity (since I've used the same identity with startConfirmationChecker() and it worked okay). Here is my error stacktrace, in case it will help: December 12th 2016 23:34:27.465 confirm error Error: Could not act on confirmation at /all/Documents/Programming/bot/node_modules/steamcommunity/components/confirmations.js:145:12 at SteamCommunity.<anonymous> (/all/Documents/Programming/bot/node_modules/steamcommunity/components/confirmations.js:256:3) at Request._callback (/all/Documents/Programming/bot/node_modules/steamcommunity/components/http.js:68:15) at Request.self.callback (/all/Documents/Programming/bot/node_modules/steamcommunity/node_modules/request/request.js:186:22) at emitTwo (events.js:106:13) at Request.emit (events.js:191:7) at Request.<anonymous> (/all/Documents/Programming/bot/node_modules/steamcommunity/node_modules/request/request.js:1060:10) at emitOne (events.js:96:13) at Request.emit (events.js:188:7) at IncomingMessage.<anonymous> (/all/Documents/Programming/bot/node_modules/steamcommunity/node_modules/request/request.js:980:12) Quote
Dr. McKay Posted December 12, 2016 Report Posted December 12, 2016 Are you definitely logged in? Quote
sergey.peshkov Posted December 13, 2016 Author Report Posted December 13, 2016 I suppose if I can send a tradeoffer (with status pending) then I'm logged in.Also I have some log statements for login errors and I have nothing related to login errors in my console. Here is a complete .js file I'm using for managing bot, if it will help. import SteamUser from 'steam-user' import SteamTotp from 'steam-totp' import TradeOfferManager from 'steam-tradeoffer-manager' import SteamCommunity from 'steamcommunity' import { log, sleep } from './utils' function getRandomInt(min, max) { return Math.floor(Math.random() * ((max - min) + 1)) + min } class SteamBot { loginBot() { log(`[bot] Logging in, login [${this.login}] \ password [${this.password}] shared [${this.shared}] \ identity [${this.identity}]`) this.status = { name: this.login, loggedIn: false, gotApiKey: false, error: null } this.client = new SteamUser() this.client.setOption('promptSteamGuardCode', false) this.community = new SteamCommunity() const authCode = SteamTotp.getAuthCode(this.shared) const logOnOptions = { accountName: this.login, password: this.password, twoFactorCode: authCode, } this.client.on('loggedOn', () => { this.status.loggedIn = true log(`[bot] Logged into Steam as ${this.client.steamID.getSteam3RenderedID()}`) this.client.setPersona(SteamUser.EPersonaState.Online) }) this.client.on('steamGuard', (domain, callback) => { log('[bot] Requiring Steam Guard, waiting 30 sec...', true, true) setTimeout(() => { const code = SteamTotp.getAuthCode(this.shared) callback(code) }, 30000) // 30 sec sleeping }) this.client.on('error', error => this.onBotLoginError(error)) this.manager = new TradeOfferManager({ steam: this.client, community: this.community, domain: "localhost", language: 'en', pollInterval: 5000 }) this.client.on('webSession', (sessionID, cookies) => this.onBotWebSession(sessionID, cookies)) this.client.logOn(logOnOptions) } onBotWebSession(sessionID, cookies) { this.manager.setCookies(cookies, err => this.onManagerSetCookies(err)) this.community.setCookies(cookies) this.community.startConfirmationChecker(10000, this.identity); } onManagerSendOfferChanged(offer, old) { log(`[bot] Offer #${offer.id} status: ${TradeOfferManager.ETradeOfferState[offer.state]}`, true, true) } makeOffer(id, itemsToGive, itemsToReceive, token) { return new Promise((res, rej) => { const offer = this.manager.createOffer(id) offer.itemsToGive = itemsToGive.map(i => ({ appid: 730, contextid: 2, amount: 1, assetid: i })) offer.itemsToReceive = itemsToReceive.map(i => ({ appid: 730, contextid: 2, amount: 1, assetid: i })) offer.setToken(token) offer.send((err, status) => { if (err) return rej(err) this.community.checkConfirmations() res(`Sent offer ${offer.id}, status: ${status}`) }) }) } onManagerSetCookies(err) { if (err) { this.status.error = err.message log(`[bot] Error getting API key: ${err.message}`) if (err.message === 'HTTP error 429') { // too many requests const interval = getRandomInt(60, 300) log(`[bot] Too many requests, relogin in ${interval} seconds`, true, true) this.client.logOff() setTimeout(() => { this.loginBot() }, interval * 1000) // 60-300 sec sleeping } else log(`[bot] Unrecoverable error, not retrying. Error: ${err.message}`, true) return } this.status.gotApiKey = true log(`[bot] Got API key: ${this.manager.apiKey}`) this.manager.on('newOffer', (offer, old) => this.onManagerNewOffer(offer, old)) this.manager.on('sentOfferChanged', (offer, old) => this.onManagerSendOfferChanged(offer, old)) this.community.on('newConfirmation', (confirmation) => this.onCommunityNewConfirmation(confirmation)); this.community.on('confirmationAccepted', (confirmation) => this.onCommunityConfirmationAccepted(confirmation)); this.community.on('confKeyNeeded', (tag, callback) => { const time = Math.floor(Date.now() / 1000) log(`Conf Key Needed ${JSON.stringify(tag)}`, true, true) callback(null, time, SteamTotp.generateAuthCode(this.identity, time, tag)) }) } onCommunityNewConfirmation(confirmation) { log(`Confirmation needed: ${JSON.stringify(confirmation)}`, true, true) } onCommunityConfirmationAccepted(confirmation) { log(`Confirmation accepted: ${JSON.stringify(confirmation)}`, true, true) } confirmAll() { return new Promise((res, rej) => { const time = Math.floor(Date.now() / 1000) const confKey = SteamTotp.getConfirmationKey(this.identity + 'aaa', time, 'conf') const allowKey = SteamTotp.getConfirmationKey(this.identity + 'aaa', time, 'allow') this.community.acceptAllConfirmations(time, confKey, allowKey, (err, confirmations) => { if (err) return rej(err) return res(confirmations) }) }) } onManagerNewOffer(offer) { const steamId = offer.partner.getSteamID64() log(`[bot] New offer #${offer.id}: ${TradeOfferManager.ETradeOfferState[offer.state]} from ${steamId}`, true, true) offer.accept(err => { if (err) { log(`[bot] Offer ${offer.id} error: ${err}`, true, true) } else { log(`[bot] Offer from ${steamId} accepted: ${offer.id}`, true, true); } }) } onBotLoginError(error) { this.status.loggedIn = false this.status.error = error.message const interval = getRandomInt(5, 15) log(`[bot] Error logging in: ${error.message}, sleeping for ${interval} min...`, true, true) setTimeout(() => { this.loginBot() }, interval * 1000 * 60) // 5-15 min sleeping } constructor(login, password, shared, identity) { this.login = login this.password = password this.shared = shared this.identity = identity this.loginBot() } } export default SteamBot Quote
Dr. McKay Posted December 13, 2016 Report Posted December 13, 2016 It's possible it was only a temporary Steam issue. Has this been happening repeatedly for a long time? Quote
sergey.peshkov Posted December 14, 2016 Author Report Posted December 14, 2016 Yep, most of the times it returns this error. Sometimes it works okay and confirms everything, but most of the times it just displays an error. Quote
Dr. McKay Posted December 14, 2016 Report Posted December 14, 2016 Make sure you aren't trying to double-confirm things, I suppose. When accepting a confirmation fails, all Steam returns is {"success":false} which is what triggers this error. Unfortunately, there's no more detail. Quote
sergey.peshkov Posted December 15, 2016 Author Report Posted December 15, 2016 Can this somehow interfere with startConfirmationChecker? I think it's the only way how I can double-confirm. Quote
sergey.peshkov Posted December 16, 2016 Author Report Posted December 16, 2016 Is there any way to avoid this (in case it indeed interferes with startConfirmationChecker)? I tried just comment out the startConfirmationChecker line, but without it it just doesn't work. Quote
Dr. McKay Posted December 16, 2016 Report Posted December 16, 2016 It should definitely work without the confirmation checker running. Quote
sergey.peshkov Posted December 18, 2016 Author Report Posted December 18, 2016 I forgot that I was calling checkConfirmations() after sending offer, that's why everything crashed. I disabled it and now it's working without startConfirmationChecker, seems like they were indeed interfering. Thanks a lot! Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.