Skip to content

Commit 6da569d

Browse files
authored
Merge pull request #92 from simple-robot/dev/support-message-reference
支持 MessageReference 的相关收发API
2 parents 2055ff1 + 88eb895 commit 6da569d

File tree

9 files changed

+152
-28
lines changed

9 files changed

+152
-28
lines changed

simbot-component-onebot-v11/simbot-component-onebot-v11-core/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/core/utils/MessageUtil.kt

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package love.forte.simbot.component.onebot.v11.core.utils
1919

2020
import love.forte.simbot.common.id.ID
21+
import love.forte.simbot.component.onebot.common.annotations.InternalOneBotAPI
2122
import love.forte.simbot.component.onebot.v11.core.api.OneBotMessageOutgoing
2223
import love.forte.simbot.component.onebot.v11.core.api.SendMsgApi
2324
import love.forte.simbot.component.onebot.v11.message.segment.OneBotMessageSegment
@@ -29,7 +30,8 @@ import love.forte.simbot.component.onebot.v11.message.segment.OneBotText
2930
*
3031
* @param messageType see [SendMsgApi]`.MESSAGE_TYPE_*`
3132
*/
32-
internal fun sendTextMsgApi(
33+
@InternalOneBotAPI
34+
public fun sendTextMsgApi(
3335
messageType: String,
3436
target: ID,
3537
text: String,
@@ -58,7 +60,8 @@ internal fun sendTextMsgApi(
5860
}
5961
}
6062

61-
internal fun sendPrivateTextMsgApi(
63+
@InternalOneBotAPI
64+
public fun sendPrivateTextMsgApi(
6265
target: ID,
6366
text: String,
6467
reply: ID? = null,
@@ -69,7 +72,8 @@ internal fun sendPrivateTextMsgApi(
6972
reply = reply,
7073
)
7174

72-
internal fun sendGroupTextMsgApi(
75+
@InternalOneBotAPI
76+
public fun sendGroupTextMsgApi(
7377
target: ID,
7478
text: String,
7579
reply: ID? = null,
@@ -86,7 +90,8 @@ internal fun sendGroupTextMsgApi(
8690
*
8791
* @param messageType see [SendMsgApi]`.MESSAGE_TYPE_*`
8892
*/
89-
internal fun sendMsgApi(
93+
@InternalOneBotAPI
94+
public fun sendMsgApi(
9095
messageType: String,
9196
target: ID,
9297
message: List<OneBotMessageSegment>,
@@ -112,7 +117,8 @@ internal fun sendMsgApi(
112117
}
113118
}
114119

115-
internal fun resolveReplyMessageSegmentList(
120+
@InternalOneBotAPI
121+
public fun resolveReplyMessageSegmentList(
116122
message: List<OneBotMessageSegment>,
117123
reply: ID,
118124
): List<OneBotMessageSegment> {
@@ -132,7 +138,8 @@ internal fun resolveReplyMessageSegmentList(
132138
return newMessage
133139
}
134140

135-
internal fun sendPrivateMsgApi(
141+
@InternalOneBotAPI
142+
public fun sendPrivateMsgApi(
136143
target: ID,
137144
message: List<OneBotMessageSegment>,
138145
reply: ID? = null,
@@ -143,7 +150,8 @@ internal fun sendPrivateMsgApi(
143150
reply = reply,
144151
)
145152

146-
internal fun sendGroupMsgApi(
153+
@InternalOneBotAPI
154+
public fun sendGroupMsgApi(
147155
target: ID,
148156
message: List<OneBotMessageSegment>,
149157
reply: ID? = null,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package love.forte.simbot.component.onebot.v11.core
2+
3+
import kotlinx.coroutines.test.runTest
4+
import love.forte.simbot.common.id.IntID.Companion.ID
5+
import love.forte.simbot.component.onebot.v11.core.api.OneBotMessageOutgoing
6+
import love.forte.simbot.component.onebot.v11.core.api.SendMsgApi
7+
import love.forte.simbot.component.onebot.v11.core.utils.sendMsgApi
8+
import love.forte.simbot.component.onebot.v11.core.utils.sendTextMsgApi
9+
import love.forte.simbot.component.onebot.v11.message.resolveToOneBotSegmentList
10+
import love.forte.simbot.component.onebot.v11.message.segment.OneBotFace
11+
import love.forte.simbot.component.onebot.v11.message.segment.OneBotReply
12+
import love.forte.simbot.component.onebot.v11.message.segment.OneBotText
13+
import love.forte.simbot.message.Face
14+
import love.forte.simbot.message.MessageIdReference
15+
import love.forte.simbot.message.buildMessages
16+
import kotlin.collections.first
17+
import kotlin.test.Test
18+
import kotlin.test.assertEquals
19+
import kotlin.test.assertIs
20+
import kotlin.test.assertNotNull
21+
22+
/**
23+
* Tests for `OneBotReply` and `MessageReference` for send.
24+
*
25+
* @author ForteScarlet
26+
*/
27+
class ReplyAndMessageReferenceTests {
28+
@Test
29+
fun sendReplyWithSingleSegmentTest() {
30+
val api = sendMsgApi(
31+
SendMsgApi.MESSAGE_TYPE_GROUP,
32+
target = 123.ID,
33+
message = listOf(OneBotText.create("Hello")),
34+
reply = 456.ID,
35+
)
36+
37+
val body = assertIs<SendMsgApi.Body>(api.body)
38+
val content = assertIs<OneBotMessageOutgoing.SegmentsValue>(body.message)
39+
val firstReply = assertIs<OneBotReply>(content.segments.first())
40+
41+
assertEquals(456.ID, firstReply.id)
42+
}
43+
44+
@Test
45+
fun sendReplyWithSegmentsTest() {
46+
val api = sendMsgApi(
47+
SendMsgApi.MESSAGE_TYPE_GROUP,
48+
target = 123.ID,
49+
message = listOf(OneBotText.create("Hello"), OneBotText.create("Hello"), OneBotFace.create(999.ID)),
50+
reply = 456.ID,
51+
)
52+
53+
val body = assertIs<SendMsgApi.Body>(api.body)
54+
val content = assertIs<OneBotMessageOutgoing.SegmentsValue>(body.message)
55+
val firstReply = assertIs<OneBotReply>(content.segments.first())
56+
57+
assertEquals(456.ID, firstReply.id)
58+
}
59+
60+
@Test
61+
fun sendReplyWithTextTest() {
62+
val api = sendTextMsgApi(
63+
SendMsgApi.MESSAGE_TYPE_GROUP,
64+
target = 123.ID,
65+
text = "666",
66+
reply = 456.ID,
67+
)
68+
69+
val body = assertIs<SendMsgApi.Body>(api.body)
70+
val content = assertIs<OneBotMessageOutgoing.SegmentsValue>(body.message)
71+
val firstReply = assertIs<OneBotReply>(content.segments.first())
72+
73+
assertEquals(456.ID, firstReply.id)
74+
}
75+
76+
@Test
77+
fun messagesToSegmentsWithMessageReferenceTest() = runTest {
78+
val messages = buildMessages {
79+
+"Hello"
80+
+MessageIdReference(123.ID)
81+
+Face(111.ID)
82+
}
83+
84+
val segments = messages.resolveToOneBotSegmentList(null)
85+
assertEquals(3, segments.size)
86+
val reply = assertNotNull(
87+
segments.firstNotNullOfOrNull { it as? OneBotReply }
88+
)
89+
90+
assertEquals(123.ID, reply.id)
91+
}
92+
93+
}

simbot-component-onebot-v11/simbot-component-onebot-v11-core/src/jvmTest/kotlin/ApiExecutableTests.kt renamed to simbot-component-onebot-v11/simbot-component-onebot-v11-core/src/jvmTest/kotlin/love/forte/simbot/component/onebot/v11/core/ApiExecutableTests.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1+
package love.forte.simbot.component.onebot.v11.core
2+
13
import io.mockk.coVerify
24
import io.mockk.mockk
35
import kotlinx.coroutines.test.runTest
46
import love.forte.simbot.component.onebot.v11.core.api.OneBotApi
57
import love.forte.simbot.component.onebot.v11.core.api.OneBotApiExecutable
68
import love.forte.simbot.component.onebot.v11.core.api.inExecutableScope
7-
import kotlin.test.Test
89

910
/**
1011
*

simbot-component-onebot-v11/simbot-component-onebot-v11-core/src/jvmTest/kotlin/AppTest.kt renamed to simbot-component-onebot-v11/simbot-component-onebot-v11-core/src/jvmTest/kotlin/love/forte/simbot/component/onebot/v11/core/AppTest.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
package love.forte.simbot.component.onebot.v11.core
2+
13
import io.ktor.client.engine.java.Java
24
import io.ktor.http.Url
35
import love.forte.simbot.application.listeners
@@ -34,7 +36,7 @@ suspend fun main() {
3436
eventServerHost = Url("ws://localhost:3001")
3537
wsClientEngineFactory = Java
3638
apiClientEngineFactory = Java
37-
accessToken = "test"
39+
accessToken("test")
3840
}
3941
)
4042

simbot-component-onebot-v11/simbot-component-onebot-v11-core/src/jvmTest/kotlin/BotDefaultImageAdditionalTests.kt renamed to simbot-component-onebot-v11/simbot-component-onebot-v11-core/src/jvmTest/kotlin/love/forte/simbot/component/onebot/v11/core/BotDefaultImageAdditionalTests.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
package love.forte.simbot.component.onebot.v11.core
2+
13
import kotlinx.coroutines.test.runTest
24
import love.forte.simbot.component.onebot.v11.core.bot.firstOneBotBotManager
35
import love.forte.simbot.component.onebot.v11.core.bot.register
4-
import love.forte.simbot.component.onebot.v11.core.useOneBot11
56
import love.forte.simbot.component.onebot.v11.message.resolveToOneBotSegment
67
import love.forte.simbot.component.onebot.v11.message.segment.OneBotImage
78
import love.forte.simbot.core.application.launchSimpleApplication

simbot-component-onebot-v11/simbot-component-onebot-v11-message/api/simbot-component-onebot-v11-message.api

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ public abstract interface class love/forte/simbot/component/onebot/v11/message/O
44
public abstract fun getMessages ()Llove/forte/simbot/message/Messages;
55
public abstract fun getPlainText ()Ljava/lang/String;
66
public abstract fun getSourceSegments ()Ljava/util/List;
7+
public fun reference (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
8+
public static synthetic fun reference$suspendImpl (Llove/forte/simbot/component/onebot/v11/message/OneBotMessageContent;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
79
}
810

911
public abstract interface class love/forte/simbot/component/onebot/v11/message/OneBotMessageElement : love/forte/simbot/message/Message$Element {
@@ -918,14 +920,14 @@ public final class love/forte/simbot/component/onebot/v11/message/segment/OneBot
918920
public final fun serializer ()Lkotlinx/serialization/KSerializer;
919921
}
920922

921-
public final class love/forte/simbot/component/onebot/v11/message/segment/OneBotReply : love/forte/simbot/component/onebot/v11/message/segment/OneBotMessageSegment {
923+
public final class love/forte/simbot/component/onebot/v11/message/segment/OneBotReply : love/forte/simbot/component/onebot/v11/message/segment/OneBotMessageSegment, love/forte/simbot/message/MessageReference {
922924
public static final field Factory Llove/forte/simbot/component/onebot/v11/message/segment/OneBotReply$Factory;
923925
public static final field TYPE Ljava/lang/String;
924926
public synthetic fun <init> (Llove/forte/simbot/component/onebot/v11/message/segment/OneBotReply$Data;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
925927
public static final fun create (Llove/forte/simbot/common/id/ID;)Llove/forte/simbot/component/onebot/v11/message/segment/OneBotReply;
926928
public synthetic fun getData ()Ljava/lang/Object;
927929
public fun getData ()Llove/forte/simbot/component/onebot/v11/message/segment/OneBotReply$Data;
928-
public final fun getId ()Llove/forte/simbot/common/id/ID;
930+
public fun getId ()Llove/forte/simbot/common/id/ID;
929931
}
930932

931933
public synthetic class love/forte/simbot/component/onebot/v11/message/segment/OneBotReply$$serializer : kotlinx/serialization/internal/GeneratedSerializer {

simbot-component-onebot-v11/simbot-component-onebot-v11-message/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/message/MessageElementResolvers.kt

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -87,23 +87,24 @@ public suspend fun Message.Element.resolveToOneBotSegment(
8787
is Face -> OneBotFace.create(id)
8888
is At -> OneBotAt.create(target)
8989
is AtAll -> OneBotAt.createAtAll()
90-
is Image -> {
91-
when (this) {
92-
// offline image
93-
is OfflineImage -> suspendCancellableCoroutine<OneBotMessageSegment?> { continuation ->
94-
offlineImageResolver(defaultImageAdditionalParams)
95-
.resolve(this, continuation)
96-
}
97-
98-
// remote images, OneBot组件中实际上没有此类型的实现
99-
// 将它的 id 直接视为 file
100-
is RemoteImage -> OneBotImage.create(id.literal)
101-
102-
// 其他未知类型,不管
103-
else -> null
90+
is Image -> when (this) {
91+
// offline image
92+
is OfflineImage -> suspendCancellableCoroutine<OneBotMessageSegment?> { continuation ->
93+
offlineImageResolver(defaultImageAdditionalParams)
94+
.resolve(this, continuation)
10495
}
96+
97+
// remote images, OneBot组件中实际上没有此类型的实现
98+
// 将它的 id 直接视为 file
99+
is RemoteImage -> OneBotImage.create(id.literal)
100+
101+
// 其他未知类型,不管
102+
else -> null
105103
}
106104

105+
// since 1.2.0
106+
is MessageReference -> OneBotReply.create(id)
107+
107108
// 其他未知类型,不管
108109
else -> null
109110
}

simbot-component-onebot-v11/simbot-component-onebot-v11-message/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/message/OneBotMessageContent.kt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,12 @@ import love.forte.simbot.ability.StandardDeleteOption
2222
import love.forte.simbot.common.id.ID
2323
import love.forte.simbot.component.onebot.v11.message.segment.OneBotMessageSegment
2424
import love.forte.simbot.component.onebot.v11.message.segment.OneBotMessageSegmentElement
25+
import love.forte.simbot.component.onebot.v11.message.segment.OneBotReply
2526
import love.forte.simbot.component.onebot.v11.message.segment.OneBotText
2627
import love.forte.simbot.message.MessageContent
2728
import love.forte.simbot.message.Messages
2829
import love.forte.simbot.message.PlainText
30+
import love.forte.simbot.suspendrunner.STP
2931

3032

3133
/**
@@ -55,6 +57,19 @@ public interface OneBotMessageContent : MessageContent {
5557
*/
5658
override val messages: Messages
5759

60+
/**
61+
* 寻找 [messages] 中第一个 [OneBotReply] 类型的元素,
62+
* 如果没有则得到 `null`。
63+
* 寻找的过程是即时的,不会发生挂起。
64+
*
65+
* @since 1.2.0
66+
* @see messages
67+
* @see OneBotReply
68+
*/
69+
@STP
70+
override suspend fun reference(): OneBotReply? =
71+
messages.firstNotNullOfOrNull { it as? OneBotReply }
72+
5873
/**
5974
* 消息中所有的 [文本消息][PlainText]
6075
* (或者说 [sourceSegments] 中所有的 [OneBotText])

simbot-component-onebot-v11/simbot-component-onebot-v11-message/src/commonMain/kotlin/love/forte/simbot/component/onebot/v11/message/segment/OneBotReply.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ package love.forte.simbot.component.onebot.v11.message.segment
2020
import kotlinx.serialization.SerialName
2121
import kotlinx.serialization.Serializable
2222
import love.forte.simbot.common.id.ID
23+
import love.forte.simbot.message.MessageReference
2324
import kotlin.jvm.JvmStatic
2425

2526

@@ -32,14 +33,14 @@ import kotlin.jvm.JvmStatic
3233
@SerialName(OneBotReply.TYPE)
3334
public class OneBotReply private constructor(
3435
override val data: Data
35-
) : OneBotMessageSegment {
36+
) : OneBotMessageSegment, MessageReference {
3637

3738
/**
3839
* The [Data.id].
3940
*
4041
* @see Data.id
4142
*/
42-
public val id: ID
43+
override val id: ID
4344
get() = data.id
4445

4546
public companion object Factory {

0 commit comments

Comments
 (0)