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
93dc8e58
Commit
93dc8e58
authored
Sep 07, 2019
by
liujiahua123123
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/master'
# Conflicts: # mirai-core/src/main/java/net/mamoe/mirai/Robot.java
parents
5b07f09d
9a0092ff
Changes
75
Hide whitespace changes
Inline
Side-by-side
Showing
75 changed files
with
1945 additions
and
1250 deletions
+1945
-1250
README.md
README.md
+5
-3
mirai-core/pom.xml
mirai-core/pom.xml
+6
-0
mirai-core/src/main/java/net/mamoe/mirai/MiraiMain.java
mirai-core/src/main/java/net/mamoe/mirai/MiraiMain.java
+2
-16
mirai-core/src/main/java/net/mamoe/mirai/MiraiServer.java
mirai-core/src/main/java/net/mamoe/mirai/MiraiServer.java
+48
-84
mirai-core/src/main/java/net/mamoe/mirai/Robot.java
mirai-core/src/main/java/net/mamoe/mirai/Robot.java
+77
-55
mirai-core/src/main/java/net/mamoe/mirai/contact/Contact.kt
mirai-core/src/main/java/net/mamoe/mirai/contact/Contact.kt
+3
-1
mirai-core/src/main/java/net/mamoe/mirai/contact/Group.kt
mirai-core/src/main/java/net/mamoe/mirai/contact/Group.kt
+48
-51
mirai-core/src/main/java/net/mamoe/mirai/contact/Lazy.kt
mirai-core/src/main/java/net/mamoe/mirai/contact/Lazy.kt
+0
-17
mirai-core/src/main/java/net/mamoe/mirai/contact/QQ.kt
mirai-core/src/main/java/net/mamoe/mirai/contact/QQ.kt
+11
-6
mirai-core/src/main/java/net/mamoe/mirai/event/AsyncEvent.java
...-core/src/main/java/net/mamoe/mirai/event/AsyncEvent.java
+27
-0
mirai-core/src/main/java/net/mamoe/mirai/event/AsyncEventKt.kt
...-core/src/main/java/net/mamoe/mirai/event/AsyncEventKt.kt
+18
-0
mirai-core/src/main/java/net/mamoe/mirai/event/Cancellable.java
...core/src/main/java/net/mamoe/mirai/event/Cancellable.java
+1
-1
mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEvent.java
...-core/src/main/java/net/mamoe/mirai/event/MiraiEvent.java
+35
-0
mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEventHook.java
...e/src/main/java/net/mamoe/mirai/event/MiraiEventHook.java
+12
-11
mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEventHookKt.kt
...e/src/main/java/net/mamoe/mirai/event/MiraiEventHookKt.kt
+31
-0
mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEventKt.kt
...-core/src/main/java/net/mamoe/mirai/event/MiraiEventKt.kt
+8
-0
mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEventManager.java
...rc/main/java/net/mamoe/mirai/event/MiraiEventManager.java
+35
-16
mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEventManagerKt.kt
...rc/main/java/net/mamoe/mirai/event/MiraiEventManagerKt.kt
+31
-2
mirai-core/src/main/java/net/mamoe/mirai/event/events/network/BeforePacketSendEvent.java
...moe/mirai/event/events/network/BeforePacketSendEvent.java
+16
-0
mirai-core/src/main/java/net/mamoe/mirai/event/events/network/ClientPacketEvent.java
...t/mamoe/mirai/event/events/network/ClientPacketEvent.java
+18
-0
mirai-core/src/main/java/net/mamoe/mirai/event/events/network/PacketEvent.java
...ava/net/mamoe/mirai/event/events/network/PacketEvent.java
+22
-0
mirai-core/src/main/java/net/mamoe/mirai/event/events/network/PacketSentEvent.java
...net/mamoe/mirai/event/events/network/PacketSentEvent.java
+15
-0
mirai-core/src/main/java/net/mamoe/mirai/event/events/network/ServerPacketEvent.java
...t/mamoe/mirai/event/events/network/ServerPacketEvent.java
+17
-0
mirai-core/src/main/java/net/mamoe/mirai/event/events/network/ServerPacketReceivedEvent.java
...mirai/event/events/network/ServerPacketReceivedEvent.java
+17
-0
mirai-core/src/main/java/net/mamoe/mirai/event/events/robot/RobotEvent.java
...n/java/net/mamoe/mirai/event/events/robot/RobotEvent.java
+1
-1
mirai-core/src/main/java/net/mamoe/mirai/event/events/robot/RobotEvents.kt
...in/java/net/mamoe/mirai/event/events/robot/RobotEvents.kt
+5
-6
mirai-core/src/main/java/net/mamoe/mirai/event/events/robot/RobotLoginSucceedEvent.java
...amoe/mirai/event/events/robot/RobotLoginSucceedEvent.java
+0
-1
mirai-core/src/main/java/net/mamoe/mirai/event/events/server/ServerDisableEvent.java
...t/mamoe/mirai/event/events/server/ServerDisableEvent.java
+0
-7
mirai-core/src/main/java/net/mamoe/mirai/event/events/server/ServerDisabledEvent.java
.../mamoe/mirai/event/events/server/ServerDisabledEvent.java
+8
-0
mirai-core/src/main/java/net/mamoe/mirai/event/events/server/ServerEnableEvent.java
...et/mamoe/mirai/event/events/server/ServerEnableEvent.java
+0
-8
mirai-core/src/main/java/net/mamoe/mirai/event/events/server/ServerEnabledEvent.java
...t/mamoe/mirai/event/events/server/ServerEnabledEvent.java
+9
-0
mirai-core/src/main/java/net/mamoe/mirai/message/Message.java
...i-core/src/main/java/net/mamoe/mirai/message/Message.java
+8
-1
mirai-core/src/main/java/net/mamoe/mirai/message/MessageKt.kt
...i-core/src/main/java/net/mamoe/mirai/message/MessageKt.kt
+5
-0
mirai-core/src/main/java/net/mamoe/mirai/message/defaults/At.java
...re/src/main/java/net/mamoe/mirai/message/defaults/At.java
+7
-4
mirai-core/src/main/java/net/mamoe/mirai/message/defaults/Face.java
.../src/main/java/net/mamoe/mirai/message/defaults/Face.java
+2
-0
mirai-core/src/main/java/net/mamoe/mirai/message/defaults/MessageChain.java
...n/java/net/mamoe/mirai/message/defaults/MessageChain.java
+3
-0
mirai-core/src/main/java/net/mamoe/mirai/network/Protocol.kt
mirai-core/src/main/java/net/mamoe/mirai/network/Protocol.kt
+67
-53
mirai-core/src/main/java/net/mamoe/mirai/network/RobotNetworkHandler.kt
.../main/java/net/mamoe/mirai/network/RobotNetworkHandler.kt
+449
-211
mirai-core/src/main/java/net/mamoe/mirai/network/packet/AccountInfo.kt
...c/main/java/net/mamoe/mirai/network/packet/AccountInfo.kt
+12
-13
mirai-core/src/main/java/net/mamoe/mirai/network/packet/ClientPacket.kt
.../main/java/net/mamoe/mirai/network/packet/ClientPacket.kt
+54
-48
mirai-core/src/main/java/net/mamoe/mirai/network/packet/Heartbeat.kt
...src/main/java/net/mamoe/mirai/network/packet/Heartbeat.kt
+2
-6
mirai-core/src/main/java/net/mamoe/mirai/network/packet/MessageEvent.kt
.../main/java/net/mamoe/mirai/network/packet/MessageEvent.kt
+0
-84
mirai-core/src/main/java/net/mamoe/mirai/network/packet/SKey.kt
...core/src/main/java/net/mamoe/mirai/network/packet/SKey.kt
+10
-16
mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerEvent.kt
...c/main/java/net/mamoe/mirai/network/packet/ServerEvent.kt
+78
-12
mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerPacket.kt
.../main/java/net/mamoe/mirai/network/packet/ServerPacket.kt
+50
-39
mirai-core/src/main/java/net/mamoe/mirai/network/packet/Session.kt
...e/src/main/java/net/mamoe/mirai/network/packet/Session.kt
+15
-23
mirai-core/src/main/java/net/mamoe/mirai/network/packet/Touch.kt
...ore/src/main/java/net/mamoe/mirai/network/packet/Touch.kt
+16
-27
mirai-core/src/main/java/net/mamoe/mirai/network/packet/VerificationCode.kt
...n/java/net/mamoe/mirai/network/packet/VerificationCode.kt
+103
-0
mirai-core/src/main/java/net/mamoe/mirai/network/packet/action/ClientSendFriendMessagePacket.kt
...ai/network/packet/action/ClientSendFriendMessagePacket.kt
+8
-11
mirai-core/src/main/java/net/mamoe/mirai/network/packet/action/ClientSendGroupMessagePacket.kt
...rai/network/packet/action/ClientSendGroupMessagePacket.kt
+7
-27
mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ClientChangeOnlineStatusPacket.kt
...ai/network/packet/login/ClientChangeOnlineStatusPacket.kt
+5
-3
mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ClientLogin.kt
.../java/net/mamoe/mirai/network/packet/login/ClientLogin.kt
+20
-19
mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ClientLoginVerificationCodePacket.kt
...network/packet/login/ClientLoginVerificationCodePacket.kt
+0
-41
mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/LoginState.kt
...n/java/net/mamoe/mirai/network/packet/login/LoginState.kt
+46
-0
mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponseFailedPacket.kt
...i/network/packet/login/ServerLoginResponseFailedPacket.kt
+1
-13
mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponsePasswordVerifiedPacket.kt
...packet/login/ServerLoginResponsePasswordVerifiedPacket.kt
+14
-91
mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponseResendPacket.kt
...i/network/packet/login/ServerLoginResponseResendPacket.kt
+4
-32
mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponseVerificationCodeInitPacket.kt
...et/login/ServerLoginResponseVerificationCodeInitPacket.kt
+70
-0
mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponseVerificationCodePacket.kt
...packet/login/ServerLoginResponseVerificationCodePacket.kt
+0
-42
mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginSuccessPacket.kt
...oe/mirai/network/packet/login/ServerLoginSuccessPacket.kt
+3
-5
mirai-core/src/main/java/net/mamoe/mirai/network/packet/verification/ServerVerificationCodePacket.kt
...twork/packet/verification/ServerVerificationCodePacket.kt
+0
-44
mirai-core/src/main/java/net/mamoe/mirai/plugin/MiraiPluginBase.java
...src/main/java/net/mamoe/mirai/plugin/MiraiPluginBase.java
+11
-1
mirai-core/src/main/java/net/mamoe/mirai/task/MiraiTaskExceptionHandler.java
.../java/net/mamoe/mirai/task/MiraiTaskExceptionHandler.java
+5
-8
mirai-core/src/main/java/net/mamoe/mirai/task/MiraiTaskManager.java
.../src/main/java/net/mamoe/mirai/task/MiraiTaskManager.java
+7
-7
mirai-core/src/main/java/net/mamoe/mirai/utils/ClientLoginStatus.java
...rc/main/java/net/mamoe/mirai/utils/ClientLoginStatus.java
+6
-2
mirai-core/src/main/java/net/mamoe/mirai/utils/ContactList.java
...core/src/main/java/net/mamoe/mirai/utils/ContactList.java
+1
-1
mirai-core/src/main/java/net/mamoe/mirai/utils/RobotAccount.java
...ore/src/main/java/net/mamoe/mirai/utils/RobotAccount.java
+17
-0
mirai-core/src/main/java/net/mamoe/mirai/utils/TEA.java
mirai-core/src/main/java/net/mamoe/mirai/utils/TEA.java
+28
-21
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
+27
-9
mirai-core/src/main/java/net/mamoe/mirai/utils/config/MiraiConfigSection.java
...java/net/mamoe/mirai/utils/config/MiraiConfigSection.java
+2
-2
mirai-core/src/main/java/net/mamoe/mirai/utils/setting/MiraiSettings.java
...ain/java/net/mamoe/mirai/utils/setting/MiraiSettings.java
+20
-12
mirai-core/src/test/java/BadQQFilter.kt
mirai-core/src/test/java/BadQQFilter.kt
+129
-0
mirai-core/src/test/java/HexComparator.java
mirai-core/src/test/java/HexComparator.java
+98
-35
mirai-core/src/test/java/TestKt.kt
mirai-core/src/test/java/TestKt.kt
+8
-0
No files found.
README.md
View file @
93dc8e58
...
@@ -15,23 +15,25 @@ The project is all for <b>learning proposes</b> and still in <b>developing stage
...
@@ -15,23 +15,25 @@ The project is all for <b>learning proposes</b> and still in <b>developing stage
### 代码结构
### 代码结构
Network部分使用 Kotlin 完成(因为kt有对 unsigned byte 的支持).
Network部分使用 Kotlin 完成(因为kt有对 unsigned byte 的支持).
与插件相关性强(或其他在二次开发中容易接触
的部分)均
使用 Java 完成,
与插件相关性强(或其他在二次开发中容易接触
)的部分
使用 Java 完成,
同时也会针对kotlin提供优化的方法调用. 例如对'+'操作符的重载:
`String+BufferedImage+QQ.At+Face+URL+String+File`
将会被自动处理为String消息.
同时也会针对kotlin提供优化的方法调用. 例如对'+'操作符的重载:
`String+BufferedImage+QQ.At+Face+URL+String+File`
将会被自动处理为String消息.
### TODO
### TODO
-
[x] 事件(Event)模块
-
[x] 事件(Event)模块
-
[ ] 插件(Plugin)模块
**(Working on)**
-
[ ] 插件(Plugin)模块
-
[x] Network - Touch
-
[x] Network - Touch
-
[X] Network - Login
-
[X] Network - Login
-
[X] Network - Session
-
[X] Network - Session
-
[ ] Network - Verification Code
(Low priority)
-
[ ] Network - Verification Code
**(Working on)**
-
[X] Network - Message Receiving
-
[X] Network - Message Receiving
-
[X] Network - Message Sending
-
[X] Network - Message Sending
-
[ ] Network - Events
**(Working on)**
-
[ ] Network - Events
**(Working on)**
-
[ ] Robot - Friend/group list
-
[ ] Robot - Friend/group list
-
[ ] Robot - Actions(joining group, adding friend, etc.)
-
[ ] Message Section
**(Working on)**
-
[ ] Message Section
**(Working on)**
-
[ ] Contact
-
[ ] Contact
-
[ ] UI
**(Working on)**
<br>
<br>
...
...
mirai-core/pom.xml
View file @
93dc8e58
...
@@ -56,6 +56,12 @@
...
@@ -56,6 +56,12 @@
<artifactId>
snakeyaml
</artifactId>
<artifactId>
snakeyaml
</artifactId>
<version>
1.18
</version>
<version>
1.18
</version>
</dependency>
</dependency>
<dependency>
<groupId>
org.jetbrains.kotlin
</groupId>
<artifactId>
kotlin-reflect
</artifactId>
<version>
1.3.41
</version>
<scope>
compile
</scope>
</dependency>
</dependencies>
</dependencies>
...
...
mirai-core/src/main/java/net/mamoe/mirai/MiraiMain.java
View file @
93dc8e58
package
net.mamoe.mirai
;
package
net.mamoe.mirai
;
import
net.mamoe.mirai.utils.config.MiraiConfig
;
import
net.mamoe.mirai.utils.config.MiraiConfigSection
;
/**
/**
* @author Him188moe
* @author Him188moe
*/
*/
public
final
class
MiraiMain
{
public
final
class
MiraiMain
{
private
static
MiraiServer
server
;
private
static
MiraiServer
server
;
public
static
void
main
(
String
[]
args
)
{
public
static
void
main
(
String
[]
args
)
{
server
=
new
MiraiServer
();
server
=
new
MiraiServer
();
Runtime
.
getRuntime
().
addShutdownHook
(
new
Thread
(()
->
{
Runtime
.
getRuntime
().
addShutdownHook
(
new
Thread
(()
->
server
.
shutdown
()));
server
.
shutdown
();
}));
MiraiConfig
config
=
new
MiraiConfig
(
"QQ.yml"
);
MiraiConfigSection
<
Object
>
data
=
config
.
getSection
(
"123123"
);
data
.
put
(
"account"
,
"123123a"
);
try
{
Robot
robot
=
new
Robot
(
data
);
}
catch
(
Throwable
throwable
)
{
throwable
.
printStackTrace
();
}
}
}
}
}
mirai-core/src/main/java/net/mamoe/mirai/MiraiServer.java
View file @
93dc8e58
...
@@ -2,24 +2,25 @@ package net.mamoe.mirai;
...
@@ -2,24 +2,25 @@ package net.mamoe.mirai;
import
lombok.Getter
;
import
lombok.Getter
;
import
net.mamoe.mirai.event.MiraiEventManager
;
import
net.mamoe.mirai.event.MiraiEventManager
;
import
net.mamoe.mirai.event.events.server.ServerDisableEvent
;
import
net.mamoe.mirai.event.events.server.ServerDisabledEvent
;
import
net.mamoe.mirai.event.events.server.ServerEnableEvent
;
import
net.mamoe.mirai.event.events.server.ServerEnabledEvent
;
import
net.mamoe.mirai.network.RobotNetworkHandler
;
import
net.mamoe.mirai.network.packet.login.LoginState
;
import
net.mamoe.mirai.network.packet.ClientTouchPacket
;
import
net.mamoe.mirai.task.MiraiTaskManager
;
import
net.mamoe.mirai.task.MiraiTaskManager
;
import
net.mamoe.mirai.utils.LoggerTextFormat
;
import
net.mamoe.mirai.utils.LoggerTextFormat
;
import
net.mamoe.mirai.utils.MiraiLogger
;
import
net.mamoe.mirai.utils.MiraiLogger
;
import
net.mamoe.mirai.utils.config.MiraiConfig
;
import
net.mamoe.mirai.utils.config.MiraiConfig
;
import
net.mamoe.mirai.utils.config.MiraiConfigSection
;
import
net.mamoe.mirai.utils.config.MiraiConfigSection
;
import
net.mamoe.mirai.utils.setting.MiraiSetting
;
import
net.mamoe.mirai.utils.setting.MiraiSettingListSection
;
import
net.mamoe.mirai.utils.setting.MiraiSettingListSection
;
import
net.mamoe.mirai.utils.setting.MiraiSettingMapSection
;
import
net.mamoe.mirai.utils.setting.MiraiSettingMapSection
;
import
net.mamoe.mirai.utils.setting.MiraiSettings
;
import
java.io.File
;
import
java.io.File
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.util.LinkedList
;
import
java.util.Scanner
;
import
java.util.Scanner
;
/**
* @author NaturalHG
*/
public
class
MiraiServer
{
public
class
MiraiServer
{
private
static
MiraiServer
instance
;
private
static
MiraiServer
instance
;
...
@@ -27,17 +28,15 @@ public class MiraiServer {
...
@@ -27,17 +28,15 @@ public class MiraiServer {
return
instance
;
return
instance
;
}
}
//mirai version
private
final
static
String
MIRAI_VERSION
=
"1.0.0"
;
private
final
static
String
MIRAI_VERSION
=
"1.0.0"
;
//qq version
private
final
static
String
QQ_VERSION
=
"4.9.0"
;
private
final
static
String
QQ_VERSION
=
"4.9.0"
;
@Getter
//is running under UNIX
@Getter
//is running under UNIX
private
boolean
unix
;
private
boolean
unix
;
@Getter
//file path
@Getter
//file path
q
public
File
parentFolder
;
public
File
parentFolder
;
@Getter
@Getter
...
@@ -48,30 +47,30 @@ public class MiraiServer {
...
@@ -48,30 +47,30 @@ public class MiraiServer {
@Getter
@Getter
MiraiLogger
logger
;
MiraiLogger
logger
;
MiraiSetting
setting
;
MiraiSetting
s
settings
;
MiraiConfig
qqs
;
MiraiConfig
qqs
;
protected
MiraiServer
()
{
MiraiServer
()
{
instance
=
this
;
instance
=
this
;
this
.
onLoad
();
this
.
onLoad
ed
();
this
.
onEnable
();
this
.
onEnable
d
();
}
}
private
boolean
enabled
;
private
boolean
enabled
;
protected
void
shutdown
()
{
void
shutdown
()
{
if
(
this
.
enabled
)
{
if
(
this
.
enabled
)
{
getLogger
().
info
(
"About to shutdown Mirai"
);
getLogger
().
info
(
"About to shutdown Mirai"
);
this
.
getEventManager
().
broadcastEvent
(
new
ServerDisable
Event
());
this
.
eventManager
.
broadcastEventAsync
(
new
ServerDisabled
Event
());
getLogger
().
info
(
"Data have been saved"
);
getLogger
().
info
(
"Data have been saved"
);
}
}
}
}
private
void
onLoad
()
{
private
void
onLoad
ed
()
{
this
.
parentFolder
=
new
File
(
System
.
getProperty
(
"user.dir"
));
this
.
parentFolder
=
new
File
(
System
.
getProperty
(
"user.dir"
));
this
.
unix
=
!
System
.
getProperties
().
getProperty
(
"os.name"
).
toUpperCase
().
contains
(
"WINDOWS"
);
this
.
unix
=
!
System
.
getProperties
().
getProperty
(
"os.name"
).
toUpperCase
().
contains
(
"WINDOWS"
);
...
@@ -88,7 +87,7 @@ public class MiraiServer {
...
@@ -88,7 +87,7 @@ public class MiraiServer {
if
(!
setting
.
exists
())
{
if
(!
setting
.
exists
())
{
this
.
initSetting
(
setting
);
this
.
initSetting
(
setting
);
}
else
{
}
else
{
this
.
setting
=
new
MiraiSetting
(
setting
);
this
.
setting
s
=
new
MiraiSettings
(
setting
);
}
}
File
qqs
=
new
File
(
this
.
parentFolder
+
"/QQ.yml"
);
File
qqs
=
new
File
(
this
.
parentFolder
+
"/QQ.yml"
);
...
@@ -116,65 +115,6 @@ public class MiraiServer {
...
@@ -116,65 +115,6 @@ public class MiraiServer {
});
});
*/
*/
getLogger
().
info
(
"ready to connect"
);
/*
MiraiConfigSection section = new MiraiConfigSection<MiraiConfigSection<String>>(){{
put("1",new MiraiConfigSection<>(){{
put("1","0");
}});
}};
this.qqs.put("test",section);
this.qqs.save();
*/
MiraiConfigSection
<
MiraiConfigSection
>
x
=
this
.
qqs
.
getTypedSection
(
"test"
);
//System.out.println(x.getSection("1").getInt("1"));
/*
System.out.println(v);
System.out.println(v.get("1111"));
*/
Robot
robot
=
new
Robot
(
1994701021
,
"xiaoqqq"
,
new
LinkedList
<>());
RobotNetworkHandler
robotNetworkHandler
=
robot
.
getHandler
();
try
{
//System.out.println(Protocol.Companion.getSERVER_IP().get(3));
//System.out.println(Protocol.Companion.getSERVER_IP().toString());
robotNetworkHandler
.
setServerIP
(
"14.116.136.106"
);
robotNetworkHandler
.
sendPacket
(
new
ClientTouchPacket
(
1994701021
,
"14.116.136.106"
));
while
(
true
)
;
//robotNetworkHandler.connect("14.116.136.106");
//robotNetworkHandler.connect(Protocol.Companion.getSERVER_IP().get(2));
//robotNetworkHandler.connect("125.39.132.242");
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
System
.
exit
(
1
);
}
/*
System.out.println("network test");
try {
MiraiUDPServer server = new MiraiUDPServer();
MiraiUDPClient client = new MiraiUDPClient(InetAddress.getLocalHost(),9999,MiraiNetwork.getAvailablePort());
this.getTaskManager().repeatingTask(() -> {
byte[] sendInfo = "test test".getBytes(StandardCharsets.UTF_8);
try {
client.send(new DatagramPacket(sendInfo,sendInfo.length));
} catch (IOException e) {
e.printStackTrace();
}
},300);
} catch (IOException e) {
e.printStackTrace();
}*/
}
}
private
void
initSetting
(
File
setting
)
{
private
void
initSetting
(
File
setting
)
{
...
@@ -187,21 +127,21 @@ public class MiraiServer {
...
@@ -187,21 +127,21 @@ public class MiraiServer {
}
catch
(
IOException
e
)
{
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
e
.
printStackTrace
();
}
}
this
.
setting
=
new
MiraiSetting
(
setting
);
this
.
setting
s
=
new
MiraiSettings
(
setting
);
MiraiSettingMapSection
network
=
this
.
setting
.
getMapSection
(
"network"
);
MiraiSettingMapSection
network
=
this
.
setting
s
.
getMapSection
(
"network"
);
network
.
set
(
"enable_proxy"
,
"not supporting yet"
);
network
.
set
(
"enable_proxy"
,
"not supporting yet"
);
MiraiSettingListSection
proxy
=
this
.
setting
.
getListSection
(
"proxy"
);
MiraiSettingListSection
proxy
=
this
.
setting
s
.
getListSection
(
"proxy"
);
proxy
.
add
(
"1.2.3.4:95"
);
proxy
.
add
(
"1.2.3.4:95"
);
proxy
.
add
(
"1.2.3.4:100"
);
proxy
.
add
(
"1.2.3.4:100"
);
MiraiSettingMapSection
worker
=
this
.
setting
.
getMapSection
(
"worker"
);
MiraiSettingMapSection
worker
=
this
.
setting
s
.
getMapSection
(
"worker"
);
worker
.
set
(
"core_task_pool_worker_amount"
,
5
);
worker
.
set
(
"core_task_pool_worker_amount"
,
5
);
MiraiSettingMapSection
plugin
=
this
.
setting
.
getMapSection
(
"plugin"
);
MiraiSettingMapSection
plugin
=
this
.
setting
s
.
getMapSection
(
"plugin"
);
plugin
.
set
(
"debug"
,
false
);
plugin
.
set
(
"debug"
,
false
);
this
.
setting
.
save
();
this
.
setting
s
.
save
();
getLogger
().
info
(
"initialized; changing can be made in setting file: "
+
setting
.
toString
());
getLogger
().
info
(
"initialized; changing can be made in setting file: "
+
setting
.
toString
());
}
}
...
@@ -227,11 +167,35 @@ public class MiraiServer {
...
@@ -227,11 +167,35 @@ public class MiraiServer {
getLogger
().
info
(
"QQ account initialized; changing can be made in Config file: "
+
qqConfig
.
toString
());
getLogger
().
info
(
"QQ account initialized; changing can be made in Config file: "
+
qqConfig
.
toString
());
}
}
private
void
onEnable
()
{
private
void
onEnabled
()
{
this
.
eventManager
.
broadcastEvent
(
new
ServerEnableEvent
());
this
.
enabled
=
true
;
this
.
enabled
=
true
;
this
.
eventManager
.
broadcastEventAsync
(
new
ServerEnabledEvent
());
getLogger
().
info
(
LoggerTextFormat
.
GREEN
+
"Server enabled; Welcome to Mirai"
);
getLogger
().
info
(
LoggerTextFormat
.
GREEN
+
"Server enabled; Welcome to Mirai"
);
getLogger
().
info
(
"Mirai Version="
+
MiraiServer
.
MIRAI_VERSION
+
" QQ Version="
+
MiraiServer
.
QQ_VERSION
);
getLogger
().
info
(
"Mirai Version="
+
MiraiServer
.
MIRAI_VERSION
+
" QQ Version="
+
MiraiServer
.
QQ_VERSION
);
getLogger
().
info
(
"Initializing [Robot]s"
);
this
.
qqs
.
keySet
().
stream
().
map
(
key
->
this
.
qqs
.
getSection
(
key
)).
forEach
(
section
->
{
getLogger
().
info
(
"Initializing [Robot] "
+
section
.
getString
(
"account"
));
try
{
Robot
robot
=
new
Robot
(
section
);
var
state
=
robot
.
network
.
tryLogin
$mirai_core
().
get
();
//robot.network.tryLogin$mirai_core().whenComplete((state, e) -> {
if
(
state
==
LoginState
.
SUCCEED
)
{
Robot
.
instances
.
add
(
robot
);
getLogger
().
info
(
" Succeed"
);
}
else
{
getLogger
().
error
(
" Failed with error "
+
state
);
robot
.
close
();
}
// }).get();
}
catch
(
Throwable
e
)
{
e
.
printStackTrace
();
getLogger
().
error
(
"Could not load QQ robots config!"
);
System
.
exit
(
1
);
}
});
}
}
...
...
mirai-core/src/main/java/net/mamoe/mirai/Robot.java
View file @
93dc8e58
package
net.mamoe.mirai
;
package
net.mamoe.mirai
;
import
kotlin.jvm.internal.MagicApiIntrinsics
;
import
lombok.Getter
;
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.RobotNetworkHandler
;
import
net.mamoe.mirai.network.RobotNetworkHandler
;
import
net.mamoe.mirai.utils.ContactList
;
import
net.mamoe.mirai.utils.ContactList
;
import
net.mamoe.mirai.utils.
config.MiraiConfig
;
import
net.mamoe.mirai.utils.
RobotAccount
;
import
net.mamoe.mirai.utils.config.MiraiConfigSection
;
import
net.mamoe.mirai.utils.config.MiraiConfigSection
;
import
org.jetbrains.annotations.NotNull
;
import
java.io.Closeable
;
import
java.util.*
;
/**
* Mirai 的机器人. 一个机器人实例登录一个 QQ 账号.
* Mirai 为多账号设计, 可同时维护多个机器人账号.
* <br>
* {@link Robot} 由 2 个模块组成.
* {@linkplain ContactSystem 联系人管理}: 可通过 {@link Robot#contacts} 访问
* {@linkplain RobotNetworkHandler 网络处理器}: 可通过 {@link Robot#network} 访问
* <br>
* 另外地, 若你需要得到机器人的 QQ 账号, 请访问 {@link Robot#account}
* 若你需要得到服务器上所有机器人列表, 请访问 {@link Robot#instances}
*
* @author Him188moe
* @author NatrualHG
* @see net.mamoe.mirai.contact.Contact
*
* <p>
* Robot that is the base of the whole program.
* It contains a {@link ContactSystem}, which manage contacts such as {@link QQ} and {@link Group}.
*/
public
final
class
Robot
implements
Closeable
{
public
static
final
List
<
Robot
>
instances
=
Collections
.
synchronizedList
(
new
LinkedList
<>());
public
final
RobotAccount
account
;
public
final
ContactSystem
contacts
=
new
ContactSystem
();
public
final
RobotNetworkHandler
network
;
import
java.util.ArrayList
;
/**
import
java.util.Collections
;
* Robot 联系人管理.
import
java.util.List
;
*
* @see Robot#contacts
*/
public
final
class
ContactSystem
{
private
final
ContactList
<
Group
>
groups
=
new
ContactList
<>();
private
final
ContactList
<
QQ
>
qqs
=
new
ContactList
<>();
public
class
Robot
{
private
ContactSystem
()
{
}
public
QQ
getQQ
(
long
qqNumber
)
{
if
(!
this
.
qqs
.
containsKey
(
qqNumber
))
{
this
.
qqs
.
put
(
qqNumber
,
new
QQ
(
Robot
.
this
,
qqNumber
));
}
return
this
.
qqs
.
get
(
qqNumber
);
}
public
Group
getGroupByNumber
(
long
groupNumber
)
{
if
(!
this
.
groups
.
containsKey
(
groupNumber
))
{
this
.
groups
.
put
(
groupNumber
,
new
Group
(
Robot
.
this
,
groupNumber
));
}
return
groups
.
get
(
groupNumber
);
}
public
Group
getGroupById
(
long
groupId
)
{
return
getGroupByNumber
(
Group
.
Companion
.
groupIdToNumber
(
groupId
));
}
}
private
final
int
qqNumber
;
private
final
String
password
;
@Getter
private
final
RobotNetworkHandler
handler
;
/**
/**
* Ref list
* Ref list
...
@@ -26,66 +79,35 @@ public class Robot {
...
@@ -26,66 +79,35 @@ public class Robot {
@Getter
@Getter
private
final
List
<
String
>
owners
;
private
final
List
<
String
>
owners
;
private
final
ContactList
<
Group
>
groups
=
new
ContactList
<>();
private
final
ContactList
<
QQ
>
qqs
=
new
ContactList
<>();
public
boolean
isOwnBy
(
String
ownerName
)
{
public
boolean
isOwnBy
(
String
ownerName
)
{
return
owners
.
contains
(
ownerName
);
return
owners
.
contains
(
ownerName
);
}
}
public
Robot
(
MiraiConfigSection
<
Object
>
data
)
throws
Throwable
{
public
Robot
(
MiraiConfigSection
<
Object
>
data
)
throws
Throwable
{
this
(
this
(
data
.
getIntOrThrow
(
"account"
,
()
->
new
IllegalArgumentException
(
"account"
)),
new
RobotAccount
(
data
.
getStringOrThrow
(
"password"
,
()
->
new
IllegalArgumentException
(
"password"
)),
data
.
getLongOrThrow
(
"account"
,
()
->
new
IllegalArgumentException
(
"account"
)),
data
.
getStringOrThrow
(
"password"
,
()
->
new
IllegalArgumentException
(
"password"
))
),
data
.
getAsOrDefault
(
"owners"
,
ArrayList:
:
new
)
data
.
getAsOrDefault
(
"owners"
,
ArrayList:
:
new
)
);
);
}
}
public
Robot
(
int
qqNumber
,
String
password
,
List
<
String
>
owners
)
{
public
Robot
(
@NotNull
RobotAccount
account
,
@NotNull
List
<
String
>
owners
)
{
this
.
qqNumber
=
qqNumber
;
Objects
.
requireNonNull
(
account
);
this
.
password
=
password
;
Objects
.
requireNonNull
(
owners
);
this
.
account
=
account
;
this
.
owners
=
Collections
.
unmodifiableList
(
owners
);
this
.
owners
=
Collections
.
unmodifiableList
(
owners
);
this
.
handler
=
new
RobotNetworkHandler
(
this
,
this
.
qqNumber
,
this
.
password
);
this
.
network
=
new
RobotNetworkHandler
(
this
);
}
public
QQ
getQQ
(
int
qqNumber
)
{
if
(!
this
.
qqs
.
containsKey
(
qqNumber
))
{
this
.
qqs
.
put
(
qqNumber
,
new
QQ
(
qqNumber
));
}
return
this
.
qqs
.
get
(
qqNumber
);
}
public
Group
getGroup
(
int
groupNumber
)
{
if
(!
this
.
groups
.
containsKey
(
groupNumber
))
{
this
.
groups
.
put
(
groupNumber
,
new
Group
(
groupNumber
));
}
return
groups
.
get
(
groupNumber
);
}
}
public
Group
getGroupByGroupId
(
int
groupId
)
{
return
getGroup
(
Group
.
Companion
.
groupIdToNumber
(
groupId
));
}
/* Attribute
* Attribute will be SAVED and LOAD automatically as long as the QQ account is same
* {Attributes} is in the format of Map<String, Object>, keeping thread-safe
* {Attributes} is a KEY-VALUE typed Data.
* *
**/
}
/*
class RobotAttribute extends MiraiConfigSection<Object>{
static RobotAttribute load(Robot robot){
public
void
close
()
{
this
.
network
.
close
();
this
.
contacts
.
groups
.
values
().
forEach
(
Group:
:
close
);
this
.
contacts
.
groups
.
clear
();
this
.
contacts
.
qqs
.
clear
();
}
}
private MiraiConfigSection<Object> data;//late init
}
}
*/
mirai-core/src/main/java/net/mamoe/mirai/contact/Contact.kt
View file @
93dc8e58
package
net.mamoe.mirai.contact
package
net.mamoe.mirai.contact
import
net.mamoe.mirai.Robot
import
net.mamoe.mirai.message.Message
import
net.mamoe.mirai.message.Message
import
net.mamoe.mirai.message.defaults.PlainText
import
net.mamoe.mirai.message.defaults.PlainText
/**
/**
* A contact is a [QQ] or a [Group] for one particular [Robot] instance only.
* A contact is a [QQ] or a [Group] for one particular [Robot] instance only.
*
*
* @param robot Owner [Robot]
* @author Him188moe
* @author Him188moe
*/
*/
abstract
class
Contact
(
val
number
:
Int
)
{
abstract
class
Contact
(
val
robot
:
Robot
,
val
number
:
Long
)
{
/**
/**
* Async
* Async
...
...
mirai-core/src/main/java/net/mamoe/mirai/contact/Group.kt
View file @
93dc8e58
package
net.mamoe.mirai.contact
package
net.mamoe.mirai.contact
import
net.mamoe.mirai.Robot
import
net.mamoe.mirai.message.Message
import
net.mamoe.mirai.message.Message
import
net.mamoe.mirai.utils.ContactList
import
net.mamoe.mirai.utils.ContactList
import
java.io.Closeable
class
Group
(
number
:
Int
)
:
Contact
(
number
)
{
class
Group
(
robot
:
Robot
,
number
:
Long
)
:
Contact
(
robot
,
number
),
Closeable
{
val
groupId
=
groupNumberToId
(
number
)
val
groupId
=
groupNumberToId
(
number
)
val
members
=
ContactList
<
QQ
>()
val
members
=
ContactList
<
QQ
>()
init
{
Instances
.
groups
.
add
(
this
)
}
override
fun
sendMessage
(
message
:
Message
)
{
override
fun
sendMessage
(
message
:
Message
)
{
robot
.
network
.
messageHandler
.
sendGroupMessage
(
this
,
message
)
}
}
override
fun
sendXMLMessage
(
message
:
String
)
{
override
fun
sendXMLMessage
(
message
:
String
)
{
}
}
override
fun
close
()
{
this
.
members
.
clear
()
}
companion
object
{
companion
object
{
fun
groupNumberToId
(
number
:
Int
):
Int
{
fun
groupNumberToId
(
number
:
Long
):
Long
{
val
left
:
Int
=
number
.
toString
().
let
{
val
left
:
Long
=
number
.
toString
().
let
{
if
(
it
.
length
<
6
)
{
if
(
it
.
length
<
6
)
{
return
@
groupNumberToId
number
return
@
groupNumberToId
number
}
}
it
.
substring
(
0
,
it
.
length
-
6
).
to
Int
()
it
.
substring
(
0
,
it
.
length
-
6
).
to
Long
()
}
}
val
right
:
Int
=
number
.
toString
().
let
{
val
right
:
Long
=
number
.
toString
().
let
{
it
.
substring
(
it
.
length
-
6
).
to
Int
()
it
.
substring
(
it
.
length
-
6
).
to
Long
()
}
}
return
when
(
left
)
{
return
when
(
left
)
{
in
1
..
10
->
{
in
1
..
10
->
{
((
left
+
202
).
toString
()
+
right
.
toString
()).
to
Int
()
((
left
+
202
).
toString
()
+
right
.
toString
()).
to
Long
()
}
}
in
11
..
19
->
{
in
11
..
19
->
{
((
left
+
469
).
toString
()
+
right
.
toString
()).
to
Int
()
((
left
+
469
).
toString
()
+
right
.
toString
()).
to
Long
()
}
}
in
20
..
66
->
{
in
20
..
66
->
{
((
left
+
208
).
toString
()
+
right
.
toString
()).
to
Int
()
((
left
+
208
).
toString
()
+
right
.
toString
()).
to
Long
()
}
}
in
67
..
156
->
{
in
67
..
156
->
{
((
left
+
1943
).
toString
()
+
right
.
toString
()).
to
Int
()
((
left
+
1943
).
toString
()
+
right
.
toString
()).
to
Long
()
}
}
in
157
..
209
->
{
in
157
..
209
->
{
((
left
+
199
).
toString
()
+
right
.
toString
()).
to
Int
()
((
left
+
199
).
toString
()
+
right
.
toString
()).
to
Long
()
}
}
in
210
..
309
->
{
in
210
..
309
->
{
((
left
+
389
).
toString
()
+
right
.
toString
()).
to
Int
()
((
left
+
389
).
toString
()
+
right
.
toString
()).
to
Long
()
}
}
in
310
..
499
->
{
in
310
..
499
->
{
((
left
+
349
).
toString
()
+
right
.
toString
()).
to
Int
()
((
left
+
349
).
toString
()
+
right
.
toString
()).
to
Long
()
}
}
else
->
number
else
->
number
}
}
}
}
@JvmStatic
fun
groupIdToNumber
(
id
:
Long
):
Long
{
fun
main
(
args
:
Array
<
String
>)
{
var
left
:
Long
=
id
.
toString
().
let
{
groupNumberToId
(
580266363
)
}
fun
groupIdToNumber
(
id
:
Int
):
Int
{
var
left
:
Int
=
id
.
toString
().
let
{
if
(
it
.
length
<
6
)
{
if
(
it
.
length
<
6
)
{
return
@
groupIdToNumber
id
return
@
groupIdToNumber
id
}
}
it
.
substring
(
0
until
it
.
length
-
6
).
to
Int
()
it
.
substring
(
0
until
it
.
length
-
6
).
to
Long
()
}
}
return
when
(
left
)
{
return
when
(
left
)
{
in
203
..
212
->
{
in
203
..
212
->
{
val
right
:
Int
=
id
.
toString
().
let
{
val
right
:
Long
=
id
.
toString
().
let
{
it
.
substring
(
it
.
length
-
6
).
to
Int
()
it
.
substring
(
it
.
length
-
6
).
to
Long
()
}
}
((
left
-
202
).
toString
()
+
right
.
toString
()).
to
Int
()
((
left
-
202
).
toString
()
+
right
.
toString
()).
to
Long
()
}
}
in
480
..
488
->
{
in
480
..
488
->
{
val
right
:
Int
=
id
.
toString
().
let
{
val
right
:
Long
=
id
.
toString
().
let
{
it
.
substring
(
it
.
length
-
6
).
to
Int
()
it
.
substring
(
it
.
length
-
6
).
to
Long
()
}
}
((
left
-
469
).
toString
()
+
right
.
toString
()).
to
Int
()
((
left
-
469
).
toString
()
+
right
.
toString
()).
to
Long
()
}
}
in
2100
..
2146
->
{
in
2100
..
2146
->
{
val
right
:
Int
=
id
.
toString
().
let
{
val
right
:
Long
=
id
.
toString
().
let
{
it
.
substring
(
it
.
length
-
7
).
to
Int
()
it
.
substring
(
it
.
length
-
7
).
to
Long
()
}
}
left
=
left
.
toString
().
substring
(
0
until
3
).
to
Int
()
left
=
left
.
toString
().
substring
(
0
until
3
).
to
Long
()
((
left
-
208
).
toString
()
+
right
.
toString
()).
to
Int
()
((
left
-
208
).
toString
()
+
right
.
toString
()).
to
Long
()
}
}
in
2010
..
2099
->
{
in
2010
..
2099
->
{
val
right
:
Int
=
id
.
toString
().
let
{
val
right
:
Long
=
id
.
toString
().
let
{
it
.
substring
(
it
.
length
-
6
).
to
Int
()
it
.
substring
(
it
.
length
-
6
).
to
Long
()
}
}
((
left
-
1943
).
toString
()
+
right
.
toString
()).
to
Int
()
((
left
-
1943
).
toString
()
+
right
.
toString
()).
to
Long
()
}
}
in
2147
..
2199
->
{
in
2147
..
2199
->
{
val
right
:
Int
=
id
.
toString
().
let
{
val
right
:
Long
=
id
.
toString
().
let
{
it
.
substring
(
it
.
length
-
7
).
to
Int
()
it
.
substring
(
it
.
length
-
7
).
to
Long
()
}
}
left
=
left
.
toString
().
substring
(
0
until
3
).
to
Int
()
left
=
left
.
toString
().
substring
(
0
until
3
).
to
Long
()
((
left
-
199
).
toString
()
+
right
.
toString
()).
to
Int
()
((
left
-
199
).
toString
()
+
right
.
toString
()).
to
Long
()
}
}
in
4100
..
4199
->
{
in
4100
..
4199
->
{
val
right
:
Int
=
id
.
toString
().
let
{
val
right
:
Long
=
id
.
toString
().
let
{
it
.
substring
(
it
.
length
-
7
).
to
Int
()
it
.
substring
(
it
.
length
-
7
).
to
Long
()
}
}
left
=
left
.
toString
().
substring
(
0
until
3
).
to
Int
()
left
=
left
.
toString
().
substring
(
0
until
3
).
to
Long
()
((
left
-
389
).
toString
()
+
right
.
toString
()).
to
Int
()
((
left
-
389
).
toString
()
+
right
.
toString
()).
to
Long
()
}
}
in
3800
..
3989
->
{
in
3800
..
3989
->
{
val
right
:
Int
=
id
.
toString
().
let
{
val
right
:
Long
=
id
.
toString
().
let
{
it
.
substring
(
it
.
length
-
7
).
to
Int
()
it
.
substring
(
it
.
length
-
7
).
to
Long
()
}
}
left
=
left
.
toString
().
substring
(
0
until
3
).
to
Int
()
left
=
left
.
toString
().
substring
(
0
until
3
).
to
Long
()
((
left
-
349
).
toString
()
+
right
.
toString
()).
to
Int
()
((
left
-
349
).
toString
()
+
right
.
toString
()).
to
Long
()
}
}
else
->
id
else
->
id
}
}
...
...
mirai-core/src/main/java/net/mamoe/mirai/contact/Lazy.kt
deleted
100644 → 0
View file @
5b07f09d
package
net.mamoe.mirai.contact
fun
Int
.
asQQ
():
QQ
=
Instances
.
qqs
.
stream
().
filter
{
t
:
QQ
?
->
t
?.
number
?.
equals
(
this
)
!!
}.
findAny
().
orElse
(
QQ
(
this
))
!!
fun
Int
.
asGroup
():
Group
=
Instances
.
groups
.
stream
().
filter
{
t
:
Group
?
->
t
?.
number
?.
equals
(
this
)
!!
}.
findAny
().
orElse
(
Group
(
this
))
!!
fun
String
.
withImage
(
id
:
String
,
type
:
String
)
=
"{$id}.$type"
fun
String
.
withAt
(
qq
:
Int
)
=
qq
.
asQQ
().
at
()
fun
String
.
withAt
(
qq
:
QQ
)
=
qq
.
at
()
object
Instances
{
var
qqs
=
arrayListOf
<
QQ
>()
var
groups
=
arrayListOf
<
Group
>()
}
mirai-core/src/main/java/net/mamoe/mirai/contact/QQ.kt
View file @
93dc8e58
package
net.mamoe.mirai.contact
package
net.mamoe.mirai.contact
import
net.mamoe.mirai.Robot
import
net.mamoe.mirai.message.Message
import
net.mamoe.mirai.message.Message
import
net.mamoe.mirai.message.defaults.At
import
net.mamoe.mirai.message.defaults.At
/**
/**
* QQ 账号.
* 注意: 一个 [QQ] 实例并不是独立的, 它属于一个 [Robot].
*
* A QQ instance helps you to receive message from or send message to.
* Notice that, one QQ instance belong to one [Robot], that is, QQ instances from different [Robot] are NOT the same.
*
* @author Him188moe
* @author Him188moe
*/
*/
class
QQ
(
number
:
Int
)
:
Contact
(
number
)
{
class
QQ
(
robot
:
Robot
,
number
:
Long
)
:
Contact
(
robot
,
number
)
{
init
{
Instances
.
qqs
.
add
(
this
)
}
override
fun
sendMessage
(
message
:
Message
)
{
override
fun
sendMessage
(
message
:
Message
)
{
robot
.
network
.
messageHandler
.
sendFriendMessage
(
this
,
message
)
}
}
override
fun
sendXMLMessage
(
message
:
String
)
{
override
fun
sendXMLMessage
(
message
:
String
)
{
...
@@ -21,6 +24,8 @@ class QQ(number: Int) : Contact(number) {
...
@@ -21,6 +24,8 @@ class QQ(number: Int) : Contact(number) {
/**
/**
* At(@) this account.
* At(@) this account.
*
* @return an instance of [Message].
*/
*/
fun
at
():
At
{
fun
at
():
At
{
return
At
(
this
)
return
At
(
this
)
...
...
mirai-core/src/main/java/net/mamoe/mirai/event/AsyncEvent.java
0 → 100644
View file @
93dc8e58
package
net.mamoe.mirai.event
;
import
java.util.concurrent.CompletableFuture
;
import
java.util.function.Consumer
;
/**
* 实现这个接口的事件可以被异步执行或阻塞执行
*
* @author Him188moe
* @see AsyncEventKt 若你使用 kotlin, 请查看针对 kotlin 的优化实现
*/
public
interface
AsyncEvent
{
default
CompletableFuture
<?
extends
AsyncEvent
>
broadcastAsync
()
{
return
MiraiEventManager
.
getInstance
().
broadcastEventAsync
(
this
);
}
@SuppressWarnings
(
"unchecked"
)
default
<
E
extends
AsyncEvent
>
CompletableFuture
<
E
>
broadcastEventAsync
(
Consumer
<
E
>
callback
)
{
return
MiraiEventManager
.
getInstance
().
broadcastEventAsync
((
E
)
this
,
callback
);
}
@SuppressWarnings
(
"unchecked"
)
default
<
E
extends
AsyncEvent
>
CompletableFuture
<
E
>
broadcastEventAsync
(
Runnable
callback
)
{
return
MiraiEventManager
.
getInstance
().
broadcastEventAsync
((
E
)
this
,
callback
);
}
}
mirai-core/src/main/java/net/mamoe/mirai/event/AsyncEventKt.kt
0 → 100644
View file @
93dc8e58
@
file
:
JvmName
(
"AsyncEventKt"
)
package
net.mamoe.mirai.event
import
java.util.concurrent.CompletableFuture
import
java.util.function.Consumer
fun
<
E
:
AsyncEvent
>
E
.
broadcastAsync
(
callback
:
Consumer
<
E
>):
CompletableFuture
<
E
>
{
return
MiraiEventManager
.
getInstance
().
broadcastEventAsync
(
this
,
callback
)
}
fun
<
E
:
AsyncEvent
>
E
.
broadcastAsync
(
callback
:
Runnable
):
CompletableFuture
<
E
>
{
return
MiraiEventManager
.
getInstance
().
broadcastEventAsync
(
this
,
callback
)
}
fun
<
E
:
AsyncEvent
>
E
.
broadcastAsyncSmart
():
CompletableFuture
<
E
>
{
return
MiraiEventManager
.
getInstance
().
broadcastEventAsync
(
this
)
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/event/
events/
Cancellable.java
→
mirai-core/src/main/java/net/mamoe/mirai/event/Cancellable.java
View file @
93dc8e58
package
net.mamoe.mirai.event
.events
;
package
net.mamoe.mirai.event
;
/**
/**
* @author NaturalHG
* @author NaturalHG
...
...
mirai-core/src/main/java/net/mamoe/mirai/event/
events/
MiraiEvent.java
→
mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEvent.java
View file @
93dc8e58
package
net.mamoe.mirai.event
.events
;
package
net.mamoe.mirai.event
;
import
net.mamoe.mirai.event.MiraiEventManager
;
import
net.mamoe.mirai.utils.EventException
;
import
net.mamoe.mirai.utils.EventException
;
import
java.util.function.Consumer
;
/**
* @author NatrualHG
* @see AsyncEvent
*/
public
abstract
class
MiraiEvent
{
public
abstract
class
MiraiEvent
{
private
boolean
cancelled
;
private
boolean
cancelled
;
public
boolean
isCancelled
()
{
public
boolean
isCancelled
()
{
if
(!(
this
instanceof
Cancellable
))
{
if
(!(
this
instanceof
Cancellable
))
{
throw
new
EventException
(
"Event is not Cancellable"
)
;
return
false
;
}
}
return
this
.
cancelled
;
return
this
.
cancelled
;
}
}
...
@@ -27,27 +28,8 @@ public abstract class MiraiEvent {
...
@@ -27,27 +28,8 @@ public abstract class MiraiEvent {
this
.
cancelled
=
value
;
this
.
cancelled
=
value
;
}
}
protected
String
eventName
;
public
String
getEventName
()
{
if
(
this
.
eventName
==
null
)
{
return
this
.
getClass
().
getSimpleName
();
}
return
this
.
eventName
;
}
public
final
MiraiEvent
broadcast
()
{
public
final
MiraiEvent
broadcast
()
{
MiraiEventManager
.
getInstance
().
broadcastEvent
(
this
);
MiraiEventManager
.
getInstance
().
broadcastEvent
(
this
);
return
this
;
return
this
;
}
}
@SuppressWarnings
(
"unchecked"
)
public
final
<
D
extends
MiraiEvent
>
void
asyncBroadcast
(
Consumer
<
D
>
callback
)
{
MiraiEventManager
.
getInstance
().
asyncBroadcastEvent
((
D
)
this
,
callback
);
}
@SuppressWarnings
(
"unchecked"
)
public
final
<
D
extends
MiraiEvent
>
void
asyncBroadcast
(
Runnable
callback
)
{
MiraiEventManager
.
getInstance
().
asyncBroadcastEvent
((
D
)
this
,
callback
);
}
}
}
mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEventHook.java
View file @
93dc8e58
...
@@ -2,20 +2,21 @@ package net.mamoe.mirai.event;
...
@@ -2,20 +2,21 @@ package net.mamoe.mirai.event;
import
lombok.Getter
;
import
lombok.Getter
;
import
lombok.Setter
;
import
lombok.Setter
;
import
net.mamoe.mirai.event.events.Cancellable
;
import
net.mamoe.mirai.event.events.MiraiEvent
;
import
java.io.Closeable
;
import
java.io.Closeable
;
import
java.util.function.Consumer
;
import
java.util.function.Consumer
;
import
java.util.function.Predicate
;
import
java.util.function.Predicate
;
/**
* @author NatrualHG
*/
public
class
MiraiEventHook
<
T
extends
MiraiEvent
>
implements
Closeable
{
public
class
MiraiEventHook
<
T
extends
MiraiEvent
>
implements
Closeable
{
@Getter
@Getter
Class
<
T
>
eventClass
;
Class
<
T
>
eventClass
;
@Getter
@Getter
pr
ivate
volatile
Consumer
<
T
>
handler
;
pr
otected
volatile
Consumer
<
T
>
handler
;
@Getter
@Getter
private
volatile
int
priority
=
0
;
private
volatile
int
priority
=
0
;
...
@@ -31,7 +32,7 @@ public class MiraiEventHook<T extends MiraiEvent> implements Closeable {
...
@@ -31,7 +32,7 @@ public class MiraiEventHook<T extends MiraiEvent> implements Closeable {
* return true -> this hook need to be removed
* return true -> this hook need to be removed
*/
*/
@Getter
@Getter
pr
ivate
Predicate
<
T
>
valid
;
pr
otected
Predicate
<
T
>
validChecker
;
public
MiraiEventHook
(
Class
<
T
>
eventClass
)
{
public
MiraiEventHook
(
Class
<
T
>
eventClass
)
{
this
(
eventClass
,
null
);
this
(
eventClass
,
null
);
...
@@ -58,26 +59,26 @@ public class MiraiEventHook<T extends MiraiEvent> implements Closeable {
...
@@ -58,26 +59,26 @@ public class MiraiEventHook<T extends MiraiEvent> implements Closeable {
}
}
private
MiraiEventHook
<
T
>
setValid
(
Predicate
<
T
>
valid
)
{
private
MiraiEventHook
<
T
>
setValid
Checker
(
Predicate
<
T
>
validChecker
)
{
this
.
valid
=
valid
;
this
.
valid
Checker
=
validChecker
;
return
this
;
return
this
;
}
}
public
MiraiEventHook
<
T
>
setValidUntil
(
Predicate
<
T
>
valid
)
{
public
MiraiEventHook
<
T
>
setValidUntil
(
Predicate
<
T
>
valid
)
{
return
this
.
setValid
(
valid
);
return
this
.
setValid
Checker
(
valid
);
}
}
public
MiraiEventHook
<
T
>
setValidWhile
(
Predicate
<
T
>
valid
)
{
public
MiraiEventHook
<
T
>
setValidWhile
(
Predicate
<
T
>
valid
)
{
return
this
.
setValid
(
valid
.
negate
());
return
this
.
setValid
Checker
(
valid
.
negate
());
}
}
@SuppressWarnings
(
"unchecked"
)
@SuppressWarnings
(
"unchecked"
)
public
boolean
accept
(
MiraiEvent
event
)
{
public
boolean
accept
(
MiraiEvent
event
)
{
if
(!(
event
instanceof
Cancellable
&&
event
.
isCancelled
()
&&
this
.
isIgnoreCancelled
())){
if
(!(
event
instanceof
Cancellable
&&
event
.
isCancelled
()
&&
this
.
isIgnoreCancelled
())){
this
.
getHandler
().
accept
((
T
)
event
);
this
.
getHandler
().
accept
((
T
)
event
);
}
}
return
this
.
valid
==
null
||
this
.
valid
.
test
((
T
)
event
);
return
this
.
valid
Checker
==
null
||
this
.
validChecker
.
test
((
T
)
event
);
}
}
/**
/**
...
@@ -103,6 +104,6 @@ public class MiraiEventHook<T extends MiraiEvent> implements Closeable {
...
@@ -103,6 +104,6 @@ public class MiraiEventHook<T extends MiraiEvent> implements Closeable {
@Override
@Override
public
void
close
(){
public
void
close
(){
this
.
handler
=
null
;
this
.
handler
=
null
;
this
.
valid
=
null
;
this
.
valid
Checker
=
null
;
}
}
}
}
mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEventHookKt.kt
0 → 100644
View file @
93dc8e58
package
net.mamoe.mirai.event
import
java.util.function.Consumer
import
java.util.function.Predicate
/**
* @author Him188moe
*/
class
MiraiEventHookKt
<
E
:
MiraiEvent
>(
eventClass
:
Class
<
E
>)
:
MiraiEventHook
<
E
>(
eventClass
)
{
fun
onEvent
(
handler
:
(
E
)
->
Unit
)
{
this
@MiraiEventHookKt
.
handler
=
Consumer
(
handler
)
}
fun
validChecker
(
predicate
:
(
E
)
->
Boolean
)
{
this
@MiraiEventHookKt
.
validChecker
=
Predicate
(
predicate
)
}
}
/**
* Kotlin 风格回调
* 你的代码可以这样(并且 validChecker 是可选的):
*
* event.hook {
* onEvent {}
* validChecker {}
* }
*/
fun
<
E
:
MiraiEvent
>
E
.
hook
(
handler
:
MiraiEventHookKt
<
E
>.()
->
Unit
):
MiraiEventHookKt
<
E
>
{
return
MiraiEventHookKt
(
this
.
javaClass
).
apply
(
handler
)
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEventKt.kt
0 → 100644
View file @
93dc8e58
@
file
:
JvmName
(
"MiraiEventKt"
)
package
net.mamoe.mirai.event
fun
<
E
:
MiraiEvent
>
E
.
broadcastSmart
():
E
{
MiraiEventManager
.
getInstance
().
broadcastEvent
(
this
as
MiraiEvent
)
return
this
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEventManager.java
View file @
93dc8e58
package
net.mamoe.mirai.event
;
package
net.mamoe.mirai.event
;
import
net.mamoe.mirai.MiraiServer
;
import
net.mamoe.mirai.event.events.MiraiEvent
;
import
java.util.*
;
import
java.util.*
;
import
java.util.concurrent.CompletableFuture
;
import
java.util.concurrent.locks.ReentrantReadWriteLock
;
import
java.util.concurrent.locks.ReentrantReadWriteLock
;
import
java.util.function.Consumer
;
import
java.util.function.Consumer
;
import
java.util.function.Predicate
;
import
java.util.function.Predicate
;
import
java.util.stream.Collectors
;
import
java.util.stream.Collectors
;
/**
* 线程安全的事件管理器.
*
* @author NaturalHG
* @see MiraiEventManagerKt 若你使用 kotlin, 请查看针对 kotlin 的优化实现
*/
public
class
MiraiEventManager
{
public
class
MiraiEventManager
{
private
MiraiEventManager
()
{
MiraiEventManager
()
{
}
}
private
static
MiraiEventManager
instance
=
new
MiraiEventManager
();
public
static
MiraiEventManager
getInstance
()
{
public
static
MiraiEventManager
getInstance
()
{
return
MiraiEventManager
.
instance
;
return
EventManager
.
INSTANCE
;
//实例来自 kotlin 的 singleton
}
}
private
final
ReentrantReadWriteLock
hooksLock
=
new
ReentrantReadWriteLock
();
private
final
ReentrantReadWriteLock
hooksLock
=
new
ReentrantReadWriteLock
();
...
@@ -117,23 +119,40 @@ public class MiraiEventManager {
...
@@ -117,23 +119,40 @@ public class MiraiEventManager {
}
}
public
void
asyncBroadcastEvent
(
MiraiEvent
event
)
{
public
<
E
extends
AsyncEvent
>
CompletableFuture
<
E
>
broadcastEventAsync
(
E
event
)
{
this
.
asyncBroadcastEvent
(
event
,
a
->
{
Objects
.
requireNonNull
(
event
);
if
(!(
event
instanceof
MiraiEvent
))
{
throw
new
IllegalArgumentException
(
"event must be instanceof MiraiEvent"
);
}
CompletableFuture
<
E
>
future
=
new
CompletableFuture
<>();
future
.
completeAsync
(()
->
{
MiraiEventManager
.
this
.
broadcastEvent
((
MiraiEvent
)
event
);
return
event
;
});
});
return
future
;
}
}
public
<
D
extends
MiraiEvent
>
void
asyncBroadcastEvent
(
D
event
,
Consumer
<
D
>
callback
)
{
public
<
E
extends
AsyncEvent
>
CompletableFuture
<
E
>
broadcastEventAsync
(
E
event
,
Consumer
<
E
>
callback
)
{
MiraiServer
.
getInstance
().
getTaskManager
().
ansycTask
(()
->
{
Objects
.
requireNonNull
(
event
);
MiraiEventManager
.
this
.
broadcastEvent
(
event
);
Objects
.
requireNonNull
(
callback
);
if
(!(
event
instanceof
MiraiEvent
))
{
throw
new
IllegalArgumentException
(
"event must be instanceof MiraiEvent"
);
}
CompletableFuture
<
E
>
future
=
new
CompletableFuture
<>();
future
.
whenComplete
((
a
,
b
)
->
callback
.
accept
(
event
));
future
.
completeAsync
(()
->
{
MiraiEventManager
.
this
.
broadcastEvent
((
MiraiEvent
)
event
);
return
event
;
return
event
;
},
callback
);
});
return
future
;
}
}
public
<
D
extends
MiraiEvent
>
void
asyncBroadcastEvent
(
D
event
,
Runnable
callback
)
{
public
<
D
extends
AsyncEvent
>
CompletableFuture
<
D
>
broadcastEventAsync
(
D
event
,
Runnable
callback
)
{
asyncBroadcastEvent
(
event
,
t
->
callback
.
run
());
return
broadcastEventAsync
(
event
,
t
->
callback
.
run
());
}
}
}
}
...
...
mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEventManagerKt.kt
View file @
93dc8e58
@
file
:
JvmName
(
"MiraiEventManagerKt"
)
package
net.mamoe.mirai.event
package
net.mamoe.mirai.event
import
net.mamoe.mirai.event.events.MiraiEvent
import
kotlin.reflect.KClass
import
kotlin.reflect.KClass
/**
* [MiraiEventManager] 的 kotlin 简易化实现.
* 若要 hook 一个事件, 你可以:
* FriendMessageEvent::class.hookOnce {}
* FriendMessageEvent::class.hookAlways {}
*
* @author Him188moe
*/
object
EventManager
:
MiraiEventManager
()
/**
* 每次事件触发时都会调用 hook
*/
fun
<
C
:
Class
<
E
>,
E
:
MiraiEvent
>
C
.
hookAlways
(
hook
:
(
E
)
->
Unit
)
{
fun
<
C
:
Class
<
E
>,
E
:
MiraiEvent
>
C
.
hookAlways
(
hook
:
(
E
)
->
Unit
)
{
MiraiEventManager
.
getInstance
().
hookAlways
(
MiraiEventHook
<
E
>(
this
,
hook
))
MiraiEventManager
.
getInstance
().
hookAlways
(
MiraiEventHook
<
E
>(
this
,
hook
))
}
}
/**
* 当下一次事件触发时调用 hook
*/
fun
<
C
:
Class
<
E
>,
E
:
MiraiEvent
>
C
.
hookOnce
(
hook
:
(
E
)
->
Unit
)
{
fun
<
C
:
Class
<
E
>,
E
:
MiraiEvent
>
C
.
hookOnce
(
hook
:
(
E
)
->
Unit
)
{
MiraiEventManager
.
getInstance
().
hookOnce
(
MiraiEventHook
<
E
>(
this
,
hook
))
MiraiEventManager
.
getInstance
().
hookOnce
(
MiraiEventHook
<
E
>(
this
,
hook
))
}
}
/**
* 每次事件触发时都会调用 hook, 直到 hook 返回 false 时停止 hook
*/
fun
<
C
:
Class
<
E
>,
E
:
MiraiEvent
>
C
.
hookWhile
(
hook
:
(
E
)
->
Boolean
)
{
fun
<
C
:
Class
<
E
>,
E
:
MiraiEvent
>
C
.
hookWhile
(
hook
:
(
E
)
->
Boolean
)
{
MiraiEventManager
.
getInstance
().
hookAlways
(
MiraiEventHookSimple
<
E
>
(
this
,
hook
))
MiraiEventManager
.
getInstance
().
hookAlways
(
MiraiEventHookSimple
(
this
,
hook
))
}
}
/**
* 每次事件触发时都会调用 hook
*/
fun
<
C
:
KClass
<
E
>,
E
:
MiraiEvent
>
C
.
hookAlways
(
hook
:
(
E
)
->
Unit
)
{
fun
<
C
:
KClass
<
E
>,
E
:
MiraiEvent
>
C
.
hookAlways
(
hook
:
(
E
)
->
Unit
)
{
this
.
java
.
hookAlways
(
hook
)
this
.
java
.
hookAlways
(
hook
)
}
}
/**
* 当下一次事件触发时调用 hook
*/
fun
<
C
:
KClass
<
E
>,
E
:
MiraiEvent
>
C
.
hookOnce
(
hook
:
(
E
)
->
Unit
)
{
fun
<
C
:
KClass
<
E
>,
E
:
MiraiEvent
>
C
.
hookOnce
(
hook
:
(
E
)
->
Unit
)
{
this
.
java
.
hookOnce
(
hook
)
this
.
java
.
hookOnce
(
hook
)
}
}
/**
* 每次事件触发时都会调用 hook, 直到 hook 返回 false 时停止 hook
*/
fun
<
C
:
KClass
<
E
>,
E
:
MiraiEvent
>
C
.
hookWhile
(
hook
:
(
E
)
->
Boolean
)
{
fun
<
C
:
KClass
<
E
>,
E
:
MiraiEvent
>
C
.
hookWhile
(
hook
:
(
E
)
->
Boolean
)
{
this
.
java
.
hookWhile
(
hook
)
this
.
java
.
hookWhile
(
hook
)
}
}
...
...
mirai-core/src/main/java/net/mamoe/mirai/event/events/network/BeforePacketSendEvent.java
0 → 100644
View file @
93dc8e58
package
net.mamoe.mirai.event.events.network
;
import
net.mamoe.mirai.event.Cancellable
;
import
net.mamoe.mirai.network.packet.ClientPacket
;
import
org.jetbrains.annotations.NotNull
;
/**
* Packet 已经 {@link ClientPacket#encode()}, 即将被发送
*
* @author Him188moe
*/
public
final
class
BeforePacketSendEvent
extends
ClientPacketEvent
implements
Cancellable
{
public
BeforePacketSendEvent
(
@NotNull
ClientPacket
packet
)
{
super
(
packet
);
}
}
mirai-core/src/main/java/net/mamoe/mirai/event/events/network/ClientPacketEvent.java
0 → 100644
View file @
93dc8e58
package
net.mamoe.mirai.event.events.network
;
import
net.mamoe.mirai.network.packet.ClientPacket
;
import
org.jetbrains.annotations.NotNull
;
/**
* @author Him188moe
*/
public
abstract
class
ClientPacketEvent
extends
PacketEvent
{
public
ClientPacketEvent
(
@NotNull
ClientPacket
packet
)
{
super
(
packet
);
}
@Override
public
ClientPacket
getPacket
()
{
return
(
ClientPacket
)
super
.
getPacket
();
}
}
mirai-core/src/main/java/net/mamoe/mirai/event/events/network/PacketEvent.java
0 → 100644
View file @
93dc8e58
package
net.mamoe.mirai.event.events.network
;
import
net.mamoe.mirai.event.MiraiEvent
;
import
net.mamoe.mirai.network.packet.Packet
;
import
org.jetbrains.annotations.NotNull
;
import
java.util.Objects
;
/**
* @author Him188moe
*/
public
abstract
class
PacketEvent
extends
MiraiEvent
{
private
final
Packet
packet
;
public
PacketEvent
(
@NotNull
Packet
packet
)
{
this
.
packet
=
Objects
.
requireNonNull
(
packet
);
}
public
Packet
getPacket
()
{
return
packet
;
}
}
mirai-core/src/main/java/net/mamoe/mirai/event/events/network/PacketSentEvent.java
0 → 100644
View file @
93dc8e58
package
net.mamoe.mirai.event.events.network
;
import
net.mamoe.mirai.network.packet.ClientPacket
;
import
org.jetbrains.annotations.NotNull
;
/**
* Packet 已经发出
*
* @author Him188moe
*/
public
final
class
PacketSentEvent
extends
ClientPacketEvent
{
public
PacketSentEvent
(
@NotNull
ClientPacket
packet
)
{
super
(
packet
);
}
}
mirai-core/src/main/java/net/mamoe/mirai/event/events/network/ServerPacketEvent.java
0 → 100644
View file @
93dc8e58
package
net.mamoe.mirai.event.events.network
;
import
net.mamoe.mirai.network.packet.ServerPacket
;
/**
* @author Him188moe
*/
public
abstract
class
ServerPacketEvent
extends
PacketEvent
{
public
ServerPacketEvent
(
ServerPacket
packet
)
{
super
(
packet
);
}
@Override
public
ServerPacket
getPacket
()
{
return
(
ServerPacket
)
super
.
getPacket
();
}
}
mirai-core/src/main/java/net/mamoe/mirai/event/events/network/ServerPacketReceivedEvent.java
0 → 100644
View file @
93dc8e58
package
net.mamoe.mirai.event.events.network
;
import
net.mamoe.mirai.event.Cancellable
;
import
net.mamoe.mirai.network.packet.ServerPacket
;
import
net.mamoe.mirai.network.packet.ServerVerificationCodePacket
;
/**
* 服务器接到某数据包时触发这个事件.
* 注意, 当接收到数据包的加密包(如 {@link ServerVerificationCodePacket.Encrypted})也会触发这个事件, 随后才会
*
* @author Him188moe
*/
public
final
class
ServerPacketReceivedEvent
extends
ServerPacketEvent
implements
Cancellable
{
public
ServerPacketReceivedEvent
(
ServerPacket
packet
)
{
super
(
packet
);
}
}
mirai-core/src/main/java/net/mamoe/mirai/event/events/robot/RobotEvent.java
View file @
93dc8e58
package
net.mamoe.mirai.event.events.robot
;
package
net.mamoe.mirai.event.events.robot
;
import
net.mamoe.mirai.Robot
;
import
net.mamoe.mirai.Robot
;
import
net.mamoe.mirai.event.
events.
MiraiEvent
;
import
net.mamoe.mirai.event.MiraiEvent
;
import
org.jetbrains.annotations.NotNull
;
import
org.jetbrains.annotations.NotNull
;
import
java.util.Objects
;
import
java.util.Objects
;
...
...
mirai-core/src/main/java/net/mamoe/mirai/event/events/robot/RobotEvents.kt
View file @
93dc8e58
package
net.mamoe.mirai.event.events.robot
package
net.mamoe.mirai.event.events.robot
import
net.mamoe.mirai.
event.events.MiraiEven
t
import
net.mamoe.mirai.
Robo
t
import
net.mamoe.mirai.
network.RobotNetworkHandler
import
net.mamoe.mirai.
event.MiraiEvent
/**
/**
* @author Him188moe
* @author Him188moe
*/
*/
class
RobotLoginEvent
(
val
robot
NetworkHandler
:
RobotNetworkHandler
)
:
MiraiEvent
()
class
RobotLoginEvent
(
val
robot
:
Robot
)
:
MiraiEvent
()
class
RobotLogoutEvent
(
val
robot
NetworkHandler
:
RobotNetworkHandler
)
:
MiraiEvent
()
class
RobotLogoutEvent
(
val
robot
:
Robot
)
:
MiraiEvent
()
class
RobotMessageReceivedEvent
(
val
robot
NetworkHandler
:
RobotNetworkHandler
,
val
type
:
Type
,
val
message
:
String
)
:
MiraiEvent
()
{
class
RobotMessageReceivedEvent
(
val
robot
:
Robot
,
val
type
:
Type
,
val
message
:
String
)
:
MiraiEvent
()
{
enum
class
Type
{
enum
class
Type
{
FRIEND
,
FRIEND
,
GROUP
GROUP
}
}
}
}
mirai-core/src/main/java/net/mamoe/mirai/event/events/robot/RobotLoginSucceedEvent.java
View file @
93dc8e58
...
@@ -7,5 +7,4 @@ public final class RobotLoginSucceedEvent extends RobotEvent {
...
@@ -7,5 +7,4 @@ public final class RobotLoginSucceedEvent extends RobotEvent {
public
RobotLoginSucceedEvent
(
Robot
robot
)
{
public
RobotLoginSucceedEvent
(
Robot
robot
)
{
super
(
robot
);
super
(
robot
);
}
}
}
}
mirai-core/src/main/java/net/mamoe/mirai/event/events/server/ServerDisableEvent.java
deleted
100644 → 0
View file @
5b07f09d
package
net.mamoe.mirai.event.events.server
;
import
net.mamoe.mirai.event.events.MiraiEvent
;
public
final
class
ServerDisableEvent
extends
MiraiEvent
{
}
mirai-core/src/main/java/net/mamoe/mirai/event/events/server/ServerDisabledEvent.java
0 → 100644
View file @
93dc8e58
package
net.mamoe.mirai.event.events.server
;
import
net.mamoe.mirai.event.AsyncEvent
;
import
net.mamoe.mirai.event.MiraiEvent
;
public
final
class
ServerDisabledEvent
extends
MiraiEvent
implements
AsyncEvent
{
}
mirai-core/src/main/java/net/mamoe/mirai/event/events/server/ServerEnableEvent.java
deleted
100644 → 0
View file @
5b07f09d
package
net.mamoe.mirai.event.events.server
;
import
net.mamoe.mirai.event.events.MiraiEvent
;
public
final
class
ServerEnableEvent
extends
MiraiEvent
{
}
mirai-core/src/main/java/net/mamoe/mirai/event/events/server/ServerEnabledEvent.java
0 → 100644
View file @
93dc8e58
package
net.mamoe.mirai.event.events.server
;
import
net.mamoe.mirai.event.AsyncEvent
;
import
net.mamoe.mirai.event.MiraiEvent
;
public
final
class
ServerEnabledEvent
extends
MiraiEvent
implements
AsyncEvent
{
}
mirai-core/src/main/java/net/mamoe/mirai/message/Message.java
View file @
93dc8e58
package
net.mamoe.mirai.message
;
package
net.mamoe.mirai.message
;
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.At
;
import
net.mamoe.mirai.message.defaults.Image
;
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
org.jetbrains.annotations.NotNull
;
import
org.jetbrains.annotations.NotNull
;
...
@@ -11,7 +13,12 @@ import java.io.File;
...
@@ -11,7 +13,12 @@ import java.io.File;
import
java.util.Objects
;
import
java.util.Objects
;
/**
/**
* 可发送的或从服务器接收的消息.
* 采用这样的消息模式是因为 QQ 的消息多元化, 一条消息中可包含 {@linkplain PlainText 纯文本}, {@linkplain Image 图片} 等.
*
* @author Him188moe
* @author Him188moe
* @see Contact#sendMessage(Message) 发送这个消息
* @see MessageKt 若你使用 kotlin, 请查看针对 kotlin 的优化实现
*/
*/
public
abstract
class
Message
{
public
abstract
class
Message
{
@Override
@Override
...
@@ -38,7 +45,7 @@ public abstract class Message {
...
@@ -38,7 +45,7 @@ public abstract class Message {
return
new
MessageChain
(
this
,
Objects
.
requireNonNull
(
tail
));
return
new
MessageChain
(
this
,
Objects
.
requireNonNull
(
tail
));
}
}
public
Message
concat
(
String
tail
)
{
public
final
Message
concat
(
String
tail
)
{
return
concat
(
new
PlainText
(
tail
));
return
concat
(
new
PlainText
(
tail
));
}
}
...
...
mirai-core/src/main/java/net/mamoe/mirai/message/MessageKt.kt
View file @
93dc8e58
@
file
:
JvmName
(
"MessageKt"
)
package
net.mamoe.mirai.message
package
net.mamoe.mirai.message
import
net.mamoe.mirai.message.defaults.PlainText
import
net.mamoe.mirai.message.defaults.PlainText
...
@@ -12,4 +14,7 @@ infix operator fun Message.plus(another: Message): Message = this.concat(another
...
@@ -12,4 +14,7 @@ infix operator fun Message.plus(another: Message): Message = this.concat(another
*/
*/
infix
operator
fun
Message
.
plus
(
another
:
String
):
Message
=
this
.
concat
(
another
)
infix
operator
fun
Message
.
plus
(
another
:
String
):
Message
=
this
.
concat
(
another
)
/**
* 连接 [String] 与 [Message]
*/
infix
fun
String
.
concat
(
another
:
Message
):
Message
=
PlainText
(
this
).
concat
(
another
)
infix
fun
String
.
concat
(
another
:
Message
):
Message
=
PlainText
(
this
).
concat
(
another
)
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/message/defaults/At.java
View file @
93dc8e58
...
@@ -7,25 +7,28 @@ import org.jetbrains.annotations.NotNull;
...
@@ -7,25 +7,28 @@ import org.jetbrains.annotations.NotNull;
import
java.util.Objects
;
import
java.util.Objects
;
/**
/**
* At 一个人的消息.
*
* @author Him188moe
* @author Him188moe
*/
*/
public
final
class
At
extends
Message
{
public
final
class
At
extends
Message
{
private
final
int
target
;
private
final
long
target
;
public
At
(
@NotNull
QQ
target
)
{
public
At
(
@NotNull
QQ
target
)
{
this
(
Objects
.
requireNonNull
(
target
).
getNumber
());
this
(
Objects
.
requireNonNull
(
target
).
getNumber
());
}
}
public
At
(
int
target
)
{
public
At
(
long
target
)
{
this
.
target
=
target
;
this
.
target
=
target
;
}
}
public
int
getTarget
()
{
public
long
getTarget
()
{
return
target
;
return
target
;
}
}
@Override
@Override
public
String
toString
()
{
public
String
toString
()
{
return
null
;
// TODO: 2019/9/4 At.toString
throw
new
UnsupportedOperationException
();
}
}
}
}
mirai-core/src/main/java/net/mamoe/mirai/message/defaults/Face.java
View file @
93dc8e58
...
@@ -4,6 +4,8 @@ import net.mamoe.mirai.message.FaceID;
...
@@ -4,6 +4,8 @@ import net.mamoe.mirai.message.FaceID;
import
net.mamoe.mirai.message.Message
;
import
net.mamoe.mirai.message.Message
;
/**
/**
* QQ 自带表情
*
* @author Him188moe
* @author Him188moe
*/
*/
public
final
class
Face
extends
Message
{
public
final
class
Face
extends
Message
{
...
...
mirai-core/src/main/java/net/mamoe/mirai/message/defaults/MessageChain.java
View file @
93dc8e58
...
@@ -29,6 +29,9 @@ public final class MessageChain extends Message {
...
@@ -29,6 +29,9 @@ public final class MessageChain extends Message {
list
.
add
(
message
);
list
.
add
(
message
);
}
}
/**
* @return An unmodifiable list
*/
public
List
<
Message
>
toList
()
{
public
List
<
Message
>
toList
()
{
return
List
.
copyOf
(
list
);
return
List
.
copyOf
(
list
);
}
}
...
...
mirai-core/src/main/java/net/mamoe/mirai/network/Protocol.kt
View file @
93dc8e58
...
@@ -7,70 +7,84 @@ import java.util.stream.Collectors
...
@@ -7,70 +7,84 @@ import java.util.stream.Collectors
/**
/**
* @author Him188moe
* @author Him188moe
*/
*/
interface
Protocol
{
object
Protocol
{
companion
object
{
val
SERVER_IP
:
List
<
String
>
=
object
:
ArrayList
<
String
>()
{
val
SERVER_IP
:
ArrayList
<
String
>
=
object
:
ArrayList
<
String
>()
{
init
{
init
{
add
(
"183.60.56.29"
)
add
(
"183.60.56.29"
)
arrayOf
(
arrayOf
(
"sz2
.tencent.com"
,
"sz3
.tencent.com"
,
"sz3
.tencent.com"
,
"sz4
.tencent.com"
,
"sz4
.tencent.com"
,
"sz5
.tencent.com"
,
"sz5
.tencent.com"
,
"sz6
.tencent.com"
,
"sz6
.tencent.com"
,
"sz8
.tencent.com"
,
"sz8
.tencent.com"
,
"sz9
.tencent.com"
,
"sz9
.tencent.com"
"sz2
.tencent.com"
).
forEach
{
this
.
add
(
InetAddress
.
getByName
(
it
).
hostAddress
)
}
).
forEach
{
this
.
add
(
InetAddress
.
getByName
(
it
).
hostAddress
)
}
}
}
}
}
get
()
=
Collections
.
unmodifiableList
(
field
)
const
val
head
=
"02"
const
val
ver
=
"37 13"
const
val
fixVer
=
"03 00 00 00 01 2E 01 00 00 68 52 00 00 00 00"
const
val
tail
=
"03"
/**
* _fixVer
*/
const
val
fixVer2
=
"02 00 00 00 01 01 01 00 00 68 20"
/**
* 0825data1
*/
const
val
constantData0
=
"00 18 00 16 00 01 "
/**
* 0825data2
*/
const
val
constantData1
=
"00 00 04 53 00 00 00 01 00 00 15 85 "
const
val
key0825
=
"A4 F1 91 88 C9 82 14 99 0C 9E 56 55 91 23 C8 3D"
const
val
redirectionKey
=
"A8 F2 14 5F 58 12 60 AF 07 63 97 D6 76 B2 1A 3B"
const
val
publicKey
=
"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"
const
val
shareKey
=
"1A E9 7F 7D C9 73 75 98 AC 02 E0 80 5F A9 C6 AF"
const
val
fix0836
=
"06 A9 12 97 B7 F8 76 25 AF AF D3 EA B4 C8 BC E7 "
const
val
head
=
"02"
const
val
key00BA
=
"C1 9C B8 C8 7B 8C 81 BA 9E 9E 7A 89 E1 7A EC 94"
const
val
ver
=
"37 13 "
const
val
key00BAFix
=
"69 20 D1 14 74 F5 B3 93 E4 D5 02 B3 71 1A CD 2A"
const
val
fixVer
=
"03 00 00 00 01 2E 01 00 00 68 52 00 00 00 00 "
const
val
tail
=
" 03"
const
val
_fixVer
=
"02 00 00 00 01 01 01 00 00 68 20 "
const
val
_0825data0
=
"00 18 00 16 00 01 "
const
val
_0825data2
=
"00 00 04 53 00 00 00 01 00 00 15 85 "
const
val
_0825key
=
"A4 F1 91 88 C9 82 14 99 0C 9E 56 55 91 23 C8 3D"
const
val
redirectionKey
=
"A8 F2 14 5F 58 12 60 AF 07 63 97 D6 76 B2 1A 3B"
const
val
publicKey
=
"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"
const
val
shareKey
=
"1A E9 7F 7D C9 73 75 98 AC 02 E0 80 5F A9 C6 AF"
const
val
_0836fix
=
"06 A9 12 97 B7 F8 76 25 AF AF D3 EA B4 C8 BC E7 "
const
val
_00BaKey
=
"C1 9C B8 C8 7B 8C 81 BA 9E 9E 7A 89 E1 7A EC 94"
const
val
_00BaFixKey
=
"69 20 D1 14 74 F5 B3 93 E4 D5 02 B3 71 1A CD 2A"
const
val
encryptKey
=
"“BA 42 FF 01 CF B4 FF D2 12 F0 6E A7 1B 7C B3 08”"
const
val
_0836_622_fix2
=
"00 15 00 30 00 01 01 27 9B C7 F5 00 10 65 03 FD 8B 00 00 00 00 00 00 00 00 00 00 00 00 02 90 49 55 33 00 10 15 74 C4 89 85 7A 19 F5 5E A9 C9 A3 5E 8A 5A 9B"
;
/**
const
val
_0836_622_fix1
=
"03 00 00 00 01 01 01 00 00 68 20 00 00 00 00 00 01 01 03 00 19"
;
* 0836_622_fix2
const
val
_0836key1
=
"EF 4A 36 6A 16 A8 E6 3D 2E EA BD 1F 98 C1 3C DA"
*/
const
val
passwordSubmissionKey2
=
"00 15 00 30 00 01 01 27 9B C7 F5 00 10 65 03 FD 8B 00 00 00 00 00 00 00 00 00 00 00 00 02 90 49 55 33 00 10 15 74 C4 89 85 7A 19 F5 5E A9 C9 A3 5E 8A 5A 9B"
;
/**
* 0836_622_fix1
*/
const
val
passwordSubmissionKey1
=
"03 00 00 00 01 01 01 00 00 68 20 00 00 00 00 00 01 01 03 00 19"
;
/**
* fix_0836_1
*/
const
val
key0836
=
"EF 4A 36 6A 16 A8 E6 3D 2E EA BD 1F 98 C1 3C DA"
private
val
hexToByteArrayCacheMap
:
MutableMap
<
Int
,
ByteArray
>
=
mutableMapOf
()
private
val
hexToByteArrayCacheMap
:
MutableMap
<
Int
,
ByteArray
>
=
mutableMapOf
()
@ExperimentalUnsignedTypes
@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
))
{
return
hexToByteArrayCacheMap
[
id
]
!!
.
clone
()
return
hexToByteArrayCacheMap
[
id
]
!!
.
clone
()
}
else
{
}
else
{
hexToUBytes
(
hex
).
toByteArray
().
let
{
hexToUBytes
(
hex
).
toByteArray
().
let
{
hexToByteArrayCacheMap
[
id
]
=
it
.
clone
();
hexToByteArrayCacheMap
[
id
]
=
it
.
clone
();
return
it
return
it
}
}
}
}
}
}
}
}
@ExperimentalUnsignedTypes
@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
<=
' '
}
}
.
map
{
s
->
s
.
toUByte
(
16
)
}
.
map
{
s
->
s
.
toUByte
(
16
)
}
.
collect
(
Collectors
.
toList
()).
toUByteArray
()
.
collect
(
Collectors
.
toList
()).
toUByteArray
()
}
}
}
mirai-core/src/main/java/net/mamoe/mirai/network/RobotNetworkHandler.kt
View file @
93dc8e58
@
file
:
JvmMultifileClass
@
file
:
JvmName
(
"RobotNetworkHandler"
)
package
net.mamoe.mirai.network
package
net.mamoe.mirai.network
import
net.mamoe.mirai.MiraiServer
import
net.mamoe.mirai.Robot
import
net.mamoe.mirai.Robot
import
net.mamoe.mirai.contact.Group
import
net.mamoe.mirai.contact.Group
import
net.mamoe.mirai.contact.QQ
import
net.mamoe.mirai.event.events.network.BeforePacketSendEvent
import
net.mamoe.mirai.event.events.network.PacketSentEvent
import
net.mamoe.mirai.event.events.network.ServerPacketReceivedEvent
import
net.mamoe.mirai.event.events.qq.FriendMessageEvent
import
net.mamoe.mirai.event.events.qq.FriendMessageEvent
import
net.mamoe.mirai.event.events.robot.RobotLoginSucceedEvent
import
net.mamoe.mirai.event.events.robot.RobotLoginSucceedEvent
import
net.mamoe.mirai.event.hookWhile
import
net.mamoe.mirai.message.Message
import
net.mamoe.mirai.network.RobotNetworkHandler.*
import
net.mamoe.mirai.network.packet.*
import
net.mamoe.mirai.network.packet.*
import
net.mamoe.mirai.network.packet.action.ServerSendFriendMessageResponsePacket
import
net.mamoe.mirai.network.packet.action.ServerSendGroupMessageResponsePacket
import
net.mamoe.mirai.network.packet.login.*
import
net.mamoe.mirai.network.packet.login.*
import
net.mamoe.mirai.network.packet.message.ClientSendGroupMessagePacket
import
net.mamoe.mirai.network.packet.message.ServerSendFriendMessageResponsePacket
import
net.mamoe.mirai.network.packet.message.ServerSendGroupMessageResponsePacket
import
net.mamoe.mirai.network.packet.verification.ServerVerificationCodePacket
import
net.mamoe.mirai.network.packet.verification.ServerVerificationCodePacketEncrypted
import
net.mamoe.mirai.task.MiraiThreadPool
import
net.mamoe.mirai.task.MiraiThreadPool
import
net.mamoe.mirai.utils.*
import
net.mamoe.mirai.utils.*
import
java.io.ByteArrayInputStream
import
java.io.Closeable
import
java.io.FileOutputStream
import
java.net.DatagramPacket
import
java.net.DatagramPacket
import
java.net.DatagramSocket
import
java.net.DatagramSocket
import
java.net.InetSocketAddress
import
java.net.InetSocketAddress
import
java.util.*
import
java.util.concurrent.CompletableFuture
import
java.util.concurrent.ScheduledFuture
import
java.util.concurrent.TimeUnit
import
java.util.concurrent.TimeUnit
import
java.util.concurrent.TimeoutException
import
kotlin.reflect.KClass
/**
/**
* Mirai 的网络处理器, 它处理所有数据包([Packet])的发送和接收.
* [RobotNetworkHandler] 是全程异步和线程安全的.
*
* [RobotNetworkHandler] 由 2 个模块构成:
* - [SocketHandler]: 处理数据包底层的发送([ByteArray])
* - [PacketHandler]: 制作 [Packet] 并传递给 [SocketHandler] 继续处理; 分析来自服务器的数据包并处理
*
* 其中, [PacketHandler] 由 4 个子模块构成:
* - [DebugHandler] 输出 [Packet.toString]
* - [LoginHandler] 处理 touch/login/verification code 相关
* - [MessageHandler] 处理消息相关(群消息/好友消息)([ServerEventPacket])
* - [ActionHandler] 处理动作相关(踢人/加入群/好友列表等)
*
* A RobotNetworkHandler is used to connect with Tencent servers.
* A RobotNetworkHandler is used to connect with Tencent servers.
*
*
* @author Him188moe
* @author Him188moe
*/
*/
@ExperimentalUnsignedTypes
@Suppress
(
"EXPERIMENTAL_API_USAGE"
)
//to simplify code
class
RobotNetworkHandler
(
val
robot
:
Robot
,
val
number
:
Int
,
private
val
password
:
String
)
{
class
RobotNetworkHandler
(
private
val
robot
:
Robot
)
:
Closeable
{
private
val
socketHandler
:
SocketHandler
=
SocketHandler
()
val
debugHandler
=
DebugHandler
()
val
loginHandler
=
LoginHandler
()
val
messageHandler
=
MessageHandler
()
val
actionHandler
=
ActionHandler
()
private
val
packetHandlers
:
Map
<
KClass
<
out
PacketHandler
>,
PacketHandler
>
=
linkedMapOf
(
DebugHandler
::
class
to debug
Handler
,
LoginHandler
::
class
to login
Handler
,
MessageHandler
::
class
to message
Handler
,
ActionHandler
::
class
to action
Handler
)
private
var
sequence
:
Int
=
0
/**
* Not async
*/
@ExperimentalUnsignedTypes
fun
sendPacket
(
packet
:
ClientPacket
)
{
socketHandler
.
sendPacket
(
packet
)
}
var
socket
:
DatagramSocket
=
DatagramSocket
((
15314
+
Math
.
random
()
*
100
).
toInt
())
override
fun
close
()
{
this
.
packetHandlers
.
values
.
forEach
{
it
.
close
()
}
this
.
socketHandler
.
close
()
}
var
serverIP
:
String
=
""
set
(
value
)
{
serverAddress
=
InetSocketAddress
(
value
,
8000
)
field
=
value
socket
.
close
()
//private | internal
socket
=
DatagramSocket
((
15314
+
Math
.
random
()
*
100
).
toInt
())
socket
.
connect
(
this
.
serverAddress
)
internal
fun
tryLogin
():
CompletableFuture
<
LoginState
>
=
this
.
tryLogin
(
500
,
TimeUnit
.
MILLISECONDS
)
val
zeroByte
:
Byte
=
0
Thread
{
while
(
true
)
{
/**
val
dp1
=
DatagramPacket
(
ByteArray
(
2048
),
2048
)
* 仅当 [LoginState] 非 [LoginState.UNKNOWN] 且非 [LoginState.TIMEOUT] 才会调用 [loginHook].
try
{
* 如果要输入验证码, 那么会以参数 [LoginState.VERIFICATION_CODE] 调用 [loginHandler], 登录完成后再以 [LoginState.SUCCEED] 调用 [loginHandler]
socket
.
receive
(
dp1
)
*
}
catch
(
e
:
Exception
)
{
* @param connectingTimeout 连接每个服务器的 timeout
if
(
e
.
message
==
"socket closed"
)
{
*/
return
@Thread
internal
fun
tryLogin
(
connectingTimeout
:
Long
,
unit
:
TimeUnit
=
TimeUnit
.
MILLISECONDS
):
CompletableFuture
<
LoginState
>
{
val
ipQueue
:
LinkedList
<
String
>
=
LinkedList
(
Protocol
.
SERVER_IP
)
val
future
=
CompletableFuture
<
LoginState
>()
fun
login
()
{
val
ip
=
ipQueue
.
poll
()
if
(
ip
!=
null
)
{
// val future = this@RobotNetworkHandler.socketHandler.touch(ip)
this
@RobotNetworkHandler
.
socketHandler
.
touch
(
ip
).
runCatching
{
this
@
runCatching
.
get
(
connectingTimeout
,
unit
).
let
{
state
->
if
(
state
==
LoginState
.
UNKNOWN
)
{
login
()
}
else
{
future
.
complete
(
state
)
}
}
}
}
MiraiThreadPool
.
getInstance
().
submit
{
}.
onFailure
{
var
i
=
dp1
.
data
.
size
-
1
;
when
(
it
)
{
while
(
dp1
.
data
[
i
]
==
zeroByte
)
{
is
TimeoutException
->
login
()
--
i
else
->
throw
it
}
try
{
onPacketReceived
(
ServerPacket
.
ofByteArray
(
dp1
.
data
.
copyOfRange
(
0
,
i
+
1
)))
}
catch
(
e
:
Exception
)
{
e
.
printStackTrace
()
}
}
}
}
}
}.
start
()
}
else
{
future
.
complete
(
LoginState
.
UNKNOWN
)
//所有服务器均返回 UNKNOWN
}
}
}
login
()
private
lateinit
var
serverAddress
:
InetSocketAddress
return
future
}
private
lateinit
var
token00BA
:
ByteArray
//这些数据全部是login用的
private
lateinit
var
token0825
:
ByteArray
private
var
loginTime
:
Int
=
0
private
lateinit
var
loginIP
:
String
private
var
tgtgtKey
:
ByteArray
?
=
null
private
var
tlv0105
:
ByteArray
private
lateinit
var
_0828_rec_decr_key
:
ByteArray
private
lateinit
var
sessionKey
:
ByteArray
//这两个是登录成功后得到的
private
lateinit
var
sKey
:
String
/**
/**
*
Used to access web API(for friends list etc.)
*
分配收到的数据包
*/
*/
private
lateinit
var
cookies
:
String
@ExperimentalUnsignedTypes
private
var
gtk
:
Int
=
0
internal
fun
distributePacket
(
packet
:
ServerPacket
)
{
private
var
ignoreMessage
:
Boolean
=
false
packet
.
decode
()
if
(
ServerPacketReceivedEvent
(
packet
).
broadcast
().
isCancelled
)
{
init
{
debugHandler
.
onPacketReceived
(
packet
)
tlv0105
=
lazyEncode
{
return
it
.
writeHex
(
"01 05 00 30"
)
}
it
.
writeHex
(
"00 01 01 02 00 14 01 01 00 10"
)
this
.
packetHandlers
.
values
.
forEach
{
it
.
writeRandom
(
16
)
it
.
onPacketReceived
(
packet
)
it
.
writeHex
(
"00 14 01 02 00 10"
)
it
.
writeRandom
(
16
)
}
}
}
}
@ExperimentalUnsignedTypes
private
inner
class
SocketHandler
:
Closeable
{
private
var
md5_32
:
ByteArray
=
getRandomKey
(
32
)
private
var
socket
:
DatagramSocket
?
=
null
internal
var
serverIP
:
String
=
""
set
(
value
)
{
field
=
value
@ExperimentalUnsignedTypes
restartSocket
()
internal
fun
onPacketReceived
(
packet
:
ServerPacket
)
{
packet
.
decode
()
MiraiLogger
info
"Packet received: $packet"
if
(
packet
is
ServerEventPacket
)
{
sendPacket
(
ClientMessageResponsePacket
(
this
.
number
,
packet
.
packetId
,
this
.
sessionKey
,
packet
.
eventIdentity
))
}
when
(
packet
)
{
is
ServerTouchResponsePacket
->
{
if
(
packet
.
serverIP
!=
null
)
{
//redirection
serverIP
=
packet
.
serverIP
!!
//connect(packet.serverIP!!)
sendPacket
(
ClientServerRedirectionPacket
(
packet
.
serverIP
!!
,
number
))
}
else
{
//password submission
this
.
loginIP
=
packet
.
loginIP
this
.
loginTime
=
packet
.
loginTime
this
.
token0825
=
packet
.
token0825
this
.
tgtgtKey
=
packet
.
tgtgtKey
sendPacket
(
ClientPasswordSubmissionPacket
(
this
.
number
,
this
.
password
,
packet
.
loginTime
,
packet
.
loginIP
,
packet
.
tgtgtKey
,
packet
.
token0825
))
}
}
}
is
ServerLoginResponseFailedPacket
->
{
internal
var
loginFuture
:
CompletableFuture
<
LoginState
>?
=
null
MiraiLogger
error
"Login failed: "
+
packet
.
state
.
toString
()
return
}
is
ServerLoginResponseVerificationCodePacket
->
{
private
fun
restartSocket
()
{
//[token00BA]来源之一: 验证码
socket
?.
close
()
this
.
token00BA
=
packet
.
token00BA
socket
=
DatagramSocket
(
0
)
socket
!!
.
connect
(
InetSocketAddress
(
serverIP
,
8000
))
Thread
{
while
(
socket
!!
.
isConnected
)
{
val
packet
=
DatagramPacket
(
ByteArray
(
2048
),
2048
)
kotlin
.
runCatching
{
socket
!!
.
receive
(
packet
)
}
.
onSuccess
{
MiraiThreadPool
.
getInstance
().
submit
{
try
{
distributePacket
(
ServerPacket
.
ofByteArray
(
packet
.
data
.
removeZeroTail
()))
}
catch
(
e
:
Exception
)
{
e
.
printStackTrace
()
}
}
}.
onFailure
{
if
(
it
.
message
==
"Socket closed"
||
it
.
message
==
"socket closed"
)
{
return
@Thread
}
it
.
printStackTrace
()
}
with
(
MiraiServer
.
getInstance
().
parentFolder
+
"verifyCode.png"
)
{
ByteArrayInputStream
(
packet
.
verifyCode
).
transferTo
(
FileOutputStream
(
this
))
println
(
"验证码已写入到 "
+
this
.
path
)
}
}
}.
start
()
}
/**
* Start network and touch the server
*/
internal
fun
touch
(
serverAddress
:
String
):
CompletableFuture
<
LoginState
>
{
MiraiLogger
.
info
(
"Connecting server: $serverAddress"
)
this
.
loginFuture
=
CompletableFuture
()
socketHandler
.
serverIP
=
serverAddress
sendPacket
(
ClientTouchPacket
(
robot
.
account
.
qqNumber
,
socketHandler
.
serverIP
))
return
this
.
loginFuture
!!
}
/**
* Not async
*/
@ExperimentalUnsignedTypes
internal
fun
sendPacket
(
packet
:
ClientPacket
)
{
checkNotNull
(
socket
)
{
"socket closed"
}
if
(
packet
.
unknownBoolean
!=
null
&&
packet
.
unknownBoolean
!!
)
{
try
{
this
.
sequence
=
1
packet
.
encodePacket
()
sendPacket
(
ClientLoginVerificationCodePacket
(
this
.
number
,
this
.
token0825
,
this
.
sequence
,
this
.
token00BA
))
if
(
BeforePacketSendEvent
(
packet
).
broadcast
().
isCancelled
)
{
return
}
}
}
val
data
=
packet
.
toByteArray
()
socket
!!
.
send
(
DatagramPacket
(
data
,
data
.
size
))
MiraiLogger
info
"Packet sent: $packet"
is
ServerLoginResponseSuccessPacket
->
{
PacketSentEvent
(
packet
).
broadcast
()
this
.
_0828_rec_decr_key
=
packet
.
_0828_rec_decr_key
}
catch
(
e
:
Throwable
)
{
sendPacket
(
ClientSessionRequestPacket
(
this
.
number
,
this
.
serverIP
,
this
.
loginIP
,
this
.
md5_32
,
packet
.
token38
,
packet
.
token88
,
packet
.
encryptionKey
,
this
.
tlv0105
)
)
e
.
printStackTrace
(
)
}
}
}
//是ClientPasswordSubmissionPacket之后服务器回复的
@Suppress
(
"UNCHECKED_CAST"
)
is
ServerLoginResponseResendPacket
->
{
private
fun
<
P
:
ServerPacket
>
waitForPacket
(
packetClass
:
KClass
<
P
>,
timeoutMillis
:
Long
,
timeout
:
()
->
Unit
)
{
if
(
packet
.
tokenUnknown
!=
null
)
{
var
got
=
false
//this.token00BA = packet.token00BA!!
ServerPacketReceivedEvent
::
class
.
hookWhile
{
//println("token00BA changed!!! to " + token00BA.toUByteArray())
if
(
packetClass
.
isInstance
(
it
.
packet
))
{
}
got
=
true
if
(
packet
.
flag
==
ServerLoginResponseResendPacket
.
Flag
.
`
08
36
31
03
`
)
{
true
this
.
tgtgtKey
=
packet
.
tgtgtKey
sendPacket
(
ClientLoginResendPacket3104
(
this
.
number
,
this
.
password
,
this
.
loginTime
,
this
.
loginIP
,
this
.
tgtgtKey
!!
,
this
.
token0825
,
when
(
packet
.
tokenUnknown
!=
null
)
{
true
->
packet
.
tokenUnknown
!!
false
->
this
.
token00BA
},
packet
.
_0836_tlv0006_encr
))
}
else
{
}
else
{
sendPacket
(
ClientLoginResendPacket3106
(
false
this
.
number
,
this
.
password
,
this
.
loginTime
,
this
.
loginIP
,
this
.
tgtgtKey
!!
,
this
.
token0825
,
when
(
packet
.
tokenUnknown
!=
null
)
{
true
->
packet
.
tokenUnknown
!!
false
->
this
.
token00BA
},
packet
.
_0836_tlv0006_encr
))
}
}
}
}
is
ServerVerificationCodePacket
->
{
MiraiThreadPool
.
getInstance
().
submit
{
this
.
sequence
++
val
startingTime
=
System
.
currentTimeMillis
()
while
(!
got
)
{
if
(
System
.
currentTimeMillis
()
-
startingTime
>
timeoutMillis
)
{
timeout
.
invoke
()
return
@
submit
}
Thread
.
sleep
(
10
)
}
}
}
override
fun
close
()
{
this
.
socket
?.
close
()
if
(
this
.
loginFuture
!=
null
)
{
if
(!
this
.
loginFuture
!!
.
isDone
)
{
this
.
loginFuture
!!
.
cancel
(
true
)
}
this
.
loginFuture
=
null
}
}
}
}
is
ServerSessionKeyResponsePacket
->
{
this
.
sessionKey
=
packet
.
sessionKey
MiraiThreadPool
.
getInstance
().
scheduleWithFixedDelay
({
sendPacket
(
ClientHeartbeatPacket
(
this
.
number
,
this
.
sessionKey
))
},
90000
,
90000
,
TimeUnit
.
MILLISECONDS
)
RobotLoginSucceedEvent
(
robot
).
broadcast
()
MiraiThreadPool
.
getInstance
().
schedule
({
private
lateinit
var
sessionKey
:
ByteArray
ignoreMessage
=
false
},
2
,
TimeUnit
.
SECONDS
)
this
.
tlv0105
=
packet
.
tlv0105
abstract
inner
class
PacketHandler
:
Closeable
{
sendPacket
(
ClientLoginStatusPacket
(
this
.
number
,
this
.
sessionKey
,
ClientLoginStatus
.
ONLINE
))
abstract
fun
onPacketReceived
(
packet
:
ServerPacket
)
}
override
fun
close
()
{
is
ServerLoginSuccessPacket
->
{
}
sendPacket
(
ClientSKeyRequestPacket
(
this
.
number
,
this
.
sessionKey
))
}
/**
* Kind of [PacketHandler] that prints all packets received in the format of hex byte array.
*/
inner
class
DebugHandler
:
PacketHandler
()
{
override
fun
onPacketReceived
(
packet
:
ServerPacket
)
{
MiraiLogger
info
"Packet received: $packet"
if
(
packet
is
ServerEventPacket
)
{
sendPacket
(
ClientMessageResponsePacket
(
robot
.
account
.
qqNumber
,
packet
.
packetId
,
sessionKey
,
packet
.
eventIdentity
))
}
}
}
}
is
ServerSKeyResponsePacket
->
{
/**
this
.
sKey
=
packet
.
sKey
* 处理登录过程
this
.
cookies
=
"uin=o"
+
this
.
number
+
";skey="
+
this
.
sKey
+
";"
*/
inner
class
LoginHandler
:
PacketHandler
()
{
private
lateinit
var
token00BA
:
ByteArray
private
lateinit
var
token0825
:
ByteArray
private
var
loginTime
:
Int
=
0
private
lateinit
var
loginIP
:
String
private
var
tgtgtKey
:
ByteArray
?
=
null
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
)
}
MiraiThreadPool
.
getInstance
().
scheduleWithFixedDelay
({
/**
sendPacket
(
ClientSKeyRefreshmentRequestPacket
(
this
.
number
,
this
.
sessionKey
))
* 0828_decr_key
},
1800000
,
1800000
,
TimeUnit
.
MILLISECONDS
)
*/
private
lateinit
var
sessionResponseDecryptionKey
:
ByteArray
private
var
verificationCodeSequence
:
Int
=
0
//这两个验证码使用
private
var
verificationCodeCache
:
ByteArray
?
=
null
//每次包只发一部分验证码来
private
var
verificationCodeCacheCount
:
Int
=
1
//
private
lateinit
var
verificationToken
:
ByteArray
private
var
heartbeatFuture
:
ScheduledFuture
<
*
>?
=
null
private
var
sKeyRefresherFuture
:
ScheduledFuture
<
*
>?
=
null
override
fun
onPacketReceived
(
packet
:
ServerPacket
)
{
when
(
packet
)
{
is
ServerTouchResponsePacket
->
{
if
(
packet
.
serverIP
!=
null
)
{
//redirection
socketHandler
.
serverIP
=
packet
.
serverIP
!!
//connect(packet.serverIP!!)
sendPacket
(
ClientServerRedirectionPacket
(
packet
.
serverIP
!!
,
robot
.
account
.
qqNumber
))
}
else
{
//password submission
this
.
loginIP
=
packet
.
loginIP
this
.
loginTime
=
packet
.
loginTime
this
.
token0825
=
packet
.
token0825
this
.
tgtgtKey
=
packet
.
tgtgtKey
sendPacket
(
ClientPasswordSubmissionPacket
(
robot
.
account
.
qqNumber
,
robot
.
account
.
password
,
packet
.
loginTime
,
packet
.
loginIP
,
packet
.
tgtgtKey
,
packet
.
token0825
))
}
}
this
.
gtk
=
getGTK
(
sKey
)
is
ServerLoginResponseFailedPacket
->
{
sendPacket
(
ClientAccountInfoRequestPacket
(
this
.
number
,
this
.
sessionKey
))
socketHandler
.
loginFuture
!!
.
complete
(
packet
.
loginState
)
}
return
}
is
ServerHeartbeatResponsePacket
->
{
is
ServerLoginResponseVerificationCodeInitPacket
->
{
//[token00BA]来源之一: 验证码
this
.
token00BA
=
packet
.
token00BA
this
.
verificationCodeCache
=
packet
.
verifyCodePart1
}
if
(
packet
.
unknownBoolean
!=
null
&&
packet
.
unknownBoolean
!!
)
{
this
.
verificationCodeSequence
=
1
sendPacket
(
ClientVerificationCodeTransmissionRequestPacket
(
1
,
robot
.
account
.
qqNumber
,
this
.
token0825
,
this
.
verificationCodeSequence
,
this
.
token00BA
))
}
}
is
ServerAccountInfoResponsePacket
->
{
is
ServerVerificationCodeRepeatPacket
->
{
//todo 这个名字正确么
this
.
tgtgtKey
=
packet
.
tgtgtKeyUpdate
this
.
token00BA
=
packet
.
token00BA
sendPacket
(
ClientLoginResendPacket3105
(
robot
.
account
.
qqNumber
,
robot
.
account
.
password
,
this
.
loginTime
,
this
.
loginIP
,
this
.
tgtgtKey
!!
,
this
.
token0825
,
this
.
token00BA
))
}
}
is
ServerVerificationCodeTransmissionPacket
->
{
this
.
verificationCodeSequence
++
this
.
verificationCodeCache
=
this
.
verificationCodeCache
!!
+
packet
.
verificationCodePartN
this
.
verificationToken
=
packet
.
verificationToken
this
.
verificationCodeCacheCount
++
is
ServerFriendMessageEventPacket
->
{
this
.
token00BA
=
packet
.
token00BA
if
(
ignoreMessage
)
{
return
//todo 看易语言 count 和 sequence 是怎样变化的
if
(
packet
.
transmissionCompleted
)
{
this
.
verificationCodeCache
TODO
(
"验证码好了"
)
}
else
{
sendPacket
(
ClientVerificationCodeTransmissionRequestPacket
(
this
.
verificationCodeCacheCount
,
robot
.
account
.
qqNumber
,
this
.
token0825
,
this
.
verificationCodeSequence
,
this
.
token00BA
))
}
}
}
FriendMessageEvent
(
this
.
robot
,
this
.
robot
.
getQQ
(
packet
.
qq
),
packet
.
message
)
is
ServerLoginResponseSuccessPacket
->
{
}
this
.
sessionResponseDecryptionKey
=
packet
.
sessionResponseDecryptionKey
sendPacket
(
ClientSessionRequestPacket
(
robot
.
account
.
qqNumber
,
socketHandler
.
serverIP
,
packet
.
token38
,
packet
.
token88
,
packet
.
encryptionKey
,
this
.
tlv0105
))
}
is
ServerGroupMessageEventPacket
->
{
//是ClientPasswordSubmissionPacket之后服务器回复的
//group message
is
ServerLoginResponseResendPacket
->
{
if
(
packet
.
message
==
"牛逼"
)
{
//if (packet.tokenUnknown != null) {
sendPacket
(
ClientSendGroupMessagePacket
(
Group
.
groupNumberToId
(
packet
.
groupNumber
),
this
.
number
,
this
.
sessionKey
,
"牛逼!"
))
//this.token00BA = packet.token00BA!!
//println("token00BA changed!!! to " + token00BA.toUByteArray())
//}
if
(
packet
.
flag
==
ServerLoginResponseResendPacket
.
Flag
.
`
08
36
31
03
`
)
{
this
.
tgtgtKey
=
packet
.
tgtgtKey
sendPacket
(
ClientLoginResendPacket3104
(
robot
.
account
.
qqNumber
,
robot
.
account
.
password
,
this
.
loginTime
,
this
.
loginIP
,
this
.
tgtgtKey
!!
,
this
.
token0825
,
when
(
packet
.
tokenUnknown
!=
null
)
{
true
->
packet
.
tokenUnknown
!!
false
->
this
.
token00BA
},
packet
.
_0836_tlv0006_encr
))
}
else
{
sendPacket
(
ClientLoginResendPacket3106
(
robot
.
account
.
qqNumber
,
robot
.
account
.
password
,
this
.
loginTime
,
this
.
loginIP
,
this
.
tgtgtKey
!!
,
this
.
token0825
,
when
(
packet
.
tokenUnknown
!=
null
)
{
true
->
packet
.
tokenUnknown
!!
false
->
this
.
token00BA
},
packet
.
_0836_tlv0006_encr
))
}
}
}
//todo
is
ServerSessionKeyResponsePacket
->
{
//GroupMessageEvent(this.robot, this.robot.getGroup(packet.groupNumber), this.robot.getQQ(packet.qq), packet.message)
sessionKey
=
packet
.
sessionKey
}
heartbeatFuture
=
MiraiThreadPool
.
getInstance
().
scheduleWithFixedDelay
({
sendPacket
(
ClientHeartbeatPacket
(
robot
.
account
.
qqNumber
,
sessionKey
))
},
90000
,
90000
,
TimeUnit
.
MILLISECONDS
)
is
UnknownServerEventPacket
->
{
RobotLoginSucceedEvent
(
robot
).
broadcast
()
//unknown message event
}
is
UnknownServerPacket
->
{
//登录成功后会收到大量上次的消息, 忽略掉
MiraiThreadPool
.
getInstance
().
schedule
({
(
packetHandlers
[
MessageHandler
::
class
]
as
MessageHandler
).
ignoreMessage
=
false
},
2
,
TimeUnit
.
SECONDS
)
}
this
.
tlv0105
=
packet
.
tlv0105
sendPacket
(
ClientChangeOnlineStatusPacket
(
robot
.
account
.
qqNumber
,
sessionKey
,
ClientLoginStatus
.
ONLINE
))
}
is
ServerGroupUploadFileEventPacket
->
{
is
ServerLoginSuccessPacket
->
{
socketHandler
.
loginFuture
!!
.
complete
(
LoginState
.
SUCCEED
)
sendPacket
(
ClientSKeyRequestPacket
(
robot
.
account
.
qqNumber
,
sessionKey
))
}
is
ServerSKeyResponsePacket
->
{
val
actionHandler
=
packetHandlers
[
ActionHandler
::
class
]
as
ActionHandler
actionHandler
.
sKey
=
packet
.
sKey
actionHandler
.
cookies
=
"uin=o"
+
robot
.
account
.
qqNumber
+
";skey="
+
actionHandler
.
sKey
+
";"
sKeyRefresherFuture
=
MiraiThreadPool
.
getInstance
().
scheduleWithFixedDelay
({
sendPacket
(
ClientSKeyRefreshmentRequestPacket
(
robot
.
account
.
qqNumber
,
sessionKey
))
},
1800000
,
1800000
,
TimeUnit
.
MILLISECONDS
)
actionHandler
.
gtk
=
getGTK
(
actionHandler
.
sKey
)
sendPacket
(
ClientAccountInfoRequestPacket
(
robot
.
account
.
qqNumber
,
sessionKey
))
}
is
ServerEventPacket
.
Raw
->
distributePacket
(
packet
.
distribute
())
is
ServerVerificationCodePacket
.
Encrypted
->
distributePacket
(
packet
.
decrypt
())
is
ServerLoginResponseVerificationCodeInitPacket
.
Encrypted
->
distributePacket
(
packet
.
decrypt
())
is
ServerLoginResponseResendPacket
.
Encrypted
->
distributePacket
(
packet
.
decrypt
(
this
.
tgtgtKey
!!
))
is
ServerLoginResponseSuccessPacket
.
Encrypted
->
distributePacket
(
packet
.
decrypt
(
this
.
tgtgtKey
!!
))
is
ServerSessionKeyResponsePacket
.
Encrypted
->
distributePacket
(
packet
.
decrypt
(
this
.
sessionResponseDecryptionKey
))
is
ServerTouchResponsePacket
.
Encrypted
->
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
UnknownServerPacket
->
{
//ignored
}
else
->
{
}
}
}
}
is
ServerMessageEventPacketRaw
->
onPacketReceived
(
packet
.
analyze
())
override
fun
close
()
{
this
.
verificationCodeCache
=
null
this
.
tgtgtKey
=
null
is
ServerVerificationCodePacketEncrypted
->
onPacketReceived
(
packet
.
decrypt
(
this
.
token00BA
))
this
.
heartbeatFuture
?.
cancel
(
true
)
is
ServerLoginResponseVerificationCodePacketEncrypted
->
onPacketReceived
(
packet
.
decrypt
())
this
.
sKeyRefresherFuture
?.
cancel
(
true
)
is
ServerLoginResponseResendPacketEncrypted
->
onPacketReceived
(
packet
.
decrypt
(
this
.
tgtgtKey
!!
))
is
ServerLoginResponseSuccessPacketEncrypted
->
onPacketReceived
(
packet
.
decrypt
(
this
.
tgtgtKey
!!
))
is
ServerSessionKeyResponsePacketEncrypted
->
onPacketReceived
(
packet
.
decrypt
(
this
.
_0828_rec_decr_key
))
is
ServerTouchResponsePacketEncrypted
->
onPacketReceived
(
packet
.
decrypt
())
is
ServerSKeyResponsePacketEncrypted
->
onPacketReceived
(
packet
.
decrypt
(
this
.
sessionKey
))
is
ServerAccountInfoResponsePacketEncrypted
->
onPacketReceived
(
packet
.
decrypt
(
this
.
sessionKey
))
is
ServerMessageEventPacketRawEncoded
->
onPacketReceived
(
packet
.
decrypt
(
this
.
sessionKey
))
this
.
heartbeatFuture
=
null
this
.
sKeyRefresherFuture
=
null
}
}
is
ServerSendFriendMessageResponsePacket
,
/**
is
ServerSendGroupMessageResponsePacket
->
{
* 处理消息事件, 承担消息发送任务.
*/
inner
class
MessageHandler
:
PacketHandler
()
{
internal
var
ignoreMessage
:
Boolean
=
false
override
fun
onPacketReceived
(
packet
:
ServerPacket
)
{
when
(
packet
)
{
is
ServerGroupUploadFileEventPacket
->
{
//todo
}
is
ServerFriendMessageEventPacket
->
{
if
(
ignoreMessage
)
{
return
}
FriendMessageEvent
(
robot
,
robot
.
contacts
.
getQQ
(
packet
.
qq
),
packet
.
message
)
}
is
ServerGroupMessageEventPacket
->
{
//todo message chain
//GroupMessageEvent(this.robot, robot.contacts.getGroupByNumber(packet.groupNumber), robot.contacts.getQQ(packet.qq), packet.message)
}
is
UnknownServerEventPacket
,
is
ServerSendFriendMessageResponsePacket
,
is
ServerSendGroupMessageResponsePacket
->
{
//ignored
}
else
->
{
//ignored
}
}
}
}
else
->
throw
IllegalArgumentException
(
packet
.
toString
())
fun
sendFriendMessage
(
qq
:
QQ
,
message
:
Message
)
{
TODO
()
//sendPacket(ClientSendFriendMessagePacket(robot.account.qqNumber, qq.number, sessionKey, message))
}
}
fun
sendGroupMessage
(
group
:
Group
,
message
:
Message
):
Unit
{
TODO
()
//sendPacket(ClientSendGroupMessagePacket(group.groupId, robot.account.qqNumber, sessionKey, message))
}
}
}
@ExperimentalUnsignedTypes
/**
fun
sendPacket
(
packet
:
ClientPacket
)
{
* 动作: 获取好友列表, 点赞, 踢人等.
MiraiThreadPool
.
getInstance
().
submit
{
* 处理动作事件, 承担动作任务.
try
{
*/
packet
.
encode
()
inner
class
ActionHandler
:
PacketHandler
()
{
packet
.
writeHex
(
Protocol
.
tail
)
internal
lateinit
var
cookies
:
String
internal
lateinit
var
sKey
:
String
internal
var
gtk
:
Int
=
0
override
fun
onPacketReceived
(
packet
:
ServerPacket
)
{
}
override
fun
close
()
{
val
data
=
packet
.
toByteArray
()
socket
.
send
(
DatagramPacket
(
data
,
data
.
size
))
MiraiLogger
info
"Packet sent: $packet"
}
catch
(
e
:
Throwable
)
{
e
.
printStackTrace
()
}
}
}
}
}
}
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/network/packet/AccountInfo.kt
View file @
93dc8e58
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.TEA
Cryptor
import
net.mamoe.mirai.utils.TEA
import
java.io.DataInputStream
import
java.io.DataInputStream
/**
/**
...
@@ -12,13 +12,14 @@ import java.io.DataInputStream
...
@@ -12,13 +12,14 @@ import java.io.DataInputStream
@ExperimentalUnsignedTypes
@ExperimentalUnsignedTypes
@PacketId
(
"00 5C"
)
@PacketId
(
"00 5C"
)
class
ClientAccountInfoRequestPacket
(
class
ClientAccountInfoRequestPacket
(
private
val
qq
:
Int
,
private
val
qq
:
Long
,
private
val
sessionKey
:
ByteArray
private
val
sessionKey
:
ByteArray
)
:
ClientPacket
()
{
)
:
ClientPacket
()
{
override
fun
encode
()
{
override
fun
encode
()
{
this
.
writeRandom
(
2
)
//part of packet id
this
.
writeRandom
(
2
)
//part of packet id
this
.
writeQQ
(
qq
)
this
.
writeQQ
(
qq
)
this
.
writeHex
(
Protocol
.
_fixVer
)
this
.
writeHex
(
Protocol
.
fixVer2
)
this
.
encryptAndWrite
(
sessionKey
)
{
this
.
encryptAndWrite
(
sessionKey
)
{
it
.
writeByte
(
0
x88
)
it
.
writeByte
(
0
x88
)
it
.
writeQQ
(
qq
)
it
.
writeQQ
(
qq
)
...
@@ -27,6 +28,7 @@ class ClientAccountInfoRequestPacket(
...
@@ -27,6 +28,7 @@ class ClientAccountInfoRequestPacket(
}
}
}
}
@PacketId
(
"00 5C"
)
class
ServerAccountInfoResponsePacket
(
input
:
DataInputStream
)
:
ServerPacket
(
input
)
{
class
ServerAccountInfoResponsePacket
(
input
:
DataInputStream
)
:
ServerPacket
(
input
)
{
//等级
//等级
//升级剩余活跃天数
//升级剩余活跃天数
...
@@ -34,16 +36,13 @@ class ServerAccountInfoResponsePacket(input: DataInputStream) : ServerPacket(inp
...
@@ -34,16 +36,13 @@ class ServerAccountInfoResponsePacket(input: DataInputStream) : ServerPacket(inp
override
fun
decode
()
{
override
fun
decode
()
{
}
}
}
class
ServerAccountInfoResponsePacketEncrypted
(
inputStream
:
DataInputStream
)
:
ServerPacket
(
inputStream
)
{
override
fun
decode
()
{
}
fun
decrypt
(
sessionKey
:
ByteArray
):
ServerAccountInfoResponsePacket
{
@PacketId
(
"00 5C"
)
this
.
input
goto
14
class
Encrypted
(
inputStream
:
DataInputStream
)
:
ServerPacket
(
inputStream
)
{
val
data
=
this
.
input
.
readAllBytes
().
let
{
it
.
copyOfRange
(
0
,
it
.
size
-
1
)
}
fun
decrypt
(
sessionKey
:
ByteArray
):
ServerAccountInfoResponsePacket
{
return
ServerAccountInfoResponsePacket
(
TEACryptor
.
decrypt
(
data
,
sessionKey
).
dataInputStream
());
this
.
input
goto
14
val
data
=
this
.
input
.
readAllBytes
().
let
{
it
.
copyOfRange
(
0
,
it
.
size
-
1
)
}
return
ServerAccountInfoResponsePacket
(
TEA
.
decrypt
(
data
,
sessionKey
).
dataInputStream
());
}
}
}
}
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/network/packet/ClientPacket.kt
View file @
93dc8e58
...
@@ -2,7 +2,6 @@ package net.mamoe.mirai.network.packet
...
@@ -2,7 +2,6 @@ package net.mamoe.mirai.network.packet
import
lombok.Getter
import
lombok.Getter
import
net.mamoe.mirai.network.Protocol
import
net.mamoe.mirai.network.Protocol
import
net.mamoe.mirai.util.TestedSuccessfully
import
net.mamoe.mirai.utils.*
import
net.mamoe.mirai.utils.*
import
java.io.DataOutputStream
import
java.io.DataOutputStream
import
java.io.IOException
import
java.io.IOException
...
@@ -15,11 +14,13 @@ import java.security.MessageDigest
...
@@ -15,11 +14,13 @@ import java.security.MessageDigest
@ExperimentalUnsignedTypes
@ExperimentalUnsignedTypes
abstract
class
ClientPacket
:
ByteArrayDataOutputStream
(),
Packet
{
abstract
class
ClientPacket
:
ByteArrayDataOutputStream
(),
Packet
{
@Getter
@Getter
val
packageId
:
String
val
idHex
:
String
var
encoded
:
Boolean
=
false
init
{
init
{
val
annotation
=
this
.
javaClass
.
getAnnotation
(
PacketId
::
class
.
java
)
val
annotation
=
this
.
javaClass
.
getAnnotation
(
PacketId
::
class
.
java
)
packageId
=
annotation
.
value
idHex
=
annotation
.
value
try
{
try
{
this
.
writeHex
(
Protocol
.
head
)
this
.
writeHex
(
Protocol
.
head
)
...
@@ -33,7 +34,7 @@ abstract class ClientPacket : ByteArrayDataOutputStream(), Packet {
...
@@ -33,7 +34,7 @@ abstract class ClientPacket : ByteArrayDataOutputStream(), Packet {
@Throws
(
IOException
::
class
)
@Throws
(
IOException
::
class
)
fun
writePacketId
()
{
fun
writePacketId
()
{
this
.
writeHex
(
this
@ClientPacket
.
packageId
)
this
.
writeHex
(
this
@ClientPacket
.
idHex
)
}
}
/**
/**
...
@@ -43,11 +44,19 @@ abstract class ClientPacket : ByteArrayDataOutputStream(), Packet {
...
@@ -43,11 +44,19 @@ abstract class ClientPacket : ByteArrayDataOutputStream(), Packet {
* Before sending the packet, a [tail][Protocol.tail] will be added.
* Before sending the packet, a [tail][Protocol.tail] will be added.
*/
*/
@Throws
(
IOException
::
class
)
@Throws
(
IOException
::
class
)
abstract
fun
encode
()
protected
abstract
fun
encode
()
fun
encodePacket
()
{
if
(
encoded
)
{
return
}
encode
()
writeHex
(
Protocol
.
tail
)
}
@Throws
(
IOException
::
class
)
@Throws
(
IOException
::
class
)
fun
encodeToByteArray
():
ByteArray
{
fun
encodeToByteArray
():
ByteArray
{
encode
()
encode
Packet
()
return
toByteArray
()
return
toByteArray
()
}
}
...
@@ -89,73 +98,52 @@ fun DataOutputStream.writeHex(hex: String) {
...
@@ -89,73 +98,52 @@ fun DataOutputStream.writeHex(hex: String) {
}
}
}
}
@ExperimentalUnsignedTypes
fun
DataOutputStream
.
writeVarInt
(
dec
:
UInt
)
{
/*.判断开始 (n < 256)
返回 (取文本右边 (“0” + 取十六进制文本 (n), 2))
.判断 (n ≥ 256)
hex = 取文本右边 (“0” + 取十六进制文本 (n), 4)
返回 (取文本左边 (hex, 2) + “ ” + 取文本右边 (hex, 2))
.默认
返回 (“”)
.判断结束*/
when
{
dec
<
256
u
->
this
.
writeByte
(
dec
.
toByte
().
toInt
())
//drop other bits
dec
>
256
u
->
this
.
writeShort
(
dec
.
toShort
().
toInt
())
else
->
throw
IllegalArgumentException
(
dec
.
toString
())
}
}
fun
DataOutputStream
.
encryptAndWrite
(
byteArray
:
ByteArray
,
key
:
ByteArray
)
{
fun
DataOutputStream
.
encryptAndWrite
(
byteArray
:
ByteArray
,
key
:
ByteArray
)
{
this
.
write
(
TEA
Cryptor
.
encrypt
(
byteArray
,
key
))
this
.
write
(
TEA
.
encrypt
(
byteArray
,
key
))
}
}
fun
DataOutputStream
.
encryptAndWrite
(
byteArray
:
ByteArray
,
cryptor
:
TEA
Cryptor
)
{
fun
DataOutputStream
.
encryptAndWrite
(
byteArray
:
ByteArray
,
cryptor
:
TEA
)
{
this
.
write
(
cryptor
.
encrypt
(
byteArray
))
this
.
write
(
cryptor
.
encrypt
(
byteArray
))
}
}
fun
DataOutputStream
.
encryptAndWrite
(
key
:
ByteArray
,
encoder
:
(
ByteArrayDataOutputStream
)
->
Unit
)
{
fun
DataOutputStream
.
encryptAndWrite
(
key
:
ByteArray
,
encoder
:
(
ByteArrayDataOutputStream
)
->
Unit
)
{
this
.
write
(
TEA
Cryptor
.
encrypt
(
ByteArrayDataOutputStream
().
let
{
encoder
(
it
);
it
.
toByteArray
()
},
key
))
this
.
write
(
TEA
.
encrypt
(
ByteArrayDataOutputStream
().
let
{
encoder
(
it
);
it
.
toByteArray
()
},
key
))
}
}
fun
DataOutputStream
.
encryptAndWrite
(
cryptor
:
TEACryptor
,
encoder
:
(
ByteArrayDataOutputStream
)
->
Unit
)
{
@ExperimentalUnsignedTypes
fun
DataOutputStream
.
encryptAndWrite
(
keyHex
:
String
,
encoder
:
(
ByteArrayDataOutputStream
)
->
Unit
)
{
this
.
encryptAndWrite
(
keyHex
.
hexToBytes
(),
encoder
)
}
fun
DataOutputStream
.
encryptAndWrite
(
cryptor
:
TEA
,
encoder
:
(
ByteArrayDataOutputStream
)
->
Unit
)
{
this
.
write
(
cryptor
.
encrypt
(
ByteArrayDataOutputStream
().
let
{
encoder
(
it
);
it
.
toByteArray
()
}))
this
.
write
(
cryptor
.
encrypt
(
ByteArrayDataOutputStream
().
let
{
encoder
(
it
);
it
.
toByteArray
()
}))
}
}
@ExperimentalUnsignedTypes
@ExperimentalUnsignedTypes
@Throws
(
IOException
::
class
)
@Throws
(
IOException
::
class
)
fun
DataOutputStream
.
writeTLV0006
(
qq
:
Int
,
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
{
it
.
write
Hex
(
"12 12 12 12"
)
//it.writeRandom(4) todo
it
.
write
Random
(
4
)
it
.
writeHex
(
"00 02"
)
it
.
writeHex
(
"00 02"
)
it
.
writeQQ
(
qq
)
it
.
writeQQ
(
qq
)
it
.
writeHex
(
Protocol
.
_0825data2
)
it
.
writeHex
(
Protocol
.
constantData1
)
it
.
writeHex
(
"00 00 01"
)
it
.
writeHex
(
"00 00 01"
)
val
md5_1
=
md5
(
password
);
val
firstMD5
=
md5
(
password
)
val
md5_2
=
md5
(
md5_1
+
"00 00 00 00"
.
hexToBytes
()
+
qq
.
toByteArray
())
val
secondMD5
=
md5
(
firstMD5
+
"00 00 00 00"
.
hexToBytes
()
+
qq
.
toUInt
().
toByteArray
())
println
(
md5_1
.
toUByteArray
().
toUHexString
())
it
.
write
(
firstMD5
)
println
(
md5_2
.
toUByteArray
().
toUHexString
())
it
.
write
(
md5_1
)
it
.
writeInt
(
loginTime
)
it
.
writeInt
(
loginTime
)
it
.
writeByte
(
0
)
;
it
.
writeByte
(
0
)
it
.
writeZero
(
4
*
3
)
it
.
writeZero
(
4
*
3
)
it
.
writeIP
(
loginIP
)
it
.
writeIP
(
loginIP
)
it
.
writeZero
(
8
)
it
.
writeZero
(
8
)
it
.
writeHex
(
"00 10"
)
it
.
writeHex
(
"00 10"
)
it
.
writeHex
(
"15 74 C4 89 85 7A 19 F5 5E A9 C9 A3 5E 8A 5A 9B"
)
it
.
writeHex
(
"15 74 C4 89 85 7A 19 F5 5E A9 C9 A3 5E 8A 5A 9B"
)
it
.
write
(
tgtgtKey
)
it
.
write
(
tgtgtKey
)
println
()
this
.
write
(
TEA
.
encrypt
(
it
.
toByteArray
(),
secondMD5
))
println
(
it
.
toByteArray
().
toUHexString
())
this
.
write
(
TEACryptor
.
encrypt
(
it
.
toByteArray
(),
md5_2
))
}
}
}
}
fun
main
()
{
}
/*
/*
@ExperimentalUnsignedTypes
@ExperimentalUnsignedTypes
fun main() {
fun main() {
...
@@ -164,7 +152,7 @@ fun main() {
...
@@ -164,7 +152,7 @@ fun main() {
@ExperimentalUnsignedTypes
@ExperimentalUnsignedTypes
@TestedSuccessfully
@TestedSuccessfully
fun
DataOutputStream
.
writeCRC32
()
=
writeCRC32
(
getRandom
Ke
y
(
16
))
fun
DataOutputStream
.
writeCRC32
()
=
writeCRC32
(
getRandom
ByteArra
y
(
16
))
@ExperimentalUnsignedTypes
@ExperimentalUnsignedTypes
...
@@ -193,6 +181,17 @@ fun Int.toByteArray(): ByteArray = byteArrayOf(
...
@@ -193,6 +181,17 @@ fun Int.toByteArray(): ByteArray = byteArrayOf(
(
this
.
ushr
(
0
)
and
0
xFF
).
toByte
()
(
this
.
ushr
(
0
)
and
0
xFF
).
toByte
()
)
)
/**
* 255u -> 00 00 00 FF
*/
@ExperimentalUnsignedTypes
fun
UInt
.
toByteArray
():
ByteArray
=
byteArrayOf
(
(
this
.
shr
(
24
)
and
255
u
).
toByte
(),
(
this
.
shr
(
16
)
and
255
u
).
toByte
(),
(
this
.
shr
(
8
)
and
255
u
).
toByte
(),
(
this
.
shr
(
0
)
and
255
u
).
toByte
()
)
/**
/**
* 255 -> FF 00 00 00
* 255 -> FF 00 00 00
*/
*/
...
@@ -204,7 +203,7 @@ fun Int.toLByteArray(): ByteArray = byteArrayOf(
...
@@ -204,7 +203,7 @@ fun Int.toLByteArray(): ByteArray = byteArrayOf(
)
)
@ExperimentalUnsignedTypes
@ExperimentalUnsignedTypes
fun
Int
.
toHexString
(
separator
:
String
=
" "
):
String
=
this
.
toByteArray
().
toUByteArray
().
toUHexString
(
separator
)
;
fun
Int
.
toHexString
(
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
())
...
@@ -225,7 +224,14 @@ fun DataOutputStream.writeRandom(length: Int) {
...
@@ -225,7 +224,14 @@ fun DataOutputStream.writeRandom(length: Int) {
}
}
}
}
@ExperimentalUnsignedTypes
@Throws
(
IOException
::
class
)
fun
DataOutputStream
.
writeQQ
(
qq
:
Long
)
{
this
.
write
(
qq
.
toUInt
().
toByteArray
())
}
@ExperimentalUnsignedTypes
@Throws
(
IOException
::
class
)
@Throws
(
IOException
::
class
)
fun
DataOutputStream
.
write
QQ
(
qq
:
Int
)
{
fun
DataOutputStream
.
write
Group
(
groupIdOrGroupNumber
:
Long
)
{
this
.
write
Int
(
qq
)
this
.
write
(
groupIdOrGroupNumber
.
toUInt
().
toByteArray
()
)
}
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/network/packet/Heartbeat.kt
View file @
93dc8e58
...
@@ -10,7 +10,7 @@ import java.io.IOException
...
@@ -10,7 +10,7 @@ import java.io.IOException
@ExperimentalUnsignedTypes
@ExperimentalUnsignedTypes
@PacketId
(
"00 58"
)
@PacketId
(
"00 58"
)
class
ClientHeartbeatPacket
(
class
ClientHeartbeatPacket
(
private
val
qq
:
Int
,
private
val
qq
:
Long
,
private
val
sessionKey
:
ByteArray
private
val
sessionKey
:
ByteArray
)
:
ClientPacket
()
{
)
:
ClientPacket
()
{
@Throws
(
IOException
::
class
)
@Throws
(
IOException
::
class
)
...
@@ -24,8 +24,4 @@ class ClientHeartbeatPacket(
...
@@ -24,8 +24,4 @@ class ClientHeartbeatPacket(
}
}
}
}
class
ServerHeartbeatResponsePacket
(
input
:
DataInputStream
)
:
ServerPacket
(
input
)
{
class
ServerHeartbeatResponsePacket
(
input
:
DataInputStream
)
:
ServerPacket
(
input
)
override
fun
decode
()
{
\ No newline at end of file
}
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/network/packet/MessageEvent.kt
deleted
100644 → 0
View file @
5b07f09d
package
net.mamoe.mirai.network.packet
import
net.mamoe.mirai.network.Protocol
import
net.mamoe.mirai.utils.TEACryptor
import
net.mamoe.mirai.utils.toUHexString
import
java.io.DataInputStream
/**
* 告知服务器已经收到数据
*/
@PacketId
(
""
)
//随后写入
@ExperimentalUnsignedTypes
class
ClientMessageResponsePacket
(
private
val
qq
:
Int
,
private
val
packetIdFromServer
:
ByteArray
,
private
val
sessionKey
:
ByteArray
,
private
val
eventIdentity
:
ByteArray
)
:
ClientPacket
()
{
override
fun
encode
()
{
this
.
write
(
packetIdFromServer
)
this
.
writeQQ
(
qq
)
this
.
writeHex
(
Protocol
.
_fixVer
)
this
.
encryptAndWrite
(
sessionKey
)
{
it
.
write
(
eventIdentity
)
}
}
}
/**
* 群聊和好友消息分发
*/
@PacketId
(
"00 17"
)
class
ServerMessageEventPacketRaw
(
input
:
DataInputStream
,
private
val
dataLength
:
Int
,
private
val
packetId
:
ByteArray
)
:
ServerPacket
(
input
)
{
lateinit
var
type
:
ByteArray
;
lateinit
var
eventIdentity
:
ByteArray
;
override
fun
decode
()
{
eventIdentity
=
this
.
input
.
readNBytes
(
16
)
type
=
this
.
input
.
goto
(
18
).
readNBytes
(
2
)
}
fun
analyze
():
ServerEventPacket
=
when
(
val
typeHex
=
type
.
toUHexString
())
{
"00 C4"
->
{
if
(
this
.
input
.
goto
(
33
).
readBoolean
())
{
ServerAndroidOnlineEventPacket
(
this
.
input
,
packetId
,
eventIdentity
)
}
else
{
ServerAndroidOfflineEventPacket
(
this
.
input
,
packetId
,
eventIdentity
)
}
}
"00 2D"
->
ServerGroupUploadFileEventPacket
(
this
.
input
,
packetId
,
eventIdentity
)
"00 52"
->
ServerGroupMessageEventPacket
(
this
.
input
,
packetId
,
eventIdentity
)
"00 A6"
->
ServerFriendMessageEventPacket
(
this
.
input
,
packetId
,
eventIdentity
)
//"02 10", "00 12" -> ServerUnknownEventPacket(this.input, packetId, eventIdentity)
else
->
UnknownServerEventPacket
(
this
.
input
,
packetId
,
eventIdentity
)
}
}
class
UnknownServerEventPacket
(
input
:
DataInputStream
,
packetId
:
ByteArray
,
eventIdentity
:
ByteArray
)
:
ServerEventPacket
(
input
,
packetId
,
eventIdentity
)
@PacketId
(
"00 17"
)
class
ServerMessageEventPacketRawEncoded
(
input
:
DataInputStream
,
val
packetId
:
ByteArray
)
:
ServerPacket
(
input
)
{
override
fun
decode
()
{
}
fun
decrypt
(
sessionKey
:
ByteArray
):
ServerMessageEventPacketRaw
{
this
.
input
goto
14
val
data
=
this
.
input
.
readAllBytes
().
let
{
it
.
copyOfRange
(
0
,
it
.
size
-
1
)
}
return
ServerMessageEventPacketRaw
(
TEACryptor
.
decrypt
(
data
,
sessionKey
).
dataInputStream
(),
data
.
size
,
packetId
);
}
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/network/packet/SKey.kt
View file @
93dc8e58
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.TEA
Cryptor
import
net.mamoe.mirai.utils.TEA
import
java.io.DataInputStream
import
java.io.DataInputStream
...
@@ -11,14 +11,14 @@ import java.io.DataInputStream
...
@@ -11,14 +11,14 @@ import java.io.DataInputStream
@ExperimentalUnsignedTypes
@ExperimentalUnsignedTypes
@PacketId
(
"00 1D"
)
@PacketId
(
"00 1D"
)
class
ClientSKeyRequestPacket
(
class
ClientSKeyRequestPacket
(
private
val
qq
:
Int
,
private
val
qq
:
Long
,
private
val
sessionKey
:
ByteArray
private
val
sessionKey
:
ByteArray
)
:
ClientPacket
()
{
)
:
ClientPacket
()
{
override
fun
encode
()
{
override
fun
encode
()
{
this
.
writeRandom
(
2
)
//part of packet id
this
.
writeRandom
(
2
)
//part of packet id
this
.
writeQQ
(
qq
)
this
.
writeQQ
(
qq
)
this
.
writeHex
(
Protocol
.
_fixVer
)
this
.
writeHex
(
Protocol
.
fixVer2
)
this
.
encryptAndWrite
(
sessionKey
)
{
this
.
encryptAndWrite
(
sessionKey
)
{
it
.
writeHex
(
"33 00 05 00 08 74 2E 71 71 2E 63 6F 6D 00 0A 71 75 6E 2E 71 71 2E 63 6F 6D 00 0C 71 7A 6F 6E 65 2E 71 71 2E 63 6F 6D 00 0C 6A 75 62 61 6F 2E 71 71 2E 63 6F 6D 00 09 6B 65 2E 71 71 2E 63 6F 6D"
)
it
.
writeHex
(
"33 00 05 00 08 74 2E 71 71 2E 63 6F 6D 00 0A 71 75 6E 2E 71 71 2E 63 6F 6D 00 0C 71 7A 6F 6E 65 2E 71 71 2E 63 6F 6D 00 0C 6A 75 62 61 6F 2E 71 71 2E 63 6F 6D 00 09 6B 65 2E 71 71 2E 63 6F 6D"
)
}
}
...
@@ -31,7 +31,7 @@ class ClientSKeyRequestPacket(
...
@@ -31,7 +31,7 @@ class ClientSKeyRequestPacket(
@PacketId
(
"00 1D"
)
@PacketId
(
"00 1D"
)
@ExperimentalUnsignedTypes
@ExperimentalUnsignedTypes
class
ClientSKeyRefreshmentRequestPacket
(
class
ClientSKeyRefreshmentRequestPacket
(
private
val
qq
:
Int
,
private
val
qq
:
Long
,
private
val
sessionKey
:
ByteArray
private
val
sessionKey
:
ByteArray
)
:
ClientPacket
()
{
)
:
ClientPacket
()
{
override
fun
encode
()
{
override
fun
encode
()
{
...
@@ -52,19 +52,13 @@ class ServerSKeyResponsePacket(input: DataInputStream) : ServerPacket(input) {
...
@@ -52,19 +52,13 @@ class ServerSKeyResponsePacket(input: DataInputStream) : ServerPacket(input) {
override
fun
decode
()
{
override
fun
decode
()
{
this
.
sKey
=
String
(
this
.
input
.
goto
(
4
).
readNBytes
(
10
))
this
.
sKey
=
String
(
this
.
input
.
goto
(
4
).
readNBytes
(
10
))
}
}
}
/**
* @author Him188moe
*/
class
ServerSKeyResponsePacketEncrypted
(
inputStream
:
DataInputStream
)
:
ServerPacket
(
inputStream
)
{
override
fun
decode
()
{
}
fun
decrypt
(
sessionKey
:
ByteArray
):
ServerSKeyResponsePacket
{
class
Encrypted
(
inputStream
:
DataInputStream
)
:
ServerPacket
(
inputStream
)
{
this
.
input
goto
14
fun
decrypt
(
sessionKey
:
ByteArray
):
ServerSKeyResponsePacket
{
val
data
=
this
.
input
.
readAllBytes
().
let
{
it
.
copyOfRange
(
0
,
it
.
size
-
1
)
}
this
.
input
goto
14
return
ServerSKeyResponsePacket
(
TEACryptor
.
decrypt
(
data
,
sessionKey
).
dataInputStream
());
val
data
=
this
.
input
.
readAllBytes
().
let
{
it
.
copyOfRange
(
0
,
it
.
size
-
1
)
}
return
ServerSKeyResponsePacket
(
TEA
.
decrypt
(
data
,
sessionKey
).
dataInputStream
());
}
}
}
}
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerEvent.kt
View file @
93dc8e58
...
@@ -2,28 +2,65 @@ package net.mamoe.mirai.network.packet
...
@@ -2,28 +2,65 @@ package net.mamoe.mirai.network.packet
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.network.Protocol
import
net.mamoe.mirai.utils.MiraiLogger
import
net.mamoe.mirai.utils.toUHexString
import
net.mamoe.mirai.utils.toUHexString
import
java.io.ByteArrayOutputStream
import
java.io.ByteArrayOutputStream
import
java.io.DataInputStream
import
java.io.DataInputStream
import
java.util.zip.GZIPInputStream
import
java.util.zip.GZIPInputStream
/**
/**
* Packet id: `00 CE` or `00 17`
*
* @author Him188moe
* @author Him188moe
*/
*/
open
class
ServerEventPacket
(
input
:
DataInputStream
,
val
packetId
:
ByteArray
,
val
eventIdentity
:
ByteArray
)
:
ServerPacket
(
input
)
{
open
class
ServerEventPacket
(
input
:
DataInputStream
,
val
packetId
:
ByteArray
,
val
eventIdentity
:
ByteArray
)
:
ServerPacket
(
input
)
{
@PacketId
(
"00 17"
)
class
Raw
(
input
:
DataInputStream
,
private
val
packetId
:
ByteArray
)
:
ServerPacket
(
input
)
{
@ExperimentalUnsignedTypes
fun
distribute
():
ServerEventPacket
{
val
eventIdentity
=
this
.
input
.
readNBytes
(
16
)
val
type
=
this
.
input
.
goto
(
18
).
readNBytes
(
2
)
return
when
(
type
.
toUHexString
())
{
"00 C4"
->
{
if
(
this
.
input
.
goto
(
33
).
readBoolean
())
{
ServerAndroidOnlineEventPacket
(
this
.
input
,
packetId
,
eventIdentity
)
}
else
{
ServerAndroidOfflineEventPacket
(
this
.
input
,
packetId
,
eventIdentity
)
}
}
"00 2D"
->
ServerGroupUploadFileEventPacket
(
this
.
input
,
packetId
,
eventIdentity
)
override
fun
decode
()
{
"00 52"
->
ServerGroupMessageEventPacket
(
this
.
input
,
packetId
,
eventIdentity
)
"00 A6"
->
ServerFriendMessageEventPacket
(
this
.
input
,
packetId
,
eventIdentity
)
//"02 10", "00 12" -> ServerUnknownEventPacket(this.input, packetId, eventIdentity)
else
->
UnknownServerEventPacket
(
this
.
input
,
packetId
,
eventIdentity
)
}
}
@PacketId
(
"00 17"
)
class
Encrypted
(
input
:
DataInputStream
,
private
val
packetId
:
ByteArray
)
:
ServerPacket
(
input
)
{
fun
decrypt
(
sessionKey
:
ByteArray
):
Raw
=
Raw
(
decryptBy
(
sessionKey
),
packetId
)
}
}
}
}
}
/**
* Unknown event
*/
class
UnknownServerEventPacket
(
input
:
DataInputStream
,
packetId
:
ByteArray
,
eventIdentity
:
ByteArray
)
:
ServerEventPacket
(
input
,
packetId
,
eventIdentity
)
/**
/**
* Android 客户端上线
* Android 客户端上线
*/
*/
class
ServerAndroidOnlineEventPacket
(
input
:
DataInputStream
,
packetId
:
ByteArray
,
eventIdentity
:
ByteArray
)
:
ServerEventPacket
(
input
,
packetId
,
eventIdentity
)
class
ServerAndroidOnlineEventPacket
(
input
:
DataInputStream
,
packetId
:
ByteArray
,
eventIdentity
:
ByteArray
)
:
ServerEventPacket
(
input
,
packetId
,
eventIdentity
)
/**
/**
* Android 客户端
上
线
* Android 客户端
下
线
*/
*/
class
ServerAndroidOfflineEventPacket
(
input
:
DataInputStream
,
packetId
:
ByteArray
,
eventIdentity
:
ByteArray
)
:
ServerEventPacket
(
input
,
packetId
,
eventIdentity
)
class
ServerAndroidOfflineEventPacket
(
input
:
DataInputStream
,
packetId
:
ByteArray
,
eventIdentity
:
ByteArray
)
:
ServerEventPacket
(
input
,
packetId
,
eventIdentity
)
...
@@ -31,7 +68,7 @@ class ServerAndroidOfflineEventPacket(input: DataInputStream, packetId: ByteArra
...
@@ -31,7 +68,7 @@ class ServerAndroidOfflineEventPacket(input: DataInputStream, packetId: ByteArra
* 群文件上传
* 群文件上传
*/
*/
class
ServerGroupUploadFileEventPacket
(
input
:
DataInputStream
,
packetId
:
ByteArray
,
eventIdentity
:
ByteArray
)
:
ServerEventPacket
(
input
,
packetId
,
eventIdentity
)
{
class
ServerGroupUploadFileEventPacket
(
input
:
DataInputStream
,
packetId
:
ByteArray
,
eventIdentity
:
ByteArray
)
:
ServerEventPacket
(
input
,
packetId
,
eventIdentity
)
{
lateinit
var
xmlMessage
:
String
private
lateinit
var
xmlMessage
:
String
override
fun
decode
()
{
override
fun
decode
()
{
xmlMessage
=
String
(
this
.
input
.
goto
(
65
).
readNBytes
(
this
.
input
.
goto
(
60
).
readShort
().
toInt
()))
xmlMessage
=
String
(
this
.
input
.
goto
(
65
).
readNBytes
(
this
.
input
.
goto
(
60
).
readShort
().
toInt
()))
...
@@ -39,8 +76,8 @@ class ServerGroupUploadFileEventPacket(input: DataInputStream, packetId: ByteArr
...
@@ -39,8 +76,8 @@ class ServerGroupUploadFileEventPacket(input: DataInputStream, packetId: ByteArr
}
}
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
:
Int
=
0
var
groupNumber
:
Long
=
0
var
qq
:
Int
=
0
var
qq
:
Long
=
0
lateinit
var
message
:
String
lateinit
var
message
:
String
lateinit
var
messageType
:
MessageType
lateinit
var
messageType
:
MessageType
...
@@ -58,9 +95,10 @@ class ServerGroupMessageEventPacket(input: DataInputStream, packetId: ByteArray,
...
@@ -58,9 +95,10 @@ class ServerGroupMessageEventPacket(input: DataInputStream, packetId: ByteArray,
OTHER
,
OTHER
,
}
}
@ExperimentalUnsignedTypes
override
fun
decode
()
{
override
fun
decode
()
{
groupNumber
=
this
.
input
.
goto
(
51
).
readInt
()
groupNumber
=
this
.
input
.
goto
(
51
).
readInt
()
.
toLong
()
qq
=
this
.
input
.
goto
(
56
).
read
Int
()
qq
=
this
.
input
.
goto
(
56
).
read
Long
().
toUInt
().
toLong
()
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
...
@@ -76,7 +114,7 @@ class ServerGroupMessageEventPacket(input: DataInputStream, packetId: ByteArray,
...
@@ -76,7 +114,7 @@ class ServerGroupMessageEventPacket(input: DataInputStream, packetId: ByteArray,
25
->
MessageType
.
ANONYMOUS
25
->
MessageType
.
ANONYMOUS
else
->
{
else
->
{
println
(
"
id=$id"
)
MiraiLogger
debug
(
"ServerGroupMessageEventPacket
id=$id"
)
MessageType
.
OTHER
MessageType
.
OTHER
}
}
}
}
...
@@ -142,10 +180,9 @@ class ServerGroupMessageEventPacket(input: DataInputStream, packetId: ByteArray,
...
@@ -142,10 +180,9 @@ class ServerGroupMessageEventPacket(input: DataInputStream, packetId: ByteArray,
}
}
class
ServerFriendMessageEventPacket
(
input
:
DataInputStream
,
packetId
:
ByteArray
,
eventIdentity
:
ByteArray
)
:
ServerEventPacket
(
input
,
packetId
,
eventIdentity
)
{
class
ServerFriendMessageEventPacket
(
input
:
DataInputStream
,
packetId
:
ByteArray
,
eventIdentity
:
ByteArray
)
:
ServerEventPacket
(
input
,
packetId
,
eventIdentity
)
{
var
qq
:
Int
=
0
var
qq
:
Long
=
0
lateinit
var
message
:
MessageChain
lateinit
var
message
:
MessageChain
@ExperimentalUnsignedTypes
@ExperimentalUnsignedTypes
override
fun
decode
()
{
override
fun
decode
()
{
//start at Sep1.0:27
//start at Sep1.0:27
...
@@ -153,7 +190,7 @@ class ServerFriendMessageEventPacket(input: DataInputStream, packetId: ByteArray
...
@@ -153,7 +190,7 @@ class ServerFriendMessageEventPacket(input: DataInputStream, packetId: ByteArray
println
(
input
.
readAllBytes
().
toUHexString
())
println
(
input
.
readAllBytes
().
toUHexString
())
input
.
goto
(
0
)
input
.
goto
(
0
)
qq
=
input
.
readIntAt
(
0
)
qq
=
input
.
readIntAt
(
0
)
.
toLong
()
val
msgLength
=
input
.
readShortAt
(
22
)
val
msgLength
=
input
.
readShortAt
(
22
)
val
fontLength
=
input
.
readShortAt
(
93
+
msgLength
)
val
fontLength
=
input
.
readShortAt
(
93
+
msgLength
)
val
offset
=
msgLength
+
fontLength
val
offset
=
msgLength
+
fontLength
...
@@ -165,13 +202,42 @@ class ServerFriendMessageEventPacket(input: DataInputStream, packetId: ByteArray
...
@@ -165,13 +202,42 @@ class ServerFriendMessageEventPacket(input: DataInputStream, packetId: ByteArray
}
}
/**
* 告知服务器已经收到数据
*/
@PacketId
(
""
)
//随后写入
@ExperimentalUnsignedTypes
class
ClientMessageResponsePacket
(
private
val
qq
:
Long
,
private
val
packetIdFromServer
:
ByteArray
,
//4bytes
private
val
sessionKey
:
ByteArray
,
private
val
eventIdentity
:
ByteArray
)
:
ClientPacket
()
{
override
fun
encode
()
{
this
.
write
(
packetIdFromServer
)
//packet id 4bytes
this
.
writeQQ
(
qq
)
this
.
writeHex
(
Protocol
.
fixVer2
)
this
.
encryptAndWrite
(
sessionKey
)
{
it
.
write
(
eventIdentity
)
}
}
}
/*
3E 03 3F A2 76 E4 B8 DD 00 09 7C 3F 64 5C 2A 60 1F 40 00 A6 00 00 00 2D 00 05 00 02 00 01 00 06 00 04 00 01 2E 01 00 09 00 06 00 01 00 00 00 01 00 0A 00 04 01 00 00 00 00 01 00 04 00 00 00 00 00 03 00 01 02 38 03 3E 03 3F A2 76 E4 B8 DD 01 10 9D D6 12 EA BC 07 91 EF DC 29 75 67 A9 1E 00 0B 2F E4 5D 6B A8 F6 01 1D 00 00 00 00 01 00 00 00 01 4D 53 47 00 00 00 00 00 5D 6B A8 F6 08 7E 90 CE 00 00 00 00 0C 00 86 22 00 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 00 00 01 00 09 01 00 06 E7 89 9B E9 80 BC 0E 00 07 01 00 04 00 00 00 09 19 00 18 01 00 15 AA 02 12 9A 01 0F 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00
3E 03 3F A2 76 E4 B8 DD 00 03 5F 85 64 5C 2A A4 1F 40 00 A6 00 00 00 2D 00 05 00 02 00 01 00 06 00 04 00 01 2E 01 00 09 00 06 00 01 00 00 00 01 00 0A 00 04 01 00 00 00 00 01 00 04 00 00 00 00 00 03 00 01 02 38 03 3E 03 3F A2 76 E4 B8 DD 01 10 9D D6 12 EA BC 07 91 EF DC 29 75 67 A9 1E 00 0B 2F E5 5D 6B A9 16 01 1D 00 00 00 00 01 00 00 00 01 4D 53 47 00 00 00 00 00 5D 6B A9 17 1B B3 4D D7 00 00 00 00 0C 00 86 22 00 0C E5 BE AE E8 BD AF E9 9B 85 E9 BB 91 00 00 01 00 09 01 00 06 E7 89 9B E9 80 BC 0E 00 07 01 00 04 00 00 00 09 19 00 18 01 00 15 AA 02 12 9A 01 0F 80 01 01 C8 01 00 F0 01 00 F8 01 00 90 02 00
*/
/*
/*
backup
backup
class ServerFriendMessageEventPacket(input: DataInputStream, packetId: ByteArray, eventIdentity: ByteArray) : ServerEventPacket(input, packetId, eventIdentity) {
class ServerFriendMessageEventPacket(input: DataInputStream, packetId: ByteArray, eventIdentity: ByteArray) : ServerEventPacket(input, packetId, eventIdentity) {
var qq:
Int
= 0
var qq:
Long
= 0
lateinit var message: String
lateinit var message: String
...
...
mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerPacket.kt
View file @
93dc8e58
package
net.mamoe.mirai.network.packet
package
net.mamoe.mirai.network.packet
import
net.mamoe.mirai.network.packet.action.ServerSendFriendMessageResponsePacket
import
net.mamoe.mirai.network.packet.action.ServerSendGroupMessageResponsePacket
import
net.mamoe.mirai.network.packet.login.*
import
net.mamoe.mirai.network.packet.login.*
import
net.mamoe.mirai.network.packet.message.ServerSendFriendMessageResponsePacket
import
net.mamoe.mirai.utils.*
import
net.mamoe.mirai.network.packet.message.ServerSendGroupMessageResponsePacket
import
net.mamoe.mirai.network.packet.verification.ServerVerificationCodePacketEncrypted
import
net.mamoe.mirai.utils.getAllDeclaredFields
import
net.mamoe.mirai.utils.hexToBytes
import
net.mamoe.mirai.utils.toUHexString
import
java.io.DataInputStream
import
java.io.DataInputStream
/**
/**
...
@@ -14,7 +11,9 @@ import java.io.DataInputStream
...
@@ -14,7 +11,9 @@ import java.io.DataInputStream
*/
*/
abstract
class
ServerPacket
(
val
input
:
DataInputStream
)
:
Packet
{
abstract
class
ServerPacket
(
val
input
:
DataInputStream
)
:
Packet
{
abstract
fun
decode
()
open
fun
decode
()
{
}
companion
object
{
companion
object
{
...
@@ -28,55 +27,56 @@ abstract class ServerPacket(val input: DataInputStream) : Packet {
...
@@ -28,55 +27,56 @@ abstract class ServerPacket(val input: DataInputStream) : Packet {
return
when
(
val
idHex
=
stream
.
readInt
().
toHexString
(
" "
))
{
return
when
(
val
idHex
=
stream
.
readInt
().
toHexString
(
" "
))
{
"08 25 31 01"
->
ServerTouchResponsePacketEncrypted
(
ServerTouchResponsePacket
.
Type
.
TYPE_08_25_31_01
,
stream
)
"08 25 31 01"
->
ServerTouchResponsePacket
.
Encrypted
(
ServerTouchResponsePacket
.
Type
.
TYPE_08_25_31_01
,
stream
)
"08 25 31 02"
->
ServerTouchResponsePacket
.
Encrypted
(
ServerTouchResponsePacket
.
Type
.
TYPE_08_25_31_02
,
stream
)
"08 25 31 02"
->
ServerTouchResponsePacketEncrypted
(
ServerTouchResponsePacket
.
Type
.
TYPE_08_25_31_02
,
stream
)
"08 36 31 03"
,
"08 36 31 04"
,
"08 36 31 05"
,
"08 36 31 06"
->
{
"08 36 31 03"
,
"08 36 31 04"
,
"08 36 31 05"
,
"08 36 31 06"
->
{
when
(
bytes
.
size
)
{
when
(
bytes
.
size
)
{
271
,
207
->
return
ServerLoginResponseResendPacketEncrypted
(
stream
,
when
(
idHex
)
{
271
,
207
->
return
ServerLoginResponseResendPacket
.
Encrypted
(
stream
,
when
(
idHex
)
{
"08 36 31 03"
->
ServerLoginResponseResendPacket
.
Flag
.
`
08
36
31
03
`
"08 36 31 03"
->
ServerLoginResponseResendPacket
.
Flag
.
`
08
36
31
03
`
else
->
{
else
->
{
println
(
"
flag=$idHex"
);
ServerLoginResponseResendPacket
.
Flag
.
OTHER
MiraiLogger
debug
(
"ServerLoginResponseResendPacketEncrypted:
flag=$idHex"
);
ServerLoginResponseResendPacket
.
Flag
.
OTHER
}
}
})
})
871
->
return
ServerLoginResponseVerificationCode
Packet
Encrypted
(
stream
)
871
->
return
ServerLoginResponseVerificationCode
InitPacket
.
Encrypted
(
stream
)
}
}
if
(
bytes
.
size
>
700
)
{
if
(
bytes
.
size
>
700
)
{
return
ServerLoginResponseSuccessPacketEncrypted
(
stream
)
return
ServerLoginResponseSuccessPacket
.
Encrypted
(
stream
)
}
}
return
ServerLoginResponseFailedPacket
(
when
(
bytes
.
size
)
{
return
ServerLoginResponseFailedPacket
(
when
(
bytes
.
size
)
{
319
->
ServerLoginResponseFailedPacket
.
State
.
WRONG_PASSWORD
319
,
135
->
LoginState
.
WRONG_PASSWORD
135
->
ServerLoginResponseFailedPacket
.
State
.
RETYPE_PASSWORD
//135 -> LoginState.RETYPE_PASSWORD
279
->
ServerLoginResponseFailedPacket
.
State
.
BLOCKED
279
->
LoginState
.
BLOCKED
263
->
ServerLoginResponseFailedPacket
.
State
.
UNKNOWN_QQ_NUMBER
263
->
LoginState
.
UNKNOWN_QQ_NUMBER
551
,
487
->
ServerLoginResponseFailedPacket
.
State
.
DEVICE_LOCK
551
,
487
->
LoginState
.
DEVICE_LOCK
359
->
ServerLoginResponseFailedPacket
.
State
.
TAKEN_BACK
359
->
LoginState
.
TAKEN_BACK
else
->
LoginState
.
UNKNOWN
/*
//unknown
//unknown
63
->
throw
IllegalArgumentException
(
bytes
.
size
.
toString
()
+
" (
Already logged in)"
)
//可能是已经完成登录, 服务器拒绝第二次登录
63 -> throw IllegalArgumentException(bytes.size.toString() + " (
Unknown error)")
351
->
throw
IllegalArgumentException
(
bytes
.
size
.
toString
()
+
" (Illegal package data)"
)
//包数据有误
351 -> throw IllegalArgumentException(bytes.size.toString() + " (Illegal package data
or Unknown error
)")//包数据有误
else
->
throw
IllegalArgumentException
(
bytes
.
size
.
toString
())
else -> throw IllegalArgumentException(bytes.size.toString())
*/
},
stream
)
},
stream
)
}
}
"08 28 04 34"
->
ServerSessionKeyResponsePacketEncrypted
(
stream
)
"08 28 04 34"
->
ServerSessionKeyResponsePacket
.
Encrypted
(
stream
)
else
->
when
(
idHex
.
substring
(
0
,
5
))
{
else
->
when
(
idHex
.
substring
(
0
,
5
))
{
"00 EC"
->
ServerLoginSuccessPacket
(
stream
)
"00 EC"
->
ServerLoginSuccessPacket
(
stream
)
"00 1D"
->
ServerSKeyResponsePacketEncrypted
(
stream
)
"00 1D"
->
ServerSKeyResponsePacket
.
Encrypted
(
stream
)
"00 5C"
->
ServerAccountInfoResponsePacketEncrypted
(
stream
)
"00 5C"
->
ServerAccountInfoResponsePacket
.
Encrypted
(
stream
)
"00 58"
->
ServerHeartbeatResponsePacket
(
stream
)
"00 58"
->
ServerHeartbeatResponsePacket
(
stream
)
"00 BA"
->
ServerVerificationCodePacketEncrypted
(
stream
)
"00 BA"
->
ServerVerificationCodePacket
.
Encrypted
(
stream
)
"00 CE"
,
"00 17"
->
Server
MessageEventPacketRawEncod
ed
(
stream
,
idHex
.
hexToBytes
())
"00 CE"
,
"00 17"
->
Server
EventPacket
.
Raw
.
Encrypt
ed
(
stream
,
idHex
.
hexToBytes
())
"00 81"
->
UnknownServerPacket
(
stream
)
"00 81"
->
UnknownServerPacket
(
stream
)
...
@@ -89,6 +89,7 @@ abstract class ServerPacket(val input: DataInputStream) : Packet {
...
@@ -89,6 +89,7 @@ abstract class ServerPacket(val input: DataInputStream) : Packet {
}
}
}
}
@ExperimentalUnsignedTypes
override
fun
toString
():
String
{
override
fun
toString
():
String
{
return
this
.
javaClass
.
simpleName
+
this
.
getAllDeclaredFields
().
joinToString
(
", "
,
"{"
,
"}"
)
{
return
this
.
javaClass
.
simpleName
+
this
.
getAllDeclaredFields
().
joinToString
(
", "
,
"{"
,
"}"
)
{
it
.
trySetAccessible
();
it
.
name
+
"="
+
it
.
get
(
this
).
let
{
value
->
it
.
trySetAccessible
();
it
.
name
+
"="
+
it
.
get
(
this
).
let
{
value
->
...
@@ -100,20 +101,19 @@ abstract class ServerPacket(val input: DataInputStream) : Packet {
...
@@ -100,20 +101,19 @@ abstract class ServerPacket(val input: DataInputStream) : Packet {
}
}
}
}
}
}
}
fun
decryptBy
(
key
:
ByteArray
):
DataInputStream
{
input
.
goto
(
14
)
return
DataInputStream
(
TEA
.
decrypt
(
input
.
readAllBytes
().
let
{
it
.
copyOfRange
(
0
,
it
.
size
-
1
)
},
key
).
inputStream
())
}
fun
DataInputStream
.
readUntil
(
byte
:
Byte
):
ByteArray
{
@ExperimentalUnsignedTypes
var
buff
=
byteArrayOf
()
fun
decryptBy
(
keyHex
:
String
):
DataInputStream
{
var
b
:
Byte
return
this
.
decryptBy
(
keyHex
.
hexToBytes
())
b
=
readByte
()
while
(
b
!=
byte
)
{
buff
+=
b
b
=
readByte
()
}
}
return
buff
}
}
@ExperimentalUnsignedTypes
@ExperimentalUnsignedTypes
fun
DataInputStream
.
readIP
():
String
{
fun
DataInputStream
.
readIP
():
String
{
var
buff
=
""
var
buff
=
""
...
@@ -150,6 +150,15 @@ fun <N : Number> DataInputStream.readNBytesAt(position: N, length: Int): ByteArr
...
@@ -150,6 +150,15 @@ fun <N : Number> DataInputStream.readNBytesAt(position: N, length: Int): ByteArr
return
this
.
readNBytes
(
length
)
return
this
.
readNBytes
(
length
)
}
}
fun
<
N
:
Number
>
DataInputStream
.
readNBytes
(
length
:
N
):
ByteArray
{
return
this
.
readNBytes
(
length
.
toInt
())
}
fun
DataInputStream
.
readNBytesIn
(
range
:
IntRange
):
ByteArray
{
this
.
goto
(
range
.
first
)
return
this
.
readNBytes
(
range
.
last
-
range
.
first
+
1
)
}
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
();
...
@@ -163,4 +172,6 @@ fun <N : Number> DataInputStream.readByteAt(position: N): Byte {
...
@@ -163,4 +172,6 @@ fun <N : Number> DataInputStream.readByteAt(position: N): Byte {
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
();
}
}
\ No newline at end of file
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 @
93dc8e58
...
@@ -2,8 +2,8 @@ package net.mamoe.mirai.network.packet
...
@@ -2,8 +2,8 @@ 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.ByteArrayDataOutputStream
import
net.mamoe.mirai.utils.TEA
Cryptor
import
net.mamoe.mirai.utils.TEA
import
net.mamoe.mirai.utils.getRandom
Ke
y
import
net.mamoe.mirai.utils.getRandom
ByteArra
y
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
...
@@ -14,10 +14,8 @@ import java.net.InetAddress
...
@@ -14,10 +14,8 @@ import java.net.InetAddress
@ExperimentalUnsignedTypes
@ExperimentalUnsignedTypes
@PacketId
(
"08 28 04 34"
)
@PacketId
(
"08 28 04 34"
)
class
ClientSessionRequestPacket
(
class
ClientSessionRequestPacket
(
private
val
qq
:
Int
,
private
val
qq
:
Long
,
private
val
serverIp
:
String
,
private
val
serverIp
:
String
,
private
val
loginIP
:
String
,
private
val
md5_32
:
ByteArray
,
private
val
token38
:
ByteArray
,
private
val
token38
:
ByteArray
,
private
val
token88
:
ByteArray
,
private
val
token88
:
ByteArray
,
private
val
encryptionKey
:
ByteArray
,
private
val
encryptionKey
:
ByteArray
,
...
@@ -28,7 +26,7 @@ class ClientSessionRequestPacket(
...
@@ -28,7 +26,7 @@ class ClientSessionRequestPacket(
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
Cryptor
.
encrypt
(
object
:
ByteArrayDataOutputStream
()
{
this
.
write
(
TEA
.
encrypt
(
object
:
ByteArrayDataOutputStream
()
{
override
fun
toByteArray
():
ByteArray
{
override
fun
toByteArray
():
ByteArray
{
this
.
writeHex
(
"00 07 00 88"
)
this
.
writeHex
(
"00 07 00 88"
)
this
.
write
(
token88
)
this
.
write
(
token88
)
...
@@ -36,22 +34,22 @@ class ClientSessionRequestPacket(
...
@@ -36,22 +34,22 @@ class ClientSessionRequestPacket(
this
.
writeIP
(
serverIp
)
this
.
writeIP
(
serverIp
)
this
.
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
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 "
)
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 "
)
this
.
writeHex
(
Protocol
.
_0836fix
)
this
.
writeHex
(
Protocol
.
fix0836
)
this
.
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"
)
this
.
writeHex
(
Protocol
.
_0825d
ata0
)
this
.
writeHex
(
Protocol
.
constantD
ata0
)
this
.
writeHex
(
Protocol
.
_0825data2
)
this
.
writeHex
(
Protocol
.
constantData1
)
this
.
writeQQ
(
qq
)
this
.
writeQQ
(
qq
)
this
.
writeHex
(
"00 00 00 00 00 1F 00 22 00 01"
)
this
.
writeHex
(
"00 00 00 00 00 1F 00 22 00 01"
)
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
.
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
)
this
.
write
(
tlv0105
)
this
.
writeHex
(
"01 0B 00 85 00 02"
)
this
.
writeHex
(
"01 0B 00 85 00 02"
)
this
.
writeHex
(
"B9 ED EF D7 CD E5 47 96 7A B5 28 34 CA 93 6B 5C"
)
//fix2
this
.
writeHex
(
"B9 ED EF D7 CD E5 47 96 7A B5 28 34 CA 93 6B 5C"
)
//fix2
this
.
write
(
getRandom
Ke
y
(
1
))
this
.
write
(
getRandom
ByteArra
y
(
1
))
this
.
writeHex
(
"10 00 00 00 00 00 00 00 02"
)
this
.
writeHex
(
"10 00 00 00 00 00 00 00 02"
)
//fix3
//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"
)
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"
)
this
.
write
(
md5_32
)
this
.
write
(
getRandomByteArray
(
32
))
//md5 32
this
.
writeHex
(
"68"
)
this
.
writeHex
(
"68"
)
this
.
writeHex
(
"00 00 00 00 00 2D 00 06 00 01"
)
this
.
writeHex
(
"00 00 00 00 00 2D 00 06 00 01"
)
...
@@ -64,8 +62,6 @@ class ClientSessionRequestPacket(
...
@@ -64,8 +62,6 @@ class ClientSessionRequestPacket(
}
}
/**
/**
* Dispose_0828
*
* @author Him188moe
* @author Him188moe
*/
*/
class
ServerSessionKeyResponsePacket
(
inputStream
:
DataInputStream
,
private
val
dataLength
:
Int
)
:
ServerPacket
(
inputStream
)
{
class
ServerSessionKeyResponsePacket
(
inputStream
:
DataInputStream
,
private
val
dataLength
:
Int
)
:
ServerPacket
(
inputStream
)
{
...
@@ -106,16 +102,12 @@ class ServerSessionKeyResponsePacket(inputStream: DataInputStream, private val d
...
@@ -106,16 +102,12 @@ class ServerSessionKeyResponsePacket(inputStream: DataInputStream, private val d
//tlv0105 = "01 05 00 88 00 01 01 02 00 40 02 01 03 3C 01 03 00 00" + 取文本中间(data, 取文本长度(data) - 367, 167) + “00 40 02 02 03 3C 01 03 00 00 ” + 取文本中间 (data, 取文本长度 (data) - 166, 167)
//tlv0105 = "01 05 00 88 00 01 01 02 00 40 02 01 03 3C 01 03 00 00" + 取文本中间(data, 取文本长度(data) - 367, 167) + “00 40 02 02 03 3C 01 03 00 00 ” + 取文本中间 (data, 取文本长度 (data) - 166, 167)
}
}
}
class
ServerSessionKeyResponsePacketEncrypted
(
inputStream
:
DataInputStream
)
:
ServerPacket
(
inputStream
)
{
override
fun
decode
()
{
}
class
Encrypted
(
inputStream
:
DataInputStream
)
:
ServerPacket
(
inputStream
)
{
fun
decrypt
(
sessionResponseDecryptionKey
:
ByteArray
):
ServerSessionKeyResponsePacket
{
fun
decrypt
(
_0828_rec_decr_key
:
ByteArray
):
ServerSessionKeyResponsePacket
{
this
.
input
goto
14
this
.
input
goto
14
val
data
=
this
.
input
.
readAllBytes
().
let
{
it
.
copyOfRange
(
0
,
it
.
size
-
1
)
}
val
data
=
this
.
input
.
readAllBytes
().
let
{
it
.
copyOfRange
(
0
,
it
.
size
-
1
)
}
return
ServerSessionKeyResponsePacket
(
TEA
.
decrypt
(
data
,
sessionResponseDecryptionKey
).
dataInputStream
(),
data
.
size
)
return
ServerSessionKeyResponsePacket
(
TEACryptor
.
decrypt
(
data
,
_0828_rec_decr_key
).
dataInputStream
(),
data
.
size
);
}
}
}
}
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/network/packet/Touch.kt
View file @
93dc8e58
...
@@ -40,7 +40,7 @@ class ServerTouchResponsePacket(inputStream: DataInputStream) : ServerPacket(inp
...
@@ -40,7 +40,7 @@ class ServerTouchResponsePacket(inputStream: DataInputStream) : ServerPacket(inp
loginTime
=
input
.
readInt
()
loginTime
=
input
.
readInt
()
loginIP
=
input
.
readIP
()
loginIP
=
input
.
readIP
()
tgtgtKey
=
getRandom
Ke
y
(
16
)
tgtgtKey
=
getRandom
ByteArra
y
(
16
)
}
}
else
->
{
else
->
{
...
@@ -48,24 +48,13 @@ class ServerTouchResponsePacket(inputStream: DataInputStream) : ServerPacket(inp
...
@@ -48,24 +48,13 @@ class ServerTouchResponsePacket(inputStream: DataInputStream) : ServerPacket(inp
}
}
}
}
}
}
}
class
ServerTouchResponsePacketEncrypted
(
private
val
type
:
ServerTouchResponsePacket
.
Type
,
inputStream
:
DataInputStream
)
:
ServerPacket
(
inputStream
)
{
override
fun
decode
()
{
}
@ExperimentalUnsignedTypes
fun
decrypt
():
ServerTouchResponsePacket
{
input
.
skip
(
7
)
var
bytes
=
input
.
readAllBytes
();
bytes
=
bytes
.
copyOfRange
(
0
,
bytes
.
size
-
1
);
println
(
bytes
.
toUByteArray
().
toUHexString
())
return
ServerTouchResponsePacket
(
DataInputStream
(
TEACryptor
.
decrypt
(
bytes
,
when
(
type
)
{
class
Encrypted
(
private
val
type
:
Type
,
inputStream
:
DataInputStream
)
:
ServerPacket
(
inputStream
)
{
ServerTouchResponsePacket
.
Type
.
TYPE_08_25_31_02
->
Protocol
.
redirectionKey
.
hexToBytes
()
@ExperimentalUnsignedTypes
ServerTouchResponsePacket
.
Type
.
TYPE_08_25_31_01
->
Protocol
.
_0825key
.
hexToBytes
()
fun
decrypt
():
ServerTouchResponsePacket
=
ServerTouchResponsePacket
(
decryptBy
(
when
(
type
)
{
}).
inputStream
()));
Type
.
TYPE_08_25_31_02
->
Protocol
.
redirectionKey
.
hexToBytes
()
Type
.
TYPE_08_25_31_01
->
Protocol
.
key0825
.
hexToBytes
()
}))
}
}
}
}
...
@@ -76,19 +65,19 @@ class ServerTouchResponsePacketEncrypted(private val type: ServerTouchResponsePa
...
@@ -76,19 +65,19 @@ class ServerTouchResponsePacketEncrypted(private val type: ServerTouchResponsePa
*/
*/
@ExperimentalUnsignedTypes
@ExperimentalUnsignedTypes
@PacketId
(
"08 25 31 01"
)
@PacketId
(
"08 25 31 01"
)
class
ClientTouchPacket
(
val
qq
:
Int
,
val
serverIp
:
String
)
:
ClientPacket
()
{
class
ClientTouchPacket
(
val
qq
:
Long
,
val
serverIp
:
String
)
:
ClientPacket
()
{
@ExperimentalUnsignedTypes
@ExperimentalUnsignedTypes
@Throws
(
IOException
::
class
)
@Throws
(
IOException
::
class
)
override
fun
encode
()
{
override
fun
encode
()
{
this
.
writeQQ
(
qq
)
this
.
writeQQ
(
qq
)
this
.
writeHex
(
Protocol
.
fixVer
)
this
.
writeHex
(
Protocol
.
fixVer
)
this
.
writeHex
(
Protocol
.
_0825key
)
this
.
writeHex
(
Protocol
.
key0825
)
this
.
write
(
TEA
Cryptor
.
CRYPTOR_0825KEY
.
encrypt
(
object
:
ByteArrayDataOutputStream
()
{
this
.
write
(
TEA
.
CRYPTOR_0825KEY
.
encrypt
(
object
:
ByteArrayDataOutputStream
()
{
@Throws
(
IOException
::
class
)
@Throws
(
IOException
::
class
)
override
fun
toByteArray
():
ByteArray
{
override
fun
toByteArray
():
ByteArray
{
this
.
writeHex
(
Protocol
.
_0825d
ata0
)
this
.
writeHex
(
Protocol
.
constantD
ata0
)
this
.
writeHex
(
Protocol
.
_0825data2
)
this
.
writeHex
(
Protocol
.
constantData1
)
this
.
writeQQ
(
qq
)
this
.
writeQQ
(
qq
)
this
.
writeHex
(
"00 00 00 00 03 09 00 08 00 01"
)
this
.
writeHex
(
"00 00 00 00 03 09 00 08 00 01"
)
this
.
writeIP
(
serverIp
);
this
.
writeIP
(
serverIp
);
...
@@ -108,7 +97,7 @@ class ClientTouchPacket(val qq: Int, val serverIp: String) : ClientPacket() {
...
@@ -108,7 +97,7 @@ class ClientTouchPacket(val qq: Int, val serverIp: String) : ClientPacket() {
*/
*/
@ExperimentalUnsignedTypes
@ExperimentalUnsignedTypes
@PacketId
(
"08 25 31 02"
)
@PacketId
(
"08 25 31 02"
)
class
ClientServerRedirectionPacket
(
private
val
serverIP
:
String
,
private
val
qq
:
Int
)
:
ClientPacket
()
{
class
ClientServerRedirectionPacket
(
private
val
serverIP
:
String
,
private
val
qq
:
Long
)
:
ClientPacket
()
{
@ExperimentalUnsignedTypes
@ExperimentalUnsignedTypes
override
fun
encode
()
{
override
fun
encode
()
{
this
.
writeQQ
(
qq
)
this
.
writeQQ
(
qq
)
...
@@ -116,11 +105,11 @@ class ClientServerRedirectionPacket(private val serverIP: String, private val qq
...
@@ -116,11 +105,11 @@ class ClientServerRedirectionPacket(private val serverIP: String, private val qq
this
.
writeHex
(
Protocol
.
redirectionKey
)
this
.
writeHex
(
Protocol
.
redirectionKey
)
this
.
write
(
TEA
Cryptor
.
encrypt
(
object
:
ByteArrayDataOutputStream
()
{
this
.
write
(
TEA
.
encrypt
(
object
:
ByteArrayDataOutputStream
()
{
@Throws
(
IOException
::
class
)
@Throws
(
IOException
::
class
)
override
fun
toByteArray
():
ByteArray
{
override
fun
toByteArray
():
ByteArray
{
this
.
writeHex
(
Protocol
.
_0825d
ata0
)
this
.
writeHex
(
Protocol
.
constantD
ata0
)
this
.
writeHex
(
Protocol
.
_0825data2
)
this
.
writeHex
(
Protocol
.
constantData1
)
this
.
writeQQ
(
qq
)
this
.
writeQQ
(
qq
)
this
.
writeHex
(
"00 01 00 00 03 09 00 0C 00 01"
)
this
.
writeHex
(
"00 01 00 00 03 09 00 0C 00 01"
)
this
.
writeIP
(
serverIP
)
this
.
writeIP
(
serverIP
)
...
...
mirai-core/src/main/java/net/mamoe/mirai/network/packet/VerificationCode.kt
0 → 100644
View file @
93dc8e58
package
net.mamoe.mirai.network.packet
import
net.mamoe.mirai.network.Protocol
import
net.mamoe.mirai.utils.*
import
java.io.DataInputStream
/**
* 客户端请求验证码图片数据的第几部分
*/
@ExperimentalUnsignedTypes
@PacketId
(
"00 BA 31"
)
class
ClientVerificationCodeTransmissionRequestPacket
(
private
val
count
:
Int
,
private
val
qq
:
Long
,
private
val
token0825
:
ByteArray
,
private
val
verificationSequence
:
Int
,
private
val
token00BA
:
ByteArray
)
:
ClientPacket
()
{
@TestedSuccessfully
override
fun
encode
()
{
this
.
writeByte
(
count
)
//part of packet id
this
.
writeQQ
(
qq
)
this
.
writeHex
(
Protocol
.
fixVer2
)
this
.
writeHex
(
Protocol
.
key00BA
)
this
.
encryptAndWrite
(
Protocol
.
key00BA
)
{
it
.
writeHex
(
"00 02 00 00 08 04 01 E0"
)
it
.
writeHex
(
Protocol
.
constantData1
)
it
.
writeHex
(
"00 00 38"
)
it
.
write
(
token0825
)
it
.
writeHex
(
"01 03 00 19"
)
it
.
writeHex
(
Protocol
.
publicKey
)
it
.
writeHex
(
"13 00 05 00 00 00 00"
)
it
.
writeByte
(
verificationSequence
)
it
.
writeHex
(
"00 28"
)
it
.
write
(
token00BA
)
it
.
writeHex
(
"00 10"
)
it
.
writeHex
(
Protocol
.
key00BAFix
)
}
}
}
/**
* 服务器发送验证码图片文件一部分过来
*
* @author Him188moe
*/
class
ServerVerificationCodeTransmissionPacket
(
input
:
DataInputStream
,
private
val
dataSize
:
Int
,
private
val
packetId
:
ByteArray
)
:
ServerVerificationCodePacket
(
input
)
{
lateinit
var
verificationCodePartN
:
ByteArray
lateinit
var
verificationToken
:
ByteArray
//56bytes
var
transmissionCompleted
:
Boolean
=
false
//验证码是否已经传输完成
lateinit
var
token00BA
:
ByteArray
//40 bytes
var
count
:
Int
=
0
@ExperimentalUnsignedTypes
override
fun
decode
()
{
this
.
verificationToken
=
this
.
input
.
readNBytesAt
(
10
,
56
)
val
length
=
this
.
input
.
readShortAt
(
66
)
this
.
verificationCodePartN
=
this
.
input
.
readNBytes
(
length
)
this
.
input
.
skip
(
2
)
this
.
transmissionCompleted
=
this
.
input
.
readBoolean
().
not
()
this
.
token00BA
=
this
.
input
.
readNBytesAt
(
dataSize
-
57
,
40
)
this
.
count
=
byteArrayOf
(
0
,
0
,
packetId
[
2
],
packetId
[
3
]).
toUHexString
().
hexToInt
()
}
}
/**
* 暂不了解意义
*
* @author Him188moe
*/
class
ServerVerificationCodeRepeatPacket
(
input
:
DataInputStream
)
:
ServerVerificationCodePacket
(
input
)
{
lateinit
var
token00BA
:
ByteArray
//56 bytes
lateinit
var
tgtgtKeyUpdate
:
ByteArray
@ExperimentalUnsignedTypes
override
fun
decode
()
{
token00BA
=
this
.
input
.
readNBytesAt
(
10
,
56
)
tgtgtKeyUpdate
=
getRandomByteArray
(
16
)
}
}
abstract
class
ServerVerificationCodePacket
(
input
:
DataInputStream
)
:
ServerPacket
(
input
)
{
@PacketId
(
"00 BA"
)
class
Encrypted
(
input
:
DataInputStream
)
:
ServerPacket
(
input
)
{
@ExperimentalUnsignedTypes
fun
decrypt
():
ServerVerificationCodePacket
{
this
.
input
goto
14
val
data
=
TEA
.
decrypt
(
this
.
input
.
readAllBytes
().
let
{
it
.
copyOfRange
(
0
,
it
.
size
-
1
)
},
Protocol
.
key00BA
.
hexToBytes
())
return
if
(
data
.
size
==
95
)
{
ServerVerificationCodeRepeatPacket
(
data
.
dataInputStream
())
}
else
{
ServerVerificationCodeTransmissionPacket
(
data
.
dataInputStream
(),
data
.
size
,
this
.
input
.
readNBytesAt
(
3
,
4
))
}
}
}
}
mirai-core/src/main/java/net/mamoe/mirai/network/packet/
message
/ClientSendFriendMessagePacket.kt
→
mirai-core/src/main/java/net/mamoe/mirai/network/packet/
action
/ClientSendFriendMessagePacket.kt
View file @
93dc8e58
package
net.mamoe.mirai.network.packet.
message
package
net.mamoe.mirai.network.packet.
action
import
net.mamoe.mirai.network.Protocol
import
net.mamoe.mirai.network.Protocol
import
net.mamoe.mirai.network.packet.*
import
net.mamoe.mirai.network.packet.*
...
@@ -11,15 +11,15 @@ import java.io.DataInputStream
...
@@ -11,15 +11,15 @@ import java.io.DataInputStream
@PacketId
(
"00 CD"
)
@PacketId
(
"00 CD"
)
@ExperimentalUnsignedTypes
@ExperimentalUnsignedTypes
class
ClientSendFriendMessagePacket
(
class
ClientSendFriendMessagePacket
(
val
robotQQ
:
Int
,
private
val
robotQQ
:
Long
,
val
targetQQ
:
Int
,
private
val
targetQQ
:
Long
,
val
sessionKey
:
ByteArray
,
private
val
sessionKey
:
ByteArray
,
val
message
:
String
private
val
message
:
String
)
:
ClientPacket
()
{
)
:
ClientPacket
()
{
override
fun
encode
()
{
override
fun
encode
()
{
this
.
writeRandom
(
2
)
//part of packet id
this
.
writeRandom
(
2
)
//part of packet id
this
.
writeQQ
(
robotQQ
)
this
.
writeQQ
(
robotQQ
)
this
.
writeHex
(
Protocol
.
_fixVer
)
this
.
writeHex
(
Protocol
.
fixVer2
)
this
.
encryptAndWrite
(
sessionKey
)
{
this
.
encryptAndWrite
(
sessionKey
)
{
it
.
writeQQ
(
robotQQ
)
it
.
writeQQ
(
robotQQ
)
...
@@ -52,13 +52,10 @@ class ClientSendFriendMessagePacket(
...
@@ -52,13 +52,10 @@ class ClientSendFriendMessagePacket(
it
.
writeByte
(
0
x01
)
it
.
writeByte
(
0
x01
)
it
.
writeShort
(
bytes
.
size
)
it
.
writeShort
(
bytes
.
size
)
it
.
write
(
bytes
)
it
.
write
(
bytes
)
}
//todo check
}
}
}
}
}
}
}
@PacketId
(
"00 CD"
)
@PacketId
(
"00 CD"
)
class
ServerSendFriendMessageResponsePacket
(
input
:
DataInputStream
)
:
ServerPacket
(
input
)
{
class
ServerSendFriendMessageResponsePacket
(
input
:
DataInputStream
)
:
ServerPacket
(
input
)
override
fun
decode
()
{
\ No newline at end of file
}
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/network/packet/
message
/ClientSendGroupMessagePacket.kt
→
mirai-core/src/main/java/net/mamoe/mirai/network/packet/
action
/ClientSendGroupMessagePacket.kt
View file @
93dc8e58
package
net.mamoe.mirai.network.packet.
message
package
net.mamoe.mirai.network.packet.
action
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.lazyEncode
import
net.mamoe.mirai.utils.toUHexString
import
net.mamoe.mirai.utils.toUHexString
import
java.io.DataInputStream
import
java.io.DataInputStream
...
@@ -12,20 +11,20 @@ import java.io.DataInputStream
...
@@ -12,20 +11,20 @@ import java.io.DataInputStream
@PacketId
(
"00 02"
)
@PacketId
(
"00 02"
)
@ExperimentalUnsignedTypes
@ExperimentalUnsignedTypes
class
ClientSendGroupMessagePacket
(
class
ClientSendGroupMessagePacket
(
private
val
groupId
:
Int
,
//不是 number
private
val
groupId
:
Long
,
//不是 number
private
val
qq
:
Int
,
private
val
robotQQ
:
Long
,
private
val
sessionKey
:
ByteArray
,
private
val
sessionKey
:
ByteArray
,
private
val
message
:
String
private
val
message
:
String
)
:
ClientPacket
()
{
)
:
ClientPacket
()
{
override
fun
encode
()
{
override
fun
encode
()
{
this
.
writeRandom
(
2
)
//part of packet id
this
.
writeRandom
(
2
)
//part of packet id
this
.
writeQQ
(
qq
)
this
.
writeQQ
(
robotQQ
)
this
.
writeHex
(
Protocol
.
_fixVer
)
this
.
writeHex
(
Protocol
.
fixVer2
)
this
.
encryptAndWrite
(
sessionKey
)
{
this
.
encryptAndWrite
(
sessionKey
)
{
val
bytes
=
message
.
toByteArray
()
val
bytes
=
message
.
toByteArray
()
it
.
writeByte
(
0
x2A
)
it
.
writeByte
(
0
x2A
)
it
.
write
Int
(
groupId
)
it
.
write
Group
(
groupId
)
it
.
writeShort
(
56
+
bytes
.
size
)
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
.
writeHex
(
"00 01 01 00 00 00 00 00 00 00 4D 53 47 00 00 00 00 00"
)
...
@@ -46,24 +45,5 @@ class ClientSendGroupMessagePacket(
...
@@ -46,24 +45,5 @@ class ClientSendGroupMessagePacket(
}
}
}
}
fun
main
()
{
println
(
lazyEncode
{
val
bytes
=
"message"
.
toByteArray
()
it
.
writeByte
(
0
x2A
)
it
.
writeInt
(
580266363
)
it
.
writeShort
(
19
+
bytes
.
size
)
it
.
writeByte
(
0
x01
)
it
.
writeByte
(
0
x01
)
it
.
writeShort
(
bytes
.
size
+
3
)
it
.
writeByte
(
0
x01
)
it
.
writeShort
(
bytes
.
size
)
it
.
write
(
bytes
)
}.
toUHexString
())
}
@PacketId
(
"00 02"
)
@PacketId
(
"00 02"
)
class
ServerSendGroupMessageResponsePacket
(
input
:
DataInputStream
)
:
ServerPacket
(
input
)
{
class
ServerSendGroupMessageResponsePacket
(
input
:
DataInputStream
)
:
ServerPacket
(
input
)
override
fun
decode
()
{
\ No newline at end of file
}
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/Client
Login
StatusPacket.kt
→
mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/Client
ChangeOnline
StatusPacket.kt
View file @
93dc8e58
...
@@ -5,12 +5,14 @@ import net.mamoe.mirai.network.packet.*
...
@@ -5,12 +5,14 @@ import net.mamoe.mirai.network.packet.*
import
net.mamoe.mirai.utils.ClientLoginStatus
import
net.mamoe.mirai.utils.ClientLoginStatus
/**
/**
* 改变在线状态: "我在线上", "隐身" 等
*
* @author Him188moe
* @author Him188moe
*/
*/
@ExperimentalUnsignedTypes
@ExperimentalUnsignedTypes
@PacketId
(
"00 EC"
)
@PacketId
(
"00 EC"
)
class
Client
Login
StatusPacket
(
class
Client
ChangeOnline
StatusPacket
(
private
val
qq
:
Int
,
private
val
qq
:
Long
,
private
val
sessionKey
:
ByteArray
,
private
val
sessionKey
:
ByteArray
,
private
val
loginStatus
:
ClientLoginStatus
private
val
loginStatus
:
ClientLoginStatus
...
@@ -18,7 +20,7 @@ class ClientLoginStatusPacket(
...
@@ -18,7 +20,7 @@ class ClientLoginStatusPacket(
override
fun
encode
()
{
override
fun
encode
()
{
this
.
writeRandom
(
2
)
//part of packet id
this
.
writeRandom
(
2
)
//part of packet id
this
.
writeQQ
(
qq
)
this
.
writeQQ
(
qq
)
this
.
writeHex
(
Protocol
.
_fixVer
)
this
.
writeHex
(
Protocol
.
fixVer2
)
this
.
encryptAndWrite
(
sessionKey
)
{
this
.
encryptAndWrite
(
sessionKey
)
{
it
.
writeHex
(
"01 00"
)
it
.
writeHex
(
"01 00"
)
it
.
writeByte
(
loginStatus
.
id
)
it
.
writeByte
(
loginStatus
.
id
)
...
...
mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ClientLogin
Packet
.kt
→
mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ClientLogin.kt
View file @
93dc8e58
...
@@ -2,11 +2,7 @@ package net.mamoe.mirai.network.packet.login
...
@@ -2,11 +2,7 @@ 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.*
import
net.mamoe.mirai.network.packet.*
import
net.mamoe.mirai.util.TestedSuccessfully
import
net.mamoe.mirai.utils.*
import
net.mamoe.mirai.utils.ByteArrayDataOutputStream
import
net.mamoe.mirai.utils.TEACryptor
import
net.mamoe.mirai.utils.hexToBytes
import
net.mamoe.mirai.utils.toUHexString
import
java.io.DataOutputStream
import
java.io.DataOutputStream
/**
/**
...
@@ -18,7 +14,7 @@ import java.io.DataOutputStream
...
@@ -18,7 +14,7 @@ import java.io.DataOutputStream
@ExperimentalUnsignedTypes
@ExperimentalUnsignedTypes
@TestedSuccessfully
@TestedSuccessfully
class
ClientPasswordSubmissionPacket
(
class
ClientPasswordSubmissionPacket
(
private
val
qq
:
Int
,
private
val
qq
:
Long
,
private
val
password
:
String
,
private
val
password
:
String
,
private
val
loginTime
:
Int
,
private
val
loginTime
:
Int
,
private
val
loginIP
:
String
,
private
val
loginIP
:
String
,
...
@@ -28,10 +24,10 @@ class ClientPasswordSubmissionPacket(
...
@@ -28,10 +24,10 @@ class ClientPasswordSubmissionPacket(
@ExperimentalUnsignedTypes
@ExperimentalUnsignedTypes
override
fun
encode
()
{
override
fun
encode
()
{
this
.
writeQQ
(
qq
)
this
.
writeQQ
(
qq
)
this
.
writeHex
(
Protocol
.
_0836_622_fix
1
)
this
.
writeHex
(
Protocol
.
passwordSubmissionKey
1
)
this
.
writeHex
(
Protocol
.
publicKey
)
this
.
writeHex
(
Protocol
.
publicKey
)
this
.
writeHex
(
"00 00 00 10"
)
this
.
writeHex
(
"00 00 00 10"
)
this
.
writeHex
(
Protocol
.
_0836key1
)
this
.
writeHex
(
Protocol
.
key0836
)
this
.
encryptAndWrite
(
Protocol
.
shareKey
.
hexToBytes
())
{
this
.
encryptAndWrite
(
Protocol
.
shareKey
.
hexToBytes
())
{
it
.
writePart1
(
qq
,
password
,
loginTime
,
loginIP
,
tgtgtKey
,
token0825
)
it
.
writePart1
(
qq
,
password
,
loginTime
,
loginIP
,
tgtgtKey
,
token0825
)
...
@@ -43,17 +39,22 @@ class ClientPasswordSubmissionPacket(
...
@@ -43,17 +39,22 @@ class ClientPasswordSubmissionPacket(
@PacketId
(
"08 36 31 04"
)
@PacketId
(
"08 36 31 04"
)
@ExperimentalUnsignedTypes
@ExperimentalUnsignedTypes
class
ClientLoginResendPacket3104
(
qq
:
Int
,
password
:
String
,
loginTime
:
Int
,
loginIP
:
String
,
tgtgtKey
:
ByteArray
,
token0825
:
ByteArray
,
token00BA
:
ByteArray
,
tlv_0006_encr
:
ByteArray
?
=
null
)
class
ClientLoginResendPacket3104
(
qq
:
Long
,
password
:
String
,
loginTime
:
Int
,
loginIP
:
String
,
tgtgtKey
:
ByteArray
,
token0825
:
ByteArray
,
token00BA
:
ByteArray
,
tlv_0006_encr
:
ByteArray
?
=
null
)
:
ClientLoginResendPacket
(
qq
,
password
,
loginTime
,
loginIP
,
tgtgtKey
,
token0825
,
token00BA
,
tlv_0006_encr
)
:
ClientLoginResendPacket
(
qq
,
password
,
loginTime
,
loginIP
,
tgtgtKey
,
token0825
,
token00BA
,
tlv_0006_encr
)
@PacketId
(
"08 36 31 05"
)
@ExperimentalUnsignedTypes
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
)
@PacketId
(
"08 36 31 06"
)
@PacketId
(
"08 36 31 06"
)
@ExperimentalUnsignedTypes
@ExperimentalUnsignedTypes
class
ClientLoginResendPacket3106
(
qq
:
Int
,
password
:
String
,
loginTime
:
Int
,
loginIP
:
String
,
tgtgtKey
:
ByteArray
,
token0825
:
ByteArray
,
token00BA
:
ByteArray
,
tlv_0006_encr
:
ByteArray
?
=
null
)
class
ClientLoginResendPacket3106
(
qq
:
Long
,
password
:
String
,
loginTime
:
Int
,
loginIP
:
String
,
tgtgtKey
:
ByteArray
,
token0825
:
ByteArray
,
token00BA
:
ByteArray
,
tlv_0006_encr
:
ByteArray
?
=
null
)
:
ClientLoginResendPacket
(
qq
,
password
,
loginTime
,
loginIP
,
tgtgtKey
,
token0825
,
token00BA
,
tlv_0006_encr
)
:
ClientLoginResendPacket
(
qq
,
password
,
loginTime
,
loginIP
,
tgtgtKey
,
token0825
,
token00BA
,
tlv_0006_encr
)
@ExperimentalUnsignedTypes
@ExperimentalUnsignedTypes
open
class
ClientLoginResendPacket
internal
constructor
(
open
class
ClientLoginResendPacket
internal
constructor
(
val
qq
:
Int
,
val
qq
:
Long
,
val
password
:
String
,
val
password
:
String
,
val
loginTime
:
Int
,
val
loginTime
:
Int
,
val
loginIP
:
String
,
val
loginIP
:
String
,
...
@@ -64,12 +65,12 @@ open class ClientLoginResendPacket internal constructor(
...
@@ -64,12 +65,12 @@ open class ClientLoginResendPacket internal constructor(
)
:
ClientPacket
()
{
)
:
ClientPacket
()
{
override
fun
encode
()
{
override
fun
encode
()
{
this
.
writeQQ
(
qq
)
this
.
writeQQ
(
qq
)
this
.
writeHex
(
Protocol
.
_0836_622_fix
1
)
this
.
writeHex
(
Protocol
.
passwordSubmissionKey
1
)
this
.
writeHex
(
Protocol
.
publicKey
)
this
.
writeHex
(
Protocol
.
publicKey
)
this
.
writeHex
(
"00 00 00 10"
)
this
.
writeHex
(
"00 00 00 10"
)
this
.
writeHex
(
Protocol
.
_0836key1
)
this
.
writeHex
(
Protocol
.
key0836
)
this
.
write
(
TEA
Cryptor
.
encrypt
(
object
:
ByteArrayDataOutputStream
()
{
this
.
write
(
TEA
.
encrypt
(
object
:
ByteArrayDataOutputStream
()
{
override
fun
toByteArray
():
ByteArray
{
override
fun
toByteArray
():
ByteArray
{
this
.
writePart1
(
qq
,
password
,
loginTime
,
loginIP
,
tgtgtKey
,
token0825
,
tlv_0006_encr
)
this
.
writePart1
(
qq
,
password
,
loginTime
,
loginIP
,
tgtgtKey
,
token0825
,
tlv_0006_encr
)
...
@@ -91,7 +92,7 @@ open class ClientLoginResendPacket internal constructor(
...
@@ -91,7 +92,7 @@ open class ClientLoginResendPacket internal constructor(
* @author Him188moe
* @author Him188moe
*/
*/
@ExperimentalUnsignedTypes
@ExperimentalUnsignedTypes
private
fun
DataOutputStream
.
writePart1
(
qq
:
Int
,
password
:
String
,
loginTime
:
Int
,
loginIP
:
String
,
tgtgtKey
:
ByteArray
,
token0825
:
ByteArray
,
tlv_0006_encr
:
ByteArray
?
=
null
)
{
private
fun
DataOutputStream
.
writePart1
(
qq
:
Long
,
password
:
String
,
loginTime
:
Int
,
loginIP
:
String
,
tgtgtKey
:
ByteArray
,
token0825
:
ByteArray
,
tlv_0006_encr
:
ByteArray
?
=
null
)
{
//this.writeInt(System.currentTimeMillis().toInt())
//this.writeInt(System.currentTimeMillis().toInt())
this
.
writeHex
(
"01 12"
)
//tag
this
.
writeHex
(
"01 12"
)
//tag
...
@@ -110,12 +111,12 @@ private fun DataOutputStream.writePart1(qq: Int, password: String, loginTime: In
...
@@ -110,12 +111,12 @@ private fun DataOutputStream.writePart1(qq: Int, password: String, loginTime: In
this
.
writeTLV0006
(
qq
,
password
,
loginTime
,
loginIP
,
tgtgtKey
)
this
.
writeTLV0006
(
qq
,
password
,
loginTime
,
loginIP
,
tgtgtKey
)
}
}
//fix
//fix
this
.
writeHex
(
Protocol
.
_0836_622_fix
2
)
this
.
writeHex
(
Protocol
.
passwordSubmissionKey
2
)
this
.
writeHex
(
"00 1A"
)
//tag
this
.
writeHex
(
"00 1A"
)
//tag
this
.
writeHex
(
"00 40"
)
//length
this
.
writeHex
(
"00 40"
)
//length
this
.
write
(
TEA
Cryptor
.
encrypt
(
Protocol
.
_0836_622_fix
2
.
hexToBytes
(),
tgtgtKey
))
this
.
write
(
TEA
.
encrypt
(
Protocol
.
passwordSubmissionKey
2
.
hexToBytes
(),
tgtgtKey
))
this
.
writeHex
(
Protocol
.
_0825d
ata0
)
this
.
writeHex
(
Protocol
.
constantD
ata0
)
this
.
writeHex
(
Protocol
.
_0825data2
)
this
.
writeHex
(
Protocol
.
constantData1
)
this
.
writeQQ
(
qq
)
this
.
writeQQ
(
qq
)
this
.
writeZero
(
4
)
this
.
writeZero
(
4
)
...
...
mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ClientLoginVerificationCodePacket.kt
deleted
100644 → 0
View file @
5b07f09d
package
net.mamoe.mirai.network.packet.login
import
net.mamoe.mirai.network.Protocol
import
net.mamoe.mirai.network.packet.*
import
net.mamoe.mirai.utils.ByteArrayDataOutputStream
import
net.mamoe.mirai.utils.TEACryptor
/**
* @author Him188moe
*/
@PacketId
(
"00 BA 31 01"
)
@ExperimentalUnsignedTypes
class
ClientLoginVerificationCodePacket
(
private
val
qq
:
Int
,
private
val
token0825
:
ByteArray
,
private
val
sequence
:
Int
,
private
val
token00BA
:
ByteArray
)
:
ClientPacket
()
{
override
fun
encode
()
{
this
.
writeQQ
(
qq
)
this
.
writeHex
(
Protocol
.
fixVer
)
this
.
writeHex
(
Protocol
.
_00BaKey
)
this
.
write
(
TEACryptor
.
CRYPTOR_00BAKEY
.
encrypt
(
object
:
ByteArrayDataOutputStream
()
{
override
fun
toByteArray
():
ByteArray
{
this
.
writeHex
(
"00 02 00 00 08 04 01 E0"
)
this
.
writeHex
(
Protocol
.
_0825data2
)
this
.
writeHex
(
"00 00 38"
)
this
.
write
(
token0825
)
this
.
writeHex
(
"01 03 00 19"
)
this
.
writeHex
(
Protocol
.
publicKey
)
this
.
writeHex
(
"13 00 05 00 00 00 00"
)
this
.
writeVarInt
(
sequence
.
toUInt
())
this
.
writeHex
(
"00 28"
)
this
.
write
(
token00BA
)
this
.
writeHex
(
"00 10"
)
this
.
writeHex
(
Protocol
.
_00BaFixKey
)
return
super
.
toByteArray
()
}
}.
toByteArray
()))
}
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/LoginState.kt
0 → 100644
View file @
93dc8e58
package
net.mamoe.mirai.network.packet.login
/**
* @author Him188moe
*/
enum
class
LoginState
{
/**
* 登录成功
*/
SUCCEED
,
/**
* 密码错误
*/
WRONG_PASSWORD
,
/**
* 被冻结
*/
BLOCKED
,
/**
* QQ 号码输入有误
*/
UNKNOWN_QQ_NUMBER
,
/**
* 账号开启了设备锁. 暂不支持设备锁登录
*/
DEVICE_LOCK
,
/**
* 账号被回收
*/
TAKEN_BACK
,
/**
* 需要验证码登录
*/
VERIFICATION_CODE
,
/**
* 未知. 更换服务器或等几分钟再登录可能解决.
*/
UNKNOWN
,
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponseFailedPacket.kt
View file @
93dc8e58
...
@@ -6,19 +6,7 @@ import java.io.DataInputStream
...
@@ -6,19 +6,7 @@ import java.io.DataInputStream
/**
/**
* @author Him188moe
* @author Him188moe
*/
*/
class
ServerLoginResponseFailedPacket
(
val
state
:
State
,
input
:
DataInputStream
)
:
ServerPacket
(
input
)
{
class
ServerLoginResponseFailedPacket
(
val
loginState
:
LoginState
,
input
:
DataInputStream
)
:
ServerPacket
(
input
)
{
enum
class
State
{
WRONG_PASSWORD
,
// UNKNOWN,//? 要再次发送某数据包
RETYPE_PASSWORD
,
//similar to [WRONG_PASSWORD]
BLOCKED
,
//你的帐号存在被盗风险,已进入保护模式
UNKNOWN_QQ_NUMBER
,
//你输入的帐号不存在
DEVICE_LOCK
,
//设备锁
TAKEN_BACK
,
//被回收
// VERIFICATION_CODE,//需要验证码
// SUCCEED,
}
override
fun
decode
()
{
override
fun
decode
()
{
}
}
}
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponsePasswordVerifiedPacket.kt
View file @
93dc8e58
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.*
import
net.mamoe.mirai.network.packet.goto
import
net.mamoe.mirai.utils.TEA
import
net.mamoe.mirai.network.packet.readNBytesAt
import
net.mamoe.mirai.utils.TestedSuccessfully
import
net.mamoe.mirai.network.packet.readVarString
import
net.mamoe.mirai.util.TestedSuccessfully
import
net.mamoe.mirai.utils.TEACryptor
import
net.mamoe.mirai.utils.hexToBytes
import
net.mamoe.mirai.utils.toUHexString
import
net.mamoe.mirai.utils.toUHexString
import
java.io.DataInputStream
import
java.io.DataInputStream
...
@@ -15,8 +11,8 @@ import java.io.DataInputStream
...
@@ -15,8 +11,8 @@ import java.io.DataInputStream
* @author NaturalHG
* @author NaturalHG
*/
*/
class
ServerLoginResponseSuccessPacket
(
input
:
DataInputStream
)
:
ServerPacket
(
input
)
{
class
ServerLoginResponseSuccessPacket
(
input
:
DataInputStream
)
:
ServerPacket
(
input
)
{
lateinit
var
_0828_rec_decr_k
ey
:
ByteArray
//16 bytes|
lateinit
var
sessionResponseDecryptionK
ey
:
ByteArray
//16 bytes|
lateinit
var
nick
:
String
lateinit
var
nick
name
:
String
lateinit
var
token38
:
ByteArray
lateinit
var
token38
:
ByteArray
lateinit
var
token88
:
ByteArray
lateinit
var
token88
:
ByteArray
...
@@ -26,72 +22,6 @@ class ServerLoginResponseSuccessPacket(input: DataInputStream) : ServerPacket(in
...
@@ -26,72 +22,6 @@ class ServerLoginResponseSuccessPacket(input: DataInputStream) : ServerPacket(in
@TestedSuccessfully
@TestedSuccessfully
@ExperimentalUnsignedTypes
@ExperimentalUnsignedTypes
override
fun
decode
()
{
override
fun
decode
()
{
//测试完成 @NaturalHG
/**
* Version 1 @Deprecated
this.input.skip(7)//8
encryptionKey = this.input.readNBytesAt(16)//24
this.input.skip(2)//25->26
token38 = this.input.readNBytesAt(56)//81->82
this.input.skip(60L)//142
//??
var b = this.input.readNBytesAt(2)
val msgLength = when (b.toUByteArray().toUHexString()) {
"01 07" -> 0
"00 33" -> 28
"01 10" -> 65
else -> throw IllegalStateException()
}//144
System.out.println(msgLength)
this.input.skip(17L + msgLength)//161+msgLength
this.input.skip(10)//171+msgLength
_0828_rec_decr_key = this.input.readNBytesAt(16)//187+msgLength
this.input.skip(2)
token88 = this.input.readNBytesAt(136)//325+ // msgLength
this.input.skip(299L)//624+msgLength
//varString (nickLength bytes)
val nickLength = this.input.readByteAt().toInt()//625+msgLength
System.out.println(nickLength)
nick = this.input.readVarString(nickLength)//625+msgLength+nickLength
val dataIndex = packetDataLength - 31
/*
this.input.skip((dataIndex - (625 + msgLength + nickLength)) + 0L)//-31
gender = this.input.readByteAt().toUByte().toInt()//-30
this.input.skip(9)//-27
age = this.input.readShortAt()//-25
*/
age = 0
gender = 0
/*
age = HexToDec(取文本中间(data, 取文本长度(data) - 82, 5))
gender = 取文本中间(data, 取文本长度(data) - 94, 2)
*/
* **/
/** version 2 */
this
.
input
.
skip
(
7
)
//8
this
.
input
.
skip
(
7
)
//8
this
.
encryptionKey
=
this
.
input
.
readNBytes
(
16
)
//24
this
.
encryptionKey
=
this
.
input
.
readNBytes
(
16
)
//24
...
@@ -106,32 +36,25 @@ class ServerLoginResponseSuccessPacket(input: DataInputStream) : ServerPacket(in
...
@@ -106,32 +36,25 @@ class ServerLoginResponseSuccessPacket(input: DataInputStream) : ServerPacket(in
else
->
throw
IllegalStateException
(
id
)
else
->
throw
IllegalStateException
(
id
)
}
}
this
.
_0828_rec_decr_k
ey
=
this
.
input
.
readNBytesAt
(
171
+
msgLength
,
16
)
this
.
sessionResponseDecryptionK
ey
=
this
.
input
.
readNBytesAt
(
171
+
msgLength
,
16
)
this
.
token88
=
this
.
input
.
readNBytesAt
(
189
+
msgLength
,
136
)
this
.
token88
=
this
.
input
.
readNBytesAt
(
189
+
msgLength
,
136
)
val
nickLength
=
this
.
input
.
goto
(
624
+
msgLength
).
readByte
().
toInt
()
val
nickLength
=
this
.
input
.
goto
(
624
+
msgLength
).
readByte
().
toInt
()
this
.
nick
=
this
.
input
.
readVarString
(
nickLength
)
this
.
nick
name
=
this
.
input
.
readVarString
(
nickLength
)
//this.age = this.input.goto(packetDataLength - 28).readShortAt()
//this.age = this.input.goto(packetDataLength - 28).readShortAt()
//this.gender = this.input.goto(packetDataLength - 32).readByteAt().toInt()
//this.gender = this.input.goto(packetDataLength - 32).readByteAt().toInt()
}
}
}
class
ServerLoginResponseSuccessPacketEncrypted
(
input
:
DataInputStream
)
:
ServerPacket
(
input
)
{
override
fun
decode
()
{
class
Encrypted
(
input
:
DataInputStream
)
:
ServerPacket
(
input
)
{
@ExperimentalUnsignedTypes
fun
decrypt
(
tgtgtKey
:
ByteArray
):
ServerLoginResponseSuccessPacket
{
input
goto
14
return
ServerLoginResponseSuccessPacket
(
TEA
.
decrypt
(
TEA
.
decrypt
(
input
.
readAllBytes
().
cutTail
(
1
),
Protocol
.
shareKey
),
tgtgtKey
).
dataInputStream
());
}
}
}
@ExperimentalUnsignedTypes
}
fun
decrypt
(
tgtgtKey
:
ByteArray
):
ServerLoginResponseSuccessPacket
{
\ No newline at end of file
input
goto
14
var
bytes
=
input
.
readAllBytes
()
bytes
=
bytes
.
copyOfRange
(
0
,
bytes
.
size
-
1
)
println
(
bytes
.
toUByteArray
().
toUHexString
())
return
ServerLoginResponseSuccessPacket
(
DataInputStream
(
TEACryptor
.
decrypt
(
TEACryptor
.
decrypt
(
bytes
,
Protocol
.
shareKey
.
hexToBytes
()),
tgtgtKey
).
inputStream
()));
//TeaDecrypt(取文本中间(data, 43, 取文本长度(data) - 45), m_0828_rec_decr_key)
}
}
mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponseResendPacket.kt
View file @
93dc8e58
...
@@ -2,12 +2,8 @@ package net.mamoe.mirai.network.packet.login
...
@@ -2,12 +2,8 @@ package net.mamoe.mirai.network.packet.login
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.dataInputStream
import
net.mamoe.mirai.network.packet.goto
import
net.mamoe.mirai.network.packet.goto
import
net.mamoe.mirai.util.TestedSuccessfully
import
net.mamoe.mirai.utils.TestedSuccessfully
import
net.mamoe.mirai.utils.TEACryptor
import
net.mamoe.mirai.utils.hexToUBytes
import
net.mamoe.mirai.utils.toUHexString
import
java.io.DataInputStream
import
java.io.DataInputStream
/**
/**
...
@@ -45,33 +41,9 @@ class ServerLoginResponseResendPacket(input: DataInputStream, val flag: Flag) :
...
@@ -45,33 +41,9 @@ class ServerLoginResponseResendPacket(input: DataInputStream, val flag: Flag) :
}
}
}
}
}
}
}
class
ServerLoginResponseResendPacketEncrypted
(
input
:
DataInputStream
,
private
val
flag
:
ServerLoginResponseResendPacket
.
Flag
)
:
ServerPacket
(
input
)
{
override
fun
decode
()
{
}
class
Encrypted
(
input
:
DataInputStream
,
private
val
flag
:
Flag
)
:
ServerPacket
(
input
)
{
@TestedSuccessfully
@TestedSuccessfully
fun
decrypt
(
tgtgtKey
:
ByteArray
):
ServerLoginResponseResendPacket
=
ServerLoginResponseResendPacket
(
decryptBy
(
tgtgtKey
),
flag
)
fun
decrypt
(
tgtgtKey
:
ByteArray
):
ServerLoginResponseResendPacket
{
//this.input.skip(7)
this
.
input
goto
14
var
data
:
ByteArray
=
this
.
input
.
readAllBytes
()
data
=
TEACryptor
.
CRYPTOR_SHARE_KEY
.
decrypt
(
data
.
let
{
it
.
copyOfRange
(
0
,
it
.
size
-
1
)
});
data
=
TEACryptor
.
decrypt
(
data
,
tgtgtKey
)
return
ServerLoginResponseResendPacket
(
data
.
dataInputStream
(),
flag
)
}
}
}
}
fun
main
()
{
val
tgtgtkey
=
"9E 83 61 FF 18 61 4B 77 34 FE 1C 9C E2 03 B4 F2"
.
hexToUBytes
()
ServerLoginResponseResendPacketEncrypted
(
"02 37 13 08 36 31 03 76 E4 B8 DD 00 00 00 94 9B 87 00 87 7F 9E D0 E5 6A F6 17 41 02 0C AA F3 AC C8 CF 4E C6 9D EC FA 6C BD F8 7C 4B A5 28 80 CC DE B5 0A 41 8E 63 CE 5E 30 D8 A6 83 92 0E 2E 5C 35 E5 6E 62 3D FE 17 DD 7C 47 9A AD EF F0 F7 2A 6F 21 32 99 1B 6D E1 DA BE 68 2F 26 A9 93 DE 1B 4F 11 F0 AF A1 06 7B 85 53 46 D2 A3 DD A6 BE F2 76 8A 61 BF 15 FD 17 C4 45 DB EC 05 51 56 46 63 48 87 49 79 0D 40 DF 9D D9 99 93 EC D0 44 7B 4A 79 EB BD 08 10 18 29 0E 85 EE 26 A0 CD 40 00 2F 3E ED F4 A4 C3 01 5E 82 F5 A8 02 FA 70 EB F2 07 AD FF 0E DA 08 7A 3A FE B6 F4 5D 98 18 F7 58 C2 19 21 AF 29 D2 95 16 CE C4 A3 5F B0 E6 23 C2 B2 C6 5F 03 42 C2 44 C2 B0 A0 3F 95 8E 89 EF FC EC E4 BF 03 CB DA 9C D3 84 3F 9B A0 F1 B4 14 6E 23 D5 74 79 6F 89 DA B8 33 DB EF 0B 21 E1 27 27 57 8B 56 CB D9 BF C2 A8 25 6E 48 23 EB 31 9D 03"
.
hexToUBytes
().
toByteArray
().
dataInputStream
(),
ServerLoginResponseResendPacket
.
Flag
.
`
08
36
31
03
`
).
decrypt
(
tgtgtkey
.
toByteArray
()).
let
{
it
.
decode
();
println
(
it
.
_0836_tlv0006_encr
.
toUHexString
())
}
val
data
=
"94 9B 87 00 87 7F 9E D0 E5 6A F6 17 41 02 0C AA F3 AC C8 CF 4E C6 9D EC FA 6C BD F8 7C 4B A5 28 80 CC DE B5 0A 41 8E 63 CE 5E 30 D8 A6 83 92 0E 2E 5C 35 E5 6E 62 3D FE 17 DD 7C 47 9A AD EF F0 F7 2A 6F 21 32 99 1B 6D E1 DA BE 68 2F 26 A9 93 DE 1B 4F 11 F0 AF A1 06 7B 85 53 46 D2 A3 DD A6 BE F2 76 8A 61 BF 15 FD 17 C4 45 DB EC 05 51 56 46 63 48 87 49 79 0D 40 DF 9D D9 99 93 EC D0 44 7B 4A 79 EB BD 08 10 18 29 0E 85 EE 26 A0 CD 40 00 2F 3E ED F4 A4 C3 01 5E 82 F5 A8 02 FA 70 EB F2 07 AD FF 0E DA 08 7A 3A FE B6 F4 5D 98 18 F7 58 C2 19 21 AF 29 D2 95 16 CE C4 A3 5F B0 E6 23 C2 B2 C6 5F 03 42 C2 44 C2 B0 A0 3F 95 8E 89 EF FC EC E4 BF 03 CB DA 9C D3 84 3F 9B A0 F1 B4 14 6E 23 D5 74 79 6F 89 DA B8 33 DB EF 0B 21 E1 27 27 57 8B 56 CB D9 BF C2 A8 25 6E 48 23 EB 31 9D"
.
hexToUBytes
()
val
d1
=
TEACryptor
.
CRYPTOR_SHARE_KEY
.
decrypt
(
data
.
toByteArray
())
ServerLoginResponseResendPacket
(
TEACryptor
.
decrypt
(
d1
,
tgtgtkey
.
toByteArray
()).
dataInputStream
(),
ServerLoginResponseResendPacket
.
Flag
.
`
08
36
31
03
`
).
let
{
it
.
decode
();
println
(
it
.
_0836_tlv0006_encr
.
toUHexString
())
}
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponseVerificationCodeInitPacket.kt
0 → 100644
View file @
93dc8e58
package
net.mamoe.mirai.network.packet.login
import
net.mamoe.mirai.network.packet.ServerPacket
import
net.mamoe.mirai.network.packet.cutTail
import
net.mamoe.mirai.network.packet.dataInputStream
import
net.mamoe.mirai.network.packet.goto
import
net.mamoe.mirai.utils.TEA
import
net.mamoe.mirai.utils.TestedSuccessfully
import
net.mamoe.mirai.utils.hexToUBytes
import
java.io.DataInputStream
/**
* 收到这个包意味着需要验证码登录, 并且能得到验证码图片文件的一半
*
* @author Him188moe
*/
class
ServerLoginResponseVerificationCodeInitPacket
(
input
:
DataInputStream
,
private
val
packetLength
:
Int
)
:
ServerPacket
(
input
)
{
lateinit
var
verifyCodePart1
:
ByteArray
lateinit
var
token00BA
:
ByteArray
var
unknownBoolean
:
Boolean
?
=
null
@TestedSuccessfully
@ExperimentalUnsignedTypes
override
fun
decode
()
{
val
verifyCodeLength
=
this
.
input
.
goto
(
78
).
readShort
()
//2bytes
this
.
verifyCodePart1
=
this
.
input
.
readNBytes
(
verifyCodeLength
.
toInt
())
this
.
input
.
skip
(
1
)
this
.
unknownBoolean
=
this
.
input
.
readByte
().
toInt
()
==
1
this
.
token00BA
=
this
.
input
.
goto
(
packetLength
-
60
).
readNBytes
(
40
)
}
class
Encrypted
(
input
:
DataInputStream
)
:
ServerPacket
(
input
)
{
override
fun
decode
()
{
}
fun
decrypt
():
ServerLoginResponseVerificationCodeInitPacket
{
this
.
input
goto
14
val
data
=
TEA
.
CRYPTOR_SHARE_KEY
.
decrypt
(
this
.
input
.
readAllBytes
().
cutTail
(
1
));
return
ServerLoginResponseVerificationCodeInitPacket
(
data
.
dataInputStream
(),
data
.
size
)
}
}
}
fun
main
()
{
val
data
=
"FB 01 04 03 33 00 01 00 BA 02 03 2C 13 00 05 01 00 00 01 23 00 38 D5 01 05 8B 67 4D 52 5A FA 92 DB 99 18 D4 F0 72 03 E0 17 71 7C 8A 45 74 1F C3 2D F8 61 96 0D 93 0D 8C 51 95 70 F8 F9 CB B9 2D 5D BC 4F 5D 89 5F E7 59 8C E4 E5 A2 04 56 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 45 50 4C 54 45 FE F6 ED E2 F1 DF F3 FF F2 11 77 48 FE FE F3 F1 F9 EA D7 FD E7 F8 F9 EC FC EF E7 E8 FF EE 2D 69 48 2A 8A 5D 29 7A 52 F0 ED E1 A9 C7 B1 65 96 79 AB E0 C2 C3 F0 D5 42 7D 5C 4A 99 72 89 AA 93 51 73 5C 6E BA 94 42 BD 7A 0B 00 00 09 C5 49 44 41 54 58 C3 AC 99 8B 76 AB 3A 12 44 91 D0 1B 10 08 04 FF FF A9 B3 5B 60 C7 AF 38 77 EE 0C EB C4 76 6C 07 95 BA AB AB AB 75 BA EE 1F 5D DE CB 63 08 C1 C7 A8 AD BC B6 31 46 6B 3B A3 79 94 E7 F3 63 79 E4 D9 98 89 37 7D F7 FF BB 3C 10 82 6F B7 F7 2A B6 5B 07 EF B5 16 60 DE 1B 63 3A 1F 7E BE 6D 0C 50 EC 09 E1 FE 76 B8 3F FC 6B 0C 1D 5B 37 1F 3E E1 AE 61 9A D8 B6 07 93 B7 56 4D 66 22 06 9D FC EE 5F BF F9 3F 81 90 BB 99 F3 49 E2 1D DA 43 38 13 44 14 8C 9D B4 8E E7 65 40 11 E4 BB FE 8C 5B 78 41 F1 AF 01 48 2E 08 6D 8B AD F1 BA 05 F9 C4 E0 25 E6 31 BA EB 2A 90 C3 74 26 FC 1E 80 CF 14 91 44 7F FC 39 FF D4 37 10 82 C0 B3 B0 67 BF 2E 5E 5B F4 46 E5 3A 5F D7 BE A6 54 17 2D 7C 0D D7 DA E1 7E 93 C7 E5 DB 9E 6E 9F FD A3 14 9C 7F 23 97 55 FA DC 6F 74 8A CC 04 49 03 3F DE 4E 5C 4A 95 9C 53 8D 7A EA 82 F9 10 77 7F EE E5 43 28 C2 9F 00 BA 5B C0 59 A4 CE DB BA AE DB BC 14 D5 2A 82 A5 83 E0 30 92 19 A8 99 36 A7 15 7C BC DF F6 BE D7 86 C0 7F C9 C5 ED 93 C7 1F B9 E0 56 CB AC 61 F5 5D 2E 00 F0 93 D2 5A 9D B6 B0 3F 4B 4D 5C B9 0F C1 EE 29 46 65 4E 40 46 E2 E4 1B 91 C3 A5 2E FE D3 7A 3C 84 0B E3 F3 E2 57 16 2F 08 B9 E6 5A 73 29 65 29 4E B9 25 CF 6B 9A 97 48 20 B2 35 46 1B 6D AD D6 9A 57 69 45 B2 1A 00 90 05 51 8D C7 24 F8 1B B9 FE A6 41 B8 83 6C 59 05 84 9F 44 0F 85 05 9A 97 5A 97 BC A6 6D 81 FE 59 DE 2F 4B 5E E4 DF B2 A4 19 AA 06 D9 FE F9 33 4D 7E 6A 40 FC 97 34 BF 84 E4 81 81 ED E9 DC 85 32 56 47 E5 A4 F0 2D 6F 4D 2A BA 65 4B 73 89 B6 58 5E D7 35 8D 69 E4 4A 6B 76 50 C1 5C 3A D9 59 11 CF 37 99 FA 48 88 70 7F F4 9F 22 12 F2 24 91 3E 2B BF 28 A5 34 68 C0 50 A3 55 DD A4 E3 9C 6E 85 99 95 B6 24 2E 18 D9 3C 5C B1 4D AA 2F 08 E1 75 F1 F0 6B 49 FC BC E3 8D 00 01 00 28 42 E6 18 57 D4 B1 4D AE 51 27 D5 EF A2 38 91 39 15 37 6C 5A FE 75 93 49 DB FC 57 3C 12 3F 26 D9 16 1D 83 45 8B 78 39 D8 01 15 00 10 F6 F0 50 03 74 BB 18 91 D3 55 8D 7F BB 53 15 7A"
.
hexToUBytes
().
toByteArray
();
ServerLoginResponseVerificationCodeInitPacket
(
data
.
dataInputStream
(),
data
.
size
).
let
{
it
.
decode
();
println
(
it
)
}
}
/*
data
FB 01 04 03 33 00 01 00 BA 02 03 2C 13 00 05 01 00 00 01 23 00 38 D5 01 05 8B 67 4D 52 5A FA 92 DB 99 18 D4 F0 72 03 E0 17 71 7C 8A 45 74 1F C3 2D F8 61 96 0D 93 0D 8C 51 95 70 F8 F9 CB B9 2D 5D BC 4F 5D 89 5F E7 59 8C E4 E5 A2 04 56 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 45 50 4C 54 45 FE F6 ED E2 F1 DF F3 FF F2 11 77 48 FE FE F3 F1 F9 EA D7 FD E7 F8 F9 EC FC EF E7 E8 FF EE 2D 69 48 2A 8A 5D 29 7A 52 F0 ED E1 A9 C7 B1 65 96 79 AB E0 C2 C3 F0 D5 42 7D 5C 4A 99 72 89 AA 93 51 73 5C 6E BA 94 42 BD 7A 0B 00 00 09 C5 49 44 41 54 58 C3 AC 99 8B 76 AB 3A 12 44 91 D0 1B 10 08 04 FF FF A9 B3 5B 60 C7 AF 38 77 EE 0C EB C4 76 6C 07 95 BA AB AB AB 75 BA EE 1F 5D DE CB 63 08 C1 C7 A8 AD BC B6 31 46 6B 3B A3 79 94 E7 F3 63 79 E4 D9 98 89 37 7D F7 FF BB 3C 10 82 6F B7 F7 2A B6 5B 07 EF B5 16 60 DE 1B 63 3A 1F 7E BE 6D 0C 50 EC 09 E1 FE 76 B8 3F FC 6B 0C 1D 5B 37 1F 3E E1 AE 61 9A D8 B6 07 93 B7 56 4D 66 22 06 9D FC EE 5F BF F9 3F 81 90 BB 99 F3 49 E2 1D DA 43 38 13 44 14 8C 9D B4 8E E7 65 40 11 E4 BB FE 8C 5B 78 41 F1 AF 01 48 2E 08 6D 8B AD F1 BA 05 F9 C4 E0 25 E6 31 BA EB 2A 90 C3 74 26 FC 1E 80 CF 14 91 44 7F FC 39 FF D4 37 10 82 C0 B3 B0 67 BF 2E 5E 5B F4 46 E5 3A 5F D7 BE A6 54 17 2D 7C 0D D7 DA E1 7E 93 C7 E5 DB 9E 6E 9F FD A3 14 9C 7F 23 97 55 FA DC 6F 74 8A CC 04 49 03 3F DE 4E 5C 4A 95 9C 53 8D 7A EA 82 F9 10 77 7F EE E5 43 28 C2 9F 00 BA 5B C0 59 A4 CE DB BA AE DB BC 14 D5 2A 82 A5 83 E0 30 92 19 A8 99 36 A7 15 7C BC DF F6 BE D7 86 C0 7F C9 C5 ED 93 C7 1F B9 E0 56 CB AC 61 F5 5D 2E 00 F0 93 D2 5A 9D B6 B0 3F 4B 4D 5C B9 0F C1 EE 29 46 65 4E 40 46 E2 E4 1B 91 C3 A5 2E FE D3 7A 3C 84 0B E3 F3 E2 57 16 2F 08 B9 E6 5A 73 29 65 29 4E B9 25 CF 6B 9A 97 48 20 B2 35 46 1B 6D AD D6 9A 57 69 45 B2 1A 00 90 05 51 8D C7 24 F8 1B B9 FE A6 41 B8 83 6C 59 05 84 9F 44 0F 85 05 9A 97 5A 97 BC A6 6D 81 FE 59 DE 2F 4B 5E E4 DF B2 A4 19 AA 06 D9 FE F9 33 4D 7E 6A 40 FC 97 34 BF 84 E4 81 81 ED E9 DC 85 32 56 47 E5 A4 F0 2D 6F 4D 2A BA 65 4B 73 89 B6 58 5E D7 35 8D 69 E4 4A 6B 76 50 C1 5C 3A D9 59 11 CF 37 99 FA 48 88 70 7F F4 9F 22 12 F2 24 91 3E 2B BF 28 A5 34 68 C0 50 A3 55 DD A4 E3 9C 6E 85 99 95 B6 24 2E 18 D9 3C 5C B1 4D AA 2F 08 E1 75 F1 F0 6B 49 FC BC E3 8D 00 01 00 28 42 E6 18 57 D4 B1 4D AE 51 27 D5 EF A2 38 91 39 15 37 6C 5A FE 75 93 49 DB FC 57 3C 12 3F 26 D9 16 1D 83 45 8B 78 39 D8 01 15 00 10 F6 F0 50 03 74 BB 18 91 D3 55 8D 7F BB 53 15 7A
length 700
verify code
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 45 50 4C 54 45 FE F6 ED E2 F1 DF F3 FF F2 11 77 48 FE FE F3 F1 F9 EA D7 FD E7 F8 F9 EC FC EF E7 E8 FF EE 2D 69 48 2A 8A 5D 29 7A 52 F0 ED E1 A9 C7 B1 65 96 79 AB E0 C2 C3 F0 D5 42 7D 5C 4A 99 72 89 AA 93 51 73 5C 6E BA 94 42 BD 7A 0B 00 00 09 C5 49 44 41 54 58 C3 AC 99 8B 76 AB 3A 12 44 91 D0 1B 10 08 04 FF FF A9 B3 5B 60 C7 AF 38 77 EE 0C EB C4 76 6C 07 95 BA AB AB AB 75 BA EE 1F 5D DE CB 63 08 C1 C7 A8 AD BC B6 31 46 6B 3B A3 79 94 E7 F3 63 79 E4 D9 98 89 37 7D F7 FF BB 3C 10 82 6F B7 F7 2A B6 5B 07 EF B5 16 60 DE 1B 63 3A 1F 7E BE 6D 0C 50 EC 09 E1 FE 76 B8 3F FC 6B 0C 1D 5B 37 1F 3E E1 AE 61 9A D8 B6 07 93 B7 56 4D 66 22 06 9D FC EE 5F BF F9 3F 81 90 BB 99 F3 49 E2 1D DA 43 38 13 44 14 8C 9D B4 8E E7 65 40 11 E4 BB FE 8C 5B 78 41 F1 AF 01 48 2E 08 6D 8B AD F1 BA 05 F9 C4 E0 25 E6 31 BA EB 2A 90 C3 74 26 FC 1E 80 CF 14 91 44 7F FC 39 FF D4 37 10 82 C0 B3 B0 67 BF 2E 5E 5B F4 46 E5 3A 5F D7 BE A6 54 17 2D 7C 0D D7 DA E1 7E 93 C7 E5 DB 9E 6E 9F FD A3 14 9C 7F 23 97 55 FA DC 6F 74 8A CC 04 49 03 3F DE 4E 5C 4A 95 9C 53 8D 7A EA 82 F9 10 77 7F EE E5 43 28 C2 9F 00 BA 5B C0 59 A4 CE DB BA AE DB BC 14 D5 2A 82 A5 83 E0 30 92 19 A8 99 36 A7 15 7C BC DF F6 BE D7 86 C0 7F C9 C5 ED 93 C7 1F B9 E0 56 CB AC 61 F5 5D 2E 00 F0 93 D2 5A 9D B6 B0 3F 4B 4D 5C B9 0F C1 EE 29 46 65 4E 40 46 E2 E4 1B 91 C3 A5 2E FE D3 7A 3C 84 0B E3 F3 E2 57 16 2F 08 B9 E6 5A 73 29 65 29 4E B9 25 CF 6B 9A 97 48 20 B2 35 46 1B 6D AD D6 9A 57 69 45 B2 1A 00 90 05 51 8D C7 24 F8 1B B9 FE A6 41 B8 83 6C 59 05 84 9F 44 0F 85 05 9A 97 5A 97 BC A6 6D 81 FE 59 DE 2F 4B 5E E4 DF B2 A4 19 AA 06 D9 FE F9 33 4D 7E 6A 40 FC 97 34 BF 84 E4 81 81 ED E9 DC 85 32 56 47 E5 A4 F0 2D 6F 4D 2A BA 65 4B 73 89 B6 58 5E D7 35 8D 69 E4 4A 6B 76 50 C1 5C 3A D9 59 11 CF 37 99 FA 48 88 70 7F F4 9F 22 12 F2 24 91 3E 2B BF 28 A5 34 68 C0 50 A3 55 DD A4 E3 9C 6E 85 99 95 B6 24 2E 18 D9 3C 5C B1 4D AA 2F 08 E1 75 F1 F0 6B 49 FC BC E3 8D
token00ba
42 E6 18 57 D4 B1 4D AE 51 27 D5 EF A2 38 91 39 15 37 6C 5A FE 75 93 49 DB FC 57 3C 12 3F 26 D9 16 1D 83 45 8B 78 39 D8
*/
mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginResponseVerificationCodePacket.kt
deleted
100644 → 0
View file @
5b07f09d
package
net.mamoe.mirai.network.packet.login
import
net.mamoe.mirai.network.packet.ServerPacket
import
net.mamoe.mirai.network.packet.dataInputStream
import
net.mamoe.mirai.network.packet.goto
import
net.mamoe.mirai.utils.TEACryptor
import
java.io.DataInputStream
/**
* @author Him188moe
*/
class
ServerLoginResponseVerificationCodePacket
(
input
:
DataInputStream
,
private
val
packetLength
:
Int
)
:
ServerPacket
(
input
)
{
lateinit
var
verifyCode
:
ByteArray
lateinit
var
token00BA
:
ByteArray
var
unknownBoolean
:
Boolean
?
=
null
@ExperimentalUnsignedTypes
override
fun
decode
()
{
val
verifyCodeLength
=
this
.
input
.
goto
(
78
).
readShort
()
//2bytes
this
.
verifyCode
=
this
.
input
.
readNBytes
(
verifyCodeLength
.
toInt
())
this
.
input
.
skip
(
1
)
this
.
unknownBoolean
=
this
.
input
.
readByte
().
toInt
()
==
1
this
.
token00BA
=
this
.
input
.
goto
(
packetLength
-
60
).
readNBytes
(
40
)
}
}
class
ServerLoginResponseVerificationCodePacketEncrypted
(
input
:
DataInputStream
)
:
ServerPacket
(
input
)
{
override
fun
decode
()
{
}
fun
decrypt
():
ServerLoginResponseVerificationCodePacket
{
this
.
input
goto
14
val
data
=
TEACryptor
.
CRYPTOR_SHARE_KEY
.
decrypt
(
this
.
input
.
readAllBytes
().
let
{
it
.
copyOfRange
(
0
,
it
.
size
-
1
)
});
return
ServerLoginResponseVerificationCodePacket
(
data
.
dataInputStream
(),
data
.
size
)
}
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/ServerLoginSuccessPacket.kt
View file @
93dc8e58
...
@@ -4,10 +4,8 @@ import net.mamoe.mirai.network.packet.ServerPacket
...
@@ -4,10 +4,8 @@ import net.mamoe.mirai.network.packet.ServerPacket
import
java.io.DataInputStream
import
java.io.DataInputStream
/**
/**
* Congratulations!
*
* @author Him188moe
* @author Him188moe
*/
*/
class
ServerLoginSuccessPacket
(
input
:
DataInputStream
)
:
ServerPacket
(
input
)
{
class
ServerLoginSuccessPacket
(
input
:
DataInputStream
)
:
ServerPacket
(
input
)
override
fun
decode
()
{
\ No newline at end of file
}
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/network/packet/verification/ServerVerificationCodePacket.kt
deleted
100644 → 0
View file @
5b07f09d
package
net.mamoe.mirai.network.packet.verification
import
net.mamoe.mirai.network.packet.ServerPacket
import
net.mamoe.mirai.network.packet.dataInputStream
import
net.mamoe.mirai.network.packet.goto
import
net.mamoe.mirai.utils.TEACryptor
import
java.io.DataInputStream
/**
* @author Him188moe
*/
class
ServerVerificationCodePacket
(
input
:
DataInputStream
)
:
ServerPacket
(
input
)
{
lateinit
var
verifyCode
:
ByteArray
lateinit
var
verifyToken
:
ByteArray
var
unknownBoolean
:
Boolean
?
=
null
lateinit
var
token00BA
:
ByteArray
var
count
:
Int
=
0
@ExperimentalUnsignedTypes
override
fun
decode
()
{
TODO
()
val
verifyCodeLength
=
this
.
input
.
goto
(
78
).
readShort
()
//2bytes
this
.
verifyCode
=
this
.
input
.
readNBytes
(
verifyCodeLength
.
toInt
())
this
.
input
.
skip
(
1
)
this
.
unknownBoolean
=
this
.
input
.
readByte
().
toInt
()
==
1
//this.token00BA = this.input.goto(packetLength - 60).readNBytesAt(40)
}
}
class
ServerVerificationCodePacketEncrypted
(
input
:
DataInputStream
)
:
ServerPacket
(
input
)
{
override
fun
decode
()
{
}
fun
decrypt
(
token00BA
:
ByteArray
):
ServerVerificationCodePacket
{
this
.
input
goto
14
val
data
=
TEACryptor
.
decrypt
(
token00BA
,
this
.
input
.
readAllBytes
().
let
{
it
.
copyOfRange
(
0
,
it
.
size
-
1
)
});
return
ServerVerificationCodePacket
(
data
.
dataInputStream
())
}
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/plugin/MiraiPluginBase.java
View file @
93dc8e58
package
net.mamoe.mirai.plugin
;
package
net.mamoe.mirai.plugin
;
public
class
MiraiPluginBase
{
import
net.mamoe.mirai.Robot
;
/**
* 插件基类.
* <p>
* 插件属于整个 Mirai, 而不是属于单个 {@link Robot}.
*
* @see net.mamoe.mirai.event.MiraiEventManager
* @see net.mamoe.mirai.event.MiraiEventManagerKt
*/
public
abstract
class
MiraiPluginBase
{
}
}
mirai-core/src/main/java/net/mamoe/mirai/task/MiraiTaskExceptionHandler.java
View file @
93dc8e58
...
@@ -4,15 +4,12 @@ package net.mamoe.mirai.task;
...
@@ -4,15 +4,12 @@ package net.mamoe.mirai.task;
public
interface
MiraiTaskExceptionHandler
{
public
interface
MiraiTaskExceptionHandler
{
void
onHandle
(
Throwable
e
);
void
onHandle
(
Throwable
e
);
static
MiraiTaskExceptionHandler
byDefault
(){
static
MiraiTaskExceptionHandler
printing
()
{
return
byPrint
();
return
Throwable:
:
printStackTrace
;
}
static
MiraiTaskExceptionHandler
byIgnore
(){
return
a
->
{};
}
}
static
MiraiTaskExceptionHandler
byPrint
(){
static
MiraiTaskExceptionHandler
ignoring
()
{
return
Throwable:
:
printStackTrace
;
return
a
->
{
};
}
}
}
}
mirai-core/src/main/java/net/mamoe/mirai/task/MiraiTaskManager.java
View file @
93dc8e58
...
@@ -2,7 +2,7 @@ package net.mamoe.mirai.task;
...
@@ -2,7 +2,7 @@ package net.mamoe.mirai.task;
import
net.mamoe.mirai.event.MiraiEventHook
;
import
net.mamoe.mirai.event.MiraiEventHook
;
import
net.mamoe.mirai.event.events.server.ServerDisableEvent
;
import
net.mamoe.mirai.event.events.server.ServerDisable
d
Event
;
import
java.util.concurrent.Callable
;
import
java.util.concurrent.Callable
;
import
java.util.concurrent.Future
;
import
java.util.concurrent.Future
;
...
@@ -24,7 +24,7 @@ public final class MiraiTaskManager {
...
@@ -24,7 +24,7 @@ public final class MiraiTaskManager {
this
.
pool
=
new
MiraiThreadPool
();
this
.
pool
=
new
MiraiThreadPool
();
MiraiEventHook
MiraiEventHook
.
onEvent
(
ServerDisableEvent
.
class
)
.
onEvent
(
ServerDisable
d
Event
.
class
)
.
handler
(
a
->
this
.
pool
.
close
())
.
handler
(
a
->
this
.
pool
.
close
())
.
mount
();
.
mount
();
...
@@ -35,7 +35,7 @@ public final class MiraiTaskManager {
...
@@ -35,7 +35,7 @@ public final class MiraiTaskManager {
*/
*/
public
void
execute
(
Runnable
runnable
)
{
public
void
execute
(
Runnable
runnable
)
{
this
.
execute
(
runnable
,
MiraiTaskExceptionHandler
.
byDefault
());
this
.
execute
(
runnable
,
MiraiTaskExceptionHandler
.
printing
());
}
}
public
void
execute
(
Runnable
runnable
,
MiraiTaskExceptionHandler
handler
)
{
public
void
execute
(
Runnable
runnable
,
MiraiTaskExceptionHandler
handler
)
{
...
@@ -51,7 +51,7 @@ public final class MiraiTaskManager {
...
@@ -51,7 +51,7 @@ public final class MiraiTaskManager {
public
<
D
>
Future
<
D
>
submit
(
Callable
<
D
>
callable
)
{
public
<
D
>
Future
<
D
>
submit
(
Callable
<
D
>
callable
)
{
return
this
.
submit
(
callable
,
MiraiTaskExceptionHandler
.
byDefault
());
return
this
.
submit
(
callable
,
MiraiTaskExceptionHandler
.
printing
());
}
}
public
<
D
>
Future
<
D
>
submit
(
Callable
<
D
>
callable
,
MiraiTaskExceptionHandler
handler
)
{
public
<
D
>
Future
<
D
>
submit
(
Callable
<
D
>
callable
,
MiraiTaskExceptionHandler
handler
)
{
...
@@ -69,7 +69,7 @@ public final class MiraiTaskManager {
...
@@ -69,7 +69,7 @@ public final class MiraiTaskManager {
* 异步任务
* 异步任务
*/
*/
public
<
D
>
void
ansycTask
(
Callable
<
D
>
callable
,
Consumer
<
D
>
callback
)
{
public
<
D
>
void
ansycTask
(
Callable
<
D
>
callable
,
Consumer
<
D
>
callback
)
{
this
.
ansycTask
(
callable
,
callback
,
MiraiTaskExceptionHandler
.
byDefault
());
this
.
ansycTask
(
callable
,
callback
,
MiraiTaskExceptionHandler
.
printing
());
}
}
public
<
D
>
void
ansycTask
(
Callable
<
D
>
callable
,
Consumer
<
D
>
callback
,
MiraiTaskExceptionHandler
handler
)
{
public
<
D
>
void
ansycTask
(
Callable
<
D
>
callable
,
Consumer
<
D
>
callback
,
MiraiTaskExceptionHandler
handler
)
{
...
@@ -87,7 +87,7 @@ public final class MiraiTaskManager {
...
@@ -87,7 +87,7 @@ public final class MiraiTaskManager {
*/
*/
public
void
repeatingTask
(
Runnable
runnable
,
long
intervalMillis
)
{
public
void
repeatingTask
(
Runnable
runnable
,
long
intervalMillis
)
{
this
.
repeatingTask
(
runnable
,
intervalMillis
,
MiraiTaskExceptionHandler
.
byDefault
());
this
.
repeatingTask
(
runnable
,
intervalMillis
,
MiraiTaskExceptionHandler
.
printing
());
}
}
public
void
repeatingTask
(
Runnable
runnable
,
long
intervalMillis
,
MiraiTaskExceptionHandler
handler
)
{
public
void
repeatingTask
(
Runnable
runnable
,
long
intervalMillis
,
MiraiTaskExceptionHandler
handler
)
{
...
@@ -95,7 +95,7 @@ public final class MiraiTaskManager {
...
@@ -95,7 +95,7 @@ public final class MiraiTaskManager {
}
}
public
void
repeatingTask
(
Runnable
runnable
,
long
intervalMillis
,
int
times
)
{
public
void
repeatingTask
(
Runnable
runnable
,
long
intervalMillis
,
int
times
)
{
this
.
repeatingTask
(
runnable
,
intervalMillis
,
times
,
MiraiTaskExceptionHandler
.
byDefault
());
this
.
repeatingTask
(
runnable
,
intervalMillis
,
times
,
MiraiTaskExceptionHandler
.
printing
());
}
}
public
void
repeatingTask
(
Runnable
runnable
,
long
intervalMillis
,
int
times
,
MiraiTaskExceptionHandler
handler
)
{
public
void
repeatingTask
(
Runnable
runnable
,
long
intervalMillis
,
int
times
,
MiraiTaskExceptionHandler
handler
)
{
...
...
mirai-core/src/main/java/net/mamoe/mirai/utils/ClientLoginStatus.java
View file @
93dc8e58
...
@@ -4,10 +4,14 @@ package net.mamoe.mirai.utils;
...
@@ -4,10 +4,14 @@ package net.mamoe.mirai.utils;
* @author Him188moe
* @author Him188moe
*/
*/
public
enum
ClientLoginStatus
{
public
enum
ClientLoginStatus
{
/**
* 我在线上
*/
ONLINE
(
0x0A
);
ONLINE
(
0x0A
);
// TODO: 2019/8/31 add more
// TODO: 2019/8/31 add more ClientLoginStatus
public
final
int
id
;
//1byte
public
final
int
id
;
//1 ubyte
ClientLoginStatus
(
int
id
)
{
ClientLoginStatus
(
int
id
)
{
this
.
id
=
id
;
this
.
id
=
id
;
...
...
mirai-core/src/main/java/net/mamoe/mirai/utils/ContactList.java
View file @
93dc8e58
...
@@ -6,5 +6,5 @@ import net.mamoe.mirai.utils.config.MiraiSynchronizedLinkedListMap;
...
@@ -6,5 +6,5 @@ import net.mamoe.mirai.utils.config.MiraiSynchronizedLinkedListMap;
/**
/**
* @author Him188moe
* @author Him188moe
*/
*/
public
class
ContactList
<
C
extends
Contact
>
extends
MiraiSynchronizedLinkedListMap
<
Integer
,
C
>
{
public
class
ContactList
<
C
extends
Contact
>
extends
MiraiSynchronizedLinkedListMap
<
Long
,
C
>
{
}
}
mirai-core/src/main/java/net/mamoe/mirai/utils/RobotAccount.java
0 → 100644
View file @
93dc8e58
package
net.mamoe.mirai.utils
;
import
lombok.Data
;
/**
* @author Him188moe
*/
@Data
public
final
class
RobotAccount
{
public
final
long
qqNumber
;
public
final
String
password
;
public
RobotAccount
(
long
qqNumber
,
String
password
)
{
this
.
qqNumber
=
qqNumber
;
this
.
password
=
password
;
}
}
mirai-core/src/main/java/net/mamoe/mirai/utils/TEA
Cryptor
.java
→
mirai-core/src/main/java/net/mamoe/mirai/utils/TEA.java
View file @
93dc8e58
...
@@ -6,12 +6,13 @@ import java.nio.ByteBuffer;
...
@@ -6,12 +6,13 @@ import java.nio.ByteBuffer;
import
java.util.Random
;
import
java.util.Random
;
/**
/**
* 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
*/
*/
public
class
TEACryptor
{
public
final
class
TEA
{
public
static
final
TEACryptor
CRYPTOR_SHARE_KEY
=
new
TEACryptor
(
Protocol
.
Companion
.
hexToBytes
(
Protocol
.
shareKey
));
public
static
final
TEA
CRYPTOR_SHARE_KEY
=
new
TEA
(
Protocol
.
INSTANCE
.
hexToBytes
(
Protocol
.
shareKey
));
public
static
final
TEACryptor
CRYPTOR_0825KEY
=
new
TEACryptor
(
Protocol
.
Companion
.
hexToBytes
(
Protocol
.
_0825key
));
public
static
final
TEA
CRYPTOR_0825KEY
=
new
TEA
(
Protocol
.
INSTANCE
.
hexToBytes
(
Protocol
.
key0825
));
public
static
final
TEACryptor
CRYPTOR_00BAKEY
=
new
TEACryptor
(
Protocol
.
Companion
.
hexToBytes
(
Protocol
.
_00BaKey
));
private
static
final
long
UINT32_MASK
=
0xffffffff
L
;
private
static
final
long
UINT32_MASK
=
0xffffffff
L
;
private
final
long
[]
mKey
;
private
final
long
[]
mKey
;
...
@@ -23,26 +24,33 @@ public class TEACryptor {
...
@@ -23,26 +24,33 @@ public class TEACryptor {
private
int
mOutPos
;
private
int
mOutPos
;
private
int
mPreOutPos
;
private
int
mPreOutPos
;
private
boolean
isFirstBlock
;
private
boolean
isFirstBlock
;
private
boolean
isRand
;
public
TEA
Cryptor
(
byte
[]
key
)
{
public
TEA
(
byte
[]
key
)
{
mKey
=
new
long
[
4
];
mKey
=
new
long
[
4
];
for
(
int
i
=
0
;
i
<
4
;
i
++)
{
for
(
int
i
=
0
;
i
<
4
;
i
++)
{
mKey
[
i
]
=
pack
(
key
,
i
*
4
,
4
);
mKey
[
i
]
=
pack
(
key
,
i
*
4
,
4
);
}
}
isRand
=
true
;
mRandom
=
new
Random
();
mRandom
=
new
Random
();
isFirstBlock
=
true
;
isFirstBlock
=
true
;
}
}
public
static
byte
[]
encrypt
(
byte
[]
source
,
byte
[]
key
)
{
public
static
byte
[]
encrypt
(
byte
[]
source
,
byte
[]
key
)
{
return
new
TEACryptor
(
key
).
encrypt
(
source
);
return
new
TEA
(
key
).
encrypt
(
source
);
}
public
static
byte
[]
encrypt
(
byte
[]
source
,
String
keyHex
)
{
return
encrypt
(
source
,
UtilsKt
.
hexToBytes
(
keyHex
));
}
}
public
static
byte
[]
decrypt
(
byte
[]
source
,
byte
[]
key
)
{
public
static
byte
[]
decrypt
(
byte
[]
source
,
byte
[]
key
)
{
return
new
TEACryptor
(
key
).
decrypt
(
source
);
return
new
TEA
(
key
).
decrypt
(
source
);
}
public
static
byte
[]
decrypt
(
byte
[]
source
,
String
keyHex
)
{
return
decrypt
(
source
,
UtilsKt
.
hexToBytes
(
keyHex
));
}
}
@SuppressWarnings
(
"SameParameterValue"
)
private
static
long
pack
(
byte
[]
bytes
,
int
offset
,
int
len
)
{
private
static
long
pack
(
byte
[]
bytes
,
int
offset
,
int
len
)
{
long
result
=
0
;
long
result
=
0
;
int
max_offset
=
len
>
8
?
offset
+
8
:
offset
+
len
;
int
max_offset
=
len
>
8
?
offset
+
8
:
offset
+
len
;
...
@@ -53,11 +61,7 @@ public class TEACryptor {
...
@@ -53,11 +61,7 @@ public class TEACryptor {
}
}
private
int
rand
()
{
private
int
rand
()
{
return
isRand
?
mRandom
.
nextInt
()
:
0xff00ff
;
return
mRandom
.
nextInt
();
}
public
void
enableRandom
(
boolean
rand
)
{
isRand
=
rand
;
}
}
private
byte
[]
encode
(
byte
[]
bytes
)
{
private
byte
[]
encode
(
byte
[]
bytes
)
{
...
@@ -109,6 +113,7 @@ public class TEACryptor {
...
@@ -109,6 +113,7 @@ public class TEACryptor {
isFirstBlock
=
false
;
isFirstBlock
=
false
;
}
}
@SuppressWarnings
(
"BooleanMethodIsAlwaysInverted"
)
private
boolean
decodeOneBlock
(
byte
[]
ciphertext
,
int
offset
,
int
len
)
{
private
boolean
decodeOneBlock
(
byte
[]
ciphertext
,
int
offset
,
int
len
)
{
for
(
mIndexPos
=
0
;
mIndexPos
<
8
;
mIndexPos
++)
{
for
(
mIndexPos
=
0
;
mIndexPos
<
8
;
mIndexPos
++)
{
if
(
mOutPos
+
mIndexPos
<
len
)
{
if
(
mOutPos
+
mIndexPos
<
len
)
{
...
@@ -125,6 +130,7 @@ public class TEACryptor {
...
@@ -125,6 +130,7 @@ public class TEACryptor {
}
}
@SuppressWarnings
(
"SameParameterValue"
)
private
byte
[]
encrypt
(
byte
[]
plaintext
,
int
offset
,
int
len
)
{
private
byte
[]
encrypt
(
byte
[]
plaintext
,
int
offset
,
int
len
)
{
mInBlock
=
new
byte
[
8
];
mInBlock
=
new
byte
[
8
];
mIV
=
new
byte
[
8
];
mIV
=
new
byte
[
8
];
...
@@ -175,11 +181,12 @@ public class TEACryptor {
...
@@ -175,11 +181,12 @@ public class TEACryptor {
return
mOutput
;
return
mOutput
;
}
}
private
byte
[]
decrypt
(
byte
[]
ciphertext
,
int
offset
,
int
len
)
{
@SuppressWarnings
(
"SameParameterValue"
)
private
byte
[]
decrypt
(
byte
[]
cipherText
,
int
offset
,
int
len
)
{
if
(
len
%
8
!=
0
||
len
<
16
)
{
if
(
len
%
8
!=
0
||
len
<
16
)
{
throw
new
IllegalArgumentException
(
"must len % 8 == 0 && len >= 16"
);
throw
new
IllegalArgumentException
(
"must len % 8 == 0 && len >= 16"
);
}
}
mIV
=
decode
(
cipher
t
ext
,
offset
);
mIV
=
decode
(
cipher
T
ext
,
offset
);
mIndexPos
=
mIV
[
0
]
&
7
;
mIndexPos
=
mIV
[
0
]
&
7
;
int
plen
=
len
-
mIndexPos
-
10
;
int
plen
=
len
-
mIndexPos
-
10
;
isFirstBlock
=
true
;
isFirstBlock
=
true
;
...
@@ -198,7 +205,7 @@ public class TEACryptor {
...
@@ -198,7 +205,7 @@ public class TEACryptor {
}
}
if
(
mIndexPos
==
8
)
{
if
(
mIndexPos
==
8
)
{
isFirstBlock
=
false
;
isFirstBlock
=
false
;
if
(!
decodeOneBlock
(
cipher
t
ext
,
offset
,
len
))
{
if
(!
decodeOneBlock
(
cipher
T
ext
,
offset
,
len
))
{
throw
new
RuntimeException
(
"Unable to decode"
);
throw
new
RuntimeException
(
"Unable to decode"
);
}
}
}
}
...
@@ -208,20 +215,20 @@ public class TEACryptor {
...
@@ -208,20 +215,20 @@ public class TEACryptor {
if
(
mIndexPos
<
8
)
{
if
(
mIndexPos
<
8
)
{
mOutput
[
outpos
++]
=
isFirstBlock
?
mOutput
[
outpos
++]
=
isFirstBlock
?
mIV
[
mIndexPos
]
:
mIV
[
mIndexPos
]
:
(
byte
)
(
cipher
t
ext
[
mPreOutPos
+
offset
+
mIndexPos
]
^
mIV
[
mIndexPos
]);
(
byte
)
(
cipher
T
ext
[
mPreOutPos
+
offset
+
mIndexPos
]
^
mIV
[
mIndexPos
]);
++
mIndexPos
;
++
mIndexPos
;
}
}
if
(
mIndexPos
==
8
)
{
if
(
mIndexPos
==
8
)
{
mPreOutPos
=
mOutPos
-
8
;
mPreOutPos
=
mOutPos
-
8
;
isFirstBlock
=
false
;
isFirstBlock
=
false
;
if
(!
decodeOneBlock
(
cipher
t
ext
,
offset
,
len
))
{
if
(!
decodeOneBlock
(
cipher
T
ext
,
offset
,
len
))
{
throw
new
RuntimeException
(
"Unable to decode"
);
throw
new
RuntimeException
(
"Unable to decode"
);
}
}
}
}
}
}
for
(
g
=
0
;
g
<
7
;
g
++)
{
for
(
g
=
0
;
g
<
7
;
g
++)
{
if
(
mIndexPos
<
8
)
{
if
(
mIndexPos
<
8
)
{
if
((
cipher
t
ext
[
mPreOutPos
+
offset
+
mIndexPos
]
^
mIV
[
mIndexPos
])
!=
0
)
{
if
((
cipher
T
ext
[
mPreOutPos
+
offset
+
mIndexPos
]
^
mIV
[
mIndexPos
])
!=
0
)
{
throw
new
RuntimeException
();
throw
new
RuntimeException
();
}
else
{
}
else
{
++
mIndexPos
;
++
mIndexPos
;
...
@@ -230,7 +237,7 @@ public class TEACryptor {
...
@@ -230,7 +237,7 @@ public class TEACryptor {
if
(
mIndexPos
==
8
)
{
if
(
mIndexPos
==
8
)
{
mPreOutPos
=
mOutPos
;
mPreOutPos
=
mOutPos
;
if
(!
decodeOneBlock
(
cipher
t
ext
,
offset
,
len
))
{
if
(!
decodeOneBlock
(
cipher
T
ext
,
offset
,
len
))
{
throw
new
RuntimeException
(
"Unable to decode"
);
throw
new
RuntimeException
(
"Unable to decode"
);
}
}
}
}
...
...
mirai-core/src/main/java/net/mamoe/mirai/utils/Tested.kt
View file @
93dc8e58
package
net.mamoe.mirai.util
package
net.mamoe.mirai.util
s
/**
/**
* @author Him188moe
* @author Him188moe
...
...
mirai-core/src/main/java/net/mamoe/mirai/utils/Utils.kt
View file @
93dc8e58
...
@@ -8,7 +8,9 @@ import java.lang.reflect.Field
...
@@ -8,7 +8,9 @@ import java.lang.reflect.Field
import
java.util.*
import
java.util.*
import
java.util.zip.CRC32
import
java.util.zip.CRC32
@JvmSynthetic
fun
ByteArray
.
toHexString
():
String
=
toHexString
(
" "
)
fun
ByteArray
.
toHexString
():
String
=
toHexString
(
" "
)
fun
ByteArray
.
toHexString
(
separator
:
String
=
" "
):
String
=
this
.
joinToString
(
separator
)
{
fun
ByteArray
.
toHexString
(
separator
:
String
=
" "
):
String
=
this
.
joinToString
(
separator
)
{
var
ret
=
it
.
toString
(
16
).
toUpperCase
()
var
ret
=
it
.
toString
(
16
).
toUpperCase
()
if
(
ret
.
length
==
1
)
{
if
(
ret
.
length
==
1
)
{
...
@@ -21,18 +23,23 @@ fun ByteArray.toHexString(separator: String = " "): String = this.joinToString(s
...
@@ -21,18 +23,23 @@ fun ByteArray.toHexString(separator: String = " "): String = this.joinToString(s
fun
ByteArray
.
toUHexString
(
separator
:
String
=
" "
):
String
=
this
.
toUByteArray
().
toUHexString
(
separator
)
fun
ByteArray
.
toUHexString
(
separator
:
String
=
" "
):
String
=
this
.
toUByteArray
().
toUHexString
(
separator
)
@ExperimentalUnsignedTypes
@ExperimentalUnsignedTypes
@JvmSynthetic
fun
ByteArray
.
toUHexString
():
String
=
this
.
toUByteArray
().
toUHexString
()
fun
ByteArray
.
toUHexString
():
String
=
this
.
toUByteArray
().
toUHexString
()
@ExperimentalUnsignedTypes
@ExperimentalUnsignedTypes
fun
UByteArray
.
toUHexString
(
separator
:
String
=
" "
):
String
=
this
.
joinToString
(
separator
)
{
@JvmSynthetic
var
ret
=
it
.
toString
(
16
).
toUpperCase
()
fun
UByteArray
.
toUHexString
(
separator
:
String
=
" "
):
String
{
if
(
ret
.
length
==
1
)
{
return
this
.
joinToString
(
separator
)
{
ret
=
"0$ret"
var
ret
=
it
.
toString
(
16
).
toUpperCase
()
if
(
ret
.
length
==
1
)
{
ret
=
"0$ret"
}
return
@
joinToString
ret
}
}
return
@
joinToString
ret
}
}
@ExperimentalUnsignedTypes
@ExperimentalUnsignedTypes
@JvmSynthetic
fun
UByteArray
.
toUHexString
():
String
=
this
.
toUHexString
(
" "
)
fun
UByteArray
.
toUHexString
():
String
=
this
.
toUHexString
(
" "
)
@ExperimentalUnsignedTypes
@ExperimentalUnsignedTypes
...
@@ -51,7 +58,7 @@ fun String.hexToUBytes(): UByteArray = Protocol.hexToUBytes(this)
...
@@ -51,7 +58,7 @@ fun String.hexToUBytes(): UByteArray = Protocol.hexToUBytes(this)
fun
String
.
hexToShort
():
Short
=
hexToBytes
().
let
{
((
it
[
1
].
toInt
()
shl
8
)
+
it
[
0
]).
toShort
()
}
fun
String
.
hexToShort
():
Short
=
hexToBytes
().
let
{
((
it
[
1
].
toInt
()
shl
8
)
+
it
[
0
]).
toShort
()
}
@ExperimentalUnsignedTypes
@ExperimentalUnsignedTypes
fun
String
.
hexToInt
():
Int
=
hexToBytes
().
let
{
((
it
[
3
].
toInt
()
shl
24
)
+
(
it
[
2
].
toInt
()
shl
16
)
+
(
it
[
1
].
toInt
()
shl
8
)
+
it
[
0
])
}
fun
String
.
hexToInt
():
Int
=
hexToBytes
().
let
{
((
it
[
0
].
toInt
()
shl
24
)
+
(
it
[
1
].
toInt
()
shl
16
)
+
(
it
[
2
].
toInt
()
shl
8
)
+
it
[
3
])
}
@ExperimentalUnsignedTypes
@ExperimentalUnsignedTypes
fun
String
.
hexToByte
():
Byte
=
hexToBytes
()[
0
]
fun
String
.
hexToByte
():
Byte
=
hexToBytes
()[
0
]
...
@@ -65,17 +72,18 @@ open class ByteArrayDataOutputStream : DataOutputStream(ByteArrayOutputStream())
...
@@ -65,17 +72,18 @@ open class ByteArrayDataOutputStream : DataOutputStream(ByteArrayOutputStream())
fun
lazyEncode
(
t
:
(
ByteArrayDataOutputStream
)
->
Unit
):
ByteArray
=
ByteArrayDataOutputStream
().
let
{
t
(
it
);
return
it
.
toByteArray
()
}
fun
lazyEncode
(
t
:
(
ByteArrayDataOutputStream
)
->
Unit
):
ByteArray
=
ByteArrayDataOutputStream
().
let
{
t
(
it
);
return
it
.
toByteArray
()
}
@ExperimentalUnsignedTypes
@ExperimentalUnsignedTypes
fun
getRandom
Ke
y
(
length
:
Int
):
ByteArray
{
fun
getRandom
ByteArra
y
(
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
())
}
return
bytes
.
toByteArray
()
return
bytes
.
toByteArray
()
}
}
@JvmSynthetic
operator
fun
File
.
plus
(
child
:
String
):
File
=
File
(
this
,
child
)
operator
fun
File
.
plus
(
child
:
String
):
File
=
File
(
this
,
child
)
private
const
val
GTK_BASE_VALUE
:
Int
=
5381
private
const
val
GTK_BASE_VALUE
:
Int
=
5381
fun
getGTK
(
sKey
:
String
):
Int
{
internal
fun
getGTK
(
sKey
:
String
):
Int
{
var
value
=
GTK_BASE_VALUE
var
value
=
GTK_BASE_VALUE
for
(
c
in
sKey
.
toCharArray
())
{
for
(
c
in
sKey
.
toCharArray
())
{
value
+=
(
value
shl
5
)
+
c
.
toInt
()
value
+=
(
value
shl
5
)
+
c
.
toInt
()
...
@@ -85,7 +93,7 @@ fun getGTK(sKey: String): Int {
...
@@ -85,7 +93,7 @@ fun getGTK(sKey: String): Int {
return
value
return
value
}
}
fun
getCrc32
(
key
:
ByteArray
):
Int
=
CRC32
().
let
{
it
.
update
(
key
);
it
.
value
.
toInt
()
}
internal
fun
getCrc32
(
key
:
ByteArray
):
Int
=
CRC32
().
let
{
it
.
update
(
key
);
it
.
value
.
toInt
()
}
/**
/**
...
@@ -118,3 +126,13 @@ fun Any.getAllDeclaredFields(): List<Field> {
...
@@ -118,3 +126,13 @@ fun Any.getAllDeclaredFields(): List<Field> {
return
list
return
list
}
}
private
const
val
ZERO_BYTE
:
Byte
=
0
fun
ByteArray
.
removeZeroTail
():
ByteArray
{
var
i
=
this
.
size
-
1
while
(
this
[
i
]
==
ZERO_BYTE
)
{
--
i
}
return
this
.
copyOfRange
(
0
,
i
+
1
)
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/utils/config/MiraiConfigSection.java
View file @
93dc8e58
...
@@ -126,10 +126,10 @@ public class MiraiConfigSection<T> extends MiraiSynchronizedLinkedListMap<String
...
@@ -126,10 +126,10 @@ public class MiraiConfigSection<T> extends MiraiSynchronizedLinkedListMap<String
return
result
==
null
?
defaultV:
result
.
toString
();
return
result
==
null
?
defaultV:
result
.
toString
();
}
}
public
String
getStringOrThrow
(
String
key
,
Callable
<
Throwable
>
throwableCallable
)
throws
Throwable
{
public
String
getStringOrThrow
(
String
key
,
Supplier
<
Throwable
>
exceptionSupplier
)
throws
Throwable
{
Object
result
=
this
.
getOrDefault
(
key
,
null
);
Object
result
=
this
.
getOrDefault
(
key
,
null
);
if
(
result
==
null
){
if
(
result
==
null
){
throw
throwableCallable
.
call
();
throw
exceptionSupplier
.
get
();
}
}
return
result
.
toString
();
return
result
.
toString
();
}
}
...
...
mirai-core/src/main/java/net/mamoe/mirai/utils/setting/MiraiSetting.java
→
mirai-core/src/main/java/net/mamoe/mirai/utils/setting/MiraiSetting
s
.java
View file @
93dc8e58
package
net.mamoe.mirai.utils.setting
;
package
net.mamoe.mirai.utils.setting
;
import
net.mamoe.mirai.plugin.MiraiPluginBase
;
import
org.ini4j.Config
;
import
org.ini4j.Config
;
import
org.ini4j.Ini
;
import
org.ini4j.Ini
;
import
java.io.File
;
import
java.io.File
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.util.HashMap
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Map
;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.concurrent.ConcurrentHashMap
;
/**
/**
* Mirai Config
* Thread-safe Mirai Config <br>
* Only support {INI} format
* Only supports <code>INI</code> format <br>
* Support MAP and LIST
* Supports {@link Map} and {@link List}
* Thread safe
*/
*/
public
class
MiraiSetting
{
public
class
MiraiSetting
s
{
private
File
file
;
private
File
file
;
...
@@ -23,14 +24,21 @@ public class MiraiSetting {
...
@@ -23,14 +24,21 @@ public class MiraiSetting {
private
volatile
Map
<
String
,
MiraiSettingSection
>
cacheSection
=
new
ConcurrentHashMap
<>();
private
volatile
Map
<
String
,
MiraiSettingSection
>
cacheSection
=
new
ConcurrentHashMap
<>();
public
MiraiSetting
(
File
file
){
public
MiraiSettings
(
MiraiPluginBase
pluginBase
,
String
filename
)
{
// TODO: 2019/9/6 每个插件独立文件夹存放
this
(
new
File
(
filename
));
}
public
MiraiSettings
(
File
file
)
{
if
(!
file
.
getName
().
contains
(
"."
)){
if
(!
file
.
getName
().
contains
(
"."
)){
file
=
new
File
(
file
.
getPa
rent
()
+
file
.
getName
()
+
".ini"
);
file
=
new
File
(
file
.
getPa
th
()
+
".ini"
);
}
}
this
.
file
=
file
;
this
.
file
=
file
;
try
{
try
{
if
(
file
.
exists
()){
if
(
file
.
exists
()){
file
.
createNewFile
();
if
(!
file
.
createNewFile
())
{
throw
new
RuntimeException
(
"cannot create config file "
+
file
);
}
}
}
Config
config
=
new
Config
();
Config
config
=
new
Config
();
config
.
setMultiSection
(
true
);
config
.
setMultiSection
(
true
);
...
@@ -42,12 +50,12 @@ public class MiraiSetting {
...
@@ -42,12 +50,12 @@ public class MiraiSetting {
}
}
}
}
public
void
setSection
(
String
key
,
MiraiSettingSection
section
)
{
public
synchronized
void
setSection
(
String
key
,
MiraiSettingSection
section
)
{
cacheSection
.
put
(
key
,
section
);
cacheSection
.
put
(
key
,
section
);
}
}
public
MiraiSettingMapSection
getMapSection
(
String
key
)
{
public
synchronized
MiraiSettingMapSection
getMapSection
(
String
key
)
{
if
(!
cacheSection
.
containsKey
(
key
))
{
if
(!
cacheSection
.
containsKey
(
key
))
{
MiraiSettingMapSection
section
=
new
MiraiSettingMapSection
();
MiraiSettingMapSection
section
=
new
MiraiSettingMapSection
();
if
(
ini
.
containsKey
(
key
)){
if
(
ini
.
containsKey
(
key
)){
...
@@ -58,7 +66,7 @@ public class MiraiSetting {
...
@@ -58,7 +66,7 @@ public class MiraiSetting {
return
(
MiraiSettingMapSection
)
cacheSection
.
get
(
key
);
return
(
MiraiSettingMapSection
)
cacheSection
.
get
(
key
);
}
}
public
MiraiSettingListSection
getListSection
(
String
key
)
{
public
synchronized
MiraiSettingListSection
getListSection
(
String
key
)
{
if
(!
cacheSection
.
containsKey
(
key
))
{
if
(!
cacheSection
.
containsKey
(
key
))
{
MiraiSettingListSection
section
=
new
MiraiSettingListSection
();
MiraiSettingListSection
section
=
new
MiraiSettingListSection
();
if
(
ini
.
containsKey
(
key
)){
if
(
ini
.
containsKey
(
key
)){
...
@@ -85,7 +93,7 @@ public class MiraiSetting {
...
@@ -85,7 +93,7 @@ public class MiraiSetting {
}
}
}
}
public
void
clearCache
()
{
public
synchronized
void
clearCache
()
{
cacheSection
.
clear
();
cacheSection
.
clear
();
}
}
}
}
...
...
mirai-core/src/test/java/BadQQFilter.kt
0 → 100644
View file @
93dc8e58
import
kotlinx.coroutines.GlobalScope
import
kotlinx.coroutines.launch
import
net.mamoe.mirai.Robot
import
net.mamoe.mirai.network.packet.login.LoginState
import
net.mamoe.mirai.utils.RobotAccount
import
java.util.*
/**
* @author Him188moe
*/
val
qqList
=
"2258868346----123456789.\n"
+
"1545483785----yuk7k1dxnf3jn5\n"
+
"2948786488----123123123\n"
+
"3059674084----qq123456\n"
+
"1918079979----123456789.\n"
+
"3050478794----18872590321\n"
+
"3331537204----123456789.\n"
+
"2128659972----123456789.\n"
+
"3435376516----abc123456\n"
+
"2980527804----a123456\n"
+
"2752195782----qq123456789\n"
+
"3130257966----13415986622\n"
+
"1802730396----123456789\n"
+
"3021732783----15866103923\n"
+
"306499606----abc123456\n"
+
"2893904328----abc123456\n"
+
"1765904806----123456789\n"
+
"3254202261----15223045268\n"
+
"2947707697----abc123456\n"
+
"3500959200----123456789.\n"
+
"2169513531----123456789.\n"
+
"2983688661----a123456\n"
+
"1246882194----pz49779866\n"
+
"2315275635----147258369\n"
+
"2802294904----123456789\n"
+
"2955364492----1234567890\n"
+
"1753325115----123456789\n"
+
"2642725191----qq123456\n"
+
"2152972686----123456789.\n"
+
"2845953617----123456789.\n"
+
"3329641753----123456789.\n"
+
"1458302685----123456789a\n"
+
"2351156352----987654321\n"
+
"2304786984----fkhwt53787\n"
+
"3322756212----123456789.\n"
+
"3187253283----123456789.\n"
+
"3168715730----147258369\n"
+
"2189916732----18831892323\n"
+
"2965337631----123456789.\n"
+
"1901802165----123456789.\n"
+
"414015319----abc123456\n"
+
"3400636089----123456789a\n"
+
"3530336304----seoua80060\n"
+
"3147312971----123456789.\n"
+
"3011083526----yp70y9\n"
+
"286888078----abc123456\n"
+
"3126754112----1234567890\n"
+
"2924643025----123123123\n"
+
"341870356----ncvhZtQD\n"
+
"3358177328----123456789a\n"
+
"1396419201----eakuj14475\n"
+
"3541159580----123456789.\n"
+
"2540245592----1234567890\n"
+
"2024802855----123456789.\n"
+
"2578309660----1234567890\n"
+
"1934965091----123456789.\n"
+
"3449408956----a123456789\n"
+
"2509348670----123456789.\n"
+
"2305961679----123456789.\n"
+
"3532858521----123456789.\n"
+
"3308276898----123456789a\n"
+
"1760897490----123456789\n"
+
"2920800012----123123123\n"
+
"2923942248----123123123\n"
+
"3216600579----13882755274\n"
+
"3100259299----qq123456\n"
+
"3242723735----1234567890\n"
+
"2142733062----123456789.\n"
+
"1557689693----123456789\n"
+
"3505693439----sb2662vqy6q\n"
+
"3231125974----123456789.\n"
+
"3433048975----13893690883\n"
+
"3168017129----18780999209\n"
+
"2922045831----123123123\n"
+
"3578152022----a123456789\n"
+
"2116254935----147258369\n"
+
"3158479284----1234567890\n"
+
"3149394424----qq123456789\n"
+
"2829521712----123456789.\n"
+
"3218671461----123456789.\n"
+
"3035873094----123456789a\n"
+
"2224518667----147258369\n"
+
"3175801590----123456789.\n"
+
"3203228181----123456789a\n"
+
"3213497536----123456789a\n"
+
"3377317115----123456789\n"
+
"2672537341----qq123456789\n"
+
"2945957617----123123123\n"
+
"2763390197----123456789.\n"
+
"3322711709----123456789."
fun
main
()
{
val
goodRobotList
=
Collections
.
synchronizedList
(
mutableListOf
<
Robot
>())
qqList
.
split
(
"\n"
).
forEach
{
GlobalScope
.
launch
{
val
strings
=
it
.
split
(
"----"
)
val
robot
=
Robot
(
RobotAccount
(
strings
[
0
].
toLong
(),
strings
[
1
].
let
{
password
->
if
(
password
.
endsWith
(
"."
))
{
return
@
let
password
.
substring
(
0
,
password
.
length
-
1
)
}
return
@
let
password
}),
listOf
())
robot
.
network
.
tryLogin
().
whenComplete
{
state
,
_
->
if
(!(
state
==
LoginState
.
BLOCKED
||
state
==
LoginState
.
DEVICE_LOCK
||
state
==
LoginState
.
WRONG_PASSWORD
))
{
goodRobotList
.
add
(
robot
)
}
}
}
}
Thread
.
sleep
(
9
*
3000
)
println
(
goodRobotList
.
joinToString
(
"\n"
)
{
it
.
account
.
qqNumber
.
toString
()
+
" "
+
it
.
account
.
password
})
}
mirai-core/src/test/java/HexComparator.java
View file @
93dc8e58
...
@@ -3,11 +3,17 @@ import lombok.AllArgsConstructor;
...
@@ -3,11 +3,17 @@ import lombok.AllArgsConstructor;
import
lombok.Getter
;
import
lombok.Getter
;
import
lombok.ToString
;
import
lombok.ToString
;
import
net.mamoe.mirai.network.Protocol
;
import
net.mamoe.mirai.network.Protocol
;
import
net.mamoe.mirai.network.packet.ClientPacketKt
;
import
net.mamoe.mirai.utils.UtilsKt
;
import
java.awt.*
;
import
java.awt.datatransfer.DataFlavor
;
import
java.awt.datatransfer.Transferable
;
import
java.lang.reflect.Field
;
import
java.lang.reflect.Field
;
import
java.util.Arrays
;
import
java.util.Arrays
;
import
java.util.LinkedList
;
import
java.util.LinkedList
;
import
java.util.List
;
import
java.util.List
;
import
java.util.Scanner
;
import
java.util.concurrent.atomic.AtomicBoolean
;
import
java.util.concurrent.atomic.AtomicBoolean
;
import
java.util.concurrent.atomic.AtomicInteger
;
import
java.util.concurrent.atomic.AtomicInteger
;
import
java.util.function.BiConsumer
;
import
java.util.function.BiConsumer
;
...
@@ -32,15 +38,24 @@ public class HexComparator {
...
@@ -32,15 +38,24 @@ public class HexComparator {
private
static
final
String
BLUE
=
"\033[34m"
;
private
static
final
String
BLUE
=
"\033[34m"
;
public
static
final
List
<
HexReader
>
consts
=
new
LinkedList
<>()
{{
public
static
final
List
<
HexReader
>
consts
=
new
LinkedList
<>()
{{
add
(
new
HexReader
(
"90 5E 39 DF 00 02 76 E4 B8 DD 00"
));
add
(
new
HexReader
(
"90 5E 39 DF 00 02 76 E4 B8 DD 00"
));
}};
}};
private
static
class
ConstMatcher
{
private
static
class
ConstMatcher
{
private
static
final
List
<
Field
>
CONST_FIELDS
=
new
LinkedList
<>()
{{
private
static
final
List
<
Field
>
CONST_FIELDS
=
new
LinkedList
<>()
{{
List
.
of
(
Protocol
.
class
).
forEach
(
aClass
->
Arrays
.
stream
(
aClass
.
getDeclaredFields
()).
peek
(
this
::
add
).
forEach
(
Field:
:
trySetAccessible
));
List
.
of
(
Protocol
.
class
).
forEach
(
aClass
->
Arrays
.
stream
(
aClass
.
getDeclaredFields
()).
peek
(
this
::
add
).
forEach
(
Field:
:
trySetAccessible
));
List
.
of
(
TestConsts
.
class
).
forEach
(
aClass
->
Arrays
.
stream
(
aClass
.
getDeclaredFields
()).
peek
(
this
::
add
).
forEach
(
Field:
:
trySetAccessible
));
}};
}};
@SuppressWarnings
({
"unused"
,
"NonAsciiCharacters"
})
private
static
class
TestConsts
{
private
static
final
String
牛逼
=
UtilsKt
.
toUHexString
(
"牛逼"
.
getBytes
(),
" "
);
private
static
final
String
_1994701021
=
ClientPacketKt
.
toHexString
(
1994701021
,
" "
);
private
static
final
String
_1040400290
=
ClientPacketKt
.
toHexString
(
1040400290
,
" "
);
private
static
final
String
_580266363
=
ClientPacketKt
.
toHexString
(
580266363
,
" "
);
}
private
final
List
<
Match
>
matches
=
new
LinkedList
<>();
private
final
List
<
Match
>
matches
=
new
LinkedList
<>();
private
ConstMatcher
(
String
hex
)
{
private
ConstMatcher
(
String
hex
)
{
...
@@ -89,6 +104,23 @@ public class HexComparator {
...
@@ -89,6 +104,23 @@ public class HexComparator {
}
}
}
}
private
static
void
buildConstNameChain
(
int
length
,
ConstMatcher
constMatcher
,
StringBuilder
constNameBuilder
)
{
for
(
int
i
=
0
;
i
<
length
;
i
++)
{
constNameBuilder
.
append
(
" "
);
String
match
=
constMatcher
.
getMatchedConstName
(
i
/
4
);
if
(
match
!=
null
)
{
int
appendedNameLength
=
match
.
length
();
constNameBuilder
.
append
(
match
);
while
(
constMatcher
.
getMatchedConstName
(
i
++
/
4
)
!=
null
)
{
if
(
appendedNameLength
--
<=
0
)
{
constNameBuilder
.
append
(
" "
);
}
}
}
}
}
private
static
String
compare
(
String
hex1s
,
String
hex2s
)
{
private
static
String
compare
(
String
hex1s
,
String
hex2s
)
{
StringBuilder
builder
=
new
StringBuilder
();
StringBuilder
builder
=
new
StringBuilder
();
...
@@ -105,10 +137,17 @@ public class HexComparator {
...
@@ -105,10 +137,17 @@ public class HexComparator {
StringBuilder
numberLine
=
new
StringBuilder
();
StringBuilder
numberLine
=
new
StringBuilder
();
StringBuilder
hex1ConstName
=
new
StringBuilder
();
StringBuilder
hex1b
=
new
StringBuilder
();
StringBuilder
hex1b
=
new
StringBuilder
();
StringBuilder
hex2b
=
new
StringBuilder
();
StringBuilder
hex2b
=
new
StringBuilder
();
StringBuilder
hex2ConstName
=
new
StringBuilder
();
int
dif
=
0
;
int
dif
=
0
;
int
length
=
Math
.
max
(
hex1
.
length
,
hex2
.
length
)
*
4
;
buildConstNameChain
(
length
,
constMatcher1
,
hex1ConstName
);
buildConstNameChain
(
length
,
constMatcher2
,
hex2ConstName
);
for
(
int
i
=
0
;
i
<
Math
.
max
(
hex1
.
length
,
hex2
.
length
);
++
i
)
{
for
(
int
i
=
0
;
i
<
Math
.
max
(
hex1
.
length
,
hex2
.
length
);
++
i
)
{
String
h1
=
null
;
String
h1
=
null
;
String
h2
=
null
;
String
h2
=
null
;
...
@@ -152,7 +191,7 @@ public class HexComparator {
...
@@ -152,7 +191,7 @@ public class HexComparator {
}
}
}
}
numberLine
.
append
(
UNKNOWN
).
append
(
getNumber
(
i
)).
append
(
" "
);
numberLine
.
append
(
UNKNOWN
).
append
(
get
Fixed
Number
(
i
)).
append
(
" "
);
hex1b
.
append
(
" "
).
append
(
h1
).
append
(
" "
);
hex1b
.
append
(
" "
).
append
(
h1
).
append
(
" "
);
hex2b
.
append
(
" "
).
append
(
h2
).
append
(
" "
);
hex2b
.
append
(
" "
).
append
(
h2
).
append
(
" "
);
if
(
isDif
)
{
if
(
isDif
)
{
...
@@ -165,42 +204,46 @@ public class HexComparator {
...
@@ -165,42 +204,46 @@ public class HexComparator {
return
(
builder
.
append
(
" "
).
append
(
dif
).
append
(
" 个不同"
).
append
(
"\n"
)
return
(
builder
.
append
(
" "
).
append
(
dif
).
append
(
" 个不同"
).
append
(
"\n"
)
.
append
(
numberLine
).
append
(
"\n"
)
.
append
(
numberLine
).
append
(
"\n"
)
.
append
(
hex1ConstName
).
append
(
"\n"
)
.
append
(
hex1b
).
append
(
"\n"
)
.
append
(
hex1b
).
append
(
"\n"
)
.
append
(
hex2b
))
.
append
(
hex2b
).
append
(
"\n"
)
.
append
(
hex2ConstName
).
append
(
"\n"
)
)
.
toString
();
.
toString
();
}
}
private
static
void
doConstReplacement
(
StringBuilder
builder
){
private
static
void
doConstReplacement
(
StringBuilder
builder
)
{
String
mirror
=
builder
.
toString
();
String
mirror
=
builder
.
toString
();
HexReader
hexs
=
new
HexReader
(
mirror
);
HexReader
hexs
=
new
HexReader
(
mirror
);
for
(
AtomicInteger
i
=
new
AtomicInteger
(
0
);
i
.
get
()<
builder
.
length
();
i
.
addAndGet
(
1
))
{
for
(
AtomicInteger
i
=
new
AtomicInteger
(
0
);
i
.
get
()
<
builder
.
length
();
i
.
addAndGet
(
1
))
{
hexs
.
setTo
(
i
.
get
());
hexs
.
setTo
(
i
.
get
());
consts
.
forEach
(
a
->
{
consts
.
forEach
(
a
->
{
hexs
.
setTo
(
i
.
get
());
hexs
.
setTo
(
i
.
get
());
List
<
Integer
>
posToPlaceColor
=
new
LinkedList
<>();
List
<
Integer
>
posToPlaceColor
=
new
LinkedList
<>();
AtomicBoolean
is
=
new
AtomicBoolean
(
false
);
AtomicBoolean
is
=
new
AtomicBoolean
(
false
);
a
.
readFully
((
c
,
d
)
->
{
a
.
readFully
((
c
,
d
)
->
{
if
(
c
.
equals
(
hexs
.
readHex
()))
{
if
(
c
.
equals
(
hexs
.
readHex
()))
{
posToPlaceColor
.
add
(
d
);
posToPlaceColor
.
add
(
d
);
}
else
{
}
else
{
is
.
set
(
false
);
is
.
set
(
false
);
}
}
});
});
if
(
is
.
get
())
{
if
(
is
.
get
())
{
AtomicInteger
adder
=
new
AtomicInteger
();
AtomicInteger
adder
=
new
AtomicInteger
();
posToPlaceColor
.
forEach
(
e
->
{
posToPlaceColor
.
forEach
(
e
->
{
builder
.
insert
(
e
+
adder
.
getAndAdd
(
BLUE
.
length
()),
BLUE
);
builder
.
insert
(
e
+
adder
.
getAndAdd
(
BLUE
.
length
()),
BLUE
);
});
});
}
}
});
});
}
}
}
}
private
static
String
getNumber
(
int
number
)
{
private
static
String
getFixedNumber
(
int
number
)
{
if
(
number
<
10
)
{
if
(
number
<
10
)
{
return
"00"
+
number
;
return
"00"
+
number
;
}
}
...
@@ -210,8 +253,31 @@ public class HexComparator {
...
@@ -210,8 +253,31 @@ public class HexComparator {
return
String
.
valueOf
(
number
);
return
String
.
valueOf
(
number
);
}
}
public
static
void
main
(
String
[]
args
)
{
private
static
String
getClipboardString
()
{
Transferable
trans
=
Toolkit
.
getDefaultToolkit
().
getSystemClipboard
().
getContents
(
null
);
if
(
trans
.
isDataFlavorSupported
(
DataFlavor
.
stringFlavor
))
{
try
{
return
(
String
)
trans
.
getTransferData
(
DataFlavor
.
stringFlavor
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
}
return
null
;
}
public
static
void
main
(
String
[]
args
)
{
Scanner
scanner
=
new
Scanner
(
System
.
in
);
while
(
true
)
{
System
.
out
.
println
(
"Hex1: "
);
var
hex1
=
scanner
.
nextLine
();
System
.
out
.
println
(
"Hex2: "
);
var
hex2
=
scanner
.
nextLine
();
System
.
out
.
println
(
"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
);
System
.
out
.
println
(
HexComparator
.
compare
(
hex1
,
hex2
));
System
.
out
.
println
();
}
/*
System.out.println(HexComparator.compare(
System.out.println(HexComparator.compare(
//mirai
//mirai
...
@@ -230,66 +296,63 @@ public class HexComparator {
...
@@ -230,66 +296,63 @@ public class HexComparator {
"6F 0B DF 92 00 02 76 E4 B8 DD 00 00 04 53 00 00 00 01 00 00 15 85 00 00 01 55 35 05 8E C9 BA 16 D0 01 63 5B 59 4B 59 52 31 01 B9 00 00 00 00 00 00 00 00 00 00 00 00 00 E9 E9 E9 E9 00 00 00 00 00 00 00 00 00 10 15 74 C4 89 85 7A 19 F5 5E A9 C9 A3 5E 8A 5A 9B AA BB CC DD EE FF AA BB CC\n\n\n"
"6F 0B DF 92 00 02 76 E4 B8 DD 00 00 04 53 00 00 00 01 00 00 15 85 00 00 01 55 35 05 8E C9 BA 16 D0 01 63 5B 59 4B 59 52 31 01 B9 00 00 00 00 00 00 00 00 00 00 00 00 00 E9 E9 E9 E9 00 00 00 00 00 00 00 00 00 10 15 74 C4 89 85 7A 19 F5 5E A9 C9 A3 5E 8A 5A 9B AA BB CC DD EE FF AA BB CC\n\n\n"
));*/
));*/
}
}
}
}
class
HexReader
{
class
HexReader
{
private
String
s
;
private
String
s
;
private
int
pos
=
0
;
private
int
pos
=
0
;
private
int
lastHaxPos
=
0
;
private
int
lastHaxPos
=
0
;
public
HexReader
(
String
s
){
public
HexReader
(
String
s
)
{
this
.
s
=
s
;
this
.
s
=
s
;
}
}
public
String
readHex
(){
public
String
readHex
()
{
boolean
isStr
=
false
;
boolean
isStr
=
false
;
String
next
=
""
;
String
next
=
""
;
for
(;
pos
<
s
.
length
()-
2
;++
pos
)
{
for
(;
pos
<
s
.
length
()
-
2
;
++
pos
)
{
char
s1
=
' '
;
char
s1
=
' '
;
if
(
pos
!=
0
)
{
if
(
pos
!=
0
)
{
s1
=
this
.
s
.
charAt
(
0
);
s1
=
this
.
s
.
charAt
(
0
);
}
}
char
s2
=
this
.
s
.
charAt
(
pos
+
1
);
char
s2
=
this
.
s
.
charAt
(
pos
+
1
);
char
s3
=
this
.
s
.
charAt
(
pos
+
2
);
char
s3
=
this
.
s
.
charAt
(
pos
+
2
);
char
s4
=
' '
;
char
s4
=
' '
;
if
(
this
.
s
.
length
()
!=
(
this
.
pos
+
3
))
{
if
(
this
.
s
.
length
()
!=
(
this
.
pos
+
3
))
{
s4
=
this
.
s
.
charAt
(
pos
+
3
);
s4
=
this
.
s
.
charAt
(
pos
+
3
);
}
}
if
(
if
(
Character
.
isSpaceChar
(
s1
)
&&
Character
.
isSpaceChar
(
s4
)
Character
.
isSpaceChar
(
s1
)
&&
Character
.
isSpaceChar
(
s4
)
&&
&&
(
Character
.
isDigit
(
s2
)
||
Character
.
isAlphabetic
(
s2
))
(
Character
.
isDigit
(
s2
)
||
Character
.
isAlphabetic
(
s2
))
&&
&&
(
Character
.
isDigit
(
s3
)
||
Character
.
isAlphabetic
(
s3
))
(
Character
.
isDigit
(
s3
)
||
Character
.
isAlphabetic
(
s3
))
){
)
{
this
.
pos
+=
2
;
this
.
pos
+=
2
;
this
.
lastHaxPos
=
this
.
pos
+
1
;
this
.
lastHaxPos
=
this
.
pos
+
1
;
return
String
.
valueOf
(
s2
)
+
String
.
valueOf
(
s3
)
;
return
String
.
valueOf
(
s2
)
+
s3
;
}
}
}
}
return
""
;
return
""
;
}
}
public
void
readFully
(
BiConsumer
<
String
,
Integer
>
processor
){
public
void
readFully
(
BiConsumer
<
String
,
Integer
>
processor
)
{
this
.
reset
();
this
.
reset
();
String
nextHax
=
this
.
readHex
();
String
nextHax
=
this
.
readHex
();
while
(!
nextHax
.
equals
(
" "
)){
while
(!
nextHax
.
equals
(
" "
))
{
processor
.
accept
(
nextHax
,
this
.
lastHaxPos
);
processor
.
accept
(
nextHax
,
this
.
lastHaxPos
);
nextHax
=
this
.
readHex
();
nextHax
=
this
.
readHex
();
}
}
}
}
public
void
setTo
(
int
pos
){
public
void
setTo
(
int
pos
)
{
this
.
pos
=
pos
;
this
.
pos
=
pos
;
}
}
public
void
reset
(){
public
void
reset
()
{
this
.
pos
=
0
;
this
.
pos
=
0
;
}
}
}
}
mirai-core/src/test/java/TestKt.kt
0 → 100644
View file @
93dc8e58
import
net.mamoe.mirai.utils.toUHexString
/**
* @author Him188moe
*/
fun
main
()
{
println
(
"牛逼"
.
toByteArray
().
toUHexString
())
}
\ No newline at end of file
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