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
Hide 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
import
kotlinx.coroutines.runBlocking
...
...
@@ -172,7 +174,7 @@ object MiraiServer {
get
()
{
for
(
it
in
qqList
.
split
(
"\n"
).
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
)
{
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
import
kotlinx.atomicfu.atomic
...
...
@@ -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
))
}
}
...
...
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotHelper.kt
View file @
fdf50e4d
...
...
@@ -17,14 +17,14 @@ import net.mamoe.mirai.utils.toUHexString
*/
//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
:
UInt
):
Group
=
getGroupByNumber
(
number
.
toLong
()
)
fun
Bot
.
getGroupByNumber
(
number
:
Long
):
Group
=
this
.
contacts
.
getGroupByNumber
(
number
.
toUInt
()
)
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
...
...
@@ -39,7 +39,7 @@ suspend fun Bot.login(configuration: BotNetworkConfiguration.() -> Unit): LoginR
suspend
fun
Bot
.
login
():
LoginResult
=
this
.
network
.
login
(
BotNetworkConfiguration
.
Default
)
//BotAccount
val
Bot
.
qqAccount
:
Long
get
()
=
this
.
account
.
account
val
Bot
.
qqAccount
:
UInt
get
()
=
this
.
account
.
account
//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
import
net.mamoe.mirai.Bot
...
...
@@ -11,7 +13,7 @@ import net.mamoe.mirai.message.toChain
*
* @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
)
...
...
@@ -33,4 +35,4 @@ abstract class PlatformContactBase internal constructor(val bot: Bot, val number
* 在不同平台可能有不同的实现.
* 如在 JVM, suspend 调用不便, [Contact] 中有简化调用的 `blocking`() 和 `async`
*/
expect
sealed
class
Contact
(
bot
:
Bot
,
number
:
Long
)
:
PlatformContactBase
\ No newline at end of file
expect
sealed
class
Contact
(
bot
:
Bot
,
number
:
UInt
)
:
PlatformContactBase
\ 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
import
net.mamoe.mirai.Bot
...
...
@@ -13,8 +15,8 @@ import net.mamoe.mirai.utils.ContactList
*
* @author Him188moe
*/
expect
class
Group
(
bot
:
Bot
,
number
:
Long
)
:
Contact
{
val
groupId
:
Long
expect
class
Group
(
bot
:
Bot
,
number
:
UInt
)
:
Contact
{
val
groupId
:
UInt
val
members
:
ContactList
<
QQ
>
override
suspend
fun
sendMessage
(
message
:
MessageChain
)
...
...
@@ -23,7 +25,7 @@ expect class Group(bot: Bot, number: Long) : Contact {
companion
object
}
fun
Group
.
Companion
.
groupNumberToId
(
number
:
Long
):
Long
{
//求你别出错
fun
Group
.
Companion
.
groupNumberToId
(
number
:
UInt
):
UInt
{
//求你别出错
val
left
:
Long
=
number
.
toString
().
let
{
if
(
it
.
length
<
6
)
{
return
@
groupNumberToId
number
...
...
@@ -36,84 +38,84 @@ fun Group.Companion.groupNumberToId(number: Long): Long {//求你别出错
return
when
(
left
)
{
in
1
..
10
->
{
((
left
+
202
).
toString
()
+
right
.
toString
()).
to
Long
()
((
left
+
202
).
toString
()
+
right
.
toString
()).
to
UInt
()
}
in
11
..
19
->
{
((
left
+
469
).
toString
()
+
right
.
toString
()).
to
Long
()
((
left
+
469
).
toString
()
+
right
.
toString
()).
to
UInt
()
}
in
20
..
66
->
{
((
left
+
208
).
toString
()
+
right
.
toString
()).
to
Long
()
((
left
+
208
).
toString
()
+
right
.
toString
()).
to
UInt
()
}
in
67
..
156
->
{
((
left
+
1943
).
toString
()
+
right
.
toString
()).
to
Long
()
((
left
+
1943
).
toString
()
+
right
.
toString
()).
to
UInt
()
}
in
157
..
209
->
{
((
left
+
199
).
toString
()
+
right
.
toString
()).
to
Long
()
((
left
+
199
).
toString
()
+
right
.
toString
()).
to
UInt
()
}
in
210
..
309
->
{
((
left
+
389
).
toString
()
+
right
.
toString
()).
to
Long
()
((
left
+
389
).
toString
()
+
right
.
toString
()).
to
UInt
()
}
in
310
..
499
->
{
((
left
+
349
).
toString
()
+
right
.
toString
()).
to
Long
()
((
left
+
349
).
toString
()
+
right
.
toString
()).
to
UInt
()
}
else
->
number
}
}
fun
Group
.
Companion
.
groupIdToNumber
(
id
:
Long
):
Long
{
//求你别出错
var
left
:
Long
=
id
.
toString
().
let
{
fun
Group
.
Companion
.
groupIdToNumber
(
id
:
UInt
):
UInt
{
//求你别出错
var
left
:
UInt
=
id
.
toString
().
let
{
if
(
it
.
length
<
6
)
{
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
->
{
val
right
:
Long
=
id
.
toString
().
let
{
it
.
substring
(
it
.
length
-
6
).
to
Long
()
val
right
:
UInt
=
id
.
toString
().
let
{
it
.
substring
(
it
.
length
-
6
).
to
UInt
()
}
((
left
-
202
).
toString
()
+
right
.
toString
()).
toLong
()
((
left
-
202
u
).
toString
()
+
right
.
toString
()).
toUInt
()
}
in
480
..
488
->
{
val
right
:
Long
=
id
.
toString
().
let
{
it
.
substring
(
it
.
length
-
6
).
to
Long
()
val
right
:
UInt
=
id
.
toString
().
let
{
it
.
substring
(
it
.
length
-
6
).
to
UInt
()
}
((
left
-
469
).
toString
()
+
right
.
toString
()).
toLong
()
((
left
-
469
u
).
toString
()
+
right
.
toString
()).
toUInt
()
}
in
2100
..
2146
->
{
val
right
:
Long
=
id
.
toString
().
let
{
it
.
substring
(
it
.
length
-
7
).
to
Long
()
val
right
:
UInt
=
id
.
toString
().
let
{
it
.
substring
(
it
.
length
-
7
).
to
UInt
()
}
left
=
left
.
toString
().
substring
(
0
until
3
).
to
Long
()
((
left
-
208
).
toString
()
+
right
.
toString
()).
toLong
()
left
=
left
.
toString
().
substring
(
0
until
3
).
to
UInt
()
((
left
-
208
u
).
toString
()
+
right
.
toString
()).
toUInt
()
}
in
2010
..
2099
->
{
val
right
:
Long
=
id
.
toString
().
let
{
it
.
substring
(
it
.
length
-
6
).
to
Long
()
val
right
:
UInt
=
id
.
toString
().
let
{
it
.
substring
(
it
.
length
-
6
).
to
UInt
()
}
((
left
-
1943
).
toString
()
+
right
.
toString
()).
toLong
()
((
left
-
1943
u
).
toString
()
+
right
.
toString
()).
toUInt
()
}
in
2147
..
2199
->
{
val
right
:
Long
=
id
.
toString
().
let
{
it
.
substring
(
it
.
length
-
7
).
to
Long
()
val
right
:
UInt
=
id
.
toString
().
let
{
it
.
substring
(
it
.
length
-
7
).
to
UInt
()
}
left
=
left
.
toString
().
substring
(
0
until
3
).
to
Long
()
((
left
-
199
).
toString
()
+
right
.
toString
()).
toLong
()
left
=
left
.
toString
().
substring
(
0
until
3
).
to
UInt
()
((
left
-
199
u
).
toString
()
+
right
.
toString
()).
toUInt
()
}
in
4100
..
4199
->
{
val
right
:
Long
=
id
.
toString
().
let
{
it
.
substring
(
it
.
length
-
7
).
to
Long
()
val
right
:
UInt
=
id
.
toString
().
let
{
it
.
substring
(
it
.
length
-
7
).
to
UInt
()
}
left
=
left
.
toString
().
substring
(
0
until
3
).
to
Long
()
((
left
-
389
).
toString
()
+
right
.
toString
()).
toLong
()
left
=
left
.
toString
().
substring
(
0
until
3
).
to
UInt
()
((
left
-
389
u
).
toString
()
+
right
.
toString
()).
toUInt
()
}
in
3800
..
3989
->
{
val
right
:
Long
=
id
.
toString
().
let
{
it
.
substring
(
it
.
length
-
7
).
to
Long
()
val
right
:
UInt
=
id
.
toString
().
let
{
it
.
substring
(
it
.
length
-
7
).
to
UInt
()
}
left
=
left
.
toString
().
substring
(
0
until
3
).
to
Long
()
((
left
-
349
).
toString
()
+
right
.
toString
()).
toLong
()
left
=
left
.
toString
().
substring
(
0
until
3
).
to
UInt
()
((
left
-
349
u
).
toString
()
+
right
.
toString
()).
toUInt
()
}
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
import
net.mamoe.mirai.Bot
...
...
@@ -14,7 +16,7 @@ import net.mamoe.mirai.message.MessageChain
*
* @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
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
...
...
@@ -87,21 +87,24 @@ data class PlainText(override val stringValue: String) : Message() {
// ==================================== 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
()
{
override
val
stringValue
:
String
=
"[$
id
]"
data class
Image
(
val
id
:
ImageId
,
val
filename
:
String
=
""
)
:
Message
()
{
override
val
stringValue
:
String
=
"[$
{id.value}
]"
}
inline
class
ImageId
(
val
value
:
String
)
// ==================================== At ====================================
/**
* At 一个人
*/
data class
At
(
val
targetQQ
:
Long
)
:
Message
()
{
data class
At
(
val
targetQQ
:
UInt
)
:
Message
()
{
constructor
(
target
:
QQ
)
:
this
(
target
.
number
)
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) {
PLAIN_TEXT
(
0
x01u
),
AT
(
0
x06u
),
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
This diff is collapsed.
Click to expand it.
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/BotNetworkHandler.kt
View file @
fdf50e4d
...
...
@@ -70,7 +70,7 @@ interface BotNetworkHandler<Socket : DataPacketSocketAdapter> {
* @see [BotSession.sendAndExpect] 发送并期待一个包
* @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
import
kotlinx.coroutines.Completable
Job
import
kotlinx.coroutines.Completable
Deferred
import
kotlinx.coroutines.CoroutineScope
import
kotlinx.coroutines.Job
import
net.mamoe.mirai.Bot
...
...
@@ -65,10 +65,10 @@ class BotSession(
* @param handlerTemporary 处理器.
*/
//@JvmSynthetic
suspend
inline
fun
<
reified
P
:
ServerPacket
>
sendAndExpect
(
handlerTemporary
:
TemporaryPacketHandler
<
P
>.()
->
Unit
):
CompletableJob
{
val
job
=
coroutineContext
[
Job
].
takeIf
{
it
!=
null
}
?.
let
{
Job
(
it
)
}
?:
Job
()
this
.
bot
.
network
.
addHandler
(
TemporaryPacketHandler
(
P
::
class
,
job
,
this
).
also
(
handlerTemporary
))
return
job
suspend
inline
fun
<
reified
P
:
ServerPacket
,
R
>
sendAndExpect
(
handlerTemporary
:
TemporaryPacketHandler
<
P
,
R
>.()
->
Unit
):
CompletableDeferred
<
R
>
{
val
deferred
:
CompletableDeferred
<
R
>
=
coroutineContext
[
Job
].
takeIf
{
it
!=
null
}
?.
let
{
CompletableDeferred
<
R
>(
it
)
}
?:
CompletableDeferred
()
this
.
bot
.
network
.
addHandler
(
TemporaryPacketHandler
(
P
::
class
,
deferred
,
this
).
also
(
handlerTemporary
))
return
deferred
}
/**
...
...
@@ -86,13 +86,13 @@ class BotSession(
* @param P 期待的包
* @param handler 处理期待的包
*/
suspend
inline
fun
<
reified
P
:
ServerPacket
>
ClientPacket
.
sendAndExpect
(
noinline
handler
:
suspend
(
P
)
->
Unit
):
CompletableJob
{
val
job
=
coroutineContext
[
Job
].
takeIf
{
it
!=
null
}
?.
let
{
Job
(
it
)
}
?:
Job
()
bot
.
network
.
addHandler
(
TemporaryPacketHandler
(
P
::
class
,
job
,
this
@BotSession
).
also
{
suspend
inline
fun
<
reified
P
:
ServerPacket
,
R
>
ClientPacket
.
sendAndExpect
(
noinline
handler
:
suspend
(
P
)
->
R
):
CompletableDeferred
<
R
>
{
val
deferred
:
CompletableDeferred
<
R
>
=
coroutineContext
[
Job
].
takeIf
{
it
!=
null
}
?.
let
{
CompletableDeferred
<
R
>(
it
)
}
?:
CompletableDeferred
()
bot
.
network
.
addHandler
(
TemporaryPacketHandler
(
P
::
class
,
deferred
,
this
@BotSession
).
also
{
it
.
toSend
(
this
)
it
.
onExpect
(
handler
)
})
return
job
return
deferred
}
suspend
inline
fun
ClientPacket
.
send
()
=
socket
.
sendPacket
(
this
)
...
...
@@ -101,6 +101,6 @@ class BotSession(
suspend
fun
BotSession
.
distributePacket
(
packet
:
ServerPacket
)
=
this
.
socket
.
distributePacket
(
packet
)
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
\ 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) :
override
lateinit
var
socket
:
BotSocketAdapter
private
set
internal
val
temporaryPacketHandlers
=
mutableListOf
<
TemporaryPacketHandler
<
*
>>()
internal
val
temporaryPacketHandlers
=
mutableListOf
<
TemporaryPacketHandler
<
*
,
*
>>()
private
val
handlersLock
=
Mutex
()
private
var
heartbeatJob
:
Job
?
=
null
override
suspend
fun
addHandler
(
temporaryPacketHandler
:
TemporaryPacketHandler
<
*
>)
{
override
suspend
fun
addHandler
(
temporaryPacketHandler
:
TemporaryPacketHandler
<
*
,
*
>)
{
handlersLock
.
withLock
{
temporaryPacketHandlers
.
add
(
temporaryPacketHandler
)
}
...
...
@@ -408,7 +408,7 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
class
HeartbeatTimeoutException
:
CancellationException
(
"heartbeat timeout"
)
if
(
withTimeoutOrNull
(
configuration
.
heartbeatTimeout
.
millisecondsLong
)
{
ClientHeartbeatPacket
(
bot
.
qqAccount
,
sessionKey
).
sendAndExpect
<
ServerHeartbeatResponsePacket
>
{}
ClientHeartbeatPacket
(
bot
.
qqAccount
,
sessionKey
).
sendAndExpect
<
ServerHeartbeatResponsePacket
,
Unit
>
{}
}
==
null
)
{
bot
.
logPurple
(
"Heartbeat timed out"
)
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) {
}
is
ServerSubmitImageFilenameResponsePacket
->
{
}
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
->
{
...
...
@@ -84,7 +89,7 @@ class ActionPacketHandler(session: BotSession) : PacketHandler(session) {
}
//@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
session
=
AddFriendSession
(
account
,
future
,
message
)
// uploadImageSessions.add(session)
...
...
@@ -160,7 +165,7 @@ class ActionPacketHandler(session: BotSession) : PacketHandler(session) {
}
private
inner
class
AddFriendSession
(
private
val
qq
:
Long
,
private
val
qq
:
UInt
,
private
val
future
:
CompletableDeferred
<
AddFriendResult
>,
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) {
}
is
ServerGroupMessageEventPacket
->
{
if
(
packet
.
qq
.
toLong
()
==
bot
.
account
.
account
)
return
if
(
packet
.
qq
==
bot
.
account
.
account
)
return
GroupMessageEvent
(
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
import
kotlinx.coroutines.Completable
Job
import
kotlinx.coroutines.Completable
Deferred
import
net.mamoe.mirai.network.BotSession
import
net.mamoe.mirai.network.protocol.tim.packet.ClientPacket
import
net.mamoe.mirai.network.protocol.tim.packet.ServerPacket
...
...
@@ -19,14 +19,14 @@ import kotlin.reflect.KClass
*
* @see BotSession.sendAndExpect
*/
class
TemporaryPacketHandler
<
P
:
ServerPacket
>(
class
TemporaryPacketHandler
<
P
:
ServerPacket
,
R
>(
private
val
expectationClass
:
KClass
<
P
>,
private
val
job
:
CompletableJob
,
private
val
deferred
:
CompletableDeferred
<
R
>
,
private
val
fromSession
:
BotSession
)
{
private
lateinit
var
toSend
:
ClientPacket
private
lateinit
var
expect
:
suspend
(
P
)
->
Unit
private
lateinit
var
expect
:
suspend
(
P
)
->
R
lateinit
var
session
:
BotSession
//无需覆盖
...
...
@@ -40,7 +40,7 @@ class TemporaryPacketHandler<P : ServerPacket>(
}
fun
onExpect
(
handler
:
suspend
(
P
)
->
Unit
)
{
fun
onExpect
(
handler
:
suspend
(
P
)
->
R
)
{
this
.
expect
=
handler
}
...
...
@@ -51,10 +51,15 @@ class TemporaryPacketHandler<P : ServerPacket>(
suspend
fun
shouldRemove
(
session
:
BotSession
,
packet
:
ServerPacket
):
Boolean
{
if
(
expectationClass
.
isInstance
(
packet
)
&&
session
===
this
.
fromSession
)
{
kotlin
.
runCatching
{
@Suppress
(
"UNCHECKED_CAST"
)
@Suppress
(
"UNCHECKED_CAST"
)
val
ret
=
try
{
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
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 {
}
}
@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
)
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
import
net.mamoe.mirai.utils.encryptAndWrite
import
net.mamoe.mirai.utils.writeHex
import
net.mamoe.mirai.utils.writeQQ
import
net.mamoe.mirai.utils.writeRandom
/**
* 获取升级天数等.
...
...
@@ -18,7 +17,7 @@ import net.mamoe.mirai.utils.writeRandom
*/
@PacketId
(
0
x00_5Cu
)
class
ClientAccountInfoRequestPacket
(
private
val
qq
:
Long
,
private
val
qq
:
UInt
,
private
val
sessionKey
:
ByteArray
)
:
ClientPacket
()
{
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
@PacketId
(
0
x00_58u
)
class
ClientHeartbeatPacket
(
private
val
bot
:
Long
,
private
val
bot
:
UInt
,
private
val
sessionKey
:
ByteArray
)
:
ClientPacket
()
{
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
@Retention
(
AnnotationRetention
.
RUNTIME
)
@Target
(
AnnotationTarget
.
CLASS
,
AnnotationTarget
.
FILE
)
@Target
(
AnnotationTarget
.
CLASS
)
annotation
class
PacketId
(
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 {
override
fun
close
()
=
this
.
input
.
close
()
override
fun
toString
():
String
=
this
.
packetToString
()
fun
<
S
:
ServerPacket
>
S
.
applySequence
()
=
this
.
applySequence
(
this
@ServerPacket
.
sequenceId
)
}
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 @@
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.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.*
*/
@PacketId
(
0
x00_A7u
)
class
ClientCanAddFriendPacket
(
val
bot
:
Long
,
val
qq
:
Long
,
val
bot
:
UInt
,
val
qq
:
UInt
,
val
sessionKey
:
ByteArray
)
:
ClientPacket
()
{
override
fun
encode
(
builder
:
BytePacketBuilder
)
=
with
(
builder
)
{
...
...
@@ -85,8 +90,8 @@ class ServerCanAddFriendResponsePacket(input: ByteReadPacket) : ServerPacket(inp
*/
@PacketId
(
0
x00_AEu
)
class
ClientAddFriendPacket
(
val
bot
:
Long
,
val
qq
:
Long
,
val
bot
:
UInt
,
val
qq
:
UInt
,
val
sessionKey
:
ByteArray
)
:
ClientPacket
()
{
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
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.PacketId
import
net.mamoe.mirai.network.protocol.tim.packet.PacketVersion
import
net.mamoe.mirai.network.protocol.tim.packet.ServerPacket
import
net.mamoe.mirai.utils.*
fun
main
()
{
println
(
"牛逼"
.
toMessage
().
toChain
().
toPacket
().
readBytes
().
toUHexString
())
println
(
"牛逼"
.
toMessage
().
toChain
().
toPacket
(
true
).
readBytes
().
toUHexString
())
}
@PacketId
(
0
x00_CDu
)
class
ClientSendFriendMessagePacket
(
private
val
botQQ
:
Long
,
private
val
targetQQ
:
Long
,
private
val
botQQ
:
UInt
,
private
val
targetQQ
:
UInt
,
private
val
sessionKey
:
ByteArray
,
private
val
message
:
MessageChain
)
:
ClientPacket
()
{
@PacketVersion
(
date
=
"2019.10.19"
,
timVersion
=
"2.3.2.21173"
)
override
fun
encode
(
builder
:
BytePacketBuilder
)
=
with
(
builder
)
{
writeQQ
(
botQQ
)
writeHex
(
TIMProtocol
.
versionNewest
)
encryptAndWrite
(
sessionKey
)
{
//TIM最新
//3E 03 3F A2
//76 E4 B8 DD
//00 00 00 08 00 01 00 04 00 00 00 00
//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 7F
//5D AA A8 E2
//01 1D
// TIM最新, 消息内容 "牛逼"
// 3E 03 3F A2
// 76 E4 B8 DD
// 00 00 00 [08] 00 01 00 04 00 00 00 00
// 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 7F
// 5D AA A8 E2
// 01 1D
// 00 00 00 00
// 01
// 00
// 00
// 00 01 4D 53 47 00 00 00 00 00
// 5D AA A8 E2
// E2 AE 94 2D
// 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 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 A8 E2
//E2 AE 94 2D
//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 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 09 01 00 06 E7 89 9B E9 80 BC
// 01 00 0F 01 00 0C E5 8F 91 E5 9B BE E7 89 87 E7 BE A4
writeQQ
(
botQQ
)
writeQQ
(
targetQQ
)
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
(
targetQQ
)
writeFully
(
md5
(
buildPacket
{
writeQQ
(
targetQQ
);
writeFully
(
sessionKey
)
}.
readBytes
()))
...
...
@@ -81,12 +108,11 @@ class ClientSendFriendMessagePacket(
writeHex
(
"00 01 4D 53 47 00 00 00 00 00"
)
writeTime
()
writeRandom
(
4
)
writeHex
(
"00 00 00 00 0C 00 86"
)
//TIM最新 0C 00 86
writeHex
(
TIMProtocol
.
messageConstNewest
)
//... 85 E9 BB 91
writeHex
(
"00 00 00 00 0C 00 86"
)
writeHex
(
TIMProtocol
.
messageConstNewest
)
writeZero
(
2
)
message
.
toPacket
().
debugPrint
(
"CHAIN"
)
writePacket
(
message
.
toPacket
())
writePacket
(
message
.
toPacket
(
false
))
/*
//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
...
...
@@ -15,8 +15,8 @@ import net.mamoe.mirai.utils.*
@PacketId
(
0
x00_02u
)
class
ClientSendGroupMessagePacket
(
private
val
botQQ
:
Long
,
private
val
groupId
:
Long
,
//不是 number
private
val
botQQ
:
UInt
,
private
val
groupId
:
UInt
,
//不是 number
private
val
sessionKey
:
ByteArray
,
private
val
message
:
MessageChain
)
:
ClientPacket
()
{
...
...
@@ -28,7 +28,7 @@ class ClientSendGroupMessagePacket(
writeByte
(
0
x2A
)
writeGroup
(
groupId
)
writeLVPacket
{
write
Short
LVPacket
{
writeHex
(
"00 01 01"
)
writeHex
(
"00 00 00 00 00 00 00 4D 53 47 00 00 00 00 00"
)
...
...
@@ -38,7 +38,7 @@ class ClientSendGroupMessagePacket(
writeHex
(
TIMProtocol
.
messageConst1
)
writeZero
(
2
)
writePacket
(
message
.
toPacket
())
writePacket
(
message
.
toPacket
(
true
))
}
/*it.writeByte(0x01)
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
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
// 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
}
inner
class
ResponsePacket
(
val
bot
:
Long
,
val
bot
:
UInt
,
val
sessionKey
:
ByteArray
)
:
ClientPacket
()
{
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
*/
@PacketId
(
0
x00_ECu
)
class
ClientChangeOnlineStatusPacket
(
private
val
bot
:
Long
,
private
val
bot
:
UInt
,
private
val
sessionKey
:
ByteArray
,
private
val
loginStatus
:
OnlineStatus
)
:
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
...
...
@@ -16,7 +16,7 @@ import net.mamoe.mirai.utils.*
*/
@PacketId
(
0
x08_36u
)
class
ClientPasswordSubmissionPacket
constructor
(
private
val
bot
:
Long
,
private
val
bot
:
UInt
,
private
val
password
:
String
,
private
val
loginTime
:
Int
,
private
val
loginIP
:
String
,
...
...
@@ -57,7 +57,7 @@ class ClientPasswordSubmissionPacket constructor(
private
fun
BytePacketBuilder
.
writePart1
(
qq
:
Long
,
qq
:
UInt
,
password
:
String
,
loginTime
:
Int
,
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
...
...
@@ -14,7 +14,7 @@ import net.mamoe.mirai.utils.*
*/
@PacketId
(
0
x00_1Du
)
class
ClientSKeyRequestPacket
(
private
val
qq
:
Long
,
private
val
qq
:
UInt
,
private
val
sessionKey
:
ByteArray
)
:
ClientPacket
()
{
override
fun
encode
(
builder
:
BytePacketBuilder
)
=
with
(
builder
)
{
...
...
@@ -28,7 +28,7 @@ class ClientSKeyRequestPacket(
@PacketId
(
0
x00_1Du
)
class
ClientSKeyRefreshmentRequestPacket
(
private
val
qq
:
Long
,
private
val
qq
:
UInt
,
private
val
sessionKey
:
ByteArray
)
:
ClientPacket
()
{
override
fun
encode
(
builder
:
BytePacketBuilder
)
=
with
(
builder
)
{
...
...
@@ -46,7 +46,7 @@ class ServerSKeyResponsePacket(input: ByteReadPacket) : ServerPacket(input) {
override
fun
decode
()
=
with
(
input
)
{
discardExact
(
4
)
//debugDiscardExact(2)
sKey
=
this
.
readString
(
10
)
sKey
=
this
.
readString
(
10
)
//16??
DebugLogger
.
logPurple
(
"SKey=$sKey"
)
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
...
...
@@ -9,7 +9,7 @@ import net.mamoe.mirai.utils.*
@PacketId
(
0
x08_28u
)
class
ClientSessionRequestPacket
(
private
val
bot
:
Long
,
private
val
bot
:
UInt
,
private
val
serverIp
:
String
,
private
val
token38
:
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
...
...
@@ -60,7 +60,7 @@ class ServerTouchResponsePacket(input: ByteReadPacket) : ServerPacket(input) {
* @author Him188moe
*/
@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
)
{
this
.
writeQQ
(
bot
)
this
.
writeHex
(
TIMProtocol
.
fixVer
)
...
...
@@ -84,7 +84,7 @@ class ClientTouchPacket(private val bot: Long, private val serverIp: String) : C
* @author Him188moe
*/
@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
)
{
this
.
writeQQ
(
qq
)
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.*
*/
@PacketId
(
0
x00_BAu
)
class
ClientCaptchaTransmissionRequestPacket
(
private
val
qq
:
Long
,
private
val
qq
:
UInt
,
private
val
token0825
:
ByteArray
,
private
val
verificationSequence
:
Int
,
private
val
token00BA
:
ByteArray
...
...
@@ -44,7 +44,7 @@ class ClientCaptchaTransmissionRequestPacket(
*/
@PacketId
(
0
x00_BAu
)
class
ClientCaptchaSubmitPacket
(
private
val
qq
:
Long
,
private
val
qq
:
UInt
,
private
val
token0825
:
ByteArray
,
private
val
captcha
:
String
,
private
val
verificationToken
:
IoBuffer
...
...
@@ -83,7 +83,7 @@ class ClientCaptchaSubmitPacket(
*/
@PacketId
(
0
x00_BAu
)
class
ClientCaptchaRefreshPacket
(
private
val
qq
:
Long
,
private
val
qq
:
UInt
,
private
val
token0825
:
ByteArray
)
:
ClientPacket
()
{
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
data class
BotAccount
(
val
account
:
Long
,
//实际上是 UInt
val
account
:
UInt
,
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 {
0
x00_CD_u
->
ServerSendFriendMessageResponsePacket
(
this
)
0
x00_02_u
->
ServerSendGroupMessageResponsePacket
(
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
)
}.
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
import
net.mamoe.mirai.contact.Contact
class
ContactList
<
C
:
Contact
>
:
MutableMap
<
Long
,
C
>
by
mutableMapOf
()
\ No newline at end of file
class
ContactList
<
C
:
Contact
>
:
MutableMap
<
UInt
,
C
>
by
mutableMapOf
()
\ 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
import
kotlinx.io.core.ByteReadPacket
import
kotlinx.io.core.Input
import
kotlinx.io.core.IoBuffer
import
kotlinx.io.core.readBytes
import
kotlinx.io.core.*
internal
object
DebugLogger
:
MiraiLogger
by
PlatformLogger
(
"Packet Debug"
)
...
...
@@ -15,7 +12,7 @@ internal fun ByteArray.debugPrint(name: String): ByteArray {
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
{
val
readBytes
=
this
.
readBytes
()
DebugLogger
.
logPurple
(
name
+
"="
+
readBytes
.
toUHexString
())
...
...
@@ -27,20 +24,33 @@ internal fun Input.debugDiscardExact(n: Number, name: String = "") {
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
{
val
bytes
=
this
.
readBytes
()
DebugLogger
.
logPurple
(
"ByteReadPacket $name="
+
bytes
.
toUHexString
())
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
{
val
bytes
=
this
.
readBytes
()
bytes
.
printColorizedHex
(
name
,
ignoreUntilFirstConst
)
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
()
{
println
(
this
.
hexToBytes
().
stringOfWitch
())
...
...
@@ -54,4 +64,10 @@ internal fun ByteArray.printColorizedHex(name: String = "", ignoreUntilFirstCons
}
expect
fun
compareHex
(
hex1s
:
String
,
hex2s
:
String
):
String
expect
fun
String
.
colorize
(
ignoreUntilFirstConst
:
Boolean
=
false
):
String
\ No newline at end of file
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)
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
:
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
)
{
this
.
writeShort
(
byteArray
.
size
.
toShort
())
this
.
writeFully
(
byteArray
)
}
fun
BytePacketBuilder
.
writeLVPacket
(
packet
:
ByteReadPacket
)
{
fun
BytePacketBuilder
.
write
Short
LVPacket
(
packet
:
ByteReadPacket
)
{
this
.
writeShort
(
packet
.
remaining
.
toShort
())
this
.
writePacket
(
packet
)
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"
)
fun
BytePacketBuilder
.
writeLVString
(
str
:
String
)
=
this
.
writeLVByteArray
(
str
.
toByteArray
())
fun
BytePacketBuilder
.
write
Short
LVString
(
str
:
String
)
=
this
.
writeLVByteArray
(
str
.
toByteArray
())
@Suppress
(
"DEPRECATION"
)
fun
BytePacketBuilder
.
writeLVHex
(
hex
:
String
)
=
this
.
writeLVByteArray
(
hex
.
hexToBytes
())
...
...
@@ -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
(
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
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
import
com.soywiz.klock.DateTime
...
...
@@ -38,10 +40,14 @@ expect fun localIpAddress(): String
/**
* 上传群图片
*/
expect
suspend
fun
httpPost
Group
Image
(
expect
suspend
fun
httpPost
Friend
Image
(
uKeyHex
:
String
,
fileSize
:
Int
,
botNumber
:
Long
,
groupCode
:
Long
,
botNumber
:
UInt
,
qq
:
UInt
,
imageData
:
ByteArray
):
Boolean
\ No newline at end of file
):
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(),
private
fun
ByteArray
.
checkLength
():
ByteArray
{
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
}
\ 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)
fun
String
.
hexToInt
():
Int
=
hexToBytes
().
toUInt
().
toInt
()
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
.
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
import
kotlinx.coroutines.launch
...
...
@@ -18,7 +20,7 @@ import net.mamoe.mirai.utils.ContactList
* @author Him188moe
*/
@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
)
...
...
@@ -71,7 +73,7 @@ actual sealed class Contact actual constructor(bot: Bot, number: Long) : Platfor
* Java 调用 [groupNumberToId] : `Group.groupNumberToId(number)`
* @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
members
:
ContactList
<
QQ
>
//todo members
...
...
@@ -100,7 +102,7 @@ actual class Group actual constructor(bot: Bot, number: Long) : Contact(bot, num
*
* @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
)
{
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 @@
package
net.mamoe.mirai.network.protocol.tim.packet
import
kotlinx.io.core.BytePacketBuilder
import
kotlinx.io.core.writeFully
import
kotlinx.io.core.*
import
net.mamoe.mirai.utils.*
import
java.io.File
import
javax.imageio.ImageIO
actual
typealias
ClientTryGetImageIDPacket
=
ClientTryGetImageIDPacketJvm
fun
main
()
{
val
packet
=
ClientTryGetImageIDPacketJvm
(
1040400290
u
,
"99 82 67 D4 62 20 CA 5D 81 F8 6F 83 EE 8A F7 68"
.
hexToBytes
(),
2978594313
u
,
ImageIO
.
read
(
File
((
"C:\\Users\\Him18\\Desktop\\哈哈哈操.jpg"
))))
println
(
packet
.
packet
.
readBytes
().
toUHexString
())
"89 FC A6 8C 0B"
.
hexToBytes
().
read
{
println
(
readUnsignedVarInt
())
}
}
/**
* 请求上传图片. 将发送图片的 md5, size.
* 请求上传图片. 将发送图片的 md5, size
, width, height
.
* 服务器返回以下之一:
* - 服务器已经存有这个图片 [ServerTryGetImageIDFailedPacket]
* - 服务器未存有, 返回一个 key 用于客户端上传 [ServerTryGetImageIDSuccessPacket]
*
* @author Him188moe
*/
@PacketId
(
0
x03_
88
u
)
@PacketId
(
0
x03_
52
u
)
class
ClientTryGetImageIDPacketJvm
(
private
val
botNumber
:
Long
,
private
val
botNumber
:
UInt
,
private
val
sessionKey
:
ByteArray
,
private
val
groupNumberOrAccount
:
Long
,
private
val
target
:
UInt
,
private
val
image
:
PlatformImage
)
:
ClientPacket
()
{
override
fun
encode
(
builder
:
BytePacketBuilder
)
=
with
(
builder
)
{
this
.
writeRandom
(
2
)
//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
//一次 body
//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
)
this
.
writeHex
(
"04 00 00 00 01 01 01 00 00 68 20 00 00 00 00 00 00 00 00"
)
@PacketVersion
(
date
=
"2019.10.19"
,
timVersion
=
"2.3.2.21173"
)
override
fun
encode
(
builder
:
BytePacketBuilder
)
=
with
(
builder
)
{
writeQQ
(
botNumber
)
//04 00 00 00 01 01 01 00 00 68 20 00 00 00 00 00 00 00 00
writeHex
(
"04 00 00 00 01 2E 01 00 00 69 35 00 00 00 00 00 00 00 00"
)
val
imageData
=
image
.
toByteArray
()
encryptAndWrite
(
sessionKey
)
{
//好友图片
// 00 00 00
// 07 00
// 00 00
// proto
// [4D 08]后文长度
// 01 12
// 03 98
// 01 01
// 08 01
// 12 49
// 08 [A2 FF 8C F0 03](1040400290 varint)
// 10 [DD F1 92 B7 07](1994701021 varint)
// 18 00
// 22 [10](=16) [E9 BA 47 2E 36 ED D4 BF 8C 4F E5 6A CB A0 2D 5E](md5)
// 28 [CE 0E](1870 varint)
// 32 1A
// 39 00
// 51 00
// 24 00
// 32 00
// 4A 00
// 53 00
// 25 00
// 4C 00
// 56 00
// 42 00
// 33 00
// 44 00
// 44 00
// 38 01
// 48 00
// 70 [92 03](402 varint)
// 78 [E3 01](227 varint)
//好友图片
/*
* 00 00 00 07 00 00 00
* [4E 08]后文长度
* 01 12
* 03 98
* 01 01
* 08 01
* 12 4A
* 08 [A2 FF 8C F0 03](varint)
* 10 [DD F1 92 B7 07](varint)
* 18 00//24
* 22 10 72 02 57 44 84 1D 83 FC C0 85 A1 E9 10 AA 9C 2C
* 28 [BD D9 19](421053 varint)
* 32 1A//48
* 49 00
* 49 00
* 25 00
* 45 00
* 5D 00
* 50 00
* 41 00
* 7D 00
* 4F 00
* 56 00
* 46 00
* 4B 00
* 5D 00
* 38 01
* 48 00//78
*
*
* 70 [80 14]
* 78 [A0 0B]//84
*/
val
byteArray
=
image
.
toByteArray
()
this
.
encryptAndWrite
(
sessionKey
)
{
writeZero
(
3
)
writeHex
(
"07 00"
)
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"
)
writeUVarInt
(
image
.
width
.
toUInt
())
writeHex
(
"58"
)
writeUVarInt
(
image
.
height
.
toUInt
())
writeHex
(
"60 04"
)
writeHex
(
"6A"
)
writeHex
(
"05"
)
writeHex
(
"32 36 36 35 36"
)
writeHex
(
"70 00"
)
writeHex
(
"78 03"
)
writeHex
(
"80 01"
)
writeHex
(
"00"
)
writeUShort
(
0
x07_00u
)
writeZero
(
1
)
//proto
val
packet
=
buildPacket
{
writeUByte
(
0
x08u
)
writeUShort
(
0
x01_12u
)
writeUShort
(
0
x03_98u
)
writeUShort
(
0
x01_01u
)
writeUShort
(
0
x08_01u
)
writeUShort
(
0
x12_47u
)
//?似乎会变
writeUByte
(
0
x08u
)
writeUVarInt
(
target
)
//todo 这两qq号反过来放也tm可以成功
writeUByte
(
0
x10u
)
writeUVarInt
(
botNumber
)
writeUShort
(
0
x18_00u
)
writeUByte
(
0
x22u
)
writeUByte
(
0
x10u
)
writeFully
(
md5
(
imageData
))
writeUByte
(
0
x28u
)
writeUVarInt
(
imageData
.
size
.
toUInt
())
writeUByte
(
0
x32u
)
//长度应为1A
writeUVarintLVPacket
{
writeUShort
(
0
x28_00u
)
writeUShort
(
0
x46_00u
)
writeUShort
(
0
x51_00u
)
writeUShort
(
0
x56_00u
)
writeUShort
(
0
x4B_00u
)
writeUShort
(
0
x41_00u
)
writeUShort
(
0
x49_00u
)
writeUShort
(
0
x25_00u
)
writeUShort
(
0
x4B_00u
)
writeUShort
(
0
x24_00u
)
writeUShort
(
0
x55_00u
)
writeUShort
(
0
x30_00u
)
writeUShort
(
0
x24_00u
)
}
writeUShort
(
0
x38_01u
)
writeUShort
(
0
x48_00u
)
writeUByte
(
0
x70u
)
writeUVarInt
(
image
.
width
.
toUInt
())
writeUByte
(
0
x78u
)
writeUVarInt
(
image
.
height
.
toUInt
())
}
writeShort
((
packet
.
remaining
-
7
).
toShort
())
//why?
writePacket
(
packet
)
//println(this.build().readBytes().toUHexString())
}
}
}
\ No newline at end of file
mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/PlatformImageJvm.kt
View file @
fdf50e4d
...
...
@@ -7,4 +7,4 @@ import javax.imageio.ImageIO
actual
typealias
PlatformImage
=
BufferedImage
@JvmOverloads
actual
fun
BufferedImage
.
toByteArray
(
formatName
:
String
):
ByteArray
=
ByteArrayOutputStream
().
use
{
ImageIO
.
write
(
this
,
"JPG"
,
it
);
it
.
toByteArray
()
}
\ No newline at end of file
actual
fun
BufferedImage
.
toByteArray
(
formatName
:
String
):
ByteArray
=
ByteArrayOutputStream
().
use
{
ImageIO
.
write
(
this
,
"PNG"
,
it
);
it
.
toByteArray
()
}
\ 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
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.withContext
import
org.jsoup.Connection
import
org.jsoup.Jsoup
import
java.net.HttpURLConnection
import
java.net.InetAddress
import
java.net.URL
import
java.security.MessageDigest
import
java.util.zip.CRC32
...
...
@@ -19,36 +19,62 @@ actual fun solveIpAddress(hostname: String): String = InetAddress.getByName(host
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
,
fileSize
:
Int
,
botNumber
:
Long
,
groupCode
:
Long
,
botNumber
:
UInt
,
qq
:
UInt
,
imageData
:
ByteArray
):
Boolean
=
Jsoup
.
connect
(
"http://htdata2.qq.com/cgi-bin/httpconn?htcmd=0x6ff0071&ver=5515&term=pc"
+
):
Boolean
{
/*Jsoup
//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(" ", "") +
"&filezise=" + fileSize +
"&range=" + "0" +
"&uin="
+
botNumber
+
"&groupcode="
+
groupCode
)
.
userAgent
(
"QQClient"
)
"&uin=" + botNumber.toLong())
//.userAgent("QQClient")
.header("Content-Length", fileSize.toString())
.
requestBody
(
String
(
imageData
))
.requestBody(String(imageData
, Charset.forName("ASCII")
))
.method(Connection.Method.POST)
.ignoreContentType(true)
.let {
withContext(Dispatchers.IO) {
it.execute()
}
}
/*
val conn = URL(builder).openConnection() as HttpURLConnection
conn.setRequestProperty("User-Agent", "QQClient")
conn.setRequestProperty("Content-Length", "" + fileSize)
conn.requestMethod = "POST"
conn.doOutput = true
conn.outputStream.write(img)
conn.connect()*/
.
statusCode
()
==
200
\ No newline at end of file
};*/
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
(
"Content-Length"
,
""
+
fileSize
)
conn
.
requestMethod
=
"POST"
conn
.
doOutput
=
true
conn
.
outputStream
.
buffered
().
write
(
imageData
)
conn
.
connect
()
println
(
conn
.
responseMessage
)
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.GlobalScope
import
kotlinx.coroutines.runBlocking
...
...
@@ -44,7 +46,7 @@ suspend fun main() {
runBlocking
{
val
bot
=
Bot
(
BotAccount
(
qq
,
qq
.
toUInt
()
,
if
(
password
.
endsWith
(
"."
))
password
.
substring
(
0
,
password
.
length
-
1
)
else
password
),
Console
()
...
...
mirai-debug/build.gradle
View file @
fdf50e4d
...
...
@@ -8,6 +8,8 @@ dependencies {
implementation
rootProject
.
ext
.
coroutineCommon
implementation
rootProject
.
ext
.
kotlinJvm
implementation
rootProject
.
ext
.
kotlinxIOJvm
compile
"org.jetbrains.kotlin:kotlin-reflect:1.3.50"
implementation
'org.jsoup:jsoup:1.12.1'
}
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.packet.IPPacket
...
...
@@ -31,7 +31,7 @@ object Main {
jpcap
=
JpcapCaptor
.
openDevice
(
devices
[
0
],
caplen
,
promiscCheck
,
50
)
while
(
true
)
{
assert
(
jpcap
!=
null
)
val
pk
=
jpcap
!!
.
packet
val
pk
=
jpcap
!!
.
packet
?:
continue
if
(
pk
is
IPPacket
&&
pk
.
version
.
toInt
()
==
4
)
{
if
(
pk
is
UDPPacket
)
{
...
...
@@ -47,6 +47,7 @@ object Main {
}
}
else
{
try
{
//println("发出包全部=${pk.data.toUHexString()}")
dataSent
(
pk
.
data
)
println
()
}
catch
(
e
:
Throwable
)
{
...
...
@@ -73,20 +74,36 @@ object Main {
* 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
qq
:
UInt
=
1040400290
u
fun
dataReceived
(
data
:
ByteArray
)
{
println
(
"--------------"
)
println
(
"接收数据包"
)
//println("raw = " + data.toUHexString())
data
.
read
{
discardExact
(
3
)
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
(
"解密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
)
{
...
...
@@ -118,15 +135,38 @@ object Main {
}
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
(
"---------------------------"
)
discardExact
(
3
)
//head
val
idHex
=
readBytes
(
4
).
toUHexString
()
println
(
"发出包ID = $idHex"
)
readUInt
()
//客户端登录的qq
println
(
"TIM的fixVer2="
+
readBytes
(
TIMProtocol
.
fixVer2
.
hexToBytes
().
size
).
toUHexString
())
if
(
readUInt
()
!=
qq
)
{
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
()
println
(
"解密body = ${encryptedBody.decryptBy(sessionKey).toUHexString()}"
)
try
{
println
(
"解密body=${encryptedBody.decryptBy(sessionKey).toUHexString()}"
)
}
catch
(
e
:
DecryptionFailedException
)
{
println
(
"密文="
+
encryptedBody
.
toUHexString
())
println
(
"解密body=解密失败"
)
}
encryptedBody
.
read
{
...
...
@@ -139,13 +179,18 @@ object Main {
val
messageData
=
raw
.
decryptBy
(
sessionKey
)
println
(
"解密结果: "
+
messageData
.
toUHexString
())
println
(
"尝试解消息"
)
messageData
.
read
{
discardExact
(
4
+
4
+
12
+
2
+
4
+
4
+
16
+
2
+
2
+
4
+
2
+
16
+
4
+
4
+
7
+
15
+
2
+
1
)
val
chain
=
readMessageChain
()
println
(
chain
)
try
{
messageData
.
read
{
discardExact
(
4
+
4
+
12
+
2
+
4
+
4
+
16
+
2
+
2
+
4
+
2
+
16
+
4
+
4
+
7
+
15
+
2
+
1
)
val
chain
=
readMessageChain
()
println
(
chain
)
}
}
catch
(
e
:
Exception
)
{
println
(
"失败"
)
}
}
...
...
mirai-demos/mirai-demo-1/src/main/java/demo1/Main.kt
View file @
fdf50e4d
@
file
:
Suppress
(
"EXPERIMENTAL_UNSIGNED_LITERALS"
,
"EXPERIMENTAL_API_USAGE"
)
package
demo1
import
kotlinx.coroutines.delay
import
kotlinx.coroutines.withTimeoutOrNull
import
net.mamoe.mirai.Bot
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.GroupMessageEvent
import
net.mamoe.mirai.event.subscribeAll
...
...
@@ -10,12 +14,16 @@ import net.mamoe.mirai.event.subscribeAlways
import
net.mamoe.mirai.event.subscribeUntilFalse
import
net.mamoe.mirai.login
import
net.mamoe.mirai.message.Image
import
net.mamoe.mirai.message.ImageId
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.utils.BotAccount
import
net.mamoe.mirai.utils.MiraiLogger
import
net.mamoe.mirai.utils.PlatformLogger
import
net.mamoe.mirai.network.protocol.tim.packet.uploadImage
import
net.mamoe.mirai.network.session
import
net.mamoe.mirai.qqAccount
import
net.mamoe.mirai.utils.*
import
java.io.File
import
javax.imageio.ImageIO
private
fun
readTestAccount
():
BotAccount
?
{
val
file
=
File
(
"testAccount.txt"
)
...
...
@@ -25,7 +33,7 @@ private fun readTestAccount(): BotAccount? {
val
lines
=
file
.
readLines
()
return
try
{
BotAccount
(
lines
[
0
].
to
Long
(),
lines
[
1
])
BotAccount
(
lines
[
0
].
to
UInt
(),
lines
[
1
])
}
catch
(
e
:
IndexOutOfBoundsException
)
{
null
}
...
...
@@ -34,7 +42,7 @@ private fun readTestAccount(): BotAccount? {
@Suppress
(
"UNUSED_VARIABLE"
)
suspend
fun
main
()
{
val
bot
=
Bot
(
readTestAccount
()
?:
BotAccount
(
//填写你的账号
account
=
1994701121
,
account
=
1994701121
u
,
password
=
"123456"
),
PlatformLogger
())
...
...
@@ -61,20 +69,31 @@ suspend fun main() {
"复读"
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 ->
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 ->
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