8 Commits

Author SHA1 Message Date
59d762eecf fix https://github.com/KarinJS/kritor/issues/10 2024-04-11 12:37:54 +08:00
e891bc8512 fix build 2024-04-11 01:17:13 +08:00
494c70f2f8 update kritor 2024-04-11 00:58:36 +08:00
7baf459b2a Shamrock: fix scene and group code 2024-04-10 21:09:10 +08:00
36a09ca088 update kritor 2024-04-08 20:00:44 +08:00
926c4659f6 Shamrock: add kritor metadata 2024-04-07 16:51:21 +08:00
cb7c68f36c fix: build error 2024-04-07 16:27:35 +08:00
72af39208c update kritor 2024-04-07 16:08:33 +08:00
17 changed files with 198 additions and 82 deletions

View File

@ -2,8 +2,15 @@
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.grpc.MethodDescriptor
import io.kritor.common.Request import io.kritor.common.Request
import io.kritor.common.Response import io.kritor.common.Response
import io.kritor.event.EventServiceGrpcKt import io.kritor.event.EventServiceGrpcKt
@ -23,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(
@ -39,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)

View File

@ -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,14 +15,35 @@ 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)
.intercept(serverInterceptor)
.addService(AuthenticationService) .addService(AuthenticationService)
.addService(CoreService) .addService(CoreService)
.addService(FriendService) .addService(FriendService)

View File

@ -2,12 +2,37 @@ package kritor.service
import com.google.protobuf.ByteString import com.google.protobuf.ByteString
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.FileUtils
import moe.fuqiuluo.shamrock.utils.MMKVFetcher import moe.fuqiuluo.shamrock.utils.MMKVFetcher
import moe.fuqiuluo.shamrock.utils.PlatformUtils import moe.fuqiuluo.shamrock.utils.PlatformUtils
import qq.service.QQInterfaces import qq.service.QQInterfaces
import java.io.File
internal object DeveloperService: DeveloperServiceGrpcKt.DeveloperServiceCoroutineImplBase() { internal object DeveloperService: DeveloperServiceGrpcKt.DeveloperServiceCoroutineImplBase() {
@Grpc("DeveloperService", "Shell")
override suspend fun shell(request: ShellRequest): ShellResponse {
if (request.commandList.isEmpty()) return ShellResponse.newBuilder().setIsSuccess(false).build()
val runtime = Runtime.getRuntime()
val result = withTimeoutOrNull(5000L) {
withContext(Dispatchers.IO) {
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()
}
@Grpc("DeveloperService", "ClearCache") @Grpc("DeveloperService", "ClearCache")
override suspend fun clearCache(request: ClearCacheRequest): ClearCacheResponse { override suspend fun clearCache(request: ClearCacheRequest): ClearCacheResponse {
FileUtils.clearCache() FileUtils.clearCache()

View File

@ -225,8 +225,8 @@ internal object FriendService : FriendServiceGrpcKt.FriendServiceCoroutineImplBa
} }
@Grpc("FriendService", "GetUidByUin") @Grpc("FriendService", "GetUidByUin")
override suspend fun getUidByUin(request: GetUidRequest): GetUidResponse { override suspend fun getUidByUin(request: GetUidByUinRequest): GetUidByUinResponse {
return GetUidResponse.newBuilder().apply { return GetUidByUinResponse.newBuilder().apply {
request.targetUinsList.forEach { request.targetUinsList.forEach {
putUidMap(it, ContactHelper.getUidByUinAsync(it)) putUidMap(it, ContactHelper.getUidByUinAsync(it))
} }

View File

@ -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.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
@ -213,9 +214,10 @@ internal object GroupService : GroupServiceGrpcKt.GroupServiceCoroutineImplBase(
return GetGroupListResponse.newBuilder().apply { return GetGroupListResponse.newBuilder().apply {
groupList.forEach { groupInfo -> groupList.forEach { groupInfo ->
this.addGroupsInfo(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))

View File

@ -463,7 +463,7 @@ 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 ReactMessageWithEmojiResponse.newBuilder().build() return ReactMessageWithEmojiResponse.newBuilder().build()
} }

View File

@ -23,4 +23,11 @@ internal object QsignService: QsignServiceGrpcKt.QsignServiceCoroutineImplBase()
this.result = ByteString.copyFrom(Dandelion.getInstance().fly(request.data, request.salt.toByteArray())) this.result = ByteString.copyFrom(Dandelion.getInstance().fly(request.data, request.salt.toByteArray()))
}.build() }.build()
} }
@Grpc("QsignService", "GetCmdWhitelist")
override suspend fun getCmdWhitelist(request: GetCmdWhitelistRequest): GetCmdWhitelistResponse {
return GetCmdWhitelistResponse.newBuilder().apply {
addAllCommands(FEKit.getInstance().cmdWhiteList)
}.build()
}
} }

View File

@ -7,6 +7,7 @@ import com.tencent.qqnt.kernel.nativeinterface.MsgRecord
import io.kritor.event.* import io.kritor.event.*
import io.kritor.common.PushMessageBody import io.kritor.common.PushMessageBody
import io.kritor.common.Contact import io.kritor.common.Contact
import io.kritor.common.Scene
import io.kritor.common.Sender import io.kritor.common.Sender
import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
@ -14,6 +15,7 @@ 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() {
@ -24,12 +26,12 @@ internal object GlobalEventTransmitter : QQInterfaces() {
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: PushMessageBody) = private suspend fun transMessageEvent(record: MsgRecord, message: PushMessageBody) =
MessageEventFlow.emit(record to message) MessageEventFlow.emit(record to message)
@ -44,7 +46,7 @@ internal object GlobalEventTransmitter : QQInterfaces() {
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 {
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()
@ -67,8 +69,8 @@ internal object GlobalEventTransmitter : QQInterfaces() {
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 {
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 {
@ -92,8 +94,8 @@ internal object GlobalEventTransmitter : QQInterfaces() {
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 {
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 {
@ -115,7 +117,7 @@ internal object GlobalEventTransmitter : QQInterfaces() {
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 {
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()
@ -139,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,
@ -148,12 +151,13 @@ internal object GlobalEventTransmitter : QQInterfaces() {
url: String url: String
): Boolean { ): Boolean {
pushNotice(NoticeEvent.newBuilder().apply { pushNotice(NoticeEvent.newBuilder().apply {
this.type = NoticeEvent.NoticeType.FRIEND_FILE_COME this.type = NoticeEvent.NoticeType.PRIVATE_FILE_UPLOADED
this.time = msgTime.toInt() this.time = msgTime.toInt()
this.friendFileUploaded = FriendFileUploadedNotice.newBuilder().apply { this.privateFileUploaded = PrivateFileUploadedNotice.newBuilder().apply {
this.fileId = fileId this.fileId = fileId
this.fileName = fileName this.fileName = fileName
this.operatorUin = userId this.operatorUid = senderUid
this.operatorUin = senderUin
this.fileSize = fileSize this.fileSize = fileSize
this.expireTime = expireTime.toInt() this.expireTime = expireTime.toInt()
this.fileSubId = fileSubId this.fileSubId = fileSubId
@ -168,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,
@ -177,16 +182,17 @@ internal object GlobalEventTransmitter : QQInterfaces() {
url: String url: String
): Boolean { ): Boolean {
pushNotice(NoticeEvent.newBuilder().apply { pushNotice(NoticeEvent.newBuilder().apply {
this.type = NoticeEvent.NoticeType.GROUP_FILE_COME this.type = NoticeEvent.NoticeType.GROUP_FILE_UPLOADED
this.time = msgTime.toInt() this.time = msgTime.toInt()
this.groupFileUploaded = GroupFileUploadedNotice.newBuilder().apply { this.groupFileUploaded = GroupFileUploadedNotice.newBuilder().apply {
this.groupId = groupId this.groupId = groupId
this.operatorUin = 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.busId = bizId
this.url = url this.fileUrl = url
}.build() }.build()
}.build()) }.build())
return true return true
@ -200,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 = NoticeEvent.NoticeType.GROUP_SIGN this.type = NoticeEvent.NoticeType.GROUP_SIGN_IN
this.time = time.toInt() this.time = time.toInt()
this.groupSignIn = GroupSignInNotice.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
@ -222,9 +228,9 @@ 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 {
@ -232,11 +238,13 @@ internal object GlobalEventTransmitter : QQInterfaces() {
this.time = time.toInt() this.time = time.toInt()
this.groupPoke = GroupPokeNotice.newBuilder().apply { this.groupPoke = GroupPokeNotice.newBuilder().apply {
this.groupId = groupCode this.groupId = groupCode
this.action = action ?: "" this.action = action
this.targetUid = ContactHelper.getUidByUinAsync(target)
this.targetUin = target this.targetUin = target
this.operatorUid = ContactHelper.getUidByUinAsync(operator)
this.operatorUin = operator this.operatorUin = operator
this.suffix = suffix ?: "" this.suffix = suffix
this.actionImage = actionImg ?: "" this.actionImage = actionImg
}.build() }.build()
}.build()) }.build())
return true return true
@ -276,7 +284,7 @@ internal object GlobalEventTransmitter : QQInterfaces() {
type: GroupMemberDecreasedNotice.GroupMemberDecreasedType type: GroupMemberDecreasedNotice.GroupMemberDecreasedType
): Boolean { ): Boolean {
pushNotice(NoticeEvent.newBuilder().apply { pushNotice(NoticeEvent.newBuilder().apply {
this.type = NoticeEvent.NoticeType.GROUP_MEMBER_INCREASE this.type = NoticeEvent.NoticeType.GROUP_MEMBER_DECREASE
this.time = time.toInt() this.time = time.toInt()
this.groupMemberDecrease = GroupMemberDecreasedNotice.newBuilder().apply { this.groupMemberDecrease = GroupMemberDecreasedNotice.newBuilder().apply {
this.groupId = groupCode this.groupId = groupCode
@ -300,7 +308,7 @@ internal object GlobalEventTransmitter : QQInterfaces() {
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.toInt()
this.groupAdminChange = GroupAdminChangedNotice.newBuilder().apply { this.groupAdminChanged = GroupAdminChangedNotice.newBuilder().apply {
this.groupId = groupCode this.groupId = groupCode
this.targetUid = targetUid this.targetUid = targetUid
this.targetUin = target this.targetUin = target
@ -312,8 +320,9 @@ 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 {
@ -322,6 +331,7 @@ internal object GlobalEventTransmitter : QQInterfaces() {
this.groupWholeBan = GroupWholeBanNotice.newBuilder().apply { this.groupWholeBan = GroupWholeBanNotice.newBuilder().apply {
this.groupId = groupCode this.groupId = groupCode
this.isBan = isOpen this.isBan = isOpen
this.operatorUid = operatorUid
this.operatorUin = operator this.operatorUin = operator
}.build() }.build()
}.build()) }.build())
@ -338,7 +348,7 @@ internal object GlobalEventTransmitter : QQInterfaces() {
duration: Int duration: Int
): Boolean { ): Boolean {
pushNotice(NoticeEvent.newBuilder().apply { pushNotice(NoticeEvent.newBuilder().apply {
this.type = NoticeEvent.NoticeType.GROUP_MEMBER_BANNED this.type = NoticeEvent.NoticeType.GROUP_MEMBER_BAN
this.time = msgTime.toInt() this.time = msgTime.toInt()
this.groupMemberBan = GroupMemberBanNotice.newBuilder().apply { this.groupMemberBan = GroupMemberBanNotice.newBuilder().apply {
this.groupId = groupCode this.groupId = groupCode
@ -400,7 +410,7 @@ internal object GlobalEventTransmitter : QQInterfaces() {
suspend fun transTitleChange( suspend fun transTitleChange(
time: Long, time: Long,
targetId: Long, targetUin: Long,
title: String, title: String,
groupId: Long groupId: Long
): Boolean { ): Boolean {
@ -409,7 +419,8 @@ internal object GlobalEventTransmitter : QQInterfaces() {
this.time = time.toInt() this.time = time.toInt()
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())
@ -430,9 +441,11 @@ internal object GlobalEventTransmitter : QQInterfaces() {
this.groupEssenceChanged = GroupEssenceMessageNotice.newBuilder().apply { this.groupEssenceChanged = GroupEssenceMessageNotice.newBuilder().apply {
this.groupId = groupId this.groupId = groupId
this.messageId = msgId.toString() this.messageId = msgId.toString()
this.targetUid = ContactHelper.getUidByUinAsync(targetUin)
this.targetUin = senderUin this.targetUin = senderUin
this.operatorUid = ContactHelper.getUidByUinAsync(operatorUin)
this.operatorUin = operatorUin this.operatorUin = operatorUin
this.subType = subType.toInt() this.isSet = subType.toInt() == 1
}.build() }.build()
}.build()) }.build())
return true return true
@ -446,16 +459,16 @@ 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 = NoticeEvent.NoticeType.FRIEND_POKE this.type = NoticeEvent.NoticeType.PRIVATE_POKE
this.time = msgTime.toInt() this.time = msgTime.toInt()
this.friendPoke = FriendPokeNotice.newBuilder().apply { this.privatePoke = PrivatePokeNotice.newBuilder().apply {
this.action = action ?: "" this.action = action ?: ""
this.operatorUid = ContactHelper.getUidByUinAsync(operator)
this.operatorUin = operator this.operatorUin = operator
this.suffix = suffix ?: "" this.suffix = suffix ?: ""
this.actionImage = actionImg ?: "" this.actionImage = actionImg ?: ""
@ -466,9 +479,9 @@ 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.FRIEND_RECALL this.type = NoticeEvent.NoticeType.PRIVATE_RECALL
this.time = time.toInt() this.time = time.toInt()
this.friendRecall = FriendRecallNotice.newBuilder().apply { this.privateRecall = PrivateRecallNotice.newBuilder().apply {
this.operatorUin = operator this.operatorUin = operator
this.messageId = msgId.toString() this.messageId = msgId.toString()
this.tipText = tipText this.tipText = tipText
@ -483,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 = RequestsEvent.RequestType.FRIEND_APPLY this.type = RequestEvent.RequestType.FRIEND_APPLY
this.time = time.toInt() this.time = time.toInt()
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
@ -504,15 +518,35 @@ internal object GlobalEventTransmitter : QQInterfaces() {
groupCode: Long, groupCode: Long,
flag: String flag: String
): Boolean { ): Boolean {
pushRequest(RequestsEvent.newBuilder().apply { pushRequest(RequestEvent.newBuilder().apply {
this.type = RequestsEvent.RequestType.GROUP_APPLY this.type = RequestEvent.RequestType.GROUP_APPLY
this.time = time.toInt() this.time = time.toInt()
this.requestId = flag
this.groupApply = GroupApplyRequest.newBuilder().apply { this.groupApply = GroupApplyRequest.newBuilder().apply {
this.applierUid = applierUid this.applierUid = applierUid
this.applierUin = applierUin this.applierUin = applierUin
this.groupId = groupCode this.groupId = groupCode
this.reason = reason this.reason = reason
this.flag = flag }.build()
}.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.toInt()
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
@ -535,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)

View File

@ -117,7 +117,7 @@ internal object GroupFileHelper: QQInterfaces() {
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()
this.deadTime = fileInfo.uint32_dead_time.get() this.expireTime = fileInfo.uint32_dead_time.get()
this.modifyTime = fileInfo.uint32_modify_time.get() this.modifyTime = fileInfo.uint32_modify_time.get()
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()

View File

@ -97,7 +97,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 {
@ -113,7 +112,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)
} }
@ -121,7 +120,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 {
@ -137,7 +135,7 @@ 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)
} }

View File

@ -126,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)
} }
@ -161,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)
} }
@ -320,8 +320,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"]
@ -332,9 +332,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)
} }
@ -506,7 +506,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)
} }
@ -657,7 +657,7 @@ internal object PrimitiveListener {
"$time;$groupCode;$uin" "$time;$groupCode;$uin"
} }
if (!GlobalEventTransmitter.RequestTransmitter if (!GlobalEventTransmitter.RequestTransmitter
.transGroupApply(time, invitor, invitorUid, "", groupCode, flag) .transGroupInvite(time, invitorUid, invitor, groupCode, flag)
) { ) {
LogCenter.log("邀请入群推送失败!", Level.WARN) LogCenter.log("邀请入群推送失败!", Level.WARN)
} }

View File

@ -401,10 +401,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.type = ElementType.BUTTON elem.type = ElementType.KEYBOARD
elem.setButton(ButtonElement.newBuilder().apply { 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 {

View File

@ -227,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

View File

@ -97,7 +97,7 @@ object NtMsgConvertor {
ElementType.JSON to ::jsonConvertor, ElementType.JSON to ::jsonConvertor,
ElementType.FORWARD to ::forwardConvertor, ElementType.FORWARD to ::forwardConvertor,
ElementType.MARKDOWN to ::markdownConvertor, ElementType.MARKDOWN to ::markdownConvertor,
ElementType.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> {
@ -663,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,
@ -848,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 ->

View File

@ -366,9 +366,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

View File

@ -511,13 +511,13 @@ suspend fun List<Element>.toRichText(contact: Contact): Result<Pair<String, Rich
elems.add(elem) elems.add(elem)
summary.append("[Markdown消息]") summary.append("[Markdown消息]")
} }
Element.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
@ -544,7 +544,7 @@ suspend fun List<Element>.toRichText(contact: Contact): Result<Pair<String, Rich
) )
}) })
}, },
appid = it.button.botAppid.toULong() appid = it.keyboard.botAppid.toULong()
) )
).toByteArray(), ).toByteArray(),
businessType = 1 businessType = 1