Add Message.contentEquals parameter strict for checking element properties.

This commit is contained in:
Him188 2020-12-23 18:23:17 +08:00
parent 4a8aded303
commit cce37faae9
2 changed files with 48 additions and 30 deletions

View File

@ -30,6 +30,7 @@ import net.mamoe.mirai.utils.MiraiExperimentalApi
import net.mamoe.mirai.utils.PlannedRemoval
import net.mamoe.mirai.utils.safeCast
import kotlin.contracts.contract
import kotlin.internal.LowPriorityInOverloadResolution
/**
* 可发送的或从服务器接收的消息.
@ -132,14 +133,31 @@ public interface Message { // must be interface. Don't consider any changes.
/**
* 判断内容是否与 [another] 相等.
* 判断内容是否与 [another] 相等即 `this` [another] [contentToString] 相等.
* [strict] `true` , 还会额外判断每个消息元素的类型, 顺序和属性. [Image] 会判断 [Image.imageId]
*
* 若本函数返回 `true`, 则表明:
* - `this` [another] [contentToString] 相等
* **有关 [strict]:** 每个 [Image] [contentToString] 都是 `"[图片]"`,
* [strict] `false` [contentEquals] 会得到 `true`,
* 而为 `true` 时由于 [Image.imageId] 会被比较, 两张不同的图片的 [contentEquals] 会是 `false`.
*
* @param ignoreCase `true` 时忽略大小写
*/
public fun contentEquals(another: Message, ignoreCase: Boolean = false, strict: Boolean = false): Boolean {
return if (strict) this.contentEqualsStrictImpl(another, ignoreCase)
else this.contentToString().equals(another.contentToString(), ignoreCase = ignoreCase)
}
/**
* 判断内容是否与 [another] 相等即 `this` [another] [contentToString] 相等.
*
* 单个消息的顺序和内容不会被检查, 即只要比较两个 [Image], 总是会得到 `true`, 因为 [Image] [contentToString] 都是 `"[图片]"`.
*
* @param ignoreCase `true` 时忽略大小写
*/
@LowPriorityInOverloadResolution
public fun contentEquals(another: Message, ignoreCase: Boolean = false): Boolean =
this.contentToString().equals(another.contentToString(), ignoreCase = ignoreCase)
// contentEqualsImpl(another, ignoreCase)
contentEquals(another, ignoreCase, false)
/**
* 判断内容是否与 [another] 相等.

View File

@ -38,31 +38,31 @@ private fun Message.hasDuplicationOfConstrain(key: MessageKey<*>): Boolean {
}*/
}
//@JvmSynthetic
//internal fun Message.contentEqualsImpl(another: Message, ignoreCase: Boolean): Boolean {
// if (!this.contentToString().equals(another.contentToString(), ignoreCase = ignoreCase)) return false
// return when {
// this is SingleMessage && another is SingleMessage -> true
// this is SingleMessage && another is MessageChain -> another.all { it is MessageMetadata || it is PlainText }
// this is MessageChain && another is SingleMessage -> this.all { it is MessageMetadata || it is PlainText }
// this is MessageChain && another is MessageChain -> {
// val anotherIterator = another.iterator()
//
// /**
// * 逐个判断非 [PlainText] 的 [Message] 是否 [equals]
// */
// this.forEachContent { thisElement ->
// if (thisElement.isPlain()) return@forEachContent
// for (it in anotherIterator) {
// if (it.isPlain() || it !is MessageContent) continue
// if (thisElement != it) return false
// }
// }
// return true
// }
// else -> error("shouldn't be reached")
// }
//}
@JvmSynthetic
internal fun Message.contentEqualsStrictImpl(another: Message, ignoreCase: Boolean): Boolean {
if (!this.contentToString().equals(another.contentToString(), ignoreCase = ignoreCase)) return false
return when {
this is SingleMessage && another is SingleMessage -> true
this is SingleMessage && another is MessageChain -> another.all { it is MessageMetadata || it is PlainText }
this is MessageChain && another is SingleMessage -> this.all { it is MessageMetadata || it is PlainText }
this is MessageChain && another is MessageChain -> {
val anotherIterator = another.iterator()
/**
* 逐个判断非 [PlainText] [Message] 是否 [equals]
*/
this.forEachContent { thisElement ->
if (thisElement.isPlain()) return@forEachContent
for (it in anotherIterator) {
if (it.isPlain() || it !is MessageContent) continue
if (thisElement != it) return false
}
}
return true
}
else -> error("shouldn't be reached")
}
}
@JvmSynthetic
internal fun Message.followedByImpl(tail: Message): MessageChain {