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
a776b25b
Commit
a776b25b
authored
Feb 03, 2020
by
jiahua.liu
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/master'
parents
df24d101
b240370f
Changes
15
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
1160 additions
and
42 deletions
+1160
-42
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt
...ommonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt
+79
-2
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt
...tlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt
+5
-1
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/highway/Codec.kt
...kotlin/net/mamoe/mirai/qqandroid/network/highway/Codec.kt
+129
-0
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/data/proto/Cmd0x388.kt
...e/mirai/qqandroid/network/protocol/data/proto/Cmd0x388.kt
+279
-0
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/data/proto/Highway.kt
...oe/mirai/qqandroid/network/protocol/data/proto/Highway.kt
+454
-0
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/PacketFactory.kt
.../mirai/qqandroid/network/protocol/packet/PacketFactory.kt
+6
-1
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/image/ImageUpPacket.kt
...droid/network/protocol/packet/chat/image/ImageUpPacket.kt
+8
-11
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/image/ImgStore.kt
.../qqandroid/network/protocol/packet/chat/image/ImgStore.kt
+101
-0
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/image/LongConn.kt
.../qqandroid/network/protocol/packet/chat/image/LongConn.kt
+42
-0
mirai-core-qqandroid/src/jvmTest/kotlin/test/ProtoBufDataClassGenerator.kt
...oid/src/jvmTest/kotlin/test/ProtoBufDataClassGenerator.kt
+1
-1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Group.kt
...re/src/commonMain/kotlin/net.mamoe.mirai/contact/Group.kt
+0
-2
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Image.kt
...c/commonMain/kotlin/net.mamoe.mirai/message/data/Image.kt
+3
-2
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/ExternalImage.kt
.../commonMain/kotlin/net.mamoe.mirai/utils/ExternalImage.kt
+44
-18
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/ExternalImageJvm.kt
.../jvmMain/kotlin/net/mamoe/mirai/utils/ExternalImageJvm.kt
+4
-2
mirai-demos/mirai-demo-gentleman/build.gradle
mirai-demos/mirai-demo-gentleman/build.gradle
+5
-2
No files found.
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/ContactImpl.kt
View file @
a776b25b
package
net.mamoe.mirai.qqandroid
package
net.mamoe.mirai.qqandroid
import
kotlinx.io.core.readBytes
import
net.mamoe.mirai.contact.*
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.Image
import
net.mamoe.mirai.message.data.Image
import
net.mamoe.mirai.message.data.MessageChain
import
net.mamoe.mirai.message.data.MessageChain
import
net.mamoe.mirai.message.data.NotOnlineImageFromFile
import
net.mamoe.mirai.qqandroid.io.serialization.readProtoBuf
import
net.mamoe.mirai.qqandroid.network.highway.Highway
import
net.mamoe.mirai.qqandroid.network.protocol.data.proto.CSDataHighwayHead
import
net.mamoe.mirai.qqandroid.network.protocol.packet.chat.image.ImgStore
import
net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.MessageSvc
import
net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.MessageSvc
import
net.mamoe.mirai.qqandroid.network.protocol.packet.withUse
import
net.mamoe.mirai.qqandroid.utils.toIpV4AddressString
import
net.mamoe.mirai.utils.ExternalImage
import
net.mamoe.mirai.utils.ExternalImage
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.cryptor.contentToString
import
net.mamoe.mirai.utils.getValue
import
net.mamoe.mirai.utils.getValue
import
net.mamoe.mirai.utils.io.PlatformSocket
import
net.mamoe.mirai.utils.io.toUHexString
import
net.mamoe.mirai.utils.unsafeWeakRef
import
net.mamoe.mirai.utils.unsafeWeakRef
import
kotlin.coroutines.CoroutineContext
import
kotlin.coroutines.CoroutineContext
...
@@ -116,7 +127,73 @@ internal class GroupImpl(
...
@@ -116,7 +127,73 @@ internal class GroupImpl(
}
}
override
suspend
fun
uploadImage
(
image
:
ExternalImage
):
Image
{
override
suspend
fun
uploadImage
(
image
:
ExternalImage
):
Image
{
TODO
(
"not implemented"
)
bot
.
network
.
run
{
val
response
:
ImgStore
.
GroupPicUp
.
Response
=
ImgStore
.
GroupPicUp
(
bot
.
client
,
uin
=
bot
.
uin
,
groupCode
=
id
,
md5
=
image
.
md5
,
size
=
image
.
inputSize
,
picWidth
=
image
.
width
,
picHeight
=
image
.
height
,
picType
=
image
.
imageType
,
filename
=
image
.
filename
).
sendAndExpect
()
when
(
response
)
{
is
ImgStore
.
GroupPicUp
.
Response
.
Failed
->
error
(
"upload group image failed with reason ${response.message}"
)
is
ImgStore
.
GroupPicUp
.
Response
.
FileExists
->
{
val
resourceId
=
image
.
calculateImageResourceId
()
return
NotOnlineImageFromFile
(
resourceId
=
resourceId
,
md5
=
response
.
fileInfo
.
fileMd5
,
filepath
=
resourceId
,
fileLength
=
response
.
fileInfo
.
fileSize
.
toInt
(),
height
=
response
.
fileInfo
.
fileHeight
,
width
=
response
.
fileInfo
.
fileWidth
,
imageType
=
response
.
fileInfo
.
fileType
)
}
is
ImgStore
.
GroupPicUp
.
Response
.
RequireUpload
->
{
val
socket
=
PlatformSocket
()
socket
.
connect
(
response
.
uploadIpList
.
first
().
toIpV4AddressString
().
also
{
println
(
"serverIp=$it"
)
},
response
.
uploadPortList
.
first
())
// socket.use {
socket
.
send
(
Highway
.
RequestDataTrans
(
uin
=
bot
.
uin
,
command
=
"PicUp.DataUp"
,
buildVer
=
bot
.
client
.
buildVer
,
uKey
=
response
.
uKey
,
data
=
image
.
input
,
dataSize
=
image
.
inputSize
.
toInt
(),
md5
=
image
.
md5
,
sequenceId
=
bot
.
client
.
nextHighwayDataTransSequenceId
()
)
)
// }
//0A 3C 08 01 12 0A 31 39 39 34 37 30 31 30 32 31 1A 0C 50 69 63 55 70 2E 44 61 74 61 55 70 20 E9 A7 05 28 00 30 BD DB 8B 80 02 38 80 20 40 02 4A 0A 38 2E 32 2E 30 2E 31 32 39 36 50 84 10 12 3D 08 00 10 FD 08 18 00 20 FD 08 28 C6 01 38 00 42 10 D4 1D 8C D9 8F 00 B2 04 E9 80 09 98 EC F8 42 7E 4A 10 D4 1D 8C D9 8F 00 B2 04 E9 80 09 98 EC F8 42 7E 50 89 92 A2 FB 06 58 00 60 00 18 53 20 01 28 00 30 04 3A 00 40 E6 B7 F7 D9 80 2E 48 00 50 00
socket
.
read
().
withUse
{
readByte
()
val
headLength
=
readInt
()
val
bodyLength
=
readInt
()
val
proto
=
readProtoBuf
(
CSDataHighwayHead
.
RspDataHighwayHead
.
serializer
(),
length
=
headLength
)
println
(
proto
.
contentToString
())
println
(
readBytes
(
bodyLength
).
toUHexString
())
}
val
resourceId
=
image
.
calculateImageResourceId
()
return
NotOnlineImageFromFile
(
resourceId
=
resourceId
,
md5
=
image
.
md5
,
filepath
=
resourceId
,
fileLength
=
image
.
inputSize
.
toInt
(),
height
=
image
.
height
,
width
=
image
.
width
,
imageType
=
image
.
imageType
)
}
}
}
}
}
}
}
\ No newline at end of file
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt
View file @
a776b25b
...
@@ -95,7 +95,8 @@ internal open class QQAndroidClient(
...
@@ -95,7 +95,8 @@ internal open class QQAndroidClient(
var
openAppId
:
Long
=
715019303L
var
openAppId
:
Long
=
715019303L
val
apkVersionName
:
ByteArray
=
"8.2.0"
.
toByteArray
()
val
apkVersionName
:
ByteArray
get
()
=
"8.2.0"
.
toByteArray
()
val
buildVer
:
String
get
()
=
"8.2.0.1296"
private
val
messageSequenceId
:
AtomicInt
=
atomic
(
0
)
private
val
messageSequenceId
:
AtomicInt
=
atomic
(
0
)
internal
fun
atomicNextMessageSequenceId
():
Int
=
messageSequenceId
.
getAndAdd
(
2
)
internal
fun
atomicNextMessageSequenceId
():
Int
=
messageSequenceId
.
getAndAdd
(
2
)
...
@@ -103,6 +104,9 @@ internal open class QQAndroidClient(
...
@@ -103,6 +104,9 @@ internal open class QQAndroidClient(
private
val
requestPacketRequestId
:
AtomicInt
=
atomic
(
1921334513
)
private
val
requestPacketRequestId
:
AtomicInt
=
atomic
(
1921334513
)
internal
fun
nextRequestPacketRequestId
():
Int
=
requestPacketRequestId
.
getAndAdd
(
2
)
internal
fun
nextRequestPacketRequestId
():
Int
=
requestPacketRequestId
.
getAndAdd
(
2
)
private
val
highwayDataTransSequenceId
:
AtomicInt
=
atomic
(
87017
)
internal
fun
nextHighwayDataTransSequenceId
():
Int
=
highwayDataTransSequenceId
.
getAndAdd
(
2
)
val
appClientVersion
:
Int
=
0
val
appClientVersion
:
Int
=
0
var
networkType
:
NetworkType
=
NetworkType
.
WIFI
var
networkType
:
NetworkType
=
NetworkType
.
WIFI
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/highway/Codec.kt
0 → 100644
View file @
a776b25b
package
net.mamoe.mirai.qqandroid.network.highway
import
io.ktor.client.HttpClient
import
io.ktor.client.request.post
import
io.ktor.http.ContentType
import
io.ktor.http.HttpStatusCode
import
io.ktor.http.URLProtocol
import
io.ktor.http.content.OutgoingContent
import
io.ktor.http.userAgent
import
kotlinx.coroutines.io.ByteWriteChannel
import
kotlinx.io.core.*
import
kotlinx.io.pool.useInstance
import
net.mamoe.mirai.qqandroid.io.serialization.toByteArray
import
net.mamoe.mirai.qqandroid.network.protocol.data.proto.CSDataHighwayHead
import
net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
import
net.mamoe.mirai.utils.io.ByteArrayPool
@Suppress
(
"SpellCheckingInspection"
)
internal
suspend
inline
fun
HttpClient
.
postImage
(
htcmd
:
String
,
uin
:
Long
,
groupcode
:
Long
?,
imageInput
:
Input
,
inputSize
:
Long
,
uKeyHex
:
String
):
Boolean
=
try
{
post
<
HttpStatusCode
>
{
url
{
protocol
=
URLProtocol
.
HTTP
host
=
"htdata2.qq.com"
path
(
"cgi-bin/httpconn"
)
parameters
[
"htcmd"
]
=
htcmd
parameters
[
"uin"
]
=
uin
.
toString
()
if
(
groupcode
!=
null
)
parameters
[
"groupcode"
]
=
groupcode
.
toString
()
parameters
[
"term"
]
=
"pc"
parameters
[
"ver"
]
=
"5603"
parameters
[
"filesize"
]
=
inputSize
.
toString
()
parameters
[
"range"
]
=
0
.
toString
()
parameters
[
"ukey"
]
=
uKeyHex
userAgent
(
"QQClient"
)
}
body
=
object
:
OutgoingContent
.
WriteChannelContent
()
{
override
val
contentType
:
ContentType
=
ContentType
.
Image
.
Any
override
val
contentLength
:
Long
=
inputSize
override
suspend
fun
writeTo
(
channel
:
ByteWriteChannel
)
{
ByteArrayPool
.
useInstance
{
buffer
:
ByteArray
->
var
size
:
Int
while
(
imageInput
.
readAvailable
(
buffer
).
also
{
size
=
it
}
!=
0
)
{
channel
.
writeFully
(
buffer
,
0
,
size
)
}
}
}
}
}
==
HttpStatusCode
.
OK
}
finally
{
imageInput
.
close
()
}
object
Highway
{
fun
RequestDataTrans
(
uin
:
Long
,
command
:
String
,
sequenceId
:
Int
,
buildVer
:
String
,
appId
:
Int
=
537062845
,
dataFlag
:
Int
=
4096
,
commandId
:
Int
=
2
,
localId
:
Int
=
2052
,
uKey
:
ByteArray
,
data
:
Input
,
dataSize
:
Int
,
md5
:
ByteArray
):
ByteReadPacket
{
val
dataHighwayHead
=
CSDataHighwayHead
.
DataHighwayHead
(
version
=
1
,
uin
=
uin
.
toString
(),
command
=
command
,
seq
=
sequenceId
,
retryTimes
=
0
,
appid
=
appId
,
dataflag
=
dataFlag
,
commandId
=
commandId
,
buildVer
=
buildVer
,
localeId
=
localId
)
val
segHead
=
CSDataHighwayHead
.
SegHead
(
datalength
=
dataSize
,
filesize
=
dataSize
.
toLong
()
and
0
xFFffFFff
,
serviceticket
=
uKey
,
md5
=
md5
,
fileMd5
=
md5
)
return
Codec
.
buildC2SData
(
dataHighwayHead
,
segHead
,
EMPTY_BYTE_ARRAY
,
null
,
data
,
dataSize
)
}
private
object
Codec
{
fun
buildC2SData
(
dataHighwayHead
:
CSDataHighwayHead
.
DataHighwayHead
,
segHead
:
CSDataHighwayHead
.
SegHead
,
extendInfo
:
ByteArray
,
loginSigHead
:
CSDataHighwayHead
.
LoginSigHead
?,
body
:
Input
,
bodySize
:
Int
):
ByteReadPacket
{
val
head
=
CSDataHighwayHead
.
ReqDataHighwayHead
(
msgBasehead
=
dataHighwayHead
,
msgSeghead
=
segHead
,
reqExtendinfo
=
extendInfo
,
msgLoginSigHead
=
loginSigHead
).
toByteArray
(
CSDataHighwayHead
.
ReqDataHighwayHead
.
serializer
())
return
buildPacket
{
writeByte
(
40
)
writeInt
(
head
.
size
)
writeInt
(
bodySize
)
writeFully
(
head
)
body
.
copyTo
(
this
)
writeByte
(
41
)
}
}
}
}
\ No newline at end of file
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/data/proto/Cmd0x388.kt
0 → 100644
View file @
a776b25b
This diff is collapsed.
Click to expand it.
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/data/proto/Highway.kt
0 → 100644
View file @
a776b25b
This diff is collapsed.
Click to expand it.
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/PacketFactory.kt
View file @
a776b25b
...
@@ -5,7 +5,9 @@ import kotlinx.io.pool.useInstance
...
@@ -5,7 +5,9 @@ import kotlinx.io.pool.useInstance
import
net.mamoe.mirai.data.Packet
import
net.mamoe.mirai.data.Packet
import
net.mamoe.mirai.event.Subscribable
import
net.mamoe.mirai.event.Subscribable
import
net.mamoe.mirai.qqandroid.QQAndroidBot
import
net.mamoe.mirai.qqandroid.QQAndroidBot
import
net.mamoe.mirai.qqandroid.network.protocol.packet.chat.TroopManagement
import
net.mamoe.mirai.qqandroid.network.protocol.packet.chat.image.ImageUpPacket
import
net.mamoe.mirai.qqandroid.network.protocol.packet.chat.image.ImgStore
import
net.mamoe.mirai.qqandroid.network.protocol.packet.chat.image.LongConn
import
net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.MessageSvc
import
net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.MessageSvc
import
net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.OnlinePush
import
net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.OnlinePush
import
net.mamoe.mirai.qqandroid.network.protocol.packet.list.FriendList
import
net.mamoe.mirai.qqandroid.network.protocol.packet.list.FriendList
...
@@ -119,6 +121,9 @@ internal object KnownPacketFactories {
...
@@ -119,6 +121,9 @@ internal object KnownPacketFactories {
FriendList
.
GetFriendGroupList
,
FriendList
.
GetFriendGroupList
,
FriendList
.
GetTroopListSimplify
,
FriendList
.
GetTroopListSimplify
,
FriendList
.
GetTroopMemberList
,
FriendList
.
GetTroopMemberList
,
ImgStore
.
GroupPicUp
,
ImageUpPacket
,
LongConn
.
OffPicDown
,
TroopManagement
.
EditNametag
,
TroopManagement
.
EditNametag
,
TroopManagement
.
Mute
,
TroopManagement
.
Mute
,
TroopManagement
.
MuteAll
TroopManagement
.
MuteAll
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/image/ImageUpPacket.kt
View file @
a776b25b
...
@@ -10,15 +10,13 @@ import net.mamoe.mirai.qqandroid.network.protocol.data.proto.Cmd0x352Packet
...
@@ -10,15 +10,13 @@ import net.mamoe.mirai.qqandroid.network.protocol.data.proto.Cmd0x352Packet
import
net.mamoe.mirai.qqandroid.network.protocol.data.proto.UploadImgReq
import
net.mamoe.mirai.qqandroid.network.protocol.data.proto.UploadImgReq
import
net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket
import
net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket
import
net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacketFactory
import
net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacketFactory
import
net.mamoe.mirai.qqandroid.network.protocol.packet.buildLoginOutgoingPacket
import
net.mamoe.mirai.qqandroid.network.protocol.packet.buildOutgoingUniPacket
import
net.mamoe.mirai.qqandroid.network.protocol.packet.writeSsoPacket
internal
object
ImageUpPacket
:
OutgoingPacketFactory
<
ImageUpPacket
.
ImageUpPacketResponse
>(
"LongConn.OffPicUp"
)
{
internal
object
ImageUpPacket
:
OutgoingPacketFactory
<
ImageUpPacket
.
ImageUpPacketResponse
>(
"LongConn.OffPicUp"
)
{
operator
fun
invoke
(
client
:
QQAndroidClient
,
req
:
UploadImgReq
):
OutgoingPacket
{
operator
fun
invoke
(
client
:
QQAndroidClient
,
req
:
UploadImgReq
):
OutgoingPacket
{
// TODO: 2020/1/24 测试: bodyType, subAppId
// TODO: 2020/1/24 测试: bodyType, subAppId
return
buildLoginOutgoingPacket
(
client
,
key
=
client
.
wLoginSigInfo
.
d2Key
,
bodyType
=
1
)
{
return
buildOutgoingUniPacket
(
client
)
{
writeSsoPacket
(
client
,
subAppId
=
0
,
commandName
=
commandName
,
sequenceId
=
it
)
{
val
data
=
ProtoBufWithNullableSupport
.
dump
(
val
data
=
ProtoBufWithNullableSupport
.
dump
(
Cmd0x352Packet
.
serializer
(),
Cmd0x352Packet
.
serializer
(),
Cmd0x352Packet
.
createByImageRequest
(
req
)
Cmd0x352Packet
.
createByImageRequest
(
req
)
...
@@ -27,7 +25,6 @@ internal object ImageUpPacket : OutgoingPacketFactory<ImageUpPacket.ImageUpPacke
...
@@ -27,7 +25,6 @@ internal object ImageUpPacket : OutgoingPacketFactory<ImageUpPacket.ImageUpPacke
writeFully
(
data
)
writeFully
(
data
)
}
}
}
}
}
override
suspend
fun
ByteReadPacket
.
decode
(
bot
:
QQAndroidBot
):
ImageUpPacketResponse
{
override
suspend
fun
ByteReadPacket
.
decode
(
bot
:
QQAndroidBot
):
ImageUpPacketResponse
{
TODO
(
"not implemented"
)
//To change body of created functions use File | Settings | File Templates.
TODO
(
"not implemented"
)
//To change body of created functions use File | Settings | File Templates.
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/image/ImgStore.kt
0 → 100644
View file @
a776b25b
package
net.mamoe.mirai.qqandroid.network.protocol.packet.chat.image
import
io.ktor.client.HttpClient
import
kotlinx.io.core.ByteReadPacket
import
net.mamoe.mirai.data.Packet
import
net.mamoe.mirai.qqandroid.QQAndroidBot
import
net.mamoe.mirai.qqandroid.io.serialization.readProtoBuf
import
net.mamoe.mirai.qqandroid.io.serialization.writeProtoBuf
import
net.mamoe.mirai.qqandroid.network.QQAndroidClient
import
net.mamoe.mirai.qqandroid.network.protocol.data.proto.Cmd0x388
import
net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacket
import
net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacketFactory
import
net.mamoe.mirai.qqandroid.network.protocol.packet.buildOutgoingUniPacket
internal
class
ImgStore
{
object
GroupPicUp
:
OutgoingPacketFactory
<
GroupPicUp
.
Response
>(
"ImgStore.GroupPicUp"
)
{
operator
fun
invoke
(
client
:
QQAndroidClient
,
uin
:
Long
,
groupCode
:
Long
,
md5
:
ByteArray
,
size
:
Long
,
picWidth
:
Int
,
picHeight
:
Int
,
picType
:
Int
=
1000
,
fileId
:
Long
=
0
,
filename
:
String
,
srcTerm
:
Int
=
5
,
platformType
:
Int
=
9
,
buType
:
Int
=
1
,
appPicType
:
Int
=
1006
,
originalPic
:
Int
=
0
):
OutgoingPacket
=
buildOutgoingUniPacket
(
client
)
{
writeProtoBuf
(
Cmd0x388
.
ReqBody
.
serializer
(),
Cmd0x388
.
ReqBody
(
netType
=
3
,
// wifi
subcmd
=
1
,
msgTryupImgReq
=
listOf
(
Cmd0x388
.
TryUpImgReq
(
groupCode
=
groupCode
,
srcUin
=
uin
,
fileMd5
=
md5
,
fileSize
=
size
,
fileId
=
fileId
,
fileName
=
filename
,
picWidth
=
picWidth
,
picHeight
=
picHeight
,
picType
=
picType
,
appPicType
=
appPicType
,
buildVer
=
client
.
buildVer
,
srcTerm
=
srcTerm
,
platformType
=
platformType
,
originalPic
=
originalPic
,
buType
=
buType
)
)
)
)
}
sealed
class
Response
:
Packet
{
class
FileExists
(
val
fileId
:
Long
,
val
fileInfo
:
Cmd0x388
.
ImgInfo
)
:
Response
()
{
override
fun
toString
():
String
{
return
"FileExists(fileId=$fileId, fileInfo=$fileInfo)"
}
}
class
RequireUpload
(
val
fileId
:
Long
,
val
uKey
:
ByteArray
,
val
uploadIpList
:
List
<
Int
>,
val
uploadPortList
:
List
<
Int
>
)
:
Response
()
{
override
fun
toString
():
String
{
return
"RequireUpload(fileId=$fileId, uKey=${uKey.contentToString()})"
}
}
data class
Failed
(
val
resultCode
:
Int
,
val
message
:
String
)
:
Response
()
}
override
suspend
fun
ByteReadPacket
.
decode
(
bot
:
QQAndroidBot
):
Response
{
val
resp0
=
readProtoBuf
(
Cmd0x388
.
RspBody
.
serializer
())
resp0
.
msgTryupImgRsp
?:
error
(
"cannot find `msgTryupImgRsp` from `Cmd0x388.RspBody`"
)
val
resp
=
resp0
.
msgTryupImgRsp
.
first
()
return
when
{
resp
.
result
!=
0
->
Response
.
Failed
(
resultCode
=
resp
.
result
,
message
=
resp
.
failMsg
)
resp
.
boolFileExit
->
Response
.
FileExists
(
fileId
=
resp
.
fileid
,
fileInfo
=
resp
.
msgImgInfo
!!
)
else
->
Response
.
RequireUpload
(
fileId
=
resp
.
fileid
,
uKey
=
resp
.
upUkey
,
uploadIpList
=
resp
.
uint32UpIp
!!
,
uploadPortList
=
resp
.
uint32UpPort
!!
)
}
}
}
}
\ No newline at end of file
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/image/
ImageDownPacket
.kt
→
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/image/
LongConn
.kt
View file @
a776b25b
...
@@ -13,8 +13,9 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacketFactory
...
@@ -13,8 +13,9 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.OutgoingPacketFactory
import
net.mamoe.mirai.qqandroid.network.protocol.packet.buildLoginOutgoingPacket
import
net.mamoe.mirai.qqandroid.network.protocol.packet.buildLoginOutgoingPacket
import
net.mamoe.mirai.qqandroid.network.protocol.packet.writeSsoPacket
import
net.mamoe.mirai.qqandroid.network.protocol.packet.writeSsoPacket
internal
object
ImageDownPacket
:
OutgoingPacketFactory
<
ImageDownPacket
.
ImageDownPacketResponse
>(
"LongConn.OffPicDown"
)
{
internal
class
LongConn
{
object
OffPicDown
:
OutgoingPacketFactory
<
OffPicDown
.
ImageDownPacketResponse
>(
"LongConn.OffPicDown"
){
operator
fun
invoke
(
client
:
QQAndroidClient
,
req
:
GetImgUrlReq
):
OutgoingPacket
{
operator
fun
invoke
(
client
:
QQAndroidClient
,
req
:
GetImgUrlReq
):
OutgoingPacket
{
// TODO: 2020/1/24 测试: bodyType, subAppId
// TODO: 2020/1/24 测试: bodyType, subAppId
return
buildLoginOutgoingPacket
(
client
,
key
=
client
.
wLoginSigInfo
.
d2Key
,
bodyType
=
1
)
{
return
buildLoginOutgoingPacket
(
client
,
key
=
client
.
wLoginSigInfo
.
d2Key
,
bodyType
=
1
)
{
...
@@ -37,6 +38,5 @@ internal object ImageDownPacket : OutgoingPacketFactory<ImageDownPacket.ImageDow
...
@@ -37,6 +38,5 @@ internal object ImageDownPacket : OutgoingPacketFactory<ImageDownPacket.ImageDow
sealed
class
ImageDownPacketResponse
:
Packet
{
sealed
class
ImageDownPacketResponse
:
Packet
{
object
Success
:
ImageDownPacketResponse
()
object
Success
:
ImageDownPacketResponse
()
}
}
}
}
}
\ No newline at end of file
mirai-core-qqandroid/src/jvmTest/kotlin/test/ProtoBufDataClassGenerator.kt
View file @
a776b25b
...
@@ -6,7 +6,7 @@ import java.io.File
...
@@ -6,7 +6,7 @@ import java.io.File
fun
main
()
{
fun
main
()
{
println
(
println
(
File
(
"""/Users/jiahua.liu/Desktop/QQAndroid-F/app/src/main/java/tencent/im/
group/group_label/
"""
)
File
(
"""/Users/jiahua.liu/Desktop/QQAndroid-F/app/src/main/java/tencent/im/
s2c/msgtype0x210/submsgtype0xc7/bussinfo/mutualmark
"""
)
.
generateUnarrangedClasses
().
toMutableList
().
arrangeClasses
().
joinToString
(
"\n\n"
)
.
generateUnarrangedClasses
().
toMutableList
().
arrangeClasses
().
joinToString
(
"\n\n"
)
)
)
}
}
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Group.kt
View file @
a776b25b
...
@@ -31,8 +31,6 @@ interface Group : Contact, CoroutineScope {
...
@@ -31,8 +31,6 @@ interface Group : Contact, CoroutineScope {
/**
/**
* 在 [Group] 实例创建的时候查询一次. 并与事件同步事件更新
* 在 [Group] 实例创建的时候查询一次. 并与事件同步事件更新
*
* **注意**: 获得的列表仅为这一时刻的成员列表的镜像. 它将不会被更新
*/
*/
val
members
:
ContactList
<
Member
>
val
members
:
ContactList
<
Member
>
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Image.kt
View file @
a776b25b
...
@@ -5,6 +5,7 @@ package net.mamoe.mirai.message.data
...
@@ -5,6 +5,7 @@ package net.mamoe.mirai.message.data
import
kotlinx.serialization.Serializable
import
kotlinx.serialization.Serializable
sealed
class
Image
:
Message
{
sealed
class
Image
:
Message
{
abstract
val
filepath
:
String
abstract
val
md5
:
ByteArray
abstract
val
md5
:
ByteArray
abstract
override
fun
toString
():
String
abstract
override
fun
toString
():
String
...
@@ -15,7 +16,7 @@ sealed class Image : Message {
...
@@ -15,7 +16,7 @@ sealed class Image : Message {
}
}
abstract
class
CustomFace
:
Image
()
{
abstract
class
CustomFace
:
Image
()
{
abstract
val
filepath
:
String
abstract
override
val
filepath
:
String
abstract
val
fileId
:
Int
abstract
val
fileId
:
Int
abstract
val
serverIp
:
Int
abstract
val
serverIp
:
Int
abstract
val
serverPort
:
Int
abstract
val
serverPort
:
Int
...
@@ -106,7 +107,7 @@ data class CustomFaceFromFile(
...
@@ -106,7 +107,7 @@ data class CustomFaceFromFile(
abstract
class
NotOnlineImage
:
Image
()
{
abstract
class
NotOnlineImage
:
Image
()
{
abstract
val
resourceId
:
String
abstract
val
resourceId
:
String
abstract
override
val
md5
:
ByteArray
abstract
override
val
md5
:
ByteArray
abstract
val
filepath
:
String
abstract
override
val
filepath
:
String
abstract
val
fileLength
:
Int
abstract
val
fileLength
:
Int
abstract
val
height
:
Int
abstract
val
height
:
Int
abstract
val
width
:
Int
abstract
val
width
:
Int
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/ExternalImage.kt
View file @
a776b25b
...
@@ -7,18 +7,10 @@ import kotlinx.io.core.Input
...
@@ -7,18 +7,10 @@ import kotlinx.io.core.Input
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.QQ
import
net.mamoe.mirai.contact.QQ
import
net.mamoe.mirai.message.data.*
import
net.mamoe.mirai.message.data.Image
import
net.mamoe.mirai.message.data.sendTo
import
net.mamoe.mirai.utils.io.toUHexString
import
net.mamoe.mirai.utils.io.toUHexString
@Suppress
(
"FunctionName"
)
fun
ExternalImage
(
width
:
Int
,
height
:
Int
,
md5
:
ByteArray
,
format
:
String
,
data
:
ByteReadPacket
):
ExternalImage
=
ExternalImage
(
width
,
height
,
md5
,
format
,
data
,
data
.
remaining
)
/**
/**
* 外部图片. 图片数据还没有读取到内存.
* 外部图片. 图片数据还没有读取到内存.
*
*
...
@@ -33,19 +25,53 @@ class ExternalImage(
...
@@ -33,19 +25,53 @@ class ExternalImage(
val
md5
:
ByteArray
,
val
md5
:
ByteArray
,
imageFormat
:
String
,
imageFormat
:
String
,
val
input
:
Input
,
val
input
:
Input
,
val
inputSize
:
Long
val
inputSize
:
Long
,
val
filename
:
String
)
{
)
{
private
val
format
:
String
companion
object
{
operator
fun
invoke
(
width
:
Int
,
height
:
Int
,
md5
:
ByteArray
,
format
:
String
,
data
:
ByteReadPacket
,
filename
:
String
):
ExternalImage
=
ExternalImage
(
width
,
height
,
md5
,
format
,
data
,
data
.
remaining
,
filename
)
}
init
{
private
val
format
:
String
=
when
(
val
it
=
imageFormat
.
toLowerCase
())
{
if
(
imageFormat
==
"JPEG"
||
imageFormat
==
"jpeg"
)
{
//必须转换
"jpeg"
->
"jpg"
//必须转换
this
.
format
=
"jpg"
else
->
it
}
else
{
this
.
format
=
imageFormat
}
}
/**
*
* ImgType:
* JPG: 1000
* PNG: 1001
* WEBP: 1002
* BMP: 1005
* GIG: 2000
* APNG: 2001
* SHARPP: 1004
*/
val
imageType
:
Int
get
()
=
when
(
format
){
"jpg"
->
1000
"png"
->
1001
"webp"
->
1002
"bmp"
->
1005
"gig"
->
2000
"apng"
->
2001
"sharpp"
->
1004
else
->
1000
// unsupported, just make it jpg
}
}
override
fun
toString
():
String
=
"[ExternalImage(${width}x$height $format)]"
override
fun
toString
():
String
=
"[ExternalImage(${width}x$height $format)]"
fun
calculateImageResourceId
():
String
{
return
"{${md5[0..3]}-${md5[4..5]}-${md5[6..7]}-${md5[8..9]}-${md5[10..15]}}.$format"
}
}
}
/**
/**
...
...
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/ExternalImageJvm.kt
View file @
a776b25b
...
@@ -12,6 +12,7 @@ import kotlinx.io.core.copyTo
...
@@ -12,6 +12,7 @@ import kotlinx.io.core.copyTo
import
kotlinx.io.errors.IOException
import
kotlinx.io.errors.IOException
import
kotlinx.io.streams.asInput
import
kotlinx.io.streams.asInput
import
kotlinx.io.streams.asOutput
import
kotlinx.io.streams.asOutput
import
net.mamoe.mirai.utils.io.getRandomString
import
java.awt.image.BufferedImage
import
java.awt.image.BufferedImage
import
java.io.File
import
java.io.File
import
java.io.InputStream
import
java.io.InputStream
...
@@ -44,7 +45,7 @@ fun BufferedImage.toExternalImage(formatName: String = "gif"): ExternalImage {
...
@@ -44,7 +45,7 @@ fun BufferedImage.toExternalImage(formatName: String = "gif"): ExternalImage {
})
})
}
}
return
ExternalImage
(
width
,
height
,
digest
.
digest
(),
formatName
,
buffer
)
return
ExternalImage
(
width
,
height
,
digest
.
digest
(),
formatName
,
buffer
,
getRandomString
(
10
)
+
"."
+
formatName
)
}
}
suspend
inline
fun
BufferedImage
.
suspendToExternalImage
():
ExternalImage
=
withContext
(
IO
)
{
toExternalImage
()
}
suspend
inline
fun
BufferedImage
.
suspendToExternalImage
():
ExternalImage
=
withContext
(
IO
)
{
toExternalImage
()
}
...
@@ -66,7 +67,8 @@ fun File.toExternalImage(): ExternalImage {
...
@@ -66,7 +67,8 @@ fun File.toExternalImage(): ExternalImage {
md5
=
this
.
inputStream
().
use
{
it
.
md5
()
},
md5
=
this
.
inputStream
().
use
{
it
.
md5
()
},
imageFormat
=
image
.
formatName
,
imageFormat
=
image
.
formatName
,
input
=
this
.
inputStream
().
asInput
(
IoBuffer
.
Pool
),
input
=
this
.
inputStream
().
asInput
(
IoBuffer
.
Pool
),
inputSize
=
this
.
length
()
inputSize
=
this
.
length
(),
filename
=
this
.
name
)
)
}
}
...
...
mirai-demos/mirai-demo-gentleman/build.gradle
View file @
a776b25b
...
@@ -15,7 +15,10 @@ dependencies {
...
@@ -15,7 +15,10 @@ dependencies {
implementation
'org.jsoup:jsoup:1.12.1'
implementation
'org.jsoup:jsoup:1.12.1'
}
}
mainClassName
=
"demo.gentleman.MainKt"
run
{
standardInput
=
System
.
in
mainClassName
=
"demo.gentleman.MainKt"
}
compileKotlin
{
compileKotlin
{
kotlinOptions
{
kotlinOptions
{
freeCompilerArgs
=
[
"-XXLanguage:+InlineClasses"
]
freeCompilerArgs
=
[
"-XXLanguage:+InlineClasses"
]
...
...
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