Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
M
Mirai
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
MyCard
Mirai
Commits
3474c87f
Commit
3474c87f
authored
Oct 20, 2019
by
Him188
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Image uploading
parent
fdf50e4d
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
401 additions
and
224 deletions
+401
-224
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/TIMProtocol.kt
...otlin/net.mamoe.mirai/network/protocol/tim/TIMProtocol.kt
+2
-1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/UploadFriendImage.kt
...oe.mirai/network/protocol/tim/packet/UploadFriendImage.kt
+164
-10
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/UploadGroupImage.kt
...moe.mirai/network/protocol/tim/packet/UploadGroupImage.kt
+153
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/action/ClientSendFriendMessagePacket.kt
...otocol/tim/packet/action/ClientSendFriendMessagePacket.kt
+1
-1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/PacketBuilderUtil.kt
...monMain/kotlin/net.mamoe.mirai/utils/PacketBuilderUtil.kt
+56
-15
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/PlatformImage.kt
.../commonMain/kotlin/net.mamoe.mirai/utils/PlatformImage.kt
+5
-1
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/network/protocol/tim/packet/UploadImageJvm.kt
...mamoe/mirai/network/protocol/tim/packet/UploadImageJvm.kt
+0
-187
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/PlatformImageJvm.kt
.../jvmMain/kotlin/net/mamoe/mirai/utils/PlatformImageJvm.kt
+5
-1
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/PlatformUtilsJvm.kt
.../jvmMain/kotlin/net/mamoe/mirai/utils/PlatformUtilsJvm.kt
+8
-2
mirai-debug/src/main/java/PacketDebuger.kt
mirai-debug/src/main/java/PacketDebuger.kt
+7
-6
No files found.
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/TIMProtocol.kt
View file @
3474c87f
...
...
@@ -31,7 +31,8 @@ object TIMProtocol {
*/
const
val
fixVer2
=
"02 00 00 00 01 01 01 00 00 68 20"
// 02 38 03 00 CD 48 68 3E 03 3F A2 02 00 00 00
const
val
versionNewest
=
"02 00 00 00 01 2E 01 00 00 69 35"
const
val
version0x02
=
"02 00 00 00 01 2E 01 00 00 69 35"
const
val
version0x04
=
"04 00 00 00 01 2E 01 00 00 69 35 00 00 00 00 00 00 00 00"
const
val
constantData1
=
"00 18 00 16 00 01 "
const
val
constantData2
=
"00 00 04 53 00 00 00 01 00 00 15 85 "
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/UploadImage.kt
→
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/Upload
Friend
Image.kt
View file @
3474c87f
...
...
@@ -8,7 +8,6 @@ import net.mamoe.mirai.contact.QQ
import
net.mamoe.mirai.message.ImageId
import
net.mamoe.mirai.network.BotSession
import
net.mamoe.mirai.network.account
import
net.mamoe.mirai.network.protocol.tim.TIMProtocol
import
net.mamoe.mirai.network.session
import
net.mamoe.mirai.qqAccount
import
net.mamoe.mirai.utils.*
...
...
@@ -33,8 +32,8 @@ class ClientSubmitImageFilenamePacket(
)
:
ClientPacket
()
{
override
fun
encode
(
builder
:
BytePacketBuilder
)
=
with
(
builder
)
{
writeQQ
(
bot
)
writeHex
(
TIMProtocol
.
fixVer2
)
//
writeHex("04 00 00 00 01 2E 01 00 00 69 35")
//
writeHex(TIMProtocol.fixVer2)
writeHex
(
"04 00 00 00 01 2E 01 00 00 69 35"
)
encryptAndWrite
(
sessionKey
)
{
writeByte
(
0
x01
)
...
...
@@ -49,7 +48,7 @@ class ClientSubmitImageFilenamePacket(
writeStringUtf8
(
name
)
writeHex
(
"00 00"
)
writeRandom
(
2
)
//这个也与是哪个好友有关?
writeHex
(
"00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 2E 01"
)
//35 02? 最后这个值是与是哪个
哈有
有关
writeHex
(
"00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 2E 01"
)
//35 02? 最后这个值是与是哪个
好友
有关
//this.debugPrintThis("ClientSubmitImageFilenamePacket")
}
...
...
@@ -76,14 +75,169 @@ class ServerSubmitImageFilenameResponsePacket(input: ByteReadPacket) : ServerPac
}
}
/**
* 请求上传图片. 将发送图片的 md5, size, width, height.
* 服务器返回以下之一:
* - 服务器已经存有这个图片 [ServerTryGetImageIDFailedPacket]
* - 服务器未存有, 返回一个 key 用于客户端上传 [ServerTryGetImageIDSuccessPacket]
*
* @author Him188moe
*/
@PacketId
(
0
x03_52u
)
expect
class
ClientTryGetImageIDPacket
(
botNumber
:
UInt
,
sessionKey
:
ByteArray
,
target
:
UInt
,
image
:
PlatformImage
)
:
ClientPacket
class
ClientTryGetImageIDPacket
(
private
val
botNumber
:
UInt
,
private
val
sessionKey
:
ByteArray
,
private
val
target
:
UInt
,
private
val
image
:
PlatformImage
)
:
ClientPacket
()
{
//00 00 00 07 00 00 00 4B 08 01 12 03 98 01 01 08 01 12 47 08 A2 FF 8C F0 03 10 89 FC A6 8C 0B 18 00 22 10 2B 23 D7 05 CA D1 F2 CF 37 10 FE 58 26 92 FC C4 28 FD 08 32 1A 7B 00 47 00 47 00 42 00 7E 00 49 00 31 00 5A 00 4D 00 43 00 28 00 25 00 49 00 38 01 48 00 70 42 78 42
@PacketVersion
(
date
=
"2019.10.19"
,
timVersion
=
"2.3.2.21173"
)
override
fun
encode
(
builder
:
BytePacketBuilder
)
=
with
(
builder
)
{
writeQQ
(
botNumber
)
//04 00 00 00 01 01 01 00 00 68 20 00 00 00 00 00 00 00 00
writeHex
(
"04 00 00 00 01 2E 01 00 00 69 35 00 00 00 00 00 00 00 00"
)
val
imageData
=
image
.
toByteArray
()
encryptAndWrite
(
sessionKey
)
{
//好友图片
// 00 00 00
// 07 00
// 00 00
// proto
// [4D 08]后文长度
// 01 12
// 03 98
// 01 01
// 08 01
// 12 49
// 08 [A2 FF 8C F0 03](1040400290 varint)
// 10 [DD F1 92 B7 07](1994701021 varint)
// 18 00
// 22 [10](=16) [E9 BA 47 2E 36 ED D4 BF 8C 4F E5 6A CB A0 2D 5E](md5)
// 28 [CE 0E](1870 varint)
// 32 1A
// 39 00
// 51 00
// 24 00
// 32 00
// 4A 00
// 53 00
// 25 00
// 4C 00
// 56 00
// 42 00
// 33 00
// 44 00
// 44 00
// 38 01
// 48 00
// 70 [92 03](402 varint)
// 78 [E3 01](227 varint)
//好友图片
/*
* 00 00 00 07 00 00 00
* [4E 08]后文长度
* 01 12
* 03 98
* 01 01
* 08 01
* 12 4A
* 08 [A2 FF 8C F0 03](varint)
* 10 [DD F1 92 B7 07](varint)
* 18 00//24
* 22 10 72 02 57 44 84 1D 83 FC C0 85 A1 E9 10 AA 9C 2C
* 28 [BD D9 19](421053 varint)
* 32 1A//48
* 49 00
* 49 00
* 25 00
* 45 00
* 5D 00
* 50 00
* 41 00
* 7D 00
* 4F 00
* 56 00
* 46 00
* 4B 00
* 5D 00
* 38 01
* 48 00//78
*
*
* 70 [80 14]
* 78 [A0 0B]//84
*/
writeZero
(
3
)
writeUShort
(
0
x07_00u
)
writeZero
(
1
)
//proto
val
packet
=
buildPacket
{
writeUByte
(
0
x08u
)
writeUShort
(
0
x01_12u
)
writeUShort
(
0
x03_98u
)
writeUShort
(
0
x01_01u
)
writeUShort
(
0
x08_01u
)
writeUShort
(
0
x12_47u
)
//?似乎会变
writeUByte
(
0
x08u
)
writeUVarInt
(
botNumber
)
writeUByte
(
0
x10u
)
writeUVarInt
(
target
)
writeUShort
(
0
x18_00u
)
writeUByte
(
0
x22u
)
writeUByte
(
0
x10u
)
writeFully
(
md5
(
imageData
))
writeUByte
(
0
x28u
)
writeUVarInt
(
imageData
.
size
.
toUInt
())
writeUByte
(
0
x32u
)
//长度应为1A
writeUVarintLVPacket
{
writeUShort
(
0
x28_00u
)
writeUShort
(
0
x46_00u
)
writeUShort
(
0
x51_00u
)
writeUShort
(
0
x56_00u
)
writeUShort
(
0
x4B_00u
)
writeUShort
(
0
x41_00u
)
writeUShort
(
0
x49_00u
)
writeUShort
(
0
x25_00u
)
writeUShort
(
0
x4B_00u
)
writeUShort
(
0
x24_00u
)
writeUShort
(
0
x55_00u
)
writeUShort
(
0
x30_00u
)
writeUShort
(
0
x24_00u
)
}
writeUShort
(
0
x38_01u
)
writeUShort
(
0
x48_00u
)
writeUByte
(
0
x70u
)
writeUVarInt
(
image
.
imageWidth
.
toUInt
())
writeUByte
(
0
x78u
)
writeUVarInt
(
image
.
imageHeight
.
toUInt
())
}
writeShort
((
packet
.
remaining
-
7
).
toShort
())
//why?
writePacket
(
packet
)
//println(this.build().readBytes().toUHexString())
}
}
}
@PacketId
(
0
x03_52u
)
sealed
class
ServerTryGetImageIDResponsePacket
(
input
:
ByteReadPacket
)
:
ServerPacket
(
input
)
{
@PacketId
(
0
x03_52u
)
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/UploadGroupImage.kt
0 → 100644
View file @
3474c87f
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
,
"EXPERIMENTAL_UNSIGNED_LITERALS"
)
package
net.mamoe.mirai.network.protocol.tim.packet
import
kotlinx.io.core.BytePacketBuilder
import
kotlinx.io.core.writeUByte
import
net.mamoe.mirai.network.protocol.tim.TIMProtocol
import
net.mamoe.mirai.utils.*
fun
main
()
{
"1A"
.
hexToBytes
().
read
{
println
(
readUnsignedVarInt
())
}
}
/**
* 获取 Image Id 和上传用的一个 uKey
*/
@PacketId
(
0
x0388u
)
class
ClientGroupImageIdRequestPacket
(
private
val
bot
:
UInt
,
private
val
group
:
UInt
,
private
val
image
:
PlatformImage
,
private
val
imageData
:
ByteArray
,
private
val
sessionKey
:
ByteArray
)
:
ClientPacket
()
{
@PacketVersion
(
date
=
"2019.10.20"
,
timVersion
=
"2.3.2.21173"
)
override
fun
encode
(
builder
:
BytePacketBuilder
)
=
with
(
builder
)
{
//未知图片A
// 00 00 00 07 00 00 00
// 53 08 =后文长度-6
// 01 12 03 98 01 02 10 02 22 4F 08 F3 DB F3 E3 01 10 A2 FF 8C F0 03 18 B1 C7 B1 BB 0A 22 10 77 FB 3D 6F 97 BD 7B F0 C4 1F DC 60 1F 22 D2 7C 28 04 30 02 38 20 40 FF 01 48 00 50 01 5A 05 32 36 39 33 33 60 00 68 00 70 00 78 00 80 01 A4 05 88 01 D8 03 90 01 EB 07 A0 01 01
//小图B
// 00 00 00 07 00 00 00
// 5B 08 =后文长度-6
// 01 12 03 98 01 01 10 01 1A
// 57长度
// 08 FB D2 D8 94 02
// 10 A2 FF 8C F0 03
// 18 00
// 22 [10] 7A A4 B3 AA 8C 3C 0F 45 2D 9B 7F 30 2A 0A CE AA
// 28 F3 06//size
// 32 1A
// 29 00
// 37 00
// 42 00
// 53 00
// 4B 00
// 48 00
// 32 00
// 44 00
// 35 00
// 54 00
// 51 00
// 28 00
// 5A 00
// 38 01
// 48 01
// 50 41 //宽度
// 58 34 //高度
// 60 04
// 6A [05] 32 36 39 33 33
// 70 00
// 78 03
// 80 01 00
//大图C
// 00 00 00 07 00 00 00
// 5E 08 =后文长度-6
// 01 12 03 98 01 01 10 01 1A
// 5A长度
// 08 A0 89 F7 B6 03
// 10 A2 FF 8C F0 03
// 18 00
// 22 [10] F1 DD 65 4D A1 AB 66 B4 0F B5 27 B5 14 8E 73 B5
// 28 96 83 08//size
// 32 1A
// 31 00
// 35 00
// 4C 00
// 24 00
// 40 00
// 5B 00
// 4D 00
// 5B 00
// 39 00
// 39 00
// 40 00
// 57 00
// 5D 00
// 38 01
// 48 01
// 50 80 14 //宽度
// 58 A0 0B //高度
// 60 02
// 6A [05] 32 36 39 33 33
// 70 00
// 78 03
// 80 01 00
writeQQ
(
bot
)
writeHex
(
TIMProtocol
.
version0x04
)
encryptAndWrite
(
sessionKey
)
{
writeHex
(
"00 00 00 07 00 00 00"
)
writeUVarintLVPacket
(
lengthOffset
=
{
it
-
6
})
{
writeHex
(
"01 12 03 98 01 01 10 01 1A"
)
writeUVarintLVPacket
(
lengthOffset
=
{
it
+
1
})
{
writeUVarInt
(
group
)
writeUVarInt
(
bot
)
writeTV
(
0
x1800u
)
writeTLV
(
0
x22u
,
md5
(
imageData
))
writeTUVarint
(
0
x28u
,
imageData
.
size
.
toUInt
())
writeUVarintLVPacket
(
tag
=
0
x32u
)
{
writeTV
(
0
x31_00u
)
writeTV
(
0
x35_00u
)
writeTV
(
0
x4C_00u
)
writeTV
(
0
x24_00u
)
writeTV
(
0
x40_00u
)
writeTV
(
0
x5B_00u
)
writeTV
(
0
x4D_00u
)
writeTV
(
0
x5B_00u
)
writeTV
(
0
x39_00u
)
writeTV
(
0
x39_00u
)
writeTV
(
0
x40_00u
)
writeTV
(
0
x57_00u
)
writeTV
(
0
x5D_00u
)
}
writeTV
(
0
x38_01u
)
writeTV
(
0
x48_01u
)
writeTUVarint
(
0
x50u
,
image
.
imageWidth
.
toUInt
())
writeTUVarint
(
0
x58u
,
image
.
imageHeight
.
toUInt
())
writeTV
(
0
x60_02u
)
writeTLV
(
0
x6Au
,
value0x6A
)
writeTV
(
0
x70_00u
)
writeTV
(
0
x78_03u
)
writeTV
(
0
x80_01u
)
writeUByte
(
0
u
)
}
}
}
}
companion
object
{
private
val
value0x6A
:
UByteArray
=
ubyteArrayOf
(
32
u
,
36
u
,
39
u
,
33
u
,
33
u
)
}
}
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/action/ClientSendFriendMessagePacket.kt
View file @
3474c87f
...
...
@@ -30,7 +30,7 @@ class ClientSendFriendMessagePacket(
@PacketVersion
(
date
=
"2019.10.19"
,
timVersion
=
"2.3.2.21173"
)
override
fun
encode
(
builder
:
BytePacketBuilder
)
=
with
(
builder
)
{
writeQQ
(
botQQ
)
writeHex
(
TIMProtocol
.
version
Newest
)
writeHex
(
TIMProtocol
.
version
0x02
)
encryptAndWrite
(
sessionKey
)
{
// TIM最新, 消息内容 "牛逼"
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/PacketBuilderUtil.kt
View file @
3474c87f
...
...
@@ -18,32 +18,39 @@ fun BytePacketBuilder.writeQQ(qq: UInt) = this.writeUInt(qq)
fun
BytePacketBuilder
.
writeGroup
(
groupIdOrGroupNumber
:
Long
)
=
this
.
writeUInt
(
groupIdOrGroupNumber
.
toUInt
())
fun
BytePacketBuilder
.
writeGroup
(
groupIdOrGroupNumber
:
UInt
)
=
this
.
writeUInt
(
groupIdOrGroupNumber
)
fun
BytePacketBuilder
.
writeLVByteArray
(
byteArray
:
ByteArray
)
{
fun
BytePacketBuilder
.
write
Short
LVByteArray
(
byteArray
:
ByteArray
)
{
this
.
writeShort
(
byteArray
.
size
.
toShort
())
this
.
writeFully
(
byteArray
)
}
fun
BytePacketBuilder
.
writeShortLVPacket
(
packet
:
ByteReadPacket
)
{
this
.
writeShort
(
packet
.
remaining
.
toShort
())
this
.
writePacket
(
packet
)
packet
.
release
()
}
fun
BytePacketBuilder
.
writeUVarintLVPacket
(
packet
:
ByteReadPacket
)
{
this
.
writeUVarLong
(
packet
.
remaining
)
this
.
writePacket
(
packet
)
packet
.
release
()
}
private
fun
<
N
:
Comparable
<
N
>>
N
.
coerceAtMostOrFail
(
maximumValue
:
N
):
N
=
if
(
this
>
maximumValue
)
error
(
"value is greater than its expected maximum value $maximumValue"
)
else
this
fun
BytePacketBuilder
.
writeShortLVPacket
(
tag
:
UByte
?
=
null
,
lengthOffset
:
((
Long
)
->
Long
)?
=
null
,
builder
:
BytePacketBuilder
.()
->
Unit
)
=
with
(
BytePacketBuilder
().
apply
(
builder
).
build
())
{
if
(
tag
!=
null
)
{
writeUByte
(
tag
)
}
writeUShort
((
lengthOffset
?.
invoke
(
remaining
)
?:
remaining
).
coerceAtMostOrFail
(
0
xFFFFL
).
toUShort
())
writePacket
(
this
)
this
.
release
()
}
fun
BytePacketBuilder
.
writeShortLVPacket
(
builder
:
BytePacketBuilder
.()
->
Unit
)
=
this
.
writeShortLVPacket
(
BytePacketBuilder
().
apply
(
builder
).
build
())
fun
BytePacketBuilder
.
writeUVarintLVPacket
(
builder
:
BytePacketBuilder
.()
->
Unit
)
=
this
.
writeUVarintLVPacket
(
BytePacketBuilder
().
apply
(
builder
).
build
())
fun
BytePacketBuilder
.
writeUVarintLVPacket
(
tag
:
UByte
?
=
null
,
lengthOffset
:
((
Long
)
->
Long
)?
=
null
,
builder
:
BytePacketBuilder
.()
->
Unit
)
=
with
(
BytePacketBuilder
().
apply
(
builder
).
build
())
{
if
(
tag
!=
null
)
{
writeUByte
(
tag
)
}
writeUVarInt
((
lengthOffset
?.
invoke
(
remaining
)
?:
remaining
).
coerceAtMostOrFail
(
0
xFFFFL
))
writePacket
(
this
)
this
.
release
()
}
@Suppress
(
"DEPRECATION"
)
fun
BytePacketBuilder
.
writeShortLVString
(
str
:
String
)
=
this
.
writeLVByteArray
(
str
.
toByteArray
())
fun
BytePacketBuilder
.
writeShortLVString
(
str
:
String
)
=
this
.
write
Short
LVByteArray
(
str
.
toByteArray
())
@Suppress
(
"DEPRECATION"
)
fun
BytePacketBuilder
.
writeLVHex
(
hex
:
String
)
=
this
.
writeLVByteArray
(
hex
.
hexToBytes
())
fun
BytePacketBuilder
.
writeLVHex
(
hex
:
String
)
=
this
.
write
Short
LVByteArray
(
hex
.
hexToBytes
())
fun
BytePacketBuilder
.
writeIP
(
ip
:
String
)
=
writeFully
(
ip
.
trim
().
split
(
"."
).
map
{
it
.
toUByte
()
}.
toUByteArray
())
...
...
@@ -51,6 +58,40 @@ fun BytePacketBuilder.writeTime() = this.writeInt(currentTime.toInt())
fun
BytePacketBuilder
.
writeHex
(
uHex
:
String
)
=
this
.
writeFully
(
uHex
.
hexToUBytes
())
fun
BytePacketBuilder
.
writeTLV
(
tag
:
UByte
,
values
:
UByteArray
)
{
writeUByte
(
tag
)
writeVarInt
(
values
.
size
)
writeFully
(
values
)
}
fun
BytePacketBuilder
.
writeTLV
(
tag
:
UByte
,
values
:
ByteArray
)
{
writeUByte
(
tag
)
writeVarInt
(
values
.
size
)
writeFully
(
values
)
}
fun
BytePacketBuilder
.
writeTHex
(
tag
:
UByte
,
uHex
:
String
)
{
this
.
writeUByte
(
tag
)
this
.
writeFully
(
uHex
.
hexToUBytes
())
}
fun
BytePacketBuilder
.
writeTV
(
tagValue
:
UShort
)
=
writeUShort
(
tagValue
)
fun
BytePacketBuilder
.
writeTUbyte
(
tag
:
UByte
,
value
:
UByte
)
{
this
.
writeUByte
(
tag
)
this
.
writeUByte
(
value
)
}
fun
BytePacketBuilder
.
writeTUVarint
(
tag
:
UByte
,
value
:
UInt
)
{
this
.
writeUByte
(
tag
)
this
.
writeUVarInt
(
value
)
}
fun
BytePacketBuilder
.
writeTByteArray
(
tag
:
UByte
,
value
:
ByteArray
)
{
this
.
writeUByte
(
tag
)
this
.
writeFully
(
value
)
}
fun
BytePacketBuilder
.
encryptAndWrite
(
key
:
IoBuffer
,
encoder
:
BytePacketBuilder
.()
->
Unit
)
=
encryptAndWrite
(
key
.
readBytes
(),
encoder
)
fun
BytePacketBuilder
.
encryptAndWrite
(
key
:
ByteArray
,
encoder
:
BytePacketBuilder
.()
->
Unit
)
=
writeFully
(
TEA
.
encrypt
(
BytePacketBuilder
().
apply
(
encoder
).
use
{
it
.
build
().
readBytes
()
},
key
))
fun
BytePacketBuilder
.
encryptAndWrite
(
keyHex
:
String
,
encoder
:
BytePacketBuilder
.()
->
Unit
)
=
encryptAndWrite
(
keyHex
.
hexToBytes
(),
encoder
)
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/PlatformImage.kt
View file @
3474c87f
...
...
@@ -6,4 +6,8 @@ import kotlin.jvm.JvmOverloads
expect
class
PlatformImage
@JvmOverloads
expect
fun
PlatformImage
.
toByteArray
(
formatName
:
String
=
"JPG"
):
ByteArray
\ No newline at end of file
expect
fun
PlatformImage
.
toByteArray
(
formatName
:
String
=
"JPG"
):
ByteArray
expect
val
PlatformImage
.
imageWidth
:
Int
expect
val
PlatformImage
.
imageHeight
:
Int
\ No newline at end of file
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/network/protocol/tim/packet/UploadImageJvm.kt
deleted
100644 → 0
View file @
fdf50e4d
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
,
"EXPERIMENTAL_UNSIGNED_LITERALS"
)
package
net.mamoe.mirai.network.protocol.tim.packet
import
kotlinx.io.core.*
import
net.mamoe.mirai.utils.*
import
java.io.File
import
javax.imageio.ImageIO
actual
typealias
ClientTryGetImageIDPacket
=
ClientTryGetImageIDPacketJvm
fun
main
()
{
val
packet
=
ClientTryGetImageIDPacketJvm
(
1040400290
u
,
"99 82 67 D4 62 20 CA 5D 81 F8 6F 83 EE 8A F7 68"
.
hexToBytes
(),
2978594313
u
,
ImageIO
.
read
(
File
((
"C:\\Users\\Him18\\Desktop\\哈哈哈操.jpg"
))))
println
(
packet
.
packet
.
readBytes
().
toUHexString
())
"89 FC A6 8C 0B"
.
hexToBytes
().
read
{
println
(
readUnsignedVarInt
())
}
}
/**
* 请求上传图片. 将发送图片的 md5, size, width, height.
* 服务器返回以下之一:
* - 服务器已经存有这个图片 [ServerTryGetImageIDFailedPacket]
* - 服务器未存有, 返回一个 key 用于客户端上传 [ServerTryGetImageIDSuccessPacket]
*
* @author Him188moe
*/
@PacketId
(
0
x03_52u
)
class
ClientTryGetImageIDPacketJvm
(
private
val
botNumber
:
UInt
,
private
val
sessionKey
:
ByteArray
,
private
val
target
:
UInt
,
private
val
image
:
PlatformImage
)
:
ClientPacket
()
{
//00 00 00 07 00 00 00 4B 08 01 12 03 98 01 01 08 01 12 47 08 A2 FF 8C F0 03 10 89 FC A6 8C 0B 18 00 22 10 2B 23 D7 05 CA D1 F2 CF 37 10 FE 58 26 92 FC C4 28 FD 08 32 1A 7B 00 47 00 47 00 42 00 7E 00 49 00 31 00 5A 00 4D 00 43 00 28 00 25 00 49 00 38 01 48 00 70 42 78 42
@PacketVersion
(
date
=
"2019.10.19"
,
timVersion
=
"2.3.2.21173"
)
override
fun
encode
(
builder
:
BytePacketBuilder
)
=
with
(
builder
)
{
writeQQ
(
botNumber
)
//04 00 00 00 01 01 01 00 00 68 20 00 00 00 00 00 00 00 00
writeHex
(
"04 00 00 00 01 2E 01 00 00 69 35 00 00 00 00 00 00 00 00"
)
val
imageData
=
image
.
toByteArray
()
encryptAndWrite
(
sessionKey
)
{
//好友图片
// 00 00 00
// 07 00
// 00 00
// proto
// [4D 08]后文长度
// 01 12
// 03 98
// 01 01
// 08 01
// 12 49
// 08 [A2 FF 8C F0 03](1040400290 varint)
// 10 [DD F1 92 B7 07](1994701021 varint)
// 18 00
// 22 [10](=16) [E9 BA 47 2E 36 ED D4 BF 8C 4F E5 6A CB A0 2D 5E](md5)
// 28 [CE 0E](1870 varint)
// 32 1A
// 39 00
// 51 00
// 24 00
// 32 00
// 4A 00
// 53 00
// 25 00
// 4C 00
// 56 00
// 42 00
// 33 00
// 44 00
// 44 00
// 38 01
// 48 00
// 70 [92 03](402 varint)
// 78 [E3 01](227 varint)
//好友图片
/*
* 00 00 00 07 00 00 00
* [4E 08]后文长度
* 01 12
* 03 98
* 01 01
* 08 01
* 12 4A
* 08 [A2 FF 8C F0 03](varint)
* 10 [DD F1 92 B7 07](varint)
* 18 00//24
* 22 10 72 02 57 44 84 1D 83 FC C0 85 A1 E9 10 AA 9C 2C
* 28 [BD D9 19](421053 varint)
* 32 1A//48
* 49 00
* 49 00
* 25 00
* 45 00
* 5D 00
* 50 00
* 41 00
* 7D 00
* 4F 00
* 56 00
* 46 00
* 4B 00
* 5D 00
* 38 01
* 48 00//78
*
*
* 70 [80 14]
* 78 [A0 0B]//84
*/
writeZero
(
3
)
writeUShort
(
0
x07_00u
)
writeZero
(
1
)
//proto
val
packet
=
buildPacket
{
writeUByte
(
0
x08u
)
writeUShort
(
0
x01_12u
)
writeUShort
(
0
x03_98u
)
writeUShort
(
0
x01_01u
)
writeUShort
(
0
x08_01u
)
writeUShort
(
0
x12_47u
)
//?似乎会变
writeUByte
(
0
x08u
)
writeUVarInt
(
target
)
//todo 这两qq号反过来放也tm可以成功
writeUByte
(
0
x10u
)
writeUVarInt
(
botNumber
)
writeUShort
(
0
x18_00u
)
writeUByte
(
0
x22u
)
writeUByte
(
0
x10u
)
writeFully
(
md5
(
imageData
))
writeUByte
(
0
x28u
)
writeUVarInt
(
imageData
.
size
.
toUInt
())
writeUByte
(
0
x32u
)
//长度应为1A
writeUVarintLVPacket
{
writeUShort
(
0
x28_00u
)
writeUShort
(
0
x46_00u
)
writeUShort
(
0
x51_00u
)
writeUShort
(
0
x56_00u
)
writeUShort
(
0
x4B_00u
)
writeUShort
(
0
x41_00u
)
writeUShort
(
0
x49_00u
)
writeUShort
(
0
x25_00u
)
writeUShort
(
0
x4B_00u
)
writeUShort
(
0
x24_00u
)
writeUShort
(
0
x55_00u
)
writeUShort
(
0
x30_00u
)
writeUShort
(
0
x24_00u
)
}
writeUShort
(
0
x38_01u
)
writeUShort
(
0
x48_00u
)
writeUByte
(
0
x70u
)
writeUVarInt
(
image
.
width
.
toUInt
())
writeUByte
(
0
x78u
)
writeUVarInt
(
image
.
height
.
toUInt
())
}
writeShort
((
packet
.
remaining
-
7
).
toShort
())
//why?
writePacket
(
packet
)
//println(this.build().readBytes().toUHexString())
}
}
}
\ No newline at end of file
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/PlatformImageJvm.kt
View file @
3474c87f
...
...
@@ -7,4 +7,8 @@ import javax.imageio.ImageIO
actual
typealias
PlatformImage
=
BufferedImage
@JvmOverloads
actual
fun
BufferedImage
.
toByteArray
(
formatName
:
String
):
ByteArray
=
ByteArrayOutputStream
().
use
{
ImageIO
.
write
(
this
,
"PNG"
,
it
);
it
.
toByteArray
()
}
\ No newline at end of file
actual
fun
BufferedImage
.
toByteArray
(
formatName
:
String
):
ByteArray
=
ByteArrayOutputStream
().
use
{
ImageIO
.
write
(
this
,
"PNG"
,
it
);
it
.
toByteArray
()
}
actual
val
PlatformImage
.
imageWidth
:
Int
get
()
=
this
.
width
actual
val
PlatformImage
.
imageHeight
:
Int
get
()
=
this
.
height
\ No newline at end of file
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/PlatformUtilsJvm.kt
View file @
3474c87f
...
...
@@ -69,11 +69,17 @@ actual suspend fun httpPostFriendImage(
"&uin="
+
botNumber
.
toLong
()).
openConnection
()
as
HttpURLConnection
conn
.
setRequestProperty
(
"User-Agent"
,
"QQClient"
)
conn
.
setRequestProperty
(
"Content-Length"
,
""
+
fileSize
)
conn
.
setRequestProperty
(
"connection"
,
"Keep-Alive"
)
conn
.
setRequestProperty
(
"Content-type"
,
"image/png"
)
conn
.
requestMethod
=
"POST"
conn
.
doOutput
=
true
conn
.
outputStream
.
buffered
().
write
(
imageData
)
conn
.
doInput
=
true
conn
.
connect
()
val
buffered
=
conn
.
outputStream
.
buffered
()
buffered
.
write
(
imageData
)
buffered
.
flush
()
println
(
conn
.
responseMessage
)
println
(
conn
.
responseCode
)
return
conn
.
responseCode
==
200
...
...
mirai-debug/src/main/java/PacketDebuger.kt
View file @
3474c87f
...
...
@@ -73,7 +73,7 @@ object Main {
* 6. 运行到 `mov eax,dword ptr ss:[ebp+10]`
* 7. 查看内存, 从 `eax` 开始的 16 bytes 便是 `sessionKey`
*/
val
sessionKey
:
ByteArray
=
"
99 82 67 D4 62 20 CA 5D 81 F8 6F 83 EE 8A F7 68
"
.
hexToBytes
()
val
sessionKey
:
ByteArray
=
"
F1 ED F2 BC 55 17 7B FE CC CC F3 08 D1 8D A7 0E
"
.
hexToBytes
()
val
qq
:
UInt
=
1040400290
u
fun
dataReceived
(
data
:
ByteArray
)
{
...
...
@@ -175,9 +175,9 @@ object Main {
println
(
"好友消息"
)
val
raw
=
readRemainingBytes
()
println
(
"解密前数据: "
+
raw
.
toUHexString
())
//
println("解密前数据: " + raw.toUHexString())
val
messageData
=
raw
.
decryptBy
(
sessionKey
)
println
(
"解密结果: "
+
messageData
.
toUHexString
())
//
println("解密结果: " + messageData.toUHexString())
println
(
"尝试解消息"
)
try
{
...
...
@@ -195,10 +195,11 @@ object Main {
}
"03 88"
->
{
println
(
"上传图片-获取图片ID"
)
println
(
"
0388
上传图片-获取图片ID"
)
discardExact
(
8
)
val
body
=
readRemainingBytes
().
decryptBy
(
sessionKey
)
println
(
body
.
toUHexString
())
//val body = readRemainingBytes().decryptBy(sessionKey)
//println(body.toUHexString())
}
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment