This commit is contained in:
Him188 2020-03-29 14:28:32 +08:00
parent f223971c4e
commit 2f063987a9
2 changed files with 47 additions and 22 deletions

View File

@ -12,6 +12,8 @@
package net.mamoe.mirai.qqandroid.contact package net.mamoe.mirai.qqandroid.contact
import kotlinx.atomicfu.AtomicInt
import kotlinx.atomicfu.atomic
import kotlinx.io.core.Closeable import kotlinx.io.core.Closeable
import net.mamoe.mirai.LowLevelAPI import net.mamoe.mirai.LowLevelAPI
import net.mamoe.mirai.contact.Contact import net.mamoe.mirai.contact.Contact
@ -37,6 +39,8 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.image.LongConn
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.MessageSvc import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.MessageSvc
import net.mamoe.mirai.utils.* import net.mamoe.mirai.utils.*
import net.mamoe.mirai.utils.io.toUHexString import net.mamoe.mirai.utils.io.toUHexString
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
import kotlin.jvm.JvmSynthetic import kotlin.jvm.JvmSynthetic
@ -47,12 +51,23 @@ internal inline class FriendInfoImpl(
override val uin: Long get() = jceFriendInfo.friendUin override val uin: Long get() = jceFriendInfo.friendUin
} }
@OptIn(ExperimentalContracts::class)
internal fun QQ.checkIsQQImpl(): QQImpl {
contract {
returns() implies (this@checkIsQQImpl is QQImpl)
}
check(this is QQImpl) { "A QQ instance is not instance of QQImpl. Don't interlace two protocol implementations together!" }
return this
}
internal class QQImpl( internal class QQImpl(
bot: QQAndroidBot, bot: QQAndroidBot,
override val coroutineContext: CoroutineContext, override val coroutineContext: CoroutineContext,
override val id: Long, override val id: Long,
private val friendInfo: FriendInfo private val friendInfo: FriendInfo
) : QQ() { ) : QQ() {
var lastMessageSequence: AtomicInt = atomic(-1)
override val bot: QQAndroidBot by bot.unsafeWeakRef() override val bot: QQAndroidBot by bot.unsafeWeakRef()
override val nick: String override val nick: String
get() = friendInfo.nick get() = friendInfo.nick
@ -68,12 +83,12 @@ internal class QQImpl(
bot.network.run { bot.network.run {
check( check(
MessageSvc.PbSendMsg.ToFriend( MessageSvc.PbSendMsg.ToFriend(
bot.client, bot.client,
id, id,
event.message event.message
) { ) {
source = it source = it
} }
.sendAndExpect<MessageSvc.PbSendMsg.Response>() is MessageSvc.PbSendMsg.Response.SUCCESS .sendAndExpect<MessageSvc.PbSendMsg.Response>() is MessageSvc.PbSendMsg.Response.SUCCESS
) { "send message failed" } ) { "send message failed" }
} }

View File

@ -11,6 +11,7 @@
package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive package net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive
import kotlinx.atomicfu.loop
import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.* import kotlinx.coroutines.flow.*
import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.ByteReadPacket
@ -19,16 +20,15 @@ import net.mamoe.mirai.LowLevelAPI
import net.mamoe.mirai.contact.Group import net.mamoe.mirai.contact.Group
import net.mamoe.mirai.contact.MemberPermission import net.mamoe.mirai.contact.MemberPermission
import net.mamoe.mirai.data.MemberInfo import net.mamoe.mirai.data.MemberInfo
import net.mamoe.mirai.qqandroid.network.MultiPacketByIterable
import net.mamoe.mirai.qqandroid.network.Packet
import net.mamoe.mirai.event.events.BotJoinGroupEvent import net.mamoe.mirai.event.events.BotJoinGroupEvent
import net.mamoe.mirai.event.events.BotOfflineEvent import net.mamoe.mirai.event.events.BotOfflineEvent
import net.mamoe.mirai.event.events.MemberJoinEvent import net.mamoe.mirai.event.events.MemberJoinEvent
import net.mamoe.mirai.getFriendOrNull import net.mamoe.mirai.getFriendOrNull
import net.mamoe.mirai.message.FriendMessage import net.mamoe.mirai.message.FriendMessage
import net.mamoe.mirai.message.data.MessageChain import net.mamoe.mirai.message.data.MessageChain
import net.mamoe.mirai.qqandroid.contact.GroupImpl
import net.mamoe.mirai.qqandroid.QQAndroidBot import net.mamoe.mirai.qqandroid.QQAndroidBot
import net.mamoe.mirai.qqandroid.contact.GroupImpl
import net.mamoe.mirai.qqandroid.contact.checkIsQQImpl
import net.mamoe.mirai.qqandroid.io.serialization.decodeUniPacket import net.mamoe.mirai.qqandroid.io.serialization.decodeUniPacket
import net.mamoe.mirai.qqandroid.io.serialization.readProtoBuf import net.mamoe.mirai.qqandroid.io.serialization.readProtoBuf
import net.mamoe.mirai.qqandroid.io.serialization.toByteArray import net.mamoe.mirai.qqandroid.io.serialization.toByteArray
@ -37,6 +37,8 @@ import net.mamoe.mirai.qqandroid.message.MessageSourceFromSendFriend
import net.mamoe.mirai.qqandroid.message.MessageSourceFromSendGroup import net.mamoe.mirai.qqandroid.message.MessageSourceFromSendGroup
import net.mamoe.mirai.qqandroid.message.toMessageChain import net.mamoe.mirai.qqandroid.message.toMessageChain
import net.mamoe.mirai.qqandroid.message.toRichTextElems import net.mamoe.mirai.qqandroid.message.toRichTextElems
import net.mamoe.mirai.qqandroid.network.MultiPacketByIterable
import net.mamoe.mirai.qqandroid.network.Packet
import net.mamoe.mirai.qqandroid.network.QQAndroidClient import net.mamoe.mirai.qqandroid.network.QQAndroidClient
import net.mamoe.mirai.qqandroid.network.protocol.data.jce.RequestPushForceOffline import net.mamoe.mirai.qqandroid.network.protocol.data.jce.RequestPushForceOffline
import net.mamoe.mirai.qqandroid.network.protocol.data.jce.RequestPushNotify import net.mamoe.mirai.qqandroid.network.protocol.data.jce.RequestPushNotify
@ -195,9 +197,8 @@ internal class MessageSvc {
bot.groups.delegate.addLast(newGroup) bot.groups.delegate.addLast(newGroup)
return@mapNotNull BotJoinGroupEvent(newGroup) return@mapNotNull BotJoinGroupEvent(newGroup)
} else { } else {
if (group == null) { group ?: return@mapNotNull null
return@mapNotNull null
}
if (group.members.contains(msg.msgHead.authUin)) { if (group.members.contains(msg.msgHead.authUin)) {
return@mapNotNull null return@mapNotNull null
} }
@ -207,21 +208,30 @@ internal class MessageSvc {
override val specialTitle: String get() = "" override val specialTitle: String get() = ""
override val muteTimestamp: Int get() = 0 override val muteTimestamp: Int get() = 0
override val uin: Long get() = msg.msgHead.authUin override val uin: Long get() = msg.msgHead.authUin
override val nick: String override val nick: String = msg.msgHead.authNick.takeIf { it.isNotEmpty() }
get() = msg.msgHead.authNick.takeIf { it.isNotEmpty() } ?: msg.msgHead.fromNick
?: msg.msgHead.fromNick
}).also { group.members.delegate.addLast(it) }) }).also { group.members.delegate.addLast(it) })
} }
} }
166 -> { 166 -> {
val friend = bot.getFriendOrNull(msg.msgHead.fromUin) ?: return@mapNotNull null val friend = bot.getFriendOrNull(msg.msgHead.fromUin) ?: return@mapNotNull null
return@mapNotNull when { friend.checkIsQQImpl()
msg.msgHead.fromUin == bot.uin -> null
!bot.firstLoginSucceed -> null if (msg.msgHead.fromUin == bot.uin || !bot.firstLoginSucceed) {
else -> FriendMessage( return@mapNotNull null
friend, }
msg.toMessageChain()
) friend.lastMessageSequence.loop { instant ->
if (msg.msgHead.msgSeq > instant) {
println("bigger")
if (friend.lastMessageSequence.compareAndSet(instant, msg.msgHead.msgSeq)) {
println("set ok")
return@mapNotNull FriendMessage(
friend,
msg.toMessageChain()
)
}
} else return@mapNotNull null
} }
} }
else -> return@mapNotNull null else -> return@mapNotNull null