diff --git a/pom.xml b/pom.xml
index 802b66b..45adce3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -31,9 +31,9 @@
9+181-r4173-1
1.6.0
native-mt
- 1.3.1
- 1.1.17
- 1.1.6
+ 1.3.2
+ 1.1.18
+ 1.2.2
1.0.2
1.1.0
diff --git a/src/main/java/top/focess/qq/FocessQQ.java b/src/main/java/top/focess/qq/FocessQQ.java
index cc61fd1..ce5d8bd 100755
--- a/src/main/java/top/focess/qq/FocessQQ.java
+++ b/src/main/java/top/focess/qq/FocessQQ.java
@@ -55,8 +55,6 @@
import top.focess.qq.core.plugin.PluginCoreClassLoader;
import top.focess.qq.core.util.FocessSecurityManager;
import top.focess.qq.core.util.MethodCaller;
-import top.focess.scheduler.FocessScheduler;
-import top.focess.scheduler.Scheduler;
import top.focess.scheduler.Task;
import top.focess.util.Pair;
import top.focess.util.option.Option;
@@ -73,7 +71,6 @@
import java.io.FileInputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
-import java.time.Duration;
import java.util.*;
import java.util.concurrent.Future;
import java.util.zip.GZIPOutputStream;
@@ -107,7 +104,6 @@ public class FocessQQ {
* The Focess Logger
*/
private static final FocessLogger LOGGER = new FocessLogger();
- private static final Scheduler SCHEDULER = new FocessScheduler("FocessQQ");
private static final Scanner SCANNER = new Scanner(System.in);
private static final Thread CONSOLE_INPUT_THREAD = new Thread(() -> {
@@ -561,12 +557,6 @@ public static void exit() {
return;
isStopped = true;
}
- SCHEDULER.run(() -> {
- try {
- getLogger().fatalLang("fatal-exit-failed");
- } catch (final Exception ignored) {}
- System.exit(0);
- }, Duration.ofSeconds(5), "force-exit");
Runtime.getRuntime().removeShutdownHook(SHUTDOWN_HOOK);
// need to check if Exit is called by Initialization
if (MAIN_PLUGIN != null && MAIN_PLUGIN.isEnabled())
@@ -578,7 +568,6 @@ public static void exit() {
getUdpSocket().close();
// make sure scheduler is stopped at the end
Schedulers.closeAll();
- SCHEDULER.close();
if (!saved) {
saveLogFile();
saved = true;
@@ -586,14 +575,15 @@ public static void exit() {
CONSOLE_INPUT_THREAD.interrupt();
Thread thread = new Thread(() -> {
try {
- Thread.sleep(10000);
+ Thread.sleep(5000);
} catch (InterruptedException ignored) {
}
- System.err.println("Force Shutdown");
+ System.out.println("Force Shutdown");
System.exit(0);
});
thread.setDaemon(true);
thread.start();
+ System.out.println("Wait for 5000ms to shut down.");
}
private static void saveLogFile() {
diff --git a/src/main/java/top/focess/qq/api/bot/BotManager.java b/src/main/java/top/focess/qq/api/bot/BotManager.java
index 60dc14a..599e0b7 100644
--- a/src/main/java/top/focess/qq/api/bot/BotManager.java
+++ b/src/main/java/top/focess/qq/api/bot/BotManager.java
@@ -34,7 +34,7 @@ public interface BotManager {
*/
@NotNull
default Future login(final long id, final String password, final Plugin plugin) {
- return this.login(id, password, plugin, BotProtocol.ANDROID_PAD);
+ return this.login(id, password, plugin, BotProtocol.MACOS);
}
/**
@@ -66,7 +66,7 @@ default Future login(final long id, final String password, final Plugin plu
*/
@NotNull
default Bot loginDirectly(final long id, final String password, final Plugin plugin) throws BotLoginException {
- return this.loginDirectly(id, password, plugin, BotProtocol.ANDROID_PAD);
+ return this.loginDirectly(id, password, plugin, BotProtocol.MACOS);
}
/**
diff --git a/src/main/java/top/focess/qq/api/scheduler/Schedulers.java b/src/main/java/top/focess/qq/api/scheduler/Schedulers.java
index 81e589e..981ca51 100644
--- a/src/main/java/top/focess/qq/api/scheduler/Schedulers.java
+++ b/src/main/java/top/focess/qq/api/scheduler/Schedulers.java
@@ -69,7 +69,6 @@ public static Scheduler newThreadPoolScheduler(@NotNull final Plugin plugin, fin
Permission.checkPermission(Permission.SCHEDULER);
final ThreadPoolScheduler scheduler = new ThreadPoolScheduler(plugin.getName(),poolSize);
scheduler.setThreadUncaughtExceptionHandler((t, e) -> FocessQQ.getLogger().thrLang("exception-thread-pool-scheduler-thread-uncaught", e, t.getName()));
- scheduler.setThreadCatchExceptionHandler((t, e) -> FocessQQ.getLogger().thrLang("exception-thread-pool-scheduler-thread", e));
return new AScheduler(plugin, scheduler);
}
@@ -91,7 +90,6 @@ public static Scheduler newThreadPoolScheduler(@NotNull final Plugin plugin, fin
Permission.checkPermission(Permission.SCHEDULER);
final ThreadPoolScheduler scheduler = new ThreadPoolScheduler(poolSize, immediate, name);
scheduler.setThreadUncaughtExceptionHandler((t, e) -> FocessQQ.getLogger().thrLang("exception-thread-pool-scheduler-thread-uncaught", e, t.getName()));
- scheduler.setThreadCatchExceptionHandler((t, e) -> FocessQQ.getLogger().thrLang("exception-thread-pool-scheduler-thread", e));
return new AScheduler(plugin,scheduler);
}
diff --git a/src/main/java/top/focess/qq/api/util/session/Session.java b/src/main/java/top/focess/qq/api/util/session/Session.java
index eb5e630..4bc47e9 100644
--- a/src/main/java/top/focess/qq/api/util/session/Session.java
+++ b/src/main/java/top/focess/qq/api/util/session/Session.java
@@ -29,7 +29,10 @@ public Session(@Nullable final Map values) {
@Override
public SessionSection createSection(final String key) {
final Map values = Maps.newHashMap();
- this.set(key, values);
+ final Plugin plugin = PluginCoreClassLoader.getPluginByClass(MethodCaller.getCallerClass());
+ if (plugin != null)
+ SectionMap.super.set(plugin.getName() + ":" + key, values);
+ else SectionMap.super.set(key, values);
return new SessionSection(this, values);
}
@@ -40,7 +43,11 @@ public Map getValues() {
@Override
public SectionMap getSection(final String key) {
- final Object value = this.get(key);
+ Object value;
+ final Plugin plugin = PluginCoreClassLoader.getPluginByClass(MethodCaller.getCallerClass());
+ if (plugin != null)
+ value = SectionMap.super.get(plugin.getName() + ":" + key);
+ else value = SectionMap.super.get(key);
if (value == null)
this.containsSection(key);
if (value instanceof Map)
@@ -50,7 +57,10 @@ public SectionMap getSection(final String key) {
@Override
public boolean containsSection(final String key) {
- return this.get(key) instanceof Map;
+ final Plugin plugin = PluginCoreClassLoader.getPluginByClass(MethodCaller.getCallerClass());
+ if (plugin != null)
+ return SectionMap.super.get(plugin.getName() + ":" + key) instanceof Map;
+ else return SectionMap.super.get(key) instanceof Map;
}
@Override
diff --git a/src/main/java/top/focess/qq/core/bot/mirai/MiraiBotManager.java b/src/main/java/top/focess/qq/core/bot/mirai/MiraiBotManager.java
index 9a58e95..25c8f80 100644
--- a/src/main/java/top/focess/qq/core/bot/mirai/MiraiBotManager.java
+++ b/src/main/java/top/focess/qq/core/bot/mirai/MiraiBotManager.java
@@ -3,11 +3,17 @@
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import kotlin.coroutines.Continuation;
+import kotlin.coroutines.CoroutineContext;
+import kotlin.coroutines.EmptyCoroutineContext;
import net.mamoe.mirai.BotFactory;
+import net.mamoe.mirai.auth.BotAuthorization;
+import net.mamoe.mirai.auth.QRCodeLoginListener;
import net.mamoe.mirai.contact.OtherClient;
import net.mamoe.mirai.event.Listener;
import net.mamoe.mirai.event.events.*;
import net.mamoe.mirai.utils.BotConfiguration;
+import net.mamoe.mirai.utils.DeviceVerificationRequests;
+import net.mamoe.mirai.utils.DeviceVerificationResult;
import net.mamoe.mirai.utils.LoginSolver;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -144,7 +150,7 @@ public Object onSolvePicCaptcha(@NotNull final net.mamoe.mirai.Bot bot, final by
}
FocessQQ.getLogger().infoLang("input-captcha-code");
try {
- return IOHandler.getConsoleIoHandler().inputMessage();
+ return IOHandler.getConsoleIoHandler().inputMessage().toString();
} catch (final InputTimeoutException e) {
return null;
}
@@ -155,10 +161,10 @@ public Object onSolvePicCaptcha(@NotNull final net.mamoe.mirai.Bot bot, final by
public Object onSolveSliderCaptcha(@NotNull final net.mamoe.mirai.Bot bot, @NotNull final String s, @NotNull final Continuation super String> continuation) {
FocessQQ.getLogger().info(s);
try {
- IOHandler.getConsoleIoHandler().inputMessage();
+ return IOHandler.getConsoleIoHandler().inputMessage().toString();
} catch (final InputTimeoutException ignored) {
+ return null;
}
- return null;
}
@Nullable
@@ -166,13 +172,83 @@ public Object onSolveSliderCaptcha(@NotNull final net.mamoe.mirai.Bot bot, @NotN
public Object onSolveUnsafeDeviceLoginVerify(@NotNull final net.mamoe.mirai.Bot bot, @NotNull final String s, @NotNull final Continuation super String> continuation) {
FocessQQ.getLogger().info(s);
try {
- IOHandler.getConsoleIoHandler().inputMessage();
+ return IOHandler.getConsoleIoHandler().inputMessage().toString();
} catch (final InputTimeoutException ignored) {
+ return null;
+ }
+ }
+
+ @Override
+ public @NotNull Object onSolveDeviceVerification(@NotNull net.mamoe.mirai.Bot bot, @NotNull DeviceVerificationRequests requests, @NotNull Continuation super DeviceVerificationResult> continuation) {
+ if (requests.getPreferSms()) {
+ FocessQQ.getLogger().info(requests.getSms().getCountryCode() + " " + requests.getSms().getPhoneNumber());
+ try {
+ IOHandler.getConsoleIoHandler().inputMessage();
+ } catch (final InputTimeoutException ignored) {
+ }
+
+ Object lock = new Object();
+ requests.getSms().requestSms(new Continuation<>() {
+ @Override
+ public @NotNull CoroutineContext getContext() {
+ return EmptyCoroutineContext.INSTANCE;
+ }
+
+ @Override
+ public void resumeWith(@NotNull Object result) {
+ synchronized (lock) {
+ lock.notify();
+ }
+ }
+ });
+ synchronized (lock) {
+ try {
+ lock.wait();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ String code;
+ try {
+ code = IOHandler.getConsoleIoHandler().inputMessage().toString();
+ } catch (final InputTimeoutException ignored) {
+ code = "";
+ }
+ return requests.getSms().solved(code);
+ } else {
+ FocessQQ.getLogger().info(requests.getFallback().getUrl());
+ try {
+ IOHandler.getConsoleIoHandler().inputMessage();
+ } catch (final InputTimeoutException ignored) {
+ }
+ return requests.getFallback().solved();
}
- return null;
+ }
+
+ @NotNull
+ @Override
+ public QRCodeLoginListener createQRCodeLoginListener(@NotNull net.mamoe.mirai.Bot bot) {
+ return new QRCodeLoginListener() {
+ @Override
+ public void onStateChanged(@NotNull net.mamoe.mirai.Bot bot, @NotNull QRCodeLoginListener.State state) {
+ FocessQQ.getLogger().infoLang("bot-login-qrcode-state", id, state.name());
+ }
+
+ @Override
+ public void onFetchQRCode(@NotNull net.mamoe.mirai.Bot bot, @NotNull byte[] bytes) {
+ System.out.println("????????");
+ try {
+ final FileImageOutputStream outputStream = new FileImageOutputStream(new File("qrcode.jpg"));
+ outputStream.write(bytes);
+ outputStream.close();
+ } catch (final IOException e) {
+ FocessQQ.getLogger().thrLang("exception-load-qrcode-picture", e);
+ }
+ }
+ };
}
});
- final net.mamoe.mirai.Bot bot = BotFactory.INSTANCE.newBot(id, password, configuration);
+ final net.mamoe.mirai.Bot bot = BotFactory.INSTANCE.newBot(id, password.equalsIgnoreCase("qr") ? BotAuthorization.byQRCode() : BotAuthorization.byPassword(password), configuration);
try {
bot.login();
} catch (final Exception e) {
diff --git a/src/main/java/top/focess/qq/core/commands/PermissionCommand.java b/src/main/java/top/focess/qq/core/commands/PermissionCommand.java
index 8dadfec..0eeaf2d 100644
--- a/src/main/java/top/focess/qq/core/commands/PermissionCommand.java
+++ b/src/main/java/top/focess/qq/core/commands/PermissionCommand.java
@@ -24,7 +24,7 @@ public void init() {
this.setExecutorPermission(i -> i.isAdministrator() || i.isConsole());
this.addExecutor((sender,data,ioHandler)->{
Plugin plugin = data.get(Plugin.class);
- if (plugin.getPluginDescription().getPermissions().size() == 0)
+ if (plugin.getPluginDescription().getPermissions().isEmpty())
ioHandler.outputLang("permission-command-no-permission",plugin.getName());
else {
StringBuilder stringBuilder = new StringBuilder();
diff --git a/src/main/java/top/focess/qq/core/scheduler/AScheduler.java b/src/main/java/top/focess/qq/core/scheduler/AScheduler.java
index 29ff9f9..e2319cd 100644
--- a/src/main/java/top/focess/qq/core/scheduler/AScheduler.java
+++ b/src/main/java/top/focess/qq/core/scheduler/AScheduler.java
@@ -9,7 +9,6 @@
import top.focess.qq.core.permission.Permission;
import top.focess.qq.core.permission.PermissionEnv;
import top.focess.scheduler.Callback;
-import top.focess.scheduler.CatchExceptionHandler;
import top.focess.scheduler.Scheduler;
import top.focess.scheduler.Task;
@@ -33,7 +32,6 @@ public AScheduler(final Plugin plugin, final Scheduler scheduler) {
this.plugin = plugin;
this.scheduler = scheduler;
this.scheduler.setUncaughtExceptionHandler((t, e) -> FocessQQ.getLogger().thrLang("exception-scheduler-uncaught", e, this.getName()));
- this.scheduler.setCatchExceptionHandler((t, e) -> FocessQQ.getLogger().thrLang("exception-scheduler", e, this.getName()));
PLUGIN_SCHEDULER_MAP.compute(plugin, (k, v) -> {
if (v == null)
v = Lists.newCopyOnWriteArrayList();
@@ -123,16 +121,6 @@ public Thread.UncaughtExceptionHandler getUncaughtExceptionHandler() {
return this.scheduler.getUncaughtExceptionHandler();
}
- @Override
- public @Nullable CatchExceptionHandler getCatchExceptionHandler() {
- return this.scheduler.getCatchExceptionHandler();
- }
-
- @Override
- public void setCatchExceptionHandler(final CatchExceptionHandler catchExceptionHandler) {
- this.scheduler.setCatchExceptionHandler(catchExceptionHandler);
- }
-
@Override
public @UnmodifiableView List getRemainingTasks() {
return this.scheduler.getRemainingTasks();
diff --git a/src/main/resources/lang.yml b/src/main/resources/lang.yml
index c781d4c..0fce2cc 100644
--- a/src/main/resources/lang.yml
+++ b/src/main/resources/lang.yml
@@ -47,6 +47,7 @@ exception-load-class: Load class exception
exception-load-plugin: Load plugin exception
exception-load-plugin-file: Load plugin file exception
exception-load-captcha-picture: Load captcha picture exception
+exception-load-qrcode-picture: Load qrcode picture exception
exception-reload-plugin: Reload plugin exception
exception-load-default-plugin: Load default plugin exception
exception-unload-default-plugin: Unload default plugin exception
@@ -157,7 +158,7 @@ friend-command-send-success: Send message to friend %d successfully
debug-command-debug-output-status: "Debug Output Status: %b"
pause-command-pause-mode-status: "Pause Mode Status: %b"
plugin-description-not-found: File plugin.yml not found
-unknown-command: Unknown command %s
+unknown-command: "Unknown command: %s"
command-exec: "%s exec: %s"
input-account-username: Please input account username
input-account-password: Please input account password
@@ -217,4 +218,5 @@ debug-cancel-event: "Cancel event: %s to %s"
permission-command-no-permission: "The plugin %s does not have permissions"
permission-command-list: "The plugin %s has the following permissions:%s"
permission-command-set-success: "The plugin %s set the permission %s successfully"
-permission-command-set-failed: "The plugin %s set the permission %s failed, it may already have the permission"
\ No newline at end of file
+permission-command-set-failed: "The plugin %s set the permission %s failed, it may already have the permission"
+bot-login-qrcode-state: "Bot %d login qrcode state: %s"
\ No newline at end of file
diff --git a/src/test/java/top/focess/qq/test/TestUtil.java b/src/test/java/top/focess/qq/test/TestUtil.java
index 33f3005..3959c96 100644
--- a/src/test/java/top/focess/qq/test/TestUtil.java
+++ b/src/test/java/top/focess/qq/test/TestUtil.java
@@ -26,9 +26,9 @@
import java.lang.reflect.Field;
import java.time.Duration;
import java.util.List;
+import java.util.PriorityQueue;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
-import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
@@ -230,7 +230,7 @@ void testScheduler4() throws Exception {
field1.setAccessible(true);
Field field2 = ComparableTask.class.getDeclaredField("task");
field2.setAccessible(true);
- PriorityBlockingQueue tasks2 = (PriorityBlockingQueue) field.get(scheduler);
+ PriorityQueue tasks2 = (PriorityQueue) field.get(scheduler);
List tasks = Lists.newArrayList();
for (int i = 0;i<5;i++) {
int finalI = i;