diff --git a/README.md b/README.md index a0f5883..6b0eadb 100644 --- a/README.md +++ b/README.md @@ -105,17 +105,37 @@ fun main() { # 消息构造器 +## 链式调用构造消息 + > 框架支持使用链式调用的方式构造一个消息, 以下是一个简单的示例, 也可以直接使用字符串的形式发送 ```kotlin val msgChain = MessageChain.Builder() .addAt(message.sender.userId) .addText(message.rawMessage) - .addNewLine(3) // repeat 3 times: append 3 \n to end + .addNewLine(3) // 添加3个换行符到末尾 .build() this.sendGroupMessage(message.groupId, msgChain) ``` +## 操作符重载构造消息 + +```kotlin +fun main() { + // 可以直接对一个链式调用构造的消息使用操作符重载 + val chain = MessageChain.Builder().addText("1").build() + Text("") + println(chain) + val operator = AT(3458671395) + + Text("114514") + + Image("https://example.com/example.png") + + Reply(114514L) + + Face(666) + + NewLine() + + "1919810" + println(operator) +} +``` + # 消息即对象 > 你可以对一个消息对象执行某些操作例如 撤回(revoke/recall) 回复(reply) diff --git a/gradle.properties b/gradle.properties index 194cf05..49b828a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,2 @@ kotlin.code.style=official -libVersion=2.4.1 \ No newline at end of file +libVersion=2.4.2 \ No newline at end of file diff --git a/onebot/src/main/kotlin/cn/rtast/rob/segment/BaseSegment.kt b/onebot/src/main/kotlin/cn/rtast/rob/segment/BaseSegment.kt deleted file mode 100644 index f117716..0000000 --- a/onebot/src/main/kotlin/cn/rtast/rob/segment/BaseSegment.kt +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright © 2024 RTAkland - * Author: RTAkland - * Date: 2024/9/2 - */ - - -package cn.rtast.rob.segment - -import cn.rtast.rob.enums.ArrayMessageType - -/** - * 内部使用的Segment作为超类 - */ -internal interface InternalBaseSegment { - val type: ArrayMessageType -} - -/** - * 用户可以使用的Segment作为超类 - */ -interface Segment \ No newline at end of file diff --git a/onebot/src/main/kotlin/cn/rtast/rob/segment/InternalMessageSegment.kt b/onebot/src/main/kotlin/cn/rtast/rob/segment/InternalMessageSegment.kt index eb2f362..fe13b96 100644 --- a/onebot/src/main/kotlin/cn/rtast/rob/segment/InternalMessageSegment.kt +++ b/onebot/src/main/kotlin/cn/rtast/rob/segment/InternalMessageSegment.kt @@ -10,6 +10,13 @@ package cn.rtast.rob.segment import cn.rtast.rob.enums.ArrayMessageType import cn.rtast.rob.enums.internal.ContactType +/** + * 内部使用的Segment作为超类 + */ +internal interface InternalBaseSegment { + val type: ArrayMessageType +} + internal data class IPlainText( val data: Data, override val type: ArrayMessageType = ArrayMessageType.text diff --git a/onebot/src/main/kotlin/cn/rtast/rob/segment/MessageSegment.kt b/onebot/src/main/kotlin/cn/rtast/rob/segment/MessageSegment.kt index 77d6ff1..e5f3577 100644 --- a/onebot/src/main/kotlin/cn/rtast/rob/segment/MessageSegment.kt +++ b/onebot/src/main/kotlin/cn/rtast/rob/segment/MessageSegment.kt @@ -11,38 +11,109 @@ import cn.rtast.rob.enums.MusicShareType import cn.rtast.rob.enums.PokeMessage import cn.rtast.rob.enums.QQFace -data class Text(val text: String) : Segment -data class AT(val qq: Long) : Segment -data class Face(val id: Int) : Segment -data class QFace(val id: QQFace) : Segment -data class Image(val file: String, val base64: Boolean = false) : Segment -data class Record(val file: String) : Segment -data class Video(val file: String) : Segment -data class Poke(val poke: PokeMessage) : Segment -data class Reply(val id: Long) : Segment -data class XML(val xml: String) : Segment -data class FriendContact(val id: Long) : Segment -data class GroupContact(val id: Long) : Segment -data class JSON(val json: String) : Segment -data class MusicShare(val type: MusicShareType, val id: String) : Segment -class Rps : Segment -class Dice : Segment -class Shake : Segment +/** + * 非内部类, Segment作为超类 + */ +sealed class Segment + +/** + * 纯文本 + */ +data class Text(val text: String) : Segment() + +/** + * AT某人 + */ +data class AT(val qq: Long) : Segment() + +/** + * 表情但是使用整形来构造 + */ +data class Face(val id: Int) : Segment() + +/** + * 表情但是用[QQFace]来构造 + */ +data class QFace(val id: QQFace) : Segment() + +/** + * 图片 + */ +data class Image(val file: String, val base64: Boolean = false) : Segment() + +/** + * 语音 + */ +data class Record(val file: String) : Segment() + +/** + * 视频 + */ +data class Video(val file: String) : Segment() + +/** + * 戳一戳(旧版) + */ +data class Poke(val poke: PokeMessage) : Segment() + +/** + * 回复 + */ +data class Reply(val id: Long) : Segment() + +/** + * XML消息 + */ +data class XML(val xml: String) : Segment() + +/** + * 好友推荐 + */ +data class FriendContact(val id: Long) : Segment() + +/** + * 群聊推荐 + */ +data class GroupContact(val id: Long) : Segment() + +/** + * JSON消息 + */ +data class JSON(val json: String) : Segment() + +/** + * 消息分享 + */ +data class MusicShare(val type: MusicShareType, val id: String) : Segment() + +/** + * 插入换行符 + */ +data class NewLine(val times: Int = 1) : Segment() + +/** + * 链接分享 + */ data class Share( val url: String, val title: String, val content: String? = null, val image: String? = null -) : Segment - +) : Segment() +/** + * 位置分享 + */ data class Location( val lat: Double, val lon: Double, val title: String? = null, val content: String? = null, -) : Segment +) : Segment() +/** + * 自定义音乐分享 + */ data class CustomMusicShare( val url: String, val audio: String, @@ -50,4 +121,52 @@ data class CustomMusicShare( val content: String? = null, val image: String? = null, val type: String = "custom", -) : Segment \ No newline at end of file +) : Segment() + +/** + * 剪刀石头布 + */ +class Rps : Segment() { + override fun toString() = "Rps" + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is Rps) return false + return true + } + + override fun hashCode(): Int { + return javaClass.hashCode() + } +} + +/** + * 骰子 + */ +class Dice : Segment() { + override fun toString() = "Dice" + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is Dice) return false + return true + } + + override fun hashCode(): Int { + return javaClass.hashCode() + } +} + +/** + * 屏震(旧版) + */ +class Shake : Segment() { + override fun toString() = "Shake" + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is Shake) return false + return true + } + + override fun hashCode(): Int { + return javaClass.hashCode() + } +} \ No newline at end of file diff --git a/onebot/src/main/kotlin/cn/rtast/rob/util/ob/MessageChain.kt b/onebot/src/main/kotlin/cn/rtast/rob/util/ob/MessageChain.kt index d97c2f8..1244016 100644 --- a/onebot/src/main/kotlin/cn/rtast/rob/util/ob/MessageChain.kt +++ b/onebot/src/main/kotlin/cn/rtast/rob/util/ob/MessageChain.kt @@ -41,6 +41,7 @@ import cn.rtast.rob.segment.InternalBaseSegment import cn.rtast.rob.segment.JSON import cn.rtast.rob.segment.Location import cn.rtast.rob.segment.MusicShare +import cn.rtast.rob.segment.NewLine import cn.rtast.rob.segment.Poke import cn.rtast.rob.segment.QFace import cn.rtast.rob.segment.Record @@ -182,13 +183,6 @@ operator fun MessageChain.plus(other: Any): MessageChain { return this.finalArrayMsgList.add(IPlainText(IPlainText.Data(other.toString()))).toMessageChain() } -/** - * 对一个构造好的[MessageChain]使用+操作符快速添加一个[IAT]类型的消息段 - */ -operator fun MessageChain.plus(other: Long): MessageChain { - return this.finalArrayMsgList.add(IAT(IAT.Data(other.toString()))).toMessageChain() -} - /** * 将一个手动构造的Segment拼接成一个MessageChain */ @@ -198,7 +192,6 @@ operator fun Segment.plus(other: Segment): MessageChain { is Text -> msg.addText(this.text) is AT -> msg.addAt(this.qq) is Face -> msg.addFace(this.id) - is QFace -> msg.addFace(this.id) is Image -> msg.addImage(this.file, base64) is Record -> msg.addRecord(this.file) is Video -> msg.addVideo(this.file) @@ -215,6 +208,8 @@ operator fun Segment.plus(other: Segment): MessageChain { is Share -> msg.addShare(this.url, this.title, this.content, this.image) is Location -> msg.addLocation(this.lat, this.lon, this.title, this.content) is CustomMusicShare -> msg.addCustomMusicShare(this.url, this.audio, this.title, this.content, this.image) + is NewLine -> msg.addNewLine(this.times) + is QFace -> msg.addFace(this.id) } when (other) { is Text -> msg.addText(other.text) @@ -236,6 +231,8 @@ operator fun Segment.plus(other: Segment): MessageChain { is Share -> msg.addShare(other.url, other.title, other.content, other.image) is Location -> msg.addLocation(other.lat, other.lon, other.title, other.content) is CustomMusicShare -> msg.addCustomMusicShare(other.url, other.audio, other.title, other.content, other.image) + is NewLine -> msg.addNewLine(other.times) + is QFace -> msg.addFace(other.id) } return msg.build() } @@ -251,6 +248,20 @@ operator fun MessageChain.plus(segment: Segment): MessageChain { return newBuilder.build() } +/** + * [Segment]+[String]拼接 + */ +operator fun Segment.plus(other: String): MessageChain { + return MessageChain.Builder().addSegment(this).addText(other).build() +} + +/** + * [String]+[Segment]拼接 + */ +operator fun String.plus(other: Segment): MessageChain { + return MessageChain.Builder().addText(this).addSegment(other).build() +} + /** * 快速构造一个数组形式的消息链 * 支持绝大部分的消息链(Segment) @@ -505,6 +516,8 @@ class MessageChain internal constructor(arrayMessageList: MutableList addDice() is Shake -> addShake() is Share -> addShare(segment.url, segment.title, segment.content, segment.image) + is NewLine -> addNewLine(segment.times) + is QFace -> addFace(segment.id) is Location -> addLocation( segment.lat.toDouble(), segment.lon.toDouble(), diff --git a/onebot/src/test/kotlin/test/MessageChainTest.kt b/onebot/src/test/kotlin/test/MessageChainTest.kt index 279b2c9..1ef9a8c 100644 --- a/onebot/src/test/kotlin/test/MessageChainTest.kt +++ b/onebot/src/test/kotlin/test/MessageChainTest.kt @@ -7,12 +7,25 @@ package test import cn.rtast.rob.segment.AT +import cn.rtast.rob.segment.Face +import cn.rtast.rob.segment.Image +import cn.rtast.rob.segment.NewLine +import cn.rtast.rob.segment.Reply import cn.rtast.rob.segment.Text import cn.rtast.rob.util.ob.MessageChain import cn.rtast.rob.util.ob.plus fun main() { - MessageChain.Builder().addText("1").build() + Text("") - println((AT(3458671395) + Text("") + Text("1111") + Text("1111"))) + // 可以直接对一个链式调用构造的消息使用操作符重载 + val chain = MessageChain.Builder().addText("1").build() + Text("") + println(chain) + val operator = AT(3458671395) + + Text("114514") + + Image("https://example.com/example.png") + + Reply(114514L) + + Face(666) + + NewLine() + + "" + println(operator) }