Commit 6f0853e6 authored by Him188's avatar Him188

Implement `MessagePreSendEvent` and `MessagePostSendEvent`.

Deprecate `MessageSendEvent`
Fix #339
parent 4c79d4cd
...@@ -33,6 +33,7 @@ import net.mamoe.mirai.event.events.ImageUploadEvent ...@@ -33,6 +33,7 @@ import net.mamoe.mirai.event.events.ImageUploadEvent
import net.mamoe.mirai.message.MessageReceipt import net.mamoe.mirai.message.MessageReceipt
import net.mamoe.mirai.message.data.Image import net.mamoe.mirai.message.data.Image
import net.mamoe.mirai.message.data.Message import net.mamoe.mirai.message.data.Message
import net.mamoe.mirai.message.data.OfflineFriendImage
import net.mamoe.mirai.message.data.isContentNotEmpty import net.mamoe.mirai.message.data.isContentNotEmpty
import net.mamoe.mirai.qqandroid.QQAndroidBot import net.mamoe.mirai.qqandroid.QQAndroidBot
import net.mamoe.mirai.qqandroid.network.highway.postImage import net.mamoe.mirai.qqandroid.network.highway.postImage
...@@ -87,7 +88,11 @@ internal class FriendImpl( ...@@ -87,7 +88,11 @@ internal class FriendImpl(
@Suppress("DuplicatedCode") @Suppress("DuplicatedCode")
override suspend fun sendMessage(message: Message): MessageReceipt<Friend> { override suspend fun sendMessage(message: Message): MessageReceipt<Friend> {
require(message.isContentNotEmpty()) { "message is empty" } require(message.isContentNotEmpty()) { "message is empty" }
return sendMessageImpl(this, message).also { return sendMessageImpl(
message,
friendReceiptConstructor = { MessageReceipt(it, this, null) },
tReceiptConstructor = { MessageReceipt(it, this, null) }
).also {
logMessageSent(message) logMessageSent(message)
} }
} }
...@@ -101,23 +106,23 @@ internal class FriendImpl( ...@@ -101,23 +106,23 @@ internal class FriendImpl(
if (BeforeImageUploadEvent(this, image).broadcast().isCancelled) { if (BeforeImageUploadEvent(this, image).broadcast().isCancelled) {
throw EventCancelledException("cancelled by BeforeImageUploadEvent.ToGroup") throw EventCancelledException("cancelled by BeforeImageUploadEvent.ToGroup")
} }
bot.network.run { val response = bot.network.run {
val response = LongConn.OffPicUp( LongConn.OffPicUp(
bot.client, Cmd0x352.TryUpImgReq( bot.client, Cmd0x352.TryUpImgReq(
srcUin = bot.id.toInt(), srcUin = bot.id.toInt(),
dstUin = id.toInt(), dstUin = id.toInt(),
fileId = 0, fileId = 0,
fileMd5 = @Suppress("INVISIBLE_MEMBER") image.md5, fileMd5 = image.md5,
fileSize = @Suppress("INVISIBLE_MEMBER") fileSize = image.input.size.toInt(),
image.input.size.toInt(), fileName = image.md5.toUHexString("") + "." + ExternalImage.defaultFormatName,
fileName = @Suppress("INVISIBLE_MEMBER") image.md5.toUHexString("") + "." + ExternalImage.defaultFormatName,
imgOriginal = 1 imgOriginal = 1
) )
).sendAndExpect<LongConn.OffPicUp.Response>() ).sendAndExpect<LongConn.OffPicUp.Response>()
}
@Suppress("UNCHECKED_CAST", "DEPRECATION", "INVISIBLE_MEMBER") @Suppress("UNCHECKED_CAST", "DEPRECATION")
return when (response) { when (response) {
is LongConn.OffPicUp.Response.FileExists -> net.mamoe.mirai.message.data.OfflineFriendImage(response.resourceId) is LongConn.OffPicUp.Response.FileExists -> OfflineFriendImage(response.resourceId)
.also { .also {
ImageUploadEvent.Succeed(this@FriendImpl, image, it).broadcast() ImageUploadEvent.Succeed(this@FriendImpl, image, it).broadcast()
} }
...@@ -151,7 +156,7 @@ internal class FriendImpl( ...@@ -151,7 +156,7 @@ internal class FriendImpl(
)*/ )*/
// 为什么不能 ?? // 为什么不能 ??
return net.mamoe.mirai.message.data.OfflineFriendImage(response.resourceId).also { OfflineFriendImage(response.resourceId).also {
ImageUploadEvent.Succeed(this@FriendImpl, image, it).broadcast() ImageUploadEvent.Succeed(this@FriendImpl, image, it).broadcast()
} }
} }
...@@ -160,7 +165,6 @@ internal class FriendImpl( ...@@ -160,7 +165,6 @@ internal class FriendImpl(
error(response.message) error(response.message)
} }
} }
}
} finally { } finally {
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
(image.input as? Closeable)?.close() (image.input as? Closeable)?.close()
......
...@@ -22,7 +22,6 @@ import net.mamoe.mirai.data.GroupInfo ...@@ -22,7 +22,6 @@ import net.mamoe.mirai.data.GroupInfo
import net.mamoe.mirai.data.MemberInfo import net.mamoe.mirai.data.MemberInfo
import net.mamoe.mirai.event.broadcast import net.mamoe.mirai.event.broadcast
import net.mamoe.mirai.event.events.* import net.mamoe.mirai.event.events.*
import net.mamoe.mirai.event.events.MessageSendEvent.GroupMessageSendEvent
import net.mamoe.mirai.message.MessageReceipt import net.mamoe.mirai.message.MessageReceipt
import net.mamoe.mirai.message.data.* import net.mamoe.mirai.message.data.*
import net.mamoe.mirai.qqandroid.QQAndroidBot import net.mamoe.mirai.qqandroid.QQAndroidBot
...@@ -33,6 +32,7 @@ import net.mamoe.mirai.qqandroid.network.highway.HighwayHelper ...@@ -33,6 +32,7 @@ import net.mamoe.mirai.qqandroid.network.highway.HighwayHelper
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.TroopManagement import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.TroopManagement
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.image.ImgStore import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.image.ImgStore
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.MessageSvcPbSendMsg import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.MessageSvcPbSendMsg
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.createToGroup
import net.mamoe.mirai.qqandroid.network.protocol.packet.list.ProfileService import net.mamoe.mirai.qqandroid.network.protocol.packet.list.ProfileService
import net.mamoe.mirai.qqandroid.utils.estimateLength import net.mamoe.mirai.qqandroid.utils.estimateLength
import net.mamoe.mirai.utils.* import net.mamoe.mirai.utils.*
...@@ -304,80 +304,66 @@ internal class GroupImpl( ...@@ -304,80 +304,66 @@ internal class GroupImpl(
check(message.nodeList.size < 200) { check(message.nodeList.size < 200) {
throw MessageTooLargeException( throw MessageTooLargeException(
this, message, message, this, message, message,
"ForwardMessage allows up to 200 nodes, but found ${message.nodeList.size}") "ForwardMessage allows up to 200 nodes, but found ${message.nodeList.size}"
)
} }
return bot.lowLevelSendGroupLongOrForwardMessage(this.id, message.nodeList, false, message) return bot.lowLevelSendGroupLongOrForwardMessage(this.id, message.nodeList, false, message)
} }
val msg: MessageChain val msg: MessageChain = if (message !is LongMessage && message !is ForwardMessageInternal) {
val chain = kotlin.runCatching {
if (message !is LongMessage && message !is ForwardMessageInternal) { GroupMessagePreSendEvent(this, message).broadcast()
val event = GroupMessageSendEvent(this, message.asMessageChain()).broadcast() }.onSuccess {
if (event.isCancelled) { check(!it.isCancelled) {
throw EventCancelledException("cancelled by GroupMessageSendEvent") throw EventCancelledException("cancelled by GroupMessagePreSendEvent")
} }
}.getOrElse {
throw EventCancelledException("exception thrown when broadcasting GroupMessagePreSendEvent", it)
}.message.asMessageChain()
val length = event.message.estimateLength(703) // 阈值为700左右,限制到3的倍数 val length = chain.estimateLength(703) // 阈值为700左右,限制到3的倍数
var imageCnt = 0 // 通过下方逻辑短路延迟计算 var imageCnt = 0 // 通过下方逻辑短路延迟计算
if (length > 5000 || event.message.count { it is Image }.apply { imageCnt = this } > 50) { if (length > 5000 || chain.count { it is Image }.apply { imageCnt = this } > 50) {
throw MessageTooLargeException( throw MessageTooLargeException(
this, this, message, chain,
message, "message(${chain.joinToString("", limit = 10)}) is too large. Allow up to 50 images or 5000 chars"
event.message,
"message(${event.message.joinToString(
"",
limit = 10
)}) is too large. Allow up to 50 images or 5000 chars"
) )
} }
if (length > 702 || imageCnt > 2) { if (length > 702 || imageCnt > 2) {
return bot.lowLevelSendGroupLongOrForwardMessage(this.id, return bot.lowLevelSendGroupLongOrForwardMessage(
listOf(ForwardMessage.Node( this.id,
listOf(
ForwardMessage.Node(
senderId = bot.id, senderId = bot.id,
time = currentTimeSeconds.toInt(), time = currentTimeSeconds.toInt(),
message = event.message, message = chain,
senderName = bot.nick) senderName = bot.nick
)
), ),
true, null) true, null
)
} }
chain
} else message.asMessageChain()
msg = event.message
} else msg = message.asMessageChain()
msg.firstIsInstanceOrNull<QuoteReply>()?.source?.ensureSequenceIdAvailable() msg.firstIsInstanceOrNull<QuoteReply>()?.source?.ensureSequenceIdAvailable()
lateinit var source: MessageSourceToGroupImpl
bot.network.run { val result = bot.network.runCatching {
val response: MessageSvcPbSendMsg.Response = MessageSvcPbSendMsg.createToGroup( val source: MessageSourceToGroupImpl
MessageSvcPbSendMsg.createToGroup(
bot.client, bot.client,
this@GroupImpl, this@GroupImpl,
msg, msg,
isForward isForward
) { ) {
source = it source = it
}.sendAndExpect() }.sendAndExpect<MessageSvcPbSendMsg.Response>().let {
if (response is MessageSvcPbSendMsg.Response.Failed) { check(it is MessageSvcPbSendMsg.Response.SUCCESS) {
when (response.resultType) { "Send temp message failed: $it"
120 -> throw BotIsBeingMutedException(this@GroupImpl)
34 -> {
kotlin.runCatching { // allow retry once
return bot.lowLevelSendGroupLongOrForwardMessage(
id, listOf(
ForwardMessage.Node(
senderId = bot.id,
time = currentTimeSeconds.toInt(),
message = msg,
senderName = bot.nick
)
), true, null)
}.getOrElse {
throw IllegalStateException("internal error: send message failed(34)", it)
}
}
else -> error("send message failed: $response")
}
} }
} }
...@@ -391,7 +377,19 @@ internal class GroupImpl( ...@@ -391,7 +377,19 @@ internal class GroupImpl(
bot.network.logger.warning(e) bot.network.logger.warning(e)
} }
return MessageReceipt(source, this, botAsMember) MessageReceipt(source, this@GroupImpl, botAsMember)
}
result.fold(
onSuccess = {
GroupMessagePostSendEvent(this, msg, null, it)
},
onFailure = {
GroupMessagePostSendEvent(this, msg, it, null)
}
).broadcast()
return result.getOrThrow()
} }
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
......
...@@ -28,6 +28,7 @@ import net.mamoe.mirai.qqandroid.message.firstIsInstanceOrNull ...@@ -28,6 +28,7 @@ import net.mamoe.mirai.qqandroid.message.firstIsInstanceOrNull
import net.mamoe.mirai.qqandroid.network.protocol.data.jce.StTroopMemberInfo import net.mamoe.mirai.qqandroid.network.protocol.data.jce.StTroopMemberInfo
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.TroopManagement import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.TroopManagement
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.MessageSvcPbSendMsg import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.MessageSvcPbSendMsg
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.createToTemp
import net.mamoe.mirai.utils.ExternalImage import net.mamoe.mirai.utils.ExternalImage
import net.mamoe.mirai.utils.currentTimeSeconds import net.mamoe.mirai.utils.currentTimeSeconds
import net.mamoe.mirai.utils.getValue import net.mamoe.mirai.utils.getValue
...@@ -54,34 +55,59 @@ internal class MemberImpl constructor( ...@@ -54,34 +55,59 @@ internal class MemberImpl constructor(
override val id: Long = qq.id override val id: Long = qq.id
override val nick: String = qq.nick override val nick: String = qq.nick
@Suppress("UNCHECKED_CAST")
@JvmSynthetic @JvmSynthetic
override suspend fun sendMessage(message: Message): MessageReceipt<Member> { override suspend fun sendMessage(message: Message): MessageReceipt<Member> {
require(message.isContentNotEmpty()) { "message is empty" } require(message.isContentNotEmpty()) { "message is empty" }
return (this.asFriendOrNull()?.sendMessageImpl(this, message) ?: sendMessageImpl(message)) val asFriend = this.asFriendOrNull()
.also { logMessageSent(message) }
return (asFriend?.sendMessageImpl(
message,
friendReceiptConstructor = { MessageReceipt(it, asFriend, null) },
tReceiptConstructor = { MessageReceipt(it, this, null) }
) ?: sendMessageImpl(message)).also { logMessageSent(message) }
} }
private suspend fun sendMessageImpl(message: Message): MessageReceipt<Member> { private suspend fun sendMessageImpl(message: Message): MessageReceipt<Member> {
val event = MessageSendEvent.TempMessageSendEvent(this, message.asMessageChain()).broadcast() val chain = kotlin.runCatching {
if (event.isCancelled) { TempMessagePreSendEvent(this, message).broadcast()
throw EventCancelledException("cancelled by TempMessageSendEvent") }.onSuccess {
check(!it.isCancelled) {
throw EventCancelledException("cancelled by TempMessagePreSendEvent")
} }
event.message.firstIsInstanceOrNull<QuoteReply>()?.source?.ensureSequenceIdAvailable() }.getOrElse {
throw EventCancelledException("exception thrown when broadcasting TempMessagePreSendEvent", it)
}.message.asMessageChain()
lateinit var source: MessageSourceToTempImpl chain.firstIsInstanceOrNull<QuoteReply>()?.source?.ensureSequenceIdAvailable()
bot.network.run {
check( val result = bot.network.runCatching {
val source: MessageSourceToTempImpl
MessageSvcPbSendMsg.createToTemp( MessageSvcPbSendMsg.createToTemp(
bot.client, bot.client,
this@MemberImpl, this@MemberImpl,
message.asMessageChain() chain
) { ) {
source = it source = it
}.sendAndExpect<MessageSvcPbSendMsg.Response>() is MessageSvcPbSendMsg.Response.SUCCESS }.sendAndExpect<MessageSvcPbSendMsg.Response>().let {
) { "send message failed" } check(it is MessageSvcPbSendMsg.Response.SUCCESS) {
"Send temp message failed: $it"
}
} }
return MessageReceipt(source, this, null) MessageReceipt(source, this@MemberImpl, null)
}
result.fold(
onSuccess = {
TempMessagePostSendEvent(this, chain, null, it)
},
onFailure = {
TempMessagePostSendEvent(this, chain, it, null)
}
).broadcast()
return result.getOrThrow()
} }
@JvmSynthetic @JvmSynthetic
......
...@@ -12,40 +12,72 @@ package net.mamoe.mirai.qqandroid.contact ...@@ -12,40 +12,72 @@ package net.mamoe.mirai.qqandroid.contact
import net.mamoe.mirai.contact.Contact import net.mamoe.mirai.contact.Contact
import net.mamoe.mirai.contact.Friend import net.mamoe.mirai.contact.Friend
import net.mamoe.mirai.contact.User
import net.mamoe.mirai.event.broadcast import net.mamoe.mirai.event.broadcast
import net.mamoe.mirai.event.events.EventCancelledException import net.mamoe.mirai.event.events.EventCancelledException
import net.mamoe.mirai.event.events.MessageSendEvent import net.mamoe.mirai.event.events.FriendMessagePostSendEvent
import net.mamoe.mirai.event.events.FriendMessagePreSendEvent
import net.mamoe.mirai.message.* import net.mamoe.mirai.message.*
import net.mamoe.mirai.message.data.Message import net.mamoe.mirai.message.data.Message
import net.mamoe.mirai.message.data.QuoteReply import net.mamoe.mirai.message.data.QuoteReply
import net.mamoe.mirai.message.data.asMessageChain import net.mamoe.mirai.message.data.asMessageChain
import net.mamoe.mirai.message.data.firstIsInstanceOrNull
import net.mamoe.mirai.qqandroid.asQQAndroidBot import net.mamoe.mirai.qqandroid.asQQAndroidBot
import net.mamoe.mirai.qqandroid.message.MessageSourceToFriendImpl import net.mamoe.mirai.qqandroid.message.MessageSourceToFriendImpl
import net.mamoe.mirai.qqandroid.message.ensureSequenceIdAvailable import net.mamoe.mirai.qqandroid.message.ensureSequenceIdAvailable
import net.mamoe.mirai.qqandroid.message.firstIsInstanceOrNull
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.MessageSvcPbSendMsg import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.MessageSvcPbSendMsg
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.createToFriend
import net.mamoe.mirai.utils.verbose import net.mamoe.mirai.utils.verbose
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
internal suspend fun <T : Contact> Friend.sendMessageImpl(generic: T, message: Message): MessageReceipt<T> { internal suspend fun <T : User> Friend.sendMessageImpl(
val event = MessageSendEvent.FriendMessageSendEvent(this, message.asMessageChain()).broadcast() message: Message,
if (event.isCancelled) { friendReceiptConstructor: (MessageSourceToFriendImpl) -> MessageReceipt<Friend>,
throw EventCancelledException("cancelled by FriendMessageSendEvent") tReceiptConstructor: (MessageSourceToFriendImpl) -> MessageReceipt<T>
): MessageReceipt<T> {
contract { callsInPlace(friendReceiptConstructor, InvocationKind.EXACTLY_ONCE) }
val bot = bot.asQQAndroidBot()
val chain = kotlin.runCatching {
FriendMessagePreSendEvent(this, message).broadcast()
}.onSuccess {
check(!it.isCancelled) {
throw EventCancelledException("cancelled by FriendMessagePreSendEvent")
} }
event.message.firstIsInstanceOrNull<QuoteReply>()?.source?.ensureSequenceIdAvailable() }.getOrElse {
throw EventCancelledException("exception thrown when broadcasting FriendMessagePreSendEvent", it)
}.message.asMessageChain()
chain.firstIsInstanceOrNull<QuoteReply>()?.source?.ensureSequenceIdAvailable()
lateinit var source: MessageSourceToFriendImpl lateinit var source: MessageSourceToFriendImpl
val bot = bot.asQQAndroidBot() val result = bot.network.runCatching {
bot.network.run {
check(
MessageSvcPbSendMsg.createToFriend( MessageSvcPbSendMsg.createToFriend(
bot.asQQAndroidBot().client, bot.client,
this@sendMessageImpl, this@sendMessageImpl,
event.message chain
) { ) {
source = it source = it
}.sendAndExpect<MessageSvcPbSendMsg.Response>() is MessageSvcPbSendMsg.Response.SUCCESS }.sendAndExpect<MessageSvcPbSendMsg.Response>().let {
) { "send message failed" } check(it is MessageSvcPbSendMsg.Response.SUCCESS) {
"Send temp message failed: $it"
} }
return MessageReceipt(source, generic, null) }
friendReceiptConstructor(source)
}
result.fold(
onSuccess = {
FriendMessagePostSendEvent(this, chain, null, it)
},
onFailure = {
FriendMessagePostSendEvent(this, chain, it, null)
}
).broadcast()
result.getOrThrow()
return tReceiptConstructor(source)
} }
internal fun Contact.logMessageSent(message: Message) { internal fun Contact.logMessageSent(message: Message) {
......
...@@ -34,6 +34,8 @@ import net.mamoe.mirai.qqandroid.utils.io.serialization.readProtoBuf ...@@ -34,6 +34,8 @@ import net.mamoe.mirai.qqandroid.utils.io.serialization.readProtoBuf
import net.mamoe.mirai.qqandroid.utils.io.serialization.toByteArray import net.mamoe.mirai.qqandroid.utils.io.serialization.toByteArray
import net.mamoe.mirai.qqandroid.utils.io.serialization.writeProtoBuf import net.mamoe.mirai.qqandroid.utils.io.serialization.writeProtoBuf
import net.mamoe.mirai.utils.currentTimeSeconds import net.mamoe.mirai.utils.currentTimeSeconds
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
import kotlin.math.absoluteValue import kotlin.math.absoluteValue
import kotlin.random.Random import kotlin.random.Random
...@@ -52,34 +54,11 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg. ...@@ -52,34 +54,11 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg.
} }
} }
inline fun createToFriend(
client: QQAndroidClient,
qq: Friend,
message: MessageChain,
crossinline sourceCallback: (MessageSourceToFriendImpl) -> Unit
): OutgoingPacket {
val rand = Random.nextInt().absoluteValue
val source = MessageSourceToFriendImpl(
internalId = rand,
sender = client.bot,
target = qq,
time = currentTimeSeconds.toInt(),
sequenceId = client.nextFriendSeq(),
originalMessage = message
)
sourceCallback(source)
return createToFriend(
client,
qq.id,
message,
source)
}
/** /**
* 发送好友消息 * 发送好友消息
*/ */
@Suppress("FunctionName") @Suppress("FunctionName")
private fun createToFriend( internal fun createToFriendImpl(
client: QQAndroidClient, client: QQAndroidClient,
toUin: Long, toUin: Long,
message: MessageChain, message: MessageChain,
...@@ -106,33 +85,10 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg. ...@@ -106,33 +85,10 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg.
} }
inline fun createToTemp(
client: QQAndroidClient,
member: Member,
message: MessageChain,
sourceCallback: (MessageSourceToTempImpl) -> Unit
): OutgoingPacket {
val source = MessageSourceToTempImpl(
internalId = Random.nextInt().absoluteValue,
sender = client.bot,
target = member,
time = currentTimeSeconds.toInt(),
sequenceId = client.atomicNextMessageSequenceId(),
originalMessage = message
)
sourceCallback(source)
return createToTemp(
client,
(member.group as GroupImpl).uin,
member.id,
message,
source)
}
/** /**
* 发送临时消息 * 发送临时消息
*/ */
private fun createToTemp( internal fun createToTempImpl(
client: QQAndroidClient, client: QQAndroidClient,
groupUin: Long, groupUin: Long,
toUin: Long, toUin: Long,
...@@ -158,37 +114,11 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg. ...@@ -158,37 +114,11 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg.
} }
inline fun createToGroup(
client: QQAndroidClient,
group: Group,
message: MessageChain,
isForward: Boolean,
sourceCallback: (MessageSourceToGroupImpl) -> Unit
): OutgoingPacket {
val source = MessageSourceToGroupImpl(
group,
internalId = Random.nextInt().absoluteValue,
sender = client.bot,
target = group,
time = currentTimeSeconds.toInt(),
originalMessage = message//,
// sourceMessage = message
)
sourceCallback(source)
return createToGroup(
client,
group.id,
message,
isForward,
source)
}
/** /**
* 发送群消息 * 发送群消息
*/ */
@Suppress("FunctionName") @Suppress("FunctionName")
private fun createToGroup( internal fun createToGroupImpl(
client: QQAndroidClient, client: QQAndroidClient,
groupCode: Long, groupCode: Long,
message: MessageChain, message: MessageChain,
...@@ -231,7 +161,91 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg. ...@@ -231,7 +161,91 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg.
Response.Failed( Response.Failed(
response.result, response.result,
response.errtype, response.errtype,
response.errmsg) response.errmsg
)
}
}
}
internal inline fun MessageSvcPbSendMsg.createToTemp(
client: QQAndroidClient,
member: Member,
message: MessageChain,
crossinline sourceCallback: (MessageSourceToTempImpl) -> Unit
): OutgoingPacket {
contract {
callsInPlace(sourceCallback, InvocationKind.EXACTLY_ONCE)
} }
val source = MessageSourceToTempImpl(
internalId = Random.nextInt().absoluteValue,
sender = client.bot,
target = member,
time = currentTimeSeconds.toInt(),
sequenceId = client.atomicNextMessageSequenceId(),
originalMessage = message
)
sourceCallback(source)
return createToTempImpl(
client,
(member.group as GroupImpl).uin,
member.id,
message,
source
)
}
internal inline fun MessageSvcPbSendMsg.createToFriend(
client: QQAndroidClient,
qq: Friend,
message: MessageChain,
crossinline sourceCallback: (MessageSourceToFriendImpl) -> Unit
): OutgoingPacket {
contract {
callsInPlace(sourceCallback, InvocationKind.EXACTLY_ONCE)
} }
val rand = Random.nextInt().absoluteValue
val source = MessageSourceToFriendImpl(
internalId = rand,
sender = client.bot,
target = qq,
time = currentTimeSeconds.toInt(),
sequenceId = client.nextFriendSeq(),
originalMessage = message
)
sourceCallback(source)
return createToFriendImpl(
client,
qq.id,
message,
source
)
}
internal inline fun MessageSvcPbSendMsg.createToGroup(
client: QQAndroidClient,
group: Group,
message: MessageChain,
isForward: Boolean,
crossinline sourceCallback: (MessageSourceToGroupImpl) -> Unit
): OutgoingPacket {
contract {
callsInPlace(sourceCallback, InvocationKind.EXACTLY_ONCE)
}
val source = MessageSourceToGroupImpl(
group,
internalId = Random.nextInt().absoluteValue,
sender = client.bot,
target = group,
time = currentTimeSeconds.toInt(),
originalMessage = message//,
// sourceMessage = message
)
sourceCallback(source)
return createToGroupImpl(
client,
group.id,
message,
isForward,
source
)
} }
\ No newline at end of file
...@@ -16,13 +16,11 @@ import kotlinx.coroutines.CoroutineScope ...@@ -16,13 +16,11 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.JavaFriendlyAPI import net.mamoe.mirai.JavaFriendlyAPI
import net.mamoe.mirai.event.events.BeforeImageUploadEvent import net.mamoe.mirai.event.events.*
import net.mamoe.mirai.event.events.EventCancelledException
import net.mamoe.mirai.event.events.ImageUploadEvent
import net.mamoe.mirai.event.events.MessageSendEvent.FriendMessageSendEvent
import net.mamoe.mirai.event.events.MessageSendEvent.GroupMessageSendEvent
import net.mamoe.mirai.message.MessageReceipt import net.mamoe.mirai.message.MessageReceipt
import net.mamoe.mirai.message.data.* import net.mamoe.mirai.message.data.*
import net.mamoe.mirai.message.quote
import net.mamoe.mirai.message.recall
import net.mamoe.mirai.recall import net.mamoe.mirai.recall
import net.mamoe.mirai.recallIn import net.mamoe.mirai.recallIn
import net.mamoe.mirai.utils.ExternalImage import net.mamoe.mirai.utils.ExternalImage
...@@ -57,8 +55,8 @@ abstract class Contact : ContactOrBot, CoroutineScope, ContactJavaFriendlyAPI { ...@@ -57,8 +55,8 @@ abstract class Contact : ContactOrBot, CoroutineScope, ContactJavaFriendlyAPI {
* *
* 单条消息最大可发送 4500 字符或 50 张图片. * 单条消息最大可发送 4500 字符或 50 张图片.
* *
* @see FriendMessageSendEvent 发送好友信息事件, cancellable * @see MessagePreSendEvent 发送消息前事件
* @see GroupMessageSendEvent 发送群消息事件. cancellable * @see MessagePostSendEvent 发送消息后事件
* *
* @throws EventCancelledException 当发送消息事件被取消时抛出 * @throws EventCancelledException 当发送消息事件被取消时抛出
* @throws BotIsBeingMutedException 发送群消息时若 [Bot] 被禁言抛出 * @throws BotIsBeingMutedException 发送群消息时若 [Bot] 被禁言抛出
...@@ -71,7 +69,7 @@ abstract class Contact : ContactOrBot, CoroutineScope, ContactJavaFriendlyAPI { ...@@ -71,7 +69,7 @@ abstract class Contact : ContactOrBot, CoroutineScope, ContactJavaFriendlyAPI {
abstract suspend fun sendMessage(message: Message): MessageReceipt<Contact> abstract suspend fun sendMessage(message: Message): MessageReceipt<Contact>
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "VIRTUAL_MEMBER_HIDDEN", "OVERRIDE_BY_INLINE") @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "VIRTUAL_MEMBER_HIDDEN", "OVERRIDE_BY_INLINE")
@kotlin.internal.InlineOnly // purely virtual @kotlin.internal.InlineOnly
@JvmSynthetic @JvmSynthetic
suspend inline fun sendMessage(message: String): MessageReceipt<Contact> { suspend inline fun sendMessage(message: String): MessageReceipt<Contact> {
return sendMessage(message.toMessage()) return sendMessage(message.toMessage())
......
...@@ -14,12 +14,14 @@ package net.mamoe.mirai.contact ...@@ -14,12 +14,14 @@ package net.mamoe.mirai.contact
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.event.events.EventCancelledException import net.mamoe.mirai.event.events.EventCancelledException
import net.mamoe.mirai.event.events.MessageSendEvent.FriendMessageSendEvent import net.mamoe.mirai.event.events.FriendMessagePostSendEvent
import net.mamoe.mirai.event.events.MessageSendEvent.GroupMessageSendEvent import net.mamoe.mirai.event.events.FriendMessagePreSendEvent
import net.mamoe.mirai.message.FriendMessageEvent import net.mamoe.mirai.message.FriendMessageEvent
import net.mamoe.mirai.message.MessageReceipt import net.mamoe.mirai.message.MessageReceipt
import net.mamoe.mirai.message.data.Message import net.mamoe.mirai.message.data.Message
import net.mamoe.mirai.message.data.isContentEmpty
import net.mamoe.mirai.message.data.toMessage import net.mamoe.mirai.message.data.toMessage
import net.mamoe.mirai.message.recall
import kotlin.jvm.JvmSynthetic import kotlin.jvm.JvmSynthetic
/** /**
...@@ -55,8 +57,8 @@ abstract class Friend : User(), CoroutineScope { ...@@ -55,8 +57,8 @@ abstract class Friend : User(), CoroutineScope {
* *
* 单条消息最大可发送 4500 字符或 50 张图片. * 单条消息最大可发送 4500 字符或 50 张图片.
* *
* @see FriendMessageSendEvent 发送好友信息事件, cancellable * @see FriendMessagePreSendEvent 发送消息前事件
* @see GroupMessageSendEvent 发送群消息事件. cancellable * @see FriendMessagePostSendEvent 发送消息后事件
* *
* @throws EventCancelledException 当发送消息事件被取消时抛出 * @throws EventCancelledException 当发送消息事件被取消时抛出
* @throws BotIsBeingMutedException 发送群消息时若 [Bot] 被禁言抛出 * @throws BotIsBeingMutedException 发送群消息时若 [Bot] 被禁言抛出
...@@ -69,7 +71,7 @@ abstract class Friend : User(), CoroutineScope { ...@@ -69,7 +71,7 @@ abstract class Friend : User(), CoroutineScope {
abstract override suspend fun sendMessage(message: Message): MessageReceipt<Friend> abstract override suspend fun sendMessage(message: Message): MessageReceipt<Friend>
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "VIRTUAL_MEMBER_HIDDEN", "OVERRIDE_BY_INLINE") @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "VIRTUAL_MEMBER_HIDDEN", "OVERRIDE_BY_INLINE")
@kotlin.internal.InlineOnly // purely virtual @kotlin.internal.InlineOnly
@JvmSynthetic @JvmSynthetic
suspend inline fun sendMessage(message: String): MessageReceipt<Friend> { suspend inline fun sendMessage(message: String): MessageReceipt<Friend> {
return sendMessage(message.toMessage()) return sendMessage(message.toMessage())
......
...@@ -17,12 +17,12 @@ import net.mamoe.mirai.JavaFriendlyAPI ...@@ -17,12 +17,12 @@ import net.mamoe.mirai.JavaFriendlyAPI
import net.mamoe.mirai.LowLevelAPI import net.mamoe.mirai.LowLevelAPI
import net.mamoe.mirai.data.MemberInfo import net.mamoe.mirai.data.MemberInfo
import net.mamoe.mirai.event.events.* import net.mamoe.mirai.event.events.*
import net.mamoe.mirai.event.events.MessageSendEvent.FriendMessageSendEvent
import net.mamoe.mirai.event.events.MessageSendEvent.GroupMessageSendEvent
import net.mamoe.mirai.message.MessageReceipt import net.mamoe.mirai.message.MessageReceipt
import net.mamoe.mirai.message.data.Image import net.mamoe.mirai.message.data.Image
import net.mamoe.mirai.message.data.Message import net.mamoe.mirai.message.data.Message
import net.mamoe.mirai.message.data.isContentEmpty
import net.mamoe.mirai.message.data.toMessage import net.mamoe.mirai.message.data.toMessage
import net.mamoe.mirai.message.recall
import net.mamoe.mirai.utils.* import net.mamoe.mirai.utils.*
import net.mamoe.mirai.utils.internal.runBlocking import net.mamoe.mirai.utils.internal.runBlocking
import kotlin.jvm.JvmName import kotlin.jvm.JvmName
...@@ -137,8 +137,8 @@ abstract class Group : Contact(), CoroutineScope { ...@@ -137,8 +137,8 @@ abstract class Group : Contact(), CoroutineScope {
* *
* 单条消息最大可发送 4500 字符或 50 张图片. * 单条消息最大可发送 4500 字符或 50 张图片.
* *
* @see FriendMessageSendEvent 发送好友信息事件, cancellable * @see GroupMessagePreSendEvent 发送消息前事件
* @see GroupMessageSendEvent 发送群消息事件. cancellable * @see GroupMessagePostSendEvent 发送消息后事件
* *
* @throws EventCancelledException 当发送消息事件被取消时抛出 * @throws EventCancelledException 当发送消息事件被取消时抛出
* @throws BotIsBeingMutedException 发送群消息时若 [Bot] 被禁言抛出 * @throws BotIsBeingMutedException 发送群消息时若 [Bot] 被禁言抛出
...@@ -154,7 +154,7 @@ abstract class Group : Contact(), CoroutineScope { ...@@ -154,7 +154,7 @@ abstract class Group : Contact(), CoroutineScope {
* @see sendMessage * @see sendMessage
*/ */
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "VIRTUAL_MEMBER_HIDDEN", "OVERRIDE_BY_INLINE") @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "VIRTUAL_MEMBER_HIDDEN", "OVERRIDE_BY_INLINE")
@kotlin.internal.InlineOnly // purely virtual @kotlin.internal.InlineOnly
@JvmSynthetic @JvmSynthetic
suspend inline fun sendMessage(message: String): MessageReceipt<Group> { suspend inline fun sendMessage(message: String): MessageReceipt<Group> {
return sendMessage(message.toMessage()) return sendMessage(message.toMessage())
......
...@@ -17,7 +17,12 @@ import net.mamoe.mirai.event.events.* ...@@ -17,7 +17,12 @@ import net.mamoe.mirai.event.events.*
import net.mamoe.mirai.getFriendOrNull import net.mamoe.mirai.getFriendOrNull
import net.mamoe.mirai.message.MessageReceipt import net.mamoe.mirai.message.MessageReceipt
import net.mamoe.mirai.message.data.Message import net.mamoe.mirai.message.data.Message
import net.mamoe.mirai.message.data.isContentEmpty
import net.mamoe.mirai.message.data.toMessage import net.mamoe.mirai.message.data.toMessage
import net.mamoe.mirai.message.recall
import net.mamoe.mirai.utils.hoursToSeconds
import net.mamoe.mirai.utils.daysToSeconds
import net.mamoe.mirai.utils.minutesToSeconds
import net.mamoe.mirai.utils.WeakRefProperty import net.mamoe.mirai.utils.WeakRefProperty
import kotlin.jvm.JvmSynthetic import kotlin.jvm.JvmSynthetic
import kotlin.time.Duration import kotlin.time.Duration
...@@ -139,8 +144,11 @@ abstract class Member : MemberJavaFriendlyAPI, User() { ...@@ -139,8 +144,11 @@ abstract class Member : MemberJavaFriendlyAPI, User() {
* *
* 单条消息最大可发送 4500 字符或 50 张图片. * 单条消息最大可发送 4500 字符或 50 张图片.
* *
* @see MessageSendEvent.FriendMessageSendEvent 发送好友信息事件, cancellable * @see FriendMessagePreSendEvent 当此成员是好友时发送消息前事件
* @see MessageSendEvent.GroupMessageSendEvent 发送群消息事件. cancellable * @see FriendMessagePostSendEvent 当此成员是好友时发送消息后事件
*
* @see TempMessagePreSendEvent 当此成员不是好友时发送消息前事件
* @see TempMessagePostSendEvent 当此成员不是好友时发送消息后事件
* *
* @throws EventCancelledException 当发送消息事件被取消时抛出 * @throws EventCancelledException 当发送消息事件被取消时抛出
* @throws BotIsBeingMutedException 发送群消息时若 [Bot] 被禁言抛出 * @throws BotIsBeingMutedException 发送群消息时若 [Bot] 被禁言抛出
...@@ -156,7 +164,7 @@ abstract class Member : MemberJavaFriendlyAPI, User() { ...@@ -156,7 +164,7 @@ abstract class Member : MemberJavaFriendlyAPI, User() {
* @see sendMessage * @see sendMessage
*/ */
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "VIRTUAL_MEMBER_HIDDEN", "OVERRIDE_BY_INLINE") @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "VIRTUAL_MEMBER_HIDDEN", "OVERRIDE_BY_INLINE")
@kotlin.internal.InlineOnly // purely virtual @kotlin.internal.InlineOnly
@JvmSynthetic @JvmSynthetic
suspend inline fun sendMessage(message: String): MessageReceipt<Member> { suspend inline fun sendMessage(message: String): MessageReceipt<Member> {
return sendMessage(message.toMessage()) return sendMessage(message.toMessage())
......
...@@ -13,11 +13,7 @@ package net.mamoe.mirai.contact ...@@ -13,11 +13,7 @@ package net.mamoe.mirai.contact
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.event.events.BeforeImageUploadEvent import net.mamoe.mirai.event.events.*
import net.mamoe.mirai.event.events.EventCancelledException
import net.mamoe.mirai.event.events.ImageUploadEvent
import net.mamoe.mirai.event.events.MessageSendEvent.FriendMessageSendEvent
import net.mamoe.mirai.event.events.MessageSendEvent.GroupMessageSendEvent
import net.mamoe.mirai.message.MessageReceipt import net.mamoe.mirai.message.MessageReceipt
import net.mamoe.mirai.message.data.Image import net.mamoe.mirai.message.data.Image
import net.mamoe.mirai.message.data.Message import net.mamoe.mirai.message.data.Message
...@@ -58,8 +54,8 @@ abstract class User : Contact(), CoroutineScope { ...@@ -58,8 +54,8 @@ abstract class User : Contact(), CoroutineScope {
* *
* 单条消息最大可发送 4500 字符或 50 张图片. * 单条消息最大可发送 4500 字符或 50 张图片.
* *
* @see FriendMessageSendEvent 发送好友信息事件, cancellable * @see UserMessagePreSendEvent 发送消息前事件
* @see GroupMessageSendEvent 发送群消息事件. cancellable * @see UserMessagePostSendEvent 发送消息后事件
* *
* @throws EventCancelledException 当发送消息事件被取消时抛出 * @throws EventCancelledException 当发送消息事件被取消时抛出
* @throws BotIsBeingMutedException 发送群消息时若 [Bot] 被禁言抛出 * @throws BotIsBeingMutedException 发送群消息时若 [Bot] 被禁言抛出
...@@ -75,7 +71,7 @@ abstract class User : Contact(), CoroutineScope { ...@@ -75,7 +71,7 @@ abstract class User : Contact(), CoroutineScope {
* @see sendMessage * @see sendMessage
*/ */
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "VIRTUAL_MEMBER_HIDDEN", "OVERRIDE_BY_INLINE") @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "VIRTUAL_MEMBER_HIDDEN", "OVERRIDE_BY_INLINE")
@kotlin.internal.InlineOnly // purely virtual @kotlin.internal.InlineOnly
@JvmSynthetic @JvmSynthetic
suspend inline fun sendMessage(message: String): MessageReceipt<User> { suspend inline fun sendMessage(message: String): MessageReceipt<User> {
return sendMessage(message.toMessage()) return sendMessage(message.toMessage())
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment