import requests # for HTTP requests
import bs4 # might be needed for parsing HTML at some point
import re # regular expressions
import traceback # debugging
from collections import defaultdict # because python's dictionary structure sucks
from xml.etree import ElementTree # parsing XML
# FILL IN THIS STUFF TO MAKE GO VROOM
APIKEY = "" # your API key goes here
sessionid = "" # your sessionid cookie goes here
steamLogin="" # your steam login cookie goes here
# Descriptive info for app IDs
def appName(appID):
appID = int(appID)
appDetails = defaultdict(str)
appDetails[753] = "Steam"
appDetails[440] = "Team Fortress 2"
appDetails[620] = "Portal 2"
appDetails[570] = "Dota 2"
appDetails[238460] = "BattleBlock Theater"
return appDetails[appID] if appDetails[appID] else "Unknown App" # this would be easy to hook up to an app id basis or use an API to do the lookup, but I only care for basic item info
# Descriptive info for context IDs within Steam
def contextName(appID, contextID):
if appID=="753":
contextID = int(contextID)
contextDetails = defaultdict(str)
contextDetails[1] = "Gift"
contextDetails[3] = "Coupon"
contextDetails[6] = "Community Item"
contextDetails[7] = "Item Reward"
return contextDetails[contextID] if contextDetails[contextID] else "Unknown Context"
else:
return "Game Item" # This is probably not true but maybe useful
# Reduces Steam market items (emoticons, backgrounds, cards) to base type:
def reduceType(marketText):
if "Profile Background" in marketText:
return "Profile Background"
elif "Emoticon" in marketText:
return "Emoticon"
elif "Trading Card" in marketText:
return "Trading Card"
else:
return marketText
def getItemsFromTradeOffers(xmldoc):
print "Begin loading items"
itemSet = defaultdict(list)
#print itemSet
try:
itemDescriptions = xmldoc.findall("descriptions")[0].findall("message")
except:
print "No items, no trades"
return itemSet
for item in itemDescriptions:
#print "Found item"
try:
appid = item.findall("appid")[0].text
appname = appName(appid)
classid = int(item.findall("classid")[0].text)
instanceid = item.findall("instanceid")[0].text
icon_url_large = item.findall("icon_url_large")[0].text
name = item.findall("name")[0].text.encode("ascii","ignore")
typeItem = reduceType(item.findall("type")[0].text.encode("ascii","ignore"))
if item.findall("descriptions"):
baseDescription = item.findall("descriptions")[0].findall("message")[0].findall("value")[0].text
if baseDescription:
baseDescription = baseDescription.encode("ascii","ignore")
else:
baseDescription = ""
else:
baseDescription = ""
itemSet[classid] = [appid, appname, classid, instanceid, icon_url_large, name, typeItem, baseDescription]
except:
print traceback.format_exc()
print item
pass
return itemSet
def getNameFromUserid(userid):
global APIKEY
print userid
u = requests.get("https://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key="+APIKEY+"&steamids="+str(userid)+"&format=xml")
tradeXML = u.text
xmldoc = ElementTree.fromstring(tradeXML)
players = xmldoc.findall("players")[0].findall("player")
if players is not None:
if len(players[0].findall("personaname")):
personaname = players[0].findall("personaname")[0].text
else:
personaname = "No username"
if len(players[0].findall("realname")):
realname = players[0].findall("realname")[0].text
else:
realname = personaname
print "Player Info: "+personaname+" ("+realname+")"
return 1
else:
print "Found no name"
return -1
def getTradeOffers():
global APIKEY
# Load, read, enter into XML parser
u = requests.get("https://api.steampowered.com/IEconService/GetTradeOffers/v0001/?key="+APIKEY+"&get_received_offers=1&get_descriptions=1&active_only=1&format=xml")
tradeXML = u.text
xmldoc = ElementTree.fromstring(tradeXML)
# Pre-load item information
itemSet = getItemsFromTradeOffers(xmldoc)
# Parse through trades
try:
tradeOffers = xmldoc.findall("trade_offers_received")[0].findall("message")
except:
print "No trades"
return
for tradeOffer in tradeOffers:
# Basic trade metadata
tradeOfferID = tradeOffer.findall("tradeofferid")[0].text
otherUser = int(tradeOffer.findall("accountid_other")[0].text)
otherUser += 76561197960265728 # 32-bit steamid to 64-bit steamid conversion, python implicitly switches int to long
getNameFromUserid(otherUser) # not necessary, might be useful for a log
trade_offer_state = int(tradeOffer.findall("trade_offer_state")[0].text)
message = tradeOffer.findall("message")[0].text
# Processing
print "BEGIN Trade "+tradeOfferID
# Trade error codes
if trade_offer_state==1:
print "ERROR on Trade "+tradeOfferID+": Invalid"
continue
elif trade_offer_state==3:
print "ERROR on Trade "+tradeOfferID+": Trade already accepted"
continue
elif trade_offer_state==4:
print "ERROR on Trade "+tradeOfferID+": Counter offer"
declineTrade(tradeOfferID)
continue
elif trade_offer_state==5:
print "ERROR on Trade "+tradeOfferID+": Trade expired"
continue
elif trade_offer_state==6:
print "ERROR on Trade "+tradeOfferID+": Trade cancelled"
continue
elif trade_offer_state==7:
print "ERROR on Trade "+tradeOfferID+": Trade already declined"
continue
elif trade_offer_state==8:
print "ERROR on Trade "+tradeOfferID+": Trade items messed up"
continue
# Now get details
giveItems = tradeOffer.findall("items_to_give")
if giveItems:
# Right now, any trade that requests items from me gets declined
print "ERROR on Trade "+tradeOfferID+": "+str(len(giveItems[0].findall("message")))+" items requested. Declining"
declineOffer(tradeOfferID)
continue
else:
#print "PROCESSING Trade "+tradeOfferID+": 0 items requested. Continuing."
pass
receiveItems = tradeOffer.findall("items_to_receive")[0]
if receiveItems is not None:
print "PROCESSING Trade "+tradeOfferID+": "+str(len(receiveItems.findall("message")))+" items being sent"
itemsReceiving = receiveItems.findall("message")
for item in itemsReceiving:
appid = item.findall("appid")[0].text
appname = appName(appid)
contextid = item.findall("contextid")[0].text
context = contextName(appid,contextid)
assetid = item.findall("assetid")[0].text
classid = int(item.findall("classid")[0].text)
instanceid = item.findall("instanceid")[0].text
amount = item.findall("amount")[0].text
# Get Item
print "Item: "+appid+" ("+appname+", context: "+contextid+" ["+context+"]). Class: "+str(classid)
if len(itemSet[classid]):
# Get better item description
imageURL = "http://steamcommunity-a.akamaihd.net/economy/image/"+itemSet[classid][4]+"/292x136"
print itemSet[classid][5]+" ("+itemSet[classid][6]+")"
else:
print "No better info found"
status = acceptOffer(tradeOfferID, otherUser)
if status==1:
return
else:
continue
else:
print "ERROR on Trade "+tradeOfferID+": No items included. Declining"
declineOffer(tradeOfferID)
continue
# Use API to decline offer
def declineOffer(tradeOfferID):
print "Attempting to decline "+str(tradeOfferID)
global APIKEY
data = {'key': APIKEY, 'tradeofferid': tradeOfferID}
u = requests.post("https://api.steampowered.com/IEconService/DeclineTradeOffer/v0001/", data=data)
response = u.read().lower()
if "error" in response:
print response
return -1
else:
return 0
return -1
# User scraping to accept offer
def acceptOffer(tradeOfferID, otherUser):
global sessionid, steamLogin
tradeOfferID = int(tradeOfferID)
data = {'sessionid': sessionid, 'tradeofferid': tradeOfferID, 'partner': str(otherUser)}
headers = {'referer': "http://steamcommunity.com/tradeoffer/"+str(tradeOfferID)+"/"}
cookies = dict(sessionid=sessionid,steamLogin=steamLogin)
r = requests.post("https://steamcommunity.com/tradeoffer/"+str(tradeOfferID)+"/accept",data=data,headers=headers,cookies=cookies)
if r.status_code==403:
print "Error, forbidden"
return -1
else:
print r.text
print "Accepted"
return 1
getTradeOffers()