Commit 5f4c3882 authored by Him188's avatar Him188

Group image support

parent 1b3065a4
...@@ -8,10 +8,10 @@ import net.mamoe.mirai.data.Profile ...@@ -8,10 +8,10 @@ import net.mamoe.mirai.data.Profile
import net.mamoe.mirai.message.data.CustomFaceFromFile import net.mamoe.mirai.message.data.CustomFaceFromFile
import net.mamoe.mirai.message.data.Image 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.message.data.NotOnlineImageFromFile
import net.mamoe.mirai.qqandroid.io.serialization.readProtoBuf import net.mamoe.mirai.qqandroid.io.serialization.readProtoBuf
import net.mamoe.mirai.qqandroid.network.highway.Highway import net.mamoe.mirai.qqandroid.network.highway.Highway
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.CSDataHighwayHead import net.mamoe.mirai.qqandroid.network.protocol.data.proto.CSDataHighwayHead
import net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.TroopManagement 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.image.ImgStore
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.MessageSvc import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.MessageSvc
...@@ -324,14 +324,20 @@ internal class GroupImpl( ...@@ -324,14 +324,20 @@ internal class GroupImpl(
is ImgStore.GroupPicUp.Response.Failed -> error("upload group image failed with reason ${response.message}") is ImgStore.GroupPicUp.Response.Failed -> error("upload group image failed with reason ${response.message}")
is ImgStore.GroupPicUp.Response.FileExists -> { is ImgStore.GroupPicUp.Response.FileExists -> {
val resourceId = image.calculateImageResourceId() val resourceId = image.calculateImageResourceId()
return NotOnlineImageFromFile( // return NotOnlineImageFromFile(
resourceId = resourceId, // resourceId = resourceId,
md5 = response.fileInfo.fileMd5, // md5 = response.fileInfo.fileMd5,
filepath = resourceId, // filepath = resourceId,
fileLength = response.fileInfo.fileSize.toInt(), // fileLength = response.fileInfo.fileSize.toInt(),
height = response.fileInfo.fileHeight, // height = response.fileInfo.fileHeight,
width = response.fileInfo.fileWidth, // width = response.fileInfo.fileWidth,
imageType = response.fileInfo.fileType // imageType = response.fileInfo.fileType,
// fileId = response.fileId.toInt()
// )
// println("NMSL")
return CustomFaceFromFile(
md5 = image.md5,
filepath = resourceId
) )
} }
is ImgStore.GroupPicUp.Response.RequireUpload -> { is ImgStore.GroupPicUp.Response.RequireUpload -> {
...@@ -362,12 +368,21 @@ internal class GroupImpl( ...@@ -362,12 +368,21 @@ internal class GroupImpl(
} }
socket.close() socket.close()
val resourceId = image.calculateImageResourceId() 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 CustomFaceFromFile( return CustomFaceFromFile(
md5 = image.md5, md5 = image.md5,
filepath = resourceId, filepath = resourceId,
fileId = response.fileId.toInt(), fileId = response.fileId.toInt(),
fileType = 66, // ? fileType = 0, // ?
height = image.height, height = image.height,
width = image.width, width = image.width,
imageType = image.imageType, imageType = image.imageType,
...@@ -378,8 +393,8 @@ internal class GroupImpl( ...@@ -378,8 +393,8 @@ internal class GroupImpl(
size = image.inputSize.toInt(), size = image.inputSize.toInt(),
useful = 1, useful = 1,
source = 200, source = 200,
origin = 1, original = 1,
pbReserve = byteArrayOf(0x78, 0x02) pbReserve = EMPTY_BYTE_ARRAY
) )
} }
} }
......
...@@ -36,6 +36,7 @@ internal abstract class QQAndroidBotBase constructor( ...@@ -36,6 +36,7 @@ internal abstract class QQAndroidBotBase constructor(
val selfQQ: QQ by lazy { QQ(uin) } val selfQQ: QQ by lazy { QQ(uin) }
override fun getFriend(id: Long): QQ { override fun getFriend(id: Long): QQ {
if (id == uin) return selfQQ
return qqs.delegate[id] return qqs.delegate[id]
} }
......
...@@ -15,19 +15,19 @@ class Oidb0x8fc : ProtoBuf { ...@@ -15,19 +15,19 @@ class Oidb0x8fc : ProtoBuf {
@Serializable @Serializable
class CommCardNameBuf( class CommCardNameBuf(
@SerialId(1) val richCardName: List<Oidb0x8fc.RichCardNameElem>? = null @SerialId(1) val richCardName: List<RichCardNameElem>? = null
) : ProtoBuf ) : ProtoBuf
@Serializable @Serializable
class ReqBody( class ReqBody(
@SerialId(1) val groupCode: Long = 0L, @SerialId(1) val groupCode: Long = 0L,
@SerialId(2) val showFlag: Int = 0, @SerialId(2) val showFlag: Int = 0,
@SerialId(3) val memLevelInfo: List<Oidb0x8fc.MemberInfo>? = null, @SerialId(3) val memLevelInfo: List<MemberInfo>? = null,
@SerialId(4) val levelName: List<Oidb0x8fc.LevelName>? = null, @SerialId(4) val levelName: List<LevelName>? = null,
@SerialId(5) val updateTime: Int = 0, @SerialId(5) val updateTime: Int = 0,
@SerialId(6) val officeMode: Int = 0, @SerialId(6) val officeMode: Int = 0,
@SerialId(7) val groupOpenAppid: Int = 0, @SerialId(7) val groupOpenAppid: Int = 0,
@SerialId(8) val msgClientInfo: Oidb0x8fc.ClientInfo? = null, @SerialId(8) val msgClientInfo: ClientInfo? = null,
@SerialId(9) val authKey: ByteArray = EMPTY_BYTE_ARRAY @SerialId(9) val authKey: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf ) : ProtoBuf
...@@ -48,7 +48,7 @@ class Oidb0x8fc : ProtoBuf { ...@@ -48,7 +48,7 @@ class Oidb0x8fc : ProtoBuf {
@SerialId(13) val job: ByteArray = EMPTY_BYTE_ARRAY, @SerialId(13) val job: ByteArray = EMPTY_BYTE_ARRAY,
@SerialId(14) val tribeLevel: Int = 0, @SerialId(14) val tribeLevel: Int = 0,
@SerialId(15) val tribePoint: Int = 0, @SerialId(15) val tribePoint: Int = 0,
@SerialId(16) val richCardName: List<Oidb0x8fc.CardNameElem>? = null, @SerialId(16) val richCardName: List<CardNameElem>? = null,
@SerialId(17) val commRichCardName: ByteArray = EMPTY_BYTE_ARRAY @SerialId(17) val commRichCardName: ByteArray = EMPTY_BYTE_ARRAY
) : ProtoBuf ) : ProtoBuf
......
...@@ -27,7 +27,9 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.buildOutgoingUniPacket ...@@ -27,7 +27,9 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.buildOutgoingUniPacket
import net.mamoe.mirai.qqandroid.utils.toMessageChain import net.mamoe.mirai.qqandroid.utils.toMessageChain
import net.mamoe.mirai.qqandroid.utils.toRichTextElems import net.mamoe.mirai.qqandroid.utils.toRichTextElems
import net.mamoe.mirai.utils.MiraiInternalAPI import net.mamoe.mirai.utils.MiraiInternalAPI
import net.mamoe.mirai.utils.cryptor.contentToString
import net.mamoe.mirai.utils.currentTimeSeconds import net.mamoe.mirai.utils.currentTimeSeconds
import net.mamoe.mirai.utils.io.DebugLogger
import kotlin.math.absoluteValue import kotlin.math.absoluteValue
import kotlin.random.Random import kotlin.random.Random
...@@ -121,9 +123,6 @@ internal class MessageSvc { ...@@ -121,9 +123,6 @@ internal class MessageSvc {
return EmptyResponse return EmptyResponse
} }
if (!bot.firstLoginSucceed)
return EmptyResponse
val messages = resp.uinPairMsgs.asSequence().filterNot { it.msg == null }.flatMap { it.msg!!.asSequence() }.mapNotNull { val messages = resp.uinPairMsgs.asSequence().filterNot { it.msg == null }.flatMap { it.msg!!.asSequence() }.mapNotNull {
when (it.msgHead.msgType) { when (it.msgHead.msgType) {
166 -> FriendMessage( 166 -> FriendMessage(
...@@ -220,6 +219,8 @@ internal class MessageSvc { ...@@ -220,6 +219,8 @@ internal class MessageSvc {
///writeFully("0A 08 0A 06 08 89 FC A6 8C 0B 12 06 08 01 10 00 18 00 1A 1F 0A 1D 12 08 0A 06 0A 04 F0 9F 92 A9 12 11 AA 02 0E 88 01 00 9A 01 08 78 00 F8 01 00 C8 02 00 20 9B 7A 28 F4 CA 9B B8 03 32 34 08 92 C2 C4 F1 05 10 92 C2 C4 F1 05 18 E6 ED B9 C3 02 20 89 FE BE A4 06 28 89 84 F9 A2 06 48 DE 8C EA E5 0E 58 D9 BD BB A0 09 60 1D 68 92 C2 C4 F1 05 70 00 40 01".hexToBytes()) ///writeFully("0A 08 0A 06 08 89 FC A6 8C 0B 12 06 08 01 10 00 18 00 1A 1F 0A 1D 12 08 0A 06 0A 04 F0 9F 92 A9 12 11 AA 02 0E 88 01 00 9A 01 08 78 00 F8 01 00 C8 02 00 20 9B 7A 28 F4 CA 9B B8 03 32 34 08 92 C2 C4 F1 05 10 92 C2 C4 F1 05 18 E6 ED B9 C3 02 20 89 FE BE A4 06 28 89 84 F9 A2 06 48 DE 8C EA E5 0E 58 D9 BD BB A0 09 60 1D 68 92 C2 C4 F1 05 70 00 40 01".hexToBytes())
DebugLogger.debug("sending group message: " + message.toRichTextElems().contentToString())
val seq = client.atomicNextMessageSequenceId() val seq = client.atomicNextMessageSequenceId()
///return@buildOutgoingUniPacket ///return@buildOutgoingUniPacket
writeProtoBuf( writeProtoBuf(
......
...@@ -30,10 +30,51 @@ internal fun NotOnlineImageFromFile.toJceData(): ImMsgBody.NotOnlineImage { ...@@ -30,10 +30,51 @@ internal fun NotOnlineImageFromFile.toJceData(): ImMsgBody.NotOnlineImage {
picWidth = this.width, picWidth = this.width,
bizType = this.bizType, bizType = this.bizType,
imgType = this.imageType, imgType = this.imageType,
downloadPath = this.downloadPath downloadPath = this.downloadPath,
original = this.original,
fileId = this.fileId,
pbReserve = byteArrayOf(0x78, 0x02)
) )
} }
/*
CustomFace#24412994 {
guid=<Empty ByteArray>
filePath={01E9451B-70ED-EAE3-B37C-101F1EEBF5B5}.png
shortcut=
buffer=<Empty ByteArray>
flag=00 00 00 00
oldData=15 36 20 39 32 6B 41 31 00 38 37 32 66 30 36 36 30 33 61 65 31 30 33 62 37 20 20 20 20 20 20 35 30 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 7B 30 31 45 39 34 35 31 42 2D 37 30 45 44 2D 45 41 45 33 2D 42 33 37 43 2D 31 30 31 46 31 45 45 42 46 35 42 35 7D 2E 70 6E 67 41
fileId=0x872F0660(-2026961312)
serverIp=0x3AE103B7(987825079)
serverPort=0x00000050(80)
fileType=0x00000000(0)
signature=<Empty ByteArray>
useful=0x00000001(1)
md5=01 E9 45 1B 70 ED EA E3 B3 7C 10 1F 1E EB F5 B5
thumbUrl=/gchatpic_new/1040400290/1041235568-2268005984-01E9451B70EDEAE3B37C101F1EEBF5B5/198?term=2
bigUrl=
origUrl=/gchatpic_new/1040400290/1041235568-2268005984-01E9451B70EDEAE3B37C101F1EEBF5B5/0?term=2
bizType=0x00000000(0)
repeatIndex=0x00000000(0)
repeatImage=0x00000000(0)
imageType=0x00000000(0)
index=0x00000000(0)
width=0x0000015F(351)
height=0x000000EB(235)
source=0x00000000(0)
size=0x0000057C(1404)
origin=0x00000000(0)
thumbWidth=0x000000C6(198)
thumbHeight=0x00000084(132)
showLen=0x00000000(0)
downloadLen=0x00000000(0)
_400Url=/gchatpic_new/1040400290/1041235568-2268005984-01E9451B70EDEAE3B37C101F1EEBF5B5/400?term=2
_400Width=0x0000015F(351)
_400Height=0x000000EB(235)
pbReserve=<Empty ByteArray>
}
*/
internal fun CustomFaceFromFile.toJceData(): ImMsgBody.CustomFace { internal fun CustomFaceFromFile.toJceData(): ImMsgBody.CustomFace {
return ImMsgBody.CustomFace( return ImMsgBody.CustomFace(
filePath = this.filepath, filePath = this.filepath,
...@@ -50,11 +91,19 @@ internal fun CustomFaceFromFile.toJceData(): ImMsgBody.CustomFace { ...@@ -50,11 +91,19 @@ internal fun CustomFaceFromFile.toJceData(): ImMsgBody.CustomFace {
height = this.height, height = this.height,
source = this.source, source = this.source,
size = this.size, size = this.size,
origin = this.origin, origin = this.original,
pbReserve = this.pbReserve pbReserve = this.pbReserve,
flag = ByteArray(4),
//_400Height = 235,
//_400Url = "/gchatpic_new/1040400290/1041235568-2195821338-01E9451B70EDEAE3B37C101F1EEBF5B5/400?term=2",
//_400Width = 351,
oldData = oldData
) )
} }
private val oldData: ByteArray =
"15 36 20 39 32 6B 41 31 00 38 37 32 66 30 36 36 30 33 61 65 31 30 33 62 37 20 20 20 20 20 20 35 30 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 7B 30 31 45 39 34 35 31 42 2D 37 30 45 44 2D 45 41 45 33 2D 42 33 37 43 2D 31 30 31 46 31 45 45 42 46 35 42 35 7D 2E 70 6E 67 41".hexToBytes()
/* /*
customFace=CustomFace#2050019814 { customFace=CustomFace#2050019814 {
guid=<Empty ByteArray> guid=<Empty ByteArray>
...@@ -165,8 +214,9 @@ internal class CustomFaceFromServer( ...@@ -165,8 +214,9 @@ internal class CustomFaceFromServer(
override val height: Int get() = delegate.height override val height: Int get() = delegate.height
override val source: Int get() = delegate.source override val source: Int get() = delegate.source
override val size: Int get() = delegate.size override val size: Int get() = delegate.size
override val origin: Int get() = delegate.origin override val original: Int get() = delegate.origin
override val pbReserve: ByteArray get() = delegate.pbReserve override val pbReserve: ByteArray get() = delegate.pbReserve
override val miraiImageId: String get() = delegate.filePath
} }
internal class NotOnlineImageFromServer( internal class NotOnlineImageFromServer(
...@@ -181,6 +231,8 @@ internal class NotOnlineImageFromServer( ...@@ -181,6 +231,8 @@ internal class NotOnlineImageFromServer(
override val bizType: Int get() = delegate.bizType override val bizType: Int get() = delegate.bizType
override val imageType: Int get() = delegate.imgType override val imageType: Int get() = delegate.imgType
override val downloadPath: String get() = delegate.downloadPath override val downloadPath: String get() = delegate.downloadPath
override val fileId: Int get() = delegate.fileId
override val original: Int get() = delegate.original
} }
@UseExperimental(ExperimentalUnsignedTypes::class, MiraiInternalAPI::class) @UseExperimental(ExperimentalUnsignedTypes::class, MiraiInternalAPI::class)
......
package net.mamoe.mirai.qqandroid
import io.ktor.client.HttpClient
import io.ktor.client.request.get
import io.ktor.client.request.header
import io.ktor.client.request.headers
import io.ktor.client.request.post
import io.ktor.client.response.HttpResponse
import io.ktor.http.URLProtocol
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.io.readRemaining
import kotlinx.coroutines.launch
import kotlinx.io.core.readBytes
suspend fun main(){
val lst = listOf<String>("N","n","M","m","S","s","L","l","1","2","3","4","5","0")
fun rdm(l:Int):String{
var s = "Pp";
repeat(l){
s+=lst.random()
}
return s
}
val lst2 = listOf<String>("1","2","3","4","5","6","7")
fun rdmQQ(){
var s = "1"
repeat(8){
s+=lst2.random()
}
}
coroutineScope {
repeat(1000) {
launch {
val r = HttpClient().get<HttpResponse>() {
url {
protocol = URLProtocol.HTTPS
host = "papl.lfdevs.com"
path("/check/regcheck")
parameters["c"] = "reg"
parameters["username"] = rdm(12)
parameters["email"] = rdm(5) + "@126.com"
parameters["pwd"] = rdm(10)
parameters["qq"] = rdmQQ().toString()
parameters["sex"] = "1"
}
headers {
header("referer","https://papl.lfdevs.com/index/login")
header("user-agent","Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36")
}
}
if(r.status.value==200) {
println(r.status.toString() + "|" + String(r.content.readRemaining().readBytes()))
}
}
}
}
}
...@@ -4,6 +4,7 @@ package net.mamoe.mirai.message ...@@ -4,6 +4,7 @@ package net.mamoe.mirai.message
import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.IoBuffer import kotlinx.io.core.IoBuffer
import kotlinx.io.core.readBytes
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.contact.Contact import net.mamoe.mirai.contact.Contact
import net.mamoe.mirai.contact.Group import net.mamoe.mirai.contact.Group
...@@ -105,7 +106,7 @@ abstract class MessagePacketBase<TSender : QQ, TSubject : Contact>(_bot: Bot) : ...@@ -105,7 +106,7 @@ abstract class MessagePacketBase<TSender : QQ, TSubject : Contact>(_bot: Bot) :
* 非常不推荐这样做. * 非常不推荐这样做.
*/ */
@Deprecated("内存使用效率十分低下", ReplaceWith("this.download()"), DeprecationLevel.WARNING) @Deprecated("内存使用效率十分低下", ReplaceWith("this.download()"), DeprecationLevel.WARNING)
suspend inline fun Image.downloadAsByteArray(): ByteArray = bot.run { downloadAsByteArray() } suspend inline fun Image.downloadAsByteArray(): ByteArray = bot.run { download().readBytes() }
// TODO: 2020/2/5 为下载图片添加文件系统的存储方式 // TODO: 2020/2/5 为下载图片添加文件系统的存储方式
......
...@@ -3,11 +3,10 @@ ...@@ -3,11 +3,10 @@
package net.mamoe.mirai.message.data package net.mamoe.mirai.message.data
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import net.mamoe.mirai.utils.io.chunkedHexToBytes
sealed class Image : Message { sealed class Image : Message {
abstract val filepath: String abstract val miraiImageId: String
abstract val md5: ByteArray
abstract override fun toString(): String abstract override fun toString(): String
companion object Key : Message.Key<Image> companion object Key : Message.Key<Image>
...@@ -16,22 +15,22 @@ sealed class Image : Message { ...@@ -16,22 +15,22 @@ sealed class Image : Message {
} }
abstract class CustomFace : Image() { abstract class CustomFace : Image() {
abstract override val filepath: String abstract val filepath: String
abstract val fileId: Int abstract val fileId: Int
abstract val serverIp: Int abstract val serverIp: Int
abstract val serverPort: Int abstract val serverPort: Int
abstract val fileType: Int abstract val fileType: Int
abstract val signature: ByteArray abstract val signature: ByteArray
abstract val useful: Int abstract val useful: Int
abstract override val md5: ByteArray abstract val md5: ByteArray
abstract val bizType: Int abstract val bizType: Int
abstract val imageType: Int abstract val imageType: Int
abstract val width: Int abstract val width: Int
abstract val height: Int abstract val height: Int
abstract val source: Int abstract val source: Int
abstract val size:Int abstract val size: Int
abstract val pbReserve: ByteArray abstract val pbReserve: ByteArray
abstract val origin: Int abstract val original: Int
override fun toString(): String { override fun toString(): String {
return "[CustomFace]" return "[CustomFace]"
...@@ -42,25 +41,47 @@ abstract class CustomFace : Image() { ...@@ -42,25 +41,47 @@ abstract class CustomFace : Image() {
} }
} }
private val EMPTY_BYTE_ARRAY = ByteArray(0)
private fun calculateImageMd5ByMiraiImageId(miraiImageId: String): ByteArray {
return if (miraiImageId.startsWith('/')) {
miraiImageId
.drop(1)
.replace('-', ' ')
.take(16 * 2)
.chunkedHexToBytes()
} else {
miraiImageId
.substringAfter('{')
.substringBefore('}')
.replace('-', ' ')
.chunkedHexToBytes()
}
}
@Serializable @Serializable
data class CustomFaceFromFile( data class CustomFaceFromFile(
override val filepath: String, override val filepath: String, // {01E9451B-70ED-EAE3-B37C-101F1EEBF5B5}.png
override val fileId: Int, override val md5: ByteArray
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 origin: Int,
override val pbReserve: ByteArray
) : CustomFace() { ) : CustomFace() {
constructor(miraiImageId: String) : this(filepath = miraiImageId, md5 = calculateImageMd5ByMiraiImageId(miraiImageId))
override val fileId: Int get() = 0
override val serverIp: Int get() = 0
override val serverPort: Int get() = 0
override val fileType: Int get() = 0 // 0
override val signature: ByteArray get() = EMPTY_BYTE_ARRAY
override val useful: Int get() = 1
override val bizType: Int get() = 0
override val imageType: Int get() = 0
override val width: Int get() = 0
override val height: Int get() = 0
override val source: Int get() = 200
override val size: Int get() = 0
override val original: Int get() = 1
override val pbReserve: ByteArray get() = EMPTY_BYTE_ARRAY
override val miraiImageId: String get() = filepath
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
if (other == null || this::class != other::class) return false if (other == null || this::class != other::class) return false
...@@ -81,7 +102,7 @@ data class CustomFaceFromFile( ...@@ -81,7 +102,7 @@ data class CustomFaceFromFile(
if (height != other.height) return false if (height != other.height) return false
if (source != other.source) return false if (source != other.source) return false
if (size != other.size) return false if (size != other.size) return false
if (origin != this.origin) return false if (original != this.original) return false
if (!pbReserve.contentEquals(other.pbReserve)) return false if (!pbReserve.contentEquals(other.pbReserve)) return false
return true return true
...@@ -107,19 +128,23 @@ data class CustomFaceFromFile( ...@@ -107,19 +128,23 @@ data class CustomFaceFromFile(
} }
} }
/**
* 电脑可能看不到这个消息.
*/
abstract class NotOnlineImage : Image() { abstract class NotOnlineImage : Image() {
abstract val resourceId: String abstract val resourceId: String
abstract override val md5: ByteArray abstract val md5: ByteArray
abstract override val filepath: String abstract val filepath: String
abstract val fileLength: Int abstract val fileLength: Int
abstract val height: Int abstract val height: Int
abstract val width: Int abstract val width: Int
open val bizType: Int get() = 0 open val bizType: Int get() = 0
open val imageType: Int get() = 1000 open val imageType: Int get() = 1000
abstract val fileId: Int
open val downloadPath: String get() = resourceId open val downloadPath: String get() = resourceId
open val origin: Int get()= 1 open val original: Int get() = 1
open val signature: ByteArray get() = md5
open val fileType: Int get()= 66 override val miraiImageId: String get() = resourceId
override fun toString(): String { override fun toString(): String {
return "[NotOnlineImage $resourceId]" return "[NotOnlineImage $resourceId]"
...@@ -139,7 +164,8 @@ data class NotOnlineImageFromFile( ...@@ -139,7 +164,8 @@ data class NotOnlineImageFromFile(
override val width: Int, override val width: Int,
override val bizType: Int = 0, override val bizType: Int = 0,
override val imageType: Int = 1000, override val imageType: Int = 1000,
override val downloadPath: String = resourceId override val downloadPath: String = resourceId,
override val fileId: Int
) : NotOnlineImage() { ) : NotOnlineImage() {
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
......
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