107 lines
3.4 KiB
Python
107 lines
3.4 KiB
Python
#!/usr/bin/env python3
|
|
import base64
|
|
import json
|
|
import os
|
|
import shutil
|
|
import sys
|
|
import urllib.error
|
|
import urllib.request
|
|
from pathlib import Path
|
|
|
|
PROJECT_ROOT = Path(__file__).resolve().parents[1]
|
|
UPROJECT = PROJECT_ROOT / "FunnyGirl.uproject"
|
|
DEST = PROJECT_ROOT / "Plugins" / "MobileFSR"
|
|
BRANCH = os.environ.get("MOBILE_FSR_BRANCH", "5.6.1-release")
|
|
TOKEN = os.environ.get("GITHUB_TOKEN", "")
|
|
OWNER = "EpicGames"
|
|
REPO = "UnrealEngine"
|
|
SOURCE_PATH = "Engine/Plugins/Runtime/MobileFSR"
|
|
API_ROOT = f"https://api.github.com/repos/{OWNER}/{REPO}/contents"
|
|
|
|
|
|
def request_json(url):
|
|
request = urllib.request.Request(url)
|
|
request.add_header("Accept", "application/vnd.github+json")
|
|
request.add_header("X-GitHub-Api-Version", "2022-11-28")
|
|
if TOKEN:
|
|
request.add_header("Authorization", f"Bearer {TOKEN}")
|
|
|
|
try:
|
|
with urllib.request.urlopen(request) as response:
|
|
return json.loads(response.read().decode("utf-8"))
|
|
except urllib.error.HTTPError as error:
|
|
body = error.read().decode("utf-8", errors="replace")
|
|
raise RuntimeError(f"GitHub API failed: HTTP {error.code}\n{body}") from error
|
|
|
|
|
|
def download_file(api_url, output_path):
|
|
data = request_json(api_url)
|
|
encoding = data.get("encoding")
|
|
content = data.get("content")
|
|
if encoding != "base64" or content is None:
|
|
raise RuntimeError(f"Unsupported file response for {api_url}")
|
|
|
|
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
output_path.write_bytes(base64.b64decode(content))
|
|
|
|
|
|
def download_dir(source_path, output_dir):
|
|
url = f"{API_ROOT}/{source_path}?ref={BRANCH}"
|
|
entries = request_json(url)
|
|
if not isinstance(entries, list):
|
|
raise RuntimeError(f"Expected directory listing for {source_path}")
|
|
|
|
for entry in entries:
|
|
name = entry["name"]
|
|
entry_type = entry["type"]
|
|
if entry_type == "dir":
|
|
download_dir(entry["path"], output_dir)
|
|
elif entry_type == "file":
|
|
rel_path = Path(entry["path"]).relative_to(SOURCE_PATH)
|
|
print(f"Downloading {rel_path}")
|
|
download_file(entry["url"], output_dir / rel_path)
|
|
else:
|
|
print(f"Skipping {entry['path']} ({entry_type})")
|
|
|
|
|
|
def enable_plugin():
|
|
data = json.loads(UPROJECT.read_text())
|
|
plugins = data.setdefault("Plugins", [])
|
|
for plugin in plugins:
|
|
if plugin.get("Name") == "MobileFSR":
|
|
plugin["Enabled"] = True
|
|
break
|
|
else:
|
|
plugins.append({"Name": "MobileFSR", "Enabled": True})
|
|
UPROJECT.write_text(json.dumps(data, indent="\t") + "\n")
|
|
|
|
|
|
def main():
|
|
if not TOKEN:
|
|
print("GITHUB_TOKEN is required for private EpicGames/UnrealEngine access.", file=sys.stderr)
|
|
return 1
|
|
|
|
tmp_dest = DEST.with_name(".MobileFSR.download")
|
|
shutil.rmtree(tmp_dest, ignore_errors=True)
|
|
shutil.rmtree(DEST, ignore_errors=True)
|
|
tmp_dest.mkdir(parents=True)
|
|
|
|
print(f"Downloading MobileFSR from {OWNER}/{REPO}:{BRANCH}")
|
|
download_dir(SOURCE_PATH, tmp_dest)
|
|
|
|
if not (tmp_dest / "MobileFSR.uplugin").exists():
|
|
print("MobileFSR.uplugin was not downloaded; aborting.", file=sys.stderr)
|
|
return 1
|
|
|
|
shutil.rmtree(DEST, ignore_errors=True)
|
|
shutil.move(str(tmp_dest), str(DEST))
|
|
enable_plugin()
|
|
|
|
print(f"Installed MobileFSR to {DEST}")
|
|
print(f"Enabled MobileFSR in {UPROJECT}")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|