1
0
Fork 0
matrix-appservice-minecraft/wrapper.py

112 lines
3.1 KiB
Python

import argparse
import logging
import re
import subprocess
import threading
from typing import List
import message_queue
LOG = logging.getLogger(__name__)
class ProcessWrapper:
"""Iterator that spawns a process and yields lines from its stdout."""
def __init__(self, command: List[str]):
self.proc = subprocess.Popen(
" ".join(command),
shell=True,
stdout=subprocess.PIPE,
stdin=subprocess.PIPE,
universal_newlines=True,
)
def __iter__(self):
return iter(self.proc.stdout.readline, "")
def send(self, msg):
self.proc.stdin.write(msg)
self.proc.stdin.flush()
def wait(self):
return self.proc.wait()
@property
def closed(self) -> bool:
return self.proc.returncode is not None
def send_process_output(
process: ProcessWrapper, msg_queue: message_queue.MessageQueue
):
# "[07:36:28] [Server thread/INFO] [minecraft/DedicatedServer]: <khr_> test"
log = LOG.getChild("process_output")
prog = re.compile(r"(\[.*\] )?\[(.*)\] \[(.*)\]: <(.*)> (.*)")
for line in process:
log.info(line.rstrip("\n"))
result = prog.search(line)
if result:
log.info(
"user: {} msg: {}".format(
result.group(4), result.group(5).rstrip("\n"),
)
)
msg_queue.add(
{"user": result.group(4), "msg": result.group(5).rstrip("\n")},
)
def relay_queue_input(
process: ProcessWrapper, msg_queue: message_queue.MessageQueue
):
log = LOG.getChild("relay_input")
while not process.closed:
try:
for message in msg_queue:
log.debug(message)
if "command" in message:
command = message["command"] + "\n"
log.debug("forwarding to process: {!r}".format(command))
process.send(command)
else:
log.debug(message)
except Exception as e:
log.exception(e)
def main():
logging.basicConfig(level=logging.DEBUG)
parser = argparse.ArgumentParser()
parser.add_argument("--matrix_server", required=True)
parser.add_argument("--matrix_server_port", type=int, default=5001)
parser.add_argument("command", nargs=argparse.REMAINDER)
args = parser.parse_args()
LOG.info("Running Minecraft Server Wrapper")
wrapper = ProcessWrapper(args.command)
queue = message_queue.MessageQueue(
host=args.matrix_server,
port=args.matrix_server_port,
side=message_queue.Side.CLIENT,
)
send_worker = threading.Thread(
target=send_process_output, args=(wrapper, queue), daemon=True,
)
receive_worker = threading.Thread(
target=relay_queue_input, args=(wrapper, queue), daemon=True,
)
send_worker.start()
receive_worker.start()
LOG.info("All threads created")
send_worker.join()
receive_worker.join()
queue.close()
LOG.info("All threads terminated")
return wrapper.wait()
if __name__ == "__main__":
main()