From 1a5445634afbfe4b29d53b5cba975f12753b9d4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=82=A0=E9=9D=99=E8=90=9D=E8=8E=89?= Date: Thu, 11 Mar 2021 13:04:11 +0800 Subject: [PATCH 1/6] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ac2b4cc..e148241 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ - + From 3d032bb22eb8cad432e6958142a1e1327f9b120a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=82=A0=E9=9D=99=E8=90=9D=E8=8E=89?= Date: Thu, 11 Mar 2021 22:50:41 +0800 Subject: [PATCH 2/6] 03/11 Last Update --- AuroraNative/README.md | 0 AuroraNative/WebSockets/Client.cs | 16 ++++++++++------ 2 files changed, 10 insertions(+), 6 deletions(-) delete mode 100644 AuroraNative/README.md diff --git a/AuroraNative/README.md b/AuroraNative/README.md deleted file mode 100644 index e69de29..0000000 diff --git a/AuroraNative/WebSockets/Client.cs b/AuroraNative/WebSockets/Client.cs index 812510f..e7f1250 100644 --- a/AuroraNative/WebSockets/Client.cs +++ b/AuroraNative/WebSockets/Client.cs @@ -41,15 +41,19 @@ static Client() /// /// 创建并连接到WebSocket服务器 /// - public void Create() + public bool Create() { WebSocket = new ClientWebSocket(); - Task Connect = ((ClientWebSocket)WebSocket).ConnectAsync(new Uri("ws://" + Host + "/"), CancellationToken.None); - Connect.Wait(); - if (WebSocket.State == WebSocketState.Open) - { - Task.Run(Feedback); + if (WebSocket is ClientWebSocket socket) { + Task Connect = socket.ConnectAsync(new Uri("ws://" + Host + "/"), CancellationToken.None); + Connect.Wait(); + if (WebSocket.State == WebSocketState.Open) + { + Task.Run(Feedback); + return true; + } } + return false; } /// From c6bb234e5287a62549a832fa0e944b11fd88b29b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=82=A0=E9=9D=99=E8=90=9D=E8=8E=89?= Date: Fri, 12 Mar 2021 23:21:30 +0800 Subject: [PATCH 3/6] 03/12 Last Update --- AuroraNative/API/Api.cs | 34 ++++++- AuroraNative/AuroraNative.csproj | 7 +- AuroraNative/AuroraNative.xml | 90 ++++++++++++++++--- AuroraNative/Event.cs | 1 + AuroraNative/Logger.cs | 110 +++++++++++++++++++++++ AuroraNative/WebSockets/BaseWebSocket.cs | 9 +- AuroraNative/WebSockets/Client.cs | 49 ++++++++-- AuroraNative/WebSockets/Server.cs | 42 +++++++-- README.md | 10 ++- 9 files changed, 307 insertions(+), 45 deletions(-) create mode 100644 AuroraNative/Logger.cs diff --git a/AuroraNative/API/Api.cs b/AuroraNative/API/Api.cs index 6f57e84..db79fd6 100644 --- a/AuroraNative/API/Api.cs +++ b/AuroraNative/API/Api.cs @@ -1,7 +1,9 @@ using AuroraNative.EventArgs; using AuroraNative.WebSockets; +using Microsoft.Extensions.Caching.Memory; using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using System; using System.Threading; using System.Threading.Tasks; @@ -10,7 +12,7 @@ namespace AuroraNative /// /// API 类 /// - public class Api + public sealed class Api { #region --变量-- @@ -18,18 +20,28 @@ public class Api /// 任务队列 /// internal static JObject TaskList = new JObject(); + internal static MemoryCache Cache = new MemoryCache(new MemoryCacheOptions()); private readonly BaseWebSocket WebSocket; #endregion + #region --属性-- + + /// + /// 获取API实例 + /// + public static Api CurrentApi => (Api)Cache.Get($"API{AppDomain.CurrentDomain.Id}"); + + #endregion + #region --构造函数-- /// /// 构建函数 /// /// WebSocket句柄 - public Api(BaseWebSocket WebSocket) + private Api(BaseWebSocket WebSocket) { this.WebSocket = WebSocket; } @@ -856,7 +868,8 @@ private static JObject FeedbackObject(string UniqueCode) return null; } - private static JObject GetFeedback(string UniqueCode) { + private static JObject GetFeedback(string UniqueCode) + { JObject FBJson = new JObject(); do @@ -868,9 +881,22 @@ private static JObject GetFeedback(string UniqueCode) { break; } Thread.Sleep(10); - }while (FBJson["status"] == null); + } while (FBJson["status"] == null); return FBJson; } + + internal static Api Create(BaseWebSocket WebSocket) + { + Api api = new Api(WebSocket); + Cache.Set($"API{AppDomain.CurrentDomain.Id}", api); + return api; + } + + internal static void Destroy() + { + Cache.Remove($"API{AppDomain.CurrentDomain.Id}"); + } + #endregion } } diff --git a/AuroraNative/AuroraNative.csproj b/AuroraNative/AuroraNative.csproj index 20db5b0..e84de38 100644 --- a/AuroraNative/AuroraNative.csproj +++ b/AuroraNative/AuroraNative.csproj @@ -15,13 +15,13 @@ false false true - 0.1.0.0311 - 0.1.0.0311 + 0.2.0.0312 + 0.2.0.0312 Icon.png false AuroraNative AuroraNative - 0.1.0-alpha + 0.2.0-alpha true @@ -41,6 +41,7 @@ + diff --git a/AuroraNative/AuroraNative.xml b/AuroraNative/AuroraNative.xml index 7163e89..5f3e9ad 100644 --- a/AuroraNative/AuroraNative.xml +++ b/AuroraNative/AuroraNative.xml @@ -14,6 +14,11 @@ 任务队列 + + + 获取API实例 + + 构建函数 @@ -1784,6 +1789,69 @@ 异常 类 -- 关于WebSocket异常 + + + 彩色日志输出类 + + + + + 日志级别设定默认 Info + + + + + 输出一个等级为 调试 的信息 + + 要输出的信息 + 输出的方法名,可选传入 + + + + 输出一个等级为 信息 的信息 + + 要输出的信息 + 输出的方法名,可选传入 + + + + 输出一个等级为 警告 的信息 + + 要输出的信息 + 输出的方法名,可选传入 + + + + 输出一个等级为 错误 的信息 + + 要输出的信息 + 输出的方法名,可选传入 + + + + 表示日志信息等级的枚举 + + + + + 表示输出日志的等级是 "调试" 级别 + + + + + 表示输出日志的等级是 "信息" 级别 + + + + + 表示输出日志的等级是 "警告" 级别 + + + + + 表示输出日志的等级是 "错误" 级别 + + 通用方法 类 @@ -1815,16 +1883,6 @@ WebSocket 基础类 - - - Websocket句柄 - - - - - 事件钩子 - - 发送数据到服务端/客户端 @@ -1842,6 +1900,12 @@ WebSocket服务端地址请记得带端口号 + + + 创建一个 实例 + + 重写后的事件类实例 + 创建并连接到WebSocket服务器 @@ -1863,6 +1927,12 @@ WebSocket监听端口 + + + 创建一个 实例 + + 重写后的事件类实例 + 创建WebSocket服务器并监听端口 diff --git a/AuroraNative/Event.cs b/AuroraNative/Event.cs index 186fe40..f016728 100644 --- a/AuroraNative/Event.cs +++ b/AuroraNative/Event.cs @@ -1,4 +1,5 @@ using AuroraNative.EventArgs; +using AuroraNative.WebSockets; using Newtonsoft.Json.Linq; namespace AuroraNative diff --git a/AuroraNative/Logger.cs b/AuroraNative/Logger.cs new file mode 100644 index 0000000..04f7902 --- /dev/null +++ b/AuroraNative/Logger.cs @@ -0,0 +1,110 @@ +using System; + +namespace AuroraNative +{ + /// + /// 彩色日志输出类 + /// + public static class Logger + { + #region --属性-- + + /// + /// 日志级别设定默认 Info + /// + public static LogLevel LogLevel = LogLevel.Info; + + #endregion + + #region --公开函数-- + + /// + /// 输出一个等级为 调试 的信息 + /// + /// 要输出的信息 + /// 输出的方法名,可选传入 + public static void Debug(string Message, string MethodName = null) { + if (LogLevel <= LogLevel.Debug) { + Output(Message, ConsoleColor.Gray, LogLevel.Debug, MethodName); + } + } + + /// + /// 输出一个等级为 信息 的信息 + /// + /// 要输出的信息 + /// 输出的方法名,可选传入 + public static void Info(string Message, string MethodName = null) + { + if (LogLevel <= LogLevel.Info) + { + Output(Message, ConsoleColor.White, LogLevel.Info, MethodName); + } + } + + /// + /// 输出一个等级为 警告 的信息 + /// + /// 要输出的信息 + /// 输出的方法名,可选传入 + public static void Warning(string Message, string MethodName = null) + { + if (LogLevel <= LogLevel.Warning) + { + Output(Message, ConsoleColor.Yellow, LogLevel.Warning, MethodName); + } + } + + /// + /// 输出一个等级为 错误 的信息 + /// + /// 要输出的信息 + /// 输出的方法名,可选传入 + public static void Error(string Message, string MethodName = null) + { + if (LogLevel <= LogLevel.Error) + { + Output(Message, ConsoleColor.Red, LogLevel.Error, MethodName); + } + } + + #endregion + + #region --私有函数-- + + internal static void Output(string Message, ConsoleColor Color,LogLevel Level, string MethodName) { + Console.ForegroundColor = Color; + if (MethodName != null) { + Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss fff") + $" [{Level}]" + $" [{MethodName}] " + Message); + } + else { + Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss") + $" [{Level}] " + Message); + } + Console.ForegroundColor = ConsoleColor.White; + } + + #endregion + } + + /// + /// 表示日志信息等级的枚举 + /// + public enum LogLevel { + /// + /// 表示输出日志的等级是 "调试" 级别 + /// + Debug = 0, + /// + /// 表示输出日志的等级是 "信息" 级别 + /// + Info = 1, + /// + /// 表示输出日志的等级是 "警告" 级别 + /// + Warning = 2, + /// + /// 表示输出日志的等级是 "错误" 级别 + /// + Error = 3 + } +} diff --git a/AuroraNative/WebSockets/BaseWebSocket.cs b/AuroraNative/WebSockets/BaseWebSocket.cs index 4c14c56..9fa23c7 100644 --- a/AuroraNative/WebSockets/BaseWebSocket.cs +++ b/AuroraNative/WebSockets/BaseWebSocket.cs @@ -17,15 +17,8 @@ public abstract class BaseWebSocket { #region --变量-- - /// - /// Websocket句柄 - /// internal WebSocket WebSocket; - /// - /// 事件钩子 - /// - public Event EventHook; - + internal Event EventHook; internal JObject Json; internal static Type[] AttributeTypes; diff --git a/AuroraNative/WebSockets/Client.cs b/AuroraNative/WebSockets/Client.cs index e7f1250..6517a21 100644 --- a/AuroraNative/WebSockets/Client.cs +++ b/AuroraNative/WebSockets/Client.cs @@ -34,6 +34,12 @@ static Client() AttributeTypes = Assembly.GetExecutingAssembly().GetTypes().Where(p => p.IsAbstract == false && p.IsInterface == false && typeof(Attribute).IsAssignableFrom(p)).ToArray(); } + /// + /// 创建一个 实例 + /// + /// 重写后的事件类实例 + public Client(Event Event) => EventHook = Event; + #endregion #region --公开函数-- @@ -43,16 +49,32 @@ static Client() /// public bool Create() { - WebSocket = new ClientWebSocket(); - if (WebSocket is ClientWebSocket socket) { - Task Connect = socket.ConnectAsync(new Uri("ws://" + Host + "/"), CancellationToken.None); - Connect.Wait(); - if (WebSocket.State == WebSocketState.Open) + Logger.Debug("正向WebSocket已创建,准备连接...", $"{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}"); + for (int i = 1;i < 4;i++) { + try + { + WebSocket = new ClientWebSocket(); + if (WebSocket is ClientWebSocket socket) + { + Logger.Debug($"准备连接至IP:{Host}", $"{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}"); + Task Connect = socket.ConnectAsync(new Uri("ws://" + Host + "/"), CancellationToken.None); + Connect.Wait(); + if (WebSocket.State == WebSocketState.Open) + { + Logger.Info("已连接至 go-cqhttp 服务器!"); + Task.Run(Feedback); + Api.Create(this); + return true; + } + } + } + catch (AggregateException) { - Task.Run(Feedback); - return true; + Logger.Warning($"连接到 go-cqhttp 服务器失败!五秒后重试(重试次数:{i})...", $"{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}"); + Thread.Sleep(5000); } } + Logger.Error("连接到 go-cqhttp 服务器失败!请检查IP是否正确(需要携带端口号)或确认服务器是否启动和初始化完毕!", $"{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}"); return false; } @@ -61,8 +83,17 @@ public bool Create() /// public void Dispose() { - WebSocket.Dispose(); - WebSocket.Abort(); + Logger.Debug($"准备销毁正向WebSocket...", $"{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}"); + try + { + WebSocket.Dispose(); + WebSocket.Abort(); + Api.Destroy(); + Logger.Info("已销毁正向WebSocket"); + } + catch(Exception e) { + Logger.Error("销毁正向WebSocket失败!\n" + e.Message, $"{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}"); + } } #endregion diff --git a/AuroraNative/WebSockets/Server.cs b/AuroraNative/WebSockets/Server.cs index 87f1f77..3fbb4f2 100644 --- a/AuroraNative/WebSockets/Server.cs +++ b/AuroraNative/WebSockets/Server.cs @@ -38,6 +38,12 @@ static Server() AttributeTypes = Assembly.GetExecutingAssembly().GetTypes().Where(p => p.IsAbstract == false && p.IsInterface == false && typeof(Attribute).IsAssignableFrom(p)).ToArray(); } + /// + /// 创建一个 实例 + /// + /// 重写后的事件类实例 + public Server(Event Event) => EventHook = Event; + #endregion #region --公开函数-- @@ -47,13 +53,22 @@ static Server() /// public void Create() { - Listener = new HttpListener(); - Listener.Prefixes.Add("http://*:" + Port + "/"); - Listener.Start(); - Task.Run(Feedback); - while (!IsConnect) + try { - Thread.Sleep(100); + Logger.Debug("反向WebSocket已创建,准备监听...", $"{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}"); + Listener = new HttpListener(); + Listener.Prefixes.Add("http://*:" + Port + "/"); + Listener.Start(); + Logger.Info("开始监听来自 go-cqhttp 客户端的连接..."); + Task.Run(Feedback); + while (!IsConnect) { + Thread.Sleep(100); + } + } + catch(HttpListenerException) { + Logger.Error("无法启动监听服务器,请确保使用管理员权限运行。否则无法监听!", $"{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}"); + Console.ReadKey(); + Environment.Exit(0); } } @@ -62,9 +77,16 @@ public void Create() /// public void Dispose() { - Listener.Stop(); - WebSocket.Dispose(); - WebSocket.Abort(); + Logger.Debug($"准备销毁反向WebSocket...", $"{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}"); + try { + Listener.Stop(); + WebSocket.Dispose(); + WebSocket.Abort(); + Api.Destroy(); + Logger.Info("已销毁反向WebSocket"); + } catch (Exception e) { + Logger.Error("销毁反向WebSocket失败!\n" + e.Message, $"{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}"); + } } #endregion @@ -78,9 +100,11 @@ private async void Feedback() HttpListenerContext Context = await Listener.GetContextAsync(); if (Context.Request.IsWebSocketRequest) { + Logger.Info("收到来自 go-cqhttp 客户端的连接!连接已建立!"); HttpListenerWebSocketContext SocketContext = await Context.AcceptWebSocketAsync(null); WebSocket = SocketContext.WebSocket; IsConnect = true; + Api.Create(this); while (WebSocket.State == WebSocketState.Open) { await GetEventAsync(); diff --git a/README.md b/README.md index e148241..35678b2 100644 --- a/README.md +++ b/README.md @@ -39,9 +39,15 @@ - 优化内部算法或修改类型(如将返回的JObject类型抽象为新自定义类型) - vX.X.X+1 - 重命名/删除/新增 文件/命名空间/API - vX.X+1.X +## 文档 + +开发文档:[点我查看](https://auroranative.mikuy.cn) + +> 开发文档是与框架一起更新的,因此文档也处于快速迭代状态。 + ## 兼容性 -### 接口 +### 通讯方式 - [ ] HTTP API - [ ] 反向 HTTP POST @@ -50,7 +56,7 @@ ## 关于 ISSUE -如果没有大问题请到 Discussions 处提问 +如果没有大问题请到 [Discussions](https://github.com/timi137137/AuroraNative/discussions) 处提问 以下 ISSUE 会被直接关闭 From de4fe14d74afcb2f000c8ef517bc136e0dda478f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=82=A0=E9=9D=99=E8=90=9D=E8=8E=89?= Date: Sat, 13 Mar 2021 22:37:29 +0800 Subject: [PATCH 4/6] 03/13 Last Update --- AuroraNative/API/Api.cs | 45 +++++++++++--- AuroraNative/AuroraNative.csproj | 7 ++- AuroraNative/AuroraNative.xml | 2 +- .../Utils/EnumDescriptionConverter.cs | 61 +++++++++++++++++++ AuroraNative/{ => Utils}/Event.cs | 1 - AuroraNative/{ => Utils}/Logger.cs | 18 ++++-- AuroraNative/{ => Utils}/Utils.cs | 8 +-- AuroraNative/WebSockets/BaseWebSocket.cs | 9 ++- AuroraNative/WebSockets/Client.cs | 9 ++- AuroraNative/WebSockets/Server.cs | 41 +++++++++---- README.md | 2 +- 11 files changed, 165 insertions(+), 38 deletions(-) create mode 100644 AuroraNative/Utils/EnumDescriptionConverter.cs rename AuroraNative/{ => Utils}/Event.cs (99%) rename AuroraNative/{ => Utils}/Logger.cs (93%) rename AuroraNative/{ => Utils}/Utils.cs (90%) 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 @@ public sealed class Api /// 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 @@ public void SendGroupForwardMessage(long GroupID, JArray Message) { "group_id", GroupID }, { "messages", Message } }; - + //TODO 需要做CQ码转换 SendCallVoid(new BaseAPI("send_group_forward_msg", Params, "SendGroupForwardMessage:" + Utils.NowTimeSteamp())); } @@ -129,7 +138,7 @@ public async Task SendMsg(string Message, string MessageType = null, lon case "group": Params.Add("group_id", GroupID); break; - default: + case null: if (QID != 0) { Params.Add("user_id", QID); @@ -139,6 +148,8 @@ public async Task SendMsg(string Message, string MessageType = null, lon 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 @@ public void DeleteMessage(int MessageID) /// /// 消息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 @@ public async Task GetMsg(string MessageID) /// 错误返回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 @@ private static JObject GetFeedback(string UniqueCode) 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 @@ public static class Logger /// /// 要输出的信息 /// 输出的方法名,可选传入 - 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 @@ public static void Error(string Message, string MethodName = null) #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 @@ internal static void Output(string Message, ConsoleColor Color,LogLevel Level, s /// /// 表示日志信息等级的枚举 /// - 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 @@ public class Utils /// 通过 枚举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 @@ public abstract class BaseWebSocket /// 传输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 @@ static Client() 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 @@ public bool Create() 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 @@ public void Dispose() 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 @@ public void Create() 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 @@ public void Create() 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 @@ private async void Feedback() { 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 From f6c1e9f115bf30358014c83ea4bc16175c23284e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=82=A0=E9=9D=99=E8=90=9D=E8=8E=89?= Date: Sun, 14 Mar 2021 20:27:46 +0800 Subject: [PATCH 5/6] 03/14 Last Update --- .gitignore | 3 +- AuroraNative/API/Api.cs | 164 +++++--- AuroraNative/Abstract/Friends.cs | 32 ++ AuroraNative/AuroraNative.xml | 364 ++++++++++-------- AuroraNative/Enum/LogLevel.cs | 29 ++ .../Utils/EnumDescriptionConverter.cs | 61 --- AuroraNative/Utils/Event.cs | 22 +- AuroraNative/Utils/Logger.cs | 42 +- AuroraNative/WebSockets/BaseWebSocket.cs | 20 +- AuroraNative/WebSockets/Client.cs | 52 ++- AuroraNative/WebSockets/Server.cs | 17 +- 11 files changed, 478 insertions(+), 328 deletions(-) create mode 100644 AuroraNative/Abstract/Friends.cs create mode 100644 AuroraNative/Enum/LogLevel.cs delete mode 100644 AuroraNative/Utils/EnumDescriptionConverter.cs diff --git a/.gitignore b/.gitignore index d36957e..12e22ad 100644 --- a/.gitignore +++ b/.gitignore @@ -340,4 +340,5 @@ ASALocalRun/ healthchecksdb DevIcon.* Test -nuget.config \ No newline at end of file +nuget.config +*.cd \ No newline at end of file diff --git a/AuroraNative/API/Api.cs b/AuroraNative/API/Api.cs index 420c42f..1434752 100644 --- a/AuroraNative/API/Api.cs +++ b/AuroraNative/API/Api.cs @@ -62,15 +62,15 @@ private Api(BaseWebSocket WebSocket) /// /// 发送私聊消息 /// - /// 接受者QQ号 + /// 接受者QQ号 /// 信息内容 /// 是否转义默认:false /// 返回消息ID,错误返回-1 - public async Task SendPrivateMessage(long QID, string Message, bool AutoEscape = false) + public async Task SendPrivateMessage(long UserID, string Message, bool AutoEscape = false) { JObject Params = new JObject { - { "user_id", QID }, + { "user_id", UserID }, { "message", Message }, { "auto_escape", AutoEscape } }; @@ -119,11 +119,11 @@ public void SendGroupForwardMessage(long GroupID, JArray Message) /// /// 信息内容 /// 信息类型私聊:private群聊:group - /// QQ号 + /// QQ号 /// 群号 /// 是否转义默认:false /// 错误返回-1,成功返回信息ID - public async Task SendMsg(string Message, string MessageType = null, long QID = 0, long GroupID = 0, bool AutoEscape = false) + public async Task SendMsg(string Message, string MessageType = null, long UserID = 0, long GroupID = 0, bool AutoEscape = false) { JObject Params = new JObject() { { "message", Message}, @@ -133,15 +133,15 @@ public async Task SendMsg(string Message, string MessageType = null, lon switch (MessageType) { case "private": - Params.Add("user_id", QID); + Params.Add("user_id", UserID); break; case "group": Params.Add("group_id", GroupID); break; case null: - if (QID != 0) + if (UserID != 0) { - Params.Add("user_id", QID); + Params.Add("user_id", UserID); } else if (GroupID != 0) { @@ -199,26 +199,33 @@ public async Task GetForwardMsg(string MessageID) /// /// 图片缓存文件名,带不带后缀你喜欢就好 /// 错误返回null,成功返回JObject - public async Task GetImage(string Filename) + public async Task> GetImage(string Filename) { if (!Filename.Contains(".image")) { Filename += ".image"; } - return await SendCallObject(new BaseAPI("get_image", new JObject() { { "file", Filename } }, "GetImage:" + Utils.NowTimeSteamp())); + + JObject Json = await SendCallObject(new BaseAPI("get_image", new JObject() { { "file", Filename } }, "GetImage:" + Utils.NowTimeSteamp())); + + return new Dictionary() { + {"Size",Json.Value("size")}, + {"FileName",Json.Value("filename")}, + {"Url",Json.Value("url")} + }; } /// /// 群组踢人 /// /// 群号 - /// QQ号 + /// QQ号 /// 是否自动拒绝此人加群申请默认:false - public void SetGroupKick(long GroupID, long QID, bool RejectAddRequest = false) + public void SetGroupKick(long GroupID, long UserID, bool RejectAddRequest = false) { JObject Params = new JObject { - { "user_id", QID }, + { "user_id", UserID }, { "group_id", GroupID }, { "reject_add_request", RejectAddRequest } }; @@ -230,13 +237,13 @@ public void SetGroupKick(long GroupID, long QID, bool RejectAddRequest = false) /// 群组单人禁言 /// /// 群号 - /// QQ号 + /// QQ号 /// 禁言时间,单位秒默认:30分钟(1800秒) - public void SetGroupBan(long GroupID, long QID, int Duration = 1800) + public void SetGroupBan(long GroupID, long UserID, int Duration = 1800) { JObject Params = new JObject { - { "user_id", QID }, + { "user_id", UserID }, { "group_id", GroupID }, { "duration", Duration } }; @@ -291,13 +298,13 @@ public void SetGroupWholeBan(long GroupID, bool Enable = true) /// 设置群管理员 /// /// 群号 - /// QQ号 + /// QQ号 /// 是否设置为管理员默认:true - public void SetGroupAdmin(long GroupID, long QID, bool Enable = true) + public void SetGroupAdmin(long GroupID, long UserID, bool Enable = true) { JObject Params = new JObject { - { "user_id", QID }, + { "user_id", UserID }, { "group_id", GroupID }, { "enable", Enable } }; @@ -309,13 +316,13 @@ public void SetGroupAdmin(long GroupID, long QID, bool Enable = true) /// 设置群名片 /// /// 群号 - /// QQ号 + /// QQ号 /// 群名片内容默认:null(删除群名片) - public void SetGroupCard(long GroupID, long QID, string Card = null) + public void SetGroupCard(long GroupID, long UserID, string Card = null) { JObject Params = new JObject { - { "user_id", QID }, + { "user_id", UserID }, { "group_id", GroupID }, { "card", Card } }; @@ -359,14 +366,14 @@ public void SetGroupLeave(long GroupID, bool IsDismiss = false) /// 设置群组专属头衔 /// /// 群号 - /// QQ号 + /// QQ号 /// 群名片内容默认:null(删除群名片) /// 专属头衔有效期, 单位秒, 不过此项似乎没有效果, 可能是只有某些特殊的时间长度有效, 有待测试默认:-1(永久) - public void SetGroupSpecialTitle(long GroupID, long QID, string SpecialTitle = null, int Duration = -1) + public void SetGroupSpecialTitle(long GroupID, long UserID, string SpecialTitle = null, int Duration = -1) { JObject Params = new JObject { - { "user_id", QID }, + { "user_id", UserID }, { "group_id", GroupID }, { "duration", Duration }, { "special_title", SpecialTitle } @@ -417,35 +424,48 @@ public void SetGroupAddRequest(string Flag, string SubType, bool Approve = true, /// 获取登录号信息 /// /// 错误返回null,成功返回JObject - public async Task GetLoginInfo() + public async Task> GetLoginInfo() { - return await SendCallObject(new BaseAPI("get_login_info", null, "GetLoginInfo:" + Utils.NowTimeSteamp())); + JObject Json = await SendCallObject(new BaseAPI("get_login_info", null, "GetLoginInfo:" + Utils.NowTimeSteamp())); + + return new Dictionary() { + {"UserID",Json.Value("user_id")}, + {"NickName",Json.Value("nickname")} + }; } /// /// 获取陌生人信息 /// - /// QQ号 + /// QQ号 /// 是否使用缓存,使用缓存响应快但是可能更新不及时默认:false /// 错误返回null,成功返回JObject - public async Task GetStrangerInfo(long QID, bool Cache = false) + public async Task> GetStrangerInfo(long UserID, bool Cache = false) { JObject Params = new JObject { - { "user_id", QID }, + { "user_id", UserID }, { "no_cache ", Cache } }; - return await SendCallObject(new BaseAPI("get_stranger_info", Params, "GetStrangerInfo:" + Utils.NowTimeSteamp())); + JObject Json = await SendCallObject(new BaseAPI("get_stranger_info", Params, "GetStrangerInfo:" + Utils.NowTimeSteamp())); + + return new Dictionary() { + {"UserID",Json.Value("user_id")}, + {"NickName",Json.Value("nickname")}, + {"Sex",Json.Value("sex")}, + {"Age",Json.Value("age")}, + {"QID",Json.Value("qid")} + }; } /// /// 获取好友列表 /// /// 错误返回null,成功返回JObject - public async Task GetFriendList() + public async Task> GetFriendList() { - return await SendCallObject(new BaseAPI("get_friend_list", null, "GetFriendList:" + Utils.NowTimeSteamp())); + return (await SendCallArray(new BaseAPI("get_friend_list", null, "GetFriendList:" + Utils.NowTimeSteamp()))).ToObject>(); } /// @@ -478,15 +498,15 @@ public async Task GetGroupList() /// 获取群成员信息 /// /// 群号 - /// QQ号 + /// QQ号 /// 是否使用缓存,使用缓存响应快但是可能更新不及时默认:false /// 错误返回null,成功返回JObject - public async Task GetGroupMemberInfo(long GroupID, long QID, bool Cache = false) + public async Task GetGroupMemberInfo(long GroupID, long UserID, bool Cache = false) { JObject Params = new JObject { { "group_id", GroupID }, - { "user_id", QID }, + { "user_id", UserID }, { "no_cache ", Cache } }; @@ -542,9 +562,26 @@ public async Task CanSendRecord() /// 获取版本信息 /// /// 错误返回null,成功返回JObject - public async Task GetVersionInfo() + public async Task> GetVersionInfo() { - return await SendCallObject(new BaseAPI("get_version_info", null, "GetVersionInfo:" + Utils.NowTimeSteamp())); + JObject Json = await SendCallObject(new BaseAPI("get_version_info", null, "GetVersionInfo:" + Utils.NowTimeSteamp())); + + return new Dictionary() { + {"AppFullName",Json.Value("app_full_name")}, + {"AppName",Json.Value("app_name")}, + {"AppVersion",Json.Value("app_version")}, + {"CQDirectory",Json.Value("coolq_directory")}, + {"CQEdition",Json.Value("coolq_edition")}, + {"IsGoCqhttp",Json.Value("go-cqhttp")}, + {"PluginBuildConfiguration",Json.Value("plugin_build_configuration")}, + {"PluginBuildNumber",Json.Value("plugin_build_number")}, + {"PluginVersion",Json.Value("plugin_version")}, + {"Protocol",Json.Value("protocol")}, + {"ProtocolVersion",Json.Value("protocol_version")}, + {"RuntimeOS",Json.Value("runtime_os")}, + {"RuntimeVersion",Json.Value("runtime_version")}, + {"Version",Json.Value("version")} + }; } /// @@ -717,11 +754,11 @@ public void HandleQuickOperation(object Context, object Operation) /// /// 获取VIP信息 /// - /// QQ号 + /// QQ号 /// 错误返回null,成功返回JObject - public async Task GetVIPInfo(long QID) + public async Task GetVIPInfo(long UserID) { - return await SendCallObject(new BaseAPI("_get_vip_info", new JObject { { "user_id", QID } }, "GetGroupAtAllRemain:" + Utils.NowTimeSteamp())); + return await SendCallObject(new BaseAPI("_get_vip_info", new JObject { { "user_id", UserID } }, "GetGroupAtAllRemain:" + Utils.NowTimeSteamp())); } /// @@ -840,8 +877,7 @@ public async Task CheckURLSafely(string URL) private async Task SendCallMessageID(BaseAPI Params) { - WebSocket.Send(Params); - TaskList.Add(Params.UniqueCode, "Sended"); + SendCall(Params); string Result = "-1"; await Task.Run(() => { Result = FeedbackMessageID(Params.UniqueCode); }); @@ -850,14 +886,32 @@ private async Task SendCallMessageID(BaseAPI Params) private async Task SendCallObject(BaseAPI Params) { - WebSocket.Send(Params); - TaskList.Add(Params.UniqueCode, "Sended"); + SendCall(Params); JObject Result = null; await Task.Run(() => { Result = FeedbackObject(Params.UniqueCode); }); return Result; } + private async Task SendCallArray(BaseAPI Params) + { + SendCall(Params); + + JArray Result = null; + await Task.Run(() => { Result = FeedbackArray(Params.UniqueCode); }); + return Result; + } + + private void SendCall(BaseAPI Params) + { + Logger.Debug($"API调用:\n请求的接口:{Params.Action}\n请求的唯一码:{Params.UniqueCode}\n请求的参数:\n{Params.Params}"); + WebSocket.Send(Params); + if (!TaskList.TryGetValue(Params.UniqueCode, out _)) + { + TaskList.Add(Params.UniqueCode, "Sended"); + } + } + private void SendCallVoid(BaseAPI Params) { WebSocket.Send(Params); @@ -889,6 +943,18 @@ private static JObject FeedbackObject(string UniqueCode) return null; } + private static JArray FeedbackArray(string UniqueCode) + { + JObject FBJson = GetFeedback(UniqueCode); + + //判断返回 + if (FBJson["status"].ToString() == "ok") + { + return JArray.Parse(FBJson["data"].ToString()); + } + return null; + } + private static JObject GetFeedback(string UniqueCode) { JObject FBJson = new JObject(); @@ -912,6 +978,14 @@ internal static Api Create(BaseWebSocket WebSocket) { Api api = new Api(WebSocket); Cache.Set($"API{AppDomain.CurrentDomain.Id}", api); + Task.Run(() => + { + Thread.Sleep(5000); + if (!BaseWebSocket.IsCheckVersion) + { + Event.CheckVersion(); + } + }); return api; } catch (WebSocketException e) diff --git a/AuroraNative/Abstract/Friends.cs b/AuroraNative/Abstract/Friends.cs new file mode 100644 index 0000000..c1dc2f3 --- /dev/null +++ b/AuroraNative/Abstract/Friends.cs @@ -0,0 +1,32 @@ +using Newtonsoft.Json; + +namespace AuroraNative +{ + /// + /// 好友 抽象类 + /// + public sealed class Friends + { + #region --属性-- + + /// + /// QQ号 + /// + [JsonProperty(PropertyName = "user_id")] + public long UserID; + + /// + /// 昵称 + /// + [JsonProperty(PropertyName = "nickname")] + public string NickName; + + /// + /// 备注 + /// + [JsonProperty(PropertyName = "remark")] + public string Remark; + + #endregion + } +} diff --git a/AuroraNative/AuroraNative.xml b/AuroraNative/AuroraNative.xml index cc8acbe..53e026a 100644 --- a/AuroraNative/AuroraNative.xml +++ b/AuroraNative/AuroraNative.xml @@ -4,6 +4,26 @@ AuroraNative + + + 好友 抽象类 + + + + + QQ号 + + + + + 昵称 + + + + + 备注 + + API 类 @@ -29,7 +49,7 @@ 发送私聊消息 - 接受者QQ号 + 接受者QQ号 信息内容 是否转义默认:false 返回消息ID,错误返回-1 @@ -43,7 +63,7 @@ 是否转义默认:false 返回消息ID,错误返回-1 - + 转发合并消息 - 群 @@ -57,7 +77,7 @@ 信息内容 信息类型私聊:private群聊:group - QQ号 + QQ号 群号 是否转义默认:false 错误返回-1,成功返回信息ID @@ -94,7 +114,7 @@ 群组踢人 群号 - QQ号 + QQ号 是否自动拒绝此人加群申请默认:false @@ -102,7 +122,7 @@ 群组单人禁言 群号 - QQ号 + QQ号 禁言时间,单位秒默认:30分钟(1800秒) @@ -126,7 +146,7 @@ 设置群管理员 群号 - QQ号 + QQ号 是否设置为管理员默认:true @@ -134,7 +154,7 @@ 设置群名片 群号 - QQ号 + QQ号 群名片内容默认:null(删除群名片) @@ -156,7 +176,7 @@ 设置群组专属头衔 群号 - QQ号 + QQ号 群名片内容默认:null(删除群名片) 专属头衔有效期, 单位秒, 不过此项似乎没有效果, 可能是只有某些特殊的时间长度有效, 有待测试默认:-1(永久) @@ -187,7 +207,7 @@ 获取陌生人信息 - QQ号 + QQ号 是否使用缓存,使用缓存响应快但是可能更新不及时默认:false 错误返回null,成功返回JObject @@ -216,7 +236,7 @@ 获取群成员信息 群号 - QQ号 + QQ号 是否使用缓存,使用缓存响应快但是可能更新不及时默认:false 错误返回null,成功返回JObject @@ -351,7 +371,7 @@ 获取VIP信息 - QQ号 + QQ号 错误返回null,成功返回JObject @@ -703,146 +723,34 @@ 请求事件 - - - 事件类 - - - - - 元事件 - 生命周期 - - 生命周期事件参数 - - - - 元事件 - 心跳 - - 心跳事件参数 - - - - 消息事件 - 私聊消息 - - 私聊消息参数 - - - - 消息事件 - 群消息 - - 群消息参数 - - - - 请求事件 - 好友请求 - - 好友请求参数 - - - - 请求事件 - 群请求 - - 群请求参数 - - - - 通知事件 - 群文件上传 - - 群文件上传参数 - - - - 通知事件 - 群管理员变动 - - 群管理员变动参数 - - - - 通知事件 - 群成员减少 - - 群成员减少参数 - - - - 通知事件 - 群成员增加 - - 群成员增加参数 - - - - 通知事件 - 群禁言 - - 群禁言参数 - - - - 通知事件 - 好友添加 - - 好友添加参数 - - - - 通知事件 - 群消息撤回 - - 群消息撤回参数 - - - - 通知事件 - 好友消息撤回 - - 好友消息撤回参数 - - - - 通知事件 - 群内戳一戳 - - 群内戳一戳参数 - - - - 通知事件 - 好友戳一戳 - - 群内戳一戳参数 - - - - 通知事件 - 群红包运气王提示 - - 群红包运气王提示参数 - - + - 通知事件 - 群成员荣誉变更提示 + 表示日志信息等级的枚举 - 群成员荣誉变更提示参数 - + - 通知事件 - 群成员名片更新(核验) + 表示输出日志的等级是 "调试" 级别 - 群成员名片更新(核验)参数 - + - 通知事件 - 接收到离线文件 + 表示输出日志的等级是 "信息" 级别 - 接收到离线文件参数 - + - 通知事件 - 其他客户端在线状态变更 + 表示输出日志的等级是 "警告" 级别 - 其他客户端在线状态变更参数 - + - 通知事件 - 精华消息变更 + 表示输出日志的等级是 "错误" 级别 - 精华消息变更参数 - + - 请勿使用,用于子事件分发 + 表示不输出日志 @@ -1789,6 +1697,148 @@ 异常 类 -- 关于WebSocket异常 + + + 事件类 + + + + + 元事件 - 生命周期 + + 生命周期事件参数 + + + + 元事件 - 心跳 + + 心跳事件参数 + + + + 消息事件 - 私聊消息 + + 私聊消息参数 + + + + 消息事件 - 群消息 + + 群消息参数 + + + + 请求事件 - 好友请求 + + 好友请求参数 + + + + 请求事件 - 群请求 + + 群请求参数 + + + + 通知事件 - 群文件上传 + + 群文件上传参数 + + + + 通知事件 - 群管理员变动 + + 群管理员变动参数 + + + + 通知事件 - 群成员减少 + + 群成员减少参数 + + + + 通知事件 - 群成员增加 + + 群成员增加参数 + + + + 通知事件 - 群禁言 + + 群禁言参数 + + + + 通知事件 - 好友添加 + + 好友添加参数 + + + + 通知事件 - 群消息撤回 + + 群消息撤回参数 + + + + 通知事件 - 好友消息撤回 + + 好友消息撤回参数 + + + + 通知事件 - 群内戳一戳 + + 群内戳一戳参数 + + + + 通知事件 - 好友戳一戳 + + 群内戳一戳参数 + + + + 通知事件 - 群红包运气王提示 + + 群红包运气王提示参数 + + + + 通知事件 - 群成员荣誉变更提示 + + 群成员荣誉变更提示参数 + + + + 通知事件 - 群成员名片更新(核验) + + 群成员名片更新(核验)参数 + + + + 通知事件 - 接收到离线文件 + + 接收到离线文件参数 + + + + 通知事件 - 其他客户端在线状态变更 + + 其他客户端在线状态变更参数 + + + + 通知事件 - 精华消息变更 + + 精华消息变更参数 + + + + 请勿使用,用于子事件分发 + + 彩色日志输出类 @@ -1827,31 +1877,6 @@ 要输出的信息 输出的方法名,可选传入 - - - 表示日志信息等级的枚举 - - - - - 表示输出日志的等级是 "调试" 级别 - - - - - 表示输出日志的等级是 "信息" 级别 - - - - - 表示输出日志的等级是 "警告" 级别 - - - - - 表示输出日志的等级是 "错误" 级别 - - 通用方法 类 @@ -1862,7 +1887,7 @@ 通过 枚举Description 转为枚举 枚举 - 需要转换的Description + 需要转换的Description 返回该枚举 @@ -1883,6 +1908,16 @@ WebSocket 基础类 + + + 客户端创建 抽象方法 + + + + + 客户端销毁 抽象方法 + + 发送数据到服务端/客户端 @@ -1897,7 +1932,12 @@ - WebSocket服务端地址请记得带端口号 + WebSocket服务端地址 + + + + + WebSocket服务端端口号 diff --git a/AuroraNative/Enum/LogLevel.cs b/AuroraNative/Enum/LogLevel.cs new file mode 100644 index 0000000..ba0c67b --- /dev/null +++ b/AuroraNative/Enum/LogLevel.cs @@ -0,0 +1,29 @@ +namespace AuroraNative +{ + /// + /// 表示日志信息等级的枚举 + /// + public enum LogLevel + { + /// + /// 表示输出日志的等级是 "调试" 级别 + /// + Debug = 0, + /// + /// 表示输出日志的等级是 "信息" 级别 + /// + Info = 1, + /// + /// 表示输出日志的等级是 "警告" 级别 + /// + Warning = 2, + /// + /// 表示输出日志的等级是 "错误" 级别 + /// + Error = 3, + /// + /// 表示不输出日志 + /// + Off = 4 + } +} diff --git a/AuroraNative/Utils/EnumDescriptionConverter.cs b/AuroraNative/Utils/EnumDescriptionConverter.cs deleted file mode 100644 index db13b5c..0000000 --- a/AuroraNative/Utils/EnumDescriptionConverter.cs +++ /dev/null @@ -1,61 +0,0 @@ -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/Utils/Event.cs b/AuroraNative/Utils/Event.cs index 186fe40..57ececb 100644 --- a/AuroraNative/Utils/Event.cs +++ b/AuroraNative/Utils/Event.cs @@ -1,12 +1,14 @@ using AuroraNative.EventArgs; +using AuroraNative.WebSockets; using Newtonsoft.Json.Linq; +using System; namespace AuroraNative { /// /// 事件类 /// - public class Event + public abstract class Event { #region --公开函数-- @@ -230,5 +232,23 @@ public void RouterNotify(JObject Json) #endregion #endregion + + #region --私有函数-- + + internal static async void CheckVersion() + { + Logger.Debug("开始检查 go-cqhttp 版本是否符合最低版本..."); + if ((await Api.CurrentApi.GetVersionInfo()).TryGetValue("AppVersion", out object Version) && new Version(Version.ToString().Substring(1, Version.ToString().IndexOf('-') - 1)) < BaseWebSocket.DependencyVersion) + { + Logger.Warning($"框架最低依赖版本与 go-cqhttp 不符!请检查是否为最新的框架或符合的 go-cqhttp\ngo-cqhttp版本:{Version}\n框架最低依赖版本:v{BaseWebSocket.DependencyVersion}"); + } + else + { + Logger.Debug("go-cqhttp 版本符合最低版本!"); + } + BaseWebSocket.IsCheckVersion = true; + } + + #endregion } } diff --git a/AuroraNative/Utils/Logger.cs b/AuroraNative/Utils/Logger.cs index 6460410..20a93cb 100644 --- a/AuroraNative/Utils/Logger.cs +++ b/AuroraNative/Utils/Logger.cs @@ -27,7 +27,7 @@ public static void Debug(string Message, string MethodName = null) { if (LogLevel <= LogLevel.Debug) { - Output(Message, ConsoleColor.Gray, LogLevel.Debug, MethodName); + Output(Message, ConsoleColor.Gray, LogLevel.Debug, MethodName, true); } } @@ -74,43 +74,31 @@ public static void Error(string Message, string MethodName = null) #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, bool IsFine = false) { Console.ForegroundColor = Color; + string NowTime; + + if (!IsFine) + { + NowTime = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"); + } + else + { + NowTime = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss fff"); + } + if (MethodName != null) { - Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss fff") + $" [{Level}]" + $" [{MethodName}] " + Message); + Console.WriteLine($"[{NowTime}]" + $" [{Level}]" + $" [{MethodName}]: " + Message); } else { - Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss") + $" [{Level}] " + Message); + Console.WriteLine($"[{NowTime}]" + $" [{Level}]: " + Message); } Console.ForegroundColor = ConsoleColor.White; } #endregion } - - /// - /// 表示日志信息等级的枚举 - /// - public enum LogLevel - { - /// - /// 表示输出日志的等级是 "调试" 级别 - /// - Debug = 0, - /// - /// 表示输出日志的等级是 "信息" 级别 - /// - Info = 1, - /// - /// 表示输出日志的等级是 "警告" 级别 - /// - Warning = 2, - /// - /// 表示输出日志的等级是 "错误" 级别 - /// - Error = 3 - } } diff --git a/AuroraNative/WebSockets/BaseWebSocket.cs b/AuroraNative/WebSockets/BaseWebSocket.cs index b87626b..32af9e4 100644 --- a/AuroraNative/WebSockets/BaseWebSocket.cs +++ b/AuroraNative/WebSockets/BaseWebSocket.cs @@ -17,20 +17,34 @@ public abstract class BaseWebSocket { #region --变量-- + internal int Port = 6700; internal WebSocket WebSocket; internal Event EventHook; internal JObject Json; - internal static Type[] AttributeTypes; + internal static readonly Type[] AttributeTypes = Assembly.GetExecutingAssembly().GetTypes().Where(p => p.IsAbstract == false && p.IsInterface == false && typeof(Attribute).IsAssignableFrom(p)).ToArray(); + internal static readonly Version DependencyVersion = new Version("0.9.40"); + internal static bool IsCheckVersion = false; #endregion #region --公开函数-- + /// + /// 客户端创建 抽象方法 + /// + public abstract void Create(); + /// + /// 客户端销毁 抽象方法 + /// + public abstract void Dispose(); + + internal abstract void Feedback(); + /// /// 发送数据到服务端/客户端 /// /// 传输Json格式的文本 - public void Send(BaseAPI Json) + internal void Send(BaseAPI Json) { try { @@ -64,7 +78,7 @@ internal async Task GetEventAsync() { foreach (MethodInfo Method in EventHook.GetType().GetMethods().Where(p => p.GetCustomAttribute() != null)) { - if (Method.GetCustomAttribute(Type) is BaseAttribute attribute && attribute.Type == (string)Json.GetValue(Utils.GetChildTypeByPostType(Json))) + if (Method.GetCustomAttribute(Type) is BaseAttribute Attribute && Attribute.Type == (string)Json.GetValue(Utils.GetChildTypeByPostType(Json))) { ParameterInfo Parameter = Method.GetParameters().SingleOrDefault(); diff --git a/AuroraNative/WebSockets/Client.cs b/AuroraNative/WebSockets/Client.cs index 948bc90..d2157a1 100644 --- a/AuroraNative/WebSockets/Client.cs +++ b/AuroraNative/WebSockets/Client.cs @@ -1,7 +1,7 @@ using System; -using System.Linq; using System.Net.WebSockets; using System.Reflection; +using System.Text; using System.Threading; using System.Threading.Tasks; @@ -15,25 +15,41 @@ public class Client : BaseWebSocket { #region --变量-- - private string Host = "127.0.0.1:6700"; + private string Host = "127.0.0.1"; + /// - /// WebSocket服务端地址请记得带端口号 + /// WebSocket服务端地址 /// public string host { private get { return Host; } - set { Host = value; } + set + { + if (value.Contains(":")) + { + string[] Cache = value.Split(':'); + Host = Cache[0]; + Port = int.Parse(Cache[1]); + } + else + { + Host = value; + } + } + } + /// + /// WebSocket服务端端口号 + /// + public int port + { + private get { return Port; } + set { Port = value; } } #endregion #region --构造函数-- - static Client() - { - AttributeTypes = Assembly.GetExecutingAssembly().GetTypes().Where(p => p.IsAbstract == false && p.IsInterface == false && typeof(Attribute).IsAssignableFrom(p)).ToArray(); - } - /// /// 创建一个 实例 /// @@ -47,8 +63,13 @@ static Client() /// /// 创建并连接到WebSocket服务器 /// - public bool Create() + public override void Create() { + StringBuilder Cache = new StringBuilder(); + Cache.Append(Host); + Cache.Append(':'); + Cache.Append(Port); + Logger.Debug("正向WebSocket已创建,准备连接...", $"{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}"); for (int i = 1; i < 4; i++) { @@ -57,8 +78,8 @@ public bool Create() WebSocket = new ClientWebSocket(); if (WebSocket is ClientWebSocket socket) { - Logger.Debug($"准备连接至IP:{Host}", $"{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}"); - Task Connect = socket.ConnectAsync(new Uri("ws://" + Host + "/"), CancellationToken.None); + Logger.Debug($"准备连接至IP:{Cache}", $"{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}"); + Task Connect = socket.ConnectAsync(new Uri("ws://" + Cache.ToString() + "/"), CancellationToken.None); Connect.Wait(); if (WebSocket.State == WebSocketState.Open) { @@ -68,7 +89,7 @@ public bool Create() Logger.Debug("go-cqhttp 初始化完毕!"); Task.Run(Feedback); Api.Create(this); - return true; + return; } } } @@ -79,13 +100,12 @@ public bool Create() } } Logger.Error("连接到 go-cqhttp 服务器失败!请检查IP是否正确(需要携带端口号)或确认服务器是否启动和初始化完毕!", $"{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}"); - return false; } /// /// 立刻中断并释放连接注意!断开后需要重新Create /// - public void Dispose() + public override void Dispose() { Logger.Debug($"准备销毁正向WebSocket...", $"{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}"); try @@ -105,7 +125,7 @@ public void Dispose() #region --私有函数-- - private async void Feedback() + internal override async void Feedback() { while (true) { diff --git a/AuroraNative/WebSockets/Server.cs b/AuroraNative/WebSockets/Server.cs index 9e8fc97..e04eade 100644 --- a/AuroraNative/WebSockets/Server.cs +++ b/AuroraNative/WebSockets/Server.cs @@ -1,5 +1,4 @@ using System; -using System.Linq; using System.Net; using System.Net.WebSockets; using System.Reflection; @@ -16,11 +15,10 @@ public class Server : BaseWebSocket { #region --变量-- - private string Port = "6700"; /// /// WebSocket监听端口 /// - public string port + public int port { private get { return Port; } set { Port = value; } @@ -33,11 +31,6 @@ public string port #region --构造函数-- - static Server() - { - AttributeTypes = Assembly.GetExecutingAssembly().GetTypes().Where(p => p.IsAbstract == false && p.IsInterface == false && typeof(Attribute).IsAssignableFrom(p)).ToArray(); - } - /// /// 创建一个 实例 /// @@ -51,13 +44,13 @@ static Server() /// /// 创建WebSocket服务器并监听端口 /// - public void Create() + public override void Create() { try { Logger.Debug("反向WebSocket已创建,准备监听...", $"{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}"); Listener = new HttpListener(); - Listener.Prefixes.Add("http://*:" + Port + "/"); + Listener.Prefixes.Add("http://*:" + Port.ToString() + "/"); Listener.Start(); Logger.Info("开始监听来自 go-cqhttp 客户端的连接..."); Task.Run(Feedback); @@ -77,7 +70,7 @@ public void Create() /// /// 立刻中断并释放连接注意!断开后需要重新Create /// - public void Dispose() + public override void Dispose() { Logger.Debug($"准备销毁反向WebSocket...", $"{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}"); try @@ -98,7 +91,7 @@ public void Dispose() #region --私有函数-- - private async void Feedback() + internal override async void Feedback() { while (true) { From a3bce2495030193ea810a5a0a5f25dc4f951c62f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=82=A0=E9=9D=99=E8=90=9D=E8=8E=89?= Date: Mon, 15 Mar 2021 23:15:36 +0800 Subject: [PATCH 6/6] 1.0.0-Beta --- AuroraNative/API/Api.cs | 131 +++- .../{EventArgs/Basic => Abstract}/Device.cs | 2 +- AuroraNative/Abstract/Essences.cs | 56 ++ AuroraNative/Abstract/Groups/Files/File.cs | 74 ++ AuroraNative/Abstract/Groups/Files/Folder.cs | 50 ++ AuroraNative/Abstract/Groups/GroupMember.cs | 104 +++ AuroraNative/Abstract/Groups/Groups.cs | 38 + AuroraNative/Abstract/Groups/HonorListInfo.cs | 44 ++ .../Groups/SystemMessage/BaseRequest.cs | 44 ++ .../Groups/SystemMessage/InvitedRequest.cs | 26 + .../Groups/SystemMessage/JoinRequest.cs | 32 + AuroraNative/Abstract/Messages.cs | 98 +++ AuroraNative/Abstract/OCRTextDetection.cs | 33 + AuroraNative/Abstract/Statistics.cs | 57 ++ .../Basic => Abstract/Users}/Anonymous.cs | 2 +- AuroraNative/Abstract/{ => Users}/Friends.cs | 0 .../Basic => Abstract/Users}/Sender.cs | 2 +- AuroraNative/AuroraNative.csproj | 6 +- AuroraNative/AuroraNative.xml | 717 +++++++++++++++--- AuroraNative/EventArgs/Basic/File.cs | 2 +- AuroraNative/WebSockets/BaseWebSocket.cs | 11 +- AuroraNative/WebSockets/Server.cs | 4 +- 22 files changed, 1355 insertions(+), 178 deletions(-) rename AuroraNative/{EventArgs/Basic => Abstract}/Device.cs (97%) create mode 100644 AuroraNative/Abstract/Essences.cs create mode 100644 AuroraNative/Abstract/Groups/Files/File.cs create mode 100644 AuroraNative/Abstract/Groups/Files/Folder.cs create mode 100644 AuroraNative/Abstract/Groups/GroupMember.cs create mode 100644 AuroraNative/Abstract/Groups/Groups.cs create mode 100644 AuroraNative/Abstract/Groups/HonorListInfo.cs create mode 100644 AuroraNative/Abstract/Groups/SystemMessage/BaseRequest.cs create mode 100644 AuroraNative/Abstract/Groups/SystemMessage/InvitedRequest.cs create mode 100644 AuroraNative/Abstract/Groups/SystemMessage/JoinRequest.cs create mode 100644 AuroraNative/Abstract/Messages.cs create mode 100644 AuroraNative/Abstract/OCRTextDetection.cs create mode 100644 AuroraNative/Abstract/Statistics.cs rename AuroraNative/{EventArgs/Basic => Abstract/Users}/Anonymous.cs (97%) rename AuroraNative/Abstract/{ => Users}/Friends.cs (100%) rename AuroraNative/{EventArgs/Basic => Abstract/Users}/Sender.cs (98%) diff --git a/AuroraNative/API/Api.cs b/AuroraNative/API/Api.cs index 1434752..7542b9c 100644 --- a/AuroraNative/API/Api.cs +++ b/AuroraNative/API/Api.cs @@ -474,7 +474,7 @@ public async Task> GetFriendList() /// 群号 /// 是否使用缓存,使用缓存响应快但是可能更新不及时默认:false /// 错误返回null,成功返回JObject - public async Task GetGroupInfo(long GroupID, bool Cache = false) + public async Task GetGroupInfo(long GroupID, bool Cache = false) { JObject Params = new JObject { @@ -482,16 +482,16 @@ public async Task GetGroupInfo(long GroupID, bool Cache = false) { "no_cache ", Cache } }; - return await SendCallObject(new BaseAPI("get_group_info", Params, "GetGroupInfo:" + Utils.NowTimeSteamp())); + return (await SendCallObject(new BaseAPI("get_group_info", Params, "GetGroupInfo:" + Utils.NowTimeSteamp()))).ToObject(); } /// /// 获取群列表 /// /// 错误返回null,成功返回JObject - public async Task GetGroupList() + public async Task> GetGroupList() { - return await SendCallObject(new BaseAPI("get_group_list", null, "GetGroupList:" + Utils.NowTimeSteamp())); + return (await SendCallObject(new BaseAPI("get_group_list", null, "GetGroupList:" + Utils.NowTimeSteamp()))).ToObject>(); } /// @@ -501,7 +501,7 @@ public async Task GetGroupList() /// QQ号 /// 是否使用缓存,使用缓存响应快但是可能更新不及时默认:false /// 错误返回null,成功返回JObject - public async Task GetGroupMemberInfo(long GroupID, long UserID, bool Cache = false) + public async Task GetGroupMemberInfo(long GroupID, long UserID, bool Cache = false) { JObject Params = new JObject { @@ -510,7 +510,7 @@ public async Task GetGroupMemberInfo(long GroupID, long UserID, bool Ca { "no_cache ", Cache } }; - return await SendCallObject(new BaseAPI("get_group_member_info", Params, "GetGroupMemberInfo:" + Utils.NowTimeSteamp())); + return (await SendCallObject(new BaseAPI("get_group_member_info", Params, "GetGroupMemberInfo:" + Utils.NowTimeSteamp()))).ToObject(); } /// @@ -518,9 +518,9 @@ public async Task GetGroupMemberInfo(long GroupID, long UserID, bool Ca /// /// 群号 /// 错误返回null,成功返回JObject - public async Task GetGroupMemberList(long GroupID) + public async Task> GetGroupMemberList(long GroupID) { - return await SendCallObject(new BaseAPI("get_group_member_info", new JObject { { "group_id", GroupID } }, "GetGroupMemberInfo:" + Utils.NowTimeSteamp())); + return (await SendCallObject(new BaseAPI("get_group_member_info", new JObject { { "group_id", GroupID } }, "GetGroupMemberInfo:" + Utils.NowTimeSteamp()))).ToObject>(); } /// @@ -529,7 +529,7 @@ public async Task GetGroupMemberList(long GroupID) /// 群号 /// 要获取的群荣誉类型talkative/performer/legend/strong_newbie/emotion/all /// 错误返回null,成功返回JObject - public async Task GetGroupHonorInfo(long GroupID, string Type) + public async Task> GetGroupHonorInfo(long GroupID, string Type) { JObject Params = new JObject { @@ -537,7 +537,22 @@ public async Task GetGroupHonorInfo(long GroupID, string Type) { "type ", Type } }; - return await SendCallObject(new BaseAPI("get_group_honor_info", Params, "GetGroupHonorInfo:" + Utils.NowTimeSteamp())); + JObject Json = await SendCallObject(new BaseAPI("get_group_honor_info", Params, "GetGroupHonorInfo:" + Utils.NowTimeSteamp())); + List Result = new List(); + + foreach (string i in new string[] { "talkative", "performer", "legend", "strong_newbie", "emotion" }) + { + if (Json.TryGetValue("current_talkative", out JToken Cache)) + { + Result.Add(Cache.ToObject()); + } + if (Json.TryGetValue(i + "_list", out Cache)) + { + Result.Add(Cache.ToObject()); + } + } + + return Result; } /// @@ -626,18 +641,20 @@ public async Task GetWordSlices(string Content) /// /// 图片ID /// 错误返回null,成功返回JObject - public async Task OCRImage(string Image) + public async Task<(List, string)> OCRImage(string Image) { - return await SendCallObject(new BaseAPI("ocr_image", new JObject { { "image", Image } }, "OCRImage:" + Utils.NowTimeSteamp())); + JObject Json = await SendCallObject(new BaseAPI("ocr_image", new JObject { { "image", Image } }, "OCRImage:" + Utils.NowTimeSteamp())); + return (Json.Value("texts").ToObject>(), Json.Value("language")); } /// /// 获取群系统消息 /// /// 错误或不存在任何消息返回null,成功返回JObject - public async Task GetGroupSystemMsg() + public async Task<(List, List)> GetGroupSystemMsg() { - return await SendCallObject(new BaseAPI("get_group_system_msg", null, "GetGroupSystemMsg:" + Utils.NowTimeSteamp())); + JObject Json = await SendCallObject(new BaseAPI("get_group_system_msg", null, "GetGroupSystemMsg:" + Utils.NowTimeSteamp())); + return (Json.Value("invited_requests").ToObject>(), Json.Value("join_requests").ToObject>()); } /// @@ -665,9 +682,16 @@ public void UploadGroupFile(long GroupID, string FilePath, string SaveName, stri /// /// 群号 /// 错误返回null,成功返回JObject - public async Task GetGroupFileSystemInfo(long GroupID) + public async Task> GetGroupFileSystemInfo(long GroupID) { - return await SendCallObject(new BaseAPI("get_group_file_system_info", new JObject { { "group_id", GroupID } }, "GetGroupFileSystemInfo:" + Utils.NowTimeSteamp())); + JObject Json = await SendCallObject(new BaseAPI("get_group_file_system_info", new JObject { { "group_id", GroupID } }, "GetGroupFileSystemInfo:" + Utils.NowTimeSteamp())); + + return new Dictionary { + { "FileCount",Json.Value("file_count")}, + { "LimitCount",Json.Value("limit_count")}, + { "UsedSpace",Json.Value("used_space")}, + { "TotalSpace",Json.Value("total_space")} + }; } /// @@ -675,9 +699,11 @@ public async Task GetGroupFileSystemInfo(long GroupID) /// /// 群号 /// 错误返回null,成功返回JObject - public async Task GetGroupRootFiles(long GroupID) + public async Task<(List, List)> GetGroupRootFiles(long GroupID) { - return await SendCallObject(new BaseAPI("get_group_root_files", new JObject { { "group_id", GroupID } }, "GetGroupRootFiles:" + Utils.NowTimeSteamp())); + JObject Json = await SendCallObject(new BaseAPI("get_group_root_files", new JObject { { "group_id", GroupID } }, "GetGroupRootFiles:" + Utils.NowTimeSteamp())); + + return (Json.Value("files").ToObject>(), Json.Value("folders").ToObject>()); } /// @@ -686,7 +712,7 @@ public async Task GetGroupRootFiles(long GroupID) /// 群号 /// 文件夹ID /// 错误返回null,成功返回JObject - public async Task GetGroupFilesByFolder(long GroupID, string FolderID) + public async Task<(List, List)> GetGroupFilesByFolder(long GroupID, string FolderID) { JObject Params = new JObject { @@ -694,7 +720,9 @@ public async Task GetGroupFilesByFolder(long GroupID, string FolderID) { "folder_id ", FolderID } }; - return await SendCallObject(new BaseAPI("get_group_files_by_folder", Params, "GetGroupFilesByFolder:" + Utils.NowTimeSteamp())); + JObject Json = await SendCallObject(new BaseAPI("get_group_files_by_folder", Params, "GetGroupFilesByFolder:" + Utils.NowTimeSteamp())); + + return (Json.Value("files").ToObject>(), Json.Value("folders").ToObject>()); } /// @@ -720,9 +748,10 @@ public async Task GetGroupFilesURL(long GroupID, string FileID, int BusI /// 获取状态 /// /// 错误返回null,成功返回JObject - public async Task GetStatus() + public async Task<(bool, Statistics)> GetStatus() { - return await SendCallObject(new BaseAPI("get_group_info", null, "GetGroupInfo:" + Utils.NowTimeSteamp())); + JObject Json = await SendCallObject(new BaseAPI("get_group_info", null, "GetGroupInfo:" + Utils.NowTimeSteamp())); + return (Json.Value("online"), Json.Value("stat")); } /// @@ -730,9 +759,15 @@ public async Task GetStatus() /// /// 群号 /// 错误返回null,成功返回JObject - public async Task GetGroupAtAllRemain(long GroupID) + public async Task> GetGroupAtAllRemain(long GroupID) { - return await SendCallObject(new BaseAPI("get_group_at_all_remain", new JObject { { "group_id", GroupID } }, "GetGroupAtAllRemain:" + Utils.NowTimeSteamp())); + JObject Json = await SendCallObject(new BaseAPI("get_group_at_all_remain", new JObject { { "group_id", GroupID } }, "GetGroupAtAllRemain:" + Utils.NowTimeSteamp())); + + return new Dictionary() { + { "CanAtAll",Json.Value("can_at_all")}, + { "GroupAdminAtAllCount",Json.Value("remain_at_all_count_for_group")}, + { "BotAtAllCount",Json.Value("remain_at_all_count_for_uin")} + }; } /// @@ -756,9 +791,19 @@ public void HandleQuickOperation(object Context, object Operation) /// /// QQ号 /// 错误返回null,成功返回JObject - public async Task GetVIPInfo(long UserID) + public async Task> GetVIPInfo(long UserID) { - return await SendCallObject(new BaseAPI("_get_vip_info", new JObject { { "user_id", UserID } }, "GetGroupAtAllRemain:" + Utils.NowTimeSteamp())); + JObject Json = await SendCallObject(new BaseAPI("_get_vip_info", new JObject { { "user_id", UserID } }, "GetGroupAtAllRemain:" + Utils.NowTimeSteamp())); + + return new Dictionary() { + { "UserID",Json.Value("user_id")}, + { "NickName",Json.Value("nickname")}, + { "Level",Json.Value("level")}, + { "LevelSpeed",Json.Value("level_speed")}, + { "VipLevel",Json.Value("vip_level")}, + { "VipGrowthSpeed",Json.Value("vip_growth_speed")}, + { "VipGrowthTotal",Json.Value("vip_growth_total")} + }; } /// @@ -809,9 +854,9 @@ public async Task DownloadFile(string URL, int ThreadCount, string[] Hea /// /// 是否无视缓存 /// 错误返回null,成功返回JObject - public async Task GetOnlineClients(bool Cache) + public async Task> GetOnlineClients(bool Cache) { - return await SendCallObject(new BaseAPI("get_online_clients", new JObject { { "no_cache ", Cache } }, "GetOnlineClients:" + Utils.NowTimeSteamp())); + return (await SendCallObject(new BaseAPI("get_online_clients", new JObject { { "no_cache ", Cache } }, "GetOnlineClients:" + Utils.NowTimeSteamp()))).Value("clients").ToObject>(); } /// @@ -820,15 +865,21 @@ public async Task GetOnlineClients(bool Cache) /// 起始消息序号 /// 群号 /// 错误返回null,成功返回JObject - public async Task GetGroupMsgHistory(long MessageSeq, long GroupID) + public async Task> GetGroupMsgHistory(long GroupID, long MessageSeq = 0) { JObject Params = new JObject { { "message_seq", MessageSeq }, - { "group_id ", GroupID } + { "group_id", GroupID } }; - return await SendCallObject(new BaseAPI("get_group_msg_history", Params, "GetGroupMsgHistory:" + Utils.NowTimeSteamp())); + if (MessageSeq == 0) + { + Params.Remove("message_seq"); + } + + JObject Json = await SendCallObject(new BaseAPI("get_group_msg_history", Params, "GetGroupMsgHistory:" + Utils.NowTimeSteamp())); + return Json.Value("messages").ToObject>(); } /// @@ -854,9 +905,9 @@ public void DelEssenceMsg(string MessageID) /// /// 群号 /// 错误返回null,成功返回JObject - public async Task GetEssenceMsgList(long GroupID) + public async Task> GetEssenceMsgList(long GroupID) { - return await SendCallObject(new BaseAPI("get_essence_msg_list", new JObject { { "group_id", GroupID } }, "GetEssenceMsgList:" + Utils.NowTimeSteamp())); + return (await SendCallObject(new BaseAPI("get_essence_msg_list", new JObject { { "group_id", GroupID } }, "GetEssenceMsgList:" + Utils.NowTimeSteamp()))).ToObject>(); } /// @@ -921,7 +972,7 @@ private void SendCallVoid(BaseAPI Params) private static string FeedbackMessageID(string UniqueCode) { - JObject FBJson = GetFeedback(UniqueCode); + JToken FBJson = GetFeedback(UniqueCode); //判断返回 if (FBJson["status"].ToString() == "ok") @@ -933,7 +984,7 @@ private static string FeedbackMessageID(string UniqueCode) private static JObject FeedbackObject(string UniqueCode) { - JObject FBJson = GetFeedback(UniqueCode); + JToken FBJson = GetFeedback(UniqueCode); //判断返回 if (FBJson["status"].ToString() == "ok") @@ -945,7 +996,7 @@ private static JObject FeedbackObject(string UniqueCode) private static JArray FeedbackArray(string UniqueCode) { - JObject FBJson = GetFeedback(UniqueCode); + JToken FBJson = GetFeedback(UniqueCode); //判断返回 if (FBJson["status"].ToString() == "ok") @@ -955,20 +1006,20 @@ private static JArray FeedbackArray(string UniqueCode) return null; } - private static JObject GetFeedback(string UniqueCode) + private static JToken GetFeedback(string UniqueCode) { - JObject FBJson = new JObject(); + JToken FBJson = null; do { if (TaskList[UniqueCode].ToString() != "Sended") { - FBJson = JObject.Parse(TaskList[UniqueCode].ToString()); + FBJson = TaskList[UniqueCode]; TaskList.Remove(UniqueCode); break; } Thread.Sleep(10); - } while (FBJson["status"] == null); + } while (FBJson == null); return FBJson; } diff --git a/AuroraNative/EventArgs/Basic/Device.cs b/AuroraNative/Abstract/Device.cs similarity index 97% rename from AuroraNative/EventArgs/Basic/Device.cs rename to AuroraNative/Abstract/Device.cs index 0f42780..ab91fae 100644 --- a/AuroraNative/EventArgs/Basic/Device.cs +++ b/AuroraNative/Abstract/Device.cs @@ -1,6 +1,6 @@ using Newtonsoft.Json; -namespace AuroraNative.EventArgs +namespace AuroraNative { /// /// 提供用于描述事件参数的基础类, 该类是抽象的 diff --git a/AuroraNative/Abstract/Essences.cs b/AuroraNative/Abstract/Essences.cs new file mode 100644 index 0000000..b2365ac --- /dev/null +++ b/AuroraNative/Abstract/Essences.cs @@ -0,0 +1,56 @@ +using Newtonsoft.Json; + +namespace AuroraNative +{ + /// + /// 精华消息 抽象类 + /// + public sealed class Essences + { + #region --属性-- + + /// + /// 发送者QQ 号 + /// + [JsonProperty(PropertyName = "sender_id")] + public long SenderID { get; private set; } + + /// + /// 发送者昵称 + /// + [JsonProperty(PropertyName = "sender_nick")] + public string SenderNickName { get; private set; } + + /// + /// 消息发送时间 + /// + [JsonProperty(PropertyName = "sender_time")] + public string SenderTime { get; private set; } + + /// + /// 操作者QQ 号 + /// + [JsonProperty(PropertyName = "operator_id")] + public string OperatorID { get; private set; } + + /// + /// 操作者昵称 + /// + [JsonProperty(PropertyName = "operator_nick")] + public string OperatorNickName { get; private set; } + + /// + /// 精华设置时间 + /// + [JsonProperty(PropertyName = "operator_time")] + public string OperatorTime { get; private set; } + + /// + /// 消息ID + /// + [JsonProperty(PropertyName = "message_id")] + public string MessageID { get; private set; } + + #endregion + } +} diff --git a/AuroraNative/Abstract/Groups/Files/File.cs b/AuroraNative/Abstract/Groups/Files/File.cs new file mode 100644 index 0000000..03ed694 --- /dev/null +++ b/AuroraNative/Abstract/Groups/Files/File.cs @@ -0,0 +1,74 @@ +using Newtonsoft.Json; + +namespace AuroraNative +{ + /// + /// 群文件 抽象类 + /// + public sealed class File + { + #region --属性-- + + /// + /// 文件ID + /// + [JsonProperty(PropertyName = "file_id")] + public string FileID; + + /// + /// 文件名称 + /// + [JsonProperty(PropertyName = "file_name")] + public string FileName; + + /// + /// 文件类型 + /// + [JsonProperty(PropertyName = "busid")] + public long BusID; + + /// + /// 文件大小 + /// + [JsonProperty(PropertyName = "file_size")] + public long FileSize; + + /// + /// 上传时间 + /// + [JsonProperty(PropertyName = "upload_time")] + public string UploadTime; + + /// + /// 过期时间,永久为零 + /// + [JsonProperty(PropertyName = "dead_time")] + public int DeadTime; + + /// + /// 最后修改时间 + /// + [JsonProperty(PropertyName = "modify_time")] + public int ModifyTime; + + /// + /// 下载次数 + /// + [JsonProperty(PropertyName = "download_times")] + public int DownloadsCount; + + /// + /// 上传者ID + /// + [JsonProperty(PropertyName = "uploader")] + public int Uploader; + + /// + /// 上传者名字 + /// + [JsonProperty(PropertyName = "uploader_name")] + public int UploaderName; + + #endregion + } +} diff --git a/AuroraNative/Abstract/Groups/Files/Folder.cs b/AuroraNative/Abstract/Groups/Files/Folder.cs new file mode 100644 index 0000000..4b17f83 --- /dev/null +++ b/AuroraNative/Abstract/Groups/Files/Folder.cs @@ -0,0 +1,50 @@ +using Newtonsoft.Json; + +namespace AuroraNative +{ + /// + /// 群文件夹 抽象类 + /// + public sealed class Folder + { + #region --属性-- + + /// + /// 文件夹ID + /// + [JsonProperty(PropertyName = "folder_id")] + public string FolderID; + + /// + /// 文件夹名称 + /// + [JsonProperty(PropertyName = "folder_name")] + public string FolderName; + + /// + /// 创建时间 + /// + [JsonProperty(PropertyName = "create_time")] + public long CreateTime; + + /// + /// 创建者 + /// + [JsonProperty(PropertyName = "creator")] + public long Creator; + + /// + /// 创建者名称 + /// + [JsonProperty(PropertyName = "creator_name")] + public string CreatoName; + + /// + /// 子文件数量 + /// + [JsonProperty(PropertyName = "total_file_count")] + public int TotalFilesCount; + + #endregion + } +} diff --git a/AuroraNative/Abstract/Groups/GroupMember.cs b/AuroraNative/Abstract/Groups/GroupMember.cs new file mode 100644 index 0000000..205add0 --- /dev/null +++ b/AuroraNative/Abstract/Groups/GroupMember.cs @@ -0,0 +1,104 @@ +using Newtonsoft.Json; + +namespace AuroraNative +{ + /// + /// 群成员信息 抽象类 + /// + public sealed class GroupMember + { + #region --属性-- + + /// + /// 群号 + /// + [JsonProperty(PropertyName = "group_id", NullValueHandling = NullValueHandling.Include)] + public long GroupID; + + /// + /// QQ号 + /// + [JsonProperty(PropertyName = "user_id", NullValueHandling = NullValueHandling.Include)] + public long UserID; + + /// + /// 昵称 + /// + [JsonProperty(PropertyName = "nickname", NullValueHandling = NullValueHandling.Include)] + public string NickName; + + /// + /// 群名片 + /// + [JsonProperty(PropertyName = "card", NullValueHandling = NullValueHandling.Include)] + public string Card; + + /// + /// 现在人数 + /// + [JsonProperty(PropertyName = "sex", NullValueHandling = NullValueHandling.Include)] + public string Sex; + + /// + /// 最大人数 + /// + [JsonProperty(PropertyName = "age", NullValueHandling = NullValueHandling.Include)] + public int MaxMemberCount; + + /// + /// 地区 + /// + [JsonProperty(PropertyName = "area", NullValueHandling = NullValueHandling.Include)] + public string Area; + + /// + /// 加群时间戳 + /// + [JsonProperty(PropertyName = "join_time", NullValueHandling = NullValueHandling.Include)] + public int JoinTime; + + /// + /// 最后发言时间戳 + /// + [JsonProperty(PropertyName = "last_sent_time", NullValueHandling = NullValueHandling.Include)] + public int LastSentTime; + + /// + /// 成员等级 + /// + [JsonProperty(PropertyName = "level", NullValueHandling = NullValueHandling.Include)] + public int Level; + + /// + /// 角色 + /// + [JsonProperty(PropertyName = "role", NullValueHandling = NullValueHandling.Include)] + public int Role; + + /// + /// 是否不良记录成员 + /// + [JsonProperty(PropertyName = "unfriendly", NullValueHandling = NullValueHandling.Include)] + public bool UnFriendly; + + /// + /// 专属头衔 + /// + [JsonProperty(PropertyName = "title", NullValueHandling = NullValueHandling.Include)] + public string ExclusiveTitle; + + /// + /// 专属头衔过期时间戳 + /// + [JsonProperty(PropertyName = "title_expire_time", NullValueHandling = NullValueHandling.Include)] + public long ExclusiveTitleTime; + + /// + /// 是否允许修改群名片 + /// + [JsonProperty(PropertyName = "card_changeable", NullValueHandling = NullValueHandling.Include)] + public bool IsChangeCard; + + #endregion + } +} diff --git a/AuroraNative/Abstract/Groups/Groups.cs b/AuroraNative/Abstract/Groups/Groups.cs new file mode 100644 index 0000000..ccb8dab --- /dev/null +++ b/AuroraNative/Abstract/Groups/Groups.cs @@ -0,0 +1,38 @@ +using Newtonsoft.Json; + +namespace AuroraNative +{ + /// + /// 群组 抽象类 + /// + public sealed class Groups + { + #region --属性-- + + /// + /// 群号 + /// + [JsonProperty(PropertyName = "group_id")] + public long GroupID; + + /// + /// 群名称 + /// + [JsonProperty(PropertyName = "group_name")] + public string GroupName; + + /// + /// 现在人数 + /// + [JsonProperty(PropertyName = "member_count")] + public int MemberCount; + + /// + /// 最大人数 + /// + [JsonProperty(PropertyName = "max_member_count")] + public int MaxMemberCount; + + #endregion + } +} diff --git a/AuroraNative/Abstract/Groups/HonorListInfo.cs b/AuroraNative/Abstract/Groups/HonorListInfo.cs new file mode 100644 index 0000000..e0747e9 --- /dev/null +++ b/AuroraNative/Abstract/Groups/HonorListInfo.cs @@ -0,0 +1,44 @@ +using Newtonsoft.Json; + +namespace AuroraNative +{ + /// + /// 群荣誉详细信息 抽象类 + /// + public sealed class HonorListInfo + { + #region --属性-- + + /// + /// QQ号 + /// + [JsonProperty(PropertyName = "user_id")] + public long UserID; + + /// + /// 昵称 + /// + [JsonProperty(PropertyName = "nickname")] + public string NickName; + + /// + /// 头像URL + /// + [JsonProperty(PropertyName = "avatar")] + public string Avater; + + /// + /// 荣誉描述 + /// + [JsonProperty(PropertyName = "description", NullValueHandling = NullValueHandling.Ignore)] + public string Description; + + /// + /// 持续天数 + /// + [JsonProperty(PropertyName = "day_count", NullValueHandling = NullValueHandling.Ignore)] + public string DayCount; + + #endregion + } +} diff --git a/AuroraNative/Abstract/Groups/SystemMessage/BaseRequest.cs b/AuroraNative/Abstract/Groups/SystemMessage/BaseRequest.cs new file mode 100644 index 0000000..7c36b7e --- /dev/null +++ b/AuroraNative/Abstract/Groups/SystemMessage/BaseRequest.cs @@ -0,0 +1,44 @@ +using Newtonsoft.Json; + +namespace AuroraNative +{ + /// + /// 群系统消息 - 消息列表 基抽象类 + /// + public abstract class BaseRequest + { + #region --属性-- + + /// + /// 请求ID + /// + [JsonProperty(PropertyName = "request_id")] + public long RequestID; + + /// + /// 群号 + /// + [JsonProperty(PropertyName = "group_id")] + public long GroupID; + + /// + /// 群名称 + /// + [JsonProperty(PropertyName = "group_name")] + public string GroupName; + + /// + /// 是否已处理 + /// + [JsonProperty(PropertyName = "checked")] + public bool Checked; + + /// + /// 处理者,未处理是0 + /// + [JsonProperty(PropertyName = "actor")] + public long Actor; + + #endregion + } +} diff --git a/AuroraNative/Abstract/Groups/SystemMessage/InvitedRequest.cs b/AuroraNative/Abstract/Groups/SystemMessage/InvitedRequest.cs new file mode 100644 index 0000000..df275cb --- /dev/null +++ b/AuroraNative/Abstract/Groups/SystemMessage/InvitedRequest.cs @@ -0,0 +1,26 @@ +using Newtonsoft.Json; + +namespace AuroraNative +{ + /// + /// 群系统消息 - 邀请消息列表 抽象类 + /// + public sealed class InvitedRequest : BaseRequest + { + #region --属性-- + + /// + /// 邀请者 + /// + [JsonProperty(PropertyName = "invitor_uin")] + public long InvitorUserID; + + /// + /// 邀请者昵称 + /// + [JsonProperty(PropertyName = "invitor_nick")] + public string InvitorNickName; + + #endregion + } +} diff --git a/AuroraNative/Abstract/Groups/SystemMessage/JoinRequest.cs b/AuroraNative/Abstract/Groups/SystemMessage/JoinRequest.cs new file mode 100644 index 0000000..495ceeb --- /dev/null +++ b/AuroraNative/Abstract/Groups/SystemMessage/JoinRequest.cs @@ -0,0 +1,32 @@ +using Newtonsoft.Json; + +namespace AuroraNative +{ + /// + /// 群系统消息 - 进群消息列表 抽象类 + /// + public sealed class JoinRequest : BaseRequest + { + #region --属性-- + + /// + /// 请求者 + /// + [JsonProperty(PropertyName = "requester_uin")] + public long RequesterUserID; + + /// + /// 请求者昵称 + /// + [JsonProperty(PropertyName = "requester_nick")] + public string RequesterNickName; + + /// + /// 验证信息 + /// + [JsonProperty(PropertyName = "message")] + public long Message; + + #endregion + } +} diff --git a/AuroraNative/Abstract/Messages.cs b/AuroraNative/Abstract/Messages.cs new file mode 100644 index 0000000..9b4f6ec --- /dev/null +++ b/AuroraNative/Abstract/Messages.cs @@ -0,0 +1,98 @@ +using Newtonsoft.Json; + +namespace AuroraNative +{ + /// + /// 消息 抽象类 + /// + public sealed class Messages + { + #region --属性-- + + /// + /// 匿名信息 + /// + [JsonProperty(PropertyName = "anonymous")] + public Anonymous Anonymous; + + /// + /// 字体 + /// + [JsonProperty(PropertyName = "font")] + public int Font; + + /// + /// 群号 + /// + [JsonProperty(PropertyName = "group_id")] + public long GroupID; + + /// + /// 消息内容 + /// + [JsonProperty(PropertyName = "message")] + public string Message; + + /// + /// 原始消息内容 + /// + [JsonProperty(PropertyName = "raw_message")] + public string RawMessage; + + /// + /// 消息ID + /// + [JsonProperty(PropertyName = "message_id")] + public int MessageID; + + /// + /// 消息序号 + /// + [JsonProperty(PropertyName = "message_seq")] + public long MessageSeq; + + /// + /// 消息类型 + /// + [JsonProperty(PropertyName = "message_type")] + public string MessageType; + + /// + /// 消息事件主类型 + /// + [JsonProperty(PropertyName = "post_type")] + public string PostType; + + /// + /// 消息事件子类型 + /// + [JsonProperty(PropertyName = "sub_type")] + public string SubType; + + /// + /// 收到事件的机器人QQ号 + /// + [JsonProperty(PropertyName = "self_id")] + public int SelfID; + + /// + /// 发送者 + /// + [JsonProperty(PropertyName = "sender")] + public Sender Sender; + + /// + /// 消息时间戳 + /// + [JsonProperty(PropertyName = "time")] + public long TimeStamp; + + /// + /// 发送者QQ号 + /// + [JsonProperty(PropertyName = "user_id")] + public long UserID; + + #endregion + } +} diff --git a/AuroraNative/Abstract/OCRTextDetection.cs b/AuroraNative/Abstract/OCRTextDetection.cs new file mode 100644 index 0000000..94dd71a --- /dev/null +++ b/AuroraNative/Abstract/OCRTextDetection.cs @@ -0,0 +1,33 @@ +using Newtonsoft.Json; +using System.Numerics; + +namespace AuroraNative +{ + /// + /// OCR结果信息 抽象类 + /// + public sealed class OCRTextDetection + { + #region --属性-- + + /// + /// 文本 + /// + [JsonProperty(PropertyName = "text")] + public string Text; + + /// + /// 置信度 + /// + [JsonProperty(PropertyName = "confidence")] + public int Confidence; + + /// + /// 坐标 + /// + [JsonProperty(PropertyName = "coordinates")] + public Vector2 Coordinates; + + #endregion + } +} diff --git a/AuroraNative/Abstract/Statistics.cs b/AuroraNative/Abstract/Statistics.cs new file mode 100644 index 0000000..481bc0c --- /dev/null +++ b/AuroraNative/Abstract/Statistics.cs @@ -0,0 +1,57 @@ +using Newtonsoft.Json; + +namespace AuroraNative +{ + /// + /// 运行统计 抽象类 + /// + public sealed class Statistics + { + #region --属性-- + + /// + /// 收到的数据包总数 + /// + [JsonProperty(PropertyName = "packet_received")] + public ulong PacketReceived; + + /// + /// 发送的数据包总数 + /// + [JsonProperty(PropertyName = "packet_sent")] + public ulong PacketSent; + + /// + /// 数据包丢失总数 + /// + [JsonProperty(PropertyName = "packet_lost")] + public uint PacketLost; + + /// + /// 接受信息总数 + /// + [JsonProperty(PropertyName = "message_received")] + public ulong MessageReceived; + + /// + /// 发送信息总数 + /// + [JsonProperty(PropertyName = "message_sent")] + public ulong MessageSent; + + /// + /// TCP 链接断开次数 + /// + [JsonProperty(PropertyName = "disconnect_times")] + public uint DisconnectsCount; + + + /// + /// 账号掉线次数 + /// + [JsonProperty(PropertyName = "lost_times")] + public uint LostsCount; + + #endregion + } +} diff --git a/AuroraNative/EventArgs/Basic/Anonymous.cs b/AuroraNative/Abstract/Users/Anonymous.cs similarity index 97% rename from AuroraNative/EventArgs/Basic/Anonymous.cs rename to AuroraNative/Abstract/Users/Anonymous.cs index 4cb522d..895bc76 100644 --- a/AuroraNative/EventArgs/Basic/Anonymous.cs +++ b/AuroraNative/Abstract/Users/Anonymous.cs @@ -1,6 +1,6 @@ using Newtonsoft.Json; -namespace AuroraNative.EventArgs +namespace AuroraNative { /// /// 提供用于描述匿名信息的基础类, 该类是抽象的 diff --git a/AuroraNative/Abstract/Friends.cs b/AuroraNative/Abstract/Users/Friends.cs similarity index 100% rename from AuroraNative/Abstract/Friends.cs rename to AuroraNative/Abstract/Users/Friends.cs diff --git a/AuroraNative/EventArgs/Basic/Sender.cs b/AuroraNative/Abstract/Users/Sender.cs similarity index 98% rename from AuroraNative/EventArgs/Basic/Sender.cs rename to AuroraNative/Abstract/Users/Sender.cs index ef0404f..6bfb011 100644 --- a/AuroraNative/EventArgs/Basic/Sender.cs +++ b/AuroraNative/Abstract/Users/Sender.cs @@ -1,6 +1,6 @@ using Newtonsoft.Json; -namespace AuroraNative.EventArgs +namespace AuroraNative { /// /// 提供用于描述发送者信息的基础类, 该类是抽象的 diff --git a/AuroraNative/AuroraNative.csproj b/AuroraNative/AuroraNative.csproj index 3182789..e90a043 100644 --- a/AuroraNative/AuroraNative.csproj +++ b/AuroraNative/AuroraNative.csproj @@ -15,13 +15,13 @@ false false true - 0.2.0.0312 - 0.2.0.0312 + 1.0.0.0315 + 1.0.0.0315 Icon.png false AuroraNative AuroraNative - 0.2.0-alpha + 1.0.0-Beta true diff --git a/AuroraNative/AuroraNative.xml b/AuroraNative/AuroraNative.xml index 53e026a..79ebc0a 100644 --- a/AuroraNative/AuroraNative.xml +++ b/AuroraNative/AuroraNative.xml @@ -4,6 +4,527 @@ AuroraNative + + + 提供用于描述事件参数的基础类, 该类是抽象的 + + + + + 客户端ID + + + + + 设备名称 + + + + + 设备类型 + + + + + 初始化 类的新实例 + + 客户端ID + 设备名称 + 设备类型 + + + + 精华消息 抽象类 + + + + + 发送者QQ 号 + + + + + 发送者昵称 + + + + + 消息发送时间 + + + + + 操作者QQ 号 + + + + + 操作者昵称 + + + + + 精华设置时间 + + + + + 消息ID + + + + + 群文件 抽象类 + + + + + 文件ID + + + + + 文件名称 + + + + + 文件类型 + + + + + 文件大小 + + + + + 上传时间 + + + + + 过期时间,永久为零 + + + + + 最后修改时间 + + + + + 下载次数 + + + + + 上传者ID + + + + + 上传者名字 + + + + + 群文件夹 抽象类 + + + + + 文件夹ID + + + + + 文件夹名称 + + + + + 创建时间 + + + + + 创建者 + + + + + 创建者名称 + + + + + 子文件数量 + + + + + 群成员信息 抽象类 + + + + + 群号 + + + + + QQ号 + + + + + 昵称 + + + + + 群名片 + + + + + 现在人数 + + + + + 最大人数 + + + + + 地区 + + + + + 加群时间戳 + + + + + 最后发言时间戳 + + + + + 成员等级 + + + + + 角色 + + + + + 是否不良记录成员 + + + + + 专属头衔 + + + + + 专属头衔过期时间戳 + + + + + 是否允许修改群名片 + + + + + 群组 抽象类 + + + + + 群号 + + + + + 群名称 + + + + + 现在人数 + + + + + 最大人数 + + + + + 群荣誉详细信息 抽象类 + + + + + QQ号 + + + + + 昵称 + + + + + 头像URL + + + + + 荣誉描述 + + + + + 持续天数 + + + + + 群系统消息 - 消息列表 基抽象类 + + + + + 请求ID + + + + + 群号 + + + + + 群名称 + + + + + 是否已处理 + + + + + 处理者,未处理是0 + + + + + 群系统消息 - 邀请消息列表 抽象类 + + + + + 邀请者 + + + + + 邀请者昵称 + + + + + 群系统消息 - 进群消息列表 抽象类 + + + + + 请求者 + + + + + 请求者昵称 + + + + + 验证信息 + + + + + 消息 抽象类 + + + + + 匿名信息 + + + + + 字体 + + + + + 群号 + + + + + 消息内容 + + + + + 原始消息内容 + + + + + 消息ID + + + + + 消息序号 + + + + + 消息类型 + + + + + 消息事件主类型 + + + + + 消息事件子类型 + + + + + 收到事件的机器人QQ号 + + + + + 发送者 + + + + + 消息时间戳 + + + + + 发送者QQ号 + + + + + OCR结果信息 抽象类 + + + + + 文本 + + + + + 置信度 + + + + + 坐标 + + + + + 运行统计 抽象类 + + + + + 收到的数据包总数 + + + + + 发送的数据包总数 + + + + + 数据包丢失总数 + + + + + 接受信息总数 + + + + + 发送信息总数 + + + + + TCP 链接断开次数 + + + + + 账号掉线次数 + + + + + 提供用于描述匿名信息的基础类, 该类是抽象的 + + + + + 匿名用户 ID + + + + + 匿名用户名称 + + + + + 匿名用户 flag, 在调用禁言 API 时需要传入 + + + + + 初始化 类的新实例 + + 匿名用户 ID + 匿名用户名称 + 匿名用户 flag, 在调用禁言 API 时需要传入 + 好友 抽象类 @@ -24,6 +545,70 @@ 备注 + + + 提供用于描述发送者信息的基础类, 该类是抽象的 + + + + + 发送者 QQ 号 + + + + + 昵称 + + + + + 性别 + + + + + 年龄 + + + + + 群名片/备注 + + + + + 地区 + + + + + 成员等级 + + + + + 角色 + + + + + 专属头衔 + + + + + 初始化 类的新实例 + + 发送者 QQ 号 + 昵称 + 群名片/备注 + 性别 + 年龄 + 地区 + 成员等级 + 角色 + 专属头衔 + API 类 @@ -125,7 +710,7 @@ QQ号 禁言时间,单位秒默认:30分钟(1800秒) - + 群组匿名用户禁言 @@ -753,34 +1338,6 @@ 表示不输出日志 - - - 提供用于描述匿名信息的基础类, 该类是抽象的 - - - - - 匿名用户 ID - - - - - 匿名用户名称 - - - - - 匿名用户 flag, 在调用禁言 API 时需要传入 - - - - - 初始化 类的新实例 - - 匿名用户 ID - 匿名用户名称 - 匿名用户 flag, 在调用禁言 API 时需要传入 - 提供用于描述事件参数的基础类, 该类是抽象的 @@ -809,37 +1366,9 @@ 收到事件的机器人QQ号 上报类型 - - - 提供用于描述事件参数的基础类, 该类是抽象的 - - - - - 客户端ID - - - - - 设备名称 - - - - - 设备类型 - - - - - 初始化 类的新实例 - - 客户端ID - 设备名称 - 设备类型 - - 提供用于描述匿名信息的基础类, 该类是抽象的 + 提供用于描述文件数据的基础类, 该类是抽象的 @@ -877,70 +1406,6 @@ 下载链接 busid ( 目前不清楚有什么作用 ) - - - 提供用于描述发送者信息的基础类, 该类是抽象的 - - - - - 发送者 QQ 号 - - - - - 昵称 - - - - - 性别 - - - - - 年龄 - - - - - 群名片/备注 - - - - - 地区 - - - - - 成员等级 - - - - - 角色 - - - - - 专属头衔 - - - - - 初始化 类的新实例 - - 发送者 QQ 号 - 昵称 - 群名片/备注 - 性别 - 年龄 - 地区 - 成员等级 - 角色 - 专属头衔 - 提供用于描述消息事件中群聊消息事件参数的类 @@ -956,7 +1421,7 @@ 匿名消息 - + 初始化 类的新实例 @@ -1019,7 +1484,7 @@ 发送者信息 - + 初始化 类的新实例 @@ -1040,7 +1505,7 @@ 提供用于描述消息事件中私聊消息事件参数的类 - + 初始化 类的新实例 @@ -1136,7 +1601,7 @@ 当前是否在线 - + 初始化 类的新实例 diff --git a/AuroraNative/EventArgs/Basic/File.cs b/AuroraNative/EventArgs/Basic/File.cs index d0eb1d2..db42ca3 100644 --- a/AuroraNative/EventArgs/Basic/File.cs +++ b/AuroraNative/EventArgs/Basic/File.cs @@ -3,7 +3,7 @@ namespace AuroraNative.EventArgs { /// - /// 提供用于描述匿名信息的基础类, 该类是抽象的 + /// 提供用于描述文件数据的基础类, 该类是抽象的 /// public sealed class File { diff --git a/AuroraNative/WebSockets/BaseWebSocket.cs b/AuroraNative/WebSockets/BaseWebSocket.cs index 32af9e4..0bac87f 100644 --- a/AuroraNative/WebSockets/BaseWebSocket.cs +++ b/AuroraNative/WebSockets/BaseWebSocket.cs @@ -58,13 +58,18 @@ internal void Send(BaseAPI Json) internal async Task GetEventAsync() { - ArraySegment BytesReceived = new ArraySegment(new byte[5120]); + ArraySegment BytesReceived = new ArraySegment(new byte[10240]); WebSocketReceiveResult Result = await WebSocket.ReceiveAsync(BytesReceived, CancellationToken.None); - Json = JObject.Parse(Encoding.UTF8.GetString(BytesReceived.Array, 0, Result.Count)); + if (Result.Count == 0) {return;} + Json = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(BytesReceived.Array, 0, Result.Count)); if (Json.TryGetValue("echo", out JToken Token)) { - Api.TaskList[Json["echo"].ToString()] = Json; + if (Json.TryGetValue("status", out JToken Cache) && Cache.ToString() != "ok") { + Logger.Warning(Json.ToString(), $"{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}"); + } + + Api.TaskList[Token.ToString()] = Json; } else { diff --git a/AuroraNative/WebSockets/Server.cs b/AuroraNative/WebSockets/Server.cs index e04eade..ef5a104 100644 --- a/AuroraNative/WebSockets/Server.cs +++ b/AuroraNative/WebSockets/Server.cs @@ -103,8 +103,8 @@ internal override async void Feedback() 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未初始化异常,连接后需等待5秒..."); + Thread.Sleep(5000); Logger.Debug("go-cqhttp 初始化完毕!"); IsConnect = true; Api.Create(this);