Shamrock: 臨時メッセージ

Signed-off-by: WhiteChi <whitechi73@outlook.com>
This commit is contained in:
WhiteChi 2023-10-31 14:30:40 +08:00
parent 52b8db70be
commit e41b7515d3
10 changed files with 93 additions and 25 deletions

View File

@ -44,8 +44,6 @@ public final class Contact implements IKernelModel, Serializable {
public Contact(int i2, String str, String str2) { public Contact(int i2, String str, String str2) {
this.serialVersionUID = 1L; this.serialVersionUID = 1L;
this.peerUid = "";
this.guildId = "";
this.chatType = i2; this.chatType = i2;
this.peerUid = str; this.peerUid = str;
this.guildId = str2; this.guildId = str2;

View File

@ -7,7 +7,6 @@ import com.tencent.qqnt.msg.api.IMsgService
import kotlinx.coroutines.suspendCancellableCoroutine import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withTimeoutOrNull import kotlinx.coroutines.withTimeoutOrNull
import kotlinx.serialization.json.JsonArray import kotlinx.serialization.json.JsonArray
import moe.fuqiuluo.shamrock.helper.Level
import moe.fuqiuluo.shamrock.helper.MessageHelper import moe.fuqiuluo.shamrock.helper.MessageHelper
import moe.fuqiuluo.shamrock.helper.LogCenter import moe.fuqiuluo.shamrock.helper.LogCenter
import moe.fuqiuluo.shamrock.xposed.helper.NTServiceFetcher import moe.fuqiuluo.shamrock.xposed.helper.NTServiceFetcher
@ -103,10 +102,15 @@ internal object MsgSvc: BaseSvc() {
* *
* Aio 腾讯内部命名 All In One * Aio 腾讯内部命名 All In One
*/ */
suspend fun sendToAio(chatType: Int, peedId: String, message: JsonArray): Pair<Long, Int> { suspend fun sendToAio(
chatType: Int,
peedId: String,
message: JsonArray,
fromId: String = peedId
): Pair<Long, Int> {
//LogCenter.log(message.toString(), Level.ERROR) //LogCenter.log(message.toString(), Level.ERROR)
//callback.msgHash = result.second 什么垃圾代码万一cb比你快你不就寄了 //callback.msgHash = result.second 什么垃圾代码万一cb比你快你不就寄了
return MessageHelper.sendMessageWithoutMsgId(chatType, peedId, message, MessageCallback(peedId, 0)) return MessageHelper.sendMessageWithoutMsgId(chatType, peedId, message, MessageCallback(peedId, 0), fromId)
} }
class MessageCallback( class MessageCallback(

View File

@ -23,7 +23,13 @@ import moe.fuqiuluo.shamrock.tools.jsonArray
import kotlin.math.abs import kotlin.math.abs
internal object MessageHelper { internal object MessageHelper {
suspend fun sendMessageWithoutMsgId(chatType: Int, peerId: String, message: JsonArray, callback: IOperateCallback): Pair<Long, Int> { suspend fun sendMessageWithoutMsgId(
chatType: Int,
peerId: String,
message: JsonArray,
callback: IOperateCallback,
fromId: String = peerId
): Pair<Long, Int> {
val uniseq = generateMsgId(chatType) val uniseq = generateMsgId(chatType)
var nonMsg: Boolean var nonMsg: Boolean
val msg = messageArrayToMessageElements(chatType, uniseq.second, peerId, message).also { val msg = messageArrayToMessageElements(chatType, uniseq.second, peerId, message).also {
@ -39,7 +45,7 @@ internal object MessageHelper {
callback.msgHash = uniseq.first callback.msgHash = uniseq.first
} }
service.sendMsg( service.sendMsg(
generateContact(chatType, peerId), generateContact(chatType, peerId, fromId),
uniseq.second, uniseq.second,
msg as ArrayList<MsgElement>, msg as ArrayList<MsgElement>,
callback callback
@ -51,7 +57,7 @@ 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) { val peerId = if (MsgConstant.KCHATTYPEC2C == chatType || MsgConstant.KCHATTYPETEMPC2CFROMGROUP == chatType) {
ContactHelper.getUidByUinAsync(id.toLong()) ContactHelper.getUidByUinAsync(id.toLong())
} else id } else id
return Contact(chatType, peerId, subId) return Contact(chatType, peerId, subId)
@ -107,6 +113,7 @@ internal object MessageHelper {
val key = when (chatType) { val key = when (chatType) {
MsgConstant.KCHATTYPEGROUP -> "grp$msgId" MsgConstant.KCHATTYPEGROUP -> "grp$msgId"
MsgConstant.KCHATTYPEC2C -> "c2c$msgId" MsgConstant.KCHATTYPEC2C -> "c2c$msgId"
MsgConstant.KCHATTYPETEMPC2CFROMGROUP -> "tmpgrp$msgId"
else -> error("不支持的消息来源类型 | generateMsgIdHash: $chatType") else -> error("不支持的消息来源类型 | generateMsgIdHash: $chatType")
} }
return abs(key.hashCode()) return abs(key.hashCode())

View File

@ -10,7 +10,7 @@ internal object SendGroupMessage: IActionHandler() {
return if (session.isString("message")) { return if (session.isString("message")) {
val autoEscape = session.getBooleanOrDefault("auto_escape", false) val autoEscape = session.getBooleanOrDefault("auto_escape", false)
val message = session.getString("message") val message = session.getString("message")
SendMessage(MsgConstant.KCHATTYPEGROUP, groupId, message, autoEscape, session.echo) SendMessage(MsgConstant.KCHATTYPEGROUP, groupId, message, autoEscape, echo = session.echo)
} else { } else {
val message = session.getArray("message") val message = session.getArray("message")
SendMessage(MsgConstant.KCHATTYPEGROUP, groupId, message, session.echo) SendMessage(MsgConstant.KCHATTYPEGROUP, groupId, message, session.echo)

View File

@ -19,13 +19,13 @@ internal object SendMessage: IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String { override suspend fun internalHandle(session: ActionSession): String {
val detailType = session.getStringOrNull("detail_type") ?: session.getStringOrNull("message_type") val detailType = session.getStringOrNull("detail_type") ?: session.getStringOrNull("message_type")
try { try {
val chatType = detailType?.let { var chatType = detailType?.let {
MessageHelper.obtainMessageTypeByDetailType(it) MessageHelper.obtainMessageTypeByDetailType(it)
} ?: run { } ?: run {
if (session.has("group_id")) { if (session.has("user_id")) {
MsgConstant.KCHATTYPEGROUP
} else if (session.has("user_id")) {
MsgConstant.KCHATTYPEC2C MsgConstant.KCHATTYPEC2C
} else if (session.has("group_id")) {
MsgConstant.KCHATTYPEGROUP
} else { } else {
return noParam("detail_type/message_type", session.echo) return noParam("detail_type/message_type", session.echo)
} }
@ -35,13 +35,21 @@ internal object SendMessage: IActionHandler() {
MsgConstant.KCHATTYPEC2C -> session.getStringOrNull("user_id") ?: return noParam("user_id", session.echo) MsgConstant.KCHATTYPEC2C -> session.getStringOrNull("user_id") ?: return noParam("user_id", session.echo)
else -> error("unknown chat type: $chatType") else -> error("unknown chat type: $chatType")
} }
var fromId = peerId
if (chatType == MsgConstant.KCHATTYPEC2C) {
val groupId = session.getStringOrNull("group_id")
if (groupId != null) {
chatType = MsgConstant.KCHATTYPETEMPC2CFROMGROUP
fromId = groupId
}
}
return if (session.isString("message")) { return if (session.isString("message")) {
val autoEscape = session.getBooleanOrDefault("auto_escape", false) val autoEscape = session.getBooleanOrDefault("auto_escape", false)
val message = session.getString("message") val message = session.getString("message")
invoke(chatType, peerId, message, autoEscape, session.echo) invoke(chatType, peerId, message, autoEscape, echo = session.echo, fromId = fromId)
} else { } else {
val message = session.getArray("message") val message = session.getArray("message")
invoke(chatType, peerId, message, session.echo) invoke(chatType, peerId, message, session.echo, fromId = fromId)
} }
} catch (e: ParamsException) { } catch (e: ParamsException) {
return noParam(e.message!!, session.echo) return noParam(e.message!!, session.echo)
@ -56,20 +64,21 @@ internal object SendMessage: IActionHandler() {
peerId: String, peerId: String,
message: String, message: String,
autoEscape: Boolean, autoEscape: Boolean,
fromId: String = peerId,
echo: JsonElement = EmptyJsonString echo: JsonElement = EmptyJsonString
): String { ): String {
//if (!ContactHelper.checkContactAvailable(chatType, peerId)) { //if (!ContactHelper.checkContactAvailable(chatType, peerId)) {
// return logic("contact is not found", echo = echo) // return logic("contact is not found", echo = echo)
//} //}
val result = if (autoEscape) { val result = if (autoEscape) {
MsgSvc.sendToAio(chatType, peerId, arrayListOf(message).json) MsgSvc.sendToAio(chatType, peerId, arrayListOf(message).json, fromId = fromId)
} else { } else {
val msg = MessageHelper.decodeCQCode(message) val msg = MessageHelper.decodeCQCode(message)
if (msg.isEmpty()) { if (msg.isEmpty()) {
LogCenter.log("CQ码不合法", Level.WARN) LogCenter.log("CQ码不合法", Level.WARN)
return logic("CQCode is illegal", echo) return logic("CQCode is illegal", echo)
} else { } else {
MsgSvc.sendToAio(chatType, peerId, msg) MsgSvc.sendToAio(chatType, peerId, msg, fromId = fromId)
} }
} }
return ok(MessageResult( return ok(MessageResult(
@ -80,12 +89,12 @@ internal object SendMessage: IActionHandler() {
// 消息段格式消息 // 消息段格式消息
suspend operator fun invoke( suspend operator fun invoke(
chatType: Int, peerId: String, message: JsonArray, echo: JsonElement = EmptyJsonString chatType: Int, peerId: String, message: JsonArray, echo: JsonElement = EmptyJsonString, fromId: String = peerId
): String { ): String {
//if (!ContactHelper.checkContactAvailable(chatType, peerId)) { //if (!ContactHelper.checkContactAvailable(chatType, peerId)) {
// return logic("contact is not found", echo = echo) // return logic("contact is not found", echo = echo)
//} //}
val result = MsgSvc.sendToAio(chatType, peerId, message) val result = MsgSvc.sendToAio(chatType, peerId, message, fromId = fromId)
return ok(MessageResult( return ok(MessageResult(
msgId = result.second, msgId = result.second,
time = result.first * 0.001 time = result.first * 0.001

View File

@ -7,13 +7,15 @@ import moe.fuqiuluo.shamrock.remote.action.IActionHandler
internal object SendPrivateMessage: IActionHandler() { internal object SendPrivateMessage: IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String { override suspend fun internalHandle(session: ActionSession): String {
val userId = session.getString("user_id") val userId = session.getString("user_id")
val groupId = session.getStringOrNull("group_id")
val chatTYpe = if (groupId == null) MsgConstant.KCHATTYPEC2C else MsgConstant.KCHATTYPETEMPC2CFROMGROUP
return if (session.isString("message")) { return if (session.isString("message")) {
val autoEscape = session.getBooleanOrDefault("auto_escape", false) val autoEscape = session.getBooleanOrDefault("auto_escape", false)
val message = session.getString("message") val message = session.getString("message")
SendMessage(MsgConstant.KCHATTYPEC2C, userId, message, autoEscape, session.echo) SendMessage(chatTYpe, userId, message, autoEscape, echo = session.echo, fromId = groupId ?: userId)
} else { } else {
val message = session.getArray("message") val message = session.getArray("message")
SendMessage(MsgConstant.KCHATTYPEC2C, userId, message, session.echo) SendMessage(chatTYpe, userId, message, session.echo, fromId = groupId ?: userId)
} }
} }

View File

@ -82,9 +82,16 @@ fun Routing.messageAction() {
route("/send_private_(msg|message)".toRegex()) { route("/send_private_(msg|message)".toRegex()) {
get { get {
val userId = fetchGetOrThrow("user_id") val userId = fetchGetOrThrow("user_id")
val groupId = fetchGetOrNull("group_id")
val message = fetchGetOrThrow("message") val message = fetchGetOrThrow("message")
val autoEscape = fetchGetOrNull("auto_escape")?.toBooleanStrict() ?: false val autoEscape = fetchGetOrNull("auto_escape")?.toBooleanStrict() ?: false
call.respondText(SendMessage(MsgConstant.KCHATTYPEC2C, userId, message, autoEscape)) call.respondText(SendMessage(
chatType = if (groupId == null) MsgConstant.KCHATTYPEC2C else MsgConstant.KCHATTYPETEMPC2CFROMGROUP,
peerId = userId,
message = message,
autoEscape = autoEscape,
fromId = groupId ?: userId
))
} }
post { post {
val userId = fetchPostOrThrow("user_id") val userId = fetchPostOrThrow("user_id")

View File

@ -14,6 +14,7 @@ import moe.fuqiuluo.shamrock.remote.service.data.push.MsgSubType
import moe.fuqiuluo.shamrock.remote.service.data.push.MsgType import moe.fuqiuluo.shamrock.remote.service.data.push.MsgType
import moe.fuqiuluo.shamrock.remote.service.data.push.PostType import moe.fuqiuluo.shamrock.remote.service.data.push.PostType
import moe.fuqiuluo.shamrock.remote.service.data.push.MessageEvent import moe.fuqiuluo.shamrock.remote.service.data.push.MessageEvent
import moe.fuqiuluo.shamrock.remote.service.data.push.MessageTempSource
import moe.fuqiuluo.shamrock.remote.service.data.push.NoticeEvent import moe.fuqiuluo.shamrock.remote.service.data.push.NoticeEvent
import moe.fuqiuluo.shamrock.remote.service.data.push.NoticeSubType import moe.fuqiuluo.shamrock.remote.service.data.push.NoticeSubType
import moe.fuqiuluo.shamrock.remote.service.data.push.NoticeType import moe.fuqiuluo.shamrock.remote.service.data.push.NoticeType
@ -92,7 +93,8 @@ internal object GlobalEventTransmitter: BaseSvc() {
elements: ArrayList<MsgElement>, elements: ArrayList<MsgElement>,
rawMsg: String, rawMsg: String,
msgHash: Int, msgHash: Int,
postType: PostType = PostType.Msg postType: PostType = PostType.Msg,
tempSource: MessageTempSource = MessageTempSource.Unknown
): Boolean { ): Boolean {
val uin = app.longAccountUin val uin = app.longAccountUin
transMessageEvent(record, transMessageEvent(record,
@ -119,7 +121,8 @@ internal object GlobalEventTransmitter: BaseSvc() {
role = MemberRole.Member, role = MemberRole.Member,
title = "", title = "",
level = "", level = "",
) ),
tmpSource = tempSource.id
) )
) )
return true return true

View File

@ -56,9 +56,23 @@ internal data class MessageEvent (
@SerialName("message") val message: JsonElement, @SerialName("message") val message: JsonElement,
@SerialName("raw_message") val rawMessage: String, @SerialName("raw_message") val rawMessage: String,
@SerialName("font") val font: Int, @SerialName("font") val font: Int,
@SerialName("sender") val sender: Sender @SerialName("sender") val sender: Sender,
@SerialName("temp_source") val tmpSource: Int = -1
) )
enum class MessageTempSource(val id: Int) {
Group(0),
Consultation(1),
Seek(2),
QQMovie(3),
HotChat(4),
VerifyMsg(6),
Discussion(7),
Dating(8),
Contact(9),
Unknown(-1),
}
@Serializable @Serializable
internal data class Anonymous( internal data class Anonymous(
@SerialName("name") val name: String @SerialName("name") val name: String

View File

@ -12,6 +12,7 @@ import moe.fuqiuluo.shamrock.remote.service.config.ShamrockConfig
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.remote.service.api.GlobalEventTransmitter import moe.fuqiuluo.shamrock.remote.service.api.GlobalEventTransmitter
import moe.fuqiuluo.shamrock.remote.service.data.push.MessageTempSource
import moe.fuqiuluo.shamrock.remote.service.data.push.PostType import moe.fuqiuluo.shamrock.remote.service.data.push.PostType
import java.util.ArrayList import java.util.ArrayList
import java.util.HashMap import java.util.HashMap
@ -71,6 +72,24 @@ internal object AioListener: IKernelMsgListener {
LogCenter.log("私聊消息推送失败 -> MessageTransmitter", Level.WARN) LogCenter.log("私聊消息推送失败 -> MessageTransmitter", Level.WARN)
} }
} }
MsgConstant.KCHATTYPETEMPC2CFROMGROUP -> {
if (!ShamrockConfig.allowTempSession()) {
return
}
LogCenter.log("私聊临时消息(private = ${record.senderUin}, id = $msgHash, msg = $rawMsg)")
ShamrockConfig.getPrivateRule()?.let { rule ->
if (rule.black?.contains(record.peerUin) == true) return
if (rule.white?.contains(record.peerUin) == false) return
}
if(!GlobalEventTransmitter.MessageTransmitter.transPrivateMessage(
record, record.elements, rawMsg, msgHash, tempSource = MessageTempSource.Group
)) {
LogCenter.log("私聊临时消息推送失败 -> MessageTransmitter", Level.WARN)
}
}
else -> LogCenter.log("不支持PUSH事件: ${record.chatType}") else -> LogCenter.log("不支持PUSH事件: ${record.chatType}")
} }
} catch (e: Throwable) { } catch (e: Throwable) {
@ -109,6 +128,11 @@ internal object AioListener: IKernelMsgListener {
GlobalEventTransmitter.MessageTransmitter GlobalEventTransmitter.MessageTransmitter
.transPrivateMessage(record, record.elements, rawMsg, msgHash, PostType.MsgSent) .transPrivateMessage(record, record.elements, rawMsg, msgHash, PostType.MsgSent)
} }
MsgConstant.KCHATTYPETEMPC2CFROMGROUP -> {
if (!ShamrockConfig.allowTempSession()) return@launch
GlobalEventTransmitter.MessageTransmitter
.transPrivateMessage(record, record.elements, rawMsg, msgHash, PostType.MsgSent, MessageTempSource.Group)
}
else -> LogCenter.log("不支持SELF PUSH事件: ${record.chatType}") else -> LogCenter.log("不支持SELF PUSH事件: ${record.chatType}")
} }
} catch (e: Throwable) { } catch (e: Throwable) {