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
126b2210
Commit
126b2210
authored
Oct 02, 2019
by
Him188
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
New event listeners
parent
ffdb7c03
Changes
54
Hide whitespace changes
Inline
Side-by-side
Showing
54 changed files
with
790 additions
and
800 deletions
+790
-800
README.md
README.md
+6
-13
mirai-api/src/main/java/net/mamoe/mirai/MiraiAPI.java
mirai-api/src/main/java/net/mamoe/mirai/MiraiAPI.java
+25
-24
mirai-console/pom.xml
mirai-console/pom.xml
+54
-2
mirai-console/src/main/java/net/mamoe/mirai/MiraiMain.java
mirai-console/src/main/java/net/mamoe/mirai/MiraiMain.java
+0
-3
mirai-console/src/main/java/net/mamoe/mirai/MiraiServer.kt
mirai-console/src/main/java/net/mamoe/mirai/MiraiServer.kt
+200
-0
mirai-core/pom.xml
mirai-core/pom.xml
+5
-0
mirai-core/src/main/java/net/mamoe/mirai/Bot.java
mirai-core/src/main/java/net/mamoe/mirai/Bot.java
+0
-123
mirai-core/src/main/java/net/mamoe/mirai/Bot.kt
mirai-core/src/main/java/net/mamoe/mirai/Bot.kt
+103
-0
mirai-core/src/main/java/net/mamoe/mirai/BotKt.kt
mirai-core/src/main/java/net/mamoe/mirai/BotKt.kt
+5
-0
mirai-core/src/main/java/net/mamoe/mirai/contact/Contact.kt
mirai-core/src/main/java/net/mamoe/mirai/contact/Contact.kt
+1
-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/event/AsyncEvent.java
...-core/src/main/java/net/mamoe/mirai/event/AsyncEvent.java
+0
-27
mirai-core/src/main/java/net/mamoe/mirai/event/AsyncEventKt.kt
...-core/src/main/java/net/mamoe/mirai/event/AsyncEventKt.kt
+0
-18
mirai-core/src/main/java/net/mamoe/mirai/event/Cancellable.java
...core/src/main/java/net/mamoe/mirai/event/Cancellable.java
+0
-12
mirai-core/src/main/java/net/mamoe/mirai/event/Event.kt
mirai-core/src/main/java/net/mamoe/mirai/event/Event.kt
+53
-0
mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEvent.java
...-core/src/main/java/net/mamoe/mirai/event/MiraiEvent.java
+0
-35
mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEventHook.java
...e/src/main/java/net/mamoe/mirai/event/MiraiEventHook.java
+0
-114
mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEventHookKt.kt
...e/src/main/java/net/mamoe/mirai/event/MiraiEventHookKt.kt
+0
-40
mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEventKt.kt
...-core/src/main/java/net/mamoe/mirai/event/MiraiEventKt.kt
+0
-8
mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEventManager.java
...rc/main/java/net/mamoe/mirai/event/MiraiEventManager.java
+0
-159
mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEventManagerKt.kt
...rc/main/java/net/mamoe/mirai/event/MiraiEventManagerKt.kt
+0
-82
mirai-core/src/main/java/net/mamoe/mirai/event/Subscribers.kt
...i-core/src/main/java/net/mamoe/mirai/event/Subscribers.kt
+79
-0
mirai-core/src/main/java/net/mamoe/mirai/event/events/bot/BotEvent.kt
...rc/main/java/net/mamoe/mirai/event/events/bot/BotEvent.kt
+6
-3
mirai-core/src/main/java/net/mamoe/mirai/event/events/group/GroupMessageEvent.kt
...a/net/mamoe/mirai/event/events/group/GroupMessageEvent.kt
+2
-0
mirai-core/src/main/java/net/mamoe/mirai/event/events/network/ClientPacketEvents.kt
...et/mamoe/mirai/event/events/network/ClientPacketEvents.kt
+14
-2
mirai-core/src/main/java/net/mamoe/mirai/event/events/network/ServerPacketEvents.kt
...et/mamoe/mirai/event/events/network/ServerPacketEvents.kt
+4
-1
mirai-core/src/main/java/net/mamoe/mirai/event/events/qq/FriendMessageEvent.java
...a/net/mamoe/mirai/event/events/qq/FriendMessageEvent.java
+0
-5
mirai-core/src/main/java/net/mamoe/mirai/event/events/qq/FriendMessageEvent.kt
...ava/net/mamoe/mirai/event/events/qq/FriendMessageEvent.kt
+5
-1
mirai-core/src/main/java/net/mamoe/mirai/event/events/server/ServerDisabledEvent.java
.../mamoe/mirai/event/events/server/ServerDisabledEvent.java
+0
-8
mirai-core/src/main/java/net/mamoe/mirai/event/events/server/ServerEnabledEvent.java
...t/mamoe/mirai/event/events/server/ServerEnabledEvent.java
+0
-9
mirai-core/src/main/java/net/mamoe/mirai/event/internal/InternalEventListenres.kt
.../net/mamoe/mirai/event/internal/InternalEventListenres.kt
+76
-0
mirai-core/src/main/java/net/mamoe/mirai/network/BotNetworkHandler.kt
...rc/main/java/net/mamoe/mirai/network/BotNetworkHandler.kt
+2
-2
mirai-core/src/main/java/net/mamoe/mirai/network/protocol/tim/TIMBotNetworkHandler.kt
.../mamoe/mirai/network/protocol/tim/TIMBotNetworkHandler.kt
+19
-19
mirai-core/src/main/java/net/mamoe/mirai/network/protocol/tim/handler/MessagePacketHandler.kt
...irai/network/protocol/tim/handler/MessagePacketHandler.kt
+1
-0
mirai-core/src/main/java/net/mamoe/mirai/network/protocol/tim/packet/ClientPacket.kt
...t/mamoe/mirai/network/protocol/tim/packet/ClientPacket.kt
+2
-2
mirai-core/src/main/java/net/mamoe/mirai/network/protocol/tim/packet/ServerPacket.kt
...t/mamoe/mirai/network/protocol/tim/packet/ServerPacket.kt
+2
-2
mirai-core/src/main/java/net/mamoe/mirai/network/protocol/tim/packet/UnknownServerPacket.kt
.../mirai/network/protocol/tim/packet/UnknownServerPacket.kt
+2
-1
mirai-core/src/main/java/net/mamoe/mirai/network/protocol/tim/packet/action/AddContact.kt
...oe/mirai/network/protocol/tim/packet/action/AddContact.kt
+0
-2
mirai-core/src/main/java/net/mamoe/mirai/network/protocol/tim/packet/action/ClientSendFriendMessagePacket.kt
...otocol/tim/packet/action/ClientSendFriendMessagePacket.kt
+0
-1
mirai-core/src/main/java/net/mamoe/mirai/network/protocol/tim/packet/login/ClientLogin.kt
...oe/mirai/network/protocol/tim/packet/login/ClientLogin.kt
+20
-24
mirai-core/src/main/java/net/mamoe/mirai/network/protocol/tim/packet/login/ServerLoginResponseKeyExchangePacket.kt
.../tim/packet/login/ServerLoginResponseKeyExchangePacket.kt
+5
-5
mirai-core/src/main/java/net/mamoe/mirai/network/protocol/tim/packet/login/ServerLoginResponsePasswordVerifiedPacket.kt
...packet/login/ServerLoginResponsePasswordVerifiedPacket.kt
+2
-2
mirai-core/src/main/java/net/mamoe/mirai/network/protocol/tim/packet/login/ServerLoginResponseVerificationCodeInitPacket.kt
...et/login/ServerLoginResponseVerificationCodeInitPacket.kt
+1
-3
mirai-core/src/main/java/net/mamoe/mirai/task/MiraiTaskManager.java
.../src/main/java/net/mamoe/mirai/task/MiraiTaskManager.java
+0
-10
mirai-core/src/main/java/net/mamoe/mirai/utils/ContactList.java
...core/src/main/java/net/mamoe/mirai/utils/ContactList.java
+0
-9
mirai-core/src/main/java/net/mamoe/mirai/utils/ContactList.kt
...i-core/src/main/java/net/mamoe/mirai/utils/ContactList.kt
+8
-0
mirai-core/src/main/java/net/mamoe/mirai/utils/MiraiLogger.kt
...i-core/src/main/java/net/mamoe/mirai/utils/MiraiLogger.kt
+4
-3
mirai-core/src/test/java/BadQQFilter.kt
mirai-core/src/test/java/BadQQFilter.kt
+4
-2
mirai-core/src/test/java/PacketDebuger.kt
mirai-core/src/test/java/PacketDebuger.kt
+7
-7
mirai-core/src/test/java/data.txxt
mirai-core/src/test/java/data.txxt
+4
-4
mirai-core/src/test/java/event/EventTest.kt
mirai-core/src/test/java/event/EventTest.kt
+30
-0
mirai-demos/mirai-demo-1/src/main/java/demo1/Main.kt
mirai-demos/mirai-demo-1/src/main/java/demo1/Main.kt
+36
-5
mirai-demos/pom.xml
mirai-demos/pom.xml
+1
-0
pom.xml
pom.xml
+1
-7
No files found.
README.md
View file @
126b2210
...
...
@@ -3,7 +3,7 @@
一个以
<b>
TIM QQ协议(非web)
</b>
驱动的QQ机器人服务端核心
采用服务端-插件模式运行,同时提供独立的协议层库
**我们承诺项目的所有模块均开源**
项目的所有模块均开源
项目处于开发阶段,学生无法每日大量更新。
项目还有很多未完善的地方, 欢迎任何的代码贡献, 或是 issue.
...
...
@@ -22,19 +22,12 @@
### 事件 Hook
#### Java:
```
MiraiEventHook.onEvent(FriendMessageEvent.class)
.handler(a -> {
if(a.message.eq("你好"))
a.getSender().sendMessage("你好!");
})
.mountAlways();
```
暂不支持
#### Kotlin:
```
FriendMessageEvent
::class.hook
Always{
if(it.message eq "你好")
it.reply("你好!")
```
kotlin
FriendMessageEvent
.
subscribe
Always
{
if
(
it
.
message
eq
"你好"
)
it
.
reply
(
"你好!"
)
}
```

...
...
mirai-api/src/main/java/net/mamoe/mirai/MiraiAPI.java
View file @
126b2210
...
...
@@ -5,58 +5,59 @@ import java.util.List;
/**
* MiraiAPI provides
*
- the status of the Mirai-Core
*
- the fundamental bot operations.
*
- the plugin status.
*
*
It was designed for users, not developers,
*
Web-based controller, UI controller or console is depending on Mirai-API
*
*
Mirai-API does NOT contains fancy objects, and this means there are less functions it can do compare with Mirai-Core
*
*
Again, for extending/developing Mirai, you should refer to Mirai-Core
*
for only using
, you should refer to Mirai-API
* - the status of the Mirai-Core
* - the fundamental bot operations.
* - the plugin status.
*
<p>
* It was designed for users, not developers,
* Web-based controller, UI controller or console is depending on Mirai-API
*
<p>
* Mirai-API does NOT contains fancy objects, and this means there are less functions it can do compare with Mirai-Core
*
<p>
* Again, for extending/developing Mirai, you should refer to Mirai-Core
*
for only using
, you should refer to Mirai-API
*/
public
class
MiraiAPI
{
public
static
void
startMirai
(
String
[]
args
){
public
static
void
startMirai
(
String
[]
args
)
{
MiraiMain
.
main
(
args
);
}
public
static
void
closeMirai
(){
MiraiServer
.
getInstance
()
.
shutdown
();
public
static
void
closeMirai
()
{
MiraiServer
.
INSTANCE
.
shutdown
();
}
public
static
void
restartMirai
(
String
[]
args
){
MiraiServer
.
getInstance
()
.
shutdown
();
public
static
void
restartMirai
(
String
[]
args
)
{
MiraiServer
.
INSTANCE
.
shutdown
();
MiraiMain
.
main
(
args
);
}
public
static
String
getMiraiVersion
(){
public
static
String
getMiraiVersion
()
{
return
MiraiServer
.
MIRAI_VERSION
;
}
public
static
String
getQQPortocolVersion
(){
public
static
String
getQQPortocolVersion
()
{
return
MiraiServer
.
QQ_VERSION
;
}
public
static
boolean
isMiraiEnabled
(){
return
MiraiServer
.
getInstance
()!=
null
;
public
static
boolean
isMiraiEnabled
()
{
// TODO: 2019/10/2
return
false
;
}
public
static
List
<
String
>
getEnabledPluginList
(){
public
static
List
<
String
>
getEnabledPluginList
()
{
return
new
ArrayList
<>();
}
public
static
List
<
Long
>
getEnabledBots
(){
public
static
List
<
Long
>
getEnabledBots
()
{
return
new
ArrayList
<>();
}
public
static
Bot
getBot
(
long
qq
){
public
static
Bot
getBot
(
long
qq
)
{
return
new
Bot
(
qq
);
}
public
static
void
addBot
(
long
qq
,
String
password
){
public
static
void
addBot
(
long
qq
,
String
password
)
{
}
...
...
mirai-console/pom.xml
View file @
126b2210
...
...
@@ -13,15 +13,23 @@
<artifactId>
mirai-console
</artifactId>
<version>
1.0
</version>
<dependencies>
<dependency>
<groupId>
net.mamoe
</groupId>
<artifactId>
mirai-core
</artifactId>
<version>
1.0
</version>
<scope>
compile
</scope>
</dependency>
<dependency>
<groupId>
org.jetbrains.kotlin
</groupId>
<artifactId>
kotlin-stdlib
</artifactId>
</dependency>
<dependency>
<groupId>
org.jetbrains.kotlin
</groupId>
<artifactId>
kotlin-test
</artifactId>
<version>
${kotlin.version}
</version>
<scope>
test
</scope>
</dependency>
</dependencies>
<build>
...
...
@@ -37,6 +45,50 @@
<plugins>
<plugin>
<groupId>
org.jetbrains.kotlin
</groupId>
<artifactId>
kotlin-maven-plugin
</artifactId>
<version>
${kotlin.version}
</version>
<executions>
<execution>
<id>
compile
</id>
<phase>
compile
</phase>
<goals>
<goal>
compile
</goal>
</goals>
</execution>
<execution>
<id>
test-compile
</id>
<phase>
test-compile
</phase>
<goals>
<goal>
test-compile
</goal>
</goals>
</execution>
</executions>
<configuration>
<jvmTarget>
1.8
</jvmTarget>
</configuration>
</plugin>
<plugin>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-compiler-plugin
</artifactId>
<executions>
<execution>
<id>
compile
</id>
<phase>
compile
</phase>
<goals>
<goal>
compile
</goal>
</goals>
</execution>
<execution>
<id>
testCompile
</id>
<phase>
test-compile
</phase>
<goals>
<goal>
testCompile
</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
...
mirai-console/src/main/java/net/mamoe/mirai/MiraiMain.java
View file @
126b2210
...
...
@@ -3,8 +3,6 @@ package net.mamoe.mirai;
import
lombok.Getter
;
import
java.io.PrintStream
;
/**
* @author NaturalHG
*/
...
...
@@ -13,7 +11,6 @@ public final class MiraiMain {
private
static
MiraiServer
server
;
public
static
void
main
(
String
[]
args
)
{
server
=
new
MiraiServer
();
Runtime
.
getRuntime
().
addShutdownHook
(
new
Thread
(()
->
server
.
shutdown
()));
}
}
\ No newline at end of file
mirai-console/src/main/java/net/mamoe/mirai/MiraiServer.
java
→
mirai-console/src/main/java/net/mamoe/mirai/MiraiServer.
kt
View file @
126b2210
package
net.mamoe.mirai
;
import
lombok.Getter
;
import
net.mamoe.mirai.event.MiraiEventManager
;
import
net.mamoe.mirai.event.events.server.ServerDisabledEvent
;
import
net.mamoe.mirai.event.events.server.ServerEnabledEvent
;
import
net.mamoe.mirai.network.protocol.tim.packet.login.LoginState
;
import
net.mamoe.mirai.task.MiraiTaskManager
;
import
net.mamoe.mirai.utils.*
;
import
net.mamoe.mirai.utils.config.MiraiConfig
;
import
net.mamoe.mirai.utils.setting.MiraiSettingListSection
;
import
net.mamoe.mirai.utils.setting.MiraiSettingMapSection
;
import
net.mamoe.mirai.utils.setting.MiraiSettings
;
import
java.io.File
;
import
java.io.IOException
;
import
java.util.concurrent.ExecutionException
;
package
net.mamoe.mirai
import
kotlinx.coroutines.runBlocking
import
lombok.Getter
import
net.mamoe.mirai.network.protocol.tim.packet.login.LoginState
import
net.mamoe.mirai.task.MiraiTaskManager
import
net.mamoe.mirai.utils.*
import
net.mamoe.mirai.utils.config.MiraiConfig
import
net.mamoe.mirai.utils.setting.MiraiSettings
import
java.io.File
import
java.io.IOException
import
java.util.concurrent.ExecutionException
/**
* @author Him188moe
*/
/**
* Mirai 服务器.
...
...
@@ -22,68 +21,44 @@ import java.util.concurrent.ExecutionException;
*
* @author NaturalHG
*/
public
final
class
MiraiServer
{
private
static
MiraiServer
instance
;
public
static
MiraiServer
getInstance
()
{
return
instance
;
}
public
final
static
String
MIRAI_VERSION
=
"1.0.0"
;
public
final
static
String
QQ_VERSION
=
"4.9.0"
;
object
MiraiServer
{
const
val
MIRAI_VERSION
=
"1.0.0"
const
val
QQ_VERSION
=
"4.9.0"
@Getter
//is running under UNIX
private
boolean
unix
;
var
isUnix
:
Boolean
=
false
private
set
@Getter
//file pathq
public
File
parentFolder
;
@Getter
MiraiEventManager
eventManager
;
@Getter
MiraiTaskManager
taskManager
;
var
parentFolder
:
File
=
File
(
System
.
getProperty
(
"user.dir"
))
@Getter
MiraiLogger
logger
;
MiraiSettings
settings
;
MiraiConfig
qqs
;
var
taskManager
:
MiraiTaskManager
internal
set
@Getter
var
logger
:
MiraiLogger
internal
set
MiraiServer
()
{
instance
=
this
;
this
.
onLoaded
();
this
.
onEnabled
();
}
private
boolean
enabled
;
internal
lateinit
var
settings
:
MiraiSettings
void
shutdown
()
{
if
(
this
.
enabled
)
{
getLogger
().
info
(
"About to shutdown Mirai"
);
this
.
eventManager
.
broadcastEventAsync
(
new
ServerDisabledEvent
());
getLogger
().
info
(
"Data have been saved"
);
}
internal
lateinit
var
qqs
:
MiraiConfig
}
private
var
enabled
:
Boolean
=
false
private
void
onLoaded
()
{
this
.
parentFolder
=
new
File
(
System
.
getProperty
(
"user.dir"
));
this
.
unix
=
!
System
.
getProperties
().
getProperty
(
"os.name"
).
toUpperCase
().
contains
(
"WINDOWS"
);
init
{
this
.
isUnix
=
!
System
.
getProperties
().
getProperty
(
"os.name"
).
toUpperCase
().
contains
(
"WINDOWS"
)
this
.
logger
=
MiraiLogger
.
Companion
;
this
.
eventManager
=
MiraiEventManager
.
getInstance
();
this
.
taskManager
=
MiraiTaskManager
.
getInstance
();
this
.
logger
=
MiraiLogger
this
.
taskManager
=
MiraiTaskManager
.
getInstance
()
getLogger
().
info
(
"About to run Mirai ("
+
MiraiServer
.
MIRAI_VERSION
+
") under "
+
(
isUnix
()
?
"unix"
:
"windows"
));
getLogger
().
info
(
"Loading data under "
+
LoggerTextFormat
.
GREEN
+
this
.
parentFolder
);
logger
.
info
(
"About to run Mirai ("
+
MiraiServer
.
MIRAI_VERSION
+
") under "
+
if
(
isUnix
)
"unix"
else
"windows"
)
logger
.
info
(
"Loading data under "
+
LoggerTextFormat
.
GREEN
+
this
.
parentFolder
)
File
setting
=
new
File
(
this
.
parentFolder
+
"/Mirai.ini"
);
getLogger
().
info
(
"Selecting setting from "
+
LoggerTextFormat
.
GREEN
+
setting
);
val
setting
=
this
.
parentFolder
+
"/Mirai.ini"
logger
.
info
(
"Selecting setting from "
+
LoggerTextFormat
.
GREEN
+
setting
)
/*
if (!setting.exists()) {
...
...
@@ -117,54 +92,66 @@ public final class MiraiServer {
});
*/
this
.
reload
()
}
fun
shutdown
()
{
if
(
this
.
enabled
)
{
logger
.
info
(
"About to shutdown Mirai"
)
logger
.
info
(
"Data have been saved"
)
}
}
private
void
initSetting
(
File
setting
)
{
getLogger
().
info
(
"Thanks for using Mirai"
);
getLogger
().
info
(
"initializing Settings"
);
private
fun
initSetting
(
setting
:
File
)
{
logger
.
info
(
"Thanks for using Mirai"
)
logger
.
info
(
"initializing Settings"
)
try
{
if
(
setting
.
createNewFile
())
{
getLogger
().
info
(
"Mirai Config Created"
);
logger
.
info
(
"Mirai Config Created"
)
}
}
catch
(
IOException
e
)
{
e
.
printStackTrace
()
;
}
catch
(
e
:
IOException
)
{
e
.
printStackTrace
()
}
this
.
settings
=
new
MiraiSettings
(
setting
);
MiraiSettingMapSection
network
=
this
.
settings
.
getMapSection
(
"network"
);
network
.
set
(
"enable_proxy"
,
"not supporting yet"
);
MiraiSettingListSection
proxy
=
this
.
settings
.
getListSection
(
"proxy"
);
proxy
.
add
(
"1.2.3.4:95"
);
proxy
.
add
(
"1.2.3.4:100"
);
this
.
settings
=
MiraiSettings
(
setting
)
val
network
=
this
.
settings
.
getMapSection
(
"network"
)
network
.
set
(
"enable_proxy"
,
"not supporting yet"
)
MiraiSettingMapSection
worker
=
this
.
settings
.
getMapSection
(
"worker"
);
worker
.
set
(
"core_task_pool_worker_amount"
,
5
);
val
proxy
=
this
.
settings
.
getListSection
(
"proxy"
)
proxy
.
add
(
"1.2.3.4:95"
)
proxy
.
add
(
"1.2.3.4:100"
)
MiraiSettingMapSection
plugin
=
this
.
settings
.
getMapSection
(
"plugin"
);
plugin
.
set
(
"debug"
,
false
);
val
worker
=
this
.
settings
.
getMapSection
(
"worker"
)
worker
.
set
(
"core_task_pool_worker_amount"
,
5
)
this
.
settings
.
save
();
getLogger
().
info
(
"initialized; changing can be made in setting file: "
+
setting
.
toString
());
val
plugin
=
this
.
settings
.
getMapSection
(
"plugin"
)
plugin
.
set
(
"debug"
,
false
)
this
.
settings
.
save
()
logger
.
info
(
"initialized; changing can be made in setting file: $setting"
)
}
private
void
initQQConfig
(
File
qqConfig
)
{
this
.
qqs
=
new
MiraiConfig
(
qqConfig
);
getLogger
().
info
(
"QQ account initialized; changing can be made in Config file: "
+
qqConfig
.
toString
());
getLogger
().
info
(
"QQ 账户管理初始化完毕"
);
private
fun
initQQConfig
(
qqConfig
:
File
)
{
this
.
qqs
=
MiraiConfig
(
qqConfig
)
MiraiLogger
.
info
(
"QQ account initialized; changing can be made in Config file: $qqConfig"
)
logger
.
info
(
"QQ 账户管理初始化完毕"
)
}
private
void
onEnabled
()
{
this
.
enabled
=
true
;
this
.
eventManager
.
broadcastEventAsync
(
new
ServerEnabledEvent
());
getLogger
().
info
(
LoggerTextFormat
.
GREEN
+
"Server enabled; Welcome to Mirai"
);
getLogger
().
info
(
"Mirai Version="
+
MiraiServer
.
MIRAI_VERSION
+
" QQ Version="
+
MiraiServer
.
QQ_VERSION
);
private
fun
reload
()
{
this
.
enabled
=
true
MiraiLogger
.
info
(
LoggerTextFormat
.
GREEN
.
toString
()
+
"Server enabled; Welcome to Mirai"
)
MiraiLogger
.
info
(
"Mirai Version="
+
MiraiServer
.
MIRAI_VERSION
+
" QQ Version="
+
MiraiServer
.
QQ_VERSION
)
getLogger
().
info
(
"Initializing [Bot]s"
);
MiraiLogger
.
info
(
"Initializing [Bot]s"
)
try
{
getAvailableBot
();
}
catch
(
ExecutionException
|
InterruptedException
e
)
{
e
.
printStackTrace
();
availableBot
}
catch
(
e
:
ExecutionException
)
{
e
.
printStackTrace
()
}
catch
(
e
:
InterruptedException
)
{
e
.
printStackTrace
()
}
/*
...
...
@@ -176,7 +163,7 @@ public final class MiraiServer {
//bot.network.tryLogin$mirai_core().whenComplete((state, e) -> {
if (state == LoginState.SUCCESS) {
Bot.instances.add(bot);
getLogger().
success
(" Login Succeed");
getLogger().
green
(" Login Succeed");
} else {
getLogger().error(" Login Failed with error " + state);
bot.close();
...
...
@@ -192,20 +179,22 @@ public final class MiraiServer {
}
String
qqList
=
"1683921395----bb22222\n"
;
//todo only for test now
private
var
qqList
=
"1683921395----bb22222\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
]),
new
Console
());
private
val
availableBot
:
Bot
@Throws
(
ExecutionException
::
class
,
InterruptedException
::
class
)
get
()
{
for
(
it
in
qqList
.
split
(
"\n"
).
dropLastWhile
{
it
.
isEmpty
()
}.
toTypedArray
())
{
val
strings
=
it
.
split
(
"----"
).
dropLastWhile
{
it
.
isEmpty
()
}.
toTypedArray
()
val
bot
=
Bot
(
BotAccount
(
strings
[
0
].
toLong
(),
strings
[
1
]),
Console
())
if
(
bot
.
network
.
tryLogin
(
200
).
get
()
==
LoginState
.
SUCCESS
)
{
MiraiLoggerKt
.
success
(
bot
,
"Login succeed"
);
return
bot
;
if
(
runBlocking
{
bot
.
network
.
tryLogin
(
200
).
await
()
}
===
LoginState
.
SUCCESS
)
{
bot
.
green
(
"Login succeed"
)
return
bot
}
}
}
throw
new
RuntimeException
();
}
throw
RuntimeException
()
}
}
mirai-core/pom.xml
View file @
126b2210
...
...
@@ -106,6 +106,11 @@
<plugin>
<groupId>
org.jetbrains.kotlin
</groupId>
<artifactId>
kotlin-maven-plugin
</artifactId>
<configuration>
<args>
<arg>
-XXLanguage:+InlineClasses
</arg>
</args>
</configuration>
</plugin>
</plugins>
</build>
...
...
mirai-core/src/main/java/net/mamoe/mirai/Bot.java
deleted
100644 → 0
View file @
ffdb7c03
package
net.mamoe.mirai
;
import
net.mamoe.mirai.contact.Group
;
import
net.mamoe.mirai.contact.QQ
;
import
net.mamoe.mirai.network.BotNetworkHandler
;
import
net.mamoe.mirai.network.protocol.tim.TIMBotNetworkHandler
;
import
net.mamoe.mirai.utils.BotAccount
;
import
net.mamoe.mirai.utils.ContactList
;
import
net.mamoe.mirai.utils.MiraiLogger
;
import
org.jetbrains.annotations.NotNull
;
import
java.io.Closeable
;
import
java.util.Collections
;
import
java.util.LinkedList
;
import
java.util.List
;
import
java.util.Objects
;
import
java.util.concurrent.atomic.AtomicInteger
;
/**
* Mirai 的机器人. 一个机器人实例登录一个 QQ 账号.
* Mirai 为多账号设计, 可同时维护多个机器人.
* <br>
* {@link Bot} 由 3 个模块组成.
* {@linkplain ContactSystem 联系人管理}: 可通过 {@link Bot#contacts} 访问
* {@linkplain TIMBotNetworkHandler 网络处理器}: 可通过 {@link Bot#network} 访问
* {@linkplain BotAccount 机器人账号信息}: 可通过 {@link Bot#account} 访问
* <br>
* 若你需要得到机器人的 QQ 账号, 请访问 {@link Bot#account}
* 若你需要得到服务器上所有机器人列表, 请访问 {@link Bot#instances}
*
* <p>
* 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 TIMBotNetworkHandler}, which manages the connection to the server;
* a {@link BotAccount}, which stores the account information(e.g. qq number the bot)
* <br>
* To of all the QQ contacts, access {@link Bot#account}
* To of all the Robot instance, access {@link Bot#instances}
* </p>
*
* @author Him188moe
* @author NatrualHG
* @see net.mamoe.mirai.contact.Contact
*/
public
final
class
Bot
implements
Closeable
{
public
static
final
List
<
Bot
>
instances
=
Collections
.
synchronizedList
(
new
LinkedList
<>());
{
instances
.
add
(
this
);
}
public
final
int
id
=
_id
.
getAndAdd
(
1
);
public
final
BotAccount
account
;
public
final
ContactSystem
contacts
=
new
ContactSystem
();
public
final
BotNetworkHandler
network
;
public
final
MiraiLogger
logger
;
@Override
public
String
toString
()
{
return
String
.
format
(
"Bot{id=%d,qq=%d}"
,
id
,
this
.
account
.
getQqNumber
());
}
/**
* Bot 联系人管理.
*
* @see Bot#contacts
*/
public
final
class
ContactSystem
{
private
final
ContactList
<
Group
>
groups
=
new
ContactList
<>();
private
final
ContactList
<
QQ
>
qqs
=
new
ContactList
<>();
private
ContactSystem
()
{
}
public
QQ
getQQ
(
long
qqNumber
)
{
if
(!
this
.
qqs
.
containsKey
(
qqNumber
))
{
this
.
qqs
.
put
(
qqNumber
,
new
QQ
(
Bot
.
this
,
qqNumber
));
}
return
this
.
qqs
.
get
(
qqNumber
);
}
public
Group
getGroupByNumber
(
long
groupNumber
)
{
if
(!
this
.
groups
.
containsKey
(
groupNumber
))
{
this
.
groups
.
put
(
groupNumber
,
new
Group
(
Bot
.
this
,
groupNumber
));
}
return
groups
.
get
(
groupNumber
);
}
public
Group
getGroupById
(
long
groupId
)
{
return
getGroupByNumber
(
Group
.
Companion
.
groupIdToNumber
(
groupId
));
}
}
public
Bot
(
@NotNull
BotAccount
account
,
@NotNull
MiraiLogger
logger
)
{
Objects
.
requireNonNull
(
account
);
this
.
account
=
account
;
this
.
logger
=
Objects
.
requireNonNull
(
logger
);
this
.
logger
.
setIdentity
(
"Bot"
+
this
.
id
+
"("
+
this
.
account
.
getQqNumber
()
+
")"
);
this
.
network
=
new
TIMBotNetworkHandler
(
this
);
}
public
void
close
()
{
this
.
network
.
close
();
this
.
contacts
.
groups
.
values
().
forEach
(
Group:
:
close
);
this
.
contacts
.
groups
.
clear
();
this
.
contacts
.
qqs
.
clear
();
}
/* PRIVATE */
private
static
final
AtomicInteger
_id
=
new
AtomicInteger
(
0
);
}
mirai-core/src/main/java/net/mamoe/mirai/Bot.kt
0 → 100644
View file @
126b2210
package
net.mamoe.mirai
import
net.mamoe.mirai.Bot.ContactSystem
import
net.mamoe.mirai.contact.Group
import
net.mamoe.mirai.contact.QQ
import
net.mamoe.mirai.network.BotNetworkHandler
import
net.mamoe.mirai.network.protocol.tim.TIMBotNetworkHandler
import
net.mamoe.mirai.utils.BotAccount
import
net.mamoe.mirai.utils.ContactList
import
net.mamoe.mirai.utils.MiraiLogger
import
java.io.Closeable
import
java.util.*
import
java.util.concurrent.atomic.AtomicInteger
/**
* Mirai 的机器人. 一个机器人实例登录一个 QQ 账号.
* Mirai 为多账号设计, 可同时维护多个机器人.
* <br></br>
* [Bot] 由 3 个模块组成.
* [联系人管理][ContactSystem]: 可通过 [Bot.contacts] 访问
* [网络处理器][TIMBotNetworkHandler]: 可通过 [Bot.network] 访问
* [机器人账号信息][BotAccount]: 可通过 [Bot.account] 访问
* <br></br>
* 若你需要得到机器人的 QQ 账号, 请访问 [Bot.account]
* 若你需要得到服务器上所有机器人列表, 请访问 [Bot.instances]
*
*
*
* Bot that is the base of the whole program.
* It consists of
* a [ContactSystem], which manage contacts such as [QQ] and [Group];
* a [TIMBotNetworkHandler], which manages the connection to the server;
* a [BotAccount], which stores the account information(e.g. qq number the bot)
* <br></br>
* To of all the QQ contacts, access [Bot.account]
* To of all the Robot instance, access [Bot.instances]
*
*
* @author Him188moe
* @author NatrualHG
* @see net.mamoe.mirai.contact.Contact
*/
class
Bot
(
val
account
:
BotAccount
,
val
logger
:
MiraiLogger
)
:
Closeable
{
val
id
=
createdBotsCount
.
getAndAdd
(
1
)
val
contacts
=
ContactSystem
()
val
network
:
BotNetworkHandler
=
TIMBotNetworkHandler
(
this
)
init
{
instances
.
add
(
this
)
this
.
logger
.
identity
=
"Bot"
+
this
.
id
+
"("
+
this
.
account
.
qqNumber
+
")"
}
override
fun
toString
():
String
=
"Bot{id=$id,qq=${account.qqNumber}}"
/**
* Bot 联系人管理.
*
* @see Bot.contacts
*/
inner
class
ContactSystem
internal
constructor
()
{
val
groups
=
ContactList
<
Group
>()
val
qqs
=
ContactList
<
QQ
>()
fun
getQQ
(
qqNumber
:
Long
):
QQ
{
synchronized
(
this
.
qqs
)
{
if
(!
this
.
qqs
.
containsKey
(
qqNumber
))
{
this
.
qqs
[
qqNumber
]
=
QQ
(
this
@Bot
,
qqNumber
)
}
return
this
.
qqs
[
qqNumber
]
!!
}
}
fun
getGroupByNumber
(
groupNumber
:
Long
):
Group
{
synchronized
(
this
.
groups
)
{
if
(!
this
.
groups
.
containsKey
(
groupNumber
))
{
this
.
groups
[
groupNumber
]
=
Group
(
this
@Bot
,
groupNumber
)
}
return
this
.
groups
[
groupNumber
]
!!
}
}
fun
getGroupById
(
groupId
:
Long
):
Group
{
return
getGroupByNumber
(
Group
.
groupIdToNumber
(
groupId
))
}
}
override
fun
close
()
{
this
.
network
.
close
()
this
.
contacts
.
groups
.
values
.
forEach
{
it
.
close
()
}
this
.
contacts
.
groups
.
clear
()
this
.
contacts
.
qqs
.
clear
()
}
companion
object
{
val
instances
:
MutableList
<
Bot
>
=
Collections
.
synchronizedList
(
LinkedList
())
private
val
createdBotsCount
=
AtomicInteger
(
0
)
}
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/BotKt.kt
View file @
126b2210
...
...
@@ -3,6 +3,7 @@ package net.mamoe.mirai
import
net.mamoe.mirai.contact.Group
import
net.mamoe.mirai.contact.QQ
import
net.mamoe.mirai.network.protocol.tim.packet.ClientPacket
import
net.mamoe.mirai.utils.ContactList
/**
* The mirror of functions in inner classes of [Bot]
...
...
@@ -17,6 +18,10 @@ fun Bot.getGroupByNumber(number: Long): Group = this.contacts.getGroupByNumber(n
fun
Bot
.
getGroupById
(
number
:
Long
):
Group
=
this
.
contacts
.
getGroupById
(
number
)
val
Bot
.
groups
:
ContactList
<
Group
>
get
()
=
this
.
contacts
.
groups
val
Bot
.
qqs
:
ContactList
<
QQ
>
get
()
=
this
.
contacts
.
qqs
//NetworkHandler
suspend
fun
Bot
.
sendPacket
(
packet
:
ClientPacket
)
{
...
...
mirai-core/src/main/java/net/mamoe/mirai/contact/Contact.kt
View file @
126b2210
...
...
@@ -18,6 +18,7 @@ import java.util.concurrent.CompletableFuture
* @author Him188moe
*/
abstract
class
Contact
internal
constructor
(
val
bot
:
Bot
,
val
number
:
Long
)
{
abstract
suspend
fun
sendMessage
(
message
:
MessageChain
)
/**
...
...
mirai-core/src/main/java/net/mamoe/mirai/contact/Group.kt
View file @
126b2210
...
...
@@ -23,7 +23,7 @@ import java.io.Closeable
*/
class
Group
(
bot
:
Bot
,
number
:
Long
)
:
Contact
(
bot
,
number
),
Closeable
{
val
groupId
=
groupNumberToId
(
number
)
val
members
=
ContactList
<
QQ
>()
val
members
=
ContactList
<
QQ
>()
//todo members
override
suspend
fun
sendMessage
(
message
:
MessageChain
)
{
bot
.
network
.
message
.
sendGroupMessage
(
this
,
message
)
...
...
mirai-core/src/main/java/net/mamoe/mirai/event/AsyncEvent.java
deleted
100644 → 0
View file @
ffdb7c03
package
net.mamoe.mirai.event
;
import
java.util.concurrent.CompletableFuture
;
import
java.util.function.Consumer
;
/**
* 实现这个接口的事件可以被异步执行或阻塞执行
*
* @author Him188moe
* @see AsyncEventKt 若你使用 kotlin, 请查看针对 kotlin 的优化实现
*/
public
interface
AsyncEvent
{
default
CompletableFuture
<?
extends
AsyncEvent
>
broadcastAsync
()
{
return
MiraiEventManager
.
getInstance
().
broadcastEventAsync
(
this
);
}
@SuppressWarnings
(
"unchecked"
)
default
<
E
extends
AsyncEvent
>
CompletableFuture
<
E
>
broadcastEventAsync
(
Consumer
<
E
>
callback
)
{
return
MiraiEventManager
.
getInstance
().
broadcastEventAsync
((
E
)
this
,
callback
);
}
@SuppressWarnings
(
"unchecked"
)
default
<
E
extends
AsyncEvent
>
CompletableFuture
<
E
>
broadcastEventAsync
(
Runnable
callback
)
{
return
MiraiEventManager
.
getInstance
().
broadcastEventAsync
((
E
)
this
,
callback
);
}
}
mirai-core/src/main/java/net/mamoe/mirai/event/AsyncEventKt.kt
deleted
100644 → 0
View file @
ffdb7c03
@
file
:
JvmName
(
"AsyncEventKt"
)
package
net.mamoe.mirai.event
import
java.util.concurrent.CompletableFuture
import
java.util.function.Consumer
fun
<
E
:
AsyncEvent
>
E
.
broadcastAsync
(
callback
:
Consumer
<
E
>):
CompletableFuture
<
E
>
{
return
MiraiEventManager
.
getInstance
().
broadcastEventAsync
(
this
,
callback
)
}
fun
<
E
:
AsyncEvent
>
E
.
broadcastAsync
(
callback
:
Runnable
):
CompletableFuture
<
E
>
{
return
MiraiEventManager
.
getInstance
().
broadcastEventAsync
(
this
,
callback
)
}
fun
<
E
:
AsyncEvent
>
E
.
broadcastAsyncSmart
():
CompletableFuture
<
E
>
{
return
MiraiEventManager
.
getInstance
().
broadcastEventAsync
(
this
)
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/event/Cancellable.java
deleted
100644 → 0
View file @
ffdb7c03
package
net.mamoe.mirai.event
;
/**
* @author NaturalHG
*/
public
interface
Cancellable
{
boolean
isCancelled
();
void
cancel
(
boolean
forceCancel
);
void
cancel
();
}
mirai-core/src/main/java/net/mamoe/mirai/event/Event.kt
0 → 100644
View file @
126b2210
@
file
:
Suppress
(
"unused"
)
package
net.mamoe.mirai.event
import
net.mamoe.mirai.event.internal.broadcastInternal
/**
* 所有事件的基类.
* 若监听这个类, 监听器将会接收所有事件的广播.
*
* @see [broadcast] 广播事件
* @see [subscribe] 监听事件
* @author Him188moe
*/
abstract
class
Event
{
/**
* 事件是否已取消. 事件需实现 [Cancellable] 才可以被取消, 否则这个字段为常量值 false
*/
var
cancelled
:
Boolean
=
false
get
()
=
field
.
takeIf
{
this
is
Cancellable
}
?:
false
private
set
(
value
)
=
if
(
this
is
Cancellable
)
{
check
(!
field
);
field
=
value
}
else
throw
UnsupportedOperationException
()
/**
* 取消事件. 事件需实现 [Cancellable] 才可以被取消, 否则调用这个方法将会得到 [UnsupportedOperationException]
*
* @throws UnsupportedOperationException 如果事件没有实现 [Cancellable]
*/
@Throws
(
UnsupportedOperationException
::
class
)
fun
cancel
()
{
cancelled
=
true
}
}
/**
* 实现这个接口的事件可以被取消.
*
* @author Him188moe
*/
interface
Cancellable
{
val
cancelled
:
Boolean
fun
cancel
()
}
/**
* 广播一个事件的唯一途径
*/
@Synchronized
@Suppress
(
"UNCHECKED_CAST"
)
suspend
fun
<
E
:
Event
>
E
.
broadcast
():
E
=
this
.
broadcastInternal
()
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEvent.java
deleted
100644 → 0
View file @
ffdb7c03
package
net.mamoe.mirai.event
;
import
net.mamoe.mirai.utils.EventException
;
/**
* @author NatrualHG
* @see AsyncEvent
*/
public
abstract
class
MiraiEvent
{
private
boolean
cancelled
;
public
boolean
isCancelled
()
{
if
(!(
this
instanceof
Cancellable
))
{
return
false
;
}
return
this
.
cancelled
;
}
public
void
cancel
()
{
cancel
(
true
);
}
public
void
cancel
(
boolean
value
)
{
if
(!(
this
instanceof
Cancellable
))
{
throw
new
EventException
(
"Event is not Cancellable"
);
}
this
.
cancelled
=
value
;
}
public
final
MiraiEvent
broadcast
()
{
MiraiEventManager
.
getInstance
().
broadcastEvent
(
this
);
return
this
;
}
}
mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEventHook.java
deleted
100644 → 0
View file @
ffdb7c03
package
net.mamoe.mirai.event
;
import
lombok.Getter
;
import
lombok.Setter
;
import
java.io.Closeable
;
import
java.util.function.Consumer
;
import
java.util.function.Predicate
;
/**
* @author NatrualHG
*/
public
class
MiraiEventHook
<
T
extends
MiraiEvent
>
implements
Closeable
{
@Getter
Class
<
T
>
eventClass
;
@Getter
protected
volatile
Consumer
<
T
>
handler
;
@Getter
private
volatile
int
priority
=
0
;
@Getter
private
volatile
boolean
ignoreCancelled
=
true
;
@Getter
@Setter
private
volatile
boolean
mount
=
false
;
/**
* return true -> this hook need to be removed
*/
@Getter
protected
Predicate
<
T
>
validChecker
;
public
MiraiEventHook
(
Class
<
T
>
eventClass
)
{
this
(
eventClass
,
null
);
}
public
MiraiEventHook
(
Class
<
T
>
eventClass
,
Consumer
<
T
>
handler
){
this
.
eventClass
=
eventClass
;
this
.
handler
(
handler
);
}
public
MiraiEventHook
<
T
>
handler
(
Consumer
<
T
>
handler
)
{
this
.
handler
=
handler
;
return
this
;
}
public
MiraiEventHook
<
T
>
priority
(
int
priority
)
{
this
.
priority
=
priority
;
return
this
;
}
public
MiraiEventHook
<
T
>
ignoreCancelled
(
boolean
ignoreCancelled
)
{
this
.
ignoreCancelled
=
ignoreCancelled
;
return
this
;
}
private
MiraiEventHook
<
T
>
setValidChecker
(
Predicate
<
T
>
validChecker
)
{
this
.
validChecker
=
validChecker
;
return
this
;
}
public
MiraiEventHook
<
T
>
setValidUntil
(
Predicate
<
T
>
valid
)
{
return
this
.
setValidChecker
(
valid
);
}
public
MiraiEventHook
<
T
>
setValidWhile
(
Predicate
<
T
>
valid
)
{
return
this
.
setValidChecker
(
valid
.
negate
());
}
@SuppressWarnings
(
"unchecked"
)
public
boolean
accept
(
MiraiEvent
event
)
{
if
(!(
event
instanceof
Cancellable
&&
event
.
isCancelled
()
&&
this
.
isIgnoreCancelled
())){
this
.
getHandler
().
accept
((
T
)
event
);
}
return
this
.
validChecker
==
null
||
this
.
validChecker
.
test
((
T
)
event
);
}
/**
* 更加安全高效的方式
* Remember to use {@link this.mount()} at last
* */
public
static
<
D
extends
MiraiEvent
>
MiraiEventHook
<
D
>
onEvent
(
Class
<
D
>
event
){
return
new
MiraiEventHook
<>(
event
);
}
public
void
mount
(){
if
(
this
.
handler
==
null
)
this
.
handler
=
a
->
{};
MiraiEventManager
.
getInstance
().
registerHook
(
this
);
}
public
void
mountAlways
(){
if
(
this
.
handler
==
null
)
this
.
handler
=
a
->
{};
MiraiEventManager
.
getInstance
().
hookAlways
(
this
);
}
public
void
mountOnce
(){
if
(
this
.
handler
==
null
)
this
.
handler
=
a
->
{};
MiraiEventManager
.
getInstance
().
hookOnce
(
this
);
}
@Override
public
void
close
(){
this
.
handler
=
null
;
this
.
validChecker
=
null
;
}
}
mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEventHookKt.kt
deleted
100644 → 0
View file @
ffdb7c03
package
net.mamoe.mirai.event
import
kotlinx.coroutines.runBlocking
import
java.util.function.Consumer
import
java.util.function.Predicate
/**
* @author Him188moe
*/
class
MiraiEventHookKt
<
E
:
MiraiEvent
>(
eventClass
:
Class
<
E
>)
:
MiraiEventHook
<
E
>(
eventClass
)
{
fun
onEvent
(
handler
:
suspend
(
E
)
->
Unit
)
{
this
@MiraiEventHookKt
.
handler
=
Consumer
{
runBlocking
{
handler
(
it
)
}
}
}
fun
validChecker
(
predicate
:
suspend
(
E
)
->
Boolean
)
{
//todo 把 mirai event 变为 suspend, 而不是在这里 run blocking
this
@MiraiEventHookKt
.
validChecker
=
Predicate
{
runBlocking
{
predicate
(
it
)
}
}
}
}
/**
* Kotlin 风格回调
* 你的代码可以这样(并且 validChecker 是可选的):
*
* event.hook {
* onEvent {}
* validChecker {}
* }
*/
fun
<
E
:
MiraiEvent
>
E
.
hook
(
handler
:
MiraiEventHookKt
<
E
>.()
->
Unit
):
MiraiEventHookKt
<
E
>
{
return
MiraiEventHookKt
(
this
.
javaClass
).
apply
(
handler
)
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEventKt.kt
deleted
100644 → 0
View file @
ffdb7c03
@
file
:
JvmName
(
"MiraiEventKt"
)
package
net.mamoe.mirai.event
fun
<
E
:
MiraiEvent
>
E
.
broadcastSmart
():
E
{
MiraiEventManager
.
getInstance
().
broadcastEvent
(
this
as
MiraiEvent
)
return
this
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEventManager.java
deleted
100644 → 0
View file @
ffdb7c03
package
net.mamoe.mirai.event
;
import
java.util.*
;
import
java.util.concurrent.CompletableFuture
;
import
java.util.concurrent.locks.ReentrantReadWriteLock
;
import
java.util.function.Consumer
;
import
java.util.function.Predicate
;
import
java.util.stream.Collectors
;
/**
* 线程安全的事件管理器.
*
* @author NaturalHG
* @see MiraiEventManagerKt 若你使用 kotlin, 请查看针对 kotlin 的优化实现
*/
public
class
MiraiEventManager
{
MiraiEventManager
()
{
}
public
static
MiraiEventManager
getInstance
()
{
return
EventManager
.
INSTANCE
;
//实例来自 kotlin 的 singleton
}
private
final
ReentrantReadWriteLock
hooksLock
=
new
ReentrantReadWriteLock
();
private
Map
<
Class
<?
extends
MiraiEvent
>,
List
<
MiraiEventHook
<?
extends
MiraiEvent
>>>
hooks
=
new
HashMap
<>();
public
<
D
extends
MiraiEvent
>
void
hookUntil
(
MiraiEventHook
<
D
>
hook
,
Predicate
<
D
>
toRemove
)
{
this
.
mountHook
(
hook
.
setValidUntil
(
toRemove
));
}
public
<
D
extends
MiraiEvent
>
void
hookWhile
(
MiraiEventHook
<
D
>
hook
,
Predicate
<
D
>
toKeep
)
{
this
.
mountHook
(
hook
.
setValidWhile
(
toKeep
));
}
public
<
D
extends
MiraiEvent
>
void
hookAlways
(
MiraiEventHook
<
D
>
hook
)
{
this
.
hookUntil
(
hook
,
(
a
)
->
false
);
}
public
<
D
extends
MiraiEvent
>
void
hookOnce
(
MiraiEventHook
<
D
>
hook
)
{
this
.
hookUntil
(
hook
,
(
a
)
->
true
);
}
public
<
D
extends
MiraiEvent
>
void
registerHook
(
MiraiEventHook
<
D
>
hook
)
{
this
.
mountHook
(
hook
);
}
private
<
D
extends
MiraiEvent
>
void
mountHook
(
MiraiEventHook
<
D
>
hook
)
{
if
(!
hook
.
isMount
())
{
hook
.
setMount
(
true
);
hooksLock
.
writeLock
().
lock
();
try
{
if
(!
hooks
.
containsKey
(
hook
.
getEventClass
()))
{
hooks
.
put
(
hook
.
getEventClass
(),
new
LinkedList
<>()
{{
add
(
hook
);
}});
}
else
{
hooks
.
get
(
hook
.
getEventClass
()).
add
(
hook
);
}
}
finally
{
hooksLock
.
writeLock
().
unlock
();
}
}
}
/**
* 不推荐onEvent
* 由于不能保证Hook的原子性 非线程安全
* 不能保证下一个 D event发生时handler就位
*
* @author NaturalHG Aug27
* use {@link MiraiEventHook::onEvent()} to replace
*/
@Deprecated
public
<
D
extends
MiraiEvent
>
MiraiEventHook
<
D
>
onEvent
(
Class
<
D
>
event
)
{
MiraiEventHook
<
D
>
hook
=
new
MiraiEventHook
<>(
event
);
this
.
registerHook
(
hook
);
return
hook
;
}
@Deprecated
public
<
D
extends
MiraiEvent
>
MiraiEventHook
<
D
>
onEventOnce
(
Class
<
D
>
event
)
{
MiraiEventHook
<
D
>
hook
=
new
MiraiEventHook
<>(
event
);
this
.
hookOnce
(
hook
);
return
hook
;
}
@Deprecated
public
<
D
extends
MiraiEvent
>
MiraiEventHook
<
D
>
onEventUntil
(
Class
<
D
>
event
,
Predicate
<
D
>
toRemove
)
{
MiraiEventHook
<
D
>
hook
=
new
MiraiEventHook
<>(
event
);
this
.
hookUntil
(
hook
,
toRemove
);
return
hook
;
}
@Deprecated
public
<
D
extends
MiraiEvent
>
MiraiEventHook
<
D
>
onEventWhile
(
Class
<
D
>
event
,
Predicate
<
D
>
toKeep
)
{
MiraiEventHook
<
D
>
hook
=
new
MiraiEventHook
<>(
event
);
this
.
hookWhile
(
hook
,
toKeep
);
return
hook
;
}
public
void
broadcastEvent
(
MiraiEvent
event
)
{
hooksLock
.
readLock
().
lock
();
try
{
if
(
hooks
.
containsKey
(
event
.
getClass
()))
{
hooks
.
put
(
event
.
getClass
(),
hooks
.
get
(
event
.
getClass
())
.
stream
()
.
sorted
(
Comparator
.
comparingInt
(
MiraiEventHook:
:
getPriority
))
.
filter
(
a
->
!
a
.
accept
(
event
))
.
collect
(
Collectors
.
toList
())
);
}
}
finally
{
hooksLock
.
readLock
().
unlock
();
}
}
public
<
E
extends
AsyncEvent
>
CompletableFuture
<
E
>
broadcastEventAsync
(
E
event
)
{
Objects
.
requireNonNull
(
event
);
if
(!(
event
instanceof
MiraiEvent
))
{
throw
new
IllegalArgumentException
(
"event must be instanceof MiraiEvent"
);
}
CompletableFuture
<
E
>
future
=
new
CompletableFuture
<>();
future
.
completeAsync
(()
->
{
MiraiEventManager
.
this
.
broadcastEvent
((
MiraiEvent
)
event
);
return
event
;
});
return
future
;
}
public
<
E
extends
AsyncEvent
>
CompletableFuture
<
E
>
broadcastEventAsync
(
E
event
,
Consumer
<
E
>
callback
)
{
Objects
.
requireNonNull
(
event
);
Objects
.
requireNonNull
(
callback
);
if
(!(
event
instanceof
MiraiEvent
))
{
throw
new
IllegalArgumentException
(
"event must be instanceof MiraiEvent"
);
}
CompletableFuture
<
E
>
future
=
new
CompletableFuture
<>();
future
.
whenComplete
((
a
,
b
)
->
callback
.
accept
(
event
));
future
.
completeAsync
(()
->
{
MiraiEventManager
.
this
.
broadcastEvent
((
MiraiEvent
)
event
);
return
event
;
});
return
future
;
}
public
<
D
extends
AsyncEvent
>
CompletableFuture
<
D
>
broadcastEventAsync
(
D
event
,
Runnable
callback
)
{
return
broadcastEventAsync
(
event
,
t
->
callback
.
run
());
}
}
mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEventManagerKt.kt
deleted
100644 → 0
View file @
ffdb7c03
@
file
:
JvmName
(
"MiraiEventManagerKt"
)
package
net.mamoe.mirai.event
import
kotlinx.coroutines.runBlocking
import
net.mamoe.mirai.Bot
import
kotlin.reflect.KClass
/**
* [MiraiEventManager] 的 kotlin 简易化实现.
* 若要 hook 一个事件, 你可以:
* FriendMessageEvent::class.hookOnce {}
* FriendMessageEvent::class.hookAlways {}
*
* @author Him188moe
*/
object
EventManager
:
MiraiEventManager
()
/**
* 每次事件触发时都会调用 hook
*/
fun
<
C
:
Class
<
E
>,
E
:
MiraiEvent
>
C
.
hookAlways
(
bot
:
Bot
?
=
null
,
hook
:
suspend
(
E
)
->
Unit
)
{
MiraiEventManager
.
getInstance
().
hookAlways
(
MiraiEventHook
<
E
>(
this
)
{
runBlocking
{
hook
(
it
)
}
})
}
/**
* 当下一次事件触发时调用 hook
*/
fun
<
C
:
Class
<
E
>,
E
:
MiraiEvent
>
C
.
hookOnce
(
bot
:
Bot
?
=
null
,
hook
:
suspend
(
E
)
->
Unit
)
{
//todo bot 限制 实现. 或重写 hook
MiraiEventManager
.
getInstance
().
hookOnce
(
MiraiEventHook
<
E
>(
this
)
{
runBlocking
{
hook
(
it
)
}
})
}
/**
* 每次事件触发时都会调用 hook, 直到 hook 返回 false 时停止 hook
*/
fun
<
C
:
Class
<
E
>,
E
:
MiraiEvent
>
C
.
hookWhile
(
bot
:
Bot
?
=
null
,
hook
:
suspend
(
E
)
->
Boolean
)
{
MiraiEventManager
.
getInstance
().
hookAlways
(
MiraiEventHookSimple
(
this
,
hook
))
}
/**
* 每次事件触发时都会调用 hook
*
* @param bot 指定仅限于某个 [Bot] 的事件.
*/
fun
<
C
:
KClass
<
E
>,
E
:
MiraiEvent
>
C
.
hookAlways
(
bot
:
Bot
?
=
null
,
hook
:
suspend
(
E
)
->
Unit
)
{
this
.
java
.
hookAlways
(
bot
,
hook
)
}
/**
* 当下一次事件触发时调用 hook
*/
fun
<
C
:
KClass
<
E
>,
E
:
MiraiEvent
>
C
.
hookOnce
(
bot
:
Bot
?
=
null
,
hook
:
suspend
(
E
)
->
Unit
)
{
this
.
java
.
hookOnce
(
bot
,
hook
)
}
/**
* 每次事件触发时都会调用 hook, 直到 hook 返回 false 时停止 hook
*/
fun
<
C
:
KClass
<
E
>,
E
:
MiraiEvent
>
C
.
hookWhile
(
bot
:
Bot
?
=
null
,
hook
:
suspend
(
E
)
->
Boolean
)
{
this
.
java
.
hookWhile
(
bot
,
hook
)
}
private
class
MiraiEventHookSimple
<
E
:
MiraiEvent
>(
clazz
:
Class
<
E
>,
val
hook
:
suspend
(
E
)
->
Boolean
)
:
MiraiEventHook
<
E
>(
clazz
)
{
override
fun
accept
(
event
:
MiraiEvent
?):
Boolean
{
@Suppress
(
"UNCHECKED_CAST"
)
return
runBlocking
{
return
@
runBlocking
!
hook
.
invoke
(
event
as
E
)
}
}
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/event/Subscribers.kt
0 → 100644
View file @
126b2210
package
net.mamoe.mirai.event
import
net.mamoe.mirai.event.internal.Handler
import
net.mamoe.mirai.event.internal.listeners
import
net.mamoe.mirai.event.internal.subscribeInternal
import
kotlin.reflect.KClass
enum
class
ListeningStatus
{
LISTENING
,
STOPPED
}
@Synchronized
fun
<
E
:
Event
>
KClass
<
E
>.
subscribe
(
handler
:
suspend
(
E
)
->
ListeningStatus
)
=
this
.
listeners
.
add
(
Handler
(
handler
))
fun
<
E
:
Event
>
KClass
<
E
>.
subscribeAlways
(
listener
:
suspend
(
E
)
->
Unit
)
=
this
.
subscribeInternal
(
Handler
{
listener
(
it
);
ListeningStatus
.
LISTENING
})
fun
<
E
:
Event
>
KClass
<
E
>.
subscribeOnce
(
listener
:
suspend
(
E
)
->
Unit
)
=
this
.
subscribeInternal
(
Handler
{
listener
(
it
);
ListeningStatus
.
STOPPED
})
fun
<
E
:
Event
,
T
>
KClass
<
E
>.
subscribeUntil
(
valueIfStop
:
T
,
block
:
suspend
(
E
)
->
T
)
=
subscribeInternal
(
Handler
{
if
(
block
(
it
)
===
valueIfStop
)
ListeningStatus
.
STOPPED
else
ListeningStatus
.
LISTENING
})
fun
<
E
:
Event
>
KClass
<
E
>.
subscribeUntilFalse
(
block
:
suspend
(
E
)
->
Boolean
)
=
subscribeUntil
(
false
,
block
)
fun
<
E
:
Event
>
KClass
<
E
>.
subscribeUntilTrue
(
block
:
suspend
(
E
)
->
Boolean
)
=
subscribeUntil
(
true
,
block
)
fun
<
E
:
Event
>
KClass
<
E
>.
subscribeUntilNull
(
block
:
suspend
(
E
)
->
Any
?)
=
subscribeUntil
(
null
,
block
)
fun
<
E
:
Event
,
T
>
KClass
<
E
>.
subscribeWhile
(
valueIfContinue
:
T
,
block
:
suspend
(
E
)
->
T
)
=
subscribeInternal
(
Handler
{
if
(
block
(
it
)
!==
valueIfContinue
)
ListeningStatus
.
STOPPED
else
ListeningStatus
.
LISTENING
})
fun
<
E
:
Event
>
KClass
<
E
>.
subscribeWhileFalse
(
block
:
suspend
(
E
)
->
Boolean
)
=
subscribeWhile
(
false
,
block
)
fun
<
E
:
Event
>
KClass
<
E
>.
subscribeWhileTrue
(
block
:
suspend
(
E
)
->
Boolean
)
=
subscribeWhile
(
true
,
block
)
fun
<
E
:
Event
>
KClass
<
E
>.
subscribeWhileNull
(
block
:
suspend
(
E
)
->
Any
?)
=
subscribeWhile
(
null
,
block
)
/**
* 监听一个事件. 可同时进行多种方式的监听
* @see ListenerBuilder
*/
fun
<
E
:
Event
>
KClass
<
E
>.
subscribeAll
(
listeners
:
ListenerBuilder
<
E
>.()
->
Unit
)
{
ListenerBuilder
<
E
>
{
this
.
subscribeInternal
(
it
)
}.
apply
(
listeners
)
}
/**
* 监听构建器. 可同时进行多种方式的监听
*
* ```kotlin
* FriendMessageEvent.subscribe {
* always{
* it.reply("永远发生")
* }
*
* untilFalse {
* it.reply("你发送了 ${it.message}")
* it.message eq "停止"
* }
* }
* ```
*/
@Suppress
(
"MemberVisibilityCanBePrivate"
,
"unused"
)
inline
class
ListenerBuilder
<
out
E
:
Event
>(
private
val
handlerConsumer
:
(
Handler
<
in
E
>)
->
Unit
)
{
fun
handler
(
block
:
suspend
(
E
)
->
ListeningStatus
)
{
handlerConsumer
(
Handler
(
block
))
}
fun
always
(
block
:
suspend
(
E
)
->
Unit
)
=
handler
{
block
(
it
);
ListeningStatus
.
LISTENING
}
fun
<
T
>
until
(
until
:
T
,
block
:
suspend
(
E
)
->
T
)
=
handler
{
if
(
block
(
it
)
===
until
)
ListeningStatus
.
STOPPED
else
ListeningStatus
.
LISTENING
}
fun
untilFalse
(
block
:
suspend
(
E
)
->
Boolean
)
=
until
(
false
,
block
)
fun
untilTrue
(
block
:
suspend
(
E
)
->
Boolean
)
=
until
(
true
,
block
)
fun
untilNull
(
block
:
suspend
(
E
)
->
Any
?)
=
until
(
null
,
block
)
fun
<
T
>
`while`
(
until
:
T
,
block
:
suspend
(
E
)
->
T
)
=
handler
{
if
(
block
(
it
)
!==
until
)
ListeningStatus
.
STOPPED
else
ListeningStatus
.
LISTENING
}
fun
whileFalse
(
block
:
suspend
(
E
)
->
Boolean
)
=
`while`
(
false
,
block
)
fun
whileTrue
(
block
:
suspend
(
E
)
->
Boolean
)
=
`while`
(
true
,
block
)
fun
whileNull
(
block
:
suspend
(
E
)
->
Any
?)
=
`while`
(
null
,
block
)
fun
once
(
block
:
suspend
(
E
)
->
Unit
)
=
handler
{
block
(
it
);
ListeningStatus
.
STOPPED
}
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/event/events/bot/BotEvent.kt
View file @
126b2210
package
net.mamoe.mirai.event.events.bot
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.event.MiraiEvent
import
net.mamoe.mirai.event.Event
import
kotlin.reflect.KClass
/**
* @author Him188moe
*/
abstract
class
BotEvent
(
val
bot
:
Bot
)
:
Mirai
Event
()
abstract
class
BotEvent
(
val
bot
:
Bot
)
:
Event
()
class
BotLoginSucceedEvent
(
bot
:
Bot
)
:
BotEvent
(
bot
)
\ No newline at end of file
class
BotLoginSucceedEvent
(
bot
:
Bot
)
:
BotEvent
(
bot
)
{
companion
object
:
KClass
<
BotLoginSucceedEvent
>
by
BotLoginSucceedEvent
::
class
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/event/events/group/GroupMessageEvent.kt
View file @
126b2210
...
...
@@ -5,11 +5,13 @@ import net.mamoe.mirai.contact.Group
import
net.mamoe.mirai.contact.QQ
import
net.mamoe.mirai.message.Message
import
net.mamoe.mirai.message.defaults.MessageChain
import
kotlin.reflect.KClass
/**
* @author Him188moe
*/
class
GroupMessageEvent
(
bot
:
Bot
,
group
:
Group
,
val
sender
:
QQ
,
val
message
:
MessageChain
)
:
GroupEvent
(
bot
,
group
)
{
companion
object
:
KClass
<
GroupMessageEvent
>
by
GroupMessageEvent
::
class
@
JvmSynthetic
suspend
inline
fun
reply
(
message
:
Message
)
=
group
.
sendMessage
(
message
)
...
...
mirai-core/src/main/java/net/mamoe/mirai/event/events/network/ClientPacketEvents.kt
View file @
126b2210
package
net.mamoe.mirai.event.events.network
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.event.Cancellable
import
net.mamoe.mirai.network.protocol.tim.packet.ClientPacket
import
kotlin.reflect.KClass
abstract
class
ClientPacketEvent
<
out
P
:
ClientPacket
>(
bot
:
Bot
,
packet
:
P
)
:
PacketEvent
<
P
>(
bot
,
packet
)
class
PacketSentEvent
(
bot
:
Bot
,
packet
:
ClientPacket
)
:
ClientPacketEvent
<
ClientPacket
>(
bot
,
packet
)
/**
* 包已发送. 不可被取消
*/
class
PacketSentEvent
<
P
:
ClientPacket
>(
bot
:
Bot
,
packet
:
P
)
:
ClientPacketEvent
<
P
>(
bot
,
packet
)
{
companion
object
:
KClass
<
PacketSentEvent
<
*
>>
by
PacketSentEvent
::
class
}
class
BeforePacketSendEvent
(
bot
:
Bot
,
packet
:
ClientPacket
)
:
ClientPacketEvent
<
ClientPacket
>(
bot
,
packet
)
\ No newline at end of file
/**
* 包发送前. 可被取消
*/
class
BeforePacketSendEvent
<
P
:
ClientPacket
>(
bot
:
Bot
,
packet
:
P
)
:
ClientPacketEvent
<
P
>(
bot
,
packet
),
Cancellable
{
companion
object
:
KClass
<
BeforePacketSendEvent
<
*
>>
by
BeforePacketSendEvent
::
class
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/event/events/network/ServerPacketEvents.kt
View file @
126b2210
...
...
@@ -2,8 +2,11 @@ package net.mamoe.mirai.event.events.network
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.network.protocol.tim.packet.ServerPacket
import
kotlin.reflect.KClass
abstract
class
ServerPacketEvent
<
out
P
:
ServerPacket
>(
bot
:
Bot
,
packet
:
P
)
:
PacketEvent
<
P
>(
bot
,
packet
)
class
ServerPacketReceivedEvent
(
bot
:
Bot
,
packet
:
ServerPacket
)
:
ServerPacketEvent
<
ServerPacket
>(
bot
,
packet
)
\ No newline at end of file
class
ServerPacketReceivedEvent
(
bot
:
Bot
,
packet
:
ServerPacket
)
:
ServerPacketEvent
<
ServerPacket
>(
bot
,
packet
)
{
companion
object
:
KClass
<
ServerPacketReceivedEvent
>
by
ServerPacketReceivedEvent
::
class
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/event/events/qq/FriendMessageEvent.java
deleted
100644 → 0
View file @
ffdb7c03
package
net.mamoe.mirai.event.events.qq
;
/**
* @author Him188moe
*/
mirai-core/src/main/java/net/mamoe/mirai/event/events/qq/FriendMessageEvent.kt
View file @
126b2210
...
...
@@ -4,11 +4,15 @@ import net.mamoe.mirai.Bot
import
net.mamoe.mirai.contact.QQ
import
net.mamoe.mirai.message.Message
import
net.mamoe.mirai.message.defaults.MessageChain
import
kotlin.reflect.KClass
/**
* 接受好友消息事件
*
* @author Him188moe
*/
class
FriendMessageEvent
(
bot
:
Bot
,
sender
:
QQ
,
val
message
:
MessageChain
)
:
FriendEvent
(
bot
,
sender
)
{
companion
object
:
KClass
<
FriendMessageEvent
>
by
FriendMessageEvent
::
class
@
JvmSynthetic
suspend
inline
fun
reply
(
message
:
Message
)
=
sender
.
sendMessage
(
message
)
...
...
@@ -20,5 +24,5 @@ class FriendMessageEvent(bot: Bot, sender: QQ, val message: MessageChain) : Frie
suspend
inline
fun
reply
(
message
:
List
<
Message
>)
=
sender
.
sendMessage
(
message
)
@JvmSynthetic
suspend
inline
fun
reply
(
message
:
MessageChain
)
=
sender
.
sendMessage
(
message
)
suspend
inline
fun
reply
(
message
:
MessageChain
)
=
sender
.
sendMessage
(
message
)
//shortcut
}
mirai-core/src/main/java/net/mamoe/mirai/event/events/server/ServerDisabledEvent.java
deleted
100644 → 0
View file @
ffdb7c03
package
net.mamoe.mirai.event.events.server
;
import
net.mamoe.mirai.event.AsyncEvent
;
import
net.mamoe.mirai.event.MiraiEvent
;
public
final
class
ServerDisabledEvent
extends
MiraiEvent
implements
AsyncEvent
{
}
mirai-core/src/main/java/net/mamoe/mirai/event/events/server/ServerEnabledEvent.java
deleted
100644 → 0
View file @
ffdb7c03
package
net.mamoe.mirai.event.events.server
;
import
net.mamoe.mirai.event.AsyncEvent
;
import
net.mamoe.mirai.event.MiraiEvent
;
public
final
class
ServerEnabledEvent
extends
MiraiEvent
implements
AsyncEvent
{
}
mirai-core/src/main/java/net/mamoe/mirai/event/internal/InternalEventListenres.kt
0 → 100644
View file @
126b2210
package
net.mamoe.mirai.event.internal
import
net.mamoe.mirai.event.Event
import
net.mamoe.mirai.event.ListeningStatus
import
kotlin.reflect.KClass
import
kotlin.reflect.full.allSuperclasses
/**
* 监听和广播实现
*
* @author Him188moe
*/
internal
fun
<
E
:
Event
>
KClass
<
E
>.
subscribeInternal
(
listener
:
Listener
<
E
>)
=
this
.
listeners
.
add
(
listener
)
/**
* 事件监听器
*
* @author Him188moe
*/
internal
interface
Listener
<
in
E
:
Event
>
{
suspend
fun
onEvent
(
event
:
E
):
ListeningStatus
}
/**
* Lambda 监听器.
* 不推荐直接使用该类
*/
class
Handler
<
E
:
Event
>(
val
handler
:
suspend
(
E
)
->
ListeningStatus
)
:
Listener
<
E
>
{
override
suspend
fun
onEvent
(
event
:
E
):
ListeningStatus
=
handler
.
invoke
(
event
)
}
internal
val
<
E
:
Event
>
KClass
<
E
>.
listeners
:
EventListeners
<
E
>
get
()
=
EventListenerManger
.
get
(
this
)
internal
class
EventListeners
<
E
:
Event
>
:
MutableList
<
Listener
<
E
>>
by
mutableListOf
()
internal
object
EventListenerManger
{
private
val
REGISTRIES
:
MutableMap
<
KClass
<
out
Event
>,
EventListeners
<
out
Event
>>
=
mutableMapOf
()
@Suppress
(
"UNCHECKED_CAST"
)
internal
fun
<
E
:
Event
>
get
(
clazz
:
KClass
<
E
>):
EventListeners
<
E
>
{
synchronized
(
clazz
)
{
if
(
REGISTRIES
.
containsKey
(
clazz
))
{
return
REGISTRIES
[
clazz
]
as
EventListeners
<
E
>
}
else
{
EventListeners
<
E
>().
let
{
REGISTRIES
[
clazz
]
=
it
return
it
}
}
}
}
}
@Suppress
(
"UNCHECKED_CAST"
)
internal
suspend
fun
<
E
:
Event
>
E
.
broadcastInternal
():
E
{
suspend
fun
callListeners
(
listeners
:
EventListeners
<
in
E
>)
{
val
iterator
=
listeners
.
iterator
()
while
(
iterator
.
hasNext
())
{
if
(
iterator
.
next
().
onEvent
(
this
)
==
ListeningStatus
.
STOPPED
)
{
iterator
.
remove
()
}
}
}
callListeners
(
this
::
class
.
listeners
as
EventListeners
<
E
>)
this
::
class
.
allSuperclasses
.
forEach
{
//println("super: " + it.simpleName)
if
(
Event
::
class
.
java
.
isAssignableFrom
(
it
.
java
))
{
callListeners
((
it
as
KClass
<
out
Event
>).
listeners
as
EventListeners
<
in
E
>)
}
}
return
this
}
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/network/BotNetworkHandler.kt
View file @
126b2210
package
net.mamoe.mirai.network
import
kotlinx.coroutines.CompletableDeferred
import
net.mamoe.mirai.network.protocol.tim.TIMBotNetworkHandler.BotSocket
import
net.mamoe.mirai.network.protocol.tim.TIMBotNetworkHandler.Login
import
net.mamoe.mirai.network.protocol.tim.handler.ActionPacketHandler
...
...
@@ -12,7 +13,6 @@ import net.mamoe.mirai.network.protocol.tim.packet.ServerEventPacket
import
net.mamoe.mirai.network.protocol.tim.packet.ServerPacket
import
net.mamoe.mirai.network.protocol.tim.packet.login.LoginState
import
java.io.Closeable
import
java.util.concurrent.CompletableFuture
/**
* Mirai 的网络处理器, 它承担所有数据包([Packet])的处理任务.
...
...
@@ -54,7 +54,7 @@ interface BotNetworkHandler : Closeable {
*/
val
action
:
ActionPacketHandler
fun
tryLogin
(
touchingTimeoutMillis
:
Long
=
200
):
Completable
Future
<
LoginState
>
fun
tryLogin
(
touchingTimeoutMillis
:
Long
=
200
):
Completable
Deferred
<
LoginState
>
/**
* 添加一个临时包处理器
...
...
mirai-core/src/main/java/net/mamoe/mirai/network/protocol/tim/TIMBotNetworkHandler.kt
View file @
126b2210
...
...
@@ -2,6 +2,7 @@ package net.mamoe.mirai.network.protocol.tim
import
kotlinx.coroutines.*
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.event.broadcast
import
net.mamoe.mirai.event.events.bot.BotLoginSucceedEvent
import
net.mamoe.mirai.event.events.network.BeforePacketSendEvent
import
net.mamoe.mirai.event.events.network.PacketSentEvent
...
...
@@ -58,9 +59,9 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler {
*
* @param touchingTimeoutMillis 连接每个服务器的 timeout
*/
override
fun
tryLogin
(
touchingTimeoutMillis
:
Long
):
Completable
Future
<
LoginState
>
{
override
fun
tryLogin
(
touchingTimeoutMillis
:
Long
):
Completable
Deferred
<
LoginState
>
{
val
ipQueue
:
LinkedList
<
String
>
=
LinkedList
(
TIMProtocol
.
SERVER_IP
)
val
future
=
Completable
Future
<
LoginState
>()
val
future
=
Completable
Deferred
<
LoginState
>()
fun
login
()
{
this
.
socket
.
close
()
...
...
@@ -133,7 +134,7 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler {
}
}
if
(
ServerPacketReceivedEvent
(
bot
,
packet
).
broadcast
().
isC
ancelled
)
{
if
(
ServerPacketReceivedEvent
(
bot
,
packet
).
broadcast
().
c
ancelled
)
{
return
}
...
...
@@ -222,7 +223,7 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler {
try
{
packet
.
encodePacket
()
if
(
BeforePacketSendEvent
(
bot
,
packet
).
broadcast
().
isC
ancelled
)
{
if
(
BeforePacketSendEvent
(
bot
,
packet
).
broadcast
().
c
ancelled
)
{
return
}
...
...
@@ -263,7 +264,7 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler {
private
lateinit
var
token0825
:
ByteArray
//56
private
var
loginTime
:
Int
=
0
private
lateinit
var
loginIP
:
String
private
var
random
Tgtgt
Key
:
ByteArray
=
getRandomByteArray
(
16
)
private
var
random
private
Key
:
ByteArray
=
getRandomByteArray
(
16
)
/**
* 0828_decr_key
...
...
@@ -288,7 +289,7 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler {
this
.
loginTime
=
packet
.
loginTime
this
.
token0825
=
packet
.
token0825
println
(
"token0825="
+
this
.
token0825
.
toUHexString
())
socket
.
sendPacket
(
ClientPasswordSubmissionPacket
(
bot
.
account
.
qqNumber
,
bot
.
account
.
password
,
packet
.
loginTime
,
packet
.
loginIP
,
this
.
random
Tgtgt
Key
,
packet
.
token0825
))
socket
.
sendPacket
(
ClientPasswordSubmissionPacket
(
bot
.
account
.
qqNumber
,
bot
.
account
.
password
,
packet
.
loginTime
,
packet
.
loginIP
,
this
.
random
private
Key
,
packet
.
token0825
))
}
}
...
...
@@ -299,9 +300,9 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler {
}
is
ServerCaptchaCorrectPacket
->
{
this
.
random
Tgtgt
Key
=
getRandomByteArray
(
16
)
this
.
random
private
Key
=
getRandomByteArray
(
16
)
this
.
token00BA
=
packet
.
token00BA
socket
.
sendPacket
(
ClientLoginResendPacket3105
(
bot
.
account
.
qqNumber
,
bot
.
account
.
password
,
this
.
loginTime
,
this
.
loginIP
,
this
.
random
Tgtgt
Key
,
this
.
token0825
,
this
.
token00BA
))
socket
.
sendPacket
(
ClientLoginResendPacket3105
(
bot
.
account
.
qqNumber
,
bot
.
account
.
password
,
this
.
loginTime
,
this
.
loginIP
,
this
.
random
private
Key
,
this
.
token0825
,
this
.
token00BA
))
}
is
ServerLoginResponseVerificationCodeInitPacket
->
{
...
...
@@ -309,7 +310,7 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler {
this
.
token00BA
=
packet
.
token00BA
this
.
captchaCache
=
packet
.
verifyCodePart1
if
(
packet
.
unknownBoolean
!=
null
&&
packet
.
unknownBoolean
!!
)
{
if
(
packet
.
unknownBoolean
==
true
)
{
this
.
captchaSectionId
=
1
socket
.
sendPacket
(
ClientVerificationCodeTransmissionRequestPacket
(
1
,
bot
.
account
.
qqNumber
,
this
.
token0825
,
this
.
captchaSectionId
++,
this
.
token00BA
))
}
...
...
@@ -326,6 +327,7 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler {
this
.
token00BA
=
packet
.
token00BA
if
(
packet
.
transmissionCompleted
)
{
//todo 验证码多样化处理
withContext
(
Dispatchers
.
IO
)
{
bot
.
notice
(
CharImageUtil
.
createCharImg
(
ImageIO
.
read
(
captchaCache
!!
.
inputStream
())))
}
...
...
@@ -363,11 +365,11 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler {
//println("token00BA changed!!! to " + token00BA.toUByteArray())
//}
if
(
packet
.
flag
==
ServerLoginResponseKeyExchangePacket
.
Flag
.
`
08
36
31
03
`
)
{
this
.
random
TgtgtKey
=
packet
.
tgtgt
Key
socket
.
sendPacket
(
ClientLoginResendPacket3104
(
bot
.
account
.
qqNumber
,
bot
.
account
.
password
,
loginTime
,
loginIP
,
random
Tgtgt
Key
,
token0825
,
packet
.
tokenUnknown
this
.
random
privateKey
=
packet
.
private
Key
socket
.
sendPacket
(
ClientLoginResendPacket3104
(
bot
.
account
.
qqNumber
,
bot
.
account
.
password
,
loginTime
,
loginIP
,
random
private
Key
,
token0825
,
packet
.
tokenUnknown
?:
this
.
token00BA
,
packet
.
tlv0006
))
}
else
{
socket
.
sendPacket
(
ClientLoginResendPacket3106
(
bot
.
account
.
qqNumber
,
bot
.
account
.
password
,
loginTime
,
loginIP
,
random
Tgtgt
Key
,
token0825
,
packet
.
tokenUnknown
socket
.
sendPacket
(
ClientLoginResendPacket3106
(
bot
.
account
.
qqNumber
,
bot
.
account
.
password
,
loginTime
,
loginIP
,
random
private
Key
,
token0825
,
packet
.
tokenUnknown
?:
token00BA
,
packet
.
tlv0006
))
}
}
...
...
@@ -389,7 +391,7 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler {
BotLoginSucceedEvent
(
bot
).
broadcast
()
//登录成功后会收到大量上次的消息, 忽略掉 todo 优化
Global
Scope
.
launch
{
Network
Scope
.
launch
{
delay
(
3000
)
message
.
ignoreMessage
=
false
}
...
...
@@ -401,8 +403,8 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler {
is
ServerCatchaPacket
.
Encrypted
->
socket
.
distributePacket
(
packet
.
decrypt
())
is
ServerLoginResponseVerificationCodeInitPacket
.
Encrypted
->
socket
.
distributePacket
(
packet
.
decrypt
())
is
ServerLoginResponseKeyExchangePacket
.
Encrypted
->
socket
.
distributePacket
(
packet
.
decrypt
(
this
.
random
Tgtgt
Key
))
is
ServerLoginResponseSuccessPacket
.
Encrypted
->
socket
.
distributePacket
(
packet
.
decrypt
(
this
.
random
Tgtgt
Key
))
is
ServerLoginResponseKeyExchangePacket
.
Encrypted
->
socket
.
distributePacket
(
packet
.
decrypt
(
this
.
random
private
Key
))
is
ServerLoginResponseSuccessPacket
.
Encrypted
->
socket
.
distributePacket
(
packet
.
decrypt
(
this
.
random
private
Key
))
is
ServerSessionKeyResponsePacket
.
Encrypted
->
socket
.
distributePacket
(
packet
.
decrypt
(
this
.
sessionResponseDecryptionKey
))
is
ServerTouchResponsePacket
.
Encrypted
->
socket
.
distributePacket
(
packet
.
decrypt
())
...
...
@@ -417,10 +419,8 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler {
}
}
fun
changeOnlineStatus
(
status
:
ClientLoginStatus
)
{
NetworkScope
.
launch
{
socket
.
sendPacket
(
ClientChangeOnlineStatusPacket
(
bot
.
account
.
qqNumber
,
sessionKey
,
status
))
}
suspend
fun
changeOnlineStatus
(
status
:
ClientLoginStatus
)
{
socket
.
sendPacket
(
ClientChangeOnlineStatusPacket
(
bot
.
account
.
qqNumber
,
sessionKey
,
status
))
}
override
fun
close
()
{
...
...
mirai-core/src/main/java/net/mamoe/mirai/network/protocol/tim/handler/MessagePacketHandler.kt
View file @
126b2210
...
...
@@ -2,6 +2,7 @@ package net.mamoe.mirai.network.protocol.tim.handler
import
net.mamoe.mirai.contact.Group
import
net.mamoe.mirai.contact.QQ
import
net.mamoe.mirai.event.broadcast
import
net.mamoe.mirai.event.events.group.GroupMessageEvent
import
net.mamoe.mirai.event.events.qq.FriendMessageEvent
import
net.mamoe.mirai.getGroupByNumber
...
...
mirai-core/src/main/java/net/mamoe/mirai/network/protocol/tim/packet/ClientPacket.kt
View file @
126b2210
...
...
@@ -121,7 +121,7 @@ fun DataOutputStream.encryptAndWrite(keyHex: String, encoder: (ByteArrayDataOutp
}
@Throws
(
IOException
::
class
)
fun
DataOutputStream
.
writeTLV0006
(
qq
:
Long
,
password
:
String
,
loginTime
:
Int
,
loginIP
:
String
,
tgtgt
Key
:
ByteArray
)
{
fun
DataOutputStream
.
writeTLV0006
(
qq
:
Long
,
password
:
String
,
loginTime
:
Int
,
loginIP
:
String
,
private
Key
:
ByteArray
)
{
val
firstMD5
=
md5
(
password
)
val
secondMD5
=
md5
(
firstMD5
+
"00 00 00 00"
.
hexToBytes
()
+
qq
.
toUInt
().
toByteArray
())
...
...
@@ -140,7 +140,7 @@ fun DataOutputStream.writeTLV0006(qq: Long, password: String, loginTime: Int, lo
it
.
writeZero
(
8
)
it
.
writeHex
(
"00 10"
)
//这两个hex是passwordSubmissionTLV2的末尾
it
.
writeHex
(
"15 74 C4 89 85 7A 19 F5 5E A9 C9 A3 5E 8A 5A 9B"
)
//16
it
.
write
(
tgtgt
Key
)
it
.
write
(
private
Key
)
}
}
...
...
mirai-core/src/main/java/net/mamoe/mirai/network/protocol/tim/packet/ServerPacket.kt
View file @
126b2210
...
...
@@ -4,7 +4,7 @@ package net.mamoe.mirai.network.protocol.tim.packet
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.event.events.network.ServerPacketReceivedEvent
import
net.mamoe.mirai.event.
hookWhil
e
import
net.mamoe.mirai.event.
subscribeWhileTru
e
import
net.mamoe.mirai.network.protocol.tim.packet.PacketNameFormatter.adjustName
import
net.mamoe.mirai.network.protocol.tim.packet.action.ServerCanAddFriendResponsePacket
import
net.mamoe.mirai.network.protocol.tim.packet.action.ServerSendFriendMessageResponsePacket
...
...
@@ -337,7 +337,7 @@ fun DataInputStream.gotoWhere(matcher: ByteArray): DataInputStream {
@Suppress
(
"UNCHECKED_CAST"
)
internal
fun
<
P
:
ServerPacket
>
Bot
.
waitForPacket
(
packetClass
:
KClass
<
P
>,
timeoutMillis
:
Long
=
Long
.
MAX_VALUE
,
timeout
:
()
->
Unit
=
{})
{
var
got
=
false
ServerPacketReceivedEvent
::
class
.
hookWhil
e
{
ServerPacketReceivedEvent
::
class
.
subscribeWhileTru
e
{
if
(
packetClass
.
isInstance
(
it
.
packet
)
&&
it
.
bot
===
this
)
{
got
=
true
true
...
...
mirai-core/src/main/java/net/mamoe/mirai/network/protocol/tim/packet/UnknownServerPacket.kt
View file @
126b2210
package
net.mamoe.mirai.network.protocol.tim.packet
import
net.mamoe.mirai.utils.LoggerTextFormat
import
net.mamoe.mirai.utils.MiraiLogger
import
net.mamoe.mirai.utils.toUHexString
import
java.io.DataInputStream
...
...
@@ -9,7 +10,7 @@ import java.io.DataInputStream
*/
class
UnknownServerPacket
(
input
:
DataInputStream
)
:
ServerPacket
(
input
)
{
override
fun
decode
()
{
println
(
"UnknownServerPacket data: "
+
this
.
input
.
goto
(
0
).
readAllBytes
().
toUHexString
())
MiraiLogger
.
debug
(
"UnknownServerPacket data: "
+
this
.
input
.
goto
(
0
).
readAllBytes
().
toUHexString
())
}
override
fun
toString
():
String
{
...
...
mirai-core/src/main/java/net/mamoe/mirai/network/protocol/tim/packet/action/AddContact.kt
View file @
126b2210
...
...
@@ -15,7 +15,6 @@ import java.util.*
* @author Him188moe
*/
@PacketId
(
"00 A7"
)
class
ClientCanAddFriendPacket
(
val
bot
:
Long
,
val
qq
:
Long
,
...
...
@@ -80,7 +79,6 @@ class ServerCanAddFriendResponsePacket(input: DataInputStream) : ServerPacket(in
* 请求添加好友
*/
@PacketId
(
"00 AE"
)
class
ClientAddFriendPacket
(
val
bot
:
Long
,
val
qq
:
Long
,
...
...
mirai-core/src/main/java/net/mamoe/mirai/network/protocol/tim/packet/action/ClientSendFriendMessagePacket.kt
View file @
126b2210
...
...
@@ -10,7 +10,6 @@ import java.io.DataInputStream
* @author Him188moe
*/
@PacketId
(
"00 CD"
)
class
ClientSendFriendMessagePacket
(
private
val
botQQ
:
Long
,
private
val
targetQQ
:
Long
,
...
...
mirai-core/src/main/java/net/mamoe/mirai/network/protocol/tim/packet/login/ClientLogin.kt
View file @
126b2210
...
...
@@ -19,7 +19,7 @@ class ClientPasswordSubmissionPacket(
private
val
password
:
String
,
private
val
loginTime
:
Int
,
private
val
loginIP
:
String
,
private
val
tgtgt
Key
:
ByteArray
,
//16 random by client
private
val
private
Key
:
ByteArray
,
//16 random by client
private
val
token0825
:
ByteArray
//56 from server
)
:
ClientPacket
()
{
...
...
@@ -34,37 +34,34 @@ class ClientPasswordSubmissionPacket(
this
.
writeHex
(
TIMProtocol
.
key0836
)
this
.
encryptAndWrite
(
TIMProtocol
.
shareKey
.
hexToBytes
())
{
it
.
writePart1
(
qq
,
password
,
loginTime
,
loginIP
,
tgtgt
Key
,
token0825
)
it
.
writePart1
(
qq
,
password
,
loginTime
,
loginIP
,
private
Key
,
token0825
)
it
.
writePart2
()
}
}
}
@PacketId
(
"08 36 31 04"
)
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
)
class
ClientLoginResendPacket3104
(
qq
:
Long
,
password
:
String
,
loginTime
:
Int
,
loginIP
:
String
,
privateKey
:
ByteArray
,
token0825
:
ByteArray
,
token00BA
:
ByteArray
,
tlv0006
:
ByteArray
?
=
null
)
:
ClientLoginResendPacket
(
qq
,
password
,
loginTime
,
loginIP
,
privateKey
,
token0825
,
token00BA
,
tlv0006
)
@PacketId
(
"08 36 31 05"
)
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
)
class
ClientLoginResendPacket3105
(
qq
:
Long
,
password
:
String
,
loginTime
:
Int
,
loginIP
:
String
,
privateKey
:
ByteArray
,
token0825
:
ByteArray
,
token00BA
:
ByteArray
)
:
ClientLoginResendPacket
(
qq
,
password
,
loginTime
,
loginIP
,
privateKey
,
token0825
,
token00BA
,
null
)
@PacketId
(
"08 36 31 06"
)
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
)
class
ClientLoginResendPacket3106
(
qq
:
Long
,
password
:
String
,
loginTime
:
Int
,
loginIP
:
String
,
privateKey
:
ByteArray
,
token0825
:
ByteArray
,
token00BA
:
ByteArray
,
tlv0006
:
ByteArray
?
=
null
)
:
ClientLoginResendPacket
(
qq
,
password
,
loginTime
,
loginIP
,
privateKey
,
token0825
,
token00BA
,
tlv0006
)
open
class
ClientLoginResendPacket
internal
constructor
(
val
qq
:
Long
,
val
password
:
String
,
val
loginTime
:
Int
,
val
loginIP
:
String
,
val
tgtgt
Key
:
ByteArray
,
val
token0825
:
ByteArray
,
val
token00BA
:
ByteArray
,
val
tlv0006
:
ByteArray
?
=
null
private
val
qq
:
Long
,
private
val
password
:
String
,
private
val
loginTime
:
Int
,
private
val
loginIP
:
String
,
private
val
private
Key
:
ByteArray
,
private
val
token0825
:
ByteArray
,
private
val
token00BA
:
ByteArray
,
private
val
tlv0006
:
ByteArray
?
=
null
)
:
ClientPacket
()
{
override
fun
encode
()
{
this
.
writeQQ
(
qq
)
...
...
@@ -77,7 +74,7 @@ open class ClientLoginResendPacket internal constructor(
this
.
writeHex
(
TIMProtocol
.
key0836
)
//16
this
.
encryptAndWrite
(
TIMProtocol
.
shareKey
.
hexToBytes
())
{
it
.
writePart1
(
qq
,
password
,
loginTime
,
loginIP
,
tgtgt
Key
,
token0825
,
tlv0006
)
it
.
writePart1
(
qq
,
password
,
loginTime
,
loginIP
,
private
Key
,
token0825
,
tlv0006
)
it
.
writeHex
(
"01 10"
)
//tag
it
.
writeHex
(
"00 3C"
)
//length
...
...
@@ -94,8 +91,7 @@ open class ClientLoginResendPacket internal constructor(
/**
* @author Him188moe
*/
private
fun
DataOutputStream
.
writePart1
(
qq
:
Long
,
password
:
String
,
loginTime
:
Int
,
loginIP
:
String
,
tgtgtKey
:
ByteArray
,
token0825
:
ByteArray
,
tlv0006
:
ByteArray
?
=
null
)
{
private
fun
DataOutputStream
.
writePart1
(
qq
:
Long
,
password
:
String
,
loginTime
:
Int
,
loginIP
:
String
,
privateKey
:
ByteArray
,
token0825
:
ByteArray
,
tlv0006
:
ByteArray
?
=
null
)
{
//this.writeInt(System.currentTimeMillis().toInt())
this
.
writeHex
(
"01 12"
)
//tag
...
...
@@ -111,13 +107,13 @@ private fun DataOutputStream.writePart1(qq: Long, password: String, loginTime: I
if
(
tlv0006
!=
null
)
{
this
.
write
(
tlv0006
)
}
else
{
this
.
writeTLV0006
(
qq
,
password
,
loginTime
,
loginIP
,
tgtgt
Key
)
this
.
writeTLV0006
(
qq
,
password
,
loginTime
,
loginIP
,
private
Key
)
}
//fix
this
.
writeHex
(
TIMProtocol
.
passwordSubmissionTLV2
)
this
.
writeHex
(
"00 1A"
)
//tag
this
.
writeHex
(
"00 40"
)
//length
this
.
write
(
TEA
.
encrypt
(
TIMProtocol
.
passwordSubmissionTLV2
.
hexToBytes
(),
tgtgt
Key
))
this
.
write
(
TEA
.
encrypt
(
TIMProtocol
.
passwordSubmissionTLV2
.
hexToBytes
(),
private
Key
))
this
.
writeHex
(
TIMProtocol
.
constantData1
)
this
.
writeHex
(
TIMProtocol
.
constantData2
)
this
.
writeQQ
(
qq
)
...
...
mirai-core/src/main/java/net/mamoe/mirai/network/protocol/tim/packet/login/ServerLoginResponseKeyExchangePacket.kt
View file @
126b2210
...
...
@@ -8,7 +8,7 @@ import net.mamoe.mirai.utils.Tested
import
java.io.DataInputStream
/**
* 服务器进行加密后返回
tgtgt
Key
* 服务器进行加密后返回
private
Key
*
* @author NaturalHG
*/
...
...
@@ -21,12 +21,12 @@ class ServerLoginResponseKeyExchangePacket(input: DataInputStream, val flag: Fla
lateinit
var
tlv0006
:
ByteArray
;
//120bytes
var
tokenUnknown
:
ByteArray
?
=
null
lateinit
var
tgtgt
Key
:
ByteArray
//16bytes
lateinit
var
private
Key
:
ByteArray
//16bytes
@Tested
override
fun
decode
()
{
this
.
input
.
skip
(
5
)
tgtgt
Key
=
this
.
input
.
readNBytes
(
16
)
//22
private
Key
=
this
.
input
.
readNBytes
(
16
)
//22
//this.input.skip(2)//25
this
.
input
.
goto
(
25
)
tlv0006
=
this
.
input
.
readNBytes
(
120
)
...
...
@@ -48,8 +48,8 @@ class ServerLoginResponseKeyExchangePacket(input: DataInputStream, val flag: Fla
class
Encrypted
(
input
:
DataInputStream
,
private
val
flag
:
Flag
)
:
ServerPacket
(
input
)
{
@Tested
fun
decrypt
(
tgtgt
Key
:
ByteArray
):
ServerLoginResponseKeyExchangePacket
{
return
ServerLoginResponseKeyExchangePacket
(
this
.
decryptBy
(
TIMProtocol
.
shareKey
,
tgtgt
Key
),
flag
).
setId
(
this
.
idHex
)
fun
decrypt
(
private
Key
:
ByteArray
):
ServerLoginResponseKeyExchangePacket
{
return
ServerLoginResponseKeyExchangePacket
(
this
.
decryptBy
(
TIMProtocol
.
shareKey
,
private
Key
),
flag
).
setId
(
this
.
idHex
)
}
}
}
mirai-core/src/main/java/net/mamoe/mirai/network/protocol/tim/packet/login/ServerLoginResponsePasswordVerifiedPacket.kt
View file @
126b2210
...
...
@@ -55,9 +55,9 @@ class ServerLoginResponseSuccessPacket(input: DataInputStream) : ServerPacket(in
class
Encrypted
(
input
:
DataInputStream
)
:
ServerPacket
(
input
)
{
fun
decrypt
(
tgtgt
Key
:
ByteArray
):
ServerLoginResponseSuccessPacket
{
fun
decrypt
(
private
Key
:
ByteArray
):
ServerLoginResponseSuccessPacket
{
input
goto
14
return
ServerLoginResponseSuccessPacket
(
this
.
decryptBy
(
TIMProtocol
.
shareKey
,
tgtgt
Key
)).
setId
(
this
.
idHex
)
return
ServerLoginResponseSuccessPacket
(
this
.
decryptBy
(
TIMProtocol
.
shareKey
,
private
Key
)).
setId
(
this
.
idHex
)
}
}
...
...
mirai-core/src/main/java/net/mamoe/mirai/network/protocol/tim/packet/login/ServerLoginResponseVerificationCodeInitPacket.kt
View file @
126b2210
...
...
@@ -11,7 +11,7 @@ import net.mamoe.mirai.utils.hexToUBytes
import
java.io.DataInputStream
/**
* 收到这个包意味着需要验证码登录, 并且能得到验证码图片文件的一
半
* 收到这个包意味着需要验证码登录, 并且能得到验证码图片文件的一
部分
*
* @author Him188moe
*/
...
...
@@ -23,7 +23,6 @@ class ServerLoginResponseVerificationCodeInitPacket(input: DataInputStream, priv
@Tested
override
fun
decode
()
{
val
verifyCodeLength
=
this
.
input
.
goto
(
78
).
readShort
()
//2bytes
this
.
verifyCodePart1
=
this
.
input
.
readNBytes
(
verifyCodeLength
.
toInt
())
...
...
@@ -41,7 +40,6 @@ class ServerLoginResponseVerificationCodeInitPacket(input: DataInputStream, priv
}
fun
decrypt
():
ServerLoginResponseVerificationCodeInitPacket
{
this
.
input
goto
14
val
data
=
this
.
decryptBy
(
TIMProtocol
.
shareKey
).
goto
(
0
).
readAllBytes
()
...
...
mirai-core/src/main/java/net/mamoe/mirai/task/MiraiTaskManager.java
View file @
126b2210
package
net.mamoe.mirai.task
;
import
net.mamoe.mirai.event.MiraiEventHook
;
import
net.mamoe.mirai.event.events.server.ServerDisabledEvent
;
import
java.util.concurrent.Callable
;
import
java.util.concurrent.Future
;
import
java.util.concurrent.atomic.AtomicInteger
;
...
...
@@ -25,12 +21,6 @@ public final class MiraiTaskManager {
private
MiraiTaskManager
()
{
this
.
pool
=
new
MiraiThreadPool
();
MiraiEventHook
.
onEvent
(
ServerDisabledEvent
.
class
)
.
handler
(
a
->
this
.
pool
.
close
())
.
mount
();
}
/**
...
...
mirai-core/src/main/java/net/mamoe/mirai/utils/ContactList.java
deleted
100644 → 0
View file @
ffdb7c03
package
net.mamoe.mirai.utils
;
import
net.mamoe.mirai.contact.Contact
;
/**
* @author Him188moe
*/
public
class
ContactList
<
C
extends
Contact
>
extends
MiraiSynchronizedLinkedHashMap
<
Long
,
C
>
{
}
mirai-core/src/main/java/net/mamoe/mirai/utils/ContactList.kt
0 → 100644
View file @
126b2210
package
net.mamoe.mirai.utils
import
net.mamoe.mirai.contact.Contact
/**
* @author Him188moe
*/
class
ContactList
<
C
:
Contact
>
:
MiraiSynchronizedLinkedHashMap
<
Long
,
C
>()
\ No newline at end of file
mirai-core/src/main/java/net/mamoe/mirai/utils/MiraiLogger.kt
View file @
126b2210
...
...
@@ -6,12 +6,11 @@ import net.mamoe.mirai.network.protocol.tim.packet.goto
import
java.text.SimpleDateFormat
import
java.util.*
/**
* @author Him188moe
*/
interface
MiraiLogger
{
companion
object
:
Console
(
"[TOP Level]"
)
companion
object
:
MiraiLogger
by
defaultLogger
(
)
var
identity
:
String
...
...
@@ -31,6 +30,8 @@ interface MiraiLogger {
fun
blue
(
any
:
Any
?)
}
private
fun
defaultLogger
():
MiraiLogger
=
Console
(
"[TOP Level]"
)
val
DEBUGGING
:
Boolean
by
lazy
{
//avoid inspections
true
...
...
@@ -70,7 +71,7 @@ fun Bot.notice(o: Any?) = print(this, o.toString(), LoggerTextFormat.LIGHT_BLUE)
fun
Bot
.
purple
(
o
:
Any
?)
=
print
(
this
,
o
.
toString
(),
LoggerTextFormat
.
PURPLE
)
fun
Bot
.
cyan
(
o
:
Any
?)
=
print
(
this
,
o
.
toString
(),
LoggerTextFormat
.
LIGHT_CYAN
)
fun
Bot
.
success
(
o
:
Any
?)
=
print
(
this
,
o
.
toString
(),
LoggerTextFormat
.
GREEN
)
fun
Bot
.
green
(
o
:
Any
?)
=
print
(
this
,
o
.
toString
(),
LoggerTextFormat
.
GREEN
)
fun
Bot
.
debug
(
o
:
Any
?)
=
print
(
this
,
o
.
toString
(),
LoggerTextFormat
.
YELLOW
)
...
...
mirai-core/src/test/java/BadQQFilter.kt
View file @
126b2210
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.launch
import
kotlinx.coroutines.withContext
import
kotlinx.coroutines.withTimeout
import
net.mamoe.mirai.Bot
import
net.mamoe.mirai.network.protocol.tim.packet.login.LoginState
import
net.mamoe.mirai.utils.BotAccount
import
net.mamoe.mirai.utils.Console
import
java.util.*
import
java.util.concurrent.TimeUnit
/**
* 筛选掉无法登录(冻结/设备锁/UNKNOWN)的 qq
...
...
@@ -85,7 +85,9 @@ suspend fun main() {
)
withContext
(
Dispatchers
.
IO
)
{
bot
.
network
.
tryLogin
().
get
(
3
,
TimeUnit
.
MILLISECONDS
)
withTimeout
(
3000
)
{
bot
.
network
.
tryLogin
().
await
()
}
}.
let
{
state
->
if
(!(
state
==
LoginState
.
BLOCKED
||
state
==
LoginState
.
DEVICE_LOCK
||
state
==
LoginState
.
WRONG_PASSWORD
))
{
goodBotList
.
add
(
bot
)
...
...
mirai-core/src/test/java/PacketDebuger.kt
View file @
126b2210
...
...
@@ -18,7 +18,7 @@ import java.io.DataInputStream
* @author Him188moe
*/
object
Main
{
val
localIp
=
"192.168.3.10"
const
val
localIp
=
"192.168.3.10"
@JvmStatic
fun
main
(
args
:
Array
<
String
>)
{
...
...
@@ -99,12 +99,12 @@ object Main {
println
(
"login failed"
)
}
is
ServerLoginResponseKeyExchangePacket
.
Encrypted
->
packetReceived
(
packet
.
decrypt
(
tgtgt
Key
))
is
ServerLoginResponseKeyExchangePacket
.
Encrypted
->
packetReceived
(
packet
.
decrypt
(
private
Key
))
is
ServerLoginResponseVerificationCodeInitPacket
.
Encrypted
->
packetReceived
(
packet
.
decrypt
())
is
ServerLoginResponseSuccessPacket
.
Encrypted
->
packetReceived
(
packet
.
decrypt
(
tgtgt
Key
))
is
ServerLoginResponseSuccessPacket
.
Encrypted
->
packetReceived
(
packet
.
decrypt
(
private
Key
))
is
ServerLoginResponseKeyExchangePacket
->
{
tgtgtKey
=
packet
.
tgtgt
Key
privateKey
=
packet
.
private
Key
//then 31 04 or 31 06
}
...
...
@@ -133,7 +133,7 @@ object Main {
lateinit
var
token0825
:
ByteArray
//56
var
loginTime
:
Int
=
0
lateinit
var
loginIp
:
String
lateinit
var
tgtgt
Key
:
ByteArray
//16
lateinit
var
private
Key
:
ByteArray
//16
lateinit
var
sessionKey
:
ByteArray
lateinit
var
sessionResponseDecryptionKey
:
ByteArray
...
...
@@ -177,9 +177,9 @@ object Main {
tlv0006
.
skip
(
3
)
tlv0006
.
skip
(
16
+
4
+
1
+
4
*
3
+
4
+
8
+
2
)
tlv0006
.
skipHex
(
"15 74 C4 89 85 7A 19 F5 5E A9 C9 A3 5E 8A 5A 9B"
)
tgtgt
Key
=
tlv0006
.
readNBytes
(
16
)
private
Key
=
tlv0006
.
readNBytes
(
16
)
}
println
(
"Got
tgtgtKey="
+
tgtgt
Key
.
toUHexString
())
println
(
"Got
privateKey="
+
private
Key
.
toUHexString
())
//then receive
}
...
...
mirai-core/src/test/java/data.txxt
View file @
126b2210
...
...
@@ -19,7 +19,7 @@ flag = 08 25 31 02
得到m_loginTime = 5D 61 20 F9
得到m_loginIP = AB 70 E2 96
得到m_0825token = BF A4 B1 36 7C 5D 5A A6 3B 2E 65 E9 20 59 7B 04 3B 7C 36 A2 0F 56 79 BA 9D 66 95 08 F3 B1 56 80 AF C6 C7 C0 AC A8 C2 39 1C AC B5 D5 F8 CD 47 F7 33 06 96 85 1F BA 6E AF
得到m_
tgtgt
Key = CE AD BA 22 50 A9 FE 62 AF C4 29 86 2C AF 17 5C
得到m_
private
Key = CE AD BA 22 50 A9 FE 62 AF C4 29 86 2C AF 17 5C
发送 ClientPasswordSubmissionPacket
PCName 取主机名 () = DESKTOP-M17JREU
PCName 处理后 = 44 45 53 4B 54 4F 50 2D 4D 31 37 4A 52 45 55
...
...
@@ -27,7 +27,7 @@ g_pass = xiaoqqq
g_QQ = 76 E4 B8 DD
crc32_code(Random) = B9 11 E7 AB 9D AB 61 35 4B B2 2D E0 EA 78 C6 C0
crc32_data = 95 9D B2 30
m_
tgtgt
Key = CE AD BA 22 50 A9 FE 62 AF C4 29 86 2C AF 17 5C
m_
private
Key = CE AD BA 22 50 A9 FE 62 AF C4 29 86 2C AF 17 5C
packet = 79 35 21 65 00 02 76 E4 B8 DD 00 00 04 53 00 00 00 01 00 00 15 85 00 00 01 95 5B 96 CB 95 CF 1C A6 94 C4 B7 79 07 9A BB 15 5D 61 20 F9 00 00 00 00 00 00 00 00 00 00 00 00 00 AB 70 E2 96 00 00 00 00 00 00 00 00 00 10 15 74 C4 89 85 7A 19 F5 5E A9 C9 A3 5E 8A 5A 9B CE AD BA 22 50 A9 FE 62 AF C4 29 86 2C AF 17 5C
TEA 加密, 内容=79 35 21 65 00 02 76 E4 B8 DD 00 00 04 53 00 00 00 01 00 00 15 85 00 00 01 95 5B 96 CB 95 CF 1C A6 94 C4 B7 79 07 9A BB 15 5D 61 20 F9 00 00 00 00 00 00 00 00 00 00 00 00 00 AB 70 E2 96 00 00 00 00 00 00 00 00 00 10 15 74 C4 89 85 7A 19 F5 5E A9 C9 A3 5E 8A 5A 9B CE AD BA 22 50 A9 FE 62 AF C4 29 86 2C AF 17 5C
TEA 加密, 内容=00 15 00 30 00 01 01 27 9B C7 F5 00 10 65 03 FD 8B 00 00 00 00 00 00 00 00 00 00 00 00 02 90 49 55 33 00 10 15 74 C4 89 85 7A 19 F5 5E A9 C9 A3 5E 8A 5A 9B
...
...
@@ -39,7 +39,7 @@ g_pass = xiaoqqq
g_QQ = 76 E4 B8 DD
crc32_code(Random) = A0 99 89 10 F4 AB AD F5 C1 03 CE 74 FE FB 49 FD
crc32_data = 5B 1F 17 CA
m_
tgtgt
Key = CE AD BA 22 50 A9 FE 62 AF C4 29 86 2C AF 17 5C
m_
private
Key = CE AD BA 22 50 A9 FE 62 AF C4 29 86 2C AF 17 5C
packet = A5 FD E6 15 00 02 76 E4 B8 DD 00 00 04 53 00 00 00 01 00 00 15 85 00 00 01 95 5B 96 CB 95 CF 1C A6 94 C4 B7 79 07 9A BB 15 5D 61 20 F9 00 00 00 00 00 00 00 00 00 00 00 00 00 AB 70 E2 96 00 00 00 00 00 00 00 00 00 10 15 74 C4 89 85 7A 19 F5 5E A9 C9 A3 5E 8A 5A 9B CE AD BA 22 50 A9 FE 62 AF C4 29 86 2C AF 17 5C
TEA 加密, 内容=A5 FD E6 15 00 02 76 E4 B8 DD 00 00 04 53 00 00 00 01 00 00 15 85 00 00 01 95 5B 96 CB 95 CF 1C A6 94 C4 B7 79 07 9A BB 15 5D 61 20 F9 00 00 00 00 00 00 00 00 00 00 00 00 00 AB 70 E2 96 00 00 00 00 00 00 00 00 00 10 15 74 C4 89 85 7A 19 F5 5E A9 C9 A3 5E 8A 5A 9B CE AD BA 22 50 A9 FE 62 AF C4 29 86 2C AF 17 5C
TEA 加密, 内容=00 15 00 30 00 01 01 27 9B C7 F5 00 10 65 03 FD 8B 00 00 00 00 00 00 00 00 00 00 00 00 02 90 49 55 33 00 10 15 74 C4 89 85 7A 19 F5 5E A9 C9 A3 5E 8A 5A 9B
...
...
@@ -49,7 +49,7 @@ paccket sent: 02 37 13 08 36 31 03 76 E4 B8 DD 03 00 00 00 01 01 01 00 00 68 20
flag = 08 36 31 03
收到 ServerLoginResponseSucceedPacket
原文 = 02 37 13 08 36 31 03 76 E4 B8 DD 00 00 00 BD 57 C9 45 45 E4 52 BE DA 05 67 A3 49 0F B7 90 AD 3E 47 34 A9 A8 B3 D9 82 E1 45 95 A4 41 F0 66 56 20 D5 0C B7 AF 9E A3 3A 32 FE 89 B2 0A AD 81 EC D0 D1 7A 17 00 51 5E FA BD 75 D1 DB E9 12 DC 89 25 A8 6D 80 F4 00 21 68 70 A0 77 E3 EF FA 9C 80 25 47 5B 55 E1 A0 1D D9 6B FE B7 7F 6A 3B 67 45 A5 F1 CE 33 F4 43 67 1D FD 83 F6 88 9F 2E 7E F3 8B 0E DE 68 76 B1 48 9A 5C B2 B2 8D 12 E3 FA CE 0F 22 F1 7C 20 4D AD 01 09 36 C6 64 3A BE CA 33 68 46 19 8A A9 66 7A 13 DC F2 EE 04 91 74 FB CB 57 B5 48 84 BF 99 24 3C 1E 5C 04 56 F1 28 E1 49 95 0D 71 39 FB A2 AE EE C5 E6 99 91 A3 A3 59 48 CA DE 10 66 F2 FA 88 D8 6F 46 2B B3 F4 33 C0 64 92 92 99 83 06 43 C2 3C FC 0F 34 38 7C 0F F8 3C 35 D0 CD 23 05 06 5B 61 B3 AD 38 D9 E2 5F 51 A4 A0 CA AF 4A A9 86 11 C9 AC 2C 44 11 08 52 E3 3C 0D 1B 91 B6 C6 70 FC 15 CC 16 F6 3B C9 97 C0 82 D1 8B 24 2F AA 35 50 61 E9 11 F8 E1 09 29 B9 20 5E 3A 73 33 BF 78 9C CC D0 A7 BF 23 66 65 3B D1 1F 71 40 C2 E2 0D CA 6F 57 D8 E1 46 B6 47 65 9E 43 04 0E 30 54 EB 70 42 49 6F 75 55 C5 63 3A A4 9D FF 0B F8 56 3B 89 74 14 56 6B 6E 9D 32 D4 DD FA E7 C6 B2 6B 61 F0 54 EF 05 7E E1 49 D6 38 A0 C1 B3 F6 B4 7A 4A 03 31 1D E7 88 BA 56 9D 50 03 95 FF DB 23 DC 3C B9 51 1B 4B 06 1E 5E C5 B1 96 EA 8B 64 92 48 24 65 A4 92 EC BA 90 42 AD BA 04 81 4F 42 FB 41 60 E9 93 68 1F 59 67 57 57 5F 40 22 1B F2 D9 C5 5D 53 34 2C E4 82 ED D2 A8 3B F1 C2 05 2A 4D F9 45 63 21 E7 92 5A 01 D4 A4 3A 98 D8 57 39 34 D4 E2 CC F6 D1 76 12 76 00 A5 89 18 66 9C F9 18 31 52 E6 92 B2 11 46 73 8D 37 92 99 7A 3B FC 82 36 A1 7A 7B 91 D0 F7 59 C2 64 76 7A 4F 7E 88 8A AF 11 AA 90 5C 0D E2 9F F7 A8 9B 04 A7 05 48 EC 92 01 2A 19 0E 8C A7 1B 9C 1F B2 F8 BD C5 AE 98 D5 86 C7 C6 D2 D5 BC B5 BB D7 F9 05 52 F1 5A 6D B5 94 2C 44 86 11 A9 B3 EB 9D D7 30 BF 21 1F 22 2D FB AC 0C 5C 94 C4 69 C2 82 C8 48 6C 86 40 95 EF 67 9B B1 60 17 09 56 AE CB 85 EF FD 60 7D BA A3 1D 13 05 10 93 ED 5D 91 6B 3B 8C 23 C4 45 EF 02 BA 86 0E F7 8E 46 C7 3D 07 8A 67 94 3B 5C 4B 05 BD 64 76 DF 1A 3B A5 C9 26 AA F6 A5 36 4E EC 00 AD D8 B7 5E 32 53 02 9F CF 3C 23 9C 94 BB 03 F8 97 9F 53 CC A0 68 77 4D A4 DE D0 CE DE 68 FC A2 07 A5 9E 65 28 E2 A2 95 E0 1D 45 11 47 E9 03 1A BE F5 1F 48 36 37 B8 EA EA 6B 9C 73 93 7D 21 CA 77 F7 62 73 BF BA 54 BB C2 38 0C 04 68 A 4 E0 05 98 18 6E 5D EC 40 EE 54 27 9C 67 5C 79 5D 89 3C 4F DC 29 50 46 87 D9 EB F9 12 03
进行解密, key=m_
tgtgt
Key = CE AD BA 22 50 A9 FE 62 AF C4 29 86 2C AF 17 5C
进行解密, key=m_
private
Key = CE AD BA 22 50 A9 FE 62 AF C4 29 86 2C AF 17 5C
得到m_0828_rec_decr_key = 79 44 42 48 54 78 7D 76 35 2D 37 5F 74 58 77 66
得到nick_length = 20
得到m_nick = (?ω)
...
...
mirai-core/src/test/java/event/EventTest.kt
0 → 100644
View file @
126b2210
package
event
import
net.mamoe.mirai.event.Event
import
net.mamoe.mirai.event.broadcast
import
net.mamoe.mirai.event.subscribeAll
import
kotlin.reflect.KClass
/**
* @author Him188moe
*/
open
class
SuperEvent
:
Event
()
{
companion
object
:
KClass
<
SuperEvent
>
by
SuperEvent
::
class
//方便 subscribe
}
open
class
ChildEvent
:
SuperEvent
()
open
class
ChildChildEvent
:
ChildEvent
()
class
ChildChildChildEvent
:
ChildChildEvent
()
suspend
fun
main
()
{
SuperEvent
.
subscribeAll
{
always
{
println
(
it
.
javaClass
.
simpleName
)
//ChildChildChildEvent
}
}
ChildChildChildEvent
().
broadcast
()
}
\ No newline at end of file
mirai-demos/mirai-demo-1/src/main/java/demo1/Main.kt
View file @
126b2210
...
...
@@ -4,7 +4,9 @@ import net.mamoe.mirai.Bot
import
net.mamoe.mirai.contact.Group
import
net.mamoe.mirai.event.events.group.GroupMessageEvent
import
net.mamoe.mirai.event.events.qq.FriendMessageEvent
import
net.mamoe.mirai.event.hookAlways
import
net.mamoe.mirai.event.subscribeAll
import
net.mamoe.mirai.event.subscribeAlways
import
net.mamoe.mirai.event.subscribeUntilFalse
import
net.mamoe.mirai.message.defaults.Image
import
net.mamoe.mirai.message.defaults.PlainText
import
net.mamoe.mirai.network.protocol.tim.packet.login.LoginState
...
...
@@ -14,18 +16,29 @@ import net.mamoe.mirai.utils.Console
/**
* @author Him188moe
*/
fun
main
()
{
suspend
fun
main
()
{
val
bot
=
Bot
(
BotAccount
(
qqNumber
=
1683921395
,
password
=
"bb22222"
),
Console
())
bot
.
network
.
tryLogin
().
ge
t
().
let
{
bot
.
network
.
tryLogin
().
awai
t
().
let
{
check
(
it
==
LoginState
.
SUCCESS
)
{
"Login failed: "
+
it
.
name
}
}
//DSL 监听
FriendMessageEvent
.
subscribeAll
{
always
{
//获取第一个纯文本消息
val
firstText
=
it
.
message
[
PlainText
]
}
}
//监听事件:
FriendMessageEvent
::
class
.
hook
Always
{
FriendMessageEvent
.
subscribe
Always
{
//获取第一个纯文本消息
val
firstText
=
it
.
message
[
PlainText
]
...
...
@@ -57,9 +70,27 @@ fun main() {
}
}
GroupMessageEvent
::
class
.
hook
Always
{
GroupMessageEvent
::
class
.
subscribe
Always
{
when
{
it
.
message
.
contains
(
"复读"
)
->
it
.
reply
(
it
.
message
)
}
}
}
/**
* 实现功能:
* 对机器人说 "记笔记", 机器人记录之后的所有消息.
* 对机器人说 "停止", 机器人停止
*/
fun
demo2
()
{
FriendMessageEvent
.
subscribeAlways
{
event
->
if
(
event
.
message
eq
"记笔记"
)
{
FriendMessageEvent
.
subscribeUntilFalse
{
it
.
reply
(
"你发送了 ${it.message}"
)
it
.
message
eq
"停止"
}
}
}
}
\ No newline at end of file
mirai-demos/pom.xml
View file @
126b2210
...
...
@@ -15,6 +15,7 @@
<modules>
<module>
mirai-demo-1
</module>
<module>
mirai-demo-event
</module>
</modules>
...
...
pom.xml
View file @
126b2210
...
...
@@ -34,7 +34,7 @@
<properties>
<kotlin.version>
1.3.
41
</kotlin.version>
<kotlin.version>
1.3.
50
</kotlin.version>
<maven.compiler.source>
11
</maven.compiler.source>
<maven.compiler.target>
11
</maven.compiler.target>
<project.build.sourceEncoding>
UTF-8
</project.build.sourceEncoding>
...
...
@@ -80,12 +80,6 @@
<version>
5.4.0
</version>
</dependency>
<dependency>
<groupId>
com.google.code.gson
</groupId>
<artifactId>
gson
</artifactId>
<version>
2.8.5
</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core -->
<dependency>
<groupId>
org.jetbrains.kotlinx
</groupId>
...
...
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