Files

72 lines
3.8 KiB
Python

import os
import re
import sys
from pathlib import Path
service = sys.argv[1] if len(sys.argv) == 2 else ""
if service not in ("realmd", "mangosd"):
raise SystemExit("Expected realmd or mangosd")
password = Path("/run/secrets/db_password").read_text().strip()
if not re.fullmatch(r"[A-Za-z0-9]{32,}", password):
raise SystemExit("DB password must contain at least 32 alphanumeric characters")
host = os.environ.get("DB_HOST", "db")
if not re.fullmatch(r"[A-Za-z0-9.-]+", host):
raise SystemExit("Invalid DB_HOST")
def connection(db):
return f'"{host};3306;vmangos;{password};{db}"'
values = {"LogsDir": '"/var/log/vmangos"', "BindIP": '"0.0.0.0"', "ProcessPriority": "0", "WaitAtStartupError": "0"}
if service == "realmd":
values.update({"LoginDatabaseInfo": connection("realmd"), "PatchesDir": '"/data/patches"'})
else:
for name, db in (("Login", "realmd"), ("World", "mangos"), ("Character", "characters"), ("Logs", "logs")):
values[name + "Database.Info"] = connection(db)
for name, key, default, minimum, maximum in (
("PLAYER_LIMIT", "PlayerLimit", 100, 1, 10000),
("WOW_PATCH", "WowPatch", 10, 0, 10),
("PARTY_BOT_MAX_BOTS", "PartyBot.MaxBots", 4, 0, 39),
("BATTLE_BOT_AUTO_JOIN", "BattleBot.AutoJoin", 0, 0, 1),
):
value = int(os.environ.get(name, default))
if not minimum <= value <= maximum:
raise SystemExit("Invalid " + name)
values[key] = str(value)
values.update({"DataDir": '"/data"', "HonorDir": '"/var/log/vmangos"', "RealmID": "1", "RealmZone": "12", "DeclinedNames": "1", "Console.Enable": "0", "Ra.Enable": "0", "SOAP.Enabled": "0", "PlayerSave.Interval": "300000"})
values.update({"Warden.WinEnabled": "0", "Warden.OSXEnabled": "0"})
quest_drop = os.environ.get("RATE_DROP_ITEM_QUEST", "2")
if not re.fullmatch(r"[0-9]{1,2}(\.[0-9]{1,2})?", quest_drop) or not 0 < float(quest_drop) <= 10:
raise SystemExit("Invalid RATE_DROP_ITEM_QUEST")
values["Rate.Drop.Item.Quest"] = quest_drop
console = os.environ.get("CONSOLE_ENABLE", "0")
if console not in ("0", "1"):
raise SystemExit("Invalid CONSOLE_ENABLE")
values["Console.Enable"] = console
voice = os.environ.get("MOONWELL_VOICE_ENABLE", "0")
if voice not in ("0", "1"):
raise SystemExit("Invalid MOONWELL_VOICE_ENABLE")
values["MoonWell.Voice.Enable"] = voice
if voice == "1":
secret_file = Path("/run/secrets/voice_secret")
if not secret_file.is_file():
raise SystemExit("MOONWELL_VOICE_ENABLE=1 needs the voice_secret secret")
secret = secret_file.read_text().strip()
if not re.fullmatch(r"[A-Za-z0-9]{32,}", secret):
raise SystemExit("The voice secret must contain at least 32 alphanumeric characters")
values["MoonWell.Voice.Secret"] = f'"{secret}"'
for name, key in (("MOONWELL_VOICE_ADDRESS", "MoonWell.Voice.Address"), ("MOONWELL_VOICE_FEED", "MoonWell.Voice.Feed")):
address = os.environ.get(name, "")
if not re.fullmatch(r"[A-Za-z0-9.-]+:[0-9]{1,5}", address):
raise SystemExit("Invalid " + name)
values[key] = f'"{address}"'
for directory in ("5875/dbc", "maps", "vmaps", "mmaps"):
if not Path("/data", directory).is_dir():
raise SystemExit("Missing client data: /data/" + directory)
text = Path("/opt/templates", service + ".conf").read_text()
for key, value in values.items():
text, count = re.subn(r"(?m)^" + re.escape(key) + r"\s*=.*$", lambda _: key + " = " + value, text)
if count != 1:
raise SystemExit("Unknown or duplicate config option: " + key)
config = Path("/run/vmangos", service + ".conf")
config.write_text(text)
config.chmod(0o600)
os.execv("/opt/vmangos/bin/" + service, [service, "-c", str(config)])