Small updates

This commit is contained in:
Him188 2019-10-10 11:30:06 +08:00
parent f51790e79b
commit 5292b22461
5 changed files with 71 additions and 65 deletions

View File

@ -23,7 +23,12 @@ import net.mamoe.mirai.contact.QQ
* *
* 但注意: 不能 `String + Message`. 只能 `Message + String` * 但注意: 不能 `String + Message`. 只能 `Message + String`
* *
* @see Contact.sendMessage * @see PlainText 纯文本
* @see Image 图片
* @see Face 表情
* @see MessageChain 消息链( `List<Message>`)
*
* @see Contact.sendMessage 发送消息
*/ */
sealed class Message { sealed class Message {
/** /**
@ -45,7 +50,7 @@ sealed class Message {
*/ */
infix fun eq(other: String): Boolean = this.stringValue == other infix fun eq(other: String): Boolean = this.stringValue == other
abstract operator fun contains(sub: String): Boolean open operator fun contains(sub: String): Boolean = false
/** /**
* 把这个消息连接到另一个消息的头部. 类似于字符串相加 * 把这个消息连接到另一个消息的头部. 类似于字符串相加
@ -59,10 +64,14 @@ sealed class Message {
infix operator fun plus(another: Number): MessageChain = this.concat(another.toString().toMessage()) infix operator fun plus(another: Number): MessageChain = this.concat(another.toString().toMessage())
} }
// ==================================== PlainText ====================================
data class PlainText(override val stringValue: String) : Message() { data class PlainText(override val stringValue: String) : Message() {
override operator fun contains(sub: String): Boolean = this.stringValue.contains(sub) override operator fun contains(sub: String): Boolean = this.stringValue.contains(sub)
} }
// ==================================== Image ====================================
/** /**
* 图片消息. * 图片消息.
* 由接收消息时构建, 可直接发送 * 由接收消息时构建, 可直接发送
@ -71,27 +80,30 @@ data class PlainText(override val stringValue: String) : Message() {
*/ */
data class Image(val imageId: String) : Message() { data class Image(val imageId: String) : Message() {
override val stringValue: String = "[$imageId]" override val stringValue: String = "[$imageId]"
override operator fun contains(sub: String): Boolean = false //No string can be contained in a image
} }
// ==================================== At ====================================
/** /**
* At 一个人 * At 一个人
*/ */
data class At(val target: Long) : Message() { data class At(val targetQQ: Long) : Message() {
constructor(target: QQ) : this(target.number) constructor(target: QQ) : this(target.number)
override val stringValue: String = "[@$target]" override val stringValue: String = "[@$targetQQ]"
override operator fun contains(sub: String): Boolean = false
} }
// ==================================== Face ====================================
/** /**
* QQ 自带表情 * QQ 自带表情
*/ */
data class Face(val id: FaceID) : Message() { data class Face(val id: FaceID) : Message() {
override val stringValue: String = "[face${id.id}]" override val stringValue: String = "[face${id.id}]"
override operator fun contains(sub: String): Boolean = false
} }
// ==================================== MessageChain ====================================
data class MessageChain( data class MessageChain(
/** /**
* Elements will not be instances of [MessageChain] * Elements will not be instances of [MessageChain]

View File

@ -4,6 +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 net.mamoe.mirai.* import net.mamoe.mirai.*
import net.mamoe.mirai.event.EventScope
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
@ -93,31 +94,32 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler {
override suspend fun distributePacket(packet: ServerPacket) { override suspend fun distributePacket(packet: ServerPacket) {
try { try {
packet.decode() packet.decode()
} catch (e: java.lang.Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
bot.debugPacket(packet) bot.printPacketDebugging(packet)
return return
} }
//removeIf is not inline
with(temporaryPacketHandlers.iterator()) { with(temporaryPacketHandlers.iterator()) {
while (hasNext()) { while (hasNext()) {
if (next().onPacketReceived(action.session, packet)) { if (next().onPacketReceived(action.session, packet)) {
remove() remove()
} }
} }
} };
//For debug //For debug
kotlin.run { {
if (!packet.javaClass.name.endsWith("Encrypted") && !packet.javaClass.name.endsWith("Raw")) { if (!packet.javaClass.name.endsWith("Encrypted") && !packet.javaClass.name.endsWith("Raw")) {
bot.notice("Packet received: $packet") bot.notice("Packet received: $packet")
} }
} }()
if (packet is ServerEventPacket) { if (packet is ServerEventPacket) {
//no need to sync acknowledgement packets //no need to sync acknowledgement packets
NetworkScope.launch { NetworkScope.launch {
sendPacket(packet.ResponsePacket(bot.account.qqNumber, sessionKey)) sendPacket(packet.ResponsePacket(bot.qqNumber, sessionKey))
} }
} }
@ -201,39 +203,35 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler {
loginResult.complete(LoginState.TIMEOUT) loginResult.complete(LoginState.TIMEOUT)
} }
} }
sendPacket(ClientTouchPacket(bot.account.qqNumber, serverIP)) sendPacket(ClientTouchPacket(bot.qqNumber, serverIP))
return withContext(Dispatchers.IO) { return withContext(Dispatchers.IO) { loginResult.await() }
loginResult.await()
}
} }
override suspend fun sendPacket(packet: ClientPacket) { override suspend fun sendPacket(packet: ClientPacket) = withContext(NetworkScope.coroutineContext) {
checkNotNull(socket) { "network closed" } checkNotNull(socket) { "network closed" }
if (socket!!.isClosed) { if (socket!!.isClosed) {
return return@withContext
} }
try { packet.encodePacket()
packet.encodePacket()
if (BeforePacketSendEvent(bot, packet).broadcast().cancelled) { if (BeforePacketSendEvent(bot, packet).broadcast().cancelled) {
return return@withContext
}
val data = packet.toByteArray()
withContext(Dispatchers.IO) {
socket!!.send(DatagramPacket(data, data.size))
}
bot.cyan("Packet sent: $packet")
PacketSentEvent(bot, packet).broadcast()
} catch (e: Throwable) {
e.printStackTrace()
} }
val data = packet.toByteArray()
withContext(Dispatchers.IO) {
socket!!.send(DatagramPacket(data, data.size))
}
bot.cyan("Packet sent: $packet")
EventScope.launch { PacketSentEvent(bot, packet).broadcast() }
Unit
} }
override fun getOwner(): Bot = this@TIMBotNetworkHandler.bot override val owner: Bot get() = this@TIMBotNetworkHandler.bot
override fun close() { override fun close() {
@ -245,9 +243,7 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler {
} }
} }
override fun isClosed(): Boolean { override fun isClosed(): Boolean = this.socket?.isClosed ?: true
return this.socket?.isClosed ?: true
}
} }
companion object { companion object {
@ -262,7 +258,7 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler {
private lateinit var token0825: ByteArray//56 private lateinit var token0825: ByteArray//56
private var loginTime: Int = 0 private var loginTime: Int = 0
private lateinit var loginIP: String private lateinit var loginIP: String
private var randomprivateKey: ByteArray = getRandomByteArray(16) private var privateKey: ByteArray = getRandomByteArray(16)
/** /**
* 0828_decr_key * 0828_decr_key
@ -281,13 +277,13 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler {
if (packet.serverIP != null) {//redirection if (packet.serverIP != null) {//redirection
socket.serverIP = packet.serverIP!! socket.serverIP = packet.serverIP!!
//connect(packet.serverIP!!) //connect(packet.serverIP!!)
socket.sendPacket(ClientServerRedirectionPacket(packet.serverIP!!, bot.account.qqNumber)) socket.sendPacket(ClientServerRedirectionPacket(packet.serverIP!!, bot.qqNumber))
} else {//password submission } else {//password submission
this.loginIP = packet.loginIP this.loginIP = packet.loginIP
this.loginTime = packet.loginTime this.loginTime = packet.loginTime
this.token0825 = packet.token0825 this.token0825 = packet.token0825
println("token0825=" + this.token0825.toUHexString()) println("token0825=" + this.token0825.toUHexString())
socket.sendPacket(ClientPasswordSubmissionPacket(bot.account.qqNumber, bot.account.password, packet.loginTime, packet.loginIP, this.randomprivateKey, packet.token0825)) socket.sendPacket(ClientPasswordSubmissionPacket(bot.qqNumber, bot.account.password, packet.loginTime, packet.loginIP, this.privateKey, packet.token0825))
} }
} }
@ -298,9 +294,9 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler {
} }
is ServerCaptchaCorrectPacket -> { is ServerCaptchaCorrectPacket -> {
this.randomprivateKey = getRandomByteArray(16) this.privateKey = getRandomByteArray(16)
this.token00BA = packet.token00BA this.token00BA = packet.token00BA
socket.sendPacket(ClientLoginResendPacket3105(bot.account.qqNumber, bot.account.password, this.loginTime, this.loginIP, this.randomprivateKey, this.token0825, this.token00BA)) socket.sendPacket(ClientLoginResendPacket3105(bot.qqNumber, bot.account.password, this.loginTime, this.loginIP, this.privateKey, this.token0825, this.token00BA))
} }
is ServerLoginResponseVerificationCodeInitPacket -> { is ServerLoginResponseVerificationCodeInitPacket -> {
@ -310,7 +306,7 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler {
if (packet.unknownBoolean == true) { if (packet.unknownBoolean == true) {
this.captchaSectionId = 1 this.captchaSectionId = 1
socket.sendPacket(ClientVerificationCodeTransmissionRequestPacket(1, bot.account.qqNumber, this.token0825, this.captchaSectionId++, this.token00BA)) socket.sendPacket(ClientVerificationCodeTransmissionRequestPacket(1, bot.qqNumber, this.token0825, this.captchaSectionId++, this.token00BA))
} }
} }
@ -347,18 +343,18 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler {
if (code.isEmpty() || code.length != 4) { if (code.isEmpty() || code.length != 4) {
this.captchaCache = byteArrayOf() this.captchaCache = byteArrayOf()
this.captchaSectionId = 1 this.captchaSectionId = 1
socket.sendPacket(ClientVerificationCodeRefreshPacket(packet.packetIdLast + 1, bot.account.qqNumber, token0825)) socket.sendPacket(ClientVerificationCodeRefreshPacket(packet.packetIdLast + 1, bot.qqNumber, token0825))
} else { } else {
socket.sendPacket(ClientVerificationCodeSubmitPacket(packet.packetIdLast + 1, bot.account.qqNumber, token0825, code, packet.verificationToken)) socket.sendPacket(ClientVerificationCodeSubmitPacket(packet.packetIdLast + 1, bot.qqNumber, token0825, code, packet.verificationToken))
} }
} else { } else {
socket.sendPacket(ClientVerificationCodeTransmissionRequestPacket(packet.packetIdLast + 1, bot.account.qqNumber, token0825, captchaSectionId++, token00BA)) socket.sendPacket(ClientVerificationCodeTransmissionRequestPacket(packet.packetIdLast + 1, bot.qqNumber, token0825, captchaSectionId++, token00BA))
} }
} }
is ServerLoginResponseSuccessPacket -> { is ServerLoginResponseSuccessPacket -> {
this.sessionResponseDecryptionKey = packet.sessionResponseDecryptionKey this.sessionResponseDecryptionKey = packet.sessionResponseDecryptionKey
socket.sendPacket(ClientSessionRequestPacket(bot.account.qqNumber, socket.serverIP, packet.token38, packet.token88, packet.encryptionKey)) socket.sendPacket(ClientSessionRequestPacket(bot.qqNumber, socket.serverIP, packet.token38, packet.token88, packet.encryptionKey))
} }
//是ClientPasswordSubmissionPacket之后服务器回复的 //是ClientPasswordSubmissionPacket之后服务器回复的
@ -368,11 +364,11 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler {
//println("token00BA changed!!! to " + token00BA.toUByteArray()) //println("token00BA changed!!! to " + token00BA.toUByteArray())
//} //}
if (packet.flag == ServerLoginResponseKeyExchangePacket.Flag.`08 36 31 03`) { if (packet.flag == ServerLoginResponseKeyExchangePacket.Flag.`08 36 31 03`) {
this.randomprivateKey = packet.privateKey this.privateKey = packet.privateKeyUpdate
socket.sendPacket(ClientLoginResendPacket3104(bot.account.qqNumber, bot.account.password, loginTime, loginIP, randomprivateKey, token0825, packet.tokenUnknown socket.sendPacket(ClientLoginResendPacket3104(bot.qqNumber, bot.account.password, loginTime, loginIP, privateKey, token0825, packet.tokenUnknown
?: this.token00BA, packet.tlv0006)) ?: this.token00BA, packet.tlv0006))
} else { } else {
socket.sendPacket(ClientLoginResendPacket3106(bot.account.qqNumber, bot.account.password, loginTime, loginIP, randomprivateKey, token0825, packet.tokenUnknown socket.sendPacket(ClientLoginResendPacket3106(bot.qqNumber, bot.account.password, loginTime, loginIP, privateKey, token0825, packet.tokenUnknown
?: token00BA, packet.tlv0006)) ?: token00BA, packet.tlv0006))
} }
} }
@ -382,7 +378,7 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler {
heartbeatJob = NetworkScope.launch { heartbeatJob = NetworkScope.launch {
delay(90000) delay(90000)
socket.sendPacket(ClientHeartbeatPacket(bot.account.qqNumber, sessionKey)) socket.sendPacket(ClientHeartbeatPacket(bot.qqNumber, sessionKey))
} }
socket.loginResult.complete(LoginState.SUCCESS) socket.loginResult.complete(LoginState.SUCCESS)
@ -406,8 +402,8 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler {
is ServerCaptchaPacket.Encrypted -> socket.distributePacket(packet.decrypt()) is ServerCaptchaPacket.Encrypted -> socket.distributePacket(packet.decrypt())
is ServerLoginResponseVerificationCodeInitPacket.Encrypted -> socket.distributePacket(packet.decrypt()) is ServerLoginResponseVerificationCodeInitPacket.Encrypted -> socket.distributePacket(packet.decrypt())
is ServerLoginResponseKeyExchangePacket.Encrypted -> socket.distributePacket(packet.decrypt(this.randomprivateKey)) is ServerLoginResponseKeyExchangePacket.Encrypted -> socket.distributePacket(packet.decrypt(this.privateKey))
is ServerLoginResponseSuccessPacket.Encrypted -> socket.distributePacket(packet.decrypt(this.randomprivateKey)) is ServerLoginResponseSuccessPacket.Encrypted -> socket.distributePacket(packet.decrypt(this.privateKey))
is ServerSessionKeyResponsePacket.Encrypted -> socket.distributePacket(packet.decrypt(this.sessionResponseDecryptionKey)) is ServerSessionKeyResponsePacket.Encrypted -> socket.distributePacket(packet.decrypt(this.sessionResponseDecryptionKey))
is ServerTouchResponsePacket.Encrypted -> socket.distributePacket(packet.decrypt()) is ServerTouchResponsePacket.Encrypted -> socket.distributePacket(packet.decrypt())
@ -424,7 +420,7 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler {
@Suppress("MemberVisibilityCanBePrivate") @Suppress("MemberVisibilityCanBePrivate")
suspend fun changeOnlineStatus(status: ClientLoginStatus) { suspend fun changeOnlineStatus(status: ClientLoginStatus) {
socket.sendPacket(ClientChangeOnlineStatusPacket(bot.account.qqNumber, sessionKey, status)) socket.sendPacket(ClientChangeOnlineStatusPacket(bot.qqNumber, sessionKey, status))
} }
fun close() { fun close() {

View File

@ -19,7 +19,6 @@ import net.mamoe.mirai.network.protocol.tim.packet.login.ServerSKeyResponsePacke
import net.mamoe.mirai.task.MiraiThreadPool import net.mamoe.mirai.task.MiraiThreadPool
import net.mamoe.mirai.utils.getGTK import net.mamoe.mirai.utils.getGTK
import java.awt.image.BufferedImage import java.awt.image.BufferedImage
import java.io.Closeable
import java.util.* import java.util.*
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
import java.util.concurrent.ScheduledFuture import java.util.concurrent.ScheduledFuture
@ -94,7 +93,7 @@ class ActionPacketHandler(session: LoginSession) : PacketHandler(session) {
val future = CompletableFuture<AddFriendResult>() val future = CompletableFuture<AddFriendResult>()
val session = AddFriendSession(qqNumber, future, message) val session = AddFriendSession(qqNumber, future, message)
// uploadImageSessions.add(session) // uploadImageSessions.add(session)
session.sendAddRequest(); session.sendAddRequest()
return future return future
} }
@ -117,7 +116,7 @@ class ActionPacketHandler(session: LoginSession) : PacketHandler(session) {
private val group: Long, private val group: Long,
private val future: CompletableFuture<AddFriendResult>, private val future: CompletableFuture<AddFriendResult>,
private val image: BufferedImage private val image: BufferedImage
) : Closeable { ) {
lateinit var id: ByteArray lateinit var id: ByteArray
@ -161,7 +160,7 @@ class ActionPacketHandler(session: LoginSession) : PacketHandler(session) {
} }
override fun close() { fun close() {
uploadImageSessions.remove(this) uploadImageSessions.remove(this)
} }
} }
@ -170,7 +169,7 @@ class ActionPacketHandler(session: LoginSession) : PacketHandler(session) {
private val qq: Long, private val qq: Long,
private val future: CompletableFuture<AddFriendResult>, private val future: CompletableFuture<AddFriendResult>,
private val message: Lazy<String> private val message: Lazy<String>
) : Closeable { ) {
lateinit var id: ByteArray lateinit var id: ByteArray
@ -215,7 +214,7 @@ class ActionPacketHandler(session: LoginSession) : PacketHandler(session) {
session.socket.sendPacket(ClientCanAddFriendPacket(session.bot.account.qqNumber, qq, session.sessionKey).also { this.id = it.packetIdLast }) session.socket.sendPacket(ClientCanAddFriendPacket(session.bot.account.qqNumber, qq, session.sessionKey).also { this.id = it.packetIdLast })
} }
override fun close() { fun close() {
// uploadImageSessions.remove(this) // uploadImageSessions.remove(this)
} }
} }

View File

@ -15,7 +15,7 @@ import net.mamoe.mirai.network.protocol.tim.packet.ServerPacket
* @author Him188moe * @author Him188moe
*/ */
interface DataPacketSocket { interface DataPacketSocket {
fun getOwner(): Bot val owner: Bot
/** /**
* 分发数据包给 [PacketHandler] * 分发数据包给 [PacketHandler]

View File

@ -2,17 +2,16 @@ package net.mamoe.mirai.network.protocol.tim.handler
import net.mamoe.mirai.network.LoginSession import net.mamoe.mirai.network.LoginSession
import net.mamoe.mirai.network.protocol.tim.packet.ServerPacket import net.mamoe.mirai.network.protocol.tim.packet.ServerPacket
import java.io.Closeable
/** /**
* 数据包(接受/发送)处理器 * 数据包(接受/发送)处理器
*/ */
abstract class PacketHandler( abstract class PacketHandler(
val session: LoginSession val session: LoginSession
) : Closeable { ) {
abstract suspend fun onPacketReceived(packet: ServerPacket) abstract suspend fun onPacketReceived(packet: ServerPacket)
override fun close() { open fun close() {
} }
} }