From 29803204e6eaa1b08f9b33a1bc3a3b030d1db428 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=A8=E6=B3=A0?= Date: Sun, 15 Dec 2024 17:27:49 +0800 Subject: [PATCH 1/3] Revert "Update to v2.4.1" --- .github/workflows/build.yml | 12 +- .gitignore | 1 - README.md | 49 ++++--- README_en_us.md | 21 ++- config.ini | 5 +- descriptions/en_us.md | 1 - descriptions/zh_cn.md | 1 - doc/introduction-zh_cn.md | 3 + doc/introduction.md | 3 + docs.md | 21 +-- lang/en_us.yml | 24 +--- lang/zh_cn.yml | 24 +--- matrix_sync/client.py | 43 +++---- matrix_sync/config.py | 9 +- matrix_sync/entry.py | 108 +++++++++------- matrix_sync/receiver.py | 66 +++++----- matrix_sync/reporter.py | 60 ++++----- matrix_sync/utils/__init__.py | 36 +----- matrix_sync/utils/commands.py | 120 ++++++++---------- matrix_sync/utils/globals.py | 6 +- matrix_sync/utils/token.py | 4 +- mcdreforged.plugin.json | 2 +- pack_plugin.sh | 11 ++ .../advancement_tips/__init__.py | 56 ++++++++ .../AdvancementTips/mcdreforged.plugin.json | 15 +++ .../DeathTips/death_tips/__init__.py | 83 ++++++++++++ .../DeathTips/mcdreforged.plugin.json | 16 +++ subpacks(rolling)/README.md | 3 + .../[MSync]AutoReply/mcdreforged.plugin.json | 15 +++ .../msync_auto_reply/__init__.py | 44 +++++++ .../[MSync]AutoReply/requirements.txt | 1 + .../mcdreforged.plugin.json | 15 +++ .../msync_more_msg/__init__.py | 34 +++++ subpacks(rolling)/[MSync]PlayerBind/.temp | 1 + .../mcdreforged.plugin.json | 15 +++ .../msync_playing_tips/__init__.py | 28 ++++ .../mcdreforged.plugin.json | 15 +++ .../msync_debugger/__init__.py | 12 ++ 38 files changed, 659 insertions(+), 324 deletions(-) delete mode 100644 .gitignore delete mode 100644 descriptions/en_us.md delete mode 100644 descriptions/zh_cn.md create mode 100644 doc/introduction-zh_cn.md create mode 100644 doc/introduction.md create mode 100644 subpacks(rolling)/AdvancementTips/advancement_tips/__init__.py create mode 100644 subpacks(rolling)/AdvancementTips/mcdreforged.plugin.json create mode 100644 subpacks(rolling)/DeathTips/death_tips/__init__.py create mode 100644 subpacks(rolling)/DeathTips/mcdreforged.plugin.json create mode 100644 subpacks(rolling)/README.md create mode 100644 subpacks(rolling)/[MSync]AutoReply/mcdreforged.plugin.json create mode 100644 subpacks(rolling)/[MSync]AutoReply/msync_auto_reply/__init__.py create mode 100644 subpacks(rolling)/[MSync]AutoReply/requirements.txt create mode 100644 subpacks(rolling)/[MSync]MoreMessages/mcdreforged.plugin.json create mode 100644 subpacks(rolling)/[MSync]MoreMessages/msync_more_msg/__init__.py create mode 100644 subpacks(rolling)/[MSync]PlayerBind/.temp create mode 100644 subpacks(rolling)/[MSync]PlayingTips/mcdreforged.plugin.json create mode 100644 subpacks(rolling)/[MSync]PlayingTips/msync_playing_tips/__init__.py create mode 100644 subpacks(rolling)/[MSync]plgDebugger/mcdreforged.plugin.json create mode 100644 subpacks(rolling)/[MSync]plgDebugger/msync_debugger/__init__.py diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bb0beb5..8e20301 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,8 +3,10 @@ name: 自动打包插件 on: push: branches: - - mdf - dev # 触发打包的分支,可以根据需要修改 + pull_request: + branches: + - dev # 可以修改为触发的 PR 分支 jobs: build: @@ -21,10 +23,16 @@ jobs: - name: 检查构建 run: | ls + tree "subpacks(rolling)" + + - name: 移动构建 + run: | + find subpacks\(rolling\) -type f -name 'MSync.*.mcdr' -exec mv {} . \; - name: 上传插件 uses: actions/upload-artifact@v3 with: name: plugin path: | - MatrixSync-*.mcdr \ No newline at end of file + MatrixSync-*.mcdr + MSync.*.mcdr \ No newline at end of file diff --git a/.gitignore b/.gitignore deleted file mode 100644 index ba0430d..0000000 --- a/.gitignore +++ /dev/null @@ -1 +0,0 @@ -__pycache__/ \ No newline at end of file diff --git a/README.md b/README.md index 76638ad..d15abca 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ - 中文 - [English](https://github.com/Mooling0602/MatrixSync-MCDR/blob/main/README_en_us.md) -> 为避免合并入主分支后链接指向错误,URL一律使用主分支的地址。如果你正在访问其他分支,请注意自行定位链接跳转位置。 # MatrixSync-MCDR 一个MCDR(全称[MCDReforged](https://mcdreforged.com/))插件,用于同步Matrix群组和《我的世界》服务器的线上游戏之间的消息。 @@ -9,6 +8,8 @@ 开发过程中用到的pypi项目:[matrix-nio](https://pypi.org/project/matrix-nio/)。 +当前分支版本:主分支@2.4.0 + ## 用法 从release下载最新版本,在MCDReforged的启动环境中安装好需要的Python依赖,然后扔到plugins文件夹里面即可。 @@ -18,23 +19,32 @@ 若消息同步的过程中有任意方向的消息转发出现问题,也请按配置文件部分的内容检查配置是否正确。 +### 使用 Git 从源码打包插件 +> This part doesn't support English yet, please use translate tools at present. +> +> 依赖软件包`zip` +> +> 在终端上运行`git clone https://github.com/Mooling0602/MatrixSync-MCDR.git`,然后进入`MatrixSync-MCDR`目录下并运行`pack_plugin.sh`(记得给文件设置可执行权限) +> +> 若无法正常访问GitHub,可以运行`git clone https://mirror.ghproxy.com/https://github.com/Mooling0602/MatrixSync-MCDR.git` +> +> 懒人用命令:`git clone https://mirror.ghproxy.com/https://github.com/Mooling0602/MatrixSync-MCDR.git && cd MatrixSync-MCDR && chmod +x pack_plugin.sh && ./pack_plugin.sh` +> +> 打包脚本所用配置(config.ini)中的ci部分为主插件和配套子包的构建开关,设置为1即可打开,脚本运行后将生成打包好的插件,其中子包的构建在`subpack(rolling)/[MSync]*/内(如果开发完成),主插件的构建在主目录。 + ### 配置文件 #### config.json | 配置项 | 配置内容 | | - | - | -| **homeserver** | 机器人账号所属的根服务器 | +| **homeserver** | 机器人账号登录所使用的根服务器 | | **user_id** | 机器人的账号ID,格式为@<用户名>:<根服务器>,如@mcchatbot:example.com | -| **password** | 机器人账号的密码,在初次登录和重新生成token时使用 | -| **room_id** | 需要接收游戏消息的房间的ID,使用管理员权限在房间设置中查看 | +| **password** | 机器人账号的密码,仅在初次登录使用 | +| **room_id** | 需要接收游戏消息的房间的ID | | **room_name** | 需要转发消息到游戏内的房间的显示名称(必须准确无误,若发生更新也需要同步修改,否则你将看不到任何消息) | | **device_id** | 登录用的设备名,一般无需修改,可自定义 | -> 只支持单账号和单聊天房间(相当于QQ群),计划在v3版本以后开发多配置管理。 -> -> v2 LTS 即将推出,如果你不需要多账号、多房间管理,可以持续使用v2版本。 -> -> v2 LTS 推送将于v2.5.x进行,届时会对当前的配置文件格式进行修改,可能和之前完全不兼容,请注意。 +> 目前只支持单账号和单聊天房间(相当于QQ群),计划在v3版本以后开放多配置接口支持。 #### settings.json @@ -56,22 +66,31 @@ from matrix_sync.reporter import send_matrix def main(): message = "你要发送的消息" - send_matrix(message) + clientStatus = matrix_sync.client.clientStatus + if clientStatus: + send_matrix(message) # 消息将在独立线程MatrixReporter中被发送到Matrix,不再可能会阻塞MCDR主线程 -# 如果消息没有发送到Matrix,启用MCDR配置中的`debug.plugin`,会显示详情 ``` ## 热重载(reload)及消息互通控制 -始终建议在运行环境稳定时,尽量不使用热重载。 +插件默认在游戏服务端启动完成时自动启动房间消息接收进程,在游戏服务端关闭后自动关闭房间消息接收进程。 + +要手动启动房间消息接收器(例如重载插件后的场景),请执行MCDR命令`!!msync start`,游戏内和控制台上都可以使用。 + +要提前关闭房间消息接收器,可以在控制台使用`!!msync stop`,直到下次服务器启动完成前消息接收器都必须手动使用`!!msync start`重新启动。 + +插件会自动在解析到游戏内的消息时尝试转发到配置好的Matrix房间内,暂时无法禁用,将于v2.4.0以后版本(v2.4.x)中通过和房间消息接收器同步开闭状态的方式解决。 + +该指令没有权限要求,但设置了进程锁(安全机制),重复执行会警告提示,不会影响插件功能的正常运行。 -现在Matrix消息的收发已经实现同步,使用`!!msync`查看帮助。 +请注意,该功能仍然是不稳定的,若发现任何错误请及时通过GitHub Issue向插件作者反馈。另外,重载插件前尽量先关闭房间消息接收器,否则可能无法清楚残留进程,导致只能重启整个MCDR解决! -服务器启动完成后,插件会自动启动Minecraft游戏服务器和Matrix之间的消息互通,暂时不能对消息的收发方向进行配置。(将于2.5.x继续改善) +建议在运行环境稳定时,尽量不使用热重载。 ## 注意 ### 关于首次使用 -首次加载插件的时候,插件将自动初始化配置并卸载自己。你需要正确修改默认的配置文件,并在settings.json中启用plugin_enabled配置项以启用插件,然后重载插件以正常使用。 +首次加载插件的时候,插件将自动初始化配置并卸载自己。你需要正确修改默认的配置文件,并在settings.json中启用plugin_enabled配置项以启用插件,然后重启服务器或着重载插件以正常使用。若选择后一个方案,在插件重载后如果服务器已启动完毕,你可以使用`!!msync start`启动房间消息接收器,使Matrix的消息转发到游戏内。另外,只要插件成功加载没有出现问题,游戏内的消息将始终自动转发到Matrix的房间,将在v2.4.0以上版本中改为和房间消息接收器同步。 - 不打算支持加密信息(EE2E),有需要可以二次开发修改插件,欢迎PR。 diff --git a/README_en_us.md b/README_en_us.md index 87c9dde..0c55048 100644 --- a/README_en_us.md +++ b/README_en_us.md @@ -1,6 +1,5 @@ - [中文](https://github.com/Mooling0602/MatrixSync-MCDR/blob/main/README.md) - English -> To avoid incorrect links after merging into the main branch, all URLs should use the main branch's address. If you are accessing other branches, please make sure to manually adjust the link's target location. # MatrixSync-MCDR A MCDR (full name [MCDReforged](https://mcdreforged.com/)) plugin, use to sync messages between Matrix groups and online gaming in Minecraft servers. @@ -11,6 +10,8 @@ The following project is used in the development process: [matrix-nio](https://p Thanks for ChatGPT and Google Translate's help to translate the content from Chinese, if anything wrong, please issue to feedback or PR to `/lang`. +Present branch version: main@2.4.0 + ## Usage Download the latest version from the release, install the necessary Python dependencies in the MCDReforged startup environment, and then throw it into the plugins folder. @@ -25,7 +26,7 @@ If there is any issue with message forwarding in any direction during the messag | Configuration Item | Content | | - | - | -| **homeserver** | The homeserver address used to log in to the bot account | +| **homeserver** | The home server used to log in to the bot account | | **user_id** | The bot account ID, formatted as @username:example.com | | **password** | The password of the bot account, generally only used for the initial login | | **room_id** | The ID of the room to receive game messages | @@ -42,12 +43,22 @@ Multi-config is not supported, will add API support for developers from v3. | sync_old_msg | Whether to sync old messages, enabled on default, disable to see old messages when plugin is just loaded | ## Interface (API) -See the docs in [中文文档](https://github.com/Mooling0602/MatrixSync-MCDR/blob/docs.md) at present. +See "接口(API)" [中文](https://github.com/Mooling0602/MatrixSync-MCDR/blob/README.md) README. ## Hot Reload (reload) & message sync control -It is advisable not to use hot reload in a stable environment. +By default, the plugin automatically starts the room message reception process when the game server starts and automatically stops the process when the game server shuts down. + +To manually start the room message receiver (e.g., after reloading the plugin), execute the MCDR command !!msync start, which can be used both in-game and in the console. + +To stop the room message receiver in advance, you can use !!msync stop in the console. The message receiver must be manually restarted with !!msync start before the next server startup. -Execute `!!msync` to see the usage. +The plugin will automatically attempt to forward in-game messages to the configured Matrix room when parsing them. This feature cannot be disabled at the moment but will be resolved in version 2.4.0 (v2.4.x) by syncing the open/close status with the room message receiver. + +This command has no permission requirements but is protected by a process lock (security mechanism). Repeated execution will trigger a warning but will not affect the normal operation of the plugin. + +Please note that this feature is still unstable. If any errors occur, please report them promptly via GitHub Issues to the plugin author. Additionally, before reloading the plugin, it's recommended to close the room message receiver, as failing to do so may leave residual processes that could only be cleared by restarting the entire MCDR. + +It is advisable not to use hot reload in a stable environment. ## Note ### First-time Use diff --git a/config.ini b/config.ini index db81378..5054226 100644 --- a/config.ini +++ b/config.ini @@ -3,8 +3,9 @@ [framework] ver=3 [main] -ver=2.4.1 +ver=2.4.0 [release] test=0 [ci] -plugin=1 \ No newline at end of file +plugin=1 +subpack=0 \ No newline at end of file diff --git a/descriptions/en_us.md b/descriptions/en_us.md deleted file mode 100644 index cc480b2..0000000 --- a/descriptions/en_us.md +++ /dev/null @@ -1 +0,0 @@ -A MCDR (full name "MCDReforged") plugin sync messages between online game and Matrix groups, uses the Apache-2.0 open source license. \ No newline at end of file diff --git a/descriptions/zh_cn.md b/descriptions/zh_cn.md deleted file mode 100644 index c01de2b..0000000 --- a/descriptions/zh_cn.md +++ /dev/null @@ -1 +0,0 @@ -一个使用 Apache-2.0 开源协议的MCDR(全称MCDReforged)插件,用于同步Matrix群组和《我的世界》服务器的线上游戏之间的消息。 diff --git a/doc/introduction-zh_cn.md b/doc/introduction-zh_cn.md new file mode 100644 index 0000000..d033cf1 --- /dev/null +++ b/doc/introduction-zh_cn.md @@ -0,0 +1,3 @@ +一个MCDR(全称MCDReforged)插件,用于同步Matrix群组和《我的世界》服务器的线上游戏之间的消息。 + +2.2.0 版本修复了久未解决的许多问题,并从该版本开始正式使用 Apache-2.0 开源协议。 diff --git a/doc/introduction.md b/doc/introduction.md new file mode 100644 index 0000000..62b2b4b --- /dev/null +++ b/doc/introduction.md @@ -0,0 +1,3 @@ +A MCDR (full name "MCDReforged") plugin sync messages between online game and Matrix groups. + +Version 2.2.0 fixes many long-pending issues and officially uses the Apache-2.0 open source license from that release. \ No newline at end of file diff --git a/docs.md b/docs.md index 43e5807..87832af 100644 --- a/docs.md +++ b/docs.md @@ -1,8 +1,8 @@ - 中文 -- English (Unsupported yet, please use translate tools at present.) +- English (Unsupported yet, please use translate tools.) # MatrixSync-MCDR 文档 -这里是MCDReforged插件MatrixSync的API文档。 +这里是MCDReforged插件MatrixSync的文档。 插件配置部分仍保留在README。 @@ -18,17 +18,22 @@ import ... from matrix_sync.reporter import send_matrix def main(): - # 若message为MCDR.ServerInterface.rtr(),你需要将其转换为str类型,或改用MCDR.ServerInterface.tr(),否则会发生错误。 - # 该问题的产生原因未知,暂时无法解决。 - message = "你要发送的消息" send_matrix(message) ``` -目前发送结果可以通过启用MCDR配置中的debug.plugin项获取。 +目前仍无法获取发送结果,但如果主插件在加载时没有成功初始化客户端,你可以通过以下方式获取到相关报错: +```python +import ... +from matrix_sync.reporter import sender +def main(): + response = send_matrix(message) + if response is not None: + print(response) +``` > 在MCDR中,常用`server.logger.info`或`psi.logger.info`代替`print`,以进行更标准化的日志格式输出。 ### 旧版接口(v2.2-) -旧版接口具有体验问题和潜在错误(会阻塞MCDR主线程,消息发不出去等故障情况将导致MCDR卡死),且一般情况下已不具备实用的应用场景,但仍然可用。 +旧版接口含有较大缺陷(会阻塞MCDR主线程,消息发不出去等故障情况将导致MCDR卡死),且已不具备实用的应用场景,但仍然可用。 ```python import ... import asyncio @@ -50,4 +55,4 @@ async def async_main(): 任何情况下,都不要再尝试使用这个接口! -另外,建议马上停止使用v2.3.x版本,如果你正在使用! \ No newline at end of file +另外,建议停止使用v2.3.x版本。 \ No newline at end of file diff --git a/lang/en_us.yml b/lang/en_us.yml index 08fb534..25d3e59 100644 --- a/lang/en_us.yml +++ b/lang/en_us.yml @@ -1,22 +1,16 @@ matrix_sync: - debug: - send_command: Message you typed has sent to matrix. init_tips: config_path: Config path need_edit_config: Please edit the default config.json to the correct configuration information, and then restart the plugin after enabling the plugin_enabled item in settings.json! read_config: Applying precent config, please waiting... - user_mismatch: Detected token cached mismatch present bot account (%user_id%), please delete token or use correct bot account! - do_unload: Plugin is unloading, please reload manually after you configured right. + hotload_tip: If reloading plugin needs to enable message sync manually, to transfer messages from matrix to the game, please execute `!!msync start` on_console: commands: Excute command on_server_stop: Server stopped, stopping messages sync. on_server_crash: Server crashed or not stopped normally, stopping messages sync, unknown errors may happen. on_unload: Unloading plugin, waiting for message sync process to exit... - unload_tips: - on_clean: Execute clean process. - start_clean: Preparing clean... run_tips: - failed: Failed to login + failed: Failed to login! first_time_login: First login, continuing with password... login_success: Login successfully, caching token for later uses. get_token: Token Cached! @@ -34,8 +28,6 @@ matrix_sync: server_started: MC Server started successfully! server_crashed: MC Server crashed or not stopped normally! reporter_status: Message sync has inited on MC Server! - msync_running: Message sync is running - msync_stopped: Message sync is stopped start_report: Bot login successfully, sent a test message. test: Player message detected, trying to send to Matrix group... tr: @@ -43,11 +35,7 @@ matrix_sync: ac: Account cs: Console help_tips: - message: "See command help page for §7!!msync§r " - title: "----- MatrixSync command help page -----" - root_command: "§7!!msync §rShow this help page" - start_command: "§7!!msync start §rStart message sync(Auto executes when server startup.)" - stop_command: "§7!!msync stop §rStop message sync(Auto stops when server exit.)" - send_command: "§7!!msync send §rSend a text message to the matrix room, can be quote by \"\" if spaces are included in the text." - status_command: "§7!!msync status §rSee the present status of message sync" - reload_command: "§7!!msync reload §rReload this plugin and apply config changes" + title: "!!msync Command Help" + start_command: "!!msync start - Start message sync process. (will automatically start when server startup) " + stop_command: "!!msync stop - Stop message sync process. (will automatically stop when server stopped)" + closetip_command: Use !!msync closetip to close the numerous prompts that appear after starting message sync. It is recommended to read and understand them carefully before closing. diff --git a/lang/zh_cn.yml b/lang/zh_cn.yml index bf044b3..000fd69 100644 --- a/lang/zh_cn.yml +++ b/lang/zh_cn.yml @@ -1,22 +1,16 @@ matrix_sync: - debug: - send_command: 已将你输入的消息发送到Matrix init_tips: config_path: 配置文件所在目录 need_edit_config: 请将默认配置config.json修改为正确的配置信息,然后启用settings.json中的plugin_enabled项后重启插件! read_config: 正在应用当前配置,请稍等…… - user_mismatch: 检测到当前配置的机器人账号(%user_id%)与缓存的token不符,请删除当前token.json或使用正确的账号! - do_unload: 插件将卸载,请在处理完成后手动重载插件! + hotload_tip: 若重载插件需要手动开启消息同步,以将Matrix的消息转发到游戏中,请执行!!msync start on_console: commands: 执行命令 on_server_stop: 服务器已关闭,停止消息同步。 on_server_crash: 服务器崩溃或者非正常退出,已停止消息同步,可能出现未知报错。 on_unload: 正在卸载插件,等待消息同步进程退出…… - unload_tips: - on_clean: 执行清理进程 - start_clean: 正在准备清理... run_tips: - failed: 登录失败 + failed: 登录失败! first_time_login: 首次登录,将使用密码继续…… login_success: 登录成功,正在缓存Token以供后续使用。 get_token: Token缓存完成! @@ -34,8 +28,6 @@ matrix_sync: server_started: "[√] 服务器启动完成!" server_crashed: "[×] 服务器崩溃或非正常退出!" reporter_status: "[!] 消息互通已在游戏服务器上初始化完成" - msync_running: 消息互通正在运行 - msync_stopped: 消息互通未在运行 start_report: 机器人登录成功,已发送测试消息。 test: 检测到玩家消息,正在尝试发送到Matrix群组…… tr: @@ -43,11 +35,7 @@ matrix_sync: ac: 账户 cs: 控制台 help_tips: - message: "查看指令 §7!!msync §r的帮助" - title: "----- MatrixSync 指令帮助 -----" - root_command: "§7!!msync §r显示此帮助页面" - start_command: "§7!!msync start §r开始消息同步(服务器启动完成时会自动开始)" - stop_command: "§7!!msync stop §r关闭消息同步(服务端停止运行后会自动关闭)" - send_command: "§7!!msync send §r向Matrix房间发送指定消息,若含有空格请使用\"\"括起来" - status_command: "§7!!msync status §r查看当前消息同步状态" - reload_command: "§7!!msync reload §r重载插件并刷新插件配置" \ No newline at end of file + title: "!!msync 指令帮助" + start_command: "!!msync start - 开始消息同步(服务器启动完成时会自动开始)" + stop_command: "!!msync stop - 关闭消息同步(服务端停止运行后会自动关闭)" + closetip_command: "!!msync closetip - 关闭消息同步开始后出现的大量提示,建议认真阅读理解后再关闭" diff --git a/matrix_sync/client.py b/matrix_sync/client.py index c0760b5..bb0e00e 100644 --- a/matrix_sync/client.py +++ b/matrix_sync/client.py @@ -2,23 +2,21 @@ import json import os import sys - -from .utils import psi, plgSelf, tr -from .utils.token import getToken -from .reporter import sendMsg -from mcdreforged.api.decorator import new_thread +import matrix_sync.config +from matrix_sync.reporter import sendMsg +from mcdreforged.api.all import * from nio import AsyncClient, LoginResponse +psi = ServerInterface.psi() clientStatus = False # Cache Token. def cache_token(resp: LoginResponse): - from .config import TOKEN_FILE, user_id + TOKEN_FILE = matrix_sync.config.TOKEN_FILE with open(TOKEN_FILE, "w") as f: json.dump( { - "user_id": user_id, "token": resp.access_token }, f, @@ -33,36 +31,35 @@ async def init_task(): await init_client() async def init_client() -> None: - from .config import TOKEN_FILE, homeserver, user_id, password, device_id + TOKEN_FILE = matrix_sync.config.TOKEN_FILE + homeserver = matrix_sync.config.homeserver + user_id = matrix_sync.config.user_id + password = matrix_sync.config.password + device_id = matrix_sync.config.device_id + psi.logger.info(user_id) if not os.path.exists(TOKEN_FILE): - psi.logger.info(tr("run_tips.first_time_login")) + psi.logger.info(psi.rtr("matrix_sync.run_tips.first_time_login")) client = AsyncClient(homeserver, user_id) resp = await client.login(password, device_name=f"{device_id}") if isinstance(resp, LoginResponse): - psi.logger.info(tr("run_tips.login_success")) + psi.logger.info(psi.rtr("matrix_sync.run_tips.login_success")) cache_token(resp) - psi.logger.info(tr("run_tips.get_token")) + psi.logger.info(psi.rtr("matrix_sync.run_tips.get_token")) await test_client() else: - failed_tip = tr("run_tips.failed") - homeserver_tr = tr("tr.hs") - account_tr = tr("tr.ac") + failed_tip = psi.rtr("matrix_sync.run_tips.failed") + 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'{homeserver_tr}: "{homeserver}", {account_tr}: "{user_id}"') - psi.logger.info(tr("run_tips.error")) + psi.logger.info(psi.rtr("matrix_sync.run_tips.error")) sys.exit(1) else: - user, token = await getToken() - if user != user_id: - psi.logger.error(tr("init_tips.user_mismatch")) - psi.logger.info(tr("init_tips.do_unload")) - psi.unload_plugin(plgSelf.id) - else: - await test_client() + await test_client() # Send test messages. async def test_client(): global clientStatus - message = tr("sync_tips.reporter_status") + message = psi.rtr("matrix_sync.sync_tips.reporter_status") await sendMsg(message) clientStatus = True diff --git a/matrix_sync/config.py b/matrix_sync/config.py index 7ea9920..514b646 100644 --- a/matrix_sync/config.py +++ b/matrix_sync/config.py @@ -1,5 +1,6 @@ -from .utils import psi +from mcdreforged.api.all import * +psi = ServerInterface.psi() lock_is_None = True # Default config. @@ -16,11 +17,7 @@ bot_config = { "plugin_enabled": False, "allow_all_rooms_msg": False, - "sync_old_msg": False, - "room_msg_format": { - "single_room": "[MSync] %sender%: %message%", - "multi_room": "[MSync|%room_display_name%] %sender%: %message%" - } + "sync_old_msg": False } def load_config(): diff --git a/matrix_sync/entry.py b/matrix_sync/entry.py index bb90d40..7932481 100644 --- a/matrix_sync/entry.py +++ b/matrix_sync/entry.py @@ -1,74 +1,90 @@ -import time +import asyncio +import matrix_sync.config +import matrix_sync.client +import matrix_sync.receiver +import matrix_sync.reporter -from typing import Optional -from .utils import tr -from .client import init -from .config import load_config, check_config -from .utils import psi, globals -from .utils.commands import * -from .reporter import send_matrix +from matrix_sync.utils.globals import * +from matrix_sync.client import init +from matrix_sync.config import load_config, check_config +from matrix_sync.utils.commands import * +from matrix_sync.reporter import send_matrix from mcdreforged.api.all import * - -# Framwork ver: 2.4.1 -def on_load(server: PluginServerInterface, prev_module): +# Framwork ver: 2.4.0-3 +def on_load(server: PluginServerInterface, old): load_config() - from .config import load_tip - server.logger.info(load_tip) + server.logger.info(matrix_sync.config.load_tip) check_config() - from .config import do_unload + do_unload = matrix_sync.config.do_unload if do_unload: - server.unload_plugin(plgSelf.id) + server.unload_plugin("matrix_sync") else: init() plugin_command(server) - if server.is_server_startup(): - start_sync() + server.logger.info(psi.rtr("matrix_sync.init_tips.hotload_tip")) + +# Restart room message receiver, not recommend. +# def restartSync(src): +# stopSync(src) +# manualSync() # Automatically run sync processes. -def start_sync(on_reload: Optional[bool] = True): - if not globals.tLock.locked(): - start_room_msg() - if not on_reload: - time.sleep(1) - message = tr("sync_tips.server_started") +def on_server_startup(server: PluginServerInterface): + clientStatus = matrix_sync.client.clientStatus + if not tLock.locked(): + if clientStatus: + message = psi.rtr("matrix_sync.sync_tips.server_started") send_matrix(message) + start_room_msg() else: - psi.logger.info(tr("manual_sync.start_error")) - -def on_server_startup(server: PluginServerInterface): - start_sync(False) + server.logger.info(server.rtr("matrix_sync.manual_sync.start_error")) # Game message reporter def on_user_info(server: PluginServerInterface, info: Info): + # formater(server, info) if info.player is not None and not info.content.startswith("!!"): playerMsg = f"<{info.player}> {info.content}" - send_matrix(playerMsg) + clientStatus = matrix_sync.client.clientStatus + if clientStatus: + send_matrix(playerMsg) # Exit sync process when server stop. def on_server_stop(server: PluginServerInterface, server_return_code: int): + global cleaned, sync_task if server_return_code == 0: - server.logger.info(tr("on_server_stop")) - exit_message = tr("sync_tips.server_stopped") + server.logger.info(server.rtr("matrix_sync.on_server_stop")) + clientStatus = matrix_sync.client.clientStatus + stopTip = server.rtr("matrix_sync.sync_tips.server_stopped") + if clientStatus: + send_matrix(stopTip) else: - server.logger.info(tr("on_server_crash")) - exit_message = tr("sync_tips.server_crashed") - - # 鉴于有用户反馈关服时消息发送不到Matrix,这里卡一个协程用于发送 - # 为了防止卡住MCDR主线程出现无响应提示影响用户体验,一般都在子线程中发送消息,但是直接用协程正常情况下也没啥问题 - # 有bug的话应该会有人在issues提出,暂时先这么解决 - from .reporter import sendMsg - asyncio.run(sendMsg(exit_message)) + server.logger.info(server.rtr("matrix_sync.on_server_crash")) + crashTip = server.rtr("matrix_sync.sync_tips.server_crashed") + clientStatus = matrix_sync.client.clientStatus + if clientStatus: + send_matrix(crashTip) + + if sync_task is not None: + sync_task.cancel() + try: + pass + except asyncio.TimeoutError: + server.logger.warning("Timed out waiting for sync_task to finish.") - globals.cleaned = True + cleaned = True def on_unload(server: PluginServerInterface): - server.logger.info(tr("unload_tips.on_clean")) - if globals.cleaned: - server.logger.info(tr("on_unload")) + global sync_task, cleaned + if cleaned: + server.logger.info(server.rtr("matrix_sync.on_unload")) else: - psi.logger.info(tr("unload_tips.start_clean")) - psi.logger.info(exit_sync()) - from .config import lock_is_None + if sync_task is not None: + sync_task.cancel() + try: + pass + except asyncio.TimeoutError: + server.logger.warning("Timed out waiting for sync_task to finish.") + sync_task = None if not lock_is_None: - server.logger.info(tr("on_unload")) \ No newline at end of file + server.logger.info(server.rtr("matrix_sync.on_unload")) diff --git a/matrix_sync/receiver.py b/matrix_sync/receiver.py index 092c644..59b198f 100644 --- a/matrix_sync/receiver.py +++ b/matrix_sync/receiver.py @@ -2,14 +2,14 @@ import asyncio import matrix_sync.config -from .utils.token import getToken -from .utils import psi, plgSelf, tr -from mcdreforged.api.event import PluginEvent +from matrix_sync.utils.token import getToken +from matrix_sync.utils.globals import psi +from mcdreforged.api.all import * from nio import AsyncClient, MatrixRoom, RoomMessageText, SyncError from typing import Optional - homeserver_online = True +msg_callback = False class RoomMessageEvent(PluginEvent): def __init__(self, message: str, sender: str, room: Optional[str] = None): @@ -19,23 +19,24 @@ def __init__(self, message: str, sender: str, room: Optional[str] = None): self.room = room async def message_callback(room: MatrixRoom, event: RoomMessageText) -> None: + global msg_callback transfer = False - from .config import user_id, room_name, settings - msg_format = settings["room_msg_format"]["multi_room"] - roomMsg = msg_format.replace('%room_display_name%', room.display_name).replace('%sender%', room.user_name(event.sender)).replace('%message%', event.body) - # Avoid echo messages. - if not event.sender == user_id: - # Apply settings config - if not matrix_sync.config.settings["allow_all_rooms_msg"]: - msg_format = matrix_sync.config.settings["room_msg_format"]["single_room"] - roomMsg = msg_format.replace('%sender%', room.user_name(event.sender)).replace('%message%', event.body) - if room.display_name == room_name: - transfer = True - psi.dispatch_event(RoomMessageEvent(event.body, room.user_name(event.sender)), (event.body, room.user_name(event.sender))) - else: - psi.dispatch_event(RoomMessageEvent(event.body, room.user_name(event.sender), room.display_name), (event.body, room.user_name(event.sender), room.display_name)) - if transfer: - psi.broadcast(f"{roomMsg}") + user_id = matrix_sync.config.user_id + room_name = matrix_sync.config.room_name + roomMsg = f"[MSync|{room.display_name}] {room.user_name(event.sender)}: {event.body}" + if msg_callback: + # Avoid echo messages. + if not event.sender == user_id: + # Apply settings config + if not matrix_sync.config.settings["allow_all_rooms_msg"]: + roomMsg = f"[MSync] {room.user_name(event.sender)}: {event.body}" + if room.display_name == room_name: + transfer = True + psi.dispatch_event(RoomMessageEvent(event.body, room.user_name(event.sender)), (event.body, room.user_name(event.sender))) + else: + psi.dispatch_event(RoomMessageEvent(event.body, room.user_name(event.sender), room.display_name), (event.body, room.user_name(event.sender), room.display_name)) + if transfer: + psi.broadcast(f"{roomMsg}") def on_sync_error(response: SyncError): global homeserver_online @@ -45,33 +46,30 @@ def on_sync_error(response: SyncError): async def getMsg() -> None: global next_batch, msg_callback - from .config import homeserver, device_id, user_id, sync_old_msg + homeserver = matrix_sync.config.homeserver + device_id = matrix_sync.config.device_id + user_id = matrix_sync.config.user_id + sync_old_msg = matrix_sync.config.sync_old_msg client = AsyncClient(f"{homeserver}") - user, token = await getToken() - client.access_token = token - if user != user_id: - if user is not None: - tip = tr("init_tips.user_mismatch") - psi.logger.error(tip.replace("%user_id%", user_id)) - psi.logger.info(tr("init_tips.do_unload")) - psi.unload_plugin(plgSelf.id) - else: - client.user_id = user_id - client.device_id = device_id + client.access_token = await getToken() + client.user_id = user_id + client.device_id = device_id client.add_response_callback(on_sync_error, SyncError) + client.add_event_callback(message_callback, RoomMessageText) try: if homeserver_online: if sync_old_msg is True: await client.sync_forever(timeout=5) else: + msg_callback = False await client.sync(timeout=5) - client.add_event_callback(message_callback, RoomMessageText) + msg_callback = True await client.sync_forever(timeout=5) else: psi.logger.error("Sync failed: homeserver is down or your network disconnected with it.") - psi.logger.info("Use §7!!msync start §rafter homeserver is running or your network restored.") + psi.logger.info("Use !!msync start after homeserver is running or your network restored.") except Exception as e: psi.logger.error(f"Sync error: {e}") except asyncio.CancelledError: diff --git a/matrix_sync/reporter.py b/matrix_sync/reporter.py index 3c35bb2..ff543ec 100644 --- a/matrix_sync/reporter.py +++ b/matrix_sync/reporter.py @@ -1,11 +1,10 @@ import asyncio -import re +import matrix_sync.config -from mcdreforged.api.decorator import new_thread +from mcdreforged.api.all import * from nio import AsyncClient -from .utils import psi, plgSelf, tr, globals -from .utils.token import getToken - +from matrix_sync.utils.token import getToken +from matrix_sync.utils.globals import psi # Game Message reporter. @new_thread('MatrixReporter') @@ -13,38 +12,25 @@ def send_matrix(message): asyncio.run(send(message)) async def send(message): - from .client import clientStatus - if clientStatus: - if globals.report_matrix: - await sendMsg(message) - psi.logger.debug("消息已发送!") - else: - psi.logger.debug("消息未发送:同步未启动") - else: - psi.logger.debug("消息未发送:bot未初始化成功") + await sendMsg(message) async def sendMsg(message) -> None: - from .config import homeserver, user_id, room_id, device_id + homeserver = matrix_sync.config.homeserver + user_id = matrix_sync.config.user_id + room_id = matrix_sync.config.room_id + device_id = matrix_sync.config.device_id client = AsyncClient(f"{homeserver}") - user, token = await getToken() - client.access_token = token - if user != user_id: - tip = tr("init_tips.user_mismatch") - psi.logger.error(tip.replace("%user_id%", user_id)) - psi.logger.info(tr("init_tips.do_unload")) - psi.unload_plugin(plgSelf.id) - else: - client.user_id = user_id - client.device_id = device_id - - pattern = re.compile(r'§[0-9a-v]') - - message_to_send = re.sub(pattern, '', message) - - await client.room_send( - room_id, - message_type="m.room.message", - content={"msgtype": "m.text", "body": message_to_send}, - ) - - await client.close() + client.access_token = await getToken() + client.user_id = user_id + client.device_id = device_id + + try: + await client.room_send( + room_id, + message_type="m.room.message", + content={"msgtype": "m.text", "body": f"{message}"}, + ) + + await client.close() + except Exception as e: + psi.logger.error(f"Send to matrix error: {e}") diff --git a/matrix_sync/utils/__init__.py b/matrix_sync/utils/__init__.py index c09a8b7..b974282 100644 --- a/matrix_sync/utils/__init__.py +++ b/matrix_sync/utils/__init__.py @@ -1,35 +1 @@ -from typing import Optional -from mcdreforged.api.all import * - -psi = ServerInterface.psi() -MCDRConfig = psi.get_mcdr_config() -plgSelf = psi.get_self_metadata() -serverDir = MCDRConfig["working_directory"] -configDir = psi.get_data_folder() -builder = SimpleCommandBuilder() - -def tr(tr_key: str, return_str: Optional[bool] = True): - ''' - 对`ServerInterface.rtr()`进行优化,提高翻译效率。 - - 参数: - tr_key (str): 原始或简化后的翻译键名称 - return_str (可选[bool]): 是否尝试转换成字符串减少出错 - - 返回: - translation: RTextMCDRTranslation组件 - 或tr_to_str: 字符串 - ''' - if tr_key.startswith(f"{plgSelf.id}"): - translation = psi.rtr(f"{tr_key}") - else: - # 使用此前缀代表非本插件的翻译键,则翻译时不会附加本插件的ID,避免错误。 - if tr_key.startswith("#"): - translation = psi.rtr(tr_key.replace("#", "")) - else: - translation = psi.rtr(f"{plgSelf.id}.{tr_key}") - if return_str: - tr_to_str: str = str(translation) - return tr_to_str - else: - return translation \ No newline at end of file +from . import * \ No newline at end of file diff --git a/matrix_sync/utils/commands.py b/matrix_sync/utils/commands.py index 86efe87..5e577a9 100644 --- a/matrix_sync/utils/commands.py +++ b/matrix_sync/utils/commands.py @@ -1,91 +1,77 @@ import asyncio -from . import builder, tr, globals from mcdreforged.api.all import * -from . import psi, plgSelf -from ..reporter import send_matrix -from ..receiver import getMsg +from matrix_sync.utils.globals import * +from matrix_sync.receiver import getMsg +psi = ServerInterface.psi() def plugin_command(server: PluginServerInterface): - help_message = tr("help_tips.message", False) - server.register_help_message("!!msync", help_message) - builder.arg("message", QuotableText) - builder.register(server) - -@builder.command("!!msync send ") -def send_command(src: CommandSource, ctx: CommandContext): - send_matrix(ctx["message"]) - src.reply(tr("debug.send_command")) + server.register_help_message("!!msync", help()) + server.register_command( + Literal('!!msync') + .then( + Literal('start') + .runs( + lambda src: src.reply(manualSync()) + ) + ) + # .then( + # Literal('restart') + # .runs( + # lambda src: src.reply(restartSync()) + # ) + # ) + .then( + Literal('stop') + .runs( + lambda src: src.reply(stopSync(src)) + ) + ) + ) # Help tips. -@builder.command("!!msync") -@builder.command("!!msync help") -def show_help(src: CommandSource): - pfx = f"{plgSelf.id}.help_tips" - src.reply(RTextList( - tr(f"{pfx}.title", False) + "\n", - tr(f"{pfx}.root_command", False) + "\n", - tr(f"{pfx}.start_command", False) + "\n", - tr(f"{pfx}.stop_command", False) + "\n", - tr(f"{pfx}.send_command", False) + "\n", - tr(f"{pfx}.status_command", False) + "\n", - tr(f"{pfx}.reload_command", False) + "\n" - )) +def help() -> RTextList: + return RTextList( + psi.rtr("matrix_sync.help_tips.title") + "\n", + psi.rtr("matrix_sync.help_tips.start_command") + "\n", + psi.rtr("matrix_sync.help_tips.stop_command") + "\n", + psi.rtr("matrix_sync.help_tips.closetip_command") + "\n" + ) # Manually run sync processes. -@builder.command("!!msync start") -def manualSync(src: CommandSource): - if not globals.tLock.locked(): - globals.report_matrix = True +def manualSync(): + if not tLock.locked(): start_room_msg() - src.reply(tr("manual_sync.start_sync")) - else: - src.reply(tr("manual_sync.start_error")) - -@builder.command("!!msync status") -def syncStatus(src: CommandSource): - if globals.report_matrix is True: - src.reply(tr("sync_tips.msync_running")) + return psi.rtr("matrix_sync.manual_sync.start_sync") else: - src.reply(tr("sync_tips.msync_stopped")) - -def exit_sync(): - try: - if globals.sync_task is not None: - globals.sync_task.cancel() - globals.report_matrix = False - globals.sync_task = None - return tr("manual_sync.stop_sync") - else: - return tr("manual_sync.not_running") - except Exception as e: - psi.logger.error(f"Error exit {plgSelf.id}: {e}") - return tr("manual_sync.stop_error") + return psi.rtr("matrix_sync.manual_sync.start_error") # Manually stop sync processes. -@builder.command("!!msync stop") def stopSync(src): + global sync_task if src.is_console: - response = exit_sync() - src.reply(response) + try: + if sync_task is not None: + sync_task.cancel() + return psi.rtr("matrix_sync.manual_sync.stop_sync") + else: + return psi.rtr("matrix_sync.manual_sync.not_running") + except Exception: + return psi.rtr("matrix_sync.manual_sync.stop_error") else: - src.reply(tr("manual_sync.stop_denied")) - -@builder.command("!!msync reload") -def reload_plugin(): - psi.reload_plugin(plgSelf.id) + return psi.rtr("matrix_sync.manual_sync.stop_denied") # Sub thread to receive room messages from matrix without block main MCDR thread. @new_thread('MatrixReceiver') def start_room_msg(): - with globals.tLock: - globals.report_matrix = True + with tLock: asyncio.run(on_room_msg()) async def on_room_msg(): - if globals.sync_task is not None and not globals.sync_task.done(): - globals.sync_task.cancel() - await globals.sync_task - globals.sync_task = asyncio.create_task(getMsg()) - await globals.sync_task \ No newline at end of file + global sync_task + if sync_task is not None and not sync_task.done(): + sync_task.cancel() + await sync_task + sync_task = asyncio.create_task(getMsg()) + await sync_task \ No newline at end of file diff --git a/matrix_sync/utils/globals.py b/matrix_sync/utils/globals.py index ac2fbc6..22c1316 100644 --- a/matrix_sync/utils/globals.py +++ b/matrix_sync/utils/globals.py @@ -1,6 +1,10 @@ import threading +from .. import config +from mcdreforged.api.all import * + +psi = ServerInterface.psi() tLock = threading.Lock() -report_matrix = False +lock_is_None = config.lock_is_None cleaned = False sync_task = None \ No newline at end of file diff --git a/matrix_sync/utils/token.py b/matrix_sync/utils/token.py index b69a7b1..2a48427 100644 --- a/matrix_sync/utils/token.py +++ b/matrix_sync/utils/token.py @@ -8,6 +8,4 @@ async def getToken(): async with aiofiles.open(TOKEN_FILE, "r") as f: contents = await f.read() cache = json.loads(contents) - user_id = cache.get("user_id", None) - token = cache.get("token", None) - return user_id, token \ No newline at end of file + return cache["token"] \ No newline at end of file diff --git a/mcdreforged.plugin.json b/mcdreforged.plugin.json index e456fa0..f524b47 100644 --- a/mcdreforged.plugin.json +++ b/mcdreforged.plugin.json @@ -1,6 +1,6 @@ { "id": "matrix_sync", - "version": "2.4.1", + "version": "2.4.0", "name": "MatrixSync", "description": { "en_us": "Sync messages between online game and Matrix groups.", diff --git a/pack_plugin.sh b/pack_plugin.sh index 20d036b..cc76b31 100644 --- a/pack_plugin.sh +++ b/pack_plugin.sh @@ -26,4 +26,15 @@ if [ "$build_plg" -eq 1 ]; then else zip -r "MatrixSync-v${main_ver}.mcdr" README.md README_en_us.md mcdreforged.plugin.json requirements.txt LICENSE lang matrix_sync fi +fi +if [ "$build_subpack" -eq 1 ]; then + pushd "subpacks(rolling)/[MSync]AutoReply" >> /dev/null + zip -r "MSync.AutoReply.mcdr" msync_auto_reply mcdreforged.plugin.json requirements.txt + popd >> /dev/null + pushd "subpacks(rolling)/[MSync]MoreMessages" >> /dev/null + zip -r "MSync.MoreMessages.mcdr" msync_more_msg mcdreforged.plugin.json + popd >> /dev/null + pushd "subpacks(rolling)/[MSync]PlayingTips" >> /dev/null + zip -r "MSync.PlayingTips.mcdr" msync_playing_tips mcdreforged.plugin.json + popd >> /dev/null fi \ No newline at end of file diff --git a/subpacks(rolling)/AdvancementTips/advancement_tips/__init__.py b/subpacks(rolling)/AdvancementTips/advancement_tips/__init__.py new file mode 100644 index 0000000..5f0fb89 --- /dev/null +++ b/subpacks(rolling)/AdvancementTips/advancement_tips/__init__.py @@ -0,0 +1,56 @@ +import asyncio +import re +import matrix_sync.client + +from mcdreforged.api.all import * +from matrix_sync.reporter import sendMsg +from gtl_api import parseKey, parseValue, parseContent + +psi = ServerInterface.psi() + +lang_files = { + "raw_lang": "server/plugins/Geyser-Spigot/locales/en_us.json", + "translated_lang": "server/plugins/Geyser-Spigot/locales/zh_cn.json" +} + +config = psi.load_config_simple("config.json", lang_files) + +raw_lang = config["raw_lang"] +translated_lang = config["translated_lang"] + +def on_load(server: PluginServerInterface, old): + server.logger.info("MatrixSync 子包: AdvancementsTips 已加载") + server.logger.info("本插件仅供简体中文用户使用") + server.logger.info("语言文件默认使用Geyser配置,若未使用Geyser请自行获取语言文件并配置其路径") + +def on_info(server: PluginServerInterface, info: Info): + if info.is_from_server and re.fullmatch(r'(.+) has completed the challenge (.+)', info.content): + match = re.fullmatch(r'(.+) has completed the challenge (.+)', info.content) + if match: + player = match.group(1) + raw_content = match.group(2) + content = parseContent(raw_content) + key = parseKey(raw_lang, content) + tr_content = parseValue(translated_lang, key) + if matrix_sync.client.clientStatus: + asyncio.run(sendMsg(f"[!]玩家 {player} 完成了挑战 [{tr_content}]")) + if info.is_from_server and re.fullmatch(r'(.+) has reached the goal (.+)', info.content): + match = re.fullmatch(r'(.+) has reached the goal (.+)', info.content) + if match: + player = match.group(1) + raw_content = match.group(2) + content = parseContent(raw_content) + key = parseKey(raw_lang, content) + tr_content = parseValue(translated_lang, key) + if matrix_sync.client.clientStatus: + asyncio.run(sendMsg(f"[!]玩家 {player} 达成了目标 [{tr_content}]")) + if info.is_from_server and re.fullmatch(r'(.+) has made the advancement (.+)', info.content): + match = re.fullmatch(r'(.+) has made the advancement (.+)', info.content) + if match: + player = match.group(1) + raw_content = match.group(2) + content = parseContent(raw_content) + key = parseKey(raw_lang, content) + tr_content = parseValue(translated_lang, key) + if matrix_sync.client.clientStatus: + asyncio.run(sendMsg(f"[!]玩家 {player} 取得了进度 [{tr_content}]")) \ No newline at end of file diff --git a/subpacks(rolling)/AdvancementTips/mcdreforged.plugin.json b/subpacks(rolling)/AdvancementTips/mcdreforged.plugin.json new file mode 100644 index 0000000..9b07588 --- /dev/null +++ b/subpacks(rolling)/AdvancementTips/mcdreforged.plugin.json @@ -0,0 +1,15 @@ +{ + "id": "advancements_tips", + "version": "0.0.1", + "name": "AdvancementTips", + "description": { + "en_us": "A subpack of MatrixSync, send tips to the group when player finished advancements.", + "zh_cn": "MatrixSync的子包,在玩家完成成就时在群内进行提示。" + }, + "dependencies": { + "mcdreforged": ">=2.1.0", + "matrix_sync": ">=2.0.2" + }, + "author": "Mooling0602", + "link": "https://github.com/Mooling0602/MatrixSync-MCDR" +} \ No newline at end of file diff --git a/subpacks(rolling)/DeathTips/death_tips/__init__.py b/subpacks(rolling)/DeathTips/death_tips/__init__.py new file mode 100644 index 0000000..9ce45f7 --- /dev/null +++ b/subpacks(rolling)/DeathTips/death_tips/__init__.py @@ -0,0 +1,83 @@ +import asyncio +import re +import json +import matrix_sync.client + +from mcdreforged.api.all import * +from gtl_api import parseKey, parseValue +from matrix_sync.reporter import sendMsg + +psi = ServerInterface.psi() + +lang_files = { + "raw_lang": "server/plugins/Geyser-Spigot/locales/en_us.json", + "translated_lang": "server/plugins/Geyser-Spigot/locales/zh_cn.json" +} + +config = psi.load_config_simple("config.json", lang_files) + +raw_lang = config["raw_lang"] +translated_lang = config["translated_lang"] + +death_messages = {} + +def on_load(server: PluginServerInterface, old): + server.logger.info("MatrixSync子包: DeathTips 已加载") + server.logger.info("本插件仅供简体中文用户使用") + server.logger.info("语言文件默认使用Geyser配置,若未使用Geyser请自行获取语言文件并配置其路径") + +def on_info(server: PluginServerInterface, info: Info): + global death_messages + if info.is_from_server: + key, groups = match_death_msg(raw_lang, info.content) + if key: + deathRawFormat = parseValue(raw_lang, key) + deathMsg = parseValue(translated_lang, key) + partten_deathRawFormat = re.compile(r"%(\d+)\$s") + matches_deathRawFormat = partten_deathRawFormat.findall(deathRawFormat) + regex_template = re.escape(deathRawFormat) + regex_template = regex_template.replace(r"%1\$s", r"(.+)").replace(r"%2\$s", r"(.+)").replace(r"%3\$s", r"\[(.+)\]|(.+)") + content_matches = re.match(regex_template, info.content) + if content_matches: + placeholder_to_content = {int(matches_deathRawFormat[i]): content_matches.group(i + 1) for i in range(len(matches_deathRawFormat))} + deathTip = deathMsg + for placeholder, content in placeholder_to_content.items(): + placeholder_str = f"%{placeholder}$s" + if placeholder_str == "%2$s": + contentKey = parseKey(raw_lang, content) + tr_content = parseValue(translated_lang, contentKey) + if tr_content is not None: + content = tr_content + else: + content = content + # if placeholder_str == "%3$s": + # content = re.escape(content) + deathTip = deathTip.replace(placeholder_str, content) + # 修正部分 + if re.fullmatch(r'(.+)被(.+) using \[(.+)\]|(.+)杀死了', deathTip): + match = re.fullmatch(r'(.+)被(.+) using (.+)杀死了', deathTip) + if match: + player = match.group(1) + killer = match.group(2) + weapon = match.group(3) + deathTip = f"{player}被{killer}用{weapon}杀死了" + clientStatus = matrix_sync.client.clientStatus + if clientStatus: + asyncio.run(sendMsg(deathTip)) + +def match_death_msg(lang, content): + global death_messages + with open(lang, 'r') as file: + lang = file.read() + lang = json.loads(lang) + for key in lang.keys(): + if key.startswith("death."): + value = lang.get(key, None) + if value: + value = re.sub(r'%(\d+)\$s', r'(?P.+)', value) + death_messages[key] = value + for key, value in death_messages.items(): + match = re.fullmatch(value, content) + if match: + return key, match.groupdict() + return None, None diff --git a/subpacks(rolling)/DeathTips/mcdreforged.plugin.json b/subpacks(rolling)/DeathTips/mcdreforged.plugin.json new file mode 100644 index 0000000..458e234 --- /dev/null +++ b/subpacks(rolling)/DeathTips/mcdreforged.plugin.json @@ -0,0 +1,16 @@ +{ + "id": "death_tips", + "version": "0.0.1", + "name": "DeathTips", + "description": { + "en_us": "A subpack of MatrixSync, send tips to the group when player finished advancements.", + "zh_cn": "MatrixSync的子包,在玩家死亡时在群内进行提示。" + }, + "dependencies": { + "mcdreforged": ">=2.1.0", + "matrix_sync": ">=2.0.2", + "atl_api": ">=0.0.1" + }, + "author": "Mooling0602", + "link": "https://github.com/Mooling0602/MatrixSync-MCDR" +} diff --git a/subpacks(rolling)/README.md b/subpacks(rolling)/README.md new file mode 100644 index 0000000..213d158 --- /dev/null +++ b/subpacks(rolling)/README.md @@ -0,0 +1,3 @@ +Subpacks for MatrixSync, rolling update + +MatrixSync的子包,滚动更新 diff --git a/subpacks(rolling)/[MSync]AutoReply/mcdreforged.plugin.json b/subpacks(rolling)/[MSync]AutoReply/mcdreforged.plugin.json new file mode 100644 index 0000000..a16af6b --- /dev/null +++ b/subpacks(rolling)/[MSync]AutoReply/mcdreforged.plugin.json @@ -0,0 +1,15 @@ +{ + "id": "msync_auto_reply", + "version": "0.0.2", + "name": "[MSync]AutoReply", + "description": { + "en_us": "A subpack of MatrixSync, automatically reply messages from room.", + "zh_cn": "MatrixSync的子包,自动回复房间内消息" + }, + "dependencies": { + "mcdreforged": ">=2.1.0", + "matrix_sync": ">=2.3.1" + }, + "author": "Mooling0602", + "link": "https://github.com/Mooling0602/MatrixSync-MCDR" +} \ No newline at end of file diff --git a/subpacks(rolling)/[MSync]AutoReply/msync_auto_reply/__init__.py b/subpacks(rolling)/[MSync]AutoReply/msync_auto_reply/__init__.py new file mode 100644 index 0000000..4b5e812 --- /dev/null +++ b/subpacks(rolling)/[MSync]AutoReply/msync_auto_reply/__init__.py @@ -0,0 +1,44 @@ +import os +import matrix_sync.config +import matrix_sync.client +import yaml +from mcdreforged.api.all import * +from matrix_sync.reporter import send_matrix + +CONFIG_PATH = 'config/matrix_sync/auto_reply/config.yml' + +DEFAULT_CONFIG = { + "triggers": { + "触发词1": "回复内容1", + "触发词2": "回复内容2", + "触发词3": "回复内容3" + } +} + +def load_config(): + if not os.path.exists(CONFIG_PATH): + os.makedirs(os.path.dirname(CONFIG_PATH), exist_ok=True) + with open(CONFIG_PATH, 'w', encoding='utf-8') as config_file: + yaml.dump(DEFAULT_CONFIG, config_file, allow_unicode=True) + with open(CONFIG_PATH, 'r', encoding='utf-8') as config_file: + return yaml.safe_load(config_file) + +def on_load(server: PluginServerInterface, old): + global plugin_config + plugin_config = load_config() + + server.logger.info("[MSync]AutoReply loaded.") + server.register_event_listener('MatrixRoomMessage', main) + +def main(server: PluginServerInterface, message: str, sender: str): + user_id = matrix_sync.config.user_id + triggers = plugin_config.get("triggers", {}) + + if sender != user_id: + for trigger_word, reply_content in triggers.items(): + if message == trigger_word: + clientStatus = matrix_sync.client.clientStatus + if clientStatus: + send_matrix(reply_content) + server.logger.info("解析到指定内容,已自动发送回复") + break \ No newline at end of file diff --git a/subpacks(rolling)/[MSync]AutoReply/requirements.txt b/subpacks(rolling)/[MSync]AutoReply/requirements.txt new file mode 100644 index 0000000..4818cc5 --- /dev/null +++ b/subpacks(rolling)/[MSync]AutoReply/requirements.txt @@ -0,0 +1 @@ +pyyaml \ No newline at end of file diff --git a/subpacks(rolling)/[MSync]MoreMessages/mcdreforged.plugin.json b/subpacks(rolling)/[MSync]MoreMessages/mcdreforged.plugin.json new file mode 100644 index 0000000..7afdd42 --- /dev/null +++ b/subpacks(rolling)/[MSync]MoreMessages/mcdreforged.plugin.json @@ -0,0 +1,15 @@ +{ + "id": "msync_more_msg", + "version": "0.0.2", + "name": "[MSync]MoreMessages", + "description": { + "en_us": "A subpack of MatrixSync, transfer more kinds of messages from the game.", + "zh_cn": "MatrixSync的子包,转发更多类型的游戏消息。" + }, + "dependencies": { + "mcdreforged": ">=2.1.0", + "matrix_sync": ">=2.3.1" + }, + "author": "Mooling0602", + "link": "https://github.com/Mooling0602/MatrixSync-MCDR" +} \ No newline at end of file diff --git a/subpacks(rolling)/[MSync]MoreMessages/msync_more_msg/__init__.py b/subpacks(rolling)/[MSync]MoreMessages/msync_more_msg/__init__.py new file mode 100644 index 0000000..b9838e9 --- /dev/null +++ b/subpacks(rolling)/[MSync]MoreMessages/msync_more_msg/__init__.py @@ -0,0 +1,34 @@ +import re + +from matrix_sync.reporter import send_matrix +from mcdreforged.api.all import * + +psi = ServerInterface.psi() + +def on_load(server: PluginServerInterface, old): + server.logger.info("Subpack of MatrixSync: [Msync]MoreMessages loaded.") + +def on_user_info(server: PluginServerInterface, info: Info): + formatter(info) + if gameMsg is not None: + send_matrix(gameMsg) + + +def formatter(info: Info): + global gameMsg + console_tr = psi.rtr("matrix_sync.tr.cs") + if info.player is None: + if re.fullmatch(r'say \S*', info.content): + msg_content = '{}'.format(info.content.rsplit(' ', 1)[1]) + gameMsg = f"<{console_tr}> {msg_content}" + else: + option = psi.rtr("matrix_sync.on_console.commands") + gameMsg = f"[!] {console_tr} {option} -> {info.content}" + if info.content == "stop": + gameMsg = psi.rtr("matrix_sync.sync_tips.server_stopping") + else: + if info.content.startswith("!!"): + option = psi.rtr("matrix_sync.on_console.commands") + gameMsg = f"[!] {info.player} {option} -> {info.content}" + else: + return None \ No newline at end of file diff --git a/subpacks(rolling)/[MSync]PlayerBind/.temp b/subpacks(rolling)/[MSync]PlayerBind/.temp new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/subpacks(rolling)/[MSync]PlayerBind/.temp @@ -0,0 +1 @@ + diff --git a/subpacks(rolling)/[MSync]PlayingTips/mcdreforged.plugin.json b/subpacks(rolling)/[MSync]PlayingTips/mcdreforged.plugin.json new file mode 100644 index 0000000..9c30315 --- /dev/null +++ b/subpacks(rolling)/[MSync]PlayingTips/mcdreforged.plugin.json @@ -0,0 +1,15 @@ +{ + "id": "msync_playing_tips", + "version": "0.0.1", + "name": "[MSync]PlayingTips", + "description": { + "en_us": "A subpack of MatrixSync, send tips to the group when player joined and left the game.", + "zh_cn": "MatrixSync的子包,在玩家上下线时在群内进行提示。" + }, + "dependencies": { + "mcdreforged": ">=2.1.0", + "matrix_sync": ">=2.3.1" + }, + "author": "Mooling0602", + "link": "https://github.com/Mooling0602/MatrixSync-MCDR" +} \ No newline at end of file diff --git a/subpacks(rolling)/[MSync]PlayingTips/msync_playing_tips/__init__.py b/subpacks(rolling)/[MSync]PlayingTips/msync_playing_tips/__init__.py new file mode 100644 index 0000000..d89c084 --- /dev/null +++ b/subpacks(rolling)/[MSync]PlayingTips/msync_playing_tips/__init__.py @@ -0,0 +1,28 @@ +import matrix_sync.client +import re +from matrix_sync.reporter import send_matrix +from mcdreforged.api.all import * + +def on_load(server: PluginServerInterface, old): + server.logger.info("Subpack of MatrixSync: [MSync]PlayingTips loaded.") + +def on_player_joined(server: PluginServerInterface, player: str, info: Info): + tip = f"[+]{player}" + if matrix_sync.client.clientStatus: + send_matrix(tip) + +def on_player_left(server: PluginServerInterface, player: str): + tip = f"[-]{player}" + if matrix_sync.client.clientStatus: + send_matrix(tip) + +def on_info(server: PluginServerInterface, info: Info): + if info.is_from_server and re.fullmatch(r'(.+) issued server command: (.+)', info.content): + match = re.fullmatch(r'(.+) issued server command: (.+)', info.content) + if match: + player = match.group(1) + command = match.group(2) + server.say(f"* {player} 执行游戏指令 -> {command}") + clientStatus = matrix_sync.client.clientStatus + if clientStatus: + send_matrix(f"* {player} 执行游戏指令 -> {command}") diff --git a/subpacks(rolling)/[MSync]plgDebugger/mcdreforged.plugin.json b/subpacks(rolling)/[MSync]plgDebugger/mcdreforged.plugin.json new file mode 100644 index 0000000..76c68d9 --- /dev/null +++ b/subpacks(rolling)/[MSync]plgDebugger/mcdreforged.plugin.json @@ -0,0 +1,15 @@ +{ + "id": "msync_debugger", + "version": "0.0.1", + "name": "[MSync]plgDebugger", + "description": { + "en_us": "A subpack of MatrixSync, used to debug.", + "zh_cn": "MatrixSync的子包,用于调试。" + }, + "dependencies": { + "mcdreforged": ">=2.1.0", + "matrix_sync": ">=2.0.2" + }, + "author": "Mooling0602", + "link": "https://github.com/Mooling0602/MatrixSync-MCDR" +} \ No newline at end of file diff --git a/subpacks(rolling)/[MSync]plgDebugger/msync_debugger/__init__.py b/subpacks(rolling)/[MSync]plgDebugger/msync_debugger/__init__.py new file mode 100644 index 0000000..9b97f61 --- /dev/null +++ b/subpacks(rolling)/[MSync]plgDebugger/msync_debugger/__init__.py @@ -0,0 +1,12 @@ +from mcdreforged.api.all import * +from typing import Optional + +def on_load(server: PluginServerInterface, old): + server.logger.info("Subpack of MatrixSync: [MSync]plgDebugger loaded.") + server.register_event_listener('MatrixRoomMessage', main) + +def main(server: PluginServerInterface, message: str, sender: str, room: Optional[str] = None): + server.logger.info(f"Content: {message}") + server.logger.info(f"Sender: {sender}") + if room is not None: + server.logger.info(f"Room Name: {room}") \ No newline at end of file From 92427382afbb21e361abbbca8157aa00bcc9f675 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=A8=E6=B3=A0?= Date: Sun, 15 Dec 2024 17:35:34 +0800 Subject: [PATCH 2/3] Revert "Revert "Update to v2.4.1"" --- .github/workflows/build.yml | 12 +- .gitignore | 1 + README.md | 49 +++---- README_en_us.md | 21 +-- config.ini | 5 +- descriptions/en_us.md | 1 + descriptions/zh_cn.md | 1 + doc/introduction-zh_cn.md | 3 - doc/introduction.md | 3 - docs.md | 21 ++- lang/en_us.yml | 24 +++- lang/zh_cn.yml | 24 +++- matrix_sync/client.py | 43 ++++--- matrix_sync/config.py | 9 +- matrix_sync/entry.py | 108 +++++++--------- matrix_sync/receiver.py | 66 +++++----- matrix_sync/reporter.py | 60 +++++---- matrix_sync/utils/__init__.py | 36 +++++- matrix_sync/utils/commands.py | 120 ++++++++++-------- matrix_sync/utils/globals.py | 6 +- matrix_sync/utils/token.py | 4 +- mcdreforged.plugin.json | 2 +- pack_plugin.sh | 11 -- .../advancement_tips/__init__.py | 56 -------- .../AdvancementTips/mcdreforged.plugin.json | 15 --- .../DeathTips/death_tips/__init__.py | 83 ------------ .../DeathTips/mcdreforged.plugin.json | 16 --- subpacks(rolling)/README.md | 3 - .../[MSync]AutoReply/mcdreforged.plugin.json | 15 --- .../msync_auto_reply/__init__.py | 44 ------- .../[MSync]AutoReply/requirements.txt | 1 - .../mcdreforged.plugin.json | 15 --- .../msync_more_msg/__init__.py | 34 ----- subpacks(rolling)/[MSync]PlayerBind/.temp | 1 - .../mcdreforged.plugin.json | 15 --- .../msync_playing_tips/__init__.py | 28 ---- .../mcdreforged.plugin.json | 15 --- .../msync_debugger/__init__.py | 12 -- 38 files changed, 324 insertions(+), 659 deletions(-) create mode 100644 .gitignore create mode 100644 descriptions/en_us.md create mode 100644 descriptions/zh_cn.md delete mode 100644 doc/introduction-zh_cn.md delete mode 100644 doc/introduction.md delete mode 100644 subpacks(rolling)/AdvancementTips/advancement_tips/__init__.py delete mode 100644 subpacks(rolling)/AdvancementTips/mcdreforged.plugin.json delete mode 100644 subpacks(rolling)/DeathTips/death_tips/__init__.py delete mode 100644 subpacks(rolling)/DeathTips/mcdreforged.plugin.json delete mode 100644 subpacks(rolling)/README.md delete mode 100644 subpacks(rolling)/[MSync]AutoReply/mcdreforged.plugin.json delete mode 100644 subpacks(rolling)/[MSync]AutoReply/msync_auto_reply/__init__.py delete mode 100644 subpacks(rolling)/[MSync]AutoReply/requirements.txt delete mode 100644 subpacks(rolling)/[MSync]MoreMessages/mcdreforged.plugin.json delete mode 100644 subpacks(rolling)/[MSync]MoreMessages/msync_more_msg/__init__.py delete mode 100644 subpacks(rolling)/[MSync]PlayerBind/.temp delete mode 100644 subpacks(rolling)/[MSync]PlayingTips/mcdreforged.plugin.json delete mode 100644 subpacks(rolling)/[MSync]PlayingTips/msync_playing_tips/__init__.py delete mode 100644 subpacks(rolling)/[MSync]plgDebugger/mcdreforged.plugin.json delete mode 100644 subpacks(rolling)/[MSync]plgDebugger/msync_debugger/__init__.py diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8e20301..bb0beb5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,10 +3,8 @@ name: 自动打包插件 on: push: branches: + - mdf - dev # 触发打包的分支,可以根据需要修改 - pull_request: - branches: - - dev # 可以修改为触发的 PR 分支 jobs: build: @@ -23,16 +21,10 @@ jobs: - name: 检查构建 run: | ls - tree "subpacks(rolling)" - - - name: 移动构建 - run: | - find subpacks\(rolling\) -type f -name 'MSync.*.mcdr' -exec mv {} . \; - name: 上传插件 uses: actions/upload-artifact@v3 with: name: plugin path: | - MatrixSync-*.mcdr - MSync.*.mcdr \ No newline at end of file + MatrixSync-*.mcdr \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ba0430d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +__pycache__/ \ No newline at end of file diff --git a/README.md b/README.md index d15abca..76638ad 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ - 中文 - [English](https://github.com/Mooling0602/MatrixSync-MCDR/blob/main/README_en_us.md) +> 为避免合并入主分支后链接指向错误,URL一律使用主分支的地址。如果你正在访问其他分支,请注意自行定位链接跳转位置。 # MatrixSync-MCDR 一个MCDR(全称[MCDReforged](https://mcdreforged.com/))插件,用于同步Matrix群组和《我的世界》服务器的线上游戏之间的消息。 @@ -8,8 +9,6 @@ 开发过程中用到的pypi项目:[matrix-nio](https://pypi.org/project/matrix-nio/)。 -当前分支版本:主分支@2.4.0 - ## 用法 从release下载最新版本,在MCDReforged的启动环境中安装好需要的Python依赖,然后扔到plugins文件夹里面即可。 @@ -19,32 +18,23 @@ 若消息同步的过程中有任意方向的消息转发出现问题,也请按配置文件部分的内容检查配置是否正确。 -### 使用 Git 从源码打包插件 -> This part doesn't support English yet, please use translate tools at present. -> -> 依赖软件包`zip` -> -> 在终端上运行`git clone https://github.com/Mooling0602/MatrixSync-MCDR.git`,然后进入`MatrixSync-MCDR`目录下并运行`pack_plugin.sh`(记得给文件设置可执行权限) -> -> 若无法正常访问GitHub,可以运行`git clone https://mirror.ghproxy.com/https://github.com/Mooling0602/MatrixSync-MCDR.git` -> -> 懒人用命令:`git clone https://mirror.ghproxy.com/https://github.com/Mooling0602/MatrixSync-MCDR.git && cd MatrixSync-MCDR && chmod +x pack_plugin.sh && ./pack_plugin.sh` -> -> 打包脚本所用配置(config.ini)中的ci部分为主插件和配套子包的构建开关,设置为1即可打开,脚本运行后将生成打包好的插件,其中子包的构建在`subpack(rolling)/[MSync]*/内(如果开发完成),主插件的构建在主目录。 - ### 配置文件 #### config.json | 配置项 | 配置内容 | | - | - | -| **homeserver** | 机器人账号登录所使用的根服务器 | +| **homeserver** | 机器人账号所属的根服务器 | | **user_id** | 机器人的账号ID,格式为@<用户名>:<根服务器>,如@mcchatbot:example.com | -| **password** | 机器人账号的密码,仅在初次登录使用 | -| **room_id** | 需要接收游戏消息的房间的ID | +| **password** | 机器人账号的密码,在初次登录和重新生成token时使用 | +| **room_id** | 需要接收游戏消息的房间的ID,使用管理员权限在房间设置中查看 | | **room_name** | 需要转发消息到游戏内的房间的显示名称(必须准确无误,若发生更新也需要同步修改,否则你将看不到任何消息) | | **device_id** | 登录用的设备名,一般无需修改,可自定义 | -> 目前只支持单账号和单聊天房间(相当于QQ群),计划在v3版本以后开放多配置接口支持。 +> 只支持单账号和单聊天房间(相当于QQ群),计划在v3版本以后开发多配置管理。 +> +> v2 LTS 即将推出,如果你不需要多账号、多房间管理,可以持续使用v2版本。 +> +> v2 LTS 推送将于v2.5.x进行,届时会对当前的配置文件格式进行修改,可能和之前完全不兼容,请注意。 #### settings.json @@ -66,31 +56,22 @@ from matrix_sync.reporter import send_matrix def main(): message = "你要发送的消息" - clientStatus = matrix_sync.client.clientStatus - if clientStatus: - send_matrix(message) + send_matrix(message) # 消息将在独立线程MatrixReporter中被发送到Matrix,不再可能会阻塞MCDR主线程 +# 如果消息没有发送到Matrix,启用MCDR配置中的`debug.plugin`,会显示详情 ``` ## 热重载(reload)及消息互通控制 -插件默认在游戏服务端启动完成时自动启动房间消息接收进程,在游戏服务端关闭后自动关闭房间消息接收进程。 - -要手动启动房间消息接收器(例如重载插件后的场景),请执行MCDR命令`!!msync start`,游戏内和控制台上都可以使用。 - -要提前关闭房间消息接收器,可以在控制台使用`!!msync stop`,直到下次服务器启动完成前消息接收器都必须手动使用`!!msync start`重新启动。 - -插件会自动在解析到游戏内的消息时尝试转发到配置好的Matrix房间内,暂时无法禁用,将于v2.4.0以后版本(v2.4.x)中通过和房间消息接收器同步开闭状态的方式解决。 - -该指令没有权限要求,但设置了进程锁(安全机制),重复执行会警告提示,不会影响插件功能的正常运行。 +始终建议在运行环境稳定时,尽量不使用热重载。 -请注意,该功能仍然是不稳定的,若发现任何错误请及时通过GitHub Issue向插件作者反馈。另外,重载插件前尽量先关闭房间消息接收器,否则可能无法清楚残留进程,导致只能重启整个MCDR解决! +现在Matrix消息的收发已经实现同步,使用`!!msync`查看帮助。 -建议在运行环境稳定时,尽量不使用热重载。 +服务器启动完成后,插件会自动启动Minecraft游戏服务器和Matrix之间的消息互通,暂时不能对消息的收发方向进行配置。(将于2.5.x继续改善) ## 注意 ### 关于首次使用 -首次加载插件的时候,插件将自动初始化配置并卸载自己。你需要正确修改默认的配置文件,并在settings.json中启用plugin_enabled配置项以启用插件,然后重启服务器或着重载插件以正常使用。若选择后一个方案,在插件重载后如果服务器已启动完毕,你可以使用`!!msync start`启动房间消息接收器,使Matrix的消息转发到游戏内。另外,只要插件成功加载没有出现问题,游戏内的消息将始终自动转发到Matrix的房间,将在v2.4.0以上版本中改为和房间消息接收器同步。 +首次加载插件的时候,插件将自动初始化配置并卸载自己。你需要正确修改默认的配置文件,并在settings.json中启用plugin_enabled配置项以启用插件,然后重载插件以正常使用。 - 不打算支持加密信息(EE2E),有需要可以二次开发修改插件,欢迎PR。 diff --git a/README_en_us.md b/README_en_us.md index 0c55048..87c9dde 100644 --- a/README_en_us.md +++ b/README_en_us.md @@ -1,5 +1,6 @@ - [中文](https://github.com/Mooling0602/MatrixSync-MCDR/blob/main/README.md) - English +> To avoid incorrect links after merging into the main branch, all URLs should use the main branch's address. If you are accessing other branches, please make sure to manually adjust the link's target location. # MatrixSync-MCDR A MCDR (full name [MCDReforged](https://mcdreforged.com/)) plugin, use to sync messages between Matrix groups and online gaming in Minecraft servers. @@ -10,8 +11,6 @@ The following project is used in the development process: [matrix-nio](https://p Thanks for ChatGPT and Google Translate's help to translate the content from Chinese, if anything wrong, please issue to feedback or PR to `/lang`. -Present branch version: main@2.4.0 - ## Usage Download the latest version from the release, install the necessary Python dependencies in the MCDReforged startup environment, and then throw it into the plugins folder. @@ -26,7 +25,7 @@ If there is any issue with message forwarding in any direction during the messag | Configuration Item | Content | | - | - | -| **homeserver** | The home server used to log in to the bot account | +| **homeserver** | The homeserver address used to log in to the bot account | | **user_id** | The bot account ID, formatted as @username:example.com | | **password** | The password of the bot account, generally only used for the initial login | | **room_id** | The ID of the room to receive game messages | @@ -43,23 +42,13 @@ Multi-config is not supported, will add API support for developers from v3. | sync_old_msg | Whether to sync old messages, enabled on default, disable to see old messages when plugin is just loaded | ## Interface (API) -See "接口(API)" [中文](https://github.com/Mooling0602/MatrixSync-MCDR/blob/README.md) README. +See the docs in [中文文档](https://github.com/Mooling0602/MatrixSync-MCDR/blob/docs.md) at present. ## Hot Reload (reload) & message sync control -By default, the plugin automatically starts the room message reception process when the game server starts and automatically stops the process when the game server shuts down. - -To manually start the room message receiver (e.g., after reloading the plugin), execute the MCDR command !!msync start, which can be used both in-game and in the console. - -To stop the room message receiver in advance, you can use !!msync stop in the console. The message receiver must be manually restarted with !!msync start before the next server startup. - -The plugin will automatically attempt to forward in-game messages to the configured Matrix room when parsing them. This feature cannot be disabled at the moment but will be resolved in version 2.4.0 (v2.4.x) by syncing the open/close status with the room message receiver. - -This command has no permission requirements but is protected by a process lock (security mechanism). Repeated execution will trigger a warning but will not affect the normal operation of the plugin. - -Please note that this feature is still unstable. If any errors occur, please report them promptly via GitHub Issues to the plugin author. Additionally, before reloading the plugin, it's recommended to close the room message receiver, as failing to do so may leave residual processes that could only be cleared by restarting the entire MCDR. - It is advisable not to use hot reload in a stable environment. +Execute `!!msync` to see the usage. + ## Note ### First-time Use When loading the plugin for the first time, the plugin will automatically initialize the configuration and then unload itself. You need to correctly modify the default configuration file and enable the plugin_enabled option in settings.json to activate the plugin. Then, restart the server or reload the plugin for proper use. If you choose the latter, after reloading the plugin, if the server has finished starting, you can use !!msync start to start the room message receiver, enabling Matrix message forwarding to the game. Furthermore, as long as the plugin is successfully loaded without issues, in-game messages will always be automatically forwarded to the Matrix room. This will be synchronized with the room message receiver in versions above 2.4.0. diff --git a/config.ini b/config.ini index 5054226..db81378 100644 --- a/config.ini +++ b/config.ini @@ -3,9 +3,8 @@ [framework] ver=3 [main] -ver=2.4.0 +ver=2.4.1 [release] test=0 [ci] -plugin=1 -subpack=0 \ No newline at end of file +plugin=1 \ No newline at end of file diff --git a/descriptions/en_us.md b/descriptions/en_us.md new file mode 100644 index 0000000..cc480b2 --- /dev/null +++ b/descriptions/en_us.md @@ -0,0 +1 @@ +A MCDR (full name "MCDReforged") plugin sync messages between online game and Matrix groups, uses the Apache-2.0 open source license. \ No newline at end of file diff --git a/descriptions/zh_cn.md b/descriptions/zh_cn.md new file mode 100644 index 0000000..c01de2b --- /dev/null +++ b/descriptions/zh_cn.md @@ -0,0 +1 @@ +一个使用 Apache-2.0 开源协议的MCDR(全称MCDReforged)插件,用于同步Matrix群组和《我的世界》服务器的线上游戏之间的消息。 diff --git a/doc/introduction-zh_cn.md b/doc/introduction-zh_cn.md deleted file mode 100644 index d033cf1..0000000 --- a/doc/introduction-zh_cn.md +++ /dev/null @@ -1,3 +0,0 @@ -一个MCDR(全称MCDReforged)插件,用于同步Matrix群组和《我的世界》服务器的线上游戏之间的消息。 - -2.2.0 版本修复了久未解决的许多问题,并从该版本开始正式使用 Apache-2.0 开源协议。 diff --git a/doc/introduction.md b/doc/introduction.md deleted file mode 100644 index 62b2b4b..0000000 --- a/doc/introduction.md +++ /dev/null @@ -1,3 +0,0 @@ -A MCDR (full name "MCDReforged") plugin sync messages between online game and Matrix groups. - -Version 2.2.0 fixes many long-pending issues and officially uses the Apache-2.0 open source license from that release. \ No newline at end of file diff --git a/docs.md b/docs.md index 87832af..43e5807 100644 --- a/docs.md +++ b/docs.md @@ -1,8 +1,8 @@ - 中文 -- English (Unsupported yet, please use translate tools.) +- English (Unsupported yet, please use translate tools at present.) # MatrixSync-MCDR 文档 -这里是MCDReforged插件MatrixSync的文档。 +这里是MCDReforged插件MatrixSync的API文档。 插件配置部分仍保留在README。 @@ -18,22 +18,17 @@ import ... from matrix_sync.reporter import send_matrix def main(): + # 若message为MCDR.ServerInterface.rtr(),你需要将其转换为str类型,或改用MCDR.ServerInterface.tr(),否则会发生错误。 + # 该问题的产生原因未知,暂时无法解决。 + message = "你要发送的消息" send_matrix(message) ``` -目前仍无法获取发送结果,但如果主插件在加载时没有成功初始化客户端,你可以通过以下方式获取到相关报错: -```python -import ... -from matrix_sync.reporter import sender +目前发送结果可以通过启用MCDR配置中的debug.plugin项获取。 -def main(): - response = send_matrix(message) - if response is not None: - print(response) -``` > 在MCDR中,常用`server.logger.info`或`psi.logger.info`代替`print`,以进行更标准化的日志格式输出。 ### 旧版接口(v2.2-) -旧版接口含有较大缺陷(会阻塞MCDR主线程,消息发不出去等故障情况将导致MCDR卡死),且已不具备实用的应用场景,但仍然可用。 +旧版接口具有体验问题和潜在错误(会阻塞MCDR主线程,消息发不出去等故障情况将导致MCDR卡死),且一般情况下已不具备实用的应用场景,但仍然可用。 ```python import ... import asyncio @@ -55,4 +50,4 @@ async def async_main(): 任何情况下,都不要再尝试使用这个接口! -另外,建议停止使用v2.3.x版本。 \ No newline at end of file +另外,建议马上停止使用v2.3.x版本,如果你正在使用! \ No newline at end of file diff --git a/lang/en_us.yml b/lang/en_us.yml index 25d3e59..08fb534 100644 --- a/lang/en_us.yml +++ b/lang/en_us.yml @@ -1,16 +1,22 @@ matrix_sync: + debug: + send_command: Message you typed has sent to matrix. init_tips: config_path: Config path need_edit_config: Please edit the default config.json to the correct configuration information, and then restart the plugin after enabling the plugin_enabled item in settings.json! read_config: Applying precent config, please waiting... - hotload_tip: If reloading plugin needs to enable message sync manually, to transfer messages from matrix to the game, please execute `!!msync start` + user_mismatch: Detected token cached mismatch present bot account (%user_id%), please delete token or use correct bot account! + do_unload: Plugin is unloading, please reload manually after you configured right. on_console: commands: Excute command on_server_stop: Server stopped, stopping messages sync. on_server_crash: Server crashed or not stopped normally, stopping messages sync, unknown errors may happen. on_unload: Unloading plugin, waiting for message sync process to exit... + unload_tips: + on_clean: Execute clean process. + start_clean: Preparing clean... run_tips: - failed: Failed to login! + failed: Failed to login first_time_login: First login, continuing with password... login_success: Login successfully, caching token for later uses. get_token: Token Cached! @@ -28,6 +34,8 @@ matrix_sync: server_started: MC Server started successfully! server_crashed: MC Server crashed or not stopped normally! reporter_status: Message sync has inited on MC Server! + msync_running: Message sync is running + msync_stopped: Message sync is stopped start_report: Bot login successfully, sent a test message. test: Player message detected, trying to send to Matrix group... tr: @@ -35,7 +43,11 @@ matrix_sync: ac: Account cs: Console help_tips: - title: "!!msync Command Help" - start_command: "!!msync start - Start message sync process. (will automatically start when server startup) " - stop_command: "!!msync stop - Stop message sync process. (will automatically stop when server stopped)" - closetip_command: Use !!msync closetip to close the numerous prompts that appear after starting message sync. It is recommended to read and understand them carefully before closing. + message: "See command help page for §7!!msync§r " + title: "----- MatrixSync command help page -----" + root_command: "§7!!msync §rShow this help page" + start_command: "§7!!msync start §rStart message sync(Auto executes when server startup.)" + stop_command: "§7!!msync stop §rStop message sync(Auto stops when server exit.)" + send_command: "§7!!msync send §rSend a text message to the matrix room, can be quote by \"\" if spaces are included in the text." + status_command: "§7!!msync status §rSee the present status of message sync" + reload_command: "§7!!msync reload §rReload this plugin and apply config changes" diff --git a/lang/zh_cn.yml b/lang/zh_cn.yml index 000fd69..bf044b3 100644 --- a/lang/zh_cn.yml +++ b/lang/zh_cn.yml @@ -1,16 +1,22 @@ matrix_sync: + debug: + send_command: 已将你输入的消息发送到Matrix init_tips: config_path: 配置文件所在目录 need_edit_config: 请将默认配置config.json修改为正确的配置信息,然后启用settings.json中的plugin_enabled项后重启插件! read_config: 正在应用当前配置,请稍等…… - hotload_tip: 若重载插件需要手动开启消息同步,以将Matrix的消息转发到游戏中,请执行!!msync start + user_mismatch: 检测到当前配置的机器人账号(%user_id%)与缓存的token不符,请删除当前token.json或使用正确的账号! + do_unload: 插件将卸载,请在处理完成后手动重载插件! on_console: commands: 执行命令 on_server_stop: 服务器已关闭,停止消息同步。 on_server_crash: 服务器崩溃或者非正常退出,已停止消息同步,可能出现未知报错。 on_unload: 正在卸载插件,等待消息同步进程退出…… + unload_tips: + on_clean: 执行清理进程 + start_clean: 正在准备清理... run_tips: - failed: 登录失败! + failed: 登录失败 first_time_login: 首次登录,将使用密码继续…… login_success: 登录成功,正在缓存Token以供后续使用。 get_token: Token缓存完成! @@ -28,6 +34,8 @@ matrix_sync: server_started: "[√] 服务器启动完成!" server_crashed: "[×] 服务器崩溃或非正常退出!" reporter_status: "[!] 消息互通已在游戏服务器上初始化完成" + msync_running: 消息互通正在运行 + msync_stopped: 消息互通未在运行 start_report: 机器人登录成功,已发送测试消息。 test: 检测到玩家消息,正在尝试发送到Matrix群组…… tr: @@ -35,7 +43,11 @@ matrix_sync: ac: 账户 cs: 控制台 help_tips: - title: "!!msync 指令帮助" - start_command: "!!msync start - 开始消息同步(服务器启动完成时会自动开始)" - stop_command: "!!msync stop - 关闭消息同步(服务端停止运行后会自动关闭)" - closetip_command: "!!msync closetip - 关闭消息同步开始后出现的大量提示,建议认真阅读理解后再关闭" + message: "查看指令 §7!!msync §r的帮助" + title: "----- MatrixSync 指令帮助 -----" + root_command: "§7!!msync §r显示此帮助页面" + start_command: "§7!!msync start §r开始消息同步(服务器启动完成时会自动开始)" + stop_command: "§7!!msync stop §r关闭消息同步(服务端停止运行后会自动关闭)" + send_command: "§7!!msync send §r向Matrix房间发送指定消息,若含有空格请使用\"\"括起来" + status_command: "§7!!msync status §r查看当前消息同步状态" + reload_command: "§7!!msync reload §r重载插件并刷新插件配置" \ No newline at end of file diff --git a/matrix_sync/client.py b/matrix_sync/client.py index bb0e00e..c0760b5 100644 --- a/matrix_sync/client.py +++ b/matrix_sync/client.py @@ -2,21 +2,23 @@ import json import os import sys -import matrix_sync.config -from matrix_sync.reporter import sendMsg -from mcdreforged.api.all import * + +from .utils import psi, plgSelf, tr +from .utils.token import getToken +from .reporter import sendMsg +from mcdreforged.api.decorator import new_thread from nio import AsyncClient, LoginResponse -psi = ServerInterface.psi() clientStatus = False # Cache Token. def cache_token(resp: LoginResponse): - TOKEN_FILE = matrix_sync.config.TOKEN_FILE + from .config import TOKEN_FILE, user_id with open(TOKEN_FILE, "w") as f: json.dump( { + "user_id": user_id, "token": resp.access_token }, f, @@ -31,35 +33,36 @@ async def init_task(): await init_client() async def init_client() -> None: - TOKEN_FILE = matrix_sync.config.TOKEN_FILE - homeserver = matrix_sync.config.homeserver - user_id = matrix_sync.config.user_id - password = matrix_sync.config.password - device_id = matrix_sync.config.device_id - psi.logger.info(user_id) + from .config import TOKEN_FILE, homeserver, user_id, password, device_id if not os.path.exists(TOKEN_FILE): - psi.logger.info(psi.rtr("matrix_sync.run_tips.first_time_login")) + psi.logger.info(tr("run_tips.first_time_login")) client = AsyncClient(homeserver, user_id) resp = await client.login(password, device_name=f"{device_id}") if isinstance(resp, LoginResponse): - psi.logger.info(psi.rtr("matrix_sync.run_tips.login_success")) + psi.logger.info(tr("run_tips.login_success")) cache_token(resp) - psi.logger.info(psi.rtr("matrix_sync.run_tips.get_token")) + psi.logger.info(tr("run_tips.get_token")) await test_client() else: - failed_tip = psi.rtr("matrix_sync.run_tips.failed") - homeserver_tr = psi.rtr("matrix_sync.tr.hs") - account_tr = psi.rtr("matrix_sync.tr.ac") + failed_tip = tr("run_tips.failed") + homeserver_tr = tr("tr.hs") + account_tr = tr("tr.ac") psi.logger.info(f"{failed_tip}: {resp}") psi.logger.info(f'{homeserver_tr}: "{homeserver}", {account_tr}: "{user_id}"') - psi.logger.info(psi.rtr("matrix_sync.run_tips.error")) + psi.logger.info(tr("run_tips.error")) sys.exit(1) else: - await test_client() + user, token = await getToken() + if user != user_id: + psi.logger.error(tr("init_tips.user_mismatch")) + psi.logger.info(tr("init_tips.do_unload")) + psi.unload_plugin(plgSelf.id) + else: + await test_client() # Send test messages. async def test_client(): global clientStatus - message = psi.rtr("matrix_sync.sync_tips.reporter_status") + message = tr("sync_tips.reporter_status") await sendMsg(message) clientStatus = True diff --git a/matrix_sync/config.py b/matrix_sync/config.py index 514b646..7ea9920 100644 --- a/matrix_sync/config.py +++ b/matrix_sync/config.py @@ -1,6 +1,5 @@ -from mcdreforged.api.all import * +from .utils import psi -psi = ServerInterface.psi() lock_is_None = True # Default config. @@ -17,7 +16,11 @@ bot_config = { "plugin_enabled": False, "allow_all_rooms_msg": False, - "sync_old_msg": False + "sync_old_msg": False, + "room_msg_format": { + "single_room": "[MSync] %sender%: %message%", + "multi_room": "[MSync|%room_display_name%] %sender%: %message%" + } } def load_config(): diff --git a/matrix_sync/entry.py b/matrix_sync/entry.py index 7932481..bb90d40 100644 --- a/matrix_sync/entry.py +++ b/matrix_sync/entry.py @@ -1,90 +1,74 @@ -import asyncio -import matrix_sync.config -import matrix_sync.client -import matrix_sync.receiver -import matrix_sync.reporter +import time -from matrix_sync.utils.globals import * -from matrix_sync.client import init -from matrix_sync.config import load_config, check_config -from matrix_sync.utils.commands import * -from matrix_sync.reporter import send_matrix +from typing import Optional +from .utils import tr +from .client import init +from .config import load_config, check_config +from .utils import psi, globals +from .utils.commands import * +from .reporter import send_matrix from mcdreforged.api.all import * -# Framwork ver: 2.4.0-3 -def on_load(server: PluginServerInterface, old): + +# Framwork ver: 2.4.1 +def on_load(server: PluginServerInterface, prev_module): load_config() - server.logger.info(matrix_sync.config.load_tip) + from .config import load_tip + server.logger.info(load_tip) check_config() - do_unload = matrix_sync.config.do_unload + from .config import do_unload if do_unload: - server.unload_plugin("matrix_sync") + server.unload_plugin(plgSelf.id) else: init() plugin_command(server) - server.logger.info(psi.rtr("matrix_sync.init_tips.hotload_tip")) - -# Restart room message receiver, not recommend. -# def restartSync(src): -# stopSync(src) -# manualSync() + if server.is_server_startup(): + start_sync() # Automatically run sync processes. -def on_server_startup(server: PluginServerInterface): - clientStatus = matrix_sync.client.clientStatus - if not tLock.locked(): - if clientStatus: - message = psi.rtr("matrix_sync.sync_tips.server_started") +def start_sync(on_reload: Optional[bool] = True): + if not globals.tLock.locked(): + start_room_msg() + if not on_reload: + time.sleep(1) + message = tr("sync_tips.server_started") send_matrix(message) - start_room_msg() else: - server.logger.info(server.rtr("matrix_sync.manual_sync.start_error")) + psi.logger.info(tr("manual_sync.start_error")) + +def on_server_startup(server: PluginServerInterface): + start_sync(False) # Game message reporter def on_user_info(server: PluginServerInterface, info: Info): - # formater(server, info) if info.player is not None and not info.content.startswith("!!"): playerMsg = f"<{info.player}> {info.content}" - clientStatus = matrix_sync.client.clientStatus - if clientStatus: - send_matrix(playerMsg) + send_matrix(playerMsg) # Exit sync process when server stop. def on_server_stop(server: PluginServerInterface, server_return_code: int): - global cleaned, sync_task if server_return_code == 0: - server.logger.info(server.rtr("matrix_sync.on_server_stop")) - clientStatus = matrix_sync.client.clientStatus - stopTip = server.rtr("matrix_sync.sync_tips.server_stopped") - if clientStatus: - send_matrix(stopTip) + server.logger.info(tr("on_server_stop")) + exit_message = tr("sync_tips.server_stopped") else: - server.logger.info(server.rtr("matrix_sync.on_server_crash")) - crashTip = server.rtr("matrix_sync.sync_tips.server_crashed") - clientStatus = matrix_sync.client.clientStatus - if clientStatus: - send_matrix(crashTip) - - if sync_task is not None: - sync_task.cancel() - try: - pass - except asyncio.TimeoutError: - server.logger.warning("Timed out waiting for sync_task to finish.") + server.logger.info(tr("on_server_crash")) + exit_message = tr("sync_tips.server_crashed") + + # 鉴于有用户反馈关服时消息发送不到Matrix,这里卡一个协程用于发送 + # 为了防止卡住MCDR主线程出现无响应提示影响用户体验,一般都在子线程中发送消息,但是直接用协程正常情况下也没啥问题 + # 有bug的话应该会有人在issues提出,暂时先这么解决 + from .reporter import sendMsg + asyncio.run(sendMsg(exit_message)) - cleaned = True + globals.cleaned = True def on_unload(server: PluginServerInterface): - global sync_task, cleaned - if cleaned: - server.logger.info(server.rtr("matrix_sync.on_unload")) + server.logger.info(tr("unload_tips.on_clean")) + if globals.cleaned: + server.logger.info(tr("on_unload")) else: - if sync_task is not None: - sync_task.cancel() - try: - pass - except asyncio.TimeoutError: - server.logger.warning("Timed out waiting for sync_task to finish.") - sync_task = None + psi.logger.info(tr("unload_tips.start_clean")) + psi.logger.info(exit_sync()) + from .config import lock_is_None if not lock_is_None: - server.logger.info(server.rtr("matrix_sync.on_unload")) + server.logger.info(tr("on_unload")) \ No newline at end of file diff --git a/matrix_sync/receiver.py b/matrix_sync/receiver.py index 59b198f..092c644 100644 --- a/matrix_sync/receiver.py +++ b/matrix_sync/receiver.py @@ -2,14 +2,14 @@ import asyncio import matrix_sync.config -from matrix_sync.utils.token import getToken -from matrix_sync.utils.globals import psi -from mcdreforged.api.all import * +from .utils.token import getToken +from .utils import psi, plgSelf, tr +from mcdreforged.api.event import PluginEvent from nio import AsyncClient, MatrixRoom, RoomMessageText, SyncError from typing import Optional + homeserver_online = True -msg_callback = False class RoomMessageEvent(PluginEvent): def __init__(self, message: str, sender: str, room: Optional[str] = None): @@ -19,24 +19,23 @@ def __init__(self, message: str, sender: str, room: Optional[str] = None): self.room = room async def message_callback(room: MatrixRoom, event: RoomMessageText) -> None: - global msg_callback transfer = False - user_id = matrix_sync.config.user_id - room_name = matrix_sync.config.room_name - roomMsg = f"[MSync|{room.display_name}] {room.user_name(event.sender)}: {event.body}" - if msg_callback: - # Avoid echo messages. - if not event.sender == user_id: - # Apply settings config - if not matrix_sync.config.settings["allow_all_rooms_msg"]: - roomMsg = f"[MSync] {room.user_name(event.sender)}: {event.body}" - if room.display_name == room_name: - transfer = True - psi.dispatch_event(RoomMessageEvent(event.body, room.user_name(event.sender)), (event.body, room.user_name(event.sender))) - else: - psi.dispatch_event(RoomMessageEvent(event.body, room.user_name(event.sender), room.display_name), (event.body, room.user_name(event.sender), room.display_name)) - if transfer: - psi.broadcast(f"{roomMsg}") + from .config import user_id, room_name, settings + msg_format = settings["room_msg_format"]["multi_room"] + roomMsg = msg_format.replace('%room_display_name%', room.display_name).replace('%sender%', room.user_name(event.sender)).replace('%message%', event.body) + # Avoid echo messages. + if not event.sender == user_id: + # Apply settings config + if not matrix_sync.config.settings["allow_all_rooms_msg"]: + msg_format = matrix_sync.config.settings["room_msg_format"]["single_room"] + roomMsg = msg_format.replace('%sender%', room.user_name(event.sender)).replace('%message%', event.body) + if room.display_name == room_name: + transfer = True + psi.dispatch_event(RoomMessageEvent(event.body, room.user_name(event.sender)), (event.body, room.user_name(event.sender))) + else: + psi.dispatch_event(RoomMessageEvent(event.body, room.user_name(event.sender), room.display_name), (event.body, room.user_name(event.sender), room.display_name)) + if transfer: + psi.broadcast(f"{roomMsg}") def on_sync_error(response: SyncError): global homeserver_online @@ -46,30 +45,33 @@ def on_sync_error(response: SyncError): async def getMsg() -> None: global next_batch, msg_callback - homeserver = matrix_sync.config.homeserver - device_id = matrix_sync.config.device_id - user_id = matrix_sync.config.user_id - sync_old_msg = matrix_sync.config.sync_old_msg + from .config import homeserver, device_id, user_id, sync_old_msg client = AsyncClient(f"{homeserver}") - client.access_token = await getToken() - client.user_id = user_id - client.device_id = device_id + user, token = await getToken() + client.access_token = token + if user != user_id: + if user is not None: + tip = tr("init_tips.user_mismatch") + psi.logger.error(tip.replace("%user_id%", user_id)) + psi.logger.info(tr("init_tips.do_unload")) + psi.unload_plugin(plgSelf.id) + else: + client.user_id = user_id + client.device_id = device_id client.add_response_callback(on_sync_error, SyncError) - client.add_event_callback(message_callback, RoomMessageText) try: if homeserver_online: if sync_old_msg is True: await client.sync_forever(timeout=5) else: - msg_callback = False await client.sync(timeout=5) - msg_callback = True + client.add_event_callback(message_callback, RoomMessageText) await client.sync_forever(timeout=5) else: psi.logger.error("Sync failed: homeserver is down or your network disconnected with it.") - psi.logger.info("Use !!msync start after homeserver is running or your network restored.") + psi.logger.info("Use §7!!msync start §rafter homeserver is running or your network restored.") except Exception as e: psi.logger.error(f"Sync error: {e}") except asyncio.CancelledError: diff --git a/matrix_sync/reporter.py b/matrix_sync/reporter.py index ff543ec..3c35bb2 100644 --- a/matrix_sync/reporter.py +++ b/matrix_sync/reporter.py @@ -1,10 +1,11 @@ import asyncio -import matrix_sync.config +import re -from mcdreforged.api.all import * +from mcdreforged.api.decorator import new_thread from nio import AsyncClient -from matrix_sync.utils.token import getToken -from matrix_sync.utils.globals import psi +from .utils import psi, plgSelf, tr, globals +from .utils.token import getToken + # Game Message reporter. @new_thread('MatrixReporter') @@ -12,25 +13,38 @@ def send_matrix(message): asyncio.run(send(message)) async def send(message): - await sendMsg(message) + from .client import clientStatus + if clientStatus: + if globals.report_matrix: + await sendMsg(message) + psi.logger.debug("消息已发送!") + else: + psi.logger.debug("消息未发送:同步未启动") + else: + psi.logger.debug("消息未发送:bot未初始化成功") async def sendMsg(message) -> None: - homeserver = matrix_sync.config.homeserver - user_id = matrix_sync.config.user_id - room_id = matrix_sync.config.room_id - device_id = matrix_sync.config.device_id + from .config import homeserver, user_id, room_id, device_id client = AsyncClient(f"{homeserver}") - client.access_token = await getToken() - client.user_id = user_id - client.device_id = device_id - - try: - await client.room_send( - room_id, - message_type="m.room.message", - content={"msgtype": "m.text", "body": f"{message}"}, - ) - - await client.close() - except Exception as e: - psi.logger.error(f"Send to matrix error: {e}") + user, token = await getToken() + client.access_token = token + if user != user_id: + tip = tr("init_tips.user_mismatch") + psi.logger.error(tip.replace("%user_id%", user_id)) + psi.logger.info(tr("init_tips.do_unload")) + psi.unload_plugin(plgSelf.id) + else: + client.user_id = user_id + client.device_id = device_id + + pattern = re.compile(r'§[0-9a-v]') + + message_to_send = re.sub(pattern, '', message) + + await client.room_send( + room_id, + message_type="m.room.message", + content={"msgtype": "m.text", "body": message_to_send}, + ) + + await client.close() diff --git a/matrix_sync/utils/__init__.py b/matrix_sync/utils/__init__.py index b974282..c09a8b7 100644 --- a/matrix_sync/utils/__init__.py +++ b/matrix_sync/utils/__init__.py @@ -1 +1,35 @@ -from . import * \ No newline at end of file +from typing import Optional +from mcdreforged.api.all import * + +psi = ServerInterface.psi() +MCDRConfig = psi.get_mcdr_config() +plgSelf = psi.get_self_metadata() +serverDir = MCDRConfig["working_directory"] +configDir = psi.get_data_folder() +builder = SimpleCommandBuilder() + +def tr(tr_key: str, return_str: Optional[bool] = True): + ''' + 对`ServerInterface.rtr()`进行优化,提高翻译效率。 + + 参数: + tr_key (str): 原始或简化后的翻译键名称 + return_str (可选[bool]): 是否尝试转换成字符串减少出错 + + 返回: + translation: RTextMCDRTranslation组件 + 或tr_to_str: 字符串 + ''' + if tr_key.startswith(f"{plgSelf.id}"): + translation = psi.rtr(f"{tr_key}") + else: + # 使用此前缀代表非本插件的翻译键,则翻译时不会附加本插件的ID,避免错误。 + if tr_key.startswith("#"): + translation = psi.rtr(tr_key.replace("#", "")) + else: + translation = psi.rtr(f"{plgSelf.id}.{tr_key}") + if return_str: + tr_to_str: str = str(translation) + return tr_to_str + else: + return translation \ No newline at end of file diff --git a/matrix_sync/utils/commands.py b/matrix_sync/utils/commands.py index 5e577a9..86efe87 100644 --- a/matrix_sync/utils/commands.py +++ b/matrix_sync/utils/commands.py @@ -1,77 +1,91 @@ import asyncio +from . import builder, tr, globals from mcdreforged.api.all import * -from matrix_sync.utils.globals import * -from matrix_sync.receiver import getMsg +from . import psi, plgSelf +from ..reporter import send_matrix +from ..receiver import getMsg -psi = ServerInterface.psi() def plugin_command(server: PluginServerInterface): - server.register_help_message("!!msync", help()) - server.register_command( - Literal('!!msync') - .then( - Literal('start') - .runs( - lambda src: src.reply(manualSync()) - ) - ) - # .then( - # Literal('restart') - # .runs( - # lambda src: src.reply(restartSync()) - # ) - # ) - .then( - Literal('stop') - .runs( - lambda src: src.reply(stopSync(src)) - ) - ) - ) + help_message = tr("help_tips.message", False) + server.register_help_message("!!msync", help_message) + builder.arg("message", QuotableText) + builder.register(server) + +@builder.command("!!msync send ") +def send_command(src: CommandSource, ctx: CommandContext): + send_matrix(ctx["message"]) + src.reply(tr("debug.send_command")) # Help tips. -def help() -> RTextList: - return RTextList( - psi.rtr("matrix_sync.help_tips.title") + "\n", - psi.rtr("matrix_sync.help_tips.start_command") + "\n", - psi.rtr("matrix_sync.help_tips.stop_command") + "\n", - psi.rtr("matrix_sync.help_tips.closetip_command") + "\n" - ) +@builder.command("!!msync") +@builder.command("!!msync help") +def show_help(src: CommandSource): + pfx = f"{plgSelf.id}.help_tips" + src.reply(RTextList( + tr(f"{pfx}.title", False) + "\n", + tr(f"{pfx}.root_command", False) + "\n", + tr(f"{pfx}.start_command", False) + "\n", + tr(f"{pfx}.stop_command", False) + "\n", + tr(f"{pfx}.send_command", False) + "\n", + tr(f"{pfx}.status_command", False) + "\n", + tr(f"{pfx}.reload_command", False) + "\n" + )) # Manually run sync processes. -def manualSync(): - if not tLock.locked(): +@builder.command("!!msync start") +def manualSync(src: CommandSource): + if not globals.tLock.locked(): + globals.report_matrix = True start_room_msg() - return psi.rtr("matrix_sync.manual_sync.start_sync") + src.reply(tr("manual_sync.start_sync")) + else: + src.reply(tr("manual_sync.start_error")) + +@builder.command("!!msync status") +def syncStatus(src: CommandSource): + if globals.report_matrix is True: + src.reply(tr("sync_tips.msync_running")) else: - return psi.rtr("matrix_sync.manual_sync.start_error") + src.reply(tr("sync_tips.msync_stopped")) + +def exit_sync(): + try: + if globals.sync_task is not None: + globals.sync_task.cancel() + globals.report_matrix = False + globals.sync_task = None + return tr("manual_sync.stop_sync") + else: + return tr("manual_sync.not_running") + except Exception as e: + psi.logger.error(f"Error exit {plgSelf.id}: {e}") + return tr("manual_sync.stop_error") # Manually stop sync processes. +@builder.command("!!msync stop") def stopSync(src): - global sync_task if src.is_console: - try: - if sync_task is not None: - sync_task.cancel() - return psi.rtr("matrix_sync.manual_sync.stop_sync") - else: - return psi.rtr("matrix_sync.manual_sync.not_running") - except Exception: - return psi.rtr("matrix_sync.manual_sync.stop_error") + response = exit_sync() + src.reply(response) else: - return psi.rtr("matrix_sync.manual_sync.stop_denied") + src.reply(tr("manual_sync.stop_denied")) + +@builder.command("!!msync reload") +def reload_plugin(): + psi.reload_plugin(plgSelf.id) # Sub thread to receive room messages from matrix without block main MCDR thread. @new_thread('MatrixReceiver') def start_room_msg(): - with tLock: + with globals.tLock: + globals.report_matrix = True asyncio.run(on_room_msg()) async def on_room_msg(): - global sync_task - if sync_task is not None and not sync_task.done(): - sync_task.cancel() - await sync_task - sync_task = asyncio.create_task(getMsg()) - await sync_task \ No newline at end of file + if globals.sync_task is not None and not globals.sync_task.done(): + globals.sync_task.cancel() + await globals.sync_task + globals.sync_task = asyncio.create_task(getMsg()) + await globals.sync_task \ No newline at end of file diff --git a/matrix_sync/utils/globals.py b/matrix_sync/utils/globals.py index 22c1316..ac2fbc6 100644 --- a/matrix_sync/utils/globals.py +++ b/matrix_sync/utils/globals.py @@ -1,10 +1,6 @@ import threading -from .. import config -from mcdreforged.api.all import * - -psi = ServerInterface.psi() tLock = threading.Lock() -lock_is_None = config.lock_is_None +report_matrix = False cleaned = False sync_task = None \ No newline at end of file diff --git a/matrix_sync/utils/token.py b/matrix_sync/utils/token.py index 2a48427..b69a7b1 100644 --- a/matrix_sync/utils/token.py +++ b/matrix_sync/utils/token.py @@ -8,4 +8,6 @@ async def getToken(): async with aiofiles.open(TOKEN_FILE, "r") as f: contents = await f.read() cache = json.loads(contents) - return cache["token"] \ No newline at end of file + user_id = cache.get("user_id", None) + token = cache.get("token", None) + return user_id, token \ No newline at end of file diff --git a/mcdreforged.plugin.json b/mcdreforged.plugin.json index f524b47..e456fa0 100644 --- a/mcdreforged.plugin.json +++ b/mcdreforged.plugin.json @@ -1,6 +1,6 @@ { "id": "matrix_sync", - "version": "2.4.0", + "version": "2.4.1", "name": "MatrixSync", "description": { "en_us": "Sync messages between online game and Matrix groups.", diff --git a/pack_plugin.sh b/pack_plugin.sh index cc76b31..20d036b 100644 --- a/pack_plugin.sh +++ b/pack_plugin.sh @@ -26,15 +26,4 @@ if [ "$build_plg" -eq 1 ]; then else zip -r "MatrixSync-v${main_ver}.mcdr" README.md README_en_us.md mcdreforged.plugin.json requirements.txt LICENSE lang matrix_sync fi -fi -if [ "$build_subpack" -eq 1 ]; then - pushd "subpacks(rolling)/[MSync]AutoReply" >> /dev/null - zip -r "MSync.AutoReply.mcdr" msync_auto_reply mcdreforged.plugin.json requirements.txt - popd >> /dev/null - pushd "subpacks(rolling)/[MSync]MoreMessages" >> /dev/null - zip -r "MSync.MoreMessages.mcdr" msync_more_msg mcdreforged.plugin.json - popd >> /dev/null - pushd "subpacks(rolling)/[MSync]PlayingTips" >> /dev/null - zip -r "MSync.PlayingTips.mcdr" msync_playing_tips mcdreforged.plugin.json - popd >> /dev/null fi \ No newline at end of file diff --git a/subpacks(rolling)/AdvancementTips/advancement_tips/__init__.py b/subpacks(rolling)/AdvancementTips/advancement_tips/__init__.py deleted file mode 100644 index 5f0fb89..0000000 --- a/subpacks(rolling)/AdvancementTips/advancement_tips/__init__.py +++ /dev/null @@ -1,56 +0,0 @@ -import asyncio -import re -import matrix_sync.client - -from mcdreforged.api.all import * -from matrix_sync.reporter import sendMsg -from gtl_api import parseKey, parseValue, parseContent - -psi = ServerInterface.psi() - -lang_files = { - "raw_lang": "server/plugins/Geyser-Spigot/locales/en_us.json", - "translated_lang": "server/plugins/Geyser-Spigot/locales/zh_cn.json" -} - -config = psi.load_config_simple("config.json", lang_files) - -raw_lang = config["raw_lang"] -translated_lang = config["translated_lang"] - -def on_load(server: PluginServerInterface, old): - server.logger.info("MatrixSync 子包: AdvancementsTips 已加载") - server.logger.info("本插件仅供简体中文用户使用") - server.logger.info("语言文件默认使用Geyser配置,若未使用Geyser请自行获取语言文件并配置其路径") - -def on_info(server: PluginServerInterface, info: Info): - if info.is_from_server and re.fullmatch(r'(.+) has completed the challenge (.+)', info.content): - match = re.fullmatch(r'(.+) has completed the challenge (.+)', info.content) - if match: - player = match.group(1) - raw_content = match.group(2) - content = parseContent(raw_content) - key = parseKey(raw_lang, content) - tr_content = parseValue(translated_lang, key) - if matrix_sync.client.clientStatus: - asyncio.run(sendMsg(f"[!]玩家 {player} 完成了挑战 [{tr_content}]")) - if info.is_from_server and re.fullmatch(r'(.+) has reached the goal (.+)', info.content): - match = re.fullmatch(r'(.+) has reached the goal (.+)', info.content) - if match: - player = match.group(1) - raw_content = match.group(2) - content = parseContent(raw_content) - key = parseKey(raw_lang, content) - tr_content = parseValue(translated_lang, key) - if matrix_sync.client.clientStatus: - asyncio.run(sendMsg(f"[!]玩家 {player} 达成了目标 [{tr_content}]")) - if info.is_from_server and re.fullmatch(r'(.+) has made the advancement (.+)', info.content): - match = re.fullmatch(r'(.+) has made the advancement (.+)', info.content) - if match: - player = match.group(1) - raw_content = match.group(2) - content = parseContent(raw_content) - key = parseKey(raw_lang, content) - tr_content = parseValue(translated_lang, key) - if matrix_sync.client.clientStatus: - asyncio.run(sendMsg(f"[!]玩家 {player} 取得了进度 [{tr_content}]")) \ No newline at end of file diff --git a/subpacks(rolling)/AdvancementTips/mcdreforged.plugin.json b/subpacks(rolling)/AdvancementTips/mcdreforged.plugin.json deleted file mode 100644 index 9b07588..0000000 --- a/subpacks(rolling)/AdvancementTips/mcdreforged.plugin.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "id": "advancements_tips", - "version": "0.0.1", - "name": "AdvancementTips", - "description": { - "en_us": "A subpack of MatrixSync, send tips to the group when player finished advancements.", - "zh_cn": "MatrixSync的子包,在玩家完成成就时在群内进行提示。" - }, - "dependencies": { - "mcdreforged": ">=2.1.0", - "matrix_sync": ">=2.0.2" - }, - "author": "Mooling0602", - "link": "https://github.com/Mooling0602/MatrixSync-MCDR" -} \ No newline at end of file diff --git a/subpacks(rolling)/DeathTips/death_tips/__init__.py b/subpacks(rolling)/DeathTips/death_tips/__init__.py deleted file mode 100644 index 9ce45f7..0000000 --- a/subpacks(rolling)/DeathTips/death_tips/__init__.py +++ /dev/null @@ -1,83 +0,0 @@ -import asyncio -import re -import json -import matrix_sync.client - -from mcdreforged.api.all import * -from gtl_api import parseKey, parseValue -from matrix_sync.reporter import sendMsg - -psi = ServerInterface.psi() - -lang_files = { - "raw_lang": "server/plugins/Geyser-Spigot/locales/en_us.json", - "translated_lang": "server/plugins/Geyser-Spigot/locales/zh_cn.json" -} - -config = psi.load_config_simple("config.json", lang_files) - -raw_lang = config["raw_lang"] -translated_lang = config["translated_lang"] - -death_messages = {} - -def on_load(server: PluginServerInterface, old): - server.logger.info("MatrixSync子包: DeathTips 已加载") - server.logger.info("本插件仅供简体中文用户使用") - server.logger.info("语言文件默认使用Geyser配置,若未使用Geyser请自行获取语言文件并配置其路径") - -def on_info(server: PluginServerInterface, info: Info): - global death_messages - if info.is_from_server: - key, groups = match_death_msg(raw_lang, info.content) - if key: - deathRawFormat = parseValue(raw_lang, key) - deathMsg = parseValue(translated_lang, key) - partten_deathRawFormat = re.compile(r"%(\d+)\$s") - matches_deathRawFormat = partten_deathRawFormat.findall(deathRawFormat) - regex_template = re.escape(deathRawFormat) - regex_template = regex_template.replace(r"%1\$s", r"(.+)").replace(r"%2\$s", r"(.+)").replace(r"%3\$s", r"\[(.+)\]|(.+)") - content_matches = re.match(regex_template, info.content) - if content_matches: - placeholder_to_content = {int(matches_deathRawFormat[i]): content_matches.group(i + 1) for i in range(len(matches_deathRawFormat))} - deathTip = deathMsg - for placeholder, content in placeholder_to_content.items(): - placeholder_str = f"%{placeholder}$s" - if placeholder_str == "%2$s": - contentKey = parseKey(raw_lang, content) - tr_content = parseValue(translated_lang, contentKey) - if tr_content is not None: - content = tr_content - else: - content = content - # if placeholder_str == "%3$s": - # content = re.escape(content) - deathTip = deathTip.replace(placeholder_str, content) - # 修正部分 - if re.fullmatch(r'(.+)被(.+) using \[(.+)\]|(.+)杀死了', deathTip): - match = re.fullmatch(r'(.+)被(.+) using (.+)杀死了', deathTip) - if match: - player = match.group(1) - killer = match.group(2) - weapon = match.group(3) - deathTip = f"{player}被{killer}用{weapon}杀死了" - clientStatus = matrix_sync.client.clientStatus - if clientStatus: - asyncio.run(sendMsg(deathTip)) - -def match_death_msg(lang, content): - global death_messages - with open(lang, 'r') as file: - lang = file.read() - lang = json.loads(lang) - for key in lang.keys(): - if key.startswith("death."): - value = lang.get(key, None) - if value: - value = re.sub(r'%(\d+)\$s', r'(?P.+)', value) - death_messages[key] = value - for key, value in death_messages.items(): - match = re.fullmatch(value, content) - if match: - return key, match.groupdict() - return None, None diff --git a/subpacks(rolling)/DeathTips/mcdreforged.plugin.json b/subpacks(rolling)/DeathTips/mcdreforged.plugin.json deleted file mode 100644 index 458e234..0000000 --- a/subpacks(rolling)/DeathTips/mcdreforged.plugin.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "id": "death_tips", - "version": "0.0.1", - "name": "DeathTips", - "description": { - "en_us": "A subpack of MatrixSync, send tips to the group when player finished advancements.", - "zh_cn": "MatrixSync的子包,在玩家死亡时在群内进行提示。" - }, - "dependencies": { - "mcdreforged": ">=2.1.0", - "matrix_sync": ">=2.0.2", - "atl_api": ">=0.0.1" - }, - "author": "Mooling0602", - "link": "https://github.com/Mooling0602/MatrixSync-MCDR" -} diff --git a/subpacks(rolling)/README.md b/subpacks(rolling)/README.md deleted file mode 100644 index 213d158..0000000 --- a/subpacks(rolling)/README.md +++ /dev/null @@ -1,3 +0,0 @@ -Subpacks for MatrixSync, rolling update - -MatrixSync的子包,滚动更新 diff --git a/subpacks(rolling)/[MSync]AutoReply/mcdreforged.plugin.json b/subpacks(rolling)/[MSync]AutoReply/mcdreforged.plugin.json deleted file mode 100644 index a16af6b..0000000 --- a/subpacks(rolling)/[MSync]AutoReply/mcdreforged.plugin.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "id": "msync_auto_reply", - "version": "0.0.2", - "name": "[MSync]AutoReply", - "description": { - "en_us": "A subpack of MatrixSync, automatically reply messages from room.", - "zh_cn": "MatrixSync的子包,自动回复房间内消息" - }, - "dependencies": { - "mcdreforged": ">=2.1.0", - "matrix_sync": ">=2.3.1" - }, - "author": "Mooling0602", - "link": "https://github.com/Mooling0602/MatrixSync-MCDR" -} \ No newline at end of file diff --git a/subpacks(rolling)/[MSync]AutoReply/msync_auto_reply/__init__.py b/subpacks(rolling)/[MSync]AutoReply/msync_auto_reply/__init__.py deleted file mode 100644 index 4b5e812..0000000 --- a/subpacks(rolling)/[MSync]AutoReply/msync_auto_reply/__init__.py +++ /dev/null @@ -1,44 +0,0 @@ -import os -import matrix_sync.config -import matrix_sync.client -import yaml -from mcdreforged.api.all import * -from matrix_sync.reporter import send_matrix - -CONFIG_PATH = 'config/matrix_sync/auto_reply/config.yml' - -DEFAULT_CONFIG = { - "triggers": { - "触发词1": "回复内容1", - "触发词2": "回复内容2", - "触发词3": "回复内容3" - } -} - -def load_config(): - if not os.path.exists(CONFIG_PATH): - os.makedirs(os.path.dirname(CONFIG_PATH), exist_ok=True) - with open(CONFIG_PATH, 'w', encoding='utf-8') as config_file: - yaml.dump(DEFAULT_CONFIG, config_file, allow_unicode=True) - with open(CONFIG_PATH, 'r', encoding='utf-8') as config_file: - return yaml.safe_load(config_file) - -def on_load(server: PluginServerInterface, old): - global plugin_config - plugin_config = load_config() - - server.logger.info("[MSync]AutoReply loaded.") - server.register_event_listener('MatrixRoomMessage', main) - -def main(server: PluginServerInterface, message: str, sender: str): - user_id = matrix_sync.config.user_id - triggers = plugin_config.get("triggers", {}) - - if sender != user_id: - for trigger_word, reply_content in triggers.items(): - if message == trigger_word: - clientStatus = matrix_sync.client.clientStatus - if clientStatus: - send_matrix(reply_content) - server.logger.info("解析到指定内容,已自动发送回复") - break \ No newline at end of file diff --git a/subpacks(rolling)/[MSync]AutoReply/requirements.txt b/subpacks(rolling)/[MSync]AutoReply/requirements.txt deleted file mode 100644 index 4818cc5..0000000 --- a/subpacks(rolling)/[MSync]AutoReply/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -pyyaml \ No newline at end of file diff --git a/subpacks(rolling)/[MSync]MoreMessages/mcdreforged.plugin.json b/subpacks(rolling)/[MSync]MoreMessages/mcdreforged.plugin.json deleted file mode 100644 index 7afdd42..0000000 --- a/subpacks(rolling)/[MSync]MoreMessages/mcdreforged.plugin.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "id": "msync_more_msg", - "version": "0.0.2", - "name": "[MSync]MoreMessages", - "description": { - "en_us": "A subpack of MatrixSync, transfer more kinds of messages from the game.", - "zh_cn": "MatrixSync的子包,转发更多类型的游戏消息。" - }, - "dependencies": { - "mcdreforged": ">=2.1.0", - "matrix_sync": ">=2.3.1" - }, - "author": "Mooling0602", - "link": "https://github.com/Mooling0602/MatrixSync-MCDR" -} \ No newline at end of file diff --git a/subpacks(rolling)/[MSync]MoreMessages/msync_more_msg/__init__.py b/subpacks(rolling)/[MSync]MoreMessages/msync_more_msg/__init__.py deleted file mode 100644 index b9838e9..0000000 --- a/subpacks(rolling)/[MSync]MoreMessages/msync_more_msg/__init__.py +++ /dev/null @@ -1,34 +0,0 @@ -import re - -from matrix_sync.reporter import send_matrix -from mcdreforged.api.all import * - -psi = ServerInterface.psi() - -def on_load(server: PluginServerInterface, old): - server.logger.info("Subpack of MatrixSync: [Msync]MoreMessages loaded.") - -def on_user_info(server: PluginServerInterface, info: Info): - formatter(info) - if gameMsg is not None: - send_matrix(gameMsg) - - -def formatter(info: Info): - global gameMsg - console_tr = psi.rtr("matrix_sync.tr.cs") - if info.player is None: - if re.fullmatch(r'say \S*', info.content): - msg_content = '{}'.format(info.content.rsplit(' ', 1)[1]) - gameMsg = f"<{console_tr}> {msg_content}" - else: - option = psi.rtr("matrix_sync.on_console.commands") - gameMsg = f"[!] {console_tr} {option} -> {info.content}" - if info.content == "stop": - gameMsg = psi.rtr("matrix_sync.sync_tips.server_stopping") - else: - if info.content.startswith("!!"): - option = psi.rtr("matrix_sync.on_console.commands") - gameMsg = f"[!] {info.player} {option} -> {info.content}" - else: - return None \ No newline at end of file diff --git a/subpacks(rolling)/[MSync]PlayerBind/.temp b/subpacks(rolling)/[MSync]PlayerBind/.temp deleted file mode 100644 index 8b13789..0000000 --- a/subpacks(rolling)/[MSync]PlayerBind/.temp +++ /dev/null @@ -1 +0,0 @@ - diff --git a/subpacks(rolling)/[MSync]PlayingTips/mcdreforged.plugin.json b/subpacks(rolling)/[MSync]PlayingTips/mcdreforged.plugin.json deleted file mode 100644 index 9c30315..0000000 --- a/subpacks(rolling)/[MSync]PlayingTips/mcdreforged.plugin.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "id": "msync_playing_tips", - "version": "0.0.1", - "name": "[MSync]PlayingTips", - "description": { - "en_us": "A subpack of MatrixSync, send tips to the group when player joined and left the game.", - "zh_cn": "MatrixSync的子包,在玩家上下线时在群内进行提示。" - }, - "dependencies": { - "mcdreforged": ">=2.1.0", - "matrix_sync": ">=2.3.1" - }, - "author": "Mooling0602", - "link": "https://github.com/Mooling0602/MatrixSync-MCDR" -} \ No newline at end of file diff --git a/subpacks(rolling)/[MSync]PlayingTips/msync_playing_tips/__init__.py b/subpacks(rolling)/[MSync]PlayingTips/msync_playing_tips/__init__.py deleted file mode 100644 index d89c084..0000000 --- a/subpacks(rolling)/[MSync]PlayingTips/msync_playing_tips/__init__.py +++ /dev/null @@ -1,28 +0,0 @@ -import matrix_sync.client -import re -from matrix_sync.reporter import send_matrix -from mcdreforged.api.all import * - -def on_load(server: PluginServerInterface, old): - server.logger.info("Subpack of MatrixSync: [MSync]PlayingTips loaded.") - -def on_player_joined(server: PluginServerInterface, player: str, info: Info): - tip = f"[+]{player}" - if matrix_sync.client.clientStatus: - send_matrix(tip) - -def on_player_left(server: PluginServerInterface, player: str): - tip = f"[-]{player}" - if matrix_sync.client.clientStatus: - send_matrix(tip) - -def on_info(server: PluginServerInterface, info: Info): - if info.is_from_server and re.fullmatch(r'(.+) issued server command: (.+)', info.content): - match = re.fullmatch(r'(.+) issued server command: (.+)', info.content) - if match: - player = match.group(1) - command = match.group(2) - server.say(f"* {player} 执行游戏指令 -> {command}") - clientStatus = matrix_sync.client.clientStatus - if clientStatus: - send_matrix(f"* {player} 执行游戏指令 -> {command}") diff --git a/subpacks(rolling)/[MSync]plgDebugger/mcdreforged.plugin.json b/subpacks(rolling)/[MSync]plgDebugger/mcdreforged.plugin.json deleted file mode 100644 index 76c68d9..0000000 --- a/subpacks(rolling)/[MSync]plgDebugger/mcdreforged.plugin.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "id": "msync_debugger", - "version": "0.0.1", - "name": "[MSync]plgDebugger", - "description": { - "en_us": "A subpack of MatrixSync, used to debug.", - "zh_cn": "MatrixSync的子包,用于调试。" - }, - "dependencies": { - "mcdreforged": ">=2.1.0", - "matrix_sync": ">=2.0.2" - }, - "author": "Mooling0602", - "link": "https://github.com/Mooling0602/MatrixSync-MCDR" -} \ No newline at end of file diff --git a/subpacks(rolling)/[MSync]plgDebugger/msync_debugger/__init__.py b/subpacks(rolling)/[MSync]plgDebugger/msync_debugger/__init__.py deleted file mode 100644 index 9b97f61..0000000 --- a/subpacks(rolling)/[MSync]plgDebugger/msync_debugger/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from mcdreforged.api.all import * -from typing import Optional - -def on_load(server: PluginServerInterface, old): - server.logger.info("Subpack of MatrixSync: [MSync]plgDebugger loaded.") - server.register_event_listener('MatrixRoomMessage', main) - -def main(server: PluginServerInterface, message: str, sender: str, room: Optional[str] = None): - server.logger.info(f"Content: {message}") - server.logger.info(f"Sender: {sender}") - if room is not None: - server.logger.info(f"Room Name: {room}") \ No newline at end of file From 7a3e930ffb0e99e7338bb4bd4a8d10d55318028e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=A8=E6=B3=A0?= Date: Sun, 15 Dec 2024 18:56:29 +0800 Subject: [PATCH 3/3] Fix first load error --- matrix_sync/entry.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/matrix_sync/entry.py b/matrix_sync/entry.py index bb90d40..d1f6a84 100644 --- a/matrix_sync/entry.py +++ b/matrix_sync/entry.py @@ -2,7 +2,7 @@ from typing import Optional from .utils import tr -from .client import init +from .client import init, clientStatus from .config import load_config, check_config from .utils import psi, globals from .utils.commands import * @@ -22,7 +22,7 @@ def on_load(server: PluginServerInterface, prev_module): else: init() plugin_command(server) - if server.is_server_startup(): + if server.is_server_startup() and clientStatus: start_sync() # Automatically run sync processes. @@ -71,4 +71,4 @@ def on_unload(server: PluginServerInterface): psi.logger.info(exit_sync()) from .config import lock_is_None if not lock_is_None: - server.logger.info(tr("on_unload")) \ No newline at end of file + server.logger.info(tr("on_unload"))