From 4c800a5b82e5e93077cc71c42e73613685f9d922 Mon Sep 17 00:00:00 2001 From: DarkRRb <177549718+DarkRRb@users.noreply.github.com> Date: Sun, 13 Oct 2024 16:32:53 +0800 Subject: [PATCH 01/19] [Core] fix no custom status info (#634) --- Lagrange.Core/Internal/Service/System/FetchUserInfoService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lagrange.Core/Internal/Service/System/FetchUserInfoService.cs b/Lagrange.Core/Internal/Service/System/FetchUserInfoService.cs index 314330c21..e4745c167 100644 --- a/Lagrange.Core/Internal/Service/System/FetchUserInfoService.cs +++ b/Lagrange.Core/Internal/Service/System/FetchUserInfoService.cs @@ -65,7 +65,7 @@ protected override bool Parse(Span input, BotKeystore keystore, BotAppInfo CustomStatus? customs = null; if (bytesProperties[27406].Length != 0) { - using var stream = new MemoryStream(); + using var stream = new MemoryStream(bytesProperties[27406]); customs = Serializer.Deserialize(stream); } From 6abd758fa77ad991b84a377b3a56fe7177a2a54c Mon Sep 17 00:00:00 2001 From: DarkRRb <177549718+DarkRRb@users.noreply.github.com> Date: Sun, 13 Oct 2024 16:40:01 +0800 Subject: [PATCH 02/19] [Core] style beautify (#635) --- .../Service/System/FetchUserInfoService.cs | 64 ++++++++++++++++++- 1 file changed, 61 insertions(+), 3 deletions(-) diff --git a/Lagrange.Core/Internal/Service/System/FetchUserInfoService.cs b/Lagrange.Core/Internal/Service/System/FetchUserInfoService.cs index e4745c167..1cd274367 100644 --- a/Lagrange.Core/Internal/Service/System/FetchUserInfoService.cs +++ b/Lagrange.Core/Internal/Service/System/FetchUserInfoService.cs @@ -17,8 +17,46 @@ namespace Lagrange.Core.Internal.Service.System; [Service("OidbSvcTrpcTcp.0xfe1_2")] internal class FetchUserInfoService : BaseService { - private static readonly List _keys = new() { - new() { Key = 20002 }, new() { Key = 27394 }, new() { Key = 20009 }, new() { Key = 20031 }, new() { Key = 101 }, new() { Key = 103 }, new() { Key = 102 }, new() { Key = 20022 }, new() { Key = 20023 }, new() { Key = 20024 }, new() { Key = 24002 }, new() { Key = 27037 }, new() { Key = 27049 }, new() { Key = 20011 }, new() { Key = 20016 }, new() { Key = 20021 }, new() { Key = 20003 }, new() { Key = 20004 }, new() { Key = 20005 }, new() { Key = 20006 }, new() { Key = 20020 }, new() { Key = 20026 }, new() { Key = 24007 }, new() { Key = 104 }, new() { Key = 105 }, new() { Key = 42432 }, new() { Key = 42362 }, new() { Key = 41756 }, new() { Key = 41757 }, new() { Key = 42257 }, new() { Key = 27372 }, new() { Key = 42315 }, new() { Key = 107 }, new() { Key = 45160 }, new() { Key = 45161 }, new() { Key = 27406 }, new() { Key = 62026 }, new() { Key = 20037 } + private static readonly List _keys = new() + { + new() { Key = 20002 }, + new() { Key = 27394 }, + new() { Key = 20009 }, + new() { Key = 20031 }, + new() { Key = 101 }, + new() { Key = 103 }, + new() { Key = 102 }, + new() { Key = 20022 }, + new() { Key = 20023 }, + new() { Key = 20024 }, + new() { Key = 24002 }, + new() { Key = 27037 }, + new() { Key = 27049 }, + new() { Key = 20011 }, + new() { Key = 20016 }, + new() { Key = 20021 }, + new() { Key = 20003 }, + new() { Key = 20004 }, + new() { Key = 20005 }, + new() { Key = 20006 }, + new() { Key = 20020 }, + new() { Key = 20026 }, + new() { Key = 24007 }, + new() { Key = 104 }, + new() { Key = 105 }, + new() { Key = 42432 }, + new() { Key = 42362 }, + new() { Key = 41756 }, + new() { Key = 41757 }, + new() { Key = 42257 }, + new() { Key = 27372 }, + new() { Key = 42315 }, + new() { Key = 107 }, + new() { Key = 45160 }, + new() { Key = 45161 }, + new() { Key = 27406 }, + new() { Key = 62026 }, + new() { Key = 20037 } }; protected override bool Build(FetchUserInfoEvent input, BotKeystore keystore, BotAppInfo appInfo, @@ -82,7 +120,27 @@ protected override bool Parse(Span input, BotKeystore keystore, BotAppInfo string? school = Encoding.UTF8.GetString(bytesProperties[20021]); string? sign = Encoding.UTF8.GetString(bytesProperties[102]); - var info = new BotUserInfo(payload.Body.Body.Uin, nickname, avatarurl, birthday, city, country, school, numberProperties[20037], reg, (GenderInfo)numberProperties[20009], qid, numberProperties[105], sign, new() { StatusId = statusId, FaceId = customs?.FaceId ?? 0, Msg = customs?.Msg }); + var info = new BotUserInfo( + payload.Body.Body.Uin, + nickname, + avatarurl, + birthday, + city, + country, + school, + numberProperties[20037], + reg, + (GenderInfo)numberProperties[20009], + qid, + numberProperties[105], + sign, + new() + { + StatusId = statusId, + FaceId = customs?.FaceId ?? 0, + Msg = customs?.Msg + } + ); output = FetchUserInfoEvent.Result(0, info); extraEvents = null; From 450599fb09d51c038328fe52f2a7c130c7642ba7 Mon Sep 17 00:00:00 2001 From: DarkRRb <177549718+DarkRRb@users.noreply.github.com> Date: Mon, 14 Oct 2024 00:44:14 +0800 Subject: [PATCH 03/19] [Core] fix images sent by `Lagrange.Core` do not show up in group essence (#636) --- Lagrange.Core/Message/Entity/ImageEntity.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lagrange.Core/Message/Entity/ImageEntity.cs b/Lagrange.Core/Message/Entity/ImageEntity.cs index 05d157a7b..57fa98dbe 100644 --- a/Lagrange.Core/Message/Entity/ImageEntity.cs +++ b/Lagrange.Core/Message/Entity/ImageEntity.cs @@ -81,7 +81,7 @@ IEnumerable IMessageEntity.PackElement() { ServiceType = 48, PbElem = common.ToArray(), - BusinessType = 10, + BusinessType = IsGroup ? 20u : 10u, } } }; From 93c35bc5605d0f8565ca9e26d909233247d3e985 Mon Sep 17 00:00:00 2001 From: DarkRRb <177549718+DarkRRb@users.noreply.github.com> Date: Mon, 14 Oct 2024 13:14:01 +0800 Subject: [PATCH 04/19] [Core] fix images sent by `Lagrange.Core` do not show up in group essence (#637) --- Lagrange.Core/Message/Entity/ImageEntity.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Lagrange.Core/Message/Entity/ImageEntity.cs b/Lagrange.Core/Message/Entity/ImageEntity.cs index 57fa98dbe..bc4924771 100644 --- a/Lagrange.Core/Message/Entity/ImageEntity.cs +++ b/Lagrange.Core/Message/Entity/ImageEntity.cs @@ -70,6 +70,8 @@ public ImageEntity(Stream stream) IEnumerable IMessageEntity.PackElement() { + bool isGroup = MsgInfo?.MsgInfoBody is { Count: > 0 } body && body[0].HashSum.TroopSource?.GroupUin != null; + var common = MsgInfo.Serialize(); var elems = new Elem[] @@ -81,7 +83,7 @@ IEnumerable IMessageEntity.PackElement() { ServiceType = 48, PbElem = common.ToArray(), - BusinessType = IsGroup ? 20u : 10u, + BusinessType = isGroup ? 20u : 10u, } } }; From f9db6de50597fc97fdc3be460250c23892f2f905 Mon Sep 17 00:00:00 2001 From: Linwenxuan04 Date: Wed, 16 Oct 2024 21:08:43 -0400 Subject: [PATCH 05/19] [Core] Corrected Protobuf Field Name --- .../Internal/Packets/Message/ContentHead.cs | 22 ++++++++++--------- Lagrange.Core/Message/MessagePacker.cs | 18 +++++++-------- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/Lagrange.Core/Internal/Packets/Message/ContentHead.cs b/Lagrange.Core/Internal/Packets/Message/ContentHead.cs index 57b7125b4..8bc2c1bb2 100644 --- a/Lagrange.Core/Internal/Packets/Message/ContentHead.cs +++ b/Lagrange.Core/Internal/Packets/Message/ContentHead.cs @@ -7,27 +7,29 @@ namespace Lagrange.Core.Internal.Packets.Message; [ProtoContract] internal class ContentHead { - [ProtoMember(1)] public uint Type { get; set; } + [ProtoMember(1)] public uint Type { get; set; } // 消息类型 - [ProtoMember(2)] public uint? SubType { get; set; } + [ProtoMember(2)] public uint? SubType { get; set; } // 消息子类型(0x211\0x2dc\0x210等系统消息的子类型,取值同c2c_cmd) - [ProtoMember(3)] public uint? DivSeq { get; set; } + [ProtoMember(3)] public uint? C2CCmd { get; set; } // c2c消息子类型 - [ProtoMember(4)] public long? MsgId { get; set; } + [ProtoMember(4)] public long? Random { get; set; } [ProtoMember(5)] public uint? Sequence { get; set; } [ProtoMember(6)] public long? Timestamp { get; set; } - [ProtoMember(7)] public long? Field7 { get; set; } + [ProtoMember(7)] public long? PkgNum { get; set; } // 分包数目,消息需要分包发送时该值不为1 - [ProtoMember(8)] public uint? Field8 { get; set; } + [ProtoMember(8)] public uint? PkgIndex { get; set; } // 当前分包索引,从 0开始 + + [ProtoMember(9)] public uint? DivSeq { get; set; } // 消息分包的序列号,同一条消息的各个分包的 div_seq 相同 + + [ProtoMember(10)] public uint AutoReply { get; set; } - [ProtoMember(9)] public uint? Field9 { get; set; } + [ProtoMember(11)] public uint? NTMsgSeq { get; set; } // 两个uin之间c2c消息唯一递增seq - [ProtoMember(11)] public uint? FriendSequence { get; set; } - - [ProtoMember(12)] public ulong? NewId { get; set; } + [ProtoMember(12)] public ulong? MsgUid { get; set; } [ProtoMember(15)] public ForwardHead? Forward { get; set; } } \ No newline at end of file diff --git a/Lagrange.Core/Message/MessagePacker.cs b/Lagrange.Core/Message/MessagePacker.cs index c46216bff..d978ea739 100644 --- a/Lagrange.Core/Message/MessagePacker.cs +++ b/Lagrange.Core/Message/MessagePacker.cs @@ -195,7 +195,7 @@ public static MessageChain ParsePrivateFile(PushMsgBody message) { Type = 1, // regarded as the const SubType = 0, - DivSeq = 0 + C2CCmd = 0 }, Body = new MessageBody { RichText = new RichText { Elems = new List() } }, ClientSequence = chain.ClientSequence, @@ -224,13 +224,13 @@ public static MessageChain ParsePrivateFile(PushMsgBody message) { Type = (uint)(chain.IsGroup ? 82 : 9), SubType = chain.IsGroup ? null : 4, - DivSeq = chain.IsGroup ? null : 4, - MsgId = (uint)(chain.MessageId & 0xFFFFFFFF), + C2CCmd = chain.IsGroup ? null : 4, + Random = (uint)(chain.MessageId & 0xFFFFFFFF), Sequence = (uint?)Random.Shared.Next(1000000, 9999999), Timestamp = (chain.Time == default ? DateTimeOffset.Now : new(chain.Time)).ToUnixTimeSeconds(), - Field7 = 1, - Field8 = 0, - Field9 = 0, + PkgNum = 1, + PkgIndex = 0, + DivSeq = 0, Forward = new ForwardHead { Field1 = 0, @@ -251,16 +251,16 @@ private static MessageChain ParseChain(PushMsgBody message) message.ResponseHead.ToUid ?? string.Empty, message.ResponseHead.FromUid ?? string.Empty, message.ResponseHead.ToUin, - message.ContentHead.FriendSequence ?? 0, + message.ContentHead.NTMsgSeq ?? 0, message.ContentHead.Sequence ?? 0, - message.ContentHead.NewId ?? 0, + message.ContentHead.MsgUid ?? 0, message.ContentHead.Type == 141 ? MessageChain.MessageType.Temp : MessageChain.MessageType.Friend) : new MessageChain( message.ResponseHead.Grp.GroupUin, message.ResponseHead.FromUin, message.ContentHead.Sequence ?? 0, - message.ContentHead.NewId ?? 0); + message.ContentHead.MsgUid ?? 0); if (message.Body?.RichText?.Elems is { } elems) chain.Elements.AddRange(elems); From 28d0cdd58c8d76887b5d080413b89433985ee33a Mon Sep 17 00:00:00 2001 From: DarkRRb <177549718+DarkRRb@users.noreply.github.com> Date: Thu, 17 Oct 2024 11:10:17 +0800 Subject: [PATCH 06/19] [OneBot] fix litedb auto EmptyStringToNull and TrimWhitespace (#641) --- Lagrange.OneBot/LagrangeAppBuilder.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Lagrange.OneBot/LagrangeAppBuilder.cs b/Lagrange.OneBot/LagrangeAppBuilder.cs index c254ef3e6..a190db713 100644 --- a/Lagrange.OneBot/LagrangeAppBuilder.cs +++ b/Lagrange.OneBot/LagrangeAppBuilder.cs @@ -115,6 +115,9 @@ public LagrangeAppBuilder ConfigureOneBot() { var logger = provider.GetRequiredService>(); + BsonMapper.Global.TrimWhitespace = false; + BsonMapper.Global.EmptyStringToNull = false; + string path = Configuration["ConfigPath:Database"] ?? $"lagrange-{Configuration["Account:Uin"]}.db"; var db = new LiteDatabase(path) From 5270314d7e7cb657a955e0bc66f4495107a8be3e Mon Sep 17 00:00:00 2001 From: DarkRRb <177549718+DarkRRb@users.noreply.github.com> Date: Fri, 18 Oct 2024 17:48:12 +0800 Subject: [PATCH 07/19] [All] fix get msg cannot obtain resid (#642) --- Lagrange.Core/Message/Entity/MultiMsgEntity.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lagrange.Core/Message/Entity/MultiMsgEntity.cs b/Lagrange.Core/Message/Entity/MultiMsgEntity.cs index 85ba77754..b966d9e22 100644 --- a/Lagrange.Core/Message/Entity/MultiMsgEntity.cs +++ b/Lagrange.Core/Message/Entity/MultiMsgEntity.cs @@ -14,7 +14,7 @@ public class MultiMsgEntity : IMessageEntity { private static readonly XmlSerializer Serializer = new(typeof(MultiMessage)); - internal string? ResId { get; set; } + public string? ResId { get; set; } [Obsolete("No more need for group uin")] public uint? GroupUin { get; set; } @@ -118,7 +118,7 @@ IEnumerable IMessageEntity.PackElement() { if (elem.RichMsg is { ServiceId: 35, Template1: not null } richMsg) { - var xml = ZCompression.ZDecompress(richMsg.Template1[1..]); + var xml = ZCompression.ZDecompress(richMsg.Template1.AsSpan(1)); if ((MultiMessage?)Serializer.Deserialize(new MemoryStream(xml)) is { } xmlEntity) { return new MultiMsgEntity(xmlEntity.ResId); From f9b26f46215c8b9cd9bcc9fd9d8c15f05cfcf503 Mon Sep 17 00:00:00 2001 From: DarkRRb <177549718+DarkRRb@users.noreply.github.com> Date: Sat, 19 Oct 2024 12:48:28 +0800 Subject: [PATCH 08/19] [All] fix get msg cannot obtain face id (#643) --- Lagrange.Core/Message/Entity/FaceEntity.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Lagrange.Core/Message/Entity/FaceEntity.cs b/Lagrange.Core/Message/Entity/FaceEntity.cs index c149e3569..0e56d6279 100644 --- a/Lagrange.Core/Message/Entity/FaceEntity.cs +++ b/Lagrange.Core/Message/Entity/FaceEntity.cs @@ -8,10 +8,10 @@ namespace Lagrange.Core.Message.Entity; [MessageElement(typeof(Face)), MessageElement(typeof(CommonElem))] public class FaceEntity : IMessageEntity { - public ushort FaceId { get; } - - public bool IsLargeFace { get; } - + public ushort FaceId { get; set; } + + public bool IsLargeFace { get; set; } + public FaceEntity() { } public FaceEntity(ushort faceId, bool isLargeFace) @@ -19,7 +19,7 @@ public FaceEntity(ushort faceId, bool isLargeFace) FaceId = faceId; IsLargeFace = isLargeFace; } - + IEnumerable IMessageEntity.PackElement() { if (IsLargeFace) @@ -51,7 +51,7 @@ IEnumerable IMessageEntity.PackElement() } }; } - + return new Elem[] { new() { Face = new Face { Index = FaceId } } }; } @@ -63,10 +63,10 @@ IEnumerable IMessageEntity.PackElement() if (faceId != null) return new FaceEntity((ushort)faceId, false); } - if (elems.CommonElem is { ServiceType:37, PbElem: not null } common) + if (elems.CommonElem is { ServiceType: 37, PbElem: not null } common) { var qFace = Serializer.Deserialize(common.PbElem.AsSpan()); - + ushort? faceId = (ushort?)qFace.FaceId; if (faceId != null) return new FaceEntity((ushort)faceId, true); } @@ -76,7 +76,7 @@ IEnumerable IMessageEntity.PackElement() var qSmallFace = Serializer.Deserialize(append.PbElem.AsSpan()); return new FaceEntity((ushort)qSmallFace.FaceId, false); } - + return null; } From b42d7c32769f2d23122a8a2f6b0518e1487f0534 Mon Sep 17 00:00:00 2001 From: DarkRRb <177549718+DarkRRb@users.noreply.github.com> Date: Sun, 20 Oct 2024 09:51:10 +0800 Subject: [PATCH 09/19] [Core] Supported APIs about group todo (#644) --- .../Common/Entity/BotGetGroupTodoResult.cs | 24 ++++++ .../Common/Interface/Api/GroupExt.cs | 13 ++++ .../Logic/Implementation/OperationLogic.cs | 76 ++++++++++++++++--- .../Event/Action/GroupFinishTodoEvent.cs | 21 +++++ .../Event/Action/GroupGetTodoEvent.cs | 38 ++++++++++ .../Event/Action/GroupRemoveTodoEvent.cs | 21 +++++ .../Event/Action/GroupSetTodoEvent.cs | 24 ++++++ .../Oidb/Request/OidbSvcTrpcTcp0xF8E_1.cs | 12 +++ .../Oidb/Request/OidbSvcTrpcTcp0xF90.cs | 14 ++++ .../Response/OidbSvcTrpcTcp0xF8E_1Response.cs | 20 +++++ .../Service/Action/GroupFinishTodoService.cs | 37 +++++++++ .../Service/Action/GroupGetTodoService.cs | 46 +++++++++++ .../Service/Action/GroupRemoveTodoService.cs | 37 +++++++++ .../Service/Action/GroupSetTodoService.cs | 38 ++++++++++ 14 files changed, 410 insertions(+), 11 deletions(-) create mode 100644 Lagrange.Core/Common/Entity/BotGetGroupTodoResult.cs create mode 100644 Lagrange.Core/Internal/Event/Action/GroupFinishTodoEvent.cs create mode 100644 Lagrange.Core/Internal/Event/Action/GroupGetTodoEvent.cs create mode 100644 Lagrange.Core/Internal/Event/Action/GroupRemoveTodoEvent.cs create mode 100644 Lagrange.Core/Internal/Event/Action/GroupSetTodoEvent.cs create mode 100644 Lagrange.Core/Internal/Packets/Service/Oidb/Request/OidbSvcTrpcTcp0xF8E_1.cs create mode 100644 Lagrange.Core/Internal/Packets/Service/Oidb/Request/OidbSvcTrpcTcp0xF90.cs create mode 100644 Lagrange.Core/Internal/Packets/Service/Oidb/Response/OidbSvcTrpcTcp0xF8E_1Response.cs create mode 100644 Lagrange.Core/Internal/Service/Action/GroupFinishTodoService.cs create mode 100644 Lagrange.Core/Internal/Service/Action/GroupGetTodoService.cs create mode 100644 Lagrange.Core/Internal/Service/Action/GroupRemoveTodoService.cs create mode 100644 Lagrange.Core/Internal/Service/Action/GroupSetTodoService.cs diff --git a/Lagrange.Core/Common/Entity/BotGetGroupTodoResult.cs b/Lagrange.Core/Common/Entity/BotGetGroupTodoResult.cs new file mode 100644 index 000000000..d47cf398f --- /dev/null +++ b/Lagrange.Core/Common/Entity/BotGetGroupTodoResult.cs @@ -0,0 +1,24 @@ +namespace Lagrange.Core.Common.Entity; + +[Serializable] +public class BotGetGroupTodoResult +{ + public int Retcode { get; } + + public string? ResultMessage { get; } + + public uint GroupUin { get; } + + public uint Sequence { get; } + + public string Preview { get; } + + public BotGetGroupTodoResult(int retcode, string? resultMessage, uint groupUin, uint sequence, string preview) + { + Retcode = retcode; + ResultMessage = resultMessage; + GroupUin = groupUin; + Sequence = sequence; + Preview = preview; + } +} diff --git a/Lagrange.Core/Common/Interface/Api/GroupExt.cs b/Lagrange.Core/Common/Interface/Api/GroupExt.cs index 35dbc2ddf..6e7270e9f 100644 --- a/Lagrange.Core/Common/Interface/Api/GroupExt.cs +++ b/Lagrange.Core/Common/Interface/Api/GroupExt.cs @@ -45,6 +45,19 @@ public static Task KickGroupMember(this BotContext bot, uint groupUin, uin public static Task SetGroupAdmin(this BotContext bot, uint groupUin, uint targetUin, bool isAdmin) => bot.ContextCollection.Business.OperationLogic.SetGroupAdmin(groupUin, targetUin, isAdmin); + // 300204 Check group manager:Not an administrator + public static Task<(int, string?)> SetGroupTodo(this BotContext bot, uint groupUin, uint sequence) + => bot.ContextCollection.Business.OperationLogic.SetGroupTodo(groupUin, sequence); + + public static Task<(int, string?)> RemoveGroupTodo(this BotContext bot, uint groupUin) + => bot.ContextCollection.Business.OperationLogic.RemoveGroupTodo(groupUin); + + public static Task<(int, string?)> FinishGroupTodo(this BotContext bot, uint groupUin) + => bot.ContextCollection.Business.OperationLogic.FinishGroupTodo(groupUin); + + public static Task GetGroupTodo(this BotContext bot, uint groupUin) + => bot.ContextCollection.Business.OperationLogic.GetGroupTodo(groupUin); + public static Task SetGroupBot(this BotContext bot, uint targetUin, uint On, uint groupUin) => bot.ContextCollection.Business.OperationLogic.SetGroupBot(targetUin, On, groupUin); diff --git a/Lagrange.Core/Internal/Context/Logic/Implementation/OperationLogic.cs b/Lagrange.Core/Internal/Context/Logic/Implementation/OperationLogic.cs index d4bb7e817..fdf82a6aa 100644 --- a/Lagrange.Core/Internal/Context/Logic/Implementation/OperationLogic.cs +++ b/Lagrange.Core/Internal/Context/Logic/Implementation/OperationLogic.cs @@ -81,11 +81,65 @@ public async Task SetGroupAdmin(uint groupUin, uint targetUin, bool isAdmi string? uid = await Collection.Business.CachingLogic.ResolveUid(groupUin, targetUin); if (uid == null) return false; - var muteGroupMemberEvent = GroupSetAdminEvent.Create(groupUin, uid, isAdmin); - var events = await Collection.Business.SendEvent(muteGroupMemberEvent); + var setGroupAdminEvent = GroupSetAdminEvent.Create(groupUin, uid, isAdmin); + var events = await Collection.Business.SendEvent(setGroupAdminEvent); return events.Count != 0 && ((GroupSetAdminEvent)events[0]).ResultCode == 0; } + public async Task<(int, string?)> SetGroupTodo(uint groupUin, uint sequence) + { + var setGroupTodoEvent = GroupSetTodoEvent.Create(groupUin, sequence); + var events = await Collection.Business.SendEvent(setGroupTodoEvent); + + if (events.Count == 0) return (-1, "No Events"); + + var @event = (GroupSetTodoEvent)events[0]; + + return (@event.ResultCode, @event.ResultMessage); + } + + public async Task<(int, string?)> RemoveGroupTodo(uint groupUin) + { + var setGroupTodoEvent = GroupRemoveTodoEvent.Create(groupUin); + var events = await Collection.Business.SendEvent(setGroupTodoEvent); + + if (events.Count == 0) return (-1, "No Event"); + + var @event = (GroupRemoveTodoEvent)events[0]; + + return (@event.ResultCode, @event.ResultMessage); + } + + public async Task<(int, string?)> FinishGroupTodo(uint groupUin) + { + var setGroupTodoEvent = GroupFinishTodoEvent.Create(groupUin); + var events = await Collection.Business.SendEvent(setGroupTodoEvent); + + if (events.Count == 0) return (-1, "No Event"); + + var @event = (GroupFinishTodoEvent)events[0]; + + return (@event.ResultCode, @event.ResultMessage); + } + + public async Task GetGroupTodo(uint groupUin) + { + var setGroupTodoEvent = GroupGetTodoEvent.Create(groupUin); + var events = await Collection.Business.SendEvent(setGroupTodoEvent); + + if (events.Count == 0) return new(-1, "No Event", 0, 0, string.Empty); + + var @event = (GroupGetTodoEvent)events[0]; + + return new( + @event.ResultCode, + @event.ResultMessage, + @event.GroupUin, + @event.Sequence, + @event.Preview + ); + } + public async Task SetGroupBot(uint BotId, uint On, uint groupUin) { var muteBotEvent = GroupSetBotEvent.Create(BotId, On, groupUin); @@ -342,9 +396,9 @@ async Task ResolveUid(string? uid) result.TargetUin = uins[0]; result.SourceUin = uins[1]; } - + return resolved; - + async Task ResolveUid(string? uid) { if (uid == null) return 0; @@ -603,24 +657,24 @@ public Task FriendShake(uint friendUin, PokeFaceType type, uint s public async Task SetAvatar(ImageEntity avatar) { if (avatar.ImageStream == null) return false; - + var highwayUrlEvent = HighwayUrlEvent.Create(); var highwayUrlResults = await Collection.Business.SendEvent(highwayUrlEvent); if (highwayUrlResults.Count == 0) return false; - + var ticket = ((HighwayUrlEvent)highwayUrlResults[0]).SigSession; var md5 = avatar.ImageStream.Value.Md5().UnHex(); return await Collection.Highway.UploadSrcByStreamAsync(90, avatar.ImageStream.Value, ticket, md5, Array.Empty()); } - + public async Task GroupSetAvatar(uint groupUin, ImageEntity avatar) { if (avatar.ImageStream == null) return false; - + var highwayUrlEvent = HighwayUrlEvent.Create(); var highwayUrlResults = await Collection.Business.SendEvent(highwayUrlEvent); if (highwayUrlResults.Count == 0) return false; - + var ticket = ((HighwayUrlEvent)highwayUrlResults[0]).SigSession; var md5 = avatar.ImageStream.Value.Md5().UnHex(); var extra = new GroupAvatarExtra @@ -633,13 +687,13 @@ public async Task GroupSetAvatar(uint groupUin, ImageEntity avatar) }.Serialize().ToArray(); return await Collection.Highway.UploadSrcByStreamAsync(3000, avatar.ImageStream.Value, ticket, md5, extra); } - + public async Task<(uint, uint)> GroupRemainAtAll(uint groupUin) { var groupRemainAtAllEvent = FetchGroupAtAllRemainEvent.Create(groupUin); var results = await Collection.Business.SendEvent(groupRemainAtAllEvent); if (results.Count == 0) return (0, 0); - + var ret = (FetchGroupAtAllRemainEvent)results[0]; return (ret.RemainAtAllCountForUin, ret.RemainAtAllCountForGroup); } diff --git a/Lagrange.Core/Internal/Event/Action/GroupFinishTodoEvent.cs b/Lagrange.Core/Internal/Event/Action/GroupFinishTodoEvent.cs new file mode 100644 index 000000000..6ab54cf1f --- /dev/null +++ b/Lagrange.Core/Internal/Event/Action/GroupFinishTodoEvent.cs @@ -0,0 +1,21 @@ +namespace Lagrange.Core.Internal.Event.Action; + +internal class GroupFinishTodoEvent : ProtocolEvent +{ + public uint GroupUin { get; set; } + + public string? ResultMessage { get; set; } + + private GroupFinishTodoEvent(uint groupUin) : base(0) + { + GroupUin = groupUin; + } + + private GroupFinishTodoEvent(int resultCode, string? message) : base(resultCode) { + ResultMessage = message; + } + + public static GroupFinishTodoEvent Create(uint groupUin) => new(groupUin); + + public static GroupFinishTodoEvent Result(int resultCode, string? message) => new(resultCode, message); +} \ No newline at end of file diff --git a/Lagrange.Core/Internal/Event/Action/GroupGetTodoEvent.cs b/Lagrange.Core/Internal/Event/Action/GroupGetTodoEvent.cs new file mode 100644 index 000000000..2d34c96da --- /dev/null +++ b/Lagrange.Core/Internal/Event/Action/GroupGetTodoEvent.cs @@ -0,0 +1,38 @@ +namespace Lagrange.Core.Internal.Event.Action; + +internal class GroupGetTodoEvent : ProtocolEvent +{ + public uint GroupUin { get; set; } + + public uint Sequence { get; set; } + + public string Preview { get; set; } + + public string? ResultMessage { get; set; } + + private GroupGetTodoEvent(uint groupUin) : base(0) { + GroupUin = groupUin; + Preview = string.Empty; + } + + private GroupGetTodoEvent(int resultCode, string? message, uint groupUin, uint sequence, string preview) : base(resultCode) + { + ResultMessage = message; + + GroupUin = groupUin; + Sequence = sequence; + Preview = preview; + } + + private GroupGetTodoEvent(int resultCode, string? message) : base(resultCode) + { + ResultMessage = message; + Preview = string.Empty; + } + + public static GroupGetTodoEvent Create(uint groupUin) => new(groupUin); + + public static GroupGetTodoEvent Result(int resultCode, string? message) => Result(resultCode, message, 0, 0, string.Empty); + + public static GroupGetTodoEvent Result(int resultCode, string? message, uint groupUin, uint sequence, string preview) => new(resultCode, message, groupUin, sequence, preview); +} \ No newline at end of file diff --git a/Lagrange.Core/Internal/Event/Action/GroupRemoveTodoEvent.cs b/Lagrange.Core/Internal/Event/Action/GroupRemoveTodoEvent.cs new file mode 100644 index 000000000..0534d2f98 --- /dev/null +++ b/Lagrange.Core/Internal/Event/Action/GroupRemoveTodoEvent.cs @@ -0,0 +1,21 @@ +namespace Lagrange.Core.Internal.Event.Action; + +internal class GroupRemoveTodoEvent : ProtocolEvent +{ + public uint GroupUin { get; set; } + + public string? ResultMessage { get; set; } + + private GroupRemoveTodoEvent(uint groupUin) : base(0) + { + GroupUin = groupUin; + } + + private GroupRemoveTodoEvent(int resultCode, string? message) : base(resultCode) { + ResultMessage = message; + } + + public static GroupRemoveTodoEvent Create(uint groupUin) => new(groupUin); + + public static GroupRemoveTodoEvent Result(int resultCode, string? message) => new(resultCode, message); +} \ No newline at end of file diff --git a/Lagrange.Core/Internal/Event/Action/GroupSetTodoEvent.cs b/Lagrange.Core/Internal/Event/Action/GroupSetTodoEvent.cs new file mode 100644 index 000000000..e7b81948c --- /dev/null +++ b/Lagrange.Core/Internal/Event/Action/GroupSetTodoEvent.cs @@ -0,0 +1,24 @@ +namespace Lagrange.Core.Internal.Event.Action; + +internal class GroupSetTodoEvent : ProtocolEvent +{ + public uint GroupUin { get; set; } + + public uint Sequence { get; set; } + + public string? ResultMessage { get; set; } + + private GroupSetTodoEvent(uint groupUin, uint sequence) : base(0) + { + GroupUin = groupUin; + Sequence = sequence; + } + + private GroupSetTodoEvent(int resultCode, string? message) : base(resultCode) { + ResultMessage = message; + } + + public static GroupSetTodoEvent Create(uint groupUin, uint sequence) => new(groupUin, sequence); + + public static GroupSetTodoEvent Result(int resultCode, string? message) => new(resultCode, message); +} \ No newline at end of file diff --git a/Lagrange.Core/Internal/Packets/Service/Oidb/Request/OidbSvcTrpcTcp0xF8E_1.cs b/Lagrange.Core/Internal/Packets/Service/Oidb/Request/OidbSvcTrpcTcp0xF8E_1.cs new file mode 100644 index 000000000..724e9d178 --- /dev/null +++ b/Lagrange.Core/Internal/Packets/Service/Oidb/Request/OidbSvcTrpcTcp0xF8E_1.cs @@ -0,0 +1,12 @@ +using ProtoBuf; + +namespace Lagrange.Core.Internal.Packets.Service.Oidb.Request; + +// ReSharper disable InconsistentNaming +#pragma warning disable CS8618 + +[ProtoContract] +internal class OidbSvcTrpcTcp0xF8E_1 +{ + [ProtoMember(1)] public uint GroupUin { get; set; } +} \ No newline at end of file diff --git a/Lagrange.Core/Internal/Packets/Service/Oidb/Request/OidbSvcTrpcTcp0xF90.cs b/Lagrange.Core/Internal/Packets/Service/Oidb/Request/OidbSvcTrpcTcp0xF90.cs new file mode 100644 index 000000000..e22e6354e --- /dev/null +++ b/Lagrange.Core/Internal/Packets/Service/Oidb/Request/OidbSvcTrpcTcp0xF90.cs @@ -0,0 +1,14 @@ +using ProtoBuf; + +namespace Lagrange.Core.Internal.Packets.Service.Oidb.Request; + +// ReSharper disable InconsistentNaming +#pragma warning disable CS8618 + +[ProtoContract] +internal class OidbSvcTrpcTcp0xF90 +{ + [ProtoMember(1)] public uint GroupUin { get; set; } + + [ProtoMember(2)] public uint Sequence { get; set; } +} \ No newline at end of file diff --git a/Lagrange.Core/Internal/Packets/Service/Oidb/Response/OidbSvcTrpcTcp0xF8E_1Response.cs b/Lagrange.Core/Internal/Packets/Service/Oidb/Response/OidbSvcTrpcTcp0xF8E_1Response.cs new file mode 100644 index 000000000..bf756f0a6 --- /dev/null +++ b/Lagrange.Core/Internal/Packets/Service/Oidb/Response/OidbSvcTrpcTcp0xF8E_1Response.cs @@ -0,0 +1,20 @@ +using ProtoBuf; + +namespace Lagrange.Core.Internal.Packets.Service.Oidb.Response; +#pragma warning disable CS8618 + +[ProtoContract] +internal class OidbSvcTrpcTcp0xF8E_1Response +{ + [ProtoMember(1)] public OidbSvcTrpcTcp0xF8E_1ResponseBody Body { get; set; } +} + +[ProtoContract] +internal class OidbSvcTrpcTcp0xF8E_1ResponseBody +{ + [ProtoMember(1)] public uint GroupUin { get; set; } + + [ProtoMember(2)] public uint Sequence { get; set; } + + [ProtoMember(6)] public string Preview { get; set; } +} diff --git a/Lagrange.Core/Internal/Service/Action/GroupFinishTodoService.cs b/Lagrange.Core/Internal/Service/Action/GroupFinishTodoService.cs new file mode 100644 index 000000000..48af9de5a --- /dev/null +++ b/Lagrange.Core/Internal/Service/Action/GroupFinishTodoService.cs @@ -0,0 +1,37 @@ +using Lagrange.Core.Common; +using Lagrange.Core.Internal.Event; +using Lagrange.Core.Internal.Event.Action; +using Lagrange.Core.Internal.Packets.Service.Oidb; +using Lagrange.Core.Internal.Packets.Service.Oidb.Request; +using Lagrange.Core.Utility.Extension; +using ProtoBuf; + +namespace Lagrange.Core.Internal.Service.Action; + +[EventSubscribe(typeof(GroupFinishTodoEvent))] +[Service("OidbSvcTrpcTcp.0xf90_2")] +internal class GroupFinishTodoService : BaseService +{ + protected override bool Build(GroupFinishTodoEvent input, BotKeystore keystore, BotAppInfo appInfo, + BotDeviceInfo device, out Span output, out List>? extraPackets) + { + var packet = new OidbSvcTrpcTcpBase(new OidbSvcTrpcTcp0xF90 + { + GroupUin = input.GroupUin, + }, 0xF90, 2); + + output = packet.Serialize(); + extraPackets = null; + return true; + } + + protected override bool Parse(Span input, BotKeystore keystore, BotAppInfo appInfo, BotDeviceInfo device, + out GroupFinishTodoEvent output, out List? extraEvents) + { + var packet = Serializer.Deserialize>(input); + + output = GroupFinishTodoEvent.Result((int)packet.ErrorCode, packet.ErrorMsg); + extraEvents = null; + return true; + } +} \ No newline at end of file diff --git a/Lagrange.Core/Internal/Service/Action/GroupGetTodoService.cs b/Lagrange.Core/Internal/Service/Action/GroupGetTodoService.cs new file mode 100644 index 000000000..70a212a6c --- /dev/null +++ b/Lagrange.Core/Internal/Service/Action/GroupGetTodoService.cs @@ -0,0 +1,46 @@ +using Lagrange.Core.Common; +using Lagrange.Core.Internal.Event; +using Lagrange.Core.Internal.Event.Action; +using Lagrange.Core.Internal.Packets.Service.Oidb; +using Lagrange.Core.Internal.Packets.Service.Oidb.Request; +using Lagrange.Core.Internal.Packets.Service.Oidb.Response; +using Lagrange.Core.Utility.Extension; +using ProtoBuf; + +namespace Lagrange.Core.Internal.Service.Action; + +[EventSubscribe(typeof(GroupGetTodoEvent))] +[Service("OidbSvcTrpcTcp.0xf8e_1")] +internal class GroupGetTodoService : BaseService +{ + protected override bool Build(GroupGetTodoEvent input, BotKeystore keystore, BotAppInfo appInfo, + BotDeviceInfo device, out Span output, out List>? extraPackets) + { + var packet = new OidbSvcTrpcTcpBase(new OidbSvcTrpcTcp0xF8E_1 + { + GroupUin = input.GroupUin, + }, 0xF8E, 1); + + output = packet.Serialize(); + extraPackets = null; + return true; + } + + protected override bool Parse(Span input, BotKeystore keystore, BotAppInfo appInfo, BotDeviceInfo device, + out GroupGetTodoEvent output, out List? extraEvents) + { + var packet = Serializer.Deserialize>(input); + + output = packet.ErrorCode != 0 + ? GroupGetTodoEvent.Result((int)packet.ErrorCode, packet.ErrorMsg) + : GroupGetTodoEvent.Result( + (int)packet.ErrorCode, + packet.ErrorMsg, + packet.Body.Body.GroupUin, + packet.Body.Body.Sequence, + packet.Body.Body.Preview + ); + extraEvents = null; + return true; + } +} \ No newline at end of file diff --git a/Lagrange.Core/Internal/Service/Action/GroupRemoveTodoService.cs b/Lagrange.Core/Internal/Service/Action/GroupRemoveTodoService.cs new file mode 100644 index 000000000..5f9d1fe2d --- /dev/null +++ b/Lagrange.Core/Internal/Service/Action/GroupRemoveTodoService.cs @@ -0,0 +1,37 @@ +using Lagrange.Core.Common; +using Lagrange.Core.Internal.Event; +using Lagrange.Core.Internal.Event.Action; +using Lagrange.Core.Internal.Packets.Service.Oidb; +using Lagrange.Core.Internal.Packets.Service.Oidb.Request; +using Lagrange.Core.Utility.Extension; +using ProtoBuf; + +namespace Lagrange.Core.Internal.Service.Action; + +[EventSubscribe(typeof(GroupRemoveTodoEvent))] +[Service("OidbSvcTrpcTcp.0xf90_3")] +internal class GroupRemoveTodoService : BaseService +{ + protected override bool Build(GroupRemoveTodoEvent input, BotKeystore keystore, BotAppInfo appInfo, + BotDeviceInfo device, out Span output, out List>? extraPackets) + { + var packet = new OidbSvcTrpcTcpBase(new OidbSvcTrpcTcp0xF90 + { + GroupUin = input.GroupUin, + }, 0xF90, 3); + + output = packet.Serialize(); + extraPackets = null; + return true; + } + + protected override bool Parse(Span input, BotKeystore keystore, BotAppInfo appInfo, BotDeviceInfo device, + out GroupRemoveTodoEvent output, out List? extraEvents) + { + var packet = Serializer.Deserialize>(input); + + output = GroupRemoveTodoEvent.Result((int)packet.ErrorCode, packet.ErrorMsg); + extraEvents = null; + return true; + } +} \ No newline at end of file diff --git a/Lagrange.Core/Internal/Service/Action/GroupSetTodoService.cs b/Lagrange.Core/Internal/Service/Action/GroupSetTodoService.cs new file mode 100644 index 000000000..12fd6ae6c --- /dev/null +++ b/Lagrange.Core/Internal/Service/Action/GroupSetTodoService.cs @@ -0,0 +1,38 @@ +using Lagrange.Core.Common; +using Lagrange.Core.Internal.Event; +using Lagrange.Core.Internal.Event.Action; +using Lagrange.Core.Internal.Packets.Service.Oidb; +using Lagrange.Core.Internal.Packets.Service.Oidb.Request; +using Lagrange.Core.Utility.Extension; +using ProtoBuf; + +namespace Lagrange.Core.Internal.Service.Action; + +[EventSubscribe(typeof(GroupSetTodoEvent))] +[Service("OidbSvcTrpcTcp.0xf90_1")] +internal class GroupSetTodoService : BaseService +{ + protected override bool Build(GroupSetTodoEvent input, BotKeystore keystore, BotAppInfo appInfo, + BotDeviceInfo device, out Span output, out List>? extraPackets) + { + var packet = new OidbSvcTrpcTcpBase(new OidbSvcTrpcTcp0xF90 + { + GroupUin = input.GroupUin, + Sequence = input.Sequence + }, 0xF90, 1); + + output = packet.Serialize(); + extraPackets = null; + return true; + } + + protected override bool Parse(Span input, BotKeystore keystore, BotAppInfo appInfo, BotDeviceInfo device, + out GroupSetTodoEvent output, out List? extraEvents) + { + var packet = Serializer.Deserialize>(input); + + output = GroupSetTodoEvent.Result((int)packet.ErrorCode, packet.ErrorMsg); + extraEvents = null; + return true; + } +} \ No newline at end of file From 0b5e038b94b8e0c2a3c71f771d848c4ee56f4f2b Mon Sep 17 00:00:00 2001 From: Decrabbityyy <99632363+Decrabbityyy@users.noreply.github.com> Date: Mon, 21 Oct 2024 11:57:40 +0800 Subject: [PATCH 10/19] [Core] Fix group mute always is false (#647) --- Lagrange.Core/Internal/Service/Message/PushMessageService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lagrange.Core/Internal/Service/Message/PushMessageService.cs b/Lagrange.Core/Internal/Service/Message/PushMessageService.cs index 76fabecac..bf471e4fb 100644 --- a/Lagrange.Core/Internal/Service/Message/PushMessageService.cs +++ b/Lagrange.Core/Internal/Service/Message/PushMessageService.cs @@ -183,7 +183,7 @@ private static void ProcessEvent0x2DC(Span payload, PushMsg msg, List(content.AsSpan()); if (mute.Data.State.TargetUid == null) { - var groupMuteEvent = GroupSysMuteEvent.Result(mute.GroupUin, mute.OperatorUid, mute.Data.State.Duration == uint.MaxValue); + var groupMuteEvent = GroupSysMuteEvent.Result(mute.GroupUin, mute.OperatorUid, mute.Data.State.Duration !=0); extraEvents.Add(groupMuteEvent); } else From 853385aa07b253b082ca422b7ea18dcb9b9013dd Mon Sep 17 00:00:00 2001 From: Xeron <2398003522@qq.com> Date: Mon, 21 Oct 2024 18:55:50 +0800 Subject: [PATCH 11/19] [fix] Fixed conversion between timestamp and datetime (#646) --- .../Internal/Service/System/FetchMembersService.cs | 6 +++--- .../Core/Entity/Action/Response/OneBotGetMessageResponse.cs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Lagrange.Core/Internal/Service/System/FetchMembersService.cs b/Lagrange.Core/Internal/Service/System/FetchMembersService.cs index b51966625..5c499c029 100644 --- a/Lagrange.Core/Internal/Service/System/FetchMembersService.cs +++ b/Lagrange.Core/Internal/Service/System/FetchMembersService.cs @@ -54,9 +54,9 @@ protected override bool Parse(Span input, BotKeystore keystore, BotAppInfo member.MemberCard.MemberCard, member.MemberName, member.SpecialTitle ?? "", - DateTimeOffset.FromUnixTimeSeconds(member.JoinTimestamp).DateTime, - DateTimeOffset.FromUnixTimeSeconds(member.LastMsgTimestamp).DateTime, - DateTimeOffset.FromUnixTimeSeconds(member.ShutUpTimestamp ?? 0).DateTime)).ToList(); + DateTimeOffset.FromUnixTimeSeconds(member.JoinTimestamp).LocalDateTime, + DateTimeOffset.FromUnixTimeSeconds(member.LastMsgTimestamp).LocalDateTime, + DateTimeOffset.FromUnixTimeSeconds(member.ShutUpTimestamp ?? 0).LocalDateTime)).ToList(); output = FetchMembersEvent.Result(members, response.Body.Token); extraEvents = null; diff --git a/Lagrange.OneBot/Core/Entity/Action/Response/OneBotGetMessageResponse.cs b/Lagrange.OneBot/Core/Entity/Action/Response/OneBotGetMessageResponse.cs index c910ae780..9a68cadc6 100644 --- a/Lagrange.OneBot/Core/Entity/Action/Response/OneBotGetMessageResponse.cs +++ b/Lagrange.OneBot/Core/Entity/Action/Response/OneBotGetMessageResponse.cs @@ -6,7 +6,7 @@ namespace Lagrange.OneBot.Core.Entity.Action.Response; [Serializable] public class OneBotGetMessageResponse(DateTime time, string messageType, int messageId, OneBotSender sender, List message) { - [JsonPropertyName("time")] public int Time { get; set; } = (int)(time - DateTime.UnixEpoch).TotalSeconds; + [JsonPropertyName("time")] public int Time { get; set; } = (int)(TimeZoneInfo.ConvertTimeToUtc(time, TimeZoneInfo.Local) - DateTime.UnixEpoch).TotalSeconds; [JsonPropertyName("message_type")] public string MessageType { get; set; } = messageType; From 1fb104bcb82ddd355f44856ef829cff3cf6364ad Mon Sep 17 00:00:00 2001 From: DarkRRb <177549718+DarkRRb@users.noreply.github.com> Date: Mon, 21 Oct 2024 22:14:29 +0800 Subject: [PATCH 12/19] [Core] Support todo events (#649) --- Lagrange.Core/Event/EventArg/GroupTodoEvent.cs | 16 ++++++++++++++++ Lagrange.Core/Event/EventInvoker.Events.cs | 2 ++ Lagrange.Core/Event/EventInvoker.cs | 2 ++ .../Logic/Implementation/MessagingLogic.cs | 8 ++++++++ .../Internal/Event/Notify/GroupSysTodoEvent.cs | 17 +++++++++++++++++ .../Service/Message/PushMessageService.cs | 8 +++++++- 6 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 Lagrange.Core/Event/EventArg/GroupTodoEvent.cs create mode 100644 Lagrange.Core/Internal/Event/Notify/GroupSysTodoEvent.cs diff --git a/Lagrange.Core/Event/EventArg/GroupTodoEvent.cs b/Lagrange.Core/Event/EventArg/GroupTodoEvent.cs new file mode 100644 index 000000000..b473b40bd --- /dev/null +++ b/Lagrange.Core/Event/EventArg/GroupTodoEvent.cs @@ -0,0 +1,16 @@ +namespace Lagrange.Core.Event.EventArg; + +public class GroupTodoEvent : EventBase +{ + public uint GroupUin { get; } + + public uint OperatorUin { get; } + + public GroupTodoEvent(uint groupUin, uint operatorUin) + { + GroupUin = groupUin; + OperatorUin = operatorUin; + + EventMessage = $"{nameof(GroupPokeEvent)}: GroupUin: {GroupUin} | OperatorUin: {OperatorUin}"; + } +} diff --git a/Lagrange.Core/Event/EventInvoker.Events.cs b/Lagrange.Core/Event/EventInvoker.Events.cs index fcfb502c2..0243713bd 100644 --- a/Lagrange.Core/Event/EventInvoker.Events.cs +++ b/Lagrange.Core/Event/EventInvoker.Events.cs @@ -53,4 +53,6 @@ public partial class EventInvoker public event LagrangeEvent? OnGroupReactionEvent; public event LagrangeEvent? OnGroupNameChangeEvent; + + public event LagrangeEvent? OnGroupTodoEvent; } \ No newline at end of file diff --git a/Lagrange.Core/Event/EventInvoker.cs b/Lagrange.Core/Event/EventInvoker.cs index 666ff1162..eb846f663 100644 --- a/Lagrange.Core/Event/EventInvoker.cs +++ b/Lagrange.Core/Event/EventInvoker.cs @@ -1,5 +1,6 @@ using System.Runtime.CompilerServices; using Lagrange.Core.Event.EventArg; +using Lagrange.Core.Internal.Event.Notify; namespace Lagrange.Core.Event; @@ -40,6 +41,7 @@ internal EventInvoker(BotContext context) RegisterEvent((GroupEssenceEvent e) => OnGroupEssenceEvent?.Invoke(context, e)); RegisterEvent((GroupReactionEvent e) => OnGroupReactionEvent?.Invoke(context, e)); RegisterEvent((GroupNameChangeEvent e) => OnGroupNameChangeEvent?.Invoke(context, e)); + RegisterEvent((GroupTodoEvent e) => OnGroupTodoEvent?.Invoke(context, e)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/Lagrange.Core/Internal/Context/Logic/Implementation/MessagingLogic.cs b/Lagrange.Core/Internal/Context/Logic/Implementation/MessagingLogic.cs index 86271dcba..9da1c8f2c 100644 --- a/Lagrange.Core/Internal/Context/Logic/Implementation/MessagingLogic.cs +++ b/Lagrange.Core/Internal/Context/Logic/Implementation/MessagingLogic.cs @@ -38,6 +38,7 @@ namespace Lagrange.Core.Internal.Context.Logic.Implementation; [EventSubscribe(typeof(FriendSysPokeEvent))] [EventSubscribe(typeof(LoginNotifyEvent))] [EventSubscribe(typeof(MultiMsgDownloadEvent))] +[EventSubscribe(typeof(GroupSysTodoEvent))] [BusinessLogic("MessagingLogic", "Manage the receiving and sending of messages and notifications")] internal class MessagingLogic : LogicBase { @@ -235,6 +236,13 @@ public override async Task Incoming(ProtocolEvent e) } break; } + case GroupSysTodoEvent todo: + { + uint uin = await Collection.Business.CachingLogic.ResolveUin(todo.GroupUin, todo.OperatorUid) ?? 0; + + Collection.Invoker.PostEvent(new GroupTodoEvent(todo.GroupUin, uin)); + break; + } } } diff --git a/Lagrange.Core/Internal/Event/Notify/GroupSysTodoEvent.cs b/Lagrange.Core/Internal/Event/Notify/GroupSysTodoEvent.cs new file mode 100644 index 000000000..d92afa952 --- /dev/null +++ b/Lagrange.Core/Internal/Event/Notify/GroupSysTodoEvent.cs @@ -0,0 +1,17 @@ +namespace Lagrange.Core.Internal.Event.Notify; + +internal class GroupSysTodoEvent : ProtocolEvent +{ + public uint GroupUin { get; } + + public string OperatorUid { get; } + + private GroupSysTodoEvent(uint groupUin, string operatorUid) : base(0) + { + GroupUin = groupUin; + OperatorUid = operatorUid; + } + + public static GroupSysTodoEvent Result(uint groupUin, string operatorUid) + => new(groupUin, operatorUid); +} \ No newline at end of file diff --git a/Lagrange.Core/Internal/Service/Message/PushMessageService.cs b/Lagrange.Core/Internal/Service/Message/PushMessageService.cs index bf471e4fb..71e678101 100644 --- a/Lagrange.Core/Internal/Service/Message/PushMessageService.cs +++ b/Lagrange.Core/Internal/Service/Message/PushMessageService.cs @@ -143,6 +143,11 @@ private static void ProcessEvent0x2DC(Span payload, PushMsg msg, List payload, PushMsg msg, List(content.AsSpan()); if (mute.Data.State.TargetUid == null) { - var groupMuteEvent = GroupSysMuteEvent.Result(mute.GroupUin, mute.OperatorUid, mute.Data.State.Duration !=0); + var groupMuteEvent = GroupSysMuteEvent.Result(mute.GroupUin, mute.OperatorUid, mute.Data.State.Duration != 0); extraEvents.Add(groupMuteEvent); } else @@ -329,6 +334,7 @@ private enum Event0x2DCSubType16Field13 { GroupMemberSpecialTitleNotice = 6, GroupNameChangeNotice = 12, + GroupTodoNotice = 23, GroupReactionNotice = 35, } From d015386e4b431dde324e79dd8caba18c1139ac79 Mon Sep 17 00:00:00 2001 From: dogdie233 Date: Mon, 21 Oct 2024 23:15:31 +0900 Subject: [PATCH 13/19] feat: Make all API cancellable (#630) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: Create all API cancellable (Login not completed) * nya nya nya * 西井姐姐说要把CancellationToken放在最后面 * fix stupid compile error caused by my stupid brain --- Lagrange.Core/Common/Interface/Api/BotExt.cs | 34 +- .../Common/Interface/Api/GroupExt.cs | 217 +++++++++-- .../Common/Interface/Api/OperationExt.cs | 338 ++++++++++++++++-- .../Internal/Context/BusinessContext.cs | 47 ++- .../Internal/Context/HighwayContext.cs | 34 +- .../Logic/Implementation/CachingLogic.cs | 56 +-- .../Logic/Implementation/MessagingLogic.cs | 100 +++--- .../Logic/Implementation/OperationLogic.cs | 327 +++++++++-------- .../Logic/Implementation/WtExchangeLogic.cs | 171 +++++---- .../Internal/Context/Logic/LogicBase.cs | 6 +- .../Internal/Context/PacketContext.cs | 38 +- .../Internal/Context/SocketContext.cs | 31 +- .../Internal/Context/Uploader/Common.cs | 6 +- .../Internal/Context/Uploader/FileUploader.cs | 219 ++++++------ .../Context/Uploader/IHighwayUploader.cs | 6 +- .../Context/Uploader/ImageUploader.cs | 14 +- .../Internal/Context/Uploader/PttUploader.cs | 14 +- .../Context/Uploader/VideoUploader.cs | 18 +- .../Internal/Network/ClientListener.cs | 11 +- Lagrange.Core/Utility/Network/Http.cs | 10 +- Lagrange.OneBot/Core/Notify/NotifyService.cs | 2 +- .../Operation/Ability/UploadImageOperation.cs | 4 +- .../Operation/Generic/SendPacketOperation.cs | 2 +- .../Message/SendForwardMessageOperation.cs | 2 +- .../Request/SetFriendAddRequestOperation.cs | 2 +- .../Request/SetGroupAddRequestOperation.cs | 4 +- 26 files changed, 1115 insertions(+), 598 deletions(-) diff --git a/Lagrange.Core/Common/Interface/Api/BotExt.cs b/Lagrange.Core/Common/Interface/Api/BotExt.cs index e709267ad..951b2946b 100644 --- a/Lagrange.Core/Common/Interface/Api/BotExt.cs +++ b/Lagrange.Core/Common/Interface/Api/BotExt.cs @@ -9,18 +9,37 @@ public static class BotExt /// /// return url and qrcode image in PNG format public static Task<(string Url, byte[] QrCode)?> FetchQrCode(this BotContext bot) - => bot.ContextCollection.Business.WtExchangeLogic.FetchQrCode(); + => bot.ContextCollection.Business.WtExchangeLogic.FetchQrCode(CancellationToken.None); + + /// + /// Fetch the qrcode for QRCode Login + /// + /// return url and qrcode image in PNG format + public static Task<(string Url, byte[] QrCode)?> FetchQrCode(this BotContext bot, CancellationToken cancellationToken) + => bot.ContextCollection.Business.WtExchangeLogic.FetchQrCode(cancellationToken); /// /// Use this method to login by QrCode, you should call first /// - public static Task LoginByQrCode(this BotContext bot, CancellationToken cancellationToken = default) + public static Task LoginByQrCode(this BotContext bot) + => bot.ContextCollection.Business.WtExchangeLogic.LoginByQrCode(CancellationToken.None); + + /// + /// Use this method to login by QrCode, you should call first + /// + public static Task LoginByQrCode(this BotContext bot, CancellationToken cancellationToken) => bot.ContextCollection.Business.WtExchangeLogic.LoginByQrCode(cancellationToken); /// /// Use this method to login by password, EasyLogin may be preformed if there is sig in /// - public static Task LoginByPassword(this BotContext bot, CancellationToken cancellationToken = default) + public static Task LoginByPassword(this BotContext bot) + => bot.ContextCollection.Business.WtExchangeLogic.LoginByPassword(CancellationToken.None); + + /// + /// Use this method to login by password, EasyLogin may be preformed if there is sig in + /// + public static Task LoginByPassword(this BotContext bot, CancellationToken cancellationToken) => bot.ContextCollection.Business.WtExchangeLogic.LoginByPassword(cancellationToken); /// @@ -30,8 +49,11 @@ public static Task LoginByPassword(this BotContext bot, CancellationToken public static bool SubmitCaptcha(this BotContext bot, string ticket, string randStr) => bot.ContextCollection.Business.WtExchangeLogic.SubmitCaptcha(ticket, randStr); - public static Task SetNeedToConfirmSwitch(this BotContext bot, bool needToConfirm) - => bot.ContextCollection.Business.OperationLogic.SetNeedToConfirmSwitch(needToConfirm); + public static Task SetNeedToConfirmSwitch(this BotContext bot, bool needToConfirm) + => bot.ContextCollection.Business.OperationLogic.SetNeedToConfirmSwitch(needToConfirm, CancellationToken.None); + + public static Task SetNeedToConfirmSwitch(this BotContext bot, bool needToConfirm, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.SetNeedToConfirmSwitch(needToConfirm, cancellationToken); /// /// Use this method to update keystore, so EasyLogin may be preformed next time by using this keystore @@ -46,4 +68,4 @@ public static BotKeystore UpdateKeystore(this BotContext bot) /// public static BotDeviceInfo UpdateDeviceInfo(this BotContext bot) => bot.ContextCollection.Device; -} \ No newline at end of file +} diff --git a/Lagrange.Core/Common/Interface/Api/GroupExt.cs b/Lagrange.Core/Common/Interface/Api/GroupExt.cs index 6e7270e9f..3e9327a7b 100644 --- a/Lagrange.Core/Common/Interface/Api/GroupExt.cs +++ b/Lagrange.Core/Common/Interface/Api/GroupExt.cs @@ -1,3 +1,4 @@ +using System.Globalization; using Lagrange.Core.Common.Entity; using Lagrange.Core.Event.EventArg; using Lagrange.Core.Message; @@ -16,7 +17,19 @@ public static class GroupExt /// The duration in seconds, 0 for unmute member /// Successfully muted or not public static Task MuteGroupMember(this BotContext bot, uint groupUin, uint targetUin, uint duration) - => bot.ContextCollection.Business.OperationLogic.MuteGroupMember(groupUin, targetUin, duration); + => bot.ContextCollection.Business.OperationLogic.MuteGroupMember(groupUin, targetUin, duration, CancellationToken.None); + + /// + /// Mute the member in the group, Bot must be admin + /// + /// target BotContext + /// The uin for target group + /// The uin for target member in such group + /// The duration in seconds, 0 for unmute member + /// The cancellation token + /// Successfully muted or not + public static Task MuteGroupMember(this BotContext bot, uint groupUin, uint targetUin, uint duration, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.MuteGroupMember(groupUin, targetUin, duration, cancellationToken); /// /// Mute the group @@ -26,7 +39,18 @@ public static Task MuteGroupMember(this BotContext bot, uint groupUin, uin /// true for mute and false for unmute /// Successfully muted or not public static Task MuteGroupGlobal(this BotContext bot, uint groupUin, bool isMute) - => bot.ContextCollection.Business.OperationLogic.MuteGroupGlobal(groupUin, isMute); + => bot.ContextCollection.Business.OperationLogic.MuteGroupGlobal(groupUin, isMute, CancellationToken.None); + + /// + /// Mute the group + /// + /// target BotContext + /// The uin for target group + /// true for mute and false for unmute + /// The cancellation token + /// Successfully muted or not + public static Task MuteGroupGlobal(this BotContext bot, uint groupUin, bool isMute, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.MuteGroupGlobal(groupUin, isMute, cancellationToken); /// /// @@ -37,115 +61,230 @@ public static Task MuteGroupGlobal(this BotContext bot, uint groupUin, boo /// whether the kicked member can request /// Successfully kicked or not public static Task KickGroupMember(this BotContext bot, uint groupUin, uint targetUin, bool rejectAddRequest) - => bot.ContextCollection.Business.OperationLogic.KickGroupMember(groupUin, targetUin, rejectAddRequest, ""); + => bot.ContextCollection.Business.OperationLogic.KickGroupMember(groupUin, targetUin, rejectAddRequest, "", CancellationToken.None); + + + /// + /// + /// + /// target BotContext + /// The uin for target group + /// The uin for target member in such group + /// whether the kicked member can request + /// The cancellation token + /// Successfully kicked or not + public static Task KickGroupMember(this BotContext bot, uint groupUin, uint targetUin, bool rejectAddRequest, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.KickGroupMember(groupUin, targetUin, rejectAddRequest, "", cancellationToken); public static Task KickGroupMember(this BotContext bot, uint groupUin, uint targetUin, bool rejectAddRequest, string reason) - => bot.ContextCollection.Business.OperationLogic.KickGroupMember(groupUin, targetUin, rejectAddRequest, reason); + => bot.ContextCollection.Business.OperationLogic.KickGroupMember(groupUin, targetUin, rejectAddRequest, reason, CancellationToken.None); + + public static Task KickGroupMember(this BotContext bot, uint groupUin, uint targetUin, bool rejectAddRequest, string reason, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.KickGroupMember(groupUin, targetUin, rejectAddRequest, reason, cancellationToken); public static Task SetGroupAdmin(this BotContext bot, uint groupUin, uint targetUin, bool isAdmin) - => bot.ContextCollection.Business.OperationLogic.SetGroupAdmin(groupUin, targetUin, isAdmin); + => bot.ContextCollection.Business.OperationLogic.SetGroupAdmin(groupUin, targetUin, isAdmin, CancellationToken.None); + + public static Task SetGroupAdmin(this BotContext bot, uint groupUin, uint targetUin, bool isAdmin, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.SetGroupAdmin(groupUin, targetUin, isAdmin, cancellationToken); // 300204 Check group manager:Not an administrator public static Task<(int, string?)> SetGroupTodo(this BotContext bot, uint groupUin, uint sequence) - => bot.ContextCollection.Business.OperationLogic.SetGroupTodo(groupUin, sequence); + => bot.ContextCollection.Business.OperationLogic.SetGroupTodo(groupUin, sequence, CancellationToken.None); + + // 300204 Check group manager:Not an administrator + public static Task<(int, string?)> SetGroupTodo(this BotContext bot, uint groupUin, uint sequence, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.SetGroupTodo(groupUin, sequence, cancellationToken); public static Task<(int, string?)> RemoveGroupTodo(this BotContext bot, uint groupUin) - => bot.ContextCollection.Business.OperationLogic.RemoveGroupTodo(groupUin); + => bot.ContextCollection.Business.OperationLogic.RemoveGroupTodo(groupUin, CancellationToken.None); + + public static Task<(int, string?)> RemoveGroupTodo(this BotContext bot, uint groupUin, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.RemoveGroupTodo(groupUin, cancellationToken); public static Task<(int, string?)> FinishGroupTodo(this BotContext bot, uint groupUin) - => bot.ContextCollection.Business.OperationLogic.FinishGroupTodo(groupUin); + => bot.ContextCollection.Business.OperationLogic.FinishGroupTodo(groupUin, CancellationToken.None); + + public static Task<(int, string?)> FinishGroupTodo(this BotContext bot, uint groupUin, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.FinishGroupTodo(groupUin, cancellationToken); public static Task GetGroupTodo(this BotContext bot, uint groupUin) - => bot.ContextCollection.Business.OperationLogic.GetGroupTodo(groupUin); + => bot.ContextCollection.Business.OperationLogic.GetGroupTodo(groupUin, CancellationToken.None); + + public static Task GetGroupTodo(this BotContext bot, uint groupUin, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.GetGroupTodo(groupUin, cancellationToken); public static Task SetGroupBot(this BotContext bot, uint targetUin, uint On, uint groupUin) - => bot.ContextCollection.Business.OperationLogic.SetGroupBot(targetUin, On, groupUin); + => bot.ContextCollection.Business.OperationLogic.SetGroupBot(targetUin, On, groupUin, CancellationToken.None); + + public static Task SetGroupBot(this BotContext bot, uint targetUin, uint On, uint groupUin, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.SetGroupBot(targetUin, On, groupUin, cancellationToken); [Obsolete("Cosider using SetGroupBotHD(BotContext, uint, uint, string?, string?) instead")] public static Task SetGroupBotHD(this BotContext bot, uint targetUin, uint groupUin) => bot.SetGroupBotHD(targetUin, groupUin, null, null); public static Task SetGroupBotHD(this BotContext bot, uint targetUin, uint groupUin, string? data_1, string? data_2) - => bot.ContextCollection.Business.OperationLogic.SetGroupBotHD(targetUin, groupUin, data_1, data_2); + => bot.ContextCollection.Business.OperationLogic.SetGroupBotHD(targetUin, groupUin, data_1, data_2, CancellationToken.None); + public static Task SetGroupBotHD(this BotContext bot, uint targetUin, uint groupUin, string? data_1, string? data_2, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.SetGroupBotHD(targetUin, groupUin, data_1, data_2, cancellationToken); public static Task RenameGroupMember(this BotContext bot, uint groupUin, uint targetUin, string targetName) - => bot.ContextCollection.Business.OperationLogic.RenameGroupMember(groupUin, targetUin, targetName); + => bot.ContextCollection.Business.OperationLogic.RenameGroupMember(groupUin, targetUin, targetName, CancellationToken.None); + + public static Task RenameGroupMember(this BotContext bot, uint groupUin, uint targetUin, string targetName, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.RenameGroupMember(groupUin, targetUin, targetName, cancellationToken); public static Task RenameGroup(this BotContext bot, uint groupUin, string targetName) - => bot.ContextCollection.Business.OperationLogic.RenameGroup(groupUin, targetName); + => bot.ContextCollection.Business.OperationLogic.RenameGroup(groupUin, targetName, CancellationToken.None); + + public static Task RenameGroup(this BotContext bot, uint groupUin, string targetName, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.RenameGroup(groupUin, targetName, cancellationToken); public static Task RemarkGroup(this BotContext bot, uint groupUin, string targetRemark) - => bot.ContextCollection.Business.OperationLogic.RemarkGroup(groupUin, targetRemark); + => bot.ContextCollection.Business.OperationLogic.RemarkGroup(groupUin, targetRemark, CancellationToken.None); + + public static Task RemarkGroup(this BotContext bot, uint groupUin, string targetRemark, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.RemarkGroup(groupUin, targetRemark, cancellationToken); public static Task LeaveGroup(this BotContext bot, uint groupUin) - => bot.ContextCollection.Business.OperationLogic.LeaveGroup(groupUin); + => bot.ContextCollection.Business.OperationLogic.LeaveGroup(groupUin, CancellationToken.None); + + public static Task LeaveGroup(this BotContext bot, uint groupUin, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.LeaveGroup(groupUin, cancellationToken); public static Task InviteGroup(this BotContext bot, uint groupUin, Dictionary invitedUins) - => bot.ContextCollection.Business.OperationLogic.InviteGroup(groupUin, invitedUins); + => bot.ContextCollection.Business.OperationLogic.InviteGroup(groupUin, invitedUins, CancellationToken.None); + + public static Task InviteGroup(this BotContext bot, uint groupUin, Dictionary invitedUins, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.InviteGroup(groupUin, invitedUins, cancellationToken); public static Task SetGroupRequest(this BotContext bot, BotGroupRequest request, bool accept = true, string reason = "") - => bot.ContextCollection.Business.OperationLogic.SetGroupRequest(request.GroupUin, request.Sequence, (uint)request.EventType, accept, reason); + => bot.ContextCollection.Business.OperationLogic.SetGroupRequest(request.GroupUin, request.Sequence, (uint)request.EventType, accept, reason, CancellationToken.None); + + public static Task SetGroupRequest(this BotContext bot, BotGroupRequest request, bool accept, string reason, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.SetGroupRequest(request.GroupUin, request.Sequence, (uint)request.EventType, accept, reason, cancellationToken); public static Task SetGroupFilteredRequest(this BotContext bot, BotGroupRequest request, bool accept = true, string reason = "") - => bot.ContextCollection.Business.OperationLogic.SetGroupFilteredRequest(request.GroupUin, request.Sequence, (uint)request.EventType, accept, reason); + => bot.ContextCollection.Business.OperationLogic.SetGroupFilteredRequest(request.GroupUin, request.Sequence, (uint)request.EventType, accept, reason, CancellationToken.None); + + public static Task SetGroupFilteredRequest(this BotContext bot, BotGroupRequest request, bool accept, string reason, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.SetGroupFilteredRequest(request.GroupUin, request.Sequence, (uint)request.EventType, accept, reason, cancellationToken); public static Task SetFriendRequest(this BotContext bot, FriendRequestEvent request, bool accept = true) - => bot.ContextCollection.Business.OperationLogic.SetFriendRequest(request.SourceUid, accept); + => bot.ContextCollection.Business.OperationLogic.SetFriendRequest(request.SourceUid, accept, CancellationToken.None); + + public static Task SetFriendRequest(this BotContext bot, FriendRequestEvent request, bool accept, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.SetFriendRequest(request.SourceUid, accept, cancellationToken); public static Task GroupPoke(this BotContext bot, uint groupUin, uint friendUin) - => bot.ContextCollection.Business.OperationLogic.GroupPoke(groupUin, friendUin); + => bot.ContextCollection.Business.OperationLogic.GroupPoke(groupUin, friendUin, CancellationToken.None); + + public static Task GroupPoke(this BotContext bot, uint groupUin, uint friendUin, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.GroupPoke(groupUin, friendUin, cancellationToken); public static Task SetEssenceMessage(this BotContext bot, MessageChain chain) - => bot.ContextCollection.Business.OperationLogic.SetEssenceMessage(chain.GroupUin ?? 0, chain.Sequence, (uint)(chain.MessageId & 0xFFFFFFFF)); + => bot.ContextCollection.Business.OperationLogic.SetEssenceMessage(chain.GroupUin ?? 0, chain.Sequence, (uint)(chain.MessageId & 0xFFFFFFFF), CancellationToken.None); + + public static Task SetEssenceMessage(this BotContext bot, MessageChain chain, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.SetEssenceMessage(chain.GroupUin ?? 0, chain.Sequence, (uint)(chain.MessageId & 0xFFFFFFFF), cancellationToken); public static Task RemoveEssenceMessage(this BotContext bot, MessageChain chain) - => bot.ContextCollection.Business.OperationLogic.RemoveEssenceMessage(chain.GroupUin ?? 0, chain.Sequence, (uint)(chain.MessageId & 0xFFFFFFFF)); + => bot.ContextCollection.Business.OperationLogic.RemoveEssenceMessage(chain.GroupUin ?? 0, chain.Sequence, (uint)(chain.MessageId & 0xFFFFFFFF), CancellationToken.None); + + public static Task RemoveEssenceMessage(this BotContext bot, MessageChain chain, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.RemoveEssenceMessage(chain.GroupUin ?? 0, chain.Sequence, (uint)(chain.MessageId & 0xFFFFFFFF), cancellationToken); public static Task GroupSetSpecialTitle(this BotContext bot, uint groupUin, uint targetUin, string title) - => bot.ContextCollection.Business.OperationLogic.GroupSetSpecialTitle(groupUin, targetUin, title); + => bot.ContextCollection.Business.OperationLogic.GroupSetSpecialTitle(groupUin, targetUin, title, CancellationToken.None); + + public static Task GroupSetSpecialTitle(this BotContext bot, uint groupUin, uint targetUin, string title, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.GroupSetSpecialTitle(groupUin, targetUin, title, cancellationToken); public static Task GroupSetMessageReaction(this BotContext bot, uint groupUin, uint sequence, string code) - => bot.ContextCollection.Business.OperationLogic.SetMessageReaction(groupUin, sequence, code, true); + => bot.ContextCollection.Business.OperationLogic.SetMessageReaction(groupUin, sequence, code, true, CancellationToken.None); + + public static Task GroupSetMessageReaction(this BotContext bot, uint groupUin, uint sequence, string code, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.SetMessageReaction(groupUin, sequence, code, true, cancellationToken); public static Task GroupSetMessageReaction(this BotContext bot, uint groupUin, uint sequence, string code, bool isSet) - => bot.ContextCollection.Business.OperationLogic.SetMessageReaction(groupUin, sequence, code, isSet); - + => bot.ContextCollection.Business.OperationLogic.SetMessageReaction(groupUin, sequence, code, isSet, CancellationToken.None); + + public static Task GroupSetMessageReaction(this BotContext bot, uint groupUin, uint sequence, string code, bool isSet, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.SetMessageReaction(groupUin, sequence, code, isSet, cancellationToken); + public static Task GroupSetAvatar(this BotContext bot, uint groupUin, ImageEntity imageEntity) - => bot.ContextCollection.Business.OperationLogic.GroupSetAvatar(groupUin, imageEntity); + => bot.ContextCollection.Business.OperationLogic.GroupSetAvatar(groupUin, imageEntity, CancellationToken.None); + public static Task GroupSetAvatar(this BotContext bot, uint groupUin, ImageEntity imageEntity, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.GroupSetAvatar(groupUin, imageEntity, cancellationToken); + public static Task<(uint, uint)> GroupRemainAtAll(this BotContext bot, uint groupUin) - => bot.ContextCollection.Business.OperationLogic.GroupRemainAtAll(groupUin); + => bot.ContextCollection.Business.OperationLogic.GroupRemainAtAll(groupUin, CancellationToken.None); + + public static Task<(uint, uint)> GroupRemainAtAll(this BotContext bot, uint groupUin, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.GroupRemainAtAll(groupUin, cancellationToken); #region Group File System public static Task FetchGroupFSSpace(this BotContext bot, uint groupUin) - => bot.ContextCollection.Business.OperationLogic.FetchGroupFSSpace(groupUin); + => bot.ContextCollection.Business.OperationLogic.FetchGroupFSSpace(groupUin, CancellationToken.None); + + public static Task FetchGroupFSSpace(this BotContext bot, uint groupUin, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.FetchGroupFSSpace(groupUin, cancellationToken); public static Task FetchGroupFSCount(this BotContext bot, uint groupUin) - => bot.ContextCollection.Business.OperationLogic.FetchGroupFSCount(groupUin); + => bot.ContextCollection.Business.OperationLogic.FetchGroupFSCount(groupUin, CancellationToken.None); + + public static Task FetchGroupFSCount(this BotContext bot, uint groupUin, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.FetchGroupFSCount(groupUin, cancellationToken); public static Task> FetchGroupFSList(this BotContext bot, uint groupUin, string targetDirectory = "/") - => bot.ContextCollection.Business.OperationLogic.FetchGroupFSList(groupUin, targetDirectory); + => bot.ContextCollection.Business.OperationLogic.FetchGroupFSList(groupUin, targetDirectory, CancellationToken.None); + + public static Task> FetchGroupFSList(this BotContext bot, uint groupUin, string targetDirectory, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.FetchGroupFSList(groupUin, targetDirectory, cancellationToken); public static Task FetchGroupFSDownload(this BotContext bot, uint groupUin, string fileId) - => bot.ContextCollection.Business.OperationLogic.FetchGroupFSDownload(groupUin, fileId); + => bot.ContextCollection.Business.OperationLogic.FetchGroupFSDownload(groupUin, fileId, CancellationToken.None); + + public static Task FetchGroupFSDownload(this BotContext bot, uint groupUin, string fileId, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.FetchGroupFSDownload(groupUin, fileId, cancellationToken); public static Task<(int RetCode, string RetMsg)> GroupFSMove(this BotContext bot, uint groupUin, string fileId, string parentDirectory, string targetDirectory) - => bot.ContextCollection.Business.OperationLogic.GroupFSMove(groupUin, fileId, parentDirectory, targetDirectory); + => bot.ContextCollection.Business.OperationLogic.GroupFSMove(groupUin, fileId, parentDirectory, targetDirectory, CancellationToken.None); + + public static Task<(int RetCode, string RetMsg)> GroupFSMove(this BotContext bot, uint groupUin, string fileId, string parentDirectory, string targetDirectory, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.GroupFSMove(groupUin, fileId, parentDirectory, targetDirectory, cancellationToken); public static Task<(int RetCode, string RetMsg)> GroupFSDelete(this BotContext bot, uint groupUin, string fileId) - => bot.ContextCollection.Business.OperationLogic.GroupFSDelete(groupUin, fileId); + => bot.ContextCollection.Business.OperationLogic.GroupFSDelete(groupUin, fileId, CancellationToken.None); + + public static Task<(int RetCode, string RetMsg)> GroupFSDelete(this BotContext bot, uint groupUin, string fileId, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.GroupFSDelete(groupUin, fileId, cancellationToken); public static Task<(int RetCode, string RetMsg)> GroupFSCreateFolder(this BotContext bot, uint groupUin, string name) - => bot.ContextCollection.Business.OperationLogic.GroupFSCreateFolder(groupUin, name); + => bot.ContextCollection.Business.OperationLogic.GroupFSCreateFolder(groupUin, name, CancellationToken.None); + + public static Task<(int RetCode, string RetMsg)> GroupFSCreateFolder(this BotContext bot, uint groupUin, string name, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.GroupFSCreateFolder(groupUin, name, cancellationToken); public static Task<(int RetCode, string RetMsg)> GroupFSDeleteFolder(this BotContext bot, uint groupUin, string folderId) - => bot.ContextCollection.Business.OperationLogic.GroupFSDeleteFolder(groupUin, folderId); + => bot.ContextCollection.Business.OperationLogic.GroupFSDeleteFolder(groupUin, folderId, CancellationToken.None); + + public static Task<(int RetCode, string RetMsg)> GroupFSDeleteFolder(this BotContext bot, uint groupUin, string folderId, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.GroupFSDeleteFolder(groupUin, folderId, cancellationToken); public static Task<(int RetCode, string RetMsg)> GroupFSRenameFolder(this BotContext bot, uint groupUin, string folderId, string newFolderName) - => bot.ContextCollection.Business.OperationLogic.GroupFSRenameFolder(groupUin, folderId, newFolderName); + => bot.ContextCollection.Business.OperationLogic.GroupFSRenameFolder(groupUin, folderId, newFolderName, CancellationToken.None); + + public static Task<(int RetCode, string RetMsg)> GroupFSRenameFolder(this BotContext bot, uint groupUin, string folderId, string newFolderName, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.GroupFSRenameFolder(groupUin, folderId, newFolderName, cancellationToken); public static Task GroupFSUpload(this BotContext bot, uint groupUin, FileEntity fileEntity, string targetDirectory = "/") - => bot.ContextCollection.Business.OperationLogic.GroupFSUpload(groupUin, fileEntity, targetDirectory); + => bot.ContextCollection.Business.OperationLogic.GroupFSUpload(groupUin, fileEntity, targetDirectory, CancellationToken.None); + + public static Task GroupFSUpload(this BotContext bot, uint groupUin, FileEntity fileEntity, string targetDirectory, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.GroupFSUpload(groupUin, fileEntity, targetDirectory, cancellationToken); #endregion -} \ No newline at end of file +} diff --git a/Lagrange.Core/Common/Interface/Api/OperationExt.cs b/Lagrange.Core/Common/Interface/Api/OperationExt.cs index 3900a4416..355afb399 100644 --- a/Lagrange.Core/Common/Interface/Api/OperationExt.cs +++ b/Lagrange.Core/Common/Interface/Api/OperationExt.cs @@ -13,7 +13,18 @@ public static class OperationExt /// force the cache to be refreshed /// public static Task> FetchFriends(this BotContext bot, bool refreshCache = false) - => bot.ContextCollection.Business.OperationLogic.FetchFriends(refreshCache); + => bot.ContextCollection.Business.OperationLogic.FetchFriends(refreshCache, CancellationToken.None); + + + /// + /// Fetch the friend list of account from server or cache + /// + /// target BotContext + /// The cancellation token + /// force the cache to be refreshed + /// + public static Task> FetchFriends(this BotContext bot, bool refreshCache, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.FetchFriends(refreshCache, CancellationToken.None); /// /// Fetch the member list of the group from server or cache @@ -23,7 +34,18 @@ public static Task> FetchFriends(this BotContext bot, bool refre /// force the cache to be refreshed /// public static Task> FetchMembers(this BotContext bot, uint groupUin, bool refreshCache = false) - => bot.ContextCollection.Business.OperationLogic.FetchMembers(groupUin, refreshCache); + => bot.ContextCollection.Business.OperationLogic.FetchMembers(groupUin, CancellationToken.None, refreshCache); + + /// + /// Fetch the member list of the group from server or cache + /// + /// target BotContext + /// + /// The cancellation token + /// force the cache to be refreshed + /// + public static Task> FetchMembers(this BotContext bot, uint groupUin, bool refreshCache, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.FetchMembers(groupUin, cancellationToken, refreshCache); /// /// Fetch the group list of the account from server or cache @@ -32,7 +54,17 @@ public static Task> FetchMembers(this BotContext bot, uint /// force the cache to be refreshed /// public static Task> FetchGroups(this BotContext bot, bool refreshCache = false) - => bot.ContextCollection.Business.OperationLogic.FetchGroups(refreshCache); + => bot.ContextCollection.Business.OperationLogic.FetchGroups(refreshCache, CancellationToken.None); + + /// + /// Fetch the group list of the account from server or cache + /// + /// target BotContext + /// The cancellation token + /// force the cache to be refreshed + /// + public static Task> FetchGroups(this BotContext bot, bool refreshCache, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.FetchGroups(refreshCache, cancellationToken); /// /// Fetch the cookies/pskey for accessing other site @@ -41,7 +73,17 @@ public static Task> FetchGroups(this BotContext bot, bool refresh /// the domain for the cookie to be valid /// the list of cookies public static Task> FetchCookies(this BotContext bot, List domains) - => bot.ContextCollection.Business.OperationLogic.GetCookies(domains); + => bot.ContextCollection.Business.OperationLogic.GetCookies(domains, CancellationToken.None); + + /// + /// Fetch the cookies/pskey for accessing other site + /// + /// target BotContext + /// the domain for the cookie to be valid + /// The cancellation token + /// the list of cookies + public static Task> FetchCookies(this BotContext bot, List domains, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.GetCookies(domains, cancellationToken); /// /// Send the message @@ -49,17 +91,37 @@ public static Task> FetchCookies(this BotContext bot, List /// target BotContext /// the chain constructed by public static Task SendMessage(this BotContext bot, MessageChain chain) - => bot.ContextCollection.Business.OperationLogic.SendMessage(chain); + => bot.ContextCollection.Business.OperationLogic.SendMessage(chain, CancellationToken.None); + + /// + /// Send the message + /// + /// target BotContext + /// the chain constructed by + /// The cancellation token + public static Task SendMessage(this BotContext bot, MessageChain chain, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.SendMessage(chain, cancellationToken); /// /// Recall the group message from Bot itself by /// /// target BotContext /// The uin for target group of the message - /// The return value for + /// The return value for /// Successfully recalled or not public static Task RecallGroupMessage(this BotContext bot, uint groupUin, MessageResult result) - => bot.ContextCollection.Business.OperationLogic.RecallGroupMessage(groupUin, result); + => bot.ContextCollection.Business.OperationLogic.RecallGroupMessage(groupUin, result, CancellationToken.None); + + /// + /// Recall the group message from Bot itself by + /// + /// target BotContext + /// The uin for target group of the message + /// The return value for + /// The cancellation token + /// Successfully recalled or not + public static Task RecallGroupMessage(this BotContext bot, uint groupUin, MessageResult result, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.RecallGroupMessage(groupUin, result, cancellationToken); /// /// Recall the group message by @@ -68,7 +130,17 @@ public static Task RecallGroupMessage(this BotContext bot, uint groupUin, /// target MessageChain, must be Group /// Successfully recalled or not public static Task RecallGroupMessage(this BotContext bot, MessageChain chain) - => bot.ContextCollection.Business.OperationLogic.RecallGroupMessage(chain); + => bot.ContextCollection.Business.OperationLogic.RecallGroupMessage(chain, CancellationToken.None); + + /// + /// Recall the group message by + /// + /// target BotContext + /// target MessageChain, must be Group + /// The cancellation token + /// Successfully recalled or not + public static Task RecallGroupMessage(this BotContext bot, MessageChain chain, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.RecallGroupMessage(chain, cancellationToken); /// /// Recall the group message by sequence @@ -78,17 +150,39 @@ public static Task RecallGroupMessage(this BotContext bot, MessageChain ch /// The sequence for target message /// Successfully recalled or not public static Task RecallGroupMessage(this BotContext bot, uint groupUin, uint sequence) - => bot.ContextCollection.Business.OperationLogic.RecallGroupMessage(groupUin, sequence); + => bot.ContextCollection.Business.OperationLogic.RecallGroupMessage(groupUin, sequence, CancellationToken.None); + + /// + /// Recall the group message by sequence + /// + /// target BotContext + /// The uin for target group of the message + /// The sequence for target message + /// The cancellation token + /// Successfully recalled or not + public static Task RecallGroupMessage(this BotContext bot, uint groupUin, uint sequence, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.RecallGroupMessage(groupUin, sequence, cancellationToken); /// /// Recall the group message from Bot itself by /// /// target BotContext /// The uin for target friend of the message - /// The return value for + /// The return value for /// Successfully recalled or not public static Task RecallFriendMessage(this BotContext bot, uint friendUin, MessageResult result) - => bot.ContextCollection.Business.OperationLogic.RecallFriendMessage(friendUin, result); + => bot.ContextCollection.Business.OperationLogic.RecallFriendMessage(friendUin, result, CancellationToken.None); + + /// + /// Recall the group message from Bot itself by + /// + /// target BotContext + /// The uin for target friend of the message + /// The return value for + /// The cancellation token + /// Successfully recalled or not + public static Task RecallFriendMessage(this BotContext bot, uint friendUin, MessageResult result, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.RecallFriendMessage(friendUin, result, cancellationToken); /// /// Recall the group message by @@ -97,7 +191,17 @@ public static Task RecallFriendMessage(this BotContext bot, uint friendUin /// target MessageChain, must be Friend /// Successfully recalled or not public static Task RecallFriendMessage(this BotContext bot, MessageChain chain) - => bot.ContextCollection.Business.OperationLogic.RecallFriendMessage(chain); + => bot.ContextCollection.Business.OperationLogic.RecallFriendMessage(chain, CancellationToken.None); + + /// + /// Recall the group message by + /// + /// target BotContext + /// target MessageChain, must be Friend + /// The cancellation token + /// Successfully recalled or not + public static Task RecallFriendMessage(this BotContext bot, MessageChain chain, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.RecallFriendMessage(chain, cancellationToken); /// /// Fetch Notifications and requests such as friend requests and Group Join Requests @@ -105,7 +209,16 @@ public static Task RecallFriendMessage(this BotContext bot, MessageChain c /// target BotContext /// public static Task?> FetchGroupRequests(this BotContext bot) - => bot.ContextCollection.Business.OperationLogic.FetchGroupRequests(); + => bot.ContextCollection.Business.OperationLogic.FetchGroupRequests(CancellationToken.None); + + /// + /// Fetch Notifications and requests such as friend requests and Group Join Requests + /// + /// target BotContext + /// The cancellation token + /// + public static Task?> FetchGroupRequests(this BotContext bot, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.FetchGroupRequests(cancellationToken); /// /// @@ -113,7 +226,16 @@ public static Task RecallFriendMessage(this BotContext bot, MessageChain c /// /// public static Task?> FetchFriendRequests(this BotContext bot) - => bot.ContextCollection.Business.OperationLogic.FetchFriendRequests(); + => bot.ContextCollection.Business.OperationLogic.FetchFriendRequests(CancellationToken.None); + + /// + /// + /// + /// + /// The cancellation token + /// + public static Task?> FetchFriendRequests(this BotContext bot, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.FetchFriendRequests(cancellationToken); /// /// set status @@ -122,7 +244,17 @@ public static Task RecallFriendMessage(this BotContext bot, MessageChain c /// The status code /// public static Task SetStatus(this BotContext bot, uint status) - => bot.ContextCollection.Business.OperationLogic.SetStatus(status); + => bot.ContextCollection.Business.OperationLogic.SetStatus(status, CancellationToken.None); + + /// + /// set status + /// + /// target BotContext + /// The status code + /// The cancellation token + /// + public static Task SetStatus(this BotContext bot, uint status, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.SetStatus(status, cancellationToken); /// /// set custom status @@ -132,22 +264,48 @@ public static Task SetStatus(this BotContext bot, uint status) /// text that would shown /// public static Task SetCustomStatus(this BotContext bot, uint faceId, string text) - => bot.ContextCollection.Business.OperationLogic.SetCustomStatus(faceId, text); + => bot.ContextCollection.Business.OperationLogic.SetCustomStatus(faceId, text, CancellationToken.None); + + /// + /// set custom status + /// + /// target BotContext + /// faceId that is same as the + /// text that would shown + /// The cancellation token + /// + public static Task SetCustomStatus(this BotContext bot, uint faceId, string text, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.SetCustomStatus(faceId, text, cancellationToken); public static Task GroupTransfer(this BotContext bot, uint groupUin, uint targetUin) - => bot.ContextCollection.Business.OperationLogic.GroupTransfer(groupUin, targetUin); + => bot.ContextCollection.Business.OperationLogic.GroupTransfer(groupUin, targetUin, CancellationToken.None); + + public static Task GroupTransfer(this BotContext bot, uint groupUin, uint targetUin, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.GroupTransfer(groupUin, targetUin, cancellationToken); public static Task RequestFriend(this BotContext bot, uint targetUin, string question = "", string message = "") - => bot.ContextCollection.Business.OperationLogic.RequestFriend(targetUin, question, message); + => bot.ContextCollection.Business.OperationLogic.RequestFriend(targetUin, question, message, CancellationToken.None); + + public static Task RequestFriend(this BotContext bot, uint targetUin, string question, string message, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.RequestFriend(targetUin, question, message, cancellationToken); public static Task Like(this BotContext bot, uint targetUin, uint count = 1) - => bot.ContextCollection.Business.OperationLogic.Like(targetUin, count); + => bot.ContextCollection.Business.OperationLogic.Like(targetUin, count, CancellationToken.None); + + public static Task Like(this BotContext bot, uint targetUin, uint count, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.Like(targetUin, count, cancellationToken); /// /// Get the client key for all sites /// public static Task GetClientKey(this BotContext bot) - => bot.ContextCollection.Business.OperationLogic.GetClientKey(); + => bot.ContextCollection.Business.OperationLogic.GetClientKey(CancellationToken.None); + + /// + /// Get the client key for all sites + /// + public static Task GetClientKey(this BotContext bot, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.GetClientKey(cancellationToken); /// /// Get the history message record, max 30 seqs @@ -157,7 +315,18 @@ public static Task Like(this BotContext bot, uint targetUin, uint count = /// Start Sequence of the message /// End Sequence of the message public static Task?> GetGroupMessage(this BotContext bot, uint groupUin, uint startSequence, uint endSequence) - => bot.ContextCollection.Business.OperationLogic.GetGroupMessage(groupUin, startSequence, endSequence); + => bot.ContextCollection.Business.OperationLogic.GetGroupMessage(groupUin, startSequence, endSequence, CancellationToken.None); + + /// + /// Get the history message record, max 30 seqs + /// + /// target BotContext + /// target GroupUin + /// Start Sequence of the message + /// End Sequence of the message + /// The cancellation token + public static Task?> GetGroupMessage(this BotContext bot, uint groupUin, uint startSequence, uint endSequence, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.GetGroupMessage(groupUin, startSequence, endSequence, cancellationToken); /// /// Get the history message record for private message @@ -167,7 +336,18 @@ public static Task Like(this BotContext bot, uint targetUin, uint count = /// timestamp of the message chain /// number of message to be fetched before timestamp public static Task?> GetRoamMessage(this BotContext bot, uint friendUin, uint timestamp, uint count) - => bot.ContextCollection.Business.OperationLogic.GetRoamMessage(friendUin, timestamp, count); + => bot.ContextCollection.Business.OperationLogic.GetRoamMessage(friendUin, timestamp, count, CancellationToken.None); + + /// + /// Get the history message record for private message + /// + /// target BotContext + /// target FriendUin + /// timestamp of the message chain + /// number of message to be fetched before timestamp + /// The cancellation token + public static Task?> GetRoamMessage(this BotContext bot, uint friendUin, uint timestamp, uint count, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.GetRoamMessage(friendUin, timestamp, count, cancellationToken); /// /// Get the history message record for private message @@ -178,17 +358,40 @@ public static Task Like(this BotContext bot, uint targetUin, uint count = public static Task?> GetRoamMessage(this BotContext bot, MessageChain targetChain, uint count) { uint timestamp = (uint)new DateTimeOffset(targetChain.Time).ToUnixTimeSeconds(); - return bot.ContextCollection.Business.OperationLogic.GetRoamMessage(targetChain.FriendUin, timestamp, count); + return bot.ContextCollection.Business.OperationLogic.GetRoamMessage(targetChain.FriendUin, timestamp, count, CancellationToken.None); + } + + /// + /// Get the history message record for private message + /// + /// target BotContext + /// target chain + /// number of message to be fetched before timestamp + /// The cancellation token + public static Task?> GetRoamMessage(this BotContext bot, MessageChain targetChain, uint count, CancellationToken cancellationToken) + { + uint timestamp = (uint)new DateTimeOffset(targetChain.Time).ToUnixTimeSeconds(); + return bot.ContextCollection.Business.OperationLogic.GetRoamMessage(targetChain.FriendUin, timestamp, count, cancellationToken); } public static Task?> GetC2cMessage(this BotContext bot, uint friendUin, uint startSequence, uint endSequence) { - return bot.ContextCollection.Business.OperationLogic.GetC2cMessage(friendUin, startSequence, endSequence); + return bot.ContextCollection.Business.OperationLogic.GetC2cMessage(friendUin, startSequence, endSequence, CancellationToken.None); + } + + public static Task?> GetC2cMessage(this BotContext bot, uint friendUin, uint startSequence, uint endSequence, CancellationToken cancellationToken) + { + return bot.ContextCollection.Business.OperationLogic.GetC2cMessage(friendUin, startSequence, endSequence, cancellationToken); } public static Task<(int code, List? chains)> GetMessagesByResId(this BotContext bot, string resId) { - return bot.ContextCollection.Business.OperationLogic.GetMessagesByResId(resId); + return bot.ContextCollection.Business.OperationLogic.GetMessagesByResId(resId, CancellationToken.None); + } + + public static Task<(int code, List? chains)> GetMessagesByResId(this BotContext bot, string resId, CancellationToken cancellationToken) + { + return bot.ContextCollection.Business.OperationLogic.GetMessagesByResId(resId, cancellationToken); } /// @@ -198,28 +401,59 @@ public static Task Like(this BotContext bot, uint targetUin, uint count = /// target groupUin /// public static Task GroupClockIn(this BotContext bot, uint groupUin) - => bot.ContextCollection.Business.OperationLogic.GroupClockIn(groupUin); + => bot.ContextCollection.Business.OperationLogic.GroupClockIn(groupUin, CancellationToken.None); + + /// + /// Do group clock in (群打卡) + /// + /// target BotContext + /// target groupUin + /// The cancellation token + /// + public static Task GroupClockIn(this BotContext bot, uint groupUin, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.GroupClockIn(groupUin, cancellationToken); public static Task FetchUserInfo(this BotContext bot, uint uin, bool refreshCache = false) - => bot.ContextCollection.Business.OperationLogic.FetchUserInfo(uin, refreshCache); + => bot.ContextCollection.Business.OperationLogic.FetchUserInfo(uin, refreshCache, CancellationToken.None); + + public static Task FetchUserInfo(this BotContext bot, uint uin, bool refreshCache, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.FetchUserInfo(uin, refreshCache, cancellationToken); public static Task?> FetchCustomFace(this BotContext bot) - => bot.ContextCollection.Business.OperationLogic.FetchCustomFace(); + => bot.ContextCollection.Business.OperationLogic.FetchCustomFace(CancellationToken.None); + + public static Task?> FetchCustomFace(this BotContext bot, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.FetchCustomFace(cancellationToken); public static Task UploadLongMessage(this BotContext bot, List chains) - => bot.ContextCollection.Business.OperationLogic.UploadLongMessage(chains); + => bot.ContextCollection.Business.OperationLogic.UploadLongMessage(chains, CancellationToken.None); + + public static Task UploadLongMessage(this BotContext bot, List chains, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.UploadLongMessage(chains, cancellationToken); public static Task MarkAsRead(this BotContext bot, MessageChain targetChain) { uint timestamp = (uint)(targetChain.Time - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds; - return bot.ContextCollection.Business.OperationLogic.MarkAsRead(targetChain.GroupUin ?? 0, targetChain.Uid, targetChain.Sequence, timestamp); + return bot.ContextCollection.Business.OperationLogic.MarkAsRead(targetChain.GroupUin ?? 0, targetChain.Uid, targetChain.Sequence, timestamp, CancellationToken.None); + } + + public static Task MarkAsRead(this BotContext bot, MessageChain targetChain, CancellationToken cancellationToken) + { + uint timestamp = (uint)(targetChain.Time - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds; + return bot.ContextCollection.Business.OperationLogic.MarkAsRead(targetChain.GroupUin ?? 0, targetChain.Uid, targetChain.Sequence, timestamp, cancellationToken); } public static Task UploadFriendFile(this BotContext bot, uint targetUin, FileEntity fileEntity) - => bot.ContextCollection.Business.OperationLogic.UploadFriendFile(targetUin, fileEntity); + => bot.ContextCollection.Business.OperationLogic.UploadFriendFile(targetUin, fileEntity, CancellationToken.None); + + public static Task UploadFriendFile(this BotContext bot, uint targetUin, FileEntity fileEntity, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.UploadFriendFile(targetUin, fileEntity, cancellationToken); public static Task FriendPoke(this BotContext bot, uint friendUin) - => bot.ContextCollection.Business.OperationLogic.FriendPoke(friendUin); + => bot.ContextCollection.Business.OperationLogic.FriendPoke(friendUin, CancellationToken.None); + + public static Task FriendPoke(this BotContext bot, uint friendUin, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.FriendPoke(friendUin, cancellationToken); /// /// Send a special window shake to friend @@ -228,7 +462,17 @@ public static Task FriendPoke(this BotContext bot, uint friendUin) /// face type /// count of face public static Task FriendSpecialShake(this BotContext bot, uint friendUin, SpecialPokeFaceType type, uint count) - => bot.ContextCollection.Business.OperationLogic.FriendSpecialShake(friendUin, type, count); + => bot.ContextCollection.Business.OperationLogic.FriendSpecialShake(friendUin, type, count, CancellationToken.None); + + /// + /// Send a special window shake to friend + /// + /// target friend uin + /// face type + /// count of face + /// The cancellation token + public static Task FriendSpecialShake(this BotContext bot, uint friendUin, SpecialPokeFaceType type, uint count, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.FriendSpecialShake(friendUin, type, count, cancellationToken); /// /// Send a window shake to friend @@ -237,10 +481,23 @@ public static Task FriendSpecialShake(this BotContext bot, uint f /// face type /// How big the face will be displayed ([0,3] is valid) public static Task FriendShake(this BotContext bot, uint friendUin, PokeFaceType type, ushort strength) - => bot.ContextCollection.Business.OperationLogic.FriendShake(friendUin, type, strength); + => bot.ContextCollection.Business.OperationLogic.FriendShake(friendUin, type, strength, CancellationToken.None); + + /// + /// Send a window shake to friend + /// + /// target friend uin + /// face type + /// How big the face will be displayed ([0,3] is valid) + /// The cancellation token + public static Task FriendShake(this BotContext bot, uint friendUin, PokeFaceType type, ushort strength, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.FriendShake(friendUin, type, strength, cancellationToken); public static Task?> FetchMarketFaceKey(this BotContext bot, List faceIds) - => bot.ContextCollection.Business.OperationLogic.FetchMarketFaceKey(faceIds); + => bot.ContextCollection.Business.OperationLogic.FetchMarketFaceKey(faceIds, CancellationToken.None); + + public static Task?> FetchMarketFaceKey(this BotContext bot, List faceIds, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.FetchMarketFaceKey(faceIds, cancellationToken); /// /// Set the avatar of the bot itself @@ -248,5 +505,14 @@ public static Task FriendShake(this BotContext bot, uint friendUi /// target /// The avatar object, public static Task SetAvatar(this BotContext bot, ImageEntity avatar) - => bot.ContextCollection.Business.OperationLogic.SetAvatar(avatar); + => bot.ContextCollection.Business.OperationLogic.SetAvatar(avatar, CancellationToken.None); + + /// + /// Set the avatar of the bot itself + /// + /// target + /// The avatar object, + /// The cancellation token + public static Task SetAvatar(this BotContext bot, ImageEntity avatar, CancellationToken cancellationToken) + => bot.ContextCollection.Business.OperationLogic.SetAvatar(avatar, cancellationToken); } diff --git a/Lagrange.Core/Internal/Context/BusinessContext.cs b/Lagrange.Core/Internal/Context/BusinessContext.cs index 9b5e44658..40f213054 100644 --- a/Lagrange.Core/Internal/Context/BusinessContext.cs +++ b/Lagrange.Core/Internal/Context/BusinessContext.cs @@ -73,12 +73,16 @@ private void RegisterLogics() } } - public async Task PushEvent(ProtocolEvent @event) + public async Task PushEvent(ProtocolEvent @event, CancellationToken cancellationToken) { try { var packets = Collection.Service.ResolvePacketByEvent(@event); - foreach (var packet in packets) await Collection.Packet.PostPacket(packet); + foreach (var packet in packets) + { + cancellationToken.ThrowIfCancellationRequested(); + await Collection.Packet.PostPacket(packet); + } } catch { @@ -91,25 +95,32 @@ public async Task PushEvent(ProtocolEvent @event) /// /// Send Event to the Server, goes through the given context /// - public async Task> SendEvent(ProtocolEvent @event) + public async Task> SendEvent(ProtocolEvent @event, CancellationToken cancellationToken) { - await HandleOutgoingEvent(@event); + await HandleOutgoingEvent(@event, cancellationToken); var result = new List(); - + + cancellationToken.ThrowIfCancellationRequested(); + try { var packets = Collection.Service.ResolvePacketByEvent(@event); foreach (var packet in packets) { - var returnVal = await Collection.Packet.SendPacket(packet); + var returnVal = await Collection.Packet.SendPacket(packet, cancellationToken); var resolved = Collection.Service.ResolveEventByPacket(returnVal); foreach (var protocol in resolved) { - await HandleIncomingEvent(protocol); + await HandleIncomingEvent(protocol, cancellationToken); result.Add(protocol); } } } + catch (TaskCanceledException) + { + // if task is cancelled, we should throw the exception + throw; + } catch (Exception e) { Collection.Log.LogWarning(Tag, $"Error when processing the event: {@event}"); @@ -119,7 +130,7 @@ public async Task> SendEvent(ProtocolEvent @event) return result; } - public async Task HandleIncomingEvent(ProtocolEvent @event) + public async Task HandleIncomingEvent(ProtocolEvent @event, CancellationToken cancellationToken) { _businessLogics.TryGetValue(typeof(ProtocolEvent), out var baseLogics); _businessLogics.TryGetValue(@event.GetType(), out var normalLogics); @@ -132,7 +143,12 @@ public async Task HandleIncomingEvent(ProtocolEvent @event) { try { - await logic.Incoming(@event); + await logic.Incoming(@event, cancellationToken); + } + catch (TaskCanceledException) + { + // if task is cancelled, we should throw the exception + throw; } catch (Exception e) { @@ -145,7 +161,7 @@ public async Task HandleIncomingEvent(ProtocolEvent @event) return true; } - public async Task HandleOutgoingEvent(ProtocolEvent @event) + public async Task HandleOutgoingEvent(ProtocolEvent @event, CancellationToken cancellationToken) { _businessLogics.TryGetValue(typeof(ProtocolEvent), out var baseLogics); _businessLogics.TryGetValue(@event.GetType(), out var normalLogics); @@ -158,7 +174,12 @@ public async Task HandleOutgoingEvent(ProtocolEvent @event) { try { - await logic.Outgoing(@event); + await logic.Outgoing(@event, cancellationToken); + } + catch (TaskCanceledException) + { + // if task is cancelled, we should throw the exception + throw; } catch (Exception e) { @@ -183,7 +204,7 @@ public async Task HandleServerPacket(SsoPacket packet) var events = Collection.Service.ResolveEventByPacket(packet); foreach (var @event in events) { - var isSuccessful = await Collection.Business.HandleIncomingEvent(@event); + var isSuccessful = await Collection.Business.HandleIncomingEvent(@event, CancellationToken.None); if (!isSuccessful) break; success = true; @@ -199,4 +220,4 @@ public async Task HandleServerPacket(SsoPacket packet) return success; } -} \ No newline at end of file +} diff --git a/Lagrange.Core/Internal/Context/HighwayContext.cs b/Lagrange.Core/Internal/Context/HighwayContext.cs index 8f7789b50..01a3bdfd0 100644 --- a/Lagrange.Core/Internal/Context/HighwayContext.cs +++ b/Lagrange.Core/Internal/Context/HighwayContext.cs @@ -57,7 +57,7 @@ public HighwayContext(ContextCollection collection, BotKeystore keystore, BotApp _concurrent = config.HighwayConcurrent; } - public async Task UploadResources(MessageChain chain) + public async Task UploadResources(MessageChain chain, CancellationToken cancellationToken = default) { foreach (var entity in chain) { @@ -65,8 +65,8 @@ public async Task UploadResources(MessageChain chain) { try { - if (chain.IsGroup) await uploader.UploadGroup(Collection, chain, entity); - else await uploader.UploadPrivate(Collection, chain, entity); + if (chain.IsGroup) await uploader.UploadGroup(Collection, chain, entity, cancellationToken); + else await uploader.UploadPrivate(Collection, chain, entity, cancellationToken); } catch { @@ -76,7 +76,7 @@ public async Task UploadResources(MessageChain chain) } } - public async Task ManualUploadEntity(IMessageEntity entity) + public async Task ManualUploadEntity(IMessageEntity entity, CancellationToken cancellationToken = default) { if (_uploaders.TryGetValue(entity.GetType(), out var uploader)) { @@ -86,7 +86,7 @@ public async Task ManualUploadEntity(IMessageEntity entity) string uid = Collection.Keystore.Uid ?? ""; var chain = new MessageChain(uin, uid, uid) { entity }; - await uploader.UploadPrivate(Collection, chain, entity); + await uploader.UploadPrivate(Collection, chain, entity, cancellationToken); } catch { @@ -95,11 +95,11 @@ public async Task ManualUploadEntity(IMessageEntity entity) } } - public async Task UploadSrcByStreamAsync(int commonId, Stream data, byte[] ticket, byte[] md5, byte[]? extendInfo = null) + public async Task UploadSrcByStreamAsync(int commonId, Stream data, byte[] ticket, byte[] md5, byte[]? extendInfo = null, CancellationToken cancellation = default) { if (_uri == null) { - var highwayUrlEvent = await Collection.Business.SendEvent(HighwayUrlEvent.Create()); + var highwayUrlEvent = await Collection.Business.SendEvent(HighwayUrlEvent.Create(), cancellation); var result = (HighwayUrlEvent)highwayUrlEvent[0]; _uri = result.HighwayUrls[1][0]; } @@ -114,7 +114,7 @@ public async Task UploadSrcByStreamAsync(int commonId, Stream data, byte[] while (offset < fileSize) { var buffer = new byte[Math.Min(_chunkSize, fileSize - offset)]; - int payload = await data.ReadAsync(buffer.AsMemory()); + int payload = await data.ReadAsync(buffer.AsMemory(), cancellation); uint uin = Collection.Keystore.Uin; uint sequence = Interlocked.Increment(ref _sequence); var reqBody = new UpBlock(commonId, uin, sequence, (ulong)fileSize, (ulong)offset, ticket, md5, buffer, extendInfo); @@ -123,7 +123,7 @@ public async Task UploadSrcByStreamAsync(int commonId, Stream data, byte[] if (upBlocks.Count >= _concurrent || data.Position == data.Length) { - var tasks = upBlocks.Select(x => SendUpBlockAsync(x, _uri)).ToArray(); + var tasks = upBlocks.Select(x => SendUpBlockAsync(x, _uri, cancellation)).ToArray(); var results = await Task.WhenAll(tasks); success &= results.All(x => x); @@ -134,7 +134,7 @@ public async Task UploadSrcByStreamAsync(int commonId, Stream data, byte[] return success; } - private async Task SendUpBlockAsync(UpBlock upBlock, Uri server) + private async Task SendUpBlockAsync(UpBlock upBlock, Uri server, CancellationToken cancellation = default) { var head = new DataHighwayHead { @@ -171,7 +171,7 @@ private async Task SendUpBlockAsync(UpBlock upBlock, Uri server) }; bool isEnd = upBlock.Offset + (ulong)upBlock.Block.Length == upBlock.FileSize; - var payload = await SendPacketAsync(highwayHead, new BinaryPacket(upBlock.Block), server, isEnd); + var payload = await SendPacketAsync(highwayHead, new BinaryPacket(upBlock.Block), server, end: isEnd, cancellation: cancellation); var (respHead, resp) = ParsePacket(payload); Collection.Log.LogDebug(Tag, $"Highway Block Result: {respHead.ErrorCode} | {respHead.MsgSegHead?.RetCode} | {respHead.BytesRspExtendInfo?.Hex()} | {resp.ToArray().Hex()}"); @@ -179,7 +179,7 @@ private async Task SendUpBlockAsync(UpBlock upBlock, Uri server) return respHead.ErrorCode == 0; } - private Task SendPacketAsync(ReqDataHighwayHead head, BinaryPacket buffer, Uri server, bool end = true) + private Task SendPacketAsync(ReqDataHighwayHead head, BinaryPacket buffer, Uri server, bool end = true, CancellationToken cancellation = default) { using var stream = new MemoryStream(); Serializer.Serialize(stream, head); @@ -192,7 +192,7 @@ private Task SendPacketAsync(ReqDataHighwayHead head, BinaryPacket .WritePacket(buffer) .WriteByte(0x29); // packet end - return SendDataAsync(writer.ToArray(), server, end); + return SendDataAsync(writer.ToArray(), server, end, cancellation); } private static (RespDataHighwayHead, BinaryPacket) ParsePacket(BinaryPacket packet) @@ -210,7 +210,7 @@ private static (RespDataHighwayHead, BinaryPacket) ParsePacket(BinaryPacket pack throw new InvalidOperationException("Invalid packet"); } - private async Task SendDataAsync(byte[] packet, Uri server, bool end) + private async Task SendDataAsync(byte[] packet, Uri server, bool end, CancellationToken cancellation) { var content = new ByteArrayContent(packet); var request = new HttpRequestMessage(HttpMethod.Post, server) @@ -221,8 +221,8 @@ private async Task SendDataAsync(byte[] packet, Uri server, bool e { "Connection" , end ? "close" : "keep-alive" }, } }; - var response = await _client.SendAsync(request); - var data = await response.Content.ReadAsByteArrayAsync(); + var response = await _client.SendAsync(request, cancellation); + var data = await response.Content.ReadAsByteArrayAsync(cancellation); return new BinaryPacket(data); } @@ -242,4 +242,4 @@ public void Dispose() { _client.Dispose(); } -} \ No newline at end of file +} diff --git a/Lagrange.Core/Internal/Context/Logic/Implementation/CachingLogic.cs b/Lagrange.Core/Internal/Context/Logic/Implementation/CachingLogic.cs index 645946768..c7e766474 100644 --- a/Lagrange.Core/Internal/Context/Logic/Implementation/CachingLogic.cs +++ b/Lagrange.Core/Internal/Context/Logic/Implementation/CachingLogic.cs @@ -37,25 +37,25 @@ internal CachingLogic(ContextCollection collection) : base(collection) _cacheUsers = new ConcurrentDictionary(); } - public override Task Incoming(ProtocolEvent e) + public override Task Incoming(ProtocolEvent e, CancellationToken cancellationToken) { return e switch { - GroupSysDecreaseEvent groupSysDecreaseEvent when groupSysDecreaseEvent.MemberUid != Collection.Keystore.Uid => CacheUid(groupSysDecreaseEvent.GroupUin, true), - GroupSysIncreaseEvent groupSysIncreaseEvent => CacheUid(groupSysIncreaseEvent.GroupUin, true), - GroupSysAdminEvent groupSysAdminEvent => CacheUid(groupSysAdminEvent.GroupUin, true), + GroupSysDecreaseEvent groupSysDecreaseEvent when groupSysDecreaseEvent.MemberUid != Collection.Keystore.Uid => CacheUid(groupSysDecreaseEvent.GroupUin, force: true, cancellationToken: cancellationToken), + GroupSysIncreaseEvent groupSysIncreaseEvent => CacheUid(groupSysIncreaseEvent.GroupUin, force: true, cancellationToken: cancellationToken), + GroupSysAdminEvent groupSysAdminEvent => CacheUid(groupSysAdminEvent.GroupUin, force: true, cancellationToken: cancellationToken), _ => Task.CompletedTask, }; } - public async Task> GetCachedGroups(bool refreshCache) + public async Task> GetCachedGroups(bool refreshCache, CancellationToken cancellationToken) { if (_cachedGroupEntities.Count == 0 || refreshCache) { _cachedGroupEntities.Clear(); var fetchGroupsEvent = FetchGroupsEvent.Create(); - var events = await Collection.Business.SendEvent(fetchGroupsEvent); + var events = await Collection.Business.SendEvent(fetchGroupsEvent, cancellationToken); var groups = ((FetchGroupsEvent)events[0]).Groups; _cachedGroupEntities.AddRange(groups); @@ -65,60 +65,60 @@ public async Task> GetCachedGroups(bool refreshCache) return _cachedGroupEntities; } - public async Task ResolveUid(uint? groupUin, uint friendUin) + public async Task ResolveUid(uint? groupUin, uint friendUin, CancellationToken cancellationToken) { - if (_uinToUid.Count == 0) await ResolveFriendsUidAndFriendGroups(); + if (_uinToUid.Count == 0) await ResolveFriendsUidAndFriendGroups(cancellationToken); if (groupUin == null) return _uinToUid.GetValueOrDefault(friendUin); - await CacheUid(groupUin.Value); + await CacheUid(groupUin.Value, false, cancellationToken); return _uinToUid.GetValueOrDefault(friendUin); } - public async Task ResolveUin(uint? groupUin, string friendUid, bool force = false) + public async Task ResolveUin(uint? groupUin, string friendUid, bool force, CancellationToken cancellationToken) { - if (_uinToUid.Count == 0) await ResolveFriendsUidAndFriendGroups(); + if (_uinToUid.Count == 0) await ResolveFriendsUidAndFriendGroups(cancellationToken); if (groupUin == null) return _uinToUid.FirstOrDefault(x => x.Value == friendUid).Key; - await CacheUid(groupUin.Value, force); + await CacheUid(groupUin.Value, force: force, cancellationToken: cancellationToken); return _uinToUid.FirstOrDefault(x => x.Value == friendUid).Key; } - public async Task> GetCachedMembers(uint groupUin, bool refreshCache) + public async Task> GetCachedMembers(uint groupUin, bool refreshCache, CancellationToken cancellationToken) { if (!_cachedGroupMembers.TryGetValue(groupUin, out var members) || refreshCache) { - await ResolveMembersUid(groupUin); + await ResolveMembersUid(groupUin, cancellationToken); return _cachedGroupMembers.TryGetValue(groupUin, out members) ? members : new List(); } return members; } - public async Task> GetCachedFriends(bool refreshCache) + public async Task> GetCachedFriends(bool refreshCache, CancellationToken cancellationToken) { - if (_cachedFriends.Count == 0 || refreshCache) await ResolveFriendsUidAndFriendGroups(); + if (_cachedFriends.Count == 0 || refreshCache) await ResolveFriendsUidAndFriendGroups(cancellationToken); return _cachedFriends; } - public async Task GetCachedUsers(uint uin, bool refreshCache) + public async Task GetCachedUsers(uint uin, bool refreshCache, CancellationToken cancellationToken) { - if (!_cacheUsers.ContainsKey(uin) || refreshCache) await ResolveUser(uin); + if (!_cacheUsers.ContainsKey(uin) || refreshCache) await ResolveUser(uin, cancellationToken); if (!_cacheUsers.TryGetValue(uin, out BotUserInfo? info)) return null; return info; } - private async Task CacheUid(uint groupUin, bool force = false) + private async Task CacheUid(uint groupUin, bool force, CancellationToken cancellationToken) { if (!_cachedGroups.Contains(groupUin) || force) { Collection.Log.LogVerbose(Tag, $"Caching group members: {groupUin}"); - await ResolveMembersUid(groupUin); + await ResolveMembersUid(groupUin, cancellationToken); _cachedGroups.Add(groupUin); } } - private async Task ResolveFriendsUidAndFriendGroups() + private async Task ResolveFriendsUidAndFriendGroups(CancellationToken cancellationToken) { uint? next = null; var friends = new List(); @@ -126,7 +126,7 @@ private async Task ResolveFriendsUidAndFriendGroups() do { var @event = FetchFriendsEvent.Create(next); - var results = await Collection.Business.SendEvent(@event); + var results = await Collection.Business.SendEvent(@event, cancellationToken); if (results.Count == 0) { @@ -153,10 +153,10 @@ private async Task ResolveFriendsUidAndFriendGroups() _cachedFriends.AddRange(friends); } - private async Task ResolveMembersUid(uint groupUin) + private async Task ResolveMembersUid(uint groupUin, CancellationToken cancellationToken) { var fetchFriendsEvent = FetchMembersEvent.Create(groupUin); - var events = await Collection.Business.SendEvent(fetchFriendsEvent); + var events = await Collection.Business.SendEvent(fetchFriendsEvent, cancellationToken); if (events.Count != 0) { @@ -166,7 +166,7 @@ private async Task ResolveMembersUid(uint groupUin) while (token != null) { var next = FetchMembersEvent.Create(groupUin, token); - var results = await Collection.Business.SendEvent(next); + var results = await Collection.Business.SendEvent(next, cancellationToken); @event.Members.AddRange(((FetchMembersEvent)results[0]).Members); token = ((FetchMembersEvent)results[0]).Token; } @@ -181,13 +181,13 @@ private async Task ResolveMembersUid(uint groupUin) } } - private async Task ResolveUser(uint uin) + private async Task ResolveUser(uint uin, CancellationToken cancellationToken) { - var events = await Collection.Business.SendEvent(FetchUserInfoEvent.Create(uin)); + var events = await Collection.Business.SendEvent(FetchUserInfoEvent.Create(uin), cancellationToken); if (events.Count != 0 && events[0] is FetchUserInfoEvent { } @event) { _cacheUsers.AddOrUpdate(uin, @event.UserInfo, (_key, _value) => @event.UserInfo); } } -} \ No newline at end of file +} diff --git a/Lagrange.Core/Internal/Context/Logic/Implementation/MessagingLogic.cs b/Lagrange.Core/Internal/Context/Logic/Implementation/MessagingLogic.cs index 9da1c8f2c..f9267a8fe 100644 --- a/Lagrange.Core/Internal/Context/Logic/Implementation/MessagingLogic.cs +++ b/Lagrange.Core/Internal/Context/Logic/Implementation/MessagingLogic.cs @@ -46,15 +46,15 @@ internal class MessagingLogic : LogicBase internal MessagingLogic(ContextCollection collection) : base(collection) { } - public override async Task Incoming(ProtocolEvent e) + public override async Task Incoming(ProtocolEvent e, CancellationToken cancellationToken) { switch (e) { case PushMessageEvent push: { if (push.Chain.Count == 0) return; - await ResolveIncomingChain(push.Chain); - await ResolveChainMetadata(push.Chain); + await ResolveIncomingChain(push.Chain, cancellationToken); + await ResolveChainMetadata(push.Chain, cancellationToken); MessageFilter.Filter(push.Chain); var chain = push.Chain; @@ -76,8 +76,8 @@ public override async Task Incoming(ProtocolEvent e) foreach (var chain in get.Chains) { if (chain.Count == 0) return; - await ResolveIncomingChain(chain); - await ResolveChainMetadata(chain); + await ResolveIncomingChain(chain, cancellationToken); + await ResolveChainMetadata(chain, cancellationToken); MessageFilter.Filter(chain); } break; @@ -87,40 +87,40 @@ public override async Task Incoming(ProtocolEvent e) foreach (var chain in get.Chains) { if (chain.Count == 0) return; - await ResolveIncomingChain(chain); - await ResolveChainMetadata(chain); + await ResolveIncomingChain(chain, cancellationToken); + await ResolveChainMetadata(chain, cancellationToken); MessageFilter.Filter(chain); } break; } case GroupSysInviteEvent invite: { - uint invitorUin = await Collection.Business.CachingLogic.ResolveUin(null, invite.InvitorUid) ?? 0; + uint invitorUin = await Collection.Business.CachingLogic.ResolveUin(null, invite.InvitorUid, false, cancellationToken) ?? 0; var inviteArgs = new GroupInvitationEvent(invite.GroupUin, invitorUin); Collection.Invoker.PostEvent(inviteArgs); break; } case GroupSysAdminEvent admin: { - uint adminUin = await Collection.Business.CachingLogic.ResolveUin(admin.GroupUin, admin.Uid) ?? 0; + uint adminUin = await Collection.Business.CachingLogic.ResolveUin(admin.GroupUin, admin.Uid, false, cancellationToken) ?? 0; var adminArgs = new GroupAdminChangedEvent(admin.GroupUin, adminUin, admin.IsPromoted); Collection.Invoker.PostEvent(adminArgs); break; } case GroupSysIncreaseEvent increase: { - uint memberUin = await Collection.Business.CachingLogic.ResolveUin(increase.GroupUin, increase.MemberUid, true) ?? 0; + uint memberUin = await Collection.Business.CachingLogic.ResolveUin(increase.GroupUin, increase.MemberUid, true, cancellationToken) ?? 0; uint? invitorUin = null; - if (increase.InvitorUid != null) invitorUin = await Collection.Business.CachingLogic.ResolveUin(increase.GroupUin, increase.InvitorUid); + if (increase.InvitorUid != null) invitorUin = await Collection.Business.CachingLogic.ResolveUin(increase.GroupUin, increase.InvitorUid, false, cancellationToken); var increaseArgs = new GroupMemberIncreaseEvent(increase.GroupUin, memberUin, invitorUin, increase.Type); Collection.Invoker.PostEvent(increaseArgs); break; } case GroupSysDecreaseEvent decrease: { - uint memberUin = await Collection.Business.CachingLogic.ResolveUin(decrease.GroupUin, decrease.MemberUid) ?? 0; + uint memberUin = await Collection.Business.CachingLogic.ResolveUin(decrease.GroupUin, decrease.MemberUid, false, cancellationToken) ?? 0; uint? operatorUin = null; - if (decrease.OperatorUid != null) operatorUin = await Collection.Business.CachingLogic.ResolveUin(decrease.GroupUin, decrease.OperatorUid); + if (decrease.OperatorUid != null) operatorUin = await Collection.Business.CachingLogic.ResolveUin(decrease.GroupUin, decrease.OperatorUid, false, cancellationToken); var decreaseArgs = new GroupMemberDecreaseEvent(decrease.GroupUin, memberUin, operatorUin, decrease.Type); Collection.Invoker.PostEvent(decreaseArgs); break; @@ -139,7 +139,7 @@ public override async Task Incoming(ProtocolEvent e) } case GroupSysReactionEvent reaction: { - uint operatorUin = await Collection.Business.CachingLogic.ResolveUin(reaction.TargetGroupUin, reaction.OperatorUid) ?? 0; + uint operatorUin = await Collection.Business.CachingLogic.ResolveUin(reaction.TargetGroupUin, reaction.OperatorUid, false, cancellationToken) ?? 0; var pokeArgs = new GroupReactionEvent(reaction.TargetGroupUin, reaction.TargetSequence, operatorUin, reaction.IsAdd, reaction.Code, reaction.Count); Collection.Invoker.PostEvent(pokeArgs); break; @@ -159,25 +159,25 @@ public override async Task Incoming(ProtocolEvent e) case GroupSysMuteEvent groupMute: { uint? operatorUin = null; - if (groupMute.OperatorUid != null) operatorUin = await Collection.Business.CachingLogic.ResolveUin(groupMute.GroupUin, groupMute.OperatorUid); + if (groupMute.OperatorUid != null) operatorUin = await Collection.Business.CachingLogic.ResolveUin(groupMute.GroupUin, groupMute.OperatorUid, false, cancellationToken); var muteArgs = new GroupMuteEvent(groupMute.GroupUin, operatorUin, groupMute.IsMuted); Collection.Invoker.PostEvent(muteArgs); break; } case GroupSysMemberMuteEvent memberMute: { - uint memberUin = await Collection.Business.CachingLogic.ResolveUin(memberMute.GroupUin, memberMute.TargetUid) ?? 0; + uint memberUin = await Collection.Business.CachingLogic.ResolveUin(memberMute.GroupUin, memberMute.TargetUid, false, cancellationToken) ?? 0; uint? operatorUin = null; - if (memberMute.OperatorUid != null) operatorUin = await Collection.Business.CachingLogic.ResolveUin(memberMute.GroupUin, memberMute.OperatorUid); + if (memberMute.OperatorUid != null) operatorUin = await Collection.Business.CachingLogic.ResolveUin(memberMute.GroupUin, memberMute.OperatorUid, false, cancellationToken); var muteArgs = new GroupMemberMuteEvent(memberMute.GroupUin, memberUin, operatorUin, memberMute.Duration); Collection.Invoker.PostEvent(muteArgs); break; } case GroupSysRecallEvent recall: { - uint authorUin = await Collection.Business.CachingLogic.ResolveUin(recall.GroupUin, recall.AuthorUid) ?? 0; + uint authorUin = await Collection.Business.CachingLogic.ResolveUin(recall.GroupUin, recall.AuthorUid, false, cancellationToken) ?? 0; uint operatorUin = 0; - if (recall.OperatorUid != null) operatorUin = await Collection.Business.CachingLogic.ResolveUin(recall.GroupUin, recall.OperatorUid) ?? 0; + if (recall.OperatorUid != null) operatorUin = await Collection.Business.CachingLogic.ResolveUin(recall.GroupUin, recall.OperatorUid, false, cancellationToken) ?? 0; var recallArgs = new GroupRecallEvent(recall.GroupUin, authorUin, operatorUin, recall.Sequence, recall.Time, recall.Random, recall.Tip); Collection.Invoker.PostEvent(recallArgs); break; @@ -185,7 +185,7 @@ public override async Task Incoming(ProtocolEvent e) case GroupSysRequestJoinEvent join: { var fetchUidEvent = FetchUserInfoEvent.Create(join.TargetUid); - var results = await Collection.Business.SendEvent(fetchUidEvent); + var results = await Collection.Business.SendEvent(fetchUidEvent, cancellationToken); uint targetUin = results.Count == 0 ? 0 : ((FetchUserInfoEvent)results[0]).UserInfo.Uin; var joinArgs = new GroupJoinRequestEvent(join.GroupUin, targetUin); @@ -194,10 +194,10 @@ public override async Task Incoming(ProtocolEvent e) } case GroupSysRequestInvitationEvent invitation: { - uint invitorUin = await Collection.Business.CachingLogic.ResolveUin(invitation.GroupUin, invitation.InvitorUid) ?? 0; + uint invitorUin = await Collection.Business.CachingLogic.ResolveUin(invitation.GroupUin, invitation.InvitorUid, false, cancellationToken) ?? 0; var fetchUidEvent = FetchUserInfoEvent.Create(invitation.TargetUid); - var results = await Collection.Business.SendEvent(fetchUidEvent); + var results = await Collection.Business.SendEvent(fetchUidEvent, cancellationToken); uint targetUin = results.Count == 0 ? 0 : ((FetchUserInfoEvent)results[0]).UserInfo.Uin; var invitationArgs = new GroupInvitationRequestEvent(invitation.GroupUin, targetUin, invitorUin); @@ -206,7 +206,7 @@ public override async Task Incoming(ProtocolEvent e) } case FriendSysRecallEvent recall: { - uint fromUin = await Collection.Business.CachingLogic.ResolveUin(null, recall.FromUid) ?? 0; + uint fromUin = await Collection.Business.CachingLogic.ResolveUin(null, recall.FromUid, false, cancellationToken) ?? 0; var recallArgs = new FriendRecallEvent(fromUin, recall.ClientSequence, recall.Time, recall.Random, recall.Tip); Collection.Invoker.PostEvent(recallArgs); break; @@ -230,7 +230,7 @@ public override async Task Incoming(ProtocolEvent e) foreach (var chain in multi.Chains) { if (chain.Count == 0) continue; - await ResolveIncomingChain(chain); + await ResolveIncomingChain(chain, cancellationToken); MessageFilter.Filter(chain); } } @@ -246,7 +246,7 @@ public override async Task Incoming(ProtocolEvent e) } } - public override async Task Outgoing(ProtocolEvent e) + public override async Task Outgoing(ProtocolEvent e, CancellationToken cancellationToken) { switch (e) { @@ -254,23 +254,23 @@ public override async Task Outgoing(ProtocolEvent e) { foreach (var chain in chains) { - await ResolveChainMetadata(chain); - await ResolveOutgoingChain(chain); - await Collection.Highway.UploadResources(chain); + await ResolveChainMetadata(chain, cancellationToken); + await ResolveOutgoingChain(chain, cancellationToken); + await Collection.Highway.UploadResources(chain, cancellationToken); } break; } case SendMessageEvent send: // resolve Uin to Uid { - await ResolveChainMetadata(send.Chain); - await ResolveOutgoingChain(send.Chain); - await Collection.Highway.UploadResources(send.Chain); + await ResolveChainMetadata(send.Chain, cancellationToken); + await ResolveOutgoingChain(send.Chain, cancellationToken); + await Collection.Highway.UploadResources(send.Chain, cancellationToken); break; } } } - private async Task ResolveIncomingChain(MessageChain chain) + private async Task ResolveIncomingChain(MessageChain chain, CancellationToken cancellationToken) { foreach (var entity in chain) { @@ -279,7 +279,7 @@ private async Task ResolveIncomingChain(MessageChain chain) case FileEntity { FileHash: not null, FileUuid: not null } file: // private { var @event = FileDownloadEvent.Create(file.FileUuid, file.FileHash, chain.Uid, chain.SelfUid); - var results = await Collection.Business.SendEvent(@event); + var results = await Collection.Business.SendEvent(@event, cancellationToken); if (results.Count != 0) { var result = (FileDownloadEvent)results[0]; @@ -291,7 +291,7 @@ private async Task ResolveIncomingChain(MessageChain chain) case FileEntity { FileId: not null } file when chain.GroupUin is not null: // group { var @event = GroupFSDownloadEvent.Create(chain.GroupUin.Value, file.FileId); - var results = await Collection.Business.SendEvent(@event); + var results = await Collection.Business.SendEvent(@event, cancellationToken); if (results.Count != 0) { var result = (GroupFSDownloadEvent)results[0]; @@ -303,7 +303,7 @@ private async Task ResolveIncomingChain(MessageChain chain) case MultiMsgEntity { ResId: not null } multi: { var @event = MultiMsgDownloadEvent.Create(chain.Uid ?? "", multi.ResId); - var results = await Collection.Business.SendEvent(@event); + var results = await Collection.Business.SendEvent(@event, cancellationToken); if (results.Count != 0) { var result = (MultiMsgDownloadEvent)results[0]; @@ -318,7 +318,7 @@ private async Task ResolveIncomingChain(MessageChain chain) ? RecordGroupDownloadEvent.Create(chain.GroupUin ?? 0, record.MsgInfo) : RecordDownloadEvent.Create(chain.Uid ?? string.Empty, record.MsgInfo); - var results = await Collection.Business.SendEvent(@event); + var results = await Collection.Business.SendEvent(@event, cancellationToken); if (results.Count != 0) { var result = (RecordDownloadEvent)results[0]; @@ -333,7 +333,7 @@ private async Task ResolveIncomingChain(MessageChain chain) ? RecordGroupDownloadEvent.Create(chain.GroupUin ?? 0, record.AudioUuid) : RecordDownloadEvent.Create(chain.Uid ?? string.Empty, record.AudioUuid); - var results = await Collection.Business.SendEvent(@event); + var results = await Collection.Business.SendEvent(@event, cancellationToken); if (results.Count != 0) { var result = (RecordDownloadEvent)results[0]; @@ -345,10 +345,10 @@ private async Task ResolveIncomingChain(MessageChain chain) case VideoEntity { VideoUuid: not null } video: { string uid = (chain.IsGroup - ? await Collection.Business.CachingLogic.ResolveUid(chain.GroupUin, chain.FriendUin) + ? await Collection.Business.CachingLogic.ResolveUid(chain.GroupUin, chain.FriendUin, cancellationToken) : chain.Uid) ?? ""; var @event = VideoDownloadEvent.Create(video.VideoUuid, uid, video.FilePath, "", "", chain.IsGroup); - var results = await Collection.Business.SendEvent(@event); + var results = await Collection.Business.SendEvent(@event, cancellationToken); if (results.Count != 0) { var result = (VideoDownloadEvent)results[0]; @@ -363,7 +363,7 @@ private async Task ResolveIncomingChain(MessageChain chain) ? ImageGroupDownloadEvent.Create(image.GroupUin ?? 0, image.MsgInfo) : ImageDownloadEvent.Create(image.FriendUid ?? string.Empty, image.MsgInfo); - var results = await Collection.Business.SendEvent(@event); + var results = await Collection.Business.SendEvent(@event, cancellationToken); if (results.Count != 0) { var result = (ImageDownloadEvent)results[0]; @@ -376,7 +376,7 @@ private async Task ResolveIncomingChain(MessageChain chain) } } - private async Task ResolveOutgoingChain(MessageChain chain) + private async Task ResolveOutgoingChain(MessageChain chain, CancellationToken cancellationToken) { foreach (var entity in chain) { @@ -385,24 +385,24 @@ private async Task ResolveOutgoingChain(MessageChain chain) case ForwardEntity forward when forward.TargetUin != 0: { var cache = Collection.Business.CachingLogic; - forward.Uid = await cache.ResolveUid(chain.GroupUin, forward.TargetUin) ?? throw new Exception($"Failed to resolve Uid for Uin {forward.TargetUin}"); + forward.Uid = await cache.ResolveUid(chain.GroupUin, forward.TargetUin, cancellationToken) ?? throw new Exception($"Failed to resolve Uid for Uin {forward.TargetUin}"); break; } case MentionEntity mention when mention.Uin != 0: { var cache = Collection.Business.CachingLogic; - mention.Uid = await cache.ResolveUid(chain.GroupUin, mention.Uin) ?? throw new Exception($"Failed to resolve Uid for Uin {mention.Uin}"); + mention.Uid = await cache.ResolveUid(chain.GroupUin, mention.Uin, cancellationToken) ?? throw new Exception($"Failed to resolve Uid for Uin {mention.Uin}"); if (chain is { IsGroup: true, GroupUin: not null } && mention.Name is null) { - var members = await Collection.Business.CachingLogic.GetCachedMembers(chain.GroupUin.Value, false); + var members = await Collection.Business.CachingLogic.GetCachedMembers(chain.GroupUin.Value, false, cancellationToken); var member = members.FirstOrDefault(x => x.Uin == mention.Uin); if (member != null) mention.Name = $"@{member.MemberCard ?? member.MemberName}"; } else if (chain is { IsGroup: false } && mention.Name is null) { - var friends = await Collection.Business.CachingLogic.GetCachedFriends(false); + var friends = await Collection.Business.CachingLogic.GetCachedFriends(false, cancellationToken); string? friend = friends.FirstOrDefault(x => x.Uin == mention.Uin)?.Nickname; if (friend != null) mention.Name = $"@{friend}"; } @@ -414,7 +414,7 @@ private async Task ResolveOutgoingChain(MessageChain chain) if (chain.GroupUin != null) foreach (var c in multiMsg.Chains) c.GroupUin = chain.GroupUin; var multiMsgEvent = MultiMsgUploadEvent.Create(chain.GroupUin, multiMsg.Chains); - var results = await Collection.Business.SendEvent(multiMsgEvent); + var results = await Collection.Business.SendEvent(multiMsgEvent, cancellationToken); if (results.Count != 0) { var result = (MultiMsgUploadEvent)results[0]; @@ -425,7 +425,7 @@ private async Task ResolveOutgoingChain(MessageChain chain) case MultiMsgEntity { ResId: not null, Chains.Count: 0 } multiMsg: { var @event = MultiMsgDownloadEvent.Create(chain.Uid ?? "", multiMsg.ResId); - var results = await Collection.Business.SendEvent(@event); + var results = await Collection.Business.SendEvent(@event, cancellationToken); if (results.Count != 0) { var result = (MultiMsgDownloadEvent)results[0]; @@ -442,11 +442,11 @@ private async Task ResolveOutgoingChain(MessageChain chain) /// for both Incoming and Outgoing MessageChain /// /// The target chain - private async Task ResolveChainMetadata(MessageChain chain) + private async Task ResolveChainMetadata(MessageChain chain, CancellationToken cancellationToken) { if (chain is { IsGroup: true, GroupUin: not null }) { - var groups = await Collection.Business.CachingLogic.GetCachedMembers(chain.GroupUin.Value, false); + var groups = await Collection.Business.CachingLogic.GetCachedMembers(chain.GroupUin.Value, false, cancellationToken); chain.GroupMemberInfo = chain.FriendUin == 0 ? groups.FirstOrDefault(x => x.Uin == Collection.Keystore.Uin) : groups.FirstOrDefault(x => x.Uin == chain.FriendUin); @@ -455,7 +455,7 @@ private async Task ResolveChainMetadata(MessageChain chain) } else { - var friends = await Collection.Business.CachingLogic.GetCachedFriends(false); + var friends = await Collection.Business.CachingLogic.GetCachedFriends(false, cancellationToken); if (friends.FirstOrDefault(x => x.Uin == chain.FriendUin) is { } friend) { chain.FriendInfo = friend; diff --git a/Lagrange.Core/Internal/Context/Logic/Implementation/OperationLogic.cs b/Lagrange.Core/Internal/Context/Logic/Implementation/OperationLogic.cs index fdf82a6aa..5b182c060 100644 --- a/Lagrange.Core/Internal/Context/Logic/Implementation/OperationLogic.cs +++ b/Lagrange.Core/Internal/Context/Logic/Implementation/OperationLogic.cs @@ -18,29 +18,29 @@ internal class OperationLogic : LogicBase internal OperationLogic(ContextCollection collection) : base(collection) { } - public async Task> GetCookies(List domains) + public async Task> GetCookies(List domains, CancellationToken cancellation) { var fetchCookieEvent = FetchCookieEvent.Create(domains); - var events = await Collection.Business.SendEvent(fetchCookieEvent); + var events = await Collection.Business.SendEvent(fetchCookieEvent, cancellation); return events.Count != 0 ? ((FetchCookieEvent)events[0]).Cookies : new List(); } - public Task> FetchFriends(bool refreshCache = false) => - Collection.Business.CachingLogic.GetCachedFriends(refreshCache); + public Task> FetchFriends(bool refreshCache = false, CancellationToken cancellationToken = default) => + Collection.Business.CachingLogic.GetCachedFriends(refreshCache, cancellationToken); - public Task> FetchMembers(uint groupUin, bool refreshCache = false) => - Collection.Business.CachingLogic.GetCachedMembers(groupUin, refreshCache); + public Task> FetchMembers(uint groupUin, CancellationToken cancellationToken, bool refreshCache = false) => + Collection.Business.CachingLogic.GetCachedMembers(groupUin, refreshCache, cancellationToken); - public Task> FetchGroups(bool refreshCache) => - Collection.Business.CachingLogic.GetCachedGroups(refreshCache); + public Task> FetchGroups(bool refreshCache, CancellationToken cancellationToken) => + Collection.Business.CachingLogic.GetCachedGroups(refreshCache, cancellationToken); - public async Task SendMessage(MessageChain chain) + public async Task SendMessage(MessageChain chain, CancellationToken cancellation) { uint clientSeq = chain.ClientSequence; ulong messageId = chain.MessageId; var sendMessageEvent = SendMessageEvent.Create(chain); - var events = await Collection.Business.SendEvent(sendMessageEvent); + var events = await Collection.Business.SendEvent(sendMessageEvent, cancellation); if (events.Count == 0) return new MessageResult { Result = 9057 }; var result = ((SendMessageEvent)events[0]).MsgResult; @@ -49,47 +49,47 @@ public async Task SendMessage(MessageChain chain) return result; } - public async Task MuteGroupMember(uint groupUin, uint targetUin, uint duration) + public async Task MuteGroupMember(uint groupUin, uint targetUin, uint duration, CancellationToken cancellationToken) { - string? uid = await Collection.Business.CachingLogic.ResolveUid(groupUin, targetUin); + string? uid = await Collection.Business.CachingLogic.ResolveUid(groupUin, targetUin, cancellationToken); if (uid == null) return false; var muteGroupMemberEvent = GroupMuteMemberEvent.Create(groupUin, duration, uid); - var events = await Collection.Business.SendEvent(muteGroupMemberEvent); + var events = await Collection.Business.SendEvent(muteGroupMemberEvent, cancellationToken); return events.Count != 0 && ((GroupMuteMemberEvent)events[0]).ResultCode == 0; } - public async Task MuteGroupGlobal(uint groupUin, bool isMute) + public async Task MuteGroupGlobal(uint groupUin, bool isMute, CancellationToken cancellationToken) { var muteGroupMemberEvent = GroupMuteGlobalEvent.Create(groupUin, isMute); - var events = await Collection.Business.SendEvent(muteGroupMemberEvent); + var events = await Collection.Business.SendEvent(muteGroupMemberEvent, cancellationToken); return events.Count != 0 && ((GroupMuteGlobalEvent)events[0]).ResultCode == 0; } - public async Task KickGroupMember(uint groupUin, uint targetUin, bool rejectAddRequest, string reason) + public async Task KickGroupMember(uint groupUin, uint targetUin, bool rejectAddRequest, string reason, CancellationToken cancellationToken) { - string? uid = await Collection.Business.CachingLogic.ResolveUid(groupUin, targetUin); + string? uid = await Collection.Business.CachingLogic.ResolveUid(groupUin, targetUin, cancellationToken); if (uid == null) return false; var muteGroupMemberEvent = GroupKickMemberEvent.Create(groupUin, uid, rejectAddRequest, reason); - var events = await Collection.Business.SendEvent(muteGroupMemberEvent); + var events = await Collection.Business.SendEvent(muteGroupMemberEvent, cancellationToken); return events.Count != 0 && ((GroupKickMemberEvent)events[0]).ResultCode == 0; } - public async Task SetGroupAdmin(uint groupUin, uint targetUin, bool isAdmin) + public async Task SetGroupAdmin(uint groupUin, uint targetUin, bool isAdmin, CancellationToken cancellationToken) { - string? uid = await Collection.Business.CachingLogic.ResolveUid(groupUin, targetUin); + string? uid = await Collection.Business.CachingLogic.ResolveUid(groupUin, targetUin, cancellationToken); if (uid == null) return false; var setGroupAdminEvent = GroupSetAdminEvent.Create(groupUin, uid, isAdmin); - var events = await Collection.Business.SendEvent(setGroupAdminEvent); + var events = await Collection.Business.SendEvent(setGroupAdminEvent, cancellationToken); return events.Count != 0 && ((GroupSetAdminEvent)events[0]).ResultCode == 0; } - public async Task<(int, string?)> SetGroupTodo(uint groupUin, uint sequence) + public async Task<(int, string?)> SetGroupTodo(uint groupUin, uint sequence, CancellationToken cancellationToken) { var setGroupTodoEvent = GroupSetTodoEvent.Create(groupUin, sequence); - var events = await Collection.Business.SendEvent(setGroupTodoEvent); + var events = await Collection.Business.SendEvent(setGroupTodoEvent, cancellationToken); if (events.Count == 0) return (-1, "No Events"); @@ -98,10 +98,10 @@ public async Task SetGroupAdmin(uint groupUin, uint targetUin, bool isAdmi return (@event.ResultCode, @event.ResultMessage); } - public async Task<(int, string?)> RemoveGroupTodo(uint groupUin) + public async Task<(int, string?)> RemoveGroupTodo(uint groupUin, CancellationToken cancellationToken) { var setGroupTodoEvent = GroupRemoveTodoEvent.Create(groupUin); - var events = await Collection.Business.SendEvent(setGroupTodoEvent); + var events = await Collection.Business.SendEvent(setGroupTodoEvent, cancellationToken); if (events.Count == 0) return (-1, "No Event"); @@ -110,10 +110,10 @@ public async Task SetGroupAdmin(uint groupUin, uint targetUin, bool isAdmi return (@event.ResultCode, @event.ResultMessage); } - public async Task<(int, string?)> FinishGroupTodo(uint groupUin) + public async Task<(int, string?)> FinishGroupTodo(uint groupUin, CancellationToken cancellationToken) { var setGroupTodoEvent = GroupFinishTodoEvent.Create(groupUin); - var events = await Collection.Business.SendEvent(setGroupTodoEvent); + var events = await Collection.Business.SendEvent(setGroupTodoEvent, cancellationToken); if (events.Count == 0) return (-1, "No Event"); @@ -122,10 +122,10 @@ public async Task SetGroupAdmin(uint groupUin, uint targetUin, bool isAdmi return (@event.ResultCode, @event.ResultMessage); } - public async Task GetGroupTodo(uint groupUin) + public async Task GetGroupTodo(uint groupUin, CancellationToken cancellationToken) { var setGroupTodoEvent = GroupGetTodoEvent.Create(groupUin); - var events = await Collection.Business.SendEvent(setGroupTodoEvent); + var events = await Collection.Business.SendEvent(setGroupTodoEvent, cancellationToken); if (events.Count == 0) return new(-1, "No Event", 0, 0, string.Empty); @@ -140,73 +140,73 @@ public async Task GetGroupTodo(uint groupUin) ); } - public async Task SetGroupBot(uint BotId, uint On, uint groupUin) + public async Task SetGroupBot(uint BotId, uint On, uint groupUin, CancellationToken cancellationToken) { var muteBotEvent = GroupSetBotEvent.Create(BotId, On, groupUin); - var events = await Collection.Business.SendEvent(muteBotEvent); + var events = await Collection.Business.SendEvent(muteBotEvent, cancellationToken); return events.Count != 0 && ((GroupSetBotEvent)events[0]).ResultCode == 0; } - public async Task SetGroupBotHD(uint BotId, uint groupUin, string? data_1, string? data_2) + public async Task SetGroupBotHD(uint BotId, uint groupUin, string? data_1, string? data_2, CancellationToken cancellationToken) { var muteBotEvent = GroupSetBothdEvent.Create(BotId, groupUin, data_1, data_2); - var events = await Collection.Business.SendEvent(muteBotEvent); + var events = await Collection.Business.SendEvent(muteBotEvent, cancellationToken); return events.Count != 0 && ((GroupSetBothdEvent)events[0]).ResultCode == 0; } - public async Task RenameGroupMember(uint groupUin, uint targetUin, string targetName) + public async Task RenameGroupMember(uint groupUin, uint targetUin, string targetName, CancellationToken cancellationToken) { - string? uid = await Collection.Business.CachingLogic.ResolveUid(groupUin, targetUin); + string? uid = await Collection.Business.CachingLogic.ResolveUid(groupUin, targetUin, cancellationToken); if (uid == null) return false; var renameGroupEvent = RenameMemberEvent.Create(groupUin, uid, targetName); - var events = await Collection.Business.SendEvent(renameGroupEvent); + var events = await Collection.Business.SendEvent(renameGroupEvent, cancellationToken); return events.Count != 0 && ((RenameMemberEvent)events[0]).ResultCode == 0; } - public async Task RenameGroup(uint groupUin, string targetName) + public async Task RenameGroup(uint groupUin, string targetName, CancellationToken cancellationToken) { var renameGroupEvent = GroupRenameEvent.Create(groupUin, targetName); - var events = await Collection.Business.SendEvent(renameGroupEvent); + var events = await Collection.Business.SendEvent(renameGroupEvent, cancellationToken); return events.Count != 0 && ((GroupRenameEvent)events[0]).ResultCode == 0; } - public async Task RemarkGroup(uint groupUin, string targetRemark) + public async Task RemarkGroup(uint groupUin, string targetRemark, CancellationToken cancellationToken) { var renameGroupEvent = GroupRemarkEvent.Create(groupUin, targetRemark); - var events = await Collection.Business.SendEvent(renameGroupEvent); + var events = await Collection.Business.SendEvent(renameGroupEvent, cancellationToken); return events.Count != 0 && ((GroupRemarkEvent)events[0]).ResultCode == 0; } - public async Task LeaveGroup(uint groupUin) + public async Task LeaveGroup(uint groupUin, CancellationToken cancellationToken) { var leaveGroupEvent = GroupLeaveEvent.Create(groupUin); - var events = await Collection.Business.SendEvent(leaveGroupEvent); + var events = await Collection.Business.SendEvent(leaveGroupEvent, cancellationToken); return events.Count != 0 && ((GroupLeaveEvent)events[0]).ResultCode == 0; } - public async Task FetchGroupFSSpace(uint groupUin) + public async Task FetchGroupFSSpace(uint groupUin, CancellationToken cancellationToken) { var groupFSSpaceEvent = GroupFSSpaceEvent.Create(groupUin); - var events = await Collection.Business.SendEvent(groupFSSpaceEvent); + var events = await Collection.Business.SendEvent(groupFSSpaceEvent, cancellationToken); return ((GroupFSSpaceEvent)events[0]).TotalSpace - ((GroupFSSpaceEvent)events[0]).UsedSpace; } - public async Task FetchGroupFSCount(uint groupUin) + public async Task FetchGroupFSCount(uint groupUin, CancellationToken cancellationToken) { var groupFSSpaceEvent = GroupFSCountEvent.Create(groupUin); - var events = await Collection.Business.SendEvent(groupFSSpaceEvent); + var events = await Collection.Business.SendEvent(groupFSSpaceEvent, cancellationToken); return ((GroupFSCountEvent)events[0]).FileCount; } - public async Task> FetchGroupFSList(uint groupUin, string targetDirectory) + public async Task> FetchGroupFSList(uint groupUin, string targetDirectory, CancellationToken cancellationToken) { uint startIndex = 0; var entries = new List(); while (true) { var groupFSListEvent = GroupFSListEvent.Create(groupUin, targetDirectory, startIndex, 20); - var events = await Collection.Business.SendEvent(groupFSListEvent); + var events = await Collection.Business.SendEvent(groupFSListEvent, cancellationToken); if (events.Count == 0) break; entries.AddRange(((GroupFSListEvent)events[0]).FileEntries); if (((GroupFSListEvent)events[0]).IsEnd) break; @@ -215,63 +215,67 @@ public async Task> FetchGroupFSList(uint groupUin, string targ return entries; } - public async Task FetchGroupFSDownload(uint groupUin, string fileId) + public async Task FetchGroupFSDownload(uint groupUin, string fileId, CancellationToken cancellationToken) { var groupFSDownloadEvent = GroupFSDownloadEvent.Create(groupUin, fileId); - var events = await Collection.Business.SendEvent(groupFSDownloadEvent); + var events = await Collection.Business.SendEvent(groupFSDownloadEvent, cancellationToken); return $"{((GroupFSDownloadEvent)events[0]).FileUrl}{fileId}"; } - public async Task<(int, string)> GroupFSMove(uint groupUin, string fileId, string parentDirectory, string targetDirectory) + public async Task<(int, string)> GroupFSMove(uint groupUin, string fileId, string parentDirectory, string targetDirectory, CancellationToken cancellationToken) { var groupFSMoveEvent = GroupFSMoveEvent.Create(groupUin, fileId, parentDirectory, targetDirectory); - var events = await Collection.Business.SendEvent(groupFSMoveEvent); + var events = await Collection.Business.SendEvent(groupFSMoveEvent, cancellationToken); int retCode = events.Count > 0 ? ((GroupFSMoveEvent)events[0]).ResultCode : -1; string retMsg = events.Count > 0 ? ((GroupFSMoveEvent)events[0]).RetMsg : string.Empty; return (retCode, retMsg); } - public async Task<(int, string)> GroupFSDelete(uint groupUin, string fileId) + public async Task<(int, string)> GroupFSDelete(uint groupUin, string fileId, CancellationToken cancellationToken) { var groupFSDeleteEvent = GroupFSDeleteEvent.Create(groupUin, fileId); - var events = await Collection.Business.SendEvent(groupFSDeleteEvent); + var events = await Collection.Business.SendEvent(groupFSDeleteEvent, cancellationToken); int retCode = events.Count > 0 ? ((GroupFSDeleteEvent)events[0]).ResultCode : -1; string retMsg = events.Count > 0 ? ((GroupFSDeleteEvent)events[0]).RetMsg : string.Empty; return (retCode, retMsg); } - public async Task<(int, string)> GroupFSCreateFolder(uint groupUin, string name) + public async Task<(int, string)> GroupFSCreateFolder(uint groupUin, string name, CancellationToken cancellationToken) { var groupFSCreateFolderEvent = GroupFSCreateFolderEvent.Create(groupUin, name); - var events = await Collection.Business.SendEvent(groupFSCreateFolderEvent); + var events = await Collection.Business.SendEvent(groupFSCreateFolderEvent, cancellationToken); int retCode = events.Count > 0 ? ((GroupFSCreateFolderEvent)events[0]).ResultCode : -1; string retMsg = events.Count > 0 ? ((GroupFSCreateFolderEvent)events[0]).RetMsg : string.Empty; return (retCode, retMsg); } - public async Task<(int, string)> GroupFSDeleteFolder(uint groupUin, string folderId) + public async Task<(int, string)> GroupFSDeleteFolder(uint groupUin, string folderId, CancellationToken cancellationToken) { var groupFSDeleteFolderEvent = GroupFSDeleteFolderEvent.Create(groupUin, folderId); - var events = await Collection.Business.SendEvent(groupFSDeleteFolderEvent); + var events = await Collection.Business.SendEvent(groupFSDeleteFolderEvent, cancellationToken); int retCode = events.Count > 0 ? ((GroupFSDeleteFolderEvent)events[0]).ResultCode : -1; string retMsg = events.Count > 0 ? ((GroupFSDeleteFolderEvent)events[0]).RetMsg : string.Empty; return (retCode, retMsg); } - public async Task<(int, string)> GroupFSRenameFolder(uint groupUin, string folderId, string newFolderName) + public async Task<(int, string)> GroupFSRenameFolder(uint groupUin, string folderId, string newFolderName, CancellationToken cancellationToken) { var groupFSDeleteFolderEvent = GroupFSRenameFolderEvent.Create(groupUin, folderId, newFolderName); - var events = await Collection.Business.SendEvent(groupFSDeleteFolderEvent); + var events = await Collection.Business.SendEvent(groupFSDeleteFolderEvent, cancellationToken); int retCode = events.Count > 0 ? ((GroupFSRenameFolderEvent)events[0]).ResultCode : -1; string retMsg = events.Count > 0 ? ((GroupFSRenameFolderEvent)events[0]).RetMsg : ""; return (retCode, retMsg); } - public Task GroupFSUpload(uint groupUin, FileEntity fileEntity, string targetDirectory) + public Task GroupFSUpload(uint groupUin, FileEntity fileEntity, string targetDirectory, CancellationToken cancellationToken) { try { - return FileUploader.UploadGroup(Collection, MessageBuilder.Group(groupUin).Build(), fileEntity, targetDirectory); + return FileUploader.UploadGroup(Collection, MessageBuilder.Group(groupUin).Build(), fileEntity, targetDirectory, cancellationToken); + } + catch (TaskCanceledException) + { + throw; } catch { @@ -279,14 +283,18 @@ public Task GroupFSUpload(uint groupUin, FileEntity fileEntity, string tar } } - public async Task UploadFriendFile(uint targetUin, FileEntity fileEntity) + public async Task UploadFriendFile(uint targetUin, FileEntity fileEntity, CancellationToken cancellationToken) { - string? uid = await Collection.Business.CachingLogic.ResolveUid(null, targetUin); + string? uid = await Collection.Business.CachingLogic.ResolveUid(null, targetUin, cancellationToken); var chain = new MessageChain(targetUin, Collection.Keystore.Uid ?? "", uid ?? "") { fileEntity }; try { - return await FileUploader.UploadPrivate(Collection, chain, fileEntity); + return await FileUploader.UploadPrivate(Collection, chain, fileEntity, cancellationToken); + } + catch (TaskCanceledException) + { + throw; } catch { @@ -294,55 +302,55 @@ public async Task UploadFriendFile(uint targetUin, FileEntity fileEntity) } } - public async Task RecallGroupMessage(uint groupUin, MessageResult result) + public async Task RecallGroupMessage(uint groupUin, MessageResult result, CancellationToken cancellationToken) { if (result.Sequence == null) return false; var recallMessageEvent = RecallGroupMessageEvent.Create(groupUin, result.Sequence.Value); - var events = await Collection.Business.SendEvent(recallMessageEvent); + var events = await Collection.Business.SendEvent(recallMessageEvent, cancellationToken); return events.Count != 0 && ((RecallGroupMessageEvent)events[0]).ResultCode == 0; } - public async Task RecallGroupMessage(MessageChain chain) + public async Task RecallGroupMessage(MessageChain chain, CancellationToken cancellationToken) { if (chain.GroupUin == null) return false; var recallMessageEvent = RecallGroupMessageEvent.Create(chain.GroupUin.Value, chain.Sequence); - var events = await Collection.Business.SendEvent(recallMessageEvent); + var events = await Collection.Business.SendEvent(recallMessageEvent, cancellationToken); return events.Count != 0 && ((RecallGroupMessageEvent)events[0]).ResultCode == 0; } - public async Task RecallGroupMessage(uint groupUin, uint sequence) + public async Task RecallGroupMessage(uint groupUin, uint sequence, CancellationToken cancellationToken) { var recallMessageEvent = RecallGroupMessageEvent.Create(groupUin, sequence); - var events = await Collection.Business.SendEvent(recallMessageEvent); + var events = await Collection.Business.SendEvent(recallMessageEvent, cancellationToken); return events.Count != 0 && ((RecallGroupMessageEvent)events[0]).ResultCode == 0; } - public async Task RecallFriendMessage(uint friendUin, MessageResult result) + public async Task RecallFriendMessage(uint friendUin, MessageResult result, CancellationToken cancellationToken) { if (result.Sequence == null) return false; - if (await Collection.Business.CachingLogic.ResolveUid(null, friendUin) is not { } uid) return false; + if (await Collection.Business.CachingLogic.ResolveUid(null, friendUin, cancellationToken) is not { } uid) return false; var recallMessageEvent = RecallFriendMessageEvent.Create(uid, result.ClientSequence, result.Sequence ?? 0, (uint)(result.MessageId & uint.MaxValue), result.Timestamp); - var events = await Collection.Business.SendEvent(recallMessageEvent); + var events = await Collection.Business.SendEvent(recallMessageEvent, cancellationToken); return events.Count != 0 && ((RecallFriendMessageEvent)events[0]).ResultCode == 0; } - public async Task RecallFriendMessage(MessageChain chain) + public async Task RecallFriendMessage(MessageChain chain, CancellationToken cancellationToken) { - if (await Collection.Business.CachingLogic.ResolveUid(null, chain.TargetUin) is not { } uid) return false; + if (await Collection.Business.CachingLogic.ResolveUid(null, chain.TargetUin, cancellationToken) is not { } uid) return false; uint timestamp = (uint)new DateTimeOffset(chain.Time).ToUnixTimeSeconds(); var recallMessageEvent = RecallFriendMessageEvent.Create(uid, chain.ClientSequence, chain.Sequence, (uint)(chain.MessageId & uint.MaxValue), timestamp); - var events = await Collection.Business.SendEvent(recallMessageEvent); + var events = await Collection.Business.SendEvent(recallMessageEvent, cancellationToken); return events.Count != 0 && ((RecallFriendMessageEvent)events[0]).ResultCode == 0; } - public async Task?> FetchGroupRequests() + public async Task?> FetchGroupRequests(CancellationToken cancellationToken) { var fetchRequestsEvent = FetchGroupRequestsEvent.Create(); - var events = await Collection.Business.SendEvent(fetchRequestsEvent); + var events = await Collection.Business.SendEvent(fetchRequestsEvent, cancellationToken); if (events.Count == 0) return null; var resolved = events.Cast().SelectMany(e => e.Events).ToList(); @@ -378,15 +386,15 @@ async Task ResolveUid(string? uid) if (uid == null) return 0; var fetchUidEvent = FetchUserInfoEvent.Create(uid); - var e = await Collection.Business.SendEvent(fetchUidEvent); + var e = await Collection.Business.SendEvent(fetchUidEvent, cancellationToken); return e.Count == 0 ? 0 : ((FetchUserInfoEvent)e[0]).UserInfo.Uin; } } - public async Task?> FetchFriendRequests() + public async Task?> FetchFriendRequests(CancellationToken cancellationToken) { var fetchRequestsEvent = FetchFriendsRequestsEvent.Create(); - var events = await Collection.Business.SendEvent(fetchRequestsEvent); + var events = await Collection.Business.SendEvent(fetchRequestsEvent, cancellationToken); if (events.Count == 0) return null; var resolved = ((FetchFriendsRequestsEvent)events[0]).Requests; @@ -404,132 +412,132 @@ async Task ResolveUid(string? uid) if (uid == null) return 0; var fetchUidEvent = FetchUserInfoEvent.Create(uid); - var e = await Collection.Business.SendEvent(fetchUidEvent); + var e = await Collection.Business.SendEvent(fetchUidEvent, cancellationToken); return e.Count == 0 ? 0 : ((FetchUserInfoEvent)e[0]).UserInfo.Uin; } } - public async Task GroupTransfer(uint groupUin, uint targetUin) + public async Task GroupTransfer(uint groupUin, uint targetUin, CancellationToken cancellationToken) { - string? uid = await Collection.Business.CachingLogic.ResolveUid(groupUin, targetUin); + string? uid = await Collection.Business.CachingLogic.ResolveUid(groupUin, targetUin, cancellationToken); if (uid == null || Collection.Keystore.Uid is not { } source) return false; var transferEvent = GroupTransferEvent.Create(groupUin, source, uid); - var results = await Collection.Business.SendEvent(transferEvent); + var results = await Collection.Business.SendEvent(transferEvent, cancellationToken); return results.Count != 0 && results[0].ResultCode == 0; } - public async Task SetStatus(uint status) + public async Task SetStatus(uint status, CancellationToken cancellationToken) { var setStatusEvent = SetStatusEvent.Create(status, 0); - var results = await Collection.Business.SendEvent(setStatusEvent); + var results = await Collection.Business.SendEvent(setStatusEvent, cancellationToken); return results.Count != 0 && results[0].ResultCode == 0; } - public async Task SetCustomStatus(uint faceId, string text) + public async Task SetCustomStatus(uint faceId, string text, CancellationToken cancellationToken) { var setCustomStatusEvent = SetCustomStatusEvent.Create(faceId, text); - var results = await Collection.Business.SendEvent(setCustomStatusEvent); + var results = await Collection.Business.SendEvent(setCustomStatusEvent, cancellationToken); return results.Count != 0 && results[0].ResultCode == 0; } - public async Task RequestFriend(uint targetUin, string question, string message) + public async Task RequestFriend(uint targetUin, string question, string message, CancellationToken cancellationToken) { var requestFriendSearchEvent = RequestFriendSearchEvent.Create(targetUin); - var searchEvents = await Collection.Business.SendEvent(requestFriendSearchEvent); + var searchEvents = await Collection.Business.SendEvent(requestFriendSearchEvent, cancellationToken); if (searchEvents.Count == 0) return false; await Task.Delay(5000); var requestFriendSettingEvent = RequestFriendSettingEvent.Create(targetUin); - var settingEvents = await Collection.Business.SendEvent(requestFriendSettingEvent); + var settingEvents = await Collection.Business.SendEvent(requestFriendSettingEvent, cancellationToken); if (settingEvents.Count == 0) return false; var requestFriendEvent = RequestFriendEvent.Create(targetUin, message, question); - var events = await Collection.Business.SendEvent(requestFriendEvent); + var events = await Collection.Business.SendEvent(requestFriendEvent, cancellationToken); return events.Count != 0 && ((RequestFriendEvent)events[0]).ResultCode == 0; } - public async Task Like(uint targetUin, uint count) + public async Task Like(uint targetUin, uint count, CancellationToken cancellationToken) { - var uid = await Collection.Business.CachingLogic.ResolveUid(null, targetUin); + var uid = await Collection.Business.CachingLogic.ResolveUid(null, targetUin, cancellationToken); if (uid == null) return false; var friendLikeEvent = FriendLikeEvent.Create(uid, count); - var results = await Collection.Business.SendEvent(friendLikeEvent); + var results = await Collection.Business.SendEvent(friendLikeEvent, cancellationToken); return results.Count != 0 && results[0].ResultCode == 0; } - public async Task InviteGroup(uint targetGroupUin, Dictionary invitedUins) + public async Task InviteGroup(uint targetGroupUin, Dictionary invitedUins, CancellationToken cancellationToken) { var invitedUids = new Dictionary(invitedUins.Count); foreach (var (friendUin, groupUin) in invitedUins) { - string? uid = await Collection.Business.CachingLogic.ResolveUid(groupUin, friendUin); + string? uid = await Collection.Business.CachingLogic.ResolveUid(groupUin, friendUin, cancellationToken); if (uid != null) invitedUids[uid] = groupUin; } var @event = GroupInviteEvent.Create(targetGroupUin, invitedUids); - var results = await Collection.Business.SendEvent(@event); + var results = await Collection.Business.SendEvent(@event, cancellationToken); return results.Count != 0 && results[0].ResultCode == 0; } - public async Task GetClientKey() + public async Task GetClientKey(CancellationToken cancellationToken) { var clientKeyEvent = FetchClientKeyEvent.Create(); - var events = await Collection.Business.SendEvent(clientKeyEvent); + var events = await Collection.Business.SendEvent(clientKeyEvent, cancellationToken); return events.Count == 0 ? null : ((FetchClientKeyEvent)events[0]).ClientKey; } - public async Task SetGroupRequest(uint groupUin, ulong sequence, uint type, bool accept, string reason) + public async Task SetGroupRequest(uint groupUin, ulong sequence, uint type, bool accept, string reason, CancellationToken cancellationToken) { var inviteEvent = SetGroupRequestEvent.Create(accept, groupUin, sequence, type, reason); - var results = await Collection.Business.SendEvent(inviteEvent); + var results = await Collection.Business.SendEvent(inviteEvent, cancellationToken); return results.Count != 0 && results[0].ResultCode == 0; } - public async Task SetGroupFilteredRequest(uint groupUin, ulong sequence, uint type, bool accept, string reason) + public async Task SetGroupFilteredRequest(uint groupUin, ulong sequence, uint type, bool accept, string reason, CancellationToken cancellationToken) { var inviteEvent = SetGroupFilteredRequestEvent.Create(accept, groupUin, sequence, type, reason); - var results = await Collection.Business.SendEvent(inviteEvent); + var results = await Collection.Business.SendEvent(inviteEvent, cancellationToken); return results.Count != 0 && results[0].ResultCode == 0; } - public async Task SetFriendRequest(string targetUid, bool accept) + public async Task SetFriendRequest(string targetUid, bool accept, CancellationToken cancellationToken) { var inviteEvent = SetFriendRequestEvent.Create(targetUid, accept); - var results = await Collection.Business.SendEvent(inviteEvent); + var results = await Collection.Business.SendEvent(inviteEvent, cancellationToken); return results.Count != 0 && results[0].ResultCode == 0; } - public async Task?> GetGroupMessage(uint groupUin, uint startSequence, uint endSequence) + public async Task?> GetGroupMessage(uint groupUin, uint startSequence, uint endSequence, CancellationToken cancellationToken) { var getMsgEvent = GetGroupMessageEvent.Create(groupUin, startSequence, endSequence); - var results = await Collection.Business.SendEvent(getMsgEvent); + var results = await Collection.Business.SendEvent(getMsgEvent, cancellationToken); return results.Count != 0 ? ((GetGroupMessageEvent)results[0]).Chains : null; } - public async Task?> GetRoamMessage(uint friendUin, uint time, uint count) + public async Task?> GetRoamMessage(uint friendUin, uint time, uint count, CancellationToken cancellationToken) { - if (await Collection.Business.CachingLogic.ResolveUid(null, friendUin) is not { } uid) return null; + if (await Collection.Business.CachingLogic.ResolveUid(null, friendUin, cancellationToken) is not { } uid) return null; var roamEvent = GetRoamMessageEvent.Create(uid, time, count); - var results = await Collection.Business.SendEvent(roamEvent); + var results = await Collection.Business.SendEvent(roamEvent, cancellationToken); return results.Count != 0 ? ((GetRoamMessageEvent)results[0]).Chains : null; } - public async Task?> GetC2cMessage(uint friendUin, uint startSequence, uint endSequence) + public async Task?> GetC2cMessage(uint friendUin, uint startSequence, uint endSequence, CancellationToken cancellationToken) { - if (await Collection.Business.CachingLogic.ResolveUid(null, friendUin) is not { } uid) return null; + if (await Collection.Business.CachingLogic.ResolveUid(null, friendUin, cancellationToken) is not { } uid) return null; var c2cEvent = GetC2cMessageEvent.Create(uid, startSequence, endSequence); - var results = await Collection.Business.SendEvent(c2cEvent); + var results = await Collection.Business.SendEvent(c2cEvent, cancellationToken); return results.Count != 0 ? ((GetC2cMessageEvent)results[0]).Chains : null; } - public async Task<(int code, List? chains)> GetMessagesByResId(string resId) + public async Task<(int code, List? chains)> GetMessagesByResId(string resId, CancellationToken cancellationToken) { var @event = MultiMsgDownloadEvent.Create(Collection.Keystore.Uid ?? "", resId); - var results = await Collection.Business.SendEvent(@event); + var results = await Collection.Business.SendEvent(@event, cancellationToken); if (results.Count == 0) return (-9999, null); var result = (MultiMsgDownloadEvent)results[0]; @@ -537,142 +545,143 @@ public async Task SetFriendRequest(string targetUid, bool accept) return (result.ResultCode, result.Chains); } - public async Task?> FetchCustomFace() + public async Task?> FetchCustomFace(CancellationToken cancellationToken) { var fetchCustomFaceEvent = FetchCustomFaceEvent.Create(); - var results = await Collection.Business.SendEvent(fetchCustomFaceEvent); + var results = await Collection.Business.SendEvent(fetchCustomFaceEvent, cancellationToken); return results.Count != 0 ? ((FetchCustomFaceEvent)results[0]).Urls : null; } - public async Task UploadLongMessage(List chains) + public async Task UploadLongMessage(List chains, CancellationToken cancellationToken) { var multiMsgUploadEvent = MultiMsgUploadEvent.Create(null, chains); - var results = await Collection.Business.SendEvent(multiMsgUploadEvent); + var results = await Collection.Business.SendEvent(multiMsgUploadEvent, cancellationToken); return results.Count != 0 ? ((MultiMsgUploadEvent)results[0]).ResId : null; } - public async Task MarkAsRead(uint groupUin, string? targetUid, uint startSequence, uint time) + public async Task MarkAsRead(uint groupUin, string? targetUid, uint startSequence, uint time, CancellationToken cancellationToken) { var markAsReadEvent = MarkReadedEvent.Create(groupUin, targetUid, startSequence, time); - var results = await Collection.Business.SendEvent(markAsReadEvent); + var results = await Collection.Business.SendEvent(markAsReadEvent, cancellationToken); return results.Count != 0 && ((MarkReadedEvent)results[0]).ResultCode == 0; } - public async Task FriendPoke(uint friendUin) + public async Task FriendPoke(uint friendUin, CancellationToken cancellationToken) { var friendPokeEvent = FriendPokeEvent.Create(friendUin); - var results = await Collection.Business.SendEvent(friendPokeEvent); + var results = await Collection.Business.SendEvent(friendPokeEvent, cancellationToken); return results.Count != 0 && ((FriendPokeEvent)results[0]).ResultCode == 0; } - public async Task GroupPoke(uint groupUin, uint friendUin) + public async Task GroupPoke(uint groupUin, uint friendUin, CancellationToken cancellationToken) { var friendPokeEvent = GroupPokeEvent.Create(friendUin, groupUin); - var results = await Collection.Business.SendEvent(friendPokeEvent); + var results = await Collection.Business.SendEvent(friendPokeEvent, cancellationToken); return results.Count != 0 && ((FriendPokeEvent)results[0]).ResultCode == 0; } - public async Task SetEssenceMessage(uint groupUin, uint sequence, uint random) + public async Task SetEssenceMessage(uint groupUin, uint sequence, uint random, CancellationToken cancellationToken) { var setEssenceMessageEvent = SetEssenceMessageEvent.Create(groupUin, sequence, random); - var results = await Collection.Business.SendEvent(setEssenceMessageEvent); + var results = await Collection.Business.SendEvent(setEssenceMessageEvent, cancellationToken); return results.Count != 0 && ((SetEssenceMessageEvent)results[0]).ResultCode == 0; } - public async Task RemoveEssenceMessage(uint groupUin, uint sequence, uint random) + public async Task RemoveEssenceMessage(uint groupUin, uint sequence, uint random, CancellationToken cancellationToken) { var removeEssenceMessageEvent = RemoveEssenceMessageEvent.Create(groupUin, sequence, random); - var results = await Collection.Business.SendEvent(removeEssenceMessageEvent); + var results = await Collection.Business.SendEvent(removeEssenceMessageEvent, cancellationToken); return results.Count != 0 && ((RemoveEssenceMessageEvent)results[0]).ResultCode == 0; } - public async Task GroupSetSpecialTitle(uint groupUin, uint targetUin, string title) + public async Task GroupSetSpecialTitle(uint groupUin, uint targetUin, string title, CancellationToken cancellationToken) { - string? uid = await Collection.Business.CachingLogic.ResolveUid(groupUin, targetUin); + string? uid = await Collection.Business.CachingLogic.ResolveUid(groupUin, targetUin, cancellationToken); if (uid == null) return false; var groupSetSpecialTitleEvent = GroupSetSpecialTitleEvent.Create(groupUin, uid, title); - var events = await Collection.Business.SendEvent(groupSetSpecialTitleEvent); + var events = await Collection.Business.SendEvent(groupSetSpecialTitleEvent, cancellationToken); return events.Count != 0 && ((GroupSetSpecialTitleEvent)events[0]).ResultCode == 0; } - public async Task FetchUserInfo(uint uin, bool refreshCache = false) + public async Task FetchUserInfo(uint uin, bool refreshCache, CancellationToken cancellationToken) { - return await Collection.Business.CachingLogic.GetCachedUsers(uin, refreshCache); + return await Collection.Business.CachingLogic.GetCachedUsers(uin, refreshCache, cancellationToken); } - public async Task SetMessageReaction(uint groupUin, uint sequence, string code, bool isAdd) + public async Task SetMessageReaction(uint groupUin, uint sequence, string code, bool isAdd, CancellationToken cancellationToken) { if (isAdd) { var addReactionEvent = GroupAddReactionEvent.Create(groupUin, sequence, code); - var results = await Collection.Business.SendEvent(addReactionEvent); + var results = await Collection.Business.SendEvent(addReactionEvent, cancellationToken); return results.Count != 0 && results[0].ResultCode == 0; } else { var reduceReactionEvent = GroupReduceReactionEvent.Create(groupUin, sequence, code); - var results = await Collection.Business.SendEvent(reduceReactionEvent); + var results = await Collection.Business.SendEvent(reduceReactionEvent, cancellationToken); return results.Count != 0 && results[0].ResultCode == 0; } } - public async Task SetNeedToConfirmSwitch(bool enableNoNeed) + public async Task SetNeedToConfirmSwitch(bool enableNoNeed, CancellationToken cancellationToken) { var setNeedToConfirmSwitchEvent = SetNeedToConfirmSwitchEvent.Create(enableNoNeed); - var results = await Collection.Business.SendEvent(setNeedToConfirmSwitchEvent); + var results = await Collection.Business.SendEvent(setNeedToConfirmSwitchEvent, cancellationToken); return results.Count != 0 && results[0].ResultCode == 0; } - public async Task?> FetchMarketFaceKey(List faceIds) + public async Task?> FetchMarketFaceKey(List faceIds, CancellationToken cancellationToken) { var fetchMarketFaceKeyEvent = FetchMarketFaceKeyEvent.Create(faceIds); - var results = await Collection.Business.SendEvent(fetchMarketFaceKeyEvent); + var results = await Collection.Business.SendEvent(fetchMarketFaceKeyEvent, cancellationToken); return results.Count != 0 ? ((FetchMarketFaceKeyEvent)results[0]).Keys : null; } - public async Task GroupClockIn(uint groupUin) + public async Task GroupClockIn(uint groupUin, CancellationToken cancellationToken) { var groupClockInEvent = GroupClockInEvent.Create(groupUin); - var results = await Collection.Business.SendEvent(groupClockInEvent); + var results = await Collection.Business.SendEvent(groupClockInEvent, cancellationToken); return ((GroupClockInEvent)results[0]).ResultInfo ?? new BotGroupClockInResult(false); } - public Task FriendSpecialShake(uint friendUin, SpecialPokeFaceType type, uint count) + public Task FriendSpecialShake(uint friendUin, SpecialPokeFaceType type, uint count, CancellationToken cancellationToken) { var chain = MessageBuilder.Friend(friendUin) .SpecialPoke(type, count) .Build(); - return SendMessage(chain); + return SendMessage(chain, cancellationToken); } - public Task FriendShake(uint friendUin, PokeFaceType type, uint strength) + public Task FriendShake(uint friendUin, PokeFaceType type, uint strength, CancellationToken cancellationToken) { var chain = MessageBuilder.Friend(friendUin) .Poke(type, strength) .Build(); - return SendMessage(chain); + return SendMessage(chain, cancellationToken); } - public async Task SetAvatar(ImageEntity avatar) + public async Task SetAvatar(ImageEntity avatar, CancellationToken cancellationToken) { if (avatar.ImageStream == null) return false; var highwayUrlEvent = HighwayUrlEvent.Create(); - var highwayUrlResults = await Collection.Business.SendEvent(highwayUrlEvent); + var highwayUrlResults = await Collection.Business.SendEvent(highwayUrlEvent, cancellationToken); if (highwayUrlResults.Count == 0) return false; var ticket = ((HighwayUrlEvent)highwayUrlResults[0]).SigSession; var md5 = avatar.ImageStream.Value.Md5().UnHex(); - return await Collection.Highway.UploadSrcByStreamAsync(90, avatar.ImageStream.Value, ticket, md5, Array.Empty()); + return await Collection.Highway.UploadSrcByStreamAsync(90, avatar.ImageStream.Value, ticket, md5, + extendInfo: Array.Empty(), cancellation: cancellationToken); } - public async Task GroupSetAvatar(uint groupUin, ImageEntity avatar) + public async Task GroupSetAvatar(uint groupUin, ImageEntity avatar, CancellationToken cancellationToken) { if (avatar.ImageStream == null) return false; var highwayUrlEvent = HighwayUrlEvent.Create(); - var highwayUrlResults = await Collection.Business.SendEvent(highwayUrlEvent); + var highwayUrlResults = await Collection.Business.SendEvent(highwayUrlEvent, cancellationToken); if (highwayUrlResults.Count == 0) return false; var ticket = ((HighwayUrlEvent)highwayUrlResults[0]).SigSession; @@ -685,16 +694,16 @@ public async Task GroupSetAvatar(uint groupUin, ImageEntity avatar) Field5 = 3, Field6 = 1 }.Serialize().ToArray(); - return await Collection.Highway.UploadSrcByStreamAsync(3000, avatar.ImageStream.Value, ticket, md5, extra); + return await Collection.Highway.UploadSrcByStreamAsync(3000, avatar.ImageStream.Value, ticket, md5, extendInfo: extra, cancellation: cancellationToken); } - public async Task<(uint, uint)> GroupRemainAtAll(uint groupUin) + public async Task<(uint, uint)> GroupRemainAtAll(uint groupUin, CancellationToken cancellationToken) { var groupRemainAtAllEvent = FetchGroupAtAllRemainEvent.Create(groupUin); - var results = await Collection.Business.SendEvent(groupRemainAtAllEvent); + var results = await Collection.Business.SendEvent(groupRemainAtAllEvent, cancellationToken); if (results.Count == 0) return (0, 0); var ret = (FetchGroupAtAllRemainEvent)results[0]; return (ret.RemainAtAllCountForUin, ret.RemainAtAllCountForGroup); } -} \ No newline at end of file +} diff --git a/Lagrange.Core/Internal/Context/Logic/Implementation/WtExchangeLogic.cs b/Lagrange.Core/Internal/Context/Logic/Implementation/WtExchangeLogic.cs index f2e7a7421..9636444d5 100644 --- a/Lagrange.Core/Internal/Context/Logic/Implementation/WtExchangeLogic.cs +++ b/Lagrange.Core/Internal/Context/Logic/Implementation/WtExchangeLogic.cs @@ -27,7 +27,7 @@ internal class WtExchangeLogic : LogicBase private const string Tag = nameof(WtExchangeLogic); private readonly Timer _reLoginTimer; - + private TaskCompletionSource _transEmpTask = new(); private TaskCompletionSource<(string, string)> _captchaTask = new(); @@ -39,10 +39,10 @@ internal class WtExchangeLogic : LogicBase internal WtExchangeLogic(ContextCollection collection) : base(collection) { - _reLoginTimer = new Timer(async _ => await ReLogin(), null, Timeout.Infinite, Timeout.Infinite); + _reLoginTimer = new Timer(async _ => await ReLogin(CancellationToken.None), null, Timeout.Infinite, Timeout.Infinite); } - public override async Task Incoming(ProtocolEvent e) + public override async Task Incoming(ProtocolEvent e, CancellationToken _) { switch (e) { @@ -50,7 +50,7 @@ public override async Task Incoming(ProtocolEvent e) Collection.Log.LogFatal(Tag, $"KickNTEvent: {kick.Tag}: {kick.Message}"); Collection.Log.LogFatal(Tag, "Bot will be offline in 5 seconds..."); await Task.Delay(5000); - + Collection.Invoker.PostEvent(new BotOfflineEvent(kick.Tag, kick.Message)); // TODO: Fill in the reason of offline Collection.Scheduler.Dispose(); break; @@ -67,28 +67,29 @@ private void OnCancellation() { Collection.Scheduler.Cancel(QueryEvent); Collection.Scheduler.Cancel(HeartbeatEvent); - _transEmpTask.TrySetException(new TaskCanceledException()); - _captchaTask.TrySetException(new TaskCanceledException()); + _transEmpTask.TrySetCanceled(); + _captchaTask.TrySetCanceled(); } /// /// 1. resolve wtlogin.trans_emp CMD0x31 packet /// 2. Schedule wtlogin.trans_emp CMD0x12 Task /// - public async Task<(string, byte[])?> FetchQrCode() + public async Task<(string, byte[])?> FetchQrCode(CancellationToken cancellationToken) { Collection.Log.LogInfo(Tag, "Connecting Servers..."); - if (!await Collection.Socket.Connect()) return null; - Collection.Scheduler.Interval(HeartbeatEvent, 10 * 1000, async () => await Collection.Business.PushEvent(AliveEvent.Create())); - + if (!await Collection.Socket.Connect(cancellationToken)) return null; + ScheduleWithCancellation(HeartbeatEvent, 10 * 1000, + async () => await Collection.Business.PushEvent(AliveEvent.Create(), cancellationToken), cancellationToken); + if (Collection.Keystore.Session.D2.Length != 0) { Collection.Log.LogWarning(Tag, "Invalid Session found, try to clean D2Key, D2 and TGT Token"); Collection.Keystore.ClearSession(); } - + var transEmp = TransEmpEvent.Create(TransEmpEvent.State.FetchQrCode); - var result = await Collection.Business.SendEvent(transEmp); + var result = await Collection.Business.SendEvent(transEmp, cancellationToken); if (result.Count != 0) { @@ -107,7 +108,7 @@ public Task LoginByQrCode(CancellationToken cancellationToken) { Reset(); cancellationToken.Register(OnCancellation); - + Collection.Scheduler.Interval(QueryEvent, 2 * 1000, async () => await QueryTransEmpState(async @event => { if (@event.TgtgtKey != null) @@ -117,8 +118,8 @@ public Task LoginByQrCode(CancellationToken cancellationToken) Collection.Keystore.Session.NoPicSig = @event.NoPicSig; } - return await DoWtLogin(); - })); + return await DoWtLogin(cancellationToken); + }, cancellationToken)); return _transEmpTask.Task; } @@ -127,11 +128,11 @@ public async Task LoginByPassword(CancellationToken cancellationToken) { Reset(); cancellationToken.Register(OnCancellation); - + if (!Collection.Socket.Connected) // if socket not connected, try to connect { - if (!await Collection.Socket.Connect()) return false; - Collection.Scheduler.Interval(HeartbeatEvent, 10 * 1000, async () => await Collection.Business.PushEvent(AliveEvent.Create())); + if (!await Collection.Socket.Connect(cancellationToken)) return false; + ScheduleWithCancellation(HeartbeatEvent, 10 * 1000, async () => await Collection.Business.PushEvent(AliveEvent.Create(), cancellationToken), cancellationToken); } if (Collection.Keystore.Session.D2.Length > 0 && Collection.Keystore.Session.Tgt.Length > 0 && @@ -140,7 +141,7 @@ public async Task LoginByPassword(CancellationToken cancellationToken) Collection.Log.LogInfo(Tag, "Session has not expired, using session to login and register status"); try { - if (await BotOnline()) return true; + if (await BotOnline(cancellationToken: cancellationToken)) return true; Collection.Log.LogWarning(Tag, "Register by session failed, try to login by EasyLogin"); } @@ -154,7 +155,7 @@ public async Task LoginByPassword(CancellationToken cancellationToken) { Collection.Keystore.ClearSession(); - if (!await KeyExchange()) + if (!await KeyExchange(cancellationToken)) { Collection.Log.LogInfo(Tag, "Key Exchange Failed, please try again later"); return false; @@ -165,7 +166,7 @@ public async Task LoginByPassword(CancellationToken cancellationToken) { Collection.Log.LogInfo(Tag, "Trying to Login by EasyLogin..."); var easyLoginEvent = EasyLoginEvent.Create(); - var easyLoginResult = await Collection.Business.SendEvent(easyLoginEvent); + var easyLoginResult = await Collection.Business.SendEvent(easyLoginEvent, CancellationToken.None); if (easyLoginResult.Count != 0) { @@ -174,7 +175,7 @@ public async Task LoginByPassword(CancellationToken cancellationToken) case LoginCommon.Error.Success: { Collection.Log.LogInfo(Tag, "Login Success, try to register services"); - return await BotOnline(); + return await BotOnline(cancellationToken: cancellationToken); } case LoginCommon.Error.UnusualVerify: { @@ -191,13 +192,13 @@ public async Task LoginByPassword(CancellationToken cancellationToken) if (e.TempPassword != null) { Collection.Keystore.Session.TempPassword = e.TempPassword; - return await DoUnusualEasyLogin(); + return await DoUnusualEasyLogin(cancellationToken); } return false; - })); + }, cancellationToken)); bool result = await _transEmpTask.Task; - return result && await BotOnline(); + return result && await BotOnline(cancellationToken: cancellationToken); } default: { @@ -213,7 +214,7 @@ public async Task LoginByPassword(CancellationToken cancellationToken) { Collection.Log.LogInfo(Tag, "Trying to Login by Password..."); var passwordLoginEvent = PasswordLoginEvent.Create(); - var passwordLoginResult = await Collection.Business.SendEvent(passwordLoginEvent); + var passwordLoginResult = await Collection.Business.SendEvent(passwordLoginEvent, CancellationToken.None); if (passwordLoginResult.Count != 0) { @@ -224,7 +225,7 @@ public async Task LoginByPassword(CancellationToken cancellationToken) { Collection.Log.LogInfo(Tag, "Login Success"); - await BotOnline(); + await BotOnline(cancellationToken: cancellationToken); return true; } case LoginCommon.Error.UnusualVerify: @@ -271,7 +272,7 @@ public async Task LoginByPassword(CancellationToken cancellationToken) }; var client = new HttpClient(); - var response = await client.PostAsJsonAsync(url, request, cancellationToken); + var response = await client.PostAsJsonAsync(url, request, cancellationToken: cancellationToken); var json = await response.Content.ReadFromJsonAsync(cancellationToken: cancellationToken); if (json == null) return false; @@ -281,8 +282,8 @@ public async Task LoginByPassword(CancellationToken cancellationToken) string? original = HttpUtility.ParseQueryString(json.StrUrl.Split("?")[1])["str_url"]; if (original == null) return false; - - Collection.Scheduler.Interval(QueryEvent, 2 * 1000, async () => + + ScheduleWithCancellation(QueryEvent, 2 * 1000, async () => { var query = new NTNewDeviceQrCodeQuery { @@ -294,7 +295,7 @@ public async Task LoginByPassword(CancellationToken cancellationToken) if (!string.IsNullOrEmpty(responseJson?.StrNtSuccToken)) { Collection.Scheduler.Cancel(QueryEvent); // cancel the event - + Collection.Keystore.Session.TempPassword = Encoding.UTF8.GetBytes(responseJson.StrNtSuccToken); _transEmpTask.SetResult(true); client.Dispose(); @@ -303,14 +304,14 @@ public async Task LoginByPassword(CancellationToken cancellationToken) { Collection.Log.LogInfo(Tag, "NewDeviceLogin is waiting for scanning"); } - }); + }, cancellationToken); if (await _transEmpTask.Task) { Collection.Log.LogInfo(Tag, "Trying to Login by NewDeviceLogin..."); var newDeviceLogin = NewDeviceLoginEvent.Create(); - _ = await Collection.Business.SendEvent(newDeviceLogin); - return await BotOnline(); + _ = await Collection.Business.SendEvent(newDeviceLogin, cancellationToken); + return await BotOnline(cancellationToken: cancellationToken); } return false; @@ -320,7 +321,7 @@ public async Task LoginByPassword(CancellationToken cancellationToken) Collection.Log.LogWarning(Tag, @event is { Message: not null, Tag: not null } ? $"Login Failed: {(LoginCommon.Error)@event.ResultCode} | {@event.Tag}: {@event.Message}" : $"Login Failed: {(LoginCommon.Error)@event.ResultCode}"); - + return false; } } @@ -330,10 +331,10 @@ public async Task LoginByPassword(CancellationToken cancellationToken) return false; } - private async Task KeyExchange() + private async Task KeyExchange(CancellationToken cancellationToken) { var keyExchangeEvent = KeyExchangeEvent.Create(); - var exchangeResult = await Collection.Business.SendEvent(keyExchangeEvent); + var exchangeResult = await Collection.Business.SendEvent(keyExchangeEvent, cancellationToken); if (exchangeResult.Count != 0) { Collection.Log.LogInfo(Tag, "Key Exchange successfully!"); @@ -343,14 +344,14 @@ private async Task KeyExchange() return false; } - private async Task DoWtLogin() + private async Task DoWtLogin(CancellationToken cancellationToken) { Collection.Log.LogInfo(Tag, "Doing Login..."); Collection.Keystore.Session.Sequence = 0; Collection.Keystore.SecpImpl = new EcdhImpl(EcdhImpl.CryptMethod.Secp192K1); var loginEvent = LoginEvent.Create(); - var result = await Collection.Business.SendEvent(loginEvent); + var result = await Collection.Business.SendEvent(loginEvent, cancellationToken); if (result.Count != 0) { @@ -360,7 +361,7 @@ private async Task DoWtLogin() Collection.Log.LogInfo(Tag, "Login Success"); Collection.Keystore.Info = new BotKeystore.BotInfo(@event.Age, @event.Sex, @event.Name); Collection.Log.LogInfo(Tag, Collection.Keystore.Info.ToString()); - return await BotOnline(); + return await BotOnline(cancellationToken: cancellationToken); } Collection.Log.LogFatal(Tag, $"Login failed: {@event.ResultCode}"); @@ -370,8 +371,14 @@ private async Task DoWtLogin() return false; } - private async Task QueryTransEmpState(Func> callback) + private async Task QueryTransEmpState(Func> callback, CancellationToken cancellationToken) { + if (cancellationToken.IsCancellationRequested) + { + Collection.Scheduler.Cancel(QueryEvent); + _transEmpTask.SetCanceled(cancellationToken); + return; + } if (Collection.Keystore.Session.QrString != null) { var request = new NTLoginHttpRequest @@ -382,13 +389,13 @@ private async Task QueryTransEmpState(Func> callback) }; var payload = JsonSerializer.SerializeToUtf8Bytes(request); - var response = await Http.PostAsync(Interface, payload, "application/json"); + var response = await Http.PostAsync(Interface, payload, "application/json", cancellationToken); var info = JsonSerializer.Deserialize(response); if (info != null) Collection.Keystore.Uin = info.Uin; } var transEmp = TransEmpEvent.Create(TransEmpEvent.State.QueryResult); - var result = await Collection.Business.SendEvent(transEmp); + var result = await Collection.Business.SendEvent(transEmp, cancellationToken); if (result.Count != 0) { @@ -427,14 +434,14 @@ private async Task QueryTransEmpState(Func> callback) break; } } - } - public async Task BotOnline(BotOnlineEvent.OnlineReason reason = BotOnlineEvent.OnlineReason.Login) + public async Task BotOnline(BotOnlineEvent.OnlineReason reason = BotOnlineEvent.OnlineReason.Login, CancellationToken cancellationToken = default) { var registerEvent = StatusRegisterEvent.Create(); - var registerResponse = await Collection.Business.SendEvent(registerEvent); - var heartbeatDelegate = new Action(async () => await Collection.Business.PushEvent(SsoAliveEvent.Create())); + var registerResponse = await Collection.Business.SendEvent(registerEvent, cancellationToken); + // Cancellation token use default here is because the heartbeatDelegate is order to keep alive after online + var heartbeatDelegate = new Action(async () => await Collection.Business.PushEvent(SsoAliveEvent.Create(), CancellationToken.None)); if (registerResponse.Count != 0) { @@ -449,7 +456,8 @@ public async Task BotOnline(BotOnlineEvent.OnlineReason reason = BotOnline var onlineEvent = new BotOnlineEvent(reason); Collection.Invoker.PostEvent(onlineEvent); - await Collection.Business.PushEvent(InfoSyncEvent.Create()); + // cancellation token use default here is because the bot have online + await Collection.Business.PushEvent(InfoSyncEvent.Create(), CancellationToken.None); _reLoginTimer.Change(TimeSpan.FromDays(15), TimeSpan.FromDays(15)); Collection.Log.LogInfo(Tag, "AutoReLogin Enabled, session would be refreshed in 15 days period"); @@ -464,7 +472,7 @@ public async Task BotOnline(BotOnlineEvent.OnlineReason reason = BotOnline private async Task FetchUnusual() { var transEmp = TransEmpEvent.Create(TransEmpEvent.State.FetchQrCode); - var result = await Collection.Business.SendEvent(transEmp); + var result = await Collection.Business.SendEvent(transEmp, CancellationToken.None); if (result.Count != 0) { @@ -475,15 +483,15 @@ private async Task FetchUnusual() return false; } - private async Task DoUnusualEasyLogin() + private async Task DoUnusualEasyLogin(CancellationToken cancellationToken) { Collection.Log.LogInfo(Tag, "Trying to Login by EasyLogin..."); var unusualEvent = UnusualEasyLoginEvent.Create(); - var result = await Collection.Business.SendEvent(unusualEvent); + var result = await Collection.Business.SendEvent(unusualEvent, cancellationToken); return result.Count != 0 && ((UnusualEasyLoginEvent)result[0]).Success; } - private async Task ReLogin() + private async Task ReLogin(CancellationToken cancellationToken) { Collection.Log.LogInfo(Tag, "Session is about to expire, try to relogin and refresh"); if (Collection.Keystore.Session.TempPassword == null) @@ -498,35 +506,56 @@ private async Task ReLogin() Collection.Socket.Disconnect(); Collection.Keystore.ClearSession(); - await Collection.Socket.Connect(); - if (await KeyExchange()) + try { - var easyLoginEvent = EasyLoginEvent.Create(); - var easyLoginResult = await Collection.Business.SendEvent(easyLoginEvent); - if (easyLoginResult.Count != 0) + await Collection.Socket.Connect(cancellationToken); + + if (await KeyExchange(cancellationToken)) { - var result = (EasyLoginEvent)easyLoginResult[0]; - if ((LoginCommon.Error)result.ResultCode == LoginCommon.Error.Success) + var easyLoginEvent = EasyLoginEvent.Create(); + var easyLoginResult = await Collection.Business.SendEvent(easyLoginEvent, CancellationToken.None); + if (easyLoginResult.Count != 0) { - Collection.Log.LogInfo(Tag, "Login Success, try to register services"); - if (await BotOnline(BotOnlineEvent.OnlineReason.Reconnect)) return; - - Collection.Log.LogInfo(Tag, "Re-login failed, please refresh manually"); + var result = (EasyLoginEvent)easyLoginResult[0]; + if ((LoginCommon.Error)result.ResultCode == LoginCommon.Error.Success) + { + Collection.Log.LogInfo(Tag, "Login Success, try to register services"); + if (await BotOnline(BotOnlineEvent.OnlineReason.Reconnect, cancellationToken)) return; + + Collection.Log.LogInfo(Tag, "Re-login failed, please refresh manually"); + } } } + else + { + Collection.Log.LogInfo(Tag, "Key Exchange Failed, trying to online, please refresh manually"); + } } - else + catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested) { - Collection.Log.LogInfo(Tag, "Key Exchange Failed, trying to online, please refresh manually"); + Collection.Keystore.Session.D2 = d2; + Collection.Keystore.Session.D2Key = d2Key; + Collection.Keystore.Session.Tgt = tgt; + throw; } - - Collection.Keystore.Session.D2 = d2; - Collection.Keystore.Session.D2Key = d2Key; - Collection.Keystore.Session.Tgt = tgt; - await BotOnline(BotOnlineEvent.OnlineReason.Reconnect); + await BotOnline(BotOnlineEvent.OnlineReason.Reconnect, cancellationToken); } public bool SubmitCaptcha(string ticket, string randStr) => _captchaTask.TrySetResult((ticket, randStr)); -} \ No newline at end of file + + private void ScheduleWithCancellation(string tag, int interval, Action func, CancellationToken ct) + { + Collection.Scheduler.Interval(tag, interval, () => + { + if (ct.IsCancellationRequested) + { + Collection.Scheduler.Cancel(tag); + return; + } + + func(); + }); + } +} diff --git a/Lagrange.Core/Internal/Context/Logic/LogicBase.cs b/Lagrange.Core/Internal/Context/Logic/LogicBase.cs index 49a04586d..a93c2dc13 100644 --- a/Lagrange.Core/Internal/Context/Logic/LogicBase.cs +++ b/Lagrange.Core/Internal/Context/Logic/LogicBase.cs @@ -8,7 +8,7 @@ internal abstract class LogicBase protected LogicBase(ContextCollection collection) => Collection = collection; - public virtual Task Incoming(ProtocolEvent e) => Task.CompletedTask; + public virtual Task Incoming(ProtocolEvent e, CancellationToken cancellationToken) => Task.CompletedTask; - public virtual Task Outgoing(ProtocolEvent e) => Task.CompletedTask; -} \ No newline at end of file + public virtual Task Outgoing(ProtocolEvent e, CancellationToken cancellationToken) => Task.CompletedTask; +} diff --git a/Lagrange.Core/Internal/Context/PacketContext.cs b/Lagrange.Core/Internal/Context/PacketContext.cs index 927625ab9..29746a2f7 100644 --- a/Lagrange.Core/Internal/Context/PacketContext.cs +++ b/Lagrange.Core/Internal/Context/PacketContext.cs @@ -17,7 +17,7 @@ internal class PacketContext : ContextBase { internal SignProvider SignProvider { private get; set; } - private readonly ConcurrentDictionary> _pendingTasks; + private readonly ConcurrentDictionary task, CancellationToken cancellationToken)> _pendingTasks; public PacketContext(ContextCollection collection, BotKeystore keystore, BotAppInfo appInfo, BotDeviceInfo device, BotConfig config) : base(collection, keystore, appInfo, device) @@ -29,34 +29,43 @@ public PacketContext(ContextCollection collection, BotKeystore keystore, BotAppI "Linux" => new LinuxSigner(), _ => throw new Exception("Unknown System Found") }; - _pendingTasks = new ConcurrentDictionary>(); + _pendingTasks = new ConcurrentDictionary task, CancellationToken cancellationToken)>(); } /// /// Send the packet and wait for the corresponding response by the packet's sequence number. /// - public Task SendPacket(SsoPacket packet) + public Task SendPacket(SsoPacket packet, CancellationToken cancellationToken) { - var task = new TaskCompletionSource(); - _pendingTasks.TryAdd(packet.Sequence, task); - + byte[] data; switch (packet.PacketType) { case 12: { var sso = SsoPacker.Build(packet, AppInfo, DeviceInfo, Keystore, SignProvider); var service = ServicePacker.BuildProtocol12(sso, Keystore); - bool _ = Collection.Socket.Send(service.ToArray()).GetAwaiter().GetResult(); + data = service.ToArray(); break; } case 13: { var service = ServicePacker.BuildProtocol13(packet.Payload, Keystore, packet.Command, packet.Sequence); - bool _ = Collection.Socket.Send(service.ToArray()).GetAwaiter().GetResult(); + data = service.ToArray(); break; } + default: + throw new Exception("Unknown Packet Type"); } + cancellationToken.ThrowIfCancellationRequested(); + + var task = new TaskCompletionSource(); + _pendingTasks.TryAdd(packet.Sequence, (task, cancellationToken)); + + // We have to wait packet to be sent before we can return the task + // Because the packet's sequence number is used to identify the response + bool _ = Collection.Socket.Send(data).GetAwaiter().GetResult(); + return task.Task; } @@ -90,16 +99,21 @@ public void DispatchPacket(BinaryPacket packet) var sso = SsoPacker.Parse(service); - if (_pendingTasks.TryRemove(sso.Sequence, out var task)) + if (_pendingTasks.TryRemove(sso.Sequence, out var pendingTask)) { + if (pendingTask.cancellationToken.IsCancellationRequested) + { + pendingTask.task.SetCanceled(pendingTask.cancellationToken); + return; + } if (sso is { RetCode: not 0, Extra: { } extra}) { string msg = $"Packet '{sso.Command}' returns {sso.RetCode} with seq: {sso.Sequence}, extra: {extra}"; - task.SetException(new InvalidOperationException(msg)); + pendingTask.task.SetException(new InvalidOperationException(msg)); } else { - task.SetResult(sso); + pendingTask.task.SetResult(sso); } } else @@ -107,4 +121,4 @@ public void DispatchPacket(BinaryPacket packet) Collection.Business.HandleServerPacket(sso); } } -} \ No newline at end of file +} diff --git a/Lagrange.Core/Internal/Context/SocketContext.cs b/Lagrange.Core/Internal/Context/SocketContext.cs index e722f1081..ba956f929 100644 --- a/Lagrange.Core/Internal/Context/SocketContext.cs +++ b/Lagrange.Core/Internal/Context/SocketContext.cs @@ -35,20 +35,20 @@ public SocketContext(ContextCollection collection, BotKeystore keystore, BotAppI _config = config; } - public async Task Connect() + public async Task Connect(CancellationToken cancellationToken) { if (_tcpClient.Connected) return true; - var servers = await OptimumServer(_config.GetOptimumServer, _config.UseIPv6Network); + var servers = await OptimumServer(_config.GetOptimumServer, _config.UseIPv6Network, cancellationToken); ServerUri = servers.First(); - return await _tcpClient.Connect(ServerUri.Host, ServerUri.Port); + return await _tcpClient.Connect(ServerUri.Host, ServerUri.Port, cancellationToken); } - private async Task Reconnect() + private async Task Reconnect(CancellationToken cancellationToken) { if (ServerUri != null && !_tcpClient.Connected) { - bool reconnect = await _tcpClient.Connect(ServerUri.Host, ServerUri.Port); + bool reconnect = await _tcpClient.Connect(ServerUri.Host, ServerUri.Port, cancellationToken); if (reconnect) { Collection.Log.LogInfo(Tag, $"Reconnect to {ServerUri}"); @@ -77,10 +77,15 @@ public void OnDisconnect() if (_config.AutoReconnect) { - Collection.Scheduler.Interval("Reconnect", 10 * 1000, async () => + var cancellationToken = CancellationToken.None; + + async void DoScheduleReconnect() { - if (await Reconnect()) Collection.Scheduler.Cancel("Reconnect"); - }); + if (cancellationToken.IsCancellationRequested || await Reconnect(cancellationToken)) + Collection.Scheduler.Cancel("Reconnect"); + } + + Collection.Scheduler.Interval("Reconnect", 10 * 1000, DoScheduleReconnect); } } @@ -109,12 +114,12 @@ public void OnSocketError(Exception e, ReadOnlyMemory data = default) new("http://119.147.190.138:8080") }; - private async Task> OptimumServer(bool requestMsf, bool useIPv6Network = false) + private async Task> OptimumServer(bool requestMsf, bool useIPv6Network = false, CancellationToken cancellationToken = default) { - var result = requestMsf ? await ResolveDns(useIPv6Network) : useIPv6Network ? HardCodeIPv6Uris : TestIPv4HardCodes; + var result = requestMsf ? await ResolveDns(useIPv6Network, cancellationToken: cancellationToken) : useIPv6Network ? HardCodeIPv6Uris : TestIPv4HardCodes; var latencyTasks = result.Select(uri => Icmp.PingAsync(uri)).ToArray(); - var latency = await Task.WhenAll(latencyTasks); + var latency = await Task.WhenAll(latencyTasks).WaitAsync(cancellationToken); Array.Sort(latency, result); var list = result.ToList(); @@ -122,10 +127,10 @@ private async Task> OptimumServer(bool requestMsf, bool useIPv6Network return list; } - private static async Task ResolveDns(bool useIPv6Network = false) + private static async Task ResolveDns(bool useIPv6Network = false, CancellationToken cancellationToken = default) { string dns = useIPv6Network ? "msfwifiv6.3g.qq.com" : "msfwifi.3g.qq.com"; - var addresses = await Dns.GetHostEntryAsync(dns); + var addresses = await Dns.GetHostEntryAsync(dns, cancellationToken); var result = new Uri[addresses.AddressList.Length]; for (int i = 0; i < addresses.AddressList.Length; i++) result[i] = new Uri($"http://{addresses.AddressList[i]}:8080"); diff --git a/Lagrange.Core/Internal/Context/Uploader/Common.cs b/Lagrange.Core/Internal/Context/Uploader/Common.cs index 8548a2fc4..6e7a766af 100644 --- a/Lagrange.Core/Internal/Context/Uploader/Common.cs +++ b/Lagrange.Core/Internal/Context/Uploader/Common.cs @@ -49,10 +49,10 @@ internal static class Common }; } - public static async Task GetTicket(ContextCollection context) + public static async Task GetTicket(ContextCollection context, CancellationToken cancellationToken) { var hwUrlEvent = HighwayUrlEvent.Create(); - var highwayUrlResult = await context.Business.SendEvent(hwUrlEvent); + var highwayUrlResult = await context.Business.SendEvent(hwUrlEvent, cancellationToken); return ((HighwayUrlEvent)highwayUrlResult[0]).SigSession; } @@ -110,4 +110,4 @@ private static string ConvertIP(uint raw) var ip = BitConverter.GetBytes(raw); return $"{ip[0]}.{ip[1]}.{ip[2]}.{ip[3]}"; } -} \ No newline at end of file +} diff --git a/Lagrange.Core/Internal/Context/Uploader/FileUploader.cs b/Lagrange.Core/Internal/Context/Uploader/FileUploader.cs index abad6c619..75db6aee7 100644 --- a/Lagrange.Core/Internal/Context/Uploader/FileUploader.cs +++ b/Lagrange.Core/Internal/Context/Uploader/FileUploader.cs @@ -11,148 +11,151 @@ namespace Lagrange.Core.Internal.Context.Uploader; /// internal static class FileUploader { - public static async Task UploadPrivate(ContextCollection context, MessageChain chain, IMessageEntity entity) + public static async Task UploadPrivate(ContextCollection context, MessageChain chain, IMessageEntity entity, CancellationToken cancellationToken) { if (entity is not FileEntity { FileStream: not null } file) return false; - - var uploadEvent = FileUploadEvent.Create(chain.Uid ?? "", file); - var result = await context.Business.SendEvent(uploadEvent); - var uploadResp = (FileUploadEvent)result[0]; - - if (!uploadResp.IsExist) + + try { - var ext = new FileUploadExt + var uploadEvent = FileUploadEvent.Create(chain.Uid ?? "", file); + var result = await context.Business.SendEvent(uploadEvent, cancellationToken); + var uploadResp = (FileUploadEvent)result[0]; + + if (!uploadResp.IsExist) { - Unknown1 = 100, - Unknown2 = 1, - Entry = new FileUploadEntry + var ext = new FileUploadExt { - BusiBuff = new ExcitingBusiInfo - { - SenderUin = context.Keystore.Uin, - }, - FileEntry = new ExcitingFileEntry - { - FileSize = file.FileStream.Length, - Md5 = file.FileMd5, - CheckKey = file.FileSha1, - Md5S2 = file.FileMd5, - FileId = uploadResp.FileId, - UploadKey = uploadResp.UploadKey - }, - ClientInfo = new ExcitingClientInfo - { - ClientType = 3, - AppId = "100", - TerminalType = 3, - ClientVer = "1.1.1", - Unknown = 4 - }, - FileNameInfo = new ExcitingFileNameInfo - { - FileName = file.FileName - }, - Host = new ExcitingHostConfig + Unknown1 = 100, + Unknown2 = 1, + Entry = new FileUploadEntry { - Hosts = new List + BusiBuff = new ExcitingBusiInfo { SenderUin = context.Keystore.Uin, }, + FileEntry = + new ExcitingFileEntry + { + FileSize = file.FileStream.Length, + Md5 = file.FileMd5, + CheckKey = file.FileSha1, + Md5S2 = file.FileMd5, + FileId = uploadResp.FileId, + UploadKey = uploadResp.UploadKey + }, + ClientInfo = + new ExcitingClientInfo + { + ClientType = 3, + AppId = "100", + TerminalType = 3, + ClientVer = "1.1.1", + Unknown = 4 + }, + FileNameInfo = new ExcitingFileNameInfo { FileName = file.FileName }, + Host = new ExcitingHostConfig { - new() + Hosts = new List { - Url = new ExcitingUrlInfo + new() { - Unknown = 1, - Host = uploadResp.Ip - }, - Port = uploadResp.Port + Url = new ExcitingUrlInfo { Unknown = 1, Host = uploadResp.Ip }, + Port = uploadResp.Port + } } } - } - }, - Unknown200 = 1 - }; + }, + Unknown200 = 1 + }; - file.FileHash = uploadResp.Addon; - file.FileUuid = uploadResp.FileId; + file.FileHash = uploadResp.Addon; + file.FileUuid = uploadResp.FileId; - bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(95, file.FileStream, await Common.GetTicket(context), file.FileMd5, ext.Serialize().ToArray()); - if (!hwSuccess) return false; + bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(95, file.FileStream, + await Common.GetTicket(context, cancellationToken), file.FileMd5, extendInfo: ext.Serialize().ToArray(), cancellation: cancellationToken); + if (!hwSuccess) return false; + } + } + finally + { + await file.FileStream.DisposeAsync(); } - await file.FileStream.DisposeAsync(); var sendEvent = SendMessageEvent.Create(chain); - var sendResult = await context.Business.SendEvent(sendEvent); + var sendResult = await context.Business.SendEvent(sendEvent, cancellationToken); return sendResult.Count != 0 && ((SendMessageEvent)sendResult[0]).MsgResult.Result == 0; } - public static async Task UploadGroup(ContextCollection context, MessageChain chain, IMessageEntity entity, string targetDirectory) + public static async Task UploadGroup(ContextCollection context, MessageChain chain, IMessageEntity entity, string targetDirectory, CancellationToken cancellationToken) { if (entity is not FileEntity { FileStream: not null } file) return false; - - var uploadEvent = GroupFSUploadEvent.Create(chain.GroupUin ?? 0, targetDirectory, file); - var result = await context.Business.SendEvent(uploadEvent); - var uploadResp = (GroupFSUploadEvent)result[0]; - - if (!uploadResp.IsExist) + string fileId = ""; + try { - var ext = new FileUploadExt + var uploadEvent = GroupFSUploadEvent.Create(chain.GroupUin ?? 0, targetDirectory, file); + var result = await context.Business.SendEvent(uploadEvent, cancellationToken); + var uploadResp = (GroupFSUploadEvent)result[0]; + + if (!uploadResp.IsExist) { - Unknown1 = 100, - Unknown2 = 1, - Entry = new FileUploadEntry + var ext = new FileUploadExt { - BusiBuff = new ExcitingBusiInfo - { - SenderUin = context.Keystore.Uin, - ReceiverUin = chain.GroupUin ?? 0, - GroupCode = chain.GroupUin ?? 0 - }, - FileEntry = new ExcitingFileEntry - { - FileSize = file.FileStream.Length, - Md5 = file.FileMd5, - CheckKey = uploadResp.CheckKey, - Md5S2 = file.FileMd5, - FileId = uploadResp.FileId, - UploadKey = uploadResp.UploadKey - }, - ClientInfo = new ExcitingClientInfo - { - ClientType = 3, - AppId = "100", - TerminalType = 3, - ClientVer = "1.1.1", - Unknown = 4 - }, - FileNameInfo = new ExcitingFileNameInfo + Unknown1 = 100, + Unknown2 = 1, + Entry = new FileUploadEntry { - FileName = file.FileName - }, - Host = new ExcitingHostConfig - { - Hosts = new List + BusiBuff = + new ExcitingBusiInfo + { + SenderUin = context.Keystore.Uin, + ReceiverUin = chain.GroupUin ?? 0, + GroupCode = chain.GroupUin ?? 0 + }, + FileEntry = new ExcitingFileEntry + { + FileSize = file.FileStream.Length, + Md5 = file.FileMd5, + CheckKey = uploadResp.CheckKey, + Md5S2 = file.FileMd5, + FileId = uploadResp.FileId, + UploadKey = uploadResp.UploadKey + }, + ClientInfo = + new ExcitingClientInfo + { + ClientType = 3, + AppId = "100", + TerminalType = 3, + ClientVer = "1.1.1", + Unknown = 4 + }, + FileNameInfo = new ExcitingFileNameInfo { FileName = file.FileName }, + Host = new ExcitingHostConfig { - new() + Hosts = new List { - Url = new ExcitingUrlInfo + new() { - Unknown = 1, - Host = uploadResp.Ip - }, - Port = uploadResp.Port + Url = new ExcitingUrlInfo { Unknown = 1, Host = uploadResp.Ip }, + Port = uploadResp.Port + } } } } - } - }; + }; + + bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(71, file.FileStream, + await Common.GetTicket(context, cancellationToken), file.FileMd5, extendInfo: ext.Serialize().ToArray(), cancellation: cancellationToken); + if (!hwSuccess) return false; - bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(71, file.FileStream, await Common.GetTicket(context), file.FileMd5, ext.Serialize().ToArray()); - if (!hwSuccess) return false; + fileId = uploadResp.FileId; + } + } + finally + { + await file.FileStream.DisposeAsync(); } - await file.FileStream.DisposeAsync(); - var sendEvent = GroupSendFileEvent.Create(chain.GroupUin ?? 0, uploadResp.FileId); - var sendResult = await context.Business.SendEvent(sendEvent); + var sendEvent = GroupSendFileEvent.Create(chain.GroupUin ?? 0, fileId); + var sendResult = await context.Business.SendEvent(sendEvent, cancellationToken); return sendResult.Count != 0 && ((GroupSendFileEvent)sendResult[0]).ResultCode == 0; } -} \ No newline at end of file +} diff --git a/Lagrange.Core/Internal/Context/Uploader/IHighwayUploader.cs b/Lagrange.Core/Internal/Context/Uploader/IHighwayUploader.cs index 7af032b9d..8c756820c 100644 --- a/Lagrange.Core/Internal/Context/Uploader/IHighwayUploader.cs +++ b/Lagrange.Core/Internal/Context/Uploader/IHighwayUploader.cs @@ -4,7 +4,7 @@ namespace Lagrange.Core.Internal.Context.Uploader; internal interface IHighwayUploader { - public Task UploadPrivate(ContextCollection context, MessageChain chain, IMessageEntity entity); + public Task UploadPrivate(ContextCollection context, MessageChain chain, IMessageEntity entity, CancellationToken cancellationToken); - public Task UploadGroup(ContextCollection context, MessageChain chain, IMessageEntity entity); -} \ No newline at end of file + public Task UploadGroup(ContextCollection context, MessageChain chain, IMessageEntity entity, CancellationToken cancellationToken); +} diff --git a/Lagrange.Core/Internal/Context/Uploader/ImageUploader.cs b/Lagrange.Core/Internal/Context/Uploader/ImageUploader.cs index 14b0d7221..a3bb0ccb5 100644 --- a/Lagrange.Core/Internal/Context/Uploader/ImageUploader.cs +++ b/Lagrange.Core/Internal/Context/Uploader/ImageUploader.cs @@ -8,18 +8,18 @@ namespace Lagrange.Core.Internal.Context.Uploader; [HighwayUploader(typeof(ImageEntity))] internal class ImageUploader : IHighwayUploader { - public async Task UploadPrivate(ContextCollection context, MessageChain chain, IMessageEntity entity) + public async Task UploadPrivate(ContextCollection context, MessageChain chain, IMessageEntity entity, CancellationToken cancellationToken) { if (entity is ImageEntity { ImageStream: { } stream } image) { var uploadEvent = ImageUploadEvent.Create(image, chain.FriendInfo?.Uid ?? ""); - var uploadResult = await context.Business.SendEvent(uploadEvent); + var uploadResult = await context.Business.SendEvent(uploadEvent, cancellationToken); var metaResult = (ImageUploadEvent)uploadResult[0]; if (Common.GenerateExt(metaResult) is { } ext) { var hash = metaResult.MsgInfo.MsgInfoBody[0].Index.Info.FileHash.UnHex(); - bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(1003, stream.Value, await Common.GetTicket(context), hash, ext.Serialize().ToArray()); + bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(1003, stream.Value, await Common.GetTicket(context, cancellationToken), hash, extendInfo: ext.Serialize().ToArray(), cancellation: cancellationToken); if (!hwSuccess) { await stream.Value.DisposeAsync(); @@ -33,18 +33,18 @@ public async Task UploadPrivate(ContextCollection context, MessageChain chain, I } } - public async Task UploadGroup(ContextCollection context, MessageChain chain, IMessageEntity entity) + public async Task UploadGroup(ContextCollection context, MessageChain chain, IMessageEntity entity, CancellationToken cancellationToken) { if (entity is ImageEntity { ImageStream: { } stream } image) { var uploadEvent = ImageGroupUploadEvent.Create(image, chain.GroupUin ?? 0); - var uploadResult = await context.Business.SendEvent(uploadEvent); + var uploadResult = await context.Business.SendEvent(uploadEvent, cancellationToken); var metaResult = (ImageGroupUploadEvent)uploadResult[0]; if (Common.GenerateExt(metaResult) is { } ext) { var hash = metaResult.MsgInfo.MsgInfoBody[0].Index.Info.FileHash.UnHex(); - bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(1004, stream.Value, await Common.GetTicket(context), hash, ext.Serialize().ToArray()); + bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(1004, stream.Value, await Common.GetTicket(context, cancellationToken), hash, extendInfo: ext.Serialize().ToArray(), cancellation: cancellationToken); if (!hwSuccess) { await stream.Value.DisposeAsync(); @@ -57,4 +57,4 @@ public async Task UploadGroup(ContextCollection context, MessageChain chain, IMe await image.ImageStream.Value.DisposeAsync(); } } -} \ No newline at end of file +} diff --git a/Lagrange.Core/Internal/Context/Uploader/PttUploader.cs b/Lagrange.Core/Internal/Context/Uploader/PttUploader.cs index f2bd489a1..032922172 100644 --- a/Lagrange.Core/Internal/Context/Uploader/PttUploader.cs +++ b/Lagrange.Core/Internal/Context/Uploader/PttUploader.cs @@ -8,18 +8,18 @@ namespace Lagrange.Core.Internal.Context.Uploader; [HighwayUploader(typeof(RecordEntity))] internal class PttUploader : IHighwayUploader { - public async Task UploadPrivate(ContextCollection context, MessageChain chain, IMessageEntity entity) + public async Task UploadPrivate(ContextCollection context, MessageChain chain, IMessageEntity entity, CancellationToken cancellationToken) { if (entity is RecordEntity { AudioStream: { } stream } record) { var uploadEvent = RecordUploadEvent.Create(record, chain.FriendInfo?.Uid ?? ""); - var uploadResult = await context.Business.SendEvent(uploadEvent); + var uploadResult = await context.Business.SendEvent(uploadEvent, cancellationToken); var metaResult = (RecordUploadEvent)uploadResult[0]; if (Common.GenerateExt(metaResult) is { } ext) { var hash = metaResult.MsgInfo.MsgInfoBody[0].Index.Info.FileHash.UnHex(); - bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(1007, stream.Value, await Common.GetTicket(context), hash, ext.Serialize().ToArray()); + bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(1007, stream.Value, await Common.GetTicket(context, cancellationToken), hash, extendInfo: ext.Serialize().ToArray(), cancellation: cancellationToken); if (!hwSuccess) { await stream.Value.DisposeAsync(); @@ -33,18 +33,18 @@ public async Task UploadPrivate(ContextCollection context, MessageChain chain, I } } - public async Task UploadGroup(ContextCollection context, MessageChain chain, IMessageEntity entity) + public async Task UploadGroup(ContextCollection context, MessageChain chain, IMessageEntity entity, CancellationToken cancellationToken) { if (entity is RecordEntity { AudioStream: { } stream } record) { var uploadEvent = RecordGroupUploadEvent.Create(record, chain.GroupUin ?? 0); - var uploadResult = await context.Business.SendEvent(uploadEvent); + var uploadResult = await context.Business.SendEvent(uploadEvent, cancellationToken); var metaResult = (RecordGroupUploadEvent)uploadResult[0]; if (Common.GenerateExt(metaResult) is { } ext) { var hash = metaResult.MsgInfo.MsgInfoBody[0].Index.Info.FileHash.UnHex(); - bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(1008, stream.Value, await Common.GetTicket(context), hash, ext.Serialize().ToArray()); + bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(1008, stream.Value, await Common.GetTicket(context, cancellationToken), hash, extendInfo: ext.Serialize().ToArray(), cancellation: cancellationToken); if (!hwSuccess) { await stream.Value.DisposeAsync(); @@ -57,4 +57,4 @@ public async Task UploadGroup(ContextCollection context, MessageChain chain, IMe await record.AudioStream.Value.DisposeAsync(); } } -} \ No newline at end of file +} diff --git a/Lagrange.Core/Internal/Context/Uploader/VideoUploader.cs b/Lagrange.Core/Internal/Context/Uploader/VideoUploader.cs index 5e5df607a..d20fb2e90 100644 --- a/Lagrange.Core/Internal/Context/Uploader/VideoUploader.cs +++ b/Lagrange.Core/Internal/Context/Uploader/VideoUploader.cs @@ -8,12 +8,12 @@ namespace Lagrange.Core.Internal.Context.Uploader; [HighwayUploader(typeof(VideoEntity))] internal class VideoUploader : IHighwayUploader { - public async Task UploadPrivate(ContextCollection context, MessageChain chain, IMessageEntity entity) + public async Task UploadPrivate(ContextCollection context, MessageChain chain, IMessageEntity entity, CancellationToken cancellationToken) { if (entity is VideoEntity { VideoStream: { } stream, ThumbnailStream: { } thumbnail } video) { var uploadEvent = VideoUploadEvent.Create(video, chain.FriendInfo?.Uid ?? ""); - var uploadResult = await context.Business.SendEvent(uploadEvent); + var uploadResult = await context.Business.SendEvent(uploadEvent, cancellationToken); var metaResult = (VideoUploadEvent)uploadResult[0]; if (Common.GenerateExt(metaResult) is { } ext) @@ -21,7 +21,7 @@ public async Task UploadPrivate(ContextCollection context, MessageChain chain, I ext.Hash.FileSha1 = Common.CalculateStreamBytes(stream.Value); var hash = metaResult.MsgInfo.MsgInfoBody[0].Index.Info.FileHash.UnHex(); - bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(1001, stream.Value, await Common.GetTicket(context), hash, ext.Serialize().ToArray()); + bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(1001, stream.Value, await Common.GetTicket(context, cancellationToken), hash, extendInfo: ext.Serialize().ToArray(), cancellation: cancellationToken); if (!hwSuccess) { await stream.Value.DisposeAsync(); @@ -32,7 +32,7 @@ public async Task UploadPrivate(ContextCollection context, MessageChain chain, I if (Common.GenerateExt(metaResult, metaResult.SubFiles[0]) is { } subExt) { var hash = metaResult.MsgInfo.MsgInfoBody[1].Index.Info.FileHash.UnHex(); - bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(1002, thumbnail.Value, await Common.GetTicket(context), hash, subExt.Serialize().ToArray()); + bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(1002, thumbnail.Value, await Common.GetTicket(context, cancellationToken), hash, extendInfo: subExt.Serialize().ToArray(), cancellation: cancellationToken); if (!hwSuccess) { await stream.Value.DisposeAsync(); @@ -48,12 +48,12 @@ public async Task UploadPrivate(ContextCollection context, MessageChain chain, I } } - public async Task UploadGroup(ContextCollection context, MessageChain chain, IMessageEntity entity) + public async Task UploadGroup(ContextCollection context, MessageChain chain, IMessageEntity entity, CancellationToken cancellationToken) { if (entity is VideoEntity { VideoStream: { } stream, ThumbnailStream: { } thumbnail } video) { var uploadEvent = VideoGroupUploadEvent.Create(video, chain.GroupUin ?? 0); - var uploadResult = await context.Business.SendEvent(uploadEvent); + var uploadResult = await context.Business.SendEvent(uploadEvent, cancellationToken); var metaResult = (VideoGroupUploadEvent)uploadResult[0]; if (Common.GenerateExt(metaResult) is { } ext) @@ -61,7 +61,7 @@ public async Task UploadGroup(ContextCollection context, MessageChain chain, IMe ext.Hash.FileSha1 = Common.CalculateStreamBytes(stream.Value); var hash = metaResult.MsgInfo.MsgInfoBody[0].Index.Info.FileHash.UnHex(); - bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(1005, stream.Value, await Common.GetTicket(context), hash, ext.Serialize().ToArray()); + bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(1005, stream.Value, await Common.GetTicket(context, cancellationToken), hash, extendInfo: ext.Serialize().ToArray(), cancellation: cancellationToken); if (!hwSuccess) { await stream.Value.DisposeAsync(); @@ -72,7 +72,7 @@ public async Task UploadGroup(ContextCollection context, MessageChain chain, IMe if (Common.GenerateExt(metaResult, metaResult.SubFiles[0]) is { } subExt) { var hash = metaResult.MsgInfo.MsgInfoBody[1].Index.Info.FileHash.UnHex(); - bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(1006, thumbnail.Value, await Common.GetTicket(context), hash, subExt.Serialize().ToArray()); + bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(1006, thumbnail.Value, await Common.GetTicket(context, cancellationToken), hash, extendInfo: subExt.Serialize().ToArray(), cancellation: cancellationToken); if (!hwSuccess) { await stream.Value.DisposeAsync(); @@ -87,4 +87,4 @@ public async Task UploadGroup(ContextCollection context, MessageChain chain, IMe await thumbnail.Value.DisposeAsync(); } } -} \ No newline at end of file +} diff --git a/Lagrange.Core/Internal/Network/ClientListener.cs b/Lagrange.Core/Internal/Network/ClientListener.cs index 9682b773b..58e963ea8 100644 --- a/Lagrange.Core/Internal/Network/ClientListener.cs +++ b/Lagrange.Core/Internal/Network/ClientListener.cs @@ -20,12 +20,12 @@ internal abstract partial class ClientListener : IClientListener /// public ClientListener() { } - private async Task InternalConnectAsync(SocketSession session, string host, int port) + private async Task InternalConnectAsync(SocketSession session, string host, int port, CancellationToken cancellationToken) { try { - await session.Socket.ConnectAsync(host, port); - _ = ReceiveLoop(session); + await session.Socket.ConnectAsync(host, port, cancellationToken); + _ = ReceiveLoop(session, cancellationToken); return true; } catch (Exception e) @@ -41,8 +41,9 @@ private async Task InternalConnectAsync(SocketSession session, string host /// /// /// + /// /// - public Task Connect(string host, int port) + public Task Connect(string host, int port, CancellationToken cancellationToken) { SocketSession? previousSession = Session, createdSession = null; if (previousSession != null || // The client has been connected @@ -52,7 +53,7 @@ public Task Connect(string host, int port) return Task.FromResult(false); } - return InternalConnectAsync(createdSession, host, port); // Connect to server + return InternalConnectAsync(createdSession, host, port, cancellationToken); // Connect to server } /// diff --git a/Lagrange.Core/Utility/Network/Http.cs b/Lagrange.Core/Utility/Network/Http.cs index b720e21fd..a986d037c 100644 --- a/Lagrange.Core/Utility/Network/Http.cs +++ b/Lagrange.Core/Utility/Network/Http.cs @@ -42,4 +42,12 @@ public static async Task PostAsync(string url, byte[] payload, string co var response = await Client.PostAsync(url, contentData); return await response.Content.ReadAsByteArrayAsync(); } -} \ No newline at end of file + + public static async Task PostAsync(string url, byte[] payload, string content, CancellationToken cancellationToken) + { + var contentData = new ByteArrayContent(payload); + contentData.Headers.ContentType = new MediaTypeHeaderValue(content); + using var response = await Client.PostAsync(url, contentData, cancellationToken); + return await response.Content.ReadAsByteArrayAsync(cancellationToken); + } +} diff --git a/Lagrange.OneBot/Core/Notify/NotifyService.cs b/Lagrange.OneBot/Core/Notify/NotifyService.cs index a54ab1695..bd4b9fbc8 100644 --- a/Lagrange.OneBot/Core/Notify/NotifyService.cs +++ b/Lagrange.OneBot/Core/Notify/NotifyService.cs @@ -99,7 +99,7 @@ public void RegisterEvents() { logger.LogInformation(@event.ToString()); - BotGroupRequest? botGroupRequest = (await bot.ContextCollection.Business.OperationLogic.FetchGroupRequests()) + BotGroupRequest? botGroupRequest = (await bot.ContextCollection.Business.OperationLogic.FetchGroupRequests(CancellationToken.None)) ?.AsParallel() .FirstOrDefault(r => { diff --git a/Lagrange.OneBot/Core/Operation/Ability/UploadImageOperation.cs b/Lagrange.OneBot/Core/Operation/Ability/UploadImageOperation.cs index 78e39a444..f7c16a4ce 100644 --- a/Lagrange.OneBot/Core/Operation/Ability/UploadImageOperation.cs +++ b/Lagrange.OneBot/Core/Operation/Ability/UploadImageOperation.cs @@ -15,12 +15,12 @@ public async Task HandleOperation(BotContext context, JsonNode? pa if (payload?["file"]?.ToString() is { } file && CommonResolver.ResolveStream(file) is { } stream) { var entity = new ImageEntity(stream); - await context.ContextCollection.Highway.ManualUploadEntity(entity); + await context.ContextCollection.Highway.ManualUploadEntity(entity, CancellationToken.None); var msgInfo = entity.MsgInfo; if (msgInfo is null) throw new Exception(); var downloadEvent = ImageDownloadEvent.Create(context.ContextCollection.Keystore.Uid ?? "", msgInfo); - var result = await context.ContextCollection.Business.SendEvent(downloadEvent); + var result = await context.ContextCollection.Business.SendEvent(downloadEvent, CancellationToken.None); var ret = (ImageDownloadEvent)result[0]; return new OneBotResult(ret.ImageUrl, 0, "ok"); diff --git a/Lagrange.OneBot/Core/Operation/Generic/SendPacketOperation.cs b/Lagrange.OneBot/Core/Operation/Generic/SendPacketOperation.cs index 5cb743e21..0a2dbc0f3 100644 --- a/Lagrange.OneBot/Core/Operation/Generic/SendPacketOperation.cs +++ b/Lagrange.OneBot/Core/Operation/Generic/SendPacketOperation.cs @@ -17,7 +17,7 @@ public async Task HandleOperation(BotContext context, JsonNode? pa { int sequence = context.ContextCollection.Service.GetNewSequence(); var ssoPacket = new SsoPacket(send.Type, send.Command, (uint)sequence, send.Data.UnHex()); - var task = await context.ContextCollection.Packet.SendPacket(ssoPacket); + var task = await context.ContextCollection.Packet.SendPacket(ssoPacket, CancellationToken.None); return new OneBotResult(new OneBotSendPacketResponse { diff --git a/Lagrange.OneBot/Core/Operation/Message/SendForwardMessageOperation.cs b/Lagrange.OneBot/Core/Operation/Message/SendForwardMessageOperation.cs index dc5fba242..c329defa4 100644 --- a/Lagrange.OneBot/Core/Operation/Message/SendForwardMessageOperation.cs +++ b/Lagrange.OneBot/Core/Operation/Message/SendForwardMessageOperation.cs @@ -18,7 +18,7 @@ public async Task HandleOperation(BotContext context, JsonNode? pa var chains = common.BuildForwardChains(context, forward); var @event = MultiMsgUploadEvent.Create(null, chains); - var result = await context.ContextCollection.Business.SendEvent(@event); + var result = await context.ContextCollection.Business.SendEvent(@event, CancellationToken.None); if (result.Count != 0 && result[0] is MultiMsgUploadEvent res) { return new OneBotResult(res.ResId, 0, "ok"); diff --git a/Lagrange.OneBot/Core/Operation/Request/SetFriendAddRequestOperation.cs b/Lagrange.OneBot/Core/Operation/Request/SetFriendAddRequestOperation.cs index 3c09ab3cc..09f137e80 100644 --- a/Lagrange.OneBot/Core/Operation/Request/SetFriendAddRequestOperation.cs +++ b/Lagrange.OneBot/Core/Operation/Request/SetFriendAddRequestOperation.cs @@ -13,7 +13,7 @@ public async Task HandleOperation(BotContext context, JsonNode? pa { if (payload.Deserialize(SerializerOptions.DefaultOptions) is { } request) { - bool result = await context.ContextCollection.Business.OperationLogic.SetFriendRequest(request.Flag, request.Approve); + bool result = await context.ContextCollection.Business.OperationLogic.SetFriendRequest(request.Flag, request.Approve, CancellationToken.None); return new OneBotResult(null, result ? 0 : 1, "ok"); } diff --git a/Lagrange.OneBot/Core/Operation/Request/SetGroupAddRequestOperation.cs b/Lagrange.OneBot/Core/Operation/Request/SetGroupAddRequestOperation.cs index e85a45a9c..1faad95bc 100644 --- a/Lagrange.OneBot/Core/Operation/Request/SetGroupAddRequestOperation.cs +++ b/Lagrange.OneBot/Core/Operation/Request/SetGroupAddRequestOperation.cs @@ -21,9 +21,9 @@ public async Task HandleOperation(BotContext context, JsonNode? pa bool result = isFiltered ? await context.ContextCollection.Business.OperationLogic.SetGroupFilteredRequest(groupUin, sequence, - eventType, request.Approve, request.Reason) + eventType, request.Approve, request.Reason, CancellationToken.None) : await context.ContextCollection.Business.OperationLogic.SetGroupRequest(groupUin, sequence, eventType, - request.Approve, request.Reason); + request.Approve, request.Reason, CancellationToken.None); return new OneBotResult(null, result ? 0 : 1, "ok"); } From bff0f207799b4bd3d844ef5673cadfe9805aae97 Mon Sep 17 00:00:00 2001 From: dogdie233 Date: Mon, 21 Oct 2024 23:28:43 +0900 Subject: [PATCH 14/19] fix conflict (#651) --- .../Internal/Context/Logic/Implementation/CachingLogic.cs | 4 ++-- .../Internal/Context/Logic/Implementation/MessagingLogic.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Lagrange.Core/Internal/Context/Logic/Implementation/CachingLogic.cs b/Lagrange.Core/Internal/Context/Logic/Implementation/CachingLogic.cs index c7e766474..667aa196c 100644 --- a/Lagrange.Core/Internal/Context/Logic/Implementation/CachingLogic.cs +++ b/Lagrange.Core/Internal/Context/Logic/Implementation/CachingLogic.cs @@ -75,7 +75,7 @@ public async Task> GetCachedGroups(bool refreshCache, Cancellatio return _uinToUid.GetValueOrDefault(friendUin); } - public async Task ResolveUin(uint? groupUin, string friendUid, bool force, CancellationToken cancellationToken) + public async Task ResolveUin(uint? groupUin, string friendUid, bool force = false, CancellationToken cancellationToken = default) { if (_uinToUid.Count == 0) await ResolveFriendsUidAndFriendGroups(cancellationToken); if (groupUin == null) return _uinToUid.FirstOrDefault(x => x.Value == friendUid).Key; @@ -85,7 +85,7 @@ public async Task> GetCachedGroups(bool refreshCache, Cancellatio return _uinToUid.FirstOrDefault(x => x.Value == friendUid).Key; } - public async Task> GetCachedMembers(uint groupUin, bool refreshCache, CancellationToken cancellationToken) + public async Task> GetCachedMembers(uint groupUin, bool refreshCache, CancellationToken cancellationToken = default) { if (!_cachedGroupMembers.TryGetValue(groupUin, out var members) || refreshCache) { diff --git a/Lagrange.Core/Internal/Context/Logic/Implementation/MessagingLogic.cs b/Lagrange.Core/Internal/Context/Logic/Implementation/MessagingLogic.cs index f9267a8fe..19cbc47db 100644 --- a/Lagrange.Core/Internal/Context/Logic/Implementation/MessagingLogic.cs +++ b/Lagrange.Core/Internal/Context/Logic/Implementation/MessagingLogic.cs @@ -238,7 +238,7 @@ public override async Task Incoming(ProtocolEvent e, CancellationToken cancellat } case GroupSysTodoEvent todo: { - uint uin = await Collection.Business.CachingLogic.ResolveUin(todo.GroupUin, todo.OperatorUid) ?? 0; + uint uin = await Collection.Business.CachingLogic.ResolveUin(todo.GroupUin, todo.OperatorUid, false, cancellationToken) ?? 0; Collection.Invoker.PostEvent(new GroupTodoEvent(todo.GroupUin, uin)); break; From 6f0b2cb8005dc99ff0afa30c4dab73ffa6e2facc Mon Sep 17 00:00:00 2001 From: DarkRRb <177549718+DarkRRb@users.noreply.github.com> Date: Mon, 21 Oct 2024 22:53:30 +0800 Subject: [PATCH 15/19] Revert "feat: Make all API cancellable (#630)" (#655) * Revert "feat: Make all API cancellable (#630)" This reverts commit d015386e4b431dde324e79dd8caba18c1139ac79. * fix --- Lagrange.Core/Common/Interface/Api/BotExt.cs | 34 +- .../Common/Interface/Api/GroupExt.cs | 217 ++--------- .../Common/Interface/Api/OperationExt.cs | 338 ++---------------- .../Internal/Context/BusinessContext.cs | 47 +-- .../Internal/Context/HighwayContext.cs | 34 +- .../Logic/Implementation/CachingLogic.cs | 56 +-- .../Logic/Implementation/MessagingLogic.cs | 102 +++--- .../Logic/Implementation/OperationLogic.cs | 327 ++++++++--------- .../Logic/Implementation/WtExchangeLogic.cs | 171 ++++----- .../Internal/Context/Logic/LogicBase.cs | 6 +- .../Internal/Context/PacketContext.cs | 38 +- .../Internal/Context/SocketContext.cs | 31 +- .../Internal/Context/Uploader/Common.cs | 6 +- .../Internal/Context/Uploader/FileUploader.cs | 219 ++++++------ .../Context/Uploader/IHighwayUploader.cs | 6 +- .../Context/Uploader/ImageUploader.cs | 14 +- .../Internal/Context/Uploader/PttUploader.cs | 14 +- .../Context/Uploader/VideoUploader.cs | 18 +- .../Internal/Network/ClientListener.cs | 11 +- Lagrange.Core/Utility/Network/Http.cs | 10 +- Lagrange.OneBot/Core/Notify/NotifyService.cs | 2 +- .../Operation/Ability/UploadImageOperation.cs | 4 +- .../Operation/Generic/SendPacketOperation.cs | 2 +- .../Message/SendForwardMessageOperation.cs | 2 +- .../Request/SetFriendAddRequestOperation.cs | 2 +- .../Request/SetGroupAddRequestOperation.cs | 4 +- 26 files changed, 599 insertions(+), 1116 deletions(-) diff --git a/Lagrange.Core/Common/Interface/Api/BotExt.cs b/Lagrange.Core/Common/Interface/Api/BotExt.cs index 951b2946b..e709267ad 100644 --- a/Lagrange.Core/Common/Interface/Api/BotExt.cs +++ b/Lagrange.Core/Common/Interface/Api/BotExt.cs @@ -9,37 +9,18 @@ public static class BotExt /// /// return url and qrcode image in PNG format public static Task<(string Url, byte[] QrCode)?> FetchQrCode(this BotContext bot) - => bot.ContextCollection.Business.WtExchangeLogic.FetchQrCode(CancellationToken.None); - - /// - /// Fetch the qrcode for QRCode Login - /// - /// return url and qrcode image in PNG format - public static Task<(string Url, byte[] QrCode)?> FetchQrCode(this BotContext bot, CancellationToken cancellationToken) - => bot.ContextCollection.Business.WtExchangeLogic.FetchQrCode(cancellationToken); + => bot.ContextCollection.Business.WtExchangeLogic.FetchQrCode(); /// /// Use this method to login by QrCode, you should call first /// - public static Task LoginByQrCode(this BotContext bot) - => bot.ContextCollection.Business.WtExchangeLogic.LoginByQrCode(CancellationToken.None); - - /// - /// Use this method to login by QrCode, you should call first - /// - public static Task LoginByQrCode(this BotContext bot, CancellationToken cancellationToken) + public static Task LoginByQrCode(this BotContext bot, CancellationToken cancellationToken = default) => bot.ContextCollection.Business.WtExchangeLogic.LoginByQrCode(cancellationToken); /// /// Use this method to login by password, EasyLogin may be preformed if there is sig in /// - public static Task LoginByPassword(this BotContext bot) - => bot.ContextCollection.Business.WtExchangeLogic.LoginByPassword(CancellationToken.None); - - /// - /// Use this method to login by password, EasyLogin may be preformed if there is sig in - /// - public static Task LoginByPassword(this BotContext bot, CancellationToken cancellationToken) + public static Task LoginByPassword(this BotContext bot, CancellationToken cancellationToken = default) => bot.ContextCollection.Business.WtExchangeLogic.LoginByPassword(cancellationToken); /// @@ -49,11 +30,8 @@ public static Task LoginByPassword(this BotContext bot, CancellationToken public static bool SubmitCaptcha(this BotContext bot, string ticket, string randStr) => bot.ContextCollection.Business.WtExchangeLogic.SubmitCaptcha(ticket, randStr); - public static Task SetNeedToConfirmSwitch(this BotContext bot, bool needToConfirm) - => bot.ContextCollection.Business.OperationLogic.SetNeedToConfirmSwitch(needToConfirm, CancellationToken.None); - - public static Task SetNeedToConfirmSwitch(this BotContext bot, bool needToConfirm, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.SetNeedToConfirmSwitch(needToConfirm, cancellationToken); + public static Task SetNeedToConfirmSwitch(this BotContext bot, bool needToConfirm) + => bot.ContextCollection.Business.OperationLogic.SetNeedToConfirmSwitch(needToConfirm); /// /// Use this method to update keystore, so EasyLogin may be preformed next time by using this keystore @@ -68,4 +46,4 @@ public static BotKeystore UpdateKeystore(this BotContext bot) /// public static BotDeviceInfo UpdateDeviceInfo(this BotContext bot) => bot.ContextCollection.Device; -} +} \ No newline at end of file diff --git a/Lagrange.Core/Common/Interface/Api/GroupExt.cs b/Lagrange.Core/Common/Interface/Api/GroupExt.cs index 3e9327a7b..6e7270e9f 100644 --- a/Lagrange.Core/Common/Interface/Api/GroupExt.cs +++ b/Lagrange.Core/Common/Interface/Api/GroupExt.cs @@ -1,4 +1,3 @@ -using System.Globalization; using Lagrange.Core.Common.Entity; using Lagrange.Core.Event.EventArg; using Lagrange.Core.Message; @@ -17,19 +16,7 @@ public static class GroupExt /// The duration in seconds, 0 for unmute member /// Successfully muted or not public static Task MuteGroupMember(this BotContext bot, uint groupUin, uint targetUin, uint duration) - => bot.ContextCollection.Business.OperationLogic.MuteGroupMember(groupUin, targetUin, duration, CancellationToken.None); - - /// - /// Mute the member in the group, Bot must be admin - /// - /// target BotContext - /// The uin for target group - /// The uin for target member in such group - /// The duration in seconds, 0 for unmute member - /// The cancellation token - /// Successfully muted or not - public static Task MuteGroupMember(this BotContext bot, uint groupUin, uint targetUin, uint duration, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.MuteGroupMember(groupUin, targetUin, duration, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.MuteGroupMember(groupUin, targetUin, duration); /// /// Mute the group @@ -39,18 +26,7 @@ public static Task MuteGroupMember(this BotContext bot, uint groupUin, uin /// true for mute and false for unmute /// Successfully muted or not public static Task MuteGroupGlobal(this BotContext bot, uint groupUin, bool isMute) - => bot.ContextCollection.Business.OperationLogic.MuteGroupGlobal(groupUin, isMute, CancellationToken.None); - - /// - /// Mute the group - /// - /// target BotContext - /// The uin for target group - /// true for mute and false for unmute - /// The cancellation token - /// Successfully muted or not - public static Task MuteGroupGlobal(this BotContext bot, uint groupUin, bool isMute, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.MuteGroupGlobal(groupUin, isMute, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.MuteGroupGlobal(groupUin, isMute); /// /// @@ -61,230 +37,115 @@ public static Task MuteGroupGlobal(this BotContext bot, uint groupUin, boo /// whether the kicked member can request /// Successfully kicked or not public static Task KickGroupMember(this BotContext bot, uint groupUin, uint targetUin, bool rejectAddRequest) - => bot.ContextCollection.Business.OperationLogic.KickGroupMember(groupUin, targetUin, rejectAddRequest, "", CancellationToken.None); - - - /// - /// - /// - /// target BotContext - /// The uin for target group - /// The uin for target member in such group - /// whether the kicked member can request - /// The cancellation token - /// Successfully kicked or not - public static Task KickGroupMember(this BotContext bot, uint groupUin, uint targetUin, bool rejectAddRequest, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.KickGroupMember(groupUin, targetUin, rejectAddRequest, "", cancellationToken); + => bot.ContextCollection.Business.OperationLogic.KickGroupMember(groupUin, targetUin, rejectAddRequest, ""); public static Task KickGroupMember(this BotContext bot, uint groupUin, uint targetUin, bool rejectAddRequest, string reason) - => bot.ContextCollection.Business.OperationLogic.KickGroupMember(groupUin, targetUin, rejectAddRequest, reason, CancellationToken.None); - - public static Task KickGroupMember(this BotContext bot, uint groupUin, uint targetUin, bool rejectAddRequest, string reason, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.KickGroupMember(groupUin, targetUin, rejectAddRequest, reason, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.KickGroupMember(groupUin, targetUin, rejectAddRequest, reason); public static Task SetGroupAdmin(this BotContext bot, uint groupUin, uint targetUin, bool isAdmin) - => bot.ContextCollection.Business.OperationLogic.SetGroupAdmin(groupUin, targetUin, isAdmin, CancellationToken.None); - - public static Task SetGroupAdmin(this BotContext bot, uint groupUin, uint targetUin, bool isAdmin, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.SetGroupAdmin(groupUin, targetUin, isAdmin, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.SetGroupAdmin(groupUin, targetUin, isAdmin); // 300204 Check group manager:Not an administrator public static Task<(int, string?)> SetGroupTodo(this BotContext bot, uint groupUin, uint sequence) - => bot.ContextCollection.Business.OperationLogic.SetGroupTodo(groupUin, sequence, CancellationToken.None); - - // 300204 Check group manager:Not an administrator - public static Task<(int, string?)> SetGroupTodo(this BotContext bot, uint groupUin, uint sequence, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.SetGroupTodo(groupUin, sequence, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.SetGroupTodo(groupUin, sequence); public static Task<(int, string?)> RemoveGroupTodo(this BotContext bot, uint groupUin) - => bot.ContextCollection.Business.OperationLogic.RemoveGroupTodo(groupUin, CancellationToken.None); - - public static Task<(int, string?)> RemoveGroupTodo(this BotContext bot, uint groupUin, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.RemoveGroupTodo(groupUin, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.RemoveGroupTodo(groupUin); public static Task<(int, string?)> FinishGroupTodo(this BotContext bot, uint groupUin) - => bot.ContextCollection.Business.OperationLogic.FinishGroupTodo(groupUin, CancellationToken.None); - - public static Task<(int, string?)> FinishGroupTodo(this BotContext bot, uint groupUin, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.FinishGroupTodo(groupUin, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.FinishGroupTodo(groupUin); public static Task GetGroupTodo(this BotContext bot, uint groupUin) - => bot.ContextCollection.Business.OperationLogic.GetGroupTodo(groupUin, CancellationToken.None); - - public static Task GetGroupTodo(this BotContext bot, uint groupUin, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.GetGroupTodo(groupUin, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.GetGroupTodo(groupUin); public static Task SetGroupBot(this BotContext bot, uint targetUin, uint On, uint groupUin) - => bot.ContextCollection.Business.OperationLogic.SetGroupBot(targetUin, On, groupUin, CancellationToken.None); - - public static Task SetGroupBot(this BotContext bot, uint targetUin, uint On, uint groupUin, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.SetGroupBot(targetUin, On, groupUin, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.SetGroupBot(targetUin, On, groupUin); [Obsolete("Cosider using SetGroupBotHD(BotContext, uint, uint, string?, string?) instead")] public static Task SetGroupBotHD(this BotContext bot, uint targetUin, uint groupUin) => bot.SetGroupBotHD(targetUin, groupUin, null, null); public static Task SetGroupBotHD(this BotContext bot, uint targetUin, uint groupUin, string? data_1, string? data_2) - => bot.ContextCollection.Business.OperationLogic.SetGroupBotHD(targetUin, groupUin, data_1, data_2, CancellationToken.None); - public static Task SetGroupBotHD(this BotContext bot, uint targetUin, uint groupUin, string? data_1, string? data_2, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.SetGroupBotHD(targetUin, groupUin, data_1, data_2, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.SetGroupBotHD(targetUin, groupUin, data_1, data_2); public static Task RenameGroupMember(this BotContext bot, uint groupUin, uint targetUin, string targetName) - => bot.ContextCollection.Business.OperationLogic.RenameGroupMember(groupUin, targetUin, targetName, CancellationToken.None); - - public static Task RenameGroupMember(this BotContext bot, uint groupUin, uint targetUin, string targetName, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.RenameGroupMember(groupUin, targetUin, targetName, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.RenameGroupMember(groupUin, targetUin, targetName); public static Task RenameGroup(this BotContext bot, uint groupUin, string targetName) - => bot.ContextCollection.Business.OperationLogic.RenameGroup(groupUin, targetName, CancellationToken.None); - - public static Task RenameGroup(this BotContext bot, uint groupUin, string targetName, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.RenameGroup(groupUin, targetName, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.RenameGroup(groupUin, targetName); public static Task RemarkGroup(this BotContext bot, uint groupUin, string targetRemark) - => bot.ContextCollection.Business.OperationLogic.RemarkGroup(groupUin, targetRemark, CancellationToken.None); - - public static Task RemarkGroup(this BotContext bot, uint groupUin, string targetRemark, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.RemarkGroup(groupUin, targetRemark, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.RemarkGroup(groupUin, targetRemark); public static Task LeaveGroup(this BotContext bot, uint groupUin) - => bot.ContextCollection.Business.OperationLogic.LeaveGroup(groupUin, CancellationToken.None); - - public static Task LeaveGroup(this BotContext bot, uint groupUin, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.LeaveGroup(groupUin, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.LeaveGroup(groupUin); public static Task InviteGroup(this BotContext bot, uint groupUin, Dictionary invitedUins) - => bot.ContextCollection.Business.OperationLogic.InviteGroup(groupUin, invitedUins, CancellationToken.None); - - public static Task InviteGroup(this BotContext bot, uint groupUin, Dictionary invitedUins, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.InviteGroup(groupUin, invitedUins, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.InviteGroup(groupUin, invitedUins); public static Task SetGroupRequest(this BotContext bot, BotGroupRequest request, bool accept = true, string reason = "") - => bot.ContextCollection.Business.OperationLogic.SetGroupRequest(request.GroupUin, request.Sequence, (uint)request.EventType, accept, reason, CancellationToken.None); - - public static Task SetGroupRequest(this BotContext bot, BotGroupRequest request, bool accept, string reason, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.SetGroupRequest(request.GroupUin, request.Sequence, (uint)request.EventType, accept, reason, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.SetGroupRequest(request.GroupUin, request.Sequence, (uint)request.EventType, accept, reason); public static Task SetGroupFilteredRequest(this BotContext bot, BotGroupRequest request, bool accept = true, string reason = "") - => bot.ContextCollection.Business.OperationLogic.SetGroupFilteredRequest(request.GroupUin, request.Sequence, (uint)request.EventType, accept, reason, CancellationToken.None); - - public static Task SetGroupFilteredRequest(this BotContext bot, BotGroupRequest request, bool accept, string reason, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.SetGroupFilteredRequest(request.GroupUin, request.Sequence, (uint)request.EventType, accept, reason, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.SetGroupFilteredRequest(request.GroupUin, request.Sequence, (uint)request.EventType, accept, reason); public static Task SetFriendRequest(this BotContext bot, FriendRequestEvent request, bool accept = true) - => bot.ContextCollection.Business.OperationLogic.SetFriendRequest(request.SourceUid, accept, CancellationToken.None); - - public static Task SetFriendRequest(this BotContext bot, FriendRequestEvent request, bool accept, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.SetFriendRequest(request.SourceUid, accept, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.SetFriendRequest(request.SourceUid, accept); public static Task GroupPoke(this BotContext bot, uint groupUin, uint friendUin) - => bot.ContextCollection.Business.OperationLogic.GroupPoke(groupUin, friendUin, CancellationToken.None); - - public static Task GroupPoke(this BotContext bot, uint groupUin, uint friendUin, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.GroupPoke(groupUin, friendUin, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.GroupPoke(groupUin, friendUin); public static Task SetEssenceMessage(this BotContext bot, MessageChain chain) - => bot.ContextCollection.Business.OperationLogic.SetEssenceMessage(chain.GroupUin ?? 0, chain.Sequence, (uint)(chain.MessageId & 0xFFFFFFFF), CancellationToken.None); - - public static Task SetEssenceMessage(this BotContext bot, MessageChain chain, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.SetEssenceMessage(chain.GroupUin ?? 0, chain.Sequence, (uint)(chain.MessageId & 0xFFFFFFFF), cancellationToken); + => bot.ContextCollection.Business.OperationLogic.SetEssenceMessage(chain.GroupUin ?? 0, chain.Sequence, (uint)(chain.MessageId & 0xFFFFFFFF)); public static Task RemoveEssenceMessage(this BotContext bot, MessageChain chain) - => bot.ContextCollection.Business.OperationLogic.RemoveEssenceMessage(chain.GroupUin ?? 0, chain.Sequence, (uint)(chain.MessageId & 0xFFFFFFFF), CancellationToken.None); - - public static Task RemoveEssenceMessage(this BotContext bot, MessageChain chain, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.RemoveEssenceMessage(chain.GroupUin ?? 0, chain.Sequence, (uint)(chain.MessageId & 0xFFFFFFFF), cancellationToken); + => bot.ContextCollection.Business.OperationLogic.RemoveEssenceMessage(chain.GroupUin ?? 0, chain.Sequence, (uint)(chain.MessageId & 0xFFFFFFFF)); public static Task GroupSetSpecialTitle(this BotContext bot, uint groupUin, uint targetUin, string title) - => bot.ContextCollection.Business.OperationLogic.GroupSetSpecialTitle(groupUin, targetUin, title, CancellationToken.None); - - public static Task GroupSetSpecialTitle(this BotContext bot, uint groupUin, uint targetUin, string title, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.GroupSetSpecialTitle(groupUin, targetUin, title, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.GroupSetSpecialTitle(groupUin, targetUin, title); public static Task GroupSetMessageReaction(this BotContext bot, uint groupUin, uint sequence, string code) - => bot.ContextCollection.Business.OperationLogic.SetMessageReaction(groupUin, sequence, code, true, CancellationToken.None); - - public static Task GroupSetMessageReaction(this BotContext bot, uint groupUin, uint sequence, string code, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.SetMessageReaction(groupUin, sequence, code, true, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.SetMessageReaction(groupUin, sequence, code, true); public static Task GroupSetMessageReaction(this BotContext bot, uint groupUin, uint sequence, string code, bool isSet) - => bot.ContextCollection.Business.OperationLogic.SetMessageReaction(groupUin, sequence, code, isSet, CancellationToken.None); - - public static Task GroupSetMessageReaction(this BotContext bot, uint groupUin, uint sequence, string code, bool isSet, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.SetMessageReaction(groupUin, sequence, code, isSet, cancellationToken); - + => bot.ContextCollection.Business.OperationLogic.SetMessageReaction(groupUin, sequence, code, isSet); + public static Task GroupSetAvatar(this BotContext bot, uint groupUin, ImageEntity imageEntity) - => bot.ContextCollection.Business.OperationLogic.GroupSetAvatar(groupUin, imageEntity, CancellationToken.None); + => bot.ContextCollection.Business.OperationLogic.GroupSetAvatar(groupUin, imageEntity); - public static Task GroupSetAvatar(this BotContext bot, uint groupUin, ImageEntity imageEntity, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.GroupSetAvatar(groupUin, imageEntity, cancellationToken); - public static Task<(uint, uint)> GroupRemainAtAll(this BotContext bot, uint groupUin) - => bot.ContextCollection.Business.OperationLogic.GroupRemainAtAll(groupUin, CancellationToken.None); - - public static Task<(uint, uint)> GroupRemainAtAll(this BotContext bot, uint groupUin, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.GroupRemainAtAll(groupUin, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.GroupRemainAtAll(groupUin); #region Group File System public static Task FetchGroupFSSpace(this BotContext bot, uint groupUin) - => bot.ContextCollection.Business.OperationLogic.FetchGroupFSSpace(groupUin, CancellationToken.None); - - public static Task FetchGroupFSSpace(this BotContext bot, uint groupUin, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.FetchGroupFSSpace(groupUin, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.FetchGroupFSSpace(groupUin); public static Task FetchGroupFSCount(this BotContext bot, uint groupUin) - => bot.ContextCollection.Business.OperationLogic.FetchGroupFSCount(groupUin, CancellationToken.None); - - public static Task FetchGroupFSCount(this BotContext bot, uint groupUin, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.FetchGroupFSCount(groupUin, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.FetchGroupFSCount(groupUin); public static Task> FetchGroupFSList(this BotContext bot, uint groupUin, string targetDirectory = "/") - => bot.ContextCollection.Business.OperationLogic.FetchGroupFSList(groupUin, targetDirectory, CancellationToken.None); - - public static Task> FetchGroupFSList(this BotContext bot, uint groupUin, string targetDirectory, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.FetchGroupFSList(groupUin, targetDirectory, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.FetchGroupFSList(groupUin, targetDirectory); public static Task FetchGroupFSDownload(this BotContext bot, uint groupUin, string fileId) - => bot.ContextCollection.Business.OperationLogic.FetchGroupFSDownload(groupUin, fileId, CancellationToken.None); - - public static Task FetchGroupFSDownload(this BotContext bot, uint groupUin, string fileId, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.FetchGroupFSDownload(groupUin, fileId, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.FetchGroupFSDownload(groupUin, fileId); public static Task<(int RetCode, string RetMsg)> GroupFSMove(this BotContext bot, uint groupUin, string fileId, string parentDirectory, string targetDirectory) - => bot.ContextCollection.Business.OperationLogic.GroupFSMove(groupUin, fileId, parentDirectory, targetDirectory, CancellationToken.None); - - public static Task<(int RetCode, string RetMsg)> GroupFSMove(this BotContext bot, uint groupUin, string fileId, string parentDirectory, string targetDirectory, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.GroupFSMove(groupUin, fileId, parentDirectory, targetDirectory, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.GroupFSMove(groupUin, fileId, parentDirectory, targetDirectory); public static Task<(int RetCode, string RetMsg)> GroupFSDelete(this BotContext bot, uint groupUin, string fileId) - => bot.ContextCollection.Business.OperationLogic.GroupFSDelete(groupUin, fileId, CancellationToken.None); - - public static Task<(int RetCode, string RetMsg)> GroupFSDelete(this BotContext bot, uint groupUin, string fileId, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.GroupFSDelete(groupUin, fileId, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.GroupFSDelete(groupUin, fileId); public static Task<(int RetCode, string RetMsg)> GroupFSCreateFolder(this BotContext bot, uint groupUin, string name) - => bot.ContextCollection.Business.OperationLogic.GroupFSCreateFolder(groupUin, name, CancellationToken.None); - - public static Task<(int RetCode, string RetMsg)> GroupFSCreateFolder(this BotContext bot, uint groupUin, string name, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.GroupFSCreateFolder(groupUin, name, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.GroupFSCreateFolder(groupUin, name); public static Task<(int RetCode, string RetMsg)> GroupFSDeleteFolder(this BotContext bot, uint groupUin, string folderId) - => bot.ContextCollection.Business.OperationLogic.GroupFSDeleteFolder(groupUin, folderId, CancellationToken.None); - - public static Task<(int RetCode, string RetMsg)> GroupFSDeleteFolder(this BotContext bot, uint groupUin, string folderId, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.GroupFSDeleteFolder(groupUin, folderId, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.GroupFSDeleteFolder(groupUin, folderId); public static Task<(int RetCode, string RetMsg)> GroupFSRenameFolder(this BotContext bot, uint groupUin, string folderId, string newFolderName) - => bot.ContextCollection.Business.OperationLogic.GroupFSRenameFolder(groupUin, folderId, newFolderName, CancellationToken.None); - - public static Task<(int RetCode, string RetMsg)> GroupFSRenameFolder(this BotContext bot, uint groupUin, string folderId, string newFolderName, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.GroupFSRenameFolder(groupUin, folderId, newFolderName, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.GroupFSRenameFolder(groupUin, folderId, newFolderName); public static Task GroupFSUpload(this BotContext bot, uint groupUin, FileEntity fileEntity, string targetDirectory = "/") - => bot.ContextCollection.Business.OperationLogic.GroupFSUpload(groupUin, fileEntity, targetDirectory, CancellationToken.None); - - public static Task GroupFSUpload(this BotContext bot, uint groupUin, FileEntity fileEntity, string targetDirectory, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.GroupFSUpload(groupUin, fileEntity, targetDirectory, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.GroupFSUpload(groupUin, fileEntity, targetDirectory); #endregion -} +} \ No newline at end of file diff --git a/Lagrange.Core/Common/Interface/Api/OperationExt.cs b/Lagrange.Core/Common/Interface/Api/OperationExt.cs index 355afb399..3900a4416 100644 --- a/Lagrange.Core/Common/Interface/Api/OperationExt.cs +++ b/Lagrange.Core/Common/Interface/Api/OperationExt.cs @@ -13,18 +13,7 @@ public static class OperationExt /// force the cache to be refreshed /// public static Task> FetchFriends(this BotContext bot, bool refreshCache = false) - => bot.ContextCollection.Business.OperationLogic.FetchFriends(refreshCache, CancellationToken.None); - - - /// - /// Fetch the friend list of account from server or cache - /// - /// target BotContext - /// The cancellation token - /// force the cache to be refreshed - /// - public static Task> FetchFriends(this BotContext bot, bool refreshCache, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.FetchFriends(refreshCache, CancellationToken.None); + => bot.ContextCollection.Business.OperationLogic.FetchFriends(refreshCache); /// /// Fetch the member list of the group from server or cache @@ -34,18 +23,7 @@ public static Task> FetchFriends(this BotContext bot, bool refre /// force the cache to be refreshed /// public static Task> FetchMembers(this BotContext bot, uint groupUin, bool refreshCache = false) - => bot.ContextCollection.Business.OperationLogic.FetchMembers(groupUin, CancellationToken.None, refreshCache); - - /// - /// Fetch the member list of the group from server or cache - /// - /// target BotContext - /// - /// The cancellation token - /// force the cache to be refreshed - /// - public static Task> FetchMembers(this BotContext bot, uint groupUin, bool refreshCache, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.FetchMembers(groupUin, cancellationToken, refreshCache); + => bot.ContextCollection.Business.OperationLogic.FetchMembers(groupUin, refreshCache); /// /// Fetch the group list of the account from server or cache @@ -54,17 +32,7 @@ public static Task> FetchMembers(this BotContext bot, uint /// force the cache to be refreshed /// public static Task> FetchGroups(this BotContext bot, bool refreshCache = false) - => bot.ContextCollection.Business.OperationLogic.FetchGroups(refreshCache, CancellationToken.None); - - /// - /// Fetch the group list of the account from server or cache - /// - /// target BotContext - /// The cancellation token - /// force the cache to be refreshed - /// - public static Task> FetchGroups(this BotContext bot, bool refreshCache, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.FetchGroups(refreshCache, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.FetchGroups(refreshCache); /// /// Fetch the cookies/pskey for accessing other site @@ -73,17 +41,7 @@ public static Task> FetchGroups(this BotContext bot, bool refresh /// the domain for the cookie to be valid /// the list of cookies public static Task> FetchCookies(this BotContext bot, List domains) - => bot.ContextCollection.Business.OperationLogic.GetCookies(domains, CancellationToken.None); - - /// - /// Fetch the cookies/pskey for accessing other site - /// - /// target BotContext - /// the domain for the cookie to be valid - /// The cancellation token - /// the list of cookies - public static Task> FetchCookies(this BotContext bot, List domains, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.GetCookies(domains, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.GetCookies(domains); /// /// Send the message @@ -91,37 +49,17 @@ public static Task> FetchCookies(this BotContext bot, List /// target BotContext /// the chain constructed by public static Task SendMessage(this BotContext bot, MessageChain chain) - => bot.ContextCollection.Business.OperationLogic.SendMessage(chain, CancellationToken.None); - - /// - /// Send the message - /// - /// target BotContext - /// the chain constructed by - /// The cancellation token - public static Task SendMessage(this BotContext bot, MessageChain chain, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.SendMessage(chain, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.SendMessage(chain); /// /// Recall the group message from Bot itself by /// /// target BotContext /// The uin for target group of the message - /// The return value for + /// The return value for /// Successfully recalled or not public static Task RecallGroupMessage(this BotContext bot, uint groupUin, MessageResult result) - => bot.ContextCollection.Business.OperationLogic.RecallGroupMessage(groupUin, result, CancellationToken.None); - - /// - /// Recall the group message from Bot itself by - /// - /// target BotContext - /// The uin for target group of the message - /// The return value for - /// The cancellation token - /// Successfully recalled or not - public static Task RecallGroupMessage(this BotContext bot, uint groupUin, MessageResult result, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.RecallGroupMessage(groupUin, result, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.RecallGroupMessage(groupUin, result); /// /// Recall the group message by @@ -130,17 +68,7 @@ public static Task RecallGroupMessage(this BotContext bot, uint groupUin, /// target MessageChain, must be Group /// Successfully recalled or not public static Task RecallGroupMessage(this BotContext bot, MessageChain chain) - => bot.ContextCollection.Business.OperationLogic.RecallGroupMessage(chain, CancellationToken.None); - - /// - /// Recall the group message by - /// - /// target BotContext - /// target MessageChain, must be Group - /// The cancellation token - /// Successfully recalled or not - public static Task RecallGroupMessage(this BotContext bot, MessageChain chain, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.RecallGroupMessage(chain, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.RecallGroupMessage(chain); /// /// Recall the group message by sequence @@ -150,39 +78,17 @@ public static Task RecallGroupMessage(this BotContext bot, MessageChain ch /// The sequence for target message /// Successfully recalled or not public static Task RecallGroupMessage(this BotContext bot, uint groupUin, uint sequence) - => bot.ContextCollection.Business.OperationLogic.RecallGroupMessage(groupUin, sequence, CancellationToken.None); - - /// - /// Recall the group message by sequence - /// - /// target BotContext - /// The uin for target group of the message - /// The sequence for target message - /// The cancellation token - /// Successfully recalled or not - public static Task RecallGroupMessage(this BotContext bot, uint groupUin, uint sequence, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.RecallGroupMessage(groupUin, sequence, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.RecallGroupMessage(groupUin, sequence); /// /// Recall the group message from Bot itself by /// /// target BotContext /// The uin for target friend of the message - /// The return value for + /// The return value for /// Successfully recalled or not public static Task RecallFriendMessage(this BotContext bot, uint friendUin, MessageResult result) - => bot.ContextCollection.Business.OperationLogic.RecallFriendMessage(friendUin, result, CancellationToken.None); - - /// - /// Recall the group message from Bot itself by - /// - /// target BotContext - /// The uin for target friend of the message - /// The return value for - /// The cancellation token - /// Successfully recalled or not - public static Task RecallFriendMessage(this BotContext bot, uint friendUin, MessageResult result, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.RecallFriendMessage(friendUin, result, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.RecallFriendMessage(friendUin, result); /// /// Recall the group message by @@ -191,17 +97,7 @@ public static Task RecallFriendMessage(this BotContext bot, uint friendUin /// target MessageChain, must be Friend /// Successfully recalled or not public static Task RecallFriendMessage(this BotContext bot, MessageChain chain) - => bot.ContextCollection.Business.OperationLogic.RecallFriendMessage(chain, CancellationToken.None); - - /// - /// Recall the group message by - /// - /// target BotContext - /// target MessageChain, must be Friend - /// The cancellation token - /// Successfully recalled or not - public static Task RecallFriendMessage(this BotContext bot, MessageChain chain, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.RecallFriendMessage(chain, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.RecallFriendMessage(chain); /// /// Fetch Notifications and requests such as friend requests and Group Join Requests @@ -209,16 +105,7 @@ public static Task RecallFriendMessage(this BotContext bot, MessageChain c /// target BotContext /// public static Task?> FetchGroupRequests(this BotContext bot) - => bot.ContextCollection.Business.OperationLogic.FetchGroupRequests(CancellationToken.None); - - /// - /// Fetch Notifications and requests such as friend requests and Group Join Requests - /// - /// target BotContext - /// The cancellation token - /// - public static Task?> FetchGroupRequests(this BotContext bot, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.FetchGroupRequests(cancellationToken); + => bot.ContextCollection.Business.OperationLogic.FetchGroupRequests(); /// /// @@ -226,16 +113,7 @@ public static Task RecallFriendMessage(this BotContext bot, MessageChain c /// /// public static Task?> FetchFriendRequests(this BotContext bot) - => bot.ContextCollection.Business.OperationLogic.FetchFriendRequests(CancellationToken.None); - - /// - /// - /// - /// - /// The cancellation token - /// - public static Task?> FetchFriendRequests(this BotContext bot, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.FetchFriendRequests(cancellationToken); + => bot.ContextCollection.Business.OperationLogic.FetchFriendRequests(); /// /// set status @@ -244,17 +122,7 @@ public static Task RecallFriendMessage(this BotContext bot, MessageChain c /// The status code /// public static Task SetStatus(this BotContext bot, uint status) - => bot.ContextCollection.Business.OperationLogic.SetStatus(status, CancellationToken.None); - - /// - /// set status - /// - /// target BotContext - /// The status code - /// The cancellation token - /// - public static Task SetStatus(this BotContext bot, uint status, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.SetStatus(status, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.SetStatus(status); /// /// set custom status @@ -264,48 +132,22 @@ public static Task SetStatus(this BotContext bot, uint status, Cancellatio /// text that would shown /// public static Task SetCustomStatus(this BotContext bot, uint faceId, string text) - => bot.ContextCollection.Business.OperationLogic.SetCustomStatus(faceId, text, CancellationToken.None); - - /// - /// set custom status - /// - /// target BotContext - /// faceId that is same as the - /// text that would shown - /// The cancellation token - /// - public static Task SetCustomStatus(this BotContext bot, uint faceId, string text, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.SetCustomStatus(faceId, text, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.SetCustomStatus(faceId, text); public static Task GroupTransfer(this BotContext bot, uint groupUin, uint targetUin) - => bot.ContextCollection.Business.OperationLogic.GroupTransfer(groupUin, targetUin, CancellationToken.None); - - public static Task GroupTransfer(this BotContext bot, uint groupUin, uint targetUin, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.GroupTransfer(groupUin, targetUin, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.GroupTransfer(groupUin, targetUin); public static Task RequestFriend(this BotContext bot, uint targetUin, string question = "", string message = "") - => bot.ContextCollection.Business.OperationLogic.RequestFriend(targetUin, question, message, CancellationToken.None); - - public static Task RequestFriend(this BotContext bot, uint targetUin, string question, string message, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.RequestFriend(targetUin, question, message, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.RequestFriend(targetUin, question, message); public static Task Like(this BotContext bot, uint targetUin, uint count = 1) - => bot.ContextCollection.Business.OperationLogic.Like(targetUin, count, CancellationToken.None); - - public static Task Like(this BotContext bot, uint targetUin, uint count, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.Like(targetUin, count, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.Like(targetUin, count); /// /// Get the client key for all sites /// public static Task GetClientKey(this BotContext bot) - => bot.ContextCollection.Business.OperationLogic.GetClientKey(CancellationToken.None); - - /// - /// Get the client key for all sites - /// - public static Task GetClientKey(this BotContext bot, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.GetClientKey(cancellationToken); + => bot.ContextCollection.Business.OperationLogic.GetClientKey(); /// /// Get the history message record, max 30 seqs @@ -315,18 +157,7 @@ public static Task Like(this BotContext bot, uint targetUin, uint count, C /// Start Sequence of the message /// End Sequence of the message public static Task?> GetGroupMessage(this BotContext bot, uint groupUin, uint startSequence, uint endSequence) - => bot.ContextCollection.Business.OperationLogic.GetGroupMessage(groupUin, startSequence, endSequence, CancellationToken.None); - - /// - /// Get the history message record, max 30 seqs - /// - /// target BotContext - /// target GroupUin - /// Start Sequence of the message - /// End Sequence of the message - /// The cancellation token - public static Task?> GetGroupMessage(this BotContext bot, uint groupUin, uint startSequence, uint endSequence, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.GetGroupMessage(groupUin, startSequence, endSequence, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.GetGroupMessage(groupUin, startSequence, endSequence); /// /// Get the history message record for private message @@ -336,18 +167,7 @@ public static Task Like(this BotContext bot, uint targetUin, uint count, C /// timestamp of the message chain /// number of message to be fetched before timestamp public static Task?> GetRoamMessage(this BotContext bot, uint friendUin, uint timestamp, uint count) - => bot.ContextCollection.Business.OperationLogic.GetRoamMessage(friendUin, timestamp, count, CancellationToken.None); - - /// - /// Get the history message record for private message - /// - /// target BotContext - /// target FriendUin - /// timestamp of the message chain - /// number of message to be fetched before timestamp - /// The cancellation token - public static Task?> GetRoamMessage(this BotContext bot, uint friendUin, uint timestamp, uint count, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.GetRoamMessage(friendUin, timestamp, count, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.GetRoamMessage(friendUin, timestamp, count); /// /// Get the history message record for private message @@ -358,40 +178,17 @@ public static Task Like(this BotContext bot, uint targetUin, uint count, C public static Task?> GetRoamMessage(this BotContext bot, MessageChain targetChain, uint count) { uint timestamp = (uint)new DateTimeOffset(targetChain.Time).ToUnixTimeSeconds(); - return bot.ContextCollection.Business.OperationLogic.GetRoamMessage(targetChain.FriendUin, timestamp, count, CancellationToken.None); - } - - /// - /// Get the history message record for private message - /// - /// target BotContext - /// target chain - /// number of message to be fetched before timestamp - /// The cancellation token - public static Task?> GetRoamMessage(this BotContext bot, MessageChain targetChain, uint count, CancellationToken cancellationToken) - { - uint timestamp = (uint)new DateTimeOffset(targetChain.Time).ToUnixTimeSeconds(); - return bot.ContextCollection.Business.OperationLogic.GetRoamMessage(targetChain.FriendUin, timestamp, count, cancellationToken); + return bot.ContextCollection.Business.OperationLogic.GetRoamMessage(targetChain.FriendUin, timestamp, count); } public static Task?> GetC2cMessage(this BotContext bot, uint friendUin, uint startSequence, uint endSequence) { - return bot.ContextCollection.Business.OperationLogic.GetC2cMessage(friendUin, startSequence, endSequence, CancellationToken.None); - } - - public static Task?> GetC2cMessage(this BotContext bot, uint friendUin, uint startSequence, uint endSequence, CancellationToken cancellationToken) - { - return bot.ContextCollection.Business.OperationLogic.GetC2cMessage(friendUin, startSequence, endSequence, cancellationToken); + return bot.ContextCollection.Business.OperationLogic.GetC2cMessage(friendUin, startSequence, endSequence); } public static Task<(int code, List? chains)> GetMessagesByResId(this BotContext bot, string resId) { - return bot.ContextCollection.Business.OperationLogic.GetMessagesByResId(resId, CancellationToken.None); - } - - public static Task<(int code, List? chains)> GetMessagesByResId(this BotContext bot, string resId, CancellationToken cancellationToken) - { - return bot.ContextCollection.Business.OperationLogic.GetMessagesByResId(resId, cancellationToken); + return bot.ContextCollection.Business.OperationLogic.GetMessagesByResId(resId); } /// @@ -401,59 +198,28 @@ public static Task Like(this BotContext bot, uint targetUin, uint count, C /// target groupUin /// public static Task GroupClockIn(this BotContext bot, uint groupUin) - => bot.ContextCollection.Business.OperationLogic.GroupClockIn(groupUin, CancellationToken.None); - - /// - /// Do group clock in (群打卡) - /// - /// target BotContext - /// target groupUin - /// The cancellation token - /// - public static Task GroupClockIn(this BotContext bot, uint groupUin, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.GroupClockIn(groupUin, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.GroupClockIn(groupUin); public static Task FetchUserInfo(this BotContext bot, uint uin, bool refreshCache = false) - => bot.ContextCollection.Business.OperationLogic.FetchUserInfo(uin, refreshCache, CancellationToken.None); - - public static Task FetchUserInfo(this BotContext bot, uint uin, bool refreshCache, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.FetchUserInfo(uin, refreshCache, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.FetchUserInfo(uin, refreshCache); public static Task?> FetchCustomFace(this BotContext bot) - => bot.ContextCollection.Business.OperationLogic.FetchCustomFace(CancellationToken.None); - - public static Task?> FetchCustomFace(this BotContext bot, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.FetchCustomFace(cancellationToken); + => bot.ContextCollection.Business.OperationLogic.FetchCustomFace(); public static Task UploadLongMessage(this BotContext bot, List chains) - => bot.ContextCollection.Business.OperationLogic.UploadLongMessage(chains, CancellationToken.None); - - public static Task UploadLongMessage(this BotContext bot, List chains, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.UploadLongMessage(chains, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.UploadLongMessage(chains); public static Task MarkAsRead(this BotContext bot, MessageChain targetChain) { uint timestamp = (uint)(targetChain.Time - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds; - return bot.ContextCollection.Business.OperationLogic.MarkAsRead(targetChain.GroupUin ?? 0, targetChain.Uid, targetChain.Sequence, timestamp, CancellationToken.None); - } - - public static Task MarkAsRead(this BotContext bot, MessageChain targetChain, CancellationToken cancellationToken) - { - uint timestamp = (uint)(targetChain.Time - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds; - return bot.ContextCollection.Business.OperationLogic.MarkAsRead(targetChain.GroupUin ?? 0, targetChain.Uid, targetChain.Sequence, timestamp, cancellationToken); + return bot.ContextCollection.Business.OperationLogic.MarkAsRead(targetChain.GroupUin ?? 0, targetChain.Uid, targetChain.Sequence, timestamp); } public static Task UploadFriendFile(this BotContext bot, uint targetUin, FileEntity fileEntity) - => bot.ContextCollection.Business.OperationLogic.UploadFriendFile(targetUin, fileEntity, CancellationToken.None); - - public static Task UploadFriendFile(this BotContext bot, uint targetUin, FileEntity fileEntity, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.UploadFriendFile(targetUin, fileEntity, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.UploadFriendFile(targetUin, fileEntity); public static Task FriendPoke(this BotContext bot, uint friendUin) - => bot.ContextCollection.Business.OperationLogic.FriendPoke(friendUin, CancellationToken.None); - - public static Task FriendPoke(this BotContext bot, uint friendUin, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.FriendPoke(friendUin, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.FriendPoke(friendUin); /// /// Send a special window shake to friend @@ -462,17 +228,7 @@ public static Task FriendPoke(this BotContext bot, uint friendUin, Cancell /// face type /// count of face public static Task FriendSpecialShake(this BotContext bot, uint friendUin, SpecialPokeFaceType type, uint count) - => bot.ContextCollection.Business.OperationLogic.FriendSpecialShake(friendUin, type, count, CancellationToken.None); - - /// - /// Send a special window shake to friend - /// - /// target friend uin - /// face type - /// count of face - /// The cancellation token - public static Task FriendSpecialShake(this BotContext bot, uint friendUin, SpecialPokeFaceType type, uint count, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.FriendSpecialShake(friendUin, type, count, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.FriendSpecialShake(friendUin, type, count); /// /// Send a window shake to friend @@ -481,23 +237,10 @@ public static Task FriendSpecialShake(this BotContext bot, uint f /// face type /// How big the face will be displayed ([0,3] is valid) public static Task FriendShake(this BotContext bot, uint friendUin, PokeFaceType type, ushort strength) - => bot.ContextCollection.Business.OperationLogic.FriendShake(friendUin, type, strength, CancellationToken.None); - - /// - /// Send a window shake to friend - /// - /// target friend uin - /// face type - /// How big the face will be displayed ([0,3] is valid) - /// The cancellation token - public static Task FriendShake(this BotContext bot, uint friendUin, PokeFaceType type, ushort strength, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.FriendShake(friendUin, type, strength, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.FriendShake(friendUin, type, strength); public static Task?> FetchMarketFaceKey(this BotContext bot, List faceIds) - => bot.ContextCollection.Business.OperationLogic.FetchMarketFaceKey(faceIds, CancellationToken.None); - - public static Task?> FetchMarketFaceKey(this BotContext bot, List faceIds, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.FetchMarketFaceKey(faceIds, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.FetchMarketFaceKey(faceIds); /// /// Set the avatar of the bot itself @@ -505,14 +248,5 @@ public static Task FriendShake(this BotContext bot, uint friendUi /// target /// The avatar object, public static Task SetAvatar(this BotContext bot, ImageEntity avatar) - => bot.ContextCollection.Business.OperationLogic.SetAvatar(avatar, CancellationToken.None); - - /// - /// Set the avatar of the bot itself - /// - /// target - /// The avatar object, - /// The cancellation token - public static Task SetAvatar(this BotContext bot, ImageEntity avatar, CancellationToken cancellationToken) - => bot.ContextCollection.Business.OperationLogic.SetAvatar(avatar, cancellationToken); + => bot.ContextCollection.Business.OperationLogic.SetAvatar(avatar); } diff --git a/Lagrange.Core/Internal/Context/BusinessContext.cs b/Lagrange.Core/Internal/Context/BusinessContext.cs index 40f213054..9b5e44658 100644 --- a/Lagrange.Core/Internal/Context/BusinessContext.cs +++ b/Lagrange.Core/Internal/Context/BusinessContext.cs @@ -73,16 +73,12 @@ private void RegisterLogics() } } - public async Task PushEvent(ProtocolEvent @event, CancellationToken cancellationToken) + public async Task PushEvent(ProtocolEvent @event) { try { var packets = Collection.Service.ResolvePacketByEvent(@event); - foreach (var packet in packets) - { - cancellationToken.ThrowIfCancellationRequested(); - await Collection.Packet.PostPacket(packet); - } + foreach (var packet in packets) await Collection.Packet.PostPacket(packet); } catch { @@ -95,32 +91,25 @@ public async Task PushEvent(ProtocolEvent @event, CancellationToken cancel /// /// Send Event to the Server, goes through the given context /// - public async Task> SendEvent(ProtocolEvent @event, CancellationToken cancellationToken) + public async Task> SendEvent(ProtocolEvent @event) { - await HandleOutgoingEvent(@event, cancellationToken); + await HandleOutgoingEvent(@event); var result = new List(); - - cancellationToken.ThrowIfCancellationRequested(); - + try { var packets = Collection.Service.ResolvePacketByEvent(@event); foreach (var packet in packets) { - var returnVal = await Collection.Packet.SendPacket(packet, cancellationToken); + var returnVal = await Collection.Packet.SendPacket(packet); var resolved = Collection.Service.ResolveEventByPacket(returnVal); foreach (var protocol in resolved) { - await HandleIncomingEvent(protocol, cancellationToken); + await HandleIncomingEvent(protocol); result.Add(protocol); } } } - catch (TaskCanceledException) - { - // if task is cancelled, we should throw the exception - throw; - } catch (Exception e) { Collection.Log.LogWarning(Tag, $"Error when processing the event: {@event}"); @@ -130,7 +119,7 @@ public async Task> SendEvent(ProtocolEvent @event, Cancellat return result; } - public async Task HandleIncomingEvent(ProtocolEvent @event, CancellationToken cancellationToken) + public async Task HandleIncomingEvent(ProtocolEvent @event) { _businessLogics.TryGetValue(typeof(ProtocolEvent), out var baseLogics); _businessLogics.TryGetValue(@event.GetType(), out var normalLogics); @@ -143,12 +132,7 @@ public async Task HandleIncomingEvent(ProtocolEvent @event, CancellationTo { try { - await logic.Incoming(@event, cancellationToken); - } - catch (TaskCanceledException) - { - // if task is cancelled, we should throw the exception - throw; + await logic.Incoming(@event); } catch (Exception e) { @@ -161,7 +145,7 @@ public async Task HandleIncomingEvent(ProtocolEvent @event, CancellationTo return true; } - public async Task HandleOutgoingEvent(ProtocolEvent @event, CancellationToken cancellationToken) + public async Task HandleOutgoingEvent(ProtocolEvent @event) { _businessLogics.TryGetValue(typeof(ProtocolEvent), out var baseLogics); _businessLogics.TryGetValue(@event.GetType(), out var normalLogics); @@ -174,12 +158,7 @@ public async Task HandleOutgoingEvent(ProtocolEvent @event, CancellationTo { try { - await logic.Outgoing(@event, cancellationToken); - } - catch (TaskCanceledException) - { - // if task is cancelled, we should throw the exception - throw; + await logic.Outgoing(@event); } catch (Exception e) { @@ -204,7 +183,7 @@ public async Task HandleServerPacket(SsoPacket packet) var events = Collection.Service.ResolveEventByPacket(packet); foreach (var @event in events) { - var isSuccessful = await Collection.Business.HandleIncomingEvent(@event, CancellationToken.None); + var isSuccessful = await Collection.Business.HandleIncomingEvent(@event); if (!isSuccessful) break; success = true; @@ -220,4 +199,4 @@ public async Task HandleServerPacket(SsoPacket packet) return success; } -} +} \ No newline at end of file diff --git a/Lagrange.Core/Internal/Context/HighwayContext.cs b/Lagrange.Core/Internal/Context/HighwayContext.cs index 01a3bdfd0..8f7789b50 100644 --- a/Lagrange.Core/Internal/Context/HighwayContext.cs +++ b/Lagrange.Core/Internal/Context/HighwayContext.cs @@ -57,7 +57,7 @@ public HighwayContext(ContextCollection collection, BotKeystore keystore, BotApp _concurrent = config.HighwayConcurrent; } - public async Task UploadResources(MessageChain chain, CancellationToken cancellationToken = default) + public async Task UploadResources(MessageChain chain) { foreach (var entity in chain) { @@ -65,8 +65,8 @@ public async Task UploadResources(MessageChain chain, CancellationToken cancella { try { - if (chain.IsGroup) await uploader.UploadGroup(Collection, chain, entity, cancellationToken); - else await uploader.UploadPrivate(Collection, chain, entity, cancellationToken); + if (chain.IsGroup) await uploader.UploadGroup(Collection, chain, entity); + else await uploader.UploadPrivate(Collection, chain, entity); } catch { @@ -76,7 +76,7 @@ public async Task UploadResources(MessageChain chain, CancellationToken cancella } } - public async Task ManualUploadEntity(IMessageEntity entity, CancellationToken cancellationToken = default) + public async Task ManualUploadEntity(IMessageEntity entity) { if (_uploaders.TryGetValue(entity.GetType(), out var uploader)) { @@ -86,7 +86,7 @@ public async Task ManualUploadEntity(IMessageEntity entity, CancellationToken ca string uid = Collection.Keystore.Uid ?? ""; var chain = new MessageChain(uin, uid, uid) { entity }; - await uploader.UploadPrivate(Collection, chain, entity, cancellationToken); + await uploader.UploadPrivate(Collection, chain, entity); } catch { @@ -95,11 +95,11 @@ public async Task ManualUploadEntity(IMessageEntity entity, CancellationToken ca } } - public async Task UploadSrcByStreamAsync(int commonId, Stream data, byte[] ticket, byte[] md5, byte[]? extendInfo = null, CancellationToken cancellation = default) + public async Task UploadSrcByStreamAsync(int commonId, Stream data, byte[] ticket, byte[] md5, byte[]? extendInfo = null) { if (_uri == null) { - var highwayUrlEvent = await Collection.Business.SendEvent(HighwayUrlEvent.Create(), cancellation); + var highwayUrlEvent = await Collection.Business.SendEvent(HighwayUrlEvent.Create()); var result = (HighwayUrlEvent)highwayUrlEvent[0]; _uri = result.HighwayUrls[1][0]; } @@ -114,7 +114,7 @@ public async Task UploadSrcByStreamAsync(int commonId, Stream data, byte[] while (offset < fileSize) { var buffer = new byte[Math.Min(_chunkSize, fileSize - offset)]; - int payload = await data.ReadAsync(buffer.AsMemory(), cancellation); + int payload = await data.ReadAsync(buffer.AsMemory()); uint uin = Collection.Keystore.Uin; uint sequence = Interlocked.Increment(ref _sequence); var reqBody = new UpBlock(commonId, uin, sequence, (ulong)fileSize, (ulong)offset, ticket, md5, buffer, extendInfo); @@ -123,7 +123,7 @@ public async Task UploadSrcByStreamAsync(int commonId, Stream data, byte[] if (upBlocks.Count >= _concurrent || data.Position == data.Length) { - var tasks = upBlocks.Select(x => SendUpBlockAsync(x, _uri, cancellation)).ToArray(); + var tasks = upBlocks.Select(x => SendUpBlockAsync(x, _uri)).ToArray(); var results = await Task.WhenAll(tasks); success &= results.All(x => x); @@ -134,7 +134,7 @@ public async Task UploadSrcByStreamAsync(int commonId, Stream data, byte[] return success; } - private async Task SendUpBlockAsync(UpBlock upBlock, Uri server, CancellationToken cancellation = default) + private async Task SendUpBlockAsync(UpBlock upBlock, Uri server) { var head = new DataHighwayHead { @@ -171,7 +171,7 @@ private async Task SendUpBlockAsync(UpBlock upBlock, Uri server, Cancellat }; bool isEnd = upBlock.Offset + (ulong)upBlock.Block.Length == upBlock.FileSize; - var payload = await SendPacketAsync(highwayHead, new BinaryPacket(upBlock.Block), server, end: isEnd, cancellation: cancellation); + var payload = await SendPacketAsync(highwayHead, new BinaryPacket(upBlock.Block), server, isEnd); var (respHead, resp) = ParsePacket(payload); Collection.Log.LogDebug(Tag, $"Highway Block Result: {respHead.ErrorCode} | {respHead.MsgSegHead?.RetCode} | {respHead.BytesRspExtendInfo?.Hex()} | {resp.ToArray().Hex()}"); @@ -179,7 +179,7 @@ private async Task SendUpBlockAsync(UpBlock upBlock, Uri server, Cancellat return respHead.ErrorCode == 0; } - private Task SendPacketAsync(ReqDataHighwayHead head, BinaryPacket buffer, Uri server, bool end = true, CancellationToken cancellation = default) + private Task SendPacketAsync(ReqDataHighwayHead head, BinaryPacket buffer, Uri server, bool end = true) { using var stream = new MemoryStream(); Serializer.Serialize(stream, head); @@ -192,7 +192,7 @@ private Task SendPacketAsync(ReqDataHighwayHead head, BinaryPacket .WritePacket(buffer) .WriteByte(0x29); // packet end - return SendDataAsync(writer.ToArray(), server, end, cancellation); + return SendDataAsync(writer.ToArray(), server, end); } private static (RespDataHighwayHead, BinaryPacket) ParsePacket(BinaryPacket packet) @@ -210,7 +210,7 @@ private static (RespDataHighwayHead, BinaryPacket) ParsePacket(BinaryPacket pack throw new InvalidOperationException("Invalid packet"); } - private async Task SendDataAsync(byte[] packet, Uri server, bool end, CancellationToken cancellation) + private async Task SendDataAsync(byte[] packet, Uri server, bool end) { var content = new ByteArrayContent(packet); var request = new HttpRequestMessage(HttpMethod.Post, server) @@ -221,8 +221,8 @@ private async Task SendDataAsync(byte[] packet, Uri server, bool e { "Connection" , end ? "close" : "keep-alive" }, } }; - var response = await _client.SendAsync(request, cancellation); - var data = await response.Content.ReadAsByteArrayAsync(cancellation); + var response = await _client.SendAsync(request); + var data = await response.Content.ReadAsByteArrayAsync(); return new BinaryPacket(data); } @@ -242,4 +242,4 @@ public void Dispose() { _client.Dispose(); } -} +} \ No newline at end of file diff --git a/Lagrange.Core/Internal/Context/Logic/Implementation/CachingLogic.cs b/Lagrange.Core/Internal/Context/Logic/Implementation/CachingLogic.cs index 667aa196c..645946768 100644 --- a/Lagrange.Core/Internal/Context/Logic/Implementation/CachingLogic.cs +++ b/Lagrange.Core/Internal/Context/Logic/Implementation/CachingLogic.cs @@ -37,25 +37,25 @@ internal CachingLogic(ContextCollection collection) : base(collection) _cacheUsers = new ConcurrentDictionary(); } - public override Task Incoming(ProtocolEvent e, CancellationToken cancellationToken) + public override Task Incoming(ProtocolEvent e) { return e switch { - GroupSysDecreaseEvent groupSysDecreaseEvent when groupSysDecreaseEvent.MemberUid != Collection.Keystore.Uid => CacheUid(groupSysDecreaseEvent.GroupUin, force: true, cancellationToken: cancellationToken), - GroupSysIncreaseEvent groupSysIncreaseEvent => CacheUid(groupSysIncreaseEvent.GroupUin, force: true, cancellationToken: cancellationToken), - GroupSysAdminEvent groupSysAdminEvent => CacheUid(groupSysAdminEvent.GroupUin, force: true, cancellationToken: cancellationToken), + GroupSysDecreaseEvent groupSysDecreaseEvent when groupSysDecreaseEvent.MemberUid != Collection.Keystore.Uid => CacheUid(groupSysDecreaseEvent.GroupUin, true), + GroupSysIncreaseEvent groupSysIncreaseEvent => CacheUid(groupSysIncreaseEvent.GroupUin, true), + GroupSysAdminEvent groupSysAdminEvent => CacheUid(groupSysAdminEvent.GroupUin, true), _ => Task.CompletedTask, }; } - public async Task> GetCachedGroups(bool refreshCache, CancellationToken cancellationToken) + public async Task> GetCachedGroups(bool refreshCache) { if (_cachedGroupEntities.Count == 0 || refreshCache) { _cachedGroupEntities.Clear(); var fetchGroupsEvent = FetchGroupsEvent.Create(); - var events = await Collection.Business.SendEvent(fetchGroupsEvent, cancellationToken); + var events = await Collection.Business.SendEvent(fetchGroupsEvent); var groups = ((FetchGroupsEvent)events[0]).Groups; _cachedGroupEntities.AddRange(groups); @@ -65,60 +65,60 @@ public async Task> GetCachedGroups(bool refreshCache, Cancellatio return _cachedGroupEntities; } - public async Task ResolveUid(uint? groupUin, uint friendUin, CancellationToken cancellationToken) + public async Task ResolveUid(uint? groupUin, uint friendUin) { - if (_uinToUid.Count == 0) await ResolveFriendsUidAndFriendGroups(cancellationToken); + if (_uinToUid.Count == 0) await ResolveFriendsUidAndFriendGroups(); if (groupUin == null) return _uinToUid.GetValueOrDefault(friendUin); - await CacheUid(groupUin.Value, false, cancellationToken); + await CacheUid(groupUin.Value); return _uinToUid.GetValueOrDefault(friendUin); } - public async Task ResolveUin(uint? groupUin, string friendUid, bool force = false, CancellationToken cancellationToken = default) + public async Task ResolveUin(uint? groupUin, string friendUid, bool force = false) { - if (_uinToUid.Count == 0) await ResolveFriendsUidAndFriendGroups(cancellationToken); + if (_uinToUid.Count == 0) await ResolveFriendsUidAndFriendGroups(); if (groupUin == null) return _uinToUid.FirstOrDefault(x => x.Value == friendUid).Key; - await CacheUid(groupUin.Value, force: force, cancellationToken: cancellationToken); + await CacheUid(groupUin.Value, force); return _uinToUid.FirstOrDefault(x => x.Value == friendUid).Key; } - public async Task> GetCachedMembers(uint groupUin, bool refreshCache, CancellationToken cancellationToken = default) + public async Task> GetCachedMembers(uint groupUin, bool refreshCache) { if (!_cachedGroupMembers.TryGetValue(groupUin, out var members) || refreshCache) { - await ResolveMembersUid(groupUin, cancellationToken); + await ResolveMembersUid(groupUin); return _cachedGroupMembers.TryGetValue(groupUin, out members) ? members : new List(); } return members; } - public async Task> GetCachedFriends(bool refreshCache, CancellationToken cancellationToken) + public async Task> GetCachedFriends(bool refreshCache) { - if (_cachedFriends.Count == 0 || refreshCache) await ResolveFriendsUidAndFriendGroups(cancellationToken); + if (_cachedFriends.Count == 0 || refreshCache) await ResolveFriendsUidAndFriendGroups(); return _cachedFriends; } - public async Task GetCachedUsers(uint uin, bool refreshCache, CancellationToken cancellationToken) + public async Task GetCachedUsers(uint uin, bool refreshCache) { - if (!_cacheUsers.ContainsKey(uin) || refreshCache) await ResolveUser(uin, cancellationToken); + if (!_cacheUsers.ContainsKey(uin) || refreshCache) await ResolveUser(uin); if (!_cacheUsers.TryGetValue(uin, out BotUserInfo? info)) return null; return info; } - private async Task CacheUid(uint groupUin, bool force, CancellationToken cancellationToken) + private async Task CacheUid(uint groupUin, bool force = false) { if (!_cachedGroups.Contains(groupUin) || force) { Collection.Log.LogVerbose(Tag, $"Caching group members: {groupUin}"); - await ResolveMembersUid(groupUin, cancellationToken); + await ResolveMembersUid(groupUin); _cachedGroups.Add(groupUin); } } - private async Task ResolveFriendsUidAndFriendGroups(CancellationToken cancellationToken) + private async Task ResolveFriendsUidAndFriendGroups() { uint? next = null; var friends = new List(); @@ -126,7 +126,7 @@ private async Task ResolveFriendsUidAndFriendGroups(CancellationToken cancellati do { var @event = FetchFriendsEvent.Create(next); - var results = await Collection.Business.SendEvent(@event, cancellationToken); + var results = await Collection.Business.SendEvent(@event); if (results.Count == 0) { @@ -153,10 +153,10 @@ private async Task ResolveFriendsUidAndFriendGroups(CancellationToken cancellati _cachedFriends.AddRange(friends); } - private async Task ResolveMembersUid(uint groupUin, CancellationToken cancellationToken) + private async Task ResolveMembersUid(uint groupUin) { var fetchFriendsEvent = FetchMembersEvent.Create(groupUin); - var events = await Collection.Business.SendEvent(fetchFriendsEvent, cancellationToken); + var events = await Collection.Business.SendEvent(fetchFriendsEvent); if (events.Count != 0) { @@ -166,7 +166,7 @@ private async Task ResolveMembersUid(uint groupUin, CancellationToken cancellati while (token != null) { var next = FetchMembersEvent.Create(groupUin, token); - var results = await Collection.Business.SendEvent(next, cancellationToken); + var results = await Collection.Business.SendEvent(next); @event.Members.AddRange(((FetchMembersEvent)results[0]).Members); token = ((FetchMembersEvent)results[0]).Token; } @@ -181,13 +181,13 @@ private async Task ResolveMembersUid(uint groupUin, CancellationToken cancellati } } - private async Task ResolveUser(uint uin, CancellationToken cancellationToken) + private async Task ResolveUser(uint uin) { - var events = await Collection.Business.SendEvent(FetchUserInfoEvent.Create(uin), cancellationToken); + var events = await Collection.Business.SendEvent(FetchUserInfoEvent.Create(uin)); if (events.Count != 0 && events[0] is FetchUserInfoEvent { } @event) { _cacheUsers.AddOrUpdate(uin, @event.UserInfo, (_key, _value) => @event.UserInfo); } } -} +} \ No newline at end of file diff --git a/Lagrange.Core/Internal/Context/Logic/Implementation/MessagingLogic.cs b/Lagrange.Core/Internal/Context/Logic/Implementation/MessagingLogic.cs index 19cbc47db..9da1c8f2c 100644 --- a/Lagrange.Core/Internal/Context/Logic/Implementation/MessagingLogic.cs +++ b/Lagrange.Core/Internal/Context/Logic/Implementation/MessagingLogic.cs @@ -46,15 +46,15 @@ internal class MessagingLogic : LogicBase internal MessagingLogic(ContextCollection collection) : base(collection) { } - public override async Task Incoming(ProtocolEvent e, CancellationToken cancellationToken) + public override async Task Incoming(ProtocolEvent e) { switch (e) { case PushMessageEvent push: { if (push.Chain.Count == 0) return; - await ResolveIncomingChain(push.Chain, cancellationToken); - await ResolveChainMetadata(push.Chain, cancellationToken); + await ResolveIncomingChain(push.Chain); + await ResolveChainMetadata(push.Chain); MessageFilter.Filter(push.Chain); var chain = push.Chain; @@ -76,8 +76,8 @@ public override async Task Incoming(ProtocolEvent e, CancellationToken cancellat foreach (var chain in get.Chains) { if (chain.Count == 0) return; - await ResolveIncomingChain(chain, cancellationToken); - await ResolveChainMetadata(chain, cancellationToken); + await ResolveIncomingChain(chain); + await ResolveChainMetadata(chain); MessageFilter.Filter(chain); } break; @@ -87,40 +87,40 @@ public override async Task Incoming(ProtocolEvent e, CancellationToken cancellat foreach (var chain in get.Chains) { if (chain.Count == 0) return; - await ResolveIncomingChain(chain, cancellationToken); - await ResolveChainMetadata(chain, cancellationToken); + await ResolveIncomingChain(chain); + await ResolveChainMetadata(chain); MessageFilter.Filter(chain); } break; } case GroupSysInviteEvent invite: { - uint invitorUin = await Collection.Business.CachingLogic.ResolveUin(null, invite.InvitorUid, false, cancellationToken) ?? 0; + uint invitorUin = await Collection.Business.CachingLogic.ResolveUin(null, invite.InvitorUid) ?? 0; var inviteArgs = new GroupInvitationEvent(invite.GroupUin, invitorUin); Collection.Invoker.PostEvent(inviteArgs); break; } case GroupSysAdminEvent admin: { - uint adminUin = await Collection.Business.CachingLogic.ResolveUin(admin.GroupUin, admin.Uid, false, cancellationToken) ?? 0; + uint adminUin = await Collection.Business.CachingLogic.ResolveUin(admin.GroupUin, admin.Uid) ?? 0; var adminArgs = new GroupAdminChangedEvent(admin.GroupUin, adminUin, admin.IsPromoted); Collection.Invoker.PostEvent(adminArgs); break; } case GroupSysIncreaseEvent increase: { - uint memberUin = await Collection.Business.CachingLogic.ResolveUin(increase.GroupUin, increase.MemberUid, true, cancellationToken) ?? 0; + uint memberUin = await Collection.Business.CachingLogic.ResolveUin(increase.GroupUin, increase.MemberUid, true) ?? 0; uint? invitorUin = null; - if (increase.InvitorUid != null) invitorUin = await Collection.Business.CachingLogic.ResolveUin(increase.GroupUin, increase.InvitorUid, false, cancellationToken); + if (increase.InvitorUid != null) invitorUin = await Collection.Business.CachingLogic.ResolveUin(increase.GroupUin, increase.InvitorUid); var increaseArgs = new GroupMemberIncreaseEvent(increase.GroupUin, memberUin, invitorUin, increase.Type); Collection.Invoker.PostEvent(increaseArgs); break; } case GroupSysDecreaseEvent decrease: { - uint memberUin = await Collection.Business.CachingLogic.ResolveUin(decrease.GroupUin, decrease.MemberUid, false, cancellationToken) ?? 0; + uint memberUin = await Collection.Business.CachingLogic.ResolveUin(decrease.GroupUin, decrease.MemberUid) ?? 0; uint? operatorUin = null; - if (decrease.OperatorUid != null) operatorUin = await Collection.Business.CachingLogic.ResolveUin(decrease.GroupUin, decrease.OperatorUid, false, cancellationToken); + if (decrease.OperatorUid != null) operatorUin = await Collection.Business.CachingLogic.ResolveUin(decrease.GroupUin, decrease.OperatorUid); var decreaseArgs = new GroupMemberDecreaseEvent(decrease.GroupUin, memberUin, operatorUin, decrease.Type); Collection.Invoker.PostEvent(decreaseArgs); break; @@ -139,7 +139,7 @@ public override async Task Incoming(ProtocolEvent e, CancellationToken cancellat } case GroupSysReactionEvent reaction: { - uint operatorUin = await Collection.Business.CachingLogic.ResolveUin(reaction.TargetGroupUin, reaction.OperatorUid, false, cancellationToken) ?? 0; + uint operatorUin = await Collection.Business.CachingLogic.ResolveUin(reaction.TargetGroupUin, reaction.OperatorUid) ?? 0; var pokeArgs = new GroupReactionEvent(reaction.TargetGroupUin, reaction.TargetSequence, operatorUin, reaction.IsAdd, reaction.Code, reaction.Count); Collection.Invoker.PostEvent(pokeArgs); break; @@ -159,25 +159,25 @@ public override async Task Incoming(ProtocolEvent e, CancellationToken cancellat case GroupSysMuteEvent groupMute: { uint? operatorUin = null; - if (groupMute.OperatorUid != null) operatorUin = await Collection.Business.CachingLogic.ResolveUin(groupMute.GroupUin, groupMute.OperatorUid, false, cancellationToken); + if (groupMute.OperatorUid != null) operatorUin = await Collection.Business.CachingLogic.ResolveUin(groupMute.GroupUin, groupMute.OperatorUid); var muteArgs = new GroupMuteEvent(groupMute.GroupUin, operatorUin, groupMute.IsMuted); Collection.Invoker.PostEvent(muteArgs); break; } case GroupSysMemberMuteEvent memberMute: { - uint memberUin = await Collection.Business.CachingLogic.ResolveUin(memberMute.GroupUin, memberMute.TargetUid, false, cancellationToken) ?? 0; + uint memberUin = await Collection.Business.CachingLogic.ResolveUin(memberMute.GroupUin, memberMute.TargetUid) ?? 0; uint? operatorUin = null; - if (memberMute.OperatorUid != null) operatorUin = await Collection.Business.CachingLogic.ResolveUin(memberMute.GroupUin, memberMute.OperatorUid, false, cancellationToken); + if (memberMute.OperatorUid != null) operatorUin = await Collection.Business.CachingLogic.ResolveUin(memberMute.GroupUin, memberMute.OperatorUid); var muteArgs = new GroupMemberMuteEvent(memberMute.GroupUin, memberUin, operatorUin, memberMute.Duration); Collection.Invoker.PostEvent(muteArgs); break; } case GroupSysRecallEvent recall: { - uint authorUin = await Collection.Business.CachingLogic.ResolveUin(recall.GroupUin, recall.AuthorUid, false, cancellationToken) ?? 0; + uint authorUin = await Collection.Business.CachingLogic.ResolveUin(recall.GroupUin, recall.AuthorUid) ?? 0; uint operatorUin = 0; - if (recall.OperatorUid != null) operatorUin = await Collection.Business.CachingLogic.ResolveUin(recall.GroupUin, recall.OperatorUid, false, cancellationToken) ?? 0; + if (recall.OperatorUid != null) operatorUin = await Collection.Business.CachingLogic.ResolveUin(recall.GroupUin, recall.OperatorUid) ?? 0; var recallArgs = new GroupRecallEvent(recall.GroupUin, authorUin, operatorUin, recall.Sequence, recall.Time, recall.Random, recall.Tip); Collection.Invoker.PostEvent(recallArgs); break; @@ -185,7 +185,7 @@ public override async Task Incoming(ProtocolEvent e, CancellationToken cancellat case GroupSysRequestJoinEvent join: { var fetchUidEvent = FetchUserInfoEvent.Create(join.TargetUid); - var results = await Collection.Business.SendEvent(fetchUidEvent, cancellationToken); + var results = await Collection.Business.SendEvent(fetchUidEvent); uint targetUin = results.Count == 0 ? 0 : ((FetchUserInfoEvent)results[0]).UserInfo.Uin; var joinArgs = new GroupJoinRequestEvent(join.GroupUin, targetUin); @@ -194,10 +194,10 @@ public override async Task Incoming(ProtocolEvent e, CancellationToken cancellat } case GroupSysRequestInvitationEvent invitation: { - uint invitorUin = await Collection.Business.CachingLogic.ResolveUin(invitation.GroupUin, invitation.InvitorUid, false, cancellationToken) ?? 0; + uint invitorUin = await Collection.Business.CachingLogic.ResolveUin(invitation.GroupUin, invitation.InvitorUid) ?? 0; var fetchUidEvent = FetchUserInfoEvent.Create(invitation.TargetUid); - var results = await Collection.Business.SendEvent(fetchUidEvent, cancellationToken); + var results = await Collection.Business.SendEvent(fetchUidEvent); uint targetUin = results.Count == 0 ? 0 : ((FetchUserInfoEvent)results[0]).UserInfo.Uin; var invitationArgs = new GroupInvitationRequestEvent(invitation.GroupUin, targetUin, invitorUin); @@ -206,7 +206,7 @@ public override async Task Incoming(ProtocolEvent e, CancellationToken cancellat } case FriendSysRecallEvent recall: { - uint fromUin = await Collection.Business.CachingLogic.ResolveUin(null, recall.FromUid, false, cancellationToken) ?? 0; + uint fromUin = await Collection.Business.CachingLogic.ResolveUin(null, recall.FromUid) ?? 0; var recallArgs = new FriendRecallEvent(fromUin, recall.ClientSequence, recall.Time, recall.Random, recall.Tip); Collection.Invoker.PostEvent(recallArgs); break; @@ -230,7 +230,7 @@ public override async Task Incoming(ProtocolEvent e, CancellationToken cancellat foreach (var chain in multi.Chains) { if (chain.Count == 0) continue; - await ResolveIncomingChain(chain, cancellationToken); + await ResolveIncomingChain(chain); MessageFilter.Filter(chain); } } @@ -238,7 +238,7 @@ public override async Task Incoming(ProtocolEvent e, CancellationToken cancellat } case GroupSysTodoEvent todo: { - uint uin = await Collection.Business.CachingLogic.ResolveUin(todo.GroupUin, todo.OperatorUid, false, cancellationToken) ?? 0; + uint uin = await Collection.Business.CachingLogic.ResolveUin(todo.GroupUin, todo.OperatorUid) ?? 0; Collection.Invoker.PostEvent(new GroupTodoEvent(todo.GroupUin, uin)); break; @@ -246,7 +246,7 @@ public override async Task Incoming(ProtocolEvent e, CancellationToken cancellat } } - public override async Task Outgoing(ProtocolEvent e, CancellationToken cancellationToken) + public override async Task Outgoing(ProtocolEvent e) { switch (e) { @@ -254,23 +254,23 @@ public override async Task Outgoing(ProtocolEvent e, CancellationToken cancellat { foreach (var chain in chains) { - await ResolveChainMetadata(chain, cancellationToken); - await ResolveOutgoingChain(chain, cancellationToken); - await Collection.Highway.UploadResources(chain, cancellationToken); + await ResolveChainMetadata(chain); + await ResolveOutgoingChain(chain); + await Collection.Highway.UploadResources(chain); } break; } case SendMessageEvent send: // resolve Uin to Uid { - await ResolveChainMetadata(send.Chain, cancellationToken); - await ResolveOutgoingChain(send.Chain, cancellationToken); - await Collection.Highway.UploadResources(send.Chain, cancellationToken); + await ResolveChainMetadata(send.Chain); + await ResolveOutgoingChain(send.Chain); + await Collection.Highway.UploadResources(send.Chain); break; } } } - private async Task ResolveIncomingChain(MessageChain chain, CancellationToken cancellationToken) + private async Task ResolveIncomingChain(MessageChain chain) { foreach (var entity in chain) { @@ -279,7 +279,7 @@ private async Task ResolveIncomingChain(MessageChain chain, CancellationToken ca case FileEntity { FileHash: not null, FileUuid: not null } file: // private { var @event = FileDownloadEvent.Create(file.FileUuid, file.FileHash, chain.Uid, chain.SelfUid); - var results = await Collection.Business.SendEvent(@event, cancellationToken); + var results = await Collection.Business.SendEvent(@event); if (results.Count != 0) { var result = (FileDownloadEvent)results[0]; @@ -291,7 +291,7 @@ private async Task ResolveIncomingChain(MessageChain chain, CancellationToken ca case FileEntity { FileId: not null } file when chain.GroupUin is not null: // group { var @event = GroupFSDownloadEvent.Create(chain.GroupUin.Value, file.FileId); - var results = await Collection.Business.SendEvent(@event, cancellationToken); + var results = await Collection.Business.SendEvent(@event); if (results.Count != 0) { var result = (GroupFSDownloadEvent)results[0]; @@ -303,7 +303,7 @@ private async Task ResolveIncomingChain(MessageChain chain, CancellationToken ca case MultiMsgEntity { ResId: not null } multi: { var @event = MultiMsgDownloadEvent.Create(chain.Uid ?? "", multi.ResId); - var results = await Collection.Business.SendEvent(@event, cancellationToken); + var results = await Collection.Business.SendEvent(@event); if (results.Count != 0) { var result = (MultiMsgDownloadEvent)results[0]; @@ -318,7 +318,7 @@ private async Task ResolveIncomingChain(MessageChain chain, CancellationToken ca ? RecordGroupDownloadEvent.Create(chain.GroupUin ?? 0, record.MsgInfo) : RecordDownloadEvent.Create(chain.Uid ?? string.Empty, record.MsgInfo); - var results = await Collection.Business.SendEvent(@event, cancellationToken); + var results = await Collection.Business.SendEvent(@event); if (results.Count != 0) { var result = (RecordDownloadEvent)results[0]; @@ -333,7 +333,7 @@ private async Task ResolveIncomingChain(MessageChain chain, CancellationToken ca ? RecordGroupDownloadEvent.Create(chain.GroupUin ?? 0, record.AudioUuid) : RecordDownloadEvent.Create(chain.Uid ?? string.Empty, record.AudioUuid); - var results = await Collection.Business.SendEvent(@event, cancellationToken); + var results = await Collection.Business.SendEvent(@event); if (results.Count != 0) { var result = (RecordDownloadEvent)results[0]; @@ -345,10 +345,10 @@ private async Task ResolveIncomingChain(MessageChain chain, CancellationToken ca case VideoEntity { VideoUuid: not null } video: { string uid = (chain.IsGroup - ? await Collection.Business.CachingLogic.ResolveUid(chain.GroupUin, chain.FriendUin, cancellationToken) + ? await Collection.Business.CachingLogic.ResolveUid(chain.GroupUin, chain.FriendUin) : chain.Uid) ?? ""; var @event = VideoDownloadEvent.Create(video.VideoUuid, uid, video.FilePath, "", "", chain.IsGroup); - var results = await Collection.Business.SendEvent(@event, cancellationToken); + var results = await Collection.Business.SendEvent(@event); if (results.Count != 0) { var result = (VideoDownloadEvent)results[0]; @@ -363,7 +363,7 @@ private async Task ResolveIncomingChain(MessageChain chain, CancellationToken ca ? ImageGroupDownloadEvent.Create(image.GroupUin ?? 0, image.MsgInfo) : ImageDownloadEvent.Create(image.FriendUid ?? string.Empty, image.MsgInfo); - var results = await Collection.Business.SendEvent(@event, cancellationToken); + var results = await Collection.Business.SendEvent(@event); if (results.Count != 0) { var result = (ImageDownloadEvent)results[0]; @@ -376,7 +376,7 @@ private async Task ResolveIncomingChain(MessageChain chain, CancellationToken ca } } - private async Task ResolveOutgoingChain(MessageChain chain, CancellationToken cancellationToken) + private async Task ResolveOutgoingChain(MessageChain chain) { foreach (var entity in chain) { @@ -385,24 +385,24 @@ private async Task ResolveOutgoingChain(MessageChain chain, CancellationToken ca case ForwardEntity forward when forward.TargetUin != 0: { var cache = Collection.Business.CachingLogic; - forward.Uid = await cache.ResolveUid(chain.GroupUin, forward.TargetUin, cancellationToken) ?? throw new Exception($"Failed to resolve Uid for Uin {forward.TargetUin}"); + forward.Uid = await cache.ResolveUid(chain.GroupUin, forward.TargetUin) ?? throw new Exception($"Failed to resolve Uid for Uin {forward.TargetUin}"); break; } case MentionEntity mention when mention.Uin != 0: { var cache = Collection.Business.CachingLogic; - mention.Uid = await cache.ResolveUid(chain.GroupUin, mention.Uin, cancellationToken) ?? throw new Exception($"Failed to resolve Uid for Uin {mention.Uin}"); + mention.Uid = await cache.ResolveUid(chain.GroupUin, mention.Uin) ?? throw new Exception($"Failed to resolve Uid for Uin {mention.Uin}"); if (chain is { IsGroup: true, GroupUin: not null } && mention.Name is null) { - var members = await Collection.Business.CachingLogic.GetCachedMembers(chain.GroupUin.Value, false, cancellationToken); + var members = await Collection.Business.CachingLogic.GetCachedMembers(chain.GroupUin.Value, false); var member = members.FirstOrDefault(x => x.Uin == mention.Uin); if (member != null) mention.Name = $"@{member.MemberCard ?? member.MemberName}"; } else if (chain is { IsGroup: false } && mention.Name is null) { - var friends = await Collection.Business.CachingLogic.GetCachedFriends(false, cancellationToken); + var friends = await Collection.Business.CachingLogic.GetCachedFriends(false); string? friend = friends.FirstOrDefault(x => x.Uin == mention.Uin)?.Nickname; if (friend != null) mention.Name = $"@{friend}"; } @@ -414,7 +414,7 @@ private async Task ResolveOutgoingChain(MessageChain chain, CancellationToken ca if (chain.GroupUin != null) foreach (var c in multiMsg.Chains) c.GroupUin = chain.GroupUin; var multiMsgEvent = MultiMsgUploadEvent.Create(chain.GroupUin, multiMsg.Chains); - var results = await Collection.Business.SendEvent(multiMsgEvent, cancellationToken); + var results = await Collection.Business.SendEvent(multiMsgEvent); if (results.Count != 0) { var result = (MultiMsgUploadEvent)results[0]; @@ -425,7 +425,7 @@ private async Task ResolveOutgoingChain(MessageChain chain, CancellationToken ca case MultiMsgEntity { ResId: not null, Chains.Count: 0 } multiMsg: { var @event = MultiMsgDownloadEvent.Create(chain.Uid ?? "", multiMsg.ResId); - var results = await Collection.Business.SendEvent(@event, cancellationToken); + var results = await Collection.Business.SendEvent(@event); if (results.Count != 0) { var result = (MultiMsgDownloadEvent)results[0]; @@ -442,11 +442,11 @@ private async Task ResolveOutgoingChain(MessageChain chain, CancellationToken ca /// for both Incoming and Outgoing MessageChain /// /// The target chain - private async Task ResolveChainMetadata(MessageChain chain, CancellationToken cancellationToken) + private async Task ResolveChainMetadata(MessageChain chain) { if (chain is { IsGroup: true, GroupUin: not null }) { - var groups = await Collection.Business.CachingLogic.GetCachedMembers(chain.GroupUin.Value, false, cancellationToken); + var groups = await Collection.Business.CachingLogic.GetCachedMembers(chain.GroupUin.Value, false); chain.GroupMemberInfo = chain.FriendUin == 0 ? groups.FirstOrDefault(x => x.Uin == Collection.Keystore.Uin) : groups.FirstOrDefault(x => x.Uin == chain.FriendUin); @@ -455,7 +455,7 @@ private async Task ResolveChainMetadata(MessageChain chain, CancellationToken ca } else { - var friends = await Collection.Business.CachingLogic.GetCachedFriends(false, cancellationToken); + var friends = await Collection.Business.CachingLogic.GetCachedFriends(false); if (friends.FirstOrDefault(x => x.Uin == chain.FriendUin) is { } friend) { chain.FriendInfo = friend; diff --git a/Lagrange.Core/Internal/Context/Logic/Implementation/OperationLogic.cs b/Lagrange.Core/Internal/Context/Logic/Implementation/OperationLogic.cs index 5b182c060..fdf82a6aa 100644 --- a/Lagrange.Core/Internal/Context/Logic/Implementation/OperationLogic.cs +++ b/Lagrange.Core/Internal/Context/Logic/Implementation/OperationLogic.cs @@ -18,29 +18,29 @@ internal class OperationLogic : LogicBase internal OperationLogic(ContextCollection collection) : base(collection) { } - public async Task> GetCookies(List domains, CancellationToken cancellation) + public async Task> GetCookies(List domains) { var fetchCookieEvent = FetchCookieEvent.Create(domains); - var events = await Collection.Business.SendEvent(fetchCookieEvent, cancellation); + var events = await Collection.Business.SendEvent(fetchCookieEvent); return events.Count != 0 ? ((FetchCookieEvent)events[0]).Cookies : new List(); } - public Task> FetchFriends(bool refreshCache = false, CancellationToken cancellationToken = default) => - Collection.Business.CachingLogic.GetCachedFriends(refreshCache, cancellationToken); + public Task> FetchFriends(bool refreshCache = false) => + Collection.Business.CachingLogic.GetCachedFriends(refreshCache); - public Task> FetchMembers(uint groupUin, CancellationToken cancellationToken, bool refreshCache = false) => - Collection.Business.CachingLogic.GetCachedMembers(groupUin, refreshCache, cancellationToken); + public Task> FetchMembers(uint groupUin, bool refreshCache = false) => + Collection.Business.CachingLogic.GetCachedMembers(groupUin, refreshCache); - public Task> FetchGroups(bool refreshCache, CancellationToken cancellationToken) => - Collection.Business.CachingLogic.GetCachedGroups(refreshCache, cancellationToken); + public Task> FetchGroups(bool refreshCache) => + Collection.Business.CachingLogic.GetCachedGroups(refreshCache); - public async Task SendMessage(MessageChain chain, CancellationToken cancellation) + public async Task SendMessage(MessageChain chain) { uint clientSeq = chain.ClientSequence; ulong messageId = chain.MessageId; var sendMessageEvent = SendMessageEvent.Create(chain); - var events = await Collection.Business.SendEvent(sendMessageEvent, cancellation); + var events = await Collection.Business.SendEvent(sendMessageEvent); if (events.Count == 0) return new MessageResult { Result = 9057 }; var result = ((SendMessageEvent)events[0]).MsgResult; @@ -49,47 +49,47 @@ public async Task SendMessage(MessageChain chain, CancellationTok return result; } - public async Task MuteGroupMember(uint groupUin, uint targetUin, uint duration, CancellationToken cancellationToken) + public async Task MuteGroupMember(uint groupUin, uint targetUin, uint duration) { - string? uid = await Collection.Business.CachingLogic.ResolveUid(groupUin, targetUin, cancellationToken); + string? uid = await Collection.Business.CachingLogic.ResolveUid(groupUin, targetUin); if (uid == null) return false; var muteGroupMemberEvent = GroupMuteMemberEvent.Create(groupUin, duration, uid); - var events = await Collection.Business.SendEvent(muteGroupMemberEvent, cancellationToken); + var events = await Collection.Business.SendEvent(muteGroupMemberEvent); return events.Count != 0 && ((GroupMuteMemberEvent)events[0]).ResultCode == 0; } - public async Task MuteGroupGlobal(uint groupUin, bool isMute, CancellationToken cancellationToken) + public async Task MuteGroupGlobal(uint groupUin, bool isMute) { var muteGroupMemberEvent = GroupMuteGlobalEvent.Create(groupUin, isMute); - var events = await Collection.Business.SendEvent(muteGroupMemberEvent, cancellationToken); + var events = await Collection.Business.SendEvent(muteGroupMemberEvent); return events.Count != 0 && ((GroupMuteGlobalEvent)events[0]).ResultCode == 0; } - public async Task KickGroupMember(uint groupUin, uint targetUin, bool rejectAddRequest, string reason, CancellationToken cancellationToken) + public async Task KickGroupMember(uint groupUin, uint targetUin, bool rejectAddRequest, string reason) { - string? uid = await Collection.Business.CachingLogic.ResolveUid(groupUin, targetUin, cancellationToken); + string? uid = await Collection.Business.CachingLogic.ResolveUid(groupUin, targetUin); if (uid == null) return false; var muteGroupMemberEvent = GroupKickMemberEvent.Create(groupUin, uid, rejectAddRequest, reason); - var events = await Collection.Business.SendEvent(muteGroupMemberEvent, cancellationToken); + var events = await Collection.Business.SendEvent(muteGroupMemberEvent); return events.Count != 0 && ((GroupKickMemberEvent)events[0]).ResultCode == 0; } - public async Task SetGroupAdmin(uint groupUin, uint targetUin, bool isAdmin, CancellationToken cancellationToken) + public async Task SetGroupAdmin(uint groupUin, uint targetUin, bool isAdmin) { - string? uid = await Collection.Business.CachingLogic.ResolveUid(groupUin, targetUin, cancellationToken); + string? uid = await Collection.Business.CachingLogic.ResolveUid(groupUin, targetUin); if (uid == null) return false; var setGroupAdminEvent = GroupSetAdminEvent.Create(groupUin, uid, isAdmin); - var events = await Collection.Business.SendEvent(setGroupAdminEvent, cancellationToken); + var events = await Collection.Business.SendEvent(setGroupAdminEvent); return events.Count != 0 && ((GroupSetAdminEvent)events[0]).ResultCode == 0; } - public async Task<(int, string?)> SetGroupTodo(uint groupUin, uint sequence, CancellationToken cancellationToken) + public async Task<(int, string?)> SetGroupTodo(uint groupUin, uint sequence) { var setGroupTodoEvent = GroupSetTodoEvent.Create(groupUin, sequence); - var events = await Collection.Business.SendEvent(setGroupTodoEvent, cancellationToken); + var events = await Collection.Business.SendEvent(setGroupTodoEvent); if (events.Count == 0) return (-1, "No Events"); @@ -98,10 +98,10 @@ public async Task SetGroupAdmin(uint groupUin, uint targetUin, bool isAdmi return (@event.ResultCode, @event.ResultMessage); } - public async Task<(int, string?)> RemoveGroupTodo(uint groupUin, CancellationToken cancellationToken) + public async Task<(int, string?)> RemoveGroupTodo(uint groupUin) { var setGroupTodoEvent = GroupRemoveTodoEvent.Create(groupUin); - var events = await Collection.Business.SendEvent(setGroupTodoEvent, cancellationToken); + var events = await Collection.Business.SendEvent(setGroupTodoEvent); if (events.Count == 0) return (-1, "No Event"); @@ -110,10 +110,10 @@ public async Task SetGroupAdmin(uint groupUin, uint targetUin, bool isAdmi return (@event.ResultCode, @event.ResultMessage); } - public async Task<(int, string?)> FinishGroupTodo(uint groupUin, CancellationToken cancellationToken) + public async Task<(int, string?)> FinishGroupTodo(uint groupUin) { var setGroupTodoEvent = GroupFinishTodoEvent.Create(groupUin); - var events = await Collection.Business.SendEvent(setGroupTodoEvent, cancellationToken); + var events = await Collection.Business.SendEvent(setGroupTodoEvent); if (events.Count == 0) return (-1, "No Event"); @@ -122,10 +122,10 @@ public async Task SetGroupAdmin(uint groupUin, uint targetUin, bool isAdmi return (@event.ResultCode, @event.ResultMessage); } - public async Task GetGroupTodo(uint groupUin, CancellationToken cancellationToken) + public async Task GetGroupTodo(uint groupUin) { var setGroupTodoEvent = GroupGetTodoEvent.Create(groupUin); - var events = await Collection.Business.SendEvent(setGroupTodoEvent, cancellationToken); + var events = await Collection.Business.SendEvent(setGroupTodoEvent); if (events.Count == 0) return new(-1, "No Event", 0, 0, string.Empty); @@ -140,73 +140,73 @@ public async Task GetGroupTodo(uint groupUin, Cancellatio ); } - public async Task SetGroupBot(uint BotId, uint On, uint groupUin, CancellationToken cancellationToken) + public async Task SetGroupBot(uint BotId, uint On, uint groupUin) { var muteBotEvent = GroupSetBotEvent.Create(BotId, On, groupUin); - var events = await Collection.Business.SendEvent(muteBotEvent, cancellationToken); + var events = await Collection.Business.SendEvent(muteBotEvent); return events.Count != 0 && ((GroupSetBotEvent)events[0]).ResultCode == 0; } - public async Task SetGroupBotHD(uint BotId, uint groupUin, string? data_1, string? data_2, CancellationToken cancellationToken) + public async Task SetGroupBotHD(uint BotId, uint groupUin, string? data_1, string? data_2) { var muteBotEvent = GroupSetBothdEvent.Create(BotId, groupUin, data_1, data_2); - var events = await Collection.Business.SendEvent(muteBotEvent, cancellationToken); + var events = await Collection.Business.SendEvent(muteBotEvent); return events.Count != 0 && ((GroupSetBothdEvent)events[0]).ResultCode == 0; } - public async Task RenameGroupMember(uint groupUin, uint targetUin, string targetName, CancellationToken cancellationToken) + public async Task RenameGroupMember(uint groupUin, uint targetUin, string targetName) { - string? uid = await Collection.Business.CachingLogic.ResolveUid(groupUin, targetUin, cancellationToken); + string? uid = await Collection.Business.CachingLogic.ResolveUid(groupUin, targetUin); if (uid == null) return false; var renameGroupEvent = RenameMemberEvent.Create(groupUin, uid, targetName); - var events = await Collection.Business.SendEvent(renameGroupEvent, cancellationToken); + var events = await Collection.Business.SendEvent(renameGroupEvent); return events.Count != 0 && ((RenameMemberEvent)events[0]).ResultCode == 0; } - public async Task RenameGroup(uint groupUin, string targetName, CancellationToken cancellationToken) + public async Task RenameGroup(uint groupUin, string targetName) { var renameGroupEvent = GroupRenameEvent.Create(groupUin, targetName); - var events = await Collection.Business.SendEvent(renameGroupEvent, cancellationToken); + var events = await Collection.Business.SendEvent(renameGroupEvent); return events.Count != 0 && ((GroupRenameEvent)events[0]).ResultCode == 0; } - public async Task RemarkGroup(uint groupUin, string targetRemark, CancellationToken cancellationToken) + public async Task RemarkGroup(uint groupUin, string targetRemark) { var renameGroupEvent = GroupRemarkEvent.Create(groupUin, targetRemark); - var events = await Collection.Business.SendEvent(renameGroupEvent, cancellationToken); + var events = await Collection.Business.SendEvent(renameGroupEvent); return events.Count != 0 && ((GroupRemarkEvent)events[0]).ResultCode == 0; } - public async Task LeaveGroup(uint groupUin, CancellationToken cancellationToken) + public async Task LeaveGroup(uint groupUin) { var leaveGroupEvent = GroupLeaveEvent.Create(groupUin); - var events = await Collection.Business.SendEvent(leaveGroupEvent, cancellationToken); + var events = await Collection.Business.SendEvent(leaveGroupEvent); return events.Count != 0 && ((GroupLeaveEvent)events[0]).ResultCode == 0; } - public async Task FetchGroupFSSpace(uint groupUin, CancellationToken cancellationToken) + public async Task FetchGroupFSSpace(uint groupUin) { var groupFSSpaceEvent = GroupFSSpaceEvent.Create(groupUin); - var events = await Collection.Business.SendEvent(groupFSSpaceEvent, cancellationToken); + var events = await Collection.Business.SendEvent(groupFSSpaceEvent); return ((GroupFSSpaceEvent)events[0]).TotalSpace - ((GroupFSSpaceEvent)events[0]).UsedSpace; } - public async Task FetchGroupFSCount(uint groupUin, CancellationToken cancellationToken) + public async Task FetchGroupFSCount(uint groupUin) { var groupFSSpaceEvent = GroupFSCountEvent.Create(groupUin); - var events = await Collection.Business.SendEvent(groupFSSpaceEvent, cancellationToken); + var events = await Collection.Business.SendEvent(groupFSSpaceEvent); return ((GroupFSCountEvent)events[0]).FileCount; } - public async Task> FetchGroupFSList(uint groupUin, string targetDirectory, CancellationToken cancellationToken) + public async Task> FetchGroupFSList(uint groupUin, string targetDirectory) { uint startIndex = 0; var entries = new List(); while (true) { var groupFSListEvent = GroupFSListEvent.Create(groupUin, targetDirectory, startIndex, 20); - var events = await Collection.Business.SendEvent(groupFSListEvent, cancellationToken); + var events = await Collection.Business.SendEvent(groupFSListEvent); if (events.Count == 0) break; entries.AddRange(((GroupFSListEvent)events[0]).FileEntries); if (((GroupFSListEvent)events[0]).IsEnd) break; @@ -215,67 +215,63 @@ public async Task> FetchGroupFSList(uint groupUin, string targ return entries; } - public async Task FetchGroupFSDownload(uint groupUin, string fileId, CancellationToken cancellationToken) + public async Task FetchGroupFSDownload(uint groupUin, string fileId) { var groupFSDownloadEvent = GroupFSDownloadEvent.Create(groupUin, fileId); - var events = await Collection.Business.SendEvent(groupFSDownloadEvent, cancellationToken); + var events = await Collection.Business.SendEvent(groupFSDownloadEvent); return $"{((GroupFSDownloadEvent)events[0]).FileUrl}{fileId}"; } - public async Task<(int, string)> GroupFSMove(uint groupUin, string fileId, string parentDirectory, string targetDirectory, CancellationToken cancellationToken) + public async Task<(int, string)> GroupFSMove(uint groupUin, string fileId, string parentDirectory, string targetDirectory) { var groupFSMoveEvent = GroupFSMoveEvent.Create(groupUin, fileId, parentDirectory, targetDirectory); - var events = await Collection.Business.SendEvent(groupFSMoveEvent, cancellationToken); + var events = await Collection.Business.SendEvent(groupFSMoveEvent); int retCode = events.Count > 0 ? ((GroupFSMoveEvent)events[0]).ResultCode : -1; string retMsg = events.Count > 0 ? ((GroupFSMoveEvent)events[0]).RetMsg : string.Empty; return (retCode, retMsg); } - public async Task<(int, string)> GroupFSDelete(uint groupUin, string fileId, CancellationToken cancellationToken) + public async Task<(int, string)> GroupFSDelete(uint groupUin, string fileId) { var groupFSDeleteEvent = GroupFSDeleteEvent.Create(groupUin, fileId); - var events = await Collection.Business.SendEvent(groupFSDeleteEvent, cancellationToken); + var events = await Collection.Business.SendEvent(groupFSDeleteEvent); int retCode = events.Count > 0 ? ((GroupFSDeleteEvent)events[0]).ResultCode : -1; string retMsg = events.Count > 0 ? ((GroupFSDeleteEvent)events[0]).RetMsg : string.Empty; return (retCode, retMsg); } - public async Task<(int, string)> GroupFSCreateFolder(uint groupUin, string name, CancellationToken cancellationToken) + public async Task<(int, string)> GroupFSCreateFolder(uint groupUin, string name) { var groupFSCreateFolderEvent = GroupFSCreateFolderEvent.Create(groupUin, name); - var events = await Collection.Business.SendEvent(groupFSCreateFolderEvent, cancellationToken); + var events = await Collection.Business.SendEvent(groupFSCreateFolderEvent); int retCode = events.Count > 0 ? ((GroupFSCreateFolderEvent)events[0]).ResultCode : -1; string retMsg = events.Count > 0 ? ((GroupFSCreateFolderEvent)events[0]).RetMsg : string.Empty; return (retCode, retMsg); } - public async Task<(int, string)> GroupFSDeleteFolder(uint groupUin, string folderId, CancellationToken cancellationToken) + public async Task<(int, string)> GroupFSDeleteFolder(uint groupUin, string folderId) { var groupFSDeleteFolderEvent = GroupFSDeleteFolderEvent.Create(groupUin, folderId); - var events = await Collection.Business.SendEvent(groupFSDeleteFolderEvent, cancellationToken); + var events = await Collection.Business.SendEvent(groupFSDeleteFolderEvent); int retCode = events.Count > 0 ? ((GroupFSDeleteFolderEvent)events[0]).ResultCode : -1; string retMsg = events.Count > 0 ? ((GroupFSDeleteFolderEvent)events[0]).RetMsg : string.Empty; return (retCode, retMsg); } - public async Task<(int, string)> GroupFSRenameFolder(uint groupUin, string folderId, string newFolderName, CancellationToken cancellationToken) + public async Task<(int, string)> GroupFSRenameFolder(uint groupUin, string folderId, string newFolderName) { var groupFSDeleteFolderEvent = GroupFSRenameFolderEvent.Create(groupUin, folderId, newFolderName); - var events = await Collection.Business.SendEvent(groupFSDeleteFolderEvent, cancellationToken); + var events = await Collection.Business.SendEvent(groupFSDeleteFolderEvent); int retCode = events.Count > 0 ? ((GroupFSRenameFolderEvent)events[0]).ResultCode : -1; string retMsg = events.Count > 0 ? ((GroupFSRenameFolderEvent)events[0]).RetMsg : ""; return (retCode, retMsg); } - public Task GroupFSUpload(uint groupUin, FileEntity fileEntity, string targetDirectory, CancellationToken cancellationToken) + public Task GroupFSUpload(uint groupUin, FileEntity fileEntity, string targetDirectory) { try { - return FileUploader.UploadGroup(Collection, MessageBuilder.Group(groupUin).Build(), fileEntity, targetDirectory, cancellationToken); - } - catch (TaskCanceledException) - { - throw; + return FileUploader.UploadGroup(Collection, MessageBuilder.Group(groupUin).Build(), fileEntity, targetDirectory); } catch { @@ -283,18 +279,14 @@ public Task GroupFSUpload(uint groupUin, FileEntity fileEntity, string tar } } - public async Task UploadFriendFile(uint targetUin, FileEntity fileEntity, CancellationToken cancellationToken) + public async Task UploadFriendFile(uint targetUin, FileEntity fileEntity) { - string? uid = await Collection.Business.CachingLogic.ResolveUid(null, targetUin, cancellationToken); + string? uid = await Collection.Business.CachingLogic.ResolveUid(null, targetUin); var chain = new MessageChain(targetUin, Collection.Keystore.Uid ?? "", uid ?? "") { fileEntity }; try { - return await FileUploader.UploadPrivate(Collection, chain, fileEntity, cancellationToken); - } - catch (TaskCanceledException) - { - throw; + return await FileUploader.UploadPrivate(Collection, chain, fileEntity); } catch { @@ -302,55 +294,55 @@ public async Task UploadFriendFile(uint targetUin, FileEntity fileEntity, } } - public async Task RecallGroupMessage(uint groupUin, MessageResult result, CancellationToken cancellationToken) + public async Task RecallGroupMessage(uint groupUin, MessageResult result) { if (result.Sequence == null) return false; var recallMessageEvent = RecallGroupMessageEvent.Create(groupUin, result.Sequence.Value); - var events = await Collection.Business.SendEvent(recallMessageEvent, cancellationToken); + var events = await Collection.Business.SendEvent(recallMessageEvent); return events.Count != 0 && ((RecallGroupMessageEvent)events[0]).ResultCode == 0; } - public async Task RecallGroupMessage(MessageChain chain, CancellationToken cancellationToken) + public async Task RecallGroupMessage(MessageChain chain) { if (chain.GroupUin == null) return false; var recallMessageEvent = RecallGroupMessageEvent.Create(chain.GroupUin.Value, chain.Sequence); - var events = await Collection.Business.SendEvent(recallMessageEvent, cancellationToken); + var events = await Collection.Business.SendEvent(recallMessageEvent); return events.Count != 0 && ((RecallGroupMessageEvent)events[0]).ResultCode == 0; } - public async Task RecallGroupMessage(uint groupUin, uint sequence, CancellationToken cancellationToken) + public async Task RecallGroupMessage(uint groupUin, uint sequence) { var recallMessageEvent = RecallGroupMessageEvent.Create(groupUin, sequence); - var events = await Collection.Business.SendEvent(recallMessageEvent, cancellationToken); + var events = await Collection.Business.SendEvent(recallMessageEvent); return events.Count != 0 && ((RecallGroupMessageEvent)events[0]).ResultCode == 0; } - public async Task RecallFriendMessage(uint friendUin, MessageResult result, CancellationToken cancellationToken) + public async Task RecallFriendMessage(uint friendUin, MessageResult result) { if (result.Sequence == null) return false; - if (await Collection.Business.CachingLogic.ResolveUid(null, friendUin, cancellationToken) is not { } uid) return false; + if (await Collection.Business.CachingLogic.ResolveUid(null, friendUin) is not { } uid) return false; var recallMessageEvent = RecallFriendMessageEvent.Create(uid, result.ClientSequence, result.Sequence ?? 0, (uint)(result.MessageId & uint.MaxValue), result.Timestamp); - var events = await Collection.Business.SendEvent(recallMessageEvent, cancellationToken); + var events = await Collection.Business.SendEvent(recallMessageEvent); return events.Count != 0 && ((RecallFriendMessageEvent)events[0]).ResultCode == 0; } - public async Task RecallFriendMessage(MessageChain chain, CancellationToken cancellationToken) + public async Task RecallFriendMessage(MessageChain chain) { - if (await Collection.Business.CachingLogic.ResolveUid(null, chain.TargetUin, cancellationToken) is not { } uid) return false; + if (await Collection.Business.CachingLogic.ResolveUid(null, chain.TargetUin) is not { } uid) return false; uint timestamp = (uint)new DateTimeOffset(chain.Time).ToUnixTimeSeconds(); var recallMessageEvent = RecallFriendMessageEvent.Create(uid, chain.ClientSequence, chain.Sequence, (uint)(chain.MessageId & uint.MaxValue), timestamp); - var events = await Collection.Business.SendEvent(recallMessageEvent, cancellationToken); + var events = await Collection.Business.SendEvent(recallMessageEvent); return events.Count != 0 && ((RecallFriendMessageEvent)events[0]).ResultCode == 0; } - public async Task?> FetchGroupRequests(CancellationToken cancellationToken) + public async Task?> FetchGroupRequests() { var fetchRequestsEvent = FetchGroupRequestsEvent.Create(); - var events = await Collection.Business.SendEvent(fetchRequestsEvent, cancellationToken); + var events = await Collection.Business.SendEvent(fetchRequestsEvent); if (events.Count == 0) return null; var resolved = events.Cast().SelectMany(e => e.Events).ToList(); @@ -386,15 +378,15 @@ async Task ResolveUid(string? uid) if (uid == null) return 0; var fetchUidEvent = FetchUserInfoEvent.Create(uid); - var e = await Collection.Business.SendEvent(fetchUidEvent, cancellationToken); + var e = await Collection.Business.SendEvent(fetchUidEvent); return e.Count == 0 ? 0 : ((FetchUserInfoEvent)e[0]).UserInfo.Uin; } } - public async Task?> FetchFriendRequests(CancellationToken cancellationToken) + public async Task?> FetchFriendRequests() { var fetchRequestsEvent = FetchFriendsRequestsEvent.Create(); - var events = await Collection.Business.SendEvent(fetchRequestsEvent, cancellationToken); + var events = await Collection.Business.SendEvent(fetchRequestsEvent); if (events.Count == 0) return null; var resolved = ((FetchFriendsRequestsEvent)events[0]).Requests; @@ -412,132 +404,132 @@ async Task ResolveUid(string? uid) if (uid == null) return 0; var fetchUidEvent = FetchUserInfoEvent.Create(uid); - var e = await Collection.Business.SendEvent(fetchUidEvent, cancellationToken); + var e = await Collection.Business.SendEvent(fetchUidEvent); return e.Count == 0 ? 0 : ((FetchUserInfoEvent)e[0]).UserInfo.Uin; } } - public async Task GroupTransfer(uint groupUin, uint targetUin, CancellationToken cancellationToken) + public async Task GroupTransfer(uint groupUin, uint targetUin) { - string? uid = await Collection.Business.CachingLogic.ResolveUid(groupUin, targetUin, cancellationToken); + string? uid = await Collection.Business.CachingLogic.ResolveUid(groupUin, targetUin); if (uid == null || Collection.Keystore.Uid is not { } source) return false; var transferEvent = GroupTransferEvent.Create(groupUin, source, uid); - var results = await Collection.Business.SendEvent(transferEvent, cancellationToken); + var results = await Collection.Business.SendEvent(transferEvent); return results.Count != 0 && results[0].ResultCode == 0; } - public async Task SetStatus(uint status, CancellationToken cancellationToken) + public async Task SetStatus(uint status) { var setStatusEvent = SetStatusEvent.Create(status, 0); - var results = await Collection.Business.SendEvent(setStatusEvent, cancellationToken); + var results = await Collection.Business.SendEvent(setStatusEvent); return results.Count != 0 && results[0].ResultCode == 0; } - public async Task SetCustomStatus(uint faceId, string text, CancellationToken cancellationToken) + public async Task SetCustomStatus(uint faceId, string text) { var setCustomStatusEvent = SetCustomStatusEvent.Create(faceId, text); - var results = await Collection.Business.SendEvent(setCustomStatusEvent, cancellationToken); + var results = await Collection.Business.SendEvent(setCustomStatusEvent); return results.Count != 0 && results[0].ResultCode == 0; } - public async Task RequestFriend(uint targetUin, string question, string message, CancellationToken cancellationToken) + public async Task RequestFriend(uint targetUin, string question, string message) { var requestFriendSearchEvent = RequestFriendSearchEvent.Create(targetUin); - var searchEvents = await Collection.Business.SendEvent(requestFriendSearchEvent, cancellationToken); + var searchEvents = await Collection.Business.SendEvent(requestFriendSearchEvent); if (searchEvents.Count == 0) return false; await Task.Delay(5000); var requestFriendSettingEvent = RequestFriendSettingEvent.Create(targetUin); - var settingEvents = await Collection.Business.SendEvent(requestFriendSettingEvent, cancellationToken); + var settingEvents = await Collection.Business.SendEvent(requestFriendSettingEvent); if (settingEvents.Count == 0) return false; var requestFriendEvent = RequestFriendEvent.Create(targetUin, message, question); - var events = await Collection.Business.SendEvent(requestFriendEvent, cancellationToken); + var events = await Collection.Business.SendEvent(requestFriendEvent); return events.Count != 0 && ((RequestFriendEvent)events[0]).ResultCode == 0; } - public async Task Like(uint targetUin, uint count, CancellationToken cancellationToken) + public async Task Like(uint targetUin, uint count) { - var uid = await Collection.Business.CachingLogic.ResolveUid(null, targetUin, cancellationToken); + var uid = await Collection.Business.CachingLogic.ResolveUid(null, targetUin); if (uid == null) return false; var friendLikeEvent = FriendLikeEvent.Create(uid, count); - var results = await Collection.Business.SendEvent(friendLikeEvent, cancellationToken); + var results = await Collection.Business.SendEvent(friendLikeEvent); return results.Count != 0 && results[0].ResultCode == 0; } - public async Task InviteGroup(uint targetGroupUin, Dictionary invitedUins, CancellationToken cancellationToken) + public async Task InviteGroup(uint targetGroupUin, Dictionary invitedUins) { var invitedUids = new Dictionary(invitedUins.Count); foreach (var (friendUin, groupUin) in invitedUins) { - string? uid = await Collection.Business.CachingLogic.ResolveUid(groupUin, friendUin, cancellationToken); + string? uid = await Collection.Business.CachingLogic.ResolveUid(groupUin, friendUin); if (uid != null) invitedUids[uid] = groupUin; } var @event = GroupInviteEvent.Create(targetGroupUin, invitedUids); - var results = await Collection.Business.SendEvent(@event, cancellationToken); + var results = await Collection.Business.SendEvent(@event); return results.Count != 0 && results[0].ResultCode == 0; } - public async Task GetClientKey(CancellationToken cancellationToken) + public async Task GetClientKey() { var clientKeyEvent = FetchClientKeyEvent.Create(); - var events = await Collection.Business.SendEvent(clientKeyEvent, cancellationToken); + var events = await Collection.Business.SendEvent(clientKeyEvent); return events.Count == 0 ? null : ((FetchClientKeyEvent)events[0]).ClientKey; } - public async Task SetGroupRequest(uint groupUin, ulong sequence, uint type, bool accept, string reason, CancellationToken cancellationToken) + public async Task SetGroupRequest(uint groupUin, ulong sequence, uint type, bool accept, string reason) { var inviteEvent = SetGroupRequestEvent.Create(accept, groupUin, sequence, type, reason); - var results = await Collection.Business.SendEvent(inviteEvent, cancellationToken); + var results = await Collection.Business.SendEvent(inviteEvent); return results.Count != 0 && results[0].ResultCode == 0; } - public async Task SetGroupFilteredRequest(uint groupUin, ulong sequence, uint type, bool accept, string reason, CancellationToken cancellationToken) + public async Task SetGroupFilteredRequest(uint groupUin, ulong sequence, uint type, bool accept, string reason) { var inviteEvent = SetGroupFilteredRequestEvent.Create(accept, groupUin, sequence, type, reason); - var results = await Collection.Business.SendEvent(inviteEvent, cancellationToken); + var results = await Collection.Business.SendEvent(inviteEvent); return results.Count != 0 && results[0].ResultCode == 0; } - public async Task SetFriendRequest(string targetUid, bool accept, CancellationToken cancellationToken) + public async Task SetFriendRequest(string targetUid, bool accept) { var inviteEvent = SetFriendRequestEvent.Create(targetUid, accept); - var results = await Collection.Business.SendEvent(inviteEvent, cancellationToken); + var results = await Collection.Business.SendEvent(inviteEvent); return results.Count != 0 && results[0].ResultCode == 0; } - public async Task?> GetGroupMessage(uint groupUin, uint startSequence, uint endSequence, CancellationToken cancellationToken) + public async Task?> GetGroupMessage(uint groupUin, uint startSequence, uint endSequence) { var getMsgEvent = GetGroupMessageEvent.Create(groupUin, startSequence, endSequence); - var results = await Collection.Business.SendEvent(getMsgEvent, cancellationToken); + var results = await Collection.Business.SendEvent(getMsgEvent); return results.Count != 0 ? ((GetGroupMessageEvent)results[0]).Chains : null; } - public async Task?> GetRoamMessage(uint friendUin, uint time, uint count, CancellationToken cancellationToken) + public async Task?> GetRoamMessage(uint friendUin, uint time, uint count) { - if (await Collection.Business.CachingLogic.ResolveUid(null, friendUin, cancellationToken) is not { } uid) return null; + if (await Collection.Business.CachingLogic.ResolveUid(null, friendUin) is not { } uid) return null; var roamEvent = GetRoamMessageEvent.Create(uid, time, count); - var results = await Collection.Business.SendEvent(roamEvent, cancellationToken); + var results = await Collection.Business.SendEvent(roamEvent); return results.Count != 0 ? ((GetRoamMessageEvent)results[0]).Chains : null; } - public async Task?> GetC2cMessage(uint friendUin, uint startSequence, uint endSequence, CancellationToken cancellationToken) + public async Task?> GetC2cMessage(uint friendUin, uint startSequence, uint endSequence) { - if (await Collection.Business.CachingLogic.ResolveUid(null, friendUin, cancellationToken) is not { } uid) return null; + if (await Collection.Business.CachingLogic.ResolveUid(null, friendUin) is not { } uid) return null; var c2cEvent = GetC2cMessageEvent.Create(uid, startSequence, endSequence); - var results = await Collection.Business.SendEvent(c2cEvent, cancellationToken); + var results = await Collection.Business.SendEvent(c2cEvent); return results.Count != 0 ? ((GetC2cMessageEvent)results[0]).Chains : null; } - public async Task<(int code, List? chains)> GetMessagesByResId(string resId, CancellationToken cancellationToken) + public async Task<(int code, List? chains)> GetMessagesByResId(string resId) { var @event = MultiMsgDownloadEvent.Create(Collection.Keystore.Uid ?? "", resId); - var results = await Collection.Business.SendEvent(@event, cancellationToken); + var results = await Collection.Business.SendEvent(@event); if (results.Count == 0) return (-9999, null); var result = (MultiMsgDownloadEvent)results[0]; @@ -545,143 +537,142 @@ public async Task SetFriendRequest(string targetUid, bool accept, Cancella return (result.ResultCode, result.Chains); } - public async Task?> FetchCustomFace(CancellationToken cancellationToken) + public async Task?> FetchCustomFace() { var fetchCustomFaceEvent = FetchCustomFaceEvent.Create(); - var results = await Collection.Business.SendEvent(fetchCustomFaceEvent, cancellationToken); + var results = await Collection.Business.SendEvent(fetchCustomFaceEvent); return results.Count != 0 ? ((FetchCustomFaceEvent)results[0]).Urls : null; } - public async Task UploadLongMessage(List chains, CancellationToken cancellationToken) + public async Task UploadLongMessage(List chains) { var multiMsgUploadEvent = MultiMsgUploadEvent.Create(null, chains); - var results = await Collection.Business.SendEvent(multiMsgUploadEvent, cancellationToken); + var results = await Collection.Business.SendEvent(multiMsgUploadEvent); return results.Count != 0 ? ((MultiMsgUploadEvent)results[0]).ResId : null; } - public async Task MarkAsRead(uint groupUin, string? targetUid, uint startSequence, uint time, CancellationToken cancellationToken) + public async Task MarkAsRead(uint groupUin, string? targetUid, uint startSequence, uint time) { var markAsReadEvent = MarkReadedEvent.Create(groupUin, targetUid, startSequence, time); - var results = await Collection.Business.SendEvent(markAsReadEvent, cancellationToken); + var results = await Collection.Business.SendEvent(markAsReadEvent); return results.Count != 0 && ((MarkReadedEvent)results[0]).ResultCode == 0; } - public async Task FriendPoke(uint friendUin, CancellationToken cancellationToken) + public async Task FriendPoke(uint friendUin) { var friendPokeEvent = FriendPokeEvent.Create(friendUin); - var results = await Collection.Business.SendEvent(friendPokeEvent, cancellationToken); + var results = await Collection.Business.SendEvent(friendPokeEvent); return results.Count != 0 && ((FriendPokeEvent)results[0]).ResultCode == 0; } - public async Task GroupPoke(uint groupUin, uint friendUin, CancellationToken cancellationToken) + public async Task GroupPoke(uint groupUin, uint friendUin) { var friendPokeEvent = GroupPokeEvent.Create(friendUin, groupUin); - var results = await Collection.Business.SendEvent(friendPokeEvent, cancellationToken); + var results = await Collection.Business.SendEvent(friendPokeEvent); return results.Count != 0 && ((FriendPokeEvent)results[0]).ResultCode == 0; } - public async Task SetEssenceMessage(uint groupUin, uint sequence, uint random, CancellationToken cancellationToken) + public async Task SetEssenceMessage(uint groupUin, uint sequence, uint random) { var setEssenceMessageEvent = SetEssenceMessageEvent.Create(groupUin, sequence, random); - var results = await Collection.Business.SendEvent(setEssenceMessageEvent, cancellationToken); + var results = await Collection.Business.SendEvent(setEssenceMessageEvent); return results.Count != 0 && ((SetEssenceMessageEvent)results[0]).ResultCode == 0; } - public async Task RemoveEssenceMessage(uint groupUin, uint sequence, uint random, CancellationToken cancellationToken) + public async Task RemoveEssenceMessage(uint groupUin, uint sequence, uint random) { var removeEssenceMessageEvent = RemoveEssenceMessageEvent.Create(groupUin, sequence, random); - var results = await Collection.Business.SendEvent(removeEssenceMessageEvent, cancellationToken); + var results = await Collection.Business.SendEvent(removeEssenceMessageEvent); return results.Count != 0 && ((RemoveEssenceMessageEvent)results[0]).ResultCode == 0; } - public async Task GroupSetSpecialTitle(uint groupUin, uint targetUin, string title, CancellationToken cancellationToken) + public async Task GroupSetSpecialTitle(uint groupUin, uint targetUin, string title) { - string? uid = await Collection.Business.CachingLogic.ResolveUid(groupUin, targetUin, cancellationToken); + string? uid = await Collection.Business.CachingLogic.ResolveUid(groupUin, targetUin); if (uid == null) return false; var groupSetSpecialTitleEvent = GroupSetSpecialTitleEvent.Create(groupUin, uid, title); - var events = await Collection.Business.SendEvent(groupSetSpecialTitleEvent, cancellationToken); + var events = await Collection.Business.SendEvent(groupSetSpecialTitleEvent); return events.Count != 0 && ((GroupSetSpecialTitleEvent)events[0]).ResultCode == 0; } - public async Task FetchUserInfo(uint uin, bool refreshCache, CancellationToken cancellationToken) + public async Task FetchUserInfo(uint uin, bool refreshCache = false) { - return await Collection.Business.CachingLogic.GetCachedUsers(uin, refreshCache, cancellationToken); + return await Collection.Business.CachingLogic.GetCachedUsers(uin, refreshCache); } - public async Task SetMessageReaction(uint groupUin, uint sequence, string code, bool isAdd, CancellationToken cancellationToken) + public async Task SetMessageReaction(uint groupUin, uint sequence, string code, bool isAdd) { if (isAdd) { var addReactionEvent = GroupAddReactionEvent.Create(groupUin, sequence, code); - var results = await Collection.Business.SendEvent(addReactionEvent, cancellationToken); + var results = await Collection.Business.SendEvent(addReactionEvent); return results.Count != 0 && results[0].ResultCode == 0; } else { var reduceReactionEvent = GroupReduceReactionEvent.Create(groupUin, sequence, code); - var results = await Collection.Business.SendEvent(reduceReactionEvent, cancellationToken); + var results = await Collection.Business.SendEvent(reduceReactionEvent); return results.Count != 0 && results[0].ResultCode == 0; } } - public async Task SetNeedToConfirmSwitch(bool enableNoNeed, CancellationToken cancellationToken) + public async Task SetNeedToConfirmSwitch(bool enableNoNeed) { var setNeedToConfirmSwitchEvent = SetNeedToConfirmSwitchEvent.Create(enableNoNeed); - var results = await Collection.Business.SendEvent(setNeedToConfirmSwitchEvent, cancellationToken); + var results = await Collection.Business.SendEvent(setNeedToConfirmSwitchEvent); return results.Count != 0 && results[0].ResultCode == 0; } - public async Task?> FetchMarketFaceKey(List faceIds, CancellationToken cancellationToken) + public async Task?> FetchMarketFaceKey(List faceIds) { var fetchMarketFaceKeyEvent = FetchMarketFaceKeyEvent.Create(faceIds); - var results = await Collection.Business.SendEvent(fetchMarketFaceKeyEvent, cancellationToken); + var results = await Collection.Business.SendEvent(fetchMarketFaceKeyEvent); return results.Count != 0 ? ((FetchMarketFaceKeyEvent)results[0]).Keys : null; } - public async Task GroupClockIn(uint groupUin, CancellationToken cancellationToken) + public async Task GroupClockIn(uint groupUin) { var groupClockInEvent = GroupClockInEvent.Create(groupUin); - var results = await Collection.Business.SendEvent(groupClockInEvent, cancellationToken); + var results = await Collection.Business.SendEvent(groupClockInEvent); return ((GroupClockInEvent)results[0]).ResultInfo ?? new BotGroupClockInResult(false); } - public Task FriendSpecialShake(uint friendUin, SpecialPokeFaceType type, uint count, CancellationToken cancellationToken) + public Task FriendSpecialShake(uint friendUin, SpecialPokeFaceType type, uint count) { var chain = MessageBuilder.Friend(friendUin) .SpecialPoke(type, count) .Build(); - return SendMessage(chain, cancellationToken); + return SendMessage(chain); } - public Task FriendShake(uint friendUin, PokeFaceType type, uint strength, CancellationToken cancellationToken) + public Task FriendShake(uint friendUin, PokeFaceType type, uint strength) { var chain = MessageBuilder.Friend(friendUin) .Poke(type, strength) .Build(); - return SendMessage(chain, cancellationToken); + return SendMessage(chain); } - public async Task SetAvatar(ImageEntity avatar, CancellationToken cancellationToken) + public async Task SetAvatar(ImageEntity avatar) { if (avatar.ImageStream == null) return false; var highwayUrlEvent = HighwayUrlEvent.Create(); - var highwayUrlResults = await Collection.Business.SendEvent(highwayUrlEvent, cancellationToken); + var highwayUrlResults = await Collection.Business.SendEvent(highwayUrlEvent); if (highwayUrlResults.Count == 0) return false; var ticket = ((HighwayUrlEvent)highwayUrlResults[0]).SigSession; var md5 = avatar.ImageStream.Value.Md5().UnHex(); - return await Collection.Highway.UploadSrcByStreamAsync(90, avatar.ImageStream.Value, ticket, md5, - extendInfo: Array.Empty(), cancellation: cancellationToken); + return await Collection.Highway.UploadSrcByStreamAsync(90, avatar.ImageStream.Value, ticket, md5, Array.Empty()); } - public async Task GroupSetAvatar(uint groupUin, ImageEntity avatar, CancellationToken cancellationToken) + public async Task GroupSetAvatar(uint groupUin, ImageEntity avatar) { if (avatar.ImageStream == null) return false; var highwayUrlEvent = HighwayUrlEvent.Create(); - var highwayUrlResults = await Collection.Business.SendEvent(highwayUrlEvent, cancellationToken); + var highwayUrlResults = await Collection.Business.SendEvent(highwayUrlEvent); if (highwayUrlResults.Count == 0) return false; var ticket = ((HighwayUrlEvent)highwayUrlResults[0]).SigSession; @@ -694,16 +685,16 @@ public async Task GroupSetAvatar(uint groupUin, ImageEntity avatar, Cancel Field5 = 3, Field6 = 1 }.Serialize().ToArray(); - return await Collection.Highway.UploadSrcByStreamAsync(3000, avatar.ImageStream.Value, ticket, md5, extendInfo: extra, cancellation: cancellationToken); + return await Collection.Highway.UploadSrcByStreamAsync(3000, avatar.ImageStream.Value, ticket, md5, extra); } - public async Task<(uint, uint)> GroupRemainAtAll(uint groupUin, CancellationToken cancellationToken) + public async Task<(uint, uint)> GroupRemainAtAll(uint groupUin) { var groupRemainAtAllEvent = FetchGroupAtAllRemainEvent.Create(groupUin); - var results = await Collection.Business.SendEvent(groupRemainAtAllEvent, cancellationToken); + var results = await Collection.Business.SendEvent(groupRemainAtAllEvent); if (results.Count == 0) return (0, 0); var ret = (FetchGroupAtAllRemainEvent)results[0]; return (ret.RemainAtAllCountForUin, ret.RemainAtAllCountForGroup); } -} +} \ No newline at end of file diff --git a/Lagrange.Core/Internal/Context/Logic/Implementation/WtExchangeLogic.cs b/Lagrange.Core/Internal/Context/Logic/Implementation/WtExchangeLogic.cs index 9636444d5..f2e7a7421 100644 --- a/Lagrange.Core/Internal/Context/Logic/Implementation/WtExchangeLogic.cs +++ b/Lagrange.Core/Internal/Context/Logic/Implementation/WtExchangeLogic.cs @@ -27,7 +27,7 @@ internal class WtExchangeLogic : LogicBase private const string Tag = nameof(WtExchangeLogic); private readonly Timer _reLoginTimer; - + private TaskCompletionSource _transEmpTask = new(); private TaskCompletionSource<(string, string)> _captchaTask = new(); @@ -39,10 +39,10 @@ internal class WtExchangeLogic : LogicBase internal WtExchangeLogic(ContextCollection collection) : base(collection) { - _reLoginTimer = new Timer(async _ => await ReLogin(CancellationToken.None), null, Timeout.Infinite, Timeout.Infinite); + _reLoginTimer = new Timer(async _ => await ReLogin(), null, Timeout.Infinite, Timeout.Infinite); } - public override async Task Incoming(ProtocolEvent e, CancellationToken _) + public override async Task Incoming(ProtocolEvent e) { switch (e) { @@ -50,7 +50,7 @@ public override async Task Incoming(ProtocolEvent e, CancellationToken _) Collection.Log.LogFatal(Tag, $"KickNTEvent: {kick.Tag}: {kick.Message}"); Collection.Log.LogFatal(Tag, "Bot will be offline in 5 seconds..."); await Task.Delay(5000); - + Collection.Invoker.PostEvent(new BotOfflineEvent(kick.Tag, kick.Message)); // TODO: Fill in the reason of offline Collection.Scheduler.Dispose(); break; @@ -67,29 +67,28 @@ private void OnCancellation() { Collection.Scheduler.Cancel(QueryEvent); Collection.Scheduler.Cancel(HeartbeatEvent); - _transEmpTask.TrySetCanceled(); - _captchaTask.TrySetCanceled(); + _transEmpTask.TrySetException(new TaskCanceledException()); + _captchaTask.TrySetException(new TaskCanceledException()); } /// /// 1. resolve wtlogin.trans_emp CMD0x31 packet /// 2. Schedule wtlogin.trans_emp CMD0x12 Task /// - public async Task<(string, byte[])?> FetchQrCode(CancellationToken cancellationToken) + public async Task<(string, byte[])?> FetchQrCode() { Collection.Log.LogInfo(Tag, "Connecting Servers..."); - if (!await Collection.Socket.Connect(cancellationToken)) return null; - ScheduleWithCancellation(HeartbeatEvent, 10 * 1000, - async () => await Collection.Business.PushEvent(AliveEvent.Create(), cancellationToken), cancellationToken); - + if (!await Collection.Socket.Connect()) return null; + Collection.Scheduler.Interval(HeartbeatEvent, 10 * 1000, async () => await Collection.Business.PushEvent(AliveEvent.Create())); + if (Collection.Keystore.Session.D2.Length != 0) { Collection.Log.LogWarning(Tag, "Invalid Session found, try to clean D2Key, D2 and TGT Token"); Collection.Keystore.ClearSession(); } - + var transEmp = TransEmpEvent.Create(TransEmpEvent.State.FetchQrCode); - var result = await Collection.Business.SendEvent(transEmp, cancellationToken); + var result = await Collection.Business.SendEvent(transEmp); if (result.Count != 0) { @@ -108,7 +107,7 @@ public Task LoginByQrCode(CancellationToken cancellationToken) { Reset(); cancellationToken.Register(OnCancellation); - + Collection.Scheduler.Interval(QueryEvent, 2 * 1000, async () => await QueryTransEmpState(async @event => { if (@event.TgtgtKey != null) @@ -118,8 +117,8 @@ public Task LoginByQrCode(CancellationToken cancellationToken) Collection.Keystore.Session.NoPicSig = @event.NoPicSig; } - return await DoWtLogin(cancellationToken); - }, cancellationToken)); + return await DoWtLogin(); + })); return _transEmpTask.Task; } @@ -128,11 +127,11 @@ public async Task LoginByPassword(CancellationToken cancellationToken) { Reset(); cancellationToken.Register(OnCancellation); - + if (!Collection.Socket.Connected) // if socket not connected, try to connect { - if (!await Collection.Socket.Connect(cancellationToken)) return false; - ScheduleWithCancellation(HeartbeatEvent, 10 * 1000, async () => await Collection.Business.PushEvent(AliveEvent.Create(), cancellationToken), cancellationToken); + if (!await Collection.Socket.Connect()) return false; + Collection.Scheduler.Interval(HeartbeatEvent, 10 * 1000, async () => await Collection.Business.PushEvent(AliveEvent.Create())); } if (Collection.Keystore.Session.D2.Length > 0 && Collection.Keystore.Session.Tgt.Length > 0 && @@ -141,7 +140,7 @@ public async Task LoginByPassword(CancellationToken cancellationToken) Collection.Log.LogInfo(Tag, "Session has not expired, using session to login and register status"); try { - if (await BotOnline(cancellationToken: cancellationToken)) return true; + if (await BotOnline()) return true; Collection.Log.LogWarning(Tag, "Register by session failed, try to login by EasyLogin"); } @@ -155,7 +154,7 @@ public async Task LoginByPassword(CancellationToken cancellationToken) { Collection.Keystore.ClearSession(); - if (!await KeyExchange(cancellationToken)) + if (!await KeyExchange()) { Collection.Log.LogInfo(Tag, "Key Exchange Failed, please try again later"); return false; @@ -166,7 +165,7 @@ public async Task LoginByPassword(CancellationToken cancellationToken) { Collection.Log.LogInfo(Tag, "Trying to Login by EasyLogin..."); var easyLoginEvent = EasyLoginEvent.Create(); - var easyLoginResult = await Collection.Business.SendEvent(easyLoginEvent, CancellationToken.None); + var easyLoginResult = await Collection.Business.SendEvent(easyLoginEvent); if (easyLoginResult.Count != 0) { @@ -175,7 +174,7 @@ public async Task LoginByPassword(CancellationToken cancellationToken) case LoginCommon.Error.Success: { Collection.Log.LogInfo(Tag, "Login Success, try to register services"); - return await BotOnline(cancellationToken: cancellationToken); + return await BotOnline(); } case LoginCommon.Error.UnusualVerify: { @@ -192,13 +191,13 @@ public async Task LoginByPassword(CancellationToken cancellationToken) if (e.TempPassword != null) { Collection.Keystore.Session.TempPassword = e.TempPassword; - return await DoUnusualEasyLogin(cancellationToken); + return await DoUnusualEasyLogin(); } return false; - }, cancellationToken)); + })); bool result = await _transEmpTask.Task; - return result && await BotOnline(cancellationToken: cancellationToken); + return result && await BotOnline(); } default: { @@ -214,7 +213,7 @@ public async Task LoginByPassword(CancellationToken cancellationToken) { Collection.Log.LogInfo(Tag, "Trying to Login by Password..."); var passwordLoginEvent = PasswordLoginEvent.Create(); - var passwordLoginResult = await Collection.Business.SendEvent(passwordLoginEvent, CancellationToken.None); + var passwordLoginResult = await Collection.Business.SendEvent(passwordLoginEvent); if (passwordLoginResult.Count != 0) { @@ -225,7 +224,7 @@ public async Task LoginByPassword(CancellationToken cancellationToken) { Collection.Log.LogInfo(Tag, "Login Success"); - await BotOnline(cancellationToken: cancellationToken); + await BotOnline(); return true; } case LoginCommon.Error.UnusualVerify: @@ -272,7 +271,7 @@ public async Task LoginByPassword(CancellationToken cancellationToken) }; var client = new HttpClient(); - var response = await client.PostAsJsonAsync(url, request, cancellationToken: cancellationToken); + var response = await client.PostAsJsonAsync(url, request, cancellationToken); var json = await response.Content.ReadFromJsonAsync(cancellationToken: cancellationToken); if (json == null) return false; @@ -282,8 +281,8 @@ public async Task LoginByPassword(CancellationToken cancellationToken) string? original = HttpUtility.ParseQueryString(json.StrUrl.Split("?")[1])["str_url"]; if (original == null) return false; - - ScheduleWithCancellation(QueryEvent, 2 * 1000, async () => + + Collection.Scheduler.Interval(QueryEvent, 2 * 1000, async () => { var query = new NTNewDeviceQrCodeQuery { @@ -295,7 +294,7 @@ public async Task LoginByPassword(CancellationToken cancellationToken) if (!string.IsNullOrEmpty(responseJson?.StrNtSuccToken)) { Collection.Scheduler.Cancel(QueryEvent); // cancel the event - + Collection.Keystore.Session.TempPassword = Encoding.UTF8.GetBytes(responseJson.StrNtSuccToken); _transEmpTask.SetResult(true); client.Dispose(); @@ -304,14 +303,14 @@ public async Task LoginByPassword(CancellationToken cancellationToken) { Collection.Log.LogInfo(Tag, "NewDeviceLogin is waiting for scanning"); } - }, cancellationToken); + }); if (await _transEmpTask.Task) { Collection.Log.LogInfo(Tag, "Trying to Login by NewDeviceLogin..."); var newDeviceLogin = NewDeviceLoginEvent.Create(); - _ = await Collection.Business.SendEvent(newDeviceLogin, cancellationToken); - return await BotOnline(cancellationToken: cancellationToken); + _ = await Collection.Business.SendEvent(newDeviceLogin); + return await BotOnline(); } return false; @@ -321,7 +320,7 @@ public async Task LoginByPassword(CancellationToken cancellationToken) Collection.Log.LogWarning(Tag, @event is { Message: not null, Tag: not null } ? $"Login Failed: {(LoginCommon.Error)@event.ResultCode} | {@event.Tag}: {@event.Message}" : $"Login Failed: {(LoginCommon.Error)@event.ResultCode}"); - + return false; } } @@ -331,10 +330,10 @@ public async Task LoginByPassword(CancellationToken cancellationToken) return false; } - private async Task KeyExchange(CancellationToken cancellationToken) + private async Task KeyExchange() { var keyExchangeEvent = KeyExchangeEvent.Create(); - var exchangeResult = await Collection.Business.SendEvent(keyExchangeEvent, cancellationToken); + var exchangeResult = await Collection.Business.SendEvent(keyExchangeEvent); if (exchangeResult.Count != 0) { Collection.Log.LogInfo(Tag, "Key Exchange successfully!"); @@ -344,14 +343,14 @@ private async Task KeyExchange(CancellationToken cancellationToken) return false; } - private async Task DoWtLogin(CancellationToken cancellationToken) + private async Task DoWtLogin() { Collection.Log.LogInfo(Tag, "Doing Login..."); Collection.Keystore.Session.Sequence = 0; Collection.Keystore.SecpImpl = new EcdhImpl(EcdhImpl.CryptMethod.Secp192K1); var loginEvent = LoginEvent.Create(); - var result = await Collection.Business.SendEvent(loginEvent, cancellationToken); + var result = await Collection.Business.SendEvent(loginEvent); if (result.Count != 0) { @@ -361,7 +360,7 @@ private async Task DoWtLogin(CancellationToken cancellationToken) Collection.Log.LogInfo(Tag, "Login Success"); Collection.Keystore.Info = new BotKeystore.BotInfo(@event.Age, @event.Sex, @event.Name); Collection.Log.LogInfo(Tag, Collection.Keystore.Info.ToString()); - return await BotOnline(cancellationToken: cancellationToken); + return await BotOnline(); } Collection.Log.LogFatal(Tag, $"Login failed: {@event.ResultCode}"); @@ -371,14 +370,8 @@ private async Task DoWtLogin(CancellationToken cancellationToken) return false; } - private async Task QueryTransEmpState(Func> callback, CancellationToken cancellationToken) + private async Task QueryTransEmpState(Func> callback) { - if (cancellationToken.IsCancellationRequested) - { - Collection.Scheduler.Cancel(QueryEvent); - _transEmpTask.SetCanceled(cancellationToken); - return; - } if (Collection.Keystore.Session.QrString != null) { var request = new NTLoginHttpRequest @@ -389,13 +382,13 @@ private async Task QueryTransEmpState(Func> callback, }; var payload = JsonSerializer.SerializeToUtf8Bytes(request); - var response = await Http.PostAsync(Interface, payload, "application/json", cancellationToken); + var response = await Http.PostAsync(Interface, payload, "application/json"); var info = JsonSerializer.Deserialize(response); if (info != null) Collection.Keystore.Uin = info.Uin; } var transEmp = TransEmpEvent.Create(TransEmpEvent.State.QueryResult); - var result = await Collection.Business.SendEvent(transEmp, cancellationToken); + var result = await Collection.Business.SendEvent(transEmp); if (result.Count != 0) { @@ -434,14 +427,14 @@ private async Task QueryTransEmpState(Func> callback, break; } } + } - public async Task BotOnline(BotOnlineEvent.OnlineReason reason = BotOnlineEvent.OnlineReason.Login, CancellationToken cancellationToken = default) + public async Task BotOnline(BotOnlineEvent.OnlineReason reason = BotOnlineEvent.OnlineReason.Login) { var registerEvent = StatusRegisterEvent.Create(); - var registerResponse = await Collection.Business.SendEvent(registerEvent, cancellationToken); - // Cancellation token use default here is because the heartbeatDelegate is order to keep alive after online - var heartbeatDelegate = new Action(async () => await Collection.Business.PushEvent(SsoAliveEvent.Create(), CancellationToken.None)); + var registerResponse = await Collection.Business.SendEvent(registerEvent); + var heartbeatDelegate = new Action(async () => await Collection.Business.PushEvent(SsoAliveEvent.Create())); if (registerResponse.Count != 0) { @@ -456,8 +449,7 @@ public async Task BotOnline(BotOnlineEvent.OnlineReason reason = BotOnline var onlineEvent = new BotOnlineEvent(reason); Collection.Invoker.PostEvent(onlineEvent); - // cancellation token use default here is because the bot have online - await Collection.Business.PushEvent(InfoSyncEvent.Create(), CancellationToken.None); + await Collection.Business.PushEvent(InfoSyncEvent.Create()); _reLoginTimer.Change(TimeSpan.FromDays(15), TimeSpan.FromDays(15)); Collection.Log.LogInfo(Tag, "AutoReLogin Enabled, session would be refreshed in 15 days period"); @@ -472,7 +464,7 @@ public async Task BotOnline(BotOnlineEvent.OnlineReason reason = BotOnline private async Task FetchUnusual() { var transEmp = TransEmpEvent.Create(TransEmpEvent.State.FetchQrCode); - var result = await Collection.Business.SendEvent(transEmp, CancellationToken.None); + var result = await Collection.Business.SendEvent(transEmp); if (result.Count != 0) { @@ -483,15 +475,15 @@ private async Task FetchUnusual() return false; } - private async Task DoUnusualEasyLogin(CancellationToken cancellationToken) + private async Task DoUnusualEasyLogin() { Collection.Log.LogInfo(Tag, "Trying to Login by EasyLogin..."); var unusualEvent = UnusualEasyLoginEvent.Create(); - var result = await Collection.Business.SendEvent(unusualEvent, cancellationToken); + var result = await Collection.Business.SendEvent(unusualEvent); return result.Count != 0 && ((UnusualEasyLoginEvent)result[0]).Success; } - private async Task ReLogin(CancellationToken cancellationToken) + private async Task ReLogin() { Collection.Log.LogInfo(Tag, "Session is about to expire, try to relogin and refresh"); if (Collection.Keystore.Session.TempPassword == null) @@ -506,56 +498,35 @@ private async Task ReLogin(CancellationToken cancellationToken) Collection.Socket.Disconnect(); Collection.Keystore.ClearSession(); + await Collection.Socket.Connect(); - try + if (await KeyExchange()) { - await Collection.Socket.Connect(cancellationToken); - - if (await KeyExchange(cancellationToken)) + var easyLoginEvent = EasyLoginEvent.Create(); + var easyLoginResult = await Collection.Business.SendEvent(easyLoginEvent); + if (easyLoginResult.Count != 0) { - var easyLoginEvent = EasyLoginEvent.Create(); - var easyLoginResult = await Collection.Business.SendEvent(easyLoginEvent, CancellationToken.None); - if (easyLoginResult.Count != 0) + var result = (EasyLoginEvent)easyLoginResult[0]; + if ((LoginCommon.Error)result.ResultCode == LoginCommon.Error.Success) { - var result = (EasyLoginEvent)easyLoginResult[0]; - if ((LoginCommon.Error)result.ResultCode == LoginCommon.Error.Success) - { - Collection.Log.LogInfo(Tag, "Login Success, try to register services"); - if (await BotOnline(BotOnlineEvent.OnlineReason.Reconnect, cancellationToken)) return; - - Collection.Log.LogInfo(Tag, "Re-login failed, please refresh manually"); - } + Collection.Log.LogInfo(Tag, "Login Success, try to register services"); + if (await BotOnline(BotOnlineEvent.OnlineReason.Reconnect)) return; + + Collection.Log.LogInfo(Tag, "Re-login failed, please refresh manually"); } } - else - { - Collection.Log.LogInfo(Tag, "Key Exchange Failed, trying to online, please refresh manually"); - } } - catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested) + else { - Collection.Keystore.Session.D2 = d2; - Collection.Keystore.Session.D2Key = d2Key; - Collection.Keystore.Session.Tgt = tgt; - throw; + Collection.Log.LogInfo(Tag, "Key Exchange Failed, trying to online, please refresh manually"); } + + Collection.Keystore.Session.D2 = d2; + Collection.Keystore.Session.D2Key = d2Key; + Collection.Keystore.Session.Tgt = tgt; - await BotOnline(BotOnlineEvent.OnlineReason.Reconnect, cancellationToken); + await BotOnline(BotOnlineEvent.OnlineReason.Reconnect); } public bool SubmitCaptcha(string ticket, string randStr) => _captchaTask.TrySetResult((ticket, randStr)); - - private void ScheduleWithCancellation(string tag, int interval, Action func, CancellationToken ct) - { - Collection.Scheduler.Interval(tag, interval, () => - { - if (ct.IsCancellationRequested) - { - Collection.Scheduler.Cancel(tag); - return; - } - - func(); - }); - } -} +} \ No newline at end of file diff --git a/Lagrange.Core/Internal/Context/Logic/LogicBase.cs b/Lagrange.Core/Internal/Context/Logic/LogicBase.cs index a93c2dc13..49a04586d 100644 --- a/Lagrange.Core/Internal/Context/Logic/LogicBase.cs +++ b/Lagrange.Core/Internal/Context/Logic/LogicBase.cs @@ -8,7 +8,7 @@ internal abstract class LogicBase protected LogicBase(ContextCollection collection) => Collection = collection; - public virtual Task Incoming(ProtocolEvent e, CancellationToken cancellationToken) => Task.CompletedTask; + public virtual Task Incoming(ProtocolEvent e) => Task.CompletedTask; - public virtual Task Outgoing(ProtocolEvent e, CancellationToken cancellationToken) => Task.CompletedTask; -} + public virtual Task Outgoing(ProtocolEvent e) => Task.CompletedTask; +} \ No newline at end of file diff --git a/Lagrange.Core/Internal/Context/PacketContext.cs b/Lagrange.Core/Internal/Context/PacketContext.cs index 29746a2f7..927625ab9 100644 --- a/Lagrange.Core/Internal/Context/PacketContext.cs +++ b/Lagrange.Core/Internal/Context/PacketContext.cs @@ -17,7 +17,7 @@ internal class PacketContext : ContextBase { internal SignProvider SignProvider { private get; set; } - private readonly ConcurrentDictionary task, CancellationToken cancellationToken)> _pendingTasks; + private readonly ConcurrentDictionary> _pendingTasks; public PacketContext(ContextCollection collection, BotKeystore keystore, BotAppInfo appInfo, BotDeviceInfo device, BotConfig config) : base(collection, keystore, appInfo, device) @@ -29,43 +29,34 @@ public PacketContext(ContextCollection collection, BotKeystore keystore, BotAppI "Linux" => new LinuxSigner(), _ => throw new Exception("Unknown System Found") }; - _pendingTasks = new ConcurrentDictionary task, CancellationToken cancellationToken)>(); + _pendingTasks = new ConcurrentDictionary>(); } /// /// Send the packet and wait for the corresponding response by the packet's sequence number. /// - public Task SendPacket(SsoPacket packet, CancellationToken cancellationToken) + public Task SendPacket(SsoPacket packet) { - byte[] data; + var task = new TaskCompletionSource(); + _pendingTasks.TryAdd(packet.Sequence, task); + switch (packet.PacketType) { case 12: { var sso = SsoPacker.Build(packet, AppInfo, DeviceInfo, Keystore, SignProvider); var service = ServicePacker.BuildProtocol12(sso, Keystore); - data = service.ToArray(); + bool _ = Collection.Socket.Send(service.ToArray()).GetAwaiter().GetResult(); break; } case 13: { var service = ServicePacker.BuildProtocol13(packet.Payload, Keystore, packet.Command, packet.Sequence); - data = service.ToArray(); + bool _ = Collection.Socket.Send(service.ToArray()).GetAwaiter().GetResult(); break; } - default: - throw new Exception("Unknown Packet Type"); } - cancellationToken.ThrowIfCancellationRequested(); - - var task = new TaskCompletionSource(); - _pendingTasks.TryAdd(packet.Sequence, (task, cancellationToken)); - - // We have to wait packet to be sent before we can return the task - // Because the packet's sequence number is used to identify the response - bool _ = Collection.Socket.Send(data).GetAwaiter().GetResult(); - return task.Task; } @@ -99,21 +90,16 @@ public void DispatchPacket(BinaryPacket packet) var sso = SsoPacker.Parse(service); - if (_pendingTasks.TryRemove(sso.Sequence, out var pendingTask)) + if (_pendingTasks.TryRemove(sso.Sequence, out var task)) { - if (pendingTask.cancellationToken.IsCancellationRequested) - { - pendingTask.task.SetCanceled(pendingTask.cancellationToken); - return; - } if (sso is { RetCode: not 0, Extra: { } extra}) { string msg = $"Packet '{sso.Command}' returns {sso.RetCode} with seq: {sso.Sequence}, extra: {extra}"; - pendingTask.task.SetException(new InvalidOperationException(msg)); + task.SetException(new InvalidOperationException(msg)); } else { - pendingTask.task.SetResult(sso); + task.SetResult(sso); } } else @@ -121,4 +107,4 @@ public void DispatchPacket(BinaryPacket packet) Collection.Business.HandleServerPacket(sso); } } -} +} \ No newline at end of file diff --git a/Lagrange.Core/Internal/Context/SocketContext.cs b/Lagrange.Core/Internal/Context/SocketContext.cs index ba956f929..e722f1081 100644 --- a/Lagrange.Core/Internal/Context/SocketContext.cs +++ b/Lagrange.Core/Internal/Context/SocketContext.cs @@ -35,20 +35,20 @@ public SocketContext(ContextCollection collection, BotKeystore keystore, BotAppI _config = config; } - public async Task Connect(CancellationToken cancellationToken) + public async Task Connect() { if (_tcpClient.Connected) return true; - var servers = await OptimumServer(_config.GetOptimumServer, _config.UseIPv6Network, cancellationToken); + var servers = await OptimumServer(_config.GetOptimumServer, _config.UseIPv6Network); ServerUri = servers.First(); - return await _tcpClient.Connect(ServerUri.Host, ServerUri.Port, cancellationToken); + return await _tcpClient.Connect(ServerUri.Host, ServerUri.Port); } - private async Task Reconnect(CancellationToken cancellationToken) + private async Task Reconnect() { if (ServerUri != null && !_tcpClient.Connected) { - bool reconnect = await _tcpClient.Connect(ServerUri.Host, ServerUri.Port, cancellationToken); + bool reconnect = await _tcpClient.Connect(ServerUri.Host, ServerUri.Port); if (reconnect) { Collection.Log.LogInfo(Tag, $"Reconnect to {ServerUri}"); @@ -77,15 +77,10 @@ public void OnDisconnect() if (_config.AutoReconnect) { - var cancellationToken = CancellationToken.None; - - async void DoScheduleReconnect() + Collection.Scheduler.Interval("Reconnect", 10 * 1000, async () => { - if (cancellationToken.IsCancellationRequested || await Reconnect(cancellationToken)) - Collection.Scheduler.Cancel("Reconnect"); - } - - Collection.Scheduler.Interval("Reconnect", 10 * 1000, DoScheduleReconnect); + if (await Reconnect()) Collection.Scheduler.Cancel("Reconnect"); + }); } } @@ -114,12 +109,12 @@ public void OnSocketError(Exception e, ReadOnlyMemory data = default) new("http://119.147.190.138:8080") }; - private async Task> OptimumServer(bool requestMsf, bool useIPv6Network = false, CancellationToken cancellationToken = default) + private async Task> OptimumServer(bool requestMsf, bool useIPv6Network = false) { - var result = requestMsf ? await ResolveDns(useIPv6Network, cancellationToken: cancellationToken) : useIPv6Network ? HardCodeIPv6Uris : TestIPv4HardCodes; + var result = requestMsf ? await ResolveDns(useIPv6Network) : useIPv6Network ? HardCodeIPv6Uris : TestIPv4HardCodes; var latencyTasks = result.Select(uri => Icmp.PingAsync(uri)).ToArray(); - var latency = await Task.WhenAll(latencyTasks).WaitAsync(cancellationToken); + var latency = await Task.WhenAll(latencyTasks); Array.Sort(latency, result); var list = result.ToList(); @@ -127,10 +122,10 @@ private async Task> OptimumServer(bool requestMsf, bool useIPv6Network return list; } - private static async Task ResolveDns(bool useIPv6Network = false, CancellationToken cancellationToken = default) + private static async Task ResolveDns(bool useIPv6Network = false) { string dns = useIPv6Network ? "msfwifiv6.3g.qq.com" : "msfwifi.3g.qq.com"; - var addresses = await Dns.GetHostEntryAsync(dns, cancellationToken); + var addresses = await Dns.GetHostEntryAsync(dns); var result = new Uri[addresses.AddressList.Length]; for (int i = 0; i < addresses.AddressList.Length; i++) result[i] = new Uri($"http://{addresses.AddressList[i]}:8080"); diff --git a/Lagrange.Core/Internal/Context/Uploader/Common.cs b/Lagrange.Core/Internal/Context/Uploader/Common.cs index 6e7a766af..8548a2fc4 100644 --- a/Lagrange.Core/Internal/Context/Uploader/Common.cs +++ b/Lagrange.Core/Internal/Context/Uploader/Common.cs @@ -49,10 +49,10 @@ internal static class Common }; } - public static async Task GetTicket(ContextCollection context, CancellationToken cancellationToken) + public static async Task GetTicket(ContextCollection context) { var hwUrlEvent = HighwayUrlEvent.Create(); - var highwayUrlResult = await context.Business.SendEvent(hwUrlEvent, cancellationToken); + var highwayUrlResult = await context.Business.SendEvent(hwUrlEvent); return ((HighwayUrlEvent)highwayUrlResult[0]).SigSession; } @@ -110,4 +110,4 @@ private static string ConvertIP(uint raw) var ip = BitConverter.GetBytes(raw); return $"{ip[0]}.{ip[1]}.{ip[2]}.{ip[3]}"; } -} +} \ No newline at end of file diff --git a/Lagrange.Core/Internal/Context/Uploader/FileUploader.cs b/Lagrange.Core/Internal/Context/Uploader/FileUploader.cs index 75db6aee7..abad6c619 100644 --- a/Lagrange.Core/Internal/Context/Uploader/FileUploader.cs +++ b/Lagrange.Core/Internal/Context/Uploader/FileUploader.cs @@ -11,151 +11,148 @@ namespace Lagrange.Core.Internal.Context.Uploader; /// internal static class FileUploader { - public static async Task UploadPrivate(ContextCollection context, MessageChain chain, IMessageEntity entity, CancellationToken cancellationToken) + public static async Task UploadPrivate(ContextCollection context, MessageChain chain, IMessageEntity entity) { if (entity is not FileEntity { FileStream: not null } file) return false; - - try + + var uploadEvent = FileUploadEvent.Create(chain.Uid ?? "", file); + var result = await context.Business.SendEvent(uploadEvent); + var uploadResp = (FileUploadEvent)result[0]; + + if (!uploadResp.IsExist) { - var uploadEvent = FileUploadEvent.Create(chain.Uid ?? "", file); - var result = await context.Business.SendEvent(uploadEvent, cancellationToken); - var uploadResp = (FileUploadEvent)result[0]; - - if (!uploadResp.IsExist) + var ext = new FileUploadExt { - var ext = new FileUploadExt + Unknown1 = 100, + Unknown2 = 1, + Entry = new FileUploadEntry { - Unknown1 = 100, - Unknown2 = 1, - Entry = new FileUploadEntry + BusiBuff = new ExcitingBusiInfo { - BusiBuff = new ExcitingBusiInfo { SenderUin = context.Keystore.Uin, }, - FileEntry = - new ExcitingFileEntry - { - FileSize = file.FileStream.Length, - Md5 = file.FileMd5, - CheckKey = file.FileSha1, - Md5S2 = file.FileMd5, - FileId = uploadResp.FileId, - UploadKey = uploadResp.UploadKey - }, - ClientInfo = - new ExcitingClientInfo - { - ClientType = 3, - AppId = "100", - TerminalType = 3, - ClientVer = "1.1.1", - Unknown = 4 - }, - FileNameInfo = new ExcitingFileNameInfo { FileName = file.FileName }, - Host = new ExcitingHostConfig + SenderUin = context.Keystore.Uin, + }, + FileEntry = new ExcitingFileEntry + { + FileSize = file.FileStream.Length, + Md5 = file.FileMd5, + CheckKey = file.FileSha1, + Md5S2 = file.FileMd5, + FileId = uploadResp.FileId, + UploadKey = uploadResp.UploadKey + }, + ClientInfo = new ExcitingClientInfo + { + ClientType = 3, + AppId = "100", + TerminalType = 3, + ClientVer = "1.1.1", + Unknown = 4 + }, + FileNameInfo = new ExcitingFileNameInfo + { + FileName = file.FileName + }, + Host = new ExcitingHostConfig + { + Hosts = new List { - Hosts = new List + new() { - new() + Url = new ExcitingUrlInfo { - Url = new ExcitingUrlInfo { Unknown = 1, Host = uploadResp.Ip }, - Port = uploadResp.Port - } + Unknown = 1, + Host = uploadResp.Ip + }, + Port = uploadResp.Port } } - }, - Unknown200 = 1 - }; + } + }, + Unknown200 = 1 + }; - file.FileHash = uploadResp.Addon; - file.FileUuid = uploadResp.FileId; + file.FileHash = uploadResp.Addon; + file.FileUuid = uploadResp.FileId; - bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(95, file.FileStream, - await Common.GetTicket(context, cancellationToken), file.FileMd5, extendInfo: ext.Serialize().ToArray(), cancellation: cancellationToken); - if (!hwSuccess) return false; - } - } - finally - { - await file.FileStream.DisposeAsync(); + bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(95, file.FileStream, await Common.GetTicket(context), file.FileMd5, ext.Serialize().ToArray()); + if (!hwSuccess) return false; } + await file.FileStream.DisposeAsync(); var sendEvent = SendMessageEvent.Create(chain); - var sendResult = await context.Business.SendEvent(sendEvent, cancellationToken); + var sendResult = await context.Business.SendEvent(sendEvent); return sendResult.Count != 0 && ((SendMessageEvent)sendResult[0]).MsgResult.Result == 0; } - public static async Task UploadGroup(ContextCollection context, MessageChain chain, IMessageEntity entity, string targetDirectory, CancellationToken cancellationToken) + public static async Task UploadGroup(ContextCollection context, MessageChain chain, IMessageEntity entity, string targetDirectory) { if (entity is not FileEntity { FileStream: not null } file) return false; + + var uploadEvent = GroupFSUploadEvent.Create(chain.GroupUin ?? 0, targetDirectory, file); + var result = await context.Business.SendEvent(uploadEvent); + var uploadResp = (GroupFSUploadEvent)result[0]; + - string fileId = ""; - try + if (!uploadResp.IsExist) { - var uploadEvent = GroupFSUploadEvent.Create(chain.GroupUin ?? 0, targetDirectory, file); - var result = await context.Business.SendEvent(uploadEvent, cancellationToken); - var uploadResp = (GroupFSUploadEvent)result[0]; - - if (!uploadResp.IsExist) + var ext = new FileUploadExt { - var ext = new FileUploadExt + Unknown1 = 100, + Unknown2 = 1, + Entry = new FileUploadEntry { - Unknown1 = 100, - Unknown2 = 1, - Entry = new FileUploadEntry + BusiBuff = new ExcitingBusiInfo { - BusiBuff = - new ExcitingBusiInfo - { - SenderUin = context.Keystore.Uin, - ReceiverUin = chain.GroupUin ?? 0, - GroupCode = chain.GroupUin ?? 0 - }, - FileEntry = new ExcitingFileEntry - { - FileSize = file.FileStream.Length, - Md5 = file.FileMd5, - CheckKey = uploadResp.CheckKey, - Md5S2 = file.FileMd5, - FileId = uploadResp.FileId, - UploadKey = uploadResp.UploadKey - }, - ClientInfo = - new ExcitingClientInfo - { - ClientType = 3, - AppId = "100", - TerminalType = 3, - ClientVer = "1.1.1", - Unknown = 4 - }, - FileNameInfo = new ExcitingFileNameInfo { FileName = file.FileName }, - Host = new ExcitingHostConfig + SenderUin = context.Keystore.Uin, + ReceiverUin = chain.GroupUin ?? 0, + GroupCode = chain.GroupUin ?? 0 + }, + FileEntry = new ExcitingFileEntry + { + FileSize = file.FileStream.Length, + Md5 = file.FileMd5, + CheckKey = uploadResp.CheckKey, + Md5S2 = file.FileMd5, + FileId = uploadResp.FileId, + UploadKey = uploadResp.UploadKey + }, + ClientInfo = new ExcitingClientInfo + { + ClientType = 3, + AppId = "100", + TerminalType = 3, + ClientVer = "1.1.1", + Unknown = 4 + }, + FileNameInfo = new ExcitingFileNameInfo + { + FileName = file.FileName + }, + Host = new ExcitingHostConfig + { + Hosts = new List { - Hosts = new List + new() { - new() + Url = new ExcitingUrlInfo { - Url = new ExcitingUrlInfo { Unknown = 1, Host = uploadResp.Ip }, - Port = uploadResp.Port - } + Unknown = 1, + Host = uploadResp.Ip + }, + Port = uploadResp.Port } } } - }; - - bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(71, file.FileStream, - await Common.GetTicket(context, cancellationToken), file.FileMd5, extendInfo: ext.Serialize().ToArray(), cancellation: cancellationToken); - if (!hwSuccess) return false; + } + }; - fileId = uploadResp.FileId; - } - } - finally - { - await file.FileStream.DisposeAsync(); + bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(71, file.FileStream, await Common.GetTicket(context), file.FileMd5, ext.Serialize().ToArray()); + if (!hwSuccess) return false; } - var sendEvent = GroupSendFileEvent.Create(chain.GroupUin ?? 0, fileId); - var sendResult = await context.Business.SendEvent(sendEvent, cancellationToken); + await file.FileStream.DisposeAsync(); + var sendEvent = GroupSendFileEvent.Create(chain.GroupUin ?? 0, uploadResp.FileId); + var sendResult = await context.Business.SendEvent(sendEvent); return sendResult.Count != 0 && ((GroupSendFileEvent)sendResult[0]).ResultCode == 0; } -} +} \ No newline at end of file diff --git a/Lagrange.Core/Internal/Context/Uploader/IHighwayUploader.cs b/Lagrange.Core/Internal/Context/Uploader/IHighwayUploader.cs index 8c756820c..7af032b9d 100644 --- a/Lagrange.Core/Internal/Context/Uploader/IHighwayUploader.cs +++ b/Lagrange.Core/Internal/Context/Uploader/IHighwayUploader.cs @@ -4,7 +4,7 @@ namespace Lagrange.Core.Internal.Context.Uploader; internal interface IHighwayUploader { - public Task UploadPrivate(ContextCollection context, MessageChain chain, IMessageEntity entity, CancellationToken cancellationToken); + public Task UploadPrivate(ContextCollection context, MessageChain chain, IMessageEntity entity); - public Task UploadGroup(ContextCollection context, MessageChain chain, IMessageEntity entity, CancellationToken cancellationToken); -} + public Task UploadGroup(ContextCollection context, MessageChain chain, IMessageEntity entity); +} \ No newline at end of file diff --git a/Lagrange.Core/Internal/Context/Uploader/ImageUploader.cs b/Lagrange.Core/Internal/Context/Uploader/ImageUploader.cs index a3bb0ccb5..14b0d7221 100644 --- a/Lagrange.Core/Internal/Context/Uploader/ImageUploader.cs +++ b/Lagrange.Core/Internal/Context/Uploader/ImageUploader.cs @@ -8,18 +8,18 @@ namespace Lagrange.Core.Internal.Context.Uploader; [HighwayUploader(typeof(ImageEntity))] internal class ImageUploader : IHighwayUploader { - public async Task UploadPrivate(ContextCollection context, MessageChain chain, IMessageEntity entity, CancellationToken cancellationToken) + public async Task UploadPrivate(ContextCollection context, MessageChain chain, IMessageEntity entity) { if (entity is ImageEntity { ImageStream: { } stream } image) { var uploadEvent = ImageUploadEvent.Create(image, chain.FriendInfo?.Uid ?? ""); - var uploadResult = await context.Business.SendEvent(uploadEvent, cancellationToken); + var uploadResult = await context.Business.SendEvent(uploadEvent); var metaResult = (ImageUploadEvent)uploadResult[0]; if (Common.GenerateExt(metaResult) is { } ext) { var hash = metaResult.MsgInfo.MsgInfoBody[0].Index.Info.FileHash.UnHex(); - bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(1003, stream.Value, await Common.GetTicket(context, cancellationToken), hash, extendInfo: ext.Serialize().ToArray(), cancellation: cancellationToken); + bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(1003, stream.Value, await Common.GetTicket(context), hash, ext.Serialize().ToArray()); if (!hwSuccess) { await stream.Value.DisposeAsync(); @@ -33,18 +33,18 @@ public async Task UploadPrivate(ContextCollection context, MessageChain chain, I } } - public async Task UploadGroup(ContextCollection context, MessageChain chain, IMessageEntity entity, CancellationToken cancellationToken) + public async Task UploadGroup(ContextCollection context, MessageChain chain, IMessageEntity entity) { if (entity is ImageEntity { ImageStream: { } stream } image) { var uploadEvent = ImageGroupUploadEvent.Create(image, chain.GroupUin ?? 0); - var uploadResult = await context.Business.SendEvent(uploadEvent, cancellationToken); + var uploadResult = await context.Business.SendEvent(uploadEvent); var metaResult = (ImageGroupUploadEvent)uploadResult[0]; if (Common.GenerateExt(metaResult) is { } ext) { var hash = metaResult.MsgInfo.MsgInfoBody[0].Index.Info.FileHash.UnHex(); - bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(1004, stream.Value, await Common.GetTicket(context, cancellationToken), hash, extendInfo: ext.Serialize().ToArray(), cancellation: cancellationToken); + bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(1004, stream.Value, await Common.GetTicket(context), hash, ext.Serialize().ToArray()); if (!hwSuccess) { await stream.Value.DisposeAsync(); @@ -57,4 +57,4 @@ public async Task UploadGroup(ContextCollection context, MessageChain chain, IMe await image.ImageStream.Value.DisposeAsync(); } } -} +} \ No newline at end of file diff --git a/Lagrange.Core/Internal/Context/Uploader/PttUploader.cs b/Lagrange.Core/Internal/Context/Uploader/PttUploader.cs index 032922172..f2bd489a1 100644 --- a/Lagrange.Core/Internal/Context/Uploader/PttUploader.cs +++ b/Lagrange.Core/Internal/Context/Uploader/PttUploader.cs @@ -8,18 +8,18 @@ namespace Lagrange.Core.Internal.Context.Uploader; [HighwayUploader(typeof(RecordEntity))] internal class PttUploader : IHighwayUploader { - public async Task UploadPrivate(ContextCollection context, MessageChain chain, IMessageEntity entity, CancellationToken cancellationToken) + public async Task UploadPrivate(ContextCollection context, MessageChain chain, IMessageEntity entity) { if (entity is RecordEntity { AudioStream: { } stream } record) { var uploadEvent = RecordUploadEvent.Create(record, chain.FriendInfo?.Uid ?? ""); - var uploadResult = await context.Business.SendEvent(uploadEvent, cancellationToken); + var uploadResult = await context.Business.SendEvent(uploadEvent); var metaResult = (RecordUploadEvent)uploadResult[0]; if (Common.GenerateExt(metaResult) is { } ext) { var hash = metaResult.MsgInfo.MsgInfoBody[0].Index.Info.FileHash.UnHex(); - bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(1007, stream.Value, await Common.GetTicket(context, cancellationToken), hash, extendInfo: ext.Serialize().ToArray(), cancellation: cancellationToken); + bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(1007, stream.Value, await Common.GetTicket(context), hash, ext.Serialize().ToArray()); if (!hwSuccess) { await stream.Value.DisposeAsync(); @@ -33,18 +33,18 @@ public async Task UploadPrivate(ContextCollection context, MessageChain chain, I } } - public async Task UploadGroup(ContextCollection context, MessageChain chain, IMessageEntity entity, CancellationToken cancellationToken) + public async Task UploadGroup(ContextCollection context, MessageChain chain, IMessageEntity entity) { if (entity is RecordEntity { AudioStream: { } stream } record) { var uploadEvent = RecordGroupUploadEvent.Create(record, chain.GroupUin ?? 0); - var uploadResult = await context.Business.SendEvent(uploadEvent, cancellationToken); + var uploadResult = await context.Business.SendEvent(uploadEvent); var metaResult = (RecordGroupUploadEvent)uploadResult[0]; if (Common.GenerateExt(metaResult) is { } ext) { var hash = metaResult.MsgInfo.MsgInfoBody[0].Index.Info.FileHash.UnHex(); - bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(1008, stream.Value, await Common.GetTicket(context, cancellationToken), hash, extendInfo: ext.Serialize().ToArray(), cancellation: cancellationToken); + bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(1008, stream.Value, await Common.GetTicket(context), hash, ext.Serialize().ToArray()); if (!hwSuccess) { await stream.Value.DisposeAsync(); @@ -57,4 +57,4 @@ public async Task UploadGroup(ContextCollection context, MessageChain chain, IMe await record.AudioStream.Value.DisposeAsync(); } } -} +} \ No newline at end of file diff --git a/Lagrange.Core/Internal/Context/Uploader/VideoUploader.cs b/Lagrange.Core/Internal/Context/Uploader/VideoUploader.cs index d20fb2e90..5e5df607a 100644 --- a/Lagrange.Core/Internal/Context/Uploader/VideoUploader.cs +++ b/Lagrange.Core/Internal/Context/Uploader/VideoUploader.cs @@ -8,12 +8,12 @@ namespace Lagrange.Core.Internal.Context.Uploader; [HighwayUploader(typeof(VideoEntity))] internal class VideoUploader : IHighwayUploader { - public async Task UploadPrivate(ContextCollection context, MessageChain chain, IMessageEntity entity, CancellationToken cancellationToken) + public async Task UploadPrivate(ContextCollection context, MessageChain chain, IMessageEntity entity) { if (entity is VideoEntity { VideoStream: { } stream, ThumbnailStream: { } thumbnail } video) { var uploadEvent = VideoUploadEvent.Create(video, chain.FriendInfo?.Uid ?? ""); - var uploadResult = await context.Business.SendEvent(uploadEvent, cancellationToken); + var uploadResult = await context.Business.SendEvent(uploadEvent); var metaResult = (VideoUploadEvent)uploadResult[0]; if (Common.GenerateExt(metaResult) is { } ext) @@ -21,7 +21,7 @@ public async Task UploadPrivate(ContextCollection context, MessageChain chain, I ext.Hash.FileSha1 = Common.CalculateStreamBytes(stream.Value); var hash = metaResult.MsgInfo.MsgInfoBody[0].Index.Info.FileHash.UnHex(); - bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(1001, stream.Value, await Common.GetTicket(context, cancellationToken), hash, extendInfo: ext.Serialize().ToArray(), cancellation: cancellationToken); + bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(1001, stream.Value, await Common.GetTicket(context), hash, ext.Serialize().ToArray()); if (!hwSuccess) { await stream.Value.DisposeAsync(); @@ -32,7 +32,7 @@ public async Task UploadPrivate(ContextCollection context, MessageChain chain, I if (Common.GenerateExt(metaResult, metaResult.SubFiles[0]) is { } subExt) { var hash = metaResult.MsgInfo.MsgInfoBody[1].Index.Info.FileHash.UnHex(); - bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(1002, thumbnail.Value, await Common.GetTicket(context, cancellationToken), hash, extendInfo: subExt.Serialize().ToArray(), cancellation: cancellationToken); + bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(1002, thumbnail.Value, await Common.GetTicket(context), hash, subExt.Serialize().ToArray()); if (!hwSuccess) { await stream.Value.DisposeAsync(); @@ -48,12 +48,12 @@ public async Task UploadPrivate(ContextCollection context, MessageChain chain, I } } - public async Task UploadGroup(ContextCollection context, MessageChain chain, IMessageEntity entity, CancellationToken cancellationToken) + public async Task UploadGroup(ContextCollection context, MessageChain chain, IMessageEntity entity) { if (entity is VideoEntity { VideoStream: { } stream, ThumbnailStream: { } thumbnail } video) { var uploadEvent = VideoGroupUploadEvent.Create(video, chain.GroupUin ?? 0); - var uploadResult = await context.Business.SendEvent(uploadEvent, cancellationToken); + var uploadResult = await context.Business.SendEvent(uploadEvent); var metaResult = (VideoGroupUploadEvent)uploadResult[0]; if (Common.GenerateExt(metaResult) is { } ext) @@ -61,7 +61,7 @@ public async Task UploadGroup(ContextCollection context, MessageChain chain, IMe ext.Hash.FileSha1 = Common.CalculateStreamBytes(stream.Value); var hash = metaResult.MsgInfo.MsgInfoBody[0].Index.Info.FileHash.UnHex(); - bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(1005, stream.Value, await Common.GetTicket(context, cancellationToken), hash, extendInfo: ext.Serialize().ToArray(), cancellation: cancellationToken); + bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(1005, stream.Value, await Common.GetTicket(context), hash, ext.Serialize().ToArray()); if (!hwSuccess) { await stream.Value.DisposeAsync(); @@ -72,7 +72,7 @@ public async Task UploadGroup(ContextCollection context, MessageChain chain, IMe if (Common.GenerateExt(metaResult, metaResult.SubFiles[0]) is { } subExt) { var hash = metaResult.MsgInfo.MsgInfoBody[1].Index.Info.FileHash.UnHex(); - bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(1006, thumbnail.Value, await Common.GetTicket(context, cancellationToken), hash, extendInfo: subExt.Serialize().ToArray(), cancellation: cancellationToken); + bool hwSuccess = await context.Highway.UploadSrcByStreamAsync(1006, thumbnail.Value, await Common.GetTicket(context), hash, subExt.Serialize().ToArray()); if (!hwSuccess) { await stream.Value.DisposeAsync(); @@ -87,4 +87,4 @@ public async Task UploadGroup(ContextCollection context, MessageChain chain, IMe await thumbnail.Value.DisposeAsync(); } } -} +} \ No newline at end of file diff --git a/Lagrange.Core/Internal/Network/ClientListener.cs b/Lagrange.Core/Internal/Network/ClientListener.cs index 58e963ea8..9682b773b 100644 --- a/Lagrange.Core/Internal/Network/ClientListener.cs +++ b/Lagrange.Core/Internal/Network/ClientListener.cs @@ -20,12 +20,12 @@ internal abstract partial class ClientListener : IClientListener /// public ClientListener() { } - private async Task InternalConnectAsync(SocketSession session, string host, int port, CancellationToken cancellationToken) + private async Task InternalConnectAsync(SocketSession session, string host, int port) { try { - await session.Socket.ConnectAsync(host, port, cancellationToken); - _ = ReceiveLoop(session, cancellationToken); + await session.Socket.ConnectAsync(host, port); + _ = ReceiveLoop(session); return true; } catch (Exception e) @@ -41,9 +41,8 @@ private async Task InternalConnectAsync(SocketSession session, string host /// /// /// - /// /// - public Task Connect(string host, int port, CancellationToken cancellationToken) + public Task Connect(string host, int port) { SocketSession? previousSession = Session, createdSession = null; if (previousSession != null || // The client has been connected @@ -53,7 +52,7 @@ public Task Connect(string host, int port, CancellationToken cancellationT return Task.FromResult(false); } - return InternalConnectAsync(createdSession, host, port, cancellationToken); // Connect to server + return InternalConnectAsync(createdSession, host, port); // Connect to server } /// diff --git a/Lagrange.Core/Utility/Network/Http.cs b/Lagrange.Core/Utility/Network/Http.cs index a986d037c..b720e21fd 100644 --- a/Lagrange.Core/Utility/Network/Http.cs +++ b/Lagrange.Core/Utility/Network/Http.cs @@ -42,12 +42,4 @@ public static async Task PostAsync(string url, byte[] payload, string co var response = await Client.PostAsync(url, contentData); return await response.Content.ReadAsByteArrayAsync(); } - - public static async Task PostAsync(string url, byte[] payload, string content, CancellationToken cancellationToken) - { - var contentData = new ByteArrayContent(payload); - contentData.Headers.ContentType = new MediaTypeHeaderValue(content); - using var response = await Client.PostAsync(url, contentData, cancellationToken); - return await response.Content.ReadAsByteArrayAsync(cancellationToken); - } -} +} \ No newline at end of file diff --git a/Lagrange.OneBot/Core/Notify/NotifyService.cs b/Lagrange.OneBot/Core/Notify/NotifyService.cs index bd4b9fbc8..a54ab1695 100644 --- a/Lagrange.OneBot/Core/Notify/NotifyService.cs +++ b/Lagrange.OneBot/Core/Notify/NotifyService.cs @@ -99,7 +99,7 @@ public void RegisterEvents() { logger.LogInformation(@event.ToString()); - BotGroupRequest? botGroupRequest = (await bot.ContextCollection.Business.OperationLogic.FetchGroupRequests(CancellationToken.None)) + BotGroupRequest? botGroupRequest = (await bot.ContextCollection.Business.OperationLogic.FetchGroupRequests()) ?.AsParallel() .FirstOrDefault(r => { diff --git a/Lagrange.OneBot/Core/Operation/Ability/UploadImageOperation.cs b/Lagrange.OneBot/Core/Operation/Ability/UploadImageOperation.cs index f7c16a4ce..78e39a444 100644 --- a/Lagrange.OneBot/Core/Operation/Ability/UploadImageOperation.cs +++ b/Lagrange.OneBot/Core/Operation/Ability/UploadImageOperation.cs @@ -15,12 +15,12 @@ public async Task HandleOperation(BotContext context, JsonNode? pa if (payload?["file"]?.ToString() is { } file && CommonResolver.ResolveStream(file) is { } stream) { var entity = new ImageEntity(stream); - await context.ContextCollection.Highway.ManualUploadEntity(entity, CancellationToken.None); + await context.ContextCollection.Highway.ManualUploadEntity(entity); var msgInfo = entity.MsgInfo; if (msgInfo is null) throw new Exception(); var downloadEvent = ImageDownloadEvent.Create(context.ContextCollection.Keystore.Uid ?? "", msgInfo); - var result = await context.ContextCollection.Business.SendEvent(downloadEvent, CancellationToken.None); + var result = await context.ContextCollection.Business.SendEvent(downloadEvent); var ret = (ImageDownloadEvent)result[0]; return new OneBotResult(ret.ImageUrl, 0, "ok"); diff --git a/Lagrange.OneBot/Core/Operation/Generic/SendPacketOperation.cs b/Lagrange.OneBot/Core/Operation/Generic/SendPacketOperation.cs index 0a2dbc0f3..5cb743e21 100644 --- a/Lagrange.OneBot/Core/Operation/Generic/SendPacketOperation.cs +++ b/Lagrange.OneBot/Core/Operation/Generic/SendPacketOperation.cs @@ -17,7 +17,7 @@ public async Task HandleOperation(BotContext context, JsonNode? pa { int sequence = context.ContextCollection.Service.GetNewSequence(); var ssoPacket = new SsoPacket(send.Type, send.Command, (uint)sequence, send.Data.UnHex()); - var task = await context.ContextCollection.Packet.SendPacket(ssoPacket, CancellationToken.None); + var task = await context.ContextCollection.Packet.SendPacket(ssoPacket); return new OneBotResult(new OneBotSendPacketResponse { diff --git a/Lagrange.OneBot/Core/Operation/Message/SendForwardMessageOperation.cs b/Lagrange.OneBot/Core/Operation/Message/SendForwardMessageOperation.cs index c329defa4..dc5fba242 100644 --- a/Lagrange.OneBot/Core/Operation/Message/SendForwardMessageOperation.cs +++ b/Lagrange.OneBot/Core/Operation/Message/SendForwardMessageOperation.cs @@ -18,7 +18,7 @@ public async Task HandleOperation(BotContext context, JsonNode? pa var chains = common.BuildForwardChains(context, forward); var @event = MultiMsgUploadEvent.Create(null, chains); - var result = await context.ContextCollection.Business.SendEvent(@event, CancellationToken.None); + var result = await context.ContextCollection.Business.SendEvent(@event); if (result.Count != 0 && result[0] is MultiMsgUploadEvent res) { return new OneBotResult(res.ResId, 0, "ok"); diff --git a/Lagrange.OneBot/Core/Operation/Request/SetFriendAddRequestOperation.cs b/Lagrange.OneBot/Core/Operation/Request/SetFriendAddRequestOperation.cs index 09f137e80..3c09ab3cc 100644 --- a/Lagrange.OneBot/Core/Operation/Request/SetFriendAddRequestOperation.cs +++ b/Lagrange.OneBot/Core/Operation/Request/SetFriendAddRequestOperation.cs @@ -13,7 +13,7 @@ public async Task HandleOperation(BotContext context, JsonNode? pa { if (payload.Deserialize(SerializerOptions.DefaultOptions) is { } request) { - bool result = await context.ContextCollection.Business.OperationLogic.SetFriendRequest(request.Flag, request.Approve, CancellationToken.None); + bool result = await context.ContextCollection.Business.OperationLogic.SetFriendRequest(request.Flag, request.Approve); return new OneBotResult(null, result ? 0 : 1, "ok"); } diff --git a/Lagrange.OneBot/Core/Operation/Request/SetGroupAddRequestOperation.cs b/Lagrange.OneBot/Core/Operation/Request/SetGroupAddRequestOperation.cs index 1faad95bc..e85a45a9c 100644 --- a/Lagrange.OneBot/Core/Operation/Request/SetGroupAddRequestOperation.cs +++ b/Lagrange.OneBot/Core/Operation/Request/SetGroupAddRequestOperation.cs @@ -21,9 +21,9 @@ public async Task HandleOperation(BotContext context, JsonNode? pa bool result = isFiltered ? await context.ContextCollection.Business.OperationLogic.SetGroupFilteredRequest(groupUin, sequence, - eventType, request.Approve, request.Reason, CancellationToken.None) + eventType, request.Approve, request.Reason) : await context.ContextCollection.Business.OperationLogic.SetGroupRequest(groupUin, sequence, eventType, - request.Approve, request.Reason, CancellationToken.None); + request.Approve, request.Reason); return new OneBotResult(null, result ? 0 : 1, "ok"); } From 358068777535584a3b1ce31c3082ebdf559fe228 Mon Sep 17 00:00:00 2001 From: pk5ls20 Date: Tue, 22 Oct 2024 15:31:42 +0800 Subject: [PATCH 16/19] [All] Fix the issue of sending super emoticons and some other normal emoticons (#618) * [Core] Correction of some field names in QFaceExtra * [Core] Correction of some field names in QFaceExtra x2 * [Core] Introduce `0x9154_1` & spilt `QFaceExtra` * [Core] faceId >= 260 * [All] Fix the issue of sending super emoticons & add JoinEmojiChan * [Core] Always send small face by default * [Core] resolve https://github.com/LagrangeDev/Lagrange.Core/pull/618#discussion_r1810102549 & https://github.com/LagrangeDev/Lagrange.Core/pull/618#discussion_r1810103474 --- Lagrange.Core/Common/Entity/SysFaceEntry.cs | 67 +++++++++++++++ .../Common/Interface/Api/OperationExt.cs | 12 +++ .../Logic/Implementation/CachingLogic.cs | 36 ++++++++ .../Logic/Implementation/MessagingLogic.cs | 8 ++ .../Logic/Implementation/OperationLogic.cs | 20 +++++ .../Event/Action/FriendJoinEmojiChainEvent.cs | 14 ++++ .../Event/Action/GroupJoinEmojiChainEvent.cs | 14 ++++ .../Event/Action/JoinEmojiChainEvent.cs | 22 +++++ .../Event/System/FetchFullSysFacesEvent.cs | 22 +++++ .../Extra/{QFaceExtra.cs => QBigFaceExtra.cs} | 8 +- .../Implementation/Extra/QSmallFaceExtra.cs | 13 +-- .../Oidb/Request/OidbSvcTrpcTcp.0x90EE_1.cs | 24 ++++++ .../Oidb/Request/OidbSvcTrpcTcp0x9154_1.cs | 17 ++++ .../OidbSvcTrpcTcp0x9154_1Response.cs | 84 +++++++++++++++++++ .../Service/Action/JoinEmojiChainService.cs | 41 +++++++++ .../System/FetchFullSysFacesService.cs | 68 +++++++++++++++ Lagrange.Core/Message/Entity/FaceEntity.cs | 60 +++++++++---- Lagrange.Core/Message/MessageBuilder.cs | 2 +- .../Action/OneBotGroupJoinEmojiChain.cs | 11 +++ .../Action/OneBotPrivateJoinEmojiChain.cs | 11 +++ .../Generic/FriendJoinEmojiChainOperation.cs | 27 ++++++ .../Generic/GroupJoinEmojiChainOperation.cs | 27 ++++++ Lagrange.OneBot/Message/Entity/FaceSegment.cs | 5 +- 23 files changed, 584 insertions(+), 29 deletions(-) create mode 100644 Lagrange.Core/Common/Entity/SysFaceEntry.cs create mode 100644 Lagrange.Core/Internal/Event/Action/FriendJoinEmojiChainEvent.cs create mode 100644 Lagrange.Core/Internal/Event/Action/GroupJoinEmojiChainEvent.cs create mode 100644 Lagrange.Core/Internal/Event/Action/JoinEmojiChainEvent.cs create mode 100644 Lagrange.Core/Internal/Event/System/FetchFullSysFacesEvent.cs rename Lagrange.Core/Internal/Packets/Message/Element/Implementation/Extra/{QFaceExtra.cs => QBigFaceExtra.cs} (70%) create mode 100644 Lagrange.Core/Internal/Packets/Service/Oidb/Request/OidbSvcTrpcTcp.0x90EE_1.cs create mode 100644 Lagrange.Core/Internal/Packets/Service/Oidb/Request/OidbSvcTrpcTcp0x9154_1.cs create mode 100644 Lagrange.Core/Internal/Packets/Service/Oidb/Response/OidbSvcTrpcTcp0x9154_1Response.cs create mode 100644 Lagrange.Core/Internal/Service/Action/JoinEmojiChainService.cs create mode 100644 Lagrange.Core/Internal/Service/System/FetchFullSysFacesService.cs create mode 100644 Lagrange.OneBot/Core/Entity/Action/OneBotGroupJoinEmojiChain.cs create mode 100644 Lagrange.OneBot/Core/Entity/Action/OneBotPrivateJoinEmojiChain.cs create mode 100644 Lagrange.OneBot/Core/Operation/Generic/FriendJoinEmojiChainOperation.cs create mode 100644 Lagrange.OneBot/Core/Operation/Generic/GroupJoinEmojiChainOperation.cs diff --git a/Lagrange.Core/Common/Entity/SysFaceEntry.cs b/Lagrange.Core/Common/Entity/SysFaceEntry.cs new file mode 100644 index 000000000..7bbf0468e --- /dev/null +++ b/Lagrange.Core/Common/Entity/SysFaceEntry.cs @@ -0,0 +1,67 @@ +namespace Lagrange.Core.Common.Entity; + +[Serializable] +public class SysFaceEntry +{ + public string QSid { get; set; } + + public string? QDes { get; set; } + + public string? EMCode { get; set; } + + public int? QCid { get; set; } + + public int? AniStickerType { get; set; } + + public int? AniStickerPackId { get; set; } + + public int? AniStickerId { get; set; } + + public string? Url { get; set; } + + public string[]? EmojiNameAlias { get; set; } + + public int? AniStickerWidth { get; set; } + + public int? AniStickerHeight { get; set; } + + public SysFaceEntry(string qSid, string? qDes, string? emCode, int? qCid, int? aniStickerType, + int? aniStickerPackId, int? aniStickerId, string? url, string[]? emojiNameAlias, int? aniStickerWidth, + int? aniStickerHeight) + { + QSid = qSid; + QDes = qDes; + EMCode = emCode; + QCid = qCid; + AniStickerType = aniStickerType; + AniStickerPackId = aniStickerPackId; + AniStickerId = aniStickerId; + Url = url; + EmojiNameAlias = emojiNameAlias; + AniStickerWidth = aniStickerWidth; + AniStickerHeight = aniStickerHeight; + } +} + +[Serializable] +public class SysFacePackEntry +{ + public string EmojiPackName { get; set; } + + public SysFaceEntry[] Emojis { get; set; } + + public SysFacePackEntry(string emojiPackName, SysFaceEntry[] emojis) + { + EmojiPackName = emojiPackName; + Emojis = emojis; + } + + public uint[] GetUniqueSuperQSids((int AniStickerType, int AniStickerPackId)[] excludeAniStickerTypesAndPackIds) + => Emojis + .Where(e => e.AniStickerType is not null + && e.AniStickerPackId is not null + && !excludeAniStickerTypesAndPackIds.Contains((e.AniStickerType.Value, e.AniStickerPackId.Value))) + .Select(e => uint.Parse(e.QSid)) + .Distinct() + .ToArray(); +} \ No newline at end of file diff --git a/Lagrange.Core/Common/Interface/Api/OperationExt.cs b/Lagrange.Core/Common/Interface/Api/OperationExt.cs index 3900a4416..fee6b08a2 100644 --- a/Lagrange.Core/Common/Interface/Api/OperationExt.cs +++ b/Lagrange.Core/Common/Interface/Api/OperationExt.cs @@ -249,4 +249,16 @@ public static Task FriendShake(this BotContext bot, uint friendUi /// The avatar object, public static Task SetAvatar(this BotContext bot, ImageEntity avatar) => bot.ContextCollection.Business.OperationLogic.SetAvatar(avatar); + + public static Task FetchSuperFaceId(this BotContext bot, uint id) + => bot.ContextCollection.Business.OperationLogic.FetchSuperFaceId(id); + + public static Task FetchFaceEntity(this BotContext bot, uint id) + => bot.ContextCollection.Business.OperationLogic.FetchFaceEntity(id); + + public static Task GroupJoinEmojiChain(this BotContext bot, uint groupUin, uint emojiId, uint targetMessageSeq) + => bot.ContextCollection.Business.OperationLogic.GroupJoinEmojiChain(groupUin, emojiId, targetMessageSeq); + + public static Task FriendJoinEmojiChain(this BotContext bot, uint friendUin, uint emojiId, uint targetMessageSeq) + => bot.ContextCollection.Business.OperationLogic.FriendJoinEmojiChain(friendUin, emojiId, targetMessageSeq); } diff --git a/Lagrange.Core/Internal/Context/Logic/Implementation/CachingLogic.cs b/Lagrange.Core/Internal/Context/Logic/Implementation/CachingLogic.cs index 645946768..3fbafcdb7 100644 --- a/Lagrange.Core/Internal/Context/Logic/Implementation/CachingLogic.cs +++ b/Lagrange.Core/Internal/Context/Logic/Implementation/CachingLogic.cs @@ -25,6 +25,9 @@ internal class CachingLogic : LogicBase private readonly ConcurrentDictionary _cacheUsers; + private readonly Dictionary _cacheFaceEntities; + private readonly List _cacheSuperFaceId; + internal CachingLogic(ContextCollection collection) : base(collection) { _uinToUid = new Dictionary(); @@ -35,6 +38,9 @@ internal CachingLogic(ContextCollection collection) : base(collection) _cachedGroupMembers = new Dictionary>(); _cacheUsers = new ConcurrentDictionary(); + + _cacheFaceEntities = new Dictionary(); + _cacheSuperFaceId = new List(); } public override Task Incoming(ProtocolEvent e) @@ -92,6 +98,7 @@ public async Task> GetCachedMembers(uint groupUin, bool ref await ResolveMembersUid(groupUin); return _cachedGroupMembers.TryGetValue(groupUin, out members) ? members : new List(); } + return members; } @@ -142,6 +149,7 @@ private async Task ResolveFriendsUidAndFriendGroups() { friend.Group = new(friend.Group.GroupId, friendGroups[friend.Group.GroupId]); } + friends.AddRange(result.Friends); next = result.NextUin; @@ -190,4 +198,32 @@ private async Task ResolveUser(uint uin) _cacheUsers.AddOrUpdate(uin, @event.UserInfo, (_key, _value) => @event.UserInfo); } } + + private async Task ResolveEmojiCache() + { + var fetchSysEmojisEvent = FetchFullSysFacesEvent.Create(); + var events = await Collection.Business.SendEvent(fetchSysEmojisEvent); + var emojiPacks = ((FetchFullSysFacesEvent)events[0]).FacePacks; + + emojiPacks + .SelectMany(pack => pack.Emojis) + .Where(emoji => uint.TryParse(emoji.QSid, out _)) + .ToList() + .ForEach(emoji => _cacheFaceEntities[uint.Parse(emoji.QSid)] = emoji); + + _cacheSuperFaceId.AddRange(emojiPacks + .SelectMany(emojiPack => emojiPack.GetUniqueSuperQSids(new[] { (1, 1) }))); + } + + public async Task GetCachedIsSuperFaceId(uint id) + { + if (!_cacheSuperFaceId.Any()) await ResolveEmojiCache(); + return _cacheSuperFaceId.Contains(id); + } + + public async Task GetCachedFaceEntity(uint faceId) + { + if (!_cacheFaceEntities.ContainsKey(faceId)) await ResolveEmojiCache(); + return _cacheFaceEntities.GetValueOrDefault(faceId); + } } \ No newline at end of file diff --git a/Lagrange.Core/Internal/Context/Logic/Implementation/MessagingLogic.cs b/Lagrange.Core/Internal/Context/Logic/Implementation/MessagingLogic.cs index 9da1c8f2c..4581d2ce5 100644 --- a/Lagrange.Core/Internal/Context/Logic/Implementation/MessagingLogic.cs +++ b/Lagrange.Core/Internal/Context/Logic/Implementation/MessagingLogic.cs @@ -10,6 +10,7 @@ using Lagrange.Core.Message; using Lagrange.Core.Message.Entity; using Lagrange.Core.Message.Filter; +using Lagrange.Core.Utility.Extension; using FriendPokeEvent = Lagrange.Core.Event.EventArg.FriendPokeEvent; using GroupPokeEvent = Lagrange.Core.Event.EventArg.GroupPokeEvent; @@ -382,6 +383,13 @@ private async Task ResolveOutgoingChain(MessageChain chain) { switch (entity) { + case FaceEntity face: + { + var cache = Collection.Business.CachingLogic; + face.SysFaceEntry ??= await cache.GetCachedFaceEntity(face.FaceId); + break; + } + case ForwardEntity forward when forward.TargetUin != 0: { var cache = Collection.Business.CachingLogic; diff --git a/Lagrange.Core/Internal/Context/Logic/Implementation/OperationLogic.cs b/Lagrange.Core/Internal/Context/Logic/Implementation/OperationLogic.cs index fdf82a6aa..1d1ce7796 100644 --- a/Lagrange.Core/Internal/Context/Logic/Implementation/OperationLogic.cs +++ b/Lagrange.Core/Internal/Context/Logic/Implementation/OperationLogic.cs @@ -697,4 +697,24 @@ public async Task GroupSetAvatar(uint groupUin, ImageEntity avatar) var ret = (FetchGroupAtAllRemainEvent)results[0]; return (ret.RemainAtAllCountForUin, ret.RemainAtAllCountForGroup); } + + public async Task FetchSuperFaceId(uint id) => await Collection.Business.CachingLogic.GetCachedIsSuperFaceId(id); + + public async Task FetchFaceEntity(uint id) => await Collection.Business.CachingLogic.GetCachedFaceEntity(id); + + public async Task GroupJoinEmojiChain(uint groupUin, uint emojiId, uint targetMessageSeq) + { + var groupJoinEmojiChainEvent = GroupJoinEmojiChainEvent.Create(targetMessageSeq, emojiId, groupUin); + var results = await Collection.Business.SendEvent(groupJoinEmojiChainEvent); + return results.Count != 0 && results[0].ResultCode == 0; + } + + public async Task FriendJoinEmojiChain(uint friendUin, uint emojiId, uint targetMessageSeq) + { + string? friendUid = await Collection.Business.CachingLogic.ResolveUid(null, friendUin); + if (friendUid == null) return false; + var friendJoinEmojiChainEvent = FriendJoinEmojiChainEvent.Create(targetMessageSeq, emojiId, friendUid); + var results = await Collection.Business.SendEvent(friendJoinEmojiChainEvent); + return results.Count != 0 && results[0].ResultCode == 0; + } } \ No newline at end of file diff --git a/Lagrange.Core/Internal/Event/Action/FriendJoinEmojiChainEvent.cs b/Lagrange.Core/Internal/Event/Action/FriendJoinEmojiChainEvent.cs new file mode 100644 index 000000000..1846f5048 --- /dev/null +++ b/Lagrange.Core/Internal/Event/Action/FriendJoinEmojiChainEvent.cs @@ -0,0 +1,14 @@ +namespace Lagrange.Core.Internal.Event.Action; + +internal class FriendJoinEmojiChainEvent : JoinEmojiChainEvent +{ + private FriendJoinEmojiChainEvent(uint targetMessageSeq, uint targetFaceId, string friendUid) : base(targetMessageSeq, targetFaceId) + { + FriendUid = friendUid; + } + + private FriendJoinEmojiChainEvent(int resultCode) : base(resultCode) { } + + public static FriendJoinEmojiChainEvent Create(uint targetMessageSeq, uint targetFaceId, string friendUid) + => new(targetMessageSeq, targetFaceId, friendUid); +} \ No newline at end of file diff --git a/Lagrange.Core/Internal/Event/Action/GroupJoinEmojiChainEvent.cs b/Lagrange.Core/Internal/Event/Action/GroupJoinEmojiChainEvent.cs new file mode 100644 index 000000000..8f58544ec --- /dev/null +++ b/Lagrange.Core/Internal/Event/Action/GroupJoinEmojiChainEvent.cs @@ -0,0 +1,14 @@ +namespace Lagrange.Core.Internal.Event.Action; + +internal class GroupJoinEmojiChainEvent : JoinEmojiChainEvent +{ + private GroupJoinEmojiChainEvent(uint targetMessageSeq, uint targetFaceId, uint groupUin) : base(targetMessageSeq, targetFaceId) + { + GroupUin = groupUin; + } + + private GroupJoinEmojiChainEvent(int resultCode) : base(resultCode) { } + + public static GroupJoinEmojiChainEvent Create(uint targetMessageSeq, uint targetFaceId, uint groupUin) + => new(targetMessageSeq, targetFaceId, groupUin); +} diff --git a/Lagrange.Core/Internal/Event/Action/JoinEmojiChainEvent.cs b/Lagrange.Core/Internal/Event/Action/JoinEmojiChainEvent.cs new file mode 100644 index 000000000..7f0c0d74b --- /dev/null +++ b/Lagrange.Core/Internal/Event/Action/JoinEmojiChainEvent.cs @@ -0,0 +1,22 @@ +namespace Lagrange.Core.Internal.Event.Action; + +internal class JoinEmojiChainEvent : ProtocolEvent +{ + public uint TargetMessageSeq { get; set; } + + public uint TargetFaceId { get; set; } + + public uint? GroupUin { get; set; } + + public string? FriendUid { get; set; } + + protected JoinEmojiChainEvent(uint targetMessageSeq, uint targetFaceId) : base(true) + { + TargetMessageSeq = targetMessageSeq; + TargetFaceId = targetFaceId; + } + + protected JoinEmojiChainEvent(int resultCode) : base(resultCode) { } + + public static JoinEmojiChainEvent Result(int resultCode) => new(resultCode); +} diff --git a/Lagrange.Core/Internal/Event/System/FetchFullSysFacesEvent.cs b/Lagrange.Core/Internal/Event/System/FetchFullSysFacesEvent.cs new file mode 100644 index 000000000..71c64950d --- /dev/null +++ b/Lagrange.Core/Internal/Event/System/FetchFullSysFacesEvent.cs @@ -0,0 +1,22 @@ +using Lagrange.Core.Common.Entity; + +namespace Lagrange.Core.Internal.Event.System; + +internal class FetchFullSysFacesEvent : ProtocolEvent +{ + public List FacePacks { get; set; } + + private FetchFullSysFacesEvent(List facePacks) : base(true) + { + FacePacks = facePacks; + } + + private FetchFullSysFacesEvent(int resultCode, List facePacks) : base(resultCode) + { + FacePacks = facePacks; + } + + public static FetchFullSysFacesEvent Create() => new(new List()); + + public static FetchFullSysFacesEvent Result(int resultCode, List emojiPacks) => new(resultCode, emojiPacks); +} \ No newline at end of file diff --git a/Lagrange.Core/Internal/Packets/Message/Element/Implementation/Extra/QFaceExtra.cs b/Lagrange.Core/Internal/Packets/Message/Element/Implementation/Extra/QBigFaceExtra.cs similarity index 70% rename from Lagrange.Core/Internal/Packets/Message/Element/Implementation/Extra/QFaceExtra.cs rename to Lagrange.Core/Internal/Packets/Message/Element/Implementation/Extra/QBigFaceExtra.cs index 49c4d4a12..db7a9defa 100644 --- a/Lagrange.Core/Internal/Packets/Message/Element/Implementation/Extra/QFaceExtra.cs +++ b/Lagrange.Core/Internal/Packets/Message/Element/Implementation/Extra/QBigFaceExtra.cs @@ -6,17 +6,17 @@ namespace Lagrange.Core.Internal.Packets.Message.Element.Implementation.Extra; /// Constructed at , Service Type 33, Big face /// [ProtoContract] -internal class QFaceExtra +internal class QBigFaceExtra { - [ProtoMember(1)] public string? Field1 { get; set; } + [ProtoMember(1)] public string? AniStickerPackId { get; set; } - [ProtoMember(2)] public string? Field2 { get; set; } + [ProtoMember(2)] public string? AniStickerId { get; set; } [ProtoMember(3)] public int? FaceId { get; set; } // 318 [ProtoMember(4)] public int? Field4 { get; set; } - [ProtoMember(5)] public int? Field5 { get; set; } + [ProtoMember(5)] public int? AniStickerType { get; set; } [ProtoMember(6)] public string? Field6 { get; set; } diff --git a/Lagrange.Core/Internal/Packets/Message/Element/Implementation/Extra/QSmallFaceExtra.cs b/Lagrange.Core/Internal/Packets/Message/Element/Implementation/Extra/QSmallFaceExtra.cs index 4c53d714a..749dcd9c1 100644 --- a/Lagrange.Core/Internal/Packets/Message/Element/Implementation/Extra/QSmallFaceExtra.cs +++ b/Lagrange.Core/Internal/Packets/Message/Element/Implementation/Extra/QSmallFaceExtra.cs @@ -1,15 +1,16 @@ using ProtoBuf; - -#pragma warning disable CS8618 namespace Lagrange.Core.Internal.Packets.Message.Element.Implementation.Extra; +/// +/// Constructed at , Service Type 33, Small face (FaceId >= 260) +/// [ProtoContract] internal class QSmallFaceExtra { [ProtoMember(1)] public uint FaceId { get; set; } - - [ProtoMember(2)] public string Preview { get; set; } - - [ProtoMember(3)] public string Preview2 { get; set; } + + [ProtoMember(2)] public string? Text { get; set; } + + [ProtoMember(3)] public string? CompatText { get; set; } } \ No newline at end of file diff --git a/Lagrange.Core/Internal/Packets/Service/Oidb/Request/OidbSvcTrpcTcp.0x90EE_1.cs b/Lagrange.Core/Internal/Packets/Service/Oidb/Request/OidbSvcTrpcTcp.0x90EE_1.cs new file mode 100644 index 000000000..0ca6e733d --- /dev/null +++ b/Lagrange.Core/Internal/Packets/Service/Oidb/Request/OidbSvcTrpcTcp.0x90EE_1.cs @@ -0,0 +1,24 @@ +using ProtoBuf; + +#pragma warning disable CS8618 +// ReSharper disable InconsistentNaming + +namespace Lagrange.Core.Internal.Packets.Service.Oidb.Request; + +[ProtoContract] +[OidbSvcTrpcTcp(0x90EE, 1)] +internal class OidbSvcTrpcTcp0x90EE_1 +{ + [ProtoMember(1)] public uint FaceId { get; set; } + + [ProtoMember(2)] public uint TargetMsgSeq { get; set; } + + [ProtoMember(3)] public uint TargetMsgSeq_2 { get; set; } + + [ProtoMember(4)] public int Field4 { get; set; } // group 2 friend 1 ? + + [ProtoMember(5)] public uint? TargetGroupId { get; set; } + + [ProtoMember(6)] public string? TargetUid { get; set; } + +} \ No newline at end of file diff --git a/Lagrange.Core/Internal/Packets/Service/Oidb/Request/OidbSvcTrpcTcp0x9154_1.cs b/Lagrange.Core/Internal/Packets/Service/Oidb/Request/OidbSvcTrpcTcp0x9154_1.cs new file mode 100644 index 000000000..09c246d12 --- /dev/null +++ b/Lagrange.Core/Internal/Packets/Service/Oidb/Request/OidbSvcTrpcTcp0x9154_1.cs @@ -0,0 +1,17 @@ +using ProtoBuf; + +#pragma warning disable CS8618 +// ReSharper disable InconsistentNaming + +namespace Lagrange.Core.Internal.Packets.Service.Oidb.Request; + +[ProtoContract] +[OidbSvcTrpcTcp(0x9154, 1)] +internal class OidbSvcTrpcTcp0x9154_1 +{ + [ProtoMember(1)] public int Field1 { get; set; } // 0 + + [ProtoMember(2)] public int Field2 { get; set; } // 7 + + [ProtoMember(3)] public string Field3 { get; set; } // 0 +} \ No newline at end of file diff --git a/Lagrange.Core/Internal/Packets/Service/Oidb/Response/OidbSvcTrpcTcp0x9154_1Response.cs b/Lagrange.Core/Internal/Packets/Service/Oidb/Response/OidbSvcTrpcTcp0x9154_1Response.cs new file mode 100644 index 000000000..a29ce92dd --- /dev/null +++ b/Lagrange.Core/Internal/Packets/Service/Oidb/Response/OidbSvcTrpcTcp0x9154_1Response.cs @@ -0,0 +1,84 @@ +using ProtoBuf; + +#pragma warning disable CS8618 +// Resharper disable InconsistentNaming + +namespace Lagrange.Core.Internal.Packets.Service.Oidb.Response; + +[ProtoContract] +internal class OidbSvcTrpcTcp0x9154_1Response +{ + [ProtoMember(1)] public int Field1 { get; set; } + + [ProtoMember(2)] public OidbSvcTrpcTcp0x9154_1ResponseContent CommonFace { get; set; } + + [ProtoMember(3)] public OidbSvcTrpcTcp0x9154_1ResponseContent SpecialBigFace { get; set; } + + [ProtoMember(4)] public OidbSvcTrpcTcp0x9154_1ResponsesMagicEmojiContent SpecialMagicFace { get; set; } +} + +[ProtoContract] +internal class OidbSvcTrpcTcp0x9154_1ResponseContent +{ + [ProtoMember(1)] public OidbSvcTrpcTcp0x9154_1ResponseContentEmojiList[] EmojiList { get; set; } + + [ProtoMember(2)] public OidbSvcTrpcTcp0x9154_1ResponseContentResourceUrl? ResourceUrl { get; set; } +} + +[ProtoContract] +internal class OidbSvcTrpcTcp0x9154_1ResponsesMagicEmojiContent +{ + [ProtoMember(1)] public OidbSvcTrpcTcp0x9154_1ResponsesMagicEmojiContentList Field1 { get; set; } + + [ProtoMember(2)] public OidbSvcTrpcTcp0x9154_1ResponseContentResourceUrl? ResourceUrl { get; set; } +} + +[ProtoContract] +internal class OidbSvcTrpcTcp0x9154_1ResponsesMagicEmojiContentList +{ + [ProtoMember(2)] public OidbSvcTrpcTcp0x9154_1ResponseContentEmoji[] EmojiList { get; set; } +} + +[ProtoContract] +internal class OidbSvcTrpcTcp0x9154_1ResponseContentEmojiList +{ + [ProtoMember(1)] public string EmojiPackName { get; set; } + + [ProtoMember(2)] public OidbSvcTrpcTcp0x9154_1ResponseContentEmoji[] EmojiDetail { get; set; } +} + +[ProtoContract] +internal class OidbSvcTrpcTcp0x9154_1ResponseContentEmoji +{ + [ProtoMember(1)] public string QSid { get; set; } + + [ProtoMember(2)] public string? QDes { get; set; } + + [ProtoMember(3)] public string? EMCode { get; set; } + + [ProtoMember(4)] public int? QCid { get; set; } + + [ProtoMember(5)] public int? AniStickerType { get; set; } + + [ProtoMember(6)] public int? AniStickerPackId { get; set; } + + [ProtoMember(7)] public int? AniStickerId { get; set; } + + [ProtoMember(8)] public OidbSvcTrpcTcp0x9154_1ResponseContentResourceUrl? Url { get; set; } + + [ProtoMember(9)] public string[]? EmojiNameAlias { get; set; } + + [ProtoMember(10)] public int? Unknown10 { get; set; } + + [ProtoMember(13)] public int? AniStickerWidth { get; set; } + + [ProtoMember(14)] public int? AniStickerHeight { get; set; } +} + +[ProtoContract] +internal class OidbSvcTrpcTcp0x9154_1ResponseContentResourceUrl +{ + [ProtoMember(1)] public string? BaseUrl { get; set; } + + [ProtoMember(2)] public string? AdvUrl { get; set; } +} \ No newline at end of file diff --git a/Lagrange.Core/Internal/Service/Action/JoinEmojiChainService.cs b/Lagrange.Core/Internal/Service/Action/JoinEmojiChainService.cs new file mode 100644 index 000000000..4364dcd4d --- /dev/null +++ b/Lagrange.Core/Internal/Service/Action/JoinEmojiChainService.cs @@ -0,0 +1,41 @@ +using Lagrange.Core.Common; +using Lagrange.Core.Internal.Event; +using Lagrange.Core.Internal.Event.Action; +using Lagrange.Core.Internal.Packets.Service.Oidb; +using Lagrange.Core.Internal.Packets.Service.Oidb.Request; +using Lagrange.Core.Utility.Extension; +using ProtoBuf; + +namespace Lagrange.Core.Internal.Service.Action; + +[EventSubscribe(typeof(GroupJoinEmojiChainEvent))] +[EventSubscribe(typeof(FriendJoinEmojiChainEvent))] +[Service("OidbSvcTrpcTcp.0x90ee_1")] +internal class JoinEmojiChainService : BaseService +{ + protected override bool Build(JoinEmojiChainEvent input, BotKeystore keystore, BotAppInfo appInfo, + BotDeviceInfo device, out Span output, out List>? extraPackets) + { + var packet = new OidbSvcTrpcTcpBase(new OidbSvcTrpcTcp0x90EE_1 + { + FaceId = input.TargetFaceId, + TargetMsgSeq = input.TargetMessageSeq, + TargetMsgSeq_2 = input.TargetMessageSeq, + Field4 = input.GroupUin == null ? 1 : 2, + TargetGroupId = input.GroupUin, + TargetUid = input.FriendUid, + }); + output = packet.Serialize(); + extraPackets = null; + return true; + } + + protected override bool Parse(Span input, BotKeystore keystore, BotAppInfo appInfo, BotDeviceInfo device, + out JoinEmojiChainEvent output, out List? extraEvents) + { + var payload = Serializer.Deserialize>(input); + output = JoinEmojiChainEvent.Result((int)payload.ErrorCode); + extraEvents = null; + return true; + } +} \ No newline at end of file diff --git a/Lagrange.Core/Internal/Service/System/FetchFullSysFacesService.cs b/Lagrange.Core/Internal/Service/System/FetchFullSysFacesService.cs new file mode 100644 index 000000000..681c12cc5 --- /dev/null +++ b/Lagrange.Core/Internal/Service/System/FetchFullSysFacesService.cs @@ -0,0 +1,68 @@ +using Lagrange.Core.Common; +using Lagrange.Core.Common.Entity; +using Lagrange.Core.Internal.Event; +using Lagrange.Core.Internal.Event.System; +using Lagrange.Core.Internal.Packets.Service.Oidb; +using Lagrange.Core.Internal.Packets.Service.Oidb.Request; +using Lagrange.Core.Internal.Packets.Service.Oidb.Response; +using Lagrange.Core.Utility.Extension; +using ProtoBuf; + +namespace Lagrange.Core.Internal.Service.System; + +// TODO: onebot11 API (? +[EventSubscribe(typeof(FetchFullSysFacesEvent))] +[Service("OidbSvcTrpcTcp.0x9154_1")] +internal class FetchFullSysFacesService : BaseService +{ + protected override bool Build(FetchFullSysFacesEvent input, BotKeystore keystore, BotAppInfo appInfo, + BotDeviceInfo device, out Span output, out List>? extraPackets) + { + var packet = new OidbSvcTrpcTcpBase(new OidbSvcTrpcTcp0x9154_1 + { + Field1 = 0, + Field2 = 7, + Field3 = "0", + }); + + output = packet.Serialize(); + extraPackets = null; + return true; + } + + protected override bool Parse(Span input, BotKeystore keystore, BotAppInfo appInfo, BotDeviceInfo device, + out FetchFullSysFacesEvent output, out List? extraEvents) + { + var packet = Serializer.Deserialize>(input); + var response = packet.Body; + + var emojiPackList = new[] { response.CommonFace, response.SpecialBigFace } + .SelectMany(content => content.EmojiList) + .Select( + emojiList => new SysFacePackEntry( + emojiList.EmojiPackName, emojiList.EmojiDetail.Select( + emoji => new SysFaceEntry( + emoji.QSid, emoji.QDes, emoji.EMCode, emoji.QCid, emoji.AniStickerType, + emoji.AniStickerPackId, emoji.AniStickerId, emoji.Url?.BaseUrl, + emoji.EmojiNameAlias, emoji.AniStickerWidth, emoji.AniStickerHeight + ) + ).ToArray() + ) + ).ToList(); + + var magicFaceList = response.SpecialMagicFace.Field1.EmojiList.Select( + emoji => new SysFaceEntry( + emoji.QSid, emoji.QDes, emoji.EMCode, emoji.QCid, emoji.AniStickerType, + emoji.AniStickerPackId, emoji.AniStickerId, emoji.Url?.BaseUrl, + emoji.EmojiNameAlias, emoji.AniStickerWidth, emoji.AniStickerHeight + ) + ).ToList(); + + var magicFacePackEntry = new SysFacePackEntry("MagicFace", magicFaceList.ToArray()); + emojiPackList.Add(magicFacePackEntry); + + output = FetchFullSysFacesEvent.Result((int)packet.ErrorCode, emojiPackList); + extraEvents = null; + return true; + } +} \ No newline at end of file diff --git a/Lagrange.Core/Message/Entity/FaceEntity.cs b/Lagrange.Core/Message/Entity/FaceEntity.cs index 0e56d6279..941f1b6d8 100644 --- a/Lagrange.Core/Message/Entity/FaceEntity.cs +++ b/Lagrange.Core/Message/Entity/FaceEntity.cs @@ -1,3 +1,4 @@ +using Lagrange.Core.Common.Entity; using Lagrange.Core.Internal.Packets.Message.Element; using Lagrange.Core.Internal.Packets.Message.Element.Implementation; using Lagrange.Core.Internal.Packets.Message.Element.Implementation.Extra; @@ -10,11 +11,13 @@ public class FaceEntity : IMessageEntity { public ushort FaceId { get; set; } - public bool IsLargeFace { get; set; } + public bool? IsLargeFace { get; set; } + + public SysFaceEntry? SysFaceEntry { get; set; } public FaceEntity() { } - public FaceEntity(ushort faceId, bool isLargeFace) + public FaceEntity(ushort faceId, bool? isLargeFace) { FaceId = faceId; IsLargeFace = isLargeFace; @@ -22,22 +25,21 @@ public FaceEntity(ushort faceId, bool isLargeFace) IEnumerable IMessageEntity.PackElement() { - if (IsLargeFace) + if (IsLargeFace ?? false) { - var qFace = new QFaceExtra + var qBigFace = new QBigFaceExtra { - Field1 = "1", - Field2 = "8", + AniStickerPackId = SysFaceEntry?.AniStickerPackId.ToString() ?? "1", + AniStickerId = SysFaceEntry?.AniStickerId.ToString() ?? "8", FaceId = FaceId, Field4 = 1, - Field5 = 1, + AniStickerType = SysFaceEntry?.AniStickerType ?? 1, Field6 = "", - Preview = "", + Preview = SysFaceEntry?.QDes ?? "", Field9 = 1 }; using var stream = new MemoryStream(); - Serializer.Serialize(stream, qFace); - + Serializer.Serialize(stream, qBigFace); return new Elem[] { new() @@ -46,12 +48,36 @@ IEnumerable IMessageEntity.PackElement() { ServiceType = 37, PbElem = stream.ToArray(), - BusinessType = 1 + BusinessType = (uint)(SysFaceEntry?.AniStickerType ?? 1) } } }; } - + + if (FaceId >= 260) + { + var qSmallFace = new QSmallFaceExtra + { + FaceId = FaceId, + Text = SysFaceEntry?.QDes ?? "", + CompatText = SysFaceEntry?.QDes ?? "" + }; + using var stream = new MemoryStream(); + Serializer.Serialize(stream, qSmallFace); + return new Elem[] + { + new() + { + CommonElem = new CommonElem + { + ServiceType = 33, + PbElem = stream.ToArray(), + BusinessType = (uint)(SysFaceEntry?.AniStickerType ?? 1) + } + } + }; + } + return new Elem[] { new() { Face = new Face { Index = FaceId } } }; } @@ -63,10 +89,10 @@ IEnumerable IMessageEntity.PackElement() if (faceId != null) return new FaceEntity((ushort)faceId, false); } - if (elems.CommonElem is { ServiceType: 37, PbElem: not null } common) + if (elems.CommonElem is { ServiceType:37, PbElem: not null } common) { - var qFace = Serializer.Deserialize(common.PbElem.AsSpan()); - + var qFace = Serializer.Deserialize(common.PbElem.AsSpan()); + ushort? faceId = (ushort?)qFace.FaceId; if (faceId != null) return new FaceEntity((ushort)faceId, true); } @@ -76,9 +102,9 @@ IEnumerable IMessageEntity.PackElement() var qSmallFace = Serializer.Deserialize(append.PbElem.AsSpan()); return new FaceEntity((ushort)qSmallFace.FaceId, false); } - + return null; } - public string ToPreviewString() => $"[Face][{(IsLargeFace ? "Large" : "Small")}]: {FaceId}"; + public string ToPreviewString() => $"[Face][{(IsLargeFace ?? false ? "Large" : "Small")}]: {FaceId}"; } \ No newline at end of file diff --git a/Lagrange.Core/Message/MessageBuilder.cs b/Lagrange.Core/Message/MessageBuilder.cs index 5bf5fc34d..a20a5cd3b 100644 --- a/Lagrange.Core/Message/MessageBuilder.cs +++ b/Lagrange.Core/Message/MessageBuilder.cs @@ -102,7 +102,7 @@ public MessageBuilder Mention(uint target, string? display = null) /// /// The id of emoji /// Is the emoji large - public MessageBuilder Face(ushort id, bool isLarge = false) + public MessageBuilder Face(ushort id, bool? isLarge = false) { var faceEntity = new FaceEntity(id, isLarge); _chain.Add(faceEntity); diff --git a/Lagrange.OneBot/Core/Entity/Action/OneBotGroupJoinEmojiChain.cs b/Lagrange.OneBot/Core/Entity/Action/OneBotGroupJoinEmojiChain.cs new file mode 100644 index 000000000..9adf71032 --- /dev/null +++ b/Lagrange.OneBot/Core/Entity/Action/OneBotGroupJoinEmojiChain.cs @@ -0,0 +1,11 @@ +using System.Text.Json.Serialization; +namespace Lagrange.OneBot.Core.Entity.Action; + +public class OneBotGroupJoinEmojiChain +{ + [JsonPropertyName("group_id")] public uint GroupId { get; set; } + + [JsonPropertyName("message_id")] public int MessageId { get; set; } + + [JsonPropertyName("emoji_id")] public uint EmojiId { get; set; } +} \ No newline at end of file diff --git a/Lagrange.OneBot/Core/Entity/Action/OneBotPrivateJoinEmojiChain.cs b/Lagrange.OneBot/Core/Entity/Action/OneBotPrivateJoinEmojiChain.cs new file mode 100644 index 000000000..47b44fd05 --- /dev/null +++ b/Lagrange.OneBot/Core/Entity/Action/OneBotPrivateJoinEmojiChain.cs @@ -0,0 +1,11 @@ +using System.Text.Json.Serialization; +namespace Lagrange.OneBot.Core.Entity.Action; + +public class OneBotPrivateJoinEmojiChain +{ + [JsonPropertyName("user_id")] public uint UserId { get; set; } + + [JsonPropertyName("message_id")] public int MessageId { get; set; } + + [JsonPropertyName("emoji_id")] public uint EmojiId { get; set; } +} \ No newline at end of file diff --git a/Lagrange.OneBot/Core/Operation/Generic/FriendJoinEmojiChainOperation.cs b/Lagrange.OneBot/Core/Operation/Generic/FriendJoinEmojiChainOperation.cs new file mode 100644 index 000000000..e6b17db93 --- /dev/null +++ b/Lagrange.OneBot/Core/Operation/Generic/FriendJoinEmojiChainOperation.cs @@ -0,0 +1,27 @@ +using System.Text.Json; +using System.Text.Json.Nodes; +using Lagrange.Core; +using Lagrange.Core.Message; +using Lagrange.Core.Common.Interface.Api; +using Lagrange.OneBot.Core.Entity.Action; +using Lagrange.OneBot.Core.Operation.Converters; +using Lagrange.OneBot.Database; +using LiteDB; + +namespace Lagrange.OneBot.Core.Operation.Generic; + + +[Operation(".join_friend_emoji_chain")] +public class FriendJoinEmojiChainOperation(LiteDatabase database) : IOperation +{ + public async Task HandleOperation(BotContext context, JsonNode? payload) + { + if (payload.Deserialize(SerializerOptions.DefaultOptions) is { } data) + { + var message = (MessageChain)database.GetCollection().FindById(data.MessageId); + bool res = await context.FriendJoinEmojiChain(data.UserId, data.EmojiId, message.Sequence); + return new OneBotResult(null, res ? 0 : -1, res ? "ok" : "failed"); + } + throw new Exception(); + } +} diff --git a/Lagrange.OneBot/Core/Operation/Generic/GroupJoinEmojiChainOperation.cs b/Lagrange.OneBot/Core/Operation/Generic/GroupJoinEmojiChainOperation.cs new file mode 100644 index 000000000..71638e322 --- /dev/null +++ b/Lagrange.OneBot/Core/Operation/Generic/GroupJoinEmojiChainOperation.cs @@ -0,0 +1,27 @@ +using System.Text.Json; +using System.Text.Json.Nodes; +using Lagrange.Core; +using Lagrange.Core.Message; +using Lagrange.Core.Common.Interface.Api; +using Lagrange.OneBot.Core.Entity.Action; +using Lagrange.OneBot.Core.Operation.Converters; +using Lagrange.OneBot.Database; +using LiteDB; + +namespace Lagrange.OneBot.Core.Operation.Generic; + + +[Operation(".join_group_emoji_chain")] +public class GroupJoinEmojiChainOperation(LiteDatabase database) : IOperation +{ + public async Task HandleOperation(BotContext context, JsonNode? payload) + { + if (payload.Deserialize(SerializerOptions.DefaultOptions) is { } data) + { + var message = (MessageChain)database.GetCollection().FindById(data.MessageId); + bool res = await context.GroupJoinEmojiChain(data.GroupId, data.EmojiId, message.Sequence); + return new OneBotResult(null, res ? 0 : -1, res ? "ok" : "failed"); + } + throw new Exception(); + } +} \ No newline at end of file diff --git a/Lagrange.OneBot/Message/Entity/FaceSegment.cs b/Lagrange.OneBot/Message/Entity/FaceSegment.cs index 3e2f5d2cc..4fa52beea 100644 --- a/Lagrange.OneBot/Message/Entity/FaceSegment.cs +++ b/Lagrange.OneBot/Message/Entity/FaceSegment.cs @@ -10,6 +10,9 @@ public partial class FaceSegment(int id) public FaceSegment() : this(0) { } [JsonPropertyName("id")] [CQProperty] public string Id { get; set; } = id.ToString(); + + [JsonPropertyName("large")] [CQProperty] public bool? IsLarge { get; set; } + } [SegmentSubscriber(typeof(FaceEntity), "face")] @@ -19,7 +22,7 @@ public partial class FaceSegment : SegmentBase public override void Build(MessageBuilder builder, SegmentBase segment) { - if (segment is FaceSegment faceSegment) builder.Face(ushort.Parse(faceSegment.Id)); + if (segment is FaceSegment faceSegment) builder.Face(ushort.Parse(faceSegment.Id), faceSegment.IsLarge); } public override SegmentBase? FromEntity(MessageChain chain, IMessageEntity entity) From 946891c658f62abab4a9cf3da15080ad3baf37ab Mon Sep 17 00:00:00 2001 From: DarkRRb <177549718+DarkRRb@users.noreply.github.com> Date: Wed, 23 Oct 2024 18:50:07 +0800 Subject: [PATCH 17/19] [Core] More visible and easy-to-understand indexing-in and indexing-complete prompts (#656) * More visible and easy-to-understand indexing-in and indexing-complete prompts * Update LagrangeAppBuilder.cs * Update LagrangeAppBuilder.cs --- Lagrange.OneBot/LagrangeAppBuilder.cs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Lagrange.OneBot/LagrangeAppBuilder.cs b/Lagrange.OneBot/LagrangeAppBuilder.cs index a190db713..11bb6e864 100644 --- a/Lagrange.OneBot/LagrangeAppBuilder.cs +++ b/Lagrange.OneBot/LagrangeAppBuilder.cs @@ -111,6 +111,7 @@ public LagrangeAppBuilder ConfigureOneBot() return services.GetRequiredService().Create() ?? throw new Exception("Invalid conf detected"); }); + // Database Services.AddSingleton(provider => { var logger = provider.GetRequiredService>(); @@ -120,6 +121,9 @@ public LagrangeAppBuilder ConfigureOneBot() string path = Configuration["ConfigPath:Database"] ?? $"lagrange-{Configuration["Account:Uin"]}.db"; + bool isFirstCreate = false; + if (!File.Exists(path)) isFirstCreate = true; + var db = new LiteDatabase(path) { CheckpointSize = 50 @@ -135,7 +139,7 @@ public LagrangeAppBuilder ConfigureOneBot() logger.LogWarning("In the database index"); logger.LogWarning("Depending on the size of the database will consume some time and memory"); - logger.LogWarning("Please restart the program after indexing is complete"); + logger.LogWarning("Not yet finished, please wait..."); hasFirstIndex = true; break; @@ -147,14 +151,14 @@ public LagrangeAppBuilder ConfigureOneBot() records.EnsureIndex(BsonExpression.Create(expression)); } - if (hasFirstIndex) + // Skipping the first database creation is a restart after indexing + if (!isFirstCreate && hasFirstIndex) { db.Dispose(); // Ensure that the database is written correctly - logger.LogWarning("Indexing complete, please restart the program"); + logger.LogInformation("Indexing Complete! Press any key to close and restart the program manually!"); Console.ReadKey(true); Environment.Exit(0); } - return db; }); Services.AddSingleton(); From b5857eb46feb7a4e3423a4e1194572ca9760d1f7 Mon Sep 17 00:00:00 2001 From: dogdie233 Date: Thu, 24 Oct 2024 15:30:14 +0900 Subject: [PATCH 18/19] [Core] parse markdown entity (#658) * add: parse markdown entity * fix: exception throw when preview markdown string --- Lagrange.Core/Message/Entity/MarkdownEntity.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/Lagrange.Core/Message/Entity/MarkdownEntity.cs b/Lagrange.Core/Message/Entity/MarkdownEntity.cs index 8a1d16dfd..95dfab842 100644 --- a/Lagrange.Core/Message/Entity/MarkdownEntity.cs +++ b/Lagrange.Core/Message/Entity/MarkdownEntity.cs @@ -7,6 +7,7 @@ namespace Lagrange.Core.Message.Entity; +[MessageElement(typeof(CommonElem))] public class MarkdownEntity : IMessageEntity { public MarkdownData Data { get; set; } @@ -30,9 +31,18 @@ public class MarkdownEntity : IMessageEntity } }; - IMessageEntity? IMessageEntity.UnpackElement(Elem elem) => null; + IMessageEntity? IMessageEntity.UnpackElement(Elem elem) + { + if (elem.CommonElem?.ServiceType != 45 || elem.CommonElem?.BusinessType != 1) + return null; + + return new MarkdownEntity(Serializer.Deserialize(elem.CommonElem.PbElem.AsSpan())); + } - public string ToPreviewString() => throw new NotImplementedException(); + public string ToPreviewString() + { + return $"[Markdown] {Data.Content}"; + } } [ProtoContract] From 7815fc83cac8d777e0f3d45b14a22988aae37618 Mon Sep 17 00:00:00 2001 From: DarkRRb <177549718+DarkRRb@users.noreply.github.com> Date: Sun, 27 Oct 2024 20:03:24 +0800 Subject: [PATCH 19/19] [Core] Support sending with group reaction (#659) Co-authored-by: Decrabbityyy <99632363+Decrabbityyy@users.noreply.github.com> --- .../Common/Entity/BotGroupReaction.cs | 20 ++++++ .../Extra/GroupReactionExtra.cs | 41 ++++++++++++ .../Message/Entity/GroupReactionEntity.cs | 67 +++++++++++++++++++ 3 files changed, 128 insertions(+) create mode 100644 Lagrange.Core/Common/Entity/BotGroupReaction.cs create mode 100644 Lagrange.Core/Internal/Packets/Message/Element/Implementation/Extra/GroupReactionExtra.cs create mode 100644 Lagrange.Core/Message/Entity/GroupReactionEntity.cs diff --git a/Lagrange.Core/Common/Entity/BotGroupReaction.cs b/Lagrange.Core/Common/Entity/BotGroupReaction.cs new file mode 100644 index 000000000..ec0ebdff8 --- /dev/null +++ b/Lagrange.Core/Common/Entity/BotGroupReaction.cs @@ -0,0 +1,20 @@ +namespace Lagrange.Core.Common.Entity; + +public class BotGroupReaction +{ + public string FaceId { get; set; } + + public uint Type { get; set; } + + public uint Count { get; set; } + + public bool IsAdded { get; set; } + + public BotGroupReaction(string faceId, uint type, uint count, bool isAdded) + { + FaceId = faceId; + Type = type; + Count = count; + IsAdded = isAdded; + } +} \ No newline at end of file diff --git a/Lagrange.Core/Internal/Packets/Message/Element/Implementation/Extra/GroupReactionExtra.cs b/Lagrange.Core/Internal/Packets/Message/Element/Implementation/Extra/GroupReactionExtra.cs new file mode 100644 index 000000000..7973ffffe --- /dev/null +++ b/Lagrange.Core/Internal/Packets/Message/Element/Implementation/Extra/GroupReactionExtra.cs @@ -0,0 +1,41 @@ +#pragma warning disable CS8618 + +using ProtoBuf; + +namespace Lagrange.Core.Internal.Packets.Message.Element.Implementation.Extra; + +[ProtoContract] +internal class GroupReactionExtra +{ + [ProtoMember(1)] public GroupReactionExtraBody Body { get; set; } +} + +[ProtoContract] +internal class GroupReactionExtraBody +{ + [ProtoMember(1)] public GroupReactionExtraBodyField1 Field1 { get; set; } + + [ProtoMember(2)] public GroupReactionExtraFaceInfo[] FaceInfos { get; set; } +} + +[ProtoContract] +internal class GroupReactionExtraBodyField1 +{ + [ProtoMember(1)] public uint Field1 { get; set; } + + [ProtoMember(2)] public uint Field2 { get; set; } +} + +[ProtoContract] +internal class GroupReactionExtraFaceInfo +{ + // See Lagrange.Core/Internal/Service/System/FetchFullSysFacesService.cs + [ProtoMember(1)] public string FaceId { get; set; } + + // See Lagrange.Core/Internal/Service/System/FetchFullSysFacesService.cs + [ProtoMember(2)] public uint Type { get; set; } + + [ProtoMember(3)] public uint Count { get; set; } + + [ProtoMember(4)] public uint IsAdded { get; set; } +} \ No newline at end of file diff --git a/Lagrange.Core/Message/Entity/GroupReactionEntity.cs b/Lagrange.Core/Message/Entity/GroupReactionEntity.cs new file mode 100644 index 000000000..4944a44c2 --- /dev/null +++ b/Lagrange.Core/Message/Entity/GroupReactionEntity.cs @@ -0,0 +1,67 @@ +using Lagrange.Core.Common.Entity; +using Lagrange.Core.Internal.Packets.Message.Element; +using Lagrange.Core.Internal.Packets.Message.Element.Implementation; +using Lagrange.Core.Internal.Packets.Message.Element.Implementation.Extra; +using ProtoBuf; + +namespace Lagrange.Core.Message.Entity; + +[MessageElement(typeof(CommonElem))] +public class GroupReactionEntity : IMessageEntity +{ + private readonly IEnumerable _reactions; + + public GroupReactionEntity() { _reactions = Array.Empty(); } + + public GroupReactionEntity(IEnumerable reactions) + { + _reactions = reactions; + } + + IEnumerable IMessageEntity.PackElement() + { + var infos = _reactions + .Select(reaction => new GroupReactionExtraFaceInfo() + { + FaceId = reaction.FaceId, + Type = reaction.Type, + Count = reaction.Count, + IsAdded = reaction.IsAdded ? 1u : 0u, + }) + .ToArray(); + + var extra = new GroupReactionExtra + { + Body = new() + { + Field1 = new() + { + Field1 = 0, + Field2 = 7240 + }, + FaceInfos = infos, + } + }; + using var stream = new MemoryStream(); + Serializer.Serialize(stream, extra); + + return new Elem[] { + new() { CommonElem = new() { + ServiceType = 38, + PbElem = stream.ToArray(), + BusinessType = 1 + } } + }; + } + + string IMessageEntity.ToPreviewString() + { + return ""; + } + + IMessageEntity? IMessageEntity.UnpackElement(Elem elem) + { + // TODO Parase + return null; + } +} \ No newline at end of file