Adapt for server time difference, let MessageSource.time refer to server time. Fixes 1519

This commit is contained in:
Him188 2021-09-04 21:30:20 +08:00
parent 5188d88483
commit 238ec52eea
7 changed files with 75 additions and 13 deletions

View File

@ -149,7 +149,8 @@ public sealed class MessageSource : Message, MessageMetadata, ConstrainSingle {
/** /**
* 发送时间时间戳, 单位为秒. * 发送时间时间戳, 单位为秒.
* *
* 时间戳可能来自服务器, 也可能来自 mirai, 且无法保证两者时间同步. * 2.8.0 , 时间戳为服务器时区 (UTC+8).
* 2.8.0 以前, 时间戳可能来自服务器 (UTC+8), 也可能来自 mirai (本地), 且无法保证两者时间同步.
*/ */
public abstract val time: Int public abstract val time: Int

View File

@ -0,0 +1,30 @@
/*
* 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.
*
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
package net.mamoe.mirai.utils
public interface Clock {
public fun currentTimeMillis(): Long
public fun currentTimeSeconds(): Long
public object SystemDefault : Clock {
override fun currentTimeMillis(): Long = net.mamoe.mirai.utils.currentTimeMillis()
override fun currentTimeSeconds(): Long = net.mamoe.mirai.utils.currentTimeSeconds()
}
}
public fun Clock.adjusted(diffMillis: Long): Clock = AdjustedClock(this, diffMillis)
public class AdjustedClock(
private val clock: Clock,
private val diffMillis: Long,
) : Clock {
override fun currentTimeMillis(): Long = clock.currentTimeMillis() + diffMillis
override fun currentTimeSeconds(): Long = (clock.currentTimeMillis() + diffMillis) / 1000
}

View File

@ -232,6 +232,7 @@ internal open class QQAndroidBot constructor(
return ConcurrentComponentStorage { return ConcurrentComponentStorage {
set(BotClientHolder, BotClientHolderImpl(bot, networkLogger.subLogger("BotClientHolder"))) set(BotClientHolder, BotClientHolderImpl(bot, networkLogger.subLogger("BotClientHolder")))
set(SyncController, SyncControllerImpl()) set(SyncController, SyncControllerImpl())
set(ClockHolder, ClockHolder())
}.withFallback(defaultBotLevelComponents) }.withFallback(defaultBotLevelComponents)
} }

View File

@ -19,6 +19,7 @@ import net.mamoe.mirai.internal.getMiraiImpl
import net.mamoe.mirai.internal.message.* import net.mamoe.mirai.internal.message.*
import net.mamoe.mirai.internal.network.Packet import net.mamoe.mirai.internal.network.Packet
import net.mamoe.mirai.internal.network.QQAndroidClient import net.mamoe.mirai.internal.network.QQAndroidClient
import net.mamoe.mirai.internal.network.components.ClockHolder.Companion.clock
import net.mamoe.mirai.internal.network.components.MessageSvcSyncer import net.mamoe.mirai.internal.network.components.MessageSvcSyncer
import net.mamoe.mirai.internal.network.handler.logger import net.mamoe.mirai.internal.network.handler.logger
import net.mamoe.mirai.internal.network.notice.group.GroupMessageProcessor.SendGroupMessageReceipt import net.mamoe.mirai.internal.network.notice.group.GroupMessageProcessor.SendGroupMessageReceipt
@ -399,7 +400,7 @@ internal open class GroupSendMessageHandler(
providedSequenceIds = intArrayOf(receipt.sequenceId), providedSequenceIds = intArrayOf(receipt.sequenceId),
sender = bot, sender = bot,
target = contact, target = contact,
time = currentTimeSeconds().toInt(), time = bot.clock.server.currentTimeSeconds().toInt(),
originalMessage = finalMessage originalMessage = finalMessage
) )
} }

View File

@ -0,0 +1,23 @@
/*
* 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.
*
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
package net.mamoe.mirai.internal.network.components
import net.mamoe.mirai.internal.QQAndroidBot
import net.mamoe.mirai.internal.network.component.ComponentKey
import net.mamoe.mirai.utils.Clock
internal class ClockHolder {
val local: Clock get() = Clock.SystemDefault
var server: Clock = local
companion object : ComponentKey<ClockHolder> {
val QQAndroidBot.clock get() = components[ClockHolder]
}
}

View File

@ -23,6 +23,7 @@ import net.mamoe.mirai.internal.contact.uin
import net.mamoe.mirai.internal.message.* import net.mamoe.mirai.internal.message.*
import net.mamoe.mirai.internal.network.Packet import net.mamoe.mirai.internal.network.Packet
import net.mamoe.mirai.internal.network.QQAndroidClient import net.mamoe.mirai.internal.network.QQAndroidClient
import net.mamoe.mirai.internal.network.components.ClockHolder.Companion.clock
import net.mamoe.mirai.internal.network.components.SyncController.Companion.syncController import net.mamoe.mirai.internal.network.components.SyncController.Companion.syncController
import net.mamoe.mirai.internal.network.components.SyncController.Companion.syncCookie import net.mamoe.mirai.internal.network.components.SyncController.Companion.syncCookie
import net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody import net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody
@ -35,7 +36,6 @@ import net.mamoe.mirai.internal.network.protocol.packet.buildOutgoingUniPacket
import net.mamoe.mirai.internal.utils.io.serialization.readProtoBuf import net.mamoe.mirai.internal.utils.io.serialization.readProtoBuf
import net.mamoe.mirai.internal.utils.io.serialization.writeProtoBuf import net.mamoe.mirai.internal.utils.io.serialization.writeProtoBuf
import net.mamoe.mirai.message.data.* import net.mamoe.mirai.message.data.*
import net.mamoe.mirai.utils.currentTimeSeconds
import net.mamoe.mirai.utils.getRandomUnsignedInt import net.mamoe.mirai.utils.getRandomUnsignedInt
import java.util.concurrent.atomic.AtomicReference import java.util.concurrent.atomic.AtomicReference
import kotlin.contracts.InvocationKind import kotlin.contracts.InvocationKind
@ -215,7 +215,7 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg.
internalIds = randIds.get(), internalIds = randIds.get(),
sender = client.bot, sender = client.bot,
target = target, target = target,
time = currentTimeSeconds().toInt(), time = client.bot.clock.server.currentTimeSeconds().toInt(),
sequenceIds = sequenceIds.get(), sequenceIds = sequenceIds.get(),
originalMessage = message, originalMessage = message,
), ),
@ -275,7 +275,7 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg.
internalIds = randIds.get(), internalIds = randIds.get(),
sender = client.bot, sender = client.bot,
target = targetFriend, target = targetFriend,
time = currentTimeSeconds().toInt(), time = client.bot.clock.server.currentTimeSeconds().toInt(),
sequenceIds = sequenceIds.get(), sequenceIds = sequenceIds.get(),
originalMessage = message, originalMessage = message,
), ),
@ -400,7 +400,7 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg.
internalIds = randIds.get(), internalIds = randIds.get(),
sender = client.bot, sender = client.bot,
target = targetGroup, target = targetGroup,
time = currentTimeSeconds().toInt(), time = client.bot.clock.server.currentTimeSeconds().toInt(),
originalMessage = message, //, originalMessage = message, //,
// sourceMessage = message // sourceMessage = message
), ),
@ -488,7 +488,7 @@ internal inline fun MessageSvcPbSendMsg.createToTemp(
internalIds = intArrayOf(Random.nextInt().absoluteValue), internalIds = intArrayOf(Random.nextInt().absoluteValue),
sender = client.bot, sender = client.bot,
target = member, target = member,
time = currentTimeSeconds().toInt(), time = client.bot.clock.server.currentTimeSeconds().toInt(),
sequenceIds = intArrayOf(client.atomicNextMessageSequenceId()), sequenceIds = intArrayOf(client.atomicNextMessageSequenceId()),
originalMessage = message, originalMessage = message,
) )

View File

@ -27,9 +27,12 @@ import net.mamoe.mirai.internal.contact.appId
import net.mamoe.mirai.internal.contact.createOtherClient import net.mamoe.mirai.internal.contact.createOtherClient
import net.mamoe.mirai.internal.message.contextualBugReportException import net.mamoe.mirai.internal.message.contextualBugReportException
import net.mamoe.mirai.internal.network.* import net.mamoe.mirai.internal.network.*
import net.mamoe.mirai.internal.network.components.ClockHolder
import net.mamoe.mirai.internal.network.components.ContactCacheService import net.mamoe.mirai.internal.network.components.ContactCacheService
import net.mamoe.mirai.internal.network.components.ContactUpdater import net.mamoe.mirai.internal.network.components.ContactUpdater
import net.mamoe.mirai.internal.network.components.ServerList import net.mamoe.mirai.internal.network.components.ServerList
import net.mamoe.mirai.internal.network.getRandomByteArray
import net.mamoe.mirai.internal.network.handler.logger
import net.mamoe.mirai.internal.network.handler.selector.NetworkException import net.mamoe.mirai.internal.network.handler.selector.NetworkException
import net.mamoe.mirai.internal.network.impl.netty.HeartbeatFailedException import net.mamoe.mirai.internal.network.impl.netty.HeartbeatFailedException
import net.mamoe.mirai.internal.network.protocol.data.jce.* import net.mamoe.mirai.internal.network.protocol.data.jce.*
@ -41,10 +44,7 @@ import net.mamoe.mirai.internal.utils.NetworkType
import net.mamoe.mirai.internal.utils._miraiContentToString import net.mamoe.mirai.internal.utils._miraiContentToString
import net.mamoe.mirai.internal.utils.io.serialization.* import net.mamoe.mirai.internal.utils.io.serialization.*
import net.mamoe.mirai.internal.utils.toIpV4Long import net.mamoe.mirai.internal.utils.toIpV4Long
import net.mamoe.mirai.utils.BotConfiguration import net.mamoe.mirai.utils.*
import net.mamoe.mirai.utils.currentTimeMillis
import net.mamoe.mirai.utils.encodeToString
import net.mamoe.mirai.utils.toReadPacket
@Suppress("EnumEntryName", "unused") @Suppress("EnumEntryName", "unused")
internal enum class RegPushReason { internal enum class RegPushReason {
@ -150,11 +150,17 @@ internal class StatSvc {
override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): Response { override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): Response {
val packet = readUniPacket(SvcRespRegister.serializer()) val packet = readUniPacket(SvcRespRegister.serializer())
packet.iHelloInterval.let { return Response(packet)
}
override suspend fun QQAndroidBot.handle(packet: Response) {
packet.origin.iHelloInterval.let {
bot.configuration.statHeartbeatPeriodMillis = it.times(1000).toLong() bot.configuration.statHeartbeatPeriodMillis = it.times(1000).toLong()
} }
return Response(packet) val diffMillis = packet.origin.serverTime - currentTimeMillis()
bot.components[ClockHolder].server = Clock.SystemDefault.adjusted(diffMillis)
bot.network.logger.info { "Server time updated, diff: ${diffMillis}ms=${diffMillis.millisToHumanReadableString()}" }
} }
fun online( fun online(