mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-04 08:59:51 +08:00
Updated events and KDocs
This commit is contained in:
parent
402e8fbb32
commit
305a7a6f73
@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
@ -13,6 +13,21 @@ import java.io.Closeable;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Mirai 的机器人. 一个机器人实例登录一个 QQ 账号.
|
||||
* Mirai 为多账号设计, 可同时维护多个机器人账号.
|
||||
* <br>
|
||||
* {@link Robot} 由 2 个模块组成.
|
||||
* {@linkplain ContactSystem 联系人管理}: 可通过 {@link Robot#contacts} 访问
|
||||
* {@linkplain RobotNetworkHandler 网络处理器}: 可通过 {@link Robot#network} 访问
|
||||
* <br>
|
||||
* 另外地, 若你需要得到机器人的 QQ 账号, 请访问 {@link Robot#account}
|
||||
* 若你需要得到服务器上所有机器人列表, 请访问 {@link Robot#instances}
|
||||
*
|
||||
* @author Him188moe
|
||||
* @author NatrualHG
|
||||
* @see net.mamoe.mirai.contact.Contact
|
||||
*
|
||||
* <p>
|
||||
* Robot that is the base of the whole program.
|
||||
* It contains a {@link ContactSystem}, which manage contacts such as {@link QQ} and {@link Group}.
|
||||
*/
|
||||
|
@ -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)
|
||||
|
@ -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 <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);
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
@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<out AsyncEvent> {
|
||||
return MiraiEventManager.getInstance().broadcastEventAsync(this, callback)
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package net.mamoe.mirai.event.events;
|
||||
package net.mamoe.mirai.event;
|
||||
|
||||
/**
|
||||
* @author NaturalHG
|
@ -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;
|
||||
}
|
||||
}
|
@ -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<T extends MiraiEvent> implements Closeable {
|
||||
|
||||
@Getter
|
||||
Class<T> eventClass;
|
||||
|
||||
@Getter
|
||||
private volatile Consumer<T> handler;
|
||||
protected volatile Consumer<T> handler;
|
||||
|
||||
@Getter
|
||||
private volatile int priority = 0;
|
||||
@ -31,7 +32,7 @@ public class MiraiEventHook<T extends MiraiEvent> implements Closeable {
|
||||
* return true -> this hook need to be removed
|
||||
*/
|
||||
@Getter
|
||||
private Predicate<T> valid;
|
||||
protected Predicate<T> validChecker;
|
||||
|
||||
public MiraiEventHook(Class<T> eventClass) {
|
||||
this(eventClass,null);
|
||||
@ -58,26 +59,26 @@ public class MiraiEventHook<T extends MiraiEvent> implements Closeable {
|
||||
}
|
||||
|
||||
|
||||
private MiraiEventHook<T> setValid(Predicate<T> valid) {
|
||||
this.valid = valid;
|
||||
private MiraiEventHook<T> setValidChecker(Predicate<T> validChecker) {
|
||||
this.validChecker = validChecker;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MiraiEventHook<T> setValidUntil(Predicate<T> valid) {
|
||||
return this.setValid(valid);
|
||||
return this.setValidChecker(valid);
|
||||
}
|
||||
|
||||
public MiraiEventHook<T> setValidWhile(Predicate<T> 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<T extends MiraiEvent> implements Closeable {
|
||||
@Override
|
||||
public void close(){
|
||||
this.handler = null;
|
||||
this.valid = null;
|
||||
this.validChecker = null;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,31 @@
|
||||
package net.mamoe.mirai.event
|
||||
|
||||
import java.util.function.Consumer
|
||||
import java.util.function.Predicate
|
||||
|
||||
/**
|
||||
* @author Him188moe
|
||||
*/
|
||||
class MiraiEventHookKt<E : MiraiEvent>(eventClass: Class<E>) : MiraiEventHook<E>(eventClass) {
|
||||
fun onEvent(handler: (E) -> Unit) {
|
||||
this@MiraiEventHookKt.handler = Consumer(handler)
|
||||
}
|
||||
|
||||
fun validChecker(predicate: (E) -> Boolean) {
|
||||
this@MiraiEventHookKt.validChecker = Predicate(predicate)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Kotlin 风格回调
|
||||
* 你的代码可以这样(并且 validChecker 是可选的):
|
||||
*
|
||||
* event.hook {
|
||||
* onEvent {}
|
||||
* validChecker {}
|
||||
* }
|
||||
*/
|
||||
fun <E : MiraiEvent> E.hook(handler: MiraiEventHookKt<E>.() -> Unit): MiraiEventHookKt<E> {
|
||||
return MiraiEventHookKt(this.javaClass).apply(handler)
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
@file:JvmName("MiraiEventKt")
|
||||
|
||||
package net.mamoe.mirai.event
|
||||
|
||||
fun <E : MiraiEvent> E.broadcast(): E {
|
||||
MiraiEventManager.getInstance().broadcastEvent(this as MiraiEvent)
|
||||
return this
|
||||
}
|
@ -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 <E extends AsyncEvent> CompletableFuture<E> broadcastEventAsync(E event) {
|
||||
Objects.requireNonNull(event);
|
||||
if (!(event instanceof MiraiEvent)) {
|
||||
throw new IllegalArgumentException("event must be instanceof MiraiEvent");
|
||||
}
|
||||
|
||||
public <D extends MiraiEvent> void asyncBroadcastEvent(D event, Consumer<D> callback) {
|
||||
MiraiServer.getInstance().getTaskManager().ansycTask(() -> {
|
||||
MiraiEventManager.this.broadcastEvent(event);
|
||||
CompletableFuture<E> future = new CompletableFuture<>();
|
||||
future.completeAsync(() -> {
|
||||
MiraiEventManager.this.broadcastEvent((MiraiEvent) event);
|
||||
return event;
|
||||
}, callback);
|
||||
});
|
||||
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 MiraiEvent> void asyncBroadcastEvent(D event, Runnable callback) {
|
||||
asyncBroadcastEvent(event, t -> callback.run());
|
||||
public <D extends AsyncEvent> CompletableFuture<D> broadcastEventAsync(D event, Runnable callback) {
|
||||
return broadcastEventAsync(event, t -> callback.run());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -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 <C : Class<E>, E : MiraiEvent> C.hookAlways(hook: (E) -> Unit) {
|
||||
MiraiEventManager.getInstance().hookAlways(MiraiEventHook<E>(this, hook))
|
||||
}
|
||||
|
||||
/**
|
||||
* 当下一次事件触发时调用 hook
|
||||
*/
|
||||
fun <C : Class<E>, E : MiraiEvent> C.hookOnce(hook: (E) -> Unit) {
|
||||
MiraiEventManager.getInstance().hookOnce(MiraiEventHook<E>(this, hook))
|
||||
}
|
||||
|
||||
/**
|
||||
* 每次事件触发时都会调用 hook, 直到 hook 返回 false 时停止 hook
|
||||
*/
|
||||
fun <C : Class<E>, E : MiraiEvent> C.hookWhile(hook: (E) -> Boolean) {
|
||||
MiraiEventManager.getInstance().hookAlways(MiraiEventHookSimple<E>(this, hook))
|
||||
MiraiEventManager.getInstance().hookAlways(MiraiEventHookSimple(this, hook))
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 每次事件触发时都会调用 hook
|
||||
*/
|
||||
fun <C : KClass<E>, E : MiraiEvent> C.hookAlways(hook: (E) -> Unit) {
|
||||
this.java.hookAlways(hook)
|
||||
}
|
||||
|
||||
/**
|
||||
* 当下一次事件触发时调用 hook
|
||||
*/
|
||||
fun <C : KClass<E>, E : MiraiEvent> C.hookOnce(hook: (E) -> Unit) {
|
||||
this.java.hookOnce(hook)
|
||||
}
|
||||
|
||||
/**
|
||||
* 每次事件触发时都会调用 hook, 直到 hook 返回 false 时停止 hook
|
||||
*/
|
||||
fun <C : KClass<E>, E : MiraiEvent> C.hookWhile(hook: (E) -> Boolean) {
|
||||
this.java.hookWhile(hook)
|
||||
}
|
@ -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 <D extends MiraiEvent> void asyncBroadcast(Consumer<D> callback) {
|
||||
MiraiEventManager.getInstance().asyncBroadcastEvent((D) this, callback);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public final <D extends MiraiEvent> void asyncBroadcast(Runnable callback) {
|
||||
MiraiEventManager.getInstance().asyncBroadcastEvent((D) this, callback);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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() {
|
||||
|
@ -1,7 +0,0 @@
|
||||
package net.mamoe.mirai.event.events.network;
|
||||
|
||||
/**
|
||||
* @author Him188moe
|
||||
*/
|
||||
public class PacketReceivedEvent {
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,5 +7,4 @@ public final class RobotLoginSucceedEvent extends RobotEvent {
|
||||
public RobotLoginSucceedEvent(Robot robot) {
|
||||
super(robot);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,7 +0,0 @@
|
||||
package net.mamoe.mirai.event.events.server;
|
||||
|
||||
import net.mamoe.mirai.event.events.MiraiEvent;
|
||||
|
||||
public final class ServerDisableEvent extends MiraiEvent {
|
||||
|
||||
}
|
@ -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 {
|
||||
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
package net.mamoe.mirai.event.events.server;
|
||||
|
||||
import net.mamoe.mirai.event.events.MiraiEvent;
|
||||
|
||||
public final class ServerEnableEvent extends MiraiEvent {
|
||||
|
||||
|
||||
}
|
@ -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 {
|
||||
|
||||
|
||||
}
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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)
|
@ -7,6 +7,8 @@ import org.jetbrains.annotations.NotNull;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* At 一个人的消息.
|
||||
*
|
||||
* @author Him188moe
|
||||
*/
|
||||
public final class At extends Message {
|
||||
|
@ -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<LoginState> = 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<LoginState> {
|
||||
val ipQueue: LinkedList<String> = LinkedList(Protocol.SERVER_IP)
|
||||
fun login(): Boolean {
|
||||
val future = CompletableFuture<LoginState>()
|
||||
|
||||
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<LoginState>? = 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<LoginState> {
|
||||
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))
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -4,7 +4,6 @@ import net.mamoe.mirai.network.Protocol
|
||||
import net.mamoe.mirai.utils.*
|
||||
import java.io.DataInputStream
|
||||
|
||||
|
||||
/**
|
||||
* 客户端请求验证码图片数据的第几部分
|
||||
*/
|
||||
|
@ -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,
|
||||
}
|
@ -1,4 +1,14 @@
|
||||
package net.mamoe.mirai.plugin;
|
||||
|
||||
public class MiraiPluginBase {
|
||||
import net.mamoe.mirai.Robot;
|
||||
|
||||
/**
|
||||
* 插件基类.
|
||||
* <p>
|
||||
* 插件属于整个 Mirai, 而不是属于单个 {@link Robot}.
|
||||
*
|
||||
* @see net.mamoe.mirai.event.MiraiEventManager
|
||||
* @see net.mamoe.mirai.event.MiraiEventManagerKt
|
||||
*/
|
||||
public abstract class MiraiPluginBase {
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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 <code>INI</code> format <br>
|
||||
* 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<String, MiraiSettingSection> cacheSection = new ConcurrentHashMap<>();
|
||||
|
||||
public MiraiSetting(File file){
|
||||
public MiraiSettings(MiraiPluginBase pluginBase, String filename) {
|
||||
// TODO: 2019/9/6 每个插件独立文件夹存放
|
||||
this(new File(filename));
|
||||
}
|
||||
|
||||
public MiraiSettings(File file) {
|
||||
if(!file.getName().contains(".")){
|
||||
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);
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user