Spaces:
Runtime error
Runtime error
| #!/usr/bin/env python3 | |
| import os | |
| import sys | |
| import shutil | |
| import zipfile | |
| import tempfile | |
| from pathlib import Path | |
| from huggingface_hub import HfApi, hf_hub_download | |
| HF_REPO_ID = os.environ.get("HF_REPO_ID", "eaglercraft/world") | |
| HF_REPO_TYPE = "dataset" | |
| HF_TOKEN = os.environ.get("HF_TOKEN", "") | |
| WORLD_DIR = Path("/opt/server/backend/world") | |
| ZIP_REPO_PATH = "world.zip" | |
| TMP_DIR = Path("/tmp/hf_world") | |
| def _api() -> HfApi: | |
| return HfApi(token=HF_TOKEN) | |
| def _ensure_repo(): | |
| try: | |
| _api().create_repo( | |
| repo_id=HF_REPO_ID, | |
| repo_type=HF_REPO_TYPE, | |
| exist_ok=True, | |
| private=True, | |
| ) | |
| except Exception: | |
| pass | |
| def _repo_has_world() -> bool: | |
| try: | |
| files = list(_api().list_repo_files( | |
| repo_id=HF_REPO_ID, | |
| repo_type=HF_REPO_TYPE, | |
| token=HF_TOKEN, | |
| )) | |
| return ZIP_REPO_PATH in files | |
| except Exception as e: | |
| print(f"[sync_world] Could not list repo files: {e}") | |
| return False | |
| def download() -> bool: | |
| if not HF_TOKEN: | |
| print("[sync_world] WARNING: HF_TOKEN not set, skipping download") | |
| return False | |
| if not _repo_has_world(): | |
| print("[sync_world] world.zip not found in repo — first-run setup required") | |
| return False | |
| try: | |
| TMP_DIR.mkdir(parents=True, exist_ok=True) | |
| zip_path = hf_hub_download( | |
| repo_id=HF_REPO_ID, | |
| filename=ZIP_REPO_PATH, | |
| repo_type=HF_REPO_TYPE, | |
| token=HF_TOKEN, | |
| local_dir=str(TMP_DIR), | |
| ) | |
| if WORLD_DIR.exists(): | |
| shutil.rmtree(WORLD_DIR) | |
| WORLD_DIR.mkdir(parents=True, exist_ok=True) | |
| with zipfile.ZipFile(zip_path, "r") as zf: | |
| members = zf.namelist() | |
| top_dirs = {m.split("/")[0] for m in members if m.strip("/")} | |
| if len(top_dirs) == 1: | |
| top = top_dirs.pop() | |
| for member in members: | |
| rel = member[len(top):].lstrip("/") | |
| if not rel: | |
| continue | |
| dest = WORLD_DIR / rel | |
| if member.endswith("/"): | |
| dest.mkdir(parents=True, exist_ok=True) | |
| else: | |
| dest.parent.mkdir(parents=True, exist_ok=True) | |
| with zf.open(member) as src, open(dest, "wb") as dst: | |
| shutil.copyfileobj(src, dst) | |
| else: | |
| zf.extractall(WORLD_DIR) | |
| size_mb = os.path.getsize(zip_path) / 1_048_576 | |
| print(f"[sync_world] World downloaded and extracted ({size_mb:.1f} MB)") | |
| return True | |
| except Exception as e: | |
| print(f"[sync_world] Download failed: {e}") | |
| return False | |
| def upload() -> bool: | |
| if not HF_TOKEN: | |
| print("[sync_world] WARNING: HF_TOKEN not set, skipping upload") | |
| return False | |
| if not WORLD_DIR.exists(): | |
| print(f"[sync_world] {WORLD_DIR} does not exist, skipping upload") | |
| return False | |
| tmp_zip = Path(tempfile.mktemp(suffix=".zip")) | |
| try: | |
| print("[sync_world] Zipping world...") | |
| with zipfile.ZipFile(tmp_zip, "w", zipfile.ZIP_DEFLATED) as zf: | |
| for fpath in WORLD_DIR.rglob("*"): | |
| if fpath.is_file(): | |
| zf.write(fpath, fpath.relative_to(WORLD_DIR.parent)) | |
| size_mb = tmp_zip.stat().st_size / 1_048_576 | |
| print(f"[sync_world] Uploading world.zip ({size_mb:.1f} MB)...") | |
| _ensure_repo() | |
| _api().upload_file( | |
| path_or_fileobj=str(tmp_zip), | |
| path_in_repo=ZIP_REPO_PATH, | |
| repo_id=HF_REPO_ID, | |
| repo_type=HF_REPO_TYPE, | |
| token=HF_TOKEN, | |
| commit_message=f"World autosave ({size_mb:.1f} MB)", | |
| ) | |
| print(f"[sync_world] Upload complete.") | |
| return True | |
| except Exception as e: | |
| print(f"[sync_world] Upload failed: {e}") | |
| return False | |
| finally: | |
| tmp_zip.unlink(missing_ok=True) | |
| def store_uploaded_zip(local_zip_path: str) -> bool: | |
| if not HF_TOKEN: | |
| print("[sync_world] WARNING: HF_TOKEN not set") | |
| return False | |
| try: | |
| size_mb = os.path.getsize(local_zip_path) / 1_048_576 | |
| print(f"[sync_world] Storing user-supplied zip ({size_mb:.1f} MB)...") | |
| _ensure_repo() | |
| _api().upload_file( | |
| path_or_fileobj=local_zip_path, | |
| path_in_repo=ZIP_REPO_PATH, | |
| repo_id=HF_REPO_ID, | |
| repo_type=HF_REPO_TYPE, | |
| token=HF_TOKEN, | |
| commit_message=f"Initial world upload ({size_mb:.1f} MB)", | |
| ) | |
| print("[sync_world] Zip stored on HF.") | |
| if WORLD_DIR.exists(): | |
| shutil.rmtree(WORLD_DIR) | |
| WORLD_DIR.mkdir(parents=True, exist_ok=True) | |
| with zipfile.ZipFile(local_zip_path, "r") as zf: | |
| members = zf.namelist() | |
| top_dirs = {m.split("/")[0] for m in members if m.strip("/")} | |
| if len(top_dirs) == 1: | |
| top = top_dirs.pop() | |
| for member in members: | |
| rel = member[len(top):].lstrip("/") | |
| if not rel: | |
| continue | |
| dest = WORLD_DIR / rel | |
| if member.endswith("/"): | |
| dest.mkdir(parents=True, exist_ok=True) | |
| else: | |
| dest.parent.mkdir(parents=True, exist_ok=True) | |
| with zf.open(member) as src, open(dest, "wb") as dst: | |
| shutil.copyfileobj(src, dst) | |
| else: | |
| zf.extractall(WORLD_DIR) | |
| print("[sync_world] World extracted locally.") | |
| return True | |
| except Exception as e: | |
| print(f"[sync_world] store_uploaded_zip failed: {e}") | |
| return False | |
| if __name__ == "__main__": | |
| if len(sys.argv) < 2: | |
| print(__doc__) | |
| sys.exit(1) | |
| action = sys.argv[1].lower() | |
| if action == "download": | |
| sys.exit(0 if download() else 1) | |
| elif action == "upload": | |
| sys.exit(0 if upload() else 1) | |
| elif action == "store" and len(sys.argv) >= 3: | |
| sys.exit(0 if store_uploaded_zip(sys.argv[2]) else 1) | |
| else: | |
| print(f"Unknown action: {action}") | |
| sys.exit(1) |