├── .gitattributes ├── .github └── workflows │ └── python-publish.yml ├── .gitignore ├── .travis.yml ├── BackpackTF ├── __init__.py ├── __pycache__ │ ├── __init__.cpython-37.pyc │ ├── __init__.cpython-38.pyc │ ├── account.cpython-37.pyc │ ├── account.cpython-38.pyc │ ├── currency.cpython-37.pyc │ ├── currency.cpython-38.pyc │ ├── miscutils.cpython-37.pyc │ └── miscutils.cpython-38.pyc ├── account.py ├── currency.py └── miscutils.py ├── LICENSE ├── LICENSE.txt ├── README.md ├── _config.yml ├── examples ├── createListing.py ├── extractTradeUrl.py └── getItemPrice.py ├── setup.py └── tests ├── __pycache__ ├── test_miscutils.cpython-37-pytest-5.1.2.pyc ├── test_miscutils.cpython-38-pytest-6.0.1.pyc └── test_misutils.cpython-37-pytest-5.1.2.pyc └── test_miscutils.py /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.github/workflows/python-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflows will upload a Python Package using Twine when a release is created 2 | # For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries 3 | 4 | name: Upload Python Package 5 | 6 | on: 7 | release: 8 | types: [created] 9 | 10 | jobs: 11 | deploy: 12 | 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v2 17 | - name: Set up Python 18 | uses: actions/setup-python@v2 19 | with: 20 | python-version: '3.x' 21 | - name: Install dependencies 22 | run: | 23 | python -m pip install --upgrade pip 24 | pip install setuptools wheel twine 25 | - name: Build and publish 26 | env: 27 | TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} 28 | TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} 29 | run: | 30 | python setup.py sdist 31 | twine upload dist/* 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | test.py 3 | test.json 4 | .pytest_cache/* 5 | dist/* 6 | BackpackTF.egg-info/* -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: xenial 2 | language: python 3 | python: 4 | - "3.5" 5 | - "3.6" 6 | - "3.7" 7 | - "3.8-dev" 8 | - "nightly" 9 | 10 | matrix: 11 | allow_failures: 12 | - python: "3.8-dev" 13 | - python: "nightly" 14 | 15 | install: 16 | - pip install pytest 17 | 18 | before_script: 19 | - "python setup.py install" 20 | 21 | script: 22 | - pytest tests/test_miscutils.py 23 | -------------------------------------------------------------------------------- /BackpackTF/__init__.py: -------------------------------------------------------------------------------- 1 | from BackpackTF.currency import Currency 2 | from BackpackTF.account import Account 3 | from BackpackTF.miscutils import MiscUtils 4 | -------------------------------------------------------------------------------- /BackpackTF/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidteather/BackpackTf-API/2019881f84669d2a660f0eab721b4ad43c0a9bf2/BackpackTF/__pycache__/__init__.cpython-37.pyc -------------------------------------------------------------------------------- /BackpackTF/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidteather/BackpackTf-API/2019881f84669d2a660f0eab721b4ad43c0a9bf2/BackpackTF/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /BackpackTF/__pycache__/account.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidteather/BackpackTf-API/2019881f84669d2a660f0eab721b4ad43c0a9bf2/BackpackTF/__pycache__/account.cpython-37.pyc -------------------------------------------------------------------------------- /BackpackTF/__pycache__/account.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidteather/BackpackTf-API/2019881f84669d2a660f0eab721b4ad43c0a9bf2/BackpackTF/__pycache__/account.cpython-38.pyc -------------------------------------------------------------------------------- /BackpackTF/__pycache__/currency.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidteather/BackpackTf-API/2019881f84669d2a660f0eab721b4ad43c0a9bf2/BackpackTF/__pycache__/currency.cpython-37.pyc -------------------------------------------------------------------------------- /BackpackTF/__pycache__/currency.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidteather/BackpackTf-API/2019881f84669d2a660f0eab721b4ad43c0a9bf2/BackpackTF/__pycache__/currency.cpython-38.pyc -------------------------------------------------------------------------------- /BackpackTF/__pycache__/miscutils.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidteather/BackpackTf-API/2019881f84669d2a660f0eab721b4ad43c0a9bf2/BackpackTF/__pycache__/miscutils.cpython-37.pyc -------------------------------------------------------------------------------- /BackpackTF/__pycache__/miscutils.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidteather/BackpackTf-API/2019881f84669d2a660f0eab721b4ad43c0a9bf2/BackpackTF/__pycache__/miscutils.cpython-38.pyc -------------------------------------------------------------------------------- /BackpackTF/account.py: -------------------------------------------------------------------------------- 1 | from requests_oauthlib import OAuth2Session 2 | from oauthlib.oauth2 import TokenExpiredError 3 | import requests 4 | import urllib.parse 5 | import json 6 | import requests 7 | from lxml import html 8 | 9 | 10 | class Account: 11 | # 12 | # Inital Thing 13 | # 14 | def __init__(self, client_id, client_secret, api_key): 15 | # Self Things 16 | self.api_key = api_key 17 | self.client_id = client_id 18 | self.client_secret = client_secret 19 | 20 | # Gets The Token 21 | client = BackendApplicationClient(client_id=self.client_id) 22 | oauth = OAuth2Session(client=client) 23 | token = oauth.fetch_token( 24 | token_url="https://backpack.tf/oauth/access_token", 25 | client_id=self.client_id, 26 | client_secret=self.client_secret, 27 | ) 28 | 29 | self.token = token 30 | 31 | # 32 | # Gets a listing by id 33 | # 34 | # id - the listing's ID 35 | # 36 | def get_listing(self, listing_id=0): 37 | try: 38 | client = OAuth2Session(self.client_id, token=self.token) 39 | r = client.get( 40 | "https://backpack.tf/api/1.0/classifieds/listings/" + str(listing_id) 41 | ) 42 | 43 | except TokenExpiredError as e: 44 | token = client.post("https://backpack.tf/oauth/access_token") 45 | self.token = token 46 | 47 | client = OAuth2Session(self.client_id, token=self.token) 48 | r = client.get( 49 | "https://backpack.tf/api/1.0/classifieds/listings/" + str(listing_id) 50 | ) 51 | 52 | return r.text 53 | 54 | # alias for compatibility with older versions 55 | # please use the new name, "get_listing" 56 | getListing = get_listing 57 | 58 | # 59 | # Delete a listing by ID 60 | # 61 | # id - the listing's ID 62 | # 63 | def delete_listing(self, listing_id=0): 64 | try: 65 | client = OAuth2Session(self.client_id, token=self.token) 66 | r = client.delete( 67 | "https://backpack.tf/api/1.0/classifieds/listings/" + str(listing_id) 68 | ) 69 | 70 | except TokenExpiredError as e: 71 | token = client.post("https://backpack.tf/oauth/access_token") 72 | self.token = token 73 | 74 | client = OAuth2Session(self.client_id, token=self.token) 75 | r = client.delete( 76 | "https://backpack.tf/api/1.0/classifieds/listings/" + str(listing_id) 77 | ) 78 | 79 | return r.text 80 | 81 | # alias for compatibility with older versions 82 | # please use the new name, "delete_listing" 83 | deleteListing = delete_listing 84 | 85 | # 86 | # Create a listing 87 | # 88 | # intent - 0 (Buy) or 1 (Sell) 89 | # id - if intent is 1, the current id of the id you want to list 90 | # If buy order 91 | # item_name - the item's name you want to buy 92 | # quality - either the number or the text 93 | # craftable - 0 or 1 94 | # offers - set to 0 for only accepting friend requests 95 | # buyout - set to 0 to allow negotiation 96 | # promoted - set to 1 to promote it, must be premium 97 | # details - the listing comment, max 200 characters 98 | # currencies - json of the currency EX: {"metal": 23} 99 | # PriceIndex - Most items is 0, however particle effects is the ID of the particle effect 100 | # for crates it corresponds to the crate series, for strangifiers/unusualifiers is the 101 | # definition index of the item it can be used on, chemistry set is a hyphented 102 | # definition index 1086-14 is the index for a collector's festive wrangler 103 | # here's a link to an item http://prntscr.com/pf2s0h 104 | # 105 | # returns int: 0 or 1, states the success of the listing 106 | # 107 | def create_listing( 108 | self, 109 | intent=0, 110 | id=0, 111 | quality=6, 112 | item_name="", 113 | craftable=1, 114 | priceindex=0, 115 | offers=0, 116 | buyout=1, 117 | promoted=0, 118 | details="", 119 | currencies={"metal": 0}, 120 | account_token="", 121 | ): 122 | if intent == 0: 123 | payload = { 124 | "token": account_token, 125 | "listings": [ 126 | { 127 | "intent": str(intent), 128 | "item": { 129 | "quality": str(quality), 130 | "item_name": item_name, 131 | "craftable": str(craftable), 132 | "priceindex": str(priceindex), 133 | }, 134 | "offers": str(offers), 135 | "buyout": str(buyout), 136 | "promoted": str(promoted), 137 | "details": str(details), 138 | "currencies": currencies, 139 | } 140 | ], 141 | } 142 | else: 143 | payload = { 144 | "token": account_token, 145 | "listings": [ 146 | { 147 | "id": str(id), 148 | "intent": str(intent), 149 | "offers": str(offers), 150 | "buyout": str(buyout), 151 | "promoted": str(promoted), 152 | "details": str(details), 153 | "currencies": currencies, 154 | } 155 | ], 156 | } 157 | 158 | r = requests.post("https://backpack.tf/api/classifieds/list/v1", json=payload) 159 | 160 | jsonResponse = json.loads(r.text) 161 | 162 | try: 163 | return int(jsonResponse["listings"][item_name]["created"]) 164 | except: 165 | return jsonResponse 166 | 167 | # alias for compatibility with older versions 168 | # please use the new name, "create_listing" 169 | createListing = create_listing 170 | 171 | # 172 | # This function searches for classified listings 173 | # 174 | # intent - either sell, buy, or both 175 | # page_size - the results / page 0 < page_size <= 30 176 | # page - the page number you want to view 177 | # fold - if set 0 disables listing folding 178 | # item_name - the name of the item you want to search for 179 | # steamid - the steam id of the user who you want to check their listings 180 | # tradable - 0/1 181 | # craftable - 0/1 182 | # australium - 0/1 183 | # wear_tier - 1-5 for tier of skin wear, in order - factory new, minimal wear, field-tested, well-worn, battle scared 184 | # texture_name - required to search by wear_tier, the name of the skin / texture to search by 185 | # quality - the integer of the quality to search by use MiscUtils.qualityStringToInt("unique") to get it 186 | # paint - the paint's ID to search by, TODO: add a function to find the paint ID 187 | # particle - particle ID effect, TODO: add a function to find the particle ID from string 188 | # killstreak_tier - 1-3, in order standard, specialized, professional 189 | # sheen - 0-7, in order team shine, deadly daffodil, manndarin, mean green, agonizing emerald, villainous violet, hot rod 190 | # killstreaker - the id of the killstreaker 191 | # 192 | def search_classifieds( 193 | self, 194 | intent="dual", 195 | page_size=10, 196 | fold=1, 197 | item_name="", 198 | steamid="", 199 | tradable="", 200 | craftable="", 201 | australium="", 202 | wear_tier="", 203 | quality="", 204 | paint="", 205 | particle="", 206 | killstreak_tier="", 207 | sheen="", 208 | killstreaker="", 209 | page=0, 210 | texture_name="", 211 | ): 212 | payload = { 213 | "key": self.api_key, 214 | "intent": intent, 215 | "texture_name": texture_name, 216 | "page": str(page), 217 | "page_size": str(page_size), 218 | "fold": str(fold), 219 | "item": item_name, 220 | "steamid": str(steamid), 221 | "tradable": str(tradable), 222 | "craftable": str(craftable), 223 | "australium": str(australium), 224 | "wear_tier": str(wear_tier), 225 | "quality": str(quality), 226 | "paint": str(paint), 227 | "particle": str(particle), 228 | "killstreak_tier": str(killstreak_tier), 229 | "sheen": str(sheen), 230 | "killstreaker": str(killstreaker), 231 | } 232 | 233 | encoded = urllib.parse.urlencode(payload) 234 | 235 | r = requests.get("https://backpack.tf/api/classifieds/search/v1?" + encoded) 236 | jsondata = json.loads(r.text) 237 | 238 | return jsondata 239 | 240 | # alias for compatibility with older verisions 241 | # please use the new function name, "search_classifieds" (lowercase c) 242 | search_Classifieds = search_classifieds 243 | 244 | # 245 | # This function extracts the trade url. 246 | # 247 | # listingJSON - the JSON object from the search_listings under whatever the listing thing you use is. 248 | # 249 | def extract_trade_url(self, listingJSON, proxy=None): 250 | payload = { 251 | "item": listingJSON["item"]["name"], 252 | "steamid": listingJSON["steamid"], 253 | "quality": listingJSON["item"]["quality"], 254 | } 255 | 256 | encoded = urllib.parse.urlencode(payload) 257 | 258 | if proxy == None: 259 | r = requests.get( 260 | "https://backpack.tf/classifieds?" + encoded.replace("+", "%20") 261 | ) 262 | else: 263 | r = requests.get( 264 | "https://backpack.tf/classifieds?" + encoded.replace("+", "%20"), 265 | proxies=proxy, 266 | ) 267 | 268 | with open("test.html", "w+", encoding="utf-8") as thing: 269 | thing.write(r.text) 270 | 271 | tree = html.fromstring(r.text) 272 | 273 | try: 274 | url = tree.xpath( 275 | "//li[@id='listing-" 276 | + listingJSON["id"] 277 | + "']/div[@class='listing-item']/div" 278 | )[0].get("data-listing_offers_url") 279 | return url 280 | except: 281 | raise IndexError("List index out of range") 282 | -------------------------------------------------------------------------------- /BackpackTF/currency.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import json 3 | import urllib.parse 4 | 5 | 6 | class Currency: 7 | # 8 | # Documentation for the backpack.tf API https://backpack.tf/api/index.html#/ 9 | # 10 | def __init__(self, apikey): 11 | self.api_key = apikey 12 | 13 | self.standard_params = {"appid": "440", "key": self.api_key} 14 | 15 | # 16 | # Function Returns A JSON of the value of currencies 17 | # 18 | def get_currencies(self): 19 | currencies = requests.get( 20 | "https://backpack.tf/api/IGetCurrencies/v1?key=" + self.api_key 21 | ) 22 | currencyJSON = json.loads(currencies.text) 23 | if ( 24 | currencyJSON["response"]["success"] == "1" 25 | or currencyJSON["response"]["success"] == 1 26 | ): 27 | return currencyJSON["response"]["currencies"] 28 | else: 29 | raise Exception("Your API key is invalid") 30 | 31 | # alias for compatibility with older versions 32 | # please use the new name, "get_currencies" 33 | getCurrencies = get_currencies 34 | 35 | # 36 | # Gets Price History of a specific item in an array of previous values 37 | # 38 | # Name - The item's base name 39 | # Quality - The item's quality, Strange, Unique, Unusual 40 | # Craftable - Get the item's craftable or not 0 or 1 41 | # Tradable - get the item's tradable status 42 | # PriceIndex - Most items is 0, however particle effects is the ID of the particle effect 43 | # for crates it corresponds to the crate series, for strangifiers/unusualifiers is the 44 | # definition index of the item it can be used on, chemistry set is a hyphented 45 | # definition index 1086-14 is the index for a collector's festive wrangler 46 | # here's a link to an item http://prntscr.com/pf2s0h 47 | # 48 | 49 | def price_history(self, **kwargs): 50 | kwargs.update(self.standard_params) 51 | encoded = urllib.parse.urlencode(kwargs) 52 | 53 | r = requests.get("https://backpack.tf/api/IGetPriceHistory/v1?" + encoded) 54 | jsondata = json.loads(r.text) 55 | 56 | success = False 57 | try: 58 | if ( 59 | jsondata["response"]["success"] == 1 60 | or jsondata["response"]["success"] == "1" 61 | ): 62 | success = True 63 | except: 64 | return jsondata 65 | 66 | if success: 67 | return jsondata["response"]["history"] 68 | else: 69 | raise Exception("Unsuccessful Request") 70 | 71 | # alias for compatibility with older versions 72 | # please use the new name, "price_history" 73 | priceHistory = price_history 74 | 75 | # 76 | # Gets Price of a specific item 77 | # 78 | # Name - The item's base name 79 | # Quality - The item's quality, Strange, Unique, Unusual 80 | # Craftable - Get the item's craftable or not 0 or 1 81 | # Tradable - get the item's tradable status 82 | # PriceIndex - Not really sure to be honest 83 | # 84 | 85 | def item_price(self, **kwargs): 86 | kwargs.update(self.standard_params) 87 | encoded = urllib.parse.urlencode(kwargs) 88 | r = requests.get("https://backpack.tf/api/IGetPriceHistory/v1?" + encoded) 89 | jsondata = json.loads(r.text) 90 | 91 | success = False 92 | try: 93 | if ( 94 | jsondata["response"]["success"] == 1 95 | or jsondata["response"]["success"] == "1" 96 | ): 97 | success = True 98 | except: 99 | return jsondata 100 | 101 | if success: 102 | return jsondata["response"]["history"][ 103 | len(jsondata["response"]["history"]) - 1 104 | ] 105 | else: 106 | raise Exception("Request Unsuccessful.") 107 | 108 | # alias for compatibility with older versions 109 | # please use the new name, "item_price" 110 | itemPrice = item_price 111 | 112 | # 113 | # Gets all prices, requires an elevated API key 114 | # 115 | # Since - Only prices that have been updated since the unix EPOCH will be shown 116 | # 117 | 118 | def get_all_prices(self, raw=2, since=0): 119 | 120 | r = requests.get( 121 | "https://backpack.tf/api/IGetPrices/v4?raw=" 122 | + str(raw) 123 | + "&since=" 124 | + str(since) 125 | + "&key=" 126 | + self.api_key 127 | ) 128 | jsondata = json.loads(r.text) 129 | 130 | success = False 131 | try: 132 | if ( 133 | jsondata["response"]["success"] == 1 134 | or jsondata["response"]["success"] == "1" 135 | ): 136 | success = True 137 | except: 138 | return jsondata 139 | 140 | if success: 141 | return jsondata["response"] 142 | else: 143 | raise Exception("Unsuccessful Request") 144 | 145 | # alias for compatibility with older versions 146 | # please use the new name, "get_all_prices" 147 | getAllPrices = get_all_prices 148 | -------------------------------------------------------------------------------- /BackpackTF/miscutils.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import json 3 | import struct 4 | 5 | 6 | class MiscUtils: 7 | def __init__(self, obj=None, use_cached=True): 8 | if use_cached != True: 9 | r = requests.get("https://backpack.tf/filters") 10 | 11 | obj = json.loads(r.text) 12 | 13 | else: 14 | # cached because backpacktf has cloudflare for some reason 15 | if obj == None: 16 | obj = {"quality":[{"id":"14","color":"830000","name":"Collector's"},{"id":"15","color":"fafafa","name":"Decorated Weapon"},{"id":"1","color":"4D7455","name":"Genuine"},{"id":"13","color":"38F3AB","name":"Haunted"},{"id":"0","color":"B2B2B2","name":"Normal"},{"id":"9","color":"70B04A","name":"Self-Made"},{"id":"11","color":"CF6A32","name":"Strange"},{"id":"6","color":"FFD700","name":"Unique"},{"id":"5","color":"8650AC","name":"Unusual"},{"id":"3","color":"476291","name":"Vintage"}],"particle":[{"id":"3004","name":"'72"},{"id":"91","name":"Abduction"},{"id":"125","name":"Abyssal Aura"},{"id":"3024","name":"Accursed"},{"id":"59","name":"Aces High"},{"id":"3017","name":"Acidic Bubbles of Envy"},{"id":"82","name":"Amaranthine"},{"id":"98","name":"Ancient Codex"},{"id":"105","name":"Ancient Eldritch"},{"id":"69","name":"Anti-Freeze"},{"id":"3047","name":"Arachnid Assault"},{"id":"73","name":"Arcana"},{"id":"3039","name":"Arcane Assistance"},{"id":"3040","name":"Arcane Assistance"},{"id":"3033","name":"Arctic Aurora"},{"id":"148","name":"Aromatica"},{"id":"3038","name":"Astral Presence"},{"id":"92","name":"Atomic"},{"id":"151","name":"Bee Swarm"},{"id":"3023","name":"Bewitched"},{"id":"30","name":"Blizzardy Storm"},{"id":"81","name":"Bonzo The All-Gnawing"},{"id":"111","name":"Brain Drain"},{"id":"34","name":"Bubbling"},{"id":"13","name":"Burning Flames"},{"id":"39","name":"Cauldron Bubbles"},{"id":"75","name":"Chiroptera Venenata"},{"id":"149","name":"Chromatica"},{"id":"19","name":"Circling Heart"},{"id":"18","name":"Circling Peace Sign"},{"id":"11","name":"Circling TF Logo"},{"id":"121","name":"Clairvoyance"},{"id":"58","name":"Cloud 9"},{"id":"38","name":"Cloudy Moon"},{"id":"4","name":"Community Sparkle"},{"id":"703","name":"Cool"},{"id":"3048","name":"Creepy Crawlies"},{"id":"79","name":"Darkblaze"},{"id":"60","name":"Dead Presidents"},{"id":"90","name":"Death at Dusk"},{"id":"100","name":"Death by Disco"},{"id":"139","name":"Defragmenting Reality"},{"id":"80","name":"Demonflame"},{"id":"62","name":"Disco Beat Down"},{"id":"3027","name":"Eerie Lightning"},{"id":"40","name":"Eerie Orbiting Fire"},{"id":"106","name":"Eldritch Flame"},{"id":"94","name":"Electric Hat Protector"},{"id":"67","name":"Electrostatic"},{"id":"3041","name":"Emerald Allurement"},{"id":"3025","name":"Enchanted"},{"id":"704","name":"Energy Orb"},{"id":"103","name":"Ether Trail"},{"id":"129","name":"Ethereal Essence"},{"id":"3035","name":"Festive Spirit"},{"id":"122","name":"Fifth Dimension"},{"id":"37","name":"Flaming Lantern"},{"id":"3018","name":"Flammable Bubbles of Attraction"},{"id":"3005","name":"Fountain of Delight"},{"id":"136","name":"Fragmented Gluons"},{"id":"138","name":"Fragmented Photons"},{"id":"137","name":"Fragmented Quarks"},{"id":"141","name":"Fragmenting Reality"},{"id":"152","name":"Frisky Fireflies"},{"id":"87","name":"Frostbite"},{"id":"135","name":"Frozen Icefall"},{"id":"97","name":"Galactic Codex"},{"id":"114","name":"Galactic Gateway"},{"id":"28","name":"Genteel Smoke"},{"id":"3012","name":"Ghastly Ghosts"},{"id":"85","name":"Ghastly Ghosts Jr"},{"id":"127","name":"Ghastly Grove"},{"id":"3031","name":"Good-Hearted Goodies"},{"id":"162","name":"Gourdian Angel"},{"id":"160","name":"Gravelly Ghoul"},{"id":"71","name":"Green Black Hole"},{"id":"6","name":"Green Confetti"},{"id":"9","name":"Green Energy"},{"id":"156","name":"Green Giggler"},{"id":"45","name":"Harvest Moon"},{"id":"8","name":"Haunted Ghosts"},{"id":"3011","name":"Haunted Phantasm"},{"id":"86","name":"Haunted Phantasm Jr"},{"id":"113","name":"Head of Steam"},{"id":"78","name":"Hellfire"},{"id":"3013","name":"Hellish Inferno"},{"id":"3003","name":"Holy Grail"},{"id":"701","name":"Hot"},{"id":"3015","name":"Infernal Flames"},{"id":"3016","name":"Infernal Smoke"},{"id":"702","name":"Isotope"},{"id":"46","name":"It's A Secret To Everybody"},{"id":"101","name":"It's a mystery to everyone"},{"id":"102","name":"It's a puzzle to me"},{"id":"3029","name":"Jarate Shock"},{"id":"155","name":"Kaleidoscope"},{"id":"56","name":"Kill-a-Watt"},{"id":"43","name":"Knifestorm"},{"id":"157","name":"Laugh-O-Lantern"},{"id":"3036","name":"Magical Spirit"},{"id":"95","name":"Magnetic Hat Protector"},{"id":"12","name":"Massed Flies"},{"id":"3010","name":"Mega Strike"},{"id":"65","name":"Memory Leak"},{"id":"124","name":"Menacing Miasma"},{"id":"61","name":"Miami Nights"},{"id":"3008","name":"Midnight Whirlwind"},{"id":"44","name":"Misty Skull"},{"id":"88","name":"Molten Mallard"},{"id":"89","name":"Morning Glory"},{"id":"128","name":"Mystical Medley"},{"id":"99","name":"Nebula"},{"id":"104","name":"Nether Trail"},{"id":"3030","name":"Nether Void"},{"id":"107","name":"Neutron Star"},{"id":"31","name":"Nuts n' Bolts"},{"id":"3022","name":"Ominous Night"},{"id":"120","name":"Omniscient Orb"},{"id":"112","name":"Open Mind"},{"id":"33","name":"Orbiting Fire"},{"id":"32","name":"Orbiting Planets"},{"id":"66","name":"Overclocked"},{"id":"63","name":"Phosphorous"},{"id":"158","name":"Plum Prankster"},{"id":"76","name":"Poisoned Shadows"},{"id":"3019","name":"Poisonous Bubbles of Regret"},{"id":"68","name":"Power Surge"},{"id":"150","name":"Prismatica"},{"id":"163","name":"Pumpkin Party"},{"id":"7","name":"Purple Confetti"},{"id":"10","name":"Purple Energy"},{"id":"145","name":"Pyroland Daydream"},{"id":"159","name":"Pyroland Nightmare"},{"id":"3042","name":"Pyrophoric Personality"},{"id":"142","name":"Refragmenting Reality"},{"id":"117","name":"Ring of Fire"},{"id":"3020","name":"Roaring Rockets"},{"id":"72","name":"Roboactive"},{"id":"14","name":"Scorching Flames"},{"id":"3006","name":"Screaming Tiger"},{"id":"15","name":"Searing Plasma"},{"id":"3001","name":"Showstopper"},{"id":"3009","name":"Silver Cyclone"},{"id":"3007","name":"Skill Gotten Gains"},{"id":"35","name":"Smoking"},{"id":"153","name":"Smoldering Spirits"},{"id":"144","name":"Snowblinded"},{"id":"143","name":"Snowfallen"},{"id":"77","name":"Something Burning This Way Comes"},{"id":"134","name":"Sparkling Lights"},{"id":"3037","name":"Spectral Escort"},{"id":"3014","name":"Spectral Swirl"},{"id":"74","name":"Spellbound"},{"id":"3043","name":"Spellbound Aspect"},{"id":"3021","name":"Spooky Night"},{"id":"83","name":"Stare From Beyond"},{"id":"109","name":"Starstorm Insomnia"},{"id":"110","name":"Starstorm Slumber"},{"id":"3026","name":"Static Mist"},{"id":"3044","name":"Static Shock"},{"id":"36","name":"Steaming"},{"id":"47","name":"Stormy 13th Hour"},{"id":"29","name":"Stormy Storm"},{"id":"93","name":"Subatomic"},{"id":"64","name":"Sulphurous"},{"id":"17","name":"Sunbeams"},{"id":"3028","name":"Terrifying Thunder"},{"id":"57","name":"Terror-Watt"},{"id":"108","name":"Tesla Coil"},{"id":"116","name":"The Dark Doorway"},{"id":"115","name":"The Eldritch Opening"},{"id":"84","name":"The Ooze"},{"id":"70","name":"Time Warp"},{"id":"3046","name":"Toxic Terrors"},{"id":"130","name":"Twisted Radiance"},{"id":"133","name":"Valiant Vortex"},{"id":"3045","name":"Veno Shock"},{"id":"132","name":"Verdant Vortex"},{"id":"147","name":"Verdatica"},{"id":"161","name":"Vexed Volcanics"},{"id":"118","name":"Vicious Circle"},{"id":"123","name":"Vicious Vortex"},{"id":"131","name":"Violet Vortex"},{"id":"16","name":"Vivid Plasma"},{"id":"96","name":"Voltaic Hat Protector"},{"id":"154","name":"Wandering Wisps"},{"id":"119","name":"White Lightning"},{"id":"126","name":"Wicked Wood"},{"id":"3034","name":"Winter Spirit"},{"id":"3032","name":"Wintery Wisp"}],"rarity":[{"id":"99","color":"FFD700","name":""},{"id":"5","color":"D32CE6","name":"Assassin"},{"id":"1","color":"B0C3D9","name":"Civilian"},{"id":"4","color":"8847FF","name":"Commando"},{"id":"6","color":"EB4B4B","name":"Elite"},{"id":"2","color":"5E98D9","name":"Freelance"},{"id":"7","color":"E4AE39","name":"Immortal"},{"id":"3","color":"4B69FF","name":"Mercenary"},{"id":"0","color":"6A6156","name":"Stock"}],"paint":[{"id":3100495,"color":"2f4f4f","name":"A Color Similar to Slate"},{"id":8208497,"color":"7d4071","name":"A Deep Commitment to Purple"},{"id":1315860,"color":"141414","name":"A Distinctive Lack of Hue"},{"id":12377523,"color":"bcddb3","name":"A Mann's Mint"},{"id":2960676,"color":"2d2d24","name":"After Eight"},{"id":8289918,"color":"7e7e7e","name":"Aged Moustache Grey"},{"id":6637376,"color":"654740","name":"An Air of Debonair"},{"id":15132390,"color":"e6e6e6","name":"An Extraordinary Abundance of Tinge"},{"id":15185211,"color":"e7b53b","name":"Australium Gold"},{"id":3874595,"color":"3b1f23","name":"Balaclavas Are Forever"},{"id":14204632,"color":"d8bed8","name":"Color No. 216-190-216"},{"id":12807213,"color":"c36c2d","name":"Cream Spirit"},{"id":15308410,"color":"e9967a","name":"Dark Salmon Injustice"},{"id":8421376,"color":"808000","name":"Drably Olive"},{"id":7511618,"color":"729e42","name":"Indubitably Green"},{"id":13595446,"color":"cf7336","name":"Mann Co. Orange"},{"id":10843461,"color":"a57545","name":"Muskelmannbraun"},{"id":5322826,"color":"51384a","name":"Noble Hatter's Violet"},{"id":4732984,"color":"483838","name":"Operator's Overalls"},{"id":12955537,"color":"c5af91","name":"Peculiarly Drab Tincture"},{"id":16738740,"color":"ff69b4","name":"Pink as Hell"},{"id":6901050,"color":"694d3a","name":"Radigan Conagher Brown"},{"id":12073019,"color":"b8383b","name":"Team Spirit"},{"id":3329330,"color":"32cd32","name":"The Bitter Taste of Defeat and Lime"},{"id":15787660,"color":"f0e68c","name":"The Color of a Gentlemann's Business Pants"},{"id":8400928,"color":"803020","name":"The Value of Teamwork"},{"id":11049612,"color":"a89a8c","name":"Waterlogged Lab Coat"},{"id":8154199,"color":"7c6c57","name":"Ye Olde Rustic Colour"},{"id":4345659,"color":"424f3b","name":"Zepheniah's Greed"}],"spell_footsteps":[{"id":"8208497","color":"490623","name":"Halloween Spell: Bruised Purple Footprints","defindex":8919},{"id":"3100495","color":"100495","name":"Halloween Spell: Corpse Gray Footprints","defindex":8916},{"id":"8421376","color":"9168","name":"Halloween Spell: Gangreen Footprints","defindex":8915},{"id":"2","color":"109759","name":"Halloween Spell: Headless Horseshoes","defindex":8920},{"id":"13595446","color":"6737280","name":"Halloween Spell: Rotten Orange Footprints","defindex":8918},{"id":"1","color":"4540032","name":"Halloween Spell: Team Spirit Footprints","defindex":8914},{"id":"5322826","color":"6742399","name":"Halloween Spell: Violent Violet Footprints","defindex":8917}],"spell_paints":[{"id":"1","color":"6711680","name":"Halloween Spell: Chromatic Corruption","defindex":8902},{"id":"0","color":"55","name":"Halloween Spell: Die Job","defindex":8901},{"id":"2","color":"5280","name":"Halloween Spell: Putrescent Pigmentation","defindex":8900},{"id":"4","color":"6776960","name":"Halloween Spell: Sinister Staining","defindex":8904},{"id":"3","color":"6744192","name":"Halloween Spell: Spectral Spectrum","defindex":8903}],"origin":[{"id":"1","name":"Achievement"},{"id":"15","name":"CD Key"},{"id":"27","name":"CYOA Blood Money Purchase"},{"id":"16","name":"Collection Reward"},{"id":"23","name":"Contract Completion Reward"},{"id":"4","name":"Crafted"},{"id":"9","name":"Earned"},{"id":"14","name":"Foreign Item"},{"id":"8","name":"Found in Crate"},{"id":"6","name":"Gifted"},{"id":"12","name":"Halloween Drop"},{"id":"20","name":"MvM Badge completion reward"},{"id":"21","name":"MvM Squad surplus reward"},{"id":"19","name":"Periodic score reward"},{"id":"17","name":"Preview Item"},{"id":"2","name":"Purchased"},{"id":"22","name":"Recipe output"},{"id":"13","name":"Steam Purchase"},{"id":"18","name":"Steam Workshop Contribution"},{"id":"5","name":"Store Promotion"},{"id":"7","name":"Support Granted"},{"id":"10","name":"Third-Party Promotion"},{"id":"0","name":"Timed Drop"},{"id":"25","name":"Trade-Up"},{"id":"24","name":"Trade-Up Output"},{"id":"3","name":"Traded"},{"id":"29","name":"Untradable Free Contract Reward"},{"id":"26","name":"Viral Competitive Beta Pass Spread"},{"id":"28","name":"War Paint"},{"id":"11","name":"Wrapped Gift"}],"numerics":[{"name":"Crate Series","field":"crate"},{"name":"Level","field":"level"},{"name":"Medal #","field":"medal"},{"name":"Craft #","field":"craft_number"}],"show_tradable":True,"show_craftable":True,"wear_tiers":{"Factory New":{"id":1,"name":"Factory New"},"Minimal Wear":{"id":2,"name":"Minimal Wear"},"Field-Tested":{"id":3,"name":"Field-Tested"},"Well-Worn":{"id":4,"name":"Well-Worn"},"Battle Scarred":{"id":5,"name":"Battle Scarred"}},"show_australium":True,"show_slot":True,"show_class":True,"show_killstreak_tab":True,"killstreakers":[{"id":2002,"name":"Fire Horns"},{"id":2003,"name":"Cerebral Discharge"},{"id":2004,"name":"Tornado"},{"id":2005,"name":"Flames"},{"id":2006,"name":"Singularity"},{"id":2007,"name":"Incinerator"},{"id":2008,"name":"Hypno-Beam"}],"sheens":[{"id":1,"name":"Team Shine"},{"id":2,"name":"Deadly Daffodil"},{"id":3,"name":"Manndarin"},{"id":4,"name":"Mean Green"},{"id":5,"name":"Agonizing Emerald"},{"id":6,"name":"Villainous Violet"},{"id":7,"name":"Hot Rod"}],"killstreak_tiers":[{"id":0,"name":"None"},{"id":1,"name":"Standard"},{"id":2,"name":"Specialized"},{"id":3,"name":"Professional"}],"strange_parts":[{"id":22,"name":"Airborne Enemies Killed"},{"id":84,"name":"Allied Healing Done"},{"id":95,"name":"Assists"},{"id":19,"name":"Buildings Destroyed"},{"id":79,"name":"Burning Enemy Kills"},{"id":37,"name":"Cloaked Spies Killed"},{"id":33,"name":"Critical Kills"},{"id":82,"name":"Damage Dealt"},{"id":47,"name":"Defender Kills"},{"id":13,"name":"Demomen Killed"},{"id":28,"name":"Domination Kills"},{"id":17,"name":"Engineers Killed"},{"id":83,"name":"Fires Survived"},{"id":81,"name":"Freezecam Taunt Appearances"},{"id":88,"name":"Full Health Kills"},{"id":27,"name":"Full Moon Kills"},{"id":40,"name":"Giant Robots Destroyed"},{"id":23,"name":"Gib Kills"},{"id":45,"name":"Halloween Kills"},{"id":21,"name":"Headshot Kills"},{"id":14,"name":"Heavies Killed"},{"id":87,"name":"Kills"},{"id":67,"name":"Kills During Victory Time"},{"id":34,"name":"Kills While Explosive Jumping"},{"id":49,"name":"Kills While \u00dcbercharged"},{"id":77,"name":"Kills with a Taunt Attack"},{"id":80,"name":"Killstreaks Ended"},{"id":62,"name":"Long-Distance Kills"},{"id":44,"name":"Low-Health Kills"},{"id":18,"name":"Medics Killed"},{"id":38,"name":"Medics Killed That Have Full \u00dcberCharge"},{"id":93,"name":"Not Crit nor MiniCrit Kills"},{"id":94,"name":"Player Hits"},{"id":85,"name":"Point-Blank Kills"},{"id":31,"name":"Posthumous Kills"},{"id":20,"name":"Projectiles Reflected"},{"id":15,"name":"Pyros Killed"},{"id":30,"name":"Revenge Kills"},{"id":68,"name":"Robot Scouts Destroyed"},{"id":74,"name":"Robot Spies Destroyed"},{"id":39,"name":"Robots Destroyed"},{"id":46,"name":"Robots Destroyed During Halloween"},{"id":36,"name":"Sappers Destroyed"},{"id":10,"name":"Scouts Killed"},{"id":11,"name":"Snipers Killed"},{"id":12,"name":"Soldiers Killed"},{"id":16,"name":"Spies Killed"},{"id":61,"name":"Tanks Destroyed"},{"id":89,"name":"Taunting Player Kills"},{"id":32,"name":"Teammates Extinguished"},{"id":48,"name":"Underwater Kills"},{"id":78,"name":"Unusual-Wearing Player Kills"}],"appid":440,"default_quality":6} 17 | 18 | particles = obj["particle"] 19 | qualities = obj["quality"] 20 | rarities = obj["rarity"] 21 | paints = obj["paint"] 22 | origins = obj["origin"] 23 | wear_tiers = obj["wear_tiers"] 24 | killstreakers = obj["killstreakers"] 25 | sheens = obj["sheens"] 26 | killstreak_tiers = obj["killstreak_tiers"] 27 | strange_parts = obj["strange_parts"] 28 | 29 | self.particleObj = {} 30 | self.qualitiesObj = {} 31 | self.raritiesObj = {} 32 | self.paintsObj = {} 33 | self.originsObj = {} 34 | self.wear_tiersObj = {} 35 | self.killstreakers = {} 36 | self.sheensObj = {} 37 | self.killstreak_tiers = {} 38 | self.strange_partsObj = {} 39 | 40 | for particle in particles: 41 | self.particleObj[particle["name"].lower()] = int(particle["id"]) 42 | 43 | for quality in qualities: 44 | self.qualitiesObj[quality["name"].lower()] = int(quality["id"]) 45 | 46 | for rarity in rarities: 47 | self.raritiesObj[rarity["name"].lower()] = int(rarity["id"]) 48 | 49 | for paint in paints: 50 | self.paintsObj[paint["name"].lower()] = int(paint["id"]) 51 | 52 | for particle in origins: 53 | self.originsObj[particle["name"].lower()] = int(particle["id"]) 54 | 55 | for particle in wear_tiers: 56 | self.wear_tiersObj[wear_tiers[particle]["name"].lower()] = int( 57 | wear_tiers[particle]["id"] 58 | ) 59 | 60 | for particle in killstreakers: 61 | self.killstreakers[particle["name"].lower()] = int(particle["id"]) 62 | 63 | for particle in sheens: 64 | self.sheensObj[particle["name"].lower()] = int(particle["id"]) 65 | 66 | for particle in killstreak_tiers: 67 | self.killstreak_tiers[particle["name"].lower()] = int(particle["id"]) 68 | 69 | for particle in strange_parts: 70 | self.strange_partsObj[particle["name"].lower()] = int(particle["id"]) 71 | 72 | # 73 | # Converts quality string to quality int 74 | # 75 | def quality_string_to_int(self, string): 76 | try: 77 | return self.qualitiesObj[string.lower()] 78 | except: 79 | return "" 80 | 81 | # alias for compatibility with older versions 82 | # please use the new name, "quality_string_to_int" 83 | quality_String_To_Int = quality_string_to_int 84 | 85 | # 86 | # Converts particle string to particle int 87 | # 88 | def particle_string_to_int(self, string): 89 | try: 90 | return self.particleObj[string.lower()] 91 | except: 92 | return "" 93 | 94 | # alias for compatibility with older versions 95 | # please use the new name, "particle_string_to_int" 96 | particle_String_To_Int = particle_string_to_int 97 | 98 | # 99 | # Converts rarity string to rarity int 100 | # 101 | def rarity_string_to_int(self, string): 102 | try: 103 | return self.raritiesObj[string.lower()] 104 | except: 105 | return "" 106 | 107 | # alias for compatibility with older versions 108 | # please use the new name, "rarity_string_to_int" 109 | rarity_String_To_Int = rarity_string_to_int 110 | 111 | # 112 | # Origin quality string to origin int 113 | # 114 | def origin_string_to_int(self, string): 115 | try: 116 | return self.originsObj[string.lower()] 117 | except: 118 | return "" 119 | 120 | # alias for compatibility with older versions 121 | # please use the new name, "origin_string_to_int" 122 | origin_String_To_Int = origin_string_to_int 123 | 124 | # 125 | # Converts wear_tier string to wear_tier int 126 | # 127 | def wear_tier_string_to_int(self, string): 128 | try: 129 | return self.wear_tiersObj[string.lower()] 130 | except: 131 | return "" 132 | 133 | # alias for compatibility with older versions 134 | # please use the new name, "wear_tier_string_to_int" 135 | wear_tier_String_To_Int = wear_tier_string_to_int 136 | 137 | # 138 | # Converts killstreaker string to killstreaker int 139 | # 140 | def killstreaker_string_to_int(self, string): 141 | try: 142 | return self.killstreakers[string.lower()] 143 | except: 144 | return "" 145 | 146 | # alias for compatibility with older versions 147 | # please use the new name, "killstreaker_string_to_int" 148 | killstreaker_String_To_Int = killstreaker_string_to_int 149 | 150 | # 151 | # Converts sheen string to sheen int 152 | # 153 | def sheen_string_to_int(self, string): 154 | try: 155 | return self.sheensObj[string.lower()] 156 | except: 157 | return "" 158 | 159 | # alias for compatibility with older versions 160 | # please use the new name, "sheen_string_to_int" 161 | sheen_String_To_Int = sheen_string_to_int 162 | 163 | # 164 | # Converts killstreak_tier string to killstreak_tier int 165 | # 166 | def killstreak_tier_string_to_int(self, string): 167 | try: 168 | return self.killstreak_tiers[string.lower()] 169 | except: 170 | return "" 171 | 172 | # alias for compatibility with older versions 173 | # please use the new name, "killstreak_tier_string_to_int" 174 | killstreak_tier_String_To_Int = killstreak_tier_string_to_int 175 | 176 | # 177 | # Converts strange_part string to strange_part int 178 | # 179 | def strange_parts_string_to_int(self, string): 180 | try: 181 | return self.strange_partsObj[string.lower()] 182 | except: 183 | return "" 184 | 185 | # alias for compatibility with older versions 186 | # please use the new name, "strange_parts_string_to_int" 187 | strange_parts_String_To_Int = strange_parts_string_to_int 188 | 189 | # 190 | # Converts paint string to paint int 191 | # 192 | def paint_string_to_int(self, string): 193 | try: 194 | return self.paintsObj[string.lower()] 195 | except: 196 | return "" 197 | 198 | # alias for compatibility with older versions 199 | # please use the new name, "paint_string_to_int" 200 | paint_String_To_Int = paint_string_to_int 201 | 202 | # 203 | # Converts steam ID into the account_id account ID is used in trading requests 204 | # 205 | def steam_id_to_account_id(self, steam_id): 206 | return str( 207 | struct.unpack(">L", int(steam_id).to_bytes(8, byteorder="big")[4:])[0] 208 | ) 209 | 210 | # Get information about a steam user 211 | def get_user_info(self, steam_id): 212 | p = {"steamids": [steam_id]} 213 | r = requests.get("https://backpack.tf/api/IGetUsers/v3", params=p) 214 | 215 | obj = json.loads(r.text) 216 | 217 | if obj["response"]["success"] == 1: 218 | # steam_id can be either a str or an int 219 | return obj["response"]["players"][str(steam_id)] 220 | else: 221 | return None 222 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 David Teather 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 David Teather 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # BackpackTF-API 3 | This is an unoffical api wrapper for the Backpack.tf API in python. You can do a lot with this API keep reading for more information 4 | 5 | [![GitHub release (latest by date)](https://img.shields.io/github/v/release/davidteather/BackpackTf-API)](https://github.com/davidteather/BackpackTf-API/releases) [![Build Status](https://travis-ci.com/davidteather/BackpackTf-API.svg?branch=master)](https://travis-ci.com/davidteather/BackpackTf-API) [![GitHub](https://img.shields.io/github/license/davidteather/BackpackTf-API)](https://github.com/davidteather/BackpackTf-API/blob/master/LICENSE) [![PyPI - Downloads](https://img.shields.io/pypi/dm/BackpackTF)](https://pypi.org/project/BackPackTF/) 6 | 7 | ## Getting Started 8 | 9 | To get started using this api follow the instructions below. 10 | 11 | You need to register for an API key and create an app to use all the fucntions of this api at [BackpackTF](https://backpack.tf/developer) 12 | 13 | ### Installing 14 | 15 | ``` 16 | pip install BackpackTF 17 | ``` 18 | 19 | ## Quick Start Guide 20 | 21 | Here's a quick bit of code to get an item's price 22 | 23 | ``` 24 | from BackpackTF import Currency 25 | 26 | api = Currency(apikey="xxxxxxxxxxxxxxxxx") 27 | 28 | price = api.item_price(item="Tour of Duty Ticket", quality="Unique", craftable=1, tradable=1, priceindex=0) 29 | 30 | print(price) 31 | ``` 32 | 33 | ## Detailed Documentation 34 | 35 | ### The Account Class 36 | 37 | __init__ 38 | 39 | 40 | | Attributes | Description | 41 | | ------------- | ------------- | 42 | | client_id | from your backpack.tf app [here](https://backpack.tf/developer/apps) | 43 | | client_secret | from your backpack.tf app [here](https://backpack.tf/developer/apps) | 44 | | api_key | your api key from [here](https://backpack.tf/developer/apikey/view) | 45 | 46 | 47 | #### create_listing - creates a listing / classified on backpack.tf 48 | 49 | 50 | | Attributes | Description | 51 | | ------------- | ------------- | 52 | | intent | 0 (Buy) or 1 (Sell) | 53 | | id | if intent is 1, the current id of the id you want to list | 54 | | item_name | if intent is 0, the item's name you want to buy | 55 | | quality | if intent is 0, either the number or the text | 56 | | craftable | if intent is 0, 0 or 1 | 57 | | offers | set to 0 for only accepting friend requests | 58 | | buyout | set to 0 to allow negotiation | 59 | | promoted | set to 1 to promote it, must be premium | 60 | | details | the listing comment, max 200 characters | 61 | | priceindex | complicated, most of the time is 0. [More info](https://image.prntscr.com/image/-zjCD9FiS0ijpGHtG8gNBA.png) | 62 | 63 | returns 0 or 1 for success or failure. 64 | 65 | 66 | #### search_classifieds - searches for classifieds 67 | 68 | 69 | | Attributes | Description | 70 | | ------------- | ------------- | 71 | | intent | either sell, buy, or both | 72 | | page_size | the results / page 0 < page_size <= 30 | 73 | | page | the page number you want to view | 74 | | fold | if set 0 disables listing folding | 75 | | item_name | the name of the item you want to search for | 76 | | steamid | the steam id of the user who you want to check their listings | 77 | | tradable | 0/1 | 78 | | craftable | 0/1 | 79 | | australium | 0/1 | 80 | | wear_tier | 1-5 for tier of skin wear, use MiscUtils().wear_Tier_String_To_Int() | 81 | | texture_name | required to search by wear_tier, the name of the skin / texture to search by | 82 | | quality | the integer of the quality to search by use MiscUtils().qualityStringToInt() to get it | 83 | | paint | the paint's ID to search by | 84 | | particle | particle ID effect | 85 | | killstreak_tier | 1-3, use MiscUtils().killstreaker_Tier_String_To_Int() | 86 | | sheen | 0-7, use MiscUtils().sheen_String_To_Int() | 87 | | killstreaker | the id of the killstreaker | 88 | 89 | returns a dictionary. [Here](https://gist.github.com/davidteather/109acc0acd7e7d59f8192d8d8cfcba7c)'s an example json 90 | 91 | 92 | #### extract_trade_url - extracts the trade url with token from a listing 93 | 94 | 95 | | Attributes | Description | 96 | | ------------- | ------------- | 97 | | listingJSON | This is the json object of a classified listing on backpack.tf. You can get this using the method above. | 98 | | proxy | This is an optional field, provide a dictionary that fits the python requests module requirements. See [here](https://stackoverflow.com/questions/8287628/proxies-with-python-requests-module) | 99 | 100 | 101 | returns the trade url as a string. 102 | 103 | 104 | ### The Currency Class 105 | 106 | __init__ 107 | 108 | 109 | | Attributes | Description | 110 | | ------------- | ------------------------------------------------------------------- | 111 | | apikey | your api key from [here](https://backpack.tf/developer/apikey/view) | 112 | 113 | 114 | #### get_currencies - gets currency values 115 | 116 | 117 | | Attributes | Description | 118 | | ------------- | ------------- | 119 | | None | None | 120 | 121 | returns a dictonary. [Here's](https://gist.github.com/davidteather/4f9c82f3d224e64c3a187ad28db26d1a) an example json. 122 | 123 | 124 | #### price_history - gets the price history for a given item 125 | 126 | 127 | | Attributes | Description | 128 | | ------------- | ------------- | 129 | | item | the name of the item you want to search for | 130 | | quality | the integer of the quality to search by use MiscUtils().qualityStringToInt("Unique") to get it | 131 | | craftable | 0/1 | 132 | | tradable | 0/1 | 133 | | priceindex | complicated, most of the time is 0. [More info](https://image.prntscr.com/image/-zjCD9FiS0ijpGHtG8gNBA.png) | 134 | 135 | returns an array of dictionaries. [Here's](https://gist.github.com/davidteather/db87fbe0bfd7d0ac88cb5412d1bba878) an example. 136 | 137 | 138 | #### item_price - gets the current price for a given item 139 | 140 | 141 | | Attributes | Description | 142 | | ------------- | ------------- | 143 | | item | the name of the item you want to search for | 144 | | quality | the integer of the quality to search by use MiscUtils().qualityStringToInt("Unique") to get it | 145 | | craftable | 0/1 | 146 | | tradable | 0/1 | 147 | | priceindex | complicated, most of the time is 0. [More info](https://image.prntscr.com/image/-zjCD9FiS0ijpGHtG8gNBA.png) | 148 | 149 | returns a single dictionary of current value. [Here's](https://gist.github.com/davidteather/a791078ef11d6977d7a9b77d249bd78e) an example. 150 | 151 | 152 | #### get_all_prices - gets all prices 153 | 154 | 155 | | Attributes | Description | 156 | | ------------- | ------------- | 157 | | raw | shows a value_low field | 158 | | since | will only show items that has had price changes since the unix epoch. | 159 | 160 | returns a kind of weird json file. [Here's](https://gist.github.com/davidteather/eefde719b1ac0031656acbacc4a614c8) an example, and [here's](https://gist.github.com/davidteather/9a8fc5c7bfa6a484b8f28785ee30c6dd) the structure. 161 | 162 | 163 | ### The MiscUtils Class 164 | 165 | __init__ 166 | 167 | 168 | | Attributes | Description | 169 | | ------------- | ------------- | 170 | | None | None | 171 | 172 | 173 | #### quality_string_to_int 174 | 175 | 176 | | Attributes | Description | 177 | | ------------- | ------------- | 178 | | string | The string of the quality. Ex: "Unique" | 179 | 180 | 181 | #### particle_string_to_int 182 | 183 | 184 | | Attributes | Description | 185 | | ------------- | ------------- | 186 | | string | The string of the particle effect. | 187 | 188 | 189 | #### rarity_string_to_int 190 | 191 | 192 | | Attributes | Description | 193 | | ------------- | ------------- | 194 | | string | The string of the rarity. | 195 | 196 | 197 | #### origin_string_to_int 198 | 199 | 200 | | Attributes | Description | 201 | | ------------- | ------------- | 202 | | string | The string of the origin. | 203 | 204 | 205 | #### wear_tier_string_to_int 206 | 207 | 208 | | Attributes | Description | 209 | | ------------- | ------------- | 210 | | string | The string of the wear_tier. | 211 | 212 | 213 | #### killstreaker_string_to_int 214 | 215 | 216 | | Attributes | Description | 217 | | ------------- | ------------- | 218 | | string | The string of the killstreaker. | 219 | 220 | 221 | #### strange_parts_string_to_int 222 | 223 | 224 | | Attributes | Description | 225 | | ------------- | ------------- | 226 | | string | The string of the strange part. | 227 | 228 | 229 | #### steam_id_to_account_id 230 | 231 | 232 | | Attributes | Description | 233 | | ------------- | ------------- | 234 | | string | The string of the steam_id. | 235 | 236 | returns an int of the account id. 237 | 238 | ## Built With 239 | 240 | * [Python 3.7](https://www.python.org/) - The web framework used 241 | 242 | ## Authors 243 | 244 | * **David Teather** - *Initial work* - [davidteather](https://github.com/davidteather) 245 | 246 | See also the list of [contributors](https://github.com/davidteather/BackpackTF-API/contributors) who participated in this project. 247 | 248 | ## License 249 | 250 | This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details 251 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /examples/createListing.py: -------------------------------------------------------------------------------- 1 | from BackpackTF.account import Account 2 | 3 | # Get these attributes from backpack.tf/developer 4 | user = Account(client_id="xxxxxxxxx", client_secret="xxxxxxxxxx", api_key="xxxxxxxxxx") 5 | 6 | 7 | print( 8 | user.createListing( 9 | intent=0, 10 | id=0, 11 | quality=6, 12 | item_name="Tour of Duty Ticket", 13 | craftable=1, 14 | priceindex=0, 15 | offers=1, 16 | buyout=1, 17 | promoted=0, 18 | details="", 19 | currencies={"metal": "23"}, 20 | account_token="xxxxxxxxxxxxxxxxx", 21 | ) 22 | ) 23 | -------------------------------------------------------------------------------- /examples/extractTradeUrl.py: -------------------------------------------------------------------------------- 1 | from BackpackTF.account import Account 2 | 3 | user = Account(client_id="xxxxxx", client_secret="xxxxxx", api_key="xxxxxx") 4 | 5 | classifieds = user.search_Classifieds()["buy"]["listings"] 6 | 7 | for classified in classifieds: 8 | trade_url = user.extract_trade_url(classified) 9 | print(trade_url) 10 | -------------------------------------------------------------------------------- /examples/getItemPrice.py: -------------------------------------------------------------------------------- 1 | from BackpackTF import Currency 2 | 3 | api = Currency(apikey="xxxxxxxxxxxxxxxxx") 4 | 5 | price = api.itemPrice( 6 | item="Tour of Duty Ticket", quality="Unique", craftable=1, tradable=1, priceindex=0 7 | ) 8 | 9 | print(price) 10 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup 2 | import os.path 3 | import setuptools 4 | 5 | with open("README.md", "r") as fh: 6 | long_description = fh.read() 7 | 8 | setuptools.setup( 9 | name="BackpackTF", 10 | packages=["BackpackTF"], 11 | version="0.1.4", 12 | license="MIT", 13 | description="The Unoffical Backpack.tf API Wrapper in Python 3.", 14 | author="David Teather", 15 | author_email="contact.davidteather@gmail.com", 16 | url="https://github.com/davidteather/BackpackTf-API", 17 | long_description=long_description, 18 | long_description_content_type="text/markdown", 19 | download_url="https://github.com/davidteather/BackpackTf-API/tarball/master", 20 | keywords=[ 21 | "backpacktf", 22 | "python3", 23 | "tf2", 24 | "unofficial", 25 | "backpack.tf", 26 | "trading-bot", 27 | "api", 28 | ], 29 | install_requires=[ 30 | "oauth2", 31 | "lxml", 32 | "requests_oauthlib", 33 | ], 34 | classifiers=[ 35 | "Development Status :: 3 - Alpha", 36 | "Intended Audience :: Developers", 37 | "Topic :: Software Development :: Build Tools", 38 | "License :: OSI Approved :: MIT License", 39 | "Programming Language :: Python :: 3.7", 40 | "Programming Language :: Python :: 3.6", 41 | "Programming Language :: Python :: 3.5", 42 | "Programming Language :: Python :: 3.4", 43 | ], 44 | ) 45 | -------------------------------------------------------------------------------- /tests/__pycache__/test_miscutils.cpython-37-pytest-5.1.2.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidteather/BackpackTf-API/2019881f84669d2a660f0eab721b4ad43c0a9bf2/tests/__pycache__/test_miscutils.cpython-37-pytest-5.1.2.pyc -------------------------------------------------------------------------------- /tests/__pycache__/test_miscutils.cpython-38-pytest-6.0.1.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidteather/BackpackTf-API/2019881f84669d2a660f0eab721b4ad43c0a9bf2/tests/__pycache__/test_miscutils.cpython-38-pytest-6.0.1.pyc -------------------------------------------------------------------------------- /tests/__pycache__/test_misutils.cpython-37-pytest-5.1.2.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidteather/BackpackTf-API/2019881f84669d2a660f0eab721b4ad43c0a9bf2/tests/__pycache__/test_misutils.cpython-37-pytest-5.1.2.pyc -------------------------------------------------------------------------------- /tests/test_miscutils.py: -------------------------------------------------------------------------------- 1 | from BackpackTF import MiscUtils 2 | 3 | 4 | def test_quality_to_int(): 5 | misc = MiscUtils() 6 | 7 | assert misc.quality_String_To_Int("Collector's") == 14 8 | assert misc.quality_String_To_Int("Decorated Weapon") == 15 9 | assert misc.quality_String_To_Int("Genuine") == 1 10 | assert misc.quality_String_To_Int("Haunted") == 13 11 | assert misc.quality_String_To_Int("Normal") == 0 12 | assert misc.quality_String_To_Int("Self-Made") == 9 13 | assert misc.quality_String_To_Int("Strange") == 11 14 | assert misc.quality_String_To_Int("Unique") == 6 15 | assert misc.quality_String_To_Int("Unusual") == 5 16 | assert misc.quality_String_To_Int("Vintage") == 3 17 | 18 | 19 | def test_particle_to_int(): 20 | misc = MiscUtils() 21 | 22 | assert misc.particle_String_To_Int("Abduction") == 91 23 | assert misc.particle_String_To_Int("Aces High") == 59 24 | assert misc.particle_String_To_Int("Acidic Bubbles of Envy") == 3017 25 | assert misc.particle_String_To_Int("Amaranthine") == 82 26 | assert misc.particle_String_To_Int("Bubbling") == 34 27 | assert misc.particle_String_To_Int("Burning Flames") == 13 28 | assert misc.particle_String_To_Int("Cauldron Bubbles") == 39 29 | assert misc.particle_String_To_Int("Cool") == 703 30 | assert misc.particle_String_To_Int("Dead Presidents") == 60 31 | 32 | 33 | def test_rarity_to_int(): 34 | misc = MiscUtils() 35 | 36 | assert misc.rarity_String_To_Int("") == 99 37 | assert misc.rarity_String_To_Int("Assassin") == 5 38 | assert misc.rarity_String_To_Int("Civilian") == 1 39 | assert misc.rarity_String_To_Int("Elite") == 6 40 | assert misc.rarity_String_To_Int("Freelance") == 2 41 | assert misc.rarity_String_To_Int("Immortal") == 7 42 | 43 | 44 | def test_origin_to_int(): 45 | misc = MiscUtils() 46 | 47 | assert misc.origin_String_To_Int("Achievement") == 1 48 | assert misc.origin_String_To_Int("CD Key") == 15 49 | assert misc.origin_String_To_Int("Collection Reward") == 16 50 | assert misc.origin_String_To_Int("Earned") == 9 51 | assert misc.origin_String_To_Int("Gifted") == 6 52 | 53 | 54 | def test_wear_tier_to_int(): 55 | misc = MiscUtils() 56 | 57 | assert misc.wear_tier_String_To_Int("Factory New") == 1 58 | assert misc.wear_tier_String_To_Int("Minimal Wear") == 2 59 | assert misc.wear_tier_String_To_Int("Field-Tested") == 3 60 | assert misc.wear_tier_String_To_Int("Well-Worn") == 4 61 | assert misc.wear_tier_String_To_Int("Battle Scarred") == 5 62 | 63 | 64 | def test_killstreaker_to_int(): 65 | misc = MiscUtils() 66 | 67 | assert misc.killstreaker_String_To_Int("Fire Horns") == 2002 68 | assert misc.killstreaker_String_To_Int("Cerebral Discharge") == 2003 69 | assert misc.killstreaker_String_To_Int("Tornado") == 2004 70 | assert misc.killstreaker_String_To_Int("Flames") == 2005 71 | assert misc.killstreaker_String_To_Int("Singularity") == 2006 72 | assert misc.killstreaker_String_To_Int("Incinerator") == 2007 73 | 74 | 75 | def test_sheen_to_int(): 76 | misc = MiscUtils() 77 | 78 | assert misc.sheen_String_To_Int("Team Shine") == 1 79 | assert misc.sheen_String_To_Int("Deadly Daffodil") == 2 80 | assert misc.sheen_String_To_Int("Manndarin") == 3 81 | assert misc.sheen_String_To_Int("Mean Green") == 4 82 | assert misc.sheen_String_To_Int("Agonizing Emerald") == 5 83 | assert misc.sheen_String_To_Int("Villainous Violet") == 6 84 | assert misc.sheen_String_To_Int("Hot Rod") == 7 85 | 86 | 87 | def test_Killstreak_tier_to_int(): 88 | misc = MiscUtils() 89 | 90 | assert misc.killstreak_tier_String_To_Int("None") == 0 91 | assert misc.killstreak_tier_String_To_Int("Standard") == 1 92 | assert misc.killstreak_tier_String_To_Int("Specialized") == 2 93 | assert misc.killstreak_tier_String_To_Int("Professional") == 3 94 | 95 | 96 | def test_strange_parts_to_int(): 97 | misc = MiscUtils() 98 | 99 | assert misc.strange_parts_String_To_Int("Airborne Enemies Killed") == 22 100 | assert misc.strange_parts_String_To_Int("Allied Healing Done") == 84 101 | assert misc.strange_parts_String_To_Int("Assists") == 95 102 | assert misc.strange_parts_String_To_Int("Critical Kills") == 33 103 | assert misc.strange_parts_String_To_Int("Damage Dealt") == 82 104 | 105 | 106 | def test_paint_to_Int(): 107 | misc = MiscUtils() 108 | 109 | assert misc.paint_String_To_Int("A Color Similar to Slate") == 3100495 110 | assert misc.paint_String_To_Int("A Deep Commitment to Purple") == 8208497 111 | assert misc.paint_String_To_Int("A Distinctive Lack of Hue") == 1315860 112 | assert misc.paint_String_To_Int("A Mann's Mint") == 12377523 113 | assert misc.paint_String_To_Int("After Eight") == 2960676 114 | assert misc.paint_String_To_Int("Aged Moustache Grey") == 8289918 115 | 116 | 117 | def test_steam_id_to_account_id(): 118 | misc = MiscUtils() 119 | 120 | assert misc.steam_id_to_account_id("76561198195716551") == "235450823" 121 | --------------------------------------------------------------------------------