mirror of
https://github.com/whitechi73/OpenShamrock.git
synced 2024-08-14 05:12:17 +00:00
Compare commits
3 Commits
a485e72ddf
...
c97f79335a
Author | SHA1 | Date | |
---|---|---|---|
c97f79335a | |||
e07e75747a | |||
9482641c38 |
@ -0,0 +1,14 @@
|
|||||||
|
package moe.whitechi73.protobuf.oidb.cmd0x9082
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.protobuf.ProtoNumber
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Oidb0x9082(
|
||||||
|
@ProtoNumber(2) val peer: ULong = ULong.MIN_VALUE,
|
||||||
|
@ProtoNumber(3) val msgSeq: ULong = ULong.MIN_VALUE,
|
||||||
|
@ProtoNumber(4) val faceIndex: String = "",
|
||||||
|
@ProtoNumber(5) val flag: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(6) val u1: UInt = UInt.MIN_VALUE,
|
||||||
|
@ProtoNumber(7) val u2: UInt = UInt.MIN_VALUE,
|
||||||
|
)
|
@ -19,4 +19,11 @@ public class QQSysFaceUtil {
|
|||||||
public static String getFaceDescription(int localId) {
|
public static String getFaceDescription(int localId) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getPrueFaceDescription(String str) {
|
||||||
|
if (str == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return str.startsWith("/") ? str.substring(1) : str;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
package moe.fuqiuluo.qqinterface.servlet
|
||||||
|
|
||||||
|
import kotlinx.serialization.encodeToByteArray
|
||||||
|
import kotlinx.serialization.protobuf.ProtoBuf
|
||||||
|
import moe.whitechi73.protobuf.oidb.cmd0x9082.Oidb0x9082
|
||||||
|
|
||||||
|
internal object ChatSvc: BaseSvc() {
|
||||||
|
fun setGroupMessageCommentFace(peer: Long, msgSeq: ULong, faceIndex: String, isSet: Boolean) {
|
||||||
|
val serviceId = if (isSet) 1 else 2
|
||||||
|
sendOidb("OidbSvcTrpcTcp.0x9082_$serviceId", 36994, serviceId, ProtoBuf.encodeToByteArray(Oidb0x9082(
|
||||||
|
peer = peer.toULong(),
|
||||||
|
msgSeq = msgSeq,
|
||||||
|
faceIndex = faceIndex,
|
||||||
|
flag = 1u,
|
||||||
|
u1 = 0u,
|
||||||
|
u2 = 0u
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
}
|
@ -9,6 +9,7 @@ import com.tencent.mobileqq.qroute.QRoute
|
|||||||
import com.tencent.qphone.base.remote.ToServiceMsg
|
import com.tencent.qphone.base.remote.ToServiceMsg
|
||||||
import com.tencent.qqnt.aio.adapter.api.IAIOPttApi
|
import com.tencent.qqnt.aio.adapter.api.IAIOPttApi
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.ArkElement
|
import com.tencent.qqnt.kernel.nativeinterface.ArkElement
|
||||||
|
import com.tencent.qqnt.kernel.nativeinterface.FaceBubbleElement
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.FaceElement
|
import com.tencent.qqnt.kernel.nativeinterface.FaceElement
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.MarkdownElement
|
import com.tencent.qqnt.kernel.nativeinterface.MarkdownElement
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.MarketFaceElement
|
import com.tencent.qqnt.kernel.nativeinterface.MarketFaceElement
|
||||||
@ -20,9 +21,9 @@ import com.tencent.qqnt.kernel.nativeinterface.PttElement
|
|||||||
import com.tencent.qqnt.kernel.nativeinterface.QQNTWrapperUtil
|
import com.tencent.qqnt.kernel.nativeinterface.QQNTWrapperUtil
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.ReplyElement
|
import com.tencent.qqnt.kernel.nativeinterface.ReplyElement
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.RichMediaFilePathInfo
|
import com.tencent.qqnt.kernel.nativeinterface.RichMediaFilePathInfo
|
||||||
|
import com.tencent.qqnt.kernel.nativeinterface.SmallYellowFaceInfo
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.TextElement
|
import com.tencent.qqnt.kernel.nativeinterface.TextElement
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.VideoElement
|
import com.tencent.qqnt.kernel.nativeinterface.VideoElement
|
||||||
import kotlinx.serialization.SerializationException
|
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import kotlinx.serialization.json.JsonElement
|
import kotlinx.serialization.json.JsonElement
|
||||||
import kotlinx.serialization.json.JsonObject
|
import kotlinx.serialization.json.JsonObject
|
||||||
@ -45,7 +46,9 @@ import moe.fuqiuluo.qqinterface.servlet.transfile.with
|
|||||||
import moe.fuqiuluo.shamrock.helper.ActionMsgException
|
import moe.fuqiuluo.shamrock.helper.ActionMsgException
|
||||||
import moe.fuqiuluo.shamrock.helper.ContactHelper
|
import moe.fuqiuluo.shamrock.helper.ContactHelper
|
||||||
import moe.fuqiuluo.shamrock.helper.IllegalParamsException
|
import moe.fuqiuluo.shamrock.helper.IllegalParamsException
|
||||||
|
import moe.fuqiuluo.shamrock.helper.Level
|
||||||
import moe.fuqiuluo.shamrock.helper.LocalCacheHelper
|
import moe.fuqiuluo.shamrock.helper.LocalCacheHelper
|
||||||
|
import moe.fuqiuluo.shamrock.helper.LogCenter
|
||||||
import moe.fuqiuluo.shamrock.helper.LogicException
|
import moe.fuqiuluo.shamrock.helper.LogicException
|
||||||
import moe.fuqiuluo.shamrock.helper.MessageHelper
|
import moe.fuqiuluo.shamrock.helper.MessageHelper
|
||||||
import moe.fuqiuluo.shamrock.helper.MusicHelper
|
import moe.fuqiuluo.shamrock.helper.MusicHelper
|
||||||
@ -62,8 +65,6 @@ import moe.fuqiuluo.shamrock.utils.AudioUtils
|
|||||||
import moe.fuqiuluo.shamrock.utils.FileUtils
|
import moe.fuqiuluo.shamrock.utils.FileUtils
|
||||||
import moe.fuqiuluo.shamrock.utils.MediaType
|
import moe.fuqiuluo.shamrock.utils.MediaType
|
||||||
import moe.fuqiuluo.shamrock.utils.PlatformUtils
|
import moe.fuqiuluo.shamrock.utils.PlatformUtils
|
||||||
import moe.fuqiuluo.shamrock.helper.Level
|
|
||||||
import moe.fuqiuluo.shamrock.helper.LogCenter
|
|
||||||
import moe.fuqiuluo.shamrock.xposed.helper.AppRuntimeFetcher
|
import moe.fuqiuluo.shamrock.xposed.helper.AppRuntimeFetcher
|
||||||
import moe.fuqiuluo.shamrock.xposed.helper.NTServiceFetcher
|
import moe.fuqiuluo.shamrock.xposed.helper.NTServiceFetcher
|
||||||
import moe.fuqiuluo.shamrock.xposed.helper.msgService
|
import moe.fuqiuluo.shamrock.xposed.helper.msgService
|
||||||
@ -106,8 +107,32 @@ internal object MessageMaker {
|
|||||||
"basketball" to MessageMaker::createBasketballElem,
|
"basketball" to MessageMaker::createBasketballElem,
|
||||||
//"node" to MessageMaker::createNodeElem,
|
//"node" to MessageMaker::createNodeElem,
|
||||||
//"multi_msg" to MessageMaker::createLongMsgStruct,
|
//"multi_msg" to MessageMaker::createLongMsgStruct,
|
||||||
|
"bubble_face" to MessageMaker::createBubbleFaceElem,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private suspend fun createBubbleFaceElem(chatType: Int, msgId: Long, peerId: String, data: JsonObject): Result<MsgElement> {
|
||||||
|
data.checkAndThrow("id", "count")
|
||||||
|
val faceId = data["id"].asInt
|
||||||
|
val local = QQSysFaceUtil.convertToLocal(faceId)
|
||||||
|
val name = QQSysFaceUtil.getFaceDescription(local)
|
||||||
|
val count = data["count"].asInt
|
||||||
|
val elem = MsgElement()
|
||||||
|
elem.elementType = MsgConstant.KELEMTYPEFACEBUBBLE
|
||||||
|
val face = FaceBubbleElement()
|
||||||
|
face.faceType = 13
|
||||||
|
face.faceCount = count
|
||||||
|
face.faceSummary = QQSysFaceUtil.getPrueFaceDescription(name)
|
||||||
|
val smallYellowFaceInfo = SmallYellowFaceInfo()
|
||||||
|
smallYellowFaceInfo.index = faceId
|
||||||
|
smallYellowFaceInfo.compatibleText = face.faceSummary
|
||||||
|
smallYellowFaceInfo.text = face.faceSummary
|
||||||
|
face.yellowFaceInfo = smallYellowFaceInfo
|
||||||
|
face.faceFlag = 0
|
||||||
|
face.content = data["text"].asStringOrNull ?: "[${face.faceSummary}]x$count"
|
||||||
|
elem.faceBubbleElement = face
|
||||||
|
return Result.success(elem)
|
||||||
|
}
|
||||||
|
|
||||||
// private suspend fun createNodeElem(
|
// private suspend fun createNodeElem(
|
||||||
// chatType: Int,
|
// chatType: Int,
|
||||||
// msgId: Long,
|
// msgId: Long,
|
||||||
@ -475,19 +500,31 @@ internal object MessageMaker {
|
|||||||
private suspend fun createFaceElem(chatType: Int, msgId: Long, peerId: String, data: JsonObject): Result<MsgElement> {
|
private suspend fun createFaceElem(chatType: Int, msgId: Long, peerId: String, data: JsonObject): Result<MsgElement> {
|
||||||
data.checkAndThrow("id")
|
data.checkAndThrow("id")
|
||||||
|
|
||||||
|
val big = data["big"].asBooleanOrNull ?: false
|
||||||
|
|
||||||
val elem = MsgElement()
|
val elem = MsgElement()
|
||||||
elem.elementType = MsgConstant.KELEMTYPEFACE
|
elem.elementType = MsgConstant.KELEMTYPEFACE
|
||||||
val face = FaceElement()
|
val face = FaceElement()
|
||||||
|
|
||||||
|
// 1 old face
|
||||||
|
// 2 normal face
|
||||||
|
// 3 super face
|
||||||
// 4 is market face
|
// 4 is market face
|
||||||
// 5 is vas poke
|
// 5 is vas poke
|
||||||
face.faceType = 0
|
face.faceType = if (big) 3 else 2
|
||||||
val serverId = data["id"].asInt
|
val serverId = data["id"].asInt
|
||||||
val localId = QQSysFaceUtil.convertToLocal(serverId)
|
|
||||||
face.faceIndex = serverId
|
face.faceIndex = serverId
|
||||||
face.faceText = QQSysFaceUtil.getFaceDescription(localId)
|
face.faceText = QQSysFaceUtil.getFaceDescription(QQSysFaceUtil.convertToLocal(serverId))
|
||||||
face.imageType = 0
|
face.imageType = 0
|
||||||
face.packId = "0"
|
if (big) {
|
||||||
|
face.stickerId = 30.toString()
|
||||||
|
face.packId = "1"
|
||||||
|
face.sourceType = 1
|
||||||
|
face.stickerType = 1
|
||||||
|
face.randomType = 1
|
||||||
|
} else {
|
||||||
|
face.packId = "0"
|
||||||
|
}
|
||||||
elem.faceElement = face
|
elem.faceElement = face
|
||||||
|
|
||||||
return Result.success(elem)
|
return Result.success(elem)
|
||||||
|
@ -4,6 +4,7 @@ import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
|
|||||||
import com.tencent.qqnt.kernel.nativeinterface.MsgElement
|
import com.tencent.qqnt.kernel.nativeinterface.MsgElement
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.MsgRecord
|
import com.tencent.qqnt.kernel.nativeinterface.MsgRecord
|
||||||
import kotlinx.serialization.json.JsonElement
|
import kotlinx.serialization.json.JsonElement
|
||||||
|
import moe.fuqiuluo.qqinterface.servlet.msg.convert.MessageElemConverter.*
|
||||||
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.helper.MessageHelper
|
import moe.fuqiuluo.shamrock.helper.MessageHelper
|
||||||
@ -43,19 +44,20 @@ internal suspend fun List<MsgElement>.toCQCode(chatType: Int, peerId: String): S
|
|||||||
internal object MessageConvert {
|
internal object MessageConvert {
|
||||||
private val convertMap by lazy {
|
private val convertMap by lazy {
|
||||||
mutableMapOf<Int, IMessageConvert>(
|
mutableMapOf<Int, IMessageConvert>(
|
||||||
MsgConstant.KELEMTYPETEXT to MessageElemConverter.TextConverter,
|
MsgConstant.KELEMTYPETEXT to TextConverter,
|
||||||
MsgConstant.KELEMTYPEFACE to MessageElemConverter.FaceConverter,
|
MsgConstant.KELEMTYPEFACE to FaceConverter,
|
||||||
MsgConstant.KELEMTYPEPIC to MessageElemConverter.ImageConverter,
|
MsgConstant.KELEMTYPEPIC to ImageConverter,
|
||||||
MsgConstant.KELEMTYPEPTT to MessageElemConverter.VoiceConverter,
|
MsgConstant.KELEMTYPEPTT to VoiceConverter,
|
||||||
MsgConstant.KELEMTYPEVIDEO to MessageElemConverter.VideoConverter,
|
MsgConstant.KELEMTYPEVIDEO to VideoConverter,
|
||||||
MsgConstant.KELEMTYPEMARKETFACE to MessageElemConverter.MarketFaceConverter,
|
MsgConstant.KELEMTYPEMARKETFACE to MarketFaceConverter,
|
||||||
MsgConstant.KELEMTYPEARKSTRUCT to MessageElemConverter.StructJsonConverter,
|
MsgConstant.KELEMTYPEARKSTRUCT to StructJsonConverter,
|
||||||
MsgConstant.KELEMTYPEREPLY to MessageElemConverter.ReplyConverter,
|
MsgConstant.KELEMTYPEREPLY to ReplyConverter,
|
||||||
MsgConstant.KELEMTYPEGRAYTIP to MessageElemConverter.GrayTipsConverter,
|
MsgConstant.KELEMTYPEGRAYTIP to GrayTipsConverter,
|
||||||
MsgConstant.KELEMTYPEFILE to MessageElemConverter.FileConverter,
|
MsgConstant.KELEMTYPEFILE to FileConverter,
|
||||||
MsgConstant.KELEMTYPEMARKDOWN to MessageElemConverter.MarkdownConverter,
|
MsgConstant.KELEMTYPEMARKDOWN to MarkdownConverter,
|
||||||
//MsgConstant.KELEMTYPEMULTIFORWARD to MessageElemConverter.XmlMultiMsgConverter,
|
//MsgConstant.KELEMTYPEMULTIFORWARD to XmlMultiMsgConverter,
|
||||||
//MsgConstant.KELEMTYPESTRUCTLONGMSG to MessageElemConverter.XmlLongMsgConverter,
|
//MsgConstant.KELEMTYPESTRUCTLONGMSG to XmlLongMsgConverter,
|
||||||
|
MsgConstant.KELEMTYPEFACEBUBBLE to BubbleFaceConverter,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,11 +67,11 @@ internal object MessageConvert {
|
|||||||
peerId: String
|
peerId: String
|
||||||
): ArrayList<MessageSegment> {
|
): ArrayList<MessageSegment> {
|
||||||
val messageData = arrayListOf<MessageSegment>()
|
val messageData = arrayListOf<MessageSegment>()
|
||||||
elements.forEach {
|
elements.forEach { msg ->
|
||||||
kotlin.runCatching {
|
kotlin.runCatching {
|
||||||
val elementId = it.elementType
|
val elementId = msg.elementType
|
||||||
val converter = convertMap[elementId]
|
val converter = convertMap[elementId]
|
||||||
converter?.convert(chatType, peerId, it)
|
converter?.convert(chatType, peerId, msg)
|
||||||
?: throw UnsupportedOperationException("不支持的消息element类型:$elementId")
|
?: throw UnsupportedOperationException("不支持的消息element类型:$elementId")
|
||||||
}.onSuccess {
|
}.onSuccess {
|
||||||
messageData.add(it)
|
messageData.add(it)
|
||||||
@ -77,7 +79,7 @@ internal object MessageConvert {
|
|||||||
if (it is UnknownError) {
|
if (it is UnknownError) {
|
||||||
// 不处理的消息类型,抛出unknown error
|
// 不处理的消息类型,抛出unknown error
|
||||||
} else {
|
} else {
|
||||||
LogCenter.log("消息element转换错误:$it", Level.WARN)
|
LogCenter.log("消息element转换错误:$it, elementType: ${msg.elementType}", Level.WARN)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ internal sealed class MessageElemConverter: IMessageConvert {
|
|||||||
/**
|
/**
|
||||||
* 文本 / 艾特 消息转换消息段
|
* 文本 / 艾特 消息转换消息段
|
||||||
*/
|
*/
|
||||||
object TextConverter: MessageElemConverter() {
|
data object TextConverter: MessageElemConverter() {
|
||||||
override suspend fun convert(chatType: Int, peerId: String, element: MsgElement): MessageSegment {
|
override suspend fun convert(chatType: Int, peerId: String, element: MsgElement): MessageSegment {
|
||||||
val text = element.textElement
|
val text = element.textElement
|
||||||
return if (text.atType != MsgConstant.ATTYPEUNKNOWN) {
|
return if (text.atType != MsgConstant.ATTYPEUNKNOWN) {
|
||||||
@ -42,9 +42,10 @@ internal sealed class MessageElemConverter: IMessageConvert {
|
|||||||
/**
|
/**
|
||||||
* 小表情 / 戳一戳 消息转换消息段
|
* 小表情 / 戳一戳 消息转换消息段
|
||||||
*/
|
*/
|
||||||
object FaceConverter: MessageElemConverter() {
|
data object FaceConverter: MessageElemConverter() {
|
||||||
override suspend fun convert(chatType: Int, peerId: String, element: MsgElement): MessageSegment {
|
override suspend fun convert(chatType: Int, peerId: String, element: MsgElement): MessageSegment {
|
||||||
val face = element.faceElement
|
val face = element.faceElement
|
||||||
|
|
||||||
if (face.faceType == 5) {
|
if (face.faceType == 5) {
|
||||||
return MessageSegment(
|
return MessageSegment(
|
||||||
type = "poke",
|
type = "poke",
|
||||||
@ -55,8 +56,6 @@ internal sealed class MessageElemConverter: IMessageConvert {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
when (face.faceIndex) {
|
when (face.faceIndex) {
|
||||||
114 -> {
|
114 -> {
|
||||||
return MessageSegment(
|
return MessageSegment(
|
||||||
@ -87,7 +86,8 @@ internal sealed class MessageElemConverter: IMessageConvert {
|
|||||||
else -> return MessageSegment(
|
else -> return MessageSegment(
|
||||||
type = "face",
|
type = "face",
|
||||||
data = hashMapOf(
|
data = hashMapOf(
|
||||||
"id" to face.faceIndex
|
"id" to face.faceIndex,
|
||||||
|
"big" to (face.faceType == 3)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -97,7 +97,7 @@ internal sealed class MessageElemConverter: IMessageConvert {
|
|||||||
/**
|
/**
|
||||||
* 图片消息转换消息段
|
* 图片消息转换消息段
|
||||||
*/
|
*/
|
||||||
object ImageConverter: MessageElemConverter() {
|
data object ImageConverter: MessageElemConverter() {
|
||||||
override suspend fun convert(
|
override suspend fun convert(
|
||||||
chatType: Int,
|
chatType: Int,
|
||||||
peerId: String,
|
peerId: String,
|
||||||
@ -121,7 +121,9 @@ internal sealed class MessageElemConverter: IMessageConvert {
|
|||||||
MsgConstant.KCHATTYPEGROUP -> RichProtoSvc.getGroupPicDownUrl(md5)
|
MsgConstant.KCHATTYPEGROUP -> RichProtoSvc.getGroupPicDownUrl(md5)
|
||||||
MsgConstant.KCHATTYPEC2C -> RichProtoSvc.getC2CPicDownUrl(md5)
|
MsgConstant.KCHATTYPEC2C -> RichProtoSvc.getC2CPicDownUrl(md5)
|
||||||
else -> unknownChatType(chatType)
|
else -> unknownChatType(chatType)
|
||||||
}
|
},
|
||||||
|
"subType" to image.picSubType,
|
||||||
|
"type" to if (image.isFlashPic) "flash" else "show"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -130,7 +132,7 @@ internal sealed class MessageElemConverter: IMessageConvert {
|
|||||||
/**
|
/**
|
||||||
* 语音消息转换消息段
|
* 语音消息转换消息段
|
||||||
*/
|
*/
|
||||||
object VoiceConverter: MessageElemConverter() {
|
data object VoiceConverter: MessageElemConverter() {
|
||||||
override suspend fun convert(
|
override suspend fun convert(
|
||||||
chatType: Int,
|
chatType: Int,
|
||||||
peerId: String,
|
peerId: String,
|
||||||
@ -166,7 +168,7 @@ internal sealed class MessageElemConverter: IMessageConvert {
|
|||||||
/**
|
/**
|
||||||
* 视频消息转换消息段
|
* 视频消息转换消息段
|
||||||
*/
|
*/
|
||||||
object VideoConverter: MessageElemConverter() {
|
data object VideoConverter: MessageElemConverter() {
|
||||||
override suspend fun convert(
|
override suspend fun convert(
|
||||||
chatType: Int,
|
chatType: Int,
|
||||||
peerId: String,
|
peerId: String,
|
||||||
@ -195,7 +197,7 @@ internal sealed class MessageElemConverter: IMessageConvert {
|
|||||||
/**
|
/**
|
||||||
* 商城大表情消息转换消息段
|
* 商城大表情消息转换消息段
|
||||||
*/
|
*/
|
||||||
object MarketFaceConverter: MessageElemConverter() {
|
data object MarketFaceConverter: MessageElemConverter() {
|
||||||
override suspend fun convert(
|
override suspend fun convert(
|
||||||
chatType: Int,
|
chatType: Int,
|
||||||
peerId: String,
|
peerId: String,
|
||||||
@ -218,7 +220,7 @@ internal sealed class MessageElemConverter: IMessageConvert {
|
|||||||
/**
|
/**
|
||||||
* JSON消息转消息段
|
* JSON消息转消息段
|
||||||
*/
|
*/
|
||||||
object StructJsonConverter: MessageElemConverter() {
|
data object StructJsonConverter: MessageElemConverter() {
|
||||||
override suspend fun convert(
|
override suspend fun convert(
|
||||||
chatType: Int,
|
chatType: Int,
|
||||||
peerId: String,
|
peerId: String,
|
||||||
@ -280,7 +282,7 @@ internal sealed class MessageElemConverter: IMessageConvert {
|
|||||||
/**
|
/**
|
||||||
* 回复消息转消息段
|
* 回复消息转消息段
|
||||||
*/
|
*/
|
||||||
object ReplyConverter: MessageElemConverter() {
|
data object ReplyConverter: MessageElemConverter() {
|
||||||
override suspend fun convert(
|
override suspend fun convert(
|
||||||
chatType: Int,
|
chatType: Int,
|
||||||
peerId: String,
|
peerId: String,
|
||||||
@ -312,7 +314,7 @@ internal sealed class MessageElemConverter: IMessageConvert {
|
|||||||
/**
|
/**
|
||||||
* 灰色提示条消息过滤
|
* 灰色提示条消息过滤
|
||||||
*/
|
*/
|
||||||
object GrayTipsConverter: MessageElemConverter() {
|
data object GrayTipsConverter: MessageElemConverter() {
|
||||||
override suspend fun convert(
|
override suspend fun convert(
|
||||||
chatType: Int,
|
chatType: Int,
|
||||||
peerId: String,
|
peerId: String,
|
||||||
@ -347,7 +349,7 @@ internal sealed class MessageElemConverter: IMessageConvert {
|
|||||||
/**
|
/**
|
||||||
* 文件消息转换消息段
|
* 文件消息转换消息段
|
||||||
*/
|
*/
|
||||||
object FileConverter: MessageElemConverter() {
|
data object FileConverter: MessageElemConverter() {
|
||||||
override suspend fun convert(
|
override suspend fun convert(
|
||||||
chatType: Int,
|
chatType: Int,
|
||||||
peerId: String,
|
peerId: String,
|
||||||
@ -381,7 +383,7 @@ internal sealed class MessageElemConverter: IMessageConvert {
|
|||||||
/**
|
/**
|
||||||
* 老板QQ的合并转发信息
|
* 老板QQ的合并转发信息
|
||||||
*/
|
*/
|
||||||
object XmlMultiMsgConverter: MessageElemConverter() {
|
data object XmlMultiMsgConverter: MessageElemConverter() {
|
||||||
override suspend fun convert(
|
override suspend fun convert(
|
||||||
chatType: Int,
|
chatType: Int,
|
||||||
peerId: String,
|
peerId: String,
|
||||||
@ -397,7 +399,7 @@ internal sealed class MessageElemConverter: IMessageConvert {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object XmlLongMsgConverter: MessageElemConverter() {
|
data object XmlLongMsgConverter: MessageElemConverter() {
|
||||||
override suspend fun convert(
|
override suspend fun convert(
|
||||||
chatType: Int,
|
chatType: Int,
|
||||||
peerId: String,
|
peerId: String,
|
||||||
@ -413,7 +415,7 @@ internal sealed class MessageElemConverter: IMessageConvert {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object MarkdownConverter: MessageElemConverter() {
|
data object MarkdownConverter: MessageElemConverter() {
|
||||||
override suspend fun convert(
|
override suspend fun convert(
|
||||||
chatType: Int,
|
chatType: Int,
|
||||||
peerId: String,
|
peerId: String,
|
||||||
@ -429,6 +431,23 @@ internal sealed class MessageElemConverter: IMessageConvert {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data object BubbleFaceConverter: MessageElemConverter() {
|
||||||
|
override suspend fun convert(
|
||||||
|
chatType: Int,
|
||||||
|
peerId: String,
|
||||||
|
element: MsgElement
|
||||||
|
): MessageSegment {
|
||||||
|
val bubbleElement = element.faceBubbleElement
|
||||||
|
return MessageSegment(
|
||||||
|
type = "bubble_face",
|
||||||
|
data = mapOf(
|
||||||
|
"id" to bubbleElement.yellowFaceInfo.index,
|
||||||
|
"count" to (bubbleElement.faceCount ?: 1),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected fun unknownChatType(chatType: Int) {
|
protected fun unknownChatType(chatType: Int) {
|
||||||
throw UnsupportedOperationException("Not supported chat type: $chatType")
|
throw UnsupportedOperationException("Not supported chat type: $chatType")
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
package moe.fuqiuluo.shamrock.remote.action.handlers
|
||||||
|
|
||||||
|
import kotlinx.serialization.json.JsonElement
|
||||||
|
import moe.fuqiuluo.qqinterface.servlet.ChatSvc
|
||||||
|
import moe.fuqiuluo.qqinterface.servlet.MsgSvc
|
||||||
|
import moe.fuqiuluo.shamrock.helper.MessageHelper
|
||||||
|
import moe.fuqiuluo.shamrock.remote.action.ActionSession
|
||||||
|
import moe.fuqiuluo.shamrock.remote.action.IActionHandler
|
||||||
|
import moe.fuqiuluo.shamrock.tools.EmptyJsonString
|
||||||
|
import moe.fuqiuluo.symbols.OneBotHandler
|
||||||
|
|
||||||
|
@OneBotHandler("set_group_comment_face")
|
||||||
|
internal object SetGroupCommentFace: IActionHandler() {
|
||||||
|
override suspend fun internalHandle(session: ActionSession): String {
|
||||||
|
val groupId = session.getLong("group_id")
|
||||||
|
val msgId = session.getIntOrNull("msg_id") ?: session.getInt("message_id")
|
||||||
|
val faceId = session.getInt("face_id")
|
||||||
|
val isSet = session.getBooleanOrDefault("is_set", true)
|
||||||
|
return invoke(groupId, msgId, faceId, isSet, session.echo)
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun invoke(groupId: Long, msgHash: Int, faceIndex: Int, isSet: Boolean, echo: JsonElement = EmptyJsonString): String {
|
||||||
|
val mapping = MessageHelper.getMsgMappingByHash(msgHash)
|
||||||
|
?: return error("failed to locate message", echo = echo)
|
||||||
|
ChatSvc.setGroupMessageCommentFace(groupId, mapping.msgSeq.toULong(), faceIndex.toString(), isSet)
|
||||||
|
return ok("success", echo = echo)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val requiredParams: Array<String> = arrayOf("group_id", "face_id")
|
||||||
|
}
|
@ -1,19 +1,30 @@
|
|||||||
package moe.fuqiuluo.shamrock.remote.api
|
package moe.fuqiuluo.shamrock.remote.api
|
||||||
|
|
||||||
import io.ktor.http.ContentType
|
import io.ktor.http.ContentType
|
||||||
import moe.fuqiuluo.shamrock.helper.LogicException
|
|
||||||
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 moe.fuqiuluo.shamrock.remote.action.ActionManager
|
|
||||||
import moe.fuqiuluo.shamrock.remote.action.ActionSession
|
|
||||||
import moe.fuqiuluo.shamrock.remote.action.handlers.*
|
import moe.fuqiuluo.shamrock.remote.action.handlers.*
|
||||||
import moe.fuqiuluo.shamrock.tools.fetch
|
import moe.fuqiuluo.shamrock.tools.fetchGetOrNull
|
||||||
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.getOrPost
|
import moe.fuqiuluo.shamrock.tools.getOrPost
|
||||||
|
|
||||||
fun Routing.troopAction() {
|
fun Routing.troopAction() {
|
||||||
|
getOrPost("/set_group_comment_face") {
|
||||||
|
val groupId = fetchOrThrow("group_id").toLong()
|
||||||
|
val msgId = fetchOrNull("msg_id")?.toIntOrNull() ?: fetchOrThrow("message_id").toInt()
|
||||||
|
val faceId = fetchOrThrow("face_id").toInt()
|
||||||
|
val isSet = fetchGetOrNull("is_set") ?: "true"
|
||||||
|
call.respondText(SetGroupCommentFace(groupId, msgId, faceId, when(isSet) {
|
||||||
|
"true" -> true
|
||||||
|
"false" -> false
|
||||||
|
"1" -> true
|
||||||
|
"0" -> false
|
||||||
|
else -> true
|
||||||
|
}), ContentType.Application.Json)
|
||||||
|
}
|
||||||
|
|
||||||
getOrPost("/get_not_joined_group_info") {
|
getOrPost("/get_not_joined_group_info") {
|
||||||
val groupId = fetchOrThrow("group_id")
|
val groupId = fetchOrThrow("group_id")
|
||||||
call.respondText(GetNotJoinedGroupInfo(groupId), ContentType.Application.Json)
|
call.respondText(GetNotJoinedGroupInfo(groupId), ContentType.Application.Json)
|
||||||
|
@ -16,7 +16,7 @@ import moe.fuqiuluo.shamrock.xposed.ipc.ShamrockIpc
|
|||||||
import moe.fuqiuluo.symbols.Process
|
import moe.fuqiuluo.symbols.Process
|
||||||
import moe.fuqiuluo.symbols.XposedHook
|
import moe.fuqiuluo.symbols.XposedHook
|
||||||
|
|
||||||
@XposedHook(Process.MSF, 0)
|
@XposedHook(Process.MSF, priority = 0)
|
||||||
internal class IpcService: IAction {
|
internal class IpcService: IAction {
|
||||||
override fun invoke(ctx: Context) {
|
override fun invoke(ctx: Context) {
|
||||||
if (!PlatformUtils.isMsfProcess()) return
|
if (!PlatformUtils.isMsfProcess()) return
|
||||||
|
Reference in New Issue
Block a user