Send temp messages as friend messages if a target Member is also a friend

This commit is contained in:
Him188 2020-04-23 18:36:04 +08:00
parent 5b2ae6e9ad
commit 8e8f91bbee
4 changed files with 47 additions and 108 deletions

View File

@ -31,14 +31,14 @@ import net.mamoe.mirai.qqandroid.network.protocol.data.proto.Cmd0x352
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.image.LongConn
import net.mamoe.mirai.qqandroid.utils.MiraiPlatformUtils
import net.mamoe.mirai.qqandroid.utils.toUHexString
import net.mamoe.mirai.utils.ExternalImage
import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.getValue
import net.mamoe.mirai.utils.unsafeWeakRef
import net.mamoe.mirai.utils.*
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
import kotlin.coroutines.CoroutineContext
import kotlin.jvm.JvmSynthetic
import kotlin.math.roundToInt
import kotlin.time.ExperimentalTime
import kotlin.time.measureTime
internal inline class FriendInfoImpl(
private val jceFriendInfo: net.mamoe.mirai.qqandroid.network.protocol.data.jce.FriendInfo
@ -72,13 +72,13 @@ internal class FriendImpl(
@JvmSynthetic
@Suppress("DuplicatedCode")
override suspend fun sendMessage(message: Message): MessageReceipt<Friend> {
return sendMessageImpl(message).also {
return sendMessageImpl(this, message).also {
logMessageSent(message)
}
}
@JvmSynthetic
@OptIn(MiraiInternalAPI::class)
@OptIn(MiraiInternalAPI::class, ExperimentalStdlibApi::class, ExperimentalTime::class)
override suspend fun uploadImage(image: ExternalImage): OfflineFriendImage = try {
if (BeforeImageUploadEvent(this, image).broadcast().isCancelled) {
throw EventCancelledException("cancelled by BeforeImageUploadEvent.ToGroup")
@ -102,24 +102,34 @@ internal class FriendImpl(
ImageUploadEvent.Succeed(this@FriendImpl, image, it).broadcast()
}
is LongConn.OffPicUp.Response.RequireUpload -> {
MiraiPlatformUtils.Http.postImage(
"0x6ff0070",
bot.id,
null,
imageInput = image.input,
inputSize = image.inputSize,
uKeyHex = response.uKey.toUHexString("")
)
//HighwayHelper.uploadImage(
// client = bot.client,
// serverIp = response.serverIp[0].toIpV4AddressString(),
// serverPort = response.serverPort[0],
// imageInput = image.input,
// inputSize = image.inputSize.toInt(),
// fileMd5 = image.md5,
// uKey = response.uKey,
// commandId = 1
//)
bot.network.logger.verbose {
"[Http] Uploading friend image, size=${image.inputSize / 1024} KiB"
}
val time = measureTime {
MiraiPlatformUtils.Http.postImage(
"0x6ff0070",
bot.id,
null,
imageInput = image.input,
inputSize = image.inputSize,
uKeyHex = response.uKey.toUHexString("")
)
}
bot.network.logger.verbose {
"[Http] Uploading friend image: succeed at ${(image.inputSize.toDouble() / 1024 / time.inSeconds).roundToInt()} KiB/s"
}
/*
HighwayHelper.uploadImageToServers(
bot,
response.serverIp.zip(response.serverPort),
response.uKey,
image,
kind = "friend",
commandId = 1
)*/
// 为什么不能 ??
return OfflineFriendImage(response.resourceId).also {

View File

@ -13,7 +13,6 @@
package net.mamoe.mirai.qqandroid.contact
import kotlinx.coroutines.launch
import kotlinx.coroutines.withTimeoutOrNull
import kotlinx.io.core.Closeable
import net.mamoe.mirai.LowLevelAPI
import net.mamoe.mirai.contact.*
@ -33,17 +32,13 @@ 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.MessageSvc
import net.mamoe.mirai.qqandroid.network.protocol.packet.list.ProfileService
import net.mamoe.mirai.qqandroid.utils.addSuppressedMirai
import net.mamoe.mirai.qqandroid.utils.estimateLength
import net.mamoe.mirai.qqandroid.utils.toIpV4AddressString
import net.mamoe.mirai.utils.*
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
import kotlin.coroutines.CoroutineContext
import kotlin.jvm.JvmSynthetic
import kotlin.math.roundToInt
import kotlin.time.ExperimentalTime
import kotlin.time.measureTime
@OptIn(ExperimentalContracts::class)
internal fun GroupImpl.Companion.checkIsInstance(instance: Group) {
@ -412,86 +407,21 @@ internal class GroupImpl(
}
is ImgStore.GroupPicUp.Response.FileExists -> {
val resourceId = image.calculateImageResourceId()
// return NotOnlineImageFromFile(
// resourceId = resourceId,
// md5 = response.fileInfo.fileMd5,
// filepath = resourceId,
// fileLength = response.fileInfo.fileSize.toInt(),
// height = response.fileInfo.fileHeight,
// width = response.fileInfo.fileWidth,
// imageType = response.fileInfo.fileType,
// fileId = response.fileId.toInt()
// )
// println("NMSL")
return OfflineGroupImage(imageId = resourceId)
.also { ImageUploadEvent.Succeed(this@GroupImpl, image, it).broadcast() }
}
is ImgStore.GroupPicUp.Response.RequireUpload -> {
// 每 10KB 等 1 秒, 最少等待 5 秒
var exception: Throwable? = null
val success = response.uploadIpList.zip(response.uploadPortList).any { (ip, port) ->
kotlin.runCatching {
withTimeoutOrNull((image.inputSize * 1000 / 1024 / 10).coerceAtLeast(5000)) {
bot.network.logger.verbose { "[Highway] Uploading group image to ${ip.toIpV4AddressString()}:$port, size=${image.inputSize / 1024} KiB" }
val time = measureTime {
HighwayHelper.uploadImage(
client = bot.client,
serverIp = ip.toIpV4AddressString(),
serverPort = port,
imageInput = image.input,
inputSize = image.inputSize.toInt(),
fileMd5 = image.md5,
ticket = response.uKey,
commandId = 2
)
}
bot.network.logger.verbose { "[Highway] Uploading group image: succeed at ${(image.inputSize.toDouble() / 1024 / time.inSeconds).roundToInt()} KiB/s" }
true
} ?: kotlin.run {
bot.network.logger.verbose { "[Highway] Uploading group image: timeout, retrying next server" }
false
}
}.getOrElse {
exception?.addSuppressedMirai(it)
exception = it
false
}
}
if (!success) {
throw IllegalStateException("cannot upload group image, failed on all servers.", exception)
}
HighwayHelper.uploadImageToServers(
bot,
response.uploadIpList.zip(response.uploadPortList),
response.uKey,
image,
kind = "group",
commandId = 2
)
val resourceId = image.calculateImageResourceId()
// return NotOnlineImageFromFile(
// resourceId = resourceId,
// md5 = image.md5,
// filepath = resourceId,
// fileLength = image.inputSize.toInt(),
// height = image.height,
// width = image.width,
// imageType = image.imageType,
// fileId = response.fileId.toInt()
// )
return OfflineGroupImage(imageId = resourceId)
.also { ImageUploadEvent.Succeed(this@GroupImpl, image, it).broadcast() }
/*
fileId = response.fileId.toInt(),
fileType = 0, // ?
height = image.height,
width = image.width,
imageType = image.imageType,
bizType = 0,
serverIp = response.uploadIpList.first(),
serverPort = response.uploadPortList.first(),
signature = image.md5,
size = image.inputSize.toInt(),
useful = 1,
source = 200,
original = 1,
pbReserve = EMPTY_BYTE_ARRAY
*/
}
}
}
@ -500,4 +430,4 @@ internal class GroupImpl(
}
override fun toString(): String = "Group($id)"
}
}

View File

@ -54,9 +54,8 @@ internal class MemberImpl constructor(
@JvmSynthetic
override suspend fun sendMessage(message: Message): MessageReceipt<Member> {
return sendMessageImpl(message).also {
logMessageSent(message)
}
return (this.asFriendOrNull()?.sendMessageImpl(this, message) ?: sendMessageImpl(message))
.also { logMessageSent(message) }
}
private suspend fun sendMessageImpl(message: Message): MessageReceipt<Member> {

View File

@ -31,7 +31,7 @@ import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.verbose
@OptIn(MiraiInternalAPI::class)
internal suspend fun Friend.sendMessageImpl(message: Message): MessageReceipt<Friend> {
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")
@ -49,7 +49,7 @@ internal suspend fun Friend.sendMessageImpl(message: Message): MessageReceipt<Fr
}.sendAndExpect<MessageSvc.PbSendMsg.Response>() is MessageSvc.PbSendMsg.Response.SUCCESS
) { "send message failed" }
}
return MessageReceipt(source, this, null)
return MessageReceipt(source, generic, null)
}
@OptIn(MiraiInternalAPI::class, MiraiExperimentalAPI::class)