Shamrock: support /send_guild_channel_msg

This commit is contained in:
白池 2024-02-02 22:47:38 +08:00
parent 137c354acc
commit db252b6b6c
13 changed files with 240 additions and 55 deletions

View File

@ -61,7 +61,7 @@ internal object MsgSvc: BaseSvc() {
?: return Result.failure(Exception("没有对应消息映射,消息获取失败")) ?: return Result.failure(Exception("没有对应消息映射,消息获取失败"))
val peerId = mapping.peerId val peerId = mapping.peerId
val contact = MessageHelper.generateContact(mapping.chatType, peerId) val contact = MessageHelper.generateContact(mapping.chatType, peerId, mapping.subPeerId ?: "")
val msg = withTimeoutOrNull(5000) { val msg = withTimeoutOrNull(5000) {
val service = QRoute.api(IMsgService::class.java) val service = QRoute.api(IMsgService::class.java)
@ -89,11 +89,11 @@ internal object MsgSvc: BaseSvc() {
suspend fun getMsgByQMsgId( suspend fun getMsgByQMsgId(
chatType: Int, chatType: Int,
peerId: String, peerId: String,
qqMsgId: Long qqMsgId: Long,
subPeerId: String = ""
): Result<MsgRecord> { ): Result<MsgRecord> {
val contact = MessageHelper.generateContact(chatType, peerId) val contact = MessageHelper.generateContact(chatType, peerId, subPeerId)
val service = QRoute.api(IMsgService::class.java) ?: val service = QRoute.api(IMsgService::class.java)
return Result.failure(Exception("获取消息服务"))
val msg = withTimeoutOrNull(5000) { val msg = withTimeoutOrNull(5000) {
suspendCoroutine { continuation -> suspendCoroutine { continuation ->
@ -152,7 +152,7 @@ internal object MsgSvc: BaseSvc() {
val mapping = MessageHelper.getMsgMappingByHash(msgHash) val mapping = MessageHelper.getMsgMappingByHash(msgHash)
?: return -1 to "无法找到消息映射" ?: return -1 to "无法找到消息映射"
val contact = MessageHelper.generateContact(mapping.chatType, mapping.peerId) val contact = MessageHelper.generateContact(mapping.chatType, mapping.peerId, mapping.subPeerId ?: "")
return suspendCancellableCoroutine { continuation -> return suspendCancellableCoroutine { continuation ->
msgService.recallMsg(contact, arrayListOf(mapping.qqMsgId)) { code, why -> msgService.recallMsg(contact, arrayListOf(mapping.qqMsgId)) { code, why ->
@ -184,7 +184,7 @@ internal object MsgSvc: BaseSvc() {
} }
val result = MessageHelper.sendMessageWithoutMsgId(chatType, peedId, message, fromId, MessageCallback(peedId, 0)) val result = MessageHelper.sendMessageWithoutMsgId(chatType, peedId, message, fromId, MessageCallback(peedId, 0))
result.onFailure { result.onFailure {
LogCenter.log(it.stackTraceToString(), Level.ERROR) LogCenter.log("sendToAio: " + it.stackTraceToString(), Level.ERROR)
return result return result
} }
val sendResult = result.getOrThrow() val sendResult = result.getOrThrow()
@ -192,7 +192,7 @@ internal object MsgSvc: BaseSvc() {
// 发送失败,可能网络问题出现红色感叹号,重试 // 发送失败,可能网络问题出现红色感叹号,重试
// 例如 rich media transfer failed // 例如 rich media transfer failed
delay(100) delay(100)
MessageHelper.resendMsg(chatType, peedId, fromId, sendResult.qqMsgId, 3, sendResult.msgHashId) MessageHelper.resendMsg(chatType, peedId, fromId, sendResult.qqMsgId, retryCnt, sendResult.msgHashId)
} else { } else {
result result
} }

View File

@ -107,12 +107,7 @@ internal object MessageHelper {
val sendRet = withTimeoutOrNull<Pair<Int, String>>(estimateTime) { val sendRet = withTimeoutOrNull<Pair<Int, String>>(estimateTime) {
suspendCancellableCoroutine { suspendCancellableCoroutine {
GlobalScope.launch { GlobalScope.launch {
sendResult = sendMessageWithoutMsgId( sendResult = sendMessageWithoutMsgId(chatType, peerId, msg, fromId) { code, message ->
chatType,
peerId,
msg,
fromId
) { code, message ->
callback.onResult(code, message) callback.onResult(code, message)
it.resume(code to message) it.resume(code to message)
} }
@ -248,10 +243,17 @@ internal object MessageHelper {
} }
suspend fun generateContact(chatType: Int, id: String, subId: String = ""): Contact { suspend fun generateContact(chatType: Int, id: String, subId: String = ""): Contact {
val peerId = if (MsgConstant.KCHATTYPEC2C == chatType || MsgConstant.KCHATTYPETEMPC2CFROMGROUP == chatType) { val peerId = when(chatType) {
ContactHelper.getUidByUinAsync(id.toLong()) MsgConstant.KCHATTYPEC2C, MsgConstant.KCHATTYPETEMPC2CFROMGROUP -> {
} else id ContactHelper.getUidByUinAsync(id.toLong())
return Contact(chatType, peerId, subId) }
else -> id
}
return if (chatType == MsgConstant.KCHATTYPEGUILD) {
Contact(chatType, subId, peerId)
} else {
Contact(chatType, peerId, subId)
}
} }
fun obtainMessageTypeByDetailType(detailType: String): Int { fun obtainMessageTypeByDetailType(detailType: String): Int {
@ -342,11 +344,12 @@ internal object MessageHelper {
time: Long, time: Long,
chatType: Int, chatType: Int,
peerId: String, peerId: String,
subPeerId: String,
msgSeq: Int, msgSeq: Int,
subChatType: Int = chatType subChatType: Int = chatType
) { ) {
val database = MessageDB.getInstance() val database = MessageDB.getInstance()
val mapping = MessageMapping(hash, qqMsgId, chatType, subChatType, peerId, time, msgSeq) val mapping = MessageMapping(hash, qqMsgId, chatType, subChatType, peerId, time, msgSeq, subPeerId)
database.messageMappingDao().insert(mapping) database.messageMappingDao().insert(mapping)
} }

View File

@ -12,7 +12,7 @@ import androidx.room.Room
import androidx.room.RoomDatabase import androidx.room.RoomDatabase
import mqq.app.MobileQQ import mqq.app.MobileQQ
@Entity(tableName = "message_mapping") @Entity(tableName = "message_mapping_v2")
data class MessageMapping ( data class MessageMapping (
@PrimaryKey @PrimaryKey
val msgHashId: Int, val msgHashId: Int,
@ -21,7 +21,8 @@ data class MessageMapping (
val subChatType: Int, // 细化各种事件消息 val subChatType: Int, // 细化各种事件消息
val peerId: String, val peerId: String,
val time: Long, val time: Long,
val msgSeq: Int val msgSeq: Int,
val subPeerId: String,
) )
@Dao @Dao
@ -29,25 +30,25 @@ interface MessageMappingDao {
@Insert(onConflict = OnConflictStrategy.REPLACE) @Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(mapping: MessageMapping) fun insert(mapping: MessageMapping)
@Query("UPDATE message_mapping SET msgSeq = :msgSeq WHERE msgHashId = :hash") @Query("UPDATE message_mapping_v2 SET msgSeq = :msgSeq WHERE msgHashId = :hash")
fun updateMsgSeqByMsgHash(hash: Int, msgSeq: Int) fun updateMsgSeqByMsgHash(hash: Int, msgSeq: Int)
@Query("DELETE FROM message_mapping WHERE msgHashId = :hash") @Query("DELETE FROM message_mapping_v2 WHERE msgHashId = :hash")
fun deleteByMsgHash(hash: Int) fun deleteByMsgHash(hash: Int)
@Query("SELECT * FROM message_mapping WHERE msgHashId = :msgHashId") @Query("SELECT * FROM message_mapping_v2 WHERE msgHashId = :msgHashId")
fun queryByMsgHashId(msgHashId: Int): MessageMapping? fun queryByMsgHashId(msgHashId: Int): MessageMapping?
@Query("SELECT * FROM message_mapping WHERE qqMsgId = :qqMsgId AND chatType = :chatType") @Query("SELECT * FROM message_mapping_v2 WHERE qqMsgId = :qqMsgId AND chatType = :chatType")
fun queryByQqMsgId(chatType: Int, qqMsgId: Long): MessageMapping? fun queryByQqMsgId(chatType: Int, qqMsgId: Long): MessageMapping?
@Query("SELECT * FROM message_mapping WHERE chatType = :chatType") @Query("SELECT * FROM message_mapping_v2 WHERE chatType = :chatType")
fun queryByChatType(chatType: Int): List<MessageMapping> fun queryByChatType(chatType: Int): List<MessageMapping>
@Query("SELECT * FROM message_mapping WHERE subChatType = :subChatType AND chatType = :chatType") @Query("SELECT * FROM message_mapping_v2 WHERE subChatType = :subChatType AND chatType = :chatType")
fun queryBySubChatType(chatType: Int, subChatType: Int): List<MessageMapping> fun queryBySubChatType(chatType: Int, subChatType: Int): List<MessageMapping>
@Query("SELECT * FROM message_mapping WHERE peerId = :peerId AND chatType = :chatType") @Query("SELECT * FROM message_mapping_v2 WHERE peerId = :peerId AND chatType = :chatType")
fun queryByPeerId(chatType: Int, peerId: String): List<MessageMapping> fun queryByPeerId(chatType: Int, peerId: String): List<MessageMapping>
//@Query("SELECT * FROM message_mapping WHERE msgSeq = :msgSeq AND chatType = :chatType") //@Query("SELECT * FROM message_mapping WHERE msgSeq = :msgSeq AND chatType = :chatType")
@ -55,7 +56,7 @@ interface MessageMappingDao {
// 不要调用这个seq不唯一啊老哥 // 不要调用这个seq不唯一啊老哥
// 我就说怎么这么多bug // 我就说怎么这么多bug
@Query("SELECT * FROM message_mapping WHERE msgSeq = :msgSeq AND chatType = :chatType AND peerId = :peerId") @Query("SELECT * FROM message_mapping_v2 WHERE msgSeq = :msgSeq AND chatType = :chatType AND peerId = :peerId")
fun queryByMsgSeq(chatType: Int, peerId: String, msgSeq: Int): MessageMapping? fun queryByMsgSeq(chatType: Int, peerId: String, msgSeq: Int): MessageMapping?
} }
@ -64,7 +65,7 @@ internal abstract class MessageDB: RoomDatabase() {
abstract fun messageMappingDao(): MessageMappingDao abstract fun messageMappingDao(): MessageMappingDao
companion object { companion object {
private const val DB_NAME = "message_mapping.db" private const val DB_NAME = "message_mapping_v2.db"
@Volatile @Volatile
private var instance: MessageDB? = null private var instance: MessageDB? = null

View File

@ -41,7 +41,7 @@ internal object GetForwardMsg: IActionHandler() {
msg.senderUin, msg.sendNickName msg.senderUin, msg.sendNickName
.ifEmpty { msg.sendMemberName } .ifEmpty { msg.sendMemberName }
.ifEmpty { msg.sendRemarkName } .ifEmpty { msg.sendRemarkName }
.ifEmpty { msg.peerName }, "unknown", 0, msg.senderUid .ifEmpty { msg.peerName }, "unknown", 0, msg.senderUid, msg.senderUid
), ),
message = MessageConvert.convertMessageRecordToMsgSegment(msg).map { message = MessageConvert.convertMessageRecordToMsgSegment(msg).map {
it.toJson() it.toJson()

View File

@ -65,7 +65,7 @@ internal object GetHistoryMsg: IActionHandler() {
msgId = msgHash, msgId = msgHash,
realId = msg.msgSeq.toInt(), realId = msg.msgSeq.toInt(),
sender = MessageSender( sender = MessageSender(
msg.senderUin, msg.sendNickName, "unknown", 0, msg.senderUid msg.senderUin, msg.sendNickName, "unknown", 0, msg.senderUid, msg.senderUid
), ),
message = MessageConvert.convertMessageRecordToMsgSegment(msg).map { message = MessageConvert.convertMessageRecordToMsgSegment(msg).map {
it.toJson() it.toJson()
@ -89,7 +89,7 @@ internal object GetHistoryMsg: IActionHandler() {
msg.senderUin, msg.sendNickName msg.senderUin, msg.sendNickName
.ifEmpty { msg.sendMemberName } .ifEmpty { msg.sendMemberName }
.ifEmpty { msg.sendRemarkName } .ifEmpty { msg.sendRemarkName }
.ifEmpty { msg.peerName }, "unknown", 0, msg.senderUid .ifEmpty { msg.peerName }, "unknown", 0, msg.senderUid, msg.senderUid
), ),
message = MessageConvert.convertMessageRecordToMsgSegment(msg).map { message = MessageConvert.convertMessageRecordToMsgSegment(msg).map {
it.toJson() it.toJson()

View File

@ -34,7 +34,10 @@ internal object GetMsg: IActionHandler() {
msg.senderUin, msg.sendNickName msg.senderUin, msg.sendNickName
.ifEmpty { msg.sendMemberName } .ifEmpty { msg.sendMemberName }
.ifEmpty { msg.sendRemarkName } .ifEmpty { msg.sendRemarkName }
.ifEmpty { msg.peerName }, "unknown", 0, msg.senderUid .ifEmpty { msg.peerName }, "unknown",
0,
msg.senderUid,
msg.senderUid
), ),
message = MessageConvert.convertMessageRecordToMsgSegment(msg).map { message = MessageConvert.convertMessageRecordToMsgSegment(msg).map {
it.toJson() it.toJson()

View File

@ -0,0 +1,112 @@
package moe.fuqiuluo.shamrock.remote.action.handlers
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.jsonArray
import moe.fuqiuluo.qqinterface.servlet.MsgSvc
import moe.fuqiuluo.shamrock.helper.Level
import moe.fuqiuluo.shamrock.helper.LogCenter
import moe.fuqiuluo.shamrock.helper.MessageHelper
import moe.fuqiuluo.shamrock.remote.action.ActionSession
import moe.fuqiuluo.shamrock.remote.action.IActionHandler
import moe.fuqiuluo.shamrock.remote.service.data.MessageResult
import moe.fuqiuluo.shamrock.tools.EmptyJsonString
import moe.fuqiuluo.shamrock.tools.json
import moe.fuqiuluo.shamrock.tools.jsonArray
import moe.fuqiuluo.symbols.OneBotHandler
@OneBotHandler("send_guild_message", ["send_guild_msg", "send_guild_channel_msg"])
internal object SendGuildMessage: IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val guildId = session.getString("guild_id").toULong()
val channelId = session.getString("channel_id").toULong()
val retryCnt = session.getIntOrNull("retry_cnt") ?: 3
val recallDuration = session.getLongOrNull("recall_duration")
return if (session.isString("message")) {
val autoEscape = session.getBooleanOrDefault("auto_escape", false)
val message = session.getString("message")
return invoke(guildId, channelId, message, autoEscape, retryCnt, recallDuration, echo = session.echo)
} else if (session.isArray("message")) {
val message = session.getArray("message")
return invoke(guildId, channelId, message, echo = session.echo, retryCnt = retryCnt, recallDuration = recallDuration)
} else {
val message = session.getObject("message")
invoke(guildId, channelId, listOf(message).jsonArray, session.echo, retryCnt, recallDuration = recallDuration)
}
}
suspend operator fun invoke(
guildId: ULong,
channelId: ULong,
message: String,
autoEscape: Boolean,
retryCnt: Int,
recallDuration: Long?,
echo: JsonElement = EmptyJsonString
): String {
val result = if (autoEscape) {
MsgSvc.sendToAio(MsgConstant.KCHATTYPEGUILD, guildId.toString(), listOf(
mapOf(
"type" to "text",
"data" to mapOf(
"text" to message
)
)
).json, fromId = channelId.toString(), retryCnt)
} else {
val msg = MessageHelper.decodeCQCode(message)
if (msg.isEmpty()) {
LogCenter.log("CQ码不合法", Level.WARN)
return logic("CQCode is illegal", echo)
} else {
MsgSvc.sendToAio(MsgConstant.KCHATTYPEGUILD, guildId.toString(), msg, fromId = channelId.toString(), retryCnt)
}
}
if (result.isFailure) {
return logic(result.exceptionOrNull()?.message ?: "", echo)
}
val sendMsgResult = result.getOrThrow()
if (sendMsgResult.msgHashId <= 0) {
return logic("send message failed", echo = echo)
}
recallDuration?.let { autoRecall(sendMsgResult.msgHashId, it) }
return ok(
MessageResult(
msgId = sendMsgResult.msgHashId,
time = (sendMsgResult.msgTime * 0.001).toLong()
), echo = echo)
}
suspend operator fun invoke(
guildId: ULong, channelId: ULong, message: JsonArray, echo: JsonElement = EmptyJsonString, retryCnt: Int, recallDuration: Long?,
): String {
val result = MsgSvc.sendToAio(MsgConstant.KCHATTYPEGUILD, guildId.toString(), message, fromId = channelId.toString(), retryCnt)
if (result.isFailure) {
return logic(result.exceptionOrNull()?.message ?: "", echo)
}
val sendMsgResult = result.getOrThrow()
if (sendMsgResult.msgHashId <= 0) {
return logic("send message failed", echo = echo)
}
recallDuration?.let { autoRecall(sendMsgResult.msgHashId, it) }
return ok(MessageResult(
msgId = sendMsgResult.msgHashId,
time = (sendMsgResult.msgTime * 0.001).toLong()
), echo)
}
override val requiredParams: Array<String> = arrayOf("guild_id", "channel_id", "message")
private fun autoRecall(msgHash: Int, duration: Long) {
GlobalScope.launch(Dispatchers.Default) {
delay(duration)
MsgSvc.recallMsg(msgHash)
}
}
}

View File

@ -81,9 +81,6 @@ internal object SendMessage: IActionHandler() {
recallDuration: Long?, recallDuration: Long?,
echo: JsonElement = EmptyJsonString echo: JsonElement = EmptyJsonString
): String { ): String {
//if (!ContactHelper.checkContactAvailable(chatType, peerId)) {
// return logic("contact is not found", echo = echo)
//}
val result = if (autoEscape) { val result = if (autoEscape) {
MsgSvc.sendToAio(chatType, peerId, listOf( MsgSvc.sendToAio(chatType, peerId, listOf(
mapOf( mapOf(

View File

@ -4,16 +4,31 @@ import io.ktor.http.ContentType
import io.ktor.server.application.call import io.ktor.server.application.call
import io.ktor.server.response.respondText import io.ktor.server.response.respondText
import io.ktor.server.routing.Routing import io.ktor.server.routing.Routing
import io.ktor.server.routing.get
import io.ktor.server.routing.post
import io.ktor.server.routing.route
import moe.fuqiuluo.shamrock.helper.MessageHelper
import moe.fuqiuluo.shamrock.remote.action.handlers.GetGProChannelList import moe.fuqiuluo.shamrock.remote.action.handlers.GetGProChannelList
import moe.fuqiuluo.shamrock.remote.action.handlers.GetGuildList import moe.fuqiuluo.shamrock.remote.action.handlers.GetGuildList
import moe.fuqiuluo.shamrock.remote.action.handlers.GetGuildMemberList import moe.fuqiuluo.shamrock.remote.action.handlers.GetGuildMemberList
import moe.fuqiuluo.shamrock.remote.action.handlers.GetGuildMemberProfile import moe.fuqiuluo.shamrock.remote.action.handlers.GetGuildMemberProfile
import moe.fuqiuluo.shamrock.remote.action.handlers.GetGuildMetaByGuest import moe.fuqiuluo.shamrock.remote.action.handlers.GetGuildMetaByGuest
import moe.fuqiuluo.shamrock.remote.action.handlers.GetGuildServiceProfile import moe.fuqiuluo.shamrock.remote.action.handlers.GetGuildServiceProfile
import moe.fuqiuluo.shamrock.remote.action.handlers.SendGuildMessage
import moe.fuqiuluo.shamrock.remote.action.handlers.SendMessage
import moe.fuqiuluo.shamrock.tools.fetchGetOrNull import moe.fuqiuluo.shamrock.tools.fetchGetOrNull
import moe.fuqiuluo.shamrock.tools.fetchGetOrThrow
import moe.fuqiuluo.shamrock.tools.fetchOrNull import moe.fuqiuluo.shamrock.tools.fetchOrNull
import moe.fuqiuluo.shamrock.tools.fetchOrThrow import moe.fuqiuluo.shamrock.tools.fetchOrThrow
import moe.fuqiuluo.shamrock.tools.fetchPostJsonArray
import moe.fuqiuluo.shamrock.tools.fetchPostJsonObject
import moe.fuqiuluo.shamrock.tools.fetchPostOrNull
import moe.fuqiuluo.shamrock.tools.fetchPostOrThrow
import moe.fuqiuluo.shamrock.tools.getOrPost import moe.fuqiuluo.shamrock.tools.getOrPost
import moe.fuqiuluo.shamrock.tools.isJsonData
import moe.fuqiuluo.shamrock.tools.isJsonObject
import moe.fuqiuluo.shamrock.tools.isJsonString
import moe.fuqiuluo.shamrock.tools.jsonArray
fun Routing.guildAction() { fun Routing.guildAction() {
getOrPost("/get_guild_service_profile") { getOrPost("/get_guild_service_profile") {
@ -47,4 +62,51 @@ fun Routing.guildAction() {
val userId = fetchOrThrow("user_id") val userId = fetchOrThrow("user_id")
call.respondText(GetGuildMemberProfile(guildId.toULong(), userId.toULong()), ContentType.Application.Json) call.respondText(GetGuildMemberProfile(guildId.toULong(), userId.toULong()), ContentType.Application.Json)
} }
route("/(send_guild_channel_msg|send_guild_message|send_guild_msg)".toRegex()) {
get {
val guildId = fetchGetOrThrow("guild_id").toULong()
val channelId = fetchGetOrThrow("channel_id").toULong()
val message = fetchGetOrThrow("message")
val autoEscape = fetchGetOrNull("auto_escape")?.toBoolean() ?: false
val retryCnt = fetchGetOrNull("retry_cnt")?.toInt() ?: 3
val recallDuration = fetchGetOrNull("recall_duration")?.toLong()
call.respondText(SendGuildMessage(guildId, channelId, message, autoEscape, retryCnt, recallDuration), ContentType.Application.Json)
}
post {
val retryCnt = fetchOrNull("retry_cnt")?.toInt() ?: 3
val recallDuration = fetchOrNull("recall_duration")?.toLong()
val guildId = fetchOrThrow("guild_id").toULong()
val channelId = fetchOrThrow("channel_id").toULong()
call.respondText(if (isJsonData() && !isJsonString("message")) {
if (isJsonObject("message")) {
SendGuildMessage(
guildId = guildId,
channelId = channelId,
message = listOf(fetchPostJsonObject("message")).jsonArray,
retryCnt = retryCnt,
recallDuration = recallDuration
)
} else {
SendGuildMessage(
guildId = guildId,
channelId = channelId,
message = fetchPostJsonArray("message"),
retryCnt = retryCnt,
recallDuration = recallDuration
)
}
} else {
val autoEscape = fetchPostOrNull("auto_escape")?.toBooleanStrict() ?: false
SendGuildMessage(
guildId = guildId,
channelId = channelId,
message = fetchOrThrow("message"),
autoEscape = autoEscape,
retryCnt = retryCnt,
recallDuration = recallDuration
)
}, ContentType.Application.Json)
}
}
} }

View File

@ -189,6 +189,7 @@ internal object GlobalEventTransmitter: BaseSvc() {
role = MemberRole.Member, role = MemberRole.Member,
title = record.sendNickName, title = record.sendNickName,
level = record.roleId.toString(), level = record.roleId.toString(),
tinyId = record.senderUid
), ),
) )
) )

View File

@ -35,6 +35,7 @@ internal data class MessageSender(
@SerialName("sex") val sex: String, @SerialName("sex") val sex: String,
@SerialName("age") val age: Int, @SerialName("age") val age: Int,
@SerialName("uid") val uid: String, @SerialName("uid") val uid: String,
@SerialName("tiny_id") val tinyId: String,
) )
@Serializable @Serializable

View File

@ -97,4 +97,5 @@ internal data class Sender(
@SerialName("role") val role: MemberRole?, @SerialName("role") val role: MemberRole?,
@SerialName("title") val title: String, @SerialName("title") val title: String,
@SerialName("level") val level: String, @SerialName("level") val level: String,
@SerialName("tiny_id") val tinyId: String = "0",
) )

View File

@ -48,21 +48,21 @@ internal object AioListener : IKernelMsgListener {
val msgHash = MessageHelper.generateMsgIdHash(record.chatType, record.msgId) val msgHash = MessageHelper.generateMsgIdHash(record.chatType, record.msgId)
val peerId = when(record.chatType) {
MsgConstant.KCHATTYPEGUILD -> record.guildId
else -> record.peerUin.toString()
}
MessageHelper.saveMsgMapping( MessageHelper.saveMsgMapping(
hash = msgHash, hash = msgHash,
qqMsgId = record.msgId, qqMsgId = record.msgId,
chatType = record.chatType, chatType = record.chatType,
subChatType = record.chatType, subChatType = record.chatType,
peerId = record.peerUin.toString(), peerId = peerId,
msgSeq = record.msgSeq.toInt(), msgSeq = record.msgSeq.toInt(),
time = record.msgTime time = record.msgTime,
subPeerId = record.channelId ?: peerId
) )
val peerId = when(record.chatType) {
MsgConstant.KCHATTYPEGUILD -> record.guildId
else -> record.peerUin.toString()
}
val rawMsg = record.elements.toCQCode(record.chatType, peerId, record.channelId ?: peerId) val rawMsg = record.elements.toCQCode(record.chatType, peerId, record.channelId ?: peerId)
if (rawMsg.isEmpty()) return if (rawMsg.isEmpty()) return
@ -124,7 +124,7 @@ internal object AioListener : IKernelMsgListener {
} }
MsgConstant.KCHATTYPEGUILD -> { MsgConstant.KCHATTYPEGUILD -> {
LogCenter.log("频道消息(guildId = ${record.guildId}, id = [$msgHash | ${record.msgId}], msg = $rawMsg)") LogCenter.log("频道消息(guildId = ${record.guildId}, sender=${record.senderUid}, id = [$msgHash | ${record.msgId}], msg = $rawMsg)")
if(!GlobalEventTransmitter.MessageTransmitter if(!GlobalEventTransmitter.MessageTransmitter
.transGuildMessage(record, record.elements, rawMsg, msgHash, postType = postType) .transGuildMessage(record, record.elements, rawMsg, msgHash, postType = postType)
) { ) {
@ -144,21 +144,25 @@ internal object AioListener : IKernelMsgListener {
} }
override fun onAddSendMsg(record: MsgRecord) { override fun onAddSendMsg(record: MsgRecord) {
if (record.chatType == MsgConstant.KCHATTYPEGUILD) return // TODO: 频道消息暂不处理
if (record.peerUin == TicketSvc.getLongUin()) return // 发给自己的消息不处理 if (record.peerUin == TicketSvc.getLongUin()) return // 发给自己的消息不处理
GlobalScope.launch { GlobalScope.launch {
try { try {
val msgHash = MessageHelper.generateMsgIdHash(record.chatType, record.msgId) val msgHash = MessageHelper.generateMsgIdHash(record.chatType, record.msgId)
val peerId = when(record.chatType) {
MsgConstant.KCHATTYPEGUILD -> record.guildId
else -> record.peerUin.toString()
}
MessageHelper.saveMsgMapping( MessageHelper.saveMsgMapping(
hash = msgHash, hash = msgHash,
qqMsgId = record.msgId, qqMsgId = record.msgId,
chatType = record.chatType, chatType = record.chatType,
subChatType = record.chatType, subChatType = record.chatType,
peerId = record.peerUin.toString(), peerId = peerId,
msgSeq = record.msgSeq.toInt(), msgSeq = record.msgSeq.toInt(),
time = record.msgTime time = record.msgTime,
subPeerId = record.channelId ?: peerId
) )
LogCenter.log("预发送消息($msgHash | ${record.msgSeq} | ${record.msgId})") LogCenter.log("预发送消息($msgHash | ${record.msgSeq} | ${record.msgId})")
@ -180,6 +184,10 @@ internal object AioListener : IKernelMsgListener {
GlobalScope.launch { GlobalScope.launch {
val msgHash = MessageHelper.generateMsgIdHash(record.chatType, record.msgId) val msgHash = MessageHelper.generateMsgIdHash(record.chatType, record.msgId)
val peerId = when(record.chatType) {
MsgConstant.KCHATTYPEGUILD -> record.guildId
else -> record.peerUin.toString()
}
val mapping = MessageHelper.getMsgMappingByHash(msgHash) val mapping = MessageHelper.getMsgMappingByHash(msgHash)
if (mapping == null) { if (mapping == null) {
@ -188,9 +196,10 @@ internal object AioListener : IKernelMsgListener {
qqMsgId = record.msgId, qqMsgId = record.msgId,
chatType = record.chatType, chatType = record.chatType,
subChatType = record.chatType, subChatType = record.chatType,
peerId = record.peerUin.toString(), peerId = peerId,
msgSeq = record.msgSeq.toInt(), msgSeq = record.msgSeq.toInt(),
time = record.msgTime time = record.msgTime,
subPeerId = record.channelId ?: peerId
) )
} else { } else {
LogCenter.log("Update message info from ${mapping.msgSeq} to ${record.msgSeq}", Level.INFO) LogCenter.log("Update message info from ${mapping.msgSeq} to ${record.msgSeq}", Level.INFO)
@ -203,11 +212,6 @@ internal object AioListener : IKernelMsgListener {
|| record.peerUin == TicketSvc.getLongUin() || record.peerUin == TicketSvc.getLongUin()
) return@launch ) return@launch
val peerId = when(record.chatType) {
MsgConstant.KCHATTYPEGUILD -> record.guildId
else -> record.peerUin.toString()
}
val rawMsg = record.elements.toCQCode(record.chatType, peerId, record.channelId ?: peerId) val rawMsg = record.elements.toCQCode(record.chatType, peerId, record.channelId ?: peerId)
if (rawMsg.isEmpty()) return@launch if (rawMsg.isEmpty()) return@launch
LogCenter.log("自发消息(target = ${record.peerUin}, id = $msgHash, msg = $rawMsg)") LogCenter.log("自发消息(target = ${record.peerUin}, id = $msgHash, msg = $rawMsg)")