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) {
this.serialVersionUID = 1L;
this.peerUid = "";
this.guildId = "";
this.chatType = i2;
this.peerUid = str;
this.guildId = str2;

View File

@ -7,7 +7,6 @@ import com.tencent.qqnt.msg.api.IMsgService
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withTimeoutOrNull
import kotlinx.serialization.json.JsonArray
import moe.fuqiuluo.shamrock.helper.Level
import moe.fuqiuluo.shamrock.helper.MessageHelper
import moe.fuqiuluo.shamrock.helper.LogCenter
import moe.fuqiuluo.shamrock.xposed.helper.NTServiceFetcher
@ -103,10 +102,15 @@ internal object MsgSvc: BaseSvc() {
*
* 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)
//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(

View File

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

View File

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

View File

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

View File

@ -7,13 +7,15 @@ import moe.fuqiuluo.shamrock.remote.action.IActionHandler
internal object SendPrivateMessage: IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
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")) {
val autoEscape = session.getBooleanOrDefault("auto_escape", false)
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 {
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()) {
get {
val userId = fetchGetOrThrow("user_id")
val groupId = fetchGetOrNull("group_id")
val message = fetchGetOrThrow("message")
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 {
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.PostType
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.NoticeSubType
import moe.fuqiuluo.shamrock.remote.service.data.push.NoticeType
@ -92,7 +93,8 @@ internal object GlobalEventTransmitter: BaseSvc() {
elements: ArrayList<MsgElement>,
rawMsg: String,
msgHash: Int,
postType: PostType = PostType.Msg
postType: PostType = PostType.Msg,
tempSource: MessageTempSource = MessageTempSource.Unknown
): Boolean {
val uin = app.longAccountUin
transMessageEvent(record,
@ -119,7 +121,8 @@ internal object GlobalEventTransmitter: BaseSvc() {
role = MemberRole.Member,
title = "",
level = "",
)
),
tmpSource = tempSource.id
)
)
return true

View File

@ -56,9 +56,23 @@ internal data class MessageEvent (
@SerialName("message") val message: JsonElement,
@SerialName("raw_message") val rawMessage: String,
@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
internal data class Anonymous(
@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.LogCenter
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 java.util.ArrayList
import java.util.HashMap
@ -71,6 +72,24 @@ internal object AioListener: IKernelMsgListener {
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}")
}
} catch (e: Throwable) {
@ -109,6 +128,11 @@ internal object AioListener: IKernelMsgListener {
GlobalEventTransmitter.MessageTransmitter
.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}")
}
} catch (e: Throwable) {