mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-20 16:14:43 +08:00
Add docs and more useful functions
This commit is contained in:
parent
b8323a5ed6
commit
33409f3a82
@ -3,6 +3,9 @@
|
||||
package net.mamoe.mirai.event
|
||||
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.contact.isAdministrator
|
||||
import net.mamoe.mirai.contact.isOperator
|
||||
import net.mamoe.mirai.contact.isOwner
|
||||
import net.mamoe.mirai.message.Message
|
||||
import net.mamoe.mirai.message.any
|
||||
import net.mamoe.mirai.network.protocol.tim.packet.event.FriendMessage
|
||||
@ -18,12 +21,12 @@ import kotlin.jvm.JvmName
|
||||
*/
|
||||
@UseExperimental(ExperimentalContracts::class)
|
||||
@MessageDsl
|
||||
suspend inline fun subscribeMessages(crossinline listeners: suspend MessageSubscribersBuilder<MessagePacket<*>>.() -> Unit) {
|
||||
suspend inline fun subscribeMessages(crossinline listeners: suspend MessageSubscribersBuilder<MessagePacket<*, *>>.() -> Unit) {
|
||||
contract {
|
||||
callsInPlace(listeners, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
MessageSubscribersBuilder<MessagePacket<*>> { listener ->
|
||||
subscribeAlways<MessagePacket<*>> {
|
||||
MessageSubscribersBuilder<MessagePacket<*, *>> { listener ->
|
||||
subscribeAlways<MessagePacket<*, *>> {
|
||||
listener(it)
|
||||
}
|
||||
}.apply { listeners() }
|
||||
@ -66,12 +69,12 @@ suspend inline fun subscribeFriendMessages(crossinline listeners: suspend Messag
|
||||
*/
|
||||
@UseExperimental(ExperimentalContracts::class)
|
||||
@MessageDsl
|
||||
suspend inline fun Bot.subscribeMessages(crossinline listeners: suspend MessageSubscribersBuilder<MessagePacket<*>>.() -> Unit) {
|
||||
suspend inline fun Bot.subscribeMessages(crossinline listeners: suspend MessageSubscribersBuilder<MessagePacket<*, *>>.() -> Unit) {
|
||||
contract {
|
||||
callsInPlace(listeners, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
MessageSubscribersBuilder<MessagePacket<*>> { listener ->
|
||||
this.subscribeAlways<MessagePacket<*>> {
|
||||
MessageSubscribersBuilder<MessagePacket<*, *>> { listener ->
|
||||
this.subscribeAlways<MessagePacket<*, *>> {
|
||||
listener(it)
|
||||
}
|
||||
}.apply { listeners() }
|
||||
@ -111,11 +114,11 @@ suspend inline fun Bot.subscribeFriendMessages(crossinline listeners: suspend Me
|
||||
|
||||
private typealias AnyReplier<T> = @MessageDsl suspend T.(String) -> Any?
|
||||
|
||||
private suspend inline operator fun <T : MessagePacket<*>> (@MessageDsl suspend T.(String) -> Unit).invoke(t: T) =
|
||||
private suspend inline operator fun <T : MessagePacket<*, *>> (@MessageDsl suspend T.(String) -> Unit).invoke(t: T) =
|
||||
this.invoke(t, t.message.stringValue)
|
||||
|
||||
@JvmName("invoke1") //Avoid Platform declaration clash
|
||||
private suspend inline operator fun <T : MessagePacket<*>> AnyReplier<T>.invoke(t: T): Any? =
|
||||
private suspend inline operator fun <T : MessagePacket<*, *>> AnyReplier<T>.invoke(t: T): Any? =
|
||||
this.invoke(t, t.message.stringValue)
|
||||
|
||||
/**
|
||||
@ -127,7 +130,7 @@ private suspend inline operator fun <T : MessagePacket<*>> AnyReplier<T>.invoke(
|
||||
// TODO: 2019/11/29 应定义为 inline, 但这会导致一个 JVM run-time VerifyError. 等待 kotlin 修复 bug
|
||||
@Suppress("unused")
|
||||
@MessageDsl
|
||||
class MessageSubscribersBuilder<T : MessagePacket<*>>(
|
||||
class MessageSubscribersBuilder<T : MessagePacket<*, *>>(
|
||||
inline val subscriber: suspend (@MessageDsl suspend T.(String) -> Unit) -> Unit
|
||||
) {
|
||||
/**
|
||||
@ -194,6 +197,27 @@ class MessageSubscribersBuilder<T : MessagePacket<*>>(
|
||||
@MessageDsl
|
||||
suspend inline fun sentBy(qqId: Long, noinline onEvent: @MessageDsl suspend T.(String) -> Unit) = sentBy(qqId.toUInt(), onEvent)
|
||||
|
||||
/**
|
||||
* 如果是管理员或群主发的消息, 就执行 [onEvent]
|
||||
*/
|
||||
@MessageDsl
|
||||
suspend inline fun sentByOperator(noinline onEvent: @MessageDsl suspend T.(String) -> Unit) =
|
||||
content({ this is GroupMessage && sender.permission.isOperator() }, onEvent)
|
||||
|
||||
/**
|
||||
* 如果是管理员发的消息, 就执行 [onEvent]
|
||||
*/
|
||||
@MessageDsl
|
||||
suspend inline fun sentByAdministrator(noinline onEvent: @MessageDsl suspend T.(String) -> Unit) =
|
||||
content({ this is GroupMessage && sender.permission.isAdministrator() }, onEvent)
|
||||
|
||||
/**
|
||||
* 如果是群主发的消息, 就执行 [onEvent]
|
||||
*/
|
||||
@MessageDsl
|
||||
suspend inline fun sentByOwner(noinline onEvent: @MessageDsl suspend T.(String) -> Unit) =
|
||||
content({ this is GroupMessage && sender.permission.isOwner() }, onEvent)
|
||||
|
||||
/**
|
||||
* 如果是来自这个群的消息, 就执行 [onEvent]
|
||||
*/
|
||||
@ -221,21 +245,74 @@ class MessageSubscribersBuilder<T : MessagePacket<*>>(
|
||||
suspend inline fun content(noinline filter: T.(String) -> Boolean, noinline onEvent: @MessageDsl suspend T.(String) -> Unit) =
|
||||
subscriber { if (this.filter(message.stringValue)) onEvent(this) }
|
||||
|
||||
/**
|
||||
* 若消息内容包含 [this] 则回复 [reply]
|
||||
*/
|
||||
@MessageDsl
|
||||
suspend inline infix fun String.containsReply(replier: String) =
|
||||
content({ this@containsReply in it }) { this@content.reply(replier) }
|
||||
suspend inline infix fun String.containsReply(reply: String) =
|
||||
content({ this@containsReply in it }) { this@content.reply(reply) }
|
||||
|
||||
/**
|
||||
* 若消息内容包含 [this] 则执行 [replier] 并将其返回值回复给发信对象.
|
||||
*
|
||||
* [replier] 的 `it` 将会是消息内容 string.
|
||||
*
|
||||
* @param replier 若返回 [Message] 则直接发送; 若返回 [Unit] 则不回复; 其他情况则 [Any.toString] 后回复
|
||||
*/
|
||||
@MessageDsl
|
||||
suspend inline infix fun String.containsReply(noinline replier: AnyReplier<T>) =
|
||||
content({ this@containsReply in it }) { replier(this) }
|
||||
content({ this@containsReply in it }) {
|
||||
@Suppress("DSL_SCOPE_VIOLATION_WARNING") // false negative warning
|
||||
executeAndReply(replier)
|
||||
}
|
||||
|
||||
/**
|
||||
* 不考虑空格, 若消息内容以 [this] 开始则执行 [replier] 并将其返回值回复给发信对象.
|
||||
*
|
||||
* [replier] 的 `it` 将会是去掉用来判断的前缀并删除前后空格后的字符串.
|
||||
* 如当消息为 "kick 123456 " 时
|
||||
* ```kotlin
|
||||
* "kick" startsWithReply {
|
||||
* println(it) // it 为 "123456"
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param replier 若返回 [Message] 则直接发送; 若返回 [Unit] 则不回复; 其他类型则 [Any.toString] 后回复
|
||||
*/
|
||||
@MessageDsl
|
||||
suspend inline infix fun String.startsWithReply(noinline replier: AnyReplier<T>) =
|
||||
content({ it.startsWith(this@startsWithReply) }) { replier(this) }
|
||||
suspend inline infix fun String.startsWithReply(noinline replier: AnyReplier<T>) {
|
||||
val toCheck = this.trimStart()
|
||||
content({ it.trimStart().startsWith(toCheck) }) {
|
||||
@Suppress("DSL_SCOPE_VIOLATION_WARNING") // false negative warning
|
||||
executeAndReply {
|
||||
replier(it.removePrefix(toCheck).trim())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 不考虑空格, 若消息内容以 [this] 结尾则执行 [replier] 并将其返回值回复给发信对象.
|
||||
*
|
||||
* [replier] 的 `it` 将会是去掉用来判断的后缀并删除前后空格后的字符串.
|
||||
* 如当消息为 " 123456 test" 时
|
||||
* ```kotlin
|
||||
* "test" endswithReply {
|
||||
* println(it) // it 为 "123456"
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param replier 若返回 [Message] 则直接发送; 若返回 [Unit] 则不回复; 其他情况则 [Any.toString] 后回复
|
||||
*/
|
||||
@MessageDsl
|
||||
suspend inline infix fun String.endswithReply(noinline replier: AnyReplier<T>) =
|
||||
content({ it.endsWith(this@endswithReply) }) { replier(this) }
|
||||
suspend inline infix fun String.endswithReply(noinline replier: AnyReplier<T>) {
|
||||
val toCheck = this.trimEnd()
|
||||
content({ it.endsWith(this@endswithReply) }) {
|
||||
@Suppress("DSL_SCOPE_VIOLATION_WARNING") // false negative warning
|
||||
executeAndReply {
|
||||
replier(it.removeSuffix(toCheck).trim())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@MessageDsl
|
||||
suspend inline infix fun String.reply(reply: String) = case(this) {
|
||||
@ -243,17 +320,23 @@ class MessageSubscribersBuilder<T : MessagePacket<*>>(
|
||||
}
|
||||
|
||||
@MessageDsl
|
||||
suspend inline infix fun String.reply(noinline reply: AnyReplier<T>) = case(this) {
|
||||
when (val message = reply(this)) {
|
||||
is Message -> reply(message)
|
||||
suspend inline infix fun String.reply(noinline replier: AnyReplier<T>) = case(this) {
|
||||
@Suppress("DSL_SCOPE_VIOLATION_WARNING") // false negative warning
|
||||
executeAndReply(replier)
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
internal suspend inline fun T.executeAndReply(noinline replier: AnyReplier<T>) {
|
||||
when (val message = replier(this)) {
|
||||
is Message -> this.reply(message)
|
||||
is Unit -> {
|
||||
|
||||
}
|
||||
else -> reply(message.toString())
|
||||
else -> this.reply(message.toString())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* 易产生迷惑感
|
||||
suspend inline fun replyCase(equals: String, trim: Boolean = true, noinline replier: MessageReplier<T>) = case(equals, trim) { reply(replier(this)) }
|
||||
suspend inline fun replyContains(value: String, noinline replier: MessageReplier<T>) = content({ value in it }) { replier(this) }
|
||||
@ -265,6 +348,7 @@ class MessageSubscribersBuilder<T : MessagePacket<*>>(
|
||||
/**
|
||||
* DSL 标记. 将能让 IDE 阻止一些错误的方法调用.
|
||||
*/
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS, AnnotationTarget.TYPE)
|
||||
@DslMarker
|
||||
internal annotation class MessageDsl
|
@ -118,7 +118,7 @@ suspend fun Bot.messageDSL() {
|
||||
|
||||
|
||||
// 如果是这个 QQ 号发送的消息(可以是好友消息也可以是群消息)
|
||||
sentBy(1040400290) {
|
||||
sentBy(123456789) {
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user