4 Commits

Author SHA1 Message Date
976526ab79 fix: #350 2024-08-04 13:37:11 +08:00
cdc9ca1a72 fix: #351 2024-08-04 13:25:27 +08:00
609e87d0ec fix: move gpro api #346 2024-07-25 01:11:13 +08:00
cf01a25ea6 fix: #346 2024-07-25 00:35:56 +08:00
41 changed files with 429 additions and 84 deletions

View File

@ -146,6 +146,7 @@ public class TroopInfo {
public byte[] troopInfoExtByte;
public String troopLevelMap;
public String troopRemark;
@Deprecated
public String troopcode;
public short troopface;
public String troopmemo;
@ -154,6 +155,7 @@ public class TroopInfo {
public int trooptype;
public String troopuin;
public long udwCmdUinRingtoneID;
@Deprecated
public String uin;
public int wClickBAFTipCount;
public int wInsertBAFTipCount;

View File

@ -0,0 +1,11 @@
package com.tencent.mobileqq.qqguildsdk.api.impl;
import com.tencent.qqnt.kernelgpro.nativeinterface.IKernelGuildService;
public class GProSessionImpl {
public IKernelGuildService getGuildService() {
return null;
}
}

View File

@ -1,20 +1,12 @@
package com.tencent.mobileqq.qqguildsdk.data;
import android.text.TextUtils;
import com.tencent.mobileqq.qqguildsdk.data.genc.GGProMedalInfo;
import com.tencent.mobileqq.qqguildsdk.data.genc.GGProNavigationInfo;
import com.tencent.mobileqq.qqguildsdk.data.genc.IGProMedalInfo;
import com.tencent.mobileqq.qqguildsdk.data.genc.IGProNavigationInfo;
import com.tencent.qqnt.kernel.nativeinterface.GProGuild;
import com.tencent.qqnt.kernel.nativeinterface.GProGuildSpeakableThreshold;
import com.tencent.qqnt.kernel.nativeinterface.GProMedalInfo;
import com.tencent.qqnt.kernel.nativeinterface.GProNavigationInfo;
import com.tencent.qqnt.kernelgpro.nativeinterface.GProGuild;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Iterator;
public class GProGuildInfo implements IGProGuildInfo {

View File

@ -2,7 +2,7 @@ package com.tencent.mobileqq.qqguildsdk.data;
import androidx.annotation.NonNull;
import com.tencent.qqnt.kernel.nativeinterface.GProGuildRole;
import com.tencent.qqnt.kernelgpro.nativeinterface.GProGuildRole;
import java.util.ArrayList;
import java.util.Iterator;

View File

@ -1,6 +1,6 @@
package com.tencent.mobileqq.qqguildsdk.data;
import com.tencent.qqnt.kernel.nativeinterface.GProGuildRole;
import com.tencent.qqnt.kernelgpro.nativeinterface.GProGuildRole;
import com.tencent.qqnt.kernel.nativeinterface.GProUser;
import java.util.ArrayList;

View File

@ -1,14 +1,9 @@
package com.tencent.mobileqq.qqguildsdk.data.genc;
import com.tencent.mobileqq.qqguildsdk.data.GProGuildRoleInfo;
import com.tencent.mobileqq.qqguildsdk.data.GProUserInfo;
import com.tencent.mobileqq.qqguildsdk.data.IGProGuildRoleInfo;
import com.tencent.mobileqq.qqguildsdk.data.IGProUserInfo;
import com.tencent.qqnt.kernel.nativeinterface.GProGuildRole;
import com.tencent.qqnt.kernel.nativeinterface.GProUser;
import java.util.ArrayList;
import java.util.Iterator;
public class GGProGuildMemberSearchResult implements IGProGuildMemberSearchResult {

View File

@ -0,0 +1,51 @@
package com.tencent.qqnt.kernel.nativeinterface;
import java.io.Serializable;
public final class Contact implements IKernelModel, Serializable {
int chatType;
String guildId;
String peerUid;
long serialVersionUID;
public Contact() {
this.serialVersionUID = 1L;
this.peerUid = "";
this.guildId = "";
}
public int getChatType() {
return this.chatType;
}
public String getGuildId() {
return this.guildId;
}
public String getPeerUid() {
return this.peerUid;
}
public void setChatType(int i2) {
this.chatType = i2;
}
public void setGuildId(String str) {
this.guildId = str;
}
public void setPeerUid(String str) {
this.peerUid = str;
}
public String toString() {
return "Contact{chatType=" + this.chatType + ",peerUid=" + this.peerUid + ",guildId=" + this.guildId + ",}";
}
public Contact(int i2, String str, String str2) {
this.serialVersionUID = 1L;
this.chatType = i2;
this.peerUid = str;
this.guildId = str2;
}
}

View File

@ -1,5 +1,7 @@
package com.tencent.qqnt.kernel.nativeinterface;
import com.tencent.qqnt.kernelgpro.nativeinterface.GProGuild;
public final class GProJoinGuildResult {
GProGuild guildInfo;
GProGuildInit guildInit;

View File

@ -1,5 +1,7 @@
package com.tencent.qqnt.kernel.nativeinterface;
import com.tencent.qqnt.kernelgpro.nativeinterface.GProGuild;
import java.io.Serializable;
public final class GProJoinGuildsResult implements Serializable {

View File

@ -1,5 +1,7 @@
package com.tencent.qqnt.kernel.nativeinterface;
import com.tencent.qqnt.kernelgpro.nativeinterface.GProGuildRole;
import java.util.ArrayList;
public final class GProRoleMemberList {

View File

@ -1,5 +1,7 @@
package com.tencent.qqnt.kernel.nativeinterface;
import com.tencent.qqnt.kernelgpro.nativeinterface.GProGuildRole;
import java.util.ArrayList;
public final class GProSearchMemberAndRoleResult {

View File

@ -1,5 +1,7 @@
package com.tencent.qqnt.kernel.nativeinterface;
import com.tencent.qqnt.kernelgpro.nativeinterface.GProGuildRole;
import java.util.ArrayList;
public interface IGProFetchChannelInvisibleRoleListCallback {

View File

@ -1,5 +1,7 @@
package com.tencent.qqnt.kernel.nativeinterface;
import com.tencent.qqnt.kernelgpro.nativeinterface.GProGuildRole;
import java.util.ArrayList;
public interface IGProFetchChannelLiveableRoleListCallback {

View File

@ -1,5 +1,7 @@
package com.tencent.qqnt.kernel.nativeinterface;
import com.tencent.qqnt.kernelgpro.nativeinterface.GProGuild;
public interface IGProFetchGuildInfoCallback {
void onFetchGuildInfo(int code, String reason, GProGuild gProGuild);
}

View File

@ -1,5 +1,7 @@
package com.tencent.qqnt.kernel.nativeinterface;
import com.tencent.qqnt.kernelgpro.nativeinterface.GProGuild;
import java.util.ArrayList;
public interface IGProFetchGuildListCallback {

View File

@ -1,5 +0,0 @@
package com.tencent.qqnt.kernel.nativeinterface;
public interface IGProResultCallback {
void onResult(int code, String msg, GProSecurityResult result);
}

View File

@ -1,5 +1,8 @@
package com.tencent.qqnt.kernel.nativeinterface;
import com.tencent.qqnt.kernelgpro.nativeinterface.GProGuild;
import com.tencent.qqnt.kernelgpro.nativeinterface.GProGuildRole;
import java.util.ArrayList;
import java.util.HashMap;

View File

@ -1,5 +1,14 @@
package com.tencent.qqnt.kernel.nativeinterface;
import com.tencent.qqnt.kernelgpro.nativeinterface.GProGuild;
import com.tencent.qqnt.kernelgpro.nativeinterface.GProRoleCreateInfo;
import com.tencent.qqnt.kernelgpro.nativeinterface.IGProCreateRoleCallback;
import com.tencent.qqnt.kernelgpro.nativeinterface.IGProFetchMemberListWithRoleCallback;
import com.tencent.qqnt.kernelgpro.nativeinterface.IGProFetchMemberRolesCallback;
import com.tencent.qqnt.kernelgpro.nativeinterface.IGProFetchRoleListPermissionCallback;
import com.tencent.qqnt.kernelgpro.nativeinterface.IGProFetchRolePermissionCallback;
import com.tencent.qqnt.kernelgpro.nativeinterface.IGProResultCallback;
import java.util.ArrayList;
public interface IKernelGuildService {

View File

@ -19,11 +19,6 @@ public interface IQQNTWrapperSession {
return null;
}
@Override
public IKernelGuildService getGuildService() {
return null;
}
@Override
public IKernelMsgService getMsgService() {
return null;
@ -93,7 +88,7 @@ public interface IQQNTWrapperSession {
//IKernelGroupService getGroupService();
IKernelGuildService getGuildService();
//IKernelGuildService getGuildService();
IKernelMsgService getMsgService();

View File

@ -1,7 +1,9 @@
package com.tencent.qqnt.kernel.nativeinterface;
package com.tencent.qqnt.kernelgpro.nativeinterface;
import com.tencent.qqnt.kernel.nativeinterface.GProCmdUinInfo;
import com.tencent.qqnt.kernel.nativeinterface.GProGuildInfo;
import java.io.Serializable;
import java.util.ArrayList;
public final class GProGuild implements Serializable {
GProCmdUinInfo cmdUinInfo;

View File

@ -1,4 +1,6 @@
package com.tencent.qqnt.kernel.nativeinterface;
package com.tencent.qqnt.kernelgpro.nativeinterface;
import com.tencent.qqnt.kernel.nativeinterface.GProRolePermission;
import java.util.ArrayList;

View File

@ -1,4 +1,6 @@
package com.tencent.qqnt.kernel.nativeinterface;
package com.tencent.qqnt.kernelgpro.nativeinterface;
import com.tencent.qqnt.kernel.nativeinterface.GProRolePermission;
public final class GProRoleCreateInfo {
boolean bHoist;

View File

@ -1,4 +1,6 @@
package com.tencent.qqnt.kernel.nativeinterface;
package com.tencent.qqnt.kernelgpro.nativeinterface;
import com.tencent.qqnt.kernel.nativeinterface.GProSecurityResult;
public interface IGProCreateRoleCallback {
void onCreateRoleResult(int code, String msg, GProSecurityResult result, GProGuildRole role);

View File

@ -1,4 +1,6 @@
package com.tencent.qqnt.kernel.nativeinterface;
package com.tencent.qqnt.kernelgpro.nativeinterface;
import com.tencent.qqnt.kernel.nativeinterface.GProRoleMemberList;
import java.util.ArrayList;

View File

@ -1,4 +1,4 @@
package com.tencent.qqnt.kernel.nativeinterface;
package com.tencent.qqnt.kernelgpro.nativeinterface;
import java.util.ArrayList;

View File

@ -1,4 +1,4 @@
package com.tencent.qqnt.kernel.nativeinterface;
package com.tencent.qqnt.kernelgpro.nativeinterface;
import java.util.ArrayList;

View File

@ -1,4 +1,8 @@
package com.tencent.qqnt.kernel.nativeinterface;
package com.tencent.qqnt.kernelgpro.nativeinterface;
import com.tencent.qqnt.kernel.nativeinterface.GProRolePermission;
import com.tencent.qqnt.kernel.nativeinterface.GProRolePermissionCategory;
import com.tencent.qqnt.kernel.nativeinterface.GProRolePermissionDesc;
import java.util.ArrayList;

View File

@ -0,0 +1,7 @@
package com.tencent.qqnt.kernelgpro.nativeinterface;
import com.tencent.qqnt.kernel.nativeinterface.GProSecurityResult;
public interface IGProResultCallback {
void onResult(int code, String msg, GProSecurityResult result);
}

View File

@ -0,0 +1,90 @@
package com.tencent.qqnt.kernelgpro.nativeinterface;
import com.tencent.qqnt.kernel.nativeinterface.GProFaceAuthInfo;
import com.tencent.qqnt.kernel.nativeinterface.GProGuildReqInfo;
import com.tencent.qqnt.kernel.nativeinterface.GProSimpleProfile;
import com.tencent.qqnt.kernel.nativeinterface.IGProAddGuildInfoCallBack;
import com.tencent.qqnt.kernel.nativeinterface.IGProFetchChannelInvisibleRoleListCallback;
import com.tencent.qqnt.kernel.nativeinterface.IGProFetchChannelLiveableRoleListCallback;
import com.tencent.qqnt.kernel.nativeinterface.IGProFetchGuildInfoCallback;
import com.tencent.qqnt.kernel.nativeinterface.IGProFetchGuildListCallback;
import com.tencent.qqnt.kernel.nativeinterface.IGProFetchRetentionGuildListCallback;
import com.tencent.qqnt.kernel.nativeinterface.IGProFetchUserJoinedGuildListCallback;
import com.tencent.qqnt.kernel.nativeinterface.IGProGetMemberInfoByOpenIdCallback;
import com.tencent.qqnt.kernel.nativeinterface.IGProGetUserInfoCallback;
import com.tencent.qqnt.kernel.nativeinterface.IKernelGuildListener;
import java.util.ArrayList;
public interface IKernelGuildService {
void refreshGuildList(boolean isForced); // 只刷新id详细信息需要额外获取
//ArrayList<GProQQMsgListGuild> getQQMsgListGuilds(); 啥也拿不到
void fetchGuildList(ArrayList<GProGuildReqInfo> reqInfos, byte[] cookie, int i2, IGProFetchGuildListCallback iGProFetchGuildListCallback);
void fetchRetentionGuildList(int i2, int i3, byte[] cookie, long j2, IGProFetchRetentionGuildListCallback iGProFetchRetentionGuildListCallback);
void fetchUserJoinedGuildList(long guildId, long tinyId, String cookie, IGProFetchUserJoinedGuildListCallback cb);
void addKernelGuildListener(IKernelGuildListener iKernelGuildListener);
void GetMemberInfoByOpenId(String str, long j2, boolean z, boolean z2, IGProGetMemberInfoByOpenIdCallback iGProGetMemberInfoByOpenIdCallback);
ArrayList<GProGuild> getGroupGuildListFromCache();
ArrayList<GProGuild> getGuildListFromCache();
void fetchAddGuildInfo(int appId, long guildId, IGProAddGuildInfoCallBack iGProAddGuildInfoCallBack);
void fetchGuildInfo(long guildId, int seq, IGProFetchGuildInfoCallback iGProFetchGuildInfoCallback);
//void fetchGuildInfoByAppIdentity(GProGuildIdentity gProGuildIdentity, String str, String str2, IGProFetchGuildInfoByAppIdentityCallback iGProFetchGuildInfoByAppIdentityCallback);
void fetchGuildInfoForGuest(long guildId, int seq, IGProFetchGuildInfoCallback cb);
//void fetchGuestGuildInfoWithChannelList(String guildId, String str2, int i2, int seq, String str3,
// IGProFetchGuestGuildInfoWithChannelListCallback iGProFetchGuestGuildInfoWithChannelListCallback);
GProGuild getGuildInfoFromCache(long guildId);
// 第一次请求: startIndex = 0 , roleIdIndex = 2
void fetchMemberListWithRole(long guildId, long channelId, long startIndex, long roleIndex, int count, int seq, IGProFetchMemberListWithRoleCallback cb);
void refreshGuildInfo(long guildId, boolean force, int seq);
void refreshGuildInfoOnly(long j2, boolean z, int i2);
void refreshGuildUserProfileInfo(long guildId, long tinyId, int seq);
void fetchUserInfo(long guildId, long channelId, ArrayList<Long> tinyIdList, int seq, IGProGetUserInfoCallback cb);
//@Deprecated(since = "QQ新版本不支持创建话题子频道")
//void fetchTopFeeds(long guildId, long channelId, IGProFetchTopFeedsCallback cb);
void fetchChannelInvisibleRoleList(long guildId, long channelId, IGProFetchChannelInvisibleRoleListCallback cb);
void fetchChannelLiveableRoleList(long guildId, long channelId, IGProFetchChannelLiveableRoleListCallback cb);
void fetchMemberRoles(long guildId, long channelId, long tinyId, int seq, IGProFetchMemberRolesCallback cb);
void fetchRoleListWithPermission(long guildId, int seq, IGProFetchRoleListPermissionCallback cb);
void fetchRoleWithPermission(long guildId, long roleId, int seq, IGProFetchRolePermissionCallback cb);
GProSimpleProfile getSimpleProfile(long guildId, long tinyId, int seq);
GProFaceAuthInfo getFaceAuthInfo();
String getGuildUserAvatarUrl(long guildId, long tinyId, int seq);
String getGuildUserNickname(long guildId);
void deleteRole(long guild, long role, IGProResultCallback cb);
void setMemberRoles(long guild, long u1, long u2, long tinyId, ArrayList<Long> addRoles, ArrayList<Long> removeRoles, IGProResultCallback cb);
void setRoleInfo(long guild, long role, GProRoleCreateInfo info, IGProResultCallback cb);
void createRole(long guildId, GProRoleCreateInfo info, ArrayList<Long> initialUsers, IGProCreateRoleCallback cb);
}

View File

@ -0,0 +1,9 @@
package com.tencent.qqnt.kernelgpro.nativeinterface;
public interface IQQGProWrapperSession {
IKernelGuildService getGuildService();
static class CppProxy {
public static native IQQGProWrapperSession getGProWrapperSession(String str);
}
}

View File

@ -0,0 +1,11 @@
package com.tencent.qqnt.ntstartup.nativeinterface;
import java.util.HashMap;
public interface IQQNTStartupSessionWrapper {
HashMap<String, String> getSessionIdList();
int start();
int stop();
}

View File

@ -0,0 +1,45 @@
package com.tencent.qqnt.trooplist;
import androidx.lifecycle.LifecycleOwner;
import com.tencent.mobileqq.data.troop.TroopInfo;
import com.tencent.mobileqq.qroute.QRouteApi;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import kotlin.Unit;
import kotlin.jvm.functions.Function1;
public interface ITroopListRepoApi extends QRouteApi {
void fetchTroopLevelInfo(@NotNull String str, boolean z);
void fetchTroopList(boolean z);
//@NotNull
//a<Boolean> getFetchTroopListResultLiveData();
@NotNull
List<TroopInfo> getSortedValidTopTroopInfoFromCache();
@NotNull
List<TroopInfo> getSortedValidTroopInfoFromCache();
@NotNull
List<TroopInfo> getTopTroopListFromCache();
@Nullable
TroopInfo getTroopInfoFromCache(@NotNull String str);
@NotNull
List<TroopInfo> getTroopListFromCache();
//@Nullable
//a<List<TroopInfo>> getTroopListLiveData();
void preloadTroopList();
void requestSetTroopTop(@NotNull LifecycleOwner lifecycleOwner, @NotNull String str, boolean z, @NotNull Function1<? super Boolean, Unit> function1);
}

View File

@ -3,10 +3,11 @@
package moe.fuqiuluo.qqinterface.servlet
import com.tencent.mobileqq.qqguildsdk.api.IGPSService
import com.tencent.qqnt.kernel.nativeinterface.GProGuildRole
import com.tencent.qqnt.kernel.nativeinterface.GProRoleCreateInfo
import com.tencent.qqnt.kernelgpro.nativeinterface.GProGuildRole
import com.tencent.qqnt.kernelgpro.nativeinterface.GProRoleCreateInfo
import com.tencent.qqnt.kernel.nativeinterface.GProRoleMemberList
import com.tencent.qqnt.kernel.nativeinterface.GProRolePermission
import com.tencent.qqnt.kernelgpro.nativeinterface.IQQGProWrapperSession
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withTimeoutOrNull
import kotlinx.serialization.ExperimentalSerializationApi
@ -21,7 +22,6 @@ import moe.fuqiuluo.shamrock.helper.LogCenter
import moe.fuqiuluo.shamrock.tools.EMPTY_BYTE_ARRAY
import moe.fuqiuluo.shamrock.tools.decodeToObject
import moe.fuqiuluo.shamrock.tools.decodeToOidb
import moe.fuqiuluo.shamrock.tools.slice
import moe.fuqiuluo.shamrock.utils.PlatformUtils
import moe.fuqiuluo.shamrock.xposed.helper.NTServiceFetcher
import moe.fuqiuluo.shamrock.xposed.helper.QQInterfaces
@ -44,7 +44,6 @@ import protobuf.qweb.DEFAULT_DEVICE_INFO
import protobuf.qweb.QWebExtInfo
import protobuf.qweb.QWebReq
import protobuf.qweb.QWebRsp
import tencent.im.oidb.oidb_sso
import kotlin.coroutines.resume
internal object GProSvc: QQInterfaces() {
@ -53,6 +52,10 @@ internal object GProSvc: QQInterfaces() {
return service.selfTinyId.toULong()
}
private fun getNTGProSessionId(): String? {
return NTServiceFetcher.startupSessionWrapper.sessionIdList["gpro"]
}
suspend fun getGuildInfo(guildId: ULong): Result<Oidb0xf57MetaInfo> {
val respBuffer = sendOidbAW("OidbSvcTrpcTcp.0xf57_9", 0xf57, 9, Oidb0xf57Req(
filter = Oidb0xf57Filter(
@ -132,7 +135,9 @@ internal object GProSvc: QQInterfaces() {
}
fun refreshGuildInfo(guildId: ULong) {
val kernelGProService = NTServiceFetcher.kernelService.wrapperSession.guildService
val kernelGProService = IQQGProWrapperSession.CppProxy.getGProWrapperSession(
getNTGProSessionId()
).guildService
kernelGProService.refreshGuildInfo(guildId.toLong(), true, 1)
}
@ -144,8 +149,8 @@ internal object GProSvc: QQInterfaces() {
fetchAll: Boolean = false,
result: ArrayList<GProRoleMemberList> = arrayListOf()
): Result<Pair<GetGuildMemberListNextToken, ArrayList<GProRoleMemberList>>> {
val kernelGProService = NTServiceFetcher.kernelService.wrapperSession.guildService
val kernelGProService =
IQQGProWrapperSession.CppProxy.getGProWrapperSession(getNTGProSessionId()).guildService
val fetchGuildMemberListResult: Pair<GetGuildMemberListNextToken, ArrayList<GProRoleMemberList>> = (withTimeoutOrNull(5000) {
suspendCancellableCoroutine {
kernelGProService.fetchMemberListWithRole(guildId.toLong(), 0, startIndex, roleIndex, count, 0) { code, reason, finish, nextIndex, nextRoleIdIndex, _, seq, roleList ->
@ -214,7 +219,8 @@ internal object GProSvc: QQInterfaces() {
}
private fun getGuildListByNt(result: ArrayList<GuildInfo>) {
val kernelGProService = NTServiceFetcher.kernelService.wrapperSession.guildService
val kernelGProService =
IQQGProWrapperSession.CppProxy.getGProWrapperSession(getNTGProSessionId()).guildService
kernelGProService.guildListFromCache.forEach {
if (it.result != 0) return@forEach
val guildInfo = it.guildInfo
@ -236,7 +242,9 @@ internal object GProSvc: QQInterfaces() {
}
suspend fun fetchGuildMemberRoles(guildId: ULong, tinyId: ULong, refresh: Boolean = false): Result<ArrayList<GProGuildRole>> {
val kernelGProService = NTServiceFetcher.kernelService.wrapperSession.guildService
val kernelGProService = IQQGProWrapperSession.CppProxy.getGProWrapperSession(
getNTGProSessionId()
).guildService
if (refresh) {
kernelGProService.refreshGuildUserProfileInfo(guildId.toLong(), tinyId.toLong(), 1)
}
@ -251,7 +259,9 @@ internal object GProSvc: QQInterfaces() {
}
fun getGuildList(refresh: Boolean = false, forceOldApi: Boolean): ArrayList<GuildInfo> {
val kernelGProService = NTServiceFetcher.kernelService.wrapperSession.guildService
val kernelGProService = IQQGProWrapperSession.CppProxy.getGProWrapperSession(
getNTGProSessionId()
).guildService
if (refresh) {
kernelGProService.refreshGuildList(true)
kernelGProService.guildListFromCache.forEach {
@ -274,7 +284,10 @@ internal object GProSvc: QQInterfaces() {
}
suspend fun getGuildRoles(guildId: ULong): Result<List<GProGuildRole>> {
val kernelGProService = NTServiceFetcher.kernelService.wrapperSession.guildService
val kernelGProService = IQQGProWrapperSession.CppProxy.getGProWrapperSession(
getNTGProSessionId()
).guildService
val roles: List<GProGuildRole> = withTimeoutOrNull(5000) {
suspendCancellableCoroutine {
kernelGProService.fetchRoleListWithPermission(guildId.toLong(), 1) { code, _, roles, _, _, _ ->
@ -286,7 +299,10 @@ internal object GProSvc: QQInterfaces() {
}
fun deleteGuildRole(guildId: ULong, roleId: ULong) {
val kernelGProService = NTServiceFetcher.kernelService.wrapperSession.guildService
val kernelGProService = IQQGProWrapperSession.CppProxy.getGProWrapperSession(
getNTGProSessionId()
).guildService
kernelGProService.deleteRole(guildId.toLong(), roleId.toLong()) { code, msg, result ->
if (code != 0) {
LogCenter.log("deleteGuildRole failed: $code($msg) => $result", Level.WARN)
@ -295,7 +311,10 @@ internal object GProSvc: QQInterfaces() {
}
fun setMemberRole(guildId: ULong, tinyId: ULong, roleId: ULong, isSet: Boolean) {
val kernelGProService = NTServiceFetcher.kernelService.wrapperSession.guildService
val kernelGProService = IQQGProWrapperSession.CppProxy.getGProWrapperSession(
getNTGProSessionId()
).guildService
val addList = arrayListOf<Long>()
val rmList = arrayListOf<Long>()
(if (isSet) addList else rmList).add(roleId.toLong())
@ -307,8 +326,11 @@ internal object GProSvc: QQInterfaces() {
}
suspend fun getGuildRolePermission(guildId: ULong, roleId: ULong): Result<GProGuildRole> {
val kernelGProService = NTServiceFetcher.kernelService.wrapperSession.guildService
val role:GProGuildRole = withTimeoutOrNull(5000) {
val kernelGProService = IQQGProWrapperSession.CppProxy.getGProWrapperSession(
getNTGProSessionId()
).guildService
val role: GProGuildRole = withTimeoutOrNull(5000) {
suspendCancellableCoroutine {
kernelGProService.fetchRoleWithPermission(guildId.toLong(), roleId.toLong(), 1) { code, msg, role, _, _, _ ->
if (code != 0) {
@ -325,10 +347,14 @@ internal object GProSvc: QQInterfaces() {
val oldInfo = getGuildRolePermission(guildId, roleId).onFailure {
return Result.failure(it)
}.getOrThrow()
val kernelGProService = NTServiceFetcher.kernelService.wrapperSession.guildService
val info = GProRoleCreateInfo(
name, color, oldInfo.bHoist, oldInfo.rolePermissions
)
val kernelGProService = IQQGProWrapperSession.CppProxy.getGProWrapperSession(
getNTGProSessionId()
).guildService
val info =
GProRoleCreateInfo(
name, color, oldInfo.bHoist, oldInfo.rolePermissions
)
kernelGProService.setRoleInfo(guildId.toLong(), roleId.toLong(), info) { code, msg, result ->
if (code != 0) {
LogCenter.log("updateGuildRole failed: $code($msg) => $result", Level.WARN)
@ -338,9 +364,18 @@ internal object GProSvc: QQInterfaces() {
}
suspend fun createGuildRole(guildId: ULong, name: String, color: Long, initialUsers: ArrayList<Long>): Result<GProGuildRole> {
val kernelGProService = NTServiceFetcher.kernelService.wrapperSession.guildService
val kernelGProService = IQQGProWrapperSession.CppProxy.getGProWrapperSession(
getNTGProSessionId()
).guildService
val permission = GProRolePermission(false, arrayListOf())
val info = GProRoleCreateInfo(name, color, false, permission)
val info =
GProRoleCreateInfo(
name,
color,
false,
permission
)
val role: GProGuildRole = withTimeoutOrNull(5000) {
suspendCancellableCoroutine {
kernelGProService.createRole(guildId.toLong(), info, initialUsers) { code, msg, result, role ->

View File

@ -19,6 +19,7 @@ import com.tencent.protofile.join_group_link.join_group_link
import com.tencent.qphone.base.remote.ToServiceMsg
import com.tencent.qqnt.kernel.nativeinterface.MemberInfo
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
import com.tencent.qqnt.trooplist.ITroopListRepoApi
import com.tencent.qqnt.troopmemberlist.ITroopMemberListRepoApi
import friendlist.stUinInfo
import io.ktor.client.call.body
@ -56,7 +57,6 @@ 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
@ -76,7 +76,8 @@ import moe.fuqiuluo.shamrock.tools.ifNullOrEmpty
import moe.fuqiuluo.shamrock.tools.putBuf32Long
import moe.fuqiuluo.shamrock.utils.FileUtils
import moe.fuqiuluo.shamrock.utils.PlatformUtils
import moe.fuqiuluo.shamrock.utils.PlatformUtils.QQ_9_0_65_VER
import moe.fuqiuluo.shamrock.utils.PlatformUtils.QQ_9_0_71_VER
import moe.fuqiuluo.shamrock.utils.PlatformUtils.QQ_9_0_80_VER
import moe.fuqiuluo.shamrock.utils.PlatformUtils.QQ_9_0_8_VER
import moe.fuqiuluo.shamrock.xposed.helper.AppRuntimeFetcher
import moe.fuqiuluo.shamrock.xposed.helper.NTServiceFetcher
@ -229,17 +230,27 @@ internal object GroupSvc: QQInterfaces() {
}
suspend fun getGroupList(refresh: Boolean): Result<List<TroopInfo>> {
val service = app.getRuntimeService(ITroopInfoService::class.java, "all")
if (PlatformUtils.getQQVersionCode() <= QQ_9_0_80_VER) {
val service = app.getRuntimeService(ITroopInfoService::class.java, "all")
var troopList = service.allTroopList
if(refresh || !service.isTroopCacheInited || troopList == null) {
if(!requestGroupInfo(service)) {
return Result.failure(Exception("获取群列表失败"))
} else {
troopList = service.allTroopList
var troopList = service.allTroopList
if(refresh || !service.isTroopCacheInited || troopList == null) {
if(!requestGroupInfo(service)) {
return Result.failure(Exception("获取群列表失败"))
} else {
troopList = service.allTroopList
}
}
return Result.success(troopList)
} else {
val service = QRoute.api(ITroopListRepoApi::class.java)
val troopList = service.troopListFromCache
if (troopList == null || troopList.isEmpty() || refresh) {
service.fetchTroopList(true)
return Result.success(service.troopListFromCache)
}
return Result.success(troopList)
}
return Result.success(troopList)
}
suspend fun getNotJoinedGroupInfo(groupId: Long): Result<NotJoinedGroupInfo> {
@ -290,7 +301,7 @@ internal object GroupSvc: QQInterfaces() {
var nick = getTroopMemberInfoByUinV2(groupId, userId, true).getOrThrow().let {
it.troopnick.ifEmpty { it.troopremark.ifNullOrEmpty("") }
}
if (PlatformUtils.getQQVersionCode() > QQ_9_0_65_VER && nick == null) {
if (PlatformUtils.getQQVersionCode() > QQ_9_0_71_VER && nick == null) {
nick = getTroopMemberNickByUin(groupId, userId)?.let {
it.troopNick
.ifNullOrEmpty(it.friendNick)
@ -478,7 +489,7 @@ internal object GroupSvc: QQInterfaces() {
}
suspend fun isAdmin(groupId: Long): Boolean {
if (PlatformUtils.getQQVersionCode() > QQ_9_0_65_VER) {
if (PlatformUtils.getQQVersionCode() > QQ_9_0_71_VER) {
// 针对新版本api做的适配
val account = app.longAccountUin
getTroopMemberInfoByUinV2(groupId, account, false).onSuccess {
@ -607,7 +618,7 @@ internal object GroupSvc: QQInterfaces() {
groupId: Long,
uin: Long
): TroopMemberNickInfo? {
if (PlatformUtils.getQQVersionCode() > QQ_9_0_65_VER) {
if (PlatformUtils.getQQVersionCode() > QQ_9_0_71_VER) {
val api = QRoute.api(ITroopMemberListRepoApi::class.java)
return withTimeoutOrNull(5.seconds) {
suspendCancellableCoroutine<TroopMemberNickInfo> { continuation ->
@ -627,7 +638,7 @@ internal object GroupSvc: QQInterfaces() {
refresh: Boolean = false
): Result<TroopMemberInfo> {
var info: TroopMemberInfo? = null
if (PlatformUtils.getQQVersionCode() <= QQ_9_0_65_VER) {
if (PlatformUtils.getQQVersionCode() <= QQ_9_0_71_VER) {
val service = app.getRuntimeService(ITroopMemberInfoService::class.java, "all")
info = service.getTroopMember(groupId.toString(), uin.toString())
if (refresh || !service.isMemberInCache(groupId.toString(), uin.toString()) || info == null || info.troopnick == null) {

View File

@ -15,6 +15,7 @@ import com.tencent.qqnt.kernel.nativeinterface.VideoElement
import com.tencent.qqnt.kernelpublic.nativeinterface.Contact
import kotlinx.atomicfu.atomic
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.withTimeoutOrNull
import moe.fuqiuluo.qqinterface.servlet.TicketSvc
import moe.fuqiuluo.qqinterface.servlet.transfile.data.TryUpPicData
@ -45,6 +46,7 @@ import protobuf.oidb.cmd0x11c5.IndexNode
import protobuf.oidb.cmd0x11c5.MultiMediaReqHead
import protobuf.oidb.cmd0x11c5.NtV2RichMediaReq
import protobuf.oidb.cmd0x11c5.NtV2RichMediaRsp
import protobuf.oidb.cmd0x11c5.RKeyInfo
import protobuf.oidb.cmd0x11c5.SceneInfo
import protobuf.oidb.cmd0x11c5.UploadInfo
import protobuf.oidb.cmd0x11c5.UploadReq
@ -63,6 +65,8 @@ import kotlin.time.Duration
import kotlin.time.Duration.Companion.seconds
internal object NtV2RichMediaSvc: QQInterfaces() {
private lateinit var cacheRKeyInfo: DownloadRkeyRsp
private var lastRefreshRKeyTime = 0L
private val requestIdSeq = atomic(2L)
fun fetchGroupResUploadTo(): String {
@ -325,6 +329,9 @@ internal object NtV2RichMediaSvc: QQInterfaces() {
}
suspend fun getTempNtRKey(): Result<DownloadRkeyRsp> {
if (System.currentTimeMillis() - lastRefreshRKeyTime < 60 * 60_000 && ::cacheRKeyInfo.isInitialized) {
return Result.success(cacheRKeyInfo)
}
runCatching {
val req = NtV2RichMediaReq(
head = MultiMediaReqHead(
@ -350,6 +357,8 @@ internal object NtV2RichMediaSvc: QQInterfaces() {
}
val trpc = fromServiceMsg.decodeToTrpcOidb()
trpc.buffer.decodeProtobuf<NtV2RichMediaRsp>().downloadRkeyRsp?.let {
cacheRKeyInfo = it
lastRefreshRKeyTime = System.currentTimeMillis()
return Result.success(it)
}
}.onFailure {

View File

@ -11,6 +11,7 @@ import com.tencent.qqnt.kernel.nativeinterface.PicElement
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.serialization.ExperimentalSerializationApi
import moe.fuqiuluo.qqinterface.servlet.transfile.NtV2RichMediaSvc.getNtPicRKey
import moe.fuqiuluo.qqinterface.servlet.transfile.NtV2RichMediaSvc.getTempNtRKey
import moe.fuqiuluo.shamrock.helper.ContactHelper
import moe.fuqiuluo.shamrock.helper.Level
import moe.fuqiuluo.shamrock.helper.LogCenter
@ -160,7 +161,7 @@ internal object RichProtoSvc: QQInterfaces() {
): String {
val isNtServer = originalUrl.startsWith("/download")
if (isNtServer) {
val tmpRKey = NtV2RichMediaSvc.getTempNtRKey()
val tmpRKey = getTempNtRKey()
if (tmpRKey.isSuccess) {
val tmpRKeyRsp = tmpRKey.getOrThrow()
val tmpRKeyMap = hashMapOf<UInt, String>()
@ -168,10 +169,10 @@ internal object RichProtoSvc: QQInterfaces() {
tmpRKeyMap[rKeyInfo.type] = rKeyInfo.rkey
}
val rkey = tmpRKeyMap[when(chatType) {
MsgConstant.KCHATTYPEDISC, MsgConstant.KCHATTYPEGROUP -> 10u
MsgConstant.KCHATTYPEC2C -> 20u
MsgConstant.KCHATTYPEGUILD -> 10u
else -> 0u
MsgConstant.KCHATTYPEDISC, MsgConstant.KCHATTYPEGROUP -> 20u
MsgConstant.KCHATTYPEC2C -> 10u
MsgConstant.KCHATTYPEGUILD -> 20u
else -> 20u
}]
if (rkey != null) {
return "https://$MULTIMEDIA_DOMAIN$originalUrl$rkey"
@ -231,6 +232,23 @@ internal object RichProtoSvc: QQInterfaces() {
val isNtServer = originalUrl.startsWith("/download")
val domain = if (isNtServer) MULTIMEDIA_DOMAIN else GPRO_PIC
if (originalUrl.isNotEmpty()) {
// 高于QQ9.0.70可以直接请求获取rkey
val tmpRKey = getTempNtRKey().onFailure {
LogCenter.log("getTempNtRKey: ${it.stackTraceToString()}", Level.WARN)
}
if (tmpRKey.isSuccess) {
val tmpRKeyRsp = tmpRKey.getOrThrow()
val tmpRKeyMap = hashMapOf<UInt, String>()
tmpRKeyRsp.rkeys?.forEach { rKeyInfo ->
tmpRKeyMap[rKeyInfo.type] = rKeyInfo.rkey
}
val rkey = tmpRKeyMap[20u]
if (rkey != null) {
return "https://$MULTIMEDIA_DOMAIN$originalUrl$rkey"
}
}
// 低于QQ9.0.70但是支持nt资源的客户端支持
if (isNtServer && !originalUrl.contains("rkey=")) {
getNtPicRKey(
fileId = fileId,
@ -267,6 +285,21 @@ internal object RichProtoSvc: QQInterfaces() {
val isNtServer = storeId == 1 || originalUrl.startsWith("/download")
val domain = if (isNtServer) MULTIMEDIA_DOMAIN else C2C_PIC
if (originalUrl.isNotEmpty()) {
// 高于QQ9.0.70可以直接请求获取rkey
val tmpRKey = getTempNtRKey()
if (tmpRKey.isSuccess) {
val tmpRKeyRsp = tmpRKey.getOrThrow()
val tmpRKeyMap = hashMapOf<UInt, String>()
tmpRKeyRsp.rkeys?.forEach { rKeyInfo ->
tmpRKeyMap[rKeyInfo.type] = rKeyInfo.rkey
}
val rkey = tmpRKeyMap[10u]
if (rkey != null) {
return "https://$MULTIMEDIA_DOMAIN$originalUrl$rkey"
}
}
// 低于QQ9.0.70但是支持nt资源的客户端支持
if (fileId.isNotEmpty()) getNtPicRKey(
fileId = fileId,
md5 = md5,

View File

@ -12,7 +12,7 @@ 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
import moe.fuqiuluo.shamrock.utils.PlatformUtils.QQ_9_0_65_VER
import moe.fuqiuluo.shamrock.utils.PlatformUtils.QQ_9_0_71_VER
import moe.fuqiuluo.symbols.OneBotHandler
@OneBotHandler("get_group_member_info")
@ -37,7 +37,7 @@ internal object GetTroopMemberInfo : IActionHandler() {
val code = PlatformUtils.getQQVersionCode()
return ok(when {
(code >= QQ_9_0_65_VER) -> ntQQApiData(groupId, userId, info)
(code >= QQ_9_0_71_VER) -> ntQQApiData(groupId, userId, info)
else -> oldQQApiData(groupId, userId, info)
}, echo)
}
@ -111,7 +111,7 @@ internal object GetTroopMemberInfo : IActionHandler() {
age = info.age.toInt(),
shutUpTimestamp = 0L
).also {
if (PlatformUtils.getQQVersionCode() <= QQ_9_0_65_VER) {
if (PlatformUtils.getQQVersionCode() <= QQ_9_0_71_VER) {
it.distance = info.distance
it.area = info.alias
}

View File

@ -42,6 +42,7 @@ internal object AioListener : IKernelMsgListener {
try {
if (MessageTempHandler.notify(record)) return
if (record.msgSeq < 0) return
if (record.chatType == MsgConstant.KCHATTYPETEMPPUBLICACCOUNT) return // 订阅号不处理
val msgHash = MessageHelper.generateMsgIdHash(record.chatType, record.msgId)

View File

@ -12,12 +12,12 @@ import com.tencent.qqnt.kernel.nativeinterface.GProCreateGuildGuideInfo
import com.tencent.qqnt.kernel.nativeinterface.GProDailyRecommendPush
import com.tencent.qqnt.kernel.nativeinterface.GProDiscoveryStateChangedMsg
import com.tencent.qqnt.kernel.nativeinterface.GProGlobalBanner
import com.tencent.qqnt.kernel.nativeinterface.GProGuild
import com.tencent.qqnt.kernelgpro.nativeinterface.GProGuild
import com.tencent.qqnt.kernel.nativeinterface.GProGuildData
import com.tencent.qqnt.kernel.nativeinterface.GProGuildInit
import com.tencent.qqnt.kernel.nativeinterface.GProGuildListSortInfo
import com.tencent.qqnt.kernel.nativeinterface.GProGuildMemberCountInfo
import com.tencent.qqnt.kernel.nativeinterface.GProGuildRole
import com.tencent.qqnt.kernelgpro.nativeinterface.GProGuildRole
import com.tencent.qqnt.kernel.nativeinterface.GProGuildSpeakableThreshold
import com.tencent.qqnt.kernel.nativeinterface.GProGuildStateRspInfo
import com.tencent.qqnt.kernel.nativeinterface.GProGuildUserProfile
@ -49,7 +49,6 @@ import com.tencent.qqnt.kernel.nativeinterface.GProVoiceSmobaGameUserActionPush
import com.tencent.qqnt.kernel.nativeinterface.GProWorldState
import com.tencent.qqnt.kernel.nativeinterface.GProYLGameTeamInfo
import com.tencent.qqnt.kernel.nativeinterface.IKernelGuildListener
import moe.fuqiuluo.shamrock.helper.LogCenter
import java.util.ArrayList
import java.util.HashMap

View File

@ -17,7 +17,8 @@ import kotlin.random.Random
internal object PlatformUtils {
const val QQ_9_0_8_VER = 5540
const val QQ_9_0_65_VER = 6566
const val QQ_9_0_71_VER = 6702
const val QQ_9_0_80_VER = 6869
fun getQUA(): String {
return "V1_AND_SQ_${getQQVersion(MobileQQ.getContext())}_${getQQVersionCode()}_YYB_D"

View File

@ -1,9 +1,11 @@
package moe.fuqiuluo.shamrock.xposed.helper
import com.tencent.qqnt.kernel.api.IKernelService
import com.tencent.qqnt.kernel.api.impl.KernelServiceImpl
import com.tencent.qqnt.kernel.api.impl.MsgService
import com.tencent.qqnt.kernel.nativeinterface.IOperateCallback
import com.tencent.qqnt.kernel.nativeinterface.IQQNTWrapperSession
import com.tencent.qqnt.ntstartup.nativeinterface.IQQNTStartupSessionWrapper
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import moe.fuqiuluo.shamrock.helper.Level
@ -15,6 +17,7 @@ import moe.fuqiuluo.shamrock.utils.PlatformUtils
internal object NTServiceFetcher {
private lateinit var iKernelService: IKernelService
private lateinit var startupSession: IQQNTStartupSessionWrapper
private val lock = Mutex()
private var curKernelHash = 0
@ -30,7 +33,13 @@ internal object NTServiceFetcher {
LogCenter.log("Fetch kernel service successfully: $curKernelHash,$curHash,${PlatformUtils.isMainProcess()}")
curKernelHash = curHash
this.iKernelService = service
if (PlatformUtils.getQQVersionCode() >= PlatformUtils.QQ_9_0_71_VER) {
this.startupSession = KernelServiceImpl::class.java.declaredFields.first {
it.type == IQQNTStartupSessionWrapper::class.java
}.also {
it.isAccessible = true
}.get(service) as IQQNTStartupSessionWrapper
}
initNTKernelListener(msgService)
antiBackgroundMode(sessionService)
@ -99,4 +108,6 @@ internal object NTServiceFetcher {
val kernelService: IKernelService
get() = iKernelService
val startupSessionWrapper: IQQNTStartupSessionWrapper
get() = startupSession
}