Skip to content

Commit c77f94c

Browse files
KarlatempHim188
andauthored
UserProfile query (#866)
* UserProfile query * zip vReq0x5ebFieldId * Move UserProfile to `net.mamoe.mirai.data` * Move `queryProfile` to high-level api * Add doc * Update UserProfile.kt * Make UserProfile experimental * Convert UserProfile.sex to enum * Remove debugging code * Dump apis Co-authored-by: Him188 <[email protected]>
1 parent baa7eae commit c77f94c

File tree

8 files changed

+455
-1
lines changed

8 files changed

+455
-1
lines changed

binary-compatibility-validator/api/binary-compatibility-validator.api

+19
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ public abstract interface class net/mamoe/mirai/Bot : kotlinx/coroutines/Corouti
3636
public abstract fun login (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
3737
public fun nudge ()Lnet/mamoe/mirai/message/action/BotNudge;
3838
public synthetic fun nudge ()Lnet/mamoe/mirai/message/action/Nudge;
39+
public fun queryProfile (J)Lnet/mamoe/mirai/data/UserProfile;
40+
public abstract fun queryProfile (JLkotlin/coroutines/Continuation;)Ljava/lang/Object;
3941
}
4042

4143
public final class net/mamoe/mirai/Bot$Companion {
@@ -1416,6 +1418,23 @@ public abstract interface class net/mamoe/mirai/data/UserInfo {
14161418
public abstract fun getUin ()J
14171419
}
14181420

1421+
public abstract interface class net/mamoe/mirai/data/UserProfile {
1422+
public abstract fun getAge ()I
1423+
public abstract fun getEmail ()Ljava/lang/String;
1424+
public abstract fun getNickname ()Ljava/lang/String;
1425+
public abstract fun getQLevel ()I
1426+
public abstract fun getSex ()Lnet/mamoe/mirai/data/UserProfile$Sex;
1427+
public abstract fun getSign ()Ljava/lang/String;
1428+
}
1429+
1430+
public final class net/mamoe/mirai/data/UserProfile$Sex : java/lang/Enum {
1431+
public static final field FEMALE Lnet/mamoe/mirai/data/UserProfile$Sex;
1432+
public static final field MALE Lnet/mamoe/mirai/data/UserProfile$Sex;
1433+
public static final field UNKNOWN Lnet/mamoe/mirai/data/UserProfile$Sex;
1434+
public static fun valueOf (Ljava/lang/String;)Lnet/mamoe/mirai/data/UserProfile$Sex;
1435+
public static fun values ()[Lnet/mamoe/mirai/data/UserProfile$Sex;
1436+
}
1437+
14191438
public abstract class net/mamoe/mirai/event/AbstractEvent : net/mamoe/mirai/event/Event {
14201439
public fun <init> ()V
14211440
public final fun cancel ()V

mirai-core-api/src/commonMain/kotlin/Bot.kt

+12
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,14 @@ package net.mamoe.mirai
1717
import kotlinx.coroutines.*
1818
import net.mamoe.kjbb.JvmBlockingBridge
1919
import net.mamoe.mirai.contact.*
20+
import net.mamoe.mirai.data.UserProfile
2021
import net.mamoe.mirai.event.EventChannel
2122
import net.mamoe.mirai.event.events.BotEvent
2223
import net.mamoe.mirai.message.action.BotNudge
2324
import net.mamoe.mirai.message.action.MemberNudge
2425
import net.mamoe.mirai.network.LoginFailedException
2526
import net.mamoe.mirai.utils.BotConfiguration
27+
import net.mamoe.mirai.utils.MiraiExperimentalApi
2628
import net.mamoe.mirai.utils.MiraiLogger
2729
import java.util.concurrent.ConcurrentHashMap
2830

@@ -171,6 +173,16 @@ public interface Bot : CoroutineScope, ContactOrBot, UserOrBot {
171173
*/
172174
public override fun nudge(): BotNudge = BotNudge(this)
173175

176+
177+
/**
178+
* 查询某个用户的信息
179+
*
180+
* @since 2.1.0
181+
*/
182+
@MiraiExperimentalApi
183+
@JvmBlockingBridge
184+
public suspend fun queryProfile(targetId: Long): UserProfile
185+
174186
/**
175187
* 关闭这个 [Bot], 立即取消 [Bot] 的 [SupervisorJob], 取消与这个 [Bot] 相关的所有有协程联系的任务.
176188
*

mirai-core-api/src/commonMain/kotlin/LowLevelApiAccessor.kt

+1
Original file line numberDiff line numberDiff line change
@@ -270,4 +270,5 @@ public interface LowLevelApiAccessor {
270270
groupId: Long,
271271
seconds: Int,
272272
)
273+
273274
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright 2019-2021 Mamoe Technologies and contributors.
3+
*
4+
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
5+
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
6+
*
7+
* https://github.com/mamoe/mirai/blob/master/LICENSE
8+
*/
9+
10+
package net.mamoe.mirai.data
11+
12+
import net.mamoe.mirai.utils.MiraiExperimentalApi
13+
14+
@MiraiExperimentalApi
15+
public interface UserProfile {
16+
public val nickname: String
17+
public val email: String
18+
public val age: Int
19+
public val qLevel: Int
20+
public val sex: Sex
21+
22+
/**
23+
* 个性签名
24+
*/
25+
public val sign: String
26+
27+
public enum class Sex {
28+
MALE,
29+
FEMALE,
30+
/** 保密 */
31+
UNKNOWN;
32+
}
33+
}

mirai-core/src/commonMain/kotlin/QQAndroidBot.kt

+8
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import net.mamoe.mirai.internal.message.*
2626
import net.mamoe.mirai.internal.network.QQAndroidBotNetworkHandler
2727
import net.mamoe.mirai.internal.network.QQAndroidClient
2828
import net.mamoe.mirai.internal.network.protocol.packet.chat.*
29+
import net.mamoe.mirai.internal.network.protocol.packet.summarycard.SummaryCard
2930
import net.mamoe.mirai.message.data.*
3031
import net.mamoe.mirai.network.LoginFailedException
3132
import net.mamoe.mirai.utils.*
@@ -110,6 +111,13 @@ internal class QQAndroidBot constructor(
110111
return groups.firstOrNull { it.checkIsGroupImpl(); it.uin == uin }
111112
}
112113

114+
override suspend fun queryProfile(targetId: Long): UserProfile {
115+
network.apply {
116+
return SummaryCard.ReqSummaryCard(client, targetId)
117+
.sendAndExpect<SummaryCard.ReqSummaryCard.RespSummaryCard>()
118+
}
119+
}
120+
113121
/**
114122
* 获取 获取群公告 所需的 bkn 参数
115123
* */
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
/*
2+
* Copyright 2019-2021 Mamoe Technologies and contributors.
3+
*
4+
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
5+
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
6+
*
7+
* https://github.com/mamoe/mirai/blob/master/LICENSE
8+
*/
9+
10+
package net.mamoe.mirai.internal.network.protocol.data.jce
11+
12+
import kotlinx.serialization.Serializable
13+
import net.mamoe.mirai.internal.utils.io.JceStruct
14+
import net.mamoe.mirai.internal.utils.io.serialization.tars.TarsId
15+
16+
17+
@Serializable
18+
internal class ReqHead(
19+
@JvmField @TarsId(0) val iVersion: Int = 1
20+
) : JceStruct
21+
22+
@Serializable
23+
internal class ReqSummaryCard(
24+
@JvmField @TarsId(0) val uin: Long,
25+
@JvmField @TarsId(1) val eComeFrom: Int = 65535,
26+
@JvmField @TarsId(2) val uQzoneFeedTimestamp: Long? = null,
27+
@JvmField @TarsId(3) val isFriend: Byte? = null,
28+
@JvmField @TarsId(4) val groupCode: Long? = null,
29+
@JvmField @TarsId(5) val groupUin: Long? = null,
30+
//@JvmField @TarsId(6) val vSeed: ByteArray? = null,
31+
//@JvmField @TarsId(7) val searchName: String? = "",
32+
@JvmField @TarsId(8) val getControl: Long? = null,
33+
@JvmField @TarsId(9) val eAddFriendSource: Int? = null,
34+
@JvmField @TarsId(10) val vSecureSig: ByteArray? = null,
35+
//@JvmField @TarsId(11) val vReqLastGameInfo: ByteArray? = null,
36+
//@JvmField @TarsId(12) val vReqTemplateInfo: ByteArray? = null,
37+
//@JvmField @TarsId(13) val vReqStarInfo: ByteArray? = null,
38+
//@JvmField @TarsId(14) val vvReqServices: List<ByteArray>? = null,
39+
@JvmField @TarsId(15) val tinyId: Long? = null,
40+
@JvmField @TarsId(16) val uLikeSource: Long? = null,
41+
//@JvmField @TarsId(17) val stLocaleInfo: UserLocaleInfo? = null,
42+
@JvmField @TarsId(18) val reqMedalWallInfo: Byte? = null,
43+
@JvmField @TarsId(19) val vReq0x5ebFieldId: List<Int>? = null,
44+
@JvmField @TarsId(20) val reqNearbyGodInfo: Byte? = null,
45+
//@JvmField @TarsId(21) val reqCommLabel: Byte? = null,
46+
@JvmField @TarsId(22) val reqExtendCard: Byte? = null,
47+
//@JvmField @TarsId(23) val vReqKandianInfo: ByteArray? = null,
48+
//@JvmField @TarsId(24) val uRichCardNameVer: Long? = null
49+
) : JceStruct
50+
51+
@Serializable
52+
internal class RespHead(
53+
@JvmField @TarsId(0) val iVersion: Int,
54+
@JvmField @TarsId(1) val iResult: Int,
55+
@JvmField @TarsId(2) val errorMsg: String = "",
56+
@JvmField @TarsId(3) val vCookies: ByteArray? = null
57+
) : JceStruct
58+
59+
@Serializable
60+
internal class RespSearch(
61+
@JvmField @TarsId(0) val vRecords: List<SearchInfo>,
62+
@JvmField @TarsId(1) val vSecureSig: ByteArray? = null,
63+
@JvmField @TarsId(2) val vvRespServices: List<ByteArray>? = null
64+
) : JceStruct
65+
66+
@Serializable
67+
internal class RespSummaryCard(
68+
// @JvmField @TarsId(0) val iFace: Int? = null,
69+
@JvmField @TarsId(1) val sex: Byte? = null,
70+
@JvmField @TarsId(2) val age: Byte? = null,
71+
@JvmField @TarsId(3) val nick: String? = "",
72+
@JvmField @TarsId(4) val remark: String? = "",
73+
@JvmField @TarsId(5) val iLevel: Int? = null,
74+
@JvmField @TarsId(6) val province: String? = "",
75+
@JvmField @TarsId(7) val city: String? = "",
76+
@JvmField @TarsId(8) val sign: String? = "",
77+
@JvmField @TarsId(9) val groupName: String? = "",
78+
@JvmField @TarsId(10) val groupNick: String? = "",
79+
@JvmField @TarsId(11) val mobile: String? = "",
80+
@JvmField @TarsId(12) val contactName: String? = "",
81+
@JvmField @TarsId(13) val ulShowControl: Long? = null,
82+
@JvmField @TarsId(14) val qzoneFeedsDesc: String? = "",
83+
// @JvmField @TarsId(15) val oLatestPhotos:AlbumInfo? = null,
84+
@JvmField @TarsId(16) val iVoteCount: Int? = null,
85+
@JvmField @TarsId(17) val iLastestVoteCount: Int? = null,
86+
@JvmField @TarsId(18) val valid4Vote: Byte? = null,
87+
@JvmField @TarsId(19) val country: String? = "",
88+
@JvmField @TarsId(20) val status: String? = "",
89+
@JvmField @TarsId(21) val autoRemark: String? = "",
90+
@JvmField @TarsId(22) val cacheControl: Long? = null,
91+
@JvmField @TarsId(23) val uin: Long? = null,
92+
@JvmField @TarsId(24) val iPhotoCount: Int? = null,
93+
@JvmField @TarsId(25) val eAddOption: Int? = 101,
94+
@JvmField @TarsId(26) val vAddQuestion: List<String>? = null,
95+
@JvmField @TarsId(27) val vSeed: ByteArray? = null,
96+
@JvmField @TarsId(28) val discussName: String? = "",
97+
@JvmField @TarsId(29) val stVipInfo: VipBaseInfo? = null,
98+
@JvmField @TarsId(30) val showName: String? = "",
99+
@JvmField @TarsId(31) val stVoiceInfo: VoiceInfo? = null,
100+
@JvmField @TarsId(32) val vRichSign: ByteArray? = null,
101+
@JvmField @TarsId(33) val uSignModifyTime: Long? = null,
102+
@JvmField @TarsId(34) val vRespLastGameInfo: ByteArray? = null,
103+
@JvmField @TarsId(35) val userFlag: Long? = null,
104+
@JvmField @TarsId(36) val uLoginDays: Long? = null,
105+
@JvmField @TarsId(37) val loginDesc: String? = "",
106+
@JvmField @TarsId(38) val uTemplateId: Long? = null,
107+
@JvmField @TarsId(39) val uQQMasterLoginDays: Long? = 20L,
108+
@JvmField @TarsId(40) val ulFaceAddonId: Long? = null,
109+
@JvmField @TarsId(41) val vRespTemplateInfo: ByteArray? = null,
110+
@JvmField @TarsId(42) val respMusicInfo: String? = "",
111+
@JvmField @TarsId(43) val vRespStarInfo: ByteArray? = null,
112+
@JvmField @TarsId(44) val stDiamonds: VipBaseInfo? = null,
113+
@JvmField @TarsId(45) val uAccelerateMultiple: Long? = null,
114+
@JvmField @TarsId(46) val vvRespServices: List<ByteArray>? = null,
115+
@JvmField @TarsId(47) val spaceName: String? = "",
116+
// @JvmField @TarsId(48) val stDateCard:DateCard? = null,
117+
@JvmField @TarsId(49) val iBirthday: Int? = null,
118+
// @JvmField @TarsId(50) val stQCallInfo:QCallInfo? = null,
119+
// @JvmField @TarsId(51) val stGiftInfo:GiftInfo? = null,
120+
// @JvmField @TarsId(52) val stPanSocialInfo:PanSocialInfo? = null,
121+
// @JvmField @TarsId(53) val stVideoInfo:QQVideoInfo? = null,
122+
@JvmField @TarsId(54) val vTempChatSig: ByteArray? = null,
123+
// @JvmField @TarsId(55) val stInterestTag:InterestTagInfo? = null,
124+
// @JvmField @TarsId(56) val stUserFeed: UserFeed? = null,
125+
// @JvmField @TarsId(57) val stQiqiVideoInfo:QiqiVideoInfo? = null,
126+
// @JvmField @TarsId(58) val stPrivInfo:PrivilegeBaseInfo? = null,
127+
// @JvmField @TarsId(59) val stApollo:QQApolloInfo? = null,
128+
// @JvmField @TarsId(60) val stAddFrdSrcInfo:AddFrdSrcInfo? = null,
129+
// @JvmField @TarsId(61) val stBindPhoneInfo:BindPhoneInfo? = null,
130+
@JvmField @TarsId(62) val vVisitingCardInfo: ByteArray? = null,
131+
@JvmField @TarsId(63) val voteLimitedNotice: String? = "",
132+
@JvmField @TarsId(64) val haveVotedCnt: Short? = null,
133+
@JvmField @TarsId(65) val availVoteCnt: Short? = null,
134+
@JvmField @TarsId(66) val eIMBindPhoneNum: String? = "",
135+
@JvmField @TarsId(67) val eIMId: String? = "",
136+
@JvmField @TarsId(68) val email: String? = "",
137+
@JvmField @TarsId(69) val uCareer: Long? = null,
138+
@JvmField @TarsId(70) val personal: String? = "",
139+
@JvmField @TarsId(71) val vHotChatInfo: ByteArray? = null,
140+
// @JvmField @TarsId(72) val stOlympicInfo:OlympicInfo? = null,
141+
@JvmField @TarsId(73) val stCoverInfo: TCoverInfo? = null,
142+
@JvmField @TarsId(74) val stNowBroadcastInfo: TNowBroadcastInfo? = null,
143+
// @JvmField @TarsId(75) val stEimInfo:TEIMInfo? = null,
144+
@JvmField @TarsId(78) val stVideoHeadInfo: TVideoHeadInfo? = null,
145+
@JvmField @TarsId(79) val iContactNotBindQQ: Int? = null,
146+
// @JvmField @TarsId(80) val stMedalWallInfo:TMedalWallInfo? = null,
147+
@JvmField @TarsId(81) val vvRespServicesBigOrder: List<ByteArray>? = null,
148+
@JvmField @TarsId(82) val vResp0x5ebInfo: ByteArray? = null,
149+
@JvmField @TarsId(83) val stNearbyGodInfo: TNearbyGodInfo? = null,
150+
@JvmField @TarsId(84) val vRespQQStoryInfo: ByteArray? = null,
151+
@JvmField @TarsId(85) val vRespCustomLabelInfo: ByteArray? = null,
152+
@JvmField @TarsId(86) val vPraiseList: List<TPraiseInfo>? = null,
153+
@JvmField @TarsId(87) val stCampusCircleInfo: TCampusCircleInfo? = null,
154+
@JvmField @TarsId(88) val stTimInfo: TTimInfo? = null,
155+
@JvmField @TarsId(89) val stQimInfo: TQimInfo? = null,
156+
// @JvmField @TarsId(90) val stHeartInfo:HeartInfo? = null,
157+
@JvmField @TarsId(91) val vQzoneCoverInfo: ByteArray? = null,
158+
@JvmField @TarsId(92) val vNearbyTaskInfo: ByteArray? = null,
159+
@JvmField @TarsId(93) val vNowInfo: ByteArray? = null,
160+
@JvmField @TarsId(94) val uFriendGroupId: Long? = null,
161+
@JvmField @TarsId(95) val vCommLabel: ByteArray? = null,
162+
@JvmField @TarsId(96) val vExtendCard: ByteArray? = null,
163+
@JvmField @TarsId(97) val qzoneHeader: String? = "",
164+
@JvmField @TarsId(98) val mapQzoneEx: Map<String, String>? = null,
165+
@JvmField @TarsId(99) val vRespKandianInfo: ByteArray? = null,
166+
// @JvmField @TarsId(100) val stWeishiInfo:WeishiInfo? = null,
167+
@JvmField @TarsId(101) val uRichCardNameVer: Long? = null,
168+
@JvmField @TarsId(102) val uCurMulType: Long? = null,
169+
@JvmField @TarsId(103) val vLongNickTopicInfo: ByteArray? = null
170+
) : JceStruct
171+
172+
@Serializable
173+
internal class RespVoiceManage(
174+
@JvmField @TarsId(0) val eOpType: Int
175+
) : JceStruct
176+
177+
@Serializable
178+
internal class SearchInfo(
179+
@JvmField @TarsId(0) val uIN: Long,
180+
@JvmField @TarsId(1) val eSource: Int,
181+
@JvmField @TarsId(2) val nick: String? = "",
182+
@JvmField @TarsId(3) val mobile: String? = "",
183+
@JvmField @TarsId(4) val isFriend: Byte? = null,
184+
@JvmField @TarsId(5) val inContact: Byte? = null,
185+
@JvmField @TarsId(6) val isEnterpriseQQ: Byte? = null
186+
) : JceStruct
187+
188+
@Serializable
189+
internal class TCampusCircleInfo(
190+
@JvmField @TarsId(0) val iIsSigned: Int? = null,
191+
@JvmField @TarsId(1) val name: String? = "",
192+
@JvmField @TarsId(2) val academy: String? = "",
193+
@JvmField @TarsId(3) val eStatus: Int? = null,
194+
@JvmField @TarsId(4) val stSchoolInfo: TCampusSchoolInfo? = null
195+
) : JceStruct
196+
197+
@Serializable
198+
internal class TCampusSchoolInfo(
199+
@JvmField @TarsId(0) val uTimestamp: Long? = null,
200+
@JvmField @TarsId(1) val uSchoolId: Long? = null,
201+
@JvmField @TarsId(2) val iIsValidForCertified: Int? = null
202+
) : JceStruct
203+
204+
@Serializable
205+
internal class TCoverInfo(
206+
@JvmField @TarsId(0) val vTagInfo: ByteArray? = null
207+
) : JceStruct
208+
209+
210+
@Serializable
211+
internal class TNearbyGodInfo(
212+
@JvmField @TarsId(0) val iIsGodFlag: Int? = null,
213+
@JvmField @TarsId(1) val jumpUrl: String? = ""
214+
) : JceStruct
215+
216+
@Serializable
217+
internal class TNowBroadcastInfo(
218+
@JvmField @TarsId(0) val iFlag: Int? = null,
219+
@JvmField @TarsId(1) val iconURL: String? = "",
220+
@JvmField @TarsId(2) val hrefURL: String? = "",
221+
@JvmField @TarsId(3) val vAnchorDataRsp: ByteArray? = null
222+
) : JceStruct
223+
224+
@Serializable
225+
internal class TPraiseInfo(
226+
@JvmField @TarsId(0) val uCustomId: Long? = null,
227+
@JvmField @TarsId(1) val iIsPayed: Int? = null
228+
) : JceStruct
229+
230+
@Serializable
231+
internal class TQimInfo(
232+
@JvmField @TarsId(0) val iIsOnline: Int? = null
233+
) : JceStruct
234+
235+
@Serializable
236+
internal class TTimInfo(
237+
@JvmField @TarsId(0) val iIsOnline: Int? = null
238+
) : JceStruct
239+
240+
@Serializable
241+
internal class TVideoHeadInfo(
242+
@JvmField @TarsId(0) val iNearbyFlag: Int? = null,
243+
@JvmField @TarsId(1) val iBasicFlag: Int? = null,
244+
@JvmField @TarsId(2) val vMsg: ByteArray? = null
245+
) : JceStruct
246+
247+
@Serializable
248+
internal class UserFeed(
249+
@JvmField @TarsId(0) val uFlag: Long? = null,
250+
@JvmField @TarsId(1) val vFeedInfo: ByteArray? = null
251+
) : JceStruct
252+
253+
@Serializable
254+
internal class UserLocaleInfo(
255+
@JvmField @TarsId(1) val longitude: Long? = null,
256+
@JvmField @TarsId(2) val latitude: Long? = null
257+
) : JceStruct
258+
259+
@Serializable
260+
internal class VoiceInfo(
261+
@JvmField @TarsId(0) val vVoiceId: ByteArray? = null,
262+
@JvmField @TarsId(1) val shDuration: Short? = null,
263+
@JvmField @TarsId(2) val read: Byte? = 2,
264+
@JvmField @TarsId(3) val url: String? = ""
265+
) : JceStruct

0 commit comments

Comments
 (0)