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