Commit 0334d33d authored by Him188's avatar Him188

Extensions of subscribers for Bot

parent cb320dd9
...@@ -21,60 +21,38 @@ enum class ListeningStatus { ...@@ -21,60 +21,38 @@ enum class ListeningStatus {
// region 顶层方法 // region 顶层方法
suspend inline fun <reified E : Event> subscribe(noinline handler: suspend (E) -> ListeningStatus) = suspend inline fun <reified E : Event> subscribe(noinline handler: suspend (E) -> ListeningStatus) = E::class.subscribe(handler)
E::class.subscribe(handler)
suspend inline fun <reified E : Event> subscribeAlways(noinline listener: suspend (E) -> Unit) = suspend inline fun <reified E : Event> subscribeAlways(noinline listener: suspend (E) -> Unit) = E::class.subscribeAlways(listener)
E::class.subscribeAlways(listener)
suspend inline fun <reified E : Event> subscribeOnce(noinline listener: suspend (E) -> Unit) = suspend inline fun <reified E : Event> subscribeOnce(noinline listener: suspend (E) -> Unit) = E::class.subscribeOnce(listener)
E::class.subscribeOnce(listener)
suspend inline fun <reified E : Event, T> subscribeUntil(valueIfStop: T, noinline listener: suspend (E) -> T) = suspend inline fun <reified E : Event, T> subscribeUntil(valueIfStop: T, noinline listener: suspend (E) -> T) = E::class.subscribeUntil(valueIfStop, listener)
E::class.subscribeUntil(valueIfStop, listener) suspend inline fun <reified E : Event> subscribeUntilFalse(noinline listener: suspend (E) -> Boolean) = E::class.subscribeUntilFalse(listener)
suspend inline fun <reified E : Event> subscribeUntilTrue(noinline listener: suspend (E) -> Boolean) = E::class.subscribeUntilTrue(listener)
suspend inline fun <reified E : Event> subscribeUntilNull(noinline listener: suspend (E) -> Any?) = E::class.subscribeUntilNull(listener)
suspend inline fun <reified E : Event> subscribeUntilFalse(noinline listener: suspend (E) -> Boolean) =
E::class.subscribeUntilFalse(listener)
suspend inline fun <reified E : Event> subscribeUntilTrue(noinline listener: suspend (E) -> Boolean) = suspend inline fun <reified E : Event, T> subscribeWhile(valueIfContinue: T, noinline listener: suspend (E) -> T) = E::class.subscribeWhile(valueIfContinue, listener)
E::class.subscribeUntilTrue(listener) suspend inline fun <reified E : Event> subscribeWhileFalse(noinline listener: suspend (E) -> Boolean) = E::class.subscribeWhileFalse(listener)
suspend inline fun <reified E : Event> subscribeWhileTrue(noinline listener: suspend (E) -> Boolean) = E::class.subscribeWhileTrue(listener)
suspend inline fun <reified E : Event> subscribeUntilNull(noinline listener: suspend (E) -> Any?) = suspend inline fun <reified E : Event> subscribeWhileNull(noinline listener: suspend (E) -> Any?) = E::class.subscribeWhileNull(listener)
E::class.subscribeUntilNull(listener)
suspend inline fun <reified E : Event, T> subscribeWhile(valueIfContinue: T, noinline listener: suspend (E) -> T) =
E::class.subscribeWhile(valueIfContinue, listener)
suspend inline fun <reified E : Event> subscribeWhileFalse(noinline listener: suspend (E) -> Boolean) =
E::class.subscribeWhileFalse(listener)
suspend inline fun <reified E : Event> subscribeWhileTrue(noinline listener: suspend (E) -> Boolean) =
E::class.subscribeWhileTrue(listener)
suspend inline fun <reified E : Event> subscribeWhileNull(noinline listener: suspend (E) -> Any?) =
E::class.subscribeWhileNull(listener)
// endregion // endregion
// region KClass 的扩展方法 (不推荐) // region KClass 的扩展方法 (不推荐)
suspend fun <E : Event> KClass<E>.subscribe(handler: suspend (E) -> ListeningStatus) = suspend fun <E : Event> KClass<E>.subscribe(handler: suspend (E) -> ListeningStatus) = this.subscribeInternal(Handler(handler))
this.subscribeInternal(Handler(handler))
suspend fun <E : Event> KClass<E>.subscribeAlways(listener: suspend (E) -> Unit) = suspend fun <E : Event> KClass<E>.subscribeAlways(listener: suspend (E) -> Unit) = this.subscribeInternal(Handler { listener(it); ListeningStatus.LISTENING })
this.subscribeInternal(Handler { listener(it); ListeningStatus.LISTENING })
suspend fun <E : Event> KClass<E>.subscribeOnce(listener: suspend (E) -> Unit) = suspend fun <E : Event> KClass<E>.subscribeOnce(listener: suspend (E) -> Unit) = this.subscribeInternal(Handler { listener(it); ListeningStatus.STOPPED })
this.subscribeInternal(Handler { listener(it); ListeningStatus.STOPPED })
suspend fun <E : Event, T> KClass<E>.subscribeUntil(valueIfStop: T, listener: suspend (E) -> T) = suspend fun <E : Event, T> KClass<E>.subscribeUntil(valueIfStop: T, listener: suspend (E) -> T) =
subscribeInternal(Handler { if (listener(it) === valueIfStop) ListeningStatus.STOPPED else ListeningStatus.LISTENING }) subscribeInternal(Handler { if (listener(it) === valueIfStop) ListeningStatus.STOPPED else ListeningStatus.LISTENING })
suspend fun <E : Event> KClass<E>.subscribeUntilFalse(listener: suspend (E) -> Boolean) = suspend fun <E : Event> KClass<E>.subscribeUntilFalse(listener: suspend (E) -> Boolean) = subscribeUntil(false, listener)
subscribeUntil(false, listener)
suspend fun <E : Event> KClass<E>.subscribeUntilTrue(listener: suspend (E) -> Boolean) = subscribeUntil(true, listener) suspend fun <E : Event> KClass<E>.subscribeUntilTrue(listener: suspend (E) -> Boolean) = subscribeUntil(true, listener)
suspend fun <E : Event> KClass<E>.subscribeUntilNull(listener: suspend (E) -> Any?) = subscribeUntil(null, listener) suspend fun <E : Event> KClass<E>.subscribeUntilNull(listener: suspend (E) -> Any?) = subscribeUntil(null, listener)
...@@ -82,9 +60,7 @@ suspend fun <E : Event> KClass<E>.subscribeUntilNull(listener: suspend (E) -> An ...@@ -82,9 +60,7 @@ suspend fun <E : Event> KClass<E>.subscribeUntilNull(listener: suspend (E) -> An
suspend fun <E : Event, T> KClass<E>.subscribeWhile(valueIfContinue: T, listener: suspend (E) -> T) = suspend fun <E : Event, T> KClass<E>.subscribeWhile(valueIfContinue: T, listener: suspend (E) -> T) =
subscribeInternal(Handler { if (listener(it) !== valueIfContinue) ListeningStatus.STOPPED else ListeningStatus.LISTENING }) subscribeInternal(Handler { if (listener(it) !== valueIfContinue) ListeningStatus.STOPPED else ListeningStatus.LISTENING })
suspend fun <E : Event> KClass<E>.subscribeWhileFalse(listener: suspend (E) -> Boolean) = suspend fun <E : Event> KClass<E>.subscribeWhileFalse(listener: suspend (E) -> Boolean) = subscribeWhile(false, listener)
subscribeWhile(false, listener)
suspend fun <E : Event> KClass<E>.subscribeWhileTrue(listener: suspend (E) -> Boolean) = subscribeWhile(true, listener) suspend fun <E : Event> KClass<E>.subscribeWhileTrue(listener: suspend (E) -> Boolean) = subscribeWhile(true, listener)
suspend fun <E : Event> KClass<E>.subscribeWhileNull(listener: suspend (E) -> Any?) = subscribeWhile(null, listener) suspend fun <E : Event> KClass<E>.subscribeWhileNull(listener: suspend (E) -> Any?) = subscribeWhile(null, listener)
...@@ -106,8 +82,7 @@ suspend fun <E : Event> KClass<E>.subscribeAll(listeners: suspend ListenerBuilde ...@@ -106,8 +82,7 @@ suspend fun <E : Event> KClass<E>.subscribeAll(listeners: suspend ListenerBuilde
* 监听一个事件. 可同时进行多种方式的监听 * 监听一个事件. 可同时进行多种方式的监听
* @see ListenerBuilder * @see ListenerBuilder
*/ */
suspend inline fun <reified E : Event> subscribeAll(noinline listeners: suspend ListenerBuilder<E>.() -> Unit) = suspend inline fun <reified E : Event> subscribeAll(noinline listeners: suspend ListenerBuilder<E>.() -> Unit) = E::class.subscribeAll(listeners)
E::class.subscribeAll(listeners)
/** /**
* 监听构建器. 可同时进行多种方式的监听 * 监听构建器. 可同时进行多种方式的监听
...@@ -135,17 +110,13 @@ inline class ListenerBuilder<out E : Event>( ...@@ -135,17 +110,13 @@ inline class ListenerBuilder<out E : Event>(
suspend fun always(listener: suspend (E) -> Unit) = handler { listener(it); ListeningStatus.LISTENING } suspend fun always(listener: suspend (E) -> Unit) = handler { listener(it); ListeningStatus.LISTENING }
suspend fun <T> until(until: T, listener: suspend (E) -> T) = suspend fun <T> until(until: T, listener: suspend (E) -> T) = handler { if (listener(it) === until) ListeningStatus.STOPPED else ListeningStatus.LISTENING }
handler { if (listener(it) === until) ListeningStatus.STOPPED else ListeningStatus.LISTENING }
suspend fun untilFalse(listener: suspend (E) -> Boolean) = until(false, listener) suspend fun untilFalse(listener: suspend (E) -> Boolean) = until(false, listener)
suspend fun untilTrue(listener: suspend (E) -> Boolean) = until(true, listener) suspend fun untilTrue(listener: suspend (E) -> Boolean) = until(true, listener)
suspend fun untilNull(listener: suspend (E) -> Any?) = until(null, listener) suspend fun untilNull(listener: suspend (E) -> Any?) = until(null, listener)
suspend fun <T> `while`(until: T, listener: suspend (E) -> T) = suspend fun <T> `while`(until: T, listener: suspend (E) -> T) = handler { if (listener(it) !== until) ListeningStatus.STOPPED else ListeningStatus.LISTENING }
handler { if (listener(it) !== until) ListeningStatus.STOPPED else ListeningStatus.LISTENING }
suspend fun whileFalse(listener: suspend (E) -> Boolean) = `while`(false, listener) suspend fun whileFalse(listener: suspend (E) -> Boolean) = `while`(false, listener)
suspend fun whileTrue(listener: suspend (E) -> Boolean) = `while`(true, listener) suspend fun whileTrue(listener: suspend (E) -> Boolean) = `while`(true, listener)
suspend fun whileNull(listener: suspend (E) -> Any?) = `while`(null, listener) suspend fun whileNull(listener: suspend (E) -> Any?) = `while`(null, listener)
......
@file:Suppress("unused")
package net.mamoe.mirai.event
import net.mamoe.mirai.Bot
import net.mamoe.mirai.event.internal.HandlerWithBot
import net.mamoe.mirai.event.internal.subscribeInternal
import kotlin.reflect.KClass
/**
* 该文件为所有的含 Bot 的事件的订阅方法
*
* 与不含 bot 的相比, 在监听时将会有 `this: Bot`
* 在 demo 中找到实例可很快了解区别.
*/
// region 顶层方法
suspend inline fun <reified E : Event> Bot.subscribe(noinline handler: suspend Bot.(E) -> ListeningStatus) = E::class.subscribe(this, handler)
suspend inline fun <reified E : Event> Bot.subscribeAlways(noinline listener: suspend Bot.(E) -> Unit) = E::class.subscribeAlways(this, listener)
suspend inline fun <reified E : Event> Bot.subscribeOnce(noinline listener: suspend Bot.(E) -> Unit) = E::class.subscribeOnce(this, listener)
suspend inline fun <reified E : Event, T> Bot.subscribeUntil(valueIfStop: T, noinline listener: suspend Bot.(E) -> T) = E::class.subscribeUntil(this, valueIfStop, listener)
suspend inline fun <reified E : Event> Bot.subscribeUntilFalse(noinline listener: suspend Bot.(E) -> Boolean) = E::class.subscribeUntilFalse(this, listener)
suspend inline fun <reified E : Event> Bot.subscribeUntilTrue(noinline listener: suspend Bot.(E) -> Boolean) = E::class.subscribeUntilTrue(this, listener)
suspend inline fun <reified E : Event> Bot.subscribeUntilNull(noinline listener: suspend Bot.(E) -> Any?) = E::class.subscribeUntilNull(this, listener)
suspend inline fun <reified E : Event, T> Bot.subscribeWhile(valueIfContinue: T, noinline listener: suspend Bot.(E) -> T) = E::class.subscribeWhile(this, valueIfContinue, listener)
suspend inline fun <reified E : Event> Bot.subscribeWhileFalse(noinline listener: suspend Bot.(E) -> Boolean) = E::class.subscribeWhileFalse(this, listener)
suspend inline fun <reified E : Event> Bot.subscribeWhileTrue(noinline listener: suspend Bot.(E) -> Boolean) = E::class.subscribeWhileTrue(this, listener)
suspend inline fun <reified E : Event> Bot.subscribeWhileNull(noinline listener: suspend Bot.(E) -> Any?) = E::class.subscribeWhileNull(this, listener)
// endregion
// region KClass 的扩展方法 (不推荐)
suspend fun <E : Event> KClass<E>.subscribe(bot: Bot, handler: suspend Bot.(E) -> ListeningStatus) = this.subscribeInternal(HandlerWithBot(bot, handler))
suspend fun <E : Event> KClass<E>.subscribeAlways(bot: Bot, listener: suspend Bot.(E) -> Unit) =
this.subscribeInternal(HandlerWithBot(bot) { listener(it); ListeningStatus.LISTENING })
suspend fun <E : Event> KClass<E>.subscribeOnce(bot: Bot, listener: suspend Bot.(E) -> Unit) = this.subscribeInternal(HandlerWithBot(bot) { listener(it); ListeningStatus.STOPPED })
suspend fun <E : Event, T> KClass<E>.subscribeUntil(bot: Bot, valueIfStop: T, listener: suspend Bot.(E) -> T) =
subscribeInternal(HandlerWithBot(bot) { if (listener(it) === valueIfStop) ListeningStatus.STOPPED else ListeningStatus.LISTENING })
suspend fun <E : Event> KClass<E>.subscribeUntilFalse(bot: Bot, listener: suspend Bot.(E) -> Boolean) = subscribeUntil(bot, false, listener)
suspend fun <E : Event> KClass<E>.subscribeUntilTrue(bot: Bot, listener: suspend Bot.(E) -> Boolean) = subscribeUntil(bot, true, listener)
suspend fun <E : Event> KClass<E>.subscribeUntilNull(bot: Bot, listener: suspend Bot.(E) -> Any?) = subscribeUntil(bot, null, listener)
suspend fun <E : Event, T> KClass<E>.subscribeWhile(bot: Bot, valueIfContinue: T, listener: suspend Bot.(E) -> T) =
subscribeInternal(HandlerWithBot(bot) { if (listener(it) !== valueIfContinue) ListeningStatus.STOPPED else ListeningStatus.LISTENING })
suspend fun <E : Event> KClass<E>.subscribeWhileFalse(bot: Bot, listener: suspend Bot.(E) -> Boolean) = subscribeWhile(bot, false, listener)
suspend fun <E : Event> KClass<E>.subscribeWhileTrue(bot: Bot, listener: suspend Bot.(E) -> Boolean) = subscribeWhile(bot, true, listener)
suspend fun <E : Event> KClass<E>.subscribeWhileNull(bot: Bot, listener: suspend Bot.(E) -> Any?) = subscribeWhile(bot, null, listener)
// endregion
\ No newline at end of file
...@@ -3,6 +3,7 @@ package net.mamoe.mirai.event.internal ...@@ -3,6 +3,7 @@ package net.mamoe.mirai.event.internal
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.sync.withLock
import net.mamoe.mirai.Bot
import net.mamoe.mirai.event.Event import net.mamoe.mirai.event.Event
import net.mamoe.mirai.event.EventScope import net.mamoe.mirai.event.EventScope
import net.mamoe.mirai.event.ListeningStatus import net.mamoe.mirai.event.ListeningStatus
...@@ -49,18 +50,24 @@ internal suspend fun <E : Event> KClass<E>.subscribeInternal(listener: Listener< ...@@ -49,18 +50,24 @@ internal suspend fun <E : Event> KClass<E>.subscribeInternal(listener: Listener<
* *
* @author Him188moe * @author Him188moe
*/ */
internal interface Listener<in E : Event> { sealed class Listener<in E : Event> {
suspend fun onEvent(event: E): ListeningStatus abstract suspend fun onEvent(event: E): ListeningStatus
} }
/** /**
* Lambda 监听器. * Lambda 监听器.
* 不推荐直接使用该类 * 不推荐直接使用该类
*/ */
class Handler<E : Event>(val handler: suspend (E) -> ListeningStatus) : Listener<E> { class Handler<E : Event>(val handler: suspend (E) -> ListeningStatus) : Listener<E>() {
override suspend fun onEvent(event: E): ListeningStatus = handler.invoke(event) override suspend fun onEvent(event: E): ListeningStatus = handler.invoke(event)
} }
class HandlerWithBot<E : Event>(val bot: Bot, val handler: suspend Bot.(E) -> ListeningStatus) : Listener<E>() {
override suspend fun onEvent(event: E): ListeningStatus = with(bot) {
handler(event)
}
}
/** /**
* 这个事件类的监听器 list * 这个事件类的监听器 list
*/ */
...@@ -105,7 +112,6 @@ internal object EventListenerManger { ...@@ -105,7 +112,6 @@ internal object EventListenerManger {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
internal suspend fun <E : Event> E.broadcastInternal(): E { internal suspend fun <E : Event> E.broadcastInternal(): E {
//FIXME 若一个 listener 阻塞, 则这个事件全部阻塞.
suspend fun callListeners(listeners: EventListeners<in E>) = listeners.mainMutex.withLock { suspend fun callListeners(listeners: EventListeners<in E>) = listeners.mainMutex.withLock {
listeners.inlinedRemoveIf { it.onEvent(this) == ListeningStatus.STOPPED } listeners.inlinedRemoveIf { it.onEvent(this) == ListeningStatus.STOPPED }
} }
......
...@@ -91,6 +91,6 @@ class BotSession( ...@@ -91,6 +91,6 @@ class BotSession(
suspend fun BotSession.distributePacket(packet: ServerPacket) = this.socket.distributePacket(packet) suspend fun BotSession.distributePacket(packet: ServerPacket) = this.socket.distributePacket(packet)
val BotSession.isOpen: Boolean get() = socket.isOpen val BotSession.isOpen: Boolean get() = socket.isOpen
val BotSession.qqAccount: UInt get() = bot.account.account val BotSession.qqAccount: UInt get() = bot.account.id
val <T : BotNetworkHandler<*>> T.session get() = this[ActionPacketHandler].session val <T : BotNetworkHandler<*>> T.session get() = this[ActionPacketHandler].session
\ No newline at end of file
...@@ -4,7 +4,7 @@ import kotlinx.coroutines.* ...@@ -4,7 +4,7 @@ import kotlinx.coroutines.*
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.sync.withLock
import kotlinx.io.core.* import kotlinx.io.core.*
import net.mamoe.mirai.* import net.mamoe.mirai.Bot
import net.mamoe.mirai.event.ListeningStatus import net.mamoe.mirai.event.ListeningStatus
import net.mamoe.mirai.event.broadcast import net.mamoe.mirai.event.broadcast
import net.mamoe.mirai.event.events.BeforePacketSendEvent import net.mamoe.mirai.event.events.BeforePacketSendEvent
...@@ -22,6 +22,7 @@ import net.mamoe.mirai.network.protocol.tim.packet.UnknownServerPacket ...@@ -22,6 +22,7 @@ import net.mamoe.mirai.network.protocol.tim.packet.UnknownServerPacket
import net.mamoe.mirai.network.protocol.tim.packet.event.ServerEventPacket import net.mamoe.mirai.network.protocol.tim.packet.event.ServerEventPacket
import net.mamoe.mirai.network.protocol.tim.packet.login.* import net.mamoe.mirai.network.protocol.tim.packet.login.*
import net.mamoe.mirai.network.session import net.mamoe.mirai.network.session
import net.mamoe.mirai.qqAccount
import net.mamoe.mirai.utils.* import net.mamoe.mirai.utils.*
import net.mamoe.mirai.utils.io.parseServerPacket import net.mamoe.mirai.utils.io.parseServerPacket
import net.mamoe.mirai.utils.io.toUHexString import net.mamoe.mirai.utils.io.toUHexString
...@@ -184,7 +185,9 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) : ...@@ -184,7 +185,9 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
packet.decode() packet.decode()
} catch (e: Exception) { } catch (e: Exception) {
e.log() e.log()
bot.printPacketDebugging(packet) bot.logger.logDebug("Packet=$packet")
bot.logger.logDebug("Packet size=" + packet.input.readBytes().size)
bot.logger.logDebug("Packet data=" + packet.input.readBytes().toUHexString())
packet.close() packet.close()
throw e throw e
} }
...@@ -192,7 +195,7 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) : ...@@ -192,7 +195,7 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
packet.use { packet.use {
val name = packet::class.simpleName val name = packet::class.simpleName
if (name != null && !name.endsWith("Encrypted") && !name.endsWith("Raw")) { if (name != null && !name.endsWith("Encrypted") && !name.endsWith("Raw")) {
bot.logCyan("Packet received: $packet") bot.logger.logCyan("Packet received: $packet")
} }
handlersLock.withLock { handlersLock.withLock {
...@@ -258,7 +261,7 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) : ...@@ -258,7 +261,7 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
} }
} }
bot.logGreen("Packet sent: $packet") bot.logger.logGreen("Packet sent: $packet")
PacketSentEvent(bot, packet).broadcast() PacketSentEvent(bot, packet).broadcast()
...@@ -374,7 +377,7 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) : ...@@ -374,7 +377,7 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
is ServerCaptchaTransmissionPacket -> { is ServerCaptchaTransmissionPacket -> {
//packet is ServerCaptchaWrongPacket //packet is ServerCaptchaWrongPacket
if (this.captchaSectionId == 0) { if (this.captchaSectionId == 0) {
bot.logError("验证码错误, 请重新输入") bot.logger.logPurple("验证码错误, 请重新输入")
this.captchaSectionId = 1 this.captchaSectionId = 1
this.captchaCache = null this.captchaCache = null
} }
...@@ -460,7 +463,7 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) : ...@@ -460,7 +463,7 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
sessionKey sessionKey
).sendAndExpect<HeartbeatPacket.Response>().join() ).sendAndExpect<HeartbeatPacket.Response>().join()
} == null) { } == null) {
bot.logPurple("Heartbeat timed out") bot.logger.logPurple("Heartbeat timed out")
bot.reinitializeNetworkHandler(configuration, HeartbeatTimeoutException()) bot.reinitializeNetworkHandler(configuration, HeartbeatTimeoutException())
return@launch return@launch
} }
......
package net.mamoe.mirai.network.protocol.tim.handler package net.mamoe.mirai.network.protocol.tim.handler
import net.mamoe.mirai.contact.Group import net.mamoe.mirai.contact.Group
import net.mamoe.mirai.contact.GroupId
import net.mamoe.mirai.contact.QQ import net.mamoe.mirai.contact.QQ
import net.mamoe.mirai.event.broadcast import net.mamoe.mirai.event.broadcast
import net.mamoe.mirai.event.events.FriendMessageEvent import net.mamoe.mirai.event.events.FriendMessageEvent
import net.mamoe.mirai.event.events.GroupMessageEvent import net.mamoe.mirai.event.events.GroupMessageEvent
import net.mamoe.mirai.getGroupByNumber import net.mamoe.mirai.getGroup
import net.mamoe.mirai.getQQ import net.mamoe.mirai.getQQ
import net.mamoe.mirai.message.MessageChain import net.mamoe.mirai.message.MessageChain
import net.mamoe.mirai.network.BotSession import net.mamoe.mirai.network.BotSession
...@@ -41,11 +42,11 @@ class EventPacketHandler(session: BotSession) : PacketHandler(session) { ...@@ -41,11 +42,11 @@ class EventPacketHandler(session: BotSession) : PacketHandler(session) {
} }
is ServerGroupMessageEventPacket -> { is ServerGroupMessageEventPacket -> {
if (packet.qq == bot.account.account) return if (packet.qq == bot.account.id) return
GroupMessageEvent( GroupMessageEvent(
bot, bot,
group = bot.getGroupByNumber(packet.groupNumber), group = bot.getGroup(GroupId(packet.groupNumber)),
sender = bot.getQQ(packet.qq), sender = bot.getQQ(packet.qq),
message = packet.message, message = packet.message,
senderName = packet.senderName, senderName = packet.senderName,
...@@ -68,10 +69,10 @@ class EventPacketHandler(session: BotSession) : PacketHandler(session) { ...@@ -68,10 +69,10 @@ class EventPacketHandler(session: BotSession) : PacketHandler(session) {
} }
suspend fun sendFriendMessage(qq: QQ, message: MessageChain) { suspend fun sendFriendMessage(qq: QQ, message: MessageChain) {
session.socket.sendPacket(SendFriendMessagePacket(session.bot.account.account, qq.number, session.sessionKey, message)) session.socket.sendPacket(SendFriendMessagePacket(session.bot.account.id, qq.id, session.sessionKey, message))
} }
suspend fun sendGroupMessage(group: Group, message: MessageChain) { suspend fun sendGroupMessage(group: Group, message: MessageChain) {
session.socket.sendPacket(SendGroupMessagePacket(session.bot.account.account, group.groupId, session.sessionKey, message)) session.socket.sendPacket(SendGroupMessagePacket(session.bot.account.id, group.internalId, session.sessionKey, message))
} }
} }
\ No newline at end of file
@file:Suppress("EXPERIMENTAL_API_USAGE")
package net.mamoe.mirai.utils
import net.mamoe.mirai.contact.Contact
class ContactList<C : Contact> : MutableMap<UInt, C> by mutableMapOf()
\ No newline at end of file
@file:Suppress("EXPERIMENTAL_API_USAGE")
package net.mamoe.mirai.contact
import net.mamoe.mirai.Bot
import net.mamoe.mirai.message.MessageChain
import net.mamoe.mirai.network.protocol.tim.handler.EventPacketHandler
import net.mamoe.mirai.utils.ContactList
/**
* 联系人.
*
* A contact is a [QQ] or a [Group] for one particular [Bot] instance only.
*
* @param bot the Owner [Bot]
* @param number the id number of this contact
* @author Him188moe
*/
@Suppress("unused")
actual sealed class Contact actual constructor(bot: Bot, number: UInt) : PlatformContactBase(bot, number) {
abstract override suspend fun sendMessage(message: MessageChain)
abstract override suspend fun sendXMLMessage(message: String)
//
// /**
// * 阻塞发送一个消息. 仅应在 Java 使用
// */
// fun blockingSendMessage(chain: MessageChain) = runBlocking { sendMessage(chain) }
//
// /**
// * 阻塞发送一个消息. 仅应在 Java 使用
// */
// fun blockingSendMessage(message: Message) = runBlocking { sendMessage(message) }
//
// /**
// * 阻塞发送一个消息. 仅应在 Java 使用
// */
// fun blockingSendMessage(plain: String) = runBlocking { sendMessage(plain) }
//
// /**
// * 异步发送一个消息. 仅应在 Java 使用
// */
// fun asyncSendMessage(chain: MessageChain) = bot.network.launch { sendMessage(chain) }
//
// /**
// * 异步发送一个消息. 仅应在 Java 使用
// */
// fun asyncSendMessage(message: Message) = bot.network.launch { sendMessage(message) }
//
// /**
// * 异步发送一个消息. 仅应在 Java 使用
// */
// fun asyncSendMessage(plain: String) = bot.network.launch { sendMessage(plain) }
}
/**
* 群.
*
* Group ID 与 Group Number 并不是同一个值.
* - Group Number([Group.number]) 是通常使用的群号码.(在 QQ 客户端中可见)
* - Group ID([Group.groupId]) 是与服务器通讯时使用的 id.(在 QQ 客户端中不可见)
*
* Java 获取 groupNumber: `group.getNumber()`
* Java 获取所属 bot: `group.getBot()`
* Java 获取群成员列表: `group.getMembers()`
* Java 获取 groupId: `group.getGroupId()`
*
* Java 调用 [groupNumberToId] : `Group.groupNumberToId(number)`
* @author Him188moe
*/
actual class Group actual constructor(bot: Bot, number: UInt) : Contact(bot, number) {
actual val groupId = groupNumberToId(number)
actual val members: ContactList<QQ>
//todo members
get() = throw UnsupportedOperationException("Not yet supported")
actual override suspend fun sendMessage(message: MessageChain) {
bot.network[EventPacketHandler].sendGroupMessage(this, message)
}
actual override suspend fun sendXMLMessage(message: String) {
}
actual companion object
}
/**
* QQ 账号.
* 注意: 一个 [QQ] 实例并不是独立的, 它属于一个 [Bot].
*
* Java 获取 qq 号: `qq.getNumber()`
* Java 获取所属 bot: `qq.getBot()`
*
* A QQ instance helps you to receive event from or sendPacket event to.
* Notice that, one QQ instance belong to one [Bot], that is, QQ instances from different [Bot] are NOT the same.
*
* @author Him188moe
*/
actual class QQ actual constructor(bot: Bot, number: UInt) : Contact(bot, number) {
actual override suspend fun sendMessage(message: MessageChain) {
bot.network[EventPacketHandler].sendFriendMessage(this, message)
}
actual override suspend fun sendXMLMessage(message: String) {
TODO()
}
}
\ No newline at end of file
...@@ -2,11 +2,11 @@ ...@@ -2,11 +2,11 @@
package demo1 package demo1
import kotlinx.coroutines.* import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.withTimeoutOrNull
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.BotAccount import net.mamoe.mirai.BotAccount
import net.mamoe.mirai.contact.Group
import net.mamoe.mirai.contact.QQ
import net.mamoe.mirai.event.events.FriendMessageEvent import net.mamoe.mirai.event.events.FriendMessageEvent
import net.mamoe.mirai.event.events.GroupMessageEvent import net.mamoe.mirai.event.events.GroupMessageEvent
import net.mamoe.mirai.event.subscribeAll import net.mamoe.mirai.event.subscribeAll
...@@ -24,7 +24,6 @@ import net.mamoe.mirai.qqAccount ...@@ -24,7 +24,6 @@ import net.mamoe.mirai.qqAccount
import net.mamoe.mirai.utils.* import net.mamoe.mirai.utils.*
import net.mamoe.mirai.utils.io.toUHexString import net.mamoe.mirai.utils.io.toUHexString
import java.io.File import java.io.File
import javax.imageio.ImageIO
private fun readTestAccount(): BotAccount? { private fun readTestAccount(): BotAccount? {
val file = File("testAccount.txt") val file = File("testAccount.txt")
...@@ -42,10 +41,12 @@ private fun readTestAccount(): BotAccount? { ...@@ -42,10 +41,12 @@ private fun readTestAccount(): BotAccount? {
@Suppress("UNUSED_VARIABLE") @Suppress("UNUSED_VARIABLE")
suspend fun main() = coroutineScope { suspend fun main() = coroutineScope {
val bot = Bot(readTestAccount() ?: BotAccount(//填写你的账号 val bot = Bot(
account = 1994701121u, readTestAccount() ?: BotAccount(//填写你的账号
id = 1994701121u,
password = "123456" password = "123456"
), PlatformLogger()) ), PlatformLogger()
)
bot.login { bot.login {
randomDeviceName = false randomDeviceName = false
...@@ -57,18 +58,22 @@ suspend fun main() = coroutineScope { ...@@ -57,18 +58,22 @@ suspend fun main() = coroutineScope {
} }
subscribeAlways<GroupMessageEvent> { subscribeAlways<GroupMessageEvent> {
if (it.message eq "复读" && it.group.groupId == 580266363u) { if (it.message eq "复读" && it.group.internalId == 580266363u) {
it.reply(it.message) it.reply(it.message)
} }
} }
//提供泛型以监听事件 // 使用 Bot 的扩展方法监听, 将在处理事件时得到一个 this: Bot.
subscribeAlways<FriendMessageEvent> { // 这样可以很方便地调用 Bot 内的一些扩展方法如 UInt.qq():QQ
//获取第一个纯文本消息, 获取不到会抛出 NoSuchElementException bot.subscribeAlways<FriendMessageEvent> {
//val firstText = it.message.first<PlainText>() // this: Bot
// it: FriendMessageEvent
// 获取第一个纯文本消息, 获取不到会抛出 NoSuchElementException
// val firstText = it.message.first<PlainText>()
val firstText = it.message.firstOrNull<PlainText>() val firstText = it.message.firstOrNull<PlainText>()
//获取第一个图片 // 获取第一个图片
val firstImage = it.message.firstOrNull<Image>() val firstImage = it.message.firstOrNull<Image>()
when { when {
...@@ -76,32 +81,43 @@ suspend fun main() = coroutineScope { ...@@ -76,32 +81,43 @@ suspend fun main() = coroutineScope {
"复读" in it.message -> it.sender.sendMessage(it.message) "复读" in it.message -> it.sender.sendMessage(it.message)
"发群消息" in it.message -> Group(bot, 580266363u).sendMessage(it.message.toString().substringAfter("发群消息")) "发群消息" in it.message -> 580266363u.group().sendMessage(it.message.toString().substringAfter("发群消息"))
"直接发送包" in it.message -> { "直接发送包" in it.message -> {
val d = ("01 " + 1994701021u.toByteArray().toUHexString() + " 3E 03 3F A2 00 00 02 BB 00 0A 00 01 00 01 00 5E 4F 53 52 6F 6F 74 3A 43 3A 5C 55 73 65 72 73 5C 48 69 6D 31 38 5C 44 6F 63 75 6D 65 6E 74 73 5C 54 65 6E 63 65 6E 74 20 46 69 6C 65 73 5C 31 30 34 30 34 30 30 32 39 30 5C 49 6D 61 67 65 5C 43 32 43 5C 7B 47 47 42 7E 49 31 5A 4D 43 28 25 49 4D 5A 5F 47 55 51 36 35 5D 51 2E 6A 70 67 00 00 04 7D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 35 02") val d =
("01 " + 1994701021u.toByteArray().toUHexString() + " 3E 03 3F A2 00 00 02 BB 00 0A 00 01 00 01 00 5E 4F 53 52 6F 6F 74 3A 43 3A 5C 55 73 65 72 73 5C 48 69 6D 31 38 5C 44 6F 63 75 6D 65 6E 74 73 5C 54 65 6E 63 65 6E 74 20 46 69 6C 65 73 5C 31 30 34 30 34 30 30 32 39 30 5C 49 6D 61 67 65 5C 43 32 43 5C 7B 47 47 42 7E 49 31 5A 4D 43 28 25 49 4D 5A 5F 47 55 51 36 35 5D 51 2E 6A 70 67 00 00 04 7D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 35 02")
.hexToBytes() .hexToBytes()
it.bot.network.socket.sendPacket(OutgoingRawPacket(0x01_BDu, it.bot.qqAccount, "00 00 00 01 2E 01 00 00 69 35".hexToBytes(), it.bot.network.session.sessionKey, d)) it.bot.network.socket.sendPacket(
OutgoingRawPacket(
0x01_BDu,
it.bot.qqAccount,
"00 00 00 01 2E 01 00 00 69 35".hexToBytes(),
it.bot.network.session.sessionKey,
d
)
)
} }
"上传好友图片" in it.message -> withTimeoutOrNull(5000) { "上传好友图片" in it.message -> withTimeoutOrNull(5000) {
val id = QQ(bot, 1040400290u) val id = 1040400290u.qq()
.uploadImage(withContext(Dispatchers.IO) { ImageIO.read(File("C:\\Users\\Him18\\Desktop\\${it.message.toString().substringAfter("上传好友图片")}").inputStream()) }.toMiraiImage("gif")) .uploadImage(File("C:\\Users\\Him18\\Desktop\\${it.message.toString().substringAfter("上传好友图片")}").toMiraiImage())
it.reply(id.value) it.reply(id.value)
delay(1000) delay(1000)
it.reply(Image(id)) it.reply(Image(id))
} }
"上传群图片" in it.message -> withTimeoutOrNull(5000) { "上传群图片" in it.message -> withTimeoutOrNull(5000) {
val image = withContext(Dispatchers.IO) { ImageIO.read(File("C:\\Users\\Him18\\Desktop\\${it.message.toString().substringAfter("上传群图片")}").inputStream()) }.toMiraiImage("gif") val image = File(
Group(bot, 580266363u).uploadImage(image) "C:\\Users\\Him18\\Desktop\\${it.message.toString().substringAfter("上传群图片")}"
).toMiraiImage()
580266363u.group().uploadImage(image)
it.reply(image.groupImageId.value) it.reply(image.groupImageId.value)
delay(1000) delay(1000)
Group(bot, 580266363u).sendMessage(Image(image.groupImageId)) 580266363u.group().sendMessage(Image(image.groupImageId))
} }
"发群图片" in it.message -> { "发群图片" in it.message -> {
Group(bot, 580266363u).sendMessage(Image(ImageId(it.message.toString().substringAfter("发群图片")))) 580266363u.group().sendMessage(Image(ImageId(it.message.toString().substringAfter("发群图片"))))
} }
"发好友图片" in it.message -> { "发好友图片" in it.message -> {
...@@ -112,12 +128,15 @@ suspend fun main() = coroutineScope { ...@@ -112,12 +128,15 @@ suspend fun main() = coroutineScope {
image.upload(session, Group(session.bot, 580266363)).of() image.upload(session, Group(session.bot, 580266363)).of()
})*/ })*/
it.message eq "发图片群2" -> Group(bot, 580266363u).sendMessage(Image(ImageId("{7AA4B3AA-8C3C-0F45-2D9B-7F302A0ACEAA}.jpg"))) it.message eq "发图片群2" -> 580266363u.group().sendMessage(Image(ImageId("{7AA4B3AA-8C3C-0F45-2D9B-7F302A0ACEAA}.jpg")))
/* it.event eq "发图片" -> sendFriendMessage(it.sender, PlainText("test") + UnsolvedImage(File("C:\\Users\\Him18\\Desktop\\faceImage_1559564477775.jpg")).also { image -> /* it.event eq "发图片" -> sendFriendMessage(it.sender, PlainText("test") + UnsolvedImage(File("C:\\Users\\Him18\\Desktop\\faceImage_1559564477775.jpg")).also { image ->
image.upload(session, it.sender).of() image.upload(session, it.sender).of()
})*/ })*/
it.message eq "发图片2" -> it.reply(PlainText("test") + Image(ImageId("{7AA4B3AA-8C3C-0F45-2D9B-7F302A0ACEAA}.jpg"))) it.message eq "发图片2" -> it.reply(PlainText("test") + Image(ImageId("{7AA4B3AA-8C3C-0F45-2D9B-7F302A0ACEAA}.jpg")))
else -> {
}
} }
} }
......
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