mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-05 23:50:08 +08:00
Support sending MusicShare
to friends. (#1615)
* Support sending `MusicShare` to friends. - Also fix a potential data out-of-bounds issues * `TypeSafeMap.get` with default values * Fix tests
This commit is contained in:
parent
e61fbbcc70
commit
217907c58a
@ -31,6 +31,7 @@ public sealed interface TypeSafeMap {
|
||||
public val size: Int
|
||||
|
||||
public operator fun <T> get(key: TypeKey<T>): T
|
||||
public operator fun <T> get(key: TypeKey<T>, defaultValue: T): T
|
||||
public operator fun <T> contains(key: TypeKey<T>): Boolean = get(key) != null
|
||||
|
||||
public fun toMapBoxed(): Map<TypeKey<*>, Any?>
|
||||
@ -80,7 +81,10 @@ internal open class TypeSafeMapImpl(
|
||||
override operator fun <T> get(key: TypeKey<T>): T =
|
||||
map[key.name]?.uncheckedCast() ?: throw NoSuchElementException(key.toString())
|
||||
|
||||
override operator fun <T> contains(key: TypeKey<T>): Boolean = get(key) != null
|
||||
override operator fun <T> get(key: TypeKey<T>, defaultValue: T): T =
|
||||
map[key.name]?.uncheckedCast() ?: defaultValue
|
||||
|
||||
override operator fun <T> contains(key: TypeKey<T>): Boolean = map.containsKey(key.name)
|
||||
|
||||
override fun toMapBoxed(): Map<TypeKey<*>, Any?> = map.mapKeys { TypeKey<Any?>(it.key) }
|
||||
override fun toMap(): Map<String, Any?> = map
|
||||
|
@ -23,6 +23,7 @@ import net.mamoe.mirai.internal.network.components.ClockHolder.Companion.clock
|
||||
import net.mamoe.mirai.internal.network.components.MessageSvcSyncer
|
||||
import net.mamoe.mirai.internal.network.handler.logger
|
||||
import net.mamoe.mirai.internal.network.notice.group.GroupMessageProcessor.SendGroupMessageReceipt
|
||||
import net.mamoe.mirai.internal.network.notice.priv.PrivateMessageProcessor.SendPrivateMessageReceipt
|
||||
import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacket
|
||||
import net.mamoe.mirai.internal.network.protocol.packet.chat.FileManagement
|
||||
@ -357,6 +358,25 @@ internal class FriendSendMessageHandler(
|
||||
) : UserSendMessageHandler<FriendImpl>(contact) {
|
||||
override val messageSvcSendMessage: (client: QQAndroidClient, contact: FriendImpl, message: MessageChain, fragmented: Boolean, sourceCallback: (Deferred<OnlineMessageSource.Outgoing>) -> Unit) -> List<OutgoingPacket> =
|
||||
MessageSvcPbSendMsg::createToFriend
|
||||
|
||||
override suspend fun constructSourceForSpecialMessage(
|
||||
finalMessage: MessageChain,
|
||||
fromAppId: Int
|
||||
): OnlineMessageSource.Outgoing {
|
||||
|
||||
val receipt: SendPrivateMessageReceipt = nextEventOrNull(3000) {
|
||||
it.bot === bot && it.fromAppId == fromAppId
|
||||
} ?: SendPrivateMessageReceipt.EMPTY
|
||||
|
||||
return OnlineMessageSourceToFriendImpl(
|
||||
internalIds = intArrayOf(receipt.messageRandom),
|
||||
sequenceIds = intArrayOf(receipt.sequenceId),
|
||||
sender = bot,
|
||||
target = contact,
|
||||
time = bot.clock.server.currentTimeSeconds().toInt(),
|
||||
originalMessage = finalMessage
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal class StrangerSendMessageHandler(
|
||||
@ -399,8 +419,9 @@ internal open class GroupSendMessageHandler(
|
||||
fromAppId: Int,
|
||||
): OnlineMessageSource.Outgoing {
|
||||
|
||||
val receipt: SendGroupMessageReceipt =
|
||||
nextEventOrNull(3000) { it.fromAppId == fromAppId } ?: SendGroupMessageReceipt.EMPTY
|
||||
val receipt: SendGroupMessageReceipt = nextEventOrNull(3000) {
|
||||
it.bot === bot && it.fromAppId == fromAppId
|
||||
} ?: SendGroupMessageReceipt.EMPTY
|
||||
|
||||
return OnlineMessageSourceToGroupImpl(
|
||||
contact,
|
||||
|
@ -172,6 +172,7 @@ internal class OnlineMessageSourceToGroupImpl(
|
||||
coroutineScope.asyncFromEventOrNull<SendGroupMessageReceipt, IntArray>(
|
||||
timeoutMillis = 3000L * this@OnlineMessageSourceToGroupImpl.internalIds.size
|
||||
) {
|
||||
if (it.bot !== this.bot) return@asyncFromEventOrNull null
|
||||
if (it.messageRandom in this@OnlineMessageSourceToGroupImpl.internalIds) {
|
||||
multi[it.messageRandom] = it.sequenceId
|
||||
if (multi.size == this@OnlineMessageSourceToGroupImpl.internalIds.size) {
|
||||
|
@ -141,6 +141,7 @@ internal interface NoticePipelineContext : BotAware, NewContactSupport {
|
||||
val KEY_MSG_INFO = TypeKey<MsgInfo>("msgInfo")
|
||||
|
||||
val NoticePipelineContext.fromSync get() = attributes[KEY_FROM_SYNC]
|
||||
val NoticePipelineContext.fromSyncSafely get() = attributes[KEY_FROM_SYNC, false]
|
||||
|
||||
/**
|
||||
* 来自 [MsgInfo] 的数据, 即 [MsgType0x210], [MsgType0x2DC] 的处理过程之中可以使用
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
package net.mamoe.mirai.internal.network.notice.group
|
||||
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.contact.Member
|
||||
import net.mamoe.mirai.event.AbstractEvent
|
||||
import net.mamoe.mirai.event.Event
|
||||
@ -44,6 +45,7 @@ internal class GroupMessageProcessor(
|
||||
private val logger: MiraiLogger,
|
||||
) : SimpleNoticeProcessor<MsgOnlinePush.PbPushMsg>(type()) {
|
||||
internal data class SendGroupMessageReceipt(
|
||||
val bot: Bot?,
|
||||
val messageRandom: Int,
|
||||
val sequenceId: Int,
|
||||
val fromAppId: Int,
|
||||
@ -53,7 +55,7 @@ internal class GroupMessageProcessor(
|
||||
}
|
||||
|
||||
companion object {
|
||||
val EMPTY = SendGroupMessageReceipt(0, 0, 0)
|
||||
val EMPTY = SendGroupMessageReceipt(null, 0, 0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
@ -81,7 +83,7 @@ internal class GroupMessageProcessor(
|
||||
// 3116=group music share
|
||||
// 2021=group file
|
||||
// message sent by bot
|
||||
collect(SendGroupMessageReceipt(messageRandom, msgHead.msgSeq, msgHead.fromAppid))
|
||||
collect(SendGroupMessageReceipt(bot, messageRandom, msgHead.msgSeq, msgHead.fromAppid))
|
||||
return
|
||||
}
|
||||
// else: sync form other device
|
||||
|
@ -9,12 +9,17 @@
|
||||
|
||||
package net.mamoe.mirai.internal.network.notice.priv
|
||||
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.event.AbstractEvent
|
||||
import net.mamoe.mirai.event.Event
|
||||
import net.mamoe.mirai.event.events.*
|
||||
import net.mamoe.mirai.internal.contact.*
|
||||
import net.mamoe.mirai.internal.getGroupByUinOrCode
|
||||
import net.mamoe.mirai.internal.message.toMessageChainOnline
|
||||
import net.mamoe.mirai.internal.network.Packet
|
||||
import net.mamoe.mirai.internal.network.components.NoticePipelineContext
|
||||
import net.mamoe.mirai.internal.network.components.NoticePipelineContext.Companion.fromSync
|
||||
import net.mamoe.mirai.internal.network.components.NoticePipelineContext.Companion.fromSyncSafely
|
||||
import net.mamoe.mirai.internal.network.components.SimpleNoticeProcessor
|
||||
import net.mamoe.mirai.internal.network.components.SsoProcessor
|
||||
import net.mamoe.mirai.internal.network.notice.group.GroupMessageProcessor
|
||||
@ -36,8 +41,35 @@ import net.mamoe.mirai.utils.context
|
||||
* @see GroupTempMessageSyncEvent
|
||||
*/
|
||||
internal class PrivateMessageProcessor : SimpleNoticeProcessor<MsgComm.Msg>(type()) {
|
||||
|
||||
internal data class SendPrivateMessageReceipt(
|
||||
val bot: Bot?,
|
||||
val messageRandom: Int,
|
||||
val sequenceId: Int,
|
||||
val fromAppId: Int,
|
||||
) : Packet, Event, Packet.NoLog, AbstractEvent() {
|
||||
override fun toString(): String {
|
||||
return "OnlinePush.PbC2CMsgSync.SendPrivateMessageReceipt(messageRandom=$messageRandom, sequenceId=$sequenceId)"
|
||||
}
|
||||
|
||||
companion object {
|
||||
val EMPTY = SendPrivateMessageReceipt(null, 0, 0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun NoticePipelineContext.processImpl(data: MsgComm.Msg) = data.context {
|
||||
markAsConsumed()
|
||||
|
||||
if (fromSyncSafely) {
|
||||
val msgFromAppid = msgHead.fromAppid
|
||||
// 3116 = music share
|
||||
// message sent by bot
|
||||
if (msgFromAppid == 3116) {
|
||||
handleSpecialMessageSendingResponse(data, msgFromAppid)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if (msgHead.fromUin == bot.id && fromSync) {
|
||||
// Bot send message to himself? or from other client? I am not the implementer.
|
||||
bot.client.sendFriendMessageSeq.updateIfSmallerThan(msgHead.msgSeq)
|
||||
@ -107,4 +139,16 @@ internal class PrivateMessageProcessor : SimpleNoticeProcessor<MsgComm.Msg>(type
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun NoticePipelineContext.handleSpecialMessageSendingResponse(
|
||||
data: MsgComm.Msg,
|
||||
fromAppId: Int,
|
||||
) = data.context {
|
||||
val messageRandom = data.msgBody.richText.attr?.random ?: return
|
||||
collect(
|
||||
SendPrivateMessageReceipt(
|
||||
bot, messageRandom, data.msgHead.msgSeq, fromAppId
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user