diff --git a/src/main/java/it/tdlight/tdlibsession/td/easy/AsyncTdEasy.java b/src/main/java/it/tdlight/tdlibsession/td/easy/AsyncTdEasy.java index 0dc6180..37247ac 100644 --- a/src/main/java/it/tdlight/tdlibsession/td/easy/AsyncTdEasy.java +++ b/src/main/java/it/tdlight/tdlibsession/td/easy/AsyncTdEasy.java @@ -1,6 +1,5 @@ package it.tdlight.tdlibsession.td.easy; -import it.tdlight.common.utils.ScannerUtils; import it.tdlight.jni.TdApi; import it.tdlight.jni.TdApi.AuthorizationState; import it.tdlight.jni.TdApi.AuthorizationStateClosed; @@ -8,11 +7,13 @@ import it.tdlight.jni.TdApi.AuthorizationStateClosing; import it.tdlight.jni.TdApi.AuthorizationStateReady; import it.tdlight.jni.TdApi.AuthorizationStateWaitCode; import it.tdlight.jni.TdApi.AuthorizationStateWaitEncryptionKey; +import it.tdlight.jni.TdApi.AuthorizationStateWaitOtherDeviceConfirmation; import it.tdlight.jni.TdApi.AuthorizationStateWaitPassword; import it.tdlight.jni.TdApi.AuthorizationStateWaitPhoneNumber; import it.tdlight.jni.TdApi.AuthorizationStateWaitRegistration; import it.tdlight.jni.TdApi.AuthorizationStateWaitTdlibParameters; import it.tdlight.jni.TdApi.CheckAuthenticationBotToken; +import it.tdlight.jni.TdApi.CheckAuthenticationCode; import it.tdlight.jni.TdApi.CheckAuthenticationPassword; import it.tdlight.jni.TdApi.CheckDatabaseEncryptionKey; import it.tdlight.jni.TdApi.Error; @@ -38,6 +39,7 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.Comparator; +import java.util.Objects; import java.util.Set; import org.reactivestreams.Publisher; import org.slf4j.Logger; @@ -390,26 +392,67 @@ public class AsyncTdEasy { logger.info("Telegram Terms of Service:\n" + authorizationStateWaitRegistration.termsOfService.text.text); } - while (registerUser.firstName == null || registerUser.firstName.length() <= 0 - || registerUser.firstName.length() > 64 || registerUser.firstName.isBlank()) { - registerUser.firstName = ScannerUtils.askParameter(this.logName, "Enter First Name").trim(); - } - while (registerUser.lastName == null || registerUser.firstName.length() > 64) { - registerUser.lastName = ScannerUtils.askParameter(this.logName, "Enter Last Name").trim(); - } - - return MonoUtils.thenOrError(sendDirectly(registerUser)); + return Mono + .from(settings) + .map(TdEasySettings::getParameterRequestHandler) + .flatMap(handler -> { + return handler + .onParameterRequest(Parameter.ASK_FIRST_NAME, new ParameterInfoEmpty()) + .filter(Objects::nonNull) + .map(String::trim) + .filter(firstName -> !firstName.isBlank() && firstName.length() <= 64 && firstName.length() > 0) + .repeatWhen(s -> s.takeWhile(n -> n == 0)) + .last() + .doOnNext(firstName -> registerUser.firstName = firstName) + .then(handler + .onParameterRequest(Parameter.ASK_LAST_NAME, new ParameterInfoEmpty()) + .filter(Objects::nonNull) + .map(String::trim) + .filter(lastName -> lastName.length() <= 64) + .repeatWhen(s -> s.takeWhile(n -> n == 0)) + .last() + .defaultIfEmpty("") + .doOnNext(lastName -> registerUser.lastName = lastName) + ) + .thenReturn(handler); + }) + .then(MonoUtils.thenOrError(sendDirectly(registerUser))); + case TdApi.AuthorizationStateWaitOtherDeviceConfirmation.CONSTRUCTOR: + var authorizationStateWaitOtherDeviceConfirmation = (AuthorizationStateWaitOtherDeviceConfirmation) obj; + return Mono + .from(settings) + .map(TdEasySettings::getParameterRequestHandler) + .flatMap(handler -> { + return handler.onParameterRequest(Parameter.NOTIFY_LINK, + new ParameterInfoNotifyLink(authorizationStateWaitOtherDeviceConfirmation.link) + ); + }); + case TdApi.AuthorizationStateWaitCode.CONSTRUCTOR: + var authorizationStateWaitCode = (AuthorizationStateWaitCode) obj; + return Mono + .from(settings) + .map(TdEasySettings::getParameterRequestHandler) + .flatMap(handler -> { + return handler.onParameterRequest(Parameter.ASK_CODE, + new ParameterInfoCode(authorizationStateWaitCode.codeInfo.phoneNumber, + authorizationStateWaitCode.codeInfo.nextType, + authorizationStateWaitCode.codeInfo.timeout, + authorizationStateWaitCode.codeInfo.type + ) + ); + }) + .flatMap(code -> MonoUtils.thenOrError(sendDirectly(new CheckAuthenticationCode(code)))); case AuthorizationStateWaitPassword.CONSTRUCTOR: var authorizationStateWaitPassword = (AuthorizationStateWaitPassword) obj; - String passwordMessage = "Password authorization of '" + this.logName + "':"; - if (authorizationStateWaitPassword.passwordHint != null && !authorizationStateWaitPassword.passwordHint.isBlank()) { - passwordMessage += "\n\tHint: " + authorizationStateWaitPassword.passwordHint; - } - logger.info(passwordMessage); - - var password = ScannerUtils.askParameter(this.logName, "Enter your password"); - - return MonoUtils.thenOrError(sendDirectly(new CheckAuthenticationPassword(password))); + return Mono + .from(settings) + .map(TdEasySettings::getParameterRequestHandler) + .flatMap(handler -> { + return handler.onParameterRequest(Parameter.ASK_PASSWORD, + new ParameterInfoPasswordHint(authorizationStateWaitPassword.passwordHint) + ); + }) + .flatMap(password -> MonoUtils.thenOrError(sendDirectly(new CheckAuthenticationPassword(password)))); case AuthorizationStateReady.CONSTRUCTOR: { return Mono.empty(); } diff --git a/src/main/java/it/tdlight/tdlibsession/td/easy/Parameter.java b/src/main/java/it/tdlight/tdlibsession/td/easy/Parameter.java new file mode 100644 index 0000000..8c8be84 --- /dev/null +++ b/src/main/java/it/tdlight/tdlibsession/td/easy/Parameter.java @@ -0,0 +1,9 @@ +package it.tdlight.tdlibsession.td.easy; + +public enum Parameter { + ASK_FIRST_NAME, + ASK_LAST_NAME, + ASK_CODE, + ASK_PASSWORD, + NOTIFY_LINK +} diff --git a/src/main/java/it/tdlight/tdlibsession/td/easy/ParameterInfo.java b/src/main/java/it/tdlight/tdlibsession/td/easy/ParameterInfo.java new file mode 100644 index 0000000..e0a22b5 --- /dev/null +++ b/src/main/java/it/tdlight/tdlibsession/td/easy/ParameterInfo.java @@ -0,0 +1,5 @@ +package it.tdlight.tdlibsession.td.easy; + +public interface ParameterInfo { + +} diff --git a/src/main/java/it/tdlight/tdlibsession/td/easy/ParameterInfoCode.java b/src/main/java/it/tdlight/tdlibsession/td/easy/ParameterInfoCode.java new file mode 100644 index 0000000..08e1a40 --- /dev/null +++ b/src/main/java/it/tdlight/tdlibsession/td/easy/ParameterInfoCode.java @@ -0,0 +1,47 @@ +package it.tdlight.tdlibsession.td.easy; + +import it.tdlight.jni.TdApi.AuthenticationCodeType; +import java.util.StringJoiner; + +public class ParameterInfoCode implements ParameterInfo { + private final String phoneNumber; + private final AuthenticationCodeType nextType; + private final int timeout; + private final AuthenticationCodeType type; + + public ParameterInfoCode(String phoneNumber, + AuthenticationCodeType nextType, + int timeout, + AuthenticationCodeType type) { + this.phoneNumber = phoneNumber; + this.nextType = nextType; + this.timeout = timeout; + this.type = type; + } + + public String getPhoneNumber() { + return phoneNumber; + } + + public AuthenticationCodeType getNextType() { + return nextType; + } + + public int getTimeout() { + return timeout; + } + + public AuthenticationCodeType getType() { + return type; + } + + @Override + public String toString() { + return new StringJoiner(", ", ParameterInfoCode.class.getSimpleName() + "[", "]") + .add("phoneNumber='" + phoneNumber + "'") + .add("nextType=" + nextType) + .add("timeout=" + timeout) + .add("type=" + type) + .toString(); + } +} diff --git a/src/main/java/it/tdlight/tdlibsession/td/easy/ParameterInfoEmpty.java b/src/main/java/it/tdlight/tdlibsession/td/easy/ParameterInfoEmpty.java new file mode 100644 index 0000000..13f0315 --- /dev/null +++ b/src/main/java/it/tdlight/tdlibsession/td/easy/ParameterInfoEmpty.java @@ -0,0 +1,5 @@ +package it.tdlight.tdlibsession.td.easy; + +public class ParameterInfoEmpty implements ParameterInfo { + +} diff --git a/src/main/java/it/tdlight/tdlibsession/td/easy/ParameterInfoNotifyLink.java b/src/main/java/it/tdlight/tdlibsession/td/easy/ParameterInfoNotifyLink.java new file mode 100644 index 0000000..17c586e --- /dev/null +++ b/src/main/java/it/tdlight/tdlibsession/td/easy/ParameterInfoNotifyLink.java @@ -0,0 +1,13 @@ +package it.tdlight.tdlibsession.td.easy; + +public class ParameterInfoNotifyLink implements ParameterInfo { + private final String link; + + public ParameterInfoNotifyLink(String link) { + this.link = link; + } + + public String getLink() { + return link; + } +} diff --git a/src/main/java/it/tdlight/tdlibsession/td/easy/ParameterInfoPasswordHint.java b/src/main/java/it/tdlight/tdlibsession/td/easy/ParameterInfoPasswordHint.java new file mode 100644 index 0000000..cea17f0 --- /dev/null +++ b/src/main/java/it/tdlight/tdlibsession/td/easy/ParameterInfoPasswordHint.java @@ -0,0 +1,13 @@ +package it.tdlight.tdlibsession.td.easy; + +public class ParameterInfoPasswordHint implements ParameterInfo { + private final String hint; + + public ParameterInfoPasswordHint(String hint) { + this.hint = hint; + } + + public String getHint() { + return hint; + } +} diff --git a/src/main/java/it/tdlight/tdlibsession/td/easy/ParameterRequestHandler.java b/src/main/java/it/tdlight/tdlibsession/td/easy/ParameterRequestHandler.java new file mode 100644 index 0000000..7d6193f --- /dev/null +++ b/src/main/java/it/tdlight/tdlibsession/td/easy/ParameterRequestHandler.java @@ -0,0 +1,7 @@ +package it.tdlight.tdlibsession.td.easy; + +import reactor.core.publisher.Mono; + +public interface ParameterRequestHandler { + Mono onParameterRequest(Parameter parameter, ParameterInfo parameterInfo); +} diff --git a/src/main/java/it/tdlight/tdlibsession/td/easy/ScannerParameterRequestHandler.java b/src/main/java/it/tdlight/tdlibsession/td/easy/ScannerParameterRequestHandler.java new file mode 100644 index 0000000..b8f0f8a --- /dev/null +++ b/src/main/java/it/tdlight/tdlibsession/td/easy/ScannerParameterRequestHandler.java @@ -0,0 +1,47 @@ +package it.tdlight.tdlibsession.td.easy; + +import it.tdlight.common.utils.ScannerUtils; +import reactor.core.publisher.Mono; +import reactor.core.scheduler.Schedulers; + +public class ScannerParameterRequestHandler implements ParameterRequestHandler { + + private final String botName; + + public ScannerParameterRequestHandler(String botName) { + this.botName = botName; + } + + @Override + public Mono onParameterRequest(Parameter parameter, ParameterInfo parameterInfo) { + return Mono.fromCallable(() -> { + String question; + boolean trim = false; + switch (parameter) { + case ASK_FIRST_NAME: question = "Enter first name"; trim = true; break; + case ASK_LAST_NAME: question = "Enter last name"; trim = true; break; + case ASK_CODE: question = "Enter authentication code"; trim = true; break; + case ASK_PASSWORD: + question = "Enter your password"; + String passwordMessage = "Password authorization of '" + this.botName + "':"; + String hint = ((ParameterInfoPasswordHint) parameterInfo).getHint(); + if (hint != null && !hint.isBlank()) { + passwordMessage += "\n\tHint: " + hint; + } + System.out.println(passwordMessage); + break; + case NOTIFY_LINK: + System.out.println("Please confirm this login link on another device: " + + ((ParameterInfoNotifyLink) parameterInfo).getLink()); + return ""; + default: question = parameter.toString(); break; + } + var result = ScannerUtils.askParameter(this.botName, question); + if (trim) { + return result.trim(); + } else { + return result; + } + }).subscribeOn(Schedulers.boundedElastic()); + } +} diff --git a/src/main/java/it/tdlight/tdlibsession/td/easy/TdEasySettings.java b/src/main/java/it/tdlight/tdlibsession/td/easy/TdEasySettings.java index 6e3d1b1..38dce6c 100644 --- a/src/main/java/it/tdlight/tdlibsession/td/easy/TdEasySettings.java +++ b/src/main/java/it/tdlight/tdlibsession/td/easy/TdEasySettings.java @@ -20,6 +20,7 @@ public class TdEasySettings { public final boolean ignoreFileNames; private final Long phoneNumber; private final String botToken; + private final ParameterRequestHandler parameterRequestHandler; public TdEasySettings(boolean useTestDc, String databaseDirectory, @@ -36,7 +37,8 @@ public class TdEasySettings { boolean enableStorageOptimizer, boolean ignoreFileNames, @Nullable Long phoneNumber, - @Nullable String botToken) { + @Nullable String botToken, + @Nullable ParameterRequestHandler parameterRequestHandler) { this.useTestDc = useTestDc; this.databaseDirectory = databaseDirectory; this.filesDirectory = filesDirectory; @@ -56,6 +58,14 @@ public class TdEasySettings { if ((phoneNumber == null) == (botToken == null)) { throw new IllegalArgumentException("You must set a phone number or a bot token"); } + if (parameterRequestHandler == null) { + if (botToken != null) { + parameterRequestHandler = new ScannerParameterRequestHandler("bot_" + botToken.split(":")[0]); + } else { + parameterRequestHandler = new ScannerParameterRequestHandler("+" + phoneNumber); + } + } + this.parameterRequestHandler = parameterRequestHandler; } public boolean isPhoneNumberSet() { @@ -74,6 +84,10 @@ public class TdEasySettings { return Objects.requireNonNull(botToken, "You must set a bot token"); } + public ParameterRequestHandler getParameterRequestHandler() { + return Objects.requireNonNull(parameterRequestHandler, "You must set a parameter request handler"); + } + public static Builder newBuilder() { return new Builder(); } @@ -98,6 +112,7 @@ public class TdEasySettings { private Long phoneNumber = null; @Nullable private String botToken = null; + private ParameterRequestHandler parameterRequestHandler; private Builder() { @@ -239,6 +254,15 @@ public class TdEasySettings { return this; } + public Builder setParameterRequestHandler(ParameterRequestHandler parameterRequestHandler) { + this.parameterRequestHandler = parameterRequestHandler; + return this; + } + + public ParameterRequestHandler getParameterRequestHandler() { + return parameterRequestHandler; + } + public TdEasySettings build() { return new TdEasySettings(useTestDc, databaseDirectory, @@ -255,7 +279,8 @@ public class TdEasySettings { enableStorageOptimizer, ignoreFileNames, phoneNumber, - botToken + botToken, + parameterRequestHandler ); } }