mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-07 16:40:43 +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 val size: Int
|
||||||
|
|
||||||
public operator fun <T> get(key: TypeKey<T>): T
|
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 operator fun <T> contains(key: TypeKey<T>): Boolean = get(key) != null
|
||||||
|
|
||||||
public fun toMapBoxed(): Map<TypeKey<*>, Any?>
|
public fun toMapBoxed(): Map<TypeKey<*>, Any?>
|
||||||
@ -80,7 +81,10 @@ internal open class TypeSafeMapImpl(
|
|||||||
override operator fun <T> get(key: TypeKey<T>): T =
|
override operator fun <T> get(key: TypeKey<T>): T =
|
||||||
map[key.name]?.uncheckedCast() ?: throw NoSuchElementException(key.toString())
|
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 toMapBoxed(): Map<TypeKey<*>, Any?> = map.mapKeys { TypeKey<Any?>(it.key) }
|
||||||
override fun toMap(): Map<String, Any?> = map
|
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.components.MessageSvcSyncer
|
||||||
import net.mamoe.mirai.internal.network.handler.logger
|
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.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.data.proto.MsgComm
|
||||||
import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacket
|
import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacket
|
||||||
import net.mamoe.mirai.internal.network.protocol.packet.chat.FileManagement
|
import net.mamoe.mirai.internal.network.protocol.packet.chat.FileManagement
|
||||||
@ -357,6 +358,25 @@ internal class FriendSendMessageHandler(
|
|||||||
) : UserSendMessageHandler<FriendImpl>(contact) {
|
) : UserSendMessageHandler<FriendImpl>(contact) {
|
||||||
override val messageSvcSendMessage: (client: QQAndroidClient, contact: FriendImpl, message: MessageChain, fragmented: Boolean, sourceCallback: (Deferred<OnlineMessageSource.Outgoing>) -> Unit) -> List<OutgoingPacket> =
|
override val messageSvcSendMessage: (client: QQAndroidClient, contact: FriendImpl, message: MessageChain, fragmented: Boolean, sourceCallback: (Deferred<OnlineMessageSource.Outgoing>) -> Unit) -> List<OutgoingPacket> =
|
||||||
MessageSvcPbSendMsg::createToFriend
|
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(
|
internal class StrangerSendMessageHandler(
|
||||||
@ -399,8 +419,9 @@ internal open class GroupSendMessageHandler(
|
|||||||
fromAppId: Int,
|
fromAppId: Int,
|
||||||
): OnlineMessageSource.Outgoing {
|
): OnlineMessageSource.Outgoing {
|
||||||
|
|
||||||
val receipt: SendGroupMessageReceipt =
|
val receipt: SendGroupMessageReceipt = nextEventOrNull(3000) {
|
||||||
nextEventOrNull(3000) { it.fromAppId == fromAppId } ?: SendGroupMessageReceipt.EMPTY
|
it.bot === bot && it.fromAppId == fromAppId
|
||||||
|
} ?: SendGroupMessageReceipt.EMPTY
|
||||||
|
|
||||||
return OnlineMessageSourceToGroupImpl(
|
return OnlineMessageSourceToGroupImpl(
|
||||||
contact,
|
contact,
|
||||||
|
@ -172,6 +172,7 @@ internal class OnlineMessageSourceToGroupImpl(
|
|||||||
coroutineScope.asyncFromEventOrNull<SendGroupMessageReceipt, IntArray>(
|
coroutineScope.asyncFromEventOrNull<SendGroupMessageReceipt, IntArray>(
|
||||||
timeoutMillis = 3000L * this@OnlineMessageSourceToGroupImpl.internalIds.size
|
timeoutMillis = 3000L * this@OnlineMessageSourceToGroupImpl.internalIds.size
|
||||||
) {
|
) {
|
||||||
|
if (it.bot !== this.bot) return@asyncFromEventOrNull null
|
||||||
if (it.messageRandom in this@OnlineMessageSourceToGroupImpl.internalIds) {
|
if (it.messageRandom in this@OnlineMessageSourceToGroupImpl.internalIds) {
|
||||||
multi[it.messageRandom] = it.sequenceId
|
multi[it.messageRandom] = it.sequenceId
|
||||||
if (multi.size == this@OnlineMessageSourceToGroupImpl.internalIds.size) {
|
if (multi.size == this@OnlineMessageSourceToGroupImpl.internalIds.size) {
|
||||||
|
@ -141,6 +141,7 @@ internal interface NoticePipelineContext : BotAware, NewContactSupport {
|
|||||||
val KEY_MSG_INFO = TypeKey<MsgInfo>("msgInfo")
|
val KEY_MSG_INFO = TypeKey<MsgInfo>("msgInfo")
|
||||||
|
|
||||||
val NoticePipelineContext.fromSync get() = attributes[KEY_FROM_SYNC]
|
val NoticePipelineContext.fromSync get() = attributes[KEY_FROM_SYNC]
|
||||||
|
val NoticePipelineContext.fromSyncSafely get() = attributes[KEY_FROM_SYNC, false]
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 来自 [MsgInfo] 的数据, 即 [MsgType0x210], [MsgType0x2DC] 的处理过程之中可以使用
|
* 来自 [MsgInfo] 的数据, 即 [MsgType0x210], [MsgType0x2DC] 的处理过程之中可以使用
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai.internal.network.notice.group
|
package net.mamoe.mirai.internal.network.notice.group
|
||||||
|
|
||||||
|
import net.mamoe.mirai.Bot
|
||||||
import net.mamoe.mirai.contact.Member
|
import net.mamoe.mirai.contact.Member
|
||||||
import net.mamoe.mirai.event.AbstractEvent
|
import net.mamoe.mirai.event.AbstractEvent
|
||||||
import net.mamoe.mirai.event.Event
|
import net.mamoe.mirai.event.Event
|
||||||
@ -44,6 +45,7 @@ internal class GroupMessageProcessor(
|
|||||||
private val logger: MiraiLogger,
|
private val logger: MiraiLogger,
|
||||||
) : SimpleNoticeProcessor<MsgOnlinePush.PbPushMsg>(type()) {
|
) : SimpleNoticeProcessor<MsgOnlinePush.PbPushMsg>(type()) {
|
||||||
internal data class SendGroupMessageReceipt(
|
internal data class SendGroupMessageReceipt(
|
||||||
|
val bot: Bot?,
|
||||||
val messageRandom: Int,
|
val messageRandom: Int,
|
||||||
val sequenceId: Int,
|
val sequenceId: Int,
|
||||||
val fromAppId: Int,
|
val fromAppId: Int,
|
||||||
@ -53,7 +55,7 @@ internal class GroupMessageProcessor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
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
|
// 3116=group music share
|
||||||
// 2021=group file
|
// 2021=group file
|
||||||
// message sent by bot
|
// message sent by bot
|
||||||
collect(SendGroupMessageReceipt(messageRandom, msgHead.msgSeq, msgHead.fromAppid))
|
collect(SendGroupMessageReceipt(bot, messageRandom, msgHead.msgSeq, msgHead.fromAppid))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// else: sync form other device
|
// else: sync form other device
|
||||||
|
@ -9,12 +9,17 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai.internal.network.notice.priv
|
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.event.events.*
|
||||||
import net.mamoe.mirai.internal.contact.*
|
import net.mamoe.mirai.internal.contact.*
|
||||||
import net.mamoe.mirai.internal.getGroupByUinOrCode
|
import net.mamoe.mirai.internal.getGroupByUinOrCode
|
||||||
import net.mamoe.mirai.internal.message.toMessageChainOnline
|
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
|
||||||
import net.mamoe.mirai.internal.network.components.NoticePipelineContext.Companion.fromSync
|
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.SimpleNoticeProcessor
|
||||||
import net.mamoe.mirai.internal.network.components.SsoProcessor
|
import net.mamoe.mirai.internal.network.components.SsoProcessor
|
||||||
import net.mamoe.mirai.internal.network.notice.group.GroupMessageProcessor
|
import net.mamoe.mirai.internal.network.notice.group.GroupMessageProcessor
|
||||||
@ -36,8 +41,35 @@ import net.mamoe.mirai.utils.context
|
|||||||
* @see GroupTempMessageSyncEvent
|
* @see GroupTempMessageSyncEvent
|
||||||
*/
|
*/
|
||||||
internal class PrivateMessageProcessor : SimpleNoticeProcessor<MsgComm.Msg>(type()) {
|
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 {
|
override suspend fun NoticePipelineContext.processImpl(data: MsgComm.Msg) = data.context {
|
||||||
markAsConsumed()
|
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) {
|
if (msgHead.fromUin == bot.id && fromSync) {
|
||||||
// Bot send message to himself? or from other client? I am not the implementer.
|
// Bot send message to himself? or from other client? I am not the implementer.
|
||||||
bot.client.sendFriendMessageSeq.updateIfSmallerThan(msgHead.msgSeq)
|
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