mirror of
https://github.com/rightup/pyMC_Repeater.git
synced 2026-03-28 17:43:06 +01:00
147 lines
4.3 KiB
Python
147 lines
4.3 KiB
Python
"""
|
|
CLI client for pyMC Repeater.
|
|
Connects to an already-running repeater daemon via its HTTP API.
|
|
Reads admin password and HTTP port from the local config.yaml automatically.
|
|
"""
|
|
|
|
import sys
|
|
|
|
|
|
CONFIG_PATHS = [
|
|
"/etc/pymc_repeater/config.yaml",
|
|
"config.yaml",
|
|
]
|
|
|
|
|
|
def _load_config(config_path=None):
|
|
"""Load repeater config.yaml, trying common paths."""
|
|
import yaml
|
|
from pathlib import Path
|
|
|
|
paths = [config_path] if config_path else CONFIG_PATHS
|
|
for p in paths:
|
|
path = Path(p)
|
|
if path.is_file():
|
|
with open(path) as f:
|
|
return yaml.safe_load(f) or {}
|
|
return {}
|
|
|
|
|
|
def run_client_cli(host: str = "127.0.0.1", port: int = 8000, password: str = ""):
|
|
"""
|
|
Standalone CLI client that connects to a running repeater's HTTP API.
|
|
"""
|
|
import urllib.request
|
|
import urllib.error
|
|
import json
|
|
|
|
base_url = f"http://{host}:{port}"
|
|
|
|
# Authenticate to get JWT token
|
|
token = None
|
|
if password:
|
|
try:
|
|
auth_data = json.dumps({
|
|
"username": "admin",
|
|
"password": password,
|
|
"client_id": "pymc-cli",
|
|
}).encode()
|
|
req = urllib.request.Request(
|
|
f"{base_url}/auth/login",
|
|
data=auth_data,
|
|
headers={"Content-Type": "application/json"},
|
|
method="POST",
|
|
)
|
|
with urllib.request.urlopen(req, timeout=5) as resp:
|
|
result = json.loads(resp.read())
|
|
token = result.get("token") or result.get("data", {}).get("token")
|
|
except urllib.error.URLError as e:
|
|
print(f"Error: Cannot connect to repeater at {base_url} — {e.reason}")
|
|
sys.exit(1)
|
|
except Exception as e:
|
|
print(f"Authentication failed: {e}")
|
|
sys.exit(1)
|
|
|
|
if not token:
|
|
print("Error: Authentication failed. Check password or repeater status.")
|
|
sys.exit(1)
|
|
|
|
print(f"\npyMC Repeater CLI (connected to {base_url})")
|
|
print("Type 'help' for available commands, 'exit' to quit.\n")
|
|
|
|
while True:
|
|
try:
|
|
command = input(">> ").strip()
|
|
except (EOFError, KeyboardInterrupt):
|
|
print()
|
|
break
|
|
|
|
if not command:
|
|
continue
|
|
if command in ("exit", "quit"):
|
|
break
|
|
|
|
try:
|
|
payload = json.dumps({"command": command}).encode()
|
|
req = urllib.request.Request(
|
|
f"{base_url}/api/cli",
|
|
data=payload,
|
|
headers={
|
|
"Content-Type": "application/json",
|
|
"Authorization": f"Bearer {token}",
|
|
},
|
|
method="POST",
|
|
)
|
|
with urllib.request.urlopen(req, timeout=10) as resp:
|
|
result = json.loads(resp.read())
|
|
if result.get("success"):
|
|
print(result["data"]["reply"])
|
|
else:
|
|
print(f"Error: {result.get('error', 'Unknown error')}")
|
|
except urllib.error.URLError as e:
|
|
print(f"Connection error: {e.reason}")
|
|
except Exception as e:
|
|
print(f"Error: {e}")
|
|
|
|
|
|
def main():
|
|
"""Entry point for pymc-cli command."""
|
|
import argparse
|
|
|
|
parser = argparse.ArgumentParser(
|
|
description="Connect to a running pyMC Repeater and issue CLI commands"
|
|
)
|
|
parser.add_argument(
|
|
"--config", default=None,
|
|
help="Path to config.yaml (auto-detected if not set)",
|
|
)
|
|
parser.add_argument(
|
|
"--host", default=None,
|
|
help="Repeater HTTP host (default: 127.0.0.1)",
|
|
)
|
|
parser.add_argument(
|
|
"--port", type=int, default=None,
|
|
help="Repeater HTTP port (default: from config or 8000)",
|
|
)
|
|
args = parser.parse_args()
|
|
|
|
# Load config to get password and port automatically
|
|
config = _load_config(args.config)
|
|
repeater_cfg = config.get("repeater", {})
|
|
security_cfg = repeater_cfg.get("security", {})
|
|
password = security_cfg.get("admin_password", "")
|
|
|
|
if not password:
|
|
print("Error: No admin_password found in config.yaml.")
|
|
print("Searched: " + ", ".join(CONFIG_PATHS))
|
|
sys.exit(1)
|
|
|
|
host = args.host or "127.0.0.1"
|
|
port = args.port or config.get("http", {}).get("port", 8000)
|
|
|
|
run_client_cli(host=host, port=port, password=password)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|