internal.contact.util.kt Maven / Gradle / Ivy
/*
* Copyright 2019-2023 Mamoe Technologies and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
*
* https://github.com/mamoe/mirai/blob/dev/LICENSE
*/
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "CANNOT_OVERRIDE_INVISIBLE_MEMBER")
package net.mamoe.mirai.mock.internal.contact
import kotlinx.serialization.Serializable
import net.mamoe.mirai.Bot
import net.mamoe.mirai.contact.Contact
import net.mamoe.mirai.contact.Group
import net.mamoe.mirai.contact.Member
import net.mamoe.mirai.contact.PermissionDeniedException
import net.mamoe.mirai.internal.contact.uin
import net.mamoe.mirai.internal.message.data.OnlineAudioImpl
import net.mamoe.mirai.internal.message.image.DeferredOriginUrlAware
import net.mamoe.mirai.message.data.*
import net.mamoe.mirai.mock.MockBot
import net.mamoe.mirai.mock.contact.MockGroup
import net.mamoe.mirai.mock.utils.mock
import net.mamoe.mirai.mock.utils.plusHttpSubpath
import net.mamoe.mirai.utils.ExternalResource
import net.mamoe.mirai.utils.ExternalResource.Companion.toExternalResource
import net.mamoe.mirai.utils.Services
import net.mamoe.mirai.utils.cast
import net.mamoe.mirai.utils.toUHexString
internal fun Member.requireBotPermissionHigherThanThis(msg: String) {
if (this.permission < this.group.botPermission) return
throw PermissionDeniedException("bot current permission ${group.botPermission} can't modify $id($permission), $msg")
}
internal fun MessageSource.withMessage(msg: Message): MessageChain = buildMessageChain {
add(this@withMessage)
if (msg is MessageChain) {
msg.forEach { sub ->
if (sub !is MessageSource) {
add(sub)
}
}
} else if (msg !is MessageSource) {
add(msg)
}
}
@Suppress("UNUSED_PARAMETER")
internal suspend fun ExternalResource.mockUploadAudio(bot: MockBot): OfflineAudio {
val md5 = md5 // calculate before using resource
return inResource {
OfflineAudio(
filename = md5.toUHexString() + ".amr",
fileMd5 = md5,
fileSize = size,
codec = AudioCodec.SILK,
extraData = null,
)
}
}
internal suspend fun ExternalResource.mockUploadVoice(bot: MockBot) = kotlin.run {
val md5 = this.md5
val size = this.size
@Suppress("DEPRECATION_ERROR")
net.mamoe.mirai.message.data.Voice(
fileName = md5.toUHexString() + ".amr",
md5 = md5,
fileSize = size,
_url = bot.tmpResourceServer.uploadResourceAndGetUrl(this)
)
}
internal const val AQQ_RECALL_FAILED_MESSAGE: String = "No message meets the requirements"
internal val Group.mockUin: Long
get() = when (this) {
is MockGroup -> this.uin
else -> this.uin
}
internal suspend fun ExternalResource.mockImplUploadAudioAsOnline(bot: MockBot): OnlineAudio {
val md5 = this.md5
val size = this.size
return OnlineAudioImpl(
filename = md5.toUHexString() + ".amr",
fileMd5 = md5,
fileSize = size,
codec = AudioCodec.SILK,
url = bot.tmpResourceServer.uploadResourceAndGetUrl(this),
length = size,
originalPtt = null,
)
}
@Suppress("SERIALIZER_TYPE_INCOMPATIBLE")
@Serializable(MockImage.Serializer::class)
internal class MockImage(
override val imageId: String,
private val urlPath: String,
override val width: Int = 0,
override val height: Int = 0,
override val size: Long = 0,
override val imageType: ImageType = ImageType.UNKNOWN,
) : DeferredOriginUrlAware, Image {
companion object {
// create a mockImage with random content
internal suspend fun random(bot: MockBot): MockImage {
val text = bot.avatarGenerator.generateRandomAvatar()
return bot.uploadMockImage(text.toExternalResource().toAutoCloseable()).cast()
}
internal suspend fun randomForPerson(bot: MockBot, id: Long): MockImage {
val text = bot.avatarGenerator.generateAvatarForPerson(id)
return bot.uploadMockImage(text.toExternalResource().toAutoCloseable()).cast()
}
internal suspend fun randomForGroup(bot: MockBot, id: Long): MockImage {
val text = bot.avatarGenerator.generateAvatarForGroup(id)
return bot.uploadMockImage(text.toExternalResource().toAutoCloseable()).cast()
}
}
object Serializer : Image.FallbackSerializer("MockImage")
private val _stringValue: String? by lazy(LazyThreadSafetyMode.NONE) { "[mirai:image:$imageId]" }
override fun getUrl(bot: Bot): String {
if (urlPath.startsWith("http"))
return urlPath
return bot.mock().tmpResourceServer.storageRoot.toString().plusHttpSubpath(urlPath)
}
override fun toString(): String = _stringValue!!
override fun contentToString(): String = if (isEmoji) {
"[动画表情]"
} else {
"[图片]"
}
override fun appendMiraiCodeTo(builder: StringBuilder) {
builder.append("[mirai:image:").append(imageId).append("]")
}
override fun hashCode(): Int = imageId.hashCode()
override fun equals(other: Any?): Boolean {
if (other === this) return true
if (other !is Image) return false
return this.imageId == other.imageId
}
}
internal object MockInternalImageProtocolImpl : InternalImageProtocol {
override fun createImage(
imageId: String,
size: Long,
type: ImageType,
width: Int,
height: Int,
isEmoji: Boolean
): Image = MockImage(imageId, "images/" + imageId.substring(1..36), width, height, size, type)
override suspend fun isUploaded(
bot: Bot,
md5: ByteArray,
size: Long,
context: Contact?,
type: ImageType,
width: Int,
height: Int
): Boolean = bot.cast().tmpResourceServer.isImageUploaded(md5, size)
}
internal fun registerMockServices() {
Services.registerAsOverride(
Services.qualifiedNameOrFail(InternalImageProtocol::class),
"net.mamoe.mirai.mock.internal.contact.MockInternalImageProtocolImpl"
) {
MockInternalImageProtocolImpl
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy