diff --git a/mirai-core/src/main/java/net/mamoe/mirai/MiraiServer.java b/mirai-core/src/main/java/net/mamoe/mirai/MiraiServer.java
index a2a1556c0..81ba8639c 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/MiraiServer.java
+++ b/mirai-core/src/main/java/net/mamoe/mirai/MiraiServer.java
@@ -2,22 +2,25 @@ package net.mamoe.mirai;
import lombok.Getter;
import net.mamoe.mirai.event.MiraiEventManager;
-import net.mamoe.mirai.event.events.server.ServerDisableEvent;
-import net.mamoe.mirai.event.events.server.ServerEnableEvent;
+import net.mamoe.mirai.event.events.server.ServerDisabledEvent;
+import net.mamoe.mirai.event.events.server.ServerEnabledEvent;
import net.mamoe.mirai.network.packet.login.LoginState;
import net.mamoe.mirai.task.MiraiTaskManager;
import net.mamoe.mirai.utils.LoggerTextFormat;
import net.mamoe.mirai.utils.MiraiLogger;
import net.mamoe.mirai.utils.config.MiraiConfig;
import net.mamoe.mirai.utils.config.MiraiConfigSection;
-import net.mamoe.mirai.utils.setting.MiraiSetting;
import net.mamoe.mirai.utils.setting.MiraiSettingListSection;
import net.mamoe.mirai.utils.setting.MiraiSettingMapSection;
+import net.mamoe.mirai.utils.setting.MiraiSettings;
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
+/**
+ * @author NaturalHG
+ */
public class MiraiServer {
private static MiraiServer instance;
@@ -25,10 +28,8 @@ public class MiraiServer {
return instance;
}
- //mirai version
private final static String MIRAI_VERSION = "1.0.0";
- //qq version
private final static String QQ_VERSION = "4.9.0";
@@ -46,30 +47,30 @@ public class MiraiServer {
@Getter
MiraiLogger logger;
- MiraiSetting setting;
+ MiraiSettings settings;
MiraiConfig qqs;
- protected MiraiServer() {
+ MiraiServer() {
instance = this;
- this.onLoad();
- this.onEnable();
+ this.onLoaded();
+ this.onEnabled();
}
private boolean enabled;
- protected void shutdown() {
+ void shutdown() {
if (this.enabled) {
getLogger().info("About to shutdown Mirai");
- this.getEventManager().broadcastEvent(new ServerDisableEvent());
+ this.eventManager.broadcastEventAsync(new ServerDisabledEvent());
getLogger().info("Data have been saved");
}
}
- private void onLoad() {
+ private void onLoaded() {
this.parentFolder = new File(System.getProperty("user.dir"));
this.unix = !System.getProperties().getProperty("os.name").toUpperCase().contains("WINDOWS");
@@ -86,7 +87,7 @@ public class MiraiServer {
if (!setting.exists()) {
this.initSetting(setting);
} else {
- this.setting = new MiraiSetting(setting);
+ this.settings = new MiraiSettings(setting);
}
File qqs = new File(this.parentFolder + "/QQ.yml");
@@ -114,27 +115,6 @@ public class MiraiServer {
});
*/
- getLogger().info("ready to connect");
-
-
- this.qqs.keySet().stream().map(key -> this.qqs.getSection(key)).forEach(section -> {
- try {
- Robot robot = new Robot(section);
- robot.network.tryLogin$mirai_core((robot1, state) -> {
- if (state == LoginState.SUCCEED) {
- Robot.instances.add(robot);
- } else {
- robot.close();
- }
- return null;
- });
-
- } catch (Throwable e) {
- e.printStackTrace();
- getLogger().error("Could not load QQ robots config!");
- System.exit(1);
- }
- });
}
private void initSetting(File setting) {
@@ -147,21 +127,21 @@ public class MiraiServer {
} catch (IOException e) {
e.printStackTrace();
}
- this.setting = new MiraiSetting(setting);
- MiraiSettingMapSection network = this.setting.getMapSection("network");
+ this.settings = new MiraiSettings(setting);
+ MiraiSettingMapSection network = this.settings.getMapSection("network");
network.set("enable_proxy", "not supporting yet");
- MiraiSettingListSection proxy = this.setting.getListSection("proxy");
+ MiraiSettingListSection proxy = this.settings.getListSection("proxy");
proxy.add("1.2.3.4:95");
proxy.add("1.2.3.4:100");
- MiraiSettingMapSection worker = this.setting.getMapSection("worker");
+ MiraiSettingMapSection worker = this.settings.getMapSection("worker");
worker.set("core_task_pool_worker_amount", 5);
- MiraiSettingMapSection plugin = this.setting.getMapSection("plugin");
+ MiraiSettingMapSection plugin = this.settings.getMapSection("plugin");
plugin.set("debug", false);
- this.setting.save();
+ this.settings.save();
getLogger().info("initialized; changing can be made in setting file: " + setting.toString());
}
@@ -187,11 +167,35 @@ public class MiraiServer {
getLogger().info("QQ account initialized; changing can be made in Config file: " + qqConfig.toString());
}
- private void onEnable() {
- this.eventManager.broadcastEvent(new ServerEnableEvent());
+ 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);
+
+ getLogger().info("Initializing [Robot]s");
+
+ this.qqs.keySet().stream().map(key -> this.qqs.getSection(key)).forEach(section -> {
+ getLogger().info("Initializing [Robot] " + section.getString("account"));
+ try {
+ Robot robot = new Robot(section);
+ var state = robot.network.tryLogin$mirai_core().get();
+ //robot.network.tryLogin$mirai_core().whenComplete((state, e) -> {
+ if (state == LoginState.SUCCEED) {
+ Robot.instances.add(robot);
+ getLogger().info(" Succeed");
+ } else {
+ getLogger().error(" Failed with error " + state);
+ robot.close();
+ }
+ // }).get();
+
+ } catch (Throwable e) {
+ e.printStackTrace();
+ getLogger().error("Could not load QQ robots config!");
+ System.exit(1);
+ }
+ });
}
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/Robot.java b/mirai-core/src/main/java/net/mamoe/mirai/Robot.java
index 7d25a04f0..d4e711deb 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/Robot.java
+++ b/mirai-core/src/main/java/net/mamoe/mirai/Robot.java
@@ -13,6 +13,21 @@ import java.io.Closeable;
import java.util.*;
/**
+ * Mirai 的机器人. 一个机器人实例登录一个 QQ 账号.
+ * Mirai 为多账号设计, 可同时维护多个机器人账号.
+ *
+ * {@link Robot} 由 2 个模块组成.
+ * {@linkplain ContactSystem 联系人管理}: 可通过 {@link Robot#contacts} 访问
+ * {@linkplain RobotNetworkHandler 网络处理器}: 可通过 {@link Robot#network} 访问
+ *
+ * 另外地, 若你需要得到机器人的 QQ 账号, 请访问 {@link Robot#account}
+ * 若你需要得到服务器上所有机器人列表, 请访问 {@link Robot#instances}
+ *
+ * @author Him188moe
+ * @author NatrualHG
+ * @see net.mamoe.mirai.contact.Contact
+ *
+ *
* Robot that is the base of the whole program.
* It contains a {@link ContactSystem}, which manage contacts such as {@link QQ} and {@link Group}.
*/
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/contact/QQ.kt b/mirai-core/src/main/java/net/mamoe/mirai/contact/QQ.kt
index 2b8fb792d..af009045e 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/contact/QQ.kt
+++ b/mirai-core/src/main/java/net/mamoe/mirai/contact/QQ.kt
@@ -5,8 +5,11 @@ import net.mamoe.mirai.message.Message
import net.mamoe.mirai.message.defaults.At
/**
+ * QQ 账号.
+ * 注意: 一个 [QQ] 实例并不是独立的, 它属于一个 [Robot].
+ *
* A QQ instance helps you to receive message from or send message to.
- * Notice that one QQ instance belong to one [Robot], that is, QQ instances from different [Robot] are NOT the same.
+ * Notice that, one QQ instance belong to one [Robot], that is, QQ instances from different [Robot] are NOT the same.
*
* @author Him188moe
*/
@@ -21,6 +24,8 @@ class QQ(robot: Robot, number: Long) : Contact(robot, number) {
/**
* At(@) this account.
+ *
+ * @return an instance of [Message].
*/
fun at(): At {
return At(this)
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/event/AsyncEvent.java b/mirai-core/src/main/java/net/mamoe/mirai/event/AsyncEvent.java
new file mode 100644
index 000000000..583f0dc2a
--- /dev/null
+++ b/mirai-core/src/main/java/net/mamoe/mirai/event/AsyncEvent.java
@@ -0,0 +1,27 @@
+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 CompletableFuture broadcastEventAsync(Consumer callback) {
+ return MiraiEventManager.getInstance().broadcastEventAsync((E) this, callback);
+ }
+
+ @SuppressWarnings("unchecked")
+ default CompletableFuture broadcastEventAsync(Runnable callback) {
+ return MiraiEventManager.getInstance().broadcastEventAsync((E) this, callback);
+ }
+}
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/event/AsyncEventKt.kt b/mirai-core/src/main/java/net/mamoe/mirai/event/AsyncEventKt.kt
new file mode 100644
index 000000000..32490d42a
--- /dev/null
+++ b/mirai-core/src/main/java/net/mamoe/mirai/event/AsyncEventKt.kt
@@ -0,0 +1,14 @@
+@file:JvmName("AsyncEventKt")
+
+package net.mamoe.mirai.event
+
+import java.util.concurrent.CompletableFuture
+import java.util.function.Consumer
+
+fun E.broadcastAsync(callback: Consumer): CompletableFuture {
+ return MiraiEventManager.getInstance().broadcastEventAsync(this, callback)
+}
+
+fun E.broadcastAsync(callback: Runnable): CompletableFuture {
+ return MiraiEventManager.getInstance().broadcastEventAsync(this, callback)
+}
\ No newline at end of file
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/event/events/Cancellable.java b/mirai-core/src/main/java/net/mamoe/mirai/event/Cancellable.java
similarity index 79%
rename from mirai-core/src/main/java/net/mamoe/mirai/event/events/Cancellable.java
rename to mirai-core/src/main/java/net/mamoe/mirai/event/Cancellable.java
index 59167fda0..e12d0cb9b 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/event/events/Cancellable.java
+++ b/mirai-core/src/main/java/net/mamoe/mirai/event/Cancellable.java
@@ -1,4 +1,4 @@
-package net.mamoe.mirai.event.events;
+package net.mamoe.mirai.event;
/**
* @author NaturalHG
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEvent.java b/mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEvent.java
new file mode 100644
index 000000000..efa532ff0
--- /dev/null
+++ b/mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEvent.java
@@ -0,0 +1,35 @@
+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;
+ }
+}
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEventHook.java b/mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEventHook.java
index c8088be6e..d46deb7d8 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEventHook.java
+++ b/mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEventHook.java
@@ -2,20 +2,21 @@ package net.mamoe.mirai.event;
import lombok.Getter;
import lombok.Setter;
-import net.mamoe.mirai.event.events.Cancellable;
-import net.mamoe.mirai.event.events.MiraiEvent;
import java.io.Closeable;
import java.util.function.Consumer;
import java.util.function.Predicate;
+/**
+ * @author NatrualHG
+ */
public class MiraiEventHook implements Closeable {
@Getter
Class eventClass;
@Getter
- private volatile Consumer handler;
+ protected volatile Consumer handler;
@Getter
private volatile int priority = 0;
@@ -31,7 +32,7 @@ public class MiraiEventHook implements Closeable {
* return true -> this hook need to be removed
*/
@Getter
- private Predicate valid;
+ protected Predicate validChecker;
public MiraiEventHook(Class eventClass) {
this(eventClass,null);
@@ -58,26 +59,26 @@ public class MiraiEventHook implements Closeable {
}
- private MiraiEventHook setValid(Predicate valid) {
- this.valid = valid;
+ private MiraiEventHook setValidChecker(Predicate validChecker) {
+ this.validChecker = validChecker;
return this;
}
public MiraiEventHook setValidUntil(Predicate valid) {
- return this.setValid(valid);
+ return this.setValidChecker(valid);
}
public MiraiEventHook setValidWhile(Predicate valid) {
- return this.setValid(valid.negate());
+ 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);
+ this.getHandler().accept((T) event);
}
- return this.valid == null || this.valid.test((T) event);
+ return this.validChecker == null || this.validChecker.test((T) event);
}
/**
@@ -103,6 +104,6 @@ public class MiraiEventHook implements Closeable {
@Override
public void close(){
this.handler = null;
- this.valid = null;
+ this.validChecker = null;
}
}
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEventHookKt.kt b/mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEventHookKt.kt
new file mode 100644
index 000000000..4a072a2be
--- /dev/null
+++ b/mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEventHookKt.kt
@@ -0,0 +1,31 @@
+package net.mamoe.mirai.event
+
+import java.util.function.Consumer
+import java.util.function.Predicate
+
+/**
+ * @author Him188moe
+ */
+class MiraiEventHookKt(eventClass: Class) : MiraiEventHook(eventClass) {
+ fun onEvent(handler: (E) -> Unit) {
+ this@MiraiEventHookKt.handler = Consumer(handler)
+ }
+
+ fun validChecker(predicate: (E) -> Boolean) {
+ this@MiraiEventHookKt.validChecker = Predicate(predicate)
+ }
+}
+
+
+/**
+ * Kotlin 风格回调
+ * 你的代码可以这样(并且 validChecker 是可选的):
+ *
+ * event.hook {
+ * onEvent {}
+ * validChecker {}
+ * }
+ */
+fun E.hook(handler: MiraiEventHookKt.() -> Unit): MiraiEventHookKt {
+ return MiraiEventHookKt(this.javaClass).apply(handler)
+}
\ No newline at end of file
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEventKt.kt b/mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEventKt.kt
new file mode 100644
index 000000000..d4441bb62
--- /dev/null
+++ b/mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEventKt.kt
@@ -0,0 +1,8 @@
+@file:JvmName("MiraiEventKt")
+
+package net.mamoe.mirai.event
+
+fun E.broadcast(): E {
+ MiraiEventManager.getInstance().broadcastEvent(this as MiraiEvent)
+ return this
+}
\ No newline at end of file
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEventManager.java b/mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEventManager.java
index d93ba6684..90622b1e2 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEventManager.java
+++ b/mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEventManager.java
@@ -1,21 +1,25 @@
package net.mamoe.mirai.event;
-import net.mamoe.mirai.MiraiServer;
-import net.mamoe.mirai.event.events.MiraiEvent;
-
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;
+ return EventManager.INSTANCE;//实例来自 kotlin 的 singleton
}
private final ReentrantReadWriteLock hooksLock = new ReentrantReadWriteLock();
@@ -115,23 +119,40 @@ public class MiraiEventManager {
}
- public void asyncBroadcastEvent(MiraiEvent event) {
- this.asyncBroadcastEvent(event, a -> {
- });
- }
+ public CompletableFuture broadcastEventAsync(E event) {
+ Objects.requireNonNull(event);
+ if (!(event instanceof MiraiEvent)) {
+ throw new IllegalArgumentException("event must be instanceof MiraiEvent");
+ }
- public void asyncBroadcastEvent(D event, Consumer callback) {
- MiraiServer.getInstance().getTaskManager().ansycTask(() -> {
- MiraiEventManager.this.broadcastEvent(event);
+ CompletableFuture future = new CompletableFuture<>();
+ future.completeAsync(() -> {
+ MiraiEventManager.this.broadcastEvent((MiraiEvent) event);
return event;
- }, callback);
+ });
+ return future;
+ }
+
+ public CompletableFuture broadcastEventAsync(E event, Consumer callback) {
+ Objects.requireNonNull(event);
+ Objects.requireNonNull(callback);
+ if (!(event instanceof MiraiEvent)) {
+ throw new IllegalArgumentException("event must be instanceof MiraiEvent");
+ }
+
+ CompletableFuture future = new CompletableFuture<>();
+ future.whenComplete((a, b) -> callback.accept(event));
+ future.completeAsync(() -> {
+ MiraiEventManager.this.broadcastEvent((MiraiEvent) event);
+ return event;
+ });
+ return future;
}
- public void asyncBroadcastEvent(D event, Runnable callback) {
- asyncBroadcastEvent(event, t -> callback.run());
+ public CompletableFuture broadcastEventAsync(D event, Runnable callback) {
+ return broadcastEventAsync(event, t -> callback.run());
}
-
}
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/event/EventManager.kt b/mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEventManagerKt.kt
similarity index 63%
rename from mirai-core/src/main/java/net/mamoe/mirai/event/EventManager.kt
rename to mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEventManagerKt.kt
index 42e6765f0..e3cd769a1 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/event/EventManager.kt
+++ b/mirai-core/src/main/java/net/mamoe/mirai/event/MiraiEventManagerKt.kt
@@ -1,33 +1,59 @@
+@file:JvmName("MiraiEventManagerKt")
+
package net.mamoe.mirai.event
-import net.mamoe.mirai.event.events.MiraiEvent
import kotlin.reflect.KClass
-object EventManager : MiraiEventManager()
-typealias MiraiEventManagerKt = EventManager
-typealias EventMgr = EventManager
+/**
+ * [MiraiEventManager] 的 kotlin 简易化实现.
+ * 若要 hook 一个事件, 你可以:
+ * FriendMessageEvent::class.hookOnce {}
+ * FriendMessageEvent::class.hookAlways {}
+ *
+ * @author Him188moe
+ */
+object EventManager : MiraiEventManager()
+
+/**
+ * 每次事件触发时都会调用 hook
+ */
fun , E : MiraiEvent> C.hookAlways(hook: (E) -> Unit) {
MiraiEventManager.getInstance().hookAlways(MiraiEventHook(this, hook))
}
+/**
+ * 当下一次事件触发时调用 hook
+ */
fun , E : MiraiEvent> C.hookOnce(hook: (E) -> Unit) {
MiraiEventManager.getInstance().hookOnce(MiraiEventHook(this, hook))
}
+/**
+ * 每次事件触发时都会调用 hook, 直到 hook 返回 false 时停止 hook
+ */
fun , E : MiraiEvent> C.hookWhile(hook: (E) -> Boolean) {
- MiraiEventManager.getInstance().hookAlways(MiraiEventHookSimple(this, hook))
+ MiraiEventManager.getInstance().hookAlways(MiraiEventHookSimple(this, hook))
}
+/**
+ * 每次事件触发时都会调用 hook
+ */
fun , E : MiraiEvent> C.hookAlways(hook: (E) -> Unit) {
this.java.hookAlways(hook)
}
+/**
+ * 当下一次事件触发时调用 hook
+ */
fun , E : MiraiEvent> C.hookOnce(hook: (E) -> Unit) {
this.java.hookOnce(hook)
}
+/**
+ * 每次事件触发时都会调用 hook, 直到 hook 返回 false 时停止 hook
+ */
fun , E : MiraiEvent> C.hookWhile(hook: (E) -> Boolean) {
this.java.hookWhile(hook)
}
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/event/events/MiraiEvent.java b/mirai-core/src/main/java/net/mamoe/mirai/event/events/MiraiEvent.java
deleted file mode 100644
index a8509e7f3..000000000
--- a/mirai-core/src/main/java/net/mamoe/mirai/event/events/MiraiEvent.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package net.mamoe.mirai.event.events;
-
-import net.mamoe.mirai.event.MiraiEventManager;
-import net.mamoe.mirai.utils.EventException;
-
-import java.util.function.Consumer;
-
-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;
- }
-
- protected String eventName;
-
- public String getEventName() {
- if (this.eventName == null) {
- return this.getClass().getSimpleName();
- }
- return this.eventName;
- }
-
- public final MiraiEvent broadcast() {
- MiraiEventManager.getInstance().broadcastEvent(this);
- return this;
- }
-
- @SuppressWarnings("unchecked")
- public final void asyncBroadcast(Consumer callback) {
- MiraiEventManager.getInstance().asyncBroadcastEvent((D) this, callback);
- }
-
- @SuppressWarnings("unchecked")
- public final void asyncBroadcast(Runnable callback) {
- MiraiEventManager.getInstance().asyncBroadcastEvent((D) this, callback);
- }
-}
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/event/events/network/BeforePacketSendEvent.java b/mirai-core/src/main/java/net/mamoe/mirai/event/events/network/BeforePacketSendEvent.java
new file mode 100644
index 000000000..2996d08ee
--- /dev/null
+++ b/mirai-core/src/main/java/net/mamoe/mirai/event/events/network/BeforePacketSendEvent.java
@@ -0,0 +1,14 @@
+package net.mamoe.mirai.event.events.network;
+
+import net.mamoe.mirai.event.Cancellable;
+import net.mamoe.mirai.network.packet.ClientPacket;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Him188moe
+ */
+public final class BeforePacketSendEvent extends ClientPacketEvent implements Cancellable {
+ public BeforePacketSendEvent(@NotNull ClientPacket packet) {
+ super(packet);
+ }
+}
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/event/events/network/ClientPacketEvent.java b/mirai-core/src/main/java/net/mamoe/mirai/event/events/network/ClientPacketEvent.java
new file mode 100644
index 000000000..e25920e95
--- /dev/null
+++ b/mirai-core/src/main/java/net/mamoe/mirai/event/events/network/ClientPacketEvent.java
@@ -0,0 +1,18 @@
+package net.mamoe.mirai.event.events.network;
+
+import net.mamoe.mirai.network.packet.ClientPacket;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Him188moe
+ */
+public abstract class ClientPacketEvent extends PacketEvent {
+ public ClientPacketEvent(@NotNull ClientPacket packet) {
+ super(packet);
+ }
+
+ @Override
+ public ClientPacket getPacket() {
+ return (ClientPacket) super.getPacket();
+ }
+}
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/event/events/network/PacketEvent.java b/mirai-core/src/main/java/net/mamoe/mirai/event/events/network/PacketEvent.java
index 119f87933..08d4b6a79 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/event/events/network/PacketEvent.java
+++ b/mirai-core/src/main/java/net/mamoe/mirai/event/events/network/PacketEvent.java
@@ -1,7 +1,10 @@
package net.mamoe.mirai.event.events.network;
-import net.mamoe.mirai.event.events.MiraiEvent;
+import net.mamoe.mirai.event.MiraiEvent;
import net.mamoe.mirai.network.packet.Packet;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Objects;
/**
* @author Him188moe
@@ -9,8 +12,8 @@ import net.mamoe.mirai.network.packet.Packet;
public abstract class PacketEvent extends MiraiEvent {
private final Packet packet;
- public PacketEvent(Packet packet) {
- this.packet = packet;
+ public PacketEvent(@NotNull Packet packet) {
+ this.packet = Objects.requireNonNull(packet);
}
public Packet getPacket() {
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/event/events/network/PacketReceivedEvent.java b/mirai-core/src/main/java/net/mamoe/mirai/event/events/network/PacketReceivedEvent.java
deleted file mode 100644
index 77b697050..000000000
--- a/mirai-core/src/main/java/net/mamoe/mirai/event/events/network/PacketReceivedEvent.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package net.mamoe.mirai.event.events.network;
-
-/**
- * @author Him188moe
- */
-public class PacketReceivedEvent {
-}
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/event/events/network/ServerPacketReceivedEvent.java b/mirai-core/src/main/java/net/mamoe/mirai/event/events/network/ServerPacketReceivedEvent.java
index 77fa219ea..79a302b46 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/event/events/network/ServerPacketReceivedEvent.java
+++ b/mirai-core/src/main/java/net/mamoe/mirai/event/events/network/ServerPacketReceivedEvent.java
@@ -1,12 +1,16 @@
package net.mamoe.mirai.event.events.network;
-import net.mamoe.mirai.event.events.Cancellable;
+import net.mamoe.mirai.event.Cancellable;
import net.mamoe.mirai.network.packet.ServerPacket;
+import net.mamoe.mirai.network.packet.ServerVerificationCodePacket;
/**
+ * 服务器接到某数据包时触发这个事件.
+ * 注意, 当接收到数据包的加密包(如 {@link ServerVerificationCodePacket.Encrypted})也会触发这个事件, 随后才会
+ *
* @author Him188moe
*/
-public class ServerPacketReceivedEvent extends ServerPacketEvent implements Cancellable {
+public final class ServerPacketReceivedEvent extends ServerPacketEvent implements Cancellable {
public ServerPacketReceivedEvent(ServerPacket packet) {
super(packet);
}
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/event/events/robot/RobotEvent.java b/mirai-core/src/main/java/net/mamoe/mirai/event/events/robot/RobotEvent.java
index ab410af4a..70d85ed78 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/event/events/robot/RobotEvent.java
+++ b/mirai-core/src/main/java/net/mamoe/mirai/event/events/robot/RobotEvent.java
@@ -1,7 +1,7 @@
package net.mamoe.mirai.event.events.robot;
import net.mamoe.mirai.Robot;
-import net.mamoe.mirai.event.events.MiraiEvent;
+import net.mamoe.mirai.event.MiraiEvent;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/event/events/robot/RobotEvents.kt b/mirai-core/src/main/java/net/mamoe/mirai/event/events/robot/RobotEvents.kt
index 737c47d58..9b452b1fd 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/event/events/robot/RobotEvents.kt
+++ b/mirai-core/src/main/java/net/mamoe/mirai/event/events/robot/RobotEvents.kt
@@ -1,7 +1,7 @@
package net.mamoe.mirai.event.events.robot
import net.mamoe.mirai.Robot
-import net.mamoe.mirai.event.events.MiraiEvent
+import net.mamoe.mirai.event.MiraiEvent
/**
* @author Him188moe
@@ -16,4 +16,3 @@ class RobotMessageReceivedEvent(val robot: Robot, val type: Type, val message: S
GROUP
}
}
-
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/event/events/robot/RobotLoginSucceedEvent.java b/mirai-core/src/main/java/net/mamoe/mirai/event/events/robot/RobotLoginSucceedEvent.java
index 15151ea91..a49d5f213 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/event/events/robot/RobotLoginSucceedEvent.java
+++ b/mirai-core/src/main/java/net/mamoe/mirai/event/events/robot/RobotLoginSucceedEvent.java
@@ -7,5 +7,4 @@ public final class RobotLoginSucceedEvent extends RobotEvent {
public RobotLoginSucceedEvent(Robot robot) {
super(robot);
}
-
}
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/event/events/server/ServerDisableEvent.java b/mirai-core/src/main/java/net/mamoe/mirai/event/events/server/ServerDisableEvent.java
deleted file mode 100644
index dd0be1c57..000000000
--- a/mirai-core/src/main/java/net/mamoe/mirai/event/events/server/ServerDisableEvent.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package net.mamoe.mirai.event.events.server;
-
-import net.mamoe.mirai.event.events.MiraiEvent;
-
-public final class ServerDisableEvent extends MiraiEvent {
-
-}
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/event/events/server/ServerDisabledEvent.java b/mirai-core/src/main/java/net/mamoe/mirai/event/events/server/ServerDisabledEvent.java
new file mode 100644
index 000000000..294498f1d
--- /dev/null
+++ b/mirai-core/src/main/java/net/mamoe/mirai/event/events/server/ServerDisabledEvent.java
@@ -0,0 +1,8 @@
+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 {
+
+}
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/event/events/server/ServerEnableEvent.java b/mirai-core/src/main/java/net/mamoe/mirai/event/events/server/ServerEnableEvent.java
deleted file mode 100644
index 18aeefccf..000000000
--- a/mirai-core/src/main/java/net/mamoe/mirai/event/events/server/ServerEnableEvent.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package net.mamoe.mirai.event.events.server;
-
-import net.mamoe.mirai.event.events.MiraiEvent;
-
-public final class ServerEnableEvent extends MiraiEvent {
-
-
-}
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/event/events/server/ServerEnabledEvent.java b/mirai-core/src/main/java/net/mamoe/mirai/event/events/server/ServerEnabledEvent.java
new file mode 100644
index 000000000..83b4772b9
--- /dev/null
+++ b/mirai-core/src/main/java/net/mamoe/mirai/event/events/server/ServerEnabledEvent.java
@@ -0,0 +1,9 @@
+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 {
+
+
+}
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/message/Message.java b/mirai-core/src/main/java/net/mamoe/mirai/message/Message.java
index e56f328b6..16954515c 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/message/Message.java
+++ b/mirai-core/src/main/java/net/mamoe/mirai/message/Message.java
@@ -1,7 +1,9 @@
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 org.jetbrains.annotations.NotNull;
@@ -11,7 +13,12 @@ import java.io.File;
import java.util.Objects;
/**
+ * 可发送的或从服务器接收的消息.
+ * 采用这样的消息模式是因为 QQ 的消息多元化, 一条消息中可包含 {@linkplain PlainText 纯文本}, {@linkplain Image 图片} 等.
+ *
* @author Him188moe
+ * @see Contact#sendMessage(Message) 发送这个消息
+ * @see MessageKt 若你使用 kotlin, 请查看针对 kotlin 的优化实现
*/
public abstract class Message {
@Override
@@ -38,7 +45,7 @@ public abstract class Message {
return new MessageChain(this, Objects.requireNonNull(tail));
}
- public Message concat(String tail) {
+ public final Message concat(String tail) {
return concat(new PlainText(tail));
}
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/message/MessageKt.kt b/mirai-core/src/main/java/net/mamoe/mirai/message/MessageKt.kt
index 6ae5be4b9..0257cbf57 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/message/MessageKt.kt
+++ b/mirai-core/src/main/java/net/mamoe/mirai/message/MessageKt.kt
@@ -1,3 +1,5 @@
+@file:JvmName("MessageKt")
+
package net.mamoe.mirai.message
import net.mamoe.mirai.message.defaults.PlainText
@@ -12,4 +14,7 @@ infix operator fun Message.plus(another: Message): Message = this.concat(another
*/
infix operator fun Message.plus(another: String): Message = this.concat(another)
+/**
+ * 连接 [String] 与 [Message]
+ */
infix fun String.concat(another: Message): Message = PlainText(this).concat(another)
\ No newline at end of file
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/message/defaults/At.java b/mirai-core/src/main/java/net/mamoe/mirai/message/defaults/At.java
index d552e53c4..dbae4f45a 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/message/defaults/At.java
+++ b/mirai-core/src/main/java/net/mamoe/mirai/message/defaults/At.java
@@ -7,6 +7,8 @@ import org.jetbrains.annotations.NotNull;
import java.util.Objects;
/**
+ * At 一个人的消息.
+ *
* @author Him188moe
*/
public final class At extends Message {
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/RobotNetworkHandler.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/RobotNetworkHandler.kt
index 22081cc11..52f5e056b 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/network/RobotNetworkHandler.kt
+++ b/mirai-core/src/main/java/net/mamoe/mirai/network/RobotNetworkHandler.kt
@@ -1,3 +1,5 @@
+@file:JvmMultifileClass
+@file:JvmName("RobotNetworkHandler")
package net.mamoe.mirai.network
import net.mamoe.mirai.Robot
@@ -8,6 +10,7 @@ import net.mamoe.mirai.event.events.qq.FriendMessageEvent
import net.mamoe.mirai.event.events.robot.RobotLoginSucceedEvent
import net.mamoe.mirai.event.hookWhile
import net.mamoe.mirai.message.Message
+import net.mamoe.mirai.network.RobotNetworkHandler.*
import net.mamoe.mirai.network.packet.*
import net.mamoe.mirai.network.packet.action.ServerSendFriendMessageResponsePacket
import net.mamoe.mirai.network.packet.action.ServerSendGroupMessageResponsePacket
@@ -19,17 +22,33 @@ import java.net.DatagramPacket
import java.net.DatagramSocket
import java.net.InetSocketAddress
import java.util.*
+import java.util.concurrent.CompletableFuture
import java.util.concurrent.ScheduledFuture
import java.util.concurrent.TimeUnit
+import java.util.concurrent.TimeoutException
import kotlin.reflect.KClass
+
/**
+ * Mirai 的网络处理器, 它处理所有数据包([Packet])的发送和接收.
+ * [RobotNetworkHandler] 是全程异步和线程安全的.
+ *
+ * [RobotNetworkHandler] 由 2 个模块构成:
+ * - [SocketHandler]: 处理数据包底层的发送([ByteArray])
+ * - [PacketHandler]: 制作 [Packet] 并传递给 [SocketHandler] 继续处理; 分析来自服务器的数据包并处理
+ *
+ * 其中, [PacketHandler] 由 4 个子模块构成:
+ * - [DebugHandler] 输出 [Packet.toString]
+ * - [LoginHandler] 处理 touch/login/verification code 相关
+ * - [MessageHandler] 处理消息相关(群消息/好友消息)([ServerEventPacket])
+ * - [ActionHandler] 处理动作相关(踢人/加入群/好友列表等)
+ *
* A RobotNetworkHandler is used to connect with Tencent servers.
*
* @author Him188moe
*/
@Suppress("EXPERIMENTAL_API_USAGE")//to simplify code
-internal class RobotNetworkHandler(private val robot: Robot) : Closeable {
+class RobotNetworkHandler(private val robot: Robot) : Closeable {
private val socketHandler: SocketHandler = SocketHandler()
val debugHandler = DebugHandler()
@@ -44,9 +63,6 @@ internal class RobotNetworkHandler(private val robot: Robot) : Closeable {
ActionHandler::class to actionHandler
)
- private var closed: Boolean = false
-
-
/**
* Not async
*/
@@ -65,30 +81,49 @@ internal class RobotNetworkHandler(private val robot: Robot) : Closeable {
//private | internal
+ internal fun tryLogin(): CompletableFuture = this.tryLogin(500, TimeUnit.MILLISECONDS)
+
+
/**
* 仅当 [LoginState] 非 [LoginState.UNKNOWN] 且非 [LoginState.TIMEOUT] 才会调用 [loginHook].
* 如果要输入验证码, 那么会以参数 [LoginState.VERIFICATION_CODE] 调用 [loginHandler], 登录完成后再以 [LoginState.SUCCEED] 调用 [loginHandler]
+ *
+ * @param connectingTimeout 连接每个服务器的 timeout
*/
- internal fun tryLogin(loginHook: (Robot.(LoginState) -> Unit)? = null) {
+ internal fun tryLogin(connectingTimeout: Long, unit: TimeUnit = TimeUnit.MILLISECONDS): CompletableFuture {
val ipQueue: LinkedList = LinkedList(Protocol.SERVER_IP)
- fun login(): Boolean {
+ val future = CompletableFuture()
+
+ fun login() {
val ip = ipQueue.poll()
- return if (ip != null) {
- this@RobotNetworkHandler.socketHandler.touch(ip) { state ->
- if (state == LoginState.UNKNOWN || state == LoginState.TIMEOUT) {
- login()
- } else {
- if (loginHook != null) {
- robot.loginHook(state)
+ if (ip != null) {
+ // val future = this@RobotNetworkHandler.socketHandler.touch(ip)
+
+ this@RobotNetworkHandler.socketHandler.touch(ip).runCatching {
+ this@runCatching.get(connectingTimeout, unit).let { state ->
+ if (state == LoginState.UNKNOWN) {
+ login()
+ } else {
+ future.complete(state)
}
}
+ }.onFailure {
+ when (it) {
+ is TimeoutException -> login()
+ else -> throw it
+ }
}
- true
- } else false
+ } else {
+ future.complete(LoginState.UNKNOWN)//所有服务器均返回 UNKNOWN
+ }
}
login()
+ return future
}
+ /**
+ * 分配收到的数据包
+ */
@ExperimentalUnsignedTypes
internal fun distributePacket(packet: ServerPacket) {
packet.decode()
@@ -112,14 +147,7 @@ internal class RobotNetworkHandler(private val robot: Robot) : Closeable {
restartSocket()
}
- private var loginHook: ((LoginState) -> Unit)? = null
- internal var loginState: LoginState? = null
- set(value) {
- field = value
- if (value != null) {
- loginHook?.invoke(value)
- }
- }
+ internal var loginFuture: CompletableFuture? = null
private fun restartSocket() {
socket?.close()
@@ -151,17 +179,14 @@ internal class RobotNetworkHandler(private val robot: Robot) : Closeable {
/**
* Start network and touch the server
*/
- internal fun touch(serverAddress: String, loginHook: ((LoginState) -> Unit)? = null) {
+ internal fun touch(serverAddress: String): CompletableFuture {
MiraiLogger.info("Connecting server: $serverAddress")
+ this.loginFuture = CompletableFuture()
+
socketHandler.serverIP = serverAddress
- if (loginHook != null) {
- this.loginHook = loginHook
- }
sendPacket(ClientTouchPacket(robot.account.qqNumber, socketHandler.serverIP))
- waitForPacket(ServerTouchResponsePacket::class, 100) {
- MiraiLogger.error(" Timeout")
- loginHook?.invoke(LoginState.TIMEOUT)
- }
+
+ return this.loginFuture!!
}
/**
@@ -209,8 +234,12 @@ internal class RobotNetworkHandler(private val robot: Robot) : Closeable {
override fun close() {
this.socket?.close()
- this.loginState = null
- this.loginHook = null
+ if (this.loginFuture != null) {
+ if (!this.loginFuture!!.isDone) {
+ this.loginFuture!!.cancel(true)
+ }
+ this.loginFuture = null
+ }
}
}
@@ -286,8 +315,7 @@ internal class RobotNetworkHandler(private val robot: Robot) : Closeable {
}
is ServerLoginResponseFailedPacket -> {
- socketHandler.loginState = packet.loginState
- MiraiLogger error "Login failed: " + packet.loginState.toString()
+ socketHandler.loginFuture!!.complete(packet.loginState)
return
}
@@ -309,8 +337,6 @@ internal class RobotNetworkHandler(private val robot: Robot) : Closeable {
}
is ServerVerificationCodeTransmissionPacket -> {
- socketHandler.loginState = LoginState.VERIFICATION_CODE
-
this.verificationCodeSequence++
this.verificationCodeCache = this.verificationCodeCache!! + packet.verificationCodePartN
@@ -391,7 +417,7 @@ internal class RobotNetworkHandler(private val robot: Robot) : Closeable {
}
is ServerLoginSuccessPacket -> {
- socketHandler.loginState = LoginState.SUCCEED
+ socketHandler.loginFuture!!.complete(LoginState.SUCCEED)
sendPacket(ClientSKeyRequestPacket(robot.account.qqNumber, sessionKey))
}
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerPacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerPacket.kt
index 395b92e56..4e54a750b 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerPacket.kt
+++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/ServerPacket.kt
@@ -46,8 +46,8 @@ abstract class ServerPacket(val input: DataInputStream) : Packet {
}
return ServerLoginResponseFailedPacket(when (bytes.size) {
- 319 -> LoginState.WRONG_PASSWORD
- 135 -> LoginState.RETYPE_PASSWORD
+ 319, 135 -> LoginState.WRONG_PASSWORD
+ //135 -> LoginState.RETYPE_PASSWORD
279 -> LoginState.BLOCKED
263 -> LoginState.UNKNOWN_QQ_NUMBER
551, 487 -> LoginState.DEVICE_LOCK
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/VerificationCode.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/VerificationCode.kt
index 5f4b6bdae..3abf7a2f2 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/VerificationCode.kt
+++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/VerificationCode.kt
@@ -4,7 +4,6 @@ import net.mamoe.mirai.network.Protocol
import net.mamoe.mirai.utils.*
import java.io.DataInputStream
-
/**
* 客户端请求验证码图片数据的第几部分
*/
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/LoginState.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/LoginState.kt
index c2168c03c..482c057a9 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/LoginState.kt
+++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/login/LoginState.kt
@@ -4,20 +4,43 @@ package net.mamoe.mirai.network.packet.login
* @author Him188moe
*/
enum class LoginState {
+ /**
+ * 登录成功
+ */
SUCCEED,
+ /**
+ * 密码错误
+ */
WRONG_PASSWORD,
- // UNKNOWN,//? 要再次发送某数据包
- RETYPE_PASSWORD,//similar to [WRONG_PASSWORD]
- BLOCKED,//你的帐号存在被盗风险,已进入保护模式
- UNKNOWN_QQ_NUMBER,//你输入的帐号不存在
- DEVICE_LOCK,//设备锁
- TAKEN_BACK,//被回收
+ /**
+ * 被冻结
+ */
+ BLOCKED,
- VERIFICATION_CODE,//需要验证码
+ /**
+ * QQ 号码输入有误
+ */
+ UNKNOWN_QQ_NUMBER,
+ /**
+ * 账号开启了设备锁. 暂不支持设备锁登录
+ */
+ DEVICE_LOCK,
+ /**
+ * 账号被回收
+ */
+ TAKEN_BACK,
+
+ /**
+ * 需要验证码登录
+ */
+ VERIFICATION_CODE,
+
+ /**
+ * 未知. 更换服务器或等几分钟再登录可能解决.
+ */
UNKNOWN,
- TIMEOUT,
}
\ No newline at end of file
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/plugin/MiraiPluginBase.java b/mirai-core/src/main/java/net/mamoe/mirai/plugin/MiraiPluginBase.java
index 085ee1aab..8bec23692 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/plugin/MiraiPluginBase.java
+++ b/mirai-core/src/main/java/net/mamoe/mirai/plugin/MiraiPluginBase.java
@@ -1,4 +1,14 @@
package net.mamoe.mirai.plugin;
-public class MiraiPluginBase {
+import net.mamoe.mirai.Robot;
+
+/**
+ * 插件基类.
+ *
+ * 插件属于整个 Mirai, 而不是属于单个 {@link Robot}.
+ *
+ * @see net.mamoe.mirai.event.MiraiEventManager
+ * @see net.mamoe.mirai.event.MiraiEventManagerKt
+ */
+public abstract class MiraiPluginBase {
}
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/task/MiraiTaskManager.java b/mirai-core/src/main/java/net/mamoe/mirai/task/MiraiTaskManager.java
index 1f623387d..4e950374b 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/task/MiraiTaskManager.java
+++ b/mirai-core/src/main/java/net/mamoe/mirai/task/MiraiTaskManager.java
@@ -2,7 +2,7 @@ package net.mamoe.mirai.task;
import net.mamoe.mirai.event.MiraiEventHook;
-import net.mamoe.mirai.event.events.server.ServerDisableEvent;
+import net.mamoe.mirai.event.events.server.ServerDisabledEvent;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
@@ -24,7 +24,7 @@ public final class MiraiTaskManager {
this.pool = new MiraiThreadPool();
MiraiEventHook
- .onEvent(ServerDisableEvent.class)
+ .onEvent(ServerDisabledEvent.class)
.handler(a -> this.pool.close())
.mount();
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/utils/setting/MiraiSetting.java b/mirai-core/src/main/java/net/mamoe/mirai/utils/setting/MiraiSettings.java
similarity index 83%
rename from mirai-core/src/main/java/net/mamoe/mirai/utils/setting/MiraiSetting.java
rename to mirai-core/src/main/java/net/mamoe/mirai/utils/setting/MiraiSettings.java
index 851cdd862..7eaa08cb7 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/utils/setting/MiraiSetting.java
+++ b/mirai-core/src/main/java/net/mamoe/mirai/utils/setting/MiraiSettings.java
@@ -1,5 +1,6 @@
package net.mamoe.mirai.utils.setting;
+import net.mamoe.mirai.plugin.MiraiPluginBase;
import org.ini4j.Config;
import org.ini4j.Ini;
@@ -15,7 +16,7 @@ import java.util.concurrent.ConcurrentHashMap;
* Only supports INI
format
* Supports {@link Map} and {@link List}
*/
-public class MiraiSetting {
+public class MiraiSettings {
private File file;
@@ -23,14 +24,21 @@ public class MiraiSetting {
private volatile Map cacheSection = new ConcurrentHashMap<>();
- public MiraiSetting(File file){
+ public MiraiSettings(MiraiPluginBase pluginBase, String filename) {
+ // TODO: 2019/9/6 每个插件独立文件夹存放
+ this(new File(filename));
+ }
+
+ public MiraiSettings(File file) {
if(!file.getName().contains(".")){
- file = new File(file.getParent() + file.getName() + ".ini");
+ file = new File(file.getPath() + ".ini");
}
this.file = file;
try {
if(file.exists()){
- file.createNewFile();
+ if (!file.createNewFile()) {
+ throw new RuntimeException("cannot create config file " + file);
+ }
}
Config config = new Config();
config.setMultiSection(true);
diff --git a/mirai-core/src/test/java/BadQQFilter.kt b/mirai-core/src/test/java/BadQQFilter.kt
index 22114508e..7cac454e1 100644
--- a/mirai-core/src/test/java/BadQQFilter.kt
+++ b/mirai-core/src/test/java/BadQQFilter.kt
@@ -107,14 +107,16 @@ fun main() {
qqList.split("\n").forEach {
GlobalScope.launch {
val strings = it.split("----")
- Robot(RobotAccount(strings[0].toLong(), strings[1].let { password ->
+ val robot = Robot(RobotAccount(strings[0].toLong(), strings[1].let { password ->
if (password.endsWith(".")) {
return@let password.substring(0, password.length - 1)
}
return@let password
- }), listOf()).network.tryLogin { state ->
+ }), listOf())
+
+ robot.network.tryLogin().whenComplete { state, _ ->
if (!(state == LoginState.BLOCKED || state == LoginState.DEVICE_LOCK || state == LoginState.WRONG_PASSWORD)) {
- goodRobotList.add(this)
+ goodRobotList.add(robot)
}
}
}