diff --git a/src/CaiBot/Config.cs b/src/CaiBot/Config.cs index 4524ef459..74a4e8eae 100644 --- a/src/CaiBot/Config.cs +++ b/src/CaiBot/Config.cs @@ -5,9 +5,9 @@ namespace CaiBot; public class Config { - private const string Path = "tshock/CaiBot.json"; + private const string ConfigPath = "tshock/CaiBot.json"; - public static Config config = new (); + public static Config Settings = new (); [JsonProperty("白名单开关",Order = 1)] public bool WhiteList = true; [JsonProperty("密钥",Order = 2)] public string Token = ""; [JsonProperty("白名单拦截提示的群号",Order = 3)] public long GroupNumber; @@ -21,42 +21,39 @@ public class Config [JsonProperty("群聊天发送格式",Order = 9)] public string GroupChatFormat = "[{0}]{1}:{2}"; // "[群名]玩家昵称:内容" 额外 {3}:群QQ号 {4}:发送者QQ [JsonProperty("群聊天自定义群名",Order = 10)] public Dictionary CustomGroupName = new (); - public void Write(string path = Path) + /// + /// 将配置文件写入硬盘 + /// + public void Write() { - using FileStream fileStream = new (path, FileMode.Create, FileAccess.Write, FileShare.Write); - this.Write(fileStream); + using FileStream fileStream = new(ConfigPath, FileMode.Create, FileAccess.Write, FileShare.Write); + using StreamWriter streamWriter = new(fileStream); + streamWriter.Write(JsonConvert.SerializeObject(this, JsonSettings)); } - private void Write(Stream stream) + /// + /// 从硬盘读取配置文件 + /// + public void Read() { - var value = JsonConvert.SerializeObject(this, Formatting.Indented); - using StreamWriter streamWriter = new (stream); - streamWriter.Write(value); - } - - public static void Read(string path = Path) - { - var flag = !File.Exists(path); - Config? result; - if (flag) + Config result; + if (!File.Exists(ConfigPath)) { result = new Config(); - result.Write(path); + result.Write(); } else { - using FileStream fileStream = new (path, FileMode.Open, FileAccess.Read, FileShare.Read); - result = Read(fileStream); + using FileStream fileStream = new(ConfigPath, FileMode.Open, FileAccess.Read, FileShare.Read); + using StreamReader streamReader = new(fileStream); + result = JsonConvert.DeserializeObject(streamReader.ReadToEnd(), JsonSettings)!; } - - config = result!; + Settings = result; } - - private static Config? Read(Stream stream) + + private static readonly JsonSerializerSettings JsonSettings = new() { - using StreamReader streamReader = new (stream); - var result = JsonConvert.DeserializeObject(streamReader.ReadToEnd()); - - return result; - } + Formatting = Formatting.Indented, + ObjectCreationHandling = ObjectCreationHandling.Replace + }; } \ No newline at end of file diff --git a/src/CaiBot/Login.cs b/src/CaiBot/Login.cs index 18a0257f6..a731a1397 100644 --- a/src/CaiBot/Login.cs +++ b/src/CaiBot/Login.cs @@ -15,7 +15,7 @@ public static bool MessageBuffer_InvokeGetData(Hooks.MessageBuffer.orig_InvokeGe MessageBuffer instance, ref byte packetId, ref int readOffset, ref int start, ref int length, ref int messageType, int maxPackets) { - if (!Config.config.WhiteList) + if (!Config.Settings.WhiteList) { return orig(instance, ref packetId, ref readOffset, ref start, ref length, ref messageType, maxPackets); } @@ -57,7 +57,7 @@ public static bool MessageBuffer_InvokeGetData(Hooks.MessageBuffer.orig_InvokeGe public static void OnGetData(GetDataEventArgs args) { - if (!Config.config.WhiteList) + if (!Config.Settings.WhiteList) { return; } @@ -97,7 +97,7 @@ public static void OnGetData(GetDataEventArgs args) public static bool CheckWhite(string name, int code) { var playerList = TSPlayer.FindByNameOrID("tsn:" + name); - var number = Config.config.GroupNumber; + var number = Config.Settings.GroupNumber; if (playerList.Count == 0) { return false; diff --git a/src/CaiBot/MessageHandler.cs b/src/CaiBot/MessageHandler.cs index 63d2c9e77..b0771d5eb 100644 --- a/src/CaiBot/MessageHandler.cs +++ b/src/CaiBot/MessageHandler.cs @@ -38,8 +38,8 @@ public static async Task HandleMessageAsync(string receivedData) { case "delserver": TShock.Log.ConsoleInfo("[CaiAPI]BOT发送解绑命令..."); - Config.config.Token = ""; - Config.config.Write(); + Config.Settings.Token = ""; + Config.Settings.Write(); Random rnd = new (); Plugin.InitCode = rnd.Next(10000000, 99999999); TShock.Log.ConsoleError($"[CaiBot]您的服务器绑定码为: {Plugin.InitCode}"); @@ -54,11 +54,11 @@ public static async Task HandleMessageAsync(string receivedData) { "tshock_version", TShock.VersionNum.ToString() }, { "plugin_version", Plugin.VersionNum }, { "terraria_version", Main.versionNumber }, - { "cai_whitelist", Config.config.WhiteList }, + { "cai_whitelist", Config.Settings.WhiteList }, { "os", RuntimeInformation.RuntimeIdentifier }, { "world", TShock.Config.Settings.UseServerName ? TShock.Config.Settings.ServerName : Main.worldName }, - { "sync_group_chat", Config.config.SyncChatFromGroup }, - { "sync_server_chat", Config.config.SyncChatFromServer }, + { "sync_group_chat", Config.Settings.SyncChatFromGroup }, + { "sync_server_chat", Config.Settings.SyncChatFromServer }, { "group", (long) jsonObject["group"]! } }; await SendDateAsync(JsonConvert.SerializeObject(result)); @@ -66,13 +66,13 @@ public static async Task HandleMessageAsync(string receivedData) case "groupid": var groupId = (long) jsonObject["groupid"]!; TShock.Log.ConsoleInfo($"[CaiAPI]群号获取成功: {groupId}"); - if (Config.config.GroupNumber != 0L) + if (Config.Settings.GroupNumber != 0L) { - TShock.Log.ConsoleWarn($"[CaiAPI]检测到你在配置文件中已设置群号[{Config.config.GroupNumber}],BOT自动获取的群号将被忽略!"); + TShock.Log.ConsoleWarn($"[CaiAPI]检测到你在配置文件中已设置群号[{Config.Settings.GroupNumber}],BOT自动获取的群号将被忽略!"); } else { - Config.config.GroupNumber = groupId; + Config.Settings.GroupNumber = groupId; } break; @@ -85,31 +85,18 @@ public static async Task HandleMessageAsync(string receivedData) await SendDateAsync(JsonConvert.SerializeObject(result)); break; case "online": - var onlineResult = ""; + var onlineResult = new StringBuilder(); if (TShock.Utils.GetActivePlayerCount() == 0) { - onlineResult = "当前没有玩家在线捏"; + onlineResult.AppendLine("没有玩家在线捏..."); } else { - onlineResult += $"在线的玩家({TShock.Utils.GetActivePlayerCount()}/{TShock.Config.Settings.MaxSlots})\n"; - - - List players = new (); - - foreach (var ply in TShock.Players) - { - if (ply is { Active: true }) - { - players.Add(ply.Name); - } - } - - onlineResult += string.Join(',', players); + onlineResult.AppendLine($"在线玩家({TShock.Utils.GetActivePlayerCount()}/{TShock.Config.Settings.MaxSlots})"); + onlineResult.AppendLine(string.Join(',', TShock.Players.Where(x=>x!=null && x.Active).Select(x=>x.Name))); } List onlineProcessList = new (); - #region 进度查询 if (!NPC.downedSlimeKing) @@ -181,8 +168,8 @@ public static async Task HandleMessageAsync(string receivedData) result = new RestObject { { "type", "online" }, - { "result", onlineResult }, - { "worldname", Main.worldName }, + { "result", onlineResult.ToString()}, // “怎么有种我是男的的感觉” -- 张芷睿大人 (24.12.22) + { "worldname", string.IsNullOrEmpty(Main.worldName) ? "地图还没加载捏~" : Main.worldName }, { "process", onlineProcess }, { "group", (long) jsonObject["group"]! } }; @@ -546,12 +533,12 @@ public static async Task HandleMessageAsync(string receivedData) var chatText = (string) jsonObject["chat_text"]!; var groupNumber = (long) jsonObject["group_id"]!; var senderId = (long) jsonObject["sender_id"]!; - if (Config.config.CustomGroupName.TryGetValue(groupNumber, out var value)) + if (Config.Settings.CustomGroupName.TryGetValue(groupNumber, out var value)) { groupName = value; } - TShock.Utils.Broadcast(string.Format(Config.config.GroupChatFormat, groupName, nickname, chatText, groupNumber, senderId), Color.White); + TShock.Utils.Broadcast(string.Format(Config.Settings.GroupChatFormat, groupName, nickname, chatText, groupNumber, senderId), Color.White); break; } } diff --git a/src/CaiBot/Plugin.cs b/src/CaiBot/Plugin.cs index dad6617ae..c3e62a33a 100644 --- a/src/CaiBot/Plugin.cs +++ b/src/CaiBot/Plugin.cs @@ -7,7 +7,6 @@ using System.Reflection; using System.Text; using Terraria; -using Terraria.Localization; using TerrariaApi.Server; using TShockAPI; using TShockAPI.DB; @@ -19,7 +18,7 @@ namespace CaiBot; [ApiVersion(2, 1)] public class Plugin : TerrariaPlugin { - public static readonly Version VersionNum = new (2024, 12, 20, 1); //日期+版本号(0,1,2...) + public static readonly Version VersionNum = new (2024, 12, 22, 1); //日期+版本号(0,1,2...) public static int InitCode = -1; public static bool LocalMode; public static bool DebugMode; @@ -41,12 +40,11 @@ public override void Initialize() { AppDomain.CurrentDomain.AssemblyResolve += this.CurrentDomain_AssemblyResolve; Commands.ChatCommands.Add(new Command("CaiBot.Admin", this.CaiBotCommand, "caibot")); - Config.Read(); - Config.config.Write(); + Config.Settings.Read(); + Config.Settings.Write(); LocalMode = Program.LaunchParameters.ContainsKey("-cailocalbot"); DebugMode = Program.LaunchParameters.ContainsKey("-caidebug"); BanManager.OnBanPostAdd += this.OnBanInsert; - Hooks.MessageBuffer.InvokeGetData += this.MessageBuffer_InvokeGetData; Hooks.MessageBuffer.InvokeGetData += Login.MessageBuffer_InvokeGetData; ServerApi.Hooks.NetGetData.Register(this, Login.OnGetData, int.MaxValue); ServerApi.Hooks.ServerChat.Register(this, this.OnChat, int.MaxValue); @@ -60,7 +58,7 @@ public override void Initialize() try { WebSocket = new ClientWebSocket(); - while (string.IsNullOrEmpty(Config.config.Token)) + while (string.IsNullOrEmpty(Config.Settings.Token)) { await Task.Delay(TimeSpan.FromSeconds(10)); HttpClient client = new (); @@ -68,27 +66,27 @@ public override void Initialize() var response = client.GetAsync($"http://api.terraria.ink:22334/bot/get_token?" + $"code={InitCode}") .Result; - //TShock.Log.ConsoleInfo($"[CaiAPI]尝试被动绑定,状态码:{response.StatusCode}"); - if (response.StatusCode == HttpStatusCode.OK && Config.config.Token == "") + if (response.StatusCode != HttpStatusCode.OK || Config.Settings.Token != "") { - var responseBody = await response.Content.ReadAsStringAsync(); - var json = JObject.Parse(responseBody); - var token = json["token"]!.ToString(); - Config.config.Token = token; - Config.config.Write(); - TShock.Log.ConsoleInfo("[CaiAPI]被动绑定成功!"); + continue; } + var responseBody = await response.Content.ReadAsStringAsync(); + var json = JObject.Parse(responseBody); + var token = json["token"]!.ToString(); + Config.Settings.Token = token; + Config.Settings.Write(); + TShock.Log.ConsoleInfo("[CaiAPI]被动绑定成功!"); } if (LocalMode) { - await WebSocket.ConnectAsync(new Uri("ws://127.0.0.1:22334/bot/" + Config.config.Token), + await WebSocket.ConnectAsync(new Uri("ws://127.0.0.1:22334/bot/" + Config.Settings.Token), CancellationToken.None); TShock.Log.ConsoleWarn("[CaiAPI]你正在使用CaiBot本地模式,请确保你已本地部署CaiBot!"); } else { - await WebSocket.ConnectAsync(new Uri("ws://api.terraria.ink:22334/bot/" + Config.config.Token), + await WebSocket.ConnectAsync(new Uri("ws://api.terraria.ink:22334/bot/" + Config.Settings.Token), CancellationToken.None); } @@ -150,7 +148,6 @@ protected override void Dispose(bool disposing) var asm = Assembly.GetExecutingAssembly(); Commands.ChatCommands.RemoveAll(c => c.CommandDelegate.Method.DeclaringType?.Assembly == asm); AppDomain.CurrentDomain.AssemblyResolve -= this.CurrentDomain_AssemblyResolve; - Hooks.MessageBuffer.InvokeGetData -= this.MessageBuffer_InvokeGetData; Hooks.MessageBuffer.InvokeGetData -= Login.MessageBuffer_InvokeGetData; BanManager.OnBanPostAdd -= this.OnBanInsert; ServerApi.Hooks.NetGetData.Deregister(this, Login.OnGetData); @@ -174,12 +171,12 @@ private void OnChat(ServerChatEventArgs args) { var plr = TShock.Players[args.Who]; - if (Config.config.WhiteList && plr is { IsLoggedIn: false }) + if (Config.Settings.WhiteList && plr is { IsLoggedIn: false }) { args.Handled = true; } - if (!Config.config.SyncChatFromServer || plr == null || !plr.IsLoggedIn || args.Text.StartsWith(TShock.Config.Settings.CommandSpecifier) || args.Text.StartsWith(TShock.Config.Settings.CommandSilentSpecifier) || string.IsNullOrEmpty(args.Text)) + if (!Config.Settings.SyncChatFromServer || plr == null || !plr.IsLoggedIn || args.Text.StartsWith(TShock.Config.Settings.CommandSpecifier) || args.Text.StartsWith(TShock.Config.Settings.CommandSilentSpecifier) || string.IsNullOrEmpty(args.Text)) { return; } @@ -187,8 +184,8 @@ private void OnChat(ServerChatEventArgs args) var result = new RestObject { { "type", "chat" }, - { "chat", string.Format(Config.config.ServerChatFormat, plr.Name, args.Text, plr.Group.Name, plr.Group.Prefix, EconomicSupport.IsSupported("GetLevelName") ? EconomicSupport.GetLevelName(plr.Account.Name).Replace("职业:", "") : "不支持") }, //[Server]玩家名:内容" 额外 {2}:玩家组名 {3}:玩家聊天前缀 {4}:Ec职业名 - { "group", Config.config.GroupNumber } + { "chat", string.Format(Config.Settings.ServerChatFormat, plr.Name, args.Text, plr.Group.Name, plr.Group.Prefix, EconomicSupport.IsSupported("GetLevelName") ? EconomicSupport.GetLevelName(plr.Account.Name).Replace("职业:", "") : "不支持") }, //[Server]玩家名:内容" 额外 {2}:玩家组名 {3}:玩家聊天前缀 {4}:Ec职业名 + { "group", Config.Settings.GroupNumber } }; _ = MessageHandle.SendDateAsync(JsonConvert.SerializeObject(result)); } @@ -196,7 +193,7 @@ private void OnChat(ServerChatEventArgs args) private void PlayerHooksOnPlayerPostLogin(PlayerPostLoginEventArgs e) { var plr = e.Player; - if (!Config.config.SyncChatFromServer || plr == null) + if (!Config.Settings.SyncChatFromServer || plr == null) { return; } @@ -204,8 +201,8 @@ private void PlayerHooksOnPlayerPostLogin(PlayerPostLoginEventArgs e) var result = new RestObject { { "type", "chat" }, - { "chat", string.Format(Config.config.JoinServerFormat, plr.Name, plr.Group.Name, plr.Group.Prefix, EconomicSupport.IsSupported("GetLevelName") ? EconomicSupport.GetLevelName(plr.Account.Name).Replace("职业:", "") : "不支持") }, //[Server]玩家名:内容" 额外 {2}:玩家组名 {3}:玩家聊天前缀 {4}:Ec职业名 - { "group", Config.config.GroupNumber } + { "chat", string.Format(Config.Settings.JoinServerFormat, plr.Name, plr.Group.Name, plr.Group.Prefix, EconomicSupport.IsSupported("GetLevelName") ? EconomicSupport.GetLevelName(plr.Account.Name).Replace("职业:", "") : "不支持") }, //[Server]玩家名:内容" 额外 {2}:玩家组名 {3}:玩家聊天前缀 {4}:Ec职业名 + { "group", Config.Settings.GroupNumber } }; _ = MessageHandle.SendDateAsync(JsonConvert.SerializeObject(result)); } @@ -213,7 +210,7 @@ private void PlayerHooksOnPlayerPostLogin(PlayerPostLoginEventArgs e) private void PlayerHooksOnPlayerLogout(PlayerLogoutEventArgs e) { var plr = e.Player; - if (!Config.config.SyncChatFromServer || plr == null) + if (!Config.Settings.SyncChatFromServer || plr == null) { return; } @@ -221,8 +218,8 @@ private void PlayerHooksOnPlayerLogout(PlayerLogoutEventArgs e) var result = new RestObject { { "type", "chat" }, - { "chat", string.Format(Config.config.ExitServerFormat, plr.Name, plr.Group.Name, plr.Group.Prefix, EconomicSupport.IsSupported("GetLevelName") ? EconomicSupport.GetLevelName(plr.Account.Name).Replace("职业:", "") : "不支持") }, //[Server]玩家名:内容" 额外 {2}:玩家组名 {3}:玩家聊天前缀 {4}:Ec职业名 - { "group", Config.config.GroupNumber } + { "chat", string.Format(Config.Settings.ExitServerFormat, plr.Name, plr.Group.Name, plr.Group.Prefix, EconomicSupport.IsSupported("GetLevelName") ? EconomicSupport.GetLevelName(plr.Account.Name).Replace("职业:", "") : "不支持") }, //[Server]玩家名:内容" 额外 {2}:玩家组名 {3}:玩家聊天前缀 {4}:Ec职业名 + { "group", Config.Settings.GroupNumber } }; _ = MessageHandle.SendDateAsync(JsonConvert.SerializeObject(result)); } @@ -269,9 +266,9 @@ void ShowHelpText() plr.SendInfoMessage($"[CaiBot信息]\n" + $"插件版本: v{VersionNum}\n" + $"WebSocket状态: {WebSocket.State}\n" + - $"绑定QQ群: {(Config.config.GroupNumber == 0L ? "未绑定|未连接" : Config.config.GroupNumber)}\n" + + $"绑定QQ群: {(Config.Settings.GroupNumber == 0L ? "未绑定|未连接" : Config.Settings.GroupNumber)}\n" + $"本地模式: {LocalMode}\n" + - $"绑定状态: {Config.config.Token != ""}\n" + + $"绑定状态: {Config.Settings.Token != ""}\n" + $"Debug模式: {DebugMode}\n" + $"Economic API支持: {EconomicSupport.GetCoinsSupport}\n" + $"Economic RPG支持: {EconomicSupport.GetLevelNameSupport}\n" + @@ -285,7 +282,7 @@ void ShowHelpText() break; case "验证码": case "code": - if (!string.IsNullOrEmpty(Config.config.Token)) + if (!string.IsNullOrEmpty(Config.Settings.Token)) { plr.SendInfoMessage("[CaiBot]服务器已绑定无法生成验证码!"); return; @@ -319,7 +316,7 @@ private void OnBanInsert(object? sender, BanEventArgs e) private void GenCode(EventArgs args) { EconomicSupport.Init(); - if (!string.IsNullOrEmpty(Config.config.Token)) + if (!string.IsNullOrEmpty(Config.Settings.Token)) { return; } @@ -327,37 +324,7 @@ private void GenCode(EventArgs args) InitCode = new Random().Next(10000000, 99999999); TShock.Log.ConsoleError($"[CaiBot]您的服务器绑定码为: {InitCode}"); } - - private bool MessageBuffer_InvokeGetData(Hooks.MessageBuffer.orig_InvokeGetData orig, - MessageBuffer instance, ref byte packetId, ref int readOffset, ref int start, ref int length, - ref int messageType, int maxPackets) - { - if (messageType == 217) - { - if (!string.IsNullOrEmpty(Config.config.Token)) - { - NetMessage.SendData(2, instance.whoAmI, -1, NetworkText.FromFormattable("exist")); - TShock.Log.ConsoleInfo("[CaiAPI]试图绑定已绑定服务器!"); - return false; - } - - instance.ResetReader(); - instance.reader.BaseStream.Position = start + 1; - var data = instance.reader.ReadString(); - var token = Guid.NewGuid().ToString(); - if (data == InitCode.ToString()) - { - NetMessage.SendData(2, instance.whoAmI, -1, NetworkText.FromFormattable(token)); - Config.config.Token = token; - Config.config.Write(); - TShock.Log.ConsoleInfo("[CaiAPI]主动绑定成功!"); - return false; - } - - NetMessage.SendData(2, instance.whoAmI, -1, NetworkText.FromFormattable("code")); - } - return orig(instance, ref packetId, ref readOffset, ref start, ref length, ref messageType, maxPackets); - } + #region 加载前置 diff --git a/src/CaiBot/README.md b/src/CaiBot/README.md index 168b7543a..e6e8af571 100644 --- a/src/CaiBot/README.md +++ b/src/CaiBot/README.md @@ -25,6 +25,7 @@ ## 更新日志 ``` +v2024.12.22.1优化在线查询,世界未加载时不再返回空世界名,移除主动绑定 v2024.12.20.1 修复使用外挂绕过登录的问题,UUID和IP合并以提高UUID登录安全性 v2024.12.1.2 调整配置文件配置项的顺序,整理代码 v2024.12.1.1 新增同步聊天的功能,修复热重载无法断开Websocket