Make SingleMessage implement CharSequence and Iterable<String>

This commit is contained in:
Him188 2020-03-23 19:39:40 +08:00
parent 83064d0c37
commit bb9d2fb322
8 changed files with 75 additions and 27 deletions

View File

@ -29,7 +29,10 @@ import kotlin.jvm.JvmSynthetic
* @see AtAll 全体成员
*/
class At
private constructor(val target: Long, val display: String) : Message, MessageContent {
private constructor(val target: Long, val display: String) :
MessageContent,
CharSequence by display,
Comparable<String> by display {
/**
* 构造一个 [At] 实例. 这是唯一的公开的构造方式.
@ -52,9 +55,9 @@ private constructor(val target: Long, val display: String) : Message, MessageCon
override fun followedBy(tail: Message): CombinedMessage {
if (tail is PlainText && tail.stringValue.startsWith(' ')) {
return super<MessageContent>.followedBy(tail)
return super.followedBy(tail)
}
return super<MessageContent>.followedBy(PlainText(" ")) + tail
return super.followedBy(PlainText(" ")) + tail
}
}

View File

@ -15,6 +15,8 @@ package net.mamoe.mirai.message.data
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
private const val display = "@全体成员"
/**
* "@全体成员".
*
@ -22,15 +24,20 @@ import kotlin.jvm.JvmName
*
* @see At at 单个群成员
*/
object AtAll : Message, Message.Key<AtAll>, MessageContent {
override fun toString(): String = "@全体成员"
object AtAll :
Message.Key<AtAll>,
MessageContent,
CharSequence by display,
Comparable<String> by display {
override fun toString(): String = display
// 自动为消息补充 " "
override fun followedBy(tail: Message): CombinedMessage {
if (tail is PlainText && tail.stringValue.startsWith(' ')) {
return super<MessageContent>.followedBy(tail)
return super.followedBy(tail)
}
return super<MessageContent>.followedBy(PlainText(" ")) + tail
return super.followedBy(PlainText(" ")) + tail
}
}

View File

@ -18,7 +18,12 @@ import kotlin.jvm.JvmName
/**
* QQ 自带表情
*/
class Face(val id: Int) : Message, MessageContent {
class Face private constructor(val id: Int, private val stringValue: String) :
MessageContent,
CharSequence by stringValue, Comparable<String> by stringValue {
constructor(id: Int) : this(id, "[mirai:face$id]")
override fun toString(): String = "[mirai:face$id]"
/**

View File

@ -44,6 +44,9 @@ interface Image : Message, MessageContent {
}
/**
* 通过 [Image.imageId] 构造一个 [Image] 以便发送.
* 这个图片必须是服务器已经存在的图片.
*
* 请查看 `ExternalImageJvm` 获取更多创建 [Image] 的方法
*/
@Suppress("FunctionName")
@ -57,9 +60,21 @@ fun Image(imageId: String): Image = when (imageId.length) {
@MiraiInternalAPI("使用 Image")
abstract class AbstractImage internal constructor() : Image {
final override fun toString(): String {
return "[mirai:$imageId]"
private var _stringValue: String? = null
get() {
return field ?: kotlin.run {
field = "[mirai:$imageId]"
field
}
}
override val length: Int get() = _stringValue!!.length
override fun get(index: Int): Char = _stringValue!![index]
override fun subSequence(startIndex: Int, endIndex: Int): CharSequence =
_stringValue!!.subSequence(startIndex, endIndex)
override fun compareTo(other: String): Int = _stringValue!!.compareTo(other)
final override fun toString(): String = _stringValue!!
}
// region 在线图片
@ -120,7 +135,9 @@ suspend inline fun OfflineImage.queryOriginUrl(): String = queryUrl()
/**
* 群图片
* 群图片.
*
* [imageId] 形如 `{01E9451B-70ED-EAE3-B37C-101F1EEBF5B5}.png` (42 长度)
*/
// CustomFace
@OptIn(MiraiInternalAPI::class)
@ -191,6 +208,8 @@ abstract class OnlineGroupImage : GroupImage(), OnlineImage
/**
* 好友图片
*
* [imageId] 形如 `/f8f1ab55-bf8e-4236-b55e-955848d7069f` (37 长度)
*/ // NotOnlineImage
@OptIn(MiraiInternalAPI::class)
sealed class FriendImage : AbstractImage() {

View File

@ -98,6 +98,14 @@ interface Message {
return CombinedMessage(tail, this)
}
/**
* 转换为易辨识的字符串.
*
* 各个 [SingleMessage] 的转换示例:
* [PlainText]: "Hello"
* [GroupImage]: "[mirai:{01E9451B-70ED-EAE3-B37C-101F1EEBF5B5}.png]"
* [FriendImage]: ""
*/
override fun toString(): String
operator fun plus(another: Message): CombinedMessage = this.followedBy(another)
@ -121,24 +129,17 @@ fun Message.repeat(count: Int): MessageChain {
inline operator fun Message.times(count: Int): MessageChain = this.repeat(count)
interface SingleMessage : Message
interface SingleMessage : Message, CharSequence, Comparable<String>
/**
* 消息元数据, 即不含内容的元素.
* 包括: [MessageSource]
*/
interface MessageMetadata : SingleMessage {
/*
fun iterator(): Iterator<Message> {
return object : Iterator<Message> {
var visited: Boolean = false
override fun hasNext(): Boolean = !visited
override fun next(): Message {
if (visited) throw NoSuchElementException()
return this@MessageMetadata.also { visited = true }
}
}
}*/
override val length: Int get() = 0
override fun get(index: Int): Char = ""[index] // produce uniform exception
override fun subSequence(startIndex: Int, endIndex: Int): CharSequence = "".subSequence(startIndex, endIndex)
override fun compareTo(other: String): Int = "".compareTo(other)
}
/**

View File

@ -23,7 +23,11 @@ import kotlin.jvm.JvmSynthetic
*
* 一般不需要主动构造 [PlainText], [Message] 可直接与 [String] 相加. Java 用户请使用 [MessageChain.plus]
*/
inline class PlainText(val stringValue: String) : Message, MessageContent {
class PlainText(val stringValue: String) :
MessageContent,
Comparable<String> by stringValue,
CharSequence by stringValue {
constructor(charSequence: CharSequence) : this(charSequence.toString())
override operator fun contains(sub: String): Boolean = sub in stringValue

View File

@ -29,10 +29,10 @@ import kotlin.jvm.JvmName
* 总是使用 [quote] 来构造这个实例.
*/
open class QuoteReply
@MiraiInternalAPI constructor(val source: MessageSource) : Message, MessageContent {
@MiraiInternalAPI constructor(val source: MessageSource) : Message, MessageMetadata {
companion object Key : Message.Key<QuoteReply>
override fun toString(): String = ""
final override fun toString(): String = ""
}
/**

View File

@ -7,15 +7,22 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
@file:JvmMultifileClass
@file:JvmName("MessageUtils")
package net.mamoe.mirai.message.data
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
import kotlin.jvm.JvmOverloads
import kotlin.jvm.JvmSynthetic
/**
* 构建一个 [MessageChain]
*
* @see MessageChainBuilder
*/
@JvmSynthetic
inline fun buildMessageChain(block: MessageChainBuilder.() -> Unit): MessageChain {
return MessageChainBuilder().apply(block).asMessageChain()
}
@ -25,6 +32,7 @@ inline fun buildMessageChain(block: MessageChainBuilder.() -> Unit): MessageChai
*
* @see MessageChainBuilder
*/
@JvmSynthetic
inline fun buildMessageChain(initialSize: Int, block: MessageChainBuilder.() -> Unit): MessageChain {
return MessageChainBuilder(initialSize).apply(block).asMessageChain()
}
@ -34,6 +42,7 @@ inline fun buildMessageChain(initialSize: Int, block: MessageChainBuilder.() ->
*
* @see MessageChainBuilder
*/
@JvmSynthetic
inline fun buildMessageChain(
container: MutableCollection<Message>,
block: MessageChainBuilder.() -> Unit