vrtgn
-
Posts
61 -
Joined
Reputation Activity
-
-
vrtgn reacted to Dr. McKay in Do AssetIDs change?
Assuming we're talking about Valve games and games using Steam Inventory Service (which is not all games on Steam), asset IDs change when:
The item is traded The item is modified (e.g. painted in TF2, renamed in TF2/CSGO) The item is attempted to be traded but the trade fails and is rolled back There are probably also a few other weird cases where an asset ID changes because this is Valve we're talking about.
-
-
vrtgn got a reaction from Dr. McKay in Getting the eresult.
No, you should check when you process the offer. It should be among the first things you check in the offer.
You can't act on an offer (e.g. decline the offer) after you've accepted it which you are doing in the above code.
-
-
vrtgn reacted to SnaBe in inviteToGroup
Since you haven't posted any code I'm unsure how you're using the method. So I'll show you how I usually do it.
Let's say you want to invite the user as soon as they become friends with yout bot, you can do it as follows:
client.on('friendRelationship', (steamID, relationship) => { switch(relationship) { //The bot received a friend request from another Steam user case 2: console.log(`Bot ${client.steamID.getSteamID64()} received a friend request from user ${steamID}.`); client.addFriend(steamID, (err) => { if(err) { console.log(`Error adding user ${steamID}.`); } else { client.getPersonas([steamID], (err, personas) => { var persona = personas[steamID.getSteamID64()]; var name = persona ? persona.player_name : ("[" + steamID.getSteamID64() + "]"); client.chatMessage(steamID, `Greetings ${name}! ${config.steam.messages.new_friend}`); }); console.log(`Bot ${client.steamID.getSteamID64()} accepted user ${steamID}'s friend request.`); } }); break; //The bot is now friends with another Steam user case 3: //Invite that user to our Steam group client.inviteToGroup(steamID, config.steam.groupID); console.log(`Bot ${client.steamID.getSteamID64()} invited user ${steamID} to our Steam group.`); break; default: break; } }); The inviteToGroup methods takes two arguments, the SteamID of the user you wish to invite and the groupID for the group.
The SteamID is retrieved from the friendRelationship event. You'll have to store your Steam group ID in a variable or in a separate file. I store mine in a JSON config file.
If you don't have the groupID you can find it by replacing <GroupName> in this url https://steamcommunity.com/groups/<GroupName>/memberslistxml/?xml=1 with the name of your Steam group. Then you'll be able to extract the groupID from the XML file in your browser.
I hope this helps!
-
vrtgn reacted to sergun in Is there any risk of ban for using this package?
There are bots which send 1k+ trades every day, it's not bannable.
Feel free to do so, just make sure you are not abusing it.
-
vrtgn got a reaction from CUTONI8 in Error: ETIMEDOUT and reload cookies
You're not meant to use the method I gave in conjunction with the confirmation checker.
The confirmation checker (in simple terms) works by telling Steam every X seconds: "Hey, I wanna confirm everything waiting to be confirmed". It will tell steam even if there is nothing waiting to be confirmed thus the load it puts on servers - imagine loads of bots doing this.
Whereas the method I put tells steams servers: "Hey, I wanna confirm this specific trade". Therefore, it only tells steam when there is something to be confirmed.
-
vrtgn reacted to xLeeJYx in Im having some trouble when trying to make my steam bot because i have the node module downloaded but it keeps giving me this error
@2can
your newOffer event should be
processOffer(offer) Its better off you coding it yourself since you can learn your mistake and improve. Not by copying blindly from others and not knowing what is it doing
-
vrtgn reacted to Heateen in Im having some trouble when trying to make my steam bot because i have the node module downloaded but it keeps giving me this error
The user deleted this message on request!
-
vrtgn reacted to Heateen in Im having some trouble when trying to make my steam bot because i have the node module downloaded but it keeps giving me this error
The user deleted this message on request!
-
vrtgn reacted to Emily in Im having some trouble when trying to make my steam bot because i have the node module downloaded but it keeps giving me this error
No.
var ourItems = offer.itemsToGive; -
vrtgn got a reaction from PonyExpress in EYldRefreshAppIfNecessary failed with EResult 55
These are both different endpoints, the deprecated loadUserInventory is giving you a response because it is not used as much due to it being unstable.
-
vrtgn reacted to Dr. McKay in EYldRefreshAppIfNecessary failed with EResult 55
55 = RemoteCallFailed
That error means that the Steam Community backend wasn't able to get the inventory from the GC (item server), likely because the GC is overloaded (status is probably "critical" at steamstat.us).
-
vrtgn reacted to Dr. McKay in Function doesn't return inventory
Thanks so much for the help @vrtgn.
It may be worth noting that if you're using async, you don't need to use .catch((err) => . . .). You can use try/catch:
try { const inventory = await getInventory(); // do whatever } catch (err) { console.error(err); }
-
vrtgn got a reaction from Dr. McKay in Function doesn't return inventory
I also made this mistake as a beginner.
You have a misunderstanding of asynchronous code in javascript. Fetching the inventory takes some time, and so by returning inventory, the variable is being returned before the program can even fetch your inventory.
You will have to create your own callback and that works by taking in a function as a callback parameter, and then executing that function once the inventory has been fetched.
const getInventory = (callback) => { manager.loadInventory(730, 2, true, (err, inventory) => { if (err) { callback(err); } else { callback(null, inventory); } }) } I personally prefer to check for errors first, but whatever you prefer you can change it to.
When we want to fetch the inventory we use it like so:
getInventory((err, inventory) => { if (err) { console.log('error getting the inventory :('); } else { // code to do whatever you want with inventory here } })
I also saw that you are using the loadInventory method, it would be much better if you used the getInventoryContents method as it says this in the docs:
EDIT: Callbacks are getting ugly nowadays imo so you can also use a promise if you prefer:
const getInventory = () => { return new Promise((resolve, reject) => { manager.loadInventory(730, 2, true, (err, inventory) => { if (err) { reject(err); } else { resolve(inventory); } }); }); } getInventory() .then(inventory => { // do whatever here }) .catch(err => console.log('oops')); // OR // this must be inside a async function try { const inventory = await getInventory(); // do whatever here } catch (err) { console.error(err) }
-
vrtgn reacted to What Comes Around in Function doesn't return inventory
Yes I was mistaken, my bad. Thanks again! Your code is very clean, would have taken me a while to get all the mess I had perfected.
-
vrtgn reacted to What Comes Around in Function doesn't return inventory
This makes perfect sense! I tried using a callback and it worked, but I didn't like the mess I created so I made the code in my original question. Your solution is clean and makes sense. Also I will use getInventoryContents. Thanks a bunch!
Oh but one question. getInventoryContents has a steamid param, so I'd assume you can fetch other users inventories, but there is a getUserInventoryContents function for that. What's the difference?
-
vrtgn got a reaction from What Comes Around in Function doesn't return inventory
I also made this mistake as a beginner.
You have a misunderstanding of asynchronous code in javascript. Fetching the inventory takes some time, and so by returning inventory, the variable is being returned before the program can even fetch your inventory.
You will have to create your own callback and that works by taking in a function as a callback parameter, and then executing that function once the inventory has been fetched.
const getInventory = (callback) => { manager.loadInventory(730, 2, true, (err, inventory) => { if (err) { callback(err); } else { callback(null, inventory); } }) } I personally prefer to check for errors first, but whatever you prefer you can change it to.
When we want to fetch the inventory we use it like so:
getInventory((err, inventory) => { if (err) { console.log('error getting the inventory :('); } else { // code to do whatever you want with inventory here } })
I also saw that you are using the loadInventory method, it would be much better if you used the getInventoryContents method as it says this in the docs:
EDIT: Callbacks are getting ugly nowadays imo so you can also use a promise if you prefer:
const getInventory = () => { return new Promise((resolve, reject) => { manager.loadInventory(730, 2, true, (err, inventory) => { if (err) { reject(err); } else { resolve(inventory); } }); }); } getInventory() .then(inventory => { // do whatever here }) .catch(err => console.log('oops')); // OR // this must be inside a async function try { const inventory = await getInventory(); // do whatever here } catch (err) { console.error(err) }
-
vrtgn reacted to IdiNium in How to properly use getUserDetails function
Hey @vrtgn!
I think I've solve this. Since getAvatarUrl is not working properly (maybe due to my mistake or idk why), so I decided to get avatarHash instead, and it turned out to be working fine after about 20 times of accepted trades.
Here's my coding:
Myhandler.ts (only the part that I'm working on):
private sendWebHookReviewOfferSummary(offer: TradeOfferManager.TradeOffer, reason: string): void { const request = new XMLHttpRequest(); request.open('POST', process.env.DISCORD_WEBHOOK_REVIEW_OFFER_URL); request.setRequestHeader('Content-type', 'application/json'); const partnerSteamID = offer.partner.toString(); const tradeSummary = offer.summarize(this.bot.schema); let partnerAvatar; let partnerName; log.debug('getting partner Avatar and Name...'); offer.getUserDetails(function(err, me, them) { if (err) { log.debug('Error retrieving partner Avatar and Name: ', err); partnerAvatar = 'https://p7.hiclipart.com/preview/313/980/1020/question-mark-icon-question-mark-png.jpg'; partnerName = 'unknown'; } else { log.debug('partner Avatar and Name retrieved. Applying...'); partnerAvatar = them.avatarFull; log.debug(partnerAvatar); partnerName = them.personaName; log.debug(partnerName); } const stringified = JSON.stringify(discordReviewOfferSummary) .replace(/%partnerId%/g, partnerSteamID) .replace(/%partnerName%/g, partnerName) .replace(/%partnerAvatar%/g, partnerAvatar) .replace(/%offerId%/g, offer.id) .replace(/%reason%/g, reason) .replace(/%tradeSummary%/g, tradeSummary.replace('Offered:', '\\n Offered:')) .replace(/%ownerDiscordId%/g, process.env.OWNER_DISCORD_ID) .replace(/%currentTime%/g, moment().format('MMMM Do YYYY, HH:mm:ss') + ' UTC'); const jsonObject = JSON.parse(stringified); request.send(JSON.stringify(jsonObject)); log.debug('Review offer summary sent to webhook'); }); } private sendWebHookTradeSummary(offer: TradeOfferManager.TradeOffer): void { const request = new XMLHttpRequest(); request.open('POST', process.env.DISCORD_WEBHOOK_TRADE_SUMMARY_URL); request.setRequestHeader('Content-type', 'application/json'); const partnerSteamID = offer.partner.toString(); const tradeSummary = offer.summarize(this.bot.schema); let tradesTotal = 0; const offerData = this.bot.manager.pollData.offerData; for (const offerID in offerData) { if (!Object.prototype.hasOwnProperty.call(offerData, offerID)) { continue; } if (offerData[offerID].handledByUs === true && offerData[offerID].isAccepted === true) { // Sucessful trades handled by the bot tradesTotal++; } } const tradesMade = process.env.TRADES_MADE_STARTER_VALUE ? +process.env.TRADES_MADE_STARTER_VALUE + tradesTotal : 0 + tradesTotal; let personaName; let avatarFull; let avatarFullPrint; log.debug('getting partner Avatar and Name...'); this.getPartnerDetails(offer, function(err, details) { if (err) { log.debug('Error retrieving partner Avatar and Name: ', err); personaName = 'unknown'; avatarFullPrint = 'https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/72/72f78b4c8cc1f62323f8a33f6d53e27db57c2252_full.jpg'; //default "?" image } else { log.debug('partner Avatar and Name retrieved. Applying...'); personaName = details.personaName; log.debug(personaName); avatarFull = details.avatarFull ? details.avatarFull : '72f78b4c8cc1f62323f8a33f6d53e27db57c2252'; //if something wrong, it'll use the default "?"" image log.debug(avatarFull); avatarFullPrint = 'https://steamcdn-a.akamaihd.net/steamcommunity/public/images/avatars/' + avatarFull.substring(0, 2) + '/' + avatarFull + '_full.jpg'; log.debug(avatarFullPrint); } const stringified = JSON.stringify(discordTradeSummary) .replace(/%partnerId%/g, partnerSteamID) .replace(/%partnerName%/g, personaName) .replace(/%partnerAvatar%/g, avatarFullPrint) .replace(/%offerId%/g, offer.id) .replace(/%tradeNum%/g, tradesMade.toString()) .replace(/%tradeSummary%/g, tradeSummary.replace('Offered:', '\\n Offered:')) .replace(/%currentTime%/g, moment().format('MMMM Do YYYY, HH:mm:ss') + ' UTC'); const jsonObject = JSON.parse(stringified); request.send(JSON.stringify(jsonObject)); log.debug('Accepted trade summmary sent to webhook'); }); } private getPartnerDetails(offer: TradeOfferManager.TradeOffer, callback: (err: any, details: any) => void): any { // check state of the offer if (offer.state === TradeOfferManager.ETradeOfferState.active) { offer.getUserDetails(function(err, me, them) { if (err) { callback(err, {}); } else { callback(null, them); } }); } else { this.bot.community.getSteamUser(offer.partner, (err, user) => { if (err) { callback(err, {}); } else { callback(null, { personaName: user.name, avatarFull: user.avatarHash }); } }); } } And here's the steamcommunity module (index.d.ts):
⁝ getSteamUser(id: SteamID | string, callback: (err?: Error, user?: SteamCommunity.User) => void): void; acceptConfirmationForObject(identitySecret: string, objectID: string, callback: (err?: Error) => void): void; } namespace SteamCommunity { interface Group { steamID: SteamID; name: string; url: string; headline: string; summary: string; avatarHash: Buffer; members: number; membersInChat: number; membersInGame: number; membersOnline: number; join: (callback?: (err?: Error) => void) => void; } interface User { steamID: SteamID; name: string; onlineState: string; stateMessage: string; privacyState: string; visibilityState: string; avatarHash: string; vacBanned: string; tradeBanState: string; isLimitedAccount: string; customURL: string; groups: null; primaryGroup: null; } } export = SteamCommunity; } I think I'll stick on this solution for now.
If you have any other alternative or maybe make it look nicer, I'd like to know it!
Thank you very much
-
vrtgn got a reaction from Dr. McKay in How to properly use getUserDetails function
You can make the function a private and place it in the body of the MyHandler, but you will have to call it by prefixing "this." before the function.
this.getPartnerDetails(...) As for the "this" error you can change the parameters of the getPartnerDetails to:
function getPartnerDetails(this: any, offer: TradeOfferManager.TradeOffer, callback: (err: any, details: any) => void): any {
-
vrtgn reacted to Dr. McKay in Change user description
You can use node-steamcommunity for that: https://github.com/DoctorMcKay/node-steamcommunity/wiki/SteamCommunity#editprofilesettings-callback
-
vrtgn reacted to Dr. McKay in Userscript for steam-twofactor-server not working anymore
You're correct. I'll update that now.
-
vrtgn reacted to Gergely Szabo in Interacting with CS:GO Storage Units programmatically
That is great to hear, thanks for your work!
-
vrtgn reacted to Dr. McKay in Unable to get polling to work
The CM sends a notification message to the Steam client (which steam-user can receive), but that message only contains the count of pending trade offers. To get any details at all about the actual content of the trade, we need to hit the API for that.