Skip to content

Commit 56dea84

Browse files
NambersKarlatemp
andauthored
[mock] Fix message recalling (#2421)
* Fix message recalling Co-authored-by: Karlatemp <[email protected]> * Message recalling tests Co-authored-by: Karlatemp <[email protected]>
1 parent aa84e6d commit 56dea84

File tree

5 files changed

+436
-50
lines changed

5 files changed

+436
-50
lines changed

mirai-core-mock/src/MockActions.kt

+90-39
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,11 @@ package net.mamoe.mirai.mock
1111

1212
import me.him188.kotlin.jvm.blocking.bridge.JvmBlockingBridge
1313
import net.mamoe.mirai.Bot
14-
import net.mamoe.mirai.contact.Friend
15-
import net.mamoe.mirai.contact.Group
16-
import net.mamoe.mirai.contact.MemberPermission
17-
import net.mamoe.mirai.contact.User
14+
import net.mamoe.mirai.contact.*
1815
import net.mamoe.mirai.event.broadcast
1916
import net.mamoe.mirai.event.events.*
2017
import net.mamoe.mirai.message.MessageReceipt
21-
import net.mamoe.mirai.message.data.MessageChain
22-
import net.mamoe.mirai.message.data.MessageSource
23-
import net.mamoe.mirai.message.data.OnlineMessageSource
24-
import net.mamoe.mirai.message.data.source
18+
import net.mamoe.mirai.message.data.*
2519
import net.mamoe.mirai.mock.contact.MockFriend
2620
import net.mamoe.mirai.mock.contact.MockNormalMember
2721
import net.mamoe.mirai.mock.contact.MockStranger
@@ -125,42 +119,99 @@ public object MockActions {
125119
*/
126120
@JvmStatic
127121
public suspend fun fireMessageRecalled(source: MessageSource, operator: User? = null) {
128-
if (source is OnlineMessageSource) {
129-
val from = source.sender
130-
when (val target = source.target) {
131-
is Group -> {
132-
from.bot.mock().msgDatabase.removeMessageInfo(source)
133-
MessageRecallEvent.GroupRecall(
134-
source.bot,
135-
from.id,
136-
source.ids,
137-
source.internalIds,
138-
source.time,
139-
operator?.cast(),
140-
target,
141-
when (from) {
142-
is Bot -> target.botAsMember
143-
else -> from.cast()
144-
}
145-
).broadcast()
146-
return
122+
fun notSupported(): Nothing = error("Unsupported message source kind: ${source.kind}: ${source.javaClass}")
123+
124+
val bot: MockBot = when {
125+
source is OnlineMessageSource -> source.bot.mock()
126+
operator != null -> operator.bot.mock()
127+
else -> source.botOrNull?.mock() ?: error("Cannot find bot from source or operator")
128+
}
129+
130+
val sourceKind = source.kind
131+
132+
fun target(): ContactOrBot = when {
133+
source is OnlineMessageSource -> source.target
134+
source.targetId == bot.id -> bot
135+
136+
sourceKind == MessageSourceKind.FRIEND -> bot.getFriendOrFail(source.targetId)
137+
sourceKind == MessageSourceKind.STRANGER -> bot.getStrangerOrFail(source.targetId)
138+
sourceKind == MessageSourceKind.TEMP -> error("Cannot detect message target from TEMP source kind")
139+
sourceKind == MessageSourceKind.GROUP -> bot.getGroupOrFail(source.targetId)
140+
141+
else -> notSupported()
142+
}
143+
144+
fun sender(): ContactOrBot = when {
145+
source is OnlineMessageSource -> source.sender
146+
source.fromId == bot.id -> bot
147+
148+
149+
sourceKind == MessageSourceKind.FRIEND -> bot.getFriendOrFail(source.fromId)
150+
sourceKind == MessageSourceKind.STRANGER -> bot.getStrangerOrFail(source.fromId)
151+
sourceKind == MessageSourceKind.TEMP -> error("Cannot detect message sender from TEMP source kind")
152+
sourceKind == MessageSourceKind.GROUP -> throw AssertionError("Message from group")
153+
154+
else -> notSupported()
155+
}
156+
157+
fun subject(): Contact = when {
158+
source is OnlineMessageSource -> source.subject
159+
160+
source.fromId == bot.id -> target() as Contact
161+
sourceKind == MessageSourceKind.GROUP -> target() as Contact
162+
163+
else -> sender() as Contact
164+
}
165+
166+
167+
when (sourceKind) {
168+
MessageSourceKind.GROUP -> {
169+
val sender = sender()
170+
val group = subject() as Group
171+
172+
val operator0 = when {
173+
operator === bot -> null
174+
operator === group.botAsMember -> null
175+
176+
operator == null -> sender.cast()
177+
operator is Member -> operator
178+
179+
else -> error("Provided operator $operator(${operator.javaClass}) not a member")
147180
}
148181

149-
is Friend -> {
150-
from.bot.mock().msgDatabase.removeMessageInfo(source)
151-
MessageRecallEvent.FriendRecall(
152-
source.bot,
153-
source.ids,
154-
source.internalIds,
155-
source.time,
156-
from.id,
157-
from.cast()
158-
).broadcast()
159-
return
182+
bot.msgDatabase.removeMessageInfo(source)
183+
MessageRecallEvent.GroupRecall(
184+
bot, sender.id, source.ids, source.internalIds, source.time,
185+
operator0,
186+
group,
187+
when (sender) {
188+
is Bot -> group.botAsMember
189+
else -> sender.cast()
190+
}
191+
).broadcast()
192+
}
193+
MessageSourceKind.FRIEND -> {
194+
val subject = subject() as Friend
195+
196+
bot.msgDatabase.removeMessageInfo(source)
197+
if (source.fromId == bot.id) {
198+
return // no event
160199
}
200+
201+
MessageRecallEvent.FriendRecall(bot, source.ids, source.internalIds, source.time, subject.id, subject)
202+
.broadcast()
161203
}
204+
MessageSourceKind.TEMP -> {
205+
bot.mock().msgDatabase.removeMessageInfo(source)
206+
// TODO: event not available
207+
}
208+
MessageSourceKind.STRANGER -> {
209+
bot.mock().msgDatabase.removeMessageInfo(source)
210+
// TODO: event not available
211+
}
212+
213+
else -> notSupported()
162214
}
163-
error("Unsupported message source type: ${source.javaClass}")
164215
}
165216

166217
/**

mirai-core-mock/src/internal/MockMiraiImpl.kt

+25-6
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@ import net.mamoe.mirai.internal.MiraiImpl
2424
import net.mamoe.mirai.internal.network.components.EventDispatcher
2525
import net.mamoe.mirai.message.action.Nudge
2626
import net.mamoe.mirai.message.data.*
27+
import net.mamoe.mirai.mock.MockActions
2728
import net.mamoe.mirai.mock.MockBotFactory
2829
import net.mamoe.mirai.mock.contact.MockGroup
2930
import net.mamoe.mirai.mock.database.queryMessageInfo
31+
import net.mamoe.mirai.mock.database.removeMessageInfo
3032
import net.mamoe.mirai.mock.internal.contact.AQQ_RECALL_FAILED_MESSAGE
3133
import net.mamoe.mirai.mock.internal.contact.MockFriendImpl
3234
import net.mamoe.mirai.mock.internal.contact.MockImage
@@ -178,6 +180,8 @@ internal class MockMiraiImpl : MiraiImpl() {
178180
val canDelete = when (group.botPermission) {
179181
MemberPermission.OWNER -> true
180182
MemberPermission.ADMINISTRATOR -> kotlin.run w@{
183+
if (info.sender == bot.id) return@w true
184+
181185
val member = group.getMember(info.sender) ?: return@w true
182186
member.permission == MemberPermission.MEMBER
183187
}
@@ -241,9 +245,21 @@ internal class MockMiraiImpl : MiraiImpl() {
241245
)
242246
if (!resp) doFailed()
243247
}
244-
else -> {
248+
249+
is OnlineMessageSource.Incoming.FromStranger -> doFailed()
250+
is OnlineMessageSource.Incoming.FromTemp -> doFailed()
251+
252+
253+
is OnlineMessageSource.Outgoing.ToStranger -> {
254+
bot.mock().msgDatabase.removeMessageInfo(source)
255+
// TODO: No Event
256+
}
257+
is OnlineMessageSource.Outgoing.ToTemp -> {
258+
bot.mock().msgDatabase.removeMessageInfo(source)
245259
// TODO: No Event
246260
}
261+
262+
else -> doFailed()
247263
}
248264
} else {
249265
source as OfflineMessageSource
@@ -267,12 +283,15 @@ internal class MockMiraiImpl : MiraiImpl() {
267283
)
268284
if (!resp) doFailed()
269285
}
270-
MessageSourceKind.TEMP -> {
271-
// TODO: No Event
272-
}
273-
MessageSourceKind.STRANGER -> {
274-
// TODO: No Event
286+
MessageSourceKind.TEMP, MessageSourceKind.STRANGER -> {
287+
if (source.fromId != bot.id) {
288+
doFailed()
289+
}
290+
291+
MockActions.fireMessageRecalled(source, bot.asFriend)
275292
}
293+
294+
else -> doFailed()
276295
}
277296
}
278297
}

mirai-core-mock/test/MockBotTestBase.kt

+16
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,17 @@ package net.mamoe.mirai.mock.test
1111

1212
import net.mamoe.mirai.event.Event
1313
import net.mamoe.mirai.event.GlobalEventChannel
14+
import net.mamoe.mirai.message.data.MessageSource
1415
import net.mamoe.mirai.mock.MockBotFactory
16+
import net.mamoe.mirai.mock.database.queryMessageInfo
1517
import net.mamoe.mirai.mock.internal.MockBotImpl
1618
import net.mamoe.mirai.mock.utils.MockActionsScope
1719
import net.mamoe.mirai.mock.utils.broadcastMockEvents
1820
import org.junit.jupiter.api.AfterEach
1921
import org.junit.jupiter.api.TestInstance
2022
import kotlin.contracts.InvocationKind
2123
import kotlin.contracts.contract
24+
import kotlin.test.fail
2225

2326
@TestInstance(TestInstance.Lifecycle.PER_METHOD)
2427
internal open class MockBotTestBase : TestBase() {
@@ -55,4 +58,17 @@ internal open class MockBotTestBase : TestBase() {
5558
return result
5659
}
5760

61+
62+
internal fun assertMessageNotAvailable(source: MessageSource) {
63+
if (bot.msgDatabase.queryMessageInfo(source.ids, source.internalIds) != null) {
64+
fail("Require message $source no longer available.")
65+
}
66+
}
67+
68+
internal fun assertMessageAvailable(source: MessageSource) {
69+
if (bot.msgDatabase.queryMessageInfo(source.ids, source.internalIds) == null) {
70+
fail("Require message $source available.")
71+
}
72+
}
73+
5874
}

mirai-core-mock/test/TestBase.kt

+14
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ import net.mamoe.mirai.event.Event
1515
import net.mamoe.mirai.event.events.MessageEvent
1616
import net.mamoe.mirai.event.events.MessagePostSendEvent
1717
import net.mamoe.mirai.event.events.MessagePreSendEvent
18+
import org.junit.jupiter.api.DynamicContainer
19+
import org.junit.jupiter.api.DynamicNode
20+
import org.junit.jupiter.api.DynamicTest
1821
import org.junit.jupiter.api.fail
1922
import java.net.URL
2023
import kotlin.reflect.jvm.jvmName
@@ -47,4 +50,15 @@ internal open class TestBase {
4750
assertFails { block() }
4851
}
4952

53+
internal fun dynamicTest(displayName: String, action: suspend CoroutineScope.() -> Unit): DynamicTest {
54+
return DynamicTest.dynamicTest(displayName) { runBlocking(block = action) }
55+
}
56+
57+
internal fun dynamicContainer(
58+
displayName: String,
59+
action: suspend CoroutineScope.() -> Iterable<DynamicNode>
60+
): DynamicContainer {
61+
return DynamicContainer.dynamicContainer(displayName, runBlocking(block = action))
62+
}
63+
5064
}

0 commit comments

Comments
 (0)