Initial version

This commit is contained in:
2026-01-26 15:43:33 -05:00
parent be2e77c357
commit 0d4f36b89a
3 changed files with 161 additions and 1 deletions

1
.gitignore vendored
View File

@@ -188,3 +188,4 @@ cython_debug/
# Built Visual Studio Code Extensions
*.vsix
.api_key

View File

@@ -1,3 +1,20 @@
# unbox.py
A simple Python script that unboxes a keyless crate or locked crate.
Extremely simple script that unboxes a crate and prints the item name and value.
## Usage
```bash
python3 unbox.py
```
Use key crates instead of keyless crates:
```bash
python3 unbox.py --key
```
### API key
On first run, the script will prompt for an API key and store it in `.api_key`
in the current directory. Delete `.api_key` to re-enter the key.

142
unbox.py Normal file
View File

@@ -0,0 +1,142 @@
#!/usr/bin/env python3
import json
import os
import sys
import urllib.error
import urllib.parse
import urllib.request
BASE_URL = os.environ.get("UNBOX_API_BASE", "https://api.unbox.tf")
API_KEY_FILE = ".api_key"
def load_api_key():
if os.path.exists(API_KEY_FILE):
with open(API_KEY_FILE, "r", encoding="utf-8") as f:
return f.read().strip()
key = input("Enter API key: ").strip()
if not key:
print("No API key provided.")
sys.exit(1)
with open(API_KEY_FILE, "w", encoding="utf-8") as f:
f.write(key)
return key
def get_json(path, params=None, headers=None):
query = urllib.parse.urlencode(params or {})
url = f"{BASE_URL}{path}"
if query:
url = f"{url}?{query}"
req = urllib.request.Request(url, headers=headers or {})
with urllib.request.urlopen(req) as resp:
return json.load(resp)
def post_json(path, params=None, headers=None):
query = urllib.parse.urlencode(params or {})
url = f"{BASE_URL}{path}"
if query:
url = f"{url}?{query}"
req = urllib.request.Request(url, method="POST", headers=headers or {})
with urllib.request.urlopen(req) as resp:
return json.load(resp)
def main():
use_alt = "--key" in sys.argv[1:]
crate_ref_id = 2 if use_alt else 1
api_key = load_api_key()
headers = {"Authorization": f"Bearer {api_key}"}
try:
crates_resp = get_json("/user/crates", headers=headers)
except urllib.error.HTTPError as e:
print(f"Failed to fetch crates: {e.code} {e.reason}")
return 1
except urllib.error.URLError as e:
print(f"Failed to fetch crates: {e.reason}")
return 1
crates = crates_resp.get("data", {}).get("crates", [])
crate = next((c for c in crates if c.get("crate_reference_id") == crate_ref_id), None)
if not crate:
if crate_ref_id == 1:
print("No keyless crate available")
elif crate_ref_id == 2:
print("No keys available to use")
else:
print(f"No crate with reference ID {crate_ref_id} found.")
return 1
crate_id = crate.get("crate_id")
if not crate_id:
print("Crate is missing crate_id.")
return 1
try:
unbox_resp = post_json("/unbox", params={"crate_id": crate_id}, headers=headers)
except urllib.error.HTTPError as e:
print(f"Failed to unbox: {e.code} {e.reason}")
return 1
except urllib.error.URLError as e:
print(f"Failed to unbox: {e.reason}")
return 1
item_ids = unbox_resp.get("data", {}).get("item_ids", [])
if not item_ids:
print("No item_ids returned from unbox.")
return 1
item_id = item_ids[0]
try:
name_resp = get_json(
"/name",
params={
"item_id": item_id,
"add_emojis": "false",
"separate_item_effect": "true",
},
)
except urllib.error.HTTPError as e:
print(f"Failed to fetch item name: {e.code} {e.reason}")
return 1
except urllib.error.URLError as e:
print(f"Failed to fetch item name: {e.reason}")
return 1
data = name_resp.get("data", {})
item_name = data.get("item_name") or "Unknown Item"
effect_name = data.get("effect_name")
try:
value_resp = get_json(
"/value",
params={"item_id": item_id, "separate_keys_ref": "true"},
)
except urllib.error.HTTPError as e:
print(f"Failed to fetch item value: {e.code} {e.reason}")
return 1
except urllib.error.URLError as e:
print(f"Failed to fetch item value: {e.reason}")
return 1
value_data = value_resp.get("data", {})
if isinstance(value_data, dict):
keys_val = value_data.get("keys", 0)
refined_val = value_data.get("refined_metal", 0)
else:
keys_val = 0
refined_val = value_data or 0
if effect_name:
print(f"{item_name} ({effect_name})")
else:
print(item_name)
print(f"{keys_val} Keys - {refined_val} Refined")
return 0
if __name__ == "__main__":
raise SystemExit(main())