mirror of
https://github.com/mamoe/mirai.git
synced 2025-04-25 04:50:26 +08:00
CustomFace support
This commit is contained in:
parent
c13109cf5b
commit
dc940ee0cc
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data
mirai-demos/mirai-demo-gentleman/src/main/kotlin/demo/gentleman
@ -19,7 +19,64 @@ internal fun NotOnlineImageFromFile.toJceData(): ImMsgBody.NotOnlineImage {
|
||||
)
|
||||
}
|
||||
|
||||
internal fun CustomFaceFromFile.toJceData(): ImMsgBody.CustomFace {
|
||||
return ImMsgBody.CustomFace(
|
||||
filePath = this.filepath,
|
||||
fileId = this.fileId,
|
||||
serverIp = this.serverIp,
|
||||
serverPort = this.serverPort,
|
||||
fileType = this.fileType,
|
||||
signature = this.signature,
|
||||
useful = this.useful,
|
||||
md5 = this.md5,
|
||||
bizType = this.bizType,
|
||||
imageType = this.imageType,
|
||||
width = this.width,
|
||||
height = this.height,
|
||||
source = this.source,
|
||||
size = this.size,
|
||||
pbReserve = this.pbReserve
|
||||
)
|
||||
}
|
||||
|
||||
/*
|
||||
customFace=CustomFace#2050019814 {
|
||||
guid=<Empty ByteArray>
|
||||
filePath=5F6C522DEAC4F36C0ED8EF362660EFD6.png
|
||||
shortcut=
|
||||
buffer=<Empty ByteArray>
|
||||
flag=<Empty ByteArray>
|
||||
oldData=<Empty ByteArray>
|
||||
fileId=0xB40AF10E(-1274351346)
|
||||
serverIp=0xB703E13A(-1224482502)
|
||||
serverPort=0x00000050(80)
|
||||
fileType=0x00000042(66)
|
||||
signature=6B 44 61 76 72 79 68 79 57 67 70 52 41 45 78 49
|
||||
useful=0x00000001(1)
|
||||
md5=5F 6C 52 2D EA C4 F3 6C 0E D8 EF 36 26 60 EF D6
|
||||
thumbUrl=
|
||||
bigUrl=
|
||||
origUrl=
|
||||
bizType=0x00000005(5)
|
||||
repeatIndex=0x00000000(0)
|
||||
repeatImage=0x00000000(0)
|
||||
imageType=0x000003E9(1001)
|
||||
index=0x00000000(0)
|
||||
width=0x0000005F(95)
|
||||
height=0x00000054(84)
|
||||
source=0x00000067(103)
|
||||
size=0x000006E2(1762)
|
||||
origin=0x00000000(0)
|
||||
thumbWidth=0x00000000(0)
|
||||
thumbHeight=0x00000000(0)
|
||||
showLen=0x00000000(0)
|
||||
downloadLen=0x00000000(0)
|
||||
_400Url=
|
||||
_400Width=0x00000000(0)
|
||||
_400Height=0x00000000(0)
|
||||
pbReserve=08 01 10 00 32 00 4A 0E 5B E5 8A A8 E7 94 BB E8 A1 A8 E6 83 85 5D 50 00 78 05
|
||||
}
|
||||
|
||||
notOnlineImage=NotOnlineImage#2050019814 {
|
||||
filePath=41AEF2D4B5BD24CF3791EFC5FEB67D60.jpg
|
||||
fileLen=0x00000350(848)
|
||||
@ -57,26 +114,39 @@ internal fun MessageChain.toRichTextElems(): MutableList<ImMsgBody.Elem> {
|
||||
|
||||
this.forEach {
|
||||
when (it) {
|
||||
is PlainText -> {
|
||||
elements.add(ImMsgBody.Elem(text = ImMsgBody.Text(str = it.stringValue)))
|
||||
}
|
||||
is PlainText -> elements.add(ImMsgBody.Elem(text = ImMsgBody.Text(str = it.stringValue)))
|
||||
is At -> {
|
||||
|
||||
}
|
||||
is NotOnlineImageFromServer -> {
|
||||
elements.add(ImMsgBody.Elem(notOnlineImage = it.delegate))
|
||||
// elements.add(ImMsgBody.Elem(generalFlags = ImMsgBody.GeneralFlags(pbReserve = "78 00 90 01 01 F8 01 00 A0 02 00 C8 02 00".hexToBytes())))
|
||||
}
|
||||
is NotOnlineImageFromFile -> {
|
||||
elements.add(ImMsgBody.Elem(notOnlineImage = it.toJceData()))
|
||||
// elements.add(ImMsgBody.Elem(generalFlags = ImMsgBody.GeneralFlags(pbReserve = "78 00 90 01 01 F8 01 00 A0 02 00 C8 02 00".hexToBytes())))
|
||||
}
|
||||
is CustomFaceFromFile -> elements.add(ImMsgBody.Elem(customFace = it.toJceData()))
|
||||
is CustomFaceFromServer -> elements.add(ImMsgBody.Elem(customFace = it.delegate))
|
||||
is NotOnlineImageFromServer -> elements.add(ImMsgBody.Elem(notOnlineImage = it.delegate))
|
||||
is NotOnlineImageFromFile -> elements.add(ImMsgBody.Elem(notOnlineImage = it.toJceData()))
|
||||
}
|
||||
}
|
||||
|
||||
return elements
|
||||
}
|
||||
|
||||
internal class CustomFaceFromServer(
|
||||
internal val delegate: ImMsgBody.CustomFace
|
||||
) : CustomFace() {
|
||||
override val filepath: String get() = delegate.filePath
|
||||
override val fileId: Int get() = delegate.fileId
|
||||
override val serverIp: Int get() = delegate.serverIp
|
||||
override val serverPort: Int get() = delegate.serverPort
|
||||
override val fileType: Int get() = delegate.fileType
|
||||
override val signature: ByteArray get() = delegate.signature
|
||||
override val useful: Int get() = delegate.useful
|
||||
override val md5: ByteArray get() = delegate.md5
|
||||
override val bizType: Int get() = delegate.bizType
|
||||
override val imageType: Int get() = delegate.imageType
|
||||
override val width: Int get() = delegate.width
|
||||
override val height: Int get() = delegate.height
|
||||
override val source: Int get() = delegate.source
|
||||
override val size: Int get() = delegate.size
|
||||
override val pbReserve: ByteArray get() = delegate.pbReserve
|
||||
}
|
||||
|
||||
internal class NotOnlineImageFromServer(
|
||||
internal val delegate: ImMsgBody.NotOnlineImage
|
||||
@ -107,22 +177,8 @@ internal fun ImMsgBody.RichText.toMessageChain(): MessageChain {
|
||||
|
||||
elems.forEach {
|
||||
when {
|
||||
it.notOnlineImage != null -> message.add(
|
||||
NotOnlineImageFromServer(it.notOnlineImage)
|
||||
)
|
||||
it.customFace != null -> message.add(
|
||||
NotOnlineImageFromFile(
|
||||
it.customFace.filePath,
|
||||
it.customFace.md5,
|
||||
it.customFace.origUrl,
|
||||
it.customFace.downloadLen,
|
||||
it.customFace.height,
|
||||
it.customFace.width,
|
||||
it.customFace.bizType,
|
||||
it.customFace.imageType,
|
||||
it.customFace.filePath
|
||||
)
|
||||
)
|
||||
it.notOnlineImage != null -> message.add(NotOnlineImageFromServer(it.notOnlineImage))
|
||||
it.customFace != null -> message.add(CustomFaceFromServer(it.customFace))
|
||||
it.text != null -> message.add(it.text.str.toMessage())
|
||||
}
|
||||
}
|
||||
|
@ -2,19 +2,110 @@
|
||||
|
||||
package net.mamoe.mirai.message.data
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
sealed class Image : Message {
|
||||
abstract val resourceId: String
|
||||
abstract val md5: ByteArray
|
||||
|
||||
abstract override fun toString(): String
|
||||
|
||||
final companion object Key : Message.Key<Image>
|
||||
companion object Key : Message.Key<Image>
|
||||
|
||||
abstract override fun eq(other: Message): Boolean
|
||||
}
|
||||
|
||||
abstract class CustomFace : Image() {
|
||||
abstract val filepath: String
|
||||
abstract val fileId: Int
|
||||
abstract val serverIp: Int
|
||||
abstract val serverPort: Int
|
||||
abstract val fileType: Int
|
||||
abstract val signature: ByteArray
|
||||
abstract val useful: Int
|
||||
abstract override val md5: ByteArray
|
||||
abstract val bizType: Int
|
||||
abstract val imageType: Int
|
||||
abstract val width: Int
|
||||
abstract val height: Int
|
||||
abstract val source: Int
|
||||
abstract val size:Int
|
||||
abstract val pbReserve: ByteArray
|
||||
|
||||
override fun toString(): String {
|
||||
return "[CustomFace]"
|
||||
}
|
||||
|
||||
override fun eq(other: Message): Boolean {
|
||||
return this.toString() == other.toString()
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class CustomFaceFromFile(
|
||||
override val filepath: String,
|
||||
override val fileId: Int,
|
||||
override val serverIp: Int,
|
||||
override val serverPort: Int,
|
||||
override val fileType: Int,
|
||||
override val signature: ByteArray,
|
||||
override val useful: Int,
|
||||
override val md5: ByteArray,
|
||||
override val bizType: Int,
|
||||
override val imageType: Int,
|
||||
override val width: Int,
|
||||
override val height: Int,
|
||||
override val source: Int,
|
||||
override val size: Int,
|
||||
override val pbReserve: ByteArray
|
||||
) : CustomFace() {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other == null || this::class != other::class) return false
|
||||
|
||||
other as CustomFaceFromFile
|
||||
|
||||
if (filepath != other.filepath) return false
|
||||
if (fileId != other.fileId) return false
|
||||
if (serverIp != other.serverIp) return false
|
||||
if (serverPort != other.serverPort) return false
|
||||
if (fileType != other.fileType) return false
|
||||
if (!signature.contentEquals(other.signature)) return false
|
||||
if (useful != other.useful) return false
|
||||
if (!md5.contentEquals(other.md5)) return false
|
||||
if (bizType != other.bizType) return false
|
||||
if (imageType != other.imageType) return false
|
||||
if (width != other.width) return false
|
||||
if (height != other.height) return false
|
||||
if (source != other.source) return false
|
||||
if (size != other.size) return false
|
||||
if (!pbReserve.contentEquals(other.pbReserve)) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = filepath.hashCode()
|
||||
result = 31 * result + fileId
|
||||
result = 31 * result + serverIp
|
||||
result = 31 * result + serverPort
|
||||
result = 31 * result + fileType
|
||||
result = 31 * result + signature.contentHashCode()
|
||||
result = 31 * result + useful
|
||||
result = 31 * result + md5.contentHashCode()
|
||||
result = 31 * result + bizType
|
||||
result = 31 * result + imageType
|
||||
result = 31 * result + width
|
||||
result = 31 * result + height
|
||||
result = 31 * result + source
|
||||
result = 31 * result + size
|
||||
result = 31 * result + pbReserve.contentHashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
abstract class NotOnlineImage : Image() {
|
||||
abstract override val resourceId: String
|
||||
abstract val md5: ByteArray
|
||||
abstract val resourceId: String
|
||||
abstract override val md5: ByteArray
|
||||
abstract val filepath: String
|
||||
abstract val fileLength: Int
|
||||
abstract val height: Int
|
||||
@ -24,7 +115,7 @@ abstract class NotOnlineImage : Image() {
|
||||
open val downloadPath: String get() = resourceId
|
||||
|
||||
override fun toString(): String {
|
||||
return "[$resourceId]"
|
||||
return "[NotOnlineImage $resourceId]"
|
||||
}
|
||||
|
||||
override fun eq(other: Message): Boolean {
|
||||
@ -32,7 +123,7 @@ abstract class NotOnlineImage : Image() {
|
||||
}
|
||||
}
|
||||
|
||||
open class NotOnlineImageFromFile(
|
||||
data class NotOnlineImageFromFile(
|
||||
override val resourceId: String,
|
||||
override val md5: ByteArray,
|
||||
override val filepath: String,
|
||||
@ -42,4 +133,36 @@ open class NotOnlineImageFromFile(
|
||||
override val bizType: Int = 0,
|
||||
override val imageType: Int = 1000,
|
||||
override val downloadPath: String = resourceId
|
||||
) : NotOnlineImage()
|
||||
) : NotOnlineImage() {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other == null || this::class != other::class) return false
|
||||
|
||||
other as NotOnlineImageFromFile
|
||||
|
||||
if (resourceId != other.resourceId) return false
|
||||
if (!md5.contentEquals(other.md5)) return false
|
||||
if (filepath != other.filepath) return false
|
||||
if (fileLength != other.fileLength) return false
|
||||
if (height != other.height) return false
|
||||
if (width != other.width) return false
|
||||
if (bizType != other.bizType) return false
|
||||
if (imageType != other.imageType) return false
|
||||
if (downloadPath != other.downloadPath) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = resourceId.hashCode()
|
||||
result = 31 * result + md5.contentHashCode()
|
||||
result = 31 * result + filepath.hashCode()
|
||||
result = 31 * result + fileLength
|
||||
result = 31 * result + height
|
||||
result = 31 * result + width
|
||||
result = 31 * result + bizType
|
||||
result = 31 * result + imageType
|
||||
result = 31 * result + downloadPath.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
@ -23,6 +23,7 @@ import net.mamoe.mirai.message.data.buildXMLMessage
|
||||
import net.mamoe.mirai.message.data.getValue
|
||||
import net.mamoe.mirai.message.sendAsImageTo
|
||||
import net.mamoe.mirai.utils.ContextImpl
|
||||
import net.mamoe.mirai.utils.io.toUHexString
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
import javax.swing.filechooser.FileSystemView
|
||||
@ -130,7 +131,7 @@ suspend fun main() {
|
||||
|
||||
try {
|
||||
image.downloadTo(newTestTempFile(suffix = ".png").also { reply("Temp file: ${it.absolutePath}") })
|
||||
reply(image.resourceId + " downloaded")
|
||||
reply(image.md5.toUHexString() + " downloaded")
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
reply(e.message ?: e::class.java.simpleName)
|
||||
|
Loading…
Reference in New Issue
Block a user