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
86d64f02
Commit
86d64f02
authored
Sep 13, 2019
by
liujiahua123123
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/master'
parents
5c00a59a
ff0acc87
Changes
58
Hide whitespace changes
Inline
Side-by-side
Showing
58 changed files
with
2244 additions
and
750 deletions
+2244
-750
mirai-api/src/main/java/net/mamoe/mirai/Bot.java
mirai-api/src/main/java/net/mamoe/mirai/Bot.java
+15
-0
mirai-api/src/main/java/net/mamoe/mirai/utils/BotAccount.java
...i-api/src/main/java/net/mamoe/mirai/utils/BotAccount.java
+0
-0
mirai-core/pom.xml
mirai-core/pom.xml
+31
-1
mirai-core/src/main/java/net/mamoe/mirai/Bot.java
mirai-core/src/main/java/net/mamoe/mirai/Bot.java
+4
-3
mirai-core/src/main/java/net/mamoe/mirai/MiraiServer.java
mirai-core/src/main/java/net/mamoe/mirai/MiraiServer.java
+17
-10
mirai-core/src/main/java/net/mamoe/mirai/contact/Contact.kt
mirai-core/src/main/java/net/mamoe/mirai/contact/Contact.kt
+10
-0
mirai-core/src/main/java/net/mamoe/mirai/contact/Group.kt
mirai-core/src/main/java/net/mamoe/mirai/contact/Group.kt
+1
-1
mirai-core/src/main/java/net/mamoe/mirai/contact/QQ.kt
mirai-core/src/main/java/net/mamoe/mirai/contact/QQ.kt
+2
-2
mirai-core/src/main/java/net/mamoe/mirai/message/FaceID.java
mirai-core/src/main/java/net/mamoe/mirai/message/FaceID.java
+2
-0
mirai-core/src/main/java/net/mamoe/mirai/message/Message.kt
mirai-core/src/main/java/net/mamoe/mirai/message/Message.kt
+12
-34
mirai-core/src/main/java/net/mamoe/mirai/message/defaults/Face.kt
...re/src/main/java/net/mamoe/mirai/message/defaults/Face.kt
+19
-7
mirai-core/src/main/java/net/mamoe/mirai/message/defaults/Image.kt
...e/src/main/java/net/mamoe/mirai/message/defaults/Image.kt
+30
-47
mirai-core/src/main/java/net/mamoe/mirai/message/defaults/MessageChain.kt
...ain/java/net/mamoe/mirai/message/defaults/MessageChain.kt
+7
-11
mirai-core/src/main/java/net/mamoe/mirai/message/defaults/PlainText.kt
...c/main/java/net/mamoe/mirai/message/defaults/PlainText.kt
+4
-4
mirai-core/src/main/java/net/mamoe/mirai/message/defaults/UnsolvedImage.kt
...in/java/net/mamoe/mirai/message/defaults/UnsolvedImage.kt
+63
-0
mirai-core/src/main/java/net/mamoe/mirai/network/BotNetworkHandler.kt
...rc/main/java/net/mamoe/mirai/network/BotNetworkHandler.kt
+64
-0
mirai-core/src/main/java/net/mamoe/mirai/network/BotNetworkHandlerImpl.kt
...ain/java/net/mamoe/mirai/network/BotNetworkHandlerImpl.kt
+403
-0
mirai-core/src/main/java/net/mamoe/mirai/network/LoginSession.kt
...ore/src/main/java/net/mamoe/mirai/network/LoginSession.kt
+98
-0
mirai-core/src/main/java/net/mamoe/mirai/network/Protocol.kt
mirai-core/src/main/java/net/mamoe/mirai/network/Protocol.kt
+4
-2
mirai-core/src/main/java/net/mamoe/mirai/network/handler/ActionPacketHandler.kt
...va/net/mamoe/mirai/network/handler/ActionPacketHandler.kt
+213
-0
mirai-core/src/main/java/net/mamoe/mirai/network/handler/DataPacketSocket.kt
.../java/net/mamoe/mirai/network/handler/DataPacketSocket.kt
+53
-0
mirai-core/src/main/java/net/mamoe/mirai/network/handler/MessagePacketHandler.kt
...a/net/mamoe/mirai/network/handler/MessagePacketHandler.kt
+91
-0
mirai-core/src/main/java/net/mamoe/mirai/network/handler/PacketHandler.kt
...ain/java/net/mamoe/mirai/network/handler/PacketHandler.kt
+42
-0
mirai-core/src/main/java/net/mamoe/mirai/network/handler/TemporaryPacketHandler.kt
...net/mamoe/mirai/network/handler/TemporaryPacketHandler.kt
+49
-0
mirai-core/src/main/java/net/mamoe/mirai/network/packet/ClientPacket.kt
.../main/java/net/mamoe/mirai/network/packet/ClientPacket.kt
+20
-41
mirai-core/src/main/java/net/mamoe/mirai/network/packet/GradeInfo.kt
...src/main/java/net/mamoe/mirai/network/packet/GradeInfo.kt
+1
-1
mirai-core/src/main/java/net/mamoe/mirai/network/packet/Heartbeat.kt
...src/main/java/net/mamoe/mirai/network/packet/Heartbeat.kt
+1
-1
mirai-core/src/main/java/net/mamoe/mirai/network/packet/SKey.kt
...core/src/main/java/net/mamoe/mirai/network/packet/SKey.kt
+4
-2
mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerEvent.kt
...c/main/java/net/mamoe/mirai/network/packet/ServerEvent.kt
+16
-13
mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerPacket.kt
.../main/java/net/mamoe/mirai/network/packet/ServerPacket.kt
+97
-18
mirai-core/src/main/java/net/mamoe/mirai/network/packet/Session.kt
...e/src/main/java/net/mamoe/mirai/network/packet/Session.kt
+39
-38
mirai-core/src/main/java/net/mamoe/mirai/network/packet/Touch.kt
...ore/src/main/java/net/mamoe/mirai/network/packet/Touch.kt
+11
-9
mirai-core/src/main/java/net/mamoe/mirai/network/packet/VerificationCode.kt
...n/java/net/mamoe/mirai/network/packet/VerificationCode.kt
+11
-40
mirai-core/src/main/java/net/mamoe/mirai/network/packet/action/AddContact.kt
.../java/net/mamoe/mirai/network/packet/action/AddContact.kt
+6
-4
mirai-core/src/main/java/net/mamoe/mirai/network/packet/action/ClientSendFriendMessagePacket.kt
...ai/network/packet/action/ClientSendFriendMessagePacket.kt
+2
-2
mirai-core/src/main/java/net/mamoe/mirai/network/packet/action/ClientSendGroupMessagePacket.kt
...rai/network/packet/action/ClientSendGroupMessagePacket.kt
+11
-7
mirai-core/src/main/java/net/mamoe/mirai/network/packet/image/ClientGetGroupImageIDPacket.kt
...mirai/network/packet/image/ClientGetGroupImageIDPacket.kt
+0
-35
mirai-core/src/main/java/net/mamoe/mirai/network/packet/image/UploadGroupImage.kt
.../net/mamoe/mirai/network/packet/image/UploadGroupImage.kt
+132
-0
mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ClientChangeOnlineStatusPacket.kt
...ai/network/packet/login/ClientChangeOnlineStatusPacket.kt
+4
-2
mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ClientLogin.kt
.../java/net/mamoe/mirai/network/packet/login/ClientLogin.kt
+10
-10
mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/LoginState.kt
...n/java/net/mamoe/mirai/network/packet/login/LoginState.kt
+0
-5
mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponseKeyExchangePacket.kt
...work/packet/login/ServerLoginResponseKeyExchangePacket.kt
+4
-4
mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponsePasswordVerifiedPacket.kt
...packet/login/ServerLoginResponsePasswordVerifiedPacket.kt
+6
-4
mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponseVerificationCodeInitPacket.kt
...et/login/ServerLoginResponseVerificationCodeInitPacket.kt
+6
-4
mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginSuccessPacket.kt
...oe/mirai/network/packet/login/ServerLoginSuccessPacket.kt
+2
-0
mirai-core/src/main/java/net/mamoe/mirai/utils/ContactList.java
...core/src/main/java/net/mamoe/mirai/utils/ContactList.java
+1
-2
mirai-core/src/main/java/net/mamoe/mirai/utils/ImageNetworkUtils.java
...rc/main/java/net/mamoe/mirai/utils/ImageNetworkUtils.java
+19
-24
mirai-core/src/main/java/net/mamoe/mirai/utils/MiraiLogger.kt
...i-core/src/main/java/net/mamoe/mirai/utils/MiraiLogger.kt
+24
-17
mirai-core/src/main/java/net/mamoe/mirai/utils/MiraiSynchronizedLinkedHashMap.java
...net/mamoe/mirai/utils/MiraiSynchronizedLinkedHashMap.java
+6
-6
mirai-core/src/main/java/net/mamoe/mirai/utils/MiraiSynchronizedLinkedList.java
...va/net/mamoe/mirai/utils/MiraiSynchronizedLinkedList.java
+195
-0
mirai-core/src/main/java/net/mamoe/mirai/utils/ProtocolBuff.kt
...-core/src/main/java/net/mamoe/mirai/utils/ProtocolBuff.kt
+0
-48
mirai-core/src/main/java/net/mamoe/mirai/utils/TEA.kt
mirai-core/src/main/java/net/mamoe/mirai/utils/TEA.kt
+205
-213
mirai-core/src/main/java/net/mamoe/mirai/utils/Tested.kt
mirai-core/src/main/java/net/mamoe/mirai/utils/Tested.kt
+1
-1
mirai-core/src/main/java/net/mamoe/mirai/utils/Utils.kt
mirai-core/src/main/java/net/mamoe/mirai/utils/Utils.kt
+22
-12
mirai-core/src/main/java/net/mamoe/mirai/utils/Varint.kt
mirai-core/src/main/java/net/mamoe/mirai/utils/Varint.kt
+133
-0
mirai-core/src/main/java/net/mamoe/mirai/utils/config/MiraiConfigSection.java
...java/net/mamoe/mirai/utils/config/MiraiConfigSection.java
+2
-1
mirai-core/src/test/java/PacketTest.kt
mirai-core/src/test/java/PacketTest.kt
+0
-47
pom.xml
pom.xml
+19
-17
No files found.
mirai-api/src/main/java/net/mamoe/mirai/Bot.java
0 → 100644
View file @
86d64f02
package
net.mamoe.mirai
;
import
net.mamoe.mirai.utils.BotAccount
;
import
java.io.Closeable
;
/**
* @author Him188moe
*/
public
interface
Bot
extends
Closeable
{
BotAccount
getAccount
();
// TODO: 2019/9/13 add more
}
mirai-
core
/src/main/java/net/mamoe/mirai/utils/BotAccount.java
→
mirai-
api
/src/main/java/net/mamoe/mirai/utils/BotAccount.java
View file @
86d64f02
File moved
mirai-core/pom.xml
View file @
86d64f02
...
@@ -17,6 +17,31 @@
...
@@ -17,6 +17,31 @@
</parent>
</parent>
<dependencies>
<dependencies>
<dependency>
<groupId>
org.pcap4j
</groupId>
<artifactId>
pcap4j-core
</artifactId>
<version>
1.8.2
</version>
<scope>
compile
</scope>
</dependency>
<dependency>
<groupId>
org.pcap4j
</groupId>
<artifactId>
pcap4j-packetfactory-static
</artifactId>
<version>
1.8.2
</version>
<scope>
compile
</scope>
</dependency>
<dependency>
<groupId>
net.mamoe
</groupId>
<artifactId>
mirai-api
</artifactId>
<version>
1.0
</version>
<scope>
compile
</scope>
</dependency>
<dependency>
<groupId>
com.google.protobuf
</groupId>
<artifactId>
protobuf-java
</artifactId>
</dependency>
<dependency>
<dependency>
<groupId>
org.jetbrains.kotlinx
</groupId>
<groupId>
org.jetbrains.kotlinx
</groupId>
<artifactId>
kotlinx-coroutines-core
</artifactId>
<artifactId>
kotlinx-coroutines-core
</artifactId>
...
@@ -56,7 +81,12 @@
...
@@ -56,7 +81,12 @@
<dependency>
<dependency>
<groupId>
org.jsoup
</groupId>
<groupId>
org.jsoup
</groupId>
<artifactId>
jsoup
</artifactId>
<artifactId>
jsoup
</artifactId>
<version>
1.12.1
</version>
<scope>
compile
</scope>
</dependency>
<dependency>
<groupId>
org.ini4j
</groupId>
<artifactId>
ini4j
</artifactId>
<scope>
compile
</scope>
<scope>
compile
</scope>
</dependency>
</dependency>
...
...
mirai-core/src/main/java/net/mamoe/mirai/Bot.java
View file @
86d64f02
...
@@ -4,6 +4,7 @@ import lombok.Getter;
...
@@ -4,6 +4,7 @@ import lombok.Getter;
import
net.mamoe.mirai.contact.Group
;
import
net.mamoe.mirai.contact.Group
;
import
net.mamoe.mirai.contact.QQ
;
import
net.mamoe.mirai.contact.QQ
;
import
net.mamoe.mirai.network.BotNetworkHandler
;
import
net.mamoe.mirai.network.BotNetworkHandler
;
import
net.mamoe.mirai.network.BotNetworkHandlerImpl
;
import
net.mamoe.mirai.utils.BotAccount
;
import
net.mamoe.mirai.utils.BotAccount
;
import
net.mamoe.mirai.utils.ContactList
;
import
net.mamoe.mirai.utils.ContactList
;
import
net.mamoe.mirai.utils.config.MiraiConfigSection
;
import
net.mamoe.mirai.utils.config.MiraiConfigSection
;
...
@@ -19,7 +20,7 @@ import java.util.concurrent.atomic.AtomicInteger;
...
@@ -19,7 +20,7 @@ import java.util.concurrent.atomic.AtomicInteger;
* <br>
* <br>
* {@link Bot} 由 3 个模块组成.
* {@link Bot} 由 3 个模块组成.
* {@linkplain ContactSystem 联系人管理}: 可通过 {@link Bot#contacts} 访问
* {@linkplain ContactSystem 联系人管理}: 可通过 {@link Bot#contacts} 访问
* {@linkplain BotNetworkHandler 网络处理器}: 可通过 {@link Bot#network} 访问
* {@linkplain BotNetworkHandler
Impl
网络处理器}: 可通过 {@link Bot#network} 访问
* {@linkplain BotAccount 机器人账号信息}: 可通过 {@link Bot#account} 访问
* {@linkplain BotAccount 机器人账号信息}: 可通过 {@link Bot#account} 访问
* <br>
* <br>
* 若你需要得到机器人的 QQ 账号, 请访问 {@link Bot#account}
* 若你需要得到机器人的 QQ 账号, 请访问 {@link Bot#account}
...
@@ -29,7 +30,7 @@ import java.util.concurrent.atomic.AtomicInteger;
...
@@ -29,7 +30,7 @@ import java.util.concurrent.atomic.AtomicInteger;
* Bot that is the base of the whole program.
* Bot that is the base of the whole program.
* It consists of
* It consists of
* a {@link ContactSystem}, which manage contacts such as {@link QQ} and {@link Group};
* a {@link ContactSystem}, which manage contacts such as {@link QQ} and {@link Group};
* a {@link BotNetworkHandler}, which manages the connection to the server;
* a {@link BotNetworkHandler
Impl
}, which manages the connection to the server;
* a {@link BotAccount}, which stores the account information(e.g. qq number the bot)
* a {@link BotAccount}, which stores the account information(e.g. qq number the bot)
* <br>
* <br>
* To get all the QQ contacts, access {@link Bot#account}
* To get all the QQ contacts, access {@link Bot#account}
...
@@ -118,7 +119,7 @@ public final class Bot implements Closeable {
...
@@ -118,7 +119,7 @@ public final class Bot implements Closeable {
Objects
.
requireNonNull
(
owners
);
Objects
.
requireNonNull
(
owners
);
this
.
account
=
account
;
this
.
account
=
account
;
this
.
owners
=
Collections
.
unmodifiableList
(
owners
);
this
.
owners
=
Collections
.
unmodifiableList
(
owners
);
this
.
network
=
new
BotNetworkHandler
(
this
);
this
.
network
=
new
BotNetworkHandler
Impl
(
this
);
}
}
...
...
mirai-core/src/main/java/net/mamoe/mirai/MiraiServer.java
View file @
86d64f02
...
@@ -212,22 +212,29 @@ public final class MiraiServer {
...
@@ -212,22 +212,29 @@ public final class MiraiServer {
}
}
String
qqList
=
"3150499752----1234567890\n"
+
String
qqList
=
"3119292829----987654321\n"
+
"2573990098----qq123456789\n"
+
"2399148773----12345678910\n"
+
"3303923865----q123456789\n"
+
"3145561616----987654321\n"
+
"3349933294----q123456789\n"
+
"2374150554----12345678910\n"
+
"3303708824----q123456789\n"
+
"2375307394----12345678910\n"
+
"3227036647----q123456789\n"
+
"2401645747----12345678910\n"
+
"3451394431----q123456789\n"
+
"1515419818----1234567890\n"
+
"3533243484----q123456789\n"
+
"3107367848----987654321\n"
;
"3364512686----q123456789\n"
+
"3137567463----q123456789\n"
+
"3414786399----q123456789\n"
+
"3347405939----q123456789\n"
+
"3544089622----q123456789\n"
+
"3108512993----q123456789\n"
+
"2985563549----q123456789\n"
+
"3463531892----q123456789\n"
;
private
Bot
getAvailableBot
()
throws
ExecutionException
,
InterruptedException
{
private
Bot
getAvailableBot
()
throws
ExecutionException
,
InterruptedException
{
for
(
String
it
:
qqList
.
split
(
"\n"
))
{
for
(
String
it
:
qqList
.
split
(
"\n"
))
{
var
strings
=
it
.
split
(
"----"
);
var
strings
=
it
.
split
(
"----"
);
var
bot
=
new
Bot
(
new
BotAccount
(
Long
.
parseLong
(
strings
[
0
]),
strings
[
1
]),
List
.
of
());
var
bot
=
new
Bot
(
new
BotAccount
(
Long
.
parseLong
(
strings
[
0
]),
strings
[
1
]),
List
.
of
());
if
(
bot
.
network
.
tryLogin
$mirai_core
(
).
get
()
==
LoginState
.
SUCCESS
)
{
if
(
bot
.
network
.
tryLogin
(
200
).
get
()
==
LoginState
.
SUCCESS
)
{
MiraiLoggerKt
.
success
(
bot
,
"Login succeed"
);
MiraiLoggerKt
.
success
(
bot
,
"Login succeed"
);
return
bot
;
return
bot
;
}
}
...
...
mirai-core/src/main/java/net/mamoe/mirai/contact/Contact.kt
View file @
86d64f02
...
@@ -4,6 +4,9 @@ import net.mamoe.mirai.Bot
...
@@ -4,6 +4,9 @@ import net.mamoe.mirai.Bot
import
net.mamoe.mirai.message.Message
import
net.mamoe.mirai.message.Message
import
net.mamoe.mirai.message.defaults.MessageChain
import
net.mamoe.mirai.message.defaults.MessageChain
import
net.mamoe.mirai.message.defaults.PlainText
import
net.mamoe.mirai.message.defaults.PlainText
import
net.mamoe.mirai.message.defaults.UnsolvedImage
import
net.mamoe.mirai.network.LoginSession
import
java.util.concurrent.CompletableFuture
/**
/**
* 联系人.
* 联系人.
...
@@ -20,6 +23,13 @@ abstract class Contact internal constructor(val bot: Bot, val number: Long) {
...
@@ -20,6 +23,13 @@ abstract class Contact internal constructor(val bot: Bot, val number: Long) {
*/
*/
abstract
fun
sendMessage
(
message
:
MessageChain
)
abstract
fun
sendMessage
(
message
:
MessageChain
)
/**
* 上传图片
*/
fun
uploadImage
(
session
:
LoginSession
,
image
:
UnsolvedImage
):
CompletableFuture
<
Unit
>
{
return
image
.
upload
(
session
,
this
)
}
fun
sendMessage
(
message
:
Message
)
{
fun
sendMessage
(
message
:
Message
)
{
if
(
message
is
MessageChain
)
{
if
(
message
is
MessageChain
)
{
return
sendMessage
(
message
)
return
sendMessage
(
message
)
...
...
mirai-core/src/main/java/net/mamoe/mirai/contact/Group.kt
View file @
86d64f02
...
@@ -26,7 +26,7 @@ class Group(bot: Bot, number: Long) : Contact(bot, number), Closeable {
...
@@ -26,7 +26,7 @@ class Group(bot: Bot, number: Long) : Contact(bot, number), Closeable {
val
members
=
ContactList
<
QQ
>()
val
members
=
ContactList
<
QQ
>()
override
fun
sendMessage
(
message
:
MessageChain
)
{
override
fun
sendMessage
(
message
:
MessageChain
)
{
bot
.
network
.
message
Handler
.
sendGroupMessage
(
this
,
message
)
bot
.
network
.
message
.
sendGroupMessage
(
this
,
message
)
}
}
override
fun
sendXMLMessage
(
message
:
String
)
{
override
fun
sendXMLMessage
(
message
:
String
)
{
...
...
mirai-core/src/main/java/net/mamoe/mirai/contact/QQ.kt
View file @
86d64f02
...
@@ -12,14 +12,14 @@ import net.mamoe.mirai.message.defaults.MessageChain
...
@@ -12,14 +12,14 @@ import net.mamoe.mirai.message.defaults.MessageChain
* Java 获取 qq 号: `qq.getNumber()`
* Java 获取 qq 号: `qq.getNumber()`
* Java 获取所属 bot: `qq.getBot()`
* Java 获取所属 bot: `qq.getBot()`
*
*
* A QQ instance helps you to receive message from or send message to.
* A QQ instance helps you to receive message from or send
Packet
message to.
* Notice that, one QQ instance belong to one [Bot], that is, QQ instances from different [Bot] are NOT the same.
* Notice that, one QQ instance belong to one [Bot], that is, QQ instances from different [Bot] are NOT the same.
*
*
* @author Him188moe
* @author Him188moe
*/
*/
class
QQ
(
bot
:
Bot
,
number
:
Long
)
:
Contact
(
bot
,
number
)
{
class
QQ
(
bot
:
Bot
,
number
:
Long
)
:
Contact
(
bot
,
number
)
{
override
fun
sendMessage
(
message
:
MessageChain
)
{
override
fun
sendMessage
(
message
:
MessageChain
)
{
bot
.
network
.
message
Handler
.
sendFriendMessage
(
this
,
message
)
bot
.
network
.
message
.
sendFriendMessage
(
this
,
message
)
}
}
override
fun
sendXMLMessage
(
message
:
String
)
{
override
fun
sendXMLMessage
(
message
:
String
)
{
...
...
mirai-core/src/main/java/net/mamoe/mirai/message/FaceID.java
View file @
86d64f02
...
@@ -4,6 +4,8 @@ package net.mamoe.mirai.message;
...
@@ -4,6 +4,8 @@ package net.mamoe.mirai.message;
* @author Him188moe
* @author Him188moe
*/
*/
public
enum
FaceID
{
public
enum
FaceID
{
unknown
(
0xff
),
Face_jingya
(
0
),
Face_jingya
(
0
),
Face_piezui
(
1
),
Face_piezui
(
1
),
Face_se
(
2
),
Face_se
(
2
),
...
...
mirai-core/src/main/java/net/mamoe/mirai/message/Message.kt
View file @
86d64f02
...
@@ -2,10 +2,7 @@ package net.mamoe.mirai.message
...
@@ -2,10 +2,7 @@ package net.mamoe.mirai.message
import
net.mamoe.mirai.contact.Contact
import
net.mamoe.mirai.contact.Contact
import
net.mamoe.mirai.contact.QQ
import
net.mamoe.mirai.contact.QQ
import
net.mamoe.mirai.message.defaults.At
import
net.mamoe.mirai.message.defaults.*
import
net.mamoe.mirai.message.defaults.Image
import
net.mamoe.mirai.message.defaults.MessageChain
import
net.mamoe.mirai.message.defaults.PlainText
import
java.awt.image.BufferedImage
import
java.awt.image.BufferedImage
import
java.io.File
import
java.io.File
import
java.util.*
import
java.util.*
...
@@ -106,41 +103,22 @@ abstract class Message {
...
@@ -106,41 +103,22 @@ abstract class Message {
* @param tail tail
* @param tail tail
* @return message connected
* @return message connected
*/
*/
open
fun
concat
(
tail
:
Message
):
Message
{
open
fun
concat
(
tail
:
Message
):
Message
Chain
{
return
MessageChain
(
this
,
Objects
.
requireNonNull
(
tail
))
return
MessageChain
(
this
,
Objects
.
requireNonNull
(
tail
))
}
}
fun
concat
(
tail
:
String
):
Message
{
fun
concat
(
tail
:
String
):
Message
Chain
{
return
concat
(
PlainText
(
tail
))
return
concat
(
PlainText
(
tail
))
}
}
fun
withImage
(
imageId
:
String
):
Message
{
infix
fun
withImage
(
imageId
:
String
):
MessageChain
=
this
+
Image
(
imageId
)
fun
withImage
(
filename
:
String
,
image
:
BufferedImage
):
MessageChain
=
this
+
UnsolvedImage
(
filename
,
image
)
infix
fun
withImage
(
imageFile
:
File
):
MessageChain
=
this
+
UnsolvedImage
(
imageFile
)
// TODO: 2019/9/1
infix
fun
withAt
(
target
:
QQ
):
MessageChain
=
this
+
target
.
at
()
return
this
infix
fun
withAt
(
target
:
Long
):
MessageChain
=
this
+
At
(
target
)
}
fun
withImage
(
image
:
BufferedImage
):
Message
{
// TODO: 2019/9/1
return
this
}
fun
withImage
(
image
:
File
):
Message
{
// TODO: 2019/9/1
return
this
}
fun
withAt
(
target
:
QQ
):
Message
{
this
.
concat
(
target
.
at
())
return
this
}
fun
withAt
(
target
:
Int
):
Message
{
this
.
concat
(
At
(
target
.
toLong
()))
return
this
}
open
fun
toChain
():
MessageChain
{
open
fun
toChain
():
MessageChain
{
return
MessageChain
(
this
)
return
MessageChain
(
this
)
...
@@ -152,22 +130,22 @@ abstract class Message {
...
@@ -152,22 +130,22 @@ abstract class Message {
/**
/**
* 实现使用 '+' 操作符连接 [Message] 与 [Message]
* 实现使用 '+' 操作符连接 [Message] 与 [Message]
*/
*/
infix
operator
fun
plus
(
another
:
Message
):
Message
=
this
.
concat
(
another
)
infix
operator
fun
plus
(
another
:
Message
):
Message
Chain
=
this
.
concat
(
another
)
/**
/**
* 实现使用 '+' 操作符连接 [Message] 与 [String]
* 实现使用 '+' 操作符连接 [Message] 与 [String]
*/
*/
infix
operator
fun
plus
(
another
:
String
):
Message
=
this
.
concat
(
another
)
infix
operator
fun
plus
(
another
:
String
):
Message
Chain
=
this
.
concat
(
another
)
/**
/**
* 实现使用 '+' 操作符连接 [Message] 与 [Number]
* 实现使用 '+' 操作符连接 [Message] 与 [Number]
*/
*/
infix
operator
fun
plus
(
another
:
Number
):
Message
=
this
.
concat
(
another
.
toString
())
infix
operator
fun
plus
(
another
:
Number
):
Message
Chain
=
this
.
concat
(
another
.
toString
())
/**
/**
* 连接 [String] 与 [Message]
* 连接 [String] 与 [Message]
*/
*/
fun
String
.
concat
(
another
:
Message
):
Message
=
PlainText
(
this
).
concat
(
another
)
fun
String
.
concat
(
another
:
Message
):
Message
Chain
=
PlainText
(
this
).
concat
(
another
)
override
fun
hashCode
():
Int
{
override
fun
hashCode
():
Int
{
return
javaClass
.
hashCode
()
return
javaClass
.
hashCode
()
...
...
mirai-core/src/main/java/net/mamoe/mirai/message/defaults/Face.kt
View file @
86d64f02
...
@@ -3,26 +3,38 @@ package net.mamoe.mirai.message.defaults
...
@@ -3,26 +3,38 @@ package net.mamoe.mirai.message.defaults
import
net.mamoe.mirai.message.FaceID
import
net.mamoe.mirai.message.FaceID
import
net.mamoe.mirai.message.Message
import
net.mamoe.mirai.message.Message
import
net.mamoe.mirai.message.MessageId
import
net.mamoe.mirai.message.MessageId
import
net.mamoe.mirai.network.packet.writeHex
import
net.mamoe.mirai.network.packet.writeLVByteArray
import
net.mamoe.mirai.utils.lazyEncode
/**
/**
* QQ 自带表情
* QQ 自带表情
*
*
* @author Him188moe
* @author Him188moe
*/
*/
class
Face
(
val
id
:
FaceID
?
)
:
Message
()
{
class
Face
(
val
id
:
FaceID
)
:
Message
()
{
override
val
type
:
Int
=
MessageId
.
FACE
override
val
type
:
Int
=
MessageId
.
FACE
override
fun
toStringImpl
():
String
{
override
fun
toStringImpl
():
String
{
return
if
(
id
==
null
)
{
return
String
.
format
(
"[face%d]"
,
id
.
id
)
"[face?]"
}
else
String
.
format
(
"[face%d]"
,
id
.
id
)
}
}
override
fun
toByteArray
():
ByteArray
{
override
fun
toByteArray
():
ByteArray
=
lazyEncode
{
section
->
TODO
()
section
.
writeByte
(
this
.
type
)
section
.
writeLVByteArray
(
lazyEncode
{
child
->
child
.
writeShort
(
1
)
child
.
writeByte
(
this
.
id
.
id
)
child
.
writeHex
(
"0B 00 08 00 01 00 04 52 CC F5 D0 FF"
)
child
.
writeShort
(
2
)
child
.
writeByte
(
0
x14
)
//??
child
.
writeByte
(
this
.
id
.
id
+
65
)
})
}
}
override
fun
valueEquals
(
another
:
Message
):
Boolean
{
override
fun
valueEquals
(
another
:
Message
):
Boolean
{
if
(
another
!
is
Face
)
{
if
(
another
!
is
Face
)
{
return
false
return
false
...
...
mirai-core/src/main/java/net/mamoe/mirai/message/defaults/Image.kt
View file @
86d64f02
...
@@ -2,66 +2,49 @@ package net.mamoe.mirai.message.defaults
...
@@ -2,66 +2,49 @@ package net.mamoe.mirai.message.defaults
import
net.mamoe.mirai.message.Message
import
net.mamoe.mirai.message.Message
import
net.mamoe.mirai.message.MessageId
import
net.mamoe.mirai.message.MessageId
import
net.mamoe.mirai.network.packet.cutTail
import
net.mamoe.mirai.network.packet.writeHex
import
net.mamoe.mirai.network.packet.md5
import
net.mamoe.mirai.network.packet.writeLVByteArray
import
java.awt.image.BufferedImage
import
net.mamoe.mirai.network.packet.writeLVString
import
java.io.*
import
net.mamoe.mirai.utils.lazyEncode
import
java.net.URL
import
javax.imageio.ImageIO
/**
/**
* 图片消息.
* 由接收消息时构建, 可直接发送
*
* @author Him188moe
* @author Him188moe
*/
*/
class
Image
:
Message
{
open
class
Image
internal
constructor
(
val
imageID
:
String
)
:
Message
()
{
override
val
type
:
Int
=
MessageId
.
IMAGE
override
val
type
:
Int
=
MessageId
.
IMAGE
private
var
imageID
:
String
?
=
null
constructor
(
inputStream
:
InputStream
)
{
}
constructor
(
image
:
BufferedImage
)
{
}
@Throws
(
FileNotFoundException
::
class
)
constructor
(
imageFile
:
File
)
:
this
(
FileInputStream
(
imageFile
))
{
}
@Throws
(
IOException
::
class
)
constructor
(
url
:
URL
)
:
this
(
ImageIO
.
read
(
url
))
{
}
/**
* {xxxxx}.jpg
*
* @param imageID
*/
constructor
(
imageID
:
String
)
{
this
.
imageID
=
imageID
}
override
fun
toStringImpl
():
String
{
override
fun
toStringImpl
():
String
{
return
imageID
!!
return
imageID
}
}
override
fun
toByteArray
():
ByteArray
{
override
fun
toByteArray
():
ByteArray
=
lazyEncode
{
section
->
TODO
()
section
.
writeByte
(
0
x03
)
//todo 可能是 0x03?
section
.
writeLVByteArray
(
lazyEncode
{
child
->
child
.
writeByte
(
0
x02
)
child
.
writeLVString
(
this
.
imageID
)
child
.
writeHex
(
"04 00 "
+
"04 9B 53 B0 08 "
+
"05 00 "
+
"04 D9 8A 5A 70 "
+
"06 00 "
+
"04 00 00 00 50 "
+
"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"
)
child
.
writeHex
(
"20 20 20 20 20 35 30 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20"
)
child
.
writeBytes
(
this
.
imageID
)
child
.
writeByte
(
0
x41
)
})
}
}
override
fun
valueEquals
(
another
:
Message
):
Boolean
{
override
fun
valueEquals
(
another
:
Message
):
Boolean
{
if
(
another
!
is
Image
)
{
if
(
another
is
Image
)
{
return
false
return
this
.
imageID
==
another
.
imageID
}
}
return
this
.
imageID
==
another
.
imageID
}
companion
object
{
return
false
fun
getImageID
(
filename
:
String
):
ByteArray
=
md5
(
filename
).
cutTail
(
1
)
}
}
}
fun
main
()
{
println
(
0
xB0
)
}
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/message/defaults/MessageChain.kt
View file @
86d64f02
...
@@ -11,7 +11,7 @@ import java.util.stream.Stream
...
@@ -11,7 +11,7 @@ import java.util.stream.Stream
class
MessageChain
:
Message
{
class
MessageChain
:
Message
{
override
val
type
:
Int
=
MessageId
.
CHAIN
override
val
type
:
Int
=
MessageId
.
CHAIN
internal
val
list
=
LinkedList
<
Message
>(
)
val
list
:
MutableList
<
Message
>
=
Collections
.
synchronizedList
(
LinkedList
<
Message
>()
)
constructor
(
head
:
Message
,
tail
:
Message
)
{
constructor
(
head
:
Message
,
tail
:
Message
)
{
Objects
.
requireNonNull
(
head
)
Objects
.
requireNonNull
(
head
)
...
@@ -26,17 +26,16 @@ class MessageChain : Message {
...
@@ -26,17 +26,16 @@ class MessageChain : Message {
list
.
add
(
message
)
list
.
add
(
message
)
}
}
constructor
()
constructor
(
messages
:
Collection
<
Message
>)
{
list
.
addAll
(
messages
)
fun
toList
():
List
<
Message
>
{
return
list
.
toList
()
}
}
constructor
()
fun
size
():
Int
{
fun
size
():
Int
{
return
list
.
size
return
list
.
size
}
}
@Synchronized
fun
containsType
(
@MagicConstant
(
valuesFromClass
=
MessageId
::
class
)
type
:
Int
):
Boolean
{
fun
containsType
(
@MagicConstant
(
valuesFromClass
=
MessageId
::
class
)
type
:
Int
):
Boolean
{
for
(
message
in
list
)
{
for
(
message
in
list
)
{
if
(
message
.
type
==
type
)
{
if
(
message
.
type
==
type
)
{
...
@@ -47,21 +46,18 @@ class MessageChain : Message {
...
@@ -47,21 +46,18 @@ class MessageChain : Message {
}
}
fun
stream
():
Stream
<
Message
>
{
fun
stream
():
Stream
<
Message
>
{
return
ArrayList
(
list
)
.
stream
()
return
list
.
stream
()
}
}
@Synchronized
override
fun
toStringImpl
():
String
{
override
fun
toStringImpl
():
String
{
return
this
.
list
.
stream
().
map
{
it
.
toString
()
}.
collect
(
Collectors
.
joining
(
""
))
return
this
.
list
.
stream
().
map
{
it
.
toString
()
}.
collect
(
Collectors
.
joining
(
""
))
}
}
@Synchronized
override
fun
toObjectString
():
String
{
override
fun
toObjectString
():
String
{
return
String
.
format
(
"MessageChain(%s)"
,
this
.
list
.
stream
().
map
{
it
.
toObjectString
()
}.
collect
(
Collectors
.
joining
(
", "
)))
return
String
.
format
(
"MessageChain(%s)"
,
this
.
list
.
stream
().
map
{
it
.
toObjectString
()
}.
collect
(
Collectors
.
joining
(
", "
)))
}
}
@Synchronized
override
fun
concat
(
tail
:
Message
):
MessageChain
{
override
fun
concat
(
tail
:
Message
):
Message
{
this
.
list
.
add
(
tail
)
this
.
list
.
add
(
tail
)
clearToStringCache
()
clearToStringCache
()
return
this
return
this
...
...
mirai-core/src/main/java/net/mamoe/mirai/message/defaults/PlainText.kt
View file @
86d64f02
...
@@ -2,8 +2,8 @@ package net.mamoe.mirai.message.defaults
...
@@ -2,8 +2,8 @@ package net.mamoe.mirai.message.defaults
import
net.mamoe.mirai.message.Message
import
net.mamoe.mirai.message.Message
import
net.mamoe.mirai.message.MessageId
import
net.mamoe.mirai.message.MessageId
import
net.mamoe.mirai.network.packet.write
Var
ByteArray
import
net.mamoe.mirai.network.packet.write
LV
ByteArray
import
net.mamoe.mirai.network.packet.write
Var
String
import
net.mamoe.mirai.network.packet.write
LV
String
import
net.mamoe.mirai.utils.lazyEncode
import
net.mamoe.mirai.utils.lazyEncode
/**
/**
...
@@ -19,9 +19,9 @@ class PlainText(private val text: String) : Message() {
...
@@ -19,9 +19,9 @@ class PlainText(private val text: String) : Message() {
override
fun
toByteArray
():
ByteArray
=
lazyEncode
{
section
->
override
fun
toByteArray
():
ByteArray
=
lazyEncode
{
section
->
section
.
writeByte
(
this
.
type
)
section
.
writeByte
(
this
.
type
)
section
.
write
Var
ByteArray
(
lazyEncode
{
child
->
section
.
write
LV
ByteArray
(
lazyEncode
{
child
->
child
.
writeByte
(
0
x01
)
child
.
writeByte
(
0
x01
)
child
.
write
Var
String
(
this
.
text
)
child
.
write
LV
String
(
this
.
text
)
})
})
}
}
...
...
mirai-core/src/main/java/net/mamoe/mirai/message/defaults/UnsolvedImage.kt
0 → 100644
View file @
86d64f02
package
net.mamoe.mirai.message.defaults
import
net.mamoe.mirai.contact.Contact
import
net.mamoe.mirai.network.LoginSession
import
net.mamoe.mirai.network.packet.image.ClientTryGetImageIDPacket
import
net.mamoe.mirai.network.packet.image.ServerTryUploadGroupImageFailedPacket
import
net.mamoe.mirai.network.packet.image.ServerTryUploadGroupImageResponsePacket
import
net.mamoe.mirai.network.packet.image.ServerTryUploadGroupImageSuccessPacket
import
net.mamoe.mirai.network.packet.md5
import
net.mamoe.mirai.utils.ImageNetworkUtils
import
net.mamoe.mirai.utils.toByteArray
import
net.mamoe.mirai.utils.toUHexString
import
java.awt.image.BufferedImage
import
java.io.File
import
java.net.URL
import
java.util.concurrent.CompletableFuture
import
javax.imageio.ImageIO
/**
* 不确定是否存在于服务器的 [Image].
* 必须在发送之前 [UnsolvedImage.upload] 或 [Contact.uploadImage], 否则会发送失败.
x *
* @author Him188moe
*/
class
UnsolvedImage
(
filename
:
String
,
val
image
:
BufferedImage
)
:
Image
(
getImageId
(
filename
))
{
constructor
(
imageFile
:
File
)
:
this
(
imageFile
.
name
,
ImageIO
.
read
(
imageFile
))
constructor
(
url
:
URL
)
:
this
(
File
(
url
.
file
))
fun
upload
(
session
:
LoginSession
,
contact
:
Contact
):
CompletableFuture
<
Unit
>
{
return
session
.
expectPacket
<
ServerTryUploadGroupImageResponsePacket
>
{
toSend
{
ClientTryGetImageIDPacket
(
session
.
bot
.
account
.
qqNumber
,
session
.
sessionKey
,
session
.
bot
.
account
.
qqNumber
,
image
)
}
expect
{
when
(
it
)
{
is
ServerTryUploadGroupImageFailedPacket
->
{
//已经存在于服务器了
}
is
ServerTryUploadGroupImageSuccessPacket
->
{
val
data
=
image
.
toByteArray
()
if
(!
ImageNetworkUtils
.
postImage
(
it
.
uKey
.
toUHexString
(),
data
.
size
,
session
.
bot
.
account
.
qqNumber
,
contact
.
number
,
data
))
{
throw
RuntimeException
(
"cannot upload image"
)
}
}
}
}
}
}
companion
object
{
@JvmStatic
fun
getImageId
(
filename
:
String
):
String
{
val
md5
=
md5
(
filename
)
return
"{"
+
md5
.
copyOfRange
(
0
,
4
).
toUHexString
(
""
)
+
"-"
.
plus
(
md5
.
copyOfRange
(
4
,
6
).
toUHexString
(
""
))
+
"-"
.
plus
(
md5
.
copyOfRange
(
6
,
8
).
toUHexString
(
""
))
+
"-"
.
plus
(
md5
.
copyOfRange
(
8
,
12
).
toUHexString
(
""
))
+
"-"
.
plus
(
md5
.
copyOfRange
(
12
,
16
).
toUHexString
(
""
))
+
"}."
+
if
(
filename
.
endsWith
(
".jpeg"
))
"jpg"
else
filename
.
substringAfter
(
"."
,
"jpg"
)
}
}
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/network/BotNetworkHandler.kt
0 → 100644
View file @
86d64f02
package
net.mamoe.mirai.network
import
net.mamoe.mirai.network.BotNetworkHandlerImpl.BotSocket
import
net.mamoe.mirai.network.BotNetworkHandlerImpl.Login
import
net.mamoe.mirai.network.handler.*
import
net.mamoe.mirai.network.packet.ClientPacket
import
net.mamoe.mirai.network.packet.Packet
import
net.mamoe.mirai.network.packet.ServerEventPacket
import
net.mamoe.mirai.network.packet.ServerPacket
import
net.mamoe.mirai.network.packet.login.LoginState
import
java.io.Closeable
import
java.util.concurrent.CompletableFuture
/**
* Mirai 的网络处理器, 它承担所有数据包([Packet])的处理任务.
* [BotNetworkHandler] 是全异步和线程安全的.
*
* [BotNetworkHandler] 由 2 个模块构成:
* - [BotSocket]: 处理数据包底层的发送([ByteArray])
* - [PacketHandler]: 制作 [ClientPacket] 并传递给 [BotSocket] 发送; 分析 [ServerPacket] 并处理
*
* 其中, [PacketHandler] 由 4 个子模块构成:
* - [DebugPacketHandler] 输出 [Packet.toString]
* - [Login] 处理 touch/login/verification code 相关
* - [MessagePacketHandler] 处理消息相关(群消息/好友消息)([ServerEventPacket])
* - [ActionPacketHandler] 处理动作相关(踢人/加入群/好友列表等)
*
* A BotNetworkHandler is used to connect with Tencent servers.
*
* @author Him188moe
*/
interface
BotNetworkHandler
:
Closeable
{
/**
* 网络层处理器. 用于编码/解码 [Packet], 发送/接受 [ByteArray]
*
* java 调用方式: `botNetWorkHandler.getSocket()`
*/
val
socket
:
DataPacketSocket
/**
* 消息处理. 如发送好友消息, 接受群消息并触发事件
*
* java 调用方式: `botNetWorkHandler.getMessage()`
*/
var
message
:
MessagePacketHandler
/**
* 动作处理. 如发送好友请求, 处理别人发来的好友请求等
*
* java 调用方式: `botNetWorkHandler.getAction()`
*/
var
action
:
ActionPacketHandler
fun
tryLogin
(
touchingTimeoutMillis
:
Long
=
200
):
CompletableFuture
<
LoginState
>
/**
* 添加一个临时包处理器
*
* @see [TemporaryPacketHandler]
*/
fun
addHandler
(
temporaryPacketHandler
:
TemporaryPacketHandler
<
*
>)
override
fun
close
()
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/network/
RobotNetworkHandler
.kt
→
mirai-core/src/main/java/net/mamoe/mirai/network/
BotNetworkHandlerImpl
.kt
View file @
86d64f02
@
file
:
JvmMultifileClass
@
file
:
JvmName
(
"BotNetworkHandler"
)
package
net.mamoe.mirai.network
package
net.mamoe.mirai.network
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.MiraiServer
import
net.mamoe.mirai.MiraiServer
import
net.mamoe.mirai.contact.Group
import
net.mamoe.mirai.contact.QQ
import
net.mamoe.mirai.event.events.bot.BotLoginSucceedEvent
import
net.mamoe.mirai.event.events.bot.BotLoginSucceedEvent
import
net.mamoe.mirai.event.events.network.BeforePacketSendEvent
import
net.mamoe.mirai.event.events.network.BeforePacketSendEvent
import
net.mamoe.mirai.event.events.network.PacketSentEvent
import
net.mamoe.mirai.event.events.network.PacketSentEvent
import
net.mamoe.mirai.event.events.network.ServerPacketReceivedEvent
import
net.mamoe.mirai.event.events.network.ServerPacketReceivedEvent
import
net.mamoe.mirai.event.events.qq.FriendMessageEvent
import
net.mamoe.mirai.network.handler.*
import
net.mamoe.mirai.event.hookWhile
import
net.mamoe.mirai.message.Message
import
net.mamoe.mirai.message.defaults.MessageChain
import
net.mamoe.mirai.network.BotNetworkHandler.*
import
net.mamoe.mirai.network.packet.*
import
net.mamoe.mirai.network.packet.*
import
net.mamoe.mirai.network.packet.action.*
import
net.mamoe.mirai.network.packet.login.*
import
net.mamoe.mirai.network.packet.login.*
import
net.mamoe.mirai.task.MiraiThreadPool
import
net.mamoe.mirai.task.MiraiThreadPool
import
net.mamoe.mirai.utils.*
import
net.mamoe.mirai.utils.*
...
@@ -29,85 +19,53 @@ import java.util.*
...
@@ -29,85 +19,53 @@ import java.util.*
import
java.util.concurrent.CompletableFuture
import
java.util.concurrent.CompletableFuture
import
java.util.concurrent.ScheduledFuture
import
java.util.concurrent.ScheduledFuture
import
java.util.concurrent.TimeUnit
import
java.util.concurrent.TimeUnit
import
java.util.function.Supplier
import
javax.imageio.ImageIO
import
javax.imageio.ImageIO
import
kotlin.reflect.KClass
/**
/**
* Mirai 的网络处理器, 它处理所有数据包([Packet])的发送和接收.
* [BotNetworkHandler] 的内部实现, 该类不会有帮助理解的注解, 请查看 [BotNetworkHandler] 以获取帮助
* [BotNetworkHandler] 是全程异步和线程安全的.
*
* [BotNetworkHandler] 由 2 个模块构成:
* - [SocketHandler]: 处理数据包底层的发送([ByteArray])
* - [PacketHandler]: 制作 [Packet] 并传递给 [SocketHandler] 继续处理; 分析来自服务器的数据包并处理
*
* 其中, [PacketHandler] 由 4 个子模块构成:
* - [DebugHandler] 输出 [Packet.toString]
* - [LoginHandler] 处理 touch/login/verification code 相关
* - [MessageHandler] 处理消息相关(群消息/好友消息)([ServerEventPacket])
* - [ActionHandler] 处理动作相关(踢人/加入群/好友列表等)
*
* A BotNetworkHandler is used to connect with Tencent servers.
*
*
* @see BotNetworkHandler
* @author Him188moe
* @author Him188moe
*/
*/
@Suppress
(
"EXPERIMENTAL_API_USAGE"
)
//to simplify code
@Suppress
(
"EXPERIMENTAL_API_USAGE"
)
//to simplify code
class
BotNetworkHandler
(
private
val
bot
:
Bot
)
:
Closeable
{
internal
class
BotNetworkHandlerImpl
(
private
val
bot
:
Bot
)
:
BotNetworkHandler
{
private
val
socketHandler
:
SocketHandler
=
SocketHandler
()
override
val
socket
:
BotSocket
=
BotSocket
()
val
debugHandler
=
DebugHandler
()
lateinit
var
login
:
Login
val
loginHandler
=
LoginHandler
()
val
messageHandler
=
MessageHandler
()
val
actionHandler
=
ActionHandler
()
private
val
packetHandlers
:
Map
<
KClass
<
out
PacketHandler
>,
PacketHandler
>
=
linkedMapOf
(
override
lateinit
var
message
:
MessagePacketHandler
DebugHandler
::
class
to debug
Handler
,
override
lateinit
var
action
:
ActionPacketHandler
LoginHandler
::
class
to login
Handler
,
MessageHandler
::
class
to message
Handler
,
ActionHandler
::
class
to action
Handler
)
/**
val
packetHandlers
:
PacketHandlerList
=
PacketHandlerList
()
* Not async
*/
@ExperimentalUnsignedTypes
fun
sendPacket
(
packet
:
ClientPacket
)
{
socketHandler
.
sendPacket
(
packet
)
}
override
fun
close
()
{
internal
val
temporaryPacketHandlers
=
Collections
.
synchronizedList
(
mutableListOf
<
TemporaryPacketHandler
<
*
>>())
this
.
packetHandlers
.
values
.
forEach
{
it
.
close
()
}
this
.
socketHandler
.
close
()
}
override
fun
addHandler
(
temporaryPacketHandler
:
TemporaryPacketHandler
<
*
>)
{
temporaryPacketHandler
.
send
(
action
.
session
)
temporaryPacketHandlers
.
add
(
temporaryPacketHandler
)
}
//private | internal
//private | internal
/**
/**
* 仅当 [LoginState] 非 [LoginState.UNKNOWN] 且非 [LoginState.TIMEOUT] 才会调用 [loginHook].
* 尝试登录
* 如果要输入验证码, 那么会以参数 [LoginState.VERIFICATION_CODE] 调用 [loginHandler], 登录完成后再以 [LoginState.SUCCESS] 调用 [loginHandler]
*
*
* @param touchingTimeoutMillis 连接每个服务器的 timeout
* @param touchingTimeoutMillis 连接每个服务器的 timeout
*/
*/
@JvmOverloads
override
fun
tryLogin
(
touchingTimeoutMillis
:
Long
):
CompletableFuture
<
LoginState
>
{
internal
fun
tryLogin
(
touchingTimeoutMillis
:
Long
=
200
):
CompletableFuture
<
LoginState
>
{
val
ipQueue
:
LinkedList
<
String
>
=
LinkedList
(
Protocol
.
SERVER_IP
)
val
ipQueue
:
LinkedList
<
String
>
=
LinkedList
(
Protocol
.
SERVER_IP
)
val
future
=
CompletableFuture
<
LoginState
>()
val
future
=
CompletableFuture
<
LoginState
>()
fun
login
()
{
fun
login
()
{
this
.
socket
Handler
.
close
()
this
.
socket
.
close
()
val
ip
=
ipQueue
.
poll
()
val
ip
=
ipQueue
.
poll
()
if
(
ip
==
null
)
{
if
(
ip
==
null
)
{
future
.
complete
(
LoginState
.
UNKNOWN
)
//所有服务器均返回 UNKNOWN
future
.
complete
(
LoginState
.
UNKNOWN
)
//所有服务器均返回 UNKNOWN
return
return
}
}
this
@BotNetworkHandler
.
socketHandler
.
touch
(
ip
,
touchingTimeoutMillis
).
get
().
let
{
state
->
this
.
socket
.
touch
(
ip
,
touchingTimeoutMillis
).
get
().
let
{
state
->
if
(
state
==
LoginState
.
UNKNOWN
||
state
==
LoginState
.
TIMEOUT
)
{
if
(
state
==
LoginState
.
UNKNOWN
||
state
==
LoginState
.
TIMEOUT
)
{
login
()
login
()
//超时或未知, 重试连接下一个服务器
}
else
{
}
else
{
future
.
complete
(
state
)
future
.
complete
(
state
)
}
}
...
@@ -117,32 +75,60 @@ class BotNetworkHandler(private val bot: Bot) : Closeable {
...
@@ -117,32 +75,60 @@ class BotNetworkHandler(private val bot: Bot) : Closeable {
return
future
return
future
}
}
/**
private
fun
onLoggedIn
(
sessionKey
:
ByteArray
)
{
* 分配收到的数据包
val
session
=
LoginSession
(
bot
,
sessionKey
,
socket
)
*/
message
=
MessagePacketHandler
(
session
)
@ExperimentalUnsignedTypes
action
=
ActionPacketHandler
(
session
)
internal
fun
distributePacket
(
packet
:
ServerPacket
)
{
try
{
packet
.
decode
()
}
catch
(
e
:
java
.
lang
.
Exception
)
{
e
.
printStackTrace
()
bot
.
debug
(
"Packet=$packet"
)
bot
.
debug
(
"Packet size="
+
packet
.
input
.
goto
(
0
).
readAllBytes
().
size
)
bot
.
debug
(
"Packet data="
+
packet
.
input
.
goto
(
0
).
readAllBytes
().
toUHexString
())
return
}
if
(
ServerPacketReceivedEvent
(
bot
,
packet
).
broadcast
().
isCancelled
)
{
packetHandlers
.
add
(
message
.
asNode
())
debugHandler
.
onPacketReceived
(
packet
)
packetHandlers
.
add
(
action
.
asNode
())
return
}
}
this
.
packetHandlers
.
values
.
forEach
{
private
lateinit
var
sessionKey
:
ByteArray
it
.
onPacketReceived
(
packet
)
override
fun
close
()
{
this
.
packetHandlers
.
forEach
{
it
.
instance
.
close
()
}
}
this
.
socket
.
close
()
}
}
private
inner
class
SocketHandler
:
Closeable
{
internal
inner
class
BotSocket
:
Closeable
,
DataPacketSocket
{
override
fun
distributePacket
(
packet
:
ServerPacket
)
{
try
{
packet
.
decode
()
}
catch
(
e
:
java
.
lang
.
Exception
)
{
e
.
printStackTrace
()
bot
.
debugPacket
(
packet
)
return
}
temporaryPacketHandlers
.
removeIf
{
it
.
onPacketReceived
(
action
.
session
,
packet
)
}
//For debug
kotlin
.
run
{
if
(!
packet
.
javaClass
.
name
.
endsWith
(
"Encrypted"
)
&&
!
packet
.
javaClass
.
name
.
endsWith
(
"Raw"
))
{
bot
.
notice
(
"Packet received: $packet"
)
}
if
(
packet
is
ServerEventPacket
)
{
sendPacket
(
ClientEventResponsePacket
(
bot
.
account
.
qqNumber
,
packet
.
packetId
,
sessionKey
,
packet
.
eventIdentity
))
}
}
if
(
ServerPacketReceivedEvent
(
bot
,
packet
).
broadcast
().
isCancelled
)
{
return
}
login
.
onPacketReceived
(
packet
)
packetHandlers
.
forEach
{
it
.
instance
.
onPacketReceived
(
packet
)
}
}
private
var
socket
:
DatagramSocket
?
=
null
private
var
socket
:
DatagramSocket
?
=
null
internal
var
serverIP
:
String
=
""
internal
var
serverIP
:
String
=
""
...
@@ -182,18 +168,23 @@ class BotNetworkHandler(private val bot: Bot) : Closeable {
...
@@ -182,18 +168,23 @@ class BotNetworkHandler(private val bot: Bot) : Closeable {
}.
start
()
}.
start
()
}
}
/**
/**
* Start network and touch the server
* Start network and touch the server
*/
*/
internal
fun
touch
(
serverAddress
:
String
,
timeoutMillis
:
Long
):
CompletableFuture
<
LoginState
>
{
fun
touch
(
serverAddress
:
String
,
timeoutMillis
:
Long
):
CompletableFuture
<
LoginState
>
{
bot
.
info
(
"Connecting server: $serverAddress"
)
bot
.
info
(
"Connecting server: $serverAddress"
)
if
(
this
@BotNetworkHandlerImpl
::
login
.
isInitialized
)
{
login
.
close
()
}
login
=
Login
()
this
.
loginFuture
=
CompletableFuture
()
this
.
loginFuture
=
CompletableFuture
()
s
ocketHandler
.
s
erverIP
=
serverAddress
serverIP
=
serverAddress
waitForPacket
(
ServerPacket
::
class
,
timeoutMillis
)
{
bot
.
waitForPacket
(
ServerPacket
::
class
,
timeoutMillis
)
{
loginFuture
!!
.
complete
(
LoginState
.
TIMEOUT
)
loginFuture
!!
.
complete
(
LoginState
.
TIMEOUT
)
}
}
sendPacket
(
ClientTouchPacket
(
bot
.
account
.
qqNumber
,
s
ocketHandler
.
s
erverIP
))
sendPacket
(
ClientTouchPacket
(
bot
.
account
.
qqNumber
,
serverIP
))
return
this
.
loginFuture
!!
return
this
.
loginFuture
!!
}
}
...
@@ -202,8 +193,8 @@ class BotNetworkHandler(private val bot: Bot) : Closeable {
...
@@ -202,8 +193,8 @@ class BotNetworkHandler(private val bot: Bot) : Closeable {
* Not async
* Not async
*/
*/
@Synchronized
@Synchronized
@ExperimentalUnsignedTypes
internal
fun
sendPacket
(
packet
:
ClientPacket
)
{
override
fun
sendPacket
(
packet
:
ClientPacket
)
{
checkNotNull
(
socket
)
{
"network closed"
}
checkNotNull
(
socket
)
{
"network closed"
}
if
(
socket
!!
.
isClosed
)
{
if
(
socket
!!
.
isClosed
)
{
return
return
...
@@ -218,7 +209,7 @@ class BotNetworkHandler(private val bot: Bot) : Closeable {
...
@@ -218,7 +209,7 @@ class BotNetworkHandler(private val bot: Bot) : Closeable {
val
data
=
packet
.
toByteArray
()
val
data
=
packet
.
toByteArray
()
socket
!!
.
send
(
DatagramPacket
(
data
,
data
.
size
))
socket
!!
.
send
(
DatagramPacket
(
data
,
data
.
size
))
bot
cyanL
"Packet sent: $packet"
bot
.
cyanL
(
"Packet sent: $packet"
)
PacketSentEvent
(
bot
,
packet
).
broadcast
()
PacketSentEvent
(
bot
,
packet
).
broadcast
()
}
catch
(
e
:
Throwable
)
{
}
catch
(
e
:
Throwable
)
{
...
@@ -226,30 +217,7 @@ class BotNetworkHandler(private val bot: Bot) : Closeable {
...
@@ -226,30 +217,7 @@ class BotNetworkHandler(private val bot: Bot) : Closeable {
}
}
}
}
@Suppress
(
"UNCHECKED_CAST"
)
override
fun
getOwner
():
Bot
=
this
@BotNetworkHandlerImpl
.
bot
internal
fun
<
P
:
ServerPacket
>
waitForPacket
(
packetClass
:
KClass
<
P
>,
timeoutMillis
:
Long
,
timeout
:
()
->
Unit
)
{
var
got
=
false
ServerPacketReceivedEvent
::
class
.
hookWhile
{
if
(
packetClass
.
isInstance
(
it
.
packet
)
&&
it
.
bot
==
bot
)
{
got
=
true
true
}
else
{
false
}
}
MiraiThreadPool
.
getInstance
().
submit
{
val
startingTime
=
System
.
currentTimeMillis
()
while
(!
got
)
{
if
(
System
.
currentTimeMillis
()
-
startingTime
>
timeoutMillis
)
{
timeout
.
invoke
()
return
@
submit
}
Thread
.
sleep
(
10
)
}
}
}
override
fun
close
()
{
override
fun
close
()
{
this
.
socket
?.
close
()
this
.
socket
?.
close
()
...
@@ -261,54 +229,21 @@ class BotNetworkHandler(private val bot: Bot) : Closeable {
...
@@ -261,54 +229,21 @@ class BotNetworkHandler(private val bot: Bot) : Closeable {
}
}
}
}
fun
isClosed
():
Boolean
{
override
fun
isClosed
():
Boolean
{
return
this
.
socket
?.
isClosed
?:
true
return
this
.
socket
?.
isClosed
?:
true
}
}
}
}
private
lateinit
var
sessionKey
:
ByteArray
abstract
inner
class
PacketHandler
:
Closeable
{
abstract
fun
onPacketReceived
(
packet
:
ServerPacket
)
override
fun
close
()
{
}
}
/**
* Kind of [PacketHandler] that prints all packets received in the format of hex byte array.
*/
inner
class
DebugHandler
:
PacketHandler
()
{
override
fun
onPacketReceived
(
packet
:
ServerPacket
)
{
if
(!
packet
.
javaClass
.
name
.
endsWith
(
"Encrypted"
)
&&
!
packet
.
javaClass
.
name
.
endsWith
(
"Raw"
))
{
bot
notice
"Packet received: $packet"
}
if
(
packet
is
ServerEventPacket
)
{
sendPacket
(
ClientMessageResponsePacket
(
bot
.
account
.
qqNumber
,
packet
.
packetId
,
sessionKey
,
packet
.
eventIdentity
))
}
}
}
/**
/**
* 处理登录过程
* 处理登录过程
*/
*/
inner
class
Login
Handler
:
PacketHandler
()
{
inner
class
Login
:
Closeable
{
private
lateinit
var
token00BA
:
ByteArray
private
lateinit
var
token00BA
:
ByteArray
private
lateinit
var
token0825
:
ByteArray
private
lateinit
var
token0825
:
ByteArray
private
var
loginTime
:
Int
=
0
private
var
loginTime
:
Int
=
0
private
lateinit
var
loginIP
:
String
private
lateinit
var
loginIP
:
String
private
var
tgtgtKey
:
ByteArray
=
getRandomByteArray
(
16
)
private
var
tgtgtKey
:
ByteArray
=
getRandomByteArray
(
16
)
private
var
tlv0105
:
ByteArray
=
lazyEncode
{
it
.
writeHex
(
"01 05 00 30"
)
it
.
writeHex
(
"00 01 01 02 00 14 01 01 00 10"
)
it
.
writeRandom
(
16
)
it
.
writeHex
(
"00 14 01 02 00 10"
)
it
.
writeRandom
(
16
)
}
/**
/**
* 0828_decr_key
* 0828_decr_key
*/
*/
...
@@ -317,34 +252,33 @@ class BotNetworkHandler(private val bot: Bot) : Closeable {
...
@@ -317,34 +252,33 @@ class BotNetworkHandler(private val bot: Bot) : Closeable {
private
var
captchaSectionId
:
Int
=
1
private
var
captchaSectionId
:
Int
=
1
private
var
captchaCache
:
ByteArray
?
=
byteArrayOf
()
//每次包只发一部分验证码来
private
var
captchaCache
:
ByteArray
?
=
byteArrayOf
()
//每次包只发一部分验证码来
private
var
heartbeatFuture
:
ScheduledFuture
<
*
>?
=
null
private
var
heartbeatFuture
:
ScheduledFuture
<
*
>?
=
null
private
var
sKeyRefresherFuture
:
ScheduledFuture
<
*
>?
=
null
override
fun
onPacketReceived
(
packet
:
ServerPacket
)
{
fun
onPacketReceived
(
packet
:
ServerPacket
)
{
when
(
packet
)
{
when
(
packet
)
{
is
ServerTouchResponsePacket
->
{
is
ServerTouchResponsePacket
->
{
if
(
packet
.
serverIP
!=
null
)
{
//redirection
if
(
packet
.
serverIP
!=
null
)
{
//redirection
socket
Handler
.
serverIP
=
packet
.
serverIP
!!
socket
.
serverIP
=
packet
.
serverIP
!!
//connect(packet.serverIP!!)
//connect(packet.serverIP!!)
sendPacket
(
ClientServerRedirectionPacket
(
packet
.
serverIP
!!
,
bot
.
account
.
qqNumber
))
s
ocket
.
s
endPacket
(
ClientServerRedirectionPacket
(
packet
.
serverIP
!!
,
bot
.
account
.
qqNumber
))
}
else
{
//password submission
}
else
{
//password submission
this
.
loginIP
=
packet
.
loginIP
this
.
loginIP
=
packet
.
loginIP
this
.
loginTime
=
packet
.
loginTime
this
.
loginTime
=
packet
.
loginTime
this
.
token0825
=
packet
.
token0825
this
.
token0825
=
packet
.
token0825
sendPacket
(
ClientPasswordSubmissionPacket
(
bot
.
account
.
qqNumber
,
bot
.
account
.
password
,
packet
.
loginTime
,
packet
.
loginIP
,
this
.
tgtgtKey
,
packet
.
token0825
))
s
ocket
.
s
endPacket
(
ClientPasswordSubmissionPacket
(
bot
.
account
.
qqNumber
,
bot
.
account
.
password
,
packet
.
loginTime
,
packet
.
loginIP
,
this
.
tgtgtKey
,
packet
.
token0825
))
}
}
}
}
is
ServerLoginResponseFailedPacket
->
{
is
ServerLoginResponseFailedPacket
->
{
socket
Handler
.
loginFuture
?.
complete
(
packet
.
loginState
)
socket
.
loginFuture
?.
complete
(
packet
.
loginState
)
return
return
}
}
is
ServerVerificationCodeCorrectPacket
->
{
is
ServerVerificationCodeCorrectPacket
->
{
this
.
tgtgtKey
=
getRandomByteArray
(
16
)
this
.
tgtgtKey
=
getRandomByteArray
(
16
)
this
.
token00BA
=
packet
.
token00BA
this
.
token00BA
=
packet
.
token00BA
sendPacket
(
ClientLoginResendPacket3105
(
bot
.
account
.
qqNumber
,
bot
.
account
.
password
,
this
.
loginTime
,
this
.
loginIP
,
this
.
tgtgtKey
,
this
.
token0825
,
this
.
token00BA
))
s
ocket
.
s
endPacket
(
ClientLoginResendPacket3105
(
bot
.
account
.
qqNumber
,
bot
.
account
.
password
,
this
.
loginTime
,
this
.
loginIP
,
this
.
tgtgtKey
,
this
.
token0825
,
this
.
token00BA
))
}
}
is
ServerLoginResponseVerificationCodeInitPacket
->
{
is
ServerLoginResponseVerificationCodeInitPacket
->
{
...
@@ -354,13 +288,13 @@ class BotNetworkHandler(private val bot: Bot) : Closeable {
...
@@ -354,13 +288,13 @@ class BotNetworkHandler(private val bot: Bot) : Closeable {
if
(
packet
.
unknownBoolean
!=
null
&&
packet
.
unknownBoolean
!!
)
{
if
(
packet
.
unknownBoolean
!=
null
&&
packet
.
unknownBoolean
!!
)
{
this
.
captchaSectionId
=
1
this
.
captchaSectionId
=
1
sendPacket
(
ClientVerificationCodeTransmissionRequestPacket
(
1
,
bot
.
account
.
qqNumber
,
this
.
token0825
,
this
.
captchaSectionId
++,
this
.
token00BA
))
s
ocket
.
s
endPacket
(
ClientVerificationCodeTransmissionRequestPacket
(
1
,
bot
.
account
.
qqNumber
,
this
.
token0825
,
this
.
captchaSectionId
++,
this
.
token00BA
))
}
}
}
}
is
ServerVerificationCodeTransmissionPacket
->
{
is
ServerVerificationCodeTransmissionPacket
->
{
if
(
packet
is
ServerVerificationCodeWrongPacket
)
{
if
(
packet
is
ServerVerificationCodeWrongPacket
)
{
bot
error
"验证码错误, 请重新输入"
bot
.
error
(
"验证码错误, 请重新输入"
)
captchaSectionId
=
1
captchaSectionId
=
1
this
.
captchaCache
=
byteArrayOf
()
this
.
captchaCache
=
byteArrayOf
()
}
}
...
@@ -369,31 +303,31 @@ class BotNetworkHandler(private val bot: Bot) : Closeable {
...
@@ -369,31 +303,31 @@ class BotNetworkHandler(private val bot: Bot) : Closeable {
this
.
token00BA
=
packet
.
token00BA
this
.
token00BA
=
packet
.
token00BA
if
(
packet
.
transmissionCompleted
)
{
if
(
packet
.
transmissionCompleted
)
{
bot
notice
(
CharImageUtil
.
createCharImg
(
ImageIO
.
read
(
this
.
captchaCache
!!
.
inputStream
())))
bot
.
notice
(
CharImageUtil
.
createCharImg
(
ImageIO
.
read
(
this
.
captchaCache
!!
.
inputStream
())))
bot
notice
(
"需要验证码登录, 验证码为 4 字母"
)
bot
.
notice
(
"需要验证码登录, 验证码为 4 字母"
)
try
{
try
{
(
MiraiServer
.
getInstance
().
parentFolder
+
"VerificationCode.png"
).
writeBytes
(
this
.
captchaCache
!!
)
(
MiraiServer
.
getInstance
().
parentFolder
+
"VerificationCode.png"
).
writeBytes
(
this
.
captchaCache
!!
)
bot
notice
(
"若看不清字符图片, 请查看 Mirai 根目录下 VerificationCode.png"
)
bot
.
notice
(
"若看不清字符图片, 请查看 Mirai 根目录下 VerificationCode.png"
)
}
catch
(
e
:
Exception
)
{
}
catch
(
e
:
Exception
)
{
bot
notice
"无法写出验证码文件, 请尝试查看以上字符图片"
bot
.
notice
(
"无法写出验证码文件, 请尝试查看以上字符图片"
)
}
}
bot
notice
(
"若要更换验证码, 请直接回车"
)
bot
.
notice
(
"若要更换验证码, 请直接回车"
)
val
code
=
Scanner
(
System
.
`in`
).
nextLine
()
val
code
=
Scanner
(
System
.
`in`
).
nextLine
()
if
(
code
.
isEmpty
()
||
code
.
length
!=
4
)
{
if
(
code
.
isEmpty
()
||
code
.
length
!=
4
)
{
this
.
captchaCache
=
byteArrayOf
()
this
.
captchaCache
=
byteArrayOf
()
this
.
captchaSectionId
=
1
this
.
captchaSectionId
=
1
sendPacket
(
ClientVerificationCodeRefreshPacket
(
packet
.
packetIdLast
+
1
,
bot
.
account
.
qqNumber
,
token0825
))
s
ocket
.
s
endPacket
(
ClientVerificationCodeRefreshPacket
(
packet
.
packetIdLast
+
1
,
bot
.
account
.
qqNumber
,
token0825
))
}
else
{
}
else
{
sendPacket
(
ClientVerificationCodeSubmitPacket
(
packet
.
packetIdLast
+
1
,
bot
.
account
.
qqNumber
,
token0825
,
code
,
packet
.
verificationToken
))
s
ocket
.
s
endPacket
(
ClientVerificationCodeSubmitPacket
(
packet
.
packetIdLast
+
1
,
bot
.
account
.
qqNumber
,
token0825
,
code
,
packet
.
verificationToken
))
}
}
}
else
{
}
else
{
sendPacket
(
ClientVerificationCodeTransmissionRequestPacket
(
packet
.
packetIdLast
+
1
,
bot
.
account
.
qqNumber
,
token0825
,
captchaSectionId
++,
token00BA
))
s
ocket
.
s
endPacket
(
ClientVerificationCodeTransmissionRequestPacket
(
packet
.
packetIdLast
+
1
,
bot
.
account
.
qqNumber
,
token0825
,
captchaSectionId
++,
token00BA
))
}
}
}
}
is
ServerLoginResponseSuccessPacket
->
{
is
ServerLoginResponseSuccessPacket
->
{
this
.
sessionResponseDecryptionKey
=
packet
.
sessionResponseDecryptionKey
this
.
sessionResponseDecryptionKey
=
packet
.
sessionResponseDecryptionKey
s
endPacket
(
ClientSessionRequestPacket
(
bot
.
account
.
qqNumber
,
socketHandler
.
serverIP
,
packet
.
token38
,
packet
.
token88
,
packet
.
encryptionKey
,
this
.
tlv0105
))
s
ocket
.
sendPacket
(
ClientSessionRequestPacket
(
bot
.
account
.
qqNumber
,
socket
.
serverIP
,
packet
.
token38
,
packet
.
token88
,
packet
.
encryptionKey
))
}
}
//是ClientPasswordSubmissionPacket之后服务器回复的
//是ClientPasswordSubmissionPacket之后服务器回复的
...
@@ -404,10 +338,10 @@ class BotNetworkHandler(private val bot: Bot) : Closeable {
...
@@ -404,10 +338,10 @@ class BotNetworkHandler(private val bot: Bot) : Closeable {
//}
//}
if
(
packet
.
flag
==
ServerLoginResponseKeyExchangePacket
.
Flag
.
`
08
36
31
03
`
)
{
if
(
packet
.
flag
==
ServerLoginResponseKeyExchangePacket
.
Flag
.
`
08
36
31
03
`
)
{
this
.
tgtgtKey
=
packet
.
tgtgtKey
this
.
tgtgtKey
=
packet
.
tgtgtKey
sendPacket
(
ClientLoginResendPacket3104
(
bot
.
account
.
qqNumber
,
bot
.
account
.
password
,
loginTime
,
loginIP
,
tgtgtKey
,
token0825
,
packet
.
tokenUnknown
s
ocket
.
s
endPacket
(
ClientLoginResendPacket3104
(
bot
.
account
.
qqNumber
,
bot
.
account
.
password
,
loginTime
,
loginIP
,
tgtgtKey
,
token0825
,
packet
.
tokenUnknown
?:
this
.
token00BA
,
packet
.
tlv0006
))
?:
this
.
token00BA
,
packet
.
tlv0006
))
}
else
{
}
else
{
sendPacket
(
ClientLoginResendPacket3106
(
bot
.
account
.
qqNumber
,
bot
.
account
.
password
,
loginTime
,
loginIP
,
tgtgtKey
,
token0825
,
packet
.
tokenUnknown
s
ocket
.
s
endPacket
(
ClientLoginResendPacket3106
(
bot
.
account
.
qqNumber
,
bot
.
account
.
password
,
loginTime
,
loginIP
,
tgtgtKey
,
token0825
,
packet
.
tokenUnknown
?:
token00BA
,
packet
.
tlv0006
))
?:
token00BA
,
packet
.
tlv0006
))
}
}
}
}
...
@@ -415,51 +349,35 @@ class BotNetworkHandler(private val bot: Bot) : Closeable {
...
@@ -415,51 +349,35 @@ class BotNetworkHandler(private val bot: Bot) : Closeable {
is
ServerSessionKeyResponsePacket
->
{
is
ServerSessionKeyResponsePacket
->
{
sessionKey
=
packet
.
sessionKey
sessionKey
=
packet
.
sessionKey
heartbeatFuture
=
MiraiThreadPool
.
getInstance
().
scheduleWithFixedDelay
({
heartbeatFuture
=
MiraiThreadPool
.
getInstance
().
scheduleWithFixedDelay
({
sendPacket
(
ClientHeartbeatPacket
(
bot
.
account
.
qqNumber
,
sessionKey
))
s
ocket
.
s
endPacket
(
ClientHeartbeatPacket
(
bot
.
account
.
qqNumber
,
sessionKey
))
},
90000
,
90000
,
TimeUnit
.
MILLISECONDS
)
},
90000
,
90000
,
TimeUnit
.
MILLISECONDS
)
BotLoginSucceedEvent
(
bot
).
broadcast
()
socket
.
loginFuture
!!
.
complete
(
LoginState
.
SUCCESS
)
//登录成功后会收到大量上次的消息, 忽略掉
MiraiThreadPool
.
getInstance
().
schedule
({
messageHandler
.
ignoreMessage
=
false
},
3
,
TimeUnit
.
SECONDS
)
this
.
tlv0105
=
packet
.
tlv0105
login
.
changeOnlineStatus
(
ClientLoginStatus
.
ONLINE
)
sendPacket
(
ClientChangeOnlineStatusPacket
(
bot
.
account
.
qqNumber
,
sessionKey
,
ClientLoginStatus
.
ONLINE
))
}
}
is
ServerLoginSuccessPacket
->
{
is
ServerLoginSuccessPacket
->
{
socketHandler
.
loginFuture
!!
.
complete
(
LoginState
.
SUCCESS
)
BotLoginSucceedEvent
(
bot
).
broadcast
()
sendPacket
(
ClientSKeyRequestPacket
(
bot
.
account
.
qqNumber
,
sessionKey
))
}
is
ServerSKeyResponsePacket
->
{
//登录成功后会收到大量上次的消息, 忽略掉
actionHandler
.
sKey
=
packet
.
sKey
MiraiThreadPool
.
getInstance
().
schedule
({
actionHandler
.
cookies
=
"uin=o"
+
bot
.
account
.
qqNumber
+
";skey="
+
actionHandler
.
sKey
+
";"
message
.
ignoreMessage
=
false
},
3
,
TimeUnit
.
SECONDS
)
sKeyRefresherFuture
=
MiraiThreadPool
.
getInstance
().
scheduleWithFixedDelay
({
sendPacket
(
ClientSKeyRefreshmentRequestPacket
(
bot
.
account
.
qqNumber
,
sessionKey
))
},
1800000
,
1800000
,
TimeUnit
.
MILLISECONDS
)
actionHandler
.
gtk
=
getGTK
(
actionHandler
.
sKey
)
onLoggedIn
(
sessionKey
)
sendPacket
(
ClientAccountInfoRequestPacket
(
bot
.
account
.
qqNumber
,
sessionKey
))
}
}
is
ServerEventPacket
.
Raw
->
distributePacket
(
packet
.
distribute
())
is
ServerVerificationCodePacket
.
Encrypted
->
distributePacket
(
packet
.
decrypt
())
is
ServerVerificationCodePacket
.
Encrypted
->
socket
.
distributePacket
(
packet
.
decrypt
())
is
ServerLoginResponseVerificationCodeInitPacket
.
Encrypted
->
distributePacket
(
packet
.
decrypt
())
is
ServerLoginResponseVerificationCodeInitPacket
.
Encrypted
->
socket
.
distributePacket
(
packet
.
decrypt
())
is
ServerLoginResponseKeyExchangePacket
.
Encrypted
->
distributePacket
(
packet
.
decrypt
(
this
.
tgtgtKey
))
is
ServerLoginResponseKeyExchangePacket
.
Encrypted
->
socket
.
distributePacket
(
packet
.
decrypt
(
this
.
tgtgtKey
))
is
ServerLoginResponseSuccessPacket
.
Encrypted
->
distributePacket
(
packet
.
decrypt
(
this
.
tgtgtKey
))
is
ServerLoginResponseSuccessPacket
.
Encrypted
->
socket
.
distributePacket
(
packet
.
decrypt
(
this
.
tgtgtKey
))
is
ServerSessionKeyResponsePacket
.
Encrypted
->
distributePacket
(
packet
.
decrypt
(
this
.
sessionResponseDecryptionKey
))
is
ServerSessionKeyResponsePacket
.
Encrypted
->
socket
.
distributePacket
(
packet
.
decrypt
(
this
.
sessionResponseDecryptionKey
))
is
ServerTouchResponsePacket
.
Encrypted
->
distributePacket
(
packet
.
decrypt
())
is
ServerTouchResponsePacket
.
Encrypted
->
socket
.
distributePacket
(
packet
.
decrypt
())
is
ServerSKeyResponsePacket
.
Encrypted
->
distributePacket
(
packet
.
decrypt
(
sessionKey
))
is
ServerAccountInfoResponsePacket
.
Encrypted
->
distributePacket
(
packet
.
decrypt
(
sessionKey
))
is
ServerEventPacket
.
Raw
.
Encrypted
->
distributePacket
(
packet
.
decrypt
(
sessionKey
))
is
ServerAccountInfoResponsePacket
,
is
ServerHeartbeatResponsePacket
,
is
ServerHeartbeatResponsePacket
,
is
UnknownServerPacket
->
{
is
UnknownServerPacket
->
{
//ignored
//ignored
...
@@ -470,176 +388,16 @@ class BotNetworkHandler(private val bot: Bot) : Closeable {
...
@@ -470,176 +388,16 @@ class BotNetworkHandler(private val bot: Bot) : Closeable {
}
}
}
}
fun
changeOnlineStatus
(
status
:
ClientLoginStatus
)
{
socket
.
sendPacket
(
ClientChangeOnlineStatusPacket
(
bot
.
account
.
qqNumber
,
sessionKey
,
status
))
}
override
fun
close
()
{
override
fun
close
()
{
this
.
captchaCache
=
null
this
.
captchaCache
=
null
this
.
heartbeatFuture
?.
cancel
(
true
)
this
.
heartbeatFuture
?.
cancel
(
true
)
this
.
sKeyRefresherFuture
?.
cancel
(
true
)
this
.
heartbeatFuture
=
null
this
.
heartbeatFuture
=
null
this
.
sKeyRefresherFuture
=
null
}
}
/**
* 处理消息事件, 承担消息发送任务.
*/
inner
class
MessageHandler
:
PacketHandler
()
{
internal
var
ignoreMessage
:
Boolean
=
true
init
{
//todo for test
FriendMessageEvent
::
class
.
hookWhile
{
if
(
socketHandler
.
isClosed
())
{
return
@
hookWhile
false
}
if
(
it
.
message
()
valueEquals
"你好"
)
{
it
.
qq
.
sendMessage
(
"你好!"
)
}
else
if
(
it
.
message
().
toString
().
startsWith
(
"复读"
))
{
it
.
qq
.
sendMessage
(
it
.
message
())
}
return
@
hookWhile
true
}
}
override
fun
onPacketReceived
(
packet
:
ServerPacket
)
{
when
(
packet
)
{
is
ServerGroupUploadFileEventPacket
->
{
//todo
}
is
ServerFriendMessageEventPacket
->
{
if
(
ignoreMessage
)
{
return
}
FriendMessageEvent
(
bot
,
bot
.
contacts
.
getQQ
(
packet
.
qq
),
packet
.
message
).
broadcast
()
}
is
ServerGroupMessageEventPacket
->
{
//todo message chain
//GroupMessageEvent(this.bot, bot.contacts.getGroupByNumber(packet.groupNumber), bot.contacts.getQQ(packet.qq), packet.message)
}
is
UnknownServerEventPacket
->
{
//todo
}
is
ServerSendFriendMessageResponsePacket
,
is
ServerSendGroupMessageResponsePacket
->
{
//ignored
}
else
->
{
//ignored
}
}
}
fun
sendFriendMessage
(
qq
:
QQ
,
message
:
MessageChain
)
{
sendPacket
(
ClientSendFriendMessagePacket
(
bot
.
account
.
qqNumber
,
qq
.
number
,
sessionKey
,
message
))
}
fun
sendGroupMessage
(
group
:
Group
,
message
:
Message
):
Unit
{
TODO
()
//sendPacket(ClientSendGroupMessagePacket(group.groupId, bot.account.qqNumber, sessionKey, message))
}
}
/**
* 动作: 获取好友列表, 点赞, 踢人等.
* 处理动作事件, 承担动作任务.
*/
inner
class
ActionHandler
:
PacketHandler
()
{
internal
lateinit
var
cookies
:
String
internal
var
sKey
:
String
=
""
set
(
value
)
{
field
=
value
gtk
=
getGTK
(
value
)
}
internal
var
gtk
:
Int
=
0
private
val
addFriendSessions
=
Collections
.
synchronizedCollection
(
mutableListOf
<
AddFriendSession
>())
override
fun
onPacketReceived
(
packet
:
ServerPacket
)
{
when
(
packet
)
{
is
ServerCanAddFriendResponsePacket
->
{
this
.
addFriendSessions
.
forEach
{
it
.
onPacketReceived
(
packet
)
}
}
else
->
{
}
}
}
fun
addFriend
(
qqNumber
:
Long
,
message
:
Supplier
<
String
>)
{
addFriend
(
qqNumber
,
lazy
{
message
.
get
()
})
}
@JvmSynthetic
fun
addFriend
(
qqNumber
:
Long
,
message
:
Lazy
<
String
>
=
lazyOf
(
""
)):
CompletableFuture
<
AddFriendResult
>
{
val
future
=
CompletableFuture
<
AddFriendResult
>()
val
session
=
AddFriendSession
(
qqNumber
,
future
,
message
)
addFriendSessions
.
add
(
session
)
session
.
sendAddRequest
();
return
future
}
override
fun
close
()
{
}
private
inner
class
AddFriendSession
(
private
val
qq
:
Long
,
private
val
future
:
CompletableFuture
<
AddFriendResult
>,
private
val
message
:
Lazy
<
String
>
)
:
Closeable
{
lateinit
var
id
:
ByteArray
fun
onPacketReceived
(
packet
:
ServerPacket
)
{
if
(!
::
id
.
isInitialized
)
{
return
}
when
(
packet
)
{
is
ServerCanAddFriendResponsePacket
->
{
if
(!(
packet
.
idByteArray
[
2
]
==
id
[
0
]
&&
packet
.
idByteArray
[
3
]
==
id
[
1
]))
{
return
}
when
(
packet
.
state
)
{
ServerCanAddFriendResponsePacket
.
State
.
FAILED
->
{
future
.
complete
(
AddFriendResult
.
FAILED
)
close
()
}
ServerCanAddFriendResponsePacket
.
State
.
ALREADY_ADDED
->
{
future
.
complete
(
AddFriendResult
.
ALREADY_ADDED
)
close
()
}
ServerCanAddFriendResponsePacket
.
State
.
REQUIRE_VERIFICATION
->
{
sendPacket
(
ClientAddFriendPacket
(
bot
.
account
.
qqNumber
,
qq
,
sessionKey
))
}
ServerCanAddFriendResponsePacket
.
State
.
NOT_REQUIRE_VERIFICATION
->
{
}
}
}
}
}
fun
sendAddRequest
()
{
sendPacket
(
ClientCanAddFriendPacket
(
bot
.
account
.
qqNumber
,
qq
,
sessionKey
).
also
{
this
.
id
=
it
.
packetIdLast
})
}
override
fun
close
()
{
addFriendSessions
.
remove
(
this
)
}
}
}
}
}
}
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/network/LoginSession.kt
0 → 100644
View file @
86d64f02
package
net.mamoe.mirai.network
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.network.handler.DataPacketSocket
import
net.mamoe.mirai.network.handler.TemporaryPacketHandler
import
net.mamoe.mirai.network.packet.ClientPacket
import
net.mamoe.mirai.network.packet.ServerPacket
import
net.mamoe.mirai.utils.getGTK
import
java.util.concurrent.CompletableFuture
/**
* 登录会话. 当登录完成后, 客户端会拿到 sessionKey.
* 此时建立 session, 然后开始处理事务.
*
* @author Him188moe
*/
class
LoginSession
(
val
bot
:
Bot
,
val
sessionKey
:
ByteArray
,
val
socket
:
DataPacketSocket
)
{
/**
* Web api 使用
*/
lateinit
var
cookies
:
String
/**
* Web api 使用
*/
var
sKey
:
String
=
""
set
(
value
)
{
field
=
value
gtk
=
getGTK
(
value
)
}
/**
* Web api 使用
*/
var
gtk
:
Int
=
0
/**
* 发送一个数据包, 并期待接受一个特定的 [ServerPacket]. 仅 Kotlin 使用
* 发送成功后, 该方法会等待收到 [ServerPacket] 直到超时.
*
* 实现方法:
* ```kotlin
* session.expectPacket<ServerPacketXXX> {
* toSend { ClientPacketXXX(...) }
* expect {//it: ServerPacketXXX
*
* }
* }
* ```
*
* @param P 期待的包
* @param handlerTemporary 处理器.
* @return future. 可进行超时处理
*
* Kotlin DSL: 仅 Kotlin 使用.
*/
@JvmSynthetic
inline
fun
<
reified
P
:
ServerPacket
>
expectPacket
(
handlerTemporary
:
TemporaryPacketHandler
<
P
>.()
->
Unit
):
CompletableFuture
<
Unit
>
{
val
future
=
CompletableFuture
<
Unit
>()
this
.
bot
.
network
.
addHandler
(
TemporaryPacketHandler
(
P
::
class
,
future
,
this
).
also
(
handlerTemporary
))
return
future
}
/**
* 发送一个数据包, 并期待接受一个特定的 [ServerPacket].
* 发送成功后, 该方法会等待收到 [ServerPacket] 直到超时.
* 由于包名可能过长, 可使用 `DataPacketSocket.expectPacket(PacketProcessor)` 替代.
*
* 实现方法:
* ```kotlin
* session.expectPacket<ServerPacketXXX>(ClientPacketXXX(...)) {//it: ServerPacketXXX
*
* }
* ```
*
* @param P 期待的包
* @param toSend 将要发送的包
* @param handler 处理期待的包
* @return future. 可进行超时处理
*
* Kotlin DSL: 仅 Kotlin 使用.
*/
@JvmSynthetic
inline
fun
<
reified
P
:
ServerPacket
>
expectPacket
(
toSend
:
ClientPacket
,
noinline
handler
:
(
P
)
->
Unit
):
CompletableFuture
<
Unit
>
{
val
future
=
CompletableFuture
<
Unit
>()
this
.
bot
.
network
.
addHandler
(
TemporaryPacketHandler
(
P
::
class
,
future
,
this
).
also
{
it
.
toSend
{
toSend
}
it
.
expect
(
handler
)
})
return
future
}
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/network/Protocol.kt
View file @
86d64f02
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
)
package
net.mamoe.mirai.network
package
net.mamoe.mirai.network
import
java.net.InetAddress
import
java.net.InetAddress
...
@@ -72,7 +74,7 @@ object Protocol {
...
@@ -72,7 +74,7 @@ object Protocol {
private
val
hexToByteArrayCacheMap
:
MutableMap
<
Int
,
ByteArray
>
=
mutableMapOf
()
private
val
hexToByteArrayCacheMap
:
MutableMap
<
Int
,
ByteArray
>
=
mutableMapOf
()
@ExperimentalUnsignedTypes
fun
hexToBytes
(
hex
:
String
):
ByteArray
{
fun
hexToBytes
(
hex
:
String
):
ByteArray
{
hex
.
hashCode
().
let
{
id
->
hex
.
hashCode
().
let
{
id
->
if
(
hexToByteArrayCacheMap
.
containsKey
(
id
))
{
if
(
hexToByteArrayCacheMap
.
containsKey
(
id
))
{
...
@@ -86,7 +88,7 @@ object Protocol {
...
@@ -86,7 +88,7 @@ object Protocol {
}
}
}
}
@ExperimentalUnsignedTypes
fun
hexToUBytes
(
hex
:
String
):
UByteArray
=
Arrays
fun
hexToUBytes
(
hex
:
String
):
UByteArray
=
Arrays
.
stream
(
hex
.
split
(
" "
.
toRegex
()).
dropLastWhile
{
it
.
isEmpty
()
}.
toTypedArray
())
.
stream
(
hex
.
split
(
" "
.
toRegex
()).
dropLastWhile
{
it
.
isEmpty
()
}.
toTypedArray
())
.
map
{
value
->
value
.
trim
{
it
<=
' '
}
}
.
map
{
value
->
value
.
trim
{
it
<=
' '
}
}
...
...
mirai-core/src/main/java/net/mamoe/mirai/network/handler/ActionPacketHandler.kt
0 → 100644
View file @
86d64f02
package
net.mamoe.mirai.network.handler
import
net.mamoe.mirai.network.LoginSession
import
net.mamoe.mirai.network.packet.*
import
net.mamoe.mirai.network.packet.action.AddFriendResult
import
net.mamoe.mirai.network.packet.action.ClientAddFriendPacket
import
net.mamoe.mirai.network.packet.action.ClientCanAddFriendPacket
import
net.mamoe.mirai.network.packet.action.ServerCanAddFriendResponsePacket
import
net.mamoe.mirai.network.packet.image.ServerTryUploadGroupImageFailedPacket
import
net.mamoe.mirai.network.packet.image.ServerTryUploadGroupImageResponsePacket
import
net.mamoe.mirai.network.packet.image.ServerTryUploadGroupImageSuccessPacket
import
net.mamoe.mirai.task.MiraiThreadPool
import
net.mamoe.mirai.utils.getGTK
import
java.awt.image.BufferedImage
import
java.io.Closeable
import
java.util.*
import
java.util.concurrent.CompletableFuture
import
java.util.concurrent.ScheduledFuture
import
java.util.concurrent.TimeUnit
import
java.util.function.Supplier
/**
* 动作: 获取好友列表, 点赞, 踢人等.
* 处理动作事件, 承担动作任务.
*
* @author Him188moe
*/
class
ActionPacketHandler
(
session
:
LoginSession
)
:
PacketHandler
(
session
)
{
private
val
addFriendSessions
=
Collections
.
synchronizedCollection
(
mutableListOf
<
AddFriendSession
>())
private
val
uploadImageSessions
=
Collections
.
synchronizedCollection
(
mutableListOf
<
UploadImageSession
>())
private
var
sKeyRefresherFuture
:
ScheduledFuture
<
*
>?
=
null
override
fun
onPacketReceived
(
packet
:
ServerPacket
)
{
when
(
packet
)
{
is
ServerCanAddFriendResponsePacket
->
{
this
.
uploadImageSessions
.
forEach
{
it
.
onPacketReceived
(
packet
)
}
}
is
ServerTryUploadGroupImageSuccessPacket
->
{
// ImageNetworkUtils.postImage(packet.uKey.toUHexString(), )
}
is
ServerTryUploadGroupImageFailedPacket
->
{
}
is
ServerTryUploadGroupImageResponsePacket
.
Encrypted
->
session
.
socket
.
distributePacket
(
packet
.
decrypt
(
session
.
sessionKey
))
is
ServerAccountInfoResponsePacket
.
Encrypted
->
session
.
socket
.
distributePacket
(
packet
.
decrypt
(
session
.
sessionKey
))
is
ServerAccountInfoResponsePacket
->
{
}
is
ServerSKeyResponsePacket
.
Encrypted
->
session
.
socket
.
distributePacket
(
packet
.
decrypt
(
session
.
sessionKey
))
is
ServerSKeyResponsePacket
->
{
session
.
sKey
=
packet
.
sKey
session
.
cookies
=
"uin=o"
+
session
.
bot
.
account
.
qqNumber
+
";skey="
+
session
.
sKey
+
";"
sKeyRefresherFuture
=
MiraiThreadPool
.
getInstance
().
scheduleWithFixedDelay
({
session
.
socket
.
sendPacket
(
ClientSKeyRefreshmentRequestPacket
(
session
.
bot
.
account
.
qqNumber
,
session
.
sessionKey
))
},
1800000
,
1800000
,
TimeUnit
.
MILLISECONDS
)
session
.
gtk
=
getGTK
(
session
.
sKey
)
}
is
ServerEventPacket
.
Raw
.
Encrypted
->
session
.
socket
.
distributePacket
(
packet
.
decrypt
(
session
.
sessionKey
))
is
ServerEventPacket
.
Raw
->
session
.
socket
.
distributePacket
(
packet
.
distribute
())
else
->
{
}
}
}
fun
addFriend
(
qqNumber
:
Long
,
message
:
Supplier
<
String
>)
{
addFriend
(
qqNumber
,
lazy
{
message
.
get
()
})
}
@JvmSynthetic
fun
addFriend
(
qqNumber
:
Long
,
message
:
Lazy
<
String
>
=
lazyOf
(
""
)):
CompletableFuture
<
AddFriendResult
>
{
val
future
=
CompletableFuture
<
AddFriendResult
>()
val
session
=
AddFriendSession
(
qqNumber
,
future
,
message
)
// uploadImageSessions.add(session)
session
.
sendAddRequest
();
return
future
}
fun
requestSKey
()
{
session
.
socket
.
sendPacket
(
ClientSKeyRequestPacket
(
session
.
bot
.
account
.
qqNumber
,
session
.
sessionKey
))
}
fun
requestAccountInfo
()
{
session
.
socket
.
sendPacket
(
ClientAccountInfoRequestPacket
(
session
.
bot
.
account
.
qqNumber
,
session
.
sessionKey
))
}
override
fun
close
()
{
this
.
sKeyRefresherFuture
?.
cancel
(
true
)
this
.
sKeyRefresherFuture
=
null
}
private
inner
class
UploadImageSession
(
private
val
group
:
Long
,
private
val
future
:
CompletableFuture
<
AddFriendResult
>,
private
val
image
:
BufferedImage
)
:
Closeable
{
lateinit
var
id
:
ByteArray
fun
onPacketReceived
(
packet
:
ServerPacket
)
{
if
(!
::
id
.
isInitialized
)
{
return
}
when
(
packet
)
{
is
ServerCanAddFriendResponsePacket
->
{
if
(!(
packet
.
idByteArray
[
2
]
==
id
[
0
]
&&
packet
.
idByteArray
[
3
]
==
id
[
1
]))
{
return
}
when
(
packet
.
state
)
{
ServerCanAddFriendResponsePacket
.
State
.
FAILED
->
{
future
.
complete
(
AddFriendResult
.
FAILED
)
close
()
}
ServerCanAddFriendResponsePacket
.
State
.
ALREADY_ADDED
->
{
future
.
complete
(
AddFriendResult
.
ALREADY_ADDED
)
close
()
}
ServerCanAddFriendResponsePacket
.
State
.
REQUIRE_VERIFICATION
->
{
// session.socket.sendPacket(ClientAddFriendPacket(session.bot.account.qqNumber, qq, session.sessionKey))
}
ServerCanAddFriendResponsePacket
.
State
.
NOT_REQUIRE_VERIFICATION
->
{
}
}
}
}
}
fun
sendRequest
()
{
}
override
fun
close
()
{
uploadImageSessions
.
remove
(
this
)
}
}
private
inner
class
AddFriendSession
(
private
val
qq
:
Long
,
private
val
future
:
CompletableFuture
<
AddFriendResult
>,
private
val
message
:
Lazy
<
String
>
)
:
Closeable
{
lateinit
var
id
:
ByteArray
fun
onPacketReceived
(
packet
:
ServerPacket
)
{
if
(!
::
id
.
isInitialized
)
{
return
}
when
(
packet
)
{
is
ServerCanAddFriendResponsePacket
->
{
if
(!(
packet
.
idByteArray
[
2
]
==
id
[
0
]
&&
packet
.
idByteArray
[
3
]
==
id
[
1
]))
{
return
}
when
(
packet
.
state
)
{
ServerCanAddFriendResponsePacket
.
State
.
FAILED
->
{
future
.
complete
(
AddFriendResult
.
FAILED
)
close
()
}
ServerCanAddFriendResponsePacket
.
State
.
ALREADY_ADDED
->
{
future
.
complete
(
AddFriendResult
.
ALREADY_ADDED
)
close
()
}
ServerCanAddFriendResponsePacket
.
State
.
REQUIRE_VERIFICATION
->
{
session
.
socket
.
sendPacket
(
ClientAddFriendPacket
(
session
.
bot
.
account
.
qqNumber
,
qq
,
session
.
sessionKey
))
}
ServerCanAddFriendResponsePacket
.
State
.
NOT_REQUIRE_VERIFICATION
->
{
}
}
}
}
}
fun
sendAddRequest
()
{
session
.
socket
.
sendPacket
(
ClientCanAddFriendPacket
(
session
.
bot
.
account
.
qqNumber
,
qq
,
session
.
sessionKey
).
also
{
this
.
id
=
it
.
packetIdLast
})
}
override
fun
close
()
{
// uploadImageSessions.remove(this)
}
}
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/network/handler/DataPacketSocket.kt
0 → 100644
View file @
86d64f02
package
net.mamoe.mirai.network.handler
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.event.events.network.ServerPacketReceivedEvent
import
net.mamoe.mirai.network.BotNetworkHandlerImpl
import
net.mamoe.mirai.network.LoginSession
import
net.mamoe.mirai.network.packet.ClientPacket
import
net.mamoe.mirai.network.packet.ServerPacket
import
net.mamoe.mirai.task.MiraiThreadPool
import
java.io.Closeable
import
java.util.concurrent.Future
/**
* 网络接口.
* 发包 / 处理包.
* 仅可通过 [BotNetworkHandlerImpl.socket] 得到实例.
*
* @author Him188moe
*/
interface
DataPacketSocket
:
Closeable
{
fun
getOwner
():
Bot
/**
* 分发数据包给 [PacketHandler]
*/
fun
distributePacket
(
packet
:
ServerPacket
)
/**
* 发送一个数据包(非异步).
*
* 可通过 hook 事件 [ServerPacketReceivedEvent] 来获取服务器返回.
*
* @see [LoginSession.expectPacket] kotlin DSL
*/
fun
sendPacket
(
packet
:
ClientPacket
)
/**
* 发送一个数据包(异步).
*
* 可通过 hook 事件 [ServerPacketReceivedEvent] 来获取服务器返回.
*
* @see [LoginSession.expectPacket] kotlin DSL
*/
fun
sendPacketAsync
(
packet
:
ClientPacket
):
Future
<
*
>
{
return
MiraiThreadPool
.
getInstance
().
submit
{
sendPacket
(
packet
)
}
}
fun
isClosed
():
Boolean
override
fun
close
()
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/network/handler/MessagePacketHandler.kt
0 → 100644
View file @
86d64f02
package
net.mamoe.mirai.network.handler
import
net.mamoe.mirai.contact.Group
import
net.mamoe.mirai.contact.QQ
import
net.mamoe.mirai.event.events.qq.FriendMessageEvent
import
net.mamoe.mirai.event.hookWhile
import
net.mamoe.mirai.message.defaults.MessageChain
import
net.mamoe.mirai.message.defaults.PlainText
import
net.mamoe.mirai.message.defaults.UnsolvedImage
import
net.mamoe.mirai.network.LoginSession
import
net.mamoe.mirai.network.packet.*
import
net.mamoe.mirai.network.packet.action.ClientSendFriendMessagePacket
import
net.mamoe.mirai.network.packet.action.ClientSendGroupMessagePacket
import
net.mamoe.mirai.network.packet.action.ServerSendFriendMessageResponsePacket
import
net.mamoe.mirai.network.packet.action.ServerSendGroupMessageResponsePacket
import
java.io.File
/**
* 处理消息事件, 承担消息发送任务.
*
* @author Him188moe
*/
@Suppress
(
"EXPERIMENTAL_API_USAGE"
)
class
MessagePacketHandler
(
session
:
LoginSession
)
:
PacketHandler
(
session
)
{
internal
var
ignoreMessage
:
Boolean
=
true
init
{
//todo for test
FriendMessageEvent
::
class
.
hookWhile
{
if
(
session
.
socket
.
isClosed
())
{
return
@
hookWhile
false
}
when
{
it
.
message
()
valueEquals
"你好"
->
it
.
qq
.
sendMessage
(
"你好!"
)
it
.
message
().
toString
().
startsWith
(
"复读"
)
->
it
.
qq
.
sendMessage
(
it
.
message
())
it
.
message
().
toString
().
startsWith
(
"发群"
)
->
{
it
.
message
().
list
.
toMutableList
().
let
{
messages
->
messages
.
removeAt
(
0
)
sendGroupMessage
(
Group
(
session
.
bot
,
580266363
),
MessageChain
(
messages
))
}
}
it
.
message
()
valueEquals
"发图片"
->
sendGroupMessage
(
Group
(
session
.
bot
,
580266363
),
PlainText
(
"test"
)
+
UnsolvedImage
(
File
(
"C:\\Users\\Him18\\Desktop\\faceImage_1559564477775.jpg"
)).
also
{
image
->
image
.
upload
(
session
,
it
.
qq
).
get
()
})
}
return
@
hookWhile
true
}
}
override
fun
onPacketReceived
(
packet
:
ServerPacket
)
{
when
(
packet
)
{
is
ServerGroupUploadFileEventPacket
->
{
//todo
}
is
ServerFriendMessageEventPacket
->
{
if
(
ignoreMessage
)
{
return
}
FriendMessageEvent
(
session
.
bot
,
session
.
bot
.
contacts
.
getQQ
(
packet
.
qq
),
packet
.
message
).
broadcast
()
}
is
ServerGroupMessageEventPacket
->
{
//todo message chain
//GroupMessageEvent(this.bot, bot.contacts.getGroupByNumber(packet.groupNumber), bot.contacts.getQQ(packet.qq), packet.message)
}
is
UnknownServerEventPacket
->
{
//todo
}
is
ServerSendFriendMessageResponsePacket
,
is
ServerSendGroupMessageResponsePacket
->
{
//ignored
}
else
->
{
//ignored
}
}
}
fun
sendFriendMessage
(
qq
:
QQ
,
message
:
MessageChain
)
{
session
.
socket
.
sendPacketAsync
(
ClientSendFriendMessagePacket
(
session
.
bot
.
account
.
qqNumber
,
qq
.
number
,
session
.
sessionKey
,
message
))
}
fun
sendGroupMessage
(
group
:
Group
,
message
:
MessageChain
)
{
session
.
socket
.
sendPacket
(
ClientSendGroupMessagePacket
(
group
.
groupId
,
session
.
bot
.
account
.
qqNumber
,
session
.
sessionKey
,
message
))
}
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/network/handler/PacketHandler.kt
0 → 100644
View file @
86d64f02
package
net.mamoe.mirai.network.handler
import
net.mamoe.mirai.network.LoginSession
import
net.mamoe.mirai.network.packet.ServerPacket
import
net.mamoe.mirai.utils.MiraiSynchronizedLinkedList
import
java.io.Closeable
/**
* 数据包(接受/发送)处理器
*/
abstract
class
PacketHandler
(
val
session
:
LoginSession
)
:
Closeable
{
abstract
fun
onPacketReceived
(
packet
:
ServerPacket
)
override
fun
close
()
{
}
}
class
PacketHandlerNode
<
T
:
PacketHandler
>(
val
clazz
:
Class
<
T
>,
val
instance
:
T
)
fun
PacketHandler
.
asNode
():
PacketHandlerNode
<
PacketHandler
>
{
return
PacketHandlerNode
(
this
.
javaClass
,
this
)
}
class
PacketHandlerList
:
MiraiSynchronizedLinkedList
<
PacketHandlerNode
<
*
>>()
{
fun
<
T
:
PacketHandler
>
get
(
clazz
:
Class
<
T
>):
T
{
this
.
forEach
{
if
(
it
.
clazz
==
clazz
)
{
@Suppress
(
"UNCHECKED_CAST"
)
return
@
get
it
.
instance
as
T
}
}
throw
NoSuchElementException
()
}
}
mirai-core/src/main/java/net/mamoe/mirai/network/handler/TemporaryPacketHandler.kt
0 → 100644
View file @
86d64f02
package
net.mamoe.mirai.network.handler
import
net.mamoe.mirai.network.LoginSession
import
net.mamoe.mirai.network.packet.ClientPacket
import
net.mamoe.mirai.network.packet.ServerPacket
import
java.util.concurrent.CompletableFuture
import
kotlin.reflect.KClass
/**
* 临时数据包处理器
*
* @see LoginSession.expectPacket
*/
open
class
TemporaryPacketHandler
<
P
:
ServerPacket
>(
private
val
expectationClass
:
KClass
<
P
>,
private
val
future
:
CompletableFuture
<
Unit
>,
private
val
fromSession
:
LoginSession
)
{
private
lateinit
var
toSend
:
ClientPacket
private
lateinit
var
expect
:
(
P
)
->
Unit
lateinit
var
session
:
LoginSession
//无需覆盖
fun
toSend
(
packet
:
()
->
ClientPacket
)
{
this
.
toSend
=
packet
()
}
fun
expect
(
handler
:
(
P
)
->
Unit
)
{
this
.
expect
=
handler
}
fun
send
(
session
:
LoginSession
)
{
this
.
session
=
session
session
.
socket
.
sendPacket
(
toSend
)
}
fun
onPacketReceived
(
session
:
LoginSession
,
packet
:
ServerPacket
):
Boolean
{
if
(
expectationClass
.
isInstance
(
packet
)
&&
session
===
this
.
fromSession
)
{
@Suppress
(
"UNCHECKED_CAST"
)
expect
(
packet
as
P
)
future
.
complete
(
Unit
)
return
true
}
return
false
}
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/network/packet/ClientPacket.kt
View file @
86d64f02
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
,
"EXPERIMENTAL_UNSIGNED_LITERALS"
)
package
net.mamoe.mirai.network.packet
package
net.mamoe.mirai.network.packet
import
lombok.Getter
import
lombok.Getter
...
@@ -12,12 +14,12 @@ import java.security.MessageDigest
...
@@ -12,12 +14,12 @@ import java.security.MessageDigest
/**
/**
* @author Him188moe
* @author Him188moe
*/
*/
@ExperimentalUnsignedTypes
abstract
class
ClientPacket
:
ByteArrayDataOutputStream
(),
Packet
{
abstract
class
ClientPacket
:
ByteArrayDataOutputStream
(),
Packet
{
@Getter
@Getter
val
idHex
:
String
val
idHex
:
String
var
encoded
:
Boolean
=
false
private
var
encoded
:
Boolean
=
false
init
{
init
{
val
annotation
=
this
.
javaClass
.
getAnnotation
(
PacketId
::
class
.
java
)
val
annotation
=
this
.
javaClass
.
getAnnotation
(
PacketId
::
class
.
java
)
...
@@ -84,7 +86,6 @@ abstract class ClientPacket : ByteArrayDataOutputStream(), Packet {
...
@@ -84,7 +86,6 @@ abstract class ClientPacket : ByteArrayDataOutputStream(), Packet {
}
}
@ExperimentalUnsignedTypes
@Throws
(
IOException
::
class
)
@Throws
(
IOException
::
class
)
fun
DataOutputStream
.
writeIP
(
ip
:
String
)
{
fun
DataOutputStream
.
writeIP
(
ip
:
String
)
{
for
(
s
in
ip
.
trim
().
split
(
"\\."
.
toRegex
()).
dropLastWhile
{
it
.
isEmpty
()
}.
toTypedArray
())
{
for
(
s
in
ip
.
trim
().
split
(
"\\."
.
toRegex
()).
dropLastWhile
{
it
.
isEmpty
()
}.
toTypedArray
())
{
...
@@ -97,14 +98,13 @@ fun DataOutputStream.writeTime() {
...
@@ -97,14 +98,13 @@ fun DataOutputStream.writeTime() {
this
.
writeInt
(
System
.
currentTimeMillis
().
toInt
())
this
.
writeInt
(
System
.
currentTimeMillis
().
toInt
())
}
}
@ExperimentalUnsignedTypes
@Throws
(
IOException
::
class
)
@Throws
(
IOException
::
class
)
fun
DataOutputStream
.
writeHex
(
h
ex
:
String
)
{
fun
DataOutputStream
.
writeHex
(
uH
ex
:
String
)
{
for
(
s
in
h
ex
.
trim
().
split
(
" "
.
toRegex
()).
dropLastWhile
{
it
.
isEmpty
()
}.
toTypedArray
())
{
for
(
s
in
uH
ex
.
trim
().
split
(
" "
.
toRegex
()).
dropLastWhile
{
it
.
isEmpty
()
}.
toTypedArray
())
{
if
(
s
.
isEmpty
())
{
if
(
s
.
isEmpty
())
{
continue
continue
}
}
this
.
writeByte
(
s
.
toUByte
(
16
).
to
Byte
().
to
Int
())
this
.
writeByte
(
s
.
toUByte
(
16
).
toInt
())
}
}
}
}
...
@@ -113,15 +113,13 @@ fun DataOutputStream.encryptAndWrite(byteArray: ByteArray, key: ByteArray) {
...
@@ -113,15 +113,13 @@ fun DataOutputStream.encryptAndWrite(byteArray: ByteArray, key: ByteArray) {
}
}
fun
DataOutputStream
.
encryptAndWrite
(
key
:
ByteArray
,
encoder
:
(
ByteArrayDataOutputStream
)
->
Unit
)
{
fun
DataOutputStream
.
encryptAndWrite
(
key
:
ByteArray
,
encoder
:
(
ByteArrayDataOutputStream
)
->
Unit
)
{
this
.
write
(
TEA
.
encrypt
(
ByteArrayDataOutputStream
().
let
{
encoder
(
it
);
it
.
toByteArray
()
}
,
key
))
this
.
write
(
TEA
.
encrypt
(
ByteArrayDataOutputStream
().
also
(
encoder
).
toByteArray
()
,
key
))
}
}
@ExperimentalUnsignedTypes
fun
DataOutputStream
.
encryptAndWrite
(
keyHex
:
String
,
encoder
:
(
ByteArrayDataOutputStream
)
->
Unit
)
{
fun
DataOutputStream
.
encryptAndWrite
(
keyHex
:
String
,
encoder
:
(
ByteArrayDataOutputStream
)
->
Unit
)
{
this
.
encryptAndWrite
(
keyHex
.
hexToBytes
(),
encoder
)
this
.
encryptAndWrite
(
keyHex
.
hexToBytes
(),
encoder
)
}
}
@ExperimentalUnsignedTypes
@Throws
(
IOException
::
class
)
@Throws
(
IOException
::
class
)
fun
DataOutputStream
.
writeTLV0006
(
qq
:
Long
,
password
:
String
,
loginTime
:
Int
,
loginIP
:
String
,
tgtgtKey
:
ByteArray
)
{
fun
DataOutputStream
.
writeTLV0006
(
qq
:
Long
,
password
:
String
,
loginTime
:
Int
,
loginIP
:
String
,
tgtgtKey
:
ByteArray
)
{
ByteArrayDataOutputStream
().
let
{
ByteArrayDataOutputStream
().
let
{
...
@@ -146,12 +144,10 @@ fun DataOutputStream.writeTLV0006(qq: Long, password: String, loginTime: Int, lo
...
@@ -146,12 +144,10 @@ fun DataOutputStream.writeTLV0006(qq: Long, password: String, loginTime: Int, lo
}
}
}
}
@ExperimentalUnsignedTypes
@Tested
@TestedSuccessfully
fun
DataOutputStream
.
writeCRC32
()
=
writeCRC32
(
getRandomByteArray
(
16
))
fun
DataOutputStream
.
writeCRC32
()
=
writeCRC32
(
getRandomByteArray
(
16
))
@ExperimentalUnsignedTypes
fun
DataOutputStream
.
writeCRC32
(
key
:
ByteArray
)
{
fun
DataOutputStream
.
writeCRC32
(
key
:
ByteArray
)
{
key
.
let
{
key
.
let
{
write
(
it
)
//key
write
(
it
)
//key
...
@@ -159,8 +155,8 @@ fun DataOutputStream.writeCRC32(key: ByteArray) {
...
@@ -159,8 +155,8 @@ fun DataOutputStream.writeCRC32(key: ByteArray) {
}
}
}
}
@ExperimentalUnsignedTypes
@Tested
Successfully
@Tested
fun
DataOutputStream
.
writeDeviceName
(
random
:
Boolean
=
false
)
{
fun
DataOutputStream
.
writeDeviceName
(
random
:
Boolean
=
false
)
{
val
deviceName
:
String
=
if
(
random
)
{
val
deviceName
:
String
=
if
(
random
)
{
String
(
getRandomByteArray
(
10
))
String
(
getRandomByteArray
(
10
))
...
@@ -185,7 +181,7 @@ fun Int.toByteArray(): ByteArray = byteArrayOf(
...
@@ -185,7 +181,7 @@ fun Int.toByteArray(): ByteArray = byteArrayOf(
/**
/**
* 255u -> 00 00 00 FF
* 255u -> 00 00 00 FF
*/
*/
@ExperimentalUnsignedTypes
fun
UInt
.
toByteArray
():
ByteArray
=
byteArrayOf
(
fun
UInt
.
toByteArray
():
ByteArray
=
byteArrayOf
(
(
this
.
shr
(
24
)
and
255
u
).
toByte
(),
(
this
.
shr
(
24
)
and
255
u
).
toByte
(),
(
this
.
shr
(
16
)
and
255
u
).
toByte
(),
(
this
.
shr
(
16
)
and
255
u
).
toByte
(),
...
@@ -193,24 +189,14 @@ fun UInt.toByteArray(): ByteArray = byteArrayOf(
...
@@ -193,24 +189,14 @@ fun UInt.toByteArray(): ByteArray = byteArrayOf(
(
this
.
shr
(
0
)
and
255
u
).
toByte
()
(
this
.
shr
(
0
)
and
255
u
).
toByte
()
)
)
/**
* 255 -> FF 00 00 00
*/
fun
Int
.
toLByteArray
():
ByteArray
=
byteArrayOf
(
(
this
.
ushr
(
0
)
and
0
xFF
).
toByte
(),
(
this
.
ushr
(
8
)
and
0
xFF
).
toByte
(),
(
this
.
ushr
(
16
)
and
0
xFF
).
toByte
(),
(
this
.
ushr
(
24
)
and
0
xFF
).
toByte
()
)
@ExperimentalUnsignedTypes
fun
Int
.
toUHexString
(
separator
:
String
=
" "
):
String
=
this
.
toByteArray
().
toUHexString
(
separator
)
fun
Int
.
toUHexString
(
separator
:
String
=
" "
):
String
=
this
.
toByteArray
().
toUByteArray
().
toUHexString
(
separator
)
internal
fun
md5
(
str
:
String
):
ByteArray
=
MessageDigest
.
getInstance
(
"MD5"
).
digest
(
str
.
toByteArray
())
internal
fun
md5
(
str
:
String
):
ByteArray
=
MessageDigest
.
getInstance
(
"MD5"
).
digest
(
str
.
toByteArray
())
internal
fun
md5
(
byteArray
:
ByteArray
):
ByteArray
=
MessageDigest
.
getInstance
(
"MD5"
).
digest
(
byteArray
)
internal
fun
md5
(
byteArray
:
ByteArray
):
ByteArray
=
MessageDigest
.
getInstance
(
"MD5"
).
digest
(
byteArray
)
@ExperimentalUnsignedTypes
@Throws
(
IOException
::
class
)
@Throws
(
IOException
::
class
)
fun
DataOutputStream
.
writeZero
(
count
:
Int
)
{
fun
DataOutputStream
.
writeZero
(
count
:
Int
)
{
repeat
(
count
)
{
repeat
(
count
)
{
...
@@ -225,33 +211,26 @@ fun DataOutputStream.writeRandom(length: Int) {
...
@@ -225,33 +211,26 @@ fun DataOutputStream.writeRandom(length: Int) {
}
}
}
}
@ExperimentalUnsignedTypes
@Throws
(
IOException
::
class
)
@Throws
(
IOException
::
class
)
fun
DataOutputStream
.
writeQQ
(
qq
:
Long
)
{
fun
DataOutputStream
.
writeQQ
(
qq
:
Long
)
{
this
.
write
(
qq
.
toUInt
().
toByteArray
())
this
.
write
(
qq
.
toUInt
().
toByteArray
())
}
}
@ExperimentalUnsignedTypes
@Throws
(
IOException
::
class
)
@Throws
(
IOException
::
class
)
fun
DataOutputStream
.
writeGroup
(
groupIdOrGroupNumber
:
Long
)
{
fun
DataOutputStream
.
writeGroup
(
groupIdOrGroupNumber
:
Long
)
{
this
.
write
(
groupIdOrGroupNumber
.
toUInt
().
toByteArray
())
this
.
write
(
groupIdOrGroupNumber
.
toUInt
().
toByteArray
())
}
}
fun
DataOutputStream
.
write
Var
ByteArray
(
byteArray
:
ByteArray
)
{
fun
DataOutputStream
.
write
LV
ByteArray
(
byteArray
:
ByteArray
)
{
this
.
writeShort
(
byteArray
.
size
)
this
.
writeShort
(
byteArray
.
size
)
this
.
write
(
byteArray
)
this
.
write
(
byteArray
)
}
}
fun
DataOutputStream
.
writeVarString
(
str
:
String
)
{
fun
DataOutputStream
.
writeLVString
(
str
:
String
)
{
this
.
writeVarByteArray
(
str
.
toByteArray
())
this
.
writeLVByteArray
(
str
.
toByteArray
())
}
fun
DataOutputStream
.
writeVarShort
(
short
:
Int
)
{
this
.
writeByte
(
0
x02
)
this
.
writeShort
(
short
)
}
}
fun
DataOutputStream
.
writeVarInt
(
int
:
Int
)
{
fun
DataOutputStream
.
writeLVHex
(
hex
:
String
)
{
this
.
writeByte
(
0
x04
)
this
.
writeLVByteArray
(
hex
.
hexToBytes
())
this
.
writeInt
(
int
)
}
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/network/packet/GradeInfo.kt
View file @
86d64f02
...
@@ -9,7 +9,7 @@ import java.io.DataInputStream
...
@@ -9,7 +9,7 @@ import java.io.DataInputStream
*
*
* @author Him188moe
* @author Him188moe
*/
*/
@ExperimentalUnsignedTypes
@PacketId
(
"00 5C"
)
@PacketId
(
"00 5C"
)
class
ClientAccountInfoRequestPacket
(
class
ClientAccountInfoRequestPacket
(
private
val
qq
:
Long
,
private
val
qq
:
Long
,
...
...
mirai-core/src/main/java/net/mamoe/mirai/network/packet/Heartbeat.kt
View file @
86d64f02
...
@@ -7,7 +7,7 @@ import java.io.IOException
...
@@ -7,7 +7,7 @@ import java.io.IOException
/**
/**
* @author Him188moe
* @author Him188moe
*/
*/
@ExperimentalUnsignedTypes
@PacketId
(
"00 58"
)
@PacketId
(
"00 58"
)
class
ClientHeartbeatPacket
(
class
ClientHeartbeatPacket
(
private
val
qq
:
Long
,
private
val
qq
:
Long
,
...
...
mirai-core/src/main/java/net/mamoe/mirai/network/packet/SKey.kt
View file @
86d64f02
...
@@ -6,9 +6,11 @@ import java.io.DataInputStream
...
@@ -6,9 +6,11 @@ import java.io.DataInputStream
/**
/**
* SKey 用于 http api
*
* @author Him188moe
* @author Him188moe
*/
*/
@ExperimentalUnsignedTypes
@PacketId
(
"00 1D"
)
@PacketId
(
"00 1D"
)
class
ClientSKeyRequestPacket
(
class
ClientSKeyRequestPacket
(
private
val
qq
:
Long
,
private
val
qq
:
Long
,
...
@@ -29,7 +31,7 @@ class ClientSKeyRequestPacket(
...
@@ -29,7 +31,7 @@ class ClientSKeyRequestPacket(
* @author Him188moe
* @author Him188moe
*/
*/
@PacketId
(
"00 1D"
)
@PacketId
(
"00 1D"
)
@ExperimentalUnsignedTypes
class
ClientSKeyRefreshmentRequestPacket
(
class
ClientSKeyRefreshmentRequestPacket
(
private
val
qq
:
Long
,
private
val
qq
:
Long
,
private
val
sessionKey
:
ByteArray
private
val
sessionKey
:
ByteArray
...
...
mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerEvent.kt
View file @
86d64f02
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
)
package
net.mamoe.mirai.network.packet
package
net.mamoe.mirai.network.packet
import
net.mamoe.mirai.message.FaceID
import
net.mamoe.mirai.message.FaceID
...
@@ -19,10 +21,10 @@ import java.util.zip.GZIPInputStream
...
@@ -19,10 +21,10 @@ import java.util.zip.GZIPInputStream
*
*
* @author Him188moe
* @author Him188moe
*/
*/
open
class
ServerEventPacket
(
input
:
DataInputStream
,
val
packetId
:
ByteArray
,
val
eventIdentity
:
ByteArray
)
:
ServerPacket
(
input
)
{
abstract
class
ServerEventPacket
(
input
:
DataInputStream
,
val
packetId
:
ByteArray
,
val
eventIdentity
:
ByteArray
)
:
ServerPacket
(
input
)
{
@PacketId
(
"00 17"
)
@PacketId
(
"00 17"
)
class
Raw
(
input
:
DataInputStream
,
private
val
packetId
:
ByteArray
)
:
ServerPacket
(
input
)
{
class
Raw
(
input
:
DataInputStream
,
private
val
packetId
:
ByteArray
)
:
ServerPacket
(
input
)
{
@ExperimentalUnsignedTypes
fun
distribute
():
ServerEventPacket
{
fun
distribute
():
ServerEventPacket
{
val
eventIdentity
=
this
.
input
.
readNBytes
(
16
)
val
eventIdentity
=
this
.
input
.
readNBytes
(
16
)
val
type
=
this
.
input
.
goto
(
18
).
readNBytes
(
2
)
val
type
=
this
.
input
.
goto
(
18
).
readNBytes
(
2
)
...
@@ -80,6 +82,7 @@ class ServerGroupUploadFileEventPacket(input: DataInputStream, packetId: ByteArr
...
@@ -80,6 +82,7 @@ class ServerGroupUploadFileEventPacket(input: DataInputStream, packetId: ByteArr
}
//todo test
}
//todo test
}
}
@Suppress
(
"EXPERIMENTAL_API_USAGE"
)
class
ServerGroupMessageEventPacket
(
input
:
DataInputStream
,
packetId
:
ByteArray
,
eventIdentity
:
ByteArray
)
:
ServerEventPacket
(
input
,
packetId
,
eventIdentity
)
{
class
ServerGroupMessageEventPacket
(
input
:
DataInputStream
,
packetId
:
ByteArray
,
eventIdentity
:
ByteArray
)
:
ServerEventPacket
(
input
,
packetId
,
eventIdentity
)
{
var
groupNumber
:
Long
=
0
var
groupNumber
:
Long
=
0
var
qq
:
Long
=
0
var
qq
:
Long
=
0
...
@@ -100,16 +103,17 @@ class ServerGroupMessageEventPacket(input: DataInputStream, packetId: ByteArray,
...
@@ -100,16 +103,17 @@ class ServerGroupMessageEventPacket(input: DataInputStream, packetId: ByteArray,
OTHER
,
OTHER
,
}
}
@ExperimentalUnsignedTypes
override
fun
decode
()
{
override
fun
decode
()
{
println
(
this
.
input
.
goto
(
0
).
readAllBytes
().
toUHexString
())
groupNumber
=
this
.
input
.
goto
(
51
).
readInt
().
toLong
()
groupNumber
=
this
.
input
.
goto
(
51
).
readInt
().
toLong
()
qq
=
this
.
input
.
goto
(
56
).
readLong
()
.
toUInt
().
toLong
()
qq
=
this
.
input
.
goto
(
56
).
readLong
()
val
fontLength
=
this
.
input
.
goto
(
108
).
readShort
()
val
fontLength
=
this
.
input
.
goto
(
108
).
readShort
()
//println(this.input.goto(110 + fontLength).readNBytesAt(2).toUHexString())//always 00 00
//println(this.input.goto(110 + fontLength).readNBytesAt(2).toUHexString())//always 00 00
messageType
=
when
(
val
id
=
this
.
input
.
goto
(
110
+
fontLength
+
2
).
readByte
().
toInt
())
{
messageType
=
when
(
val
id
=
this
.
input
.
goto
(
110
+
fontLength
+
2
).
readByte
().
toInt
())
{
0
x13
->
MessageType
.
NORMAL
0
x13
->
MessageType
.
NORMAL
0
xE
->
MessageType
.
XML
0
x
0
E
->
MessageType
.
XML
0
x06
->
MessageType
.
AT
0
x06
->
MessageType
.
AT
...
@@ -119,7 +123,7 @@ class ServerGroupMessageEventPacket(input: DataInputStream, packetId: ByteArray,
...
@@ -119,7 +123,7 @@ class ServerGroupMessageEventPacket(input: DataInputStream, packetId: ByteArray,
0
x19
->
MessageType
.
ANONYMOUS
0
x19
->
MessageType
.
ANONYMOUS
else
->
{
else
->
{
MiraiLogger
debug
(
"ServerGroupMessageEventPacket id=$id"
)
MiraiLogger
.
debug
(
"ServerGroupMessageEventPacket id=$id"
)
MessageType
.
OTHER
MessageType
.
OTHER
}
}
}
}
...
@@ -188,7 +192,7 @@ class ServerFriendMessageEventPacket(input: DataInputStream, packetId: ByteArray
...
@@ -188,7 +192,7 @@ class ServerFriendMessageEventPacket(input: DataInputStream, packetId: ByteArray
var
qq
:
Long
=
0
var
qq
:
Long
=
0
lateinit
var
message
:
MessageChain
lateinit
var
message
:
MessageChain
@ExperimentalUnsignedTypes
override
fun
decode
()
{
override
fun
decode
()
{
input
.
goto
(
0
)
input
.
goto
(
0
)
println
()
println
()
...
@@ -222,16 +226,16 @@ class ServerFriendMessageEventPacket(input: DataInputStream, packetId: ByteArray
...
@@ -222,16 +226,16 @@ class ServerFriendMessageEventPacket(input: DataInputStream, packetId: ByteArray
//00 01 AF 0B 00 08 00 01 00 04 52 CC F5 D0 FF 00 02 14 F0
//00 01 AF 0B 00 08 00 01 00 04 52 CC F5 D0 FF 00 02 14 F0
//00 01 0C 0B 00 08 00 01 00 04 52 CC F5 D0 FF 00 02 14 4D
//00 01 0C 0B 00 08 00 01 00 04 52 CC F5 D0 FF 00 02 14 4D
val
id1
=
FaceID
.
ofId
(
read
Var
Number
().
toInt
())
//可能这个是id, 也可能下面那个
val
id1
=
FaceID
.
ofId
(
read
LV
Number
().
toInt
())
//可能这个是id, 也可能下面那个
this
.
skip
(
this
.
readByte
().
toLong
())
this
.
skip
(
this
.
readByte
().
toLong
())
this
.
read
Var
Number
()
//某id?
this
.
read
LV
Number
()
//某id?
return
Face
(
id1
)
return
Face
(
id1
)
}
}
0
x06
->
{
0
x06
->
{
this
.
skip
(
sectionLength
-
37
-
1
)
this
.
skip
(
sectionLength
-
37
-
1
)
val
imageId
=
String
(
this
.
readNBytes
(
36
))
val
imageId
=
String
(
this
.
readNBytes
(
36
))
this
.
skip
(
1
)
//0x41
this
.
skip
(
1
)
//0x41
return
Image
(
imageId
)
return
Image
(
"{$imageId}.jpg"
)
//todo 如何确定文件后缀??
}
}
else
->
null
else
->
null
}
}
...
@@ -291,8 +295,7 @@ B1 89 BE 09 8F 00 1A E5 00 0B 03 A2 09 90 BB 7A 1F 40 00 A6 00 00 00 20 00 05 00
...
@@ -291,8 +295,7 @@ B1 89 BE 09 8F 00 1A E5 00 0B 03 A2 09 90 BB 7A 1F 40 00 A6 00 00 00 20 00 05 00
* 告知服务器已经收到数据
* 告知服务器已经收到数据
*/
*/
@PacketId
(
""
)
//随后写入
@PacketId
(
""
)
//随后写入
@ExperimentalUnsignedTypes
class
ClientEventResponsePacket
(
class
ClientMessageResponsePacket
(
private
val
qq
:
Long
,
private
val
qq
:
Long
,
private
val
packetIdFromServer
:
ByteArray
,
//4bytes
private
val
packetIdFromServer
:
ByteArray
,
//4bytes
private
val
sessionKey
:
ByteArray
,
private
val
sessionKey
:
ByteArray
,
...
@@ -329,7 +332,7 @@ class ServerFriendMessageEventPacket(input: DataInputStream, packetId: ByteArray
...
@@ -329,7 +332,7 @@ class ServerFriendMessageEventPacket(input: DataInputStream, packetId: ByteArray
lateinit var message: String
lateinit var message: String
@ExperimentalUnsignedTypes
override fun decode() {
override fun decode() {
//start at Sep1.0:27
//start at Sep1.0:27
qq = input.readIntAt(0)
qq = input.readIntAt(0)
...
...
mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerPacket.kt
View file @
86d64f02
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
)
//to simplify code
package
net.mamoe.mirai.network.packet
package
net.mamoe.mirai.network.packet
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.event.events.network.ServerPacketReceivedEvent
import
net.mamoe.mirai.event.hookWhile
import
net.mamoe.mirai.network.packet.PacketNameFormatter.adjustName
import
net.mamoe.mirai.network.packet.PacketNameFormatter.adjustName
import
net.mamoe.mirai.network.packet.action.ServerCanAddFriendResponsePacket
import
net.mamoe.mirai.network.packet.action.ServerCanAddFriendResponsePacket
import
net.mamoe.mirai.network.packet.action.ServerSendFriendMessageResponsePacket
import
net.mamoe.mirai.network.packet.action.ServerSendFriendMessageResponsePacket
import
net.mamoe.mirai.network.packet.action.ServerSendGroupMessageResponsePacket
import
net.mamoe.mirai.network.packet.action.ServerSendGroupMessageResponsePacket
import
net.mamoe.mirai.network.packet.image.ServerTryUploadGroupImageResponsePacket
import
net.mamoe.mirai.network.packet.login.*
import
net.mamoe.mirai.network.packet.login.*
import
net.mamoe.mirai.task.MiraiThreadPool
import
net.mamoe.mirai.utils.*
import
net.mamoe.mirai.utils.*
import
java.io.DataInputStream
import
java.io.DataInputStream
import
java.io.EOFException
import
kotlin.reflect.KClass
/**
/**
* @author Him188moe
* @author Him188moe
...
@@ -45,7 +56,6 @@ abstract class ServerPacket(val input: DataInputStream) : Packet {
...
@@ -45,7 +56,6 @@ abstract class ServerPacket(val input: DataInputStream) : Packet {
companion
object
{
companion
object
{
@ExperimentalUnsignedTypes
fun
ofByteArray
(
bytes
:
ByteArray
):
ServerPacket
{
fun
ofByteArray
(
bytes
:
ByteArray
):
ServerPacket
{
val
stream
=
bytes
.
dataInputStream
()
val
stream
=
bytes
.
dataInputStream
()
...
@@ -72,7 +82,7 @@ abstract class ServerPacket(val input: DataInputStream) : Packet {
...
@@ -72,7 +82,7 @@ abstract class ServerPacket(val input: DataInputStream) : Packet {
println
(
bytes
.
size
)
println
(
bytes
.
size
)
return
ServerLoginResponseFailedPacket
(
when
(
bytes
.
size
)
{
return
ServerLoginResponseFailedPacket
(
when
(
bytes
.
size
)
{
63
,
319
,
135
,
351
->
LoginState
.
WRONG_PASSWORD
//这四个其中一个
也
是被冻结
63
,
319
,
135
,
351
->
LoginState
.
WRONG_PASSWORD
//这四个其中一个是被冻结
//135 -> LoginState.RETYPE_PASSWORD
//135 -> LoginState.RETYPE_PASSWORD
279
->
LoginState
.
BLOCKED
279
->
LoginState
.
BLOCKED
263
->
LoginState
.
UNKNOWN_QQ_NUMBER
263
->
LoginState
.
UNKNOWN_QQ_NUMBER
...
@@ -111,6 +121,8 @@ abstract class ServerPacket(val input: DataInputStream) : Packet {
...
@@ -111,6 +121,8 @@ abstract class ServerPacket(val input: DataInputStream) : Packet {
"00 A7"
->
ServerCanAddFriendResponsePacket
(
stream
)
"00 A7"
->
ServerCanAddFriendResponsePacket
(
stream
)
"03 88"
->
ServerTryUploadGroupImageResponsePacket
.
Encrypted
(
stream
)
else
->
throw
IllegalArgumentException
(
idHex
)
else
->
throw
IllegalArgumentException
(
idHex
)
}
}
}.
apply
{
this
.
idHex
=
idHex
}
}.
apply
{
this
.
idHex
=
idHex
}
...
@@ -118,9 +130,8 @@ abstract class ServerPacket(val input: DataInputStream) : Packet {
...
@@ -118,9 +130,8 @@ abstract class ServerPacket(val input: DataInputStream) : Packet {
}
}
@ExperimentalUnsignedTypes
override
fun
toString
():
String
{
override
fun
toString
():
String
{
return
adjustName
(
this
.
javaClass
.
simpleName
+
"(${this.getFixedId()})"
)
+
this
.
getAllDeclaredFields
().
filterNot
{
it
.
name
==
"idHex"
||
it
.
name
==
"encoded"
}.
joinToString
(
", "
,
"{"
,
"}"
)
{
return
adjustName
(
this
.
javaClass
.
simpleName
+
"(${this.getFixedId()})"
)
+
this
.
getAllDeclaredFields
().
filterNot
{
it
.
name
==
"idHex"
||
it
.
name
==
"
idByteArray"
||
it
.
name
==
"
encoded"
}.
joinToString
(
", "
,
"{"
,
"}"
)
{
it
.
trySetAccessible
();
it
.
name
+
"="
+
it
.
get
(
this
).
let
{
value
->
it
.
trySetAccessible
();
it
.
name
+
"="
+
it
.
get
(
this
).
let
{
value
->
when
(
value
)
{
when
(
value
)
{
is
ByteArray
->
value
.
toUHexString
()
is
ByteArray
->
value
.
toUHexString
()
...
@@ -145,38 +156,37 @@ abstract class ServerPacket(val input: DataInputStream) : Packet {
...
@@ -145,38 +156,37 @@ abstract class ServerPacket(val input: DataInputStream) : Packet {
return
decryptAsByteArray
(
key
).
dataInputStream
()
return
decryptAsByteArray
(
key
).
dataInputStream
()
}
}
@ExperimentalUnsignedTypes
fun
decryptBy
(
keyHex
:
String
):
DataInputStream
{
fun
decryptBy
(
keyHex
:
String
):
DataInputStream
{
return
this
.
decryptBy
(
keyHex
.
hexToBytes
())
return
this
.
decryptBy
(
keyHex
.
hexToBytes
())
}
}
fun
decryptBy
(
key1
:
ByteArray
,
key2
:
ByteArray
):
DataInputStream
{
fun
decryptBy
(
key1
:
ByteArray
,
key2
:
ByteArray
):
DataInputStream
{
return
TEA
.
decrypt
(
this
.
decryptAsByteArray
(
key1
),
key2
).
dataInputStream
()
;
return
TEA
.
decrypt
(
this
.
decryptAsByteArray
(
key1
),
key2
).
dataInputStream
()
}
}
@ExperimentalUnsignedTypes
fun
decryptBy
(
key1
:
String
,
key2
:
ByteArray
):
DataInputStream
{
fun
decryptBy
(
key1
:
String
,
key2
:
ByteArray
):
DataInputStream
{
return
this
.
decryptBy
(
key1
.
hexToBytes
(),
key2
)
return
this
.
decryptBy
(
key1
.
hexToBytes
(),
key2
)
}
}
@ExperimentalUnsignedTypes
fun
decryptBy
(
key1
:
ByteArray
,
key2
:
String
):
DataInputStream
{
fun
decryptBy
(
key1
:
ByteArray
,
key2
:
String
):
DataInputStream
{
return
this
.
decryptBy
(
key1
,
key2
.
hexToBytes
())
return
this
.
decryptBy
(
key1
,
key2
.
hexToBytes
())
}
}
@ExperimentalUnsignedTypes
fun
decryptBy
(
keyHex1
:
String
,
keyHex2
:
String
):
DataInputStream
{
fun
decryptBy
(
keyHex1
:
String
,
keyHex2
:
String
):
DataInputStream
{
return
this
.
decryptBy
(
keyHex1
.
hexToBytes
(),
keyHex2
.
hexToBytes
())
return
this
.
decryptBy
(
keyHex1
.
hexToBytes
(),
keyHex2
.
hexToBytes
())
}
}
private
fun
decryptAsByteArray
(
key
:
ByteArray
):
ByteArray
{
fun
decryptAsByteArray
(
key
:
ByteArray
):
ByteArray
{
input
.
goto
(
14
)
input
.
goto
(
14
)
return
TEA
.
decrypt
(
input
.
readAllBytes
().
cutTail
(
1
),
key
)
return
TEA
.
decrypt
(
input
.
readAllBytes
().
cutTail
(
1
),
key
)
}
}
}
}
@ExperimentalUnsignedTypes
fun
DataInputStream
.
readIP
():
String
{
fun
DataInputStream
.
readIP
():
String
{
var
buff
=
""
var
buff
=
""
for
(
i
in
0
..
3
)
{
for
(
i
in
0
..
3
)
{
...
@@ -207,7 +217,7 @@ fun ByteArray.dataInputStream(): DataInputStream = DataInputStream(this.inputStr
...
@@ -207,7 +217,7 @@ fun ByteArray.dataInputStream(): DataInputStream = DataInputStream(this.inputStr
*/
*/
infix
fun
<
N
:
Number
>
DataInputStream
.
goto
(
position
:
N
):
DataInputStream
{
infix
fun
<
N
:
Number
>
DataInputStream
.
goto
(
position
:
N
):
DataInputStream
{
this
.
reset
()
this
.
reset
()
this
.
skip
(
position
.
toLong
())
;
this
.
skip
(
position
.
toLong
())
return
this
return
this
}
}
...
@@ -221,7 +231,7 @@ fun <N : Number> DataInputStream.readNBytes(length: N): ByteArray {
...
@@ -221,7 +231,7 @@ fun <N : Number> DataInputStream.readNBytes(length: N): ByteArray {
}
}
fun
DataInputStream
.
read
Var
Number
():
Number
{
fun
DataInputStream
.
read
LV
Number
():
Number
{
return
when
(
this
.
readShort
().
toInt
())
{
return
when
(
this
.
readShort
().
toInt
())
{
1
->
this
.
readByte
()
1
->
this
.
readByte
()
2
->
this
.
readShort
()
2
->
this
.
readShort
()
...
@@ -238,23 +248,92 @@ fun DataInputStream.readNBytesIn(range: IntRange): ByteArray {
...
@@ -238,23 +248,92 @@ fun DataInputStream.readNBytesIn(range: IntRange): ByteArray {
fun
<
N
:
Number
>
DataInputStream
.
readIntAt
(
position
:
N
):
Int
{
fun
<
N
:
Number
>
DataInputStream
.
readIntAt
(
position
:
N
):
Int
{
this
.
goto
(
position
)
this
.
goto
(
position
)
return
this
.
readInt
()
;
return
this
.
readInt
()
}
}
@ExperimentalUnsignedTypes
fun
<
N
:
Number
>
DataInputStream
.
readUIntAt
(
position
:
N
):
UInt
{
fun
<
N
:
Number
>
DataInputStream
.
readUIntAt
(
position
:
N
):
UInt
{
this
.
goto
(
position
)
this
.
goto
(
position
)
return
this
.
readNBytes
(
4
).
toUInt
()
;
return
this
.
readNBytes
(
4
).
toUInt
()
}
}
fun
<
N
:
Number
>
DataInputStream
.
readByteAt
(
position
:
N
):
Byte
{
fun
<
N
:
Number
>
DataInputStream
.
readByteAt
(
position
:
N
):
Byte
{
this
.
goto
(
position
)
this
.
goto
(
position
)
return
this
.
readByte
()
;
return
this
.
readByte
()
}
}
fun
<
N
:
Number
>
DataInputStream
.
readShortAt
(
position
:
N
):
Short
{
fun
<
N
:
Number
>
DataInputStream
.
readShortAt
(
position
:
N
):
Short
{
this
.
goto
(
position
)
this
.
goto
(
position
)
return
this
.
readShort
()
;
return
this
.
readShort
()
}
}
@JvmSynthetic
fun
DataInputStream
.
gotoWhere
(
matcher
:
UByteArray
):
DataInputStream
{
return
this
.
gotoWhere
(
matcher
.
toByteArray
())
}
/**
* 去往下一个含这些连续字节的位置
*/
@Throws
(
EOFException
::
class
)
fun
DataInputStream
.
gotoWhere
(
matcher
:
ByteArray
):
DataInputStream
{
require
(
matcher
.
isNotEmpty
())
loop
@
do
{
val
byte
=
this
.
readByte
()
if
(
byte
==
matcher
[
0
])
{
//todo mark here
for
(
i
in
1
until
matcher
.
size
)
{
val
b
=
this
.
readByte
()
if
(
b
!=
matcher
[
i
])
{
continue
@
loop
//todo goto mark
}
return
this
}
}
}
while
(
true
)
}
@Suppress
(
"UNCHECKED_CAST"
)
internal
fun
<
P
:
ServerPacket
>
Bot
.
waitForPacket
(
packetClass
:
KClass
<
P
>,
timeoutMillis
:
Long
=
Long
.
MAX_VALUE
,
timeout
:
()
->
Unit
=
{})
{
var
got
=
false
ServerPacketReceivedEvent
::
class
.
hookWhile
{
if
(
packetClass
.
isInstance
(
it
.
packet
)
&&
it
.
bot
===
this
)
{
got
=
true
true
}
else
{
false
}
}
MiraiThreadPool
.
getInstance
().
submit
{
val
startingTime
=
System
.
currentTimeMillis
()
while
(!
got
)
{
if
(
System
.
currentTimeMillis
()
-
startingTime
>
timeoutMillis
)
{
timeout
.
invoke
()
return
@
submit
}
Thread
.
sleep
(
10
)
}
}
}
/*
@Throws(EOFException::class)
fun DataInputStream.gotoWhere(matcher: ByteArray) {
require(matcher.isNotEmpty())
do {
val byte = this.readByte()
if (byte == matcher[0]) {
for (i in 1 until matcher.size){
}
}
} while (true)
}*/
fun
ByteArray
.
cutTail
(
length
:
Int
):
ByteArray
=
this
.
copyOfRange
(
0
,
this
.
size
-
length
)
fun
ByteArray
.
cutTail
(
length
:
Int
):
ByteArray
=
this
.
copyOfRange
(
0
,
this
.
size
-
length
)
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/network/packet/Session.kt
View file @
86d64f02
package
net.mamoe.mirai.network.packet
package
net.mamoe.mirai.network.packet
import
net.mamoe.mirai.network.Protocol
import
net.mamoe.mirai.network.Protocol
import
net.mamoe.mirai.utils.ByteArrayDataOutputStream
import
net.mamoe.mirai.utils.TEA
import
net.mamoe.mirai.utils.TEA
import
net.mamoe.mirai.utils.getRandomByteArray
import
net.mamoe.mirai.utils.lazyEncode
import
net.mamoe.mirai.utils.lazyEncode
import
java.io.DataInputStream
import
java.io.DataInputStream
import
java.net.InetAddress
import
java.net.InetAddress
...
@@ -11,64 +9,67 @@ import java.net.InetAddress
...
@@ -11,64 +9,67 @@ import java.net.InetAddress
/**
/**
* @author Him188moe
* @author Him188moe
*/
*/
@ExperimentalUnsignedTypes
@PacketId
(
"08 28 04 34"
)
@PacketId
(
"08 28 04 34"
)
class
ClientSessionRequestPacket
(
class
ClientSessionRequestPacket
(
private
val
qq
:
Long
,
private
val
qq
:
Long
,
private
val
serverIp
:
String
,
private
val
serverIp
:
String
,
private
val
token38
:
ByteArray
,
private
val
token38
:
ByteArray
,
private
val
token88
:
ByteArray
,
private
val
token88
:
ByteArray
,
private
val
encryptionKey
:
ByteArray
,
private
val
encryptionKey
:
ByteArray
private
val
tlv0105
:
ByteArray
)
:
ClientPacket
()
{
)
:
ClientPacket
()
{
override
fun
encode
()
{
override
fun
encode
()
{
this
.
writeQQ
(
qq
)
this
.
writeQQ
(
qq
)
this
.
writeHex
(
"02 00 00 00 01 2E 01 00 00 68 52 00 30 00 3A"
)
this
.
writeHex
(
"02 00 00 00 01 2E 01 00 00 68 52 00 30 00 3A"
)
this
.
writeHex
(
"00 38"
)
this
.
writeHex
(
"00 38"
)
this
.
write
(
token38
)
this
.
write
(
token38
)
this
.
write
(
TEA
.
encrypt
(
object
:
ByteArrayDataOutputStream
()
{
this
.
encryptAndWrite
(
encryptionKey
)
{
override
fun
toByteArray
():
ByteArray
{
it
.
writeHex
(
"00 07 00 88"
)
this
.
writeHex
(
"00 07 00 88"
)
it
.
write
(
token88
)
this
.
write
(
token88
)
it
.
writeHex
(
"00 0C 00 16 00 02 00 00 00 00 00 00 00 00 00 00"
)
this
.
writeHex
(
"00 0C 00 16 00 02 00 00 00 00 00 00 00 00 00 00"
)
it
.
writeIP
(
serverIp
)
this
.
writeIP
(
serverIp
)
it
.
writeHex
(
"1F 40 00 00 00 00 00 15 00 30 00 01"
)
//fix1
this
.
writeHex
(
"1F 40 00 00 00 00 00 15 00 30 00 01"
)
//fix1
it
.
writeHex
(
"01 92 A5 D2 59 00 10 54 2D CF 9B 60 BF BB EC 0D D4 81 CE 36 87 DE 35 02 AE 6D ED DC 00 10 "
)
this
.
writeHex
(
"01 92 A5 D2 59 00 10 54 2D CF 9B 60 BF BB EC 0D D4 81 CE 36 87 DE 35 02 AE 6D ED DC 00 10 "
)
it
.
writeHex
(
Protocol
.
fix0836
)
this
.
writeHex
(
Protocol
.
fix0836
)
it
.
writeHex
(
"00 36 00 12 00 02 00 01 00 00 00 05 00 00 00 00 00 00 00 00 00 00"
)
this
.
writeHex
(
"00 36 00 12 00 02 00 01 00 00 00 05 00 00 00 00 00 00 00 00 00 00"
)
it
.
writeHex
(
Protocol
.
constantData1
)
this
.
writeHex
(
Protocol
.
constantData1
)
it
.
writeHex
(
Protocol
.
constantData2
)
this
.
writeHex
(
Protocol
.
constantData2
)
it
.
writeQQ
(
qq
)
this
.
writeQQ
(
qq
)
it
.
writeHex
(
"00 00 00 00 00 1F 00 22 00 01"
)
this
.
writeHex
(
"00 00 00 00 00 1F 00 22 00 01"
)
it
.
writeHex
(
"1A 68 73 66 E4 BA 79 92 CC C2 D4 EC 14 7C 8B AF 43 B0 62 FB 65 58 A9 EB 37 55 1D 26 13 A8 E5 3D"
)
//device ID
this
.
writeHex
(
"1A 68 73 66 E4 BA 79 92 CC C2 D4 EC 14 7C 8B AF 43 B0 62 FB 65 58 A9 EB 37 55 1D 26 13 A8 E5 3D"
)
//device ID
this
.
write
(
tlv0105
)
//tlv0106
this
.
writeHex
(
"01 0B 00 85 00 02"
)
it
.
writeHex
(
"01 05 00 30"
)
this
.
writeHex
(
"B9 ED EF D7 CD E5 47 96 7A B5 28 34 CA 93 6B 5C"
)
//fix2
it
.
writeHex
(
"00 01 01 02 00 14 01 01 00 10"
)
this
.
write
(
getRandomByteArray
(
1
))
it
.
writeRandom
(
16
)
this
.
writeHex
(
"10 00 00 00 00 00 00 00 02"
)
it
.
writeHex
(
"00 14 01 02 00 10"
)
it
.
writeRandom
(
16
)
//fix3
this
.
writeHex
(
"00 63 3E 00 63 02 04 03 06 02 00 04 00 52 D9 00 00 00 00 A9 58 3E 6D 6D 49 AA F6 A6 D9 33 0A E7 7E 36 84 03 01 00 00 68 20 15 8B 00 00 01 02 00 00 03 00 07 DF 00 0A 00 0C 00 01 00 04 00 03 00 04 20 5C 00"
)
it
.
writeHex
(
"01 0B 00 85 00 02"
)
this
.
write
(
getRandomByteArray
(
32
))
//md5 32
it
.
writeHex
(
"B9 ED EF D7 CD E5 47 96 7A B5 28 34 CA 93 6B 5C"
)
//fix2
this
.
writeHex
(
"68"
)
it
.
writeRandom
(
1
)
it
.
writeHex
(
"10 00 00 00 00 00 00 00 02"
)
this
.
writeHex
(
"00 00 00 00 00 2D 00 06 00 01"
)
this
.
writeIP
(
InetAddress
.
getLocalHost
().
hostAddress
)
//fix3
it
.
writeHex
(
"00 63 3E 00 63 02 04 03 06 02 00 04 00 52 D9 00 00 00 00 A9 58 3E 6D 6D 49 AA F6 A6 D9 33 0A E7 7E 36 84 03 01 00 00 68 20 15 8B 00 00 01 02 00 00 03 00 07 DF 00 0A 00 0C 00 01 00 04 00 03 00 04 20 5C 00"
)
return
super
.
toByteArray
()
it
.
writeRandom
(
32
)
//md5 32
}
it
.
writeHex
(
"68"
)
}.
toByteArray
(),
encryptionKey
))
it
.
writeHex
(
"00 00 00 00 00 2D 00 06 00 01"
)
it
.
writeIP
(
InetAddress
.
getLocalHost
().
hostAddress
)
}
}
}
}
}
/**
/**
* @author Him188moe
* @author Him188moe
*/
*/
@PacketId
(
"08 28 04 34"
)
class
ServerSessionKeyResponsePacket
(
inputStream
:
DataInputStream
,
private
val
dataLength
:
Int
)
:
ServerPacket
(
inputStream
)
{
class
ServerSessionKeyResponsePacket
(
inputStream
:
DataInputStream
,
private
val
dataLength
:
Int
)
:
ServerPacket
(
inputStream
)
{
lateinit
var
sessionKey
:
ByteArray
lateinit
var
sessionKey
:
ByteArray
lateinit
var
tlv0105
:
ByteArray
lateinit
var
tlv0105
:
ByteArray
@ExperimentalUnsignedTypes
override
fun
decode
()
{
override
fun
decode
()
{
when
(
dataLength
)
{
when
(
dataLength
)
{
407
->
{
407
->
{
...
...
mirai-core/src/main/java/net/mamoe/mirai/network/packet/Touch.kt
View file @
86d64f02
package
net.mamoe.mirai.network.packet
package
net.mamoe.mirai.network.packet
import
net.mamoe.mirai.network.Protocol
import
net.mamoe.mirai.network.Protocol
import
net.mamoe.mirai.network.packet.login.ClientPasswordSubmissionPacket
import
net.mamoe.mirai.utils.ByteArrayDataOutputStream
import
net.mamoe.mirai.utils.ByteArrayDataOutputStream
import
net.mamoe.mirai.utils.TEA
import
net.mamoe.mirai.utils.TEA
import
net.mamoe.mirai.utils.hexToBytes
import
net.mamoe.mirai.utils.hexToBytes
...
@@ -11,11 +12,12 @@ import java.io.IOException
...
@@ -11,11 +12,12 @@ import java.io.IOException
/**
/**
* A packet received when logging in, used to redirect server address
* A packet received when logging in, used to redirect server address
*
*
* @see
net.mamoe.mirai.network.packet.client.login.
ClientServerRedirectionPacket
* @see ClientServerRedirectionPacket
* @see
net.mamoe.mirai.network.packet.client.login.
ClientPasswordSubmissionPacket
* @see ClientPasswordSubmissionPacket
*
*
* @author Him188moe
* @author Him188moe
*/
*/
@Suppress
(
"EXPERIMENTAL_API_USAGE"
,
"EXPERIMENTAL_UNSIGNED_LITERALS"
)
@PacketId
(
"08 25 31 01"
)
@PacketId
(
"08 25 31 01"
)
class
ServerTouchResponsePacket
(
inputStream
:
DataInputStream
)
:
ServerPacket
(
inputStream
)
{
class
ServerTouchResponsePacket
(
inputStream
:
DataInputStream
)
:
ServerPacket
(
inputStream
)
{
var
serverIP
:
String
?
=
null
var
serverIP
:
String
?
=
null
...
@@ -29,7 +31,7 @@ class ServerTouchResponsePacket(inputStream: DataInputStream) : ServerPacket(inp
...
@@ -29,7 +31,7 @@ class ServerTouchResponsePacket(inputStream: DataInputStream) : ServerPacket(inp
TYPE_08_25_31_02
,
TYPE_08_25_31_02
,
}
}
@ExperimentalUnsignedTypes
override
fun
decode
()
{
override
fun
decode
()
{
when
(
val
id
=
input
.
readByte
().
toUByte
().
toInt
())
{
when
(
val
id
=
input
.
readByte
().
toUByte
().
toInt
())
{
0
xFE
->
{
0
xFE
->
{
...
@@ -52,7 +54,7 @@ class ServerTouchResponsePacket(inputStream: DataInputStream) : ServerPacket(inp
...
@@ -52,7 +54,7 @@ class ServerTouchResponsePacket(inputStream: DataInputStream) : ServerPacket(inp
}
}
class
Encrypted
(
private
val
type
:
Type
,
inputStream
:
DataInputStream
)
:
ServerPacket
(
inputStream
)
{
class
Encrypted
(
private
val
type
:
Type
,
inputStream
:
DataInputStream
)
:
ServerPacket
(
inputStream
)
{
@ExperimentalUnsignedTypes
fun
decrypt
():
ServerTouchResponsePacket
=
ServerTouchResponsePacket
(
decryptBy
(
when
(
type
)
{
fun
decrypt
():
ServerTouchResponsePacket
=
ServerTouchResponsePacket
(
decryptBy
(
when
(
type
)
{
Type
.
TYPE_08_25_31_02
->
Protocol
.
redirectionKey
.
hexToBytes
()
Type
.
TYPE_08_25_31_02
->
Protocol
.
redirectionKey
.
hexToBytes
()
Type
.
TYPE_08_25_31_01
->
Protocol
.
key0825
.
hexToBytes
()
Type
.
TYPE_08_25_31_01
->
Protocol
.
key0825
.
hexToBytes
()
...
@@ -65,10 +67,10 @@ class ServerTouchResponsePacket(inputStream: DataInputStream) : ServerPacket(inp
...
@@ -65,10 +67,10 @@ class ServerTouchResponsePacket(inputStream: DataInputStream) : ServerPacket(inp
*
*
* @author Him188moe
* @author Him188moe
*/
*/
@ExperimentalUnsignedTypes
@PacketId
(
"08 25 31 01"
)
@PacketId
(
"08 25 31 01"
)
class
ClientTouchPacket
(
private
val
qq
:
Long
,
private
val
serverIp
:
String
)
:
ClientPacket
()
{
class
ClientTouchPacket
(
private
val
qq
:
Long
,
private
val
serverIp
:
String
)
:
ClientPacket
()
{
@ExperimentalUnsignedTypes
@Throws
(
IOException
::
class
)
@Throws
(
IOException
::
class
)
override
fun
encode
()
{
override
fun
encode
()
{
this
.
writeQQ
(
qq
)
this
.
writeQQ
(
qq
)
...
@@ -80,7 +82,7 @@ class ClientTouchPacket(private val qq: Long, private val serverIp: String) : Cl
...
@@ -80,7 +82,7 @@ class ClientTouchPacket(private val qq: Long, private val serverIp: String) : Cl
it
.
writeHex
(
Protocol
.
constantData2
)
it
.
writeHex
(
Protocol
.
constantData2
)
it
.
writeQQ
(
qq
)
it
.
writeQQ
(
qq
)
it
.
writeHex
(
"00 00 00 00 03 09 00 08 00 01"
)
it
.
writeHex
(
"00 00 00 00 03 09 00 08 00 01"
)
it
.
writeIP
(
serverIp
)
;
it
.
writeIP
(
serverIp
)
it
.
writeHex
(
"00 02 00 36 00 12 00 02 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 14 00 1D 01 02 00 19"
)
it
.
writeHex
(
"00 02 00 36 00 12 00 02 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 14 00 1D 01 02 00 19"
)
it
.
writeHex
(
Protocol
.
publicKey
)
it
.
writeHex
(
Protocol
.
publicKey
)
}
}
...
@@ -92,10 +94,10 @@ class ClientTouchPacket(private val qq: Long, private val serverIp: String) : Cl
...
@@ -92,10 +94,10 @@ class ClientTouchPacket(private val qq: Long, private val serverIp: String) : Cl
*
*
* @author Him188moe
* @author Him188moe
*/
*/
@ExperimentalUnsignedTypes
@PacketId
(
"08 25 31 02"
)
@PacketId
(
"08 25 31 02"
)
class
ClientServerRedirectionPacket
(
private
val
serverIP
:
String
,
private
val
qq
:
Long
)
:
ClientPacket
()
{
class
ClientServerRedirectionPacket
(
private
val
serverIP
:
String
,
private
val
qq
:
Long
)
:
ClientPacket
()
{
@ExperimentalUnsignedTypes
override
fun
encode
()
{
override
fun
encode
()
{
this
.
writeQQ
(
qq
)
this
.
writeQQ
(
qq
)
this
.
writeHex
(
Protocol
.
fixVer
)
this
.
writeHex
(
Protocol
.
fixVer
)
...
...
mirai-core/src/main/java/net/mamoe/mirai/network/packet/VerificationCode.kt
View file @
86d64f02
package
net.mamoe.mirai.network.packet
package
net.mamoe.mirai.network.packet
import
net.mamoe.mirai.network.Protocol
import
net.mamoe.mirai.network.Protocol
import
net.mamoe.mirai.utils.*
import
net.mamoe.mirai.utils.TEA
import
net.mamoe.mirai.utils.Tested
import
net.mamoe.mirai.utils.hexToBytes
import
java.io.DataInputStream
import
java.io.DataInputStream
/**
/**
* 客户端请求验证码图片数据的第几部分
* 客户端请求验证码图片数据的第几部分
*/
*/
@ExperimentalUnsignedTypes
@PacketId
(
"00 BA 31"
)
@PacketId
(
"00 BA 31"
)
class
ClientVerificationCodeTransmissionRequestPacket
(
class
ClientVerificationCodeTransmissionRequestPacket
(
private
val
packetId
:
Int
,
private
val
packetId
:
Int
,
...
@@ -16,11 +18,8 @@ class ClientVerificationCodeTransmissionRequestPacket(
...
@@ -16,11 +18,8 @@ class ClientVerificationCodeTransmissionRequestPacket(
private
val
verificationSequence
:
Int
,
private
val
verificationSequence
:
Int
,
private
val
token00BA
:
ByteArray
private
val
token00BA
:
ByteArray
)
:
ClientPacket
()
{
)
:
ClientPacket
()
{
@Tested
Successfully
@Tested
override
fun
encode
()
{
override
fun
encode
()
{
MiraiLogger
debug
"packetId=$packetId"
MiraiLogger
debug
"verificationSequence=$verificationSequence"
this
.
writeByte
(
packetId
)
//part of packet id
this
.
writeByte
(
packetId
)
//part of packet id
this
.
writeQQ
(
qq
)
this
.
writeQQ
(
qq
)
...
@@ -47,7 +46,7 @@ class ClientVerificationCodeTransmissionRequestPacket(
...
@@ -47,7 +46,7 @@ class ClientVerificationCodeTransmissionRequestPacket(
* 提交验证码
* 提交验证码
*/
*/
@PacketId
(
"00 BA 32"
)
@PacketId
(
"00 BA 32"
)
@ExperimentalUnsignedTypes
class
ClientVerificationCodeSubmitPacket
(
class
ClientVerificationCodeSubmitPacket
(
private
val
packetIdLast
:
Int
,
private
val
packetIdLast
:
Int
,
private
val
qq
:
Long
,
private
val
qq
:
Long
,
...
@@ -90,39 +89,11 @@ class ClientVerificationCodeSubmitPacket(
...
@@ -90,39 +89,11 @@ class ClientVerificationCodeSubmitPacket(
}
}
}
}
@ExperimentalUnsignedTypes
fun
main
()
{
val
token0825
=
"6E AF F9 2C 20 2B DE 21 B6 13 6F 26 43 F4 04 7B 1F 88 08 4E 8E BE E5 D1 3F E7 93 DE DD E0 6E 38 65 C7 C7 D3 20 7D AC 73 AD F9 85 F9 CC 2A 2C 26 C6 B1 5B FD 34 3F D4 F2"
.
hexToBytes
()
val
verificationCode
=
"AAAA"
val
verificationToken
=
"84 2D 1D 9D 07 04 34 80 17 9E 3F 58 02 20 9A 1C 22 D0 73 7D 8A 90 1B 2F F8 E6 79 A6 84 2F 98 F5 1E 66 3D 9A 24 59 18 34 42 BD 45 DA E1 22 2D BC 2D 36 80 86 AD 44 C2 94"
.
hexToBytes
()
//00 02 00 00 08 04 01 E0 00 00 04 53 00 00 00 01 00 00 15 85 01 00 38 6E AF F9 2C 20 2B DE 21 B6 13 6F 26 43 F4 04 7B 1F 88 08 4E 8E BE E5 D1 3F E7 93 DE DD E0 6E 38 65 C7 C7 D3 20 7D AC 73 AD F9 85 F9 CC 2A 2C 26 C6 B1 5B FD 34 3F D4 F2 01 03 00 19 02 6D 28 41 D2 A5 6F D2 FC 3E 2A 1F 03 75 DE 6E 28 8F A8 19 3E 5F 16 49 D3 14 00 05 00 00 00 00 00 04 58 51 4E 44 00 38 84 2D 1D 9D 07 04 34 80 17 9E 3F 58 02 20 9A 1C 22 D0 73 7D 8A 90 1B 2F F8 E6 79 A6 84 2F 98 F5 1E 66 3D 9A 24 59 18 34 42 BD 45 DA E1 22 2D BC 2D 36 80 86 AD 44 C2 94 00 10 69 20 D1 14 74 F5 B3 93 E4 D5 02 B3 71 1A CD 2A
ByteArrayDataOutputStream
().
let
{
it
.
writeHex
(
"00 02 00 00 08 04 01 E0"
)
it
.
writeHex
(
Protocol
.
constantData2
)
it
.
writeHex
(
"01 00 38"
)
it
.
write
(
token0825
)
it
.
writeHex
(
"01 03"
)
it
.
writeShort
(
25
)
it
.
writeHex
(
Protocol
.
publicKey
)
it
.
writeHex
(
"14 00 05 00 00 00 00 00 04"
)
it
.
write
(
verificationCode
.
substring
(
0
..
3
).
toByteArray
())
it
.
writeHex
(
"00 38"
)
it
.
write
(
verificationToken
)
it
.
writeHex
(
"00 10"
)
it
.
writeHex
(
Protocol
.
key00BAFix
)
println
(
it
.
toByteArray
().
toUHexString
())
}
}
/**
/**
* 刷新验证码
* 刷新验证码
*/
*/
@PacketId
(
"00 BA 31"
)
@PacketId
(
"00 BA 31"
)
@ExperimentalUnsignedTypes
class
ClientVerificationCodeRefreshPacket
(
class
ClientVerificationCodeRefreshPacket
(
private
val
packetIdLast
:
Int
,
private
val
packetIdLast
:
Int
,
private
val
qq
:
Long
,
private
val
qq
:
Long
,
...
@@ -152,7 +123,7 @@ class ClientVerificationCodeRefreshPacket(
...
@@ -152,7 +123,7 @@ class ClientVerificationCodeRefreshPacket(
}
}
/**
/**
* 验证码输入错误
* 验证码输入错误
, 同时也会给一部分验证码
*/
*/
@PacketId
(
"00 BA 32"
)
@PacketId
(
"00 BA 32"
)
class
ServerVerificationCodeWrongPacket
(
input
:
DataInputStream
,
dataSize
:
Int
,
packetId
:
ByteArray
)
:
ServerVerificationCodeTransmissionPacket
(
input
,
dataSize
,
packetId
)
class
ServerVerificationCodeWrongPacket
(
input
:
DataInputStream
,
dataSize
:
Int
,
packetId
:
ByteArray
)
:
ServerVerificationCodeTransmissionPacket
(
input
,
dataSize
,
packetId
)
...
@@ -171,7 +142,7 @@ open class ServerVerificationCodeTransmissionPacket(input: DataInputStream, priv
...
@@ -171,7 +142,7 @@ open class ServerVerificationCodeTransmissionPacket(input: DataInputStream, priv
lateinit
var
token00BA
:
ByteArray
//40 bytes
lateinit
var
token00BA
:
ByteArray
//40 bytes
var
packetIdLast
:
Int
=
0
var
packetIdLast
:
Int
=
0
@ExperimentalUnsignedTypes
override
fun
decode
()
{
override
fun
decode
()
{
this
.
verificationToken
=
this
.
input
.
readNBytesAt
(
10
,
56
)
this
.
verificationToken
=
this
.
input
.
readNBytesAt
(
10
,
56
)
...
@@ -210,7 +181,7 @@ class ServerVerificationCodeCorrectPacket(input: DataInputStream) : ServerVerifi
...
@@ -210,7 +181,7 @@ class ServerVerificationCodeCorrectPacket(input: DataInputStream) : ServerVerifi
lateinit
var
token00BA
:
ByteArray
//56 bytes
lateinit
var
token00BA
:
ByteArray
//56 bytes
@ExperimentalUnsignedTypes
override
fun
decode
()
{
override
fun
decode
()
{
token00BA
=
this
.
input
.
readNBytesAt
(
10
,
56
)
token00BA
=
this
.
input
.
readNBytesAt
(
10
,
56
)
}
}
...
@@ -220,7 +191,7 @@ abstract class ServerVerificationCodePacket(input: DataInputStream) : ServerPack
...
@@ -220,7 +191,7 @@ abstract class ServerVerificationCodePacket(input: DataInputStream) : ServerPack
@PacketId
(
"00 BA"
)
@PacketId
(
"00 BA"
)
class
Encrypted
(
input
:
DataInputStream
,
private
val
id
:
String
)
:
ServerPacket
(
input
)
{
class
Encrypted
(
input
:
DataInputStream
,
private
val
id
:
String
)
:
ServerPacket
(
input
)
{
@ExperimentalUnsignedTypes
fun
decrypt
():
ServerVerificationCodePacket
{
fun
decrypt
():
ServerVerificationCodePacket
{
this
.
input
goto
14
this
.
input
goto
14
val
data
=
TEA
.
decrypt
(
this
.
input
.
readAllBytes
().
cutTail
(
1
),
Protocol
.
key00BA
.
hexToBytes
())
val
data
=
TEA
.
decrypt
(
this
.
input
.
readAllBytes
().
cutTail
(
1
),
Protocol
.
key00BA
.
hexToBytes
())
...
...
mirai-core/src/main/java/net/mamoe/mirai/network/packet/action/AddContact.kt
View file @
86d64f02
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
,
"EXPERIMENTAL_UNSIGNED_LITERALS"
)
package
net.mamoe.mirai.network.packet.action
package
net.mamoe.mirai.network.packet.action
import
net.mamoe.mirai.network.Protocol
import
net.mamoe.mirai.network.Protocol
...
@@ -13,7 +15,7 @@ import java.util.*
...
@@ -13,7 +15,7 @@ import java.util.*
* @author Him188moe
* @author Him188moe
*/
*/
@PacketId
(
"00 A7"
)
@PacketId
(
"00 A7"
)
@ExperimentalUnsignedTypes
class
ClientCanAddFriendPacket
(
class
ClientCanAddFriendPacket
(
val
bot
:
Long
,
val
bot
:
Long
,
val
qq
:
Long
,
val
qq
:
Long
,
...
@@ -47,7 +49,7 @@ class ServerCanAddFriendResponsePacket(input: DataInputStream) : ServerPacket(in
...
@@ -47,7 +49,7 @@ class ServerCanAddFriendResponsePacket(input: DataInputStream) : ServerPacket(in
FAILED
,
FAILED
,
}
}
@ExperimentalUnsignedTypes
override
fun
decode
()
{
override
fun
decode
()
{
val
data
=
input
.
goto
(
0
).
readAllBytes
()
val
data
=
input
.
goto
(
0
).
readAllBytes
()
if
(
data
.
size
==
99
)
{
if
(
data
.
size
==
99
)
{
...
@@ -78,7 +80,7 @@ class ServerCanAddFriendResponsePacket(input: DataInputStream) : ServerPacket(in
...
@@ -78,7 +80,7 @@ class ServerCanAddFriendResponsePacket(input: DataInputStream) : ServerPacket(in
* 请求添加好友
* 请求添加好友
*/
*/
@PacketId
(
"00 AE"
)
@PacketId
(
"00 AE"
)
@ExperimentalUnsignedTypes
class
ClientAddFriendPacket
(
class
ClientAddFriendPacket
(
val
bot
:
Long
,
val
bot
:
Long
,
val
qq
:
Long
,
val
qq
:
Long
,
...
@@ -111,7 +113,7 @@ class ServerAddGroupResponsePacket(input: DataInputStream) : ServerAddContactRes
...
@@ -111,7 +113,7 @@ class ServerAddGroupResponsePacket(input: DataInputStream) : ServerAddContactRes
/**
/**
* 添加好友/群的回复
* 添加好友/群的回复
*/
*/
open
class
ServerAddContactResponsePacket
(
input
:
DataInputStream
)
:
ServerPacket
(
input
)
{
abstract
class
ServerAddContactResponsePacket
(
input
:
DataInputStream
)
:
ServerPacket
(
input
)
{
class
Raw
(
input
:
DataInputStream
)
:
ServerPacket
(
input
)
{
class
Raw
(
input
:
DataInputStream
)
:
ServerPacket
(
input
)
{
...
...
mirai-core/src/main/java/net/mamoe/mirai/network/packet/action/ClientSendFriendMessagePacket.kt
View file @
86d64f02
...
@@ -10,7 +10,7 @@ import java.io.DataInputStream
...
@@ -10,7 +10,7 @@ import java.io.DataInputStream
* @author Him188moe
* @author Him188moe
*/
*/
@PacketId
(
"00 CD"
)
@PacketId
(
"00 CD"
)
@ExperimentalUnsignedTypes
class
ClientSendFriendMessagePacket
(
class
ClientSendFriendMessagePacket
(
private
val
botQQ
:
Long
,
private
val
botQQ
:
Long
,
private
val
targetQQ
:
Long
,
private
val
targetQQ
:
Long
,
...
@@ -19,6 +19,7 @@ class ClientSendFriendMessagePacket(
...
@@ -19,6 +19,7 @@ class ClientSendFriendMessagePacket(
)
:
ClientPacket
()
{
)
:
ClientPacket
()
{
override
fun
encode
()
{
override
fun
encode
()
{
this
.
writeRandom
(
2
)
//part of packet id
this
.
writeRandom
(
2
)
//part of packet id
this
.
writeQQ
(
botQQ
)
this
.
writeQQ
(
botQQ
)
this
.
writeHex
(
Protocol
.
fixVer2
)
this
.
writeHex
(
Protocol
.
fixVer2
)
...
@@ -40,7 +41,6 @@ class ClientSendFriendMessagePacket(
...
@@ -40,7 +41,6 @@ class ClientSendFriendMessagePacket(
it
.
writeHex
(
Protocol
.
friendMessageConst1
)
//... 85 E9 BB 91
it
.
writeHex
(
Protocol
.
friendMessageConst1
)
//... 85 E9 BB 91
it
.
writeZero
(
2
)
it
.
writeZero
(
2
)
it
.
write
(
message
.
toByteArray
())
it
.
write
(
message
.
toByteArray
())
/*
/*
...
...
mirai-core/src/main/java/net/mamoe/mirai/network/packet/action/ClientSendGroupMessagePacket.kt
View file @
86d64f02
package
net.mamoe.mirai.network.packet.action
package
net.mamoe.mirai.network.packet.action
import
net.mamoe.mirai.message.defaults.MessageChain
import
net.mamoe.mirai.network.Protocol
import
net.mamoe.mirai.network.Protocol
import
net.mamoe.mirai.network.packet.*
import
net.mamoe.mirai.network.packet.*
import
net.mamoe.mirai.utils.toUHexString
import
net.mamoe.mirai.utils.toUHexString
...
@@ -9,12 +10,11 @@ import java.io.DataInputStream
...
@@ -9,12 +10,11 @@ import java.io.DataInputStream
* @author Him188moe
* @author Him188moe
*/
*/
@PacketId
(
"00 02"
)
@PacketId
(
"00 02"
)
@ExperimentalUnsignedTypes
class
ClientSendGroupMessagePacket
(
class
ClientSendGroupMessagePacket
(
private
val
groupId
:
Long
,
//不是 number
private
val
groupId
:
Long
,
//不是 number
private
val
botQQ
:
Long
,
private
val
botQQ
:
Long
,
private
val
sessionKey
:
ByteArray
,
private
val
sessionKey
:
ByteArray
,
private
val
message
:
String
private
val
message
:
MessageChain
)
:
ClientPacket
()
{
)
:
ClientPacket
()
{
override
fun
encode
()
{
override
fun
encode
()
{
this
.
writeRandom
(
2
)
//part of packet id
this
.
writeRandom
(
2
)
//part of packet id
...
@@ -25,20 +25,24 @@ class ClientSendGroupMessagePacket(
...
@@ -25,20 +25,24 @@ class ClientSendGroupMessagePacket(
val
bytes
=
message
.
toByteArray
()
val
bytes
=
message
.
toByteArray
()
it
.
writeByte
(
0
x2A
)
it
.
writeByte
(
0
x2A
)
it
.
writeGroup
(
groupId
)
it
.
writeGroup
(
groupId
)
it
.
writeShort
(
56
+
bytes
.
size
)
it
.
writeHex
(
"00 01 01 00 00 00 00 00 00 00 4D 53 47 00 00 00 00 00"
)
it
.
writeShort
(
50
+
bytes
.
size
)
it
.
writeHex
(
"00 01 01"
)
it
.
writeHex
(
"00 00 00 00 00 00 00 4D 53 47 00 00 00 00 00"
)
it
.
writeTime
()
it
.
writeTime
()
it
.
writeRandom
(
4
)
it
.
writeRandom
(
4
)
it
.
writeHex
(
"Protocol.messageConst1"
)
it
.
writeHex
(
"00 00 00 00 09 00 86"
)
it
.
writeHex
(
Protocol
.
friendMessageConst1
)
it
.
writeZero
(
2
)
it
.
writeZero
(
2
)
//messages
//messages
it
.
writeByte
(
0
x01
)
it
.
write
(
bytes
)
/*it.writeByte(0x01)
it.writeShort(bytes.size + 3)
it.writeShort(bytes.size + 3)
it.writeByte(0x01)
it.writeByte(0x01)
it.writeShort(bytes.size)
it.writeShort(bytes.size)
it
.
write
(
bytes
)
it.write(bytes)
*/
println
(
it
.
toByteArray
().
toUHexString
())
println
(
it
.
toByteArray
().
toUHexString
())
}
}
...
...
mirai-core/src/main/java/net/mamoe/mirai/network/packet/image/ClientGetGroupImageIDPacket.kt
deleted
100644 → 0
View file @
5c00a59a
package
net.mamoe.mirai.network.packet.image
import
net.mamoe.mirai.network.packet.*
import
net.mamoe.mirai.utils.writeProtoInt
import
java.awt.image.BufferedImage
/**
* 查询群消息的 image id.
* That is, 查询服务器上是否有这个图片, 有就返回 id, 没有就需要上传
*
* @author Him188moe
*/
@PacketId
(
"03 88"
)
@ExperimentalUnsignedTypes
class
ClientGetGroupImageIDPacket
(
val
bot
:
Long
,
val
sessionKey
:
ByteArray
,
val
group
:
Long
,
val
image
:
BufferedImage
)
:
ClientPacket
()
{
override
fun
encode
()
{
this
.
writeRandom
(
2
)
this
.
writeQQ
(
bot
)
this
.
writeHex
(
"04 00 00 00 01 01 01 00 00 68 20 00 00 00 00 00 00 00 00"
)
this
.
encryptAndWrite
(
sessionKey
)
{
it
.
writeHex
(
"00 00 00 07 00 00 00 5E 08 01 12 03 98 01 01 10 01 1A"
)
it
.
writeHex
(
"5A"
)
it
.
writeHex
(
"08"
)
it
.
writeProtoInt
(
group
)
it
.
writeHex
(
"08"
)
it
.
writeProtoInt
(
image
.
height
)
}
}
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/network/packet/image/UploadGroupImage.kt
0 → 100644
View file @
86d64f02
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
,
"EXPERIMENTAL_UNSIGNED_LITERALS"
)
package
net.mamoe.mirai.network.packet.image
import
net.mamoe.mirai.network.packet.*
import
net.mamoe.mirai.utils.toByteArray
import
net.mamoe.mirai.utils.writeUVarInt
import
java.awt.image.BufferedImage
import
java.io.DataInputStream
/**
* 请求上传图片. 将发送图片的 md5, size.
* 服务器返回以下之一:
* - 服务器已经存有这个图片 [ServerTryUploadGroupImageFailedPacket]
* - 服务器未存有, 返回一个 key 用于客户端上传 [ServerTryUploadGroupImageSuccessPacket]
*
* @author Him188moe
*/
@PacketId
(
"03 88"
)
class
ClientTryGetImageIDPacket
(
private
val
botNumber
:
Long
,
private
val
sessionKey
:
ByteArray
,
private
val
groupNumberOrQQNumber
:
Long
,
//todo 为什么还要有qq number呢? bot不就是了么
private
val
image
:
BufferedImage
)
:
ClientPacket
()
{
override
fun
encode
()
{
this
.
writeRandom
(
2
)
this
.
writeQQ
(
botNumber
)
this
.
writeHex
(
"04 00 00 00 01 01 01 00 00 68 20 00 00 00 00 00 00 00 00"
)
val
byteArray
=
image
.
toByteArray
()
this
.
encryptAndWrite
(
sessionKey
)
{
it
.
writeZero
(
3
)
it
.
writeHex
(
"07 00"
)
it
.
writeZero
(
2
)
it
.
writeHex
(
"5E"
)
it
.
writeHex
(
"08"
)
it
.
writeHex
(
"01 12 03 98 01 01 10 01"
)
it
.
writeHex
(
"1A"
)
it
.
writeHex
(
"5A"
)
it
.
writeHex
(
"08"
)
it
.
writeUVarInt
(
groupNumberOrQQNumber
)
it
.
writeHex
(
"10"
)
it
.
writeUVarInt
(
botNumber
)
it
.
writeHex
(
"18 00"
)
it
.
writeHex
(
"22"
)
it
.
writeHex
(
"10"
)
it
.
write
(
md5
(
byteArray
))
it
.
writeHex
(
"28"
)
it
.
writeUVarInt
(
byteArray
.
size
.
toUInt
())
it
.
writeHex
(
"32"
)
it
.
writeHex
(
"1A"
)
it
.
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"
)
it
.
writeHex
(
"38 01"
)
it
.
writeHex
(
"48 01"
)
it
.
writeHex
(
"50"
)
it
.
writeUVarInt
(
image
.
width
.
toUInt
())
it
.
writeHex
(
"58"
)
it
.
writeUVarInt
(
image
.
height
.
toUInt
())
it
.
writeHex
(
"60 04"
)
it
.
writeHex
(
"6A"
)
it
.
writeHex
(
"05"
)
it
.
writeHex
(
"32 36 36 35 36"
)
it
.
writeHex
(
"70 00"
)
it
.
writeHex
(
"78 03"
)
it
.
writeHex
(
"80 01"
)
it
.
writeHex
(
"00"
)
}
}
}
abstract
class
ServerTryUploadGroupImageResponsePacket
(
input
:
DataInputStream
)
:
ServerPacket
(
input
)
{
class
Encrypted
(
input
:
DataInputStream
)
:
ServerPacket
(
input
)
{
fun
decrypt
(
sessionKey
:
ByteArray
):
ServerTryUploadGroupImageResponsePacket
{
val
data
=
this
.
decryptAsByteArray
(
sessionKey
)
println
(
data
.
size
)
println
(
data
.
size
)
if
(
data
.
size
==
209
)
{
return
ServerTryUploadGroupImageSuccessPacket
(
data
.
dataInputStream
()).
setId
(
this
.
idHex
)
}
return
ServerTryUploadGroupImageFailedPacket
(
data
.
dataInputStream
())
}
}
}
/**
* 服务器未存有图片, 返回一个 key 用于客户端上传
*/
class
ServerTryUploadGroupImageSuccessPacket
(
input
:
DataInputStream
)
:
ServerTryUploadGroupImageResponsePacket
(
input
)
{
lateinit
var
uKey
:
ByteArray
override
fun
decode
()
{
uKey
=
this
.
input
.
gotoWhere
(
ubyteArrayOf
(
0
x42u
,
0
x80u
,
0
x01u
)).
readNBytes
(
128
)
}
}
/**
* 服务器已经存有这个图片
*/
class
ServerTryUploadGroupImageFailedPacket
(
input
:
DataInputStream
)
:
ServerTryUploadGroupImageResponsePacket
(
input
)
{
override
fun
decode
()
{
}
}
fun
main
()
{
println
(
0
xff
)
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ClientChangeOnlineStatusPacket.kt
View file @
86d64f02
...
@@ -9,7 +9,7 @@ import net.mamoe.mirai.utils.ClientLoginStatus
...
@@ -9,7 +9,7 @@ import net.mamoe.mirai.utils.ClientLoginStatus
*
*
* @author Him188moe
* @author Him188moe
*/
*/
@ExperimentalUnsignedTypes
@PacketId
(
"00 EC"
)
@PacketId
(
"00 EC"
)
class
ClientChangeOnlineStatusPacket
(
class
ClientChangeOnlineStatusPacket
(
private
val
qq
:
Long
,
private
val
qq
:
Long
,
...
@@ -29,4 +29,6 @@ class ClientChangeOnlineStatusPacket(
...
@@ -29,4 +29,6 @@ class ClientChangeOnlineStatusPacket(
it
.
writeHex
(
"00 01 00 01 00 04 00 00 00 00"
)
it
.
writeHex
(
"00 01 00 01 00 04 00 00 00 00"
)
}
}
}
}
}
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ClientLogin.kt
View file @
86d64f02
...
@@ -4,7 +4,7 @@ import net.mamoe.mirai.network.Protocol
...
@@ -4,7 +4,7 @@ import net.mamoe.mirai.network.Protocol
import
net.mamoe.mirai.network.packet.*
import
net.mamoe.mirai.network.packet.*
import
net.mamoe.mirai.utils.ByteArrayDataOutputStream
import
net.mamoe.mirai.utils.ByteArrayDataOutputStream
import
net.mamoe.mirai.utils.TEA
import
net.mamoe.mirai.utils.TEA
import
net.mamoe.mirai.utils.Tested
Successfully
import
net.mamoe.mirai.utils.Tested
import
net.mamoe.mirai.utils.hexToBytes
import
net.mamoe.mirai.utils.hexToBytes
import
java.io.DataOutputStream
import
java.io.DataOutputStream
...
@@ -14,8 +14,8 @@ import java.io.DataOutputStream
...
@@ -14,8 +14,8 @@ import java.io.DataOutputStream
* @author Him188moe
* @author Him188moe
*/
*/
@PacketId
(
"08 36 31 03"
)
@PacketId
(
"08 36 31 03"
)
@ExperimentalUnsignedTypes
@Tested
Successfully
@Tested
class
ClientPasswordSubmissionPacket
(
class
ClientPasswordSubmissionPacket
(
private
val
qq
:
Long
,
private
val
qq
:
Long
,
private
val
password
:
String
,
private
val
password
:
String
,
...
@@ -24,7 +24,7 @@ class ClientPasswordSubmissionPacket(
...
@@ -24,7 +24,7 @@ class ClientPasswordSubmissionPacket(
private
val
tgtgtKey
:
ByteArray
,
private
val
tgtgtKey
:
ByteArray
,
private
val
token0825
:
ByteArray
private
val
token0825
:
ByteArray
)
:
ClientPacket
()
{
)
:
ClientPacket
()
{
@ExperimentalUnsignedTypes
override
fun
encode
()
{
override
fun
encode
()
{
this
.
writeQQ
(
qq
)
this
.
writeQQ
(
qq
)
this
.
writeHex
(
Protocol
.
passwordSubmissionKey1
)
this
.
writeHex
(
Protocol
.
passwordSubmissionKey1
)
...
@@ -40,21 +40,21 @@ class ClientPasswordSubmissionPacket(
...
@@ -40,21 +40,21 @@ class ClientPasswordSubmissionPacket(
}
}
@PacketId
(
"08 36 31 04"
)
@PacketId
(
"08 36 31 04"
)
@ExperimentalUnsignedTypes
class
ClientLoginResendPacket3104
(
qq
:
Long
,
password
:
String
,
loginTime
:
Int
,
loginIP
:
String
,
tgtgtKey
:
ByteArray
,
token0825
:
ByteArray
,
token00BA
:
ByteArray
,
tlv0006
:
ByteArray
?
=
null
)
class
ClientLoginResendPacket3104
(
qq
:
Long
,
password
:
String
,
loginTime
:
Int
,
loginIP
:
String
,
tgtgtKey
:
ByteArray
,
token0825
:
ByteArray
,
token00BA
:
ByteArray
,
tlv0006
:
ByteArray
?
=
null
)
:
ClientLoginResendPacket
(
qq
,
password
,
loginTime
,
loginIP
,
tgtgtKey
,
token0825
,
token00BA
,
tlv0006
)
:
ClientLoginResendPacket
(
qq
,
password
,
loginTime
,
loginIP
,
tgtgtKey
,
token0825
,
token00BA
,
tlv0006
)
@PacketId
(
"08 36 31 05"
)
@PacketId
(
"08 36 31 05"
)
@ExperimentalUnsignedTypes
class
ClientLoginResendPacket3105
(
qq
:
Long
,
password
:
String
,
loginTime
:
Int
,
loginIP
:
String
,
tgtgtKey
:
ByteArray
,
token0825
:
ByteArray
,
token00BA
:
ByteArray
)
class
ClientLoginResendPacket3105
(
qq
:
Long
,
password
:
String
,
loginTime
:
Int
,
loginIP
:
String
,
tgtgtKey
:
ByteArray
,
token0825
:
ByteArray
,
token00BA
:
ByteArray
)
:
ClientLoginResendPacket
(
qq
,
password
,
loginTime
,
loginIP
,
tgtgtKey
,
token0825
,
token00BA
,
null
)
:
ClientLoginResendPacket
(
qq
,
password
,
loginTime
,
loginIP
,
tgtgtKey
,
token0825
,
token00BA
,
null
)
@PacketId
(
"08 36 31 06"
)
@PacketId
(
"08 36 31 06"
)
@ExperimentalUnsignedTypes
class
ClientLoginResendPacket3106
(
qq
:
Long
,
password
:
String
,
loginTime
:
Int
,
loginIP
:
String
,
tgtgtKey
:
ByteArray
,
token0825
:
ByteArray
,
token00BA
:
ByteArray
,
tlv0006
:
ByteArray
?
=
null
)
class
ClientLoginResendPacket3106
(
qq
:
Long
,
password
:
String
,
loginTime
:
Int
,
loginIP
:
String
,
tgtgtKey
:
ByteArray
,
token0825
:
ByteArray
,
token00BA
:
ByteArray
,
tlv0006
:
ByteArray
?
=
null
)
:
ClientLoginResendPacket
(
qq
,
password
,
loginTime
,
loginIP
,
tgtgtKey
,
token0825
,
token00BA
,
tlv0006
)
:
ClientLoginResendPacket
(
qq
,
password
,
loginTime
,
loginIP
,
tgtgtKey
,
token0825
,
token00BA
,
tlv0006
)
@ExperimentalUnsignedTypes
open
class
ClientLoginResendPacket
internal
constructor
(
open
class
ClientLoginResendPacket
internal
constructor
(
val
qq
:
Long
,
val
qq
:
Long
,
val
password
:
String
,
val
password
:
String
,
...
@@ -93,7 +93,7 @@ open class ClientLoginResendPacket internal constructor(
...
@@ -93,7 +93,7 @@ open class ClientLoginResendPacket internal constructor(
/**
/**
* @author Him188moe
* @author Him188moe
*/
*/
@ExperimentalUnsignedTypes
private
fun
DataOutputStream
.
writePart1
(
qq
:
Long
,
password
:
String
,
loginTime
:
Int
,
loginIP
:
String
,
tgtgtKey
:
ByteArray
,
token0825
:
ByteArray
,
tlv0006
:
ByteArray
?
=
null
)
{
private
fun
DataOutputStream
.
writePart1
(
qq
:
Long
,
password
:
String
,
loginTime
:
Int
,
loginIP
:
String
,
tgtgtKey
:
ByteArray
,
token0825
:
ByteArray
,
tlv0006
:
ByteArray
?
=
null
)
{
//this.writeInt(System.currentTimeMillis().toInt())
//this.writeInt(System.currentTimeMillis().toInt())
...
@@ -130,7 +130,7 @@ private fun DataOutputStream.writePart1(qq: Long, password: String, loginTime: I
...
@@ -130,7 +130,7 @@ private fun DataOutputStream.writePart1(qq: Long, password: String, loginTime: I
this
.
writeHex
(
"60 C9 5D A7 45 70 04 7F 21 7D 84 50 5C 66 A5 C6"
)
//key
this
.
writeHex
(
"60 C9 5D A7 45 70 04 7F 21 7D 84 50 5C 66 A5 C6"
)
//key
}
}
@ExperimentalUnsignedTypes
private
fun
DataOutputStream
.
writePart2
()
{
private
fun
DataOutputStream
.
writePart2
()
{
this
.
writeHex
(
"03 12"
)
//tag
this
.
writeHex
(
"03 12"
)
//tag
...
...
mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/LoginState.kt
View file @
86d64f02
...
@@ -34,11 +34,6 @@ enum class LoginState {
...
@@ -34,11 +34,6 @@ enum class LoginState {
*/
*/
TAKEN_BACK
,
TAKEN_BACK
,
/**
* 需要验证码登录
*/
VERIFICATION_CODE
,
/**
/**
* 未知. 更换服务器或等几分钟再登录可能解决.
* 未知. 更换服务器或等几分钟再登录可能解决.
*/
*/
...
...
mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponseKeyExchangePacket.kt
View file @
86d64f02
...
@@ -4,7 +4,7 @@ import net.mamoe.mirai.network.Protocol
...
@@ -4,7 +4,7 @@ import net.mamoe.mirai.network.Protocol
import
net.mamoe.mirai.network.packet.PacketId
import
net.mamoe.mirai.network.packet.PacketId
import
net.mamoe.mirai.network.packet.ServerPacket
import
net.mamoe.mirai.network.packet.ServerPacket
import
net.mamoe.mirai.network.packet.goto
import
net.mamoe.mirai.network.packet.goto
import
net.mamoe.mirai.utils.Tested
Successfully
import
net.mamoe.mirai.utils.Tested
import
java.io.DataInputStream
import
java.io.DataInputStream
/**
/**
...
@@ -23,7 +23,7 @@ class ServerLoginResponseKeyExchangePacket(input: DataInputStream, val flag: Fla
...
@@ -23,7 +23,7 @@ class ServerLoginResponseKeyExchangePacket(input: DataInputStream, val flag: Fla
var
tokenUnknown
:
ByteArray
?
=
null
var
tokenUnknown
:
ByteArray
?
=
null
lateinit
var
tgtgtKey
:
ByteArray
//16bytes
lateinit
var
tgtgtKey
:
ByteArray
//16bytes
@Tested
Successfully
@Tested
override
fun
decode
()
{
override
fun
decode
()
{
this
.
input
.
skip
(
5
)
this
.
input
.
skip
(
5
)
tgtgtKey
=
this
.
input
.
readNBytes
(
16
)
//22
tgtgtKey
=
this
.
input
.
readNBytes
(
16
)
//22
...
@@ -46,8 +46,8 @@ class ServerLoginResponseKeyExchangePacket(input: DataInputStream, val flag: Fla
...
@@ -46,8 +46,8 @@ class ServerLoginResponseKeyExchangePacket(input: DataInputStream, val flag: Fla
}
}
class
Encrypted
(
input
:
DataInputStream
,
private
val
flag
:
Flag
)
:
ServerPacket
(
input
)
{
class
Encrypted
(
input
:
DataInputStream
,
private
val
flag
:
Flag
)
:
ServerPacket
(
input
)
{
@ExperimentalUnsignedTypes
@Tested
Successfully
@Tested
fun
decrypt
(
tgtgtKey
:
ByteArray
):
ServerLoginResponseKeyExchangePacket
{
fun
decrypt
(
tgtgtKey
:
ByteArray
):
ServerLoginResponseKeyExchangePacket
{
return
ServerLoginResponseKeyExchangePacket
(
this
.
decryptBy
(
Protocol
.
shareKey
,
tgtgtKey
),
flag
).
setId
(
this
.
idHex
)
return
ServerLoginResponseKeyExchangePacket
(
this
.
decryptBy
(
Protocol
.
shareKey
,
tgtgtKey
),
flag
).
setId
(
this
.
idHex
)
}
}
...
...
mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponsePasswordVerifiedPacket.kt
View file @
86d64f02
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
)
package
net.mamoe.mirai.network.packet.login
package
net.mamoe.mirai.network.packet.login
import
net.mamoe.mirai.network.Protocol
import
net.mamoe.mirai.network.Protocol
...
@@ -5,7 +7,7 @@ import net.mamoe.mirai.network.packet.ServerPacket
...
@@ -5,7 +7,7 @@ import net.mamoe.mirai.network.packet.ServerPacket
import
net.mamoe.mirai.network.packet.goto
import
net.mamoe.mirai.network.packet.goto
import
net.mamoe.mirai.network.packet.readNBytesAt
import
net.mamoe.mirai.network.packet.readNBytesAt
import
net.mamoe.mirai.network.packet.readString
import
net.mamoe.mirai.network.packet.readString
import
net.mamoe.mirai.utils.Tested
Successfully
import
net.mamoe.mirai.utils.Tested
import
net.mamoe.mirai.utils.toUHexString
import
net.mamoe.mirai.utils.toUHexString
import
java.io.DataInputStream
import
java.io.DataInputStream
...
@@ -21,8 +23,8 @@ class ServerLoginResponseSuccessPacket(input: DataInputStream) : ServerPacket(in
...
@@ -21,8 +23,8 @@ class ServerLoginResponseSuccessPacket(input: DataInputStream) : ServerPacket(in
lateinit
var
encryptionKey
:
ByteArray
lateinit
var
encryptionKey
:
ByteArray
@Tested
Successfully
@Tested
@ExperimentalUnsignedTypes
override
fun
decode
()
{
override
fun
decode
()
{
this
.
input
.
skip
(
7
)
//8
this
.
input
.
skip
(
7
)
//8
this
.
encryptionKey
=
this
.
input
.
readNBytes
(
16
)
//24
this
.
encryptionKey
=
this
.
input
.
readNBytes
(
16
)
//24
...
@@ -52,7 +54,7 @@ class ServerLoginResponseSuccessPacket(input: DataInputStream) : ServerPacket(in
...
@@ -52,7 +54,7 @@ class ServerLoginResponseSuccessPacket(input: DataInputStream) : ServerPacket(in
class
Encrypted
(
input
:
DataInputStream
)
:
ServerPacket
(
input
)
{
class
Encrypted
(
input
:
DataInputStream
)
:
ServerPacket
(
input
)
{
@ExperimentalUnsignedTypes
fun
decrypt
(
tgtgtKey
:
ByteArray
):
ServerLoginResponseSuccessPacket
{
fun
decrypt
(
tgtgtKey
:
ByteArray
):
ServerLoginResponseSuccessPacket
{
input
goto
14
input
goto
14
return
ServerLoginResponseSuccessPacket
(
this
.
decryptBy
(
Protocol
.
shareKey
,
tgtgtKey
)).
setId
(
this
.
idHex
)
return
ServerLoginResponseSuccessPacket
(
this
.
decryptBy
(
Protocol
.
shareKey
,
tgtgtKey
)).
setId
(
this
.
idHex
)
...
...
mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponseVerificationCodeInitPacket.kt
View file @
86d64f02
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
)
package
net.mamoe.mirai.network.packet.login
package
net.mamoe.mirai.network.packet.login
import
net.mamoe.mirai.network.Protocol
import
net.mamoe.mirai.network.Protocol
import
net.mamoe.mirai.network.packet.ServerPacket
import
net.mamoe.mirai.network.packet.ServerPacket
import
net.mamoe.mirai.network.packet.dataInputStream
import
net.mamoe.mirai.network.packet.dataInputStream
import
net.mamoe.mirai.network.packet.goto
import
net.mamoe.mirai.network.packet.goto
import
net.mamoe.mirai.utils.Tested
Successfully
import
net.mamoe.mirai.utils.Tested
import
net.mamoe.mirai.utils.hexToUBytes
import
net.mamoe.mirai.utils.hexToUBytes
import
java.io.DataInputStream
import
java.io.DataInputStream
...
@@ -20,8 +22,8 @@ class ServerLoginResponseVerificationCodeInitPacket(input: DataInputStream, priv
...
@@ -20,8 +22,8 @@ class ServerLoginResponseVerificationCodeInitPacket(input: DataInputStream, priv
var
unknownBoolean
:
Boolean
?
=
null
var
unknownBoolean
:
Boolean
?
=
null
@Tested
Successfully
@Tested
@ExperimentalUnsignedTypes
override
fun
decode
()
{
override
fun
decode
()
{
val
verifyCodeLength
=
this
.
input
.
goto
(
78
).
readShort
()
//2bytes
val
verifyCodeLength
=
this
.
input
.
goto
(
78
).
readShort
()
//2bytes
this
.
verifyCodePart1
=
this
.
input
.
readNBytes
(
verifyCodeLength
.
toInt
())
this
.
verifyCodePart1
=
this
.
input
.
readNBytes
(
verifyCodeLength
.
toInt
())
...
@@ -39,7 +41,7 @@ class ServerLoginResponseVerificationCodeInitPacket(input: DataInputStream, priv
...
@@ -39,7 +41,7 @@ class ServerLoginResponseVerificationCodeInitPacket(input: DataInputStream, priv
}
}
@ExperimentalUnsignedTypes
fun
decrypt
():
ServerLoginResponseVerificationCodeInitPacket
{
fun
decrypt
():
ServerLoginResponseVerificationCodeInitPacket
{
this
.
input
goto
14
this
.
input
goto
14
val
data
=
this
.
decryptBy
(
Protocol
.
shareKey
).
goto
(
0
).
readAllBytes
()
val
data
=
this
.
decryptBy
(
Protocol
.
shareKey
).
goto
(
0
).
readAllBytes
()
...
...
mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginSuccessPacket.kt
View file @
86d64f02
package
net.mamoe.mirai.network.packet.login
package
net.mamoe.mirai.network.packet.login
import
net.mamoe.mirai.network.packet.PacketId
import
net.mamoe.mirai.network.packet.ServerPacket
import
net.mamoe.mirai.network.packet.ServerPacket
import
java.io.DataInputStream
import
java.io.DataInputStream
...
@@ -8,4 +9,5 @@ import java.io.DataInputStream
...
@@ -8,4 +9,5 @@ import java.io.DataInputStream
*
*
* @author Him188moe
* @author Him188moe
*/
*/
@PacketId
(
"00 EC"
)
class
ServerLoginSuccessPacket
(
input
:
DataInputStream
)
:
ServerPacket
(
input
)
class
ServerLoginSuccessPacket
(
input
:
DataInputStream
)
:
ServerPacket
(
input
)
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/utils/ContactList.java
View file @
86d64f02
package
net.mamoe.mirai.utils
;
package
net.mamoe.mirai.utils
;
import
net.mamoe.mirai.contact.Contact
;
import
net.mamoe.mirai.contact.Contact
;
import
net.mamoe.mirai.utils.config.MiraiSynchronizedLinkedListMap
;
/**
/**
* @author Him188moe
* @author Him188moe
*/
*/
public
class
ContactList
<
C
extends
Contact
>
extends
MiraiSynchronizedLinked
List
Map
<
Long
,
C
>
{
public
class
ContactList
<
C
extends
Contact
>
extends
MiraiSynchronizedLinked
Hash
Map
<
Long
,
C
>
{
}
}
mirai-core/src/main/java/net/mamoe/mirai/utils/ImageNetworkUtils.java
View file @
86d64f02
package
net.mamoe.mirai.utils
;
package
net.mamoe.mirai.utils
;
import
org.apache.commons.httpclient.util.HttpURLConnection
;
import
org.jsoup.Connection
;
import
org.jsoup.Jsoup
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.
io.InputStream
;
import
java.
net.HttpURLConnection
;
import
java.net.URL
;
import
java.net.URL
;
/**
* @author NaturalHG
*/
public
class
ImageNetworkUtils
{
public
class
ImageNetworkUtils
{
public
static
void
postImage
(
String
ukey
,
int
fileSize
,
String
g_uin
,
String
groupCode
,
byte
[]
img
)
{
public
static
boolean
postImage
(
String
uKeyHex
,
int
fileSize
,
long
qqNumber
,
long
groupCode
,
byte
[]
img
)
throws
IOException
{
//http://htdata2.qq.com/cgi-bin/httpconn?htcmd=0x6ff0071&ver=5515&term=pc&ukey=” + 删全部空 (ukey) + “&filesize=” + 到文本 (fileSize) + “&range=0&uin=” + g_uin + “&groupcode=” + Group
//http://htdata2.qq.com/cgi-bin/httpconn?htcmd=0x6ff0071&ver=5515&term=pc&ukey=” + 删全部空 (ukey) + “&filesize=” + 到文本 (fileSize) + “&range=0&uin=” + g_uin + “&groupcode=” + Group
StringBuilder
builder
=
new
StringBuilder
(
"http://htdata2.qq.com/cgi-bin/httpconn?htcmd=0x6ff0071&ver=5515&term=pc"
);
builder
.
append
(
"&ukey="
)
.
append
(
ukey
.
trim
())
.
append
(
"&filezise="
).
append
(
fileSize
)
.
append
(
"&range="
).
append
(
"0"
)
.
append
(
"&uin="
).
append
(
g_uin
)
.
append
(
"&groupcode="
).
append
(
groupCode
);
try
{
String
builder
=
"http://htdata2.qq.com/cgi-bin/httpconn?htcmd=0x6ff0071&ver=5515&term=pc"
+
"&ukey="
+
HttpURLConnection
conn
=
(
HttpURLConnection
)
new
URL
(
builder
.
toString
()).
openConnection
();
uKeyHex
.
replace
(
" "
,
""
)
+
conn
.
setRequestProperty
(
"User-agent"
,
"QQClient"
);
"&filezise="
+
fileSize
+
conn
.
setRequestProperty
(
"Content-length"
,
""
+
fileSize
);
"&range="
+
"0"
+
conn
.
setRequestMethod
(
"POST"
);
"&uin="
+
qqNumber
+
conn
.
getOutputStream
().
write
(
img
);
"&groupcode="
+
groupCode
;
HttpURLConnection
conn
=
(
HttpURLConnection
)
new
URL
(
builder
).
openConnection
();
conn
.
setRequestProperty
(
"User-agent"
,
"QQClient"
);
conn
.
setRequestProperty
(
"Content-length"
,
""
+
fileSize
);
conn
.
setRequestMethod
(
"POST"
);
conn
.
setDoOutput
(
true
);
conn
.
getOutputStream
().
write
(
img
);
conn
.
connect
();
conn
.
connect
();
System
.
out
.
println
(
conn
.
getResponseCode
());
return
conn
.
getResponseCode
()
==
200
;
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
}
}
}
mirai-core/src/main/java/net/mamoe/mirai/utils/MiraiLogger.kt
View file @
86d64f02
package
net.mamoe.mirai.utils
package
net.mamoe.mirai.utils
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.network.packet.ServerPacket
import
net.mamoe.mirai.network.packet.goto
import
java.text.SimpleDateFormat
import
java.text.SimpleDateFormat
import
java.util.*
import
java.util.*
...
@@ -11,20 +13,20 @@ import java.util.*
...
@@ -11,20 +13,20 @@ import java.util.*
* @author NaturalHG
* @author NaturalHG
*/
*/
object
MiraiLogger
{
object
MiraiLogger
{
infix
fun
log
(
o
:
Any
?)
=
info
(
o
)
fun
log
(
o
:
Any
?)
=
info
(
o
)
infix
fun
println
(
o
:
Any
?)
=
info
(
o
)
fun
println
(
o
:
Any
?)
=
info
(
o
)
infix
fun
info
(
o
:
Any
?)
=
this
.
print
(
o
.
toString
(),
LoggerTextFormat
.
RESET
)
fun
info
(
o
:
Any
?)
=
this
.
print
(
o
.
toString
(),
LoggerTextFormat
.
RESET
)
infix
fun
error
(
o
:
Any
?)
=
this
.
print
(
o
.
toString
(),
LoggerTextFormat
.
RED
)
fun
error
(
o
:
Any
?)
=
this
.
print
(
o
.
toString
(),
LoggerTextFormat
.
RED
)
infix
fun
notice
(
o
:
Any
?)
=
this
.
print
(
o
.
toString
(),
LoggerTextFormat
.
LIGHT_BLUE
)
fun
notice
(
o
:
Any
?)
=
this
.
print
(
o
.
toString
(),
LoggerTextFormat
.
LIGHT_BLUE
)
infix
fun
success
(
o
:
Any
?)
=
this
.
print
(
o
.
toString
(),
LoggerTextFormat
.
GREEN
)
fun
success
(
o
:
Any
?)
=
this
.
print
(
o
.
toString
(),
LoggerTextFormat
.
GREEN
)
infix
fun
debug
(
o
:
Any
?)
=
this
.
print
(
o
.
toString
(),
LoggerTextFormat
.
YELLOW
)
fun
debug
(
o
:
Any
?)
=
this
.
print
(
o
.
toString
(),
LoggerTextFormat
.
YELLOW
)
infix
fun
catching
(
e
:
Throwable
)
{
fun
catching
(
e
:
Throwable
)
{
e
.
printStackTrace
()
e
.
printStackTrace
()
/*
/*
this.print(e.message)
this.print(e.message)
...
@@ -39,21 +41,26 @@ object MiraiLogger {
...
@@ -39,21 +41,26 @@ object MiraiLogger {
}
}
}
}
infix
fun
Bot
.
log
(
o
:
Any
?)
=
info
(
o
)
fun
Bot
.
log
(
o
:
Any
?)
=
info
(
o
)
infix
fun
Bot
.
println
(
o
:
Any
?)
=
info
(
o
)
fun
Bot
.
println
(
o
:
Any
?)
=
info
(
o
)
infix
fun
Bot
.
info
(
o
:
Any
?)
=
print
(
this
,
o
.
toString
(),
LoggerTextFormat
.
RESET
)
fun
Bot
.
info
(
o
:
Any
?)
=
print
(
this
,
o
.
toString
(),
LoggerTextFormat
.
RESET
)
infix
fun
Bot
.
error
(
o
:
Any
?)
=
print
(
this
,
o
.
toString
(),
LoggerTextFormat
.
RED
)
fun
Bot
.
error
(
o
:
Any
?)
=
print
(
this
,
o
.
toString
(),
LoggerTextFormat
.
RED
)
infix
fun
Bot
.
notice
(
o
:
Any
?)
=
print
(
this
,
o
.
toString
(),
LoggerTextFormat
.
LIGHT_BLUE
)
fun
Bot
.
notice
(
o
:
Any
?)
=
print
(
this
,
o
.
toString
(),
LoggerTextFormat
.
LIGHT_BLUE
)
infix
fun
Bot
.
purple
(
o
:
Any
?)
=
print
(
this
,
o
.
toString
(),
LoggerTextFormat
.
PURPLE
)
fun
Bot
.
purple
(
o
:
Any
?)
=
print
(
this
,
o
.
toString
(),
LoggerTextFormat
.
PURPLE
)
infix
fun
Bot
.
cyanL
(
o
:
Any
?)
=
print
(
this
,
o
.
toString
(),
LoggerTextFormat
.
LIGHT_CYAN
)
fun
Bot
.
cyanL
(
o
:
Any
?)
=
print
(
this
,
o
.
toString
(),
LoggerTextFormat
.
LIGHT_CYAN
)
fun
Bot
.
success
(
o
:
Any
?)
=
print
(
this
,
o
.
toString
(),
LoggerTextFormat
.
GREEN
)
infix
fun
Bot
.
success
(
o
:
Any
?)
=
print
(
this
,
o
.
toString
(),
LoggerTextFormat
.
GREEN
)
fun
Bot
.
debug
(
o
:
Any
?)
=
print
(
this
,
o
.
toString
(),
LoggerTextFormat
.
YELLOW
)
infix
fun
Bot
.
debug
(
o
:
Any
?)
=
print
(
this
,
o
.
toString
(),
LoggerTextFormat
.
YELLOW
)
fun
Bot
.
debugPacket
(
packet
:
ServerPacket
)
{
debug
(
"Packet=$packet"
)
debug
(
"Packet size="
+
packet
.
input
.
goto
(
0
).
readAllBytes
().
size
)
debug
(
"Packet data="
+
packet
.
input
.
goto
(
0
).
readAllBytes
().
toUHexString
())
}
@Synchronized
@Synchronized
...
...
mirai-core/src/main/java/net/mamoe/mirai/utils/
config/MiraiSynchronizedLinkedList
Map.java
→
mirai-core/src/main/java/net/mamoe/mirai/utils/
MiraiSynchronizedLinkedHash
Map.java
View file @
86d64f02
package
net.mamoe.mirai.utils
.config
;
package
net.mamoe.mirai.utils
;
import
org.jetbrains.annotations.NotNull
;
import
org.jetbrains.annotations.NotNull
;
import
org.jetbrains.annotations.Nullable
;
import
org.jetbrains.annotations.Nullable
;
...
@@ -16,15 +16,15 @@ import java.util.function.Function;
...
@@ -16,15 +16,15 @@ import java.util.function.Function;
*
*
* @author NaturalHG
* @author NaturalHG
*/
*/
public
class
MiraiSynchronizedLinked
ListMap
<
K
,
V
>
extends
AbstractMap
<
K
,
V
>
{
public
class
MiraiSynchronizedLinked
HashMap
<
K
,
V
>
extends
AbstractMap
<
K
,
V
>
{
public
MiraiSynchronizedLinked
ListMap
()
{
public
MiraiSynchronizedLinked
HashMap
()
{
this
.
sortedMap
=
Collections
.
synchronizedMap
(
new
LinkedHashMap
<>());
this
.
sortedMap
=
Collections
.
synchronizedMap
(
new
LinkedHashMap
<>());
}
}
protected
final
Map
<
K
,
V
>
sortedMap
;
protected
final
Map
<
K
,
V
>
sortedMap
;
public
MiraiSynchronizedLinked
ListMap
(
LinkedHashMap
<
K
,
V
>
map
)
{
public
MiraiSynchronizedLinked
HashMap
(
LinkedHashMap
<
K
,
V
>
map
)
{
this
.
sortedMap
=
Collections
.
synchronizedMap
(
map
);
this
.
sortedMap
=
Collections
.
synchronizedMap
(
map
);
}
}
...
@@ -155,13 +155,13 @@ public class MiraiSynchronizedLinkedListMap<K,V> extends AbstractMap<K,V> {
...
@@ -155,13 +155,13 @@ public class MiraiSynchronizedLinkedListMap<K,V> extends AbstractMap<K,V> {
return
this
.
sortedMap
.
merge
(
key
,
value
,
remappingFunction
);
return
this
.
sortedMap
.
merge
(
key
,
value
,
remappingFunction
);
}
}
public
boolean
equals
(
MiraiSynchronizedLinked
List
Map
o
)
{
public
boolean
equals
(
MiraiSynchronizedLinked
Hash
Map
o
)
{
return
this
.
sortedMap
.
equals
(
o
.
sortedMap
);
return
this
.
sortedMap
.
equals
(
o
.
sortedMap
);
}
}
@Override
@Override
public
boolean
equals
(
Object
o
)
{
public
boolean
equals
(
Object
o
)
{
return
o
instanceof
MiraiSynchronizedLinked
ListMap
?
this
.
equals
((
MiraiSynchronizedLinkedListMap
)
o
):
super
.
equals
(
o
);
return
o
instanceof
MiraiSynchronizedLinked
HashMap
?
this
.
equals
((
MiraiSynchronizedLinkedHashMap
)
o
)
:
super
.
equals
(
o
);
}
}
}
}
mirai-core/src/main/java/net/mamoe/mirai/utils/MiraiSynchronizedLinkedList.java
0 → 100644
View file @
86d64f02
package
net.mamoe.mirai.utils
;
import
org.jetbrains.annotations.NotNull
;
import
java.util.*
;
import
java.util.function.Consumer
;
import
java.util.function.IntFunction
;
import
java.util.function.Predicate
;
import
java.util.function.UnaryOperator
;
import
java.util.stream.Stream
;
/**
* @author Him188moe
*/
public
class
MiraiSynchronizedLinkedList
<
E
>
extends
AbstractList
<
E
>
{
@SuppressWarnings
(
"WeakerAccess"
)
protected
final
List
<
E
>
syncList
;
public
MiraiSynchronizedLinkedList
()
{
this
.
syncList
=
Collections
.
synchronizedList
(
new
LinkedList
<>());
}
public
MiraiSynchronizedLinkedList
(
Collection
<
E
>
collection
)
{
this
.
syncList
=
Collections
.
synchronizedList
(
new
LinkedList
<>(
collection
));
}
@Override
public
E
get
(
int
index
)
{
return
this
.
syncList
.
get
(
index
);
}
@Override
public
void
forEach
(
Consumer
<?
super
E
>
action
)
{
this
.
syncList
.
forEach
(
action
);
}
@Override
public
Spliterator
<
E
>
spliterator
()
{
return
this
.
syncList
.
spliterator
();
}
@Override
public
Stream
<
E
>
stream
()
{
return
this
.
syncList
.
stream
();
}
@Override
public
Stream
<
E
>
parallelStream
()
{
return
this
.
syncList
.
parallelStream
();
}
@Override
public
int
size
()
{
return
this
.
syncList
.
size
();
}
@SuppressWarnings
(
"SuspiciousToArrayCall"
)
@Override
public
<
T
>
T
[]
toArray
(
IntFunction
<
T
[]>
generator
)
{
return
this
.
syncList
.
toArray
(
generator
);
}
@Override
public
boolean
removeIf
(
Predicate
<?
super
E
>
filter
)
{
return
this
.
syncList
.
removeIf
(
filter
);
}
@Override
public
void
replaceAll
(
UnaryOperator
<
E
>
operator
)
{
this
.
syncList
.
replaceAll
(
operator
);
}
@Override
public
void
sort
(
Comparator
<?
super
E
>
c
)
{
this
.
syncList
.
sort
(
c
);
}
@Override
public
boolean
add
(
E
e
)
{
return
this
.
syncList
.
add
(
e
);
}
@Override
public
E
set
(
int
index
,
E
element
)
{
return
this
.
syncList
.
set
(
index
,
element
);
}
@Override
public
void
add
(
int
index
,
E
element
)
{
this
.
syncList
.
add
(
index
,
element
);
}
@Override
public
E
remove
(
int
index
)
{
return
this
.
syncList
.
remove
(
index
);
}
@Override
public
int
indexOf
(
Object
o
)
{
return
this
.
syncList
.
indexOf
(
o
);
}
@Override
public
int
lastIndexOf
(
Object
o
)
{
return
this
.
syncList
.
lastIndexOf
(
o
);
}
@Override
public
void
clear
()
{
this
.
syncList
.
clear
();
}
@Override
public
boolean
addAll
(
int
index
,
Collection
<?
extends
E
>
c
)
{
return
this
.
syncList
.
addAll
(
index
,
c
);
}
@NotNull
@Override
public
Iterator
<
E
>
iterator
()
{
return
this
.
syncList
.
iterator
();
}
@NotNull
@Override
public
ListIterator
<
E
>
listIterator
()
{
return
this
.
syncList
.
listIterator
();
}
@NotNull
@Override
public
ListIterator
<
E
>
listIterator
(
int
index
)
{
return
this
.
syncList
.
listIterator
(
index
);
}
@NotNull
@Override
public
List
<
E
>
subList
(
int
fromIndex
,
int
toIndex
)
{
return
this
.
syncList
.
subList
(
fromIndex
,
toIndex
);
}
@Override
public
int
hashCode
()
{
return
this
.
syncList
.
hashCode
();
}
@Override
public
boolean
isEmpty
()
{
return
this
.
syncList
.
isEmpty
();
}
@Override
public
boolean
contains
(
Object
o
)
{
return
this
.
syncList
.
contains
(
o
);
}
@NotNull
@Override
public
Object
[]
toArray
()
{
return
this
.
syncList
.
toArray
();
}
@SuppressWarnings
(
"SuspiciousToArrayCall"
)
@NotNull
@Override
public
<
T
>
T
[]
toArray
(
@NotNull
T
[]
a
)
{
return
this
.
syncList
.
toArray
(
a
);
}
@Override
public
boolean
remove
(
Object
o
)
{
return
this
.
syncList
.
remove
(
o
);
}
@Override
public
boolean
containsAll
(
@NotNull
Collection
<?>
c
)
{
return
this
.
syncList
.
containsAll
(
c
);
}
@Override
public
boolean
addAll
(
@NotNull
Collection
<?
extends
E
>
c
)
{
return
this
.
syncList
.
addAll
(
c
);
}
@Override
public
boolean
removeAll
(
@NotNull
Collection
<?>
c
)
{
return
this
.
syncList
.
removeAll
(
c
);
}
@Override
public
boolean
retainAll
(
@NotNull
Collection
<?>
c
)
{
return
this
.
syncList
.
retainAll
(
c
);
}
}
mirai-core/src/main/java/net/mamoe/mirai/utils/ProtocolBuff.kt
deleted
100644 → 0
View file @
5c00a59a
package
net.mamoe.mirai.utils
import
java.io.DataOutputStream
/**
* Google ProtocolBuff 的一些算法实现
*
* @author Him188moe
*/
/**
* 128(10000000) -> 0x7F (10000000_10000001)
*
* TODO improve
*/
@ExperimentalUnsignedTypes
fun
DataOutputStream
.
writeProtoFixedInt
(
int
:
Long
)
{
if
(
int
==
0
xFFL
)
{
this
.
writeShort
(
0
x80_01
)
//unsigned//1000000010000001
return
}
this
.
writeByte
((
int
.
rem
(
0
xFF
)
+
0
xFF
).
toInt
())
this
.
writeByte
((
int
/
0
xFF
).
toInt
())
}
/**
* 127(1111111(7)) -> 0x7F (11111111(8))
*
* TODO improve
*/
@ExperimentalUnsignedTypes
fun
DataOutputStream
.
writeProtoInt
(
int
:
Long
)
{
if
(
int
<
0
xFF
)
{
this
.
writeByte
((
int
and
0
xFF
).
toInt
())
//10000000
return
}
this
.
writeProtoFixedInt
(
int
)
}
@ExperimentalUnsignedTypes
fun
main
()
{
println
()
println
(
lazyEncode
{
it
.
writeProtoInt
(
128
)
}.
toUHexString
())
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/utils/TEA.kt
View file @
86d64f02
package
net.mamoe.mirai.utils
package
net.mamoe.mirai.utils
import
net.mamoe.mirai.network.Protocol
import
java.nio.ByteBuffer
import
java.nio.ByteBuffer
import
java.util.*
import
java.util.*
import
kotlin.experimental.and
import
kotlin.experimental.and
import
kotlin.experimental.xor
import
kotlin.experimental.xor
/**
* @author Him188moe
*/
/**
/**
* TEA 加密
* TEA 加密
*
*
* @author iweiz https://github.com/iweizime/StepChanger/blob/master/app/src/main/java/me/iweizi/stepchanger/qq/Cryptor.java
* @author iweiz https://github.com/iweizime/StepChanger/blob/master/app/src/main/java/me/iweizi/stepchanger/qq/Cryptor.java
*/
*/
class
TEA
(
private
val
key
:
ByteArray
)
{
object
TEA
{
private
const
val
UINT32_MASK
=
0
xffffffffL
private
fun
doOption
(
data
:
ByteArray
,
key
:
ByteArray
,
encrypt
:
Boolean
):
ByteArray
{
val
mRandom
=
Random
()
lateinit
var
mOutput
:
ByteArray
lateinit
var
mInBlock
:
ByteArray
var
mIndexPos
:
Int
lateinit
var
mIV
:
ByteArray
var
mOutPos
=
0
var
mPreOutPos
=
0
var
isFirstBlock
=
true
companion
object
{
val
mKey
=
LongArray
(
4
)
val
CRYPTOR_SHARE_KEY
=
TEA
(
Protocol
.
hexToBytes
(
Protocol
.
shareKey
))
val
CRYPTOR_0825KEY
=
TEA
(
Protocol
.
hexToBytes
(
Protocol
.
key0825
))
private
val
UINT32_MASK
=
0
xffffffffL
for
(
i
in
0
..
3
)
{
mKey
[
i
]
=
pack
(
key
,
i
*
4
,
4
)
fun
doOption
(
data
:
ByteArray
,
key
:
ByteArray
,
encrypt
:
Boolean
):
ByteArray
{
}
val
mRandom
=
Random
()
lateinit
var
mOutput
:
ByteArray
lateinit
var
mInBlock
:
ByteArray
var
mIndexPos
:
Int
lateinit
var
mIV
:
ByteArray
var
mOutPos
=
0
var
mPreOutPos
=
0
var
isFirstBlock
:
Boolean
=
true
val
mKey
=
LongArray
(
4
)
fun
rand
():
Int
{
return
mRandom
.
nextInt
()
}
for
(
i
in
0
..
3
)
{
fun
encode
(
bytes
:
ByteArray
):
ByteArray
{
mKey
[
i
]
=
pack
(
key
,
i
*
4
,
4
)
var
v0
=
pack
(
bytes
,
0
,
4
)
var
v1
=
pack
(
bytes
,
4
,
4
)
var
sum
:
Long
=
0
val
delta
=
0
x9e3779b9L
for
(
i
in
0
..
15
)
{
sum
=
sum
+
delta
and
UINT32_MASK
v0
+=
(
v1
shl
4
)
+
mKey
[
0
]
xor
v1
+
sum
xor
v1
.
ushr
(
5
)
+
mKey
[
1
]
v0
=
v0
and
UINT32_MASK
v1
+=
(
v0
shl
4
)
+
mKey
[
2
]
xor
v0
+
sum
xor
v0
.
ushr
(
5
)
+
mKey
[
3
]
v1
=
v1
and
UINT32_MASK
}
}
return
ByteBuffer
.
allocate
(
8
).
putInt
(
v0
.
toInt
()).
putInt
(
v1
.
toInt
()).
array
()
}
fun
rand
():
Int
{
fun
decode
(
bytes
:
ByteArray
,
offset
:
Int
):
ByteArray
{
return
mRandom
.
nextInt
()
var
v0
=
pack
(
bytes
,
offset
,
4
)
var
v1
=
pack
(
bytes
,
offset
+
4
,
4
)
val
delta
=
0
x9e3779b9L
var
sum
=
delta
shl
4
and
UINT32_MASK
for
(
i
in
0
..
15
)
{
v1
-=
(
v0
shl
4
)
+
mKey
[
2
]
xor
v0
+
sum
xor
v0
.
ushr
(
5
)
+
mKey
[
3
]
v1
=
v1
and
UINT32_MASK
v0
-=
(
v1
shl
4
)
+
mKey
[
0
]
xor
v1
+
sum
xor
v1
.
ushr
(
5
)
+
mKey
[
1
]
v0
=
v0
and
UINT32_MASK
sum
=
sum
-
delta
and
UINT32_MASK
}
}
return
ByteBuffer
.
allocate
(
8
).
putInt
(
v0
.
toInt
()).
putInt
(
v1
.
toInt
()).
array
()
}
fun
encode
(
bytes
:
ByteArray
):
ByteArray
{
fun
encodeOneBlock
()
{
var
v0
=
pack
(
bytes
,
0
,
4
)
mIndexPos
=
0
var
v1
=
pack
(
bytes
,
4
,
4
)
while
(
mIndexPos
<
8
)
{
var
sum
:
Long
=
0
mInBlock
[
mIndexPos
]
=
if
(
isFirstBlock
)
val
delta
=
0
x9e3779b9L
mInBlock
[
mIndexPos
]
for
(
i
in
0
..
15
)
{
else
sum
=
sum
+
delta
and
UINT32_MASK
(
mInBlock
[
mIndexPos
]
xor
mOutput
[
mPreOutPos
+
mIndexPos
])
v0
+=
(
v1
shl
4
)
+
mKey
[
0
]
xor
v1
+
sum
xor
v1
.
ushr
(
5
)
+
mKey
[
1
]
mIndexPos
++
v0
=
v0
and
UINT32_MASK
v1
+=
(
v0
shl
4
)
+
mKey
[
2
]
xor
v0
+
sum
xor
v0
.
ushr
(
5
)
+
mKey
[
3
]
v1
=
v1
and
UINT32_MASK
}
return
ByteBuffer
.
allocate
(
8
).
putInt
(
v0
.
toInt
()).
putInt
(
v1
.
toInt
()).
array
()
}
}
fun
decode
(
bytes
:
ByteArray
,
offset
:
Int
):
ByteArray
{
System
.
arraycopy
(
encode
(
mInBlock
),
0
,
mOutput
,
mOutPos
,
8
)
var
v0
=
pack
(
bytes
,
offset
,
4
)
mIndexPos
=
0
var
v1
=
pack
(
bytes
,
offset
+
4
,
4
)
while
(
mIndexPos
<
8
)
{
val
delta
=
0
x9e3779b9L
val
outPos
=
mOutPos
+
mIndexPos
var
sum
=
delta
shl
4
and
UINT32_MASK
mOutput
[
outPos
]
=
(
mOutput
[
outPos
]
xor
mIV
[
mIndexPos
])
for
(
i
in
0
..
15
)
{
mIndexPos
++
v1
-=
(
v0
shl
4
)
+
mKey
[
2
]
xor
v0
+
sum
xor
v0
.
ushr
(
5
)
+
mKey
[
3
]
v1
=
v1
and
UINT32_MASK
v0
-=
(
v1
shl
4
)
+
mKey
[
0
]
xor
v1
+
sum
xor
v1
.
ushr
(
5
)
+
mKey
[
1
]
v0
=
v0
and
UINT32_MASK
sum
=
sum
-
delta
and
UINT32_MASK
}
return
ByteBuffer
.
allocate
(
8
).
putInt
(
v0
.
toInt
()).
putInt
(
v1
.
toInt
()).
array
()
}
}
System
.
arraycopy
(
mInBlock
,
0
,
mIV
,
0
,
8
)
mPreOutPos
=
mOutPos
mOutPos
+=
8
mIndexPos
=
0
isFirstBlock
=
false
}
fun
encodeOneBlock
()
{
fun
decodeOneBlock
(
ciphertext
:
ByteArray
,
offset
:
Int
,
len
:
Int
):
Boolean
{
mIndexPos
=
0
mIndexPos
=
0
while
(
mIndexPos
<
8
)
{
while
(
mIndexPos
<
8
)
{
mInBlock
[
mIndexPos
]
=
if
(
isFirstBlock
)
if
(
mOutPos
+
mIndexPos
<
len
)
{
mInBlock
[
mIndexPos
]
mIV
[
mIndexPos
]
=
(
mIV
[
mIndexPos
]
xor
ciphertext
[
mOutPos
+
offset
+
mIndexPos
])
else
(
mInBlock
[
mIndexPos
]
xor
mOutput
[
mPreOutPos
+
mIndexPos
])
mIndexPos
++
}
System
.
arraycopy
(
encode
(
mInBlock
),
0
,
mOutput
,
mOutPos
,
8
)
mIndexPos
=
0
while
(
mIndexPos
<
8
)
{
val
out_pos
=
mOutPos
+
mIndexPos
mOutput
[
out_pos
]
=
(
mOutput
[
out_pos
]
xor
mIV
[
mIndexPos
])
mIndexPos
++
mIndexPos
++
continue
}
}
System
.
arraycopy
(
mInBlock
,
0
,
mIV
,
0
,
8
)
return
true
mPreOutPos
=
mOutPos
mOutPos
+=
8
mIndexPos
=
0
isFirstBlock
=
false
}
}
fun
decodeOneBlock
(
ciphertext
:
ByteArray
,
offset
:
Int
,
len
:
Int
):
Boolean
{
mIV
=
decode
(
mIV
,
0
)
mIndexPos
=
0
mOutPos
+=
8
while
(
mIndexPos
<
8
)
{
mIndexPos
=
0
if
(
mOutPos
+
mIndexPos
<
len
)
{
return
true
mIV
[
mIndexPos
]
=
(
mIV
[
mIndexPos
]
xor
ciphertext
[
mOutPos
+
offset
+
mIndexPos
])
mIndexPos
++
continue
}
return
true
}
mIV
=
decode
(
mIV
,
0
)
}
mOutPos
+=
8
mIndexPos
=
0
return
true
@Suppress
(
"NAME_SHADOWING"
)
fun
encrypt
(
plaintext
:
ByteArray
,
offset
:
Int
,
len
:
Int
):
ByteArray
{
var
len
=
len
var
offset
=
offset
mInBlock
=
ByteArray
(
8
)
mIV
=
ByteArray
(
8
)
mOutPos
=
0
mPreOutPos
=
0
isFirstBlock
=
true
mIndexPos
=
(
len
+
10
)
%
8
if
(
mIndexPos
!=
0
)
{
mIndexPos
=
8
-
mIndexPos
}
mOutput
=
ByteArray
(
mIndexPos
+
len
+
10
)
mInBlock
[
0
]
=
(
rand
()
and
0
xf8
or
mIndexPos
).
toByte
()
for
(
i
in
1
..
mIndexPos
)
{
mInBlock
[
i
]
=
(
rand
()
and
0
xff
).
toByte
()
}
++
mIndexPos
for
(
i
in
0
..
7
)
{
mIV
[
i
]
=
0
}
}
fun
encrypt
(
plaintext
:
ByteArray
,
offset
:
Int
,
len
:
Int
):
ByteArray
{
var
g
=
0
var
len
=
len
;
while
(
g
<
2
)
{
var
offset
=
offset
;
if
(
mIndexPos
<
8
)
{
mInBlock
=
ByteArray
(
8
)
mInBlock
[
mIndexPos
++]
=
(
rand
()
and
0
xff
).
toByte
()
mIV
=
ByteArray
(
8
)
++
g
mOutPos
=
0
mPreOutPos
=
0
isFirstBlock
=
true
mIndexPos
=
(
len
+
10
)
%
8
if
(
mIndexPos
!=
0
)
{
mIndexPos
=
8
-
mIndexPos
}
}
mOutput
=
ByteArray
(
mIndexPos
+
len
+
10
)
if
(
mIndexPos
==
8
)
{
mInBlock
[
0
]
=
(
rand
()
and
0
xf8
or
mIndexPos
).
toByte
()
encodeOneBlock
()
for
(
i
in
1
..
mIndexPos
)
{
mInBlock
[
i
]
=
(
rand
()
and
0
xff
).
toByte
()
}
++
mIndexPos
for
(
i
in
0
..
7
)
{
mIV
[
i
]
=
0
}
}
}
var
g
=
0
while
(
len
>
0
)
{
while
(
g
<
2
)
{
if
(
mIndexPos
<
8
)
{
if
(
mIndexPos
<
8
)
{
mInBlock
[
mIndexPos
++]
=
plaintext
[
offset
++]
mInBlock
[
mIndexPos
++]
=
(
rand
()
and
0
xff
).
toByte
()
}
++
g
if
(
mIndexPos
==
8
)
{
}
encodeOneBlock
()
if
(
mIndexPos
==
8
)
{
}
encodeOneBlock
()
len--
}
}
g
=
0
while
(
g
<
7
)
{
if
(
mIndexPos
<
8
)
{
mInBlock
[
mIndexPos
++]
=
0
.
toByte
()
}
if
(
mIndexPos
==
8
)
{
encodeOneBlock
()
}
}
g
++
}
return
mOutput
}
while
(
len
>
0
)
{
fun
decrypt
(
cipherText
:
ByteArray
,
offset
:
Int
,
len
:
Int
):
ByteArray
?
{
if
(
mIndexPos
<
8
)
{
require
(!(
len
%
8
!=
0
||
len
<
16
))
{
"must len % 8 == 0 && len >= 16"
}
mInBlock
[
mIndexPos
++]
=
plaintext
[
offset
++]
mIV
=
decode
(
cipherText
,
offset
)
}
mIndexPos
=
(
mIV
[
0
]
and
7
).
toInt
()
if
(
mIndexPos
==
8
)
{
var
plen
=
len
-
mIndexPos
-
10
encodeOneBlock
()
isFirstBlock
=
true
}
if
(
plen
<
0
)
{
len--
return
null
}
mOutput
=
ByteArray
(
plen
)
mPreOutPos
=
0
mOutPos
=
8
++
mIndexPos
var
g
=
0
while
(
g
<
2
)
{
if
(
mIndexPos
<
8
)
{
++
mIndexPos
++
g
}
}
g
=
0
if
(
mIndexPos
==
8
)
{
while
(
g
<
7
)
{
isFirstBlock
=
false
if
(
mIndexPos
<
8
)
{
if
(
!
decodeOneBlock
(
cipherText
,
offset
,
len
)
)
{
mInBlock
[
mIndexPos
++]
=
0
.
toByte
(
)
throw
RuntimeException
(
"Unable to decode"
)
}
}
if
(
mIndexPos
==
8
)
{
encodeOneBlock
()
}
g
++
}
}
return
mOutput
}
}
fun
decrypt
(
cipherText
:
ByteArray
,
offset
:
Int
,
len
:
Int
):
ByteArray
?
{
var
outpos
=
0
require
(!(
len
%
8
!=
0
||
len
<
16
))
{
"must len % 8 == 0 && len >= 16"
}
while
(
plen
!=
0
)
{
mIV
=
decode
(
cipherText
,
offset
)
if
(
mIndexPos
<
8
)
{
mIndexPos
=
(
mIV
[
0
]
and
7
).
toInt
(
)
mOutput
[
outpos
++]
=
if
(
isFirstBlock
)
var
plen
=
len
-
mIndexPos
-
10
mIV
[
mIndexPos
]
isFirstBlock
=
tru
e
els
e
if
(
plen
<
0
)
{
(
cipherText
[
mPreOutPos
+
offset
+
mIndexPos
]
xor
mIV
[
mIndexPos
])
return
null
++
mIndexPos
}
}
mOutput
=
ByteArray
(
plen
)
if
(
mIndexPos
==
8
)
{
mPreOutPos
=
0
mPreOutPos
=
mOutPos
-
8
mOutPos
=
8
isFirstBlock
=
false
++
mIndexPos
if
(!
decodeOneBlock
(
cipherText
,
offset
,
len
))
{
var
g
=
0
throw
RuntimeException
(
"Unable to decode"
)
while
(
g
<
2
)
{
if
(
mIndexPos
<
8
)
{
++
mIndexPos
++
g
}
if
(
mIndexPos
==
8
)
{
isFirstBlock
=
false
if
(!
decodeOneBlock
(
cipherText
,
offset
,
len
))
{
throw
RuntimeException
(
"Unable to decode"
)
}
}
}
}
}
plen--
var
outpos
=
0
}
while
(
plen
!=
0
)
{
g
=
0
if
(
mIndexPos
<
8
)
{
while
(
g
<
7
)
{
mOutput
[
outpos
++]
=
if
(
isFirstBlock
)
if
(
mIndexPos
<
8
)
{
mIV
[
mIndexPos
]
if
(
cipherText
[
mPreOutPos
+
offset
+
mIndexPos
].
xor
(
mIV
[
mIndexPos
]).
toInt
()
!=
0
)
{
else
throw
RuntimeException
()
(
cipherText
[
mPreOutPos
+
offset
+
mIndexPos
]
xor
mIV
[
mIndexPos
])
}
else
{
++
mIndexPos
++
mIndexPos
}
}
if
(
mIndexPos
==
8
)
{
mPreOutPos
=
mOutPos
-
8
isFirstBlock
=
false
if
(!
decodeOneBlock
(
cipherText
,
offset
,
len
))
{
throw
RuntimeException
(
"Unable to decode"
)
}
}
plen--
}
}
g
=
0
while
(
g
<
7
)
{
if
(
mIndexPos
<
8
)
{
if
(
cipherText
[
mPreOutPos
+
offset
+
mIndexPos
].
xor
(
mIV
[
mIndexPos
]).
toInt
()
!=
0
)
{
throw
RuntimeException
()
}
else
{
++
mIndexPos
}
}
if
(
mIndexPos
==
8
)
{
if
(
mIndexPos
==
8
)
{
mPreOutPos
=
mOutPos
mPreOutPos
=
mOutPos
if
(!
decodeOneBlock
(
cipherText
,
offset
,
len
))
{
if
(!
decodeOneBlock
(
cipherText
,
offset
,
len
))
{
throw
RuntimeException
(
"Unable to decode"
)
throw
RuntimeException
(
"Unable to decode"
)
}
}
}
g
++
}
}
return
mOutput
g
++
}
}
return
mOutput
}
return
if
(
encrypt
)
{
return
if
(
encrypt
)
{
encrypt
(
data
,
0
,
data
.
size
)
encrypt
(
data
,
0
,
data
.
size
)
}
else
{
}
else
{
try
{
try
{
return
decrypt
(
data
,
0
,
data
.
size
)
!!
return
decrypt
(
data
,
0
,
data
.
size
)
!!
}
catch
(
e
:
Exception
)
{
}
catch
(
e
:
Exception
)
{
println
(
"Source: "
+
data
.
toUHexString
(
" "
))
println
(
"Source: "
+
data
.
toUHexString
(
" "
))
println
(
"Key: "
+
key
.
toUHexString
(
" "
))
println
(
"Key: "
+
key
.
toUHexString
(
" "
))
throw
e
throw
e
}
}
}
}
}
}
fun
encrypt
(
source
:
ByteArray
,
key
:
ByteArray
):
ByteArray
{
fun
encrypt
(
source
:
ByteArray
,
key
:
ByteArray
):
ByteArray
{
return
doOption
(
source
,
key
,
true
)
return
doOption
(
source
,
key
,
true
)
}
}
fun
encrypt
(
source
:
ByteArray
,
keyHex
:
String
):
ByteArray
{
@Suppress
(
"unused"
)
return
encrypt
(
source
,
keyHex
.
hexToBytes
())
fun
encrypt
(
source
:
ByteArray
,
keyHex
:
String
):
ByteArray
{
}
return
encrypt
(
source
,
keyHex
.
hexToBytes
())
}
fun
decrypt
(
source
:
ByteArray
,
key
:
ByteArray
):
ByteArray
{
fun
decrypt
(
source
:
ByteArray
,
key
:
ByteArray
):
ByteArray
{
return
doOption
(
source
,
key
,
false
)
return
doOption
(
source
,
key
,
false
)
}
}
fun
decrypt
(
source
:
ByteArray
,
keyHex
:
String
):
ByteArray
{
fun
decrypt
(
source
:
ByteArray
,
keyHex
:
String
):
ByteArray
{
return
decrypt
(
source
,
keyHex
.
hexToBytes
())
return
decrypt
(
source
,
keyHex
.
hexToBytes
())
}
}
private
fun
pack
(
bytes
:
ByteArray
,
offset
:
Int
,
len
:
Int
):
Long
{
@Suppress
(
"SameParameterValue"
)
var
result
:
Long
=
0
private
fun
pack
(
bytes
:
ByteArray
,
offset
:
Int
,
len
:
Int
):
Long
{
val
max_offset
=
if
(
len
>
8
)
offset
+
8
else
offset
+
len
var
result
:
Long
=
0
for
(
index
in
offset
until
max_offset
)
{
val
maxOffset
=
if
(
len
>
8
)
offset
+
8
else
offset
+
len
result
=
result
shl
8
or
(
bytes
[
index
].
toLong
()
and
0
xffL
)
for
(
index
in
offset
until
maxOffset
)
{
}
result
=
result
shl
8
or
(
bytes
[
index
].
toLong
()
and
0
xffL
)
return
result
shr
32
or
(
result
and
UINT32_MASK
)
}
}
return
result
shr
32
or
(
result
and
UINT32_MASK
)
}
}
}
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/utils/Tested.kt
View file @
86d64f02
...
@@ -5,4 +5,4 @@ package net.mamoe.mirai.utils
...
@@ -5,4 +5,4 @@ package net.mamoe.mirai.utils
*
*
* @author Him188moe
* @author Him188moe
*/
*/
internal
annotation
class
TestedSuccessfully
internal
annotation
class
Tested
\ No newline at end of file
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/utils/Utils.kt
View file @
86d64f02
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
,
"EXPERIMENTAL_UNSIGNED_LITERALS"
)
package
net.mamoe.mirai.utils
package
net.mamoe.mirai.utils
import
net.mamoe.mirai.network.Protocol
import
net.mamoe.mirai.network.Protocol
import
java.awt.image.BufferedImage
import
java.io.ByteArrayOutputStream
import
java.io.ByteArrayOutputStream
import
java.io.DataOutputStream
import
java.io.DataOutputStream
import
java.io.File
import
java.io.File
import
java.lang.reflect.Field
import
java.lang.reflect.Field
import
java.util.*
import
java.util.*
import
java.util.zip.CRC32
import
java.util.zip.CRC32
import
javax.imageio.ImageIO
/**
/**
* @author Him188moe
* @author Him188moe
...
@@ -24,14 +28,14 @@ fun ByteArray.toHexString(separator: String = " "): String = this.joinToString(s
...
@@ -24,14 +28,14 @@ fun ByteArray.toHexString(separator: String = " "): String = this.joinToString(s
return
@
joinToString
ret
return
@
joinToString
ret
}
}
@ExperimentalUnsignedTypes
fun
ByteArray
.
toUHexString
(
separator
:
String
=
" "
):
String
=
this
.
toUByteArray
().
toUHexString
(
separator
)
fun
ByteArray
.
toUHexString
(
separator
:
String
=
" "
):
String
=
this
.
toUByteArray
().
toUHexString
(
separator
)
@ExperimentalUnsignedTypes
@JvmSynthetic
@JvmSynthetic
fun
ByteArray
.
toUHexString
():
String
=
this
.
toUByteArray
().
toUHexString
()
fun
ByteArray
.
toUHexString
():
String
=
this
.
toUByteArray
().
toUHexString
()
@ExperimentalUnsignedTypes
@JvmSynthetic
@JvmSynthetic
fun
UByteArray
.
toUHexString
(
separator
:
String
=
" "
):
String
{
fun
UByteArray
.
toUHexString
(
separator
:
String
=
" "
):
String
{
return
this
.
joinToString
(
separator
)
{
return
this
.
joinToString
(
separator
)
{
...
@@ -43,36 +47,36 @@ fun UByteArray.toUHexString(separator: String = " "): String {
...
@@ -43,36 +47,36 @@ fun UByteArray.toUHexString(separator: String = " "): String {
}
}
}
}
@ExperimentalUnsignedTypes
@JvmSynthetic
@JvmSynthetic
fun
UByteArray
.
toUHexString
():
String
=
this
.
toUHexString
(
" "
)
fun
UByteArray
.
toUHexString
():
String
=
this
.
toUHexString
(
" "
)
@ExperimentalUnsignedTypes
fun
Byte
.
toUHexString
():
String
=
this
.
toUByte
().
toString
(
16
)
fun
Byte
.
toUHexString
():
String
=
this
.
toUByte
().
toString
(
16
)
@ExperimentalUnsignedTypes
fun
String
.
hexToBytes
():
ByteArray
=
Protocol
.
hexToBytes
(
this
)
fun
String
.
hexToBytes
():
ByteArray
=
Protocol
.
hexToBytes
(
this
)
@ExperimentalUnsignedTypes
fun
String
.
hexToUBytes
():
UByteArray
=
Protocol
.
hexToUBytes
(
this
)
fun
String
.
hexToUBytes
():
UByteArray
=
Protocol
.
hexToUBytes
(
this
)
@ExperimentalUnsignedTypes
fun
String
.
hexToInt
():
Int
=
hexToBytes
().
toUInt
().
toInt
()
fun
String
.
hexToInt
():
Int
=
hexToBytes
().
toUInt
().
toInt
()
@ExperimentalUnsignedTypes
fun
ByteArray
.
toUInt
():
UInt
=
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
)
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
)
open
class
ByteArrayDataOutputStream
:
DataOutputStream
(
ByteArrayOutputStream
())
{
open
class
ByteArrayDataOutputStream
:
DataOutputStream
(
ByteArrayOutputStream
())
{
open
fun
toByteArray
():
ByteArray
=
(
out
as
ByteArrayOutputStream
).
toByteArray
()
open
fun
toByteArray
():
ByteArray
=
(
out
as
ByteArrayOutputStream
).
toByteArray
()
@ExperimentalUnsignedTypes
open
fun
toUByteArray
():
UByteArray
=
(
out
as
ByteArrayOutputStream
).
toByteArray
().
toUByteArray
()
open
fun
toUByteArray
():
UByteArray
=
(
out
as
ByteArrayOutputStream
).
toByteArray
().
toUByteArray
()
}
}
@JvmSynthetic
@JvmSynthetic
fun
lazyEncode
(
t
:
(
ByteArrayDataOutputStream
)
->
Unit
):
ByteArray
=
ByteArrayDataOutputStream
().
let
{
t
(
it
);
return
it
.
toByteArray
()
}
fun
lazyEncode
(
t
:
(
ByteArrayDataOutputStream
)
->
Unit
):
ByteArray
=
ByteArrayDataOutputStream
().
also
(
t
).
toByteArray
()
@ExperimentalUnsignedTypes
fun
getRandomByteArray
(
length
:
Int
):
ByteArray
{
fun
getRandomByteArray
(
length
:
Int
):
ByteArray
{
val
bytes
=
LinkedList
<
Byte
>()
val
bytes
=
LinkedList
<
Byte
>()
repeat
(
length
)
{
bytes
.
add
((
Math
.
random
()
*
255
).
toByte
())
}
repeat
(
length
)
{
bytes
.
add
((
Math
.
random
()
*
255
).
toByte
())
}
...
@@ -134,4 +138,10 @@ fun ByteArray.removeZeroTail(): ByteArray {
...
@@ -134,4 +138,10 @@ fun ByteArray.removeZeroTail(): ByteArray {
--
i
--
i
}
}
return
this
.
copyOfRange
(
0
,
i
+
1
)
return
this
.
copyOfRange
(
0
,
i
+
1
)
}
fun
BufferedImage
.
toByteArray
(
formatName
:
String
=
"PNG"
):
ByteArray
{
return
lazyEncode
{
ImageIO
.
write
(
this
,
formatName
,
it
)
}
}
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/utils/Varint.kt
0 → 100644
View file @
86d64f02
@
file
:
JvmName
(
"Varint"
)
@
file
:
Suppress
(
"EXPERIMENTAL_API_USAGE"
)
package
net.mamoe.mirai.utils
import
java.io.DataInputStream
import
java.io.DataOutputStream
import
java.io.IOException
import
java.io.InputStream
import
kotlin.experimental.or
/**
* Tool class for VarInt or VarLong operations.
*
* Some code from http://wiki.vg/Protocol.
*
* @author MagicDroidX of Nukkit Project
* @author lmlstarqaq of Nukkit Project
*/
fun
encodeZigZag32
(
signedInt
:
Int
):
Long
{
return
(
signedInt
shl
1
xor
(
signedInt
shr
31
)).
toLong
()
}
@JvmSynthetic
fun
decodeZigZag32
(
uint
:
UInt
):
Int
{
return
decodeZigZag32
(
uint
.
toLong
())
}
fun
decodeZigZag32
(
uint
:
Long
):
Int
{
return
(
uint
shr
1
).
toInt
()
xor
-(
uint
and
1
).
toInt
()
}
fun
encodeZigZag64
(
signedLong
:
Long
):
Long
{
return
signedLong
shl
1
xor
(
signedLong
shr
63
)
}
fun
decodeZigZag64
(
signedLong
:
Long
):
Long
{
return
signedLong
.
ushr
(
1
)
xor
-(
signedLong
and
1
)
}
@Throws
(
IOException
::
class
)
fun
DataInputStream
.
readVarInt
():
Int
{
return
decodeZigZag32
(
this
.
readUnsignedVarInt
())
}
@Throws
(
IOException
::
class
)
fun
DataInputStream
.
readUnsignedVarInt
():
UInt
{
return
read
(
this
,
5
).
toUInt
()
}
@Throws
(
IOException
::
class
)
fun
DataInputStream
.
readVarLong
():
Long
{
return
decodeZigZag64
(
readUnsignedVarLong
().
toLong
())
}
@Throws
(
IOException
::
class
)
fun
DataInputStream
.
readUnsignedVarLong
():
ULong
{
return
read
(
this
,
10
).
toULong
()
}
@Throws
(
IOException
::
class
)
fun
DataOutputStream
.
writeVarInt
(
signedInt
:
Int
)
{
this
.
writeUVarInt
(
encodeZigZag32
(
signedInt
))
}
@Throws
(
IOException
::
class
)
fun
DataOutputStream
.
writeUVarInt
(
uint
:
UInt
)
{
return
writeUVarInt
(
uint
.
toLong
())
}
@Throws
(
IOException
::
class
)
fun
DataOutputStream
.
writeUVarInt
(
uint
:
Long
)
{
this
.
write0
(
uint
)
}
@Throws
(
IOException
::
class
)
fun
DataOutputStream
.
writeVarLong
(
signedLong
:
Long
)
{
this
.
writeUVarLong
(
encodeZigZag64
(
signedLong
))
}
@Throws
(
IOException
::
class
)
fun
DataOutputStream
.
writeUVarLong
(
ulong
:
Long
)
{
this
.
write0
(
ulong
)
}
@Throws
(
IOException
::
class
)
private
fun
DataOutputStream
.
write0
(
long
:
Long
)
{
var
value
=
long
do
{
var
temp
=
(
value
and
127
).
toByte
()
value
=
value
ushr
7
if
(
value
!=
0L
)
{
temp
=
temp
or
128
.
toByte
()
}
this
.
writeByte
(
temp
.
toInt
())
}
while
(
value
!=
0L
)
}
@Throws
(
IOException
::
class
)
private
fun
read
(
stream
:
DataInputStream
,
maxSize
:
Int
):
Long
{
var
value
:
Long
=
0
var
size
=
0
var
b
=
stream
.
readByte
().
toInt
()
while
(
b
and
0
x80
==
0
x80
)
{
value
=
value
or
((
b
and
0
x7F
).
toLong
()
shl
size
++
*
7
)
require
(
size
<
maxSize
)
{
"VarLong too big"
}
b
=
stream
.
readByte
().
toInt
()
}
return
value
or
((
b
and
0
x7F
).
toLong
()
shl
size
*
7
)
}
@Throws
(
IOException
::
class
)
private
fun
read
(
stream
:
InputStream
,
maxSize
:
Int
):
Long
{
var
value
:
Long
=
0
var
size
=
0
var
b
=
stream
.
read
()
while
(
b
and
0
x80
==
0
x80
)
{
value
=
value
or
((
b
and
0
x7F
).
toLong
()
shl
size
++
*
7
)
require
(
size
<
maxSize
)
{
"VarLong too big"
}
b
=
stream
.
read
()
}
return
value
or
((
b
and
0
x7F
).
toLong
()
shl
size
*
7
)
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/utils/config/MiraiConfigSection.java
View file @
86d64f02
package
net.mamoe.mirai.utils.config
;
package
net.mamoe.mirai.utils.config
;
import
net.mamoe.mirai.utils.MiraiSynchronizedLinkedHashMap
;
import
org.jetbrains.annotations.Nullable
;
import
org.jetbrains.annotations.Nullable
;
import
java.util.LinkedHashMap
;
import
java.util.LinkedHashMap
;
...
@@ -10,7 +11,7 @@ import java.util.function.Supplier;
...
@@ -10,7 +11,7 @@ import java.util.function.Supplier;
/**
/**
* @author NaturalHG
* @author NaturalHG
*/
*/
public
class
MiraiConfigSection
<
T
>
extends
MiraiSynchronizedLinked
List
Map
<
String
,
T
>
{
public
class
MiraiConfigSection
<
T
>
extends
MiraiSynchronizedLinked
Hash
Map
<
String
,
T
>
{
public
MiraiConfigSection
(){
public
MiraiConfigSection
(){
super
();
super
();
...
...
mirai-core/src/test/java/PacketTest.kt
deleted
100644 → 0
View file @
5c00a59a
import
net.mamoe.mirai.network.packet.login.ClientPasswordSubmissionPacket
import
net.mamoe.mirai.utils.toUHexString
@ExperimentalUnsignedTypes
fun
main
(){
/*
val data = "00 37 13 08 25 31 01 EB 10 08 30 69 50 1C 84 A9 C2 16 D7 52 B9 1C 79 CA 5A CF FD BC EB 10 08 30 69 50 1C 84 A9 C2 16 D7 52 B9 1C 79 CA 5A CF FD BC AE D8 A6 BB DC 21 6E 79 26 E1 A2 23 11 AA B0 9A AE D8 A6 BB DC 21 6E 79 26 E1 A2 23 11 AA B0 9A 76 E4 B8 DD 03 00 00 00 01 2E 01 00 00 68 52 00 00 00 00 A4 F1 91 88 C9 82 14 99 0C 9E 56 55 91 23 C8 3D C3 47 F0 25 A1 8E 74 EF 1E 0B 32 5B 20 8A FA 3B 0B 52 8F 86 E6 04 F1 D6 F8 63 75 60 8C 0C 7D 06 D1 E0 22 F8 49 EF AF 61 EE 7E 69 72 EB 10 08 30 69 50 1C 84 A9 C2 16 D7 52 B9 1C 79 CA 5A CF FD BC AE D8 A6 BB DC 21 6E 79 26 E1 A2 23 11 AA B0 9A 49 39 72 ED 61 12 B6 88 4D A2 56 23 E9 92 11 92 27 4A 70 00 C9 01 7B 03";
val s = DataInputStream(data.hexToBytes().inputStream())
val packet = ServerTouchResponsePacket(ServerTouchResponsePacket.Type.TYPE_08_25_31_01, s)
packet.decode()
System.out.println(packet.token.toUByteArray().toUHexString(" "))
System.out.println(packet.loginTime.toUHexString(" "))
System.out.println(packet.loginIP)
*/
// val packet = ClientPasswordSubmissionPacket(1994701021,"xiaoqqq",)
/*
val data = "00 01 09 00 70 00 01 5C 71 80 A6 BA 20 62 2E C1 BE BF F2 47 37 40 A1 00 38 91 25 85 58 18 D3 67 77 2C 4D 02 D8 66 A6 F7 3E 57 D8 CE 01 47 7F D0 8F 13 C8 3A E5 19 A2 60 BC 4C 9A 35 4E 92 9F 21 48 6C 67 68 36 6B 94 C1 6F 11 8D 55 6B 04 9A 22 C3 00 20 29 7E D4 A7 16 02 07 14 41 90 3A 65 06 AC CB 28 AB 90 DB 46 33 C9 C0 1D 06 44 7A 92 17 C3 A5 F3 00 00 01 03 00 14 00 01 00 10 60 C9 5D A7 45 70 04 7F 21 7D 84 50 5C 66 A5 C6 01 07 01 D3 00 01 00 16 00 00 00 01 00 00 00 64 00 00 0D B6 00 09 3A 80 00 00 00 3C 00 02 2E 29 4E 47 5F 68 78 2C 47 25 5F 59 50 65 60 5D 00 88 00 04 5D 59 45 17 B7 5F F8 D4 00 00 00 00 00 78 38 E0 3B 23 4A C5 0E 93 CB C1 66 96 37 8B 46 B2 86 23 3F 2D 09 45 E0 16 1C E9 9C 11 7A FA 2D A8 50 47 42 74 01 06 84 76 0E 5F C6 04 29 1A 4A 65 AA 93 49 DF BD 00 ED 80 B8 26 CA 80 E8 20 6D 15 43 DD D8 E6 48 C2 8A 5A F8 70 6B 51 3A E2 2D 21 95 4B 6A 75 A8 90 CA B1 C0 E5 73 99 D7 59 D8 DD 3D C9 5C E4 49 61 22 11 60 85 48 C4 7D E0 84 62 AD B3 13 84 61 C1 9E 19 35 41 44 44 37 3F 21 33 64 4B 37 5D 77 6D 61 3F 00 78 00 01 5D 59 45 17 00 70 A4 D9 44 9E 95 51 B4 B0 91 CC 1E DB 34 F9 F7 13 8B 30 08 C0 AE 33 22 9C FF 87 CF 9B A2 B0 E5 E1 D0 E0 AD DD 8F E9 F6 1E 01 1F AA 74 46 66 B4 81 54 B9 29 E5 FC 0B 7F C9 13 AE 32 BA D6 55 2E B0 A1 30 24 B6 F2 E7 62 F9 2E 00 E4 51 61 50 7C D1 36 E8 61 96 36 FF B7 32 74 3C 2A F7 74 63 DA 7D 57 84 18 ED 84 E9 D8 87 6D 66 1D D5 84 D4 23 99 00 83 01 63 2A 69 2E 25 79 28 3B 29 33 29 40 28 54 7E 21 00 70 00 01 5D 59 45 17 00 68 6F 1F FB 31 7B D7 B7 D8 91 32 D7 20 8B 8A F6 02 C8 22 E5 24 8C 25 F2 6A C5 B0 ED 35 01 BF AF 42 72 33 4E FB 3F D3 02 BA F4 46 2B 68 20 0B E3 39 81 B1 D3 8A E0 1B 0F 69 D1 70 AE 49 A5 24 4F BB 58 4F F8 31 A0 37 4C CD F1 12 35 80 99 7D 25 CA F9 E9 45 B6 B0 57 56 66 61 C5 7B 90 57 BF E2 2C 94 91 80 1A B0 D7 21 A8 44 2C 33 4A 29 77 5F 71 40 41 38 3D 7A 41 65 33 01 08 00 29 00 01 00 25 00 1D 02 5B 14 28 E0 B9 91 E2 80 A2 CC 80 CF 89 E2 80 A2 CC 81 E0 B9 91 29 02 13 80 02 00 05 00 04 00 00 00 01 01 15 00 10 F9 86 85 81 30 F6 1B E0 E7 97 98 F6 46 C3 4F B2"
val s = DataInputStream(data.hexToBytes().inputStream())
val packet = ServerLoginResponseSuccessPacket(s,(data.length+1)/3)
packet.decode()
System.out.println("0828key: \n" + packet._0828_rec_decr_key.toUByteArray().toUHexString(" "))
System.out.println("token88: \n" + packet.token88.toUByteArray().toUHexString(" "))
System.out.println("token38: \n" + packet.token38.toUByteArray().toUHexString(" "))
System.out.println("enckey: \n" + packet.encryptionKey.toUByteArray().toUHexString(" "))
System.out.println("nick: " + packet.nick)
System.out.println("age: " + packet.age)
System.out.println("gender: " + packet.gender)
*/
/*
val data = "FB 01 04 03 33 00 01 00 BA 02 03 2C 13 00 05 01 00 00 01 23 00 38 F5 C3 CF F4 B4 27 C5 8F 9B D3 ED 18 73 7D E9 CB 43 1F 57 43 BE D3 1B 9A F5 26 2B F4 D9 43 14 9A ED 3B C3 6C E5 7F 4E B0 0C BA 55 57 18 06 78 E1 13 A7 B2 A8 7F 47 E1 1C 02 BC 89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52 00 00 00 82 00 00 00 35 08 03 00 00 00 BA 12 C3 02 00 00 00 04 67 41 4D 41 00 00 B1 8F 0B FC 61 05 00 00 00 01 73 52 47 42 00 AE CE 1C E9 00 00 00 6C 50 4C 54 45 F6 F8 F4 E3 EE FD E5 FD FF EE FD F0 F6 F9 E7 F7 F9 EC F4 FE FF F7 F7 F9 F5 F4 FF EC F7 FF E6 F4 E0 F5 FC F8 49 5B 8F CB DB FA BB C9 F5 2B 40 7C D6 E6 FF FD FB FF ED F1 F0 2A 43 B3 D6 F6 FF FC F1 FC 1C 38 91 A7 BD F6 63 74 BD 70 8B CC 34 4F A5 DE F3 F1 75 88 E7 A4 B7 D3 73 82 A1 8C A3 DC F3 FB D8 4D 68 B9 94 A8 FB 8D 9C B6 CB 42 B0 8E 00 00 0A 6F 49 44 41 54 58 C3 B4 57 89 76 EB 2A 12 14 20 B1 09 10 42 68 DF 2C FB FF FF 71 0A 79 49 E2 E4 CE CC 79 37 8F 13 59 B6 72 EC 2E AA BB AB 9A 2C FB 61 89 8F 95 E5 79 A9 70 CB B2 22 C7 2A 65 DB 5E 72 21 F1 A9 90 B2 28 C4 F9 AF 5F 5F 05 30 9C 28 D2 4B C6 58 F9 8C 92 17 39 13 6D 9B FF EB 10 8A 3B 0F 2F 10 52 64 45 51 64 42 A6 37 79 21 DA FC F2 6F 40 08 9F AE B7 9C A4 C8 27 31 F2 C4 50 A4 D4 9C F9 01 BC A2 90 0F 08 E1 2F AE 1F E3 7E 7D 24 52 F4 67 2C 91 02 E3 CA 13 2F 78 97 00 86 DF 4E C4 23 56 F1 F8 7B 10 90 42 3D D2 93 EE 27 04 F1 80 F0 4B 99 10 4F 62 5E D9 2D EE 57 8A F1 A0 E1 64 20 2B 55 F9 C8 C3 67 08 F8 81 7F F2 F7 BE FD 67 1D 9E 9B 4F EB 89 25 21 28 19 63 09 5D A9 94 2A 59 AA 87 B3 32 4E 84 FF 3C 13 8F AF 06 F1 29 FD E2 C1 02 54 E0 8C 5E 5C 2E A5 72 43 65 F4 E5 72 61 5C 4A 45 81 41 97 79 0A 9E FF 62 22 C2 EB 7E 42 48 45 80 2B 0F 58 B9 66 D6 1C 63 75 D3 97 BC F4 08 0F 08 5C 6B 8D CC 14 1F 10 C4 5F B4 C3 37 66 EE E5 78 CF 42 12 05 CD F5 4D 29 EB 36 AD 19 82 CF 76 35 C6 86 B2 94 A7 36 FC 62 39 BE A8 B8 D7 02 78 08 8F 66 E4 44 45 DF BB AB A3 34 92 14 DF 54 C6 32 1D 00 21 7F 41 08 7F C9 7F F8 28 88 4F B5 90 89 3A 21 90 9E DF E8 DE 34 4D 8C D1 EF C6 AC 6B 7F 74 8E B1 FA 84 90 7F B0 F0 CF 5A E2 27 4C AF 8E 28 EF 24 48 B2 AF B1 9A 96 3E F6 43 75 38 6F 29 5D 1A C7 59 78 87 F0 1B B2 F0 95 05 3C 93 B2 26 B6 9F BA 18 AB AE 59 EC 88 17 17 A9 8F 4B B3 CE 60 A1 CD F2 CB 03 42 10 7F D9 06 1F 76 80 8E 4F 6D 9F 56 99 05 25 A5 DD AA EB 62 7A 6F 87 E6 B8 0E 5D 33 C6 99 C6 C4 02 24 EB 74 8C 87 98 64 F8 5E A9 9E 1E F7 72 FB FF B3 21 8A A4 00 01 00 28 F9 59 C5 E6 34 43 53 95 C8 17 2E 62 78 BF E8 27 BF 20 BA 11 5A 74 D1 7C D0 95 6C F6 A3 41 D2 84 BD 7D F6 64 BC 27 40 50 01 15 00 10 44 98 EB B8 30 3B DE 7D 2B CC 4C 41 B3 1C 92 86"
val s = DataInputStream(data.hexToBytes().inputStream())
val packet = ServerLoginResponseVerificationCodePacket(s,(data.length+1)/3)
packet.decode()
println(packet.token00BA.toUByteArray().toUHexString(" "))
println(packet.verifyCode.toUByteArray().toUHexString(" "))
println(packet.verifyCodeLength)
File(System.getProperty("user.dir") + "/5.png").createNewFile()
packet.verifyCode.inputStream().transferTo(FileOutputStream(System.getProperty("user.dir") + "/5.png"))
*/
val
packet
=
ClientPasswordSubmissionPacket
(
1994701021
,
"xiaoqqq"
,
131513
,
"123.123.123.123"
,
"tgtgtKey"
.
toByteArray
(),
""
.
toByteArray
())
packet
.
encodeToByteArray
().
toUByteArray
().
toUHexString
(
" "
)
}
\ No newline at end of file
pom.xml
View file @
86d64f02
...
@@ -17,10 +17,12 @@
...
@@ -17,10 +17,12 @@
</modules>
</modules>
<repositories>
<repositories>
<!--
<repository>
<repository>
<id>mamoe-repo</id>
<id>mamoe-repo</id>
<url>http://mamoe.net:8081/repository/public/</url>
<url>http://mamoe.net:8081/repository/public/</url>
</repository>
</repository>
-->
<repository>
<repository>
<id>
huawei
</id>
<id>
huawei
</id>
<url>
https://mirrors.huaweicloud.com/repository/maven/
</url>
<url>
https://mirrors.huaweicloud.com/repository/maven/
</url>
...
@@ -52,17 +54,24 @@
...
@@ -52,17 +54,24 @@
<version>
1.18.8
</version>
<version>
1.18.8
</version>
<scope>
compile
</scope>
<scope>
compile
</scope>
</dependency>
</dependency>
<dependency>
<groupId>
org.ini4j
</groupId>
<artifactId>
ini4j
</artifactId>
<version>
0.5.2
</version>
</dependency>
</dependencies>
</dependencies>
<dependencyManagement>
<dependencyManagement>
<dependencies>
<dependencies>
<dependency>
<groupId>
com.google.protobuf
</groupId>
<artifactId>
protobuf-java
</artifactId>
<version>
3.5.0
</version>
</dependency>
<dependency>
<groupId>
org.ini4j
</groupId>
<artifactId>
ini4j
</artifactId>
<version>
0.5.2
</version>
</dependency>
<!-- https://mvnrepository.com/artifact/net.java.dev.jna/jna -->
<!-- https://mvnrepository.com/artifact/net.java.dev.jna/jna -->
<dependency>
<dependency>
<groupId>
net.java.dev.jna
</groupId>
<groupId>
net.java.dev.jna
</groupId>
...
@@ -90,12 +99,6 @@
...
@@ -90,12 +99,6 @@
<version>
4.1.38.Final
</version>
<version>
4.1.38.Final
</version>
</dependency>
</dependency>
<dependency>
<groupId>
org.ini4j
</groupId>
<artifactId>
ini4j
</artifactId>
<version>
0.5.2
</version>
</dependency>
<dependency>
<dependency>
<groupId>
org.jetbrains.kotlin
</groupId>
<groupId>
org.jetbrains.kotlin
</groupId>
<artifactId>
kotlin-stdlib
</artifactId>
<artifactId>
kotlin-stdlib
</artifactId>
...
@@ -123,12 +126,11 @@
...
@@ -123,12 +126,11 @@
</dependency>
</dependency>
<dependency>
<dependency>
<groupId>
commons-httpclient
</groupId>
<groupId>
org.jsoup
</groupId>
<artifactId>
commons-httpclient
</artifactId>
<artifactId>
jsoup
</artifactId>
<version>
3
.1
</version>
<version>
1.12
.1
</version>
<scope>
compile
</scope>
<scope>
compile
</scope>
</dependency>
</dependency>
</dependencies>
</dependencies>
</dependencyManagement>
</dependencyManagement>
...
...
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