Simplify message handler

This commit is contained in:
Him188 2019-11-28 12:44:47 +08:00
parent 265a431b7f
commit 57685d39e7
10 changed files with 54 additions and 49 deletions

View File

@ -18,13 +18,17 @@ import net.mamoe.mirai.utils.internal.coerceAtLeastOrFail
interface Group : Contact {
val internalId: GroupInternalId
/**
* [Group] 实例创建的时候查询一次. 收到各事件后
*/
val member: ContactList<Member>
suspend fun getMember(id: UInt): Member
/**
* 查询群资料
*/
*/ // should be `suspend val` if kotlin supports in the future
suspend fun queryGroupInfo(): GroupInfo
}

View File

@ -2,11 +2,10 @@
package net.mamoe.mirai.contact
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.Deferred
import net.mamoe.mirai.Bot
import net.mamoe.mirai.contact.data.Profile
import net.mamoe.mirai.network.BotSession
import net.mamoe.mirai.network.protocol.tim.packet.action.FriendNameRemark
import net.mamoe.mirai.network.protocol.tim.packet.action.PreviousNameList
/**
@ -23,17 +22,9 @@ import net.mamoe.mirai.network.protocol.tim.packet.action.PreviousNameList
*/
interface QQ : Contact {
/**
* 用户资料.
* 第一次获取时将会向服务器查询.
* 第一次以后则是直接得到一个用 [CompletableDeferred] 包装的值
* 查询用户资料
*/
val profile: Deferred<Profile>
/**
* 更新个人资料.
* 将会同步更新 property [profile]
*/
suspend fun updateProfile(): Profile
suspend fun queryProfile(): Profile
/**
* 查询曾用名.
@ -43,4 +34,9 @@ interface QQ : Contact {
* - 共同群内的群名片
*/
suspend fun queryPreviousNameList(): PreviousNameList
/**
* 查询机器人账号给这个人设置的备注
*/
suspend fun queryRemark(): FriendNameRemark
}

View File

@ -2,8 +2,6 @@
package net.mamoe.mirai.contact.internal
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.sync.Mutex
import net.mamoe.mirai.Bot
import net.mamoe.mirai.contact.*
@ -17,7 +15,6 @@ import net.mamoe.mirai.network.qqAccount
import net.mamoe.mirai.network.sessionKey
import net.mamoe.mirai.qqAccount
import net.mamoe.mirai.sendPacket
import net.mamoe.mirai.utils.SuspendLazy
import net.mamoe.mirai.withSession
internal sealed class ContactImpl : Contact {
@ -40,9 +37,7 @@ internal data class GroupImpl internal constructor(override val bot: Bot, val gr
override suspend fun getMember(id: UInt): Member =
if (_members.containsKey(id)) _members[id]!!
else throw NoSuchElementException("No such member whose id is $id in group $id") /*membersLock.withLock {
_members.getOrPut(id) { MemberImpl(bot.getQQ(id), this) }
}*/
else throw NoSuchElementException("No such member whose id is $id in group $id")
override suspend fun sendMessage(message: MessageChain) {
bot.sendPacket(GroupPacket.Message(bot.qqAccount, internalId, bot.sessionKey, message))
@ -56,25 +51,21 @@ internal data class GroupImpl internal constructor(override val bot: Bot, val gr
}
internal data class QQImpl internal constructor(override val bot: Bot, override val id: UInt) : ContactImpl(), QQ {
private var _profile: Profile? = null
private val _initialProfile by bot.network.SuspendLazy { updateProfile() }
override val profile: Deferred<Profile> get() = if (_profile == null) _initialProfile else CompletableDeferred(_profile!!)
override suspend fun sendMessage(message: MessageChain) =
bot.sendPacket(SendFriendMessagePacket(bot.qqAccount, id, bot.sessionKey, message))
override suspend fun updateProfile(): Profile = bot.withSession {
_profile = RequestProfileDetailsPacket(bot.qqAccount, id, sessionKey)
.sendAndExpect<RequestProfileDetailsResponse, Profile> { it.profile }
return _profile!!
override suspend fun queryProfile(): Profile = bot.withSession {
RequestProfileDetailsPacket(bot.qqAccount, id, sessionKey).sendAndExpect<RequestProfileDetailsResponse>().profile
}
override suspend fun queryPreviousNameList(): PreviousNameList = bot.withSession {
QueryPreviousNamePacket(bot.qqAccount, sessionKey, id).sendAndExpect()
}
override suspend fun queryRemark(): FriendNameRemark = bot.withSession {
QueryFriendRemarkPacket(bot.qqAccount, sessionKey, id).sendAndExpect()
}
override fun toString(): String = "QQ(${this.id})"
}

View File

@ -109,15 +109,13 @@ suspend inline fun Bot.subscribeFriendMessages(crossinline listeners: suspend Me
}.apply { listeners() }
}
private typealias MessageReplier<T> = @MessageDsl suspend T.(String) -> Message
private typealias StringReplier<T> = @MessageDsl suspend T.(String) -> String
private typealias AnyReplier<T> = @MessageDsl suspend T.(String) -> Any?
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<*>> StringReplier<T>.invoke(t: T): String =
private suspend inline operator fun <T : MessagePacket<*>> AnyReplier<T>.invoke(t: T): Any? =
this.invoke(t, t.message.stringValue)
/**
@ -217,15 +215,15 @@ class MessageSubscribersBuilder<T : MessagePacket<*>>(
content({ this@containsReply in it }) { this@content.reply(replier) }
@MessageDsl
suspend infix fun String.containsReply(replier: StringReplier<T>) =
suspend infix fun String.containsReply(replier: AnyReplier<T>) =
content({ this@containsReply in it }) { replier(this) }
@MessageDsl
suspend infix fun String.startsWithReply(replier: StringReplier<T>) =
suspend infix fun String.startsWithReply(replier: AnyReplier<T>) =
content({ it.startsWith(this@startsWithReply) }) { replier(this) }
@MessageDsl
suspend infix fun String.endswithReply(replier: StringReplier<T>) =
suspend infix fun String.endswithReply(replier: AnyReplier<T>) =
content({ it.endsWith(this@endswithReply) }) { replier(this) }
@MessageDsl
@ -234,7 +232,15 @@ class MessageSubscribersBuilder<T : MessagePacket<*>>(
}
@MessageDsl
suspend infix fun String.reply(reply: StringReplier<T>) = case(this) { this@case.reply(reply(this)) }
suspend infix fun String.reply(reply: AnyReplier<T>) = case(this) {
when (val message = reply(this)) {
is Message -> reply(message)
is Unit -> {
}
else -> reply(message.toString())
}
}
/* 易产生迷惑感

View File

@ -99,18 +99,16 @@ fun SingleMessageChain(delegate: Message): MessageChain {
/**
* 得到包含 [this] [MessageChain].
* [this] [MessageChain] 将直接返回 this
* 否则将调用 [SingleMessageChain] 构造一个唯一成员且不可修改的 [SingleMessageChainImpl]
*
* @see SingleMessageChain
* @see SingleMessageChainImpl
* 否则将调用 [MessageChain] 构造一个 [MessageChainImpl]
*/
fun Message.chain(): MessageChain = if (this is MessageChain) this else MessageChain(this)
@Suppress("NOTHING_TO_INLINE")
inline fun Message.chain(): MessageChain = if (this is MessageChain) this else MessageChain(this)
/**
* 构造 [MessageChain]
*/
@Suppress("unused")
fun List<Message>.messageChain(): MessageChain = MessageChain(this)
@Suppress("unused", "NOTHING_TO_INLINE")
inline fun List<Message>.messageChain(): MessageChain = MessageChain(this)
/**

View File

@ -32,6 +32,10 @@ import kotlin.jvm.JvmName
@UseExperimental(MiraiInternalAPI::class)
expect abstract class MessagePacket<TSubject : Contact>() : MessagePacketBase<TSubject>
interface BotExtensions {
suspend fun MessageChain.reply()
}
@MiraiInternalAPI
abstract class MessagePacketBase<TSubject : Contact> : EventPacket, BotEvent() {
internal lateinit var botVar: Bot
@ -172,7 +176,9 @@ data class FriendMessage(
/**
* 是否应被自动广播. 此为内部 API
*/
override val shouldBroadcast: Boolean get() = !previous
@MiraiInternalAPI
override val shouldBroadcast: Boolean
get() = !previous
override val subject: QQ get() = sender
}

View File

@ -49,6 +49,9 @@ actual abstract class MessagePacket<TSubject : Contact> : MessagePacketBase<TSub
suspend inline fun File.sendAsImage() = sendAsImageTo(subject)
suspend inline fun Image.downloadTo(file: File): Long = file.outputStream().use { downloadTo(it) }
/**
* 这个函数结束后不会关闭 [output]
*/
suspend inline fun Image.downloadTo(output: OutputStream): Long =
download().inputStream().use { input -> withContext(Dispatchers.IO) { input.copyTo(output) } }

View File

@ -96,6 +96,8 @@ suspend fun Bot.messageDSL() {
// sender: QQ
// it: String (MessageChain.toString)
message[Image].download()
if (this is GroupMessage) {
//如果是群消息
// group: Group
@ -112,7 +114,7 @@ suspend fun Bot.messageDSL() {
// 当收到 "我的qq" 就执行 lambda 并回复 lambda 的返回值 String
"我的qq" reply { sender.id.toString() }
"我的qq" reply { sender.id }
// 如果是这个 QQ 号发送的消息(可以是好友消息也可以是群消息)

View File

@ -108,7 +108,7 @@ class MiraiService : Service() {
// 当收到 "我的qq" 就执行 lambda 并回复 lambda 的返回值 String
"我的qq" reply { sender.id.toString() }
"我的qq" reply { sender.id }
// 当消息前缀为 "我是" 时

View File

@ -68,7 +68,6 @@ suspend fun main() {
if (this is GroupMessage) {
group.queryGroupInfo().toString().reply()
}
""
}
startsWith("profile", removePrefix = true) {
@ -77,7 +76,7 @@ suspend fun main() {
bot.getQQ(account.toUInt())
} else {
sender
}.profile.await().toString().reply()
}.queryProfile().toString().reply()
}
has<Image> {