3 Commits

Author SHA1 Message Date
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
10 changed files with 66 additions and 16 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

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

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

@ -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> {
@ -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