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
3f523e6f
Commit
3f523e6f
authored
Mar 27, 2020
by
Him188
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Long message
parent
e495b91d
Changes
16
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
996 additions
and
49 deletions
+996
-49
mirai-core-qqandroid/src/androidMain/kotlin/net/mamoe/mirai/qqandroid/utils/cryptor/arraycopy.kt
...tlin/net/mamoe/mirai/qqandroid/utils/cryptor/arraycopy.kt
+9
-0
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt
...mmonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt
+32
-0
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/MessageSourceImpl.kt
...in/net/mamoe/mirai/qqandroid/message/MessageSourceImpl.kt
+1
-1
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/messages.kt
...Main/kotlin/net/mamoe/mirai/qqandroid/message/messages.kt
+69
-29
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt
...tlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt
+1
-1
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/data/proto/LongMsg.kt
...oe/mirai/qqandroid/network/protocol/data/proto/LongMsg.kt
+72
-0
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/data/proto/MsgTransmit.kt
...irai/qqandroid/network/protocol/data/proto/MsgTransmit.kt
+25
-0
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/data/proto/MultiMsg.kt
...e/mirai/qqandroid/network/protocol/data/proto/MultiMsg.kt
+80
-0
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/PacketFactory.kt
.../mirai/qqandroid/network/protocol/packet/PacketFactory.kt
+4
-2
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/MultiMsg.kt
.../mirai/qqandroid/network/protocol/packet/chat/MultiMsg.kt
+222
-0
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils/cryptor/MultiMsgCryptor.kt
...et/mamoe/mirai/qqandroid/utils/cryptor/MultiMsgCryptor.kt
+32
-0
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils/cryptor/class_1457.kt
...lin/net/mamoe/mirai/qqandroid/utils/cryptor/class_1457.kt
+382
-0
mirai-core-qqandroid/src/jvmMain/kotlin/net/mamoe/mirai/qqandroid/utils/cryptor/arraycopy.kt
...tlin/net/mamoe/mirai/qqandroid/utils/cryptor/arraycopy.kt
+9
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/lowLevelApi.kt
...core/src/commonMain/kotlin/net.mamoe.mirai/lowLevelApi.kt
+9
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/PlainText.kt
...mmonMain/kotlin/net.mamoe.mirai/message/data/PlainText.kt
+2
-16
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/RichMessage.kt
...onMain/kotlin/net.mamoe.mirai/message/data/RichMessage.kt
+47
-0
No files found.
mirai-core-qqandroid/src/androidMain/kotlin/net/mamoe/mirai/qqandroid/utils/cryptor/arraycopy.kt
0 → 100644
View file @
3f523e6f
package
net.mamoe.mirai.qqandroid.utils.cryptor
internal
actual
fun
arraycopy
(
src
:
ByteArray
,
srcPos
:
Int
,
dest
:
ByteArray
,
destPos
:
Int
,
length
:
Int
)
=
System
.
arraycopy
(
src
,
srcPos
,
dest
,
destPos
,
length
)
\ No newline at end of file
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt
View file @
3f523e6f
...
...
@@ -33,11 +33,13 @@ import net.mamoe.mirai.message.data.*
import
net.mamoe.mirai.qqandroid.contact.MemberInfoImpl
import
net.mamoe.mirai.qqandroid.contact.QQImpl
import
net.mamoe.mirai.qqandroid.contact.checkIsGroupImpl
import
net.mamoe.mirai.qqandroid.message.MessageSourceFromSendFriend
import
net.mamoe.mirai.qqandroid.message.OnlineFriendImageImpl
import
net.mamoe.mirai.qqandroid.message.OnlineGroupImageImpl
import
net.mamoe.mirai.qqandroid.network.QQAndroidBotNetworkHandler
import
net.mamoe.mirai.qqandroid.network.QQAndroidClient
import
net.mamoe.mirai.qqandroid.network.protocol.packet.chat.GroupInfoImpl
import
net.mamoe.mirai.qqandroid.network.protocol.packet.chat.MultiMsg
import
net.mamoe.mirai.qqandroid.network.protocol.packet.chat.PbMessageSvc
import
net.mamoe.mirai.qqandroid.network.protocol.packet.chat.TroopManagement
import
net.mamoe.mirai.qqandroid.network.protocol.packet.list.FriendList
...
...
@@ -45,6 +47,8 @@ import net.mamoe.mirai.utils.*
import
net.mamoe.mirai.utils.io.encodeToString
import
kotlin.collections.asSequence
import
kotlin.coroutines.CoroutineContext
import
kotlin.math.absoluteValue
import
kotlin.random.Random
@OptIn
(
MiraiInternalAPI
::
class
)
internal
expect
class
QQAndroidBot
constructor
(
...
...
@@ -360,6 +364,34 @@ internal abstract class QQAndroidBotBase constructor(
return
json
.
parse
(
GroupActiveData
.
serializer
(),
rep
)
}
@LowLevelAPI
@MiraiExperimentalAPI
override
suspend
fun
_lowLevelSendLongMessage
(
groupCode
:
Long
,
message
:
Message
)
{
val
source
=
MessageSourceFromSendFriend
(
messageRandom
=
Random
.
nextInt
().
absoluteValue
,
senderId
=
client
.
uin
,
toUin
=
Group
.
calculateGroupUinByGroupCode
(
groupCode
),
time
=
currentTimeSeconds
,
groupId
=
groupCode
,
originalMessage
=
message
.
asMessageChain
(),
sequenceId
=
0
// sourceMessage = message
)
// TODO: 2020/3/26 util 方法来添加单例元素
val
toSend
=
buildMessageChain
{
source
.
originalMessage
.
filter
{
it
!
is
MessageSource
}.
forEach
{
add
(
it
)
}
add
(
source
)
}
network
.
run
{
val
response
=
MultiMsg
.
ApplyUp
.
createForLongMessage
(
this
@QQAndroidBotBase
.
client
,
toSend
,
groupCode
)
.
sendAndExpect
<
MultiMsg
.
ApplyUp
.
Response
>()
println
(
response
.
_miraiContentToString
())
}
}
override
suspend
fun
queryImageUrl
(
image
:
Image
):
String
=
when
(
image
)
{
is
OnlineFriendImageImpl
->
image
.
originUrl
is
OnlineGroupImageImpl
->
image
.
originUrl
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/MessageSourceImpl.kt
View file @
3f523e6f
...
...
@@ -254,7 +254,7 @@ internal class MessageSourceFromSendGroup(
override
val
groupId
:
Long
,
override
val
originalMessage
:
MessageChain
)
:
MessageSourceFromSend
()
{
private
lateinit
var
sequenceIdDeferred
:
Deferred
<
Int
>
internal
lateinit
var
sequenceIdDeferred
:
Deferred
<
Int
>
@OptIn
(
ExperimentalCoroutinesApi
::
class
)
override
val
id
:
Long
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/message/messages.kt
View file @
3f523e6f
...
...
@@ -6,6 +6,7 @@
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
@
file
:
OptIn
(
MiraiExperimentalAPI
::
class
,
MiraiInternalAPI
::
class
,
LowLevelAPI
::
class
,
ExperimentalUnsignedTypes
::
class
)
package
net.mamoe.mirai.qqandroid.message
...
...
@@ -218,6 +219,8 @@ private val atAllData = ImMsgBody.Elem(
)
)
private
val
UNSUPPORTED_MERGED_MESSAGE_PLAIN
=
PlainText
(
"你的QQ暂不支持查看[转发多条消息],请期待后续版本。"
)
@OptIn
(
MiraiInternalAPI
::
class
,
MiraiExperimentalAPI
::
class
)
internal
fun
MessageChain
.
toRichTextElems
(
forGroup
:
Boolean
):
MutableList
<
ImMsgBody
.
Elem
>
{
val
elements
=
mutableListOf
<
ImMsgBody
.
Elem
>()
...
...
@@ -233,31 +236,49 @@ internal fun MessageChain.toRichTextElems(forGroup: Boolean): MutableList<ImMsgB
fun
transformOneMessage
(
it
:
Message
)
{
if
(
it
is
RichMessage
)
{
val
content
=
MiraiPlatformUtils
.
zip
(
it
.
content
.
toByteArray
())
when
(
it
)
{
is
LightApp
->
elements
.
add
(
ImMsgBody
.
Elem
(
lightApp
=
ImMsgBody
.
LightAppElem
(
data
=
byteArrayOf
(
1
)
+
content
)
)
)
is
MergedForwardedMessage
->
{
elements
.
add
(
ImMsgBody
.
Elem
(
richMsg
=
ImMsgBody
.
RichMsg
(
serviceId
=
35
,
template1
=
byteArrayOf
(
1
)
+
content
)
)
)
transformOneMessage
(
UNSUPPORTED_MERGED_MESSAGE_PLAIN
)
// required
}
else
->
elements
.
add
(
ImMsgBody
.
Elem
(
richMsg
=
ImMsgBody
.
RichMsg
(
serviceId
=
when
(
it
)
{
is
XmlMessage
->
60
is
JsonMessage
->
1
is
MergedForwardedMessage
->
35
else
->
error
(
"unsupported RichMessage: ${it::class.simpleName}"
)
},
template1
=
byteArrayOf
(
1
)
+
content
)
)
)
}
}
when
(
it
)
{
is
PlainText
->
elements
.
add
(
ImMsgBody
.
Elem
(
text
=
ImMsgBody
.
Text
(
str
=
it
.
stringValue
)))
is
At
->
{
elements
.
add
(
ImMsgBody
.
Elem
(
text
=
it
.
toJceData
()))
elements
.
add
(
ImMsgBody
.
Elem
(
text
=
ImMsgBody
.
Text
(
str
=
" "
)))
}
is
LightApp
->
elements
.
add
(
ImMsgBody
.
Elem
(
lightApp
=
ImMsgBody
.
LightAppElem
(
data
=
byteArrayOf
(
1
)
+
MiraiPlatformUtils
.
zip
(
it
.
content
.
toByteArray
())
)
)
)
is
RichMessage
->
elements
.
add
(
ImMsgBody
.
Elem
(
richMsg
=
ImMsgBody
.
RichMsg
(
serviceId
=
when
(
it
)
{
is
XmlMessage
->
60
is
JsonMessage
->
1
else
->
error
(
"unsupported RichMessage"
)
},
template1
=
byteArrayOf
(
1
)
+
MiraiPlatformUtils
.
zip
(
it
.
content
.
toByteArray
())
)
)
)
is
OfflineGroupImage
->
elements
.
add
(
ImMsgBody
.
Elem
(
customFace
=
it
.
toJceData
()))
is
OnlineGroupImageImpl
->
elements
.
add
(
ImMsgBody
.
Elem
(
customFace
=
it
.
delegate
))
is
OnlineFriendImageImpl
->
elements
.
add
(
ImMsgBody
.
Elem
(
notOnlineImage
=
it
.
delegate
))
...
...
@@ -267,16 +288,17 @@ internal fun MessageChain.toRichTextElems(forGroup: Boolean): MutableList<ImMsgB
is
QuoteReplyToSend
->
{
if
(
forGroup
)
{
check
(
it
is
QuoteReplyToSend
.
ToGroup
)
{
"sending a quote to group using QuoteReplyToSend.ToFriend"
"sending a quote to group using QuoteReplyToSend.ToFriend
is prohibited
"
}
if
(
it
.
sender
is
Member
)
{
transformOneMessage
(
it
.
createAt
())
}
transformOneMessage
(
" "
.
toMessage
(
))
transformOneMessage
(
PlainText
(
" "
))
}
}
is
QuoteReply
,
is
MessageSource
->
{
is
MessageSource
,
->
{
}
else
->
error
(
"unsupported message type: ${it::class.simpleName}"
)
...
...
@@ -358,7 +380,7 @@ internal fun MsgComm.Msg.toMessageChain(): MessageChain {
return
buildMessageChain
(
elements
.
size
+
1
)
{
+
MessageSourceFromMsg
(
delegate
=
this
@
toMessageChain
)
elements
.
joinToMessageChain
(
this
)
}.
removeAtIfHasQuoteReply
()
}.
cleanupRubbishMessageElements
()
}
// These two functions are not identical, dont combine.
...
...
@@ -369,11 +391,31 @@ internal fun ImMsgBody.SourceMsg.toMessageChain(): MessageChain {
return
buildMessageChain
(
elements
.
size
+
1
)
{
+
MessageSourceFromServer
(
delegate
=
this
@
toMessageChain
)
elements
.
joinToMessageChain
(
this
)
}.
removeAtIfHasQuoteReply
()
}.
cleanupRubbishMessageElements
()
}
private
fun
MessageChain
.
cleanupRubbishMessageElements
():
MessageChain
{
var
last
:
SingleMessage
?
=
null
return
buildMessageChain
(
initialSize
=
this
.
count
())
{
this
@
cleanupRubbishMessageElements
.
forEach
{
element
->
if
(
last
==
null
)
{
last
=
element
return
@
forEach
}
else
{
if
(
last
is
MergedForwardedMessage
&&
element
is
PlainText
)
{
if
(
element
==
UNSUPPORTED_MERGED_MESSAGE_PLAIN
)
{
last
=
element
return
@
forEach
}
}
}
add
(
element
)
last
=
element
}
}
}
private
fun
MessageChain
.
removeAtIfHasQuoteReply
():
MessageChain
=
this
/*
if (this.any<QuoteReply>()) {
var removed = false
...
...
@@ -387,9 +429,6 @@ private fun MessageChain.removeAtIfHasQuoteReply(): MessageChain =
}.asMessageChain()
} else this*/
@OptIn
(
MiraiInternalAPI
::
class
,
ExperimentalUnsignedTypes
::
class
,
MiraiDebugAPI
::
class
,
LowLevelAPI
::
class
)
internal
fun
List
<
ImMsgBody
.
Elem
>.
joinToMessageChain
(
message
:
MessageChainBuilder
)
{
this
.
forEach
{
when
{
...
...
@@ -425,6 +464,7 @@ internal fun List<ImMsgBody.Elem>.joinToMessageChain(message: MessageChainBuilde
when
(
it
.
richMsg
.
serviceId
)
{
1
->
message
.
add
(
JsonMessage
(
content
))
60
->
message
.
add
(
XmlMessage
(
content
))
35
->
message
.
add
(
MergedForwardedMessage
(
content
))
else
->
{
@Suppress
(
"DEPRECATION"
)
MiraiLogger
.
debug
{
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidClient.kt
View file @
3f523e6f
...
...
@@ -101,7 +101,7 @@ internal open class QQAndroidClient(
var
openAppId
:
Long
=
715019303L
val
apkVersionName
:
ByteArray
get
()
=
"8.2.7"
.
toByteArray
()
val
buildVer
:
String
get
()
=
"8.2.7.4410"
val
buildVer
:
String
get
()
=
"8.2.7.4410"
// 8.2.0.1296
private
val
messageSequenceId
:
AtomicInt
=
atomic
(
22911
)
internal
fun
atomicNextMessageSequenceId
():
Int
=
messageSequenceId
.
getAndAdd
(
2
)
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/data/proto/LongMsg.kt
0 → 100644
View file @
3f523e6f
package
net.mamoe.mirai.qqandroid.network.protocol.data.proto
import
kotlinx.serialization.Serializable
import
kotlinx.serialization.protobuf.ProtoId
import
net.mamoe.mirai.qqandroid.io.ProtoBuf
import
net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
internal
class
LongMsg
:
ProtoBuf
{
@Serializable
class
MsgDeleteReq
(
@ProtoId
(
1
)
val
msgResid
:
ByteArray
=
EMPTY_BYTE_ARRAY
,
@ProtoId
(
2
)
val
msgType
:
Int
=
0
)
:
ProtoBuf
@Serializable
class
MsgDeleteRsp
(
@ProtoId
(
1
)
val
result
:
Int
=
0
,
@ProtoId
(
2
)
val
msgResid
:
ByteArray
=
EMPTY_BYTE_ARRAY
)
:
ProtoBuf
@Serializable
class
MsgDownReq
(
@ProtoId
(
1
)
val
srcUin
:
Int
=
0
,
@ProtoId
(
2
)
val
msgResid
:
ByteArray
=
EMPTY_BYTE_ARRAY
,
@ProtoId
(
3
)
val
msgType
:
Int
=
0
,
@ProtoId
(
4
)
val
needCache
:
Int
=
0
)
:
ProtoBuf
@Serializable
class
MsgDownRsp
(
@ProtoId
(
1
)
val
result
:
Int
=
0
,
@ProtoId
(
2
)
val
msgResid
:
ByteArray
=
EMPTY_BYTE_ARRAY
,
@ProtoId
(
3
)
val
msgContent
:
ByteArray
=
EMPTY_BYTE_ARRAY
)
:
ProtoBuf
@Serializable
class
MsgUpReq
(
@ProtoId
(
1
)
val
msgType
:
Int
=
0
,
@ProtoId
(
2
)
val
dstUin
:
Long
=
0L
,
@ProtoId
(
3
)
val
msgId
:
Int
=
0
,
@ProtoId
(
4
)
val
msgContent
:
ByteArray
=
EMPTY_BYTE_ARRAY
,
@ProtoId
(
5
)
val
storeType
:
Int
=
0
,
@ProtoId
(
6
)
val
msgUkey
:
ByteArray
=
EMPTY_BYTE_ARRAY
,
@ProtoId
(
7
)
val
needCache
:
Int
=
0
)
:
ProtoBuf
@Serializable
class
MsgUpRsp
(
@ProtoId
(
1
)
val
result
:
Int
=
0
,
@ProtoId
(
2
)
val
msgId
:
Int
=
0
,
@ProtoId
(
3
)
val
msgResid
:
ByteArray
=
EMPTY_BYTE_ARRAY
)
:
ProtoBuf
@Serializable
class
ReqBody
(
@ProtoId
(
1
)
val
subcmd
:
Int
=
0
,
@ProtoId
(
2
)
val
termType
:
Int
=
0
,
@ProtoId
(
3
)
val
platformType
:
Int
=
0
,
@ProtoId
(
4
)
val
msgUpReq
:
List
<
LongMsg
.
MsgUpReq
>?
=
null
,
@ProtoId
(
5
)
val
msgDownReq
:
List
<
LongMsg
.
MsgDownReq
>?
=
null
,
@ProtoId
(
6
)
val
msgDelReq
:
List
<
LongMsg
.
MsgDeleteReq
>?
=
null
,
@ProtoId
(
10
)
val
agentType
:
Int
=
0
)
:
ProtoBuf
@Serializable
class
RspBody
(
@ProtoId
(
1
)
val
subcmd
:
Int
=
0
,
@ProtoId
(
2
)
val
msgUpRsp
:
List
<
LongMsg
.
MsgUpRsp
>?
=
null
,
@ProtoId
(
3
)
val
msgDownRsp
:
List
<
LongMsg
.
MsgDownRsp
>?
=
null
,
@ProtoId
(
4
)
val
msgDelRsp
:
List
<
LongMsg
.
MsgDeleteRsp
>?
=
null
)
:
ProtoBuf
}
\ No newline at end of file
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/data/proto/MsgTransmit.kt
0 → 100644
View file @
3f523e6f
package
net.mamoe.mirai.qqandroid.network.protocol.data.proto
import
kotlinx.serialization.Serializable
import
kotlinx.serialization.protobuf.ProtoId
import
net.mamoe.mirai.qqandroid.io.ProtoBuf
import
net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
internal
class
MsgTransmit
:
ProtoBuf
{
@Serializable
class
PbMultiMsgItem
(
@ProtoId
(
1
)
val
fileName
:
String
=
""
,
@ProtoId
(
2
)
val
buffer
:
ByteArray
=
EMPTY_BYTE_ARRAY
)
:
ProtoBuf
@Serializable
class
PbMultiMsgNew
(
@ProtoId
(
1
)
val
msg
:
List
<
MsgComm
.
Msg
>?
=
null
)
:
ProtoBuf
@Serializable
class
PbMultiMsgTransmit
(
@ProtoId
(
1
)
val
msg
:
List
<
MsgComm
.
Msg
>?
=
null
,
@ProtoId
(
2
)
val
pbItemList
:
List
<
MsgTransmit
.
PbMultiMsgItem
>?
=
null
)
:
ProtoBuf
}
\ No newline at end of file
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/data/proto/MultiMsg.kt
0 → 100644
View file @
3f523e6f
package
net.mamoe.mirai.qqandroid.network.protocol.data.proto
import
kotlinx.serialization.Serializable
import
kotlinx.serialization.protobuf.ProtoId
import
net.mamoe.mirai.qqandroid.io.ProtoBuf
import
net.mamoe.mirai.qqandroid.network.protocol.packet.EMPTY_BYTE_ARRAY
@Serializable
internal
class
MultiMsg
:
ProtoBuf
{
@Serializable
class
ExternMsg
(
@ProtoId
(
1
)
val
channelType
:
Int
=
0
)
:
ProtoBuf
@Serializable
class
MultiMsgApplyDownReq
(
@ProtoId
(
1
)
val
msgResid
:
ByteArray
=
EMPTY_BYTE_ARRAY
,
@ProtoId
(
2
)
val
msgType
:
Int
=
0
,
@ProtoId
(
3
)
val
srcUin
:
Long
=
0L
)
:
ProtoBuf
@Serializable
class
MultiMsgApplyDownRsp
(
@ProtoId
(
1
)
val
result
:
Int
=
0
,
@ProtoId
(
2
)
val
thumbDownPara
:
ByteArray
=
EMPTY_BYTE_ARRAY
,
@ProtoId
(
3
)
val
msgKey
:
ByteArray
=
EMPTY_BYTE_ARRAY
,
@ProtoId
(
4
)
val
uint32DownIp
:
List
<
Int
>?
=
null
,
@ProtoId
(
5
)
val
uint32DownPort
:
List
<
Int
>?
=
null
,
@ProtoId
(
6
)
val
msgResid
:
ByteArray
=
EMPTY_BYTE_ARRAY
,
@ProtoId
(
7
)
val
msgExternInfo
:
MultiMsg
.
ExternMsg
?
=
null
,
@ProtoId
(
8
)
val
bytesDownIpV6
:
List
<
ByteArray
>?
=
null
,
@ProtoId
(
9
)
val
uint32DownV6Port
:
List
<
Int
>?
=
null
)
:
ProtoBuf
@Serializable
class
MultiMsgApplyUpReq
(
@ProtoId
(
1
)
val
dstUin
:
Long
=
0L
,
@ProtoId
(
2
)
val
msgSize
:
Long
=
0L
,
@ProtoId
(
3
)
val
msgMd5
:
ByteArray
=
EMPTY_BYTE_ARRAY
,
@ProtoId
(
4
)
val
msgType
:
Int
=
0
,
@ProtoId
(
5
)
val
applyId
:
Int
=
0
)
:
ProtoBuf
@Serializable
class
MultiMsgApplyUpRsp
(
@ProtoId
(
1
)
val
result
:
Int
=
0
,
@ProtoId
(
2
)
val
msgResid
:
ByteArray
=
EMPTY_BYTE_ARRAY
,
@ProtoId
(
3
)
val
msgUkey
:
ByteArray
=
EMPTY_BYTE_ARRAY
,
@ProtoId
(
4
)
val
uint32UpIp
:
List
<
Int
>?
=
null
,
@ProtoId
(
5
)
val
uint32UpPort
:
List
<
Int
>?
=
null
,
@ProtoId
(
6
)
val
blockSize
:
Long
=
0L
,
@ProtoId
(
7
)
val
upOffset
:
Long
=
0L
,
@ProtoId
(
8
)
val
applyId
:
Int
=
0
,
@ProtoId
(
9
)
val
msgKey
:
ByteArray
=
EMPTY_BYTE_ARRAY
,
@ProtoId
(
10
)
val
msgSig
:
ByteArray
=
EMPTY_BYTE_ARRAY
,
@ProtoId
(
11
)
val
msgExternInfo
:
MultiMsg
.
ExternMsg
?
=
null
,
@ProtoId
(
12
)
val
bytesUpIpV6
:
List
<
ByteArray
>?
=
null
,
@ProtoId
(
13
)
val
uint32UpV6Port
:
List
<
Int
>?
=
null
)
:
ProtoBuf
@Serializable
class
ReqBody
(
@ProtoId
(
1
)
val
subcmd
:
Int
=
0
,
@ProtoId
(
2
)
val
termType
:
Int
=
0
,
@ProtoId
(
3
)
val
platformType
:
Int
=
0
,
@ProtoId
(
4
)
val
netType
:
Int
=
0
,
@ProtoId
(
5
)
val
buildVer
:
String
=
""
,
@ProtoId
(
6
)
val
multimsgApplyupReq
:
List
<
MultiMsg
.
MultiMsgApplyUpReq
>?
=
null
,
@ProtoId
(
7
)
val
multimsgApplydownReq
:
List
<
MultiMsg
.
MultiMsgApplyDownReq
>?
=
null
,
@ProtoId
(
8
)
val
buType
:
Int
=
0
,
@ProtoId
(
9
)
val
reqChannelType
:
Int
=
0
)
:
ProtoBuf
@Serializable
class
RspBody
(
@ProtoId
(
1
)
val
subcmd
:
Int
=
0
,
@ProtoId
(
2
)
val
multimsgApplyupRsp
:
List
<
MultiMsg
.
MultiMsgApplyUpRsp
>?
=
null
,
@ProtoId
(
3
)
val
multimsgApplydownRsp
:
List
<
MultiMsg
.
MultiMsgApplyDownRsp
>?
=
null
)
:
ProtoBuf
}
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/PacketFactory.kt
View file @
3f523e6f
...
...
@@ -11,9 +11,10 @@ package net.mamoe.mirai.qqandroid.network.protocol.packet
import
kotlinx.io.core.*
import
kotlinx.io.pool.useInstance
import
net.mamoe.mirai.qqandroid.network.Packet
import
net.mamoe.mirai.event.Event
import
net.mamoe.mirai.qqandroid.QQAndroidBot
import
net.mamoe.mirai.qqandroid.network.Packet
import
net.mamoe.mirai.qqandroid.network.protocol.packet.chat.MultiMsg
import
net.mamoe.mirai.qqandroid.network.protocol.packet.chat.PbMessageSvc
import
net.mamoe.mirai.qqandroid.network.protocol.packet.chat.TroopManagement
import
net.mamoe.mirai.qqandroid.network.protocol.packet.chat.image.ImgStore
...
...
@@ -144,7 +145,8 @@ internal object KnownPacketFactories {
TroopManagement
.
EditGroupNametag
,
TroopManagement
.
Kick
,
Heartbeat
.
Alive
,
PbMessageSvc
.
PbMsgWithDraw
PbMessageSvc
.
PbMsgWithDraw
,
MultiMsg
.
ApplyUp
)
object
IncomingFactories
:
List
<
IncomingPacketFactory
<
*
>>
by
mutableListOf
(
...
...
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/protocol/packet/chat/MultiMsg.kt
0 → 100644
View file @
3f523e6f
/*
* Copyright 2020 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/master/LICENSE
*/
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
)
package
net.mamoe.mirai.qqandroid.network.protocol.packet.chat
import
kotlinx.io.core.ByteReadPacket
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.message.data.*
import
net.mamoe.mirai.qqandroid.QQAndroidBot
import
net.mamoe.mirai.qqandroid.io.serialization.readProtoBuf
import
net.mamoe.mirai.qqandroid.io.serialization.toByteArray
import
net.mamoe.mirai.qqandroid.io.serialization.writeProtoBuf
import
net.mamoe.mirai.qqandroid.message.MessageSourceFromSendFriend
import
net.mamoe.mirai.qqandroid.message.MessageSourceFromSendGroup
import
net.mamoe.mirai.qqandroid.message.toRichTextElems
import
net.mamoe.mirai.qqandroid.network.Packet
import
net.mamoe.mirai.qqandroid.network.QQAndroidClient
import
net.mamoe.mirai.qqandroid.network.protocol.data.proto.ImMsgBody
import
net.mamoe.mirai.qqandroid.network.protocol.data.proto.MsgComm
import
net.mamoe.mirai.qqandroid.network.protocol.data.proto.MsgTransmit
import
net.mamoe.mirai.qqandroid.network.protocol.data.proto.MultiMsg
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
import
net.mamoe.mirai.utils.MiraiInternalAPI
import
net.mamoe.mirai.utils.MiraiPlatformUtils
import
net.mamoe.mirai.utils._miraiContentToString
internal
class
MessageValidationData
@OptIn
(
MiraiInternalAPI
::
class
)
constructor
(
val
data
:
ByteArray
,
val
md5
:
ByteArray
=
MiraiPlatformUtils
.
md5
(
data
),
)
{
override
fun
toString
():
String
{
return
"MessageValidationData(data=<size=${data.size}>, md5=${md5.contentToString()})"
}
}
@OptIn
(
MiraiInternalAPI
::
class
)
internal
fun
MessageChain
.
calculateValidationData
(
bot
:
Bot
):
MessageValidationData
{
// top_package.akkv#method_42702
val
source
:
MessageSource
by
this
.
orElse
{
error
(
"internal error: calculateValidationData: cannot find MessageSource, chain=${this._miraiContentToString()}"
)
}
check
(
source
is
MessageSourceFromSendGroup
||
source
is
MessageSourceFromSendFriend
)
{
"internal error: calculateValidationData: MessageSource must be "
}
val
richTextElems
=
this
.
toRichTextElems
(
source
is
MessageSourceFromSendGroup
)
val
msgTransmit
=
MsgTransmit
.
PbMultiMsgTransmit
(
msg
=
listOf
(
MsgComm
.
Msg
(
msgHead
=
MsgComm
.
MsgHead
(
fromUin
=
source
.
senderId
,
msgSeq
=
source
.
sequenceId
,
msgTime
=
source
.
time
.
toInt
(),
msgUid
=
source
.
messageRandom
.
toLong
(),
// TODO: 2020/3/26 CHECK IT
mutiltransHead
=
MsgComm
.
MutilTransHead
(
status
=
0
,
msgId
=
1
),
msgType
=
82
,
// troop
groupInfo
=
MsgComm
.
GroupInfo
(
groupCode
=
source
.
toUin
,
groupCard
=
bot
.
nick
,
),
),
msgBody
=
ImMsgBody
.
MsgBody
(
richText
=
ImMsgBody
.
RichText
(
elems
=
richTextElems
)
)
)
)
)
val
bytes
=
msgTransmit
.
toByteArray
(
MsgTransmit
.
PbMultiMsgTransmit
.
serializer
())
return
MessageValidationData
(
MiraiPlatformUtils
.
zip
(
bytes
))
}
/*
=======================处理客户端到服务器=======================
flag1=0x0000000B(11), flag2=1, sequenceId = 00 00 E0 90, flag3=00, // 解密 bodyouter by D2 key
Packet 20:02:51 : ByteReadPacket outer body decrypted=00 00 00 28 00 00 00 18 4D 65 73 73 61 67 65 53 76 63 2E 50 62 53 65 6E 64 4D 73 67 00 00 00 08 8A 51 B1 25 00 00 00 04 00 00 02 7A 0A 08 12 06 08 F6 DD 96 FC 03 12 07 08 01 10 00 18 F2 46 1A D5 04 0A D2 04 12 A9 03 62 A6 03 0A A1 03 01 78 9C 7D 91 4B 4F DB 40 10 C7 BF CA 6A 2F 3E 81 1F 21 0D 91 6C 23 F1 48 15 CA A3 28 04 89 5C AA C5 1E 9B 15 6B 3B F5 AE 97 38 27 E8 05 04 5C B9 21 71 A1 95 B8 D0 1E 2A 24 54 F5 CB 20 25 F0 31 18 1B AA DE 90 46 AB 9D 9D D9 F9 CF 6F C6 5D 18 25 82 68 C8 25 CF 52 CF B0 67 2D 83 40 1A 64 21 4F 63 CF E8 6F 77 66 E6 0D 22 15 4B 43 26 B2 14 3C A3 04 69 90 05 DF 4D 64 4C 24 E4 9A 07 D0 5D F6 68 A3 49 89 82 64 28 98 AA 7D 9B 12 16 A8 AA 26 D5 1C 0E D7 0B A1 F8 BA 8C 29 D9 CB 39 44 18 77 1A 68 8E 8D 16 49 A9 A5 0E AB 83 E9 10 4D 6B 4A 92 2F 39 48 1E 7A 74 73 BB BD B1 16 7C B4 07 65 B9 37 E2 6D 4B 1F 9A 81 B5 3B B6 16 57 F9 4A F0 69 D5 71 3E 2C 2D F6 0F 76 3A 5D 25 C7 73 5B 03 D9 1F 8D 8B AF 83 9E 39 6A 44 9F 75 6F 4D 55 A5 22 2E 60 83 25 80 B2 CD F9 A6 DD 68 B5 5A 4E DB B6 28 91 59 91 07 80 7D 75 51 09 FD 22 17 1E A5 24 12 2C 46 24 44 08 71 32 3D 1E A7 75 34 79 83 E8 D4 61 9B FA 2E 47 64 22 58 99 15 EA F5 41 71 25 C0 7F 1F EE F1 E8 87 6B BE 26 BA FB 39 D9 E7 61 08 28 10 31 21 01 5B 52 A5 80 5A CE F4 5D 59 24 09 CB 4B FF E9 DB C3 E4 E4 CF F4 FA FB D3 D5 F9 E4 EE 62 7A F9 7B 7A 7F 3A 3D FE E9 9A FF 32 5C B3 EA 05 7F D4 44 24 AD 69 9F 8F CF 26 37 B7 CF 77 BF 26 7F 2F 29 E1 41 B5 8D FF 7B C1 DB 70 58 8D 78 C6 AE C5 4C 5C A9 FF 02 0F 69 BA A1 10 23 12 4D 0A 4B 0A 49 E4 BD A0 E7 9A 84 51 51 E6 9A 82 E4 B8 8D E6 94 AF E6 8C 81 E6 9F A5 E7 9C 8B 5B E8 BD AC E5 8F 91 E5 A4 9A E6 9D A1 E6 B6 88 E6 81 AF 5D EF BC 8C E8 AF B7 E6 9C 9F E5 BE 85 E5 90 8E E7 BB AD E7 89 88 E6 9C AC E3 80 82 12 55 AA 02 52 30 01 3A 40 4F 54 39 4E 4C 63 47 31 5A 79 79 62 78 69 39 30 76 77 2F 63 30 59 7A 30 42 4A 69 45 63 4B 4A 32 32 36 43 42 55 6B 56 46 49 74 73 7A 34 51 5A 73 55 78 7A 75 71 5A 53 2F 78 33 66 50 76 53 4C 74 88 01 00 9A 01 08 78 00 F8 01 00 C8 02 00 20 92 3F 28 E9 9B 97 86 04 40 00
// 尝试解 Uni
// head
Packet Debug 20:02:51 : head=00 00 00 18 4D 65 73 73 61 67 65 53 76 63 2E 50 62 53 65 6E 64 4D 73 67 00 00 00 08 8A 51 B1 25 00 00 00 04
Packet 20:02:51 : commandName=MessageSvc.PbSendMsg
MessageSvc.PbSendMsg
unknown4Bytes=8A 51 B1 25
extraData=
Packet Debug 20:02:51 : Real body=0A 08 12 06 08 F6 DD 96 FC 03 12 07 08 01 10 00 18 F2 46 1A D5 04 0A D2 04 12 A9 03 62 A6 03 0A A1 03 01 78 9C 7D 91 4B 4F DB 40 10 C7 BF CA 6A 2F 3E 81 1F 21 0D 91 6C 23 F1 48 15 CA A3 28 04 89 5C AA C5 1E 9B 15 6B 3B F5 AE 97 38 27 E8 05 04 5C B9 21 71 A1 95 B8 D0 1E 2A 24 54 F5 CB 20 25 F0 31 18 1B AA DE 90 46 AB 9D 9D D9 F9 CF 6F C6 5D 18 25 82 68 C8 25 CF 52 CF B0 67 2D 83 40 1A 64 21 4F 63 CF E8 6F 77 66 E6 0D 22 15 4B 43 26 B2 14 3C A3 04 69 90 05 DF 4D 64 4C 24 E4 9A 07 D0 5D F6 68 A3 49 89 82 64 28 98 AA 7D 9B 12 16 A8 AA 26 D5 1C 0E D7 0B A1 F8 BA 8C 29 D9 CB 39 44 18 77 1A 68 8E 8D 16 49 A9 A5 0E AB 83 E9 10 4D 6B 4A 92 2F 39 48 1E 7A 74 73 BB BD B1 16 7C B4 07 65 B9 37 E2 6D 4B 1F 9A 81 B5 3B B6 16 57 F9 4A F0 69 D5 71 3E 2C 2D F6 0F 76 3A 5D 25 C7 73 5B 03 D9 1F 8D 8B AF 83 9E 39 6A 44 9F 75 6F 4D 55 A5 22 2E 60 83 25 80 B2 CD F9 A6 DD 68 B5 5A 4E DB B6 28 91 59 91 07 80 7D 75 51 09 FD 22 17 1E A5 24 12 2C 46 24 44 08 71 32 3D 1E A7 75 34 79 83 E8 D4 61 9B FA 2E 47 64 22 58 99 15 EA F5 41 71 25 C0 7F 1F EE F1 E8 87 6B BE 26 BA FB 39 D9 E7 61 08 28 10 31 21 01 5B 52 A5 80 5A CE F4 5D 59 24 09 CB 4B FF E9 DB C3 E4 E4 CF F4 FA FB D3 D5 F9 E4 EE 62 7A F9 7B 7A 7F 3A 3D FE E9 9A FF 32 5C B3 EA 05 7F D4 44 24 AD 69 9F 8F CF 26 37 B7 CF 77 BF 26 7F 2F 29 E1 41 B5 8D FF 7B C1 DB 70 58 8D 78 C6 AE C5 4C 5C A9 FF 02 0F 69 BA A1 10 23 12 4D 0A 4B 0A 49 E4 BD A0 E7 9A 84 51 51 E6 9A 82 E4 B8 8D E6 94 AF E6 8C 81 E6 9F A5 E7 9C 8B 5B E8 BD AC E5 8F 91 E5 A4 9A E6 9D A1 E6 B6 88 E6 81 AF 5D EF BC 8C E8 AF B7 E6 9C 9F E5 BE 85 E5 90 8E E7 BB AD E7 89 88 E6 9C AC E3 80 82 12 55 AA 02 52 30 01 3A 40 4F 54 39 4E 4C 63 47 31 5A 79 79 62 78 69 39 30 76 77 2F 63 30 59 7A 30 42 4A 69 45 63 4B 4A 32 32 36 43 42 55 6B 56 46 49 74 73 7A 34 51 5A 73 55 78 7A 75 71 5A 53 2F 78 33 66 50 76 53 4C 74 88 01 00 9A 01 08 78 00 F8 01 00 C8 02 00 20 92 3F 28 E9 9B 97 86 04 40 00
Packet 20:02:51 : ByteReadPacket uni packet=
Packet 20:02:51 : =======================共有 1 个包=======================
=======================处理服务器到客户端客户端=======================
=======================处理服务器到客户端客户端=======================
Packet 20:02:51 : ByteReadPacket 正在处理=00 00 00 0B 01 00 00 00 00 0E 31 39 39 34 37 30 31 30 32 31 0B 1C 26 01 C3 F8 46 01 ED 8D 1E C8 86 C1 62 89 9C F4 16 57 67 99 4F 39 E7 69 4F 74 33 6E 92 89 74 49 09 84 19 10 6F 3C 81 DA 0C 92 DD 04 B7 60 C9 DB C8 4F F8 60 57 A2 3F CF 95 5F 01 F8 0A 79 E7 28 B9 6A F6 AD 0A 71 BA 54 F8 8C DF AF CF D3
Packet 20:02:51 : flag1(0A/0B) = 0B
Packet 20:02:51 : 包类型(flag2) = 1. (可能是 uni)
Packet 20:02:51 : 成功使用 d2Key 解密
Packet 20:02:51 : ByteReadPacket sso/uni body==00 00 00 34 00 00 E0 90 00 00 00 00 00 00 00 04 00 00 00 18 4D 65 73 73 61 67 65 53 76 63 2E 50 62 53 65 6E 64 4D 73 67 00 00 00 08 8A 51 B1 25 00 00 00 00 00 00 00 0C 08 00 18 EA 90 ED F3 05
Packet 20:02:51 : sequenceId = 57488
Packet 20:02:51 : sso(inner)extraData =
Packet Debug 20:02:51 : commandName=MessageSvc.PbSendMsg
Packet 20:02:51 : 不是oicq response(可能是 UNI/PB)= 00 00 00 0C 08 00 18 EA 90 ED F3 05
Packet 20:02:51 : =======================共有 0 个包=======================
*/
/*
=======================处理客户端到服务器=======================
flag1=0x0000000B(11), flag2=1, sequenceId = 00 00 E0 8D, flag3=00, // 解密 bodyouter by D2 key
Packet 20:02:50 : ByteReadPacket outer body decrypted=00 00 00 24 00 00 00 14 4D 75 6C 74 69 4D 73 67 2E 41 70 70 6C 79 55 70 00 00 00 08 8A 51 B1 25 00 00 00 04 00 00 00 3B 08 01 10 05 18 09 20 03 2A 0A 38 2E 32 2E 30 2E 31 32 39 36 32 1F 08 F6 DD 96 FC 03 10 CF 05 1A 10 BB 45 B9 71 2C F4 D3 06 5D A7 A7 A2 FF D4 62 D2 20 03 28 00 40 01
// 尝试解 Uni
// head
Packet Debug 20:02:50 : head=00 00 00 14 4D 75 6C 74 69 4D 73 67 2E 41 70 70 6C 79 55 70 00 00 00 08 8A 51 B1 25 00 00 00 04
Packet 20:02:50 : commandName=MultiMsg.ApplyUp
MultiMsg.ApplyUp
unknown4Bytes=8A 51 B1 25
extraData=
Packet Debug 20:02:50 : Real body=08 01 10 05 18 09 20 03 2A 0A 38 2E 32 2E 30 2E 31 32 39 36 32 1F 08 F6 DD 96 FC 03 10 CF 05 1A 10 BB 45 B9 71 2C F4 D3 06 5D A7 A7 A2 FF D4 62 D2 20 03 28 00 40 01
Packet 20:02:50 : ByteReadPacket uni packet=
Packet 20:02:50 : =======================共有 1 个包=======================
=======================处理服务器到客户端客户端=======================
Packet 20:02:50 : ByteReadPacket 正在处理=00 00 00 0B 01 00 00 00 00 0E 31 39 39 34 37 30 31 30 32 31 8A B2 8A B1 DA C9 60 28 D8 55 AB 39 B9 07 A6 D8 BA F2 55 87 C2 C9 29 08 53 CC AF 99 3F 22 26 1F 66 01 09 60 F2 2A 3C F1 A4 DC 74 5A 27 1C 47 E2 F0 7E 57 0C 9B 50 7D 0D 52 A3 17 BB B7 8D 9B 62 3A B3 E2 65 6D 7C 74 24 79 11 A5 23 78 83 63 35 8C C9 34 4A D9 CD 61 4D 0D 73 74 DF 49 F3 AD 65 2D 1A 87 14 2F 03 5F 0B 16 1F 87 CE 2A 53 3E 9F 8F CF 0F B8 C3 6B E1 6C 42 46 0D 59 F2 89 7E 8A 47 A8 CC 52 C0 E7 5C E4 CD 00 A0 00 61 FA AF 95 C1 C4 1B 8C C3 24 48 A5 4D 4F D7 59 38 F1 AE 4A 3B 18 7E 52 96 D5 2D 5D 67 D0 B8 0C BC F0 FD 3E 45 2C 7F 2E 1B AC FF F1 86 04 9B 8E 16 DF 7F C0 1C 25 13 36 21 D8 87 B1 FA BA 6E D2 DA E3 02 D2 31 45 9D 61 D4 43 07 F6 B5 D3 B0 6D 72 8B 83 FA B5 90 A7 BA 7A 32 2C 28 96 67 AC AB 42 37 EF 51 5B A1 A8 2D 17 93 F9 2C 22 51 6C 49 0A ED 38 AF 88 A1 E4 C7 09 BC DA 11 3F 46 DF D3 60 51 0E 92 89 56 D6 0D B4 66 DC 74 77 64 42 95 56 BE 89 61 75 CB F7 8C 33 D4 6B 40 4F 07 43 5B D9 A4 38 E1 DC 2A 0D 4D D6 8D 2B F5 E4 A2 45 3D EF 77 E5 24 F5 09 5E 1C 9C 14 CA 33 4D 3D 63 83 2E 38 94 13 1D 7A 0D 62 DB 89 0D 27 8D E2 58 5D 24 25 BC 9F D3 E3 3A 55 F2 FB 93 69 61 F0 25 E6 7F 7F B6 25 87 33 5B 5F 35 C1 E0 C4 6E 25 41 A0 12 B5 E6 DA 1A C9 F4 20 31 86 D3 B2 C9 D3 2D 96 40 92 BC BD 38 AD D6 94 E9 25 14 12 2D B6 32 6E D5 37 7D C6 E3 A8 E5 1E AD 97 52 FA DD CC 7E 96 5A E0 CB AF 79 4B CB BC E3 9F 57 4C 94 C7 9D 58 83 D0 11 41 BD E6 9C E1 98 7B BB 5B
Packet 20:02:50 : flag1(0A/0B) = 0B
Packet 20:02:50 : 包类型(flag2) = 1. (可能是 uni)
Packet 20:02:50 : 成功使用 d2Key 解密
Packet 20:02:50 : ByteReadPacket sso/uni body==00 00 00 30 00 00 E0 8D 00 00 00 00 00 00 00 04 00 00 00 14 4D 75 6C 74 69 4D 73 67 2E 41 70 70 6C 79 55 70 00 00 00 08 8A 51 B1 25 00 00 00 00 00 00 01 88 08 01 12 FF 02 08 00 12 40 4F 54 39 4E 4C 63 47 31 5A 79 79 62 78 69 39 30 76 77 2F 63 30 59 7A 30 42 4A 69 45 63 4B 4A 32 32 36 43 42 55 6B 56 46 49 74 73 7A 34 51 5A 73 55 78 7A 75 71 5A 53 2F 78 33 66 50 76 53 4C 74 1A 98 01 1B 76 62 FB B2 C6 24 C3 1F 39 47 0D 45 5C 77 BD 0C 8F 69 FB C8 4F D8 76 83 26 60 EA A3 24 BC FD F6 C8 B4 64 DA 47 9D 6C 1A FA F4 EF 02 FC A4 76 1F 87 EB FF 51 62 20 E9 1F 74 6B 2F 7B 7C 53 EC 6D A2 53 AC 2B 93 B4 79 83 6D E6 D8 86 E1 D5 E2 4D EE 75 03 A3 3B 72 EB 0A 3E 13 3A 80 70 EF CC B4 0D F9 42 E3 DF 5F 7A 4C 36 BC 3B 9C 31 5A B1 40 B4 5B 49 26 CE 65 BD 2F 86 8D 9D 0C 34 1B 5E 32 6E EF 60 4B E1 60 7F 1A 98 CF 14 42 85 A6 F8 BE A5 EE A7 A6 C7 9E 11 20 FB AE FA 95 0A 20 B7 87 A4 8F 0E 20 FB AE FA 9D 0A 20 E5 B6 95 B0 0A 28 50 28 90 3F 28 BB 03 28 50 40 00 4A 10 4E 64 43 67 6D 61 71 35 6D 52 73 43 53 38 41 58 52 68 AF 63 72 0B 4D 5B 17 6E D8 35 C1 D3 3F C8 D7 FC F0 A8 0A 67 4D B5 A6 B3 B7 E2 E1 9F 96 68 D3 BC AD 4A 6A 20 72 E8 D2 44 C3 8B 93 60 F3 3C 4B 46 83 E4 75 A2 3C 72 A4 F7 31 D9 88 89 23 34 9A AF EF FC 17 29 5D 6C D0 2B F1 63 D5 9F E2 B9 B5 49 D2 62 E3 D0 F9 19 C5 0D 20 AF 78 D5 34 7E BB B7 E2 8E 5C 69 F4 38 38 E7
Packet 20:02:50 : sequenceId = 57485
Packet 20:02:50 : sso(inner)extraData =
Packet Debug 20:02:50 : commandName=MultiMsg.ApplyUp
找不到包 PacketFactory
Packet 20:02:50 : 传递给 PacketFactory 的数据 = 00 00 01 88 08 01 12 FF 02 08 00 12 40 4F 54 39 4E 4C 63 47 31 5A 79 79 62 78 69 39 30 76 77 2F 63 30 59 7A 30 42 4A 69 45 63 4B 4A 32 32 36 43 42 55 6B 56 46 49 74 73 7A 34 51 5A 73 55 78 7A 75 71 5A 53 2F 78 33 66 50 76 53 4C 74 1A 98 01 1B 76 62 FB B2 C6 24 C3 1F 39 47 0D 45 5C 77 BD 0C 8F 69 FB C8 4F D8 76 83 26 60 EA A3 24 BC FD F6 C8 B4 64 DA 47 9D 6C 1A FA F4 EF 02 FC A4 76 1F 87 EB FF 51 62 20 E9 1F 74 6B 2F 7B 7C 53 EC 6D A2 53 AC 2B 93 B4 79 83 6D E6 D8 86 E1 D5 E2 4D EE 75 03 A3 3B 72 EB 0A 3E 13 3A 80 70 EF CC B4 0D F9 42 E3 DF 5F 7A 4C 36 BC 3B 9C 31 5A B1 40 B4 5B 49 26 CE 65 BD 2F 86 8D 9D 0C 34 1B 5E 32 6E EF 60 4B E1 60 7F 1A 98 CF 14 42 85 A6 F8 BE A5 EE A7 A6 C7 9E 11 20 FB AE FA 95 0A 20 B7 87 A4 8F 0E 20 FB AE FA 9D 0A 20 E5 B6 95 B0 0A 28 50 28 90 3F 28 BB 03 28 50 40 00 4A 10 4E 64 43 67 6D 61 71 35 6D 52 73 43 53 38 41 58 52 68 AF 63 72 0B 4D 5B 17 6E D8 35 C1 D3 3F C8 D7 FC F0 A8 0A 67 4D B5 A6 B3 B7 E2 E1 9F 96 68 D3 BC AD 4A 6A 20 72 E8 D2 44 C3 8B 93 60 F3 3C 4B 46 83 E4 75 A2 3C 72 A4 F7 31 D9 88 89 23 34 9A AF EF FC 17 29 5D 6C D0 2B F1 63 D5 9F E2 B9 B5 49 D2 62 E3 D0 F9 19 C5 0D 20 AF 78 D5 34 7E BB B7 E2 8E 5C 69 F4 38 38 E7
Packet 20:02:50 : 不是oicq response(可能是 UNI/PB)=
Packet 20:02:50 : =======================共有 0 个包=======================
*/
internal
class
MultiMsg
{
object
ApplyUp
:
OutgoingPacketFactory
<
ApplyUp
.
Response
>(
"MultiMsg.ApplyUp"
)
{
class
Response
(
val
proto
:
MultiMsg
.
MultiMsgApplyUpRsp
)
:
Packet
fun
createForLongMessage
(
client
:
QQAndroidClient
,
message
:
MessageChain
,
dstUin
:
Long
,
// group uin
):
OutgoingPacket
=
createForLongMessage
(
client
,
message
.
calculateValidationData
(
client
.
bot
),
dstUin
)
// captured from group
private
fun
createForLongMessage
(
client
:
QQAndroidClient
,
messageData
:
MessageValidationData
,
dstUin
:
Long
// group uin
):
OutgoingPacket
=
buildOutgoingUniPacket
(
client
)
{
writeProtoBuf
(
MultiMsg
.
ReqBody
.
serializer
(),
MultiMsg
.
ReqBody
(
subcmd
=
1
,
termType
=
5
,
platformType
=
9
,
netType
=
3
,
// wifi=3, wap=5
buildVer
=
client
.
buildVer
,
buType
=
1
,
multimsgApplyupReq
=
listOf
(
MultiMsg
.
MultiMsgApplyUpReq
(
applyId
=
0
,
dstUin
=
dstUin
,
msgMd5
=
messageData
.
md5
,
msgSize
=
messageData
.
data
.
size
.
toLong
(),
msgType
=
3
// TODO 3 for group?
)
)
)
)
}
/*
RspBody#195600860 {
multimsgApplyupRsp=[MultiMsgApplyUpRsp#314337396 {
applyId=0x00000000(0)
blockSize=0x0000000000000000(0)
msgKey=4E 64 43 67 6D 61 71 35 6D 52 73 43 53 38 41 58
msgResid=4F 54 39 4E 4C 63 47 31 5A 79 79 62 78 69 39 30 76 77 2F 63 30 59 7A 30 42 4A 69 45 63 4B 4A 32 32 36 43 42 55 6B 56 46 49 74 73 7A 34 51 5A 73 55 78 7A 75 71 5A 53 2F 78 33 66 50 76 53 4C 74
msgSig=AF 63 72 0B 4D 5B 17 6E D8 35 C1 D3 3F C8 D7 FC F0 A8 0A 67 4D B5 A6 B3 B7 E2 E1 9F 96 68 D3 BC AD 4A 6A 20 72 E8 D2 44 C3 8B 93 60 F3 3C 4B 46 83 E4 75 A2 3C 72 A4 F7 31 D9 88 89 23 34 9A AF EF FC 17 29 5D 6C D0 2B F1 63 D5 9F E2 B9 B5 49 D2 62 E3 D0 F9 19 C5 0D 20 AF 78 D5 34 7E BB B7 E2 8E 5C 69 F4 38 38 E7
msgUkey=1B 76 62 FB B2 C6 24 C3 1F 39 47 0D 45 5C 77 BD 0C 8F 69 FB C8 4F D8 76 83 26 60 EA A3 24 BC FD F6 C8 B4 64 DA 47 9D 6C 1A FA F4 EF 02 FC A4 76 1F 87 EB FF 51 62 20 E9 1F 74 6B 2F 7B 7C 53 EC 6D A2 53 AC 2B 93 B4 79 83 6D E6 D8 86 E1 D5 E2 4D EE 75 03 A3 3B 72 EB 0A 3E 13 3A 80 70 EF CC B4 0D F9 42 E3 DF 5F 7A 4C 36 BC 3B 9C 31 5A B1 40 B4 5B 49 26 CE 65 BD 2F 86 8D 9D 0C 34 1B 5E 32 6E EF 60 4B E1 60 7F 1A 98 CF 14 42 85 A6 F8 BE A5 EE A7 A6 C7 9E 11
result=0x00000000(0)
uint32UpIp=[0xA2BE977B(-1564567685), 0xE1E903B7(-504822857), 0xA3BE977B(-1547790469), 0xA6055B65(-1509598363)]
uint32UpPort=[0x00000050(80), 0x00001F90(8080), 0x000001BB(443), 0x00000050(80)]
upOffset=0x0000000000000000(0)
}]
subcmd=0x00000001(1)
}
*/
override
suspend
fun
ByteReadPacket
.
decode
(
bot
:
QQAndroidBot
):
Response
{
val
response
=
readProtoBuf
(
MultiMsg
.
MultiMsgApplyUpRsp
.
serializer
())
check
(
response
.
result
==
0
)
{
kotlin
.
run
{
println
(
response
.
_miraiContentToString
())
}.
let
{
"Protocol error: MultiMsg.ApplyUp failed with result ${response.result}"
}
}
return
Response
(
response
)
}
}
}
\ No newline at end of file
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils/cryptor/MultiMsgCryptor.kt
0 → 100644
View file @
3f523e6f
/*
* Copyright 2020 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/master/LICENSE
*/
package
net.mamoe.mirai.qqandroid.utils.cryptor
import
net.mamoe.mirai.utils.io.toUHexString
internal
object
MultiMsgCryptor
{
private
val
impl
=
class_1457
()
fun
decrypt
(
data
:
ByteArray
,
offset
:
Int
,
length
:
Int
,
key
:
ByteArray
):
ByteArray
{
return
this
.
impl
.
method_67425
(
data
,
offset
,
length
,
key
)
?:
error
(
"MultiMsgCryptor decypt failed: key=${key.toUHexString()}, data=${data.drop(offset).take(length).toByteArray().toUHexString()}"
)
}
fun
decrypt
(
data
:
ByteArray
,
key
:
ByteArray
):
ByteArray
{
return
this
.
impl
.
method_67426
(
data
,
key
)
?:
error
(
"MultiMsgCryptor decrypt failed: key=${key.toUHexString()}, data=${data.toUHexString()}"
)
}
fun
enableResultRandom
(
enabled
:
Boolean
)
{
this
.
impl
.
method_67424
(
enabled
)
}
fun
encrypt
(
data
:
ByteArray
,
key
:
ByteArray
):
ByteArray
{
return
this
.
impl
.
method_67427
(
data
,
key
)
}
}
\ No newline at end of file
mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/utils/cryptor/class_1457.kt
0 → 100644
View file @
3f523e6f
@
file
:
Suppress
(
"NAME_SHADOWING"
)
package
net.mamoe.mirai.qqandroid.utils.cryptor
import
kotlinx.io.core.buildPacket
import
kotlinx.io.core.readBytes
import
net.mamoe.mirai.utils.io.toByteArray
import
kotlin.experimental.and
import
kotlin.experimental.xor
import
kotlin.random.Random
// $FF: renamed from: com.tencent.qphone.base.util.b
internal
class
class_1457 {
// $
FF
:
renamed
from
:
a
byte
[]
private
lateinit
var
field_71278
:
ByteArray
// $FF: renamed from: b byte[]
private
var
field_71279
:
ByteArray
?
=
null
// $FF: renamed from: c byte[]
private
lateinit
var
field_71280
:
ByteArray
// $FF: renamed from: d int
private
var
field_71281
=
0
// $FF: renamed from: e int
private
var
field_71282
=
0
// $FF: renamed from: f int
private
var
field_71283
=
0
// $FF: renamed from: g int
private
var
field_71284
=
0
// $FF: renamed from: h byte[]
private
var
field_71285
:
ByteArray
?
=
null
// $FF: renamed from: i boolean
private
var
field_71286
=
true
// $FF: renamed from: j int
private
var
field_71287
=
0
// $FF: renamed from: k java.util.Random
private
val
field_71288
:
Random
=
Random
// $FF: renamed from: l boolean
private
var
field_71289
=
true
// $FF: renamed from: a () void
private
fun
method_67415
()
{
var
var1
:
Int
var
var2
:
ByteArray
field_71283
=
0
while
(
field_71283
<
8
)
{
if
(
field_71286
)
{
var2
=
field_71278
var1
=
field_71283
var2
[
var1
]
=
var2
[
var1
]
xor
field_71279
!!
[
field_71283
]
}
else
{
var2
=
field_71278
var1
=
field_71283
var2
[
var1
]
=
var2
[
var1
]
xor
field_71280
[
field_71282
+
field_71283
]
}
++
field_71283
}
arraycopy
(
method_67417
(
field_71278
),
0
,
field_71280
,
field_71281
,
8
)
field_71283
=
0
while
(
field_71283
<
8
)
{
var2
=
field_71280
var1
=
field_71281
+
field_71283
var2
[
var1
]
=
var2
[
var1
]
xor
field_71279
!!
[
field_71283
]
++
field_71283
}
arraycopy
(
field_71278
,
0
,
field_71279
!!
,
0
,
8
)
field_71282
=
field_71281
field_71281
+=
8
field_71283
=
0
field_71286
=
false
}
// $FF: renamed from: a (int) byte[]
private
fun
method_67416
(
var1
:
Int
):
ByteArray
{
val
var2
=
ByteArray
(
var1
)
field_71288
.
nextBytes
(
var2
)
return
var2
}
// $FF: renamed from: a (byte[]) byte[]
private
fun
method_67417
(
var1
:
ByteArray
):
ByteArray
{
var
var1
:
ByteArray
?
=
var1
var
var2
=
16
var
var5
:
Long
var
var7
:
Long
val
var9
:
Long
val
var11
:
Long
val
var13
:
Long
val
var15
:
Long
var7
=
method_67414
(
var1
,
0
,
4
)
var5
=
method_67414
(
var1
,
4
,
4
)
var9
=
method_67414
(
field_71285
,
0
,
4
)
var11
=
method_67414
(
field_71285
,
4
,
4
)
var13
=
method_67414
(
field_71285
,
8
,
4
)
var15
=
method_67414
(
field_71285
,
12
,
4
)
var
var3
=
0L
while
(
var2
>
0
)
{
var3
=
var3
+
(-
1640531527L
and
4294967295L
)
and
4294967295L
var7
=
var7
+
((
var5
shl
4
)
+
var9
xor
var5
+
var3
xor
(
var5
ushr
5
)
+
var11
)
and
4294967295L
var5
=
var5
+
((
var7
shl
4
)
+
var13
xor
var7
+
var3
xor
(
var7
ushr
5
)
+
var15
)
and
4294967295L
--
var2
}
return
buildPacket
{
writeInt
(
var7
.
toInt
())
writeInt
(
var5
.
toInt
())
}.
readBytes
()
}
// $FF: renamed from: a (byte[], int) byte[]
private
fun
method_67418
(
var1
:
ByteArray
?,
var2
:
Int
):
ByteArray
?
{
var
var1
=
var1
var
var2
=
var2
val
var3
:
Byte
=
16
var
var6
:
Long
var
var8
:
Long
val
var10
:
Long
val
var12
:
Long
val
var14
:
Long
val
var16
:
Long
var8
=
method_67414
(
var1
,
var2
,
4
)
var6
=
method_67414
(
var1
,
var2
+
4
,
4
)
var10
=
method_67414
(
field_71285
,
0
,
4
)
var12
=
method_67414
(
field_71285
,
4
,
4
)
var14
=
method_67414
(
field_71285
,
8
,
4
)
var16
=
method_67414
(
field_71285
,
12
,
4
)
var
var4
=
-
478700656L
and
4294967295L
var2
=
var3
.
toInt
()
while
(
var2
>
0
)
{
var6
=
var6
-
((
var8
shl
4
)
+
var14
xor
var8
+
var4
xor
(
var8
ushr
5
)
+
var16
)
and
4294967295L
var8
=
var8
-
((
var6
shl
4
)
+
var10
xor
var6
+
var4
xor
(
var6
ushr
5
)
+
var12
)
and
4294967295L
var4
=
var4
-
(-
1640531527L
and
4294967295L
)
and
4294967295L
--
var2
}
return
var8
.
toByteArray
()
+
var6
.
toByteArray
()
}
// $FF: renamed from: a (byte[], byte[], int) byte[]
private
fun
method_67419
(
var1
:
ByteArray
,
var2
:
ByteArray
,
var3
:
Int
):
ByteArray
?
{
var
var1
:
ByteArray
?
=
var1
var
var2
:
ByteArray
?
=
var2
var2
=
method_67425
(
var1
,
0
,
var1
!!
.
size
,
var2
)
var1
=
var2
if
(
var2
==
null
)
{
var1
=
method_67416
(
var3
)
}
return
var1
}
// $FF: renamed from: b () int
private
fun
method_67420
():
Int
{
return
if
(
field_71289
)
field_71288
.
nextInt
()
else
16711935
}
// $FF: renamed from: b (byte[], int, int) boolean
private
fun
method_67421
(
var1
:
ByteArray
?,
var2
:
Int
,
var3
:
Int
):
Boolean
{
field_71283
=
0
while
(
field_71283
<
8
)
{
if
(
field_71287
+
field_71283
>=
var3
)
{
return
true
}
val
var5
=
field_71279
val
var4
=
field_71283
var5
!!
[
var4
]
=
var5
[
var4
]
xor
var1
!!
[
field_71281
+
var2
+
field_71283
]
++
field_71283
}
field_71279
=
method_67422
(
field_71279
)
return
if
(
field_71279
==
null
)
{
false
}
else
{
field_71287
+=
8
field_71281
+=
8
field_71283
=
0
true
}
}
// $FF: renamed from: b (byte[]) byte[]
private
fun
method_67422
(
var1
:
ByteArray
?):
ByteArray
?
{
return
method_67418
(
var1
,
0
)
}
// $FF: renamed from: b (byte[], int, int, byte[]) byte[]
private
fun
method_67423
(
var1
:
ByteArray
,
var2
:
Int
,
var3
:
Int
,
var4
:
ByteArray
):
ByteArray
{
var
var1
=
var1
var
var2
=
var2
var
var3
=
var3
var
var4
=
var4
field_71278
=
ByteArray
(
8
)
field_71279
=
ByteArray
(
8
)
field_71283
=
1
field_71284
=
0
field_71282
=
0
field_71281
=
0
field_71285
=
var4
field_71286
=
true
field_71283
=
(
var3
+
10
)
%
8
if
(
field_71283
!=
0
)
{
field_71283
=
8
-
field_71283
}
field_71280
=
ByteArray
(
field_71283
+
var3
+
10
)
field_71278
[
0
]
=
(
method_67420
()
and
248
or
field_71283
).
toByte
()
var
var5
:
Int
var5
=
1
while
(
var5
<=
field_71283
)
{
field_71278
[
var5
]
=
(
method_67420
()
and
255
).
toByte
()
++
var5
}
++
field_71283
var5
=
0
while
(
var5
<
8
)
{
field_71279
!!
[
var5
]
=
0
++
var5
}
field_71284
=
1
while
(
field_71284
<=
2
)
{
if
(
field_71283
<
8
)
{
var4
=
field_71278
var5
=
field_71283
++
var4
[
var5
]
=
(
method_67420
()
and
255
).
toByte
()
++
field_71284
}
if
(
field_71283
==
8
)
{
method_67415
()
}
}
while
(
var3
>
0
)
{
if
(
field_71283
<
8
)
{
var4
=
field_71278
val
var6
=
field_71283
++
var5
=
var2
+
1
var4
[
var6
]
=
var1
[
var2
]
--
var3
var2
=
var5
}
if
(
field_71283
==
8
)
{
method_67415
()
}
}
field_71284
=
1
while
(
field_71284
<=
7
)
{
if
(
field_71283
<
8
)
{
var1
=
field_71278
var2
=
field_71283
++
var1
[
var2
]
=
0
++
field_71284
}
if
(
field_71283
==
8
)
{
method_67415
()
}
}
return
field_71280
}
// $FF: renamed from: a (boolean) void
fun
method_67424
(
var1
:
Boolean
)
{
field_71289
=
var1
}
// $FF: renamed from: a (byte[], int, int, byte[]) byte[]
internal
fun
method_67425
(
var1
:
ByteArray
?,
var2
:
Int
,
var3
:
Int
,
var4
:
ByteArray
?
):
ByteArray
?
{
var
var4
=
var4
field_71282
=
0
field_71281
=
0
field_71285
=
var4
var4
=
ByteArray
(
var2
+
8
)
return
if
(
var3
%
8
==
0
&&
var3
>=
16
)
{
field_71279
=
method_67418
(
var1
,
var2
)
field_71283
=
(
field_71279
!!
[
0
]
and
7
).
toInt
()
var
var6
=
var3
-
field_71283
-
10
if
(
var6
<
0
)
{
null
}
else
{
var
var5
:
Int
var5
=
var2
while
(
var5
<
var4
.
size
)
{
var4
[
var5
]
=
0
++
var5
}
field_71280
=
ByteArray
(
var6
)
field_71282
=
0
field_71281
=
8
field_71287
=
8
++
field_71283
field_71284
=
1
while
(
field_71284
<=
2
)
{
if
(
field_71283
<
8
)
{
++
field_71283
++
field_71284
}
if
(
field_71283
==
8
)
{
if
(!
method_67421
(
var1
,
var2
,
var3
))
{
return
null
}
var4
=
var1
}
}
var5
=
0
while
(
var6
!=
0
)
{
if
(
field_71283
<
8
)
{
field_71280
[
var5
]
=
(
var4
!!
[
field_71282
+
var2
+
field_71283
]
xor
field_71279
!!
[
field_71283
])
++
var5
++
field_71283
--
var6
}
if
(
field_71283
==
8
)
{
field_71282
=
field_71281
-
8
if
(!
method_67421
(
var1
,
var2
,
var3
))
{
return
null
}
var4
=
var1
}
}
field_71284
=
1
while
(
field_71284
<
8
)
{
if
(
field_71283
<
8
)
{
if
(
var4
!!
[
field_71282
+
var2
+
field_71283
]
xor
field_71279
!!
[
field_71283
]
!=
0
.
toByte
())
{
return
null
}
++
field_71283
}
if
(
field_71283
==
8
)
{
field_71282
=
field_71281
if
(!
method_67421
(
var1
,
var2
,
var3
))
{
return
null
}
var4
=
var1
}
++
field_71284
}
field_71280
}
}
else
{
null
}
}
// $FF: renamed from: a (byte[], byte[]) byte[]
internal
fun
method_67426
(
var1
:
ByteArray
,
var2
:
ByteArray
?):
ByteArray
?
{
return
method_67425
(
var1
,
0
,
var1
.
size
,
var2
)
}
// $FF: renamed from: b (byte[], byte[]) byte[]
internal
fun
method_67427
(
var1
:
ByteArray
,
var2
:
ByteArray
):
ByteArray
{
return
method_67423
(
var1
,
0
,
var1
.
size
,
var2
)
}
companion
object
{
// $FF: renamed from: a (byte[], int, int) long
private
fun
method_67414
(
var0
:
ByteArray
?,
var1
:
Int
,
var2
:
Int
):
Long
{
var
var1
=
var1
var
var2
=
var2
var
var3
=
0L
if
(
var2
>
8
)
{
var2
=
var1
+
8
}
else
{
var2
+=
var1
}
while
(
var1
<
var2
)
{
var3
=
var3
shl
8
or
(
var0
!!
[
var1
]
and
255
.
toByte
()).
toLong
()
++
var1
}
return
4294967295L
and
var3
or
var3
ushr
32
}
}
}
internal
expect
fun
arraycopy
(
src
:
ByteArray
,
srcPos
:
Int
,
dest
:
ByteArray
,
destPos
:
Int
,
length
:
Int
)
\ No newline at end of file
mirai-core-qqandroid/src/jvmMain/kotlin/net/mamoe/mirai/qqandroid/utils/cryptor/arraycopy.kt
0 → 100644
View file @
3f523e6f
package
net.mamoe.mirai.qqandroid.utils.cryptor
internal
actual
fun
arraycopy
(
src
:
ByteArray
,
srcPos
:
Int
,
dest
:
ByteArray
,
destPos
:
Int
,
length
:
Int
)
=
System
.
arraycopy
(
src
,
srcPos
,
dest
,
destPos
,
length
)
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/lowLevelApi.kt
View file @
3f523e6f
...
...
@@ -13,6 +13,7 @@ import kotlinx.coroutines.Job
import
net.mamoe.mirai.contact.Group
import
net.mamoe.mirai.contact.QQ
import
net.mamoe.mirai.data.*
import
net.mamoe.mirai.message.data.Message
import
net.mamoe.mirai.message.data.MessageSource
import
net.mamoe.mirai.utils.MiraiExperimentalAPI
import
net.mamoe.mirai.utils.MiraiInternalAPI
...
...
@@ -139,6 +140,14 @@ interface LowLevelBotAPIAccessor {
@LowLevelAPI
@MiraiExperimentalAPI
suspend
fun
_lowLevelGetGroupActiveData
(
groupId
:
Long
):
GroupActiveData
/**
* 发送长消息
*/
@SinceMirai
(
"0.31.0"
)
@LowLevelAPI
@MiraiExperimentalAPI
suspend
fun
_lowLevelSendLongMessage
(
groupCode
:
Long
,
message
:
Message
)
}
/**
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/PlainText.kt
View file @
3f523e6f
...
...
@@ -15,7 +15,6 @@ package net.mamoe.mirai.message.data
import
kotlin.jvm.JvmMultifileClass
import
kotlin.jvm.JvmName
import
kotlin.jvm.JvmStatic
import
kotlin.jvm.JvmSynthetic
/**
...
...
@@ -28,26 +27,13 @@ class PlainText(val stringValue: String) :
Comparable
<
String
>
by
stringValue
,
CharSequence
by
stringValue
{
@Suppress
(
"unused"
)
constructor
(
charSequence
:
CharSequence
)
:
this
(
charSequence
.
toString
())
override
operator
fun
contains
(
sub
:
String
):
Boolean
=
sub
in
stringValue
override
fun
toString
():
String
=
stringValue
companion
object
Key
:
Message
.
Key
<
PlainText
>
{
@JvmStatic
val
Empty
=
PlainText
(
""
)
@JvmStatic
val
Null
=
PlainText
(
"null"
)
inline
fun
of
(
value
:
String
):
PlainText
{
return
PlainText
(
value
)
}
inline
fun
of
(
value
:
CharSequence
):
PlainText
{
return
PlainText
(
value
)
}
}
companion
object
Key
:
Message
.
Key
<
PlainText
>
}
/**
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/RichMessage.kt
View file @
3f523e6f
...
...
@@ -33,6 +33,40 @@ interface RichMessage : MessageContent {
@SinceMirai
(
"0.30.0"
)
companion
object
Templates
:
Message
.
Key
<
RichMessage
>
{
/**
* 合并转发.
*/
@MiraiExperimentalAPI
fun
mergedForward
():
Nothing
{
TODO
()
}
/**
* 长消息.
*
* @param brief 消息内容纯文本, 显示在图片的前面
*/
@MiraiExperimentalAPI
fun
longMessage
(
brief
:
String
,
resId
:
String
,
time
:
Long
):
XmlMessage
{
val
template
=
"""
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
<msg serviceID="35" templateID="1" action="viewMultiMsg"
brief="$brief"
m_resid="$resId"
m_fileName="$time" sourceMsgId="0" url=""
flag="3" adverSign="0" multiMsgFlag="1">
<item layout="1">
<title>$brief…</title>
<hr hidden="false" style="0"/>
<summary>点击查看完整消息</summary>
</item>
<source name="聊天记录" icon="" action="" appid="-1"/>
</msg>
"""
return
XmlMessage
(
template
)
}
@MiraiExperimentalAPI
@SinceMirai
(
"0.30.0"
)
fun
share
(
url
:
String
,
title
:
String
?
=
null
,
content
:
String
?
=
null
,
coverUrl
:
String
?
=
null
):
XmlMessage
=
...
...
@@ -107,6 +141,19 @@ class XmlMessage constructor(override val content: String) : RichMessage {
override
fun
toString
():
String
=
content
}
/**
* 合并转发消息
*/
@SinceMirai
(
"0.31.0"
)
@MiraiExperimentalAPI
class
MergedForwardedMessage
(
override
val
content
:
String
)
:
RichMessage
{
companion
object
Key
:
Message
.
Key
<
XmlMessage
>
// serviceId = 35
override
fun
toString
():
String
=
content
}
/**
* 构造一条 XML 消息
*/
...
...
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