diff --git a/AuroraNative/API/Api.cs b/AuroraNative/API/Api.cs index db79fd6..420c42f 100644 --- a/AuroraNative/API/Api.cs +++ b/AuroraNative/API/Api.cs @@ -1,9 +1,11 @@ using AuroraNative.EventArgs; +using AuroraNative.Exceptions; using AuroraNative.WebSockets; using Microsoft.Extensions.Caching.Memory; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; @@ -43,7 +45,14 @@ namespace AuroraNative /// WebSocket句柄 private Api(BaseWebSocket WebSocket) { - this.WebSocket = WebSocket; + if (WebSocket != null) + { + this.WebSocket = WebSocket; + } + else + { + throw new WebSocketException(-1, "传入的WebSocket不可为空"); + } } #endregion @@ -101,7 +110,7 @@ namespace AuroraNative { "group_id", GroupID }, { "messages", Message } }; - + //TODO 需要做CQ码转换 SendCallVoid(new BaseAPI("send_group_forward_msg", Params, "SendGroupForwardMessage:" + Utils.NowTimeSteamp())); } @@ -129,7 +138,7 @@ namespace AuroraNative case "group": Params.Add("group_id", GroupID); break; - default: + case null: if (QID != 0) { Params.Add("user_id", QID); @@ -139,6 +148,8 @@ namespace AuroraNative Params.Add("group_id", GroupID); } break; + default: + throw new Exceptions.JsonException(-1, "传入的参数不符合预期"); } return await SendCallMessageID(new BaseAPI("send_msg", Params, "SendMsg:" + Utils.NowTimeSteamp())); @@ -158,9 +169,18 @@ namespace AuroraNative /// /// 消息ID /// 错误返回null,成功返回JObject - public async Task GetMsg(string MessageID) + public async Task> GetMsg(string MessageID) { - return await SendCallObject(new BaseAPI("get_msg", new JObject() { { "message_id", MessageID } }, "GetMsg:" + Utils.NowTimeSteamp())); + JObject Json = await SendCallObject(new BaseAPI("get_msg", new JObject() { { "message_id", MessageID } }, "GetMsg:" + Utils.NowTimeSteamp())); + + return new Dictionary() { + {"MessageID",Json.Value("message_id")}, + {"RealID",Json.Value("real_id")}, + {"Sender",Json.Value("sender")}, + {"Time",Json.Value("time")}, + {"Message",Json.Value("message")}, + {"RawMessage",Json.Value("raw_message")} + }; } /// @@ -170,6 +190,7 @@ namespace AuroraNative /// 错误返回null,成功返回JObject public async Task GetForwardMsg(string MessageID) { + //TODO 等转发合并消息做完后需要修改这个方法的返回类型 return await SendCallObject(new BaseAPI("get_forward_msg", new JObject() { { "message_id", MessageID } }, "GetForwardMsg:" + Utils.NowTimeSteamp())); } @@ -887,9 +908,17 @@ namespace AuroraNative internal static Api Create(BaseWebSocket WebSocket) { - Api api = new Api(WebSocket); - Cache.Set($"API{AppDomain.CurrentDomain.Id}", api); - return api; + try + { + Api api = new Api(WebSocket); + Cache.Set($"API{AppDomain.CurrentDomain.Id}", api); + return api; + } + catch (WebSocketException e) + { + Logger.Warning("警告,传入的WebSocket有误。错误代码: " + e.ErrorCode); + } + return null; } internal static void Destroy() diff --git a/AuroraNative/AuroraNative.csproj b/AuroraNative/AuroraNative.csproj index e84de38..3182789 100644 --- a/AuroraNative/AuroraNative.csproj +++ b/AuroraNative/AuroraNative.csproj @@ -40,9 +40,14 @@ - + + + + + + diff --git a/AuroraNative/AuroraNative.xml b/AuroraNative/AuroraNative.xml index 5f3e9ad..cc8acbe 100644 --- a/AuroraNative/AuroraNative.xml +++ b/AuroraNative/AuroraNative.xml @@ -43,7 +43,7 @@ 是否转义默认:false 返回消息ID,错误返回-1 - + 转发合并消息 - 群 diff --git a/AuroraNative/Utils/EnumDescriptionConverter.cs b/AuroraNative/Utils/EnumDescriptionConverter.cs new file mode 100644 index 0000000..db13b5c --- /dev/null +++ b/AuroraNative/Utils/EnumDescriptionConverter.cs @@ -0,0 +1,61 @@ +using AuroraNative.EventArgs; +using Newtonsoft.Json; +using System; +using System.ComponentModel; +using System.Linq; +using System.Reflection; + +namespace AuroraNative +{ + /// + /// Enum和Description特性互转 转换器 + /// + internal class EnumDescriptionConverter : JsonConverter + { + /// + /// 当属性的值为枚举类型时才使用转换器 + /// + /// 目标类型 + /// 返回布尔值 + public override bool CanConvert(Type objectType) => objectType == typeof(Enum); + + /// + /// 获取枚举的描述值 + /// + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + if (string.IsNullOrEmpty(value.ToString())) + { + writer.WriteValue(""); + return; + } + + FieldInfo fieldInfo = value.GetType().GetField(value.ToString()); + if (fieldInfo == null) + { + writer.WriteValue(""); + return; + } + + DescriptionAttribute[] attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false); + writer.WriteValue(attributes.Length > 0 ? attributes[0].Description : ""); + } + + /// + /// 通过Description获取枚举值 + /// + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + foreach (FieldInfo field in objectType.GetFields()) + { + object[] objects = field.GetCustomAttributes(typeof(DescriptionAttribute), false); + if (objects.Any(item => (item as DescriptionAttribute)?.Description == reader.Value?.ToString())) + { + return Convert.ChangeType(field.GetValue(-1), objectType); + } + } + + return CQCodeType.Unknown; + } + } +} diff --git a/AuroraNative/Event.cs b/AuroraNative/Utils/Event.cs similarity index 99% rename from AuroraNative/Event.cs rename to AuroraNative/Utils/Event.cs index f016728..186fe40 100644 --- a/AuroraNative/Event.cs +++ b/AuroraNative/Utils/Event.cs @@ -1,5 +1,4 @@ using AuroraNative.EventArgs; -using AuroraNative.WebSockets; using Newtonsoft.Json.Linq; namespace AuroraNative diff --git a/AuroraNative/Logger.cs b/AuroraNative/Utils/Logger.cs similarity index 93% rename from AuroraNative/Logger.cs rename to AuroraNative/Utils/Logger.cs index 04f7902..6460410 100644 --- a/AuroraNative/Logger.cs +++ b/AuroraNative/Utils/Logger.cs @@ -23,8 +23,10 @@ namespace AuroraNative /// /// 要输出的信息 /// 输出的方法名,可选传入 - public static void Debug(string Message, string MethodName = null) { - if (LogLevel <= LogLevel.Debug) { + public static void Debug(string Message, string MethodName = null) + { + if (LogLevel <= LogLevel.Debug) + { Output(Message, ConsoleColor.Gray, LogLevel.Debug, MethodName); } } @@ -72,12 +74,15 @@ namespace AuroraNative #region --私有函数-- - internal static void Output(string Message, ConsoleColor Color,LogLevel Level, string MethodName) { + internal static void Output(string Message, ConsoleColor Color, LogLevel Level, string MethodName) + { Console.ForegroundColor = Color; - if (MethodName != null) { + if (MethodName != null) + { Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss fff") + $" [{Level}]" + $" [{MethodName}] " + Message); } - else { + else + { Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss") + $" [{Level}] " + Message); } Console.ForegroundColor = ConsoleColor.White; @@ -89,7 +94,8 @@ namespace AuroraNative /// /// 表示日志信息等级的枚举 /// - public enum LogLevel { + public enum LogLevel + { /// /// 表示输出日志的等级是 "调试" 级别 /// diff --git a/AuroraNative/Utils.cs b/AuroraNative/Utils/Utils.cs similarity index 90% rename from AuroraNative/Utils.cs rename to AuroraNative/Utils/Utils.cs index 3bbf6d0..b16bef7 100644 --- a/AuroraNative/Utils.cs +++ b/AuroraNative/Utils/Utils.cs @@ -13,21 +13,21 @@ namespace AuroraNative /// 通过 枚举Description 转为枚举 /// /// 枚举 - /// 需要转换的Description + /// 需要转换的Description /// 返回该枚举 - public static T GetEnumByDescription(string description) where T : Enum + public static T GetEnumByDescription(string Description) where T : Enum { System.Reflection.FieldInfo[] fields = typeof(T).GetFields(); foreach (System.Reflection.FieldInfo field in fields) { object[] objs = field.GetCustomAttributes(typeof(DescriptionAttribute), false); - if (objs.Length > 0 && (objs[0] as DescriptionAttribute).Description == description) + if (objs.Length > 0 && (objs[0] as DescriptionAttribute).Description == Description) { return (T)field.GetValue(null); } } - throw new ArgumentException(string.Format("{0} 未能找到对应的枚举.", description), "Description"); + throw new ArgumentException(string.Format("{0} 未能找到对应的枚举.", Description), nameof(Description)); } /// diff --git a/AuroraNative/WebSockets/BaseWebSocket.cs b/AuroraNative/WebSockets/BaseWebSocket.cs index 9fa23c7..b87626b 100644 --- a/AuroraNative/WebSockets/BaseWebSocket.cs +++ b/AuroraNative/WebSockets/BaseWebSocket.cs @@ -32,7 +32,14 @@ namespace AuroraNative.WebSockets /// 传输Json格式的文本 public void Send(BaseAPI Json) { - WebSocket.SendAsync(new ArraySegment(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(Json, Formatting.None))), WebSocketMessageType.Text, true, CancellationToken.None); + try + { + WebSocket.SendAsync(new ArraySegment(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(Json, Formatting.None))), WebSocketMessageType.Text, true, CancellationToken.None); + } + catch (Exception e) + { + Logger.Error("调用API出现未知错误!\n" + e.Message, $"{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}"); + } } internal async Task GetEventAsync() diff --git a/AuroraNative/WebSockets/Client.cs b/AuroraNative/WebSockets/Client.cs index 6517a21..948bc90 100644 --- a/AuroraNative/WebSockets/Client.cs +++ b/AuroraNative/WebSockets/Client.cs @@ -50,7 +50,8 @@ namespace AuroraNative.WebSockets public bool Create() { Logger.Debug("正向WebSocket已创建,准备连接...", $"{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}"); - for (int i = 1;i < 4;i++) { + for (int i = 1; i < 4; i++) + { try { WebSocket = new ClientWebSocket(); @@ -62,6 +63,9 @@ namespace AuroraNative.WebSockets if (WebSocket.State == WebSocketState.Open) { Logger.Info("已连接至 go-cqhttp 服务器!"); + Logger.Debug("防止由于go-cqhttp未初始化异常,连接后需等待2秒..."); + Thread.Sleep(2000); + Logger.Debug("go-cqhttp 初始化完毕!"); Task.Run(Feedback); Api.Create(this); return true; @@ -91,7 +95,8 @@ namespace AuroraNative.WebSockets Api.Destroy(); Logger.Info("已销毁正向WebSocket"); } - catch(Exception e) { + catch (Exception e) + { Logger.Error("销毁正向WebSocket失败!\n" + e.Message, $"{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}"); } } diff --git a/AuroraNative/WebSockets/Server.cs b/AuroraNative/WebSockets/Server.cs index 3fbb4f2..9e8fc97 100644 --- a/AuroraNative/WebSockets/Server.cs +++ b/AuroraNative/WebSockets/Server.cs @@ -61,11 +61,13 @@ namespace AuroraNative.WebSockets Listener.Start(); Logger.Info("开始监听来自 go-cqhttp 客户端的连接..."); Task.Run(Feedback); - while (!IsConnect) { + while (!IsConnect) + { Thread.Sleep(100); } } - catch(HttpListenerException) { + catch (HttpListenerException) + { Logger.Error("无法启动监听服务器,请确保使用管理员权限运行。否则无法监听!", $"{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}"); Console.ReadKey(); Environment.Exit(0); @@ -78,13 +80,16 @@ namespace AuroraNative.WebSockets public void Dispose() { Logger.Debug($"准备销毁反向WebSocket...", $"{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}"); - try { + try + { Listener.Stop(); WebSocket.Dispose(); WebSocket.Abort(); Api.Destroy(); Logger.Info("已销毁反向WebSocket"); - } catch (Exception e) { + } + catch (Exception e) + { Logger.Error("销毁反向WebSocket失败!\n" + e.Message, $"{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}"); } } @@ -97,19 +102,29 @@ namespace AuroraNative.WebSockets { while (true) { - HttpListenerContext Context = await Listener.GetContextAsync(); - if (Context.Request.IsWebSocketRequest) + try { - Logger.Info("收到来自 go-cqhttp 客户端的连接!连接已建立!"); - HttpListenerWebSocketContext SocketContext = await Context.AcceptWebSocketAsync(null); - WebSocket = SocketContext.WebSocket; - IsConnect = true; - Api.Create(this); - while (WebSocket.State == WebSocketState.Open) + HttpListenerContext Context = await Listener.GetContextAsync(); + if (Context.Request.IsWebSocketRequest) { - await GetEventAsync(); + Logger.Info("收到来自 go-cqhttp 客户端的连接!连接已建立!"); + HttpListenerWebSocketContext SocketContext = await Context.AcceptWebSocketAsync(null); + WebSocket = SocketContext.WebSocket; + Logger.Debug("防止由于go-cqhttp未初始化异常,连接后需等待2秒..."); + Thread.Sleep(2000); + Logger.Debug("go-cqhttp 初始化完毕!"); + IsConnect = true; + Api.Create(this); + while (WebSocket.State == WebSocketState.Open) + { + await GetEventAsync(); + } } } + catch (Exception e) + { + Logger.Error("反向WebSocket出现未知错误!\n" + e.Message, $"{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}"); + } } } diff --git a/README.md b/README.md index 35678b2..76290bf 100644 --- a/README.md +++ b/README.md @@ -75,4 +75,4 @@ ### 使用到的开源库 -[Newtonsoft.Json](https://www.newtonsoft.com/json) \ No newline at end of file +[Newtonsoft.Json](https://www.newtonsoft.com/json) | [Microsoft.Extensions.Caching.Memory](https://www.nuget.org/packages/Microsoft.Extensions.Caching.Memory/5.0.0) \ No newline at end of file