03/13 Last Update

This commit is contained in:
悠静萝莉
2021-03-13 22:37:29 +08:00
parent c6bb234e52
commit de4fe14d74
11 changed files with 165 additions and 38 deletions

View File

@@ -1,9 +1,11 @@
using AuroraNative.EventArgs; using AuroraNative.EventArgs;
using AuroraNative.Exceptions;
using AuroraNative.WebSockets; using AuroraNative.WebSockets;
using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Caching.Memory;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using System; using System;
using System.Collections.Generic;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@@ -43,7 +45,14 @@ namespace AuroraNative
/// <param name="WebSocket">WebSocket句柄</param> /// <param name="WebSocket">WebSocket句柄</param>
private Api(BaseWebSocket WebSocket) private Api(BaseWebSocket WebSocket)
{ {
this.WebSocket = WebSocket; if (WebSocket != null)
{
this.WebSocket = WebSocket;
}
else
{
throw new WebSocketException(-1, "传入的WebSocket不可为空");
}
} }
#endregion #endregion
@@ -101,7 +110,7 @@ namespace AuroraNative
{ "group_id", GroupID }, { "group_id", GroupID },
{ "messages", Message } { "messages", Message }
}; };
//TODO 需要做CQ码转换
SendCallVoid(new BaseAPI("send_group_forward_msg", Params, "SendGroupForwardMessage:" + Utils.NowTimeSteamp())); SendCallVoid(new BaseAPI("send_group_forward_msg", Params, "SendGroupForwardMessage:" + Utils.NowTimeSteamp()));
} }
@@ -129,7 +138,7 @@ namespace AuroraNative
case "group": case "group":
Params.Add("group_id", GroupID); Params.Add("group_id", GroupID);
break; break;
default: case null:
if (QID != 0) if (QID != 0)
{ {
Params.Add("user_id", QID); Params.Add("user_id", QID);
@@ -139,6 +148,8 @@ namespace AuroraNative
Params.Add("group_id", GroupID); Params.Add("group_id", GroupID);
} }
break; break;
default:
throw new Exceptions.JsonException(-1, "传入的参数不符合预期");
} }
return await SendCallMessageID(new BaseAPI("send_msg", Params, "SendMsg:" + Utils.NowTimeSteamp())); return await SendCallMessageID(new BaseAPI("send_msg", Params, "SendMsg:" + Utils.NowTimeSteamp()));
@@ -158,9 +169,18 @@ namespace AuroraNative
/// </summary> /// </summary>
/// <param name="MessageID">消息ID</param> /// <param name="MessageID">消息ID</param>
/// <returns>错误返回null,成功返回JObject</returns> /// <returns>错误返回null,成功返回JObject</returns>
public async Task<JObject> GetMsg(string MessageID) public async Task<Dictionary<string, object>> 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<string, object>() {
{"MessageID",Json.Value<int>("message_id")},
{"RealID",Json.Value<int>("real_id")},
{"Sender",Json.Value<Sender>("sender")},
{"Time",Json.Value<int>("time")},
{"Message",Json.Value<string>("message")},
{"RawMessage",Json.Value<string>("raw_message")}
};
} }
/// <summary> /// <summary>
@@ -170,6 +190,7 @@ namespace AuroraNative
/// <returns>错误返回null,成功返回JObject</returns> /// <returns>错误返回null,成功返回JObject</returns>
public async Task<JObject> GetForwardMsg(string MessageID) public async Task<JObject> GetForwardMsg(string MessageID)
{ {
//TODO 等转发合并消息做完后需要修改这个方法的返回类型
return await SendCallObject(new BaseAPI("get_forward_msg", new JObject() { { "message_id", MessageID } }, "GetForwardMsg:" + Utils.NowTimeSteamp())); 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) internal static Api Create(BaseWebSocket WebSocket)
{ {
Api api = new Api(WebSocket); try
Cache.Set($"API{AppDomain.CurrentDomain.Id}", api); {
return api; 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() internal static void Destroy()

View File

@@ -40,9 +40,14 @@
</None> </None>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="5.0.0" /> <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="5.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.*" /> <PackageReference Include="Newtonsoft.Json" Version="12.*" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net5.0'">
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="5.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
</ItemGroup>
</Project> </Project>

View File

@@ -43,7 +43,7 @@
<param name="AutoEscape">是否转义<para>默认false</para></param> <param name="AutoEscape">是否转义<para>默认false</para></param>
<returns>返回消息ID错误返回-1</returns> <returns>返回消息ID错误返回-1</returns>
</member> </member>
<member name="M:AuroraNative.Api.SendGroupForwardMessage(System.Int64,Newtonsoft.Json.Linq.JArray)"> <member name="M:AuroraNative.Api.SendGroupForwardMessage(System.Int64,System.Object)">
<summary> <summary>
转发合并消息 - 群 转发合并消息 - 群
</summary> </summary>

View File

@@ -0,0 +1,61 @@
using AuroraNative.EventArgs;
using Newtonsoft.Json;
using System;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
namespace AuroraNative
{
/// <summary>
/// Enum和Description特性互转 转换器
/// </summary>
internal class EnumDescriptionConverter : JsonConverter
{
/// <summary>
/// 当属性的值为枚举类型时才使用转换器
/// </summary>
/// <param name="objectType">目标类型</param>
/// <returns>返回布尔值</returns>
public override bool CanConvert(Type objectType) => objectType == typeof(Enum);
/// <summary>
/// 获取枚举的描述值
/// </summary>
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 : "");
}
/// <summary>
/// 通过Description获取枚举值
/// </summary>
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;
}
}
}

View File

@@ -1,5 +1,4 @@
using AuroraNative.EventArgs; using AuroraNative.EventArgs;
using AuroraNative.WebSockets;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
namespace AuroraNative namespace AuroraNative

View File

@@ -23,8 +23,10 @@ namespace AuroraNative
/// </summary> /// </summary>
/// <param name="Message">要输出的信息</param> /// <param name="Message">要输出的信息</param>
/// <param name="MethodName">输出的方法名,可选传入</param> /// <param name="MethodName">输出的方法名,可选传入</param>
public static void Debug(string Message, string MethodName = null) { public static void Debug(string Message, string MethodName = null)
if (LogLevel <= LogLevel.Debug) { {
if (LogLevel <= LogLevel.Debug)
{
Output(Message, ConsoleColor.Gray, LogLevel.Debug, MethodName); Output(Message, ConsoleColor.Gray, LogLevel.Debug, MethodName);
} }
} }
@@ -72,12 +74,15 @@ namespace AuroraNative
#region ---- #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; Console.ForegroundColor = Color;
if (MethodName != null) { if (MethodName != null)
{
Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss fff") + $" [{Level}]" + $" [{MethodName}] " + Message); 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.WriteLine(DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss") + $" [{Level}] " + Message);
} }
Console.ForegroundColor = ConsoleColor.White; Console.ForegroundColor = ConsoleColor.White;
@@ -89,7 +94,8 @@ namespace AuroraNative
/// <summary> /// <summary>
/// 表示日志信息等级的枚举 /// 表示日志信息等级的枚举
/// </summary> /// </summary>
public enum LogLevel { public enum LogLevel
{
/// <summary> /// <summary>
/// 表示输出日志的等级是 "调试" 级别 /// 表示输出日志的等级是 "调试" 级别
/// </summary> /// </summary>

View File

@@ -13,21 +13,21 @@ namespace AuroraNative
/// 通过 枚举Description 转为枚举 /// 通过 枚举Description 转为枚举
/// </summary> /// </summary>
/// <typeparam name="T">枚举</typeparam> /// <typeparam name="T">枚举</typeparam>
/// <param name="description">需要转换的Description</param> /// <param name="Description">需要转换的Description</param>
/// <returns>返回该枚举</returns> /// <returns>返回该枚举</returns>
public static T GetEnumByDescription<T>(string description) where T : Enum public static T GetEnumByDescription<T>(string Description) where T : Enum
{ {
System.Reflection.FieldInfo[] fields = typeof(T).GetFields(); System.Reflection.FieldInfo[] fields = typeof(T).GetFields();
foreach (System.Reflection.FieldInfo field in fields) foreach (System.Reflection.FieldInfo field in fields)
{ {
object[] objs = field.GetCustomAttributes(typeof(DescriptionAttribute), false); 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); return (T)field.GetValue(null);
} }
} }
throw new ArgumentException(string.Format("{0} 未能找到对应的枚举.", description), "Description"); throw new ArgumentException(string.Format("{0} 未能找到对应的枚举.", Description), nameof(Description));
} }
/// <summary> /// <summary>

View File

@@ -32,7 +32,14 @@ namespace AuroraNative.WebSockets
/// <param name="Json">传输Json格式的文本</param> /// <param name="Json">传输Json格式的文本</param>
public void Send(BaseAPI Json) public void Send(BaseAPI Json)
{ {
WebSocket.SendAsync(new ArraySegment<byte>(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(Json, Formatting.None))), WebSocketMessageType.Text, true, CancellationToken.None); try
{
WebSocket.SendAsync(new ArraySegment<byte>(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() internal async Task GetEventAsync()

View File

@@ -50,7 +50,8 @@ namespace AuroraNative.WebSockets
public bool Create() public bool Create()
{ {
Logger.Debug("正向WebSocket已创建准备连接...", $"{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}"); 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 try
{ {
WebSocket = new ClientWebSocket(); WebSocket = new ClientWebSocket();
@@ -62,6 +63,9 @@ namespace AuroraNative.WebSockets
if (WebSocket.State == WebSocketState.Open) if (WebSocket.State == WebSocketState.Open)
{ {
Logger.Info("已连接至 go-cqhttp 服务器!"); Logger.Info("已连接至 go-cqhttp 服务器!");
Logger.Debug("防止由于go-cqhttp未初始化异常连接后需等待2秒...");
Thread.Sleep(2000);
Logger.Debug("go-cqhttp 初始化完毕!");
Task.Run(Feedback); Task.Run(Feedback);
Api.Create(this); Api.Create(this);
return true; return true;
@@ -91,7 +95,8 @@ namespace AuroraNative.WebSockets
Api.Destroy(); Api.Destroy();
Logger.Info("已销毁正向WebSocket"); Logger.Info("已销毁正向WebSocket");
} }
catch(Exception e) { catch (Exception e)
{
Logger.Error("销毁正向WebSocket失败\n" + e.Message, $"{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}"); Logger.Error("销毁正向WebSocket失败\n" + e.Message, $"{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}");
} }
} }

View File

@@ -61,11 +61,13 @@ namespace AuroraNative.WebSockets
Listener.Start(); Listener.Start();
Logger.Info("开始监听来自 go-cqhttp 客户端的连接..."); Logger.Info("开始监听来自 go-cqhttp 客户端的连接...");
Task.Run(Feedback); Task.Run(Feedback);
while (!IsConnect) { while (!IsConnect)
{
Thread.Sleep(100); Thread.Sleep(100);
} }
} }
catch(HttpListenerException) { catch (HttpListenerException)
{
Logger.Error("无法启动监听服务器,请确保使用管理员权限运行。否则无法监听!", $"{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}"); Logger.Error("无法启动监听服务器,请确保使用管理员权限运行。否则无法监听!", $"{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}");
Console.ReadKey(); Console.ReadKey();
Environment.Exit(0); Environment.Exit(0);
@@ -78,13 +80,16 @@ namespace AuroraNative.WebSockets
public void Dispose() public void Dispose()
{ {
Logger.Debug($"准备销毁反向WebSocket...", $"{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}"); Logger.Debug($"准备销毁反向WebSocket...", $"{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}");
try { try
{
Listener.Stop(); Listener.Stop();
WebSocket.Dispose(); WebSocket.Dispose();
WebSocket.Abort(); WebSocket.Abort();
Api.Destroy(); Api.Destroy();
Logger.Info("已销毁反向WebSocket"); Logger.Info("已销毁反向WebSocket");
} catch (Exception e) { }
catch (Exception e)
{
Logger.Error("销毁反向WebSocket失败\n" + e.Message, $"{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}"); Logger.Error("销毁反向WebSocket失败\n" + e.Message, $"{MethodBase.GetCurrentMethod().DeclaringType.Name}.{MethodBase.GetCurrentMethod().Name}");
} }
} }
@@ -97,19 +102,29 @@ namespace AuroraNative.WebSockets
{ {
while (true) while (true)
{ {
HttpListenerContext Context = await Listener.GetContextAsync(); try
if (Context.Request.IsWebSocketRequest)
{ {
Logger.Info("收到来自 go-cqhttp 客户端的连接!连接已建立!"); HttpListenerContext Context = await Listener.GetContextAsync();
HttpListenerWebSocketContext SocketContext = await Context.AcceptWebSocketAsync(null); if (Context.Request.IsWebSocketRequest)
WebSocket = SocketContext.WebSocket;
IsConnect = true;
Api.Create(this);
while (WebSocket.State == WebSocketState.Open)
{ {
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}");
}
} }
} }

View File

@@ -75,4 +75,4 @@
### 使用到的开源库 ### 使用到的开源库
[Newtonsoft.Json](https://www.newtonsoft.com/json) [Newtonsoft.Json](https://www.newtonsoft.com/json) | [Microsoft.Extensions.Caching.Memory](https://www.nuget.org/packages/Microsoft.Extensions.Caching.Memory/5.0.0)