Files
retro-alcoi/setup-quake/setup_quake.py
T
2026-03-16 10:17:30 +01:00

133 lines
3.6 KiB
Python

#!/usr/bin/env python3
"""
setup-quake: Install ioquake3 and download Quake 3 data files
to the real user's home directory for use at a retro gaming fair.
Usage: sudo ./setup-quake
"""
import argparse
import configparser
import os
import pwd
import subprocess
import sys
import urllib.request
import zipfile
def get_script_dir():
"""Return the directory containing the script or binary."""
if getattr(sys, "frozen", False):
return os.path.dirname(sys.executable)
return os.path.dirname(os.path.abspath(__file__))
def parse_args():
parser = argparse.ArgumentParser(
description="Install ioquake3 and download Quake 3 data files."
)
parser.parse_args()
def check_root():
if os.geteuid() != 0:
print("Error: this script must be run as root (use sudo).", file=sys.stderr)
sys.exit(1)
def load_config():
config_path = os.path.join(get_script_dir(), "config.ini")
cfg = configparser.ConfigParser()
cfg.read(config_path)
files_url = cfg.get("quake", "files_url", fallback="https://php.sustancia.synology.me/files/ioquake3-files.zip")
install_dir = cfg.get("quake", "install_dir", fallback=".q3a")
return files_url, install_dir
def get_real_home():
"""Resolve the actual user's home when running under sudo."""
sudo_user = os.environ.get("SUDO_USER")
if sudo_user:
home_dir = pwd.getpwnam(sudo_user).pw_dir
return home_dir, sudo_user
home_dir = os.path.expanduser("~")
return home_dir, "root"
def install_ioquake3():
print(" Running: apt-get install -y ioquake3")
subprocess.run(["apt-get", "install", "-y", "ioquake3"], check=True)
def download_files(url):
"""Download the Quake 3 files zip to /tmp. Returns destination path."""
dest = "/tmp/ioquake3-files.zip"
print(f" Downloading: {url}")
print(f" Destination: {dest}")
with urllib.request.urlopen(url) as response:
total = response.headers.get("Content-Length")
total_mb = f"{int(total) / 1024 / 1024:.1f} MB" if total else "unknown size"
print(f" File size: {total_mb}")
downloaded = 0
chunk_size = 1024 * 1024 # 1 MB
with open(dest, "wb") as f:
while True:
chunk = response.read(chunk_size)
if not chunk:
break
f.write(chunk)
downloaded += len(chunk)
print(f" Downloaded: {downloaded / 1024 / 1024:.1f} MB", end="\r")
print() # newline after progress
return dest
def extract_files(zip_path, home_dir, install_dir):
target = os.path.join(home_dir, install_dir)
print(f" Extracting to: {target}")
os.makedirs(target, exist_ok=True)
with zipfile.ZipFile(zip_path) as zf:
zf.extractall(target)
os.remove(zip_path)
print(f" Cleaned up: {zip_path}")
def main():
parse_args()
check_root()
files_url, install_dir = load_config()
home_dir, username = get_real_home()
print("=== setup-quake ===")
print(f" User : {username}")
print(f" Home directory : {home_dir}")
print(f" Install dir : {os.path.join(home_dir, install_dir)}")
print()
print("[1/3] Installing ioquake3...")
install_ioquake3()
print()
print("[2/3] Downloading Quake 3 data files...")
zip_path = download_files(files_url)
print()
print("[3/3] Extracting data files...")
extract_files(zip_path, home_dir, install_dir)
print()
print("Done. Verify with:")
print(f" dpkg -l ioquake3")
print(f" ls {os.path.join(home_dir, install_dir)}")
if __name__ == "__main__":
main()