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
import net.mamoe.mirai.message.MessageReceipt
import net.mamoe.mirai.message.data.Image
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.qqandroid.QQAndroidBot
import net.mamoe.mirai.qqandroid.network.highway.postImage
......@@ -87,7 +88,11 @@ internal class FriendImpl(
@Suppress("DuplicatedCode")
override suspend fun sendMessage(message: Message): MessageReceipt<Friend> {
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)
}
}
......@@ -101,65 +106,64 @@ internal class FriendImpl(
if (BeforeImageUploadEvent(this, image).broadcast().isCancelled) {
throw EventCancelledException("cancelled by BeforeImageUploadEvent.ToGroup")
}
bot.network.run {
val response = LongConn.OffPicUp(
val response = bot.network.run {
LongConn.OffPicUp(
bot.client, Cmd0x352.TryUpImgReq(
srcUin = bot.id.toInt(),
dstUin = id.toInt(),
fileId = 0,
fileMd5 = @Suppress("INVISIBLE_MEMBER") image.md5,
fileSize = @Suppress("INVISIBLE_MEMBER")
image.input.size.toInt(),
fileName = @Suppress("INVISIBLE_MEMBER") image.md5.toUHexString("") + "." + ExternalImage.defaultFormatName,
fileMd5 = image.md5,
fileSize = image.input.size.toInt(),
fileName = image.md5.toUHexString("") + "." + ExternalImage.defaultFormatName,
imgOriginal = 1
)
).sendAndExpect<LongConn.OffPicUp.Response>()
}
@Suppress("UNCHECKED_CAST", "DEPRECATION", "INVISIBLE_MEMBER")
return when (response) {
is LongConn.OffPicUp.Response.FileExists -> net.mamoe.mirai.message.data.OfflineFriendImage(response.resourceId)
.also {
ImageUploadEvent.Succeed(this@FriendImpl, image, it).broadcast()
}
is LongConn.OffPicUp.Response.RequireUpload -> {
bot.network.logger.verbose {
"[Http] Uploading friend image, size=${image.input.size.sizeToString()}"
}
@Suppress("UNCHECKED_CAST", "DEPRECATION")
when (response) {
is LongConn.OffPicUp.Response.FileExists -> OfflineFriendImage(response.resourceId)
.also {
ImageUploadEvent.Succeed(this@FriendImpl, image, it).broadcast()
}
is LongConn.OffPicUp.Response.RequireUpload -> {
bot.network.logger.verbose {
"[Http] Uploading friend image, size=${image.input.size.sizeToString()}"
}
val time = measureTime {
MiraiPlatformUtils.Http.postImage(
"0x6ff0070",
bot.id,
null,
imageInput = image.input,
uKeyHex = response.uKey.toUHexString("")
)
}
val time = measureTime {
MiraiPlatformUtils.Http.postImage(
"0x6ff0070",
bot.id,
null,
imageInput = image.input,
uKeyHex = response.uKey.toUHexString("")
)
}
bot.network.logger.verbose {
"[Http] Uploading friend image: succeed at ${(image.input.size.toDouble() / 1024 / time.inSeconds).roundToInt()} KiB/s"
}
bot.network.logger.verbose {
"[Http] Uploading friend image: succeed at ${(image.input.size.toDouble() / 1024 / time.inSeconds).roundToInt()} KiB/s"
}
/*
HighwayHelper.uploadImageToServers(
bot,
response.serverIp.zip(response.serverPort),
response.uKey,
image,
kind = "friend",
commandId = 1
)*/
// 为什么不能 ??
/*
HighwayHelper.uploadImageToServers(
bot,
response.serverIp.zip(response.serverPort),
response.uKey,
image,
kind = "friend",
commandId = 1
)*/
// 为什么不能 ??
return net.mamoe.mirai.message.data.OfflineFriendImage(response.resourceId).also {
ImageUploadEvent.Succeed(this@FriendImpl, image, it).broadcast()
}
}
is LongConn.OffPicUp.Response.Failed -> {
ImageUploadEvent.Failed(this@FriendImpl, image, -1, response.message).broadcast()
error(response.message)
OfflineFriendImage(response.resourceId).also {
ImageUploadEvent.Succeed(this@FriendImpl, image, it).broadcast()
}
}
is LongConn.OffPicUp.Response.Failed -> {
ImageUploadEvent.Failed(this@FriendImpl, image, -1, response.message).broadcast()
error(response.message)
}
}
} finally {
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
......
......@@ -22,7 +22,6 @@ import net.mamoe.mirai.data.GroupInfo
import net.mamoe.mirai.data.MemberInfo
import net.mamoe.mirai.event.broadcast
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.data.*
import net.mamoe.mirai.qqandroid.QQAndroidBot
......@@ -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.image.ImgStore
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.utils.estimateLength
import net.mamoe.mirai.utils.*
......@@ -304,94 +304,92 @@ internal class GroupImpl(
check(message.nodeList.size < 200) {
throw MessageTooLargeException(
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)
}
val msg: MessageChain
if (message !is LongMessage && message !is ForwardMessageInternal) {
val event = GroupMessageSendEvent(this, message.asMessageChain()).broadcast()
if (event.isCancelled) {
throw EventCancelledException("cancelled by GroupMessageSendEvent")
}
val msg: MessageChain = if (message !is LongMessage && message !is ForwardMessageInternal) {
val chain = kotlin.runCatching {
GroupMessagePreSendEvent(this, message).broadcast()
}.onSuccess {
check(!it.isCancelled) {
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 // 通过下方逻辑短路延迟计算
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(
this,
message,
event.message,
"message(${event.message.joinToString(
"",
limit = 10
)}) is too large. Allow up to 50 images or 5000 chars"
this, message, chain,
"message(${chain.joinToString("", limit = 10)}) is too large. Allow up to 50 images or 5000 chars"
)
}
if (length > 702 || imageCnt > 2) {
return bot.lowLevelSendGroupLongOrForwardMessage(this.id,
listOf(ForwardMessage.Node(
senderId = bot.id,
time = currentTimeSeconds.toInt(),
message = event.message,
senderName = bot.nick)
return bot.lowLevelSendGroupLongOrForwardMessage(
this.id,
listOf(
ForwardMessage.Node(
senderId = bot.id,
time = currentTimeSeconds.toInt(),
message = chain,
senderName = bot.nick
)
),
true, null)
true, null
)
}
chain
} else message.asMessageChain()
msg = event.message
} else msg = message.asMessageChain()
msg.firstIsInstanceOrNull<QuoteReply>()?.source?.ensureSequenceIdAvailable()
lateinit var source: MessageSourceToGroupImpl
bot.network.run {
val response: MessageSvcPbSendMsg.Response = MessageSvcPbSendMsg.createToGroup(
val result = bot.network.runCatching {
val source: MessageSourceToGroupImpl
MessageSvcPbSendMsg.createToGroup(
bot.client,
this@GroupImpl,
msg,
isForward
) {
source = it
}.sendAndExpect()
if (response is MessageSvcPbSendMsg.Response.Failed) {
when (response.resultType) {
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")
}.sendAndExpect<MessageSvcPbSendMsg.Response>().let {
check(it is MessageSvcPbSendMsg.Response.SUCCESS) {
"Send temp message failed: $it"
}
}
}
try {
source.ensureSequenceIdAvailable()
} catch (e: Exception) {
bot.network.logger.warning {
"Timeout awaiting sequenceId for group message(${message.contentToString()
.take(10)}). Some features may not work properly"
try {
source.ensureSequenceIdAvailable()
} catch (e: Exception) {
bot.network.logger.warning {
"Timeout awaiting sequenceId for group message(${message.contentToString()
.take(10)}). Some features may not work properly"
}
bot.network.logger.warning(e)
}
bot.network.logger.warning(e)
MessageReceipt(source, this@GroupImpl, botAsMember)
}
return MessageReceipt(source, this, botAsMember)
result.fold(
onSuccess = {
GroupMessagePostSendEvent(this, msg, null, it)
},
onFailure = {
GroupMessagePostSendEvent(this, msg, it, null)
}
).broadcast()
return result.getOrThrow()
}
@Suppress("DEPRECATION")
......
......@@ -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.packet.chat.TroopManagement
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.currentTimeSeconds
import net.mamoe.mirai.utils.getValue
......@@ -54,34 +55,59 @@ internal class MemberImpl constructor(
override val id: Long = qq.id
override val nick: String = qq.nick
@Suppress("UNCHECKED_CAST")
@JvmSynthetic
override suspend fun sendMessage(message: Message): MessageReceipt<Member> {
require(message.isContentNotEmpty()) { "message is empty" }
return (this.asFriendOrNull()?.sendMessageImpl(this, message) ?: sendMessageImpl(message))
.also { logMessageSent(message) }
val asFriend = this.asFriendOrNull()
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> {
val event = MessageSendEvent.TempMessageSendEvent(this, message.asMessageChain()).broadcast()
if (event.isCancelled) {
throw EventCancelledException("cancelled by TempMessageSendEvent")
}
event.message.firstIsInstanceOrNull<QuoteReply>()?.source?.ensureSequenceIdAvailable()
val chain = kotlin.runCatching {
TempMessagePreSendEvent(this, message).broadcast()
}.onSuccess {
check(!it.isCancelled) {
throw EventCancelledException("cancelled by TempMessagePreSendEvent")
}
}.getOrElse {
throw EventCancelledException("exception thrown when broadcasting TempMessagePreSendEvent", it)
}.message.asMessageChain()
lateinit var source: MessageSourceToTempImpl
bot.network.run {
check(
MessageSvcPbSendMsg.createToTemp(
bot.client,
this@MemberImpl,
message.asMessageChain()
) {
source = it
}.sendAndExpect<MessageSvcPbSendMsg.Response>() is MessageSvcPbSendMsg.Response.SUCCESS
) { "send message failed" }
chain.firstIsInstanceOrNull<QuoteReply>()?.source?.ensureSequenceIdAvailable()
val result = bot.network.runCatching {
val source: MessageSourceToTempImpl
MessageSvcPbSendMsg.createToTemp(
bot.client,
this@MemberImpl,
chain
) {
source = it
}.sendAndExpect<MessageSvcPbSendMsg.Response>().let {
check(it is MessageSvcPbSendMsg.Response.SUCCESS) {
"Send temp message failed: $it"
}
}
MessageReceipt(source, this@MemberImpl, null)
}
return MessageReceipt(source, this, null)
result.fold(
onSuccess = {
TempMessagePostSendEvent(this, chain, null, it)
},
onFailure = {
TempMessagePostSendEvent(this, chain, it, null)
}
).broadcast()
return result.getOrThrow()
}
@JvmSynthetic
......
......@@ -12,40 +12,72 @@ package net.mamoe.mirai.qqandroid.contact
import net.mamoe.mirai.contact.Contact
import net.mamoe.mirai.contact.Friend
import net.mamoe.mirai.contact.User
import net.mamoe.mirai.event.broadcast
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.data.Message
import net.mamoe.mirai.message.data.QuoteReply
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.message.MessageSourceToFriendImpl
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.createToFriend
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> {
val event = MessageSendEvent.FriendMessageSendEvent(this, message.asMessageChain()).broadcast()
if (event.isCancelled) {
throw EventCancelledException("cancelled by FriendMessageSendEvent")
}
event.message.firstIsInstanceOrNull<QuoteReply>()?.source?.ensureSequenceIdAvailable()
lateinit var source: MessageSourceToFriendImpl
internal suspend fun <T : User> Friend.sendMessageImpl(
message: Message,
friendReceiptConstructor: (MessageSourceToFriendImpl) -> MessageReceipt<Friend>,
tReceiptConstructor: (MessageSourceToFriendImpl) -> MessageReceipt<T>
): MessageReceipt<T> {
contract { callsInPlace(friendReceiptConstructor, InvocationKind.EXACTLY_ONCE) }
val bot = bot.asQQAndroidBot()
bot.network.run {
check(
MessageSvcPbSendMsg.createToFriend(
bot.asQQAndroidBot().client,
this@sendMessageImpl,
event.message
) {
source = it
}.sendAndExpect<MessageSvcPbSendMsg.Response>() is MessageSvcPbSendMsg.Response.SUCCESS
) { "send message failed" }
val chain = kotlin.runCatching {
FriendMessagePreSendEvent(this, message).broadcast()
}.onSuccess {
check(!it.isCancelled) {
throw EventCancelledException("cancelled by FriendMessagePreSendEvent")
}
}.getOrElse {
throw EventCancelledException("exception thrown when broadcasting FriendMessagePreSendEvent", it)
}.message.asMessageChain()
chain.firstIsInstanceOrNull<QuoteReply>()?.source?.ensureSequenceIdAvailable()
lateinit var source: MessageSourceToFriendImpl
val result = bot.network.runCatching {
MessageSvcPbSendMsg.createToFriend(
bot.client,
this@sendMessageImpl,
chain
) {
source = it
}.sendAndExpect<MessageSvcPbSendMsg.Response>().let {
check(it is MessageSvcPbSendMsg.Response.SUCCESS) {
"Send temp message failed: $it"
}
}
friendReceiptConstructor(source)
}
return MessageReceipt(source, generic, null)
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) {
......
......@@ -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.writeProtoBuf
import net.mamoe.mirai.utils.currentTimeSeconds
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
import kotlin.math.absoluteValue
import kotlin.random.Random
......@@ -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")
private fun createToFriend(
internal fun createToFriendImpl(
client: QQAndroidClient,
toUin: Long,
message: MessageChain,
......@@ -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,
groupUin: Long,
toUin: Long,
......@@ -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")
private fun createToGroup(
internal fun createToGroupImpl(
client: QQAndroidClient,
groupCode: Long,
message: MessageChain,
......@@ -231,7 +161,91 @@ internal object MessageSvcPbSendMsg : OutgoingPacketFactory<MessageSvcPbSendMsg.
Response.Failed(
response.result,
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
import kotlinx.coroutines.Job
import net.mamoe.mirai.Bot
import net.mamoe.mirai.JavaFriendlyAPI
import net.mamoe.mirai.event.events.BeforeImageUploadEvent
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.event.events.*
import net.mamoe.mirai.message.MessageReceipt
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.recallIn
import net.mamoe.mirai.utils.ExternalImage
......@@ -57,8 +55,8 @@ abstract class Contact : ContactOrBot, CoroutineScope, ContactJavaFriendlyAPI {
*
* 单条消息最大可发送 4500 字符或 50 张图片.
*
* @see FriendMessageSendEvent 发送好友信息事件, cancellable
* @see GroupMessageSendEvent 发送群消息事件. cancellable
* @see MessagePreSendEvent 发送消息前事件
* @see MessagePostSendEvent 发送消息后事件
*
* @throws EventCancelledException 当发送消息事件被取消时抛出
* @throws BotIsBeingMutedException 发送群消息时若 [Bot] 被禁言抛出
......@@ -71,7 +69,7 @@ abstract class Contact : ContactOrBot, CoroutineScope, ContactJavaFriendlyAPI {
abstract suspend fun sendMessage(message: Message): MessageReceipt<Contact>
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "VIRTUAL_MEMBER_HIDDEN", "OVERRIDE_BY_INLINE")
@kotlin.internal.InlineOnly // purely virtual
@kotlin.internal.InlineOnly
@JvmSynthetic
suspend inline fun sendMessage(message: String): MessageReceipt<Contact> {
return sendMessage(message.toMessage())
......
......@@ -14,12 +14,14 @@ package net.mamoe.mirai.contact
import kotlinx.coroutines.CoroutineScope
import net.mamoe.mirai.Bot
import net.mamoe.mirai.event.events.EventCancelledException
import net.mamoe.mirai.event.events.MessageSendEvent.FriendMessageSendEvent
import net.mamoe.mirai.event.events.MessageSendEvent.GroupMessageSendEvent
import net.mamoe.mirai.event.events.FriendMessagePostSendEvent
import net.mamoe.mirai.event.events.FriendMessagePreSendEvent
import net.mamoe.mirai.message.FriendMessageEvent
import net.mamoe.mirai.message.MessageReceipt
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.recall
import kotlin.jvm.JvmSynthetic
/**
......@@ -55,8 +57,8 @@ abstract class Friend : User(), CoroutineScope {
*
* 单条消息最大可发送 4500 字符或 50 张图片.
*
* @see FriendMessageSendEvent 发送好友信息事件, cancellable
* @see GroupMessageSendEvent 发送群消息事件. cancellable
* @see FriendMessagePreSendEvent 发送消息前事件
* @see FriendMessagePostSendEvent 发送消息后事件
*
* @throws EventCancelledException 当发送消息事件被取消时抛出
* @throws BotIsBeingMutedException 发送群消息时若 [Bot] 被禁言抛出
......@@ -69,7 +71,7 @@ abstract class Friend : User(), CoroutineScope {
abstract override suspend fun sendMessage(message: Message): MessageReceipt<Friend>
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "VIRTUAL_MEMBER_HIDDEN", "OVERRIDE_BY_INLINE")
@kotlin.internal.InlineOnly // purely virtual
@kotlin.internal.InlineOnly
@JvmSynthetic
suspend inline fun sendMessage(message: String): MessageReceipt<Friend> {
return sendMessage(message.toMessage())
......
......@@ -17,12 +17,12 @@ import net.mamoe.mirai.JavaFriendlyAPI
import net.mamoe.mirai.LowLevelAPI
import net.mamoe.mirai.data.MemberInfo
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.data.Image
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.recall
import net.mamoe.mirai.utils.*
import net.mamoe.mirai.utils.internal.runBlocking
import kotlin.jvm.JvmName
......@@ -137,8 +137,8 @@ abstract class Group : Contact(), CoroutineScope {
*
* 单条消息最大可发送 4500 字符或 50 张图片.
*
* @see FriendMessageSendEvent 发送好友信息事件, cancellable
* @see GroupMessageSendEvent 发送群消息事件. cancellable
* @see GroupMessagePreSendEvent 发送消息前事件
* @see GroupMessagePostSendEvent 发送消息后事件
*
* @throws EventCancelledException 当发送消息事件被取消时抛出
* @throws BotIsBeingMutedException 发送群消息时若 [Bot] 被禁言抛出
......@@ -154,7 +154,7 @@ abstract class Group : Contact(), CoroutineScope {
* @see sendMessage
*/
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "VIRTUAL_MEMBER_HIDDEN", "OVERRIDE_BY_INLINE")
@kotlin.internal.InlineOnly // purely virtual
@kotlin.internal.InlineOnly
@JvmSynthetic
suspend inline fun sendMessage(message: String): MessageReceipt<Group> {
return sendMessage(message.toMessage())
......
......@@ -17,7 +17,12 @@ import net.mamoe.mirai.event.events.*
import net.mamoe.mirai.getFriendOrNull
import net.mamoe.mirai.message.MessageReceipt
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.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 kotlin.jvm.JvmSynthetic
import kotlin.time.Duration
......@@ -139,8 +144,11 @@ abstract class Member : MemberJavaFriendlyAPI, User() {
*
* 单条消息最大可发送 4500 字符或 50 张图片.
*
* @see MessageSendEvent.FriendMessageSendEvent 发送好友信息事件, cancellable
* @see MessageSendEvent.GroupMessageSendEvent 发送群消息事件. cancellable
* @see FriendMessagePreSendEvent 当此成员是好友时发送消息前事件
* @see FriendMessagePostSendEvent 当此成员是好友时发送消息后事件
*
* @see TempMessagePreSendEvent 当此成员不是好友时发送消息前事件
* @see TempMessagePostSendEvent 当此成员不是好友时发送消息后事件
*
* @throws EventCancelledException 当发送消息事件被取消时抛出
* @throws BotIsBeingMutedException 发送群消息时若 [Bot] 被禁言抛出
......@@ -156,7 +164,7 @@ abstract class Member : MemberJavaFriendlyAPI, User() {
* @see sendMessage
*/
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "VIRTUAL_MEMBER_HIDDEN", "OVERRIDE_BY_INLINE")
@kotlin.internal.InlineOnly // purely virtual
@kotlin.internal.InlineOnly
@JvmSynthetic
suspend inline fun sendMessage(message: String): MessageReceipt<Member> {
return sendMessage(message.toMessage())
......
......@@ -13,11 +13,7 @@ package net.mamoe.mirai.contact
import kotlinx.coroutines.CoroutineScope
import net.mamoe.mirai.Bot
import net.mamoe.mirai.event.events.BeforeImageUploadEvent
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.event.events.*
import net.mamoe.mirai.message.MessageReceipt
import net.mamoe.mirai.message.data.Image
import net.mamoe.mirai.message.data.Message
......@@ -58,8 +54,8 @@ abstract class User : Contact(), CoroutineScope {
*
* 单条消息最大可发送 4500 字符或 50 张图片.
*
* @see FriendMessageSendEvent 发送好友信息事件, cancellable
* @see GroupMessageSendEvent 发送群消息事件. cancellable
* @see UserMessagePreSendEvent 发送消息前事件
* @see UserMessagePostSendEvent 发送消息后事件
*
* @throws EventCancelledException 当发送消息事件被取消时抛出
* @throws BotIsBeingMutedException 发送群消息时若 [Bot] 被禁言抛出
......@@ -75,7 +71,7 @@ abstract class User : Contact(), CoroutineScope {
* @see sendMessage
*/
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "VIRTUAL_MEMBER_HIDDEN", "OVERRIDE_BY_INLINE")
@kotlin.internal.InlineOnly // purely virtual
@kotlin.internal.InlineOnly
@JvmSynthetic
suspend inline fun sendMessage(message: String): MessageReceipt<User> {
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