Shamrock: 支持获取QQ收藏的列表 /fav/get_item_list

This commit is contained in:
WhiteChi 2023-12-23 04:47:11 +08:00
parent 1490450178
commit 77504d68fd
6 changed files with 154 additions and 2 deletions

View File

@ -51,6 +51,34 @@ internal object QFavSvc: BaseSvc() {
private const val MINOR_VERSION = 9 private const val MINOR_VERSION = 9
private var seq = 1 private var seq = 1
suspend fun getItemList(
category: Int,
startPos: Int,
pageSize: Int,
): Result<NetResp> {
val data = protobufMapOf {
it[1] = mapOf(
20000 to mapOf(
/**
* "type", "bid", "category", "start_time", "order_type", "start_pos", "page_size", "sync_policy", "req_source"
*/
1 to 0,
2 to 0,
3 to category,
//4 to System.currentTimeMillis() - 1000 * 60,
//4 to System.currentTimeMillis(),
4 to 0,
5 to 0,
6 to startPos,
7 to pageSize,
8 to 0,
9 to 0
)
)
}.toByteArray()
return sendWeiyunReq(20000, data)
}
suspend fun getItemContent( suspend fun getItemContent(
id: String id: String
): Result<NetResp> { ): Result<NetResp> {

View File

@ -52,7 +52,7 @@ internal object ActionManager {
GetWeatherCityCode, GetWeather, GetWeatherCityCode, GetWeather,
// FAV // FAV
FavAddTextMsg, FavAddImageMsg, FavGetItemContent, FavAddTextMsg, FavAddImageMsg, FavGetItemContent, FavGetItemList,
// OTHER // OTHER
GetDeviceBattery, DownloadFile GetDeviceBattery, DownloadFile

View File

@ -48,6 +48,8 @@ internal object FavGetItemContent: IActionHandler() {
override fun path(): String = "fav.get_item_content" override fun path(): String = "fav.get_item_content"
override val requiredParams: Array<String> = arrayOf("id")
@Serializable @Serializable
private data class ItemContent( private data class ItemContent(
@SerialName("content") val content: String @SerialName("content") val content: String

View File

@ -0,0 +1,113 @@
package moe.fuqiuluo.shamrock.remote.action.handlers
import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.discardExact
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonElement
import moe.fuqiuluo.proto.ProtoUtils
import moe.fuqiuluo.proto.asInt
import moe.fuqiuluo.proto.asList
import moe.fuqiuluo.proto.asLong
import moe.fuqiuluo.proto.asMap
import moe.fuqiuluo.proto.asULong
import moe.fuqiuluo.proto.asUtf8String
import moe.fuqiuluo.qqinterface.servlet.QFavSvc
import moe.fuqiuluo.shamrock.remote.action.ActionSession
import moe.fuqiuluo.shamrock.remote.action.IActionHandler
import moe.fuqiuluo.shamrock.tools.EmptyJsonString
import moe.fuqiuluo.shamrock.tools.toHexString
import moe.fuqiuluo.shamrock.utils.DeflateTools
internal object FavGetItemList: IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
val category = session.getInt("category")
val startPos = session.getInt("start_pos")
val pageSize = session.getInt("page_size")
return invoke(category, startPos, pageSize, session.echo)
}
suspend operator fun invoke(
category: Int,
startPos: Int,
pageSize: Int,
echo: JsonElement = EmptyJsonString
): String {
val result = DeflateTools.ungzip(QFavSvc.getItemList(
category = category,
startPos = startPos,
pageSize = pageSize
).onSuccess {
if (it.mHttpCode != 200 || it.mResult != 0) {
return logic("fav.get_item_list failed", echo)
}
}.getOrThrow().mRespData)
val readPacket = ByteReadPacket(result)
readPacket.discardExact(6)
val allLength = readPacket.readInt()
val dataLength = readPacket.readInt()
val headLength = allLength - dataLength - 16
readPacket.discardExact(2)
ByteArray(headLength).also {
readPacket.readFully(it, 0, it.size)
}
val data = ByteArray(dataLength).also {
readPacket.readFully(it, 0, it.size)
}
val pb = ProtoUtils.decodeFromByteArray(data)
val itemList = arrayListOf<Item>()
val rawItemList = pb[2, 20000, 1].asList
rawItemList.value.forEach {
val item = it.asMap
val itemId = item[1].asUtf8String
val authorType = item[4, 1].asInt
val author = item[4, 2].asULong
val authorName = item[4, 3].asUtf8String
val groupName: String
val groupId: Long
if (authorType == 2) {
groupName = item[4, 5].asUtf8String
groupId = item[4, 4].asULong
} else {
groupName = ""
groupId = 0L
}
val clientVersion = item[7].asUtf8String
val time = item[9].asLong
itemList.add(Item(
id = itemId,
authorType = authorType,
author = author,
authorName = authorName,
groupName = groupName,
groupId = groupId,
clientVersion = clientVersion,
time = time
))
}
return ok(ItemList(itemList), echo)
}
override val requiredParams: Array<String> = arrayOf("category", "start_pos", "page_size")
override fun path(): String = "fav.get_item_list"
@Serializable
private data class ItemList(
val items: List<Item>
)
@Serializable
private data class Item(
@SerialName("id") val id: String,
@SerialName("author_type") val authorType: Int,
@SerialName("author") val author: Long,
@SerialName("author_name") val authorName: String,
@SerialName("group_name") val groupName: String,
@SerialName("group_id") val groupId: Long,
@SerialName("client_version") val clientVersion: String,
@SerialName("time") val time: Long
)
}

View File

@ -7,6 +7,7 @@ import io.ktor.server.routing.Routing
import moe.fuqiuluo.shamrock.remote.action.handlers.FavAddImageMsg import moe.fuqiuluo.shamrock.remote.action.handlers.FavAddImageMsg
import moe.fuqiuluo.shamrock.remote.action.handlers.FavAddTextMsg import moe.fuqiuluo.shamrock.remote.action.handlers.FavAddTextMsg
import moe.fuqiuluo.shamrock.remote.action.handlers.FavGetItemContent import moe.fuqiuluo.shamrock.remote.action.handlers.FavGetItemContent
import moe.fuqiuluo.shamrock.remote.action.handlers.FavGetItemList
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
@ -37,4 +38,11 @@ fun Routing.fav() {
val id = call.fetchOrThrow("id") val id = call.fetchOrThrow("id")
call.respondText(FavGetItemContent(id), ContentType.Application.Json) call.respondText(FavGetItemContent(id), ContentType.Application.Json)
} }
getOrPost("/fav/get_item_list") {
val category = call.fetchOrThrow("category").toInt()
val startPos = call.fetchOrThrow("start_pos").toInt()
val pageSize = call.fetchOrThrow("page_size").toInt()
call.respondText(FavGetItemList(category, startPos, pageSize), ContentType.Application.Json)
}
} }

View File

@ -16,6 +16,7 @@ import mqq.app.MobileQQ
internal class HookForDebug: IAction { internal class HookForDebug: IAction {
override fun invoke(ctx: Context) { override fun invoke(ctx: Context) {
/*
val httpEngineService = AppRuntimeFetcher.appRuntime val httpEngineService = AppRuntimeFetcher.appRuntime
.getRuntimeService(IHttpEngineService::class.java, "all") .getRuntimeService(IHttpEngineService::class.java, "all")
httpEngineService.javaClass.hookMethod("sendReq").before { httpEngineService.javaClass.hookMethod("sendReq").before {
@ -28,7 +29,7 @@ internal class HookForDebug: IAction {
LogCenter.log("请求地址: ${req.mReqUrl}") LogCenter.log("请求地址: ${req.mReqUrl}")
LogCenter.log("请求: ${req.toInnerValuesString(NetReq::class.java)}") LogCenter.log("请求: ${req.toInnerValuesString(NetReq::class.java)}")
} }
} }*/
} }
} }