From c49861d982ef06a95f93d7ba965cb8831d9774a6 Mon Sep 17 00:00:00 2001 From: fuqiuluo Date: Wed, 17 Jul 2024 17:25:16 +0800 Subject: [PATCH] fix #340 --- .../mobileqq/data/troop/TroopMemberInfo.java | 73 +++++++---- .../data/troop/TroopMemberInfoExt.java | 48 ++++++++ .../troop/TroopMemberSpecialTitleInfo.java | 29 +++++ .../fuqiuluo/qqinterface/servlet/GroupSvc.kt | 16 ++- .../remote/action/handlers/BanTroopMember.kt | 2 +- .../action/handlers/GetTroopMemberInfo.kt | 114 +++++++++++++----- .../action/handlers/ModifyTroopMemberName.kt | 2 +- .../remote/action/handlers/ModifyTroopName.kt | 2 +- .../shamrock/remote/service/data/TroopData.kt | 10 +- 9 files changed, 233 insertions(+), 63 deletions(-) create mode 100644 qqinterface/src/main/java/com/tencent/mobileqq/data/troop/TroopMemberInfoExt.java create mode 100644 qqinterface/src/main/java/com/tencent/mobileqq/data/troop/TroopMemberSpecialTitleInfo.java diff --git a/qqinterface/src/main/java/com/tencent/mobileqq/data/troop/TroopMemberInfo.java b/qqinterface/src/main/java/com/tencent/mobileqq/data/troop/TroopMemberInfo.java index 7aa28447..e937850b 100644 --- a/qqinterface/src/main/java/com/tencent/mobileqq/data/troop/TroopMemberInfo.java +++ b/qqinterface/src/main/java/com/tencent/mobileqq/data/troop/TroopMemberInfo.java @@ -1,63 +1,92 @@ package com.tencent.mobileqq.data.troop; +import org.jetbrains.annotations.Nullable; +import com.tencent.qqnt.kernelpublic.nativeinterface.MemberRole; + public class TroopMemberInfo { - public long active_point; + public static final long VALUE_DISTANCE_TO_SELF_UNKOWN = -100; + protected static final int VALUE_INVALID = -100; + public static final long VALUE_MEMBER_CLOSE_SHARE_LBS = -1001; + public int addState; - public byte age; - public String alias; + + @Deprecated(since = "推荐使用TroopMemberNickInfo") public String autoremark; - public long cmduinFlagEx3Grocery; public long credit_level; - public long datetime; public String displayedNamePinyinFirst; - public short faceid; + + @Nullable + public TroopMemberInfoExt extInfo; + + @Deprecated(since = "推荐使用TroopMemberNickInfo") public String friendnick; public long gagTimeStamp; public String honorList; + public boolean isTroopFollowed; + public long join_time; + public long last_active_time; + public int level; + public int mBigClubVipType; + public byte mHonorRichFlag; + public boolean mIsShielded; + public int mVipType; + public String memberUid; + public String memberuin; + public int newRealLevel; + public TroopMemberNickInfo nickInfo; + public int realLevel; + public MemberRole role; + + @Nullable + public TroopMemberSpecialTitleInfo specialTitleInfo; + + @Deprecated(since = "推荐使用TroopMemberNickInfo") + public String troopColorNick; + + @Deprecated(since = "推荐使用TroopMemberNickInfo") + public int troopColorNickId; + + @Deprecated(since = "推荐使用TroopMemberNickInfo") + public String troopnick; + public String troopuin; + public int globalTroopLevel = VALUE_INVALID; + public int flagEx = 0; + + // QQ OLD API DATA + public long active_point; + public byte age; + public String alias; + public long cmduinFlagEx3Grocery; + public long datetime; + public short faceid; public String hwCourse; public int hwIdentity; public String hwName; public int isShowQZone; - public boolean isTroopFollowed; - public long join_time; public long lastMsgUpdateHonorRichTime; - public long last_active_time; - public int level; public int mBigClubTemplateId; public int mBigClubVipLevel; - public int mBigClubVipType; public int mGlamourLevel; - public byte mHonorRichFlag; public int mIsHideBigClub; - public boolean mIsShielded; public String mUniqueTitle; public int mVipLevel; public int mVipTemplateId; - public int mVipType; - public String memberuin; - public int newRealLevel; public String pyAll_autoremark; public String pyAll_friendnick; public String pyAll_troopnick; public String pyFirst_autoremark; public String pyFirst_friendnick; public String pyFirst_troopnick; - public int realLevel; public String recommendRemark; public byte sex; public byte status; public int tribeLevel; public int tribePoint; - public String troopColorNick; - public int troopColorNickId; - public String troopnick; public String troopremark; - public String troopuin; public int qqVipInfo = 0; public int superQqInfo = 0; public int superVipInfo = 0; public int hotChatGlamourLevel = -100; - public int globalTroopLevel = -100; public int distance = 0; public long msgseq = -100; public double distanceToSelf = -100.0d; diff --git a/qqinterface/src/main/java/com/tencent/mobileqq/data/troop/TroopMemberInfoExt.java b/qqinterface/src/main/java/com/tencent/mobileqq/data/troop/TroopMemberInfoExt.java new file mode 100644 index 00000000..ef76a146 --- /dev/null +++ b/qqinterface/src/main/java/com/tencent/mobileqq/data/troop/TroopMemberInfoExt.java @@ -0,0 +1,48 @@ +package com.tencent.mobileqq.data.troop; + +import org.jetbrains.annotations.Nullable; + +import kotlin.jvm.JvmField; + +public class TroopMemberInfoExt { + @JvmField + public int commonFrdCnt; + + @JvmField + public long flagEx3; + + @JvmField + public int hwIdentity; + + @JvmField + public long lastMsgUpdateHonorRichTime; + + @JvmField + @Nullable + public String memberUin; + + @JvmField + @Nullable + public byte[] nickIconRepeatMsgBuffer; + + @JvmField + @Nullable + public String recommendRemark; + + @JvmField + @Nullable + public String showNameForPinyin; + + @JvmField + @Nullable + public String showNamePinyinAll; + + @JvmField + @Nullable + public String showNamePinyinFirst; + + @JvmField + @Nullable + public String troopUin; + +} diff --git a/qqinterface/src/main/java/com/tencent/mobileqq/data/troop/TroopMemberSpecialTitleInfo.java b/qqinterface/src/main/java/com/tencent/mobileqq/data/troop/TroopMemberSpecialTitleInfo.java new file mode 100644 index 00000000..943da049 --- /dev/null +++ b/qqinterface/src/main/java/com/tencent/mobileqq/data/troop/TroopMemberSpecialTitleInfo.java @@ -0,0 +1,29 @@ +package com.tencent.mobileqq.data.troop; + +import org.jetbrains.annotations.NotNull; + +public class TroopMemberSpecialTitleInfo { + public final int getExpireTimeSec() { + return 0; + } + + @NotNull + public final String getFriendNick() { + return null; + } + + @NotNull + public final String getSpecialTitle() { + return null; + } + + @NotNull + public final String getTroopUin() { + return null; + } + + @NotNull + public final String getUin() { + return null; + } +} diff --git a/xposed/src/main/java/moe/fuqiuluo/qqinterface/servlet/GroupSvc.kt b/xposed/src/main/java/moe/fuqiuluo/qqinterface/servlet/GroupSvc.kt index 6a732992..9001c936 100644 --- a/xposed/src/main/java/moe/fuqiuluo/qqinterface/servlet/GroupSvc.kt +++ b/xposed/src/main/java/moe/fuqiuluo/qqinterface/servlet/GroupSvc.kt @@ -56,6 +56,7 @@ import moe.fuqiuluo.qqinterface.servlet.structures.ProhibitedMemberInfo import moe.fuqiuluo.shamrock.helper.Level import moe.fuqiuluo.shamrock.helper.LogCenter import moe.fuqiuluo.shamrock.helper.MessageHelper +import moe.fuqiuluo.shamrock.remote.action.handlers.GetTroopMemberInfo import moe.fuqiuluo.shamrock.remote.service.data.EssenceMessage import moe.fuqiuluo.shamrock.remote.service.data.GroupAnnouncement import moe.fuqiuluo.shamrock.remote.service.data.GroupAnnouncementMessage @@ -476,12 +477,21 @@ internal object GroupSvc: QQInterfaces() { return groupInfo.troopowneruin == app.account } - fun isAdmin(groupId: Long): Boolean { + suspend fun isAdmin(groupId: Long): Boolean { + if (PlatformUtils.getQQVersionCode() > QQ_9_0_65_VER) { + // 针对新版本api做的适配 + val account = app.longAccountUin + getTroopMemberInfoByUinV2(groupId, account, false).onSuccess { + if (it.role == com.tencent.qqnt.kernelpublic.nativeinterface.MemberRole.ADMIN + || it.role == com.tencent.qqnt.kernelpublic.nativeinterface.MemberRole.OWNER) { + return true + } + } + } + val service = app .getRuntimeService(ITroopInfoService::class.java, "all") - val groupInfo = service.getTroopInfo(groupId.toString()) - return groupInfo.isAdmin || groupInfo.troopowneruin == app.account } diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/BanTroopMember.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/BanTroopMember.kt index f2b45a4a..6f2267da 100644 --- a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/BanTroopMember.kt +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/BanTroopMember.kt @@ -17,7 +17,7 @@ internal object BanTroopMember: IActionHandler() { return invoke(groupId, userId, duration, session.echo) } - operator fun invoke( + suspend operator fun invoke( groupId: Long, userId: Long, duration: Int = 30 * 60, diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/GetTroopMemberInfo.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/GetTroopMemberInfo.kt index d05c0165..3a6a8b3a 100644 --- a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/GetTroopMemberInfo.kt +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/GetTroopMemberInfo.kt @@ -1,11 +1,14 @@ package moe.fuqiuluo.shamrock.remote.action.handlers import com.tencent.mobileqq.data.Card +import com.tencent.mobileqq.data.troop.TroopMemberInfo +import com.tencent.qqnt.kernelpublic.nativeinterface.MemberRole as NtMemberRole import kotlinx.serialization.json.JsonElement import moe.fuqiuluo.qqinterface.servlet.GroupSvc import moe.fuqiuluo.shamrock.remote.action.ActionSession import moe.fuqiuluo.shamrock.remote.action.IActionHandler import moe.fuqiuluo.shamrock.remote.service.data.SimpleTroopMemberInfo +import moe.fuqiuluo.shamrock.remote.service.data.push.MemberRole import moe.fuqiuluo.shamrock.tools.EmptyJsonString import moe.fuqiuluo.shamrock.tools.ifNullOrEmpty import moe.fuqiuluo.shamrock.utils.PlatformUtils @@ -32,36 +35,87 @@ internal object GetTroopMemberInfo : IActionHandler() { return error(it.message ?: "unknown error", echo) }.getOrThrow() - return ok( - SimpleTroopMemberInfo( - uin = info.memberuin.toLong(), - name = info.friendnick.ifNullOrEmpty(info.autoremark) ?: "", - showName = info.troopnick.ifNullOrEmpty(info.troopColorNick), - cardName = info.troopnick.ifNullOrEmpty(info.troopColorNick), - distance = info.distance, - honor = GroupSvc.parseHonor(info.honorList), - joinTime = info.join_time, - lastActiveTime = info.last_active_time, - uniqueName = info.mUniqueTitle, - groupId = groupId, - nick = info.friendnick.ifNullOrEmpty(info.autoremark) ?: "", - sex = when (info.sex.toShort()) { - Card.FEMALE -> "female" - Card.MALE -> "male" - else -> "unknown" - }, - area = info.alias ?: "", - lastSentTime = info.last_active_time, - level = info.level, - role = GroupSvc.getMemberRole(groupId, userId), - unfriendly = false, - title = info.mUniqueTitle ?: "", - titleExpireTime = info.mUniqueTitleExpire, - cardChangeable = GroupSvc.isAdmin(groupId), - age = info.age.toInt(), - shutUpTimestamp = 0L - ), echo - ) + val code = PlatformUtils.getQQVersionCode() + return ok(when { + (code >= QQ_9_0_65_VER) -> ntQQApiData(groupId, userId, info) + else -> oldQQApiData(groupId, userId, info) + }, echo) + } + + private suspend fun ntQQApiData(groupId: Long, userId: Long, info: TroopMemberInfo): SimpleTroopMemberInfo { + return SimpleTroopMemberInfo( + uin = info.memberuin.toLong(), + name = info.friendnick.ifNullOrEmpty(info.autoremark) ?: "", + showName = info.troopnick.ifNullOrEmpty(info.troopColorNick), + cardName = info.troopnick.ifNullOrEmpty(info.troopColorNick), + distance = 0, + honor = GroupSvc.parseHonor(info.honorList), + joinTime = info.join_time, + lastActiveTime = info.last_active_time, + uniqueName = null, + groupId = groupId, + nick = info.friendnick.ifNullOrEmpty(info.autoremark) ?: "", + sex = "unknown", + area = "", + lastSentTime = info.last_active_time, + level = info.level, + role = when(info.role) { + NtMemberRole.UNSPECIFIED -> MemberRole.Unknown + NtMemberRole.STRANGER -> MemberRole.Stranger + NtMemberRole.MEMBER -> MemberRole.Member + NtMemberRole.ADMIN -> MemberRole.Admin + NtMemberRole.OWNER -> MemberRole.Owner + null -> MemberRole.Unknown + }, + unfriendly = false, + title = "", + titleExpireTime = 0, + cardChangeable = info.role == NtMemberRole.OWNER || info.role == NtMemberRole.ADMIN, + age = 0, + shutUpTimestamp = 0L + ).also { + if (info.specialTitleInfo != null) { + it.uniqueName = info.specialTitleInfo?.specialTitle ?: "" + it.title = info.specialTitleInfo?.specialTitle ?: "" + it.titleExpireTime = info.specialTitleInfo?.expireTimeSec ?: 0 + } + } + } + + private suspend fun oldQQApiData(groupId: Long, userId: Long, info: TroopMemberInfo): SimpleTroopMemberInfo { + return SimpleTroopMemberInfo( + uin = info.memberuin.toLong(), + name = info.friendnick.ifNullOrEmpty(info.autoremark) ?: "", + showName = info.troopnick.ifNullOrEmpty(info.troopColorNick), + cardName = info.troopnick.ifNullOrEmpty(info.troopColorNick), + distance = 0, + honor = GroupSvc.parseHonor(info.honorList), + joinTime = info.join_time, + lastActiveTime = info.last_active_time, + uniqueName = info.mUniqueTitle, + groupId = groupId, + nick = info.friendnick.ifNullOrEmpty(info.autoremark) ?: "", + sex = when (info.sex.toShort()) { + Card.FEMALE -> "female" + Card.MALE -> "male" + else -> "unknown" + }, + area = "", + lastSentTime = info.last_active_time, + level = info.level, + role = GroupSvc.getMemberRole(groupId, userId), + unfriendly = false, + title = info.mUniqueTitle ?: "", + titleExpireTime = info.mUniqueTitleExpire, + cardChangeable = GroupSvc.isAdmin(groupId), + age = info.age.toInt(), + shutUpTimestamp = 0L + ).also { + if (PlatformUtils.getQQVersionCode() <= QQ_9_0_65_VER) { + it.distance = info.distance + it.area = info.alias + } + } } override val requiredParams: Array = arrayOf("user_id", "group_id") diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/ModifyTroopMemberName.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/ModifyTroopMemberName.kt index 0cf477df..343a20de 100644 --- a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/ModifyTroopMemberName.kt +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/ModifyTroopMemberName.kt @@ -17,7 +17,7 @@ internal object ModifyTroopMemberName: IActionHandler() { return invoke(groupId, userId, name, session.echo) } - operator fun invoke(groupId: Long, userId: Long, card: String, echo: JsonElement = EmptyJsonString): String { + suspend operator fun invoke(groupId: Long, userId: Long, card: String, echo: JsonElement = EmptyJsonString): String { if (!GroupSvc.isAdmin(groupId) && userId != TicketSvc.getUin().toLong()) { return logic("you are not admin", echo) } diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/ModifyTroopName.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/ModifyTroopName.kt index dd44a05a..fc863cd3 100644 --- a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/ModifyTroopName.kt +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/ModifyTroopName.kt @@ -16,7 +16,7 @@ internal object ModifyTroopName: IActionHandler() { return invoke(groupId, groupName, session.echo) } - operator fun invoke(groupId: Long, name: String, echo: JsonElement = EmptyJsonString): String { + suspend operator fun invoke(groupId: Long, name: String, echo: JsonElement = EmptyJsonString): String { return if (GroupSvc.isAdmin(groupId)) { GroupSvc.modifyTroopName(groupId, name) ok("成功", echo) diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/service/data/TroopData.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/service/data/TroopData.kt index b78f21fd..5ee162b6 100644 --- a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/service/data/TroopData.kt +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/service/data/TroopData.kt @@ -27,18 +27,18 @@ internal data class SimpleTroopMemberInfo( @SerialName("user_name") val name: String, @SerialName("sex") val sex: String, @SerialName("age") val age: Int, - @SerialName("title") val title: String, - @SerialName("title_expire_time") val titleExpireTime: Int, + @SerialName("title") var title: String?, + @SerialName("title_expire_time") var titleExpireTime: Int, @SerialName("nickname") val nick: String, @SerialName("user_displayname") val showName: String?, @SerialName("card") val cardName: String?, - @SerialName("distance") val distance: Int, + @SerialName("distance") var distance: Int, @SerialName("honor") val honor: List, @SerialName("join_time") val joinTime: Long, @SerialName("last_active_time") val lastActiveTime: Long, @SerialName("last_sent_time") val lastSentTime: Long, - @SerialName("unique_name") val uniqueName: String?, - @SerialName("area") val area: String, + @SerialName("unique_name") var uniqueName: String?, + @SerialName("area") var area: String, @SerialName("level") val level: Int, @SerialName("role") val role: MemberRole, @SerialName("unfriendly") val unfriendly: Boolean,