mirror of
https://github.com/whitechi73/OpenShamrock.git
synced 2024-08-14 05:12:17 +00:00
Compare commits
10 Commits
02f83a3c48
...
master
Author | SHA1 | Date | |
---|---|---|---|
40ffa2b71b | |||
cca2cbbbd7 | |||
40d2911135 | |||
823d9911a0 | |||
4adbc12a0b | |||
114fbfdd23 | |||
0a563d60a1 | |||
5fb1d0aeb9 | |||
012ecaa85d | |||
7ea127a279 |
3
.github/ISSUE_TEMPLATE/bug.md
vendored
3
.github/ISSUE_TEMPLATE/bug.md
vendored
@ -20,7 +20,8 @@ labels: bug
|
|||||||
|
|
||||||
## 系统信息
|
## 系统信息
|
||||||
|
|
||||||
- Shamrock 版本:
|
- Shamrock 版本:
|
||||||
|
- QQ 版本:
|
||||||
- Android 版本:
|
- Android 版本:
|
||||||
- LSPosed 框架版本:
|
- LSPosed 框架版本:
|
||||||
- 设备的制造商和型号:
|
- 设备的制造商和型号:
|
||||||
|
@ -23,9 +23,13 @@
|
|||||||
> Riru可能导致封禁,请减少使用。
|
> Riru可能导致封禁,请减少使用。
|
||||||
> 如有违反法律,请联系删除。
|
> 如有违反法律,请联系删除。
|
||||||
> 请勿在任何平台宣传,宣扬,转发本项目,请勿恶意修改企业安装包造成相关企业产生损失,如有违背,必将追责到底。
|
> 请勿在任何平台宣传,宣扬,转发本项目,请勿恶意修改企业安装包造成相关企业产生损失,如有违背,必将追责到底。
|
||||||
|
>
|
||||||
|
> 社区地址:[discord](https://discord.gg/MKR2wz863h)
|
||||||
|
|
||||||
## 兼容|迁移|替代 说明
|
## 兼容|迁移|替代 说明
|
||||||
|
|
||||||
|
仅支持QQ9.0.70以上的版本,低版本问题将不再修复与处理。
|
||||||
|
|
||||||
- 一键移植:本项目基于 go-cqhttp 的文档进行开发实现。
|
- 一键移植:本项目基于 go-cqhttp 的文档进行开发实现。
|
||||||
- 平行部署:可多平台部署。
|
- 平行部署:可多平台部署。
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
Submodule kritor/kritor updated: 27669a8f57...3dec747a8e
@ -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
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
package com.tencent.qqnt.kernel.nativeinterface;
|
||||||
|
|
||||||
|
public class GProGuildTopFeedMsg {
|
||||||
|
}
|
@ -18,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);
|
||||||
|
|
||||||
@ -32,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);
|
||||||
|
|
||||||
@ -50,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);
|
||||||
@ -64,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);
|
||||||
|
|
||||||
@ -78,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();
|
||||||
@ -94,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);
|
||||||
|
|
||||||
@ -106,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);
|
||||||
|
|
||||||
@ -116,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, boolean z, ArrayList<Byte> arrayList);
|
void onSysMsgNotification(int i, long j, long j2, boolean z, ArrayList<Byte> arrayList);
|
||||||
|
|
||||||
void onTempChatInfoUpdate(TempChatInfo tempChatInfo);
|
void onTempChatInfoUpdate(TempChatInfo tempChatInfo);
|
||||||
|
|
||||||
@ -130,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);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
package com.tencent.qqnt.kernel.nativeinterface;
|
||||||
|
|
||||||
|
public class QueryUserSecQualityRsp {
|
||||||
|
}
|
@ -156,8 +156,8 @@ internal object FriendService : FriendServiceGrpcKt.FriendServiceCoroutineImplBa
|
|||||||
val bundle = Bundle()
|
val bundle = Bundle()
|
||||||
val service = QQInterfaces.app
|
val service = QQInterfaces.app
|
||||||
.getRuntimeService(IProfileProtocolService::class.java, "all")
|
.getRuntimeService(IProfileProtocolService::class.java, "all")
|
||||||
if (request.hasNickName()) {
|
if (request.hasNick()) {
|
||||||
bundle.putString(IProfileProtocolConst.KEY_NICK, request.nickName)
|
bundle.putString(IProfileProtocolConst.KEY_NICK, request.nick)
|
||||||
}
|
}
|
||||||
if (request.hasCompany()) {
|
if (request.hasCompany()) {
|
||||||
bundle.putString(IProfileProtocolConst.KEY_COMPANY, request.company)
|
bundle.putString(IProfileProtocolConst.KEY_COMPANY, request.company)
|
||||||
|
@ -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
|
||||||
@ -33,8 +34,7 @@ internal object GroupFileService : GroupFileServiceGrpcKt.GroupFileServiceCorout
|
|||||||
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>()
|
||||||
@ -61,8 +61,7 @@ internal object GroupFileService : GroupFileServiceGrpcKt.GroupFileServiceCorout
|
|||||||
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}"))
|
||||||
@ -86,8 +85,7 @@ internal object GroupFileService : GroupFileServiceGrpcKt.GroupFileServiceCorout
|
|||||||
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())
|
||||||
}
|
}
|
||||||
@ -112,8 +110,7 @@ internal object GroupFileService : GroupFileServiceGrpcKt.GroupFileServiceCorout
|
|||||||
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}"))
|
||||||
|
@ -259,12 +259,12 @@ 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
|
||||||
addAllHonors((memberInfo.honorList ?: "")
|
addAllHonors((memberInfo.honorList ?: "")
|
||||||
@ -295,12 +295,12 @@ internal object GroupService : GroupServiceGrpcKt.GroupServiceCoroutineImplBase(
|
|||||||
nick = memberInfo.nick ?: ""
|
nick = memberInfo.nick ?: ""
|
||||||
age = 0
|
age = 0
|
||||||
uniqueTitle = memberInfo.memberSpecialTitle ?: ""
|
uniqueTitle = memberInfo.memberSpecialTitle ?: ""
|
||||||
uniqueTitleExpireTime = memberInfo.specialTitleExpireTime.toInt()
|
uniqueTitleExpireTime = memberInfo.specialTitleExpireTime
|
||||||
card = memberInfo.cardName.ifNullOrEmpty { memberInfo.nick } ?: ""
|
card = memberInfo.cardName.ifNullOrEmpty { memberInfo.nick } ?: ""
|
||||||
joinTime = memberInfo.joinTime.toLong()
|
joinTime = memberInfo.joinTime.toLong()
|
||||||
lastActiveTime = memberInfo.lastSpeakTime.toLong()
|
lastActiveTime = memberInfo.lastSpeakTime.toLong()
|
||||||
level = memberInfo.memberLevel
|
level = memberInfo.memberLevel
|
||||||
shutUpTimestamp = memberInfo.shutUpTime.toLong()
|
shutUpTime = memberInfo.shutUpTime.toLong()
|
||||||
|
|
||||||
distance = 0
|
distance = 0
|
||||||
addAllHonors(memberInfo.groupHonor.let { bytes ->
|
addAllHonors(memberInfo.groupHonor.let { bytes ->
|
||||||
@ -327,7 +327,7 @@ internal object GroupService : GroupServiceGrpcKt.GroupServiceCoroutineImplBase(
|
|||||||
this.addProhibitedUsersInfo(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()
|
||||||
@ -360,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()
|
||||||
|
@ -315,7 +315,7 @@ internal object MessageService : MessageServiceGrpcKt.MessageServiceCoroutineImp
|
|||||||
throw StatusRuntimeException(Status.INTERNAL.withCause(it))
|
throw StatusRuntimeException(Status.INTERNAL.withCause(it))
|
||||||
}.getOrThrow().map { detail ->
|
}.getOrThrow().map { detail ->
|
||||||
PushMessageBody.newBuilder().apply {
|
PushMessageBody.newBuilder().apply {
|
||||||
this.time = detail.time
|
this.time = detail.time.toLong()
|
||||||
this.messageId = detail.qqMsgId.toString()
|
this.messageId = detail.qqMsgId.toString()
|
||||||
this.messageSeq = detail.msgSeq
|
this.messageSeq = detail.msgSeq
|
||||||
this.contact = io.kritor.common.Contact.newBuilder().apply {
|
this.contact = io.kritor.common.Contact.newBuilder().apply {
|
||||||
@ -398,10 +398,10 @@ internal object MessageService : MessageServiceGrpcKt.MessageServiceCoroutineImp
|
|||||||
this.messageId = it.msgId.toString()
|
this.messageId = it.msgId.toString()
|
||||||
}
|
}
|
||||||
this.messageSeq = it.messageSeq
|
this.messageSeq = it.messageSeq
|
||||||
this.messageTime = 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()
|
||||||
|
@ -20,6 +20,7 @@ private val configKeys = setOf(
|
|||||||
ResourceGroup,
|
ResourceGroup,
|
||||||
RPCAddress,
|
RPCAddress,
|
||||||
RPCPort,
|
RPCPort,
|
||||||
|
AliveReply,
|
||||||
)
|
)
|
||||||
|
|
||||||
internal object ShamrockConfig: Properties() {
|
internal object ShamrockConfig: Properties() {
|
||||||
|
@ -42,7 +42,7 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
elements: ArrayList<MsgElement>,
|
elements: ArrayList<MsgElement>,
|
||||||
): Boolean {
|
): Boolean {
|
||||||
transMessageEvent(record, PushMessageBody.newBuilder().apply {
|
transMessageEvent(record, PushMessageBody.newBuilder().apply {
|
||||||
this.time = record.msgTime.toInt()
|
this.time = record.msgTime
|
||||||
this.messageId = record.msgId.toString()
|
this.messageId = record.msgId.toString()
|
||||||
this.messageSeq = record.msgSeq
|
this.messageSeq = record.msgSeq
|
||||||
this.contact = Contact.newBuilder().apply {
|
this.contact = Contact.newBuilder().apply {
|
||||||
@ -65,7 +65,7 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
elements: ArrayList<MsgElement>,
|
elements: ArrayList<MsgElement>,
|
||||||
): Boolean {
|
): Boolean {
|
||||||
transMessageEvent(record, PushMessageBody.newBuilder().apply {
|
transMessageEvent(record, PushMessageBody.newBuilder().apply {
|
||||||
this.time = record.msgTime.toInt()
|
this.time = record.msgTime
|
||||||
this.messageId = record.msgId.toString()
|
this.messageId = record.msgId.toString()
|
||||||
this.messageSeq = record.msgSeq
|
this.messageSeq = record.msgSeq
|
||||||
this.contact = Contact.newBuilder().apply {
|
this.contact = Contact.newBuilder().apply {
|
||||||
@ -90,7 +90,7 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
fromNick: String,
|
fromNick: String,
|
||||||
): Boolean {
|
): Boolean {
|
||||||
transMessageEvent(record, PushMessageBody.newBuilder().apply {
|
transMessageEvent(record, PushMessageBody.newBuilder().apply {
|
||||||
this.time = record.msgTime.toInt()
|
this.time = record.msgTime
|
||||||
this.messageId = record.msgId.toString()
|
this.messageId = record.msgId.toString()
|
||||||
this.messageSeq = record.msgSeq
|
this.messageSeq = record.msgSeq
|
||||||
this.contact = Contact.newBuilder().apply {
|
this.contact = Contact.newBuilder().apply {
|
||||||
@ -113,7 +113,7 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
elements: ArrayList<MsgElement>,
|
elements: ArrayList<MsgElement>,
|
||||||
): Boolean {
|
): Boolean {
|
||||||
transMessageEvent(record, PushMessageBody.newBuilder().apply {
|
transMessageEvent(record, PushMessageBody.newBuilder().apply {
|
||||||
this.time = record.msgTime.toInt()
|
this.time = record.msgTime
|
||||||
this.messageId = record.msgId.toString()
|
this.messageId = record.msgId.toString()
|
||||||
this.messageSeq = record.msgSeq
|
this.messageSeq = record.msgSeq
|
||||||
this.contact = Contact.newBuilder().apply {
|
this.contact = Contact.newBuilder().apply {
|
||||||
@ -152,16 +152,16 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
): Boolean {
|
): Boolean {
|
||||||
pushNotice(NoticeEvent.newBuilder().apply {
|
pushNotice(NoticeEvent.newBuilder().apply {
|
||||||
this.type = NoticeEvent.NoticeType.PRIVATE_FILE_UPLOADED
|
this.type = NoticeEvent.NoticeType.PRIVATE_FILE_UPLOADED
|
||||||
this.time = msgTime.toInt()
|
this.time = msgTime
|
||||||
this.privateFileUploaded = PrivateFileUploadedNotice.newBuilder().apply {
|
this.privateFileUploaded = PrivateFileUploadedNotice.newBuilder().apply {
|
||||||
this.fileId = fileId
|
this.fileId = fileId
|
||||||
this.fileName = fileName
|
this.fileName = fileName
|
||||||
this.operatorUid = senderUid
|
this.operatorUid = senderUid
|
||||||
this.operatorUin = senderUin
|
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
|
||||||
@ -183,7 +183,7 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
): Boolean {
|
): Boolean {
|
||||||
pushNotice(NoticeEvent.newBuilder().apply {
|
pushNotice(NoticeEvent.newBuilder().apply {
|
||||||
this.type = NoticeEvent.NoticeType.GROUP_FILE_UPLOADED
|
this.type = NoticeEvent.NoticeType.GROUP_FILE_UPLOADED
|
||||||
this.time = msgTime.toInt()
|
this.time = msgTime
|
||||||
this.groupFileUploaded = GroupFileUploadedNotice.newBuilder().apply {
|
this.groupFileUploaded = GroupFileUploadedNotice.newBuilder().apply {
|
||||||
this.groupId = groupId
|
this.groupId = groupId
|
||||||
this.operatorUid = senderUid
|
this.operatorUid = senderUid
|
||||||
@ -191,7 +191,7 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
this.fileId = uuid
|
this.fileId = uuid
|
||||||
this.fileName = fileName
|
this.fileName = fileName
|
||||||
this.fileSize = fileSize
|
this.fileSize = fileSize
|
||||||
this.busId = bizId
|
this.fileSubId = bizId
|
||||||
this.fileUrl = url
|
this.fileUrl = url
|
||||||
}.build()
|
}.build()
|
||||||
}.build())
|
}.build())
|
||||||
@ -212,7 +212,7 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
): Boolean {
|
): Boolean {
|
||||||
pushNotice(NoticeEvent.newBuilder().apply {
|
pushNotice(NoticeEvent.newBuilder().apply {
|
||||||
this.type = NoticeEvent.NoticeType.GROUP_SIGN_IN
|
this.type = NoticeEvent.NoticeType.GROUP_SIGN_IN
|
||||||
this.time = time.toInt()
|
this.time = time
|
||||||
this.groupSignIn = GroupSignInNotice.newBuilder().apply {
|
this.groupSignIn = GroupSignInNotice.newBuilder().apply {
|
||||||
this.groupId = groupCode
|
this.groupId = groupCode
|
||||||
this.targetUid = ContactHelper.getUidByUinAsync(target)
|
this.targetUid = ContactHelper.getUidByUinAsync(target)
|
||||||
@ -235,7 +235,7 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
): Boolean {
|
): Boolean {
|
||||||
pushNotice(NoticeEvent.newBuilder().apply {
|
pushNotice(NoticeEvent.newBuilder().apply {
|
||||||
this.type = NoticeEvent.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.groupId = groupCode
|
this.groupId = groupCode
|
||||||
this.action = action
|
this.action = action
|
||||||
@ -261,7 +261,7 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
): Boolean {
|
): Boolean {
|
||||||
pushNotice(NoticeEvent.newBuilder().apply {
|
pushNotice(NoticeEvent.newBuilder().apply {
|
||||||
this.type = NoticeEvent.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
|
||||||
@ -285,7 +285,7 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
): Boolean {
|
): Boolean {
|
||||||
pushNotice(NoticeEvent.newBuilder().apply {
|
pushNotice(NoticeEvent.newBuilder().apply {
|
||||||
this.type = NoticeEvent.NoticeType.GROUP_MEMBER_DECREASE
|
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
|
||||||
@ -307,7 +307,7 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
): Boolean {
|
): Boolean {
|
||||||
pushNotice(NoticeEvent.newBuilder().apply {
|
pushNotice(NoticeEvent.newBuilder().apply {
|
||||||
this.type = NoticeEvent.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
|
||||||
@ -327,7 +327,7 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
): Boolean {
|
): Boolean {
|
||||||
pushNotice(NoticeEvent.newBuilder().apply {
|
pushNotice(NoticeEvent.newBuilder().apply {
|
||||||
this.type = NoticeEvent.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.isBan = isOpen
|
this.isBan = isOpen
|
||||||
@ -349,7 +349,7 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
): Boolean {
|
): Boolean {
|
||||||
pushNotice(NoticeEvent.newBuilder().apply {
|
pushNotice(NoticeEvent.newBuilder().apply {
|
||||||
this.type = NoticeEvent.NoticeType.GROUP_MEMBER_BAN
|
this.type = NoticeEvent.NoticeType.GROUP_MEMBER_BAN
|
||||||
this.time = msgTime.toInt()
|
this.time = msgTime
|
||||||
this.groupMemberBan = GroupMemberBanNotice.newBuilder().apply {
|
this.groupMemberBan = GroupMemberBanNotice.newBuilder().apply {
|
||||||
this.groupId = groupCode
|
this.groupId = groupCode
|
||||||
this.operatorUid = operatorUid
|
this.operatorUid = operatorUid
|
||||||
@ -376,7 +376,7 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
): Boolean {
|
): Boolean {
|
||||||
pushNotice(NoticeEvent.newBuilder().apply {
|
pushNotice(NoticeEvent.newBuilder().apply {
|
||||||
this.type = NoticeEvent.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
|
||||||
@ -398,7 +398,7 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
): Boolean {
|
): Boolean {
|
||||||
pushNotice(NoticeEvent.newBuilder().apply {
|
pushNotice(NoticeEvent.newBuilder().apply {
|
||||||
this.type = NoticeEvent.NoticeType.GROUP_CARD_CHANGED
|
this.type = NoticeEvent.NoticeType.GROUP_CARD_CHANGED
|
||||||
this.time = time.toInt()
|
this.time = time
|
||||||
this.groupCardChanged = GroupCardChangedNotice.newBuilder().apply {
|
this.groupCardChanged = GroupCardChangedNotice.newBuilder().apply {
|
||||||
this.groupId = groupId
|
this.groupId = groupId
|
||||||
this.targetUin = targetId
|
this.targetUin = targetId
|
||||||
@ -416,7 +416,7 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
): Boolean {
|
): Boolean {
|
||||||
pushNotice(NoticeEvent.newBuilder().apply {
|
pushNotice(NoticeEvent.newBuilder().apply {
|
||||||
this.type = NoticeEvent.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.targetUid = ContactHelper.getUidByUinAsync(targetUin)
|
this.targetUid = ContactHelper.getUidByUinAsync(targetUin)
|
||||||
@ -437,7 +437,7 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
): Boolean {
|
): Boolean {
|
||||||
pushNotice(NoticeEvent.newBuilder().apply {
|
pushNotice(NoticeEvent.newBuilder().apply {
|
||||||
this.type = NoticeEvent.NoticeType.GROUP_ESSENCE_CHANGED
|
this.type = NoticeEvent.NoticeType.GROUP_ESSENCE_CHANGED
|
||||||
this.time = time.toInt()
|
this.time = time
|
||||||
this.groupEssenceChanged = GroupEssenceMessageNotice.newBuilder().apply {
|
this.groupEssenceChanged = GroupEssenceMessageNotice.newBuilder().apply {
|
||||||
this.groupId = groupId
|
this.groupId = groupId
|
||||||
this.messageId = msgId.toString()
|
this.messageId = msgId.toString()
|
||||||
@ -465,7 +465,7 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
): Boolean {
|
): Boolean {
|
||||||
pushNotice(NoticeEvent.newBuilder().apply {
|
pushNotice(NoticeEvent.newBuilder().apply {
|
||||||
this.type = NoticeEvent.NoticeType.PRIVATE_POKE
|
this.type = NoticeEvent.NoticeType.PRIVATE_POKE
|
||||||
this.time = msgTime.toInt()
|
this.time = msgTime
|
||||||
this.privatePoke = PrivatePokeNotice.newBuilder().apply {
|
this.privatePoke = PrivatePokeNotice.newBuilder().apply {
|
||||||
this.action = action ?: ""
|
this.action = action ?: ""
|
||||||
this.operatorUid = ContactHelper.getUidByUinAsync(operator)
|
this.operatorUid = ContactHelper.getUidByUinAsync(operator)
|
||||||
@ -480,7 +480,7 @@ 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 = NoticeEvent.NoticeType.PRIVATE_RECALL
|
this.type = NoticeEvent.NoticeType.PRIVATE_RECALL
|
||||||
this.time = time.toInt()
|
this.time = time
|
||||||
this.privateRecall = PrivateRecallNotice.newBuilder().apply {
|
this.privateRecall = PrivateRecallNotice.newBuilder().apply {
|
||||||
this.operatorUin = operator
|
this.operatorUin = operator
|
||||||
this.messageId = msgId.toString()
|
this.messageId = msgId.toString()
|
||||||
@ -499,7 +499,7 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
suspend fun transFriendApp(time: Long, applierUid: String, operator: Long, tipText: String, flag: String): Boolean {
|
suspend fun transFriendApp(time: Long, applierUid: String, operator: Long, tipText: String, flag: String): Boolean {
|
||||||
pushRequest(RequestEvent.newBuilder().apply {
|
pushRequest(RequestEvent.newBuilder().apply {
|
||||||
this.type = RequestEvent.RequestType.FRIEND_APPLY
|
this.type = RequestEvent.RequestType.FRIEND_APPLY
|
||||||
this.time = time.toInt()
|
this.time = time
|
||||||
this.requestId = flag
|
this.requestId = flag
|
||||||
this.friendApply = FriendApplyRequest.newBuilder().apply {
|
this.friendApply = FriendApplyRequest.newBuilder().apply {
|
||||||
this.applierUid = applierUid
|
this.applierUid = applierUid
|
||||||
@ -520,7 +520,7 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
): Boolean {
|
): Boolean {
|
||||||
pushRequest(RequestEvent.newBuilder().apply {
|
pushRequest(RequestEvent.newBuilder().apply {
|
||||||
this.type = RequestEvent.RequestType.GROUP_APPLY
|
this.type = RequestEvent.RequestType.GROUP_APPLY
|
||||||
this.time = time.toInt()
|
this.time = time
|
||||||
this.requestId = flag
|
this.requestId = flag
|
||||||
this.groupApply = GroupApplyRequest.newBuilder().apply {
|
this.groupApply = GroupApplyRequest.newBuilder().apply {
|
||||||
this.applierUid = applierUid
|
this.applierUid = applierUid
|
||||||
@ -541,7 +541,7 @@ internal object GlobalEventTransmitter : QQInterfaces() {
|
|||||||
): Boolean {
|
): Boolean {
|
||||||
pushRequest(RequestEvent.newBuilder().apply {
|
pushRequest(RequestEvent.newBuilder().apply {
|
||||||
this.type = RequestEvent.RequestType.GROUP_APPLY
|
this.type = RequestEvent.RequestType.GROUP_APPLY
|
||||||
this.time = time.toInt()
|
this.time = time
|
||||||
this.requestId = flag
|
this.requestId = flag
|
||||||
this.invitedGroup = InvitedJoinGroupRequest.newBuilder().apply {
|
this.invitedGroup = InvitedJoinGroupRequest.newBuilder().apply {
|
||||||
this.inviterUid = inviterUid
|
this.inviterUid = inviterUid
|
||||||
|
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) {
|
||||||
|
@ -21,6 +21,7 @@ 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.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
|
||||||
@ -36,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
|
||||||
@ -285,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
|
||||||
*/
|
*/
|
||||||
@ -353,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.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 {
|
||||||
@ -448,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.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}"))
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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,5 +1,3 @@
|
|||||||
@file:OptIn(ExperimentalStdlibApi::class)
|
|
||||||
|
|
||||||
package qq.service.file
|
package qq.service.file
|
||||||
|
|
||||||
import com.tencent.mobileqq.pb.ByteStringMicro
|
import com.tencent.mobileqq.pb.ByteStringMicro
|
||||||
@ -9,7 +7,9 @@ import io.kritor.file.*
|
|||||||
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
|
||||||
@ -31,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()
|
||||||
}
|
}
|
||||||
@ -53,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()
|
||||||
}
|
}
|
||||||
@ -95,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 {
|
||||||
@ -116,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.expireTime = 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()
|
||||||
@ -133,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())
|
||||||
|
@ -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
|
||||||
@ -453,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()))
|
||||||
}
|
}
|
||||||
@ -475,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()))
|
||||||
}
|
}
|
||||||
@ -637,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,14 +3,24 @@
|
|||||||
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
|
||||||
|
|
||||||
@ -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
|
||||||
|
@ -216,6 +216,9 @@ 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 这里
|
// todo 贴表情也走的 732 16 这里
|
||||||
|
@ -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?) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,7 +319,10 @@ abstract class SimpleKernelMsgListener: IKernelMsgListener {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onUserTabStatusChanged(arrayList: ArrayList<TabStatusInfo>?) {
|
override fun onUserSecQualityChanged(queryUserSecQualityRsp: QueryUserSecQualityRsp?) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onUserTabStatusChanged(arrayList: ArrayList<TabStatusInfo>?) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -78,7 +78,7 @@ private object MsgConvertor {
|
|||||||
elem.type = ElementType.POKE
|
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 {
|
||||||
@ -157,45 +157,21 @@ private object MsgConvertor {
|
|||||||
elem.type = ElementType.IMAGE
|
elem.type = ElementType.IMAGE
|
||||||
elem.setImage(ImageElement.newBuilder().apply {
|
elem.setImage(ImageElement.newBuilder().apply {
|
||||||
this.file = ByteString.copyFromUtf8(md5)
|
this.file = ByteString.copyFromUtf8(md5)
|
||||||
this.fileUrl = 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,
|
|
||||||
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) ImageElement.ImageType.FLASH else if (image.original) ImageElement.ImageType.ORIGIN else ImageElement.ImageType.COMMON
|
if (image.isFlashPic == true) ImageElement.ImageType.FLASH else if (image.original) ImageElement.ImageType.ORIGIN else ImageElement.ImageType.COMMON
|
||||||
this.subType = image.picSubType
|
this.subType = image.picSubType
|
||||||
})
|
})
|
||||||
|
@ -65,7 +65,7 @@ suspend fun List<Elem>.toKritorResponseMessages(contact: Contact): ArrayList<Ele
|
|||||||
this.type = ElementType.IMAGE
|
this.type = ElementType.IMAGE
|
||||||
this.image = ImageElement.newBuilder().apply {
|
this.image = ImageElement.newBuilder().apply {
|
||||||
this.fileMd5 = 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.fileUrl = when (contact.chatType) {
|
this.fileUrl = when (contact.chatType) {
|
||||||
MsgConstant.KCHATTYPEDISC, MsgConstant.KCHATTYPEGROUP -> RichProtoSvc.getGroupPicDownUrl(
|
MsgConstant.KCHATTYPEDISC, MsgConstant.KCHATTYPEGROUP -> RichProtoSvc.getGroupPicDownUrl(
|
||||||
origUrl,
|
origUrl,
|
||||||
@ -85,7 +85,7 @@ suspend fun List<Elem>.toKritorResponseMessages(contact: Contact): ArrayList<Ele
|
|||||||
this.type = ElementType.IMAGE
|
this.type = ElementType.IMAGE
|
||||||
this.image = ImageElement.newBuilder().apply {
|
this.image = ImageElement.newBuilder().apply {
|
||||||
this.fileMd5 = 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.fileUrl = when (contact.chatType) {
|
this.fileUrl = when (contact.chatType) {
|
||||||
MsgConstant.KCHATTYPEDISC, MsgConstant.KCHATTYPEGROUP -> RichProtoSvc.getGroupPicDownUrl(
|
MsgConstant.KCHATTYPEDISC, MsgConstant.KCHATTYPEGROUP -> RichProtoSvc.getGroupPicDownUrl(
|
||||||
origUrl,
|
origUrl,
|
||||||
|
@ -254,8 +254,8 @@ 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 = "")
|
val fileMd5 = sourceImage.image.fileName.replace(regex = "[{}\\-]".toRegex(), replacement = "")
|
||||||
@ -638,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
|
||||||
|
@ -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 {
|
||||||
@ -136,45 +136,8 @@ private object ReqMsgConvertor {
|
|||||||
val elem = Element.newBuilder()
|
val elem = Element.newBuilder()
|
||||||
elem.setImage(ImageElement.newBuilder().apply {
|
elem.setImage(ImageElement.newBuilder().apply {
|
||||||
this.fileMd5 = md5
|
this.fileMd5 = md5
|
||||||
this.fileUrl = 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,
|
|
||||||
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) ImageElement.ImageType.FLASH else if (image.original) ImageElement.ImageType.ORIGIN else ImageElement.ImageType.COMMON
|
if (image.isFlashPic == true) ImageElement.ImageType.FLASH else if (image.original) ImageElement.ImageType.ORIGIN else ImageElement.ImageType.COMMON
|
||||||
this.subType = image.picSubType
|
this.subType = image.picSubType
|
||||||
})
|
})
|
||||||
|
@ -183,7 +183,7 @@ suspend fun List<Element>.toRichText(contact: Contact): Result<Pair<String, Rich
|
|||||||
summary.append("[回复消息]")
|
summary.append("[回复消息]")
|
||||||
}
|
}
|
||||||
Element.ElementType.IMAGE -> {
|
Element.ElementType.IMAGE -> {
|
||||||
val type = it.image.type
|
val type = it.image.fileType
|
||||||
val isOriginal = type == ImageElement.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 -> {
|
||||||
@ -391,7 +391,7 @@ suspend fun List<Element>.toRichText(contact: Contact): Result<Pair<String, Rich
|
|||||||
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(),
|
||||||
|
@ -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