diff --git a/matrix_sync/__init__.py b/matrix_sync/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/matrix_sync/client.py b/matrix_sync/client.py new file mode 100644 index 0000000..1cd59c7 --- /dev/null +++ b/matrix_sync/client.py @@ -0,0 +1,66 @@ +import aiofiles +import json +import os +import sys +import matrix_sync.entry +from mcdreforged.api.all import * +from nio import AsyncClient, LoginResponse + +psi = ServerInterface.psi() + +# Cache Token. +def cache_token(resp: LoginResponse): + with open(matrix_sync.entry.TOKEN_FILE, "w") as f: + json.dump( + { + "token": resp.access_token + }, + f, + ) + +# Init Matrix bot. +async def init_client() -> None: + if not os.path.exists(matrix_sync.entry.TOKEN_FILE) or not matrix_sync.entry.settings["use_token"]: + psi.logger.info(psi.rtr("matrix_sync.run_tips.first_time_login")) + user_id = matrix_sync.entry.config["user_id"] + password = matrix_sync.entry.config["password"] + + client = AsyncClient(matrix_sync.entry.homeserver, user_id) + resp = await client.login(password, device_name="matrix-nio") + + if isinstance(resp, LoginResponse): + psi.logger.info(psi.rtr("matrix_sync.run_tips.login_success")) + cache_token(resp) + psi.logger.info(psi.rtr("matrix_sync.run_tips.get_token")) + else: + failed_tip = psi.rtr("matrix_sync.run_tips.failed") + matrix_sync.entry.homeserver_tr = psi.rtr("matrix_sync.tr.hs") + account_tr = psi.rtr("matrix_sync.tr.ac") + psi.logger.info(f"{failed_tip}: {resp}") + psi.logger.info(f'{matrix_sync.entry.homeserver_tr}: "{matrix_sync.entry.homeserver}", {account_tr}: "{user_id}"') + psi.logger.info(psi.rtr("matrix_sync.run_tips.error")) + sys.exit(1) + + else: + async with aiofiles.open(matrix_sync.entry.TOKEN_FILE, "r") as f: + contents = await f.read() + cache = json.loads(contents) + client = AsyncClient(f"{matrix_sync.entry.homeserver}") + client.access_token = cache["token"] + client.user_id = matrix_sync.entry.config["user_id"] + client.device_id = "matrix-nio" + room_id = matrix_sync.entry.config["room_id"] + + message = psi.rtr("matrix_sync.sync_tips.server_started") + + await client.room_send( + room_id, + message_type="m.room.message", + content={"msgtype": "m.text", "body": f"{message}"}, + ) + + global clientStatus + clientStatus = True + if clientStatus: + psi.logger.info(psi.rtr("matrix_sync.sync_tips.start_report")) + await client.close() \ No newline at end of file diff --git a/matrix_sync/entry.py b/matrix_sync/entry.py new file mode 100644 index 0000000..d01f63e --- /dev/null +++ b/matrix_sync/entry.py @@ -0,0 +1,63 @@ +import asyncio +import matrix_sync.client +import matrix_sync.receiver +import matrix_sync.reporter +from matrix_sync.client import init_client +from matrix_sync.receiver import getMsg +from matrix_sync.reporter import formater, sendMsg +from mcdreforged.api.all import * + +psi = ServerInterface.psi() + +# Default config. +account_config = { + "homeserver": "https://matrix.example.org", + "user_id": "@username:matrix.example.org", + "password": "your_password", + "room_id": "!your-room_id:matrix.example.org", + "room_name": "your-room-display-name" +} + +# Bot manage config. +bot_config = { + "plugin_enabled": False, + "allow_all_rooms_msg": False, + "use_token": True +} + +def on_load(server: PluginServerInterface, old): + global config, settings, DATA_FOLDR, TOKEN_FILE, homeserver + config = server.load_config_simple("config.json", account_config) + settings = server.load_config_simple("settings.json", bot_config) + DATA_FOLDER = server.get_data_folder() + tip_path = server.rtr("matrix_sync.init_tips.config_path") + server.logger.info(f"{tip_path}: {DATA_FOLDER}") + TOKEN_FILE = f"{DATA_FOLDER}/token.json" + homeserver = config["homeserver"] + if not (homeserver.startswith("https://") or homeserver.startswith("http://")): + homeserver = "https://" + config["homeserver"] + check_config() + +# Check the config. +def check_config(): + if not settings["plugin_enabled"]: + psi.logger.info(psi.rtr("matrix_sync.init_tips.need_edit_config")) + psi.unload_plugin("matrix_sync") + else: + psi.logger.info(psi.rtr("matrix_sync.init_tips.read_config")) + +# Sync processes. +@new_thread +def on_server_startup(server: PluginServerInterface): + asyncio.run(init_client()) + if matrix_sync.client.clientStatus: + asyncio.run(getMsg()) + +def on_user_info(server: PluginServerInterface, info: Info): + formater(server, info) + if matrix_sync.reporter.report: + asyncio.run(sendMsg()) + +def on_server_stop(server: PluginServerInterface, server_return_code: int): + if server_return_code == 0: + server.logger.info(server.rtr("matrix_sync.on_stop")) \ No newline at end of file diff --git a/matrix_sync/receiver.py b/matrix_sync/receiver.py new file mode 100644 index 0000000..da0a56e --- /dev/null +++ b/matrix_sync/receiver.py @@ -0,0 +1,33 @@ +import asyncio +import aiofiles +import json +import matrix_sync.entry +from mcdreforged.api.all import * +from nio import AsyncClient, MatrixRoom, RoomMessageText + +psi = ServerInterface.psi() + +async def message_callback(room: MatrixRoom, event: RoomMessageText) -> None: + roomMsg = f"[MatrixSync|{room.display_name}] {room.user_name(event.sender)}: {event.body}" + transfer = True + if not matrix_sync.entry.settings["allow_all_rooms_msg"]: + roomMsg = f"[MatrixSync] {room.user_name(event.sender)}: {event.body}" + if not room.display_name == matrix_sync.entry.config["room_name"]: + transfer = False + if event.sender == matrix_sync.entry.config["user_id"]: + transfer = False + if transfer: + psi.broadcast(f"{roomMsg}") + +async def getMsg() -> None: + async with aiofiles.open(matrix_sync.entry.TOKEN_FILE, "r") as f: + contents = await f.read() + cache = json.loads(contents) + client = AsyncClient(f"{matrix_sync.entry.homeserver}") + client.access_token = cache["token"] + client.user_id = matrix_sync.entry.config["user_id"] + client.device_id = "mcdr" + room_id = matrix_sync.entry.config["room_id"] + + client.add_event_callback(message_callback, RoomMessageText) + await client.sync_forever(timeout=0) \ No newline at end of file diff --git a/matrix_sync/reporter.py b/matrix_sync/reporter.py new file mode 100644 index 0000000..198f82b --- /dev/null +++ b/matrix_sync/reporter.py @@ -0,0 +1,47 @@ +import aiofiles +import json +import re +import matrix_sync.client +import matrix_sync.entry +from mcdreforged.api.all import * +from nio import AsyncClient + +psi = ServerInterface.psi() + +def formater(server: PluginServerInterface, info: Info): + # psi.logger.info(psi.rtr("matrix_sync.sync_tips.test")) + # Debug code: Uncomment the above to determine whether game messages have been started to be reported. + global message, report + console_tr = psi.rtr("matrix_sync.tr.cs") + message = f"<{info.player}> {info.content}" + if info.player is None: + if re.fullmatch(r'say \S*', info.content): + msg_content = '{}'.format(info.content.rsplit(' ', 1)[1]) + message = f"<{console_tr}> {msg_content}" + else: + option = psi.rtr("matrix_sync.on_console.commands") + message = f"<{console_tr}> {option} -> {info.content}" + if info.content == "stop": + message = psi.rtr("matrix_sync.sync_tips.server_stopping") + report = False + if matrix_sync.client.clientStatus: + report = True + +# Game Message reporter. +async def sendMsg() -> None: + async with aiofiles.open(matrix_sync.entry.TOKEN_FILE, "r") as f: + contents = await f.read() + cache = json.loads(contents) + client = AsyncClient(f"{matrix_sync.entry.homeserver}") + client.access_token = cache["token"] + client.user_id = matrix_sync.entry.config["user_id"] + client.device_id = "mcdr" + room_id = matrix_sync.entry.config["room_id"] + + await client.room_send( + room_id, + message_type="m.room.message", + content={"msgtype": "m.text", "body": f"{message}"}, + ) + + await client.close() \ No newline at end of file