diff --git a/Lagrange.Core/Common/Entity/BotFriend.cs b/Lagrange.Core/Common/Entity/BotFriend.cs index 379482157..84103ba19 100644 --- a/Lagrange.Core/Common/Entity/BotFriend.cs +++ b/Lagrange.Core/Common/Entity/BotFriend.cs @@ -12,15 +12,19 @@ internal BotFriend() Nickname = string.Empty; Remarks = string.Empty; PersonalSign = string.Empty; + GroupId = 0; + GroupName = string.Empty; } - internal BotFriend(uint uin,string uid, string nickname, string remarks, string personalSign) + internal BotFriend(uint uin,string uid, string nickname, string remarks, string personalSign, uint groupId, string groupName) { Uin = uin; Uid = uid; Nickname = nickname; Remarks = remarks; PersonalSign = personalSign; + GroupId = groupId; + GroupName = groupName; } public uint Uin { get; set; } @@ -33,5 +37,9 @@ internal BotFriend(uint uin,string uid, string nickname, string remarks, string public string PersonalSign { get; set; } + public uint GroupId { get; } + + public string GroupName { get; set; } + public string Avatar => $"https://q1.qlogo.cn/g?b=qq&nk={Uin}&s=640"; } \ No newline at end of file diff --git a/Lagrange.Core/Internal/Packets/Service/Oidb/Generics/OidbGroup.cs b/Lagrange.Core/Internal/Packets/Service/Oidb/Generics/OidbGroup.cs new file mode 100644 index 000000000..8dccd77ac --- /dev/null +++ b/Lagrange.Core/Internal/Packets/Service/Oidb/Generics/OidbGroup.cs @@ -0,0 +1,12 @@ +using ProtoBuf; +#pragma warning disable CS8618 + +namespace Lagrange.Core.Internal.Packets.Service.Oidb.Generics; + +[ProtoContract] +internal class OidbGroup +{ + [ProtoMember(1)] public uint GroupId { get; set; } + + [ProtoMember(2)] public string GroupName { get; set; } +} \ No newline at end of file diff --git a/Lagrange.Core/Internal/Packets/Service/Oidb/Response/OidbSvcTrpcTcp0xFD4_1Response.cs b/Lagrange.Core/Internal/Packets/Service/Oidb/Response/OidbSvcTrpcTcp0xFD4_1Response.cs index 383631951..edb53dc1d 100644 --- a/Lagrange.Core/Internal/Packets/Service/Oidb/Response/OidbSvcTrpcTcp0xFD4_1Response.cs +++ b/Lagrange.Core/Internal/Packets/Service/Oidb/Response/OidbSvcTrpcTcp0xFD4_1Response.cs @@ -10,14 +10,16 @@ namespace Lagrange.Core.Internal.Packets.Service.Oidb.Response; internal class OidbSvcTrpcTcp0xFD4_1Response { [ProtoMember(2)] public OidbSvcTrpcTcp0xFD4_1ResponseUin? Next { get; set; } - + [ProtoMember(3)] public uint DisplayFriendCount { get; set; } - + [ProtoMember(6)] public uint Timestamp { get; set; } - + [ProtoMember(7)] public uint SelfUin { get; set; } [ProtoMember(101)] public List Friends { get; set; } + + [ProtoMember(102)] public List Groups { get; set; } } [ProtoContract] diff --git a/Lagrange.Core/Internal/Service/System/FetchFriendsService.cs b/Lagrange.Core/Internal/Service/System/FetchFriendsService.cs index f613f9e3f..bc1f196df 100644 --- a/Lagrange.Core/Internal/Service/System/FetchFriendsService.cs +++ b/Lagrange.Core/Internal/Service/System/FetchFriendsService.cs @@ -17,7 +17,7 @@ namespace Lagrange.Core.Internal.Service.System; internal class FetchFriendsService : BaseService { private const int MaxFriendCount = 300; - + protected override bool Build(FetchFriendsEvent input, BotKeystore keystore, BotAppInfo appInfo, BotDeviceInfo device, out BinaryPacket output, out List? extraPackets) { @@ -32,14 +32,14 @@ protected override bool Build(FetchFriendsEvent input, BotKeystore keystore, Bot }); if (input.NextUin != null) packet.Body.NextUin = new OidbSvcTrpcTcp0xFD4_1Uin { Uin = input.NextUin.Value }; - + /* * OidbNumber里面的东西代表你想要拿到的Property,这些Property将会在返回的数据里面的Preserve的Field, * 102:个性签名 * 103:备注 * 20002:昵称 */ - + output = packet.Serialize(); extraPackets = null; return true; @@ -50,14 +50,22 @@ protected override bool Parse(Span input, BotKeystore keystore, BotAppInfo { var packet = Serializer.Deserialize>(input); - var friends = new List(); - foreach (var raw in packet.Body.Friends) + var groups = Group(packet.Body.Groups); + var friends = packet.Body.Friends.Select(f => { - var additional = raw.Additional.First(x => x.Type == 1); - var properties = Property(additional.Layer1.Properties); - friends.Add(new BotFriend(raw.Uin, raw.Uid, properties[20002], properties[103], properties[102])); - } - + var properties = Property(f.Additional.First(a => a.Type == 1).Layer1.Properties); + + return new BotFriend( + f.Uin, + f.Uid, + properties[20002], + properties[102], + properties[102], + f.CustomGroup, + groups[f.CustomGroup] + ); + }).ToList(); + output = FetchFriendsEvent.Result(0, friends, packet.Body.Next?.Uin); // 全家4完了才能想出来这种分页的逻辑 extraEvents = null; return true; @@ -65,8 +73,11 @@ protected override bool Parse(Span input, BotKeystore keystore, BotAppInfo private static Dictionary Property(List properties) { - var dict = new Dictionary(properties.Capacity); - foreach (var property in properties) dict[property.Code] = property.Value; - return dict; + return properties.ToDictionary(p => p.Code, p => p.Value); + } + + private static Dictionary Group(List groups) + { + return groups.ToDictionary(g => g.GroupId, g => g.GroupName); } } \ No newline at end of file diff --git a/Lagrange.Core/Message/MessagePacker.cs b/Lagrange.Core/Message/MessagePacker.cs index 0296b5937..2b3171b9c 100644 --- a/Lagrange.Core/Message/MessagePacker.cs +++ b/Lagrange.Core/Message/MessagePacker.cs @@ -25,7 +25,7 @@ internal static class MessagePacker { private static readonly Dictionary> EntityToElem; private static readonly Dictionary Factory; - + static MessagePacker() { EntityToElem = new Dictionary>(); @@ -34,7 +34,7 @@ static MessagePacker() var assembly = Assembly.GetExecutingAssembly(); var types = assembly.GetTypeWithMultipleAttributes(out var attributeArrays); var elemType = typeof(Elem); - + for (int i = 0; i < types.Count; i++) { var type = types[i]; @@ -73,12 +73,12 @@ public static Internal.Packets.Message.Message Build(MessageChain chain, string message.Body.MsgContent = stream.ToArray(); } } - + BuildAdditional(chain, message); return message; } - + public static PushMsgBody BuildFake(MessageChain chain, string selfUid) { var message = BuildFakePacketBase(chain, selfUid); @@ -87,7 +87,7 @@ public static PushMsgBody BuildFake(MessageChain chain, string selfUid) { entity.SetSelfUid(selfUid); message.Body?.RichText?.Elems.AddRange(entity.PackElement()); - + if (message.Body != null) { if (entity.PackMessageContent() is not { } content) continue; @@ -104,26 +104,26 @@ public static PushMsgBody BuildFake(MessageChain chain, string selfUid) private static void BuildAdditional(MessageChain chain, Internal.Packets.Message.Message message) { if (message.Body?.RichText == null) return; - + foreach (var entity in chain) { switch (entity) { case RecordEntity { Compat: { } compat }: // Append Tag 04 -> Ptt - { - message.Body.RichText.Ptt = compat.Ptt; - message.Body.RichText.Elems.AddRange(compat.Elems); - break; - } + { + message.Body.RichText.Ptt = compat.Ptt; + message.Body.RichText.Elems.AddRange(compat.Elems); + break; + } } } } - + public static MessageChain Parse(PushMsgBody message, bool isFake = false) { var chain = isFake ? ParseFakeChain(message) : ParseChain(message); - if (message.Body?.RichText is { Elems: { } elements}) // 怎么Body还能是null的 + if (message.Body?.RichText is { Elems: { } elements }) // 怎么Body还能是null的 { foreach (var element in elements) { @@ -131,7 +131,7 @@ public static MessageChain Parse(PushMsgBody message, bool isFake = false) { foreach (var expectElem in expectElems) { - if (expectElem.GetValueByExpr(element) is not null && + if (expectElem.GetValueByExpr(element) is not null && Factory[entityType].UnpackElement(element) is { } entity) { chain.Add(entity); @@ -147,8 +147,8 @@ public static MessageChain Parse(PushMsgBody message, bool isFake = false) case { } groupPtt when chain.IsGroup && groupPtt.FileId != 0: // for legacy ptt chain.Add(new RecordEntity(groupPtt.GroupFileKey, groupPtt.FileName)); break; - case { } privatePtt when !chain.IsGroup: - if (chain.OfType().FirstOrDefault(x => x.AudioName == privatePtt.FileName) == null) + case { } privatePtt when !chain.IsGroup: + if (chain.OfType().FirstOrDefault(x => x.AudioName == privatePtt.FileName) == null) chain.Add(new RecordEntity(privatePtt.FileUuid, privatePtt.FileName)); break; } @@ -159,13 +159,13 @@ public static MessageChain Parse(PushMsgBody message, bool isFake = false) public static MessageChain ParsePrivateFile(PushMsgBody message) { if (message.Body?.MsgContent == null) throw new Exception(); - + var chain = ParseChain(message); var extra = Serializer.Deserialize(message.Body.MsgContent.AsSpan()); var file = extra.File; - if ( file is { FileSize: not null, FileName: not null, FileMd5: not null, FileUuid: not null, FileHash: not null }) + if (file is { FileSize: not null, FileName: not null, FileMd5: not null, FileUuid: not null, FileHash: not null }) { chain.Add(new FileEntity((long)file.FileSize, file.FileName, file.FileMd5, file.FileUuid, file.FileHash)); return chain; @@ -243,29 +243,29 @@ public static MessageChain ParsePrivateFile(PushMsgBody message) }, Body = new MessageBody { RichText = new RichText { Elems = new List() } } }; - + private static MessageChain ParseChain(PushMsgBody message) { var chain = message.ResponseHead.Grp == null ? new MessageChain( message.ResponseHead.FromUin, - message.ResponseHead.ToUid ?? string.Empty , - message.ResponseHead.FromUid ?? string.Empty, + message.ResponseHead.ToUid ?? string.Empty, + message.ResponseHead.FromUid ?? string.Empty, message.ResponseHead.ToUin, message.ContentHead.Sequence ?? 0, message.ContentHead.NewId ?? 0, message.ContentHead.Type == 141 ? MessageChain.MessageType.Temp : MessageChain.MessageType.Friend) - + : new MessageChain( - message.ResponseHead.Grp.GroupUin, - message.ResponseHead.FromUin, + message.ResponseHead.Grp.GroupUin, + message.ResponseHead.FromUin, message.ContentHead.Sequence ?? 0, message.ContentHead.NewId ?? 0); if (message.Body?.RichText?.Elems is { } elems) chain.Elements.AddRange(elems); chain.Time = DateTimeOffset.FromUnixTimeSeconds(message.ContentHead.Timestamp ?? 0).DateTime; - + return chain; } @@ -284,9 +284,9 @@ private static MessageChain ParseFakeChain(PushMsgBody message) } else { - @base.FriendInfo = new BotFriend(0, message.ResponseHead.FromUid ?? string.Empty, message.ResponseHead.Forward?.FriendName ?? string.Empty, string.Empty, string.Empty); + @base.FriendInfo = new BotFriend(0, message.ResponseHead.FromUid ?? string.Empty, message.ResponseHead.Forward?.FriendName ?? string.Empty, string.Empty, string.Empty, 0, string.Empty); } - + return @base; } diff --git a/Lagrange.OneBot/Core/Entity/OneBotFriend.cs b/Lagrange.OneBot/Core/Entity/OneBotFriend.cs index 3c5fd5bbe..b0edf1d5c 100644 --- a/Lagrange.OneBot/Core/Entity/OneBotFriend.cs +++ b/Lagrange.OneBot/Core/Entity/OneBotFriend.cs @@ -10,4 +10,8 @@ public class OneBotFriend [JsonPropertyName("nickname")] public string NickName { get; set; } = ""; [JsonPropertyName("remark")] public string Remark { get; set; } = ""; + + [JsonPropertyName("group_id")] public uint GroupId { get; set; } = 0; + + [JsonPropertyName("group_name")] public string GroupName { get; set; } = ""; } \ No newline at end of file diff --git a/Lagrange.OneBot/Core/Operation/Info/GetFriendListOperation.cs b/Lagrange.OneBot/Core/Operation/Info/GetFriendListOperation.cs index bb04c7e7f..78b7cba70 100644 --- a/Lagrange.OneBot/Core/Operation/Info/GetFriendListOperation.cs +++ b/Lagrange.OneBot/Core/Operation/Info/GetFriendListOperation.cs @@ -14,6 +14,7 @@ public async Task HandleOperation(BotContext context, JsonNode? pa { UserId = x.Uin, NickName = x.Nickname, - Remark = x.Remarks + Remark = x.Remarks, + GroupName = x.GroupName }).ToArray(), 0, "ok"); } \ No newline at end of file diff --git a/Lagrange.OneBot/Core/Operation/Message/MessageCommon.cs b/Lagrange.OneBot/Core/Operation/Message/MessageCommon.cs index dd15b0a46..8103e7eb6 100644 --- a/Lagrange.OneBot/Core/Operation/Message/MessageCommon.cs +++ b/Lagrange.OneBot/Core/Operation/Message/MessageCommon.cs @@ -40,7 +40,7 @@ public MessageCommon(LiteDatabase database, ILogger logger) public MessageBuilder ParseFakeChain(OneBotFakeNode message, uint? groupUin) { - var builder = groupUin != null + var builder = groupUin != null ? MessageBuilder.FakeGroup((uint)groupUin, uint.Parse(message.Uin)) : MessageBuilder.Friend(uint.Parse(message.Uin)); BuildMessages(builder, message.Content); @@ -50,17 +50,17 @@ public MessageBuilder ParseFakeChain(OneBotFakeNode message, uint? groupUin) public MessageBuilder ParseFakeChain(OneBotFakeNodeSimple message, uint? groupUin) { - var builder = groupUin != null + var builder = groupUin != null ? MessageBuilder.FakeGroup((uint)groupUin, uint.Parse(message.Uin)) : MessageBuilder.Friend(uint.Parse(message.Uin)); BuildMessages(builder, message.Content); - + return builder; } public MessageBuilder ParseFakeChain(OneBotFakeNodeText message, uint? groupUin) { - var builder = groupUin != null + var builder = groupUin != null ? MessageBuilder.FakeGroup((uint)groupUin, uint.Parse(message.Uin)) : MessageBuilder.Friend(uint.Parse(message.Uin)); BuildMessages(builder, message.Content); @@ -249,7 +249,7 @@ public List BuildForwardChains(BotContext context, OneBotForward f _ => throw new Exception() }; string uid = context.ContextCollection.Keystore.Uid ?? throw new InvalidOperationException(); - chain.FriendInfo = new BotFriend(uint.Parse(element.Uin), uid, element.Name, string.Empty, string.Empty); + chain.FriendInfo = new BotFriend(uint.Parse(element.Uin), uid, element.Name, string.Empty, string.Empty, 0, string.Empty); chains.Add(chain); // as fake is constructed, use uid from bot itself to upload image } } diff --git a/Lagrange.OneBot/Core/Operation/Message/SendMessageOperation.cs b/Lagrange.OneBot/Core/Operation/Message/SendMessageOperation.cs index 0d1c71165..7bd66e202 100644 --- a/Lagrange.OneBot/Core/Operation/Message/SendMessageOperation.cs +++ b/Lagrange.OneBot/Core/Operation/Message/SendMessageOperation.cs @@ -38,6 +38,8 @@ public async Task HandleOperation(BotContext context, JsonNode? pa context.ContextCollection.Keystore.Uid ?? string.Empty, context.BotName ?? string.Empty, string.Empty, + string.Empty, + 0, string.Empty ), GroupMemberInfo = null, diff --git a/Lagrange.OneBot/Core/Operation/Message/SendPrivateForwardOperation.cs b/Lagrange.OneBot/Core/Operation/Message/SendPrivateForwardOperation.cs index d0abea552..a2c7e741f 100644 --- a/Lagrange.OneBot/Core/Operation/Message/SendPrivateForwardOperation.cs +++ b/Lagrange.OneBot/Core/Operation/Message/SendPrivateForwardOperation.cs @@ -38,6 +38,8 @@ public async Task HandleOperation(BotContext context, JsonNode? pa context.ContextCollection.Keystore.Uid ?? string.Empty, context.BotName ?? string.Empty, string.Empty, + string.Empty, + 0, string.Empty ), GroupMemberInfo = null, diff --git a/Lagrange.OneBot/Core/Operation/Message/SendPrivateMessageOperation.cs b/Lagrange.OneBot/Core/Operation/Message/SendPrivateMessageOperation.cs index 3ad181e27..c8339b7eb 100644 --- a/Lagrange.OneBot/Core/Operation/Message/SendPrivateMessageOperation.cs +++ b/Lagrange.OneBot/Core/Operation/Message/SendPrivateMessageOperation.cs @@ -38,6 +38,8 @@ public async Task HandleOperation(BotContext context, JsonNode? pa context.ContextCollection.Keystore.Uid ?? string.Empty, context.BotName ?? string.Empty, string.Empty, + string.Empty, + 0, string.Empty ), GroupMemberInfo = null,