Skip to content
This repository has been archived by the owner on Aug 12, 2024. It is now read-only.

Commit

Permalink
fix #340
Browse files Browse the repository at this point in the history
  • Loading branch information
fuqiuluo committed Jul 17, 2024
1 parent 36ed55d commit c49861d
Show file tree
Hide file tree
Showing 9 changed files with 233 additions and 63 deletions.
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
Original file line number Diff line number Diff line change
@@ -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;

}
Original file line number Diff line number Diff line change
@@ -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;
}
}
16 changes: 13 additions & 3 deletions xposed/src/main/java/moe/fuqiuluo/qqinterface/servlet/GroupSvc.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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<String> = arrayOf("user_id", "group_id")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Loading

0 comments on commit c49861d

Please sign in to comment.