Skip to content

Instantly share code, notes, and snippets.

@Syfaro
Last active February 24, 2026 11:02
Show Gist options
  • Select an option

  • Save Syfaro/583e6e1a949e0156fd022db0f05625eb to your computer and use it in GitHub Desktop.

Select an option

Save Syfaro/583e6e1a949e0156fd022db0f05625eb to your computer and use it in GitHub Desktop.
Download OBJ previews of products from Bad Dragon
from typing import List, Iterator
import os
import urllib.request
import json
from dataclasses import dataclass
import argparse
PRODUCT_URL = "https://bad-dragon.com/api/products"
SAVE_DIR = "models"
@dataclass
class DownloadableProduct:
name: str
preview_object_url: str
preview_texture_map_url: str
preview_normal_map_url: str
def load_products() -> List[dict]:
with urllib.request.urlopen(PRODUCT_URL) as f:
return json.load(f)
def process_products(products: List[dict]) -> Iterator[DownloadableProduct]:
for product in products:
name = product.get("sku")
preview_object_url = product.get("previewObjModel", {}).get("url")
preview_texture_map_url = product.get("previewTextureMap", {}).get("url")
preview_normal_map_url = product.get("previewNormalMap", {}).get("url")
if (
not name
or not preview_object_url
or not preview_texture_map_url
or not preview_normal_map_url
):
continue
yield DownloadableProduct(
name, preview_object_url, preview_texture_map_url, preview_normal_map_url
)
def download_file(url: str, path: str) -> None:
if os.path.exists(path):
print("Already downloaded {path}".format(path=path))
return
print("Downloading {path}".format(path=path))
urllib.request.urlretrieve(url, path)
def download_product(
product: DownloadableProduct, save_dir: str, include_maps: bool = False
) -> None:
download_file(
product.preview_object_url,
os.path.join(save_dir, "{name}.obj".format(name=product.name)),
)
if include_maps:
download_file(
product.preview_texture_map_url,
os.path.join(save_dir, "{name}_texture_map.png".format(name=product.name)),
)
download_file(
product.preview_normal_map_url,
os.path.join(save_dir, "{name}_normal_map.png".format(name=product.name)),
)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Download Bad Dragon preview objects.")
parser.add_argument(
"--maps", help="include texture and normal maps", action="store_true"
)
parser.add_argument("dir", help="Path to save models", nargs="?", default=SAVE_DIR)
args = parser.parse_args()
if not os.path.exists(args.dir):
os.mkdir(args.dir)
print("Saving objects to {dir}".format(dir=args.dir))
products = load_products()
for product in process_products(products):
download_product(product, args.dir, args.maps)
@PhoenixGames73
Copy link

Is there a way to download the legacy products?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment