Skip to content

Commit

Permalink
chore: 合并冲突
Browse files Browse the repository at this point in the history
  • Loading branch information
Yukari316 committed Jan 4, 2024
2 parents abd9e70 + 1971ee3 commit e4bf1d7
Show file tree
Hide file tree
Showing 8 changed files with 114 additions and 80 deletions.
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,19 @@
<img src="https://img.shields.io/github/stars/Yukari316/Sora?style=flat-square" alt="stars">
<img src="https://img.shields.io/github/actions/workflow/status/Hoshikawa-Kaguya/Sora/nuget.yml?branch=master&&style=flat-square" alt="workflow">
<a href="https://github.com/Mrs4s/go-cqhttp">
<img src="https://img.shields.io/badge/go--cqhttp-v1.0.0--rc4-blue?style=flat-square" alt="gocq-ver">
<img src="https://img.shields.io/badge/go--cqhttp-v1.1.0-blue?style=flat-square" alt="gocq-ver">
</a>
</h4>
</h1>

## 重要信息

[go-cqhttp](https://github.com/Mrs4s/go-cqhttp) 因为qq官方的一系列协议升级,可能后续会停止开发

详细的原因:[go-cqhttp#2471](https://github.com/Mrs4s/go-cqhttp/issues/2471)

目前的情况是,`gocq`能用就不要做任何迁移,如果一定要迁移,哈哈,我也不知道迁移到哪,替代的已经无了

## 文档

**=====本框架只支持Array的上报格式!=====**
Expand Down Expand Up @@ -59,11 +67,11 @@

这个框架将会一直以简单易用为主,也会向着更加便捷的方向进行开发

所以不会有什么 `起夜级` 的组件 比如:DI,AOP...
所以不会有什么特别复杂的功能

同时也不会将框架拆分为多个不同功能的包 ~~毕竟本来就没有什么功能~~

如果希望拥有 `指令路由` `多IM平台支持` `DI` 等等功能,推荐使用 [OneBot-Framework](https://github.com/ParaParty/OneBot-Framework)
如果希望拥有 `指令路由` `多IM平台支持` 等等功能,推荐使用 [OneBot-Framework](https://github.com/ParaParty/OneBot-Framework)

这个项目同时也是我学习C#这个语言的过程中的产物,所以里面可能会部分拉高血压的代码 ~~屎山~~

Expand Down
93 changes: 45 additions & 48 deletions Sora/Command/CommandManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Sora.Attributes;
using Sora.Attributes.Command;
using Sora.Entities;
Expand Down Expand Up @@ -62,8 +63,6 @@ public sealed class CommandManager

private readonly List<DynamicCommandInfo> _dynamicCommands = new();

private readonly ConcurrentDictionary<Type, dynamic> _instanceDict = new();

private readonly ConcurrentDictionary<string, bool> _commandEnableFlagDict = new();

#endregion
Expand Down Expand Up @@ -99,24 +98,24 @@ public void MappingCommands(Assembly assembly)
return;

//查找所有的指令集
Dictionary<Type, MethodInfo[]> cmdSeries = assembly.GetExportedTypes()
//获取指令组
.Where(type => type.IsDefined(typeof(CommandSeries), false)
&& type.IsClass)
.Select(type => (type,
type.GetMethods() //指令参数方法合法性检查
.Where(method => method
.CheckCommandMethodLegality())
.ToArray()))
.ToDictionary(methods => methods.type,
methods => methods.Item2);
Dictionary<Type, MethodInfo[]> cmdSeries =
assembly.GetExportedTypes()
//获取指令组
.Where(type => type.IsDefined(typeof(CommandSeries), false)
&& type.IsClass)
//指令参数方法合法性检查
.Select(type => (type, type.GetMethods()
.Where(method => method.CheckCommandMethodLegality()).ToArray()))
//将每个类的方法整合
.ToDictionary(methods => methods.type,
methods => methods.Item2);

foreach ((Type classType, MethodInfo[] methodInfos) in cmdSeries)
{
//获取指令属性
CommandSeries seriesAttr = classType.GetCustomAttribute(typeof(CommandSeries)) as CommandSeries
?? throw new
NullReferenceException("CommandSeries attribute is null with unknown reason");
CommandSeries seriesAttr =
classType.GetCustomAttribute(typeof(CommandSeries)) as CommandSeries
?? throw new NullReferenceException("CommandSeries attribute is null with unknown reason");

string prefix = string.IsNullOrEmpty(seriesAttr.GroupPrefix) ? string.Empty : seriesAttr.GroupPrefix;
string seriesName = string.IsNullOrEmpty(seriesAttr.SeriesName) ? classType.Name : seriesAttr.SeriesName;
Expand Down Expand Up @@ -404,16 +403,18 @@ internal async ValueTask CommandAdapter(BaseMessageEventArgs eventArgs)
Log.Debug("Command", "invoke command method");
try
{
dynamic instance = null;
if (commandInfo.InstanceType != null)
if (!GetInstance(commandInfo.InstanceType, out instance))
{
Log.Error("Command", $"获取指令实例失败 [t:{commandInfo.InstanceType}]");
continue;
}

if (isAsync && commandInfo.MethodInfo.ReturnType != typeof(void))
await commandInfo.MethodInfo.Invoke(commandInfo.InstanceType == null
? null
: _instanceDict[commandInfo.InstanceType],
new object[] { eventArgs });
await commandInfo.MethodInfo.Invoke(instance, new object[] { eventArgs });
else
commandInfo.MethodInfo.Invoke(commandInfo.InstanceType == null
? null
: _instanceDict[commandInfo.InstanceType],
new object[] { eventArgs });
commandInfo.MethodInfo.Invoke(instance, new object[] { eventArgs });
}
catch (Exception err)
{
Expand Down Expand Up @@ -547,25 +548,15 @@ private bool CheckAndCreateInstance(Type classType)
return false;
}

//检查是否已创建过实例
if (_instanceDict.Any(ins => ins.Key == classType))
//检查是否已注册过实例
if (ServiceHelper.Services.Any(a => a.ServiceType == classType))
return true;

try
{
//创建实例
object instance = classType.CreateInstance();

//添加实例
return _instanceDict.TryAdd(classType
?? throw new ArgumentNullException(nameof(classType), "get null class type"),
instance);
}
catch (Exception e)
{
Log.Error("Command", $"在创建实例[{classType?.Name}]时发生错误:{Log.ErrorLogBuilder(e)}");
return false;
}
Log.Debug("Command", $"reg class:{classType.FullName}");

Check warning on line 555 in Sora/Command/CommandManager.cs

View workflow job for this annotation

GitHub Actions / build

Dereference of a possibly null reference.

Check warning on line 555 in Sora/Command/CommandManager.cs

View workflow job for this annotation

GitHub Actions / build

Dereference of a possibly null reference.
//注册实例
object instance = classType.CreateInstance();
ServiceHelper.Services.AddSingleton(classType, instance);
return ServiceHelper.Services.Any(a => a.ServiceType == classType);
}

#endregion
Expand Down Expand Up @@ -704,14 +695,20 @@ public List<string> GetCommandList()
[Reviewed("XiaoHe321", "2021-03-28 20:45")]
public bool GetInstance<T>(out T instance)
{
if (_instanceDict.Any(type => type.Key == typeof(T)) && _instanceDict[typeof(T)] is T outVal)
{
instance = outVal;
return true;
}
instance = ServiceHelper.GetService<T>();
return instance is not null;
}

instance = default;
return false;
/// <summary>
/// 获取已注册过的实例
/// </summary>
/// <param name="instance">实例</param>
/// <param name="type">Type</param>
/// <returns>获取是否成功</returns>
public bool GetInstance(Type type, out dynamic instance)
{
instance = ServiceHelper.GetService(type);
return instance is not null;
}

/// <summary>
Expand Down
12 changes: 5 additions & 7 deletions Sora/Net/SoraWebsocketClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,8 @@ internal SoraWebsocketClient(ClientConfig config, Action<Exception> crashAction
//全局异常事件
AppDomain.CurrentDomain.UnhandledException += (_, args) =>
{
if (crashAction == null)
Helper.FriendlyException(args);
else
crashAction(args.ExceptionObject as Exception);
Log.UnhandledExceptionLog(args);
crashAction(args.ExceptionObject as Exception);
};
_isReady = true;
}
Expand Down Expand Up @@ -140,11 +138,11 @@ public async ValueTask StartService()
ErrorReconnectTimeout = Config.ReconnectTimeOut
};
//消息接收事件
_subClientMessageReceived = Client.MessageReceived.Subscribe(msg => Task.Run(() =>
_subClientMessageReceived = Client.MessageReceived.Subscribe(msg => Task.Run(async () =>
{
if (_disposed)
if (_disposed || string.IsNullOrEmpty(msg.Text))
return;
Event.Adapter(JObject.Parse(msg.Text ?? "{}"), ServiceId);
await Event.Adapter(JObject.Parse(msg.Text), ServiceId);
}));
//连接断开事件
_subClientDisconnectionHappened = Client.DisconnectionHappened.Subscribe(info => Task.Run(() =>
Expand Down
17 changes: 11 additions & 6 deletions Sora/Net/SoraWebsocketServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,8 @@ internal SoraWebsocketServer(ServerConfig config, Action<Exception> crashAction
//全局异常事件
AppDomain.CurrentDomain.UnhandledException += (_, args) =>
{
if (crashAction == null)
Helper.FriendlyException(args);
else
crashAction(args.ExceptionObject as Exception);
Log.UnhandledExceptionLog(args);
crashAction(args.ExceptionObject as Exception);
};
_isReady = true;
}
Expand Down Expand Up @@ -186,11 +184,18 @@ private void SocketEvent(IWebSocketConnection socket)
Log.Info("Sora", $"客户端连接被关闭[{socket.ConnectionInfo.ClientIpAddress}:{socket.ConnectionInfo.ClientPort}]");
};
//上报接收
socket.OnMessage = message => Task.Run(() =>
socket.OnMessage = message => Task.Run(async () =>
{
if (_disposed || !_isRunning)
return;
Event.Adapter(JObject.Parse(message), socket.ConnectionInfo.Id);
try
{
await Event.Adapter(JObject.Parse(message), socket.ConnectionInfo.Id);
}
catch (Exception e)
{
Helper.FriendlyException(e);
}
});
}

Expand Down
22 changes: 11 additions & 11 deletions Sora/OnebotAdapter/EventAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ public delegate ValueTask EventAsyncCallBackHandler<in TEventArgs>(string eventT
/// </summary>
/// <param name="messageJson">消息json对象</param>
/// <param name="connection">客户端链接接口</param>
internal void Adapter(JObject messageJson, Guid connection)
internal async ValueTask Adapter(JObject messageJson, Guid connection)
{
if (!ServiceRecord.Exists(ServiceId))
{
Expand All @@ -222,19 +222,19 @@ internal void Adapter(JObject messageJson, Guid connection)
{
//元事件类型
case "meta_event":
MetaAdapter(messageJson, connection);
await MetaAdapter(messageJson, connection);
break;
case "message":
MessageAdapter(messageJson, connection);
await MessageAdapter(messageJson, connection);
break;
case "request":
RequestAdapter(messageJson, connection);
await RequestAdapter(messageJson, connection);
break;
case "notice":
NoticeAdapter(messageJson, connection);
await NoticeAdapter(messageJson, connection);
break;
case "message_sent":
SelfMessageAdapter(messageJson, connection);
await SelfMessageAdapter(messageJson, connection);
break;
default:
//尝试从响应中获取标识符
Expand All @@ -258,7 +258,7 @@ internal void Adapter(JObject messageJson, Guid connection)
/// </summary>
/// <param name="messageJson">消息</param>
/// <param name="connection">连接GUID</param>
private async void MetaAdapter(JObject messageJson, Guid connection)
private async ValueTask MetaAdapter(JObject messageJson, Guid connection)
{
switch (TryGetJsonValue(messageJson, "meta_event_type"))
{
Expand Down Expand Up @@ -336,7 +336,7 @@ await OnClientConnect("Meta Event",
/// </summary>
/// <param name="messageJson">消息</param>
/// <param name="connection">连接GUID</param>
private async void MessageAdapter(JObject messageJson, Guid connection)
private async ValueTask MessageAdapter(JObject messageJson, Guid connection)
{
switch (TryGetJsonValue(messageJson, "message_type"))
{
Expand Down Expand Up @@ -409,7 +409,7 @@ private async void MessageAdapter(JObject messageJson, Guid connection)
/// </summary>
/// <param name="messageJson">消息</param>
/// <param name="connection">连接GUID</param>
private async void SelfMessageAdapter(JObject messageJson, Guid connection)
private async ValueTask SelfMessageAdapter(JObject messageJson, Guid connection)
{
switch (TryGetJsonValue(messageJson, "message_type"))
{
Expand Down Expand Up @@ -457,7 +457,7 @@ await OnSelfPrivateMessage("Message",
/// </summary>
/// <param name="messageJson">消息</param>
/// <param name="connection">连接GUID</param>
private async void RequestAdapter(JObject messageJson, Guid connection)
private async ValueTask RequestAdapter(JObject messageJson, Guid connection)
{
switch (TryGetJsonValue(messageJson, "request_type"))
{
Expand Down Expand Up @@ -518,7 +518,7 @@ await OnGroupRequest("Request",
/// </summary>
/// <param name="messageJson">消息</param>
/// <param name="connection">连接GUID</param>
private async void NoticeAdapter(JObject messageJson, Guid connection)
private async ValueTask NoticeAdapter(JObject messageJson, Guid connection)
{
switch (TryGetJsonValue(messageJson, "notice_type"))
{
Expand Down
1 change: 1 addition & 0 deletions Sora/Sora.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

<ItemGroup>
<PackageReference Include="Fleck" Version="1.2.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="System.Reactive" Version="6.0.0" />
<PackageReference Include="Websocket.Client" Version="5.0.0" />
Expand Down
11 changes: 6 additions & 5 deletions Sora/Util/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,16 @@ public static class Helper
/// <summary>
/// 友好的崩溃提示(x)
/// </summary>
[Reviewed("nidbCN", "2021-03-24 19:31")]
internal static void FriendlyException(UnhandledExceptionEventArgs args)
internal static void FriendlyException(Exception e)
{
Exception e = args.ExceptionObject as Exception;

if (e is JsonSerializationException)
{
Log.Error("Sora", "Json反序列化时出现错误,可能是go-cqhttp配置出现问题。请把go-cqhttp配置中的post_message_format从string改为array。");
return;
}

Log.UnhandledExceptionLog(args);
Log.Error(e, "Sora", "发生未知错误");
throw e;
}

#endregion
Expand Down
24 changes: 24 additions & 0 deletions Sora/Util/ServiceHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System;
using Microsoft.Extensions.DependencyInjection;

namespace Sora.Util;

internal static class ServiceHelper
{
public static readonly IServiceCollection Services = new ServiceCollection();

public static IServiceScope CreateScope()
{
return Services.BuildServiceProvider().CreateScope();
}

public static T GetService<T>()
{
return Services.BuildServiceProvider().GetService<T>();
}

public static dynamic GetService(Type type)
{
return Services.BuildServiceProvider().GetService(type);
}
}

0 comments on commit e4bf1d7

Please sign in to comment.