From 1484051d2e3c7ceb206c334b7338d00138df1cc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=80=9D=E6=80=9D?= <71646091+sisi0318@users.noreply.github.com> Date: Sat, 12 Oct 2024 13:32:39 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=20get=5Fstranger=5Finfo=20(#?= =?UTF-8?q?631)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pk5ls20 Co-authored-by: DarkRRb <177549718+DarkRRb@users.noreply.github.com> --- .../Common/Entity/BotCustomStatus.cs | 10 +++ Lagrange.Core/Common/Entity/BotUserInfo.cs | 35 +++++---- .../Oidb/Generics/OidbFriendByteProperty.cs | 13 ++++ .../Oidb/Request/OidbSvcTrpcTcp0xFE1_2.cs | 10 +-- .../Response/OidbSvcTrpcTcp0xFE1_2Response.cs | 22 +++++- .../Service/System/FetchUserInfoService.cs | 75 +++++++++++++------ Lagrange.Core/Message/MessageBuilder.cs | 2 +- .../Core/Entity/OneBotFriendStatus.cs | 11 +++ Lagrange.OneBot/Core/Entity/OneBotStranger.cs | 10 ++- .../Info/GetStrangerInfoOperation.cs | 59 ++++++++++++++- 10 files changed, 199 insertions(+), 48 deletions(-) create mode 100644 Lagrange.Core/Common/Entity/BotCustomStatus.cs create mode 100644 Lagrange.Core/Internal/Packets/Service/Oidb/Generics/OidbFriendByteProperty.cs create mode 100644 Lagrange.OneBot/Core/Entity/OneBotFriendStatus.cs diff --git a/Lagrange.Core/Common/Entity/BotCustomStatus.cs b/Lagrange.Core/Common/Entity/BotCustomStatus.cs new file mode 100644 index 000000000..776282089 --- /dev/null +++ b/Lagrange.Core/Common/Entity/BotCustomStatus.cs @@ -0,0 +1,10 @@ +namespace Lagrange.Core.Common.Entity; + +public class BotStatus +{ + public uint StatusId { get; set; } + + public uint? FaceId { get; set; } + + public string? Msg { get; set; } +} \ No newline at end of file diff --git a/Lagrange.Core/Common/Entity/BotUserInfo.cs b/Lagrange.Core/Common/Entity/BotUserInfo.cs index d63072f9d..3af6db3af 100644 --- a/Lagrange.Core/Common/Entity/BotUserInfo.cs +++ b/Lagrange.Core/Common/Entity/BotUserInfo.cs @@ -3,10 +3,11 @@ namespace Lagrange.Core.Common.Entity; [Serializable] public class BotUserInfo { - internal BotUserInfo(uint uin, string nickname, DateTime birthday, string city, string country, string school, uint age, DateTime registerTime, uint gender, string? qid, uint level) + internal BotUserInfo(uint uin, string nickname, string avatar, DateTime birthday, string city, string country, string school, uint age, DateTime registerTime, GenderInfo gender, string? qid, uint level, string sign, BotStatus status) { Uin = uin; - Avatar = $"https://q1.qlogo.cn/g?b=qq&nk={Uin}&s=640"; + Avatar = avatar; + // Avatar = $"https://q1.qlogo.cn/g?b=qq&nk={Uin}&s=640"; Nickname = nickname; Birthday = birthday; City = city; @@ -14,35 +15,41 @@ internal BotUserInfo(uint uin, string nickname, DateTime birthday, string city, School = school; Age = age; RegisterTime = registerTime; - Gender = (GenderInfo)gender; + Gender = gender; Qid = qid; Level = level; + Sign = sign; + Status = status; } public uint Uin { get; set; } - + public string Avatar { get; set; } - + public string Nickname { get; set; } - + public DateTime Birthday { get; set; } - + public string City { get; set; } - + public string Country { get; set; } - + public string School { get; set; } - + public uint Age { get; set; } - + public DateTime RegisterTime { get; set; } - + public GenderInfo Gender { get; set; } - + public string? Qid { get; set; } - + public uint Level { get; set; } + public string Sign { get; set; } + + public BotStatus Status { get; set; } + public enum GenderInfo { Unset = 0, diff --git a/Lagrange.Core/Internal/Packets/Service/Oidb/Generics/OidbFriendByteProperty.cs b/Lagrange.Core/Internal/Packets/Service/Oidb/Generics/OidbFriendByteProperty.cs new file mode 100644 index 000000000..59287d7a3 --- /dev/null +++ b/Lagrange.Core/Internal/Packets/Service/Oidb/Generics/OidbFriendByteProperty.cs @@ -0,0 +1,13 @@ +using ProtoBuf; + +namespace Lagrange.Core.Internal.Packets.Service.Oidb.Generics; + +#pragma warning disable CS8618 + +[ProtoContract] +internal class OidbFriendByteProperty +{ + [ProtoMember(1)] public uint Code { get; set; } + + [ProtoMember(2)] public byte[] Value { get; set; } +} \ No newline at end of file diff --git a/Lagrange.Core/Internal/Packets/Service/Oidb/Request/OidbSvcTrpcTcp0xFE1_2.cs b/Lagrange.Core/Internal/Packets/Service/Oidb/Request/OidbSvcTrpcTcp0xFE1_2.cs index cf991de3e..5cfbb47a0 100644 --- a/Lagrange.Core/Internal/Packets/Service/Oidb/Request/OidbSvcTrpcTcp0xFE1_2.cs +++ b/Lagrange.Core/Internal/Packets/Service/Oidb/Request/OidbSvcTrpcTcp0xFE1_2.cs @@ -6,12 +6,12 @@ namespace Lagrange.Core.Internal.Packets.Service.Oidb.Request; [ProtoContract] [OidbSvcTrpcTcp(0xfe1, 2)] -internal class OidbSvcTrpcTcp0xFE1_2 +internal class OidbSvcTrpcTcp0xFE1_2Uid { [ProtoMember(1)] public string? Uid { get; set; } - + [ProtoMember(2)] public uint Field2 { get; set; } - + [ProtoMember(3)] public List? Keys { get; set; } // can be regarded as constants } @@ -19,9 +19,9 @@ internal class OidbSvcTrpcTcp0xFE1_2 internal class OidbSvcTrpcTcp0xFE1_2Uin { [ProtoMember(1)] public uint Uin { get; set; } - + [ProtoMember(2)] public uint Field2 { get; set; } - + [ProtoMember(3)] public List? Keys { get; set; } // can be regarded as constants } diff --git a/Lagrange.Core/Internal/Packets/Service/Oidb/Response/OidbSvcTrpcTcp0xFE1_2Response.cs b/Lagrange.Core/Internal/Packets/Service/Oidb/Response/OidbSvcTrpcTcp0xFE1_2Response.cs index 0e7f04968..31d95632d 100644 --- a/Lagrange.Core/Internal/Packets/Service/Oidb/Response/OidbSvcTrpcTcp0xFE1_2Response.cs +++ b/Lagrange.Core/Internal/Packets/Service/Oidb/Response/OidbSvcTrpcTcp0xFE1_2Response.cs @@ -17,9 +17,9 @@ internal class OidbSvcTrpcTcp0xFE1_2Response internal class OidbSvcTrpcTcp0xFE1_2ResponseBody { // [ProtoMember(1)] public string Uid { get; set; } = ""; - + [ProtoMember(2)] public OidbSvcTrpcTcp0xFE1_2ResponseProperty Properties { get; set; } - + [ProtoMember(3)] public uint Uin { get; set; } } @@ -27,6 +27,20 @@ internal class OidbSvcTrpcTcp0xFE1_2ResponseBody internal class OidbSvcTrpcTcp0xFE1_2ResponseProperty { [ProtoMember(1)] public List NumberProperties { get; set; } - - [ProtoMember(2)] public List StringProperties { get; set; } + + [ProtoMember(2)] public List BytesProperties { get; set; } +} + +[ProtoContract] +public class CustomStatus +{ + [ProtoMember(1)] public uint FaceId { get; set; } + + [ProtoMember(2)] public string? Msg { get; set; } +} + +[ProtoContract] +public class Avatar +{ + [ProtoMember(5)] public string? Url { get; set; } } \ No newline at end of file diff --git a/Lagrange.Core/Internal/Service/System/FetchUserInfoService.cs b/Lagrange.Core/Internal/Service/System/FetchUserInfoService.cs index 22e9364f2..314330c21 100644 --- a/Lagrange.Core/Internal/Service/System/FetchUserInfoService.cs +++ b/Lagrange.Core/Internal/Service/System/FetchUserInfoService.cs @@ -9,6 +9,7 @@ using Lagrange.Core.Utility.Binary; using Lagrange.Core.Utility.Extension; using ProtoBuf; +using static Lagrange.Core.Common.Entity.BotUserInfo; namespace Lagrange.Core.Internal.Service.System; @@ -16,26 +17,29 @@ 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 } + }; + protected override bool Build(FetchUserInfoEvent input, BotKeystore keystore, BotAppInfo appInfo, BotDeviceInfo device, out Span output, out List>? extraPackets) { - var keys = new List { 20002, 27394, 20009, 20031, 101, 103, 102, 20022, 20023, 20024, 24002, 27037, 27049, 20011, 20016, 20021, 20003, 20004, 20005, 20006, 20020, 20026, 24007, 104, 105, 42432, 42362, 41756, 41757, 42257, 27372, 42315, 107, 45160, 45161, 27406, 62026, 20037 }; + // 27406 自定义状态文本 + // 27372 状态 - object packet = input.Uid == null + output = input.Uid == null ? new OidbSvcTrpcTcpBase(new OidbSvcTrpcTcp0xFE1_2Uin { Uin = input.Uin, Field2 = 0, - Keys = keys.Select(x => new OidbSvcTrpcTcp0xFE1_2Key { Key = x }).ToList() - }, 0xfe1, 2, false, true) - : new OidbSvcTrpcTcpBase(new OidbSvcTrpcTcp0xFE1_2 + Keys = _keys, + }, 0xfe1, 2, false, true).Serialize() + : new OidbSvcTrpcTcpBase(new OidbSvcTrpcTcp0xFE1_2Uid { Uid = input.Uid, Field2 = 0, - Keys = keys.Select(x => new OidbSvcTrpcTcp0xFE1_2Key { Key = x }).ToList() - }, 0xfe1, 2); - - output = packet.Serialize(); + Keys = _keys + }, 0xfe1, 2).Serialize(); extraPackets = null; return true; } @@ -44,21 +48,48 @@ protected override bool Parse(Span input, BotKeystore keystore, BotAppInfo out FetchUserInfoEvent output, out List? extraEvents) { var payload = Serializer.Deserialize>(input); - - var str = GetStringProperties(payload.Body.Body.Properties); - var num = GetNumberProperties(payload.Body.Body.Properties); - var birthday = GetBirthday(str[20031]); - var reg = DateTime.UnixEpoch.AddSeconds(num[20026]); - string? qid = str.GetValueOrDefault(27394); - var info = new BotUserInfo(payload.Body.Body.Uin, str[20002], birthday, str[20020], str[20003], str[20021], num[20037], reg, num[20009], qid, num[105]); + var bytesProperties = GetStringProperties(payload.Body.Body.Properties); + var numberProperties = GetNumberProperties(payload.Body.Body.Properties); + + var birthday = GetBirthday(Encoding.UTF8.GetString(bytesProperties[20031])); + var reg = DateTime.UnixEpoch.AddSeconds(numberProperties[20026]); + + string? qid = Encoding.UTF8.GetString(bytesProperties[27394]); + + uint statusId = numberProperties[27372]; + uint mask = 268435455 - statusId; + mask = (uint)((int)mask >> 31); + statusId -= 268435456 & mask; + + CustomStatus? customs = null; + if (bytesProperties[27406].Length != 0) + { + using var stream = new MemoryStream(); + customs = Serializer.Deserialize(stream); + } + + Avatar avatars; + using (var stream = new MemoryStream(bytesProperties[101])) + { + avatars = Serializer.Deserialize(stream); + } + string? avatarurl = avatars.Url + "0"; + + string? nickname = Encoding.UTF8.GetString(bytesProperties[20002]); + string? city = Encoding.UTF8.GetString(bytesProperties[20020]); + string? country = Encoding.UTF8.GetString(bytesProperties[20003]); + 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 }); output = FetchUserInfoEvent.Result(0, info); extraEvents = null; return true; } - private static DateTime GetBirthday(String birthday) + private static DateTime GetBirthday(string birthday) { var bin = new BinaryPacket(Encoding.ASCII.GetBytes(birthday)); var year = bin.ReadUshort(); @@ -70,18 +101,18 @@ private static DateTime GetBirthday(String birthday) } return new DateTime(1970, 1, 1); } - - private static Dictionary GetStringProperties(OidbSvcTrpcTcp0xFE1_2ResponseProperty properties) + + private static Dictionary GetStringProperties(OidbSvcTrpcTcp0xFE1_2ResponseProperty properties) { - var result = new Dictionary(); - foreach (var property in properties.StringProperties) + var result = new Dictionary(); + foreach (var property in properties.BytesProperties) { result[property.Code] = property.Value; } return result; } - + private static Dictionary GetNumberProperties(OidbSvcTrpcTcp0xFE1_2ResponseProperty properties) { var result = new Dictionary(); diff --git a/Lagrange.Core/Message/MessageBuilder.cs b/Lagrange.Core/Message/MessageBuilder.cs index 971af07ba..3574fd514 100644 --- a/Lagrange.Core/Message/MessageBuilder.cs +++ b/Lagrange.Core/Message/MessageBuilder.cs @@ -353,7 +353,7 @@ public MessageBuilder MarketFace(string faceId, int tabId, string key, string su return this; } - public MessageBuilder GeryTip(string greyTip) + public MessageBuilder GreyTip(string greyTip) { var greyTipEntity = new GreyTipEntity(greyTip); _chain.Add(greyTipEntity); diff --git a/Lagrange.OneBot/Core/Entity/OneBotFriendStatus.cs b/Lagrange.OneBot/Core/Entity/OneBotFriendStatus.cs new file mode 100644 index 000000000..bdbb4d666 --- /dev/null +++ b/Lagrange.OneBot/Core/Entity/OneBotFriendStatus.cs @@ -0,0 +1,11 @@ +using System.Text.Json.Serialization; + +[Serializable] +public class OneBotFriendStatus +{ + [JsonPropertyName("status_id")] public uint StatusId { get; set; } + + [JsonPropertyName("face_id")] public uint? FaceId { get; set; } + + [JsonPropertyName("message")] public string? Message { get; set; } +} \ No newline at end of file diff --git a/Lagrange.OneBot/Core/Entity/OneBotStranger.cs b/Lagrange.OneBot/Core/Entity/OneBotStranger.cs index d7b7d750b..63aad087d 100644 --- a/Lagrange.OneBot/Core/Entity/OneBotStranger.cs +++ b/Lagrange.OneBot/Core/Entity/OneBotStranger.cs @@ -7,13 +7,21 @@ public class OneBotStranger { [JsonPropertyName("user_id")] public uint UserId { get; set; } + [JsonPropertyName("avatar")] public string Avatar { get; set; } = string.Empty; + [JsonPropertyName("q_id")] public string? QId { get; set; } [JsonPropertyName("nickname")] public string NickName { get; set; } = string.Empty; + [JsonPropertyName("sign")] public string Sign { get; set; } = string.Empty; + [JsonPropertyName("sex")] public string Sex { get; set; } = "unknown"; [JsonPropertyName("age")] public uint Age { get; set; } - + [JsonPropertyName("level")] public uint Level { get; set; } + + [JsonPropertyName("status")] public OneBotFriendStatus Status { get; set; } = new(); + + [JsonPropertyName("RegisterTime")] public DateTime RegisterTime { get; set; } } \ No newline at end of file diff --git a/Lagrange.OneBot/Core/Operation/Info/GetStrangerInfoOperation.cs b/Lagrange.OneBot/Core/Operation/Info/GetStrangerInfoOperation.cs index ddc007db4..56dfdb8d7 100644 --- a/Lagrange.OneBot/Core/Operation/Info/GetStrangerInfoOperation.cs +++ b/Lagrange.OneBot/Core/Operation/Info/GetStrangerInfoOperation.cs @@ -12,6 +12,52 @@ namespace Lagrange.OneBot.Core.Operation.Info; [Operation("get_stranger_info")] public class GetStrangerInfoOperation : IOperation { + private static readonly Dictionary _statusMessage = new() + { + { 1, "在线" }, + { 3, "离开" }, + { 4, "隐身/离线" }, + { 5, "忙碌" }, + { 6, "Q我吧" }, + { 7, "请勿打扰" }, + { 263169, "听歌中" }, + { 15205121, "我的电量" }, + { 16713473, "做好事" }, + { 13829889, "出去浪" }, + { 14616321, "去旅行" }, + { 14550785, "被掏空" }, + { 14747393, "今日步数" }, + { 394241, "今日天气" }, + { 14878465, "我crush了" }, + { 14026497, "爱你" }, + { 1770497, "恋爱中" }, + { 3081217, "好运锦鲤" }, + { 11600897, "水逆退散" }, + { 2098177, "嗨到飞起" }, + { 2229249, "元气满满" }, + { 2556929, "一言难尽" }, + { 13698817, "难得糊涂" }, + { 7931137, "emo中" }, + { 2491393, "我太难了" }, + { 14485249, "我想开了" }, + { 1836033, "我没事" }, + { 2425857, "想静静" }, + { 2294785, "悠哉哉" }, + { 15926017, "信号弱" }, + { 16253697, "睡觉中" }, + { 14419713, "肝作业" }, + { 16384769, "学习中" }, + { 15140609, "搬砖中" }, + { 1312001, "摸鱼中" }, + { 2360321, "无聊中" }, + { 197633, "timi中" }, + { 15271681, "一起元梦" }, + { 15337217, "求星搭子" }, + { 525313, "熬夜中" }, + { 16581377, "追剧中" }, + { 13633281, "自定义状态"} + }; + public async Task HandleOperation(BotContext context, JsonNode? payload) { if (payload.Deserialize(SerializerOptions.DefaultOptions) is { } stranger) @@ -21,11 +67,22 @@ public async Task HandleOperation(BotContext context, JsonNode? pa return new OneBotResult(new OneBotStranger { UserId = info.Uin, + Avatar = info.Avatar, QId = info.Qid, NickName = info.Nickname, Sex = info.Gender.ToOneBotString(), Age = info.Age, - Level = info.Level + Level = info.Level, + Sign = info.Sign ?? string.Empty, + Status = new() + { + StatusId = info.Status.StatusId, + FaceId = info.Status.FaceId, + Message = info.Status.StatusId != 13633281 + ? _statusMessage.GetValueOrDefault(info.Status.StatusId) + : info.Status.Msg + }, + RegisterTime = info.RegisterTime }, 0, "ok"); }