Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
Him188 2021-01-11 17:39:28 +08:00
commit 1d4867d9b6
5 changed files with 114 additions and 10 deletions

View File

@ -111,6 +111,7 @@ public enum class Platform(
public enum class ClientKind(
@MiraiInternalApi public val id: Int,
) {
ANDROID_PAD(68104),
AOL_CHAOJIHUIYUAN(73730),
AOL_HUIYUAN(73474),
@ -128,7 +129,8 @@ public enum class ClientKind(
MOBILE_IPAD_NEW(72194),
MOBILE_IPHONE(67586),
MOBILE_OTHER(65794),
MOBILE_PC(65793),
MOBILE_PC_QQ(65793),
MOBILE_PC_TIM(77313),
MOBILE_WINPHONE_NEW(72706),
QQ_FORELDER(70922),
QQ_SERVICE(71170),

View File

@ -0,0 +1,30 @@
/*
* Copyright 2020-2021 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
package net.mamoe.mirai.internal.network.protocol.data.jce
import kotlinx.serialization.Serializable
import net.mamoe.mirai.internal.utils.io.JceStruct
import net.mamoe.mirai.internal.utils.io.serialization.tars.TarsId
@Serializable
internal class RequestPushStatus(
@JvmField @TarsId(0) val uin: Long,
@JvmField @TarsId(1) val status: Byte,
@JvmField @TarsId(2) val dataLine: Byte? = null,
@JvmField @TarsId(3) val printable: Byte? = null,
@JvmField @TarsId(4) val viewFile: Byte? = null,
@JvmField @TarsId(5) val nPCVer: Long? = null,
@JvmField @TarsId(6) val nClientType: Long? = null,
@JvmField @TarsId(7) val nInstanceId: Long? = null,
@JvmField @TarsId(8) val vecInstanceList: List<InstanceInfo>? = null
) : JceStruct

View File

@ -161,6 +161,7 @@ internal object KnownPacketFactories {
OnlinePushPbPushTransMsg,
MessageSvcPushNotify,
MessageSvcPushReaded,
MessageSvcRequestPushStatus,
ConfigPushSvc.PushReq,
StatSvc.ReqMSFOffline,
StatSvc.SvcReqMSFLoginNotify

View File

@ -0,0 +1,60 @@
package net.mamoe.mirai.internal.network.protocol.packet.chat.receive
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.cancel
import kotlinx.coroutines.sync.withLock
import kotlinx.io.core.ByteReadPacket
import net.mamoe.mirai.Mirai
import net.mamoe.mirai.contact.ClientKind
import net.mamoe.mirai.event.events.OtherClientOfflineEvent
import net.mamoe.mirai.event.events.OtherClientOnlineEvent
import net.mamoe.mirai.internal.QQAndroidBot
import net.mamoe.mirai.internal.contact.appId
import net.mamoe.mirai.internal.createOtherClient
import net.mamoe.mirai.internal.message.contextualBugReportException
import net.mamoe.mirai.internal.network.Packet
import net.mamoe.mirai.internal.network.protocol.data.jce.RequestPushStatus
import net.mamoe.mirai.internal.network.protocol.packet.IncomingPacketFactory
import net.mamoe.mirai.internal.utils._miraiContentToString
import net.mamoe.mirai.internal.utils.io.serialization.readUniPacket
internal object MessageSvcRequestPushStatus : IncomingPacketFactory<Packet?>(
"MessageSvc.RequestPushStatus", ""
) {
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot, sequenceId: Int): Packet? {
val packet = readUniPacket(RequestPushStatus.serializer())
bot.otherClientsLock.withLock {
val appId = packet.vecInstanceList?.firstOrNull()?.iAppId ?: 1
return when (packet.status.toInt()) {
1 -> { // online
if (bot.otherClients.any { appId == it.appId }) return null
val info = Mirai.getOnlineOtherClientsList(bot).firstOrNull { appId == it.appId }
?: throw contextualBugReportException(
"SvcRequestPushStatus (OtherClient online)",
packet._miraiContentToString(),
additional = "Failed to find corresponding instanceInfo."
)
val client = bot.createOtherClient(info)
bot.otherClients.delegate.add(client)
OtherClientOnlineEvent(
client,
ClientKind[packet.nClientType?.toInt() ?: 0]
)
}
2 -> { // off
val client = bot.otherClients.find { it.appId == appId } ?: return null
client.cancel(CancellationException("Offline"))
bot.otherClients.delegate.remove(client)
OtherClientOfflineEvent(client)
}
else -> throw contextualBugReportException(
"decode SvcRequestPushStatus (PC Client status change)",
packet._miraiContentToString(),
additional = "unknown status=${packet.status}"
)
}
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2019-2020 Mamoe Technologies and contributors.
* Copyright 2019-2021 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
@ -10,6 +10,7 @@
package net.mamoe.mirai.internal.utils
import kotlinx.atomicfu.locks.withLock
import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm
import net.mamoe.mirai.internal.network.protocol.data.proto.MsgOnlinePush
import net.mamoe.mirai.utils.currentTimeMillis
import java.util.concurrent.locks.ReentrantLock
@ -17,16 +18,16 @@ import java.util.concurrent.locks.ReentrantLock
/**
* fragmented message
*/
internal class GroupPkgMsgParsingCache {
class PkgMsg(
internal abstract class FragmentedMsgParsingCache<T> {
class PkgMsg<T>(
val size: Int,
val divSeq: Int,
val data: MutableMap<Int, MsgOnlinePush.PbPushMsg>,
val data: MutableMap<Int, T>,
) {
val createTime = currentTimeMillis()
}
private val deque = ArrayList<PkgMsg>(16)
private val deque = ArrayList<PkgMsg<T>>(16)
private val accessLock = ReentrantLock()
private fun clearInvalid() {
deque.removeIf {
@ -34,8 +35,10 @@ internal class GroupPkgMsgParsingCache {
}
}
fun tryMerge(msg: MsgOnlinePush.PbPushMsg): List<MsgOnlinePush.PbPushMsg> {
val head = msg.msg.contentHead ?: return listOf(msg)
internal abstract val T.contentHead: MsgComm.ContentHead?
fun tryMerge(msg: T): List<T> {
val head = msg.contentHead ?: return listOf(msg)
val size = head.pkgNum
if (size < 2) return listOf(msg)
accessLock.withLock {
@ -44,7 +47,7 @@ internal class GroupPkgMsgParsingCache {
val index = head.pkgIndex
val pkgMsg = deque.find {
it.divSeq == seq
} ?: PkgMsg(size, seq, mutableMapOf()).also { deque.add(it) }
} ?: PkgMsg<T>(size, seq, mutableMapOf()).also { deque.add(it) }
pkgMsg.data[index] = msg
if (pkgMsg.data.size == pkgMsg.size) {
deque.removeIf { it.divSeq == seq }
@ -56,4 +59,12 @@ internal class GroupPkgMsgParsingCache {
return emptyList()
}
}
}
}
/**
* fragmented message
*/
internal class GroupPkgMsgParsingCache : FragmentedMsgParsingCache<MsgOnlinePush.PbPushMsg>() {
override val MsgOnlinePush.PbPushMsg.contentHead: MsgComm.ContentHead?
get() = this.msg.contentHead
}