diff --git a/xposed/src/main/java/moe/fuqiuluo/qqinterface/servlet/GroupSvc.kt b/xposed/src/main/java/moe/fuqiuluo/qqinterface/servlet/GroupSvc.kt index fc52b8f..9654173 100644 --- a/xposed/src/main/java/moe/fuqiuluo/qqinterface/servlet/GroupSvc.kt +++ b/xposed/src/main/java/moe/fuqiuluo/qqinterface/servlet/GroupSvc.kt @@ -13,7 +13,11 @@ import com.tencent.mobileqq.troop.api.ITroopMemberInfoService import com.tencent.protofile.join_group_link.join_group_link import com.tencent.qphone.base.remote.ToServiceMsg import com.tencent.qqnt.kernel.nativeinterface.MemberInfo +import com.tencent.qqnt.kernel.nativeinterface.MsgConstant 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.GlobalScope import kotlinx.coroutines.delay @@ -22,12 +26,28 @@ import kotlinx.coroutines.suspendCancellableCoroutine import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock 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.asInt import moe.fuqiuluo.proto.asUtf8String import moe.fuqiuluo.proto.protobufOf import moe.fuqiuluo.qqinterface.servlet.entries.ProhibitedMemberInfo +import moe.fuqiuluo.shamrock.helper.Level 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.putBuf32Long import moe.fuqiuluo.shamrock.tools.slice @@ -719,4 +739,47 @@ internal object GroupSvc: BaseSvc() { return msg.groupmsgs.get() } } + + + @OptIn(ExperimentalSerializationApi::class) + suspend fun getEssenceMessageList(groupId: Long, page: Int = 0, pageSize: Int = 20): Result>{ +// 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(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)) + } + + } } \ No newline at end of file diff --git a/xposed/src/main/java/moe/fuqiuluo/qqinterface/servlet/TicketSvc.kt b/xposed/src/main/java/moe/fuqiuluo/qqinterface/servlet/TicketSvc.kt index 39f21ca..fa89aa2 100644 --- a/xposed/src/main/java/moe/fuqiuluo/qqinterface/servlet/TicketSvc.kt +++ b/xposed/src/main/java/moe/fuqiuluo/qqinterface/servlet/TicketSvc.kt @@ -74,8 +74,13 @@ internal object TicketSvc: BaseSvc() { } suspend fun getCSRF(uin: String, domain: String): String { + // 是不是要用Skey? + return getBkn(getPSKey(uin, domain) ?: "") + } + + fun getBkn(arg: String): String { var v: Long = 5381 - for (element in getPSKey(uin, domain) ?: "") { + for (element in arg) { v += (v shl 5 and 2147483647L) + element.code.toLong() } return (v and 2147483647L).toString() diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/ActionManager.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/ActionManager.kt index cb7e0e0..66d5687 100644 --- a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/ActionManager.kt +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/ActionManager.kt @@ -31,7 +31,7 @@ internal object ActionManager { // GroupActions ModifyTroopName, LeaveTroop, KickTroopMember, BanTroopMember, SetGroupWholeBan, SetGroupAdmin, ModifyTroopMemberName, SetGroupUnique, GetTroopHonor, GroupPoke, SetEssenceMessage, DeleteEssenceMessage, - GetGroupSystemMsg, GetProhibitedMemberList, + GetGroupSystemMsg, GetProhibitedMemberList, GetEssenceMessageList, // MSG ACTIONS SendMessage, DeleteMessage, GetMsg, GetForwardMsg, SendGroupForwardMsg, SendGroupMessage, SendPrivateMessage, diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/GetEssenceMessageList.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/GetEssenceMessageList.kt new file mode 100644 index 0000000..d76991a --- /dev/null +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/GetEssenceMessageList.kt @@ -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 = arrayOf("delete_essence_message") + override fun path(): String = "delete_essence_msg" +} \ No newline at end of file diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/api/GroupAction.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/api/GroupAction.kt index c49cc88..27e7b63 100644 --- a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/api/GroupAction.kt +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/api/GroupAction.kt @@ -8,6 +8,7 @@ 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.tools.fetch import moe.fuqiuluo.shamrock.tools.fetchOrNull import moe.fuqiuluo.shamrock.tools.fetchOrThrow import moe.fuqiuluo.shamrock.tools.getOrPost @@ -116,6 +117,13 @@ fun Routing.troopAction() { 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") { call.respondText(GetGroupSystemMsg(), ContentType.Application.Json) } diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/service/data/Message.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/service/data/Message.kt index 9003e06..8880583 100644 --- a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/service/data/Message.kt +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/service/data/Message.kt @@ -30,4 +30,17 @@ internal data class MessageSender( @SerialName("sex") val sex: String, @SerialName("age") val age: Int, @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, ) \ No newline at end of file