From 0d4f36b89a2a14481313345a1f900931acd47f74 Mon Sep 17 00:00:00 2001 From: lexzach Date: Mon, 26 Jan 2026 15:43:33 -0500 Subject: [PATCH] Initial version --- .gitignore | 1 + README.md | 19 ++++++- unbox.py | 142 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 unbox.py diff --git a/.gitignore b/.gitignore index 555e90e..9eeedb5 100644 --- a/.gitignore +++ b/.gitignore @@ -188,3 +188,4 @@ cython_debug/ # Built Visual Studio Code Extensions *.vsix +.api_key diff --git a/README.md b/README.md index a72788f..8df713f 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,20 @@ # unbox.py -A simple Python script that unboxes a keyless crate or locked crate. \ No newline at end of file +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. \ No newline at end of file diff --git a/unbox.py b/unbox.py new file mode 100644 index 0000000..93dd0aa --- /dev/null +++ b/unbox.py @@ -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())