package it.tdlight.tdlibsession.td.middle.direct; import static it.tdlight.tdlibsession.td.middle.server.AsyncTdMiddleEventBusServer.WAIT_DURATION; import io.vertx.core.AbstractVerticle; import io.vertx.core.DeploymentOptions; import io.vertx.core.Promise; import io.vertx.core.json.JsonObject; import it.tdlight.jni.TdApi.Function; import it.tdlight.jni.TdApi.Object; import it.tdlight.jni.TdApi.Update; import it.tdlight.tdlibsession.td.ResponseError; import it.tdlight.tdlibsession.td.TdResult; import it.tdlight.tdlibsession.td.direct.AsyncTdDirectImpl; import it.tdlight.tdlibsession.td.middle.AsyncTdMiddle; import it.tdlight.tdlibsession.td.middle.TdClusterManager; import it.tdlight.utils.MonoUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.warp.commonutils.error.InitializationException; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.core.publisher.ReplayProcessor; public class AsyncTdMiddleDirect extends AbstractVerticle implements AsyncTdMiddle { private static final Logger logger = LoggerFactory.getLogger(AsyncTdMiddleDirect.class); protected final ReplayProcessor tdClosed = ReplayProcessor.cacheLastOrDefault(false); protected AsyncTdDirectImpl td; private String botAddress; private String botAlias; public AsyncTdMiddleDirect() { } public static Mono getAndDeployInstance(TdClusterManager clusterManager, String botAlias, String botAddress) throws InitializationException { try { var instance = new AsyncTdMiddleDirect(); var options = new DeploymentOptions().setConfig(new JsonObject() .put("botAlias", botAlias) .put("botAddress", botAddress)); return MonoUtils.executeAsFuture(promise -> { clusterManager.getVertx().deployVerticle(instance, options, promise); }).doOnNext(_v -> { logger.trace("Deployed verticle for bot " + botAlias + ", address: " + botAddress); }).thenReturn(instance); } catch (RuntimeException e) { throw new InitializationException(e); } } @Override public void start(Promise startPromise) { var botAddress = config().getString("botAddress"); if (botAddress == null || botAddress.isEmpty()) { throw new IllegalArgumentException("botAddress is not set!"); } this.botAddress = botAddress; var botAlias = config().getString("botAlias"); if (botAlias == null || botAlias.isEmpty()) { throw new IllegalArgumentException("botAlias is not set!"); } this.botAlias = botAlias; this.td = new AsyncTdDirectImpl(botAlias); td.initializeClient().doOnSuccess(v -> startPromise.complete()).subscribe(success -> { }, (ex) -> { logger.error("Failure when starting bot " + botAlias + ", address " + botAddress, ex); startPromise.fail(new InitializationException("Can't connect tdlib middle client to tdlib middle server!")); }, () -> {}); } @Override public void stop(Promise stopPromise) { tdClosed.onNext(true); td.destroyClient().onErrorResume(ex -> { logger.error("Can't destroy client", ex); return Mono.empty(); }).doOnTerminate(() -> { logger.debug("TdMiddle verticle stopped"); }).subscribe(MonoUtils.toSubscriber(stopPromise)); } @Override public Flux getUpdates() { return Mono.from(tdClosed).filter(closed -> !closed).flatMapMany(_x -> td.getUpdates(WAIT_DURATION, 1000).flatMap(result -> { if (result.succeeded()) { if (result.result().succeeded()) { return Mono.just(result.result().result()); } else { logger.error("Received an errored update", ResponseError.newResponseError("incoming update", botAlias, result.result().cause()) ); return Mono.empty(); } } else { logger.error("Received an errored update", result.cause()); return Mono.empty(); } })); } @Override public Mono> execute(Function requestFunction, boolean executeDirectly) { return td.execute(requestFunction, executeDirectly).onErrorMap(error -> { return ResponseError.newResponseError( requestFunction, botAlias, error ); }); } }