Jump to content
McKay Development

Dr. McKay

Administrator
  • Posts

    3389
  • Joined

  • Last visited

Reputation Activity

  1. Like
    Dr. McKay got a reaction from k1ne in Error : "Cannot log onto steamcommunity.com without first being connected to Steam network"   
    You're probably not checking whether your client is still connected to Steam. In that case, whenever Steam goes down (or you otherwise lose connection), your web session will expire, triggering sessionExpired, which will make your code call webLogOn, which will fail with the given error because your client is no longer connected.
    You should check whether client.steamID is not null to make sure you're still connected.
  2. Like
    Dr. McKay got a reaction from stpnb in Question about pollInterval and node-steam-user   
    No, timed polling remains enabled (unless you disable it manually). Passing a SteamUser just triggers polls more quickly after specific actions happen.
  3. Like
    Dr. McKay got a reaction from Robert Lutece in Identifying Steam Items   
    Sometimes it can be a little confusing to identify a specific item in the Steam economy. There are several different types of IDs present in one particular item, and a lot of vague terminology. This guide aims to clear all that up for you.

    For starters, the "official" term for a Steam item is an asset. When I say a "Steam item", I mean a particular copy of an item. I'm not referring to the item's definition, name, image, or anything. I'm referring to a specific, unique copy of the item.

    In a general sense, every item on Steam must be owned by an app. An "app" is a game, software, or whatever on Steam. Every app has its own unique AppID. You can find a particular game's AppID by going to its store page or community hub and looking at the URL. For example, TF2's AppID is 440 so TF2's store page can be found at http://store.steampowered.com/app/440. CS:GO's is 730, Dota 2's is 570, and so on. Note that Steam Community items, Steam gifts, and other "Steam" items are owned by the "Steam" app, which has AppID 753. To identify an item, you'll need the AppID of the game which owns it.

    Of course, the AppID alone isn't enough. You also need two other IDs. Have you ever noticed how some games have multiple inventories, which appear in a drop-down list? An example is the Steam inventory, which has sub-inventories for "Community", "Gifts", "Coupons", etc. These "sub-inventories" are called contexts, and each context has its own context ID. If a game doesn't have a drop-down menu to select a context, that doesn't mean that it's without contexts. That only means that it has one single visible context. That single context still has an ID. For all current Valve games, the context ID for the publicly-visible context is 2.

    Context IDs can be a bit tricky. It's entirely up to the game's developer to determine how they work. For example, Valve games take the "single shared inventory" model in which there's one context ID which is shared by everyone. Under this model, an item belongs to one particular context and never leaves that context. Consequently, the item's context ID never changes. It is, however, possible for game developers to create contexts in any way they choose. For example, Spiral Knights uses the "per-character inventory" model in which everyone who plays the game has their own context IDs for their characters. Creating a new character creates a new context ID. This means that when an item is traded between users, its context ID will change as it moved out of a particular character's inventory.

    Those are the two different types of "containers" in the Steam economy. Apps own contexts, and contexts own assets. Every asset on Steam has, in addition to its AppID and context ID, an asset ID which is guaranteed to be unique inside of a given AppID+ContextID combination. Notice that this means that asset IDs are not unique across all of Steam. They aren't even unique across a particular app. They are only unique inside of a given context. For example, there could be two items with asset ID 1 in the same game, as long as they have different context IDs. An item's asset ID may be referred to as "assetid" or just plain "id".

    Context IDs and asset IDs are assigned by the game developer and can follow any pattern. They can change when traded or not. They may both be up to 64 bits in size. Consequently, Steam returns them (like all other 64-bit values) in JSON as strings.

    Still following? All of what we've learned so far leads us to this conclusion: in order to uniquely identify an item, you need its AppID, its context ID, and its asset ID. Once you have these three things, only then can you uniquely identify it. In fact, this is how you link to a particular item in a user's inventory: steamcommunity.com/profiles/steamid/inventory#appid_contextid_assetid. Here's an example: https://steamcommunity.com/id/DoctorMcKay/inventory#440_2_134161610

    What are these "classid" and "instanceid" values though?
    The observant reader may have noticed that there are two more IDs attached to a particular item which I haven't mentioned. These are the "classid" and "instanceid". These IDs are used to map an asset to its description.

    What's a description? A description is what you need in order to actually display an item. An item's description contains its name, image, color, market_name, whether it's tradable or not, whether it's marketable or not, and more. There are many endpoints on Steam which return JSON objects representing assets that only contain the asset's AppID, context ID, asset ID, classid, instanceid, and amount. An item's amount is how big of a stack it is. Unstackable items always have an amount of 1. Stackable items (such as Steam gems) may have a larger amount. Stacked items always have the same asset ID.

    What's the difference between a classid and an instanceid? In a nutshell, a classid "owns" an instanceid. The classid is all you need to get a general overview of an item. For example, items with the same classid will pretty much always have the same name and image. The instanceid allows you to get finer details such as how many kills are on a strange/StatTrak weapon, or custom names/descriptions.

    You can turn a classid/instanceid pair into a description using the GetAssetClassInfo WebAPI method. Notice that the instanceid is actually optional: if you only have a classid that's fine, you just won't get finer details for the item.

    Name? Market Name? Market Hash Name?
    Every asset on Steam has a name. Without a name, there's nothing to show in your inventory. The item's name is the name property of its description. The item's name may be localized if the game's developer has set it up to be.

    Every marketable item also has a "market name". This name may be the same as—or different from—the item's regular name. The item's market name is the market_name property of its description. This is the name that's displayed in the Steam Community Market when the item is up for sale. Why the distinction? There are some items which have value-affecting data that isn't in their name; for example, CS:GO skins have 5 different tiers of "wear", which isn't in their names. The wear tier is appended to each skin's market name however, so that the different tiers of wear are separated in the market. The market name may be localized or not, and may not exist at all if the item isn't marketable. It's up to the game's developer.

    Finally, every marketable item also has a "market hash name", available under the market_hash_name property. This name is supposed to be the English version of the item's market name, but in practice it may vary. For example, Steam Community items prepend the AppID of the originating app to each item's market hash name, but not to the market name. The market hash name is never localized, and may not exist if the item isn't marketable. Again, it's up to the game's developer. You can view the Community Market listings for any marketable item using this URL formula: steamcommunity.com/market/listings/appid/market_hash_name. Here's an example: https://steamcommunity.com/market/listings/440/Mann%20Co.%20Supply%20Crate%20Key

    Note that the Community Market has no concept of contexts. Consequently, market [hash] names are unique for a particular "class" of items per-app (and by extension per-context). This means that for marketable items, two items with identical market hash names will be worth roughly the same (with some exceptions, like unusual TF2 items).

    Questions?
    Ask below. I'm happy to help!
  4. Like
    Dr. McKay got a reaction from Vizzy in HTTP 404 on offer.cancel   
    Valve removed the API call to cancel and decline offers. This is fixed in 2.10.5.
  5. Like
    Dr. McKay got a reaction from Akaz in Cookies die every time ASF do RefreshSession()   
    No, you can't run the same account under multiple processes without bad things like that happening.
    You can use steamstore to get your wallet balance: https://github.com/DoctorMcKay/node-steamstore#getwalletbalancecallback
  6. Like
    Dr. McKay reacted to xeugenx in getManifest randomly failing   
    Thanks for the fast help, works with your fix 🙂
  7. Thanks
    Dr. McKay got a reaction from lupucl in Steamguard input   
    I'm assuming you're running multiple instances, so here's a way to keep track of them:
    let accounts = {}; function loginAccount(accountName, password, twoFactorCode) { if (accounts[accountName]) { throw new Error(`Account ${accountName} is already created`); } let user = new SteamUser(); accounts[accountName] = user; user.logOn({ accountName, password, twoFactorCode }); } function logoutAccount(accountName) { if (!accounts[accountName]) { throw new Error(`No SteamUser for ${accountName}`); } accounts[accountName].logOff(); accounts[accountName] = null; }  
  8. Like
    Dr. McKay got a reaction from BreadEater in Steam Community tokens seemed to be linked to IP address   
    I'm not aware of any way to share cookies between multiple IPs.
  9. Thanks
    Dr. McKay got a reaction from daeragon in Error send message to group   
    https://github.com/DoctorMcKay/node-steam-user/wiki/SteamChatRoomClient#getclanchatgroupinfoclansteamid-callback
  10. Like
    Dr. McKay got a reaction from timetoshine in Trying to Use oAuthLogin   
    Yeah, that should work for you. If you're logging in with an account name and password to an account that has mobile 2FA enabled, you need to provide a code every time even if you pass the steamguard string.
  11. Like
    Dr. McKay got a reaction from iNilo in in CSGO when you click on a friend whilst they are ingame you can request to watch the match, is this something node-globaloffensive can achieve too?   
    Watching a match involves connecting to GOTV likely using Steam's datagram relay. Honestly, that's a lot of complexity that's probably not really worth reverse-engineering. I've yet to look into retrieving demos of previous matches, which is likely much easier.
  12. Like
    Dr. McKay reacted to Epic in Webpack can't find module './clientmetrics.json' - dynamically requiring file (w/ possible fix)   
    It's working great now - no issues! 
    Thanks for the change, really appreciate it
  13. Like
    Dr. McKay got a reaction from Epic in Webpack can't find module './clientmetrics.json' - dynamically requiring file (w/ possible fix)   
    I don't see a problem with that change.
    https://github.com/DoctorMcKay/node-steam-user/releases/tag/v4.23.0
  14. Thanks
    Dr. McKay got a reaction from vanitasboi in Filter Function in getOwnedApps etc   
    I forgot about updating docs for this; I'll get that updated today.
    The filter function is the same as Array.prototype.filter, with the object passed to each invocation being of this format.
  15. Like
    Dr. McKay got a reaction from SENPAY98K in GetPlayerBan   
    let friendsList = [array of steamids]; let chunks = []; for (let i = 0; i < friendsList.length; i += 100) { chunks.push(friendsList.slice(i, i + 100)); } let chunkResults = await Promise.all(chunks.map(ck => new Promise((resolve, reject) => { try { let result = await axios.get(`https://api.steampowered.com/ISteamUser/GetPlayerBans/v1/?key=&steamids=${ck.join(',')}`); if (result && result.data && result.data.players) { return resolve(result.data.players); } reject(new Error('Malformed API response')); } catch (ex) { reject(ex); } }))); let vacFriends = []; chunkResults.forEach((chunkPlayers) => { chunkPlayers.filter(player => player.VACBanned).forEach((bannedPlayer) => { vacFriends.push(bannedPlayer); }); }); Untested and might have bugs
  16. Like
    Dr. McKay reacted to Profour in Create a ChatRoomGroup   
    Wow, thanks so much for the quick turn around! I'm gonna start using it right away.
     
    Thanks again so much for your amazing support.
     
  17. Thanks
    Dr. McKay got a reaction from Profour in Create a ChatRoomGroup   
    That functionality was indeed not implemented. I've gone ahead and added it for you in v4.21.0.
    Multi-user ad-hoc group chats are just a special kind of chat room group that is unnamed.
  18. Thanks
    Dr. McKay got a reaction from Deeerby in Accept offer by offer ID   
    That sort of error is caused by Steam unreliability. Just retry and hopefully it should work.
  19. Like
    Dr. McKay got a reaction from Deeerby in Accept offer by offer ID   
    This is how you would encapsulate it:
    const offerObject = await new Promise((resolve, reject) => tradeHandler.manager.getOffer(depositResponse.offerId, (err, offer) => { if (err) { return reject(err); } resolve(offer); });  
  20. Thanks
    Dr. McKay got a reaction from Deeerby in Accept offer by offer ID   
    Accepting a specific offer by ID without retrieving its data first isn't a supported use-case for TradeOfferManager, since it's designed to make the process as simple as possible and performs various checks and such. You'd need to either fetch the offer first using getOffer or manually craft the HTTP request that TradeOfferManager makes.
  21. Like
    Dr. McKay reacted to apibot in craftingComplete sometimes not firing   
    just got back. tried it your way and it is so much better and effective. thanks!
  22. Like
    Dr. McKay got a reaction from sludgefudge in Issue with sent offer changed   
    That seems fine.
  23. Like
    Dr. McKay got a reaction from sludgefudge in Issue with sent offer changed   
    I've never seen a trade offer go from Accepted to some other state and actually mean that the trade didn't go through. Once it goes to Accepted you're pretty safe to say that it's completed.
    It used to be possible for trades to go to InvalidItems after Accepted, but the trade had still gone through. I don't think that's possible anymore though.
  24. Like
    Dr. McKay got a reaction from anonymous in Inventory and music kits   
    That schema entry is pointing to a musickit_prefab prefab. Check the prefabs section for an item by that name, and use that as a base for the item's data.
    I don't plan to decode every individual attribute onto the item object since there are tons of them. If you need to check the value of an attribute that isn't already decoded, you'll just need to decode it yourself.
  25. Like
    Dr. McKay reacted to KTVS in Item Craftability from GC   
    Wow, never saw this website for the Steam API before. I've just been looking at the official docs for years  ... I'll definitely be making use of the GetTradeStatus endpoint now that I know about it. Hot tip, thank you
×
×
  • Create New...