This gem simplifes/allows sending steam trade offers programmatically.
z# steam-trade V0.3.3
PLEASE IF SOMETHING DOES NOT WORK PROPERLY MAKE A GITHUB ISSUE
This gem simplifes/allows sending steam trade offers programmatically.
this gem is primarly for trading cards, tho can be used to CS:GO and other games inventories
0.3.3:
- hotfix login without api-key
0.3.2:
- added send_trade_allow_request() (mobile confirmation) and confirm_all() (mobile confirmation)
0.3.1:
- added cottage() , vote_2018() and sell_items()
0.3.0:
- hotfix for cookie login
0.2.9:
- hotfix for cookie login (remember me)
0.2.8:
- fixed cookie login
0.2.7:
- added salien_card() to collect steam Salien game Trading Cards
0.2.6:
- hotfix
0.2.5:
- added finish_queue() to collect Steam Sale Trading Cards
- hotfix
0.2.4:
- hotfix
0.2.3:
- hotfix
0.2.2:
- fixed issues with ruby 2.4+
- added class methods for fa(), normal_get_inventory(), raw_get_inventory, sets_count()
0.2.1:
- many many bugs fixed
0.2.0:
- hotfix
0.1.9:
- Handler.new() now accepts a hash contains login cookies.
- get_auth_cookies() returns cookies to use for the next login
0.1.8:
- hotfix
0.1.7:
- hotfix
0.1.6:
- hotfix
0.1.5:
- added mobile_login() which allows you to send and receive steam messages
- added oauth_login() uses oauth token and steamMachine cookie to login in ( you get those from mobile_login())
0.1.4:
- added Social commands : send friend request, accept friend request, remove friend, send message, get messages
- added function to update badges blueprint (useful when there is no gem update)
0.1.3:
- decreased cooldown between requests from 2 seconds to 1 second.
- added a 0.6 second wait before attempting to confirm a trade offer (mobile).
- added a 3 times retry to get an inventory chunk before raising an error.
- exception handling for sets_count, now no longer raises an error if the target inventory contains trading cards which are not specified in the bluepirnt.
0.1.2:
- normal_get_inventory() and raw_get_inventory() now uses Mechanize instead of open-uri.
- Handler.new() and fa() now accepts a time difference parameter to adjust your 2FA codes.
- sets_count() now writes the txt file faster.
- Mechanize session associated with the account now has a 2 second cooldown before each request to avoid spamming steam servers and resulting in a ban.
in your commandline :
gem install steam-trade
First you need to require the gem:
require 'steam-trade'
Handler.new()
Handler.new(username, password,shared_secret,time_difference,remember_me)
then you need to login and optionally set your shared_secret and identity_secret:
shared_secret
is used to generate steam authentication codes so you won’t have to write them manually each time you login.time_difference
is the difference between your time and steam servers, this affects how 2FA codes are generated (this MUST BE an integer)remember_me
is a boolean used to indicate whether you want cookies which expire shortly if set to false or stay valid for weeks if set to trueaccount = Handler.new(‘username’,’password’,’shared_secret’) # share secret is optional
account = Handler.new(‘username’,’password’,50) #works
account = Handler.new(‘username’,’password’,’shared_secret’,50)
account = Handler.new(‘username’,’password’,50,’shared_secret’) # this will not work
account = Handler.new(‘username’,’password’,’shared_secret’,20,true) # works
account = Handler.new(‘username’,’password’,’shared_secret’,true) #works
account = Handler.new(‘username’,’password’,20,true) #works
account = Handler.new(‘username’,’password’,true) #works
account = Handler.new(‘username’,’password’,’shared_secret’,true,20) # will not work
account = Handler.new(‘username’) #this of course counts as non logged in
keep in mind you can initialize a Handler without params however the commands you will be able to use will be limited
```ruby
require 'steam-trade'
account = Handler.new()
puts account.fa('v3dWNq2Ncutc7RelwRVXswT8CJX=v3dWNq2Ncutc7WelwRVXswT8CJk=') => random code
Handler.new(cookies_hash,shared_secret,time_difference,remember_me)
cookies_hash
is hash containing steamLogin
, steamLoginSecure
and steamMachineAuth
cookies.get_auth_cookies()
for faster login.shared_secret
is used to generate steam authentication codes so you won’t have to write them manually each time you login.time_difference
is the difference between your time and steam servers, this affects how 2FA codes are generated (this MUST BE an integer)remember_me
is a boolean used to indicate whether you want cookies which expire shortly if set to false or stay valid for weeks if set to true
require 'steam-trade'
account = Handler.new(JSON.parse(File.read('./creds.json'))) # creds.json is created by get_auth_cookies()
account = Handler.new(JSON.parse(File.read('./creds.json')), 'shared_secret', 50)
get_auth_cookies()
File.open(‘creds.json’, ‘w’) {|f| f.puts cookies.to_json}
next time :
```ruby
require 'steam-trade'
account = Handler.new(JSON.parse(File.read('./creds.json')))
mobile_info(identity_secret)
identity_secret
is your account’s identity secret (try using google if you don’t know what this is).identity_secret
is used to automatically confirm trade offers.account = Handler.new(‘username’,’password’,’shared_secret’)
account.mobile_info(‘identity_secret’)
## Getting someone's inventory
you might want to read this [guide](https://dev.doctormckay.com/topic/332-identifying-steam-items/)
#### `normal_get_inventory('steamid','inventoryappid')`
- `steamid` is the target's steamID, or profileID, or trade link
- `inventoryappid` is the inventory type you want to load, `ex : normal inventory(the one which holds trading cards), it's is 753`
- if you call `normal_get_inventory()` with no params, it will be default use the current logged-in account `steamid`, `inventoryappid = 753`
```ruby
require 'steam-trade'
inventory = Handler.normal_get_inventory("nomg3r")
logged = Handler.new('username','password','shared_secret')
logged.mobile_info('identity_secret')
# while logged in
my_inventory = logged.normal_get_inventory() #will get your normal inventory(753) if you are logged in else raise an exception
my_inventory = logged.normal_get_inventory('730') # will get your CS:GO inventory if you are logged in else raise an exeception
#whatever can be done while **not** logged in, can be of course used while logged in
#while not logged in
nonlogged = Handler.new()
my_inventory = nonlogged.normal_get_inventory() #will raise an exception
my_inventory = nonlogged.normal_get_inventory('730') #will raise an exception
#whenever
partner_inventory = nonlogged.normal_get_inventory('76561198044170935') #using steamid
partner_inventory = nonlogged.normal_get_inventory('https://steamcommunity.com/tradeoffer/new/?partner=410155236&token=H-yK-GFt') #using trade link
partner_inventory = nonlogged.normal_get_inventory('CardExchange') #using profile id
partner_inventory = nonlogged.normal_get_inventory('76561198044170935',730) #will get that steamid CS:GO inventory
partner_inventory = nonlogged.normal_get_inventory('https://steamcommunity.com/tradeoffer/new/?partner=410155236&token=H-yK-GFt', '730') #will get that trade link owner's CS:GO inventory
partner_inventory = nonlogged.normal_get_inventory('CardExchange',730) # will get CardExchange's CS:GO inventory
the returned items from normal_get_inventory()
are in the form of an array example : [item1,item2,item3...itemN]
.
each item is a hash which contains information about the item in the form of {"appid"=>'xxx',"contextid"=>'xxx',"assetid" => 'xxx',"classid"=> 'xxx',......"name"=> 'xxxx',"market_fee_app" => 'xxx',....}
.
market_fee_app
key gives you the appid of the game’s app (for trading cards), for other items technically inventoryappid
is the games appid.
name
key gives you the item name.
raw_get_inventory(target,inventoryappid,trimming)
IMPORTANT: this command efficiency is better than normal_get_inventory
, therefore i recommend using this one.
target
is a steamID/profileID/trade linkinventoryappid
is the inventory type you want to load, ex : normal inventory(the one which holds trading cards), it's is 753
trimming
, defaults to true
this will remove images link and steam-server-side related informations from the descriptions hash, drastically reducing the size of data received.This command will return a hash nearly identitical to the one received from steam the hash will have 2 keys assets
and descriptions
:
assets
has an array as value, identical to steam’s (example)descriptions
has an array as a value identical to steam’s (example)
require 'steam-trade'
inv = Handler.raw_get_inventory("nomg3r")
logged = Handler.new('username','password','shared_secret')
inv = logged.raw_get_inventory() #works
inv = logged.raw_get_inventory(false) # returns non trimmed
inv = logged.raw_get_inventory(440) #works
inv = logged.raw_get_inventory(76561198044170935,false) #works
inv = logged.raw_get_inventory(76561198044170935,440) # works
print inv['assets'] #will print all the assets
print inv['descriptions'] #will print all the descriptions
### how to accurately use this
class_instance = {}
## map all the items
inv['descriptions'].each { |desc|
identifier = desc['classid'] + '_' + desc['instanceid']
class_instance[identifier] = desc
}
## identify your items
inv['assets'].each { |asset|
identifier = asset['classid'] + '_' + asset['instanceid']
puts class_instance[identifier] this will output the item's description
}
set_inventory_cache()
set_inventory_cache()
is:
accepts a parameter timer
which defaults to timer = 120
, this parameter is the difference between the save file was created and the moment it was checked (upong trying to retrieve the inventory).
this switch is useful if you are getting a “static” inventory or testing your code.
```ruby
require ‘steam-trade’
logged = Handler.new(‘username’,’password’,’shared_secret’)
logged.mobile_info(‘identity_secret’)
logged.set_inventory_cache(150)
partner_inventory = loggedlogged.normal_get_inventory(‘CardExchange’) #this will save CardExchange’s inventory to a local file and return the inventory
partner_inventory = loggedlogged.normal_get_inventory(‘CardExchange’) # this will load the locally saved file
**IMPORTANT**: `normal_get_inventory()` will load the whole target inventory, for each **5k** of items, you are adding **~40MB** to your memory and of course will affect performance of the code and the computer
## Sending a trade offer
#### `send_offer(myarray,theirarray,trade_offer_link,message)`
**MUST be logged in to use this command**
then you can send your offer
- `myarray` is an array which contains hashes of selected items to send in the offer. (currently you must get this on your own)
- `Theirarray` is an array which contains hashes of selected items to receive in the offer. (currently you must get this on your own)
- `trade_offer_link` can be the trade link of you partner `ex: https://steamcommunity.com/tradeoffer/new/?partner=410155236&token=H-yK-GFt`
- `trade_offer_link` can be a steamID, however using a steamID requires you and your partner to be friends on steam
- `trade_offer_link` can be a profileID, however using a profileID requires you and your partner to be friends on steam
- `message` is the comment you want to include in the trade offer
- `myarray`, `theirarray`, `trade_offer_link` are required, `message` is optional
- **returns a hash which contains informations about the trade**
- **identity_secret** is required for this function to work
```ruby
require 'steam-trade'
account = Handler.new('username','password','shared_secret')
account.mobile_info('identity_secret')
me = account.normal_get_inventory()
his = account.normal_get_inventory("nomg3r")
myarray = [me[5] , me[20] , me[60]].compact!
theirarray = [his[1], his[20], his[30]].compact!
# if you are friends
resp = account.send_offer(myarray,theirarray,"nomg3r",message)
#or (as friends)
account.send_offer(myarray,theirarray,'76561198370420964',message)
# whenever
account.send_offer(myarray,theirarray,"https://steamcommunity.com/tradeoffer/new/?partner=410155236&token=H-yK-GFt",message)
send_trade_allow_request(tradeofferid)
tradeofferid
is the ID of the offer you want to confirm (mobile confirmation)account = Handler.new(‘username’,’password’,’shared_secret’)
account.mobile_info(‘identity_secret’)
me = account.normal_get_inventory()
his = account.normal_get_inventory(“nomg3r”)
myarray = [me[5] , me[20] , me[60]].compact!
theirarray = [his[1], his[20], his[30]].compact!
resp = account.send_offer(myarray,theirarray,”nomg3r”,message)
account.send_trade_allow_request(resp[‘tradeofferid’])
#### `confirm_all()`
- confirms all trades which are waiting for mobile confirmation
- **identity_secret** is required for this function to work
```ruby
require 'steam-trade'
account = Handler.new('username','password','shared_secret')
account.mobile_info('identity_secret')
account.confirm_all
you might want to read Steam Trading API
ALL OF THE COMMANDS BELOW REQUIRE AN API_KEY
set_api_key(API_KEY)
NOTE:If you are using a logged in Handler there is no need to set the API_KEY.
API_KEY
is your apikey, you can get that from here.
require 'steam-trade'
acc = Handler.new()
trade_offers = acc.get_trade_offers() # will raise an exception
acc.set_api_key('mykey')
trade_offers = acc.get_trade_offers() # after setting an API_KEY this will succeed
get_trade_offers(time)
time
is the moment from which you want to get updates (explained in the example)trade_offers_sent
, trade_offers_received
, descriptions
as keys.descriptions
includes the descriptions of all items returned from trade_offers_sent
or trade_offers_received
require 'steam-trade'
logged = Handler.new('username','password','shared_secret')
logged.mobile_info('identity_secret')
time = '' # this is the initial check for offers so we want them all
polling = Thread.new(logged) { |logged|
loop do
offers = logged.get_trade_offers(time)
time = Time.new.to_i # we save the time of the last check
next if offers['trade_offers_received'] == nil # do nothing, if there is no trades
puts offers['trade_offers_received'] # puts the trades
sleep(15) # make sure not to spam steam's server or they will block list your IP for a period of time therefore you can't make requests
end
}
get_trade_offer(tradeofferid)
gets more information about a specific trade offer
tradeofferid
is the id of the offer you want to confirm (you can get the id using this to get the offerIDhave no example how to actually use this cause get_trade_offers(time)
is probably better
accept_trade_offer(tradeofferid)
tradeofferid
is the id of the offer you want to confirm (you can get the id using this to get the offerIDtime = ‘’ # this is the initial check for offers so we want them all
polling = Thread.new(logged) { |logged|
loop do
offers = logged.get_trade_offers(time)
time = Time.new.to_i # we save the time of the last check
next if offers[‘trade_offers_received’] == nil # do nothing, if there is no trades
offers[‘trade_offers_received’].each { |trade|
if trade[‘accountid_other’].to_i == 83905207 ## this will accept all trade received from 83905207 (Steam32 ID)
logged.accept_trade_offer(trade[‘tradeofferid’]) # to accept the trade
end
}
sleep(15) # make sure not to spam steam’s server or they will block list your IP for a period of time therefore you can’t make requests
end
}
#### `decline_trade_offer(tradeofferid)`
this declines a trade offer you **RECEIVED**
- `tradeofferid` is the id of the offer you want to confirm (you can get the id using [this](#get_trade_offerstime) to get the offerID
```ruby
require 'steam-trade'
logged = Handler.new('username','password','shared_secret')
logged.mobile_info('identity_secret')
time = '' # this is the initial check for offers so we want them all
polling = Thread.new(logged) { |logged|
loop do
offers = logged.get_trade_offers(time)
time = Time.new.to_i # we save the time of the last check
next if offers['trade_offers_received'] == nil # do nothing, if there is no trades
offers['trade_offers_received'].each { |trade| # we need to check received offers to use 'decline'
if trade['accountid_other'].to_i != 83905207 ## notice the '!='
logged.decline_trade_offer(trade['tradeofferid']) # decline the trade
end
}
sleep(15) # make sure not to spam steam's server or they will block list your IP for a period of time therefore you can't make requests
end
}
cancel_trade_offer(tradeofferid)
this cancels a trade offer you SENT
tradeofferid
is the id of the offer you want to confirm (you can get the id using this to get the offerIDtime = ‘’ # this is the initial check for offers so we want them all
polling = Thread.new(logged) { |logged|
loop do
offers = logged.get_trade_offers(time)
time = Time.new.to_i # we save the time of the last check
next if offers[‘trade_offers_sent’] == nil # do nothing, if there is no trades
offers[‘trade_offers_sent’].each { |trade| # we need to check sentoffers to use ‘cancel’
if trade[‘accountid_other’].to_i != 83905207 ## notice the ‘!=’
logged.cancel_trade_offer(trade[‘tradeofferid’]) # cancel the trade
end
}
sleep(15) # make sure not to spam steam’s server or they will block list your IP for a period of time therefore you can’t make requests
end
}
## Counting badges owned
#### `sets_count(target,non_marketable)`
**this command does not count foil badges (only normal trading cards)**
- `target` can be a steamID, a profileID or a trade link
- `non_marketable` this is a switch to count **non**-marketable trading cards(defaults to **true** if not specified)
- a .txt will be created from this command to read the badges
- this returns a hash `{'sets' => appsets, 'appxsets' => setsowned, 'totalsets' => numberofsets, 'totalcards' => total_non_foil, 'marketable' => true}`
- `'sets'` is a hash with game appids as keys and each card and number of copies owned of each card `{'appid1' => {'card1' => 5,'card2' => 3, ... 'cardN' => Z},{'appid1' => {'card1' => 0,'card2' => 2, ... 'cardN' => K} }`
- `'appxsets'` is a hash containing the number of sets available of each set `{'appid1' => 5,'appid2' => 20,...'appidN' => Z}`
- `'totalsets'` is an integer equals to the number of sets owned
- `'totalcards'` is an integer equals to the number of non-foil cards account for
```ruby
require 'steam-trade'
data = Handler.sets_count("CardExchange")
logged = Handler.new('username','password','shared_secret')
logged.mobile_info('identity_secret')
#with login
logged = account.sets_count()
logged = account.sets_count(false)
hash = account.sets_count('CardExchange',false)
hash = account.sets_count(76561198370420964)
hash = account.sets_count('https://steamcommunity.com/tradeoffer/new/?partner=410155236&token=H-yK-GFt',false)
#without login
nonlogged = Handler.new()
logged = account.sets_count() #raise exception
logged = account.sets_count(false) # raise exception
hash = account.sets_count('CardExchange')
hash = account.sets_count(76561198370420964)
hash = account.sets_count('https://steamcommunity.com/tradeoffer/new/?partner=410155236&token=H-yK-GFt',false)
update_blueprint()
handler = Handler.new
handler.update_blueprint()
## 2FA codes
#### `fa(shared_secret, time_difference)`
- `shared_secret` is the account's shared secret (if you don't know what is this try googling 'steam shared_secret'), defaults to the logged in account's steamid if logged in.
- `time_difference` is the difference between your pc's time and steam's time (**this MUST BE an integer**)
**NOTE**: using this command with a new shared_secret will not change/set the current saved shared_secret for the account
```ruby
require 'steam-trade'
puts Hander.fa('random_shared_secret')
logged = Handler.new('username','password','inital_shared_secret')
puts logged.fa() #=> random code for your account
puts logged.fa('new_shared_secret') # => this will give you a random code for another account, AND will not edit your initial_shared_secret
####
logged_without_shared_secret = Handler.new('username','password') # this is possible of course
puts logged_without_shared_secret.fa() # this will not work
puts logged_without_shared_secret.fa('shared_secret') ## will give a random code
###
nonlogged = Handler.new()
puts nonlogged.fa() # will not work
puts logged.fa() # will give a random code
mobile_login('username','password','shared_secret')
send_message()
or poll_messages()
without authenticationSteamMachine#{steamid}
cookie to use in oauth_login()
oauth_token
and machine
as keysh = Handler.new(‘user’,’pass’,’secret’)
data = h.mobile_login() #this works are you have setted username and password
puts data ## will output with oauth token and steamMachine cookie
h = Handler.new()
data = h.mobile_login() # will raise an error cause there is no username or password
h = Handler.new()
data = h.mobile_login(‘user’,’pass’,’secret’) ## will work, you are not logged in ( talking about community) here you can’t use most of the commands (send_offer() etc) and those parameters you passed will not be setted as the Handler’s
h = Handler.new(‘user1’,’pass1’,’secret1’)
data = mobile_login(‘user2’,’pass2’,’secret2’) # this works but trading commands etc will be called using user1, and chat commands will be called using user2
#### `oauth_login(oauth_token,SteamMachine)`
- `oauth_token` and `SteamMachine` can be retrieved from `mobile_login()`
```ruby
require 'steam-trade'
h = Handler.new()
h.oauth_login('oauth_token','SteamMachine')
send_message(target, message)
sends a message to the target
target
can be a steamID64, tradelink, or profileIDmessage
the message to sendh = Handler.new(‘username’, ‘password’)
h.send_message(‘nomg3r’, “Hello, Friend”)
#### `poll_messages()`
gives you the messages you receieved (after mobile login is initiated (after you call send_message() or poll_messages() ) )
```ruby
require 'steam-trade'
h = Handler.new('username', 'password')
print h.poll_messages() # will not return messages so you call at again ( only the first time in the whole program )
puts ""
puts "------"
sleep(10) #send a message to the logged in account
print h.poll_messages() # actually have messages ( if you received some in the time between the first and the second request )
ALL OF THE COMMANDS BELOW REQUIRES LOGIN
send_friend_request(target)
sends a friend request to the target
target
can be a steamID64, tradelink, or profileID
require 'steam-trade'
h = Handler.new('username', 'password')
h.send_friend_request('nomg3r')
accept_friend_request(target)
accepts a friend request from the target
target
can be a steamID64, tradelink, or profileID
require 'steam-trade'
h = Handler.new('username', 'password')
h.accept_friend_request('nomg3r')
remove_friend(target)
removes a friend
target
can be a steamID64, tradelink, or profileID
require 'steam-trade'
h = Handler.new('username', 'password')
h.remove_friend('nomg3r')
you can find more non-vital commands in the wiki
The gem is available as open source under the terms of the GNU GPLV3.