Commit 57685d39 authored by Him188's avatar Him188

Simplify message handler

parent 265a431b
...@@ -18,13 +18,17 @@ import net.mamoe.mirai.utils.internal.coerceAtLeastOrFail ...@@ -18,13 +18,17 @@ import net.mamoe.mirai.utils.internal.coerceAtLeastOrFail
interface Group : Contact { interface Group : Contact {
val internalId: GroupInternalId val internalId: GroupInternalId
/**
* 在 [Group] 实例创建的时候查询一次. 收到各事件后
*/
val member: ContactList<Member> val member: ContactList<Member>
suspend fun getMember(id: UInt): Member suspend fun getMember(id: UInt): Member
/** /**
* 查询群资料 * 查询群资料
*/ */ // should be `suspend val` if kotlin supports in the future
suspend fun queryGroupInfo(): GroupInfo suspend fun queryGroupInfo(): GroupInfo
} }
......
...@@ -2,11 +2,10 @@ ...@@ -2,11 +2,10 @@
package net.mamoe.mirai.contact package net.mamoe.mirai.contact
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.Deferred
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.contact.data.Profile import net.mamoe.mirai.contact.data.Profile
import net.mamoe.mirai.network.BotSession 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 import net.mamoe.mirai.network.protocol.tim.packet.action.PreviousNameList
/** /**
...@@ -23,17 +22,9 @@ 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 { interface QQ : Contact {
/** /**
* 用户资料. * 查询用户资料
* 第一次获取时将会向服务器查询.
* 第一次以后则是直接得到一个用 [CompletableDeferred] 包装的值
*/ */
val profile: Deferred<Profile> suspend fun queryProfile(): Profile
/**
* 更新个人资料.
* 将会同步更新 property [profile]
*/
suspend fun updateProfile(): Profile
/** /**
* 查询曾用名. * 查询曾用名.
...@@ -43,4 +34,9 @@ interface QQ : Contact { ...@@ -43,4 +34,9 @@ interface QQ : Contact {
* - 共同群内的群名片 * - 共同群内的群名片
*/ */
suspend fun queryPreviousNameList(): PreviousNameList suspend fun queryPreviousNameList(): PreviousNameList
/**
* 查询机器人账号给这个人设置的备注
*/
suspend fun queryRemark(): FriendNameRemark
} }
\ No newline at end of file
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
package net.mamoe.mirai.contact.internal package net.mamoe.mirai.contact.internal
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.contact.* import net.mamoe.mirai.contact.*
...@@ -17,7 +15,6 @@ import net.mamoe.mirai.network.qqAccount ...@@ -17,7 +15,6 @@ import net.mamoe.mirai.network.qqAccount
import net.mamoe.mirai.network.sessionKey import net.mamoe.mirai.network.sessionKey
import net.mamoe.mirai.qqAccount import net.mamoe.mirai.qqAccount
import net.mamoe.mirai.sendPacket import net.mamoe.mirai.sendPacket
import net.mamoe.mirai.utils.SuspendLazy
import net.mamoe.mirai.withSession import net.mamoe.mirai.withSession
internal sealed class ContactImpl : Contact { internal sealed class ContactImpl : Contact {
...@@ -40,9 +37,7 @@ internal data class GroupImpl internal constructor(override val bot: Bot, val gr ...@@ -40,9 +37,7 @@ internal data class GroupImpl internal constructor(override val bot: Bot, val gr
override suspend fun getMember(id: UInt): Member = override suspend fun getMember(id: UInt): Member =
if (_members.containsKey(id)) _members[id]!! if (_members.containsKey(id)) _members[id]!!
else throw NoSuchElementException("No such member whose id is $id in group $id") /*membersLock.withLock { else throw NoSuchElementException("No such member whose id is $id in group $id")
_members.getOrPut(id) { MemberImpl(bot.getQQ(id), this) }
}*/
override suspend fun sendMessage(message: MessageChain) { override suspend fun sendMessage(message: MessageChain) {
bot.sendPacket(GroupPacket.Message(bot.qqAccount, internalId, bot.sessionKey, message)) 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 ...@@ -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 { 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) = override suspend fun sendMessage(message: MessageChain) =
bot.sendPacket(SendFriendMessagePacket(bot.qqAccount, id, bot.sessionKey, message)) bot.sendPacket(SendFriendMessagePacket(bot.qqAccount, id, bot.sessionKey, message))
override suspend fun updateProfile(): Profile = bot.withSession { override suspend fun queryProfile(): Profile = bot.withSession {
_profile = RequestProfileDetailsPacket(bot.qqAccount, id, sessionKey) RequestProfileDetailsPacket(bot.qqAccount, id, sessionKey).sendAndExpect<RequestProfileDetailsResponse>().profile
.sendAndExpect<RequestProfileDetailsResponse, Profile> { it.profile }
return _profile!!
} }
override suspend fun queryPreviousNameList(): PreviousNameList = bot.withSession { override suspend fun queryPreviousNameList(): PreviousNameList = bot.withSession {
QueryPreviousNamePacket(bot.qqAccount, sessionKey, id).sendAndExpect() 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})" override fun toString(): String = "QQ(${this.id})"
} }
......
...@@ -109,15 +109,13 @@ suspend inline fun Bot.subscribeFriendMessages(crossinline listeners: suspend Me ...@@ -109,15 +109,13 @@ suspend inline fun Bot.subscribeFriendMessages(crossinline listeners: suspend Me
}.apply { listeners() } }.apply { listeners() }
} }
private typealias MessageReplier<T> = @MessageDsl suspend T.(String) -> Message private typealias AnyReplier<T> = @MessageDsl suspend T.(String) -> Any?
private typealias StringReplier<T> = @MessageDsl suspend T.(String) -> String
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) this.invoke(t, t.message.stringValue)
@JvmName("invoke1") //Avoid Platform declaration clash @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) this.invoke(t, t.message.stringValue)
/** /**
...@@ -217,15 +215,15 @@ class MessageSubscribersBuilder<T : MessagePacket<*>>( ...@@ -217,15 +215,15 @@ class MessageSubscribersBuilder<T : MessagePacket<*>>(
content({ this@containsReply in it }) { this@content.reply(replier) } content({ this@containsReply in it }) { this@content.reply(replier) }
@MessageDsl @MessageDsl
suspend infix fun String.containsReply(replier: StringReplier<T>) = suspend infix fun String.containsReply(replier: AnyReplier<T>) =
content({ this@containsReply in it }) { replier(this) } content({ this@containsReply in it }) { replier(this) }
@MessageDsl @MessageDsl
suspend infix fun String.startsWithReply(replier: StringReplier<T>) = suspend infix fun String.startsWithReply(replier: AnyReplier<T>) =
content({ it.startsWith(this@startsWithReply) }) { replier(this) } content({ it.startsWith(this@startsWithReply) }) { replier(this) }
@MessageDsl @MessageDsl
suspend infix fun String.endswithReply(replier: StringReplier<T>) = suspend infix fun String.endswithReply(replier: AnyReplier<T>) =
content({ it.endsWith(this@endswithReply) }) { replier(this) } content({ it.endsWith(this@endswithReply) }) { replier(this) }
@MessageDsl @MessageDsl
...@@ -234,7 +232,15 @@ class MessageSubscribersBuilder<T : MessagePacket<*>>( ...@@ -234,7 +232,15 @@ class MessageSubscribersBuilder<T : MessagePacket<*>>(
} }
@MessageDsl @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())
}
}
/* 易产生迷惑感 /* 易产生迷惑感
......
...@@ -99,18 +99,16 @@ fun SingleMessageChain(delegate: Message): MessageChain { ...@@ -99,18 +99,16 @@ fun SingleMessageChain(delegate: Message): MessageChain {
/** /**
* 得到包含 [this] 的 [MessageChain]. * 得到包含 [this] 的 [MessageChain].
* 若 [this] 为 [MessageChain] 将直接返回 this * 若 [this] 为 [MessageChain] 将直接返回 this
* 否则将调用 [SingleMessageChain] 构造一个唯一成员且不可修改的 [SingleMessageChainImpl] * 否则将调用 [MessageChain] 构造一个 [MessageChainImpl]
*
* @see SingleMessageChain
* @see SingleMessageChainImpl
*/ */
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] * 构造 [MessageChain]
*/ */
@Suppress("unused") @Suppress("unused", "NOTHING_TO_INLINE")
fun List<Message>.messageChain(): MessageChain = MessageChain(this) inline fun List<Message>.messageChain(): MessageChain = MessageChain(this)
/** /**
......
...@@ -32,6 +32,10 @@ import kotlin.jvm.JvmName ...@@ -32,6 +32,10 @@ import kotlin.jvm.JvmName
@UseExperimental(MiraiInternalAPI::class) @UseExperimental(MiraiInternalAPI::class)
expect abstract class MessagePacket<TSubject : Contact>() : MessagePacketBase<TSubject> expect abstract class MessagePacket<TSubject : Contact>() : MessagePacketBase<TSubject>
interface BotExtensions {
suspend fun MessageChain.reply()
}
@MiraiInternalAPI @MiraiInternalAPI
abstract class MessagePacketBase<TSubject : Contact> : EventPacket, BotEvent() { abstract class MessagePacketBase<TSubject : Contact> : EventPacket, BotEvent() {
internal lateinit var botVar: Bot internal lateinit var botVar: Bot
...@@ -172,7 +176,9 @@ data class FriendMessage( ...@@ -172,7 +176,9 @@ data class FriendMessage(
/** /**
* 是否应被自动广播. 此为内部 API * 是否应被自动广播. 此为内部 API
*/ */
override val shouldBroadcast: Boolean get() = !previous @MiraiInternalAPI
override val shouldBroadcast: Boolean
get() = !previous
override val subject: QQ get() = sender override val subject: QQ get() = sender
} }
......
...@@ -49,6 +49,9 @@ actual abstract class MessagePacket<TSubject : Contact> : MessagePacketBase<TSub ...@@ -49,6 +49,9 @@ actual abstract class MessagePacket<TSubject : Contact> : MessagePacketBase<TSub
suspend inline fun File.sendAsImage() = sendAsImageTo(subject) suspend inline fun File.sendAsImage() = sendAsImageTo(subject)
suspend inline fun Image.downloadTo(file: File): Long = file.outputStream().use { downloadTo(it) } suspend inline fun Image.downloadTo(file: File): Long = file.outputStream().use { downloadTo(it) }
/**
* 这个函数结束后不会关闭 [output]
*/
suspend inline fun Image.downloadTo(output: OutputStream): Long = suspend inline fun Image.downloadTo(output: OutputStream): Long =
download().inputStream().use { input -> withContext(Dispatchers.IO) { input.copyTo(output) } } download().inputStream().use { input -> withContext(Dispatchers.IO) { input.copyTo(output) } }
......
...@@ -96,6 +96,8 @@ suspend fun Bot.messageDSL() { ...@@ -96,6 +96,8 @@ suspend fun Bot.messageDSL() {
// sender: QQ // sender: QQ
// it: String (MessageChain.toString) // it: String (MessageChain.toString)
message[Image].download()
if (this is GroupMessage) { if (this is GroupMessage) {
//如果是群消息 //如果是群消息
// group: Group // group: Group
...@@ -112,7 +114,7 @@ suspend fun Bot.messageDSL() { ...@@ -112,7 +114,7 @@ suspend fun Bot.messageDSL() {
// 当收到 "我的qq" 就执行 lambda 并回复 lambda 的返回值 String // 当收到 "我的qq" 就执行 lambda 并回复 lambda 的返回值 String
"我的qq" reply { sender.id.toString() } "我的qq" reply { sender.id }
// 如果是这个 QQ 号发送的消息(可以是好友消息也可以是群消息) // 如果是这个 QQ 号发送的消息(可以是好友消息也可以是群消息)
......
...@@ -108,7 +108,7 @@ class MiraiService : Service() { ...@@ -108,7 +108,7 @@ class MiraiService : Service() {
// 当收到 "我的qq" 就执行 lambda 并回复 lambda 的返回值 String // 当收到 "我的qq" 就执行 lambda 并回复 lambda 的返回值 String
"我的qq" reply { sender.id.toString() } "我的qq" reply { sender.id }
// 当消息前缀为 "我是" 时 // 当消息前缀为 "我是" 时
......
...@@ -68,7 +68,6 @@ suspend fun main() { ...@@ -68,7 +68,6 @@ suspend fun main() {
if (this is GroupMessage) { if (this is GroupMessage) {
group.queryGroupInfo().toString().reply() group.queryGroupInfo().toString().reply()
} }
""
} }
startsWith("profile", removePrefix = true) { startsWith("profile", removePrefix = true) {
...@@ -77,7 +76,7 @@ suspend fun main() { ...@@ -77,7 +76,7 @@ suspend fun main() {
bot.getQQ(account.toUInt()) bot.getQQ(account.toUInt())
} else { } else {
sender sender
}.profile.await().toString().reply() }.queryProfile().toString().reply()
} }
has<Image> { has<Image> {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment