Implement op execution command

Add in-game online and offline broadcast
This commit is contained in:
2023-03-05 17:10:03 +08:00
parent b119bb0cb9
commit 2a696b4854
4 changed files with 163 additions and 33 deletions

View File

@ -41,6 +41,10 @@
- `/serverchat limit <次每分钟>` 设置发消息频率限制 - `/serverchat limit <次每分钟>` 设置发消息频率限制
- `/serverchat reload` 重载配置文件 - `/serverchat reload` 重载配置文件
- `/serverchat group <groupId>` 设置互联群号 - `/serverchat group <groupId>` 设置互联群号
- `/serverchat op|deop <userId(QQ)>` 设置或解除管理员
- 被设置为管理的账号可以在指定群内直接用管理前缀执行命令
- 命令前缀可在配置文件中设置 `adminPrefix` ,默认为 `/`,例 `/sc ban @10002`
- 目前在群内执行命令暂时没有回复因为控制台执行过程只会log到控制台不好捕获
`/serverchat` 可用别名 `/sc`,例如 `/sc ban @xxx` `/serverchat` 可用别名 `/sc`,例如 `/sc ban @xxx`
@ -57,6 +61,13 @@
建议使用 `Android Watch` 协议登录(在 `device.json``"protocol": 5` 修改为 `"protocol": 2` 建议使用 `Android Watch` 协议登录(在 `device.json``"protocol": 5` 修改为 `"protocol": 2`
### 群服互联参考流程
1. 装好插件启动后,记录下首次生成的 `Token`,或者自己填写一个 `Token`
2. 下载 [go-cqhttp](https://github.com/Mrs4s/go-cqhttp) 并初始化配置
3. 在 `access-token: ''` 填写前面所述的 `Token` 内容
4. 在 `ws-reverse` 选项下的 `universal` 填写GC的服务器地址加路径例如 `ws://127.0.0.1:443/openchat`
5. 配置你的Bot账号和登录协议建议使用 `Android Watch` 登录。具体参考文档 [配置](https://docs.go-cqhttp.org/guide/config.html)。
--- ---
## 插件配置 ## 插件配置
@ -139,8 +150,11 @@
// 是否接收群消息并发送到游戏里 // 是否接收群消息并发送到游戏里
"isSendToGame": true, "isSendToGame": true,
// // 管理员账号 // 管理员账号
// "adminId": 0, "adminIds": [0],
// 管理员执行命令前缀
"adminPrefix": "/",
// 是否启用登录消息 // 是否启用登录消息
// 当玩家登录服务器时,发送消息通知到群里 // 当玩家登录服务器时,发送消息通知到群里
@ -151,6 +165,15 @@
// {uid} 为玩家UID // {uid} 为玩家UID
"loginMessageFormat": "{nickName}({uid}) 加入了服务器", "loginMessageFormat": "{nickName}({uid}) 加入了服务器",
// 是否启用登录消息
// 当玩家登录服务器时,发送消息通知到群里
"sendLoginMessageToGame": true,
// 玩家登录服务器消息格式
// {nickName} 为玩家昵称
// {uid} 为玩家UID
"loginMessageFormatInGame": "<color=#99CC99>{nickName}({uid}) 加入了游戏</color>",
// 是否启用登出消息 // 是否启用登出消息
// 当玩家离开服务器时,发送消息通知到群里 // 当玩家离开服务器时,发送消息通知到群里
"sendLogoutMessageToBot": true, "sendLogoutMessageToBot": true,
@ -159,6 +182,15 @@
// {nickName} 为玩家昵称 // {nickName} 为玩家昵称
// {uid} 为玩家UID // {uid} 为玩家UID
"logoutMessageFormat": "{nickName}({uid}) 离开了服务器", "logoutMessageFormat": "{nickName}({uid}) 离开了服务器",
// 是否启用登出消息
// 当玩家离开服务器时,发送消息通知到群里
"sendLogoutMessageToGame": true,
// 玩家登出服务器消息格式
// {nickName} 为玩家昵称
// {uid} 为玩家UID
"logoutMessageFormatInGame": "<color=#99CC99>{nickName}({uid}) 离开了游戏</color>",
} }
``` ```

View File

@ -17,6 +17,9 @@
*/ */
package com.github.jie65535.openchat; package com.github.jie65535.openchat;
import java.util.ArrayList;
import java.util.List;
public class OpenChatConfig { public class OpenChatConfig {
/** /**
@ -127,10 +130,16 @@ public class OpenChatConfig {
*/ */
public boolean isSendToGame = true; public boolean isSendToGame = true;
// /** /**
// * 管理员账号 * 管理员账号列表
// */ * 所有来自管理员的消息如果和命令前缀匹配将作为控制台命令执行
// public Long adminId = 0L; */
public ArrayList<Long> adminIds = new ArrayList<>(List.of(0L));
/**
* 管理员执行命令前缀
*/
public String adminPrefix = "/";
/** /**
* 是否启用登录消息 * 是否启用登录消息
@ -145,6 +154,19 @@ public class OpenChatConfig {
*/ */
public String loginMessageFormat = "{nickName}({uid}) 加入了服务器"; public String loginMessageFormat = "{nickName}({uid}) 加入了服务器";
/**
* 是否启用登录消息
* 当玩家登录服务器时发送消息通知到游戏里
*/
public boolean sendLoginMessageToGame = true;
/**
* 玩家登录服务器消息格式游戏内
* {nickName} 为玩家昵称
* {uid} 为玩家UID
*/
public String loginMessageFormatInGame = "<color=#99CC99>{nickName}({uid}) 加入了游戏</color>";
/** /**
* 是否启用登出消息 * 是否启用登出消息
* 当玩家离开服务器时发送消息通知到群里 * 当玩家离开服务器时发送消息通知到群里
@ -157,4 +179,17 @@ public class OpenChatConfig {
* {uid} 为玩家UID * {uid} 为玩家UID
*/ */
public String logoutMessageFormat = "{nickName}({uid}) 离开了服务器"; public String logoutMessageFormat = "{nickName}({uid}) 离开了服务器";
/**
* 是否启用登出消息
* 当玩家登录服务器时发送消息通知到游戏里
*/
public boolean sendLogoutMessageToGame = true;
/**
* 玩家登出服务器消息格式游戏内
* {nickName} 为玩家昵称
* {uid} 为玩家UID
*/
public String logoutMessageFormatInGame = "<color=#99CC99>{nickName}({uid}) 离开了游戏</color>";
} }

View File

@ -20,6 +20,7 @@ package com.github.jie65535.openchat;
import com.github.jie65535.minionebot.MiniOneBot; import com.github.jie65535.minionebot.MiniOneBot;
import com.github.jie65535.minionebot.events.GroupMessage; import com.github.jie65535.minionebot.events.GroupMessage;
import emu.grasscutter.GameConstants; import emu.grasscutter.GameConstants;
import emu.grasscutter.command.CommandMap;
import emu.grasscutter.game.chat.ChatSystem; import emu.grasscutter.game.chat.ChatSystem;
import emu.grasscutter.game.player.Player; import emu.grasscutter.game.player.Player;
import emu.grasscutter.server.event.player.PlayerJoinEvent; import emu.grasscutter.server.event.player.PlayerJoinEvent;
@ -65,11 +66,22 @@ public class OpenChatSystem extends ChatSystem {
* @param event 事件 * @param event 事件
*/ */
public void onPlayerJoin(PlayerJoinEvent event) { public void onPlayerJoin(PlayerJoinEvent event) {
if (!plugin.getConfig().sendLoginMessageToBot || plugin.getConfig().groupId < 1) return;
var player = event.getPlayer(); var player = event.getPlayer();
miniOneBot.sendGroupMessage(plugin.getConfig().groupId, plugin.getConfig().loginMessageFormat // 发送上线消息到群里
.replace("{nickName}", player.getNickname()) if (plugin.getConfig().sendLoginMessageToBot && plugin.getConfig().groupId >= 1) {
.replace("{uid}", String.valueOf(player.getUid()))); miniOneBot.sendGroupMessage(plugin.getConfig().groupId, plugin.getConfig().loginMessageFormat
.replace("{nickName}", player.getNickname())
.replace("{uid}", String.valueOf(player.getUid())));
}
// 发送上线消息到游戏
if (plugin.getConfig().sendLoginMessageToGame) {
broadcastChatMessage(plugin.getConfig().loginMessageFormatInGame
.replace("{nickName}", player.getNickname())
.replace("{uid}", String.valueOf(player.getUid())),
player.getUid()
);
}
} }
/** /**
@ -87,11 +99,21 @@ public class OpenChatSystem extends ChatSystem {
super.clearHistoryOnLogout(player); super.clearHistoryOnLogout(player);
hasHistory.remove(player.getUid()); hasHistory.remove(player.getUid());
// 发送离线消息 // 发送离线消息到群里
if (!plugin.getConfig().sendLogoutMessageToBot || plugin.getConfig().groupId < 1) return; if (plugin.getConfig().sendLogoutMessageToBot && plugin.getConfig().groupId >= 1) {
miniOneBot.sendGroupMessage(plugin.getConfig().groupId, plugin.getConfig().logoutMessageFormat miniOneBot.sendGroupMessage(plugin.getConfig().groupId, plugin.getConfig().logoutMessageFormat
.replace("{nickName}", player.getNickname()) .replace("{nickName}", player.getNickname())
.replace("{uid}", String.valueOf(player.getUid()))); .replace("{uid}", String.valueOf(player.getUid())));
}
// 发送离线消息到游戏
if (plugin.getConfig().sendLogoutMessageToGame) {
broadcastChatMessage(plugin.getConfig().logoutMessageFormatInGame
.replace("{nickName}", player.getNickname())
.replace("{uid}", String.valueOf(player.getUid())),
player.getUid()
);
}
} }
/** /**
@ -196,19 +218,15 @@ public class OpenChatSystem extends ChatSystem {
.replace("{message}", message); .replace("{message}", message);
// 转发给其它玩家 // 转发给其它玩家
for (Player p : getServer().getPlayers().values()) { broadcastChatMessage(formattedMessage, player.getUid());
// 将消息发送给除了自己以外所有未关闭聊天的玩家
if (p != player && !plugin.getData().offChatPlayers.contains(p.getUid())) {
p.dropMessage(formattedMessage);
}
}
// 转发到机器人 // 转发到机器人
if (!plugin.getConfig().isSendToBot || plugin.getConfig().groupId < 1) return; if (plugin.getConfig().isSendToBot && plugin.getConfig().groupId >= 1) {
miniOneBot.sendGroupMessage(plugin.getConfig().groupId, plugin.getConfig().gameToGroupFormat miniOneBot.sendGroupMessage(plugin.getConfig().groupId, plugin.getConfig().gameToGroupFormat
.replace("{nickName}", player.getNickname()) .replace("{nickName}", player.getNickname())
.replace("{uid}", String.valueOf(player.getUid())) .replace("{uid}", String.valueOf(player.getUid()))
.replace("{message}", message)); .replace("{message}", message));
}
} }
/** /**
@ -217,16 +235,34 @@ public class OpenChatSystem extends ChatSystem {
* @param event 群消息事件 * @param event 群消息事件
*/ */
private void onGroupMessage(GroupMessage event) { private void onGroupMessage(GroupMessage event) {
if (!plugin.getConfig().isSendToGame if (plugin.getConfig().groupId < 1 || event.groupId() != plugin.getConfig().groupId) return;
|| plugin.getConfig().groupId < 1
|| event.groupId() != plugin.getConfig().groupId // 判断是否管理员发送的消息
) return; if (plugin.getConfig().adminIds.contains(event.senderId())
&& !plugin.getConfig().adminPrefix.isEmpty() // 判断是否符合命令前缀
&& event.message().startsWith(plugin.getConfig().adminPrefix)
) {
try {
logger.info("Command used by op [{}({})]: {}", event.senderCardOrNickname(), event.senderId(), event.message());
// 尝试执行管理员命令
CommandMap.getInstance().invoke(null, null,
event.message().substring(plugin.getConfig().adminPrefix.length()));
} catch (Exception ex) {
logger.error("Administrator command execution failed", ex);
}
return;
}
// 检查开关
if (!plugin.getConfig().isSendToGame) return;
// log messages // log messages
if (plugin.getConfig().logChat) { if (plugin.getConfig().logChat) {
logger.info("[MiniOneBot] {}: \"{}\"", logger.info("[MiniOneBot] {}: \"{}\"",
event.senderCardOrNickname(), event.message()); event.senderCardOrNickname(), event.message());
} }
// 发送给所有玩家
broadcastChatMessage(plugin.getConfig().groupToGameFormat broadcastChatMessage(plugin.getConfig().groupToGameFormat
.replace("{id}", String.valueOf(event.senderId())) .replace("{id}", String.valueOf(event.senderId()))
.replace("{name}", event.senderCardOrNickname()) .replace("{name}", event.senderCardOrNickname())
@ -238,9 +274,19 @@ public class OpenChatSystem extends ChatSystem {
* *
* @param message 纯文本消息 * @param message 纯文本消息
*/ */
public void broadcastChatMessage(String message) { private void broadcastChatMessage(String message) {
broadcastChatMessage(message, 0);
}
/**
* 广播聊天消息给除了指定玩家外所有玩家未开启聊天玩家除外
*
* @param message 纯文本消息
* @param exceptId 排除在外的Uid
*/
private void broadcastChatMessage(String message, int exceptId) {
for (Player p : getServer().getPlayers().values()) { for (Player p : getServer().getPlayers().values()) {
if (!plugin.getData().offChatPlayers.contains(p.getUid())) { if (p.getUid() != exceptId && !plugin.getData().offChatPlayers.contains(p.getUid())) {
p.dropMessage(message); p.dropMessage(message);
} }
} }

View File

@ -33,6 +33,7 @@ import java.util.List;
"limit <timesPerMinute>", "limit <timesPerMinute>",
"reload", "reload",
"group <groupId>", "group <groupId>",
"op|deop <userId(QQ)>",
}, },
permission = "server.chat", permission = "server.chat",
permissionTargeted = "server.chat.others", permissionTargeted = "server.chat.others",
@ -112,7 +113,7 @@ public class ChatServerCommands implements CommandHandler {
var groupId = 0L; var groupId = 0L;
try { try {
groupId = Long.parseLong(args.get(1)); groupId = Long.parseLong(args.get(1));
} catch (NumberFormatException ignored) { } catch (Exception ignored) {
sendUsageMessage(sender); sendUsageMessage(sender);
return; return;
} }
@ -120,6 +121,22 @@ public class ChatServerCommands implements CommandHandler {
plugin.saveConfig(); plugin.saveConfig();
CommandHandler.sendMessage(sender, "OK"); CommandHandler.sendMessage(sender, "OK");
} }
case "op", "deop" -> {
var adminId = 0L;
try {
adminId = Long.parseLong(args.get(1));
} catch (Exception ignored) {
sendUsageMessage(sender);
return;
}
if (subCommand.equals("op")) {
plugin.getConfig().adminIds.add(adminId);
} else {
plugin.getConfig().adminIds.remove(adminId);
}
plugin.saveConfig();
CommandHandler.sendMessage(sender, "OK");
}
default -> sendUsageMessage(sender); default -> sendUsageMessage(sender);
} }
} }