From f8e0f352c3629ae7906ddd3695ed437dab19bb67 Mon Sep 17 00:00:00 2001 From: Ernesto Castellotti Date: Mon, 19 Nov 2018 17:59:57 +0100 Subject: [PATCH] Implemented new checks in authorizationHandler for check if bot token, phone number, code or password are invalid Added password hint in password authorization Check if EasyClient has the authorization before send request Optimized execute in EasyClient Implemented close and open for logout from TDLib e re-login Now client can execute auto, just set logoutAtShutdown to true in initializer Fix https://github.com/ErnyTech/JTDLib/issues/5 --- .../java/it/ernytech/tdbot/BotClient.java | 2 +- .../java/it/ernytech/tdbot/EasyClient.java | 110 +++++++++++++++--- .../java/it/ernytech/tdbot/UserClient.java | 2 +- src/main/java/it/ernytech/tdlib/Client.java | 2 - src/main/java/it/ernytech/tdlib/Log.java | 2 - 5 files changed, 96 insertions(+), 22 deletions(-) diff --git a/src/main/java/it/ernytech/tdbot/BotClient.java b/src/main/java/it/ernytech/tdbot/BotClient.java index d634435..70fdf4a 100644 --- a/src/main/java/it/ernytech/tdbot/BotClient.java +++ b/src/main/java/it/ernytech/tdbot/BotClient.java @@ -29,6 +29,6 @@ public class BotClient extends EasyClient { * @param botToken The bot token generated with t.me/BotFather */ public BotClient(String botToken) { - super(easyClient -> easyClient.send(new TdApi.CheckAuthenticationBotToken(botToken))); + super(easyClient -> easyClient.sendRaw(new TdApi.CheckAuthenticationBotToken(botToken))); } } diff --git a/src/main/java/it/ernytech/tdbot/EasyClient.java b/src/main/java/it/ernytech/tdbot/EasyClient.java index fbd6ccf..62178a3 100644 --- a/src/main/java/it/ernytech/tdbot/EasyClient.java +++ b/src/main/java/it/ernytech/tdbot/EasyClient.java @@ -24,6 +24,8 @@ import it.ernytech.tdlib.utils.ReceiveCallback; import java.util.Scanner; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; @@ -36,17 +38,28 @@ public class EasyClient { private ClientActor clientActor; private ConcurrentHashMap handlers = new ConcurrentHashMap<>(); private AtomicLong requestId = new AtomicLong(1); + private ExecutorService executors = Executors.newFixedThreadPool(10); protected volatile boolean haveAuthorization = false; + private volatile boolean haveClosed = false; /** * Creates a new EasyClient. * @param authorizationHandler Callback to be implemented in the client to manage the authorization. */ public EasyClient(AuthorizationHandler authorizationHandler) { - Log.setVerbosityLevel(1); this.authorizationHandler = authorizationHandler; this.handlers.put(0L, new TdCallback(response -> {}, error -> {}, () -> {})); - this.clientActor = new ClientActor(new TdCallback(this::onResult, this::onError, this::onClosed)); + open(); + } + + public EasyClient(AuthorizationHandler authorizationHandler, boolean logoutAtShutdown) { + this.authorizationHandler = authorizationHandler; + this.handlers.put(0L, new TdCallback(response -> {}, error -> {}, () -> {})); + open(); + + if (logoutAtShutdown) { + Runtime.getRuntime().addShutdownHook(new Thread(this::close)); + } } /** @@ -56,7 +69,15 @@ public class EasyClient { */ public long send(TdApi.Function function) { var requestId = this.requestId.getAndIncrement(); - this.clientActor.request(new Request(requestId, function)); + this.executors.execute(() -> { + while (true) { + if (this.haveAuthorization) { + break; + } + } + + this.clientActor.request(new Request(requestId, function)); + }); return requestId; } @@ -67,12 +88,6 @@ public class EasyClient { * @param errorCallback Interface of callback for receive incoming error response. */ public void execute(TdApi.Function function, ReceiveCallback receiveCallback, ErrorCallback errorCallback) { - while (true) { - if (haveAuthorization) { - break; - } - } - var requestId = send(function); this.handlers.put(requestId, new TdCallback(receiveCallback, errorCallback)); } @@ -170,6 +185,17 @@ public class EasyClient { this.handlers.put(0L, new TdCallback(receiveCallback, errorCallback, closeCallback)); } + public void close() { + send(new TdApi.LogOut()); + this.executors.shutdown(); + this.haveClosed = true; + } + + public void open() { + Log.setVerbosityLevel(1); + inizializeClient(); + } + /** * Destroys the client and TDLib instance. */ @@ -179,8 +205,10 @@ public class EasyClient { } private void onResult(Response response) { + System.out.println(response.getObject()); if (response.getObject().getConstructor() == TdApi.UpdateAuthorizationState.CONSTRUCTOR) { - authorizationHandler((TdApi.UpdateAuthorizationState) response.getObject()); + TdApi.UpdateAuthorizationState updateAuthorizationState = (TdApi.UpdateAuthorizationState) response.getObject(); + authorizationHandler(updateAuthorizationState.authorizationState); return; } @@ -199,6 +227,24 @@ public class EasyClient { } private void onError(Response error) { + TdApi.Error tdError = (TdApi.Error) error.getObject(); + + if (tdError.message.equals("PHONE_CODE_INVALID")) { + authorizationHandler(new TdApi.AuthorizationStateWaitCode()); + } + + if (tdError.message.equals("PASSWORD_HASH_INVALID")) { + authorizationHandler(new TdApi.AuthorizationStateWaitPassword()); + } + + if (tdError.message.equals("PHONE_NUMBER_INVALID")) { + throw new IllegalArgumentException("Phone number is invalid!"); + } + + if (tdError.message.equals("ACCESS_TOKEN_INVALID")) { + throw new IllegalArgumentException("Bot token is invalid!"); + } + if (error.getId() == 0) { this.handlers.get(0L).getErrorCallback().onError(error); } else { @@ -216,12 +262,21 @@ public class EasyClient { this.handlers.get(0L).getCloseCallback().onClosed(); } + private void inizializeClient() { + this.clientActor = new ClientActor(new TdCallback(this::onResult, this::onError, this::onClosed)); + } + + public void sendRaw(TdApi.Function function) { + var requestId = this.requestId.getAndIncrement(); + this.clientActor.request(new Request(requestId, function)); + } + /** * Manages the authorization state updates. * @param authorizationState The status of the authorization. */ - protected void authorizationHandler(TdApi.UpdateAuthorizationState authorizationState) { - switch (authorizationState.authorizationState.getConstructor()) { + protected void authorizationHandler(TdApi.AuthorizationState authorizationState) { + switch (authorizationState.getConstructor()) { case TdApi.AuthorizationStateWaitTdlibParameters.CONSTRUCTOR : { var parameters = new TdApi.TdlibParameters(); parameters.databaseDirectory = "tdlib"; @@ -234,12 +289,12 @@ public class EasyClient { parameters.systemVersion = "TDBOT"; parameters.applicationVersion = "1.0"; parameters.enableStorageOptimizer = true; - send(new TdApi.SetTdlibParameters(parameters)); + sendRaw(new TdApi.SetTdlibParameters(parameters)); break; } case TdApi.AuthorizationStateWaitEncryptionKey.CONSTRUCTOR: { - send(new TdApi.CheckDatabaseEncryptionKey()); + sendRaw(new TdApi.CheckDatabaseEncryptionKey()); break; } @@ -251,15 +306,17 @@ public class EasyClient { case TdApi.AuthorizationStateWaitCode.CONSTRUCTOR: { var scanner = new Scanner(System.in); System.out.print("Insert your code: "); - send(new TdApi.CheckAuthenticationCode(scanner.nextLine(), "", "")); + sendRaw(new TdApi.CheckAuthenticationCode(scanner.nextLine(), "", "")); System.out.println(); break; } case TdApi.AuthorizationStateWaitPassword.CONSTRUCTOR: { var scanner = new Scanner(System.in); + System.out.println("Password authorization"); + System.out.println("Password hint: " + ((TdApi.AuthorizationStateWaitPassword) authorizationState).passwordHint); System.out.print("Insert your password: "); - send(new TdApi.CheckAuthenticationPassword(scanner.nextLine())); + sendRaw(new TdApi.CheckAuthenticationPassword(scanner.nextLine())); System.out.println(); break; } @@ -268,6 +325,27 @@ public class EasyClient { this.haveAuthorization = true; break; } + case TdApi.AuthorizationStateLoggingOut.CONSTRUCTOR: { + this.haveAuthorization = false; + break; + } + case TdApi.AuthorizationStateClosing.CONSTRUCTOR: { + this.haveAuthorization = false; + break; + } + case TdApi.AuthorizationStateClosed.CONSTRUCTOR: { + if(this.haveClosed) { + this.destroyBotClient(); + } else { + this.destroyBotClient(); + inizializeClient(); + } + break; + } + + default: { + throw new IllegalStateException("Unsupported authorization state:\n" + authorizationState); + } } } } diff --git a/src/main/java/it/ernytech/tdbot/UserClient.java b/src/main/java/it/ernytech/tdbot/UserClient.java index 428ac83..4147a51 100644 --- a/src/main/java/it/ernytech/tdbot/UserClient.java +++ b/src/main/java/it/ernytech/tdbot/UserClient.java @@ -29,6 +29,6 @@ public class UserClient extends EasyClient { * @param phoneNumber The phone number of user. */ public UserClient(long phoneNumber) { - super(easyClient -> easyClient.send(new TdApi.SetAuthenticationPhoneNumber(String.valueOf(phoneNumber), false, false))); + super(easyClient -> easyClient.sendRaw(new TdApi.SetAuthenticationPhoneNumber(String.valueOf(phoneNumber), false, false))); } } \ No newline at end of file diff --git a/src/main/java/it/ernytech/tdlib/Client.java b/src/main/java/it/ernytech/tdlib/Client.java index e3b0004..7e226bb 100644 --- a/src/main/java/it/ernytech/tdlib/Client.java +++ b/src/main/java/it/ernytech/tdlib/Client.java @@ -17,9 +17,7 @@ package it.ernytech.tdlib; -import it.ernytech.tdlib.utils.CantLoadLibrary; import it.ernytech.tdlib.utils.Init; -import it.ernytech.tdlib.utils.MissingTdlibLibrary; import java.util.ArrayList; import java.util.List; diff --git a/src/main/java/it/ernytech/tdlib/Log.java b/src/main/java/it/ernytech/tdlib/Log.java index 9b2a98d..c96bf10 100644 --- a/src/main/java/it/ernytech/tdlib/Log.java +++ b/src/main/java/it/ernytech/tdlib/Log.java @@ -17,9 +17,7 @@ package it.ernytech.tdlib; -import it.ernytech.tdlib.utils.CantLoadLibrary; import it.ernytech.tdlib.utils.Init; -import it.ernytech.tdlib.utils.MissingTdlibLibrary; import java.util.Objects;