mirror of
https://github.com/mamoe/mirai.git
synced 2025-02-08 03:44:44 +08:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
009f11ea0b
@ -10,6 +10,7 @@ import net.mamoe.mirai.message.data.Image
|
||||
import net.mamoe.mirai.message.data.MessageChain
|
||||
import net.mamoe.mirai.message.data.NotOnlineImageFromFile
|
||||
import net.mamoe.mirai.qqandroid.network.highway.HighwayHelper
|
||||
import net.mamoe.mirai.qqandroid.network.highway.postImage
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.Cmd0x352
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.TroopManagement
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.image.ImgStore
|
||||
@ -50,7 +51,6 @@ internal class QQImpl(bot: QQAndroidBot, override val coroutineContext: Coroutin
|
||||
) { "send message failed" }
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun uploadImage(image: ExternalImage): Image = try {
|
||||
bot.network.run {
|
||||
val response = LongConn.OffPicUp(
|
||||
@ -78,16 +78,17 @@ internal class QQImpl(bot: QQAndroidBot, override val coroutineContext: Coroutin
|
||||
resourceId = response.resourceId
|
||||
)
|
||||
is LongConn.OffPicUp.Response.RequireUpload -> {
|
||||
HighwayHelper.uploadImage(
|
||||
client = bot.client,
|
||||
serverIp = response.serverIp[0].toIpV4AddressString(),
|
||||
serverPort = response.serverPort[0],
|
||||
imageInput = image.input,
|
||||
inputSize = image.inputSize.toInt(),
|
||||
md5 = image.md5,
|
||||
uKey = response.uKey,
|
||||
commandId = 1
|
||||
)
|
||||
Http.postImage("0x6ff0070", bot.uin, null, imageInput = image.input, inputSize = image.inputSize, uKeyHex = response.uKey.toUHexString(""))
|
||||
// HighwayHelper.uploadImage(
|
||||
// client = bot.client,
|
||||
// serverIp = response.serverIp[0].toIpV4AddressString(),
|
||||
// serverPort = response.serverPort[0],
|
||||
// imageInput = image.input,
|
||||
// inputSize = image.inputSize.toInt(),
|
||||
// md5 = image.md5,
|
||||
// uKey = response.uKey,
|
||||
// commandId = 1
|
||||
// )
|
||||
|
||||
return NotOnlineImageFromFile(
|
||||
filepath = response.resourceId,
|
||||
|
@ -1,66 +1,9 @@
|
||||
package net.mamoe.mirai.qqandroid.network.highway
|
||||
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.request.post
|
||||
import io.ktor.http.ContentType
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.http.URLProtocol
|
||||
import io.ktor.http.content.OutgoingContent
|
||||
import io.ktor.http.userAgent
|
||||
import kotlinx.coroutines.io.ByteWriteChannel
|
||||
import kotlinx.io.core.*
|
||||
import kotlinx.io.pool.useInstance
|
||||
import net.mamoe.mirai.qqandroid.io.serialization.toByteArray
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.CSDataHighwayHead
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
|
||||
import net.mamoe.mirai.utils.io.ByteArrayPool
|
||||
|
||||
@Suppress("SpellCheckingInspection")
|
||||
internal suspend inline fun HttpClient.postImage(
|
||||
htcmd: String,
|
||||
uin: Long,
|
||||
groupcode: Long?,
|
||||
imageInput: Input,
|
||||
inputSize: Long,
|
||||
uKeyHex: String
|
||||
): Boolean = try {
|
||||
post<HttpStatusCode> {
|
||||
url {
|
||||
protocol = URLProtocol.HTTP
|
||||
host = "htdata2.qq.com"
|
||||
path("cgi-bin/httpconn")
|
||||
|
||||
parameters["htcmd"] = htcmd
|
||||
parameters["uin"] = uin.toString()
|
||||
|
||||
if (groupcode != null) parameters["groupcode"] = groupcode.toString()
|
||||
|
||||
parameters["term"] = "pc"
|
||||
parameters["ver"] = "5603"
|
||||
parameters["filesize"] = inputSize.toString()
|
||||
parameters["range"] = 0.toString()
|
||||
parameters["ukey"] = uKeyHex
|
||||
|
||||
userAgent("QQClient")
|
||||
}
|
||||
|
||||
body = object : OutgoingContent.WriteChannelContent() {
|
||||
override val contentType: ContentType = ContentType.Image.Any
|
||||
override val contentLength: Long = inputSize
|
||||
|
||||
override suspend fun writeTo(channel: ByteWriteChannel) {
|
||||
ByteArrayPool.useInstance { buffer: ByteArray ->
|
||||
var size: Int
|
||||
while (imageInput.readAvailable(buffer).also { size = it } != 0) {
|
||||
channel.writeFully(buffer, 0, size)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} == HttpStatusCode.OK
|
||||
} finally {
|
||||
imageInput.close()
|
||||
}
|
||||
|
||||
object Highway {
|
||||
fun RequestDataTrans(
|
||||
|
@ -1,18 +1,76 @@
|
||||
package net.mamoe.mirai.qqandroid.network.highway
|
||||
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.request.post
|
||||
import io.ktor.http.ContentType
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.http.URLProtocol
|
||||
import io.ktor.http.content.OutgoingContent
|
||||
import io.ktor.http.userAgent
|
||||
import kotlinx.coroutines.io.ByteWriteChannel
|
||||
import kotlinx.io.core.Input
|
||||
import kotlinx.io.core.readAvailable
|
||||
import kotlinx.io.core.use
|
||||
import kotlinx.io.pool.useInstance
|
||||
import net.mamoe.mirai.qqandroid.io.serialization.readProtoBuf
|
||||
import net.mamoe.mirai.qqandroid.network.QQAndroidClient
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.CSDataHighwayHead
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.withUse
|
||||
import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||
import net.mamoe.mirai.utils.io.ByteArrayPool
|
||||
import net.mamoe.mirai.utils.io.PlatformSocket
|
||||
import net.mamoe.mirai.utils.io.discardExact
|
||||
|
||||
|
||||
@Suppress("SpellCheckingInspection")
|
||||
internal suspend inline fun HttpClient.postImage(
|
||||
htcmd: String,
|
||||
uin: Long,
|
||||
groupcode: Long?,
|
||||
imageInput: Input,
|
||||
inputSize: Long,
|
||||
uKeyHex: String
|
||||
): Boolean = try {
|
||||
post<HttpStatusCode> {
|
||||
url {
|
||||
protocol = URLProtocol.HTTP
|
||||
host = "htdata2.qq.com"
|
||||
path("cgi-bin/httpconn")
|
||||
|
||||
parameters["htcmd"] = htcmd
|
||||
parameters["uin"] = uin.toString()
|
||||
|
||||
if (groupcode != null) parameters["groupcode"] = groupcode.toString()
|
||||
|
||||
parameters["term"] = "pc"
|
||||
parameters["ver"] = "5603"
|
||||
parameters["filesize"] = inputSize.toString()
|
||||
parameters["range"] = 0.toString()
|
||||
parameters["ukey"] = uKeyHex
|
||||
|
||||
userAgent("QQClient")
|
||||
}
|
||||
|
||||
body = object : OutgoingContent.WriteChannelContent() {
|
||||
override val contentType: ContentType = ContentType.Image.Any
|
||||
override val contentLength: Long = inputSize
|
||||
|
||||
override suspend fun writeTo(channel: ByteWriteChannel) {
|
||||
ByteArrayPool.useInstance { buffer: ByteArray ->
|
||||
var size: Int
|
||||
while (imageInput.readAvailable(buffer).also { size = it } != 0) {
|
||||
channel.writeFully(buffer, 0, size)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} == HttpStatusCode.OK
|
||||
} finally {
|
||||
imageInput.close()
|
||||
}
|
||||
|
||||
@UseExperimental(MiraiInternalAPI::class)
|
||||
internal object HighwayHelper {
|
||||
|
||||
suspend fun uploadImage(
|
||||
client: QQAndroidClient,
|
||||
serverIp: String,
|
||||
|
@ -0,0 +1,87 @@
|
||||
package net.mamoe.mirai.qqandroid.network.protocol.data.jce
|
||||
|
||||
import kotlinx.serialization.SerialId
|
||||
import kotlinx.serialization.Serializable
|
||||
import net.mamoe.mirai.qqandroid.io.JceStruct
|
||||
|
||||
class OnlinePushPack {
|
||||
@Serializable
|
||||
internal class DelMsgInfo(
|
||||
@SerialId(0) val fromUin: Long,
|
||||
@SerialId(1) val uMsgTime: Long,
|
||||
@SerialId(2) val shMsgSeq: Short,
|
||||
@SerialId(3) val vMsgCookies: ByteArray? = null,
|
||||
@SerialId(4) val wCmd: Short? = null,
|
||||
@SerialId(5) val uMsgType: Long? = null,
|
||||
@SerialId(6) val uAppId: Long? = null,
|
||||
@SerialId(7) val sendTime: Long? = null,
|
||||
@SerialId(8) val ssoSeq: Int? = null,
|
||||
@SerialId(9) val ssoIp: Int? = null,
|
||||
@SerialId(10) val clientIp: Int? = null
|
||||
) : JceStruct
|
||||
|
||||
@Serializable
|
||||
internal class DeviceInfo(
|
||||
@SerialId(0) val netType: Byte? = null,
|
||||
@SerialId(1) val devType: String? = "",
|
||||
@SerialId(2) val oSVer: String? = "",
|
||||
@SerialId(3) val vendorName: String? = "",
|
||||
@SerialId(4) val vendorOSName: String? = "",
|
||||
@SerialId(5) val iOSIdfa: String? = ""
|
||||
) : JceStruct
|
||||
|
||||
@Serializable
|
||||
internal class Name(
|
||||
@SerialId(0) val fromUin: Long,
|
||||
@SerialId(1) val uMsgTime: Long,
|
||||
@SerialId(2) val shMsgType: Short,
|
||||
@SerialId(3) val shMsgSeq: Short,
|
||||
@SerialId(4) val msg: String = "",
|
||||
@SerialId(5) val uRealMsgTime: Int? = null,
|
||||
@SerialId(6) val vMsg: ByteArray? = null,
|
||||
@SerialId(7) val uAppShareID: Long? = null,
|
||||
@SerialId(8) val vMsgCookies: ByteArray? = null,
|
||||
@SerialId(9) val vAppShareCookie: ByteArray? = null,
|
||||
@SerialId(10) val msgUid: Long? = null,
|
||||
@SerialId(11) val lastChangeTime: Long? = 1L,
|
||||
@SerialId(12) val vCPicInfo: List<CPicInfo>? = null,
|
||||
@SerialId(13) val stShareData: ShareData? = null,
|
||||
@SerialId(14) val fromInstId: Long? = null,
|
||||
@SerialId(15) val vRemarkOfSender: ByteArray? = null,
|
||||
@SerialId(16) val fromMobile: String? = "",
|
||||
@SerialId(17) val fromName: String? = "",
|
||||
@SerialId(18) val vNickName: List<String>? = null,
|
||||
@SerialId(19) val stC2CTmpMsgHead: TempMsgHead? = null
|
||||
) : JceStruct
|
||||
|
||||
@Serializable
|
||||
internal class SvcReqPushMsg(
|
||||
@SerialId(0) val uin: Long,
|
||||
@SerialId(1) val uMsgTime: Long,
|
||||
@SerialId(2) val vMsgInfos: List<MsgInfo>,
|
||||
@SerialId(3) val svrip: Int? = 0,
|
||||
@SerialId(4) val vSyncCookie: ByteArray? = null,
|
||||
@SerialId(5) val vUinPairMsg: List<UinPairMsg>? = null,
|
||||
@SerialId(6) val mPreviews: Map<String, ByteArray>? = null,
|
||||
@SerialId(7) val wUserActive: Int? = null,
|
||||
@SerialId(12) val wGeneralFlag: Int? = null
|
||||
) : JceStruct
|
||||
|
||||
@Serializable
|
||||
internal class SvcRespPushMsg(
|
||||
@SerialId(0) val uin: Long,
|
||||
@SerialId(1) val vDelInfos: List<DelMsgInfo>,
|
||||
@SerialId(2) val svrip: Int,
|
||||
@SerialId(3) val pushToken: ByteArray? = null,
|
||||
@SerialId(4) val serviceType: Int? = null,
|
||||
@SerialId(5) val deviceInfo: DeviceInfo? = null
|
||||
) : JceStruct
|
||||
|
||||
@Serializable
|
||||
internal class UinPairMsg(
|
||||
@SerialId(1) val uLastReadTime: Long? = null,
|
||||
@SerialId(2) val peerUin: Long? = null,
|
||||
@SerialId(3) val uMsgCompleted: Long? = null,
|
||||
@SerialId(4) val vMsgInfos: List<MsgInfo>? = null
|
||||
) : JceStruct
|
||||
}
|
@ -4,16 +4,21 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive
|
||||
|
||||
import kotlinx.io.core.ByteReadPacket
|
||||
import net.mamoe.mirai.contact.MemberPermission
|
||||
import net.mamoe.mirai.data.NoPakcet
|
||||
import net.mamoe.mirai.data.Packet
|
||||
import net.mamoe.mirai.event.broadcast
|
||||
import net.mamoe.mirai.message.GroupMessage
|
||||
import net.mamoe.mirai.qqandroid.QQAndroidBot
|
||||
import net.mamoe.mirai.qqandroid.io.serialization.decodeUniPacket
|
||||
import net.mamoe.mirai.qqandroid.io.serialization.readProtoBuf
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.data.jce.MsgInfo
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.data.jce.OnlinePushPack
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.ImMsgBody
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.MsgOnlinePush
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.IncomingPacketFactory
|
||||
import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket
|
||||
import net.mamoe.mirai.qqandroid.utils.toMessageChain
|
||||
import net.mamoe.mirai.utils.cryptor.contentToString
|
||||
|
||||
internal inline class GroupMessageOrNull(val delegate: GroupMessage?) : Packet {
|
||||
override fun toString(): String {
|
||||
@ -70,4 +75,21 @@ internal class OnlinePush {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
internal object ReqPush : IncomingPacketFactory<Packet>("OnlinePush.ReqPush") {
|
||||
@UseExperimental(ExperimentalStdlibApi::class)
|
||||
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot, sequenceId: Int): Packet {
|
||||
val reqPushMsg = decodeUniPacket(OnlinePushPack.SvcReqPushMsg.serializer(), "req")
|
||||
reqPushMsg.vMsgInfos.forEach { msgInfo: MsgInfo ->
|
||||
|
||||
}
|
||||
println(reqPushMsg.contentToString())
|
||||
return NoPakcet
|
||||
}
|
||||
|
||||
|
||||
override suspend fun QQAndroidBot.handle(packet: Packet, sequenceId: Int): OutgoingPacket? {
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user