mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-08 09:10:11 +08:00
Introduce Message.contentToString
This commit is contained in:
parent
3575e802c7
commit
4d6085c006
@ -40,6 +40,7 @@ private constructor(val target: Long, val display: String) :
|
||||
constructor(member: Member) : this(member.id, "@${member.nameCardOrNick}")
|
||||
|
||||
override fun toString(): String = "[mirai:at:$target]"
|
||||
override fun contentToString(): String = this.display
|
||||
|
||||
companion object Key : Message.Key<At> {
|
||||
/**
|
||||
|
@ -36,6 +36,7 @@ object AtAll :
|
||||
|
||||
@Suppress("SpellCheckingInspection")
|
||||
override fun toString(): String = "[mirai:atall]"
|
||||
override fun contentToString(): String = "@全体成员"
|
||||
|
||||
// 自动为消息补充 " "
|
||||
|
||||
|
@ -25,6 +25,7 @@ class Face private constructor(val id: Int, private val stringValue: String) :
|
||||
constructor(id: Int) : this(id, "[mirai:face:$id]")
|
||||
|
||||
override fun toString(): String = stringValue
|
||||
override fun contentToString(): String = "[表情]"
|
||||
|
||||
/**
|
||||
* @author LamGC
|
||||
|
@ -81,6 +81,10 @@ class PokeMessage @MiraiInternalAPI(message = "使用伴生对象中的常量")
|
||||
override fun subSequence(startIndex: Int, endIndex: Int): CharSequence =
|
||||
stringValue.subSequence(startIndex, endIndex)
|
||||
|
||||
override fun contentToString(): String {
|
||||
return "[戳一戳]"
|
||||
}
|
||||
|
||||
override fun compareTo(other: String): Int = stringValue.compareTo(other)
|
||||
|
||||
//businessType=0x00000001(1)
|
||||
@ -146,9 +150,10 @@ sealed class FlashImage : MessageContent, HummerMessage() {
|
||||
override fun get(index: Int) = stringValue!![index]
|
||||
override fun subSequence(startIndex: Int, endIndex: Int) = stringValue!!.subSequence(startIndex, endIndex)
|
||||
override fun compareTo(other: String) = other.compareTo(stringValue!!)
|
||||
|
||||
override fun contentToString(): String = "[闪照]"
|
||||
}
|
||||
|
||||
@JvmSynthetic
|
||||
@SinceMirai("0.33.0")
|
||||
inline fun Image.flash(): FlashImage = FlashImage(this)
|
||||
|
||||
@ -164,7 +169,7 @@ inline fun FriendImage.flash(): FriendFlashImage = FlashImage(this) as FriendFla
|
||||
* @see FlashImage.invoke
|
||||
*/
|
||||
@SinceMirai("0.33.0")
|
||||
class GroupFlashImage @MiraiInternalAPI constructor(override val image: GroupImage) : FlashImage() {
|
||||
class GroupFlashImage(override val image: GroupImage) : FlashImage() {
|
||||
companion object Key : Message.Key<GroupFlashImage>
|
||||
}
|
||||
|
||||
@ -172,6 +177,6 @@ class GroupFlashImage @MiraiInternalAPI constructor(override val image: GroupIma
|
||||
* @see FlashImage.invoke
|
||||
*/
|
||||
@SinceMirai("0.33.0")
|
||||
class FriendFlashImage @MiraiInternalAPI constructor(override val image: FriendImage) : FlashImage() {
|
||||
class FriendFlashImage(override val image: FriendImage) : FlashImage() {
|
||||
companion object Key : Message.Key<FriendFlashImage>
|
||||
}
|
||||
|
@ -81,6 +81,7 @@ sealed class AbstractImage : Image {
|
||||
|
||||
override fun compareTo(other: String): Int = _stringValue!!.compareTo(other)
|
||||
final override fun toString(): String = _stringValue!!
|
||||
final override fun contentToString(): String = "[图片]"
|
||||
}
|
||||
|
||||
// region 在线图片
|
||||
|
@ -13,6 +13,9 @@ package net.mamoe.mirai.message.data
|
||||
|
||||
import net.mamoe.mirai.contact.Contact
|
||||
import net.mamoe.mirai.message.MessageReceipt
|
||||
import net.mamoe.mirai.utils.MiraiExperimentalAPI
|
||||
import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||
import net.mamoe.mirai.utils.SinceMirai
|
||||
import kotlin.jvm.JvmSynthetic
|
||||
|
||||
/**
|
||||
@ -95,21 +98,38 @@ interface Message {
|
||||
* println(c) // "Hello world!"
|
||||
* ```
|
||||
*/
|
||||
@Suppress("DEPRECATION_ERROR")
|
||||
@OptIn(MiraiInternalAPI::class)
|
||||
@JvmSynthetic // in java they should use `plus` instead
|
||||
fun followedBy(tail: Message): CombinedMessage {
|
||||
if (this is ConstrainSingle<*> && tail is ConstrainSingle<*>
|
||||
&& this.key == tail.key
|
||||
) {
|
||||
return CombinedMessage(EmptyMessageChain, this)
|
||||
}
|
||||
return CombinedMessage(left = this, tail = tail)
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为易辨识的字符串.
|
||||
* 得到包含 mirai 消息元素代码的, 易读的字符串. 如 `At(member) + "test"` 将转为 `"[mirai:at:qqId]test"`
|
||||
*
|
||||
* 各个 [SingleMessage] 的转换示例:
|
||||
* [PlainText]: "Hello"
|
||||
* [GroupImage]: "[mirai:{01E9451B-70ED-EAE3-B37C-101F1EEBF5B5}.png]"
|
||||
* [FriendImage]: ""
|
||||
* [GroupImage]: "[mirai:image:{01E9451B-70ED-EAE3-B37C-101F1EEBF5B5}.png]"
|
||||
* [FriendImage]: "[mirai:image:/f8f1ab55-bf8e-4236-b55e-955848d7069f]"
|
||||
* [PokeMessage]: "[mirai:poke:1,-1]"
|
||||
* [MessageChain]: 直接无间隔地连接所有元素.
|
||||
*/
|
||||
override fun toString(): String
|
||||
|
||||
/**
|
||||
* 转为最接近官方格式的字符串. 如 `At(member) + "test"` 将转为 `"@群名片 test"`.
|
||||
* 对于 [NullMessageChain], 这个函数返回空字符串 ""
|
||||
* 对于其他 [MessageChain], 这个函数返回值同 [toString]
|
||||
*/
|
||||
@SinceMirai("0.34.0")
|
||||
fun contentToString(): String
|
||||
|
||||
operator fun plus(another: Message): CombinedMessage = this.followedBy(another)
|
||||
|
||||
// avoid resolution ambiguity
|
||||
@ -147,6 +167,17 @@ interface MessageMetadata : SingleMessage {
|
||||
override fun compareTo(other: String): Int = "".compareTo(other)
|
||||
}
|
||||
|
||||
/**
|
||||
* 约束一个 [MessageChain] 中只存在这一种类型的元素. 新元素将会替换旧元素, 但不会保持原顺序.
|
||||
*
|
||||
* **MiraiExperimentalAPI**: 此 API 可能在将来版本修改
|
||||
*/
|
||||
@SinceMirai("0.34.0")
|
||||
@MiraiExperimentalAPI
|
||||
interface ConstrainSingle<M : Message> {
|
||||
val key: Message.Key<M>
|
||||
}
|
||||
|
||||
/**
|
||||
* 消息内容
|
||||
*/
|
||||
|
@ -46,11 +46,6 @@ import kotlin.reflect.KProperty
|
||||
interface MessageChain : Message, Iterable<SingleMessage> {
|
||||
override operator fun contains(sub: String): Boolean
|
||||
|
||||
/**
|
||||
* 得到易读的字符串
|
||||
*/
|
||||
override fun toString(): String
|
||||
|
||||
/**
|
||||
* 元素数量
|
||||
*/
|
||||
@ -100,7 +95,7 @@ interface MessageChain : Message, Iterable<SingleMessage> {
|
||||
// region accessors
|
||||
|
||||
/**
|
||||
* 遍历每一个有内容的消息, 即 [At], [AtAll], [PlainText], [Image], [Face], [XmlMessage], [QuoteReply]
|
||||
* 遍历每一个有内容的消息, 即 [At], [AtAll], [PlainText], [Image], [Face], [XmlMessage], [PokeMessage], [FlashImage]
|
||||
*/
|
||||
@JvmSynthetic
|
||||
inline fun MessageChain.foreachContent(block: (Message) -> Unit) {
|
||||
@ -289,6 +284,7 @@ inline fun MessageChain.asMessageChain(): MessageChain = this // 避免套娃
|
||||
|
||||
@JvmSynthetic
|
||||
fun CombinedMessage.asMessageChain(): MessageChain {
|
||||
@OptIn(MiraiExperimentalAPI::class)
|
||||
if (left is SingleMessage && this.tail is SingleMessage) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return (this as Iterable<SingleMessage>).asMessageChain()
|
||||
@ -385,12 +381,13 @@ inline fun Sequence<SingleMessage>.flatten(): Sequence<SingleMessage> = this //
|
||||
fun Message.flatten(): Sequence<SingleMessage> {
|
||||
return when (this) {
|
||||
is MessageChain -> this.asSequence()
|
||||
is CombinedMessage -> this.flatten()
|
||||
is CombinedMessage -> this.flatten() // already constrained single.
|
||||
else -> sequenceOf(this as SingleMessage)
|
||||
}
|
||||
}
|
||||
|
||||
fun CombinedMessage.flatten(): Sequence<SingleMessage> {
|
||||
// already constrained single.
|
||||
if (this.isFlat()) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return (this as Iterable<SingleMessage>).asSequence()
|
||||
@ -415,9 +412,13 @@ object EmptyMessageChain : MessageChain by MessageChainImplByCollection(emptyLis
|
||||
*/
|
||||
object NullMessageChain : MessageChain {
|
||||
override fun toString(): String = "NullMessageChain"
|
||||
override fun contentToString(): String = ""
|
||||
override val size: Int get() = 0
|
||||
override fun equals(other: Any?): Boolean = other === this
|
||||
override fun contains(sub: String): Boolean = error("accessing NullMessageChain")
|
||||
|
||||
@OptIn(MiraiInternalAPI::class)
|
||||
@Suppress("DEPRECATION_ERROR")
|
||||
override fun followedBy(tail: Message): CombinedMessage = CombinedMessage(left = EmptyMessageChain, tail = tail)
|
||||
override fun iterator(): MutableIterator<SingleMessage> = error("accessing NullMessageChain")
|
||||
}
|
||||
@ -439,6 +440,8 @@ internal class MessageChainImplByIterable constructor(
|
||||
override fun toString(): String =
|
||||
toStringTemp ?: this.delegate.joinToString("") { it.toString() }.also { toStringTemp = it }
|
||||
|
||||
override fun contentToString(): String = toString()
|
||||
|
||||
override operator fun contains(sub: String): Boolean = delegate.any { it.contains(sub) }
|
||||
}
|
||||
|
||||
@ -455,6 +458,8 @@ internal class MessageChainImplByCollection constructor(
|
||||
override fun toString(): String =
|
||||
toStringTemp ?: this.delegate.joinToString("") { it.toString() }.also { toStringTemp = it }
|
||||
|
||||
override fun contentToString(): String = toString()
|
||||
|
||||
override operator fun contains(sub: String): Boolean = delegate.any { it.contains(sub) }
|
||||
}
|
||||
|
||||
@ -476,6 +481,8 @@ internal class MessageChainImplBySequence constructor(
|
||||
override fun toString(): String =
|
||||
toStringTemp ?: this.collected.joinToString("") { it.toString() }.also { toStringTemp = it }
|
||||
|
||||
override fun contentToString(): String = toString()
|
||||
|
||||
override operator fun contains(sub: String): Boolean = collected.any { it.contains(sub) }
|
||||
}
|
||||
|
||||
@ -488,6 +495,7 @@ internal class SingleMessageChainImpl constructor(
|
||||
) : Message, Iterable<SingleMessage>, MessageChain {
|
||||
override val size: Int get() = 1
|
||||
override fun toString(): String = this.delegate.toString()
|
||||
override fun contentToString(): String = this.delegate.toString()
|
||||
override fun iterator(): Iterator<SingleMessage> = iterator { yield(delegate) }
|
||||
override operator fun contains(sub: String): Boolean = sub in delegate
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import net.mamoe.mirai.message.ContactMessage
|
||||
import net.mamoe.mirai.message.MessageReceipt
|
||||
import net.mamoe.mirai.recallIn
|
||||
import net.mamoe.mirai.utils.LazyProperty
|
||||
import net.mamoe.mirai.utils.MiraiExperimentalAPI
|
||||
import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||
import net.mamoe.mirai.utils.SinceMirai
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
@ -31,9 +32,7 @@ import kotlin.jvm.JvmSynthetic
|
||||
/**
|
||||
* 消息源, 它存在于 [MessageChain] 中, 用于表示这个消息的来源.
|
||||
*
|
||||
* 消息源只用于 [引用回复][QuoteReply] 或 [撤回][Bot.recall].
|
||||
*
|
||||
* `mirai-core-qqandroid`: `net.mamoe.mirai.qqandroid.message.MessageSourceFromMsg`
|
||||
* 消息源可用于 [引用回复][QuoteReply] 或 [撤回][Bot.recall].
|
||||
*
|
||||
* @see Bot.recall 撤回一条消息
|
||||
* @see MessageSource.quote 引用这条消息, 创建 [MessageChain]
|
||||
@ -56,17 +55,24 @@ sealed class MessageSource : Message, MessageMetadata {
|
||||
abstract val id: Int // random
|
||||
|
||||
/**
|
||||
* 发送时间, 单位为秒. 撤回好友消息时可能需要
|
||||
* 发送时间时间戳, 单位为秒.
|
||||
* 撤回好友消息时需要
|
||||
*/
|
||||
abstract val time: Int
|
||||
|
||||
/**
|
||||
* 发送人. 可能为机器人自己, 好友的 id, 或群 id
|
||||
* 发送人.
|
||||
* 当 [OnlineMessageSource.Outgoing] 时为 [机器人][Bot.id]
|
||||
* 当 [OnlineMessageSource.Incoming] 时为发信 [目标好友][QQ.id] 或 [群][Group.id]
|
||||
* 当 [OfflineMessageSource] 时为 [机器人][Bot.id], 发信 [目标好友][QQ.id] 或 [群][Group.id] (取决于 [OfflineMessageSource.kind])
|
||||
*/
|
||||
abstract val fromId: Long
|
||||
|
||||
/**
|
||||
* 发送目标. 可能为机器人自己, 好友的 id, 或群 id
|
||||
* 发送目标.
|
||||
* 当 [OnlineMessageSource.Outgoing] 时为发信 [目标好友][QQ.id] 或 [群][Group.id]
|
||||
* 当 [OnlineMessageSource.Incoming] 时为 [机器人][Bot.id]
|
||||
* 当 [OfflineMessageSource] 时为 [机器人][Bot.id], 发信 [目标好友][QQ.id] 或 [群][Group.id] (取决于 [OfflineMessageSource.kind])
|
||||
*/
|
||||
abstract val targetId: Long // groupCode / friendUin
|
||||
|
||||
@ -76,7 +82,8 @@ sealed class MessageSource : Message, MessageMetadata {
|
||||
@LazyProperty
|
||||
abstract val originalMessage: MessageChain
|
||||
|
||||
final override fun toString(): String = ""
|
||||
final override fun toString(): String = "[mirai:source:$id]"
|
||||
final override fun contentToString(): String = ""
|
||||
}
|
||||
|
||||
// ONLINE
|
||||
@ -96,9 +103,12 @@ sealed class MessageSource : Message, MessageMetadata {
|
||||
* 当机器人接收一条消息 [ContactMessage], 这条消息包含一个 [内向消息源][OnlineMessageSource.Incoming], 代表着接收到的这条消息的来源.
|
||||
*/
|
||||
@SinceMirai("0.33.0")
|
||||
sealed class OnlineMessageSource : MessageSource() {
|
||||
@OptIn(MiraiExperimentalAPI::class)
|
||||
sealed class OnlineMessageSource : MessageSource(), ConstrainSingle<OnlineMessageSource> {
|
||||
companion object Key : Message.Key<OnlineMessageSource>
|
||||
|
||||
override val key: Message.Key<OnlineMessageSource> get() = Key
|
||||
|
||||
/**
|
||||
* 消息发送人. 可能为 [机器人][Bot] 或 [好友][QQ] 或 [群员][Member].
|
||||
* 即类型必定为 [Bot], [QQ] 或 [Member]
|
||||
|
@ -32,6 +32,7 @@ class PlainText(val stringValue: String) :
|
||||
|
||||
override operator fun contains(sub: String): Boolean = sub in stringValue
|
||||
override fun toString(): String = stringValue
|
||||
override fun contentToString(): String = stringValue
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return other is PlainText && other.stringValue == this.stringValue
|
||||
|
@ -15,6 +15,7 @@ package net.mamoe.mirai.message.data
|
||||
|
||||
import kotlinx.coroutines.Job
|
||||
import net.mamoe.mirai.message.MessageReceipt
|
||||
import net.mamoe.mirai.utils.MiraiExperimentalAPI
|
||||
import net.mamoe.mirai.utils.SinceMirai
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
@ -30,12 +31,16 @@ import kotlin.jvm.JvmName
|
||||
*
|
||||
* @see MessageSource 获取更多信息
|
||||
*/
|
||||
@OptIn(MiraiExperimentalAPI::class)
|
||||
@SinceMirai("0.33.0")
|
||||
class QuoteReply(val source: MessageSource) : Message, MessageMetadata {
|
||||
class QuoteReply(val source: MessageSource) : Message, MessageMetadata, ConstrainSingle<QuoteReply> {
|
||||
// TODO: 2020/4/4 Metadata or Content?
|
||||
companion object Key : Message.Key<QuoteReply>
|
||||
|
||||
override val key: Message.Key<QuoteReply> get() = Key
|
||||
|
||||
override fun toString(): String = "[mirai:quote:${source.id}]"
|
||||
override fun contentToString(): String = ""
|
||||
}
|
||||
|
||||
suspend inline fun QuoteReply.recall() = this.source.recall()
|
||||
|
@ -31,6 +31,8 @@ import kotlin.jvm.JvmSynthetic
|
||||
@SinceMirai("0.27.0")
|
||||
interface RichMessage : MessageContent {
|
||||
|
||||
override fun contentToString(): String = this.content
|
||||
|
||||
@SinceMirai("0.30.0")
|
||||
companion object Templates : Message.Key<RichMessage> {
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user