Compare commits

..

No commits in common. "master" and "1.0.6" have entirely different histories.

16 changed files with 29 additions and 211 deletions

View File

@ -1 +1 @@
1.0.7
1.0.5

View File

@ -14,7 +14,7 @@ allprojects {
apply(plugin = "java-library")
val groupName by extra("cn.wzpmc")
val projectArtifactId by extra("my-bot")
val projectVersion by extra("1.0.7-SNAPSHOT")
val projectVersion by extra("1.0.6")
repositories {
mavenCentral()
maven("https://libraries.minecraft.net")

View File

@ -8,20 +8,12 @@ package cn.wzpmc.plugins.configuration;
* @since 2024/7/31 上午3:42
*/
public interface IConfiguration {
/**
* @return WebSocket连接URL
* @author wzp
* @since 2025/3/26 17:29 v1.0.7
* @return 网络相关配置
* @since 2024/7/31 上午3:48 v0.0.1-dev
*/
INetworkConfiguration getNetwork();
/**
*
* @author wzp
* @since 2025/2/4 13:44 v1.0.5
* @return 命令前缀
*/
String getCommandPrefix();
String getWebsocket();
/**
* @return 通信验证

View File

@ -1,38 +0,0 @@
package cn.wzpmc.plugins.configuration;
/**
* @author wzp
* @since 2025/3/26 17:26
* @version 1.0.7
*/
public interface INetworkConfiguration {
/**
* @return WebSocket连接URL
* @author wzp
* @since 2025/3/26 17:26 v1.0.7
*/
String getWebsocket();
/**
* @author wzp
* @since 2025/3/26 17:27 v1.0.7
* @return 是否启用连接重试
*/
Boolean isRetry();
/**
* @author wzp
* @since 2025/3/26 17:27 v1.0.7
* @return 重试最大次数-1为无限
*/
Integer getMaxRetryCount();
/**
* @author wzp
* @since 2025/3/26 17:28 v1.0.7
* @return 获取重试间隔单位毫秒
*/
Long getRetryInterval();
}

View File

@ -18,7 +18,6 @@ import cn.wzpmc.utils.JsonUtils;
import cn.wzpmc.utils.ReflectionUtils;
import cn.wzpmc.utils.TemplateFileUtils;
import cn.wzpmc.utils.YamlUtils;
import com.alibaba.fastjson2.JSONObject;
import lombok.SneakyThrows;
import lombok.extern.log4j.Log4j2;
@ -53,7 +52,6 @@ public class Main {
}
log.debug("读取配置文件 {}", configurationFile.getAbsolutePath());
Configuration configuration = YamlUtils.readYamlFile(configurationFile, Configuration.class);
JSONObject fullConfiguration = YamlUtils.readYamlFile(configurationFile, JSONObject.class);
Configuration defaultConfiguration = TemplateFileUtils.readDefaultConfig(classLoader, DEFAULT_CONFIGURATION_FILE_PATH, Configuration.class);
// 配置文件自动更新 start
boolean isChanged = false;
@ -75,24 +73,11 @@ public class Main {
isChanged = true;
}
// end
// 1.0.7 配置文件自动更新
if (configuration.getCommandPrefix() == null) {
configuration.setCommandPrefix(defaultConfiguration.getCommandPrefix());
isChanged = true;
}
if (configuration.getNetwork() == null) {
configuration.setNetwork(defaultConfiguration.getNetwork());
configuration.getNetwork().setWebsocket(fullConfiguration.getString("websocket"));
isChanged = true;
}
// end
if (isChanged) {
log.warn("已自动升级配置文件请检查config.yml是否有错误的地方有则请修改");
YamlUtils.writeYamlFile(configurationFile, configuration);
}
// 配置文件自动更新end
return configuration;
}
@ -103,7 +88,7 @@ public class Main {
public static URI getUriFromConfiguration(Configuration configuration) {
URI uri;
try {
uri = new URI(configuration.getNetwork().getWebsocket());
uri = new URI(configuration.getWebsocket());
} catch (URISyntaxException e) {
return null;
}
@ -142,8 +127,8 @@ public class Main {
}
public static WebSocketConnectionHandler createConnection(MyBot myBot, URI uri) {
WebSocketConnectionHandler webSocketConnectionHandler = new WebSocketConnectionHandler(myBot, uri);
webSocketConnectionHandler.connect();
WebSocketConnectionHandler webSocketConnectionHandler = new WebSocketConnectionHandler(myBot);
webSocketConnectionHandler.connect(uri);
return webSocketConnectionHandler;
}

View File

@ -25,12 +25,10 @@ import java.util.concurrent.ConcurrentHashMap;
*/
public class HelpCommand implements BrigadierCommand {
private final CommandManager commandManager;
private final String commandPrefix;
public HelpCommand() {
IBot instance = MyBot.getInstance();
this.commandManager = (CommandManager) instance.getCommandManager();
this.commandPrefix = instance.getConfiguration().getCommandPrefix();
}
private static void handlerNode(Collection<CommandNode<CommandSender>> node, int tabCount, StringBuilder builder) {
@ -56,7 +54,7 @@ public class HelpCommand implements BrigadierCommand {
CommandSender source = e.getSource();
for (CommandNode<CommandSender> child : children) {
StringBuilder builder = new StringBuilder();
builder.append(commandPrefix);
builder.append('/');
builder.append(child.getUsageText());
builder.append('\n');
handlerNode(child.getChildren(), 1, builder);
@ -65,7 +63,7 @@ public class HelpCommand implements BrigadierCommand {
}
ConcurrentHashMap<String, RawCommand> rawCommands = this.commandManager.getRawCommands();
for (Map.Entry<String, RawCommand> stringRawCommandEntry : rawCommands.entrySet()) {
source.sendMessage(StringMessage.text(commandPrefix + stringRawCommandEntry.getKey()));
source.sendMessage(StringMessage.text("/" + stringRawCommandEntry.getKey()));
}
return 0;
}).
@ -80,7 +78,7 @@ public class HelpCommand implements BrigadierCommand {
continue;
}
StringBuilder builder = new StringBuilder();
builder.append(commandPrefix);
builder.append('/');
builder.append(child.getUsageText());
builder.append('\n');
handlerNode(child.getChildren(), 1, builder);
@ -89,7 +87,7 @@ public class HelpCommand implements BrigadierCommand {
}
ConcurrentHashMap<String, RawCommand> rawCommands = this.commandManager.getRawCommands();
for (Map.Entry<String, RawCommand> stringRawCommandEntry : rawCommands.entrySet()) {
source.sendMessage(StringMessage.text(commandPrefix + stringRawCommandEntry.getKey()));
source.sendMessage(StringMessage.text("/" + stringRawCommandEntry.getKey()));
}
return 0;
})

View File

@ -26,14 +26,12 @@ public class CommandEventHandler {
public void onGroupMessage(GroupMessageEvent event) {
GroupCommandSender groupCommandSender = GroupCommandSender.of(event);
IBot instance = MyBot.getInstance();
String commandPrefix = instance.getConfiguration().getCommandPrefix();
Long id = instance.getId();
String message = event.getRawMessage().getMessage();
String quotedPrefix = Pattern.quote(commandPrefix);
Pattern compile = Pattern.compile("\\[CQ:at,qq=" + id + ".*?]\\s*?" + quotedPrefix + ".*");
Pattern compile = Pattern.compile("\\[CQ:at,qq=" + id + ".*?]\\s*?/.*");
if (compile.asMatchPredicate().test(message)) {
CommandManager commandManager = (CommandManager) instance.getCommandManager();
String commandRaw = message.replaceFirst("\\[CQ:at,qq=[0-9]{10}.*?]\\s*?" + quotedPrefix, "");
String commandRaw = message.replaceFirst("\\[CQ:at,qq=[0-9]{10}.*?]\\s*?/", "");
log.info("群{}中的用户{}使用了指令{}", groupCommandSender.getGroupId(), groupCommandSender.getId(), commandRaw);
commandManager.execute(groupCommandSender, commandRaw);
}
@ -45,10 +43,9 @@ public class CommandEventHandler {
IBot instance = MyBot.getInstance();
StringMessage rawMessage = event.getRawMessage();
String message = rawMessage.getMessage();
String commandPrefix = instance.getConfiguration().getCommandPrefix();
if (message.startsWith(commandPrefix)) {
if (message.startsWith("/")) {
CommandManager commandManager = (CommandManager) instance.getCommandManager();
String commandRaw = message.replaceFirst(commandPrefix, "");
String commandRaw = message.replaceFirst("/", "");
log.info("用户{}使用了指令{}", sender.getId(), commandRaw);
commandManager.execute(sender, commandRaw);
}

View File

@ -12,19 +12,12 @@ import lombok.Data;
*/
@Data
public class Configuration implements IConfiguration {
/**
* 网络相关配置
* @since 2025/3/26 17:32 v1.0.7
* WebSocket连接URL
*
* @since 2024/7/30 下午11:48 v0.0.1-dev
*/
private NetworkConfiguration network;
/**
* 命令前缀
* @since 2025/2/4 13:45 v1.0.5
*/
private String commandPrefix;
private String websocket;
/**
* 通信验证
*

View File

@ -1,38 +0,0 @@
package cn.wzpmc.configuration;
import cn.wzpmc.plugins.configuration.INetworkConfiguration;
import lombok.Data;
/**
* @author wzp
* @since 2025/3/26 17:29
* @version 1.0.7
*/
@Data
public class NetworkConfiguration implements INetworkConfiguration {
/**
* WebSocket连接URL
* @since 2025/3/26 17:31 v1.0.7
*/
private String websocket;
/**
* 是否启用连接重试
* @since 2025/3/26 17:31 v1.0.7
*/
private Boolean retry;
/**
* 重试最大次数-1为无限
* @since 2025/3/26 17:31 v1.0.7
*/
private Integer maxRetryCount;
/**
* 获取重试间隔单位毫秒
* @since 2025/3/26 17:31 v1.0.7
*/
private Long retryInterval;
@Override
public Boolean isRetry() {
return this.retry;
}
}

View File

@ -1,10 +1,8 @@
package cn.wzpmc.console;
import cn.wzpmc.entities.api.ApiResponseRequired;
import cn.wzpmc.entities.user.bot.MyBot;
import cn.wzpmc.network.WebSocketConnectionHandler;
import cn.wzpmc.plugins.CommandManager;
import cn.wzpmc.utils.json.action.ActionReader;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
@ -49,16 +47,12 @@ public class MyBotConsole extends SimpleTerminalConsole {
@Override
public void shutdown() {
this.webSocketConnectionHandler.kill();
for (ApiResponseRequired<?, ?> value : ActionReader.tasks.values()) {
value.getFuture().complete(null);
}
running = false;
}
@Override
public void start() {
this.bot.setConsole(this);
if (this.bot.isShutdown()) return;
super.start();
}
}

View File

@ -50,8 +50,6 @@ public class MyBot extends IBot {
private final Configuration configuration;
private final CommandManager commandManager = new CommandManager(this);
private final PluginManager pluginManager = new PluginManager();
@Setter
private boolean shutdown = false;
private final IncreasbleHashMap<Class<? extends Event>, EventHandlerMethod> events = new IncreasbleHashMap<>();
@Getter
private final Ops ops;

View File

@ -37,6 +37,7 @@ public class HandshakePacketHandler extends SimpleChannelInboundHandler<FullHttp
handshaker.finishHandshake(channelHandlerContext.channel(), fullHttpResponse);
this.handshakeFuture.complete(true);
log.debug("握手成功");
log.info("连接服务器成功!");
}
}
}

View File

@ -32,8 +32,6 @@ import java.util.concurrent.Executors;
public class PacketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {
private final IBot bot;
private final ExecutorService threadPool = Executors.newFixedThreadPool(4);
private final Runnable retryFunction;
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame webSocketFrame) {
@ -107,10 +105,4 @@ public class PacketHandler extends SimpleChannelInboundHandler<TextWebSocketFram
public <REQUEST, RESPONSE> void registerResponse(UUID echo, CompletableFuture<ActionResponse<RESPONSE>> responsePromise, Action<REQUEST, RESPONSE> request) {
ActionReader.tasks.put(echo, new ApiResponseRequired<>(responsePromise, request));
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
log.info("与服务器断开连接!");
retryFunction.run();
}
}

View File

@ -2,11 +2,7 @@ package cn.wzpmc.network;
import cn.wzpmc.api.Action;
import cn.wzpmc.api.ActionResponse;
import cn.wzpmc.console.MyBotConsole;
import cn.wzpmc.entities.api.ApiResponseRequired;
import cn.wzpmc.entities.user.bot.MyBot;
import cn.wzpmc.plugins.configuration.INetworkConfiguration;
import cn.wzpmc.utils.json.action.ActionReader;
import cn.wzpmc.user.IBot;
import com.alibaba.fastjson2.JSON;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
@ -36,70 +32,26 @@ import java.util.concurrent.ExecutionException;
@RequiredArgsConstructor
public class WebSocketConnectionHandler {
private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
private final MyBot bot;
/**
* websocket连接地址
* @since 2025/3/26 17:56 v1.0.7
*/
private final URI websocket;
private final IBot bot;
private ChannelFuture channelFuture;
private PacketHandler packetHandler;
private HandshakePacketHandler handshakePacketHandler;
private int currentRetryCount = 0;
private void tryReconnect() {
INetworkConfiguration network = bot.getConfiguration().getNetwork();
if (!network.isRetry()) {
this.quit();
return;
}
Integer maxRetryCount = network.getMaxRetryCount();
if (maxRetryCount != 0 && currentRetryCount >= maxRetryCount) {
this.quit();
return;
}
this.currentRetryCount++;
log.info("尝试重连第{}次", currentRetryCount);
this.connect();
}
private void quit() {
for (ApiResponseRequired<?, ?> value : ActionReader.tasks.values()) {
value.getFuture().obtrudeException(new InterruptedException());
}
this.handshakePacketHandler.getHandshakeFuture().obtrudeException(new InterruptedException());
MyBotConsole console = bot.getConsole();
bot.setShutdown(true);
if (console == null) {
this.eventLoopGroup.shutdownGracefully();
return;
}
console.shutdown();
}
/**
* 建立连接
*
* @param websocket websocket连接地址
* @author wzp
* @since 2024/7/30 下午11:55 v0.0.1-dev
*/
public void connect() {
public void connect(URI websocket) {
log.info("正在连接websocket");
Bootstrap bootstrap = new Bootstrap();
WebSocketClientHandshaker clientHandshaker = WebSocketClientHandshakerFactory.newHandshaker(websocket, WebSocketVersion.V13, null, false, new DefaultHttpHeaders(), 65536 * 100);
this.handshakePacketHandler = new HandshakePacketHandler(clientHandshaker);
this.packetHandler = new PacketHandler(this.bot, this::tryReconnect);
this.packetHandler = new PacketHandler(this.bot);
bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class).handler(new WebSocketChannelInitializer(this.packetHandler, this.handshakePacketHandler));
this.channelFuture = bootstrap.connect(websocket.getHost(), websocket.getPort());
this.channelFuture.addListener(future -> {
if (!future.isSuccess()) {
log.info("连接失败!");
this.tryReconnect();
} else {
log.info("连接成功!");
this.currentRetryCount = 0;
}
});
}
/**
@ -129,7 +81,6 @@ public class WebSocketConnectionHandler {
this.handshakePacketHandler.getHandshakeFuture().get();
} catch (ExecutionException e) {
log.error(e);
return null;
}
CompletableFuture<ActionResponse<RESPONSE>> responsePromise = new CompletableFuture<>();
packetHandler.registerResponse(request.getEcho(), responsePromise, request);

View File

@ -1,7 +1,6 @@
package cn.wzpmc.utils;
import cn.wzpmc.configuration.Configuration;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.log4j.Log4j2;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
@ -31,8 +30,7 @@ public class YamlUtils {
*/
public static <T> T readYamlStream(InputStream is, Class<T> clazz) {
Yaml yaml = new Yaml();
JSONObject json = yaml.loadAs(is, JSONObject.class);
return json.to(clazz);
return yaml.loadAs(is, clazz);
}
/**

View File

@ -1,9 +1,4 @@
network:
websocket: "<Your WebSocket connection link, e.g: ws://127.0.0.1:3001/>"
retry: true
maxRetryCount: 3
retryInterval: 10000
commandPrefix: "/"
websocket: "<Your WebSocket connection link, e.g: ws://127.0.0.1:3001/>"
authorization:
enable: false
token: "<If you enable authorization, you should fill in this>"