Jump to content
McKay Development

Dr. McKay

Administrator
  • Posts

    3389
  • Joined

  • Last visited

Reputation Activity

  1. Thanks
    Dr. McKay got a reaction from Robert Lutece in SteamUser. Can the client log off himself after a while?   
    From time to time yes, Steam will disconnect you. When the disconnected event is emitted, SteamUser will automatically reconnect and loggedOn will fire again.
  2. Thanks
    Dr. McKay got a reaction from ViniciusM in Create exchange between two users   
    Not possible. API keys cannot create, send, accept, or cancel trade offers.
  3. Like
    Dr. McKay got a reaction from behzadpp in problme 2fa file Error   
    https://github.com/DoctorMcKay/node-steamcommunity/blob/master/examples/enable_twofactor.js
  4. Haha
  5. Thanks
    Dr. McKay got a reaction from Robert Lutece in chatRoomGroupMemberStateChange event not triggering reasonably   
    Sounds like Steam isn't replying to the getPersonas call. You might possibly need to add a short delay to give Steam time to realize that you share a chat room with the user you're requesting data for.
  6. Thanks
    Dr. McKay got a reaction from vindisel in node-steamcommunity mobile login does not work anymore   
    I don't know offhand.
    Yep.
  7. Like
    Dr. McKay got a reaction from Risse in Restriction of trade offers for accounts that have a hold of exchanges   
    https://github.com/DoctorMcKay/node-steam-tradeoffer-manager/wiki/TradeOffer#getuserdetailscallback
  8. Like
    Dr. McKay got a reaction from Akaz in Userscript for steam-twofactor-server not working anymore   
    Fixed again, they changed a class name.
  9. Like
    Dr. McKay got a reaction from Robert Lutece in Userscript for steam-twofactor-server not working anymore   
    Fixed again, they changed a class name.
  10. Like
    Dr. McKay reacted to wandermaus in VDF.parse error after login   
    I found the error. I guess in an earlier version, the GID got returned directly.
    Thanks for your help!

  11. Thanks
    Dr. McKay got a reaction from Robert Lutece in Userscript for steam-twofactor-server not working anymore   
    It's fixed now.
  12. Thanks
    Dr. McKay got a reaction from Robert Lutece in How to "accept" receiving new items in TF2?   
    Acknowledging a received item is done by simply moving it to a backpack slot using setPosition or by sorting your backpack again using sortBackpack. sortBackpack only sorts your backpack once; it won't stay sorted when you receive new items.
  13. Thanks
    Dr. McKay got a reaction from Metro in Translate new /user/ links   
    It's now possible to generate a link to allow someone to add you as a friend without you needing to accept a request. These links look like
    http://s.team/p/user-id/token which redirects to https://steamcommunity.com/user/user-id/token   You can also access a profile using https://steamcommunity.com/user/user-id which will just redirect you to /id/ or /profiles/, depending on whether the profile has a custom URL set. These user IDs look like aaa-aaaa.   I don't know why it might be useful to convert a SteamID to friend-link user-id, but converting the user-id to a SteamID might be useful.   The friend-link user-ids are just the account's accountid (the lower 32 bits in the 64-bit SteamID, or the x part in [U:1:xxxx]), encoded in hexadecimal, with some character replacements, and with a dash added. Here are the replacements: Hex = Letter ------------ 0 = b 1 = c 2 = d 3 = f 4 = g 5 = h 6 = j 7 = k 8 = m 9 = n a = p b = q c = r d = t e = v f = w To convert a SteamID to a user-id, encode the accountid in hex and perform string replacements for the above characters. The hyphen isn't necessary for a final URL to work. To convert a user-id to a SteamID, remove the dash and perform string replacements for the above characters. That gives you an accountid which you can turn into a SteamID using a platform-appropriate SteamID library.
  14. Like
    Dr. McKay got a reaction from Robert Lutece in What's in a SteamID?   
    Ever wondered what's behind that big long number that we call a "SteamID"? It isn't just random; there are actually four numbers packed into it.
     
    A SteamID has four parts:
    Universe - The "instance of Steam" in which this ID is used. There is only one public Steam instance. Its name is "public", and its number is 1. The other universes are used internally at Valve for testing. Type - A SteamID can actually stand for several different types of accounts. The most common is individual, which is an individual user account. There are also types for clans (Steam groups), gameservers, anonymous gameservers, anonymous users, and more. Instance - This number is a bit finnicky. For the most part it's just a static number. For example, for individual SteamIDs the instance is pretty much always 1 (for desktop). Account ID - This is the actual ID of the account. Account IDs increment over time. If you know what universe, type, and instance an ID is for, then this is all you need to uniquely identify the account. As I mentioned previously, a 64-bit SteamID is actually broken down into four parts:
    8 bits for the universe 4 bits for the type 20 bits for the instance 32 bits for the account ID This means that in order to get an account ID out of a 64-bit SteamID, all you need to do is steamID & 0xFFFFFFFF.
     
    Warning: The Steam WebAPI and Steam Community website actually don't care about the instance as long as you've set the type and universe correctly. This means that if you're taking user input for SteamIDs, you could end up with duplicate accounts. For example, the SteamIDs 76561198006409530 and 76561202301376826 are considered identical because the universe, type, and accountids are the same. Try it for yourself: https://steamcommunity.com/profiles/76561198006409530 https://steamcommunity.com/profiles/76561202301376826
     
    Failure to take this into account can result in such exploits as this:
     

     
    (Yes, those are actually the same Steam account)
     
    Common SteamID Confusion
    SteamID aspects are a common source of confusion. For starters, what do you call various SteamID formats?
    This is the 64-bit SteamID (or just SteamID) format: 76561198006409530 This is the Steam3 format: [U:1:46143802] This is the Steam2 format: STEAM_0:0:23071901 (or the newer Steam2 format: STEAM_1:0:23071901) The "partner ID" in trade offer URLs is actually the account's account ID.
     
    Reading Rendered IDs
    Here's how to interpret the rendered ID formats.
    Steam3 Format
    [T:U:A] or [T:U:A:I]
    T - This is a single letter (case-sensitive) which tells you what type of account this is. The characters are documented on the Valve developer wiki. U - This is the universe to which this SteamID belongs. Unless you work for Valve, this will always be 1. A - This is the account ID for this SteamID. I - This is the SteamID's instance number. May be omitted if the instance is the default for that ID type or can be determined in other ways. Steam2 Format
    The Steam2 rendered format can only be used for individual SteamIDs.
    STEAM_X:Y:Z
    X - This is the universe to which this SteamID belongs. Older games use 0 to stand for public, newer ones use 1. Y - This is the SteamID's accountid modulo 2. Z - This is the SteamID's accountid halved and rounded down. Working with SteamIDs in code
    If you're using Node.js, you can use node-steamid to parse, create, and deal with SteamIDs.
    If you're using PHP, you can use php-steamid.
    If you're using C#, SteamKit has a SteamID class.
  15. Like
    Dr. McKay got a reaction from Robert Lutece in Cookies (outdated)   
    This post is outdated. Please see the updated version.
    Every website out there (that doesn't use HTTP authentication) uses cookies to identify user sessions. Cookies usually contain session IDs, which are looked up on the server in order to determine who the session belongs to. Steam is no different.
    All Steam websites (the store, community, the help site) use the same cookies to identify user sessions. There are four cookies which are required to identify a Steam session:
    sessionid steamLogin steamLoginSecure* steamMachineAuth* * = this cookie should only be sent over HTTPS
    Despite its name, the sessionid cookie is merely a CSRF token. Its value can be anything, as long as it matches the sessionid POST parameter in your POST requests. Steam will randomly assign you one the first time you hit one of the websites without already having one, even if you aren't logged in. They are not tied to accounts or to sessions.
    steamLogin and steamLoginSecure are the actual session cookies. Their format is: (your 64-bit SteamID + two pipe characters, percent encoded as %7C + a 40-character uppercase hexadecimal token). The hexadecimal token will differ between the two cookies, but the SteamID will be the same. steamLoginSecure should be sent with all HTTPS requests, and only for HTTPS requests. These cookies are short-lived and once invalidated (the exact circumstances that cause them to be invalidated are unclear), you will be logged out.
    steamMachineAuth is your Steam Guard identification cookie. You should replace with your actual 64-bit SteamID, so for example the name of my cookie would be steamMachineAuth76561198006409530. This cookie's value is simply a 40-character uppercase hexadecimal token. The cookie identifies a "machine" for Steam Guard, so that you don't have to provide an email code every time. This cookie is still present if you're using the mobile authenticator, even though you have to provide a code for every login. This cookie's issue date is also used as the "first sign in" date for purposes of determining trade restrictions. This cookie effectively lasts forever, so you should save it and reuse it between sessions. This cookie is required for trade offers to work.
    Note: Since Steam switched to HTTPS-only, steamLogin appears to no longer be necessary and is therefore no longer issued to web logins. It does seem to still be issued to Steam client-based logins.
    How to Get Cookies
    You can get Steam login cookies in one of three ways.
    You can log in to any Steam site in a browser, which will issue you cookies for that domain (and also do some JavaScript to set those cookies for other Steam domains). node-steamcommunity can do this for you. You can use the undocumented IMobileAuthService/GetWGToken WebAPI method with an oAuth token. node-steamcommunity can do this for you. You can use the ISteamUserAuth/AuthenticateUser WebAPI method with a nonce (loginkey) received from the CM. Sessions negotiated this way will have no steamMachineAuth cookie, and that cookie is unneeded for these sessions (trade offers will still work). Sessions negotiated this way will be invalidated as soon as the client session which received the CM nonce disconnects. node-steam-user can do this for you. Once you have cookies, you can use them with any of a number of modules, e.g. node-steam-trade, node-steamcommunity, node-steamstore, etc.
    Cookie Expiration
    Cookies expire and become invalid at seemingly-random times. There seems to be no real rhyme or reason as to when it happens, but it generally does happen whenever an account is logged in somewhere else, and on some unspecific time interval.
    If you log in to Steam using node-steam-user, you will be issued cookies, but they are only linked to the CM session in that they will expire if the session disconnects. They also follow normal expiration rules, meaning that even if your Steam client session is still connected, your cookies might have expired and thus your web requests will indicate that you aren't logged in. If this happens, you'll need to use webLogOn() to get new cookies.

    Cookie Usage
    I'll briefly explain how cookies and sessions work in my libraries. A quick overview on statefulness: HTTP is stateless. Each request is distinct from every other request, and thus there is no way to link two requests together (except by using cookies). For this reason, to keep track of which user is logged in, every site on the planet uses cookies. Typically, cookies contain an opaque session ID which the server looks up to see which account you're using. Steam is no exception. TCP is stateful. Each message sent over a TCP connection belongs to that connection and thus it's easy to link two messages together.
    node-steam-user connects to the CM using TCP (or optionally UDP, but it acts like TCP anyway). This is a stateful connection, and there is no need to use cookies to identify it.  Therefore, node-steam-user has no need for cookies. While it is capable of producing cookies, it does not save them and doesn't use them in any way except to make them available to the end-user for use elsewhere. node-steamcommunity communicates with Steam over HTTP, which is stateless. Thus, cookies are required in order to authenticate your requests to your account. node-steamcommunity can either accept cookies using the setCookies method (which can accept cookies obtained by any means, including node-steam-user), or it can produce cookies using the login method. Either method will save the cookies internally in the SteamCommunity object and those cookies will be used to authenticate every HTTP request. node-steamstore is identical to node-steamcommunity, although it cannot create cookies (i.e. it can only accept them using setCookies). node-steam-tradeoffer-manager is identical to node-steamstore, except it uses node-steamcommunity under the hood for its HTTP communication. Thus, if you instantiate TradeOfferManager and pass a community instance to the constructor, calling setCookies on the TradeOfferManager will also call setCookies on the SteamCommunity, and therefore you need not call setCookies on SteamCommunity (although it doesn't hurt anything, either). In list form, where a producer can create cookies and a consumer can use cookies:
    steam-user: producer steamcommunity: producer, consumer steamstore: consumer steam-tradeoffer-manager: consumer steam: producer steam-trade: consumer
  16. Like
    Dr. McKay got a reaction from Robert Lutece in Identifying Steam Items   
    I purposefully didn't mention the WebAPIs because they aren't really "Steam items". They're "Valve items", and third-party games don't need to follow any of the same standards. However, for Valve games, the "id" in the WebAPI is the item's asset ID, and "original_id" is the item's asset ID when it was originally created. If it's identical to the item's "id", that means that the item was never traded or modified. Quality (generally) determines the color of the item's name, and (sometimes) a prefix to the item's name (for example, StatTrak, ★, etc). Quality has nothing to do with wear.
     
    For CS:GO, you can't really get much useful information out of the WebAPI except an item's raw wear value (frequently, incorrectly, and ignorantly referred to as its "float value") and perhaps original ID.
  17. 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!
  18. Thanks
    Dr. McKay got a reaction from Caffxine in Steam's Inventory Cache   
    Why is my Steam inventory out-of-date?
     
    Before we delve into Steam's inventory cache, first it helps to know how the economy server works.
     
    When you request a user's Steam inventory, your request goes to the Steam economy server. If the economy server has that inventory in its cache, it returns the cached version. If not, it requests the inventory from the game's item server, caches the result that's returned, and then sends it back to you.
     
    This cache does not automatically expire (in most circumstances). However, there are a few actions that can cause an inventory cache for a particular game to expire:
    Launching the game via Steam Quitting the game via Steam Accepting a trade offer (or having a sent trade offer accepted) which includes items from the game Accepting a real-time trade request, or having a real-time trade request which you sent be accepted* Publishers can do it at their discretion * if a real-time trading session is opened for your account, then all games' inventory caches will be invalidated for your account.
     
    I believe it's also supposed to be possible for Steamworks developers to tell the cache to expire at a certain date and time, but I don't believe it works currently.
     
    The Steam inventory cache is what causes your inventory to not appear up-to-date, especially if you craft/receive a new item while the game is running. The easiest way to invalidate the cache in order to get fresh data is to open a real-time trading session.
  19. Like
    Dr. McKay got a reaction from Robert Lutece in Trading and Escrow -- Mobile Trade Confirmations   
    As of December 2015, all users who are losing items in a trade must have the Steam Guard Mobile Authenticator enabled, or else the trade will be held for three fifteen days. It's also no longer possible to opt-out of trade confirmations.
     
    This means that effectively, all trading bots need a mobile authenticator and need to accept mobile trade confirmations. You don't need an actual physical phone to act as your mobile authenticator, however. Through the efforts of myself and others, you can emulate a mobile authenticator right from node.js, and also accept trade confirmations.
     
    Enabling a Mobile Authenticator
     
    The Steam Guard Mobile Authenticator provides two-factor authentication security (hereinafter "2FA") for your account, which is more secure than standard email-based Steam Guard. This is done using a "shared secret" which is known to both the Steam servers and to your authenticator. Both sides run this secret through an algorithm along with the current time, which produces a 5-character alphanumeric code. This code is only valid for 30 seconds, and can only be used once. Attempts to reuse a 2FA code (either through the Steam Client or by logging in on steamcommunity.com) will treat the code as incorrect and reject it. For this reason, you can't login more frequently than once in a 30-second period.
     
    Enabling 2FA is a three-step process.
    Link and verify a phone number with your Steam account. You can do this manually from your account page, or programmatically using node-steamstore. Call enableTwoFactor using either node-steam-user or node-steamcommunity. If successful, this will return an object containing a bunch of properties. You should save this entire object. You can call JSON.stringify on it safely to turn it into a string. You'll need the revocation_code in the future if you ever want to disable 2FA. At this stage, 2FA isn't enabled yet. Steam will send you an SMS containing a code which you'll need in step 3. Call finalizeTwoFactor using either node-steam-user or node-steamcommunity. You will need the value of the shared_secret property from the object returned in step 2, and the numeric activation code from your SMS. If successful, your Steam account now has 2FA. Logging in With a Mobile Authenticator
     
    If you have 2FA enabled, then for every login you will need to provide a twoFactorCode (unless you're logging in with node-steam-user using a loginKey). You can generate this code using node-steam-totp and your shared_secret which you obtained (and should have saved) when you enabled 2FA.
     
    Mobile-Confirming Trades
     
    You are now required to confirm all trades in which you lose items. If you don't have 2FA enabled, then these confirmations will go to your email and the trades will be held for fifteen days. If you do have 2FA enabled, then the confirmations must be accepted through Steam's mobile confirmation interface. You can also accept mobile confirmations through node.js.
     
    node-steam-tradeoffer-manager doesn't have anything built-in to accept mobile confirmations. This is because mobile confirmations encompass more than just trades -- market listings also require confirmation, and potentially other things in the future.
     
    node-steamcommunity can accept your confirmations for you. In order to accept mobile confirmations, you will need the identity_secret (not the shared_secret used for login) from when you enabled 2FA. The best way to do this is to call acceptConfirmationForObject right after each trade offer you send/accept or market listing you create.
  20. Like
    Dr. McKay got a reaction from eXPerience in Questions about unencrypted session ticket   
    steam-user doesn't provide any way to specify your own sessionExternalIP value, but there's nothing stopping you from spoofing that field to be whatever you want, either. It's client-controlled and isn't authenticated by Steam as far as I'm aware. You could try changing the value directly in the steam-user code here and see what happens. Yes, the internal IP is determined from the private IP specified when you connected to Steam. By default, steam-user sends 0 unless you change the logonID value in the logOn method. You need to encode your desired internal IP as a 32-bit int, then xor it with 0xBAADF00D. For example, 192.168.1.2 encodes to 3232235778, then xor that by doing 3232235778 ^ 0xBAADF00D and you get 2158493696, which is what you should use for your logonID. Yes, ownership tickets are cached in userdata/your_account_id/config/localconfig.vdf under apptickets. Not as far as I'm aware You can use NetHook for that. When you inject it, you'll need to provide the filename of the game process you want to inject into.
  21. Like
    Dr. McKay got a reaction from heinrich5991 in Source of the protobufs   
    They come from SteamDB, which itself dumps them from Steam using ProtobufDumper.
  22. Thanks
    Dr. McKay got a reaction from 3urobeat in Port is ignored for HTTP proxies   
    No bother, I fixed the bug in response to this thread. It was in one of steam-session's dependencies which I maintain.
  23. Like
    Dr. McKay got a reaction from 3urobeat in Port is ignored for HTTP proxies   
    This was a bug. Run npm update and you should be set.
  24. Like
    Dr. McKay got a reaction from Akaz in Is there a way to activate a viewer pass?   
    Not as far as I'm aware. I'm not super familiar with CS:GO stuff.
  25. Thanks
    Dr. McKay got a reaction from Akaz in cancelTime used by a different instance that the one creating the offer?   
    Yes, that is instance-linked.
×
×
  • Create New...