Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

增加与消息引用相关的内容:标准消息元素类型 MessageReference 和 API MessageContent.reference() #899

Merged
merged 2 commits into from
Aug 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions buildSrc/src/main/kotlin/P.kt
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ sealed class P(override val group: String) : ProjectDetail() {

*/
companion object {
const val VERSION = "4.4.0"
const val NEXT_VERSION = "4.4.0"
const val VERSION = "4.5.0"
const val NEXT_VERSION = "4.5.1"
const val SNAPSHOT_VERSION = "$VERSION-SNAPSHOT"
const val NEXT_SNAPSHOT_VERSION = "$NEXT_VERSION-SNAPSHOT"

Expand Down
36 changes: 36 additions & 0 deletions simbot-api/api/simbot-api.api
Original file line number Diff line number Diff line change
Expand Up @@ -1947,12 +1947,44 @@ public abstract interface class love/forte/simbot/message/MessageContent : love/
public abstract fun getId ()Llove/forte/simbot/common/id/ID;
public abstract fun getMessages ()Llove/forte/simbot/message/Messages;
public abstract fun getPlainText ()Ljava/lang/String;
public fun getReference ()Llove/forte/simbot/message/MessageReference;
public fun getReferenceAsync ()Ljava/util/concurrent/CompletableFuture;
public fun getReferenceReserve ()Llove/forte/simbot/suspendrunner/reserve/SuspendReserve;
public synthetic fun reference (Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static synthetic fun reference$suspendImpl (Llove/forte/simbot/message/MessageContent;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}

public final class love/forte/simbot/message/MessageContentKt {
public static final fun getSafePlainText (Llove/forte/simbot/message/MessageContent;)Ljava/lang/String;
}

public final class love/forte/simbot/message/MessageIdReference : love/forte/simbot/message/MessageReference {
public static final field Companion Llove/forte/simbot/message/MessageIdReference$Companion;
public fun <init> (Llove/forte/simbot/common/id/ID;)V
public final fun component1 ()Llove/forte/simbot/common/id/ID;
public final fun copy (Llove/forte/simbot/common/id/ID;)Llove/forte/simbot/message/MessageIdReference;
public static synthetic fun copy$default (Llove/forte/simbot/message/MessageIdReference;Llove/forte/simbot/common/id/ID;ILjava/lang/Object;)Llove/forte/simbot/message/MessageIdReference;
public fun equals (Ljava/lang/Object;)Z
public fun getId ()Llove/forte/simbot/common/id/ID;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public synthetic class love/forte/simbot/message/MessageIdReference$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
public static final field INSTANCE Llove/forte/simbot/message/MessageIdReference$$serializer;
public final fun childSerializers ()[Lkotlinx/serialization/KSerializer;
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Llove/forte/simbot/message/MessageIdReference;
public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Llove/forte/simbot/message/MessageIdReference;)V
public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer;
}

public final class love/forte/simbot/message/MessageIdReference$Companion {
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}

public final class love/forte/simbot/message/MessageKt {
public static final fun messageElementPolymorphic (Lkotlinx/serialization/modules/SerializersModuleBuilder;Lkotlin/jvm/functions/Function1;)V
}
Expand All @@ -1972,6 +2004,10 @@ public final class love/forte/simbot/message/MessageReceipts {
public static final fun aggregation (Ljava/util/List;)Llove/forte/simbot/message/AggregatedMessageReceipt;
}

public abstract interface class love/forte/simbot/message/MessageReference : love/forte/simbot/message/StandardMessage {
public abstract fun getId ()Llove/forte/simbot/common/id/ID;
}

public abstract interface class love/forte/simbot/message/Messages : java/lang/Iterable, kotlin/jvm/internal/markers/KMappedMarker, love/forte/simbot/message/Message {
public static final field Companion Llove/forte/simbot/message/Messages$Companion;
public static fun builder ()Llove/forte/simbot/message/MessagesBuilder;
Expand Down
2 changes: 2 additions & 0 deletions simbot-api/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ kotlin {

jvmTest {
dependencies {
implementation(libs.mockk)
implementation(project(":simbot-logger-slf4j2-impl"))
implementation(libs.kotlinx.coroutines.reactive)
implementation(libs.kotlinx.coroutines.reactor)
implementation(libs.kotlinx.coroutines.rx2)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import love.forte.simbot.ability.DeleteOption
import love.forte.simbot.ability.DeleteSupport
import love.forte.simbot.common.id.ID
import love.forte.simbot.suspendrunner.STP
import kotlin.jvm.JvmSynthetic


Expand All @@ -50,7 +51,12 @@

/**
* 消息本体中完整消息的消息链。
* [messages] 中的所有元素都是可离线构造的,换言之都是直接通过事件本体解析而来的。
* 如果存在某些例如必须进行网络查询才能得知的消息元素,则不会被包含在 [messages] 中。
*
* 如果想要获取消息引用信息,也可参考 [reference]。
*
* @see reference
*/
public val messages: Messages

Expand All @@ -72,22 +78,47 @@
/**
* 删除、撤回、撤销此消息。
*
* 如果实现者不支持这类API,则会抛出 [UnsupportedOperationException]。

Check warning on line 81 in simbot-api/src/commonMain/kotlin/love/forte/simbot/message/MessageContent.kt

View workflow job for this annotation

GitHub Actions / qodana

Unresolved reference in KDoc

Cannot resolve symbol 'UnsupportedOperationException'
* 如果删除过程中由于权限、不存在等各种业务原因导致的删除失败,则应抛出异常,
* 并建议使用或扩展 [DeleteFailureException] 异常类型。
*
* @param options 删除时的可选选项。不支持的选项将会被忽略。更多说明参考 [DeleteOption]。
*
* @throws UnsupportedOperationException API本身不被实现者支持

Check warning on line 87 in simbot-api/src/commonMain/kotlin/love/forte/simbot/message/MessageContent.kt

View workflow job for this annotation

GitHub Actions / qodana

Unresolved reference in KDoc

Cannot resolve symbol 'UnsupportedOperationException'
* @throws DeleteFailureException 删除行为失败
* @throws NoSuchElementException 没有可删除目标
*/
@JvmSynthetic
override suspend fun delete(vararg options: DeleteOption)

/**
* 获取当前消息内容中有关 [消息引用][MessageReference] 的消息元素。
*
* [reference] 在明确不支持或直接通过 [messages] 寻找获取时,不会发生挂起。
* 否则当需要通过网络查询结果时会产生挂起。
*
* [reference] 所得结果**不一定**是 [messages] 中的元素。
* 如上所述,如果需要通过网络查询才能得到结果,则 [reference] 的结果不会包含在 [messages] 中。
*
* - 如果实现者尚未针对性地实现此API,则默认逻辑为:
* 从 [messages] 中寻找第一个类型为 [MessageReference] 的元素。
* - 如果实现者的所属平台不存在、不支持 _消息引用_ 的概念,则可能始终得到 `null`。
* - 如果实现者的所属平台有明确的 _消息引用_ 概念,但是无法通过 [MessageReference] 这个类型进行表述,
* 则使用 [reference] 时应当抛出信息明确的 [UnsupportedOperationException] 异常。
*
* @throws UnsupportedOperationException 如果实现者的所属平台有明确的 _消息引用_ 概念,
* 但是无法通过 [MessageReference] 这个类型进行表述
*
* @since 4.5.0
*/
@STP
public suspend fun reference(): MessageReference? =
messages.firstOrNull { it is MessageReference } as? MessageReference?

}

/**
* 如果 [MessageContent.plainText],则以空字符串 `""` 替代之。
* 如果 [MessageContent.plainText] 为 `null`,则以空字符串 `""` 替代之。
* @see MessageContent.plainText
*/
public inline val MessageContent.safePlainText: String get() = plainText ?: ""
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ public sealed interface Messages : Message, Iterable<Message.Element> {

subclass(Emoji.serializer())
subclass(Face.serializer())
subclass(MessageIdReference.serializer())


resolvePlatformStandardSerializers()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import kotlin.jvm.*
* - [RemoteImage]
* - [表情消息][Face]
* - [emoji][Emoji]
* - [消息引用][MessageReference]
*
* JVM平台中部分扩展、辅助API通过静态类 `StandardMessages` 提供。
*
Expand Down Expand Up @@ -382,8 +383,7 @@ public data class SimpleOfflineResourceImage(
@Serializable(
ResourceBase64Serializer::class
) override val resource: Resource
) :
OfflineResourceImage
) : OfflineResourceImage


/**
Expand Down Expand Up @@ -480,3 +480,33 @@ public data class Emoji(public val id: ID) : StandardMessage, EmoticonMessage
public data class Face(public val id: ID) : StandardMessage, EmoticonMessage
//endregion

//region MessageReference

/**
* 一个消息引用元素,用来表示对另一个消息元素的引用。
* 可用于发送或接收,是否能应用取决于具体地实现。
*
* 当某个平台存在 _消息引用_ 的概念,但是无法使用 [MessageReference] 进行描述(例如它通过多重ID确定唯一身份,而不是唯一ID),
* 则需要由平台实现者自行实现,无法使用 [MessageReference],也无法使用 [MessageContent.reference]。
*
* @since 4.5.0
*
* @see MessageContent.reference
* @see MessageIdReference
*/
public interface MessageReference : StandardMessage {
/**
* 被引用的目标消息ID。
*/
public val id: ID

}

/**
* 一个仅实现 [id] 的 [MessageReference] 简单实现。
*/
@Serializable
@SerialName("m.std.messageReference.id")
public data class MessageIdReference(override val id: ID) : MessageReference

//endregion
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright (c) 2024. ForteScarlet.
*
* Project https://github.com/simple-robot/simpler-robot
* Email [email protected]
*
* This file is part of the Simple Robot Library (Alias: simple-robot, simbot, etc.).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Lesser GNU General Public License for more details.
*
* You should have received a copy of the Lesser GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/

package message

import io.mockk.coVerify
import io.mockk.every
import io.mockk.spyk
import kotlinx.coroutines.runBlocking
import love.forte.simbot.message.MessageContent
import love.forte.simbot.message.emptyMessages
import kotlin.test.Test


/**
*
* @author ForteScarlet
*/
class MessageContentReferenceTests {

@Test
fun contentReferenceTest() {
val content = spyk<MessageContent>()
every { content.messages } returns emptyMessages()

runBlocking { content.reference() }
coVerify { content.messages }
}

}
Loading