mirror of
https://github.com/whitechi73/OpenShamrock.git
synced 2024-08-14 05:12:17 +00:00
Compare commits
13 Commits
master
...
7eaa470dd2
Author | SHA1 | Date | |
---|---|---|---|
7eaa470dd2 | |||
c49861d982 | |||
36ed55d220 | |||
e2f27cb36a | |||
65ddca2ea4 | |||
a6f570e4f0 | |||
29dfc1590b | |||
ffeda0a472 | |||
0e5add2146 | |||
be9ff46134 | |||
1d6ac3e022 | |||
2db187e3d5 | |||
18ec586b12 |
2
.github/workflows/build-apk.yml
vendored
2
.github/workflows/build-apk.yml
vendored
@ -3,7 +3,7 @@ name: Build Shamrock APK
|
|||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
push:
|
push:
|
||||||
branches: [ master ]
|
branches: [ v1.0.9 ]
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- '**.md'
|
- '**.md'
|
||||||
- '**.txt'
|
- '**.txt'
|
||||||
|
@ -17,7 +17,7 @@ android {
|
|||||||
minSdk = 27
|
minSdk = 27
|
||||||
targetSdk = 34
|
targetSdk = 34
|
||||||
versionCode = getVersionCode()
|
versionCode = getVersionCode()
|
||||||
versionName = "1.0.9" + ".r${getGitCommitCount()}." + getVersionName()
|
versionName = "1.1.1.onebot" + ".r${getGitCommitCount()}." + getVersionName()
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
vectorDrawables {
|
vectorDrawables {
|
||||||
|
@ -12,7 +12,8 @@
|
|||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
JNIEXPORT jstring JNICALL
|
JNIEXPORT jstring JNICALL
|
||||||
Java_moe_fuqiuluo_shamrock_xposed_hooks_PullConfig_testNativeLibrary(JNIEnv *env, jobject thiz) {
|
Java_moe_fuqiuluo_shamrock_xposed_hooks_PullConfig_00024Companion_testNativeLibrary(JNIEnv *env,
|
||||||
|
jobject thiz) {
|
||||||
return env->NewStringUTF("加载Shamrock库成功~");
|
return env->NewStringUTF("加载Shamrock库成功~");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,7 +52,6 @@ import androidx.compose.runtime.rememberCoroutineScope
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.shadow
|
import androidx.compose.ui.draw.shadow
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.painter.Painter
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.platform.LocalView
|
import androidx.compose.ui.platform.LocalView
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
@ -64,6 +63,7 @@ import androidx.compose.ui.unit.sp
|
|||||||
import androidx.core.view.WindowCompat
|
import androidx.core.view.WindowCompat
|
||||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import moe.fuqiuluo.shamrock.ui.app.AppRuntime
|
import moe.fuqiuluo.shamrock.ui.app.AppRuntime
|
||||||
import moe.fuqiuluo.shamrock.ui.app.Logger
|
import moe.fuqiuluo.shamrock.ui.app.Logger
|
||||||
@ -79,7 +79,7 @@ import moe.fuqiuluo.shamrock.ui.theme.RANDOM_SUB_TITLE
|
|||||||
import moe.fuqiuluo.shamrock.ui.theme.RANDOM_TITLE
|
import moe.fuqiuluo.shamrock.ui.theme.RANDOM_TITLE
|
||||||
import moe.fuqiuluo.shamrock.ui.theme.ShamrockTheme
|
import moe.fuqiuluo.shamrock.ui.theme.ShamrockTheme
|
||||||
import moe.fuqiuluo.shamrock.ui.tools.NoIndication
|
import moe.fuqiuluo.shamrock.ui.tools.NoIndication
|
||||||
import moe.fuqiuluo.shamrock.ui.tools.ShamrockTab
|
import moe.fuqiuluo.shamrock.ui.tools.ShamrockTabV2
|
||||||
import moe.fuqiuluo.shamrock.ui.tools.getShamrockVersion
|
import moe.fuqiuluo.shamrock.ui.tools.getShamrockVersion
|
||||||
|
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
@ -87,6 +87,15 @@ class MainActivity : ComponentActivity() {
|
|||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
setContent {
|
setContent {
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
while (true) {
|
||||||
|
delay(5_000) // Delay in milliseconds
|
||||||
|
broadcastToModule {
|
||||||
|
putExtra("__cmd", "switch_status")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CompositionLocalProvider(
|
CompositionLocalProvider(
|
||||||
LocalIndication provides NoIndication
|
LocalIndication provides NoIndication
|
||||||
) {
|
) {
|
||||||
@ -336,7 +345,7 @@ private fun AnimatedTab(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ShamrockTab(
|
ShamrockTabV2(
|
||||||
selected = curSelected,
|
selected = curSelected,
|
||||||
onClick = {
|
onClick = {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
|
@ -30,6 +30,7 @@ abstract class ModuleHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
putExtra("__hash", callbackId)
|
putExtra("__hash", callbackId)
|
||||||
|
putExtra("__cmd", cmd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -58,7 +58,7 @@ class MultifunctionalProvider: ContentProvider() {
|
|||||||
|
|
||||||
inline fun Context.broadcastToModule(intentBuilder: Intent.() -> Unit) {
|
inline fun Context.broadcastToModule(intentBuilder: Intent.() -> Unit) {
|
||||||
val intent = Intent()
|
val intent = Intent()
|
||||||
intent.action = "moe.fuqiuluo.xqbot.dynamic"
|
intent.action = "moe.fuqiuluo.onebot.dynamic"
|
||||||
intent.intentBuilder()
|
intent.intentBuilder()
|
||||||
sendBroadcast(intent)
|
sendBroadcast(intent)
|
||||||
}
|
}
|
@ -242,13 +242,13 @@ private fun Placeable.PlacementScope.placeTextAndIcon(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ShamrockTab(
|
fun ShamrockTabV2(
|
||||||
selected: Boolean,
|
selected: Boolean,
|
||||||
onClick: () -> Unit,
|
onClick: () -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
enabled: Boolean = true,
|
enabled: Boolean = true,
|
||||||
text: @Composable (() -> Unit)? = null,
|
text: (@Composable (() -> Unit))? = null,
|
||||||
icon: @Composable (() -> Unit)? = null,
|
icon: (@Composable (() -> Unit))? = null,
|
||||||
selectedContentColor: Color = GlobalColor.TabSelected,
|
selectedContentColor: Color = GlobalColor.TabSelected,
|
||||||
unselectedContentColor: Color = selectedContentColor,
|
unselectedContentColor: Color = selectedContentColor,
|
||||||
indication: Indication? = rememberRipple(bounded = true, color = selectedContentColor),
|
indication: Indication? = rememberRipple(bounded = true, color = selectedContentColor),
|
||||||
@ -262,7 +262,7 @@ fun ShamrockTab(
|
|||||||
ProvideTextStyle(style, content = text)
|
ProvideTextStyle(style, content = text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ShamrockTab(
|
ShamrockTabV2(
|
||||||
selected,
|
selected,
|
||||||
onClick,
|
onClick,
|
||||||
modifier,
|
modifier,
|
||||||
@ -277,7 +277,7 @@ fun ShamrockTab(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ShamrockTab(
|
fun ShamrockTabV2(
|
||||||
selected: Boolean,
|
selected: Boolean,
|
||||||
onClick: () -> Unit,
|
onClick: () -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
|
@ -94,7 +94,8 @@ data class DeleteReq(
|
|||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class DownloadRkeyReq(
|
data class DownloadRkeyReq(
|
||||||
@ProtoNumber(1) val types: List<Int>
|
@ProtoNumber(1) val types: List<Int>,
|
||||||
|
@ProtoNumber(2) val downloadType: Int
|
||||||
)
|
)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
|
@ -52,11 +52,11 @@ data class DownloadRkeyRsp(
|
|||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class RKeyInfo(
|
data class RKeyInfo(
|
||||||
@ProtoNumber(1) val rkey: String?,
|
@ProtoNumber(1) val rkey: String,
|
||||||
@ProtoNumber(2) val rkeyTtlSec: ULong?,
|
@ProtoNumber(2) val rkeyTtlSec: ULong?,
|
||||||
@ProtoNumber(3) val storeId: UInt = 0u,
|
@ProtoNumber(3) val storeId: UInt = 0u,
|
||||||
@ProtoNumber(4) val rkeyCreateTime: UInt?,
|
@ProtoNumber(4) val rkeyCreateTime: UInt?,
|
||||||
@ProtoNumber(4) val type: UInt?,
|
@ProtoNumber(4) val type: UInt,
|
||||||
)
|
)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
|
@ -1,63 +1,92 @@
|
|||||||
package com.tencent.mobileqq.data.troop;
|
package com.tencent.mobileqq.data.troop;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import com.tencent.qqnt.kernelpublic.nativeinterface.MemberRole;
|
||||||
|
|
||||||
public class TroopMemberInfo {
|
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 int addState;
|
||||||
public byte age;
|
|
||||||
public String alias;
|
@Deprecated(since = "推荐使用TroopMemberNickInfo")
|
||||||
public String autoremark;
|
public String autoremark;
|
||||||
public long cmduinFlagEx3Grocery;
|
|
||||||
public long credit_level;
|
public long credit_level;
|
||||||
public long datetime;
|
|
||||||
public String displayedNamePinyinFirst;
|
public String displayedNamePinyinFirst;
|
||||||
public short faceid;
|
|
||||||
|
@Nullable
|
||||||
|
public TroopMemberInfoExt extInfo;
|
||||||
|
|
||||||
|
@Deprecated(since = "推荐使用TroopMemberNickInfo")
|
||||||
public String friendnick;
|
public String friendnick;
|
||||||
public long gagTimeStamp;
|
public long gagTimeStamp;
|
||||||
public String honorList;
|
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 String hwCourse;
|
||||||
public int hwIdentity;
|
public int hwIdentity;
|
||||||
public String hwName;
|
public String hwName;
|
||||||
public int isShowQZone;
|
public int isShowQZone;
|
||||||
public boolean isTroopFollowed;
|
|
||||||
public long join_time;
|
|
||||||
public long lastMsgUpdateHonorRichTime;
|
public long lastMsgUpdateHonorRichTime;
|
||||||
public long last_active_time;
|
|
||||||
public int level;
|
|
||||||
public int mBigClubTemplateId;
|
public int mBigClubTemplateId;
|
||||||
public int mBigClubVipLevel;
|
public int mBigClubVipLevel;
|
||||||
public int mBigClubVipType;
|
|
||||||
public int mGlamourLevel;
|
public int mGlamourLevel;
|
||||||
public byte mHonorRichFlag;
|
|
||||||
public int mIsHideBigClub;
|
public int mIsHideBigClub;
|
||||||
public boolean mIsShielded;
|
|
||||||
public String mUniqueTitle;
|
public String mUniqueTitle;
|
||||||
public int mVipLevel;
|
public int mVipLevel;
|
||||||
public int mVipTemplateId;
|
public int mVipTemplateId;
|
||||||
public int mVipType;
|
|
||||||
public String memberuin;
|
|
||||||
public int newRealLevel;
|
|
||||||
public String pyAll_autoremark;
|
public String pyAll_autoremark;
|
||||||
public String pyAll_friendnick;
|
public String pyAll_friendnick;
|
||||||
public String pyAll_troopnick;
|
public String pyAll_troopnick;
|
||||||
public String pyFirst_autoremark;
|
public String pyFirst_autoremark;
|
||||||
public String pyFirst_friendnick;
|
public String pyFirst_friendnick;
|
||||||
public String pyFirst_troopnick;
|
public String pyFirst_troopnick;
|
||||||
public int realLevel;
|
|
||||||
public String recommendRemark;
|
public String recommendRemark;
|
||||||
public byte sex;
|
public byte sex;
|
||||||
public byte status;
|
public byte status;
|
||||||
public int tribeLevel;
|
public int tribeLevel;
|
||||||
public int tribePoint;
|
public int tribePoint;
|
||||||
public String troopColorNick;
|
|
||||||
public int troopColorNickId;
|
|
||||||
public String troopnick;
|
|
||||||
public String troopremark;
|
public String troopremark;
|
||||||
public String troopuin;
|
|
||||||
public int qqVipInfo = 0;
|
public int qqVipInfo = 0;
|
||||||
public int superQqInfo = 0;
|
public int superQqInfo = 0;
|
||||||
public int superVipInfo = 0;
|
public int superVipInfo = 0;
|
||||||
public int hotChatGlamourLevel = -100;
|
public int hotChatGlamourLevel = -100;
|
||||||
public int globalTroopLevel = -100;
|
|
||||||
public int distance = 0;
|
public int distance = 0;
|
||||||
public long msgseq = -100;
|
public long msgseq = -100;
|
||||||
public double distanceToSelf = -100.0d;
|
public double distanceToSelf = -100.0d;
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
package com.tencent.mobileqq.data.troop;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class TroopMemberNickInfo {
|
||||||
|
@NotNull
|
||||||
|
public final String getAutoRemark() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public final String getColorNick() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final int getColorNickId() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public final String getFriendNick() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public final String getHBShowName() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public final String getRemarkFromFriend() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public final String getRemarkFromFriendV2() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public final String getShowName() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public final String getTroopNick() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public final String getTroopUin() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
15
qqinterface/src/main/java/com/tencent/mobileqq/l0/b/a.java
Normal file
15
qqinterface/src/main/java/com/tencent/mobileqq/l0/b/a.java
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package com.tencent.mobileqq.l0.b;
|
||||||
|
|
||||||
|
public class a {
|
||||||
|
public void b () {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void c (c cVar) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onUpdate(int progress, boolean z, Object obj) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
23
qqinterface/src/main/java/com/tencent/mobileqq/l0/b/b.java
Normal file
23
qqinterface/src/main/java/com/tencent/mobileqq/l0/b/b.java
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package com.tencent.mobileqq.l0.b;
|
||||||
|
|
||||||
|
import android.graphics.Point;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class b {
|
||||||
|
// text
|
||||||
|
public String a;
|
||||||
|
|
||||||
|
// confidence
|
||||||
|
public int b;
|
||||||
|
|
||||||
|
// coordinates
|
||||||
|
public ArrayList<Point> c;
|
||||||
|
|
||||||
|
/* renamed from: d */
|
||||||
|
public int d;
|
||||||
|
|
||||||
|
/* renamed from: e */
|
||||||
|
public boolean e;
|
||||||
|
|
||||||
|
}
|
39
qqinterface/src/main/java/com/tencent/mobileqq/l0/b/c.java
Normal file
39
qqinterface/src/main/java/com/tencent/mobileqq/l0/b/c.java
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
package com.tencent.mobileqq.l0.b;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class c {
|
||||||
|
// image
|
||||||
|
public String a;
|
||||||
|
|
||||||
|
// width
|
||||||
|
public int b;
|
||||||
|
|
||||||
|
// height
|
||||||
|
public int c;
|
||||||
|
|
||||||
|
// lang
|
||||||
|
public String d;
|
||||||
|
|
||||||
|
// url
|
||||||
|
public String e;
|
||||||
|
|
||||||
|
// results
|
||||||
|
public ArrayList<b> f;
|
||||||
|
|
||||||
|
public ArrayList<String> g;
|
||||||
|
|
||||||
|
public HashMap<String, String> h;
|
||||||
|
|
||||||
|
public int i;
|
||||||
|
|
||||||
|
public int j;
|
||||||
|
|
||||||
|
public int k;
|
||||||
|
|
||||||
|
public String l;
|
||||||
|
|
||||||
|
public int m;
|
||||||
|
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
package com.tencent.mobileqq.msf.core;
|
package com.tencent.mobileqq.msf.core;
|
||||||
|
|
||||||
public class MsfCore {
|
public class MsfCore {
|
||||||
public static synchronized int getNextSeq() {
|
public synchronized int getNextSeq() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
package com.tencent.mobileqq.msf.sdk;
|
||||||
|
|
||||||
|
import com.tencent.qphone.base.remote.FromServiceMsg;
|
||||||
|
import com.tencent.qphone.base.remote.ToServiceMsg;
|
||||||
|
|
||||||
|
public class MsfMessagePair {
|
||||||
|
public FromServiceMsg fromServiceMsg;
|
||||||
|
public String sendProcess;
|
||||||
|
public ToServiceMsg toServiceMsg;
|
||||||
|
|
||||||
|
public MsfMessagePair(String str, ToServiceMsg toServiceMsg, FromServiceMsg fromServiceMsg) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public MsfMessagePair(ToServiceMsg toServiceMsg, FromServiceMsg fromServiceMsg) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package com.tencent.mobileqq.msf.service;
|
||||||
|
|
||||||
|
import android.app.Service;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.IBinder;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.tencent.mobileqq.msf.core.MsfCore;
|
||||||
|
|
||||||
|
public class MsfService extends Service {
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public IBinder onBind(Intent intent) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MsfCore getCore() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
38
qqinterface/src/main/java/com/tencent/mobileqq/ocr/a/a.java
Normal file
38
qqinterface/src/main/java/com/tencent/mobileqq/ocr/a/a.java
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package com.tencent.mobileqq.ocr.a;
|
||||||
|
|
||||||
|
public class a {
|
||||||
|
public String a;
|
||||||
|
|
||||||
|
// 1
|
||||||
|
public int b;
|
||||||
|
|
||||||
|
// file location
|
||||||
|
public String c;
|
||||||
|
|
||||||
|
// null
|
||||||
|
public String d;
|
||||||
|
|
||||||
|
// 0
|
||||||
|
public long e;
|
||||||
|
|
||||||
|
// md5
|
||||||
|
public String f;
|
||||||
|
|
||||||
|
// null
|
||||||
|
public String g;
|
||||||
|
|
||||||
|
// false
|
||||||
|
public boolean h;
|
||||||
|
|
||||||
|
// 0
|
||||||
|
public int i;
|
||||||
|
|
||||||
|
// 0
|
||||||
|
public int j;
|
||||||
|
|
||||||
|
// 0
|
||||||
|
public long k;
|
||||||
|
|
||||||
|
// null
|
||||||
|
public String l;
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.tencent.mobileqq.ocr.api;
|
||||||
|
|
||||||
|
import mqq.app.api.IRuntimeService;
|
||||||
|
|
||||||
|
public interface IPicOcrService extends IRuntimeService {
|
||||||
|
void putOcrResult(String str, com.tencent.mobileqq.l0.b.c cVar);
|
||||||
|
|
||||||
|
void requestOcr(com.tencent.mobileqq.ocr.a.a aVar, com.tencent.mobileqq.l0.b.a callback);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
package com.tencent.mobileqq.ocr.api.impl;
|
||||||
|
|
||||||
|
public class OcrServiceImpl {
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
package com.tencent.mobileqq.ocr.api.impl;
|
||||||
|
|
||||||
|
public class PicOcrServiceImpl {
|
||||||
|
}
|
@ -1,7 +1,9 @@
|
|||||||
package com.tencent.qphone.base.util;
|
package com.tencent.qphone.base.util;
|
||||||
|
|
||||||
public abstract class CodecWarpper {
|
public abstract class CodecWarpper {
|
||||||
public abstract void onResponse(int i2, Object obj, int i3);
|
// public abstract void onResponse(int i2, Object obj, int i3);
|
||||||
|
|
||||||
|
public abstract void onInvalidData(int i2, int i3, String str);
|
||||||
|
|
||||||
public abstract void onResponse(int i2, Object obj, int i3, byte[] bArr);
|
public abstract void onResponse(int i2, Object obj, int i3, byte[] bArr);
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package com.tencent.qqnt.aio.api;
|
package com.tencent.qqnt.aio.api;
|
||||||
|
|
||||||
import com.tencent.mobileqq.qroute.QRouteApi;
|
import com.tencent.mobileqq.qroute.QRouteApi;
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.Contact;
|
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.IOperateCallback;
|
import com.tencent.qqnt.kernel.nativeinterface.IOperateCallback;
|
||||||
|
import com.tencent.qqnt.kernelpublic.nativeinterface.Contact;
|
||||||
|
|
||||||
public interface IAIOFileTransfer extends QRouteApi {
|
public interface IAIOFileTransfer extends QRouteApi {
|
||||||
void sendLocalFile(Contact contact, String path, IOperateCallback cb);
|
void sendLocalFile(Contact contact, String path, IOperateCallback cb);
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
package com.tencent.qqnt.kernel.api.impl;
|
||||||
|
|
||||||
|
public class GroupService {
|
||||||
|
}
|
@ -1,5 +1,7 @@
|
|||||||
package com.tencent.qqnt.kernel.nativeinterface;
|
package com.tencent.qqnt.kernel.nativeinterface;
|
||||||
|
|
||||||
|
import com.tencent.qqnt.kernelpublic.nativeinterface.Contact;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package com.tencent.qqnt.kernel.nativeinterface;
|
package com.tencent.qqnt.kernel.nativeinterface;
|
||||||
|
|
||||||
|
import com.tencent.qqnt.kernelpublic.nativeinterface.MemberRole;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
public final class GrayTipGroupMember implements Serializable {
|
public final class GrayTipGroupMember implements Serializable {
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package com.tencent.qqnt.kernel.nativeinterface;
|
package com.tencent.qqnt.kernel.nativeinterface;
|
||||||
|
|
||||||
|
import com.tencent.qqnt.kernelpublic.nativeinterface.MemberRole;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package com.tencent.qqnt.kernel.nativeinterface;
|
package com.tencent.qqnt.kernel.nativeinterface;
|
||||||
|
|
||||||
|
import com.tencent.qqnt.kernelpublic.nativeinterface.Contact;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
|
||||||
|
@ -0,0 +1,36 @@
|
|||||||
|
package com.tencent.qqnt.kernel.nativeinterface;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class GroupMemberCommonListResult {
|
||||||
|
public long groupCode;
|
||||||
|
public int identifyFlag;
|
||||||
|
public long startUin;
|
||||||
|
public ArrayList<MemberCommonInfo> memberList = new ArrayList<>();
|
||||||
|
public String strErrorInfo = "";
|
||||||
|
|
||||||
|
public long getGroupCode() {
|
||||||
|
return this.groupCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIdentifyFlag() {
|
||||||
|
return this.identifyFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<MemberCommonInfo> getMemberList() {
|
||||||
|
return this.memberList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getStartUin() {
|
||||||
|
return this.startUin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStrErrorInfo() {
|
||||||
|
return this.strErrorInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "GroupMemberCommonListResult{groupCode=" + this.groupCode + ",startUin=" + this.startUin + ",identifyFlag=" + this.identifyFlag + ",memberList=" + this.memberList + ",strErrorInfo=" + this.strErrorInfo + ",}";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,101 @@
|
|||||||
|
package com.tencent.qqnt.kernel.nativeinterface;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class GroupMemberCommonReq {
|
||||||
|
public long groupCode;
|
||||||
|
public int sourceType;
|
||||||
|
public String startUin = "";
|
||||||
|
public String identifyFlag = "";
|
||||||
|
public ArrayList<Long> uinList = new ArrayList<>();
|
||||||
|
public MemberCommonInfoFilter memberCommonFilter = new MemberCommonInfoFilter();
|
||||||
|
public String memberNum = "";
|
||||||
|
public String filterMethod = "";
|
||||||
|
public String onlineFlag = "";
|
||||||
|
public String realSpecialTitleFlag = "";
|
||||||
|
|
||||||
|
public String getFilterMethod() {
|
||||||
|
return this.filterMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getGroupCode() {
|
||||||
|
return this.groupCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIdentifyFlag() {
|
||||||
|
return this.identifyFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MemberCommonInfoFilter getMemberCommonFilter() {
|
||||||
|
return this.memberCommonFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMemberNum() {
|
||||||
|
return this.memberNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOnlineFlag() {
|
||||||
|
return this.onlineFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRealSpecialTitleFlag() {
|
||||||
|
return this.realSpecialTitleFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSourceType() {
|
||||||
|
return this.sourceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStartUin() {
|
||||||
|
return this.startUin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<Long> getUinList() {
|
||||||
|
return this.uinList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFilterMethod(String str) {
|
||||||
|
this.filterMethod = str;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGroupCode(long j2) {
|
||||||
|
this.groupCode = j2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIdentifyFlag(String str) {
|
||||||
|
this.identifyFlag = str;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMemberCommonFilter(MemberCommonInfoFilter memberCommonInfoFilter) {
|
||||||
|
this.memberCommonFilter = memberCommonInfoFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMemberNum(String str) {
|
||||||
|
this.memberNum = str;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnlineFlag(String str) {
|
||||||
|
this.onlineFlag = str;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRealSpecialTitleFlag(String str) {
|
||||||
|
this.realSpecialTitleFlag = str;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSourceType(int i2) {
|
||||||
|
this.sourceType = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStartUin(String str) {
|
||||||
|
this.startUin = str;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUinList(ArrayList<Long> arrayList) {
|
||||||
|
this.uinList = arrayList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "GroupMemberCommonReq{groupCode=" + this.groupCode + ",startUin=" + this.startUin + ",identifyFlag=" + this.identifyFlag + ",uinList=" + this.uinList + ",memberCommonFilter=" + this.memberCommonFilter + ",memberNum=" + this.memberNum + ",filterMethod=" + this.filterMethod + ",onlineFlag=" + this.onlineFlag + ",realSpecialTitleFlag=" + this.realSpecialTitleFlag + ",sourceType=" + this.sourceType + ",}";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,81 @@
|
|||||||
|
package com.tencent.qqnt.kernel.nativeinterface;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class GroupMemberExtListResult {
|
||||||
|
public long dataTime;
|
||||||
|
public long endUin;
|
||||||
|
public long groupCode;
|
||||||
|
public int levelNameSeq;
|
||||||
|
public int memberInfoSeq;
|
||||||
|
public int sysShowFlag;
|
||||||
|
public int timeToUpdate;
|
||||||
|
public int userShowFlag;
|
||||||
|
public int userShowFlagNew;
|
||||||
|
public ArrayList<MemberExtInfo> memberLevelInfo = new ArrayList<>();
|
||||||
|
public ArrayList<MemberLevelName> msgLevelName = new ArrayList<>();
|
||||||
|
public String strOwnerName = "";
|
||||||
|
public String strAdminName = "";
|
||||||
|
public ArrayList<MemberLevelName> msgLevelNameNew = new ArrayList<>();
|
||||||
|
|
||||||
|
public long getDataTime() {
|
||||||
|
return this.dataTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getEndUin() {
|
||||||
|
return this.endUin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getGroupCode() {
|
||||||
|
return this.groupCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLevelNameSeq() {
|
||||||
|
return this.levelNameSeq;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMemberInfoSeq() {
|
||||||
|
return this.memberInfoSeq;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<MemberExtInfo> getMemberLevelInfo() {
|
||||||
|
return this.memberLevelInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<MemberLevelName> getMsgLevelName() {
|
||||||
|
return this.msgLevelName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<MemberLevelName> getMsgLevelNameNew() {
|
||||||
|
return this.msgLevelNameNew;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStrAdminName() {
|
||||||
|
return this.strAdminName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStrOwnerName() {
|
||||||
|
return this.strOwnerName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSysShowFlag() {
|
||||||
|
return this.sysShowFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTimeToUpdate() {
|
||||||
|
return this.timeToUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getUserShowFlag() {
|
||||||
|
return this.userShowFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getUserShowFlagNew() {
|
||||||
|
return this.userShowFlagNew;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "GroupMemberExtListResult{groupCode=" + this.groupCode + ",memberLevelInfo=" + this.memberLevelInfo + ",msgLevelName=" + this.msgLevelName + ",endUin=" + this.endUin + ",dataTime=" + this.dataTime + ",userShowFlag=" + this.userShowFlag + ",sysShowFlag=" + this.sysShowFlag + ",timeToUpdate=" + this.timeToUpdate + ",strOwnerName=" + this.strOwnerName + ",strAdminName=" + this.strAdminName + ",levelNameSeq=" + this.levelNameSeq + ",userShowFlagNew=" + this.userShowFlagNew + ",msgLevelNameNew=" + this.msgLevelNameNew + ",memberInfoSeq=" + this.memberInfoSeq + ",}";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,101 @@
|
|||||||
|
package com.tencent.qqnt.kernel.nativeinterface;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class GroupMemberExtReq {
|
||||||
|
public long groupCode;
|
||||||
|
public int sourceType;
|
||||||
|
public String beginUin = "";
|
||||||
|
public String dataTime = "";
|
||||||
|
public ArrayList<Long> uinList = new ArrayList<>();
|
||||||
|
public MemberExtInfoFilter memberExtFilter = new MemberExtInfoFilter();
|
||||||
|
public String seq = "";
|
||||||
|
public String uinNum = "";
|
||||||
|
public String groupType = "";
|
||||||
|
public String richCardNameVer = "";
|
||||||
|
|
||||||
|
public String getBeginUin() {
|
||||||
|
return this.beginUin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDataTime() {
|
||||||
|
return this.dataTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getGroupCode() {
|
||||||
|
return this.groupCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGroupType() {
|
||||||
|
return this.groupType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MemberExtInfoFilter getMemberExtFilter() {
|
||||||
|
return this.memberExtFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRichCardNameVer() {
|
||||||
|
return this.richCardNameVer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSeq() {
|
||||||
|
return this.seq;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSourceType() {
|
||||||
|
return this.sourceType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<Long> getUinList() {
|
||||||
|
return this.uinList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUinNum() {
|
||||||
|
return this.uinNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBeginUin(String str) {
|
||||||
|
this.beginUin = str;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDataTime(String str) {
|
||||||
|
this.dataTime = str;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGroupCode(long j2) {
|
||||||
|
this.groupCode = j2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGroupType(String str) {
|
||||||
|
this.groupType = str;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMemberExtFilter(MemberExtInfoFilter memberExtInfoFilter) {
|
||||||
|
this.memberExtFilter = memberExtInfoFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRichCardNameVer(String str) {
|
||||||
|
this.richCardNameVer = str;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSeq(String str) {
|
||||||
|
this.seq = str;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSourceType(int i2) {
|
||||||
|
this.sourceType = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUinList(ArrayList<Long> arrayList) {
|
||||||
|
this.uinList = arrayList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUinNum(String str) {
|
||||||
|
this.uinNum = str;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "GroupMemberExtReq{groupCode=" + this.groupCode + ",beginUin=" + this.beginUin + ",dataTime=" + this.dataTime + ",uinList=" + this.uinList + ",memberExtFilter=" + this.memberExtFilter + ",seq=" + this.seq + ",uinNum=" + this.uinNum + ",groupType=" + this.groupType + ",richCardNameVer=" + this.richCardNameVer + ",sourceType=" + this.sourceType + ",}";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package com.tencent.qqnt.kernel.nativeinterface;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class GroupMemberListResult {
|
||||||
|
public boolean finish;
|
||||||
|
public boolean hasRobot;
|
||||||
|
public ArrayList<GroupMemberInfoListId> ids = new ArrayList<>();
|
||||||
|
public HashMap<String, MemberInfo> infos = new HashMap<>();
|
||||||
|
|
||||||
|
public boolean getFinish() {
|
||||||
|
return this.finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getHasRobot() {
|
||||||
|
return this.hasRobot;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<GroupMemberInfoListId> getIds() {
|
||||||
|
return this.ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HashMap<String, MemberInfo> getInfos() {
|
||||||
|
return this.infos;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "GroupMemberListResult{ids=" + this.ids + ",infos=" + this.infos + ",finish=" + this.finish + ",hasRobot=" + this.hasRobot + ",}";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,5 +1,7 @@
|
|||||||
package com.tencent.qqnt.kernel.nativeinterface;
|
package com.tencent.qqnt.kernel.nativeinterface;
|
||||||
|
|
||||||
|
import com.tencent.qqnt.kernelpublic.nativeinterface.MemberRole;
|
||||||
|
|
||||||
public final class GroupSimpleInfo implements IKernelModel {
|
public final class GroupSimpleInfo implements IKernelModel {
|
||||||
String avatarUrl;
|
String avatarUrl;
|
||||||
int discussToGroupMaxMsgSeq;
|
int discussToGroupMaxMsgSeq;
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
package com.tencent.qqnt.kernel.nativeinterface;
|
||||||
|
|
||||||
|
public interface IGroupMemberCommonCallback {
|
||||||
|
void onResult(int i2, String str, GroupMemberCommonListResult groupMemberCommonListResult);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
package com.tencent.qqnt.kernel.nativeinterface;
|
||||||
|
|
||||||
|
public interface IGroupMemberExtCallback {
|
||||||
|
void onResult(int i2, String str, GroupMemberExtListResult groupMemberExtListResult);
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
package com.tencent.qqnt.kernel.nativeinterface;
|
||||||
|
|
||||||
|
public interface IGroupMemberListCallback {
|
||||||
|
void onResult(int result, String str, GroupMemberListResult groupMemberListResult);
|
||||||
|
|
||||||
|
}
|
@ -1,7 +1,25 @@
|
|||||||
package com.tencent.qqnt.kernel.nativeinterface;
|
package com.tencent.qqnt.kernel.nativeinterface;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public interface IKernelGroupService {
|
public interface IKernelGroupService {
|
||||||
void getTransferableMemberInfo(long uin, IGetTransferableMemberCallback cb);
|
void getTransferableMemberInfo(long uin, IGetTransferableMemberCallback cb);
|
||||||
|
|
||||||
long addKernelGroupListener(IKernelGroupListener ln);
|
long addKernelGroupListener(IKernelGroupListener ln);
|
||||||
|
|
||||||
|
void getAllMemberList(long groupCode, boolean refresh, IGroupMemberListCallback iGroupMemberListCallback);
|
||||||
|
|
||||||
|
void getMemberCommonInfo(GroupMemberCommonReq groupMemberCommonReq, IGroupMemberCommonCallback iGroupMemberCommonCallback);
|
||||||
|
|
||||||
|
void getMemberExtInfo(GroupMemberExtReq groupMemberExtReq, IGroupMemberExtCallback iGroupMemberExtCallback);
|
||||||
|
|
||||||
|
void getMemberInfo(long j2, ArrayList<String> arrayList, boolean z, IOperateCallback iOperateCallback);
|
||||||
|
|
||||||
|
void getMemberInfoForMqq(long groupCode, ArrayList<String> uids, boolean z, IGroupMemberListCallback iGroupMemberListCallback);
|
||||||
|
|
||||||
|
void getNextMemberList(String sceneId, GroupMemberInfoListId groupMemberInfoListId, int i2, IGroupMemberListCallback iGroupMemberListCallback);
|
||||||
|
|
||||||
|
void getPrevMemberList(String sceneId, GroupMemberInfoListId groupMemberInfoListId, int i2, IGroupMemberListCallback iGroupMemberListCallback);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package com.tencent.qqnt.kernel.nativeinterface;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import com.tencent.qqnt.kernelpublic.nativeinterface.Contact;
|
||||||
|
|
||||||
public interface IKernelMsgListener {
|
public interface IKernelMsgListener {
|
||||||
void onAddSendMsg(MsgRecord msgRecord);
|
void onAddSendMsg(MsgRecord msgRecord);
|
||||||
@ -116,7 +117,7 @@ public interface IKernelMsgListener {
|
|||||||
|
|
||||||
void onSendMsgError(long j2, Contact contact, int i2, String str);
|
void onSendMsgError(long j2, Contact contact, int i2, String str);
|
||||||
|
|
||||||
void onSysMsgNotification(int i2, long j2, long j3, ArrayList<Byte> arrayList);
|
void onSysMsgNotification(int i2, long j2, long j3, boolean z, ArrayList<Byte> arrayList);
|
||||||
|
|
||||||
void onTempChatInfoUpdate(TempChatInfo tempChatInfo);
|
void onTempChatInfoUpdate(TempChatInfo tempChatInfo);
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package com.tencent.qqnt.kernel.nativeinterface;
|
package com.tencent.qqnt.kernel.nativeinterface;
|
||||||
|
|
||||||
|
import com.tencent.qqnt.kernelpublic.nativeinterface.Contact;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package com.tencent.qqnt.kernel.nativeinterface;
|
package com.tencent.qqnt.kernel.nativeinterface;
|
||||||
|
|
||||||
|
import com.tencent.qqnt.kernelpublic.nativeinterface.Contact;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public interface IKernelRichMediaService {
|
public interface IKernelRichMediaService {
|
||||||
|
@ -0,0 +1,63 @@
|
|||||||
|
package com.tencent.qqnt.kernel.nativeinterface;
|
||||||
|
|
||||||
|
public class MemberCommonInfo {
|
||||||
|
public long memberUin;
|
||||||
|
public int privilege;
|
||||||
|
public int shutUpTime;
|
||||||
|
public int uinFlag;
|
||||||
|
public int uinFlagExt;
|
||||||
|
public int uinMobileFlag;
|
||||||
|
|
||||||
|
public long getMemberUin() {
|
||||||
|
return this.memberUin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPrivilege() {
|
||||||
|
return this.privilege;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getShutUpTime() {
|
||||||
|
return this.shutUpTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getUinFlag() {
|
||||||
|
return this.uinFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getUinFlagExt() {
|
||||||
|
return this.uinFlagExt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getUinMobileFlag() {
|
||||||
|
return this.uinMobileFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMemberUin(long j2) {
|
||||||
|
this.memberUin = j2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPrivilege(int i2) {
|
||||||
|
this.privilege = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setShutUpTime(int i2) {
|
||||||
|
this.shutUpTime = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUinFlag(int i2) {
|
||||||
|
this.uinFlag = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUinFlagExt(int i2) {
|
||||||
|
this.uinFlagExt = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUinMobileFlag(int i2) {
|
||||||
|
this.uinMobileFlag = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "MemberCommonInfo{memberUin=" + this.memberUin + ",uinFlag=" + this.uinFlag + ",uinFlagExt=" + this.uinFlagExt + ",uinMobileFlag=" + this.uinMobileFlag + ",shutUpTime=" + this.shutUpTime + ",privilege=" + this.privilege + ",}";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
package com.tencent.qqnt.kernel.nativeinterface;
|
||||||
|
|
||||||
|
public class MemberCommonInfoFilter {
|
||||||
|
public int memberUin;
|
||||||
|
public int privilege;
|
||||||
|
public int shutUpTime;
|
||||||
|
public int uinFlag;
|
||||||
|
public int uinFlagExt;
|
||||||
|
public int uinMobileFlag;
|
||||||
|
|
||||||
|
public int getMemberUin() {
|
||||||
|
return this.memberUin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPrivilege() {
|
||||||
|
return this.privilege;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getShutUpTime() {
|
||||||
|
return this.shutUpTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getUinFlag() {
|
||||||
|
return this.uinFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getUinFlagExt() {
|
||||||
|
return this.uinFlagExt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getUinMobileFlag() {
|
||||||
|
return this.uinMobileFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMemberUin(int i2) {
|
||||||
|
this.memberUin = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPrivilege(int i2) {
|
||||||
|
this.privilege = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setShutUpTime(int i2) {
|
||||||
|
this.shutUpTime = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUinFlag(int i2) {
|
||||||
|
this.uinFlag = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUinFlagExt(int i2) {
|
||||||
|
this.uinFlagExt = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUinMobileFlag(int i2) {
|
||||||
|
this.uinMobileFlag = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "MemberCommonInfoFilter{memberUin=" + this.memberUin + ",uinFlag=" + this.uinFlag + ",uinFlagExt=" + this.uinFlagExt + ",uinMobileFlag=" + this.uinMobileFlag + ",shutUpTime=" + this.shutUpTime + ",privilege=" + this.privilege + ",}";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,110 @@
|
|||||||
|
package com.tencent.qqnt.kernel.nativeinterface;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class MemberExtInfo {
|
||||||
|
public int activeDay;
|
||||||
|
public int cmdUinFlagExt3Grocery;
|
||||||
|
public int level;
|
||||||
|
public int point;
|
||||||
|
public long specialTitleExpireTime;
|
||||||
|
public long uin;
|
||||||
|
public String strName = "";
|
||||||
|
public String nickName = "";
|
||||||
|
public String specialTitle = "";
|
||||||
|
public byte[] msgNeedField = new byte[0];
|
||||||
|
public ArrayList<MemberIcon> memberIconList = new ArrayList<>();
|
||||||
|
|
||||||
|
public int getActiveDay() {
|
||||||
|
return this.activeDay;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCmdUinFlagExt3Grocery() {
|
||||||
|
return this.cmdUinFlagExt3Grocery;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLevel() {
|
||||||
|
return this.level;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<MemberIcon> getMemberIconList() {
|
||||||
|
return this.memberIconList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getMsgNeedField() {
|
||||||
|
return this.msgNeedField;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNickName() {
|
||||||
|
return this.nickName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPoint() {
|
||||||
|
return this.point;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSpecialTitle() {
|
||||||
|
return this.specialTitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getSpecialTitleExpireTime() {
|
||||||
|
return this.specialTitleExpireTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStrName() {
|
||||||
|
return this.strName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getUin() {
|
||||||
|
return this.uin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setActiveDay(int i2) {
|
||||||
|
this.activeDay = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCmdUinFlagExt3Grocery(int i2) {
|
||||||
|
this.cmdUinFlagExt3Grocery = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLevel(int i2) {
|
||||||
|
this.level = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMemberIconList(ArrayList<MemberIcon> arrayList) {
|
||||||
|
this.memberIconList = arrayList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMsgNeedField(byte[] bArr) {
|
||||||
|
this.msgNeedField = bArr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNickName(String str) {
|
||||||
|
this.nickName = str;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPoint(int i2) {
|
||||||
|
this.point = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSpecialTitle(String str) {
|
||||||
|
this.specialTitle = str;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSpecialTitleExpireTime(long j2) {
|
||||||
|
this.specialTitleExpireTime = j2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStrName(String str) {
|
||||||
|
this.strName = str;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUin(long j2) {
|
||||||
|
this.uin = j2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "MemberExtInfo{uin=" + this.uin + ",point=" + this.point + ",activeDay=" + this.activeDay + ",level=" + this.level + ",strName=" + this.strName + ",nickName=" + this.nickName + ",specialTitle=" + this.specialTitle + ",specialTitleExpireTime=" + this.specialTitleExpireTime + ",msgNeedField=" + this.msgNeedField + ",cmdUinFlagExt3Grocery=" + this.cmdUinFlagExt3Grocery + ",memberIconList=" + this.memberIconList + ",}";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,171 @@
|
|||||||
|
package com.tencent.qqnt.kernel.nativeinterface;
|
||||||
|
|
||||||
|
public class MemberExtInfoFilter {
|
||||||
|
public int cmdUinFlagExt3Grocery;
|
||||||
|
public int dataTime;
|
||||||
|
public int levelName;
|
||||||
|
public int levelNameNew;
|
||||||
|
public int memberIcon;
|
||||||
|
public int memberInfoSeq;
|
||||||
|
public int memberLevelInfoActiveDay;
|
||||||
|
public int memberLevelInfoLevel;
|
||||||
|
public int memberLevelInfoName;
|
||||||
|
public int memberLevelInfoPoint;
|
||||||
|
public int memberLevelInfoUin;
|
||||||
|
public int msgNeedField;
|
||||||
|
public int nickName;
|
||||||
|
public int specialTitle;
|
||||||
|
public int sysShowFlag;
|
||||||
|
public int timeToUpdate;
|
||||||
|
public int userShowFlag;
|
||||||
|
public int userShowFlagNew;
|
||||||
|
|
||||||
|
public int getCmdUinFlagExt3Grocery() {
|
||||||
|
return this.cmdUinFlagExt3Grocery;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDataTime() {
|
||||||
|
return this.dataTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLevelName() {
|
||||||
|
return this.levelName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLevelNameNew() {
|
||||||
|
return this.levelNameNew;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMemberIcon() {
|
||||||
|
return this.memberIcon;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMemberInfoSeq() {
|
||||||
|
return this.memberInfoSeq;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMemberLevelInfoActiveDay() {
|
||||||
|
return this.memberLevelInfoActiveDay;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMemberLevelInfoLevel() {
|
||||||
|
return this.memberLevelInfoLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMemberLevelInfoName() {
|
||||||
|
return this.memberLevelInfoName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMemberLevelInfoPoint() {
|
||||||
|
return this.memberLevelInfoPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMemberLevelInfoUin() {
|
||||||
|
return this.memberLevelInfoUin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMsgNeedField() {
|
||||||
|
return this.msgNeedField;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNickName() {
|
||||||
|
return this.nickName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSpecialTitle() {
|
||||||
|
return this.specialTitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSysShowFlag() {
|
||||||
|
return this.sysShowFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTimeToUpdate() {
|
||||||
|
return this.timeToUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getUserShowFlag() {
|
||||||
|
return this.userShowFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getUserShowFlagNew() {
|
||||||
|
return this.userShowFlagNew;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCmdUinFlagExt3Grocery(int i2) {
|
||||||
|
this.cmdUinFlagExt3Grocery = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDataTime(int i2) {
|
||||||
|
this.dataTime = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLevelName(int i2) {
|
||||||
|
this.levelName = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLevelNameNew(int i2) {
|
||||||
|
this.levelNameNew = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMemberIcon(int i2) {
|
||||||
|
this.memberIcon = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMemberInfoSeq(int i2) {
|
||||||
|
this.memberInfoSeq = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMemberLevelInfoActiveDay(int i2) {
|
||||||
|
this.memberLevelInfoActiveDay = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMemberLevelInfoLevel(int i2) {
|
||||||
|
this.memberLevelInfoLevel = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMemberLevelInfoName(int i2) {
|
||||||
|
this.memberLevelInfoName = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMemberLevelInfoPoint(int i2) {
|
||||||
|
this.memberLevelInfoPoint = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMemberLevelInfoUin(int i2) {
|
||||||
|
this.memberLevelInfoUin = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMsgNeedField(int i2) {
|
||||||
|
this.msgNeedField = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNickName(int i2) {
|
||||||
|
this.nickName = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSpecialTitle(int i2) {
|
||||||
|
this.specialTitle = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSysShowFlag(int i2) {
|
||||||
|
this.sysShowFlag = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTimeToUpdate(int i2) {
|
||||||
|
this.timeToUpdate = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserShowFlag(int i2) {
|
||||||
|
this.userShowFlag = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserShowFlagNew(int i2) {
|
||||||
|
this.userShowFlagNew = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "MemberExtInfoFilter{memberLevelInfoUin=" + this.memberLevelInfoUin + ",memberLevelInfoPoint=" + this.memberLevelInfoPoint + ",memberLevelInfoActiveDay=" + this.memberLevelInfoActiveDay + ",memberLevelInfoLevel=" + this.memberLevelInfoLevel + ",memberLevelInfoName=" + this.memberLevelInfoName + ",levelName=" + this.levelName + ",dataTime=" + this.dataTime + ",userShowFlag=" + this.userShowFlag + ",sysShowFlag=" + this.sysShowFlag + ",timeToUpdate=" + this.timeToUpdate + ",nickName=" + this.nickName + ",specialTitle=" + this.specialTitle + ",levelNameNew=" + this.levelNameNew + ",userShowFlagNew=" + this.userShowFlagNew + ",msgNeedField=" + this.msgNeedField + ",cmdUinFlagExt3Grocery=" + this.cmdUinFlagExt3Grocery + ",memberIcon=" + this.memberIcon + ",memberInfoSeq=" + this.memberInfoSeq + ",}";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package com.tencent.qqnt.kernel.nativeinterface;
|
||||||
|
|
||||||
|
public class MemberIcon {
|
||||||
|
public int bizId;
|
||||||
|
public byte[] exInfo = new byte[0];
|
||||||
|
public long expireTime;
|
||||||
|
public int resId;
|
||||||
|
|
||||||
|
public int getBizId() {
|
||||||
|
return this.bizId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getExInfo() {
|
||||||
|
return this.exInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getExpireTime() {
|
||||||
|
return this.expireTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getResId() {
|
||||||
|
return this.resId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "MemberIcon{resId=" + this.resId + ",expireTime=" + this.expireTime + ",bizId=" + this.bizId + ",exInfo=" + this.exInfo + ",}";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,51 +1,146 @@
|
|||||||
package com.tencent.qqnt.kernel.nativeinterface;
|
package com.tencent.qqnt.kernel.nativeinterface;
|
||||||
|
|
||||||
public final class MemberInfo implements IKernelModel {
|
import com.tencent.qqnt.kernelpublic.nativeinterface.MemberRole;
|
||||||
String avatarPath;
|
|
||||||
String cardName;
|
|
||||||
int cardType;
|
|
||||||
boolean isDelete;
|
|
||||||
boolean isSpecialConcerned;
|
|
||||||
String nick;
|
|
||||||
String qid;
|
|
||||||
String remark;
|
|
||||||
MemberRole role;
|
|
||||||
long serialVersionUID;
|
|
||||||
int shutUpTime;
|
|
||||||
String uid;
|
|
||||||
long uin;
|
|
||||||
|
|
||||||
public MemberInfo() {
|
public final class MemberInfo implements IKernelModel {
|
||||||
this.serialVersionUID = 1L;
|
public int bigClubFlag;
|
||||||
this.uid = "";
|
public int bigClubLevel;
|
||||||
this.qid = "";
|
public int cardNameId;
|
||||||
this.nick = "";
|
public int cardType;
|
||||||
this.remark = "";
|
public int creditLevel;
|
||||||
this.cardName = "";
|
public int globalGroupLevel;
|
||||||
this.role = MemberRole.values()[0];
|
public int globalGroupPoint;
|
||||||
this.avatarPath = "";
|
public boolean isDelete;
|
||||||
|
public boolean isRobot;
|
||||||
|
public boolean isSpecialConcerned;
|
||||||
|
public boolean isSpecialShielded;
|
||||||
|
public int joinTime;
|
||||||
|
public int lastSpeakTime;
|
||||||
|
public int memberFlag;
|
||||||
|
public int memberFlagExt;
|
||||||
|
public int memberFlagExt2;
|
||||||
|
public int memberLevel;
|
||||||
|
public int memberMobileFlag;
|
||||||
|
public int memberTitleId;
|
||||||
|
public int mssVipType;
|
||||||
|
public int richFlag;
|
||||||
|
public int shutUpTime;
|
||||||
|
public long specialTitleExpireTime;
|
||||||
|
public long uin;
|
||||||
|
public int userShowFlag;
|
||||||
|
public int userShowFlagNew;
|
||||||
|
long serialVersionUID = 1;
|
||||||
|
public String uid = "";
|
||||||
|
public String qid = "";
|
||||||
|
public String nick = "";
|
||||||
|
public String remark = "";
|
||||||
|
public String cardName = "";
|
||||||
|
public MemberRole role = MemberRole.values()[0];
|
||||||
|
public String avatarPath = "";
|
||||||
|
public byte[] groupHonor = new byte[0];
|
||||||
|
public String memberSpecialTitle = "";
|
||||||
|
public String autoRemark = "";
|
||||||
|
|
||||||
|
public String getAutoRemark() {
|
||||||
|
return this.autoRemark;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getAvatarPath() {
|
public String getAvatarPath() {
|
||||||
return this.avatarPath;
|
return this.avatarPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getBigClubFlag() {
|
||||||
|
return this.bigClubFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBigClubLevel() {
|
||||||
|
return this.bigClubLevel;
|
||||||
|
}
|
||||||
|
|
||||||
public String getCardName() {
|
public String getCardName() {
|
||||||
return this.cardName;
|
return this.cardName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getCardNameId() {
|
||||||
|
return this.cardNameId;
|
||||||
|
}
|
||||||
|
|
||||||
public int getCardType() {
|
public int getCardType() {
|
||||||
return this.cardType;
|
return this.cardType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getCreditLevel() {
|
||||||
|
return this.creditLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getGlobalGroupLevel() {
|
||||||
|
return this.globalGroupLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getGlobalGroupPoint() {
|
||||||
|
return this.globalGroupPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getGroupHonor() {
|
||||||
|
return this.groupHonor;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean getIsDelete() {
|
public boolean getIsDelete() {
|
||||||
return this.isDelete;
|
return this.isDelete;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean getIsRobot() {
|
||||||
|
return this.isRobot;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean getIsSpecialConcerned() {
|
public boolean getIsSpecialConcerned() {
|
||||||
return this.isSpecialConcerned;
|
return this.isSpecialConcerned;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean getIsSpecialShielded() {
|
||||||
|
return this.isSpecialShielded;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getJoinTime() {
|
||||||
|
return this.joinTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLastSpeakTime() {
|
||||||
|
return this.lastSpeakTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMemberFlag() {
|
||||||
|
return this.memberFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMemberFlagExt() {
|
||||||
|
return this.memberFlagExt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMemberFlagExt2() {
|
||||||
|
return this.memberFlagExt2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMemberLevel() {
|
||||||
|
return this.memberLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMemberMobileFlag() {
|
||||||
|
return this.memberMobileFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMemberSpecialTitle() {
|
||||||
|
return this.memberSpecialTitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMemberTitleId() {
|
||||||
|
return this.memberTitleId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMssVipType() {
|
||||||
|
return this.mssVipType;
|
||||||
|
}
|
||||||
|
|
||||||
public String getNick() {
|
public String getNick() {
|
||||||
return this.nick;
|
return this.nick;
|
||||||
}
|
}
|
||||||
@ -58,6 +153,10 @@ public final class MemberInfo implements IKernelModel {
|
|||||||
return this.remark;
|
return this.remark;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getRichFlag() {
|
||||||
|
return this.richFlag;
|
||||||
|
}
|
||||||
|
|
||||||
public MemberRole getRole() {
|
public MemberRole getRole() {
|
||||||
return this.role;
|
return this.role;
|
||||||
}
|
}
|
||||||
@ -66,6 +165,10 @@ public final class MemberInfo implements IKernelModel {
|
|||||||
return this.shutUpTime;
|
return this.shutUpTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long getSpecialTitleExpireTime() {
|
||||||
|
return this.specialTitleExpireTime;
|
||||||
|
}
|
||||||
|
|
||||||
public String getUid() {
|
public String getUid() {
|
||||||
return this.uid;
|
return this.uid;
|
||||||
}
|
}
|
||||||
@ -74,26 +177,114 @@ public final class MemberInfo implements IKernelModel {
|
|||||||
return this.uin;
|
return this.uin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getUserShowFlag() {
|
||||||
|
return this.userShowFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getUserShowFlagNew() {
|
||||||
|
return this.userShowFlagNew;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAutoRemark(String str) {
|
||||||
|
this.autoRemark = str;
|
||||||
|
}
|
||||||
|
|
||||||
public void setAvatarPath(String str) {
|
public void setAvatarPath(String str) {
|
||||||
this.avatarPath = str;
|
this.avatarPath = str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setBigClubFlag(int i2) {
|
||||||
|
this.bigClubFlag = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBigClubLevel(int i2) {
|
||||||
|
this.bigClubLevel = i2;
|
||||||
|
}
|
||||||
|
|
||||||
public void setCardName(String str) {
|
public void setCardName(String str) {
|
||||||
this.cardName = str;
|
this.cardName = str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setCardNameId(int i2) {
|
||||||
|
this.cardNameId = i2;
|
||||||
|
}
|
||||||
|
|
||||||
public void setCardType(int i2) {
|
public void setCardType(int i2) {
|
||||||
this.cardType = i2;
|
this.cardType = i2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setCreditLevel(int i2) {
|
||||||
|
this.creditLevel = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGlobalGroupLevel(int i2) {
|
||||||
|
this.globalGroupLevel = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGlobalGroupPoint(int i2) {
|
||||||
|
this.globalGroupPoint = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGroupHonor(byte[] bArr) {
|
||||||
|
this.groupHonor = bArr;
|
||||||
|
}
|
||||||
|
|
||||||
public void setIsDelete(boolean z) {
|
public void setIsDelete(boolean z) {
|
||||||
this.isDelete = z;
|
this.isDelete = z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setIsRobot(boolean z) {
|
||||||
|
this.isRobot = z;
|
||||||
|
}
|
||||||
|
|
||||||
public void setIsSpecialConcerned(boolean z) {
|
public void setIsSpecialConcerned(boolean z) {
|
||||||
this.isSpecialConcerned = z;
|
this.isSpecialConcerned = z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setIsSpecialShielded(boolean z) {
|
||||||
|
this.isSpecialShielded = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setJoinTime(int i2) {
|
||||||
|
this.joinTime = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastSpeakTime(int i2) {
|
||||||
|
this.lastSpeakTime = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMemberFlag(int i2) {
|
||||||
|
this.memberFlag = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMemberFlagExt(int i2) {
|
||||||
|
this.memberFlagExt = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMemberFlagExt2(int i2) {
|
||||||
|
this.memberFlagExt2 = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMemberLevel(int i2) {
|
||||||
|
this.memberLevel = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMemberMobileFlag(int i2) {
|
||||||
|
this.memberMobileFlag = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMemberSpecialTitle(String str) {
|
||||||
|
this.memberSpecialTitle = str;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMemberTitleId(int i2) {
|
||||||
|
this.memberTitleId = i2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMssVipType(int i2) {
|
||||||
|
this.mssVipType = i2;
|
||||||
|
}
|
||||||
|
|
||||||
public void setNick(String str) {
|
public void setNick(String str) {
|
||||||
this.nick = str;
|
this.nick = str;
|
||||||
}
|
}
|
||||||
@ -106,6 +297,10 @@ public final class MemberInfo implements IKernelModel {
|
|||||||
this.remark = str;
|
this.remark = str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setRichFlag(int i2) {
|
||||||
|
this.richFlag = i2;
|
||||||
|
}
|
||||||
|
|
||||||
public void setRole(MemberRole memberRole) {
|
public void setRole(MemberRole memberRole) {
|
||||||
this.role = memberRole;
|
this.role = memberRole;
|
||||||
}
|
}
|
||||||
@ -114,6 +309,10 @@ public final class MemberInfo implements IKernelModel {
|
|||||||
this.shutUpTime = i2;
|
this.shutUpTime = i2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setSpecialTitleExpireTime(long j2) {
|
||||||
|
this.specialTitleExpireTime = j2;
|
||||||
|
}
|
||||||
|
|
||||||
public void setUid(String str) {
|
public void setUid(String str) {
|
||||||
this.uid = str;
|
this.uid = str;
|
||||||
}
|
}
|
||||||
@ -122,30 +321,16 @@ public final class MemberInfo implements IKernelModel {
|
|||||||
this.uin = j2;
|
this.uin = j2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public void setUserShowFlag(int i2) {
|
||||||
return "MemberInfo{uid=" + this.uid + ",qid=" + this.qid + ",uin=" + this.uin + ",nick=" + this.nick + ",remark=" + this.remark + ",cardType=" + this.cardType + ",cardName=" + this.cardName + ",role=" + this.role + ",avatarPath=" + this.avatarPath + ",shutUpTime=" + this.shutUpTime + ",isDelete=" + this.isDelete + ",isSpecialConcerned=" + this.isSpecialConcerned + ",}";
|
this.userShowFlag = i2;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MemberInfo(String str, String str2, long j2, String str3, String str4, int i2, String str5, MemberRole memberRole, String str6, int i3, boolean z, boolean z2) {
|
public void setUserShowFlagNew(int i2) {
|
||||||
this.serialVersionUID = 1L;
|
this.userShowFlagNew = i2;
|
||||||
this.uid = "";
|
|
||||||
this.qid = "";
|
|
||||||
this.nick = "";
|
|
||||||
this.remark = "";
|
|
||||||
this.cardName = "";
|
|
||||||
this.role = MemberRole.values()[0];
|
|
||||||
this.avatarPath = "";
|
|
||||||
this.uid = str;
|
|
||||||
this.qid = str2;
|
|
||||||
this.uin = j2;
|
|
||||||
this.nick = str3;
|
|
||||||
this.remark = str4;
|
|
||||||
this.cardType = i2;
|
|
||||||
this.cardName = str5;
|
|
||||||
this.role = memberRole;
|
|
||||||
this.avatarPath = str6;
|
|
||||||
this.shutUpTime = i3;
|
|
||||||
this.isDelete = z;
|
|
||||||
this.isSpecialConcerned = z2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "MemberInfo{uid=" + this.uid + ",qid=" + this.qid + ",uin=" + this.uin + ",nick=" + this.nick + ",remark=" + this.remark + ",cardType=" + this.cardType + ",cardName=" + this.cardName + ",role=" + this.role + ",avatarPath=" + this.avatarPath + ",shutUpTime=" + this.shutUpTime + ",isDelete=" + this.isDelete + ",isSpecialConcerned=" + this.isSpecialConcerned + ",isRobot=" + this.isRobot + ",groupHonor=" + this.groupHonor + ",memberLevel=" + this.memberLevel + ",globalGroupLevel=" + this.globalGroupLevel + ",globalGroupPoint=" + this.globalGroupPoint + ",memberTitleId=" + this.memberTitleId + ",memberSpecialTitle=" + this.memberSpecialTitle + ",specialTitleExpireTime=" + this.specialTitleExpireTime + ",userShowFlag=" + this.userShowFlag + ",userShowFlagNew=" + this.userShowFlagNew + ",richFlag=" + this.richFlag + ",mssVipType=" + this.mssVipType + ",bigClubLevel=" + this.bigClubLevel + ",bigClubFlag=" + this.bigClubFlag + ",autoRemark=" + this.autoRemark + ",creditLevel=" + this.creditLevel + ",joinTime=" + this.joinTime + ",lastSpeakTime=" + this.lastSpeakTime + ",memberFlag=" + this.memberFlag + ",memberFlagExt=" + this.memberFlagExt + ",memberMobileFlag=" + this.memberMobileFlag + ",memberFlagExt2=" + this.memberFlagExt2 + ",isSpecialShielded=" + this.isSpecialShielded + ",cardNameId=" + this.cardNameId + ",}";
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package com.tencent.qqnt.kernel.nativeinterface;
|
||||||
|
|
||||||
|
public class MemberLevelName {
|
||||||
|
public int level;
|
||||||
|
public String strName = "";
|
||||||
|
|
||||||
|
public int getLevel() {
|
||||||
|
return this.level;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStrName() {
|
||||||
|
return this.strName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "MemberLevelName{level=" + this.level + ",strName=" + this.strName + ",}";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,5 +1,7 @@
|
|||||||
package com.tencent.qqnt.kernel.nativeinterface;
|
package com.tencent.qqnt.kernel.nativeinterface;
|
||||||
|
|
||||||
|
import com.tencent.qqnt.kernelpublic.nativeinterface.Contact;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package com.tencent.qqnt.kernel.nativeinterface;
|
package com.tencent.qqnt.kernel.nativeinterface;
|
||||||
|
|
||||||
|
|
||||||
|
import com.tencent.qqnt.kernelpublic.nativeinterface.Contact;
|
||||||
|
|
||||||
public final class UnreadCntInfo {
|
public final class UnreadCntInfo {
|
||||||
UnreadCnt allUnreadCnt;
|
UnreadCnt allUnreadCnt;
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
package com.tencent.qqnt.kernel.nativeinterface;
|
package com.tencent.qqnt.kernelpublic.nativeinterface;
|
||||||
|
|
||||||
|
import com.tencent.qqnt.kernel.nativeinterface.IKernelModel;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package com.tencent.qqnt.kernel.nativeinterface;
|
package com.tencent.qqnt.kernelpublic.nativeinterface;
|
||||||
|
|
||||||
public enum MemberRole {
|
public enum MemberRole {
|
||||||
UNSPECIFIED,
|
UNSPECIFIED,
|
@ -2,6 +2,7 @@ package com.tencent.qqnt.msg.api;
|
|||||||
|
|
||||||
import com.tencent.mobileqq.qroute.QRouteApi;
|
import com.tencent.mobileqq.qroute.QRouteApi;
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.*;
|
import com.tencent.qqnt.kernel.nativeinterface.*;
|
||||||
|
import com.tencent.qqnt.kernelpublic.nativeinterface.Contact;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
@ -0,0 +1,75 @@
|
|||||||
|
package com.tencent.qqnt.troopmemberlist;
|
||||||
|
|
||||||
|
import androidx.lifecycle.LifecycleOwner;
|
||||||
|
|
||||||
|
import com.tencent.mobileqq.data.troop.TroopMemberInfo;
|
||||||
|
import com.tencent.mobileqq.data.troop.TroopMemberNickInfo;
|
||||||
|
import com.tencent.mobileqq.qroute.QRouteApi;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import kotlin.Deprecated;
|
||||||
|
import kotlin.Unit;
|
||||||
|
import kotlin.jvm.functions.Function1;
|
||||||
|
import kotlin.jvm.functions.Function2;
|
||||||
|
|
||||||
|
public interface ITroopMemberListRepoApi extends QRouteApi {
|
||||||
|
//void fetchGagTroopMemberInfo(@Nullable String str, @Nullable LifecycleOwner lifecycleOwner, boolean z, @NotNull String str2, @Nullable f fVar);
|
||||||
|
|
||||||
|
//void fetchTroopMemberInfo(@Nullable String str, @Nullable String str2, boolean z, @Nullable LifecycleOwner lifecycleOwner, @NotNull String str3, @Nullable g gVar);
|
||||||
|
|
||||||
|
//void fetchTroopMemberInfoWithExtInfo(@Nullable String str, @Nullable String str2, boolean z, @Nullable LifecycleOwner lifecycleOwner, @NotNull String str3, @Nullable g gVar);
|
||||||
|
|
||||||
|
//void fetchTroopMemberList(@Nullable String str, @Nullable LifecycleOwner lifecycleOwner, boolean z, @NotNull String str2, @Nullable f fVar);
|
||||||
|
|
||||||
|
//void fetchTroopMemberListWithExtInfo(@Nullable String str, @Nullable LifecycleOwner lifecycleOwner, boolean z, @NotNull String str2, @Nullable f fVar);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void fetchTroopMemberName(@Nullable String str, @Nullable String str2, @Nullable LifecycleOwner lifecycleOwner, @NotNull String str3, @Nullable Function1<? super TroopMemberNickInfo, Unit> cb);
|
||||||
|
|
||||||
|
void fetchTroopMemberName(@Nullable String str, @Nullable String str2, @NotNull String str3, @Nullable Function1<? super TroopMemberNickInfo, Unit> cb);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void fetchTroopMemberUid(@Nullable String str, @NotNull Function2<? super Boolean, ? super String, Unit> function2);
|
||||||
|
|
||||||
|
void fetchTroopMemberUid(@NotNull List<String> list, @NotNull Function2<? super Boolean, ? super Map<String, String>, Unit> function2);
|
||||||
|
|
||||||
|
void fetchTroopMemberUin(@Nullable String str, @NotNull Function2<? super Boolean, ? super String, Unit> function2);
|
||||||
|
|
||||||
|
void fetchTroopMemberUin(@NotNull List<String> list, @NotNull Function2<? super Boolean, ? super Map<String, String>, Unit> function2);
|
||||||
|
|
||||||
|
//void fetchTroopMemberUinListInfo(@Nullable String str, @Nullable List<String> list, boolean z, @Nullable LifecycleOwner lifecycleOwner, @NotNull String str2, @Nullable f fVar);
|
||||||
|
|
||||||
|
//void fetchTroopMemberUinListInfoWithExtInfo(@Nullable String str, @Nullable List<String> list, boolean z, @Nullable LifecycleOwner lifecycleOwner, @NotNull String str2, @Nullable f fVar);
|
||||||
|
|
||||||
|
//@Nullable
|
||||||
|
//TroopMemberInfo getTroopMemberFromCacheOrFetchAsync(@Nullable String str, @Nullable String str2, @Nullable LifecycleOwner lifecycleOwner, @NotNull String str3, @Nullable g gVar);
|
||||||
|
|
||||||
|
int getTroopMemberInfoDBVersion();
|
||||||
|
|
||||||
|
@Deprecated(message = "兼容旧逻辑,过渡用,新逻辑不要使用")
|
||||||
|
@Nullable
|
||||||
|
TroopMemberInfo getTroopMemberInfoSync(@Nullable String groupId, @Nullable String userId, @Nullable LifecycleOwner lifecycleOwner, @NotNull String from);
|
||||||
|
|
||||||
|
//@Deprecated(message = "兼容旧逻辑,过渡用,新逻辑不要使用")
|
||||||
|
//@Nullable
|
||||||
|
//TroopMemberInfo getTroopMemberInfoSync(@Nullable String str, @Nullable String str2, @Nullable LifecycleOwner lifecycleOwner, @NotNull String str3, long j);
|
||||||
|
|
||||||
|
//@Deprecated(message = "兼容旧逻辑,过渡用,新逻辑不要使用")
|
||||||
|
//@Nullable
|
||||||
|
//TroopMemberInfo getTroopMemberWithExtFromCacheOrFetchAsync(@Nullable String str, @Nullable String str2, @Nullable LifecycleOwner lifecycleOwner, @NotNull String str3, @Nullable g gVar);
|
||||||
|
|
||||||
|
//@Deprecated(message = "兼容旧逻辑,过渡用,新逻辑不要使用")
|
||||||
|
//@Nullable
|
||||||
|
//TroopMemberInfo getTroopMemberWithExtInfoSync(@Nullable String str, @Nullable String str2, @Nullable LifecycleOwner lifecycleOwner, @NotNull String str3);
|
||||||
|
|
||||||
|
boolean isTroopMemberInfoDBInited(@NotNull String str);
|
||||||
|
|
||||||
|
//void preLoadTroopMemberUinListInfo(@Nullable String str, @Nullable List<String> list, boolean z, @Nullable LifecycleOwner lifecycleOwner, @NotNull String str2, @Nullable f fVar);
|
||||||
|
}
|
@ -1,201 +0,0 @@
|
|||||||
@file:OptIn(DelicateCoroutinesApi::class)
|
|
||||||
|
|
||||||
package moe.fuqiuluo.qqinterface.servlet
|
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import com.tencent.mobileqq.app.QQAppInterface
|
|
||||||
import com.tencent.mobileqq.msf.core.MsfCore
|
|
||||||
import com.tencent.mobileqq.pb.ByteStringMicro
|
|
||||||
import com.tencent.qphone.base.remote.ToServiceMsg
|
|
||||||
import io.ktor.utils.io.core.BytePacketBuilder
|
|
||||||
import io.ktor.utils.io.core.readBytes
|
|
||||||
import io.ktor.utils.io.core.writeFully
|
|
||||||
import io.ktor.utils.io.core.writeInt
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
|
||||||
import kotlinx.coroutines.withTimeoutOrNull
|
|
||||||
import kotlinx.serialization.encodeToByteArray
|
|
||||||
|
|
||||||
import moe.fuqiuluo.shamrock.tools.slice
|
|
||||||
import moe.fuqiuluo.shamrock.utils.DeflateTools
|
|
||||||
import moe.fuqiuluo.shamrock.utils.PlatformUtils
|
|
||||||
import moe.fuqiuluo.shamrock.xposed.helper.AppRuntimeFetcher
|
|
||||||
import moe.fuqiuluo.shamrock.xposed.helper.internal.DynamicReceiver
|
|
||||||
import moe.fuqiuluo.shamrock.xposed.helper.internal.IPCRequest
|
|
||||||
import protobuf.oidb.TrpcOidb
|
|
||||||
import mqq.app.MobileQQ
|
|
||||||
import protobuf.auto.toByteArray
|
|
||||||
import tencent.im.oidb.oidb_sso
|
|
||||||
import kotlin.coroutines.CoroutineContext
|
|
||||||
import kotlin.coroutines.resume
|
|
||||||
|
|
||||||
internal abstract class BaseSvc {
|
|
||||||
companion object Default: CoroutineScope {
|
|
||||||
val currentUin: String
|
|
||||||
get() = app.currentAccountUin
|
|
||||||
|
|
||||||
val app: QQAppInterface
|
|
||||||
get() = AppRuntimeFetcher.appRuntime as QQAppInterface
|
|
||||||
|
|
||||||
fun createToServiceMsg(cmd: String): ToServiceMsg {
|
|
||||||
return ToServiceMsg("mobileqq.service", app.currentAccountUin, cmd)
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun sendOidbAW(cmd: String, cmdId: Int, serviceId: Int, data: ByteArray, trpc: Boolean = false, timeout: Long = 5000L): ByteArray? {
|
|
||||||
val seq = MsfCore.getNextSeq()
|
|
||||||
val buffer = withTimeoutOrNull(timeout) {
|
|
||||||
suspendCancellableCoroutine { continuation ->
|
|
||||||
launch(Dispatchers.Default) {
|
|
||||||
DynamicReceiver.register(IPCRequest(cmd, seq) {
|
|
||||||
val buffer = it.getByteArrayExtra("buffer")!!
|
|
||||||
continuation.resume(buffer)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if (trpc) sendTrpcOidb(cmd, cmdId, serviceId, data, seq)
|
|
||||||
else sendOidb(cmd, cmdId, serviceId, data, seq)
|
|
||||||
}
|
|
||||||
}.also {
|
|
||||||
if (it == null)
|
|
||||||
DynamicReceiver.unregister(seq)
|
|
||||||
}?.copyOf()
|
|
||||||
try {
|
|
||||||
if (buffer != null && buffer.size >= 5 && buffer[4] == 120.toByte()) {
|
|
||||||
val builder = BytePacketBuilder()
|
|
||||||
val deBuffer = DeflateTools.uncompress(buffer.slice(4))
|
|
||||||
builder.writeInt(deBuffer.size)
|
|
||||||
builder.writeFully(deBuffer)
|
|
||||||
return builder.build().readBytes()
|
|
||||||
}
|
|
||||||
} catch (_: Exception) { }
|
|
||||||
return buffer
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun sendBufferAW(cmd: String, isPb: Boolean, data: ByteArray, timeout: Long = 5000L): ByteArray? {
|
|
||||||
val seq = MsfCore.getNextSeq()
|
|
||||||
val buffer = withTimeoutOrNull<ByteArray?>(timeout) {
|
|
||||||
suspendCancellableCoroutine { continuation ->
|
|
||||||
launch(Dispatchers.Default) {
|
|
||||||
DynamicReceiver.register(IPCRequest(cmd, seq) {
|
|
||||||
val buffer = it.getByteArrayExtra("buffer")!!
|
|
||||||
continuation.resume(buffer)
|
|
||||||
})
|
|
||||||
sendBuffer(cmd, isPb, data, seq)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.also {
|
|
||||||
if (it == null)
|
|
||||||
DynamicReceiver.unregister(seq)
|
|
||||||
}?.copyOf()
|
|
||||||
try {
|
|
||||||
if (buffer != null && buffer.size >= 5 && buffer[4] == 120.toByte()) {
|
|
||||||
val builder = BytePacketBuilder()
|
|
||||||
val deBuffer = DeflateTools.uncompress(buffer.slice(4))
|
|
||||||
builder.writeInt(deBuffer.size)
|
|
||||||
builder.writeFully(deBuffer)
|
|
||||||
return builder.build().readBytes()
|
|
||||||
}
|
|
||||||
} catch (_: Exception) { }
|
|
||||||
return buffer
|
|
||||||
}
|
|
||||||
|
|
||||||
fun sendOidb(cmd: String, cmdId: Int, serviceId: Int, buffer: ByteArray, seq: Int = -1, trpc: Boolean = false) {
|
|
||||||
if (trpc) {
|
|
||||||
sendTrpcOidb(cmd, cmdId, serviceId, buffer, seq)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
val to = createToServiceMsg(cmd)
|
|
||||||
val oidb = oidb_sso.OIDBSSOPkg()
|
|
||||||
oidb.uint32_command.set(cmdId)
|
|
||||||
oidb.uint32_service_type.set(serviceId)
|
|
||||||
oidb.bytes_bodybuffer.set(ByteStringMicro.copyFrom(buffer))
|
|
||||||
oidb.str_client_version.set(PlatformUtils.getClientVersion(MobileQQ.getContext()))
|
|
||||||
to.putWupBuffer(oidb.toByteArray())
|
|
||||||
to.addAttribute("req_pb_protocol_flag", true)
|
|
||||||
if (seq != -1) {
|
|
||||||
to.addAttribute("shamrock_seq", seq)
|
|
||||||
}
|
|
||||||
app.sendToService(to)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun sendTrpcOidb(cmd: String, cmdId: Int, serviceId: Int, buffer: ByteArray, seq: Int = -1) {
|
|
||||||
val to = createToServiceMsg(cmd)
|
|
||||||
|
|
||||||
val oidb = TrpcOidb(
|
|
||||||
cmd = cmdId,
|
|
||||||
service = serviceId,
|
|
||||||
buffer = buffer,
|
|
||||||
flag = 1
|
|
||||||
)
|
|
||||||
to.putWupBuffer(oidb.toByteArray())
|
|
||||||
|
|
||||||
to.addAttribute("req_pb_protocol_flag", true)
|
|
||||||
if (seq != -1) {
|
|
||||||
to.addAttribute("shamrock_seq", seq)
|
|
||||||
}
|
|
||||||
app.sendToService(to)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun sendBuffer(cmd: String, isPb: Boolean, buffer: ByteArray, seq: Int = MsfCore.getNextSeq()) {
|
|
||||||
val toServiceMsg = ToServiceMsg("mobileqq.service", app.currentUin, cmd)
|
|
||||||
toServiceMsg.putWupBuffer(buffer)
|
|
||||||
toServiceMsg.addAttribute("req_pb_protocol_flag", isPb)
|
|
||||||
toServiceMsg.addAttribute("shamrock_seq", seq)
|
|
||||||
app.sendToService(toServiceMsg)
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
|
||||||
override val coroutineContext: CoroutineContext by lazy {
|
|
||||||
Dispatchers.IO.limitedParallelism(12)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected fun send(toServiceMsg: ToServiceMsg) {
|
|
||||||
app.sendToService(toServiceMsg)
|
|
||||||
}
|
|
||||||
|
|
||||||
protected suspend fun sendAW(toServiceMsg: ToServiceMsg, timeout: Long = 5000L): ByteArray? {
|
|
||||||
val seq = MsfCore.getNextSeq()
|
|
||||||
val buffer = withTimeoutOrNull<ByteArray?>(timeout) {
|
|
||||||
suspendCancellableCoroutine { continuation ->
|
|
||||||
launch(Dispatchers.Default) {
|
|
||||||
DynamicReceiver.register(IPCRequest(toServiceMsg.serviceCmd, seq) {
|
|
||||||
val buffer = it.getByteArrayExtra("buffer")!!
|
|
||||||
continuation.resume(buffer)
|
|
||||||
})
|
|
||||||
toServiceMsg.addAttribute("shamrock_seq", seq)
|
|
||||||
send(toServiceMsg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.also {
|
|
||||||
if (it == null) DynamicReceiver.unregister(seq)
|
|
||||||
}?.copyOf()
|
|
||||||
try {
|
|
||||||
if (buffer != null && buffer.size >= 5 && buffer[4] == 120.toByte()) {
|
|
||||||
val builder = BytePacketBuilder()
|
|
||||||
val deBuffer = DeflateTools.uncompress(buffer.slice(4))
|
|
||||||
builder.writeInt(deBuffer.size)
|
|
||||||
builder.writeFully(deBuffer)
|
|
||||||
return builder.build().readBytes()
|
|
||||||
}
|
|
||||||
} catch (_: Exception) { }
|
|
||||||
return buffer
|
|
||||||
}
|
|
||||||
|
|
||||||
protected fun sendExtra(cmd: String, builder: (Bundle) -> Unit) {
|
|
||||||
val toServiceMsg = createToServiceMsg(cmd)
|
|
||||||
builder(toServiceMsg.extraData)
|
|
||||||
app.sendToService(toServiceMsg)
|
|
||||||
}
|
|
||||||
|
|
||||||
protected fun sendPb(cmd: String, buffer: ByteArray, seq: Int) {
|
|
||||||
val toServiceMsg = createToServiceMsg(cmd)
|
|
||||||
toServiceMsg.putWupBuffer(buffer)
|
|
||||||
toServiceMsg.addAttribute("req_pb_protocol_flag", true)
|
|
||||||
toServiceMsg.addAttribute("shamrock_seq", seq)
|
|
||||||
app.sendToService(toServiceMsg)
|
|
||||||
}
|
|
||||||
}
|
|
@ -21,12 +21,14 @@ import moe.fuqiuluo.shamrock.tools.json
|
|||||||
import moe.fuqiuluo.shamrock.tools.slice
|
import moe.fuqiuluo.shamrock.tools.slice
|
||||||
import moe.fuqiuluo.shamrock.helper.Level
|
import moe.fuqiuluo.shamrock.helper.Level
|
||||||
import moe.fuqiuluo.shamrock.helper.LogCenter
|
import moe.fuqiuluo.shamrock.helper.LogCenter
|
||||||
|
import moe.fuqiuluo.shamrock.tools.decodeToOidb
|
||||||
|
import moe.fuqiuluo.shamrock.xposed.helper.QQInterfaces
|
||||||
import mqq.app.Packet
|
import mqq.app.Packet
|
||||||
import tencent.im.oidb.cmd0x11b2.oidb_0x11b2
|
import tencent.im.oidb.cmd0x11b2.oidb_0x11b2
|
||||||
import tencent.im.oidb.oidb_sso
|
import tencent.im.oidb.oidb_sso
|
||||||
import kotlin.coroutines.resume
|
import kotlin.coroutines.resume
|
||||||
|
|
||||||
internal object CardSvc: BaseSvc() {
|
internal object CardSvc: QQInterfaces() {
|
||||||
private val GetModelShowLock by lazy {
|
private val GetModelShowLock by lazy {
|
||||||
Mutex()
|
Mutex()
|
||||||
}
|
}
|
||||||
@ -46,7 +48,8 @@ internal object CardSvc: BaseSvc() {
|
|||||||
|
|
||||||
val resp = sendBufferAW("VipCustom.GetCustomOnlineStatus", false, uniPacket.encode())
|
val resp = sendBufferAW("VipCustom.GetCustomOnlineStatus", false, uniPacket.encode())
|
||||||
?: error("unable to fetch contact model_show")
|
?: error("unable to fetch contact model_show")
|
||||||
Packet.decodePacket(resp, "rsp", GetCustomOnlineStatusRsp()).sBuffer
|
val buffer = resp.wupBuffer
|
||||||
|
Packet.decodePacket(buffer, "rsp", GetCustomOnlineStatusRsp()).sBuffer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,10 +82,9 @@ internal object CardSvc: BaseSvc() {
|
|||||||
reqBody.uin.set(peerId)
|
reqBody.uin.set(peerId)
|
||||||
reqBody.jump_url.set("mqqapi://card/show_pslcard?src_type=internal&source=sharecard&version=1&uin=$peerId")
|
reqBody.jump_url.set("mqqapi://card/show_pslcard?src_type=internal&source=sharecard&version=1&uin=$peerId")
|
||||||
|
|
||||||
val buffer = sendOidbAW("OidbSvcTrpcTcp.0x11ca_0", 4790, 0, reqBody.toByteArray())
|
val fromServiceMsg = sendOidbAW("OidbSvcTrpcTcp.0x11ca_0", 4790, 0, reqBody.toByteArray())
|
||||||
?: error("unable to fetch contact ark_json_text")
|
?: error("unable to fetch contact ark_json_text")
|
||||||
val body = oidb_sso.OIDBSSOPkg()
|
val body = fromServiceMsg.decodeToOidb()
|
||||||
body.mergeFrom(buffer.slice(4))
|
|
||||||
val rsp = oidb_0x11b2.BusinessCardV3Rsp()
|
val rsp = oidb_0x11b2.BusinessCardV3Rsp()
|
||||||
rsp.mergeFrom(body.bytes_bodybuffer.get().toByteArray())
|
rsp.mergeFrom(body.bytes_bodybuffer.get().toByteArray())
|
||||||
return rsp.signed_ark_msg.get()
|
return rsp.signed_ark_msg.get()
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
package moe.fuqiuluo.qqinterface.servlet
|
package moe.fuqiuluo.qqinterface.servlet
|
||||||
|
|
||||||
import kotlinx.serialization.encodeToByteArray
|
import kotlinx.serialization.encodeToByteArray
|
||||||
|
import moe.fuqiuluo.shamrock.xposed.helper.QQInterfaces
|
||||||
import protobuf.auto.toByteArray
|
import protobuf.auto.toByteArray
|
||||||
|
|
||||||
import protobuf.oidb.cmd0x9082.Oidb0x9082
|
import protobuf.oidb.cmd0x9082.Oidb0x9082
|
||||||
|
|
||||||
internal object ChatSvc: BaseSvc() {
|
internal object ChatSvc: QQInterfaces() {
|
||||||
fun setGroupMessageCommentFace(peer: Long, msgSeq: ULong, faceIndex: String, isSet: Boolean) {
|
fun setGroupMessageCommentFace(peer: Long, msgSeq: ULong, faceIndex: String, isSet: Boolean) {
|
||||||
val serviceId = if (isSet) 1 else 2
|
val serviceId = if (isSet) 1 else 2
|
||||||
sendOidb("OidbSvcTrpcTcp.0x9082_$serviceId", 36994, serviceId, Oidb0x9082(
|
sendOidb("OidbSvcTrpcTcp.0x9082_$serviceId", 36994, serviceId, Oidb0x9082(
|
||||||
|
@ -6,9 +6,11 @@ import moe.fuqiuluo.qqinterface.servlet.transfile.RichProtoSvc
|
|||||||
import moe.fuqiuluo.shamrock.helper.Level
|
import moe.fuqiuluo.shamrock.helper.Level
|
||||||
import moe.fuqiuluo.shamrock.helper.LogCenter
|
import moe.fuqiuluo.shamrock.helper.LogCenter
|
||||||
import moe.fuqiuluo.shamrock.tools.EMPTY_BYTE_ARRAY
|
import moe.fuqiuluo.shamrock.tools.EMPTY_BYTE_ARRAY
|
||||||
|
import moe.fuqiuluo.shamrock.tools.decodeToOidb
|
||||||
import moe.fuqiuluo.shamrock.tools.slice
|
import moe.fuqiuluo.shamrock.tools.slice
|
||||||
import moe.fuqiuluo.shamrock.tools.toHexString
|
import moe.fuqiuluo.shamrock.tools.toHexString
|
||||||
import moe.fuqiuluo.shamrock.utils.DeflateTools
|
import moe.fuqiuluo.shamrock.utils.DeflateTools
|
||||||
|
import moe.fuqiuluo.shamrock.xposed.helper.QQInterfaces
|
||||||
import moe.fuqiuluo.symbols.decodeProtobuf
|
import moe.fuqiuluo.symbols.decodeProtobuf
|
||||||
import protobuf.oidb.cmd0x6d7.CreateFolderReq
|
import protobuf.oidb.cmd0x6d7.CreateFolderReq
|
||||||
import protobuf.oidb.cmd0x6d7.DeleteFolderReq
|
import protobuf.oidb.cmd0x6d7.DeleteFolderReq
|
||||||
@ -21,8 +23,10 @@ import tencent.im.oidb.cmd0x6d8.oidb_0x6d8
|
|||||||
import tencent.im.oidb.oidb_sso
|
import tencent.im.oidb.oidb_sso
|
||||||
import protobuf.group_file_common.FolderInfo as GroupFileCommonFolderInfo
|
import protobuf.group_file_common.FolderInfo as GroupFileCommonFolderInfo
|
||||||
import protobuf.auto.toByteArray
|
import protobuf.auto.toByteArray
|
||||||
|
import kotlin.time.Duration
|
||||||
|
import kotlin.time.Duration.Companion.seconds
|
||||||
|
|
||||||
internal object FileSvc: BaseSvc() {
|
internal object FileSvc: QQInterfaces() {
|
||||||
suspend fun createFileFolder(groupId: Long, folderName: String, parentFolderId: String = "/"): Result<GroupFileCommonFolderInfo> {
|
suspend fun createFileFolder(groupId: Long, folderName: String, parentFolderId: String = "/"): Result<GroupFileCommonFolderInfo> {
|
||||||
val data = Oidb0x6d7ReqBody(
|
val data = Oidb0x6d7ReqBody(
|
||||||
createFolder = CreateFolderReq(
|
createFolder = CreateFolderReq(
|
||||||
@ -32,10 +36,9 @@ internal object FileSvc: BaseSvc() {
|
|||||||
folderName = folderName
|
folderName = folderName
|
||||||
)
|
)
|
||||||
).toByteArray()
|
).toByteArray()
|
||||||
val resultBuffer = sendOidbAW("OidbSvc.0x6d7_0", 1751, 0, data)
|
val fromServiceMsg = sendOidbAW("OidbSvc.0x6d7_0", 1751, 0, data)
|
||||||
?: return Result.failure(Exception("unable to fetch result"))
|
?: return Result.failure(Exception("unable to fetch result"))
|
||||||
val oidbPkg = oidb_sso.OIDBSSOPkg()
|
val oidbPkg = fromServiceMsg.decodeToOidb()
|
||||||
oidbPkg.mergeFrom(resultBuffer.slice(4))
|
|
||||||
val rsp = oidbPkg.bytes_bodybuffer.get()
|
val rsp = oidbPkg.bytes_bodybuffer.get()
|
||||||
.toByteArray()
|
.toByteArray()
|
||||||
.decodeProtobuf<Oidb0x6d7RespBody>()
|
.decodeProtobuf<Oidb0x6d7RespBody>()
|
||||||
@ -46,21 +49,20 @@ internal object FileSvc: BaseSvc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
suspend fun deleteGroupFolder(groupId: Long, folderUid: String): Boolean {
|
suspend fun deleteGroupFolder(groupId: Long, folderUid: String): Boolean {
|
||||||
val buffer = sendOidbAW("OidbSvc.0x6d7_1", 1751, 1, Oidb0x6d7ReqBody(
|
val fromServiceMsg = sendOidbAW("OidbSvc.0x6d7_1", 1751, 1, Oidb0x6d7ReqBody(
|
||||||
deleteFolder = DeleteFolderReq(
|
deleteFolder = DeleteFolderReq(
|
||||||
groupCode = groupId.toULong(),
|
groupCode = groupId.toULong(),
|
||||||
appId = 3u,
|
appId = 3u,
|
||||||
folderId = folderUid
|
folderId = folderUid
|
||||||
)
|
)
|
||||||
).toByteArray()) ?: return false
|
).toByteArray()) ?: return false
|
||||||
val oidbPkg = oidb_sso.OIDBSSOPkg()
|
val oidbPkg = fromServiceMsg.decodeToOidb()
|
||||||
oidbPkg.mergeFrom(buffer.slice(4))
|
|
||||||
val rsp = oidbPkg.bytes_bodybuffer.get().toByteArray().decodeProtobuf<Oidb0x6d7RespBody>()
|
val rsp = oidbPkg.bytes_bodybuffer.get().toByteArray().decodeProtobuf<Oidb0x6d7RespBody>()
|
||||||
return rsp.deleteFolder?.retCode == 0
|
return rsp.deleteFolder?.retCode == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun moveGroupFolder(groupId: Long, folderUid: String, newParentFolderUid: String): Boolean {
|
suspend fun moveGroupFolder(groupId: Long, folderUid: String, newParentFolderUid: String): Boolean {
|
||||||
val buffer = sendOidbAW("OidbSvc.0x6d7_2", 1751, 2, Oidb0x6d7ReqBody(
|
val fromServiceMsg = sendOidbAW("OidbSvc.0x6d7_2", 1751, 2, Oidb0x6d7ReqBody(
|
||||||
moveFolder = MoveFolderReq(
|
moveFolder = MoveFolderReq(
|
||||||
groupCode = groupId.toULong(),
|
groupCode = groupId.toULong(),
|
||||||
appId = 3u,
|
appId = 3u,
|
||||||
@ -68,14 +70,13 @@ internal object FileSvc: BaseSvc() {
|
|||||||
parentFolderId = "/"
|
parentFolderId = "/"
|
||||||
)
|
)
|
||||||
).toByteArray()) ?: return false
|
).toByteArray()) ?: return false
|
||||||
val oidbPkg = oidb_sso.OIDBSSOPkg()
|
val oidbPkg = fromServiceMsg.decodeToOidb()
|
||||||
oidbPkg.mergeFrom(buffer.slice(4))
|
|
||||||
val rsp = oidbPkg.bytes_bodybuffer.get().toByteArray().decodeProtobuf<Oidb0x6d7RespBody>()
|
val rsp = oidbPkg.bytes_bodybuffer.get().toByteArray().decodeProtobuf<Oidb0x6d7RespBody>()
|
||||||
return rsp.moveFolder?.retCode == 0
|
return rsp.moveFolder?.retCode == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun renameFolder(groupId: Long, folderUid: String, name: String): Boolean {
|
suspend fun renameFolder(groupId: Long, folderUid: String, name: String): Boolean {
|
||||||
val buffer = sendOidbAW("OidbSvc.0x6d7_3", 1751, 3, Oidb0x6d7ReqBody(
|
val fromServiceMsg = sendOidbAW("OidbSvc.0x6d7_3", 1751, 3, Oidb0x6d7ReqBody(
|
||||||
renameFolder = RenameFolderReq(
|
renameFolder = RenameFolderReq(
|
||||||
groupCode = groupId.toULong(),
|
groupCode = groupId.toULong(),
|
||||||
appId = 3u,
|
appId = 3u,
|
||||||
@ -83,8 +84,7 @@ internal object FileSvc: BaseSvc() {
|
|||||||
folderName = name
|
folderName = name
|
||||||
)
|
)
|
||||||
).toByteArray()) ?: return false
|
).toByteArray()) ?: return false
|
||||||
val oidbPkg = oidb_sso.OIDBSSOPkg()
|
val oidbPkg = fromServiceMsg.decodeToOidb()
|
||||||
oidbPkg.mergeFrom(buffer.slice(4))
|
|
||||||
val rsp = oidbPkg.bytes_bodybuffer.get().toByteArray().decodeProtobuf<Oidb0x6d7RespBody>()
|
val rsp = oidbPkg.bytes_bodybuffer.get().toByteArray().decodeProtobuf<Oidb0x6d7RespBody>()
|
||||||
return rsp.renameFolder?.retCode == 0
|
return rsp.renameFolder?.retCode == 0
|
||||||
}
|
}
|
||||||
@ -101,8 +101,7 @@ internal object FileSvc: BaseSvc() {
|
|||||||
}
|
}
|
||||||
val result = sendOidbAW("OidbSvc.0x6d6_3", 1750, 3, oidb0x6d6ReqBody.toByteArray())
|
val result = sendOidbAW("OidbSvc.0x6d6_3", 1750, 3, oidb0x6d6ReqBody.toByteArray())
|
||||||
?: return false
|
?: return false
|
||||||
val oidbPkg = oidb_sso.OIDBSSOPkg()
|
val oidbPkg = result.decodeToOidb()
|
||||||
oidbPkg.mergeFrom(result.slice(4))
|
|
||||||
val rsp = oidb_0x6d6.RspBody().apply {
|
val rsp = oidb_0x6d6.RspBody().apply {
|
||||||
mergeFrom(oidbPkg.bytes_bodybuffer.get().toByteArray())
|
mergeFrom(oidbPkg.bytes_bodybuffer.get().toByteArray())
|
||||||
}
|
}
|
||||||
@ -120,8 +119,8 @@ internal object FileSvc: BaseSvc() {
|
|||||||
val fileCnt: Int
|
val fileCnt: Int
|
||||||
val limitCnt: Int
|
val limitCnt: Int
|
||||||
if (rspGetFileCntBuffer != null) {
|
if (rspGetFileCntBuffer != null) {
|
||||||
oidb_0x6d8.RspBody().mergeFrom(oidb_sso.OIDBSSOPkg()
|
oidb_0x6d8.RspBody().mergeFrom(
|
||||||
.mergeFrom(rspGetFileCntBuffer.slice(4))
|
rspGetFileCntBuffer.decodeToOidb()
|
||||||
.bytes_bodybuffer.get()
|
.bytes_bodybuffer.get()
|
||||||
.toByteArray()
|
.toByteArray()
|
||||||
).group_file_cnt_rsp.apply {
|
).group_file_cnt_rsp.apply {
|
||||||
@ -141,8 +140,8 @@ internal object FileSvc: BaseSvc() {
|
|||||||
val totalSpace: Long
|
val totalSpace: Long
|
||||||
val usedSpace: Long
|
val usedSpace: Long
|
||||||
if (rspGetFileSpaceBuffer != null) {
|
if (rspGetFileSpaceBuffer != null) {
|
||||||
oidb_0x6d8.RspBody().mergeFrom(oidb_sso.OIDBSSOPkg()
|
oidb_0x6d8.RspBody().mergeFrom(
|
||||||
.mergeFrom(rspGetFileSpaceBuffer.slice(4))
|
rspGetFileSpaceBuffer.decodeToOidb()
|
||||||
.bytes_bodybuffer.get()
|
.bytes_bodybuffer.get()
|
||||||
.toByteArray()).group_space_rsp.apply {
|
.toByteArray()).group_space_rsp.apply {
|
||||||
totalSpace = uint64_total_space.get()
|
totalSpace = uint64_total_space.get()
|
||||||
@ -187,15 +186,13 @@ internal object FileSvc: BaseSvc() {
|
|||||||
|
|
||||||
uint32_show_onlinedoc_folder.set(0)
|
uint32_show_onlinedoc_folder.set(0)
|
||||||
})
|
})
|
||||||
}.toByteArray(), timeout = 15_000L)
|
}.toByteArray(), timeout = 15.seconds)
|
||||||
|
|
||||||
return kotlin.runCatching {
|
return kotlin.runCatching {
|
||||||
val files = arrayListOf<FileInfo>()
|
val files = arrayListOf<FileInfo>()
|
||||||
val dirs = arrayListOf<FolderInfo>()
|
val dirs = arrayListOf<FolderInfo>()
|
||||||
if (rspGetFileListBuffer != null) {
|
if (rspGetFileListBuffer != null) {
|
||||||
val oidb = oidb_sso.OIDBSSOPkg().mergeFrom(rspGetFileListBuffer.slice(4).let {
|
val oidb = rspGetFileListBuffer.decodeToOidb()
|
||||||
if (it[0] == 0x78.toByte()) DeflateTools.uncompress(it) else it
|
|
||||||
})
|
|
||||||
|
|
||||||
oidb_0x6d8.RspBody().mergeFrom(oidb.bytes_bodybuffer.get().toByteArray())
|
oidb_0x6d8.RspBody().mergeFrom(oidb.bytes_bodybuffer.get().toByteArray())
|
||||||
.file_list_info_rsp.apply {
|
.file_list_info_rsp.apply {
|
||||||
@ -242,7 +239,7 @@ internal object FileSvc: BaseSvc() {
|
|||||||
|
|
||||||
GroupFileList(files, dirs)
|
GroupFileList(files, dirs)
|
||||||
}.onFailure {
|
}.onFailure {
|
||||||
LogCenter.log(it.message + ", buffer: ${rspGetFileListBuffer.toHexString()}", Level.ERROR)
|
LogCenter.log(it.message + ", buffer: ${rspGetFileListBuffer?.wupBuffer?.toHexString()}", Level.ERROR)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -13,13 +13,15 @@ import kotlinx.coroutines.GlobalScope
|
|||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
|
import moe.fuqiuluo.shamrock.tools.decodeToObject
|
||||||
import moe.fuqiuluo.shamrock.tools.slice
|
import moe.fuqiuluo.shamrock.tools.slice
|
||||||
import moe.fuqiuluo.shamrock.xposed.helper.AppRuntimeFetcher
|
import moe.fuqiuluo.shamrock.xposed.helper.AppRuntimeFetcher
|
||||||
|
import moe.fuqiuluo.shamrock.xposed.helper.QQInterfaces
|
||||||
import mqq.app.AppRuntime
|
import mqq.app.AppRuntime
|
||||||
import tencent.mobileim.structmsg.structmsg
|
import tencent.mobileim.structmsg.structmsg
|
||||||
import kotlin.coroutines.resume
|
import kotlin.coroutines.resume
|
||||||
|
|
||||||
internal object FriendSvc: BaseSvc() {
|
internal object FriendSvc: QQInterfaces() {
|
||||||
|
|
||||||
suspend fun getFriendList(refresh: Boolean): Result<List<Friends>> {
|
suspend fun getFriendList(refresh: Boolean): Result<List<Friends>> {
|
||||||
val runtime = AppRuntimeFetcher.appRuntime
|
val runtime = AppRuntimeFetcher.appRuntime
|
||||||
@ -91,8 +93,7 @@ internal object FriendSvc: BaseSvc() {
|
|||||||
ArrayList()
|
ArrayList()
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
val msg = structmsg.RspSystemMsgNew()
|
val msg = respBuffer.decodeToObject(structmsg.RspSystemMsgNew())
|
||||||
msg.mergeFrom(respBuffer.slice(4))
|
|
||||||
return msg.friendmsgs.get()
|
return msg.friendmsgs.get()
|
||||||
} catch (err: Throwable) {
|
} catch (err: Throwable) {
|
||||||
requestFriendSystemMsgNew(msgNum, latestFriendSeq, latestGroupSeq, retryCnt - 1)
|
requestFriendSystemMsgNew(msgNum, latestFriendSeq, latestGroupSeq, retryCnt - 1)
|
||||||
|
@ -19,9 +19,12 @@ import moe.fuqiuluo.qqinterface.servlet.structures.SlowModeInfo
|
|||||||
import moe.fuqiuluo.shamrock.helper.Level
|
import moe.fuqiuluo.shamrock.helper.Level
|
||||||
import moe.fuqiuluo.shamrock.helper.LogCenter
|
import moe.fuqiuluo.shamrock.helper.LogCenter
|
||||||
import moe.fuqiuluo.shamrock.tools.EMPTY_BYTE_ARRAY
|
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.tools.slice
|
||||||
import moe.fuqiuluo.shamrock.utils.PlatformUtils
|
import moe.fuqiuluo.shamrock.utils.PlatformUtils
|
||||||
import moe.fuqiuluo.shamrock.xposed.helper.NTServiceFetcher
|
import moe.fuqiuluo.shamrock.xposed.helper.NTServiceFetcher
|
||||||
|
import moe.fuqiuluo.shamrock.xposed.helper.QQInterfaces
|
||||||
import moe.fuqiuluo.symbols.decodeProtobuf
|
import moe.fuqiuluo.symbols.decodeProtobuf
|
||||||
import protobuf.auto.toByteArray
|
import protobuf.auto.toByteArray
|
||||||
import protobuf.guild.GetGuildFeedsReq
|
import protobuf.guild.GetGuildFeedsReq
|
||||||
@ -44,7 +47,7 @@ import protobuf.qweb.QWebRsp
|
|||||||
import tencent.im.oidb.oidb_sso
|
import tencent.im.oidb.oidb_sso
|
||||||
import kotlin.coroutines.resume
|
import kotlin.coroutines.resume
|
||||||
|
|
||||||
internal object GProSvc: BaseSvc() {
|
internal object GProSvc: QQInterfaces() {
|
||||||
fun getSelfTinyId(): ULong {
|
fun getSelfTinyId(): ULong {
|
||||||
val service = app.getRuntimeService(IGPSService::class.java, "all")
|
val service = app.getRuntimeService(IGPSService::class.java, "all")
|
||||||
return service.selfTinyId.toULong()
|
return service.selfTinyId.toULong()
|
||||||
@ -57,12 +60,8 @@ internal object GProSvc: BaseSvc() {
|
|||||||
u2 = Oidb0xf57U2(1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u)
|
u2 = Oidb0xf57U2(1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u)
|
||||||
),
|
),
|
||||||
guildInfo = Oidb0xf57GuildInfo(guildId = guildId)
|
guildInfo = Oidb0xf57GuildInfo(guildId = guildId)
|
||||||
).toByteArray())
|
).toByteArray()) ?: return Result.failure(Exception("unable to send packet"))
|
||||||
val body = oidb_sso.OIDBSSOPkg()
|
val body = respBuffer.decodeToOidb()
|
||||||
if (respBuffer == null) {
|
|
||||||
return Result.failure(Exception("unable to send packet"))
|
|
||||||
}
|
|
||||||
body.mergeFrom(respBuffer.slice(4))
|
|
||||||
return runCatching {
|
return runCatching {
|
||||||
body.bytes_bodybuffer.get()
|
body.bytes_bodybuffer.get()
|
||||||
.toByteArray()
|
.toByteArray()
|
||||||
@ -71,7 +70,7 @@ internal object GProSvc: BaseSvc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getGuildFeeds(guildId: ULong, channelId: ULong, startIndex: Int): Result<GetGuildFeedsRsp> {
|
suspend fun getGuildFeeds(guildId: ULong, channelId: ULong, startIndex: Int): Result<GetGuildFeedsRsp> {
|
||||||
val buffer = sendBufferAW("QChannelSvr.trpc.qchannel.commreader.ComReader.GetGuildFeeds", true, QWebReq(
|
val fromServiceMsg = sendBufferAW("QChannelSvr.trpc.qchannel.commreader.ComReader.GetGuildFeeds", true, QWebReq(
|
||||||
seq = 10,
|
seq = 10,
|
||||||
qua = PlatformUtils.getQUA(),
|
qua = PlatformUtils.getQUA(),
|
||||||
deviceInfo = DEFAULT_DEVICE_INFO,
|
deviceInfo = DEFAULT_DEVICE_INFO,
|
||||||
@ -92,7 +91,7 @@ internal object GProSvc: BaseSvc() {
|
|||||||
QWebExtInfo("tiny_id", getSelfTinyId().toString()),
|
QWebExtInfo("tiny_id", getSelfTinyId().toString()),
|
||||||
)
|
)
|
||||||
).toByteArray()) ?: return Result.failure(Exception("unable to send packet"))
|
).toByteArray()) ?: return Result.failure(Exception("unable to send packet"))
|
||||||
val webRsp = buffer.slice(4).decodeProtobuf<QWebRsp>()
|
val webRsp = fromServiceMsg.decodeToObject<QWebRsp>()
|
||||||
if(webRsp.buffer == null) return Result.failure(Exception("server error"))
|
if(webRsp.buffer == null) return Result.failure(Exception("server error"))
|
||||||
val wupBuffer = webRsp.buffer!!
|
val wupBuffer = webRsp.buffer!!
|
||||||
val feeds = wupBuffer.decodeProtobuf<GetGuildFeedsRsp>()
|
val feeds = wupBuffer.decodeProtobuf<GetGuildFeedsRsp>()
|
||||||
@ -188,12 +187,8 @@ internal object GProSvc: BaseSvc() {
|
|||||||
memberId = 0uL,
|
memberId = 0uL,
|
||||||
tinyId = memberTinyId,
|
tinyId = memberTinyId,
|
||||||
guildId = guildId
|
guildId = guildId
|
||||||
).toByteArray())
|
).toByteArray()) ?: return Result.failure(Exception("unable to send packet"))
|
||||||
val body = oidb_sso.OIDBSSOPkg()
|
val body = respBuffer.decodeToOidb()
|
||||||
if (respBuffer == null) {
|
|
||||||
return Result.failure(Exception("unable to send packet"))
|
|
||||||
}
|
|
||||||
body.mergeFrom(respBuffer.slice(4))
|
|
||||||
return runCatching {
|
return runCatching {
|
||||||
body.bytes_bodybuffer.get().toByteArray().decodeProtobuf<Oidb0xf88Rsp>().userInfo!!
|
body.bytes_bodybuffer.get().toByteArray().decodeProtobuf<Oidb0xf88Rsp>().userInfo!!
|
||||||
}
|
}
|
||||||
|
@ -10,13 +10,16 @@ import com.tencent.mobileqq.app.BusinessHandlerFactory
|
|||||||
import com.tencent.mobileqq.app.QQAppInterface
|
import com.tencent.mobileqq.app.QQAppInterface
|
||||||
import com.tencent.mobileqq.data.troop.TroopInfo
|
import com.tencent.mobileqq.data.troop.TroopInfo
|
||||||
import com.tencent.mobileqq.data.troop.TroopMemberInfo
|
import com.tencent.mobileqq.data.troop.TroopMemberInfo
|
||||||
|
import com.tencent.mobileqq.data.troop.TroopMemberNickInfo
|
||||||
import com.tencent.mobileqq.pb.ByteStringMicro
|
import com.tencent.mobileqq.pb.ByteStringMicro
|
||||||
|
import com.tencent.mobileqq.qroute.QRoute
|
||||||
import com.tencent.mobileqq.troop.api.ITroopInfoService
|
import com.tencent.mobileqq.troop.api.ITroopInfoService
|
||||||
import com.tencent.mobileqq.troop.api.ITroopMemberInfoService
|
import com.tencent.mobileqq.troop.api.ITroopMemberInfoService
|
||||||
import com.tencent.protofile.join_group_link.join_group_link
|
import com.tencent.protofile.join_group_link.join_group_link
|
||||||
import com.tencent.qphone.base.remote.ToServiceMsg
|
import com.tencent.qphone.base.remote.ToServiceMsg
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.MemberInfo
|
import com.tencent.qqnt.kernel.nativeinterface.MemberInfo
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
||||||
|
import com.tencent.qqnt.troopmemberlist.ITroopMemberListRepoApi
|
||||||
import friendlist.stUinInfo
|
import friendlist.stUinInfo
|
||||||
import io.ktor.client.call.body
|
import io.ktor.client.call.body
|
||||||
import io.ktor.client.request.forms.MultiPartFormDataContent
|
import io.ktor.client.request.forms.MultiPartFormDataContent
|
||||||
@ -41,12 +44,10 @@ import kotlinx.coroutines.sync.Mutex
|
|||||||
import kotlinx.coroutines.sync.withLock
|
import kotlinx.coroutines.sync.withLock
|
||||||
import kotlinx.coroutines.withTimeoutOrNull
|
import kotlinx.coroutines.withTimeoutOrNull
|
||||||
import kotlinx.serialization.ExperimentalSerializationApi
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
import kotlinx.serialization.encodeToByteArray
|
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import kotlinx.serialization.json.JsonElement
|
import kotlinx.serialization.json.JsonElement
|
||||||
import kotlinx.serialization.json.decodeFromStream
|
import kotlinx.serialization.json.decodeFromStream
|
||||||
import kotlinx.serialization.json.jsonObject
|
import kotlinx.serialization.json.jsonObject
|
||||||
|
|
||||||
import moe.fuqiuluo.qqinterface.servlet.TicketSvc.getLongUin
|
import moe.fuqiuluo.qqinterface.servlet.TicketSvc.getLongUin
|
||||||
import moe.fuqiuluo.qqinterface.servlet.TicketSvc.getUin
|
import moe.fuqiuluo.qqinterface.servlet.TicketSvc.getUin
|
||||||
import moe.fuqiuluo.qqinterface.servlet.structures.GroupAtAllRemainInfo
|
import moe.fuqiuluo.qqinterface.servlet.structures.GroupAtAllRemainInfo
|
||||||
@ -55,6 +56,7 @@ import moe.fuqiuluo.qqinterface.servlet.structures.ProhibitedMemberInfo
|
|||||||
import moe.fuqiuluo.shamrock.helper.Level
|
import moe.fuqiuluo.shamrock.helper.Level
|
||||||
import moe.fuqiuluo.shamrock.helper.LogCenter
|
import moe.fuqiuluo.shamrock.helper.LogCenter
|
||||||
import moe.fuqiuluo.shamrock.helper.MessageHelper
|
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.EssenceMessage
|
||||||
import moe.fuqiuluo.shamrock.remote.service.data.GroupAnnouncement
|
import moe.fuqiuluo.shamrock.remote.service.data.GroupAnnouncement
|
||||||
import moe.fuqiuluo.shamrock.remote.service.data.GroupAnnouncementMessage
|
import moe.fuqiuluo.shamrock.remote.service.data.GroupAnnouncementMessage
|
||||||
@ -68,17 +70,21 @@ import moe.fuqiuluo.shamrock.tools.asJsonObject
|
|||||||
import moe.fuqiuluo.shamrock.tools.asLong
|
import moe.fuqiuluo.shamrock.tools.asLong
|
||||||
import moe.fuqiuluo.shamrock.tools.asString
|
import moe.fuqiuluo.shamrock.tools.asString
|
||||||
import moe.fuqiuluo.shamrock.tools.asStringOrNull
|
import moe.fuqiuluo.shamrock.tools.asStringOrNull
|
||||||
|
import moe.fuqiuluo.shamrock.tools.decodeToObject
|
||||||
|
import moe.fuqiuluo.shamrock.tools.decodeToOidb
|
||||||
import moe.fuqiuluo.shamrock.tools.ifNullOrEmpty
|
import moe.fuqiuluo.shamrock.tools.ifNullOrEmpty
|
||||||
import moe.fuqiuluo.shamrock.tools.putBuf32Long
|
import moe.fuqiuluo.shamrock.tools.putBuf32Long
|
||||||
import moe.fuqiuluo.shamrock.tools.slice
|
|
||||||
import moe.fuqiuluo.shamrock.utils.FileUtils
|
import moe.fuqiuluo.shamrock.utils.FileUtils
|
||||||
import moe.fuqiuluo.shamrock.utils.PlatformUtils
|
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_8_VER
|
||||||
import moe.fuqiuluo.shamrock.xposed.helper.AppRuntimeFetcher
|
import moe.fuqiuluo.shamrock.xposed.helper.AppRuntimeFetcher
|
||||||
import moe.fuqiuluo.shamrock.xposed.helper.NTServiceFetcher
|
import moe.fuqiuluo.shamrock.xposed.helper.NTServiceFetcher
|
||||||
import protobuf.oidb.cmd0xf16.Oidb0xf16
|
import moe.fuqiuluo.shamrock.xposed.helper.QQInterfaces
|
||||||
import protobuf.oidb.cmd0xf16.SetGroupRemarkReq
|
|
||||||
import mqq.app.MobileQQ
|
import mqq.app.MobileQQ
|
||||||
import protobuf.auto.toByteArray
|
import protobuf.auto.toByteArray
|
||||||
|
import protobuf.oidb.cmd0xf16.Oidb0xf16
|
||||||
|
import protobuf.oidb.cmd0xf16.SetGroupRemarkReq
|
||||||
import tencent.im.group.group_member_info
|
import tencent.im.group.group_member_info
|
||||||
import tencent.im.oidb.cmd0x88d.oidb_0x88d
|
import tencent.im.oidb.cmd0x88d.oidb_0x88d
|
||||||
import tencent.im.oidb.cmd0x899.oidb_0x899
|
import tencent.im.oidb.cmd0x899.oidb_0x899
|
||||||
@ -96,8 +102,9 @@ import java.lang.reflect.Method
|
|||||||
import java.lang.reflect.Modifier
|
import java.lang.reflect.Modifier
|
||||||
import java.nio.ByteBuffer
|
import java.nio.ByteBuffer
|
||||||
import kotlin.coroutines.resume
|
import kotlin.coroutines.resume
|
||||||
|
import kotlin.time.Duration.Companion.seconds
|
||||||
|
|
||||||
internal object GroupSvc: BaseSvc() {
|
internal object GroupSvc: QQInterfaces() {
|
||||||
private const val GET_MEMBER_ROLE_BY_NT = false
|
private const val GET_MEMBER_ROLE_BY_NT = false
|
||||||
|
|
||||||
private val RefreshTroopMemberInfoLock by lazy {
|
private val RefreshTroopMemberInfoLock by lazy {
|
||||||
@ -114,15 +121,14 @@ internal object GroupSvc: BaseSvc() {
|
|||||||
private lateinit var METHOD_REQ_MODIFY_GROUP_NAME: Method
|
private lateinit var METHOD_REQ_MODIFY_GROUP_NAME: Method
|
||||||
|
|
||||||
suspend fun getGroupRemainAtAllRemain (groupId: Long): Result<GroupAtAllRemainInfo> {
|
suspend fun getGroupRemainAtAllRemain (groupId: Long): Result<GroupAtAllRemainInfo> {
|
||||||
val buffer = sendOidbAW("OidbSvcTrpcTcp.0x8a7_0", 2215, 0, cmd0x8a7.ReqBody().apply {
|
val fromServiceMsg = sendOidbAW("OidbSvcTrpcTcp.0x8a7_0", 2215, 0, cmd0x8a7.ReqBody().apply {
|
||||||
uint32_sub_cmd.set(1)
|
uint32_sub_cmd.set(1)
|
||||||
uint32_limit_interval_type_for_uin.set(2)
|
uint32_limit_interval_type_for_uin.set(2)
|
||||||
uint32_limit_interval_type_for_group.set(1)
|
uint32_limit_interval_type_for_group.set(1)
|
||||||
uint64_uin.set(getLongUin())
|
uint64_uin.set(getLongUin())
|
||||||
uint64_group_code.set(groupId)
|
uint64_group_code.set(groupId)
|
||||||
}.toByteArray(), trpc = true) ?: return Result.failure(RuntimeException("[oidb] timeout"))
|
}.toByteArray(), trpc = true) ?: return Result.failure(RuntimeException("[oidb] timeout"))
|
||||||
val body = oidb_sso.OIDBSSOPkg()
|
val body = fromServiceMsg.decodeToOidb()
|
||||||
body.mergeFrom(buffer.slice(4))
|
|
||||||
if(body.uint32_result.get() != 0) {
|
if(body.uint32_result.get() != 0) {
|
||||||
return Result.failure(RuntimeException(body.str_error_msg.get()))
|
return Result.failure(RuntimeException(body.str_error_msg.get()))
|
||||||
}
|
}
|
||||||
@ -135,7 +141,7 @@ internal object GroupSvc: BaseSvc() {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
suspend fun getProhibitedMemberList(groupId: Long): Result<List<ProhibitedMemberInfo>> {
|
suspend fun getProhibitedMemberList(groupId: Long): Result<List<ProhibitedMemberInfo>> {
|
||||||
val buffer = sendOidbAW("OidbSvc.0x899_0", 2201, 0, oidb_0x899.ReqBody().apply {
|
val fromServiceMsg = sendOidbAW("OidbSvc.0x899_0", 2201, 0, oidb_0x899.ReqBody().apply {
|
||||||
uint64_group_code.set(groupId)
|
uint64_group_code.set(groupId)
|
||||||
uint64_start_uin.set(0)
|
uint64_start_uin.set(0)
|
||||||
uint32_identify_flag.set(6)
|
uint32_identify_flag.set(6)
|
||||||
@ -144,8 +150,7 @@ internal object GroupSvc: BaseSvc() {
|
|||||||
uint32_shutup_timestap.set(0)
|
uint32_shutup_timestap.set(0)
|
||||||
})
|
})
|
||||||
}.toByteArray()) ?: return Result.failure(RuntimeException("[oidb] timeout"))
|
}.toByteArray()) ?: return Result.failure(RuntimeException("[oidb] timeout"))
|
||||||
val body = oidb_sso.OIDBSSOPkg()
|
val body = fromServiceMsg.decodeToOidb()
|
||||||
body.mergeFrom(buffer.slice(4))
|
|
||||||
if(body.uint32_result.get() != 0) {
|
if(body.uint32_result.get() != 0) {
|
||||||
return Result.failure(RuntimeException(body.str_error_msg.get()))
|
return Result.failure(RuntimeException(body.str_error_msg.get()))
|
||||||
}
|
}
|
||||||
@ -165,22 +170,62 @@ internal object GroupSvc: BaseSvc() {
|
|||||||
sendOidb("OidbSvc.0xed3", 3795, 1, req.toByteArray())
|
sendOidb("OidbSvc.0xed3", 3795, 1, req.toByteArray())
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getGroupMemberList(groupId: Long, refresh: Boolean): Result<List<TroopMemberInfo>> {
|
|
||||||
val service = app.getRuntimeService(ITroopMemberInfoService::class.java, "all")
|
|
||||||
var memberList = service.getAllTroopMembers(groupId.toString())
|
|
||||||
if (refresh || memberList == null) {
|
|
||||||
memberList = requestTroopMemberInfo(service, groupId).onFailure {
|
|
||||||
return Result.failure(Exception("获取群成员列表失败"))
|
|
||||||
}.getOrThrow()
|
|
||||||
}
|
|
||||||
|
|
||||||
getGroupInfo(groupId, true).onSuccess {
|
suspend fun getGroupMemberList(groupId: Long, refresh: Boolean): Result<HashMap<String, MemberInfo>> {
|
||||||
if(it.wMemberNum > memberList.size) {
|
val kernelService = NTServiceFetcher.kernelService
|
||||||
return getGroupMemberList(groupId, true)
|
val sessionService = kernelService.wrapperSession
|
||||||
|
val service = sessionService.groupService
|
||||||
|
val uids = suspendCancellableCoroutine { continuation ->
|
||||||
|
service.getAllMemberList(groupId, refresh) { _, _, groupMemberListResult ->
|
||||||
|
continuation.resume(groupMemberListResult?.ids?.map {
|
||||||
|
it.uid
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
val memberMap = suspendCancellableCoroutine { continuation ->
|
||||||
|
service.getMemberInfoForMqq(groupId, ArrayList(uids ?: emptyList()), refresh) { _, _, groupMemberListResult ->
|
||||||
|
continuation.resume(groupMemberListResult.infos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// val extInfo = suspendCancellableCoroutine { continuation ->
|
||||||
|
// service.getMemberExtInfo(GroupMemberExtReq().apply {
|
||||||
|
// this.groupCode = groupId
|
||||||
|
// this.beginUin = 0.toString()
|
||||||
|
// this.groupType = ""
|
||||||
|
// this.memberExtFilter = MemberExtInfoFilter().apply {
|
||||||
|
// this.memberLevelInfoName = 1
|
||||||
|
// this.memberLevelInfoUin = 1
|
||||||
|
// this.nickName = 1
|
||||||
|
// this.specialTitle = 1
|
||||||
|
// this.memberLevelInfoActiveDay = 1
|
||||||
|
// }
|
||||||
|
// this.richCardNameVer = "1"
|
||||||
|
// this.sourceType = 1
|
||||||
|
// this.uinList = ArrayList(memberMap.values.toList().map {
|
||||||
|
// it.uin
|
||||||
|
// })
|
||||||
|
// }) { _, _, groupMemberExtListResult ->
|
||||||
|
// continuation.resume(groupMemberExtListResult)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
return Result.success(memberMap)
|
||||||
|
|
||||||
|
// var memberList = service.getAllTroopMembers(groupId.toString())
|
||||||
|
// if (refresh || memberList == null) {
|
||||||
|
// memberList = requestTroopMemberInfo(service, groupId).onFailure {
|
||||||
|
// return Result.failure(Exception("获取群成员列表失败"))
|
||||||
|
// }.getOrThrow()
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// getGroupInfo(groupId, true).onSuccess {
|
||||||
|
// if(it.wMemberNum > memberList.size) {
|
||||||
|
// return getGroupMemberList(groupId, true)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return Result.success(memberList)
|
||||||
|
|
||||||
return Result.success(memberList)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getGroupList(refresh: Boolean): Result<List<TroopInfo>> {
|
suspend fun getGroupList(refresh: Boolean): Result<List<TroopInfo>> {
|
||||||
@ -203,10 +248,10 @@ internal object GroupSvc: BaseSvc() {
|
|||||||
toServiceMsg.extraData.putLong("troop_code", groupId)
|
toServiceMsg.extraData.putLong("troop_code", groupId)
|
||||||
toServiceMsg.extraData.putBoolean("is_admin", false)
|
toServiceMsg.extraData.putBoolean("is_admin", false)
|
||||||
toServiceMsg.extraData.putInt("from", 0)
|
toServiceMsg.extraData.putInt("from", 0)
|
||||||
val buffer = sendAW(toServiceMsg)
|
val fromServiceMsg = sendToServiceMsgAW(toServiceMsg) ?: return@timeout Result.failure(Exception("获取群信息超时"))
|
||||||
val uniPacket = UniPacket(true)
|
val uniPacket = UniPacket(true)
|
||||||
uniPacket.encodeName = "utf-8"
|
uniPacket.encodeName = "utf-8"
|
||||||
uniPacket.decode(buffer)
|
uniPacket.decode(fromServiceMsg.wupBuffer)
|
||||||
val respBatchProcess = uniPacket.getByClass("RespBatchProcess", RespBatchProcess())
|
val respBatchProcess = uniPacket.getByClass("RespBatchProcess", RespBatchProcess())
|
||||||
val batchRespInfo = oidb_0x88d.RspBody().mergeFrom(oidb_sso.OIDBSSOPkg()
|
val batchRespInfo = oidb_0x88d.RspBody().mergeFrom(oidb_sso.OIDBSSOPkg()
|
||||||
.mergeFrom(respBatchProcess.batch_response_list.first().buffer)
|
.mergeFrom(respBatchProcess.batch_response_list.first().buffer)
|
||||||
@ -242,14 +287,24 @@ internal object GroupSvc: BaseSvc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
suspend fun setGroupUniqueTitle(groupId: Long, userId: Long, title: String) {
|
suspend fun setGroupUniqueTitle(groupId: Long, userId: Long, title: String) {
|
||||||
val localMemberInfo = getTroopMemberInfoByUin(groupId, userId, true).getOrThrow()
|
var nick = getTroopMemberInfoByUinV2(groupId, userId, true).getOrThrow().let {
|
||||||
|
it.troopnick.ifEmpty { it.troopremark.ifNullOrEmpty("") }
|
||||||
|
}
|
||||||
|
if (PlatformUtils.getQQVersionCode() > QQ_9_0_65_VER && nick == null) {
|
||||||
|
nick = getTroopMemberNickByUin(groupId, userId)?.let {
|
||||||
|
it.troopNick
|
||||||
|
.ifNullOrEmpty(it.friendNick)
|
||||||
|
.ifNullOrEmpty(it.showName)
|
||||||
|
.ifNullOrEmpty(it.autoRemark)
|
||||||
|
.ifNullOrEmpty(it.colorNick)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val req = Oidb_0x8fc.ReqBody()
|
val req = Oidb_0x8fc.ReqBody()
|
||||||
req.uint64_group_code.set(groupId)
|
req.uint64_group_code.set(groupId)
|
||||||
val memberInfo = Oidb_0x8fc.MemberInfo()
|
val memberInfo = Oidb_0x8fc.MemberInfo()
|
||||||
memberInfo.uint64_uin.set(userId)
|
memberInfo.uint64_uin.set(userId)
|
||||||
memberInfo.bytes_uin_name.set(ByteStringMicro.copyFromUtf8(localMemberInfo.troopnick.ifEmpty {
|
memberInfo.bytes_uin_name.set(ByteStringMicro.copyFromUtf8(nick))
|
||||||
localMemberInfo.troopremark.ifNullOrEmpty("")
|
|
||||||
}))
|
|
||||||
memberInfo.bytes_special_title.set(ByteStringMicro.copyFromUtf8(title))
|
memberInfo.bytes_special_title.set(ByteStringMicro.copyFromUtf8(title))
|
||||||
memberInfo.uint32_special_title_expire_time.set(-1)
|
memberInfo.uint32_special_title_expire_time.set(-1)
|
||||||
req.rpt_mem_level_info.add(memberInfo)
|
req.rpt_mem_level_info.add(memberInfo)
|
||||||
@ -270,7 +325,7 @@ internal object GroupSvc: BaseSvc() {
|
|||||||
info.dwFlag = 1
|
info.dwFlag = 1
|
||||||
createToServiceMsg.extraData.putSerializable("vecUinInfo", arrayListOf(info))
|
createToServiceMsg.extraData.putSerializable("vecUinInfo", arrayListOf(info))
|
||||||
createToServiceMsg.extraData.putLong("dwNewSeq", 0L)
|
createToServiceMsg.extraData.putLong("dwNewSeq", 0L)
|
||||||
send(createToServiceMsg)
|
sendToServiceMsg(createToServiceMsg)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,13 +341,12 @@ internal object GroupSvc: BaseSvc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
suspend fun setEssenceMessage(groupId: Long, seq: Long, rand: Long): Pair<Boolean, String> {
|
suspend fun setEssenceMessage(groupId: Long, seq: Long, rand: Long): Pair<Boolean, String> {
|
||||||
val buffer = sendOidbAW("OidbSvc.0xeac_1", 3756, 1, oidb_0xeac.ReqBody().apply {
|
val fromServiceMsg = sendOidbAW("OidbSvc.0xeac_1", 3756, 1, oidb_0xeac.ReqBody().apply {
|
||||||
group_code.set(groupId)
|
group_code.set(groupId)
|
||||||
msg_seq.set(seq.toInt())
|
msg_seq.set(seq.toInt())
|
||||||
msg_random.set(rand.toInt())
|
msg_random.set(rand.toInt())
|
||||||
}.toByteArray()) ?: return Pair(false, "unknown error")
|
}.toByteArray()) ?: return Pair(false, "unknown error")
|
||||||
val body = oidb_sso.OIDBSSOPkg()
|
val body = fromServiceMsg.decodeToOidb()
|
||||||
body.mergeFrom(buffer.slice(4))
|
|
||||||
val result = oidb_0xeac.RspBody().mergeFrom(body.bytes_bodybuffer.get().toByteArray())
|
val result = oidb_0xeac.RspBody().mergeFrom(body.bytes_bodybuffer.get().toByteArray())
|
||||||
return if (result.wording.has()) {
|
return if (result.wording.has()) {
|
||||||
LogCenter.log("设置群精华失败: ${result.wording.get()}")
|
LogCenter.log("设置群精华失败: ${result.wording.get()}")
|
||||||
@ -304,16 +358,12 @@ internal object GroupSvc: BaseSvc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
suspend fun deleteEssenceMessage(groupId: Long, seq: Long, rand: Long): Pair<Boolean, String> {
|
suspend fun deleteEssenceMessage(groupId: Long, seq: Long, rand: Long): Pair<Boolean, String> {
|
||||||
val buffer = sendOidbAW("OidbSvc.0xeac_2", 3756, 2, oidb_0xeac.ReqBody().apply {
|
val fromServiceMsg = sendOidbAW("OidbSvc.0xeac_2", 3756, 2, oidb_0xeac.ReqBody().apply {
|
||||||
group_code.set(groupId)
|
group_code.set(groupId)
|
||||||
msg_seq.set(seq.toInt())
|
msg_seq.set(seq.toInt())
|
||||||
msg_random.set(rand.toInt())
|
msg_random.set(rand.toInt())
|
||||||
}.toByteArray())
|
}.toByteArray()) ?: return Pair(false, "unknown error")
|
||||||
val body = oidb_sso.OIDBSSOPkg()
|
val body = fromServiceMsg.decodeToOidb()
|
||||||
if (buffer == null) {
|
|
||||||
return Pair(false, "unknown error")
|
|
||||||
}
|
|
||||||
body.mergeFrom(buffer.slice(4))
|
|
||||||
val result = oidb_0xeac.RspBody().mergeFrom(body.bytes_bodybuffer.get().toByteArray())
|
val result = oidb_0xeac.RspBody().mergeFrom(body.bytes_bodybuffer.get().toByteArray())
|
||||||
return if (result.wording.has()) {
|
return if (result.wording.has()) {
|
||||||
LogCenter.log("移除群精华失败: ${result.wording.get()}")
|
LogCenter.log("移除群精华失败: ${result.wording.get()}")
|
||||||
@ -405,11 +455,11 @@ internal object GroupSvc: BaseSvc() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return when(getTroopMemberInfoByUinViaNt(groupId, memberUin, 3000).getOrNull()?.role) {
|
return when(getTroopMemberInfoByUinViaNt(groupId, memberUin, 3000).getOrNull()?.role) {
|
||||||
com.tencent.qqnt.kernel.nativeinterface.MemberRole.STRANGER -> MemberRole.Stranger
|
com.tencent.qqnt.kernelpublic.nativeinterface.MemberRole.STRANGER -> MemberRole.Stranger
|
||||||
com.tencent.qqnt.kernel.nativeinterface.MemberRole.MEMBER -> MemberRole.Member
|
com.tencent.qqnt.kernelpublic.nativeinterface.MemberRole.MEMBER -> MemberRole.Member
|
||||||
com.tencent.qqnt.kernel.nativeinterface.MemberRole.ADMIN -> MemberRole.Admin
|
com.tencent.qqnt.kernelpublic.nativeinterface.MemberRole.ADMIN -> MemberRole.Admin
|
||||||
com.tencent.qqnt.kernel.nativeinterface.MemberRole.OWNER -> MemberRole.Owner
|
com.tencent.qqnt.kernelpublic.nativeinterface.MemberRole.OWNER -> MemberRole.Owner
|
||||||
com.tencent.qqnt.kernel.nativeinterface.MemberRole.UNSPECIFIED, null -> when (memberUin) {
|
com.tencent.qqnt.kernelpublic.nativeinterface.MemberRole.UNSPECIFIED, null -> when (memberUin) {
|
||||||
getOwner(groupId) -> MemberRole.Owner
|
getOwner(groupId) -> MemberRole.Owner
|
||||||
in getAdminList(groupId) -> MemberRole.Admin
|
in getAdminList(groupId) -> MemberRole.Admin
|
||||||
else -> MemberRole.Member
|
else -> MemberRole.Member
|
||||||
@ -427,12 +477,21 @@ internal object GroupSvc: BaseSvc() {
|
|||||||
return groupInfo.troopowneruin == app.account
|
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
|
val service = app
|
||||||
.getRuntimeService(ITroopInfoService::class.java, "all")
|
.getRuntimeService(ITroopInfoService::class.java, "all")
|
||||||
|
|
||||||
val groupInfo = service.getTroopInfo(groupId.toString())
|
val groupInfo = service.getTroopInfo(groupId.toString())
|
||||||
|
|
||||||
return groupInfo.isAdmin || groupInfo.troopowneruin == app.account
|
return groupInfo.isAdmin || groupInfo.troopowneruin == app.account
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -527,65 +586,38 @@ internal object GroupSvc: BaseSvc() {
|
|||||||
reqBody.get_ark.set(true)
|
reqBody.get_ark.set(true)
|
||||||
reqBody.type.set(1)
|
reqBody.type.set(1)
|
||||||
reqBody.group_code.set(groupId)
|
reqBody.group_code.set(groupId)
|
||||||
val buffer = sendBufferAW("GroupSvc.JoinGroupLink", true, reqBody.toByteArray())
|
val fromServiceMsg = sendBufferAW("GroupSvc.JoinGroupLink", true, reqBody.toByteArray())
|
||||||
?: error("unable to fetch contact ark_json_text")
|
?: error("unable to fetch contact ark_json_text")
|
||||||
val body = join_group_link.RspBody()
|
val body = fromServiceMsg.decodeToObject(join_group_link.RspBody())
|
||||||
body.mergeFrom(buffer.slice(4))
|
|
||||||
return body.signed_ark.get().toStringUtf8()
|
return body.signed_ark.get().toStringUtf8()
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getTroopMemberInfoByUin(
|
fun getTroopMemberInfoByUinFromNt(
|
||||||
groupId: Long,
|
groupId: Long,
|
||||||
uin: Long,
|
uin: Long
|
||||||
refresh: Boolean = false
|
|
||||||
): Result<TroopMemberInfo> {
|
): Result<TroopMemberInfo> {
|
||||||
val service = app.getRuntimeService(ITroopMemberInfoService::class.java, "all")
|
return kotlin.runCatching {
|
||||||
var info = service.getTroopMember(groupId.toString(), uin.toString())
|
val api = QRoute.api(ITroopMemberListRepoApi::class.java)
|
||||||
if (refresh || !service.isMemberInCache(groupId.toString(), uin.toString()) || info == null || info.troopnick == null) {
|
api.getTroopMemberInfoSync(groupId.toString(), uin.toString(), null, groupId.toString())
|
||||||
info = requestTroopMemberInfo(service, groupId, uin).getOrNull()
|
?: throw Exception("获取群成员信息失败: NT兼容接口已废弃")
|
||||||
}
|
}
|
||||||
if (info == null) {
|
}
|
||||||
info = getTroopMemberInfoByUinViaNt(groupId, uin).getOrNull()?.let {
|
|
||||||
TroopMemberInfo().apply {
|
suspend fun getTroopMemberNickByUin(
|
||||||
troopnick = it.cardName
|
groupId: Long,
|
||||||
friendnick = it.nick
|
uin: Long
|
||||||
|
): TroopMemberNickInfo? {
|
||||||
|
if (PlatformUtils.getQQVersionCode() > QQ_9_0_65_VER) {
|
||||||
|
val api = QRoute.api(ITroopMemberListRepoApi::class.java)
|
||||||
|
return withTimeoutOrNull(5.seconds) {
|
||||||
|
suspendCancellableCoroutine<TroopMemberNickInfo> { continuation ->
|
||||||
|
api.fetchTroopMemberName(groupId.toString(), uin.toString(), null, groupId.toString()) {
|
||||||
|
continuation.resume(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
if (info != null && (info.alias == null || info.alias.isBlank())) {
|
|
||||||
val req = group_member_info.ReqBody()
|
|
||||||
req.uint64_group_code.set(groupId)
|
|
||||||
req.uint64_uin.set(uin.toLong())
|
|
||||||
req.bool_new_client.set(true)
|
|
||||||
req.uint32_client_type.set(1)
|
|
||||||
req.uint32_rich_card_name_ver.set(1)
|
|
||||||
val respBuffer = sendBufferAW("group_member_card.get_group_member_card_info", true, req.toByteArray())
|
|
||||||
if (respBuffer != null) {
|
|
||||||
val rsp = group_member_info.RspBody()
|
|
||||||
rsp.mergeFrom(respBuffer.slice(4))
|
|
||||||
if (rsp.msg_meminfo.str_location.has()) {
|
|
||||||
info.alias = rsp.msg_meminfo.str_location.get().toStringUtf8()
|
|
||||||
}
|
|
||||||
if (rsp.msg_meminfo.uint32_age.has()) {
|
|
||||||
info.age = rsp.msg_meminfo.uint32_age.get().toByte()
|
|
||||||
}
|
|
||||||
if (rsp.msg_meminfo.bytes_group_honor.has()) {
|
|
||||||
val honorBytes = rsp.msg_meminfo.bytes_group_honor.get().toByteArray()
|
|
||||||
val honor = troop_honor.GroupUserCardHonor()
|
|
||||||
honor.mergeFrom(honorBytes)
|
|
||||||
info.level = honor.level.get()
|
|
||||||
// 10315: medal_id not real group level
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (err: Throwable) {
|
|
||||||
LogCenter.log(err.stackTraceToString(), Level.WARN)
|
|
||||||
}
|
|
||||||
return if (info != null) {
|
|
||||||
Result.success(info)
|
|
||||||
} else {
|
} else {
|
||||||
Result.failure(Exception("获取群成员信息失败"))
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -594,11 +626,16 @@ internal object GroupSvc: BaseSvc() {
|
|||||||
uin: Long,
|
uin: Long,
|
||||||
refresh: Boolean = false
|
refresh: Boolean = false
|
||||||
): Result<TroopMemberInfo> {
|
): Result<TroopMemberInfo> {
|
||||||
|
var info: TroopMemberInfo? = null
|
||||||
|
if (PlatformUtils.getQQVersionCode() <= QQ_9_0_65_VER) {
|
||||||
val service = app.getRuntimeService(ITroopMemberInfoService::class.java, "all")
|
val service = app.getRuntimeService(ITroopMemberInfoService::class.java, "all")
|
||||||
var info = service.getTroopMember(groupId.toString(), uin.toString())
|
info = service.getTroopMember(groupId.toString(), uin.toString())
|
||||||
if (refresh || !service.isMemberInCache(groupId.toString(), uin.toString()) || info == null || info.troopnick == null) {
|
if (refresh || !service.isMemberInCache(groupId.toString(), uin.toString()) || info == null || info.troopnick == null) {
|
||||||
info = requestTroopMemberInfo(service, groupId, uin, timeout = 2000).getOrNull()
|
info = requestTroopMemberInfo(service, groupId, uin, timeout = 2000).getOrNull()
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
info = getTroopMemberInfoByUinFromNt(groupId, uin).getOrNull()
|
||||||
|
}
|
||||||
if (info == null) {
|
if (info == null) {
|
||||||
info = getTroopMemberInfoByUinViaNt(groupId, uin, timeout = 2000L).getOrNull()?.let {
|
info = getTroopMemberInfoByUinViaNt(groupId, uin, timeout = 2000L).getOrNull()?.let {
|
||||||
TroopMemberInfo().apply {
|
TroopMemberInfo().apply {
|
||||||
@ -607,6 +644,7 @@ internal object GroupSvc: BaseSvc() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (PlatformUtils.getQQVersionCode() <= QQ_9_0_8_VER) {
|
||||||
try {
|
try {
|
||||||
if (info != null && (info.alias == null || info.alias.isBlank())) {
|
if (info != null && (info.alias == null || info.alias.isBlank())) {
|
||||||
val req = group_member_info.ReqBody()
|
val req = group_member_info.ReqBody()
|
||||||
@ -615,10 +653,9 @@ internal object GroupSvc: BaseSvc() {
|
|||||||
req.bool_new_client.set(true)
|
req.bool_new_client.set(true)
|
||||||
req.uint32_client_type.set(1)
|
req.uint32_client_type.set(1)
|
||||||
req.uint32_rich_card_name_ver.set(1)
|
req.uint32_rich_card_name_ver.set(1)
|
||||||
val respBuffer = sendBufferAW("group_member_card.get_group_member_card_info", true, req.toByteArray(), timeout = 2000)
|
val respBuffer = sendBufferAW("group_member_card.get_group_member_card_info", true, req.toByteArray(), timeout = 2.seconds)
|
||||||
if (respBuffer != null) {
|
if (respBuffer != null) {
|
||||||
val rsp = group_member_info.RspBody()
|
val rsp = respBuffer.decodeToObject(group_member_info.RspBody())
|
||||||
rsp.mergeFrom(respBuffer.slice(4))
|
|
||||||
if (rsp.msg_meminfo.str_location.has()) {
|
if (rsp.msg_meminfo.str_location.has()) {
|
||||||
info.alias = rsp.msg_meminfo.str_location.get().toStringUtf8()
|
info.alias = rsp.msg_meminfo.str_location.get().toStringUtf8()
|
||||||
}
|
}
|
||||||
@ -637,6 +674,7 @@ internal object GroupSvc: BaseSvc() {
|
|||||||
} catch (err: Throwable) {
|
} catch (err: Throwable) {
|
||||||
LogCenter.log(err.stackTraceToString(), Level.WARN)
|
LogCenter.log(err.stackTraceToString(), Level.WARN)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return if (info != null) {
|
return if (info != null) {
|
||||||
Result.success(info)
|
Result.success(info)
|
||||||
} else {
|
} else {
|
||||||
@ -644,7 +682,7 @@ internal object GroupSvc: BaseSvc() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getTroopMemberInfoByUinViaNt(
|
private suspend fun getTroopMemberInfoByUinViaNt(
|
||||||
groupId: Long,
|
groupId: Long,
|
||||||
qq: Long,
|
qq: Long,
|
||||||
timeout: Long = 5000L
|
timeout: Long = 5000L
|
||||||
@ -673,7 +711,7 @@ internal object GroupSvc: BaseSvc() {
|
|||||||
return if (info != null) {
|
return if (info != null) {
|
||||||
Result.success(info)
|
Result.success(info)
|
||||||
} else {
|
} else {
|
||||||
Result.failure(Exception("获取群成员信息失败"))
|
Result.failure(Exception("[NT]获取群成员信息失败"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -895,7 +933,7 @@ internal object GroupSvc: BaseSvc() {
|
|||||||
}
|
}
|
||||||
val respBuffer = sendBufferAW("ProfileService.Pb.ReqSystemMsgAction.Group", true, req.toByteArray())
|
val respBuffer = sendBufferAW("ProfileService.Pb.ReqSystemMsgAction.Group", true, req.toByteArray())
|
||||||
?: return Result.failure(Exception("操作失败"))
|
?: return Result.failure(Exception("操作失败"))
|
||||||
val rsp = structmsg.RspSystemMsgAction().mergeFrom(respBuffer.slice(4))
|
val rsp = respBuffer.decodeToObject(structmsg.RspSystemMsgAction())
|
||||||
return if (rsp.head.result.has()) {
|
return if (rsp.head.result.has()) {
|
||||||
if (rsp.head.result.get() == 0) {
|
if (rsp.head.result.get() == 0) {
|
||||||
Result.success(rsp.msg_detail.get())
|
Result.success(rsp.msg_detail.get())
|
||||||
@ -946,8 +984,7 @@ internal object GroupSvc: BaseSvc() {
|
|||||||
ArrayList()
|
ArrayList()
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
val msg = structmsg.RspSystemMsgNew()
|
val msg = respBuffer.decodeToObject(structmsg.RspSystemMsgNew())
|
||||||
msg.mergeFrom(respBuffer.slice(4))
|
|
||||||
return msg.groupmsgs.get().orEmpty()
|
return msg.groupmsgs.get().orEmpty()
|
||||||
} catch (err: Throwable) {
|
} catch (err: Throwable) {
|
||||||
requestGroupSystemMsgNew(msgNum, reqMsgType, latestFriendSeq, latestGroupSeq, retryCnt - 1)
|
requestGroupSystemMsgNew(msgNum, reqMsgType, latestFriendSeq, latestGroupSeq, retryCnt - 1)
|
||||||
@ -1140,8 +1177,7 @@ internal object GroupSvc: BaseSvc() {
|
|||||||
return if (buffer == null) {
|
return if (buffer == null) {
|
||||||
Result.failure(Exception("操作失败"))
|
Result.failure(Exception("操作失败"))
|
||||||
} else {
|
} else {
|
||||||
val body = oidb_sso.OIDBSSOPkg()
|
val body = buffer.decodeToOidb()
|
||||||
body.mergeFrom(buffer.slice(4))
|
|
||||||
val rsp = oidb_0xeb7.RspBody()
|
val rsp = oidb_0xeb7.RspBody()
|
||||||
rsp.mergeFrom(body.bytes_bodybuffer.get().toByteArray())
|
rsp.mergeFrom(body.bytes_bodybuffer.get().toByteArray())
|
||||||
val doneInfo = rsp.signInWriteRsp.doneInfo
|
val doneInfo = rsp.signInWriteRsp.doneInfo
|
||||||
|
@ -2,13 +2,16 @@ package moe.fuqiuluo.qqinterface.servlet
|
|||||||
|
|
||||||
import com.tencent.biz.map.trpcprotocol.LbsSendInfo
|
import com.tencent.biz.map.trpcprotocol.LbsSendInfo
|
||||||
import com.tencent.mobileqq.msf.core.MsfCore
|
import com.tencent.mobileqq.msf.core.MsfCore
|
||||||
|
import com.tencent.mobileqq.msf.service.MsfService
|
||||||
import com.tencent.proto.lbsshare.LBSShare
|
import com.tencent.proto.lbsshare.LBSShare
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
||||||
import moe.fuqiuluo.shamrock.helper.IllegalParamsException
|
import moe.fuqiuluo.shamrock.helper.IllegalParamsException
|
||||||
|
import moe.fuqiuluo.shamrock.tools.decodeToObject
|
||||||
import moe.fuqiuluo.shamrock.tools.slice
|
import moe.fuqiuluo.shamrock.tools.slice
|
||||||
|
import moe.fuqiuluo.shamrock.xposed.helper.QQInterfaces
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
internal object LbsSvc: BaseSvc() {
|
internal object LbsSvc: QQInterfaces() {
|
||||||
suspend fun tryShareLocation(chatType: Int, peerId: Long, lat: Double, lon: Double): Result<Unit> {
|
suspend fun tryShareLocation(chatType: Int, peerId: Long, lat: Double, lon: Double): Result<Unit> {
|
||||||
val req = LbsSendInfo.SendMessageReq()
|
val req = LbsSendInfo.SendMessageReq()
|
||||||
req.uint64_peer_account.set(peerId)
|
req.uint64_peer_account.set(peerId)
|
||||||
@ -23,8 +26,8 @@ internal object LbsSvc: BaseSvc() {
|
|||||||
}.getOrNull())
|
}.getOrNull())
|
||||||
req.str_lat.set(lat.toString())
|
req.str_lat.set(lat.toString())
|
||||||
req.str_lng.set(lon.toString())
|
req.str_lng.set(lon.toString())
|
||||||
sendPb("trpc.qq_lbs.qq_lbs_ark.LocationArk.SsoSendMessage", req.toByteArray(), MsfCore.getNextSeq())
|
sendBuffer("trpc.qq_lbs.qq_lbs_ark.LocationArk.SsoSendMessage", true, req.toByteArray())
|
||||||
|
//sendPb("trpc.qq_lbs.qq_lbs_ark.LocationArk.SsoSendMessage", req.toByteArray(), MsfService.getCore().nextSeq)
|
||||||
return Result.success(Unit)
|
return Result.success(Unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,8 +52,7 @@ internal object LbsSvc: BaseSvc() {
|
|||||||
req.imei.set("")
|
req.imei.set("")
|
||||||
val buffer = sendBufferAW("LbsShareSvr.location", true, req.toByteArray())
|
val buffer = sendBufferAW("LbsShareSvr.location", true, req.toByteArray())
|
||||||
?: return Result.failure(Exception("获取位置失败"))
|
?: return Result.failure(Exception("获取位置失败"))
|
||||||
val resp = LBSShare.LocationResp()
|
val resp = buffer.decodeToObject(LBSShare.LocationResp())
|
||||||
resp.mergeFrom(buffer.slice(4))
|
|
||||||
val location = resp.mylbs
|
val location = resp.mylbs
|
||||||
return Result.success(location.addr.get())
|
return Result.success(location.addr.get())
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ import moe.fuqiuluo.shamrock.remote.structures.SendMsgResult
|
|||||||
import moe.fuqiuluo.shamrock.tools.*
|
import moe.fuqiuluo.shamrock.tools.*
|
||||||
import moe.fuqiuluo.shamrock.utils.DeflateTools
|
import moe.fuqiuluo.shamrock.utils.DeflateTools
|
||||||
import moe.fuqiuluo.shamrock.xposed.helper.NTServiceFetcher
|
import moe.fuqiuluo.shamrock.xposed.helper.NTServiceFetcher
|
||||||
|
import moe.fuqiuluo.shamrock.xposed.helper.QQInterfaces
|
||||||
import moe.fuqiuluo.shamrock.xposed.helper.msgService
|
import moe.fuqiuluo.shamrock.xposed.helper.msgService
|
||||||
import moe.fuqiuluo.symbols.decodeProtobuf
|
import moe.fuqiuluo.symbols.decodeProtobuf
|
||||||
import protobuf.auto.toByteArray
|
import protobuf.auto.toByteArray
|
||||||
@ -33,9 +34,10 @@ import java.util.*
|
|||||||
import kotlin.coroutines.resume
|
import kotlin.coroutines.resume
|
||||||
import kotlin.coroutines.suspendCoroutine
|
import kotlin.coroutines.suspendCoroutine
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
import kotlin.time.Duration.Companion.seconds
|
||||||
|
|
||||||
internal object MsgSvc : BaseSvc() {
|
internal object MsgSvc : QQInterfaces() {
|
||||||
private suspend fun prepareTempChatFromGroup(
|
suspend fun prepareTempChatFromGroup(
|
||||||
groupId: String,
|
groupId: String,
|
||||||
peerId: String
|
peerId: String
|
||||||
): Result<Unit> {
|
): Result<Unit> {
|
||||||
@ -418,13 +420,9 @@ internal object MsgSvc : BaseSvc() {
|
|||||||
)
|
)
|
||||||
).toByteArray()
|
).toByteArray()
|
||||||
|
|
||||||
val buffer = sendBufferAW("trpc.group.long_msg_interface.MsgService.SsoSendLongMsg", true, req, timeout = 30_000)
|
val buffer = sendBufferAW("trpc.group.long_msg_interface.MsgService.SsoSendLongMsg", true, req, timeout = 30.seconds)
|
||||||
?: return Result.failure(Exception("unable to upload multi message, response timeout"))
|
?: return Result.failure(Exception("unable to upload multi message, response timeout"))
|
||||||
val rsp = runCatching {
|
val rsp = buffer.decodeToObject<LongMsgRsp>()
|
||||||
buffer.slice(4).decodeProtobuf<LongMsgRsp>()
|
|
||||||
}.getOrElse {
|
|
||||||
buffer.decodeProtobuf<LongMsgRsp>()
|
|
||||||
}
|
|
||||||
val resId = rsp.sendResult?.resId ?: return Result.failure(Exception("unable to upload multi message"))
|
val resId = rsp.sendResult?.resId ?: return Result.failure(Exception("unable to upload multi message"))
|
||||||
return Result.success(MessageSegment(
|
return Result.success(MessageSegment(
|
||||||
type = "forward",
|
type = "forward",
|
||||||
@ -456,7 +454,7 @@ internal object MsgSvc : BaseSvc() {
|
|||||||
true,
|
true,
|
||||||
req.toByteArray()
|
req.toByteArray()
|
||||||
) ?: return Result.failure(Exception("unable to get multi message"))
|
) ?: return Result.failure(Exception("unable to get multi message"))
|
||||||
val rsp = buffer.slice(4).decodeProtobuf<LongMsgRsp>()
|
val rsp = buffer.decodeToObject<LongMsgRsp>()
|
||||||
val zippedPayload = DeflateTools.ungzip(
|
val zippedPayload = DeflateTools.ungzip(
|
||||||
rsp.recvResult?.payload ?: return Result.failure(Exception("payload is empty"))
|
rsp.recvResult?.payload ?: return Result.failure(Exception("payload is empty"))
|
||||||
)
|
)
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package moe.fuqiuluo.qqinterface.servlet
|
package moe.fuqiuluo.qqinterface.servlet
|
||||||
|
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.Contact
|
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.IKernelMsgService
|
import com.tencent.qqnt.kernel.nativeinterface.IKernelMsgService
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
||||||
|
import com.tencent.qqnt.kernelpublic.nativeinterface.Contact
|
||||||
import io.ktor.utils.io.core.BytePacketBuilder
|
import io.ktor.utils.io.core.BytePacketBuilder
|
||||||
import io.ktor.utils.io.core.readBytes
|
import io.ktor.utils.io.core.readBytes
|
||||||
import io.ktor.utils.io.core.writeFully
|
import io.ktor.utils.io.core.writeFully
|
||||||
@ -13,6 +13,7 @@ import moe.fuqiuluo.qqinterface.servlet.msg.MessageTempHandler
|
|||||||
import moe.fuqiuluo.shamrock.remote.action.handlers.GetHistoryMsg
|
import moe.fuqiuluo.shamrock.remote.action.handlers.GetHistoryMsg
|
||||||
import moe.fuqiuluo.shamrock.tools.broadcast
|
import moe.fuqiuluo.shamrock.tools.broadcast
|
||||||
import moe.fuqiuluo.shamrock.utils.DeflateTools
|
import moe.fuqiuluo.shamrock.utils.DeflateTools
|
||||||
|
import moe.fuqiuluo.shamrock.xposed.helper.QQInterfaces
|
||||||
import mqq.app.MobileQQ
|
import mqq.app.MobileQQ
|
||||||
import protobuf.auto.toByteArray
|
import protobuf.auto.toByteArray
|
||||||
import protobuf.message.*
|
import protobuf.message.*
|
||||||
@ -21,7 +22,7 @@ import protobuf.push.MessagePush
|
|||||||
import kotlin.coroutines.resume
|
import kotlin.coroutines.resume
|
||||||
import kotlin.text.toByteArray
|
import kotlin.text.toByteArray
|
||||||
|
|
||||||
internal object PacketSvc : BaseSvc() {
|
internal object PacketSvc : QQInterfaces() {
|
||||||
/**
|
/**
|
||||||
* 伪造收到Json卡片消息
|
* 伪造收到Json卡片消息
|
||||||
*/
|
*/
|
||||||
|
@ -23,6 +23,7 @@ import moe.fuqiuluo.shamrock.tools.toHexString
|
|||||||
import moe.fuqiuluo.shamrock.utils.DeflateTools
|
import moe.fuqiuluo.shamrock.utils.DeflateTools
|
||||||
import moe.fuqiuluo.shamrock.utils.MD5
|
import moe.fuqiuluo.shamrock.utils.MD5
|
||||||
import moe.fuqiuluo.shamrock.xposed.helper.AppRuntimeFetcher
|
import moe.fuqiuluo.shamrock.xposed.helper.AppRuntimeFetcher
|
||||||
|
import moe.fuqiuluo.shamrock.xposed.helper.QQInterfaces
|
||||||
import protobuf.fav.WeiyunAddRichMediaReq
|
import protobuf.fav.WeiyunAddRichMediaReq
|
||||||
import protobuf.fav.WeiyunAuthor
|
import protobuf.fav.WeiyunAuthor
|
||||||
import protobuf.fav.WeiyunCollectCommInfo
|
import protobuf.fav.WeiyunCollectCommInfo
|
||||||
@ -49,7 +50,7 @@ import kotlin.coroutines.resume
|
|||||||
/**
|
/**
|
||||||
* QQ收藏相关接口
|
* QQ收藏相关接口
|
||||||
*/
|
*/
|
||||||
internal object QFavSvc: BaseSvc() {
|
internal object QFavSvc: QQInterfaces() {
|
||||||
private val SERVER_LIST_COLLECTOR = listOf(ServerAddr().also {
|
private val SERVER_LIST_COLLECTOR = listOf(ServerAddr().also {
|
||||||
it.isIpv6 = false
|
it.isIpv6 = false
|
||||||
it.mIp = "collector.weiyun.com"
|
it.mIp = "collector.weiyun.com"
|
||||||
@ -275,7 +276,7 @@ internal object QFavSvc: BaseSvc() {
|
|||||||
|
|
||||||
override fun onUpdateProgeress(netReq: NetReq, curr: Long, final: Long) {}
|
override fun onUpdateProgeress(netReq: NetReq, curr: Long, final: Long) {}
|
||||||
}
|
}
|
||||||
val vi = (app.getManager(QQAppInterface.TICKET_MANAGER) as TicketManager).getA2(app.currentAccountUin)
|
val vi = ((app as QQAppInterface).getManager(QQAppInterface.TICKET_MANAGER) as TicketManager).getA2(app.currentAccountUin)
|
||||||
//LogCenter.log(pSKey)
|
//LogCenter.log(pSKey)
|
||||||
httpNetReq.mHttpMethod = HttpNetReq.HTTP_POST
|
httpNetReq.mHttpMethod = HttpNetReq.HTTP_POST
|
||||||
httpNetReq.mSendData = BytePacketBuilder().apply {
|
httpNetReq.mSendData = BytePacketBuilder().apply {
|
||||||
@ -381,7 +382,7 @@ internal object QFavSvc: BaseSvc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getWeiYunPSKey(): String {
|
private fun getWeiYunPSKey(): String {
|
||||||
val pskey = (app.getManager(QQAppInterface.TICKET_MANAGER) as TicketManager)
|
val pskey = ((app as QQAppInterface).getManager(QQAppInterface.TICKET_MANAGER) as TicketManager)
|
||||||
.getPskey(app.currentAccountUin, 16L, arrayOf("weiyun.com"), WeiYunPSKeyPromise)
|
.getPskey(app.currentAccountUin, 16L, arrayOf("weiyun.com"), WeiYunPSKeyPromise)
|
||||||
return if (pskey != null) pskey.getPSkey("weiyun.com") else ""
|
return if (pskey != null) pskey.getPSkey("weiyun.com") else ""
|
||||||
}
|
}
|
||||||
|
@ -4,12 +4,12 @@ import QQService.SvcDevLoginInfo
|
|||||||
import QQService.SvcReqGetDevLoginInfo
|
import QQService.SvcReqGetDevLoginInfo
|
||||||
import QQService.SvcRspGetDevLoginInfo
|
import QQService.SvcRspGetDevLoginInfo
|
||||||
import com.qq.jce.wup.UniPacket
|
import com.qq.jce.wup.UniPacket
|
||||||
import moe.fuqiuluo.qqinterface.servlet.BaseSvc
|
import moe.fuqiuluo.shamrock.xposed.helper.QQInterfaces
|
||||||
import mqq.app.MobileQQ
|
import mqq.app.MobileQQ
|
||||||
import mqq.app.Packet
|
import mqq.app.Packet
|
||||||
import oicq.wlogin_sdk.tools.util
|
import oicq.wlogin_sdk.tools.util
|
||||||
|
|
||||||
internal object QSafeSvc: BaseSvc() {
|
internal object QSafeSvc: QQInterfaces() {
|
||||||
|
|
||||||
suspend fun getOnlineClients(): ArrayList<SvcDevLoginInfo>? {
|
suspend fun getOnlineClients(): ArrayList<SvcDevLoginInfo>? {
|
||||||
val req = SvcReqGetDevLoginInfo()
|
val req = SvcReqGetDevLoginInfo()
|
||||||
@ -26,7 +26,7 @@ internal object QSafeSvc: BaseSvc() {
|
|||||||
val resp = sendBufferAW("StatSvc.GetDevLoginInfo", false, uniPacket.encode())
|
val resp = sendBufferAW("StatSvc.GetDevLoginInfo", false, uniPacket.encode())
|
||||||
?: return null
|
?: return null
|
||||||
|
|
||||||
return Packet.decodePacket(resp, "SvcRspGetDevLoginInfo", SvcRspGetDevLoginInfo()).vecCurrentLoginDevInfo
|
return Packet.decodePacket(resp.wupBuffer, "SvcRspGetDevLoginInfo", SvcRspGetDevLoginInfo()).vecCurrentLoginDevInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,13 +8,15 @@ import io.ktor.client.request.get
|
|||||||
import io.ktor.client.request.header
|
import io.ktor.client.request.header
|
||||||
import moe.fuqiuluo.shamrock.remote.service.data.BigDataTicket
|
import moe.fuqiuluo.shamrock.remote.service.data.BigDataTicket
|
||||||
import moe.fuqiuluo.shamrock.tools.GlobalClientNoRedirect
|
import moe.fuqiuluo.shamrock.tools.GlobalClientNoRedirect
|
||||||
|
import moe.fuqiuluo.shamrock.tools.decodeToOidb
|
||||||
import moe.fuqiuluo.shamrock.tools.slice
|
import moe.fuqiuluo.shamrock.tools.slice
|
||||||
|
import moe.fuqiuluo.shamrock.xposed.helper.QQInterfaces
|
||||||
import mqq.app.MobileQQ
|
import mqq.app.MobileQQ
|
||||||
import mqq.manager.TicketManager
|
import mqq.manager.TicketManager
|
||||||
import oicq.wlogin_sdk.request.Ticket
|
import oicq.wlogin_sdk.request.Ticket
|
||||||
import tencent.im.oidb.oidb_sso
|
import tencent.im.oidb.oidb_sso
|
||||||
|
|
||||||
internal object TicketSvc: BaseSvc() {
|
internal object TicketSvc: QQInterfaces() {
|
||||||
object SigType {
|
object SigType {
|
||||||
const val WLOGIN_A5 = 2
|
const val WLOGIN_A5 = 2
|
||||||
const val WLOGIN_RESERVED = 16
|
const val WLOGIN_RESERVED = 16
|
||||||
@ -109,23 +111,23 @@ internal object TicketSvc: BaseSvc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getTicket(uin: String, id: Int): Ticket? {
|
fun getTicket(uin: String, id: Int): Ticket? {
|
||||||
return (app.getManager(QQAppInterface.TICKET_MANAGER) as TicketManager).getLocalTicket(uin, id)
|
return ((app as QQAppInterface).getManager(QQAppInterface.TICKET_MANAGER) as TicketManager).getLocalTicket(uin, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getStWeb(uin: String): String {
|
fun getStWeb(uin: String): String {
|
||||||
return (app.getManager(QQAppInterface.TICKET_MANAGER) as TicketManager).getStweb(uin)
|
return ((app as QQAppInterface).getManager(QQAppInterface.TICKET_MANAGER) as TicketManager).getStweb(uin)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getSKey(uin: String): String {
|
fun getSKey(uin: String): String {
|
||||||
return (app.getManager(QQAppInterface.TICKET_MANAGER) as TicketManager).getSkey(uin)
|
return ((app as QQAppInterface).getManager(QQAppInterface.TICKET_MANAGER) as TicketManager).getSkey(uin)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getRealSkey(uin: String): String {
|
fun getRealSkey(uin: String): String {
|
||||||
return (app.getManager(QQAppInterface.TICKET_MANAGER) as TicketManager).getRealSkey(uin)
|
return ((app as QQAppInterface).getManager(QQAppInterface.TICKET_MANAGER) as TicketManager).getRealSkey(uin)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getPSKey(uin: String): String {
|
fun getPSKey(uin: String): String {
|
||||||
val manager = (app.getManager(QQAppInterface.TICKET_MANAGER) as TicketManager)
|
val manager = ((app as QQAppInterface).getManager(QQAppInterface.TICKET_MANAGER) as TicketManager)
|
||||||
manager.reloadCache(MobileQQ.getContext())
|
manager.reloadCache(MobileQQ.getContext())
|
||||||
return manager.getSuperkey(uin) ?: ""
|
return manager.getSuperkey(uin) ?: ""
|
||||||
}
|
}
|
||||||
@ -135,14 +137,13 @@ internal object TicketSvc: BaseSvc() {
|
|||||||
req.domains.set(domain.toList())
|
req.domains.set(domain.toList())
|
||||||
val buffer = sendOidbAW("OidbSvcTcp.0x102a", 4138, 0, req.toByteArray())
|
val buffer = sendOidbAW("OidbSvcTcp.0x102a", 4138, 0, req.toByteArray())
|
||||||
?: return Result.failure(Exception("getLessPSKey failed"))
|
?: return Result.failure(Exception("getLessPSKey failed"))
|
||||||
val body = oidb_sso.OIDBSSOPkg()
|
val body = buffer.decodeToOidb()
|
||||||
body.mergeFrom(buffer.slice(4))
|
|
||||||
val rsp = oidb_cmd0x102a.GetPSkeyResponse().mergeFrom(body.bytes_bodybuffer.get().toByteArray())
|
val rsp = oidb_cmd0x102a.GetPSkeyResponse().mergeFrom(body.bytes_bodybuffer.get().toByteArray())
|
||||||
return Result.success(rsp.private_keys.get())
|
return Result.success(rsp.private_keys.get())
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getPSKey(uin: String, domain: String): String? {
|
suspend fun getPSKey(uin: String, domain: String): String? {
|
||||||
return (app.getManager(QQAppInterface.TICKET_MANAGER) as TicketManager).getPskey(uin, domain).let {
|
return ((app as QQAppInterface).getManager(QQAppInterface.TICKET_MANAGER) as TicketManager).getPskey(uin, domain).let {
|
||||||
if (it.isNullOrBlank())
|
if (it.isNullOrBlank())
|
||||||
getLessPSKey(domain).getOrNull()?.firstOrNull()?.key?.get()
|
getLessPSKey(domain).getOrNull()?.firstOrNull()?.key?.get()
|
||||||
else it
|
else it
|
||||||
@ -150,7 +151,7 @@ internal object TicketSvc: BaseSvc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getPt4Token(uin: String, domain: String): String? {
|
fun getPt4Token(uin: String, domain: String): String? {
|
||||||
return (app.getManager(QQAppInterface.TICKET_MANAGER) as TicketManager).getPt4Token(uin, domain)
|
return ((app as QQAppInterface).getManager(QQAppInterface.TICKET_MANAGER) as TicketManager).getPt4Token(uin, domain)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun GetHttpCookies(appid: String, daid: String, jumpurl: String): String? {
|
suspend fun GetHttpCookies(appid: String, daid: String, jumpurl: String): String? {
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package moe.fuqiuluo.qqinterface.servlet
|
package moe.fuqiuluo.qqinterface.servlet
|
||||||
|
|
||||||
internal object VisitorSvc: BaseSvc() {
|
import moe.fuqiuluo.shamrock.xposed.helper.QQInterfaces
|
||||||
|
|
||||||
|
internal object VisitorSvc: QQInterfaces() {
|
||||||
const val FROM_C2C_AIO = 2
|
const val FROM_C2C_AIO = 2
|
||||||
const val FROM_CONDITION_SEARCH = 9
|
const val FROM_CONDITION_SEARCH = 9
|
||||||
const val FROM_CONTACTS_TAB = 5
|
const val FROM_CONTACTS_TAB = 5
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
package moe.fuqiuluo.qqinterface.servlet.ark
|
package moe.fuqiuluo.qqinterface.servlet.ark
|
||||||
|
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
||||||
import moe.fuqiuluo.qqinterface.servlet.BaseSvc
|
|
||||||
import moe.fuqiuluo.qqinterface.servlet.ark.data.ArkAppInfo
|
import moe.fuqiuluo.qqinterface.servlet.ark.data.ArkAppInfo
|
||||||
|
import moe.fuqiuluo.shamrock.xposed.helper.QQInterfaces
|
||||||
import tencent.im.oidb.cmd0xb77.oidb_cmd0xb77
|
import tencent.im.oidb.cmd0xb77.oidb_cmd0xb77
|
||||||
|
|
||||||
internal object ArkMsgSvc: BaseSvc() {
|
internal object ArkMsgSvc: QQInterfaces() {
|
||||||
fun tryShareMusic(
|
fun tryShareMusic(
|
||||||
chatType: Int,
|
chatType: Int,
|
||||||
peerId: Long,
|
peerId: Long,
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package moe.fuqiuluo.qqinterface.servlet.ark
|
package moe.fuqiuluo.qqinterface.servlet.ark
|
||||||
|
|
||||||
import moe.fuqiuluo.qqinterface.servlet.BaseSvc
|
|
||||||
import moe.fuqiuluo.qqinterface.servlet.ark.data.ArkAppInfo
|
import moe.fuqiuluo.qqinterface.servlet.ark.data.ArkAppInfo
|
||||||
import moe.fuqiuluo.shamrock.utils.PlatformUtils
|
import moe.fuqiuluo.shamrock.utils.PlatformUtils
|
||||||
|
import moe.fuqiuluo.shamrock.xposed.helper.QQInterfaces
|
||||||
import moe.fuqiuluo.symbols.decodeProtobuf
|
import moe.fuqiuluo.symbols.decodeProtobuf
|
||||||
import protobuf.auto.toByteArray
|
import protobuf.auto.toByteArray
|
||||||
import protobuf.lightapp.AdaptShareInfoReq
|
import protobuf.lightapp.AdaptShareInfoReq
|
||||||
@ -11,7 +11,7 @@ import protobuf.qweb.DEFAULT_DEVICE_INFO
|
|||||||
import protobuf.qweb.QWebReq
|
import protobuf.qweb.QWebReq
|
||||||
import protobuf.qweb.QWebRsp
|
import protobuf.qweb.QWebRsp
|
||||||
|
|
||||||
internal object LightAppSvc: BaseSvc() {
|
internal object LightAppSvc: QQInterfaces() {
|
||||||
suspend fun adaptShareJumpUrl(
|
suspend fun adaptShareJumpUrl(
|
||||||
arkAppInfo: ArkAppInfo,
|
arkAppInfo: ArkAppInfo,
|
||||||
coverUrl: String,
|
coverUrl: String,
|
||||||
@ -37,7 +37,7 @@ internal object LightAppSvc: BaseSvc() {
|
|||||||
webURL = url,
|
webURL = url,
|
||||||
).toByteArray(),
|
).toByteArray(),
|
||||||
traceId = app.account + "_0_0",
|
traceId = app.account + "_0_0",
|
||||||
).toByteArray())?.decodeProtobuf<QWebRsp>()?.buffer?.decodeProtobuf<AdaptShareInfoResp>()
|
).toByteArray())?.wupBuffer?.decodeProtobuf<QWebRsp>()?.buffer?.decodeProtobuf<AdaptShareInfoResp>()
|
||||||
if (rsp == null || rsp.json.isNullOrEmpty())
|
if (rsp == null || rsp.json.isNullOrEmpty())
|
||||||
return Result.failure(Exception("unable to adapt ShareInfo"))
|
return Result.failure(Exception("unable to adapt ShareInfo"))
|
||||||
return Result.success(rsp.json!!)
|
return Result.success(rsp.json!!)
|
||||||
|
@ -30,7 +30,7 @@ internal object NtMsgElementConverter {
|
|||||||
MsgConstant.KELEMTYPEMARKETFACE to NtMsgElementConverter::convertMarketFaceElem,
|
MsgConstant.KELEMTYPEMARKETFACE to NtMsgElementConverter::convertMarketFaceElem,
|
||||||
MsgConstant.KELEMTYPEARKSTRUCT to NtMsgElementConverter::convertStructJsonElem,
|
MsgConstant.KELEMTYPEARKSTRUCT to NtMsgElementConverter::convertStructJsonElem,
|
||||||
MsgConstant.KELEMTYPEREPLY to NtMsgElementConverter::convertReplyElem,
|
MsgConstant.KELEMTYPEREPLY to NtMsgElementConverter::convertReplyElem,
|
||||||
MsgConstant.KELEMTYPEGRAYTIP to NtMsgElementConverter::convertGrayTipsElem,
|
//MsgConstant.KELEMTYPEGRAYTIP to NtMsgElementConverter::convertGrayTipsElem,
|
||||||
MsgConstant.KELEMTYPEFILE to NtMsgElementConverter::convertFileElem,
|
MsgConstant.KELEMTYPEFILE to NtMsgElementConverter::convertFileElem,
|
||||||
MsgConstant.KELEMTYPEMARKDOWN to NtMsgElementConverter::convertMarkdownElem,
|
MsgConstant.KELEMTYPEMARKDOWN to NtMsgElementConverter::convertMarkdownElem,
|
||||||
//MsgConstant.KELEMTYPEMULTIFORWARD to MsgElementConverter::convertXmlMultiMsgElem,
|
//MsgConstant.KELEMTYPEMULTIFORWARD to MsgElementConverter::convertXmlMultiMsgElem,
|
||||||
@ -182,48 +182,14 @@ internal object NtMsgElementConverter {
|
|||||||
/*
|
/*
|
||||||
PicElement{picSubType=0,fileName=A655FCDADABC40D0CEAF6F9AF92937CD.jpg,fileSize=142865,picWidth=886,picHeight=1920,original=false,md5HexStr=a655fcdadabc40d0ceaf6f9af92937cd,sourcePath=null,thumbPath=null,transferStatus=2,progress=0,picType=1000,invalidState=0,fileUuid=CgoxMDI5Mzc0MTE1EhTnucgrUbp3MJjjagUM2-VxSQ5V7hiR3Agg_goo9ZCZt-HNhANQgJqeAQ,fileSubId=,thumbFileSize=0,fileBizId=null,downloadIndex=null,summary=,emojiFrom=null,emojiWebUrl=null,emojiAd=EmojiAD{url=,desc=,},emojiMall=EmojiMall{packageId=0,emojiId=0,},emojiZplan=EmojiZPlan{actionId=0,actionName=,actionType=0,playerNumber=0,peerUid=0,bytesReserveInfo=,},originImageMd5=,originImageUrl=null,importRichMediaContext=null,isFlashPic=false,}
|
PicElement{picSubType=0,fileName=A655FCDADABC40D0CEAF6F9AF92937CD.jpg,fileSize=142865,picWidth=886,picHeight=1920,original=false,md5HexStr=a655fcdadabc40d0ceaf6f9af92937cd,sourcePath=null,thumbPath=null,transferStatus=2,progress=0,picType=1000,invalidState=0,fileUuid=CgoxMDI5Mzc0MTE1EhTnucgrUbp3MJjjagUM2-VxSQ5V7hiR3Agg_goo9ZCZt-HNhANQgJqeAQ,fileSubId=,thumbFileSize=0,fileBizId=null,downloadIndex=null,summary=,emojiFrom=null,emojiWebUrl=null,emojiAd=EmojiAD{url=,desc=,},emojiMall=EmojiMall{packageId=0,emojiId=0,},emojiZplan=EmojiZPlan{actionId=0,actionName=,actionType=0,playerNumber=0,peerUid=0,bytesReserveInfo=,},originImageMd5=,originImageUrl=null,importRichMediaContext=null,isFlashPic=false,}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
val url = RichProtoSvc.getTempPicDownloadUrl(chatType, originalUrl, md5, image, storeId)
|
||||||
|
|
||||||
return MessageSegment(
|
return MessageSegment(
|
||||||
type = "image",
|
type = "image",
|
||||||
data = hashMapOf(
|
data = hashMapOf(
|
||||||
"file" to md5,
|
"file" to md5,
|
||||||
"url" to when (chatType) {
|
"url" to url,
|
||||||
MsgConstant.KCHATTYPEDISC, MsgConstant.KCHATTYPEGROUP -> RichProtoSvc.getGroupPicDownUrl(
|
|
||||||
originalUrl = originalUrl,
|
|
||||||
md5 = md5,
|
|
||||||
fileId = image.fileUuid,
|
|
||||||
width = image.picWidth.toUInt(),
|
|
||||||
height = image.picHeight.toUInt(),
|
|
||||||
sha = "",
|
|
||||||
fileSize = image.fileSize.toULong(),
|
|
||||||
peer = peerId
|
|
||||||
)
|
|
||||||
|
|
||||||
MsgConstant.KCHATTYPEC2C -> RichProtoSvc.getC2CPicDownUrl(
|
|
||||||
originalUrl = originalUrl,
|
|
||||||
md5 = md5,
|
|
||||||
fileId = image.fileUuid,
|
|
||||||
width = image.picWidth.toUInt(),
|
|
||||||
height = image.picHeight.toUInt(),
|
|
||||||
sha = "",
|
|
||||||
fileSize = image.fileSize.toULong(),
|
|
||||||
peer = peerId,
|
|
||||||
storeId = storeId
|
|
||||||
)
|
|
||||||
|
|
||||||
MsgConstant.KCHATTYPEGUILD -> RichProtoSvc.getGuildPicDownUrl(
|
|
||||||
originalUrl = originalUrl,
|
|
||||||
md5 = md5,
|
|
||||||
fileId = image.fileUuid,
|
|
||||||
width = image.picWidth.toUInt(),
|
|
||||||
height = image.picHeight.toUInt(),
|
|
||||||
sha = "",
|
|
||||||
fileSize = image.fileSize.toULong(),
|
|
||||||
peer = peerId,
|
|
||||||
subPeer = subPeer
|
|
||||||
)
|
|
||||||
|
|
||||||
else -> throw UnsupportedOperationException("Not supported chat type: $chatType")
|
|
||||||
},
|
|
||||||
"subType" to image.picSubType,
|
"subType" to image.picSubType,
|
||||||
"type" to if (image.isFlashPic == true) "flash" else if (image.original) "original" else "show"
|
"type" to if (image.isFlashPic == true) "flash" else if (image.original) "original" else "show"
|
||||||
)
|
)
|
||||||
|
@ -124,11 +124,15 @@ internal class ElemMaker {
|
|||||||
else -> {
|
else -> {
|
||||||
qq = qqStr.toLong()
|
qq = qqStr.toLong()
|
||||||
type = 0
|
type = 0
|
||||||
"@" + (data["name"].asStringOrNull ?: GroupSvc.getTroopMemberInfoByUinV2(
|
val name = (data["name"].asStringOrNull
|
||||||
peerId.toLong(),
|
?: GroupSvc.getTroopMemberNickByUin(peerId.toLong(), qq)?.let {
|
||||||
qq,
|
it.troopNick
|
||||||
true
|
.ifNullOrEmpty(it.friendNick)
|
||||||
).let {
|
.ifNullOrEmpty(it.showName)
|
||||||
|
.ifNullOrEmpty(it.autoRemark)
|
||||||
|
.ifNullOrEmpty(it.colorNick)
|
||||||
|
}
|
||||||
|
?: GroupSvc.getTroopMemberInfoByUinV2(peerId.toLong(), qq, true).let {
|
||||||
val info = it.getOrNull()
|
val info = it.getOrNull()
|
||||||
if (info == null)
|
if (info == null)
|
||||||
LogCenter.log("无法获取群成员信息: $qqStr", Level.ERROR)
|
LogCenter.log("无法获取群成员信息: $qqStr", Level.ERROR)
|
||||||
@ -136,6 +140,7 @@ internal class ElemMaker {
|
|||||||
.ifNullOrEmpty(info.friendnick)
|
.ifNullOrEmpty(info.friendnick)
|
||||||
.ifNullOrEmpty(qqStr)
|
.ifNullOrEmpty(qqStr)
|
||||||
})
|
})
|
||||||
|
"@$name"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -856,7 +856,15 @@ internal object NtMsgElementMaker {
|
|||||||
.ifNullOrEmpty(qqStr)
|
.ifNullOrEmpty(qqStr)
|
||||||
}"
|
}"
|
||||||
} else {
|
} else {
|
||||||
at.content = "@$qqStr"
|
at.content = "@${
|
||||||
|
GroupSvc.getTroopMemberNickByUin(peerId.toLong(), qq)?.let {
|
||||||
|
it.troopNick
|
||||||
|
.ifNullOrEmpty(it.friendNick)
|
||||||
|
.ifNullOrEmpty(it.showName)
|
||||||
|
.ifNullOrEmpty(it.autoRemark)
|
||||||
|
.ifNullOrEmpty(it.colorNick)
|
||||||
|
} ?: qqStr
|
||||||
|
}"
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
at.content = "@$name"
|
at.content = "@$name"
|
||||||
|
@ -5,7 +5,6 @@ import androidx.exifinterface.media.ExifInterface
|
|||||||
import com.tencent.mobileqq.qroute.QRoute
|
import com.tencent.mobileqq.qroute.QRoute
|
||||||
import com.tencent.qqnt.aio.adapter.api.IAIOPttApi
|
import com.tencent.qqnt.aio.adapter.api.IAIOPttApi
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.CommonFileInfo
|
import com.tencent.qqnt.kernel.nativeinterface.CommonFileInfo
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.Contact
|
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.MsgElement
|
import com.tencent.qqnt.kernel.nativeinterface.MsgElement
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.PicElement
|
import com.tencent.qqnt.kernel.nativeinterface.PicElement
|
||||||
@ -13,29 +12,33 @@ import com.tencent.qqnt.kernel.nativeinterface.PttElement
|
|||||||
import com.tencent.qqnt.kernel.nativeinterface.QQNTWrapperUtil
|
import com.tencent.qqnt.kernel.nativeinterface.QQNTWrapperUtil
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.RichMediaFilePathInfo
|
import com.tencent.qqnt.kernel.nativeinterface.RichMediaFilePathInfo
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.VideoElement
|
import com.tencent.qqnt.kernel.nativeinterface.VideoElement
|
||||||
|
import com.tencent.qqnt.kernelpublic.nativeinterface.Contact
|
||||||
import kotlinx.atomicfu.atomic
|
import kotlinx.atomicfu.atomic
|
||||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
import kotlinx.coroutines.withTimeoutOrNull
|
import kotlinx.coroutines.withTimeoutOrNull
|
||||||
import moe.fuqiuluo.qqinterface.servlet.BaseSvc
|
|
||||||
import moe.fuqiuluo.qqinterface.servlet.TicketSvc
|
import moe.fuqiuluo.qqinterface.servlet.TicketSvc
|
||||||
import moe.fuqiuluo.qqinterface.servlet.transfile.data.TryUpPicData
|
import moe.fuqiuluo.qqinterface.servlet.transfile.data.TryUpPicData
|
||||||
import moe.fuqiuluo.shamrock.helper.MessageHelper
|
import moe.fuqiuluo.shamrock.helper.MessageHelper
|
||||||
import moe.fuqiuluo.shamrock.remote.service.config.ShamrockConfig
|
import moe.fuqiuluo.shamrock.remote.service.config.ShamrockConfig
|
||||||
|
import moe.fuqiuluo.shamrock.tools.decodeToObject
|
||||||
|
import moe.fuqiuluo.shamrock.tools.decodeToTrpcOidb
|
||||||
import moe.fuqiuluo.shamrock.tools.hex2ByteArray
|
import moe.fuqiuluo.shamrock.tools.hex2ByteArray
|
||||||
import moe.fuqiuluo.shamrock.tools.slice
|
import moe.fuqiuluo.shamrock.tools.toHexString
|
||||||
import moe.fuqiuluo.shamrock.utils.AudioUtils
|
import moe.fuqiuluo.shamrock.utils.AudioUtils
|
||||||
import moe.fuqiuluo.shamrock.utils.FileUtils
|
import moe.fuqiuluo.shamrock.utils.FileUtils
|
||||||
import moe.fuqiuluo.shamrock.utils.MediaType
|
import moe.fuqiuluo.shamrock.utils.MediaType
|
||||||
import moe.fuqiuluo.shamrock.xposed.helper.NTServiceFetcher
|
import moe.fuqiuluo.shamrock.xposed.helper.NTServiceFetcher
|
||||||
|
import moe.fuqiuluo.shamrock.xposed.helper.QQInterfaces
|
||||||
import moe.fuqiuluo.shamrock.xposed.helper.msgService
|
import moe.fuqiuluo.shamrock.xposed.helper.msgService
|
||||||
import moe.fuqiuluo.symbols.decodeProtobuf
|
import moe.fuqiuluo.symbols.decodeProtobuf
|
||||||
import protobuf.auto.toByteArray
|
import protobuf.auto.toByteArray
|
||||||
import protobuf.oidb.TrpcOidb
|
|
||||||
import protobuf.oidb.cmd0x11c5.ClientMeta
|
import protobuf.oidb.cmd0x11c5.ClientMeta
|
||||||
import protobuf.oidb.cmd0x11c5.CodecConfigReq
|
import protobuf.oidb.cmd0x11c5.CodecConfigReq
|
||||||
import protobuf.oidb.cmd0x11c5.CommonHead
|
import protobuf.oidb.cmd0x11c5.CommonHead
|
||||||
import protobuf.oidb.cmd0x11c5.DownloadExt
|
import protobuf.oidb.cmd0x11c5.DownloadExt
|
||||||
import protobuf.oidb.cmd0x11c5.DownloadReq
|
import protobuf.oidb.cmd0x11c5.DownloadReq
|
||||||
|
import protobuf.oidb.cmd0x11c5.DownloadRkeyReq
|
||||||
|
import protobuf.oidb.cmd0x11c5.DownloadRkeyRsp
|
||||||
import protobuf.oidb.cmd0x11c5.FileInfo
|
import protobuf.oidb.cmd0x11c5.FileInfo
|
||||||
import protobuf.oidb.cmd0x11c5.FileType
|
import protobuf.oidb.cmd0x11c5.FileType
|
||||||
import protobuf.oidb.cmd0x11c5.IndexNode
|
import protobuf.oidb.cmd0x11c5.IndexNode
|
||||||
@ -57,8 +60,9 @@ import kotlin.random.Random
|
|||||||
import kotlin.random.nextUInt
|
import kotlin.random.nextUInt
|
||||||
import kotlin.random.nextULong
|
import kotlin.random.nextULong
|
||||||
import kotlin.time.Duration
|
import kotlin.time.Duration
|
||||||
|
import kotlin.time.Duration.Companion.seconds
|
||||||
|
|
||||||
internal object NtV2RichMediaSvc: BaseSvc() {
|
internal object NtV2RichMediaSvc: QQInterfaces() {
|
||||||
private val requestIdSeq = atomic(2L)
|
private val requestIdSeq = atomic(2L)
|
||||||
|
|
||||||
fun fetchGroupResUploadTo(): String {
|
fun fetchGroupResUploadTo(): String {
|
||||||
@ -320,6 +324,40 @@ internal object NtV2RichMediaSvc: BaseSvc() {
|
|||||||
return Result.success(result)
|
return Result.success(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun getTempNtRKey(): Result<DownloadRkeyRsp> {
|
||||||
|
runCatching {
|
||||||
|
val req = NtV2RichMediaReq(
|
||||||
|
head = MultiMediaReqHead(
|
||||||
|
commonHead = CommonHead(
|
||||||
|
requestId = requestIdSeq.incrementAndGet().toULong(),
|
||||||
|
cmd = 202u
|
||||||
|
),
|
||||||
|
sceneInfo = SceneInfo(
|
||||||
|
requestType = 2u,
|
||||||
|
businessType = 1u,
|
||||||
|
sceneType = 0u,
|
||||||
|
),
|
||||||
|
clientMeta = ClientMeta(2u)
|
||||||
|
),
|
||||||
|
downloadRkey = DownloadRkeyReq(
|
||||||
|
types = listOf(10, 20),
|
||||||
|
downloadType = 2
|
||||||
|
)
|
||||||
|
).toByteArray()
|
||||||
|
val fromServiceMsg = sendOidbAW("OidbSvcTrpcTcp.0x9067_202", 0x9067, 202, req, true)
|
||||||
|
if (fromServiceMsg == null || fromServiceMsg.wupBuffer == null) {
|
||||||
|
return Result.failure(Exception("failed to fetch NtTempRKey: ${fromServiceMsg?.wupBuffer?.toHexString()}"))
|
||||||
|
}
|
||||||
|
val trpc = fromServiceMsg.decodeToTrpcOidb()
|
||||||
|
trpc.buffer.decodeProtobuf<NtV2RichMediaRsp>().downloadRkeyRsp?.let {
|
||||||
|
return Result.success(it)
|
||||||
|
}
|
||||||
|
}.onFailure {
|
||||||
|
return Result.failure(it)
|
||||||
|
}
|
||||||
|
return Result.failure(Exception("failed to fetch NtTempRKey"))
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取NT图片的RKEY
|
* 获取NT图片的RKEY
|
||||||
*/
|
*/
|
||||||
@ -386,8 +424,9 @@ internal object NtV2RichMediaSvc: BaseSvc() {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
).toByteArray()
|
).toByteArray()
|
||||||
val buffer = sendOidbAW("OidbSvcTrpcTcp.0x11c5_200", 4549, 200, req, true)?.slice(4)
|
val buffer = sendOidbAW("OidbSvcTrpcTcp.0x11c5_200", 4549, 200, req, true)
|
||||||
buffer?.decodeProtobuf<TrpcOidb>()?.buffer?.decodeProtobuf<NtV2RichMediaRsp>()?.download?.rkeyParam?.let {
|
?: return Result.failure(Exception("no response"))
|
||||||
|
buffer.decodeToTrpcOidb().buffer.decodeProtobuf<NtV2RichMediaRsp>().download?.rkeyParam?.let {
|
||||||
return Result.success(it)
|
return Result.success(it)
|
||||||
}
|
}
|
||||||
}.onFailure {
|
}.onFailure {
|
||||||
@ -470,17 +509,16 @@ internal object NtV2RichMediaSvc: BaseSvc() {
|
|||||||
).toByteArray()
|
).toByteArray()
|
||||||
val buffer = when (chatType) {
|
val buffer = when (chatType) {
|
||||||
MsgConstant.KCHATTYPEGROUP -> {
|
MsgConstant.KCHATTYPEGROUP -> {
|
||||||
sendOidbAW("OidbSvcTrpcTcp.0x11c4_100", 4548, 100, req, true, timeout = 3_000)?.slice(4)
|
sendOidbAW("OidbSvcTrpcTcp.0x11c4_100", 4548, 100, req, true, timeout = 3.seconds)
|
||||||
?: return Result.failure(Exception("no response: timeout"))
|
?: return Result.failure(Exception("no response: timeout"))
|
||||||
}
|
}
|
||||||
MsgConstant.KCHATTYPEC2C -> {
|
MsgConstant.KCHATTYPEC2C -> {
|
||||||
sendOidbAW("OidbSvcTrpcTcp.0x11c5_100", 4549, 100, req, true, timeout = 3_000)?.slice(4)
|
sendOidbAW("OidbSvcTrpcTcp.0x11c5_100", 4549, 100, req, true, timeout = 3.seconds)
|
||||||
?: return Result.failure(Exception("no response: timeout"))
|
?: return Result.failure(Exception("no response: timeout"))
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> return Result.failure(Exception("unknown chat type: $chatType"))
|
else -> return Result.failure(Exception("unknown chat type: $chatType"))
|
||||||
}
|
}
|
||||||
val rspBuffer = buffer.decodeProtobuf<TrpcOidb>().buffer
|
val rspBuffer = buffer.decodeToTrpcOidb().buffer
|
||||||
val rsp = rspBuffer.decodeProtobuf<NtV2RichMediaRsp>()
|
val rsp = rspBuffer.decodeProtobuf<NtV2RichMediaRsp>()
|
||||||
if (rsp.upload == null) {
|
if (rsp.upload == null) {
|
||||||
return Result.failure(Exception("unable to request upload nt pic: ${rsp.head}"))
|
return Result.failure(Exception("unable to request upload nt pic: ${rsp.head}"))
|
||||||
@ -522,7 +560,7 @@ internal object NtV2RichMediaSvc: BaseSvc() {
|
|||||||
)
|
)
|
||||||
),
|
),
|
||||||
).toByteArray())!!
|
).toByteArray())!!
|
||||||
val rsp = rspBuffer.decodeProtobuf<Cmd0x388RspBody>()
|
val rsp = rspBuffer.decodeToObject<Cmd0x388RspBody>()
|
||||||
.msgTryUpImgRsp!!.first()
|
.msgTryUpImgRsp!!.first()
|
||||||
TryUpPicData(
|
TryUpPicData(
|
||||||
uKey = rsp.ukey,
|
uKey = rsp.ukey,
|
||||||
|
@ -6,18 +6,20 @@ import com.tencent.mobileqq.transfile.FileMsg
|
|||||||
import com.tencent.mobileqq.transfile.api.IProtoReqManager
|
import com.tencent.mobileqq.transfile.api.IProtoReqManager
|
||||||
import com.tencent.mobileqq.transfile.protohandler.RichProto
|
import com.tencent.mobileqq.transfile.protohandler.RichProto
|
||||||
import com.tencent.mobileqq.transfile.protohandler.RichProtoProc
|
import com.tencent.mobileqq.transfile.protohandler.RichProtoProc
|
||||||
|
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
||||||
|
import com.tencent.qqnt.kernel.nativeinterface.PicElement
|
||||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
import kotlinx.serialization.ExperimentalSerializationApi
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
import moe.fuqiuluo.qqinterface.servlet.BaseSvc
|
|
||||||
import moe.fuqiuluo.qqinterface.servlet.transfile.NtV2RichMediaSvc.getNtPicRKey
|
import moe.fuqiuluo.qqinterface.servlet.transfile.NtV2RichMediaSvc.getNtPicRKey
|
||||||
import moe.fuqiuluo.shamrock.helper.ContactHelper
|
import moe.fuqiuluo.shamrock.helper.ContactHelper
|
||||||
import moe.fuqiuluo.shamrock.helper.Level
|
import moe.fuqiuluo.shamrock.helper.Level
|
||||||
import moe.fuqiuluo.shamrock.helper.LogCenter
|
import moe.fuqiuluo.shamrock.helper.LogCenter
|
||||||
import moe.fuqiuluo.shamrock.tools.hex2ByteArray
|
import moe.fuqiuluo.shamrock.tools.decodeToOidb
|
||||||
import moe.fuqiuluo.shamrock.tools.slice
|
import moe.fuqiuluo.shamrock.tools.slice
|
||||||
import moe.fuqiuluo.shamrock.tools.toHexString
|
import moe.fuqiuluo.shamrock.tools.toHexString
|
||||||
import moe.fuqiuluo.shamrock.utils.PlatformUtils
|
import moe.fuqiuluo.shamrock.utils.PlatformUtils
|
||||||
import moe.fuqiuluo.shamrock.xposed.helper.AppRuntimeFetcher
|
import moe.fuqiuluo.shamrock.xposed.helper.AppRuntimeFetcher
|
||||||
|
import moe.fuqiuluo.shamrock.xposed.helper.QQInterfaces
|
||||||
import moe.fuqiuluo.symbols.decodeProtobuf
|
import moe.fuqiuluo.symbols.decodeProtobuf
|
||||||
import mqq.app.MobileQQ
|
import mqq.app.MobileQQ
|
||||||
import protobuf.auto.toByteArray
|
import protobuf.auto.toByteArray
|
||||||
@ -38,7 +40,7 @@ private const val GPRO_PIC = "gchat.qpic.cn"
|
|||||||
private const val MULTIMEDIA_DOMAIN = "multimedia.nt.qq.com.cn"
|
private const val MULTIMEDIA_DOMAIN = "multimedia.nt.qq.com.cn"
|
||||||
private const val C2C_PIC = "c2cpicdw.qpic.cn"
|
private const val C2C_PIC = "c2cpicdw.qpic.cn"
|
||||||
|
|
||||||
internal object RichProtoSvc: BaseSvc() {
|
internal object RichProtoSvc: QQInterfaces() {
|
||||||
suspend fun getGuildFileDownUrl(peerId: String, channelId: String, fileId: String, bizId: Int): String {
|
suspend fun getGuildFileDownUrl(peerId: String, channelId: String, fileId: String, bizId: Int): String {
|
||||||
val buffer = sendOidbAW("OidbSvcTrpcTcp.0xfc2_0", 4034, 0, Oidb0xfc2ReqBody(
|
val buffer = sendOidbAW("OidbSvcTrpcTcp.0xfc2_0", 4034, 0, Oidb0xfc2ReqBody(
|
||||||
msgCmd = 1200,
|
msgCmd = 1200,
|
||||||
@ -53,8 +55,7 @@ internal object RichProtoSvc: BaseSvc() {
|
|||||||
supportEncrypt = 0
|
supportEncrypt = 0
|
||||||
)
|
)
|
||||||
).toByteArray()) ?: return ""
|
).toByteArray()) ?: return ""
|
||||||
val body = oidb_sso.OIDBSSOPkg()
|
val body = buffer.decodeToOidb()
|
||||||
body.mergeFrom(buffer.slice(4))
|
|
||||||
body.bytes_bodybuffer
|
body.bytes_bodybuffer
|
||||||
.get().toByteArray()
|
.get().toByteArray()
|
||||||
.decodeProtobuf<Oidb0xfc2RspBody>()
|
.decodeProtobuf<Oidb0xfc2RspBody>()
|
||||||
@ -79,8 +80,7 @@ internal object RichProtoSvc: BaseSvc() {
|
|||||||
str_file_id.set(fileId)
|
str_file_id.set(fileId)
|
||||||
})
|
})
|
||||||
}.toByteArray()) ?: return ""
|
}.toByteArray()) ?: return ""
|
||||||
val body = oidb_sso.OIDBSSOPkg()
|
val body = buffer.decodeToOidb()
|
||||||
body.mergeFrom(buffer.slice(4))
|
|
||||||
val result = oidb_0x6d6.RspBody().mergeFrom(body.bytes_bodybuffer.get().toByteArray())
|
val result = oidb_0x6d6.RspBody().mergeFrom(body.bytes_bodybuffer.get().toByteArray())
|
||||||
if (body.uint32_result.get() != 0
|
if (body.uint32_result.get() != 0
|
||||||
|| result.download_file_rsp.int32_ret_code.get() != 0) {
|
|| result.download_file_rsp.int32_ret_code.get() != 0) {
|
||||||
@ -128,8 +128,7 @@ internal object RichProtoSvc: BaseSvc() {
|
|||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
} else {
|
} else {
|
||||||
val body = oidb_sso.OIDBSSOPkg()
|
val body = buffer.decodeToOidb()
|
||||||
body.mergeFrom(buffer.slice(4))
|
|
||||||
val result = cmd0x346.RspBody().mergeFrom(cmd0xe37.Resp0xe37().mergeFrom(
|
val result = cmd0x346.RspBody().mergeFrom(cmd0xe37.Resp0xe37().mergeFrom(
|
||||||
body.bytes_bodybuffer.get().toByteArray()
|
body.bytes_bodybuffer.get().toByteArray()
|
||||||
).bytes_cmd_0x346_rsp_body.get().toByteArray())
|
).bytes_cmd_0x346_rsp_body.get().toByteArray())
|
||||||
@ -150,6 +149,75 @@ internal object RichProtoSvc: BaseSvc() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun getTempPicDownloadUrl(
|
||||||
|
chatType: Int,
|
||||||
|
originalUrl: String,
|
||||||
|
md5: String,
|
||||||
|
image: PicElement,
|
||||||
|
storeId: Int = 0,
|
||||||
|
peer: String? = null,
|
||||||
|
subPeer: String? = null,
|
||||||
|
): String {
|
||||||
|
val isNtServer = originalUrl.startsWith("/download")
|
||||||
|
if (isNtServer) {
|
||||||
|
val tmpRKey = NtV2RichMediaSvc.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[when(chatType) {
|
||||||
|
MsgConstant.KCHATTYPEDISC, MsgConstant.KCHATTYPEGROUP -> 10u
|
||||||
|
MsgConstant.KCHATTYPEC2C -> 20u
|
||||||
|
MsgConstant.KCHATTYPEGUILD -> 10u
|
||||||
|
else -> 0u
|
||||||
|
}]
|
||||||
|
if (rkey != null) {
|
||||||
|
return "https://$MULTIMEDIA_DOMAIN$originalUrl$rkey"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return when (chatType) {
|
||||||
|
MsgConstant.KCHATTYPEDISC, MsgConstant.KCHATTYPEGROUP -> getGroupPicDownUrl(
|
||||||
|
originalUrl = originalUrl,
|
||||||
|
md5 = md5,
|
||||||
|
fileId = image.fileUuid,
|
||||||
|
width = image.picWidth.toUInt(),
|
||||||
|
height = image.picHeight.toUInt(),
|
||||||
|
sha = "",
|
||||||
|
fileSize = image.fileSize.toULong(),
|
||||||
|
peer = peer ?: "0"
|
||||||
|
)
|
||||||
|
|
||||||
|
MsgConstant.KCHATTYPEC2C -> getC2CPicDownUrl(
|
||||||
|
originalUrl = originalUrl,
|
||||||
|
md5 = md5,
|
||||||
|
fileId = image.fileUuid,
|
||||||
|
width = image.picWidth.toUInt(),
|
||||||
|
height = image.picHeight.toUInt(),
|
||||||
|
sha = "",
|
||||||
|
fileSize = image.fileSize.toULong(),
|
||||||
|
peer = peer ?: "0",
|
||||||
|
storeId = storeId
|
||||||
|
)
|
||||||
|
|
||||||
|
MsgConstant.KCHATTYPEGUILD -> getGuildPicDownUrl(
|
||||||
|
originalUrl = originalUrl,
|
||||||
|
md5 = md5,
|
||||||
|
fileId = image.fileUuid,
|
||||||
|
width = image.picWidth.toUInt(),
|
||||||
|
height = image.picHeight.toUInt(),
|
||||||
|
sha = "",
|
||||||
|
fileSize = image.fileSize.toULong(),
|
||||||
|
peer = peer ?: "0",
|
||||||
|
subPeer = subPeer ?: "0"
|
||||||
|
)
|
||||||
|
|
||||||
|
else -> throw UnsupportedOperationException("Not supported chat type: $chatType")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun getGroupPicDownUrl(
|
suspend fun getGroupPicDownUrl(
|
||||||
originalUrl: String,
|
originalUrl: String,
|
||||||
md5: String,
|
md5: String,
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
package moe.fuqiuluo.shamrock.helper
|
package moe.fuqiuluo.shamrock.helper
|
||||||
|
|
||||||
import moe.fuqiuluo.qqinterface.servlet.BaseSvc
|
|
||||||
import moe.fuqiuluo.shamrock.utils.FileUtils
|
import moe.fuqiuluo.shamrock.utils.FileUtils
|
||||||
|
import moe.fuqiuluo.shamrock.xposed.helper.QQInterfaces
|
||||||
import mqq.app.MobileQQ
|
import mqq.app.MobileQQ
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
internal object LocalCacheHelper: BaseSvc() {
|
internal object LocalCacheHelper: QQInterfaces() {
|
||||||
// 获取外部储存data目录
|
// 获取外部储存data目录
|
||||||
private val dataDir = MobileQQ.getContext().getExternalFilesDir(null)!!
|
private val dataDir = MobileQQ.getContext().getExternalFilesDir(null)!!
|
||||||
.parentFile!!.resolve("Tencent")
|
.parentFile!!.resolve("Tencent")
|
||||||
|
@ -9,8 +9,8 @@ import kotlinx.coroutines.Dispatchers
|
|||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import moe.fuqiuluo.shamrock.remote.service.config.ShamrockConfig
|
import moe.fuqiuluo.shamrock.remote.service.config.ShamrockConfig
|
||||||
import moe.fuqiuluo.shamrock.xposed.hooks.toast
|
import moe.fuqiuluo.shamrock.tools.toast
|
||||||
import moe.fuqiuluo.shamrock.xposed.helper.internal.DataRequester
|
import moe.fuqiuluo.shamrock.xposed.helper.AppTalker
|
||||||
import mqq.app.MobileQQ
|
import mqq.app.MobileQQ
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
@ -60,10 +60,10 @@ internal object LogCenter {
|
|||||||
}
|
}
|
||||||
// 把日志广播到主进程
|
// 把日志广播到主进程
|
||||||
GlobalScope.launch(Dispatchers.Default) {
|
GlobalScope.launch(Dispatchers.Default) {
|
||||||
DataRequester.request("send_message", bodyBuilder = {
|
AppTalker.talk("send_message") {
|
||||||
put("string", string)
|
put("string", string)
|
||||||
put("level", level.id)
|
put("level", level.id)
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!LogFile.exists()) {
|
if (!LogFile.exists()) {
|
||||||
@ -89,10 +89,10 @@ internal object LogCenter {
|
|||||||
}
|
}
|
||||||
// 把日志广播到主进程
|
// 把日志广播到主进程
|
||||||
GlobalScope.launch(Dispatchers.Default) {
|
GlobalScope.launch(Dispatchers.Default) {
|
||||||
DataRequester.request("send_message", bodyBuilder = {
|
AppTalker.talk("send_message") {
|
||||||
put("string", log)
|
put("string", log)
|
||||||
put("level", level.id)
|
put("level", level.id)
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!LogFile.exists()) {
|
if (!LogFile.exists()) {
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
package moe.fuqiuluo.shamrock.helper
|
package moe.fuqiuluo.shamrock.helper
|
||||||
|
|
||||||
import com.tencent.mobileqq.qroute.QRoute
|
import com.tencent.mobileqq.qroute.QRoute
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.Contact
|
import com.tencent.qqnt.kernel.api.IKernelService
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.IOperateCallback
|
import com.tencent.qqnt.kernel.nativeinterface.IOperateCallback
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.MsgElement
|
import com.tencent.qqnt.kernel.nativeinterface.MsgElement
|
||||||
|
import com.tencent.qqnt.kernel.nativeinterface.MsgRecord
|
||||||
|
import com.tencent.qqnt.kernel.nativeinterface.TempChatInfo
|
||||||
|
import com.tencent.qqnt.kernelpublic.nativeinterface.Contact
|
||||||
import com.tencent.qqnt.msg.api.IMsgService
|
import com.tencent.qqnt.msg.api.IMsgService
|
||||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
@ -16,13 +19,15 @@ import kotlinx.serialization.json.JsonElement
|
|||||||
import kotlinx.serialization.json.JsonObject
|
import kotlinx.serialization.json.JsonObject
|
||||||
import kotlinx.serialization.json.jsonObject
|
import kotlinx.serialization.json.jsonObject
|
||||||
import moe.fuqiuluo.qqinterface.servlet.MsgSvc
|
import moe.fuqiuluo.qqinterface.servlet.MsgSvc
|
||||||
|
import moe.fuqiuluo.qqinterface.servlet.MsgSvc.prepareTempChatFromGroup
|
||||||
import moe.fuqiuluo.qqinterface.servlet.msg.maker.ElemMaker
|
import moe.fuqiuluo.qqinterface.servlet.msg.maker.ElemMaker
|
||||||
import moe.fuqiuluo.qqinterface.servlet.msg.maker.NtMsgElementMaker
|
import moe.fuqiuluo.qqinterface.servlet.msg.maker.NtMsgElementMaker
|
||||||
import moe.fuqiuluo.shamrock.helper.db.MessageDB
|
import moe.fuqiuluo.shamrock.helper.db.MessageDB
|
||||||
import moe.fuqiuluo.shamrock.helper.db.MessageMapping
|
import moe.fuqiuluo.shamrock.helper.db.MessageMapping
|
||||||
import moe.fuqiuluo.shamrock.remote.structures.SendMsgResult
|
import moe.fuqiuluo.shamrock.remote.structures.SendMsgResult
|
||||||
import moe.fuqiuluo.shamrock.tools.*
|
import moe.fuqiuluo.shamrock.tools.*
|
||||||
import protobuf.message.Elem
|
import moe.fuqiuluo.shamrock.xposed.helper.QQInterfaces.Companion.app
|
||||||
|
import moe.fuqiuluo.shamrock.xposed.helper.msgService
|
||||||
import protobuf.message.RichText
|
import protobuf.message.RichText
|
||||||
import kotlin.coroutines.resume
|
import kotlin.coroutines.resume
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
@ -49,6 +54,28 @@ internal object MessageHelper {
|
|||||||
return sendMessageWithoutMsgId(chatType, peerId, msg, fromId, callback)
|
return sendMessageWithoutMsgId(chatType, peerId, msg, fromId, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun sendMessage(contact: Contact, msgs: ArrayList<MsgElement>, retry: Int, msgId: SendMsgResult): Result<SendMsgResult> {
|
||||||
|
if (contact.chatType == MsgConstant.KCHATTYPETEMPC2CFROMGROUP) {
|
||||||
|
prepareTempChatFromGroup(contact.guildId, contact.peerUid).getOrThrow()
|
||||||
|
}
|
||||||
|
return withTimeoutOrNull(5000) {
|
||||||
|
suspendCancellableCoroutine {
|
||||||
|
QRoute.api(IMsgService::class.java).sendMsg(contact, msgId.qqMsgId, msgs) { code: Int, msg: String ->
|
||||||
|
if (code == 0) {
|
||||||
|
it.resume(msgId.qqMsgId)
|
||||||
|
} else {
|
||||||
|
LogCenter.log("消息发送失败: $code:$msg", Level.WARN)
|
||||||
|
it.resume(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}?.let { Result.success(SendMsgResult(
|
||||||
|
msgHashId = msgId.msgHashId,
|
||||||
|
qqMsgId = it,
|
||||||
|
msgTime = System.currentTimeMillis()
|
||||||
|
)) } ?: resendMsg(contact, msgId.qqMsgId, retry, msgHashId = msgId.msgHashId)
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun resendMsg(
|
suspend fun resendMsg(
|
||||||
chatType: Int,
|
chatType: Int,
|
||||||
peerId: String,
|
peerId: String,
|
||||||
@ -247,6 +274,40 @@ internal object MessageHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun getTempChatInfo(chatType: Int, uid: String): Result<TempChatInfo> {
|
||||||
|
val msgService = app.getRuntimeService(IKernelService::class.java, "all").msgService
|
||||||
|
?: return Result.failure(Exception("获取消息服务失败"))
|
||||||
|
val info: TempChatInfo = withTimeoutOrNull(5000) {
|
||||||
|
suspendCancellableCoroutine {
|
||||||
|
msgService.getTempChatInfo(chatType, uid) { code, msg, tempChatInfo ->
|
||||||
|
if (code == 0) {
|
||||||
|
it.resume(tempChatInfo)
|
||||||
|
} else {
|
||||||
|
LogCenter.log("获取临时会话信息失败: $code:$msg", Level.ERROR)
|
||||||
|
it.resume(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} ?: return Result.failure(Exception("获取临时会话信息失败"))
|
||||||
|
return Result.success(info)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun generateContact(record: MsgRecord): Contact {
|
||||||
|
val peerId = when (record.chatType) {
|
||||||
|
MsgConstant.KCHATTYPEC2C, MsgConstant.KCHATTYPETEMPC2CFROMGROUP -> record.senderUid
|
||||||
|
MsgConstant.KCHATTYPEGUILD -> record.channelId
|
||||||
|
else -> record.peerUin.toString()
|
||||||
|
}
|
||||||
|
return Contact(record.chatType, peerId, if (record.chatType == MsgConstant.KCHATTYPEGUILD) {
|
||||||
|
record.guildId
|
||||||
|
} else if(record.chatType == MsgConstant.KCHATTYPETEMPC2CFROMGROUP) {
|
||||||
|
val tempInfo = getTempChatInfo(record.chatType, peerId).getOrThrow()
|
||||||
|
tempInfo.groupCode
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun generateContact(chatType: Int, id: String, subId: String = ""): Contact {
|
suspend fun generateContact(chatType: Int, id: String, subId: String = ""): Contact {
|
||||||
val peerId = when (chatType) {
|
val peerId = when (chatType) {
|
||||||
MsgConstant.KCHATTYPEC2C, MsgConstant.KCHATTYPETEMPC2CFROMGROUP -> {
|
MsgConstant.KCHATTYPEC2C, MsgConstant.KCHATTYPETEMPC2CFROMGROUP -> {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package moe.fuqiuluo.shamrock.remote
|
package moe.fuqiuluo.shamrock.remote
|
||||||
|
|
||||||
|
import com.tencent.mobileqq.app.QQAppInterface
|
||||||
import io.ktor.server.application.Application
|
import io.ktor.server.application.Application
|
||||||
import io.ktor.server.application.install
|
import io.ktor.server.application.install
|
||||||
import io.ktor.server.engine.ApplicationEngine
|
import io.ktor.server.engine.ApplicationEngine
|
||||||
@ -21,7 +22,9 @@ import moe.fuqiuluo.shamrock.remote.plugin.Auth
|
|||||||
import moe.fuqiuluo.shamrock.remote.service.config.ShamrockConfig
|
import moe.fuqiuluo.shamrock.remote.service.config.ShamrockConfig
|
||||||
import moe.fuqiuluo.shamrock.helper.Level
|
import moe.fuqiuluo.shamrock.helper.Level
|
||||||
import moe.fuqiuluo.shamrock.helper.LogCenter
|
import moe.fuqiuluo.shamrock.helper.LogCenter
|
||||||
import moe.fuqiuluo.shamrock.xposed.helper.internal.DataRequester
|
import moe.fuqiuluo.shamrock.tools.ShamrockVersion
|
||||||
|
import moe.fuqiuluo.shamrock.xposed.helper.AppTalker
|
||||||
|
import moe.fuqiuluo.shamrock.xposed.helper.QQInterfaces.Companion.app
|
||||||
import moe.fuqiuluo.shamrock.xposed.loader.NativeLoader
|
import moe.fuqiuluo.shamrock.xposed.loader.NativeLoader
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import java.security.KeyStore
|
import java.security.KeyStore
|
||||||
@ -138,10 +141,13 @@ internal object HTTPServer {
|
|||||||
isServiceStarted = true
|
isServiceStarted = true
|
||||||
currServerPort = port
|
currServerPort = port
|
||||||
LogCenter.log("Start HTTP Server: http://0.0.0.0:$currServerPort/")
|
LogCenter.log("Start HTTP Server: http://0.0.0.0:$currServerPort/")
|
||||||
DataRequester.request("success", values = mapOf(
|
AppTalker.talk("success") {
|
||||||
"port" to currServerPort,
|
put("account", app.currentAccountUin)
|
||||||
"voice" to NativeLoader.isVoiceLoaded
|
put("nickname", if (app is QQAppInterface) (app.currentNickname ?: "unknown") else "unknown")
|
||||||
))
|
put("voice", NativeLoader.isVoiceLoaded)
|
||||||
|
put("core_version", ShamrockVersion)
|
||||||
|
put("port", currServerPort)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isActive(): Boolean {
|
fun isActive(): Boolean {
|
||||||
|
@ -17,7 +17,7 @@ internal object BanTroopMember: IActionHandler() {
|
|||||||
return invoke(groupId, userId, duration, session.echo)
|
return invoke(groupId, userId, duration, session.echo)
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun invoke(
|
suspend operator fun invoke(
|
||||||
groupId: Long,
|
groupId: Long,
|
||||||
userId: Long,
|
userId: Long,
|
||||||
duration: Int = 30 * 60,
|
duration: Int = 30 * 60,
|
||||||
|
@ -14,6 +14,7 @@ import moe.fuqiuluo.shamrock.remote.service.data.HONOR_NEWBIE
|
|||||||
import moe.fuqiuluo.shamrock.remote.service.data.HONOR_TALKATIVE
|
import moe.fuqiuluo.shamrock.remote.service.data.HONOR_TALKATIVE
|
||||||
import moe.fuqiuluo.shamrock.tools.EmptyJsonString
|
import moe.fuqiuluo.shamrock.tools.EmptyJsonString
|
||||||
import moe.fuqiuluo.symbols.OneBotHandler
|
import moe.fuqiuluo.symbols.OneBotHandler
|
||||||
|
import tencent.im.troop.honor.troop_honor
|
||||||
|
|
||||||
@OneBotHandler("get_group_honor_info", ["get_troop_honor_info"])
|
@OneBotHandler("get_group_honor_info", ["get_troop_honor_info"])
|
||||||
internal object GetTroopHonor: IActionHandler() {
|
internal object GetTroopHonor: IActionHandler() {
|
||||||
@ -29,11 +30,15 @@ internal object GetTroopHonor: IActionHandler() {
|
|||||||
GroupSvc.getGroupMemberList(groupId, refresh).onFailure {
|
GroupSvc.getGroupMemberList(groupId, refresh).onFailure {
|
||||||
return error(it.message ?: "unknown error", echo)
|
return error(it.message ?: "unknown error", echo)
|
||||||
}.onSuccess { memberList ->
|
}.onSuccess { memberList ->
|
||||||
memberList.forEach { member ->
|
memberList.values.forEach { info ->
|
||||||
GroupSvc.parseHonor(member.honorList).forEach {
|
info.groupHonor.let { bytes ->
|
||||||
val honor = decodeHonor(member.memberuin.toLong(), it, member.mHonorRichFlag)
|
val honor = troop_honor.GroupUserCardHonor()
|
||||||
|
honor.mergeFrom(bytes)
|
||||||
|
honor.id.get()
|
||||||
|
}.forEach {
|
||||||
|
val honor = decodeHonor(info.uin, it, 0)
|
||||||
if (honor != null) {
|
if (honor != null) {
|
||||||
honor.nick = member.troopnick.ifEmpty { member.friendnick }
|
honor.nick = info.nick.ifEmpty { info.cardName }
|
||||||
honorInfo.add(honor)
|
honorInfo.add(honor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,18 @@
|
|||||||
package moe.fuqiuluo.shamrock.remote.action.handlers
|
package moe.fuqiuluo.shamrock.remote.action.handlers
|
||||||
|
|
||||||
import com.tencent.mobileqq.data.Card
|
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 kotlinx.serialization.json.JsonElement
|
||||||
import moe.fuqiuluo.qqinterface.servlet.GroupSvc
|
import moe.fuqiuluo.qqinterface.servlet.GroupSvc
|
||||||
import moe.fuqiuluo.shamrock.remote.action.ActionSession
|
import moe.fuqiuluo.shamrock.remote.action.ActionSession
|
||||||
import moe.fuqiuluo.shamrock.remote.action.IActionHandler
|
import moe.fuqiuluo.shamrock.remote.action.IActionHandler
|
||||||
import moe.fuqiuluo.shamrock.remote.service.data.SimpleTroopMemberInfo
|
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.EmptyJsonString
|
||||||
import moe.fuqiuluo.shamrock.tools.ifNullOrEmpty
|
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.symbols.OneBotHandler
|
import moe.fuqiuluo.symbols.OneBotHandler
|
||||||
|
|
||||||
@OneBotHandler("get_group_member_info")
|
@OneBotHandler("get_group_member_info")
|
||||||
@ -26,17 +31,64 @@ internal object GetTroopMemberInfo : IActionHandler() {
|
|||||||
refresh: Boolean,
|
refresh: Boolean,
|
||||||
echo: JsonElement = EmptyJsonString
|
echo: JsonElement = EmptyJsonString
|
||||||
): String {
|
): String {
|
||||||
val info = GroupSvc.getTroopMemberInfoByUin(groupId, userId, refresh).onFailure {
|
val info = GroupSvc.getTroopMemberInfoByUinV2(groupId, userId, refresh).onFailure {
|
||||||
return error(it.message ?: "unknown error", echo)
|
return error(it.message ?: "unknown error", echo)
|
||||||
}.getOrThrow()
|
}.getOrThrow()
|
||||||
|
|
||||||
return ok(
|
val code = PlatformUtils.getQQVersionCode()
|
||||||
SimpleTroopMemberInfo(
|
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(),
|
uin = info.memberuin.toLong(),
|
||||||
name = info.friendnick.ifNullOrEmpty(info.autoremark) ?: "",
|
name = info.friendnick.ifNullOrEmpty(info.autoremark) ?: "",
|
||||||
showName = info.troopnick.ifNullOrEmpty(info.troopColorNick),
|
showName = info.troopnick.ifNullOrEmpty(info.troopColorNick),
|
||||||
cardName = info.troopnick.ifNullOrEmpty(info.troopColorNick),
|
cardName = info.troopnick.ifNullOrEmpty(info.troopColorNick),
|
||||||
distance = info.distance,
|
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),
|
honor = GroupSvc.parseHonor(info.honorList),
|
||||||
joinTime = info.join_time,
|
joinTime = info.join_time,
|
||||||
lastActiveTime = info.last_active_time,
|
lastActiveTime = info.last_active_time,
|
||||||
@ -48,7 +100,7 @@ internal object GetTroopMemberInfo : IActionHandler() {
|
|||||||
Card.MALE -> "male"
|
Card.MALE -> "male"
|
||||||
else -> "unknown"
|
else -> "unknown"
|
||||||
},
|
},
|
||||||
area = info.alias ?: "",
|
area = "",
|
||||||
lastSentTime = info.last_active_time,
|
lastSentTime = info.last_active_time,
|
||||||
level = info.level,
|
level = info.level,
|
||||||
role = GroupSvc.getMemberRole(groupId, userId),
|
role = GroupSvc.getMemberRole(groupId, userId),
|
||||||
@ -58,8 +110,12 @@ internal object GetTroopMemberInfo : IActionHandler() {
|
|||||||
cardChangeable = GroupSvc.isAdmin(groupId),
|
cardChangeable = GroupSvc.isAdmin(groupId),
|
||||||
age = info.age.toInt(),
|
age = info.age.toInt(),
|
||||||
shutUpTimestamp = 0L
|
shutUpTimestamp = 0L
|
||||||
), echo
|
).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")
|
override val requiredParams: Array<String> = arrayOf("user_id", "group_id")
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package moe.fuqiuluo.shamrock.remote.action.handlers
|
package moe.fuqiuluo.shamrock.remote.action.handlers
|
||||||
|
|
||||||
import com.tencent.mobileqq.data.Card
|
|
||||||
import kotlinx.serialization.json.JsonElement
|
import kotlinx.serialization.json.JsonElement
|
||||||
import moe.fuqiuluo.qqinterface.servlet.GroupSvc
|
import moe.fuqiuluo.qqinterface.servlet.GroupSvc
|
||||||
import moe.fuqiuluo.shamrock.remote.action.ActionSession
|
import moe.fuqiuluo.shamrock.remote.action.ActionSession
|
||||||
@ -8,8 +7,8 @@ import moe.fuqiuluo.shamrock.remote.action.IActionHandler
|
|||||||
import moe.fuqiuluo.shamrock.remote.service.data.SimpleTroopMemberInfo
|
import moe.fuqiuluo.shamrock.remote.service.data.SimpleTroopMemberInfo
|
||||||
import moe.fuqiuluo.shamrock.remote.service.data.push.MemberRole
|
import moe.fuqiuluo.shamrock.remote.service.data.push.MemberRole
|
||||||
import moe.fuqiuluo.shamrock.tools.EmptyJsonString
|
import moe.fuqiuluo.shamrock.tools.EmptyJsonString
|
||||||
import moe.fuqiuluo.shamrock.tools.ifNullOrEmpty
|
|
||||||
import moe.fuqiuluo.symbols.OneBotHandler
|
import moe.fuqiuluo.symbols.OneBotHandler
|
||||||
|
import tencent.im.troop.honor.troop_honor
|
||||||
|
|
||||||
@OneBotHandler("get_group_member_list")
|
@OneBotHandler("get_group_member_list")
|
||||||
internal object GetTroopMemberList : IActionHandler() {
|
internal object GetTroopMemberList : IActionHandler() {
|
||||||
@ -27,49 +26,48 @@ internal object GetTroopMemberList : IActionHandler() {
|
|||||||
val memberList = GroupSvc.getGroupMemberList(groupId, refresh).onFailure {
|
val memberList = GroupSvc.getGroupMemberList(groupId, refresh).onFailure {
|
||||||
return error(it.message ?: "unknown error", echo, arrayResult = true)
|
return error(it.message ?: "unknown error", echo, arrayResult = true)
|
||||||
}.getOrThrow()
|
}.getOrThrow()
|
||||||
val prohibitedMemberList = GroupSvc.getProhibitedMemberList(groupId)
|
// val prohibitedMemberList = GroupSvc.getProhibitedMemberList(groupId)
|
||||||
.getOrDefault(arrayListOf())
|
// .getOrDefault(arrayListOf())
|
||||||
.associate { it.memberUin to it.shutuptimestap.toLong() }
|
// .associate { it.memberUin to it.shutuptimestap.toLong() }
|
||||||
return ok(arrayListOf<SimpleTroopMemberInfo>().apply {
|
return ok(arrayListOf<SimpleTroopMemberInfo>().apply {
|
||||||
memberList.forEach { info ->
|
memberList.values.forEach { info ->
|
||||||
if (info.memberuin != "0") {
|
|
||||||
add(
|
add(
|
||||||
SimpleTroopMemberInfo(
|
SimpleTroopMemberInfo(
|
||||||
uin = info.memberuin.toLong(),
|
uin = info.uin,
|
||||||
name = info.friendnick.ifNullOrEmpty(info.autoremark) ?: "",
|
name = info.nick ?: "",
|
||||||
showName = info.troopnick.ifNullOrEmpty(info.troopColorNick),
|
showName = info.cardName,
|
||||||
cardName = info.troopnick.ifNullOrEmpty(info.troopColorNick),
|
cardName = info.cardName,
|
||||||
distance = info.distance,
|
distance = 0,
|
||||||
honor = GroupSvc.parseHonor(info.honorList),
|
honor = info.groupHonor.let { bytes ->
|
||||||
joinTime = info.join_time,
|
val honor = troop_honor.GroupUserCardHonor()
|
||||||
lastActiveTime = info.last_active_time,
|
honor.mergeFrom(bytes)
|
||||||
uniqueName = info.mUniqueTitle,
|
honor.id.get()
|
||||||
groupId = groupId,
|
|
||||||
nick = info.friendnick.ifNullOrEmpty(info.autoremark) ?: "",
|
|
||||||
sex = when (info.sex.toShort()) {
|
|
||||||
Card.FEMALE -> "female"
|
|
||||||
Card.MALE -> "male"
|
|
||||||
else -> "unknown"
|
|
||||||
},
|
},
|
||||||
area = info.alias ?: "",
|
joinTime = info.joinTime.toLong(),
|
||||||
lastSentTime = info.last_active_time,
|
lastActiveTime = info.lastSpeakTime.toLong(),
|
||||||
level = info.level,
|
uniqueName = info.memberSpecialTitle,
|
||||||
role = GroupSvc.getMemberRole(groupId, info.memberuin.toLong())
|
groupId = groupId,
|
||||||
/*when {
|
nick = info.nick ?: "",
|
||||||
GroupSvc.getOwner(groupId)
|
sex = "unknown",
|
||||||
.toString() == info.memberuin -> MemberRole.Owner
|
area = "",
|
||||||
info.memberuin.toLong() in GroupSvc.getAdminList(groupId) -> MemberRole.Admin
|
lastSentTime = info.lastSpeakTime.toLong(),
|
||||||
|
level = info.memberLevel,
|
||||||
|
role = info.role.let { role ->
|
||||||
|
when (role) {
|
||||||
|
com.tencent.qqnt.kernelpublic.nativeinterface.MemberRole.OWNER -> MemberRole.Owner
|
||||||
|
com.tencent.qqnt.kernelpublic.nativeinterface.MemberRole.ADMIN -> MemberRole.Admin
|
||||||
else -> MemberRole.Member
|
else -> MemberRole.Member
|
||||||
}*/,
|
|
||||||
unfriendly = false,
|
|
||||||
title = info.mUniqueTitle ?: "",
|
|
||||||
titleExpireTime = info.mUniqueTitleExpire,
|
|
||||||
cardChangeable = GroupSvc.isAdmin(groupId),
|
|
||||||
age = 0,
|
|
||||||
shutUpTimestamp = prohibitedMemberList[info.memberuin.toLong()] ?: 0L
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
unfriendly = false,
|
||||||
|
title = info.memberSpecialTitle ?: "",
|
||||||
|
titleExpireTime = info.specialTitleExpireTime.toInt(),
|
||||||
|
cardChangeable = info.role == com.tencent.qqnt.kernelpublic.nativeinterface.MemberRole.ADMIN,
|
||||||
|
age = 0,
|
||||||
|
shutUpTimestamp = info.shutUpTime.toLong()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
}, echo)
|
}, echo)
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ internal object ModifyTroopMemberName: IActionHandler() {
|
|||||||
return invoke(groupId, userId, name, session.echo)
|
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()) {
|
if (!GroupSvc.isAdmin(groupId) && userId != TicketSvc.getUin().toLong()) {
|
||||||
return logic("you are not admin", echo)
|
return logic("you are not admin", echo)
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ internal object ModifyTroopName: IActionHandler() {
|
|||||||
return invoke(groupId, groupName, session.echo)
|
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)) {
|
return if (GroupSvc.isAdmin(groupId)) {
|
||||||
GroupSvc.modifyTroopName(groupId, name)
|
GroupSvc.modifyTroopName(groupId, name)
|
||||||
ok("成功", echo)
|
ok("成功", echo)
|
||||||
|
@ -0,0 +1,134 @@
|
|||||||
|
package moe.fuqiuluo.shamrock.remote.action.handlers
|
||||||
|
|
||||||
|
import com.tencent.mobileqq.l0.b.c
|
||||||
|
import com.tencent.mobileqq.ocr.a.a
|
||||||
|
import com.tencent.mobileqq.ocr.api.IPicOcrService
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import kotlinx.coroutines.withTimeoutOrNull
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.json.JsonElement
|
||||||
|
import moe.fuqiuluo.shamrock.helper.Level
|
||||||
|
import moe.fuqiuluo.shamrock.helper.LogCenter
|
||||||
|
import moe.fuqiuluo.shamrock.remote.action.ActionSession
|
||||||
|
import moe.fuqiuluo.shamrock.remote.action.IActionHandler
|
||||||
|
import moe.fuqiuluo.shamrock.tools.EmptyJsonString
|
||||||
|
import moe.fuqiuluo.shamrock.utils.FileUtils
|
||||||
|
import moe.fuqiuluo.shamrock.utils.MD5
|
||||||
|
import moe.fuqiuluo.shamrock.xposed.helper.QQInterfaces
|
||||||
|
import moe.fuqiuluo.symbols.OneBotHandler
|
||||||
|
import java.io.File
|
||||||
|
import kotlin.coroutines.resume
|
||||||
|
|
||||||
|
@OneBotHandler("ocr_image")
|
||||||
|
internal object OcrImage: IActionHandler() {
|
||||||
|
override suspend fun internalHandle(session: ActionSession): String {
|
||||||
|
val image = session.getString("image")
|
||||||
|
return invoke(image, session.echo)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend operator fun invoke(image: String, echo: JsonElement = EmptyJsonString): String {
|
||||||
|
val file = FileUtils.getFile(image).let {
|
||||||
|
if (!it.exists()) {
|
||||||
|
return@let FileUtils.parseAndSave(image)
|
||||||
|
}
|
||||||
|
it
|
||||||
|
}
|
||||||
|
LogCenter.log("对${file.absoluteFile.absolutePath}进行OCR", Level.DEBUG)
|
||||||
|
val retryCount = 10
|
||||||
|
val delayMillis = 1000L
|
||||||
|
repeat(retryCount) {
|
||||||
|
val result = getOcrResult(file)
|
||||||
|
|
||||||
|
if (result.isSuccess) {
|
||||||
|
return ok(result.getOrNull(), echo)
|
||||||
|
} else if (result.isFailure && result.exceptionOrNull()?.message == "no cache") {
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
Thread.sleep(delayMillis)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return error(result.exceptionOrNull()?.message ?: "", echo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return error("ocr failed", echo)
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun getOcrResult(file: File): Result<OcrResult> {
|
||||||
|
val ocrService = QQInterfaces.app.getRuntimeService(IPicOcrService::class.java, "all")
|
||||||
|
?: return Result.failure(Error("获取OCR服务失败"))
|
||||||
|
return withTimeoutOrNull(5000) {
|
||||||
|
suspendCancellableCoroutine { continuation ->
|
||||||
|
ocrService.requestOcr(
|
||||||
|
a().apply {
|
||||||
|
this.b = 1
|
||||||
|
this.c = file.absolutePath
|
||||||
|
this.f = MD5.genFileMd5Hex(file.absolutePath)
|
||||||
|
}, object : com.tencent.mobileqq.l0.b.a() {
|
||||||
|
override fun b() {
|
||||||
|
// call uploadOcrPic and then call b
|
||||||
|
continuation.resume(Result.failure(Error("no cache")))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun c(result: c?) {
|
||||||
|
continuation.resume(Result.success(OcrResult(
|
||||||
|
texts = result?.f?.map {
|
||||||
|
TextDetection(
|
||||||
|
text = it.a,
|
||||||
|
confidence = it.b,
|
||||||
|
coordinates = it.c.map {
|
||||||
|
ArrayList<Int>().apply {
|
||||||
|
add(it.x)
|
||||||
|
add(it.y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}!!,
|
||||||
|
language = result.h[result.d] ?: result.d,
|
||||||
|
url = result.e
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
override fun onUpdate(i2: Int, z: Boolean, obj: Any?) {
|
||||||
|
LogCenter.log("$i2, $z, ${obj.toString()}")
|
||||||
|
if (i2 == 100) {
|
||||||
|
val result = obj as c
|
||||||
|
continuation.resume(Result.success(OcrResult(
|
||||||
|
texts = result.f.map {
|
||||||
|
TextDetection(
|
||||||
|
text = it.a,
|
||||||
|
confidence = it.b,
|
||||||
|
coordinates = it.c.map {
|
||||||
|
ArrayList<Int>().apply {
|
||||||
|
add(it.x)
|
||||||
|
add(it.y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
language = result.h[result.d] ?: result.d,
|
||||||
|
url = result.e
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
} ?: Result.failure(Exception("OCR timed out"))
|
||||||
|
}
|
||||||
|
|
||||||
|
override val requiredParams: Array<String> = arrayOf("group_id", "user_id")
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class OcrResult (
|
||||||
|
val texts: List<TextDetection>,
|
||||||
|
val language: String,
|
||||||
|
val url: String
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class TextDetection (
|
||||||
|
val text: String,
|
||||||
|
val confidence: Int,
|
||||||
|
val coordinates: List<List<Int>>
|
||||||
|
)
|
||||||
|
}
|
@ -2,11 +2,10 @@ package moe.fuqiuluo.shamrock.remote.action.handlers
|
|||||||
|
|
||||||
import kotlinx.atomicfu.atomic
|
import kotlinx.atomicfu.atomic
|
||||||
import kotlinx.serialization.json.JsonElement
|
import kotlinx.serialization.json.JsonElement
|
||||||
|
|
||||||
import moe.fuqiuluo.qqinterface.servlet.BaseSvc
|
|
||||||
import moe.fuqiuluo.shamrock.remote.action.ActionSession
|
import moe.fuqiuluo.shamrock.remote.action.ActionSession
|
||||||
import moe.fuqiuluo.shamrock.remote.action.IActionHandler
|
import moe.fuqiuluo.shamrock.remote.action.IActionHandler
|
||||||
import moe.fuqiuluo.shamrock.tools.EmptyJsonString
|
import moe.fuqiuluo.shamrock.tools.EmptyJsonString
|
||||||
|
import moe.fuqiuluo.shamrock.xposed.helper.QQInterfaces
|
||||||
import moe.fuqiuluo.symbols.OneBotHandler
|
import moe.fuqiuluo.symbols.OneBotHandler
|
||||||
import protobuf.auto.toByteArray
|
import protobuf.auto.toByteArray
|
||||||
import protobuf.message.*
|
import protobuf.message.*
|
||||||
@ -51,7 +50,7 @@ internal object SendMsgByResid : IActionHandler() {
|
|||||||
msgRand = Random.nextUInt(),
|
msgRand = Random.nextUInt(),
|
||||||
msgVia = 0u
|
msgVia = 0u
|
||||||
)
|
)
|
||||||
BaseSvc.sendBufferAW("MessageSvc.PbSendMsg", true, req.toByteArray())
|
QQInterfaces.sendBufferAW("MessageSvc.PbSendMsg", true, req.toByteArray())
|
||||||
return ok("ok", echo)
|
return ok("ok", echo)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +39,6 @@ import moe.fuqiuluo.shamrock.tools.hex2ByteArray
|
|||||||
import moe.fuqiuluo.shamrock.tools.json
|
import moe.fuqiuluo.shamrock.tools.json
|
||||||
import moe.fuqiuluo.shamrock.tools.respond
|
import moe.fuqiuluo.shamrock.tools.respond
|
||||||
import moe.fuqiuluo.shamrock.tools.toHexString
|
import moe.fuqiuluo.shamrock.tools.toHexString
|
||||||
import moe.fuqiuluo.shamrock.xposed.ipc.ShamrockIpc
|
|
||||||
import moe.fuqiuluo.shamrock.xposed.ipc.bytedata.IByteData
|
import moe.fuqiuluo.shamrock.xposed.ipc.bytedata.IByteData
|
||||||
import moe.fuqiuluo.shamrock.xposed.ipc.qsign.IQSigner
|
import moe.fuqiuluo.shamrock.xposed.ipc.qsign.IQSigner
|
||||||
import mqq.app.MobileQQ
|
import mqq.app.MobileQQ
|
||||||
@ -113,10 +112,7 @@ fun Routing.qsign() {
|
|||||||
return@get
|
return@get
|
||||||
}
|
}
|
||||||
if (signer == null || signer?.asBinder()?.isBinderAlive == false) {
|
if (signer == null || signer?.asBinder()?.isBinderAlive == false) {
|
||||||
if (!initSigner()) {
|
call.respond(OldApiResult(-2, "不支持的操作", null))
|
||||||
respond(false, Status.InternalHandlerError)
|
|
||||||
return@get
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
val list = signer!!.cmdWhiteList
|
val list = signer!!.cmdWhiteList
|
||||||
call.respond(OldApiResult(0, "success", list))
|
call.respond(OldApiResult(0, "success", list))
|
||||||
@ -128,10 +124,7 @@ fun Routing.qsign() {
|
|||||||
return@getOrPost
|
return@getOrPost
|
||||||
}
|
}
|
||||||
if (signer == null || signer?.asBinder()?.isBinderAlive == false) {
|
if (signer == null || signer?.asBinder()?.isBinderAlive == false) {
|
||||||
if (!initSigner()) {
|
call.respond(OldApiResult(-2, "不支持的操作", null))
|
||||||
respond(false, Status.InternalHandlerError)
|
|
||||||
return@getOrPost
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val uin = fetchOrThrow("uin")
|
val uin = fetchOrThrow("uin")
|
||||||
@ -213,43 +206,7 @@ fun Routing.qsign() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get("/get_byte") {
|
get("/get_byte") {
|
||||||
if (!isMsfServiceAlive()) {
|
call.respond(OldApiResult(-2, "不支持的操作", null))
|
||||||
call.respond(OldApiResult(-2, "MSF服务未启动", null))
|
|
||||||
return@get
|
|
||||||
}
|
|
||||||
if (byteData == null || byteData?.asBinder()?.isBinderAlive == false) {
|
|
||||||
val binder = ShamrockIpc.get(ShamrockIpc.IPC_BYTEDATA)
|
|
||||||
if (binder == null) {
|
|
||||||
call.respond(OldApiResult(-2, "获取失败", null))
|
|
||||||
return@get
|
|
||||||
} else {
|
|
||||||
byteData = IByteData.Stub.asInterface(binder)
|
|
||||||
binder.linkToDeath({
|
|
||||||
byteData = null
|
|
||||||
}, 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val data = fetchGetOrThrow("data")
|
|
||||||
if(!(data.startsWith("810_") || data.startsWith("812_"))) {
|
|
||||||
call.respond(OldApiResult(-2, "data参数不合法", null))
|
|
||||||
return@get
|
|
||||||
}
|
|
||||||
|
|
||||||
val uin = fetchOrThrow("uin")
|
|
||||||
val salt = fetchSalt(data, uin)
|
|
||||||
if (salt.isEmpty()) {
|
|
||||||
call.respond(OldApiResult(-2, "无法自动决断mode,请主动提供", null))
|
|
||||||
return@get
|
|
||||||
}
|
|
||||||
|
|
||||||
val sign = byteData!!.sign(uin, data, salt).sign
|
|
||||||
|
|
||||||
if (sign == null) {
|
|
||||||
call.respond(OldApiResult(-2, "获取失败", null))
|
|
||||||
} else {
|
|
||||||
call.respond(OldApiResult(0, "success", sign.toHexString()))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get("/friend_sign") {
|
get("/friend_sign") {
|
||||||
@ -258,10 +215,7 @@ fun Routing.qsign() {
|
|||||||
return@get
|
return@get
|
||||||
}
|
}
|
||||||
if (signer == null || signer?.asBinder()?.isBinderAlive == false) {
|
if (signer == null || signer?.asBinder()?.isBinderAlive == false) {
|
||||||
if (!initSigner()) {
|
call.respond(OldApiResult(-2, "不支持的操作", null))
|
||||||
respond(false, Status.InternalHandlerError)
|
|
||||||
return@get
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val addUin = fetchOrThrow("add_uin")
|
val addUin = fetchOrThrow("add_uin")
|
||||||
@ -286,10 +240,7 @@ fun Routing.qsign() {
|
|||||||
return@get
|
return@get
|
||||||
}
|
}
|
||||||
if (signer == null || signer?.asBinder()?.isBinderAlive == false) {
|
if (signer == null || signer?.asBinder()?.isBinderAlive == false) {
|
||||||
if (!initSigner()) {
|
call.respond(OldApiResult(-2, "不支持的操作", null))
|
||||||
respond(false, Status.InternalHandlerError)
|
|
||||||
return@get
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val addUin = fetchOrThrow("group_uin")
|
val addUin = fetchOrThrow("group_uin")
|
||||||
@ -387,23 +338,6 @@ private data class Sign(
|
|||||||
val requestCallback: List<Int>
|
val requestCallback: List<Int>
|
||||||
)
|
)
|
||||||
|
|
||||||
private suspend fun initSigner(): Boolean {
|
|
||||||
if (!isMsfServiceAlive()) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
val binder = ShamrockIpc.get(ShamrockIpc.IPC_QSIGN)
|
|
||||||
if (binder == null) {
|
|
||||||
//respond(false, Status.InternalHandlerError)
|
|
||||||
return false
|
|
||||||
} else {
|
|
||||||
signer = IQSigner.Stub.asInterface(binder)
|
|
||||||
binder.linkToDeath({
|
|
||||||
signer = null
|
|
||||||
}, 0)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun PipelineContext<Unit, ApplicationCall>.requestSign(
|
private suspend fun PipelineContext<Unit, ApplicationCall>.requestSign(
|
||||||
cmd: String,
|
cmd: String,
|
||||||
uin: String,
|
uin: String,
|
||||||
@ -415,10 +349,7 @@ private suspend fun PipelineContext<Unit, ApplicationCall>.requestSign(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (signer == null || signer?.asBinder()?.isBinderAlive == false) {
|
if (signer == null || signer?.asBinder()?.isBinderAlive == false) {
|
||||||
if (!initSigner()) {
|
call.respond(OldApiResult(-2, "不支持的操作", null))
|
||||||
respond(false, Status.InternalHandlerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val sign = withTimeoutOrNull(5000) {
|
val sign = withTimeoutOrNull(5000) {
|
||||||
|
@ -12,6 +12,7 @@ import io.ktor.server.routing.post
|
|||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import kotlinx.coroutines.withTimeoutOrNull
|
import kotlinx.coroutines.withTimeoutOrNull
|
||||||
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
import kotlinx.serialization.json.JsonObject
|
import kotlinx.serialization.json.JsonObject
|
||||||
import moe.fuqiuluo.shamrock.remote.action.handlers.CleanCache
|
import moe.fuqiuluo.shamrock.remote.action.handlers.CleanCache
|
||||||
import moe.fuqiuluo.shamrock.remote.action.handlers.DownloadFile
|
import moe.fuqiuluo.shamrock.remote.action.handlers.DownloadFile
|
||||||
@ -19,8 +20,8 @@ import moe.fuqiuluo.shamrock.remote.action.handlers.GetDeviceBattery
|
|||||||
import moe.fuqiuluo.shamrock.remote.action.handlers.GetVersionInfo
|
import moe.fuqiuluo.shamrock.remote.action.handlers.GetVersionInfo
|
||||||
import moe.fuqiuluo.shamrock.remote.action.handlers.RestartMe
|
import moe.fuqiuluo.shamrock.remote.action.handlers.RestartMe
|
||||||
import moe.fuqiuluo.shamrock.remote.action.handlers.UploadFileToShamrock
|
import moe.fuqiuluo.shamrock.remote.action.handlers.UploadFileToShamrock
|
||||||
import moe.fuqiuluo.shamrock.remote.structures.Status
|
|
||||||
import moe.fuqiuluo.shamrock.remote.service.config.ShamrockConfig
|
import moe.fuqiuluo.shamrock.remote.service.config.ShamrockConfig
|
||||||
|
import moe.fuqiuluo.shamrock.remote.structures.Status
|
||||||
import moe.fuqiuluo.shamrock.tools.asString
|
import moe.fuqiuluo.shamrock.tools.asString
|
||||||
import moe.fuqiuluo.shamrock.tools.fetchOrNull
|
import moe.fuqiuluo.shamrock.tools.fetchOrNull
|
||||||
import moe.fuqiuluo.shamrock.tools.fetchOrThrow
|
import moe.fuqiuluo.shamrock.tools.fetchOrThrow
|
||||||
@ -34,6 +35,7 @@ import moe.fuqiuluo.shamrock.utils.FileUtils
|
|||||||
import moe.fuqiuluo.shamrock.utils.MD5
|
import moe.fuqiuluo.shamrock.utils.MD5
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
|
@OptIn(ExperimentalSerializationApi::class)
|
||||||
fun Routing.otherAction() {
|
fun Routing.otherAction() {
|
||||||
|
|
||||||
if (ShamrockConfig.allowShell()) {
|
if (ShamrockConfig.allowShell()) {
|
||||||
@ -144,4 +146,5 @@ fun Routing.otherAction() {
|
|||||||
ShamrockConfig[key] = value
|
ShamrockConfig[key] = value
|
||||||
respond(true, Status.Ok, "success")
|
respond(true, Status.Ok, "success")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -2,13 +2,13 @@ package moe.fuqiuluo.shamrock.remote.api
|
|||||||
|
|
||||||
import com.tencent.mobileqq.dt.model.FEBound
|
import com.tencent.mobileqq.dt.model.FEBound
|
||||||
import io.ktor.server.routing.Routing
|
import io.ktor.server.routing.Routing
|
||||||
import moe.fuqiuluo.qqinterface.servlet.BaseSvc
|
|
||||||
import moe.fuqiuluo.shamrock.remote.structures.Protocol
|
import moe.fuqiuluo.shamrock.remote.structures.Protocol
|
||||||
import moe.fuqiuluo.shamrock.remote.structures.QSignDtConfig
|
import moe.fuqiuluo.shamrock.remote.structures.QSignDtConfig
|
||||||
import moe.fuqiuluo.shamrock.remote.structures.Status
|
import moe.fuqiuluo.shamrock.remote.structures.Status
|
||||||
import moe.fuqiuluo.shamrock.tools.*
|
import moe.fuqiuluo.shamrock.tools.*
|
||||||
import moe.fuqiuluo.shamrock.utils.MMKVFetcher
|
import moe.fuqiuluo.shamrock.utils.MMKVFetcher
|
||||||
import moe.fuqiuluo.shamrock.utils.PlatformUtils
|
import moe.fuqiuluo.shamrock.utils.PlatformUtils
|
||||||
|
import moe.fuqiuluo.shamrock.xposed.helper.QQInterfaces
|
||||||
import mqq.app.MobileQQ
|
import mqq.app.MobileQQ
|
||||||
import oicq.wlogin_sdk.tlv_type.tlv_t100
|
import oicq.wlogin_sdk.tlv_type.tlv_t100
|
||||||
import oicq.wlogin_sdk.tlv_type.tlv_t106
|
import oicq.wlogin_sdk.tlv_type.tlv_t106
|
||||||
@ -20,8 +20,8 @@ fun Routing.obtainProtocolData() {
|
|||||||
val cmd = fetchOrThrow("cmd")
|
val cmd = fetchOrThrow("cmd")
|
||||||
val isPb = fetchOrThrow("proto").toBooleanStrict()
|
val isPb = fetchOrThrow("proto").toBooleanStrict()
|
||||||
val buffer = fetchOrThrow("buffer").hex2ByteArray()
|
val buffer = fetchOrThrow("buffer").hex2ByteArray()
|
||||||
val resp = BaseSvc.sendBufferAW(cmd, isPb, buffer)
|
val resp = QQInterfaces.sendBufferAW(cmd, isPb, buffer)
|
||||||
respond(true, Status.Ok, data = resp?.toHexString() ?: "null", msg = "成功")
|
respond(true, Status.Ok, data = resp?.wupBuffer?.toHexString() ?: "null", msg = "成功")
|
||||||
}
|
}
|
||||||
|
|
||||||
getOrPost("/set_guid") {
|
getOrPost("/set_guid") {
|
||||||
|
@ -21,22 +21,27 @@ private fun formatFileName(file: String): String = file
|
|||||||
|
|
||||||
fun Routing.fetchRes() {
|
fun Routing.fetchRes() {
|
||||||
getOrPost("/get_record") {
|
getOrPost("/get_record") {
|
||||||
val file = formatFileName( fetchGetOrThrow("file") )
|
val file = formatFileName( fetchOrThrow("file") )
|
||||||
val format = fetchOrThrow("out_format")
|
val format = fetchOrThrow("out_format")
|
||||||
call.respondText(GetRecord(file, format), ContentType.Application.Json)
|
call.respondText(GetRecord(file, format), ContentType.Application.Json)
|
||||||
}
|
}
|
||||||
|
|
||||||
getOrPost("/get_file") {
|
getOrPost("/get_file") {
|
||||||
val file = formatFileName( fetchGetOrThrow("file") )
|
val file = formatFileName( fetchOrThrow("file") )
|
||||||
val fileType = fetchOrThrow("file_type")
|
val fileType = fetchOrThrow("file_type")
|
||||||
call.respondText(GetFile(file, fileType), ContentType.Application.Json)
|
call.respondText(GetFile(file, fileType), ContentType.Application.Json)
|
||||||
}
|
}
|
||||||
|
|
||||||
getOrPost("/get_image") {
|
getOrPost("/get_image") {
|
||||||
val file = formatFileName( fetchGetOrThrow("file") )
|
val file = formatFileName( fetchOrThrow("file") )
|
||||||
call.respondText(GetImage(file), ContentType.Application.Json)
|
call.respondText(GetImage(file), ContentType.Application.Json)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getOrPost("/ocr_image") {
|
||||||
|
val file = fetchOrThrow("image")
|
||||||
|
call.respondText(OcrImage(file), ContentType.Application.Json)
|
||||||
|
}
|
||||||
|
|
||||||
getOrPost("/upload_group_file") {
|
getOrPost("/upload_group_file") {
|
||||||
val groupId = fetchOrThrow("group_id").toLong()
|
val groupId = fetchOrThrow("group_id").toLong()
|
||||||
val file = fetchOrThrow("file")
|
val file = fetchOrThrow("file")
|
||||||
|
@ -10,9 +10,7 @@ import moe.fuqiuluo.qqinterface.servlet.TicketSvc
|
|||||||
import moe.fuqiuluo.shamrock.helper.Level
|
import moe.fuqiuluo.shamrock.helper.Level
|
||||||
import moe.fuqiuluo.shamrock.helper.LogCenter
|
import moe.fuqiuluo.shamrock.helper.LogCenter
|
||||||
import moe.fuqiuluo.shamrock.helper.MessageHelper
|
import moe.fuqiuluo.shamrock.helper.MessageHelper
|
||||||
import moe.fuqiuluo.shamrock.remote.action.handlers.SendMsgByResid
|
|
||||||
import moe.fuqiuluo.shamrock.remote.service.config.ShamrockConfig
|
import moe.fuqiuluo.shamrock.remote.service.config.ShamrockConfig
|
||||||
import moe.fuqiuluo.shamrock.tools.fetchOrNull
|
|
||||||
import moe.fuqiuluo.shamrock.tools.fetchOrThrow
|
import moe.fuqiuluo.shamrock.tools.fetchOrThrow
|
||||||
import moe.fuqiuluo.shamrock.tools.getOrPost
|
import moe.fuqiuluo.shamrock.tools.getOrPost
|
||||||
import moe.fuqiuluo.shamrock.xposed.helper.NTServiceFetcher
|
import moe.fuqiuluo.shamrock.xposed.helper.NTServiceFetcher
|
||||||
|
@ -6,7 +6,6 @@ import io.ktor.server.application.createApplicationPlugin
|
|||||||
import moe.fuqiuluo.shamrock.remote.service.config.ShamrockConfig
|
import moe.fuqiuluo.shamrock.remote.service.config.ShamrockConfig
|
||||||
import moe.fuqiuluo.shamrock.tools.fetchOrNull
|
import moe.fuqiuluo.shamrock.tools.fetchOrNull
|
||||||
import java.net.URLDecoder
|
import java.net.URLDecoder
|
||||||
import java.nio.charset.Charset
|
|
||||||
|
|
||||||
private suspend fun ApplicationCall.checkToken() {
|
private suspend fun ApplicationCall.checkToken() {
|
||||||
val token = ShamrockConfig.getToken()
|
val token = ShamrockConfig.getToken()
|
||||||
|
@ -1,69 +0,0 @@
|
|||||||
@file:OptIn(DelicateCoroutinesApi::class)
|
|
||||||
|
|
||||||
package moe.fuqiuluo.shamrock.remote.service
|
|
||||||
|
|
||||||
import com.tencent.qphone.base.remote.FromServiceMsg
|
|
||||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.GlobalScope
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import moe.fuqiuluo.shamrock.tools.broadcast
|
|
||||||
import moe.fuqiuluo.shamrock.helper.Level
|
|
||||||
import moe.fuqiuluo.shamrock.helper.LogCenter
|
|
||||||
import moe.fuqiuluo.shamrock.xposed.helper.internal.DynamicReceiver
|
|
||||||
import moe.fuqiuluo.shamrock.xposed.helper.internal.IPCRequest
|
|
||||||
import mqq.app.MobileQQ
|
|
||||||
|
|
||||||
internal object PacketReceiver {
|
|
||||||
private val allowCommandList: MutableSet<String> by lazy { mutableSetOf(
|
|
||||||
"trpc.msg.olpush.OlPushService.MsgPush",
|
|
||||||
|
|
||||||
) } // 非动态注册,永久常驻的包
|
|
||||||
private val HandlerByIpcSet = hashSetOf<String>()
|
|
||||||
|
|
||||||
fun init() {
|
|
||||||
DynamicReceiver.register("register_handler_cmd", IPCRequest {
|
|
||||||
val cmd = it.getStringExtra("handler_cmd")!!
|
|
||||||
LogCenter.log({ "RegisterHandler(cmd = $cmd)" }, Level.DEBUG)
|
|
||||||
HandlerByIpcSet.add(cmd)
|
|
||||||
})
|
|
||||||
DynamicReceiver.register("unregister_handler_cmd", IPCRequest {
|
|
||||||
val cmd = it.getStringExtra("handler_cmd")!!
|
|
||||||
LogCenter.log({ "UnRegisterHandler(cmd = $cmd)" }, Level.DEBUG)
|
|
||||||
HandlerByIpcSet.remove(cmd)
|
|
||||||
})
|
|
||||||
MobileQQ.getContext().broadcast("xqbot") {
|
|
||||||
putExtra("__cmd", "msf_waiter")
|
|
||||||
LogCenter.log("MSF Packet Receiver running!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun onReceive(from: FromServiceMsg) {
|
|
||||||
if (HandlerByIpcSet.contains(from.serviceCmd)
|
|
||||||
|| allowCommandList.contains(from.serviceCmd)
|
|
||||||
) {
|
|
||||||
LogCenter.log({ "ReceivePacket(cmd = ${from.serviceCmd})" }, Level.DEBUG)
|
|
||||||
MobileQQ.getContext().broadcast("xqbot") {
|
|
||||||
putExtra("__cmd", from.serviceCmd)
|
|
||||||
putExtra("buffer", from.wupBuffer)
|
|
||||||
putExtra("seq", from.requestSsoSeq)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
val seq = if (from.appSeq == -1) from.requestSsoSeq else from.appSeq
|
|
||||||
val hash = (from.serviceCmd + seq).hashCode()
|
|
||||||
LogCenter.log({ "ReceivePacket[$hash](cmd = ${from.serviceCmd}, seq = $seq)" }, Level.DEBUG)
|
|
||||||
MobileQQ.getContext().broadcast("xqbot") {
|
|
||||||
putExtra("__hash", hash)
|
|
||||||
putExtra("buffer", from.wupBuffer)
|
|
||||||
putExtra("seq", seq)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun internalOnReceive(from: FromServiceMsg?) {
|
|
||||||
if (from == null) return
|
|
||||||
GlobalScope.launch(Dispatchers.Default) {
|
|
||||||
onReceive(from)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -9,7 +9,6 @@ import kotlinx.coroutines.GlobalScope
|
|||||||
import kotlinx.coroutines.flow.FlowCollector
|
import kotlinx.coroutines.flow.FlowCollector
|
||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import moe.fuqiuluo.qqinterface.servlet.BaseSvc
|
|
||||||
import moe.fuqiuluo.qqinterface.servlet.CardSvc
|
import moe.fuqiuluo.qqinterface.servlet.CardSvc
|
||||||
import moe.fuqiuluo.qqinterface.servlet.GroupSvc
|
import moe.fuqiuluo.qqinterface.servlet.GroupSvc
|
||||||
import moe.fuqiuluo.qqinterface.servlet.msg.toSegments
|
import moe.fuqiuluo.qqinterface.servlet.msg.toSegments
|
||||||
@ -35,9 +34,10 @@ import moe.fuqiuluo.shamrock.remote.service.data.push.Sender
|
|||||||
import moe.fuqiuluo.shamrock.remote.service.data.push.SignDetail
|
import moe.fuqiuluo.shamrock.remote.service.data.push.SignDetail
|
||||||
import moe.fuqiuluo.shamrock.tools.ShamrockDsl
|
import moe.fuqiuluo.shamrock.tools.ShamrockDsl
|
||||||
import moe.fuqiuluo.shamrock.tools.json
|
import moe.fuqiuluo.shamrock.tools.json
|
||||||
|
import moe.fuqiuluo.shamrock.xposed.helper.QQInterfaces
|
||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
|
|
||||||
internal object GlobalEventTransmitter: BaseSvc() {
|
internal object GlobalEventTransmitter: QQInterfaces() {
|
||||||
private val messageEventFlow by lazy {
|
private val messageEventFlow by lazy {
|
||||||
MutableSharedFlow<Pair<MsgRecord, MessageEvent>>()
|
MutableSharedFlow<Pair<MsgRecord, MessageEvent>>()
|
||||||
}
|
}
|
||||||
|
@ -1,284 +1,13 @@
|
|||||||
package moe.fuqiuluo.shamrock.remote.service.config
|
package moe.fuqiuluo.shamrock.remote.service.config
|
||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import com.tencent.mmkv.MMKV
|
|
||||||
import de.robv.android.xposed.XposedBridge
|
import de.robv.android.xposed.XposedBridge
|
||||||
import kotlinx.serialization.decodeFromString
|
import kotlinx.serialization.decodeFromString
|
||||||
import kotlinx.serialization.encodeToString
|
|
||||||
import moe.fuqiuluo.qqinterface.servlet.transfile.NtV2RichMediaSvc
|
|
||||||
import moe.fuqiuluo.shamrock.helper.Level
|
|
||||||
import moe.fuqiuluo.shamrock.helper.LogCenter
|
|
||||||
import moe.fuqiuluo.shamrock.tools.GlobalJson5
|
import moe.fuqiuluo.shamrock.tools.GlobalJson5
|
||||||
import moe.fuqiuluo.shamrock.utils.MMKVFetcher
|
import moe.fuqiuluo.shamrock.xposed.loader.LuoClassloader.moduleLoader
|
||||||
import mqq.app.MobileQQ
|
import mqq.app.MobileQQ
|
||||||
import java.io.File
|
import java.util.Properties
|
||||||
|
|
||||||
internal object ShamrockConfig {
|
internal object ShamrockConfig: ShamrockConfigV0() {
|
||||||
private val ConfigDir = MobileQQ.getContext().getExternalFilesDir(null)!!
|
|
||||||
.parentFile!!.resolve("Tencent/Shamrock").also {
|
|
||||||
if (it.exists()) it.delete()
|
|
||||||
it.mkdirs()
|
|
||||||
}
|
|
||||||
private val config = kotlin.runCatching {
|
|
||||||
GlobalJson5.decodeFromString<ServiceConfig>(ConfigDir.resolve("config.json").also {
|
|
||||||
if (!it.exists()) it.writeText("{}")
|
|
||||||
}.readText())
|
|
||||||
}.onFailure {
|
|
||||||
LogCenter.log("您的配置文件出现错误: ${it.stackTraceToString()}", Level.ERROR)
|
|
||||||
}.getOrElse {
|
|
||||||
ServiceConfig()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isInit(): Boolean {
|
|
||||||
val mmkv = MMKVFetcher.mmkvWithId("shamrock_config")
|
|
||||||
return mmkv.getBoolean("isInit", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateConfig(config: ServiceConfig = this.config) {
|
|
||||||
ConfigDir.resolve("config.json").writeText(GlobalJson5.encodeToString(config))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateConfig(intent: Intent) {
|
|
||||||
mmkv.apply {
|
|
||||||
if (!intent.getBooleanExtra("disable_auto_sync_setting", false)) {
|
|
||||||
putBoolean("tablet", intent.getBooleanExtra("tablet", false)) // 强制平板模式
|
|
||||||
putInt("port", intent.getIntExtra("port", 5700)) // 主动HTTP端口
|
|
||||||
putBoolean("ws", intent.getBooleanExtra("ws", false)) // 主动WS开关
|
|
||||||
putBoolean("http", intent.getBooleanExtra("http", false)) // HTTP回调开关
|
|
||||||
putString("http_addr", intent.getStringExtra("http_addr")) // WebHook回调地址
|
|
||||||
putBoolean("ws_client", intent.getBooleanExtra("ws_client", false)) // 被动WS开关
|
|
||||||
putBoolean("use_cqcode", intent.getBooleanExtra("use_cqcode", false)) // 使用CQ码
|
|
||||||
putBoolean("inject_packet", intent.getBooleanExtra("inject_packet", false)) // 拦截无用包
|
|
||||||
putBoolean("debug", intent.getBooleanExtra("debug", false)) // 调试模式
|
|
||||||
putString( "key_store", intent.getStringExtra("key_store")) // 证书路径
|
|
||||||
putString( "ssl_pwd", intent.getStringExtra("ssl_pwd")) // 证书密码
|
|
||||||
putString( "ssl_private_pwd", intent.getStringExtra("ssl_private_pwd")) // 证书私钥密码
|
|
||||||
putString( "ssl_alias", intent.getStringExtra("ssl_alias")) // 证书别名
|
|
||||||
putInt( "ssl_port", intent.getIntExtra("ssl_port", 5701)) // 主动HTTP端口
|
|
||||||
putBoolean("alive_reply", intent.getBooleanExtra("alive_reply", false)) // 自回复测试
|
|
||||||
putBoolean("enable_self_msg", intent.getBooleanExtra("enable_self_msg", false)) // 推送自己发的消息
|
|
||||||
putBoolean("shell", intent.getBooleanExtra("shell", false)) // 开启Shell接口
|
|
||||||
putBoolean("enable_sync_msg_as_sent_msg", intent.getBooleanExtra("enable_sync_msg_as_sent_msg", false)) // 推送同步消息
|
|
||||||
putBoolean("forbid_useless_process", intent.getBooleanExtra("forbid_useless_process", false)) // 禁用QQ生成无用进程
|
|
||||||
putBoolean("enable_old_bdh", intent.getBooleanExtra("enable_old_bdh", false)) // 启用旧版BDH
|
|
||||||
intent.getStringExtra("up_res_group")?.let { putString("up_res_group", it) }
|
|
||||||
} else {
|
|
||||||
XposedBridge.log("[Shamrock] 已禁用自动同步配置")
|
|
||||||
}
|
|
||||||
config.defaultToken = intent.getStringExtra("token")
|
|
||||||
config.antiTrace = intent.getBooleanExtra("anti_qq_trace", true)
|
|
||||||
val wsPort = intent.getIntExtra("ws_port", 5800)
|
|
||||||
config.activeWebSocket = if (config.activeWebSocket == null) ConnectionConfig(
|
|
||||||
address = "0.0.0.0",
|
|
||||||
port = wsPort,
|
|
||||||
) else config.activeWebSocket?.also {
|
|
||||||
it.port = wsPort
|
|
||||||
}
|
|
||||||
config.passiveWebSocket = intent.getStringExtra("ws_addr")?.split(",", "|", ",")?.filter { address ->
|
|
||||||
address.isNotBlank() && (address.startsWith("ws://") || address.startsWith("wss://"))
|
|
||||||
}?.map {
|
|
||||||
ConnectionConfig(address = it)
|
|
||||||
}?.toMutableList()
|
|
||||||
putBoolean("isInit", true)
|
|
||||||
}
|
|
||||||
if (!intent.getBooleanExtra("disable_auto_sync_setting", false)) {
|
|
||||||
updateConfig()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun putDefaultSettings() {
|
|
||||||
val mmkv = MMKVFetcher.mmkvWithId("shamrock_config")
|
|
||||||
if ((!isInit()) && (!mmkv.getBoolean("isEmergencyInitBefore", false))){
|
|
||||||
mmkv.apply {
|
|
||||||
putBoolean("tablet", false) // 强制平板模式
|
|
||||||
putInt("port", 5700) // 主动HTTP端口
|
|
||||||
putBoolean("ws", false) // 主动WS开关
|
|
||||||
putBoolean("http", false) // HTTP回调开关
|
|
||||||
putString("http_addr", null) // WebHook回调地址
|
|
||||||
putBoolean("ws_client", false) // 被动WS开关
|
|
||||||
putBoolean("use_cqcode", false) // 使用CQ码
|
|
||||||
putBoolean("inject_packet", false) // 拦截无用包
|
|
||||||
putBoolean("debug", false) // 调试模式
|
|
||||||
putString("key_store", null) // 证书路径
|
|
||||||
putString("ssl_pwd", null) // 证书密码
|
|
||||||
putString("ssl_private_pwd", null) // 证书私钥密码
|
|
||||||
putString("ssl_alias", null) // 证书别名
|
|
||||||
putInt("ssl_port", 5701) // 主动HTTP端口
|
|
||||||
putBoolean("alive_reply", true) // 自回复测试
|
|
||||||
putBoolean("enable_self_msg", false) // 推送自己发的消息
|
|
||||||
putBoolean("shell", false) // 开启Shell接口
|
|
||||||
putBoolean("enable_sync_msg_as_sent_msg", true) // 推送同步消息
|
|
||||||
putBoolean("forbid_useless_process", false) // 禁用QQ生成无用进程
|
|
||||||
putBoolean("enable_old_bdh", false) // 启用旧版BDH
|
|
||||||
putBoolean("antiTrace", false)
|
|
||||||
putBoolean("super_anti", true)
|
|
||||||
putString("up_res_group", "")
|
|
||||||
|
|
||||||
config.defaultToken = null
|
|
||||||
// config.antiTrace = true
|
|
||||||
val wsPort = 5800
|
|
||||||
config.activeWebSocket =
|
|
||||||
if (config.activeWebSocket == null) ConnectionConfig(
|
|
||||||
address = "0.0.0.0",
|
|
||||||
port = wsPort,
|
|
||||||
) else config.activeWebSocket?.also {
|
|
||||||
it.port = wsPort
|
|
||||||
}
|
|
||||||
config.passiveWebSocket = null
|
|
||||||
putBoolean("isInit", true)
|
|
||||||
putBoolean("isEmergencyInitBefore", true)
|
|
||||||
}
|
|
||||||
XposedBridge.log("[Shamrock] 强制初始化配置完成,请重新打开QQ")
|
|
||||||
} else {
|
|
||||||
XposedBridge.log("[Shamrock] 程序逻辑错误或错误地多次强制初始化")
|
|
||||||
mmkv.putBoolean("isEmergencyInitBefore", false)
|
|
||||||
XposedBridge.log("[Shamrock] 如果执意要再次强制初始化,请重新执行程序")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val mmkv: MMKV
|
|
||||||
get() = MMKVFetcher.mmkvWithId("shamrock_config")
|
|
||||||
|
|
||||||
fun getUpResGroup(): String {
|
|
||||||
return mmkv.getString("up_res_group", "") ?: ""
|
|
||||||
}
|
|
||||||
|
|
||||||
fun aliveReply(): Boolean {
|
|
||||||
return mmkv.getBoolean("alive_reply", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun allowTempSession(): Boolean {
|
|
||||||
return config.allowTempSession
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getGroupMsgRule(): GroupRule? {
|
|
||||||
return config.rules?.groupRule
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getPrivateRule(): PrivateRule? {
|
|
||||||
return config.rules?.privateRule
|
|
||||||
}
|
|
||||||
|
|
||||||
fun enableSyncMsgAsSentMsg(): Boolean {
|
|
||||||
return mmkv.getBoolean("enable_sync_msg_as_sent_msg", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun enableSelfMsg(): Boolean {
|
|
||||||
return mmkv.getBoolean("enable_self_msg", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun forbidUselessProcess(): Boolean {
|
|
||||||
return mmkv.getBoolean("forbid_useless_process", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun openWebSocketClient(): Boolean {
|
|
||||||
return mmkv.getBoolean("ws_client", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getWebSocketClientAddress(): List<ConnectionConfig> {
|
|
||||||
return config.passiveWebSocket ?: emptyList()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun openWebSocket(): Boolean {
|
|
||||||
return mmkv.getBoolean("ws", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getActiveWebSocketConfig(): ConnectionConfig? {
|
|
||||||
return config.activeWebSocket
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getToken(): String {
|
|
||||||
return config.defaultToken ?: ""
|
|
||||||
}
|
|
||||||
|
|
||||||
fun useCQ(): Boolean {
|
|
||||||
return mmkv.getBoolean("use_cqcode", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun allowWebHook(): Boolean {
|
|
||||||
return mmkv.getBoolean("http", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getWebHookAddress(): String {
|
|
||||||
return mmkv.getString("http_addr", "") ?: ""
|
|
||||||
}
|
|
||||||
|
|
||||||
fun forceTablet(): Boolean {
|
|
||||||
return mmkv.getBoolean("tablet", true)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getPort(): Int {
|
|
||||||
return mmkv.getInt("port", 5700)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isInjectPacket(): Boolean {
|
|
||||||
return mmkv.getBoolean("inject_packet", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun enableOldBDH(): Boolean {
|
|
||||||
return mmkv.getBoolean("enable_old_bdh", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isDebug(): Boolean {
|
|
||||||
return mmkv.getBoolean("debug", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun ssl(): Boolean {
|
|
||||||
return getKeyStorePath()?.exists() == true
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getKeyStorePath(): File? {
|
|
||||||
mmkv.getString("key_store", null)?.let {
|
|
||||||
return File(it)
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
fun sslPwd(): CharArray? {
|
|
||||||
return mmkv.getString("ssl_pwd", null)?.toCharArray()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun sslPrivatePwd(): String? {
|
|
||||||
return mmkv.getString("ssl_private_pwd", null)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun sslAlias(): String? {
|
|
||||||
return mmkv.getString("ssl_alias", null)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getSslPort(): Int {
|
|
||||||
return mmkv.getInt("ssl_port", getPort())
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isDev(): Boolean {
|
|
||||||
return mmkv.getBoolean("dev", false)
|
|
||||||
}
|
|
||||||
|
|
||||||
operator fun set(key: String, value: String) {
|
|
||||||
mmkv.putString(key, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
operator fun set(key: String, value: Boolean) {
|
|
||||||
mmkv.putBoolean(key, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
operator fun set(key: String, value: Int) {
|
|
||||||
mmkv.putInt(key, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
operator fun set(key: String, value: Long) {
|
|
||||||
mmkv.putLong(key, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
operator fun set(key: String, value: Float) {
|
|
||||||
mmkv.putFloat(key, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isAntiTrace(): Boolean {
|
|
||||||
return config.antiTrace
|
|
||||||
}
|
|
||||||
|
|
||||||
fun allowShell(): Boolean {
|
|
||||||
return mmkv.getBoolean("shell", false)
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -0,0 +1,285 @@
|
|||||||
|
package moe.fuqiuluo.shamrock.remote.service.config
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import com.tencent.mmkv.MMKV
|
||||||
|
import de.robv.android.xposed.XposedBridge
|
||||||
|
import kotlinx.serialization.decodeFromString
|
||||||
|
import kotlinx.serialization.encodeToString
|
||||||
|
import moe.fuqiuluo.shamrock.helper.Level
|
||||||
|
import moe.fuqiuluo.shamrock.helper.LogCenter
|
||||||
|
import moe.fuqiuluo.shamrock.tools.GlobalJson5
|
||||||
|
import moe.fuqiuluo.shamrock.tools.toast
|
||||||
|
import moe.fuqiuluo.shamrock.utils.MMKVFetcher
|
||||||
|
import mqq.app.MobileQQ
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
internal abstract class ShamrockConfigV0 {
|
||||||
|
private val configDir = MobileQQ.getContext().getExternalFilesDir(null)!!
|
||||||
|
.parentFile!!.resolve("Tencent/Shamrock").also {
|
||||||
|
if (it.exists()) it.delete()
|
||||||
|
it.mkdirs()
|
||||||
|
}
|
||||||
|
private val config = kotlin.runCatching {
|
||||||
|
GlobalJson5.decodeFromString<ServiceConfig>(configDir.resolve("config.json").also {
|
||||||
|
if (!it.exists()) it.writeText("{}")
|
||||||
|
}.readText())
|
||||||
|
}.onFailure {
|
||||||
|
LogCenter.log("您的配置文件出现错误: ${it.stackTraceToString()}", Level.ERROR)
|
||||||
|
}.getOrElse {
|
||||||
|
ServiceConfig()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isInit(): Boolean {
|
||||||
|
val mmkv = MMKVFetcher.mmkvWithId("shamrock_config")
|
||||||
|
return mmkv.getBoolean("isInit", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateConfig(config: ServiceConfig = this.config) {
|
||||||
|
configDir.resolve("config.json").writeText(GlobalJson5.encodeToString(config))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateConfig(intent: Intent) {
|
||||||
|
MobileQQ.getContext().toast("同步配置数据解析中...")
|
||||||
|
mmkv.apply {
|
||||||
|
if (!intent.getBooleanExtra("disable_auto_sync_setting", false)) {
|
||||||
|
putBoolean("tablet", intent.getBooleanExtra("tablet", false)) // 强制平板模式
|
||||||
|
putInt("port", intent.getIntExtra("port", 5700)) // 主动HTTP端口
|
||||||
|
putBoolean("ws", intent.getBooleanExtra("ws", false)) // 主动WS开关
|
||||||
|
putBoolean("http", intent.getBooleanExtra("http", false)) // HTTP回调开关
|
||||||
|
putString("http_addr", intent.getStringExtra("http_addr")) // WebHook回调地址
|
||||||
|
putBoolean("ws_client", intent.getBooleanExtra("ws_client", false)) // 被动WS开关
|
||||||
|
putBoolean("use_cqcode", intent.getBooleanExtra("use_cqcode", false)) // 使用CQ码
|
||||||
|
putBoolean("inject_packet", intent.getBooleanExtra("inject_packet", false)) // 拦截无用包
|
||||||
|
putBoolean("debug", intent.getBooleanExtra("debug", false)) // 调试模式
|
||||||
|
putString( "key_store", intent.getStringExtra("key_store")) // 证书路径
|
||||||
|
putString( "ssl_pwd", intent.getStringExtra("ssl_pwd")) // 证书密码
|
||||||
|
putString( "ssl_private_pwd", intent.getStringExtra("ssl_private_pwd")) // 证书私钥密码
|
||||||
|
putString( "ssl_alias", intent.getStringExtra("ssl_alias")) // 证书别名
|
||||||
|
putInt( "ssl_port", intent.getIntExtra("ssl_port", 5701)) // 主动HTTP端口
|
||||||
|
putBoolean("alive_reply", intent.getBooleanExtra("alive_reply", false)) // 自回复测试
|
||||||
|
putBoolean("enable_self_msg", intent.getBooleanExtra("enable_self_msg", false)) // 推送自己发的消息
|
||||||
|
putBoolean("shell", intent.getBooleanExtra("shell", false)) // 开启Shell接口
|
||||||
|
putBoolean("enable_sync_msg_as_sent_msg", intent.getBooleanExtra("enable_sync_msg_as_sent_msg", false)) // 推送同步消息
|
||||||
|
putBoolean("forbid_useless_process", intent.getBooleanExtra("forbid_useless_process", false)) // 禁用QQ生成无用进程
|
||||||
|
putBoolean("enable_old_bdh", intent.getBooleanExtra("enable_old_bdh", false)) // 启用旧版BDH
|
||||||
|
intent.getStringExtra("up_res_group")?.let { putString("up_res_group", it) }
|
||||||
|
} else {
|
||||||
|
XposedBridge.log("[Shamrock] 已禁用自动同步配置")
|
||||||
|
}
|
||||||
|
config.defaultToken = intent.getStringExtra("token")
|
||||||
|
config.antiTrace = intent.getBooleanExtra("anti_qq_trace", true)
|
||||||
|
val wsPort = intent.getIntExtra("ws_port", 5800)
|
||||||
|
config.activeWebSocket = if (config.activeWebSocket == null) ConnectionConfig(
|
||||||
|
address = "0.0.0.0",
|
||||||
|
port = wsPort,
|
||||||
|
) else config.activeWebSocket?.also {
|
||||||
|
it.port = wsPort
|
||||||
|
}
|
||||||
|
config.passiveWebSocket = intent.getStringExtra("ws_addr")?.split(",", "|", ",")?.filter { address ->
|
||||||
|
address.isNotBlank() && (address.startsWith("ws://") || address.startsWith("wss://"))
|
||||||
|
}?.map {
|
||||||
|
ConnectionConfig(address = it)
|
||||||
|
}?.toMutableList()
|
||||||
|
putBoolean("isInit", true)
|
||||||
|
}
|
||||||
|
if (!intent.getBooleanExtra("disable_auto_sync_setting", false)) {
|
||||||
|
updateConfig()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun putDefaultSettings() {
|
||||||
|
val mmkv = MMKVFetcher.mmkvWithId("shamrock_config")
|
||||||
|
if ((!isInit()) && (!mmkv.getBoolean("isEmergencyInitBefore", false))){
|
||||||
|
mmkv.apply {
|
||||||
|
putBoolean("tablet", false) // 强制平板模式
|
||||||
|
putInt("port", 5700) // 主动HTTP端口
|
||||||
|
putBoolean("ws", false) // 主动WS开关
|
||||||
|
putBoolean("http", false) // HTTP回调开关
|
||||||
|
putString("http_addr", null) // WebHook回调地址
|
||||||
|
putBoolean("ws_client", false) // 被动WS开关
|
||||||
|
putBoolean("use_cqcode", false) // 使用CQ码
|
||||||
|
putBoolean("inject_packet", false) // 拦截无用包
|
||||||
|
putBoolean("debug", false) // 调试模式
|
||||||
|
putString("key_store", null) // 证书路径
|
||||||
|
putString("ssl_pwd", null) // 证书密码
|
||||||
|
putString("ssl_private_pwd", null) // 证书私钥密码
|
||||||
|
putString("ssl_alias", null) // 证书别名
|
||||||
|
putInt("ssl_port", 5701) // 主动HTTP端口
|
||||||
|
putBoolean("alive_reply", true) // 自回复测试
|
||||||
|
putBoolean("enable_self_msg", false) // 推送自己发的消息
|
||||||
|
putBoolean("shell", false) // 开启Shell接口
|
||||||
|
putBoolean("enable_sync_msg_as_sent_msg", true) // 推送同步消息
|
||||||
|
putBoolean("forbid_useless_process", false) // 禁用QQ生成无用进程
|
||||||
|
putBoolean("enable_old_bdh", false) // 启用旧版BDH
|
||||||
|
putBoolean("antiTrace", false)
|
||||||
|
putBoolean("super_anti", true)
|
||||||
|
putString("up_res_group", "")
|
||||||
|
|
||||||
|
config.defaultToken = null
|
||||||
|
// config.antiTrace = true
|
||||||
|
val wsPort = 5800
|
||||||
|
config.activeWebSocket =
|
||||||
|
if (config.activeWebSocket == null) ConnectionConfig(
|
||||||
|
address = "0.0.0.0",
|
||||||
|
port = wsPort,
|
||||||
|
) else config.activeWebSocket?.also {
|
||||||
|
it.port = wsPort
|
||||||
|
}
|
||||||
|
config.passiveWebSocket = null
|
||||||
|
putBoolean("isInit", true)
|
||||||
|
putBoolean("isEmergencyInitBefore", true)
|
||||||
|
}
|
||||||
|
XposedBridge.log("[Shamrock] 强制初始化配置完成,请重新打开QQ")
|
||||||
|
} else {
|
||||||
|
XposedBridge.log("[Shamrock] 程序逻辑错误或错误地多次强制初始化")
|
||||||
|
mmkv.putBoolean("isEmergencyInitBefore", false)
|
||||||
|
XposedBridge.log("[Shamrock] 如果执意要再次强制初始化,请重新执行程序")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected val mmkv: MMKV
|
||||||
|
get() = MMKVFetcher.mmkvWithId("shamrock_config")
|
||||||
|
|
||||||
|
fun getUpResGroup(): String {
|
||||||
|
return mmkv.getString("up_res_group", "") ?: ""
|
||||||
|
}
|
||||||
|
|
||||||
|
fun aliveReply(): Boolean {
|
||||||
|
return mmkv.getBoolean("alive_reply", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun allowTempSession(): Boolean {
|
||||||
|
return config.allowTempSession
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getGroupMsgRule(): GroupRule? {
|
||||||
|
return config.rules?.groupRule
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getPrivateRule(): PrivateRule? {
|
||||||
|
return config.rules?.privateRule
|
||||||
|
}
|
||||||
|
|
||||||
|
fun enableSyncMsgAsSentMsg(): Boolean {
|
||||||
|
return mmkv.getBoolean("enable_sync_msg_as_sent_msg", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun enableSelfMsg(): Boolean {
|
||||||
|
return mmkv.getBoolean("enable_self_msg", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun forbidUselessProcess(): Boolean {
|
||||||
|
return mmkv.getBoolean("forbid_useless_process", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun openWebSocketClient(): Boolean {
|
||||||
|
return mmkv.getBoolean("ws_client", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getWebSocketClientAddress(): List<ConnectionConfig> {
|
||||||
|
return config.passiveWebSocket ?: emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun openWebSocket(): Boolean {
|
||||||
|
return mmkv.getBoolean("ws", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getActiveWebSocketConfig(): ConnectionConfig? {
|
||||||
|
return config.activeWebSocket
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getToken(): String {
|
||||||
|
return config.defaultToken ?: ""
|
||||||
|
}
|
||||||
|
|
||||||
|
fun useCQ(): Boolean {
|
||||||
|
return mmkv.getBoolean("use_cqcode", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun allowWebHook(): Boolean {
|
||||||
|
return mmkv.getBoolean("http", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getWebHookAddress(): String {
|
||||||
|
return mmkv.getString("http_addr", "") ?: ""
|
||||||
|
}
|
||||||
|
|
||||||
|
fun forceTablet(): Boolean {
|
||||||
|
return mmkv.getBoolean("tablet", true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getPort(): Int {
|
||||||
|
return mmkv.getInt("port", 5700)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isInjectPacket(): Boolean {
|
||||||
|
return mmkv.getBoolean("inject_packet", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun enableOldBDH(): Boolean {
|
||||||
|
return mmkv.getBoolean("enable_old_bdh", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isDebug(): Boolean {
|
||||||
|
return mmkv.getBoolean("debug", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ssl(): Boolean {
|
||||||
|
return getKeyStorePath()?.exists() == true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getKeyStorePath(): File? {
|
||||||
|
mmkv.getString("key_store", null)?.let {
|
||||||
|
return File(it)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun sslPwd(): CharArray? {
|
||||||
|
return mmkv.getString("ssl_pwd", null)?.toCharArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun sslPrivatePwd(): String? {
|
||||||
|
return mmkv.getString("ssl_private_pwd", null)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun sslAlias(): String? {
|
||||||
|
return mmkv.getString("ssl_alias", null)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getSslPort(): Int {
|
||||||
|
return mmkv.getInt("ssl_port", getPort())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isDev(): Boolean {
|
||||||
|
return mmkv.getBoolean("dev", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun set(key: String, value: String) {
|
||||||
|
mmkv.putString(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun set(key: String, value: Boolean) {
|
||||||
|
mmkv.putBoolean(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun set(key: String, value: Int) {
|
||||||
|
mmkv.putInt(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun set(key: String, value: Long) {
|
||||||
|
mmkv.putLong(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun set(key: String, value: Float) {
|
||||||
|
mmkv.putFloat(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isAntiTrace(): Boolean {
|
||||||
|
return config.antiTrace
|
||||||
|
}
|
||||||
|
|
||||||
|
fun allowShell(): Boolean {
|
||||||
|
return mmkv.getBoolean("shell", false)
|
||||||
|
}
|
||||||
|
}
|
@ -27,18 +27,18 @@ internal data class SimpleTroopMemberInfo(
|
|||||||
@SerialName("user_name") val name: String,
|
@SerialName("user_name") val name: String,
|
||||||
@SerialName("sex") val sex: String,
|
@SerialName("sex") val sex: String,
|
||||||
@SerialName("age") val age: Int,
|
@SerialName("age") val age: Int,
|
||||||
@SerialName("title") val title: String,
|
@SerialName("title") var title: String?,
|
||||||
@SerialName("title_expire_time") val titleExpireTime: Int,
|
@SerialName("title_expire_time") var titleExpireTime: Int,
|
||||||
@SerialName("nickname") val nick: String,
|
@SerialName("nickname") val nick: String,
|
||||||
@SerialName("user_displayname") val showName: String?,
|
@SerialName("user_displayname") val showName: String?,
|
||||||
@SerialName("card") val cardName: String?,
|
@SerialName("card") val cardName: String?,
|
||||||
@SerialName("distance") val distance: Int,
|
@SerialName("distance") var distance: Int,
|
||||||
@SerialName("honor") val honor: List<Int>,
|
@SerialName("honor") val honor: List<Int>,
|
||||||
@SerialName("join_time") val joinTime: Long,
|
@SerialName("join_time") val joinTime: Long,
|
||||||
@SerialName("last_active_time") val lastActiveTime: Long,
|
@SerialName("last_active_time") val lastActiveTime: Long,
|
||||||
@SerialName("last_sent_time") val lastSentTime: Long,
|
@SerialName("last_sent_time") val lastSentTime: Long,
|
||||||
@SerialName("unique_name") val uniqueName: String?,
|
@SerialName("unique_name") var uniqueName: String?,
|
||||||
@SerialName("area") val area: String,
|
@SerialName("area") var area: String,
|
||||||
@SerialName("level") val level: Int,
|
@SerialName("level") val level: Int,
|
||||||
@SerialName("role") val role: MemberRole,
|
@SerialName("role") val role: MemberRole,
|
||||||
@SerialName("unfriendly") val unfriendly: Boolean,
|
@SerialName("unfriendly") val unfriendly: Boolean,
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user