Commit ac6f411e authored by Him188's avatar Him188

Add `equals` and `hashCode` to `Message`s

parent db8cb84c
......@@ -29,7 +29,8 @@ import kotlin.jvm.JvmSynthetic
*
* @see AtAll 全体成员
*/
class At
data class At
@Suppress("DataClassPrivateConstructor")
private constructor(val target: Long, val display: String) :
MessageContent,
CharSequence by display,
......@@ -40,6 +41,10 @@ private constructor(val target: Long, val display: String) :
*/
constructor(member: Member) : this(member.id, "@${member.nameCardOrNick}")
override fun equals(other: Any?): Boolean {
return other is At && other.target == this.target && other.display == this.display
}
override fun toString(): String = "[mirai:at:$target]"
override fun contentToString(): String = this.display
......@@ -57,6 +62,20 @@ private constructor(val target: Long, val display: String) :
}
// 自动为消息补充 " "
override fun followedBy(tail: Message): MessageChain {
if (tail is PlainText && tail.stringValue.startsWith(' ')) {
return super.followedBy(tail)
}
return super.followedBy(PlainText(" ")) + tail
}
override fun hashCode(): Int {
var result = target.hashCode()
result = 31 * result + display.hashCode()
return result
}
@OptIn(MiraiInternalAPI::class)
@Suppress("INAPPLICABLE_JVM_NAME", "EXPOSED_FUNCTION_RETURN_TYPE")
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
......@@ -65,13 +84,6 @@ private constructor(val target: Long, val display: String) :
override fun followedBy1(tail: Message): CombinedMessage {
return followedByInternalForBinaryCompatibility(tail)
}
override fun followedBy(tail: Message): MessageChain {
if (tail is PlainText && tail.stringValue.startsWith(' ')) {
return super.followedBy(tail)
}
return super.followedBy(PlainText(" ")) + tail
}
}
/**
......
......@@ -41,6 +41,13 @@ object AtAll :
@Suppress("SpellCheckingInspection")
override fun toString(): String = "[mirai:atall]"
override fun contentToString(): String = display
override fun equals(other: Any?): Boolean {
return other === this
}
override fun hashCode(): Int {
return display.hashCode()
}
// 自动为消息补充 " "
@OptIn(MiraiInternalAPI::class)
......
......@@ -14,6 +14,7 @@ package net.mamoe.mirai.message.data
import net.mamoe.mirai.utils.MiraiExperimentalAPI
import net.mamoe.mirai.utils.MiraiInternalAPI
import kotlin.jvm.JvmField
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic
......@@ -30,8 +31,8 @@ import kotlin.jvm.JvmSynthetic
*/
internal class CombinedMessage
internal constructor(
internal val left: Message, // 必须已经完成 constrain single
internal val tail: Message
@JvmField internal val left: Message, // 必须已经完成 constrain single
@JvmField internal val tail: Message
) : Message, MessageChain {
@OptIn(MiraiExperimentalAPI::class)
fun asSequence(): Sequence<SingleMessage> = sequence {
......@@ -49,6 +50,10 @@ internal constructor(
size
}
override fun equals(other: Any?): Boolean {
return other is CombinedMessage && other.left == this.left && other.tail == this.tail
}
@OptIn(MiraiExperimentalAPI::class)
override fun toString(): String {
return tail.toString() + left.toString()
......@@ -57,6 +62,12 @@ internal constructor(
override fun contentToString(): String {
return left.contentToString() + tail.contentToString()
}
override fun hashCode(): Int {
var result = left.hashCode()
result = 31 * result + tail.hashCode()
return result
}
}
@JvmSynthetic
......
......@@ -18,15 +18,19 @@ import kotlin.jvm.JvmName
/**
* QQ 自带表情
*/
class Face private constructor(val id: Int, private val stringValue: String) :
data class Face
@Suppress("DataClassPrivateConstructor")
private constructor(val id: Int, private val stringValue: String) : // used in delegation
MessageContent,
CharSequence by stringValue, Comparable<String> by stringValue {
constructor(id: Int) : this(id, "[mirai:face:$id]")
override fun toString(): String = stringValue
override fun contentToString(): String = "[表情]"
override fun equals(other: Any?): Boolean = other is Face && other.id == this.id
override fun hashCode(): Int = id
/**
* @author LamGC
*/
......
......@@ -43,7 +43,7 @@ sealed class HummerMessage : MessageContent {
*/
@SinceMirai("0.31.0")
@OptIn(MiraiInternalAPI::class)
class PokeMessage @MiraiInternalAPI(message = "使用伴生对象中的常量") constructor(
data class PokeMessage @MiraiInternalAPI(message = "使用伴生对象中的常量") constructor(
@MiraiExperimentalAPI
val type: Int,
@MiraiExperimentalAPI
......@@ -87,12 +87,21 @@ class PokeMessage @MiraiInternalAPI(message = "使用伴生对象中的常量")
override fun subSequence(startIndex: Int, endIndex: Int): CharSequence =
stringValue.subSequence(startIndex, endIndex)
override fun contentToString(): String {
return "[戳一戳]"
}
override fun contentToString(): String = "[戳一戳]"
@OptIn(MiraiExperimentalAPI::class)
override fun equals(other: Any?): Boolean = other is PokeMessage && other.type == this.type && other.id == this.id
override fun compareTo(other: String): Int = stringValue.compareTo(other)
@OptIn(MiraiExperimentalAPI::class)
override fun hashCode(): Int {
var result = type
result = 31 * result + id
result = 31 * result + stringValue.hashCode()
return result
}
//businessType=0x00000001(1)
//pbElem=08 01 18 00 20 FF FF FF FF 0F 2A 00 32 00 38 00 50 00
//serviceType=0x00000002(2)
......@@ -178,7 +187,7 @@ inline fun FriendImage.flash(): FriendFlashImage = FlashImage(this) as FriendFla
* @see FlashImage.invoke
*/
@SinceMirai("0.33.0")
class GroupFlashImage(override val image: GroupImage) : FlashImage() {
data class GroupFlashImage(override val image: GroupImage) : FlashImage() {
companion object Key : Message.Key<GroupFlashImage> {
override val typeName: String
get() = "GroupFlashImage"
......@@ -189,7 +198,7 @@ class GroupFlashImage(override val image: GroupImage) : FlashImage() {
* @see FlashImage.invoke
*/
@SinceMirai("0.33.0")
class FriendFlashImage(override val image: FriendImage) : FlashImage() {
data class FriendFlashImage(override val image: FriendImage) : FlashImage() {
companion object Key : Message.Key<FriendFlashImage> {
override val typeName: String
get() = "FriendFlashImage"
......
......@@ -212,7 +212,7 @@ data class OfflineGroupImage(
}
override fun equals(other: Any?): Boolean {
return other is OfflineGroupImage && other.md5.contentEquals(this.md5) && other.filepath == this.filepath
return other is OfflineGroupImage && other::class == this::class && other.md5.contentEquals(this.md5) && other.filepath == this.filepath
}
}
......@@ -276,8 +276,8 @@ data class OfflineFriendImage(
}
override fun equals(other: Any?): Boolean {
return other is OfflineFriendImage && other.md5
.contentEquals(this.md5) && other.resourceId == this.resourceId
return other is OfflineFriendImage && other::class == this::class &&
other.md5.contentEquals(this.md5) && other.resourceId == this.resourceId
}
}
......@@ -290,7 +290,10 @@ abstract class OnlineFriendImage : FriendImage(), OnlineImage
// endregion
//////////////////////
// region internal
//////////////////////
private val EMPTY_BYTE_ARRAY = ByteArray(0)
......
......@@ -100,8 +100,6 @@ interface Message {
* ```
*/
@SinceMirai("0.34.0")
@Suppress("DEPRECATION_ERROR")
@OptIn(MiraiInternalAPI::class)
@JvmSynthetic // in java they should use `plus` instead
fun followedBy(tail: Message): MessageChain = followedByImpl(tail)
......
......@@ -373,6 +373,7 @@ object EmptyMessageChain : MessageChain, Iterator<SingleMessage> {
override val size: Int get() = 0
override fun toString(): String = ""
override fun contentToString(): String = ""
override fun equals(other: Any?): Boolean = other === this
override fun iterator(): Iterator<SingleMessage> = this
override fun hasNext(): Boolean = false
......
......@@ -22,7 +22,7 @@ import kotlin.jvm.JvmSynthetic
*
* 一般不需要主动构造 [PlainText], [Message] 可直接与 [String] 相加. Java 用户请使用 [MessageChain.plus]
*/
class PlainText(val stringValue: String) :
data class PlainText(val stringValue: String) :
MessageContent,
Comparable<String> by stringValue,
CharSequence by stringValue {
......@@ -33,14 +33,6 @@ class PlainText(val stringValue: String) :
override fun toString(): String = stringValue
override fun contentToString(): String = stringValue
override fun equals(other: Any?): Boolean {
return other is PlainText && other.stringValue == this.stringValue
}
override fun hashCode(): Int {
return stringValue.hashCode()
}
companion object Key : Message.Key<PlainText> {
override val typeName: String
get() = "PlainText"
......
......@@ -46,6 +46,8 @@ class QuoteReply(val source: MessageSource) : Message, MessageMetadata, Constrai
override fun toString(): String = "[mirai:quote:${source.id}]"
override fun contentToString(): String = ""
override fun equals(other: Any?): Boolean = other is QuoteReply && other.source == this.source
override fun hashCode(): Int = source.hashCode()
}
@get:JvmSynthetic
......
......@@ -33,6 +33,7 @@ interface RichMessage : MessageContent {
override fun contentToString(): String = this.content
@MiraiExperimentalAPI
@SinceMirai("0.30.0")
companion object Templates : Message.Key<RichMessage> {
......@@ -77,7 +78,7 @@ interface RichMessage : MessageContent {
* @param content 一般是 json
*/
@SinceMirai("0.27.0")
class LightApp constructor(override val content: String) : RichMessage {
data class LightApp(override val content: String) : RichMessage {
companion object Key : Message.Key<LightApp> {
override val typeName: String get() = "LightApp"
}
......@@ -97,6 +98,19 @@ open class ServiceMessage(@MiraiExperimentalAPI val serviceId: Int, final overri
}
final override fun toString(): String = "[mirai:service:$serviceId,$content]"
final override fun equals(other: Any?): Boolean {
if (other == null) return false
if (other::class != this::class) return false
other as ServiceMessage
return other.serviceId == this.serviceId && other.content == this.content
}
final override fun hashCode(): Int {
var result = serviceId
result = 31 * result + content.hashCode()
return result
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment