Rewrite image

This commit is contained in:
Him188 2020-02-02 23:21:26 +08:00
parent 73cda9dfe5
commit 6ac9acc640
4 changed files with 49 additions and 89 deletions

View File

@ -2,10 +2,9 @@ package net.mamoe.mirai.qqandroid
import net.mamoe.mirai.contact.* import net.mamoe.mirai.contact.*
import net.mamoe.mirai.data.FriendNameRemark import net.mamoe.mirai.data.FriendNameRemark
import net.mamoe.mirai.data.GroupInfo
import net.mamoe.mirai.data.PreviousNameList import net.mamoe.mirai.data.PreviousNameList
import net.mamoe.mirai.data.Profile import net.mamoe.mirai.data.Profile
import net.mamoe.mirai.message.data.ImageId import net.mamoe.mirai.message.data.Image
import net.mamoe.mirai.message.data.MessageChain import net.mamoe.mirai.message.data.MessageChain
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.MessageSvc import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.MessageSvc
import net.mamoe.mirai.utils.* import net.mamoe.mirai.utils.*
@ -28,7 +27,7 @@ internal class QQImpl(bot: QQAndroidBot, override val coroutineContext: Coroutin
} }
} }
override suspend fun uploadImage(image: ExternalImage): ImageId { override suspend fun uploadImage(image: ExternalImage): Image {
TODO("not implemented") TODO("not implemented")
} }
@ -81,6 +80,10 @@ internal class GroupImpl(
override lateinit var announcement: String override lateinit var announcement: String
override lateinit var members: ContactList<Member> override lateinit var members: ContactList<Member>
init {
members = ContactList(LockFreeLinkedList())
}
override val internalId: GroupInternalId = GroupId(id).toInternalId() override val internalId: GroupInternalId = GroupId(id).toInternalId()
override fun getMember(id: Long): Member = override fun getMember(id: Long): Member =
@ -115,7 +118,7 @@ internal class GroupImpl(
} }
} }
override suspend fun uploadImage(image: ExternalImage): ImageId { override suspend fun uploadImage(image: ExternalImage): Image {
TODO("not implemented") TODO("not implemented")
} }

View File

@ -1,14 +1,13 @@
package net.mamoe.mirai.qqandroid package net.mamoe.mirai.qqandroid
import kotlinx.io.core.ByteReadPacket
import net.mamoe.mirai.BotAccount import net.mamoe.mirai.BotAccount
import net.mamoe.mirai.BotImpl import net.mamoe.mirai.BotImpl
import net.mamoe.mirai.contact.* import net.mamoe.mirai.contact.*
import net.mamoe.mirai.data.AddFriendResult import net.mamoe.mirai.data.AddFriendResult
import net.mamoe.mirai.data.ImageLink
import net.mamoe.mirai.message.data.Image import net.mamoe.mirai.message.data.Image
import net.mamoe.mirai.qqandroid.network.QQAndroidBotNetworkHandler import net.mamoe.mirai.qqandroid.network.QQAndroidBotNetworkHandler
import net.mamoe.mirai.qqandroid.network.QQAndroidClient import net.mamoe.mirai.qqandroid.network.QQAndroidClient
import net.mamoe.mirai.qqandroid.utils.ImageIdQQA
import net.mamoe.mirai.utils.BotConfiguration import net.mamoe.mirai.utils.BotConfiguration
import net.mamoe.mirai.utils.Context import net.mamoe.mirai.utils.Context
import net.mamoe.mirai.utils.LockFreeLinkedList import net.mamoe.mirai.utils.LockFreeLinkedList
@ -56,12 +55,15 @@ internal abstract class QQAndroidBotBase constructor(
return groups.delegate.filteringGetOrAdd({ it.id == id }, { GroupImpl(this as QQAndroidBot, coroutineContext, id) }) return groups.delegate.filteringGetOrAdd({ it.id == id }, { GroupImpl(this as QQAndroidBot, coroutineContext, id) })
} }
override suspend fun Image.getLink(): ImageLink { override suspend fun addFriend(id: Long, message: String?, remark: String?): AddFriendResult {
require(this.id is ImageIdQQA) { "image.id must be ImageIdQQA" } TODO("not implemented")
return (this.id as ImageIdQQA).link
} }
override suspend fun addFriend(id: Long, message: String?, remark: String?): AddFriendResult { override suspend fun Image.download(): ByteReadPacket {
TODO("not implemented")
}
override suspend fun Image.downloadAsByteArray(): ByteArray {
TODO("not implemented") TODO("not implemented")
} }

View File

@ -2,76 +2,44 @@
package net.mamoe.mirai.message.data package net.mamoe.mirai.message.data
import net.mamoe.mirai.contact.Contact sealed class Image : Message {
import net.mamoe.mirai.contact.sendMessage abstract val resourceId: String
import net.mamoe.mirai.utils.ExternalImage
abstract override fun toString(): String
fun Image(id: String) = Image(ImageId(id)) final companion object Key : Message.Key<Image>
/** abstract override fun eq(other: Message): Boolean
* 图片消息. 在发送时将会区分群图片和好友图片发送. }
* 由接收消息时构建, 可直接发送
*
* @param id 这个图片的 [ImageId]
*/ // TODO: 2020/1/31 去掉 Image. 将 Image 改为 interface/class
inline class Image(inline val id: ImageId) : Message {
override fun toString(): String = "[${id.value}]"
companion object Key : Message.Key<Image> abstract class NotOnlineImage : Image() {
abstract override val resourceId: String
abstract val md5: ByteArray
abstract val filepath: String
abstract val fileLength: Int
abstract val height: Int
abstract val width: Int
open val bizType: Int get() = 0
open val imageType: Int get() = 1000
open val downloadPath: String get() = resourceId
override fun toString(): String {
return "[$resourceId]"
}
override fun eq(other: Message): Boolean { override fun eq(other: Message): Boolean {
return other is Image && other.id == this.id return other.toString() == this.toString()
} }
} }
inline val Image.idValue: String get() = id.value open class NotOnlineImageFromFile(
override val resourceId: String,
inline class ImageId0x06(override inline val value: String) : ImageId { override val md5: ByteArray,
override fun toString(): String = "ImageId($value)" override val filepath: String,
} override val fileLength: Int,
override val height: Int,
/** override val width: Int,
* 一般是群的图片的 id. override val bizType: Int = 0,
*/ override val imageType: Int = 1000,
class ImageId0x03 constructor(override inline val value: String, inline val uniqueId: UInt, inline val height: Int, inline val width: Int) : override val downloadPath: String = resourceId
ImageId { ) : NotOnlineImage()
override fun toString(): String = "ImageId(value=$value, uniqueId=${uniqueId}, height=$height, width=$width)"
val md5: ByteArray
get() = this.value
.substringAfter("{").substringBefore("}")
.replace("-", "")
.chunked(2)
.map { (it[0] + it[1].toString()).toUByte(16).toByte() }
.toByteArray().also { check(it.size == 16) }
}
@Suppress("FunctionName", "NOTHING_TO_INLINE")
inline fun ImageId(value: String): ImageId = ImageId0x06(value)
@Suppress("FunctionName", "NOTHING_TO_INLINE")
inline fun ImageId(value: String, uniqueId: UInt, height: Int, width: Int): ImageId =
ImageId0x03(value, uniqueId, height, width)
/**
* 图片的标识符. 由图片的数据产生.
* 对于群, [value] 类似于 `{F61593B5-5B98-1798-3F47-2A91D32ED2FC}.jpg`, 由图片文件 MD5 直接产生.
* 对于好友, [value] 类似于 `/01ee6426-5ff1-4cf0-8278-e8634d2909ef`, 由服务器返回.
*
* @see ExternalImage.groupImageId 群图片的 [ImageId] 获取
* @see FriendImagePacket 好友图片的 [ImageId] 获取
*/
interface ImageId {
val value: String
}
fun ImageId.checkLength() = check(value.length == 37 || value.length == 42) { "Illegal ImageId length" }
fun ImageId.requireLength() = require(value.length == 37 || value.length == 42) { "Illegal ImageId length" }
@Suppress("NOTHING_TO_INLINE")
inline fun ImageId.image(): Image =
Image(this)
suspend inline fun ImageId.sendTo(contact: Contact) = contact.sendMessage(this.image())

View File

@ -45,19 +45,6 @@ class ExternalImage(
} }
} }
/**
* 用于发送消息的 [ImageId]
*/
@Suppress("EXPERIMENTAL_UNSIGNED_LITERALS")
val groupImageId: ImageId by lazy {
ImageId0x03(
"{${md5[0..3]}-${md5[4..5]}-${md5[6..7]}-${md5[8..9]}-${md5[10..15]}}.$format",
0u,
height,
width
)
}
override fun toString(): String = "[ExternalImage(${width}x$height $format)]" override fun toString(): String = "[ExternalImage(${width}x$height $format)]"
} }
@ -77,8 +64,8 @@ suspend fun ExternalImage.sendTo(contact: Contact) = when (contact) {
* @see contact 图片上传对象. 由于好友图片与群图片不通用, 上传时必须提供目标联系人 * @see contact 图片上传对象. 由于好友图片与群图片不通用, 上传时必须提供目标联系人
*/ */
suspend fun ExternalImage.upload(contact: Contact): Image = when (contact) { suspend fun ExternalImage.upload(contact: Contact): Image = when (contact) {
is Group -> contact.uploadImage(this).image() is Group -> contact.uploadImage(this)
is QQ -> contact.uploadImage(this).image() is QQ -> contact.uploadImage(this)
else -> assertUnreachable() else -> assertUnreachable()
} }