Shamrock: feat: 精华消息

This commit is contained in:
ikechan8370 2023-11-20 18:36:46 +08:00
parent 46c83f5cb9
commit 16f77de5a6
6 changed files with 131 additions and 2 deletions

View File

@ -22,7 +22,10 @@ import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withTimeoutOrNull import kotlinx.coroutines.withTimeoutOrNull
import moe.fuqiuluo.proto.ProtoUtils
import moe.fuqiuluo.proto.asUtf8String
import moe.fuqiuluo.proto.protobufOf import moe.fuqiuluo.proto.protobufOf
import moe.fuqiuluo.shamrock.helper.LogCenter
import moe.fuqiuluo.shamrock.tools.ifNullOrEmpty import moe.fuqiuluo.shamrock.tools.ifNullOrEmpty
import moe.fuqiuluo.shamrock.tools.putBuf32Long import moe.fuqiuluo.shamrock.tools.putBuf32Long
import moe.fuqiuluo.shamrock.tools.slice import moe.fuqiuluo.shamrock.tools.slice
@ -32,6 +35,7 @@ import mqq.app.MobileQQ
import tencent.im.oidb.cmd0x89a.oidb_0x89a import tencent.im.oidb.cmd0x89a.oidb_0x89a
import tencent.im.oidb.cmd0x8a0.oidb_0x8a0 import tencent.im.oidb.cmd0x8a0.oidb_0x8a0
import tencent.im.oidb.cmd0x8fc.Oidb_0x8fc import tencent.im.oidb.cmd0x8fc.Oidb_0x8fc
import tencent.im.oidb.oidb_sso
import java.lang.reflect.Method import java.lang.reflect.Method
import java.lang.reflect.Modifier import java.lang.reflect.Modifier
import java.nio.ByteBuffer import java.nio.ByteBuffer
@ -139,6 +143,51 @@ internal object GroupSvc: BaseSvc() {
return true return true
} }
suspend fun setEssenceMessage(groupId: Long, seq: Long, rand: Long): Pair<Boolean, String> {
val array = protobufOf(
1 to groupId,
2 to seq,
3 to rand
).toByteArray()
val buffer = sendOidbAW("OidbSvc.0xeac_1", 3756, 1, array)
val body = oidb_sso.OIDBSSOPkg()
if (buffer == null) {
return Pair(false, "unknown error")
}
body.mergeFrom(buffer.slice(4))
val result = ProtoUtils.decodeFromByteArray(body.bytes_bodybuffer.get().toByteArray())
return if (result.has(1)) {
LogCenter.log("设置群精华失败: ${result[1].asUtf8String}")
Pair(false, "设置群精华失败: ${result[1].asUtf8String}")
} else {
LogCenter.log("设置群精华 -> $groupId:$seq")
Pair(true, "ok")
}
}
suspend fun deleteEssenceMessage(groupId: Long, seq: Long, rand: Long): Pair<Boolean, String> {
val array = protobufOf(
1 to groupId,
2 to seq,
3 to rand
).toByteArray()
val buffer = sendOidbAW("OidbSvc.0xeac_2", 3756, 2, array)
val body = oidb_sso.OIDBSSOPkg()
if (buffer == null) {
return Pair(false, "unknown error")
}
body.mergeFrom(buffer.slice(4))
val result = ProtoUtils.decodeFromByteArray(body.bytes_bodybuffer.get().toByteArray())
return if (result.has(1)) {
LogCenter.log("移除群精华失败: ${result[1].asUtf8String}")
Pair(false, "移除群精华失败: ${result[1].asUtf8String}")
} else {
LogCenter.log("移除群精华 -> $groupId:$seq")
Pair(true, "ok")
}
}
fun setGroupAdmin(groupId: Long, userId: Long, enable: Boolean) { fun setGroupAdmin(groupId: Long, userId: Long, enable: Boolean) {
val buffer = ByteBuffer.allocate(9) val buffer = ByteBuffer.allocate(9)
buffer.putBuf32Long(groupId) buffer.putBuf32Long(groupId)

View File

@ -29,7 +29,7 @@ internal object ActionManager {
// GroupActions // GroupActions
ModifyTroopName, LeaveTroop, KickTroopMember, BanTroopMember, SetGroupWholeBan, SetGroupAdmin, ModifyTroopName, LeaveTroop, KickTroopMember, BanTroopMember, SetGroupWholeBan, SetGroupAdmin,
ModifyTroopMemberName, SetGroupUnique, GetTroopHonor, GroupPoke, ModifyTroopMemberName, SetGroupUnique, GetTroopHonor, GroupPoke, SetEssenceMessage, DeleteEssenceMessage,
// MSG ACTIONS // MSG ACTIONS
SendMessage, DeleteMessage, GetMsg, GetForwardMsg, SendGroupForwardMsg, SendGroupMessage, SendPrivateMessage, SendMessage, DeleteMessage, GetMsg, GetForwardMsg, SendGroupForwardMsg, SendGroupMessage, SendPrivateMessage,

View File

@ -0,0 +1,34 @@
package moe.fuqiuluo.shamrock.remote.action.handlers
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
import kotlinx.serialization.json.JsonElement
import moe.fuqiuluo.qqinterface.servlet.GroupSvc
import moe.fuqiuluo.qqinterface.servlet.MsgSvc
import moe.fuqiuluo.shamrock.remote.action.ActionSession
import moe.fuqiuluo.shamrock.remote.action.IActionHandler
import moe.fuqiuluo.shamrock.tools.EmptyJsonString
internal object DeleteEssenceMessage: IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val messageId = session.getInt("message_id")
return invoke(messageId, session.echo)
}
suspend operator fun invoke(messageId: Int, echo: JsonElement = EmptyJsonString): String {
val msg = MsgSvc.getMsg(messageId).onFailure {
return logic("Obtain msg failed, please check your msg_id.", echo)
}.getOrThrow()
val (success, tip) = GroupSvc.deleteEssenceMessage(
if (msg.chatType == MsgConstant.KCHATTYPEGROUP) msg.peerUin else 0,
msg.msgSeq,
msg.msgRandom
)
return if (success) {
ok("成功", echo)
} else {
logic(tip, echo)
}
}
override fun path(): String = "delete_essence_message"
}

View File

@ -22,7 +22,7 @@ internal object GetMsg: IActionHandler() {
val msg = MsgSvc.getMsg(msgHash).onFailure { val msg = MsgSvc.getMsg(msgHash).onFailure {
return logic("Obtain msg failed, please check your msg_id.", echo) return logic("Obtain msg failed, please check your msg_id.", echo)
}.getOrThrow() }.getOrThrow()
val seq = msg.clientSeq.toInt() val seq = msg.msgSeq.toInt()
return ok(MessageDetail( return ok(MessageDetail(
time = msg.msgTime.toInt(), time = msg.msgTime.toInt(),
msgType = MessageHelper.obtainDetailTypeByMsgType(msg.chatType), msgType = MessageHelper.obtainDetailTypeByMsgType(msg.chatType),

View File

@ -0,0 +1,35 @@
package moe.fuqiuluo.shamrock.remote.action.handlers
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
import kotlinx.serialization.json.JsonElement
import moe.fuqiuluo.qqinterface.servlet.GroupSvc
import moe.fuqiuluo.qqinterface.servlet.MsgSvc
import moe.fuqiuluo.shamrock.remote.action.ActionSession
import moe.fuqiuluo.shamrock.remote.action.IActionHandler
import moe.fuqiuluo.shamrock.tools.EmptyJsonString
internal object SetEssenceMessage: IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val messageId = session.getInt("message_id")
return invoke(messageId, session.echo)
}
suspend operator fun invoke(messageId: Int, echo: JsonElement = EmptyJsonString): String {
val msg = MsgSvc.getMsg(messageId).onFailure {
return logic("Obtain msg failed, please check your msg_id.", echo)
}.getOrThrow()
val (success, tip) = GroupSvc.setEssenceMessage(
if (msg.chatType == MsgConstant.KCHATTYPEGROUP) msg.peerUin else 0,
msg.msgSeq,
msg.msgRandom
)
return if (success) {
ok("成功", echo)
} else {
logic(tip, echo)
}
}
override fun path(): String = "set_essence_message"
}

View File

@ -95,4 +95,15 @@ fun Routing.troopAction() {
val groupId = fetchOrThrow("group_id").toLong() val groupId = fetchOrThrow("group_id").toLong()
call.respondText(KickTroopMember(groupId, userId), ContentType.Application.Json) call.respondText(KickTroopMember(groupId, userId), ContentType.Application.Json)
} }
getOrPost("/set_essence_msg") {
val messageId = fetchOrThrow("message_id").toInt()
call.respondText(SetEssenceMessage(messageId), ContentType.Application.Json)
}
getOrPost("/delete_essence_msg") {
val messageId = fetchOrThrow("message_id").toInt()
call.respondText(DeleteEssenceMessage(messageId), ContentType.Application.Json)
}
} }