Shamrock: get_essence_msg_list

This commit is contained in:
ikechan8370 2023-11-24 00:21:05 +08:00
parent 0d35d5834b
commit b23620b5ef
6 changed files with 124 additions and 2 deletions

View File

@ -13,7 +13,11 @@ import com.tencent.mobileqq.troop.api.ITroopMemberInfoService
import com.tencent.protofile.join_group_link.join_group_link import com.tencent.protofile.join_group_link.join_group_link
import com.tencent.qphone.base.remote.ToServiceMsg import com.tencent.qphone.base.remote.ToServiceMsg
import com.tencent.qqnt.kernel.nativeinterface.MemberInfo import com.tencent.qqnt.kernel.nativeinterface.MemberInfo
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
import friendlist.stUinInfo import friendlist.stUinInfo
import io.ktor.client.call.body
import io.ktor.client.request.get
import io.ktor.client.request.header
import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
@ -22,12 +26,28 @@ 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 kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.decodeFromStream
import kotlinx.serialization.json.jsonObject
import moe.fuqiuluo.proto.ProtoUtils import moe.fuqiuluo.proto.ProtoUtils
import moe.fuqiuluo.proto.asInt import moe.fuqiuluo.proto.asInt
import moe.fuqiuluo.proto.asUtf8String import moe.fuqiuluo.proto.asUtf8String
import moe.fuqiuluo.proto.protobufOf import moe.fuqiuluo.proto.protobufOf
import moe.fuqiuluo.qqinterface.servlet.entries.ProhibitedMemberInfo import moe.fuqiuluo.qqinterface.servlet.entries.ProhibitedMemberInfo
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.remote.service.data.EssenceMessage
import moe.fuqiuluo.shamrock.tools.EmptyJsonArray
import moe.fuqiuluo.shamrock.tools.GlobalClient
import moe.fuqiuluo.shamrock.tools.asInt
import moe.fuqiuluo.shamrock.tools.asJsonArrayOrNull
import moe.fuqiuluo.shamrock.tools.asJsonObject
import moe.fuqiuluo.shamrock.tools.asLong
import moe.fuqiuluo.shamrock.tools.asString
import moe.fuqiuluo.shamrock.tools.asStringOrNull
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
@ -719,4 +739,47 @@ internal object GroupSvc: BaseSvc() {
return msg.groupmsgs.get() return msg.groupmsgs.get()
} }
} }
@OptIn(ExperimentalSerializationApi::class)
suspend fun getEssenceMessageList(groupId: Long, page: Int = 0, pageSize: Int = 20): Result<List<EssenceMessage>>{
// GlobalClient.get()
val cookie = TicketSvc.getCookie("qun.qq.com")
val bkn = TicketSvc.getBkn(TicketSvc.getRealSkey(TicketSvc.getUin()))
val url = "https://qun.qq.com/cgi-bin/group_digest/digest_list?bkn=${bkn}&group_code=${groupId}&page_start=${page}&page_limit=${pageSize}"
val response = GlobalClient.get(url) {
header("Cookie", cookie)
}
val body = Json.decodeFromStream<JsonElement>(response.body())
LogCenter.log(body.toString(), Level.WARN)
if (body.jsonObject["retcode"].asInt == 0) {
val data = body.jsonObject["data"].asJsonObject
val list = data["msg_list"].asJsonArrayOrNull
?: // is_end
return Result.success(ArrayList())
return Result.success(list.map {
val obj = it.jsonObject
val msgSeq = obj["msg_seq"].asInt
val msg = EssenceMessage(
senderId = obj["sender_uin"].asString.toLong(),
senderNick = obj["sender_nick"].asString,
senderTime = obj["sender_time"].asLong,
operatorId = obj["add_digest_uin"].asString.toLong(),
operatorNick = obj["add_digest_nick"].asString,
operatorTime = obj["add_digest_time"].asLong,
messageId = 0,
messageSeq = msgSeq,
messageContent = obj["msg_content"] ?: EmptyJsonArray
)
val mapping = MessageHelper.getMsgMappingBySeq(MsgConstant.KCHATTYPEGROUP, msgSeq)
if (mapping != null) {
msg.messageId = mapping.msgHashId
}
msg
})
} else {
return Result.failure(Exception(body.jsonObject["retmsg"].asStringOrNull))
}
}
} }

View File

@ -74,8 +74,13 @@ internal object TicketSvc: BaseSvc() {
} }
suspend fun getCSRF(uin: String, domain: String): String { suspend fun getCSRF(uin: String, domain: String): String {
// 是不是要用Skey
return getBkn(getPSKey(uin, domain) ?: "")
}
fun getBkn(arg: String): String {
var v: Long = 5381 var v: Long = 5381
for (element in getPSKey(uin, domain) ?: "") { for (element in arg) {
v += (v shl 5 and 2147483647L) + element.code.toLong() v += (v shl 5 and 2147483647L) + element.code.toLong()
} }
return (v and 2147483647L).toString() return (v and 2147483647L).toString()

View File

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

View File

@ -0,0 +1,33 @@
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 GetEssenceMessageList: IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val groupId = session.getLong("group_id")
val page = session.getIntOrNull("page") ?: 0
val pageSize = session.getIntOrNull("page_size") ?: 20
return invoke(groupId, page, pageSize, session.echo)
}
suspend operator fun invoke(groupId: Long, page: Int = 0, pageSize: Int = 20, echo: JsonElement = EmptyJsonString): String {
if (page < 0 || pageSize > 50) {
return badParam("参数不正确page_size不得大于50", echo)
}
val essenceMessageList = GroupSvc.getEssenceMessageList(groupId, page, pageSize)
if (essenceMessageList.isSuccess) {
return ok(essenceMessageList.getOrNull(), echo)
}
return logic(essenceMessageList.exceptionOrNull()?.message ?: "", echo)
}
override val alias: Array<String> = arrayOf("delete_essence_message")
override fun path(): String = "delete_essence_msg"
}

View File

@ -8,6 +8,7 @@ import io.ktor.server.routing.Routing
import moe.fuqiuluo.shamrock.remote.action.ActionManager import moe.fuqiuluo.shamrock.remote.action.ActionManager
import moe.fuqiuluo.shamrock.remote.action.ActionSession 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.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
@ -116,6 +117,13 @@ fun Routing.troopAction() {
call.respondText(DeleteEssenceMessage(messageId), ContentType.Application.Json) call.respondText(DeleteEssenceMessage(messageId), ContentType.Application.Json)
} }
getOrPost("/get_essence_msg_list") {
val groupId = fetchOrThrow("group_id").toLong()
val page = fetchOrNull("page")?.toIntOrNull() ?: 0
val pageSize = fetchOrNull("page_size")?.toIntOrNull() ?: 20
call.respondText(GetEssenceMessageList(groupId, page, pageSize), ContentType.Application.Json)
}
getOrPost("/get_group_system_msg") { getOrPost("/get_group_system_msg") {
call.respondText(GetGroupSystemMsg(), ContentType.Application.Json) call.respondText(GetGroupSystemMsg(), ContentType.Application.Json)
} }

View File

@ -30,4 +30,17 @@ 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,
)
@Serializable
internal data class EssenceMessage(
@SerialName("sender_id") val senderId: Long,
@SerialName("sender_nick") val senderNick: String,
@SerialName("sender_time") val senderTime: Long,
@SerialName("operator_id") val operatorId: Long,
@SerialName("operator_nick") val operatorNick: String,
@SerialName("operator_time") val operatorTime: Long,
@SerialName("message_id") var messageId: Int,
@SerialName("message_seq") val messageSeq: Int,
@SerialName("message_content") val messageContent: JsonElement,
) )