mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-21 18:56:03 +08:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
455f408ece
@ -71,7 +71,7 @@ fun Application.mirai() {
|
|||||||
routing {
|
routing {
|
||||||
mirai("/sendFriendMessage") {
|
mirai("/sendFriendMessage") {
|
||||||
// TODO: 2019/11/21 解析图片消息等为 Message
|
// TODO: 2019/11/21 解析图片消息等为 Message
|
||||||
Bot.instanceWhose(qq = param("bot")).getQQ(param("qq")).sendMessage(param<String>("message"))
|
Bot.instanceWhose(qq = param("bot")).getFriend(param("qq")).sendMessage(param<String>("message"))
|
||||||
call.ok()
|
call.ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,12 +33,8 @@ internal abstract class QQAndroidBotBase constructor(
|
|||||||
|
|
||||||
val selfQQ: QQ by lazy { QQ(uin) }
|
val selfQQ: QQ by lazy { QQ(uin) }
|
||||||
|
|
||||||
override fun getQQ(id: Long): QQ {
|
override fun getFriend(id: Long): QQ {
|
||||||
return qqs.delegate.filteringGetOrAdd({ it.id == id }, { QQImpl(this as QQAndroidBot, coroutineContext, id) })
|
return qqs.delegate[id]
|
||||||
}
|
|
||||||
|
|
||||||
fun getQQOrAdd(id: Long): QQ {
|
|
||||||
return qqs.delegate.filteringGetOrAdd({ it.id == id }, { QQImpl(this as QQAndroidBot, coroutineContext, id) })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun QQ(id: Long): QQ {
|
override fun QQ(id: Long): QQ {
|
||||||
|
@ -115,7 +115,8 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
|
|||||||
|
|
||||||
//val msg = MessageSvc.PbGetMsg(bot.client, MsgSvc.SyncFlag.START, currentTimeSeconds).sendAndExpect<MessageSvc.PbGetMsg.Response>()
|
//val msg = MessageSvc.PbGetMsg(bot.client, MsgSvc.SyncFlag.START, currentTimeSeconds).sendAndExpect<MessageSvc.PbGetMsg.Response>()
|
||||||
//println(msg.contentToString())
|
//println(msg.contentToString())
|
||||||
|
bot.qqs.delegate.clear()
|
||||||
|
bot.groups.delegate.clear()
|
||||||
|
|
||||||
val startTime = currentTimeMillis
|
val startTime = currentTimeMillis
|
||||||
try {
|
try {
|
||||||
@ -134,7 +135,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
|
|||||||
totalFriendCount = data.totalFriendCount
|
totalFriendCount = data.totalFriendCount
|
||||||
data.friendList.forEach {
|
data.friendList.forEach {
|
||||||
// atomic add
|
// atomic add
|
||||||
bot.qqs.delegate.addLast(bot.getQQ(it.friendUin).also {
|
bot.qqs.delegate.addLast(bot.getFriend(it.friendUin).also {
|
||||||
currentFriendCount++
|
currentFriendCount++
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -475,12 +476,12 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
|
|||||||
/**
|
/**
|
||||||
* 发送一个包, 并挂起直到接收到指定的返回包或超时(3000ms)
|
* 发送一个包, 并挂起直到接收到指定的返回包或超时(3000ms)
|
||||||
*/
|
*/
|
||||||
suspend fun <E : Packet> OutgoingPacket.sendAndExpect(timeoutMillis: Long = 3000, retry: Int = 1): E {
|
suspend fun <E : Packet> OutgoingPacket.sendAndExpect(timeoutMillis: Long = 3000, retry: Int = 0): E {
|
||||||
require(timeoutMillis > 0) { "timeoutMillis must > 0" }
|
require(timeoutMillis > 0) { "timeoutMillis must > 0" }
|
||||||
require(retry >= 0) { "retry must >= 0" }
|
require(retry >= 0) { "retry must >= 0" }
|
||||||
|
|
||||||
var lastException: Exception? = null
|
var lastException: Exception? = null
|
||||||
repeat(retry + 1) {
|
if (retry == 0) {
|
||||||
val handler = PacketListener(commandName = commandName, sequenceId = sequenceId)
|
val handler = PacketListener(commandName = commandName, sequenceId = sequenceId)
|
||||||
packetListeners.addLast(handler)
|
packetListeners.addLast(handler)
|
||||||
try {
|
try {
|
||||||
@ -495,6 +496,25 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
|
|||||||
} ?: net.mamoe.mirai.qqandroid.utils.inline {
|
} ?: net.mamoe.mirai.qqandroid.utils.inline {
|
||||||
error("timeout when receiving response of $commandName")
|
error("timeout when receiving response of $commandName")
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
|
packetListeners.remove(handler)
|
||||||
|
}
|
||||||
|
} else this.delegate.useBytes { data, length ->
|
||||||
|
repeat(retry + 1) {
|
||||||
|
val handler = PacketListener(commandName = commandName, sequenceId = sequenceId)
|
||||||
|
packetListeners.addLast(handler)
|
||||||
|
try {
|
||||||
|
withContext(this@QQAndroidBotNetworkHandler.coroutineContext + CoroutineName("Packet sender")) {
|
||||||
|
channel.send(data, 0, length)
|
||||||
|
}
|
||||||
|
bot.logger.info("Send: ${this.commandName}")
|
||||||
|
return withTimeoutOrNull(timeoutMillis) {
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
handler.await() as E
|
||||||
|
// 不要 `withTimeout`. timeout 的异常会不知道去哪了.
|
||||||
|
} ?: net.mamoe.mirai.qqandroid.utils.inline {
|
||||||
|
error("timeout when receiving response of $commandName")
|
||||||
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
lastException = e
|
lastException = e
|
||||||
} finally {
|
} finally {
|
||||||
@ -503,6 +523,7 @@ internal class QQAndroidBotNetworkHandler(bot: QQAndroidBot) : BotNetworkHandler
|
|||||||
}
|
}
|
||||||
throw lastException!!
|
throw lastException!!
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@PublishedApi
|
@PublishedApi
|
||||||
internal val packetListeners = LockFreeLinkedList<PacketListener>()
|
internal val packetListeners = LockFreeLinkedList<PacketListener>()
|
||||||
|
@ -123,14 +123,11 @@ internal class MessageSvc {
|
|||||||
|
|
||||||
val messages = resp.uinPairMsgs.asSequence().filterNot { it.msg == null }.flatMap { it.msg!!.asSequence() }.mapNotNull {
|
val messages = resp.uinPairMsgs.asSequence().filterNot { it.msg == null }.flatMap { it.msg!!.asSequence() }.mapNotNull {
|
||||||
when (it.msgHead.msgType) {
|
when (it.msgHead.msgType) {
|
||||||
166 -> {
|
166 -> FriendMessage(
|
||||||
FriendMessage(
|
|
||||||
bot,
|
bot,
|
||||||
false, // TODO: 2020/1/29 PREVIOUS??
|
bot.getFriend(it.msgHead.fromUin),
|
||||||
bot.getQQ(it.msgHead.fromUin),
|
|
||||||
it.msgBody.richText.toMessageChain()
|
it.msgBody.richText.toMessageChain()
|
||||||
)
|
)
|
||||||
}
|
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}.toMutableList()
|
}.toMutableList()
|
||||||
@ -176,7 +173,7 @@ internal class MessageSvc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
data class Failed(val errorCode: Int, val errorMessage: String) : Response() {
|
data class Failed(val errorCode: Int, val errorMessage: String) : Response() {
|
||||||
override fun toString(): String = "MessageSvc.PbSendMsg.Response.FAILED(errorCode=$errorCode, errorMessage=$errorMessage"
|
override fun toString(): String = "MessageSvc.PbSendMsg.Response.Failed(errorCode=$errorCode, errorMessage=$errorMessage"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,7 +221,7 @@ internal class MessageSvc {
|
|||||||
///return@buildOutgoingUniPacket
|
///return@buildOutgoingUniPacket
|
||||||
writeProtoBuf(
|
writeProtoBuf(
|
||||||
MsgSvc.PbSendMsgReq.serializer(), MsgSvc.PbSendMsgReq(
|
MsgSvc.PbSendMsgReq.serializer(), MsgSvc.PbSendMsgReq(
|
||||||
routingHead = MsgSvc.RoutingHead(grp = MsgSvc.Grp(groupCode = groupCode)), // TODO: 2020/1/30 确认这里是 id 还是 internalId
|
routingHead = MsgSvc.RoutingHead(grp = MsgSvc.Grp(groupCode = groupCode)),
|
||||||
contentHead = MsgComm.ContentHead(pkgNum = 1, divSeq = seq),
|
contentHead = MsgComm.ContentHead(pkgNum = 1, divSeq = seq),
|
||||||
msgBody = ImMsgBody.MsgBody(
|
msgBody = ImMsgBody.MsgBody(
|
||||||
richText = ImMsgBody.RichText(
|
richText = ImMsgBody.RichText(
|
||||||
|
@ -60,7 +60,13 @@ abstract class Bot : CoroutineScope {
|
|||||||
/**
|
/**
|
||||||
* 获取一个好友对象. 若没有这个好友, 则会抛出异常 [NoSuchElementException]
|
* 获取一个好友对象. 若没有这个好友, 则会抛出异常 [NoSuchElementException]
|
||||||
*/
|
*/
|
||||||
abstract fun getQQ(id: Long): QQ
|
@Deprecated(message = "这个函数有歧义. 它获取的是好友, 却名为 getQQ", replaceWith = ReplaceWith("getFriend(id)"))
|
||||||
|
fun getQQ(id: Long): QQ = getFriend(id)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取一个好友对象. 若没有这个好友, 则会抛出异常 [NoSuchElementException]
|
||||||
|
*/
|
||||||
|
abstract fun getFriend(id: Long): QQ
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造一个 [QQ] 对象. 它持有对 [Bot] 的弱引用([WeakRef]).
|
* 构造一个 [QQ] 对象. 它持有对 [Bot] 的弱引用([WeakRef]).
|
||||||
@ -133,8 +139,8 @@ abstract class Bot : CoroutineScope {
|
|||||||
|
|
||||||
// region extensions
|
// region extensions
|
||||||
|
|
||||||
fun Int.qq(): QQ = getQQ(this.toLong())
|
fun Int.qq(): QQ = getFriend(this.toLong())
|
||||||
fun Long.qq(): QQ = getQQ(this)
|
fun Long.qq(): QQ = getFriend(this)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -11,7 +11,7 @@ import net.mamoe.mirai.data.Profile
|
|||||||
/**
|
/**
|
||||||
* QQ 对象.
|
* QQ 对象.
|
||||||
* 注意: 一个 [QQ] 实例并不是独立的, 它属于一个 [Bot].
|
* 注意: 一个 [QQ] 实例并不是独立的, 它属于一个 [Bot].
|
||||||
* 它不能被直接构造. 任何时候都应从 [Bot.getQQ] 或事件中获取.
|
* 它不能被直接构造. 任何时候都应从 [Bot.getFriend] 或事件中获取.
|
||||||
*
|
*
|
||||||
* 对于同一个 [Bot] 任何一个人的 [QQ] 实例都是单一的.
|
* 对于同一个 [Bot] 任何一个人的 [QQ] 实例都是单一的.
|
||||||
*
|
*
|
||||||
|
@ -8,20 +8,9 @@ import net.mamoe.mirai.utils.MiraiInternalAPI
|
|||||||
|
|
||||||
class FriendMessage(
|
class FriendMessage(
|
||||||
bot: Bot,
|
bot: Bot,
|
||||||
/**
|
|
||||||
* 是否是在这次登录之前的消息, 即消息记录
|
|
||||||
*/
|
|
||||||
val previous: Boolean,
|
|
||||||
override val sender: QQ,
|
override val sender: QQ,
|
||||||
override val message: MessageChain
|
override val message: MessageChain
|
||||||
) : MessagePacket<QQ, QQ>(bot), BroadcastControllable {
|
) : MessagePacket<QQ, QQ>(bot), BroadcastControllable {
|
||||||
/**
|
|
||||||
* 是否应被自动广播. 此为内部 API
|
|
||||||
*/
|
|
||||||
@MiraiInternalAPI
|
|
||||||
override val shouldBroadcast: Boolean
|
|
||||||
get() = !previous
|
|
||||||
|
|
||||||
override val subject: QQ get() = sender
|
override val subject: QQ get() = sender
|
||||||
|
|
||||||
override fun toString(): String = "FriendMessage(sender=${sender.id}, message=$message)"
|
override fun toString(): String = "FriendMessage(sender=${sender.id}, message=$message)"
|
||||||
|
@ -4,7 +4,9 @@ package net.mamoe.mirai.message
|
|||||||
|
|
||||||
import kotlinx.io.core.ByteReadPacket
|
import kotlinx.io.core.ByteReadPacket
|
||||||
import net.mamoe.mirai.Bot
|
import net.mamoe.mirai.Bot
|
||||||
import net.mamoe.mirai.contact.*
|
import net.mamoe.mirai.contact.Contact
|
||||||
|
import net.mamoe.mirai.contact.Group
|
||||||
|
import net.mamoe.mirai.contact.QQ
|
||||||
import net.mamoe.mirai.data.EventPacket
|
import net.mamoe.mirai.data.EventPacket
|
||||||
import net.mamoe.mirai.event.events.BotEvent
|
import net.mamoe.mirai.event.events.BotEvent
|
||||||
import net.mamoe.mirai.message.data.*
|
import net.mamoe.mirai.message.data.*
|
||||||
@ -71,12 +73,19 @@ abstract class MessagePacketBase<TSender : QQ, TSubject : Contact>(_bot: Bot) :
|
|||||||
|
|
||||||
// region Image download
|
// region Image download
|
||||||
suspend inline fun Image.downloadAsByteArray(): ByteArray = bot.run { downloadAsByteArray() }
|
suspend inline fun Image.downloadAsByteArray(): ByteArray = bot.run { downloadAsByteArray() }
|
||||||
|
|
||||||
suspend inline fun Image.download(): ByteReadPacket = bot.run { download() }
|
suspend inline fun Image.download(): ByteReadPacket = bot.run { download() }
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
fun At.qq(): QQ = bot.getQQ(this.target)
|
@Deprecated(message = "这个函数有歧义, 将在不久后删除", replaceWith = ReplaceWith("bot.getFriend(this.target)"))
|
||||||
|
fun At.qq(): QQ = bot.getFriend(this.target)
|
||||||
|
|
||||||
fun Int.qq(): QQ = bot.getQQ(this.coerceAtLeastOrFail(0).toLong())
|
@Deprecated(message = "这个函数有歧义, 将在不久后删除", replaceWith = ReplaceWith("bot.getFriend(this.toLong())"))
|
||||||
fun Long.qq(): QQ = bot.getQQ(this.coerceAtLeastOrFail(0))
|
fun Int.qq(): QQ = bot.getFriend(this.coerceAtLeastOrFail(0).toLong())
|
||||||
|
|
||||||
|
@Deprecated(message = "这个函数有歧义, 将在不久后删除", replaceWith = ReplaceWith("bot.getFriend(this)"))
|
||||||
|
fun Long.qq(): QQ = bot.getFriend(this.coerceAtLeastOrFail(0))
|
||||||
|
|
||||||
|
@Deprecated(message = "这个函数有歧义, 将在不久后删除", replaceWith = ReplaceWith("bot.getGroup(this)"))
|
||||||
|
fun Long.group(): Group = bot.getGroup(this)
|
||||||
}
|
}
|
@ -34,7 +34,7 @@ fun ByteReadPacket.transferTo(outputStream: OutputStream) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <R> ByteReadPacket.useBytes(
|
inline fun <R> ByteReadPacket.useBytes(
|
||||||
n: Int = remaining.toInt(),//not that safe but adequate
|
n: Int = remaining.toInt(),//not that safe but adequate
|
||||||
block: (data: ByteArray, length: Int) -> R
|
block: (data: ByteArray, length: Int) -> R
|
||||||
): R = ByteArrayPool.useInstance {
|
): R = ByteArrayPool.useInstance {
|
||||||
|
@ -23,7 +23,7 @@ internal class BlockingBotImpl(private val bot: Bot) : BlockingBot {
|
|||||||
@UseExperimental(MiraiInternalAPI::class)
|
@UseExperimental(MiraiInternalAPI::class)
|
||||||
override fun getQQs(): List<BlockingQQ> = bot.qqs.delegate.toList().map { it.blocking() }
|
override fun getQQs(): List<BlockingQQ> = bot.qqs.delegate.toList().map { it.blocking() }
|
||||||
|
|
||||||
override fun getQQ(id: Long): BlockingQQ = bot.getQQ(id).blocking()
|
override fun getQQ(id: Long): BlockingQQ = bot.getFriend(id).blocking()
|
||||||
@UseExperimental(MiraiInternalAPI::class)
|
@UseExperimental(MiraiInternalAPI::class)
|
||||||
override fun getGroups(): List<BlockingGroup> = bot.groups.delegate.toList().map { it.blocking() }
|
override fun getGroups(): List<BlockingGroup> = bot.groups.delegate.toList().map { it.blocking() }
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user