summaryrefslogtreecommitdiff
path: root/protocols/Telegram/tdlib/td/example/java
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/Telegram/tdlib/td/example/java')
-rw-r--r--protocols/Telegram/tdlib/td/example/java/.gitignore5
-rw-r--r--protocols/Telegram/tdlib/td/example/java/CMakeLists.txt124
-rw-r--r--protocols/Telegram/tdlib/td/example/java/README.md43
-rw-r--r--protocols/Telegram/tdlib/td/example/java/org/drinkless/tdlib/Client.java242
-rw-r--r--protocols/Telegram/tdlib/td/example/java/org/drinkless/tdlib/example/Example.java685
-rw-r--r--protocols/Telegram/tdlib/td/example/java/td_jni.cpp182
6 files changed, 0 insertions, 1281 deletions
diff --git a/protocols/Telegram/tdlib/td/example/java/.gitignore b/protocols/Telegram/tdlib/td/example/java/.gitignore
deleted file mode 100644
index 8f846b80d9..0000000000
--- a/protocols/Telegram/tdlib/td/example/java/.gitignore
+++ /dev/null
@@ -1,5 +0,0 @@
-**/*build/
-bin/
-docs/
-org/drinkless/tdlib/TdApi.java
-td/
diff --git a/protocols/Telegram/tdlib/td/example/java/CMakeLists.txt b/protocols/Telegram/tdlib/td/example/java/CMakeLists.txt
deleted file mode 100644
index 576eee2cfc..0000000000
--- a/protocols/Telegram/tdlib/td/example/java/CMakeLists.txt
+++ /dev/null
@@ -1,124 +0,0 @@
-cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR)
-
-if (POLICY CMP0065)
- # do not export symbols from executables
- # affects compiler checks in project(), so must be set before it
- cmake_policy(SET CMP0065 NEW)
-endif()
-
-project(TdJavaExample VERSION 1.0 LANGUAGES CXX)
-
-if (POLICY CMP0054)
- # do not expand quoted arguments
- cmake_policy(SET CMP0054 NEW)
-endif()
-if (POLICY CMP0060)
- # link libraries by full path
- cmake_policy(SET CMP0060 NEW)
-endif()
-if (POLICY CMP0074)
- # use environment variables to find libraries
- cmake_policy(SET CMP0074 NEW)
-endif()
-
-find_package(Td REQUIRED)
-
-if (NOT JNI_FOUND)
- find_package(JNI REQUIRED)
-endif()
-message(STATUS "Found JNI: ${JNI_INCLUDE_DIRS} ${JNI_LIBRARIES}")
-
-if (NOT Java_FOUND)
- find_package(Java REQUIRED)
-endif()
-message(STATUS "Found Java: ${Java_JAVAC_EXECUTABLE} ${Java_JAVADOC_EXECUTABLE}")
-
-# Generating TdApi.java
-find_program(PHP_EXECUTABLE php)
-if ((CMAKE_SYSTEM_NAME MATCHES "FreeBSD") AND (CMAKE_SYSTEM_VERSION MATCHES "HBSD"))
- set(PHP_EXECUTABLE "PHP_EXECUTABLE-NOTFOUND")
-endif()
-
-set(TD_API_JAVA_PACKAGE "org/drinkless/tdlib")
-set(TD_API_JAVA_PATH ${CMAKE_CURRENT_SOURCE_DIR})
-set(TD_API_TLO_PATH ${CMAKE_CURRENT_SOURCE_DIR}/td/bin/td/generate/scheme/td_api.tlo)
-set(TD_API_TL_PATH ${CMAKE_CURRENT_SOURCE_DIR}/td/bin/td/generate/scheme/td_api.tl)
-set(JAVADOC_TL_DOCUMENTATION_GENERATOR_PATH ${CMAKE_CURRENT_SOURCE_DIR}/td/bin/td/generate/JavadocTlDocumentationGenerator.php)
-set(GENERATE_JAVA_API_CMD ${CMAKE_CURRENT_SOURCE_DIR}/td/bin/td_generate_java_api TdApi ${TD_API_TLO_PATH} ${TD_API_JAVA_PATH} ${TD_API_JAVA_PACKAGE})
-if (PHP_EXECUTABLE)
- set(GENERATE_JAVA_API_CMD ${GENERATE_JAVA_API_CMD} && ${PHP_EXECUTABLE} ${JAVADOC_TL_DOCUMENTATION_GENERATOR_PATH} ${TD_API_TL_PATH} ${TD_API_JAVA_PATH}/${TD_API_JAVA_PACKAGE}/TdApi.java)
-endif()
-
-add_custom_target(td_generate_java_api
- COMMAND ${GENERATE_JAVA_API_CMD}
- COMMENT "Generating Java TDLib API source files"
- DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/td/bin/td_generate_java_api ${TD_API_TLO_PATH} ${TD_API_TL_PATH} ${JAVADOC_TL_DOCUMENTATION_GENERATOR_PATH}
-)
-
-set(JAVA_SOURCE_PATH "${TD_API_JAVA_PATH}/${TD_API_JAVA_PACKAGE}")
-get_filename_component(JAVA_OUTPUT_DIRECTORY ${CMAKE_INSTALL_PREFIX}/bin REALPATH BASE_DIR "${CMAKE_CURRENT_BINARY_DIR}")
-file(MAKE_DIRECTORY ${JAVA_OUTPUT_DIRECTORY})
-add_custom_target(build_java
- COMMAND ${Java_JAVAC_EXECUTABLE} -encoding UTF-8 -d ${JAVA_OUTPUT_DIRECTORY} ${JAVA_SOURCE_PATH}/example/Example.java ${JAVA_SOURCE_PATH}/Client.java ${JAVA_SOURCE_PATH}/TdApi.java
- COMMENT "Building Java code"
- DEPENDS td_generate_java_api
-)
-
-add_custom_target(generate_javadoc
- COMMAND ${Java_JAVADOC_EXECUTABLE} -encoding UTF-8 -charset UTF-8 -d ${JAVA_OUTPUT_DIRECTORY}/../docs org.drinkless.tdlib
- WORKING_DIRECTORY ${TD_API_JAVA_PATH}
- COMMENT "Generating Javadoc documentation"
- DEPENDS td_generate_java_api
-)
-
-# Building shared library
-add_library(tdjni SHARED
- td_jni.cpp
-)
-target_include_directories(tdjni PRIVATE ${JAVA_INCLUDE_PATH} ${JAVA_INCLUDE_PATH2})
-target_link_libraries(tdjni PRIVATE Td::TdStatic ${JAVA_JVM_LIBRARY})
-target_compile_definitions(tdjni PRIVATE PACKAGE_NAME="${TD_API_JAVA_PACKAGE}")
-
-if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
- set(GCC 1)
-elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
- set(CLANG 1)
-elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
- set(INTEL 1)
-elseif (NOT MSVC)
- message(FATAL_ERROR "Compiler isn't supported")
-endif()
-
-include(CheckCXXCompilerFlag)
-
-if (GCC OR CLANG OR INTEL)
- if (WIN32 AND INTEL)
- set(STD14_FLAG /Qstd=c++14)
- else()
- set(STD14_FLAG -std=c++14)
- endif()
- check_cxx_compiler_flag(${STD14_FLAG} HAVE_STD14)
- if (NOT HAVE_STD14)
- string(REPLACE "c++14" "c++1y" STD14_FLAG "${STD14_FLAG}")
- check_cxx_compiler_flag(${STD14_FLAG} HAVE_STD1Y)
- set(HAVE_STD14 ${HAVE_STD1Y})
- endif()
-
- target_compile_options(tdjni PRIVATE "${STD14_FLAG}")
-elseif (MSVC)
- set(HAVE_STD14 MSVC_VERSION>=1900)
-endif()
-
-if (NOT HAVE_STD14)
- message(FATAL_ERROR "No C++14 support in the compiler. Please upgrade the compiler.")
-endif()
-
-add_dependencies(tdjni td_generate_java_api build_java generate_javadoc)
-
-install(TARGETS tdjni
- LIBRARY DESTINATION bin
- RUNTIME DESTINATION bin
-)
-if (MSVC AND VCPKG_TOOLCHAIN)
- install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/" DESTINATION bin FILES_MATCHING PATTERN "*.dll" PATTERN "*.pdb")
-endif()
diff --git a/protocols/Telegram/tdlib/td/example/java/README.md b/protocols/Telegram/tdlib/td/example/java/README.md
deleted file mode 100644
index 4c7df1916d..0000000000
--- a/protocols/Telegram/tdlib/td/example/java/README.md
+++ /dev/null
@@ -1,43 +0,0 @@
-# TDLib Java example
-
-To run this example, you will need installed JDK >= 1.6.
-For Javadoc documentation generation PHP is needed.
-
-You can find complete build instructions for your operating system at https://tdlib.github.io/td/build.html?language=Java.
-
-In general, the build process looks as follows.
-
-TDLib should be prebuilt with JNI bindings and installed to local subdirectory `td/` as follows:
-```
-cd <path to TDLib sources>
-mkdir jnibuild
-cd jnibuild
-cmake -DCMAKE_BUILD_TYPE=Release -DTD_ENABLE_JNI=ON -DCMAKE_INSTALL_PREFIX:PATH=../example/java/td ..
-cmake --build . --target install
-```
-If you want to compile TDLib for 32-bit/64-bit Java on Windows using MSVC, you will also need to add `-A Win32`/`-A x64` option to CMake.
-
-In Windows, use vcpkg toolchain file by adding parameter -DCMAKE_TOOLCHAIN_FILE=<VCPKG_DIR>/scripts/buildsystems/vcpkg.cmake
-
-Then you can build this example:
-```
-cd <path to TDLib sources>/example/java
-mkdir build
-cd build
-cmake -DCMAKE_BUILD_TYPE=Release -DTd_DIR=<full path to TDLib sources>/example/java/td/lib/cmake/Td -DCMAKE_INSTALL_PREFIX:PATH=.. ..
-cmake --build . --target install
-```
-
-Compiled TDLib shared library and Java example after that will be placed in bin/ and Javadoc documentation in `docs/`.
-
-Now you can run Java example:
-```
-cd <path to TDLib sources>/example/java/bin
-java '-Djava.library.path=.' org/drinkless/tdlib/example/Example
-```
-
-If you receive "Could NOT find JNI ..." error from CMake, you need to specify to CMake path to the installed JDK, for example, "-DJAVA_HOME=/usr/lib/jvm/java-8-oracle/".
-
-If you receive java.lang.UnsatisfiedLinkError with "Can't find dependent libraries", you may also need to copy some dependent shared OpenSSL and zlib libraries to `bin/`.
-
-Make sure that you compiled the example for the same architecture as your JVM.
diff --git a/protocols/Telegram/tdlib/td/example/java/org/drinkless/tdlib/Client.java b/protocols/Telegram/tdlib/td/example/java/org/drinkless/tdlib/Client.java
deleted file mode 100644
index 0a58bb45a7..0000000000
--- a/protocols/Telegram/tdlib/td/example/java/org/drinkless/tdlib/Client.java
+++ /dev/null
@@ -1,242 +0,0 @@
-//
-// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-//
-package org.drinkless.tdlib;
-
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.atomic.AtomicLong;
-
-/**
- * Main class for interaction with the TDLib.
- */
-public final class Client {
- static {
- try {
- System.loadLibrary("tdjni");
- } catch (UnsatisfiedLinkError e) {
- e.printStackTrace();
- }
- }
-
- /**
- * Interface for handler for results of queries to TDLib and incoming updates from TDLib.
- */
- public interface ResultHandler {
- /**
- * Callback called on result of query to TDLib or incoming update from TDLib.
- *
- * @param object Result of query or update of type TdApi.Update about new events.
- */
- void onResult(TdApi.Object object);
- }
-
- /**
- * Interface for handler of exceptions thrown while invoking ResultHandler.
- * By default, all such exceptions are ignored.
- * All exceptions thrown from ExceptionHandler are ignored.
- */
- public interface ExceptionHandler {
- /**
- * Callback called on exceptions thrown while invoking ResultHandler.
- *
- * @param e Exception thrown by ResultHandler.
- */
- void onException(Throwable e);
- }
-
- /**
- * Interface for handler of messages that are added to the internal TDLib log.
- */
- public interface LogMessageHandler {
- /**
- * Callback called on messages that are added to the internal TDLib log.
- *
- * @param verbosityLevel Log verbosity level with which the message was added from -1 up to 1024.
- * If 0, then TDLib will crash as soon as the callback returns.
- * None of the TDLib methods can be called from the callback.
- * @param message The message added to the internal TDLib log.
- */
- void onLogMessage(int verbosityLevel, String message);
- }
-
- /**
- * Sends a request to the TDLib.
- *
- * @param query Object representing a query to the TDLib.
- * @param resultHandler Result handler with onResult method which will be called with result
- * of the query or with TdApi.Error as parameter. If it is null, nothing
- * will be called.
- * @param exceptionHandler Exception handler with onException method which will be called on
- * exception thrown from resultHandler. If it is null, then
- * defaultExceptionHandler will be called.
- * @throws NullPointerException if query is null.
- */
- public void send(TdApi.Function query, ResultHandler resultHandler, ExceptionHandler exceptionHandler) {
- long queryId = currentQueryId.incrementAndGet();
- if (resultHandler != null) {
- handlers.put(queryId, new Handler(resultHandler, exceptionHandler));
- }
- nativeClientSend(nativeClientId, queryId, query);
- }
-
- /**
- * Sends a request to the TDLib with an empty ExceptionHandler.
- *
- * @param query Object representing a query to the TDLib.
- * @param resultHandler Result handler with onResult method which will be called with result
- * of the query or with TdApi.Error as parameter. If it is null, then
- * defaultExceptionHandler will be called.
- * @throws NullPointerException if query is null.
- */
- public void send(TdApi.Function query, ResultHandler resultHandler) {
- send(query, resultHandler, null);
- }
-
- /**
- * Synchronously executes a TDLib request. Only a few marked accordingly requests can be executed synchronously.
- *
- * @param query Object representing a query to the TDLib.
- * @return request result.
- * @throws NullPointerException if query is null.
- */
- public static TdApi.Object execute(TdApi.Function query) {
- return nativeClientExecute(query);
- }
-
- /**
- * Creates new Client.
- *
- * @param updateHandler Handler for incoming updates.
- * @param updateExceptionHandler Handler for exceptions thrown from updateHandler. If it is null, exceptions will be iggnored.
- * @param defaultExceptionHandler Default handler for exceptions thrown from all ResultHandler. If it is null, exceptions will be iggnored.
- * @return created Client
- */
- public static Client create(ResultHandler updateHandler, ExceptionHandler updateExceptionHandler, ExceptionHandler defaultExceptionHandler) {
- Client client = new Client(updateHandler, updateExceptionHandler, defaultExceptionHandler);
- synchronized (responseReceiver) {
- if (!responseReceiver.isRun) {
- responseReceiver.isRun = true;
-
- Thread receiverThread = new Thread(responseReceiver, "TDLib thread");
- receiverThread.setDaemon(true);
- receiverThread.start();
- }
- }
- return client;
- }
-
- /**
- * Sets the handler for messages that are added to the internal TDLib log.
- * None of the TDLib methods can be called from the callback.
- *
- * @param maxVerbosityLevel The maximum verbosity level of messages for which the callback will be called.
- * @param logMessageHandler Handler for messages that are added to the internal TDLib log. Pass null to remove the handler.
- */
- public static void setLogMessageHandler(int maxVerbosityLevel, Client.LogMessageHandler logMessageHandler) {
- nativeClientSetLogMessageHandler(maxVerbosityLevel, logMessageHandler);
- }
-
- private static class ResponseReceiver implements Runnable {
- public boolean isRun = false;
-
- @Override
- public void run() {
- while (true) {
- int resultN = nativeClientReceive(clientIds, eventIds, events, 100000.0 /*seconds*/);
- for (int i = 0; i < resultN; i++) {
- processResult(clientIds[i], eventIds[i], events[i]);
- events[i] = null;
- }
- }
- }
-
- private void processResult(int clientId, long id, TdApi.Object object) {
- boolean isClosed = false;
- if (id == 0 && object instanceof TdApi.UpdateAuthorizationState) {
- TdApi.AuthorizationState authorizationState = ((TdApi.UpdateAuthorizationState) object).authorizationState;
- if (authorizationState instanceof TdApi.AuthorizationStateClosed) {
- isClosed = true;
- }
- }
-
- Handler handler = id == 0 ? updateHandlers.get(clientId) : handlers.remove(id);
- if (handler != null) {
- try {
- handler.resultHandler.onResult(object);
- } catch (Throwable cause) {
- ExceptionHandler exceptionHandler = handler.exceptionHandler;
- if (exceptionHandler == null) {
- exceptionHandler = defaultExceptionHandlers.get(clientId);
- }
- if (exceptionHandler != null) {
- try {
- exceptionHandler.onException(cause);
- } catch (Throwable ignored) {
- }
- }
- }
- }
-
- if (isClosed) {
- updateHandlers.remove(clientId); // there will be no more updates
- defaultExceptionHandlers.remove(clientId); // ignore further exceptions
- clientCount.decrementAndGet();
- }
- }
-
- private static final int MAX_EVENTS = 1000;
- private final int[] clientIds = new int[MAX_EVENTS];
- private final long[] eventIds = new long[MAX_EVENTS];
- private final TdApi.Object[] events = new TdApi.Object[MAX_EVENTS];
- }
-
- private final int nativeClientId;
-
- private static final ConcurrentHashMap<Integer, ExceptionHandler> defaultExceptionHandlers = new ConcurrentHashMap<Integer, ExceptionHandler>();
- private static final ConcurrentHashMap<Integer, Handler> updateHandlers = new ConcurrentHashMap<Integer, Handler>();
- private static final ConcurrentHashMap<Long, Handler> handlers = new ConcurrentHashMap<Long, Handler>();
- private static final AtomicLong currentQueryId = new AtomicLong();
- private static final AtomicLong clientCount = new AtomicLong();
-
- private static final ResponseReceiver responseReceiver = new ResponseReceiver();
-
- private static class Handler {
- final ResultHandler resultHandler;
- final ExceptionHandler exceptionHandler;
-
- Handler(ResultHandler resultHandler, ExceptionHandler exceptionHandler) {
- this.resultHandler = resultHandler;
- this.exceptionHandler = exceptionHandler;
- }
- }
-
- private Client(ResultHandler updateHandler, ExceptionHandler updateExceptionHandler, ExceptionHandler defaultExceptionHandler) {
- clientCount.incrementAndGet();
- nativeClientId = createNativeClient();
- if (updateHandler != null) {
- updateHandlers.put(nativeClientId, new Handler(updateHandler, updateExceptionHandler));
- }
- if (defaultExceptionHandler != null) {
- defaultExceptionHandlers.put(nativeClientId, defaultExceptionHandler);
- }
- send(new TdApi.GetOption("version"), null, null);
- }
-
- @Override
- protected void finalize() throws Throwable {
- send(new TdApi.Close(), null, null);
- }
-
- private static native int createNativeClient();
-
- private static native void nativeClientSend(int nativeClientId, long eventId, TdApi.Function function);
-
- private static native int nativeClientReceive(int[] clientIds, long[] eventIds, TdApi.Object[] events, double timeout);
-
- private static native TdApi.Object nativeClientExecute(TdApi.Function function);
-
- private static native void nativeClientSetLogMessageHandler(int maxVerbosityLevel, LogMessageHandler logMessageHandler);
-}
diff --git a/protocols/Telegram/tdlib/td/example/java/org/drinkless/tdlib/example/Example.java b/protocols/Telegram/tdlib/td/example/java/org/drinkless/tdlib/example/Example.java
deleted file mode 100644
index 7e76b42276..0000000000
--- a/protocols/Telegram/tdlib/td/example/java/org/drinkless/tdlib/example/Example.java
+++ /dev/null
@@ -1,685 +0,0 @@
-//
-// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-//
-package org.drinkless.tdlib.example;
-
-import org.drinkless.tdlib.Client;
-import org.drinkless.tdlib.TdApi;
-
-import java.io.BufferedReader;
-import java.io.IOError;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.util.NavigableSet;
-import java.util.TreeSet;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
-
-/**
- * Example class for TDLib usage from Java.
- */
-public final class Example {
- private static Client client = null;
-
- private static TdApi.AuthorizationState authorizationState = null;
- private static volatile boolean haveAuthorization = false;
- private static volatile boolean needQuit = false;
- private static volatile boolean canQuit = false;
-
- private static final Client.ResultHandler defaultHandler = new DefaultHandler();
-
- private static final Lock authorizationLock = new ReentrantLock();
- private static final Condition gotAuthorization = authorizationLock.newCondition();
-
- private static final ConcurrentMap<Long, TdApi.User> users = new ConcurrentHashMap<Long, TdApi.User>();
- private static final ConcurrentMap<Long, TdApi.BasicGroup> basicGroups = new ConcurrentHashMap<Long, TdApi.BasicGroup>();
- private static final ConcurrentMap<Long, TdApi.Supergroup> supergroups = new ConcurrentHashMap<Long, TdApi.Supergroup>();
- private static final ConcurrentMap<Integer, TdApi.SecretChat> secretChats = new ConcurrentHashMap<Integer, TdApi.SecretChat>();
-
- private static final ConcurrentMap<Long, TdApi.Chat> chats = new ConcurrentHashMap<Long, TdApi.Chat>();
- private static final NavigableSet<OrderedChat> mainChatList = new TreeSet<OrderedChat>();
- private static boolean haveFullMainChatList = false;
-
- private static final ConcurrentMap<Long, TdApi.UserFullInfo> usersFullInfo = new ConcurrentHashMap<Long, TdApi.UserFullInfo>();
- private static final ConcurrentMap<Long, TdApi.BasicGroupFullInfo> basicGroupsFullInfo = new ConcurrentHashMap<Long, TdApi.BasicGroupFullInfo>();
- private static final ConcurrentMap<Long, TdApi.SupergroupFullInfo> supergroupsFullInfo = new ConcurrentHashMap<Long, TdApi.SupergroupFullInfo>();
-
- private static final String newLine = System.getProperty("line.separator");
- private static final String commandsLine = "Enter command (gcs - GetChats, gc <chatId> - GetChat, me - GetMe, sm <chatId> <message> - SendMessage, lo - LogOut, q - Quit): ";
- private static volatile String currentPrompt = null;
-
- private static void print(String str) {
- if (currentPrompt != null) {
- System.out.println("");
- }
- System.out.println(str);
- if (currentPrompt != null) {
- System.out.print(currentPrompt);
- }
- }
-
- private static void setChatPositions(TdApi.Chat chat, TdApi.ChatPosition[] positions) {
- synchronized (mainChatList) {
- synchronized (chat) {
- for (TdApi.ChatPosition position : chat.positions) {
- if (position.list.getConstructor() == TdApi.ChatListMain.CONSTRUCTOR) {
- boolean isRemoved = mainChatList.remove(new OrderedChat(chat.id, position));
- assert isRemoved;
- }
- }
-
- chat.positions = positions;
-
- for (TdApi.ChatPosition position : chat.positions) {
- if (position.list.getConstructor() == TdApi.ChatListMain.CONSTRUCTOR) {
- boolean isAdded = mainChatList.add(new OrderedChat(chat.id, position));
- assert isAdded;
- }
- }
- }
- }
- }
-
- private static void onAuthorizationStateUpdated(TdApi.AuthorizationState authorizationState) {
- if (authorizationState != null) {
- Example.authorizationState = authorizationState;
- }
- switch (Example.authorizationState.getConstructor()) {
- case TdApi.AuthorizationStateWaitTdlibParameters.CONSTRUCTOR:
- TdApi.SetTdlibParameters request = new TdApi.SetTdlibParameters();
- request.databaseDirectory = "tdlib";
- request.useMessageDatabase = true;
- request.useSecretChats = true;
- request.apiId = 94575;
- request.apiHash = "a3406de8d171bb422bb6ddf3bbd800e2";
- request.systemLanguageCode = "en";
- request.deviceModel = "Desktop";
- request.applicationVersion = "1.0";
- request.enableStorageOptimizer = true;
-
- client.send(request, new AuthorizationRequestHandler());
- break;
- case TdApi.AuthorizationStateWaitPhoneNumber.CONSTRUCTOR: {
- String phoneNumber = promptString("Please enter phone number: ");
- client.send(new TdApi.SetAuthenticationPhoneNumber(phoneNumber, null), new AuthorizationRequestHandler());
- break;
- }
- case TdApi.AuthorizationStateWaitOtherDeviceConfirmation.CONSTRUCTOR: {
- String link = ((TdApi.AuthorizationStateWaitOtherDeviceConfirmation) Example.authorizationState).link;
- System.out.println("Please confirm this login link on another device: " + link);
- break;
- }
- case TdApi.AuthorizationStateWaitEmailAddress.CONSTRUCTOR: {
- String emailAddress = promptString("Please enter email address: ");
- client.send(new TdApi.SetAuthenticationEmailAddress(emailAddress), new AuthorizationRequestHandler());
- break;
- }
- case TdApi.AuthorizationStateWaitEmailCode.CONSTRUCTOR: {
- String code = promptString("Please enter email authentication code: ");
- client.send(new TdApi.CheckAuthenticationEmailCode(new TdApi.EmailAddressAuthenticationCode(code)), new AuthorizationRequestHandler());
- break;
- }
- case TdApi.AuthorizationStateWaitCode.CONSTRUCTOR: {
- String code = promptString("Please enter authentication code: ");
- client.send(new TdApi.CheckAuthenticationCode(code), new AuthorizationRequestHandler());
- break;
- }
- case TdApi.AuthorizationStateWaitRegistration.CONSTRUCTOR: {
- String firstName = promptString("Please enter your first name: ");
- String lastName = promptString("Please enter your last name: ");
- client.send(new TdApi.RegisterUser(firstName, lastName), new AuthorizationRequestHandler());
- break;
- }
- case TdApi.AuthorizationStateWaitPassword.CONSTRUCTOR: {
- String password = promptString("Please enter password: ");
- client.send(new TdApi.CheckAuthenticationPassword(password), new AuthorizationRequestHandler());
- break;
- }
- case TdApi.AuthorizationStateReady.CONSTRUCTOR:
- haveAuthorization = true;
- authorizationLock.lock();
- try {
- gotAuthorization.signal();
- } finally {
- authorizationLock.unlock();
- }
- break;
- case TdApi.AuthorizationStateLoggingOut.CONSTRUCTOR:
- haveAuthorization = false;
- print("Logging out");
- break;
- case TdApi.AuthorizationStateClosing.CONSTRUCTOR:
- haveAuthorization = false;
- print("Closing");
- break;
- case TdApi.AuthorizationStateClosed.CONSTRUCTOR:
- print("Closed");
- if (!needQuit) {
- client = Client.create(new UpdateHandler(), null, null); // recreate client after previous has closed
- } else {
- canQuit = true;
- }
- break;
- default:
- System.err.println("Unsupported authorization state:" + newLine + Example.authorizationState);
- }
- }
-
- private static int toInt(String arg) {
- int result = 0;
- try {
- result = Integer.parseInt(arg);
- } catch (NumberFormatException ignored) {
- }
- return result;
- }
-
- private static long getChatId(String arg) {
- long chatId = 0;
- try {
- chatId = Long.parseLong(arg);
- } catch (NumberFormatException ignored) {
- }
- return chatId;
- }
-
- private static String promptString(String prompt) {
- System.out.print(prompt);
- currentPrompt = prompt;
- BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
- String str = "";
- try {
- str = reader.readLine();
- } catch (IOException e) {
- e.printStackTrace();
- }
- currentPrompt = null;
- return str;
- }
-
- private static void getCommand() {
- String command = promptString(commandsLine);
- String[] commands = command.split(" ", 2);
- try {
- switch (commands[0]) {
- case "gcs": {
- int limit = 20;
- if (commands.length > 1) {
- limit = toInt(commands[1]);
- }
- getMainChatList(limit);
- break;
- }
- case "gc":
- client.send(new TdApi.GetChat(getChatId(commands[1])), defaultHandler);
- break;
- case "me":
- client.send(new TdApi.GetMe(), defaultHandler);
- break;
- case "sm": {
- String[] args = commands[1].split(" ", 2);
- sendMessage(getChatId(args[0]), args[1]);
- break;
- }
- case "lo":
- haveAuthorization = false;
- client.send(new TdApi.LogOut(), defaultHandler);
- break;
- case "q":
- needQuit = true;
- haveAuthorization = false;
- client.send(new TdApi.Close(), defaultHandler);
- break;
- default:
- System.err.println("Unsupported command: " + command);
- }
- } catch (ArrayIndexOutOfBoundsException e) {
- print("Not enough arguments");
- }
- }
-
- private static void getMainChatList(final int limit) {
- synchronized (mainChatList) {
- if (!haveFullMainChatList && limit > mainChatList.size()) {
- // send LoadChats request if there are some unknown chats and have not enough known chats
- client.send(new TdApi.LoadChats(new TdApi.ChatListMain(), limit - mainChatList.size()), new Client.ResultHandler() {
- @Override
- public void onResult(TdApi.Object object) {
- switch (object.getConstructor()) {
- case TdApi.Error.CONSTRUCTOR:
- if (((TdApi.Error) object).code == 404) {
- synchronized (mainChatList) {
- haveFullMainChatList = true;
- }
- } else {
- System.err.println("Receive an error for LoadChats:" + newLine + object);
- }
- break;
- case TdApi.Ok.CONSTRUCTOR:
- // chats had already been received through updates, let's retry request
- getMainChatList(limit);
- break;
- default:
- System.err.println("Receive wrong response from TDLib:" + newLine + object);
- }
- }
- });
- return;
- }
-
- java.util.Iterator<OrderedChat> iter = mainChatList.iterator();
- System.out.println();
- System.out.println("First " + limit + " chat(s) out of " + mainChatList.size() + " known chat(s):");
- for (int i = 0; i < limit && i < mainChatList.size(); i++) {
- long chatId = iter.next().chatId;
- TdApi.Chat chat = chats.get(chatId);
- synchronized (chat) {
- System.out.println(chatId + ": " + chat.title);
- }
- }
- print("");
- }
- }
-
- private static void sendMessage(long chatId, String message) {
- // initialize reply markup just for testing
- TdApi.InlineKeyboardButton[] row = {new TdApi.InlineKeyboardButton("https://telegram.org?1", new TdApi.InlineKeyboardButtonTypeUrl()), new TdApi.InlineKeyboardButton("https://telegram.org?2", new TdApi.InlineKeyboardButtonTypeUrl()), new TdApi.InlineKeyboardButton("https://telegram.org?3", new TdApi.InlineKeyboardButtonTypeUrl())};
- TdApi.ReplyMarkup replyMarkup = new TdApi.ReplyMarkupInlineKeyboard(new TdApi.InlineKeyboardButton[][]{row, row, row});
-
- TdApi.InputMessageContent content = new TdApi.InputMessageText(new TdApi.FormattedText(message, null), false, true);
- client.send(new TdApi.SendMessage(chatId, 0, 0, null, replyMarkup, content), defaultHandler);
- }
-
- public static void main(String[] args) throws InterruptedException {
- // set log message handler to handle only fatal errors (0) and plain log messages (-1)
- Client.setLogMessageHandler(0, new LogMessageHandler());
-
- // disable TDLib log and redirect fatal errors and plain log messages to a file
- Client.execute(new TdApi.SetLogVerbosityLevel(0));
- if (Client.execute(new TdApi.SetLogStream(new TdApi.LogStreamFile("tdlib.log", 1 << 27, false))) instanceof TdApi.Error) {
- throw new IOError(new IOException("Write access to the current directory is required"));
- }
-
- // create client
- client = Client.create(new UpdateHandler(), null, null);
-
- // test Client.execute
- defaultHandler.onResult(Client.execute(new TdApi.GetTextEntities("@telegram /test_command https://telegram.org telegram.me @gif @test")));
-
- // main loop
- while (!needQuit) {
- // await authorization
- authorizationLock.lock();
- try {
- while (!haveAuthorization) {
- gotAuthorization.await();
- }
- } finally {
- authorizationLock.unlock();
- }
-
- while (haveAuthorization) {
- getCommand();
- }
- }
- while (!canQuit) {
- Thread.sleep(1);
- }
- }
-
- private static class OrderedChat implements Comparable<OrderedChat> {
- final long chatId;
- final TdApi.ChatPosition position;
-
- OrderedChat(long chatId, TdApi.ChatPosition position) {
- this.chatId = chatId;
- this.position = position;
- }
-
- @Override
- public int compareTo(OrderedChat o) {
- if (this.position.order != o.position.order) {
- return o.position.order < this.position.order ? -1 : 1;
- }
- if (this.chatId != o.chatId) {
- return o.chatId < this.chatId ? -1 : 1;
- }
- return 0;
- }
-
- @Override
- public boolean equals(Object obj) {
- OrderedChat o = (OrderedChat) obj;
- return this.chatId == o.chatId && this.position.order == o.position.order;
- }
- }
-
- private static class DefaultHandler implements Client.ResultHandler {
- @Override
- public void onResult(TdApi.Object object) {
- print(object.toString());
- }
- }
-
- private static class UpdateHandler implements Client.ResultHandler {
- @Override
- public void onResult(TdApi.Object object) {
- switch (object.getConstructor()) {
- case TdApi.UpdateAuthorizationState.CONSTRUCTOR:
- onAuthorizationStateUpdated(((TdApi.UpdateAuthorizationState) object).authorizationState);
- break;
-
- case TdApi.UpdateUser.CONSTRUCTOR:
- TdApi.UpdateUser updateUser = (TdApi.UpdateUser) object;
- users.put(updateUser.user.id, updateUser.user);
- break;
- case TdApi.UpdateUserStatus.CONSTRUCTOR: {
- TdApi.UpdateUserStatus updateUserStatus = (TdApi.UpdateUserStatus) object;
- TdApi.User user = users.get(updateUserStatus.userId);
- synchronized (user) {
- user.status = updateUserStatus.status;
- }
- break;
- }
- case TdApi.UpdateBasicGroup.CONSTRUCTOR:
- TdApi.UpdateBasicGroup updateBasicGroup = (TdApi.UpdateBasicGroup) object;
- basicGroups.put(updateBasicGroup.basicGroup.id, updateBasicGroup.basicGroup);
- break;
- case TdApi.UpdateSupergroup.CONSTRUCTOR:
- TdApi.UpdateSupergroup updateSupergroup = (TdApi.UpdateSupergroup) object;
- supergroups.put(updateSupergroup.supergroup.id, updateSupergroup.supergroup);
- break;
- case TdApi.UpdateSecretChat.CONSTRUCTOR:
- TdApi.UpdateSecretChat updateSecretChat = (TdApi.UpdateSecretChat) object;
- secretChats.put(updateSecretChat.secretChat.id, updateSecretChat.secretChat);
- break;
-
- case TdApi.UpdateNewChat.CONSTRUCTOR: {
- TdApi.UpdateNewChat updateNewChat = (TdApi.UpdateNewChat) object;
- TdApi.Chat chat = updateNewChat.chat;
- synchronized (chat) {
- chats.put(chat.id, chat);
-
- TdApi.ChatPosition[] positions = chat.positions;
- chat.positions = new TdApi.ChatPosition[0];
- setChatPositions(chat, positions);
- }
- break;
- }
- case TdApi.UpdateChatTitle.CONSTRUCTOR: {
- TdApi.UpdateChatTitle updateChat = (TdApi.UpdateChatTitle) object;
- TdApi.Chat chat = chats.get(updateChat.chatId);
- synchronized (chat) {
- chat.title = updateChat.title;
- }
- break;
- }
- case TdApi.UpdateChatPhoto.CONSTRUCTOR: {
- TdApi.UpdateChatPhoto updateChat = (TdApi.UpdateChatPhoto) object;
- TdApi.Chat chat = chats.get(updateChat.chatId);
- synchronized (chat) {
- chat.photo = updateChat.photo;
- }
- break;
- }
- case TdApi.UpdateChatLastMessage.CONSTRUCTOR: {
- TdApi.UpdateChatLastMessage updateChat = (TdApi.UpdateChatLastMessage) object;
- TdApi.Chat chat = chats.get(updateChat.chatId);
- synchronized (chat) {
- chat.lastMessage = updateChat.lastMessage;
- setChatPositions(chat, updateChat.positions);
- }
- break;
- }
- case TdApi.UpdateChatPosition.CONSTRUCTOR: {
- TdApi.UpdateChatPosition updateChat = (TdApi.UpdateChatPosition) object;
- if (updateChat.position.list.getConstructor() != TdApi.ChatListMain.CONSTRUCTOR) {
- break;
- }
-
- TdApi.Chat chat = chats.get(updateChat.chatId);
- synchronized (chat) {
- int i;
- for (i = 0; i < chat.positions.length; i++) {
- if (chat.positions[i].list.getConstructor() == TdApi.ChatListMain.CONSTRUCTOR) {
- break;
- }
- }
- TdApi.ChatPosition[] new_positions = new TdApi.ChatPosition[chat.positions.length + (updateChat.position.order == 0 ? 0 : 1) - (i < chat.positions.length ? 1 : 0)];
- int pos = 0;
- if (updateChat.position.order != 0) {
- new_positions[pos++] = updateChat.position;
- }
- for (int j = 0; j < chat.positions.length; j++) {
- if (j != i) {
- new_positions[pos++] = chat.positions[j];
- }
- }
- assert pos == new_positions.length;
-
- setChatPositions(chat, new_positions);
- }
- break;
- }
- case TdApi.UpdateChatReadInbox.CONSTRUCTOR: {
- TdApi.UpdateChatReadInbox updateChat = (TdApi.UpdateChatReadInbox) object;
- TdApi.Chat chat = chats.get(updateChat.chatId);
- synchronized (chat) {
- chat.lastReadInboxMessageId = updateChat.lastReadInboxMessageId;
- chat.unreadCount = updateChat.unreadCount;
- }
- break;
- }
- case TdApi.UpdateChatReadOutbox.CONSTRUCTOR: {
- TdApi.UpdateChatReadOutbox updateChat = (TdApi.UpdateChatReadOutbox) object;
- TdApi.Chat chat = chats.get(updateChat.chatId);
- synchronized (chat) {
- chat.lastReadOutboxMessageId = updateChat.lastReadOutboxMessageId;
- }
- break;
- }
- case TdApi.UpdateChatUnreadMentionCount.CONSTRUCTOR: {
- TdApi.UpdateChatUnreadMentionCount updateChat = (TdApi.UpdateChatUnreadMentionCount) object;
- TdApi.Chat chat = chats.get(updateChat.chatId);
- synchronized (chat) {
- chat.unreadMentionCount = updateChat.unreadMentionCount;
- }
- break;
- }
- case TdApi.UpdateMessageMentionRead.CONSTRUCTOR: {
- TdApi.UpdateMessageMentionRead updateChat = (TdApi.UpdateMessageMentionRead) object;
- TdApi.Chat chat = chats.get(updateChat.chatId);
- synchronized (chat) {
- chat.unreadMentionCount = updateChat.unreadMentionCount;
- }
- break;
- }
- case TdApi.UpdateChatReplyMarkup.CONSTRUCTOR: {
- TdApi.UpdateChatReplyMarkup updateChat = (TdApi.UpdateChatReplyMarkup) object;
- TdApi.Chat chat = chats.get(updateChat.chatId);
- synchronized (chat) {
- chat.replyMarkupMessageId = updateChat.replyMarkupMessageId;
- }
- break;
- }
- case TdApi.UpdateChatDraftMessage.CONSTRUCTOR: {
- TdApi.UpdateChatDraftMessage updateChat = (TdApi.UpdateChatDraftMessage) object;
- TdApi.Chat chat = chats.get(updateChat.chatId);
- synchronized (chat) {
- chat.draftMessage = updateChat.draftMessage;
- setChatPositions(chat, updateChat.positions);
- }
- break;
- }
- case TdApi.UpdateChatPermissions.CONSTRUCTOR: {
- TdApi.UpdateChatPermissions update = (TdApi.UpdateChatPermissions) object;
- TdApi.Chat chat = chats.get(update.chatId);
- synchronized (chat) {
- chat.permissions = update.permissions;
- }
- break;
- }
- case TdApi.UpdateChatNotificationSettings.CONSTRUCTOR: {
- TdApi.UpdateChatNotificationSettings update = (TdApi.UpdateChatNotificationSettings) object;
- TdApi.Chat chat = chats.get(update.chatId);
- synchronized (chat) {
- chat.notificationSettings = update.notificationSettings;
- }
- break;
- }
- case TdApi.UpdateChatDefaultDisableNotification.CONSTRUCTOR: {
- TdApi.UpdateChatDefaultDisableNotification update = (TdApi.UpdateChatDefaultDisableNotification) object;
- TdApi.Chat chat = chats.get(update.chatId);
- synchronized (chat) {
- chat.defaultDisableNotification = update.defaultDisableNotification;
- }
- break;
- }
- case TdApi.UpdateChatIsMarkedAsUnread.CONSTRUCTOR: {
- TdApi.UpdateChatIsMarkedAsUnread update = (TdApi.UpdateChatIsMarkedAsUnread) object;
- TdApi.Chat chat = chats.get(update.chatId);
- synchronized (chat) {
- chat.isMarkedAsUnread = update.isMarkedAsUnread;
- }
- break;
- }
- case TdApi.UpdateChatIsBlocked.CONSTRUCTOR: {
- TdApi.UpdateChatIsBlocked update = (TdApi.UpdateChatIsBlocked) object;
- TdApi.Chat chat = chats.get(update.chatId);
- synchronized (chat) {
- chat.isBlocked = update.isBlocked;
- }
- break;
- }
- case TdApi.UpdateChatHasScheduledMessages.CONSTRUCTOR: {
- TdApi.UpdateChatHasScheduledMessages update = (TdApi.UpdateChatHasScheduledMessages) object;
- TdApi.Chat chat = chats.get(update.chatId);
- synchronized (chat) {
- chat.hasScheduledMessages = update.hasScheduledMessages;
- }
- break;
- }
-
- case TdApi.UpdateUserFullInfo.CONSTRUCTOR:
- TdApi.UpdateUserFullInfo updateUserFullInfo = (TdApi.UpdateUserFullInfo) object;
- usersFullInfo.put(updateUserFullInfo.userId, updateUserFullInfo.userFullInfo);
- break;
- case TdApi.UpdateBasicGroupFullInfo.CONSTRUCTOR:
- TdApi.UpdateBasicGroupFullInfo updateBasicGroupFullInfo = (TdApi.UpdateBasicGroupFullInfo) object;
- basicGroupsFullInfo.put(updateBasicGroupFullInfo.basicGroupId, updateBasicGroupFullInfo.basicGroupFullInfo);
- break;
- case TdApi.UpdateSupergroupFullInfo.CONSTRUCTOR:
- TdApi.UpdateSupergroupFullInfo updateSupergroupFullInfo = (TdApi.UpdateSupergroupFullInfo) object;
- supergroupsFullInfo.put(updateSupergroupFullInfo.supergroupId, updateSupergroupFullInfo.supergroupFullInfo);
- break;
- default:
- // print("Unsupported update:" + newLine + object);
- }
- }
- }
-
- private static class AuthorizationRequestHandler implements Client.ResultHandler {
- @Override
- public void onResult(TdApi.Object object) {
- switch (object.getConstructor()) {
- case TdApi.Error.CONSTRUCTOR:
- System.err.println("Receive an error:" + newLine + object);
- onAuthorizationStateUpdated(null); // repeat last action
- break;
- case TdApi.Ok.CONSTRUCTOR:
- // result is already received through UpdateAuthorizationState, nothing to do
- break;
- default:
- System.err.println("Receive wrong response from TDLib:" + newLine + object);
- }
- }
- }
-
- private static class LogMessageHandler implements Client.LogMessageHandler {
- @Override
- public void onLogMessage(int verbosityLevel, String message) {
- if (verbosityLevel == 0) {
- onFatalError(message);
- return;
- }
- System.err.println(message);
- }
- }
-
- private static void onFatalError(String errorMessage) {
- final class ThrowError implements Runnable {
- private final String errorMessage;
- private final AtomicLong errorThrowTime;
-
- private ThrowError(String errorMessage, AtomicLong errorThrowTime) {
- this.errorMessage = errorMessage;
- this.errorThrowTime = errorThrowTime;
- }
-
- @Override
- public void run() {
- if (isDatabaseBrokenError(errorMessage) || isDiskFullError(errorMessage) || isDiskError(errorMessage)) {
- processExternalError();
- return;
- }
-
- errorThrowTime.set(System.currentTimeMillis());
- throw new ClientError("TDLib fatal error: " + errorMessage);
- }
-
- private void processExternalError() {
- errorThrowTime.set(System.currentTimeMillis());
- throw new ExternalClientError("Fatal error: " + errorMessage);
- }
-
- final class ClientError extends Error {
- private ClientError(String message) {
- super(message);
- }
- }
-
- final class ExternalClientError extends Error {
- public ExternalClientError(String message) {
- super(message);
- }
- }
-
- private boolean isDatabaseBrokenError(String message) {
- return message.contains("Wrong key or database is corrupted") ||
- message.contains("SQL logic error or missing database") ||
- message.contains("database disk image is malformed") ||
- message.contains("file is encrypted or is not a database") ||
- message.contains("unsupported file format") ||
- message.contains("Database was corrupted and deleted during execution and can't be recreated");
- }
-
- private boolean isDiskFullError(String message) {
- return message.contains("PosixError : No space left on device") ||
- message.contains("database or disk is full");
- }
-
- private boolean isDiskError(String message) {
- return message.contains("I/O error") || message.contains("Structure needs cleaning");
- }
- }
-
- final AtomicLong errorThrowTime = new AtomicLong(Long.MAX_VALUE);
- new Thread(new ThrowError(errorMessage, errorThrowTime), "TDLib fatal error thread").start();
-
- // wait at least 10 seconds after the error is thrown
- while (errorThrowTime.get() >= System.currentTimeMillis() - 10000) {
- try {
- Thread.sleep(1000 /* milliseconds */);
- } catch (InterruptedException ignore) {
- Thread.currentThread().interrupt();
- }
- }
- }
-}
diff --git a/protocols/Telegram/tdlib/td/example/java/td_jni.cpp b/protocols/Telegram/tdlib/td/example/java/td_jni.cpp
deleted file mode 100644
index 15c60a9545..0000000000
--- a/protocols/Telegram/tdlib/td/example/java/td_jni.cpp
+++ /dev/null
@@ -1,182 +0,0 @@
-//
-// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-//
-#include <td/telegram/Client.h>
-#include <td/telegram/td_api.h>
-
-#include <td/tl/tl_jni_object.h>
-
-#include <cstdint>
-#include <cstdlib>
-#include <string>
-#include <utility>
-
-namespace td_jni {
-
-static td::td_api::object_ptr<td::td_api::Function> fetch_function(JNIEnv *env, jobject function) {
- td::jni::reset_parse_error();
- auto result = td::td_api::Function::fetch(env, function);
- if (td::jni::have_parse_error()) {
- std::abort();
- }
- return result;
-}
-
-static td::ClientManager *get_manager() {
- return td::ClientManager::get_manager_singleton();
-}
-
-static jint Client_createNativeClient(JNIEnv *env, jclass clazz) {
- return static_cast<jint>(get_manager()->create_client_id());
-}
-
-static void Client_nativeClientSend(JNIEnv *env, jclass clazz, jint client_id, jlong id, jobject function) {
- get_manager()->send(static_cast<std::int32_t>(client_id), static_cast<std::uint64_t>(id),
- fetch_function(env, function));
-}
-
-static jint Client_nativeClientReceive(JNIEnv *env, jclass clazz, jintArray client_ids, jlongArray ids,
- jobjectArray events, jdouble timeout) {
- jsize events_size = env->GetArrayLength(ids); // client_ids, ids and events must be of equal size
- if (events_size == 0) {
- return 0;
- }
- jsize result_size = 0;
-
- auto *manager = get_manager();
- auto response = manager->receive(timeout);
- while (response.object) {
- auto client_id = static_cast<jint>(response.client_id);
- env->SetIntArrayRegion(client_ids, result_size, 1, &client_id);
-
- auto request_id = static_cast<jlong>(response.request_id);
- env->SetLongArrayRegion(ids, result_size, 1, &request_id);
-
- jobject object;
- response.object->store(env, object);
- env->SetObjectArrayElement(events, result_size, object);
- env->DeleteLocalRef(object);
-
- result_size++;
- if (result_size == events_size) {
- break;
- }
-
- response = manager->receive(0);
- }
- return result_size;
-}
-
-static jobject Client_nativeClientExecute(JNIEnv *env, jclass clazz, jobject function) {
- jobject result;
- td::ClientManager::execute(fetch_function(env, function))->store(env, result);
- return result;
-}
-
-static jstring Object_toString(JNIEnv *env, jobject object) {
- return td::jni::to_jstring(env, to_string(td::td_api::Object::fetch(env, object)));
-}
-
-static jstring Function_toString(JNIEnv *env, jobject object) {
- return td::jni::to_jstring(env, to_string(td::td_api::Function::fetch(env, object)));
-}
-
-static constexpr jint JAVA_VERSION = JNI_VERSION_1_6;
-static JavaVM *java_vm;
-static jobject log_message_handler;
-
-static void on_log_message(int verbosity_level, const char *log_message) {
- auto env = td::jni::get_jni_env(java_vm, JAVA_VERSION);
- if (env == nullptr) {
- return;
- }
-
- jobject handler = env->NewLocalRef(log_message_handler);
- if (!handler) {
- return;
- }
-
- jclass handler_class = env->GetObjectClass(handler);
- if (handler_class) {
- jmethodID on_log_message_method = env->GetMethodID(handler_class, "onLogMessage", "(ILjava/lang/String;)V");
- if (on_log_message_method) {
- jstring log_message_str = td::jni::to_jstring(env.get(), log_message);
- if (log_message_str) {
- env->CallVoidMethod(handler, on_log_message_method, static_cast<jint>(verbosity_level), log_message_str);
- env->DeleteLocalRef((jobject)log_message_str);
- }
- }
- env->DeleteLocalRef((jobject)handler_class);
- }
-
- env->DeleteLocalRef(handler);
-}
-
-static void Client_nativeClientSetLogMessageHandler(JNIEnv *env, jclass clazz, jint max_verbosity_level,
- jobject new_log_message_handler) {
- if (log_message_handler) {
- td::ClientManager::set_log_message_callback(0, nullptr);
- jobject old_log_message_handler = log_message_handler;
- log_message_handler = jobject();
- env->DeleteGlobalRef(old_log_message_handler);
- }
-
- if (new_log_message_handler) {
- log_message_handler = env->NewGlobalRef(new_log_message_handler);
- if (!log_message_handler) {
- // out of memory
- return;
- }
-
- td::ClientManager::set_log_message_callback(static_cast<int>(max_verbosity_level), on_log_message);
- }
-}
-
-static jint register_native(JavaVM *vm) {
- JNIEnv *env;
- if (vm->GetEnv(reinterpret_cast<void **>(&env), JAVA_VERSION) != JNI_OK) {
- return -1;
- }
-
- java_vm = vm;
-
- auto register_method = [env](jclass clazz, std::string name, std::string signature, auto function_ptr) {
- td::jni::register_native_method(env, clazz, std::move(name), std::move(signature),
- reinterpret_cast<void *>(function_ptr));
- };
-
- auto client_class = td::jni::get_jclass(env, PACKAGE_NAME "/Client");
- auto object_class = td::jni::get_jclass(env, PACKAGE_NAME "/TdApi$Object");
- auto function_class = td::jni::get_jclass(env, PACKAGE_NAME "/TdApi$Function");
-
-#define TD_OBJECT "L" PACKAGE_NAME "/TdApi$Object;"
-#define TD_FUNCTION "L" PACKAGE_NAME "/TdApi$Function;"
- register_method(client_class, "createNativeClient", "()I", Client_createNativeClient);
- register_method(client_class, "nativeClientSend", "(IJ" TD_FUNCTION ")V", Client_nativeClientSend);
- register_method(client_class, "nativeClientReceive", "([I[J[" TD_OBJECT "D)I", Client_nativeClientReceive);
- register_method(client_class, "nativeClientExecute", "(" TD_FUNCTION ")" TD_OBJECT, Client_nativeClientExecute);
- register_method(client_class, "nativeClientSetLogMessageHandler", "(IL" PACKAGE_NAME "/Client$LogMessageHandler;)V",
- Client_nativeClientSetLogMessageHandler);
-
- register_method(object_class, "toString", "()Ljava/lang/String;", Object_toString);
-
- register_method(function_class, "toString", "()Ljava/lang/String;", Function_toString);
-#undef TD_FUNCTION
-#undef TD_OBJECT
-
- td::jni::init_vars(env, PACKAGE_NAME);
- td::td_api::Object::init_jni_vars(env, PACKAGE_NAME);
- td::td_api::Function::init_jni_vars(env, PACKAGE_NAME);
-
- return JAVA_VERSION;
-}
-
-} // namespace td_jni
-
-JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
- static jint jni_version = td_jni::register_native(vm); // call_once
- return jni_version;
-}