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
fdf50e4d
Commit
fdf50e4d
authored
Oct 19, 2019
by
Him188
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Image uploading
parent
4d346a2c
Changes
49
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
49 changed files
with
842 additions
and
353 deletions
+842
-353
mirai-console/src/main/java/net/mamoe/mirai/MiraiServer.kt
mirai-console/src/main/java/net/mamoe/mirai/MiraiServer.kt
+3
-1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt
+5
-3
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotHelper.kt
...i-core/src/commonMain/kotlin/net.mamoe.mirai/BotHelper.kt
+6
-6
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Contact.kt
.../src/commonMain/kotlin/net.mamoe.mirai/contact/Contact.kt
+4
-2
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Group.kt
...re/src/commonMain/kotlin/net.mamoe.mirai/contact/Group.kt
+41
-39
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/QQ.kt
...-core/src/commonMain/kotlin/net.mamoe.mirai/contact/QQ.kt
+3
-1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/Message.kt
.../src/commonMain/kotlin/net.mamoe.mirai/message/Message.kt
+9
-6
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/MessageType.kt
.../commonMain/kotlin/net.mamoe.mirai/message/MessageType.kt
+2
-1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/internal/MessageDataInternal.kt
...n/net.mamoe.mirai/message/internal/MessageDataInternal.kt
+82
-25
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/BotNetworkHandler.kt
...nMain/kotlin/net.mamoe.mirai/network/BotNetworkHandler.kt
+1
-1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/BotSession.kt
...c/commonMain/kotlin/net.mamoe.mirai/network/BotSession.kt
+11
-11
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/TIMBotNetworkHandler.kt
....mamoe.mirai/network/protocol/tim/TIMBotNetworkHandler.kt
+3
-3
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/handler/ActionPacketHandler.kt
...mirai/network/protocol/tim/handler/ActionPacketHandler.kt
+7
-2
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/handler/EventPacketHandler.kt
....mirai/network/protocol/tim/handler/EventPacketHandler.kt
+1
-1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/handler/TemporaryPacketHandler.kt
...ai/network/protocol/tim/handler/TemporaryPacketHandler.kt
+13
-8
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/ClientPacket.kt
...t.mamoe.mirai/network/protocol/tim/packet/ClientPacket.kt
+5
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/ClientRawPacket.kt
...amoe.mirai/network/protocol/tim/packet/ClientRawPacket.kt
+25
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/GradeInfo.kt
.../net.mamoe.mirai/network/protocol/tim/packet/GradeInfo.kt
+1
-2
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/Heartbeat.kt
.../net.mamoe.mirai/network/protocol/tim/packet/Heartbeat.kt
+1
-1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/PacketId.kt
...n/net.mamoe.mirai/network/protocol/tim/packet/PacketId.kt
+1
-1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/ServerPacket.kt
...t.mamoe.mirai/network/protocol/tim/packet/ServerPacket.kt
+2
-0
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/UploadImage.kt
...et.mamoe.mirai/network/protocol/tim/packet/UploadImage.kt
+143
-32
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/action/AddContact.kt
...oe.mirai/network/protocol/tim/packet/action/AddContact.kt
+11
-6
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/action/ClientSendFriendMessagePacket.kt
...otocol/tim/packet/action/ClientSendFriendMessagePacket.kt
+56
-30
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/action/ClientSendGroupMessagePacket.kt
...rotocol/tim/packet/action/ClientSendGroupMessagePacket.kt
+5
-5
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/ServerEventPackets.kt
...i/network/protocol/tim/packet/event/ServerEventPackets.kt
+2
-2
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/login/ClientChangeOnlineStatusPacket.kt
...otocol/tim/packet/login/ClientChangeOnlineStatusPacket.kt
+1
-1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/login/PasswordSubmission.kt
...i/network/protocol/tim/packet/login/PasswordSubmission.kt
+3
-3
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/login/SKey.kt
...net.mamoe.mirai/network/protocol/tim/packet/login/SKey.kt
+4
-4
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/login/Session.kt
....mamoe.mirai/network/protocol/tim/packet/login/Session.kt
+2
-2
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/login/Touch.kt
...et.mamoe.mirai/network/protocol/tim/packet/login/Touch.kt
+3
-3
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/login/VerificationCode.kt
...rai/network/protocol/tim/packet/login/VerificationCode.kt
+3
-3
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/BotAccount.kt
...src/commonMain/kotlin/net.mamoe.mirai/utils/BotAccount.kt
+3
-1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/ByteReadPacketUtil.kt
...onMain/kotlin/net.mamoe.mirai/utils/ByteReadPacketUtil.kt
+2
-1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/ContactList.kt
...rc/commonMain/kotlin/net.mamoe.mirai/utils/ContactList.kt
+3
-1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/DebugUtil.kt
.../src/commonMain/kotlin/net.mamoe.mirai/utils/DebugUtil.kt
+24
-8
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/PacketBuilderUtil.kt
...monMain/kotlin/net.mamoe.mirai/utils/PacketBuilderUtil.kt
+15
-5
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/PlatformUtils.kt
.../commonMain/kotlin/net.mamoe.mirai/utils/PlatformUtils.kt
+10
-4
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/TEA.kt
...i-core/src/commonMain/kotlin/net.mamoe.mirai/utils/TEA.kt
+1
-1
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/TypeConvertion.kt
...commonMain/kotlin/net.mamoe.mirai/utils/TypeConvertion.kt
+1
-0
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/contact/ContactJvm.kt
.../src/jvmMain/kotlin/net/mamoe/mirai/contact/ContactJvm.kt
+5
-3
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/network/protocol/tim/packet/UploadImageJvm.kt
...mamoe/mirai/network/protocol/tim/packet/UploadImageJvm.kt
+161
-72
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/PlatformImageJvm.kt
.../jvmMain/kotlin/net/mamoe/mirai/utils/PlatformImageJvm.kt
+1
-1
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/PlatformUtilsJvm.kt
.../jvmMain/kotlin/net/mamoe/mirai/utils/PlatformUtilsJvm.kt
+50
-24
mirai-core/src/jvmTest/kotlin/BadQQFilter.kt
mirai-core/src/jvmTest/kotlin/BadQQFilter.kt
+3
-1
mirai-debug/build.gradle
mirai-debug/build.gradle
+2
-0
mirai-debug/src/main/java/DownloadImgTest.kt
mirai-debug/src/main/java/DownloadImgTest.kt
+12
-0
mirai-debug/src/main/java/PacketDebuger.kt
mirai-debug/src/main/java/PacketDebuger.kt
+63
-18
mirai-demos/mirai-demo-1/src/main/java/demo1/Main.kt
mirai-demos/mirai-demo-1/src/main/java/demo1/Main.kt
+27
-8
No files found.
mirai-console/src/main/java/net/mamoe/mirai/MiraiServer.kt
View file @
fdf50e4d
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
)
package
net.mamoe.mirai
package
net.mamoe.mirai
import
kotlinx.coroutines.runBlocking
import
kotlinx.coroutines.runBlocking
...
@@ -172,7 +174,7 @@ object MiraiServer {
...
@@ -172,7 +174,7 @@ object MiraiServer {
get
()
{
get
()
{
for
(
it
in
qqList
.
split
(
"\n"
).
dropLastWhile
{
it
.
isEmpty
()
}.
toTypedArray
())
{
for
(
it
in
qqList
.
split
(
"\n"
).
dropLastWhile
{
it
.
isEmpty
()
}.
toTypedArray
())
{
val
strings
=
it
.
split
(
"----"
).
dropLastWhile
{
it
.
isEmpty
()
}.
toTypedArray
()
val
strings
=
it
.
split
(
"----"
).
dropLastWhile
{
it
.
isEmpty
()
}.
toTypedArray
()
val
bot
=
Bot
(
BotAccount
(
strings
[
0
].
to
Long
(),
strings
[
1
]),
MiraiLogger
)
val
bot
=
Bot
(
BotAccount
(
strings
[
0
].
to
UInt
(),
strings
[
1
]),
MiraiLogger
)
if
(
runBlocking
{
bot
.
login
()
}
===
LoginResult
.
SUCCESS
)
{
if
(
runBlocking
{
bot
.
login
()
}
===
LoginResult
.
SUCCESS
)
{
bot
.
logGreen
(
"Login succeed"
)
bot
.
logGreen
(
"Login succeed"
)
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt
View file @
fdf50e4d
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
)
package
net.mamoe.mirai
package
net.mamoe.mirai
import
kotlinx.atomicfu.atomic
import
kotlinx.atomicfu.atomic
...
@@ -86,16 +88,16 @@ class Bot(val account: BotAccount, val logger: MiraiLogger) {
...
@@ -86,16 +88,16 @@ class Bot(val account: BotAccount, val logger: MiraiLogger) {
* 通过群号码获取群对象.
* 通过群号码获取群对象.
* 注意: 在并发调用时, 这个方法并不是原子的.
* 注意: 在并发调用时, 这个方法并不是原子的.
*/
*/
fun
getQQ
(
account
:
Long
):
QQ
=
qqs
.
getOrPut
(
account
)
{
QQ
(
this
@Bot
,
account
)
}
fun
getQQ
(
account
:
UInt
):
QQ
=
qqs
.
getOrPut
(
account
)
{
QQ
(
this
@Bot
,
account
)
}
/**
/**
* 通过群号码获取群对象.
* 通过群号码获取群对象.
* 注意: 在并发调用时, 这个方法并不是原子的.
* 注意: 在并发调用时, 这个方法并不是原子的.
*/
*/
fun
getGroupByNumber
(
groupNumber
:
Long
):
Group
=
groups
.
getOrPut
(
groupNumber
)
{
Group
(
this
@Bot
,
groupNumber
)
}
fun
getGroupByNumber
(
groupNumber
:
UInt
):
Group
=
groups
.
getOrPut
(
groupNumber
)
{
Group
(
this
@Bot
,
groupNumber
)
}
fun
getGroupById
(
groupId
:
Long
):
Group
{
fun
getGroupById
(
groupId
:
UInt
):
Group
{
return
getGroupByNumber
(
Group
.
groupIdToNumber
(
groupId
))
return
getGroupByNumber
(
Group
.
groupIdToNumber
(
groupId
))
}
}
}
}
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotHelper.kt
View file @
fdf50e4d
...
@@ -17,14 +17,14 @@ import net.mamoe.mirai.utils.toUHexString
...
@@ -17,14 +17,14 @@ import net.mamoe.mirai.utils.toUHexString
*/
*/
//Contacts
//Contacts
fun
Bot
.
getQQ
(
number
:
Long
):
QQ
=
this
.
contacts
.
getQQ
(
number
)
fun
Bot
.
getQQ
(
number
:
Long
):
QQ
=
this
.
contacts
.
getQQ
(
number
.
toUInt
()
)
fun
Bot
.
getQQ
(
number
:
UInt
):
QQ
=
getQQ
(
number
.
toLong
()
)
fun
Bot
.
getQQ
(
number
:
UInt
):
QQ
=
this
.
contacts
.
getQQ
(
number
)
fun
Bot
.
getGroupByNumber
(
number
:
Long
):
Group
=
this
.
contacts
.
getGroupByNumber
(
number
)
fun
Bot
.
getGroupByNumber
(
number
:
Long
):
Group
=
this
.
contacts
.
getGroupByNumber
(
number
.
toUInt
()
)
fun
Bot
.
getGroupByNumber
(
number
:
UInt
):
Group
=
getGroupByNumber
(
number
.
toLong
()
)
fun
Bot
.
getGroupByNumber
(
number
:
UInt
):
Group
=
this
.
contacts
.
getGroupByNumber
(
number
)
fun
Bot
.
getGroupById
(
number
:
Long
):
Group
=
this
.
contacts
.
getGroupById
(
number
)
fun
Bot
.
getGroupById
(
number
:
UInt
):
Group
=
this
.
contacts
.
getGroupById
(
number
)
val
Bot
.
groups
:
ContactList
<
Group
>
get
()
=
this
.
contacts
.
groups
val
Bot
.
groups
:
ContactList
<
Group
>
get
()
=
this
.
contacts
.
groups
...
@@ -39,7 +39,7 @@ suspend fun Bot.login(configuration: BotNetworkConfiguration.() -> Unit): LoginR
...
@@ -39,7 +39,7 @@ suspend fun Bot.login(configuration: BotNetworkConfiguration.() -> Unit): LoginR
suspend
fun
Bot
.
login
():
LoginResult
=
this
.
network
.
login
(
BotNetworkConfiguration
.
Default
)
suspend
fun
Bot
.
login
():
LoginResult
=
this
.
network
.
login
(
BotNetworkConfiguration
.
Default
)
//BotAccount
//BotAccount
val
Bot
.
qqAccount
:
Long
get
()
=
this
.
account
.
account
val
Bot
.
qqAccount
:
UInt
get
()
=
this
.
account
.
account
//logging
//logging
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Contact.kt
View file @
fdf50e4d
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
)
package
net.mamoe.mirai.contact
package
net.mamoe.mirai.contact
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.Bot
...
@@ -11,7 +13,7 @@ import net.mamoe.mirai.message.toChain
...
@@ -11,7 +13,7 @@ import net.mamoe.mirai.message.toChain
*
*
* @author Him188moe
* @author Him188moe
*/
*/
abstract
class
PlatformContactBase
internal
constructor
(
val
bot
:
Bot
,
val
number
:
Long
)
{
abstract
class
PlatformContactBase
internal
constructor
(
val
bot
:
Bot
,
val
number
:
UInt
)
{
abstract
suspend
fun
sendMessage
(
message
:
MessageChain
)
abstract
suspend
fun
sendMessage
(
message
:
MessageChain
)
...
@@ -33,4 +35,4 @@ abstract class PlatformContactBase internal constructor(val bot: Bot, val number
...
@@ -33,4 +35,4 @@ abstract class PlatformContactBase internal constructor(val bot: Bot, val number
* 在不同平台可能有不同的实现.
* 在不同平台可能有不同的实现.
* 如在 JVM, suspend 调用不便, [Contact] 中有简化调用的 `blocking`() 和 `async`
* 如在 JVM, suspend 调用不便, [Contact] 中有简化调用的 `blocking`() 和 `async`
*/
*/
expect
sealed
class
Contact
(
bot
:
Bot
,
number
:
Long
)
:
PlatformContactBase
expect
sealed
class
Contact
(
bot
:
Bot
,
number
:
UInt
)
:
PlatformContactBase
\ No newline at end of file
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/Group.kt
View file @
fdf50e4d
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
,
"EXPERIMENTAL_UNSIGNED_LITERALS"
)
package
net.mamoe.mirai.contact
package
net.mamoe.mirai.contact
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.Bot
...
@@ -13,8 +15,8 @@ import net.mamoe.mirai.utils.ContactList
...
@@ -13,8 +15,8 @@ import net.mamoe.mirai.utils.ContactList
*
*
* @author Him188moe
* @author Him188moe
*/
*/
expect
class
Group
(
bot
:
Bot
,
number
:
Long
)
:
Contact
{
expect
class
Group
(
bot
:
Bot
,
number
:
UInt
)
:
Contact
{
val
groupId
:
Long
val
groupId
:
UInt
val
members
:
ContactList
<
QQ
>
val
members
:
ContactList
<
QQ
>
override
suspend
fun
sendMessage
(
message
:
MessageChain
)
override
suspend
fun
sendMessage
(
message
:
MessageChain
)
...
@@ -23,7 +25,7 @@ expect class Group(bot: Bot, number: Long) : Contact {
...
@@ -23,7 +25,7 @@ expect class Group(bot: Bot, number: Long) : Contact {
companion
object
companion
object
}
}
fun
Group
.
Companion
.
groupNumberToId
(
number
:
Long
):
Long
{
//求你别出错
fun
Group
.
Companion
.
groupNumberToId
(
number
:
UInt
):
UInt
{
//求你别出错
val
left
:
Long
=
number
.
toString
().
let
{
val
left
:
Long
=
number
.
toString
().
let
{
if
(
it
.
length
<
6
)
{
if
(
it
.
length
<
6
)
{
return
@
groupNumberToId
number
return
@
groupNumberToId
number
...
@@ -36,84 +38,84 @@ fun Group.Companion.groupNumberToId(number: Long): Long {//求你别出错
...
@@ -36,84 +38,84 @@ fun Group.Companion.groupNumberToId(number: Long): Long {//求你别出错
return
when
(
left
)
{
return
when
(
left
)
{
in
1
..
10
->
{
in
1
..
10
->
{
((
left
+
202
).
toString
()
+
right
.
toString
()).
to
Long
()
((
left
+
202
).
toString
()
+
right
.
toString
()).
to
UInt
()
}
}
in
11
..
19
->
{
in
11
..
19
->
{
((
left
+
469
).
toString
()
+
right
.
toString
()).
to
Long
()
((
left
+
469
).
toString
()
+
right
.
toString
()).
to
UInt
()
}
}
in
20
..
66
->
{
in
20
..
66
->
{
((
left
+
208
).
toString
()
+
right
.
toString
()).
to
Long
()
((
left
+
208
).
toString
()
+
right
.
toString
()).
to
UInt
()
}
}
in
67
..
156
->
{
in
67
..
156
->
{
((
left
+
1943
).
toString
()
+
right
.
toString
()).
to
Long
()
((
left
+
1943
).
toString
()
+
right
.
toString
()).
to
UInt
()
}
}
in
157
..
209
->
{
in
157
..
209
->
{
((
left
+
199
).
toString
()
+
right
.
toString
()).
to
Long
()
((
left
+
199
).
toString
()
+
right
.
toString
()).
to
UInt
()
}
}
in
210
..
309
->
{
in
210
..
309
->
{
((
left
+
389
).
toString
()
+
right
.
toString
()).
to
Long
()
((
left
+
389
).
toString
()
+
right
.
toString
()).
to
UInt
()
}
}
in
310
..
499
->
{
in
310
..
499
->
{
((
left
+
349
).
toString
()
+
right
.
toString
()).
to
Long
()
((
left
+
349
).
toString
()
+
right
.
toString
()).
to
UInt
()
}
}
else
->
number
else
->
number
}
}
}
}
fun
Group
.
Companion
.
groupIdToNumber
(
id
:
Long
):
Long
{
//求你别出错
fun
Group
.
Companion
.
groupIdToNumber
(
id
:
UInt
):
UInt
{
//求你别出错
var
left
:
Long
=
id
.
toString
().
let
{
var
left
:
UInt
=
id
.
toString
().
let
{
if
(
it
.
length
<
6
)
{
if
(
it
.
length
<
6
)
{
return
@
groupIdToNumber
id
return
@
groupIdToNumber
id
}
}
it
.
substring
(
0
until
it
.
length
-
6
).
to
Long
()
it
.
substring
(
0
until
it
.
length
-
6
).
to
UInt
()
}
}
return
when
(
left
)
{
return
when
(
left
.
toInt
()
)
{
in
203
..
212
->
{
in
203
..
212
->
{
val
right
:
Long
=
id
.
toString
().
let
{
val
right
:
UInt
=
id
.
toString
().
let
{
it
.
substring
(
it
.
length
-
6
).
to
Long
()
it
.
substring
(
it
.
length
-
6
).
to
UInt
()
}
}
((
left
-
202
).
toString
()
+
right
.
toString
()).
toLong
()
((
left
-
202
u
).
toString
()
+
right
.
toString
()).
toUInt
()
}
}
in
480
..
488
->
{
in
480
..
488
->
{
val
right
:
Long
=
id
.
toString
().
let
{
val
right
:
UInt
=
id
.
toString
().
let
{
it
.
substring
(
it
.
length
-
6
).
to
Long
()
it
.
substring
(
it
.
length
-
6
).
to
UInt
()
}
}
((
left
-
469
).
toString
()
+
right
.
toString
()).
toLong
()
((
left
-
469
u
).
toString
()
+
right
.
toString
()).
toUInt
()
}
}
in
2100
..
2146
->
{
in
2100
..
2146
->
{
val
right
:
Long
=
id
.
toString
().
let
{
val
right
:
UInt
=
id
.
toString
().
let
{
it
.
substring
(
it
.
length
-
7
).
to
Long
()
it
.
substring
(
it
.
length
-
7
).
to
UInt
()
}
}
left
=
left
.
toString
().
substring
(
0
until
3
).
to
Long
()
left
=
left
.
toString
().
substring
(
0
until
3
).
to
UInt
()
((
left
-
208
).
toString
()
+
right
.
toString
()).
toLong
()
((
left
-
208
u
).
toString
()
+
right
.
toString
()).
toUInt
()
}
}
in
2010
..
2099
->
{
in
2010
..
2099
->
{
val
right
:
Long
=
id
.
toString
().
let
{
val
right
:
UInt
=
id
.
toString
().
let
{
it
.
substring
(
it
.
length
-
6
).
to
Long
()
it
.
substring
(
it
.
length
-
6
).
to
UInt
()
}
}
((
left
-
1943
).
toString
()
+
right
.
toString
()).
toLong
()
((
left
-
1943
u
).
toString
()
+
right
.
toString
()).
toUInt
()
}
}
in
2147
..
2199
->
{
in
2147
..
2199
->
{
val
right
:
Long
=
id
.
toString
().
let
{
val
right
:
UInt
=
id
.
toString
().
let
{
it
.
substring
(
it
.
length
-
7
).
to
Long
()
it
.
substring
(
it
.
length
-
7
).
to
UInt
()
}
}
left
=
left
.
toString
().
substring
(
0
until
3
).
to
Long
()
left
=
left
.
toString
().
substring
(
0
until
3
).
to
UInt
()
((
left
-
199
).
toString
()
+
right
.
toString
()).
toLong
()
((
left
-
199
u
).
toString
()
+
right
.
toString
()).
toUInt
()
}
}
in
4100
..
4199
->
{
in
4100
..
4199
->
{
val
right
:
Long
=
id
.
toString
().
let
{
val
right
:
UInt
=
id
.
toString
().
let
{
it
.
substring
(
it
.
length
-
7
).
to
Long
()
it
.
substring
(
it
.
length
-
7
).
to
UInt
()
}
}
left
=
left
.
toString
().
substring
(
0
until
3
).
to
Long
()
left
=
left
.
toString
().
substring
(
0
until
3
).
to
UInt
()
((
left
-
389
).
toString
()
+
right
.
toString
()).
toLong
()
((
left
-
389
u
).
toString
()
+
right
.
toString
()).
toUInt
()
}
}
in
3800
..
3989
->
{
in
3800
..
3989
->
{
val
right
:
Long
=
id
.
toString
().
let
{
val
right
:
UInt
=
id
.
toString
().
let
{
it
.
substring
(
it
.
length
-
7
).
to
Long
()
it
.
substring
(
it
.
length
-
7
).
to
UInt
()
}
}
left
=
left
.
toString
().
substring
(
0
until
3
).
to
Long
()
left
=
left
.
toString
().
substring
(
0
until
3
).
to
UInt
()
((
left
-
349
).
toString
()
+
right
.
toString
()).
toLong
()
((
left
-
349
u
).
toString
()
+
right
.
toString
()).
toUInt
()
}
}
else
->
id
else
->
id
}
}
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/contact/QQ.kt
View file @
fdf50e4d
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
)
package
net.mamoe.mirai.contact
package
net.mamoe.mirai.contact
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.Bot
...
@@ -14,7 +16,7 @@ import net.mamoe.mirai.message.MessageChain
...
@@ -14,7 +16,7 @@ import net.mamoe.mirai.message.MessageChain
*
*
* @author Him188moe
* @author Him188moe
*/
*/
expect
class
QQ
(
bot
:
Bot
,
number
:
Long
)
:
Contact
{
expect
class
QQ
(
bot
:
Bot
,
number
:
UInt
)
:
Contact
{
override
suspend
fun
sendMessage
(
message
:
MessageChain
)
override
suspend
fun
sendMessage
(
message
:
MessageChain
)
override
suspend
fun
sendXMLMessage
(
message
:
String
)
override
suspend
fun
sendXMLMessage
(
message
:
String
)
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/Message.kt
View file @
fdf50e4d
@
file
:
Suppress
(
"MemberVisibilityCanBePrivate"
,
"unused"
)
@
file
:
Suppress
(
"MemberVisibilityCanBePrivate"
,
"unused"
,
"EXPERIMENTAL_API_USAGE"
)
package
net.mamoe.mirai.message
package
net.mamoe.mirai.message
...
@@ -87,21 +87,24 @@ data class PlainText(override val stringValue: String) : Message() {
...
@@ -87,21 +87,24 @@ data class PlainText(override val stringValue: String) : Message() {
// ==================================== Image ====================================
// ==================================== Image ====================================
/**
/**
* 图片消息.
* 图片消息.
在发送时将会区分群图片和好友图片发送.
* 由接收消息时构建, 可直接发送
* 由接收消息时构建, 可直接发送
*
*
* @param id 类似 `{7AA4B3AA-8C3C-0F45-2D9B-7F302A0ACEAA}.jpg`. 群的是大写id, 好友的是小写id
* @param id 类似 `/01ee6426-5ff1-4cf0-8278-e8634d2909ef`. 群的是大写id, 好友的是小写id
* @param filename 文件名. 这将决定图片的显示
*/
*/
data class
Image
(
val
id
:
String
)
:
Message
()
{
data class
Image
(
val
id
:
ImageId
,
val
filename
:
String
=
""
)
:
Message
()
{
override
val
stringValue
:
String
=
"[$
id
]"
override
val
stringValue
:
String
=
"[$
{id.value}
]"
}
}
inline
class
ImageId
(
val
value
:
String
)
// ==================================== At ====================================
// ==================================== At ====================================
/**
/**
* At 一个人
* At 一个人
*/
*/
data class
At
(
val
targetQQ
:
Long
)
:
Message
()
{
data class
At
(
val
targetQQ
:
UInt
)
:
Message
()
{
constructor
(
target
:
QQ
)
:
this
(
target
.
number
)
constructor
(
target
:
QQ
)
:
this
(
target
.
number
)
override
val
stringValue
:
String
=
"[@$targetQQ]"
override
val
stringValue
:
String
=
"[@$targetQQ]"
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/MessageType.kt
View file @
fdf50e4d
...
@@ -8,7 +8,8 @@ enum class MessageType(val value: UByte) {
...
@@ -8,7 +8,8 @@ enum class MessageType(val value: UByte) {
PLAIN_TEXT
(
0
x01u
),
PLAIN_TEXT
(
0
x01u
),
AT
(
0
x06u
),
AT
(
0
x06u
),
FACE
(
0
x02u
),
FACE
(
0
x02u
),
IMAGE
(
0
x03u
),
//may be 0x06?
GROUP_IMAGE
(
0
x03u
),
FRIEND_IMAGE
(
0
x06u
),
;
;
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/internal/MessageDataInternal.kt
View file @
fdf50e4d
...
@@ -37,8 +37,8 @@ internal fun IoBuffer.parseMessageImage0x06(): Image {
...
@@ -37,8 +37,8 @@ internal fun IoBuffer.parseMessageImage0x06(): Image {
val
suffix
=
readString
(
filenameLength
).
substringAfter
(
"."
)
val
suffix
=
readString
(
filenameLength
).
substringAfter
(
"."
)
discardExact
(
8
)
//03 00 04 00 00 02 9C 04
discardExact
(
8
)
//03 00 04 00 00 02 9C 04
val
length
=
readShort
()
//=27
val
length
=
readShort
()
//=27
discardExact
(
1
)
//无意义符号?
return
Image
(
ImageId
(
readString
(
length
)),
""
)
//todo 文件名解析
return
Image
(
"{${readString(length - 2/*去掉首尾各一个无意义符号*/
)}}.$suffix"
)
//return Image("{${readString(length
)}}.$suffix")
}
}
...
@@ -56,8 +56,8 @@ fun main() {
...
@@ -56,8 +56,8 @@ fun main() {
}
}
internal
fun
IoBuffer
.
parseMessageImage0x03
():
Image
{
internal
fun
IoBuffer
.
parseMessageImage0x03
():
Image
{
discardExact
(
1
)
discardExact
(
1
)
//TODO 这里的文件名解析
return
Image
(
String
(
readLVByteArray
())
)
return
Image
(
ImageId
(
String
(
readLVByteArray
())),
""
)
}
}
internal
fun
ByteReadPacket
.
readMessage
():
Message
?
{
internal
fun
ByteReadPacket
.
readMessage
():
Message
?
{
...
@@ -67,7 +67,7 @@ internal fun ByteReadPacket.readMessage(): Message? {
...
@@ -67,7 +67,7 @@ internal fun ByteReadPacket.readMessage(): Message? {
return
try
{
return
try
{
when
(
messageType
)
{
when
(
messageType
)
{
//todo 在每个parse里面都 discard 了第一byte.
//todo 在每个parse里面都 discard 了第一
byte.
0
x01
->
sectionData
.
parsePlainText
()
0
x01
->
sectionData
.
parsePlainText
()
0
x02
->
sectionData
.
parseMessageFace
()
0
x02
->
sectionData
.
parseMessageFace
()
0
x03
->
sectionData
.
parseMessageImage0x03
()
0
x03
->
sectionData
.
parseMessageImage0x03
()
...
@@ -128,14 +128,14 @@ fun ByteReadPacket.readMessageChain(): MessageChain {
...
@@ -128,14 +128,14 @@ fun ByteReadPacket.readMessageChain(): MessageChain {
return
chain
return
chain
}
}
fun
MessageChain
.
toPacket
():
ByteReadPacket
=
buildPacket
{
fun
MessageChain
.
toPacket
(
forGroup
:
Boolean
):
ByteReadPacket
=
buildPacket
{
this
@
toPacket
.
forEach
{
message
->
this
@
toPacket
.
forEach
{
message
->
writePacket
(
with
(
message
)
{
writePacket
(
with
(
message
)
{
when
(
this
)
{
when
(
this
)
{
is
Face
->
buildPacket
{
is
Face
->
buildPacket
{
writeUByte
(
MessageType
.
FACE
.
value
)
writeUByte
(
MessageType
.
FACE
.
value
)
writeLVPacket
{
write
Short
LVPacket
{
writeShort
(
1
)
writeShort
(
1
)
writeUByte
(
id
.
id
)
writeUByte
(
id
.
id
)
...
@@ -150,11 +150,18 @@ fun MessageChain.toPacket(): ByteReadPacket = buildPacket {
...
@@ -150,11 +150,18 @@ fun MessageChain.toPacket(): ByteReadPacket = buildPacket {
is
At
->
throw
UnsupportedOperationException
(
"At is not supported now but is expecting to be supported"
)
is
At
->
throw
UnsupportedOperationException
(
"At is not supported now but is expecting to be supported"
)
is
Image
->
buildPacket
{
is
Image
->
buildPacket
{
writeUByte
(
MessageType
.
IMAGE
.
value
)
if
(
forGroup
)
{
writeUByte
(
MessageType
.
GROUP_IMAGE
.
value
)
/*
* 00 00 06 00 F3 02 00 1B 28 52 49 5F 36 31 28 32 52 59 4B 59 43 40 37 59 29 58 29 39 29 42 49 2E 67 69 66 03 00 04 00 00 11 90 04 00 25 2F 35 37 34 63 34 32 34 30 2D 30 31 33 66 2D 34 35 39 38 2D 61 37 32 34 2D 30 36 65 66 35 36 39 39 30 64 30 62 14 00 04 03 00 00 00 0B 00 00 18 00 25 2F 35 37 34 63 34 32 34 30 2D 30 31 33 66 2D 34 35 39 38 2D 61 37 32 34 2D 30 36 65 66 35 36 39 39 30 64 30 62 19 00 04 00 00 00 2D 1A 00 04 00 00 00 2D FF 00 63 16 20 20 39 39 31 30 20 38 38 31 44 42 20 20 20 20 20 20 34 34 39 36 65 33 39 46 37 36 35 33 32 45 31 41 42 35 43 41 37 38 36 44 37 41 35 31 33 38 39 32 32 35 33 38 35 2E 67 69 66 66 2F 35 37 34 63 34 32 34 30 2D 30 31 33 66 2D 34 35 39 38 2D 61 37 32 34 2D 30 36 65 66 35 36 39 39 30 64 30 62 41
* 00 00 06 00 F3 02 00 1B 46 52 25 46 60 30 59 4F 4A 5A 51 48 31 46 4A 53 4C 51 4C 4A 33 46 31 2E 6A 70 67 03 00 04 00 00 02 A2 04 00 25 2F 37 33 38 33 35 38 36 37 2D 38 64 65 31 2D 34 65 30 66 2D 61 33 36 35 2D 34 39 62 30 33 39 63 34 61 39 31 66 14 00 04 03 00 00 00 0B 00 00 18 00 25 2F 37 33 38 33 35 38 36 37 2D 38 64 65 31 2D 34 65 30 66 2D 61 33 36 35 2D 34 39 62 30 33 39 63 34 61 39 31 66 19 00 04 00 00 00 4E 1A 00 04 00 00 00 23 FF 00 63 16 20 20 39 39 31 30 20 38 38 31 43 42 20 20 20 20 20 20 20 36 37 34 65 31 46 42 34 43 32 35 45 42 34 46 45 31 32 45 34 46 33 42 42 38 31 39 31 33 37 42 44 39 39 30 39 2E 6A 70 67 66 2F 37 33 38 33 35 38 36 37 2D 38 64 65 31 2D 34 65 30 66 2D 61 33 36 35 2D 34 39 62 30 33 39 63 34 61 39 31 66 41
*/
writeLVPacket
{
writeShortLVPacket
{
//todo
writeByte
(
0
x02
)
writeByte
(
0
x02
)
writeLVString
(
id
)
writeShortLVString
(
id
.
value
.
substring
(
1
..
35
)
)
writeHex
(
"04 00 "
+
writeHex
(
"04 00 "
+
"04 9B 53 B0 08 "
+
"04 9B 53 B0 08 "
+
"05 00 "
+
"05 00 "
+
...
@@ -164,17 +171,67 @@ fun MessageChain.toPacket(): ByteReadPacket = buildPacket {
...
@@ -164,17 +171,67 @@ fun MessageChain.toPacket(): ByteReadPacket = buildPacket {
"07 00 "
+
"07 00 "
+
"01 43 08 00 00 09 00 01 01 0B 00 00 14 00 04 11 00 00 00 15 00 04 00 00 02 BC 16 00 04 00 00 02 BC 18 00 04 00 00 7D 5E FF 00 5C 15 36 20 39 32 6B 41 31 43 39 62 35 33 62 30 30 38 64 39 38 61 35 61 37 30 20"
)
"01 43 08 00 00 09 00 01 01 0B 00 00 14 00 04 11 00 00 00 15 00 04 00 00 02 BC 16 00 04 00 00 02 BC 18 00 04 00 00 7D 5E FF 00 5C 15 36 20 39 32 6B 41 31 43 39 62 35 33 62 30 30 38 64 39 38 61 35 61 37 30 20"
)
writeHex
(
"20 20 20 20 20 35 30 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20"
)
writeHex
(
"20 20 20 20 20 35 30 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20"
)
writeStringUtf8
(
id
)
writeStringUtf8
(
id
.
value
)
writeByte
(
0
x41
)
writeByte
(
0
x41
)
}
}
}
else
{
writeUByte
(
MessageType
.
FRIEND_IMAGE
.
value
)
// 00 00 06 00 F3 02
// 00 1B 24 5B 56 54 4A 38 60 4C 5A 4E 46 7D 53 39 4F 52 36 25 45 60 42 55 53 2E 6A 70 67
// 03 00 04 00 01 41 1B 04
// 00 25 2F 65 61 37 30 30 61 38 33 2D 38 38 38 62 2D 34 66 37 31 2D 61 62 64 31 2D 63 33 38 64 63 62 64 31 61 65 36 31
// 14 00 04 00 00 00 00 0B 00 00 18
// 00 25 2F 65 61 37 30 30 61 38 33 2D 38 38 38 62 2D 34 66 37 31 2D 61 62 64 31 2D 63 33 38 64 63 62 64 31 61 65 36 31
// 19 00 04 00 00 03 74 1A 00 04 00 00 02 BE FF 00 63 16 20 20 39 39 31 30 20 38 38 31 43 42 20 20 20 20 20
///38 32 32 30 33 65 39 36 30 46 42 35 44 37 46 42 33 39 46 34 39 39 31 37 46 34 37 33 44 41 45 31 37 30 32 46 44 31 2E 6A 70 67 66
// 2F 65 61 37 30 30 61 38 33 2D 38 38 38 62 2D 34 66 37 31 2D 61 62 64 31 2D 63 33 38 64 63 62 64 31 61 65 36 31 41
// 00 00 06 00 F3 02
// 00 1B 7B 48 29 47 52 53 31 29 50 24 5A 42 28 4F 35 43 44 4B 45 31 35 7B 37 2E 70 6E 67
// 03 00 04 00 00 6F 36 04
// 00 25 2F 35 65 63 32 34 63 37 62 2D 34 30 32 39 2D 34 61 39 33 2D 62 63 66 35 2D 34 31 38 34 35 32 65 39 32 33 31 64
// 14 00 04 00 00 00 00 0B 00 00 18
// 00 25 2F 35 65 63 32 34 63 37 62 2D 34 30 32 39 2D 34 61 39 33 2D 62 63 66 35 2D 34 31 38 34 35 32 65 39 32 33 31 64
// 19 00 04 00 00 04 14 1A 00 04 00 00 02 77 FF 00 63 16 20 20 39 39 31 30 20 38 38 31 41 42 20 20 20 20 20
///32 38 34 37 30 65 35 42 37 44 45 37 36 41 34 41 44 44 31 37 43 46 39 32 39 38 33 43 46 30 41 43 45 35 42 34 33 39 2E 70 6E 67 66
// 2F 35 65 63 32 34 63 37 62 2D 34 30 32 39 2D 34 61 39 33 2D 62 63 66 35 2D 34 31 38 34 35 32 65 39 32 33 31 64 41
/*
* 00 00 06 00 F3 02
* 00 1B 46 52 25 46 60 30 59 4F 4A 5A 51 48 31 46 4A 53 4C 51 4C 4A 33 46 31 2E 6A 70 67
* 03 00 04 00 00 02 A2 04
* 00 25 2F 37 33 38 33 35 38 36 37 2D 38 64 65 31 2D 34 65 30 66 2D 61 33 36 35 2D 34 39 62 30 33 39 63 34 61 39 31 66
* 14 00 04 03 00 00 00 0B 00 00 18
* 00 25 2F 37 33 38 33 35 38 36 37 2D 38 64 65 31 2D 34 65 30 66 2D 61 33 36 35 2D 34 39 62 30 33 39 63 34 61 39 31 66
* 19 00 04 00 00 00 4E 1A 00 04 00 00 00 23 FF 00 63 16 20 20 39 39 31 30 20 38 38 31 43 42 20 20 20 20 20 20 20
**36 37 34 65 31 46 42 34 43 32 35 45 42 34 46 45 31 32 45 34 46 33 42 42 38 31 39 31 33 37 42 44 39 39 30 39 2E 6A 70 67 66
* 2F 37 33 38 33 35 38 36 37 2D 38 64 65 31 2D 34 65 30 66 2D 61 33 36 35 2D 34 39 62 30 33 39 63 34 61 39 31 66 41
*/
writeShortLVPacket
{
//todo
writeByte
(
0
x02
)
//"46 52 25 46 60 30 59 4F 4A 5A 51 48 31 46 4A 53 4C 51 4C 4A 33 46 31 2E 6A 70 67".hexToBytes().stringOfWitch()
// writeShortLVString(filename)//图片文件名 FR%F`0YOJZQH1FJSLQLJ3F1.jpg
writeShortLVString
(
getRandomString
(
24
,
'A'
..
'Z'
)
+
".jpg"
)
//图片文件名 FR%F`0YOJZQH1FJSLQLJ3F1.jpg
writeHex
(
"03 00 04 00 00 02 A2 04"
)
writeShortLVString
(
id
.
value
)
writeHex
(
"14 00 04 03 00 00 00 0B 00 00 18"
)
writeShortLVString
(
id
.
value
)
writeHex
(
"19 00 04 00 00 00 4E 1A 00 04 00 00 00 23 FF 00 63 16 20 20 39 39 31 30 20 38 38 31 43 42 20 20 20 20 20 20 20 "
+
"36 37 34 65 31 46 42 34 43 32 35 45 42 34 46 45 31 32 45 34 46 33 42 42 38 31 39 31 33 37 42 44 39 39 30 39 2E 6A 70 67 66 "
)
//36 37 34 65 31 46 42 34 43 32 35 45 42 34 46 45 31 32 45 34 46 33 42 42 38 31 39 31 33 37 42 44 39 39 30 39 2E 6A 70 67 66
writeStringUtf8
(
id
.
value
)
writeUByte
(
0
x41u
)
}
}
}
}
is
PlainText
->
buildPacket
{
is
PlainText
->
buildPacket
{
writeUByte
(
MessageType
.
PLAIN_TEXT
.
value
)
writeUByte
(
MessageType
.
PLAIN_TEXT
.
value
)
writeLVPacket
{
write
Short
LVPacket
{
writeByte
(
0
x01
)
writeByte
(
0
x01
)
writeLVString
(
stringValue
)
write
Short
LVString
(
stringValue
)
}
}
}
}
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/BotNetworkHandler.kt
View file @
fdf50e4d
...
@@ -70,7 +70,7 @@ interface BotNetworkHandler<Socket : DataPacketSocketAdapter> {
...
@@ -70,7 +70,7 @@ interface BotNetworkHandler<Socket : DataPacketSocketAdapter> {
* @see [BotSession.sendAndExpect] 发送并期待一个包
* @see [BotSession.sendAndExpect] 发送并期待一个包
* @see [TemporaryPacketHandler] 临时包处理器
* @see [TemporaryPacketHandler] 临时包处理器
*/
*/
suspend
fun
addHandler
(
temporaryPacketHandler
:
TemporaryPacketHandler
<
*
>)
suspend
fun
addHandler
(
temporaryPacketHandler
:
TemporaryPacketHandler
<
*
,
*
>)
/**
/**
* 发送数据包
* 发送数据包
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/BotSession.kt
View file @
fdf50e4d
@
file
:
Suppress
(
"MemberVisibilityCanBePrivate"
,
"unused"
)
@
file
:
Suppress
(
"MemberVisibilityCanBePrivate"
,
"unused"
,
"EXPERIMENTAL_API_USAGE"
)
package
net.mamoe.mirai.network
package
net.mamoe.mirai.network
import
kotlinx.coroutines.Completable
Job
import
kotlinx.coroutines.Completable
Deferred
import
kotlinx.coroutines.CoroutineScope
import
kotlinx.coroutines.CoroutineScope
import
kotlinx.coroutines.Job
import
kotlinx.coroutines.Job
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.Bot
...
@@ -65,10 +65,10 @@ class BotSession(
...
@@ -65,10 +65,10 @@ class BotSession(
* @param handlerTemporary 处理器.
* @param handlerTemporary 处理器.
*/
*/
//@JvmSynthetic
//@JvmSynthetic
suspend
inline
fun
<
reified
P
:
ServerPacket
>
sendAndExpect
(
handlerTemporary
:
TemporaryPacketHandler
<
P
>.()
->
Unit
):
CompletableJob
{
suspend
inline
fun
<
reified
P
:
ServerPacket
,
R
>
sendAndExpect
(
handlerTemporary
:
TemporaryPacketHandler
<
P
,
R
>.()
->
Unit
):
CompletableDeferred
<
R
>
{
val
job
=
coroutineContext
[
Job
].
takeIf
{
it
!=
null
}
?.
let
{
Job
(
it
)
}
?:
Job
()
val
deferred
:
CompletableDeferred
<
R
>
=
coroutineContext
[
Job
].
takeIf
{
it
!=
null
}
?.
let
{
CompletableDeferred
<
R
>(
it
)
}
?:
CompletableDeferred
()
this
.
bot
.
network
.
addHandler
(
TemporaryPacketHandler
(
P
::
class
,
job
,
this
).
also
(
handlerTemporary
))
this
.
bot
.
network
.
addHandler
(
TemporaryPacketHandler
(
P
::
class
,
deferred
,
this
).
also
(
handlerTemporary
))
return
job
return
deferred
}
}
/**
/**
...
@@ -86,13 +86,13 @@ class BotSession(
...
@@ -86,13 +86,13 @@ class BotSession(
* @param P 期待的包
* @param P 期待的包
* @param handler 处理期待的包
* @param handler 处理期待的包
*/
*/
suspend
inline
fun
<
reified
P
:
ServerPacket
>
ClientPacket
.
sendAndExpect
(
noinline
handler
:
suspend
(
P
)
->
Unit
):
CompletableJob
{
suspend
inline
fun
<
reified
P
:
ServerPacket
,
R
>
ClientPacket
.
sendAndExpect
(
noinline
handler
:
suspend
(
P
)
->
R
):
CompletableDeferred
<
R
>
{
val
job
=
coroutineContext
[
Job
].
takeIf
{
it
!=
null
}
?.
let
{
Job
(
it
)
}
?:
Job
()
val
deferred
:
CompletableDeferred
<
R
>
=
coroutineContext
[
Job
].
takeIf
{
it
!=
null
}
?.
let
{
CompletableDeferred
<
R
>(
it
)
}
?:
CompletableDeferred
()
bot
.
network
.
addHandler
(
TemporaryPacketHandler
(
P
::
class
,
job
,
this
@BotSession
).
also
{
bot
.
network
.
addHandler
(
TemporaryPacketHandler
(
P
::
class
,
deferred
,
this
@BotSession
).
also
{
it
.
toSend
(
this
)
it
.
toSend
(
this
)
it
.
onExpect
(
handler
)
it
.
onExpect
(
handler
)
})
})
return
job
return
deferred
}
}
suspend
inline
fun
ClientPacket
.
send
()
=
socket
.
sendPacket
(
this
)
suspend
inline
fun
ClientPacket
.
send
()
=
socket
.
sendPacket
(
this
)
...
@@ -101,6 +101,6 @@ class BotSession(
...
@@ -101,6 +101,6 @@ class BotSession(
suspend
fun
BotSession
.
distributePacket
(
packet
:
ServerPacket
)
=
this
.
socket
.
distributePacket
(
packet
)
suspend
fun
BotSession
.
distributePacket
(
packet
:
ServerPacket
)
=
this
.
socket
.
distributePacket
(
packet
)
val
BotSession
.
isOpen
:
Boolean
get
()
=
socket
.
isOpen
val
BotSession
.
isOpen
:
Boolean
get
()
=
socket
.
isOpen
val
BotSession
.
account
:
Long
get
()
=
bot
.
account
.
account
val
BotSession
.
account
:
UInt
get
()
=
bot
.
account
.
account
val
<
T
:
BotNetworkHandler
<
*
>>
T
.
session
get
()
=
this
[
ActionPacketHandler
].
session
val
<
T
:
BotNetworkHandler
<
*
>>
T
.
session
get
()
=
this
[
ActionPacketHandler
].
session
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/TIMBotNetworkHandler.kt
View file @
fdf50e4d
...
@@ -33,13 +33,13 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
...
@@ -33,13 +33,13 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
override
lateinit
var
socket
:
BotSocketAdapter
override
lateinit
var
socket
:
BotSocketAdapter
private
set
private
set
internal
val
temporaryPacketHandlers
=
mutableListOf
<
TemporaryPacketHandler
<
*
>>()
internal
val
temporaryPacketHandlers
=
mutableListOf
<
TemporaryPacketHandler
<
*
,
*
>>()
private
val
handlersLock
=
Mutex
()
private
val
handlersLock
=
Mutex
()
private
var
heartbeatJob
:
Job
?
=
null
private
var
heartbeatJob
:
Job
?
=
null
override
suspend
fun
addHandler
(
temporaryPacketHandler
:
TemporaryPacketHandler
<
*
>)
{
override
suspend
fun
addHandler
(
temporaryPacketHandler
:
TemporaryPacketHandler
<
*
,
*
>)
{
handlersLock
.
withLock
{
handlersLock
.
withLock
{
temporaryPacketHandlers
.
add
(
temporaryPacketHandler
)
temporaryPacketHandlers
.
add
(
temporaryPacketHandler
)
}
}
...
@@ -408,7 +408,7 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
...
@@ -408,7 +408,7 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
class
HeartbeatTimeoutException
:
CancellationException
(
"heartbeat timeout"
)
class
HeartbeatTimeoutException
:
CancellationException
(
"heartbeat timeout"
)
if
(
withTimeoutOrNull
(
configuration
.
heartbeatTimeout
.
millisecondsLong
)
{
if
(
withTimeoutOrNull
(
configuration
.
heartbeatTimeout
.
millisecondsLong
)
{
ClientHeartbeatPacket
(
bot
.
qqAccount
,
sessionKey
).
sendAndExpect
<
ServerHeartbeatResponsePacket
>
{}
ClientHeartbeatPacket
(
bot
.
qqAccount
,
sessionKey
).
sendAndExpect
<
ServerHeartbeatResponsePacket
,
Unit
>
{}
}
==
null
)
{
}
==
null
)
{
bot
.
logPurple
(
"Heartbeat timed out"
)
bot
.
logPurple
(
"Heartbeat timed out"
)
bot
.
reinitializeNetworkHandler
(
configuration
,
HeartbeatTimeoutException
())
bot
.
reinitializeNetworkHandler
(
configuration
,
HeartbeatTimeoutException
())
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/handler/ActionPacketHandler.kt
View file @
fdf50e4d
...
@@ -50,7 +50,12 @@ class ActionPacketHandler(session: BotSession) : PacketHandler(session) {
...
@@ -50,7 +50,12 @@ class ActionPacketHandler(session: BotSession) : PacketHandler(session) {
}
}
is
ServerSubmitImageFilenameResponsePacket
->
{
}
is
ServerTryGetImageIDResponsePacket
.
Encrypted
->
session
.
socket
.
distributePacket
(
packet
.
decrypt
(
session
.
sessionKey
))
is
ServerTryGetImageIDResponsePacket
.
Encrypted
->
session
.
socket
.
distributePacket
(
packet
.
decrypt
(
session
.
sessionKey
))
is
ServerSubmitImageFilenameResponsePacket
.
Encrypted
->
session
.
socket
.
distributePacket
(
packet
.
decrypt
(
session
.
sessionKey
))
is
ServerAccountInfoResponsePacket
.
Encrypted
->
session
.
socket
.
distributePacket
(
packet
.
decrypt
(
session
.
sessionKey
))
is
ServerAccountInfoResponsePacket
.
Encrypted
->
session
.
socket
.
distributePacket
(
packet
.
decrypt
(
session
.
sessionKey
))
is
ServerAccountInfoResponsePacket
->
{
is
ServerAccountInfoResponsePacket
->
{
...
@@ -84,7 +89,7 @@ class ActionPacketHandler(session: BotSession) : PacketHandler(session) {
...
@@ -84,7 +89,7 @@ class ActionPacketHandler(session: BotSession) : PacketHandler(session) {
}
}
//@JvmSynthetic
//@JvmSynthetic
suspend
fun
addFriend
(
account
:
Long
,
message
:
Lazy
<
String
>
=
lazyOf
(
""
)):
CompletableDeferred
<
AddFriendResult
>
{
suspend
fun
addFriend
(
account
:
UInt
,
message
:
Lazy
<
String
>
=
lazyOf
(
""
)):
CompletableDeferred
<
AddFriendResult
>
{
val
future
=
CompletableDeferred
<
AddFriendResult
>()
val
future
=
CompletableDeferred
<
AddFriendResult
>()
val
session
=
AddFriendSession
(
account
,
future
,
message
)
val
session
=
AddFriendSession
(
account
,
future
,
message
)
// uploadImageSessions.add(session)
// uploadImageSessions.add(session)
...
@@ -160,7 +165,7 @@ class ActionPacketHandler(session: BotSession) : PacketHandler(session) {
...
@@ -160,7 +165,7 @@ class ActionPacketHandler(session: BotSession) : PacketHandler(session) {
}
}
private
inner
class
AddFriendSession
(
private
inner
class
AddFriendSession
(
private
val
qq
:
Long
,
private
val
qq
:
UInt
,
private
val
future
:
CompletableDeferred
<
AddFriendResult
>,
private
val
future
:
CompletableDeferred
<
AddFriendResult
>,
private
val
message
:
Lazy
<
String
>
private
val
message
:
Lazy
<
String
>
)
{
)
{
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/handler/EventPacketHandler.kt
View file @
fdf50e4d
...
@@ -41,7 +41,7 @@ class EventPacketHandler(session: BotSession) : PacketHandler(session) {
...
@@ -41,7 +41,7 @@ class EventPacketHandler(session: BotSession) : PacketHandler(session) {
}
}
is
ServerGroupMessageEventPacket
->
{
is
ServerGroupMessageEventPacket
->
{
if
(
packet
.
qq
.
toLong
()
==
bot
.
account
.
account
)
return
if
(
packet
.
qq
==
bot
.
account
.
account
)
return
GroupMessageEvent
(
GroupMessageEvent
(
bot
,
bot
,
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/handler/TemporaryPacketHandler.kt
View file @
fdf50e4d
package
net.mamoe.mirai.network.protocol.tim.handler
package
net.mamoe.mirai.network.protocol.tim.handler
import
kotlinx.coroutines.Completable
Job
import
kotlinx.coroutines.Completable
Deferred
import
net.mamoe.mirai.network.BotSession
import
net.mamoe.mirai.network.BotSession
import
net.mamoe.mirai.network.protocol.tim.packet.ClientPacket
import
net.mamoe.mirai.network.protocol.tim.packet.ClientPacket
import
net.mamoe.mirai.network.protocol.tim.packet.ServerPacket
import
net.mamoe.mirai.network.protocol.tim.packet.ServerPacket
...
@@ -19,14 +19,14 @@ import kotlin.reflect.KClass
...
@@ -19,14 +19,14 @@ import kotlin.reflect.KClass
*
*
* @see BotSession.sendAndExpect
* @see BotSession.sendAndExpect
*/
*/
class
TemporaryPacketHandler
<
P
:
ServerPacket
>(
class
TemporaryPacketHandler
<
P
:
ServerPacket
,
R
>(
private
val
expectationClass
:
KClass
<
P
>,
private
val
expectationClass
:
KClass
<
P
>,
private
val
job
:
CompletableJob
,
private
val
deferred
:
CompletableDeferred
<
R
>
,
private
val
fromSession
:
BotSession
private
val
fromSession
:
BotSession
)
{
)
{
private
lateinit
var
toSend
:
ClientPacket
private
lateinit
var
toSend
:
ClientPacket
private
lateinit
var
expect
:
suspend
(
P
)
->
Unit
private
lateinit
var
expect
:
suspend
(
P
)
->
R
lateinit
var
session
:
BotSession
//无需覆盖
lateinit
var
session
:
BotSession
//无需覆盖
...
@@ -40,7 +40,7 @@ class TemporaryPacketHandler<P : ServerPacket>(
...
@@ -40,7 +40,7 @@ class TemporaryPacketHandler<P : ServerPacket>(
}
}
fun
onExpect
(
handler
:
suspend
(
P
)
->
Unit
)
{
fun
onExpect
(
handler
:
suspend
(
P
)
->
R
)
{
this
.
expect
=
handler
this
.
expect
=
handler
}
}
...
@@ -51,10 +51,15 @@ class TemporaryPacketHandler<P : ServerPacket>(
...
@@ -51,10 +51,15 @@ class TemporaryPacketHandler<P : ServerPacket>(
suspend
fun
shouldRemove
(
session
:
BotSession
,
packet
:
ServerPacket
):
Boolean
{
suspend
fun
shouldRemove
(
session
:
BotSession
,
packet
:
ServerPacket
):
Boolean
{
if
(
expectationClass
.
isInstance
(
packet
)
&&
session
===
this
.
fromSession
)
{
if
(
expectationClass
.
isInstance
(
packet
)
&&
session
===
this
.
fromSession
)
{
kotlin
.
runCatching
{
@Suppress
(
"UNCHECKED_CAST"
)
@Suppress
(
"UNCHECKED_CAST"
)
val
ret
=
try
{
expect
(
packet
as
P
)
expect
(
packet
as
P
)
}.
onFailure
{
job
.
completeExceptionally
(
it
)
}.
onSuccess
{
job
.
complete
()
}
}
catch
(
e
:
Exception
)
{
deferred
.
completeExceptionally
(
e
)
return
true
}
deferred
.
complete
(
ret
)
return
true
return
true
}
}
return
false
return
false
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/ClientPacket.kt
View file @
fdf50e4d
...
@@ -58,4 +58,9 @@ abstract class ClientPacket : Packet(), Closeable {
...
@@ -58,4 +58,9 @@ abstract class ClientPacket : Packet(), Closeable {
}
}
}
}
@MustBeDocumented
@Target
(
AnnotationTarget
.
FUNCTION
,
AnnotationTarget
.
CLASS
)
@Retention
(
AnnotationRetention
.
SOURCE
)
annotation
class
PacketVersion
(
val
date
:
String
,
val
timVersion
:
String
)
private
val
UninitializedByteReadPacket
=
ByteReadPacket
(
IoBuffer
.
Empty
,
IoBuffer
.
EmptyPool
)
private
val
UninitializedByteReadPacket
=
ByteReadPacket
(
IoBuffer
.
Empty
,
IoBuffer
.
EmptyPool
)
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/ClientRawPacket.kt
0 → 100644
View file @
fdf50e4d
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
)
package
net.mamoe.mirai.network.protocol.tim.packet
import
kotlinx.io.core.BytePacketBuilder
import
kotlinx.io.core.writeFully
import
net.mamoe.mirai.utils.encryptAndWrite
import
net.mamoe.mirai.utils.writeQQ
class
ClientRawPacket
(
override
val
id
:
UShort
,
private
val
bot
:
UInt
,
private
val
version
:
ByteArray
,
private
val
sessionKey
:
ByteArray
,
private
val
data
:
ByteArray
)
:
ClientPacket
()
{
override
fun
encode
(
builder
:
BytePacketBuilder
)
=
with
(
builder
)
{
writeQQ
(
bot
)
writeFully
(
version
)
encryptAndWrite
(
sessionKey
)
{
writeFully
(
data
)
}
}
}
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/GradeInfo.kt
View file @
fdf50e4d
...
@@ -9,7 +9,6 @@ import net.mamoe.mirai.network.protocol.tim.TIMProtocol
...
@@ -9,7 +9,6 @@ import net.mamoe.mirai.network.protocol.tim.TIMProtocol
import
net.mamoe.mirai.utils.encryptAndWrite
import
net.mamoe.mirai.utils.encryptAndWrite
import
net.mamoe.mirai.utils.writeHex
import
net.mamoe.mirai.utils.writeHex
import
net.mamoe.mirai.utils.writeQQ
import
net.mamoe.mirai.utils.writeQQ
import
net.mamoe.mirai.utils.writeRandom
/**
/**
* 获取升级天数等.
* 获取升级天数等.
...
@@ -18,7 +17,7 @@ import net.mamoe.mirai.utils.writeRandom
...
@@ -18,7 +17,7 @@ import net.mamoe.mirai.utils.writeRandom
*/
*/
@PacketId
(
0
x00_5Cu
)
@PacketId
(
0
x00_5Cu
)
class
ClientAccountInfoRequestPacket
(
class
ClientAccountInfoRequestPacket
(
private
val
qq
:
Long
,
private
val
qq
:
UInt
,
private
val
sessionKey
:
ByteArray
private
val
sessionKey
:
ByteArray
)
:
ClientPacket
()
{
)
:
ClientPacket
()
{
override
fun
encode
(
builder
:
BytePacketBuilder
)
=
with
(
builder
)
{
override
fun
encode
(
builder
:
BytePacketBuilder
)
=
with
(
builder
)
{
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/Heartbeat.kt
View file @
fdf50e4d
...
@@ -11,7 +11,7 @@ import net.mamoe.mirai.utils.writeQQ
...
@@ -11,7 +11,7 @@ import net.mamoe.mirai.utils.writeQQ
@PacketId
(
0
x00_58u
)
@PacketId
(
0
x00_58u
)
class
ClientHeartbeatPacket
(
class
ClientHeartbeatPacket
(
private
val
bot
:
Long
,
private
val
bot
:
UInt
,
private
val
sessionKey
:
ByteArray
private
val
sessionKey
:
ByteArray
)
:
ClientPacket
()
{
)
:
ClientPacket
()
{
override
fun
encode
(
builder
:
BytePacketBuilder
)
=
with
(
builder
)
{
override
fun
encode
(
builder
:
BytePacketBuilder
)
=
with
(
builder
)
{
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/PacketId.kt
View file @
fdf50e4d
...
@@ -4,7 +4,7 @@ package net.mamoe.mirai.network.protocol.tim.packet
...
@@ -4,7 +4,7 @@ package net.mamoe.mirai.network.protocol.tim.packet
@Retention
(
AnnotationRetention
.
RUNTIME
)
@Retention
(
AnnotationRetention
.
RUNTIME
)
@Target
(
AnnotationTarget
.
CLASS
,
AnnotationTarget
.
FILE
)
@Target
(
AnnotationTarget
.
CLASS
)
annotation
class
PacketId
(
annotation
class
PacketId
(
val
value
:
UShort
val
value
:
UShort
)
)
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/ServerPacket.kt
View file @
fdf50e4d
...
@@ -27,6 +27,8 @@ abstract class ServerPacket(val input: ByteReadPacket) : Packet(), Closeable {
...
@@ -27,6 +27,8 @@ abstract class ServerPacket(val input: ByteReadPacket) : Packet(), Closeable {
override
fun
close
()
=
this
.
input
.
close
()
override
fun
close
()
=
this
.
input
.
close
()
override
fun
toString
():
String
=
this
.
packetToString
()
override
fun
toString
():
String
=
this
.
packetToString
()
fun
<
S
:
ServerPacket
>
S
.
applySequence
()
=
this
.
applySequence
(
this
@ServerPacket
.
sequenceId
)
}
}
fun
<
S
:
ServerPacket
>
S
.
applySequence
(
sequenceId
:
UShort
):
S
{
fun
<
S
:
ServerPacket
>
S
.
applySequence
(
sequenceId
:
UShort
):
S
{
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/UploadImage.kt
View file @
fdf50e4d
This diff is collapsed.
Click to expand it.
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/action/AddContact.kt
View file @
fdf50e4d
...
@@ -2,10 +2,15 @@
...
@@ -2,10 +2,15 @@
package
net.mamoe.mirai.network.protocol.tim.packet.action
package
net.mamoe.mirai.network.protocol.tim.packet.action
import
kotlinx.io.core.*
import
kotlinx.io.core.BytePacketBuilder
import
kotlinx.io.core.ByteReadPacket
import
kotlinx.io.core.discardExact
import
kotlinx.io.core.readUShort
import
net.mamoe.mirai.network.protocol.tim.TIMProtocol
import
net.mamoe.mirai.network.protocol.tim.TIMProtocol
import
net.mamoe.mirai.network.protocol.tim.packet.*
import
net.mamoe.mirai.network.protocol.tim.packet.*
import
net.mamoe.mirai.utils.*
import
net.mamoe.mirai.utils.encryptAndWrite
import
net.mamoe.mirai.utils.writeHex
import
net.mamoe.mirai.utils.writeQQ
/**
/**
* 向服务器检查是否可添加某人为好友
* 向服务器检查是否可添加某人为好友
...
@@ -14,8 +19,8 @@ import net.mamoe.mirai.utils.*
...
@@ -14,8 +19,8 @@ import net.mamoe.mirai.utils.*
*/
*/
@PacketId
(
0
x00_A7u
)
@PacketId
(
0
x00_A7u
)
class
ClientCanAddFriendPacket
(
class
ClientCanAddFriendPacket
(
val
bot
:
Long
,
val
bot
:
UInt
,
val
qq
:
Long
,
val
qq
:
UInt
,
val
sessionKey
:
ByteArray
val
sessionKey
:
ByteArray
)
:
ClientPacket
()
{
)
:
ClientPacket
()
{
override
fun
encode
(
builder
:
BytePacketBuilder
)
=
with
(
builder
)
{
override
fun
encode
(
builder
:
BytePacketBuilder
)
=
with
(
builder
)
{
...
@@ -85,8 +90,8 @@ class ServerCanAddFriendResponsePacket(input: ByteReadPacket) : ServerPacket(inp
...
@@ -85,8 +90,8 @@ class ServerCanAddFriendResponsePacket(input: ByteReadPacket) : ServerPacket(inp
*/
*/
@PacketId
(
0
x00_AEu
)
@PacketId
(
0
x00_AEu
)
class
ClientAddFriendPacket
(
class
ClientAddFriendPacket
(
val
bot
:
Long
,
val
bot
:
UInt
,
val
qq
:
Long
,
val
qq
:
UInt
,
val
sessionKey
:
ByteArray
val
sessionKey
:
ByteArray
)
:
ClientPacket
()
{
)
:
ClientPacket
()
{
override
fun
encode
(
builder
:
BytePacketBuilder
)
=
with
(
builder
)
{
override
fun
encode
(
builder
:
BytePacketBuilder
)
=
with
(
builder
)
{
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/action/ClientSendFriendMessagePacket.kt
View file @
fdf50e4d
...
@@ -10,55 +10,82 @@ import net.mamoe.mirai.message.toMessage
...
@@ -10,55 +10,82 @@ import net.mamoe.mirai.message.toMessage
import
net.mamoe.mirai.network.protocol.tim.TIMProtocol
import
net.mamoe.mirai.network.protocol.tim.TIMProtocol
import
net.mamoe.mirai.network.protocol.tim.packet.ClientPacket
import
net.mamoe.mirai.network.protocol.tim.packet.ClientPacket
import
net.mamoe.mirai.network.protocol.tim.packet.PacketId
import
net.mamoe.mirai.network.protocol.tim.packet.PacketId
import
net.mamoe.mirai.network.protocol.tim.packet.PacketVersion
import
net.mamoe.mirai.network.protocol.tim.packet.ServerPacket
import
net.mamoe.mirai.network.protocol.tim.packet.ServerPacket
import
net.mamoe.mirai.utils.*
import
net.mamoe.mirai.utils.*
fun
main
()
{
fun
main
()
{
println
(
"牛逼"
.
toMessage
().
toChain
().
toPacket
().
readBytes
().
toUHexString
())
println
(
"牛逼"
.
toMessage
().
toChain
().
toPacket
(
true
).
readBytes
().
toUHexString
())
}
}
@PacketId
(
0
x00_CDu
)
@PacketId
(
0
x00_CDu
)
class
ClientSendFriendMessagePacket
(
class
ClientSendFriendMessagePacket
(
private
val
botQQ
:
Long
,
private
val
botQQ
:
UInt
,
private
val
targetQQ
:
Long
,
private
val
targetQQ
:
UInt
,
private
val
sessionKey
:
ByteArray
,
private
val
sessionKey
:
ByteArray
,
private
val
message
:
MessageChain
private
val
message
:
MessageChain
)
:
ClientPacket
()
{
)
:
ClientPacket
()
{
@PacketVersion
(
date
=
"2019.10.19"
,
timVersion
=
"2.3.2.21173"
)
override
fun
encode
(
builder
:
BytePacketBuilder
)
=
with
(
builder
)
{
override
fun
encode
(
builder
:
BytePacketBuilder
)
=
with
(
builder
)
{
writeQQ
(
botQQ
)
writeQQ
(
botQQ
)
writeHex
(
TIMProtocol
.
versionNewest
)
writeHex
(
TIMProtocol
.
versionNewest
)
encryptAndWrite
(
sessionKey
)
{
encryptAndWrite
(
sessionKey
)
{
//
TIM最新
//
TIM最新, 消息内容 "牛逼"
//3E 03 3F A2
//
3E 03 3F A2
//76 E4 B8 DD
//
76 E4 B8 DD
//
00 00 00 08
00 01 00 04 00 00 00 00
//
00 00 00 [08]
00 01 00 04 00 00 00 00
//38 03
//
38 03
//3E 03 3F A2
//
3E 03 3F A2
//76 E4 B8 DD
//
76 E4 B8 DD
//C6 FB 06 30 0C 69 0C AD C6 AD 14 BF 0B C6 38 EA
//
C6 FB 06 30 0C 69 0C AD C6 AD 14 BF 0B C6 38 EA
//00 0B
//
00 0B
//3D 7F
//
3D 7F
//5D AA A8 E2
//
5D AA A8 E2
//01 1D
//
01 1D
// 00 00 00 00
// 00 00 00 00
//01
//
01
// 00
// 00
// 00
// 00
//00 01 4D 53 47 00 00 00 00 00
//
00 01 4D 53 47 00 00 00 00 00
//5D AA A8 E2
//
5D AA A8 E2
//E2 AE 94 2D
//
E2 AE 94 2D
//00 00 00 00 0C 00 86
//
00 00 00 00 0C 00 86
//22 00 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91
//
22 00 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91
//00 00
//
00 00
//
//
//01 00 09 01 00 06 E7 89 9B E9 80 BC
// 01 00 09 01 00 06 E7 89 9B E9 80 BC
// TIM最新, 消息内容 "发图片群"
// 3E 03 3F A2
// 76 E4 B8 DD
// 00 00 00 [0D] 00 01 00 04 00 00 00 00 00 03 00 01 01
// 38 03
// 3E 03 3F A2
// 76 E4 B8 DD
// C6 FB 06 30 0C 69 0C AD C6 AD 14 BF 0B C6 38 EA
// 00 0B
// 3D 88
// 5D AA AE 33
// 01 1D
// 00 00 00 00
// 01 00 00
// 00 01 4D 53 47 00 00 00 00 00
// 5D AA AE 33
// 7E 51 1D AA
// 00 00 00 00 0C 00 86
// 22 00 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91
// 00 00
//
// 01 00 0F 01 00 0C E5 8F 91 E5 9B BE E7 89 87 E7 BE A4
writeQQ
(
botQQ
)
writeQQ
(
botQQ
)
writeQQ
(
targetQQ
)
writeQQ
(
targetQQ
)
writeHex
(
"00 00 00 08 00 01 00 04 00 00 00 00"
)
writeHex
(
"00 00 00 08 00 01 00 04 00 00 00 00"
)
writeHex
(
"38 03"
)
//TIM最新: 38 03
writeHex
(
"38 03"
)
writeQQ
(
botQQ
)
writeQQ
(
botQQ
)
writeQQ
(
targetQQ
)
writeQQ
(
targetQQ
)
writeFully
(
md5
(
buildPacket
{
writeQQ
(
targetQQ
);
writeFully
(
sessionKey
)
}.
readBytes
()))
writeFully
(
md5
(
buildPacket
{
writeQQ
(
targetQQ
);
writeFully
(
sessionKey
)
}.
readBytes
()))
...
@@ -81,12 +108,11 @@ class ClientSendFriendMessagePacket(
...
@@ -81,12 +108,11 @@ class ClientSendFriendMessagePacket(
writeHex
(
"00 01 4D 53 47 00 00 00 00 00"
)
writeHex
(
"00 01 4D 53 47 00 00 00 00 00"
)
writeTime
()
writeTime
()
writeRandom
(
4
)
writeRandom
(
4
)
writeHex
(
"00 00 00 00 0C 00 86"
)
//TIM最新 0C 00 86
writeHex
(
"00 00 00 00 0C 00 86"
)
writeHex
(
TIMProtocol
.
messageConstNewest
)
//... 85 E9 BB 91
writeHex
(
TIMProtocol
.
messageConstNewest
)
writeZero
(
2
)
writeZero
(
2
)
message
.
toPacket
().
debugPrint
(
"CHAIN"
)
writePacket
(
message
.
toPacket
(
false
))
writePacket
(
message
.
toPacket
())
/*
/*
//Plain text
//Plain text
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/action/ClientSendGroupMessagePacket.kt
View file @
fdf50e4d
@
file
:
Suppress
(
"EXPERIMENTAL_UNSIGNED_LITERALS"
)
@
file
:
Suppress
(
"EXPERIMENTAL_UNSIGNED_LITERALS"
,
"EXPERIMENTAL_API_USAGE"
)
package
net.mamoe.mirai.network.protocol.tim.packet.action
package
net.mamoe.mirai.network.protocol.tim.packet.action
...
@@ -15,8 +15,8 @@ import net.mamoe.mirai.utils.*
...
@@ -15,8 +15,8 @@ import net.mamoe.mirai.utils.*
@PacketId
(
0
x00_02u
)
@PacketId
(
0
x00_02u
)
class
ClientSendGroupMessagePacket
(
class
ClientSendGroupMessagePacket
(
private
val
botQQ
:
Long
,
private
val
botQQ
:
UInt
,
private
val
groupId
:
Long
,
//不是 number
private
val
groupId
:
UInt
,
//不是 number
private
val
sessionKey
:
ByteArray
,
private
val
sessionKey
:
ByteArray
,
private
val
message
:
MessageChain
private
val
message
:
MessageChain
)
:
ClientPacket
()
{
)
:
ClientPacket
()
{
...
@@ -28,7 +28,7 @@ class ClientSendGroupMessagePacket(
...
@@ -28,7 +28,7 @@ class ClientSendGroupMessagePacket(
writeByte
(
0
x2A
)
writeByte
(
0
x2A
)
writeGroup
(
groupId
)
writeGroup
(
groupId
)
writeLVPacket
{
write
Short
LVPacket
{
writeHex
(
"00 01 01"
)
writeHex
(
"00 01 01"
)
writeHex
(
"00 00 00 00 00 00 00 4D 53 47 00 00 00 00 00"
)
writeHex
(
"00 00 00 00 00 00 00 4D 53 47 00 00 00 00 00"
)
...
@@ -38,7 +38,7 @@ class ClientSendGroupMessagePacket(
...
@@ -38,7 +38,7 @@ class ClientSendGroupMessagePacket(
writeHex
(
TIMProtocol
.
messageConst1
)
writeHex
(
TIMProtocol
.
messageConst1
)
writeZero
(
2
)
writeZero
(
2
)
writePacket
(
message
.
toPacket
())
writePacket
(
message
.
toPacket
(
true
))
}
}
/*it.writeByte(0x01)
/*it.writeByte(0x01)
it.writeShort(bytes.size + 3)
it.writeShort(bytes.size + 3)
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/event/ServerEventPackets.kt
View file @
fdf50e4d
...
@@ -63,7 +63,7 @@ abstract class ServerEventPacket(input: ByteReadPacket, val eventIdentity: Event
...
@@ -63,7 +63,7 @@ abstract class ServerEventPacket(input: ByteReadPacket, val eventIdentity: Event
0
x0052u
->
ServerGroupMessageEventPacket
(
input
,
eventIdentity
)
0
x0052u
->
ServerGroupMessageEventPacket
(
input
,
eventIdentity
)
0
x00A6u
->
ServerFriendMessageEventPacket
(
input
.
debugColorizedPrint
(
"好友消息事件"
,
ignoreUntilFirstConst
=
true
)
,
eventIdentity
)
0
x00A6u
->
ServerFriendMessageEventPacket
(
input
,
eventIdentity
)
//0210: 00 00 00 0E 00 08 00 02 00 01 00 0A 00 04 01 00 00 00 00 00 00 06 00 00 00 26 08 02 1A 02 08 49 0A 08 08 00 10 B2 DE 8C ED 05 0A 0C 08 A2 FF 8C F0 03 10 E4 A1 A7 ED 05 0A 0C 08 DD F1 92 B7 07 10 B1 DE 8C ED 05
//0210: 00 00 00 0E 00 08 00 02 00 01 00 0A 00 04 01 00 00 00 00 00 00 06 00 00 00 26 08 02 1A 02 08 49 0A 08 08 00 10 B2 DE 8C ED 05 0A 0C 08 A2 FF 8C F0 03 10 E4 A1 A7 ED 05 0A 0C 08 DD F1 92 B7 07 10 B1 DE 8C ED 05
// 00 00 00 08 00 0A 00 04 01 00 00 00 00 00 00 16 00 00 00 37 08 02 1A 12 08 95 02 10 90 04 40 98 E1 8C ED 05 48 AF 96 C3 A4 03 08 A2 FF 8C F0 03 10 DD F1 92 B7 07 1A 29 08 00 10 05 18 98 E1 8C ED 05 20 01 28 FF FF FF FF 0F 32 15 E5 AF B9 E6 96 B9 E6 AD A3 E5 9C A8 E8 BE 93 E5 85 A5 2E 2E 2E
// 00 00 00 08 00 0A 00 04 01 00 00 00 00 00 00 16 00 00 00 37 08 02 1A 12 08 95 02 10 90 04 40 98 E1 8C ED 05 48 AF 96 C3 A4 03 08 A2 FF 8C F0 03 10 DD F1 92 B7 07 1A 29 08 00 10 05 18 98 E1 8C ED 05 20 01 28 FF FF FF FF 0F 32 15 E5 AF B9 E6 96 B9 E6 AD A3 E5 9C A8 E8 BE 93 E5 85 A5 2E 2E 2E
...
@@ -101,7 +101,7 @@ abstract class ServerEventPacket(input: ByteReadPacket, val eventIdentity: Event
...
@@ -101,7 +101,7 @@ abstract class ServerEventPacket(input: ByteReadPacket, val eventIdentity: Event
}
}
inner
class
ResponsePacket
(
inner
class
ResponsePacket
(
val
bot
:
Long
,
val
bot
:
UInt
,
val
sessionKey
:
ByteArray
val
sessionKey
:
ByteArray
)
:
ClientPacket
()
{
)
:
ClientPacket
()
{
override
val
id
:
UShort
get
()
=
this
@ServerEventPacket
.
id
override
val
id
:
UShort
get
()
=
this
@ServerEventPacket
.
id
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/login/ClientChangeOnlineStatusPacket.kt
View file @
fdf50e4d
...
@@ -17,7 +17,7 @@ import net.mamoe.mirai.utils.writeQQ
...
@@ -17,7 +17,7 @@ import net.mamoe.mirai.utils.writeQQ
*/
*/
@PacketId
(
0
x00_ECu
)
@PacketId
(
0
x00_ECu
)
class
ClientChangeOnlineStatusPacket
(
class
ClientChangeOnlineStatusPacket
(
private
val
bot
:
Long
,
private
val
bot
:
UInt
,
private
val
sessionKey
:
ByteArray
,
private
val
sessionKey
:
ByteArray
,
private
val
loginStatus
:
OnlineStatus
private
val
loginStatus
:
OnlineStatus
)
:
ClientPacket
()
{
)
:
ClientPacket
()
{
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/login/PasswordSubmission.kt
View file @
fdf50e4d
@
file
:
Suppress
(
"EXPERIMENTAL_UNSIGNED_LITERALS"
)
@
file
:
Suppress
(
"EXPERIMENTAL_UNSIGNED_LITERALS"
,
"EXPERIMENTAL_API_USAGE"
)
package
net.mamoe.mirai.network.protocol.tim.packet.login
package
net.mamoe.mirai.network.protocol.tim.packet.login
...
@@ -16,7 +16,7 @@ import net.mamoe.mirai.utils.*
...
@@ -16,7 +16,7 @@ import net.mamoe.mirai.utils.*
*/
*/
@PacketId
(
0
x08_36u
)
@PacketId
(
0
x08_36u
)
class
ClientPasswordSubmissionPacket
constructor
(
class
ClientPasswordSubmissionPacket
constructor
(
private
val
bot
:
Long
,
private
val
bot
:
UInt
,
private
val
password
:
String
,
private
val
password
:
String
,
private
val
loginTime
:
Int
,
private
val
loginTime
:
Int
,
private
val
loginIP
:
String
,
private
val
loginIP
:
String
,
...
@@ -57,7 +57,7 @@ class ClientPasswordSubmissionPacket constructor(
...
@@ -57,7 +57,7 @@ class ClientPasswordSubmissionPacket constructor(
private
fun
BytePacketBuilder
.
writePart1
(
private
fun
BytePacketBuilder
.
writePart1
(
qq
:
Long
,
qq
:
UInt
,
password
:
String
,
password
:
String
,
loginTime
:
Int
,
loginTime
:
Int
,
loginIP
:
String
,
loginIP
:
String
,
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/login/SKey.kt
View file @
fdf50e4d
@
file
:
Suppress
(
"EXPERIMENTAL_UNSIGNED_LITERALS"
)
@
file
:
Suppress
(
"EXPERIMENTAL_UNSIGNED_LITERALS"
,
"EXPERIMENTAL_API_USAGE"
)
package
net.mamoe.mirai.network.protocol.tim.packet.login
package
net.mamoe.mirai.network.protocol.tim.packet.login
...
@@ -14,7 +14,7 @@ import net.mamoe.mirai.utils.*
...
@@ -14,7 +14,7 @@ import net.mamoe.mirai.utils.*
*/
*/
@PacketId
(
0
x00_1Du
)
@PacketId
(
0
x00_1Du
)
class
ClientSKeyRequestPacket
(
class
ClientSKeyRequestPacket
(
private
val
qq
:
Long
,
private
val
qq
:
UInt
,
private
val
sessionKey
:
ByteArray
private
val
sessionKey
:
ByteArray
)
:
ClientPacket
()
{
)
:
ClientPacket
()
{
override
fun
encode
(
builder
:
BytePacketBuilder
)
=
with
(
builder
)
{
override
fun
encode
(
builder
:
BytePacketBuilder
)
=
with
(
builder
)
{
...
@@ -28,7 +28,7 @@ class ClientSKeyRequestPacket(
...
@@ -28,7 +28,7 @@ class ClientSKeyRequestPacket(
@PacketId
(
0
x00_1Du
)
@PacketId
(
0
x00_1Du
)
class
ClientSKeyRefreshmentRequestPacket
(
class
ClientSKeyRefreshmentRequestPacket
(
private
val
qq
:
Long
,
private
val
qq
:
UInt
,
private
val
sessionKey
:
ByteArray
private
val
sessionKey
:
ByteArray
)
:
ClientPacket
()
{
)
:
ClientPacket
()
{
override
fun
encode
(
builder
:
BytePacketBuilder
)
=
with
(
builder
)
{
override
fun
encode
(
builder
:
BytePacketBuilder
)
=
with
(
builder
)
{
...
@@ -46,7 +46,7 @@ class ServerSKeyResponsePacket(input: ByteReadPacket) : ServerPacket(input) {
...
@@ -46,7 +46,7 @@ class ServerSKeyResponsePacket(input: ByteReadPacket) : ServerPacket(input) {
override
fun
decode
()
=
with
(
input
)
{
override
fun
decode
()
=
with
(
input
)
{
discardExact
(
4
)
discardExact
(
4
)
//debugDiscardExact(2)
//debugDiscardExact(2)
sKey
=
this
.
readString
(
10
)
sKey
=
this
.
readString
(
10
)
//16??
DebugLogger
.
logPurple
(
"SKey=$sKey"
)
DebugLogger
.
logPurple
(
"SKey=$sKey"
)
DebugLogger
.
logPurple
(
"Skey包后面${this.readRemainingBytes().toUHexString()}"
)
DebugLogger
.
logPurple
(
"Skey包后面${this.readRemainingBytes().toUHexString()}"
)
}
}
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/login/Session.kt
View file @
fdf50e4d
@
file
:
Suppress
(
"EXPERIMENTAL_UNSIGNED_LITERALS"
)
@
file
:
Suppress
(
"EXPERIMENTAL_UNSIGNED_LITERALS"
,
"EXPERIMENTAL_API_USAGE"
)
package
net.mamoe.mirai.network.protocol.tim.packet.login
package
net.mamoe.mirai.network.protocol.tim.packet.login
...
@@ -9,7 +9,7 @@ import net.mamoe.mirai.utils.*
...
@@ -9,7 +9,7 @@ import net.mamoe.mirai.utils.*
@PacketId
(
0
x08_28u
)
@PacketId
(
0
x08_28u
)
class
ClientSessionRequestPacket
(
class
ClientSessionRequestPacket
(
private
val
bot
:
Long
,
private
val
bot
:
UInt
,
private
val
serverIp
:
String
,
private
val
serverIp
:
String
,
private
val
token38
:
IoBuffer
,
private
val
token38
:
IoBuffer
,
private
val
token88
:
IoBuffer
,
private
val
token88
:
IoBuffer
,
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/login/Touch.kt
View file @
fdf50e4d
@
file
:
Suppress
(
"EXPERIMENTAL_UNSIGNED_LITERALS"
)
@
file
:
Suppress
(
"EXPERIMENTAL_UNSIGNED_LITERALS"
,
"EXPERIMENTAL_API_USAGE"
)
package
net.mamoe.mirai.network.protocol.tim.packet.login
package
net.mamoe.mirai.network.protocol.tim.packet.login
...
@@ -60,7 +60,7 @@ class ServerTouchResponsePacket(input: ByteReadPacket) : ServerPacket(input) {
...
@@ -60,7 +60,7 @@ class ServerTouchResponsePacket(input: ByteReadPacket) : ServerPacket(input) {
* @author Him188moe
* @author Him188moe
*/
*/
@PacketId
(
0
x08_25u
)
@PacketId
(
0
x08_25u
)
class
ClientTouchPacket
(
private
val
bot
:
Long
,
private
val
serverIp
:
String
)
:
ClientPacket
()
{
class
ClientTouchPacket
(
private
val
bot
:
UInt
,
private
val
serverIp
:
String
)
:
ClientPacket
()
{
override
fun
encode
(
builder
:
BytePacketBuilder
)
=
with
(
builder
)
{
override
fun
encode
(
builder
:
BytePacketBuilder
)
=
with
(
builder
)
{
this
.
writeQQ
(
bot
)
this
.
writeQQ
(
bot
)
this
.
writeHex
(
TIMProtocol
.
fixVer
)
this
.
writeHex
(
TIMProtocol
.
fixVer
)
...
@@ -84,7 +84,7 @@ class ClientTouchPacket(private val bot: Long, private val serverIp: String) : C
...
@@ -84,7 +84,7 @@ class ClientTouchPacket(private val bot: Long, private val serverIp: String) : C
* @author Him188moe
* @author Him188moe
*/
*/
@PacketId
(
0
x08_25u
)
@PacketId
(
0
x08_25u
)
class
ClientTouchRedirectionPacket
(
private
val
serverIP
:
String
,
private
val
qq
:
Long
)
:
ClientPacket
()
{
class
ClientTouchRedirectionPacket
(
private
val
serverIP
:
String
,
private
val
qq
:
UInt
)
:
ClientPacket
()
{
override
fun
encode
(
builder
:
BytePacketBuilder
)
=
with
(
builder
)
{
override
fun
encode
(
builder
:
BytePacketBuilder
)
=
with
(
builder
)
{
this
.
writeQQ
(
qq
)
this
.
writeQQ
(
qq
)
this
.
writeHex
(
TIMProtocol
.
fixVer
)
this
.
writeHex
(
TIMProtocol
.
fixVer
)
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/protocol/tim/packet/login/VerificationCode.kt
View file @
fdf50e4d
...
@@ -12,7 +12,7 @@ import net.mamoe.mirai.utils.*
...
@@ -12,7 +12,7 @@ import net.mamoe.mirai.utils.*
*/
*/
@PacketId
(
0
x00_BAu
)
@PacketId
(
0
x00_BAu
)
class
ClientCaptchaTransmissionRequestPacket
(
class
ClientCaptchaTransmissionRequestPacket
(
private
val
qq
:
Long
,
private
val
qq
:
UInt
,
private
val
token0825
:
ByteArray
,
private
val
token0825
:
ByteArray
,
private
val
verificationSequence
:
Int
,
private
val
verificationSequence
:
Int
,
private
val
token00BA
:
ByteArray
private
val
token00BA
:
ByteArray
...
@@ -44,7 +44,7 @@ class ClientCaptchaTransmissionRequestPacket(
...
@@ -44,7 +44,7 @@ class ClientCaptchaTransmissionRequestPacket(
*/
*/
@PacketId
(
0
x00_BAu
)
@PacketId
(
0
x00_BAu
)
class
ClientCaptchaSubmitPacket
(
class
ClientCaptchaSubmitPacket
(
private
val
qq
:
Long
,
private
val
qq
:
UInt
,
private
val
token0825
:
ByteArray
,
private
val
token0825
:
ByteArray
,
private
val
captcha
:
String
,
private
val
captcha
:
String
,
private
val
verificationToken
:
IoBuffer
private
val
verificationToken
:
IoBuffer
...
@@ -83,7 +83,7 @@ class ClientCaptchaSubmitPacket(
...
@@ -83,7 +83,7 @@ class ClientCaptchaSubmitPacket(
*/
*/
@PacketId
(
0
x00_BAu
)
@PacketId
(
0
x00_BAu
)
class
ClientCaptchaRefreshPacket
(
class
ClientCaptchaRefreshPacket
(
private
val
qq
:
Long
,
private
val
qq
:
UInt
,
private
val
token0825
:
ByteArray
private
val
token0825
:
ByteArray
)
:
ClientPacket
()
{
)
:
ClientPacket
()
{
override
fun
encode
(
builder
:
BytePacketBuilder
)
=
with
(
builder
)
{
override
fun
encode
(
builder
:
BytePacketBuilder
)
=
with
(
builder
)
{
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/BotAccount.kt
View file @
fdf50e4d
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
)
package
net.mamoe.mirai.utils
package
net.mamoe.mirai.utils
data class
BotAccount
(
data class
BotAccount
(
val
account
:
Long
,
//实际上是 UInt
val
account
:
UInt
,
val
password
:
String
//todo 不保存 password?
val
password
:
String
//todo 不保存 password?
)
)
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/ByteReadPacketUtil.kt
View file @
fdf50e4d
...
@@ -80,7 +80,8 @@ fun ByteReadPacket.parseServerPacket(size: Int): ServerPacket {
...
@@ -80,7 +80,8 @@ fun ByteReadPacket.parseServerPacket(size: Int): ServerPacket {
0
x00_CD_u
->
ServerSendFriendMessageResponsePacket
(
this
)
0
x00_CD_u
->
ServerSendFriendMessageResponsePacket
(
this
)
0
x00_02_u
->
ServerSendGroupMessageResponsePacket
(
this
)
0
x00_02_u
->
ServerSendGroupMessageResponsePacket
(
this
)
0
x00_A7_u
->
ServerCanAddFriendResponsePacket
(
this
)
0
x00_A7_u
->
ServerCanAddFriendResponsePacket
(
this
)
0
x03_88_u
->
ServerTryGetImageIDResponsePacket
.
Encrypted
(
this
)
0
x03_52_u
->
ServerTryGetImageIDResponsePacket
.
Encrypted
(
this
)
0
x01_BDu
->
ServerSubmitImageFilenameResponsePacket
.
Encrypted
(
this
)
else
->
UnknownServerPacket
.
Encrypted
(
this
,
id
,
sequenceId
)
else
->
UnknownServerPacket
.
Encrypted
(
this
,
id
,
sequenceId
)
}.
applySequence
(
sequenceId
)
}.
applySequence
(
sequenceId
)
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/ContactList.kt
View file @
fdf50e4d
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
)
package
net.mamoe.mirai.utils
package
net.mamoe.mirai.utils
import
net.mamoe.mirai.contact.Contact
import
net.mamoe.mirai.contact.Contact
class
ContactList
<
C
:
Contact
>
:
MutableMap
<
Long
,
C
>
by
mutableMapOf
()
class
ContactList
<
C
:
Contact
>
:
MutableMap
<
UInt
,
C
>
by
mutableMapOf
()
\ No newline at end of file
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/DebugUtil.kt
View file @
fdf50e4d
package
net.mamoe.mirai.utils
package
net.mamoe.mirai.utils
import
kotlinx.io.core.ByteReadPacket
import
kotlinx.io.core.*
import
kotlinx.io.core.Input
import
kotlinx.io.core.IoBuffer
import
kotlinx.io.core.readBytes
internal
object
DebugLogger
:
MiraiLogger
by
PlatformLogger
(
"Packet Debug"
)
internal
object
DebugLogger
:
MiraiLogger
by
PlatformLogger
(
"Packet Debug"
)
...
@@ -15,7 +12,7 @@ internal fun ByteArray.debugPrint(name: String): ByteArray {
...
@@ -15,7 +12,7 @@ internal fun ByteArray.debugPrint(name: String): ByteArray {
return
this
return
this
}
}
@Deprecated
(
"Low efficiency, only for debug purpose"
,
ReplaceWith
(
""
))
@Deprecated
(
"Low efficiency, only for debug purpose"
,
ReplaceWith
(
"
this
"
))
internal
fun
IoBuffer
.
debugPrint
(
name
:
String
):
IoBuffer
{
internal
fun
IoBuffer
.
debugPrint
(
name
:
String
):
IoBuffer
{
val
readBytes
=
this
.
readBytes
()
val
readBytes
=
this
.
readBytes
()
DebugLogger
.
logPurple
(
name
+
"="
+
readBytes
.
toUHexString
())
DebugLogger
.
logPurple
(
name
+
"="
+
readBytes
.
toUHexString
())
...
@@ -27,20 +24,33 @@ internal fun Input.debugDiscardExact(n: Number, name: String = "") {
...
@@ -27,20 +24,33 @@ internal fun Input.debugDiscardExact(n: Number, name: String = "") {
DebugLogger
.
logPurple
(
"Discarded($n) $name="
+
this
.
readBytes
(
n
.
toInt
()).
toUHexString
())
DebugLogger
.
logPurple
(
"Discarded($n) $name="
+
this
.
readBytes
(
n
.
toInt
()).
toUHexString
())
}
}
@Deprecated
(
"Low efficiency, only for debug purpose"
,
ReplaceWith
(
""
))
@Deprecated
(
"Low efficiency, only for debug purpose"
,
ReplaceWith
(
"
this
"
))
internal
fun
ByteReadPacket
.
debugPrint
(
name
:
String
=
""
):
ByteReadPacket
{
internal
fun
ByteReadPacket
.
debugPrint
(
name
:
String
=
""
):
ByteReadPacket
{
val
bytes
=
this
.
readBytes
()
val
bytes
=
this
.
readBytes
()
DebugLogger
.
logPurple
(
"ByteReadPacket $name="
+
bytes
.
toUHexString
())
DebugLogger
.
logPurple
(
"ByteReadPacket $name="
+
bytes
.
toUHexString
())
return
bytes
.
toReadPacket
()
return
bytes
.
toReadPacket
()
}
}
@Deprecated
(
"Low efficiency, only for debug purpose"
,
ReplaceWith
(
""
))
@Deprecated
(
"Low efficiency, only for debug purpose"
,
ReplaceWith
(
"
this
"
))
internal
fun
ByteReadPacket
.
debugColorizedPrint
(
name
:
String
=
""
,
ignoreUntilFirstConst
:
Boolean
=
false
):
ByteReadPacket
{
internal
fun
ByteReadPacket
.
debugColorizedPrint
(
name
:
String
=
""
,
ignoreUntilFirstConst
:
Boolean
=
false
):
ByteReadPacket
{
val
bytes
=
this
.
readBytes
()
val
bytes
=
this
.
readBytes
()
bytes
.
printColorizedHex
(
name
,
ignoreUntilFirstConst
)
bytes
.
printColorizedHex
(
name
,
ignoreUntilFirstConst
)
return
bytes
.
toReadPacket
()
return
bytes
.
toReadPacket
()
}
}
@Deprecated
(
"Low efficiency, only for debug purpose"
,
ReplaceWith
(
" "
))
internal
fun
BytePacketBuilder
.
debugColorizedPrintThis
(
name
:
String
=
""
)
{
val
data
=
this
.
build
().
readBytes
()
data
.
printColorizedHex
(
name
)
this
.
writeFully
(
data
)
}
@Deprecated
(
"Low efficiency, only for debug purpose"
,
ReplaceWith
(
" "
))
internal
fun
BytePacketBuilder
.
debugPrintThis
(
name
:
String
=
""
)
{
val
data
=
this
.
build
().
readBytes
()
data
.
debugPrint
(
name
)
this
.
writeFully
(
data
)
}
internal
fun
String
.
printStringFromHex
()
{
internal
fun
String
.
printStringFromHex
()
{
println
(
this
.
hexToBytes
().
stringOfWitch
())
println
(
this
.
hexToBytes
().
stringOfWitch
())
...
@@ -55,3 +65,9 @@ internal fun ByteArray.printColorizedHex(name: String = "", ignoreUntilFirstCons
...
@@ -55,3 +65,9 @@ internal fun ByteArray.printColorizedHex(name: String = "", ignoreUntilFirstCons
expect
fun
compareHex
(
hex1s
:
String
,
hex2s
:
String
):
String
expect
fun
compareHex
(
hex1s
:
String
,
hex2s
:
String
):
String
expect
fun
String
.
colorize
(
ignoreUntilFirstConst
:
Boolean
=
false
):
String
expect
fun
String
.
colorize
(
ignoreUntilFirstConst
:
Boolean
=
false
):
String
fun
main
()
{
"00 02 3E 03 3F A2 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 39 00 00 00 0B 00 00 00 2E 51 51 E7 A9 BA E9 97 B4 20 0A 20 20 E6 9C 89 E6 96 B0 E8 AE BF E5 AE A2 20 0A 20 20 E6 9C 89 E6 96 B0 E5 A5 BD E5 8F 8B E5 8A A8 E6 80 81 00 00 01 2C 00 00 00 00"
.
printStringFromHex
()
}
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/PacketBuilderUtil.kt
View file @
fdf50e4d
...
@@ -13,24 +13,34 @@ fun BytePacketBuilder.writeZero(count: Int) = repeat(count) { this.writeByte(0)
...
@@ -13,24 +13,34 @@ fun BytePacketBuilder.writeZero(count: Int) = repeat(count) { this.writeByte(0)
fun
BytePacketBuilder
.
writeRandom
(
length
:
Int
)
=
repeat
(
length
)
{
this
.
writeByte
(
Random
.
Default
.
nextInt
(
255
).
toByte
())
}
fun
BytePacketBuilder
.
writeRandom
(
length
:
Int
)
=
repeat
(
length
)
{
this
.
writeByte
(
Random
.
Default
.
nextInt
(
255
).
toByte
())
}
fun
BytePacketBuilder
.
writeQQ
(
qq
:
Long
)
=
this
.
writeUInt
(
qq
.
toUInt
())
fun
BytePacketBuilder
.
writeQQ
(
qq
:
Long
)
=
this
.
writeUInt
(
qq
.
toUInt
())
fun
BytePacketBuilder
.
writeQQ
(
qq
:
UInt
)
=
this
.
writeUInt
(
qq
)
fun
BytePacketBuilder
.
writeGroup
(
groupIdOrGroupNumber
:
Long
)
=
this
.
writeFully
(
groupIdOrGroupNumber
.
toUInt
().
toByteArray
())
fun
BytePacketBuilder
.
writeGroup
(
groupIdOrGroupNumber
:
Long
)
=
this
.
writeUInt
(
groupIdOrGroupNumber
.
toUInt
())
fun
BytePacketBuilder
.
writeGroup
(
groupIdOrGroupNumber
:
UInt
)
=
this
.
writeUInt
(
groupIdOrGroupNumber
)
fun
BytePacketBuilder
.
writeLVByteArray
(
byteArray
:
ByteArray
)
{
fun
BytePacketBuilder
.
writeLVByteArray
(
byteArray
:
ByteArray
)
{
this
.
writeShort
(
byteArray
.
size
.
toShort
())
this
.
writeShort
(
byteArray
.
size
.
toShort
())
this
.
writeFully
(
byteArray
)
this
.
writeFully
(
byteArray
)
}
}
fun
BytePacketBuilder
.
writeLVPacket
(
packet
:
ByteReadPacket
)
{
fun
BytePacketBuilder
.
write
Short
LVPacket
(
packet
:
ByteReadPacket
)
{
this
.
writeShort
(
packet
.
remaining
.
toShort
())
this
.
writeShort
(
packet
.
remaining
.
toShort
())
this
.
writePacket
(
packet
)
this
.
writePacket
(
packet
)
packet
.
release
()
packet
.
release
()
}
}
fun
BytePacketBuilder
.
writeLVPacket
(
builder
:
BytePacketBuilder
.()
->
Unit
)
=
this
.
writeLVPacket
(
BytePacketBuilder
().
apply
(
builder
).
build
())
fun
BytePacketBuilder
.
writeUVarintLVPacket
(
packet
:
ByteReadPacket
)
{
this
.
writeUVarLong
(
packet
.
remaining
)
this
.
writePacket
(
packet
)
packet
.
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
())
@Suppress
(
"DEPRECATION"
)
@Suppress
(
"DEPRECATION"
)
fun
BytePacketBuilder
.
writeLVString
(
str
:
String
)
=
this
.
writeLVByteArray
(
str
.
toByteArray
())
fun
BytePacketBuilder
.
write
Short
LVString
(
str
:
String
)
=
this
.
writeLVByteArray
(
str
.
toByteArray
())
@Suppress
(
"DEPRECATION"
)
@Suppress
(
"DEPRECATION"
)
fun
BytePacketBuilder
.
writeLVHex
(
hex
:
String
)
=
this
.
writeLVByteArray
(
hex
.
hexToBytes
())
fun
BytePacketBuilder
.
writeLVHex
(
hex
:
String
)
=
this
.
writeLVByteArray
(
hex
.
hexToBytes
())
...
@@ -45,7 +55,7 @@ fun BytePacketBuilder.encryptAndWrite(key: IoBuffer, encoder: BytePacketBuilder.
...
@@ -45,7 +55,7 @@ fun BytePacketBuilder.encryptAndWrite(key: IoBuffer, encoder: BytePacketBuilder.
fun
BytePacketBuilder
.
encryptAndWrite
(
key
:
ByteArray
,
encoder
:
BytePacketBuilder
.()
->
Unit
)
=
writeFully
(
TEA
.
encrypt
(
BytePacketBuilder
().
apply
(
encoder
).
use
{
it
.
build
().
readBytes
()
},
key
))
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
)
fun
BytePacketBuilder
.
encryptAndWrite
(
keyHex
:
String
,
encoder
:
BytePacketBuilder
.()
->
Unit
)
=
encryptAndWrite
(
keyHex
.
hexToBytes
(),
encoder
)
fun
BytePacketBuilder
.
writeTLV0006
(
qq
:
Long
,
password
:
String
,
loginTime
:
Int
,
loginIP
:
String
,
privateKey
:
ByteArray
)
{
fun
BytePacketBuilder
.
writeTLV0006
(
qq
:
UInt
,
password
:
String
,
loginTime
:
Int
,
loginIP
:
String
,
privateKey
:
ByteArray
)
{
val
firstMD5
=
md5
(
password
)
val
firstMD5
=
md5
(
password
)
val
secondMD5
=
md5
(
firstMD5
+
byteArrayOf
(
0
,
0
,
0
,
0
)
+
qq
.
toUInt
().
toByteArray
())
val
secondMD5
=
md5
(
firstMD5
+
byteArrayOf
(
0
,
0
,
0
,
0
)
+
qq
.
toUInt
().
toByteArray
())
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/PlatformUtils.kt
View file @
fdf50e4d
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
)
package
net.mamoe.mirai.utils
package
net.mamoe.mirai.utils
import
com.soywiz.klock.DateTime
import
com.soywiz.klock.DateTime
...
@@ -38,10 +40,14 @@ expect fun localIpAddress(): String
...
@@ -38,10 +40,14 @@ expect fun localIpAddress(): String
/**
/**
* 上传群图片
* 上传群图片
*/
*/
expect
suspend
fun
httpPost
Group
Image
(
expect
suspend
fun
httpPost
Friend
Image
(
uKeyHex
:
String
,
uKeyHex
:
String
,
fileSize
:
Int
,
fileSize
:
Int
,
botNumber
:
Long
,
botNumber
:
UInt
,
groupCode
:
Long
,
qq
:
UInt
,
imageData
:
ByteArray
imageData
:
ByteArray
):
Boolean
):
Boolean
fun
main
()
{
"46 52 25 46 60 30 59 4F 4A 5A 51"
.
printStringFromHex
()
}
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/TEA.kt
View file @
fdf50e4d
...
@@ -23,7 +23,7 @@ fun ByteArray.encryptBy(keyHex: String): ByteArray = TEA.encrypt(checkLength(),
...
@@ -23,7 +23,7 @@ fun ByteArray.encryptBy(keyHex: String): ByteArray = TEA.encrypt(checkLength(),
private
fun
ByteArray
.
checkLength
():
ByteArray
{
private
fun
ByteArray
.
checkLength
():
ByteArray
{
size
.
let
{
size
.
let
{
require
(
it
%
8
==
0
&&
it
>=
16
)
{
"data must len % 8 == 0 && len >= 16 but given
$it
"
}
require
(
it
%
8
==
0
&&
it
>=
16
)
{
"data must len % 8 == 0 && len >= 16 but given
(length=$it) ${this.toUHexString()}
"
}
}
}
return
this
return
this
}
}
\ No newline at end of file
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/TypeConvertion.kt
View file @
fdf50e4d
...
@@ -49,6 +49,7 @@ fun String.hexToUBytes(): UByteArray = HexCache.hexToUBytes(this)
...
@@ -49,6 +49,7 @@ fun String.hexToUBytes(): UByteArray = HexCache.hexToUBytes(this)
fun
String
.
hexToInt
():
Int
=
hexToBytes
().
toUInt
().
toInt
()
fun
String
.
hexToInt
():
Int
=
hexToBytes
().
toUInt
().
toInt
()
fun
getRandomByteArray
(
length
:
Int
):
ByteArray
=
ByteArray
(
length
)
{
Random
.
nextInt
(
0
..
255
).
toByte
()
}
fun
getRandomByteArray
(
length
:
Int
):
ByteArray
=
ByteArray
(
length
)
{
Random
.
nextInt
(
0
..
255
).
toByte
()
}
fun
getRandomString
(
length
:
Int
,
charRange
:
CharRange
):
String
=
String
(
CharArray
(
length
)
{
charRange
.
random
()
})
fun
ByteArray
.
toUInt
():
UInt
=
this
[
0
].
toUInt
().
and
(
255
u
).
shl
(
24
)
+
this
[
1
].
toUInt
().
and
(
255
u
).
shl
(
16
)
+
this
[
2
].
toUInt
().
and
(
255
u
).
shl
(
8
)
+
this
[
3
].
toUInt
().
and
(
255
u
).
shl
(
0
)
fun
ByteArray
.
toUInt
():
UInt
=
this
[
0
].
toUInt
().
and
(
255
u
).
shl
(
24
)
+
this
[
1
].
toUInt
().
and
(
255
u
).
shl
(
16
)
+
this
[
2
].
toUInt
().
and
(
255
u
).
shl
(
8
)
+
this
[
3
].
toUInt
().
and
(
255
u
).
shl
(
0
)
fun
ByteArray
.
toIoBuffer
():
IoBuffer
=
IoBuffer
.
Pool
.
borrow
().
let
{
it
.
writeFully
(
this
);
it
}
fun
ByteArray
.
toIoBuffer
():
IoBuffer
=
IoBuffer
.
Pool
.
borrow
().
let
{
it
.
writeFully
(
this
);
it
}
...
...
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/contact/ContactJvm.kt
View file @
fdf50e4d
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
)
package
net.mamoe.mirai.contact
package
net.mamoe.mirai.contact
import
kotlinx.coroutines.launch
import
kotlinx.coroutines.launch
...
@@ -18,7 +20,7 @@ import net.mamoe.mirai.utils.ContactList
...
@@ -18,7 +20,7 @@ import net.mamoe.mirai.utils.ContactList
* @author Him188moe
* @author Him188moe
*/
*/
@Suppress
(
"unused"
)
@Suppress
(
"unused"
)
actual
sealed
class
Contact
actual
constructor
(
bot
:
Bot
,
number
:
Long
)
:
PlatformContactBase
(
bot
,
number
)
{
actual
sealed
class
Contact
actual
constructor
(
bot
:
Bot
,
number
:
UInt
)
:
PlatformContactBase
(
bot
,
number
)
{
abstract
override
suspend
fun
sendMessage
(
message
:
MessageChain
)
abstract
override
suspend
fun
sendMessage
(
message
:
MessageChain
)
...
@@ -71,7 +73,7 @@ actual sealed class Contact actual constructor(bot: Bot, number: Long) : Platfor
...
@@ -71,7 +73,7 @@ actual sealed class Contact actual constructor(bot: Bot, number: Long) : Platfor
* Java 调用 [groupNumberToId] : `Group.groupNumberToId(number)`
* Java 调用 [groupNumberToId] : `Group.groupNumberToId(number)`
* @author Him188moe
* @author Him188moe
*/
*/
actual
class
Group
actual
constructor
(
bot
:
Bot
,
number
:
Long
)
:
Contact
(
bot
,
number
)
{
actual
class
Group
actual
constructor
(
bot
:
Bot
,
number
:
UInt
)
:
Contact
(
bot
,
number
)
{
actual
val
groupId
=
groupNumberToId
(
number
)
actual
val
groupId
=
groupNumberToId
(
number
)
actual
val
members
:
ContactList
<
QQ
>
actual
val
members
:
ContactList
<
QQ
>
//todo members
//todo members
...
@@ -100,7 +102,7 @@ actual class Group actual constructor(bot: Bot, number: Long) : Contact(bot, num
...
@@ -100,7 +102,7 @@ actual class Group actual constructor(bot: Bot, number: Long) : Contact(bot, num
*
*
* @author Him188moe
* @author Him188moe
*/
*/
actual
class
QQ
actual
constructor
(
bot
:
Bot
,
number
:
Long
)
:
Contact
(
bot
,
number
)
{
actual
class
QQ
actual
constructor
(
bot
:
Bot
,
number
:
UInt
)
:
Contact
(
bot
,
number
)
{
actual
override
suspend
fun
sendMessage
(
message
:
MessageChain
)
{
actual
override
suspend
fun
sendMessage
(
message
:
MessageChain
)
{
bot
.
network
[
EventPacketHandler
].
sendFriendMessage
(
this
,
message
)
bot
.
network
[
EventPacketHandler
].
sendFriendMessage
(
this
,
message
)
}
}
...
...
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/network/protocol/tim/packet/UploadImageJvm.kt
View file @
fdf50e4d
...
@@ -2,97 +2,186 @@
...
@@ -2,97 +2,186 @@
package
net.mamoe.mirai.network.protocol.tim.packet
package
net.mamoe.mirai.network.protocol.tim.packet
import
kotlinx.io.core.BytePacketBuilder
import
kotlinx.io.core.*
import
kotlinx.io.core.writeFully
import
net.mamoe.mirai.utils.*
import
net.mamoe.mirai.utils.*
import
java.io.File
import
javax.imageio.ImageIO
actual
typealias
ClientTryGetImageIDPacket
=
ClientTryGetImageIDPacketJvm
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.
* 请求上传图片. 将发送图片的 md5, size
, width, height
.
* 服务器返回以下之一:
* 服务器返回以下之一:
* - 服务器已经存有这个图片 [ServerTryGetImageIDFailedPacket]
* - 服务器已经存有这个图片 [ServerTryGetImageIDFailedPacket]
* - 服务器未存有, 返回一个 key 用于客户端上传 [ServerTryGetImageIDSuccessPacket]
* - 服务器未存有, 返回一个 key 用于客户端上传 [ServerTryGetImageIDSuccessPacket]
*
*
* @author Him188moe
* @author Him188moe
*/
*/
@PacketId
(
0
x03_
88
u
)
@PacketId
(
0
x03_
52
u
)
class
ClientTryGetImageIDPacketJvm
(
class
ClientTryGetImageIDPacketJvm
(
private
val
botNumber
:
Long
,
private
val
botNumber
:
UInt
,
private
val
sessionKey
:
ByteArray
,
private
val
sessionKey
:
ByteArray
,
private
val
groupNumberOrAccount
:
Long
,
private
val
target
:
UInt
,
private
val
image
:
PlatformImage
private
val
image
:
PlatformImage
)
:
ClientPacket
()
{
)
:
ClientPacket
()
{
override
fun
encode
(
builder
:
BytePacketBuilder
)
=
with
(
builder
)
{
this
.
writeRandom
(
2
)
//一次 body
//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
//00 00 00 00 00 00 00 00 3C 61 3C 48 85 91 81 B9 DF 27 D9 C3 20 43 F7 1C 73 DA 2A 84 74 AC 78 AC CC 38 54 8F AE 06 8C 22 AA AF 2E C1 E4 70 8C 31 63 52 95 F2 6F C3 9A 2D 77 4B F7 7B 4F C4 1A 6D 7A 3F 22 D8 9D B3 48 99 F3 E7 4F D0 2D 31 94 40 ED A7 5C D9 CE 70 B1 F7 B8 1B 3D CA B3 0E BE 86 33 56 B4 E4 30 AD 66 30 C1 C7 15 6A 71 B6 49 DC DC 0E 74 4B CE 12 3F ED
this
.
writeQQ
(
botNumber
)
@PacketVersion
(
date
=
"2019.10.19"
,
timVersion
=
"2.3.2.21173"
)
this
.
writeHex
(
"04 00 00 00 01 01 01 00 00 68 20 00 00 00 00 00 00 00 00"
)
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
*/
val
byteArray
=
image
.
toByteArray
()
this
.
encryptAndWrite
(
sessionKey
)
{
writeZero
(
3
)
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
)
}
writeHex
(
"07 00"
)
writeUShort
(
0
x38_01u
)
writeUShort
(
0
x48_00u
)
writeZero
(
2
)
writeHex
(
"5B"
)
//原5E
writeHex
(
"08"
)
writeHex
(
"01 12 03 98 01 01 10 01"
)
writeHex
(
"1A"
)
writeHex
(
"57"
)
//原5A
writeHex
(
"08"
)
writeUVarInt
(
groupNumberOrAccount
)
//FB D2 D8 94
writeByte
(
0
x02
)
writeHex
(
"10"
)
writeUVarInt
(
botNumber
)
//A2 FF 8C F0
writeHex
(
"18 00"
)
writeHex
(
"22"
)
writeHex
(
"10"
)
writeFully
(
md5
(
byteArray
))
writeHex
(
"28"
)
writeUVarInt
(
byteArray
.
size
.
toUInt
())
//E2 0D
writeHex
(
"32"
)
writeHex
(
"1A"
)
//28 00 5A 00 53 00 41 00 58 00 40 00 57 00 4B 00 52 00 4A 00 5A 00 31 00 7E 00 38 01 48 01 50 38 58 34 60 04 6A 05 32 36 39 33 33 70 00 78 03 80 01 00
writeHex
(
"37 00 4D 00 32 00 25 00 4C 00 31 00 56 00 32 00 7B 00 39 00 30 00 29 00 52 00"
)
writeHex
(
"38 01"
)
writeHex
(
"48 01"
)
writeHex
(
"50"
)
writeUByte
(
0
x70u
)
writeUVarInt
(
image
.
width
.
toUInt
())
writeUVarInt
(
image
.
width
.
toUInt
())
writeHex
(
"58"
)
writeUByte
(
0
x78u
)
writeUVarInt
(
image
.
height
.
toUInt
())
writeUVarInt
(
image
.
height
.
toUInt
())
}
writeShort
((
packet
.
remaining
-
7
).
toShort
())
//why?
writePacket
(
packet
)
writeHex
(
"60 04"
)
//println(this.build().readBytes().toUHexString())
writeHex
(
"6A"
)
writeHex
(
"05"
)
writeHex
(
"32 36 36 35 36"
)
writeHex
(
"70 00"
)
writeHex
(
"78 03"
)
writeHex
(
"80 01"
)
writeHex
(
"00"
)
}
}
}
}
}
}
\ No newline at end of file
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/PlatformImageJvm.kt
View file @
fdf50e4d
...
@@ -7,4 +7,4 @@ import javax.imageio.ImageIO
...
@@ -7,4 +7,4 @@ import javax.imageio.ImageIO
actual
typealias
PlatformImage
=
BufferedImage
actual
typealias
PlatformImage
=
BufferedImage
@JvmOverloads
@JvmOverloads
actual
fun
BufferedImage
.
toByteArray
(
formatName
:
String
):
ByteArray
=
ByteArrayOutputStream
().
use
{
ImageIO
.
write
(
this
,
"JPG"
,
it
);
it
.
toByteArray
()
}
actual
fun
BufferedImage
.
toByteArray
(
formatName
:
String
):
ByteArray
=
ByteArrayOutputStream
().
use
{
ImageIO
.
write
(
this
,
"PNG"
,
it
);
it
.
toByteArray
()
}
\ No newline at end of file
\ No newline at end of file
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/PlatformUtilsJvm.kt
View file @
fdf50e4d
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
)
package
net.mamoe.mirai.utils
package
net.mamoe.mirai.utils
import
kotlinx.coroutines.Dispatchers
import
java.net.HttpURLConnection
import
kotlinx.coroutines.withContext
import
org.jsoup.Connection
import
org.jsoup.Jsoup
import
java.net.InetAddress
import
java.net.InetAddress
import
java.net.URL
import
java.security.MessageDigest
import
java.security.MessageDigest
import
java.util.zip.CRC32
import
java.util.zip.CRC32
...
@@ -19,36 +19,62 @@ actual fun solveIpAddress(hostname: String): String = InetAddress.getByName(host
...
@@ -19,36 +19,62 @@ actual fun solveIpAddress(hostname: String): String = InetAddress.getByName(host
actual
fun
localIpAddress
():
String
=
InetAddress
.
getLocalHost
().
hostAddress
actual
fun
localIpAddress
():
String
=
InetAddress
.
getLocalHost
().
hostAddress
actual
suspend
fun
httpPostGroupImage
(
fun
main
()
{
"00 00 00 08 00 00 01 0D 12 06 98 01 01 A0 01 00 08 01 12 86 02 08 00 10 AB A7 89 D8 02 18 00 28 00 38 B4 C7 E6 B0 02 38 F1 C0 A1 BF 05 38 FB AE FA 95 0A 38 E5 C6 BF EC 06 40 B0 6D 40 90 3F 40 50 40 BB 03 4A 80 01 B5 29 1A 1B 0E 63 79 8B 34 B1 4E 2A 2A 9E 69 09 A7 69 F5 C6 4F 95 DA 96 A9 1B E3 CD 6F 3D 30 EE 59 C0 30 22 BF F0 2D 88 2D A7 6C B2 09 AD D6 CE E1 46 84 FC 7D 19 AF 1A 37 91 98 AD 2C 45 25 AA 17 2F 81 DC 5A 7F 30 F4 2D 73 E5 1C 8B 8A 23 85 42 9D 8D 5C 18 15 32 D1 CA A3 4D 01 7C 59 11 73 DA B6 09 C2 6D 58 35 EF 48 88 44 0F 2D 17 09 52 DF D4 EA A7 85 2F 27 CE DF A8 F5 9B CD C9 84 C2 52 25 2F 30 31 65 65 36 34 32 36 2D 35 66 66 31 2D 34 63 66 30 2D 38 32 37 38 2D 65 38 36 33 34 64 32 39 30 39 65 66 5A 25 2F 30 31 65 65 36 34 32 36 2D 35 66 66 31 2D 34 63 66 30 2D 38 32 37 38 2D 65 38 36 33 34 64 32 39 30 39 65 66 60 00 68 80 80 08 20 01"
.
printStringFromHex
()
println
(
md5
(
"00 00 00 08 00 00 01 0D 12 06 98 01 01 A0 01 00 08 01 12 86 02 08 00 10 AB A7 89 D8 02 18 00 28 00 38 B4 C7 E6 B0 02 38 F1 C0 A1 BF 05 38 FB AE FA 95 0A 38 E5 C6 BF EC 06 40 B0 6D 40 90 3F 40 50 40 BB 03 4A 80 01 B5 29 1A 1B 0E 63 79 8B 34 B1 4E 2A 2A 9E 69 09 A7 69 F5 C6 4F 95 DA 96 A9 1B E3 CD 6F 3D 30 EE 59 C0 30 22 BF F0 2D 88 2D A7 6C B2 09 AD D6 CE E1 46 84 FC 7D 19 AF 1A 37 91 98 AD 2C 45 25 AA 17 2F 81 DC 5A 7F 30 F4 2D 73 E5 1C 8B 8A 23 85 42 9D 8D 5C 18 15 32 D1 CA A3 4D 01 7C 59 11 73 DA B6 09 C2 6D 58 35 EF 48 88 44 0F 2D 17 09 52 DF D4 EA A7 85 2F 27 CE DF A8 F5 9B CD C9 84 C2 52 25 2F 30 31 65 65 36 34 32 36 2D 35 66 66 31 2D 34 63 66 30 2D 38 32 37 38 2D 65 38 36 33 34 64 32 39 30 39 65 66 5A 25 2F 30 31 65 65 36 34 32 36 2D 35 66 66 31 2D 34 63 66 30 2D 38 32 37 38 2D 65 38 36 33 34 64 32 39 30 39 65 66 60 00 68 80 80 08 20 01"
).
toUHexString
())
}
actual
suspend
fun
httpPostFriendImage
(
uKeyHex
:
String
,
uKeyHex
:
String
,
fileSize
:
Int
,
fileSize
:
Int
,
botNumber
:
Long
,
botNumber
:
UInt
,
groupCode
:
Long
,
qq
:
UInt
,
imageData
:
ByteArray
imageData
:
ByteArray
):
Boolean
=
Jsoup
):
Boolean
{
/*Jsoup
.
connect
(
"http://htdata2.qq.com/cgi-bin/httpconn?htcmd=0x6ff0071&ver=5515&term=pc"
+
//htdata2.qq.com
// 101.227.143.109/cgi-bin/httpconn
// ?htcmd=0x6ff0070
// &ver=5603
// &ukey=3B121C959B85035F12497519221FB9E09740E477D3A440D28253E96C95BD72EA1D11B25189894F0256F3E0F3D553FB92925A8834F85583C78D0D9639A3F35C730783D45C065FF9E9E74765183A11492D50750C6BB5DCAD9F171285B68F6A11061CDDA740AD2DCD28D5B2DB2D6440143FA53F1B6F14584DB49E926FDDC4F49907
// &filesize=137791
// &range=0
// &uin=1040400290
.connect("http://101.227.143.109/cgi-bin/httpconn" +
"?htcmd=0x6ff0070" +
"&ver=5603" +
"&ukey=" + uKeyHex.replace(" ", "") +
"&ukey=" + uKeyHex.replace(" ", "") +
"&filezise=" + fileSize +
"&filezise=" + fileSize +
"&range=" + "0" +
"&range=" + "0" +
"&uin="
+
botNumber
+
"&uin=" + botNumber.toLong())
"&groupcode="
+
groupCode
)
//.userAgent("QQClient")
.
userAgent
(
"QQClient"
)
.header("Content-Length", fileSize.toString())
.header("Content-Length", fileSize.toString())
.
requestBody
(
String
(
imageData
))
.requestBody(String(imageData
, Charset.forName("ASCII")
))
.method(Connection.Method.POST)
.method(Connection.Method.POST)
.ignoreContentType(true)
.ignoreContentType(true)
.let {
.let {
withContext(Dispatchers.IO) {
withContext(Dispatchers.IO) {
it.execute()
it.execute()
}
}
}
};*/
/*
val conn = URL(builder).openConnection() as HttpURLConnection
val
conn
=
URL
(
"http://101.227.143.109/cgi-bin/httpconn"
+
"?htcmd=0x6ff0070"
+
"&ver=5603"
+
"&ukey="
+
uKeyHex
.
replace
(
" "
,
""
)
+
"&filezise="
+
fileSize
+
"&range="
+
"0"
+
"&uin="
+
botNumber
.
toLong
()).
openConnection
()
as
HttpURLConnection
conn
.
setRequestProperty
(
"User-Agent"
,
"QQClient"
)
conn
.
setRequestProperty
(
"User-Agent"
,
"QQClient"
)
conn
.
setRequestProperty
(
"Content-Length"
,
""
+
fileSize
)
conn
.
setRequestProperty
(
"Content-Length"
,
""
+
fileSize
)
conn
.
requestMethod
=
"POST"
conn
.
requestMethod
=
"POST"
conn
.
doOutput
=
true
conn
.
doOutput
=
true
conn.outputStream.write(img
)
conn
.
outputStream
.
buffered
().
write
(
imageData
)
conn.connect()*/
conn
.
connect
()
.
statusCode
()
==
200
println
(
conn
.
responseMessage
)
\ No newline at end of file
println
(
conn
.
responseCode
)
return
conn
.
responseCode
==
200
}
\ No newline at end of file
mirai-core/src/jvmTest/kotlin/BadQQFilter.kt
View file @
fdf50e4d
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
)
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.GlobalScope
import
kotlinx.coroutines.GlobalScope
import
kotlinx.coroutines.runBlocking
import
kotlinx.coroutines.runBlocking
...
@@ -44,7 +46,7 @@ suspend fun main() {
...
@@ -44,7 +46,7 @@ suspend fun main() {
runBlocking
{
runBlocking
{
val
bot
=
Bot
(
val
bot
=
Bot
(
BotAccount
(
BotAccount
(
qq
,
qq
.
toUInt
()
,
if
(
password
.
endsWith
(
"."
))
password
.
substring
(
0
,
password
.
length
-
1
)
else
password
if
(
password
.
endsWith
(
"."
))
password
.
substring
(
0
,
password
.
length
-
1
)
else
password
),
),
Console
()
Console
()
...
...
mirai-debug/build.gradle
View file @
fdf50e4d
...
@@ -8,6 +8,8 @@ dependencies {
...
@@ -8,6 +8,8 @@ dependencies {
implementation
rootProject
.
ext
.
coroutineCommon
implementation
rootProject
.
ext
.
coroutineCommon
implementation
rootProject
.
ext
.
kotlinJvm
implementation
rootProject
.
ext
.
kotlinJvm
implementation
rootProject
.
ext
.
kotlinxIOJvm
implementation
rootProject
.
ext
.
kotlinxIOJvm
compile
"org.jetbrains.kotlin:kotlin-reflect:1.3.50"
implementation
'org.jsoup:jsoup:1.12.1'
}
}
tasks
.
withType
(
JavaCompile
)
{
tasks
.
withType
(
JavaCompile
)
{
...
...
mirai-debug/src/main/java/DownloadImgTest.kt
0 → 100644
View file @
fdf50e4d
import
net.mamoe.mirai.utils.toUHexString
import
org.jsoup.Connection
import
org.jsoup.Jsoup
fun
main
()
{
println
(
Jsoup
.
connect
(
"http://61.183.164.34/gchatpic_new/B814D8D6A55D6DB423469E38D2A17AAA23836D74E7A656A4A8288C6078950A33B4A49E854E59B6D2314EFC47D6475902EDE8CADAFAF7F2A7670CAC05EA8314A1241128102F0A3AAF9C07284B1AE35E52F6D0A265235AFA6B/0?vuin=1040400290&term=255&srvver=26933&rf=n"
)
.
cookie
(
"ST"
,
"00015DAA9C030040F3B82971FCBC718AA35573100B9CDBA2CB0DE38AF8710CA22E2986246345FC96B82BA0C211FDA700C397DF99FCC0989D67FD75F00B2FFB9CE0D032C3DCAC5A77"
)
.
method
(
Connection
.
Method
.
GET
)
.
ignoreContentType
(
true
)
.
execute
()
.
bodyAsBytes
().
toUHexString
())
}
\ No newline at end of file
mirai-debug/src/main/java/PacketDebuger.kt
View file @
fdf50e4d
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
,
"MemberVisibilityCanBePrivate"
)
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
,
"MemberVisibilityCanBePrivate"
,
"EXPERIMENTAL_UNSIGNED_LITERALS"
)
import
jpcap.JpcapCaptor
import
jpcap.JpcapCaptor
import
jpcap.packet.IPPacket
import
jpcap.packet.IPPacket
...
@@ -31,7 +31,7 @@ object Main {
...
@@ -31,7 +31,7 @@ object Main {
jpcap
=
JpcapCaptor
.
openDevice
(
devices
[
0
],
caplen
,
promiscCheck
,
50
)
jpcap
=
JpcapCaptor
.
openDevice
(
devices
[
0
],
caplen
,
promiscCheck
,
50
)
while
(
true
)
{
while
(
true
)
{
assert
(
jpcap
!=
null
)
assert
(
jpcap
!=
null
)
val
pk
=
jpcap
!!
.
packet
val
pk
=
jpcap
!!
.
packet
?:
continue
if
(
pk
is
IPPacket
&&
pk
.
version
.
toInt
()
==
4
)
{
if
(
pk
is
IPPacket
&&
pk
.
version
.
toInt
()
==
4
)
{
if
(
pk
is
UDPPacket
)
{
if
(
pk
is
UDPPacket
)
{
...
@@ -47,6 +47,7 @@ object Main {
...
@@ -47,6 +47,7 @@ object Main {
}
}
}
else
{
}
else
{
try
{
try
{
//println("发出包全部=${pk.data.toUHexString()}")
dataSent
(
pk
.
data
)
dataSent
(
pk
.
data
)
println
()
println
()
}
catch
(
e
:
Throwable
)
{
}
catch
(
e
:
Throwable
)
{
...
@@ -73,20 +74,36 @@ object Main {
...
@@ -73,20 +74,36 @@ object Main {
* 7. 查看内存, 从 `eax` 开始的 16 bytes 便是 `sessionKey`
* 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
=
"99 82 67 D4 62 20 CA 5D 81 F8 6F 83 EE 8A F7 68"
.
hexToBytes
()
val
qq
:
UInt
=
1040400290
u
fun
dataReceived
(
data
:
ByteArray
)
{
fun
dataReceived
(
data
:
ByteArray
)
{
println
(
"--------------"
)
println
(
"接收数据包"
)
//println("raw = " + data.toUHexString())
//println("raw = " + data.toUHexString())
data
.
read
{
data
.
read
{
discardExact
(
3
)
discardExact
(
3
)
val
idHex
=
readInt
().
toUHexString
(
" "
)
val
idHex
=
readInt
().
toUHexString
(
" "
)
discardExact
(
7
)
//4 for qq number, 3 for 0x00 0x00 0x00. 但更可能是应该 discard 8
if
(
idHex
.
startsWith
(
"00 81"
))
{
return
@
read
}
if
(
readUInt
()
!=
qq
)
{
return
@
read
}
println
(
"--------------"
)
println
(
"接收数据包"
)
discardExact
(
3
)
//0x00 0x00 0x00. 但更可能是应该 discard 8
println
(
"id=$idHex"
)
println
(
"id=$idHex"
)
println
(
"解密body=${this.readRemainingBytes().cutTail(1).decryptBy(sessionKey).toUHexString()}"
)
val
remaining
=
this
.
readRemainingBytes
().
cutTail
(
1
)
try
{
val
decrypted
=
remaining
.
decryptBy
(
sessionKey
)
println
(
"解密body=${decrypted.toUHexString()}"
)
packetReceived
(
data
.
read
{
parseServerPacket
(
data
.
size
)
})
}
catch
(
e
:
DecryptionFailedException
)
{
println
(
"密文body="
+
remaining
.
toUHexString
())
println
(
"解密body=解密失败"
)
}
}
packetReceived
(
data
.
read
{
this
.
parseServerPacket
(
data
.
size
)
})
}
}
}
fun
packetReceived
(
packet
:
ServerPacket
)
{
fun
packetReceived
(
packet
:
ServerPacket
)
{
...
@@ -118,15 +135,38 @@ object Main {
...
@@ -118,15 +135,38 @@ object Main {
}
}
fun
dataSent
(
rawPacket
:
ByteArray
)
=
rawPacket
.
cutTail
(
1
).
read
{
fun
dataSent
(
rawPacket
:
ByteArray
)
=
rawPacket
.
cutTail
(
1
).
read
{
// 02 38 03
// 03 52 78 9F
// 3E 03 3F A2 04 00 00 00 01 2E 01 00 00 69 35 00 00 00 00 00 00 00 00
// 02 38 03
// 01 BD 63 D6
// 3E 03 3F A2 02 00 00 00 01 2E 01 00 00 69 35
println
(
"---------------------------"
)
println
(
"---------------------------"
)
discardExact
(
3
)
//head
discardExact
(
3
)
//head
val
idHex
=
readBytes
(
4
).
toUHexString
()
val
idHex
=
readBytes
(
4
).
toUHexString
()
println
(
"发出包ID = $idHex"
)
println
(
"发出包ID = $idHex"
)
readUInt
()
//客户端登录的qq
if
(
readUInt
()
!=
qq
)
{
println
(
"TIM的fixVer2="
+
readBytes
(
TIMProtocol
.
fixVer2
.
hexToBytes
().
size
).
toUHexString
())
return
@
read
}
println
(
"fixVer2="
+
when
(
val
flag
=
readByte
().
toInt
())
{
2
->
byteArrayOf
(
2
)
+
readBytes
(
TIMProtocol
.
fixVer2
.
hexToBytes
().
size
-
1
)
4
->
byteArrayOf
(
4
)
+
readBytes
(
TIMProtocol
.
fixVer2
.
hexToBytes
().
size
-
1
+
8
)
//8个0
else
->
error
(
"unknown fixVer2 flag=$flag"
)
}.
toUHexString
())
//39 27 DC E2 04 00 00 00 00 00 00 00 1E 0E 89 00 00 01 05 0F 05 0F 00 00 00 00 00 00 00 00 00 00 00 00 00 3E 03 3F A2 00 00 00 00 00 00 00 00 00 00 00
val
encryptedBody
=
readRemainingBytes
()
val
encryptedBody
=
readRemainingBytes
()
println
(
"解密body = ${encryptedBody.decryptBy(sessionKey).toUHexString()}"
)
try
{
println
(
"解密body=${encryptedBody.decryptBy(sessionKey).toUHexString()}"
)
}
catch
(
e
:
DecryptionFailedException
)
{
println
(
"密文="
+
encryptedBody
.
toUHexString
())
println
(
"解密body=解密失败"
)
}
encryptedBody
.
read
{
encryptedBody
.
read
{
...
@@ -139,6 +179,8 @@ object Main {
...
@@ -139,6 +179,8 @@ object Main {
val
messageData
=
raw
.
decryptBy
(
sessionKey
)
val
messageData
=
raw
.
decryptBy
(
sessionKey
)
println
(
"解密结果: "
+
messageData
.
toUHexString
())
println
(
"解密结果: "
+
messageData
.
toUHexString
())
println
(
"尝试解消息"
)
println
(
"尝试解消息"
)
try
{
messageData
.
read
{
messageData
.
read
{
discardExact
(
discardExact
(
4
+
4
+
12
+
2
+
4
+
4
+
16
+
2
+
2
+
4
+
2
+
16
+
4
+
4
+
7
+
15
+
2
4
+
4
+
12
+
2
+
4
+
4
+
16
+
2
+
2
+
4
+
2
+
16
+
4
+
4
+
7
+
15
+
2
...
@@ -147,6 +189,9 @@ object Main {
...
@@ -147,6 +189,9 @@ object Main {
val
chain
=
readMessageChain
()
val
chain
=
readMessageChain
()
println
(
chain
)
println
(
chain
)
}
}
}
catch
(
e
:
Exception
)
{
println
(
"失败"
)
}
}
}
"03 88"
->
{
"03 88"
->
{
...
...
mirai-demos/mirai-demo-1/src/main/java/demo1/Main.kt
View file @
fdf50e4d
@
file
:
Suppress
(
"EXPERIMENTAL_UNSIGNED_LITERALS"
,
"EXPERIMENTAL_API_USAGE"
)
package
demo1
package
demo1
import
kotlinx.coroutines.delay
import
kotlinx.coroutines.delay
import
kotlinx.coroutines.withTimeoutOrNull
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.contact.Group
import
net.mamoe.mirai.contact.Group
import
net.mamoe.mirai.contact.QQ
import
net.mamoe.mirai.event.events.FriendMessageEvent
import
net.mamoe.mirai.event.events.FriendMessageEvent
import
net.mamoe.mirai.event.events.GroupMessageEvent
import
net.mamoe.mirai.event.events.GroupMessageEvent
import
net.mamoe.mirai.event.subscribeAll
import
net.mamoe.mirai.event.subscribeAll
...
@@ -10,12 +14,16 @@ import net.mamoe.mirai.event.subscribeAlways
...
@@ -10,12 +14,16 @@ import net.mamoe.mirai.event.subscribeAlways
import
net.mamoe.mirai.event.subscribeUntilFalse
import
net.mamoe.mirai.event.subscribeUntilFalse
import
net.mamoe.mirai.login
import
net.mamoe.mirai.login
import
net.mamoe.mirai.message.Image
import
net.mamoe.mirai.message.Image
import
net.mamoe.mirai.message.ImageId
import
net.mamoe.mirai.message.PlainText
import
net.mamoe.mirai.message.PlainText
import
net.mamoe.mirai.network.protocol.tim.packet.ClientRawPacket
import
net.mamoe.mirai.network.protocol.tim.packet.login.LoginResult
import
net.mamoe.mirai.network.protocol.tim.packet.login.LoginResult
import
net.mamoe.mirai.utils.BotAccount
import
net.mamoe.mirai.network.protocol.tim.packet.uploadImage
import
net.mamoe.mirai.utils.MiraiLogger
import
net.mamoe.mirai.network.session
import
net.mamoe.mirai.utils.PlatformLogger
import
net.mamoe.mirai.qqAccount
import
net.mamoe.mirai.utils.*
import
java.io.File
import
java.io.File
import
javax.imageio.ImageIO
private
fun
readTestAccount
():
BotAccount
?
{
private
fun
readTestAccount
():
BotAccount
?
{
val
file
=
File
(
"testAccount.txt"
)
val
file
=
File
(
"testAccount.txt"
)
...
@@ -25,7 +33,7 @@ private fun readTestAccount(): BotAccount? {
...
@@ -25,7 +33,7 @@ private fun readTestAccount(): BotAccount? {
val
lines
=
file
.
readLines
()
val
lines
=
file
.
readLines
()
return
try
{
return
try
{
BotAccount
(
lines
[
0
].
to
Long
(),
lines
[
1
])
BotAccount
(
lines
[
0
].
to
UInt
(),
lines
[
1
])
}
catch
(
e
:
IndexOutOfBoundsException
)
{
}
catch
(
e
:
IndexOutOfBoundsException
)
{
null
null
}
}
...
@@ -34,7 +42,7 @@ private fun readTestAccount(): BotAccount? {
...
@@ -34,7 +42,7 @@ private fun readTestAccount(): BotAccount? {
@Suppress
(
"UNUSED_VARIABLE"
)
@Suppress
(
"UNUSED_VARIABLE"
)
suspend
fun
main
()
{
suspend
fun
main
()
{
val
bot
=
Bot
(
readTestAccount
()
?:
BotAccount
(
//填写你的账号
val
bot
=
Bot
(
readTestAccount
()
?:
BotAccount
(
//填写你的账号
account
=
1994701121
,
account
=
1994701121
u
,
password
=
"123456"
password
=
"123456"
),
PlatformLogger
())
),
PlatformLogger
())
...
@@ -61,20 +69,31 @@ suspend fun main() {
...
@@ -61,20 +69,31 @@ suspend fun main() {
"复读"
in
it
.
message
->
it
.
sender
.
sendMessage
(
it
.
message
)
"复读"
in
it
.
message
->
it
.
sender
.
sendMessage
(
it
.
message
)
"发群"
in
it
.
message
->
{
"发群"
in
it
.
message
->
Group
(
bot
,
580266363
u
).
sendMessage
(
"h"
)
"直接发送包"
in
it
.
message
->
{
val
d
=
(
"01 "
+
1994701021
u
.
toByteArray
().
toUHexString
()
+
" 3E 03 3F A2 00 00 02 BB 00 0A 00 01 00 01 00 5E 4F 53 52 6F 6F 74 3A 43 3A 5C 55 73 65 72 73 5C 48 69 6D 31 38 5C 44 6F 63 75 6D 65 6E 74 73 5C 54 65 6E 63 65 6E 74 20 46 69 6C 65 73 5C 31 30 34 30 34 30 30 32 39 30 5C 49 6D 61 67 65 5C 43 32 43 5C 7B 47 47 42 7E 49 31 5A 4D 43 28 25 49 4D 5A 5F 47 55 51 36 35 5D 51 2E 6A 70 67 00 00 04 7D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 35 02"
)
.
hexToBytes
()
it
.
bot
.
network
.
socket
.
sendPacket
(
ClientRawPacket
(
0
x01_BDu
,
it
.
bot
.
qqAccount
,
"00 00 00 01 2E 01 00 00 69 35"
.
hexToBytes
(),
it
.
bot
.
network
.
session
.
sessionKey
,
d
))
}
"上传好友图片"
in
it
.
message
->
withTimeoutOrNull
(
3000
)
{
val
id
=
QQ
(
bot
,
1040400290
u
).
uploadImage
(
ImageIO
.
read
(
File
(
"C:\\Users\\Him18\\Desktop\\lemon.png"
).
readBytes
().
inputStream
()))
it
.
reply
(
id
.
value
)
delay
(
1000
)
it
.
reply
(
Image
(
id
))
}
}
/*it.event eq "发图片群" -> sendGroupMessage(Group(session.bot, 580266363), PlainText("test") + UnsolvedImage(File("C:\\Users\\Him18\\Desktop\\faceImage_1559564477775.jpg")).also { image ->
/*it.event eq "发图片群" -> sendGroupMessage(Group(session.bot, 580266363), PlainText("test") + UnsolvedImage(File("C:\\Users\\Him18\\Desktop\\faceImage_1559564477775.jpg")).also { image ->
image.upload(session, Group(session.bot, 580266363)).of()
image.upload(session, Group(session.bot, 580266363)).of()
})*/
})*/
it
.
message
eq
"发图片群2"
->
Group
(
bot
,
580266363
).
sendMessage
(
Image
(
"{7AA4B3AA-8C3C-0F45-2D9B-7F302A0ACEAA}.jpg"
))
it
.
message
eq
"发图片群2"
->
Group
(
bot
,
580266363
u
).
sendMessage
(
Image
(
ImageId
(
"{7AA4B3AA-8C3C-0F45-2D9B-7F302A0ACEAA}.jpg"
)
))
/* it.event eq "发图片" -> sendFriendMessage(it.sender, PlainText("test") + UnsolvedImage(File("C:\\Users\\Him18\\Desktop\\faceImage_1559564477775.jpg")).also { image ->
/* it.event eq "发图片" -> sendFriendMessage(it.sender, PlainText("test") + UnsolvedImage(File("C:\\Users\\Him18\\Desktop\\faceImage_1559564477775.jpg")).also { image ->
image.upload(session, it.sender).of()
image.upload(session, it.sender).of()
})*/
})*/
it
.
message
eq
"发图片2"
->
it
.
reply
(
PlainText
(
"test"
)
+
Image
(
"{7AA4B3AA-8C3C-0F45-2D9B-7F302A0ACEAA}.jpg"
))
it
.
message
eq
"发图片2"
->
it
.
reply
(
PlainText
(
"test"
)
+
Image
(
ImageId
(
"{7AA4B3AA-8C3C-0F45-2D9B-7F302A0ACEAA}.jpg"
)
))
}
}
}
}
...
...
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