mirror of
https://github.com/whitechi73/OpenShamrock.git
synced 2024-08-14 05:12:17 +00:00
Compare commits
26 Commits
cdc664f44a
...
1.1.1
Author | SHA1 | Date | |
---|---|---|---|
40d2911135 | |||
823d9911a0 | |||
4adbc12a0b | |||
114fbfdd23 | |||
0a563d60a1 | |||
5fb1d0aeb9 | |||
012ecaa85d | |||
7ea127a279 | |||
02f83a3c48 | |||
4016c05882 | |||
59d762eecf | |||
e891bc8512 | |||
494c70f2f8 | |||
7baf459b2a | |||
36a09ca088 | |||
926c4659f6 | |||
cb7c68f36c | |||
72af39208c | |||
042f4bd330 | |||
9aef71b09f | |||
9cbe755520 | |||
df02f9f872 | |||
5cbb695a66 | |||
c014e85faa | |||
4a396b0935 | |||
d59fcf9f6a |
@ -23,6 +23,8 @@
|
|||||||
> Riru可能导致封禁,请减少使用。
|
> Riru可能导致封禁,请减少使用。
|
||||||
> 如有违反法律,请联系删除。
|
> 如有违反法律,请联系删除。
|
||||||
> 请勿在任何平台宣传,宣扬,转发本项目,请勿恶意修改企业安装包造成相关企业产生损失,如有违背,必将追责到底。
|
> 请勿在任何平台宣传,宣扬,转发本项目,请勿恶意修改企业安装包造成相关企业产生损失,如有违背,必将追责到底。
|
||||||
|
>
|
||||||
|
> 社区地址:[discord](https://discord.gg/MKR2wz863h)
|
||||||
|
|
||||||
## 兼容|迁移|替代 说明
|
## 兼容|迁移|替代 说明
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ android {
|
|||||||
minSdk = 27
|
minSdk = 27
|
||||||
targetSdk = 34
|
targetSdk = 34
|
||||||
versionCode = getVersionCode()
|
versionCode = getVersionCode()
|
||||||
versionName = "1.1.0" + ".r${getGitCommitCount()}." + getVersionName()
|
versionName = "1.1.1" + ".r${getGitCommitCount()}." + getVersionName()
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
vectorDrawables {
|
vectorDrawables {
|
||||||
|
@ -162,7 +162,7 @@ private fun FunctionCard(
|
|||||||
|
|
||||||
Function(
|
Function(
|
||||||
title = "主动RPC",
|
title = "主动RPC",
|
||||||
desc = "Kritor协议实现RPC",
|
desc = "Kritor协议实现RPC,由Shamrock放出rpc服务",
|
||||||
isSwitch = ShamrockConfig[ctx, ActiveRPC]
|
isSwitch = ShamrockConfig[ctx, ActiveRPC]
|
||||||
) {
|
) {
|
||||||
ShamrockConfig[ctx, ActiveRPC] = it
|
ShamrockConfig[ctx, ActiveRPC] = it
|
||||||
@ -171,7 +171,7 @@ private fun FunctionCard(
|
|||||||
|
|
||||||
Function(
|
Function(
|
||||||
title = "被动RPC",
|
title = "被动RPC",
|
||||||
desc = "Kritor协议实现RPC",
|
desc = "Kritor协议实现RPC,由客户端提供反向的rpc服务",
|
||||||
isSwitch = ShamrockConfig[ctx, PassiveRPC]
|
isSwitch = ShamrockConfig[ctx, PassiveRPC]
|
||||||
) {
|
) {
|
||||||
ShamrockConfig[ctx, PassiveRPC] = it
|
ShamrockConfig[ctx, PassiveRPC] = it
|
||||||
|
@ -37,17 +37,18 @@ android {
|
|||||||
dependencies {
|
dependencies {
|
||||||
protobuf(files("kritor/protos"))
|
protobuf(files("kritor/protos"))
|
||||||
|
|
||||||
|
implementation("com.google.protobuf:protobuf-java:4.26.0")
|
||||||
|
|
||||||
implementation(kotlinx("coroutines-core", "1.8.0"))
|
implementation(kotlinx("coroutines-core", "1.8.0"))
|
||||||
implementation("com.google.protobuf:protobuf-java:3.25.3")
|
|
||||||
|
|
||||||
implementation(grpc("stub", "1.62.2"))
|
implementation(grpc("stub", "1.62.2"))
|
||||||
implementation(grpc("kotlin-stub", "1.4.1"))
|
|
||||||
implementation(grpc("protobuf", "1.62.2"))
|
implementation(grpc("protobuf", "1.62.2"))
|
||||||
|
implementation(grpc("kotlin-stub", "1.4.1"))
|
||||||
}
|
}
|
||||||
|
|
||||||
protobuf {
|
protobuf {
|
||||||
protoc {
|
protoc {
|
||||||
artifact = "com.google.protobuf:protoc:3.25.3"
|
artifact = "com.google.protobuf:protoc:4.26.0"
|
||||||
}
|
}
|
||||||
plugins {
|
plugins {
|
||||||
create("grpc") {
|
create("grpc") {
|
||||||
|
Submodule kritor/kritor updated: 94f2e74b79...3dec747a8e
@ -5,22 +5,9 @@ package moe.fuqiuluo.ksp.impl
|
|||||||
|
|
||||||
import com.google.devtools.ksp.KspExperimental
|
import com.google.devtools.ksp.KspExperimental
|
||||||
import com.google.devtools.ksp.getAnnotationsByType
|
import com.google.devtools.ksp.getAnnotationsByType
|
||||||
import com.google.devtools.ksp.getClassDeclarationByName
|
import com.google.devtools.ksp.processing.*
|
||||||
import com.google.devtools.ksp.getJavaClassByName
|
|
||||||
import com.google.devtools.ksp.getKotlinClassByName
|
|
||||||
import com.google.devtools.ksp.processing.CodeGenerator
|
|
||||||
import com.google.devtools.ksp.processing.Dependencies
|
|
||||||
import com.google.devtools.ksp.processing.KSPLogger
|
|
||||||
import com.google.devtools.ksp.processing.Resolver
|
|
||||||
import com.google.devtools.ksp.processing.SymbolProcessor
|
|
||||||
import com.google.devtools.ksp.symbol.KSAnnotated
|
import com.google.devtools.ksp.symbol.KSAnnotated
|
||||||
import com.google.devtools.ksp.symbol.KSClassDeclaration
|
|
||||||
import com.google.devtools.ksp.symbol.KSDeclaration
|
|
||||||
import com.google.devtools.ksp.symbol.KSFunctionDeclaration
|
import com.google.devtools.ksp.symbol.KSFunctionDeclaration
|
||||||
import com.google.devtools.ksp.symbol.KSType
|
|
||||||
import com.google.devtools.ksp.symbol.KSTypeParameter
|
|
||||||
import com.google.devtools.ksp.symbol.Modifier
|
|
||||||
import com.google.devtools.ksp.validate
|
|
||||||
import com.squareup.kotlinpoet.FileSpec
|
import com.squareup.kotlinpoet.FileSpec
|
||||||
import com.squareup.kotlinpoet.FunSpec
|
import com.squareup.kotlinpoet.FunSpec
|
||||||
import com.squareup.kotlinpoet.KModifier
|
import com.squareup.kotlinpoet.KModifier
|
||||||
@ -67,15 +54,16 @@ class GrpcProcessor(
|
|||||||
}
|
}
|
||||||
funcBuilder.addStatement("return EMPTY_BYTE_ARRAY")
|
funcBuilder.addStatement("return EMPTY_BYTE_ARRAY")
|
||||||
fileSpec
|
fileSpec
|
||||||
.addStatement("import io.kritor.*")
|
.addStatement("import io.kritor.authentication.*")
|
||||||
.addStatement("import io.kritor.core.*")
|
.addStatement("import io.kritor.core.*")
|
||||||
.addStatement("import io.kritor.contact.*")
|
.addStatement("import io.kritor.customization.*")
|
||||||
.addStatement("import io.kritor.group.*")
|
.addStatement("import io.kritor.developer.*")
|
||||||
.addStatement("import io.kritor.friend.*")
|
|
||||||
.addStatement("import io.kritor.file.*")
|
.addStatement("import io.kritor.file.*")
|
||||||
|
.addStatement("import io.kritor.friend.*")
|
||||||
|
.addStatement("import io.kritor.group.*")
|
||||||
|
.addStatement("import io.kritor.guild.*")
|
||||||
.addStatement("import io.kritor.message.*")
|
.addStatement("import io.kritor.message.*")
|
||||||
.addStatement("import io.kritor.web.*")
|
.addStatement("import io.kritor.web.*")
|
||||||
.addStatement("import io.kritor.developer.*")
|
|
||||||
.addFunction(funcBuilder.build())
|
.addFunction(funcBuilder.build())
|
||||||
.addImport("moe.fuqiuluo.symbols", "EMPTY_BYTE_ARRAY")
|
.addImport("moe.fuqiuluo.symbols", "EMPTY_BYTE_ARRAY")
|
||||||
runCatching {
|
runCatching {
|
||||||
|
@ -8,7 +8,9 @@ import moe.fuqiuluo.symbols.Protobuf
|
|||||||
data class TrpcOidb(
|
data class TrpcOidb(
|
||||||
@ProtoNumber(1) val cmd: Int = Int.MIN_VALUE,
|
@ProtoNumber(1) val cmd: Int = Int.MIN_VALUE,
|
||||||
@ProtoNumber(2) val service: Int = Int.MIN_VALUE,
|
@ProtoNumber(2) val service: Int = Int.MIN_VALUE,
|
||||||
@ProtoNumber(4) val buffer: ByteArray,
|
@ProtoNumber(3) val result: UInt? = null,
|
||||||
|
@ProtoNumber(4) val buffer: ByteArray? = null,
|
||||||
|
@ProtoNumber(5) val msg: String? = null,
|
||||||
//@ProtoNumber(11) val traceParams: Map<String, String> = mapOf(),
|
//@ProtoNumber(11) val traceParams: Map<String, String> = mapOf(),
|
||||||
@ProtoNumber(12) val flag: Int = Int.MIN_VALUE,
|
@ProtoNumber(12) val flag: Int = Int.MIN_VALUE,
|
||||||
): Protobuf<TrpcOidb>
|
): Protobuf<TrpcOidb>
|
@ -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,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,7 +1,7 @@
|
|||||||
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.kernelpublic.nativeinterface.Contact;
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.IOperateCallback;
|
import com.tencent.qqnt.kernel.nativeinterface.IOperateCallback;
|
||||||
|
|
||||||
public interface IAIOFileTransfer extends QRouteApi {
|
public interface IAIOFileTransfer extends QRouteApi {
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
package com.tencent.qqnt.kernel.nativeinterface;
|
||||||
|
|
||||||
|
public class GProGuildTopFeedMsg {
|
||||||
|
}
|
@ -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 + ",}";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
@ -16,7 +18,7 @@ public interface IKernelMsgListener {
|
|||||||
|
|
||||||
void onCustomWithdrawConfigUpdate(CustomWithdrawConfig customWithdrawConfig);
|
void onCustomWithdrawConfigUpdate(CustomWithdrawConfig customWithdrawConfig);
|
||||||
|
|
||||||
void onDraftUpdate(Contact contact, ArrayList<MsgElement> arrayList, long j2);
|
void onDraftUpdate(Contact contact, ArrayList<MsgElement> arrayList, long j);
|
||||||
|
|
||||||
void onEmojiDownloadComplete(EmojiNotifyInfo emojiNotifyInfo);
|
void onEmojiDownloadComplete(EmojiNotifyInfo emojiNotifyInfo);
|
||||||
|
|
||||||
@ -30,7 +32,7 @@ public interface IKernelMsgListener {
|
|||||||
|
|
||||||
void onFirstViewGroupGuildMapping(ArrayList<FirstViewGroupGuildInfo> arrayList);
|
void onFirstViewGroupGuildMapping(ArrayList<FirstViewGroupGuildInfo> arrayList);
|
||||||
|
|
||||||
void onGrabPasswordRedBag(int i2, String str, int i3, RecvdOrder recvdOrder, MsgRecord msgRecord);
|
void onGrabPasswordRedBag(int i, String str, int i2, RecvdOrder recvdOrder, MsgRecord msgRecord);
|
||||||
|
|
||||||
void onGroupFileInfoAdd(GroupItem groupItem);
|
void onGroupFileInfoAdd(GroupItem groupItem);
|
||||||
|
|
||||||
@ -48,6 +50,8 @@ public interface IKernelMsgListener {
|
|||||||
|
|
||||||
void onGuildNotificationAbstractUpdate(GuildNotificationAbstractInfo guildNotificationAbstractInfo);
|
void onGuildNotificationAbstractUpdate(GuildNotificationAbstractInfo guildNotificationAbstractInfo);
|
||||||
|
|
||||||
|
void onGuildTopFeedUpdate(GProGuildTopFeedMsg gProGuildTopFeedMsg);
|
||||||
|
|
||||||
void onHitCsRelatedEmojiResult(DownloadRelateEmojiResultInfo downloadRelateEmojiResultInfo);
|
void onHitCsRelatedEmojiResult(DownloadRelateEmojiResultInfo downloadRelateEmojiResultInfo);
|
||||||
|
|
||||||
void onHitEmojiKeywordResult(HitRelatedEmojiWordsResult hitRelatedEmojiWordsResult);
|
void onHitEmojiKeywordResult(HitRelatedEmojiWordsResult hitRelatedEmojiWordsResult);
|
||||||
@ -62,7 +66,7 @@ public interface IKernelMsgListener {
|
|||||||
|
|
||||||
void onLineDev(ArrayList<DevInfo> arrayList);
|
void onLineDev(ArrayList<DevInfo> arrayList);
|
||||||
|
|
||||||
void onLogLevelChanged(long j2);
|
void onLogLevelChanged(long j);
|
||||||
|
|
||||||
void onMsgAbstractUpdate(ArrayList<MsgAbstract> arrayList);
|
void onMsgAbstractUpdate(ArrayList<MsgAbstract> arrayList);
|
||||||
|
|
||||||
@ -76,14 +80,16 @@ public interface IKernelMsgListener {
|
|||||||
|
|
||||||
void onMsgInfoListUpdate(ArrayList<MsgRecord> arrayList);
|
void onMsgInfoListUpdate(ArrayList<MsgRecord> arrayList);
|
||||||
|
|
||||||
void onMsgQRCodeStatusChanged(int i2);
|
void onMsgQRCodeStatusChanged(int i);
|
||||||
|
|
||||||
void onMsgRecall(int i2, String str, long j2);
|
void onMsgRecall(int i, String str, long j);
|
||||||
|
|
||||||
void onMsgSecurityNotify(MsgRecord msgRecord);
|
void onMsgSecurityNotify(MsgRecord msgRecord);
|
||||||
|
|
||||||
void onMsgSettingUpdate(MsgSetting msgSetting);
|
void onMsgSettingUpdate(MsgSetting msgSetting);
|
||||||
|
|
||||||
|
void onMsgWithRichLinkInfoUpdate(ArrayList<MsgRecord> arrayList);
|
||||||
|
|
||||||
void onNtFirstViewMsgSyncEnd();
|
void onNtFirstViewMsgSyncEnd();
|
||||||
|
|
||||||
void onNtMsgSyncEnd();
|
void onNtMsgSyncEnd();
|
||||||
@ -92,11 +98,11 @@ public interface IKernelMsgListener {
|
|||||||
|
|
||||||
void onReadFeedEventUpdate(FirstViewDirectMsgNotifyInfo firstViewDirectMsgNotifyInfo);
|
void onReadFeedEventUpdate(FirstViewDirectMsgNotifyInfo firstViewDirectMsgNotifyInfo);
|
||||||
|
|
||||||
void onRecvGroupGuildFlag(int i2);
|
void onRecvGroupGuildFlag(int i);
|
||||||
|
|
||||||
void onRecvMsg(ArrayList<MsgRecord> arrayList);
|
void onRecvMsg(ArrayList<MsgRecord> arrayList);
|
||||||
|
|
||||||
void onRecvMsgSvrRspTransInfo(long j2, Contact contact, int i2, int i3, String str, byte[] bArr);
|
void onRecvMsgSvrRspTransInfo(long j, Contact contact, int i, int i2, String str, byte[] bArr);
|
||||||
|
|
||||||
void onRecvOnlineFileMsg(ArrayList<MsgRecord> arrayList);
|
void onRecvOnlineFileMsg(ArrayList<MsgRecord> arrayList);
|
||||||
|
|
||||||
@ -104,7 +110,9 @@ public interface IKernelMsgListener {
|
|||||||
|
|
||||||
void onRecvSysMsg(ArrayList<Byte> arrayList);
|
void onRecvSysMsg(ArrayList<Byte> arrayList);
|
||||||
|
|
||||||
void onRecvUDCFlag(int i2);
|
void onRecvUDCFlag(int i);
|
||||||
|
|
||||||
|
void onRedTouchChanged();
|
||||||
|
|
||||||
void onRichMediaDownloadComplete(FileTransNotifyInfo fileTransNotifyInfo);
|
void onRichMediaDownloadComplete(FileTransNotifyInfo fileTransNotifyInfo);
|
||||||
|
|
||||||
@ -114,9 +122,9 @@ public interface IKernelMsgListener {
|
|||||||
|
|
||||||
void onSearchGroupFileInfoUpdate(SearchGroupFileResult searchGroupFileResult);
|
void onSearchGroupFileInfoUpdate(SearchGroupFileResult searchGroupFileResult);
|
||||||
|
|
||||||
void onSendMsgError(long j2, Contact contact, int i2, String str);
|
void onSendMsgError(long j, Contact contact, int i, String str);
|
||||||
|
|
||||||
void onSysMsgNotification(int i2, long j2, long j3, ArrayList<Byte> arrayList);
|
void onSysMsgNotification(int i, long j, long j2, boolean z, ArrayList<Byte> arrayList);
|
||||||
|
|
||||||
void onTempChatInfoUpdate(TempChatInfo tempChatInfo);
|
void onTempChatInfoUpdate(TempChatInfo tempChatInfo);
|
||||||
|
|
||||||
@ -128,9 +136,11 @@ public interface IKernelMsgListener {
|
|||||||
|
|
||||||
void onUserOnlineStatusChanged(boolean z);
|
void onUserOnlineStatusChanged(boolean z);
|
||||||
|
|
||||||
|
void onUserSecQualityChanged(QueryUserSecQualityRsp queryUserSecQualityRsp);
|
||||||
|
|
||||||
void onUserTabStatusChanged(ArrayList<TabStatusInfo> arrayList);
|
void onUserTabStatusChanged(ArrayList<TabStatusInfo> arrayList);
|
||||||
|
|
||||||
void onlineStatusBigIconDownloadPush(int i2, long j2, String str);
|
void onlineStatusBigIconDownloadPush(int i, long j, String str);
|
||||||
|
|
||||||
void onlineStatusSmallIconDownloadPush(int i2, long j2, String str);
|
void onlineStatusSmallIconDownloadPush(int i, long j, String str);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
package com.tencent.qqnt.kernel.nativeinterface;
|
||||||
|
|
||||||
|
public class QueryUserSecQualityRsp {
|
||||||
|
}
|
@ -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;
|
||||||
|
|
@ -0,0 +1,9 @@
|
|||||||
|
package com.tencent.qqnt.kernelpublic.nativeinterface;
|
||||||
|
|
||||||
|
public enum MemberRole {
|
||||||
|
UNSPECIFIED,
|
||||||
|
STRANGER,
|
||||||
|
MEMBER,
|
||||||
|
ADMIN,
|
||||||
|
OWNER
|
||||||
|
}
|
@ -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;
|
||||||
@ -9,7 +10,6 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
import kotlin.Pair;
|
|
||||||
import kotlinx.coroutines.flow.Flow;
|
import kotlinx.coroutines.flow.Flow;
|
||||||
|
|
||||||
public interface IMsgService extends QRouteApi {
|
public interface IMsgService extends QRouteApi {
|
||||||
|
@ -2,13 +2,21 @@
|
|||||||
package kritor.client
|
package kritor.client
|
||||||
|
|
||||||
import com.google.protobuf.ByteString
|
import com.google.protobuf.ByteString
|
||||||
|
import io.grpc.CallOptions
|
||||||
|
import io.grpc.Channel
|
||||||
|
import io.grpc.ClientCall
|
||||||
|
import io.grpc.ClientInterceptor
|
||||||
|
import io.grpc.ForwardingClientCall
|
||||||
|
import io.grpc.Metadata
|
||||||
import io.grpc.ManagedChannel
|
import io.grpc.ManagedChannel
|
||||||
import io.grpc.ManagedChannelBuilder
|
import io.grpc.ManagedChannelBuilder
|
||||||
import io.kritor.ReverseServiceGrpcKt
|
import io.grpc.MethodDescriptor
|
||||||
import io.kritor.event.*
|
import io.kritor.common.Request
|
||||||
import io.kritor.reverse.ReqCode
|
import io.kritor.common.Response
|
||||||
import io.kritor.reverse.Request
|
import io.kritor.event.EventServiceGrpcKt
|
||||||
import io.kritor.reverse.Response
|
import io.kritor.event.EventStructure
|
||||||
|
import io.kritor.event.EventType
|
||||||
|
import io.kritor.reverse.ReverseServiceGrpcKt
|
||||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
@ -22,6 +30,8 @@ import kritor.handlers.handleGrpc
|
|||||||
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.internals.GlobalEventTransmitter
|
import moe.fuqiuluo.shamrock.internals.GlobalEventTransmitter
|
||||||
|
import moe.fuqiuluo.shamrock.tools.ShamrockVersion
|
||||||
|
import qq.service.ticket.TicketHelper
|
||||||
import kotlin.time.Duration.Companion.seconds
|
import kotlin.time.Duration.Companion.seconds
|
||||||
|
|
||||||
internal class KritorClient(
|
internal class KritorClient(
|
||||||
@ -38,11 +48,26 @@ internal class KritorClient(
|
|||||||
if (::channel.isInitialized && isActive()){
|
if (::channel.isInitialized && isActive()){
|
||||||
channel.shutdown()
|
channel.shutdown()
|
||||||
}
|
}
|
||||||
|
val interceptor = object : ClientInterceptor {
|
||||||
|
override fun <ReqT, RespT> interceptCall(method: MethodDescriptor<ReqT, RespT>, callOptions: CallOptions, next: Channel): ClientCall<ReqT, RespT> {
|
||||||
|
return object : ForwardingClientCall.SimpleForwardingClientCall<ReqT, RespT>(next.newCall(method, callOptions)) {
|
||||||
|
override fun start(responseListener: Listener<RespT>, headers: Metadata) {
|
||||||
|
headers.merge(Metadata().apply {
|
||||||
|
put(Metadata.Key.of("kritor-self-uin", Metadata.ASCII_STRING_MARSHALLER), TicketHelper.getUin())
|
||||||
|
put(Metadata.Key.of("kritor-self-uid", Metadata.ASCII_STRING_MARSHALLER), TicketHelper.getUid())
|
||||||
|
put(Metadata.Key.of("kritor-self-version", Metadata.ASCII_STRING_MARSHALLER), "OpenShamrock-$ShamrockVersion")
|
||||||
|
})
|
||||||
|
super.start(responseListener, headers)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
channel = ManagedChannelBuilder
|
channel = ManagedChannelBuilder
|
||||||
.forAddress(host, port)
|
.forAddress(host, port)
|
||||||
.usePlaintext()
|
.usePlaintext()
|
||||||
.enableRetry() // 允许尝试
|
.enableRetry() // 允许尝试
|
||||||
.executor(Dispatchers.IO.asExecutor()) // 使用协程的调度器
|
.executor(Dispatchers.IO.asExecutor()) // 使用协程的调度器
|
||||||
|
.intercept(interceptor)
|
||||||
.build()
|
.build()
|
||||||
}.onFailure {
|
}.onFailure {
|
||||||
LogCenter.log("KritorClient start failed: ${it.stackTraceToString()}", Level.ERROR)
|
LogCenter.log("KritorClient start failed: ${it.stackTraceToString()}", Level.ERROR)
|
||||||
@ -113,7 +138,7 @@ internal class KritorClient(
|
|||||||
val rsp = handleGrpc(request.cmd, request.buf.toByteArray())
|
val rsp = handleGrpc(request.cmd, request.buf.toByteArray())
|
||||||
senderChannel.emit(Response.newBuilder()
|
senderChannel.emit(Response.newBuilder()
|
||||||
.setCmd(request.cmd)
|
.setCmd(request.cmd)
|
||||||
.setCode(ReqCode.SUCCESS)
|
.setCode(Response.ResponseCode.SUCCESS)
|
||||||
.setMsg("success")
|
.setMsg("success")
|
||||||
.setSeq(request.seq)
|
.setSeq(request.seq)
|
||||||
.setBuf(ByteString.copyFrom(rsp))
|
.setBuf(ByteString.copyFrom(rsp))
|
||||||
@ -121,7 +146,7 @@ internal class KritorClient(
|
|||||||
}.onFailure {
|
}.onFailure {
|
||||||
senderChannel.emit(Response.newBuilder()
|
senderChannel.emit(Response.newBuilder()
|
||||||
.setCmd(request.cmd)
|
.setCmd(request.cmd)
|
||||||
.setCode(ReqCode.INTERNAL)
|
.setCode(Response.ResponseCode.INTERNAL)
|
||||||
.setMsg(it.stackTraceToString())
|
.setMsg(it.stackTraceToString())
|
||||||
.setSeq(request.seq)
|
.setSeq(request.seq)
|
||||||
.setBuf(ByteString.EMPTY)
|
.setBuf(ByteString.EMPTY)
|
||||||
|
@ -2,7 +2,12 @@
|
|||||||
package kritor.server
|
package kritor.server
|
||||||
|
|
||||||
import io.grpc.Grpc
|
import io.grpc.Grpc
|
||||||
|
import io.grpc.Metadata
|
||||||
import io.grpc.InsecureServerCredentials
|
import io.grpc.InsecureServerCredentials
|
||||||
|
import io.grpc.ServerCall
|
||||||
|
import io.grpc.ServerCallHandler
|
||||||
|
import io.grpc.ServerInterceptor
|
||||||
|
import io.grpc.ForwardingServerCall.SimpleForwardingServerCall;
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
@ -10,25 +15,45 @@ import kotlinx.coroutines.asExecutor
|
|||||||
import kritor.auth.AuthInterceptor
|
import kritor.auth.AuthInterceptor
|
||||||
import kritor.service.*
|
import kritor.service.*
|
||||||
import moe.fuqiuluo.shamrock.helper.LogCenter
|
import moe.fuqiuluo.shamrock.helper.LogCenter
|
||||||
|
import moe.fuqiuluo.shamrock.tools.ShamrockVersion
|
||||||
|
import qq.service.ticket.TicketHelper
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
|
||||||
class KritorServer(
|
class KritorServer(
|
||||||
private val port: Int
|
private val port: Int
|
||||||
): CoroutineScope {
|
): CoroutineScope {
|
||||||
|
|
||||||
|
private val serverInterceptor = object : ServerInterceptor {
|
||||||
|
override fun <ReqT, RespT> interceptCall(
|
||||||
|
call: ServerCall<ReqT, RespT>, headers: Metadata, next: ServerCallHandler<ReqT, RespT>
|
||||||
|
): ServerCall.Listener<ReqT> {
|
||||||
|
return next.startCall(object : SimpleForwardingServerCall<ReqT, RespT>(call) {
|
||||||
|
override fun sendHeaders(headers: Metadata?) {
|
||||||
|
headers?.apply {
|
||||||
|
put(Metadata.Key.of("kritor-self-uin", Metadata.ASCII_STRING_MARSHALLER), TicketHelper.getUin())
|
||||||
|
put(Metadata.Key.of("kritor-self-uid", Metadata.ASCII_STRING_MARSHALLER), TicketHelper.getUid())
|
||||||
|
put(Metadata.Key.of("kritor-self-version", Metadata.ASCII_STRING_MARSHALLER), "OpenShamrock-$ShamrockVersion")
|
||||||
|
}
|
||||||
|
super.sendHeaders(headers)
|
||||||
|
}
|
||||||
|
}, headers)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private val server = Grpc.newServerBuilderForPort(port, InsecureServerCredentials.create())
|
private val server = Grpc.newServerBuilderForPort(port, InsecureServerCredentials.create())
|
||||||
.executor(Dispatchers.IO.asExecutor())
|
.executor(Dispatchers.IO.asExecutor())
|
||||||
.intercept(AuthInterceptor)
|
.intercept(AuthInterceptor)
|
||||||
.addService(Authentication)
|
.intercept(serverInterceptor)
|
||||||
.addService(ContactService)
|
.addService(AuthenticationService)
|
||||||
.addService(KritorService)
|
.addService(CoreService)
|
||||||
.addService(FriendService)
|
.addService(FriendService)
|
||||||
.addService(GroupService)
|
.addService(GroupService)
|
||||||
.addService(GroupFileService)
|
.addService(GroupFileService)
|
||||||
.addService(MessageService)
|
.addService(MessageService)
|
||||||
.addService(EventService)
|
.addService(EventService)
|
||||||
.addService(ForwardMessageService)
|
|
||||||
.addService(WebService)
|
.addService(WebService)
|
||||||
.addService(DeveloperService)
|
.addService(DeveloperService)
|
||||||
|
.addService(QsignService)
|
||||||
.build()!!
|
.build()!!
|
||||||
|
|
||||||
fun start(block: Boolean = false) {
|
fun start(block: Boolean = false) {
|
||||||
|
@ -2,23 +2,19 @@ package kritor.service
|
|||||||
|
|
||||||
import io.grpc.Status
|
import io.grpc.Status
|
||||||
import io.grpc.StatusRuntimeException
|
import io.grpc.StatusRuntimeException
|
||||||
import io.kritor.AuthCode
|
import io.kritor.authentication.*
|
||||||
import io.kritor.AuthReq
|
import io.kritor.authentication.AuthenticateResponse.AuthenticateResponseCode
|
||||||
import io.kritor.AuthRsp
|
|
||||||
import io.kritor.AuthenticationGrpcKt
|
|
||||||
import io.kritor.GetAuthStateReq
|
|
||||||
import io.kritor.GetAuthStateRsp
|
|
||||||
import kritor.auth.AuthInterceptor
|
import kritor.auth.AuthInterceptor
|
||||||
import moe.fuqiuluo.shamrock.config.ActiveTicket
|
import moe.fuqiuluo.shamrock.config.ActiveTicket
|
||||||
import moe.fuqiuluo.shamrock.config.ShamrockConfig
|
import moe.fuqiuluo.shamrock.config.ShamrockConfig
|
||||||
import qq.service.QQInterfaces
|
import qq.service.QQInterfaces
|
||||||
|
|
||||||
internal object Authentication: AuthenticationGrpcKt.AuthenticationCoroutineImplBase() {
|
internal object AuthenticationService: AuthenticationServiceGrpcKt.AuthenticationServiceCoroutineImplBase() {
|
||||||
@Grpc("Authentication", "Auth")
|
@Grpc("AuthenticationService", "Authenticate")
|
||||||
override suspend fun auth(request: AuthReq): AuthRsp {
|
override suspend fun authenticate(request: AuthenticateRequest): AuthenticateResponse {
|
||||||
if (QQInterfaces.app.account != request.account) {
|
if (QQInterfaces.app.account != request.account) {
|
||||||
return AuthRsp.newBuilder().apply {
|
return AuthenticateResponse.newBuilder().apply {
|
||||||
code = AuthCode.NO_ACCOUNT
|
code = AuthenticateResponseCode.NO_ACCOUNT
|
||||||
msg = "No such account"
|
msg = "No such account"
|
||||||
}.build()
|
}.build()
|
||||||
}
|
}
|
||||||
@ -29,36 +25,36 @@ internal object Authentication: AuthenticationGrpcKt.AuthenticationCoroutineImpl
|
|||||||
val ticket = ShamrockConfig.getProperty(activeTicketName + if (index == 0) "" else ".$index", null)
|
val ticket = ShamrockConfig.getProperty(activeTicketName + if (index == 0) "" else ".$index", null)
|
||||||
if (ticket.isNullOrEmpty()) {
|
if (ticket.isNullOrEmpty()) {
|
||||||
if (index == 0) {
|
if (index == 0) {
|
||||||
return AuthRsp.newBuilder().apply {
|
return AuthenticateResponse.newBuilder().apply {
|
||||||
code = AuthCode.OK
|
code = AuthenticateResponseCode.OK
|
||||||
msg = "OK"
|
msg = "OK"
|
||||||
}.build()
|
}.build()
|
||||||
} else {
|
} else {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
} else if (ticket == request.ticket) {
|
} else if (ticket == request.ticket) {
|
||||||
return AuthRsp.newBuilder().apply {
|
return AuthenticateResponse.newBuilder().apply {
|
||||||
code = AuthCode.OK
|
code = AuthenticateResponseCode.OK
|
||||||
msg = "OK"
|
msg = "OK"
|
||||||
}.build()
|
}.build()
|
||||||
}
|
}
|
||||||
index++
|
index++
|
||||||
}
|
}
|
||||||
|
|
||||||
return AuthRsp.newBuilder().apply {
|
return AuthenticateResponse.newBuilder().apply {
|
||||||
code = AuthCode.NO_TICKET
|
code = AuthenticateResponseCode.NO_TICKET
|
||||||
msg = "Invalid ticket"
|
msg = "Invalid ticket"
|
||||||
}.build()
|
}.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Grpc("Authentication", "GetAuthState")
|
@Grpc("AuthenticationService", "GetAuthenticationState")
|
||||||
override suspend fun getAuthState(request: GetAuthStateReq): GetAuthStateRsp {
|
override suspend fun getAuthenticationState(request: GetAuthenticationStateRequest): GetAuthenticationStateResponse {
|
||||||
if (request.account != QQInterfaces.app.account) {
|
if (request.account != QQInterfaces.app.account) {
|
||||||
throw StatusRuntimeException(Status.CANCELLED.withDescription("No such account"))
|
throw StatusRuntimeException(Status.CANCELLED.withDescription("No such account"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetAuthStateRsp.newBuilder().apply {
|
return GetAuthenticationStateResponse.newBuilder().apply {
|
||||||
isRequiredAuth = AuthInterceptor.getAllTicket().isNotEmpty()
|
isRequired = AuthInterceptor.getAllTicket().isNotEmpty()
|
||||||
}.build()
|
}.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,187 +0,0 @@
|
|||||||
package kritor.service
|
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import com.tencent.mobileqq.profilecard.api.IProfileCardBlacklistApi
|
|
||||||
import com.tencent.mobileqq.profilecard.api.IProfileProtocolConst.*
|
|
||||||
import com.tencent.mobileqq.profilecard.api.IProfileProtocolService
|
|
||||||
import com.tencent.mobileqq.qroute.QRoute
|
|
||||||
import io.grpc.Status
|
|
||||||
import io.grpc.StatusRuntimeException
|
|
||||||
import io.kritor.contact.ContactServiceGrpcKt
|
|
||||||
import io.kritor.contact.GetUidRequest
|
|
||||||
import io.kritor.contact.GetUidResponse
|
|
||||||
import io.kritor.contact.GetUinByUidRequest
|
|
||||||
import io.kritor.contact.GetUinByUidResponse
|
|
||||||
import io.kritor.contact.IsBlackListUserRequest
|
|
||||||
import io.kritor.contact.IsBlackListUserResponse
|
|
||||||
import io.kritor.contact.ProfileCard
|
|
||||||
import io.kritor.contact.ProfileCardRequest
|
|
||||||
import io.kritor.contact.SetProfileCardRequest
|
|
||||||
import io.kritor.contact.SetProfileCardResponse
|
|
||||||
import io.kritor.contact.StrangerExt
|
|
||||||
import io.kritor.contact.StrangerInfo
|
|
||||||
import io.kritor.contact.StrangerInfoRequest
|
|
||||||
import io.kritor.contact.VoteUserRequest
|
|
||||||
import io.kritor.contact.VoteUserResponse
|
|
||||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
|
||||||
import kotlinx.coroutines.withTimeoutOrNull
|
|
||||||
import qq.service.QQInterfaces
|
|
||||||
import qq.service.contact.ContactHelper
|
|
||||||
import kotlin.coroutines.resume
|
|
||||||
|
|
||||||
internal object ContactService : ContactServiceGrpcKt.ContactServiceCoroutineImplBase() {
|
|
||||||
@Grpc("ContactService", "VoteUser")
|
|
||||||
override suspend fun voteUser(request: VoteUserRequest): VoteUserResponse {
|
|
||||||
ContactHelper.voteUser(
|
|
||||||
when (request.accountCase!!) {
|
|
||||||
VoteUserRequest.AccountCase.ACCOUNT_UIN -> request.accountUin
|
|
||||||
VoteUserRequest.AccountCase.ACCOUNT_UID -> ContactHelper.getUinByUidAsync(request.accountUid).toLong()
|
|
||||||
VoteUserRequest.AccountCase.ACCOUNT_NOT_SET -> throw StatusRuntimeException(
|
|
||||||
Status.INVALID_ARGUMENT
|
|
||||||
.withDescription("account not set")
|
|
||||||
)
|
|
||||||
}, request.voteCount
|
|
||||||
).onFailure {
|
|
||||||
throw StatusRuntimeException(
|
|
||||||
Status.INTERNAL
|
|
||||||
.withDescription(it.stackTraceToString())
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return VoteUserResponse.newBuilder().build()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Grpc("ContactService", "GetProfileCard")
|
|
||||||
override suspend fun getProfileCard(request: ProfileCardRequest): ProfileCard {
|
|
||||||
val uin = when (request.accountCase!!) {
|
|
||||||
ProfileCardRequest.AccountCase.ACCOUNT_UIN -> request.accountUin
|
|
||||||
ProfileCardRequest.AccountCase.ACCOUNT_UID -> ContactHelper.getUinByUidAsync(request.accountUid).toLong()
|
|
||||||
ProfileCardRequest.AccountCase.ACCOUNT_NOT_SET -> throw StatusRuntimeException(
|
|
||||||
Status.INVALID_ARGUMENT
|
|
||||||
.withDescription("account not set")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val contact = ContactHelper.getProfileCard(uin)
|
|
||||||
|
|
||||||
contact.onFailure {
|
|
||||||
throw StatusRuntimeException(
|
|
||||||
Status.INTERNAL
|
|
||||||
.withDescription(it.stackTraceToString())
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
contact.onSuccess {
|
|
||||||
return ProfileCard.newBuilder().apply {
|
|
||||||
this.uin = it.uin.toLong()
|
|
||||||
this.uid = if (request.hasAccountUid()) request.accountUid
|
|
||||||
else ContactHelper.getUidByUinAsync(it.uin.toLong())
|
|
||||||
this.name = it.strNick ?: ""
|
|
||||||
this.remark = it.strReMark ?: ""
|
|
||||||
this.level = it.iQQLevel
|
|
||||||
this.birthday = it.lBirthday
|
|
||||||
this.loginDay = it.lLoginDays.toInt()
|
|
||||||
this.voteCnt = it.lVoteCount.toInt()
|
|
||||||
this.qid = it.qid ?: ""
|
|
||||||
this.isSchoolVerified = it.schoolVerifiedFlag
|
|
||||||
}.build()
|
|
||||||
}
|
|
||||||
|
|
||||||
throw StatusRuntimeException(
|
|
||||||
Status.INTERNAL
|
|
||||||
.withDescription("logic failed")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Grpc("ContactService", "GetStrangerInfo")
|
|
||||||
override suspend fun getStrangerInfo(request: StrangerInfoRequest): StrangerInfo {
|
|
||||||
val userId = request.uin
|
|
||||||
val info = ContactHelper.refreshAndGetProfileCard(userId).onFailure {
|
|
||||||
throw StatusRuntimeException(
|
|
||||||
Status.INTERNAL
|
|
||||||
.withCause(it)
|
|
||||||
.withDescription("Unable to fetch stranger info")
|
|
||||||
)
|
|
||||||
}.getOrThrow()
|
|
||||||
|
|
||||||
return StrangerInfo.newBuilder().apply {
|
|
||||||
this.uid = ContactHelper.getUidByUinAsync(userId)
|
|
||||||
this.uin = (info.uin ?: "0").toLong()
|
|
||||||
this.name = info.strNick ?: ""
|
|
||||||
this.level = info.iQQLevel
|
|
||||||
this.loginDay = info.lLoginDays.toInt()
|
|
||||||
this.voteCnt = info.lVoteCount.toInt()
|
|
||||||
this.qid = info.qid ?: ""
|
|
||||||
this.isSchoolVerified = info.schoolVerifiedFlag
|
|
||||||
this.ext = StrangerExt.newBuilder().apply {
|
|
||||||
this.bigVip = info.bBigClubVipOpen == 1.toByte()
|
|
||||||
this.hollywoodVip = info.bHollywoodVipOpen == 1.toByte()
|
|
||||||
this.qqVip = info.bQQVipOpen == 1.toByte()
|
|
||||||
this.superVip = info.bSuperQQOpen == 1.toByte()
|
|
||||||
this.voted = info.bVoted == 1.toByte()
|
|
||||||
}.build().toByteString()
|
|
||||||
}.build()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Grpc("ContactService", "GetUid")
|
|
||||||
override suspend fun getUid(request: GetUidRequest): GetUidResponse {
|
|
||||||
return GetUidResponse.newBuilder().apply {
|
|
||||||
request.uinList.forEach {
|
|
||||||
putUid(it, ContactHelper.getUidByUinAsync(it))
|
|
||||||
}
|
|
||||||
}.build()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Grpc("ContactService", "GetUinByUid")
|
|
||||||
override suspend fun getUinByUid(request: GetUinByUidRequest): GetUinByUidResponse {
|
|
||||||
return GetUinByUidResponse.newBuilder().apply {
|
|
||||||
request.uidList.forEach {
|
|
||||||
putUin(it, ContactHelper.getUinByUidAsync(it).toLong())
|
|
||||||
}
|
|
||||||
}.build()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Grpc("ContactService", "SetProfileCard")
|
|
||||||
override suspend fun setProfileCard(request: SetProfileCardRequest): SetProfileCardResponse {
|
|
||||||
val bundle = Bundle()
|
|
||||||
val service = QQInterfaces.app
|
|
||||||
.getRuntimeService(IProfileProtocolService::class.java, "all")
|
|
||||||
if (request.hasNickName()) {
|
|
||||||
bundle.putString(KEY_NICK, request.nickName)
|
|
||||||
}
|
|
||||||
if (request.hasCompany()) {
|
|
||||||
bundle.putString(KEY_COMPANY, request.company)
|
|
||||||
}
|
|
||||||
if (request.hasEmail()) {
|
|
||||||
bundle.putString(KEY_EMAIL, request.email)
|
|
||||||
}
|
|
||||||
if (request.hasCollege()) {
|
|
||||||
bundle.putString(KEY_COLLEGE, request.college)
|
|
||||||
}
|
|
||||||
if (request.hasPersonalNote()) {
|
|
||||||
bundle.putString(KEY_PERSONAL_NOTE, request.personalNote)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (request.hasBirthday()) {
|
|
||||||
bundle.putInt(KEY_BIRTHDAY, request.birthday)
|
|
||||||
}
|
|
||||||
if (request.hasAge()) {
|
|
||||||
bundle.putInt(KEY_AGE, request.age)
|
|
||||||
}
|
|
||||||
|
|
||||||
service.setProfileDetail(bundle)
|
|
||||||
return super.setProfileCard(request)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Grpc("ContactService", "IsBlackListUser")
|
|
||||||
override suspend fun isBlackListUser(request: IsBlackListUserRequest): IsBlackListUserResponse {
|
|
||||||
val blacklistApi = QRoute.api(IProfileCardBlacklistApi::class.java)
|
|
||||||
val isBlack = withTimeoutOrNull(5000) {
|
|
||||||
suspendCancellableCoroutine { continuation ->
|
|
||||||
blacklistApi.isBlackOrBlackedUin(request.uin.toString()) {
|
|
||||||
continuation.resume(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} ?: false
|
|
||||||
return IsBlackListUserResponse.newBuilder().setIsBlackListUser(isBlack).build()
|
|
||||||
}
|
|
||||||
}
|
|
@ -9,15 +9,13 @@ import moe.fuqiuluo.shamrock.tools.ShamrockVersion
|
|||||||
import moe.fuqiuluo.shamrock.utils.DownloadUtils
|
import moe.fuqiuluo.shamrock.utils.DownloadUtils
|
||||||
import moe.fuqiuluo.shamrock.utils.FileUtils
|
import moe.fuqiuluo.shamrock.utils.FileUtils
|
||||||
import moe.fuqiuluo.shamrock.utils.MD5
|
import moe.fuqiuluo.shamrock.utils.MD5
|
||||||
import moe.fuqiuluo.shamrock.utils.MMKVFetcher
|
|
||||||
import moe.fuqiuluo.shamrock.utils.PlatformUtils
|
|
||||||
import mqq.app.MobileQQ
|
import mqq.app.MobileQQ
|
||||||
import qq.service.QQInterfaces.Companion.app
|
import qq.service.QQInterfaces.Companion.app
|
||||||
import qq.service.contact.ContactHelper
|
import qq.service.contact.ContactHelper
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
internal object KritorService : KritorServiceGrpcKt.KritorServiceCoroutineImplBase() {
|
internal object CoreService : CoreServiceGrpcKt.CoreServiceCoroutineImplBase() {
|
||||||
@Grpc("KritorService", "GetVersion")
|
@Grpc("CoreService", "GetVersion")
|
||||||
override suspend fun getVersion(request: GetVersionRequest): GetVersionResponse {
|
override suspend fun getVersion(request: GetVersionRequest): GetVersionResponse {
|
||||||
return GetVersionResponse.newBuilder().apply {
|
return GetVersionResponse.newBuilder().apply {
|
||||||
this.version = ShamrockVersion
|
this.version = ShamrockVersion
|
||||||
@ -25,15 +23,7 @@ internal object KritorService : KritorServiceGrpcKt.KritorServiceCoroutineImplBa
|
|||||||
}.build()
|
}.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Grpc("KritorService", "ClearCache")
|
@Grpc("CoreService", "GetCurrentAccount")
|
||||||
override suspend fun clearCache(request: ClearCacheRequest): ClearCacheResponse {
|
|
||||||
FileUtils.clearCache()
|
|
||||||
MMKVFetcher.mmkvWithId("audio2silk")
|
|
||||||
.clear()
|
|
||||||
return ClearCacheResponse.newBuilder().build()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Grpc("KritorService", "GetCurrentAccount")
|
|
||||||
override suspend fun getCurrentAccount(request: GetCurrentAccountRequest): GetCurrentAccountResponse {
|
override suspend fun getCurrentAccount(request: GetCurrentAccountRequest): GetCurrentAccountResponse {
|
||||||
return GetCurrentAccountResponse.newBuilder().apply {
|
return GetCurrentAccountResponse.newBuilder().apply {
|
||||||
this.accountName = if (app is QQAppInterface) app.currentNickname else "unknown"
|
this.accountName = if (app is QQAppInterface) app.currentNickname else "unknown"
|
||||||
@ -42,7 +32,7 @@ internal object KritorService : KritorServiceGrpcKt.KritorServiceCoroutineImplBa
|
|||||||
}.build()
|
}.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Grpc("KritorService", "DownloadFile")
|
@Grpc("CoreService", "DownloadFile")
|
||||||
override suspend fun downloadFile(request: DownloadFileRequest): DownloadFileResponse {
|
override suspend fun downloadFile(request: DownloadFileRequest): DownloadFileResponse {
|
||||||
val headerMap = mutableMapOf(
|
val headerMap = mutableMapOf(
|
||||||
"User-Agent" to "Shamrock"
|
"User-Agent" to "Shamrock"
|
||||||
@ -88,7 +78,7 @@ internal object KritorService : KritorServiceGrpcKt.KritorServiceCoroutineImplBa
|
|||||||
}.build()
|
}.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Grpc("KritorService", "SwitchAccount")
|
@Grpc("CoreService", "SwitchAccount")
|
||||||
override suspend fun switchAccount(request: SwitchAccountRequest): SwitchAccountResponse {
|
override suspend fun switchAccount(request: SwitchAccountRequest): SwitchAccountResponse {
|
||||||
val uin = when (request.accountCase!!) {
|
val uin = when (request.accountCase!!) {
|
||||||
SwitchAccountRequest.AccountCase.ACCOUNT_UID -> ContactHelper.getUinByUidAsync(request.accountUid)
|
SwitchAccountRequest.AccountCase.ACCOUNT_UID -> ContactHelper.getUinByUidAsync(request.accountUid)
|
||||||
@ -108,15 +98,4 @@ internal object KritorService : KritorServiceGrpcKt.KritorServiceCoroutineImplBa
|
|||||||
}
|
}
|
||||||
return SwitchAccountResponse.newBuilder().build()
|
return SwitchAccountResponse.newBuilder().build()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Grpc("KritorService", "GetDeviceBattery")
|
|
||||||
override suspend fun getDeviceBattery(request: GetDeviceBatteryRequest): GetDeviceBatteryResponse {
|
|
||||||
return GetDeviceBatteryResponse.newBuilder().apply {
|
|
||||||
PlatformUtils.getDeviceBattery().let {
|
|
||||||
this.battery = it.battery
|
|
||||||
this.scale = it.scale
|
|
||||||
this.status = it.status
|
|
||||||
}
|
|
||||||
}.build()
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,29 +1,56 @@
|
|||||||
package kritor.service
|
package kritor.service
|
||||||
|
|
||||||
import com.google.protobuf.ByteString
|
import com.google.protobuf.ByteString
|
||||||
import com.tencent.mobileqq.fe.FEKit
|
|
||||||
import com.tencent.mobileqq.qsec.qsecdandelionsdk.Dandelion
|
|
||||||
import io.kritor.developer.*
|
import io.kritor.developer.*
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import kotlinx.coroutines.withTimeoutOrNull
|
||||||
|
import moe.fuqiuluo.shamrock.utils.FileUtils
|
||||||
|
import moe.fuqiuluo.shamrock.utils.MMKVFetcher
|
||||||
|
import moe.fuqiuluo.shamrock.utils.PlatformUtils
|
||||||
import qq.service.QQInterfaces
|
import qq.service.QQInterfaces
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
internal object DeveloperService: DeveloperServiceGrpcKt.DeveloperServiceCoroutineImplBase() {
|
internal object DeveloperService: DeveloperServiceGrpcKt.DeveloperServiceCoroutineImplBase() {
|
||||||
@Grpc("DeveloperService", "Sign")
|
@Grpc("DeveloperService", "Shell")
|
||||||
override suspend fun sign(request: SignRequest): SignResponse {
|
override suspend fun shell(request: ShellRequest): ShellResponse {
|
||||||
return SignResponse.newBuilder().apply {
|
if (request.commandList.isEmpty()) return ShellResponse.newBuilder().setIsSuccess(false).build()
|
||||||
val result = FEKit.getInstance().getSign(request.command, request.buffer.toByteArray(), request.seq, request.uin)
|
val runtime = Runtime.getRuntime()
|
||||||
this.sign = ByteString.copyFrom(result.sign)
|
val result = withTimeoutOrNull(5000L) {
|
||||||
this.token = ByteString.copyFrom(result.token)
|
withContext(Dispatchers.IO) {
|
||||||
this.extra = ByteString.copyFrom(result.extra)
|
runtime.exec(request.commandList.toTypedArray(), null, File(request.directory)).apply { waitFor() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ShellResponse.newBuilder().apply {
|
||||||
|
if (result == null) {
|
||||||
|
isSuccess = false
|
||||||
|
} else {
|
||||||
|
isSuccess = true
|
||||||
|
result.inputStream.use {
|
||||||
|
data = it.readBytes().toString(Charsets.UTF_8)
|
||||||
|
}
|
||||||
|
}
|
||||||
}.build()
|
}.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Grpc("DeveloperService", "Energy")
|
@Grpc("DeveloperService", "ClearCache")
|
||||||
override suspend fun energy(request: EnergyRequest): EnergyResponse {
|
override suspend fun clearCache(request: ClearCacheRequest): ClearCacheResponse {
|
||||||
return EnergyResponse.newBuilder().apply {
|
FileUtils.clearCache()
|
||||||
this.result = ByteString.copyFrom(Dandelion.getInstance().fly(request.data, request.salt.toByteArray()))
|
MMKVFetcher.mmkvWithId("audio2silk")
|
||||||
}.build()
|
.clear()
|
||||||
|
return ClearCacheResponse.newBuilder().build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Grpc("DeveloperService", "GetDeviceBattery")
|
||||||
|
override suspend fun getDeviceBattery(request: GetDeviceBatteryRequest): GetDeviceBatteryResponse {
|
||||||
|
return GetDeviceBatteryResponse.newBuilder().apply {
|
||||||
|
PlatformUtils.getDeviceBattery().let {
|
||||||
|
this.battery = it.battery
|
||||||
|
this.scale = it.scale
|
||||||
|
this.status = it.status
|
||||||
|
}
|
||||||
|
}.build()
|
||||||
|
}
|
||||||
|
|
||||||
@Grpc("DeveloperService", "SendPacket")
|
@Grpc("DeveloperService", "SendPacket")
|
||||||
override suspend fun sendPacket(request: SendPacketRequest): SendPacketResponse {
|
override suspend fun sendPacket(request: SendPacketRequest): SendPacketResponse {
|
||||||
@ -37,5 +64,4 @@ internal object DeveloperService: DeveloperServiceGrpcKt.DeveloperServiceCorouti
|
|||||||
}
|
}
|
||||||
}.build()
|
}.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,85 +0,0 @@
|
|||||||
package kritor.service
|
|
||||||
|
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
|
||||||
import io.grpc.Status
|
|
||||||
import io.grpc.StatusRuntimeException
|
|
||||||
import io.kritor.event.MessageEvent
|
|
||||||
import io.kritor.message.*
|
|
||||||
import qq.service.contact.longPeer
|
|
||||||
import qq.service.msg.ForwardMessageHelper
|
|
||||||
import qq.service.msg.MessageHelper
|
|
||||||
import qq.service.msg.toKritorResponseMessages
|
|
||||||
|
|
||||||
internal object ForwardMessageService : ForwardMessageServiceGrpcKt.ForwardMessageServiceCoroutineImplBase() {
|
|
||||||
@Grpc("ForwardMessageService", "UploadForwardMessage")
|
|
||||||
override suspend fun uploadForwardMessage(request: UploadForwardMessageRequest): UploadForwardMessageResponse {
|
|
||||||
val contact = request.contact.let {
|
|
||||||
MessageHelper.generateContact(
|
|
||||||
when (it.scene!!) {
|
|
||||||
Scene.GROUP -> MsgConstant.KCHATTYPEGROUP
|
|
||||||
Scene.FRIEND -> MsgConstant.KCHATTYPEC2C
|
|
||||||
Scene.GUILD -> MsgConstant.KCHATTYPEGUILD
|
|
||||||
Scene.STRANGER_FROM_GROUP -> MsgConstant.KCHATTYPETEMPC2CFROMGROUP
|
|
||||||
Scene.NEARBY -> MsgConstant.KCHATTYPETEMPC2CFROMUNKNOWN
|
|
||||||
Scene.STRANGER -> MsgConstant.KCHATTYPETEMPC2CFROMUNKNOWN
|
|
||||||
Scene.UNRECOGNIZED -> throw StatusRuntimeException(Status.INVALID_ARGUMENT.withDescription("Unrecognized scene"))
|
|
||||||
}, it.peer, it.subPeer
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val forwardMessage = ForwardMessageHelper.uploadMultiMsg(
|
|
||||||
contact.chatType,
|
|
||||||
contact.longPeer().toString(),
|
|
||||||
contact.guildId,
|
|
||||||
request.messagesList
|
|
||||||
).onFailure {
|
|
||||||
throw StatusRuntimeException(Status.INTERNAL.withCause(it))
|
|
||||||
}.getOrThrow()
|
|
||||||
|
|
||||||
return UploadForwardMessageResponse.newBuilder().apply {
|
|
||||||
this.resId = forwardMessage.resId
|
|
||||||
}.build()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Grpc("ForwardMessageService", "DownloadForwardMessage")
|
|
||||||
override suspend fun downloadForwardMessage(request: DownloadForwardMessageRequest): DownloadForwardMessageResponse {
|
|
||||||
return DownloadForwardMessageResponse.newBuilder().apply {
|
|
||||||
this.addAllMessages(
|
|
||||||
MessageHelper.getForwardMsg(request.resId).onFailure {
|
|
||||||
throw StatusRuntimeException(Status.INTERNAL.withCause(it))
|
|
||||||
}.getOrThrow().map { detail ->
|
|
||||||
MessageEvent.newBuilder().apply {
|
|
||||||
this.time = detail.time
|
|
||||||
this.messageId = detail.qqMsgId
|
|
||||||
this.messageSeq = detail.msgSeq
|
|
||||||
this.contact = Contact.newBuilder().apply {
|
|
||||||
this.scene = when (detail.msgType) {
|
|
||||||
MsgConstant.KCHATTYPEC2C -> Scene.FRIEND
|
|
||||||
MsgConstant.KCHATTYPEGROUP -> Scene.GROUP
|
|
||||||
MsgConstant.KCHATTYPEGUILD -> Scene.GUILD
|
|
||||||
MsgConstant.KCHATTYPETEMPC2CFROMGROUP -> Scene.STRANGER_FROM_GROUP
|
|
||||||
MsgConstant.KCHATTYPETEMPC2CFROMUNKNOWN -> Scene.NEARBY
|
|
||||||
else -> Scene.STRANGER
|
|
||||||
}
|
|
||||||
this.peer = detail.peerId.toString()
|
|
||||||
}.build()
|
|
||||||
this.sender = Sender.newBuilder().apply {
|
|
||||||
this.uin = detail.sender.userId
|
|
||||||
this.nick = detail.sender.nickName
|
|
||||||
this.uid = detail.sender.uid
|
|
||||||
}.build()
|
|
||||||
detail.message?.elements?.toKritorResponseMessages(
|
|
||||||
com.tencent.qqnt.kernel.nativeinterface.Contact(
|
|
||||||
detail.msgType,
|
|
||||||
detail.peerId.toString(),
|
|
||||||
null
|
|
||||||
)
|
|
||||||
)?.let {
|
|
||||||
this.addAllElements(it)
|
|
||||||
}
|
|
||||||
}.build()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}.build()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,23 +1,33 @@
|
|||||||
package kritor.service
|
package kritor.service
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import com.tencent.mobileqq.profilecard.api.IProfileCardBlacklistApi
|
||||||
|
import com.tencent.mobileqq.profilecard.api.IProfileProtocolConst
|
||||||
|
import com.tencent.mobileqq.profilecard.api.IProfileProtocolService
|
||||||
|
import com.tencent.mobileqq.qroute.QRoute
|
||||||
import io.grpc.Status
|
import io.grpc.Status
|
||||||
import io.grpc.StatusRuntimeException
|
import io.grpc.StatusRuntimeException
|
||||||
import io.kritor.friend.*
|
import io.kritor.friend.*
|
||||||
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
|
import kotlinx.coroutines.withTimeoutOrNull
|
||||||
|
import qq.service.QQInterfaces
|
||||||
import qq.service.contact.ContactHelper
|
import qq.service.contact.ContactHelper
|
||||||
import qq.service.friend.FriendHelper
|
import qq.service.friend.FriendHelper
|
||||||
|
import kotlin.coroutines.resume
|
||||||
|
|
||||||
internal object FriendService: FriendServiceGrpcKt.FriendServiceCoroutineImplBase() {
|
internal object FriendService : FriendServiceGrpcKt.FriendServiceCoroutineImplBase() {
|
||||||
@Grpc("FriendService", "GetFriendList")
|
@Grpc("FriendService", "GetFriendList")
|
||||||
override suspend fun getFriendList(request: GetFriendListRequest): GetFriendListResponse {
|
override suspend fun getFriendList(request: GetFriendListRequest): GetFriendListResponse {
|
||||||
val friendList = FriendHelper.getFriendList(if(request.hasRefresh()) request.refresh else false).onFailure {
|
val friendList = FriendHelper.getFriendList(if (request.hasRefresh()) request.refresh else false).onFailure {
|
||||||
throw StatusRuntimeException(Status.INTERNAL
|
throw StatusRuntimeException(
|
||||||
.withDescription(it.stackTraceToString())
|
Status.INTERNAL
|
||||||
|
.withDescription(it.stackTraceToString())
|
||||||
)
|
)
|
||||||
}.getOrThrow()
|
}.getOrThrow()
|
||||||
|
|
||||||
return GetFriendListResponse.newBuilder().apply {
|
return GetFriendListResponse.newBuilder().apply {
|
||||||
friendList.forEach {
|
friendList.forEach {
|
||||||
this.addFriendList(FriendData.newBuilder().apply {
|
this.addFriendsInfo(FriendInfo.newBuilder().apply {
|
||||||
uin = it.uin.toLong()
|
uin = it.uin.toLong()
|
||||||
uid = ContactHelper.getUidByUinAsync(uin)
|
uid = ContactHelper.getUidByUinAsync(uin)
|
||||||
qid = ""
|
qid = ""
|
||||||
@ -27,10 +37,208 @@ internal object FriendService: FriendServiceGrpcKt.FriendServiceCoroutineImplBas
|
|||||||
level = 0
|
level = 0
|
||||||
gender = it.gender.toInt()
|
gender = it.gender.toInt()
|
||||||
groupId = it.groupid
|
groupId = it.groupid
|
||||||
ext = FriendExt.newBuilder().build().toByteString()
|
|
||||||
|
ext = ExtInfo.newBuilder().build()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}.build()
|
}.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Grpc("FriendService", "GetFriendProfileCard")
|
||||||
|
override suspend fun getFriendProfileCard(request: GetFriendProfileCardRequest): GetFriendProfileCardResponse {
|
||||||
|
return GetFriendProfileCardResponse.newBuilder().apply {
|
||||||
|
request.targetUinsList.forEach {
|
||||||
|
ContactHelper.getProfileCard(it).getOrThrow().let { info ->
|
||||||
|
addFriendsProfileCard(ProfileCard.newBuilder().apply {
|
||||||
|
this.uin = info.uin.toLong()
|
||||||
|
this.uid = ContactHelper.getUidByUinAsync(info.uin.toLong())
|
||||||
|
this.nick = info.strNick
|
||||||
|
this.remark = info.strReMark
|
||||||
|
this.level = info.iQQLevel
|
||||||
|
this.birthday = info.lBirthday
|
||||||
|
this.loginDay = info.lLoginDays.toInt()
|
||||||
|
this.voteCnt = info.lVoteCount.toInt()
|
||||||
|
this.qid = info.qid ?: ""
|
||||||
|
this.isSchoolVerified = info.schoolVerifiedFlag
|
||||||
|
|
||||||
|
this.ext = ExtInfo.newBuilder().apply {
|
||||||
|
this.bigVip = info.bBigClubVipOpen == 1.toByte()
|
||||||
|
this.hollywoodVip = info.bHollywoodVipOpen == 1.toByte()
|
||||||
|
this.qqVip = info.bQQVipOpen == 1.toByte()
|
||||||
|
this.superVip = info.bSuperQQOpen == 1.toByte()
|
||||||
|
this.voted = info.bVoted == 1.toByte()
|
||||||
|
}.build()
|
||||||
|
}.build())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
request.targetUidsList.forEach {
|
||||||
|
ContactHelper.getProfileCard(ContactHelper.getUinByUidAsync(it).toLong()).getOrThrow().let { info ->
|
||||||
|
addFriendsProfileCard(ProfileCard.newBuilder().apply {
|
||||||
|
this.uin = info.uin.toLong()
|
||||||
|
this.uid = it
|
||||||
|
this.nick = info.strNick
|
||||||
|
this.remark = info.strReMark
|
||||||
|
this.level = info.iQQLevel
|
||||||
|
this.birthday = info.lBirthday
|
||||||
|
this.loginDay = info.lLoginDays.toInt()
|
||||||
|
this.voteCnt = info.lVoteCount.toInt()
|
||||||
|
this.qid = info.qid ?: ""
|
||||||
|
this.isSchoolVerified = info.schoolVerifiedFlag
|
||||||
|
|
||||||
|
this.ext = ExtInfo.newBuilder().apply {
|
||||||
|
this.bigVip = info.bBigClubVipOpen == 1.toByte()
|
||||||
|
this.hollywoodVip = info.bHollywoodVipOpen == 1.toByte()
|
||||||
|
this.qqVip = info.bQQVipOpen == 1.toByte()
|
||||||
|
this.superVip = info.bSuperQQOpen == 1.toByte()
|
||||||
|
this.voted = info.bVoted == 1.toByte()
|
||||||
|
}.build()
|
||||||
|
}.build())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Grpc("FriendService", "GetStrangerProfileCard")
|
||||||
|
override suspend fun getStrangerProfileCard(request: GetStrangerProfileCardRequest): GetStrangerProfileCardResponse {
|
||||||
|
return GetStrangerProfileCardResponse.newBuilder().apply {
|
||||||
|
request.targetUinsList.forEach {
|
||||||
|
ContactHelper.refreshAndGetProfileCard(it).getOrThrow().let { info ->
|
||||||
|
addStrangersProfileCard(ProfileCard.newBuilder().apply {
|
||||||
|
this.uin = info.uin.toLong()
|
||||||
|
this.uid = ContactHelper.getUidByUinAsync(info.uin.toLong())
|
||||||
|
this.nick = info.strNick
|
||||||
|
this.level = info.iQQLevel
|
||||||
|
this.birthday = info.lBirthday
|
||||||
|
this.loginDay = info.lLoginDays.toInt()
|
||||||
|
this.voteCnt = info.lVoteCount.toInt()
|
||||||
|
this.qid = info.qid ?: ""
|
||||||
|
this.isSchoolVerified = info.schoolVerifiedFlag
|
||||||
|
|
||||||
|
this.ext = ExtInfo.newBuilder().apply {
|
||||||
|
this.bigVip = info.bBigClubVipOpen == 1.toByte()
|
||||||
|
this.hollywoodVip = info.bHollywoodVipOpen == 1.toByte()
|
||||||
|
this.qqVip = info.bQQVipOpen == 1.toByte()
|
||||||
|
this.superVip = info.bSuperQQOpen == 1.toByte()
|
||||||
|
this.voted = info.bVoted == 1.toByte()
|
||||||
|
}.build()
|
||||||
|
}.build())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
request.targetUidsList.forEach {
|
||||||
|
ContactHelper.refreshAndGetProfileCard(ContactHelper.getUinByUidAsync(it).toLong()).getOrThrow()
|
||||||
|
.let { info ->
|
||||||
|
addStrangersProfileCard(ProfileCard.newBuilder().apply {
|
||||||
|
this.uin = info.uin.toLong()
|
||||||
|
this.uid = it
|
||||||
|
this.nick = info.strNick
|
||||||
|
this.level = info.iQQLevel
|
||||||
|
this.birthday = info.lBirthday
|
||||||
|
this.loginDay = info.lLoginDays.toInt()
|
||||||
|
this.voteCnt = info.lVoteCount.toInt()
|
||||||
|
this.qid = info.qid ?: ""
|
||||||
|
this.isSchoolVerified = info.schoolVerifiedFlag
|
||||||
|
|
||||||
|
this.ext = ExtInfo.newBuilder().apply {
|
||||||
|
this.bigVip = info.bBigClubVipOpen == 1.toByte()
|
||||||
|
this.hollywoodVip = info.bHollywoodVipOpen == 1.toByte()
|
||||||
|
this.qqVip = info.bQQVipOpen == 1.toByte()
|
||||||
|
this.superVip = info.bSuperQQOpen == 1.toByte()
|
||||||
|
this.voted = info.bVoted == 1.toByte()
|
||||||
|
}.build()
|
||||||
|
}.build())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Grpc("FriendService", "SetProfileCard")
|
||||||
|
override suspend fun setProfileCard(request: SetProfileCardRequest): SetProfileCardResponse {
|
||||||
|
val bundle = Bundle()
|
||||||
|
val service = QQInterfaces.app
|
||||||
|
.getRuntimeService(IProfileProtocolService::class.java, "all")
|
||||||
|
if (request.hasNick()) {
|
||||||
|
bundle.putString(IProfileProtocolConst.KEY_NICK, request.nick)
|
||||||
|
}
|
||||||
|
if (request.hasCompany()) {
|
||||||
|
bundle.putString(IProfileProtocolConst.KEY_COMPANY, request.company)
|
||||||
|
}
|
||||||
|
if (request.hasEmail()) {
|
||||||
|
bundle.putString(IProfileProtocolConst.KEY_EMAIL, request.email)
|
||||||
|
}
|
||||||
|
if (request.hasCollege()) {
|
||||||
|
bundle.putString(IProfileProtocolConst.KEY_COLLEGE, request.college)
|
||||||
|
}
|
||||||
|
if (request.hasPersonalNote()) {
|
||||||
|
bundle.putString(IProfileProtocolConst.KEY_PERSONAL_NOTE, request.personalNote)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.hasBirthday()) {
|
||||||
|
bundle.putInt(IProfileProtocolConst.KEY_BIRTHDAY, request.birthday)
|
||||||
|
}
|
||||||
|
if (request.hasAge()) {
|
||||||
|
bundle.putInt(IProfileProtocolConst.KEY_AGE, request.age)
|
||||||
|
}
|
||||||
|
|
||||||
|
service.setProfileDetail(bundle)
|
||||||
|
return super.setProfileCard(request)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Grpc("FriendService", "IsBlackListUser")
|
||||||
|
override suspend fun isBlackListUser(request: IsBlackListUserRequest): IsBlackListUserResponse {
|
||||||
|
val uin = when (request.targetCase!!) {
|
||||||
|
IsBlackListUserRequest.TargetCase.TARGET_UIN -> request.targetUin.toString()
|
||||||
|
IsBlackListUserRequest.TargetCase.TARGET_UID -> ContactHelper.getUinByUidAsync(request.targetUid)
|
||||||
|
IsBlackListUserRequest.TargetCase.TARGET_NOT_SET -> throw StatusRuntimeException(
|
||||||
|
Status.INVALID_ARGUMENT
|
||||||
|
.withDescription("account not set")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
val blacklistApi = QRoute.api(IProfileCardBlacklistApi::class.java)
|
||||||
|
val isBlack = withTimeoutOrNull(5000) {
|
||||||
|
suspendCancellableCoroutine { continuation ->
|
||||||
|
blacklistApi.isBlackOrBlackedUin(uin) {
|
||||||
|
continuation.resume(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} ?: false
|
||||||
|
return IsBlackListUserResponse.newBuilder().setIsBlackListUser(isBlack).build()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Grpc("FriendService", "VoteUser")
|
||||||
|
override suspend fun voteUser(request: VoteUserRequest): VoteUserResponse {
|
||||||
|
ContactHelper.voteUser(
|
||||||
|
when (request.targetCase!!) {
|
||||||
|
VoteUserRequest.TargetCase.TARGET_UIN -> request.targetUin
|
||||||
|
VoteUserRequest.TargetCase.TARGET_UID -> ContactHelper.getUinByUidAsync(request.targetUid).toLong()
|
||||||
|
VoteUserRequest.TargetCase.TARGET_NOT_SET -> throw StatusRuntimeException(
|
||||||
|
Status.INVALID_ARGUMENT
|
||||||
|
.withDescription("account not set")
|
||||||
|
)
|
||||||
|
}, request.voteCount
|
||||||
|
).onFailure {
|
||||||
|
throw StatusRuntimeException(
|
||||||
|
Status.INTERNAL
|
||||||
|
.withDescription(it.stackTraceToString())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return VoteUserResponse.newBuilder().build()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Grpc("FriendService", "GetUidByUin")
|
||||||
|
override suspend fun getUidByUin(request: GetUidByUinRequest): GetUidByUinResponse {
|
||||||
|
return GetUidByUinResponse.newBuilder().apply {
|
||||||
|
request.targetUinsList.forEach {
|
||||||
|
putUidMap(it, ContactHelper.getUidByUinAsync(it))
|
||||||
|
}
|
||||||
|
}.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Grpc("FriendService", "GetUinByUid")
|
||||||
|
override suspend fun getUinByUid(request: GetUinByUidRequest): GetUinByUidResponse {
|
||||||
|
return GetUinByUidResponse.newBuilder().apply {
|
||||||
|
request.targetUidsList.forEach {
|
||||||
|
putUinMap(it, ContactHelper.getUinByUidAsync(it).toLong())
|
||||||
|
}
|
||||||
|
}.build()
|
||||||
|
}
|
||||||
}
|
}
|
@ -3,6 +3,7 @@ package kritor.service
|
|||||||
import io.grpc.Status
|
import io.grpc.Status
|
||||||
import io.grpc.StatusRuntimeException
|
import io.grpc.StatusRuntimeException
|
||||||
import io.kritor.file.*
|
import io.kritor.file.*
|
||||||
|
import moe.fuqiuluo.shamrock.tools.decodeToOidb
|
||||||
import moe.fuqiuluo.shamrock.tools.slice
|
import moe.fuqiuluo.shamrock.tools.slice
|
||||||
import moe.fuqiuluo.symbols.decodeProtobuf
|
import moe.fuqiuluo.symbols.decodeProtobuf
|
||||||
import protobuf.auto.toByteArray
|
import protobuf.auto.toByteArray
|
||||||
@ -17,7 +18,7 @@ import qq.service.file.GroupFileHelper.getGroupFileSystemInfo
|
|||||||
import tencent.im.oidb.cmd0x6d6.oidb_0x6d6
|
import tencent.im.oidb.cmd0x6d6.oidb_0x6d6
|
||||||
import tencent.im.oidb.oidb_sso
|
import tencent.im.oidb.oidb_sso
|
||||||
|
|
||||||
internal object GroupFileService: GroupFileServiceGrpcKt.GroupFileServiceCoroutineImplBase() {
|
internal object GroupFileService : GroupFileServiceGrpcKt.GroupFileServiceCoroutineImplBase() {
|
||||||
@Grpc("GroupFileService", "CreateFolder")
|
@Grpc("GroupFileService", "CreateFolder")
|
||||||
override suspend fun createFolder(request: CreateFolderRequest): CreateFolderResponse {
|
override suspend fun createFolder(request: CreateFolderRequest): CreateFolderResponse {
|
||||||
val data = Oidb0x6d7ReqBody(
|
val data = Oidb0x6d7ReqBody(
|
||||||
@ -33,8 +34,7 @@ internal object GroupFileService: GroupFileServiceGrpcKt.GroupFileServiceCorouti
|
|||||||
if (fromServiceMsg.wupBuffer == null) {
|
if (fromServiceMsg.wupBuffer == null) {
|
||||||
throw StatusRuntimeException(Status.INTERNAL.withDescription("oidb request failed"))
|
throw StatusRuntimeException(Status.INTERNAL.withDescription("oidb request failed"))
|
||||||
}
|
}
|
||||||
val oidbPkg = oidb_sso.OIDBSSOPkg()
|
val oidbPkg = fromServiceMsg.decodeToOidb()
|
||||||
oidbPkg.mergeFrom(fromServiceMsg.wupBuffer.slice(4))
|
|
||||||
val rsp = oidbPkg.bytes_bodybuffer.get()
|
val rsp = oidbPkg.bytes_bodybuffer.get()
|
||||||
.toByteArray()
|
.toByteArray()
|
||||||
.decodeProtobuf<Oidb0x6d7RespBody>()
|
.decodeProtobuf<Oidb0x6d7RespBody>()
|
||||||
@ -49,18 +49,19 @@ internal object GroupFileService: GroupFileServiceGrpcKt.GroupFileServiceCorouti
|
|||||||
|
|
||||||
@Grpc("GroupFileService", "DeleteFolder")
|
@Grpc("GroupFileService", "DeleteFolder")
|
||||||
override suspend fun deleteFolder(request: DeleteFolderRequest): DeleteFolderResponse {
|
override suspend fun deleteFolder(request: DeleteFolderRequest): DeleteFolderResponse {
|
||||||
val fromServiceMsg = QQInterfaces.sendOidbAW("OidbSvc.0x6d7_1", 1751, 1, Oidb0x6d7ReqBody(
|
val fromServiceMsg = QQInterfaces.sendOidbAW(
|
||||||
deleteFolder = DeleteFolderReq(
|
"OidbSvc.0x6d7_1", 1751, 1, Oidb0x6d7ReqBody(
|
||||||
groupCode = request.groupId.toULong(),
|
deleteFolder = DeleteFolderReq(
|
||||||
appId = 3u,
|
groupCode = request.groupId.toULong(),
|
||||||
folderId = request.folderId
|
appId = 3u,
|
||||||
)
|
folderId = request.folderId
|
||||||
).toByteArray()) ?: throw StatusRuntimeException(Status.INTERNAL.withDescription("unable to send oidb request"))
|
)
|
||||||
|
).toByteArray()
|
||||||
|
) ?: throw StatusRuntimeException(Status.INTERNAL.withDescription("unable to send oidb request"))
|
||||||
if (fromServiceMsg.wupBuffer == null) {
|
if (fromServiceMsg.wupBuffer == null) {
|
||||||
throw StatusRuntimeException(Status.INTERNAL.withDescription("oidb request failed"))
|
throw StatusRuntimeException(Status.INTERNAL.withDescription("oidb request failed"))
|
||||||
}
|
}
|
||||||
val oidbPkg = oidb_sso.OIDBSSOPkg()
|
val oidbPkg = fromServiceMsg.decodeToOidb()
|
||||||
oidbPkg.mergeFrom(fromServiceMsg.wupBuffer.slice(4))
|
|
||||||
val rsp = oidbPkg.bytes_bodybuffer.get().toByteArray().decodeProtobuf<Oidb0x6d7RespBody>()
|
val rsp = oidbPkg.bytes_bodybuffer.get().toByteArray().decodeProtobuf<Oidb0x6d7RespBody>()
|
||||||
if (rsp.deleteFolder?.retCode != 0) {
|
if (rsp.deleteFolder?.retCode != 0) {
|
||||||
throw StatusRuntimeException(Status.INTERNAL.withDescription("unable to delete folder: ${rsp.deleteFolder?.retCode}"))
|
throw StatusRuntimeException(Status.INTERNAL.withDescription("unable to delete folder: ${rsp.deleteFolder?.retCode}"))
|
||||||
@ -84,8 +85,7 @@ internal object GroupFileService: GroupFileServiceGrpcKt.GroupFileServiceCorouti
|
|||||||
if (fromServiceMsg.wupBuffer == null) {
|
if (fromServiceMsg.wupBuffer == null) {
|
||||||
throw StatusRuntimeException(Status.INTERNAL.withDescription("oidb request failed"))
|
throw StatusRuntimeException(Status.INTERNAL.withDescription("oidb request failed"))
|
||||||
}
|
}
|
||||||
val oidbPkg = oidb_sso.OIDBSSOPkg()
|
val oidbPkg = fromServiceMsg.decodeToOidb()
|
||||||
oidbPkg.mergeFrom(fromServiceMsg.wupBuffer.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())
|
||||||
}
|
}
|
||||||
@ -97,19 +97,20 @@ internal object GroupFileService: GroupFileServiceGrpcKt.GroupFileServiceCorouti
|
|||||||
|
|
||||||
@Grpc("GroupFileService", "RenameFolder")
|
@Grpc("GroupFileService", "RenameFolder")
|
||||||
override suspend fun renameFolder(request: RenameFolderRequest): RenameFolderResponse {
|
override suspend fun renameFolder(request: RenameFolderRequest): RenameFolderResponse {
|
||||||
val fromServiceMsg = QQInterfaces.sendOidbAW("OidbSvc.0x6d7_3", 1751, 3, Oidb0x6d7ReqBody(
|
val fromServiceMsg = QQInterfaces.sendOidbAW(
|
||||||
renameFolder = RenameFolderReq(
|
"OidbSvc.0x6d7_3", 1751, 3, Oidb0x6d7ReqBody(
|
||||||
groupCode = request.groupId.toULong(),
|
renameFolder = RenameFolderReq(
|
||||||
appId = 3u,
|
groupCode = request.groupId.toULong(),
|
||||||
folderId = request.folderId,
|
appId = 3u,
|
||||||
folderName = request.name
|
folderId = request.folderId,
|
||||||
)
|
folderName = request.name
|
||||||
).toByteArray()) ?: throw StatusRuntimeException(Status.INTERNAL.withDescription("unable to send oidb request"))
|
)
|
||||||
|
).toByteArray()
|
||||||
|
) ?: throw StatusRuntimeException(Status.INTERNAL.withDescription("unable to send oidb request"))
|
||||||
if (fromServiceMsg.wupBuffer == null) {
|
if (fromServiceMsg.wupBuffer == null) {
|
||||||
throw StatusRuntimeException(Status.INTERNAL.withDescription("oidb request failed"))
|
throw StatusRuntimeException(Status.INTERNAL.withDescription("oidb request failed"))
|
||||||
}
|
}
|
||||||
val oidbPkg = oidb_sso.OIDBSSOPkg()
|
val oidbPkg = fromServiceMsg.decodeToOidb()
|
||||||
oidbPkg.mergeFrom(fromServiceMsg.wupBuffer.slice(4))
|
|
||||||
val rsp = oidbPkg.bytes_bodybuffer.get().toByteArray().decodeProtobuf<Oidb0x6d7RespBody>()
|
val rsp = oidbPkg.bytes_bodybuffer.get().toByteArray().decodeProtobuf<Oidb0x6d7RespBody>()
|
||||||
if (rsp.renameFolder?.retCode != 0) {
|
if (rsp.renameFolder?.retCode != 0) {
|
||||||
throw StatusRuntimeException(Status.INTERNAL.withDescription("unable to rename folder: ${rsp.renameFolder?.retCode}"))
|
throw StatusRuntimeException(Status.INTERNAL.withDescription("unable to rename folder: ${rsp.renameFolder?.retCode}"))
|
||||||
@ -122,17 +123,11 @@ internal object GroupFileService: GroupFileServiceGrpcKt.GroupFileServiceCorouti
|
|||||||
return getGroupFileSystemInfo(request.groupId)
|
return getGroupFileSystemInfo(request.groupId)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Grpc("GroupFileService", "GetRootFiles")
|
@Grpc("GroupFileService", "GetFileList")
|
||||||
override suspend fun getRootFiles(request: GetRootFilesRequest): GetRootFilesResponse {
|
override suspend fun getFileList(request: GetFileListRequest): GetFileListResponse {
|
||||||
return GetRootFilesResponse.newBuilder().apply {
|
return if (request.hasFolderId())
|
||||||
val response = GroupFileHelper.getGroupFiles(request.groupId)
|
GroupFileHelper.getGroupFiles(request.groupId, request.folderId)
|
||||||
this.addAllFiles(response.filesList)
|
else
|
||||||
this.addAllFolders(response.foldersList)
|
GroupFileHelper.getGroupFiles(request.groupId)
|
||||||
}.build()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Grpc("GroupFileService", "GetFiles")
|
|
||||||
override suspend fun getFiles(request: GetFilesRequest): GetFilesResponse {
|
|
||||||
return GroupFileHelper.getGroupFiles(request.groupId, request.folderId)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,10 +3,12 @@ package kritor.service
|
|||||||
import io.grpc.Status
|
import io.grpc.Status
|
||||||
import io.grpc.StatusRuntimeException
|
import io.grpc.StatusRuntimeException
|
||||||
import io.kritor.group.*
|
import io.kritor.group.*
|
||||||
|
import moe.fuqiuluo.shamrock.helper.LogCenter
|
||||||
import moe.fuqiuluo.shamrock.helper.TroopHonorHelper.decodeHonor
|
import moe.fuqiuluo.shamrock.helper.TroopHonorHelper.decodeHonor
|
||||||
import moe.fuqiuluo.shamrock.tools.ifNullOrEmpty
|
import moe.fuqiuluo.shamrock.tools.ifNullOrEmpty
|
||||||
import qq.service.contact.ContactHelper
|
import qq.service.contact.ContactHelper
|
||||||
import qq.service.group.GroupHelper
|
import qq.service.group.GroupHelper
|
||||||
|
import tencent.im.troop.honor.troop_honor
|
||||||
|
|
||||||
internal object GroupService : GroupServiceGrpcKt.GroupServiceCoroutineImplBase() {
|
internal object GroupService : GroupServiceGrpcKt.GroupServiceCoroutineImplBase() {
|
||||||
@Grpc("GroupService", "BanMember")
|
@Grpc("GroupService", "BanMember")
|
||||||
@ -212,10 +214,11 @@ internal object GroupService : GroupServiceGrpcKt.GroupServiceCoroutineImplBase(
|
|||||||
}.getOrThrow()
|
}.getOrThrow()
|
||||||
return GetGroupListResponse.newBuilder().apply {
|
return GetGroupListResponse.newBuilder().apply {
|
||||||
groupList.forEach { groupInfo ->
|
groupList.forEach { groupInfo ->
|
||||||
this.addGroupInfo(GroupInfo.newBuilder().apply {
|
this.addGroupsInfo(GroupInfo.newBuilder().apply {
|
||||||
groupId = groupInfo.troopcode.toLong()
|
groupId = groupInfo.troopcode.ifNullOrEmpty { groupInfo.uin }.ifNullOrEmpty { groupInfo.troopuin }?.toLong() ?: 0
|
||||||
groupName = groupInfo.troopname.ifNullOrEmpty { groupInfo.troopRemark }
|
groupName = groupInfo.troopname.ifNullOrEmpty { groupInfo.troopRemark }
|
||||||
.ifNullOrEmpty { groupInfo.newTroopName } ?: ""
|
.ifNullOrEmpty { groupInfo.newTroopName }
|
||||||
|
?: ""
|
||||||
groupRemark = groupInfo.troopRemark ?: ""
|
groupRemark = groupInfo.troopRemark ?: ""
|
||||||
owner = groupInfo.troopowneruin?.toLong() ?: 0
|
owner = groupInfo.troopowneruin?.toLong() ?: 0
|
||||||
addAllAdmins(GroupHelper.getAdminList(groupId))
|
addAllAdmins(GroupHelper.getAdminList(groupId))
|
||||||
@ -231,8 +234,8 @@ internal object GroupService : GroupServiceGrpcKt.GroupServiceCoroutineImplBase(
|
|||||||
override suspend fun getGroupMemberInfo(request: GetGroupMemberInfoRequest): GetGroupMemberInfoResponse {
|
override suspend fun getGroupMemberInfo(request: GetGroupMemberInfoRequest): GetGroupMemberInfoResponse {
|
||||||
val memberInfo = GroupHelper.getTroopMemberInfoByUin(
|
val memberInfo = GroupHelper.getTroopMemberInfoByUin(
|
||||||
request.groupId.toString(), when (request.targetCase!!) {
|
request.groupId.toString(), when (request.targetCase!!) {
|
||||||
GetGroupMemberInfoRequest.TargetCase.UIN -> request.uin
|
GetGroupMemberInfoRequest.TargetCase.TARGET_UID -> request.targetUin
|
||||||
GetGroupMemberInfoRequest.TargetCase.UID -> ContactHelper.getUinByUidAsync(request.uid).toLong()
|
GetGroupMemberInfoRequest.TargetCase.TARGET_UIN -> ContactHelper.getUinByUidAsync(request.targetUid).toLong()
|
||||||
else -> throw StatusRuntimeException(
|
else -> throw StatusRuntimeException(
|
||||||
Status.INVALID_ARGUMENT
|
Status.INVALID_ARGUMENT
|
||||||
.withDescription("target not set")
|
.withDescription("target not set")
|
||||||
@ -246,8 +249,8 @@ internal object GroupService : GroupServiceGrpcKt.GroupServiceCoroutineImplBase(
|
|||||||
return GetGroupMemberInfoResponse.newBuilder().apply {
|
return GetGroupMemberInfoResponse.newBuilder().apply {
|
||||||
groupMemberInfo = GroupMemberInfo.newBuilder().apply {
|
groupMemberInfo = GroupMemberInfo.newBuilder().apply {
|
||||||
uid =
|
uid =
|
||||||
if (request.targetCase == GetGroupMemberInfoRequest.TargetCase.UID) request.uid else ContactHelper.getUidByUinAsync(
|
if (request.targetCase == GetGroupMemberInfoRequest.TargetCase.TARGET_UID) request.targetUid else ContactHelper.getUidByUinAsync(
|
||||||
request.uin
|
request.targetUin
|
||||||
)
|
)
|
||||||
uin = memberInfo.memberuin?.toLong() ?: 0
|
uin = memberInfo.memberuin?.toLong() ?: 0
|
||||||
nick = memberInfo.troopnick
|
nick = memberInfo.troopnick
|
||||||
@ -256,15 +259,15 @@ internal object GroupService : GroupServiceGrpcKt.GroupServiceCoroutineImplBase(
|
|||||||
.ifNullOrEmpty { memberInfo.friendnick } ?: ""
|
.ifNullOrEmpty { memberInfo.friendnick } ?: ""
|
||||||
age = memberInfo.age.toInt()
|
age = memberInfo.age.toInt()
|
||||||
uniqueTitle = memberInfo.mUniqueTitle ?: ""
|
uniqueTitle = memberInfo.mUniqueTitle ?: ""
|
||||||
uniqueTitleExpireTime = memberInfo.mUniqueTitleExpire
|
uniqueTitleExpireTime = memberInfo.mUniqueTitleExpire.toLong()
|
||||||
card = memberInfo.troopnick.ifNullOrEmpty { memberInfo.friendnick } ?: ""
|
card = memberInfo.troopnick.ifNullOrEmpty { memberInfo.friendnick } ?: ""
|
||||||
joinTime = memberInfo.join_time
|
joinTime = memberInfo.join_time
|
||||||
lastActiveTime = memberInfo.last_active_time
|
lastActiveTime = memberInfo.last_active_time
|
||||||
level = memberInfo.level
|
level = memberInfo.level
|
||||||
shutUpTimestamp = memberInfo.gagTimeStamp
|
shutUpTime = memberInfo.gagTimeStamp
|
||||||
|
|
||||||
distance = memberInfo.distance
|
distance = memberInfo.distance
|
||||||
addAllHonor((memberInfo.honorList ?: "")
|
addAllHonors((memberInfo.honorList ?: "")
|
||||||
.split("|")
|
.split("|")
|
||||||
.filter { it.isNotBlank() }
|
.filter { it.isNotBlank() }
|
||||||
.map { it.toInt() })
|
.map { it.toInt() })
|
||||||
@ -277,7 +280,7 @@ internal object GroupService : GroupServiceGrpcKt.GroupServiceCoroutineImplBase(
|
|||||||
@Grpc("GroupService", "GetGroupMemberList")
|
@Grpc("GroupService", "GetGroupMemberList")
|
||||||
override suspend fun getGroupMemberList(request: GetGroupMemberListRequest): GetGroupMemberListResponse {
|
override suspend fun getGroupMemberList(request: GetGroupMemberListRequest): GetGroupMemberListResponse {
|
||||||
val memberList = GroupHelper.getGroupMemberList(
|
val memberList = GroupHelper.getGroupMemberList(
|
||||||
request.groupId.toString(),
|
request.groupId,
|
||||||
if (request.hasRefresh()) request.refresh else false
|
if (request.hasRefresh()) request.refresh else false
|
||||||
).onFailure {
|
).onFailure {
|
||||||
throw StatusRuntimeException(
|
throw StatusRuntimeException(
|
||||||
@ -285,30 +288,28 @@ internal object GroupService : GroupServiceGrpcKt.GroupServiceCoroutineImplBase(
|
|||||||
)
|
)
|
||||||
}.getOrThrow()
|
}.getOrThrow()
|
||||||
return GetGroupMemberListResponse.newBuilder().apply {
|
return GetGroupMemberListResponse.newBuilder().apply {
|
||||||
memberList.forEach { memberInfo ->
|
memberList.values.forEach { memberInfo ->
|
||||||
this.addGroupMemberInfo(GroupMemberInfo.newBuilder().apply {
|
this.addGroupMembersInfo(GroupMemberInfo.newBuilder().apply {
|
||||||
uid = ContactHelper.getUidByUinAsync(memberInfo.memberuin?.toLong() ?: 0)
|
uid = memberInfo.uid
|
||||||
uin = memberInfo.memberuin?.toLong() ?: 0
|
uin = memberInfo.uin
|
||||||
nick = memberInfo.troopnick
|
nick = memberInfo.nick ?: ""
|
||||||
.ifNullOrEmpty { memberInfo.hwName }
|
age = 0
|
||||||
.ifNullOrEmpty { memberInfo.troopColorNick }
|
uniqueTitle = memberInfo.memberSpecialTitle ?: ""
|
||||||
.ifNullOrEmpty { memberInfo.friendnick } ?: ""
|
uniqueTitleExpireTime = memberInfo.specialTitleExpireTime
|
||||||
age = memberInfo.age.toInt()
|
card = memberInfo.cardName.ifNullOrEmpty { memberInfo.nick } ?: ""
|
||||||
uniqueTitle = memberInfo.mUniqueTitle ?: ""
|
joinTime = memberInfo.joinTime.toLong()
|
||||||
uniqueTitleExpireTime = memberInfo.mUniqueTitleExpire
|
lastActiveTime = memberInfo.lastSpeakTime.toLong()
|
||||||
card = memberInfo.troopnick.ifNullOrEmpty { memberInfo.friendnick } ?: ""
|
level = memberInfo.memberLevel
|
||||||
joinTime = memberInfo.join_time
|
shutUpTime = memberInfo.shutUpTime.toLong()
|
||||||
lastActiveTime = memberInfo.last_active_time
|
|
||||||
level = memberInfo.level
|
|
||||||
shutUpTimestamp = memberInfo.gagTimeStamp
|
|
||||||
|
|
||||||
distance = memberInfo.distance
|
distance = 0
|
||||||
addAllHonor((memberInfo.honorList ?: "")
|
addAllHonors(memberInfo.groupHonor.let { bytes ->
|
||||||
.split("|")
|
val honor = troop_honor.GroupUserCardHonor()
|
||||||
.filter { it.isNotBlank() }
|
honor.mergeFrom(bytes)
|
||||||
.map { it.toInt() })
|
honor.id.get()
|
||||||
|
})
|
||||||
unfriendly = false
|
unfriendly = false
|
||||||
cardChangeable = GroupHelper.isAdmin(request.groupId.toString())
|
cardChangeable = memberInfo.role == com.tencent.qqnt.kernelpublic.nativeinterface.MemberRole.ADMIN
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}.build()
|
}.build()
|
||||||
@ -323,10 +324,10 @@ internal object GroupService : GroupServiceGrpcKt.GroupServiceCoroutineImplBase(
|
|||||||
}.getOrThrow()
|
}.getOrThrow()
|
||||||
return GetProhibitedUserListResponse.newBuilder().apply {
|
return GetProhibitedUserListResponse.newBuilder().apply {
|
||||||
prohibitedList.forEach {
|
prohibitedList.forEach {
|
||||||
this.addProhibitedUserInfo(ProhibitedUserInfo.newBuilder().apply {
|
this.addProhibitedUsersInfo(ProhibitedUserInfo.newBuilder().apply {
|
||||||
uid = ContactHelper.getUidByUinAsync(it.memberUin)
|
uid = ContactHelper.getUidByUinAsync(it.memberUin)
|
||||||
uin = it.memberUin
|
uin = it.memberUin
|
||||||
prohibitedTime = it.shutuptimestap
|
prohibitedTime = it.shutuptimestap.toLong()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}.build()
|
}.build()
|
||||||
@ -359,7 +360,7 @@ internal object GroupService : GroupServiceGrpcKt.GroupServiceCoroutineImplBase(
|
|||||||
maxMemberCount = groupInfo.maxMember
|
maxMemberCount = groupInfo.maxMember
|
||||||
memberCount = groupInfo.memberCount
|
memberCount = groupInfo.memberCount
|
||||||
groupDesc = groupInfo.groupDesc
|
groupDesc = groupInfo.groupDesc
|
||||||
createTime = groupInfo.createTime.toInt()
|
createTime = groupInfo.createTime
|
||||||
groupFlag = groupInfo.groupFlag
|
groupFlag = groupInfo.groupFlag
|
||||||
groupFlagExt = groupInfo.groupFlagExt
|
groupFlagExt = groupInfo.groupFlagExt
|
||||||
}.build()
|
}.build()
|
||||||
@ -369,24 +370,25 @@ internal object GroupService : GroupServiceGrpcKt.GroupServiceCoroutineImplBase(
|
|||||||
@Grpc("GroupService", "GetGroupHonor")
|
@Grpc("GroupService", "GetGroupHonor")
|
||||||
override suspend fun getGroupHonor(request: GetGroupHonorRequest): GetGroupHonorResponse {
|
override suspend fun getGroupHonor(request: GetGroupHonorRequest): GetGroupHonorResponse {
|
||||||
return GetGroupHonorResponse.newBuilder().apply {
|
return GetGroupHonorResponse.newBuilder().apply {
|
||||||
GroupHelper.getGroupMemberList(request.groupId.toString(), true).onFailure {
|
GroupHelper.getGroupMemberList(request.groupId, true).onFailure {
|
||||||
throw StatusRuntimeException(
|
throw StatusRuntimeException(
|
||||||
Status.INTERNAL.withDescription("unable to get group member list").withCause(it)
|
Status.INTERNAL.withDescription("unable to get group member list").withCause(it)
|
||||||
)
|
)
|
||||||
}.onSuccess { memberList ->
|
}.onSuccess { memberList ->
|
||||||
memberList.forEach { member ->
|
memberList.values.forEach { member ->
|
||||||
(member.honorList ?: "").split("|")
|
member.groupHonor.let { bytes ->
|
||||||
.filter { it.isNotBlank() }
|
val honor = troop_honor.GroupUserCardHonor()
|
||||||
.map { it.toInt() }.forEach {
|
honor.mergeFrom(bytes)
|
||||||
val honor = decodeHonor(member.memberuin.toLong(), it, member.mHonorRichFlag)
|
honor.id.get()
|
||||||
|
}.forEach {
|
||||||
|
val honor = decodeHonor(member.uin, it, 0)
|
||||||
if (honor != null) {
|
if (honor != null) {
|
||||||
addGroupHonorInfo(GroupHonorInfo.newBuilder().apply {
|
addGroupHonorsInfo(GroupHonorInfo.newBuilder().apply {
|
||||||
uid = ContactHelper.getUidByUinAsync(member.memberuin.toLong())
|
uid = member.uid
|
||||||
uin = member.memberuin.toLong()
|
uin = member.uin
|
||||||
nick = member.troopnick
|
nick = member.nick.ifEmpty {
|
||||||
.ifNullOrEmpty { member.hwName }
|
member.cardName
|
||||||
.ifNullOrEmpty { member.troopColorNick }
|
} ?: ""
|
||||||
.ifNullOrEmpty { member.friendnick } ?: ""
|
|
||||||
honorName = honor.honorName
|
honorName = honor.honorName
|
||||||
avatar = honor.honorIconUrl
|
avatar = honor.honorIconUrl
|
||||||
id = honor.honorId
|
id = honor.honorId
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
package kritor.service
|
package kritor.service
|
||||||
|
|
||||||
import com.tencent.mobileqq.qroute.QRoute
|
import com.tencent.mobileqq.qroute.QRoute
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.Contact
|
import com.tencent.qqnt.kernelpublic.nativeinterface.Contact
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.MsgRecord
|
import com.tencent.qqnt.kernel.nativeinterface.MsgRecord
|
||||||
import com.tencent.qqnt.msg.api.IMsgService
|
import com.tencent.qqnt.msg.api.IMsgService
|
||||||
import io.grpc.Status
|
import io.grpc.Status
|
||||||
import io.grpc.StatusRuntimeException
|
import io.grpc.StatusRuntimeException
|
||||||
import io.kritor.event.MessageEvent
|
import io.kritor.common.*
|
||||||
import io.kritor.message.*
|
import io.kritor.message.*
|
||||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
import kotlinx.coroutines.withTimeoutOrNull
|
import kotlinx.coroutines.withTimeoutOrNull
|
||||||
@ -21,9 +21,9 @@ import protobuf.message.routing.Grp
|
|||||||
import qq.service.QQInterfaces
|
import qq.service.QQInterfaces
|
||||||
import qq.service.contact.longPeer
|
import qq.service.contact.longPeer
|
||||||
import qq.service.internals.NTServiceFetcher
|
import qq.service.internals.NTServiceFetcher
|
||||||
|
import qq.service.msg.*
|
||||||
|
import qq.service.msg.ForwardMessageHelper
|
||||||
import qq.service.msg.MessageHelper
|
import qq.service.msg.MessageHelper
|
||||||
import qq.service.msg.NtMsgConvertor
|
|
||||||
import qq.service.msg.toKritorReqMessages
|
|
||||||
import kotlin.coroutines.resume
|
import kotlin.coroutines.resume
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
import kotlin.random.nextUInt
|
import kotlin.random.nextUInt
|
||||||
@ -54,7 +54,7 @@ internal object MessageService : MessageServiceGrpcKt.MessageServiceCoroutineImp
|
|||||||
uniseq
|
uniseq
|
||||||
).onFailure {
|
).onFailure {
|
||||||
throw StatusRuntimeException(Status.INTERNAL.withCause(it))
|
throw StatusRuntimeException(Status.INTERNAL.withCause(it))
|
||||||
}.getOrThrow()
|
}.getOrThrow().toString()
|
||||||
}.build()
|
}.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,8 +88,8 @@ internal object MessageService : MessageServiceGrpcKt.MessageServiceCoroutineImp
|
|||||||
return SendMessageByResIdResponse.newBuilder().build()
|
return SendMessageByResIdResponse.newBuilder().build()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Grpc("MessageService", "ClearMessages")
|
@Grpc("MessageService", "SetMessageReaded")
|
||||||
override suspend fun clearMessages(request: ClearMessagesRequest): ClearMessagesResponse {
|
override suspend fun setMessageReaded(request: SetMessageReadRequest): SetMessageReadResponse {
|
||||||
val contact = request.contact
|
val contact = request.contact
|
||||||
val kernelService = NTServiceFetcher.kernelService
|
val kernelService = NTServiceFetcher.kernelService
|
||||||
val sessionService = kernelService.wrapperSession
|
val sessionService = kernelService.wrapperSession
|
||||||
@ -103,8 +103,13 @@ internal object MessageService : MessageServiceGrpcKt.MessageServiceCoroutineImp
|
|||||||
Scene.STRANGER -> MsgConstant.KCHATTYPETEMPC2CFROMUNKNOWN
|
Scene.STRANGER -> MsgConstant.KCHATTYPETEMPC2CFROMUNKNOWN
|
||||||
Scene.UNRECOGNIZED -> throw StatusRuntimeException(Status.INVALID_ARGUMENT.withDescription("Unrecognized scene"))
|
Scene.UNRECOGNIZED -> throw StatusRuntimeException(Status.INVALID_ARGUMENT.withDescription("Unrecognized scene"))
|
||||||
}
|
}
|
||||||
service.clearMsgRecords(Contact(chatType, contact.peer, contact.subPeer), null)
|
service.clearMsgRecords(
|
||||||
return ClearMessagesResponse.newBuilder().build()
|
Contact(
|
||||||
|
chatType,
|
||||||
|
contact.peer,
|
||||||
|
contact.subPeer
|
||||||
|
), null)
|
||||||
|
return SetMessageReadResponse.newBuilder().build()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Grpc("MessageService", "RecallMessage")
|
@Grpc("MessageService", "RecallMessage")
|
||||||
@ -125,7 +130,7 @@ internal object MessageService : MessageServiceGrpcKt.MessageServiceCoroutineImp
|
|||||||
val kernelService = NTServiceFetcher.kernelService
|
val kernelService = NTServiceFetcher.kernelService
|
||||||
val sessionService = kernelService.wrapperSession
|
val sessionService = kernelService.wrapperSession
|
||||||
val service = sessionService.msgService
|
val service = sessionService.msgService
|
||||||
service.recallMsg(contact, arrayListOf(request.messageId)) { code, msg ->
|
service.recallMsg(contact, arrayListOf(request.messageId.toLong())) { code, msg ->
|
||||||
if (code != 0) {
|
if (code != 0) {
|
||||||
LogCenter.log("消息撤回失败: $code:$msg", Level.WARN)
|
LogCenter.log("消息撤回失败: $code:$msg", Level.WARN)
|
||||||
}
|
}
|
||||||
@ -152,7 +157,7 @@ internal object MessageService : MessageServiceGrpcKt.MessageServiceCoroutineImp
|
|||||||
val msg: MsgRecord = withTimeoutOrNull(5000) {
|
val msg: MsgRecord = withTimeoutOrNull(5000) {
|
||||||
val service = QRoute.api(IMsgService::class.java)
|
val service = QRoute.api(IMsgService::class.java)
|
||||||
suspendCancellableCoroutine { continuation ->
|
suspendCancellableCoroutine { continuation ->
|
||||||
service.getMsgsByMsgId(contact, arrayListOf(request.messageId)) { code, _, msgRecords ->
|
service.getMsgsByMsgId(contact, arrayListOf(request.messageId.toLong())) { code, _, msgRecords ->
|
||||||
if (code == 0 && msgRecords.isNotEmpty()) {
|
if (code == 0 && msgRecords.isNotEmpty()) {
|
||||||
continuation.resume(msgRecords.first())
|
continuation.resume(msgRecords.first())
|
||||||
} else {
|
} else {
|
||||||
@ -166,13 +171,13 @@ internal object MessageService : MessageServiceGrpcKt.MessageServiceCoroutineImp
|
|||||||
} ?: throw StatusRuntimeException(Status.NOT_FOUND.withDescription("Message not found"))
|
} ?: throw StatusRuntimeException(Status.NOT_FOUND.withDescription("Message not found"))
|
||||||
|
|
||||||
return GetMessageResponse.newBuilder().apply {
|
return GetMessageResponse.newBuilder().apply {
|
||||||
this.message = MessageEvent.newBuilder().apply {
|
this.message = PushMessageBody.newBuilder().apply {
|
||||||
this.messageId = msg.msgId
|
this.messageId = msg.msgId.toString()
|
||||||
this.contact = request.contact
|
this.contact = request.contact
|
||||||
this.sender = Sender.newBuilder().apply {
|
this.sender = Sender.newBuilder().apply {
|
||||||
|
this.uid = msg.senderUid ?: ""
|
||||||
this.uin = msg.senderUin
|
this.uin = msg.senderUin
|
||||||
this.nick = msg.sendNickName ?: ""
|
this.nick = msg.sendNickName ?: ""
|
||||||
this.uid = msg.senderUid ?: ""
|
|
||||||
}.build()
|
}.build()
|
||||||
this.messageSeq = msg.msgSeq
|
this.messageSeq = msg.msgSeq
|
||||||
this.addAllElements(msg.elements.toKritorReqMessages(contact))
|
this.addAllElements(msg.elements.toKritorReqMessages(contact))
|
||||||
@ -212,8 +217,8 @@ internal object MessageService : MessageServiceGrpcKt.MessageServiceCoroutineImp
|
|||||||
} ?: throw StatusRuntimeException(Status.NOT_FOUND.withDescription("Message not found"))
|
} ?: throw StatusRuntimeException(Status.NOT_FOUND.withDescription("Message not found"))
|
||||||
|
|
||||||
return GetMessageBySeqResponse.newBuilder().apply {
|
return GetMessageBySeqResponse.newBuilder().apply {
|
||||||
this.message = MessageEvent.newBuilder().apply {
|
this.message = PushMessageBody.newBuilder().apply {
|
||||||
this.messageId = msg.msgId
|
this.messageId = msg.msgId.toString()
|
||||||
this.contact = request.contact
|
this.contact = request.contact
|
||||||
this.sender = Sender.newBuilder().apply {
|
this.sender = Sender.newBuilder().apply {
|
||||||
this.uin = msg.senderUin
|
this.uin = msg.senderUin
|
||||||
@ -244,7 +249,7 @@ internal object MessageService : MessageServiceGrpcKt.MessageServiceCoroutineImp
|
|||||||
val msgs: List<MsgRecord> = withTimeoutOrNull(5000) {
|
val msgs: List<MsgRecord> = withTimeoutOrNull(5000) {
|
||||||
val service = QRoute.api(IMsgService::class.java)
|
val service = QRoute.api(IMsgService::class.java)
|
||||||
suspendCancellableCoroutine { continuation ->
|
suspendCancellableCoroutine { continuation ->
|
||||||
service.getMsgs(contact, request.startMessageId, request.count, true) { code, _, msgRecords ->
|
service.getMsgs(contact, request.startMessageId.toLong(), request.count, true) { code, _, msgRecords ->
|
||||||
if (code == 0 && msgRecords.isNotEmpty()) {
|
if (code == 0 && msgRecords.isNotEmpty()) {
|
||||||
continuation.resume(msgRecords)
|
continuation.resume(msgRecords)
|
||||||
} else {
|
} else {
|
||||||
@ -259,8 +264,8 @@ internal object MessageService : MessageServiceGrpcKt.MessageServiceCoroutineImp
|
|||||||
|
|
||||||
return GetHistoryMessageResponse.newBuilder().apply {
|
return GetHistoryMessageResponse.newBuilder().apply {
|
||||||
msgs.forEach {
|
msgs.forEach {
|
||||||
addMessages(MessageEvent.newBuilder().apply {
|
addMessages(PushMessageBody.newBuilder().apply {
|
||||||
this.messageId = it.msgId
|
this.messageId = it.msgId.toString()
|
||||||
this.contact = request.contact
|
this.contact = request.contact
|
||||||
this.sender = Sender.newBuilder().apply {
|
this.sender = Sender.newBuilder().apply {
|
||||||
this.uin = it.senderUin
|
this.uin = it.senderUin
|
||||||
@ -274,13 +279,83 @@ internal object MessageService : MessageServiceGrpcKt.MessageServiceCoroutineImp
|
|||||||
}.build()
|
}.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Grpc("MessageService", "DeleteEssenceMsg")
|
@Grpc("MessageService", "UploadForwardMessage")
|
||||||
override suspend fun deleteEssenceMsg(request: DeleteEssenceMsgRequest): DeleteEssenceMsgResponse {
|
override suspend fun uploadForwardMessage(request: UploadForwardMessageRequest): UploadForwardMessageResponse {
|
||||||
|
val contact = request.contact.let {
|
||||||
|
MessageHelper.generateContact(
|
||||||
|
when (it.scene!!) {
|
||||||
|
Scene.GROUP -> MsgConstant.KCHATTYPEGROUP
|
||||||
|
Scene.FRIEND -> MsgConstant.KCHATTYPEC2C
|
||||||
|
Scene.GUILD -> MsgConstant.KCHATTYPEGUILD
|
||||||
|
Scene.STRANGER_FROM_GROUP -> MsgConstant.KCHATTYPETEMPC2CFROMGROUP
|
||||||
|
Scene.NEARBY -> MsgConstant.KCHATTYPETEMPC2CFROMUNKNOWN
|
||||||
|
Scene.STRANGER -> MsgConstant.KCHATTYPETEMPC2CFROMUNKNOWN
|
||||||
|
Scene.UNRECOGNIZED -> throw StatusRuntimeException(Status.INVALID_ARGUMENT.withDescription("Unrecognized scene"))
|
||||||
|
}, it.peer, it.subPeer
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val forwardMessage = ForwardMessageHelper.uploadMultiMsg(
|
||||||
|
contact,
|
||||||
|
request.messagesList
|
||||||
|
).onFailure {
|
||||||
|
throw StatusRuntimeException(Status.INTERNAL.withCause(it))
|
||||||
|
}.getOrThrow()
|
||||||
|
|
||||||
|
return UploadForwardMessageResponse.newBuilder().apply {
|
||||||
|
this.resId = forwardMessage.resId
|
||||||
|
}.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Grpc("MessageService", "DownloadForwardMessage")
|
||||||
|
override suspend fun downloadForwardMessage(request: DownloadForwardMessageRequest): DownloadForwardMessageResponse {
|
||||||
|
return DownloadForwardMessageResponse.newBuilder().apply {
|
||||||
|
this.addAllMessages(
|
||||||
|
MessageHelper.getForwardMsg(request.resId).onFailure {
|
||||||
|
throw StatusRuntimeException(Status.INTERNAL.withCause(it))
|
||||||
|
}.getOrThrow().map { detail ->
|
||||||
|
PushMessageBody.newBuilder().apply {
|
||||||
|
this.time = detail.time.toLong()
|
||||||
|
this.messageId = detail.qqMsgId.toString()
|
||||||
|
this.messageSeq = detail.msgSeq
|
||||||
|
this.contact = io.kritor.common.Contact.newBuilder().apply {
|
||||||
|
this.scene = when (detail.msgType) {
|
||||||
|
MsgConstant.KCHATTYPEC2C -> Scene.FRIEND
|
||||||
|
MsgConstant.KCHATTYPEGROUP -> Scene.GROUP
|
||||||
|
MsgConstant.KCHATTYPEGUILD -> Scene.GUILD
|
||||||
|
MsgConstant.KCHATTYPETEMPC2CFROMGROUP -> Scene.STRANGER_FROM_GROUP
|
||||||
|
MsgConstant.KCHATTYPETEMPC2CFROMUNKNOWN -> Scene.NEARBY
|
||||||
|
else -> Scene.STRANGER
|
||||||
|
}
|
||||||
|
this.peer = detail.peerId.toString()
|
||||||
|
}.build()
|
||||||
|
this.sender = Sender.newBuilder().apply {
|
||||||
|
this.uin = detail.sender.userId
|
||||||
|
this.nick = detail.sender.nickName
|
||||||
|
this.uid = detail.sender.uid
|
||||||
|
}.build()
|
||||||
|
detail.message?.elements?.toKritorResponseMessages(
|
||||||
|
Contact(
|
||||||
|
detail.msgType,
|
||||||
|
detail.peerId.toString(),
|
||||||
|
null
|
||||||
|
)
|
||||||
|
)?.let {
|
||||||
|
this.addAllElements(it)
|
||||||
|
}
|
||||||
|
}.build()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Grpc("MessageService", "DeleteEssenceMessage")
|
||||||
|
override suspend fun deleteEssenceMessage(request: DeleteEssenceMessageRequest): DeleteEssenceMessageResponse {
|
||||||
val contact = MessageHelper.generateContact(MsgConstant.KCHATTYPEGROUP, request.groupId.toString())
|
val contact = MessageHelper.generateContact(MsgConstant.KCHATTYPEGROUP, request.groupId.toString())
|
||||||
val msg: MsgRecord = withTimeoutOrNull(5000) {
|
val msg: MsgRecord = withTimeoutOrNull(5000) {
|
||||||
val service = QRoute.api(IMsgService::class.java)
|
val service = QRoute.api(IMsgService::class.java)
|
||||||
suspendCancellableCoroutine { continuation ->
|
suspendCancellableCoroutine { continuation ->
|
||||||
service.getMsgsByMsgId(contact, arrayListOf(request.messageId)) { code, _, msgRecords ->
|
service.getMsgsByMsgId(contact, arrayListOf(request.messageId.toLong())) { code, _, msgRecords ->
|
||||||
if (code == 0 && msgRecords.isNotEmpty()) {
|
if (code == 0 && msgRecords.isNotEmpty()) {
|
||||||
continuation.resume(msgRecords.first())
|
continuation.resume(msgRecords.first())
|
||||||
} else {
|
} else {
|
||||||
@ -294,17 +369,17 @@ internal object MessageService : MessageServiceGrpcKt.MessageServiceCoroutineImp
|
|||||||
} ?: throw StatusRuntimeException(Status.NOT_FOUND.withDescription("Message not found"))
|
} ?: throw StatusRuntimeException(Status.NOT_FOUND.withDescription("Message not found"))
|
||||||
if (MessageHelper.deleteEssenceMessage(request.groupId, msg.msgSeq, msg.msgRandom) == null)
|
if (MessageHelper.deleteEssenceMessage(request.groupId, msg.msgSeq, msg.msgRandom) == null)
|
||||||
throw StatusRuntimeException(Status.NOT_FOUND.withDescription("delete essence message failed"))
|
throw StatusRuntimeException(Status.NOT_FOUND.withDescription("delete essence message failed"))
|
||||||
return DeleteEssenceMsgResponse.newBuilder().build()
|
return DeleteEssenceMessageResponse.newBuilder().build()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Grpc("MessageService", "GetEssenceMessages")
|
@Grpc("MessageService", "GetEssenceMessageList")
|
||||||
override suspend fun getEssenceMessages(request: GetEssenceMessagesRequest): GetEssenceMessagesResponse {
|
override suspend fun getEssenceMessageList(request: GetEssenceMessageListRequest): GetEssenceMessageListResponse {
|
||||||
val contact = MessageHelper.generateContact(MsgConstant.KCHATTYPEGROUP, request.groupId.toString())
|
val contact = MessageHelper.generateContact(MsgConstant.KCHATTYPEGROUP, request.groupId.toString())
|
||||||
return GetEssenceMessagesResponse.newBuilder().apply {
|
return GetEssenceMessageListResponse.newBuilder().apply {
|
||||||
MessageHelper.getEssenceMessageList(request.groupId, request.page, request.pageSize).onFailure {
|
MessageHelper.getEssenceMessageList(request.groupId, request.page, request.pageSize).onFailure {
|
||||||
throw StatusRuntimeException(Status.INTERNAL.withCause(it))
|
throw StatusRuntimeException(Status.INTERNAL.withCause(it))
|
||||||
}.getOrThrow().forEach {
|
}.getOrThrow().forEach {
|
||||||
addEssenceMessage(EssenceMessage.newBuilder().apply {
|
addMessages(EssenceMessageBody.newBuilder().apply {
|
||||||
withTimeoutOrNull(5000) {
|
withTimeoutOrNull(5000) {
|
||||||
val service = QRoute.api(IMsgService::class.java)
|
val service = QRoute.api(IMsgService::class.java)
|
||||||
suspendCancellableCoroutine { continuation ->
|
suspendCancellableCoroutine { continuation ->
|
||||||
@ -320,13 +395,13 @@ internal object MessageService : MessageServiceGrpcKt.MessageServiceCoroutineImp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}?.let {
|
}?.let {
|
||||||
this.messageId = it.msgId
|
this.messageId = it.msgId.toString()
|
||||||
}
|
}
|
||||||
this.messageSeq = it.messageSeq
|
this.messageSeq = it.messageSeq
|
||||||
this.msgTime = it.senderTime.toInt()
|
this.messageTime = it.senderTime
|
||||||
this.senderNick = it.senderNick
|
this.senderNick = it.senderNick
|
||||||
this.senderUin = it.senderId
|
this.senderUin = it.senderId
|
||||||
this.operationTime = it.operatorTime.toInt()
|
this.operationTime = it.operatorTime
|
||||||
this.operatorNick = it.operatorNick
|
this.operatorNick = it.operatorNick
|
||||||
this.operatorUin = it.operatorId
|
this.operatorUin = it.operatorId
|
||||||
this.jsonElements = it.messageContent.toString()
|
this.jsonElements = it.messageContent.toString()
|
||||||
@ -341,7 +416,7 @@ internal object MessageService : MessageServiceGrpcKt.MessageServiceCoroutineImp
|
|||||||
val msg: MsgRecord = withTimeoutOrNull(5000) {
|
val msg: MsgRecord = withTimeoutOrNull(5000) {
|
||||||
val service = QRoute.api(IMsgService::class.java)
|
val service = QRoute.api(IMsgService::class.java)
|
||||||
suspendCancellableCoroutine { continuation ->
|
suspendCancellableCoroutine { continuation ->
|
||||||
service.getMsgsByMsgId(contact, arrayListOf(request.messageId)) { code, _, msgRecords ->
|
service.getMsgsByMsgId(contact, arrayListOf(request.messageId.toLong())) { code, _, msgRecords ->
|
||||||
if (code == 0 && msgRecords.isNotEmpty()) {
|
if (code == 0 && msgRecords.isNotEmpty()) {
|
||||||
continuation.resume(msgRecords.first())
|
continuation.resume(msgRecords.first())
|
||||||
} else {
|
} else {
|
||||||
@ -359,8 +434,8 @@ internal object MessageService : MessageServiceGrpcKt.MessageServiceCoroutineImp
|
|||||||
return SetEssenceMessageResponse.newBuilder().build()
|
return SetEssenceMessageResponse.newBuilder().build()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Grpc("MessageService", "SetMessageCommentEmoji")
|
@Grpc("MessageService", "ReactMessageWithEmoji")
|
||||||
override suspend fun setMessageCommentEmoji(request: SetMessageCommentEmojiRequest): SetMessageCommentEmojiResponse {
|
override suspend fun reactMessageWithEmoji(request: ReactMessageWithEmojiRequest): ReactMessageWithEmojiResponse {
|
||||||
val contact = request.contact.let {
|
val contact = request.contact.let {
|
||||||
MessageHelper.generateContact(
|
MessageHelper.generateContact(
|
||||||
when (it.scene!!) {
|
when (it.scene!!) {
|
||||||
@ -377,7 +452,7 @@ internal object MessageService : MessageServiceGrpcKt.MessageServiceCoroutineImp
|
|||||||
val msg: MsgRecord = withTimeoutOrNull(5000) {
|
val msg: MsgRecord = withTimeoutOrNull(5000) {
|
||||||
val service = QRoute.api(IMsgService::class.java)
|
val service = QRoute.api(IMsgService::class.java)
|
||||||
suspendCancellableCoroutine { continuation ->
|
suspendCancellableCoroutine { continuation ->
|
||||||
service.getMsgsByMsgId(contact, arrayListOf(request.messageId)) { code, _, msgRecords ->
|
service.getMsgsByMsgId(contact, arrayListOf(request.messageId.toLong())) { code, _, msgRecords ->
|
||||||
if (code == 0 && msgRecords.isNotEmpty()) {
|
if (code == 0 && msgRecords.isNotEmpty()) {
|
||||||
continuation.resume(msgRecords.first())
|
continuation.resume(msgRecords.first())
|
||||||
} else {
|
} else {
|
||||||
@ -393,8 +468,8 @@ internal object MessageService : MessageServiceGrpcKt.MessageServiceCoroutineImp
|
|||||||
request.contact.longPeer(),
|
request.contact.longPeer(),
|
||||||
msg.msgSeq.toULong(),
|
msg.msgSeq.toULong(),
|
||||||
request.faceId.toString(),
|
request.faceId.toString(),
|
||||||
request.isComment
|
request.isSet
|
||||||
)
|
)
|
||||||
return SetMessageCommentEmojiResponse.newBuilder().build()
|
return ReactMessageWithEmojiResponse.newBuilder().build()
|
||||||
}
|
}
|
||||||
}
|
}
|
33
xposed/src/main/java/kritor/service/QsignService.kt
Normal file
33
xposed/src/main/java/kritor/service/QsignService.kt
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package kritor.service
|
||||||
|
|
||||||
|
import com.google.protobuf.ByteString
|
||||||
|
import com.tencent.mobileqq.fe.FEKit
|
||||||
|
import com.tencent.mobileqq.qsec.qsecdandelionsdk.Dandelion
|
||||||
|
import io.kritor.developer.*
|
||||||
|
|
||||||
|
|
||||||
|
internal object QsignService: QsignServiceGrpcKt.QsignServiceCoroutineImplBase() {
|
||||||
|
@Grpc("QsignService", "Sign")
|
||||||
|
override suspend fun sign(request: SignRequest): SignResponse {
|
||||||
|
return SignResponse.newBuilder().apply {
|
||||||
|
val result = FEKit.getInstance().getSign(request.command, request.buffer.toByteArray(), request.seq, request.uin)
|
||||||
|
this.secSig = ByteString.copyFrom(result.sign)
|
||||||
|
this.secDeviceToken = ByteString.copyFrom(result.token)
|
||||||
|
this.secExtra = ByteString.copyFrom(result.extra)
|
||||||
|
}.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Grpc("QsignService", "Energy")
|
||||||
|
override suspend fun energy(request: EnergyRequest): EnergyResponse {
|
||||||
|
return EnergyResponse.newBuilder().apply {
|
||||||
|
this.result = ByteString.copyFrom(Dandelion.getInstance().fly(request.data, request.salt.toByteArray()))
|
||||||
|
}.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Grpc("QsignService", "GetCmdWhitelist")
|
||||||
|
override suspend fun getCmdWhitelist(request: GetCmdWhitelistRequest): GetCmdWhitelistResponse {
|
||||||
|
return GetCmdWhitelistResponse.newBuilder().apply {
|
||||||
|
addAllCommands(FEKit.getInstance().cmdWhiteList)
|
||||||
|
}.build()
|
||||||
|
}
|
||||||
|
}
|
@ -20,6 +20,7 @@ private val configKeys = setOf(
|
|||||||
ResourceGroup,
|
ResourceGroup,
|
||||||
RPCAddress,
|
RPCAddress,
|
||||||
RPCPort,
|
RPCPort,
|
||||||
|
AliveReply,
|
||||||
)
|
)
|
||||||
|
|
||||||
internal object ShamrockConfig: Properties() {
|
internal object ShamrockConfig: Properties() {
|
||||||
|
@ -14,7 +14,10 @@ import moe.fuqiuluo.shamrock.tools.toast
|
|||||||
import moe.fuqiuluo.shamrock.xposed.helper.AppTalker
|
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.Calendar
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
import java.util.Timer
|
||||||
|
import java.util.TimerTask
|
||||||
|
|
||||||
internal enum class Level(
|
internal enum class Level(
|
||||||
val id: Byte
|
val id: Byte
|
||||||
@ -31,7 +34,29 @@ internal object LogCenter {
|
|||||||
// 格式化时间
|
// 格式化时间
|
||||||
SimpleDateFormat("yyyy-MM-dd").format(Date())
|
SimpleDateFormat("yyyy-MM-dd").format(Date())
|
||||||
}_"
|
}_"
|
||||||
private val LogFile = MobileQQ.getContext().getExternalFilesDir(null)!!
|
private var LogFile = generateLogFile()
|
||||||
|
|
||||||
|
private val format = SimpleDateFormat("[HH:mm:ss] ")
|
||||||
|
private val timer = Timer()
|
||||||
|
|
||||||
|
init {
|
||||||
|
val now = Calendar.getInstance()
|
||||||
|
val tomorrowMidnight = Calendar.getInstance().apply {
|
||||||
|
add(Calendar.DAY_OF_YEAR, 1)
|
||||||
|
set(Calendar.HOUR_OF_DAY, 0)
|
||||||
|
set(Calendar.MINUTE, 0)
|
||||||
|
set(Calendar.SECOND, 0)
|
||||||
|
set(Calendar.MILLISECOND, 0)
|
||||||
|
}
|
||||||
|
val delay = tomorrowMidnight.timeInMillis - now.timeInMillis
|
||||||
|
timer.scheduleAtFixedRate(object : TimerTask() {
|
||||||
|
override fun run() {
|
||||||
|
LogFile = generateLogFile()
|
||||||
|
}
|
||||||
|
}, delay, 24 * 60 * 60 * 1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateLogFile() = MobileQQ.getContext().getExternalFilesDir(null)!!
|
||||||
.parentFile!!.resolve("Tencent/Shamrock/log").also {
|
.parentFile!!.resolve("Tencent/Shamrock/log").also {
|
||||||
if (it.exists()) it.delete()
|
if (it.exists()) it.delete()
|
||||||
it.mkdirs()
|
it.mkdirs()
|
||||||
@ -49,8 +74,6 @@ internal object LogCenter {
|
|||||||
return@let result
|
return@let result
|
||||||
}
|
}
|
||||||
|
|
||||||
private val format = SimpleDateFormat("[HH:mm:ss] ")
|
|
||||||
|
|
||||||
fun log(string: String, level: Level = Level.INFO, toast: Boolean = false) {
|
fun log(string: String, level: Level = Level.INFO, toast: Boolean = false) {
|
||||||
if (!ShamrockConfig[DebugMode] && level == Level.DEBUG) {
|
if (!ShamrockConfig[DebugMode] && level == Level.DEBUG) {
|
||||||
return
|
return
|
||||||
|
@ -5,32 +5,35 @@ package moe.fuqiuluo.shamrock.internals
|
|||||||
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.MsgRecord
|
||||||
import io.kritor.event.*
|
import io.kritor.event.*
|
||||||
import io.kritor.message.Contact
|
import io.kritor.common.PushMessageBody
|
||||||
import io.kritor.message.Sender
|
import io.kritor.common.Contact
|
||||||
|
import io.kritor.common.Scene
|
||||||
|
import io.kritor.common.Sender
|
||||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||||
import kotlinx.coroutines.GlobalScope
|
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 qq.service.QQInterfaces
|
import qq.service.QQInterfaces
|
||||||
|
import qq.service.contact.ContactHelper
|
||||||
import qq.service.msg.toKritorEventMessages
|
import qq.service.msg.toKritorEventMessages
|
||||||
|
|
||||||
internal object GlobalEventTransmitter : QQInterfaces() {
|
internal object GlobalEventTransmitter : QQInterfaces() {
|
||||||
private val MessageEventFlow by lazy {
|
private val MessageEventFlow by lazy {
|
||||||
MutableSharedFlow<Pair<MsgRecord, MessageEvent>>()
|
MutableSharedFlow<Pair<MsgRecord, PushMessageBody>>()
|
||||||
}
|
}
|
||||||
private val noticeEventFlow by lazy {
|
private val noticeEventFlow by lazy {
|
||||||
MutableSharedFlow<NoticeEvent>()
|
MutableSharedFlow<NoticeEvent>()
|
||||||
}
|
}
|
||||||
private val requestEventFlow by lazy {
|
private val requestEventFlow by lazy {
|
||||||
MutableSharedFlow<RequestsEvent>()
|
MutableSharedFlow<RequestEvent>()
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun pushNotice(noticeEvent: NoticeEvent) = noticeEventFlow.emit(noticeEvent)
|
private suspend fun pushNotice(noticeEvent: NoticeEvent) = noticeEventFlow.emit(noticeEvent)
|
||||||
|
|
||||||
private suspend fun pushRequest(requestEvent: RequestsEvent) = requestEventFlow.emit(requestEvent)
|
private suspend fun pushRequest(requestEvent: RequestEvent) = requestEventFlow.emit(requestEvent)
|
||||||
|
|
||||||
private suspend fun transMessageEvent(record: MsgRecord, message: MessageEvent) =
|
private suspend fun transMessageEvent(record: MsgRecord, message: PushMessageBody) =
|
||||||
MessageEventFlow.emit(record to message)
|
MessageEventFlow.emit(record to message)
|
||||||
|
|
||||||
object MessageTransmitter {
|
object MessageTransmitter {
|
||||||
@ -38,12 +41,12 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
record: MsgRecord,
|
record: MsgRecord,
|
||||||
elements: ArrayList<MsgElement>,
|
elements: ArrayList<MsgElement>,
|
||||||
): Boolean {
|
): Boolean {
|
||||||
transMessageEvent(record, MessageEvent.newBuilder().apply {
|
transMessageEvent(record, PushMessageBody.newBuilder().apply {
|
||||||
this.time = record.msgTime.toInt()
|
this.time = record.msgTime
|
||||||
this.messageId = record.msgId
|
this.messageId = record.msgId.toString()
|
||||||
this.messageSeq = record.msgSeq
|
this.messageSeq = record.msgSeq
|
||||||
this.contact = Contact.newBuilder().apply {
|
this.contact = Contact.newBuilder().apply {
|
||||||
this.scene = scene
|
this.scene = Scene.GROUP
|
||||||
this.peer = record.peerUin.toString()
|
this.peer = record.peerUin.toString()
|
||||||
this.subPeer = record.peerUid
|
this.subPeer = record.peerUid
|
||||||
}.build()
|
}.build()
|
||||||
@ -61,13 +64,13 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
record: MsgRecord,
|
record: MsgRecord,
|
||||||
elements: ArrayList<MsgElement>,
|
elements: ArrayList<MsgElement>,
|
||||||
): Boolean {
|
): Boolean {
|
||||||
transMessageEvent(record, MessageEvent.newBuilder().apply {
|
transMessageEvent(record, PushMessageBody.newBuilder().apply {
|
||||||
this.time = record.msgTime.toInt()
|
this.time = record.msgTime
|
||||||
this.messageId = record.msgId
|
this.messageId = record.msgId.toString()
|
||||||
this.messageSeq = record.msgSeq
|
this.messageSeq = record.msgSeq
|
||||||
this.contact = Contact.newBuilder().apply {
|
this.contact = Contact.newBuilder().apply {
|
||||||
this.scene = scene
|
this.scene = Scene.FRIEND
|
||||||
this.peer = record.senderUin.toString()
|
this.peer = record.senderUid
|
||||||
this.subPeer = record.senderUid
|
this.subPeer = record.senderUid
|
||||||
}.build()
|
}.build()
|
||||||
this.sender = Sender.newBuilder().apply {
|
this.sender = Sender.newBuilder().apply {
|
||||||
@ -86,13 +89,13 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
groupCode: Long,
|
groupCode: Long,
|
||||||
fromNick: String,
|
fromNick: String,
|
||||||
): Boolean {
|
): Boolean {
|
||||||
transMessageEvent(record, MessageEvent.newBuilder().apply {
|
transMessageEvent(record, PushMessageBody.newBuilder().apply {
|
||||||
this.time = record.msgTime.toInt()
|
this.time = record.msgTime
|
||||||
this.messageId = record.msgId
|
this.messageId = record.msgId.toString()
|
||||||
this.messageSeq = record.msgSeq
|
this.messageSeq = record.msgSeq
|
||||||
this.contact = Contact.newBuilder().apply {
|
this.contact = Contact.newBuilder().apply {
|
||||||
this.scene = scene
|
this.scene = if (groupCode > 0) Scene.STRANGER_FROM_GROUP else Scene.STRANGER
|
||||||
this.peer = record.senderUin.toString()
|
this.peer = record.senderUid
|
||||||
this.subPeer = groupCode.toString()
|
this.subPeer = groupCode.toString()
|
||||||
}.build()
|
}.build()
|
||||||
this.sender = Sender.newBuilder().apply {
|
this.sender = Sender.newBuilder().apply {
|
||||||
@ -109,12 +112,12 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
record: MsgRecord,
|
record: MsgRecord,
|
||||||
elements: ArrayList<MsgElement>,
|
elements: ArrayList<MsgElement>,
|
||||||
): Boolean {
|
): Boolean {
|
||||||
transMessageEvent(record, MessageEvent.newBuilder().apply {
|
transMessageEvent(record, PushMessageBody.newBuilder().apply {
|
||||||
this.time = record.msgTime.toInt()
|
this.time = record.msgTime
|
||||||
this.messageId = record.msgId
|
this.messageId = record.msgId.toString()
|
||||||
this.messageSeq = record.msgSeq
|
this.messageSeq = record.msgSeq
|
||||||
this.contact = Contact.newBuilder().apply {
|
this.contact = Contact.newBuilder().apply {
|
||||||
this.scene = scene
|
this.scene = Scene.GUILD
|
||||||
this.peer = record.guildId ?: ""
|
this.peer = record.guildId ?: ""
|
||||||
this.subPeer = record.channelId ?: ""
|
this.subPeer = record.channelId ?: ""
|
||||||
}.build()
|
}.build()
|
||||||
@ -138,7 +141,8 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
*/
|
*/
|
||||||
suspend fun transPrivateFileEvent(
|
suspend fun transPrivateFileEvent(
|
||||||
msgTime: Long,
|
msgTime: Long,
|
||||||
userId: Long,
|
senderUid: String,
|
||||||
|
senderUin: Long,
|
||||||
fileId: String,
|
fileId: String,
|
||||||
fileSubId: String,
|
fileSubId: String,
|
||||||
fileName: String,
|
fileName: String,
|
||||||
@ -147,16 +151,17 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
url: String
|
url: String
|
||||||
): Boolean {
|
): Boolean {
|
||||||
pushNotice(NoticeEvent.newBuilder().apply {
|
pushNotice(NoticeEvent.newBuilder().apply {
|
||||||
this.type = NoticeType.FRIEND_FILE_COME
|
this.type = NoticeEvent.NoticeType.PRIVATE_FILE_UPLOADED
|
||||||
this.time = msgTime.toInt()
|
this.time = msgTime
|
||||||
this.friendFileCome = FriendFileComeNotice.newBuilder().apply {
|
this.privateFileUploaded = PrivateFileUploadedNotice.newBuilder().apply {
|
||||||
this.fileId = fileId
|
this.fileId = fileId
|
||||||
this.fileName = fileName
|
this.fileName = fileName
|
||||||
this.operator = userId
|
this.operatorUid = senderUid
|
||||||
|
this.operatorUin = senderUin
|
||||||
this.fileSize = fileSize
|
this.fileSize = fileSize
|
||||||
this.expireTime = expireTime.toInt()
|
this.expireTime = expireTime
|
||||||
this.fileSubId = fileSubId
|
this.fileSubId = fileSubId.toInt() // todo(这玩意真的是一个数字?)
|
||||||
this.url = url
|
this.fileUrl = url
|
||||||
}.build()
|
}.build()
|
||||||
}.build())
|
}.build())
|
||||||
return true
|
return true
|
||||||
@ -167,7 +172,8 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
*/
|
*/
|
||||||
suspend fun transGroupFileEvent(
|
suspend fun transGroupFileEvent(
|
||||||
msgTime: Long,
|
msgTime: Long,
|
||||||
userId: Long,
|
senderUid: String,
|
||||||
|
senderUin: Long,
|
||||||
groupId: Long,
|
groupId: Long,
|
||||||
uuid: String,
|
uuid: String,
|
||||||
fileName: String,
|
fileName: String,
|
||||||
@ -176,16 +182,17 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
url: String
|
url: String
|
||||||
): Boolean {
|
): Boolean {
|
||||||
pushNotice(NoticeEvent.newBuilder().apply {
|
pushNotice(NoticeEvent.newBuilder().apply {
|
||||||
this.type = NoticeType.GROUP_FILE_COME
|
this.type = NoticeEvent.NoticeType.GROUP_FILE_UPLOADED
|
||||||
this.time = msgTime.toInt()
|
this.time = msgTime
|
||||||
this.groupFileCome = GroupFileComeNotice.newBuilder().apply {
|
this.groupFileUploaded = GroupFileUploadedNotice.newBuilder().apply {
|
||||||
this.groupId = groupId
|
this.groupId = groupId
|
||||||
this.operator = userId
|
this.operatorUid = senderUid
|
||||||
|
this.operatorUin = senderUin
|
||||||
this.fileId = uuid
|
this.fileId = uuid
|
||||||
this.fileName = fileName
|
this.fileName = fileName
|
||||||
this.fileSize = fileSize
|
this.fileSize = fileSize
|
||||||
this.biz = bizId
|
this.fileSubId = bizId
|
||||||
this.url = url
|
this.fileUrl = url
|
||||||
}.build()
|
}.build()
|
||||||
}.build())
|
}.build())
|
||||||
return true
|
return true
|
||||||
@ -199,19 +206,19 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
suspend fun transGroupSign(
|
suspend fun transGroupSign(
|
||||||
time: Long,
|
time: Long,
|
||||||
target: Long,
|
target: Long,
|
||||||
action: String?,
|
action: String,
|
||||||
rankImg: String?,
|
rankImg: String,
|
||||||
groupCode: Long
|
groupCode: Long
|
||||||
): Boolean {
|
): Boolean {
|
||||||
pushNotice(NoticeEvent.newBuilder().apply {
|
pushNotice(NoticeEvent.newBuilder().apply {
|
||||||
this.type = NoticeType.GROUP_SIGN
|
this.type = NoticeEvent.NoticeType.GROUP_SIGN_IN
|
||||||
this.time = time.toInt()
|
this.time = time
|
||||||
this.groupSign = GroupSignNotice.newBuilder().apply {
|
this.groupSignIn = GroupSignInNotice.newBuilder().apply {
|
||||||
this.groupId = groupCode
|
this.groupId = groupCode
|
||||||
|
this.targetUid = ContactHelper.getUidByUinAsync(target)
|
||||||
this.targetUin = target
|
this.targetUin = target
|
||||||
this.action = action ?: ""
|
this.action = action
|
||||||
this.suffix = ""
|
this.rankImage = rankImg
|
||||||
this.rankImage = rankImg ?: ""
|
|
||||||
}.build()
|
}.build()
|
||||||
}.build())
|
}.build())
|
||||||
return true
|
return true
|
||||||
@ -221,20 +228,23 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
time: Long,
|
time: Long,
|
||||||
operator: Long,
|
operator: Long,
|
||||||
target: Long,
|
target: Long,
|
||||||
action: String?,
|
action: String,
|
||||||
suffix: String?,
|
suffix: String,
|
||||||
actionImg: String?,
|
actionImg: String,
|
||||||
groupCode: Long
|
groupCode: Long
|
||||||
): Boolean {
|
): Boolean {
|
||||||
pushNotice(NoticeEvent.newBuilder().apply {
|
pushNotice(NoticeEvent.newBuilder().apply {
|
||||||
this.type = NoticeType.GROUP_POKE
|
this.type = NoticeEvent.NoticeType.GROUP_POKE
|
||||||
this.time = time.toInt()
|
this.time = time
|
||||||
this.groupPoke = GroupPokeNotice.newBuilder().apply {
|
this.groupPoke = GroupPokeNotice.newBuilder().apply {
|
||||||
this.action = action ?: ""
|
this.groupId = groupCode
|
||||||
this.target = target
|
this.action = action
|
||||||
this.operator = operator
|
this.targetUid = ContactHelper.getUidByUinAsync(target)
|
||||||
this.suffix = suffix ?: ""
|
this.targetUin = target
|
||||||
this.actionImage = actionImg ?: ""
|
this.operatorUid = ContactHelper.getUidByUinAsync(operator)
|
||||||
|
this.operatorUin = operator
|
||||||
|
this.suffix = suffix
|
||||||
|
this.actionImage = actionImg
|
||||||
}.build()
|
}.build()
|
||||||
}.build())
|
}.build())
|
||||||
return true
|
return true
|
||||||
@ -247,11 +257,11 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
groupCode: Long,
|
groupCode: Long,
|
||||||
operator: Long,
|
operator: Long,
|
||||||
operatorUid: String,
|
operatorUid: String,
|
||||||
type: GroupMemberIncreasedType
|
type: GroupMemberIncreasedNotice.GroupMemberIncreasedType
|
||||||
): Boolean {
|
): Boolean {
|
||||||
pushNotice(NoticeEvent.newBuilder().apply {
|
pushNotice(NoticeEvent.newBuilder().apply {
|
||||||
this.type = NoticeType.GROUP_MEMBER_INCREASE
|
this.type = NoticeEvent.NoticeType.GROUP_MEMBER_INCREASE
|
||||||
this.time = time.toInt()
|
this.time = time
|
||||||
this.groupMemberIncrease = GroupMemberIncreasedNotice.newBuilder().apply {
|
this.groupMemberIncrease = GroupMemberIncreasedNotice.newBuilder().apply {
|
||||||
this.groupId = groupCode
|
this.groupId = groupCode
|
||||||
this.operatorUid = operatorUid
|
this.operatorUid = operatorUid
|
||||||
@ -271,11 +281,11 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
groupCode: Long,
|
groupCode: Long,
|
||||||
operator: Long,
|
operator: Long,
|
||||||
operatorUid: String,
|
operatorUid: String,
|
||||||
type: GroupMemberDecreasedType
|
type: GroupMemberDecreasedNotice.GroupMemberDecreasedType
|
||||||
): Boolean {
|
): Boolean {
|
||||||
pushNotice(NoticeEvent.newBuilder().apply {
|
pushNotice(NoticeEvent.newBuilder().apply {
|
||||||
this.type = NoticeType.GROUP_MEMBER_INCREASE
|
this.type = NoticeEvent.NoticeType.GROUP_MEMBER_DECREASE
|
||||||
this.time = time.toInt()
|
this.time = time
|
||||||
this.groupMemberDecrease = GroupMemberDecreasedNotice.newBuilder().apply {
|
this.groupMemberDecrease = GroupMemberDecreasedNotice.newBuilder().apply {
|
||||||
this.groupId = groupCode
|
this.groupId = groupCode
|
||||||
this.operatorUid = operatorUid
|
this.operatorUid = operatorUid
|
||||||
@ -296,8 +306,8 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
setAdmin: Boolean
|
setAdmin: Boolean
|
||||||
): Boolean {
|
): Boolean {
|
||||||
pushNotice(NoticeEvent.newBuilder().apply {
|
pushNotice(NoticeEvent.newBuilder().apply {
|
||||||
this.type = NoticeType.GROUP_ADMIN_CHANGED
|
this.type = NoticeEvent.NoticeType.GROUP_ADMIN_CHANGED
|
||||||
this.time = msgTime.toInt()
|
this.time = msgTime
|
||||||
this.groupAdminChanged = GroupAdminChangedNotice.newBuilder().apply {
|
this.groupAdminChanged = GroupAdminChangedNotice.newBuilder().apply {
|
||||||
this.groupId = groupCode
|
this.groupId = groupCode
|
||||||
this.targetUid = targetUid
|
this.targetUid = targetUid
|
||||||
@ -310,17 +320,19 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
|
|
||||||
suspend fun transGroupWholeBan(
|
suspend fun transGroupWholeBan(
|
||||||
msgTime: Long,
|
msgTime: Long,
|
||||||
operator: Long,
|
|
||||||
groupCode: Long,
|
groupCode: Long,
|
||||||
|
operatorUid: String,
|
||||||
|
operator: Long,
|
||||||
isOpen: Boolean
|
isOpen: Boolean
|
||||||
): Boolean {
|
): Boolean {
|
||||||
pushNotice(NoticeEvent.newBuilder().apply {
|
pushNotice(NoticeEvent.newBuilder().apply {
|
||||||
this.type = NoticeType.GROUP_WHOLE_BAN
|
this.type = NoticeEvent.NoticeType.GROUP_WHOLE_BAN
|
||||||
this.time = msgTime.toInt()
|
this.time = msgTime
|
||||||
this.groupWholeBan = GroupWholeBanNotice.newBuilder().apply {
|
this.groupWholeBan = GroupWholeBanNotice.newBuilder().apply {
|
||||||
this.groupId = groupCode
|
this.groupId = groupCode
|
||||||
this.isWholeBan = isOpen
|
this.isBan = isOpen
|
||||||
this.operator = operator
|
this.operatorUid = operatorUid
|
||||||
|
this.operatorUin = operator
|
||||||
}.build()
|
}.build()
|
||||||
}.build())
|
}.build())
|
||||||
return true
|
return true
|
||||||
@ -336,17 +348,17 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
duration: Int
|
duration: Int
|
||||||
): Boolean {
|
): Boolean {
|
||||||
pushNotice(NoticeEvent.newBuilder().apply {
|
pushNotice(NoticeEvent.newBuilder().apply {
|
||||||
this.type = NoticeType.GROUP_MEMBER_BANNED
|
this.type = NoticeEvent.NoticeType.GROUP_MEMBER_BAN
|
||||||
this.time = msgTime.toInt()
|
this.time = msgTime
|
||||||
this.groupMemberBanned = GroupMemberBannedNotice.newBuilder().apply {
|
this.groupMemberBan = GroupMemberBanNotice.newBuilder().apply {
|
||||||
this.groupId = groupCode
|
this.groupId = groupCode
|
||||||
this.operatorUid = operatorUid
|
this.operatorUid = operatorUid
|
||||||
this.operatorUin = operator
|
this.operatorUin = operator
|
||||||
this.targetUid = targetUid
|
this.targetUid = targetUid
|
||||||
this.targetUin = target
|
this.targetUin = target
|
||||||
this.duration = duration
|
this.duration = duration
|
||||||
this.type = if (duration > 0) GroupMemberBanType.BAN
|
this.type = if (duration > 0) GroupMemberBanNotice.GroupMemberBanType.BAN
|
||||||
else GroupMemberBanType.LIFT_BAN
|
else GroupMemberBanNotice.GroupMemberBanType.LIFT_BAN
|
||||||
}.build()
|
}.build()
|
||||||
}.build())
|
}.build())
|
||||||
return true
|
return true
|
||||||
@ -363,15 +375,15 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
tipText: String
|
tipText: String
|
||||||
): Boolean {
|
): Boolean {
|
||||||
pushNotice(NoticeEvent.newBuilder().apply {
|
pushNotice(NoticeEvent.newBuilder().apply {
|
||||||
this.type = NoticeType.GROUP_RECALL
|
this.type = NoticeEvent.NoticeType.GROUP_RECALL
|
||||||
this.time = time.toInt()
|
this.time = time
|
||||||
this.groupRecall = GroupRecallNotice.newBuilder().apply {
|
this.groupRecall = GroupRecallNotice.newBuilder().apply {
|
||||||
this.groupId = groupCode
|
this.groupId = groupCode
|
||||||
this.operatorUid = operatorUid
|
this.operatorUid = operatorUid
|
||||||
this.operatorUin = operator
|
this.operatorUin = operator
|
||||||
this.targetUid = targetUid
|
this.targetUid = targetUid
|
||||||
this.targetUin = target
|
this.targetUin = target
|
||||||
this.messageId = msgId
|
this.messageId = msgId.toString()
|
||||||
this.tipText = tipText
|
this.tipText = tipText
|
||||||
}.build()
|
}.build()
|
||||||
}.build())
|
}.build())
|
||||||
@ -381,26 +393,34 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
suspend fun transCardChange(
|
suspend fun transCardChange(
|
||||||
time: Long,
|
time: Long,
|
||||||
targetId: Long,
|
targetId: Long,
|
||||||
oldCard: String,
|
|
||||||
newCard: String,
|
newCard: String,
|
||||||
groupId: Long
|
groupId: Long
|
||||||
): Boolean {
|
): Boolean {
|
||||||
|
pushNotice(NoticeEvent.newBuilder().apply {
|
||||||
|
this.type = NoticeEvent.NoticeType.GROUP_CARD_CHANGED
|
||||||
|
this.time = time
|
||||||
|
this.groupCardChanged = GroupCardChangedNotice.newBuilder().apply {
|
||||||
|
this.groupId = groupId
|
||||||
|
this.targetUin = targetId
|
||||||
|
this.newCard = newCard
|
||||||
|
}.build()
|
||||||
|
}.build())
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun transTitleChange(
|
suspend fun transTitleChange(
|
||||||
time: Long,
|
time: Long,
|
||||||
targetId: Long,
|
targetUin: Long,
|
||||||
title: String,
|
title: String,
|
||||||
groupId: Long
|
groupId: Long
|
||||||
): Boolean {
|
): Boolean {
|
||||||
pushNotice(NoticeEvent.newBuilder().apply {
|
pushNotice(NoticeEvent.newBuilder().apply {
|
||||||
this.type = NoticeType.GROUP_MEMBER_UNIQUE_TITLE_CHANGED
|
this.type = NoticeEvent.NoticeType.GROUP_MEMBER_UNIQUE_TITLE_CHANGED
|
||||||
this.time = time.toInt()
|
this.time = time
|
||||||
this.groupMemberUniqueTitleChanged = GroupUniqueTitleChangedNotice.newBuilder().apply {
|
this.groupMemberUniqueTitleChanged = GroupUniqueTitleChangedNotice.newBuilder().apply {
|
||||||
this.groupId = groupId
|
this.groupId = groupId
|
||||||
this.target = targetId
|
this.targetUid = ContactHelper.getUidByUinAsync(targetUin)
|
||||||
|
this.targetUin = targetUin
|
||||||
this.title = title
|
this.title = title
|
||||||
}.build()
|
}.build()
|
||||||
}.build())
|
}.build())
|
||||||
@ -416,14 +436,16 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
subType: UInt
|
subType: UInt
|
||||||
): Boolean {
|
): Boolean {
|
||||||
pushNotice(NoticeEvent.newBuilder().apply {
|
pushNotice(NoticeEvent.newBuilder().apply {
|
||||||
this.type = NoticeType.GROUP_ESSENCE_CHANGED
|
this.type = NoticeEvent.NoticeType.GROUP_ESSENCE_CHANGED
|
||||||
this.time = time.toInt()
|
this.time = time
|
||||||
this.groupEssenceChanged = EssenceMessageNotice.newBuilder().apply {
|
this.groupEssenceChanged = GroupEssenceMessageNotice.newBuilder().apply {
|
||||||
this.groupId = groupId
|
this.groupId = groupId
|
||||||
this.messageId = msgId
|
this.messageId = msgId.toString()
|
||||||
this.sender = senderUin
|
this.targetUid = ContactHelper.getUidByUinAsync(targetUin)
|
||||||
this.operator = operatorUin
|
this.targetUin = senderUin
|
||||||
this.subType = subType.toInt()
|
this.operatorUid = ContactHelper.getUidByUinAsync(operatorUin)
|
||||||
|
this.operatorUin = operatorUin
|
||||||
|
this.isSet = subType.toInt() == 1
|
||||||
}.build()
|
}.build()
|
||||||
}.build())
|
}.build())
|
||||||
return true
|
return true
|
||||||
@ -437,18 +459,17 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
suspend fun transPrivatePoke(
|
suspend fun transPrivatePoke(
|
||||||
msgTime: Long,
|
msgTime: Long,
|
||||||
operator: Long,
|
operator: Long,
|
||||||
target: Long,
|
|
||||||
action: String?,
|
action: String?,
|
||||||
suffix: String?,
|
suffix: String?,
|
||||||
actionImg: String?
|
actionImg: String?
|
||||||
): Boolean {
|
): Boolean {
|
||||||
pushNotice(NoticeEvent.newBuilder().apply {
|
pushNotice(NoticeEvent.newBuilder().apply {
|
||||||
this.type = NoticeType.FRIEND_POKE
|
this.type = NoticeEvent.NoticeType.PRIVATE_POKE
|
||||||
this.time = msgTime.toInt()
|
this.time = msgTime
|
||||||
this.friendPoke = FriendPokeNotice.newBuilder().apply {
|
this.privatePoke = PrivatePokeNotice.newBuilder().apply {
|
||||||
this.action = action ?: ""
|
this.action = action ?: ""
|
||||||
this.target = target
|
this.operatorUid = ContactHelper.getUidByUinAsync(operator)
|
||||||
this.operator = operator
|
this.operatorUin = operator
|
||||||
this.suffix = suffix ?: ""
|
this.suffix = suffix ?: ""
|
||||||
this.actionImage = actionImg ?: ""
|
this.actionImage = actionImg ?: ""
|
||||||
}.build()
|
}.build()
|
||||||
@ -458,11 +479,11 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
|
|
||||||
suspend fun transPrivateRecall(time: Long, operator: Long, msgId: Long, tipText: String): Boolean {
|
suspend fun transPrivateRecall(time: Long, operator: Long, msgId: Long, tipText: String): Boolean {
|
||||||
pushNotice(NoticeEvent.newBuilder().apply {
|
pushNotice(NoticeEvent.newBuilder().apply {
|
||||||
this.type = NoticeType.FRIEND_RECALL
|
this.type = NoticeEvent.NoticeType.PRIVATE_RECALL
|
||||||
this.time = time.toInt()
|
this.time = time
|
||||||
this.friendRecall = FriendRecallNotice.newBuilder().apply {
|
this.privateRecall = PrivateRecallNotice.newBuilder().apply {
|
||||||
this.operator = operator
|
this.operatorUin = operator
|
||||||
this.messageId = msgId
|
this.messageId = msgId.toString()
|
||||||
this.tipText = tipText
|
this.tipText = tipText
|
||||||
}.build()
|
}.build()
|
||||||
}.build())
|
}.build())
|
||||||
@ -475,14 +496,15 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
* 请求 通知器
|
* 请求 通知器
|
||||||
*/
|
*/
|
||||||
object RequestTransmitter {
|
object RequestTransmitter {
|
||||||
suspend fun transFriendApp(time: Long, operator: Long, tipText: String, flag: String): Boolean {
|
suspend fun transFriendApp(time: Long, applierUid: String, operator: Long, tipText: String, flag: String): Boolean {
|
||||||
pushRequest(RequestsEvent.newBuilder().apply {
|
pushRequest(RequestEvent.newBuilder().apply {
|
||||||
this.type = RequestType.FRIEND_APPLY
|
this.type = RequestEvent.RequestType.FRIEND_APPLY
|
||||||
this.time = time.toInt()
|
this.time = time
|
||||||
|
this.requestId = flag
|
||||||
this.friendApply = FriendApplyRequest.newBuilder().apply {
|
this.friendApply = FriendApplyRequest.newBuilder().apply {
|
||||||
|
this.applierUid = applierUid
|
||||||
this.applierUin = operator
|
this.applierUin = operator
|
||||||
this.message = tipText
|
this.message = tipText
|
||||||
this.flag = flag
|
|
||||||
}.build()
|
}.build()
|
||||||
}.build())
|
}.build())
|
||||||
return true
|
return true
|
||||||
@ -490,30 +512,48 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
|
|
||||||
suspend fun transGroupApply(
|
suspend fun transGroupApply(
|
||||||
time: Long,
|
time: Long,
|
||||||
applier: Long,
|
applierUin: Long,
|
||||||
applierUid: String,
|
applierUid: String,
|
||||||
reason: String,
|
reason: String,
|
||||||
groupCode: Long,
|
groupCode: Long,
|
||||||
flag: String,
|
flag: String
|
||||||
type: GroupApplyType
|
|
||||||
): Boolean {
|
): Boolean {
|
||||||
pushRequest(RequestsEvent.newBuilder().apply {
|
pushRequest(RequestEvent.newBuilder().apply {
|
||||||
this.type = RequestType.GROUP_APPLY
|
this.type = RequestEvent.RequestType.GROUP_APPLY
|
||||||
this.time = time.toInt()
|
this.time = time
|
||||||
|
this.requestId = flag
|
||||||
this.groupApply = GroupApplyRequest.newBuilder().apply {
|
this.groupApply = GroupApplyRequest.newBuilder().apply {
|
||||||
this.applierUid = applierUid
|
this.applierUid = applierUid
|
||||||
this.applierUin = applier
|
this.applierUin = applierUin
|
||||||
this.groupId = groupCode
|
this.groupId = groupCode
|
||||||
this.reason = reason
|
this.reason = reason
|
||||||
this.flag = flag
|
}.build()
|
||||||
this.type = type
|
}.build())
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun transGroupInvite(
|
||||||
|
time: Long,
|
||||||
|
inviterUid: String,
|
||||||
|
inviterUin: Long,
|
||||||
|
groupCode: Long,
|
||||||
|
flag: String
|
||||||
|
): Boolean {
|
||||||
|
pushRequest(RequestEvent.newBuilder().apply {
|
||||||
|
this.type = RequestEvent.RequestType.GROUP_APPLY
|
||||||
|
this.time = time
|
||||||
|
this.requestId = flag
|
||||||
|
this.invitedGroup = InvitedJoinGroupRequest.newBuilder().apply {
|
||||||
|
this.inviterUid = inviterUid
|
||||||
|
this.inviterUin = inviterUin
|
||||||
|
this.groupId = groupCode
|
||||||
}.build()
|
}.build()
|
||||||
}.build())
|
}.build())
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend inline fun onMessageEvent(collector: FlowCollector<Pair<MsgRecord, MessageEvent>>) {
|
suspend inline fun onMessageEvent(collector: FlowCollector<Pair<MsgRecord, PushMessageBody>>) {
|
||||||
MessageEventFlow.collect {
|
MessageEventFlow.collect {
|
||||||
GlobalScope.launch {
|
GlobalScope.launch {
|
||||||
collector.emit(it)
|
collector.emit(it)
|
||||||
@ -529,7 +569,7 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend inline fun onRequestEvent(collector: FlowCollector<RequestsEvent>) {
|
suspend inline fun onRequestEvent(collector: FlowCollector<RequestEvent>) {
|
||||||
requestEventFlow.collect {
|
requestEventFlow.collect {
|
||||||
GlobalScope.launch {
|
GlobalScope.launch {
|
||||||
collector.emit(it)
|
collector.emit(it)
|
||||||
|
33
xposed/src/main/java/moe/fuqiuluo/shamrock/tools/Trpc.kt
Normal file
33
xposed/src/main/java/moe/fuqiuluo/shamrock/tools/Trpc.kt
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package moe.fuqiuluo.shamrock.tools
|
||||||
|
|
||||||
|
import com.tencent.qphone.base.remote.FromServiceMsg
|
||||||
|
import moe.fuqiuluo.shamrock.helper.Level
|
||||||
|
import moe.fuqiuluo.shamrock.helper.LogCenter
|
||||||
|
import moe.fuqiuluo.shamrock.utils.DeflateTools
|
||||||
|
import moe.fuqiuluo.symbols.decodeProtobuf
|
||||||
|
import protobuf.oidb.TrpcOidb
|
||||||
|
import tencent.im.oidb.oidb_sso
|
||||||
|
|
||||||
|
fun FromServiceMsg.decodeToOidb(): oidb_sso.OIDBSSOPkg {
|
||||||
|
return kotlin.runCatching {
|
||||||
|
oidb_sso.OIDBSSOPkg().mergeFrom(wupBuffer.slice(4).let {
|
||||||
|
if (it[0] == 0x78.toByte()) DeflateTools.uncompress(it) else it
|
||||||
|
})
|
||||||
|
}.getOrElse {
|
||||||
|
oidb_sso.OIDBSSOPkg().mergeFrom(wupBuffer.let {
|
||||||
|
if (it[0] == 0x78.toByte()) DeflateTools.uncompress(it) else it
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun FromServiceMsg.decodeToTrpcOidb(): TrpcOidb {
|
||||||
|
return kotlin.runCatching {
|
||||||
|
wupBuffer.slice(4).let {
|
||||||
|
if (it[0] == 0x78.toByte()) DeflateTools.uncompress(it) else it
|
||||||
|
}.decodeProtobuf<TrpcOidb>()
|
||||||
|
}.getOrElse {
|
||||||
|
wupBuffer.let {
|
||||||
|
if (it[0] == 0x78.toByte()) DeflateTools.uncompress(it) else it
|
||||||
|
}.decodeProtobuf<TrpcOidb>()
|
||||||
|
}
|
||||||
|
}
|
@ -6,17 +6,21 @@ import android.content.Context
|
|||||||
import android.content.Context.BATTERY_SERVICE
|
import android.content.Context.BATTERY_SERVICE
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.IntentFilter
|
import android.content.IntentFilter
|
||||||
|
import android.content.pm.ApplicationInfo
|
||||||
import android.content.pm.PackageInfo
|
import android.content.pm.PackageInfo
|
||||||
import android.os.BatteryManager
|
import android.os.BatteryManager
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Process
|
import android.os.Process
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
import moe.fuqiuluo.shamrock.tools.ShamrockVersion
|
||||||
import mqq.app.MobileQQ
|
import mqq.app.MobileQQ
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
|
|
||||||
internal object PlatformUtils {
|
internal object PlatformUtils {
|
||||||
const val QQ_9_0_8_VER = 5540
|
const val QQ_9_0_8_VER = 5540
|
||||||
|
const val QQ_9_0_65_VER = 6566
|
||||||
|
|
||||||
fun getQUA(): String {
|
fun getQUA(): String {
|
||||||
return "V1_AND_SQ_${getQQVersion(MobileQQ.getContext())}_${getQQVersionCode()}_YYB_D"
|
return "V1_AND_SQ_${getQQVersion(MobileQQ.getContext())}_${getQQVersionCode()}_YYB_D"
|
||||||
@ -69,6 +73,15 @@ internal object PlatformUtils {
|
|||||||
return MobileQQ.getMobileQQ().qqProcessName == "com.tencent.tim"
|
return MobileQQ.getMobileQQ().qqProcessName == "com.tencent.tim"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun isApkInDebug(context: Context): Boolean {
|
||||||
|
try {
|
||||||
|
val info = context.applicationInfo
|
||||||
|
return (info.flags and ApplicationInfo.FLAG_DEBUGGABLE) != 0
|
||||||
|
} catch (e: Exception) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun killProcess(context: Context, processName: String) {
|
fun killProcess(context: Context, processName: String) {
|
||||||
for (processInfo in (context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager).runningAppProcesses) {
|
for (processInfo in (context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager).runningAppProcesses) {
|
||||||
if (processInfo.processName == processName) {
|
if (processInfo.processName == processName) {
|
||||||
|
@ -39,7 +39,7 @@ class AntiDetection: IAction {
|
|||||||
if (ShamrockConfig[AntiJvmTrace])
|
if (ShamrockConfig[AntiJvmTrace])
|
||||||
antiTrace()
|
antiTrace()
|
||||||
antiMemoryWalking()
|
antiMemoryWalking()
|
||||||
antiO3Report()
|
//antiO3Report()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun antiO3Report() {
|
private fun antiO3Report() {
|
||||||
|
@ -9,11 +9,13 @@ import qq.service.QQInterfaces
|
|||||||
|
|
||||||
object SwitchStatus: IInteract, QQInterfaces() {
|
object SwitchStatus: IInteract, QQInterfaces() {
|
||||||
override fun invoke(intent: Intent) {
|
override fun invoke(intent: Intent) {
|
||||||
AppTalker.talk("switch_status") {
|
if (app.isLogin) {
|
||||||
put("account", app.currentAccountUin)
|
AppTalker.talk("switch_status") {
|
||||||
put("nickname", if (app is QQAppInterface) app.currentNickname else "unknown")
|
put("account", app.currentAccountUin)
|
||||||
put("voice", NativeLoader.isVoiceLoaded)
|
put("nickname", if (app is QQAppInterface) (app.currentNickname ?: "unknown") else "unknown")
|
||||||
put("core_version", ShamrockVersion)
|
put("voice", NativeLoader.isVoiceLoaded)
|
||||||
|
put("core_version", ShamrockVersion)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,7 +5,7 @@ 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.kernelpublic.nativeinterface.Contact
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.FileTransNotifyInfo
|
import com.tencent.qqnt.kernel.nativeinterface.FileTransNotifyInfo
|
||||||
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
|
||||||
@ -20,9 +20,12 @@ import kotlinx.coroutines.suspendCancellableCoroutine
|
|||||||
import kotlinx.coroutines.withTimeoutOrNull
|
import kotlinx.coroutines.withTimeoutOrNull
|
||||||
import moe.fuqiuluo.shamrock.config.ResourceGroup
|
import moe.fuqiuluo.shamrock.config.ResourceGroup
|
||||||
import moe.fuqiuluo.shamrock.config.ShamrockConfig
|
import moe.fuqiuluo.shamrock.config.ShamrockConfig
|
||||||
|
import moe.fuqiuluo.shamrock.helper.LogCenter
|
||||||
|
import moe.fuqiuluo.shamrock.tools.decodeToTrpcOidb
|
||||||
import moe.fuqiuluo.shamrock.tools.hex2ByteArray
|
import moe.fuqiuluo.shamrock.tools.hex2ByteArray
|
||||||
import moe.fuqiuluo.shamrock.tools.ifNullOrEmpty
|
import moe.fuqiuluo.shamrock.tools.ifNullOrEmpty
|
||||||
import moe.fuqiuluo.shamrock.tools.slice
|
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
|
||||||
@ -34,6 +37,8 @@ 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
|
||||||
@ -283,6 +288,44 @@ internal object NtV2RichMediaSvc: QQInterfaces() {
|
|||||||
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()
|
||||||
|
if (trpc.buffer == null) {
|
||||||
|
return Result.failure(Exception("failed to fetch NtTempRKey: ${trpc.msg}"))
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
*/
|
*/
|
||||||
@ -351,9 +394,14 @@ internal object NtV2RichMediaSvc: QQInterfaces() {
|
|||||||
).toByteArray()
|
).toByteArray()
|
||||||
val fromServiceMsg = sendOidbAW("OidbSvcTrpcTcp.0x11c5_200", 4549, 200, req, true)
|
val fromServiceMsg = sendOidbAW("OidbSvcTrpcTcp.0x11c5_200", 4549, 200, req, true)
|
||||||
if (fromServiceMsg == null || fromServiceMsg.wupBuffer == null) {
|
if (fromServiceMsg == null || fromServiceMsg.wupBuffer == null) {
|
||||||
return Result.failure(Exception("unable to get multimedia pic info: ${fromServiceMsg?.wupBuffer}"))
|
return Result.failure(Exception("unable to get multimedia pic info: ${fromServiceMsg?.wupBuffer?.toHexString()}"))
|
||||||
}
|
}
|
||||||
fromServiceMsg.wupBuffer.slice(4).decodeProtobuf<TrpcOidb>().buffer.decodeProtobuf<NtV2RichMediaRsp>().download?.rkeyParam?.let {
|
val trpc = fromServiceMsg.decodeToTrpcOidb()
|
||||||
|
if (trpc.buffer == null) {
|
||||||
|
return Result.failure(Exception("unable to get multimedia pic info: ${trpc.msg}"))
|
||||||
|
}
|
||||||
|
|
||||||
|
trpc.buffer?.decodeProtobuf<NtV2RichMediaRsp>()?.download?.rkeyParam?.let {
|
||||||
return Result.success(it)
|
return Result.success(it)
|
||||||
}
|
}
|
||||||
}.onFailure {
|
}.onFailure {
|
||||||
@ -446,8 +494,11 @@ internal object NtV2RichMediaSvc: QQInterfaces() {
|
|||||||
if (fromServiceMsg == null || fromServiceMsg.wupBuffer == null) {
|
if (fromServiceMsg == null || fromServiceMsg.wupBuffer == null) {
|
||||||
return Result.failure(Exception("unable to request upload nt pic"))
|
return Result.failure(Exception("unable to request upload nt pic"))
|
||||||
}
|
}
|
||||||
val rspBuffer = fromServiceMsg.wupBuffer.slice(4).decodeProtobuf<TrpcOidb>().buffer
|
val trpc = fromServiceMsg.decodeToTrpcOidb()
|
||||||
val rsp = rspBuffer.decodeProtobuf<NtV2RichMediaRsp>()
|
if (trpc.buffer == null) {
|
||||||
|
return Result.failure(Exception("unable to request upload nt pic: ${trpc.msg}"))
|
||||||
|
}
|
||||||
|
val rsp = trpc.buffer!!.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}"))
|
||||||
}
|
}
|
||||||
@ -502,4 +553,4 @@ internal object NtV2RichMediaSvc: QQInterfaces() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,11 +6,16 @@ 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.Image
|
||||||
|
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
||||||
|
import com.tencent.qqnt.kernel.nativeinterface.MsgRecord
|
||||||
|
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.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.slice
|
import moe.fuqiuluo.shamrock.tools.decodeToOidb
|
||||||
|
import moe.fuqiuluo.shamrock.tools.ifNullOrEmpty
|
||||||
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.symbols.decodeProtobuf
|
import moe.fuqiuluo.symbols.decodeProtobuf
|
||||||
@ -28,7 +33,6 @@ import qq.service.contact.ContactHelper
|
|||||||
import tencent.im.cs.cmd0x346.cmd0x346
|
import tencent.im.cs.cmd0x346.cmd0x346
|
||||||
import tencent.im.oidb.cmd0x6d6.oidb_0x6d6
|
import tencent.im.oidb.cmd0x6d6.oidb_0x6d6
|
||||||
import tencent.im.oidb.cmd0xe37.cmd0xe37
|
import tencent.im.oidb.cmd0xe37.cmd0xe37
|
||||||
import tencent.im.oidb.oidb_sso
|
|
||||||
import kotlin.coroutines.resume
|
import kotlin.coroutines.resume
|
||||||
|
|
||||||
private const val GPRO_PIC = "gchat.qpic.cn"
|
private const val GPRO_PIC = "gchat.qpic.cn"
|
||||||
@ -53,8 +57,7 @@ internal object RichProtoSvc: QQInterfaces() {
|
|||||||
if (fromServiceMsg == null || fromServiceMsg.wupBuffer == null) {
|
if (fromServiceMsg == null || fromServiceMsg.wupBuffer == null) {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
val body = oidb_sso.OIDBSSOPkg()
|
val body = fromServiceMsg.decodeToOidb()
|
||||||
body.mergeFrom(fromServiceMsg.wupBuffer.slice(4))
|
|
||||||
body.bytes_bodybuffer
|
body.bytes_bodybuffer
|
||||||
.get().toByteArray()
|
.get().toByteArray()
|
||||||
.decodeProtobuf<Oidb0xfc2RspBody>()
|
.decodeProtobuf<Oidb0xfc2RspBody>()
|
||||||
@ -82,8 +85,7 @@ internal object RichProtoSvc: QQInterfaces() {
|
|||||||
if (fromServiceMsg == null || fromServiceMsg.wupBuffer == null) {
|
if (fromServiceMsg == null || fromServiceMsg.wupBuffer == null) {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
val body = oidb_sso.OIDBSSOPkg()
|
val body = fromServiceMsg.decodeToOidb()
|
||||||
body.mergeFrom(fromServiceMsg.wupBuffer.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) {
|
||||||
@ -130,8 +132,7 @@ internal object RichProtoSvc: QQInterfaces() {
|
|||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
} else {
|
} else {
|
||||||
val body = oidb_sso.OIDBSSOPkg()
|
val body = fromServiceMsg.decodeToOidb()
|
||||||
body.mergeFrom(fromServiceMsg.wupBuffer.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())
|
||||||
@ -152,6 +153,75 @@ internal object RichProtoSvc: QQInterfaces() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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,8 +1,8 @@
|
|||||||
package qq.service.contact
|
package qq.service.contact
|
||||||
|
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.Contact
|
import com.tencent.qqnt.kernelpublic.nativeinterface.Contact
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
||||||
import io.kritor.message.Scene
|
import io.kritor.common.Scene
|
||||||
|
|
||||||
suspend fun Contact.longPeer(): Long {
|
suspend fun Contact.longPeer(): Long {
|
||||||
return when(this.chatType) {
|
return when(this.chatType) {
|
||||||
@ -12,7 +12,7 @@ suspend fun Contact.longPeer(): Long {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun io.kritor.message.Contact.longPeer(): Long {
|
suspend fun io.kritor.common.Contact.longPeer(): Long {
|
||||||
return when(this.scene) {
|
return when(this.scene) {
|
||||||
Scene.GROUP -> peer.toLong()
|
Scene.GROUP -> peer.toLong()
|
||||||
Scene.FRIEND, Scene.STRANGER, Scene.STRANGER_FROM_GROUP -> if (peer.startsWith("u_")) ContactHelper.getUinByUidAsync(peer).toLong() else peer.toLong()
|
Scene.FRIEND, Scene.STRANGER, Scene.STRANGER_FROM_GROUP -> if (peer.startsWith("u_")) ContactHelper.getUinByUidAsync(peer).toLong() else peer.toLong()
|
||||||
|
@ -11,6 +11,7 @@ import com.tencent.protofile.join_group_link.join_group_link
|
|||||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import kotlinx.coroutines.sync.withLock
|
import kotlinx.coroutines.sync.withLock
|
||||||
|
import moe.fuqiuluo.shamrock.tools.decodeToOidb
|
||||||
import moe.fuqiuluo.shamrock.tools.slice
|
import moe.fuqiuluo.shamrock.tools.slice
|
||||||
import qq.service.internals.NTServiceFetcher
|
import qq.service.internals.NTServiceFetcher
|
||||||
import qq.service.QQInterfaces
|
import qq.service.QQInterfaces
|
||||||
@ -190,8 +191,7 @@ internal object ContactHelper: QQInterfaces() {
|
|||||||
val fromServiceMsg = 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(fromServiceMsg.wupBuffer.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,19 +1,15 @@
|
|||||||
@file:OptIn(ExperimentalStdlibApi::class)
|
|
||||||
|
|
||||||
package qq.service.file
|
package qq.service.file
|
||||||
|
|
||||||
import com.tencent.mobileqq.pb.ByteStringMicro
|
import com.tencent.mobileqq.pb.ByteStringMicro
|
||||||
import io.grpc.Status
|
import io.grpc.Status
|
||||||
import io.grpc.StatusRuntimeException
|
import io.grpc.StatusRuntimeException
|
||||||
import io.kritor.file.File
|
import io.kritor.file.*
|
||||||
import io.kritor.file.Folder
|
|
||||||
import io.kritor.file.GetFileSystemInfoResponse
|
|
||||||
import io.kritor.file.GetFilesRequest
|
|
||||||
import io.kritor.file.GetFilesResponse
|
|
||||||
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.utils.DeflateTools
|
import moe.fuqiuluo.shamrock.utils.DeflateTools
|
||||||
import qq.service.QQInterfaces
|
import qq.service.QQInterfaces
|
||||||
import tencent.im.oidb.cmd0x6d8.oidb_0x6d8
|
import tencent.im.oidb.cmd0x6d8.oidb_0x6d8
|
||||||
@ -35,12 +31,9 @@ internal object GroupFileHelper: QQInterfaces() {
|
|||||||
val fileCnt: Int
|
val fileCnt: Int
|
||||||
val limitCnt: Int
|
val limitCnt: Int
|
||||||
if (fromServiceMsg.wupBuffer != null) {
|
if (fromServiceMsg.wupBuffer != null) {
|
||||||
oidb_0x6d8.RspBody().mergeFrom(
|
val oidb1 = fromServiceMsg.decodeToOidb()
|
||||||
oidb_sso.OIDBSSOPkg()
|
|
||||||
.mergeFrom(fromServiceMsg.wupBuffer.slice(4))
|
oidb_0x6d8.RspBody().mergeFrom(oidb1.bytes_bodybuffer.get().toByteArray()).group_file_cnt_rsp.apply {
|
||||||
.bytes_bodybuffer.get()
|
|
||||||
.toByteArray()
|
|
||||||
).group_file_cnt_rsp.apply {
|
|
||||||
fileCnt = uint32_all_file_count.get()
|
fileCnt = uint32_all_file_count.get()
|
||||||
limitCnt = uint32_limit_count.get()
|
limitCnt = uint32_limit_count.get()
|
||||||
}
|
}
|
||||||
@ -57,11 +50,9 @@ internal object GroupFileHelper: QQInterfaces() {
|
|||||||
val totalSpace: Long
|
val totalSpace: Long
|
||||||
val usedSpace: Long
|
val usedSpace: Long
|
||||||
if (fromServiceMsg2.isSuccess && fromServiceMsg2.wupBuffer != null) {
|
if (fromServiceMsg2.isSuccess && fromServiceMsg2.wupBuffer != null) {
|
||||||
oidb_0x6d8.RspBody().mergeFrom(
|
val oidb2 = fromServiceMsg2.decodeToOidb()
|
||||||
oidb_sso.OIDBSSOPkg()
|
|
||||||
.mergeFrom(fromServiceMsg2.wupBuffer.slice(4))
|
oidb_0x6d8.RspBody().mergeFrom(oidb2.bytes_bodybuffer.get().toByteArray()).group_space_rsp.apply {
|
||||||
.bytes_bodybuffer.get()
|
|
||||||
.toByteArray()).group_space_rsp.apply {
|
|
||||||
totalSpace = uint64_total_space.get()
|
totalSpace = uint64_total_space.get()
|
||||||
usedSpace = uint64_used_space.get()
|
usedSpace = uint64_used_space.get()
|
||||||
}
|
}
|
||||||
@ -77,7 +68,7 @@ internal object GroupFileHelper: QQInterfaces() {
|
|||||||
}.build()
|
}.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getGroupFiles(groupId: Long, folderId: String = "/"): GetFilesResponse {
|
suspend fun getGroupFiles(groupId: Long, folderId: String = "/"): GetFileListResponse {
|
||||||
val fileSystemInfo = getGroupFileSystemInfo(groupId)
|
val fileSystemInfo = getGroupFileSystemInfo(groupId)
|
||||||
val fromServiceMsg = sendOidbAW("OidbSvc.0x6d8_1", 1752, 1, oidb_0x6d8.ReqBody().also {
|
val fromServiceMsg = sendOidbAW("OidbSvc.0x6d8_1", 1752, 1, oidb_0x6d8.ReqBody().also {
|
||||||
it.file_list_info_req.set(oidb_0x6d8.GetFileListReqBody().apply {
|
it.file_list_info_req.set(oidb_0x6d8.GetFileListReqBody().apply {
|
||||||
@ -99,16 +90,14 @@ internal object GroupFileHelper: QQInterfaces() {
|
|||||||
|
|
||||||
uint32_show_onlinedoc_folder.set(0)
|
uint32_show_onlinedoc_folder.set(0)
|
||||||
})
|
})
|
||||||
}.toByteArray(), timeout = 15.seconds) ?: throw StatusRuntimeException(Status.INTERNAL.withDescription("unable to send oidb request"))
|
}.toByteArray(), timeout = 30.seconds) ?: throw StatusRuntimeException(Status.INTERNAL.withDescription("unable to send oidb request"))
|
||||||
if (fromServiceMsg.wupBuffer == null) {
|
if (fromServiceMsg.wupBuffer == null) {
|
||||||
throw StatusRuntimeException(Status.INTERNAL.withDescription("oidb request failed"))
|
throw StatusRuntimeException(Status.INTERNAL.withDescription("oidb request failed"))
|
||||||
}
|
}
|
||||||
val files = arrayListOf<File>()
|
val files = arrayListOf<File>()
|
||||||
val folders = arrayListOf<Folder>()
|
val folders = arrayListOf<Folder>()
|
||||||
if (fromServiceMsg.wupBuffer != null) {
|
if (fromServiceMsg.wupBuffer != null) {
|
||||||
val oidb = oidb_sso.OIDBSSOPkg().mergeFrom(fromServiceMsg.wupBuffer.slice(4).let {
|
val oidb = fromServiceMsg.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 {
|
||||||
@ -120,9 +109,9 @@ internal object GroupFileHelper: QQInterfaces() {
|
|||||||
this.fileName = fileInfo.str_file_name.get()
|
this.fileName = fileInfo.str_file_name.get()
|
||||||
this.fileSize = fileInfo.uint64_file_size.get()
|
this.fileSize = fileInfo.uint64_file_size.get()
|
||||||
this.busId = fileInfo.uint32_bus_id.get()
|
this.busId = fileInfo.uint32_bus_id.get()
|
||||||
this.uploadTime = fileInfo.uint32_upload_time.get()
|
this.uploadTime = fileInfo.uint32_upload_time.get().toLong()
|
||||||
this.deadTime = fileInfo.uint32_dead_time.get()
|
this.expireTime = fileInfo.uint32_dead_time.get().toLong()
|
||||||
this.modifyTime = fileInfo.uint32_modify_time.get()
|
this.modifyTime = fileInfo.uint32_modify_time.get().toLong()
|
||||||
this.downloadTimes = fileInfo.uint32_download_times.get()
|
this.downloadTimes = fileInfo.uint32_download_times.get()
|
||||||
this.uploader = fileInfo.uint64_uploader_uin.get()
|
this.uploader = fileInfo.uint64_uploader_uin.get()
|
||||||
this.uploaderName = fileInfo.str_uploader_name.get()
|
this.uploaderName = fileInfo.str_uploader_name.get()
|
||||||
@ -137,7 +126,7 @@ internal object GroupFileHelper: QQInterfaces() {
|
|||||||
this.folderId = folderInfo.str_folder_id.get()
|
this.folderId = folderInfo.str_folder_id.get()
|
||||||
this.folderName = folderInfo.str_folder_name.get()
|
this.folderName = folderInfo.str_folder_name.get()
|
||||||
this.totalFileCount = folderInfo.uint32_total_file_count.get()
|
this.totalFileCount = folderInfo.uint32_total_file_count.get()
|
||||||
this.createTime = folderInfo.uint32_create_time.get()
|
this.createTime = folderInfo.uint32_create_time.get().toLong()
|
||||||
this.creator = folderInfo.uint64_create_uin.get()
|
this.creator = folderInfo.uint64_create_uin.get()
|
||||||
this.creatorName = folderInfo.str_creator_name.get()
|
this.creatorName = folderInfo.str_creator_name.get()
|
||||||
}.build())
|
}.build())
|
||||||
@ -150,7 +139,7 @@ internal object GroupFileHelper: QQInterfaces() {
|
|||||||
throw StatusRuntimeException(Status.INTERNAL.withDescription("unable to fetch oidb response"))
|
throw StatusRuntimeException(Status.INTERNAL.withDescription("unable to fetch oidb response"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetFilesResponse.newBuilder().apply {
|
return GetFileListResponse.newBuilder().apply {
|
||||||
this.addAllFiles(files)
|
this.addAllFiles(files)
|
||||||
this.addAllFolders(folders)
|
this.addAllFolders(folders)
|
||||||
}.build()
|
}.build()
|
||||||
|
@ -19,10 +19,13 @@ import kotlinx.coroutines.sync.withLock
|
|||||||
import kotlinx.coroutines.withTimeoutOrNull
|
import kotlinx.coroutines.withTimeoutOrNull
|
||||||
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 qq.service.internals.NTServiceFetcher
|
import qq.service.internals.NTServiceFetcher
|
||||||
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.tools.slice
|
||||||
|
import moe.fuqiuluo.shamrock.utils.PlatformUtils
|
||||||
|
import moe.fuqiuluo.shamrock.utils.PlatformUtils.QQ_9_0_65_VER
|
||||||
import protobuf.auto.toByteArray
|
import protobuf.auto.toByteArray
|
||||||
import protobuf.oidb.cmd0xf16.Oidb0xf16
|
import protobuf.oidb.cmd0xf16.Oidb0xf16
|
||||||
import protobuf.oidb.cmd0xf16.SetGroupRemarkReq
|
import protobuf.oidb.cmd0xf16.SetGroupRemarkReq
|
||||||
@ -398,22 +401,46 @@ internal object GroupHelper: QQInterfaces() {
|
|||||||
sendOidb("OidbSvc.0x89a_0", 2202, 0, reqBody.toByteArray())
|
sendOidb("OidbSvc.0x89a_0", 2202, 0, reqBody.toByteArray())
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getGroupMemberList(groupId: String, refresh: Boolean): Result<List<TroopMemberInfo>> {
|
suspend fun getGroupMemberList(groupId: Long, refresh: Boolean): Result<HashMap<String, MemberInfo>> {
|
||||||
val service = app.getRuntimeService(ITroopMemberInfoService::class.java, "all")
|
val kernelService = NTServiceFetcher.kernelService
|
||||||
var memberList = service.getAllTroopMembers(groupId)
|
val sessionService = kernelService.wrapperSession
|
||||||
if (refresh || memberList == null) {
|
val service = sessionService.groupService
|
||||||
memberList = requestTroopMemberInfo(service, groupId).onFailure {
|
val uids = suspendCancellableCoroutine { continuation ->
|
||||||
return Result.failure(Exception("获取群成员列表失败"))
|
service.getAllMemberList(groupId, refresh) { _, _, groupMemberListResult ->
|
||||||
}.getOrThrow()
|
continuation.resume(groupMemberListResult?.ids?.map {
|
||||||
}
|
it.uid
|
||||||
|
})
|
||||||
getGroupInfo(groupId, true).onSuccess {
|
|
||||||
if(it.wMemberNum > memberList.size) {
|
|
||||||
return getGroupMemberList(groupId, true)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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)
|
||||||
|
|
||||||
return Result.success(memberList)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getProhibitedMemberList(groupId: Long): Result<List<ProhibitedMemberInfo>> {
|
suspend fun getProhibitedMemberList(groupId: Long): Result<List<ProhibitedMemberInfo>> {
|
||||||
@ -429,8 +456,7 @@ internal object GroupHelper: QQInterfaces() {
|
|||||||
if (fromServiceMsg.wupBuffer == null) {
|
if (fromServiceMsg.wupBuffer == null) {
|
||||||
return Result.failure(RuntimeException("[oidb] failed"))
|
return Result.failure(RuntimeException("[oidb] failed"))
|
||||||
}
|
}
|
||||||
val body = oidb_sso.OIDBSSOPkg()
|
val body = fromServiceMsg.decodeToOidb()
|
||||||
body.mergeFrom(fromServiceMsg.wupBuffer.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()))
|
||||||
}
|
}
|
||||||
@ -451,8 +477,7 @@ internal object GroupHelper: QQInterfaces() {
|
|||||||
if (fromServiceMsg.wupBuffer == null) {
|
if (fromServiceMsg.wupBuffer == null) {
|
||||||
return Result.failure(RuntimeException("[oidb] failed"))
|
return Result.failure(RuntimeException("[oidb] failed"))
|
||||||
}
|
}
|
||||||
val body = oidb_sso.OIDBSSOPkg()
|
val body = fromServiceMsg.decodeToOidb()
|
||||||
body.mergeFrom(fromServiceMsg.wupBuffer.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()))
|
||||||
}
|
}
|
||||||
@ -613,6 +638,9 @@ internal object GroupHelper: QQInterfaces() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun requestTroopMemberInfo(service: ITroopMemberInfoService, groupId: String, memberUin: String, timeout: Long = 10_000): Result<TroopMemberInfo> {
|
private suspend fun requestTroopMemberInfo(service: ITroopMemberInfoService, groupId: String, memberUin: String, timeout: Long = 10_000): Result<TroopMemberInfo> {
|
||||||
|
if(PlatformUtils.getQQVersionCode() >= QQ_9_0_65_VER) {
|
||||||
|
return Result.failure(Exception("当前版本不支持该API"))
|
||||||
|
}
|
||||||
val info = RefreshTroopMemberInfoLock.withLock {
|
val info = RefreshTroopMemberInfoLock.withLock {
|
||||||
service.deleteTroopMember(groupId, memberUin)
|
service.deleteTroopMember(groupId, memberUin)
|
||||||
|
|
||||||
|
@ -3,18 +3,28 @@
|
|||||||
package qq.service.internals
|
package qq.service.internals
|
||||||
|
|
||||||
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.MsgRecord
|
import com.tencent.qqnt.kernel.nativeinterface.MsgRecord
|
||||||
|
import com.tencent.qqnt.kernel.nativeinterface.TextElement
|
||||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import moe.fuqiuluo.shamrock.config.AliveReply
|
||||||
|
import moe.fuqiuluo.shamrock.config.get
|
||||||
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.db.ImageDB
|
||||||
|
import moe.fuqiuluo.shamrock.helper.db.ImageMapping
|
||||||
import moe.fuqiuluo.shamrock.internals.GlobalEventTransmitter
|
import moe.fuqiuluo.shamrock.internals.GlobalEventTransmitter
|
||||||
|
import moe.fuqiuluo.shamrock.utils.PlatformUtils
|
||||||
|
import moe.fuqiuluo.shamrock.utils.PlatformUtils.QQ_9_0_8_VER
|
||||||
import qq.service.bdh.RichProtoSvc
|
import qq.service.bdh.RichProtoSvc
|
||||||
|
import qq.service.file.GroupFileHelper
|
||||||
|
import qq.service.group.GroupHelper
|
||||||
import qq.service.kernel.SimpleKernelMsgListener
|
import qq.service.kernel.SimpleKernelMsgListener
|
||||||
import qq.service.msg.MessageHelper
|
import qq.service.msg.MessageHelper
|
||||||
|
|
||||||
object AioListener: SimpleKernelMsgListener() {
|
object AioListener : SimpleKernelMsgListener() {
|
||||||
override fun onRecvMsg(records: ArrayList<MsgRecord>) {
|
override fun onRecvMsg(records: ArrayList<MsgRecord>) {
|
||||||
records.forEach {
|
records.forEach {
|
||||||
GlobalScope.launch {
|
GlobalScope.launch {
|
||||||
@ -27,7 +37,83 @@ object AioListener: SimpleKernelMsgListener() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun debugTest(record: MsgRecord, text: String) {
|
||||||
|
if (record.chatType == MsgConstant.KCHATTYPEGROUP && text == ".shamrock.members") {
|
||||||
|
val contact = MessageHelper.generateContact(record)
|
||||||
|
GroupHelper.getGroupMemberList(record.peerUin, true).onSuccess {
|
||||||
|
MessageHelper.sendMessage(contact, arrayListOf(
|
||||||
|
MsgElement().apply {
|
||||||
|
elementType = MsgConstant.KELEMTYPETEXT
|
||||||
|
textElement = TextElement().apply {
|
||||||
|
content = "memberCount: ${it.size}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
), 3, MessageHelper.generateMsgId(record.chatType))
|
||||||
|
}.onFailure {
|
||||||
|
LogCenter.log("获取群成员列表失败: $it", Level.ERROR)
|
||||||
|
}
|
||||||
|
} else if (record.chatType == MsgConstant.KCHATTYPEGROUP && text == ".shamrock.root_files") {
|
||||||
|
val contact = MessageHelper.generateContact(record)
|
||||||
|
val files = GroupFileHelper.getGroupFiles(record.peerUin)
|
||||||
|
MessageHelper.sendMessage(contact, arrayListOf(
|
||||||
|
MsgElement().apply {
|
||||||
|
elementType = MsgConstant.KELEMTYPETEXT
|
||||||
|
textElement = TextElement().apply {
|
||||||
|
content = "foldersCount: ${files.foldersCount}\nfilesCount: ${files.filesCount}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
), 3, MessageHelper.generateMsgId(record.chatType))
|
||||||
|
} else if (record.chatType == MsgConstant.KCHATTYPEGROUP && text == ".shamrock.pic_url") {
|
||||||
|
val contact = MessageHelper.generateContact(record)
|
||||||
|
val pic = record.elements.filter {
|
||||||
|
it.elementType == MsgConstant.KELEMTYPEPIC
|
||||||
|
}.map {
|
||||||
|
val image = it.picElement
|
||||||
|
val md5 = (image.md5HexStr ?: image.fileName
|
||||||
|
.replace("{", "")
|
||||||
|
.replace("}", "")
|
||||||
|
.replace("-", "").split(".")[0])
|
||||||
|
.uppercase()
|
||||||
|
var storeId = 0
|
||||||
|
if (PlatformUtils.getQQVersionCode() > QQ_9_0_8_VER) {
|
||||||
|
storeId = image.storeID
|
||||||
|
}
|
||||||
|
val originalUrl = image.originImageUrl ?: ""
|
||||||
|
return@map RichProtoSvc.getTempPicDownloadUrl(record.chatType, originalUrl, md5, image, storeId)
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageHelper.sendMessage(contact, arrayListOf(
|
||||||
|
MsgElement().apply {
|
||||||
|
elementType = MsgConstant.KELEMTYPETEXT
|
||||||
|
textElement = TextElement().apply {
|
||||||
|
content = "picUrl: \n${
|
||||||
|
pic.joinToString("\n")
|
||||||
|
}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
), 3, MessageHelper.generateMsgId(record.chatType))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private suspend fun onMsg(record: MsgRecord) {
|
private suspend fun onMsg(record: MsgRecord) {
|
||||||
|
if (AliveReply.get()) {
|
||||||
|
val texts = record.elements.filter { it.elementType == MsgConstant.KELEMTYPETEXT }
|
||||||
|
val text = texts.joinToString { it.textElement.content }
|
||||||
|
if (texts.isNotEmpty() && text == "ping") {
|
||||||
|
val contact = MessageHelper.generateContact(record)
|
||||||
|
MessageHelper.sendMessage(contact, arrayListOf(
|
||||||
|
MsgElement().apply {
|
||||||
|
elementType = MsgConstant.KELEMTYPETEXT
|
||||||
|
textElement = TextElement().apply {
|
||||||
|
content = "pong"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
), 3, MessageHelper.generateMsgId(record.chatType))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
debugTest(record, text)
|
||||||
|
}
|
||||||
when (record.chatType) {
|
when (record.chatType) {
|
||||||
MsgConstant.KCHATTYPEGROUP -> {
|
MsgConstant.KCHATTYPEGROUP -> {
|
||||||
if (record.senderUin == 0L) return
|
if (record.senderUin == 0L) return
|
||||||
@ -60,7 +146,12 @@ object AioListener: SimpleKernelMsgListener() {
|
|||||||
|
|
||||||
LogCenter.log("私聊临时消息(private = ${record.senderUin}, groupId=$groupCode)")
|
LogCenter.log("私聊临时消息(private = ${record.senderUin}, groupId=$groupCode)")
|
||||||
|
|
||||||
if (!GlobalEventTransmitter.MessageTransmitter.transTempMessage(record, record.elements, groupCode, fromNick)
|
if (!GlobalEventTransmitter.MessageTransmitter.transTempMessage(
|
||||||
|
record,
|
||||||
|
record.elements,
|
||||||
|
groupCode,
|
||||||
|
fromNick
|
||||||
|
)
|
||||||
) {
|
) {
|
||||||
LogCenter.log("私聊临时消息推送失败 -> MessageTransmitter", Level.WARN)
|
LogCenter.log("私聊临时消息推送失败 -> MessageTransmitter", Level.WARN)
|
||||||
}
|
}
|
||||||
@ -92,7 +183,6 @@ object AioListener: SimpleKernelMsgListener() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun onC2CFileMsg(record: MsgRecord) {
|
private suspend fun onC2CFileMsg(record: MsgRecord) {
|
||||||
val userId = record.senderUin
|
|
||||||
val fileMsg = record.elements.firstOrNull {
|
val fileMsg = record.elements.firstOrNull {
|
||||||
it.elementType == MsgConstant.KELEMTYPEFILE
|
it.elementType == MsgConstant.KELEMTYPEFILE
|
||||||
}?.fileElement ?: kotlin.run {
|
}?.fileElement ?: kotlin.run {
|
||||||
@ -108,7 +198,7 @@ object AioListener: SimpleKernelMsgListener() {
|
|||||||
val url = RichProtoSvc.getC2CFileDownUrl(fileId, fileSubId)
|
val url = RichProtoSvc.getC2CFileDownUrl(fileId, fileSubId)
|
||||||
|
|
||||||
if (!GlobalEventTransmitter.FileNoticeTransmitter
|
if (!GlobalEventTransmitter.FileNoticeTransmitter
|
||||||
.transPrivateFileEvent(record.msgTime, userId, fileId, fileSubId, fileName, fileSize, expireTime, url)
|
.transPrivateFileEvent(record.msgTime, record.senderUid, record.senderUin, fileId, fileSubId, fileName, fileSize, expireTime, url)
|
||||||
) {
|
) {
|
||||||
LogCenter.log("私聊文件消息推送失败 -> FileNoticeTransmitter", Level.WARN)
|
LogCenter.log("私聊文件消息推送失败 -> FileNoticeTransmitter", Level.WARN)
|
||||||
}
|
}
|
||||||
@ -116,7 +206,6 @@ object AioListener: SimpleKernelMsgListener() {
|
|||||||
|
|
||||||
private suspend fun onGroupFileMsg(record: MsgRecord) {
|
private suspend fun onGroupFileMsg(record: MsgRecord) {
|
||||||
val groupId = record.peerUin
|
val groupId = record.peerUin
|
||||||
val userId = record.senderUin
|
|
||||||
val fileMsg = record.elements.firstOrNull {
|
val fileMsg = record.elements.firstOrNull {
|
||||||
it.elementType == MsgConstant.KELEMTYPEFILE
|
it.elementType == MsgConstant.KELEMTYPEFILE
|
||||||
}?.fileElement ?: kotlin.run {
|
}?.fileElement ?: kotlin.run {
|
||||||
@ -132,9 +221,15 @@ object AioListener: SimpleKernelMsgListener() {
|
|||||||
val url = RichProtoSvc.getGroupFileDownUrl(record.peerUin, uuid, bizId)
|
val url = RichProtoSvc.getGroupFileDownUrl(record.peerUin, uuid, bizId)
|
||||||
|
|
||||||
if (!GlobalEventTransmitter.FileNoticeTransmitter
|
if (!GlobalEventTransmitter.FileNoticeTransmitter
|
||||||
.transGroupFileEvent(record.msgTime, userId, groupId, uuid, fileName, fileSize, bizId, url)
|
.transGroupFileEvent(record.msgTime, record.senderUid, record.senderUin, groupId, uuid, fileName, fileSize, bizId, url)
|
||||||
) {
|
) {
|
||||||
LogCenter.log("群聊文件消息推送失败 -> FileNoticeTransmitter", Level.WARN)
|
LogCenter.log("群聊文件消息推送失败 -> FileNoticeTransmitter", Level.WARN)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalStdlibApi::class)
|
||||||
|
override fun onRecvSysMsg(arrayList: ArrayList<Byte>?) {
|
||||||
|
LogCenter.log("onRecvSysMsg")
|
||||||
|
LogCenter.log(arrayList?.toByteArray()?.toHexString() ?: "")
|
||||||
|
}
|
||||||
}
|
}
|
@ -5,9 +5,8 @@ import com.tencent.mobileqq.qroute.QRoute
|
|||||||
import com.tencent.qphone.base.remote.FromServiceMsg
|
import com.tencent.qphone.base.remote.FromServiceMsg
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
||||||
import com.tencent.qqnt.msg.api.IMsgService
|
import com.tencent.qqnt.msg.api.IMsgService
|
||||||
import io.kritor.event.GroupApplyType
|
import io.kritor.event.GroupMemberDecreasedNotice.GroupMemberDecreasedType
|
||||||
import io.kritor.event.GroupMemberDecreasedType
|
import io.kritor.event.GroupMemberIncreasedNotice.GroupMemberIncreasedType
|
||||||
import io.kritor.event.GroupMemberIncreasedType
|
|
||||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -127,7 +126,7 @@ internal object PrimitiveListener {
|
|||||||
LogCenter.log("私聊戳一戳: $operation $action $target $suffix")
|
LogCenter.log("私聊戳一戳: $operation $action $target $suffix")
|
||||||
|
|
||||||
if (!GlobalEventTransmitter.PrivateNoticeTransmitter
|
if (!GlobalEventTransmitter.PrivateNoticeTransmitter
|
||||||
.transPrivatePoke(msgTime, operation.toLong(), target.toLong(), action, suffix, actionImg)
|
.transPrivatePoke(msgTime, operation.toLong(), action, suffix, actionImg)
|
||||||
) {
|
) {
|
||||||
LogCenter.log("私聊戳一戳推送失败!", Level.WARN)
|
LogCenter.log("私聊戳一戳推送失败!", Level.WARN)
|
||||||
}
|
}
|
||||||
@ -162,7 +161,7 @@ internal object PrimitiveListener {
|
|||||||
}
|
}
|
||||||
LogCenter.log("来自$applier 的好友申请:$msg ($source)")
|
LogCenter.log("来自$applier 的好友申请:$msg ($source)")
|
||||||
if (!GlobalEventTransmitter.RequestTransmitter
|
if (!GlobalEventTransmitter.RequestTransmitter
|
||||||
.transFriendApp(msgTime, applier, msg, flag)
|
.transFriendApp(msgTime, applierUid, applier, msg, flag)
|
||||||
) {
|
) {
|
||||||
LogCenter.log("好友申请推送失败!", Level.WARN)
|
LogCenter.log("好友申请推送失败!", Level.WARN)
|
||||||
}
|
}
|
||||||
@ -217,8 +216,13 @@ internal object PrimitiveListener {
|
|||||||
}.decodeProtobuf<GroupCommonTipsEvent>()
|
}.decodeProtobuf<GroupCommonTipsEvent>()
|
||||||
}
|
}
|
||||||
val groupId = event.groupCode.toLong()
|
val groupId = event.groupCode.toLong()
|
||||||
|
if (event.uniqueTitleChangeDetail == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
val detail = event.uniqueTitleChangeDetail!!.first()
|
val detail = event.uniqueTitleChangeDetail!!.first()
|
||||||
|
|
||||||
|
// todo 贴表情也走的 732 16 这里
|
||||||
|
|
||||||
//detail = if (detail[5] is ProtoList) {
|
//detail = if (detail[5] is ProtoList) {
|
||||||
// (detail[5] as ProtoList).value[0]
|
// (detail[5] as ProtoList).value[0]
|
||||||
//} else {
|
//} else {
|
||||||
@ -321,8 +325,8 @@ internal object PrimitiveListener {
|
|||||||
it.key to it.value
|
it.key to it.value
|
||||||
}
|
}
|
||||||
|
|
||||||
val target = params["uin_str2"] ?: params["mqq_uin"] ?: return
|
val target = params["uin_str2"] ?: params["mqq_uin"] ?: ""
|
||||||
val operation = params["uin_str1"] ?: return
|
val operator = params["uin_str1"] ?: ""
|
||||||
val suffix = params["suffix_str"] ?: ""
|
val suffix = params["suffix_str"] ?: ""
|
||||||
val actionImg = params["action_img_url"] ?: ""
|
val actionImg = params["action_img_url"] ?: ""
|
||||||
val action = params["alt_str1"]
|
val action = params["alt_str1"]
|
||||||
@ -333,9 +337,9 @@ internal object PrimitiveListener {
|
|||||||
|
|
||||||
when (detail.type) {
|
when (detail.type) {
|
||||||
1061u -> {
|
1061u -> {
|
||||||
LogCenter.log("群戳一戳($groupId): $operation $action $target $suffix")
|
LogCenter.log("群戳一戳($groupId): $operator $action $target $suffix")
|
||||||
if (!GlobalEventTransmitter.GroupNoticeTransmitter
|
if (!GlobalEventTransmitter.GroupNoticeTransmitter
|
||||||
.transGroupPoke(time, operation.toLong(), target.toLong(), action, suffix, actionImg, groupId)
|
.transGroupPoke(time, operator.toLong(), target.toLong(), action, suffix, actionImg, groupId)
|
||||||
) {
|
) {
|
||||||
LogCenter.log("群戳一戳推送失败!", Level.WARN)
|
LogCenter.log("群戳一戳推送失败!", Level.WARN)
|
||||||
}
|
}
|
||||||
@ -397,7 +401,7 @@ internal object PrimitiveListener {
|
|||||||
val targetUid = event.memberUid
|
val targetUid = event.memberUid
|
||||||
val type = event.type
|
val type = event.type
|
||||||
|
|
||||||
GroupHelper.getGroupMemberList(groupCode.toString(), true).onFailure {
|
GroupHelper.getGroupMemberList(groupCode, true).onFailure {
|
||||||
LogCenter.log("新成员加入刷新群成员列表失败: $groupCode", Level.WARN)
|
LogCenter.log("新成员加入刷新群成员列表失败: $groupCode", Level.WARN)
|
||||||
}.onSuccess {
|
}.onSuccess {
|
||||||
LogCenter.log("新成员加入刷新群成员列表成功,群成员数量: ${it.size}", Level.INFO)
|
LogCenter.log("新成员加入刷新群成员列表成功,群成员数量: ${it.size}", Level.INFO)
|
||||||
@ -434,7 +438,7 @@ internal object PrimitiveListener {
|
|||||||
val type = event.type
|
val type = event.type
|
||||||
val operatorUid = event.operatorUid
|
val operatorUid = event.operatorUid
|
||||||
|
|
||||||
GroupHelper.getGroupMemberList(groupCode.toString(), true).onFailure {
|
GroupHelper.getGroupMemberList(groupCode, true).onFailure {
|
||||||
LogCenter.log("新成员加入刷新群成员列表失败: $groupCode", Level.WARN)
|
LogCenter.log("新成员加入刷新群成员列表失败: $groupCode", Level.WARN)
|
||||||
}.onSuccess {
|
}.onSuccess {
|
||||||
LogCenter.log("新成员加入刷新群成员列表成功,群成员数量: ${it.size}", Level.INFO)
|
LogCenter.log("新成员加入刷新群成员列表成功,群成员数量: ${it.size}", Level.INFO)
|
||||||
@ -507,7 +511,7 @@ internal object PrimitiveListener {
|
|||||||
if (wholeBan) {
|
if (wholeBan) {
|
||||||
LogCenter.log("群全员禁言($groupCode): $operator -> ${if (rawDuration != 0) "开启" else "关闭"}")
|
LogCenter.log("群全员禁言($groupCode): $operator -> ${if (rawDuration != 0) "开启" else "关闭"}")
|
||||||
if (!GlobalEventTransmitter.GroupNoticeTransmitter
|
if (!GlobalEventTransmitter.GroupNoticeTransmitter
|
||||||
.transGroupWholeBan(msgTime, groupCode, operator, rawDuration != 0)
|
.transGroupWholeBan(msgTime, groupCode, operatorUid, operator, rawDuration != 0)
|
||||||
) {
|
) {
|
||||||
LogCenter.log("群禁言推送失败!", Level.WARN)
|
LogCenter.log("群禁言推送失败!", Level.WARN)
|
||||||
}
|
}
|
||||||
@ -595,7 +599,7 @@ internal object PrimitiveListener {
|
|||||||
}
|
}
|
||||||
LogCenter.log("入群申请($groupCode) $applier: \"$reason\", seq: $msgSeq")
|
LogCenter.log("入群申请($groupCode) $applier: \"$reason\", seq: $msgSeq")
|
||||||
if (!GlobalEventTransmitter.RequestTransmitter
|
if (!GlobalEventTransmitter.RequestTransmitter
|
||||||
.transGroupApply(time, applier, applierUid, reason, groupCode, flag, GroupApplyType.GROUP_APPLY_ADD)
|
.transGroupApply(time, applier, applierUid, reason, groupCode, flag)
|
||||||
) {
|
) {
|
||||||
LogCenter.log("入群申请推送失败!", Level.WARN)
|
LogCenter.log("入群申请推送失败!", Level.WARN)
|
||||||
}
|
}
|
||||||
@ -630,7 +634,7 @@ internal object PrimitiveListener {
|
|||||||
}
|
}
|
||||||
LogCenter.log("邀请入群申请($groupCode): $applier")
|
LogCenter.log("邀请入群申请($groupCode): $applier")
|
||||||
if (!GlobalEventTransmitter.RequestTransmitter
|
if (!GlobalEventTransmitter.RequestTransmitter
|
||||||
.transGroupApply(time, applier, applierUid, "", groupCode, flag, GroupApplyType.GROUP_APPLY_ADD)
|
.transGroupApply(time, applier, applierUid, "", groupCode, flag)
|
||||||
) {
|
) {
|
||||||
LogCenter.log("邀请入群申请推送失败!", Level.WARN)
|
LogCenter.log("邀请入群申请推送失败!", Level.WARN)
|
||||||
}
|
}
|
||||||
@ -658,7 +662,7 @@ internal object PrimitiveListener {
|
|||||||
"$time;$groupCode;$uin"
|
"$time;$groupCode;$uin"
|
||||||
}
|
}
|
||||||
if (!GlobalEventTransmitter.RequestTransmitter
|
if (!GlobalEventTransmitter.RequestTransmitter
|
||||||
.transGroupApply(time, invitor, invitorUid, "", groupCode, flag, GroupApplyType.GROUP_APPLY_INVITE)
|
.transGroupInvite(time, invitorUid, invitor, groupCode, flag)
|
||||||
) {
|
) {
|
||||||
LogCenter.log("邀请入群推送失败!", Level.WARN)
|
LogCenter.log("邀请入群推送失败!", Level.WARN)
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package qq.service.kernel
|
package qq.service.kernel
|
||||||
|
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.BroadcastHelperTransNotifyInfo
|
import com.tencent.qqnt.kernel.nativeinterface.BroadcastHelperTransNotifyInfo
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.Contact
|
import com.tencent.qqnt.kernelpublic.nativeinterface.Contact
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.ContactMsgBoxInfo
|
import com.tencent.qqnt.kernel.nativeinterface.ContactMsgBoxInfo
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.CustomWithdrawConfig
|
import com.tencent.qqnt.kernel.nativeinterface.CustomWithdrawConfig
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.DevInfo
|
import com.tencent.qqnt.kernel.nativeinterface.DevInfo
|
||||||
@ -12,6 +12,7 @@ import com.tencent.qqnt.kernel.nativeinterface.FileTransNotifyInfo
|
|||||||
import com.tencent.qqnt.kernel.nativeinterface.FirstViewDirectMsgNotifyInfo
|
import com.tencent.qqnt.kernel.nativeinterface.FirstViewDirectMsgNotifyInfo
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.FirstViewGroupGuildInfo
|
import com.tencent.qqnt.kernel.nativeinterface.FirstViewGroupGuildInfo
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.FreqLimitInfo
|
import com.tencent.qqnt.kernel.nativeinterface.FreqLimitInfo
|
||||||
|
import com.tencent.qqnt.kernel.nativeinterface.GProGuildTopFeedMsg
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.GroupFileListResult
|
import com.tencent.qqnt.kernel.nativeinterface.GroupFileListResult
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.GroupGuildNotifyInfo
|
import com.tencent.qqnt.kernel.nativeinterface.GroupGuildNotifyInfo
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.GroupItem
|
import com.tencent.qqnt.kernel.nativeinterface.GroupItem
|
||||||
@ -27,6 +28,7 @@ import com.tencent.qqnt.kernel.nativeinterface.MsgAbstract
|
|||||||
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.MsgRecord
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.MsgSetting
|
import com.tencent.qqnt.kernel.nativeinterface.MsgSetting
|
||||||
|
import com.tencent.qqnt.kernel.nativeinterface.QueryUserSecQualityRsp
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.RecvdOrder
|
import com.tencent.qqnt.kernel.nativeinterface.RecvdOrder
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.RelatedWordEmojiInfo
|
import com.tencent.qqnt.kernel.nativeinterface.RelatedWordEmojiInfo
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.SearchGroupFileResult
|
import com.tencent.qqnt.kernel.nativeinterface.SearchGroupFileResult
|
||||||
@ -135,7 +137,10 @@ abstract class SimpleKernelMsgListener: IKernelMsgListener {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onHitCsRelatedEmojiResult(downloadRelateEmojiResultInfo: DownloadRelateEmojiResultInfo?) {
|
override fun onGuildTopFeedUpdate(gProGuildTopFeedMsg: GProGuildTopFeedMsg?) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onHitCsRelatedEmojiResult(downloadRelateEmojiResultInfo: DownloadRelateEmojiResultInfo?) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,7 +212,10 @@ abstract class SimpleKernelMsgListener: IKernelMsgListener {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onNtFirstViewMsgSyncEnd() {
|
override fun onMsgWithRichLinkInfoUpdate(arrayList: ArrayList<MsgRecord>?) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNtFirstViewMsgSyncEnd() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,7 +266,10 @@ abstract class SimpleKernelMsgListener: IKernelMsgListener {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onRichMediaDownloadComplete(fileTransNotifyInfo: FileTransNotifyInfo?) {
|
override fun onRedTouchChanged() {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRichMediaDownloadComplete(fileTransNotifyInfo: FileTransNotifyInfo?) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -278,7 +289,13 @@ abstract class SimpleKernelMsgListener: IKernelMsgListener {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSysMsgNotification(i2: Int, j2: Long, j3: Long, arrayList: ArrayList<Byte>?) {
|
override fun onSysMsgNotification(
|
||||||
|
i2: Int,
|
||||||
|
j2: Long,
|
||||||
|
j3: Long,
|
||||||
|
z: Boolean,
|
||||||
|
arrayList: ArrayList<Byte>?
|
||||||
|
) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,7 +319,10 @@ abstract class SimpleKernelMsgListener: IKernelMsgListener {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onUserTabStatusChanged(arrayList: ArrayList<TabStatusInfo>?) {
|
override fun onUserSecQualityChanged(queryUserSecQualityRsp: QueryUserSecQualityRsp?) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onUserTabStatusChanged(arrayList: ArrayList<TabStatusInfo>?) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package qq.service.lightapp
|
package qq.service.lightapp
|
||||||
|
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.Contact
|
import com.tencent.qqnt.kernelpublic.nativeinterface.Contact
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
||||||
import qq.service.QQInterfaces
|
import qq.service.QQInterfaces
|
||||||
import qq.service.contact.longPeer
|
import qq.service.contact.longPeer
|
||||||
|
@ -2,7 +2,7 @@ package qq.service.lightapp
|
|||||||
|
|
||||||
import com.tencent.biz.map.trpcprotocol.LbsSendInfo
|
import com.tencent.biz.map.trpcprotocol.LbsSendInfo
|
||||||
import com.tencent.proto.lbsshare.LBSShare
|
import com.tencent.proto.lbsshare.LBSShare
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.Contact
|
import com.tencent.qqnt.kernelpublic.nativeinterface.Contact
|
||||||
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.slice
|
import moe.fuqiuluo.shamrock.tools.slice
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package qq.service.lightapp
|
package qq.service.lightapp
|
||||||
|
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.Contact
|
import com.tencent.qqnt.kernelpublic.nativeinterface.Contact
|
||||||
import io.ktor.client.request.get
|
import io.ktor.client.request.get
|
||||||
import io.ktor.client.statement.bodyAsText
|
import io.ktor.client.statement.bodyAsText
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
package qq.service.msg
|
package qq.service.msg
|
||||||
|
|
||||||
import com.tencent.mobileqq.qroute.QRoute
|
import com.tencent.mobileqq.qroute.QRoute
|
||||||
|
import com.tencent.qqnt.kernelpublic.nativeinterface.Contact
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.MsgRecord
|
import com.tencent.qqnt.kernel.nativeinterface.MsgRecord
|
||||||
import com.tencent.qqnt.msg.api.IMsgService
|
import com.tencent.qqnt.msg.api.IMsgService
|
||||||
import io.grpc.Status
|
import io.kritor.common.ForwardElement
|
||||||
import io.grpc.StatusRuntimeException
|
import io.kritor.common.ForwardMessageBody
|
||||||
import io.kritor.message.ForwardElement
|
|
||||||
import io.kritor.message.ForwardMessageBody
|
|
||||||
import io.kritor.message.Scene
|
|
||||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
import kotlinx.coroutines.withTimeoutOrNull
|
import kotlinx.coroutines.withTimeoutOrNull
|
||||||
import moe.fuqiuluo.shamrock.helper.Level
|
import moe.fuqiuluo.shamrock.helper.Level
|
||||||
@ -20,7 +18,6 @@ import protobuf.auto.toByteArray
|
|||||||
import protobuf.message.*
|
import protobuf.message.*
|
||||||
import protobuf.message.longmsg.*
|
import protobuf.message.longmsg.*
|
||||||
import qq.service.QQInterfaces
|
import qq.service.QQInterfaces
|
||||||
import qq.service.contact.ContactHelper
|
|
||||||
import qq.service.msg.MessageHelper.getMultiMsg
|
import qq.service.msg.MessageHelper.getMultiMsg
|
||||||
import qq.service.ticket.TicketHelper
|
import qq.service.ticket.TicketHelper
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@ -30,9 +27,7 @@ import kotlin.time.Duration.Companion.seconds
|
|||||||
|
|
||||||
internal object ForwardMessageHelper : QQInterfaces() {
|
internal object ForwardMessageHelper : QQInterfaces() {
|
||||||
suspend fun uploadMultiMsg(
|
suspend fun uploadMultiMsg(
|
||||||
chatType: Int,
|
contact: Contact,
|
||||||
peerId: String,
|
|
||||||
fromId: String = peerId,
|
|
||||||
messages: List<ForwardMessageBody>,
|
messages: List<ForwardMessageBody>,
|
||||||
): Result<ForwardElement> {
|
): Result<ForwardElement> {
|
||||||
var i = -1
|
var i = -1
|
||||||
@ -41,127 +36,121 @@ internal object ForwardMessageHelper : QQInterfaces() {
|
|||||||
|
|
||||||
val msgs = messages.mapNotNull { msg ->
|
val msgs = messages.mapNotNull { msg ->
|
||||||
kotlin.runCatching {
|
kotlin.runCatching {
|
||||||
val contact = msg.contact.let {
|
when (msg.forwardMessageCase) {
|
||||||
MessageHelper.generateContact(
|
ForwardMessageBody.ForwardMessageCase.MESSAGE_ID -> {
|
||||||
when (it.scene!!) {
|
val record: MsgRecord = withTimeoutOrNull(5000) {
|
||||||
Scene.GROUP -> MsgConstant.KCHATTYPEGROUP
|
val service = QRoute.api(IMsgService::class.java)
|
||||||
Scene.FRIEND -> MsgConstant.KCHATTYPEC2C
|
suspendCancellableCoroutine { continuation ->
|
||||||
Scene.GUILD -> MsgConstant.KCHATTYPEGUILD
|
service.getMsgsByMsgId(
|
||||||
Scene.STRANGER_FROM_GROUP -> MsgConstant.KCHATTYPETEMPC2CFROMGROUP
|
contact,
|
||||||
Scene.NEARBY -> MsgConstant.KCHATTYPETEMPC2CFROMUNKNOWN
|
arrayListOf(msg.messageId.toLong())
|
||||||
Scene.STRANGER -> MsgConstant.KCHATTYPETEMPC2CFROMUNKNOWN
|
) { code, _, msgRecords ->
|
||||||
Scene.UNRECOGNIZED -> throw StatusRuntimeException(Status.INVALID_ARGUMENT.withDescription("Unrecognized scene"))
|
if (code == 0 && msgRecords.isNotEmpty()) {
|
||||||
}, it.peer, it.subPeer
|
continuation.resume(msgRecords.first())
|
||||||
)
|
} else {
|
||||||
}
|
continuation.resume(null)
|
||||||
if (msg.hasMessageId()) {
|
}
|
||||||
val record: MsgRecord = withTimeoutOrNull(5000) {
|
}
|
||||||
val service = QRoute.api(IMsgService::class.java)
|
continuation.invokeOnCancellation {
|
||||||
suspendCancellableCoroutine { continuation ->
|
|
||||||
service.getMsgsByMsgId(
|
|
||||||
contact,
|
|
||||||
arrayListOf(msg.messageId.toLong())
|
|
||||||
) { code, _, msgRecords ->
|
|
||||||
if (code == 0 && msgRecords.isNotEmpty()) {
|
|
||||||
continuation.resume(msgRecords.first())
|
|
||||||
} else {
|
|
||||||
continuation.resume(null)
|
continuation.resume(null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
continuation.invokeOnCancellation {
|
} ?: error("合并转发消息节点消息(id = ${msg.messageId})获取失败")
|
||||||
continuation.resume(null)
|
PushMsgBody(
|
||||||
}
|
msgHead = ResponseHead(
|
||||||
}
|
peerUid = record.senderUid,
|
||||||
} ?: error("合并转发消息节点消息(id = ${msg.messageId})获取失败")
|
receiverUid = record.peerUid,
|
||||||
PushMsgBody(
|
forward = ResponseForward(
|
||||||
msgHead = ResponseHead(
|
friendName = record.sendNickName
|
||||||
peerUid = record.senderUid,
|
),
|
||||||
receiverUid = record.peerUid,
|
responseGrp = if (record.chatType == MsgConstant.KCHATTYPEGROUP) ResponseGrp(
|
||||||
forward = ResponseForward(
|
groupCode = record.peerUin.toULong(),
|
||||||
friendName = record.sendNickName
|
memberCard = record.sendMemberName,
|
||||||
|
u1 = 2
|
||||||
|
) else null
|
||||||
),
|
),
|
||||||
responseGrp = if (record.chatType == MsgConstant.KCHATTYPEGROUP) ResponseGrp(
|
contentHead = ContentHead(
|
||||||
groupCode = record.peerUin.toULong(),
|
msgType = when (record.chatType) {
|
||||||
memberCard = record.sendMemberName,
|
MsgConstant.KCHATTYPEC2C -> 9
|
||||||
u1 = 2
|
MsgConstant.KCHATTYPEGROUP -> 82
|
||||||
) else null
|
else -> throw UnsupportedOperationException("Unsupported chatType: ${contact.chatType}")
|
||||||
),
|
},
|
||||||
contentHead = ContentHead(
|
msgSubType = if (record.chatType == MsgConstant.KCHATTYPEC2C) 175 else null,
|
||||||
msgType = when (record.chatType) {
|
divSeq = if (record.chatType == MsgConstant.KCHATTYPEC2C) 175 else null,
|
||||||
MsgConstant.KCHATTYPEC2C -> 9
|
msgViaRandom = record.msgId,
|
||||||
MsgConstant.KCHATTYPEGROUP -> 82
|
sequence = record.msgSeq, // idk what this is(i++)
|
||||||
else -> throw UnsupportedOperationException("Unsupported chatType: $chatType")
|
msgTime = record.msgTime,
|
||||||
},
|
u2 = 1,
|
||||||
msgSubType = if (record.chatType == MsgConstant.KCHATTYPEC2C) 175 else null,
|
u6 = 0,
|
||||||
divSeq = if (record.chatType == MsgConstant.KCHATTYPEC2C) 175 else null,
|
u7 = 0,
|
||||||
msgViaRandom = record.msgId,
|
msgSeq = if (record.chatType == MsgConstant.KCHATTYPEC2C) record.msgSeq else null, // seq for dm
|
||||||
sequence = record.msgSeq, // idk what this is(i++)
|
forwardHead = ForwardHead(
|
||||||
msgTime = record.msgTime,
|
u1 = 0,
|
||||||
u2 = 1,
|
u2 = 0,
|
||||||
u6 = 0,
|
u3 = 0,
|
||||||
u7 = 0,
|
ub641 = "",
|
||||||
msgSeq = if (record.chatType == MsgConstant.KCHATTYPEC2C) record.msgSeq else null, // seq for dm
|
avatar = ""
|
||||||
forwardHead = ForwardHead(
|
)
|
||||||
u1 = 0,
|
),
|
||||||
u2 = 0,
|
body = MsgBody(
|
||||||
u3 = 0,
|
richText = record.elements.toKritorReqMessages(contact).toRichText(contact).onFailure {
|
||||||
ub641 = "",
|
error("消息合成失败: ${it.stackTraceToString()}")
|
||||||
avatar = ""
|
}.onSuccess {
|
||||||
|
desc[++i] = record.sendMemberName.ifEmpty { record.sendNickName } + ": " + it.first
|
||||||
|
}.getOrThrow().second
|
||||||
)
|
)
|
||||||
),
|
|
||||||
body = MsgBody(
|
|
||||||
richText = record.elements.toKritorReqMessages(contact).toRichText(contact).onFailure {
|
|
||||||
error("消息合成失败: ${it.stackTraceToString()}")
|
|
||||||
}.onSuccess {
|
|
||||||
desc[++i] = record.sendMemberName.ifEmpty { record.sendNickName } + ": " + it.first
|
|
||||||
}.getOrThrow().second
|
|
||||||
)
|
)
|
||||||
)
|
}
|
||||||
} else {
|
|
||||||
PushMsgBody(
|
ForwardMessageBody.ForwardMessageCase.MESSAGE -> {
|
||||||
msgHead = if (msg.hasSender()) ResponseHead(
|
val _msg = msg.message
|
||||||
peer = if (msg.sender.hasUin()) msg.sender.uin else TicketHelper.getUin().toLong(),
|
PushMsgBody(
|
||||||
peerUid = msg.sender.uid,
|
msgHead = if (_msg.hasSender()) ResponseHead(
|
||||||
receiverUid = TicketHelper.getUid(),
|
peer = if (_msg.sender.hasUin()) _msg.sender.uin else TicketHelper.getUin().toLong(),
|
||||||
forward = ResponseForward(
|
peerUid = _msg.sender.uid,
|
||||||
friendName = if (msg.sender.hasNick()) msg.sender.nick else TicketHelper.getNickname()
|
receiverUid = TicketHelper.getUid(),
|
||||||
|
forward = ResponseForward(
|
||||||
|
friendName = if (_msg.sender.hasNick()) _msg.sender.nick else TicketHelper.getNickname()
|
||||||
|
)
|
||||||
|
) else ResponseHead(
|
||||||
|
peer = TicketHelper.getUin().toLong(),
|
||||||
|
peerUid = TicketHelper.getUid(),
|
||||||
|
receiverUid = TicketHelper.getUid(),
|
||||||
|
forward = ResponseForward(
|
||||||
|
friendName = TicketHelper.getNickname()
|
||||||
|
)
|
||||||
|
),
|
||||||
|
contentHead = ContentHead(
|
||||||
|
msgType = 9,
|
||||||
|
msgSubType = 175,
|
||||||
|
divSeq = 175,
|
||||||
|
msgViaRandom = Random.nextLong(),
|
||||||
|
sequence = _msg.messageSeq,
|
||||||
|
msgTime = _msg.time.toLong(),
|
||||||
|
u2 = 1,
|
||||||
|
u6 = 0,
|
||||||
|
u7 = 0,
|
||||||
|
msgSeq = _msg.messageSeq,
|
||||||
|
forwardHead = ForwardHead(
|
||||||
|
u1 = 0,
|
||||||
|
u2 = 0,
|
||||||
|
u3 = 2,
|
||||||
|
ub641 = "",
|
||||||
|
avatar = ""
|
||||||
|
)
|
||||||
|
),
|
||||||
|
body = MsgBody(
|
||||||
|
richText = _msg.elementsList.toRichText(contact).onSuccess {
|
||||||
|
desc[++i] =
|
||||||
|
(if (_msg.hasSender() && _msg.sender.hasNick()) _msg.sender.nick else TicketHelper.getNickname()) + ": " + it.first
|
||||||
|
}.onFailure {
|
||||||
|
error("消息合成失败: ${it.stackTraceToString()}")
|
||||||
|
}.getOrThrow().second
|
||||||
)
|
)
|
||||||
) else ResponseHead(
|
|
||||||
peer = TicketHelper.getUin().toLong(),
|
|
||||||
peerUid = TicketHelper.getUid(),
|
|
||||||
receiverUid = TicketHelper.getUid(),
|
|
||||||
forward = ResponseForward(
|
|
||||||
friendName = TicketHelper.getNickname()
|
|
||||||
)
|
|
||||||
),
|
|
||||||
contentHead = ContentHead(
|
|
||||||
msgType = 9,
|
|
||||||
msgSubType = 175,
|
|
||||||
divSeq = 175,
|
|
||||||
msgViaRandom = Random.nextLong(),
|
|
||||||
sequence = msg.messageSeq.toLong(),
|
|
||||||
msgTime = msg.messageTime.toLong(),
|
|
||||||
u2 = 1,
|
|
||||||
u6 = 0,
|
|
||||||
u7 = 0,
|
|
||||||
msgSeq = msg.messageSeq.toLong(),
|
|
||||||
forwardHead = ForwardHead(
|
|
||||||
u1 = 0,
|
|
||||||
u2 = 0,
|
|
||||||
u3 = 2,
|
|
||||||
ub641 = "",
|
|
||||||
avatar = ""
|
|
||||||
)
|
|
||||||
),
|
|
||||||
body = MsgBody(
|
|
||||||
richText = msg.elementsList.toRichText(contact).onSuccess {
|
|
||||||
desc[++i] =
|
|
||||||
(if (msg.hasSender() && msg.sender.hasNick()) msg.sender.nick else TicketHelper.getNickname()) + ": " + it.first
|
|
||||||
}.onFailure {
|
|
||||||
error("消息合成失败: ${it.stackTraceToString()}")
|
|
||||||
}.getOrThrow().second
|
|
||||||
)
|
)
|
||||||
)
|
}
|
||||||
|
|
||||||
|
else -> null
|
||||||
}
|
}
|
||||||
}.onFailure {
|
}.onFailure {
|
||||||
LogCenter.log("消息节点解析失败:${it.stackTraceToString()}", Level.WARN)
|
LogCenter.log("消息节点解析失败:${it.stackTraceToString()}", Level.WARN)
|
||||||
@ -192,21 +181,21 @@ internal object ForwardMessageHelper : QQInterfaces() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
val req = LongMsgReq(
|
val req = LongMsgReq(
|
||||||
sendInfo = when (chatType) {
|
sendInfo = when (contact.chatType) {
|
||||||
MsgConstant.KCHATTYPEC2C -> SendLongMsgInfo(
|
MsgConstant.KCHATTYPEC2C -> SendLongMsgInfo(
|
||||||
type = 1,
|
type = 1,
|
||||||
uid = LongMsgUid(if (peerId.startsWith("u_")) peerId else ContactHelper.getUidByUinAsync(peerId.toLong())),
|
uid = LongMsgUid(contact.peerUid),
|
||||||
payload = DeflateTools.gzip(payload.toByteArray())
|
payload = DeflateTools.gzip(payload.toByteArray())
|
||||||
)
|
)
|
||||||
|
|
||||||
MsgConstant.KCHATTYPEGROUP -> SendLongMsgInfo(
|
MsgConstant.KCHATTYPEGROUP -> SendLongMsgInfo(
|
||||||
type = 3,
|
type = 3,
|
||||||
uid = LongMsgUid(fromId),
|
uid = LongMsgUid(contact.peerUid),
|
||||||
groupUin = fromId.toULong(),
|
groupUin = contact.peerUid.toULong(),
|
||||||
payload = DeflateTools.gzip(payload.toByteArray())
|
payload = DeflateTools.gzip(payload.toByteArray())
|
||||||
)
|
)
|
||||||
|
|
||||||
else -> throw UnsupportedOperationException("Unsupported chatType: $chatType")
|
else -> throw UnsupportedOperationException("Unsupported chatType: ${contact.chatType}")
|
||||||
},
|
},
|
||||||
setting = LongMsgSettings(
|
setting = LongMsgSettings(
|
||||||
field1 = 4,
|
field1 = 4,
|
||||||
|
@ -3,7 +3,7 @@ package qq.service.msg
|
|||||||
import com.tencent.mobileqq.qroute.QRoute
|
import com.tencent.mobileqq.qroute.QRoute
|
||||||
import com.tencent.mobileqq.troop.api.ITroopMemberNameService
|
import com.tencent.mobileqq.troop.api.ITroopMemberNameService
|
||||||
import com.tencent.qqnt.kernel.api.IKernelService
|
import com.tencent.qqnt.kernel.api.IKernelService
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.Contact
|
import com.tencent.qqnt.kernelpublic.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.MsgRecord
|
import com.tencent.qqnt.kernel.nativeinterface.MsgRecord
|
||||||
@ -31,6 +31,7 @@ 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.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
|
||||||
@ -108,8 +109,7 @@ internal object MessageHelper: QQInterfaces() {
|
|||||||
if (fromServiceMsg?.wupBuffer == null) {
|
if (fromServiceMsg?.wupBuffer == null) {
|
||||||
return "no response"
|
return "no response"
|
||||||
}
|
}
|
||||||
val body = oidb_sso.OIDBSSOPkg()
|
val body = fromServiceMsg.decodeToOidb()
|
||||||
body.mergeFrom(fromServiceMsg.wupBuffer.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()}", Level.WARN)
|
LogCenter.log("设置群精华失败: ${result.wording.get()}", Level.WARN)
|
||||||
@ -129,8 +129,7 @@ internal object MessageHelper: QQInterfaces() {
|
|||||||
if (fromServiceMsg?.wupBuffer == null) {
|
if (fromServiceMsg?.wupBuffer == null) {
|
||||||
return "no response"
|
return "no response"
|
||||||
}
|
}
|
||||||
val body = oidb_sso.OIDBSSOPkg()
|
val body = fromServiceMsg.decodeToOidb()
|
||||||
body.mergeFrom(fromServiceMsg.wupBuffer.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()}", Level.WARN)
|
LogCenter.log("移除群精华失败: ${result.wording.get()}", Level.WARN)
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
package qq.service.msg
|
package qq.service.msg
|
||||||
|
|
||||||
|
import com.google.protobuf.ByteString
|
||||||
import com.tencent.mobileqq.qroute.QRoute
|
import com.tencent.mobileqq.qroute.QRoute
|
||||||
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.MsgRecord
|
||||||
import com.tencent.qqnt.msg.api.IMsgService
|
import com.tencent.qqnt.msg.api.IMsgService
|
||||||
import io.kritor.message.*
|
import io.kritor.common.*
|
||||||
|
import io.kritor.common.Element.ElementType
|
||||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
import kotlinx.coroutines.withTimeoutOrNull
|
import kotlinx.coroutines.withTimeoutOrNull
|
||||||
import moe.fuqiuluo.shamrock.helper.ActionMsgException
|
import moe.fuqiuluo.shamrock.helper.ActionMsgException
|
||||||
@ -55,11 +57,13 @@ private object MsgConvertor {
|
|||||||
val text = element.textElement
|
val text = element.textElement
|
||||||
val elem = Element.newBuilder()
|
val elem = Element.newBuilder()
|
||||||
if (text.atType != MsgConstant.ATTYPEUNKNOWN) {
|
if (text.atType != MsgConstant.ATTYPEUNKNOWN) {
|
||||||
|
elem.type = ElementType.AT
|
||||||
elem.setAt(AtElement.newBuilder().apply {
|
elem.setAt(AtElement.newBuilder().apply {
|
||||||
this.uid = text.atNtUid
|
this.uid = text.atNtUid
|
||||||
this.uin = ContactHelper.getUinByUidAsync(text.atNtUid).toLong()
|
this.uin = ContactHelper.getUinByUidAsync(text.atNtUid).toLong()
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
elem.type = ElementType.TEXT
|
||||||
elem.setText(TextElement.newBuilder().apply {
|
elem.setText(TextElement.newBuilder().apply {
|
||||||
this.text = text.content
|
this.text = text.content
|
||||||
})
|
})
|
||||||
@ -71,35 +75,51 @@ private object MsgConvertor {
|
|||||||
val face = element.faceElement
|
val face = element.faceElement
|
||||||
val elem = Element.newBuilder()
|
val elem = Element.newBuilder()
|
||||||
if (face.faceType == 5) {
|
if (face.faceType == 5) {
|
||||||
|
elem.type = ElementType.POKE
|
||||||
elem.setPoke(PokeElement.newBuilder().apply {
|
elem.setPoke(PokeElement.newBuilder().apply {
|
||||||
this.id = face.vaspokeId
|
this.id = face.vaspokeId
|
||||||
this.type = face.pokeType
|
this.pokeType = face.pokeType
|
||||||
this.strength = face.pokeStrength
|
this.strength = face.pokeStrength
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
when (face.faceIndex) {
|
when (face.faceIndex) {
|
||||||
114 -> elem.setBasketball(BasketballElement.newBuilder().apply {
|
114 -> {
|
||||||
this.id = face.resultId.ifNullOrEmpty { "0" }?.toInt() ?: 0
|
elem.type = ElementType.BASKETBALL
|
||||||
})
|
elem.setBasketball(BasketballElement.newBuilder().apply {
|
||||||
|
this.id = face.resultId.ifNullOrEmpty { "0" }?.toInt() ?: 0
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
358 -> elem.setDice(DiceElement.newBuilder().apply {
|
358 -> {
|
||||||
this.id = face.resultId.ifNullOrEmpty { "0" }?.toInt() ?: 0
|
elem.type = ElementType.DICE
|
||||||
})
|
elem.setDice(DiceElement.newBuilder().apply {
|
||||||
|
this.id = face.resultId.ifNullOrEmpty { "0" }?.toInt() ?: 0
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
359 -> elem.setRps(RpsElement.newBuilder().apply {
|
359 -> {
|
||||||
this.id = face.resultId.ifNullOrEmpty { "0" }?.toInt() ?: 0
|
elem.type = ElementType.RPS
|
||||||
})
|
elem.setRps(RpsElement.newBuilder().apply {
|
||||||
|
this.id = face.resultId.ifNullOrEmpty { "0" }?.toInt() ?: 0
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
394 -> elem.setFace(FaceElement.newBuilder().apply {
|
394 -> {
|
||||||
this.id = face.faceIndex
|
elem.type = ElementType.FACE
|
||||||
this.isBig = face.faceType == 3
|
elem.setFace(FaceElement.newBuilder().apply {
|
||||||
this.result = face.resultId.ifNullOrEmpty { "1" }?.toInt() ?: 1
|
this.id = face.faceIndex
|
||||||
})
|
this.isBig = face.faceType == 3
|
||||||
|
this.result = face.resultId.ifNullOrEmpty { "1" }?.toInt() ?: 1
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
else -> elem.setFace(FaceElement.newBuilder().apply {
|
else -> {
|
||||||
this.id = face.faceIndex
|
elem.type = ElementType.FACE
|
||||||
this.isBig = face.faceType == 3
|
elem.setFace(FaceElement.newBuilder().apply {
|
||||||
})
|
this.id = face.faceIndex
|
||||||
|
this.isBig = face.faceType == 3
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Result.success(elem.build())
|
return Result.success(elem.build())
|
||||||
@ -134,48 +154,25 @@ private object MsgConvertor {
|
|||||||
LogCenter.log({ "receive image: $image" }, Level.DEBUG)
|
LogCenter.log({ "receive image: $image" }, Level.DEBUG)
|
||||||
|
|
||||||
val elem = Element.newBuilder()
|
val elem = Element.newBuilder()
|
||||||
|
elem.type = ElementType.IMAGE
|
||||||
elem.setImage(ImageElement.newBuilder().apply {
|
elem.setImage(ImageElement.newBuilder().apply {
|
||||||
this.file = md5
|
this.file = ByteString.copyFromUtf8(md5)
|
||||||
this.url = when (record.chatType) {
|
this.fileUrl = RichProtoSvc.getTempPicDownloadUrl(record.chatType, originalUrl, md5, image, storeId,
|
||||||
MsgConstant.KCHATTYPEDISC, MsgConstant.KCHATTYPEGROUP -> RichProtoSvc.getGroupPicDownUrl(
|
peer = when(record.chatType) {
|
||||||
originalUrl = originalUrl,
|
MsgConstant.KCHATTYPEDISC, MsgConstant.KCHATTYPEGROUP -> record.peerUin.toString()
|
||||||
md5 = md5,
|
MsgConstant.KCHATTYPEC2C -> record.senderUin.toString()
|
||||||
fileId = image.fileUuid,
|
MsgConstant.KCHATTYPEGUILD -> record.channelId.ifNullOrEmpty { record.peerUin.toString() } ?: "0"
|
||||||
width = image.picWidth.toUInt(),
|
else -> null
|
||||||
height = image.picHeight.toUInt(),
|
},
|
||||||
sha = "",
|
subPeer = when(record.chatType) {
|
||||||
fileSize = image.fileSize.toULong(),
|
MsgConstant.KCHATTYPEDISC, MsgConstant.KCHATTYPEGROUP -> null
|
||||||
peer = record.peerUin.toString()
|
MsgConstant.KCHATTYPEC2C -> null
|
||||||
)
|
MsgConstant.KCHATTYPEGUILD -> record.guildId ?: "0"
|
||||||
|
else -> null
|
||||||
MsgConstant.KCHATTYPEC2C -> RichProtoSvc.getC2CPicDownUrl(
|
}
|
||||||
originalUrl = originalUrl,
|
)
|
||||||
md5 = md5,
|
this.fileType =
|
||||||
fileId = image.fileUuid,
|
if (image.isFlashPic == true) ImageElement.ImageType.FLASH else if (image.original) ImageElement.ImageType.ORIGIN else ImageElement.ImageType.COMMON
|
||||||
width = image.picWidth.toUInt(),
|
|
||||||
height = image.picHeight.toUInt(),
|
|
||||||
sha = "",
|
|
||||||
fileSize = image.fileSize.toULong(),
|
|
||||||
peer = record.senderUin.toString(),
|
|
||||||
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 = record.channelId.ifNullOrEmpty { record.peerUin.toString() } ?: "0",
|
|
||||||
subPeer = record.guildId ?: "0"
|
|
||||||
)
|
|
||||||
|
|
||||||
else -> throw UnsupportedOperationException("Not supported chat type: ${record.chatType}")
|
|
||||||
}
|
|
||||||
this.type =
|
|
||||||
if (image.isFlashPic == true) ImageType.FLASH else if (image.original) ImageType.ORIGIN else ImageType.COMMON
|
|
||||||
this.subType = image.picSubType
|
this.subType = image.picSubType
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -190,8 +187,9 @@ private object MsgConvertor {
|
|||||||
ptt.fileName.substring(5)
|
ptt.fileName.substring(5)
|
||||||
else ptt.md5HexStr
|
else ptt.md5HexStr
|
||||||
|
|
||||||
|
elem.type = ElementType.VOICE
|
||||||
elem.setVoice(VoiceElement.newBuilder().apply {
|
elem.setVoice(VoiceElement.newBuilder().apply {
|
||||||
this.url = when (record.chatType) {
|
this.fileUrl = when (record.chatType) {
|
||||||
MsgConstant.KCHATTYPEC2C -> RichProtoSvc.getC2CPttDownUrl("0", ptt.fileUuid)
|
MsgConstant.KCHATTYPEC2C -> RichProtoSvc.getC2CPttDownUrl("0", ptt.fileUuid)
|
||||||
MsgConstant.KCHATTYPEGROUP, MsgConstant.KCHATTYPEGUILD -> RichProtoSvc.getGroupPttDownUrl(
|
MsgConstant.KCHATTYPEGROUP, MsgConstant.KCHATTYPEGUILD -> RichProtoSvc.getGroupPttDownUrl(
|
||||||
"0",
|
"0",
|
||||||
@ -201,7 +199,7 @@ private object MsgConvertor {
|
|||||||
|
|
||||||
else -> throw UnsupportedOperationException("Not supported chat type: ${record.chatType}")
|
else -> throw UnsupportedOperationException("Not supported chat type: ${record.chatType}")
|
||||||
}
|
}
|
||||||
this.file = md5
|
this.file = ByteString.copyFromUtf8(md5)
|
||||||
this.magic = ptt.voiceChangeType != MsgConstant.KPTTVOICECHANGETYPENONE
|
this.magic = ptt.voiceChangeType != MsgConstant.KPTTVOICECHANGETYPENONE
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -218,9 +216,10 @@ private object MsgConvertor {
|
|||||||
it[it.size - 2].hex2ByteArray()
|
it[it.size - 2].hex2ByteArray()
|
||||||
}
|
}
|
||||||
} else video.fileName.split(".")[0].hex2ByteArray()
|
} else video.fileName.split(".")[0].hex2ByteArray()
|
||||||
|
elem.type = ElementType.VIDEO
|
||||||
elem.setVideo(VideoElement.newBuilder().apply {
|
elem.setVideo(VideoElement.newBuilder().apply {
|
||||||
this.file = md5.toHexString()
|
this.file = ByteString.copyFromUtf8(md5.toHexString())
|
||||||
this.url = when (record.chatType) {
|
this.fileUrl = when (record.chatType) {
|
||||||
MsgConstant.KCHATTYPEGROUP -> RichProtoSvc.getGroupVideoDownUrl("0", md5, video.fileUuid)
|
MsgConstant.KCHATTYPEGROUP -> RichProtoSvc.getGroupVideoDownUrl("0", md5, video.fileUuid)
|
||||||
MsgConstant.KCHATTYPEC2C -> RichProtoSvc.getC2CVideoDownUrl("0", md5, video.fileUuid)
|
MsgConstant.KCHATTYPEC2C -> RichProtoSvc.getC2CVideoDownUrl("0", md5, video.fileUuid)
|
||||||
MsgConstant.KCHATTYPEGUILD -> RichProtoSvc.getGroupVideoDownUrl("0", md5, video.fileUuid)
|
MsgConstant.KCHATTYPEGUILD -> RichProtoSvc.getGroupVideoDownUrl("0", md5, video.fileUuid)
|
||||||
@ -233,6 +232,7 @@ private object MsgConvertor {
|
|||||||
suspend fun convertMarketFace(record: MsgRecord, element: MsgElement): Result<Element> {
|
suspend fun convertMarketFace(record: MsgRecord, element: MsgElement): Result<Element> {
|
||||||
val marketFace = element.marketFaceElement
|
val marketFace = element.marketFaceElement
|
||||||
val elem = Element.newBuilder()
|
val elem = Element.newBuilder()
|
||||||
|
elem.type = ElementType.MARKET_FACE
|
||||||
elem.setMarketFace(MarketFaceElement.newBuilder().apply {
|
elem.setMarketFace(MarketFaceElement.newBuilder().apply {
|
||||||
this.id = marketFace.emojiId.lowercase()
|
this.id = marketFace.emojiId.lowercase()
|
||||||
})
|
})
|
||||||
@ -245,6 +245,7 @@ private object MsgConvertor {
|
|||||||
when (data["app"].asString) {
|
when (data["app"].asString) {
|
||||||
"com.tencent.multimsg" -> {
|
"com.tencent.multimsg" -> {
|
||||||
val info = data["meta"].asJsonObject["detail"].asJsonObject
|
val info = data["meta"].asJsonObject["detail"].asJsonObject
|
||||||
|
elem.type = ElementType.FORWARD
|
||||||
elem.setForward(ForwardElement.newBuilder().apply {
|
elem.setForward(ForwardElement.newBuilder().apply {
|
||||||
this.resId = info["resid"].asString
|
this.resId = info["resid"].asString
|
||||||
this.uniseq = info["uniseq"].asString
|
this.uniseq = info["uniseq"].asString
|
||||||
@ -257,6 +258,7 @@ private object MsgConvertor {
|
|||||||
|
|
||||||
"com.tencent.troopsharecard" -> {
|
"com.tencent.troopsharecard" -> {
|
||||||
val info = data["meta"].asJsonObject["contact"].asJsonObject
|
val info = data["meta"].asJsonObject["contact"].asJsonObject
|
||||||
|
elem.type = ElementType.CONTACT
|
||||||
elem.setContact(ContactElement.newBuilder().apply {
|
elem.setContact(ContactElement.newBuilder().apply {
|
||||||
this.scene = Scene.GROUP
|
this.scene = Scene.GROUP
|
||||||
this.peer = info["jumpUrl"].asString.split("group_code=")[1]
|
this.peer = info["jumpUrl"].asString.split("group_code=")[1]
|
||||||
@ -265,6 +267,7 @@ private object MsgConvertor {
|
|||||||
|
|
||||||
"com.tencent.contact.lua" -> {
|
"com.tencent.contact.lua" -> {
|
||||||
val info = data["meta"].asJsonObject["contact"].asJsonObject
|
val info = data["meta"].asJsonObject["contact"].asJsonObject
|
||||||
|
elem.type = ElementType.CONTACT
|
||||||
elem.setContact(ContactElement.newBuilder().apply {
|
elem.setContact(ContactElement.newBuilder().apply {
|
||||||
this.scene = Scene.FRIEND
|
this.scene = Scene.FRIEND
|
||||||
this.peer = info["jumpUrl"].asString.split("uin=")[1]
|
this.peer = info["jumpUrl"].asString.split("uin=")[1]
|
||||||
@ -273,6 +276,7 @@ private object MsgConvertor {
|
|||||||
|
|
||||||
"com.tencent.map" -> {
|
"com.tencent.map" -> {
|
||||||
val info = data["meta"].asJsonObject["Location.Search"].asJsonObject
|
val info = data["meta"].asJsonObject["Location.Search"].asJsonObject
|
||||||
|
elem.type = ElementType.LOCATION
|
||||||
elem.setLocation(LocationElement.newBuilder().apply {
|
elem.setLocation(LocationElement.newBuilder().apply {
|
||||||
this.lat = info["lat"].asString.toFloat()
|
this.lat = info["lat"].asString.toFloat()
|
||||||
this.lon = info["lng"].asString.toFloat()
|
this.lon = info["lng"].asString.toFloat()
|
||||||
@ -281,9 +285,12 @@ private object MsgConvertor {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> elem.setJson(JsonElement.newBuilder().apply {
|
else -> {
|
||||||
this.json = data.toString()
|
elem.type = ElementType.JSON
|
||||||
})
|
elem.setJson(JsonElement.newBuilder().apply {
|
||||||
|
this.json = data.toString()
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return Result.success(elem.build())
|
return Result.success(elem.build())
|
||||||
}
|
}
|
||||||
@ -291,6 +298,7 @@ private object MsgConvertor {
|
|||||||
suspend fun convertReply(record: MsgRecord, element: MsgElement): Result<Element> {
|
suspend fun convertReply(record: MsgRecord, element: MsgElement): Result<Element> {
|
||||||
val reply = element.replyElement
|
val reply = element.replyElement
|
||||||
val elem = Element.newBuilder()
|
val elem = Element.newBuilder()
|
||||||
|
elem.type = ElementType.REPLY
|
||||||
elem.setReply(ReplyElement.newBuilder().apply {
|
elem.setReply(ReplyElement.newBuilder().apply {
|
||||||
val msgSeq = reply.replayMsgSeq
|
val msgSeq = reply.replayMsgSeq
|
||||||
val contact = MessageHelper.generateContact(record)
|
val contact = MessageHelper.generateContact(record)
|
||||||
@ -304,9 +312,9 @@ private object MsgConvertor {
|
|||||||
}
|
}
|
||||||
if (sourceRecords.isNullOrEmpty()) {
|
if (sourceRecords.isNullOrEmpty()) {
|
||||||
LogCenter.log("无法查询到回复的消息ID: seq = $msgSeq", Level.WARN)
|
LogCenter.log("无法查询到回复的消息ID: seq = $msgSeq", Level.WARN)
|
||||||
this.messageId = reply.replayMsgId
|
this.messageId = reply.replayMsgId.toString()
|
||||||
} else {
|
} else {
|
||||||
this.messageId = sourceRecords.first().msgId
|
this.messageId = sourceRecords.first().msgId.toString()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return Result.success(elem.build())
|
return Result.success(elem.build())
|
||||||
@ -332,6 +340,7 @@ private object MsgConvertor {
|
|||||||
else -> RichProtoSvc.getGroupFileDownUrl(record.peerUin, fileId, bizId)
|
else -> RichProtoSvc.getGroupFileDownUrl(record.peerUin, fileId, bizId)
|
||||||
}
|
}
|
||||||
val elem = Element.newBuilder()
|
val elem = Element.newBuilder()
|
||||||
|
elem.type = ElementType.FILE
|
||||||
elem.setFile(FileElement.newBuilder().apply {
|
elem.setFile(FileElement.newBuilder().apply {
|
||||||
this.name = fileName
|
this.name = fileName
|
||||||
this.size = fileSize
|
this.size = fileSize
|
||||||
@ -347,6 +356,7 @@ private object MsgConvertor {
|
|||||||
suspend fun convertMarkdown(record: MsgRecord, element: MsgElement): Result<Element> {
|
suspend fun convertMarkdown(record: MsgRecord, element: MsgElement): Result<Element> {
|
||||||
val markdown = element.markdownElement
|
val markdown = element.markdownElement
|
||||||
val elem = Element.newBuilder()
|
val elem = Element.newBuilder()
|
||||||
|
elem.type = ElementType.MARKDOWN
|
||||||
elem.setMarkdown(MarkdownElement.newBuilder().apply {
|
elem.setMarkdown(MarkdownElement.newBuilder().apply {
|
||||||
this.markdown = markdown.content
|
this.markdown = markdown.content
|
||||||
})
|
})
|
||||||
@ -356,6 +366,7 @@ private object MsgConvertor {
|
|||||||
suspend fun convertBubbleFace(record: MsgRecord, element: MsgElement): Result<Element> {
|
suspend fun convertBubbleFace(record: MsgRecord, element: MsgElement): Result<Element> {
|
||||||
val bubbleFace = element.faceBubbleElement
|
val bubbleFace = element.faceBubbleElement
|
||||||
val elem = Element.newBuilder()
|
val elem = Element.newBuilder()
|
||||||
|
elem.type = ElementType.BUBBLE_FACE
|
||||||
elem.setBubbleFace(BubbleFaceElement.newBuilder().apply {
|
elem.setBubbleFace(BubbleFaceElement.newBuilder().apply {
|
||||||
this.id = bubbleFace.yellowFaceInfo.index
|
this.id = bubbleFace.yellowFaceInfo.index
|
||||||
this.count = bubbleFace.faceCount ?: 1
|
this.count = bubbleFace.faceCount ?: 1
|
||||||
@ -366,9 +377,10 @@ private object MsgConvertor {
|
|||||||
suspend fun convertInlineKeyboard(record: MsgRecord, element: MsgElement): Result<Element> {
|
suspend fun convertInlineKeyboard(record: MsgRecord, element: MsgElement): Result<Element> {
|
||||||
val inlineKeyboard = element.inlineKeyboardElement
|
val inlineKeyboard = element.inlineKeyboardElement
|
||||||
val elem = Element.newBuilder()
|
val elem = Element.newBuilder()
|
||||||
elem.setButton(ButtonElement.newBuilder().apply {
|
elem.type = ElementType.KEYBOARD
|
||||||
|
elem.setKeyboard(KeyboardElement.newBuilder().apply {
|
||||||
inlineKeyboard.rows.forEach { row ->
|
inlineKeyboard.rows.forEach { row ->
|
||||||
this.addRows(ButtonRow.newBuilder().apply {
|
this.addRows(KeyboardRow.newBuilder().apply {
|
||||||
row.buttons.forEach buttonsLoop@{ button ->
|
row.buttons.forEach buttonsLoop@{ button ->
|
||||||
if (button == null) return@buttonsLoop
|
if (button == null) return@buttonsLoop
|
||||||
this.addButtons(Button.newBuilder().apply {
|
this.addButtons(Button.newBuilder().apply {
|
||||||
|
@ -2,9 +2,11 @@
|
|||||||
|
|
||||||
package qq.service.msg
|
package qq.service.msg
|
||||||
|
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.Contact
|
import com.tencent.qqnt.kernelpublic.nativeinterface.Contact
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
||||||
import io.kritor.message.*
|
import io.kritor.common.*
|
||||||
|
import io.kritor.common.Element.ElementType
|
||||||
|
import io.kritor.common.ImageElement.ImageType
|
||||||
import kotlinx.io.core.ByteReadPacket
|
import kotlinx.io.core.ByteReadPacket
|
||||||
import kotlinx.io.core.discardExact
|
import kotlinx.io.core.discardExact
|
||||||
import kotlinx.io.core.readUInt
|
import kotlinx.io.core.readUInt
|
||||||
@ -62,9 +64,9 @@ suspend fun List<Elem>.toKritorResponseMessages(contact: Contact): ArrayList<Ele
|
|||||||
kritorMessages.add(Element.newBuilder().apply {
|
kritorMessages.add(Element.newBuilder().apply {
|
||||||
this.type = ElementType.IMAGE
|
this.type = ElementType.IMAGE
|
||||||
this.image = ImageElement.newBuilder().apply {
|
this.image = ImageElement.newBuilder().apply {
|
||||||
this.fileName = md5
|
this.fileMd5 = md5
|
||||||
this.type = if (customFace.origin == true) ImageType.ORIGIN else ImageType.COMMON
|
this.fileType = if (customFace.origin == true) ImageType.ORIGIN else ImageType.COMMON
|
||||||
this.url = when (contact.chatType) {
|
this.fileUrl = when (contact.chatType) {
|
||||||
MsgConstant.KCHATTYPEDISC, MsgConstant.KCHATTYPEGROUP -> RichProtoSvc.getGroupPicDownUrl(
|
MsgConstant.KCHATTYPEDISC, MsgConstant.KCHATTYPEGROUP -> RichProtoSvc.getGroupPicDownUrl(
|
||||||
origUrl,
|
origUrl,
|
||||||
md5
|
md5
|
||||||
@ -82,9 +84,9 @@ suspend fun List<Elem>.toKritorResponseMessages(contact: Contact): ArrayList<Ele
|
|||||||
kritorMessages.add(Element.newBuilder().apply {
|
kritorMessages.add(Element.newBuilder().apply {
|
||||||
this.type = ElementType.IMAGE
|
this.type = ElementType.IMAGE
|
||||||
this.image = ImageElement.newBuilder().apply {
|
this.image = ImageElement.newBuilder().apply {
|
||||||
this.fileName = md5
|
this.fileMd5 = md5
|
||||||
this.type = if (element.notOnlineImage?.original == true) ImageType.ORIGIN else ImageType.COMMON
|
this.fileType = if (element.notOnlineImage?.original == true) ImageType.ORIGIN else ImageType.COMMON
|
||||||
this.url = when (contact.chatType) {
|
this.fileUrl = when (contact.chatType) {
|
||||||
MsgConstant.KCHATTYPEDISC, MsgConstant.KCHATTYPEGROUP -> RichProtoSvc.getGroupPicDownUrl(
|
MsgConstant.KCHATTYPEDISC, MsgConstant.KCHATTYPEGROUP -> RichProtoSvc.getGroupPicDownUrl(
|
||||||
origUrl,
|
origUrl,
|
||||||
md5
|
md5
|
||||||
@ -112,7 +114,7 @@ suspend fun List<Elem>.toKritorResponseMessages(contact: Contact): ArrayList<Ele
|
|||||||
kritorMessages.add(Element.newBuilder().apply {
|
kritorMessages.add(Element.newBuilder().apply {
|
||||||
this.type = ElementType.REPLY
|
this.type = ElementType.REPLY
|
||||||
this.reply = ReplyElement.newBuilder().apply {
|
this.reply = ReplyElement.newBuilder().apply {
|
||||||
this.messageId = msgId
|
this.messageId = msgId.toString()
|
||||||
}.build()
|
}.build()
|
||||||
}.build())
|
}.build())
|
||||||
} else if (element.lightApp != null) {
|
} else if (element.lightApp != null) {
|
||||||
@ -225,9 +227,9 @@ suspend fun List<Elem>.toKritorResponseMessages(contact: Contact): ArrayList<Ele
|
|||||||
46 -> {
|
46 -> {
|
||||||
val buttonExtra = commonElem.elem!!.decodeProtobuf<ButtonExtra>()
|
val buttonExtra = commonElem.elem!!.decodeProtobuf<ButtonExtra>()
|
||||||
kritorMessages.add(
|
kritorMessages.add(
|
||||||
Element.newBuilder().setButton(ButtonElement.newBuilder().apply {
|
Element.newBuilder().setKeyboard(KeyboardElement.newBuilder().apply {
|
||||||
this.addAllRows(buttonExtra.field1!!.rows!!.map { row ->
|
this.addAllRows(buttonExtra.field1!!.rows!!.map { row ->
|
||||||
ButtonRow.newBuilder().apply {
|
KeyboardRow.newBuilder().apply {
|
||||||
this.addAllButtons(row.buttons!!.map { button ->
|
this.addAllButtons(row.buttons!!.map { button ->
|
||||||
Button.newBuilder().apply {
|
Button.newBuilder().apply {
|
||||||
this.id = button.id
|
this.id = button.id
|
||||||
@ -256,7 +258,7 @@ suspend fun List<Elem>.toKritorResponseMessages(contact: Contact): ArrayList<Ele
|
|||||||
})
|
})
|
||||||
}.build()
|
}.build()
|
||||||
})
|
})
|
||||||
this.applicationId = buttonExtra.field1?.appid?.toLong() ?: 0L
|
this.botAppid = buttonExtra.field1?.appid?.toLong() ?: 0L
|
||||||
}.build()).build()
|
}.build()).build()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package qq.service.msg
|
package qq.service.msg
|
||||||
|
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
import android.util.Base64
|
|
||||||
import androidx.exifinterface.media.ExifInterface
|
import androidx.exifinterface.media.ExifInterface
|
||||||
import com.tencent.mobileqq.emoticon.QQSysFaceUtil
|
import com.tencent.mobileqq.emoticon.QQSysFaceUtil
|
||||||
import com.tencent.mobileqq.pb.ByteStringMicro
|
import com.tencent.mobileqq.pb.ByteStringMicro
|
||||||
@ -9,17 +8,18 @@ import com.tencent.mobileqq.qroute.QRoute
|
|||||||
import com.tencent.qphone.base.remote.ToServiceMsg
|
import com.tencent.qphone.base.remote.ToServiceMsg
|
||||||
import com.tencent.qqnt.aio.adapter.api.IAIOPttApi
|
import com.tencent.qqnt.aio.adapter.api.IAIOPttApi
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.*
|
import com.tencent.qqnt.kernel.nativeinterface.*
|
||||||
|
import com.tencent.qqnt.kernelpublic.nativeinterface.Contact
|
||||||
|
import com.tencent.qqnt.kernel.nativeinterface.FaceElement
|
||||||
|
import com.tencent.qqnt.kernel.nativeinterface.MarkdownElement
|
||||||
|
import com.tencent.qqnt.kernel.nativeinterface.MarketFaceElement
|
||||||
|
import com.tencent.qqnt.kernel.nativeinterface.ReplyElement
|
||||||
|
import com.tencent.qqnt.kernel.nativeinterface.TextElement
|
||||||
import com.tencent.qqnt.msg.api.IMsgService
|
import com.tencent.qqnt.msg.api.IMsgService
|
||||||
import io.kritor.message.AtElement
|
import io.kritor.common.*
|
||||||
import io.kritor.message.Button
|
import io.kritor.common.Element.ElementType
|
||||||
import io.kritor.message.Element
|
import io.kritor.common.ImageElement.ImageType
|
||||||
import io.kritor.message.ElementType
|
import io.kritor.common.MusicElement.MusicPlatform
|
||||||
import io.kritor.message.ElementType.*
|
import io.kritor.common.VideoElement
|
||||||
import io.kritor.message.ImageElement
|
|
||||||
import io.kritor.message.ImageType
|
|
||||||
import io.kritor.message.MusicPlatform
|
|
||||||
import io.kritor.message.Scene
|
|
||||||
import io.kritor.message.VoiceElement
|
|
||||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
import kotlinx.coroutines.withTimeoutOrNull
|
import kotlinx.coroutines.withTimeoutOrNull
|
||||||
import moe.fuqiuluo.shamrock.config.EnableOldBDH
|
import moe.fuqiuluo.shamrock.config.EnableOldBDH
|
||||||
@ -77,27 +77,27 @@ private typealias NtConvertor = suspend (Contact, Long, Element) -> Result<MsgEl
|
|||||||
|
|
||||||
object NtMsgConvertor {
|
object NtMsgConvertor {
|
||||||
private val ntConvertors = mapOf<ElementType, NtConvertor>(
|
private val ntConvertors = mapOf<ElementType, NtConvertor>(
|
||||||
TEXT to ::textConvertor,
|
ElementType.TEXT to ::textConvertor,
|
||||||
AT to ::atConvertor,
|
ElementType.AT to ::atConvertor,
|
||||||
FACE to ::faceConvertor,
|
ElementType.FACE to ::faceConvertor,
|
||||||
BUBBLE_FACE to ::bubbleFaceConvertor,
|
ElementType.BUBBLE_FACE to ::bubbleFaceConvertor,
|
||||||
REPLY to ::replyConvertor,
|
ElementType.REPLY to ::replyConvertor,
|
||||||
IMAGE to ::imageConvertor,
|
ElementType.IMAGE to ::imageConvertor,
|
||||||
VOICE to ::voiceConvertor,
|
ElementType.VOICE to ::voiceConvertor,
|
||||||
VIDEO to ::videoConvertor,
|
ElementType.VIDEO to ::videoConvertor,
|
||||||
BASKETBALL to ::basketballConvertor,
|
ElementType.BASKETBALL to ::basketballConvertor,
|
||||||
DICE to ::diceConvertor,
|
ElementType.DICE to ::diceConvertor,
|
||||||
RPS to ::rpsConvertor,
|
ElementType.RPS to ::rpsConvertor,
|
||||||
POKE to ::pokeConvertor,
|
ElementType.POKE to ::pokeConvertor,
|
||||||
MUSIC to ::musicConvertor,
|
ElementType.MUSIC to ::musicConvertor,
|
||||||
WEATHER to ::weatherConvertor,
|
ElementType.WEATHER to ::weatherConvertor,
|
||||||
LOCATION to ::locationConvertor,
|
ElementType.LOCATION to ::locationConvertor,
|
||||||
SHARE to ::shareConvertor,
|
ElementType.SHARE to ::shareConvertor,
|
||||||
CONTACT to ::contactConvertor,
|
ElementType.CONTACT to ::contactConvertor,
|
||||||
JSON to ::jsonConvertor,
|
ElementType.JSON to ::jsonConvertor,
|
||||||
FORWARD to ::forwardConvertor,
|
ElementType.FORWARD to ::forwardConvertor,
|
||||||
MARKDOWN to ::markdownConvertor,
|
ElementType.MARKDOWN to ::markdownConvertor,
|
||||||
BUTTON to ::buttonConvertor,
|
ElementType.KEYBOARD to ::buttonConvertor,
|
||||||
)
|
)
|
||||||
|
|
||||||
suspend fun convertToNtMsgs(contact: Contact, msgId: Long, msgs: Messages): ArrayList<MsgElement> {
|
suspend fun convertToNtMsgs(contact: Contact, msgId: Long, msgs: Messages): ArrayList<MsgElement> {
|
||||||
@ -135,41 +135,22 @@ object NtMsgConvertor {
|
|||||||
|
|
||||||
val elem = MsgElement()
|
val elem = MsgElement()
|
||||||
val at = TextElement()
|
val at = TextElement()
|
||||||
if (sourceAt.at.accountCase == AtElement.AccountCase.UIN) {
|
val uid = sourceAt.at.uid
|
||||||
val uin = sourceAt.at.uin
|
if (uid == "all" || uid == "0") {
|
||||||
if (uin == 0L) {
|
at.content = "@全体成员"
|
||||||
at.content = "@全体成员"
|
at.atType = MsgConstant.ATTYPEALL
|
||||||
at.atType = MsgConstant.ATTYPEALL
|
at.atNtUid = "0"
|
||||||
at.atNtUid = "0"
|
|
||||||
} else {
|
|
||||||
val info = GroupHelper.getTroopMemberInfoByUinV2(contact.peerUid, uin.toString(), true).onFailure {
|
|
||||||
LogCenter.log("无法获取群成员信息: contact=$contact, id=${uin}", Level.WARN)
|
|
||||||
}.getOrNull()
|
|
||||||
at.content = "@${
|
|
||||||
info?.troopnick.ifNullOrEmpty { info?.friendnick }
|
|
||||||
?: uin.toString()
|
|
||||||
}"
|
|
||||||
at.atType = MsgConstant.ATTYPEONE
|
|
||||||
at.atNtUid = ContactHelper.getUidByUinAsync(uin)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
val uid = sourceAt.at.uid
|
val uin = ContactHelper.getUinByUidAsync(uid)
|
||||||
if (uid == "all" || uid == "0") {
|
val info = GroupHelper.getTroopMemberInfoByUinV2(contact.peerUid, uin, true).onFailure {
|
||||||
at.content = "@全体成员"
|
LogCenter.log("无法获取群成员信息: contact=$contact, id=${uin}", Level.WARN)
|
||||||
at.atType = MsgConstant.ATTYPEALL
|
}.getOrNull()
|
||||||
at.atNtUid = "0"
|
at.content = "@${
|
||||||
} else {
|
info?.troopnick.ifNullOrEmpty { info?.friendnick }
|
||||||
val uin = ContactHelper.getUinByUidAsync(uid)
|
?: uin
|
||||||
val info = GroupHelper.getTroopMemberInfoByUinV2(contact.peerUid, uin, true).onFailure {
|
}"
|
||||||
LogCenter.log("无法获取群成员信息: contact=$contact, id=${uin}", Level.WARN)
|
at.atType = MsgConstant.ATTYPEONE
|
||||||
}.getOrNull()
|
at.atNtUid = uid
|
||||||
at.content = "@${
|
|
||||||
info?.troopnick.ifNullOrEmpty { info?.friendnick }
|
|
||||||
?: uin
|
|
||||||
}"
|
|
||||||
at.atType = MsgConstant.ATTYPEONE
|
|
||||||
at.atNtUid = uid
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
elem.textElement = at
|
elem.textElement = at
|
||||||
elem.elementType = MsgConstant.KELEMTYPETEXT
|
elem.elementType = MsgConstant.KELEMTYPETEXT
|
||||||
@ -215,7 +196,11 @@ object NtMsgConvertor {
|
|||||||
return Result.success(elem)
|
return Result.success(elem)
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun bubbleFaceConvertor(contact: Contact, msgId: Long, sourceBubbleFace: Element): Result<MsgElement> {
|
private suspend fun bubbleFaceConvertor(
|
||||||
|
contact: Contact,
|
||||||
|
msgId: Long,
|
||||||
|
sourceBubbleFace: Element
|
||||||
|
): Result<MsgElement> {
|
||||||
val faceId = sourceBubbleFace.bubbleFace.id
|
val faceId = sourceBubbleFace.bubbleFace.id
|
||||||
val local = QQSysFaceUtil.convertToLocal(faceId)
|
val local = QQSysFaceUtil.convertToLocal(faceId)
|
||||||
val name = QQSysFaceUtil.getFaceDescription(local)
|
val name = QQSysFaceUtil.getFaceDescription(local)
|
||||||
@ -242,7 +227,7 @@ object NtMsgConvertor {
|
|||||||
element.elementType = MsgConstant.KELEMTYPEREPLY
|
element.elementType = MsgConstant.KELEMTYPEREPLY
|
||||||
val reply = ReplyElement()
|
val reply = ReplyElement()
|
||||||
|
|
||||||
reply.replayMsgId = sourceReply.reply.messageId
|
reply.replayMsgId = sourceReply.reply.messageId.toLong()
|
||||||
reply.sourceMsgIdInRecords = reply.replayMsgId
|
reply.sourceMsgIdInRecords = reply.replayMsgId
|
||||||
|
|
||||||
if (reply.replayMsgId == 0L) {
|
if (reply.replayMsgId == 0L) {
|
||||||
@ -251,9 +236,10 @@ object NtMsgConvertor {
|
|||||||
|
|
||||||
withTimeoutOrNull(3000) {
|
withTimeoutOrNull(3000) {
|
||||||
suspendCancellableCoroutine {
|
suspendCancellableCoroutine {
|
||||||
QRoute.api(IMsgService::class.java).getMsgsByMsgId(contact, arrayListOf(reply.replayMsgId)) { _, _, records ->
|
QRoute.api(IMsgService::class.java)
|
||||||
it.resume(records)
|
.getMsgsByMsgId(contact, arrayListOf(reply.replayMsgId)) { _, _, records ->
|
||||||
}
|
it.resume(records)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}?.firstOrNull()?.let {
|
}?.firstOrNull()?.let {
|
||||||
reply.replayMsgSeq = it.msgSeq
|
reply.replayMsgSeq = it.msgSeq
|
||||||
@ -268,27 +254,33 @@ object NtMsgConvertor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun imageConvertor(contact: Contact, msgId: Long, sourceImage: Element): Result<MsgElement> {
|
private suspend fun imageConvertor(contact: Contact, msgId: Long, sourceImage: Element): Result<MsgElement> {
|
||||||
val isOriginal = sourceImage.image.type == ImageType.ORIGIN
|
val isOriginal = sourceImage.image.fileType == ImageType.ORIGIN
|
||||||
val isFlash = sourceImage.image.type == ImageType.FLASH
|
val isFlash = sourceImage.image.fileType == ImageType.FLASH
|
||||||
val file = when(sourceImage.image.dataCase!!) {
|
val file = when (sourceImage.image.dataCase!!) {
|
||||||
ImageElement.DataCase.FILE_NAME -> {
|
ImageElement.DataCase.FILE_NAME -> {
|
||||||
val fileMd5 = sourceImage.image.fileName.replace(regex = "[{}\\-]".toRegex(), replacement = "").split(".")[0].lowercase()
|
val fileMd5 = sourceImage.image.fileName.replace(regex = "[{}\\-]".toRegex(), replacement = "")
|
||||||
|
.split(".")[0].lowercase()
|
||||||
FileUtils.getFileByMd5(fileMd5)
|
FileUtils.getFileByMd5(fileMd5)
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageElement.DataCase.FILE_PATH -> {
|
ImageElement.DataCase.FILE_PATH -> {
|
||||||
val filePath = sourceImage.image.filePath
|
val filePath = sourceImage.image.filePath
|
||||||
File(filePath).inputStream().use {
|
File(filePath).inputStream().use {
|
||||||
FileUtils.saveFileToCache(it)
|
FileUtils.saveFileToCache(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImageElement.DataCase.FILE_BASE64 -> {
|
|
||||||
FileUtils.saveFileToCache(ByteArrayInputStream(
|
ImageElement.DataCase.FILE -> {
|
||||||
Base64.decode(sourceImage.image.fileBase64, Base64.DEFAULT)
|
FileUtils.saveFileToCache(
|
||||||
))
|
ByteArrayInputStream(
|
||||||
|
sourceImage.image.file.toByteArray()
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
ImageElement.DataCase.URL -> {
|
|
||||||
|
ImageElement.DataCase.FILE_URL -> {
|
||||||
val tmp = FileUtils.getTmpFile()
|
val tmp = FileUtils.getTmpFile()
|
||||||
if(DownloadUtils.download(sourceImage.image.url, tmp)) {
|
if (DownloadUtils.download(sourceImage.image.fileUrl, tmp)) {
|
||||||
tmp.inputStream().use {
|
tmp.inputStream().use {
|
||||||
FileUtils.saveFileToCache(it)
|
FileUtils.saveFileToCache(it)
|
||||||
}.also {
|
}.also {
|
||||||
@ -296,16 +288,20 @@ object NtMsgConvertor {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
tmp.delete()
|
tmp.delete()
|
||||||
return Result.failure(LogicException("图片资源下载失败: ${sourceImage.image.url}"))
|
return Result.failure(LogicException("图片资源下载失败: ${sourceImage.image.fileUrl}"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageElement.DataCase.DATA_NOT_SET -> return Result.failure(IllegalArgumentException("ImageElement data is not set"))
|
ImageElement.DataCase.DATA_NOT_SET -> return Result.failure(IllegalArgumentException("ImageElement data is not set"))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (EnableOldBDH.get()) {
|
if (EnableOldBDH.get()) {
|
||||||
Transfer with when (contact.chatType) {
|
Transfer with when (contact.chatType) {
|
||||||
MsgConstant.KCHATTYPEGROUP -> Troop(contact.peerUid)
|
MsgConstant.KCHATTYPEGROUP -> Troop(contact.peerUid)
|
||||||
MsgConstant.KCHATTYPETEMPC2CFROMGROUP, MsgConstant.KCHATTYPEC2C -> Private(contact.longPeer().toString())
|
MsgConstant.KCHATTYPETEMPC2CFROMGROUP, MsgConstant.KCHATTYPEC2C -> Private(
|
||||||
|
contact.longPeer().toString()
|
||||||
|
)
|
||||||
|
|
||||||
MsgConstant.KCHATTYPEGUILD -> Troop(contact.peerUid)
|
MsgConstant.KCHATTYPEGUILD -> Troop(contact.peerUid)
|
||||||
else -> return Result.failure(Exception("Not supported chatType(${contact.chatType}) for PictureMsg"))
|
else -> return Result.failure(Exception("Not supported chatType(${contact.chatType}) for PictureMsg"))
|
||||||
} trans PictureResource(file)
|
} trans PictureResource(file)
|
||||||
@ -360,25 +356,29 @@ object NtMsgConvertor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun voiceConvertor(contact: Contact, msgId: Long, sourceVoice: Element): Result<MsgElement> {
|
private suspend fun voiceConvertor(contact: Contact, msgId: Long, sourceVoice: Element): Result<MsgElement> {
|
||||||
var file = when(sourceVoice.voice.dataCase!!) {
|
var file = when (sourceVoice.voice.dataCase!!) {
|
||||||
VoiceElement.DataCase.FILE_NAME -> {
|
VoiceElement.DataCase.FILE_NAME -> {
|
||||||
val fileMd5 = sourceVoice.voice.fileName.replace(regex = "[{}\\-]".toRegex(), replacement = "").split(".")[0].lowercase()
|
val fileMd5 = sourceVoice.voice.fileName.replace(regex = "[{}\\-]".toRegex(), replacement = "")
|
||||||
|
.split(".")[0].lowercase()
|
||||||
FileUtils.getFileByMd5(fileMd5)
|
FileUtils.getFileByMd5(fileMd5)
|
||||||
}
|
}
|
||||||
|
|
||||||
VoiceElement.DataCase.FILE_PATH -> {
|
VoiceElement.DataCase.FILE_PATH -> {
|
||||||
val filePath = sourceVoice.voice.filePath
|
val filePath = sourceVoice.voice.filePath
|
||||||
File(filePath).inputStream().use {
|
File(filePath).inputStream().use {
|
||||||
FileUtils.saveFileToCache(it)
|
FileUtils.saveFileToCache(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VoiceElement.DataCase.FILE_BASE64 -> {
|
|
||||||
FileUtils.saveFileToCache(ByteArrayInputStream(
|
VoiceElement.DataCase.FILE -> {
|
||||||
Base64.decode(sourceVoice.voice.fileBase64, Base64.DEFAULT)
|
FileUtils.saveFileToCache(
|
||||||
))
|
sourceVoice.voice.file.toByteArray().inputStream()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
VoiceElement.DataCase.URL -> {
|
|
||||||
|
VoiceElement.DataCase.FILE_URL -> {
|
||||||
val tmp = FileUtils.getTmpFile()
|
val tmp = FileUtils.getTmpFile()
|
||||||
if(DownloadUtils.download(sourceVoice.voice.url, tmp)) {
|
if (DownloadUtils.download(sourceVoice.voice.fileUrl, tmp)) {
|
||||||
tmp.inputStream().use {
|
tmp.inputStream().use {
|
||||||
FileUtils.saveFileToCache(it)
|
FileUtils.saveFileToCache(it)
|
||||||
}.also {
|
}.also {
|
||||||
@ -386,9 +386,10 @@ object NtMsgConvertor {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
tmp.delete()
|
tmp.delete()
|
||||||
return Result.failure(LogicException("音频资源下载失败: ${sourceVoice.voice.url}"))
|
return Result.failure(LogicException("音频资源下载失败: ${sourceVoice.voice.fileUrl}"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VoiceElement.DataCase.DATA_NOT_SET -> return Result.failure(IllegalArgumentException("VoiceElement data is not set"))
|
VoiceElement.DataCase.DATA_NOT_SET -> return Result.failure(IllegalArgumentException("VoiceElement data is not set"))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -439,7 +440,10 @@ object NtMsgConvertor {
|
|||||||
if (EnableOldBDH.get()) {
|
if (EnableOldBDH.get()) {
|
||||||
if (!(Transfer with when (contact.chatType) {
|
if (!(Transfer with when (contact.chatType) {
|
||||||
MsgConstant.KCHATTYPEGROUP -> Troop(contact.peerUid)
|
MsgConstant.KCHATTYPEGROUP -> Troop(contact.peerUid)
|
||||||
MsgConstant.KCHATTYPETEMPC2CFROMGROUP, MsgConstant.KCHATTYPEC2C -> Private(contact.longPeer().toString())
|
MsgConstant.KCHATTYPETEMPC2CFROMGROUP, MsgConstant.KCHATTYPEC2C -> Private(
|
||||||
|
contact.longPeer().toString()
|
||||||
|
)
|
||||||
|
|
||||||
MsgConstant.KCHATTYPEGUILD -> Troop(contact.peerUid)
|
MsgConstant.KCHATTYPEGUILD -> Troop(contact.peerUid)
|
||||||
else -> return Result.failure(Exception("Not supported chatType(${contact.chatType}) for VoiceMsg"))
|
else -> return Result.failure(Exception("Not supported chatType(${contact.chatType}) for VoiceMsg"))
|
||||||
} trans VoiceResource(file))
|
} trans VoiceResource(file))
|
||||||
@ -485,27 +489,31 @@ object NtMsgConvertor {
|
|||||||
|
|
||||||
private suspend fun videoConvertor(contact: Contact, msgId: Long, sourceVideo: Element): Result<MsgElement> {
|
private suspend fun videoConvertor(contact: Contact, msgId: Long, sourceVideo: Element): Result<MsgElement> {
|
||||||
val elem = MsgElement()
|
val elem = MsgElement()
|
||||||
val video = VideoElement()
|
val video = com.tencent.qqnt.kernel.nativeinterface.VideoElement()
|
||||||
|
|
||||||
val file = when(sourceVideo.video.dataCase!!) {
|
val file = when (sourceVideo.video.dataCase!!) {
|
||||||
io.kritor.message.VideoElement.DataCase.FILE_NAME -> {
|
VideoElement.DataCase.FILE -> {
|
||||||
val fileMd5 = sourceVideo.video.fileName.replace(regex = "[{}\\-]".toRegex(), replacement = "").split(".")[0].lowercase()
|
FileUtils.saveFileToCache(
|
||||||
|
sourceVideo.video.file.toByteArray().inputStream()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
VideoElement.DataCase.FILE_NAME -> {
|
||||||
|
val fileMd5 = sourceVideo.video.fileName.replace(regex = "[{}\\-]".toRegex(), replacement = "")
|
||||||
|
.split(".")[0].lowercase()
|
||||||
FileUtils.getFileByMd5(fileMd5)
|
FileUtils.getFileByMd5(fileMd5)
|
||||||
}
|
}
|
||||||
io.kritor.message.VideoElement.DataCase.FILE_PATH -> {
|
|
||||||
|
VideoElement.DataCase.FILE_PATH -> {
|
||||||
val filePath = sourceVideo.video.filePath
|
val filePath = sourceVideo.video.filePath
|
||||||
File(filePath).inputStream().use {
|
File(filePath).inputStream().use {
|
||||||
FileUtils.saveFileToCache(it)
|
FileUtils.saveFileToCache(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
io.kritor.message.VideoElement.DataCase.FILE_BASE64 -> {
|
|
||||||
FileUtils.saveFileToCache(ByteArrayInputStream(
|
VideoElement.DataCase.FILE_URL -> {
|
||||||
Base64.decode(sourceVideo.video.fileBase64, Base64.DEFAULT)
|
|
||||||
))
|
|
||||||
}
|
|
||||||
io.kritor.message.VideoElement.DataCase.URL -> {
|
|
||||||
val tmp = FileUtils.getTmpFile()
|
val tmp = FileUtils.getTmpFile()
|
||||||
if(DownloadUtils.download(sourceVideo.video.url, tmp)) {
|
if (DownloadUtils.download(sourceVideo.video.fileUrl, tmp)) {
|
||||||
tmp.inputStream().use {
|
tmp.inputStream().use {
|
||||||
FileUtils.saveFileToCache(it)
|
FileUtils.saveFileToCache(it)
|
||||||
}.also {
|
}.also {
|
||||||
@ -513,10 +521,11 @@ object NtMsgConvertor {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
tmp.delete()
|
tmp.delete()
|
||||||
return Result.failure(LogicException("视频资源下载失败: ${sourceVideo.video.url}"))
|
return Result.failure(LogicException("视频资源下载失败: ${sourceVideo.video.fileUrl}"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
io.kritor.message.VideoElement.DataCase.DATA_NOT_SET -> return Result.failure(IllegalArgumentException("VideoElement data is not set"))
|
|
||||||
|
VideoElement.DataCase.DATA_NOT_SET -> return Result.failure(IllegalArgumentException("VideoElement data is not set"))
|
||||||
}
|
}
|
||||||
|
|
||||||
video.videoMd5 = QQNTWrapperUtil.CppProxy.genFileMd5Hex(file.absolutePath)
|
video.videoMd5 = QQNTWrapperUtil.CppProxy.genFileMd5Hex(file.absolutePath)
|
||||||
@ -543,7 +552,10 @@ object NtMsgConvertor {
|
|||||||
if (EnableOldBDH.get()) {
|
if (EnableOldBDH.get()) {
|
||||||
Transfer with when (contact.chatType) {
|
Transfer with when (contact.chatType) {
|
||||||
MsgConstant.KCHATTYPEGROUP -> Troop(contact.peerUid)
|
MsgConstant.KCHATTYPEGROUP -> Troop(contact.peerUid)
|
||||||
MsgConstant.KCHATTYPETEMPC2CFROMGROUP, MsgConstant.KCHATTYPEC2C -> Private(contact.longPeer().toString())
|
MsgConstant.KCHATTYPETEMPC2CFROMGROUP, MsgConstant.KCHATTYPEC2C -> Private(
|
||||||
|
contact.longPeer().toString()
|
||||||
|
)
|
||||||
|
|
||||||
MsgConstant.KCHATTYPEGUILD -> Troop(contact.peerUid)
|
MsgConstant.KCHATTYPEGUILD -> Troop(contact.peerUid)
|
||||||
else -> return Result.failure(Exception("Not supported chatType(${contact.chatType}) for VideoMsg"))
|
else -> return Result.failure(Exception("Not supported chatType(${contact.chatType}) for VideoMsg"))
|
||||||
} trans VideoResource(file, File(thumbPath.toString()))
|
} trans VideoResource(file, File(thumbPath.toString()))
|
||||||
@ -567,7 +579,11 @@ object NtMsgConvertor {
|
|||||||
return Result.success(elem)
|
return Result.success(elem)
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun basketballConvertor(contact: Contact, msgId: Long, sourceBasketball: Element): Result<MsgElement> {
|
private suspend fun basketballConvertor(
|
||||||
|
contact: Contact,
|
||||||
|
msgId: Long,
|
||||||
|
sourceBasketball: Element
|
||||||
|
): Result<MsgElement> {
|
||||||
val elem = MsgElement()
|
val elem = MsgElement()
|
||||||
elem.elementType = MsgConstant.KELEMTYPEFACE
|
elem.elementType = MsgConstant.KELEMTYPEFACE
|
||||||
val face = FaceElement()
|
val face = FaceElement()
|
||||||
@ -622,7 +638,7 @@ object NtMsgConvertor {
|
|||||||
face.faceText = ""
|
face.faceText = ""
|
||||||
face.faceType = 5
|
face.faceType = 5
|
||||||
face.packId = null
|
face.packId = null
|
||||||
face.pokeType = sourcePoke.poke.type
|
face.pokeType = sourcePoke.poke.pokeType
|
||||||
face.spokeSummary = ""
|
face.spokeSummary = ""
|
||||||
face.doubleHit = 0
|
face.doubleHit = 0
|
||||||
face.vaspokeId = sourcePoke.poke.id
|
face.vaspokeId = sourcePoke.poke.id
|
||||||
@ -647,14 +663,14 @@ object NtMsgConvertor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MusicPlatform.NetEase -> {
|
MusicPlatform.NETEASE -> {
|
||||||
val id = sourceMusic.music.id
|
val id = sourceMusic.music.id
|
||||||
if (!MusicHelper.tryShare163MusicById(contact, msgId, id)) {
|
if (!MusicHelper.tryShare163MusicById(contact, msgId, id)) {
|
||||||
LogCenter.log("无法发送网易云音乐分享", Level.ERROR)
|
LogCenter.log("无法发送网易云音乐分享", Level.ERROR)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MusicPlatform.Custom -> {
|
MusicPlatform.CUSTOM -> {
|
||||||
val data = sourceMusic.music.custom
|
val data = sourceMusic.music.custom
|
||||||
ArkMsgHelper.tryShareMusic(
|
ArkMsgHelper.tryShareMusic(
|
||||||
contact,
|
contact,
|
||||||
@ -697,7 +713,11 @@ object NtMsgConvertor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun locationConvertor(contact: Contact, msgId: Long, sourceLocation: Element): Result<MsgElement> {
|
private suspend fun locationConvertor(contact: Contact, msgId: Long, sourceLocation: Element): Result<MsgElement> {
|
||||||
LbsHelper.tryShareLocation(contact, sourceLocation.location.lat.toDouble(), sourceLocation.location.lon.toDouble()).onFailure {
|
LbsHelper.tryShareLocation(
|
||||||
|
contact,
|
||||||
|
sourceLocation.location.lat.toDouble(),
|
||||||
|
sourceLocation.location.lon.toDouble()
|
||||||
|
).onFailure {
|
||||||
LogCenter.log("无法发送位置分享", Level.ERROR)
|
LogCenter.log("无法发送位置分享", Level.ERROR)
|
||||||
}
|
}
|
||||||
return Result.failure(ActionMsgException)
|
return Result.failure(ActionMsgException)
|
||||||
@ -801,7 +821,8 @@ object NtMsgConvertor {
|
|||||||
val action = button.action
|
val action = button.action
|
||||||
val permission = action.permission
|
val permission = action.permission
|
||||||
return runCatching {
|
return runCatching {
|
||||||
InlineKeyboardButton(button.id, renderData.label, renderData.visitedLabel, renderData.style,
|
InlineKeyboardButton(
|
||||||
|
button.id, renderData.label, renderData.visitedLabel, renderData.style,
|
||||||
action.type, 0,
|
action.type, 0,
|
||||||
action.unsupportedTips,
|
action.unsupportedTips,
|
||||||
action.data, false,
|
action.data, false,
|
||||||
@ -811,7 +832,8 @@ object NtMsgConvertor {
|
|||||||
false, 0, false, arrayListOf()
|
false, 0, false, arrayListOf()
|
||||||
)
|
)
|
||||||
}.getOrElse {
|
}.getOrElse {
|
||||||
InlineKeyboardButton(button.id, renderData.label, renderData.visitedLabel, renderData.style,
|
InlineKeyboardButton(
|
||||||
|
button.id, renderData.label, renderData.visitedLabel, renderData.style,
|
||||||
action.type, 0,
|
action.type, 0,
|
||||||
action.unsupportedTips,
|
action.unsupportedTips,
|
||||||
action.data, false,
|
action.data, false,
|
||||||
@ -826,7 +848,7 @@ object NtMsgConvertor {
|
|||||||
elem.elementType = MsgConstant.KELEMTYPEINLINEKEYBOARD
|
elem.elementType = MsgConstant.KELEMTYPEINLINEKEYBOARD
|
||||||
val rows = arrayListOf<InlineKeyboardRow>()
|
val rows = arrayListOf<InlineKeyboardRow>()
|
||||||
|
|
||||||
val keyboard = sourceButton.button
|
val keyboard = sourceButton.keyboard
|
||||||
keyboard.rowsList.forEach { row ->
|
keyboard.rowsList.forEach { row ->
|
||||||
val buttons = arrayListOf<InlineKeyboardButton>()
|
val buttons = arrayListOf<InlineKeyboardButton>()
|
||||||
row.buttonsList.forEach { button ->
|
row.buttonsList.forEach { button ->
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
package qq.service.msg
|
package qq.service.msg
|
||||||
|
|
||||||
import com.tencent.mobileqq.qroute.QRoute
|
import com.tencent.mobileqq.qroute.QRoute
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.Contact
|
import com.tencent.qqnt.kernelpublic.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.msg.api.IMsgService
|
import com.tencent.qqnt.msg.api.IMsgService
|
||||||
import io.kritor.message.*
|
import io.kritor.common.*
|
||||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
import kotlinx.coroutines.withTimeoutOrNull
|
import kotlinx.coroutines.withTimeoutOrNull
|
||||||
import moe.fuqiuluo.shamrock.helper.ActionMsgException
|
import moe.fuqiuluo.shamrock.helper.ActionMsgException
|
||||||
@ -73,7 +73,7 @@ private object ReqMsgConvertor {
|
|||||||
if (face.faceType == 5) {
|
if (face.faceType == 5) {
|
||||||
elem.setPoke(PokeElement.newBuilder().apply {
|
elem.setPoke(PokeElement.newBuilder().apply {
|
||||||
this.id = face.vaspokeId
|
this.id = face.vaspokeId
|
||||||
this.type = face.pokeType
|
this.pokeType = face.pokeType
|
||||||
this.strength = face.pokeStrength
|
this.strength = face.pokeStrength
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
@ -135,47 +135,10 @@ private object ReqMsgConvertor {
|
|||||||
|
|
||||||
val elem = Element.newBuilder()
|
val elem = Element.newBuilder()
|
||||||
elem.setImage(ImageElement.newBuilder().apply {
|
elem.setImage(ImageElement.newBuilder().apply {
|
||||||
this.file = md5
|
this.fileMd5 = md5
|
||||||
this.url = when (contact.chatType) {
|
this.fileUrl = RichProtoSvc.getTempPicDownloadUrl(contact.chatType, originalUrl, md5, image, storeId, contact.peerUid, contact.guildId)
|
||||||
MsgConstant.KCHATTYPEDISC, MsgConstant.KCHATTYPEGROUP -> RichProtoSvc.getGroupPicDownUrl(
|
this.fileType =
|
||||||
originalUrl = originalUrl,
|
if (image.isFlashPic == true) ImageElement.ImageType.FLASH else if (image.original) ImageElement.ImageType.ORIGIN else ImageElement.ImageType.COMMON
|
||||||
md5 = md5,
|
|
||||||
fileId = image.fileUuid,
|
|
||||||
width = image.picWidth.toUInt(),
|
|
||||||
height = image.picHeight.toUInt(),
|
|
||||||
sha = "",
|
|
||||||
fileSize = image.fileSize.toULong(),
|
|
||||||
peer = contact.longPeer().toString()
|
|
||||||
)
|
|
||||||
|
|
||||||
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 = contact.longPeer().toString(),
|
|
||||||
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 = contact.longPeer().toString(),
|
|
||||||
subPeer = "0"
|
|
||||||
)
|
|
||||||
|
|
||||||
else -> throw UnsupportedOperationException("Not supported chat type: ${contact.chatType}")
|
|
||||||
}
|
|
||||||
this.type =
|
|
||||||
if (image.isFlashPic == true) ImageType.FLASH else if (image.original) ImageType.ORIGIN else ImageType.COMMON
|
|
||||||
this.subType = image.picSubType
|
this.subType = image.picSubType
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -191,7 +154,7 @@ private object ReqMsgConvertor {
|
|||||||
else ptt.md5HexStr
|
else ptt.md5HexStr
|
||||||
|
|
||||||
elem.setVoice(VoiceElement.newBuilder().apply {
|
elem.setVoice(VoiceElement.newBuilder().apply {
|
||||||
this.url = when (contact.chatType) {
|
this.fileUrl = when (contact.chatType) {
|
||||||
MsgConstant.KCHATTYPEC2C -> RichProtoSvc.getC2CPttDownUrl("0", ptt.fileUuid)
|
MsgConstant.KCHATTYPEC2C -> RichProtoSvc.getC2CPttDownUrl("0", ptt.fileUuid)
|
||||||
MsgConstant.KCHATTYPEGROUP, MsgConstant.KCHATTYPEGUILD -> RichProtoSvc.getGroupPttDownUrl(
|
MsgConstant.KCHATTYPEGROUP, MsgConstant.KCHATTYPEGUILD -> RichProtoSvc.getGroupPttDownUrl(
|
||||||
"0",
|
"0",
|
||||||
@ -201,7 +164,7 @@ private object ReqMsgConvertor {
|
|||||||
|
|
||||||
else -> throw UnsupportedOperationException("Not supported chat type: ${contact.chatType}")
|
else -> throw UnsupportedOperationException("Not supported chat type: ${contact.chatType}")
|
||||||
}
|
}
|
||||||
this.file = md5
|
this.fileMd5 = md5
|
||||||
this.magic = ptt.voiceChangeType != MsgConstant.KPTTVOICECHANGETYPENONE
|
this.magic = ptt.voiceChangeType != MsgConstant.KPTTVOICECHANGETYPENONE
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -219,8 +182,8 @@ private object ReqMsgConvertor {
|
|||||||
}
|
}
|
||||||
} else video.fileName.split(".")[0].hex2ByteArray()
|
} else video.fileName.split(".")[0].hex2ByteArray()
|
||||||
elem.setVideo(VideoElement.newBuilder().apply {
|
elem.setVideo(VideoElement.newBuilder().apply {
|
||||||
this.file = md5.toHexString()
|
this.fileMd5 = md5.toHexString()
|
||||||
this.url = when (contact.chatType) {
|
this.fileUrl = when (contact.chatType) {
|
||||||
MsgConstant.KCHATTYPEGROUP -> RichProtoSvc.getGroupVideoDownUrl("0", md5, video.fileUuid)
|
MsgConstant.KCHATTYPEGROUP -> RichProtoSvc.getGroupVideoDownUrl("0", md5, video.fileUuid)
|
||||||
MsgConstant.KCHATTYPEC2C -> RichProtoSvc.getC2CVideoDownUrl("0", md5, video.fileUuid)
|
MsgConstant.KCHATTYPEC2C -> RichProtoSvc.getC2CVideoDownUrl("0", md5, video.fileUuid)
|
||||||
MsgConstant.KCHATTYPEGUILD -> RichProtoSvc.getGroupVideoDownUrl("0", md5, video.fileUuid)
|
MsgConstant.KCHATTYPEGUILD -> RichProtoSvc.getGroupVideoDownUrl("0", md5, video.fileUuid)
|
||||||
@ -233,7 +196,11 @@ private object ReqMsgConvertor {
|
|||||||
suspend fun convertMarketFace(contact: Contact, element: MsgElement): Result<Element> {
|
suspend fun convertMarketFace(contact: Contact, element: MsgElement): Result<Element> {
|
||||||
val marketFace = element.marketFaceElement
|
val marketFace = element.marketFaceElement
|
||||||
val elem = Element.newBuilder()
|
val elem = Element.newBuilder()
|
||||||
return Result.failure(ActionMsgException)
|
elem.setMarketFace(MarketFaceElement.newBuilder().apply {
|
||||||
|
this.id = marketFace.emojiId
|
||||||
|
})
|
||||||
|
// TODO
|
||||||
|
return Result.success(elem.build())
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun convertStructJson(contact: Contact, element: MsgElement): Result<Element> {
|
suspend fun convertStructJson(contact: Contact, element: MsgElement): Result<Element> {
|
||||||
@ -300,9 +267,9 @@ private object ReqMsgConvertor {
|
|||||||
}
|
}
|
||||||
if (sourceRecords.isNullOrEmpty()) {
|
if (sourceRecords.isNullOrEmpty()) {
|
||||||
LogCenter.log("无法查询到回复的消息ID: seq = $msgSeq", Level.WARN)
|
LogCenter.log("无法查询到回复的消息ID: seq = $msgSeq", Level.WARN)
|
||||||
this.messageId = reply.replayMsgId
|
this.messageId = reply.replayMsgId.toString()
|
||||||
} else {
|
} else {
|
||||||
this.messageId = sourceRecords.first().msgId
|
this.messageId = sourceRecords.first().msgId.toString()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return Result.success(elem.build())
|
return Result.success(elem.build())
|
||||||
@ -362,9 +329,9 @@ private object ReqMsgConvertor {
|
|||||||
suspend fun convertInlineKeyboard(contact: Contact, element: MsgElement): Result<Element> {
|
suspend fun convertInlineKeyboard(contact: Contact, element: MsgElement): Result<Element> {
|
||||||
val inlineKeyboard = element.inlineKeyboardElement
|
val inlineKeyboard = element.inlineKeyboardElement
|
||||||
val elem = Element.newBuilder()
|
val elem = Element.newBuilder()
|
||||||
elem.setButton(ButtonElement.newBuilder().apply {
|
elem.setKeyboard(KeyboardElement.newBuilder().apply {
|
||||||
this.addAllRows(inlineKeyboard.rows.map { row ->
|
this.addAllRows(inlineKeyboard.rows.map { row ->
|
||||||
ButtonRow.newBuilder().apply {
|
KeyboardRow.newBuilder().apply {
|
||||||
this.addAllButtons(row.buttons.map { button ->
|
this.addAllButtons(row.buttons.map { button ->
|
||||||
Button.newBuilder().apply {
|
Button.newBuilder().apply {
|
||||||
this.id = button.id
|
this.id = button.id
|
||||||
@ -393,7 +360,7 @@ private object ReqMsgConvertor {
|
|||||||
})
|
})
|
||||||
}.build()
|
}.build()
|
||||||
})
|
})
|
||||||
this.applicationId = inlineKeyboard.botAppid
|
this.botAppid = inlineKeyboard.botAppid
|
||||||
})
|
})
|
||||||
return Result.success(elem.build())
|
return Result.success(elem.build())
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,13 @@
|
|||||||
package qq.service.msg
|
package qq.service.msg
|
||||||
|
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
import android.util.Base64
|
|
||||||
import androidx.exifinterface.media.ExifInterface
|
import androidx.exifinterface.media.ExifInterface
|
||||||
import com.tencent.mobileqq.qroute.QRoute
|
import com.tencent.mobileqq.qroute.QRoute
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.Contact
|
import com.tencent.qqnt.kernelpublic.nativeinterface.Contact
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
||||||
import com.tencent.qqnt.msg.api.IMsgService
|
import com.tencent.qqnt.msg.api.IMsgService
|
||||||
import io.kritor.message.AtElement
|
import io.kritor.common.Element
|
||||||
import io.kritor.message.Element
|
import io.kritor.common.ImageElement
|
||||||
import io.kritor.message.ElementType
|
|
||||||
import io.kritor.message.ImageElement
|
|
||||||
import io.kritor.message.ImageType
|
|
||||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
import kotlinx.coroutines.withTimeoutOrNull
|
import kotlinx.coroutines.withTimeoutOrNull
|
||||||
import moe.fuqiuluo.shamrock.helper.Level
|
import moe.fuqiuluo.shamrock.helper.Level
|
||||||
@ -68,7 +64,7 @@ suspend fun List<Element>.toRichText(contact: Contact): Result<Pair<String, Rich
|
|||||||
forEach {
|
forEach {
|
||||||
try {
|
try {
|
||||||
when(it.type!!) {
|
when(it.type!!) {
|
||||||
ElementType.TEXT -> {
|
Element.ElementType.TEXT -> {
|
||||||
val text = it.text.text
|
val text = it.text.text
|
||||||
val elem = Elem(
|
val elem = Elem(
|
||||||
text = TextMsg(text)
|
text = TextMsg(text)
|
||||||
@ -76,13 +72,11 @@ suspend fun List<Element>.toRichText(contact: Contact): Result<Pair<String, Rich
|
|||||||
elems.add(elem)
|
elems.add(elem)
|
||||||
summary.append(text)
|
summary.append(text)
|
||||||
}
|
}
|
||||||
ElementType.AT -> {
|
Element.ElementType.AT -> {
|
||||||
when (contact.chatType) {
|
when (contact.chatType) {
|
||||||
MsgConstant.KCHATTYPEGROUP -> {
|
MsgConstant.KCHATTYPEGROUP -> {
|
||||||
val qq = when (it.at.accountCase) {
|
val qq = ContactHelper.getUinByUidAsync(it.at.uid)
|
||||||
AtElement.AccountCase.UIN -> it.at.uin.toString()
|
|
||||||
else -> ContactHelper.getUinByUidAsync(it.at.uid)
|
|
||||||
}
|
|
||||||
val type: Int
|
val type: Int
|
||||||
val nick = if (it.at.uid == "all" || it.at.uin == 0L) {
|
val nick = if (it.at.uid == "all" || it.at.uin == 0L) {
|
||||||
type = 1
|
type = 1
|
||||||
@ -112,10 +106,7 @@ suspend fun List<Element>.toRichText(contact: Contact): Result<Pair<String, Rich
|
|||||||
}
|
}
|
||||||
|
|
||||||
MsgConstant.KCHATTYPEC2C -> {
|
MsgConstant.KCHATTYPEC2C -> {
|
||||||
val qq = when (it.at.accountCase) {
|
val qq = ContactHelper.getUinByUidAsync(it.at.uid)
|
||||||
AtElement.AccountCase.UIN -> it.at.uin.toString()
|
|
||||||
else -> ContactHelper.getUinByUidAsync(it.at.uid)
|
|
||||||
}
|
|
||||||
val display = "@" + (ContactHelper.getProfileCard(qq.toLong()).onSuccess {
|
val display = "@" + (ContactHelper.getProfileCard(qq.toLong()).onSuccess {
|
||||||
it.strNick.ifNullOrEmpty { qq }
|
it.strNick.ifNullOrEmpty { qq }
|
||||||
}.onFailure {
|
}.onFailure {
|
||||||
@ -130,7 +121,7 @@ suspend fun List<Element>.toRichText(contact: Contact): Result<Pair<String, Rich
|
|||||||
else -> throw UnsupportedOperationException("Unsupported chatType($contact) for AtMsg")
|
else -> throw UnsupportedOperationException("Unsupported chatType($contact) for AtMsg")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ElementType.FACE -> {
|
Element.ElementType.FACE -> {
|
||||||
val faceId = it.face.id
|
val faceId = it.face.id
|
||||||
val elem = if (it.face.isBig) {
|
val elem = if (it.face.isBig) {
|
||||||
Elem(
|
Elem(
|
||||||
@ -159,12 +150,12 @@ suspend fun List<Element>.toRichText(contact: Contact): Result<Pair<String, Rich
|
|||||||
elems.add(elem)
|
elems.add(elem)
|
||||||
summary.append("[表情]")
|
summary.append("[表情]")
|
||||||
}
|
}
|
||||||
ElementType.BUBBLE_FACE -> throw UnsupportedOperationException("Unsupported ElementType.BUBBLE_FACE")
|
Element.ElementType.BUBBLE_FACE -> throw UnsupportedOperationException("Unsupported Element.ElementType.BUBBLE_FACE")
|
||||||
ElementType.REPLY -> {
|
Element.ElementType.REPLY -> {
|
||||||
val msgId = it.reply.messageId
|
val msgId = it.reply.messageId
|
||||||
withTimeoutOrNull(3000) {
|
withTimeoutOrNull(3000) {
|
||||||
suspendCancellableCoroutine {
|
suspendCancellableCoroutine {
|
||||||
QRoute.api(IMsgService::class.java).getMsgsByMsgId(contact, arrayListOf(msgId)) { _, _, records ->
|
QRoute.api(IMsgService::class.java).getMsgsByMsgId(contact, arrayListOf(msgId.toLong())) { _, _, records ->
|
||||||
it.resume(records)
|
it.resume(records)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -191,9 +182,9 @@ suspend fun List<Element>.toRichText(contact: Contact): Result<Pair<String, Rich
|
|||||||
}
|
}
|
||||||
summary.append("[回复消息]")
|
summary.append("[回复消息]")
|
||||||
}
|
}
|
||||||
ElementType.IMAGE -> {
|
Element.ElementType.IMAGE -> {
|
||||||
val type = it.image.type
|
val type = it.image.fileType
|
||||||
val isOriginal = type == ImageType.ORIGIN
|
val isOriginal = type == ImageElement.ImageType.ORIGIN
|
||||||
val file = when(it.image.dataCase!!) {
|
val file = when(it.image.dataCase!!) {
|
||||||
ImageElement.DataCase.FILE_NAME -> {
|
ImageElement.DataCase.FILE_NAME -> {
|
||||||
val fileMd5 = it.image.fileName.replace(regex = "[{}\\-]".toRegex(), replacement = "").split(".")[0].lowercase()
|
val fileMd5 = it.image.fileName.replace(regex = "[{}\\-]".toRegex(), replacement = "").split(".")[0].lowercase()
|
||||||
@ -205,16 +196,16 @@ suspend fun List<Element>.toRichText(contact: Contact): Result<Pair<String, Rich
|
|||||||
FileUtils.saveFileToCache(it)
|
FileUtils.saveFileToCache(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImageElement.DataCase.FILE_BASE64 -> {
|
ImageElement.DataCase.FILE -> {
|
||||||
FileUtils.saveFileToCache(
|
FileUtils.saveFileToCache(
|
||||||
ByteArrayInputStream(
|
ByteArrayInputStream(
|
||||||
Base64.decode(it.image.fileBase64, Base64.DEFAULT)
|
it.image.file.toByteArray()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
ImageElement.DataCase.URL -> {
|
ImageElement.DataCase.FILE_URL -> {
|
||||||
val tmp = FileUtils.getTmpFile()
|
val tmp = FileUtils.getTmpFile()
|
||||||
if(DownloadUtils.download(it.image.url, tmp)) {
|
if(DownloadUtils.download(it.image.fileUrl, tmp)) {
|
||||||
tmp.inputStream().use {
|
tmp.inputStream().use {
|
||||||
FileUtils.saveFileToCache(it)
|
FileUtils.saveFileToCache(it)
|
||||||
}.also {
|
}.also {
|
||||||
@ -222,7 +213,7 @@ suspend fun List<Element>.toRichText(contact: Contact): Result<Pair<String, Rich
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
tmp.delete()
|
tmp.delete()
|
||||||
throw LogicException("图片资源下载失败: ${it.image.url}")
|
throw LogicException("图片资源下载失败: ${it.image.fileUrl}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImageElement.DataCase.DATA_NOT_SET -> throw IllegalArgumentException("ImageElement data is not set")
|
ImageElement.DataCase.DATA_NOT_SET -> throw IllegalArgumentException("ImageElement data is not set")
|
||||||
@ -352,10 +343,10 @@ suspend fun List<Element>.toRichText(contact: Contact): Result<Pair<String, Rich
|
|||||||
|
|
||||||
summary.append("[图片]")
|
summary.append("[图片]")
|
||||||
}
|
}
|
||||||
ElementType.VOICE -> throw UnsupportedOperationException("Unsupported ElementType.VOICE")
|
Element.ElementType.VOICE -> throw UnsupportedOperationException("Unsupported Element.ElementType.VOICE")
|
||||||
ElementType.VIDEO -> throw UnsupportedOperationException("Unsupported ElementType.VIDEO")
|
Element.ElementType.VIDEO -> throw UnsupportedOperationException("Unsupported Element.ElementType.VIDEO")
|
||||||
ElementType.BASKETBALL -> throw UnsupportedOperationException("Unsupported ElementType.BASKETBALL")
|
Element.ElementType.BASKETBALL -> throw UnsupportedOperationException("Unsupported Element.ElementType.BASKETBALL")
|
||||||
ElementType.DICE -> {
|
Element.ElementType.DICE -> {
|
||||||
val elem = Elem(
|
val elem = Elem(
|
||||||
commonElem = CommonElem(
|
commonElem = CommonElem(
|
||||||
serviceType = 37,
|
serviceType = 37,
|
||||||
@ -375,7 +366,7 @@ suspend fun List<Element>.toRichText(contact: Contact): Result<Pair<String, Rich
|
|||||||
elems.add(elem)
|
elems.add(elem)
|
||||||
summary .append( "[骰子]" )
|
summary .append( "[骰子]" )
|
||||||
}
|
}
|
||||||
ElementType.RPS -> {
|
Element.ElementType.RPS -> {
|
||||||
val elem = Elem(
|
val elem = Elem(
|
||||||
commonElem = CommonElem(
|
commonElem = CommonElem(
|
||||||
serviceType = 37,
|
serviceType = 37,
|
||||||
@ -395,12 +386,12 @@ suspend fun List<Element>.toRichText(contact: Contact): Result<Pair<String, Rich
|
|||||||
elems.add(elem)
|
elems.add(elem)
|
||||||
summary .append( "[包剪锤]" )
|
summary .append( "[包剪锤]" )
|
||||||
}
|
}
|
||||||
ElementType.POKE -> {
|
Element.ElementType.POKE -> {
|
||||||
val elem = Elem(
|
val elem = Elem(
|
||||||
commonElem = CommonElem(
|
commonElem = CommonElem(
|
||||||
serviceType = 2,
|
serviceType = 2,
|
||||||
elem = PokeExtra(
|
elem = PokeExtra(
|
||||||
type = it.poke.type,
|
type = it.poke.pokeType,
|
||||||
field7 = 0,
|
field7 = 0,
|
||||||
field8 = 0
|
field8 = 0
|
||||||
).toByteArray(),
|
).toByteArray(),
|
||||||
@ -410,8 +401,8 @@ suspend fun List<Element>.toRichText(contact: Contact): Result<Pair<String, Rich
|
|||||||
elems.add(elem)
|
elems.add(elem)
|
||||||
summary .append( "[戳一戳]" )
|
summary .append( "[戳一戳]" )
|
||||||
}
|
}
|
||||||
ElementType.MUSIC -> throw UnsupportedOperationException("Unsupported ElementType.MUSIC")
|
Element.ElementType.MUSIC -> throw UnsupportedOperationException("Unsupported Element.ElementType.MUSIC")
|
||||||
ElementType.WEATHER -> {
|
Element.ElementType.WEATHER -> {
|
||||||
var code = it.weather.code.toIntOrNull()
|
var code = it.weather.code.toIntOrNull()
|
||||||
if (code == null) {
|
if (code == null) {
|
||||||
val city = it.weather.city
|
val city = it.weather.city
|
||||||
@ -438,11 +429,11 @@ suspend fun List<Element>.toRichText(contact: Contact): Result<Pair<String, Rich
|
|||||||
throw LogicException("无法获取城市天气")
|
throw LogicException("无法获取城市天气")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ElementType.LOCATION -> throw UnsupportedOperationException("Unsupported ElementType.LOCATION")
|
Element.ElementType.LOCATION -> throw UnsupportedOperationException("Unsupported Element.ElementType.LOCATION")
|
||||||
ElementType.SHARE -> throw UnsupportedOperationException("Unsupported ElementType.SHARE")
|
Element.ElementType.SHARE -> throw UnsupportedOperationException("Unsupported Element.ElementType.SHARE")
|
||||||
ElementType.GIFT -> throw UnsupportedOperationException("Unsupported ElementType.GIFT")
|
Element.ElementType.GIFT -> throw UnsupportedOperationException("Unsupported Element.ElementType.GIFT")
|
||||||
ElementType.MARKET_FACE -> throw UnsupportedOperationException("Unsupported ElementType.MARKET_FACE")
|
Element.ElementType.MARKET_FACE -> throw UnsupportedOperationException("Unsupported Element.ElementType.MARKET_FACE")
|
||||||
ElementType.FORWARD -> {
|
Element.ElementType.FORWARD -> {
|
||||||
val resId = it.forward.resId
|
val resId = it.forward.resId
|
||||||
val filename = UUID.randomUUID().toString().uppercase()
|
val filename = UUID.randomUUID().toString().uppercase()
|
||||||
var content = it.forward.summary
|
var content = it.forward.summary
|
||||||
@ -496,8 +487,8 @@ suspend fun List<Element>.toRichText(contact: Contact): Result<Pair<String, Rich
|
|||||||
elems.add(elem)
|
elems.add(elem)
|
||||||
summary.append( "[聊天记录]" )
|
summary.append( "[聊天记录]" )
|
||||||
}
|
}
|
||||||
ElementType.CONTACT -> throw UnsupportedOperationException("Unsupported ElementType.CONTACT")
|
Element.ElementType.CONTACT -> throw UnsupportedOperationException("Unsupported Element.ElementType.CONTACT")
|
||||||
ElementType.JSON -> {
|
Element.ElementType.JSON -> {
|
||||||
val elem = Elem(
|
val elem = Elem(
|
||||||
lightApp = LightAppElem(
|
lightApp = LightAppElem(
|
||||||
data = byteArrayOf(1) + DeflateTools.compress(it.json.json.toByteArray())
|
data = byteArrayOf(1) + DeflateTools.compress(it.json.json.toByteArray())
|
||||||
@ -506,9 +497,9 @@ suspend fun List<Element>.toRichText(contact: Contact): Result<Pair<String, Rich
|
|||||||
elems.add(elem)
|
elems.add(elem)
|
||||||
summary .append( "[Json消息]" )
|
summary .append( "[Json消息]" )
|
||||||
}
|
}
|
||||||
ElementType.XML -> throw UnsupportedOperationException("Unsupported ElementType.XML")
|
Element.ElementType.XML -> throw UnsupportedOperationException("Unsupported Element.ElementType.XML")
|
||||||
ElementType.FILE -> throw UnsupportedOperationException("Unsupported ElementType.FILE")
|
Element.ElementType.FILE -> throw UnsupportedOperationException("Unsupported Element.ElementType.FILE")
|
||||||
ElementType.MARKDOWN -> {
|
Element.ElementType.MARKDOWN -> {
|
||||||
val elem = Elem(
|
val elem = Elem(
|
||||||
commonElem = CommonElem(
|
commonElem = CommonElem(
|
||||||
serviceType = 45,
|
serviceType = 45,
|
||||||
@ -519,13 +510,13 @@ suspend fun List<Element>.toRichText(contact: Contact): Result<Pair<String, Rich
|
|||||||
elems.add(elem)
|
elems.add(elem)
|
||||||
summary.append("[Markdown消息]")
|
summary.append("[Markdown消息]")
|
||||||
}
|
}
|
||||||
ElementType.BUTTON -> {
|
Element.ElementType.KEYBOARD -> {
|
||||||
val elem = Elem(
|
val elem = Elem(
|
||||||
commonElem = CommonElem(
|
commonElem = CommonElem(
|
||||||
serviceType = 46,
|
serviceType = 46,
|
||||||
elem = ButtonExtra(
|
elem = ButtonExtra(
|
||||||
field1 = Object1(
|
field1 = Object1(
|
||||||
rows = it.button.rowsList.map { row ->
|
rows = it.keyboard.rowsList.map { row ->
|
||||||
Row(buttons = row.buttonsList.map { button ->
|
Row(buttons = row.buttonsList.map { button ->
|
||||||
val renderData = button.renderData
|
val renderData = button.renderData
|
||||||
val action = button.action
|
val action = button.action
|
||||||
@ -552,7 +543,7 @@ suspend fun List<Element>.toRichText(contact: Contact): Result<Pair<String, Rich
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
appid = it.button.applicationId.toULong()
|
appid = it.keyboard.botAppid.toULong()
|
||||||
)
|
)
|
||||||
).toByteArray(),
|
).toByteArray(),
|
||||||
businessType = 1
|
businessType = 1
|
||||||
@ -561,8 +552,7 @@ suspend fun List<Element>.toRichText(contact: Contact): Result<Pair<String, Rich
|
|||||||
elems.add(elem)
|
elems.add(elem)
|
||||||
summary.append("[Button消息]")
|
summary.append("[Button消息]")
|
||||||
}
|
}
|
||||||
ElementType.NODE -> throw UnsupportedOperationException("Unsupported ElementType.NODE")
|
Element.ElementType.UNRECOGNIZED -> throw UnsupportedOperationException("Unsupported Element.ElementType.UNRECOGNIZED")
|
||||||
ElementType.UNRECOGNIZED -> throw UnsupportedOperationException("Unsupported ElementType.UNRECOGNIZED")
|
|
||||||
}
|
}
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
LogCenter.log("转换消息失败(Multi): ${e.stackTraceToString()}", Level.ERROR)
|
LogCenter.log("转换消息失败(Multi): ${e.stackTraceToString()}", Level.ERROR)
|
||||||
|
@ -10,6 +10,7 @@ import io.ktor.client.plugins.HttpTimeout
|
|||||||
import io.ktor.client.request.get
|
import io.ktor.client.request.get
|
||||||
import io.ktor.client.request.header
|
import io.ktor.client.request.header
|
||||||
import moe.fuqiuluo.shamrock.tools.GlobalClient
|
import moe.fuqiuluo.shamrock.tools.GlobalClient
|
||||||
|
import moe.fuqiuluo.shamrock.tools.decodeToOidb
|
||||||
import moe.fuqiuluo.shamrock.tools.slice
|
import moe.fuqiuluo.shamrock.tools.slice
|
||||||
import mqq.app.MobileQQ
|
import mqq.app.MobileQQ
|
||||||
import mqq.manager.TicketManager
|
import mqq.manager.TicketManager
|
||||||
@ -140,8 +141,7 @@ internal object TicketHelper: QQInterfaces() {
|
|||||||
val fromServiceMsg = sendOidbAW("OidbSvcTcp.0x102a", 4138, 0, req.toByteArray())
|
val fromServiceMsg = sendOidbAW("OidbSvcTcp.0x102a", 4138, 0, req.toByteArray())
|
||||||
?: return Result.failure(Exception("getLessPSKey failed"))
|
?: return Result.failure(Exception("getLessPSKey failed"))
|
||||||
if (fromServiceMsg.wupBuffer == null) return Result.failure(Exception("getLessPSKey failed: no response"))
|
if (fromServiceMsg.wupBuffer == null) return Result.failure(Exception("getLessPSKey failed: no response"))
|
||||||
val body = oidb_sso.OIDBSSOPkg()
|
val body = fromServiceMsg.decodeToOidb()
|
||||||
body.mergeFrom(fromServiceMsg.wupBuffer.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())
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user