mirror of
https://github.com/mamoe/mirai.git
synced 2025-02-23 02:10:16 +08:00
Kotlin coroutine
This commit is contained in:
parent
4b96bf0ee8
commit
4f4bc05da6
@ -21,23 +21,23 @@ abstract class Contact internal constructor(val bot: Bot, val number: Long) {
|
||||
/**
|
||||
* Async
|
||||
*/
|
||||
abstract fun sendMessage(message: MessageChain)
|
||||
abstract suspend fun sendMessage(message: MessageChain)
|
||||
|
||||
/**
|
||||
* 上传图片
|
||||
*/
|
||||
fun uploadImage(session: LoginSession, image: UnsolvedImage): CompletableFuture<Unit> {
|
||||
suspend fun uploadImage(session: LoginSession, image: UnsolvedImage): CompletableFuture<Unit> {
|
||||
return image.upload(session, this)
|
||||
}
|
||||
|
||||
fun sendMessage(message: Message) {
|
||||
suspend fun sendMessage(message: Message) {
|
||||
if (message is MessageChain) {
|
||||
return sendMessage(message)
|
||||
}
|
||||
return sendMessage(message.toChain())
|
||||
}
|
||||
|
||||
fun sendMessage(message: String) {
|
||||
suspend fun sendMessage(message: String) {
|
||||
this.sendMessage(PlainText(message))
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ class Group(bot: Bot, number: Long) : Contact(bot, number), Closeable {
|
||||
val groupId = groupNumberToId(number)
|
||||
val members = ContactList<QQ>()
|
||||
|
||||
override fun sendMessage(message: MessageChain) {
|
||||
override suspend fun sendMessage(message: MessageChain) {
|
||||
bot.network.message.sendGroupMessage(this, message)
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ import net.mamoe.mirai.message.defaults.MessageChain
|
||||
* @author Him188moe
|
||||
*/
|
||||
class QQ(bot: Bot, number: Long) : Contact(bot, number) {
|
||||
override fun sendMessage(message: MessageChain) {
|
||||
override suspend fun sendMessage(message: MessageChain) {
|
||||
bot.network.message.sendFriendMessage(this, message)
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ class UnsolvedImage(filename: String, val image: BufferedImage) : Image(getImage
|
||||
constructor(imageFile: File) : this(imageFile.name, ImageIO.read(imageFile))
|
||||
constructor(url: URL) : this(File(url.file))
|
||||
|
||||
fun upload(session: LoginSession, contact: Contact): CompletableFuture<Unit> {
|
||||
suspend fun upload(session: LoginSession, contact: Contact): CompletableFuture<Unit> {//todo be suspend
|
||||
return session.expectPacket<ServerTryGetImageIDResponsePacket> {
|
||||
toSend { ClientTryGetImageIDPacket(session.bot.account.qqNumber, session.sessionKey, contact.number, image) }
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package net.mamoe.mirai.network
|
||||
|
||||
import kotlinx.coroutines.*
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.MiraiServer
|
||||
import net.mamoe.mirai.event.events.bot.BotLoginSucceedEvent
|
||||
@ -40,8 +41,11 @@ internal class BotNetworkHandlerImpl(private val bot: Bot) : BotNetworkHandler {
|
||||
|
||||
internal val temporaryPacketHandlers = Collections.synchronizedList(mutableListOf<TemporaryPacketHandler<*>>())
|
||||
|
||||
|
||||
override fun addHandler(temporaryPacketHandler: TemporaryPacketHandler<*>) {
|
||||
temporaryPacketHandler.send(action.session)
|
||||
runBlocking {
|
||||
temporaryPacketHandler.send(action.session)
|
||||
}
|
||||
temporaryPacketHandlers.add(temporaryPacketHandler)
|
||||
}
|
||||
|
||||
@ -95,7 +99,7 @@ internal class BotNetworkHandlerImpl(private val bot: Bot) : BotNetworkHandler {
|
||||
|
||||
|
||||
internal inner class BotSocket : Closeable, DataPacketSocket {
|
||||
override fun distributePacket(packet: ServerPacket) {
|
||||
override suspend fun distributePacket(packet: ServerPacket) {
|
||||
try {
|
||||
packet.decode()
|
||||
} catch (e: java.lang.Exception) {
|
||||
@ -150,12 +154,8 @@ internal class BotNetworkHandlerImpl(private val bot: Bot) : BotNetworkHandler {
|
||||
val packet = DatagramPacket(ByteArray(2048), 2048)
|
||||
kotlin.runCatching { socket?.receive(packet) }
|
||||
.onSuccess {
|
||||
MiraiThreadPool.getInstance().submit {
|
||||
try {
|
||||
distributePacket(ServerPacket.ofByteArray(packet.data.removeZeroTail()))
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
GlobalScope.launch {
|
||||
distributePacket(ServerPacket.ofByteArray(packet.data.removeZeroTail()))
|
||||
}
|
||||
}.onFailure {
|
||||
if (it.message == "Socket closed" || it.message == "socket closed") {
|
||||
@ -184,7 +184,9 @@ internal class BotNetworkHandlerImpl(private val bot: Bot) : BotNetworkHandler {
|
||||
bot.waitForPacket(ServerPacket::class, timeoutMillis) {
|
||||
loginFuture!!.complete(LoginState.TIMEOUT)
|
||||
}
|
||||
sendPacket(ClientTouchPacket(bot.account.qqNumber, serverIP))
|
||||
runBlocking {
|
||||
sendPacket(ClientTouchPacket(bot.account.qqNumber, serverIP))
|
||||
}
|
||||
|
||||
return this.loginFuture!!
|
||||
}
|
||||
@ -193,8 +195,7 @@ internal class BotNetworkHandlerImpl(private val bot: Bot) : BotNetworkHandler {
|
||||
* Not async
|
||||
*/
|
||||
@Synchronized
|
||||
|
||||
override fun sendPacket(packet: ClientPacket) {
|
||||
override suspend fun sendPacket(packet: ClientPacket) {
|
||||
checkNotNull(socket) { "network closed" }
|
||||
if (socket!!.isClosed) {
|
||||
return
|
||||
@ -208,7 +209,9 @@ internal class BotNetworkHandlerImpl(private val bot: Bot) : BotNetworkHandler {
|
||||
}
|
||||
|
||||
val data = packet.toByteArray()
|
||||
socket!!.send(DatagramPacket(data, data.size))
|
||||
withContext(Dispatchers.IO) {
|
||||
socket!!.send(DatagramPacket(data, data.size))
|
||||
}
|
||||
bot.cyanL("Packet sent: $packet")
|
||||
|
||||
PacketSentEvent(bot, packet).broadcast()
|
||||
@ -255,7 +258,7 @@ internal class BotNetworkHandlerImpl(private val bot: Bot) : BotNetworkHandler {
|
||||
private var heartbeatFuture: ScheduledFuture<*>? = null
|
||||
|
||||
|
||||
fun onPacketReceived(packet: ServerPacket) {
|
||||
suspend fun onPacketReceived(packet: ServerPacket) {
|
||||
when (packet) {
|
||||
is ServerTouchResponsePacket -> {
|
||||
if (packet.serverIP != null) {//redirection
|
||||
@ -304,7 +307,9 @@ internal class BotNetworkHandlerImpl(private val bot: Bot) : BotNetworkHandler {
|
||||
this.token00BA = packet.token00BA
|
||||
|
||||
if (packet.transmissionCompleted) {
|
||||
bot.notice(CharImageUtil.createCharImg(ImageIO.read(this.captchaCache!!.inputStream())))
|
||||
withContext(Dispatchers.IO) {
|
||||
bot.notice(CharImageUtil.createCharImg(ImageIO.read(captchaCache!!.inputStream())))
|
||||
}
|
||||
bot.notice("需要验证码登录, 验证码为 4 字母")
|
||||
try {
|
||||
(MiraiServer.getInstance().parentFolder + "VerificationCode.png").writeBytes(this.captchaCache!!)
|
||||
@ -350,7 +355,9 @@ internal class BotNetworkHandlerImpl(private val bot: Bot) : BotNetworkHandler {
|
||||
is ServerSessionKeyResponsePacket -> {
|
||||
sessionKey = packet.sessionKey
|
||||
heartbeatFuture = MiraiThreadPool.getInstance().scheduleWithFixedDelay({
|
||||
socket.sendPacket(ClientHeartbeatPacket(bot.account.qqNumber, sessionKey))
|
||||
runBlocking {
|
||||
socket.sendPacket(ClientHeartbeatPacket(bot.account.qqNumber, sessionKey))
|
||||
}
|
||||
}, 90000, 90000, TimeUnit.MILLISECONDS)
|
||||
|
||||
socket.loginFuture!!.complete(LoginState.SUCCESS)
|
||||
@ -390,7 +397,9 @@ internal class BotNetworkHandlerImpl(private val bot: Bot) : BotNetworkHandler {
|
||||
}
|
||||
|
||||
fun changeOnlineStatus(status: ClientLoginStatus) {
|
||||
socket.sendPacket(ClientChangeOnlineStatusPacket(bot.account.qqNumber, sessionKey, status))
|
||||
NetworkScope.launch {
|
||||
socket.sendPacket(ClientChangeOnlineStatusPacket(bot.account.qqNumber, sessionKey, status))
|
||||
}
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
|
@ -0,0 +1,21 @@
|
||||
package net.mamoe.mirai.network
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.asCoroutineDispatcher
|
||||
import java.util.concurrent.SynchronousQueue
|
||||
import java.util.concurrent.ThreadPoolExecutor
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
object NetworkScope : CoroutineScope {
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = lazy {
|
||||
ThreadPoolExecutor(
|
||||
1,
|
||||
4,
|
||||
8000, TimeUnit.MILLISECONDS,
|
||||
SynchronousQueue()
|
||||
).asCoroutineDispatcher()
|
||||
}.value//todo improve
|
||||
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package net.mamoe.mirai.network.handler
|
||||
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import net.mamoe.mirai.network.LoginSession
|
||||
import net.mamoe.mirai.network.packet.*
|
||||
import net.mamoe.mirai.network.packet.action.AddFriendResult
|
||||
@ -32,7 +33,7 @@ class ActionPacketHandler(session: LoginSession) : PacketHandler(session) {
|
||||
private var sKeyRefresherFuture: ScheduledFuture<*>? = null
|
||||
|
||||
|
||||
override fun onPacketReceived(packet: ServerPacket) {
|
||||
override suspend fun onPacketReceived(packet: ServerPacket) {
|
||||
when (packet) {
|
||||
is ServerCanAddFriendResponsePacket -> {
|
||||
this.uploadImageSessions.forEach {
|
||||
@ -60,7 +61,9 @@ class ActionPacketHandler(session: LoginSession) : PacketHandler(session) {
|
||||
session.cookies = "uin=o" + session.bot.account.qqNumber + ";skey=" + session.sKey + ";"
|
||||
|
||||
sKeyRefresherFuture = MiraiThreadPool.getInstance().scheduleWithFixedDelay({
|
||||
session.socket.sendPacket(ClientSKeyRefreshmentRequestPacket(session.bot.account.qqNumber, session.sessionKey))
|
||||
runBlocking {
|
||||
session.socket.sendPacket(ClientSKeyRefreshmentRequestPacket(session.bot.account.qqNumber, session.sessionKey))
|
||||
}
|
||||
}, 1800000, 1800000, TimeUnit.MILLISECONDS)
|
||||
|
||||
session.gtk = getGTK(session.sKey)
|
||||
@ -75,13 +78,13 @@ class ActionPacketHandler(session: LoginSession) : PacketHandler(session) {
|
||||
}
|
||||
|
||||
|
||||
fun addFriend(qqNumber: Long, message: Supplier<String>) {
|
||||
suspend fun addFriend(qqNumber: Long, message: Supplier<String>) {
|
||||
addFriend(qqNumber, lazy { message.get() })
|
||||
}
|
||||
|
||||
|
||||
@JvmSynthetic
|
||||
fun addFriend(qqNumber: Long, message: Lazy<String> = lazyOf("")): CompletableFuture<AddFriendResult> {
|
||||
suspend fun addFriend(qqNumber: Long, message: Lazy<String> = lazyOf("")): CompletableFuture<AddFriendResult> {
|
||||
val future = CompletableFuture<AddFriendResult>()
|
||||
val session = AddFriendSession(qqNumber, future, message)
|
||||
// uploadImageSessions.add(session)
|
||||
@ -90,12 +93,12 @@ class ActionPacketHandler(session: LoginSession) : PacketHandler(session) {
|
||||
}
|
||||
|
||||
|
||||
fun requestSKey() {
|
||||
suspend fun requestSKey() {
|
||||
session.socket.sendPacket(ClientSKeyRequestPacket(session.bot.account.qqNumber, session.sessionKey))
|
||||
}
|
||||
|
||||
|
||||
fun requestAccountInfo() {
|
||||
suspend fun requestAccountInfo() {
|
||||
session.socket.sendPacket(ClientAccountInfoRequestPacket(session.bot.account.qqNumber, session.sessionKey))
|
||||
}
|
||||
|
||||
@ -165,7 +168,7 @@ class ActionPacketHandler(session: LoginSession) : PacketHandler(session) {
|
||||
lateinit var id: ByteArray
|
||||
|
||||
|
||||
fun onPacketReceived(packet: ServerPacket) {
|
||||
suspend fun onPacketReceived(packet: ServerPacket) {
|
||||
if (!::id.isInitialized) {
|
||||
return
|
||||
}
|
||||
@ -202,7 +205,7 @@ class ActionPacketHandler(session: LoginSession) : PacketHandler(session) {
|
||||
}
|
||||
|
||||
|
||||
fun sendAddRequest() {
|
||||
suspend fun sendAddRequest() {
|
||||
session.socket.sendPacket(ClientCanAddFriendPacket(session.bot.account.qqNumber, qq, session.sessionKey).also { this.id = it.packetIdLast })
|
||||
}
|
||||
|
||||
|
@ -6,9 +6,7 @@ import net.mamoe.mirai.network.BotNetworkHandlerImpl
|
||||
import net.mamoe.mirai.network.LoginSession
|
||||
import net.mamoe.mirai.network.packet.ClientPacket
|
||||
import net.mamoe.mirai.network.packet.ServerPacket
|
||||
import net.mamoe.mirai.task.MiraiThreadPool
|
||||
import java.io.Closeable
|
||||
import java.util.concurrent.Future
|
||||
|
||||
/**
|
||||
* 网络接口.
|
||||
@ -23,7 +21,7 @@ interface DataPacketSocket : Closeable {
|
||||
/**
|
||||
* 分发数据包给 [PacketHandler]
|
||||
*/
|
||||
fun distributePacket(packet: ServerPacket)
|
||||
suspend fun distributePacket(packet: ServerPacket)
|
||||
|
||||
/**
|
||||
* 发送一个数据包(非异步).
|
||||
@ -32,20 +30,7 @@ interface DataPacketSocket : Closeable {
|
||||
*
|
||||
* @see [LoginSession.expectPacket] kotlin DSL
|
||||
*/
|
||||
fun sendPacket(packet: ClientPacket)
|
||||
|
||||
/**
|
||||
* 发送一个数据包(异步).
|
||||
*
|
||||
* 可通过 hook 事件 [ServerPacketReceivedEvent] 来获取服务器返回.
|
||||
*
|
||||
* @see [LoginSession.expectPacket] kotlin DSL
|
||||
*/
|
||||
fun sendPacketAsync(packet: ClientPacket): Future<*> {
|
||||
return MiraiThreadPool.getInstance().submit {
|
||||
sendPacket(packet)
|
||||
}
|
||||
}
|
||||
suspend fun sendPacket(packet: ClientPacket)
|
||||
|
||||
fun isClosed(): Boolean
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package net.mamoe.mirai.network.handler
|
||||
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import net.mamoe.mirai.contact.Group
|
||||
import net.mamoe.mirai.contact.QQ
|
||||
import net.mamoe.mirai.event.events.group.GroupMessageEvent
|
||||
@ -30,46 +31,49 @@ class MessagePacketHandler(session: LoginSession) : PacketHandler(session) {
|
||||
init {
|
||||
//todo for test
|
||||
FriendMessageEvent::class.hookWhile {
|
||||
if (session.socket.isClosed()) {
|
||||
return@hookWhile false
|
||||
}
|
||||
when {
|
||||
it.message valueEquals "你好" -> it.sender.sendMessage("你好!")
|
||||
it.message.toString().startsWith("复读") -> it.sender.sendMessage(it.message())
|
||||
it.message.toString().startsWith("发群") -> {
|
||||
it.message().list.toMutableList().let { messages ->
|
||||
messages.removeAt(0)
|
||||
sendGroupMessage(Group(session.bot, 580266363), MessageChain(messages))
|
||||
}
|
||||
return@hookWhile runBlocking {
|
||||
if (session.socket.isClosed()) {
|
||||
return@runBlocking false
|
||||
}
|
||||
when {
|
||||
it.message valueEquals "你好" -> it.sender.sendMessage("你好!")
|
||||
it.message.toString().startsWith("复读") -> it.sender.sendMessage(it.message())
|
||||
it.message.toString().startsWith("发群") -> {
|
||||
it.message().list.toMutableList().let { messages ->
|
||||
messages.removeAt(0)
|
||||
sendGroupMessage(Group(session.bot, 580266363), MessageChain(messages))
|
||||
}
|
||||
}
|
||||
/*it.message valueEquals "发图片群" -> sendGroupMessage(Group(session.bot, 580266363), PlainText("test") + UnsolvedImage(File("C:\\Users\\Him18\\Desktop\\faceImage_1559564477775.jpg")).also { image ->
|
||||
image.upload(session, Group(session.bot, 580266363)).get()
|
||||
})*/
|
||||
it.message valueEquals "发图片群2" -> sendGroupMessage(Group(session.bot, 580266363), Image("{7AA4B3AA-8C3C-0F45-2D9B-7F302A0ACEAA}.jpg").toChain())
|
||||
/* it.message valueEquals "发图片" -> sendFriendMessage(it.sender, PlainText("test") + UnsolvedImage(File("C:\\Users\\Him18\\Desktop\\faceImage_1559564477775.jpg")).also { image ->
|
||||
image.upload(session, it.sender).get()
|
||||
})*/
|
||||
it.message valueEquals "发图片2" -> sendFriendMessage(it.sender, PlainText("test") + Image("{7AA4B3AA-8C3C-0F45-2D9B-7F302A0ACEAA}.jpg"))
|
||||
}
|
||||
/*it.message valueEquals "发图片群" -> sendGroupMessage(Group(session.bot, 580266363), PlainText("test") + UnsolvedImage(File("C:\\Users\\Him18\\Desktop\\faceImage_1559564477775.jpg")).also { image ->
|
||||
image.upload(session, Group(session.bot, 580266363)).get()
|
||||
})*/
|
||||
it.message valueEquals "发图片群2" -> sendGroupMessage(Group(session.bot, 580266363), Image("{7AA4B3AA-8C3C-0F45-2D9B-7F302A0ACEAA}.jpg").toChain())
|
||||
/* it.message valueEquals "发图片" -> sendFriendMessage(it.sender, PlainText("test") + UnsolvedImage(File("C:\\Users\\Him18\\Desktop\\faceImage_1559564477775.jpg")).also { image ->
|
||||
image.upload(session, it.sender).get()
|
||||
})*/
|
||||
it.message valueEquals "发图片2" -> sendFriendMessage(it.sender, PlainText("test") + Image("{7AA4B3AA-8C3C-0F45-2D9B-7F302A0ACEAA}.jpg"))
|
||||
}
|
||||
|
||||
return@hookWhile true
|
||||
return@runBlocking true
|
||||
}
|
||||
}
|
||||
|
||||
GroupMessageEvent::class.hookWhile {
|
||||
if (session.socket.isClosed()) {
|
||||
return@hookWhile false
|
||||
return@hookWhile runBlocking {
|
||||
if (session.socket.isClosed()) {
|
||||
return@runBlocking false
|
||||
}
|
||||
|
||||
when {
|
||||
it.message.contains("复读") -> it.group.sendMessage(it.chain)
|
||||
}
|
||||
|
||||
return@runBlocking true
|
||||
}
|
||||
|
||||
when {
|
||||
it.message.contains("复读") -> it.group.sendMessage(it.chain)
|
||||
}
|
||||
|
||||
return@hookWhile true
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPacketReceived(packet: ServerPacket) {
|
||||
override suspend fun onPacketReceived(packet: ServerPacket) {
|
||||
when (packet) {
|
||||
is ServerGroupUploadFileEventPacket -> {
|
||||
//todo
|
||||
@ -99,11 +103,11 @@ class MessagePacketHandler(session: LoginSession) : PacketHandler(session) {
|
||||
}
|
||||
}
|
||||
|
||||
fun sendFriendMessage(qq: QQ, message: MessageChain) {
|
||||
session.socket.sendPacketAsync(ClientSendFriendMessagePacket(session.bot.account.qqNumber, qq.number, session.sessionKey, message))
|
||||
suspend fun sendFriendMessage(qq: QQ, message: MessageChain) {
|
||||
session.socket.sendPacket(ClientSendFriendMessagePacket(session.bot.account.qqNumber, qq.number, session.sessionKey, message))
|
||||
}
|
||||
|
||||
fun sendGroupMessage(group: Group, message: MessageChain) {
|
||||
suspend fun sendGroupMessage(group: Group, message: MessageChain) {
|
||||
session.socket.sendPacket(ClientSendGroupMessagePacket(session.bot.account.qqNumber, group.groupId, session.sessionKey, message))
|
||||
}
|
||||
}
|
@ -11,7 +11,7 @@ import java.io.Closeable
|
||||
abstract class PacketHandler(
|
||||
val session: LoginSession
|
||||
) : Closeable {
|
||||
abstract fun onPacketReceived(packet: ServerPacket)
|
||||
abstract suspend fun onPacketReceived(packet: ServerPacket)
|
||||
|
||||
override fun close() {
|
||||
|
||||
|
@ -32,7 +32,7 @@ open class TemporaryPacketHandler<P : ServerPacket>(
|
||||
this.expect = handler
|
||||
}
|
||||
|
||||
fun send(session: LoginSession) {
|
||||
suspend fun send(session: LoginSession) {
|
||||
this.session = session
|
||||
session.socket.sendPacket(toSend)
|
||||
}
|
||||
|
@ -6,8 +6,6 @@ import lombok.Data;
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class BotAccount {
|
||||
|
||||
public final long qqNumber;
|
||||
private final String password;
|
||||
|
||||
public final String password;
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ object Main {
|
||||
println("-------------------------------------------")
|
||||
exitProcess(0)*/
|
||||
|
||||
var jpcap: JpcapCaptor? = null
|
||||
val jpcap: JpcapCaptor?
|
||||
val caplen = 4096
|
||||
val promiscCheck = true
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user