Add more MessageProtocolTest

This commit is contained in:
Him188 2022-05-16 20:57:07 +01:00
parent b4f042ae1b
commit 08d1fc1f38
12 changed files with 1062 additions and 37 deletions

View File

@ -64,25 +64,25 @@ public data class MusicShare(
// Kotlin
MusicShare(
kind = MusicKind.NeteaseCloudMusic,
title = "ファッション",
summary = "rinahamu/Yunomi",
brief = "",
jumpUrl = "http://music.163.com/song/1338728297/?userid=324076307",
pictureUrl = "http://p2.music.126.net/y19E5SadGUmSR8SZxkrNtw==/109951163785855539.jpg",
musicUrl = "http://music.163.com/song/media/outer/url?id=1338728297&userid=324076307"
kind = NeteaseCloudMusic,
title = "ジェリーフィッシュ",
summary = "Yunomi/ローラーガール",
jumpUrl = "https://y.music.163.com/m/song?id=562591636&uct=QK0IOc%2FSCIO8gBNG%2Bwcbsg%3D%3D&app_version=8.7.46",
pictureUrl = "http://p1.music.126.net/KaYSb9oYQzhl2XBeJcj8Rg==/109951165125601702.jpg",
musicUrl = "http://music.163.com/song/media/outer/url?id=562591636&&sc=wmv&tn=",
brief = "[分享]ジェリーフィッシュ",
)
// Java
new MusicShare(
MusicKind.NeteaseCloudMusic,
"ファッション",
"rinahamu/Yunomi",
"http://music.163.com/song/1338728297/?userid=324076307",
"http://p2.music.126.net/y19E5SadGUmSR8SZxkrNtw==/109951163785855539.jpg",
"http://music.163.com/song/media/outer/url?id=1338728297&userid=324076307"
NeteaseCloudMusic,
"ジェリーフィッシュ",
"Yunomi/ローラーガール",
"https://y.music.163.com/m/song?id=562591636&uct=QK0IOc%2FSCIO8gBNG%2Bwcbsg%3D%3D&app_version=8.7.46",
"http://p1.music.126.net/KaYSb9oYQzhl2XBeJcj8Rg==/109951165125601702.jpg",
"http://music.163.com/song/media/outer/url?id=562591636&&sc=wmv&tn=",
"[分享]ジェリーフィッシュ",
);
*/
public constructor(

View File

@ -11,6 +11,10 @@ package net.mamoe.mirai.internal.message.protocol
import net.mamoe.mirai.Bot
import net.mamoe.mirai.contact.ContactOrBot
import net.mamoe.mirai.internal.message.DeepMessageRefiner.refineDeep
import net.mamoe.mirai.internal.message.EmptyRefineContext
import net.mamoe.mirai.internal.message.LightMessageRefiner.refineLight
import net.mamoe.mirai.internal.message.RefineContext
import net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody
import net.mamoe.mirai.internal.utils.runCoroutineInPlace
import net.mamoe.mirai.message.data.*
@ -50,6 +54,23 @@ internal interface MessageProtocolFacade {
companion object INSTANCE : MessageProtocolFacade by MessageProtocolFacadeImpl()
}
internal fun MessageProtocolFacade.decodeAndRefineLight(
elements: List<ImMsgBody.Elem>,
groupIdOrZero: Long,
messageSourceKind: MessageSourceKind,
bot: Bot,
refineContext: RefineContext = EmptyRefineContext
): MessageChain = decode(elements, groupIdOrZero, messageSourceKind, bot).refineLight(bot, refineContext)
internal suspend fun MessageProtocolFacade.decodeAndRefineDeep(
elements: List<ImMsgBody.Elem>,
groupIdOrZero: Long,
messageSourceKind: MessageSourceKind,
bot: Bot,
refineContext: RefineContext = EmptyRefineContext
): MessageChain = decode(elements, groupIdOrZero, messageSourceKind, bot).refineDeep(bot, refineContext)
internal class MessageProtocolFacadeImpl(
protocols: Iterable<MessageProtocol> = ServiceLoader.load(MessageProtocol::class.java)
) : MessageProtocolFacade {

View File

@ -9,8 +9,10 @@
package net.mamoe.mirai.internal.message.protocol.impl
import net.mamoe.mirai.internal.message.protocol.*
import net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody
import net.mamoe.mirai.internal.message.protocol.MessageEncoder
import net.mamoe.mirai.internal.message.protocol.MessageEncoderContext
import net.mamoe.mirai.internal.message.protocol.MessageProtocol
import net.mamoe.mirai.internal.message.protocol.ProcessorCollector
import net.mamoe.mirai.message.data.MusicShare
import net.mamoe.mirai.message.data.PlainText
import net.mamoe.mirai.message.data.content
@ -18,6 +20,7 @@ import net.mamoe.mirai.message.data.content
internal class MusicShareProtocol : MessageProtocol() {
override fun ProcessorCollector.collectProcessorsImpl() {
add(Encoder())
// no decoder. refined from LightApp
// add(Decoder())
}
@ -29,11 +32,4 @@ internal class MusicShareProtocol : MessageProtocol() {
processAlso(PlainText(data.content))
}
}
private class Decoder : MessageDecoder {
override suspend fun MessageDecoderContext.process(data: ImMsgBody.Elem) {
}
}
}

View File

@ -30,7 +30,7 @@ import kotlin.contracts.contract
internal abstract class AbstractMessageProtocolTest : AbstractMockNetworkHandlerTest(), GroupExtensions {
protected abstract val protocol: MessageProtocol
protected abstract val protocols: Array<out MessageProtocol>
protected var defaultTarget: ContactOrBot? = null
private var decoderLoggerEnabled = false
@ -60,12 +60,12 @@ internal abstract class AbstractMessageProtocolTest : AbstractMockNetworkHandler
protected fun doEncoderChecks(
expectedStruct: List<ImMsgBody.Elem>,
protocol: MessageProtocol,
protocols: Array<out MessageProtocol>,
encode: MessageProtocolFacade.() -> List<ImMsgBody.Elem>
) {
asserter.assertEquals(
expectedStruct,
facadeOf(protocol).encode(),
facadeOf(*protocols).encode(),
message = "Failed to check single Protocol"
)
asserter.assertEquals(
@ -87,12 +87,12 @@ internal abstract class AbstractMessageProtocolTest : AbstractMockNetworkHandler
protected fun doDecoderChecks(
expectedChain: MessageChain,
protocol: MessageProtocol = this.protocol,
protocols: Array<out MessageProtocol> = this.protocols,
decode: MessageProtocolFacade.() -> MessageChain
) {
asserter.assertEquals(
expectedChain.toList(),
facadeOf(protocol).decode().toList(),
facadeOf(*protocols).decode().toList(),
message = "Failed to check single Protocol"
)
asserter.assertEquals(
@ -104,9 +104,9 @@ internal abstract class AbstractMessageProtocolTest : AbstractMockNetworkHandler
protected fun doEncoderChecks(
vararg expectedStruct: ImMsgBody.Elem,
protocol: MessageProtocol = this.protocol,
protocols: Array<out MessageProtocol> = this.protocols,
encode: MessageProtocolFacade.() -> List<ImMsgBody.Elem>
): Unit = doEncoderChecks(expectedStruct.toList(), protocol, encode)
): Unit = doEncoderChecks(expectedStruct.toList(), protocols, encode)
inner class ChecksBuilder {
@ -175,7 +175,7 @@ internal abstract class AbstractMessageProtocolTest : AbstractMockNetworkHandler
@OptIn(ExperimentalCoroutinesApi::class)
protected open fun Deferred<ChecksConfiguration>.doEncoderChecks() {
val config = this.getCompleted()
doEncoderChecks(config.elems, protocol) {
doEncoderChecks(config.elems, protocols) {
encode(
config.messageChain,
config.target,
@ -188,8 +188,8 @@ internal abstract class AbstractMessageProtocolTest : AbstractMockNetworkHandler
@OptIn(ExperimentalCoroutinesApi::class)
protected open fun Deferred<ChecksConfiguration>.doDecoderChecks() {
val config = this.getCompleted()
doDecoderChecks(config.messageChain, protocol) {
decode(config.elems, config.groupIdOrZero, config.messageSourceKind, bot)
doDecoderChecks(config.messageChain, protocols) {
decodeAndRefineLight(config.elems, config.groupIdOrZero, config.messageSourceKind, bot)
}
}

View File

@ -10,6 +10,7 @@
package net.mamoe.mirai.internal.message.protocol.impl
import net.mamoe.mirai.internal.message.protocol.MessageProtocol
import net.mamoe.mirai.internal.message.protocol.decodeAndRefineLight
import net.mamoe.mirai.message.data.Face
import net.mamoe.mirai.message.data.MessageSourceKind
import net.mamoe.mirai.message.data.messageChainOf
@ -17,7 +18,7 @@ import net.mamoe.mirai.utils.hexToBytes
import org.junit.jupiter.api.Test
internal class FaceProtocolTest : AbstractMessageProtocolTest() {
override val protocol: MessageProtocol = FaceProtocol()
override val protocols: Array<out MessageProtocol> = arrayOf(FaceProtocol())
@Test
fun `can encode`() {
@ -42,7 +43,7 @@ internal class FaceProtocolTest : AbstractMessageProtocolTest() {
doDecoderChecks(
messageChainOf(Face(Face.YIN_XIAN)),
) {
decode(
decodeAndRefineLight(
listOf(
net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
face = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Face(

View File

@ -0,0 +1,565 @@
/*
* Copyright 2019-2022 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
*/
package net.mamoe.mirai.internal.message.protocol.impl
import net.mamoe.mirai.contact.MemberPermission
import net.mamoe.mirai.internal.message.protocol.MessageProtocol
import net.mamoe.mirai.message.data.Image
import net.mamoe.mirai.message.data.ImageType
import net.mamoe.mirai.utils.hexToBytes
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
internal class ImageProtocolTest : AbstractMessageProtocolTest() {
override val protocols: Array<out MessageProtocol> = arrayOf(ImageProtocol())
@BeforeEach
fun `init group`() {
defaultTarget = bot.addGroup(123, 1230003).apply {
addMember(1230003, "user3", MemberPermission.OWNER)
}
}
///////////////////////////////////////////////////////////////////////////
// receive from macOS client
///////////////////////////////////////////////////////////////////////////
@Test
fun `group Image receive from macOS`() {
buildChecks {
elem(
net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
customFace = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.CustomFace(
filePath = "{A7CBB529-43A2-127C-E426-59D29BAA8515}.jpg",
fileId = -1866484636,
useful = 1,
picMd5 = "A7 CB B5 29 43 A2 12 7C E4 26 59 D2 9B AA 85 15".hexToBytes(),
thumbUrl = "/gchatpic_new/123456/12345678-2428482660-A7CBB52943A2127CE42659D29BAA8515/198?term=2",
origUrl = "/gchatpic_new/123456/12345678-2428482660-A7CBB52943A2127CE42659D29BAA8515/0?term=2",
width = 904,
height = 1214,
size = 170426,
thumbWidth = 147,
thumbHeight = 198,
_400Url = "/gchatpic_new/123456/12345678-2428482660-A7CBB52943A2127CE42659D29BAA8515/400?term=2",
_400Width = 285,
_400Height = 384,
),
)
)
message(Image("{A7CBB529-43A2-127C-E426-59D29BAA8515}.jpg") {
width = 904
height = 1214
size = 170426
type = ImageType.JPG
isEmoji = false
})
targetGroup()
useOrdinaryEquality()
}.doDecoderChecks()
}
@Test
fun `friend Image receive from macOS`() {
buildChecks {
elem(
net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
notOnlineImage = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.NotOnlineImage(
filePath = "{A7CBB529-43A2-127C-E426-59D29BAA8515}.jpg",
fileLen = 170426,
downloadPath = "/123456-306012740-A7CBB52943A2127CE42659D29BAA8515",
oldVerSendFile = "16 20 31 32 32 31 30 31 31 31 31 41 42 20 20 20 20 31 37 30 34 32 36 6B 7B 41 37 43 42 42 35 32 39 2D 34 33 41 32 2D 31 32 37 43 2D 45 34 32 36 2D 35 39 44 32 39 42 41 41 38 35 31 35 7D 2E 6A 70 67 77 2F 31 30 34 30 34 30 30 32 39 30 2D 33 30 36 30 31 32 37 34 30 2D 41 37 43 42 42 35 32 39 34 33 41 32 31 32 37 43 45 34 32 36 35 39 44 32 39 42 41 41 38 35 31 35 41".hexToBytes(),
picMd5 = "A7 CB B5 29 43 A2 12 7C E4 26 59 D2 9B AA 85 15".hexToBytes(),
picHeight = 1214,
picWidth = 904,
resId = "/123456-306012740-A7CBB52943A2127CE42659D29BAA8515",
thumbUrl = "/offpic_new/123456//123456-306012740-A7CBB52943A2127CE42659D29BAA8515/198?term=2",
origUrl = "/offpic_new/123456//123456-306012740-A7CBB52943A2127CE42659D29BAA8515/0?term=2",
thumbWidth = 147,
thumbHeight = 198,
_400Url = "/offpic_new/123456//123456-306012740-A7CBB52943A2127CE42659D29BAA8515/400?term=2",
_400Width = 285,
_400Height = 384,
),
)
)
message(Image("{A7CBB529-43A2-127C-E426-59D29BAA8515}.jpg") {
width = 904
height = 1214
size = 170426
type = ImageType.JPG
isEmoji = false
})
targetFriend()
}.doDecoderChecks()
}
///////////////////////////////////////////////////////////////////////////
// receive from Android
///////////////////////////////////////////////////////////////////////////
@Test
fun `group Image receive from Android`() {
buildChecks {
elem(
net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
customFace = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.CustomFace(
filePath = "A7CBB52943A2127CE42659D29BAA8515.jpg",
oldData = "15 36 20 38 36 65 41 31 42 61 66 34 35 64 37 38 63 36 66 31 65 39 30 33 66 20 20 20 20 20 20 35 30 57 4A 4B 53 53 71 52 79 61 52 46 42 7A 77 38 34 41 37 43 42 42 35 32 39 34 33 41 32 31 32 37 43 45 34 32 36 35 39 44 32 39 42 41 41 38 35 31 35 2E 6A 70 67 41".hexToBytes(),
fileId = -1354377332,
serverIp = 1864273983,
serverPort = 80,
fileType = 66,
signature = "WJKSSqRyaRFBzw84".toByteArray(), /* 57 4A 4B 53 53 71 52 79 61 52 46 42 7A 77 38 34 */
useful = 1,
picMd5 = "A7 CB B5 29 43 A2 12 7C E4 26 59 D2 9B AA 85 15".hexToBytes(),
thumbUrl = "/gchatpic_new/123456/622457678-2940589964-A7CBB52943A2127CE42659D29BAA8515/198?term=2",
origUrl = "/gchatpic_new/123456/622457678-2940589964-A7CBB52943A2127CE42659D29BAA8515/0?term=2",
imageType = 1000,
width = 904,
height = 1214,
source = 103,
size = 170426,
thumbWidth = 147,
thumbHeight = 198,
_400Url = "/gchatpic_new/123456/622457678-2940589964-A7CBB52943A2127CE42659D29BAA8515/400?term=2",
_400Width = 285,
_400Height = 384,
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 06".hexToBytes(),
),
)
)
message(Image("{A7CBB529-43A2-127C-E426-59D29BAA8515}.jpg") {
width = 904
height = 1214
size = 170426
type = ImageType.JPG
isEmoji = true
})
targetGroup()
useOrdinaryEquality()
}.doDecoderChecks()
}
@Test
fun `friend Image receive from Android`() {
buildChecks {
elem(
net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
notOnlineImage = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.NotOnlineImage(
filePath = "A7CBB52943A2127CE42659D29BAA8515.jpg",
fileLen = 170426,
downloadPath = "/123456-113241016-A7CBB52943A2127CE42659D29BAA8515",
oldVerSendFile = "16 20 31 31 36 31 30 31 30 35 31 41 42 20 20 20 20 31 37 30 34 32 36 65 41 37 43 42 42 35 32 39 34 33 41 32 31 32 37 43 45 34 32 36 35 39 44 32 39 42 41 41 38 35 31 35 2E 6A 70 67 77 2F 31 30 34 30 34 30 30 32 39 30 2D 31 31 33 32 34 31 30 31 36 2D 41 37 43 42 42 35 32 39 34 33 41 32 31 32 37 43 45 34 32 36 35 39 44 32 39 42 41 41 38 35 31 35 41".hexToBytes(),
imgType = 1000,
picMd5 = "A7 CB B5 29 43 A2 12 7C E4 26 59 D2 9B AA 85 15".hexToBytes(),
picHeight = 1214,
picWidth = 904,
resId = "/123456-113241016-A7CBB52943A2127CE42659D29BAA8515",
thumbUrl = "/offpic_new/123456//123456-113241016-A7CBB52943A2127CE42659D29BAA8515/198?term=2",
origUrl = "/offpic_new/123456//123456-113241016-A7CBB52943A2127CE42659D29BAA8515/0?term=2",
bizType = 5,
thumbWidth = 147,
thumbHeight = 198,
_400Url = "/offpic_new/123456//123456-113241016-A7CBB52943A2127CE42659D29BAA8515/400?term=2",
_400Width = 285,
_400Height = 384,
pbReserve = "08 01 10 00 32 00 42 0E 5B E5 8A A8 E7 94 BB E8 A1 A8 E6 83 85 5D 50 00 78 06".hexToBytes(),
),
)
)
message(Image("{A7CBB529-43A2-127C-E426-59D29BAA8515}.jpg") {
width = 904
height = 1214
size = 170426
type = ImageType.JPG
isEmoji = true
})
targetFriend()
useOrdinaryEquality()
}.doDecoderChecks()
}
///////////////////////////////////////////////////////////////////////////
// receive from iOS
///////////////////////////////////////////////////////////////////////////
@Test
fun `group Image receive from iOS`() {
buildChecks {
elem(
net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
notOnlineImage = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.NotOnlineImage(
filePath = "C344D6240014DA35BB63A958BC435134.png",
fileLen = 108536,
downloadPath = "/123456-346835805-C344D6240014DA35BB63A958BC435134",
oldVerSendFile = "16 20 31 31 36 31 30 31 30 35 31 41 42 20 20 20 20 31 30 38 35 33 36 65 43 33 34 34 44 36 32 34 30 30 31 34 44 41 33 35 42 42 36 33 41 39 35 38 42 43 34 33 35 31 33 34 2E 70 6E 67 77 2F 32 36 35 32 33 38 36 32 32 38 2D 33 34 36 38 33 35 38 30 35 2D 43 33 34 34 44 36 32 34 30 30 31 34 44 41 33 35 42 42 36 33 41 39 35 38 42 43 34 33 35 31 33 34 41".hexToBytes(),
imgType = 1000,
picMd5 = "C3 44 D6 24 00 14 DA 35 BB 63 A9 58 BC 43 51 34".hexToBytes(),
picHeight = 1214,
picWidth = 904,
resId = "/123456-346835805-C344D6240014DA35BB63A958BC435134",
thumbUrl = "/offpic_new/123456//123456-346835805-C344D6240014DA35BB63A958BC435134/198?term=2",
origUrl = "/offpic_new/123456//123456-346835805-C344D6240014DA35BB63A958BC435134/0?term=2",
bizType = 4,
thumbWidth = 147,
thumbHeight = 198,
_400Url = "/offpic_new/123456//123456-346835805-C344D6240014DA35BB63A958BC435134/400?term=2",
_400Width = 285,
_400Height = 384,
pbReserve = "08 00 10 00 18 00 50 00 78 04".hexToBytes(),
),
)
)
message(Image("{C344D624-0014-DA35-BB63-A958BC435134}.jpg") {
width = 904
height = 1214
size = 108536
type = ImageType.JPG
isEmoji = false
})
targetGroup()
useOrdinaryEquality()
}.doDecoderChecks()
}
@Test
fun `friend Image receive from iOS`() {
buildChecks {
elem(
net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
notOnlineImage = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.NotOnlineImage(
filePath = "C344D6240014DA35BB63A958BC435134.png",
fileLen = 108536,
downloadPath = "/123455-346835805-C344D6240014DA35BB63A958BC435134",
oldVerSendFile = "16 20 31 31 36 31 30 31 30 35 31 41 42 20 20 20 20 31 30 38 35 33 36 65 43 33 34 34 44 36 32 34 30 30 31 34 44 41 33 35 42 42 36 33 41 39 35 38 42 43 34 33 35 31 33 34 2E 70 6E 67 77 2F 32 36 35 32 33 38 36 32 32 38 2D 33 34 36 38 33 35 38 30 35 2D 43 33 34 34 44 36 32 34 30 30 31 34 44 41 33 35 42 42 36 33 41 39 35 38 42 43 34 33 35 31 33 34 41".hexToBytes(),
imgType = 1000,
picMd5 = "C3 44 D6 24 00 14 DA 35 BB 63 A9 58 BC 43 51 34".hexToBytes(),
picHeight = 1214,
picWidth = 904,
resId = "/123455-346835805-C344D6240014DA35BB63A958BC435134",
thumbUrl = "/offpic_new/123455//123455-346835805-C344D6240014DA35BB63A958BC435134/198?term=2",
origUrl = "/offpic_new/123455//123455-346835805-C344D6240014DA35BB63A958BC435134/0?term=2",
bizType = 4,
thumbWidth = 147,
thumbHeight = 198,
_400Url = "/offpic_new/123455//123455-346835805-C344D6240014DA35BB63A958BC435134/400?term=2",
_400Width = 285,
_400Height = 384,
pbReserve = "08 00 10 00 18 00 50 00 78 04".hexToBytes(),
),
)
)
message(Image("{C344D624-0014-DA35-BB63-A958BC435134}.jpg") {
width = 904
height = 1214
size = 108536
type = ImageType.JPG
isEmoji = false
})
targetFriend()
useOrdinaryEquality()
}.doDecoderChecks()
}
///////////////////////////////////////////////////////////////////////////
// receive from Windows
///////////////////////////////////////////////////////////////////////////
@Test
fun `group Image receive from Windows`() {
buildChecks {
elem(
net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
customFace = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.CustomFace(
filePath = "{C344D624-0014-DA35-BB63-A958BC435134}.jpg",
flag = "00 00 00 00".hexToBytes(),
oldData = "15 36 20 39 32 6B 41 31 43 39 32 65 39 64 35 30 64 34 39 38 64 33 33 37 39 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 43 33 34 34 44 36 32 34 2D 30 30 31 34 2D 44 41 33 35 2D 42 42 36 33 2D 41 39 35 38 42 43 34 33 35 31 33 34 7D 2E 6A 70 67 41".hexToBytes(),
fileId = -1830169331,
serverIp = 1233990521,
serverPort = 80,
fileType = 67,
useful = 1,
picMd5 = "C3 44 D6 24 00 14 DA 35 BB 63 A9 58 BC 43 51 34".hexToBytes(),
thumbUrl = "/gchatpic_new/123456/123456-2464797965-C344D6240014DA35BB63A958BC435134/198?term=2",
origUrl = "/gchatpic_new/123456/123456-2464797965-C344D6240014DA35BB63A958BC435134/0?term=2",
imageType = 1000,
width = 904,
height = 1214,
size = 108536,
thumbWidth = 147,
thumbHeight = 198,
_400Url = "/gchatpic_new/123456/123456-2464797965-C344D6240014DA35BB63A958BC435134/400?term=2",
_400Width = 285,
_400Height = 384,
),
)
)
message(Image("{C344D624-0014-DA35-BB63-A958BC435134}.jpg") {
width = 904
height = 1214
size = 108536
type = ImageType.JPG
isEmoji = false
})
targetGroup()
}.doDecoderChecks()
}
@Test
fun `friend Image receive from Windows`() {
buildChecks {
elem(
net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
notOnlineImage = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.NotOnlineImage(
filePath = "J9R_MJL9@9Z02}QZ0LTTX77.jpg",
fileLen = 108536,
downloadPath = "/123456-2313394132-C344D6240014DA35BB63A958BC435134",
oldVerSendFile = "16 20 31 31 37 31 30 31 30 36 31 43 42 20 20 20 20 31 30 38 35 33 36 65 43 33 34 34 44 36 32 34 30 30 31 34 44 41 33 35 42 42 36 33 41 39 35 38 42 43 34 33 35 31 33 34 2E 6A 70 67 78 2F 33 32 37 39 38 32 36 34 38 34 2D 32 33 31 33 33 39 34 31 33 32 2D 43 33 34 34 44 36 32 34 30 30 31 34 44 41 33 35 42 42 36 33 41 39 35 38 42 43 34 33 35 31 33 34 41".hexToBytes(),
imgType = 1000,
picMd5 = "C3 44 D6 24 00 14 DA 35 BB 63 A9 58 BC 43 51 34".hexToBytes(),
picHeight = 1214,
picWidth = 904,
resId = "/123456-2313394132-C344D6240014DA35BB63A958BC435134",
flag = "00 00 00 00".hexToBytes(),
thumbUrl = "/offpic_new/123456//123456-2313394132-C344D6240014DA35BB63A958BC435134/198?term=2",
origUrl = "/offpic_new/123456//123456-2313394132-C344D6240014DA35BB63A958BC435134/0?term=2",
thumbWidth = 147,
thumbHeight = 198,
_400Url = "/offpic_new/123456//123456-2313394132-C344D6240014DA35BB63A958BC435134/400?term=2",
_400Width = 285,
_400Height = 384,
),
)
)
message(Image("{C344D624-0014-DA35-BB63-A958BC435134}.jpg") {
width = 904
height = 1214
size = 108536
type = ImageType.JPG
isEmoji = false
})
targetFriend()
useOrdinaryEquality()
}.doDecoderChecks()
}
///////////////////////////////////////////////////////////////////////////
// receive from iPadOS
///////////////////////////////////////////////////////////////////////////
@Test
fun `group Image receive from iPadOS`() {
buildChecks {
elem(
net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
customFace = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.CustomFace(
filePath = "{A7CBB529-43A2-127C-E426-59D29BAA8515}.jpg",
oldData = "15 36 20 39 32 6B 41 31 E8 38 63 34 65 39 63 38 39 20 20 20 20 20 20 20 30 20 20 20 20 20 20 20 30 71 76 4A 51 79 6D 7A 37 4D 77 7A 7A 33 6A 74 4E 7B 41 37 43 42 42 35 32 39 2D 34 33 41 32 2D 31 32 37 43 2D 45 34 32 36 2D 35 39 44 32 39 42 41 41 38 35 31 35 7D 2E 6A 70 67 41".hexToBytes(),
fileId = -1941005175,
fileType = -24,
signature = "qvJQymz7Mwzz3jtN".toByteArray(), /* 71 76 4A 51 79 6D 7A 37 4D 77 7A 7A 33 6A 74 4E */
useful = 1,
picMd5 = "A7 CB B5 29 43 A2 12 7C E4 26 59 D2 9B AA 85 15".hexToBytes(),
thumbUrl = "/gchatpic_new/123456/123456-2353962121-A7CBB52943A2127CE42659D29BAA8515/198?term=2",
origUrl = "/gchatpic_new/123456/123456-2353962121-A7CBB52943A2127CE42659D29BAA8515/0?term=2",
imageType = 1000,
width = 904,
height = 1214,
source = 203,
size = 170426,
thumbWidth = 147,
thumbHeight = 198,
_400Url = "/gchatpic_new/123456/123456-2353962121-A7CBB52943A2127CE42659D29BAA8515/400?term=2",
_400Width = 285,
_400Height = 384,
pbReserve = "08 01 10 00 18 00 2A 0C E5 8A A8 E7 94 BB E8 A1 A8 E6 83 85 4A 0E 5B E5 8A A8 E7 94 BB E8 A1 A8 E6 83 85 5D 50 00 78 05".hexToBytes(),
),
)
)
message(Image("{A7CBB529-43A2-127C-E426-59D29BAA8515}.jpg") {
width = 904
height = 1214
size = 170426
type = ImageType.JPG
isEmoji = true
})
targetGroup()
}.doDecoderChecks()
}
@Test
fun `friend Image receive from iPadOS`() {
buildChecks {
elem(
net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
notOnlineImage = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.NotOnlineImage(
filePath = "A7CBB52943A2127CE42659D29BAA8515.png",
fileLen = 170426,
downloadPath = "/1040400290-197707644-A7CBB52943A2127CE42659D29BAA8515",
oldVerSendFile = "16 20 31 31 36 31 30 31 30 35 31 41 42 20 20 20 20 31 37 30 34 32 36 65 41 37 43 42 42 35 32 39 34 33 41 32 31 32 37 43 45 34 32 36 35 39 44 32 39 42 41 41 38 35 31 35 2E 70 6E 67 77 2F 31 30 34 30 34 30 30 32 39 30 2D 31 39 37 37 30 37 36 34 34 2D 41 37 43 42 42 35 32 39 34 33 41 32 31 32 37 43 45 34 32 36 35 39 44 32 39 42 41 41 38 35 31 35 41".hexToBytes(),
imgType = 1000,
picMd5 = "A7 CB B5 29 43 A2 12 7C E4 26 59 D2 9B AA 85 15".hexToBytes(),
picHeight = 1214,
picWidth = 904,
resId = "/123456-197707644-A7CBB52943A2127CE42659D29BAA8515",
thumbUrl = "/offpic_new/123456//123456-197707644-A7CBB52943A2127CE42659D29BAA8515/198?term=2",
origUrl = "/offpic_new/123456//123456-197707644-A7CBB52943A2127CE42659D29BAA8515/0?term=2",
bizType = 5,
thumbWidth = 147,
thumbHeight = 198,
_400Url = "/offpic_new/123456//123456-197707644-A7CBB52943A2127CE42659D29BAA8515/400?term=2",
_400Width = 285,
_400Height = 384,
pbReserve = "08 01 10 00 18 00 2A 0C E5 8A A8 E7 94 BB E8 A1 A8 E6 83 85 42 0E 5B E5 8A A8 E7 94 BB E8 A1 A8 E6 83 85 5D 50 00 78 05".hexToBytes(),
),
)
)
message(Image("{A7CBB529-43A2-127C-E426-59D29BAA8515}.jpg") {
width = 904
height = 1214
size = 170426
type = ImageType.JPG
isEmoji = true
})
targetFriend()
useOrdinaryEquality()
}.doDecoderChecks()
}
///////////////////////////////////////////////////////////////////////////
// send without dimension
///////////////////////////////////////////////////////////////////////////
@Test
fun `group Image send without dimension`() {
buildChecks {
elem(
net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
customFace = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.CustomFace(
filePath = "{A7CBB529-43A2-127C-E426-59D29BAA8515}.jpg",
flag = byteArrayOf(0, 0, 0, 0),
fileType = 66,
useful = 1,
picMd5 = "A7 CB B5 29 43 A2 12 7C E4 26 59 D2 9B AA 85 15".hexToBytes(),
bizType = 5,
imageType = 1000,
width = 1,
height = 1,
origin = 1,
),
)
)
message(Image("{A7CBB529-43A2-127C-E426-59D29BAA8515}.jpg"))
targetGroup()
}.doEncoderChecks()
}
@Test
fun `friend Image send without dimension`() {
buildChecks {
elem(
net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
notOnlineImage = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.NotOnlineImage(
filePath = "{A7CBB529-43A2-127C-E426-59D29BAA8515}.jpg",
downloadPath = "/000000000-000000000-A7CBB52943A2127CE42659D29BAA8515",
imgType = 1000,
picMd5 = "A7 CB B5 29 43 A2 12 7C E4 26 59 D2 9B AA 85 15".hexToBytes(),
picHeight = 1,
picWidth = 1,
resId = "/000000000-000000000-A7CBB52943A2127CE42659D29BAA8515",
original = 1,
bizType = 5,
pbReserve = "x".toByteArray(), /* 78 02 */
),
)
)
message(Image("{A7CBB529-43A2-127C-E426-59D29BAA8515}.jpg"))
targetFriend()
}.doEncoderChecks()
}
///////////////////////////////////////////////////////////////////////////
// send with dimension
///////////////////////////////////////////////////////////////////////////
@Test
fun `group Image send with dimension`() {
buildChecks {
elem(
net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
customFace = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.CustomFace(
filePath = "{A7CBB529-43A2-127C-E426-59D29BAA8515}.jpg",
flag = byteArrayOf(0, 0, 0, 0),
fileType = 66,
useful = 1,
picMd5 = "A7 CB B5 29 43 A2 12 7C E4 26 59 D2 9B AA 85 15".hexToBytes(),
bizType = 5,
imageType = 1000,
width = 904,
height = 1214,
size = 170426,
origin = 1,
),
)
)
message(Image("{A7CBB529-43A2-127C-E426-59D29BAA8515}.jpg") {
width = 904
height = 1214
size = 170426
type = ImageType.JPG
isEmoji = false
})
targetGroup()
}.doEncoderChecks()
}
private fun ChecksBuilder.targetGroup() {
target(bot.addGroup(1, 1))
}
@Test
fun `friend Image send with dimension`() {
buildChecks {
elem(
net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
notOnlineImage = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.NotOnlineImage(
filePath = "{A7CBB529-43A2-127C-E426-59D29BAA8515}.jpg",
fileLen = 170426,
downloadPath = "/000000000-000000000-A7CBB52943A2127CE42659D29BAA8515",
imgType = 1000,
picMd5 = "A7 CB B5 29 43 A2 12 7C E4 26 59 D2 9B AA 85 15".hexToBytes(),
picHeight = 1214,
picWidth = 904,
resId = "/000000000-000000000-A7CBB52943A2127CE42659D29BAA8515",
original = 1,
bizType = 5,
pbReserve = "x".toByteArray(), /* 78 02 */
),
)
)
message(Image("{A7CBB529-43A2-127C-E426-59D29BAA8515}.jpg") {
width = 904
height = 1214
size = 170426
type = ImageType.JPG
isEmoji = false
})
targetFriend()
}.doEncoderChecks()
}
private fun ChecksBuilder.targetFriend() {
target(bot.addFriend(1))
}
}

View File

@ -0,0 +1,197 @@
/*
* Copyright 2019-2022 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
*/
package net.mamoe.mirai.internal.message.protocol.impl
import net.mamoe.mirai.contact.MemberPermission
import net.mamoe.mirai.internal.message.data.MarketFaceImpl
import net.mamoe.mirai.internal.message.protocol.MessageProtocol
import net.mamoe.mirai.message.data.Dice
import net.mamoe.mirai.utils.hexToBytes
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
internal class MarketFaceProtocolTest : AbstractMessageProtocolTest() {
override val protocols: Array<out MessageProtocol> = arrayOf(MarketFaceProtocol(), TextProtocol())
@BeforeEach
fun `init group`() {
defaultTarget = bot.addGroup(123, 1230003).apply {
addMember(1230003, "user3", MemberPermission.OWNER)
}
}
@Test
fun `decode Dice`() {
buildChecks {
elem(
net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
marketFace = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.MarketFace(
faceName = "5B E9 9A 8F E6 9C BA E9 AA B0 E5 AD 90 5D".hexToBytes(),
itemType = 6,
faceInfo = 1,
faceId = "48 23 D3 AD B1 5D F0 80 14 CE 5D 67 96 B7 6E E1".hexToBytes(),
tabId = 11464,
subType = 3,
key = "409e2a69b16918f9".toByteArray(), /* 34 30 39 65 32 61 36 39 62 31 36 39 31 38 66 39 */
imageWidth = 200,
imageHeight = 200,
mobileParam = "72 73 63 54 79 70 65 3F 31 3B 76 61 6C 75 65 3D 34".hexToBytes(),
pbReserve = "0A 06 08 C8 01 10 C8 01 40 01".hexToBytes(),
),
),
net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
text = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Text(
str = "[随机骰子]",
),
),
net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
generalFlags = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.GeneralFlags(
pbReserve = "78 00 90 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00 C8 02 00 CA 04 00 D2 05 02 08 37".hexToBytes(),
),
)
)
message(Dice(5))
useOrdinaryEquality()
}.doDecoderChecks()
}
@Test
fun `encode Dice`() {
buildChecks {
elem(
net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
marketFace = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.MarketFace(
faceName = "5B E9 AA B0 E5 AD 90 5D".hexToBytes(), // [骰子]
itemType = 6,
faceInfo = 1,
faceId = "48 23 D3 AD B1 5D F0 80 14 CE 5D 67 96 B7 6E E1".hexToBytes(),
tabId = 11464,
subType = 3,
key = "409e2a69b16918f9".toByteArray(), /* 34 30 39 65 32 61 36 39 62 31 36 39 31 38 66 39 */
imageWidth = 200,
imageHeight = 200,
mobileParam = "72 73 63 54 79 70 65 3F 31 3B 76 61 6C 75 65 3D 34".hexToBytes(),
pbReserve = "0A 06 08 C8 01 10 C8 01 40 01 58 00 62 09 23 30 30 30 30 30 30 30 30 6A 09 23 30 30 30 30 30 30 30 30".hexToBytes(),
),
), net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
text = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Text(
str = "[骰子]",
),
), net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
extraInfo = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.ExtraInfo(
flags = 8,
groupMask = 1,
),
)
)
message(Dice(5))
}.doEncoderChecks()
}
@Test
fun `encode decode MarketFace from Android`() {
buildChecks {
elem(
net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
marketFace = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.MarketFace(
faceName = "5B E5 8F 91 E5 91 86 5D".hexToBytes(),
itemType = 6,
faceInfo = 1,
faceId = "71 26 44 B5 27 94 46 11 99 8A EC 31 86 75 19 D2".hexToBytes(),
tabId = 10278,
subType = 3,
key = "726a53a5372b7289".toByteArray(), /* 37 32 36 61 35 33 61 35 33 37 32 62 37 32 38 39 */
imageWidth = 200,
imageHeight = 200,
pbReserve = "0A 06 08 C8 01 10 C8 01 10 64 1A 0B 51 51 E5 A4 A7 E9 BB 84 E8 84 B8 22 40 68 74 74 70 73 3A 2F 2F 7A 62 2E 76 69 70 2E 71 71 2E 63 6F 6D 2F 69 70 3F 5F 77 76 3D 31 36 37 37 38 32 34 31 26 66 72 6F 6D 3D 61 69 6F 45 6D 6F 6A 69 4E 65 77 26 69 64 3D 31 30 38 39 31 30 2A 06 E6 9D A5 E8 87 AA 30 B5 BB B4 E3 0D 38 B5 BB B4 E3 0D 40 01 50 00".hexToBytes(),
),
), net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
text = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Text(
str = "[发呆]",
),
), net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
extraInfo = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.ExtraInfo(
flags = 8,
groupMask = 1,
),
)
)
// MarketFaceImpl 不支持手动构造
message(
MarketFaceImpl(
net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.MarketFace(
faceName = "5B E5 8F 91 E5 91 86 5D".hexToBytes(),
itemType = 6,
faceInfo = 1,
faceId = "71 26 44 B5 27 94 46 11 99 8A EC 31 86 75 19 D2".hexToBytes(),
tabId = 10278,
subType = 3,
key = "726a53a5372b7289".toByteArray(), /* 37 32 36 61 35 33 61 35 33 37 32 62 37 32 38 39 */
imageWidth = 200,
imageHeight = 200,
pbReserve = "0A 06 08 C8 01 10 C8 01 10 64 1A 0B 51 51 E5 A4 A7 E9 BB 84 E8 84 B8 22 40 68 74 74 70 73 3A 2F 2F 7A 62 2E 76 69 70 2E 71 71 2E 63 6F 6D 2F 69 70 3F 5F 77 76 3D 31 36 37 37 38 32 34 31 26 66 72 6F 6D 3D 61 69 6F 45 6D 6F 6A 69 4E 65 77 26 69 64 3D 31 30 38 39 31 30 2A 06 E6 9D A5 E8 87 AA 30 B5 BB B4 E3 0D 38 B5 BB B4 E3 0D 40 01 50 00".hexToBytes(),
)
)
)
}.doBothChecks()
}
@Test
fun `encode decode MarketFace from macOS`() {
buildChecks {
elem(
net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
marketFace = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.MarketFace(
faceName = "5B E5 8F 91 E5 91 86 5D".hexToBytes(),
itemType = 6,
faceInfo = 1,
faceId = "71 26 44 B5 27 94 46 11 99 8A EC 31 86 75 19 D2".hexToBytes(),
tabId = 10278,
subType = 3,
key = "726a53a5372b7289".toByteArray(), /* 37 32 36 61 35 33 61 35 33 37 32 62 37 32 38 39 */
imageWidth = 200,
imageHeight = 200,
pbReserve = "0A 06 08 C8 01 10 C8 01 40 01".hexToBytes(),
),
), net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
text = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Text(
str = "[发呆]",
),
), net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
extraInfo = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.ExtraInfo(
flags = 8,
groupMask = 1,
),
)
)
// MarketFaceImpl 不支持手动构造
message(
MarketFaceImpl(
net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.MarketFace(
faceName = "5B E5 8F 91 E5 91 86 5D".hexToBytes(),
itemType = 6,
faceInfo = 1,
faceId = "71 26 44 B5 27 94 46 11 99 8A EC 31 86 75 19 D2".hexToBytes(),
tabId = 10278,
subType = 3,
key = "726a53a5372b7289".toByteArray(), /* 37 32 36 61 35 33 61 35 33 37 32 62 37 32 38 39 */
imageWidth = 200,
imageHeight = 200,
pbReserve = "0A 06 08 C8 01 10 C8 01 40 01".hexToBytes(),
)
)
)
}.doBothChecks()
}
}

View File

@ -0,0 +1,77 @@
/*
* Copyright 2019-2022 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
*/
package net.mamoe.mirai.internal.message.protocol.impl
import net.mamoe.mirai.contact.MemberPermission
import net.mamoe.mirai.internal.message.protocol.MessageProtocol
import net.mamoe.mirai.message.data.LightApp
import net.mamoe.mirai.message.data.MessageOrigin
import net.mamoe.mirai.message.data.MessageOriginKind
import net.mamoe.mirai.message.data.MusicKind.NeteaseCloudMusic
import net.mamoe.mirai.message.data.MusicShare
import net.mamoe.mirai.utils.hexToBytes
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
internal class MusicShareProtocolTest : AbstractMessageProtocolTest() {
override val protocols: Array<out MessageProtocol> =
arrayOf(TextProtocol(), MusicShareProtocol(), RichMessageProtocol())
@BeforeEach
fun `init group`() {
defaultTarget = bot.addGroup(123, 1230003).apply {
addMember(1230003, "user3", MemberPermission.OWNER)
}
}
@Test
fun `decode from Android`() {
buildChecks {
elem(
net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
lightApp = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.LightAppElem(
data = "01 78 9C 7D 53 5D 6B D4 40 14 FD 2F 81 EE 53 99 CC E4 63 76 53 08 42 15 A5 16 2D B5 08 16 23 61 3A 99 4D D3 6E 66 86 64 D2 A5 96 7D D9 80 F8 68 11 C1 37 1F 44 44 AB 4F 3E A8 45 7F 4D AA E2 BF F0 4E 58 B7 50 44 32 24 F7 DC B9 33 E7 7E 9C 9C 38 4C 6B 67 CD E1 AA 44 46 48 2E A4 41 B5 A9 1A 6E CA 3A 77 56 9D 4C D4 1C B6 7F BF FA 74 F1 F5 19 E0 A3 42 4C 01 97 4D 5D 70 0B 45 05 08 23 FB 10 C0 BA 52 A5 36 E0 7A F8 E3 E9 93 8B F3 B3 47 DD FC 4B 37 7F DB B5 EF BB F6 5B D7 BE E8 E6 AF BB B6 ED E6 9F BB F6 0D 84 97 C2 30 67 ED 64 71 1D 18 8C 9B 42 49 38 0F 9B 4C 66 95 2A B2 54 1F E6 A9 64 A5 58 78 B5 4E CD B1 06 44 7A 50 64 60 61 1C 44 21 1E 85 AB 0E 9C B7 91 84 86 5E 44 A9 EF 7B CB 12 76 1B A9 CA 22 71 BB F6 63 9F CB 3B FB 9E 7F E8 ED 33 B8 F8 A0 29 F5 FD 6A 02 91 FB C6 E8 7A 2D 71 13 F7 18 F5 99 21 42 7D 04 1D 4A 5C 58 B5 92 F9 B5 22 8B 43 EA 85 11 6C D0 01 34 2B DE DE C4 1B 5B 7C C5 BB B9 73 7D 63 6B 94 AF DF BD B5 E2 AD 4F F9 5E 9D AF F8 37 60 0D 6C DE D0 AD 1A CA 8B 47 68 88 02 6A EB B7 B7 5F 92 F6 9C 57 18 2D 1D 38 45 56 B0 C4 55 8D 11 55 E2 36 D5 E4 4A 06 B5 A8 C0 E1 7B 01 1E 52 1F 0F 07 35 8F A7 E5 D1 C0 C8 B8 1F 8A 58 8C 6D 49 A2 C9 DF CA 3C 8A A4 30 89 BB C9 76 77 F6 22 B5 BB FD 78 7F E2 3D 58 17 B7 F9 C1 E8 5E 1E C7 89 4B 70 14 85 04 3A 4A BC 90 62 32 C4 1E 3A D0 56 1B B5 6A 2A 2E EE D4 F9 46 66 45 B0 F4 A4 05 EF 67 78 D9 C7 02 E5 30 97 1C 71 09 35 68 01 6F DB 0E 1B 96 B8 18 27 6E 10 25 6E 08 DF 51 68 E9 16 C3 4C C1 4A 4B A4 E5 25 57 DA F4 BD 02 6C 58 0E C6 AF EF A7 3F 5F 3E BF 38 3F 5D EA D3 14 66 62 95 F2 7F DD 35 05 E4 47 3C 3F 08 E9 6C 06 A2 51 72 5C E4 56 7F FF 90 CF 58 55 53 56 41 85 F0 57 08 20 50 87 C2 16 47 30 E1 41 38 1E 31 3F DB C3 8C 92 30 8B 08 1B B2 60 8C 23 1A 8D B9 6F 73 E9 65 EA 48 55 95 6C E2 CC 66 7F 00 45 5B 33 67".hexToBytes(),
),
),
net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
text = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Text(
str = """
|[分享]ジェリーフィッシュ
|Yunomi / ローラーガール
|https://y.music.163.com/m/song?id=562591636&uct=QK0IOc%2FSCIO8gBNG%2Bwcbsg%3D%3D&app_version=8.7.46
|来自: 网易云音乐 """.trimMargin(),
),
),
)
message(
MessageOrigin(
LightApp(
"""
{"app":"com.tencent.structmsg","desc":"音乐","view":"music","ver":"0.0.0.1","prompt":"[分享]ジェリーフィッシュ","meta":{"music":{"action":"","android_pkg_name":"","app_type":1,"appid":100495085,"ctime":1652966332,"desc":"Yunomi\/ローラーガール","jumpUrl":"https:\/\/y.music.163.com\/m\/song?id=562591636&uct=QK0IOc%2FSCIO8gBNG%2Bwcbsg%3D%3D&app_version=8.7.46","musicUrl":"http:\/\/music.163.com\/song\/media\/outer\/url?id=562591636&userid=324076307&sc=wmv&tn=","preview":"http:\/\/p1.music.126.net\/KaYSb9oYQzhl2XBeJcj8Rg==\/109951165125601702.jpg","sourceMsgId":"0","source_icon":"https:\/\/i.gtimg.cn\/open\/app_icon\/00\/49\/50\/85\/100495085_100_m.png","source_url":"","tag":"网易云音乐","title":"ジェリーフィッシュ","uin":123456}},"config":{"ctime":1652966332,"forward":true,"token":"101c45f8a3db0a615d91a7a4f0969fc3","type":"normal"}}
""".trimIndent()
),
null,
MessageOriginKind.MUSIC_SHARE
),
MusicShare(
kind = NeteaseCloudMusic,
title = "ジェリーフィッシュ",
summary = "Yunomi/ローラーガール",
jumpUrl = "https://y.music.163.com/m/song?id=562591636&uct=QK0IOc%2FSCIO8gBNG%2Bwcbsg%3D%3D&app_version=8.7.46",
pictureUrl = "http://p1.music.126.net/KaYSb9oYQzhl2XBeJcj8Rg==/109951165125601702.jpg",
musicUrl = "http://music.163.com/song/media/outer/url?id=562591636&userid=324076307&sc=wmv&tn=",
brief = "[分享]ジェリーフィッシュ",
)
)
}.doDecoderChecks()
}
// no encoder. specially handled, no test for now.
}

View File

@ -0,0 +1,85 @@
/*
* Copyright 2019-2022 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
*/
package net.mamoe.mirai.internal.message.protocol.impl
import net.mamoe.mirai.contact.MemberPermission
import net.mamoe.mirai.internal.message.protocol.MessageProtocol
import net.mamoe.mirai.message.data.PokeMessage
import net.mamoe.mirai.utils.hexToBytes
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
internal class PokeMessageProtocolTest : AbstractMessageProtocolTest() {
override val protocols: Array<out MessageProtocol> = arrayOf(TextProtocol(), PokeMessageProtocol())
@BeforeEach
fun `init group`() {
defaultTarget = bot.addGroup(123, 1230003).apply {
addMember(1230003, "user3", MemberPermission.OWNER)
}
}
@Test
fun `test PokeMessage`() {
buildChecks {
elem(
net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
commonElem = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.CommonElem(
serviceType = 2,
pbElem = "08 01 18 00 20 FF FF FF FF 0F 2A 00 32 00 38 00 50 00".hexToBytes(),
businessType = 1,
),
)
)
message(PokeMessage("戳一戳", 1, -1))
useOrdinaryEquality()
}.doDecoderChecks()
}
// Unsupported kinds
// @Test
// fun `test PokeMessage`() {
// buildChecks {
// elem(
// net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
// commonElem = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.CommonElem(
// serviceType = 23,
// pbElem = "08 0A 10 01 1A 09 E7 95 A5 E7 95 A5 E7 95 A5".hexToBytes(),
// businessType = 10,
// ),
// )
// )
// message(PokeMessage("略略略", -1, 1))
// useOrdinaryEquality()
// }.doDecoderChecks()
// }
@Test
fun encode() {
buildChecks {
elem(
net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
commonElem = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.CommonElem(
serviceType = 2,
pbElem = "08 01 20 FF FF FF FF FF FF FF FF FF 01 2A 09 E6 88 B3 E4 B8 80 E6 88 B3 32 05 37 2E 32 2E 30".hexToBytes(),
businessType = 1,
),
),
net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
text = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Text(
str = "[戳一戳]请使用最新版手机QQ体验新功能。",
),
)
)
message(PokeMessage.ChuoYiChuo)
}.doEncoderChecks()
}
}

View File

@ -0,0 +1,83 @@
/*
* Copyright 2019-2022 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
*/
package net.mamoe.mirai.internal.message.protocol.impl
import net.mamoe.mirai.contact.MemberPermission
import net.mamoe.mirai.internal.message.protocol.MessageProtocol
import net.mamoe.mirai.utils.hexToBytes
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
internal class RichMessageProtocolTest : AbstractMessageProtocolTest() {
override val protocols: Array<out MessageProtocol> = arrayOf(TextProtocol(), RichMessageProtocol())
@BeforeEach
fun `init group`() {
defaultTarget = bot.addGroup(123, 1230003).apply {
addMember(1230003, "user3", MemberPermission.OWNER)
}
}
@Test
fun `decode from Android`() {
buildChecks {
elem(
net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
richMsg = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.RichMsg(
template1 = "01 78 9C 7D 52 41 6F D3 30 14 FE 2B 96 A5 D1 13 71 92 36 59 03 71 2A 95 AA A8 4C 30 8D 82 44 85 50 E5 BA 9E EB 29 76 A2 C4 D9 28 C7 46 42 1C 99 10 12 37 0E 08 21 18 9C 38 00 13 FC 9A 14 10 FF 02 27 5D 27 4E 48 D6 F3 7B F6 F7 FC FC 7D EF 85 BD C7 32 06 C7 2C CB 45 A2 70 CB B1 EC 16 60 8A 26 73 A1 38 6E DD BF 37 BC DA 6D 81 5C 13 35 27 71 A2 18 6E 2D 59 DE 02 BD 28 94 39 07 39 CB 8E 05 65 A3 01 86 0E 04 9A C9 34 26 7A 13 BA 6D 08 08 D5 F5 A3 10 82 59 26 D8 21 86 0F 7F 3E 7B BA 3E 3F 7B 54 AD BE 56 AB 77 55 F9 A1 2A BF 57 E5 CB 6A F5 A6 2A CB 6A F5 A5 2A DF 42 90 27 45 46 D9 ED 9C 8F E6 18 DA 10 14 59 8C E1 42 EB 34 BF 86 D0 D2 92 45 2E A8 E5 F8 6D 8B 26 12 49 94 27 8A F7 C4 1C 7B BE EB 05 E6 D8 BF 42 64 7A BD A0 1A 1F EC D9 A3 7D BA E3 0E C7 37 46 FB 5D DE BF 73 73 C7 ED 9F D0 59 CE 77 DA 03 B3 1A 20 49 D3 E9 96 7D D7 DA B5 3A 3E 04 87 31 E1 4D 69 32 37 57 63 C1 55 13 C9 22 D6 C2 FC 6B 78 71 1D 85 C2 50 06 31 59 26 85 C6 D0 BD C0 6B 61 64 99 8A CD E7 C9 66 8F C2 54 50 5D 64 0C D0 C4 40 36 7C 0C 9D D4 D9 F2 71 7D 4B 31 8D F6 C8 64 3C 0B 92 C9 C1 93 45 EC 3E E8 B3 5B F4 A8 7B 97 63 8C 1C 3B 08 3C C7 F1 3D C7 F5 7C DB D9 B5 5D EB 28 E5 10 9C 34 65 16 8D 45 51 A8 85 8E 59 F4 1F 7D 43 B4 81 84 79 21 25 C9 96 D1 A4 50 89 14 A8 2A 3F 35 E0 F7 B5 5D 7D 6C FC B3 10 6D 51 21 AA B9 9A AC A6 39 40 11 C9 30 FC FD E3 F4 D7 AB 17 EB F3 D3 3F AF 3F AF BF 3D 87 40 D0 BA DD DB 5E 09 8B 6B 21 B9 45 15 4A 52 A6 50 2D 75 8D 40 B6 8D 3A 01 F2 6C D4 F5 0C 2F BB 13 78 76 D7 9B 1A 6F 2A AD 54 F1 7F 07 87 4C 37 FE 80 68 82 A1 36 93 C9 94 BE CC 31 45 0C 24 4D 6B 91 2F 0F 1B 1D 90 19 CF E8 2F D6 1B 08 55".hexToBytes(),
serviceId = 1,
),
),
net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
text = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Text(
str = "https://y.music.163.com/m/song?id=562591636&uct=QK0IOc%2FSCIO8gBNG%2Bwcbsg%3D%3D&app_version=8.7.46",
),
),
net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
generalFlags = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.GeneralFlags(
pbReserve = "78 00 C8 01 00 F0 01 00 F8 01 00 90 02 00 C8 02 00 CA 04 00 D2 05 02 08 41".hexToBytes(),
),
)
)
message(
net.mamoe.mirai.message.data.SimpleServiceMessage(
serviceId = 1,
content = """
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?><msg serviceID="1" templateID="123" action="" brief="[分享]ジェリーフィッシュ" sourceMsgId="0" url="https://y.music.163.com/m/song?id=562591636&amp;uct=QK0IOc%2FSCIO8gBNG%2Bwcbsg%3D%3D&amp;app_version=8.7.46" flag="0" adverSign="0" multiMsgFlag="0"><item layout="2" advertiser_id="0" aid="0"><picture cover="http://p1.music.126.net/KaYSb9oYQzhl2XBeJcj8Rg==/109951165125601702.jpg" w="0" h="0" /><title>ジェリーフィッシュ</title><summary>Yunomi/ローラーガール</summary></item><source name="网易云音乐" icon="https://i.gtimg.cn/open/app_icon/00/49/50/85/100495085_100_m.png" action="" a_actionData="tencent100495085://" appid="100495085" /></msg>
""".trimIndent()
)
)
}.doDecoderChecks()
}
@Test
fun encode() {
buildChecks {
elem(
net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.Elem(
richMsg = net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody.RichMsg(
template1 = "01 78 9C 7D 52 41 6F D3 30 14 FE 2B 96 A5 D1 13 71 92 36 59 03 71 2A 95 AA A8 4C 30 8D 82 44 85 50 E5 BA 9E EB 29 76 A2 C4 D9 28 C7 46 42 1C 99 10 12 37 0E 08 21 18 9C 38 00 13 FC 9A 14 10 FF 02 27 5D 27 4E 48 D6 F3 7B F6 F7 FC FC 7D EF 85 BD C7 32 06 C7 2C CB 45 A2 70 CB B1 EC 16 60 8A 26 73 A1 38 6E DD BF 37 BC DA 6D 81 5C 13 35 27 71 A2 18 6E 2D 59 DE 02 BD 28 94 39 07 39 CB 8E 05 65 A3 01 86 0E 04 9A C9 34 26 7A 13 BA 6D 08 08 D5 F5 A3 10 82 59 26 D8 21 86 0F 7F 3E 7B BA 3E 3F 7B 54 AD BE 56 AB 77 55 F9 A1 2A BF 57 E5 CB 6A F5 A6 2A CB 6A F5 A5 2A DF 42 90 27 45 46 D9 ED 9C 8F E6 18 DA 10 14 59 8C E1 42 EB 34 BF 86 D0 D2 92 45 2E A8 E5 F8 6D 8B 26 12 49 94 27 8A F7 C4 1C 7B BE EB 05 E6 D8 BF 42 64 7A BD A0 1A 1F EC D9 A3 7D BA E3 0E C7 37 46 FB 5D DE BF 73 73 C7 ED 9F D0 59 CE 77 DA 03 B3 1A 20 49 D3 E9 96 7D D7 DA B5 3A 3E 04 87 31 E1 4D 69 32 37 57 63 C1 55 13 C9 22 D6 C2 FC 6B 78 71 1D 85 C2 50 06 31 59 26 85 C6 D0 BD C0 6B 61 64 99 8A CD E7 C9 66 8F C2 54 50 5D 64 0C D0 C4 40 36 7C 0C 9D D4 D9 F2 71 7D 4B 31 8D F6 C8 64 3C 0B 92 C9 C1 93 45 EC 3E E8 B3 5B F4 A8 7B 97 63 8C 1C 3B 08 3C C7 F1 3D C7 F5 7C DB D9 B5 5D EB 28 E5 10 9C 34 65 16 8D 45 51 A8 85 8E 59 F4 1F 7D 43 B4 81 84 79 21 25 C9 96 D1 A4 50 89 14 A8 2A 3F 35 E0 F7 B5 5D 7D 6C FC B3 10 6D 51 21 AA B9 9A AC A6 39 40 11 C9 30 FC FD E3 F4 D7 AB 17 EB F3 D3 3F AF 3F AF BF 3D 87 40 D0 BA DD DB 5E 09 8B 6B 21 B9 45 15 4A 52 A6 50 2D 75 8D 40 B6 8D 3A 01 F2 6C D4 F5 0C 2F BB 13 78 76 D7 9B 1A 6F 2A AD 54 F1 7F 07 87 4C 37 FE 80 68 82 A1 36 93 C9 94 BE CC 31 45 0C 24 4D 6B 91 2F 0F 1B 1D 90 19 CF E8 2F D6 1B 08 55".hexToBytes(),
serviceId = 1,
),
),
)
message(
net.mamoe.mirai.message.data.SimpleServiceMessage(
serviceId = 1,
content = """
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?><msg serviceID="1" templateID="123" action="" brief="[分享]ジェリーフィッシュ" sourceMsgId="0" url="https://y.music.163.com/m/song?id=562591636&amp;uct=QK0IOc%2FSCIO8gBNG%2Bwcbsg%3D%3D&amp;app_version=8.7.46" flag="0" adverSign="0" multiMsgFlag="0"><item layout="2" advertiser_id="0" aid="0"><picture cover="http://p1.music.126.net/KaYSb9oYQzhl2XBeJcj8Rg==/109951165125601702.jpg" w="0" h="0" /><title>ジェリーフィッシュ</title><summary>Yunomi/ローラーガール</summary></item><source name="网易云音乐" icon="https://i.gtimg.cn/open/app_icon/00/49/50/85/100495085_100_m.png" action="" a_actionData="tencent100495085://" appid="100495085" /></msg>
""".trimIndent()
)
)
}.doEncoderChecks()
}
// no encoder. specially handled, no test for now.
}

View File

@ -10,6 +10,7 @@
package net.mamoe.mirai.internal.message.protocol.impl
import net.mamoe.mirai.contact.MemberPermission
import net.mamoe.mirai.internal.message.protocol.MessageProtocol
import net.mamoe.mirai.message.data.At
import net.mamoe.mirai.message.data.AtAll
import net.mamoe.mirai.message.data.PlainText
@ -18,8 +19,7 @@ import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
internal class TextProtocolTest : AbstractMessageProtocolTest() {
override val protocol = TextProtocol()
override val protocols: Array<out MessageProtocol> = arrayOf(TextProtocol())
@BeforeEach
fun `init group`() {