Steam's protocol in Go to allow automation of different actions on the Steam network without running an actual Steam client

Steam for Go

This library implements Steam's protocol to allow automation of different actions on Steam without running an actual Steam client. It is based on SteamKit2, a .NET library.

In addition, it contains APIs to Steam Community features, like trade offers and inventories.

Some of the currently implemented features:

  • Trading and trade offers, including inventories and notifications
  • Friend and group management
  • Chatting with friends
  • Persona states (online, offline, looking to trade, etc.)
  • SteamGuard with two-factor authentication
  • Team Fortress 2: Crafting, moving, naming and deleting items

If this is useful to you, there's also the go-steamapi package that wraps some of the official Steam Web API's types.

Installation

go get github.com/Philipp15b/go-steam

Usage

You can view the documentation with the godoc tool or online on godoc.org.

You should also take a look at the following sub-packages:

Working with go-steam

Whether you want to develop your own Steam bot or directly work on go-steam itself, there are are few things to know.

  • If something is not working, check first if the same operation works (under the same conditions!) in the Steam client on that account. Maybe there's something go-steam doesn't handle correctly or you're missing a warning that's not obviously shown in go-steam. This is particularly important when working with trading since there are restrictions, for example newly authorized devices will not be able to trade for seven days.
  • Since Steam does not maintain a public API for most of the things go-steam implements, you can expect that sometimes things break randomly. Especially the trade and tradeoffer packages have been affected in the past.
  • Always gather as much information as possible. When you file an issue, be as precise and complete as you can. This makes debugging way easier.
  • If you haven't noticed yet, expect to find lots of things out yourself. Debugging can be complicated and Steam's internals are too.
  • Sometimes things break and other SteamKit ports are fixed already. Maybe take a look what people are saying over there? There's also the SteamKit IRC channel.

Updating go-steam to a new SteamKit version

Go source code is generated with code in the generator directory. Look at generator/README.md for more information on how to use the generator.

Then, after generating new Go source files, update go-steam as necessary.

License

Steam for Go is licensed under the New BSD License. More information can be found in LICENSE.txt.

Comments
  • Wrong module path in go.mod

    Wrong module path in go.mod

    As per documention:

    If the module is released at major version 2 or higher, the module path must end with a major version suffix

    Since go-steam has go.mod file at git tag v2.0.0 it must have module github.com/Philipp15b/go-steam/v2 in go.mod and not module github.com/Philipp15b/go-steam.

    Because of that it cannot be shown in htttps://pkg.go.dev/ for example.

  • throw nil pointer error on windows 7 32 bit

    throw nil pointer error on windows 7 32 bit

    autho.go atomic.StoreUint64(&a.client.steamId, uint64(steamid.New(0, 1, int32(EUniverse_Public), EAccountType_Individual)))

    then I change the code as:

    
    uuu := uint64(steamid.New(0, 1, int32(EUniverse_Public), EAccountType_Individual))
    
    fmt.Printf("a=%p,a.client=%p,a.client.steamId=%d\n",a,a.client,a.clien.steamId)
    
    atomic.StoreUint64(&(a.client.steamId), uuu)
    
    

    Printf: a has valid address, a.client also has valid address, and a.client.steamId=0

    but atomic.StoreUint64(&(a.client.steamId), uuu) still painc nil pointer

  • Error connecting.

    Error connecting.

    When I call

    	myLoginInfo := new(steam.LogOnDetails)
    	myLoginInfo.Username = "user"
    	myLoginInfo.Password = "pass"
    
    	client := steam.NewClient()
    	client.Connect()
    

    Sometimes it works but then I get this error:

     Error reading from the connection: EOF
    

    or sometimes is throws an error on client.Connect():

    Connect failed: dial tcp 162.254.196.43:27020: connectex: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
    

    How can I solve this?

  • Update generator for new protoc and protoc-gen-go #118

    Update generator for new protoc and protoc-gen-go #118

    fixes https://github.com/Philipp15b/go-steam/issues/118

    Hello,

    this is my first PR on here, I never used go-steam yet, I wanted to but came across the issue #118

    this was a tough one I didn't test yet, the generator generate the files without errors

  • TradeOffer Create Error (Status code != 200)

    TradeOffer Create Error (Status code != 200)

    Sample of code:

    case *steam.WebLoggedOnEvent:
                log.Print("Successfully logged on web")
    
                token := "awajV_Bp"
    
                TOClient := tradeoffer.NewClient(SteamAPIKey, client.Web.SessionId, client.Web.SteamLogin, client.Web.SteamLoginSecure)
                Offers, _ := TOClient.GetOffers()
    
                for _, TOffer := range Offers.Received {
                    if (TOffer.State == 2) {
                        log.Println("Starting processing TOffer")
    
                        myItems := make([]tradeoffer.TradeItem, len(TOffer.ToReceive))
                        theirItems := make([]tradeoffer.TradeItem, 0)
                        for k, Asset := range TOffer.ToReceive {
                            myItems[k] = tradeoffer.TradeItem{
                                AppId: uint32(Asset.AppId),
                                ContextId: uint64(Asset.ContextId),
                                Amount: uint(Asset.Amount),
                                AssetId: uint64(Asset.AssetId),
                            }
                        }
    
                        log.Println(TOClient.Accept(TOffer.TradeOfferId))
                        log.Println(TOClient.Create(TOffer.OtherAccountId, &token, myItems, theirItems, nil, ""))
                    }
                }
    

    And github.com/Philipp15b/tradeoffer/tradeoffer.go

    // If we failed, error out
        if resp.StatusCode != 200 {
            return nil, errors.New("create error: status code not 200")
        }
    

    replaced to (just for check body of result page)

    // If we failed, error out
        if resp.StatusCode != 200 {
            data, _ := ioutil.ReadAll(resp.Body)
            fmt.Println(string(data))
            return nil, errors.New("create error: status code not 200")
        }
    

    Result: http://i.imgur.com/fzEYOk3.png (Checked on Windows and Mac)

    tradeoffer.Accept working good, but tradeoffer.Create doesn't work

  • Retrieving package VDF data returns binary VDF

    Retrieving package VDF data returns binary VDF

    Hi, I am trying to get the VDF data on apps and packages. The app proto CMsgClientPICSProductInfoResponse_AppInfo seems to always return okay but trying to get the VDF data from a package CMsgClientPICSProductInfoResponse_PackageInfo always returns binary VDF. Is there a helper somewhere to convert to text? Thanks.

  • Updating go-steam to a new SteamKit version fails

    Updating go-steam to a new SteamKit version fails

    I am trying to update to a new SteamKit version now, but the build fails:

    $ go run generator.go clean proto steamlang
    # Cleaning
    # Building Steam Language
    # Building Protobufs
    > [libprotobuf WARNING google/protobuf/compiler/parser.cc:564] No syntax specified for the proto file: steammessages_parental.steamclient.proto. Please use 'syntax = "proto2";' or 'syntax = "proto3";' to specify a syntax version. (Defaulted to proto2 syntax.)
    > [libprotobuf WARNING google/protobuf/compiler/parser.cc:564] No syntax specified for the proto file: steammessages_unified_base.steamclient.proto. Please use 'syntax = "proto2";' or 'syntax = "proto3";' to specify a syntax version. (Defaulted to proto2 syntax.)
    > [libprotobuf WARNING google/protobuf/compiler/parser.cc:564] No syntax specified for the proto file: google/protobuf/descriptor.proto. Please use 'syntax = "proto2";' or 'syntax = "proto3";' to specify a syntax version. (Defaulted to proto2 syntax.)
    > panic: runtime error: index out of range
    
    goroutine 1 [running]:
    main.cutAllSubmatch(0xc0000ce090, 0xc000176000, 0xeac0, 0xecc0, 0x1, 0x2, 0xc000024080, 0x0)
            /home/nuc/go/src/github.com/Philipp15b/go-steam/generator/generator.go:227 +0xe2
    main.fixProto(0xc0000aa180, 0x2b)
            /home/nuc/go/src/github.com/Philipp15b/go-steam/generator/generator.go:196 +0x530
    main.buildProtoMap(0x5301a6, 0xb, 0xc000096270, 0x531a8d, 0x14)
            /home/nuc/go/src/github.com/Philipp15b/go-steam/generator/generator.go:92 +0x195
    main.buildProto()
            /home/nuc/go/src/github.com/Philipp15b/go-steam/generator/generator.go:82 +0xfd
    main.main()
            /home/nuc/go/src/github.com/Philipp15b/go-steam/generator/generator.go:37 +0x20e
    exit status 2
    

    Btw it might help that https://github.com/faceit/go-steam has some commits for newer SteamKit versions.

  • Code review

    Code review

    Revised import statements across the whole project. Guidelines: https://github.com/golang/go/wiki/CodeReviewComments#import-dot

    The dot imports have rendered this project completely unreadable. Excessive verbosity has to be solved by other means of refactoring/restructuring/renaming. Dot imports are not a good solution.

    This change adds to clarity and separation of namespaces.

  • Type mismatch causing go-steam not to build.

    Type mismatch causing go-steam not to build.

    Hi there,

    Excuse me if I'm blatantly incorrect - this endeavour was my first time writing any Go.

    I've got a source file which is simply a Hello World, but loads in go-steam as my first ask after Hello World is going to be logging into a Steam account.

    package mmstats_provider
    
    import (
        "fmt"
        "github.com/Philipp15b/go-steam"
        "github.com/Philipp15b/go-steam/internal/steamlang"
        "io/ioutil"
        "log"
    )
    
    func main() {
        fmt.Println("Hello World")
    }
    

    When attempting to build this little bit of code, I got the following error:

    ../../Philipp15b/go-steam/auth.go:50: cannot use steamlang.EAccountType_Individual (type steamlang.EAccountType) as type int32 in argument to steamid.NewIdAdv
    

    If I understand correctly, this is because EAccountType_Individual is of type EAccountType (which is based upon int32, but I guess Go is pretty strict about it's types), whereas steamid.NewIdAdv is expecting a regular int32 for a user's account type. I can workaround this for now by casting EAccountType_Individual to int32, but I think the correct solution is to change NewIdAdv to accept an EAccountType value for accountType instead of int32 - and at present I don't know how to do that (importing steamlang errored out because of circular imports).

    Thanks,

  • UDP connection

    UDP connection

    Steam have two type of connection , UDP and TCP according to steamRE connection.cs

    Do you wish to upgrade go-steam to include it as well ? some code needed to be changed mainly on

    client.go

    • read / write loop handling should be handle by connection.go

    connection.go

    • connection interface to handle UDP and TCP

    API provided by client.go should not be changed ( at least not to my knowledge )

    what do you think ?

  • Add topt token generation

    Add topt token generation

    Closes #108. Code used in PR is originally made by https://github.com/fortis and is used in https://github.com/fortis/go-steam-totp. Code is tested and works well.

  • fix GetFullInventory fails to load huge inventories

    fix GetFullInventory fails to load huge inventories

    There were 2 variables next. One is local to the loop and another in the outer scope. On every iteration, starting from the second, latest would become equal to the outer next (which was always nil) and fail immediately.

  • proto: file

    proto: file "steammessages_base.proto" has a name conflict over CMsgProtoBufHeader

    Hey!

    I really enjoy working with your library. However, with the new protobuf library from Google, I am running into the following issue:

    panic: proto: file "steammessages_base.proto" has a name conflict over CMsgProtoBufHeader
            previously from: "github.com/Philipp15b/go-steam/v3/csgo/protocol/protobuf"
            currently from:  "github.com/Philipp15b/go-steam/v3/protocol/protobuf"
    See https://developers.google.com/protocol-buffers/docs/reference/go/faq#namespace-conflict
    

    This seems to be caused by the default init in the protobuf packages. Since both the csgo/protocol/protobuf and the protocol/protobuf package declare the same base protobufs, there seems to be a conflict.

    I am only importing github.com/Philipp15b/go-steam/v3/csgo/protocol/protobuf in my code. But I would guess that the other package is being imported automatically by a package in the background.

    Does anyone have a idea how to fix that issue? Merging the protobufs into one directory would be a solution, but not the prettiest solution.

    Update: I guess that a fix could be implemented in this projects generator. We should try to use the same base protobufs and not duplicate the definitions.

  • Sentry file ignored — possible cause

    Sentry file ignored — possible cause

    I use Steam Guard 2FA and I can't solve this one.

    Right now, the sentry file is ignored on subsequent login attempts, and I'm always asked for the 2FA. Here are some observations on the code.

    An observation on the gsbot's Auth type HandleEvent method:

    func (a *Auth) HandleEvent(event interface{}) {
    	switch e := event.(type) {
    	case *steam.MachineAuthUpdateEvent:
    		a.machineAuthHash = e.Hash
    		err := ioutil.WriteFile(a.sentryPath, e.Hash, 0666)
    		if err != nil {
    			panic(err)
    		}
    	}
    }
    

    It never informs Steam servers of accepting the Sentry file.

    An observation on SteamKit's MachineAuthUpdateEvent:

            static void OnMachineAuth( SteamUser.UpdateMachineAuthCallback callback )
            {
                Console.WriteLine( "Updating sentryfile..." );
    
                // write out our sentry file
                // ideally we'd want to write to the filename specified in the callback
                // but then this sample would require more code to find the correct sentry file to read during logon
                // for the sake of simplicity, we'll just use "sentry.bin"
    
                int fileSize;
                byte[] sentryHash;
                using ( var fs = File.Open( "sentry.bin", FileMode.OpenOrCreate, FileAccess.ReadWrite ) )
                {
                    fs.Seek( callback.Offset, SeekOrigin.Begin );
                    fs.Write( callback.Data, 0, callback.BytesToWrite );
                    fileSize = ( int )fs.Length;
    
                    fs.Seek( 0, SeekOrigin.Begin );
                    using ( var sha = SHA1.Create() )
                    {
                        sentryHash = sha.ComputeHash( fs );
                    }
                }
    
                // inform the steam servers that we're accepting this sentry file
                steamUser.SendMachineAuthResponse( new SteamUser.MachineAuthDetails
                {
                    JobID = callback.JobID,
    
                    FileName = callback.FileName,
    
                    BytesWritten = callback.BytesToWrite,
                    FileSize = fileSize,
                    Offset = callback.Offset,
    
                    Result = EResult.OK,
                    LastError = 0,
    
                    OneTimePassword = callback.OneTimePassword,
    
                    SentryFileHash = sentryHash,
                } );
    
                Console.WriteLine( "Done!" );
            }
    

    It informs Steam servers of accepting the sentry file. Source: SteamKit SteamGuard example

Related tags
Plugs module to see different types of plug types needed in different countries, and a comparison tool between two countries plug socket types.

plugs Importing the module: go get github.com/matthewboyd/plugs "github.com/matthewboyd/plugs" How to use the module: There are two functions wi

Dec 28, 2021
Zero Trust Network Communication Sentinel provides peer-to-peer, multi-protocol, automatic networking, cross-CDN and other features for network communication.
Zero Trust Network Communication Sentinel provides peer-to-peer, multi-protocol, automatic networking, cross-CDN and other features for network communication.

Thank you for your interest in ZASentinel ZASentinel helps organizations improve information security by providing a better and simpler way to protect

Nov 1, 2022
TCP proxy, highjacks HTTP to allow CORS

portproxy A shitty TCP proxy that relays all requests to a local port to a remote server. portproxy -port 8080 -raddr google.com:80 Will proxy all TC

Jan 1, 2023
Transport to allow go-libp2p applications to natively use i2p for communication

I2P Transport for go-libp2p This library can be used to build go-libp2p applications using the i2p network. Look at transport_test.go for example usag

Sep 15, 2022
Bridge REMOV will allow you to safely transfer NFT from RMRK to MOVR and backwards

remov Inspiration Our aim is to expand the capabilities of blockchain and make a secure way for transferring NFT between RMRK and MOVR blockchain. The

Dec 5, 2021
UFW-Autoblacklist - Script that allow you to ban-ip all spammers
UFW-Autoblacklist - Script that allow you to ban-ip all spammers

Setup: go build main.go tcptrack -i <interface> | ./main

Nov 1, 2022
Provides agent and server plugins for SPIRE to allow Tailscale node attestation.

SPIRE Tailscale Plugin ⚠️ this node attestation plugin relies on a Tailscale OIDC id-token feature, which is marked as Work-in-Progress and may not be

May 22, 2022
A TCP proxy used to expose services onto a tailscale network without root. Ideal for container environments.

tailscale-sidecar This is barely tested software, I don't guarantee it works but please make an issue if you use it and find a bug. Pull requests are

Dec 30, 2022
🌌 A libp2p DHT crawler that gathers information about running nodes in the network.
🌌 A libp2p DHT crawler that gathers information about running nodes in the network.

A libp2p DHT crawler that gathers information about running nodes in the network. The crawler runs every 30 minutes by connecting to the standard DHT bootstrap nodes and then recursively following all entries in the k-buckets until all peers have been visited.

Dec 27, 2022
wire protocol for multiplexing connections or streams into a single connection, based on a subset of the SSH Connection Protocol

qmux qmux is a wire protocol for multiplexing connections or streams into a single connection. It is based on the SSH Connection Protocol, which is th

Dec 26, 2022
A simple tool to convert socket5 proxy protocol to http proxy protocol

Socket5 to HTTP 这是一个超简单的 Socket5 代理转换成 HTTP 代理的小工具。 如何安装? Golang 用户 # Required Go 1.17+ go install github.com/mritd/s2h@master Docker 用户 docker pull m

Jan 2, 2023
Fluux XMPP is a Go XMPP library, focusing on simplicity, simple automation, and IoT.

Fluux XMPP is a Go XMPP library, focusing on simplicity, simple automation, and IoT. The goal is to make simple to write simple XMPP client

Dec 14, 2022
Wake-On-LAN Server for Home Automation
Wake-On-LAN Server for Home Automation

Wake-On-LAN Server for Home Automation This project builds a simple docker container that runs a webserver that allows you to send a wake-on-lan magic

Jan 21, 2022
network multiplexing and framing protocol for RPC

TChannel Network multiplexing and framing protocol for RPC Read the Docs Languages: Node.js, Python, Go, Java Questions: Open a Github issue Uber's OS

Nov 26, 2022
Capture packet request/response pairs for a port and/or IP to aid in Network protocol based Nuclei Templates creation.

network-fingerprint Capture packet request/response pairs for a port and/or IP to aid in Network protocol based Nuclei Templates creation. Resources I

Nov 15, 2022
Fast implementation of the collectd network protocol for go.

go-cdclient A fast, dependency free implementation of the collectd binary network protocol. How fast? This package can form an encrypted metric packet

Feb 6, 2022
Powerful golang network framework, supporting FFAX Protocol

X.NET framework Install $ go get github.com/RealFax/XNET This is a high-performance network framework, currently only supports tcp and FFAX protocol U

Nov 19, 2021
A minimal analytics package to start collecting traffic data without client dependencies.

go-web-analytics A minimal analytics package to start collecting traffic data without client dependencies. Logging incoming requests import "github.co

Nov 23, 2021
Package socket provides a low-level network connection type which integrates with Go's runtime network poller to provide asynchronous I/O and deadline support. MIT Licensed.

socket Package socket provides a low-level network connection type which integrates with Go's runtime network poller to provide asynchronous I/O and d

Dec 14, 2022