Skip to content

Commit 972669a

Browse files
committed
feat: 实现 OneBotFriend.send 的拦截事件和成功回调事件
1 parent f01ec9c commit 972669a

File tree

11 files changed

+632
-128
lines changed

11 files changed

+632
-128
lines changed

simbot-component-onebot-v11/simbot-component-onebot-v11-core/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/core/actor/internal/OneBotFriendImpl.kt

Lines changed: 77 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,50 +23,109 @@ import love.forte.simbot.component.onebot.v11.core.actor.OneBotStranger
2323
import love.forte.simbot.component.onebot.v11.core.api.GetFriendListResult
2424
import love.forte.simbot.component.onebot.v11.core.api.GetStrangerInfoApi
2525
import love.forte.simbot.component.onebot.v11.core.api.SendLikeApi
26+
import love.forte.simbot.component.onebot.v11.core.api.SendMsgResult
2627
import love.forte.simbot.component.onebot.v11.core.bot.internal.OneBotBotImpl
28+
import love.forte.simbot.component.onebot.v11.core.event.internal.messageinteraction.OneBotFriendPostSendEventImpl
29+
import love.forte.simbot.component.onebot.v11.core.event.internal.messageinteraction.OneBotFriendPreSendEventImpl
30+
import love.forte.simbot.component.onebot.v11.core.event.messageinteraction.OneBotSegmentsInteractionMessage
31+
import love.forte.simbot.component.onebot.v11.core.event.messageinteraction.segmentsOrNull
32+
import love.forte.simbot.component.onebot.v11.core.event.messageinteraction.toOneBotSegmentsInteractionMessage
2733
import love.forte.simbot.component.onebot.v11.core.internal.message.toReceipt
28-
import love.forte.simbot.component.onebot.v11.core.utils.resolveToOneBotSegmentList
29-
import love.forte.simbot.component.onebot.v11.core.utils.sendPrivateMsgApi
30-
import love.forte.simbot.component.onebot.v11.core.utils.sendPrivateTextMsgApi
34+
import love.forte.simbot.component.onebot.v11.core.utils.*
3135
import love.forte.simbot.component.onebot.v11.event.message.RawPrivateMessageEvent
32-
import love.forte.simbot.component.onebot.v11.message.OneBotMessageContent
3336
import love.forte.simbot.component.onebot.v11.message.OneBotMessageReceipt
37+
import love.forte.simbot.component.onebot.v11.message.segment.OneBotMessageSegment
38+
import love.forte.simbot.event.InteractionMessage
3439
import love.forte.simbot.message.Message
3540
import love.forte.simbot.message.MessageContent
41+
import love.forte.simbot.message.PlainText
3642
import kotlin.coroutines.CoroutineContext
3743

3844
internal abstract class OneBotFriendImpl : OneBotFriend {
3945
protected abstract val bot: OneBotBotImpl
4046

4147
override suspend fun send(text: String): OneBotMessageReceipt {
48+
val interactionMessage = OneBotSegmentsInteractionMessage(text = text)
49+
return interceptionAndSend(interactionMessage)
50+
}
51+
52+
override suspend fun send(messageContent: MessageContent): OneBotMessageReceipt {
53+
val interactionMessage = OneBotSegmentsInteractionMessage(content = messageContent)
54+
return interceptionAndSend(interactionMessage)
55+
}
56+
57+
override suspend fun send(message: Message): OneBotMessageReceipt {
58+
val interactionMessage = OneBotSegmentsInteractionMessage(message = message, bot = bot)
59+
return interceptionAndSend(interactionMessage)
60+
}
61+
62+
private suspend fun interceptionAndSend(
63+
interactionMessage: OneBotSegmentsInteractionMessage
64+
): OneBotMessageReceipt {
65+
val event = OneBotFriendPreSendEventImpl(
66+
this,
67+
bot,
68+
interactionMessage
69+
)
70+
71+
val currentMessage = bot.emitMessagePreSendEventAndUseCurrentMessage(event)
72+
val segments = currentMessage.segmentsOrNull
73+
if (segments != null) {
74+
return sendSegments(segments).toReceipt(bot).alsoPostSend(currentMessage)
75+
}
76+
77+
return sendByInteractionMessage(currentMessage).toReceipt(bot).alsoPostSend(currentMessage)
78+
}
79+
80+
/**
81+
* 解析一个 [InteractionMessage] 为一个 [OneBotMessageSegment] 的列表并发送。
82+
* 始终认为 `segments` 为 `null`。
83+
*/
84+
private suspend fun sendByInteractionMessage(interactionMessage: InteractionMessage): SendMsgResult {
85+
return resolveInteractionMessage(
86+
interactionMessage = interactionMessage,
87+
onSegments = { sendSegments(it) },
88+
onMessage = { sendMessage(it) },
89+
onText = { sendText(it) },
90+
)
91+
}
92+
93+
private suspend fun sendText(text: String): SendMsgResult {
4294
return bot.executeData(
4395
sendPrivateTextMsgApi(
4496
target = id,
4597
text = text,
4698
)
47-
).toReceipt(bot)
99+
)
48100
}
49101

50-
override suspend fun send(messageContent: MessageContent): OneBotMessageReceipt {
51-
if (messageContent is OneBotMessageContent) {
52-
return bot.executeData(
53-
sendPrivateMsgApi(
54-
target = id,
55-
message = messageContent.sourceSegments,
56-
)
57-
).toReceipt(bot)
102+
private suspend fun sendMessage(message: Message): SendMsgResult {
103+
return when (message) {
104+
is PlainText -> sendText(message.text)
105+
else -> sendSegments(message.resolveToOneBotSegmentList(bot))
58106
}
59-
60-
return send(messageContent.messages)
61107
}
62108

63-
override suspend fun send(message: Message): OneBotMessageReceipt {
109+
private suspend fun sendSegments(segments: List<OneBotMessageSegment>): SendMsgResult {
64110
return bot.executeData(
65111
sendPrivateMsgApi(
66112
target = id,
67-
message = message.resolveToOneBotSegmentList(bot)
113+
message = segments,
68114
)
69-
).toReceipt(bot)
115+
)
116+
}
117+
118+
private fun OneBotMessageReceipt.alsoPostSend(
119+
interactionMessage: InteractionMessage
120+
): OneBotMessageReceipt = apply {
121+
val event = OneBotFriendPostSendEventImpl(
122+
content = this@OneBotFriendImpl,
123+
bot = bot,
124+
receipt = this,
125+
message = interactionMessage.toOneBotSegmentsInteractionMessage()
126+
)
127+
128+
bot.pushEventAndLaunch(event)
70129
}
71130

72131
override suspend fun sendLike(times: Int) {

simbot-component-onebot-v11/simbot-component-onebot-v11-core/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/core/actor/internal/OneBotGroupImpl.kt

Lines changed: 15 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,14 @@ import love.forte.simbot.component.onebot.v11.core.bot.internal.OneBotBotImpl
3030
import love.forte.simbot.component.onebot.v11.core.event.internal.messageinteraction.OneBotGroupPostSendEventImpl
3131
import love.forte.simbot.component.onebot.v11.core.event.internal.messageinteraction.OneBotGroupPreSendEventImpl
3232
import love.forte.simbot.component.onebot.v11.core.event.messageinteraction.OneBotSegmentsInteractionMessage
33+
import love.forte.simbot.component.onebot.v11.core.event.messageinteraction.segmentsOrNull
3334
import love.forte.simbot.component.onebot.v11.core.event.messageinteraction.toOneBotSegmentsInteractionMessage
3435
import love.forte.simbot.component.onebot.v11.core.internal.message.toReceipt
36+
import love.forte.simbot.component.onebot.v11.core.utils.emitMessagePreSendEventAndUseCurrentMessage
37+
import love.forte.simbot.component.onebot.v11.core.utils.resolveInteractionMessage
3538
import love.forte.simbot.component.onebot.v11.core.utils.resolveToOneBotSegmentList
3639
import love.forte.simbot.component.onebot.v11.core.utils.sendGroupMsgApi
3740
import love.forte.simbot.component.onebot.v11.core.utils.sendGroupTextMsgApi
38-
import love.forte.simbot.component.onebot.v11.message.OneBotMessageContent
3941
import love.forte.simbot.component.onebot.v11.message.OneBotMessageReceipt
4042
import love.forte.simbot.component.onebot.v11.message.segment.OneBotMessageSegment
4143
import love.forte.simbot.event.InteractionMessage
@@ -94,29 +96,17 @@ internal abstract class OneBotGroupImpl(
9496
}
9597

9698
override suspend fun send(text: String): OneBotMessageReceipt {
97-
val interactionMessage = OneBotSegmentsInteractionMessage.create(
98-
message = InteractionMessage.valueOf(text),
99-
segments = null
100-
)
101-
99+
val interactionMessage = OneBotSegmentsInteractionMessage(text)
102100
return interceptionAndSend(interactionMessage)
103101
}
104102

105103
override suspend fun send(messageContent: MessageContent): OneBotMessageReceipt {
106-
val interactionMessage = OneBotSegmentsInteractionMessage.create(
107-
message = InteractionMessage.valueOf(messageContent),
108-
segments = (messageContent as? OneBotMessageContent)?.sourceSegments
109-
)
110-
104+
val interactionMessage = OneBotSegmentsInteractionMessage(messageContent)
111105
return interceptionAndSend(interactionMessage)
112106
}
113107

114108
override suspend fun send(message: Message): OneBotMessageReceipt {
115-
val interactionMessage = OneBotSegmentsInteractionMessage.create(
116-
message = InteractionMessage.valueOf(message),
117-
segments = message.resolveToOneBotSegmentList(bot)
118-
)
119-
109+
val interactionMessage = OneBotSegmentsInteractionMessage(message = message, bot = bot)
120110
return interceptionAndSend(interactionMessage)
121111
}
122112

@@ -129,9 +119,8 @@ internal abstract class OneBotGroupImpl(
129119
interactionMessage
130120
)
131121

132-
bot.emitMessagePreSendEvent(event)
133-
val currentMessage = event.useCurrentMessage()
134-
val segments = (currentMessage as? OneBotSegmentsInteractionMessage)?.segments
122+
val currentMessage = bot.emitMessagePreSendEventAndUseCurrentMessage(event)
123+
val segments = currentMessage.segmentsOrNull
135124
if (segments != null) {
136125
return sendSegments(segments).toReceipt(bot).alsoPostSend(currentMessage)
137126
}
@@ -143,38 +132,15 @@ internal abstract class OneBotGroupImpl(
143132
* 解析一个 InteractionMessage 为一个 OneBotMessageSegment 的列表并发送。
144133
* 始终认为 `segments` 为 `null`。
145134
*/
146-
private suspend fun sendByInteractionMessage(
147-
interactionMessage: InteractionMessage,
148-
allowSegmentMessage: Boolean = true
149-
): SendMsgResult {
150-
return when (interactionMessage) {
151-
is InteractionMessage.Message -> sendMessage(interactionMessage.message)
152-
is InteractionMessage.MessageContent -> {
153-
val messageContent = interactionMessage.messageContent
154-
if (messageContent is OneBotMessageContent) {
155-
sendSegments(messageContent.sourceSegments)
156-
} else {
157-
sendMessage(messageContent.messages)
158-
}
159-
}
160-
161-
is InteractionMessage.Text -> sendText(interactionMessage.text)
162-
is OneBotSegmentsInteractionMessage -> {
163-
if (!allowSegmentMessage) {
164-
error(
165-
"InteractionMessage.message does not support the type OneBotSegmentsInteractionMessage, " +
166-
"but $interactionMessage"
167-
)
168-
}
169-
170-
sendByInteractionMessage(interactionMessage.message, false)
171-
}
172-
173-
else -> error("Unknown InteractionMessage type: $interactionMessage")
174-
}
135+
private suspend fun sendByInteractionMessage(interactionMessage: InteractionMessage): SendMsgResult {
136+
return resolveInteractionMessage(
137+
interactionMessage = interactionMessage,
138+
onSegments = { sendSegments(it) },
139+
onMessage = { sendMessage(it) },
140+
onText = { sendText(it) },
141+
)
175142
}
176143

177-
178144
private suspend fun sendText(text: String): SendMsgResult {
179145
return bot.executeData(
180146
sendGroupTextMsgApi(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright (c) 2025. ForteScarlet.
3+
*
4+
* This file is part of simbot-component-onebot.
5+
*
6+
* simbot-component-onebot is free software: you can redistribute it and/or modify it under the terms
7+
* of the GNU Lesser General Public License as published by the Free Software Foundation,
8+
* either version 3 of the License, or (at your option) any later version.
9+
*
10+
* simbot-component-onebot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11+
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12+
* See the GNU Lesser General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU Lesser General Public License along with simbot-component-onebot.
15+
* If not, see <https://www.gnu.org/licenses/>.
16+
*/
17+
18+
package love.forte.simbot.component.onebot.v11.core.event.internal.messageinteraction
19+
20+
import love.forte.simbot.annotations.ExperimentalSimbotAPI
21+
import love.forte.simbot.common.atomic.atomic
22+
import love.forte.simbot.common.id.ID
23+
import love.forte.simbot.common.id.UUID
24+
import love.forte.simbot.common.time.Timestamp
25+
import love.forte.simbot.component.onebot.v11.core.event.messageinteraction.OneBotInternalMessagePostSendEvent
26+
import love.forte.simbot.component.onebot.v11.core.event.messageinteraction.OneBotInternalMessagePreSendEvent
27+
import love.forte.simbot.component.onebot.v11.core.event.messageinteraction.OneBotSegmentsInteractionMessage
28+
import love.forte.simbot.event.FuzzyEventTypeImplementation
29+
import love.forte.simbot.event.InteractionMessage
30+
31+
32+
@OptIn(FuzzyEventTypeImplementation::class)
33+
internal abstract class AbstractMessagePreSendEventImpl(override val message: OneBotSegmentsInteractionMessage) :
34+
OneBotInternalMessagePreSendEvent {
35+
override val id: ID = UUID.random()
36+
37+
@OptIn(ExperimentalSimbotAPI::class)
38+
override val time: Timestamp = Timestamp.now()
39+
40+
protected val currentMessageUsed = atomic(false)
41+
private var _currentMessage: InteractionMessage = message
42+
43+
override var currentMessage: InteractionMessage
44+
get() = _currentMessage
45+
set(value) {
46+
if (currentMessageUsed.value) {
47+
error("`currentMessage` has been used.")
48+
}
49+
_currentMessage = value
50+
}
51+
52+
internal fun useCurrentMessage(): InteractionMessage {
53+
if (!currentMessageUsed.compareAndSet(false, true)) {
54+
error("`currentMessage` has been used.")
55+
}
56+
return _currentMessage
57+
}
58+
}
59+
60+
@OptIn(FuzzyEventTypeImplementation::class)
61+
internal abstract class AbstractMessagePostSendEventImpl : OneBotInternalMessagePostSendEvent {
62+
override val id: ID = UUID.random()
63+
64+
@OptIn(ExperimentalSimbotAPI::class)
65+
override val time: Timestamp = Timestamp.now()
66+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright (c) 2025. ForteScarlet.
3+
*
4+
* This file is part of simbot-component-onebot.
5+
*
6+
* simbot-component-onebot is free software: you can redistribute it and/or modify it under the terms
7+
* of the GNU Lesser General Public License as published by the Free Software Foundation,
8+
* either version 3 of the License, or (at your option) any later version.
9+
*
10+
* simbot-component-onebot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
11+
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12+
* See the GNU Lesser General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU Lesser General Public License along with simbot-component-onebot.
15+
* If not, see <https://www.gnu.org/licenses/>.
16+
*/
17+
18+
package love.forte.simbot.component.onebot.v11.core.event.internal.messageinteraction
19+
20+
import love.forte.simbot.component.onebot.v11.core.actor.OneBotFriend
21+
import love.forte.simbot.component.onebot.v11.core.bot.OneBotBot
22+
import love.forte.simbot.component.onebot.v11.core.event.messageinteraction.OneBotFriendPostSendEvent
23+
import love.forte.simbot.component.onebot.v11.core.event.messageinteraction.OneBotFriendPreSendEvent
24+
import love.forte.simbot.component.onebot.v11.core.event.messageinteraction.OneBotSegmentsInteractionMessage
25+
import love.forte.simbot.component.onebot.v11.message.OneBotMessageReceipt
26+
27+
internal class OneBotFriendPreSendEventImpl(
28+
override val content: OneBotFriend,
29+
override val bot: OneBotBot,
30+
message: OneBotSegmentsInteractionMessage
31+
) : AbstractMessagePreSendEventImpl(message), OneBotFriendPreSendEvent
32+
33+
internal class OneBotFriendPostSendEventImpl(
34+
override val content: OneBotFriend,
35+
override val bot: OneBotBot,
36+
override val receipt: OneBotMessageReceipt,
37+
override val message: OneBotSegmentsInteractionMessage,
38+
) : AbstractMessagePostSendEventImpl(), OneBotFriendPostSendEvent

0 commit comments

Comments
 (0)