Save and reload a costume

This commit is contained in:
Howard Abrams 2026-09-09 21:27:09 -07:00
parent 0b0b67e473
commit 77301c9050
6 changed files with 225 additions and 0 deletions

150
costume.py Executable file
View file

@ -0,0 +1,150 @@
#!/usr/bin/env python3
import argparse
import json
import os
import sys
import requests
API_URL = "https://habitica.com/api/v3/user"
def get_habitica_headers():
user_id = os.getenv("HABITICA_USER_ID")
api_token = os.getenv("HABITICA_API_TOKEN")
if not user_id or not api_token:
print("Error: Environment variables HABITICA_USER_ID and HABITICA_API_TOKEN must be set.", file=sys.stderr)
sys.exit(1)
return {
"x-api-user": user_id,
"x-api-key": api_token,
"x-client": f"{user_id}-CustomizationScript"
}
def fetch_habitica_gear():
"""Fetches only the costume, background, pet, and mount from the user profile."""
try:
response = requests.get(API_URL, headers=get_habitica_headers())
response.raise_for_status()
except requests.exceptions.RequestException as e:
print(f"Error communicating with Habitica API: {e}", file=sys.stderr)
sys.exit(1)
data = response.json().get("data", {})
# Extract specific fields
items = data.get("items", {})
gear = items.get("gear", {})
costume = gear.get("costume", {})
background = data.get("preferences", {}).get("background", "default")
pet = items.get("currentPet", "")
mount = items.get("currentMount", "")
customizations = {
"costume": costume,
"background": background,
"pet": pet,
"mount": mount
}
print(customizations)
return customizations
def save_costume(filename):
# print("Fetching equipment and costume data from Habitica...")
gear_data = fetch_habitica_gear()
with open(filename, "w", encoding="utf-8") as f:
json.dump(gear_data, f, indent=4)
def equip(type, name):
try:
response = requests.post(f"{API_URL}/equip/{type}/{name}",
headers=get_habitica_headers())
response.raise_for_status()
print(f"Successfully equiped '{name}'.")
except requests.exceptions.RequestException as e:
print(f"Error communicating with Habitica API: {e}", file=sys.stderr)
if hasattr(e, 'response') and e.response is not None:
print(f"Server response: {e.response.text}", file=sys.stderr)
sys.exit(1)
def set_background(name):
bg_payload = {
"preferences.background": name
}
try:
res = requests.put(f"{API_URL}",
headers=get_habitica_headers(), json=bg_payload)
res.raise_for_status()
print(f"Successfully set background to: {name}")
except requests.exceptions.RequestException as e:
print(f"Error setting background: {e}", file=sys.stderr)
if hasattr(e, 'response') and e.response is not None:
print(f"Server response: {e.response.text}", file=sys.stderr)
def set_costume(data):
for k,v in data.get("costume").items():
if v and not v.endswith("base_0"):
equip("costume", v)
if "pet" in data:
equip("pet", data.get("pet"))
# if "mount" in data:
# equip("mount", data.get("mount"))
# TODO: Not sure how to set the background!
if "background" in data:
set_background(data["background"])
def load_costume(filename):
if os.path.exists(filename):
with open(filename, "r", encoding="utf-8") as f:
gear_data = json.load(f)
# Update defaults with values from the file
set_costume(gear_data)
def store_all(filename):
try:
response = requests.get(API_URL, headers=get_habitica_headers())
response.raise_for_status()
except requests.exceptions.RequestException as e:
print(f"Error communicating with Habitica API: {e}", file=sys.stderr)
sys.exit(1)
data = response.json().get("data", {})
with open(filename, "w", encoding="utf-8") as f:
json.dump(data, f, indent=4)
def parse_arguments():
parser = argparse.ArgumentParser(description="Costume configuration script")
parser.add_argument(
"--load",
type=str,
help="Path to a JSON file containing saved costume values"
)
parser.add_argument(
"--save",
type=str,
help="Path to a JSON file to save your costume values"
)
parser.add_argument(
"-a", "--all",
action=argparse.BooleanOptionalAction,
help="Download and store all data in 'all.json'"
)
return parser.parse_args()
def main():
args = parse_arguments()
if args.save:
save_costume(args.save)
elif args.load:
load_costume(args.load)
elif args.all:
store_all("all.json")
if __name__ == "__main__":
main()

View file

@ -0,0 +1,15 @@
{
"costume": {
"weapon": "weapon_armoire_jeweledArcherBow",
"armor": "armor_armoire_woodElfArmor",
"head": "head_armoire_woodElfHelm",
"shield": "shield_base_0",
"back": "back_base_0",
"headAccessory": "headAccessory_base_0",
"eyewear": "eyewear_special_blackTopFrame",
"body": "body_special_summerMage"
},
"background": "vegetable_garden",
"pet": "",
"mount": ""
}

15
costumes/beholder.json Normal file
View file

@ -0,0 +1,15 @@
{
"costume": {
"weapon": "weapon_special_fall2022Healer",
"armor": "armor_special_fall2022Healer",
"head": "head_special_fall2022Healer",
"shield": "shield_special_fall2022Healer",
"back": "back_base_0",
"headAccessory": "headAccessory_base_0",
"eyewear": "eyewear_base_0",
"body": "body_base_0"
},
"background": "magic_door_in_forest",
"pet": "",
"mount": ""
}

View file

@ -0,0 +1,15 @@
{
"costume": {
"weapon": "weapon_special_spring2019Mage",
"armor": "armor_special_spring2019Mage",
"head": "head_special_spring2019Mage",
"shield": "shield_base_0",
"back": "back_base_0",
"headAccessory": "headAccessory_base_0",
"eyewear": "eyewear_special_redHalfMoon",
"body": "body_base_0"
},
"background": "magic_door_in_forest",
"pet": "",
"mount": ""
}

View file

@ -0,0 +1,15 @@
{
"costume": {
"weapon": "weapon_mystery_301404",
"armor": "armor_armoire_plagueDoctorOvercoat",
"head": "head_mystery_301405",
"shield": "shield_base_0",
"back": "back_base_0",
"headAccessory": "headAccessory_base_0",
"eyewear": "eyewear_special_blackTopFrame",
"body": "body_armoire_cozyScarf"
},
"background": "sunny_street_with_shops",
"pet": "Gryphon-Base",
"mount": ""
}

15
costumes/the_reader.json Normal file
View file

@ -0,0 +1,15 @@
{
"costume": {
"weapon": "weapon_base_0",
"armor": "armor_wizard_3",
"head": "head_base_0",
"shield": "shield_mystery_201709",
"back": "back_mystery_201709",
"headAccessory": "headAccessory_base_0",
"eyewear": "eyewear_special_blackHalfMoon",
"body": "body_special_summerMage"
},
"background": "cozy_library",
"pet": "",
"mount": ""
}