mirror of
https://github.com/mamoe/mirai.git
synced 2025-02-07 15:56:57 +08:00
Fix image
This commit is contained in:
parent
c83bf64a8a
commit
f244a12b8b
@ -4,6 +4,7 @@ import net.mamoe.mirai.contact.*
|
|||||||
import net.mamoe.mirai.data.FriendNameRemark
|
import net.mamoe.mirai.data.FriendNameRemark
|
||||||
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.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.message.data.NotOnlineImageFromFile
|
||||||
@ -206,14 +207,24 @@ internal class GroupImpl(
|
|||||||
}
|
}
|
||||||
socket.close()
|
socket.close()
|
||||||
val resourceId = image.calculateImageResourceId()
|
val resourceId = image.calculateImageResourceId()
|
||||||
return NotOnlineImageFromFile(
|
|
||||||
resourceId = resourceId,
|
return CustomFaceFromFile(
|
||||||
md5 = image.md5,
|
md5 = image.md5,
|
||||||
filepath = resourceId,
|
filepath = resourceId,
|
||||||
fileLength = image.inputSize.toInt(),
|
fileId = response.fileId.toInt(),
|
||||||
|
fileType = 66, // ?
|
||||||
height = image.height,
|
height = image.height,
|
||||||
width = image.width,
|
width = image.width,
|
||||||
imageType = image.imageType
|
imageType = image.imageType,
|
||||||
|
bizType = 0,
|
||||||
|
serverIp = response.uploadIpList.first(),
|
||||||
|
serverPort = response.uploadPortList.first(),
|
||||||
|
signature = image.md5,
|
||||||
|
size = image.inputSize.toInt(),
|
||||||
|
useful = 1,
|
||||||
|
source = 200,
|
||||||
|
origin = 1,
|
||||||
|
pbReserve = byteArrayOf(0x78, 0x02)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -140,8 +140,8 @@ internal class stTroopMemberInfo(
|
|||||||
@SerialId(3) val gender: Byte,
|
@SerialId(3) val gender: Byte,
|
||||||
@SerialId(4) val nick: String = "",
|
@SerialId(4) val nick: String = "",
|
||||||
@SerialId(5) val status: Byte = 20,
|
@SerialId(5) val status: Byte = 20,
|
||||||
@SerialId(6) val sShowName: String? = "",
|
@SerialId(6) val sShowName: String? = null,
|
||||||
@SerialId(8) val sName: String? = "",
|
@SerialId(8) val sName: String? = null,
|
||||||
@SerialId(9) val cGender: Byte? = null,
|
@SerialId(9) val cGender: Byte? = null,
|
||||||
@SerialId(10) val sPhone: String? = "",
|
@SerialId(10) val sPhone: String? = "",
|
||||||
@SerialId(11) val sEmail: String? = "",
|
@SerialId(11) val sEmail: String? = "",
|
||||||
|
@ -40,6 +40,7 @@ internal class OnlinePush {
|
|||||||
|
|
||||||
val group = bot.getGroup(pbPushMsg.msg.msgHead.groupInfo!!.groupCode)
|
val group = bot.getGroup(pbPushMsg.msg.msgHead.groupInfo!!.groupCode)
|
||||||
|
|
||||||
|
// println(pbPushMsg.msg.msgBody.richText.contentToString())
|
||||||
val flags = extraInfo?.flags ?: 0
|
val flags = extraInfo?.flags ?: 0
|
||||||
return GroupMessageOrNull(
|
return GroupMessageOrNull(
|
||||||
GroupMessage(
|
GroupMessage(
|
||||||
|
@ -1,9 +1,23 @@
|
|||||||
package net.mamoe.mirai.qqandroid.utils
|
package net.mamoe.mirai.qqandroid.utils
|
||||||
|
|
||||||
import net.mamoe.mirai.data.ImageLink
|
import kotlinx.io.core.readUInt
|
||||||
import net.mamoe.mirai.message.data.*
|
import net.mamoe.mirai.message.data.*
|
||||||
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.ImMsgBody
|
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.ImMsgBody
|
||||||
|
import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||||
|
import net.mamoe.mirai.utils.io.discardExact
|
||||||
import net.mamoe.mirai.utils.io.hexToBytes
|
import net.mamoe.mirai.utils.io.hexToBytes
|
||||||
|
import net.mamoe.mirai.utils.io.read
|
||||||
|
import net.mamoe.mirai.utils.io.toByteArray
|
||||||
|
|
||||||
|
private val AT_BUF_1 = byteArrayOf(0x00, 0x01, 0x00, 0x00, 0x00, 0x0A, 0x00)
|
||||||
|
private val AT_BUF_2 = ByteArray(2)
|
||||||
|
|
||||||
|
internal fun At.toJceData(): ImMsgBody.Text {
|
||||||
|
return ImMsgBody.Text(
|
||||||
|
str = this.toString(),
|
||||||
|
attr6Buf = AT_BUF_1 + this.target.toInt().toByteArray() + AT_BUF_2
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
internal fun NotOnlineImageFromFile.toJceData(): ImMsgBody.NotOnlineImage {
|
internal fun NotOnlineImageFromFile.toJceData(): ImMsgBody.NotOnlineImage {
|
||||||
return ImMsgBody.NotOnlineImage(
|
return ImMsgBody.NotOnlineImage(
|
||||||
@ -36,6 +50,7 @@ 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,
|
||||||
pbReserve = this.pbReserve
|
pbReserve = this.pbReserve
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -116,9 +131,7 @@ internal fun MessageChain.toRichTextElems(): MutableList<ImMsgBody.Elem> {
|
|||||||
this.forEach {
|
this.forEach {
|
||||||
when (it) {
|
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 At -> elements.add(ImMsgBody.Elem(text = it.toJceData()))
|
||||||
|
|
||||||
}
|
|
||||||
is CustomFaceFromFile -> elements.add(ImMsgBody.Elem(customFace = it.toJceData()))
|
is CustomFaceFromFile -> elements.add(ImMsgBody.Elem(customFace = it.toJceData()))
|
||||||
is CustomFaceFromServer -> elements.add(ImMsgBody.Elem(customFace = it.delegate))
|
is CustomFaceFromServer -> elements.add(ImMsgBody.Elem(customFace = it.delegate))
|
||||||
is NotOnlineImageFromServer -> elements.add(ImMsgBody.Elem(notOnlineImage = it.delegate))
|
is NotOnlineImageFromServer -> elements.add(ImMsgBody.Elem(notOnlineImage = it.delegate))
|
||||||
@ -152,33 +165,25 @@ 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 pbReserve: ByteArray get() = delegate.pbReserve
|
override val pbReserve: ByteArray get() = delegate.pbReserve
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class NotOnlineImageFromServer(
|
internal class NotOnlineImageFromServer(
|
||||||
internal val delegate: ImMsgBody.NotOnlineImage
|
internal val delegate: ImMsgBody.NotOnlineImage
|
||||||
) : NotOnlineImage() {
|
) : NotOnlineImage() {
|
||||||
override val resourceId: String
|
override val resourceId: String get() = delegate.resId
|
||||||
get() = delegate.resId
|
override val md5: ByteArray get() = delegate.picMd5
|
||||||
override val md5: ByteArray
|
override val filepath: String get() = delegate.filePath
|
||||||
get() = delegate.picMd5
|
override val fileLength: Int get() = delegate.fileLen
|
||||||
override val filepath: String
|
override val height: Int get() = delegate.picHeight
|
||||||
get() = delegate.filePath
|
override val width: Int get() = delegate.picWidth
|
||||||
override val fileLength: Int
|
override val bizType: Int get() = delegate.bizType
|
||||||
get() = delegate.fileLen
|
override val imageType: Int get() = delegate.imgType
|
||||||
override val height: Int
|
override val downloadPath: String get() = delegate.downloadPath
|
||||||
get() = delegate.picHeight
|
|
||||||
override val width: Int
|
|
||||||
get() = delegate.picWidth
|
|
||||||
override val bizType: Int
|
|
||||||
get() = delegate.bizType
|
|
||||||
override val imageType: Int
|
|
||||||
get() = delegate.imgType
|
|
||||||
override val downloadPath: String
|
|
||||||
get() = delegate.downloadPath
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@UseExperimental(ExperimentalUnsignedTypes::class, MiraiInternalAPI::class)
|
||||||
internal fun ImMsgBody.RichText.toMessageChain(): MessageChain {
|
internal fun ImMsgBody.RichText.toMessageChain(): MessageChain {
|
||||||
val message = MessageChain(initialCapacity = elems.size)
|
val message = MessageChain(initialCapacity = elems.size)
|
||||||
|
|
||||||
@ -186,12 +191,17 @@ internal fun ImMsgBody.RichText.toMessageChain(): MessageChain {
|
|||||||
when {
|
when {
|
||||||
it.notOnlineImage != null -> message.add(NotOnlineImageFromServer(it.notOnlineImage))
|
it.notOnlineImage != null -> message.add(NotOnlineImageFromServer(it.notOnlineImage))
|
||||||
it.customFace != null -> message.add(CustomFaceFromServer(it.customFace))
|
it.customFace != null -> message.add(CustomFaceFromServer(it.customFace))
|
||||||
it.text != null -> message.add(it.text.str.toMessage())
|
it.text != null -> {
|
||||||
|
if (it.text.attr6Buf.isEmpty()) {
|
||||||
|
message.add(it.text.str.toMessage())
|
||||||
|
} else {
|
||||||
|
//00 01 00 00 00 0A 00 3E 03 3F A2 00 00
|
||||||
|
val id = it.text.attr6Buf.read { discardExact(7); readUInt().toLong() }
|
||||||
|
message.add(At(id, it.text.str))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return message
|
return message
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal inline class ImageLinkQQA(override val original: String) : ImageLink
|
|
@ -6,6 +6,7 @@ import kotlinx.io.core.ByteReadPacket
|
|||||||
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
|
||||||
|
import net.mamoe.mirai.contact.Member
|
||||||
import net.mamoe.mirai.contact.QQ
|
import net.mamoe.mirai.contact.QQ
|
||||||
import net.mamoe.mirai.data.EventPacket
|
import net.mamoe.mirai.data.EventPacket
|
||||||
import net.mamoe.mirai.event.events.BotEvent
|
import net.mamoe.mirai.event.events.BotEvent
|
||||||
@ -19,6 +20,7 @@ import kotlin.jvm.JvmName
|
|||||||
@UseExperimental(MiraiInternalAPI::class)
|
@UseExperimental(MiraiInternalAPI::class)
|
||||||
expect abstract class MessagePacket<TSender : QQ, TSubject : Contact>(bot: Bot) : MessagePacketBase<TSender, TSubject>
|
expect abstract class MessagePacket<TSender : QQ, TSubject : Contact>(bot: Bot) : MessagePacketBase<TSender, TSubject>
|
||||||
|
|
||||||
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
@MiraiInternalAPI
|
@MiraiInternalAPI
|
||||||
abstract class MessagePacketBase<TSender : QQ, TSubject : Contact>(_bot: Bot) : EventPacket, BotEvent() {
|
abstract class MessagePacketBase<TSender : QQ, TSubject : Contact>(_bot: Bot) : EventPacket, BotEvent() {
|
||||||
override val bot: Bot by _bot.unsafeWeakRef()
|
override val bot: Bot by _bot.unsafeWeakRef()
|
||||||
@ -69,6 +71,8 @@ abstract class MessagePacketBase<TSender : QQ, TSubject : Contact>(_bot: Bot) :
|
|||||||
suspend inline fun Message.send() = this.sendTo(subject)
|
suspend inline fun Message.send() = this.sendTo(subject)
|
||||||
suspend inline fun String.send() = this.toMessage().sendTo(subject)
|
suspend inline fun String.send() = this.toMessage().sendTo(subject)
|
||||||
|
|
||||||
|
inline fun QQ.at(): At = At(this as Member)
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region Image download
|
// region Image download
|
||||||
|
@ -2,16 +2,18 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai.message.data
|
package net.mamoe.mirai.message.data
|
||||||
|
|
||||||
import net.mamoe.mirai.contact.QQ
|
import net.mamoe.mirai.contact.Member
|
||||||
|
import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* At 一个人. 只能发送给一个群.
|
* At 一个人. 只能发送给一个群.
|
||||||
*/
|
*/
|
||||||
inline class At(val target: Long) : Message {
|
class At @MiraiInternalAPI constructor(val target: Long, val display: String) : Message {
|
||||||
constructor(target: QQ) : this(target.id)
|
@UseExperimental(MiraiInternalAPI::class)
|
||||||
|
constructor(member: Member) : this(member.id, member.groupCard)
|
||||||
|
|
||||||
override fun toString(): String = "[@$target]" // TODO: 2019/11/25 使用群名称进行 at. 因为手机端只会显示这个文字
|
override fun toString(): String = display
|
||||||
|
|
||||||
companion object Key : Message.Key<At>
|
companion object Key : Message.Key<At>
|
||||||
|
|
||||||
@ -24,4 +26,4 @@ inline class At(val target: Long) : Message {
|
|||||||
* At 这个成员
|
* At 这个成员
|
||||||
*/
|
*/
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
inline fun QQ.at(): At = At(this)
|
inline fun Member.at(): At = At(this)
|
@ -31,6 +31,7 @@ abstract class CustomFace : Image() {
|
|||||||
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
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "[CustomFace]"
|
return "[CustomFace]"
|
||||||
@ -57,6 +58,7 @@ data class CustomFaceFromFile(
|
|||||||
override val height: Int,
|
override val height: Int,
|
||||||
override val source: Int,
|
override val source: Int,
|
||||||
override val size: Int,
|
override val size: Int,
|
||||||
|
override val origin: Int,
|
||||||
override val pbReserve: ByteArray
|
override val pbReserve: ByteArray
|
||||||
) : CustomFace() {
|
) : CustomFace() {
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
@ -79,6 +81,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 (!pbReserve.contentEquals(other.pbReserve)) return false
|
if (!pbReserve.contentEquals(other.pbReserve)) return false
|
||||||
|
|
||||||
return true
|
return true
|
||||||
@ -114,6 +117,9 @@ abstract class NotOnlineImage : Image() {
|
|||||||
open val bizType: Int get() = 0
|
open val bizType: Int get() = 0
|
||||||
open val imageType: Int get() = 1000
|
open val imageType: Int get() = 1000
|
||||||
open val downloadPath: String get() = resourceId
|
open val downloadPath: String get() = resourceId
|
||||||
|
open val origin: Int get()= 1
|
||||||
|
open val signature: ByteArray get() = md5
|
||||||
|
open val fileType: Int get()= 66
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "[NotOnlineImage $resourceId]"
|
return "[NotOnlineImage $resourceId]"
|
||||||
|
@ -39,7 +39,7 @@ class ExternalImage(
|
|||||||
): ExternalImage = ExternalImage(width, height, md5, format, data, data.remaining, filename)
|
): ExternalImage = ExternalImage(width, height, md5, format, data, data.remaining, filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val format: String = when (val it =imageFormat.toLowerCase()) {
|
private val format: String = when (val it = imageFormat.toLowerCase()) {
|
||||||
"jpeg" -> "jpg" //必须转换
|
"jpeg" -> "jpg" //必须转换
|
||||||
else -> it
|
else -> it
|
||||||
}
|
}
|
||||||
@ -56,7 +56,7 @@ class ExternalImage(
|
|||||||
* SHARPP: 1004
|
* SHARPP: 1004
|
||||||
*/
|
*/
|
||||||
val imageType: Int
|
val imageType: Int
|
||||||
get() = when (format){
|
get() = when (format) {
|
||||||
"jpg" -> 1000
|
"jpg" -> 1000
|
||||||
"png" -> 1001
|
"png" -> 1001
|
||||||
"webp" -> 1002
|
"webp" -> 1002
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
apply plugin: "kotlin"
|
apply plugin: "kotlin"
|
||||||
apply plugin: "java"
|
apply plugin: "java"
|
||||||
apply plugin: "application"
|
apply plugin: "application"
|
||||||
|
apply plugin: "kotlinx-serialization"
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation files("../../mirai-core-qqandroid/build/classes/kotlin/jvm/main") // IDE bug
|
implementation files("../../mirai-core-qqandroid/build/classes/kotlin/jvm/main") // IDE bug
|
||||||
|
@ -9,6 +9,7 @@ import kotlinx.coroutines.launch
|
|||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import net.mamoe.mirai.Bot
|
import net.mamoe.mirai.Bot
|
||||||
import net.mamoe.mirai.alsoLogin
|
import net.mamoe.mirai.alsoLogin
|
||||||
|
import net.mamoe.mirai.contact.Member
|
||||||
import net.mamoe.mirai.contact.MemberPermission
|
import net.mamoe.mirai.contact.MemberPermission
|
||||||
import net.mamoe.mirai.event.Subscribable
|
import net.mamoe.mirai.event.Subscribable
|
||||||
import net.mamoe.mirai.event.events.ReceiveFriendAddRequestEvent
|
import net.mamoe.mirai.event.events.ReceiveFriendAddRequestEvent
|
||||||
@ -67,7 +68,7 @@ suspend fun main() {
|
|||||||
always {
|
always {
|
||||||
}
|
}
|
||||||
|
|
||||||
case("at me") { At(sender).reply() }
|
case("at me") { At(sender as Member).reply() }
|
||||||
// 等同于 "at me" reply { At(sender) }
|
// 等同于 "at me" reply { At(sender) }
|
||||||
|
|
||||||
"你好" reply "你好!"
|
"你好" reply "你好!"
|
||||||
|
@ -5,7 +5,6 @@ import kotlinx.coroutines.GlobalScope
|
|||||||
import net.mamoe.mirai.event.events.BotLoginSucceedEvent
|
import net.mamoe.mirai.event.events.BotLoginSucceedEvent
|
||||||
import net.mamoe.mirai.event.subscribeAlways
|
import net.mamoe.mirai.event.subscribeAlways
|
||||||
import net.mamoe.mirai.event.subscribeMessages
|
import net.mamoe.mirai.event.subscribeMessages
|
||||||
import net.mamoe.mirai.message.data.At
|
|
||||||
import net.mamoe.mirai.plugin.PluginBase
|
import net.mamoe.mirai.plugin.PluginBase
|
||||||
import net.mamoe.mirai.utils.MiraiExperimentalAPI
|
import net.mamoe.mirai.utils.MiraiExperimentalAPI
|
||||||
|
|
||||||
@ -19,7 +18,7 @@ class ImageSenderMain : PluginBase() {
|
|||||||
this.bot.subscribeMessages {
|
this.bot.subscribeMessages {
|
||||||
|
|
||||||
case("at me") {
|
case("at me") {
|
||||||
(At(sender) + " ? ").reply()
|
reply(sender.at() + " ? ")
|
||||||
}
|
}
|
||||||
|
|
||||||
(contains("image") or contains("图")) {
|
(contains("image") or contains("图")) {
|
||||||
|
Loading…
Reference in New Issue
Block a user