RefinableMessage.kt 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. /*
  2. * Copyright 2019-2022 Mamoe Technologies and contributors.
  3. *
  4. * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
  5. * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
  6. *
  7. * https://github.com/mamoe/mirai/blob/dev/LICENSE
  8. */
  9. package net.mamoe.mirai.internal.message
  10. import net.mamoe.mirai.Bot
  11. import net.mamoe.mirai.internal.message.DeepMessageRefiner.refineDeep
  12. import net.mamoe.mirai.internal.message.LightMessageRefiner.refineLight
  13. import net.mamoe.mirai.internal.message.LightMessageRefiner.refineMessageSource
  14. import net.mamoe.mirai.internal.message.flags.InternalFlagOnlyMessage
  15. import net.mamoe.mirai.internal.message.source.IncomingMessageSourceInternal
  16. import net.mamoe.mirai.message.data.*
  17. import net.mamoe.mirai.utils.safeCast
  18. /**
  19. * 在接收解析消息后会经过一层转换的消息.
  20. *
  21. * @see DeepMessageRefiner.refineDeep
  22. * @see LightMessageRefiner.refineLight
  23. */
  24. internal interface RefinableMessage : SingleMessage {
  25. /**
  26. * Refine if possible (without suspension), returns self otherwise.
  27. * @since 2.6
  28. */ // see #1157
  29. fun tryRefine(
  30. bot: Bot,
  31. context: MessageChain,
  32. refineContext: RefineContext = EmptyRefineContext,
  33. ): Message? = this
  34. /**
  35. * This message [RefinableMessage] will be replaced by return value of [refineLight]
  36. */
  37. suspend fun refine(
  38. bot: Bot,
  39. context: MessageChain,
  40. refineContext: RefineContext = EmptyRefineContext,
  41. ): Message? = tryRefine(bot, context, refineContext)
  42. }
  43. internal sealed class MessageRefiner {
  44. protected inline fun MessageChain.refineImpl(
  45. bot: Bot,
  46. refineAction: (message: RefinableMessage) -> Message?,
  47. ): MessageChain {
  48. val convertLineSeparator = bot.configuration.convertLineSeparator
  49. if (none {
  50. it is RefinableMessage
  51. || (it is PlainText && convertLineSeparator && it.content.contains('\r'))
  52. }
  53. ) return this
  54. val builder = MessageChainBuilder(this.size)
  55. for (singleMessage in this) {
  56. if (singleMessage is RefinableMessage) {
  57. val v = refineAction(singleMessage)
  58. if (v != null) builder.add(v)
  59. } else if (singleMessage is PlainText && convertLineSeparator) {
  60. val content = singleMessage.content
  61. if (content.contains('\r')) {
  62. builder.add(
  63. PlainText(
  64. content
  65. .replace("\r\n", "\n")
  66. .replace('\r', '\n')
  67. )
  68. )
  69. } else {
  70. builder.add(singleMessage)
  71. }
  72. } else {
  73. builder.add(singleMessage)
  74. }
  75. }
  76. return builder.build()
  77. }
  78. }
  79. @Suppress("unused")
  80. internal class RefineContextKey<T : Any>(
  81. val name: String?,
  82. ) {
  83. override fun toString(): String {
  84. return buildString {
  85. append("Key(")
  86. name?.also(this@buildString::append) ?: kotlin.run {
  87. append('#').append([email protected]())
  88. }
  89. append(')')
  90. }
  91. }
  92. }
  93. /**
  94. * 转换消息时的上下文
  95. */
  96. internal interface RefineContext {
  97. operator fun contains(key: RefineContextKey<*>): Boolean
  98. operator fun <T : Any> get(key: RefineContextKey<T>): T?
  99. fun <T : Any> getNotNull(key: RefineContextKey<T>): T = get(key) ?: error("No such value of `$key`")
  100. }
  101. internal interface MutableRefineContext : RefineContext {
  102. operator fun <T : Any> set(key: RefineContextKey<T>, value: T)
  103. fun remove(key: RefineContextKey<*>)
  104. }
  105. internal object EmptyRefineContext : RefineContext {
  106. override fun contains(key: RefineContextKey<*>): Boolean = false
  107. override fun <T : Any> get(key: RefineContextKey<T>): T? = null
  108. override fun toString(): String {
  109. return "EmptyRefineContext"
  110. }
  111. }
  112. @Suppress("UNCHECKED_CAST")
  113. internal class SimpleRefineContext(
  114. private val delegate: MutableMap<RefineContextKey<*>, Any> = mutableMapOf(),
  115. ) : MutableRefineContext {
  116. override fun contains(key: RefineContextKey<*>): Boolean = delegate.containsKey(key)
  117. override fun <T : Any> get(key: RefineContextKey<T>): T? {
  118. return (delegate[key] ?: return null) as T
  119. }
  120. override fun <T : Any> set(key: RefineContextKey<T>, value: T) {
  121. delegate[key] = value
  122. }
  123. override fun remove(key: RefineContextKey<*>) {
  124. delegate.remove(key)
  125. }
  126. }
  127. /**
  128. * 执行不需要 `suspend` 的 refine. 用于 [MessageSource.originalMessage].
  129. */
  130. internal object LightMessageRefiner : MessageRefiner() {
  131. /* note:
  132. * 不在 refineLight 中处理的原因是 refineMessageSource
  133. * 需要的是 **最终处理完成后** 的 MessageChain (即 refineDeep 后的 MessageChain)
  134. *
  135. * 在 refineLight/RefinableMessage.(try)refine 中直接处理将导致获取不到最终结果导致逻辑错误
  136. */
  137. fun MessageChain.refineMessageSource(): MessageChain {
  138. val source = this.sourceOrNull?.safeCast<IncomingMessageSourceInternal>() ?: return this
  139. val originalMessage = this
  140. source.originalMessageLazy = lazy {
  141. originalMessage.filterNot { it is MessageSource }.toMessageChain()
  142. // @Suppress("INVISIBLE_MEMBER")
  143. // createMessageChainImplOptimized(originalMessage.filterNot { it is MessageSource })
  144. }
  145. return this
  146. }
  147. fun MessageChain.refineLight(
  148. bot: Bot,
  149. refineContext: RefineContext = EmptyRefineContext,
  150. ): MessageChain {
  151. return refineImpl(bot) { it.tryRefine(bot, this, refineContext) }
  152. }
  153. /**
  154. * 去除 [MessageChain] 携带的内部标识
  155. *
  156. * 用于 [createMessageReceipt] <- `RemoteFile.uploadAndSend` (文件操作API v1)
  157. */
  158. fun MessageChain.dropMiraiInternalFlags(): MessageChain {
  159. return asSequence().filterNot { it is InternalFlagOnlyMessage }.toMessageChain()
  160. }
  161. }
  162. /**
  163. * 执行需要 `suspend` 的 refine. 用于解析到的消息.
  164. */
  165. internal object DeepMessageRefiner : MessageRefiner() {
  166. suspend fun MessageChain.refineDeep(
  167. bot: Bot,
  168. refineContext: RefineContext = EmptyRefineContext,
  169. ): MessageChain {
  170. return refineImpl(bot) { it.refine(bot, this, refineContext) }
  171. .refineMessageSource()
  172. }
  173. }