diff --git a/Lagrange.Core/Common/Entity/BotBusiness.cs b/Lagrange.Core/Common/Entity/BotBusiness.cs new file mode 100644 index 000000000..9d9b7d750 --- /dev/null +++ b/Lagrange.Core/Common/Entity/BotBusiness.cs @@ -0,0 +1,25 @@ +namespace Lagrange.Core.Common.Entity +{ + public class BusinessCustom + { + public uint Type; + + public uint Level; + + public string? Icon; + + public uint IsYear; + + public uint IsPro; + } + + public class BusinessCustomList + { + public List BusinessLists { get; set; } + + public BusinessCustomList(List businessLists) + { + BusinessLists = businessLists; + } + } +} \ No newline at end of file diff --git a/Lagrange.Core/Common/Entity/BotUserInfo.cs b/Lagrange.Core/Common/Entity/BotUserInfo.cs index 3af6db3af..f6f6ba980 100644 --- a/Lagrange.Core/Common/Entity/BotUserInfo.cs +++ b/Lagrange.Core/Common/Entity/BotUserInfo.cs @@ -3,7 +3,7 @@ namespace Lagrange.Core.Common.Entity; [Serializable] public class BotUserInfo { - 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) + 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, List business) { Uin = uin; Avatar = avatar; @@ -20,6 +20,7 @@ internal BotUserInfo(uint uin, string nickname, string avatar, DateTime birthday Level = level; Sign = sign; Status = status; + Business = business; } public uint Uin { get; set; } @@ -50,6 +51,8 @@ internal BotUserInfo(uint uin, string nickname, string avatar, DateTime birthday public BotStatus Status { get; set; } + public List Business { get; set; } + public enum GenderInfo { Unset = 0, 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 31d95632d..3c6d151eb 100644 --- a/Lagrange.Core/Internal/Packets/Service/Oidb/Response/OidbSvcTrpcTcp0xFE1_2Response.cs +++ b/Lagrange.Core/Internal/Packets/Service/Oidb/Response/OidbSvcTrpcTcp0xFE1_2Response.cs @@ -43,4 +43,39 @@ public class CustomStatus public class Avatar { [ProtoMember(5)] public string? Url { get; set; } +} + +[ProtoContract] +public class Business +{ + [ProtoMember(3)] public BusinessBody? Body { get; set; } +} + +[ProtoContract] +public class BusinessBody +{ + [ProtoMember(1)] public string? Msg { get; set; } + + [ProtoMember(3)] public List? Lists { get; set; } +} + +[ProtoContract] +public class BusinessList +{ + [ProtoMember(1)] public uint Type { get; set; } + + [ProtoMember(2)] internal uint Field2 { get; set; } + + [ProtoMember(3)] public uint IsYear { get; set; } // 是否年费 + + [ProtoMember(4)] public uint Level { get; set; } + + [ProtoMember(5)] public uint IsPro { get; set; } // 是否为超级 + + [ProtoMember(6)] internal string? Icon1 { get; set; } + + [ProtoMember(7)] internal string? Icon2 { get; set; } + + public string? Icon => !string.IsNullOrEmpty(Icon1) ? Icon1 : Icon2; + } \ 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 1cd274367..e9cb5f04e 100644 --- a/Lagrange.Core/Internal/Service/System/FetchUserInfoService.cs +++ b/Lagrange.Core/Internal/Service/System/FetchUserInfoService.cs @@ -19,13 +19,13 @@ 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 = 20002 }, //昵称 + new() { Key = 27394 }, //QID + new() { Key = 20009 }, //性别 + new() { Key = 20031 }, //生日 + new() { Key = 101 }, //头像 new() { Key = 103 }, - new() { Key = 102 }, + new() { Key = 102 }, //简介/签名 new() { Key = 20022 }, new() { Key = 20023 }, new() { Key = 20024 }, @@ -34,36 +34,34 @@ internal class FetchUserInfoService : BaseService new() { Key = 27049 }, new() { Key = 20011 }, new() { Key = 20016 }, - new() { Key = 20021 }, - new() { Key = 20003 }, + new() { Key = 20021 }, //学校 + new() { Key = 20003 }, //国家 new() { Key = 20004 }, new() { Key = 20005 }, new() { Key = 20006 }, - new() { Key = 20020 }, - new() { Key = 20026 }, + new() { Key = 20020 }, //城市 + new() { Key = 20026 }, //注册时间 new() { Key = 24007 }, new() { Key = 104 }, - new() { Key = 105 }, + new() { Key = 105 }, //等级 new() { Key = 42432 }, new() { Key = 42362 }, new() { Key = 41756 }, new() { Key = 41757 }, new() { Key = 42257 }, - new() { Key = 27372 }, + new() { Key = 27372 }, //状态 new() { Key = 42315 }, - new() { Key = 107 }, + new() { Key = 107 }, //业务列表 new() { Key = 45160 }, new() { Key = 45161 }, - new() { Key = 27406 }, + new() { Key = 27406 }, //自定义状态文本 new() { Key = 62026 }, - new() { Key = 20037 } + new() { Key = 20037 } //年龄 }; protected override bool Build(FetchUserInfoEvent input, BotKeystore keystore, BotAppInfo appInfo, BotDeviceInfo device, out Span output, out List>? extraPackets) { - // 27406 自定义状态文本 - // 27372 状态 output = input.Uid == null ? new OidbSvcTrpcTcpBase(new OidbSvcTrpcTcp0xFE1_2Uin @@ -100,19 +98,23 @@ protected override bool Parse(Span input, BotKeystore keystore, BotAppInfo mask = (uint)((int)mask >> 31); statusId -= 268435456 & mask; - CustomStatus? customs = null; - if (bytesProperties[27406].Length != 0) - { - using var stream = new MemoryStream(bytesProperties[27406]); - customs = Serializer.Deserialize(stream); - } - - Avatar avatars; - using (var stream = new MemoryStream(bytesProperties[101])) - { - avatars = Serializer.Deserialize(stream); - } - string? avatarurl = avatars.Url + "0"; + var customs = bytesProperties[27406].Length != 0 + ? Serializer.Deserialize(new MemoryStream(bytesProperties[27406])) + : null; + + var avatars = Serializer.Deserialize(new MemoryStream(bytesProperties[101])); + + var business = Serializer.Deserialize(new MemoryStream(bytesProperties[107])); + var businessA = (business.Body?.Lists ?? new()) + .Select(b => new BusinessCustom + { + Type = b.Type, + Level = b.Level, + Icon = b.Icon, + IsPro = b.IsPro, + IsYear = b.IsYear + }) + .ToList(); string? nickname = Encoding.UTF8.GetString(bytesProperties[20002]); string? city = Encoding.UTF8.GetString(bytesProperties[20020]); @@ -123,7 +125,7 @@ protected override bool Parse(Span input, BotKeystore keystore, BotAppInfo var info = new BotUserInfo( payload.Body.Body.Uin, nickname, - avatarurl, + $"{avatars.Url}640", birthday, city, country, @@ -139,7 +141,8 @@ protected override bool Parse(Span input, BotKeystore keystore, BotAppInfo StatusId = statusId, FaceId = customs?.FaceId ?? 0, Msg = customs?.Msg - } + }, + businessA ); output = FetchUserInfoEvent.Result(0, info); diff --git a/Lagrange.OneBot/Core/Entity/OneBotStranger.cs b/Lagrange.OneBot/Core/Entity/OneBotStranger.cs index 63aad087d..638ccba4d 100644 --- a/Lagrange.OneBot/Core/Entity/OneBotStranger.cs +++ b/Lagrange.OneBot/Core/Entity/OneBotStranger.cs @@ -1,4 +1,5 @@ using System.Text.Json.Serialization; +using Lagrange.Core.Common.Entity; namespace Lagrange.OneBot.Core.Entity; @@ -24,4 +25,6 @@ public class OneBotStranger [JsonPropertyName("status")] public OneBotFriendStatus Status { get; set; } = new(); [JsonPropertyName("RegisterTime")] public DateTime RegisterTime { get; set; } + + [JsonPropertyName("Business")] public List Business { get; set; } = new(); } \ No newline at end of file diff --git a/Lagrange.OneBot/Core/Entity/OnebotBusiness.cs b/Lagrange.OneBot/Core/Entity/OnebotBusiness.cs new file mode 100644 index 000000000..ba5e723a4 --- /dev/null +++ b/Lagrange.OneBot/Core/Entity/OnebotBusiness.cs @@ -0,0 +1,20 @@ +using System.Text.Json.Serialization; +using Lagrange.Core.Common.Entity; + +namespace Lagrange.OneBot.Core.Entity; + +[Serializable] +public class OneBotBusiness +{ + [JsonPropertyName("type")] public uint Type { get; set; } + + [JsonPropertyName("name")] public string? Name { get; set; } + + [JsonPropertyName("level")] public uint Level { get; set; } + + [JsonPropertyName("icon")] public string? Icon { get; set; } + + [JsonPropertyName("ispro")] public uint IsPro { get; set; } + + [JsonPropertyName("isyear")] public uint IsYear { get; set; } +} diff --git a/Lagrange.OneBot/Core/Operation/Info/GetStrangerInfoOperation.cs b/Lagrange.OneBot/Core/Operation/Info/GetStrangerInfoOperation.cs index 56dfdb8d7..7f79aaa23 100644 --- a/Lagrange.OneBot/Core/Operation/Info/GetStrangerInfoOperation.cs +++ b/Lagrange.OneBot/Core/Operation/Info/GetStrangerInfoOperation.cs @@ -1,6 +1,7 @@ using System.Text.Json; using System.Text.Json.Nodes; using Lagrange.Core; +using Lagrange.Core.Common.Entity; using Lagrange.Core.Common.Interface.Api; using Lagrange.OneBot.Core.Entity; using Lagrange.OneBot.Core.Entity.Action; @@ -58,6 +59,24 @@ public class GetStrangerInfoOperation : IOperation { 13633281, "自定义状态"} }; + private static readonly Dictionary _BusinessName = new() + { + { 113, "QQ大会员" }, + { 1, "QQ会员" }, + { 102, "黄钻" }, + { 117, "QQ集卡" }, + { 119, "情侣会员" }, + { 103, "绿钻" }, + { 4, "腾讯视频" }, + { 108, "大王超级会员" }, + { 104, "情侣个性钻" }, + { 105, "微云会员"}, + { 101, "红钻"}, + { 115, "cf游戏特权"}, + { 118, "蓝钻"}, + { 107, "SVIP+腾讯视频"} + }; + public async Task HandleOperation(BotContext context, JsonNode? payload) { if (payload.Deserialize(SerializerOptions.DefaultOptions) is { } stranger) @@ -82,7 +101,8 @@ public async Task HandleOperation(BotContext context, JsonNode? pa ? _statusMessage.GetValueOrDefault(info.Status.StatusId) : info.Status.Msg }, - RegisterTime = info.RegisterTime + RegisterTime = info.RegisterTime, + Business = BusinessList(info.Business) }, 0, "ok"); } @@ -90,4 +110,17 @@ public async Task HandleOperation(BotContext context, JsonNode? pa } throw new Exception(); } + + private List BusinessList(List businessCustomList) + { + return businessCustomList.Select(b => new OneBotBusiness + { + Type = b.Type, + Name = (b.IsPro == 1 ? "超级" : "") + (_BusinessName.GetValueOrDefault(b.Type) ?? "未知"), + Level = b.Level, + Icon = b.Icon, + IsPro = b.IsPro, + IsYear = b.IsYear + }).ToList(); + } } \ No newline at end of file