Prohibit unsafe usage

This commit is contained in:
Him188 2020-03-22 16:24:58 +08:00
parent 8e37cdbf93
commit 6bb8231d8e
2 changed files with 134 additions and 64 deletions

View File

@ -11,6 +11,7 @@ package net.mamoe.mirai.event
import kotlinx.coroutines.* import kotlinx.coroutines.*
import net.mamoe.mirai.message.MessagePacket import net.mamoe.mirai.message.MessagePacket
import net.mamoe.mirai.message.data.Message
import net.mamoe.mirai.message.isContextIdenticalWith import net.mamoe.mirai.message.isContextIdenticalWith
import net.mamoe.mirai.message.nextMessage import net.mamoe.mirai.message.nextMessage
import net.mamoe.mirai.utils.MiraiExperimentalAPI import net.mamoe.mirai.utils.MiraiExperimentalAPI
@ -50,7 +51,6 @@ import kotlin.jvm.JvmSynthetic
*/ */
@SinceMirai("0.29.0") @SinceMirai("0.29.0")
@Suppress("unused") @Suppress("unused")
@MiraiExperimentalAPI
suspend inline fun <reified T : MessagePacket<*, *>> T.whileSelectMessages( suspend inline fun <reified T : MessagePacket<*, *>> T.whileSelectMessages(
timeoutMillis: Long = -1, timeoutMillis: Long = -1,
crossinline selectBuilder: @MessageDsl MessageSelectBuilder<T, Boolean>.() -> Unit crossinline selectBuilder: @MessageDsl MessageSelectBuilder<T, Boolean>.() -> Unit
@ -122,7 +122,6 @@ suspend inline fun <reified T : MessagePacket<*, *>> T.selectMessagesUnit(
* *
* @see nextMessage 挂起协程并等待下一条消息 * @see nextMessage 挂起协程并等待下一条消息
*/ */
@MiraiExperimentalAPI
@SinceMirai("0.29.0") @SinceMirai("0.29.0")
@Suppress("unused") // false positive @Suppress("unused") // false positive
@OptIn(ExperimentalTypeInference::class) @OptIn(ExperimentalTypeInference::class)
@ -165,10 +164,69 @@ suspend inline fun <reified T : MessagePacket<*, *>, R> T.selectMessages(
} }
@SinceMirai("0.29.0") @SinceMirai("0.29.0")
class MessageSelectBuilder<M : MessagePacket<*, *>, R> @PublishedApi internal constructor( open class MessageSelectBuilder<M : MessagePacket<*, *>, R> @PublishedApi internal constructor(
stub: Any?, stub: Any?,
subscriber: (M.(String) -> Boolean, MessageListener<M, Any?>) -> Unit subscriber: (M.(String) -> Boolean, MessageListener<M, Any?>) -> Unit
) : MessageSubscribersBuilder<M, Unit, R, Any?>(stub, subscriber) ) : MessageSubscribersBuilder<M, Unit, R, Any?>(stub, subscriber) {
/**
* 无任何触发条件.
*/
@MessageDsl
fun default(onEvent: MessageListener<M, R>): Unit = subscriber({ true }, onEvent)
@Deprecated("Use `default` instead", level = DeprecationLevel.HIDDEN)
override fun always(onEvent: MessageListener<M, Any?>) {
super.always(onEvent)
}
// 这些函数无法获取返回值. 必须屏蔽.
@Deprecated("Using `reply` DSL in message selection is prohibited", level = DeprecationLevel.HIDDEN)
override fun String.containsReply(reply: String): Nothing = error("prohibited")
@Deprecated("Using `reply` DSL in message selection is prohibited", level = DeprecationLevel.HIDDEN)
override fun String.containsReply(replier: suspend M.(String) -> Any?) = error("prohibited")
@Deprecated("Using `reply` DSL in message selection is prohibited", level = DeprecationLevel.HIDDEN)
override fun Regex.matchingReply(replier: suspend M.(MatchResult) -> Any?) = error("prohibited")
@Deprecated("Using `reply` DSL in message selection is prohibited", level = DeprecationLevel.HIDDEN)
override fun Regex.findingReply(replier: suspend M.(MatchResult) -> Any?) = error("prohibited")
@Deprecated("Using `reply` DSL in message selection is prohibited", level = DeprecationLevel.HIDDEN)
override fun String.startsWithReply(replier: suspend M.(String) -> Any?) = error("prohibited")
@Deprecated("Using `reply` DSL in message selection is prohibited", level = DeprecationLevel.HIDDEN)
override fun String.endsWithReply(replier: suspend M.(String) -> Any?) = error("prohibited")
@Deprecated("Using `reply` DSL in message selection is prohibited", level = DeprecationLevel.HIDDEN)
override fun String.reply(reply: String) = error("prohibited")
@Deprecated("Using `reply` DSL in message selection is prohibited", level = DeprecationLevel.HIDDEN)
override fun String.reply(reply: Message) = error("prohibited")
@Deprecated("Using `reply` DSL in message selection is prohibited", level = DeprecationLevel.HIDDEN)
override fun String.reply(replier: suspend M.(String) -> Any?) = error("prohibited")
@Deprecated("Using `reply` DSL in message selection is prohibited", level = DeprecationLevel.HIDDEN)
override fun ListeningFilter.reply(toReply: String) = error("prohibited")
@Deprecated("Using `reply` DSL in message selection is prohibited", level = DeprecationLevel.HIDDEN)
override fun ListeningFilter.reply(message: Message) = error("prohibited")
@Deprecated("Using `reply` DSL in message selection is prohibited", level = DeprecationLevel.HIDDEN)
override fun ListeningFilter.reply(replier: suspend M.(String) -> Any?) = error("prohibited")
@Deprecated("Using `reply` DSL in message selection is prohibited", level = DeprecationLevel.HIDDEN)
override fun ListeningFilter.quoteReply(toReply: String) = error("prohibited")
@Deprecated("Using `reply` DSL in message selection is prohibited", level = DeprecationLevel.HIDDEN)
override fun ListeningFilter.quoteReply(message: Message) = error("prohibited")
@Deprecated("Using `reply` DSL in message selection is prohibited", level = DeprecationLevel.HIDDEN)
override fun ListeningFilter.quoteReply(replier: suspend M.(String) -> Any?) = error("prohibited")
}
@JvmSynthetic @JvmSynthetic
@PublishedApi @PublishedApi

View File

@ -24,7 +24,6 @@ import net.mamoe.mirai.message.FriendMessage
import net.mamoe.mirai.message.GroupMessage import net.mamoe.mirai.message.GroupMessage
import net.mamoe.mirai.message.MessagePacket import net.mamoe.mirai.message.MessagePacket
import net.mamoe.mirai.message.data.Message import net.mamoe.mirai.message.data.Message
import net.mamoe.mirai.utils.MiraiExperimentalAPI
import net.mamoe.mirai.utils.SinceMirai import net.mamoe.mirai.utils.SinceMirai
import kotlin.contracts.ExperimentalContracts import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind import kotlin.contracts.InvocationKind
@ -34,6 +33,8 @@ import kotlin.coroutines.EmptyCoroutineContext
import kotlin.js.JsName import kotlin.js.JsName
import kotlin.jvm.JvmName import kotlin.jvm.JvmName
typealias MessagePacketSubscribersBuilder = MessageSubscribersBuilder<MessagePacket<*, *>, Listener<MessagePacket<*, *>>, Unit, Unit>
/** /**
* 订阅来自所有 [Bot] 的所有联系人的消息事件. 联系人可以是任意群或任意好友或临时会话. * 订阅来自所有 [Bot] 的所有联系人的消息事件. 联系人可以是任意群或任意好友或临时会话.
* *
@ -43,14 +44,14 @@ import kotlin.jvm.JvmName
fun <R> CoroutineScope.subscribeMessages( fun <R> CoroutineScope.subscribeMessages(
coroutineContext: CoroutineContext = EmptyCoroutineContext, coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrencyKind: Listener.ConcurrencyKind = Listener.ConcurrencyKind.CONCURRENT, concurrencyKind: Listener.ConcurrencyKind = Listener.ConcurrencyKind.CONCURRENT,
listeners: MessageSubscribersBuilder<MessagePacket<*, *>, Listener<MessagePacket<*, *>>, Unit, Unit>.() -> R listeners: MessagePacketSubscribersBuilder.() -> R
): R { ): R {
// contract 可帮助 IDE 进行类型推断. 无实际代码作用. // contract 可帮助 IDE 进行类型推断. 无实际代码作用.
contract { contract {
callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) callsInPlace(listeners, InvocationKind.EXACTLY_ONCE)
} }
return MessageSubscribersBuilder<MessagePacket<*, *>, Listener<MessagePacket<*, *>>, Unit, Unit>(Unit) return MessagePacketSubscribersBuilder(Unit)
{ filter, messageListener: MessageListener<MessagePacket<*, *>, Unit> -> { filter, messageListener: MessageListener<MessagePacket<*, *>, Unit> ->
// subscribeAlways 即注册一个监听器. 这个监听器收到消息后就传递给 [messageListener] // subscribeAlways 即注册一个监听器. 这个监听器收到消息后就传递给 [messageListener]
// messageListener 即为 DSL 里 `contains(...) { }`, `startsWith(...) { }` 的代码块. // messageListener 即为 DSL 里 `contains(...) { }`, `startsWith(...) { }` 的代码块.
@ -63,6 +64,8 @@ fun <R> CoroutineScope.subscribeMessages(
}.run(listeners) }.run(listeners)
} }
typealias GroupMessageSubscribersBuilder = MessageSubscribersBuilder<GroupMessage, Listener<GroupMessage>, Unit, Unit>
/** /**
* 订阅来自所有 [Bot] 的所有群消息事件 * 订阅来自所有 [Bot] 的所有群消息事件
* *
@ -72,12 +75,12 @@ fun <R> CoroutineScope.subscribeMessages(
fun <R> CoroutineScope.subscribeGroupMessages( fun <R> CoroutineScope.subscribeGroupMessages(
coroutineContext: CoroutineContext = EmptyCoroutineContext, coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrencyKind: Listener.ConcurrencyKind = Listener.ConcurrencyKind.CONCURRENT, concurrencyKind: Listener.ConcurrencyKind = Listener.ConcurrencyKind.CONCURRENT,
listeners: MessageSubscribersBuilder<GroupMessage, Listener<GroupMessage>, Unit, Unit>.() -> R listeners: GroupMessageSubscribersBuilder.() -> R
): R { ): R {
contract { contract {
callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) callsInPlace(listeners, InvocationKind.EXACTLY_ONCE)
} }
return MessageSubscribersBuilder<GroupMessage, Listener<GroupMessage>, Unit, Unit>(Unit) { filter, listener -> return GroupMessageSubscribersBuilder(Unit) { filter, listener ->
subscribeAlways(coroutineContext, concurrencyKind) { subscribeAlways(coroutineContext, concurrencyKind) {
val toString = this.message.toString() val toString = this.message.toString()
if (filter(this, toString)) if (filter(this, toString))
@ -86,6 +89,8 @@ fun <R> CoroutineScope.subscribeGroupMessages(
}.run(listeners) }.run(listeners)
} }
typealias FriendMessageSubscribersBuilder = MessageSubscribersBuilder<FriendMessage, Listener<FriendMessage>, Unit, Unit>
/** /**
* 订阅来自所有 [Bot] 的所有好友消息事件 * 订阅来自所有 [Bot] 的所有好友消息事件
* *
@ -95,12 +100,12 @@ fun <R> CoroutineScope.subscribeGroupMessages(
fun <R> CoroutineScope.subscribeFriendMessages( fun <R> CoroutineScope.subscribeFriendMessages(
coroutineContext: CoroutineContext = EmptyCoroutineContext, coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrencyKind: Listener.ConcurrencyKind = Listener.ConcurrencyKind.CONCURRENT, concurrencyKind: Listener.ConcurrencyKind = Listener.ConcurrencyKind.CONCURRENT,
listeners: MessageSubscribersBuilder<FriendMessage, Listener<FriendMessage>, Unit, Unit>.() -> R listeners: FriendMessageSubscribersBuilder.() -> R
): R { ): R {
contract { contract {
callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) callsInPlace(listeners, InvocationKind.EXACTLY_ONCE)
} }
return MessageSubscribersBuilder<FriendMessage, Listener<FriendMessage>, Unit, Unit>(Unit) { filter, listener -> return FriendMessageSubscribersBuilder(Unit) { filter, listener ->
subscribeAlways(coroutineContext, concurrencyKind) { subscribeAlways(coroutineContext, concurrencyKind) {
val toString = this.message.toString() val toString = this.message.toString()
if (filter(this, toString)) if (filter(this, toString))
@ -118,12 +123,12 @@ fun <R> CoroutineScope.subscribeFriendMessages(
fun <R> Bot.subscribeMessages( fun <R> Bot.subscribeMessages(
coroutineContext: CoroutineContext = EmptyCoroutineContext, coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrencyKind: Listener.ConcurrencyKind = Listener.ConcurrencyKind.CONCURRENT, concurrencyKind: Listener.ConcurrencyKind = Listener.ConcurrencyKind.CONCURRENT,
listeners: MessageSubscribersBuilder<MessagePacket<*, *>, Listener<MessagePacket<*, *>>, Unit, Unit>.() -> R listeners: MessagePacketSubscribersBuilder.() -> R
): R { ): R {
contract { contract {
callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) callsInPlace(listeners, InvocationKind.EXACTLY_ONCE)
} }
return MessageSubscribersBuilder<MessagePacket<*, *>, Listener<MessagePacket<*, *>>, Unit, Unit>(Unit) { filter, listener -> return MessagePacketSubscribersBuilder(Unit) { filter, listener ->
this.subscribeAlways(coroutineContext, concurrencyKind) { this.subscribeAlways(coroutineContext, concurrencyKind) {
val toString = this.message.toString() val toString = this.message.toString()
if (filter(this, toString)) if (filter(this, toString))
@ -143,12 +148,12 @@ fun <R> Bot.subscribeMessages(
fun <R> Bot.subscribeGroupMessages( fun <R> Bot.subscribeGroupMessages(
coroutineContext: CoroutineContext = EmptyCoroutineContext, coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrencyKind: Listener.ConcurrencyKind = Listener.ConcurrencyKind.CONCURRENT, concurrencyKind: Listener.ConcurrencyKind = Listener.ConcurrencyKind.CONCURRENT,
listeners: MessageSubscribersBuilder<GroupMessage, Listener<GroupMessage>, Unit, Unit>.() -> R listeners: GroupMessageSubscribersBuilder.() -> R
): R { ): R {
contract { contract {
callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) callsInPlace(listeners, InvocationKind.EXACTLY_ONCE)
} }
return MessageSubscribersBuilder<GroupMessage, Listener<GroupMessage>, Unit, Unit>(Unit) { filter, listener -> return GroupMessageSubscribersBuilder(Unit) { filter, listener ->
this.subscribeAlways(coroutineContext, concurrencyKind) { this.subscribeAlways(coroutineContext, concurrencyKind) {
val toString = this.message.toString() val toString = this.message.toString()
if (filter(this, toString)) if (filter(this, toString))
@ -166,12 +171,12 @@ fun <R> Bot.subscribeGroupMessages(
fun <R> Bot.subscribeFriendMessages( fun <R> Bot.subscribeFriendMessages(
coroutineContext: CoroutineContext = EmptyCoroutineContext, coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrencyKind: Listener.ConcurrencyKind = Listener.ConcurrencyKind.CONCURRENT, concurrencyKind: Listener.ConcurrencyKind = Listener.ConcurrencyKind.CONCURRENT,
listeners: MessageSubscribersBuilder<FriendMessage, Listener<FriendMessage>, Unit, Unit>.() -> R listeners: FriendMessageSubscribersBuilder.() -> R
): R { ): R {
contract { contract {
callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) callsInPlace(listeners, InvocationKind.EXACTLY_ONCE)
} }
return MessageSubscribersBuilder<FriendMessage, Listener<FriendMessage>, Unit, Unit>(Unit) { filter, listener -> return FriendMessageSubscribersBuilder(Unit) { filter, listener ->
this.subscribeAlways(coroutineContext, concurrencyKind) { this.subscribeAlways(coroutineContext, concurrencyKind) {
val toString = this.message.toString() val toString = this.message.toString()
if (filter(this, toString)) if (filter(this, toString))
@ -245,10 +250,6 @@ inline fun <reified E : BotEvent> Bot.incoming(
typealias MessageListener<T, R> = @MessageDsl suspend T.(String) -> R typealias MessageListener<T, R> = @MessageDsl suspend T.(String) -> R
// TODO: 2020/3/21 抽象消息构造器, 以在 select 时不可访问 `reply` 等函数
// TODO: 2020/3/21 引入 TypeAlias 或新的类型以缩短类型参数
/** /**
* 消息订阅构造器 * 消息订阅构造器
* *
@ -269,41 +270,47 @@ open class MessageSubscribersBuilder<M : MessagePacket<*, *>, out Ret, R : RR, R
*/ */
val subscriber: (M.(String) -> Boolean, MessageListener<M, RR>) -> Ret val subscriber: (M.(String) -> Boolean, MessageListener<M, RR>) -> Ret
) { ) {
@Suppress("DEPRECATION")
open fun newListeningFilter(filter: M.(String) -> Boolean): ListeningFilter = ListeningFilter(filter)
/** /**
* 监听的条件 * 监听的条件
*/ */
open inner class ListeningFilter( open inner class ListeningFilter @Deprecated(
"use newListeningFilter instead",
ReplaceWith("newListeningFilter(filter)")
) constructor(
val filter: M.(String) -> Boolean val filter: M.(String) -> Boolean
) { ) {
/** /**
* 进行逻辑 `or`. * 进行逻辑 `or`.
*/ */
infix fun or(another: ListeningFilter): ListeningFilter = infix fun or(another: ListeningFilter): ListeningFilter =
ListeningFilter { filter.invoke(this, it) || another.filter.invoke(this, it) } newListeningFilter { filter.invoke(this, it) || another.filter.invoke(this, it) }
/** /**
* 进行逻辑 `and`. * 进行逻辑 `and`.
*/ */
infix fun and(another: ListeningFilter): ListeningFilter = infix fun and(another: ListeningFilter): ListeningFilter =
ListeningFilter { filter.invoke(this, it) && another.filter.invoke(this, it) } newListeningFilter { filter.invoke(this, it) && another.filter.invoke(this, it) }
/** /**
* 进行逻辑 `xor`. * 进行逻辑 `xor`.
*/ */
infix fun xor(another: ListeningFilter): ListeningFilter = infix fun xor(another: ListeningFilter): ListeningFilter =
ListeningFilter { filter.invoke(this, it) xor another.filter.invoke(this, it) } newListeningFilter { filter.invoke(this, it) xor another.filter.invoke(this, it) }
/** /**
* 进行逻辑 `nand`, `not and`. * 进行逻辑 `nand`, `not and`.
*/ */
infix fun nand(another: ListeningFilter): ListeningFilter = infix fun nand(another: ListeningFilter): ListeningFilter =
ListeningFilter { !filter.invoke(this, it) || !another.filter.invoke(this, it) } newListeningFilter { !filter.invoke(this, it) || !another.filter.invoke(this, it) }
/** /**
* 进行逻辑 `not` * 进行逻辑 `not`
*/ */
fun not(): ListeningFilter = fun not(): ListeningFilter =
ListeningFilter { !filter.invoke(this, it) } newListeningFilter { !filter.invoke(this, it) }
/** /**
* 启动事件监听. * 启动事件监听.
@ -312,37 +319,43 @@ open class MessageSubscribersBuilder<M : MessagePacket<*, *>, out Ret, R : RR, R
operator fun invoke(onEvent: MessageListener<M, R>): Ret { operator fun invoke(onEvent: MessageListener<M, R>): Ret {
return content(filter, onEvent) return content(filter, onEvent)
} }
}
infix fun reply(toReply: String): Ret { @SinceMirai("0.29.0")
open infix fun ListeningFilter.reply(toReply: String): Ret {
return content(filter) { reply(toReply);stub } return content(filter) { reply(toReply);stub }
} }
infix fun reply(message: Message): Ret { @SinceMirai("0.29.0")
open infix fun ListeningFilter.reply(message: Message): Ret {
return content(filter) { reply(message);stub } return content(filter) { reply(message);stub }
} }
infix fun reply(replier: (@MessageDsl suspend M.(String) -> Any?)): Ret { @SinceMirai("0.29.0")
open infix fun ListeningFilter.reply(replier: (@MessageDsl suspend M.(String) -> Any?)): Ret {
return content(filter) { return content(filter) {
@Suppress("DSL_SCOPE_VIOLATION_WARNING") @Suppress("DSL_SCOPE_VIOLATION_WARNING")
executeAndReply(replier) executeAndReply(replier)
} }
} }
infix fun quoteReply(toReply: String): Ret { @SinceMirai("0.29.0")
open infix fun ListeningFilter.quoteReply(toReply: String): Ret {
return content(filter) { quoteReply(toReply);stub } return content(filter) { quoteReply(toReply);stub }
} }
infix fun quoteReply(message: Message): Ret { @SinceMirai("0.29.0")
open infix fun ListeningFilter.quoteReply(message: Message): Ret {
return content(filter) { quoteReply(message);stub } return content(filter) { quoteReply(message);stub }
} }
infix fun quoteReply(replier: (@MessageDsl suspend M.(String) -> Any?)): Ret { @SinceMirai("0.29.0")
open infix fun ListeningFilter.quoteReply(replier: (@MessageDsl suspend M.(String) -> Any?)): Ret {
return content(filter) { return content(filter) {
@Suppress("DSL_SCOPE_VIOLATION_WARNING") @Suppress("DSL_SCOPE_VIOLATION_WARNING")
executeAndQuoteReply(replier) executeAndQuoteReply(replier)
} }
} }
}
// TODO: 2020/3/6 这些 lambda 都应该 crossinline, 但这会导致异常时的 stacktrace 不准确 (Kotlin 1.3.70) 待 Kotlin 修复此问题后恢复 inline 结构 // TODO: 2020/3/6 这些 lambda 都应该 crossinline, 但这会导致异常时的 stacktrace 不准确 (Kotlin 1.3.70) 待 Kotlin 修复此问题后恢复 inline 结构
@ -350,7 +363,7 @@ open class MessageSubscribersBuilder<M : MessagePacket<*, *>, out Ret, R : RR, R
* 无任何触发条件. * 无任何触发条件.
*/ */
@MessageDsl @MessageDsl
fun always(onEvent: MessageListener<M, RR>): Ret = subscriber({ true }, onEvent) open fun always(onEvent: MessageListener<M, RR>): Ret = subscriber({ true }, onEvent)
/** /**
* 如果消息内容 `==` [equals] * 如果消息内容 `==` [equals]
@ -372,7 +385,6 @@ open class MessageSubscribersBuilder<M : MessagePacket<*, *>, out Ret, R : RR, R
/** /**
* 如果消息内容 `==` [equals] * 如果消息内容 `==` [equals]
*/ */
@MiraiExperimentalAPI
@MessageDsl @MessageDsl
@JvmName("case1") @JvmName("case1")
@JsName("case1") @JsName("case1")
@ -603,7 +615,7 @@ open class MessageSubscribersBuilder<M : MessagePacket<*, *>, out Ret, R : RR, R
* 如果是好友发来的消息 * 如果是好友发来的消息
*/ */
@MessageDsl @MessageDsl
fun sentByFriend(): ListeningFilter = ListeningFilter { this is FriendMessage } fun sentByFriend(): ListeningFilter = newListeningFilter { this is FriendMessage }
/** /**
* 如果是管理员或群主发的消息 * 如果是管理员或群主发的消息
@ -682,7 +694,7 @@ open class MessageSubscribersBuilder<M : MessagePacket<*, *>, out Ret, R : RR, R
*/ */
@MessageDsl @MessageDsl
fun content(filter: M.(String) -> Boolean): ListeningFilter = fun content(filter: M.(String) -> Boolean): ListeningFilter =
ListeningFilter(filter) newListeningFilter(filter)
/** /**
* 如果 [filter] 返回 `true` 就执行 `onEvent` * 如果 [filter] 返回 `true` 就执行 `onEvent`
@ -741,7 +753,7 @@ open class MessageSubscribersBuilder<M : MessagePacket<*, *>, out Ret, R : RR, R
* 若消息内容包含 [this] 则回复 [reply] * 若消息内容包含 [this] 则回复 [reply]
*/ */
@MessageDsl @MessageDsl
infix fun String.containsReply(reply: String): Ret = open infix fun String.containsReply(reply: String): Ret =
content({ this@containsReply in it }, { reply(reply); stub }) content({ this@containsReply in it }, { reply(reply); stub })
/** /**
@ -752,7 +764,7 @@ open class MessageSubscribersBuilder<M : MessagePacket<*, *>, out Ret, R : RR, R
* @param replier 若返回 [Message] 则直接发送; 若返回 [Unit] 则不回复; 其他情况则 [Any.toString] 后回复 * @param replier 若返回 [Message] 则直接发送; 若返回 [Unit] 则不回复; 其他情况则 [Any.toString] 后回复
*/ */
@MessageDsl @MessageDsl
infix fun String.containsReply(replier: @MessageDsl suspend M.(String) -> Any?): Ret = open infix fun String.containsReply(replier: @MessageDsl suspend M.(String) -> Any?): Ret =
content({ this@containsReply in it }, { content({ this@containsReply in it }, {
@Suppress("DSL_SCOPE_VIOLATION_WARNING") @Suppress("DSL_SCOPE_VIOLATION_WARNING")
this.executeAndReply(replier) this.executeAndReply(replier)
@ -766,7 +778,7 @@ open class MessageSubscribersBuilder<M : MessagePacket<*, *>, out Ret, R : RR, R
* @param replier 若返回 [Message] 则直接发送; 若返回 [Unit] 则不回复; 其他情况则 [Any.toString] 后回复 * @param replier 若返回 [Message] 则直接发送; 若返回 [Unit] 则不回复; 其他情况则 [Any.toString] 后回复
*/ */
@MessageDsl @MessageDsl
infix fun Regex.matchingReply(replier: @MessageDsl suspend M.(MatchResult) -> Any?): Ret = open infix fun Regex.matchingReply(replier: @MessageDsl suspend M.(MatchResult) -> Any?): Ret =
always { always {
val find = this@matchingReply.matchEntire(it) ?: return@always stub val find = this@matchingReply.matchEntire(it) ?: return@always stub
@Suppress("DSL_SCOPE_VIOLATION_WARNING") @Suppress("DSL_SCOPE_VIOLATION_WARNING")
@ -783,7 +795,7 @@ open class MessageSubscribersBuilder<M : MessagePacket<*, *>, out Ret, R : RR, R
* @param replier 若返回 [Message] 则直接发送; 若返回 [Unit] 则不回复; 其他情况则 [Any.toString] 后回复 * @param replier 若返回 [Message] 则直接发送; 若返回 [Unit] 则不回复; 其他情况则 [Any.toString] 后回复
*/ */
@MessageDsl @MessageDsl
infix fun Regex.findingReply(replier: @MessageDsl suspend M.(MatchResult) -> Any?): Ret = open infix fun Regex.findingReply(replier: @MessageDsl suspend M.(MatchResult) -> Any?): Ret =
always { always {
val find = this@findingReply.find(it) ?: return@always stub val find = this@findingReply.find(it) ?: return@always stub
@Suppress("DSL_SCOPE_VIOLATION_WARNING") @Suppress("DSL_SCOPE_VIOLATION_WARNING")
@ -806,7 +818,7 @@ open class MessageSubscribersBuilder<M : MessagePacket<*, *>, out Ret, R : RR, R
* @param replier 若返回 [Message] 则直接发送; 若返回 [Unit] 则不回复; 其他类型则 [Any.toString] 后回复 * @param replier 若返回 [Message] 则直接发送; 若返回 [Unit] 则不回复; 其他类型则 [Any.toString] 后回复
*/ */
@MessageDsl @MessageDsl
infix fun String.startsWithReply(replier: @MessageDsl suspend M.(String) -> Any?): Ret { open infix fun String.startsWithReply(replier: @MessageDsl suspend M.(String) -> Any?): Ret {
val toCheck = this.trimStart() val toCheck = this.trimStart()
return content({ it.trim().startsWith(toCheck) }, { return content({ it.trim().startsWith(toCheck) }, {
@Suppress("DSL_SCOPE_VIOLATION_WARNING") @Suppress("DSL_SCOPE_VIOLATION_WARNING")
@ -830,7 +842,7 @@ open class MessageSubscribersBuilder<M : MessagePacket<*, *>, out Ret, R : RR, R
* @param replier 若返回 [Message] 则直接发送; 若返回 [Unit] 则不回复; 其他情况则 [Any.toString] 后回复 * @param replier 若返回 [Message] 则直接发送; 若返回 [Unit] 则不回复; 其他情况则 [Any.toString] 后回复
*/ */
@MessageDsl @MessageDsl
infix fun String.endsWithReply(replier: @MessageDsl suspend M.(String) -> Any?): Ret { open infix fun String.endsWithReply(replier: @MessageDsl suspend M.(String) -> Any?): Ret {
val toCheck = this.trimEnd() val toCheck = this.trimEnd()
return content({ it.trim().endsWith(toCheck) }, { return content({ it.trim().endsWith(toCheck) }, {
@Suppress("DSL_SCOPE_VIOLATION_WARNING") @Suppress("DSL_SCOPE_VIOLATION_WARNING")
@ -841,19 +853,19 @@ open class MessageSubscribersBuilder<M : MessagePacket<*, *>, out Ret, R : RR, R
} }
@MessageDsl @MessageDsl
infix fun String.reply(reply: String): Ret { open infix fun String.reply(reply: String): Ret {
val toCheck = this.trim() val toCheck = this.trim()
return content({ it.trim() == toCheck }, { reply(reply);stub }) return content({ it.trim() == toCheck }, { reply(reply);stub })
} }
@MessageDsl @MessageDsl
infix fun String.reply(reply: Message): Ret { open infix fun String.reply(reply: Message): Ret {
val toCheck = this.trim() val toCheck = this.trim()
return content({ it.trim() == toCheck }, { reply(reply);stub }) return content({ it.trim() == toCheck }, { reply(reply);stub })
} }
@MessageDsl @MessageDsl
infix fun String.reply(replier: @MessageDsl suspend M.(String) -> Any?): Ret { open infix fun String.reply(replier: @MessageDsl suspend M.(String) -> Any?): Ret {
val toCheck = this.trim() val toCheck = this.trim()
return content({ it.trim() == toCheck }, { return content({ it.trim() == toCheck }, {
@Suppress("DSL_SCOPE_VIOLATION_WARNING") @Suppress("DSL_SCOPE_VIOLATION_WARNING")