mirror of
https://github.com/mamoe/mirai.git
synced 2024-12-27 00:50:11 +08:00
[core] Proposal implementation of RoamingSupported
for Group
This commit is contained in:
parent
3c580eead4
commit
2d0b4d470a
@ -18,6 +18,7 @@ import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.contact.active.GroupActive
|
||||
import net.mamoe.mirai.contact.announcement.Announcements
|
||||
import net.mamoe.mirai.contact.file.RemoteFiles
|
||||
import net.mamoe.mirai.contact.roaming.RoamingSupported
|
||||
import net.mamoe.mirai.event.events.*
|
||||
import net.mamoe.mirai.message.MessageReceipt
|
||||
import net.mamoe.mirai.message.data.*
|
||||
@ -60,7 +61,7 @@ import kotlin.jvm.JvmSynthetic
|
||||
* 使用 [Group.files] 获取群文件管理器后操作. 详见 [RemoteFiles].
|
||||
*/
|
||||
@NotStableForInheritance
|
||||
public interface Group : Contact, CoroutineScope, FileSupported, AudioSupported {
|
||||
public interface Group : Contact, CoroutineScope, FileSupported, AudioSupported, RoamingSupported {
|
||||
/**
|
||||
* 群名称.
|
||||
*
|
||||
|
@ -17,6 +17,7 @@ import net.mamoe.mirai.contact.*
|
||||
import net.mamoe.mirai.contact.announcement.OfflineAnnouncement
|
||||
import net.mamoe.mirai.contact.announcement.buildAnnouncementParameters
|
||||
import net.mamoe.mirai.contact.file.RemoteFiles
|
||||
import net.mamoe.mirai.contact.roaming.RoamingMessages
|
||||
import net.mamoe.mirai.data.GroupHonorType
|
||||
import net.mamoe.mirai.data.MemberInfo
|
||||
import net.mamoe.mirai.event.broadcast
|
||||
@ -31,6 +32,7 @@ import net.mamoe.mirai.mock.contact.MockGroupControlPane
|
||||
import net.mamoe.mirai.mock.contact.MockNormalMember
|
||||
import net.mamoe.mirai.mock.contact.active.MockGroupActive
|
||||
import net.mamoe.mirai.mock.internal.contact.active.MockGroupActiveImpl
|
||||
import net.mamoe.mirai.mock.internal.contact.roaming.MockRoamingMessages
|
||||
import net.mamoe.mirai.mock.internal.msgsrc.OnlineMsgSrcToGroup
|
||||
import net.mamoe.mirai.mock.internal.msgsrc.newMsgSrc
|
||||
import net.mamoe.mirai.mock.utils.broadcastBlocking
|
||||
@ -353,4 +355,6 @@ internal class MockGroupImpl(
|
||||
override fun toString(): String {
|
||||
return "Group($id)"
|
||||
}
|
||||
|
||||
override val roamingMessages: RoamingMessages = MockRoamingMessages(this)
|
||||
}
|
@ -12,11 +12,8 @@ package net.mamoe.mirai.mock.test.mock
|
||||
import kotlinx.coroutines.flow.toList
|
||||
import net.mamoe.mirai.contact.MemberPermission
|
||||
import net.mamoe.mirai.event.events.*
|
||||
import net.mamoe.mirai.message.data.*
|
||||
import net.mamoe.mirai.message.data.MessageSource.Key.recall
|
||||
import net.mamoe.mirai.message.data.OnlineMessageSource
|
||||
import net.mamoe.mirai.message.data.PlainText
|
||||
import net.mamoe.mirai.message.data.messageChainOf
|
||||
import net.mamoe.mirai.message.data.source
|
||||
import net.mamoe.mirai.mock.MockActions.mockFireRecalled
|
||||
import net.mamoe.mirai.mock.test.MockBotTestBase
|
||||
import net.mamoe.mirai.mock.utils.broadcastMockEvents
|
||||
@ -148,6 +145,24 @@ internal class MessagingTest: MockBotTestBase() {
|
||||
assertEquals(messageChainOf(PlainText("Test2!")), messages[1])
|
||||
assertEquals(messageChainOf(PlainText("Pong!")), messages[2])
|
||||
}
|
||||
|
||||
val mockGroup = bot.addGroup(2, "2")
|
||||
val mockGroupMember1 = mockGroup.addMember(123, "123")
|
||||
val mockGroupMember2 = mockGroup.addMember(124, "124")
|
||||
val mockGroupMember3 = mockGroup.addMember(125, "125")
|
||||
|
||||
broadcastMockEvents {
|
||||
mockGroupMember1 says { append("msg1") }
|
||||
mockGroupMember2 says { append("msg2") }
|
||||
mockGroupMember3 says { append("msg3") }
|
||||
}
|
||||
|
||||
with(mockGroup.roamingMessages.getAllMessages().toList()) {
|
||||
assertEquals(3, size)
|
||||
assertEquals(messageChainOf(PlainText("msg1")), get(0))
|
||||
assertEquals(messageChainOf(PlainText("msg2")), get(1))
|
||||
assertEquals(messageChainOf(PlainText("msg3")), get(2))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -20,6 +20,7 @@ import net.mamoe.mirai.contact.*
|
||||
import net.mamoe.mirai.contact.active.GroupActive
|
||||
import net.mamoe.mirai.contact.announcement.Announcements
|
||||
import net.mamoe.mirai.contact.file.RemoteFiles
|
||||
import net.mamoe.mirai.contact.roaming.RoamingMessages
|
||||
import net.mamoe.mirai.data.GroupHonorType
|
||||
import net.mamoe.mirai.data.GroupInfo
|
||||
import net.mamoe.mirai.data.MemberInfo
|
||||
@ -30,6 +31,7 @@ import net.mamoe.mirai.internal.contact.active.GroupActiveImpl
|
||||
import net.mamoe.mirai.internal.contact.announcement.AnnouncementsImpl
|
||||
import net.mamoe.mirai.internal.contact.file.RemoteFilesImpl
|
||||
import net.mamoe.mirai.internal.contact.info.MemberInfoImpl
|
||||
import net.mamoe.mirai.internal.contact.roaming.RoamingMessagesImplGroup
|
||||
import net.mamoe.mirai.internal.message.contextualBugReportException
|
||||
import net.mamoe.mirai.internal.message.data.OfflineAudioImpl
|
||||
import net.mamoe.mirai.internal.message.image.OfflineGroupImage
|
||||
@ -389,6 +391,8 @@ internal abstract class CommonGroupImpl constructor(
|
||||
return result.success
|
||||
}
|
||||
|
||||
override val roamingMessages: RoamingMessages by lazy { RoamingMessagesImplGroup(this) }
|
||||
|
||||
override fun toString(): String = "Group($id)"
|
||||
}
|
||||
|
||||
|
@ -20,10 +20,14 @@ import net.mamoe.mirai.contact.roaming.RoamingMessage
|
||||
import net.mamoe.mirai.contact.roaming.RoamingMessageFilter
|
||||
import net.mamoe.mirai.contact.roaming.RoamingMessages
|
||||
import net.mamoe.mirai.internal.contact.AbstractContact
|
||||
import net.mamoe.mirai.internal.contact.CommonGroupImpl
|
||||
import net.mamoe.mirai.internal.contact.FriendImpl
|
||||
import net.mamoe.mirai.internal.message.toMessageChainOnline
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.chat.TroopManagement
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.chat.receive.MessageSvcPbGetGroupMsg
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.chat.receive.MessageSvcPbGetRoamMsgReq
|
||||
import net.mamoe.mirai.internal.utils.indexFirstBE
|
||||
import net.mamoe.mirai.message.data.MessageChain
|
||||
import net.mamoe.mirai.utils.check
|
||||
import net.mamoe.mirai.utils.mapToIntArray
|
||||
@ -106,4 +110,71 @@ internal class RoamingMessagesImplFriend(
|
||||
)
|
||||
).value.check()
|
||||
}
|
||||
}
|
||||
|
||||
internal class RoamingMessagesImplGroup(
|
||||
override val contact: CommonGroupImpl
|
||||
) : RoamingMessagesImpl() {
|
||||
override suspend fun requestRoamMsg(
|
||||
timeStart: Long,
|
||||
lastMessageTime: Long,
|
||||
random: Long // unused field
|
||||
): MessageSvcPbGetRoamMsgReq.Response {
|
||||
val lastMsgSeq = contact.bot.network.sendAndExpect(
|
||||
TroopManagement.GetGroupLastMsgSeq(
|
||||
client = contact.bot.client,
|
||||
groupUin = contact.uin
|
||||
)
|
||||
)
|
||||
return when(lastMsgSeq) {
|
||||
is TroopManagement.GetGroupLastMsgSeq.Response.Success -> {
|
||||
val results = mutableListOf<MsgComm.Msg>()
|
||||
var currentSeq = lastMsgSeq.seq
|
||||
|
||||
while (true) {
|
||||
if (currentSeq <= 0) break
|
||||
|
||||
val resp = contact.bot.network.sendAndExpect(
|
||||
MessageSvcPbGetGroupMsg(
|
||||
client = contact.bot.client,
|
||||
groupUin = contact.uin,
|
||||
messageSequence = currentSeq,
|
||||
20 // maximum 20
|
||||
)
|
||||
)
|
||||
if (resp is MessageSvcPbGetGroupMsg.Failed) break
|
||||
if ((resp as MessageSvcPbGetGroupMsg.Success).msgElem.isEmpty()) break
|
||||
|
||||
// the message may be sorted increasing by message time,
|
||||
// if so, additional sortBy will not take cost.
|
||||
val msgElems = resp.msgElem.sortedBy { it.msgHead.msgTime }
|
||||
results.addAll(0, msgElems)
|
||||
|
||||
val firstMsgElem = msgElems.first()
|
||||
if (firstMsgElem.msgHead.msgTime < timeStart) {
|
||||
break
|
||||
} else {
|
||||
currentSeq = (firstMsgElem.msgHead.msgSeq - 1).toLong()
|
||||
}
|
||||
}
|
||||
|
||||
// use binary search to find the first message that message time is lager than lastMessageTime
|
||||
var right = results.indexFirstBE(lastMessageTime) { it.msgHead.msgTime.toLong() }
|
||||
// check messages with same time
|
||||
if (results[right].msgHead.msgTime.toLong() == lastMessageTime) {
|
||||
do { right ++ } while (right <= results.size - 1 && results[right].msgHead.msgTime <= lastMessageTime)
|
||||
}
|
||||
// loops at most 20 times, just traverse
|
||||
val left = results.indexOfFirst { it.msgHead.msgTime >= timeStart }
|
||||
|
||||
MessageSvcPbGetRoamMsgReq.Response(
|
||||
if (left == right) null else results.subList(left, right),
|
||||
if (left == right) -1L else results[right - 1].msgHead.msgTime.toLong(), -1L, byteArrayOf()
|
||||
)
|
||||
}
|
||||
is TroopManagement.GetGroupLastMsgSeq.Response.Failed -> {
|
||||
MessageSvcPbGetRoamMsgReq.Response(null, -1L, -1L, byteArrayOf())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
28
mirai-core/src/commonMain/kotlin/utils/collection.kt
Normal file
28
mirai-core/src/commonMain/kotlin/utils/collection.kt
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2019-2022 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.utils
|
||||
|
||||
internal fun <T, M : Comparable<M>> List<T>.indexFirstBE(
|
||||
value: M,
|
||||
mapping: (T) -> M
|
||||
): Int {
|
||||
var (left, right) = 0 to size - 1
|
||||
var index = -1
|
||||
while (left <= right) {
|
||||
val middle = left + (right - left) / 2
|
||||
if (mapping(get(middle)) >= value) {
|
||||
index = middle
|
||||
right = middle - 1
|
||||
} else {
|
||||
left = middle + 1
|
||||
}
|
||||
}
|
||||
return index
|
||||
}
|
Loading…
Reference in New Issue
Block a user