121 lines
3.9 KiB
Python
Executable File
121 lines
3.9 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
REPO_ROOT = Path(__file__).resolve().parents[2]
|
|
RUNTIME_ROOT = Path.home() / ".timmy" / "evennia"
|
|
GAME_DIR = RUNTIME_ROOT / "timmy_world"
|
|
VENV_DIR = RUNTIME_ROOT / "venv"
|
|
EVENNIA_BIN = VENV_DIR / "bin" / "evennia"
|
|
PYTHON_BIN = VENV_DIR / "bin" / "python3"
|
|
OPERATOR_USER = os.environ.get("TIMMY_EVENNIA_OPERATOR", "Alexander")
|
|
OPERATOR_EMAIL = os.environ.get("TIMMY_EVENNIA_OPERATOR_EMAIL", "alexpaynex@gmail.com")
|
|
OPERATOR_PASSWORD = os.environ.get("TIMMY_EVENNIA_OPERATOR_PASSWORD", "timmy-local-dev")
|
|
TIMMY_PASSWORD = os.environ.get("TIMMY_EVENNIA_TIMMY_PASSWORD", "timmy-world-dev")
|
|
|
|
|
|
def ensure_venv():
|
|
if not PYTHON_BIN.exists():
|
|
subprocess.run([sys.executable, "-m", "venv", str(VENV_DIR)], check=True)
|
|
subprocess.run([str(PYTHON_BIN), "-m", "pip", "install", "--upgrade", "pip"], check=True)
|
|
subprocess.run([str(PYTHON_BIN), "-m", "pip", "install", "evennia"], check=True)
|
|
|
|
|
|
def ensure_game_dir():
|
|
if not GAME_DIR.exists():
|
|
RUNTIME_ROOT.mkdir(parents=True, exist_ok=True)
|
|
subprocess.run([str(EVENNIA_BIN), "--init", "timmy_world"], cwd=RUNTIME_ROOT, check=True)
|
|
|
|
|
|
def run_evennia(args, env=None, timeout=600):
|
|
result = subprocess.run([str(EVENNIA_BIN), *args], cwd=GAME_DIR, env=env, timeout=timeout, capture_output=True, text=True)
|
|
if result.returncode != 0:
|
|
raise RuntimeError(result.stderr or result.stdout)
|
|
return result.stdout
|
|
|
|
|
|
def ensure_db_and_owner():
|
|
run_evennia(["migrate"])
|
|
env = os.environ.copy()
|
|
env.update(
|
|
{
|
|
"EVENNIA_SUPERUSER_USERNAME": OPERATOR_USER,
|
|
"EVENNIA_SUPERUSER_EMAIL": OPERATOR_EMAIL,
|
|
"EVENNIA_SUPERUSER_PASSWORD": OPERATOR_PASSWORD,
|
|
}
|
|
)
|
|
run_evennia(["shell", "-c", "from evennia.accounts.models import AccountDB; print(AccountDB.objects.count())"], env=env)
|
|
|
|
|
|
def ensure_server_started():
|
|
run_evennia(["start"], timeout=240)
|
|
|
|
|
|
def run_shell(code: str):
|
|
env = os.environ.copy()
|
|
env["PYTHONPATH"] = str(REPO_ROOT) + os.pathsep + env.get("PYTHONPATH", "")
|
|
return run_evennia(["shell", "-c", code], env=env)
|
|
|
|
|
|
def ensure_timmy_and_world():
|
|
code = f'''
|
|
import sys
|
|
sys.path.insert(0, {str(REPO_ROOT)!r})
|
|
from evennia.accounts.models import AccountDB
|
|
from evennia.accounts.accounts import DefaultAccount
|
|
from evennia import DefaultRoom, DefaultExit, create_object
|
|
from evennia.utils.search import search_object
|
|
from evennia_tools.layout import ROOMS, EXITS, OBJECTS
|
|
from typeclasses.objects import Object
|
|
|
|
AGENTS = ["Timmy", "Allegro", "Hermes", "Gemma"]
|
|
|
|
for agent_name in AGENTS:
|
|
acc = AccountDB.objects.filter(username__iexact=agent_name).first()
|
|
if not acc:
|
|
acc, errs = DefaultAccount.create(username=agent_name, password=TIMMY_PASSWORD)
|
|
|
|
char = list(acc.characters)[0]
|
|
if agent_name == "Timmy":
|
|
char.location = room_map["Gate"]
|
|
char.home = room_map["Gate"]
|
|
else:
|
|
char.location = room_map["Courtyard"]
|
|
char.home = room_map["Courtyard"]
|
|
char.save()
|
|
print(f"PROVISIONED {agent_name} at {char.location.key}")
|
|
'''
|
|
return run_shell(code)
|
|
|
|
|
|
def verify():
|
|
status = run_evennia(["status"], timeout=120)
|
|
info = run_evennia(["info"], timeout=120)
|
|
web = subprocess.run(
|
|
[sys.executable, "-c", "import urllib.request; r=urllib.request.urlopen('http://127.0.0.1:4001', timeout=10); print(r.status); print(r.headers.get('Content-Type'))"],
|
|
timeout=30,
|
|
capture_output=True,
|
|
text=True,
|
|
check=True,
|
|
)
|
|
return {"status": status.strip(), "info": info.strip(), "web": web.stdout.strip()}
|
|
|
|
|
|
def main():
|
|
ensure_venv()
|
|
ensure_game_dir()
|
|
ensure_db_and_owner()
|
|
ensure_server_started()
|
|
provision = ensure_timmy_and_world()
|
|
proof = verify()
|
|
print(json.dumps({"provision_stdout": provision, "verification": proof}, indent=2))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|