Merge branch 'master' into dev
This commit is contained in:
commit
903df5899c
4
.gitattributes
vendored
4
.gitattributes
vendored
@ -5,6 +5,7 @@
|
|||||||
*.h text whitespace=blank-at-eol,space-before-tab,blank-at-eof,tab-in-indent
|
*.h text whitespace=blank-at-eol,space-before-tab,blank-at-eof,tab-in-indent
|
||||||
*.c text whitespace=blank-at-eol,space-before-tab,blank-at-eof,tab-in-indent
|
*.c text whitespace=blank-at-eol,space-before-tab,blank-at-eof,tab-in-indent
|
||||||
*.tl text whitespace=blank-at-eol,space-before-tab,blank-at-eof,tab-in-indent
|
*.tl text whitespace=blank-at-eol,space-before-tab,blank-at-eof,tab-in-indent
|
||||||
|
*.mm text whitespace=blank-at-eol,space-before-tab,blank-at-eof,tab-in-indent
|
||||||
*.txt text whitespace=blank-at-eol,space-before-tab,blank-at-eof,tab-in-indent
|
*.txt text whitespace=blank-at-eol,space-before-tab,blank-at-eof,tab-in-indent
|
||||||
*.sh text whitespace=blank-at-eol,space-before-tab,blank-at-eof,tab-in-indent eol=lf
|
*.sh text whitespace=blank-at-eol,space-before-tab,blank-at-eof,tab-in-indent eol=lf
|
||||||
*.php text whitespace=blank-at-eol,space-before-tab,blank-at-eof,tab-in-indent
|
*.php text whitespace=blank-at-eol,space-before-tab,blank-at-eof,tab-in-indent
|
||||||
@ -18,6 +19,7 @@
|
|||||||
*.java text whitespace=blank-at-eol,space-before-tab,blank-at-eof,tab-in-indent
|
*.java text whitespace=blank-at-eol,space-before-tab,blank-at-eof,tab-in-indent
|
||||||
*.py text whitespace=blank-at-eol,space-before-tab,blank-at-eof,tab-in-indent
|
*.py text whitespace=blank-at-eol,space-before-tab,blank-at-eof,tab-in-indent
|
||||||
*.js text whitespace=blank-at-eol,space-before-tab,blank-at-eof,tab-in-indent
|
*.js text whitespace=blank-at-eol,space-before-tab,blank-at-eof,tab-in-indent
|
||||||
|
*.patch text whitespace=blank-at-eol,space-before-tab,blank-at-eof,tab-in-indent
|
||||||
*.swift text whitespace=blank-at-eol,space-before-tab,blank-at-eof,tab-in-indent
|
*.swift text whitespace=blank-at-eol,space-before-tab,blank-at-eof,tab-in-indent
|
||||||
*.pbxproj text whitespace=blank-at-eol,space-before-tab,blank-at-eof,tab-in-indent
|
*.pbxproj text whitespace=blank-at-eol,space-before-tab,blank-at-eof,tab-in-indent
|
||||||
*.cs text whitespace=blank-at-eol,space-before-tab,blank-at-eof,tab-in-indent
|
*.cs text whitespace=blank-at-eol,space-before-tab,blank-at-eof,tab-in-indent
|
||||||
@ -32,7 +34,5 @@
|
|||||||
|
|
||||||
sqlite/sqlite/* linguist-vendored
|
sqlite/sqlite/* linguist-vendored
|
||||||
|
|
||||||
*.tlo binary
|
|
||||||
|
|
||||||
*.pfx binary
|
*.pfx binary
|
||||||
*.png binary
|
*.png binary
|
||||||
|
@ -5,6 +5,8 @@ function(td_set_up_compiler)
|
|||||||
|
|
||||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON PARENT_SCOPE)
|
set(CMAKE_POSITION_INDEPENDENT_CODE ON PARENT_SCOPE)
|
||||||
|
|
||||||
|
include(illumos)
|
||||||
|
|
||||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||||
set(GCC 1)
|
set(GCC 1)
|
||||||
set(GCC 1 PARENT_SCOPE)
|
set(GCC 1 PARENT_SCOPE)
|
||||||
@ -40,11 +42,6 @@ function(td_set_up_compiler)
|
|||||||
message(FATAL_ERROR "No C++14 support in the compiler. Please upgrade the compiler.")
|
message(FATAL_ERROR "No C++14 support in the compiler. Please upgrade the compiler.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
|
|
||||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
|
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
|
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
if (CMAKE_CXX_FLAGS_DEBUG MATCHES "/RTC1")
|
if (CMAKE_CXX_FLAGS_DEBUG MATCHES "/RTC1")
|
||||||
string(REPLACE "/RTC1" " " CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
|
string(REPLACE "/RTC1" " " CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
|
||||||
@ -55,10 +52,17 @@ function(td_set_up_compiler)
|
|||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${STD14_FLAG} -fno-omit-frame-pointer -fno-exceptions -fno-rtti")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${STD14_FLAG} -fno-omit-frame-pointer -fno-exceptions -fno-rtti")
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-dead_strip,-x,-S")
|
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-dead_strip,-x,-S")
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-dead_strip,-x,-S")
|
||||||
else()
|
else()
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffunction-sections -fdata-sections")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffunction-sections -fdata-sections")
|
||||||
|
if (CMAKE_SYSTEM_NAME STREQUAL "SunOS")
|
||||||
|
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,ignore")
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,ignore")
|
||||||
|
else()
|
||||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--gc-sections -Wl,--exclude-libs,ALL")
|
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--gc-sections -Wl,--exclude-libs,ALL")
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections -Wl,--exclude-libs,ALL")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (WIN32 OR CYGWIN)
|
if (WIN32 OR CYGWIN)
|
||||||
@ -81,6 +85,13 @@ function(td_set_up_compiler)
|
|||||||
add_definitions(-D_FILE_OFFSET_BITS=64)
|
add_definitions(-D_FILE_OFFSET_BITS=64)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (CMAKE_SYSTEM_NAME STREQUAL "SunOS")
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lsocket -lnsl")
|
||||||
|
if (ILLUMOS)
|
||||||
|
add_definitions(-DTD_ILLUMOS=1)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
include(AddCXXCompilerFlag)
|
include(AddCXXCompilerFlag)
|
||||||
if (NOT MSVC)
|
if (NOT MSVC)
|
||||||
add_cxx_compiler_flag("-Wall")
|
add_cxx_compiler_flag("-Wall")
|
||||||
@ -141,5 +152,6 @@ function(td_set_up_compiler)
|
|||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" PARENT_SCOPE)
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" PARENT_SCOPE)
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}" PARENT_SCOPE)
|
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}" PARENT_SCOPE)
|
||||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}" PARENT_SCOPE)
|
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}" PARENT_SCOPE)
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}" PARENT_SCOPE)
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" PARENT_SCOPE)
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" PARENT_SCOPE)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
@ -197,9 +197,9 @@ if (IOS_PLATFORM STREQUAL "OS")
|
|||||||
elseif (IOS_PLATFORM STREQUAL "SIMULATOR")
|
elseif (IOS_PLATFORM STREQUAL "SIMULATOR")
|
||||||
set (IOS_ARCH "i386;x86_64")
|
set (IOS_ARCH "i386;x86_64")
|
||||||
elseif (IOS_PLATFORM STREQUAL "WATCHOS")
|
elseif (IOS_PLATFORM STREQUAL "WATCHOS")
|
||||||
set (IOS_ARCH "armv7k")
|
set (IOS_ARCH "armv7k;arm64_32")
|
||||||
elseif (IOS_PLATFORM STREQUAL "WATCHSIMULATOR")
|
elseif (IOS_PLATFORM STREQUAL "WATCHSIMULATOR")
|
||||||
set (IOS_ARCH "i386")
|
set (IOS_ARCH "i386;x86_64")
|
||||||
elseif (IOS_PLATFORM STREQUAL "TVOS")
|
elseif (IOS_PLATFORM STREQUAL "TVOS")
|
||||||
set (IOS_ARCH "arm64")
|
set (IOS_ARCH "arm64")
|
||||||
elseif (IOS_PLATFORM STREQUAL "TVSIMULATOR")
|
elseif (IOS_PLATFORM STREQUAL "TVSIMULATOR")
|
||||||
|
10
CMake/illumos.cmake
Normal file
10
CMake/illumos.cmake
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
if (CMAKE_SYSTEM_NAME STREQUAL "SunOS")
|
||||||
|
#
|
||||||
|
# Determine if the host is running an illumos distribution:
|
||||||
|
#
|
||||||
|
execute_process(COMMAND /usr/bin/uname -o OUTPUT_VARIABLE UNAME_O OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
|
||||||
|
if (UNAME_O STREQUAL "illumos")
|
||||||
|
set(ILLUMOS 1)
|
||||||
|
endif()
|
||||||
|
endif()
|
@ -1,6 +1,6 @@
|
|||||||
cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR)
|
cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR)
|
||||||
|
|
||||||
project(TDLib VERSION 1.7.2 LANGUAGES CXX C)
|
project(TDLib VERSION 1.7.4 LANGUAGES CXX C)
|
||||||
|
|
||||||
if (NOT DEFINED CMAKE_MODULE_PATH)
|
if (NOT DEFINED CMAKE_MODULE_PATH)
|
||||||
set(CMAKE_MODULE_PATH "")
|
set(CMAKE_MODULE_PATH "")
|
||||||
@ -31,6 +31,7 @@ prevent_in_source_build()
|
|||||||
|
|
||||||
option(TD_ENABLE_JNI "Use \"ON\" to enable JNI-compatible TDLib API.")
|
option(TD_ENABLE_JNI "Use \"ON\" to enable JNI-compatible TDLib API.")
|
||||||
option(TD_ENABLE_DOTNET "Use \"ON\" to enable generation of C++/CLI or C++/CX TDLib API bindings.")
|
option(TD_ENABLE_DOTNET "Use \"ON\" to enable generation of C++/CLI or C++/CX TDLib API bindings.")
|
||||||
|
option(TD_EXPERIMENTAL_WATCH_OS "Use \"ON\" to enable watch os support.")
|
||||||
|
|
||||||
if (TD_ENABLE_DOTNET AND (CMAKE_VERSION VERSION_LESS "3.1.0"))
|
if (TD_ENABLE_DOTNET AND (CMAKE_VERSION VERSION_LESS "3.1.0"))
|
||||||
message(FATAL_ERROR "CMake 3.1.0 or higher is required. You are running version ${CMAKE_VERSION}.")
|
message(FATAL_ERROR "CMake 3.1.0 or higher is required. You are running version ${CMAKE_VERSION}.")
|
||||||
@ -325,6 +326,7 @@ set(TDLIB_SOURCE
|
|||||||
td/telegram/Global.cpp
|
td/telegram/Global.cpp
|
||||||
td/telegram/GroupCallManager.cpp
|
td/telegram/GroupCallManager.cpp
|
||||||
td/telegram/GroupCallParticipant.cpp
|
td/telegram/GroupCallParticipant.cpp
|
||||||
|
td/telegram/GroupCallParticipantOrder.cpp
|
||||||
td/telegram/HashtagHints.cpp
|
td/telegram/HashtagHints.cpp
|
||||||
td/telegram/InlineQueriesManager.cpp
|
td/telegram/InlineQueriesManager.cpp
|
||||||
td/telegram/InputDialogId.cpp
|
td/telegram/InputDialogId.cpp
|
||||||
@ -505,6 +507,7 @@ set(TDLIB_SOURCE
|
|||||||
td/telegram/GroupCallId.h
|
td/telegram/GroupCallId.h
|
||||||
td/telegram/GroupCallManager.h
|
td/telegram/GroupCallManager.h
|
||||||
td/telegram/GroupCallParticipant.h
|
td/telegram/GroupCallParticipant.h
|
||||||
|
td/telegram/GroupCallParticipantOrder.h
|
||||||
td/telegram/HashtagHints.h
|
td/telegram/HashtagHints.h
|
||||||
td/telegram/InlineQueriesManager.h
|
td/telegram/InlineQueriesManager.h
|
||||||
td/telegram/InputDialogId.h
|
td/telegram/InputDialogId.h
|
||||||
|
23
README.md
23
README.md
@ -11,8 +11,8 @@ TDLib developers strongly advise against the use of this feature, since it is no
|
|||||||
### Memory cleanup
|
### Memory cleanup
|
||||||
TDLight can clean itself and release some ram to the OS if you want. Look at **TdApi.OptimizeMemory** in "Modified features" paragraph to see how.
|
TDLight can clean itself and release some ram to the OS if you want. Look at **TdApi.OptimizeMemory** in "Modified features" paragraph to see how.
|
||||||
|
|
||||||
### (Almost) constant memory usage
|
### Constant memory usage without restarting
|
||||||
TDLight if used with care doesn't grow in memory usage with time. Look at **TdApi.OptimizeMemory** in "Modified features" paragraph to see how
|
TDLight, if used with care, doesn't grow in memory usage with time. Look at **TdApi.OptimizeMemory** in "Modified features" paragraph to see how
|
||||||
|
|
||||||
![memory usage](info/memory-usage.jpg)
|
![memory usage](info/memory-usage.jpg)
|
||||||
|
|
||||||
@ -30,13 +30,18 @@ We added some options:
|
|||||||
* **delete_file_reference_after_seconds** (positive number) During cleanup, free the memory of the files that have not been touched for more than X seconds
|
* **delete_file_reference_after_seconds** (positive number) During cleanup, free the memory of the files that have not been touched for more than X seconds
|
||||||
* **experiment_enable_file_reference_cleanup** (**true**/false) During cleanup, free the memory of the file references
|
* **experiment_enable_file_reference_cleanup** (**true**/false) During cleanup, free the memory of the file references
|
||||||
* **experiment_enable_chat_access_hash_cleanup** (**true**/false) During cleanup, clean chats and channels access hash
|
* **experiment_enable_chat_access_hash_cleanup** (**true**/false) During cleanup, clean chats and channels access hash
|
||||||
|
* **enable_pull_based_backpressure** (true/**false**) Enable manual `get_channel_difference` execution by calling `getChannelDifference(channel_difference_id)`.
|
||||||
|
Don't modify this option unless you have a very large bot that struggles to keep up with start-up updates throughput, or you want to implement a pull-based async library.
|
||||||
|
|
||||||
## Custom API functions
|
## Custom API functions
|
||||||
### TdApi.OptimizeMemory
|
### TdApi.OptimizeMemory
|
||||||
This method is used to optimize the memory usage, but it must be used carefully.
|
This method is used to optimize the memory usage, but it must be used carefully.
|
||||||
It removes almost all cached values and releases the memory back to the OS.
|
It removes almost all cached values and releases the memory back to the OS.
|
||||||
|
|
||||||
Removing cached values can cause problems if you don't take the following precautions:
|
You can call TdApi.OptimizeMemory normally, but removing cached values
|
||||||
|
can cause problems if you don't take some precautions.
|
||||||
|
|
||||||
|
If you want to avoid receiving data with missing fields during cleanup:
|
||||||
1. Before calling *TdApi.OptimizeMemory* you must:
|
1. Before calling *TdApi.OptimizeMemory* you must:
|
||||||
1. Read all the pending updates to empty the pending updates queue.
|
1. Read all the pending updates to empty the pending updates queue.
|
||||||
2. Disable internet connection using *TdApi.SetNetworkType(TdApi.NetworkTypeNone)*
|
2. Disable internet connection using *TdApi.SetNetworkType(TdApi.NetworkTypeNone)*
|
||||||
@ -49,12 +54,6 @@ Removing cached values can cause problems if you don't take the following precau
|
|||||||
This method is used to read the size of all the biggest data maps inside tdlib implementation.
|
This method is used to read the size of all the biggest data maps inside tdlib implementation.
|
||||||
The output contains a string that can be parsed as a JSON.
|
The output contains a string that can be parsed as a JSON.
|
||||||
|
|
||||||
## Removed features
|
|
||||||
### Local databases encryption
|
|
||||||
Local databases are no longer encrypted and deleted data is no longer overwritten with zeroes. This reduces IOPS and helps TDLight preserving SSDs life.
|
|
||||||
### Local text indicization
|
|
||||||
TDLight removed completely local text indicization, so if you search for some text it will search it through telegram servers.
|
|
||||||
|
|
||||||
## Other reccomended options
|
## Other reccomended options
|
||||||
* Options:
|
* Options:
|
||||||
* ignore_inline_thumbnails: true
|
* ignore_inline_thumbnails: true
|
||||||
@ -63,6 +62,8 @@ TDLight removed completely local text indicization, so if you search for some te
|
|||||||
* ignore_sensitive_content_restrictions: true
|
* ignore_sensitive_content_restrictions: true
|
||||||
* Disable all the databases (messages_db, users_db, files_db)
|
* Disable all the databases (messages_db, users_db, files_db)
|
||||||
|
|
||||||
|
⚠️ If you use the databases, TDLight memory cleanup feature will be automatically disabled, because databases will lose some data when cleaning up the memory.
|
||||||
|
|
||||||
|
|
||||||
-----
|
-----
|
||||||
|
|
||||||
@ -90,7 +91,7 @@ TDLib (Telegram Database library) is a cross-platform library for building [Tele
|
|||||||
|
|
||||||
`TDLib` has many advantages. Notably `TDLib` is:
|
`TDLib` has many advantages. Notably `TDLib` is:
|
||||||
|
|
||||||
* **Cross-platform**: `TDLib` can be used on Android, iOS, Windows, macOS, Linux, FreeBSD, OpenBSD, NetBSD, Windows Phone, WebAssembly, watchOS, tvOS, Tizen, Cygwin. It should also work on other *nix systems with or without minimal effort.
|
* **Cross-platform**: `TDLib` can be used on Android, iOS, Windows, macOS, Linux, FreeBSD, OpenBSD, NetBSD, illumos, Windows Phone, WebAssembly, watchOS, tvOS, Tizen, Cygwin. It should also work on other *nix systems with or without minimal effort.
|
||||||
* **Multilanguage**: `TDLib` can be easily used with any programming language that is able to execute C functions. Additionally it already has native Java (using `JNI`) bindings and .NET (using `C++/CLI` and `C++/CX`) bindings.
|
* **Multilanguage**: `TDLib` can be easily used with any programming language that is able to execute C functions. Additionally it already has native Java (using `JNI`) bindings and .NET (using `C++/CLI` and `C++/CX`) bindings.
|
||||||
* **Easy to use**: `TDLib` takes care of all network implementation details, encryption and local data storage.
|
* **Easy to use**: `TDLib` takes care of all network implementation details, encryption and local data storage.
|
||||||
* **High-performance**: in the [Telegram Bot API](https://core.telegram.org/bots/api), each `TDLib` instance handles more than 24000 active bots simultaneously.
|
* **High-performance**: in the [Telegram Bot API](https://core.telegram.org/bots/api), each `TDLib` instance handles more than 24000 active bots simultaneously.
|
||||||
@ -216,7 +217,7 @@ target_link_libraries(YourTarget PRIVATE Td::TdStatic)
|
|||||||
|
|
||||||
Or you could install `TDLib` and then reference it in your CMakeLists.txt like this:
|
Or you could install `TDLib` and then reference it in your CMakeLists.txt like this:
|
||||||
```
|
```
|
||||||
find_package(Td 1.7.2 REQUIRED)
|
find_package(Td 1.7.4 REQUIRED)
|
||||||
target_link_libraries(YourTarget PRIVATE Td::TdStatic)
|
target_link_libraries(YourTarget PRIVATE Td::TdStatic)
|
||||||
```
|
```
|
||||||
See [example/cpp/CMakeLists.txt](https://github.com/tdlib/td/tree/master/example/cpp/CMakeLists.txt).
|
See [example/cpp/CMakeLists.txt](https://github.com/tdlib/td/tree/master/example/cpp/CMakeLists.txt).
|
||||||
|
@ -278,12 +278,15 @@ function split_file($file, $chunks, $undo) {
|
|||||||
'animations_manager[_(-][^.]|AnimationsManager[^;>]' => "AnimationsManager",
|
'animations_manager[_(-][^.]|AnimationsManager[^;>]' => "AnimationsManager",
|
||||||
'audios_manager[_(-][^.]|AudiosManager' => "AudiosManager",
|
'audios_manager[_(-][^.]|AudiosManager' => "AudiosManager",
|
||||||
'auth_manager[_(-][^.]|AuthManager' => 'AuthManager',
|
'auth_manager[_(-][^.]|AuthManager' => 'AuthManager',
|
||||||
|
'background_manager[_(-][^.]|BackgroundManager' => "BackgroundManager",
|
||||||
'ConfigShared|shared_config[(]' => 'ConfigShared',
|
'ConfigShared|shared_config[(]' => 'ConfigShared',
|
||||||
'contacts_manager[_(-][^.]|ContactsManager([^ ;.]| [^*])' => 'ContactsManager',
|
'contacts_manager[_(-][^.]|ContactsManager([^ ;.]| [^*])' => 'ContactsManager',
|
||||||
|
'country_info_manager[_(-][^.]|CountryInfoManager' => 'CountryInfoManager',
|
||||||
'documents_manager[_(-][^.]|DocumentsManager' => "DocumentsManager",
|
'documents_manager[_(-][^.]|DocumentsManager' => "DocumentsManager",
|
||||||
'file_reference_manager[_(-][^.]|FileReferenceManager|file_references[)]' => 'FileReferenceManager',
|
'file_reference_manager[_(-][^.]|FileReferenceManager|file_references[)]' => 'FileReferenceManager',
|
||||||
'file_manager[_(-][^.]|FileManager([^ ;.]| [^*])|update_file[)]' => 'files/FileManager',
|
'file_manager[_(-][^.]|FileManager([^ ;.]| [^*])|update_file[)]' => 'files/FileManager',
|
||||||
'G[(][)]|Global[^A-Za-z]' => 'Global',
|
'G[(][)]|Global[^A-Za-z]' => 'Global',
|
||||||
|
'group_call_manager[_(-][^.]|GroupCallManager' => 'GroupCallManager',
|
||||||
'HashtagHints' => 'HashtagHints',
|
'HashtagHints' => 'HashtagHints',
|
||||||
'inline_queries_manager[_(-][^.]|InlineQueriesManager' => 'InlineQueriesManager',
|
'inline_queries_manager[_(-][^.]|InlineQueriesManager' => 'InlineQueriesManager',
|
||||||
'language_pack_manager[_(-][^.]|LanguagePackManager' => 'LanguagePackManager',
|
'language_pack_manager[_(-][^.]|LanguagePackManager' => 'LanguagePackManager',
|
||||||
@ -291,6 +294,8 @@ function split_file($file, $chunks, $undo) {
|
|||||||
'MessageCopyOptions' => 'MessageCopyOptions',
|
'MessageCopyOptions' => 'MessageCopyOptions',
|
||||||
'messages_manager[_(-][^.]|MessagesManager' => 'MessagesManager',
|
'messages_manager[_(-][^.]|MessagesManager' => 'MessagesManager',
|
||||||
'notification_manager[_(-][^.]|NotificationManager|notifications[)]' => 'NotificationManager',
|
'notification_manager[_(-][^.]|NotificationManager|notifications[)]' => 'NotificationManager',
|
||||||
|
'phone_number_manager[_(-][^.]|PhoneNumberManager' => "PhoneNumberManager",
|
||||||
|
'poll_manager[_(-][^.]|PollManager' => "PollManager",
|
||||||
'PublicDialogType|get_public_dialog_type' => 'PublicDialogType',
|
'PublicDialogType|get_public_dialog_type' => 'PublicDialogType',
|
||||||
'SecretChatActor' => 'SecretChatActor',
|
'SecretChatActor' => 'SecretChatActor',
|
||||||
'secret_chats_manager[_(-][^.]|SecretChatsManager' => 'SecretChatsManager',
|
'secret_chats_manager[_(-][^.]|SecretChatsManager' => 'SecretChatsManager',
|
||||||
|
44
build.html
44
build.html
@ -2,7 +2,7 @@
|
|||||||
<html>
|
<html>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title>TDLib build instructions</title>
|
<title>TDLight build instructions</title>
|
||||||
<style>
|
<style>
|
||||||
.hide { display: none; }
|
.hide { display: none; }
|
||||||
div.main { max-width:1200px; margin: auto; font-size: x-large; }
|
div.main { max-width:1200px; margin: auto; font-size: x-large; }
|
||||||
@ -14,7 +14,7 @@ select.large { font-size: large; }
|
|||||||
|
|
||||||
<div class="main">
|
<div class="main">
|
||||||
<div id="languageSelectDiv" style="text-align:center;">
|
<div id="languageSelectDiv" style="text-align:center;">
|
||||||
<p>Choose a programming language, from which you want to use TDLib:</p>
|
<p>Choose a programming language, from which you want to use TDLight:</p>
|
||||||
<select id="languageSelect" onchange="onLanguageChanged(false)" autofocus class="large">
|
<select id="languageSelect" onchange="onLanguageChanged(false)" autofocus class="large">
|
||||||
<option>Choose a programming language:</option>
|
<option>Choose a programming language:</option>
|
||||||
<option>Python</option>
|
<option>Python</option>
|
||||||
@ -45,7 +45,7 @@ select.large { font-size: large; }
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="osSelectDiv" class="hide" style="text-align:center;">
|
<div id="osSelectDiv" class="hide" style="text-align:center;">
|
||||||
<p>Choose an operating system, on which you want to use TDLib:</p>
|
<p>Choose an operating system, on which you want to use TDLight:</p>
|
||||||
<select id="osSelect" onchange="onOsChanged()" class="large">
|
<select id="osSelect" onchange="onOsChanged()" class="large">
|
||||||
<option>Choose an operating system:</option>
|
<option>Choose an operating system:</option>
|
||||||
</select>
|
</select>
|
||||||
@ -53,7 +53,7 @@ select.large { font-size: large; }
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="linuxSelectDiv" class="hide" style="text-align:center;">
|
<div id="linuxSelectDiv" class="hide" style="text-align:center;">
|
||||||
<p>Choose a Linux distro, on which you want to use TDLib:</p>
|
<p>Choose a Linux distro, on which you want to use TDLight:</p>
|
||||||
<select id="linuxSelect" onchange="onOsChanged()" class="large">
|
<select id="linuxSelect" onchange="onOsChanged()" class="large">
|
||||||
<option>Choose a Linux distro:</option>
|
<option>Choose a Linux distro:</option>
|
||||||
<option>Alpine</option>
|
<option>Alpine</option>
|
||||||
@ -81,13 +81,13 @@ select.large { font-size: large; }
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="buildInstallLocalDiv" class="hide">
|
<div id="buildInstallLocalDiv" class="hide">
|
||||||
<label><input type="checkbox" id="buildInstallLocalCheckbox" onchange="onOptionsChanged()"/>Install built TDLib to /usr/local instead of placing the files to td/tdlib.</label>
|
<label><input type="checkbox" id="buildInstallLocalCheckbox" onchange="onOptionsChanged()"/>Install built TDLight to /usr/local instead of placing the files to td/tdlib.</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p></p>
|
<p></p>
|
||||||
|
|
||||||
<div id="buildCompilerDiv" class="hide">
|
<div id="buildCompilerDiv" class="hide">
|
||||||
<span>Choose which compiler you want to use to build TDLib:</span><br>
|
<span>Choose which compiler you want to use to build TDLight:</span><br>
|
||||||
<label><input type="radio" id="buildCompilerRadioGcc" name="buildCompilerRadio" onchange="onOptionsChanged()" checked/>g++</label>
|
<label><input type="radio" id="buildCompilerRadioGcc" name="buildCompilerRadio" onchange="onOptionsChanged()" checked/>g++</label>
|
||||||
<label><input type="radio" id="buildCompilerRadioClang" name="buildCompilerRadio" onchange="onOptionsChanged()"/>clang (recommended)</label>
|
<label><input type="radio" id="buildCompilerRadioClang" name="buildCompilerRadio" onchange="onOptionsChanged()"/>clang (recommended)</label>
|
||||||
<p></p>
|
<p></p>
|
||||||
@ -116,7 +116,7 @@ select.large { font-size: large; }
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="buildBitnessDiv" class="hide">
|
<div id="buildBitnessDiv" class="hide">
|
||||||
<span>Choose for which bitness you want to build TDLib:</span><br>
|
<span>Choose for which bitness you want to build TDLight:</span><br>
|
||||||
<label><input type="radio" id="buildBitnessRadio32" name="buildBitnessRadio" onchange="onOptionsChanged()" checked/>32</label>
|
<label><input type="radio" id="buildBitnessRadio32" name="buildBitnessRadio" onchange="onOptionsChanged()" checked/>32</label>
|
||||||
<label><input type="radio" id="buildBitnessRadio64" name="buildBitnessRadio" onchange="onOptionsChanged()"/>64</label>
|
<label><input type="radio" id="buildBitnessRadio64" name="buildBitnessRadio" onchange="onOptionsChanged()"/>64</label>
|
||||||
<p></p>
|
<p></p>
|
||||||
@ -138,7 +138,7 @@ select.large { font-size: large; }
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="buildCommandsDiv" class="hide" style="text-align:left;">
|
<div id="buildCommandsDiv" class="hide" style="text-align:left;">
|
||||||
<p id="buildCommandsHeader" style="text-align:center;">Here is complete instruction for TDLib binaries building:</p>
|
<p id="buildCommandsHeader" style="text-align:center;">Here is complete instruction for TDLight binaries building:</p>
|
||||||
<p id="buildPre">Hidden text</p>
|
<p id="buildPre">Hidden text</p>
|
||||||
<code id="buildCommands">Empty commands</code>
|
<code id="buildCommands">Empty commands</code>
|
||||||
</div>
|
</div>
|
||||||
@ -300,14 +300,14 @@ function getTargetName(target) {
|
|||||||
case 'tdjson':
|
case 'tdjson':
|
||||||
case 'WebAssembly':
|
case 'WebAssembly':
|
||||||
case 'iOS':
|
case 'iOS':
|
||||||
return '<a href="https://github.com/tdlib/td#using-json">JSON</a>';
|
return '<a href="https://github.com/tdlight-team/tdlight#using-json">JSON</a>';
|
||||||
case 'tdclient':
|
case 'tdclient':
|
||||||
return '<a href="https://github.com/tdlib/td#using-cxx">a simple and convenient C++11-interface</a>';
|
return '<a href="https://github.com/tdlight-team/tdlight#using-cxx">a simple and convenient C++11-interface</a>';
|
||||||
case 'JNI':
|
case 'JNI':
|
||||||
case 'Android':
|
case 'Android':
|
||||||
return '<a href="https://github.com/tdlib/td#using-java">native ' + target + '</a>';
|
return '<a href="https://github.com/tdlight-team/tdlight#using-java">native ' + target + '</a>';
|
||||||
default:
|
default:
|
||||||
return '<a href="https://github.com/tdlib/td#using-dotnet">native ' + target + '</a>';
|
return '<a href="https://github.com/tdlight-team/tdlight#using-dotnet">native ' + target + '</a>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -321,17 +321,17 @@ function onOsChanged() {
|
|||||||
if (language === 'Other') {
|
if (language === 'Other') {
|
||||||
language = 'any other programming language';
|
language = 'any other programming language';
|
||||||
}
|
}
|
||||||
var text = 'TDLib can be used from ' + language + ' on ' + os + ' through the ' + getTargetName(target) + ' interface.<br>' +
|
var text = 'TDLight can be used from ' + language + ' on ' + os + ' through the ' + getTargetName(target) + ' interface.<br>' +
|
||||||
'See <a href="https://github.com/tdlib/td/blob/master/example/README.md#' + getExampleAnchor(language) + '">examples</a> of such usage and already available third-party frameworks.<br>';
|
'See <a href="https://github.com/tdlight-team/tdlight/blob/master/example/README.md#' + getExampleAnchor(language) + '">examples</a> of such usage and already available third-party frameworks.<br>';
|
||||||
|
|
||||||
if (target === 'WebAssembly') {
|
if (target === 'WebAssembly') {
|
||||||
text = 'TDLib is available in a prebuilt form as an <a href="https://www.npmjs.com/">NPM</a> package <a href="https://www.npmjs.com/package/tdweb">tdweb</a>.<br>' +
|
text = 'TDLight is available in a prebuilt form as an <a href="https://www.npmjs.com/">NPM</a> package <a href="https://www.npmjs.com/package/tdweb">tdweb</a>.<br>' +
|
||||||
'If you want to build it manually, take a look at our <a href="https://github.com/tdlib/td/tree/master/example/web">example</a>.';
|
'If you want to build it manually, take a look at our <a href="https://github.com/tdlight-team/tdlight/tree/master/example/web">example</a>.';
|
||||||
target = '';
|
target = '';
|
||||||
}
|
}
|
||||||
if (target === 'Android') {
|
if (target === 'Android') {
|
||||||
text = 'TDLib for Android is available in a prebuilt form and can be downloaded from <a href="https://core.telegram.org/tdlib/tdlib.zip">there</a>.<br>' +
|
text = 'TDLight for Android is available in a prebuilt form and can be downloaded from <a href="https://core.telegram.org/tdlight-team/tdlightlib.zip">there</a>.<br>' +
|
||||||
'See <a href="https://github.com/tdlib/td/issues/77#issuecomment-640719893">build instructions</a> if you want to build the latest TDLib version or want to build TDLib with different interface.';
|
'See <a href="https://github.com/tdlight-team/tdlight/issues/77#issuecomment-640719893">build instructions</a> if you want to build the latest TDLight version or want to build TDLight with different interface.';
|
||||||
target = '';
|
target = '';
|
||||||
}
|
}
|
||||||
if (target === 'iOS') {
|
if (target === 'iOS') {
|
||||||
@ -396,7 +396,7 @@ function onOptionsChanged() {
|
|||||||
if (os_linux || os_freebsd || os_netbsd) {
|
if (os_linux || os_freebsd || os_netbsd) {
|
||||||
low_memory = document.getElementById('buildLowMemoryCheckbox').checked;
|
low_memory = document.getElementById('buildLowMemoryCheckbox').checked;
|
||||||
document.getElementById('buildLowMemoryText').innerHTML = 'I have less than ' + (use_clang ? '1.5' : '3.5') +' GB of RAM.' +
|
document.getElementById('buildLowMemoryText').innerHTML = 'I have less than ' + (use_clang ? '1.5' : '3.5') +' GB of RAM.' +
|
||||||
(low_memory ? ' Now you will need only ' + (use_clang ? '0.5' : '1') +' GB of RAM to build TDLib.' : '');
|
(low_memory ? ' Now you will need only ' + (use_clang ? '0.5' : '1') +' GB of RAM to build TDLight.' : '');
|
||||||
document.getElementById('buildLowMemoryDiv').style.display = 'block';
|
document.getElementById('buildLowMemoryDiv').style.display = 'block';
|
||||||
} else {
|
} else {
|
||||||
if (os_openbsd) {
|
if (os_openbsd) {
|
||||||
@ -530,7 +530,7 @@ function onOptionsChanged() {
|
|||||||
pre_text.push('Install Git, ' + compiler + ', make, CMake >= 3.0.2, OpenSSL-dev, zlib-dev, gperf, PHP' + jdk + ' using your package manager.');
|
pre_text.push('Install Git, ' + compiler + ', make, CMake >= 3.0.2, OpenSSL-dev, zlib-dev, gperf, PHP' + jdk + ' using your package manager.');
|
||||||
}
|
}
|
||||||
if (os_linux && os.includes('Node.js')) {
|
if (os_linux && os.includes('Node.js')) {
|
||||||
pre_text.push('Note that for Node.js ≤ 9.11.2 you must build TDLib with OpenSSL 1.0.* and for Node.js ≥ 10 with OpenSSL 1.1.* instead, so you may need to modify the following commands to install a proper OpenSSL version.');
|
pre_text.push('Note that for Node.js ≤ 9.11.2 you must build TDLight with OpenSSL 1.0.* and for Node.js ≥ 10 with OpenSSL 1.1.* instead, so you may need to modify the following commands to install a proper OpenSSL version.');
|
||||||
}
|
}
|
||||||
if (os_freebsd) {
|
if (os_freebsd) {
|
||||||
pre_text.push('Note that the following instruction is for FreeBSD 11.');
|
pre_text.push('Note that the following instruction is for FreeBSD 11.');
|
||||||
@ -565,7 +565,7 @@ function onOptionsChanged() {
|
|||||||
if (os_windows) {
|
if (os_windows) {
|
||||||
pre_text.push('Close and re-open ' + terminal_name + ' if the PATH environment variable was changed.');
|
pre_text.push('Close and re-open ' + terminal_name + ' if the PATH environment variable was changed.');
|
||||||
}
|
}
|
||||||
pre_text.push('Run these commands in ' + terminal_name + ' to build TDLib and to install it to ' + install_dir + ':');
|
pre_text.push('Run these commands in ' + terminal_name + ' to build TDLight and to install it to ' + install_dir + ':');
|
||||||
document.getElementById('buildPre').innerHTML = '<ul><li>' + pre_text.join('</li><li>') + '</li></ul>';
|
document.getElementById('buildPre').innerHTML = '<ul><li>' + pre_text.join('</li><li>') + '</li></ul>';
|
||||||
document.getElementById('buildPre').style.display = 'block';
|
document.getElementById('buildPre').style.display = 'block';
|
||||||
|
|
||||||
@ -712,7 +712,7 @@ function onOptionsChanged() {
|
|||||||
commands.push('exit');
|
commands.push('exit');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
commands.push('git clone https://github.com/tdlib/td.git');
|
commands.push('git clone https://github.com/tdlight-team/tdlight.git');
|
||||||
|
|
||||||
commands.push('cd td');
|
commands.push('cd td');
|
||||||
// commands.push('git checkout v1.7.0');
|
// commands.push('git checkout v1.7.0');
|
||||||
|
@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
|
|||||||
|
|
||||||
project(TdExample VERSION 1.0 LANGUAGES CXX)
|
project(TdExample VERSION 1.0 LANGUAGES CXX)
|
||||||
|
|
||||||
find_package(Td 1.7.2 REQUIRED)
|
find_package(Td 1.7.4 REQUIRED)
|
||||||
|
|
||||||
add_executable(tdjson_example tdjson_example.cpp)
|
add_executable(tdjson_example tdjson_example.cpp)
|
||||||
target_link_libraries(tdjson_example PRIVATE Td::TdJson)
|
target_link_libraries(tdjson_example PRIVATE Td::TdJson)
|
||||||
|
@ -66,8 +66,8 @@ class TdExample {
|
|||||||
} else if (!are_authorized_) {
|
} else if (!are_authorized_) {
|
||||||
process_response(client_manager_->receive(10));
|
process_response(client_manager_->receive(10));
|
||||||
} else {
|
} else {
|
||||||
std::cout << "Enter action [q] quit [u] check for updates and request results [c] show chats [m <id> <text>] "
|
std::cout << "Enter action [q] quit [u] check for updates and request results [c] show chats [m <chat_id> "
|
||||||
"send message [me] show self [l] logout: "
|
"<text>] send message [me] show self [l] logout: "
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
std::string line;
|
std::string line;
|
||||||
std::getline(std::cin, line);
|
std::getline(std::cin, line);
|
||||||
@ -123,7 +123,7 @@ class TdExample {
|
|||||||
}
|
}
|
||||||
auto chats = td::move_tl_object_as<td_api::chats>(object);
|
auto chats = td::move_tl_object_as<td_api::chats>(object);
|
||||||
for (auto chat_id : chats->chat_ids_) {
|
for (auto chat_id : chats->chat_ids_) {
|
||||||
std::cout << "[id:" << chat_id << "] [title:" << chat_title_[chat_id] << "]" << std::endl;
|
std::cout << "[chat_id:" << chat_id << "] [title:" << chat_title_[chat_id] << "]" << std::endl;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -172,6 +172,7 @@ class TdExample {
|
|||||||
auto it = handlers_.find(response.request_id);
|
auto it = handlers_.find(response.request_id);
|
||||||
if (it != handlers_.end()) {
|
if (it != handlers_.end()) {
|
||||||
it->second(std::move(response.object));
|
it->second(std::move(response.object));
|
||||||
|
handlers_.erase(it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
16
example/ios/Python-Apple-support.patch
Normal file
16
example/ios/Python-Apple-support.patch
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
diff --git a/Makefile b/Makefile
|
||||||
|
index 695be54..bce31b9 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -56,9 +56,10 @@ CFLAGS-appletvos.arm64=-fembed-bitcode
|
||||||
|
PYTHON_CONFIGURE-tvOS=ac_cv_func_sigaltstack=no
|
||||||
|
|
||||||
|
# watchOS targets
|
||||||
|
-TARGETS-watchOS=watchsimulator.i386 watchos.armv7k
|
||||||
|
+TARGETS-watchOS=watchsimulator.i386 watchsimulator.x86_64 watchos.armv7k watchos.arm64_32
|
||||||
|
CFLAGS-watchOS=-mwatchos-version-min=4.0
|
||||||
|
CFLAGS-watchos.armv7k=-fembed-bitcode
|
||||||
|
+CFLAGS-watchos.arm64_32=-fembed-bitcode
|
||||||
|
PYTHON_CONFIGURE-watchOS=ac_cv_func_sigaltstack=no
|
||||||
|
|
||||||
|
# override machine types for arm64
|
@ -3,10 +3,12 @@
|
|||||||
git clone https://github.com/pybee/Python-Apple-support
|
git clone https://github.com/pybee/Python-Apple-support
|
||||||
cd Python-Apple-support
|
cd Python-Apple-support
|
||||||
git checkout 60b990128d5f1f04c336ff66594574515ab56604
|
git checkout 60b990128d5f1f04c336ff66594574515ab56604
|
||||||
|
git apply ../Python-Apple-support.patch
|
||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
#TODO: change openssl version
|
#TODO: change openssl version
|
||||||
platforms="macOS iOS watchOS tvOS"
|
platforms="macOS iOS watchOS tvOS"
|
||||||
|
#platforms="watchOS"
|
||||||
for platform in $platforms;
|
for platform in $platforms;
|
||||||
do
|
do
|
||||||
echo $platform
|
echo $platform
|
||||||
|
@ -6,6 +6,7 @@ mkdir -p build
|
|||||||
cd build
|
cd build
|
||||||
|
|
||||||
platforms="macOS iOS watchOS tvOS"
|
platforms="macOS iOS watchOS tvOS"
|
||||||
|
#platforms="watchOS"
|
||||||
for platform in $platforms;
|
for platform in $platforms;
|
||||||
do
|
do
|
||||||
echo "Platform = ${platform} Simulator = ${simulator}"
|
echo "Platform = ${platform} Simulator = ${simulator}"
|
||||||
@ -45,8 +46,10 @@ do
|
|||||||
else
|
else
|
||||||
ios_platform="OS"
|
ios_platform="OS"
|
||||||
fi
|
fi
|
||||||
|
watchos=""
|
||||||
if [[ $platform = "watchOS" ]]; then
|
if [[ $platform = "watchOS" ]]; then
|
||||||
ios_platform="WATCH${ios_platform}"
|
ios_platform="WATCH${ios_platform}"
|
||||||
|
watchos="-DTD_EXPERIMENTAL_WATCH_OS=ON"
|
||||||
fi
|
fi
|
||||||
if [[ $platform = "tvOS" ]]; then
|
if [[ $platform = "tvOS" ]]; then
|
||||||
ios_platform="TV${ios_platform}"
|
ios_platform="TV${ios_platform}"
|
||||||
@ -56,7 +59,7 @@ do
|
|||||||
mkdir -p $build
|
mkdir -p $build
|
||||||
mkdir -p $install
|
mkdir -p $install
|
||||||
cd $build
|
cd $build
|
||||||
cmake $td_path $options -DIOS_PLATFORM=${ios_platform} -DCMAKE_TOOLCHAIN_FILE=${td_path}/CMake/iOS.cmake -DCMAKE_INSTALL_PREFIX=../${install}
|
cmake $td_path $options $watchos -DIOS_PLATFORM=${ios_platform} -DCMAKE_TOOLCHAIN_FILE=${td_path}/CMake/iOS.cmake -DCMAKE_INSTALL_PREFIX=../${install}
|
||||||
make -j3 install || exit
|
make -j3 install || exit
|
||||||
cd ..
|
cd ..
|
||||||
done
|
done
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011">
|
<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011">
|
||||||
<Metadata>
|
<Metadata>
|
||||||
<Identity Id="Telegram.Td.UWP" Version="1.7.2" Language="en-US" Publisher="Telegram LLC" />
|
<Identity Id="Telegram.Td.UWP" Version="1.7.4" Language="en-US" Publisher="Telegram LLC" />
|
||||||
<DisplayName>TDLib for Universal Windows Platform</DisplayName>
|
<DisplayName>TDLib for Universal Windows Platform</DisplayName>
|
||||||
<Description>TDLib is a library for building Telegram clients</Description>
|
<Description>TDLib is a library for building Telegram clients</Description>
|
||||||
<MoreInfo>https://core.telegram.org/tdlib</MoreInfo>
|
<MoreInfo>https://core.telegram.org/tdlib</MoreInfo>
|
||||||
|
@ -107,6 +107,15 @@ if (NOT CMAKE_CROSSCOMPILING)
|
|||||||
add_subdirectory(tl-parser)
|
add_subdirectory(tl-parser)
|
||||||
|
|
||||||
set(TLO_AUTO_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/auto/tlo)
|
set(TLO_AUTO_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/auto/tlo)
|
||||||
|
set(TLO_FILES ${TLO_AUTO_INCLUDE_DIR}/mtproto_api.tlo ${TLO_AUTO_INCLUDE_DIR}/secret_api.tlo ${TLO_AUTO_INCLUDE_DIR}/td_api.tlo ${TLO_AUTO_INCLUDE_DIR}/telegram_api.tlo)
|
||||||
|
set(TD_API_TLO_FILE ${TLO_AUTO_INCLUDE_DIR}/td_api.tlo)
|
||||||
|
|
||||||
|
# Ninja generator uses relative paths and can't correctly handle these dependencies
|
||||||
|
# See https://gitlab.kitware.com/cmake/cmake/-/issues/13894
|
||||||
|
if (CMAKE_GENERATOR STREQUAL "Ninja")
|
||||||
|
set(TLO_FILES)
|
||||||
|
set(TD_API_TLO_FILE)
|
||||||
|
endif()
|
||||||
|
|
||||||
add_custom_target(tl_generate_tlo
|
add_custom_target(tl_generate_tlo
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
@ -124,7 +133,7 @@ if (NOT CMAKE_CROSSCOMPILING)
|
|||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
COMMAND ${GENERATE_COMMON_CMD}
|
COMMAND ${GENERATE_COMMON_CMD}
|
||||||
COMMENT "Generate common TL source files"
|
COMMENT "Generate common TL source files"
|
||||||
DEPENDS generate_common tl_generate_tlo ${TLO_AUTO_INCLUDE_DIR}/mtproto_api.tlo ${TLO_AUTO_INCLUDE_DIR}/secret_api.tlo ${TLO_AUTO_INCLUDE_DIR}/td_api.tlo ${TLO_AUTO_INCLUDE_DIR}/telegram_api.tlo ${CMAKE_CURRENT_SOURCE_DIR}/scheme/td_api.tl ${CMAKE_CURRENT_SOURCE_DIR}/DoxygenTlDocumentationGenerator.php
|
DEPENDS generate_common tl_generate_tlo ${TLO_FILES} ${CMAKE_CURRENT_SOURCE_DIR}/scheme/td_api.tl ${CMAKE_CURRENT_SOURCE_DIR}/DoxygenTlDocumentationGenerator.php
|
||||||
)
|
)
|
||||||
if (TD_ENABLE_JNI)
|
if (TD_ENABLE_JNI)
|
||||||
target_compile_definitions(generate_common PRIVATE TD_ENABLE_JNI=1)
|
target_compile_definitions(generate_common PRIVATE TD_ENABLE_JNI=1)
|
||||||
@ -139,7 +148,7 @@ if (NOT CMAKE_CROSSCOMPILING)
|
|||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
COMMAND generate_c
|
COMMAND generate_c
|
||||||
COMMENT "Generate C TL source files"
|
COMMENT "Generate C TL source files"
|
||||||
DEPENDS generate_c tl_generate_tlo ${TLO_AUTO_INCLUDE_DIR}/td_api.tlo ${CMAKE_CURRENT_SOURCE_DIR}/scheme/td_api.tl
|
DEPENDS generate_c tl_generate_tlo ${TD_API_TLO_FILE} ${CMAKE_CURRENT_SOURCE_DIR}/scheme/td_api.tl
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(td_generate_java_api ${TL_GENERATE_JAVA_SOURCE})
|
add_executable(td_generate_java_api ${TL_GENERATE_JAVA_SOURCE})
|
||||||
@ -151,7 +160,7 @@ if (NOT CMAKE_CROSSCOMPILING)
|
|||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
COMMAND generate_json
|
COMMAND generate_json
|
||||||
COMMENT "Generate JSON TL source files"
|
COMMENT "Generate JSON TL source files"
|
||||||
DEPENDS generate_json tl_generate_tlo ${TLO_AUTO_INCLUDE_DIR}/td_api.tlo ${CMAKE_CURRENT_SOURCE_DIR}/scheme/td_api.tl
|
DEPENDS generate_json tl_generate_tlo ${TD_API_TLO_FILE} ${CMAKE_CURRENT_SOURCE_DIR}/scheme/td_api.tl
|
||||||
)
|
)
|
||||||
|
|
||||||
if (TD_ENABLE_JNI)
|
if (TD_ENABLE_JNI)
|
||||||
@ -162,9 +171,9 @@ if (NOT CMAKE_CROSSCOMPILING)
|
|||||||
|
|
||||||
if (TD_ENABLE_DOTNET)
|
if (TD_ENABLE_DOTNET)
|
||||||
if (PHP_EXECUTABLE)
|
if (PHP_EXECUTABLE)
|
||||||
set(GENERATE_DOTNET_API_CMD td_generate_dotnet_api ${TLO_AUTO_INCLUDE_DIR}/td_api.tlo && ${PHP_EXECUTABLE} DotnetTlDocumentationGenerator.php scheme/td_api.tl auto/td/telegram/TdDotNetApi.h)
|
set(GENERATE_DOTNET_API_CMD td_generate_dotnet_api ${TD_API_TLO_FILE} && ${PHP_EXECUTABLE} DotnetTlDocumentationGenerator.php scheme/td_api.tl auto/td/telegram/TdDotNetApi.h)
|
||||||
else()
|
else()
|
||||||
set(GENERATE_DOTNET_API_CMD td_generate_dotnet_api ${TLO_AUTO_INCLUDE_DIR}/td_api.tlo)
|
set(GENERATE_DOTNET_API_CMD td_generate_dotnet_api ${TD_API_TLO_FILE})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_executable(td_generate_dotnet_api generate_dotnet.cpp tl_writer_dotnet.h)
|
add_executable(td_generate_dotnet_api generate_dotnet.cpp tl_writer_dotnet.h)
|
||||||
@ -173,7 +182,7 @@ if (NOT CMAKE_CROSSCOMPILING)
|
|||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
COMMAND ${GENERATE_DOTNET_API_CMD}
|
COMMAND ${GENERATE_DOTNET_API_CMD}
|
||||||
COMMENT "Generate .NET API files"
|
COMMENT "Generate .NET API files"
|
||||||
DEPENDS td_generate_dotnet_api tl_generate_tlo ${TLO_AUTO_INCLUDE_DIR}/td_api.tlo ${CMAKE_CURRENT_SOURCE_DIR}/scheme/td_api.tl ${CMAKE_CURRENT_SOURCE_DIR}/DotnetTlDocumentationGenerator.php
|
DEPENDS td_generate_dotnet_api tl_generate_tlo ${TD_API_TLO_FILE} ${CMAKE_CURRENT_SOURCE_DIR}/scheme/td_api.tl ${CMAKE_CURRENT_SOURCE_DIR}/DotnetTlDocumentationGenerator.php
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -318,14 +318,16 @@ poll id:int64 question:string options:vector<pollOption> total_voter_count:int32
|
|||||||
//@description Describes a user profile photo @id Photo identifier; 0 for an empty photo. Can be used to find a photo in a list of user profile photos
|
//@description Describes a user profile photo @id Photo identifier; 0 for an empty photo. Can be used to find a photo in a list of user profile photos
|
||||||
//@small A small (160x160) user profile photo. The file can be downloaded only before the photo is changed
|
//@small A small (160x160) user profile photo. The file can be downloaded only before the photo is changed
|
||||||
//@big A big (640x640) user profile photo. The file can be downloaded only before the photo is changed
|
//@big A big (640x640) user profile photo. The file can be downloaded only before the photo is changed
|
||||||
|
//@minithumbnail User profile photo minithumbnail; may be null
|
||||||
//@has_animation True, if the photo has animated variant
|
//@has_animation True, if the photo has animated variant
|
||||||
profilePhoto id:int64 small:file big:file has_animation:Bool = ProfilePhoto;
|
profilePhoto id:int64 small:file big:file minithumbnail:minithumbnail has_animation:Bool = ProfilePhoto;
|
||||||
|
|
||||||
//@description Contains basic information about the photo of a chat
|
//@description Contains basic information about the photo of a chat
|
||||||
//@small A small (160x160) chat photo variant in JPEG format. The file can be downloaded only before the photo is changed
|
//@small A small (160x160) chat photo variant in JPEG format. The file can be downloaded only before the photo is changed
|
||||||
//@big A big (640x640) chat photo variant in JPEG format. The file can be downloaded only before the photo is changed
|
//@big A big (640x640) chat photo variant in JPEG format. The file can be downloaded only before the photo is changed
|
||||||
|
//@minithumbnail Chat photo minithumbnail; may be null
|
||||||
//@has_animation True, if the photo has animated variant
|
//@has_animation True, if the photo has animated variant
|
||||||
chatPhotoInfo small:file big:file has_animation:Bool = ChatPhotoInfo;
|
chatPhotoInfo small:file big:file minithumbnail:minithumbnail has_animation:Bool = ChatPhotoInfo;
|
||||||
|
|
||||||
|
|
||||||
//@class UserType @description Represents the type of a user. The following types are possible: regular users, deleted users and bots
|
//@class UserType @description Represents the type of a user. The following types are possible: regular users, deleted users and bots
|
||||||
@ -455,7 +457,7 @@ chatMemberStatusCreator custom_title:string is_anonymous:Bool is_member:Bool = C
|
|||||||
//@description The user is a member of a chat and has some additional privileges. In basic groups, administrators can edit and delete messages sent by others, add new members, ban unprivileged members, and manage voice chats. In supergroups and channels, there are more detailed options for administrator privileges
|
//@description The user is a member of a chat and has some additional privileges. In basic groups, administrators can edit and delete messages sent by others, add new members, ban unprivileged members, and manage voice chats. In supergroups and channels, there are more detailed options for administrator privileges
|
||||||
//@custom_title A custom title of the administrator; 0-16 characters without emojis; applicable to supergroups only
|
//@custom_title A custom title of the administrator; 0-16 characters without emojis; applicable to supergroups only
|
||||||
//@can_be_edited True, if the current user can edit the administrator privileges for the called user
|
//@can_be_edited True, if the current user can edit the administrator privileges for the called user
|
||||||
//@can_manage_chat True, if the administrator can get chat event log, get chat statistics, get message statistics in channels, get channel members, see anonymous administrators in supergoups and ignore slow mode. Implied by any other privilege; applicable to supergroups and channels only
|
//@can_manage_chat True, if the administrator can get chat event log, get chat statistics, get message statistics in channels, get channel members, see anonymous administrators in supergroups and ignore slow mode. Implied by any other privilege; applicable to supergroups and channels only
|
||||||
//@can_change_info True, if the administrator can change the chat title, photo, and other settings
|
//@can_change_info True, if the administrator can change the chat title, photo, and other settings
|
||||||
//@can_post_messages True, if the administrator can create channel posts; applicable to channels only
|
//@can_post_messages True, if the administrator can create channel posts; applicable to channels only
|
||||||
//@can_edit_messages True, if the administrator can edit messages of other users and pin messages; applicable to channels only
|
//@can_edit_messages True, if the administrator can edit messages of other users and pin messages; applicable to channels only
|
||||||
@ -464,7 +466,7 @@ chatMemberStatusCreator custom_title:string is_anonymous:Bool is_member:Bool = C
|
|||||||
//@can_restrict_members True, if the administrator can restrict, ban, or unban chat members
|
//@can_restrict_members True, if the administrator can restrict, ban, or unban chat members
|
||||||
//@can_pin_messages True, if the administrator can pin messages; applicable to basic groups and supergroups only
|
//@can_pin_messages True, if the administrator can pin messages; applicable to basic groups and supergroups only
|
||||||
//@can_promote_members True, if the administrator can add new administrators with a subset of their own privileges or demote administrators that were directly or indirectly promoted by them
|
//@can_promote_members True, if the administrator can add new administrators with a subset of their own privileges or demote administrators that were directly or indirectly promoted by them
|
||||||
//@can_manage_voice_chats True, if the administrator can manage voice chats; applicable to basic groups and supergroups only
|
//@can_manage_voice_chats True, if the administrator can manage voice chats
|
||||||
//@is_anonymous True, if the administrator isn't shown in the chat member list and sends messages anonymously; applicable to supergroups only
|
//@is_anonymous True, if the administrator isn't shown in the chat member list and sends messages anonymously; applicable to supergroups only
|
||||||
chatMemberStatusAdministrator custom_title:string can_be_edited:Bool can_manage_chat:Bool can_change_info:Bool can_post_messages:Bool can_edit_messages:Bool can_delete_messages:Bool can_invite_users:Bool can_restrict_members:Bool can_pin_messages:Bool can_promote_members:Bool can_manage_voice_chats:Bool is_anonymous:Bool = ChatMemberStatus;
|
chatMemberStatusAdministrator custom_title:string can_be_edited:Bool can_manage_chat:Bool can_change_info:Bool can_post_messages:Bool can_edit_messages:Bool can_delete_messages:Bool can_invite_users:Bool can_restrict_members:Bool can_pin_messages:Bool can_promote_members:Bool can_manage_voice_chats:Bool is_anonymous:Bool = ChatMemberStatus;
|
||||||
|
|
||||||
@ -477,20 +479,21 @@ chatMemberStatusMember = ChatMemberStatus;
|
|||||||
//@permissions User permissions in the chat
|
//@permissions User permissions in the chat
|
||||||
chatMemberStatusRestricted is_member:Bool restricted_until_date:int32 permissions:chatPermissions = ChatMemberStatus;
|
chatMemberStatusRestricted is_member:Bool restricted_until_date:int32 permissions:chatPermissions = ChatMemberStatus;
|
||||||
|
|
||||||
//@description The user is not a chat member
|
//@description The user or the chat is not a chat member
|
||||||
chatMemberStatusLeft = ChatMemberStatus;
|
chatMemberStatusLeft = ChatMemberStatus;
|
||||||
|
|
||||||
//@description The user was banned (and hence is not a member of the chat). Implies the user can't return to the chat or view messages
|
//@description The user or the chat was banned (and hence is not a member of the chat). Implies the user can't return to the chat, view messages, or be used as a participant identifier to join a voice chat of the chat
|
||||||
//@banned_until_date Point in time (Unix timestamp) when the user will be unbanned; 0 if never. If the user is banned for more than 366 days or for less than 30 seconds from the current time, the user is considered to be banned forever. Always 0 in basic groups
|
//@banned_until_date Point in time (Unix timestamp) when the user will be unbanned; 0 if never. If the user is banned for more than 366 days or for less than 30 seconds from the current time, the user is considered to be banned forever. Always 0 in basic groups
|
||||||
chatMemberStatusBanned banned_until_date:int32 = ChatMemberStatus;
|
chatMemberStatusBanned banned_until_date:int32 = ChatMemberStatus;
|
||||||
|
|
||||||
|
|
||||||
//@description A user with information about joining/leaving a chat @user_id User identifier of the chat member
|
//@description Information about a user or a chat as a member of another chat
|
||||||
|
//@member_id Identifier of the chat member. Currently, other chats can be only Left or Banned. Only supergroups and channels can have other chats as Left or Banned members and these chats must be supergroups or channels
|
||||||
//@inviter_user_id Identifier of a user that invited/promoted/banned this member in the chat; 0 if unknown
|
//@inviter_user_id Identifier of a user that invited/promoted/banned this member in the chat; 0 if unknown
|
||||||
//@joined_chat_date Point in time (Unix timestamp) when the user joined the chat
|
//@joined_chat_date Point in time (Unix timestamp) when the user joined the chat
|
||||||
//@status Status of the member in the chat
|
//@status Status of the member in the chat
|
||||||
//@bot_info If the user is a bot, information about the bot; may be null. Can be null even for a bot if the bot is not the chat member
|
//@bot_info If the user is a bot, information about the bot; may be null. Can be null even for a bot if the bot is not the chat member
|
||||||
chatMember user_id:int32 inviter_user_id:int32 joined_chat_date:int32 status:ChatMemberStatus bot_info:botInfo = ChatMember;
|
chatMember member_id:MessageSender inviter_user_id:int32 joined_chat_date:int32 status:ChatMemberStatus bot_info:botInfo = ChatMember;
|
||||||
|
|
||||||
//@description Contains a list of chat members @total_count Approximate total count of chat members found @members A list of chat members
|
//@description Contains a list of chat members @total_count Approximate total count of chat members found @members A list of chat members
|
||||||
chatMembers total_count:int32 members:vector<chatMember> = ChatMembers;
|
chatMembers total_count:int32 members:vector<chatMember> = ChatMembers;
|
||||||
@ -551,7 +554,7 @@ supergroupMembersFilterBots = SupergroupMembersFilter;
|
|||||||
//@date Point in time (Unix timestamp) when the link was created
|
//@date Point in time (Unix timestamp) when the link was created
|
||||||
//@edit_date Point in time (Unix timestamp) when the link was last edited; 0 if never or unknown
|
//@edit_date Point in time (Unix timestamp) when the link was last edited; 0 if never or unknown
|
||||||
//@expire_date Point in time (Unix timestamp) when the link will expire; 0 if never
|
//@expire_date Point in time (Unix timestamp) when the link will expire; 0 if never
|
||||||
//@member_limit Maximum number of members, which can join the chat using the link simultaneously; 0 if not limited
|
//@member_limit The maximum number of members, which can join the chat using the link simultaneously; 0 if not limited
|
||||||
//@member_count Number of chat members, which joined the chat using the link
|
//@member_count Number of chat members, which joined the chat using the link
|
||||||
//@is_primary True, if the link is primary. Primary invite link can't have expire date or usage limit. There is exactly one primary invite link for each administrator with can_invite_users right at a given time
|
//@is_primary True, if the link is primary. Primary invite link can't have expire date or usage limit. There is exactly one primary invite link for each administrator with can_invite_users right at a given time
|
||||||
//@is_revoked True, if the link was revoked
|
//@is_revoked True, if the link was revoked
|
||||||
@ -891,6 +894,13 @@ chatSourcePublicServiceAnnouncement type:string text:string = ChatSource;
|
|||||||
chatPosition list:ChatList order:int64 is_pinned:Bool source:ChatSource = ChatPosition;
|
chatPosition list:ChatList order:int64 is_pinned:Bool source:ChatSource = ChatPosition;
|
||||||
|
|
||||||
|
|
||||||
|
//@description Describes a voice chat
|
||||||
|
//@group_call_id Group call identifier of an active voice chat; 0 if none. Full informationa about the voice chat can be received through the method getGroupCall
|
||||||
|
//@has_participants True, if the voice chat has participants
|
||||||
|
//@default_participant_id Default group call participant identifier to join the voice chat; may be null
|
||||||
|
voiceChat group_call_id:int32 has_participants:Bool default_participant_id:MessageSender = VoiceChat;
|
||||||
|
|
||||||
|
|
||||||
//@description A chat. (Can be a private chat, basic group, supergroup, or secret chat)
|
//@description A chat. (Can be a private chat, basic group, supergroup, or secret chat)
|
||||||
//@id Chat unique identifier
|
//@id Chat unique identifier
|
||||||
//@type Type of the chat
|
//@type Type of the chat
|
||||||
@ -913,12 +923,11 @@ chatPosition list:ChatList order:int64 is_pinned:Bool source:ChatSource = ChatPo
|
|||||||
//@notification_settings Notification settings for this chat
|
//@notification_settings Notification settings for this chat
|
||||||
//@message_ttl_setting Current message Time To Live setting (self-destruct timer) for the chat; 0 if not defined. TTL is counted from the time message or its content is viewed in secret chats and from the send date in other chats
|
//@message_ttl_setting Current message Time To Live setting (self-destruct timer) for the chat; 0 if not defined. TTL is counted from the time message or its content is viewed in secret chats and from the send date in other chats
|
||||||
//@action_bar Describes actions which should be possible to do through a chat action bar; may be null
|
//@action_bar Describes actions which should be possible to do through a chat action bar; may be null
|
||||||
//@voice_chat_group_call_id Group call identifier of an active voice chat; 0 if none or unknown. The voice chat can be received through the method getGroupCall
|
//@voice_chat Contains information about voice chat of the chat
|
||||||
//@is_voice_chat_empty True, if an active voice chat is empty
|
|
||||||
//@reply_markup_message_id Identifier of the message from which reply markup needs to be used; 0 if there is no default custom reply markup in the chat
|
//@reply_markup_message_id Identifier of the message from which reply markup needs to be used; 0 if there is no default custom reply markup in the chat
|
||||||
//@draft_message A draft of a message in the chat; may be null
|
//@draft_message A draft of a message in the chat; may be null
|
||||||
//@client_data Contains application-specific data associated with the chat. (For example, the chat scroll position or local chat notification settings can be stored here.) Persistent if the message database is used
|
//@client_data Contains application-specific data associated with the chat. (For example, the chat scroll position or local chat notification settings can be stored here.) Persistent if the message database is used
|
||||||
chat id:int53 type:ChatType title:string photo:chatPhotoInfo permissions:chatPermissions last_message:message positions:vector<chatPosition> is_marked_as_unread:Bool is_blocked:Bool has_scheduled_messages:Bool can_be_deleted_only_for_self:Bool can_be_deleted_for_all_users:Bool can_be_reported:Bool default_disable_notification:Bool unread_count:int32 last_read_inbox_message_id:int53 last_read_outbox_message_id:int53 unread_mention_count:int32 notification_settings:chatNotificationSettings message_ttl_setting:int32 action_bar:ChatActionBar voice_chat_group_call_id:int32 is_voice_chat_empty:Bool reply_markup_message_id:int53 draft_message:draftMessage client_data:string = Chat;
|
chat id:int53 type:ChatType title:string photo:chatPhotoInfo permissions:chatPermissions last_message:message positions:vector<chatPosition> is_marked_as_unread:Bool is_blocked:Bool has_scheduled_messages:Bool can_be_deleted_only_for_self:Bool can_be_deleted_for_all_users:Bool can_be_reported:Bool default_disable_notification:Bool unread_count:int32 last_read_inbox_message_id:int53 last_read_outbox_message_id:int53 unread_mention_count:int32 notification_settings:chatNotificationSettings message_ttl_setting:int32 action_bar:ChatActionBar voice_chat:voiceChat reply_markup_message_id:int53 draft_message:draftMessage client_data:string = Chat;
|
||||||
|
|
||||||
//@description Represents a list of chats @total_count Approximate total count of chats found @chat_ids List of chat identifiers
|
//@description Represents a list of chats @total_count Approximate total count of chats found @chat_ids List of chat identifiers
|
||||||
chats total_count:int32 chat_ids:vector<int53> = Chats;
|
chats total_count:int32 chat_ids:vector<int53> = Chats;
|
||||||
@ -1299,14 +1308,22 @@ bankCardInfo title:string actions:vector<bankCardActionOpenUrl> = BankCardInfo;
|
|||||||
address country_code:string state:string city:string street_line1:string street_line2:string postal_code:string = Address;
|
address country_code:string state:string city:string street_line1:string street_line2:string postal_code:string = Address;
|
||||||
|
|
||||||
|
|
||||||
//@description Portion of the price of a product (e.g., "delivery cost", "tax amount") @label Label for this portion of the product price @amount Currency amount in minimal quantity of the currency
|
//@description Portion of the price of a product (e.g., "delivery cost", "tax amount") @label Label for this portion of the product price @amount Currency amount in the smallest units of the currency
|
||||||
labeledPricePart label:string amount:int53 = LabeledPricePart;
|
labeledPricePart label:string amount:int53 = LabeledPricePart;
|
||||||
|
|
||||||
//@description Product invoice @currency ISO 4217 currency code @price_parts A list of objects used to calculate the total price of the product @is_test True, if the payment is a test payment
|
//@description Product invoice @currency ISO 4217 currency code
|
||||||
//@need_name True, if the user's name is needed for payment @need_phone_number True, if the user's phone number is needed for payment @need_email_address True, if the user's email address is needed for payment
|
//@price_parts A list of objects used to calculate the total price of the product
|
||||||
//@need_shipping_address True, if the user's shipping address is needed for payment @send_phone_number_to_provider True, if the user's phone number will be sent to the provider
|
//@max_tip_amount The maximum allowed amount of tip in the smallest units of the currency
|
||||||
//@send_email_address_to_provider True, if the user's email address will be sent to the provider @is_flexible True, if the total price depends on the shipping method
|
//@suggested_tip_amounts Suggested amounts of tip in the smallest units of the currency
|
||||||
invoice currency:string price_parts:vector<labeledPricePart> is_test:Bool need_name:Bool need_phone_number:Bool need_email_address:Bool need_shipping_address:Bool send_phone_number_to_provider:Bool send_email_address_to_provider:Bool is_flexible:Bool = Invoice;
|
//@is_test True, if the payment is a test payment
|
||||||
|
//@need_name True, if the user's name is needed for payment
|
||||||
|
//@need_phone_number True, if the user's phone number is needed for payment
|
||||||
|
//@need_email_address True, if the user's email address is needed for payment
|
||||||
|
//@need_shipping_address True, if the user's shipping address is needed for payment
|
||||||
|
//@send_phone_number_to_provider True, if the user's phone number will be sent to the provider
|
||||||
|
//@send_email_address_to_provider True, if the user's email address will be sent to the provider
|
||||||
|
//@is_flexible True, if the total price depends on the shipping method
|
||||||
|
invoice currency:string price_parts:vector<labeledPricePart> max_tip_amount:int53 suggested_tip_amounts:vector<int53> is_test:Bool need_name:Bool need_phone_number:Bool need_email_address:Bool need_shipping_address:Bool send_phone_number_to_provider:Bool send_email_address_to_provider:Bool is_flexible:Bool = Invoice;
|
||||||
|
|
||||||
//@description Order information @name Name of the user @phone_number Phone number of the user @email_address Email address of the user @shipping_address Shipping address for this order; may be null
|
//@description Order information @name Name of the user @phone_number Phone number of the user @email_address Email address of the user @shipping_address Shipping address for this order; may be null
|
||||||
orderInfo name:string phone_number:string email_address:string shipping_address:address = OrderInfo;
|
orderInfo name:string phone_number:string email_address:string shipping_address:address = OrderInfo;
|
||||||
@ -1334,9 +1351,23 @@ inputCredentialsGooglePay data:string = InputCredentials;
|
|||||||
//@description Stripe payment provider @publishable_key Stripe API publishable key @need_country True, if the user country must be provided @need_postal_code True, if the user ZIP/postal code must be provided @need_cardholder_name True, if the cardholder name must be provided
|
//@description Stripe payment provider @publishable_key Stripe API publishable key @need_country True, if the user country must be provided @need_postal_code True, if the user ZIP/postal code must be provided @need_cardholder_name True, if the cardholder name must be provided
|
||||||
paymentsProviderStripe publishable_key:string need_country:Bool need_postal_code:Bool need_cardholder_name:Bool = PaymentsProviderStripe;
|
paymentsProviderStripe publishable_key:string need_country:Bool need_postal_code:Bool need_cardholder_name:Bool = PaymentsProviderStripe;
|
||||||
|
|
||||||
//@description Contains information about an invoice payment form @invoice Full information of the invoice @url Payment form URL @payments_provider Contains information about the payment provider, if available, to support it natively without the need for opening the URL; may be null
|
//@description Theme colors for a payment form @background_color A color of the payment form background in the RGB24 format @text_color A color of text in the RGB24 format
|
||||||
//@saved_order_info Saved server-side order information; may be null @saved_credentials Contains information about saved card credentials; may be null @can_save_credentials True, if the user can choose to save credentials @need_password True, if the user will be able to save credentials protected by a password they set up
|
//@hint_color A color of hints in the RGB24 format @link_color A color of links in the RGB24 format @button_color A color of thebuttons in the RGB24 format
|
||||||
paymentForm invoice:invoice url:string payments_provider:paymentsProviderStripe saved_order_info:orderInfo saved_credentials:savedCredentials can_save_credentials:Bool need_password:Bool = PaymentForm;
|
//@button_text_color A color of text on the buttons in the RGB24 format
|
||||||
|
paymentFormTheme background_color:int32 text_color:int32 hint_color:int32 link_color:int32 button_color:int32 button_text_color:int32 = PaymentFormTheme;
|
||||||
|
|
||||||
|
//@description Contains information about an invoice payment form
|
||||||
|
//@id The payment form identifier
|
||||||
|
//@invoice Full information of the invoice
|
||||||
|
//@url Payment form URL
|
||||||
|
//@seller_bot_user_id User identifier of the seller bot
|
||||||
|
//@payments_provider_user_id User identifier of the payment provider bot
|
||||||
|
//@payments_provider Contains information about the payment provider, if available, to support it natively without the need for opening the URL; may be null
|
||||||
|
//@saved_order_info Saved server-side order information; may be null
|
||||||
|
//@saved_credentials Contains information about saved card credentials; may be null
|
||||||
|
//@can_save_credentials True, if the user can choose to save credentials
|
||||||
|
//@need_password True, if the user will be able to save credentials protected by a password they set up
|
||||||
|
paymentForm id:int64 invoice:invoice url:string seller_bot_user_id:int32 payments_provider_user_id:int32 payments_provider:paymentsProviderStripe saved_order_info:orderInfo saved_credentials:savedCredentials can_save_credentials:Bool need_password:Bool = PaymentForm;
|
||||||
|
|
||||||
//@description Contains a temporary identifier of validated order information, which is stored for one hour. Also contains the available shipping options @order_info_id Temporary identifier of the order information @shipping_options Available shipping options
|
//@description Contains a temporary identifier of validated order information, which is stored for one hour. Also contains the available shipping options @order_info_id Temporary identifier of the order information @shipping_options Available shipping options
|
||||||
validatedOrderInfo order_info_id:string shipping_options:vector<shippingOption> = ValidatedOrderInfo;
|
validatedOrderInfo order_info_id:string shipping_options:vector<shippingOption> = ValidatedOrderInfo;
|
||||||
@ -1344,9 +1375,19 @@ validatedOrderInfo order_info_id:string shipping_options:vector<shippingOption>
|
|||||||
//@description Contains the result of a payment request @success True, if the payment request was successful; otherwise the verification_url will be not empty @verification_url URL for additional payment credentials verification
|
//@description Contains the result of a payment request @success True, if the payment request was successful; otherwise the verification_url will be not empty @verification_url URL for additional payment credentials verification
|
||||||
paymentResult success:Bool verification_url:string = PaymentResult;
|
paymentResult success:Bool verification_url:string = PaymentResult;
|
||||||
|
|
||||||
//@description Contains information about a successful payment @date Point in time (Unix timestamp) when the payment was made @payments_provider_user_id User identifier of the payment provider bot @invoice Contains information about the invoice
|
//@description Contains information about a successful payment
|
||||||
//@order_info Contains order information; may be null @shipping_option Chosen shipping option; may be null @credentials_title Title of the saved credentials
|
//@title Product title
|
||||||
paymentReceipt date:int32 payments_provider_user_id:int32 invoice:invoice order_info:orderInfo shipping_option:shippingOption credentials_title:string = PaymentReceipt;
|
//@param_description Product description
|
||||||
|
//@photo Product photo; may be null
|
||||||
|
//@date Point in time (Unix timestamp) when the payment was made
|
||||||
|
//@seller_bot_user_id User identifier of the seller bot
|
||||||
|
//@payments_provider_user_id User identifier of the payment provider bot
|
||||||
|
//@invoice Contains information about the invoice
|
||||||
|
//@order_info Order information; may be null
|
||||||
|
//@shipping_option Chosen shipping option; may be null
|
||||||
|
//@credentials_title Title of the saved credentials chosen by the buyer
|
||||||
|
//@tip_amount The amount of tip chosen by the buyer in the smallest units of the currency
|
||||||
|
paymentReceipt title:string description:string photo:photo date:int32 seller_bot_user_id:int32 payments_provider_user_id:int32 invoice:invoice order_info:orderInfo shipping_option:shippingOption credentials_title:string tip_amount:int53 = PaymentReceipt;
|
||||||
|
|
||||||
|
|
||||||
//@description File with the date it was uploaded @file The file @date Point in time (Unix timestamp) when the file was uploaded
|
//@description File with the date it was uploaded @file The file @date Point in time (Unix timestamp) when the file was uploaded
|
||||||
@ -1660,7 +1701,7 @@ messageGame game:game = MessageContent;
|
|||||||
//@description A message with a poll @poll The poll description
|
//@description A message with a poll @poll The poll description
|
||||||
messagePoll poll:poll = MessageContent;
|
messagePoll poll:poll = MessageContent;
|
||||||
|
|
||||||
//@description A message with an invoice from a bot @title Product title @param_description Product description @photo Product photo; may be null @currency Currency for the product price @total_amount Product total price in the minimal quantity of the currency
|
//@description A message with an invoice from a bot @title Product title @param_description Product description @photo Product photo; may be null @currency Currency for the product price @total_amount Product total price in the smallest units of the currency
|
||||||
//@start_parameter Unique invoice bot start_parameter. To share an invoice use the URL https://t.me/{bot_username}?start={start_parameter} @is_test True, if the invoice is a test invoice
|
//@start_parameter Unique invoice bot start_parameter. To share an invoice use the URL https://t.me/{bot_username}?start={start_parameter} @is_test True, if the invoice is a test invoice
|
||||||
//@need_shipping_address True, if the shipping address should be specified @receipt_message_id The identifier of the message with the receipt, after the product has been purchased
|
//@need_shipping_address True, if the shipping address should be specified @receipt_message_id The identifier of the message with the receipt, after the product has been purchased
|
||||||
messageInvoice title:string description:string photo:photo currency:string total_amount:int53 start_parameter:string is_test:Bool need_shipping_address:Bool receipt_message_id:int53 = MessageContent;
|
messageInvoice title:string description:string photo:photo currency:string total_amount:int53 start_parameter:string is_test:Bool need_shipping_address:Bool receipt_message_id:int53 = MessageContent;
|
||||||
@ -1668,6 +1709,9 @@ messageInvoice title:string description:string photo:photo currency:string total
|
|||||||
//@description A message with information about an ended call @is_video True, if the call was a video call @discard_reason Reason why the call was discarded @duration Call duration, in seconds
|
//@description A message with information about an ended call @is_video True, if the call was a video call @discard_reason Reason why the call was discarded @duration Call duration, in seconds
|
||||||
messageCall is_video:Bool discard_reason:CallDiscardReason duration:int32 = MessageContent;
|
messageCall is_video:Bool discard_reason:CallDiscardReason duration:int32 = MessageContent;
|
||||||
|
|
||||||
|
//@description A new voice chat was scheduled @group_call_id Identifier of the voice chat. The voice chat can be received through the method getGroupCall @start_date Point in time (Unix timestamp) when the group call is supposed to be started by an administrator
|
||||||
|
messageVoiceChatScheduled group_call_id:int32 start_date:int32 = MessageContent;
|
||||||
|
|
||||||
//@description A newly created voice chat @group_call_id Identifier of the voice chat. The voice chat can be received through the method getGroupCall
|
//@description A newly created voice chat @group_call_id Identifier of the voice chat. The voice chat can be received through the method getGroupCall
|
||||||
messageVoiceChatStarted group_call_id:int32 = MessageContent;
|
messageVoiceChatStarted group_call_id:int32 = MessageContent;
|
||||||
|
|
||||||
@ -1722,13 +1766,13 @@ messageCustomServiceAction text:string = MessageContent;
|
|||||||
//@description A new high score was achieved in a game @game_message_id Identifier of the message with the game, can be an identifier of a deleted message @game_id Identifier of the game; may be different from the games presented in the message with the game @score New score
|
//@description A new high score was achieved in a game @game_message_id Identifier of the message with the game, can be an identifier of a deleted message @game_id Identifier of the game; may be different from the games presented in the message with the game @score New score
|
||||||
messageGameScore game_message_id:int53 game_id:int64 score:int32 = MessageContent;
|
messageGameScore game_message_id:int53 game_id:int64 score:int32 = MessageContent;
|
||||||
|
|
||||||
//@description A payment has been completed @invoice_message_id Identifier of the message with the corresponding invoice; can be an identifier of a deleted message @currency Currency for the price of the product @total_amount Total price for the product, in the minimal quantity of the currency
|
//@description A payment has been completed @invoice_chat_id Identifier of the chat, containing the corresponding invoice message; 0 if unknown @invoice_message_id Identifier of the message with the corresponding invoice; can be an identifier of a deleted message @currency Currency for the price of the product @total_amount Total price for the product, in the smallest units of the currency
|
||||||
messagePaymentSuccessful invoice_message_id:int53 currency:string total_amount:int53 = MessageContent;
|
messagePaymentSuccessful invoice_chat_id:int53 invoice_message_id:int53 currency:string total_amount:int53 = MessageContent;
|
||||||
|
|
||||||
//@description A payment has been completed; for bots only @invoice_message_id Identifier of the message with the corresponding invoice; can be an identifier of a deleted message @currency Currency for price of the product
|
//@description A payment has been completed; for bots only @currency Currency for price of the product
|
||||||
//@total_amount Total price for the product, in the minimal quantity of the currency @invoice_payload Invoice payload @shipping_option_id Identifier of the shipping option chosen by the user; may be empty if not applicable @order_info Information about the order; may be null
|
//@total_amount Total price for the product, in the smallest units of the currency @invoice_payload Invoice payload @shipping_option_id Identifier of the shipping option chosen by the user; may be empty if not applicable @order_info Information about the order; may be null
|
||||||
//@telegram_payment_charge_id Telegram payment identifier @provider_payment_charge_id Provider payment identifier
|
//@telegram_payment_charge_id Telegram payment identifier @provider_payment_charge_id Provider payment identifier
|
||||||
messagePaymentSuccessfulBot invoice_message_id:int53 currency:string total_amount:int53 invoice_payload:bytes shipping_option_id:string order_info:orderInfo telegram_payment_charge_id:string provider_payment_charge_id:string = MessageContent;
|
messagePaymentSuccessfulBot currency:string total_amount:int53 invoice_payload:bytes shipping_option_id:string order_info:orderInfo telegram_payment_charge_id:string provider_payment_charge_id:string = MessageContent;
|
||||||
|
|
||||||
//@description A contact has registered with Telegram
|
//@description A contact has registered with Telegram
|
||||||
messageContactRegistered = MessageContent;
|
messageContactRegistered = MessageContent;
|
||||||
@ -1823,7 +1867,7 @@ messageSchedulingStateSendWhenOnline = MessageSchedulingState;
|
|||||||
//@scheduling_state Message scheduling state. Messages sent to a secret chat, live location messages and self-destructing messages can't be scheduled
|
//@scheduling_state Message scheduling state. Messages sent to a secret chat, live location messages and self-destructing messages can't be scheduled
|
||||||
messageSendOptions disable_notification:Bool from_background:Bool scheduling_state:MessageSchedulingState = MessageSendOptions;
|
messageSendOptions disable_notification:Bool from_background:Bool scheduling_state:MessageSchedulingState = MessageSendOptions;
|
||||||
|
|
||||||
//@description Options to be used when a message content is copied without a link to the original message
|
//@description Options to be used when a message content is copied without a link to the original message. Service messages and messageInvoice can't be copied
|
||||||
//@send_copy True, if content of the message needs to be copied without a link to the original message. Always true if the message is forwarded to a secret chat
|
//@send_copy True, if content of the message needs to be copied without a link to the original message. Always true if the message is forwarded to a secret chat
|
||||||
//@replace_caption True, if media caption of the message copy needs to be replaced. Ignored if send_copy is false
|
//@replace_caption True, if media caption of the message copy needs to be replaced. Ignored if send_copy is false
|
||||||
//@new_caption New message caption. Ignored if replace_caption is false
|
//@new_caption New message caption. Ignored if replace_caption is false
|
||||||
@ -1882,8 +1926,10 @@ inputMessageDice emoji:string clear_draft:Bool = InputMessageContent;
|
|||||||
//@description A message with a game; not supported for channels or secret chats @bot_user_id User identifier of the bot that owns the game @game_short_name Short name of the game
|
//@description A message with a game; not supported for channels or secret chats @bot_user_id User identifier of the bot that owns the game @game_short_name Short name of the game
|
||||||
inputMessageGame bot_user_id:int32 game_short_name:string = InputMessageContent;
|
inputMessageGame bot_user_id:int32 game_short_name:string = InputMessageContent;
|
||||||
|
|
||||||
//@description A message with an invoice; can be used only by bots and only in private chats @invoice Invoice @title Product title; 1-32 characters @param_description Product description; 0-255 characters @photo_url Product photo URL; optional @photo_size Product photo size @photo_width Product photo width @photo_height Product photo height
|
//@description A message with an invoice; can be used only by bots @invoice Invoice @title Product title; 1-32 characters @param_description Product description; 0-255 characters
|
||||||
//@payload The invoice payload @provider_token Payment provider token @provider_data JSON-encoded data about the invoice, which will be shared with the payment provider @start_parameter Unique invoice bot start_parameter for the generation of this invoice
|
//@photo_url Product photo URL; optional @photo_size Product photo size @photo_width Product photo width @photo_height Product photo height
|
||||||
|
//@payload The invoice payload @provider_token Payment provider token @provider_data JSON-encoded data about the invoice, which will be shared with the payment provider
|
||||||
|
//@start_parameter Unique invoice bot deep link parameter for the generation of this invoice. If empty, it would be possible to pay directly from forwards of the invoice message
|
||||||
inputMessageInvoice invoice:invoice title:string description:string photo_url:string photo_size:int32 photo_width:int32 photo_height:int32 payload:bytes provider_token:string provider_data:string start_parameter:string = InputMessageContent;
|
inputMessageInvoice invoice:invoice title:string description:string photo_url:string photo_size:int32 photo_width:int32 photo_height:int32 payload:bytes provider_token:string provider_data:string start_parameter:string = InputMessageContent;
|
||||||
|
|
||||||
//@description A message with a poll. Polls can't be sent to secret chats. Polls can be sent only to a private chat with a bot @question Poll question; 1-255 characters (up to 300 characters for bots) @options List of poll answer options, 2-10 strings 1-100 characters each
|
//@description A message with a poll. Polls can't be sent to secret chats. Polls can be sent only to a private chat with a bot @question Poll question; 1-255 characters (up to 300 characters for bots) @options List of poll answer options, 2-10 strings 1-100 characters each
|
||||||
@ -2101,23 +2147,26 @@ callStateDiscarded reason:CallDiscardReason need_rating:Bool need_debug_informat
|
|||||||
callStateError error:error = CallState;
|
callStateError error:error = CallState;
|
||||||
|
|
||||||
|
|
||||||
//@description Describes a recently speaking user in a group call @user_id User identifier @is_speaking True, is the user has spoken recently
|
//@description Describes a recently speaking participant in a group call @participant_id Group call participant identifier @is_speaking True, is the user has spoken recently
|
||||||
groupCallRecentSpeaker user_id:int32 is_speaking:Bool = GroupCallRecentSpeaker;
|
groupCallRecentSpeaker participant_id:MessageSender is_speaking:Bool = GroupCallRecentSpeaker;
|
||||||
|
|
||||||
//@description Describes a group call
|
//@description Describes a group call
|
||||||
//@id Group call identifier
|
//@id Group call identifier
|
||||||
|
//@title Group call title
|
||||||
|
//@scheduled_start_date Point in time (Unix timestamp) when the group call is supposed to be started by an administrator; 0 if it is already active or was ended
|
||||||
|
//@enabled_start_notification True, if the group call is scheduled and the current user will receive a notification when the group call will start
|
||||||
//@is_active True, if the call is active
|
//@is_active True, if the call is active
|
||||||
//@is_joined True, if the call is joined
|
//@is_joined True, if the call is joined
|
||||||
//@need_rejoin True, if user was kicked from the call because of network loss and the call needs to be rejoined
|
//@need_rejoin True, if user was kicked from the call because of network loss and the call needs to be rejoined
|
||||||
//@can_unmute_self True, if the current user can unmute themself
|
|
||||||
//@can_be_managed True, if the current user can manage the group call
|
//@can_be_managed True, if the current user can manage the group call
|
||||||
//@participant_count Number of participants in the group call
|
//@participant_count Number of participants in the group call
|
||||||
//@loaded_all_participants True, if all group call participants are loaded
|
//@loaded_all_participants True, if all group call participants are loaded
|
||||||
//@recent_speakers Recently speaking users in the group call
|
//@recent_speakers Recently speaking users in the group call
|
||||||
//@mute_new_participants True, if only group call administrators can unmute new participants
|
//@mute_new_participants True, if only group call administrators can unmute new participants
|
||||||
//@can_change_mute_new_participants True, if the current user can enable or disable mute_new_participants setting
|
//@can_change_mute_new_participants True, if the current user can enable or disable mute_new_participants setting
|
||||||
|
//@record_duration Duration of the ongoing group call recording, in seconds; 0 if none. An updateGroupCall update is not triggered when value of this field changes, but the same recording goes on
|
||||||
//@duration Call duration; for ended calls only
|
//@duration Call duration; for ended calls only
|
||||||
groupCall id:int32 is_active:Bool is_joined:Bool need_rejoin:Bool can_unmute_self:Bool can_be_managed:Bool participant_count:int32 loaded_all_participants:Bool recent_speakers:vector<groupCallRecentSpeaker> mute_new_participants:Bool can_change_mute_new_participants:Bool duration:int32 = GroupCall;
|
groupCall id:int32 title:string scheduled_start_date:int32 enabled_start_notification:Bool is_active:Bool is_joined:Bool need_rejoin:Bool can_be_managed:Bool participant_count:int32 loaded_all_participants:Bool recent_speakers:vector<groupCallRecentSpeaker> mute_new_participants:Bool can_change_mute_new_participants:Bool record_duration:int32 duration:int32 = GroupCall;
|
||||||
|
|
||||||
//@description Describes a payload fingerprint for interaction with tgcalls @hash Value of the field hash @setup Value of the field setup @fingerprint Value of the field fingerprint
|
//@description Describes a payload fingerprint for interaction with tgcalls @hash Value of the field hash @setup Value of the field setup @fingerprint Value of the field fingerprint
|
||||||
groupCallPayloadFingerprint hash:string setup:string fingerprint:string = GroupCallPayloadFingerprint;
|
groupCallPayloadFingerprint hash:string setup:string fingerprint:string = GroupCallPayloadFingerprint;
|
||||||
@ -2130,13 +2179,23 @@ groupCallPayload ufrag:string pwd:string fingerprints:vector<groupCallPayloadFin
|
|||||||
//@ip Value of the field ip @type Value of the field type @tcp_type Value of the field tcp_type @rel_addr Value of the field rel_addr @rel_port Value of the field rel_port
|
//@ip Value of the field ip @type Value of the field type @tcp_type Value of the field tcp_type @rel_addr Value of the field rel_addr @rel_port Value of the field rel_port
|
||||||
groupCallJoinResponseCandidate port:string protocol:string network:string generation:string id:string component:string foundation:string priority:string ip:string type:string tcp_type:string rel_addr:string rel_port:string = GroupCallJoinResponseCandidate;
|
groupCallJoinResponseCandidate port:string protocol:string network:string generation:string id:string component:string foundation:string priority:string ip:string type:string tcp_type:string rel_addr:string rel_port:string = GroupCallJoinResponseCandidate;
|
||||||
|
|
||||||
//@description Describes a join response for interaction with tgcalls @payload Join response payload to pass to tgcalls @candidates Join response candidates to pass to tgcalls
|
|
||||||
groupCallJoinResponse payload:groupCallPayload candidates:vector<groupCallJoinResponseCandidate> = GroupCallJoinResponse;
|
//@class GroupCallJoinResponse @description Describes a group call join response
|
||||||
|
|
||||||
|
//@description Contains data needed to join the group call with WebRTC @payload Group call payload to pass to tgcalls @candidates Join response candidates to pass to tgcalls
|
||||||
|
groupCallJoinResponseWebrtc payload:groupCallPayload candidates:vector<groupCallJoinResponseCandidate> = GroupCallJoinResponse;
|
||||||
|
|
||||||
|
//@description Describes that group call needs to be joined as a stream
|
||||||
|
groupCallJoinResponseStream = GroupCallJoinResponse;
|
||||||
|
|
||||||
|
|
||||||
//@description Represents a group call participant
|
//@description Represents a group call participant
|
||||||
//@user_id Identifier of the user
|
//@participant_id Identifier of the group call participant
|
||||||
//@source User's synchronization source
|
//@source User's synchronization source
|
||||||
|
//@bio The participant user's bio or the participant chat's description
|
||||||
|
//@is_current_user True, if the participant is the current user
|
||||||
//@is_speaking True, if the participant is speaking as set by setGroupCallParticipantIsSpeaking
|
//@is_speaking True, if the participant is speaking as set by setGroupCallParticipantIsSpeaking
|
||||||
|
//@is_hand_raised True, if the participant hand is raised
|
||||||
//@can_be_muted_for_all_users True, if the current user can mute the participant for all other group call participants
|
//@can_be_muted_for_all_users True, if the current user can mute the participant for all other group call participants
|
||||||
//@can_be_unmuted_for_all_users True, if the current user can allow the participant to unmute themself or unmute the participant (if the participant is the current user)
|
//@can_be_unmuted_for_all_users True, if the current user can allow the participant to unmute themself or unmute the participant (if the participant is the current user)
|
||||||
//@can_be_muted_for_current_user True, if the current user can mute the participant only for self
|
//@can_be_muted_for_current_user True, if the current user can mute the participant only for self
|
||||||
@ -2145,8 +2204,8 @@ groupCallJoinResponse payload:groupCallPayload candidates:vector<groupCallJoinRe
|
|||||||
//@is_muted_for_current_user True, if the participant is muted for the current user
|
//@is_muted_for_current_user True, if the participant is muted for the current user
|
||||||
//@can_unmute_self True, if the participant is muted for all users, but can unmute themself
|
//@can_unmute_self True, if the participant is muted for all users, but can unmute themself
|
||||||
//@volume_level Participant's volume level; 1-20000 in hundreds of percents
|
//@volume_level Participant's volume level; 1-20000 in hundreds of percents
|
||||||
//@order User's order in the group call participant list. The bigger is order, the higher is user in the list. If order is 0, the user must be removed from the participant list
|
//@order User's order in the group call participant list. Orders must be compared lexicographically. The bigger is order, the higher is user in the list. If order is empty, the user must be removed from the participant list
|
||||||
groupCallParticipant user_id:int32 source:int32 is_speaking:Bool can_be_muted_for_all_users:Bool can_be_unmuted_for_all_users:Bool can_be_muted_for_current_user:Bool can_be_unmuted_for_current_user:Bool is_muted_for_all_users:Bool is_muted_for_current_user:Bool can_unmute_self:Bool volume_level:int32 order:int64 = GroupCallParticipant;
|
groupCallParticipant participant_id:MessageSender source:int32 bio:string is_current_user:Bool is_speaking:Bool is_hand_raised:Bool can_be_muted_for_all_users:Bool can_be_unmuted_for_all_users:Bool can_be_muted_for_current_user:Bool can_be_unmuted_for_current_user:Bool is_muted_for_all_users:Bool is_muted_for_current_user:Bool can_unmute_self:Bool volume_level:int32 order:string = GroupCallParticipant;
|
||||||
|
|
||||||
|
|
||||||
//@class CallProblem @description Describes the exact type of a problem with a call
|
//@class CallProblem @description Describes the exact type of a problem with a call
|
||||||
@ -2225,30 +2284,30 @@ httpUrl url:string = HttpUrl;
|
|||||||
//@video_url The URL of the video file (file size must not exceed 1MB) @video_mime_type MIME type of the video file. Must be one of "image/gif" and "video/mp4"
|
//@video_url The URL of the video file (file size must not exceed 1MB) @video_mime_type MIME type of the video file. Must be one of "image/gif" and "video/mp4"
|
||||||
//@video_duration Duration of the video, in seconds @video_width Width of the video @video_height Height of the video
|
//@video_duration Duration of the video, in seconds @video_width Width of the video @video_height Height of the video
|
||||||
//@reply_markup The message reply markup. Must be of type replyMarkupInlineKeyboard or null
|
//@reply_markup The message reply markup. Must be of type replyMarkupInlineKeyboard or null
|
||||||
//@input_message_content The content of the message to be sent. Must be one of the following types: InputMessageText, InputMessageAnimation, InputMessageLocation, InputMessageVenue or InputMessageContact
|
//@input_message_content The content of the message to be sent. Must be one of the following types: inputMessageText, inputMessageAnimation, inputMessageInvoice, inputMessageLocation, inputMessageVenue or inputMessageContact
|
||||||
inputInlineQueryResultAnimation id:string title:string thumbnail_url:string thumbnail_mime_type:string video_url:string video_mime_type:string video_duration:int32 video_width:int32 video_height:int32 reply_markup:ReplyMarkup input_message_content:InputMessageContent = InputInlineQueryResult;
|
inputInlineQueryResultAnimation id:string title:string thumbnail_url:string thumbnail_mime_type:string video_url:string video_mime_type:string video_duration:int32 video_width:int32 video_height:int32 reply_markup:ReplyMarkup input_message_content:InputMessageContent = InputInlineQueryResult;
|
||||||
|
|
||||||
//@description Represents a link to an article or web page @id Unique identifier of the query result @url URL of the result, if it exists @hide_url True, if the URL must be not shown @title Title of the result
|
//@description Represents a link to an article or web page @id Unique identifier of the query result @url URL of the result, if it exists @hide_url True, if the URL must be not shown @title Title of the result
|
||||||
//@param_description A short description of the result @thumbnail_url URL of the result thumbnail, if it exists @thumbnail_width Thumbnail width, if known @thumbnail_height Thumbnail height, if known
|
//@param_description A short description of the result @thumbnail_url URL of the result thumbnail, if it exists @thumbnail_width Thumbnail width, if known @thumbnail_height Thumbnail height, if known
|
||||||
//@reply_markup The message reply markup. Must be of type replyMarkupInlineKeyboard or null
|
//@reply_markup The message reply markup. Must be of type replyMarkupInlineKeyboard or null
|
||||||
//@input_message_content The content of the message to be sent. Must be one of the following types: InputMessageText, InputMessageLocation, InputMessageVenue or InputMessageContact
|
//@input_message_content The content of the message to be sent. Must be one of the following types: inputMessageText, inputMessageInvoice, inputMessageLocation, inputMessageVenue or inputMessageContact
|
||||||
inputInlineQueryResultArticle id:string url:string hide_url:Bool title:string description:string thumbnail_url:string thumbnail_width:int32 thumbnail_height:int32 reply_markup:ReplyMarkup input_message_content:InputMessageContent = InputInlineQueryResult;
|
inputInlineQueryResultArticle id:string url:string hide_url:Bool title:string description:string thumbnail_url:string thumbnail_width:int32 thumbnail_height:int32 reply_markup:ReplyMarkup input_message_content:InputMessageContent = InputInlineQueryResult;
|
||||||
|
|
||||||
//@description Represents a link to an MP3 audio file @id Unique identifier of the query result @title Title of the audio file @performer Performer of the audio file
|
//@description Represents a link to an MP3 audio file @id Unique identifier of the query result @title Title of the audio file @performer Performer of the audio file
|
||||||
//@audio_url The URL of the audio file @audio_duration Audio file duration, in seconds
|
//@audio_url The URL of the audio file @audio_duration Audio file duration, in seconds
|
||||||
//@reply_markup The message reply markup. Must be of type replyMarkupInlineKeyboard or null
|
//@reply_markup The message reply markup. Must be of type replyMarkupInlineKeyboard or null
|
||||||
//@input_message_content The content of the message to be sent. Must be one of the following types: InputMessageText, InputMessageAudio, InputMessageLocation, InputMessageVenue or InputMessageContact
|
//@input_message_content The content of the message to be sent. Must be one of the following types: inputMessageText, inputMessageAudio, inputMessageInvoice, inputMessageLocation, inputMessageVenue or inputMessageContact
|
||||||
inputInlineQueryResultAudio id:string title:string performer:string audio_url:string audio_duration:int32 reply_markup:ReplyMarkup input_message_content:InputMessageContent = InputInlineQueryResult;
|
inputInlineQueryResultAudio id:string title:string performer:string audio_url:string audio_duration:int32 reply_markup:ReplyMarkup input_message_content:InputMessageContent = InputInlineQueryResult;
|
||||||
|
|
||||||
//@description Represents a user contact @id Unique identifier of the query result @contact User contact @thumbnail_url URL of the result thumbnail, if it exists @thumbnail_width Thumbnail width, if known @thumbnail_height Thumbnail height, if known
|
//@description Represents a user contact @id Unique identifier of the query result @contact User contact @thumbnail_url URL of the result thumbnail, if it exists @thumbnail_width Thumbnail width, if known @thumbnail_height Thumbnail height, if known
|
||||||
//@reply_markup The message reply markup. Must be of type replyMarkupInlineKeyboard or null
|
//@reply_markup The message reply markup. Must be of type replyMarkupInlineKeyboard or null
|
||||||
//@input_message_content The content of the message to be sent. Must be one of the following types: InputMessageText, InputMessageLocation, InputMessageVenue or InputMessageContact
|
//@input_message_content The content of the message to be sent. Must be one of the following types: inputMessageText, inputMessageInvoice, inputMessageLocation, inputMessageVenue or inputMessageContact
|
||||||
inputInlineQueryResultContact id:string contact:contact thumbnail_url:string thumbnail_width:int32 thumbnail_height:int32 reply_markup:ReplyMarkup input_message_content:InputMessageContent = InputInlineQueryResult;
|
inputInlineQueryResultContact id:string contact:contact thumbnail_url:string thumbnail_width:int32 thumbnail_height:int32 reply_markup:ReplyMarkup input_message_content:InputMessageContent = InputInlineQueryResult;
|
||||||
|
|
||||||
//@description Represents a link to a file @id Unique identifier of the query result @title Title of the resulting file @param_description Short description of the result, if known @document_url URL of the file @mime_type MIME type of the file content; only "application/pdf" and "application/zip" are currently allowed
|
//@description Represents a link to a file @id Unique identifier of the query result @title Title of the resulting file @param_description Short description of the result, if known @document_url URL of the file @mime_type MIME type of the file content; only "application/pdf" and "application/zip" are currently allowed
|
||||||
//@thumbnail_url The URL of the file thumbnail, if it exists @thumbnail_width Width of the thumbnail @thumbnail_height Height of the thumbnail
|
//@thumbnail_url The URL of the file thumbnail, if it exists @thumbnail_width Width of the thumbnail @thumbnail_height Height of the thumbnail
|
||||||
//@reply_markup The message reply markup. Must be of type replyMarkupInlineKeyboard or null
|
//@reply_markup The message reply markup. Must be of type replyMarkupInlineKeyboard or null
|
||||||
//@input_message_content The content of the message to be sent. Must be one of the following types: InputMessageText, InputMessageDocument, InputMessageLocation, InputMessageVenue or InputMessageContact
|
//@input_message_content The content of the message to be sent. Must be one of the following types: inputMessageText, inputMessageDocument, inputMessageInvoice, inputMessageLocation, inputMessageVenue or inputMessageContact
|
||||||
inputInlineQueryResultDocument id:string title:string description:string document_url:string mime_type:string thumbnail_url:string thumbnail_width:int32 thumbnail_height:int32 reply_markup:ReplyMarkup input_message_content:InputMessageContent = InputInlineQueryResult;
|
inputInlineQueryResultDocument id:string title:string description:string document_url:string mime_type:string thumbnail_url:string thumbnail_width:int32 thumbnail_height:int32 reply_markup:ReplyMarkup input_message_content:InputMessageContent = InputInlineQueryResult;
|
||||||
|
|
||||||
//@description Represents a game @id Unique identifier of the query result @game_short_name Short name of the game @reply_markup Message reply markup. Must be of type replyMarkupInlineKeyboard or null
|
//@description Represents a game @id Unique identifier of the query result @game_short_name Short name of the game @reply_markup Message reply markup. Must be of type replyMarkupInlineKeyboard or null
|
||||||
@ -2258,37 +2317,37 @@ inputInlineQueryResultGame id:string game_short_name:string reply_markup:ReplyMa
|
|||||||
//@live_period Amount of time relative to the message sent time until the location can be updated, in seconds
|
//@live_period Amount of time relative to the message sent time until the location can be updated, in seconds
|
||||||
//@title Title of the result @thumbnail_url URL of the result thumbnail, if it exists @thumbnail_width Thumbnail width, if known @thumbnail_height Thumbnail height, if known
|
//@title Title of the result @thumbnail_url URL of the result thumbnail, if it exists @thumbnail_width Thumbnail width, if known @thumbnail_height Thumbnail height, if known
|
||||||
//@reply_markup The message reply markup. Must be of type replyMarkupInlineKeyboard or null
|
//@reply_markup The message reply markup. Must be of type replyMarkupInlineKeyboard or null
|
||||||
//@input_message_content The content of the message to be sent. Must be one of the following types: InputMessageText, InputMessageLocation, InputMessageVenue or InputMessageContact
|
//@input_message_content The content of the message to be sent. Must be one of the following types: inputMessageText, inputMessageInvoice, inputMessageLocation, inputMessageVenue or inputMessageContact
|
||||||
inputInlineQueryResultLocation id:string location:location live_period:int32 title:string thumbnail_url:string thumbnail_width:int32 thumbnail_height:int32 reply_markup:ReplyMarkup input_message_content:InputMessageContent = InputInlineQueryResult;
|
inputInlineQueryResultLocation id:string location:location live_period:int32 title:string thumbnail_url:string thumbnail_width:int32 thumbnail_height:int32 reply_markup:ReplyMarkup input_message_content:InputMessageContent = InputInlineQueryResult;
|
||||||
|
|
||||||
//@description Represents link to a JPEG image @id Unique identifier of the query result @title Title of the result, if known @param_description A short description of the result, if known @thumbnail_url URL of the photo thumbnail, if it exists
|
//@description Represents link to a JPEG image @id Unique identifier of the query result @title Title of the result, if known @param_description A short description of the result, if known @thumbnail_url URL of the photo thumbnail, if it exists
|
||||||
//@photo_url The URL of the JPEG photo (photo size must not exceed 5MB) @photo_width Width of the photo @photo_height Height of the photo
|
//@photo_url The URL of the JPEG photo (photo size must not exceed 5MB) @photo_width Width of the photo @photo_height Height of the photo
|
||||||
//@reply_markup The message reply markup. Must be of type replyMarkupInlineKeyboard or null
|
//@reply_markup The message reply markup. Must be of type replyMarkupInlineKeyboard or null
|
||||||
//@input_message_content The content of the message to be sent. Must be one of the following types: InputMessageText, InputMessagePhoto, InputMessageLocation, InputMessageVenue or InputMessageContact
|
//@input_message_content The content of the message to be sent. Must be one of the following types: inputMessageText, inputMessagePhoto, inputMessageInvoice, inputMessageLocation, inputMessageVenue or inputMessageContact
|
||||||
inputInlineQueryResultPhoto id:string title:string description:string thumbnail_url:string photo_url:string photo_width:int32 photo_height:int32 reply_markup:ReplyMarkup input_message_content:InputMessageContent = InputInlineQueryResult;
|
inputInlineQueryResultPhoto id:string title:string description:string thumbnail_url:string photo_url:string photo_width:int32 photo_height:int32 reply_markup:ReplyMarkup input_message_content:InputMessageContent = InputInlineQueryResult;
|
||||||
|
|
||||||
//@description Represents a link to a WEBP or TGS sticker @id Unique identifier of the query result @thumbnail_url URL of the sticker thumbnail, if it exists
|
//@description Represents a link to a WEBP or TGS sticker @id Unique identifier of the query result @thumbnail_url URL of the sticker thumbnail, if it exists
|
||||||
//@sticker_url The URL of the WEBP or TGS sticker (sticker file size must not exceed 5MB) @sticker_width Width of the sticker @sticker_height Height of the sticker
|
//@sticker_url The URL of the WEBP or TGS sticker (sticker file size must not exceed 5MB) @sticker_width Width of the sticker @sticker_height Height of the sticker
|
||||||
//@reply_markup The message reply markup. Must be of type replyMarkupInlineKeyboard or null
|
//@reply_markup The message reply markup. Must be of type replyMarkupInlineKeyboard or null
|
||||||
//@input_message_content The content of the message to be sent. Must be one of the following types: InputMessageText, inputMessageSticker, InputMessageLocation, InputMessageVenue or InputMessageContact
|
//@input_message_content The content of the message to be sent. Must be one of the following types: inputMessageText, inputMessageSticker, inputMessageInvoice, inputMessageLocation, inputMessageVenue or inputMessageContact
|
||||||
inputInlineQueryResultSticker id:string thumbnail_url:string sticker_url:string sticker_width:int32 sticker_height:int32 reply_markup:ReplyMarkup input_message_content:InputMessageContent = InputInlineQueryResult;
|
inputInlineQueryResultSticker id:string thumbnail_url:string sticker_url:string sticker_width:int32 sticker_height:int32 reply_markup:ReplyMarkup input_message_content:InputMessageContent = InputInlineQueryResult;
|
||||||
|
|
||||||
//@description Represents information about a venue @id Unique identifier of the query result @venue Venue result @thumbnail_url URL of the result thumbnail, if it exists @thumbnail_width Thumbnail width, if known @thumbnail_height Thumbnail height, if known
|
//@description Represents information about a venue @id Unique identifier of the query result @venue Venue result @thumbnail_url URL of the result thumbnail, if it exists @thumbnail_width Thumbnail width, if known @thumbnail_height Thumbnail height, if known
|
||||||
//@reply_markup The message reply markup. Must be of type replyMarkupInlineKeyboard or null
|
//@reply_markup The message reply markup. Must be of type replyMarkupInlineKeyboard or null
|
||||||
//@input_message_content The content of the message to be sent. Must be one of the following types: InputMessageText, InputMessageLocation, InputMessageVenue or InputMessageContact
|
//@input_message_content The content of the message to be sent. Must be one of the following types: inputMessageText, inputMessageInvoice, inputMessageLocation, inputMessageVenue or inputMessageContact
|
||||||
inputInlineQueryResultVenue id:string venue:venue thumbnail_url:string thumbnail_width:int32 thumbnail_height:int32 reply_markup:ReplyMarkup input_message_content:InputMessageContent = InputInlineQueryResult;
|
inputInlineQueryResultVenue id:string venue:venue thumbnail_url:string thumbnail_width:int32 thumbnail_height:int32 reply_markup:ReplyMarkup input_message_content:InputMessageContent = InputInlineQueryResult;
|
||||||
|
|
||||||
//@description Represents a link to a page containing an embedded video player or a video file @id Unique identifier of the query result @title Title of the result @param_description A short description of the result, if known
|
//@description Represents a link to a page containing an embedded video player or a video file @id Unique identifier of the query result @title Title of the result @param_description A short description of the result, if known
|
||||||
//@thumbnail_url The URL of the video thumbnail (JPEG), if it exists @video_url URL of the embedded video player or video file @mime_type MIME type of the content of the video URL, only "text/html" or "video/mp4" are currently supported
|
//@thumbnail_url The URL of the video thumbnail (JPEG), if it exists @video_url URL of the embedded video player or video file @mime_type MIME type of the content of the video URL, only "text/html" or "video/mp4" are currently supported
|
||||||
//@video_width Width of the video @video_height Height of the video @video_duration Video duration, in seconds
|
//@video_width Width of the video @video_height Height of the video @video_duration Video duration, in seconds
|
||||||
//@reply_markup The message reply markup. Must be of type replyMarkupInlineKeyboard or null
|
//@reply_markup The message reply markup. Must be of type replyMarkupInlineKeyboard or null
|
||||||
//@input_message_content The content of the message to be sent. Must be one of the following types: InputMessageText, InputMessageVideo, InputMessageLocation, InputMessageVenue or InputMessageContact
|
//@input_message_content The content of the message to be sent. Must be one of the following types: inputMessageText, inputMessageVideo, inputMessageInvoice, inputMessageLocation, inputMessageVenue or inputMessageContact
|
||||||
inputInlineQueryResultVideo id:string title:string description:string thumbnail_url:string video_url:string mime_type:string video_width:int32 video_height:int32 video_duration:int32 reply_markup:ReplyMarkup input_message_content:InputMessageContent = InputInlineQueryResult;
|
inputInlineQueryResultVideo id:string title:string description:string thumbnail_url:string video_url:string mime_type:string video_width:int32 video_height:int32 video_duration:int32 reply_markup:ReplyMarkup input_message_content:InputMessageContent = InputInlineQueryResult;
|
||||||
|
|
||||||
//@description Represents a link to an opus-encoded audio file within an OGG container, single channel audio @id Unique identifier of the query result @title Title of the voice note
|
//@description Represents a link to an opus-encoded audio file within an OGG container, single channel audio @id Unique identifier of the query result @title Title of the voice note
|
||||||
//@voice_note_url The URL of the voice note file @voice_note_duration Duration of the voice note, in seconds
|
//@voice_note_url The URL of the voice note file @voice_note_duration Duration of the voice note, in seconds
|
||||||
//@reply_markup The message reply markup. Must be of type replyMarkupInlineKeyboard or null
|
//@reply_markup The message reply markup. Must be of type replyMarkupInlineKeyboard or null
|
||||||
//@input_message_content The content of the message to be sent. Must be one of the following types: InputMessageText, InputMessageVoiceNote, InputMessageLocation, InputMessageVenue or InputMessageContact
|
//@input_message_content The content of the message to be sent. Must be one of the following types: inputMessageText, inputMessageVoiceNote, inputMessageInvoice, inputMessageLocation, inputMessageVenue or inputMessageContact
|
||||||
inputInlineQueryResultVoiceNote id:string title:string voice_note_url:string voice_note_duration:int32 reply_markup:ReplyMarkup input_message_content:InputMessageContent = InputInlineQueryResult;
|
inputInlineQueryResultVoiceNote id:string title:string voice_note_url:string voice_note_duration:int32 reply_markup:ReplyMarkup input_message_content:InputMessageContent = InputInlineQueryResult;
|
||||||
|
|
||||||
|
|
||||||
@ -2393,11 +2452,11 @@ chatEventMemberLeft = ChatEventAction;
|
|||||||
//@description A new chat member was invited @user_id New member user identifier @status New member status
|
//@description A new chat member was invited @user_id New member user identifier @status New member status
|
||||||
chatEventMemberInvited user_id:int32 status:ChatMemberStatus = ChatEventAction;
|
chatEventMemberInvited user_id:int32 status:ChatMemberStatus = ChatEventAction;
|
||||||
|
|
||||||
//@description A chat member has gained/lost administrator status, or the list of their administrator privileges has changed @user_id Chat member user identifier @old_status Previous status of the chat member @new_status New status of the chat member
|
//@description A chat member has gained/lost administrator status, or the list of their administrator privileges has changed @user_id Affected chat member user identifier @old_status Previous status of the chat member @new_status New status of the chat member
|
||||||
chatEventMemberPromoted user_id:int32 old_status:ChatMemberStatus new_status:ChatMemberStatus = ChatEventAction;
|
chatEventMemberPromoted user_id:int32 old_status:ChatMemberStatus new_status:ChatMemberStatus = ChatEventAction;
|
||||||
|
|
||||||
//@description A chat member was restricted/unrestricted or banned/unbanned, or the list of their restrictions has changed @user_id Chat member user identifier @old_status Previous status of the chat member @new_status New status of the chat member
|
//@description A chat member was restricted/unrestricted or banned/unbanned, or the list of their restrictions has changed @member_id Affected chat member identifier @old_status Previous status of the chat member @new_status New status of the chat member
|
||||||
chatEventMemberRestricted user_id:int32 old_status:ChatMemberStatus new_status:ChatMemberStatus = ChatEventAction;
|
chatEventMemberRestricted member_id:MessageSender old_status:ChatMemberStatus new_status:ChatMemberStatus = ChatEventAction;
|
||||||
|
|
||||||
//@description The chat title was changed @old_title Previous chat title @new_title New chat title
|
//@description The chat title was changed @old_title Previous chat title @new_title New chat title
|
||||||
chatEventTitleChanged old_title:string new_title:string = ChatEventAction;
|
chatEventTitleChanged old_title:string new_title:string = ChatEventAction;
|
||||||
@ -2453,11 +2512,11 @@ chatEventVoiceChatCreated group_call_id:int32 = ChatEventAction;
|
|||||||
//@description A voice chat was discarded @group_call_id Identifier of the voice chat. The voice chat can be received through the method getGroupCall
|
//@description A voice chat was discarded @group_call_id Identifier of the voice chat. The voice chat can be received through the method getGroupCall
|
||||||
chatEventVoiceChatDiscarded group_call_id:int32 = ChatEventAction;
|
chatEventVoiceChatDiscarded group_call_id:int32 = ChatEventAction;
|
||||||
|
|
||||||
//@description A voice chat participant was muted or unmuted @user_id Identifier of the affected user @is_muted New value of is_muted
|
//@description A voice chat participant was muted or unmuted @participant_id Identifier of the affected group call participant @is_muted New value of is_muted
|
||||||
chatEventVoiceChatParticipantIsMutedToggled user_id:int32 is_muted:Bool = ChatEventAction;
|
chatEventVoiceChatParticipantIsMutedToggled participant_id:MessageSender is_muted:Bool = ChatEventAction;
|
||||||
|
|
||||||
//@description A voice chat participant volume level was changed @user_id Identifier of the affected user @volume_level New value of volume_level; 1-20000 in hundreds of percents
|
//@description A voice chat participant volume level was changed @participant_id Identifier of the affected group call participant @volume_level New value of volume_level; 1-20000 in hundreds of percents
|
||||||
chatEventVoiceChatParticipantVolumeLevelChanged user_id:int32 volume_level:int32 = ChatEventAction;
|
chatEventVoiceChatParticipantVolumeLevelChanged participant_id:MessageSender volume_level:int32 = ChatEventAction;
|
||||||
|
|
||||||
//@description The mute_new_participants setting of a voice chat was toggled @mute_new_participants New value of the mute_new_participants setting
|
//@description The mute_new_participants setting of a voice chat was toggled @mute_new_participants New value of the mute_new_participants setting
|
||||||
chatEventVoiceChatMuteNewParticipantsToggled mute_new_participants:Bool = ChatEventAction;
|
chatEventVoiceChatMuteNewParticipantsToggled mute_new_participants:Bool = ChatEventAction;
|
||||||
@ -3328,6 +3387,9 @@ updateAuthorizationState authorization_state:AuthorizationState = Update;
|
|||||||
//@description A new message was received; can also be an outgoing message @message The new message
|
//@description A new message was received; can also be an outgoing message @message The new message
|
||||||
updateNewMessage message:message = Update;
|
updateNewMessage message:message = Update;
|
||||||
|
|
||||||
|
//@description A new channel difference part was received @channel_difference_id The channel difference id
|
||||||
|
updateNewChannelDifferencePart channel_difference_id:int64 = Update;
|
||||||
|
|
||||||
//@description A request to send a message has reached the Telegram server. This doesn't mean that the message will be sent successfully or even that the send message request will be processed. This update will be sent only if the option "use_quick_ack" is set to true. This update may be sent multiple times for the same message
|
//@description A request to send a message has reached the Telegram server. This doesn't mean that the message will be sent successfully or even that the send message request will be processed. This update will be sent only if the option "use_quick_ack" is set to true. This update may be sent multiple times for the same message
|
||||||
//@chat_id The chat identifier of the sent message @message_id A temporary message identifier
|
//@chat_id The chat identifier of the sent message @message_id A temporary message identifier
|
||||||
updateMessageSendAcknowledged chat_id:int53 message_id:int53 = Update;
|
updateMessageSendAcknowledged chat_id:int53 message_id:int53 = Update;
|
||||||
@ -3388,8 +3450,8 @@ updateChatIsBlocked chat_id:int53 is_blocked:Bool = Update;
|
|||||||
//@description A chat's has_scheduled_messages field has changed @chat_id Chat identifier @has_scheduled_messages New value of has_scheduled_messages
|
//@description A chat's has_scheduled_messages field has changed @chat_id Chat identifier @has_scheduled_messages New value of has_scheduled_messages
|
||||||
updateChatHasScheduledMessages chat_id:int53 has_scheduled_messages:Bool = Update;
|
updateChatHasScheduledMessages chat_id:int53 has_scheduled_messages:Bool = Update;
|
||||||
|
|
||||||
//@description A chat voice chat state has changed @chat_id Chat identifier @voice_chat_group_call_id New value of voice_chat_group_call_id @is_voice_chat_empty New value of is_voice_chat_empty
|
//@description A chat voice chat state has changed @chat_id Chat identifier @voice_chat New value of voice_chat
|
||||||
updateChatVoiceChat chat_id:int53 voice_chat_group_call_id:int32 is_voice_chat_empty:Bool = Update;
|
updateChatVoiceChat chat_id:int53 voice_chat:voiceChat = Update;
|
||||||
|
|
||||||
//@description The value of the default disable_notification parameter, used when a message is sent to the chat, was changed @chat_id Chat identifier @default_disable_notification The new default_disable_notification value
|
//@description The value of the default disable_notification parameter, used when a message is sent to the chat, was changed @chat_id Chat identifier @default_disable_notification The new default_disable_notification value
|
||||||
updateChatDefaultDisableNotification chat_id:int53 default_disable_notification:Bool = Update;
|
updateChatDefaultDisableNotification chat_id:int53 default_disable_notification:Bool = Update;
|
||||||
@ -3591,7 +3653,7 @@ updateNewInlineCallbackQuery id:int64 sender_user_id:int32 inline_message_id:str
|
|||||||
//@description A new incoming shipping query; for bots only. Only for invoices with flexible price @id Unique query identifier @sender_user_id Identifier of the user who sent the query @invoice_payload Invoice payload @shipping_address User shipping address
|
//@description A new incoming shipping query; for bots only. Only for invoices with flexible price @id Unique query identifier @sender_user_id Identifier of the user who sent the query @invoice_payload Invoice payload @shipping_address User shipping address
|
||||||
updateNewShippingQuery id:int64 sender_user_id:int32 invoice_payload:string shipping_address:address = Update;
|
updateNewShippingQuery id:int64 sender_user_id:int32 invoice_payload:string shipping_address:address = Update;
|
||||||
|
|
||||||
//@description A new incoming pre-checkout query; for bots only. Contains full information about a checkout @id Unique query identifier @sender_user_id Identifier of the user who sent the query @currency Currency for the product price @total_amount Total price for the product, in the minimal quantity of the currency
|
//@description A new incoming pre-checkout query; for bots only. Contains full information about a checkout @id Unique query identifier @sender_user_id Identifier of the user who sent the query @currency Currency for the product price @total_amount Total price for the product, in the smallest units of the currency
|
||||||
//@invoice_payload Invoice payload @shipping_option_id Identifier of a shipping option chosen by the user; may be empty if not applicable @order_info Information about the order; may be null
|
//@invoice_payload Invoice payload @shipping_option_id Identifier of a shipping option chosen by the user; may be empty if not applicable @order_info Information about the order; may be null
|
||||||
updateNewPreCheckoutQuery id:int64 sender_user_id:int32 currency:string total_amount:int53 invoice_payload:bytes shipping_option_id:string order_info:orderInfo = Update;
|
updateNewPreCheckoutQuery id:int64 sender_user_id:int32 currency:string total_amount:int53 invoice_payload:bytes shipping_option_id:string order_info:orderInfo = Update;
|
||||||
|
|
||||||
@ -3805,6 +3867,9 @@ getMessageThread chat_id:int53 message_id:int53 = MessageThreadInfo;
|
|||||||
//@description Returns information about a file; this is an offline request @file_id Identifier of the file to get
|
//@description Returns information about a file; this is an offline request @file_id Identifier of the file to get
|
||||||
getFile file_id:int32 = File;
|
getFile file_id:int32 = File;
|
||||||
|
|
||||||
|
//@description Execute a channel difference @channel_difference_id Identifier of the channel difference to execute
|
||||||
|
getChannelDifference channel_difference_id:int64 = Ok;
|
||||||
|
|
||||||
//@description Returns information about a file by its remote ID; this is an offline request. Can be used to register a URL as a file for further uploading, or sending as a message. Even the request succeeds, the file can be used only if it is still accessible to the user.
|
//@description Returns information about a file by its remote ID; this is an offline request. Can be used to register a URL as a file for further uploading, or sending as a message. Even the request succeeds, the file can be used only if it is still accessible to the user.
|
||||||
//-For example, if the file is from a message, then the message must be not deleted and accessible to the user. If the file database is disabled, then the corresponding object with the file must be preloaded by the application
|
//-For example, if the file is from a message, then the message must be not deleted and accessible to the user. If the file database is disabled, then the corresponding object with the file must be preloaded by the application
|
||||||
//@remote_file_id Remote identifier of the file to get @file_type File type, if known
|
//@remote_file_id Remote identifier of the file to get @file_type File type, if known
|
||||||
@ -3906,7 +3971,7 @@ searchChatMessages chat_id:int53 query:string sender:MessageSender from_message_
|
|||||||
|
|
||||||
//@description Searches for messages in all chats except secret chats. Returns the results in reverse chronological order (i.e., in order of decreasing (date, chat_id, message_id)).
|
//@description Searches for messages in all chats except secret chats. Returns the results in reverse chronological order (i.e., in order of decreasing (date, chat_id, message_id)).
|
||||||
//-For optimal performance the number of returned messages is chosen by the library
|
//-For optimal performance the number of returned messages is chosen by the library
|
||||||
//@chat_list Chat list in which to search messages; pass null to search in all chats regardless of their chat list
|
//@chat_list Chat list in which to search messages; pass null to search in all chats regardless of their chat list. Only Main and Archive chat lists are supported
|
||||||
//@query Query to search for
|
//@query Query to search for
|
||||||
//@offset_date The date of the message starting from which the results should be fetched. Use 0 or any date in the future to get results from the last message
|
//@offset_date The date of the message starting from which the results should be fetched. Use 0 or any date in the future to get results from the last message
|
||||||
//@offset_chat_id The chat identifier of the last found message, or 0 for the first request
|
//@offset_chat_id The chat identifier of the last found message, or 0 for the first request
|
||||||
@ -4042,7 +4107,7 @@ deleteChatMessagesFromUser chat_id:int53 user_id:int32 = Ok;
|
|||||||
|
|
||||||
|
|
||||||
//@description Edits the text of a message (or a text of a game message). Returns the edited message after the edit is completed on the server side
|
//@description Edits the text of a message (or a text of a game message). Returns the edited message after the edit is completed on the server side
|
||||||
//@chat_id The chat the message belongs to @message_id Identifier of the message @reply_markup The new message reply markup; for bots only @input_message_content New text content of the message. Should be of type InputMessageText
|
//@chat_id The chat the message belongs to @message_id Identifier of the message @reply_markup The new message reply markup; for bots only @input_message_content New text content of the message. Should be of type inputMessageText
|
||||||
editMessageText chat_id:int53 message_id:int53 reply_markup:ReplyMarkup input_message_content:InputMessageContent = Message;
|
editMessageText chat_id:int53 message_id:int53 reply_markup:ReplyMarkup input_message_content:InputMessageContent = Message;
|
||||||
|
|
||||||
//@description Edits the message content of a live location. Messages can be edited for a limited period of time specified in the live location. Returns the edited message after the edit is completed on the server side
|
//@description Edits the message content of a live location. Messages can be edited for a limited period of time specified in the live location. Returns the edited message after the edit is completed on the server side
|
||||||
@ -4052,7 +4117,7 @@ editMessageText chat_id:int53 message_id:int53 reply_markup:ReplyMarkup input_me
|
|||||||
editMessageLiveLocation chat_id:int53 message_id:int53 reply_markup:ReplyMarkup location:location heading:int32 proximity_alert_radius:int32 = Message;
|
editMessageLiveLocation chat_id:int53 message_id:int53 reply_markup:ReplyMarkup location:location heading:int32 proximity_alert_radius:int32 = Message;
|
||||||
|
|
||||||
//@description Edits the content of a message with an animation, an audio, a document, a photo or a video. The media in the message can't be replaced if the message was set to self-destruct. Media can't be replaced by self-destructing media. Media in an album can be edited only to contain a photo or a video. Returns the edited message after the edit is completed on the server side
|
//@description Edits the content of a message with an animation, an audio, a document, a photo or a video. The media in the message can't be replaced if the message was set to self-destruct. Media can't be replaced by self-destructing media. Media in an album can be edited only to contain a photo or a video. Returns the edited message after the edit is completed on the server side
|
||||||
//@chat_id The chat the message belongs to @message_id Identifier of the message @reply_markup The new message reply markup; for bots only @input_message_content New content of the message. Must be one of the following types: InputMessageAnimation, InputMessageAudio, InputMessageDocument, InputMessagePhoto or InputMessageVideo
|
//@chat_id The chat the message belongs to @message_id Identifier of the message @reply_markup The new message reply markup; for bots only @input_message_content New content of the message. Must be one of the following types: inputMessageAnimation, inputMessageAudio, inputMessageDocument, inputMessagePhoto or inputMessageVideo
|
||||||
editMessageMedia chat_id:int53 message_id:int53 reply_markup:ReplyMarkup input_message_content:InputMessageContent = Message;
|
editMessageMedia chat_id:int53 message_id:int53 reply_markup:ReplyMarkup input_message_content:InputMessageContent = Message;
|
||||||
|
|
||||||
//@description Edits the message content caption. Returns the edited message after the edit is completed on the server side
|
//@description Edits the message content caption. Returns the edited message after the edit is completed on the server side
|
||||||
@ -4063,7 +4128,7 @@ editMessageCaption chat_id:int53 message_id:int53 reply_markup:ReplyMarkup capti
|
|||||||
//@chat_id The chat the message belongs to @message_id Identifier of the message @reply_markup The new message reply markup
|
//@chat_id The chat the message belongs to @message_id Identifier of the message @reply_markup The new message reply markup
|
||||||
editMessageReplyMarkup chat_id:int53 message_id:int53 reply_markup:ReplyMarkup = Message;
|
editMessageReplyMarkup chat_id:int53 message_id:int53 reply_markup:ReplyMarkup = Message;
|
||||||
|
|
||||||
//@description Edits the text of an inline text or game message sent via a bot; for bots only @inline_message_id Inline message identifier @reply_markup The new message reply markup @input_message_content New text content of the message. Should be of type InputMessageText
|
//@description Edits the text of an inline text or game message sent via a bot; for bots only @inline_message_id Inline message identifier @reply_markup The new message reply markup @input_message_content New text content of the message. Should be of type inputMessageText
|
||||||
editInlineMessageText inline_message_id:string reply_markup:ReplyMarkup input_message_content:InputMessageContent = Ok;
|
editInlineMessageText inline_message_id:string reply_markup:ReplyMarkup input_message_content:InputMessageContent = Ok;
|
||||||
|
|
||||||
//@description Edits the content of a live location in an inline message sent via a bot; for bots only @inline_message_id Inline message identifier @reply_markup The new message reply markup
|
//@description Edits the content of a live location in an inline message sent via a bot; for bots only @inline_message_id Inline message identifier @reply_markup The new message reply markup
|
||||||
@ -4073,7 +4138,7 @@ editInlineMessageText inline_message_id:string reply_markup:ReplyMarkup input_me
|
|||||||
editInlineMessageLiveLocation inline_message_id:string reply_markup:ReplyMarkup location:location heading:int32 proximity_alert_radius:int32 = Ok;
|
editInlineMessageLiveLocation inline_message_id:string reply_markup:ReplyMarkup location:location heading:int32 proximity_alert_radius:int32 = Ok;
|
||||||
|
|
||||||
//@description Edits the content of a message with an animation, an audio, a document, a photo or a video in an inline message sent via a bot; for bots only @inline_message_id Inline message identifier
|
//@description Edits the content of a message with an animation, an audio, a document, a photo or a video in an inline message sent via a bot; for bots only @inline_message_id Inline message identifier
|
||||||
//@reply_markup The new message reply markup; for bots only @input_message_content New content of the message. Must be one of the following types: InputMessageAnimation, InputMessageAudio, InputMessageDocument, InputMessagePhoto or InputMessageVideo
|
//@reply_markup The new message reply markup; for bots only @input_message_content New content of the message. Must be one of the following types: inputMessageAnimation, inputMessageAudio, inputMessageDocument, inputMessagePhoto or inputMessageVideo
|
||||||
editInlineMessageMedia inline_message_id:string reply_markup:ReplyMarkup input_message_content:InputMessageContent = Ok;
|
editInlineMessageMedia inline_message_id:string reply_markup:ReplyMarkup input_message_content:InputMessageContent = Ok;
|
||||||
|
|
||||||
//@description Edits the caption of an inline message sent via a bot; for bots only @inline_message_id Inline message identifier @reply_markup The new message reply markup @caption New message content caption; 0-GetOption("message_caption_length_max") characters
|
//@description Edits the caption of an inline message sent via a bot; for bots only @inline_message_id Inline message identifier @reply_markup The new message reply markup @caption New message content caption; 0-GetOption("message_caption_length_max") characters
|
||||||
@ -4215,8 +4280,12 @@ viewMessages chat_id:int53 message_thread_id:int53 message_ids:vector<int53> for
|
|||||||
//@description Informs TDLib that the message content has been opened (e.g., the user has opened a photo, video, document, location or venue, or has listened to an audio file or voice note message). An updateMessageContentOpened update will be generated if something has changed @chat_id Chat identifier of the message @message_id Identifier of the message with the opened content
|
//@description Informs TDLib that the message content has been opened (e.g., the user has opened a photo, video, document, location or venue, or has listened to an audio file or voice note message). An updateMessageContentOpened update will be generated if something has changed @chat_id Chat identifier of the message @message_id Identifier of the message with the opened content
|
||||||
openMessageContent chat_id:int53 message_id:int53 = Ok;
|
openMessageContent chat_id:int53 message_id:int53 = Ok;
|
||||||
|
|
||||||
//@description Returns an HTTP URL to open when user clicks on a given HTTP link. This method can be used to automatically login user on a Telegram site @link The HTTP link
|
//@description Returns information about an action to be done when the current user clicks an HTTP link. This method can be used to automatically authorize the current user on a website. Don't use this method for links from secret chats if link preview is disabled in secret chats @link The HTTP link
|
||||||
getExternalLink link:string = HttpUrl;
|
getExternalLinkInfo link:string = LoginUrlInfo;
|
||||||
|
|
||||||
|
//@description Returns an HTTP URL which can be used to automatically authorize the current user on a website after clicking an HTTP link. Use the method getExternalLinkInfo to find whether a prior user confirmation is needed
|
||||||
|
//@link The HTTP link @allow_write_access True, if the current user allowed the bot, returned in getExternalLinkInfo, to send them messages
|
||||||
|
getExternalLink link:string allow_write_access:Bool = HttpUrl;
|
||||||
|
|
||||||
|
|
||||||
//@description Marks all mentions in a chat as read @chat_id Chat identifier
|
//@description Marks all mentions in a chat as read @chat_id Chat identifier
|
||||||
@ -4357,15 +4426,15 @@ addChatMember chat_id:int53 user_id:int32 forward_limit:int32 = Ok;
|
|||||||
addChatMembers chat_id:int53 user_ids:vector<int32> = Ok;
|
addChatMembers chat_id:int53 user_ids:vector<int32> = Ok;
|
||||||
|
|
||||||
//@description Changes the status of a chat member, needs appropriate privileges. This function is currently not suitable for adding new members to the chat and transferring chat ownership; instead, use addChatMember or transferChatOwnership
|
//@description Changes the status of a chat member, needs appropriate privileges. This function is currently not suitable for adding new members to the chat and transferring chat ownership; instead, use addChatMember or transferChatOwnership
|
||||||
//@chat_id Chat identifier @user_id User identifier @status The new status of the member in the chat
|
//@chat_id Chat identifier @member_id Member identifier. Chats can be only banned and unbanned in supergroups and channels @status The new status of the member in the chat
|
||||||
setChatMemberStatus chat_id:int53 user_id:int32 status:ChatMemberStatus = Ok;
|
setChatMemberStatus chat_id:int53 member_id:MessageSender status:ChatMemberStatus = Ok;
|
||||||
|
|
||||||
//@description Bans a member in a chat. Members can't be banned in private or secret chats. In supergroups and channels, the user will not be able to return to the group on their own using invite links, etc., unless unbanned first
|
//@description Bans a member in a chat. Members can't be banned in private or secret chats. In supergroups and channels, the user will not be able to return to the group on their own using invite links, etc., unless unbanned first
|
||||||
//@chat_id Chat identifier
|
//@chat_id Chat identifier
|
||||||
//@user_id Identifier of the user
|
//@member_id Member identifier
|
||||||
//@banned_until_date Point in time (Unix timestamp) when the user will be unbanned; 0 if never. If the user is banned for more than 366 days or for less than 30 seconds from the current time, the user is considered to be banned forever. Ignored in basic groups
|
//@banned_until_date Point in time (Unix timestamp) when the user will be unbanned; 0 if never. If the user is banned for more than 366 days or for less than 30 seconds from the current time, the user is considered to be banned forever. Ignored in basic groups
|
||||||
//@revoke_messages Pass true to delete all messages in the chat for the user. Always true for supergroups and channels
|
//@revoke_messages Pass true to delete all messages in the chat for the user. Always true for supergroups and channels
|
||||||
banChatMember chat_id:int53 user_id:int32 banned_until_date:int32 revoke_messages:Bool = Ok;
|
banChatMember chat_id:int53 member_id:MessageSender banned_until_date:int32 revoke_messages:Bool = Ok;
|
||||||
|
|
||||||
//@description Checks whether the current session can be used to transfer a chat ownership to another user
|
//@description Checks whether the current session can be used to transfer a chat ownership to another user
|
||||||
canTransferOwnership = CanTransferOwnershipResult;
|
canTransferOwnership = CanTransferOwnershipResult;
|
||||||
@ -4374,8 +4443,8 @@ canTransferOwnership = CanTransferOwnershipResult;
|
|||||||
//@chat_id Chat identifier @user_id Identifier of the user to which transfer the ownership. The ownership can't be transferred to a bot or to a deleted user @password The password of the current user
|
//@chat_id Chat identifier @user_id Identifier of the user to which transfer the ownership. The ownership can't be transferred to a bot or to a deleted user @password The password of the current user
|
||||||
transferChatOwnership chat_id:int53 user_id:int32 password:string = Ok;
|
transferChatOwnership chat_id:int53 user_id:int32 password:string = Ok;
|
||||||
|
|
||||||
//@description Returns information about a single member of a chat @chat_id Chat identifier @user_id User identifier
|
//@description Returns information about a single member of a chat @chat_id Chat identifier @member_id Member identifier
|
||||||
getChatMember chat_id:int53 user_id:int32 = ChatMember;
|
getChatMember chat_id:int53 member_id:MessageSender = ChatMember;
|
||||||
|
|
||||||
//@description Searches for a specified query in the first name, last name and username of the members of a specified chat. Requires administrator rights in channels @chat_id Chat identifier @query Query to search for @limit The maximum number of users to be returned @filter The type of users to return. By default, chatMembersFilterMembers
|
//@description Searches for a specified query in the first name, last name and username of the members of a specified chat. Requires administrator rights in channels @chat_id Chat identifier @query Query to search for @limit The maximum number of users to be returned @filter The type of users to return. By default, chatMembersFilterMembers
|
||||||
searchChatMembers chat_id:int53 query:string limit:int32 filter:ChatMembersFilter = ChatMembers;
|
searchChatMembers chat_id:int53 query:string limit:int32 filter:ChatMembersFilter = ChatMembers;
|
||||||
@ -4476,14 +4545,14 @@ replacePrimaryChatInviteLink chat_id:int53 = ChatInviteLink;
|
|||||||
//@description Creates a new invite link for a chat. Available for basic groups, supergroups, and channels. Requires administrator privileges and can_invite_users right in the chat
|
//@description Creates a new invite link for a chat. Available for basic groups, supergroups, and channels. Requires administrator privileges and can_invite_users right in the chat
|
||||||
//@chat_id Chat identifier
|
//@chat_id Chat identifier
|
||||||
//@expire_date Point in time (Unix timestamp) when the link will expire; pass 0 if never
|
//@expire_date Point in time (Unix timestamp) when the link will expire; pass 0 if never
|
||||||
//@member_limit Maximum number of chat members that can join the chat by the link simultaneously; 0-99999; pass 0 if not limited
|
//@member_limit The maximum number of chat members that can join the chat by the link simultaneously; 0-99999; pass 0 if not limited
|
||||||
createChatInviteLink chat_id:int53 expire_date:int32 member_limit:int32 = ChatInviteLink;
|
createChatInviteLink chat_id:int53 expire_date:int32 member_limit:int32 = ChatInviteLink;
|
||||||
|
|
||||||
//@description Edits a non-primary invite link for a chat. Available for basic groups, supergroups, and channels. Requires administrator privileges and can_invite_users right in the chat for own links and owner privileges for other links
|
//@description Edits a non-primary invite link for a chat. Available for basic groups, supergroups, and channels. Requires administrator privileges and can_invite_users right in the chat for own links and owner privileges for other links
|
||||||
//@chat_id Chat identifier
|
//@chat_id Chat identifier
|
||||||
//@invite_link Invite link to be edited
|
//@invite_link Invite link to be edited
|
||||||
//@expire_date Point in time (Unix timestamp) when the link will expire; pass 0 if never
|
//@expire_date Point in time (Unix timestamp) when the link will expire; pass 0 if never
|
||||||
//@member_limit Maximum number of chat members that can join the chat by the link simultaneously; 0-99999; pass 0 if not limited
|
//@member_limit The maximum number of chat members that can join the chat by the link simultaneously; 0-99999; pass 0 if not limited
|
||||||
editChatInviteLink chat_id:int53 invite_link:string expire_date:int32 member_limit:int32 = ChatInviteLink;
|
editChatInviteLink chat_id:int53 invite_link:string expire_date:int32 member_limit:int32 = ChatInviteLink;
|
||||||
|
|
||||||
//@description Returns information about an invite link. Requires administrator privileges and can_invite_users right in the chat to get own links and owner privileges to get other links
|
//@description Returns information about an invite link. Requires administrator privileges and can_invite_users right in the chat to get own links and owner privileges to get other links
|
||||||
@ -4500,11 +4569,11 @@ getChatInviteLinkCounts chat_id:int53 = ChatInviteLinkCounts;
|
|||||||
//@is_revoked Pass true if revoked links needs to be returned instead of active or expired
|
//@is_revoked Pass true if revoked links needs to be returned instead of active or expired
|
||||||
//@offset_date Creation date of an invite link starting after which to return invite links; use 0 to get results from the beginning
|
//@offset_date Creation date of an invite link starting after which to return invite links; use 0 to get results from the beginning
|
||||||
//@offset_invite_link Invite link starting after which to return invite links; use empty string to get results from the beginning
|
//@offset_invite_link Invite link starting after which to return invite links; use empty string to get results from the beginning
|
||||||
//@limit Maximum number of invite links to return
|
//@limit The maximum number of invite links to return
|
||||||
getChatInviteLinks chat_id:int53 creator_user_id:int32 is_revoked:Bool offset_date:int32 offset_invite_link:string limit:int32 = ChatInviteLinks;
|
getChatInviteLinks chat_id:int53 creator_user_id:int32 is_revoked:Bool offset_date:int32 offset_invite_link:string limit:int32 = ChatInviteLinks;
|
||||||
|
|
||||||
//@description Returns chat members joined a chat by an invite link. Requires administrator privileges and can_invite_users right in the chat for own links and owner privileges for other links @chat_id Chat identifier @invite_link Invite link for which to return chat members
|
//@description Returns chat members joined a chat by an invite link. Requires administrator privileges and can_invite_users right in the chat for own links and owner privileges for other links @chat_id Chat identifier @invite_link Invite link for which to return chat members
|
||||||
//@offset_member A chat member from which to return next chat members; use null to get results from the beginning @limit Maximum number of chat members to return
|
//@offset_member A chat member from which to return next chat members; use null to get results from the beginning @limit The maximum number of chat members to return
|
||||||
getChatInviteLinkMembers chat_id:int53 invite_link:string offset_member:chatInviteLinkMember limit:int32 = ChatInviteLinkMembers;
|
getChatInviteLinkMembers chat_id:int53 invite_link:string offset_member:chatInviteLinkMember limit:int32 = ChatInviteLinkMembers;
|
||||||
|
|
||||||
//@description Revokes invite link for a chat. Available for basic groups, supergroups, and channels. Requires administrator privileges and can_invite_users right in the chat for own links and owner privileges for other links.
|
//@description Revokes invite link for a chat. Available for basic groups, supergroups, and channels. Requires administrator privileges and can_invite_users right in the chat for own links and owner privileges for other links.
|
||||||
@ -4548,38 +4617,82 @@ sendCallRating call_id:int32 rating:int32 comment:string problems:vector<CallPro
|
|||||||
sendCallDebugInformation call_id:int32 debug_information:string = Ok;
|
sendCallDebugInformation call_id:int32 debug_information:string = Ok;
|
||||||
|
|
||||||
|
|
||||||
//@description Creates a voice chat (a group call bound to a chat). Available only for basic groups and supergroups; requires can_manage_voice_chats rights @chat_id Chat identifier
|
//@description Returns list of participant identifiers, which can be used to join voice chats in a chat @chat_id Chat identifier
|
||||||
createVoiceChat chat_id:int53 = GroupCallId;
|
getVoiceChatAvailableParticipants chat_id:int53 = MessageSenders;
|
||||||
|
|
||||||
|
//@description Changes default participant identifier, which can be used to join voice chats in a chat @chat_id Chat identifier @default_participant_id Default group call participant identifier to join the voice chats
|
||||||
|
setVoiceChatDefaultParticipant chat_id:int53 default_participant_id:MessageSender = Ok;
|
||||||
|
|
||||||
|
//@description Creates a voice chat (a group call bound to a chat). Available only for basic groups, supergroups and channels; requires can_manage_voice_chats rights
|
||||||
|
//@chat_id Chat identifier, in which the voice chat will be created
|
||||||
|
//@title Group call title; if empty, chat title will be used
|
||||||
|
//@start_date Point in time (Unix timestamp) when the group call is supposed to be started by an administrator; 0 to start the voice chat immediately. The date must be at least 10 seconds and at most 8 days in the future
|
||||||
|
createVoiceChat chat_id:int53 title:string start_date:int32 = GroupCallId;
|
||||||
|
|
||||||
//@description Returns information about a group call @group_call_id Group call identifier
|
//@description Returns information about a group call @group_call_id Group call identifier
|
||||||
getGroupCall group_call_id:int32 = GroupCall;
|
getGroupCall group_call_id:int32 = GroupCall;
|
||||||
|
|
||||||
//@description Joins a group call @group_call_id Group call identifier @payload Group join payload, received from tgcalls. Use null to cancel previous joinGroupCall request @source Caller synchronization source identifier; received from tgcalls @is_muted True, if the user's microphone is muted
|
//@description Starts a scheduled group call @group_call_id Group call identifier
|
||||||
joinGroupCall group_call_id:int32 payload:groupCallPayload source:int32 is_muted:Bool = GroupCallJoinResponse;
|
startScheduledGroupCall group_call_id:int32 = Ok;
|
||||||
|
|
||||||
|
//@description Toggles whether the current user will receive a notification when the group call will start; scheduled group calls only
|
||||||
|
//@group_call_id Group call identifier @enabled_start_notification New value of the enabled_start_notification setting
|
||||||
|
toggleGroupCallEnabledStartNotification group_call_id:int32 enabled_start_notification:Bool = Ok;
|
||||||
|
|
||||||
|
//@description Joins an active group call
|
||||||
|
//@group_call_id Group call identifier
|
||||||
|
//@participant_id Identifier of a group call participant, which will be used to join the call; voice chats only
|
||||||
|
//@payload Group join payload; received from tgcalls
|
||||||
|
//@source Caller synchronization source identifier; received from tgcalls
|
||||||
|
//@is_muted True, if the user's microphone is muted
|
||||||
|
//@invite_hash If non-empty, invite hash to be used to join the group call without being muted by administrators
|
||||||
|
joinGroupCall group_call_id:int32 participant_id:MessageSender payload:groupCallPayload source:int32 is_muted:Bool invite_hash:string = GroupCallJoinResponse;
|
||||||
|
|
||||||
|
//@description Sets group call title. Requires groupCall.can_be_managed group call flag @group_call_id Group call identifier @title New group call title; 1-64 characters
|
||||||
|
setGroupCallTitle group_call_id:int32 title:string = Ok;
|
||||||
|
|
||||||
//@description Toggles whether new participants of a group call can be unmuted only by administrators of the group call. Requires groupCall.can_change_mute_new_participants group call flag
|
//@description Toggles whether new participants of a group call can be unmuted only by administrators of the group call. Requires groupCall.can_change_mute_new_participants group call flag
|
||||||
//@group_call_id Group call identifier @mute_new_participants New value of the mute_new_participants setting
|
//@group_call_id Group call identifier @mute_new_participants New value of the mute_new_participants setting
|
||||||
toggleGroupCallMuteNewParticipants group_call_id:int32 mute_new_participants:Bool = Ok;
|
toggleGroupCallMuteNewParticipants group_call_id:int32 mute_new_participants:Bool = Ok;
|
||||||
|
|
||||||
//@description Invites users to a group call. Sends a service message of type messageInviteToGroupCall for voice chats
|
//@description Revokes invite link for a group call. Requires groupCall.can_be_managed group call flag @group_call_id Group call identifier
|
||||||
|
revokeGroupCallInviteLink group_call_id:int32 = Ok;
|
||||||
|
|
||||||
|
//@description Invites users to an active group call. Sends a service message of type messageInviteToGroupCall for voice chats
|
||||||
//@group_call_id Group call identifier @user_ids User identifiers. At most 10 users can be invited simultaneously
|
//@group_call_id Group call identifier @user_ids User identifiers. At most 10 users can be invited simultaneously
|
||||||
inviteGroupCallParticipants group_call_id:int32 user_ids:vector<int32> = Ok;
|
inviteGroupCallParticipants group_call_id:int32 user_ids:vector<int32> = Ok;
|
||||||
|
|
||||||
//@description Informs TDLib that a group call participant speaking state has changed @group_call_id Group call identifier
|
//@description Returns invite link to a voice chat in a public chat
|
||||||
|
//@group_call_id Group call identifier
|
||||||
|
//@can_self_unmute Pass true if the invite_link should contain an invite hash, passing which to joinGroupCall would allow the invited user to unmute themself. Requires groupCall.can_be_managed group call flag
|
||||||
|
getGroupCallInviteLink group_call_id:int32 can_self_unmute:Bool = HttpUrl;
|
||||||
|
|
||||||
|
//@description Starts recording of an active group call. Requires groupCall.can_be_managed group call flag @group_call_id Group call identifier @title Group call recording title; 0-64 characters
|
||||||
|
startGroupCallRecording group_call_id:int32 title:string = Ok;
|
||||||
|
|
||||||
|
//@description Ends recording of an active group call. Requires groupCall.can_be_managed group call flag @group_call_id Group call identifier
|
||||||
|
endGroupCallRecording group_call_id:int32 = Ok;
|
||||||
|
|
||||||
|
//@description Informs TDLib that a participant of an active group call speaking state has changed @group_call_id Group call identifier
|
||||||
//@source Group call participant's synchronization source identifier, or 0 for the current user @is_speaking True, if the user is speaking
|
//@source Group call participant's synchronization source identifier, or 0 for the current user @is_speaking True, if the user is speaking
|
||||||
setGroupCallParticipantIsSpeaking group_call_id:int32 source:int32 is_speaking:Bool = Ok;
|
setGroupCallParticipantIsSpeaking group_call_id:int32 source:int32 is_speaking:Bool = Ok;
|
||||||
|
|
||||||
//@description Toggles whether a group call participant is muted, unmuted, or allowed to unmute themself
|
//@description Toggles whether a participant of an active group call is muted, unmuted, or allowed to unmute themself
|
||||||
//@group_call_id Group call identifier @user_id User identifier @is_muted Pass true if the user must be muted and false otherwise
|
//@group_call_id Group call identifier @participant_id Participant identifier @is_muted Pass true if the user must be muted and false otherwise
|
||||||
toggleGroupCallParticipantIsMuted group_call_id:int32 user_id:int32 is_muted:Bool = Ok;
|
toggleGroupCallParticipantIsMuted group_call_id:int32 participant_id:MessageSender is_muted:Bool = Ok;
|
||||||
|
|
||||||
//@description Changes a group call participant's volume level. If the current user can manage the group call, then the participant's volume level will be changed for all users with default volume level
|
//@description Changes volume level of a participant of an active group call. If the current user can manage the group call, then the participant's volume level will be changed for all users with default volume level
|
||||||
//@group_call_id Group call identifier @user_id User identifier @volume_level New participant's volume level; 1-20000 in hundreds of percents
|
//@group_call_id Group call identifier @participant_id Participant identifier @volume_level New participant's volume level; 1-20000 in hundreds of percents
|
||||||
setGroupCallParticipantVolumeLevel group_call_id:int32 user_id:int32 volume_level:int32 = Ok;
|
setGroupCallParticipantVolumeLevel group_call_id:int32 participant_id:MessageSender volume_level:int32 = Ok;
|
||||||
|
|
||||||
//@description Loads more group call participants. The loaded participants will be received through updates. Use the field groupCall.loaded_all_participants to check whether all participants has already been loaded
|
//@description Toggles whether a group call participant hand is rased
|
||||||
|
//@group_call_id Group call identifier @participant_id Participant identifier
|
||||||
|
//@is_hand_raised Pass true if the user's hand should be raised. Only self hand can be raised. Requires groupCall.can_be_managed group call flag to lower other's hand
|
||||||
|
toggleGroupCallParticipantIsHandRaised group_call_id:int32 participant_id:MessageSender is_hand_raised:Bool = Ok;
|
||||||
|
|
||||||
|
//@description Loads more participants of a group call. The loaded participants will be received through updates. Use the field groupCall.loaded_all_participants to check whether all participants has already been loaded
|
||||||
//@group_call_id Group call identifier. The group call must be previously received through getGroupCall and must be joined or being joined
|
//@group_call_id Group call identifier. The group call must be previously received through getGroupCall and must be joined or being joined
|
||||||
//@limit Maximum number of participants to load
|
//@limit The maximum number of participants to load
|
||||||
loadGroupCallParticipants group_call_id:int32 limit:int32 = Ok;
|
loadGroupCallParticipants group_call_id:int32 limit:int32 = Ok;
|
||||||
|
|
||||||
//@description Leaves a group call @group_call_id Group call identifier
|
//@description Leaves a group call @group_call_id Group call identifier
|
||||||
@ -4588,6 +4701,12 @@ leaveGroupCall group_call_id:int32 = Ok;
|
|||||||
//@description Discards a group call. Requires groupCall.can_be_managed @group_call_id Group call identifier
|
//@description Discards a group call. Requires groupCall.can_be_managed @group_call_id Group call identifier
|
||||||
discardGroupCall group_call_id:int32 = Ok;
|
discardGroupCall group_call_id:int32 = Ok;
|
||||||
|
|
||||||
|
//@description Returns a file with a segment of a group call stream in a modified OGG format
|
||||||
|
//@group_call_id Group call identifier
|
||||||
|
//@time_offset Point in time when the stream segment begins; Unix timestamp in milliseconds
|
||||||
|
//@scale Segment duration scale; 0-1. Segment's duration is 1000/(2**scale) milliseconds
|
||||||
|
getGroupCallStreamSegment group_call_id:int32 time_offset:int53 scale:int32 = FilePart;
|
||||||
|
|
||||||
|
|
||||||
//@description Changes the block state of a message sender. Currently, only users and supergroup chats can be blocked @sender Message Sender @is_blocked New value of is_blocked
|
//@description Changes the block state of a message sender. Currently, only users and supergroup chats can be blocked @sender Message Sender @is_blocked New value of is_blocked
|
||||||
toggleMessageSenderIsBlocked sender:MessageSender is_blocked:Bool = Ok;
|
toggleMessageSenderIsBlocked sender:MessageSender is_blocked:Bool = Ok;
|
||||||
@ -4826,15 +4945,16 @@ closeSecretChat secret_chat_id:int32 = Ok;
|
|||||||
getChatEventLog chat_id:int53 query:string from_event_id:int64 limit:int32 filters:chatEventLogFilters user_ids:vector<int32> = ChatEvents;
|
getChatEventLog chat_id:int53 query:string from_event_id:int64 limit:int32 filters:chatEventLogFilters user_ids:vector<int32> = ChatEvents;
|
||||||
|
|
||||||
|
|
||||||
//@description Returns an invoice payment form. This method should be called when the user presses inlineKeyboardButtonBuy @chat_id Chat identifier of the Invoice message @message_id Message identifier
|
//@description Returns an invoice payment form. This method should be called when the user presses inlineKeyboardButtonBuy @chat_id Chat identifier of the Invoice message @message_id Message identifier @theme Preferred payment form theme
|
||||||
getPaymentForm chat_id:int53 message_id:int53 = PaymentForm;
|
getPaymentForm chat_id:int53 message_id:int53 theme:paymentFormTheme = PaymentForm;
|
||||||
|
|
||||||
//@description Validates the order information provided by a user and returns the available shipping options for a flexible invoice @chat_id Chat identifier of the Invoice message @message_id Message identifier @order_info The order information, provided by the user @allow_save True, if the order information can be saved
|
//@description Validates the order information provided by a user and returns the available shipping options for a flexible invoice @chat_id Chat identifier of the Invoice message @message_id Message identifier @order_info The order information, provided by the user @allow_save True, if the order information can be saved
|
||||||
validateOrderInfo chat_id:int53 message_id:int53 order_info:orderInfo allow_save:Bool = ValidatedOrderInfo;
|
validateOrderInfo chat_id:int53 message_id:int53 order_info:orderInfo allow_save:Bool = ValidatedOrderInfo;
|
||||||
|
|
||||||
//@description Sends a filled-out payment form to the bot for final verification @chat_id Chat identifier of the Invoice message @message_id Message identifier @order_info_id Identifier returned by ValidateOrderInfo, or an empty string @shipping_option_id Identifier of a chosen shipping option, if applicable
|
//@description Sends a filled-out payment form to the bot for final verification @chat_id Chat identifier of the Invoice message @message_id Message identifier
|
||||||
//@credentials The credentials chosen by user for payment
|
//@payment_form_id Payment form identifier returned by getPaymentForm @order_info_id Identifier returned by validateOrderInfo, or an empty string @shipping_option_id Identifier of a chosen shipping option, if applicable
|
||||||
sendPaymentForm chat_id:int53 message_id:int53 order_info_id:string shipping_option_id:string credentials:InputCredentials = PaymentResult;
|
//@credentials The credentials chosen by user for payment @tip_amount Chosen by the user amount of tip in the smallest units of the currency
|
||||||
|
sendPaymentForm chat_id:int53 message_id:int53 payment_form_id:int64 order_info_id:string shipping_option_id:string credentials:InputCredentials tip_amount:int53 = PaymentResult;
|
||||||
|
|
||||||
//@description Returns information about a successful payment @chat_id Chat identifier of the PaymentSuccessful message @message_id Message identifier
|
//@description Returns information about a successful payment @chat_id Chat identifier of the PaymentSuccessful message @message_id Message identifier
|
||||||
getPaymentReceipt chat_id:int53 message_id:int53 = PaymentReceipt;
|
getPaymentReceipt chat_id:int53 message_id:int53 = PaymentReceipt;
|
||||||
|
@ -55,7 +55,7 @@ inputMediaVenue#c13d1c11 geo_point:InputGeoPoint title:string address:string pro
|
|||||||
inputMediaPhotoExternal#e5bbfe1a flags:# url:string ttl_seconds:flags.0?int = InputMedia;
|
inputMediaPhotoExternal#e5bbfe1a flags:# url:string ttl_seconds:flags.0?int = InputMedia;
|
||||||
inputMediaDocumentExternal#fb52dc99 flags:# url:string ttl_seconds:flags.0?int = InputMedia;
|
inputMediaDocumentExternal#fb52dc99 flags:# url:string ttl_seconds:flags.0?int = InputMedia;
|
||||||
inputMediaGame#d33f43f3 id:InputGame = InputMedia;
|
inputMediaGame#d33f43f3 id:InputGame = InputMedia;
|
||||||
inputMediaInvoice#f4e096c3 flags:# title:string description:string photo:flags.0?InputWebDocument invoice:Invoice payload:bytes provider:string provider_data:DataJSON start_param:string = InputMedia;
|
inputMediaInvoice#d9799874 flags:# title:string description:string photo:flags.0?InputWebDocument invoice:Invoice payload:bytes provider:string provider_data:DataJSON start_param:flags.1?string = InputMedia;
|
||||||
inputMediaGeoLive#971fa843 flags:# stopped:flags.0?true geo_point:InputGeoPoint heading:flags.2?int period:flags.1?int proximity_notification_radius:flags.3?int = InputMedia;
|
inputMediaGeoLive#971fa843 flags:# stopped:flags.0?true geo_point:InputGeoPoint heading:flags.2?int period:flags.1?int proximity_notification_radius:flags.3?int = InputMedia;
|
||||||
inputMediaPoll#f94e5f1 flags:# poll:Poll correct_answers:flags.0?Vector<bytes> solution:flags.1?string solution_entities:flags.1?Vector<MessageEntity> = InputMedia;
|
inputMediaPoll#f94e5f1 flags:# poll:Poll correct_answers:flags.0?Vector<bytes> solution:flags.1?string solution_entities:flags.1?Vector<MessageEntity> = InputMedia;
|
||||||
inputMediaDice#e66fbf7b emoticon:string = InputMedia;
|
inputMediaDice#e66fbf7b emoticon:string = InputMedia;
|
||||||
@ -79,6 +79,7 @@ inputPhotoFileLocation#40181ffe id:long access_hash:long file_reference:bytes th
|
|||||||
inputPhotoLegacyFileLocation#d83466f3 id:long access_hash:long file_reference:bytes volume_id:long local_id:int secret:long = InputFileLocation;
|
inputPhotoLegacyFileLocation#d83466f3 id:long access_hash:long file_reference:bytes volume_id:long local_id:int secret:long = InputFileLocation;
|
||||||
inputPeerPhotoFileLocation#27d69997 flags:# big:flags.0?true peer:InputPeer volume_id:long local_id:int = InputFileLocation;
|
inputPeerPhotoFileLocation#27d69997 flags:# big:flags.0?true peer:InputPeer volume_id:long local_id:int = InputFileLocation;
|
||||||
inputStickerSetThumb#dbaeae9 stickerset:InputStickerSet volume_id:long local_id:int = InputFileLocation;
|
inputStickerSetThumb#dbaeae9 stickerset:InputStickerSet volume_id:long local_id:int = InputFileLocation;
|
||||||
|
inputGroupCallStream#bba51639 call:InputGroupCall time_ms:long scale:int = InputFileLocation;
|
||||||
|
|
||||||
peerUser#9db1bc6d user_id:int = Peer;
|
peerUser#9db1bc6d user_id:int = Peer;
|
||||||
peerChat#bad0e5bb chat_id:int = Peer;
|
peerChat#bad0e5bb chat_id:int = Peer;
|
||||||
@ -99,7 +100,7 @@ userEmpty#200250ba id:int = User;
|
|||||||
user#938458c1 flags:# self:flags.10?true contact:flags.11?true mutual_contact:flags.12?true deleted:flags.13?true bot:flags.14?true bot_chat_history:flags.15?true bot_nochats:flags.16?true verified:flags.17?true restricted:flags.18?true min:flags.20?true bot_inline_geo:flags.21?true support:flags.23?true scam:flags.24?true apply_min_photo:flags.25?true fake:flags.26?true id:int access_hash:flags.0?long first_name:flags.1?string last_name:flags.2?string username:flags.3?string phone:flags.4?string photo:flags.5?UserProfilePhoto status:flags.6?UserStatus bot_info_version:flags.14?int restriction_reason:flags.18?Vector<RestrictionReason> bot_inline_placeholder:flags.19?string lang_code:flags.22?string = User;
|
user#938458c1 flags:# self:flags.10?true contact:flags.11?true mutual_contact:flags.12?true deleted:flags.13?true bot:flags.14?true bot_chat_history:flags.15?true bot_nochats:flags.16?true verified:flags.17?true restricted:flags.18?true min:flags.20?true bot_inline_geo:flags.21?true support:flags.23?true scam:flags.24?true apply_min_photo:flags.25?true fake:flags.26?true id:int access_hash:flags.0?long first_name:flags.1?string last_name:flags.2?string username:flags.3?string phone:flags.4?string photo:flags.5?UserProfilePhoto status:flags.6?UserStatus bot_info_version:flags.14?int restriction_reason:flags.18?Vector<RestrictionReason> bot_inline_placeholder:flags.19?string lang_code:flags.22?string = User;
|
||||||
|
|
||||||
userProfilePhotoEmpty#4f11bae1 = UserProfilePhoto;
|
userProfilePhotoEmpty#4f11bae1 = UserProfilePhoto;
|
||||||
userProfilePhoto#69d3ab26 flags:# has_video:flags.0?true photo_id:long photo_small:FileLocation photo_big:FileLocation dc_id:int = UserProfilePhoto;
|
userProfilePhoto#cc656077 flags:# has_video:flags.0?true photo_id:long photo_small:FileLocation photo_big:FileLocation stripped_thumb:flags.1?bytes dc_id:int = UserProfilePhoto;
|
||||||
|
|
||||||
userStatusEmpty#9d05049 = UserStatus;
|
userStatusEmpty#9d05049 = UserStatus;
|
||||||
userStatusOnline#edb93949 expires:int = UserStatus;
|
userStatusOnline#edb93949 expires:int = UserStatus;
|
||||||
@ -114,8 +115,8 @@ chatForbidden#7328bdb id:int title:string = Chat;
|
|||||||
channel#d31a961e flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true has_geo:flags.21?true slowmode_enabled:flags.22?true call_active:flags.23?true call_not_empty:flags.24?true fake:flags.25?true gigagroup:flags.26?true id:int access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int version:int restriction_reason:flags.9?Vector<RestrictionReason> admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int = Chat;
|
channel#d31a961e flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true has_geo:flags.21?true slowmode_enabled:flags.22?true call_active:flags.23?true call_not_empty:flags.24?true fake:flags.25?true gigagroup:flags.26?true id:int access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int version:int restriction_reason:flags.9?Vector<RestrictionReason> admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int = Chat;
|
||||||
channelForbidden#289da732 flags:# broadcast:flags.5?true megagroup:flags.8?true id:int access_hash:long title:string until_date:flags.16?int = Chat;
|
channelForbidden#289da732 flags:# broadcast:flags.5?true megagroup:flags.8?true id:int access_hash:long title:string until_date:flags.16?int = Chat;
|
||||||
|
|
||||||
chatFull#f06c4018 flags:# can_set_username:flags.7?true has_scheduled:flags.8?true id:int about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:flags.13?ExportedChatInvite bot_info:flags.3?Vector<BotInfo> pinned_msg_id:flags.6?int folder_id:flags.11?int call:flags.12?InputGroupCall ttl_period:flags.14?int = ChatFull;
|
chatFull#8a1e2983 flags:# can_set_username:flags.7?true has_scheduled:flags.8?true id:int about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:flags.13?ExportedChatInvite bot_info:flags.3?Vector<BotInfo> pinned_msg_id:flags.6?int folder_id:flags.11?int call:flags.12?InputGroupCall ttl_period:flags.14?int groupcall_default_join_as:flags.15?Peer = ChatFull;
|
||||||
channelFull#2548c037 flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true id:int about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:flags.23?ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?int migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?int location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector<string> = ChatFull;
|
channelFull#548c3f93 flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true id:int about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:flags.23?ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?int migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?int location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector<string> groupcall_default_join_as:flags.26?Peer = ChatFull;
|
||||||
|
|
||||||
chatParticipant#c8d7493e user_id:int inviter_id:int date:int = ChatParticipant;
|
chatParticipant#c8d7493e user_id:int inviter_id:int date:int = ChatParticipant;
|
||||||
chatParticipantCreator#da13538a user_id:int = ChatParticipant;
|
chatParticipantCreator#da13538a user_id:int = ChatParticipant;
|
||||||
@ -125,7 +126,7 @@ chatParticipantsForbidden#fc900c2b flags:# chat_id:int self_participant:flags.0?
|
|||||||
chatParticipants#3f460fed chat_id:int participants:Vector<ChatParticipant> version:int = ChatParticipants;
|
chatParticipants#3f460fed chat_id:int participants:Vector<ChatParticipant> version:int = ChatParticipants;
|
||||||
|
|
||||||
chatPhotoEmpty#37c1011c = ChatPhoto;
|
chatPhotoEmpty#37c1011c = ChatPhoto;
|
||||||
chatPhoto#d20b9f3c flags:# has_video:flags.0?true photo_small:FileLocation photo_big:FileLocation dc_id:int = ChatPhoto;
|
chatPhoto#4790ee05 flags:# has_video:flags.0?true photo_small:FileLocation photo_big:FileLocation stripped_thumb:flags.1?bytes dc_id:int = ChatPhoto;
|
||||||
|
|
||||||
messageEmpty#90a6ca84 flags:# id:int peer_id:flags.0?Peer = Message;
|
messageEmpty#90a6ca84 flags:# id:int peer_id:flags.0?Peer = Message;
|
||||||
message#bce383d2 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true legacy:flags.19?true edit_hide:flags.21?true pinned:flags.24?true id:int from_id:flags.8?Peer peer_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?int reply_to:flags.3?MessageReplyHeader date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> views:flags.10?int forwards:flags.10?int replies:flags.23?MessageReplies edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long restriction_reason:flags.22?Vector<RestrictionReason> ttl_period:flags.25?int = Message;
|
message#bce383d2 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true legacy:flags.19?true edit_hide:flags.21?true pinned:flags.24?true id:int from_id:flags.8?Peer peer_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?int reply_to:flags.3?MessageReplyHeader date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> views:flags.10?int forwards:flags.10?int replies:flags.23?MessageReplies edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long restriction_reason:flags.22?Vector<RestrictionReason> ttl_period:flags.25?int = Message;
|
||||||
@ -172,6 +173,7 @@ messageActionGeoProximityReached#98e0d697 from_id:Peer to_id:Peer distance:int =
|
|||||||
messageActionGroupCall#7a0d7f42 flags:# call:InputGroupCall duration:flags.0?int = MessageAction;
|
messageActionGroupCall#7a0d7f42 flags:# call:InputGroupCall duration:flags.0?int = MessageAction;
|
||||||
messageActionInviteToGroupCall#76b9f11a call:InputGroupCall users:Vector<int> = MessageAction;
|
messageActionInviteToGroupCall#76b9f11a call:InputGroupCall users:Vector<int> = MessageAction;
|
||||||
messageActionSetMessagesTTL#aa1afbfd period:int = MessageAction;
|
messageActionSetMessagesTTL#aa1afbfd period:int = MessageAction;
|
||||||
|
messageActionGroupCallScheduled#b3a07661 call:InputGroupCall schedule_date:int = MessageAction;
|
||||||
|
|
||||||
dialog#2c171f72 flags:# pinned:flags.2?true unread_mark:flags.3?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int notify_settings:PeerNotifySettings pts:flags.0?int draft:flags.1?DraftMessage folder_id:flags.4?int = Dialog;
|
dialog#2c171f72 flags:# pinned:flags.2?true unread_mark:flags.3?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int notify_settings:PeerNotifySettings pts:flags.0?int draft:flags.1?DraftMessage folder_id:flags.4?int = Dialog;
|
||||||
dialogFolder#71bd134c flags:# pinned:flags.2?true folder:Folder peer:Peer top_message:int unread_muted_peers_count:int unread_unmuted_peers_count:int unread_muted_messages_count:int unread_unmuted_messages_count:int = Dialog;
|
dialogFolder#71bd134c flags:# pinned:flags.2?true folder:Folder peer:Peer top_message:int unread_muted_peers_count:int unread_unmuted_peers_count:int unread_muted_messages_count:int unread_unmuted_messages_count:int = Dialog;
|
||||||
@ -273,7 +275,7 @@ updateNewMessage#1f2b0afd message:Message pts:int pts_count:int = Update;
|
|||||||
updateMessageID#4e90bfd6 id:int random_id:long = Update;
|
updateMessageID#4e90bfd6 id:int random_id:long = Update;
|
||||||
updateDeleteMessages#a20db0e5 messages:Vector<int> pts:int pts_count:int = Update;
|
updateDeleteMessages#a20db0e5 messages:Vector<int> pts:int pts_count:int = Update;
|
||||||
updateUserTyping#5c486927 user_id:int action:SendMessageAction = Update;
|
updateUserTyping#5c486927 user_id:int action:SendMessageAction = Update;
|
||||||
updateChatUserTyping#9a65ea1f chat_id:int user_id:int action:SendMessageAction = Update;
|
updateChatUserTyping#86cadb6c chat_id:int from_id:Peer action:SendMessageAction = Update;
|
||||||
updateChatParticipants#7761198 participants:ChatParticipants = Update;
|
updateChatParticipants#7761198 participants:ChatParticipants = Update;
|
||||||
updateUserStatus#1bfbd823 user_id:int status:UserStatus = Update;
|
updateUserStatus#1bfbd823 user_id:int status:UserStatus = Update;
|
||||||
updateUserName#a7332b73 user_id:int first_name:string last_name:string username:string = Update;
|
updateUserName#a7332b73 user_id:int first_name:string last_name:string username:string = Update;
|
||||||
@ -350,7 +352,7 @@ updateChannelMessageForwards#6e8a84df channel_id:int id:int forwards:int = Updat
|
|||||||
updateReadChannelDiscussionInbox#1cc7de54 flags:# channel_id:int top_msg_id:int read_max_id:int broadcast_id:flags.0?int broadcast_post:flags.0?int = Update;
|
updateReadChannelDiscussionInbox#1cc7de54 flags:# channel_id:int top_msg_id:int read_max_id:int broadcast_id:flags.0?int broadcast_post:flags.0?int = Update;
|
||||||
updateReadChannelDiscussionOutbox#4638a26c channel_id:int top_msg_id:int read_max_id:int = Update;
|
updateReadChannelDiscussionOutbox#4638a26c channel_id:int top_msg_id:int read_max_id:int = Update;
|
||||||
updatePeerBlocked#246a4b22 peer_id:Peer blocked:Bool = Update;
|
updatePeerBlocked#246a4b22 peer_id:Peer blocked:Bool = Update;
|
||||||
updateChannelUserTyping#ff2abe9f flags:# channel_id:int top_msg_id:flags.0?int user_id:int action:SendMessageAction = Update;
|
updateChannelUserTyping#6b171718 flags:# channel_id:int top_msg_id:flags.0?int from_id:Peer action:SendMessageAction = Update;
|
||||||
updatePinnedMessages#ed85eab5 flags:# pinned:flags.0?true peer:Peer messages:Vector<int> pts:int pts_count:int = Update;
|
updatePinnedMessages#ed85eab5 flags:# pinned:flags.0?true peer:Peer messages:Vector<int> pts:int pts_count:int = Update;
|
||||||
updatePinnedChannelMessages#8588878b flags:# pinned:flags.0?true channel_id:int messages:Vector<int> pts:int pts_count:int = Update;
|
updatePinnedChannelMessages#8588878b flags:# pinned:flags.0?true channel_id:int messages:Vector<int> pts:int pts_count:int = Update;
|
||||||
updateChat#1330a196 chat_id:int = Update;
|
updateChat#1330a196 chat_id:int = Update;
|
||||||
@ -540,7 +542,7 @@ inputStickerSetShortName#861cc8a0 short_name:string = InputStickerSet;
|
|||||||
inputStickerSetAnimatedEmoji#28703c8 = InputStickerSet;
|
inputStickerSetAnimatedEmoji#28703c8 = InputStickerSet;
|
||||||
inputStickerSetDice#e67f520e emoticon:string = InputStickerSet;
|
inputStickerSetDice#e67f520e emoticon:string = InputStickerSet;
|
||||||
|
|
||||||
stickerSet#40e237a8 flags:# archived:flags.1?true official:flags.2?true masks:flags.3?true animated:flags.5?true installed_date:flags.0?int id:long access_hash:long title:string short_name:string thumbs:flags.4?Vector<PhotoSize> thumb_dc_id:flags.4?int count:int hash:int = StickerSet;
|
stickerSet#d7df217a flags:# archived:flags.1?true official:flags.2?true masks:flags.3?true animated:flags.5?true installed_date:flags.0?int id:long access_hash:long title:string short_name:string thumbs:flags.4?Vector<PhotoSize> thumb_dc_id:flags.4?int thumb_version:flags.4?int count:int hash:int = StickerSet;
|
||||||
|
|
||||||
messages.stickerSet#b60a24a6 set:StickerSet packs:Vector<StickerPack> documents:Vector<Document> = messages.StickerSet;
|
messages.stickerSet#b60a24a6 set:StickerSet packs:Vector<StickerPack> documents:Vector<Document> = messages.StickerSet;
|
||||||
|
|
||||||
@ -606,8 +608,8 @@ channelParticipant#15ebac1d user_id:int date:int = ChannelParticipant;
|
|||||||
channelParticipantSelf#a3289a6d user_id:int inviter_id:int date:int = ChannelParticipant;
|
channelParticipantSelf#a3289a6d user_id:int inviter_id:int date:int = ChannelParticipant;
|
||||||
channelParticipantCreator#447dca4b flags:# user_id:int admin_rights:ChatAdminRights rank:flags.0?string = ChannelParticipant;
|
channelParticipantCreator#447dca4b flags:# user_id:int admin_rights:ChatAdminRights rank:flags.0?string = ChannelParticipant;
|
||||||
channelParticipantAdmin#ccbebbaf flags:# can_edit:flags.0?true self:flags.1?true user_id:int inviter_id:flags.1?int promoted_by:int date:int admin_rights:ChatAdminRights rank:flags.2?string = ChannelParticipant;
|
channelParticipantAdmin#ccbebbaf flags:# can_edit:flags.0?true self:flags.1?true user_id:int inviter_id:flags.1?int promoted_by:int date:int admin_rights:ChatAdminRights rank:flags.2?string = ChannelParticipant;
|
||||||
channelParticipantBanned#1c0facaf flags:# left:flags.0?true user_id:int kicked_by:int date:int banned_rights:ChatBannedRights = ChannelParticipant;
|
channelParticipantBanned#50a1dfd6 flags:# left:flags.0?true peer:Peer kicked_by:int date:int banned_rights:ChatBannedRights = ChannelParticipant;
|
||||||
channelParticipantLeft#c3c6796b user_id:int = ChannelParticipant;
|
channelParticipantLeft#1b03f006 peer:Peer = ChannelParticipant;
|
||||||
|
|
||||||
channelParticipantsRecent#de3f3c79 = ChannelParticipantsFilter;
|
channelParticipantsRecent#de3f3c79 = ChannelParticipantsFilter;
|
||||||
channelParticipantsAdmins#b4608969 = ChannelParticipantsFilter;
|
channelParticipantsAdmins#b4608969 = ChannelParticipantsFilter;
|
||||||
@ -618,10 +620,10 @@ channelParticipantsSearch#656ac4b q:string = ChannelParticipantsFilter;
|
|||||||
channelParticipantsContacts#bb6ae88d q:string = ChannelParticipantsFilter;
|
channelParticipantsContacts#bb6ae88d q:string = ChannelParticipantsFilter;
|
||||||
channelParticipantsMentions#e04b5ceb flags:# q:flags.0?string top_msg_id:flags.1?int = ChannelParticipantsFilter;
|
channelParticipantsMentions#e04b5ceb flags:# q:flags.0?string top_msg_id:flags.1?int = ChannelParticipantsFilter;
|
||||||
|
|
||||||
channels.channelParticipants#f56ee2a8 count:int participants:Vector<ChannelParticipant> users:Vector<User> = channels.ChannelParticipants;
|
channels.channelParticipants#9ab0feaf count:int participants:Vector<ChannelParticipant> chats:Vector<Chat> users:Vector<User> = channels.ChannelParticipants;
|
||||||
channels.channelParticipantsNotModified#f0173fe9 = channels.ChannelParticipants;
|
channels.channelParticipantsNotModified#f0173fe9 = channels.ChannelParticipants;
|
||||||
|
|
||||||
channels.channelParticipant#d0d9b163 participant:ChannelParticipant users:Vector<User> = channels.ChannelParticipant;
|
channels.channelParticipant#dfb80317 participant:ChannelParticipant chats:Vector<Chat> users:Vector<User> = channels.ChannelParticipant;
|
||||||
|
|
||||||
help.termsOfService#780a0310 flags:# popup:flags.0?true id:DataJSON text:string entities:Vector<MessageEntity> min_age_confirm:flags.1?int = help.TermsOfService;
|
help.termsOfService#780a0310 flags:# popup:flags.0?true id:DataJSON text:string entities:Vector<MessageEntity> min_age_confirm:flags.1?int = help.TermsOfService;
|
||||||
|
|
||||||
@ -634,6 +636,7 @@ inputBotInlineMessageMediaGeo#96929a85 flags:# geo_point:InputGeoPoint heading:f
|
|||||||
inputBotInlineMessageMediaVenue#417bbf11 flags:# geo_point:InputGeoPoint title:string address:string provider:string venue_id:string venue_type:string reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
|
inputBotInlineMessageMediaVenue#417bbf11 flags:# geo_point:InputGeoPoint title:string address:string provider:string venue_id:string venue_type:string reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
|
||||||
inputBotInlineMessageMediaContact#a6edbffd flags:# phone_number:string first_name:string last_name:string vcard:string reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
|
inputBotInlineMessageMediaContact#a6edbffd flags:# phone_number:string first_name:string last_name:string vcard:string reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
|
||||||
inputBotInlineMessageGame#4b425864 flags:# reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
|
inputBotInlineMessageGame#4b425864 flags:# reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
|
||||||
|
inputBotInlineMessageMediaInvoice#d7e78225 flags:# title:string description:string photo:flags.0?InputWebDocument invoice:Invoice payload:bytes provider:string provider_data:DataJSON reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
|
||||||
|
|
||||||
inputBotInlineResult#88bf9319 flags:# id:string type:string title:flags.1?string description:flags.2?string url:flags.3?string thumb:flags.4?InputWebDocument content:flags.5?InputWebDocument send_message:InputBotInlineMessage = InputBotInlineResult;
|
inputBotInlineResult#88bf9319 flags:# id:string type:string title:flags.1?string description:flags.2?string url:flags.3?string thumb:flags.4?InputWebDocument content:flags.5?InputWebDocument send_message:InputBotInlineMessage = InputBotInlineResult;
|
||||||
inputBotInlineResultPhoto#a8d864a7 id:string type:string photo:InputPhoto send_message:InputBotInlineMessage = InputBotInlineResult;
|
inputBotInlineResultPhoto#a8d864a7 id:string type:string photo:InputPhoto send_message:InputBotInlineMessage = InputBotInlineResult;
|
||||||
@ -645,6 +648,7 @@ botInlineMessageText#8c7f65e2 flags:# no_webpage:flags.0?true message:string ent
|
|||||||
botInlineMessageMediaGeo#51846fd flags:# geo:GeoPoint heading:flags.0?int period:flags.1?int proximity_notification_radius:flags.3?int reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
|
botInlineMessageMediaGeo#51846fd flags:# geo:GeoPoint heading:flags.0?int period:flags.1?int proximity_notification_radius:flags.3?int reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
|
||||||
botInlineMessageMediaVenue#8a86659c flags:# geo:GeoPoint title:string address:string provider:string venue_id:string venue_type:string reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
|
botInlineMessageMediaVenue#8a86659c flags:# geo:GeoPoint title:string address:string provider:string venue_id:string venue_type:string reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
|
||||||
botInlineMessageMediaContact#18d1cdc2 flags:# phone_number:string first_name:string last_name:string vcard:string reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
|
botInlineMessageMediaContact#18d1cdc2 flags:# phone_number:string first_name:string last_name:string vcard:string reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
|
||||||
|
botInlineMessageMediaInvoice#354a9b09 flags:# shipping_address_requested:flags.1?true test:flags.3?true title:string description:string photo:flags.0?WebDocument currency:string total_amount:long reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
|
||||||
|
|
||||||
botInlineResult#11965f3a flags:# id:string type:string title:flags.1?string description:flags.2?string url:flags.3?string thumb:flags.4?WebDocument content:flags.5?WebDocument send_message:BotInlineMessage = BotInlineResult;
|
botInlineResult#11965f3a flags:# id:string type:string title:flags.1?string description:flags.2?string url:flags.3?string thumb:flags.4?WebDocument content:flags.5?WebDocument send_message:BotInlineMessage = BotInlineResult;
|
||||||
botInlineMediaResult#17db940b flags:# id:string type:string photo:flags.0?Photo document:flags.1?Document title:flags.2?string description:flags.3?string send_message:BotInlineMessage = BotInlineResult;
|
botInlineMediaResult#17db940b flags:# id:string type:string photo:flags.0?Photo document:flags.1?Document title:flags.2?string description:flags.3?string send_message:BotInlineMessage = BotInlineResult;
|
||||||
@ -778,7 +782,7 @@ dataJSON#7d748d04 data:string = DataJSON;
|
|||||||
|
|
||||||
labeledPrice#cb296bf8 label:string amount:long = LabeledPrice;
|
labeledPrice#cb296bf8 label:string amount:long = LabeledPrice;
|
||||||
|
|
||||||
invoice#c30aa358 flags:# test:flags.0?true name_requested:flags.1?true phone_requested:flags.2?true email_requested:flags.3?true shipping_address_requested:flags.4?true flexible:flags.5?true phone_to_provider:flags.6?true email_to_provider:flags.7?true currency:string prices:Vector<LabeledPrice> = Invoice;
|
invoice#cd886e0 flags:# test:flags.0?true name_requested:flags.1?true phone_requested:flags.2?true email_requested:flags.3?true shipping_address_requested:flags.4?true flexible:flags.5?true phone_to_provider:flags.6?true email_to_provider:flags.7?true currency:string prices:Vector<LabeledPrice> max_tip_amount:flags.8?long suggested_tip_amounts:flags.8?Vector<long> = Invoice;
|
||||||
|
|
||||||
paymentCharge#ea02c27e id:string provider_charge_id:string = PaymentCharge;
|
paymentCharge#ea02c27e id:string provider_charge_id:string = PaymentCharge;
|
||||||
|
|
||||||
@ -798,14 +802,14 @@ inputWebFileGeoPointLocation#9f2221c9 geo_point:InputGeoPoint access_hash:long w
|
|||||||
|
|
||||||
upload.webFile#21e753bc size:int mime_type:string file_type:storage.FileType mtime:int bytes:bytes = upload.WebFile;
|
upload.webFile#21e753bc size:int mime_type:string file_type:storage.FileType mtime:int bytes:bytes = upload.WebFile;
|
||||||
|
|
||||||
payments.paymentForm#3f56aea3 flags:# can_save_credentials:flags.2?true password_missing:flags.3?true bot_id:int invoice:Invoice provider_id:int url:string native_provider:flags.4?string native_params:flags.4?DataJSON saved_info:flags.0?PaymentRequestedInfo saved_credentials:flags.1?PaymentSavedCredentials users:Vector<User> = payments.PaymentForm;
|
payments.paymentForm#8d0b2415 flags:# can_save_credentials:flags.2?true password_missing:flags.3?true form_id:long bot_id:int invoice:Invoice provider_id:int url:string native_provider:flags.4?string native_params:flags.4?DataJSON saved_info:flags.0?PaymentRequestedInfo saved_credentials:flags.1?PaymentSavedCredentials users:Vector<User> = payments.PaymentForm;
|
||||||
|
|
||||||
payments.validatedRequestedInfo#d1451883 flags:# id:flags.0?string shipping_options:flags.1?Vector<ShippingOption> = payments.ValidatedRequestedInfo;
|
payments.validatedRequestedInfo#d1451883 flags:# id:flags.0?string shipping_options:flags.1?Vector<ShippingOption> = payments.ValidatedRequestedInfo;
|
||||||
|
|
||||||
payments.paymentResult#4e5f810d updates:Updates = payments.PaymentResult;
|
payments.paymentResult#4e5f810d updates:Updates = payments.PaymentResult;
|
||||||
payments.paymentVerificationNeeded#d8411139 url:string = payments.PaymentResult;
|
payments.paymentVerificationNeeded#d8411139 url:string = payments.PaymentResult;
|
||||||
|
|
||||||
payments.paymentReceipt#500911e1 flags:# date:int bot_id:int invoice:Invoice provider_id:int info:flags.0?PaymentRequestedInfo shipping:flags.1?ShippingOption currency:string total_amount:long credentials_title:string users:Vector<User> = payments.PaymentReceipt;
|
payments.paymentReceipt#10b555d0 flags:# date:int bot_id:int provider_id:int title:string description:string photo:flags.2?WebDocument invoice:Invoice info:flags.0?PaymentRequestedInfo shipping:flags.1?ShippingOption tip_amount:flags.3?long currency:string total_amount:long credentials_title:string users:Vector<User> = payments.PaymentReceipt;
|
||||||
|
|
||||||
payments.savedInfo#fb8fe43c flags:# has_saved_credentials:flags.1?true saved_info:flags.0?PaymentRequestedInfo = payments.SavedInfo;
|
payments.savedInfo#fb8fe43c flags:# has_saved_credentials:flags.1?true saved_info:flags.0?PaymentRequestedInfo = payments.SavedInfo;
|
||||||
|
|
||||||
@ -1189,15 +1193,15 @@ peerBlocked#e8fd8014 peer_id:Peer date:int = PeerBlocked;
|
|||||||
stats.messageStats#8999f295 views_graph:StatsGraph = stats.MessageStats;
|
stats.messageStats#8999f295 views_graph:StatsGraph = stats.MessageStats;
|
||||||
|
|
||||||
groupCallDiscarded#7780bcb4 id:long access_hash:long duration:int = GroupCall;
|
groupCallDiscarded#7780bcb4 id:long access_hash:long duration:int = GroupCall;
|
||||||
groupCall#55903081 flags:# join_muted:flags.1?true can_change_join_muted:flags.2?true id:long access_hash:long participants_count:int params:flags.0?DataJSON version:int = GroupCall;
|
groupCall#c95c6654 flags:# join_muted:flags.1?true can_change_join_muted:flags.2?true join_date_asc:flags.6?true schedule_start_subscribed:flags.8?true id:long access_hash:long participants_count:int params:flags.0?DataJSON title:flags.3?string stream_dc_id:flags.4?int record_start_date:flags.5?int schedule_date:flags.7?int version:int = GroupCall;
|
||||||
|
|
||||||
inputGroupCall#d8aa840f id:long access_hash:long = InputGroupCall;
|
inputGroupCall#d8aa840f id:long access_hash:long = InputGroupCall;
|
||||||
|
|
||||||
groupCallParticipant#64c62a15 flags:# muted:flags.0?true left:flags.1?true can_self_unmute:flags.2?true just_joined:flags.4?true versioned:flags.5?true min:flags.8?true muted_by_you:flags.9?true volume_by_admin:flags.10?true user_id:int date:int active_date:flags.3?int source:int volume:flags.7?int = GroupCallParticipant;
|
groupCallParticipant#b96b25ee flags:# muted:flags.0?true left:flags.1?true can_self_unmute:flags.2?true just_joined:flags.4?true versioned:flags.5?true min:flags.8?true muted_by_you:flags.9?true volume_by_admin:flags.10?true self:flags.12?true peer:Peer date:int active_date:flags.3?int source:int volume:flags.7?int about:flags.11?string raise_hand_rating:flags.13?long params:flags.6?DataJSON = GroupCallParticipant;
|
||||||
|
|
||||||
phone.groupCall#66ab0bfc call:GroupCall participants:Vector<GroupCallParticipant> participants_next_offset:string users:Vector<User> = phone.GroupCall;
|
phone.groupCall#9e727aad call:GroupCall participants:Vector<GroupCallParticipant> participants_next_offset:string chats:Vector<Chat> users:Vector<User> = phone.GroupCall;
|
||||||
|
|
||||||
phone.groupParticipants#9cfeb92d count:int participants:Vector<GroupCallParticipant> next_offset:string users:Vector<User> version:int = phone.GroupParticipants;
|
phone.groupParticipants#f47751b6 count:int participants:Vector<GroupCallParticipant> next_offset:string chats:Vector<Chat> users:Vector<User> version:int = phone.GroupParticipants;
|
||||||
|
|
||||||
inlineQueryPeerTypeSameBotPM#3081ed9d = InlineQueryPeerType;
|
inlineQueryPeerTypeSameBotPM#3081ed9d = InlineQueryPeerType;
|
||||||
inlineQueryPeerTypePM#833c0fac = InlineQueryPeerType;
|
inlineQueryPeerTypePM#833c0fac = InlineQueryPeerType;
|
||||||
@ -1226,6 +1230,10 @@ messages.chatAdminsWithInvites#b69b72d7 admins:Vector<ChatAdminWithInvites> user
|
|||||||
|
|
||||||
messages.checkedHistoryImportPeer#a24de717 confirm_text:string = messages.CheckedHistoryImportPeer;
|
messages.checkedHistoryImportPeer#a24de717 confirm_text:string = messages.CheckedHistoryImportPeer;
|
||||||
|
|
||||||
|
phone.joinAsPeers#afe5623f peers:Vector<Peer> chats:Vector<Chat> users:Vector<User> = phone.JoinAsPeers;
|
||||||
|
|
||||||
|
phone.exportedGroupCallInvite#204bd158 link:string = phone.ExportedGroupCallInvite;
|
||||||
|
|
||||||
---functions---
|
---functions---
|
||||||
|
|
||||||
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
|
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
|
||||||
@ -1458,8 +1466,8 @@ messages.getEmojiKeywordsDifference#1508b6af lang_code:string from_version:int =
|
|||||||
messages.getEmojiKeywordsLanguages#4e9963b2 lang_codes:Vector<string> = Vector<EmojiLanguage>;
|
messages.getEmojiKeywordsLanguages#4e9963b2 lang_codes:Vector<string> = Vector<EmojiLanguage>;
|
||||||
messages.getEmojiURL#d5b10c26 lang_code:string = EmojiURL;
|
messages.getEmojiURL#d5b10c26 lang_code:string = EmojiURL;
|
||||||
messages.getSearchCounters#732eef00 peer:InputPeer filters:Vector<MessagesFilter> = Vector<messages.SearchCounter>;
|
messages.getSearchCounters#732eef00 peer:InputPeer filters:Vector<MessagesFilter> = Vector<messages.SearchCounter>;
|
||||||
messages.requestUrlAuth#e33f5613 peer:InputPeer msg_id:int button_id:int = UrlAuthResult;
|
messages.requestUrlAuth#198fb446 flags:# peer:flags.1?InputPeer msg_id:flags.1?int button_id:flags.1?int url:flags.2?string = UrlAuthResult;
|
||||||
messages.acceptUrlAuth#f729ea98 flags:# write_allowed:flags.0?true peer:InputPeer msg_id:int button_id:int = UrlAuthResult;
|
messages.acceptUrlAuth#b12c7125 flags:# write_allowed:flags.0?true peer:flags.1?InputPeer msg_id:flags.1?int button_id:flags.1?int url:flags.2?string = UrlAuthResult;
|
||||||
messages.hidePeerSettingsBar#4facb138 peer:InputPeer = Bool;
|
messages.hidePeerSettingsBar#4facb138 peer:InputPeer = Bool;
|
||||||
messages.getScheduledHistory#e2c2685b peer:InputPeer hash:int = messages.Messages;
|
messages.getScheduledHistory#e2c2685b peer:InputPeer hash:int = messages.Messages;
|
||||||
messages.getScheduledMessages#bdbb0464 peer:InputPeer id:Vector<int> = messages.Messages;
|
messages.getScheduledMessages#bdbb0464 peer:InputPeer id:Vector<int> = messages.Messages;
|
||||||
@ -1539,7 +1547,7 @@ channels.deleteUserHistory#d10dd71b channel:InputChannel user_id:InputUser = mes
|
|||||||
channels.reportSpam#fe087810 channel:InputChannel user_id:InputUser id:Vector<int> = Bool;
|
channels.reportSpam#fe087810 channel:InputChannel user_id:InputUser id:Vector<int> = Bool;
|
||||||
channels.getMessages#ad8c9a23 channel:InputChannel id:Vector<InputMessage> = messages.Messages;
|
channels.getMessages#ad8c9a23 channel:InputChannel id:Vector<InputMessage> = messages.Messages;
|
||||||
channels.getParticipants#123e05e9 channel:InputChannel filter:ChannelParticipantsFilter offset:int limit:int hash:int = channels.ChannelParticipants;
|
channels.getParticipants#123e05e9 channel:InputChannel filter:ChannelParticipantsFilter offset:int limit:int hash:int = channels.ChannelParticipants;
|
||||||
channels.getParticipant#546dd7a6 channel:InputChannel user_id:InputUser = channels.ChannelParticipant;
|
channels.getParticipant#a0ab6cc6 channel:InputChannel participant:InputPeer = channels.ChannelParticipant;
|
||||||
channels.getChannels#a7f6bbb id:Vector<InputChannel> = messages.Chats;
|
channels.getChannels#a7f6bbb id:Vector<InputChannel> = messages.Chats;
|
||||||
channels.getFullChannel#8736a09 channel:InputChannel = messages.ChatFull;
|
channels.getFullChannel#8736a09 channel:InputChannel = messages.ChatFull;
|
||||||
channels.createChannel#3d5fb10f flags:# broadcast:flags.0?true megagroup:flags.1?true for_import:flags.3?true title:string about:string geo_point:flags.2?InputGeoPoint address:flags.2?string = Updates;
|
channels.createChannel#3d5fb10f flags:# broadcast:flags.0?true megagroup:flags.1?true for_import:flags.3?true title:string about:string geo_point:flags.2?InputGeoPoint address:flags.2?string = Updates;
|
||||||
@ -1555,7 +1563,7 @@ channels.deleteChannel#c0111fe3 channel:InputChannel = Updates;
|
|||||||
channels.exportMessageLink#e63fadeb flags:# grouped:flags.0?true thread:flags.1?true channel:InputChannel id:int = ExportedMessageLink;
|
channels.exportMessageLink#e63fadeb flags:# grouped:flags.0?true thread:flags.1?true channel:InputChannel id:int = ExportedMessageLink;
|
||||||
channels.toggleSignatures#1f69b606 channel:InputChannel enabled:Bool = Updates;
|
channels.toggleSignatures#1f69b606 channel:InputChannel enabled:Bool = Updates;
|
||||||
channels.getAdminedPublicChannels#f8b036af flags:# by_location:flags.0?true check_limit:flags.1?true = messages.Chats;
|
channels.getAdminedPublicChannels#f8b036af flags:# by_location:flags.0?true check_limit:flags.1?true = messages.Chats;
|
||||||
channels.editBanned#72796912 channel:InputChannel user_id:InputUser banned_rights:ChatBannedRights = Updates;
|
channels.editBanned#96e6cd81 channel:InputChannel participant:InputPeer banned_rights:ChatBannedRights = Updates;
|
||||||
channels.getAdminLog#33ddf480 flags:# channel:InputChannel q:string events_filter:flags.0?ChannelAdminLogEventsFilter admins:flags.1?Vector<InputUser> max_id:long min_id:long limit:int = channels.AdminLogResults;
|
channels.getAdminLog#33ddf480 flags:# channel:InputChannel q:string events_filter:flags.0?ChannelAdminLogEventsFilter admins:flags.1?Vector<InputUser> max_id:long min_id:long limit:int = channels.AdminLogResults;
|
||||||
channels.setStickers#ea8ca4f9 channel:InputChannel stickerset:InputStickerSet = Bool;
|
channels.setStickers#ea8ca4f9 channel:InputChannel stickerset:InputStickerSet = Bool;
|
||||||
channels.readMessageContents#eab5dc38 channel:InputChannel id:Vector<int> = Bool;
|
channels.readMessageContents#eab5dc38 channel:InputChannel id:Vector<int> = Bool;
|
||||||
@ -1574,10 +1582,10 @@ bots.sendCustomRequest#aa2769ed custom_method:string params:DataJSON = DataJSON;
|
|||||||
bots.answerWebhookJSONQuery#e6213f4d query_id:long data:DataJSON = Bool;
|
bots.answerWebhookJSONQuery#e6213f4d query_id:long data:DataJSON = Bool;
|
||||||
bots.setBotCommands#805d46f6 commands:Vector<BotCommand> = Bool;
|
bots.setBotCommands#805d46f6 commands:Vector<BotCommand> = Bool;
|
||||||
|
|
||||||
payments.getPaymentForm#99f09745 msg_id:int = payments.PaymentForm;
|
payments.getPaymentForm#8a333c8d flags:# peer:InputPeer msg_id:int theme_params:flags.0?DataJSON = payments.PaymentForm;
|
||||||
payments.getPaymentReceipt#a092a980 msg_id:int = payments.PaymentReceipt;
|
payments.getPaymentReceipt#2478d1cc peer:InputPeer msg_id:int = payments.PaymentReceipt;
|
||||||
payments.validateRequestedInfo#770a8e74 flags:# save:flags.0?true msg_id:int info:PaymentRequestedInfo = payments.ValidatedRequestedInfo;
|
payments.validateRequestedInfo#db103170 flags:# save:flags.0?true peer:InputPeer msg_id:int info:PaymentRequestedInfo = payments.ValidatedRequestedInfo;
|
||||||
payments.sendPaymentForm#2b8879b3 flags:# msg_id:int requested_info_id:flags.0?string shipping_option_id:flags.1?string credentials:InputPaymentCredentials = payments.PaymentResult;
|
payments.sendPaymentForm#30c3bc9d flags:# form_id:long peer:InputPeer msg_id:int requested_info_id:flags.0?string shipping_option_id:flags.1?string credentials:InputPaymentCredentials tip_amount:flags.2?long = payments.PaymentResult;
|
||||||
payments.getSavedInfo#227d824b = payments.SavedInfo;
|
payments.getSavedInfo#227d824b = payments.SavedInfo;
|
||||||
payments.clearSavedInfo#d83d70c1 flags:# credentials:flags.0?true info:flags.1?true = Bool;
|
payments.clearSavedInfo#d83d70c1 flags:# credentials:flags.0?true info:flags.1?true = Bool;
|
||||||
payments.getBankCardData#2e79d779 number:string = payments.BankCardData;
|
payments.getBankCardData#2e79d779 number:string = payments.BankCardData;
|
||||||
@ -1597,16 +1605,23 @@ phone.discardCall#b2cbc1c0 flags:# video:flags.0?true peer:InputPhoneCall durati
|
|||||||
phone.setCallRating#59ead627 flags:# user_initiative:flags.0?true peer:InputPhoneCall rating:int comment:string = Updates;
|
phone.setCallRating#59ead627 flags:# user_initiative:flags.0?true peer:InputPhoneCall rating:int comment:string = Updates;
|
||||||
phone.saveCallDebug#277add7e peer:InputPhoneCall debug:DataJSON = Bool;
|
phone.saveCallDebug#277add7e peer:InputPhoneCall debug:DataJSON = Bool;
|
||||||
phone.sendSignalingData#ff7a9383 peer:InputPhoneCall data:bytes = Bool;
|
phone.sendSignalingData#ff7a9383 peer:InputPhoneCall data:bytes = Bool;
|
||||||
phone.createGroupCall#bd3dabe0 peer:InputPeer random_id:int = Updates;
|
phone.createGroupCall#48cdc6d8 flags:# peer:InputPeer random_id:int title:flags.0?string schedule_date:flags.1?int = Updates;
|
||||||
phone.joinGroupCall#5f9c8e62 flags:# muted:flags.0?true call:InputGroupCall params:DataJSON = Updates;
|
phone.joinGroupCall#b132ff7b flags:# muted:flags.0?true call:InputGroupCall join_as:InputPeer invite_hash:flags.1?string params:DataJSON = Updates;
|
||||||
phone.leaveGroupCall#500377f9 call:InputGroupCall source:int = Updates;
|
phone.leaveGroupCall#500377f9 call:InputGroupCall source:int = Updates;
|
||||||
phone.editGroupCallMember#a5e76cd8 flags:# muted:flags.0?true call:InputGroupCall user_id:InputUser volume:flags.1?int = Updates;
|
|
||||||
phone.inviteToGroupCall#7b393160 call:InputGroupCall users:Vector<InputUser> = Updates;
|
phone.inviteToGroupCall#7b393160 call:InputGroupCall users:Vector<InputUser> = Updates;
|
||||||
phone.discardGroupCall#7a777135 call:InputGroupCall = Updates;
|
phone.discardGroupCall#7a777135 call:InputGroupCall = Updates;
|
||||||
phone.toggleGroupCallSettings#74bbb43d flags:# call:InputGroupCall join_muted:flags.0?Bool = Updates;
|
phone.toggleGroupCallSettings#74bbb43d flags:# reset_invite_hash:flags.1?true call:InputGroupCall join_muted:flags.0?Bool = Updates;
|
||||||
phone.getGroupCall#c7cb017 call:InputGroupCall = phone.GroupCall;
|
phone.getGroupCall#c7cb017 call:InputGroupCall = phone.GroupCall;
|
||||||
phone.getGroupParticipants#c9f1d285 call:InputGroupCall ids:Vector<int> sources:Vector<int> offset:string limit:int = phone.GroupParticipants;
|
phone.getGroupParticipants#c558d8ab call:InputGroupCall ids:Vector<InputPeer> sources:Vector<int> offset:string limit:int = phone.GroupParticipants;
|
||||||
phone.checkGroupCall#b74a7bea call:InputGroupCall source:int = Bool;
|
phone.checkGroupCall#b74a7bea call:InputGroupCall source:int = Bool;
|
||||||
|
phone.toggleGroupCallRecord#c02a66d7 flags:# start:flags.0?true call:InputGroupCall title:flags.1?string = Updates;
|
||||||
|
phone.editGroupCallParticipant#d975eb80 flags:# muted:flags.0?true call:InputGroupCall participant:InputPeer volume:flags.1?int raise_hand:flags.2?Bool = Updates;
|
||||||
|
phone.editGroupCallTitle#1ca6ac0a call:InputGroupCall title:string = Updates;
|
||||||
|
phone.getGroupCallJoinAs#ef7c213a peer:InputPeer = phone.JoinAsPeers;
|
||||||
|
phone.exportGroupCallInvite#e6aa647f flags:# can_self_unmute:flags.0?true call:InputGroupCall = phone.ExportedGroupCallInvite;
|
||||||
|
phone.toggleGroupCallStartSubscription#219c34e6 call:InputGroupCall subscribed:Bool = Updates;
|
||||||
|
phone.startScheduledGroupCall#5680e342 call:InputGroupCall = Updates;
|
||||||
|
phone.saveDefaultGroupCallJoinAs#575e1f8c peer:InputPeer join_as:InputPeer = Bool;
|
||||||
|
|
||||||
langpack.getLangPack#f2f2330a lang_pack:string lang_code:string = LangPackDifference;
|
langpack.getLangPack#f2f2330a lang_pack:string lang_code:string = LangPackDifference;
|
||||||
langpack.getStrings#efea3803 lang_pack:string lang_code:string keys:Vector<string> = Vector<LangPackString>;
|
langpack.getStrings#efea3803 lang_pack:string lang_code:string keys:Vector<string> = Vector<LangPackString>;
|
||||||
|
@ -15,5 +15,5 @@ endif()
|
|||||||
add_executable(${PROJECT_NAME} ${SOURCES})
|
add_executable(${PROJECT_NAME} ${SOURCES})
|
||||||
|
|
||||||
if (NOT WIN32)
|
if (NOT WIN32)
|
||||||
target_link_libraries(${PROJECT_NAME} m)
|
target_link_libraries(${PROJECT_NAME} PRIVATE m)
|
||||||
endif()
|
endif()
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__linux__) || defined(__CYGWIN__)
|
#if defined(__linux__) || defined(__CYGWIN__) || defined(__sun)
|
||||||
|
|
||||||
# include <endian.h>
|
# include <endian.h>
|
||||||
|
|
||||||
|
@ -55,8 +55,8 @@ void HandshakeActor::return_connection(Status status) {
|
|||||||
CHECK(!raw_connection_promise_);
|
CHECK(!raw_connection_promise_);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (status.is_error() && !raw_connection->debug_str_.empty()) {
|
if (status.is_error() && !raw_connection->extra().debug_str.empty()) {
|
||||||
status = Status::Error(status.code(), PSLICE() << status.message() << " : " << raw_connection->debug_str_);
|
status = Status::Error(status.code(), PSLICE() << status.message() << " : " << raw_connection->extra().debug_str);
|
||||||
}
|
}
|
||||||
Scheduler::unsubscribe(raw_connection->get_poll_info().get_pollable_fd_ref());
|
Scheduler::unsubscribe(raw_connection->get_poll_info().get_pollable_fd_ref());
|
||||||
if (raw_connection_promise_) {
|
if (raw_connection_promise_) {
|
||||||
|
@ -85,7 +85,7 @@ ActorOwn<> create_ping_actor(string debug, unique_ptr<RawConnection> raw_connect
|
|||||||
raw_connection->close();
|
raw_connection->close();
|
||||||
promise_.set_error(std::move(status));
|
promise_.set_error(std::move(status));
|
||||||
} else {
|
} else {
|
||||||
raw_connection->rtt_ = ping_connection_->rtt();
|
raw_connection->extra().rtt = ping_connection_->rtt();
|
||||||
if (raw_connection->stats_callback()) {
|
if (raw_connection->stats_callback()) {
|
||||||
raw_connection->stats_callback()->on_pong();
|
raw_connection->stats_callback()->on_pong();
|
||||||
}
|
}
|
||||||
|
@ -7,21 +7,52 @@
|
|||||||
#include "td/mtproto/RawConnection.h"
|
#include "td/mtproto/RawConnection.h"
|
||||||
|
|
||||||
#include "td/mtproto/AuthKey.h"
|
#include "td/mtproto/AuthKey.h"
|
||||||
|
#include "td/mtproto/IStreamTransport.h"
|
||||||
|
#include "td/mtproto/ProxySecret.h"
|
||||||
#include "td/mtproto/Transport.h"
|
#include "td/mtproto/Transport.h"
|
||||||
|
|
||||||
|
#if TD_EXPERIMENTAL_WATCH_OS
|
||||||
|
#include "td/net/DarwinHttp.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "td/utils/BufferedFd.h"
|
||||||
#include "td/utils/format.h"
|
#include "td/utils/format.h"
|
||||||
#include "td/utils/logging.h"
|
#include "td/utils/logging.h"
|
||||||
#include "td/utils/misc.h"
|
#include "td/utils/misc.h"
|
||||||
|
#include "td/utils/MpscPollableQueue.h"
|
||||||
|
#include "td/utils/port/EventFd.h"
|
||||||
|
#include "td/utils/Slice.h"
|
||||||
#include "td/utils/Status.h"
|
#include "td/utils/Status.h"
|
||||||
#include "td/utils/StorerBase.h"
|
#include "td/utils/StorerBase.h"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
namespace mtproto {
|
namespace mtproto {
|
||||||
|
|
||||||
void RawConnection::send_crypto(const Storer &storer, int64 session_id, int64 salt, const AuthKey &auth_key,
|
class RawConnectionDefault : public RawConnection {
|
||||||
uint64 quick_ack_token) {
|
public:
|
||||||
|
RawConnectionDefault(SocketFd socket_fd, TransportType transport_type, unique_ptr<StatsCallback> stats_callback)
|
||||||
|
: socket_fd_(std::move(socket_fd))
|
||||||
|
, transport_(create_transport(transport_type))
|
||||||
|
, stats_callback_(std::move(stats_callback)) {
|
||||||
|
transport_->init(&socket_fd_.input_buffer(), &socket_fd_.output_buffer());
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_connection_token(StateManager::ConnectionToken connection_token) override {
|
||||||
|
connection_token_ = std::move(connection_token);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool can_send() const override {
|
||||||
|
return transport_->can_write();
|
||||||
|
}
|
||||||
|
TransportType get_transport_type() const override {
|
||||||
|
return transport_->get_type();
|
||||||
|
}
|
||||||
|
void send_crypto(const Storer &storer, int64 session_id, int64 salt, const AuthKey &auth_key,
|
||||||
|
uint64 quick_ack_token) override {
|
||||||
PacketInfo info;
|
PacketInfo info;
|
||||||
info.version = 2;
|
info.version = 2;
|
||||||
info.no_crypto_flag = false;
|
info.no_crypto_flag = false;
|
||||||
@ -44,9 +75,9 @@ void RawConnection::send_crypto(const Storer &storer, int64 session_id, int64 sa
|
|||||||
}
|
}
|
||||||
|
|
||||||
transport_->write(std::move(packet), use_quick_ack);
|
transport_->write(std::move(packet), use_quick_ack);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64 RawConnection::send_no_crypto(const Storer &storer) {
|
uint64 send_no_crypto(const Storer &storer) override {
|
||||||
PacketInfo info;
|
PacketInfo info;
|
||||||
|
|
||||||
info.no_crypto_flag = true;
|
info.no_crypto_flag = true;
|
||||||
@ -56,9 +87,56 @@ uint64 RawConnection::send_no_crypto(const Storer &storer) {
|
|||||||
LOG(INFO) << "Send handshake packet: " << format::as_hex_dump<4>(packet.as_slice());
|
LOG(INFO) << "Send handshake packet: " << format::as_hex_dump<4>(packet.as_slice());
|
||||||
transport_->write(std::move(packet), false);
|
transport_->write(std::move(packet), false);
|
||||||
return info.message_id;
|
return info.message_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status RawConnection::flush_read(const AuthKey &auth_key, Callback &callback) {
|
PollableFdInfo &get_poll_info() override {
|
||||||
|
return socket_fd_.get_poll_info();
|
||||||
|
}
|
||||||
|
|
||||||
|
StatsCallback *stats_callback() override {
|
||||||
|
return stats_callback_.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
// NB: After first returned error, all subsequent calls will return error too.
|
||||||
|
Status flush(const AuthKey &auth_key, Callback &callback) override {
|
||||||
|
auto status = do_flush(auth_key, callback);
|
||||||
|
if (status.is_error()) {
|
||||||
|
if (stats_callback_ && status.code() != 2) {
|
||||||
|
stats_callback_->on_error();
|
||||||
|
}
|
||||||
|
has_error_ = true;
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_error() const override {
|
||||||
|
return has_error_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void close() override {
|
||||||
|
transport_.reset();
|
||||||
|
socket_fd_.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
PublicFields &extra() override {
|
||||||
|
return extra_;
|
||||||
|
}
|
||||||
|
const PublicFields &extra() const override {
|
||||||
|
return extra_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
PublicFields extra_;
|
||||||
|
BufferedFd<SocketFd> socket_fd_;
|
||||||
|
unique_ptr<IStreamTransport> transport_;
|
||||||
|
std::map<uint32, uint64> quick_ack_to_token_;
|
||||||
|
bool has_error_{false};
|
||||||
|
|
||||||
|
unique_ptr<StatsCallback> stats_callback_;
|
||||||
|
|
||||||
|
StateManager::ConnectionToken connection_token_;
|
||||||
|
|
||||||
|
Status flush_read(const AuthKey &auth_key, Callback &callback) {
|
||||||
auto r = socket_fd_.flush_read();
|
auto r = socket_fd_.flush_read();
|
||||||
if (r.is_ok()) {
|
if (r.is_ok()) {
|
||||||
if (stats_callback_) {
|
if (stats_callback_) {
|
||||||
@ -123,9 +201,9 @@ Status RawConnection::flush_read(const AuthKey &auth_key, Callback &callback) {
|
|||||||
|
|
||||||
TRY_STATUS(std::move(r));
|
TRY_STATUS(std::move(r));
|
||||||
return Status::OK();
|
return Status::OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
Status RawConnection::on_read_mtproto_error(int32 error_code) {
|
Status on_read_mtproto_error(int32 error_code) {
|
||||||
if (error_code == -429) {
|
if (error_code == -429) {
|
||||||
if (stats_callback_) {
|
if (stats_callback_) {
|
||||||
stats_callback_->on_mtproto_error();
|
stats_callback_->on_mtproto_error();
|
||||||
@ -136,9 +214,9 @@ Status RawConnection::on_read_mtproto_error(int32 error_code) {
|
|||||||
return Status::Error(-404, PSLICE() << "MTProto error: " << error_code);
|
return Status::Error(-404, PSLICE() << "MTProto error: " << error_code);
|
||||||
}
|
}
|
||||||
return Status::Error(PSLICE() << "MTProto error: " << error_code);
|
return Status::Error(PSLICE() << "MTProto error: " << error_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
Status RawConnection::on_quick_ack(uint32 quick_ack, Callback &callback) {
|
Status on_quick_ack(uint32 quick_ack, Callback &callback) {
|
||||||
auto it = quick_ack_to_token_.find(quick_ack);
|
auto it = quick_ack_to_token_.find(quick_ack);
|
||||||
if (it == quick_ack_to_token_.end()) {
|
if (it == quick_ack_to_token_.end()) {
|
||||||
LOG(WARNING) << Status::Error(PSLICE() << "Unknown quick_ack " << quick_ack);
|
LOG(WARNING) << Status::Error(PSLICE() << "Unknown quick_ack " << quick_ack);
|
||||||
@ -149,14 +227,235 @@ Status RawConnection::on_quick_ack(uint32 quick_ack, Callback &callback) {
|
|||||||
quick_ack_to_token_.erase(it);
|
quick_ack_to_token_.erase(it);
|
||||||
callback.on_quick_ack(token).ignore();
|
callback.on_quick_ack(token).ignore();
|
||||||
return Status::OK();
|
return Status::OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
Status RawConnection::flush_write() {
|
Status flush_write() {
|
||||||
TRY_RESULT(size, socket_fd_.flush_write());
|
TRY_RESULT(size, socket_fd_.flush_write());
|
||||||
if (size > 0 && stats_callback_) {
|
if (size > 0 && stats_callback_) {
|
||||||
stats_callback_->on_write(size);
|
stats_callback_->on_write(size);
|
||||||
}
|
}
|
||||||
return Status::OK();
|
return Status::OK();
|
||||||
|
}
|
||||||
|
|
||||||
|
Status do_flush(const AuthKey &auth_key, Callback &callback) TD_WARN_UNUSED_RESULT {
|
||||||
|
if (has_error_) {
|
||||||
|
return Status::Error("Connection has already failed");
|
||||||
|
}
|
||||||
|
sync_with_poll(socket_fd_);
|
||||||
|
|
||||||
|
// read/write
|
||||||
|
// EINVAL may be returned in linux kernel < 2.6.28. And on some new kernels too.
|
||||||
|
// just close connection and hope that read or write will not return this error too.
|
||||||
|
TRY_STATUS(socket_fd_.get_pending_error());
|
||||||
|
|
||||||
|
TRY_STATUS(flush_read(auth_key, callback));
|
||||||
|
TRY_STATUS(callback.before_write());
|
||||||
|
TRY_STATUS(flush_write());
|
||||||
|
if (can_close_local(socket_fd_)) {
|
||||||
|
return Status::Error("Connection closed");
|
||||||
|
}
|
||||||
|
return Status::OK();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#if TD_EXPERIMENTAL_WATCH_OS
|
||||||
|
class RawConnectionHttp : public RawConnection {
|
||||||
|
public:
|
||||||
|
RawConnectionHttp(IPAddress ip_address, unique_ptr<StatsCallback> stats_callback)
|
||||||
|
: ip_address_(std::move(ip_address)), stats_callback_(std::move(stats_callback)) {
|
||||||
|
answers_ = std::make_shared<MpscPollableQueue<Result<BufferSlice>>>();
|
||||||
|
answers_->init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_connection_token(StateManager::ConnectionToken connection_token) override {
|
||||||
|
connection_token_ = std::move(connection_token);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool can_send() const override {
|
||||||
|
return mode_ == Send;
|
||||||
|
}
|
||||||
|
TransportType get_transport_type() const override {
|
||||||
|
return mtproto::TransportType{mtproto::TransportType::Http, 0, mtproto::ProxySecret()};
|
||||||
|
}
|
||||||
|
void send_crypto(const Storer &storer, int64 session_id, int64 salt, const AuthKey &auth_key,
|
||||||
|
uint64 quick_ack_token) override {
|
||||||
|
PacketInfo info;
|
||||||
|
info.version = 2;
|
||||||
|
info.no_crypto_flag = false;
|
||||||
|
info.salt = salt;
|
||||||
|
info.session_id = session_id;
|
||||||
|
info.use_random_padding = false;
|
||||||
|
|
||||||
|
auto packet = BufferWriter{Transport::write(storer, auth_key, &info), 0, 0};
|
||||||
|
Transport::write(storer, auth_key, &info, packet.as_slice());
|
||||||
|
|
||||||
|
send_packet(packet.as_buffer_slice());
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 send_no_crypto(const Storer &storer) override {
|
||||||
|
PacketInfo info;
|
||||||
|
|
||||||
|
info.no_crypto_flag = true;
|
||||||
|
auto packet = BufferWriter{Transport::write(storer, AuthKey(), &info), 0, 0};
|
||||||
|
Transport::write(storer, AuthKey(), &info, packet.as_slice());
|
||||||
|
LOG(INFO) << "Send handshake packet: " << format::as_hex_dump<4>(packet.as_slice());
|
||||||
|
send_packet(packet.as_buffer_slice());
|
||||||
|
return info.message_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
PollableFdInfo &get_poll_info() override {
|
||||||
|
return answers_->reader_get_event_fd().get_poll_info();
|
||||||
|
}
|
||||||
|
|
||||||
|
StatsCallback *stats_callback() override {
|
||||||
|
return stats_callback_.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
// NB: After first returned error, all subsequent calls will return error too.
|
||||||
|
Status flush(const AuthKey &auth_key, Callback &callback) override {
|
||||||
|
auto status = do_flush(auth_key, callback);
|
||||||
|
if (status.is_error()) {
|
||||||
|
if (stats_callback_ && status.code() != 2) {
|
||||||
|
stats_callback_->on_error();
|
||||||
|
}
|
||||||
|
has_error_ = true;
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_error() const override {
|
||||||
|
return has_error_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void close() override {
|
||||||
|
}
|
||||||
|
|
||||||
|
PublicFields &extra() override {
|
||||||
|
return extra_;
|
||||||
|
}
|
||||||
|
const PublicFields &extra() const override {
|
||||||
|
return extra_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
PublicFields extra_;
|
||||||
|
IPAddress ip_address_;
|
||||||
|
bool has_error_{false};
|
||||||
|
EventFd event_fd_;
|
||||||
|
|
||||||
|
enum Mode { Send, Receive } mode_{Send};
|
||||||
|
|
||||||
|
unique_ptr<StatsCallback> stats_callback_;
|
||||||
|
|
||||||
|
StateManager::ConnectionToken connection_token_;
|
||||||
|
std::shared_ptr<MpscPollableQueue<Result<BufferSlice>>> answers_;
|
||||||
|
std::vector<BufferSlice> to_send_;
|
||||||
|
|
||||||
|
void send_packet(BufferSlice packet) {
|
||||||
|
CHECK(mode_ == Send);
|
||||||
|
mode_ = Receive;
|
||||||
|
to_send_.push_back(std::move(packet));
|
||||||
|
}
|
||||||
|
|
||||||
|
Status flush_read(const AuthKey &auth_key, Callback &callback) {
|
||||||
|
while (true) {
|
||||||
|
auto packets_n = answers_->reader_wait_nonblock();
|
||||||
|
if (packets_n == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < packets_n; i++) {
|
||||||
|
TRY_RESULT(packet, answers_->reader_get_unsafe());
|
||||||
|
if (stats_callback_) {
|
||||||
|
stats_callback_->on_read(packet.size());
|
||||||
|
}
|
||||||
|
callback.on_read(packet.size());
|
||||||
|
CHECK(mode_ == Receive);
|
||||||
|
mode_ = Send;
|
||||||
|
|
||||||
|
PacketInfo info;
|
||||||
|
info.version = 2;
|
||||||
|
|
||||||
|
TRY_RESULT(read_result, Transport::read(packet.as_slice(), auth_key, &info));
|
||||||
|
switch (read_result.type()) {
|
||||||
|
case Transport::ReadResult::Quickack: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Transport::ReadResult::Error: {
|
||||||
|
TRY_STATUS(on_read_mtproto_error(read_result.error()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Transport::ReadResult::Packet: {
|
||||||
|
// If a packet was successfully decrypted, then it is ok to assume that the connection is alive
|
||||||
|
if (!auth_key.empty()) {
|
||||||
|
if (stats_callback_) {
|
||||||
|
stats_callback_->on_pong();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TRY_STATUS(callback.on_raw_packet(info, packet.from_slice(read_result.packet())));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Transport::ReadResult::Nop:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status::OK();
|
||||||
|
}
|
||||||
|
|
||||||
|
Status on_read_mtproto_error(int32 error_code) {
|
||||||
|
if (error_code == -429) {
|
||||||
|
if (stats_callback_) {
|
||||||
|
stats_callback_->on_mtproto_error();
|
||||||
|
}
|
||||||
|
return Status::Error(500, PSLICE() << "MTProto error: " << error_code);
|
||||||
|
}
|
||||||
|
if (error_code == -404) {
|
||||||
|
return Status::Error(-404, PSLICE() << "MTProto error: " << error_code);
|
||||||
|
}
|
||||||
|
return Status::Error(PSLICE() << "MTProto error: " << error_code);
|
||||||
|
}
|
||||||
|
|
||||||
|
Status flush_write() {
|
||||||
|
for (auto &packet : to_send_) {
|
||||||
|
TRY_STATUS(do_send(packet.as_slice()));
|
||||||
|
if (packet.size() > 0 && stats_callback_) {
|
||||||
|
stats_callback_->on_write(packet.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
to_send_.clear();
|
||||||
|
return Status::OK();
|
||||||
|
}
|
||||||
|
|
||||||
|
Status do_send(Slice data) {
|
||||||
|
DarwinHttp::post(PSLICE() << "http://" << ip_address_.get_ip_str() << ":" << ip_address_.get_port() << "/api", data,
|
||||||
|
[answers = answers_](auto res) { answers->writer_put(std::move(res)); });
|
||||||
|
return Status::OK();
|
||||||
|
}
|
||||||
|
|
||||||
|
Status do_flush(const AuthKey &auth_key, Callback &callback) TD_WARN_UNUSED_RESULT {
|
||||||
|
if (has_error_) {
|
||||||
|
return Status::Error("Connection has already failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
TRY_STATUS(flush_read(auth_key, callback));
|
||||||
|
TRY_STATUS(callback.before_write());
|
||||||
|
TRY_STATUS(flush_write());
|
||||||
|
return Status::OK();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
unique_ptr<RawConnection> RawConnection::create(IPAddress ip_address, SocketFd socket_fd, TransportType transport_type,
|
||||||
|
unique_ptr<StatsCallback> stats_callback) {
|
||||||
|
#if TD_EXPERIMENTAL_WATCH_OS
|
||||||
|
return td::make_unique<RawConnectionHttp>(ip_address, std::move(stats_callback));
|
||||||
|
#else
|
||||||
|
return td::make_unique<RawConnectionDefault>(std::move(socket_fd), transport_type, std::move(stats_callback));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mtproto
|
} // namespace mtproto
|
||||||
|
@ -6,22 +6,19 @@
|
|||||||
//
|
//
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "td/mtproto/IStreamTransport.h"
|
#include "td/telegram/StateManager.h"
|
||||||
|
|
||||||
#include "td/mtproto/PacketInfo.h"
|
#include "td/mtproto/PacketInfo.h"
|
||||||
#include "td/mtproto/TransportType.h"
|
#include "td/mtproto/TransportType.h"
|
||||||
|
|
||||||
#include "td/utils/buffer.h"
|
#include "td/utils/buffer.h"
|
||||||
#include "td/utils/BufferedFd.h"
|
|
||||||
#include "td/utils/common.h"
|
#include "td/utils/common.h"
|
||||||
#include "td/utils/port/detail/PollableFd.h"
|
#include "td/utils/port/detail/PollableFd.h"
|
||||||
|
#include "td/utils/port/IPAddress.h"
|
||||||
#include "td/utils/port/SocketFd.h"
|
#include "td/utils/port/SocketFd.h"
|
||||||
#include "td/utils/Status.h"
|
#include "td/utils/Status.h"
|
||||||
#include "td/utils/StorerBase.h"
|
#include "td/utils/StorerBase.h"
|
||||||
|
|
||||||
#include "td/telegram/StateManager.h"
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
namespace mtproto {
|
namespace mtproto {
|
||||||
|
|
||||||
@ -40,33 +37,23 @@ class RawConnection {
|
|||||||
virtual void on_mtproto_error() = 0;
|
virtual void on_mtproto_error() = 0;
|
||||||
};
|
};
|
||||||
RawConnection() = default;
|
RawConnection() = default;
|
||||||
RawConnection(SocketFd socket_fd, TransportType transport_type, unique_ptr<StatsCallback> stats_callback)
|
RawConnection(const RawConnection &) = delete;
|
||||||
: socket_fd_(std::move(socket_fd))
|
RawConnection &operator=(const RawConnection &) = delete;
|
||||||
, transport_(create_transport(transport_type))
|
virtual ~RawConnection() = default;
|
||||||
, stats_callback_(std::move(stats_callback)) {
|
|
||||||
transport_->init(&socket_fd_.input_buffer(), &socket_fd_.output_buffer());
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_connection_token(StateManager::ConnectionToken connection_token) {
|
static unique_ptr<RawConnection> create(IPAddress ip_address, SocketFd socket_fd, TransportType transport_type,
|
||||||
connection_token_ = std::move(connection_token);
|
unique_ptr<StatsCallback> stats_callback);
|
||||||
}
|
|
||||||
|
|
||||||
bool can_send() const {
|
virtual void set_connection_token(StateManager::ConnectionToken connection_token) = 0;
|
||||||
return transport_->can_write();
|
|
||||||
}
|
|
||||||
TransportType get_transport_type() const {
|
|
||||||
return transport_->get_type();
|
|
||||||
}
|
|
||||||
void send_crypto(const Storer &storer, int64 session_id, int64 salt, const AuthKey &auth_key,
|
|
||||||
uint64 quick_ack_token = 0);
|
|
||||||
uint64 send_no_crypto(const Storer &storer);
|
|
||||||
|
|
||||||
PollableFdInfo &get_poll_info() {
|
virtual bool can_send() const = 0;
|
||||||
return socket_fd_.get_poll_info();
|
virtual TransportType get_transport_type() const = 0;
|
||||||
}
|
virtual void send_crypto(const Storer &storer, int64 session_id, int64 salt, const AuthKey &auth_key,
|
||||||
StatsCallback *stats_callback() {
|
uint64 quick_ack_token = 0) = 0;
|
||||||
return stats_callback_.get();
|
virtual uint64 send_no_crypto(const Storer &storer) = 0;
|
||||||
}
|
|
||||||
|
virtual PollableFdInfo &get_poll_info() = 0;
|
||||||
|
virtual StatsCallback *stats_callback() = 0;
|
||||||
|
|
||||||
class Callback {
|
class Callback {
|
||||||
public:
|
public:
|
||||||
@ -86,65 +73,19 @@ class RawConnection {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// NB: After first returned error, all subsequent calls will return error too.
|
// NB: After first returned error, all subsequent calls will return error too.
|
||||||
Status flush(const AuthKey &auth_key, Callback &callback) TD_WARN_UNUSED_RESULT {
|
virtual Status flush(const AuthKey &auth_key, Callback &callback) TD_WARN_UNUSED_RESULT = 0;
|
||||||
auto status = do_flush(auth_key, callback);
|
virtual bool has_error() const = 0;
|
||||||
if (status.is_error()) {
|
|
||||||
if (stats_callback_ && status.code() != 2) {
|
|
||||||
stats_callback_->on_error();
|
|
||||||
}
|
|
||||||
has_error_ = true;
|
|
||||||
}
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool has_error() const {
|
virtual void close() = 0;
|
||||||
return has_error_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void close() {
|
struct PublicFields {
|
||||||
transport_.reset();
|
uint32 extra{0};
|
||||||
socket_fd_.close();
|
string debug_str;
|
||||||
}
|
double rtt{0};
|
||||||
|
};
|
||||||
|
|
||||||
uint32 extra_{0};
|
virtual PublicFields &extra() = 0;
|
||||||
string debug_str_;
|
virtual const PublicFields &extra() const = 0;
|
||||||
double rtt_{0};
|
|
||||||
|
|
||||||
private:
|
|
||||||
BufferedFd<SocketFd> socket_fd_;
|
|
||||||
unique_ptr<IStreamTransport> transport_;
|
|
||||||
std::map<uint32, uint64> quick_ack_to_token_;
|
|
||||||
bool has_error_{false};
|
|
||||||
|
|
||||||
unique_ptr<StatsCallback> stats_callback_;
|
|
||||||
|
|
||||||
StateManager::ConnectionToken connection_token_;
|
|
||||||
|
|
||||||
Status flush_read(const AuthKey &auth_key, Callback &callback);
|
|
||||||
Status flush_write();
|
|
||||||
|
|
||||||
Status on_quick_ack(uint32 quick_ack, Callback &callback);
|
|
||||||
Status on_read_mtproto_error(int32 error_code);
|
|
||||||
|
|
||||||
Status do_flush(const AuthKey &auth_key, Callback &callback) TD_WARN_UNUSED_RESULT {
|
|
||||||
if (has_error_) {
|
|
||||||
return Status::Error("Connection has already failed");
|
|
||||||
}
|
|
||||||
sync_with_poll(socket_fd_);
|
|
||||||
|
|
||||||
// read/write
|
|
||||||
// EINVAL may be returned in linux kernel < 2.6.28. And on some new kernels too.
|
|
||||||
// just close connection and hope that read or write will not return this error too.
|
|
||||||
TRY_STATUS(socket_fd_.get_pending_error());
|
|
||||||
|
|
||||||
TRY_STATUS(flush_read(auth_key, callback));
|
|
||||||
TRY_STATUS(callback.before_write());
|
|
||||||
TRY_STATUS(flush_write());
|
|
||||||
if (can_close_local(socket_fd_)) {
|
|
||||||
return Status::Error("Connection closed");
|
|
||||||
}
|
|
||||||
return Status::OK();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mtproto
|
} // namespace mtproto
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "td/utils/format.h"
|
#include "td/utils/format.h"
|
||||||
#include "td/utils/Gzip.h"
|
#include "td/utils/Gzip.h"
|
||||||
#include "td/utils/logging.h"
|
#include "td/utils/logging.h"
|
||||||
|
#include "td/utils/misc.h"
|
||||||
#include "td/utils/Random.h"
|
#include "td/utils/Random.h"
|
||||||
#include "td/utils/ScopeGuard.h"
|
#include "td/utils/ScopeGuard.h"
|
||||||
#include "td/utils/Time.h"
|
#include "td/utils/Time.h"
|
||||||
@ -863,7 +864,7 @@ void SessionConnection::flush_packet() {
|
|||||||
max_after = HTTP_MAX_AFTER;
|
max_after = HTTP_MAX_AFTER;
|
||||||
auto time_to_disconnect =
|
auto time_to_disconnect =
|
||||||
min(ping_disconnect_delay() + last_pong_at_, read_disconnect_delay() + last_read_at_) - Time::now_cached();
|
min(ping_disconnect_delay() + last_pong_at_, read_disconnect_delay() + last_read_at_) - Time::now_cached();
|
||||||
max_wait = min(http_max_wait(), static_cast<int>(1000 * max(0.1, time_to_disconnect - rtt())));
|
max_wait = static_cast<int>(1000 * clamp(time_to_disconnect - rtt(), 0.1, http_max_wait()));
|
||||||
} else if (mode_ == Mode::Http) {
|
} else if (mode_ == Mode::Http) {
|
||||||
max_delay = HTTP_MAX_DELAY;
|
max_delay = HTTP_MAX_DELAY;
|
||||||
max_after = HTTP_MAX_AFTER;
|
max_after = HTTP_MAX_AFTER;
|
||||||
|
@ -132,7 +132,7 @@ class SessionConnection
|
|||||||
bool is_main_ = false;
|
bool is_main_ = false;
|
||||||
|
|
||||||
int rtt() const {
|
int rtt() const {
|
||||||
return max(2, static_cast<int>(raw_connection_->rtt_ * 1.5 + 1));
|
return max(2, static_cast<int>(raw_connection_->extra().rtt * 1.5 + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 read_disconnect_delay() const {
|
int32 read_disconnect_delay() const {
|
||||||
@ -151,8 +151,8 @@ class SessionConnection
|
|||||||
return online_flag_ ? rtt() : 60;
|
return online_flag_ ? rtt() : 60;
|
||||||
}
|
}
|
||||||
|
|
||||||
int http_max_wait() const {
|
double http_max_wait() const {
|
||||||
return 25 * 1000; // 25s. Longer could be closed by proxy
|
return 25.0; // 25s. Longer could be closed by proxy
|
||||||
}
|
}
|
||||||
static constexpr int HTTP_MAX_AFTER = 10; // 0.01s
|
static constexpr int HTTP_MAX_AFTER = 10; // 0.01s
|
||||||
static constexpr int HTTP_MAX_DELAY = 30; // 0.03s
|
static constexpr int HTTP_MAX_DELAY = 30; // 0.03s
|
||||||
|
@ -92,11 +92,11 @@ class Transport {
|
|||||||
MutableSlice dest = MutableSlice());
|
MutableSlice dest = MutableSlice());
|
||||||
|
|
||||||
static std::pair<uint32, UInt128> calc_message_key2(const AuthKey &auth_key, int X, Slice to_encrypt);
|
static std::pair<uint32, UInt128> calc_message_key2(const AuthKey &auth_key, int X, Slice to_encrypt);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <class HeaderT>
|
template <class HeaderT>
|
||||||
static std::pair<uint32, UInt128> calc_message_ack_and_key(const HeaderT &head, size_t data_size);
|
static std::pair<uint32, UInt128> calc_message_ack_and_key(const HeaderT &head, size_t data_size);
|
||||||
|
|
||||||
|
|
||||||
template <class HeaderT>
|
template <class HeaderT>
|
||||||
static size_t calc_crypto_size(size_t data_size);
|
static size_t calc_crypto_size(size_t data_size);
|
||||||
|
|
||||||
|
@ -302,7 +302,7 @@ FileId AnimationsManager::dup_animation(FileId new_id, FileId old_id) {
|
|||||||
|
|
||||||
bool AnimationsManager::merge_animations(FileId new_id, FileId old_id, bool can_delete_old) {
|
bool AnimationsManager::merge_animations(FileId new_id, FileId old_id, bool can_delete_old) {
|
||||||
if (!old_id.is_valid()) {
|
if (!old_id.is_valid()) {
|
||||||
LOG(ERROR) << "Old file id is invalid";
|
LOG(ERROR) << "Old file identifier is invalid";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ FileId AudiosManager::dup_audio(FileId new_id, FileId old_id) {
|
|||||||
|
|
||||||
bool AudiosManager::merge_audios(FileId new_id, FileId old_id, bool can_delete_old) {
|
bool AudiosManager::merge_audios(FileId new_id, FileId old_id, bool can_delete_old) {
|
||||||
if (!old_id.is_valid()) {
|
if (!old_id.is_valid()) {
|
||||||
LOG(ERROR) << "Old file id is invalid";
|
LOG(ERROR) << "Old file identifier is invalid";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,7 +165,7 @@ void AuthManager::check_bot_token(uint64 query_id, string bot_token) {
|
|||||||
telegram_api::auth_importBotAuthorization(0, api_id_, api_hash_, bot_token_)));
|
telegram_api::auth_importBotAuthorization(0, api_id_, api_hash_, bot_token_)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AuthManager::request_qr_code_authentication(uint64 query_id, vector<int32> other_user_ids) {
|
void AuthManager::request_qr_code_authentication(uint64 query_id, vector<UserId> other_user_ids) {
|
||||||
if (state_ != State::WaitPhoneNumber) {
|
if (state_ != State::WaitPhoneNumber) {
|
||||||
if ((state_ == State::WaitCode || state_ == State::WaitPassword || state_ == State::WaitRegistration) &&
|
if ((state_ == State::WaitCode || state_ == State::WaitPassword || state_ == State::WaitRegistration) &&
|
||||||
net_query_id_ == 0) {
|
net_query_id_ == 0) {
|
||||||
@ -181,8 +181,7 @@ void AuthManager::request_qr_code_authentication(uint64 query_id, vector<int32>
|
|||||||
"Cannot request QR code authentication after bot token was entered. You need to log out first"));
|
"Cannot request QR code authentication after bot token was entered. You need to log out first"));
|
||||||
}
|
}
|
||||||
for (auto &other_user_id : other_user_ids) {
|
for (auto &other_user_id : other_user_ids) {
|
||||||
UserId user_id(other_user_id);
|
if (!other_user_id.is_valid()) {
|
||||||
if (!user_id.is_valid()) {
|
|
||||||
return on_query_error(query_id, Status::Error(400, "Invalid user_id among other user_ids"));
|
return on_query_error(query_id, Status::Error(400, "Invalid user_id among other user_ids"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -200,8 +199,8 @@ void AuthManager::request_qr_code_authentication(uint64 query_id, vector<int32>
|
|||||||
void AuthManager::send_export_login_token_query() {
|
void AuthManager::send_export_login_token_query() {
|
||||||
poll_export_login_code_timeout_.cancel_timeout();
|
poll_export_login_code_timeout_.cancel_timeout();
|
||||||
start_net_query(NetQueryType::RequestQrCode,
|
start_net_query(NetQueryType::RequestQrCode,
|
||||||
G()->net_query_creator().create_unauth(
|
G()->net_query_creator().create_unauth(telegram_api::auth_exportLoginToken(
|
||||||
telegram_api::auth_exportLoginToken(api_id_, api_hash_, vector<int32>(other_user_ids_))));
|
api_id_, api_hash_, UserId::get_input_user_ids(other_user_ids_))));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AuthManager::set_login_token_expires_at(double login_token_expires_at) {
|
void AuthManager::set_login_token_expires_at(double login_token_expires_at) {
|
||||||
@ -308,7 +307,7 @@ void AuthManager::check_password(uint64 query_id, string password) {
|
|||||||
return on_query_error(query_id, Status::Error(8, "Call to checkAuthenticationPassword unexpected"));
|
return on_query_error(query_id, Status::Error(8, "Call to checkAuthenticationPassword unexpected"));
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(INFO) << "Have SRP id " << wait_password_state_.srp_id_;
|
LOG(INFO) << "Have SRP ID " << wait_password_state_.srp_id_;
|
||||||
on_new_query(query_id);
|
on_new_query(query_id);
|
||||||
password_ = std::move(password);
|
password_ = std::move(password);
|
||||||
start_net_query(NetQueryType::GetPassword,
|
start_net_query(NetQueryType::GetPassword,
|
||||||
@ -569,7 +568,7 @@ void AuthManager::on_get_password_result(NetQueryPtr &result) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (state_ == State::WaitPassword) {
|
if (state_ == State::WaitPassword) {
|
||||||
LOG(INFO) << "Have SRP id " << wait_password_state_.srp_id_;
|
LOG(INFO) << "Have SRP ID " << wait_password_state_.srp_id_;
|
||||||
auto hash = PasswordManager::get_input_check_password(password_, wait_password_state_.current_client_salt_,
|
auto hash = PasswordManager::get_input_check_password(password_, wait_password_state_.current_client_salt_,
|
||||||
wait_password_state_.current_server_salt_,
|
wait_password_state_.current_server_salt_,
|
||||||
wait_password_state_.srp_g_, wait_password_state_.srp_p_,
|
wait_password_state_.srp_g_, wait_password_state_.srp_p_,
|
||||||
|
@ -9,10 +9,10 @@
|
|||||||
#include "td/telegram/net/NetActor.h"
|
#include "td/telegram/net/NetActor.h"
|
||||||
#include "td/telegram/net/NetQuery.h"
|
#include "td/telegram/net/NetQuery.h"
|
||||||
#include "td/telegram/SendCodeHelper.h"
|
#include "td/telegram/SendCodeHelper.h"
|
||||||
#include "td/telegram/TermsOfService.h"
|
|
||||||
|
|
||||||
#include "td/telegram/td_api.h"
|
#include "td/telegram/td_api.h"
|
||||||
#include "td/telegram/telegram_api.h"
|
#include "td/telegram/telegram_api.h"
|
||||||
|
#include "td/telegram/TermsOfService.h"
|
||||||
|
#include "td/telegram/UserId.h"
|
||||||
|
|
||||||
#include "td/actor/actor.h"
|
#include "td/actor/actor.h"
|
||||||
#include "td/actor/Timeout.h"
|
#include "td/actor/Timeout.h"
|
||||||
@ -38,7 +38,7 @@ class AuthManager : public NetActor {
|
|||||||
void resend_authentication_code(uint64 query_id);
|
void resend_authentication_code(uint64 query_id);
|
||||||
void check_code(uint64 query_id, string code);
|
void check_code(uint64 query_id, string code);
|
||||||
void register_user(uint64 query_id, string first_name, string last_name);
|
void register_user(uint64 query_id, string first_name, string last_name);
|
||||||
void request_qr_code_authentication(uint64 query_id, vector<int32> other_user_ids);
|
void request_qr_code_authentication(uint64 query_id, vector<UserId> other_user_ids);
|
||||||
void check_bot_token(uint64 query_id, string bot_token);
|
void check_bot_token(uint64 query_id, string bot_token);
|
||||||
void check_password(uint64 query_id, string password);
|
void check_password(uint64 query_id, string password);
|
||||||
void request_password_recovery(uint64 query_id);
|
void request_password_recovery(uint64 query_id);
|
||||||
@ -113,7 +113,7 @@ class AuthManager : public NetActor {
|
|||||||
SendCodeHelper send_code_helper_;
|
SendCodeHelper send_code_helper_;
|
||||||
|
|
||||||
// WaitQrCodeConfirmation
|
// WaitQrCodeConfirmation
|
||||||
vector<int32> other_user_ids_;
|
vector<UserId> other_user_ids_;
|
||||||
string login_token_;
|
string login_token_;
|
||||||
double login_token_expires_at_ = 0;
|
double login_token_expires_at_ = 0;
|
||||||
|
|
||||||
@ -130,7 +130,7 @@ class AuthManager : public NetActor {
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
static DbState wait_qr_code_confirmation(int32 api_id, string api_hash, vector<int32> other_user_ids,
|
static DbState wait_qr_code_confirmation(int32 api_id, string api_hash, vector<UserId> other_user_ids,
|
||||||
string login_token, double login_token_expires_at) {
|
string login_token, double login_token_expires_at) {
|
||||||
DbState state(State::WaitQrCodeConfirmation, api_id, api_hash);
|
DbState state(State::WaitQrCodeConfirmation, api_id, api_hash);
|
||||||
state.other_user_ids_ = std::move(other_user_ids);
|
state.other_user_ids_ = std::move(other_user_ids);
|
||||||
@ -179,7 +179,7 @@ class AuthManager : public NetActor {
|
|||||||
string code_;
|
string code_;
|
||||||
|
|
||||||
// State::WaitQrCodeConfirmation
|
// State::WaitQrCodeConfirmation
|
||||||
vector<int32> other_user_ids_;
|
vector<UserId> other_user_ids_;
|
||||||
string login_token_;
|
string login_token_;
|
||||||
double login_token_expires_at_ = 0.0;
|
double login_token_expires_at_ = 0.0;
|
||||||
int32 imported_dc_id_ = -1;
|
int32 imported_dc_id_ = -1;
|
||||||
|
@ -243,7 +243,7 @@ int64 CallbackQueriesManager::send_callback_query(FullMessageId full_message_id,
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto dialog_id = full_message_id.get_dialog_id();
|
auto dialog_id = full_message_id.get_dialog_id();
|
||||||
td_->messages_manager_->have_dialog_force(dialog_id);
|
td_->messages_manager_->have_dialog_force(dialog_id, "send_callback_query");
|
||||||
if (!td_->messages_manager_->have_input_peer(dialog_id, AccessRights::Read)) {
|
if (!td_->messages_manager_->have_input_peer(dialog_id, AccessRights::Read)) {
|
||||||
promise.set_error(Status::Error(5, "Can't access the chat"));
|
promise.set_error(Status::Error(5, "Can't access the chat"));
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -278,7 +278,7 @@ class TdReceiver {
|
|||||||
if (is_locked) {
|
if (is_locked) {
|
||||||
LOG(FATAL) << "Receive is called after Client destroy, or simultaneously from different threads";
|
LOG(FATAL) << "Receive is called after Client destroy, or simultaneously from different threads";
|
||||||
}
|
}
|
||||||
auto response = receive_unlocked(timeout);
|
auto response = receive_unlocked(clamp(timeout, 0.0, 1000000.0));
|
||||||
is_locked = receive_lock_.exchange(false);
|
is_locked = receive_lock_.exchange(false);
|
||||||
CHECK(is_locked);
|
CHECK(is_locked);
|
||||||
VLOG(td_requests) << "End to wait for updates, returning object " << response.request_id << ' '
|
VLOG(td_requests) << "End to wait for updates, returning object " << response.request_id << ' '
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include "td/telegram/Global.h"
|
#include "td/telegram/Global.h"
|
||||||
#include "td/telegram/JsonValue.h"
|
#include "td/telegram/JsonValue.h"
|
||||||
#include "td/telegram/logevent/LogEvent.h"
|
#include "td/telegram/logevent/LogEvent.h"
|
||||||
|
#include "td/telegram/MessagesManager.h"
|
||||||
#include "td/telegram/net/AuthDataShared.h"
|
#include "td/telegram/net/AuthDataShared.h"
|
||||||
#include "td/telegram/net/ConnectionCreator.h"
|
#include "td/telegram/net/ConnectionCreator.h"
|
||||||
#include "td/telegram/net/DcId.h"
|
#include "td/telegram/net/DcId.h"
|
||||||
@ -891,6 +892,8 @@ void ConfigManager::start_up() {
|
|||||||
|
|
||||||
autologin_update_time_ = Time::now() - 365 * 86400;
|
autologin_update_time_ = Time::now() - 365 * 86400;
|
||||||
autologin_domains_ = full_split(G()->td_db()->get_binlog_pmc()->get("autologin_domains"), '\xFF');
|
autologin_domains_ = full_split(G()->td_db()->get_binlog_pmc()->get("autologin_domains"), '\xFF');
|
||||||
|
|
||||||
|
url_auth_domains_ = full_split(G()->td_db()->get_binlog_pmc()->get("url_auth_domains"), '\xFF');
|
||||||
}
|
}
|
||||||
|
|
||||||
ActorShared<> ConfigManager::create_reference() {
|
ActorShared<> ConfigManager::create_reference() {
|
||||||
@ -967,33 +970,38 @@ void ConfigManager::get_app_config(Promise<td_api::object_ptr<td_api::JsonValue>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigManager::get_external_link(string &&link, Promise<string> &&promise) {
|
void ConfigManager::get_external_link_info(string &&link, Promise<td_api::object_ptr<td_api::LoginUrlInfo>> &&promise) {
|
||||||
|
auto default_result = td_api::make_object<td_api::loginUrlInfoOpen>(link, false);
|
||||||
if (G()->close_flag()) {
|
if (G()->close_flag()) {
|
||||||
return promise.set_value(std::move(link));
|
return promise.set_value(std::move(default_result));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto r_url = parse_url(link);
|
auto r_url = parse_url(link);
|
||||||
if (r_url.is_error()) {
|
if (r_url.is_error()) {
|
||||||
return promise.set_value(std::move(link));
|
return promise.set_value(std::move(default_result));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!td::contains(autologin_domains_, r_url.ok().host_)) {
|
if (!td::contains(autologin_domains_, r_url.ok().host_)) {
|
||||||
return promise.set_value(std::move(link));
|
if (td::contains(url_auth_domains_, r_url.ok().host_)) {
|
||||||
|
send_closure(G()->messages_manager(), &MessagesManager::get_link_login_url_info, link, std::move(promise));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return promise.set_value(std::move(default_result));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (autologin_update_time_ < Time::now() - 10000) {
|
if (autologin_update_time_ < Time::now() - 10000) {
|
||||||
auto query_promise = PromiseCreator::lambda([link = std::move(link), promise = std::move(promise)](
|
auto query_promise = PromiseCreator::lambda([link = std::move(link), promise = std::move(promise)](
|
||||||
Result<td_api::object_ptr<td_api::JsonValue>> &&result) mutable {
|
Result<td_api::object_ptr<td_api::JsonValue>> &&result) mutable {
|
||||||
if (result.is_error()) {
|
if (result.is_error()) {
|
||||||
return promise.set_value(std::move(link));
|
return promise.set_value(td_api::make_object<td_api::loginUrlInfoOpen>(link, false));
|
||||||
}
|
}
|
||||||
send_closure(G()->config_manager(), &ConfigManager::get_external_link, std::move(link), std::move(promise));
|
send_closure(G()->config_manager(), &ConfigManager::get_external_link_info, std::move(link), std::move(promise));
|
||||||
});
|
});
|
||||||
return get_app_config(std::move(query_promise));
|
return get_app_config(std::move(query_promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (autologin_token_.empty()) {
|
if (autologin_token_.empty()) {
|
||||||
return promise.set_value(std::move(link));
|
return promise.set_value(std::move(default_result));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto url = r_url.move_as_ok();
|
auto url = r_url.move_as_ok();
|
||||||
@ -1018,7 +1026,7 @@ void ConfigManager::get_external_link(string &&link, Promise<string> &&promise)
|
|||||||
|
|
||||||
url.query_ = PSTRING() << path << parameters << added_parameter << hash;
|
url.query_ = PSTRING() << path << parameters << added_parameter << hash;
|
||||||
|
|
||||||
promise.set_value(url.get_url());
|
promise.set_value(td_api::make_object<td_api::loginUrlInfoOpen>(url.get_url(), false));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigManager::get_content_settings(Promise<Unit> &&promise) {
|
void ConfigManager::get_content_settings(Promise<Unit> &&promise) {
|
||||||
@ -1524,6 +1532,9 @@ void ConfigManager::process_app_config(tl_object_ptr<telegram_api::JSONValue> &c
|
|||||||
autologin_domains_.clear();
|
autologin_domains_.clear();
|
||||||
autologin_update_time_ = Time::now();
|
autologin_update_time_ = Time::now();
|
||||||
|
|
||||||
|
auto old_url_auth_domains = std::move(url_auth_domains_);
|
||||||
|
url_auth_domains_.clear();
|
||||||
|
|
||||||
vector<tl_object_ptr<telegram_api::jsonObjectValue>> new_values;
|
vector<tl_object_ptr<telegram_api::jsonObjectValue>> new_values;
|
||||||
string ignored_restriction_reasons;
|
string ignored_restriction_reasons;
|
||||||
vector<string> dice_emojis;
|
vector<string> dice_emojis;
|
||||||
@ -1714,6 +1725,22 @@ void ConfigManager::process_app_config(tl_object_ptr<telegram_api::JSONValue> &c
|
|||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (key == "url_auth_domains") {
|
||||||
|
if (value->get_id() == telegram_api::jsonArray::ID) {
|
||||||
|
auto domains = std::move(static_cast<telegram_api::jsonArray *>(value)->value_);
|
||||||
|
for (auto &domain : domains) {
|
||||||
|
CHECK(domain != nullptr);
|
||||||
|
if (domain->get_id() == telegram_api::jsonString::ID) {
|
||||||
|
url_auth_domains_.push_back(std::move(static_cast<telegram_api::jsonString *>(domain.get())->value_));
|
||||||
|
} else {
|
||||||
|
LOG(ERROR) << "Receive unexpected url auth domain " << to_string(domain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOG(ERROR) << "Receive unexpected url_auth_domains " << to_string(*value);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
new_values.push_back(std::move(key_value));
|
new_values.push_back(std::move(key_value));
|
||||||
}
|
}
|
||||||
@ -1725,6 +1752,9 @@ void ConfigManager::process_app_config(tl_object_ptr<telegram_api::JSONValue> &c
|
|||||||
if (autologin_domains_ != old_autologin_domains) {
|
if (autologin_domains_ != old_autologin_domains) {
|
||||||
G()->td_db()->get_binlog_pmc()->set("autologin_domains", implode(autologin_domains_, '\xFF'));
|
G()->td_db()->get_binlog_pmc()->set("autologin_domains", implode(autologin_domains_, '\xFF'));
|
||||||
}
|
}
|
||||||
|
if (url_auth_domains_ != old_url_auth_domains) {
|
||||||
|
G()->td_db()->get_binlog_pmc()->set("url_auth_domains", implode(url_auth_domains_, '\xFF'));
|
||||||
|
}
|
||||||
|
|
||||||
ConfigShared &shared_config = G()->shared_config();
|
ConfigShared &shared_config = G()->shared_config();
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ class ConfigManager : public NetQueryCallback {
|
|||||||
|
|
||||||
void get_app_config(Promise<td_api::object_ptr<td_api::JsonValue>> &&promise);
|
void get_app_config(Promise<td_api::object_ptr<td_api::JsonValue>> &&promise);
|
||||||
|
|
||||||
void get_external_link(string &&link, Promise<string> &&promise);
|
void get_external_link_info(string &&link, Promise<td_api::object_ptr<td_api::LoginUrlInfo>> &&promise);
|
||||||
|
|
||||||
void get_content_settings(Promise<Unit> &&promise);
|
void get_content_settings(Promise<Unit> &&promise);
|
||||||
|
|
||||||
@ -119,6 +119,7 @@ class ConfigManager : public NetQueryCallback {
|
|||||||
string autologin_token_;
|
string autologin_token_;
|
||||||
vector<string> autologin_domains_;
|
vector<string> autologin_domains_;
|
||||||
double autologin_update_time_ = 0.0;
|
double autologin_update_time_ = 0.0;
|
||||||
|
vector<string> url_auth_domains_;
|
||||||
|
|
||||||
FloodControlStrict lazy_request_flood_control_;
|
FloodControlStrict lazy_request_flood_control_;
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
|
|
||||||
Contact::Contact(string phone_number, string first_name, string last_name, string vcard, int32 user_id)
|
Contact::Contact(string phone_number, string first_name, string last_name, string vcard, UserId user_id)
|
||||||
: phone_number_(std::move(phone_number))
|
: phone_number_(std::move(phone_number))
|
||||||
, first_name_(std::move(first_name))
|
, first_name_(std::move(first_name))
|
||||||
, last_name_(std::move(last_name))
|
, last_name_(std::move(last_name))
|
||||||
@ -58,7 +58,11 @@ tl_object_ptr<telegram_api::inputPhoneContact> Contact::get_input_phone_contact(
|
|||||||
}
|
}
|
||||||
|
|
||||||
tl_object_ptr<telegram_api::inputBotInlineMessageMediaContact> Contact::get_input_bot_inline_message_media_contact(
|
tl_object_ptr<telegram_api::inputBotInlineMessageMediaContact> Contact::get_input_bot_inline_message_media_contact(
|
||||||
int32 flags, tl_object_ptr<telegram_api::ReplyMarkup> &&reply_markup) const {
|
tl_object_ptr<telegram_api::ReplyMarkup> &&reply_markup) const {
|
||||||
|
int32 flags = 0;
|
||||||
|
if (reply_markup != nullptr) {
|
||||||
|
flags |= telegram_api::inputBotInlineMessageMediaContact::REPLY_MARKUP_MASK;
|
||||||
|
}
|
||||||
return make_tl_object<telegram_api::inputBotInlineMessageMediaContact>(flags, phone_number_, first_name_, last_name_,
|
return make_tl_object<telegram_api::inputBotInlineMessageMediaContact>(flags, phone_number_, first_name_, last_name_,
|
||||||
vcard_, std::move(reply_markup));
|
vcard_, std::move(reply_markup));
|
||||||
}
|
}
|
||||||
@ -96,7 +100,8 @@ Result<Contact> process_input_message_contact(tl_object_ptr<td_api::InputMessage
|
|||||||
return Status::Error(400, "vCard must be encoded in UTF-8");
|
return Status::Error(400, "vCard must be encoded in UTF-8");
|
||||||
}
|
}
|
||||||
|
|
||||||
return Contact(contact->phone_number_, contact->first_name_, contact->last_name_, contact->vcard_, contact->user_id_);
|
return Contact(contact->phone_number_, contact->first_name_, contact->last_name_, contact->vcard_,
|
||||||
|
UserId(contact->user_id_));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace td
|
} // namespace td
|
||||||
|
@ -40,7 +40,7 @@ class Contact {
|
|||||||
public:
|
public:
|
||||||
Contact() = default;
|
Contact() = default;
|
||||||
|
|
||||||
Contact(string phone_number, string first_name, string last_name, string vcard, int32 user_id);
|
Contact(string phone_number, string first_name, string last_name, string vcard, UserId user_id);
|
||||||
|
|
||||||
void set_user_id(UserId user_id);
|
void set_user_id(UserId user_id);
|
||||||
|
|
||||||
@ -57,7 +57,7 @@ class Contact {
|
|||||||
tl_object_ptr<telegram_api::inputPhoneContact> get_input_phone_contact(int64 client_id) const;
|
tl_object_ptr<telegram_api::inputPhoneContact> get_input_phone_contact(int64 client_id) const;
|
||||||
|
|
||||||
tl_object_ptr<telegram_api::inputBotInlineMessageMediaContact> get_input_bot_inline_message_media_contact(
|
tl_object_ptr<telegram_api::inputBotInlineMessageMediaContact> get_input_bot_inline_message_media_contact(
|
||||||
int32 flags, tl_object_ptr<telegram_api::ReplyMarkup> &&reply_markup) const;
|
tl_object_ptr<telegram_api::ReplyMarkup> &&reply_markup) const;
|
||||||
|
|
||||||
template <class StorerT>
|
template <class StorerT>
|
||||||
void store(StorerT &storer) const {
|
void store(StorerT &storer) const {
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -132,6 +132,8 @@ class ContactsManager : public Actor {
|
|||||||
RestrictedRights get_channel_default_permissions(ChannelId channel_id) const;
|
RestrictedRights get_channel_default_permissions(ChannelId channel_id) const;
|
||||||
RestrictedRights get_secret_chat_default_permissions(SecretChatId secret_chat_id) const;
|
RestrictedRights get_secret_chat_default_permissions(SecretChatId secret_chat_id) const;
|
||||||
|
|
||||||
|
string get_dialog_about(DialogId dialog_id);
|
||||||
|
|
||||||
bool is_update_about_username_change_received(UserId user_id) const;
|
bool is_update_about_username_change_received(UserId user_id) const;
|
||||||
|
|
||||||
void for_each_secret_chat_with_user(UserId user_id, std::function<void(SecretChatId)> f);
|
void for_each_secret_chat_with_user(UserId user_id, std::function<void(SecretChatId)> f);
|
||||||
@ -179,6 +181,8 @@ class ContactsManager : public Actor {
|
|||||||
void on_get_chats(vector<tl_object_ptr<telegram_api::Chat>> &&chats, const char *source);
|
void on_get_chats(vector<tl_object_ptr<telegram_api::Chat>> &&chats, const char *source);
|
||||||
|
|
||||||
void on_get_chat_full(tl_object_ptr<telegram_api::ChatFull> &&chat_full, Promise<Unit> &&promise);
|
void on_get_chat_full(tl_object_ptr<telegram_api::ChatFull> &&chat_full, Promise<Unit> &&promise);
|
||||||
|
void on_get_chat_full_failed(ChatId chat_id);
|
||||||
|
void on_get_channel_full_failed(ChannelId channel_id);
|
||||||
|
|
||||||
void on_update_profile_success(int32 flags, const string &first_name, const string &last_name, const string &about);
|
void on_update_profile_success(int32 flags, const string &first_name, const string &last_name, const string &about);
|
||||||
void on_set_bot_commands_success(vector<std::pair<string, string>> &&commands);
|
void on_set_bot_commands_success(vector<std::pair<string, string>> &&commands);
|
||||||
@ -235,7 +239,7 @@ class ContactsManager : public Actor {
|
|||||||
|
|
||||||
void speculative_delete_channel_participant(ChannelId channel_id, UserId deleted_user_id, bool by_me);
|
void speculative_delete_channel_participant(ChannelId channel_id, UserId deleted_user_id, bool by_me);
|
||||||
|
|
||||||
void invalidate_channel_full(ChannelId channel_id, bool need_drop_invite_link, bool need_drop_slow_mode_delay);
|
void invalidate_channel_full(ChannelId channel_id, bool need_drop_slow_mode_delay);
|
||||||
|
|
||||||
bool on_get_channel_error(ChannelId channel_id, const Status &status, const string &source);
|
bool on_get_channel_error(ChannelId channel_id, const Status &status, const string &source);
|
||||||
|
|
||||||
@ -514,19 +518,21 @@ class ContactsManager : public Actor {
|
|||||||
ChannelId get_channel_linked_channel_id(ChannelId channel_id);
|
ChannelId get_channel_linked_channel_id(ChannelId channel_id);
|
||||||
int32 get_channel_slow_mode_delay(ChannelId channel_id);
|
int32 get_channel_slow_mode_delay(ChannelId channel_id);
|
||||||
|
|
||||||
|
static DialogId get_participant_dialog_id(const td_api::object_ptr<td_api::MessageSender> &participant_id);
|
||||||
|
|
||||||
void add_dialog_participant(DialogId dialog_id, UserId user_id, int32 forward_limit, Promise<Unit> &&promise);
|
void add_dialog_participant(DialogId dialog_id, UserId user_id, int32 forward_limit, Promise<Unit> &&promise);
|
||||||
|
|
||||||
void add_dialog_participants(DialogId dialog_id, const vector<UserId> &user_ids, Promise<Unit> &&promise);
|
void add_dialog_participants(DialogId dialog_id, const vector<UserId> &user_ids, Promise<Unit> &&promise);
|
||||||
|
|
||||||
void set_dialog_participant_status(DialogId dialog_id, UserId user_id,
|
void set_dialog_participant_status(DialogId dialog_id, DialogId participant_dialog_id,
|
||||||
const tl_object_ptr<td_api::ChatMemberStatus> &chat_member_status,
|
const tl_object_ptr<td_api::ChatMemberStatus> &chat_member_status,
|
||||||
Promise<Unit> &&promise);
|
Promise<Unit> &&promise);
|
||||||
|
|
||||||
void ban_dialog_participant(DialogId dialog_id, UserId user_id, int32 banned_until_date, bool revoke_messages,
|
void ban_dialog_participant(DialogId dialog_id, DialogId participant_dialog_id, int32 banned_until_date,
|
||||||
Promise<Unit> &&promise);
|
bool revoke_messages, Promise<Unit> &&promise);
|
||||||
|
|
||||||
DialogParticipant get_dialog_participant(DialogId dialog_id, UserId user_id, int64 &random_id, bool force,
|
DialogParticipant get_dialog_participant(DialogId dialog_id, DialogId participant_dialog_id, int64 &random_id,
|
||||||
Promise<Unit> &&promise);
|
bool force, Promise<Unit> &&promise);
|
||||||
|
|
||||||
void search_dialog_participants(DialogId dialog_id, const string &query, int32 limit, DialogParticipantsFilter filter,
|
void search_dialog_participants(DialogId dialog_id, const string &query, int32 limit, DialogParticipantsFilter filter,
|
||||||
bool without_bot_info, Promise<DialogParticipants> &&promise);
|
bool without_bot_info, Promise<DialogParticipants> &&promise);
|
||||||
@ -1254,7 +1260,7 @@ class ContactsManager : public Actor {
|
|||||||
|
|
||||||
static bool speculative_add_count(int32 &count, int32 delta_count, int32 min_count = 0);
|
static bool speculative_add_count(int32 &count, int32 delta_count, int32 min_count = 0);
|
||||||
|
|
||||||
void speculative_add_channel_participants(ChannelId channel_id, int32 delta_participant_count, bool by_me);
|
void speculative_add_channel_participant_count(ChannelId channel_id, int32 delta_participant_count, bool by_me);
|
||||||
|
|
||||||
void speculative_add_channel_user(ChannelId channel_id, UserId user_id, DialogParticipantStatus new_status,
|
void speculative_add_channel_user(ChannelId channel_id, UserId user_id, DialogParticipantStatus new_status,
|
||||||
DialogParticipantStatus old_status);
|
DialogParticipantStatus old_status);
|
||||||
@ -1334,7 +1340,7 @@ class ContactsManager : public Actor {
|
|||||||
void save_channel_full(const ChannelFull *channel_full, ChannelId channel_id);
|
void save_channel_full(const ChannelFull *channel_full, ChannelId channel_id);
|
||||||
static string get_channel_full_database_key(ChannelId channel_id);
|
static string get_channel_full_database_key(ChannelId channel_id);
|
||||||
static string get_channel_full_database_value(const ChannelFull *channel_full);
|
static string get_channel_full_database_value(const ChannelFull *channel_full);
|
||||||
void on_load_channel_full_from_database(ChannelId channel_id, string value);
|
void on_load_channel_full_from_database(ChannelId channel_id, string value, const char *source);
|
||||||
|
|
||||||
void update_user(User *u, UserId user_id, bool from_binlog = false, bool from_database = false);
|
void update_user(User *u, UserId user_id, bool from_binlog = false, bool from_database = false);
|
||||||
void update_chat(Chat *c, ChatId chat_id, bool from_binlog = false, bool from_database = false);
|
void update_chat(Chat *c, ChatId chat_id, bool from_binlog = false, bool from_database = false);
|
||||||
@ -1411,15 +1417,15 @@ class ContactsManager : public Actor {
|
|||||||
void add_chat_participant(ChatId chat_id, UserId user_id, int32 forward_limit, Promise<Unit> &&promise);
|
void add_chat_participant(ChatId chat_id, UserId user_id, int32 forward_limit, Promise<Unit> &&promise);
|
||||||
|
|
||||||
void add_channel_participant(ChannelId channel_id, UserId user_id, Promise<Unit> &&promise,
|
void add_channel_participant(ChannelId channel_id, UserId user_id, Promise<Unit> &&promise,
|
||||||
DialogParticipantStatus old_status = DialogParticipantStatus::Left());
|
DialogParticipantStatus old_status);
|
||||||
|
|
||||||
void add_channel_participants(ChannelId channel_id, const vector<UserId> &user_ids, Promise<Unit> &&promise);
|
void add_channel_participants(ChannelId channel_id, const vector<UserId> &user_ids, Promise<Unit> &&promise);
|
||||||
|
|
||||||
const DialogParticipant *get_chat_participant(ChatId chat_id, UserId user_id) const;
|
const DialogParticipant *get_chat_participant(ChatId chat_id, UserId user_id) const;
|
||||||
|
|
||||||
static const DialogParticipant *get_chat_full_participant(const ChatFull *chat_full, UserId user_id);
|
static const DialogParticipant *get_chat_full_participant(const ChatFull *chat_full, DialogId dialog_id);
|
||||||
|
|
||||||
std::pair<int32, vector<UserId>> search_among_users(const vector<UserId> &user_ids, const string &query,
|
std::pair<int32, vector<DialogId>> search_among_dialogs(const vector<DialogId> &dialog_ids, const string &query,
|
||||||
int32 limit) const;
|
int32 limit) const;
|
||||||
|
|
||||||
DialogParticipants search_private_chat_participants(UserId my_user_id, UserId peer_user_id, const string &query,
|
DialogParticipants search_private_chat_participants(UserId my_user_id, UserId peer_user_id, const string &query,
|
||||||
@ -1427,8 +1433,8 @@ class ContactsManager : public Actor {
|
|||||||
|
|
||||||
DialogParticipant get_chat_participant(ChatId chat_id, UserId user_id, bool force, Promise<Unit> &&promise);
|
DialogParticipant get_chat_participant(ChatId chat_id, UserId user_id, bool force, Promise<Unit> &&promise);
|
||||||
|
|
||||||
DialogParticipant get_channel_participant(ChannelId channel_id, UserId user_id, int64 &random_id, bool force,
|
DialogParticipant get_channel_participant(ChannelId channel_id, DialogId participant_dialog_id, int64 &random_id,
|
||||||
Promise<Unit> &&promise);
|
bool force, Promise<Unit> &&promise);
|
||||||
|
|
||||||
static string get_dialog_administrators_database_key(DialogId dialog_id);
|
static string get_dialog_administrators_database_key(DialogId dialog_id);
|
||||||
|
|
||||||
@ -1488,8 +1494,8 @@ class ContactsManager : public Actor {
|
|||||||
void change_chat_participant_status(ChatId chat_id, UserId user_id, DialogParticipantStatus status,
|
void change_chat_participant_status(ChatId chat_id, UserId user_id, DialogParticipantStatus status,
|
||||||
Promise<Unit> &&promise);
|
Promise<Unit> &&promise);
|
||||||
|
|
||||||
void change_channel_participant_status(ChannelId channel_id, UserId user_id, DialogParticipantStatus status,
|
void change_channel_participant_status(ChannelId channel_id, DialogId participant_dialog_id,
|
||||||
Promise<Unit> &&promise);
|
DialogParticipantStatus status, Promise<Unit> &&promise);
|
||||||
|
|
||||||
void delete_chat_participant(ChatId chat_id, UserId user_id, bool revoke_messages, Promise<Unit> &&promise);
|
void delete_chat_participant(ChatId chat_id, UserId user_id, bool revoke_messages, Promise<Unit> &&promise);
|
||||||
|
|
||||||
@ -1508,14 +1514,16 @@ class ContactsManager : public Actor {
|
|||||||
tl_object_ptr<telegram_api::channels_channelParticipants> &&channel_participants,
|
tl_object_ptr<telegram_api::channels_channelParticipants> &&channel_participants,
|
||||||
Promise<DialogParticipants> &&promise);
|
Promise<DialogParticipants> &&promise);
|
||||||
|
|
||||||
void change_channel_participant_status_impl(ChannelId channel_id, UserId user_id, DialogParticipantStatus status,
|
void change_channel_participant_status_impl(ChannelId channel_id, DialogId participant_dialog_id,
|
||||||
DialogParticipantStatus old_status, Promise<Unit> &&promise);
|
DialogParticipantStatus status, DialogParticipantStatus old_status,
|
||||||
|
Promise<Unit> &&promise);
|
||||||
|
|
||||||
void promote_channel_participant(ChannelId channel_id, UserId user_id, DialogParticipantStatus status,
|
void promote_channel_participant(ChannelId channel_id, UserId user_id, DialogParticipantStatus status,
|
||||||
DialogParticipantStatus old_status, Promise<Unit> &&promise);
|
DialogParticipantStatus old_status, Promise<Unit> &&promise);
|
||||||
|
|
||||||
void restrict_channel_participant(ChannelId channel_id, UserId user_id, DialogParticipantStatus status,
|
void restrict_channel_participant(ChannelId channel_id, DialogId participant_dialog_id,
|
||||||
DialogParticipantStatus old_status, Promise<Unit> &&promise);
|
DialogParticipantStatus status, DialogParticipantStatus old_status,
|
||||||
|
Promise<Unit> &&promise);
|
||||||
|
|
||||||
void transfer_channel_ownership(ChannelId channel_id, UserId user_id,
|
void transfer_channel_ownership(ChannelId channel_id, UserId user_id,
|
||||||
tl_object_ptr<telegram_api::InputCheckPasswordSRP> input_check_password,
|
tl_object_ptr<telegram_api::InputCheckPasswordSRP> input_check_password,
|
||||||
|
@ -51,38 +51,46 @@ void add_message_sender_dependencies(Dependencies &dependencies, DialogId dialog
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void resolve_dependencies_force(Td *td, const Dependencies &dependencies, const char *source) {
|
bool resolve_dependencies_force(Td *td, const Dependencies &dependencies, const char *source) {
|
||||||
|
bool success = true;
|
||||||
for (auto user_id : dependencies.user_ids) {
|
for (auto user_id : dependencies.user_ids) {
|
||||||
if (user_id.is_valid() && !td->contacts_manager_->have_user_force(user_id)) {
|
if (user_id.is_valid() && !td->contacts_manager_->have_user_force(user_id)) {
|
||||||
LOG(ERROR) << "Can't find " << user_id << " from " << source;
|
LOG(ERROR) << "Can't find " << user_id << " from " << source;
|
||||||
|
success = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (auto chat_id : dependencies.chat_ids) {
|
for (auto chat_id : dependencies.chat_ids) {
|
||||||
if (chat_id.is_valid() && !td->contacts_manager_->have_chat_force(chat_id)) {
|
if (chat_id.is_valid() && !td->contacts_manager_->have_chat_force(chat_id)) {
|
||||||
LOG(ERROR) << "Can't find " << chat_id << " from " << source;
|
LOG(ERROR) << "Can't find " << chat_id << " from " << source;
|
||||||
|
success = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (auto channel_id : dependencies.channel_ids) {
|
for (auto channel_id : dependencies.channel_ids) {
|
||||||
if (channel_id.is_valid() && !td->contacts_manager_->have_channel_force(channel_id)) {
|
if (channel_id.is_valid() && !td->contacts_manager_->have_channel_force(channel_id)) {
|
||||||
LOG(ERROR) << "Can't find " << channel_id << " from " << source;
|
LOG(ERROR) << "Can't find " << channel_id << " from " << source;
|
||||||
|
success = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (auto secret_chat_id : dependencies.secret_chat_ids) {
|
for (auto secret_chat_id : dependencies.secret_chat_ids) {
|
||||||
if (secret_chat_id.is_valid() && !td->contacts_manager_->have_secret_chat_force(secret_chat_id)) {
|
if (secret_chat_id.is_valid() && !td->contacts_manager_->have_secret_chat_force(secret_chat_id)) {
|
||||||
LOG(ERROR) << "Can't find " << secret_chat_id << " from " << source;
|
LOG(ERROR) << "Can't find " << secret_chat_id << " from " << source;
|
||||||
|
success = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (auto dialog_id : dependencies.dialog_ids) {
|
for (auto dialog_id : dependencies.dialog_ids) {
|
||||||
if (dialog_id.is_valid() && !td->messages_manager_->have_dialog_force(dialog_id)) {
|
if (dialog_id.is_valid() && !td->messages_manager_->have_dialog_force(dialog_id, source)) {
|
||||||
LOG(ERROR) << "Can't find " << dialog_id << " from " << source;
|
LOG(ERROR) << "Can't find " << dialog_id << " from " << source;
|
||||||
td->messages_manager_->force_create_dialog(dialog_id, "resolve_dependencies_force");
|
td->messages_manager_->force_create_dialog(dialog_id, "resolve_dependencies_force", true);
|
||||||
|
success = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (auto web_page_id : dependencies.web_page_ids) {
|
for (auto web_page_id : dependencies.web_page_ids) {
|
||||||
if (web_page_id.is_valid()) {
|
if (web_page_id.is_valid()) {
|
||||||
td->web_pages_manager_->have_web_page_force(web_page_id);
|
td->web_pages_manager_->have_web_page_force(web_page_id);
|
||||||
|
success = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace td
|
} // namespace td
|
||||||
|
@ -34,6 +34,6 @@ void add_dialog_dependencies(Dependencies &dependencies, DialogId dialog_id);
|
|||||||
|
|
||||||
void add_message_sender_dependencies(Dependencies &dependencies, DialogId dialog_id);
|
void add_message_sender_dependencies(Dependencies &dependencies, DialogId dialog_id);
|
||||||
|
|
||||||
void resolve_dependencies_force(Td *td, const Dependencies &dependencies, const char *source);
|
bool resolve_dependencies_force(Td *td, const Dependencies &dependencies, const char *source);
|
||||||
|
|
||||||
} // namespace td
|
} // namespace td
|
||||||
|
@ -120,7 +120,7 @@ StringBuilder &operator<<(StringBuilder &string_builder, const DeviceTokenManage
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DeviceTokenManager::register_device(tl_object_ptr<td_api::DeviceToken> device_token_ptr,
|
void DeviceTokenManager::register_device(tl_object_ptr<td_api::DeviceToken> device_token_ptr,
|
||||||
vector<int32> other_user_ids,
|
vector<UserId> other_user_ids,
|
||||||
Promise<td_api::object_ptr<td_api::pushReceiverId>> promise) {
|
Promise<td_api::object_ptr<td_api::pushReceiverId>> promise) {
|
||||||
CHECK(device_token_ptr != nullptr);
|
CHECK(device_token_ptr != nullptr);
|
||||||
TokenType token_type;
|
TokenType token_type;
|
||||||
@ -227,8 +227,7 @@ void DeviceTokenManager::register_device(tl_object_ptr<td_api::DeviceToken> devi
|
|||||||
return promise.set_error(Status::Error(400, "Device token must be encoded in UTF-8"));
|
return promise.set_error(Status::Error(400, "Device token must be encoded in UTF-8"));
|
||||||
}
|
}
|
||||||
for (auto &other_user_id : other_user_ids) {
|
for (auto &other_user_id : other_user_ids) {
|
||||||
UserId user_id(other_user_id);
|
if (!other_user_id.is_valid()) {
|
||||||
if (!user_id.is_valid()) {
|
|
||||||
return promise.set_error(Status::Error(400, "Invalid user_id among other user_ids"));
|
return promise.set_error(Status::Error(400, "Invalid user_id among other user_ids"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -373,12 +372,12 @@ void DeviceTokenManager::loop() {
|
|||||||
auto other_user_ids = info.other_user_ids;
|
auto other_user_ids = info.other_user_ids;
|
||||||
if (info.state == TokenInfo::State::Unregister) {
|
if (info.state == TokenInfo::State::Unregister) {
|
||||||
net_query = G()->net_query_creator().create(
|
net_query = G()->net_query_creator().create(
|
||||||
telegram_api::account_unregisterDevice(token_type, info.token, std::move(other_user_ids)));
|
telegram_api::account_unregisterDevice(token_type, info.token, UserId::get_input_user_ids(other_user_ids)));
|
||||||
} else {
|
} else {
|
||||||
int32 flags = telegram_api::account_registerDevice::NO_MUTED_MASK;
|
int32 flags = telegram_api::account_registerDevice::NO_MUTED_MASK;
|
||||||
net_query = G()->net_query_creator().create(
|
net_query = G()->net_query_creator().create(telegram_api::account_registerDevice(
|
||||||
telegram_api::account_registerDevice(flags, false /*ignored*/, token_type, info.token, info.is_app_sandbox,
|
flags, false /*ignored*/, token_type, info.token, info.is_app_sandbox, BufferSlice(info.encryption_key),
|
||||||
BufferSlice(info.encryption_key), std::move(other_user_ids)));
|
UserId::get_input_user_ids(other_user_ids)));
|
||||||
}
|
}
|
||||||
info.net_query_id = net_query->id();
|
info.net_query_id = net_query->id();
|
||||||
G()->net_query_dispatcher().dispatch_with_callback(std::move(net_query), actor_shared(this, token_type));
|
G()->net_query_dispatcher().dispatch_with_callback(std::move(net_query), actor_shared(this, token_type));
|
||||||
|
@ -10,8 +10,8 @@
|
|||||||
#include "td/actor/PromiseFuture.h"
|
#include "td/actor/PromiseFuture.h"
|
||||||
|
|
||||||
#include "td/telegram/net/NetQuery.h"
|
#include "td/telegram/net/NetQuery.h"
|
||||||
|
|
||||||
#include "td/telegram/td_api.h"
|
#include "td/telegram/td_api.h"
|
||||||
|
#include "td/telegram/UserId.h"
|
||||||
|
|
||||||
#include "td/utils/common.h"
|
#include "td/utils/common.h"
|
||||||
#include "td/utils/Slice.h"
|
#include "td/utils/Slice.h"
|
||||||
@ -26,7 +26,7 @@ class DeviceTokenManager : public NetQueryCallback {
|
|||||||
public:
|
public:
|
||||||
explicit DeviceTokenManager(ActorShared<> parent) : parent_(std::move(parent)) {
|
explicit DeviceTokenManager(ActorShared<> parent) : parent_(std::move(parent)) {
|
||||||
}
|
}
|
||||||
void register_device(tl_object_ptr<td_api::DeviceToken> device_token_ptr, vector<int32> other_user_ids,
|
void register_device(tl_object_ptr<td_api::DeviceToken> device_token_ptr, vector<UserId> other_user_ids,
|
||||||
Promise<td_api::object_ptr<td_api::pushReceiverId>> promise);
|
Promise<td_api::object_ptr<td_api::pushReceiverId>> promise);
|
||||||
|
|
||||||
void reregister_device();
|
void reregister_device();
|
||||||
@ -55,7 +55,7 @@ class DeviceTokenManager : public NetQueryCallback {
|
|||||||
State state = State::Sync;
|
State state = State::Sync;
|
||||||
string token;
|
string token;
|
||||||
uint64 net_query_id = 0;
|
uint64 net_query_id = 0;
|
||||||
vector<int32> other_user_ids;
|
vector<UserId> other_user_ids;
|
||||||
bool is_app_sandbox = false;
|
bool is_app_sandbox = false;
|
||||||
bool encrypt = false;
|
bool encrypt = false;
|
||||||
string encryption_key;
|
string encryption_key;
|
||||||
|
@ -90,15 +90,15 @@ Status DialogFilter::check_limits() const {
|
|||||||
|
|
||||||
if (excluded_server_dialog_count > MAX_INCLUDED_FILTER_DIALOGS ||
|
if (excluded_server_dialog_count > MAX_INCLUDED_FILTER_DIALOGS ||
|
||||||
excluded_secret_dialog_count > MAX_INCLUDED_FILTER_DIALOGS) {
|
excluded_secret_dialog_count > MAX_INCLUDED_FILTER_DIALOGS) {
|
||||||
return Status::Error(400, "Maximum number of excluded chats exceeded");
|
return Status::Error(400, "The maximum number of excluded chats exceeded");
|
||||||
}
|
}
|
||||||
if (included_server_dialog_count > MAX_INCLUDED_FILTER_DIALOGS ||
|
if (included_server_dialog_count > MAX_INCLUDED_FILTER_DIALOGS ||
|
||||||
included_secret_dialog_count > MAX_INCLUDED_FILTER_DIALOGS) {
|
included_secret_dialog_count > MAX_INCLUDED_FILTER_DIALOGS) {
|
||||||
return Status::Error(400, "Maximum number of included chats exceeded");
|
return Status::Error(400, "The maximum number of included chats exceeded");
|
||||||
}
|
}
|
||||||
if (included_server_dialog_count + pinned_server_dialog_count > MAX_INCLUDED_FILTER_DIALOGS ||
|
if (included_server_dialog_count + pinned_server_dialog_count > MAX_INCLUDED_FILTER_DIALOGS ||
|
||||||
included_secret_dialog_count + pinned_secret_dialog_count > MAX_INCLUDED_FILTER_DIALOGS) {
|
included_secret_dialog_count + pinned_secret_dialog_count > MAX_INCLUDED_FILTER_DIALOGS) {
|
||||||
return Status::Error(400, "Maximum number of pinned chats exceeded");
|
return Status::Error(400, "The maximum number of pinned chats exceeded");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_empty(false)) {
|
if (is_empty(false)) {
|
||||||
|
@ -642,9 +642,9 @@ RestrictedRights get_restricted_rights(const td_api::object_ptr<td_api::chatPerm
|
|||||||
permissions->can_pin_messages_);
|
permissions->can_pin_messages_);
|
||||||
}
|
}
|
||||||
|
|
||||||
DialogParticipant::DialogParticipant(UserId user_id, UserId inviter_user_id, int32 joined_date,
|
DialogParticipant::DialogParticipant(DialogId dialog_id, UserId inviter_user_id, int32 joined_date,
|
||||||
DialogParticipantStatus status)
|
DialogParticipantStatus status)
|
||||||
: user_id(user_id), inviter_user_id(inviter_user_id), joined_date(joined_date), status(status) {
|
: dialog_id(dialog_id), inviter_user_id(inviter_user_id), joined_date(joined_date), status(status) {
|
||||||
if (!inviter_user_id.is_valid() && inviter_user_id != UserId()) {
|
if (!inviter_user_id.is_valid() && inviter_user_id != UserId()) {
|
||||||
LOG(ERROR) << "Receive inviter " << inviter_user_id;
|
LOG(ERROR) << "Receive inviter " << inviter_user_id;
|
||||||
inviter_user_id = UserId();
|
inviter_user_id = UserId();
|
||||||
@ -660,19 +660,19 @@ DialogParticipant::DialogParticipant(tl_object_ptr<telegram_api::ChatParticipant
|
|||||||
switch (participant_ptr->get_id()) {
|
switch (participant_ptr->get_id()) {
|
||||||
case telegram_api::chatParticipant::ID: {
|
case telegram_api::chatParticipant::ID: {
|
||||||
auto participant = move_tl_object_as<telegram_api::chatParticipant>(participant_ptr);
|
auto participant = move_tl_object_as<telegram_api::chatParticipant>(participant_ptr);
|
||||||
*this = {UserId(participant->user_id_), UserId(participant->inviter_id_), participant->date_,
|
*this = {DialogId(UserId(participant->user_id_)), UserId(participant->inviter_id_), participant->date_,
|
||||||
DialogParticipantStatus::Member()};
|
DialogParticipantStatus::Member()};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case telegram_api::chatParticipantCreator::ID: {
|
case telegram_api::chatParticipantCreator::ID: {
|
||||||
auto participant = move_tl_object_as<telegram_api::chatParticipantCreator>(participant_ptr);
|
auto participant = move_tl_object_as<telegram_api::chatParticipantCreator>(participant_ptr);
|
||||||
*this = {UserId(participant->user_id_), UserId(participant->user_id_), chat_creation_date,
|
*this = {DialogId(UserId(participant->user_id_)), UserId(participant->user_id_), chat_creation_date,
|
||||||
DialogParticipantStatus::Creator(true, false, string())};
|
DialogParticipantStatus::Creator(true, false, string())};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case telegram_api::chatParticipantAdmin::ID: {
|
case telegram_api::chatParticipantAdmin::ID: {
|
||||||
auto participant = move_tl_object_as<telegram_api::chatParticipantAdmin>(participant_ptr);
|
auto participant = move_tl_object_as<telegram_api::chatParticipantAdmin>(participant_ptr);
|
||||||
*this = {UserId(participant->user_id_), UserId(participant->inviter_id_), participant->date_,
|
*this = {DialogId(UserId(participant->user_id_)), UserId(participant->inviter_id_), participant->date_,
|
||||||
DialogParticipantStatus::GroupAdministrator(is_creator)};
|
DialogParticipantStatus::GroupAdministrator(is_creator)};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -683,42 +683,44 @@ DialogParticipant::DialogParticipant(tl_object_ptr<telegram_api::ChatParticipant
|
|||||||
|
|
||||||
DialogParticipant::DialogParticipant(tl_object_ptr<telegram_api::ChannelParticipant> &&participant_ptr) {
|
DialogParticipant::DialogParticipant(tl_object_ptr<telegram_api::ChannelParticipant> &&participant_ptr) {
|
||||||
CHECK(participant_ptr != nullptr);
|
CHECK(participant_ptr != nullptr);
|
||||||
|
|
||||||
switch (participant_ptr->get_id()) {
|
switch (participant_ptr->get_id()) {
|
||||||
case telegram_api::channelParticipant::ID: {
|
case telegram_api::channelParticipant::ID: {
|
||||||
auto participant = move_tl_object_as<telegram_api::channelParticipant>(participant_ptr);
|
auto participant = move_tl_object_as<telegram_api::channelParticipant>(participant_ptr);
|
||||||
*this = {UserId(participant->user_id_), UserId(), participant->date_, DialogParticipantStatus::Member()};
|
*this = {DialogId(UserId(participant->user_id_)), UserId(), participant->date_,
|
||||||
|
DialogParticipantStatus::Member()};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case telegram_api::channelParticipantSelf::ID: {
|
case telegram_api::channelParticipantSelf::ID: {
|
||||||
auto participant = move_tl_object_as<telegram_api::channelParticipantSelf>(participant_ptr);
|
auto participant = move_tl_object_as<telegram_api::channelParticipantSelf>(participant_ptr);
|
||||||
*this = {UserId(participant->user_id_), UserId(participant->inviter_id_), participant->date_,
|
*this = {DialogId(UserId(participant->user_id_)), UserId(participant->inviter_id_), participant->date_,
|
||||||
DialogParticipantStatus::Member()};
|
DialogParticipantStatus::Member()};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case telegram_api::channelParticipantCreator::ID: {
|
case telegram_api::channelParticipantCreator::ID: {
|
||||||
auto participant = move_tl_object_as<telegram_api::channelParticipantCreator>(participant_ptr);
|
auto participant = move_tl_object_as<telegram_api::channelParticipantCreator>(participant_ptr);
|
||||||
bool is_anonymous = (participant->admin_rights_->flags_ & telegram_api::chatAdminRights::ANONYMOUS_MASK) != 0;
|
bool is_anonymous = (participant->admin_rights_->flags_ & telegram_api::chatAdminRights::ANONYMOUS_MASK) != 0;
|
||||||
*this = {UserId(participant->user_id_), UserId(), 0,
|
*this = {DialogId(UserId(participant->user_id_)), UserId(), 0,
|
||||||
DialogParticipantStatus::Creator(true, is_anonymous, std::move(participant->rank_))};
|
DialogParticipantStatus::Creator(true, is_anonymous, std::move(participant->rank_))};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case telegram_api::channelParticipantAdmin::ID: {
|
case telegram_api::channelParticipantAdmin::ID: {
|
||||||
auto participant = move_tl_object_as<telegram_api::channelParticipantAdmin>(participant_ptr);
|
auto participant = move_tl_object_as<telegram_api::channelParticipantAdmin>(participant_ptr);
|
||||||
bool can_be_edited = (participant->flags_ & telegram_api::channelParticipantAdmin::CAN_EDIT_MASK) != 0;
|
bool can_be_edited = (participant->flags_ & telegram_api::channelParticipantAdmin::CAN_EDIT_MASK) != 0;
|
||||||
*this = {UserId(participant->user_id_), UserId(participant->promoted_by_), participant->date_,
|
*this = {DialogId(UserId(participant->user_id_)), UserId(participant->promoted_by_), participant->date_,
|
||||||
get_dialog_participant_status(can_be_edited, std::move(participant->admin_rights_),
|
get_dialog_participant_status(can_be_edited, std::move(participant->admin_rights_),
|
||||||
std::move(participant->rank_))};
|
std::move(participant->rank_))};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case telegram_api::channelParticipantLeft::ID: {
|
case telegram_api::channelParticipantLeft::ID: {
|
||||||
auto participant = move_tl_object_as<telegram_api::channelParticipantLeft>(participant_ptr);
|
auto participant = move_tl_object_as<telegram_api::channelParticipantLeft>(participant_ptr);
|
||||||
*this = {UserId(participant->user_id_), UserId(), 0, DialogParticipantStatus::Left()};
|
*this = {DialogId(participant->peer_), UserId(), 0, DialogParticipantStatus::Left()};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case telegram_api::channelParticipantBanned::ID: {
|
case telegram_api::channelParticipantBanned::ID: {
|
||||||
auto participant = move_tl_object_as<telegram_api::channelParticipantBanned>(participant_ptr);
|
auto participant = move_tl_object_as<telegram_api::channelParticipantBanned>(participant_ptr);
|
||||||
auto is_member = (participant->flags_ & telegram_api::channelParticipantBanned::LEFT_MASK) == 0;
|
auto is_member = (participant->flags_ & telegram_api::channelParticipantBanned::LEFT_MASK) == 0;
|
||||||
*this = {UserId(participant->user_id_), UserId(participant->kicked_by_), participant->date_,
|
*this = {DialogId(participant->peer_), UserId(participant->kicked_by_), participant->date_,
|
||||||
get_dialog_participant_status(is_member, std::move(participant->banned_rights_))};
|
get_dialog_participant_status(is_member, std::move(participant->banned_rights_))};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -729,7 +731,7 @@ DialogParticipant::DialogParticipant(tl_object_ptr<telegram_api::ChannelParticip
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool DialogParticipant::is_valid() const {
|
bool DialogParticipant::is_valid() const {
|
||||||
if (!user_id.is_valid() || joined_date < 0) {
|
if (!dialog_id.is_valid() || joined_date < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (status.is_restricted() || status.is_banned() || (status.is_administrator() && !status.is_creator())) {
|
if (status.is_restricted() || status.is_banned() || (status.is_administrator() && !status.is_creator())) {
|
||||||
@ -739,7 +741,7 @@ bool DialogParticipant::is_valid() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder &operator<<(StringBuilder &string_builder, const DialogParticipant &dialog_participant) {
|
StringBuilder &operator<<(StringBuilder &string_builder, const DialogParticipant &dialog_participant) {
|
||||||
return string_builder << '[' << dialog_participant.user_id << " invited by " << dialog_participant.inviter_user_id
|
return string_builder << '[' << dialog_participant.dialog_id << " invited by " << dialog_participant.inviter_user_id
|
||||||
<< " at " << dialog_participant.joined_date << " with status " << dialog_participant.status
|
<< " at " << dialog_participant.joined_date << " with status " << dialog_participant.status
|
||||||
<< ']';
|
<< ']';
|
||||||
}
|
}
|
||||||
|
@ -6,10 +6,12 @@
|
|||||||
//
|
//
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "td/telegram/DialogId.h"
|
||||||
#include "td/telegram/MessageId.h"
|
#include "td/telegram/MessageId.h"
|
||||||
#include "td/telegram/td_api.h"
|
#include "td/telegram/td_api.h"
|
||||||
#include "td/telegram/telegram_api.h"
|
#include "td/telegram/telegram_api.h"
|
||||||
#include "td/telegram/UserId.h"
|
#include "td/telegram/UserId.h"
|
||||||
|
#include "td/telegram/Version.h"
|
||||||
|
|
||||||
#include "td/utils/common.h"
|
#include "td/utils/common.h"
|
||||||
#include "td/utils/StringBuilder.h"
|
#include "td/utils/StringBuilder.h"
|
||||||
@ -140,7 +142,7 @@ class DialogParticipantStatus {
|
|||||||
static constexpr uint32 IS_MEMBER = 1 << 27;
|
static constexpr uint32 IS_MEMBER = 1 << 27;
|
||||||
|
|
||||||
static constexpr uint32 IS_ANONYMOUS = 1 << 13;
|
static constexpr uint32 IS_ANONYMOUS = 1 << 13;
|
||||||
static constexpr uint32 HAS_RANK = 1u << 14;
|
static constexpr uint32 HAS_RANK = 1 << 14;
|
||||||
// bits 28-30 reserved for Type
|
// bits 28-30 reserved for Type
|
||||||
static constexpr int TYPE_SHIFT = 28;
|
static constexpr int TYPE_SHIFT = 28;
|
||||||
static constexpr uint32 HAS_UNTIL_DATE = 1u << 31;
|
static constexpr uint32 HAS_UNTIL_DATE = 1u << 31;
|
||||||
@ -235,6 +237,11 @@ class DialogParticipantStatus {
|
|||||||
return (flags_ & CAN_INVITE_USERS_ADMIN) != 0 || (flags_ & CAN_INVITE_USERS_BANNED) != 0;
|
return (flags_ & CAN_INVITE_USERS_ADMIN) != 0 || (flags_ & CAN_INVITE_USERS_BANNED) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool can_manage_invite_links() const {
|
||||||
|
// invite links can be managed, only if administrator was explicitly granted the right
|
||||||
|
return (flags_ & CAN_INVITE_USERS_ADMIN) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool can_restrict_members() const {
|
bool can_restrict_members() const {
|
||||||
return (flags_ & CAN_RESTRICT_MEMBERS) != 0;
|
return (flags_ & CAN_RESTRICT_MEMBERS) != 0;
|
||||||
}
|
}
|
||||||
@ -383,29 +390,29 @@ bool operator!=(const DialogParticipantStatus &lhs, const DialogParticipantStatu
|
|||||||
StringBuilder &operator<<(StringBuilder &string_builder, const DialogParticipantStatus &status);
|
StringBuilder &operator<<(StringBuilder &string_builder, const DialogParticipantStatus &status);
|
||||||
|
|
||||||
struct DialogParticipant {
|
struct DialogParticipant {
|
||||||
UserId user_id;
|
DialogId dialog_id;
|
||||||
UserId inviter_user_id;
|
UserId inviter_user_id;
|
||||||
int32 joined_date = 0;
|
int32 joined_date = 0;
|
||||||
DialogParticipantStatus status = DialogParticipantStatus::Left();
|
DialogParticipantStatus status = DialogParticipantStatus::Left();
|
||||||
|
|
||||||
DialogParticipant() = default;
|
DialogParticipant() = default;
|
||||||
|
|
||||||
DialogParticipant(UserId user_id, UserId inviter_user_id, int32 joined_date, DialogParticipantStatus status);
|
DialogParticipant(DialogId user_id, UserId inviter_user_id, int32 joined_date, DialogParticipantStatus status);
|
||||||
|
|
||||||
DialogParticipant(tl_object_ptr<telegram_api::ChatParticipant> &&participant_ptr, int32 chat_creation_date,
|
DialogParticipant(tl_object_ptr<telegram_api::ChatParticipant> &&participant_ptr, int32 chat_creation_date,
|
||||||
bool is_creator);
|
bool is_creator);
|
||||||
|
|
||||||
explicit DialogParticipant(tl_object_ptr<telegram_api::ChannelParticipant> &&participant_ptr);
|
explicit DialogParticipant(tl_object_ptr<telegram_api::ChannelParticipant> &&participant_ptr);
|
||||||
|
|
||||||
static DialogParticipant left(UserId user_id) {
|
static DialogParticipant left(DialogId dialog_id) {
|
||||||
return {user_id, UserId(), 0, DialogParticipantStatus::Left()};
|
return {dialog_id, UserId(), 0, DialogParticipantStatus::Left()};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_valid() const;
|
bool is_valid() const;
|
||||||
|
|
||||||
template <class StorerT>
|
template <class StorerT>
|
||||||
void store(StorerT &storer) const {
|
void store(StorerT &storer) const {
|
||||||
td::store(user_id, storer);
|
td::store(dialog_id, storer);
|
||||||
td::store(inviter_user_id, storer);
|
td::store(inviter_user_id, storer);
|
||||||
td::store(joined_date, storer);
|
td::store(joined_date, storer);
|
||||||
td::store(status, storer);
|
td::store(status, storer);
|
||||||
@ -413,7 +420,13 @@ struct DialogParticipant {
|
|||||||
|
|
||||||
template <class ParserT>
|
template <class ParserT>
|
||||||
void parse(ParserT &parser) {
|
void parse(ParserT &parser) {
|
||||||
|
if (parser.version() >= static_cast<int32>(Version::SupportBannedChannels)) {
|
||||||
|
td::parse(dialog_id, parser);
|
||||||
|
} else {
|
||||||
|
UserId user_id;
|
||||||
td::parse(user_id, parser);
|
td::parse(user_id, parser);
|
||||||
|
dialog_id = DialogId(user_id);
|
||||||
|
}
|
||||||
td::parse(inviter_user_id, parser);
|
td::parse(inviter_user_id, parser);
|
||||||
td::parse(joined_date, parser);
|
td::parse(joined_date, parser);
|
||||||
td::parse(status, parser);
|
td::parse(status, parser);
|
||||||
|
@ -368,7 +368,7 @@ Document DocumentsManager::on_get_document(RemoteDocument remote_document, Dialo
|
|||||||
// fix_animated_sticker_type();
|
// fix_animated_sticker_type();
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(DEBUG) << "Receive document with id = " << id << " of type " << document_type;
|
LOG(DEBUG) << "Receive document with ID = " << id << " of type " << document_type;
|
||||||
if (!is_web && !DcId::is_valid(dc_id)) {
|
if (!is_web && !DcId::is_valid(dc_id)) {
|
||||||
LOG(ERROR) << "Wrong dc_id = " << dc_id;
|
LOG(ERROR) << "Wrong dc_id = " << dc_id;
|
||||||
return {};
|
return {};
|
||||||
@ -660,7 +660,7 @@ FileId DocumentsManager::dup_document(FileId new_id, FileId old_id) {
|
|||||||
|
|
||||||
bool DocumentsManager::merge_documents(FileId new_id, FileId old_id, bool can_delete_old) {
|
bool DocumentsManager::merge_documents(FileId new_id, FileId old_id, bool can_delete_old) {
|
||||||
if (!old_id.is_valid()) {
|
if (!old_id.is_valid()) {
|
||||||
LOG(ERROR) << "Old file id is invalid";
|
LOG(ERROR) << "Old file identifier is invalid";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +120,7 @@ bool operator!=(const Game &lhs, const Game &rhs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder &operator<<(StringBuilder &string_builder, const Game &game) {
|
StringBuilder &operator<<(StringBuilder &string_builder, const Game &game) {
|
||||||
return string_builder << "Game[id = " << game.id_ << ", access_hash = " << game.access_hash_
|
return string_builder << "Game[ID = " << game.id_ << ", access_hash = " << game.access_hash_
|
||||||
<< ", bot = " << game.bot_user_id_ << ", short_name = " << game.short_name_
|
<< ", bot = " << game.bot_user_id_ << ", short_name = " << game.short_name_
|
||||||
<< ", title = " << game.title_ << ", description = " << game.description_
|
<< ", title = " << game.title_ << ", description = " << game.description_
|
||||||
<< ", photo = " << game.photo_ << ", animation_file_id = " << game.animation_file_id_ << "]";
|
<< ", photo = " << game.photo_ << ", animation_file_id = " << game.animation_file_id_ << "]";
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -10,6 +10,7 @@
|
|||||||
#include "td/telegram/DialogParticipant.h"
|
#include "td/telegram/DialogParticipant.h"
|
||||||
#include "td/telegram/GroupCallId.h"
|
#include "td/telegram/GroupCallId.h"
|
||||||
#include "td/telegram/GroupCallParticipant.h"
|
#include "td/telegram/GroupCallParticipant.h"
|
||||||
|
#include "td/telegram/GroupCallParticipantOrder.h"
|
||||||
#include "td/telegram/InputGroupCallId.h"
|
#include "td/telegram/InputGroupCallId.h"
|
||||||
#include "td/telegram/td_api.h"
|
#include "td/telegram/td_api.h"
|
||||||
#include "td/telegram/telegram_api.h"
|
#include "td/telegram/telegram_api.h"
|
||||||
@ -41,9 +42,19 @@ class GroupCallManager : public Actor {
|
|||||||
|
|
||||||
void memory_stats(vector<string> &output);
|
void memory_stats(vector<string> &output);
|
||||||
|
|
||||||
|
DialogId get_group_call_participant_id(const td_api::object_ptr<td_api::MessageSender> &message_sender);
|
||||||
|
|
||||||
|
bool is_group_call_being_joined(InputGroupCallId input_group_call_id) const;
|
||||||
|
|
||||||
|
bool is_group_call_joined(InputGroupCallId input_group_call_id) const;
|
||||||
|
|
||||||
GroupCallId get_group_call_id(InputGroupCallId input_group_call_id, DialogId dialog_id);
|
GroupCallId get_group_call_id(InputGroupCallId input_group_call_id, DialogId dialog_id);
|
||||||
|
|
||||||
void create_voice_chat(DialogId dialog_id, Promise<GroupCallId> &&promise);
|
void get_group_call_join_as(DialogId dialog_id, Promise<td_api::object_ptr<td_api::messageSenders>> &&promise);
|
||||||
|
|
||||||
|
void set_group_call_default_join_as(DialogId dialog_id, DialogId as_dialog_id, Promise<Unit> &&promise);
|
||||||
|
|
||||||
|
void create_voice_chat(DialogId dialog_id, string title, int32 start_date, Promise<GroupCallId> &&promise);
|
||||||
|
|
||||||
void get_group_call(GroupCallId group_call_id, Promise<td_api::object_ptr<td_api::groupCall>> &&promise);
|
void get_group_call(GroupCallId group_call_id, Promise<td_api::object_ptr<td_api::groupCall>> &&promise);
|
||||||
|
|
||||||
@ -52,22 +63,40 @@ class GroupCallManager : public Actor {
|
|||||||
void reload_group_call(InputGroupCallId input_group_call_id,
|
void reload_group_call(InputGroupCallId input_group_call_id,
|
||||||
Promise<td_api::object_ptr<td_api::groupCall>> &&promise);
|
Promise<td_api::object_ptr<td_api::groupCall>> &&promise);
|
||||||
|
|
||||||
void join_group_call(GroupCallId group_call_id, td_api::object_ptr<td_api::groupCallPayload> &&payload,
|
void get_group_call_stream_segment(GroupCallId group_call_id, int64 time_offset, int32 scale,
|
||||||
int32 audio_source, bool is_muted,
|
Promise<string> &&promise);
|
||||||
Promise<td_api::object_ptr<td_api::groupCallJoinResponse>> &&promise);
|
|
||||||
|
void start_scheduled_group_call(GroupCallId group_call_id, Promise<Unit> &&promise);
|
||||||
|
|
||||||
|
void join_group_call(GroupCallId group_call_id, DialogId as_dialog_id,
|
||||||
|
td_api::object_ptr<td_api::groupCallPayload> &&payload, int32 audio_source, bool is_muted,
|
||||||
|
const string &invite_hash, Promise<td_api::object_ptr<td_api::GroupCallJoinResponse>> &&promise);
|
||||||
|
|
||||||
|
void set_group_call_title(GroupCallId group_call_id, string title, Promise<Unit> &&promise);
|
||||||
|
|
||||||
|
void toggle_group_call_start_subscribed(GroupCallId group_call_id, bool start_subscribed, Promise<Unit> &&promise);
|
||||||
|
|
||||||
void toggle_group_call_mute_new_participants(GroupCallId group_call_id, bool mute_new_participants,
|
void toggle_group_call_mute_new_participants(GroupCallId group_call_id, bool mute_new_participants,
|
||||||
Promise<Unit> &&promise);
|
Promise<Unit> &&promise);
|
||||||
|
|
||||||
|
void revoke_group_call_invite_link(GroupCallId group_call_id, Promise<Unit> &&promise);
|
||||||
|
|
||||||
void invite_group_call_participants(GroupCallId group_call_id, vector<UserId> &&user_ids, Promise<Unit> &&promise);
|
void invite_group_call_participants(GroupCallId group_call_id, vector<UserId> &&user_ids, Promise<Unit> &&promise);
|
||||||
|
|
||||||
|
void get_group_call_invite_link(GroupCallId group_call_id, bool can_self_unmute, Promise<string> &&promise);
|
||||||
|
|
||||||
|
void toggle_group_call_recording(GroupCallId group_call_id, bool is_enabled, string title, Promise<Unit> &&promise);
|
||||||
|
|
||||||
void set_group_call_participant_is_speaking(GroupCallId group_call_id, int32 audio_source, bool is_speaking,
|
void set_group_call_participant_is_speaking(GroupCallId group_call_id, int32 audio_source, bool is_speaking,
|
||||||
Promise<Unit> &&promise, int32 date = 0);
|
Promise<Unit> &&promise, int32 date = 0);
|
||||||
|
|
||||||
void toggle_group_call_participant_is_muted(GroupCallId group_call_id, UserId user_id, bool is_muted,
|
void toggle_group_call_participant_is_muted(GroupCallId group_call_id, DialogId dialog_id, bool is_muted,
|
||||||
Promise<Unit> &&promise);
|
Promise<Unit> &&promise);
|
||||||
|
|
||||||
void set_group_call_participant_volume_level(GroupCallId group_call_id, UserId user_id, int32 volume_level,
|
void set_group_call_participant_volume_level(GroupCallId group_call_id, DialogId dialog_id, int32 volume_level,
|
||||||
|
Promise<Unit> &&promise);
|
||||||
|
|
||||||
|
void toggle_group_call_participant_is_hand_raised(GroupCallId group_call_id, DialogId dialog_id, bool is_hand_raised,
|
||||||
Promise<Unit> &&promise);
|
Promise<Unit> &&promise);
|
||||||
|
|
||||||
void load_group_call_participants(GroupCallId group_call_id, int32 limit, Promise<Unit> &&promise);
|
void load_group_call_participants(GroupCallId group_call_id, int32 limit, Promise<Unit> &&promise);
|
||||||
@ -76,9 +105,12 @@ class GroupCallManager : public Actor {
|
|||||||
|
|
||||||
void discard_group_call(GroupCallId group_call_id, Promise<Unit> &&promise);
|
void discard_group_call(GroupCallId group_call_id, Promise<Unit> &&promise);
|
||||||
|
|
||||||
|
void on_update_dialog_about(DialogId dialog_id, const string &about, bool from_server);
|
||||||
|
|
||||||
void on_update_group_call(tl_object_ptr<telegram_api::GroupCall> group_call_ptr, DialogId dialog_id);
|
void on_update_group_call(tl_object_ptr<telegram_api::GroupCall> group_call_ptr, DialogId dialog_id);
|
||||||
|
|
||||||
void on_user_speaking_in_group_call(GroupCallId group_call_id, UserId user_id, int32 date, bool recursive = false);
|
void on_user_speaking_in_group_call(GroupCallId group_call_id, DialogId dialog_id, int32 date,
|
||||||
|
bool is_recursive = false);
|
||||||
|
|
||||||
void on_get_group_call_participants(InputGroupCallId input_group_call_id,
|
void on_get_group_call_participants(InputGroupCallId input_group_call_id,
|
||||||
tl_object_ptr<telegram_api::phone_groupParticipants> &&participants, bool is_load,
|
tl_object_ptr<telegram_api::phone_groupParticipants> &&participants, bool is_load,
|
||||||
@ -86,7 +118,7 @@ class GroupCallManager : public Actor {
|
|||||||
|
|
||||||
void on_update_group_call_participants(InputGroupCallId input_group_call_id,
|
void on_update_group_call_participants(InputGroupCallId input_group_call_id,
|
||||||
vector<tl_object_ptr<telegram_api::groupCallParticipant>> &&participants,
|
vector<tl_object_ptr<telegram_api::groupCallParticipant>> &&participants,
|
||||||
int32 version);
|
int32 version, bool is_recursive = false);
|
||||||
|
|
||||||
void process_join_group_call_response(InputGroupCallId input_group_call_id, uint64 generation,
|
void process_join_group_call_response(InputGroupCallId input_group_call_id, uint64 generation,
|
||||||
tl_object_ptr<telegram_api::Updates> &&updates, Promise<Unit> &&promise);
|
tl_object_ptr<telegram_api::Updates> &&updates, Promise<Unit> &&promise);
|
||||||
@ -98,12 +130,19 @@ class GroupCallManager : public Actor {
|
|||||||
struct PendingJoinRequest;
|
struct PendingJoinRequest;
|
||||||
|
|
||||||
static constexpr int32 RECENT_SPEAKER_TIMEOUT = 60 * 60;
|
static constexpr int32 RECENT_SPEAKER_TIMEOUT = 60 * 60;
|
||||||
|
static constexpr int32 UPDATE_GROUP_CALL_PARTICIPANT_ORDER_TIMEOUT = 10;
|
||||||
static constexpr int32 CHECK_GROUP_CALL_IS_JOINED_TIMEOUT = 10;
|
static constexpr int32 CHECK_GROUP_CALL_IS_JOINED_TIMEOUT = 10;
|
||||||
|
static constexpr size_t MAX_TITLE_LENGTH = 64; // server side limit for group call/call record title length
|
||||||
|
|
||||||
void tear_down() override;
|
void tear_down() override;
|
||||||
|
|
||||||
void memory_cleanup(bool full);
|
void memory_cleanup(bool full);
|
||||||
|
|
||||||
|
static void on_update_group_call_participant_order_timeout_callback(void *group_call_manager_ptr,
|
||||||
|
int64 group_call_id_int);
|
||||||
|
|
||||||
|
void on_update_group_call_participant_order_timeout(GroupCallId group_call_id);
|
||||||
|
|
||||||
static void on_check_group_call_is_joined_timeout_callback(void *group_call_manager_ptr, int64 group_call_id_int);
|
static void on_check_group_call_is_joined_timeout_callback(void *group_call_manager_ptr, int64 group_call_id_int);
|
||||||
|
|
||||||
void on_check_group_call_is_joined_timeout(GroupCallId group_call_id);
|
void on_check_group_call_is_joined_timeout(GroupCallId group_call_id);
|
||||||
@ -133,16 +172,31 @@ class GroupCallManager : public Actor {
|
|||||||
|
|
||||||
bool can_manage_group_call(InputGroupCallId input_group_call_id) const;
|
bool can_manage_group_call(InputGroupCallId input_group_call_id) const;
|
||||||
|
|
||||||
|
bool get_group_call_can_self_unmute(InputGroupCallId input_group_call_id) const;
|
||||||
|
|
||||||
|
bool get_group_call_joined_date_asc(InputGroupCallId input_group_call_id) const;
|
||||||
|
|
||||||
void on_voice_chat_created(DialogId dialog_id, InputGroupCallId input_group_call_id, Promise<GroupCallId> &&promise);
|
void on_voice_chat_created(DialogId dialog_id, InputGroupCallId input_group_call_id, Promise<GroupCallId> &&promise);
|
||||||
|
|
||||||
void finish_get_group_call(InputGroupCallId input_group_call_id,
|
void finish_get_group_call(InputGroupCallId input_group_call_id,
|
||||||
Result<tl_object_ptr<telegram_api::phone_groupCall>> &&result);
|
Result<tl_object_ptr<telegram_api::phone_groupCall>> &&result);
|
||||||
|
|
||||||
|
void finish_get_group_call_stream_segment(InputGroupCallId input_group_call_id, int32 audio_source,
|
||||||
|
Result<string> &&result, Promise<string> &&promise);
|
||||||
|
|
||||||
void finish_check_group_call_is_joined(InputGroupCallId input_group_call_id, int32 audio_source,
|
void finish_check_group_call_is_joined(InputGroupCallId input_group_call_id, int32 audio_source,
|
||||||
Result<Unit> &&result);
|
Result<Unit> &&result);
|
||||||
|
|
||||||
|
static const string &get_group_call_title(const GroupCall *group_call);
|
||||||
|
|
||||||
|
static bool get_group_call_start_subscribed(const GroupCall *group_call);
|
||||||
|
|
||||||
static bool get_group_call_mute_new_participants(const GroupCall *group_call);
|
static bool get_group_call_mute_new_participants(const GroupCall *group_call);
|
||||||
|
|
||||||
|
static int32 get_group_call_record_start_date(const GroupCall *group_call);
|
||||||
|
|
||||||
|
static bool get_group_call_has_recording(const GroupCall *group_call);
|
||||||
|
|
||||||
bool need_group_call_participants(InputGroupCallId input_group_call_id) const;
|
bool need_group_call_participants(InputGroupCallId input_group_call_id) const;
|
||||||
|
|
||||||
bool need_group_call_participants(InputGroupCallId input_group_call_id, const GroupCall *group_call) const;
|
bool need_group_call_participants(InputGroupCallId input_group_call_id, const GroupCall *group_call) const;
|
||||||
@ -153,11 +207,14 @@ class GroupCallManager : public Actor {
|
|||||||
|
|
||||||
void on_sync_group_call_participants_failed(InputGroupCallId input_group_call_id);
|
void on_sync_group_call_participants_failed(InputGroupCallId input_group_call_id);
|
||||||
|
|
||||||
int64 get_real_participant_order(const GroupCallParticipant &participant, int64 min_order) const;
|
GroupCallParticipantOrder get_real_participant_order(bool can_self_unmute, const GroupCallParticipant &participant,
|
||||||
|
const GroupCallParticipants *participants) const;
|
||||||
|
|
||||||
|
void process_my_group_call_participant(InputGroupCallId input_group_call_id, GroupCallParticipant &&participant);
|
||||||
|
|
||||||
void process_group_call_participants(InputGroupCallId group_call_id,
|
void process_group_call_participants(InputGroupCallId group_call_id,
|
||||||
vector<tl_object_ptr<telegram_api::groupCallParticipant>> &&participants,
|
vector<tl_object_ptr<telegram_api::groupCallParticipant>> &&participants,
|
||||||
bool is_load, bool is_sync);
|
int32 version, const string &offset, bool is_load, bool is_sync);
|
||||||
|
|
||||||
bool update_group_call_participant_can_be_muted(bool can_manage, const GroupCallParticipants *participants,
|
bool update_group_call_participant_can_be_muted(bool can_manage, const GroupCallParticipants *participants,
|
||||||
GroupCallParticipant &participant);
|
GroupCallParticipant &participant);
|
||||||
@ -167,6 +224,10 @@ class GroupCallManager : public Actor {
|
|||||||
|
|
||||||
int process_group_call_participant(InputGroupCallId group_call_id, GroupCallParticipant &&participant);
|
int process_group_call_participant(InputGroupCallId group_call_id, GroupCallParticipant &&participant);
|
||||||
|
|
||||||
|
void on_add_group_call_participant(InputGroupCallId input_group_call_id, DialogId participant_dialog_id);
|
||||||
|
|
||||||
|
void on_remove_group_call_participant(InputGroupCallId input_group_call_id, DialogId participant_dialog_id);
|
||||||
|
|
||||||
void try_load_group_call_administrators(InputGroupCallId input_group_call_id, DialogId dialog_id);
|
void try_load_group_call_administrators(InputGroupCallId input_group_call_id, DialogId dialog_id);
|
||||||
|
|
||||||
void finish_load_group_call_administrators(InputGroupCallId input_group_call_id, Result<DialogParticipants> &&result);
|
void finish_load_group_call_administrators(InputGroupCallId input_group_call_id, Result<DialogParticipants> &&result);
|
||||||
@ -177,14 +238,23 @@ class GroupCallManager : public Actor {
|
|||||||
|
|
||||||
void finish_join_group_call(InputGroupCallId input_group_call_id, uint64 generation, Status error);
|
void finish_join_group_call(InputGroupCallId input_group_call_id, uint64 generation, Status error);
|
||||||
|
|
||||||
void process_group_call_after_join_requests(InputGroupCallId input_group_call_id);
|
void process_group_call_after_join_requests(InputGroupCallId input_group_call_id, const char *source);
|
||||||
|
|
||||||
GroupCallParticipants *add_group_call_participants(InputGroupCallId input_group_call_id);
|
GroupCallParticipants *add_group_call_participants(InputGroupCallId input_group_call_id);
|
||||||
|
|
||||||
GroupCallParticipant *get_group_call_participant(InputGroupCallId input_group_call_id, UserId user_id);
|
GroupCallParticipant *get_group_call_participant(InputGroupCallId input_group_call_id, DialogId dialog_id);
|
||||||
|
|
||||||
static GroupCallParticipant *get_group_call_participant(GroupCallParticipants *group_call_participants,
|
GroupCallParticipant *get_group_call_participant(GroupCallParticipants *group_call_participants,
|
||||||
UserId user_id);
|
DialogId dialog_id) const;
|
||||||
|
|
||||||
|
void send_edit_group_call_title_query(InputGroupCallId input_group_call_id, const string &title);
|
||||||
|
|
||||||
|
void on_edit_group_call_title(InputGroupCallId input_group_call_id, const string &title, Result<Unit> &&result);
|
||||||
|
|
||||||
|
void send_toggle_group_call_start_subscription_query(InputGroupCallId input_group_call_id, bool start_subscribed);
|
||||||
|
|
||||||
|
void on_toggle_group_call_start_subscription(InputGroupCallId input_group_call_id, bool start_subscribed,
|
||||||
|
Result<Unit> &&result);
|
||||||
|
|
||||||
void send_toggle_group_call_mute_new_participants_query(InputGroupCallId input_group_call_id,
|
void send_toggle_group_call_mute_new_participants_query(InputGroupCallId input_group_call_id,
|
||||||
bool mute_new_participants);
|
bool mute_new_participants);
|
||||||
@ -192,15 +262,23 @@ class GroupCallManager : public Actor {
|
|||||||
void on_toggle_group_call_mute_new_participants(InputGroupCallId input_group_call_id, bool mute_new_participants,
|
void on_toggle_group_call_mute_new_participants(InputGroupCallId input_group_call_id, bool mute_new_participants,
|
||||||
Result<Unit> &&result);
|
Result<Unit> &&result);
|
||||||
|
|
||||||
void on_toggle_group_call_participant_is_muted(InputGroupCallId input_group_call_id, UserId user_id,
|
void send_toggle_group_call_recording_query(InputGroupCallId input_group_call_id, bool is_enabled,
|
||||||
|
const string &title, uint64 generation);
|
||||||
|
|
||||||
|
void on_toggle_group_call_recording(InputGroupCallId input_group_call_id, uint64 generation, Result<Unit> &&result);
|
||||||
|
|
||||||
|
void on_toggle_group_call_participant_is_muted(InputGroupCallId input_group_call_id, DialogId dialog_id,
|
||||||
uint64 generation, Promise<Unit> &&promise);
|
uint64 generation, Promise<Unit> &&promise);
|
||||||
|
|
||||||
void on_set_group_call_participant_volume_level(InputGroupCallId input_group_call_id, UserId user_id,
|
void on_set_group_call_participant_volume_level(InputGroupCallId input_group_call_id, DialogId dialog_id,
|
||||||
|
uint64 generation, Promise<Unit> &&promise);
|
||||||
|
|
||||||
|
void on_toggle_group_call_participant_is_hand_raised(InputGroupCallId input_group_call_id, DialogId dialog_id,
|
||||||
uint64 generation, Promise<Unit> &&promise);
|
uint64 generation, Promise<Unit> &&promise);
|
||||||
|
|
||||||
void on_group_call_left(InputGroupCallId input_group_call_id, int32 audio_source, bool need_rejoin);
|
void on_group_call_left(InputGroupCallId input_group_call_id, int32 audio_source, bool need_rejoin);
|
||||||
|
|
||||||
void on_group_call_left_impl(GroupCall *group_call, bool need_rejoin);
|
void on_group_call_left_impl(GroupCall *group_call, bool need_rejoin, const char *source);
|
||||||
|
|
||||||
InputGroupCallId update_group_call(const tl_object_ptr<telegram_api::GroupCall> &group_call_ptr, DialogId dialog_id);
|
InputGroupCallId update_group_call(const tl_object_ptr<telegram_api::GroupCall> &group_call_ptr, DialogId dialog_id);
|
||||||
|
|
||||||
@ -209,19 +287,22 @@ class GroupCallManager : public Actor {
|
|||||||
void on_participant_speaking_in_group_call(InputGroupCallId input_group_call_id,
|
void on_participant_speaking_in_group_call(InputGroupCallId input_group_call_id,
|
||||||
const GroupCallParticipant &participant);
|
const GroupCallParticipant &participant);
|
||||||
|
|
||||||
void remove_recent_group_call_speaker(InputGroupCallId input_group_call_id, UserId user_id);
|
void remove_recent_group_call_speaker(InputGroupCallId input_group_call_id, DialogId dialog_id);
|
||||||
|
|
||||||
void on_group_call_recent_speakers_updated(const GroupCall *group_call, GroupCallRecentSpeakers *recent_speakers);
|
void on_group_call_recent_speakers_updated(const GroupCall *group_call, GroupCallRecentSpeakers *recent_speakers);
|
||||||
|
|
||||||
UserId set_group_call_participant_is_speaking_by_source(InputGroupCallId input_group_call_id, int32 audio_source,
|
DialogId set_group_call_participant_is_speaking_by_source(InputGroupCallId input_group_call_id, int32 audio_source,
|
||||||
bool is_speaking, int32 date);
|
bool is_speaking, int32 date);
|
||||||
|
|
||||||
static Result<td_api::object_ptr<td_api::groupCallJoinResponse>> get_group_call_join_response_object(
|
static Result<td_api::object_ptr<td_api::GroupCallJoinResponse>> get_group_call_join_response_object(
|
||||||
string json_response);
|
string json_response);
|
||||||
|
|
||||||
void try_clear_group_call_participants(InputGroupCallId input_group_call_id);
|
bool try_clear_group_call_participants(InputGroupCallId input_group_call_id);
|
||||||
|
|
||||||
void update_group_call_dialog(const GroupCall *group_call, const char *source);
|
bool set_group_call_participant_count(GroupCall *group_call, int32 count, const char *source,
|
||||||
|
bool force_update = false);
|
||||||
|
|
||||||
|
void update_group_call_dialog(const GroupCall *group_call, const char *source, bool force);
|
||||||
|
|
||||||
vector<td_api::object_ptr<td_api::groupCallRecentSpeaker>> get_recent_speakers(const GroupCall *group_call,
|
vector<td_api::object_ptr<td_api::groupCallRecentSpeaker>> get_recent_speakers(const GroupCall *group_call,
|
||||||
bool for_update);
|
bool for_update);
|
||||||
@ -237,10 +318,11 @@ class GroupCallManager : public Actor {
|
|||||||
|
|
||||||
void send_update_group_call(const GroupCall *group_call, const char *source);
|
void send_update_group_call(const GroupCall *group_call, const char *source);
|
||||||
|
|
||||||
void send_update_group_call_participant(GroupCallId group_call_id, const GroupCallParticipant &participant);
|
void send_update_group_call_participant(GroupCallId group_call_id, const GroupCallParticipant &participant,
|
||||||
|
const char *source);
|
||||||
|
|
||||||
void send_update_group_call_participant(InputGroupCallId input_group_call_id,
|
void send_update_group_call_participant(InputGroupCallId input_group_call_id, const GroupCallParticipant &participant,
|
||||||
const GroupCallParticipant &participant);
|
const char *source);
|
||||||
|
|
||||||
Td *td_;
|
Td *td_;
|
||||||
ActorShared<> parent_;
|
ActorShared<> parent_;
|
||||||
@ -253,6 +335,7 @@ class GroupCallManager : public Actor {
|
|||||||
|
|
||||||
std::unordered_map<InputGroupCallId, unique_ptr<GroupCallParticipants>, InputGroupCallIdHash>
|
std::unordered_map<InputGroupCallId, unique_ptr<GroupCallParticipants>, InputGroupCallIdHash>
|
||||||
group_call_participants_;
|
group_call_participants_;
|
||||||
|
std::unordered_map<DialogId, vector<InputGroupCallId>, DialogIdHash> participant_id_to_group_call_id_;
|
||||||
|
|
||||||
std::unordered_map<GroupCallId, unique_ptr<GroupCallRecentSpeakers>, GroupCallIdHash> group_call_recent_speakers_;
|
std::unordered_map<GroupCallId, unique_ptr<GroupCallRecentSpeakers>, GroupCallIdHash> group_call_recent_speakers_;
|
||||||
|
|
||||||
@ -262,10 +345,15 @@ class GroupCallManager : public Actor {
|
|||||||
std::unordered_map<InputGroupCallId, unique_ptr<PendingJoinRequest>, InputGroupCallIdHash> pending_join_requests_;
|
std::unordered_map<InputGroupCallId, unique_ptr<PendingJoinRequest>, InputGroupCallIdHash> pending_join_requests_;
|
||||||
uint64 join_group_request_generation_ = 0;
|
uint64 join_group_request_generation_ = 0;
|
||||||
|
|
||||||
uint64 set_volume_level_generation_ = 0;
|
uint64 toggle_recording_generation_ = 0;
|
||||||
|
|
||||||
uint64 toggle_is_muted_generation_ = 0;
|
uint64 toggle_is_muted_generation_ = 0;
|
||||||
|
|
||||||
|
uint64 set_volume_level_generation_ = 0;
|
||||||
|
|
||||||
|
uint64 toggle_is_hand_raised_generation_ = 0;
|
||||||
|
|
||||||
|
MultiTimeout update_group_call_participant_order_timeout_{"UpdateGroupCallParticipantOrderTimeout"};
|
||||||
MultiTimeout check_group_call_is_joined_timeout_{"CheckGroupCallIsJoinedTimeout"};
|
MultiTimeout check_group_call_is_joined_timeout_{"CheckGroupCallIsJoinedTimeout"};
|
||||||
MultiTimeout pending_send_speaking_action_timeout_{"PendingSendSpeakingActionTimeout"};
|
MultiTimeout pending_send_speaking_action_timeout_{"PendingSendSpeakingActionTimeout"};
|
||||||
MultiTimeout recent_speaker_update_timeout_{"RecentSpeakerUpdateTimeout"};
|
MultiTimeout recent_speaker_update_timeout_{"RecentSpeakerUpdateTimeout"};
|
||||||
|
@ -6,19 +6,26 @@
|
|||||||
//
|
//
|
||||||
#include "td/telegram/GroupCallParticipant.h"
|
#include "td/telegram/GroupCallParticipant.h"
|
||||||
|
|
||||||
#include "td/telegram/ContactsManager.h"
|
#include "td/telegram/Global.h"
|
||||||
|
#include "td/telegram/MessagesManager.h"
|
||||||
|
#include "td/telegram/Td.h"
|
||||||
|
|
||||||
#include "td/utils/logging.h"
|
#include "td/utils/logging.h"
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
|
|
||||||
GroupCallParticipant::GroupCallParticipant(const tl_object_ptr<telegram_api::groupCallParticipant> &participant) {
|
GroupCallParticipant::GroupCallParticipant(const tl_object_ptr<telegram_api::groupCallParticipant> &participant,
|
||||||
|
int32 call_version) {
|
||||||
CHECK(participant != nullptr);
|
CHECK(participant != nullptr);
|
||||||
user_id = UserId(participant->user_id_);
|
dialog_id = DialogId(participant->peer_);
|
||||||
|
about = std::move(participant->about_);
|
||||||
audio_source = participant->source_;
|
audio_source = participant->source_;
|
||||||
server_is_muted_by_themselves = participant->can_self_unmute_;
|
server_is_muted_by_themselves = participant->can_self_unmute_;
|
||||||
server_is_muted_by_admin = participant->muted_ && !participant->can_self_unmute_;
|
server_is_muted_by_admin = participant->muted_ && !participant->can_self_unmute_;
|
||||||
server_is_muted_locally = participant->muted_by_you_;
|
server_is_muted_locally = participant->muted_by_you_;
|
||||||
|
is_self = participant->self_;
|
||||||
if ((participant->flags_ & telegram_api::groupCallParticipant::VOLUME_MASK) != 0) {
|
if ((participant->flags_ & telegram_api::groupCallParticipant::VOLUME_MASK) != 0) {
|
||||||
volume_level = participant->volume_;
|
volume_level = participant->volume_;
|
||||||
if (volume_level < MIN_VOLUME_LEVEL || volume_level > MAX_VOLUME_LEVEL) {
|
if (volume_level < MIN_VOLUME_LEVEL || volume_level > MAX_VOLUME_LEVEL) {
|
||||||
@ -32,20 +39,40 @@ GroupCallParticipant::GroupCallParticipant(const tl_object_ptr<telegram_api::gro
|
|||||||
if ((participant->flags_ & telegram_api::groupCallParticipant::ACTIVE_DATE_MASK) != 0) {
|
if ((participant->flags_ & telegram_api::groupCallParticipant::ACTIVE_DATE_MASK) != 0) {
|
||||||
active_date = participant->active_date_;
|
active_date = participant->active_date_;
|
||||||
}
|
}
|
||||||
if (joined_date < 0 || active_date < 0) {
|
if (joined_date <= 0 || active_date < 0) {
|
||||||
LOG(ERROR) << "Receive invalid " << to_string(participant);
|
LOG(ERROR) << "Receive invalid active_date/joined_date in " << to_string(participant);
|
||||||
joined_date = 0;
|
joined_date = 1;
|
||||||
active_date = 0;
|
active_date = 0;
|
||||||
}
|
}
|
||||||
|
if ((participant->flags_ & telegram_api::groupCallParticipant::RAISE_HAND_RATING_MASK) != 0) {
|
||||||
|
raise_hand_rating = participant->raise_hand_rating_;
|
||||||
|
if (raise_hand_rating < 0) {
|
||||||
|
LOG(ERROR) << "Receive invalid raise_hand_rating in " << to_string(participant);
|
||||||
|
raise_hand_rating = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
is_just_joined = participant->just_joined_;
|
is_just_joined = participant->just_joined_;
|
||||||
is_min = (participant->flags_ & telegram_api::groupCallParticipant::MIN_MASK) != 0;
|
is_min = participant->min_;
|
||||||
|
version = call_version;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GroupCallParticipant::is_versioned_update(const tl_object_ptr<telegram_api::groupCallParticipant> &participant) {
|
bool GroupCallParticipant::is_versioned_update(const tl_object_ptr<telegram_api::groupCallParticipant> &participant) {
|
||||||
|
// updates about new and left participants must be applyed as versioned, even they don't increase version
|
||||||
return participant->just_joined_ || participant->left_ || participant->versioned_;
|
return participant->just_joined_ || participant->left_ || participant->versioned_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GroupCallParticipantOrder GroupCallParticipant::get_real_order(bool can_self_unmute, bool joined_date_asc,
|
||||||
|
bool keep_active_date) const {
|
||||||
|
auto sort_active_date = td::max(active_date, local_active_date);
|
||||||
|
if (!keep_active_date && sort_active_date < G()->unix_time() - 300) {
|
||||||
|
sort_active_date = 0;
|
||||||
|
}
|
||||||
|
auto sort_raise_hand_rating = can_self_unmute ? raise_hand_rating : 0;
|
||||||
|
auto sort_joined_date = joined_date_asc ? std::numeric_limits<int32>::max() - joined_date : joined_date;
|
||||||
|
return GroupCallParticipantOrder(sort_active_date, sort_raise_hand_rating, sort_joined_date);
|
||||||
|
}
|
||||||
|
|
||||||
bool GroupCallParticipant::get_is_muted_by_themselves() const {
|
bool GroupCallParticipant::get_is_muted_by_themselves() const {
|
||||||
return have_pending_is_muted ? pending_is_muted_by_themselves : server_is_muted_by_themselves;
|
return have_pending_is_muted ? pending_is_muted_by_themselves : server_is_muted_by_themselves;
|
||||||
}
|
}
|
||||||
@ -66,10 +93,15 @@ int32 GroupCallParticipant::get_volume_level() const {
|
|||||||
return pending_volume_level != 0 ? pending_volume_level : volume_level;
|
return pending_volume_level != 0 ? pending_volume_level : volume_level;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GroupCallParticipant::get_is_hand_raised() const {
|
||||||
|
return have_pending_is_hand_raised ? pending_is_hand_raised : raise_hand_rating != 0;
|
||||||
|
}
|
||||||
|
|
||||||
void GroupCallParticipant::update_from(const GroupCallParticipant &old_participant) {
|
void GroupCallParticipant::update_from(const GroupCallParticipant &old_participant) {
|
||||||
CHECK(!old_participant.is_min);
|
CHECK(!old_participant.is_min);
|
||||||
if (joined_date < old_participant.joined_date) {
|
if (joined_date < old_participant.joined_date) {
|
||||||
LOG(ERROR) << "Join date decreased from " << old_participant.joined_date << " to " << joined_date;
|
LOG(ERROR) << "Join date of " << old_participant.dialog_id << " decreased from " << old_participant.joined_date
|
||||||
|
<< " to " << joined_date;
|
||||||
joined_date = old_participant.joined_date;
|
joined_date = old_participant.joined_date;
|
||||||
}
|
}
|
||||||
if (active_date < old_participant.active_date) {
|
if (active_date < old_participant.active_date) {
|
||||||
@ -84,6 +116,10 @@ void GroupCallParticipant::update_from(const GroupCallParticipant &old_participa
|
|||||||
is_volume_level_local = true;
|
is_volume_level_local = true;
|
||||||
volume_level = old_participant.volume_level;
|
volume_level = old_participant.volume_level;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (audio_source == old_participant.audio_source) {
|
||||||
|
is_self = old_participant.is_self;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
is_min = false;
|
is_min = false;
|
||||||
|
|
||||||
@ -95,9 +131,13 @@ void GroupCallParticipant::update_from(const GroupCallParticipant &old_participa
|
|||||||
pending_is_muted_by_admin = old_participant.pending_is_muted_by_admin;
|
pending_is_muted_by_admin = old_participant.pending_is_muted_by_admin;
|
||||||
pending_is_muted_locally = old_participant.pending_is_muted_locally;
|
pending_is_muted_locally = old_participant.pending_is_muted_locally;
|
||||||
pending_is_muted_generation = old_participant.pending_is_muted_generation;
|
pending_is_muted_generation = old_participant.pending_is_muted_generation;
|
||||||
|
|
||||||
|
have_pending_is_hand_raised = old_participant.have_pending_is_hand_raised;
|
||||||
|
pending_is_hand_raised = old_participant.pending_is_hand_raised;
|
||||||
|
pending_is_hand_raised_generation = old_participant.pending_is_hand_raised_generation;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GroupCallParticipant::update_can_be_muted(bool can_manage, bool is_self, bool is_admin) {
|
bool GroupCallParticipant::update_can_be_muted(bool can_manage, bool is_admin) {
|
||||||
bool is_muted_by_admin = get_is_muted_by_admin();
|
bool is_muted_by_admin = get_is_muted_by_admin();
|
||||||
bool is_muted_by_themselves = get_is_muted_by_themselves();
|
bool is_muted_by_themselves = get_is_muted_by_themselves();
|
||||||
bool is_muted_locally = get_is_muted_locally();
|
bool is_muted_locally = get_is_muted_locally();
|
||||||
@ -141,8 +181,8 @@ bool GroupCallParticipant::update_can_be_muted(bool can_manage, bool is_self, bo
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GroupCallParticipant::set_pending_is_muted(bool is_muted, bool can_manage, bool is_self, bool is_admin) {
|
bool GroupCallParticipant::set_pending_is_muted(bool is_muted, bool can_manage, bool is_admin) {
|
||||||
update_can_be_muted(can_manage, is_self, is_admin);
|
update_can_be_muted(can_manage, is_admin);
|
||||||
if (is_muted) {
|
if (is_muted) {
|
||||||
if (!can_be_muted_for_all_users && !can_be_muted_only_for_self) {
|
if (!can_be_muted_for_all_users && !can_be_muted_only_for_self) {
|
||||||
return false;
|
return false;
|
||||||
@ -197,32 +237,33 @@ bool GroupCallParticipant::set_pending_is_muted(bool is_muted, bool can_manage,
|
|||||||
}
|
}
|
||||||
|
|
||||||
have_pending_is_muted = true;
|
have_pending_is_muted = true;
|
||||||
update_can_be_muted(can_manage, is_self, is_admin);
|
update_can_be_muted(can_manage, is_admin);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
td_api::object_ptr<td_api::groupCallParticipant> GroupCallParticipant::get_group_call_participant_object(
|
td_api::object_ptr<td_api::groupCallParticipant> GroupCallParticipant::get_group_call_participant_object(Td *td) const {
|
||||||
ContactsManager *contacts_manager) const {
|
|
||||||
if (!is_valid()) {
|
if (!is_valid()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return td_api::make_object<td_api::groupCallParticipant>(
|
return td_api::make_object<td_api::groupCallParticipant>(
|
||||||
contacts_manager->get_user_id_object(user_id, "get_group_call_participant_object"), audio_source, is_speaking,
|
td->messages_manager_->get_message_sender_object(dialog_id), audio_source, about, is_self, is_speaking,
|
||||||
can_be_muted_for_all_users, can_be_unmuted_for_all_users, can_be_muted_only_for_self,
|
get_is_hand_raised(), can_be_muted_for_all_users, can_be_unmuted_for_all_users, can_be_muted_only_for_self,
|
||||||
can_be_unmuted_only_for_self, get_is_muted_for_all_users(), get_is_muted_locally(), get_is_muted_by_themselves(),
|
can_be_unmuted_only_for_self, get_is_muted_for_all_users(), get_is_muted_locally(), get_is_muted_by_themselves(),
|
||||||
get_volume_level(), order);
|
get_volume_level(), order.get_group_call_participant_order_object());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const GroupCallParticipant &lhs, const GroupCallParticipant &rhs) {
|
bool operator==(const GroupCallParticipant &lhs, const GroupCallParticipant &rhs) {
|
||||||
return lhs.user_id == rhs.user_id && lhs.audio_source == rhs.audio_source &&
|
return lhs.dialog_id == rhs.dialog_id && lhs.audio_source == rhs.audio_source && lhs.about == rhs.about &&
|
||||||
|
lhs.is_self == rhs.is_self && lhs.is_speaking == rhs.is_speaking &&
|
||||||
|
lhs.get_is_hand_raised() == rhs.get_is_hand_raised() &&
|
||||||
lhs.can_be_muted_for_all_users == rhs.can_be_muted_for_all_users &&
|
lhs.can_be_muted_for_all_users == rhs.can_be_muted_for_all_users &&
|
||||||
lhs.can_be_unmuted_for_all_users == rhs.can_be_unmuted_for_all_users &&
|
lhs.can_be_unmuted_for_all_users == rhs.can_be_unmuted_for_all_users &&
|
||||||
lhs.can_be_muted_only_for_self == rhs.can_be_muted_only_for_self &&
|
lhs.can_be_muted_only_for_self == rhs.can_be_muted_only_for_self &&
|
||||||
lhs.can_be_unmuted_only_for_self == rhs.can_be_unmuted_only_for_self &&
|
lhs.can_be_unmuted_only_for_self == rhs.can_be_unmuted_only_for_self &&
|
||||||
lhs.get_is_muted_for_all_users() == rhs.get_is_muted_for_all_users() &&
|
lhs.get_is_muted_for_all_users() == rhs.get_is_muted_for_all_users() &&
|
||||||
lhs.get_is_muted_locally() == rhs.get_is_muted_locally() &&
|
lhs.get_is_muted_locally() == rhs.get_is_muted_locally() &&
|
||||||
lhs.get_is_muted_by_themselves() == rhs.get_is_muted_by_themselves() && lhs.is_speaking == rhs.is_speaking &&
|
lhs.get_is_muted_by_themselves() == rhs.get_is_muted_by_themselves() &&
|
||||||
lhs.get_volume_level() == rhs.get_volume_level() && lhs.order == rhs.order;
|
lhs.get_volume_level() == rhs.get_volume_level() && lhs.order == rhs.order;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,7 +272,7 @@ bool operator!=(const GroupCallParticipant &lhs, const GroupCallParticipant &rhs
|
|||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder &operator<<(StringBuilder &string_builder, const GroupCallParticipant &group_call_participant) {
|
StringBuilder &operator<<(StringBuilder &string_builder, const GroupCallParticipant &group_call_participant) {
|
||||||
return string_builder << '[' << group_call_participant.user_id << " with source "
|
return string_builder << '[' << group_call_participant.dialog_id << " with source "
|
||||||
<< group_call_participant.audio_source << " and order " << group_call_participant.order << ']';
|
<< group_call_participant.audio_source << " and order " << group_call_participant.order << ']';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,27 +6,31 @@
|
|||||||
//
|
//
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "td/telegram/DialogId.h"
|
||||||
|
#include "td/telegram/GroupCallParticipantOrder.h"
|
||||||
#include "td/telegram/td_api.h"
|
#include "td/telegram/td_api.h"
|
||||||
#include "td/telegram/telegram_api.h"
|
#include "td/telegram/telegram_api.h"
|
||||||
#include "td/telegram/UserId.h"
|
|
||||||
|
|
||||||
#include "td/utils/common.h"
|
#include "td/utils/common.h"
|
||||||
#include "td/utils/StringBuilder.h"
|
#include "td/utils/StringBuilder.h"
|
||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
|
|
||||||
class ContactsManager;
|
class Td;
|
||||||
|
|
||||||
struct GroupCallParticipant {
|
struct GroupCallParticipant {
|
||||||
UserId user_id;
|
DialogId dialog_id;
|
||||||
|
string about;
|
||||||
int32 audio_source = 0;
|
int32 audio_source = 0;
|
||||||
int32 joined_date = 0;
|
int32 joined_date = 0;
|
||||||
int32 active_date = 0;
|
int32 active_date = 0;
|
||||||
int32 volume_level = 10000;
|
int32 volume_level = 10000;
|
||||||
|
int64 raise_hand_rating = 0;
|
||||||
bool is_volume_level_local = false;
|
bool is_volume_level_local = false;
|
||||||
bool server_is_muted_by_themselves = false;
|
bool server_is_muted_by_themselves = false;
|
||||||
bool server_is_muted_by_admin = false;
|
bool server_is_muted_by_admin = false;
|
||||||
bool server_is_muted_locally = false;
|
bool server_is_muted_locally = false;
|
||||||
|
bool is_self = false;
|
||||||
|
|
||||||
bool can_be_muted_for_all_users = false;
|
bool can_be_muted_for_all_users = false;
|
||||||
bool can_be_unmuted_for_all_users = false;
|
bool can_be_unmuted_for_all_users = false;
|
||||||
@ -38,7 +42,8 @@ struct GroupCallParticipant {
|
|||||||
bool is_just_joined = false;
|
bool is_just_joined = false;
|
||||||
bool is_speaking = false;
|
bool is_speaking = false;
|
||||||
int32 local_active_date = 0;
|
int32 local_active_date = 0;
|
||||||
int64 order = 0;
|
GroupCallParticipantOrder order;
|
||||||
|
int32 version = 0;
|
||||||
|
|
||||||
int32 pending_volume_level = 0;
|
int32 pending_volume_level = 0;
|
||||||
uint64 pending_volume_level_generation = 0;
|
uint64 pending_volume_level_generation = 0;
|
||||||
@ -49,27 +54,29 @@ struct GroupCallParticipant {
|
|||||||
bool pending_is_muted_locally = false;
|
bool pending_is_muted_locally = false;
|
||||||
uint64 pending_is_muted_generation = 0;
|
uint64 pending_is_muted_generation = 0;
|
||||||
|
|
||||||
|
bool have_pending_is_hand_raised = false;
|
||||||
|
bool pending_is_hand_raised = false;
|
||||||
|
uint64 pending_is_hand_raised_generation = 0;
|
||||||
|
|
||||||
static constexpr int32 MIN_VOLUME_LEVEL = 1;
|
static constexpr int32 MIN_VOLUME_LEVEL = 1;
|
||||||
static constexpr int32 MAX_VOLUME_LEVEL = 20000;
|
static constexpr int32 MAX_VOLUME_LEVEL = 20000;
|
||||||
|
|
||||||
GroupCallParticipant() = default;
|
GroupCallParticipant() = default;
|
||||||
|
|
||||||
explicit GroupCallParticipant(const tl_object_ptr<telegram_api::groupCallParticipant> &participant);
|
GroupCallParticipant(const tl_object_ptr<telegram_api::groupCallParticipant> &participant, int32 call_version);
|
||||||
|
|
||||||
static bool is_versioned_update(const tl_object_ptr<telegram_api::groupCallParticipant> &participant);
|
static bool is_versioned_update(const tl_object_ptr<telegram_api::groupCallParticipant> &participant);
|
||||||
|
|
||||||
void update_from(const GroupCallParticipant &old_participant);
|
void update_from(const GroupCallParticipant &old_participant);
|
||||||
|
|
||||||
bool update_can_be_muted(bool can_manage, bool is_self, bool is_admin);
|
bool update_can_be_muted(bool can_manage, bool is_admin);
|
||||||
|
|
||||||
bool set_pending_is_muted(bool is_muted, bool can_manage, bool is_self, bool is_admin);
|
bool set_pending_is_muted(bool is_muted, bool can_manage, bool is_admin);
|
||||||
|
|
||||||
int64 get_real_order() const {
|
GroupCallParticipantOrder get_real_order(bool can_self_unmute, bool joined_date_asc, bool keep_active_date) const;
|
||||||
return (static_cast<int64>(max(active_date, local_active_date)) << 32) + joined_date;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_valid() const {
|
bool is_valid() const {
|
||||||
return user_id.is_valid();
|
return dialog_id.is_valid();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool get_is_muted_by_themselves() const;
|
bool get_is_muted_by_themselves() const;
|
||||||
@ -82,8 +89,9 @@ struct GroupCallParticipant {
|
|||||||
|
|
||||||
int32 get_volume_level() const;
|
int32 get_volume_level() const;
|
||||||
|
|
||||||
td_api::object_ptr<td_api::groupCallParticipant> get_group_call_participant_object(
|
bool get_is_hand_raised() const;
|
||||||
ContactsManager *contacts_manager) const;
|
|
||||||
|
td_api::object_ptr<td_api::groupCallParticipant> get_group_call_participant_object(Td *td) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool operator==(const GroupCallParticipant &lhs, const GroupCallParticipant &rhs);
|
bool operator==(const GroupCallParticipant &lhs, const GroupCallParticipant &rhs);
|
||||||
|
67
td/telegram/GroupCallParticipantOrder.cpp
Normal file
67
td/telegram/GroupCallParticipantOrder.cpp
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
//
|
||||||
|
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021
|
||||||
|
//
|
||||||
|
// 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/GroupCallParticipantOrder.h"
|
||||||
|
|
||||||
|
#include "td/utils/logging.h"
|
||||||
|
#include "td/utils/misc.h"
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
namespace td {
|
||||||
|
|
||||||
|
GroupCallParticipantOrder GroupCallParticipantOrder::max() {
|
||||||
|
return GroupCallParticipantOrder(std::numeric_limits<int32>::max(), std::numeric_limits<int64>::max(),
|
||||||
|
std::numeric_limits<int32>::max());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GroupCallParticipantOrder::is_valid() const {
|
||||||
|
return *this != GroupCallParticipantOrder();
|
||||||
|
}
|
||||||
|
|
||||||
|
string GroupCallParticipantOrder::get_group_call_participant_order_object() const {
|
||||||
|
if (!is_valid()) {
|
||||||
|
return string();
|
||||||
|
}
|
||||||
|
return PSTRING() << lpad0(to_string(active_date), 10) << lpad0(to_string(raise_hand_rating), 19)
|
||||||
|
<< lpad0(to_string(joined_date), 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const GroupCallParticipantOrder &lhs, const GroupCallParticipantOrder &rhs) {
|
||||||
|
return lhs.active_date == rhs.active_date && lhs.joined_date == rhs.joined_date &&
|
||||||
|
lhs.raise_hand_rating == rhs.raise_hand_rating;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const GroupCallParticipantOrder &lhs, const GroupCallParticipantOrder &rhs) {
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<(const GroupCallParticipantOrder &lhs, const GroupCallParticipantOrder &rhs) {
|
||||||
|
return std::tie(lhs.active_date, lhs.raise_hand_rating, lhs.joined_date) <
|
||||||
|
std::tie(rhs.active_date, rhs.raise_hand_rating, rhs.joined_date);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<=(const GroupCallParticipantOrder &lhs, const GroupCallParticipantOrder &rhs) {
|
||||||
|
return !(rhs < lhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator>(const GroupCallParticipantOrder &lhs, const GroupCallParticipantOrder &rhs) {
|
||||||
|
return rhs < lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator>=(const GroupCallParticipantOrder &lhs, const GroupCallParticipantOrder &rhs) {
|
||||||
|
return !(lhs < rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder &operator<<(StringBuilder &string_builder,
|
||||||
|
const GroupCallParticipantOrder &group_call_participant_order) {
|
||||||
|
return string_builder << group_call_participant_order.active_date << '/'
|
||||||
|
<< group_call_participant_order.raise_hand_rating << '/'
|
||||||
|
<< group_call_participant_order.joined_date;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace td
|
54
td/telegram/GroupCallParticipantOrder.h
Normal file
54
td/telegram/GroupCallParticipantOrder.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
//
|
||||||
|
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021
|
||||||
|
//
|
||||||
|
// 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)
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "td/utils/common.h"
|
||||||
|
#include "td/utils/StringBuilder.h"
|
||||||
|
|
||||||
|
namespace td {
|
||||||
|
|
||||||
|
class GroupCallParticipantOrder {
|
||||||
|
int32 active_date = 0;
|
||||||
|
int32 joined_date = 0;
|
||||||
|
int64 raise_hand_rating = 0;
|
||||||
|
|
||||||
|
friend StringBuilder &operator<<(StringBuilder &string_builder,
|
||||||
|
const GroupCallParticipantOrder &group_call_participant_order);
|
||||||
|
|
||||||
|
friend bool operator==(const GroupCallParticipantOrder &lhs, const GroupCallParticipantOrder &rhs);
|
||||||
|
|
||||||
|
friend bool operator<(const GroupCallParticipantOrder &lhs, const GroupCallParticipantOrder &rhs);
|
||||||
|
|
||||||
|
public:
|
||||||
|
GroupCallParticipantOrder() = default;
|
||||||
|
|
||||||
|
GroupCallParticipantOrder(int32 active_date, int64 raise_hand_rating, int32 joined_date)
|
||||||
|
: active_date(active_date), joined_date(joined_date), raise_hand_rating(raise_hand_rating) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static GroupCallParticipantOrder max();
|
||||||
|
|
||||||
|
bool is_valid() const;
|
||||||
|
|
||||||
|
string get_group_call_participant_order_object() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool operator==(const GroupCallParticipantOrder &lhs, const GroupCallParticipantOrder &rhs);
|
||||||
|
|
||||||
|
bool operator!=(const GroupCallParticipantOrder &lhs, const GroupCallParticipantOrder &rhs);
|
||||||
|
|
||||||
|
bool operator<(const GroupCallParticipantOrder &lhs, const GroupCallParticipantOrder &rhs);
|
||||||
|
|
||||||
|
bool operator<=(const GroupCallParticipantOrder &lhs, const GroupCallParticipantOrder &rhs);
|
||||||
|
|
||||||
|
bool operator>(const GroupCallParticipantOrder &lhs, const GroupCallParticipantOrder &rhs);
|
||||||
|
|
||||||
|
bool operator>=(const GroupCallParticipantOrder &lhs, const GroupCallParticipantOrder &rhs);
|
||||||
|
|
||||||
|
StringBuilder &operator<<(StringBuilder &string_builder, const GroupCallParticipantOrder &group_call_participant_order);
|
||||||
|
|
||||||
|
} // namespace td
|
@ -27,9 +27,11 @@
|
|||||||
#include "td/telegram/InputMessageText.h"
|
#include "td/telegram/InputMessageText.h"
|
||||||
#include "td/telegram/Location.h"
|
#include "td/telegram/Location.h"
|
||||||
#include "td/telegram/MessageContent.h"
|
#include "td/telegram/MessageContent.h"
|
||||||
|
#include "td/telegram/MessageContentType.h"
|
||||||
#include "td/telegram/MessageEntity.h"
|
#include "td/telegram/MessageEntity.h"
|
||||||
#include "td/telegram/MessagesManager.h"
|
#include "td/telegram/MessagesManager.h"
|
||||||
#include "td/telegram/misc.h"
|
#include "td/telegram/misc.h"
|
||||||
|
#include "td/telegram/Payments.h"
|
||||||
#include "td/telegram/Photo.h"
|
#include "td/telegram/Photo.h"
|
||||||
#include "td/telegram/ReplyMarkup.h"
|
#include "td/telegram/ReplyMarkup.h"
|
||||||
#include "td/telegram/StickersManager.h"
|
#include "td/telegram/StickersManager.h"
|
||||||
@ -59,6 +61,7 @@ namespace td {
|
|||||||
|
|
||||||
class GetInlineBotResultsQuery : public Td::ResultHandler {
|
class GetInlineBotResultsQuery : public Td::ResultHandler {
|
||||||
Promise<Unit> promise_;
|
Promise<Unit> promise_;
|
||||||
|
DialogId dialog_id_;
|
||||||
UserId bot_user_id_;
|
UserId bot_user_id_;
|
||||||
uint64 query_hash_;
|
uint64 query_hash_;
|
||||||
|
|
||||||
@ -68,11 +71,12 @@ class GetInlineBotResultsQuery : public Td::ResultHandler {
|
|||||||
explicit GetInlineBotResultsQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
explicit GetInlineBotResultsQuery(Promise<Unit> &&promise) : promise_(std::move(promise)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
NetQueryRef send(UserId bot_user_id, tl_object_ptr<telegram_api::InputUser> bot_input_user,
|
NetQueryRef send(UserId bot_user_id, DialogId dialog_id, tl_object_ptr<telegram_api::InputUser> bot_input_user,
|
||||||
tl_object_ptr<telegram_api::InputPeer> input_peer, Location user_location, const string &query,
|
tl_object_ptr<telegram_api::InputPeer> input_peer, Location user_location, const string &query,
|
||||||
const string &offset, uint64 query_hash) {
|
const string &offset, uint64 query_hash) {
|
||||||
CHECK(input_peer != nullptr);
|
CHECK(input_peer != nullptr);
|
||||||
bot_user_id_ = bot_user_id;
|
bot_user_id_ = bot_user_id;
|
||||||
|
dialog_id_ = dialog_id;
|
||||||
query_hash_ = query_hash;
|
query_hash_ = query_hash;
|
||||||
int32 flags = 0;
|
int32 flags = 0;
|
||||||
if (!user_location.empty()) {
|
if (!user_location.empty()) {
|
||||||
@ -94,7 +98,8 @@ class GetInlineBotResultsQuery : public Td::ResultHandler {
|
|||||||
return on_error(id, result_ptr.move_as_error());
|
return on_error(id, result_ptr.move_as_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
td->inline_queries_manager_->on_get_inline_query_results(bot_user_id_, query_hash_, result_ptr.move_as_ok());
|
td->inline_queries_manager_->on_get_inline_query_results(dialog_id_, bot_user_id_, query_hash_,
|
||||||
|
result_ptr.move_as_ok());
|
||||||
promise_.set_value(Unit());
|
promise_.set_value(Unit());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,7 +111,7 @@ class GetInlineBotResultsQuery : public Td::ResultHandler {
|
|||||||
}
|
}
|
||||||
LOG(INFO) << "Inline query returned error " << status;
|
LOG(INFO) << "Inline query returned error " << status;
|
||||||
|
|
||||||
td->inline_queries_manager_->on_get_inline_query_results(bot_user_id_, query_hash_, nullptr);
|
td->inline_queries_manager_->on_get_inline_query_results(dialog_id_, bot_user_id_, query_hash_, nullptr);
|
||||||
promise_.set_error(std::move(status));
|
promise_.set_error(std::move(status));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -211,7 +216,7 @@ tl_object_ptr<telegram_api::inputBotInlineMessageID> InlineQueriesManager::get_i
|
|||||||
if (!DcId::is_valid(result->dc_id_)) {
|
if (!DcId::is_valid(result->dc_id_)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
LOG(INFO) << "Have inline message id: " << to_string(result);
|
LOG(INFO) << "Have inline message identifier: " << to_string(result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,7 +225,7 @@ string InlineQueriesManager::get_inline_message_id(
|
|||||||
if (input_bot_inline_message_id == nullptr) {
|
if (input_bot_inline_message_id == nullptr) {
|
||||||
return string();
|
return string();
|
||||||
}
|
}
|
||||||
LOG(INFO) << "Got inline message id: " << to_string(input_bot_inline_message_id);
|
LOG(INFO) << "Got inline message identifier: " << to_string(input_bot_inline_message_id);
|
||||||
|
|
||||||
return base64url_encode(serialize(*input_bot_inline_message_id));
|
return base64url_encode(serialize(*input_bot_inline_message_id));
|
||||||
}
|
}
|
||||||
@ -233,16 +238,15 @@ Result<tl_object_ptr<telegram_api::InputBotInlineMessage>> InlineQueriesManager:
|
|||||||
}
|
}
|
||||||
TRY_RESULT(reply_markup, get_reply_markup(std::move(reply_markup_ptr), true, true, false, true));
|
TRY_RESULT(reply_markup, get_reply_markup(std::move(reply_markup_ptr), true, true, false, true));
|
||||||
auto input_reply_markup = get_input_reply_markup(reply_markup);
|
auto input_reply_markup = get_input_reply_markup(reply_markup);
|
||||||
int32 flags = 0;
|
|
||||||
if (input_reply_markup != nullptr) {
|
|
||||||
flags |= telegram_api::inputBotInlineMessageText::REPLY_MARKUP_MASK;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto constructor_id = input_message_content->get_id();
|
auto constructor_id = input_message_content->get_id();
|
||||||
if (constructor_id == td_api::inputMessageText::ID) {
|
if (constructor_id == td_api::inputMessageText::ID) {
|
||||||
TRY_RESULT(input_message_text, process_input_message_text(td_->contacts_manager_.get(), DialogId(),
|
TRY_RESULT(input_message_text, process_input_message_text(td_->contacts_manager_.get(), DialogId(),
|
||||||
std::move(input_message_content), true));
|
std::move(input_message_content), true));
|
||||||
|
int32 flags = 0;
|
||||||
|
if (input_reply_markup != nullptr) {
|
||||||
|
flags |= telegram_api::inputBotInlineMessageText::REPLY_MARKUP_MASK;
|
||||||
|
}
|
||||||
if (input_message_text.disable_web_page_preview) {
|
if (input_message_text.disable_web_page_preview) {
|
||||||
flags |= telegram_api::inputBotInlineMessageText::NO_WEBPAGE_MASK;
|
flags |= telegram_api::inputBotInlineMessageText::NO_WEBPAGE_MASK;
|
||||||
}
|
}
|
||||||
@ -257,10 +261,18 @@ Result<tl_object_ptr<telegram_api::InputBotInlineMessage>> InlineQueriesManager:
|
|||||||
}
|
}
|
||||||
if (constructor_id == td_api::inputMessageContact::ID) {
|
if (constructor_id == td_api::inputMessageContact::ID) {
|
||||||
TRY_RESULT(contact, process_input_message_contact(std::move(input_message_content)));
|
TRY_RESULT(contact, process_input_message_contact(std::move(input_message_content)));
|
||||||
return contact.get_input_bot_inline_message_media_contact(flags, std::move(input_reply_markup));
|
return contact.get_input_bot_inline_message_media_contact(std::move(input_reply_markup));
|
||||||
|
}
|
||||||
|
if (constructor_id == td_api::inputMessageInvoice::ID) {
|
||||||
|
TRY_RESULT(input_invoice, process_input_message_invoice(std::move(input_message_content), td_));
|
||||||
|
return get_input_bot_inline_message_media_invoice(input_invoice, std::move(input_reply_markup), td_);
|
||||||
}
|
}
|
||||||
if (constructor_id == td_api::inputMessageLocation::ID) {
|
if (constructor_id == td_api::inputMessageLocation::ID) {
|
||||||
TRY_RESULT(location, process_input_message_location(std::move(input_message_content)));
|
TRY_RESULT(location, process_input_message_location(std::move(input_message_content)));
|
||||||
|
int32 flags = 0;
|
||||||
|
if (input_reply_markup != nullptr) {
|
||||||
|
flags |= telegram_api::inputBotInlineMessageMediaGeo::REPLY_MARKUP_MASK;
|
||||||
|
}
|
||||||
if (location.heading != 0) {
|
if (location.heading != 0) {
|
||||||
flags |= telegram_api::inputBotInlineMessageMediaGeo::HEADING_MASK;
|
flags |= telegram_api::inputBotInlineMessageMediaGeo::HEADING_MASK;
|
||||||
}
|
}
|
||||||
@ -274,16 +286,19 @@ Result<tl_object_ptr<telegram_api::InputBotInlineMessage>> InlineQueriesManager:
|
|||||||
}
|
}
|
||||||
if (constructor_id == td_api::inputMessageVenue::ID) {
|
if (constructor_id == td_api::inputMessageVenue::ID) {
|
||||||
TRY_RESULT(venue, process_input_message_venue(std::move(input_message_content)));
|
TRY_RESULT(venue, process_input_message_venue(std::move(input_message_content)));
|
||||||
return venue.get_input_bot_inline_message_media_venue(flags, std::move(input_reply_markup));
|
return venue.get_input_bot_inline_message_media_venue(std::move(input_reply_markup));
|
||||||
}
|
}
|
||||||
if (constructor_id == allowed_media_content_id) {
|
if (constructor_id == allowed_media_content_id) {
|
||||||
TRY_RESULT(caption, process_input_caption(td_->contacts_manager_.get(), DialogId(),
|
TRY_RESULT(caption, process_input_caption(td_->contacts_manager_.get(), DialogId(),
|
||||||
extract_input_caption(input_message_content), true));
|
extract_input_caption(input_message_content), true));
|
||||||
|
int32 flags = 0;
|
||||||
|
if (input_reply_markup != nullptr) {
|
||||||
|
flags |= telegram_api::inputBotInlineMessageMediaAuto::REPLY_MARKUP_MASK;
|
||||||
|
}
|
||||||
auto entities = get_input_message_entities(td_->contacts_manager_.get(), caption.entities, "get_inline_message");
|
auto entities = get_input_message_entities(td_->contacts_manager_.get(), caption.entities, "get_inline_message");
|
||||||
if (!entities.empty()) {
|
if (!entities.empty()) {
|
||||||
flags |= telegram_api::inputBotInlineMessageText::ENTITIES_MASK;
|
flags |= telegram_api::inputBotInlineMessageMediaAuto::ENTITIES_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
return make_tl_object<telegram_api::inputBotInlineMessageMediaAuto>(flags, caption.text, std::move(entities),
|
return make_tl_object<telegram_api::inputBotInlineMessageMediaAuto>(flags, caption.text, std::move(entities),
|
||||||
std::move(input_reply_markup));
|
std::move(input_reply_markup));
|
||||||
}
|
}
|
||||||
@ -292,11 +307,15 @@ Result<tl_object_ptr<telegram_api::InputBotInlineMessage>> InlineQueriesManager:
|
|||||||
|
|
||||||
bool InlineQueriesManager::register_inline_message_content(
|
bool InlineQueriesManager::register_inline_message_content(
|
||||||
int64 query_id, const string &result_id, FileId file_id,
|
int64 query_id, const string &result_id, FileId file_id,
|
||||||
tl_object_ptr<telegram_api::BotInlineMessage> &&inline_message, int32 allowed_media_content_id, Photo *photo,
|
tl_object_ptr<telegram_api::BotInlineMessage> &&inline_message, int32 allowed_media_content_id, bool allow_invoice,
|
||||||
Game *game) {
|
Photo *photo, Game *game) {
|
||||||
InlineMessageContent content =
|
InlineMessageContent content =
|
||||||
create_inline_message_content(td_, file_id, std::move(inline_message), allowed_media_content_id, photo, game);
|
create_inline_message_content(td_, file_id, std::move(inline_message), allowed_media_content_id, photo, game);
|
||||||
if (content.message_content != nullptr) {
|
if (content.message_content != nullptr) {
|
||||||
|
if (!allow_invoice && content.message_content->get_type() == MessageContentType::Invoice) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
inline_message_contents_[query_id].emplace(result_id, std::move(content));
|
inline_message_contents_[query_id].emplace(result_id, std::move(content));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -811,12 +830,13 @@ uint64 InlineQueriesManager::send_inline_query(UserId bot_user_id, DialogId dial
|
|||||||
|
|
||||||
if (pending_inline_query_ != nullptr) {
|
if (pending_inline_query_ != nullptr) {
|
||||||
LOG(INFO) << "Drop inline query " << pending_inline_query_->query_hash;
|
LOG(INFO) << "Drop inline query " << pending_inline_query_->query_hash;
|
||||||
on_get_inline_query_results(pending_inline_query_->bot_user_id, pending_inline_query_->query_hash, nullptr);
|
on_get_inline_query_results(pending_inline_query_->dialog_id, pending_inline_query_->bot_user_id,
|
||||||
|
pending_inline_query_->query_hash, nullptr);
|
||||||
pending_inline_query_->promise.set_error(Status::Error(406, "Request cancelled"));
|
pending_inline_query_->promise.set_error(Status::Error(406, "Request cancelled"));
|
||||||
}
|
}
|
||||||
|
|
||||||
pending_inline_query_ = make_unique<PendingInlineQuery>(PendingInlineQuery{
|
pending_inline_query_ = make_unique<PendingInlineQuery>(PendingInlineQuery{
|
||||||
query_hash, bot_user_id, std::move(input_peer), user_location, query, offset, std::move(promise)});
|
query_hash, bot_user_id, dialog_id, std::move(input_peer), user_location, query, offset, std::move(promise)});
|
||||||
|
|
||||||
loop();
|
loop();
|
||||||
|
|
||||||
@ -840,7 +860,7 @@ void InlineQueriesManager::loop() {
|
|||||||
}
|
}
|
||||||
sent_query_ =
|
sent_query_ =
|
||||||
td_->create_handler<GetInlineBotResultsQuery>(std::move(pending_inline_query_->promise))
|
td_->create_handler<GetInlineBotResultsQuery>(std::move(pending_inline_query_->promise))
|
||||||
->send(pending_inline_query_->bot_user_id, std::move(bot_input_user),
|
->send(pending_inline_query_->bot_user_id, pending_inline_query_->dialog_id, std::move(bot_input_user),
|
||||||
std::move(pending_inline_query_->input_peer), pending_inline_query_->user_location,
|
std::move(pending_inline_query_->input_peer), pending_inline_query_->user_location,
|
||||||
pending_inline_query_->query, pending_inline_query_->offset, pending_inline_query_->query_hash);
|
pending_inline_query_->query, pending_inline_query_->offset, pending_inline_query_->query_hash);
|
||||||
|
|
||||||
@ -1219,7 +1239,7 @@ string InlineQueriesManager::get_web_document_content_type(
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void InlineQueriesManager::on_get_inline_query_results(UserId bot_user_id, uint64 query_hash,
|
void InlineQueriesManager::on_get_inline_query_results(DialogId dialog_id, UserId bot_user_id, uint64 query_hash,
|
||||||
tl_object_ptr<telegram_api::messages_botResults> &&results) {
|
tl_object_ptr<telegram_api::messages_botResults> &&results) {
|
||||||
LOG(INFO) << "Receive results for inline query " << query_hash;
|
LOG(INFO) << "Receive results for inline query " << query_hash;
|
||||||
if (results == nullptr) {
|
if (results == nullptr) {
|
||||||
@ -1230,6 +1250,8 @@ void InlineQueriesManager::on_get_inline_query_results(UserId bot_user_id, uint6
|
|||||||
|
|
||||||
td_->contacts_manager_->on_get_users(std::move(results->users_), "on_get_inline_query_results");
|
td_->contacts_manager_->on_get_users(std::move(results->users_), "on_get_inline_query_results");
|
||||||
|
|
||||||
|
auto dialog_type = dialog_id.get_type();
|
||||||
|
bool allow_invoice = dialog_type != DialogType::SecretChat;
|
||||||
vector<tl_object_ptr<td_api::InlineQueryResult>> output_results;
|
vector<tl_object_ptr<td_api::InlineQueryResult>> output_results;
|
||||||
for (auto &result_ptr : results->results_) {
|
for (auto &result_ptr : results->results_) {
|
||||||
tl_object_ptr<td_api::InlineQueryResult> output_result;
|
tl_object_ptr<td_api::InlineQueryResult> output_result;
|
||||||
@ -1245,6 +1267,14 @@ void InlineQueriesManager::on_get_inline_query_results(UserId bot_user_id, uint6
|
|||||||
LOG(ERROR) << "Receive game without photo in the result of inline query: " << to_string(result);
|
LOG(ERROR) << "Receive game without photo in the result of inline query: " << to_string(result);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (dialog_type == DialogType::Channel &&
|
||||||
|
td_->contacts_manager_->get_channel_type(dialog_id.get_channel_id()) == ChannelType::Broadcast) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (dialog_type == DialogType::SecretChat) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
auto game = make_tl_object<td_api::inlineQueryResultGame>();
|
auto game = make_tl_object<td_api::inlineQueryResultGame>();
|
||||||
Game inline_game(td_, std::move(result->title_), std::move(result->description_), std::move(result->photo_),
|
Game inline_game(td_, std::move(result->title_), std::move(result->description_), std::move(result->photo_),
|
||||||
std::move(result->document_), DialogId());
|
std::move(result->document_), DialogId());
|
||||||
@ -1253,8 +1283,8 @@ void InlineQueriesManager::on_get_inline_query_results(UserId bot_user_id, uint6
|
|||||||
game->game_ = inline_game.get_game_object(td_);
|
game->game_ = inline_game.get_game_object(td_);
|
||||||
|
|
||||||
if (!register_inline_message_content(results->query_id_, game->id_, FileId(),
|
if (!register_inline_message_content(results->query_id_, game->id_, FileId(),
|
||||||
std::move(result->send_message_), td_api::inputMessageGame::ID, nullptr,
|
std::move(result->send_message_), td_api::inputMessageGame::ID,
|
||||||
&inline_game)) {
|
allow_invoice, nullptr, &inline_game)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
output_result = std::move(game);
|
output_result = std::move(game);
|
||||||
@ -1280,8 +1310,8 @@ void InlineQueriesManager::on_get_inline_query_results(UserId bot_user_id, uint6
|
|||||||
animation->title_ = std::move(result->title_);
|
animation->title_ = std::move(result->title_);
|
||||||
|
|
||||||
if (!register_inline_message_content(results->query_id_, animation->id_, parsed_document.file_id,
|
if (!register_inline_message_content(results->query_id_, animation->id_, parsed_document.file_id,
|
||||||
std::move(result->send_message_),
|
std::move(result->send_message_), td_api::inputMessageAnimation::ID,
|
||||||
td_api::inputMessageAnimation::ID)) {
|
allow_invoice)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
output_result = std::move(animation);
|
output_result = std::move(animation);
|
||||||
@ -1295,7 +1325,8 @@ void InlineQueriesManager::on_get_inline_query_results(UserId bot_user_id, uint6
|
|||||||
audio->audio_ = td_->audios_manager_->get_audio_object(parsed_document.file_id);
|
audio->audio_ = td_->audios_manager_->get_audio_object(parsed_document.file_id);
|
||||||
|
|
||||||
if (!register_inline_message_content(results->query_id_, audio->id_, parsed_document.file_id,
|
if (!register_inline_message_content(results->query_id_, audio->id_, parsed_document.file_id,
|
||||||
std::move(result->send_message_), td_api::inputMessageAudio::ID)) {
|
std::move(result->send_message_), td_api::inputMessageAudio::ID,
|
||||||
|
allow_invoice)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
output_result = std::move(audio);
|
output_result = std::move(audio);
|
||||||
@ -1312,8 +1343,8 @@ void InlineQueriesManager::on_get_inline_query_results(UserId bot_user_id, uint6
|
|||||||
document->description_ = std::move(result->description_);
|
document->description_ = std::move(result->description_);
|
||||||
|
|
||||||
if (!register_inline_message_content(results->query_id_, document->id_, parsed_document.file_id,
|
if (!register_inline_message_content(results->query_id_, document->id_, parsed_document.file_id,
|
||||||
std::move(result->send_message_),
|
std::move(result->send_message_), td_api::inputMessageDocument::ID,
|
||||||
td_api::inputMessageDocument::ID)) {
|
allow_invoice)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
output_result = std::move(document);
|
output_result = std::move(document);
|
||||||
@ -1327,7 +1358,8 @@ void InlineQueriesManager::on_get_inline_query_results(UserId bot_user_id, uint6
|
|||||||
sticker->sticker_ = td_->stickers_manager_->get_sticker_object(parsed_document.file_id);
|
sticker->sticker_ = td_->stickers_manager_->get_sticker_object(parsed_document.file_id);
|
||||||
|
|
||||||
if (!register_inline_message_content(results->query_id_, sticker->id_, parsed_document.file_id,
|
if (!register_inline_message_content(results->query_id_, sticker->id_, parsed_document.file_id,
|
||||||
std::move(result->send_message_), td_api::inputMessageSticker::ID)) {
|
std::move(result->send_message_), td_api::inputMessageSticker::ID,
|
||||||
|
allow_invoice)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
output_result = std::move(sticker);
|
output_result = std::move(sticker);
|
||||||
@ -1343,7 +1375,8 @@ void InlineQueriesManager::on_get_inline_query_results(UserId bot_user_id, uint6
|
|||||||
video->description_ = std::move(result->description_);
|
video->description_ = std::move(result->description_);
|
||||||
|
|
||||||
if (!register_inline_message_content(results->query_id_, video->id_, parsed_document.file_id,
|
if (!register_inline_message_content(results->query_id_, video->id_, parsed_document.file_id,
|
||||||
std::move(result->send_message_), td_api::inputMessageVideo::ID)) {
|
std::move(result->send_message_), td_api::inputMessageVideo::ID,
|
||||||
|
allow_invoice)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
output_result = std::move(video);
|
output_result = std::move(video);
|
||||||
@ -1361,8 +1394,8 @@ void InlineQueriesManager::on_get_inline_query_results(UserId bot_user_id, uint6
|
|||||||
voice_note->title_ = std::move(result->title_);
|
voice_note->title_ = std::move(result->title_);
|
||||||
|
|
||||||
if (!register_inline_message_content(results->query_id_, voice_note->id_, parsed_document.file_id,
|
if (!register_inline_message_content(results->query_id_, voice_note->id_, parsed_document.file_id,
|
||||||
std::move(result->send_message_),
|
std::move(result->send_message_), td_api::inputMessageVoiceNote::ID,
|
||||||
td_api::inputMessageVoiceNote::ID)) {
|
allow_invoice)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
output_result = std::move(voice_note);
|
output_result = std::move(voice_note);
|
||||||
@ -1389,7 +1422,8 @@ void InlineQueriesManager::on_get_inline_query_results(UserId bot_user_id, uint6
|
|||||||
photo->description_ = std::move(result->description_);
|
photo->description_ = std::move(result->description_);
|
||||||
|
|
||||||
if (!register_inline_message_content(results->query_id_, photo->id_, FileId(),
|
if (!register_inline_message_content(results->query_id_, photo->id_, FileId(),
|
||||||
std::move(result->send_message_), td_api::inputMessagePhoto::ID, &p)) {
|
std::move(result->send_message_), td_api::inputMessagePhoto::ID,
|
||||||
|
allow_invoice, &p)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
output_result = std::move(photo);
|
output_result = std::move(photo);
|
||||||
@ -1417,7 +1451,7 @@ void InlineQueriesManager::on_get_inline_query_results(UserId bot_user_id, uint6
|
|||||||
article->thumbnail_ = register_thumbnail(std::move(result->thumb_));
|
article->thumbnail_ = register_thumbnail(std::move(result->thumb_));
|
||||||
|
|
||||||
if (!register_inline_message_content(results->query_id_, article->id_, FileId(),
|
if (!register_inline_message_content(results->query_id_, article->id_, FileId(),
|
||||||
std::move(result->send_message_), -1)) {
|
std::move(result->send_message_), -1, allow_invoice)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
output_result = std::move(article);
|
output_result = std::move(article);
|
||||||
@ -1428,16 +1462,16 @@ void InlineQueriesManager::on_get_inline_query_results(UserId bot_user_id, uint6
|
|||||||
auto inline_message_contact =
|
auto inline_message_contact =
|
||||||
static_cast<const telegram_api::botInlineMessageMediaContact *>(result->send_message_.get());
|
static_cast<const telegram_api::botInlineMessageMediaContact *>(result->send_message_.get());
|
||||||
Contact c(inline_message_contact->phone_number_, inline_message_contact->first_name_,
|
Contact c(inline_message_contact->phone_number_, inline_message_contact->first_name_,
|
||||||
inline_message_contact->last_name_, inline_message_contact->vcard_, 0);
|
inline_message_contact->last_name_, inline_message_contact->vcard_, UserId());
|
||||||
contact->contact_ = c.get_contact_object();
|
contact->contact_ = c.get_contact_object();
|
||||||
} else {
|
} else {
|
||||||
Contact c(std::move(result->description_), std::move(result->title_), string(), string(), 0);
|
Contact c(std::move(result->description_), std::move(result->title_), string(), string(), UserId());
|
||||||
contact->contact_ = c.get_contact_object();
|
contact->contact_ = c.get_contact_object();
|
||||||
}
|
}
|
||||||
contact->thumbnail_ = register_thumbnail(std::move(result->thumb_));
|
contact->thumbnail_ = register_thumbnail(std::move(result->thumb_));
|
||||||
|
|
||||||
if (!register_inline_message_content(results->query_id_, contact->id_, FileId(),
|
if (!register_inline_message_content(results->query_id_, contact->id_, FileId(),
|
||||||
std::move(result->send_message_), -1)) {
|
std::move(result->send_message_), -1, allow_invoice)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
output_result = std::move(contact);
|
output_result = std::move(contact);
|
||||||
@ -1458,7 +1492,7 @@ void InlineQueriesManager::on_get_inline_query_results(UserId bot_user_id, uint6
|
|||||||
location->thumbnail_ = register_thumbnail(std::move(result->thumb_));
|
location->thumbnail_ = register_thumbnail(std::move(result->thumb_));
|
||||||
|
|
||||||
if (!register_inline_message_content(results->query_id_, location->id_, FileId(),
|
if (!register_inline_message_content(results->query_id_, location->id_, FileId(),
|
||||||
std::move(result->send_message_), -1)) {
|
std::move(result->send_message_), -1, allow_invoice)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
output_result = std::move(location);
|
output_result = std::move(location);
|
||||||
@ -1485,7 +1519,7 @@ void InlineQueriesManager::on_get_inline_query_results(UserId bot_user_id, uint6
|
|||||||
venue->thumbnail_ = register_thumbnail(std::move(result->thumb_));
|
venue->thumbnail_ = register_thumbnail(std::move(result->thumb_));
|
||||||
|
|
||||||
if (!register_inline_message_content(results->query_id_, venue->id_, FileId(),
|
if (!register_inline_message_content(results->query_id_, venue->id_, FileId(),
|
||||||
std::move(result->send_message_), -1)) {
|
std::move(result->send_message_), -1, allow_invoice)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
output_result = std::move(venue);
|
output_result = std::move(venue);
|
||||||
@ -1515,7 +1549,7 @@ void InlineQueriesManager::on_get_inline_query_results(UserId bot_user_id, uint6
|
|||||||
|
|
||||||
if (!register_inline_message_content(results->query_id_, photo->id_, FileId(),
|
if (!register_inline_message_content(results->query_id_, photo->id_, FileId(),
|
||||||
std::move(result->send_message_), td_api::inputMessagePhoto::ID,
|
std::move(result->send_message_), td_api::inputMessagePhoto::ID,
|
||||||
&new_photo)) {
|
allow_invoice, &new_photo)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
output_result = std::move(photo);
|
output_result = std::move(photo);
|
||||||
@ -1567,7 +1601,8 @@ void InlineQueriesManager::on_get_inline_query_results(UserId bot_user_id, uint6
|
|||||||
audio->id_ = std::move(result->id_);
|
audio->id_ = std::move(result->id_);
|
||||||
audio->audio_ = td_->audios_manager_->get_audio_object(file_id);
|
audio->audio_ = td_->audios_manager_->get_audio_object(file_id);
|
||||||
if (!register_inline_message_content(results->query_id_, audio->id_, file_id,
|
if (!register_inline_message_content(results->query_id_, audio->id_, file_id,
|
||||||
std::move(result->send_message_), td_api::inputMessageAudio::ID)) {
|
std::move(result->send_message_), td_api::inputMessageAudio::ID,
|
||||||
|
allow_invoice)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
output_result = std::move(audio);
|
output_result = std::move(audio);
|
||||||
@ -1578,7 +1613,8 @@ void InlineQueriesManager::on_get_inline_query_results(UserId bot_user_id, uint6
|
|||||||
document->title_ = std::move(result->title_);
|
document->title_ = std::move(result->title_);
|
||||||
document->description_ = std::move(result->description_);
|
document->description_ = std::move(result->description_);
|
||||||
if (!register_inline_message_content(results->query_id_, document->id_, file_id,
|
if (!register_inline_message_content(results->query_id_, document->id_, file_id,
|
||||||
std::move(result->send_message_), td_api::inputMessageDocument::ID)) {
|
std::move(result->send_message_), td_api::inputMessageDocument::ID,
|
||||||
|
allow_invoice)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
output_result = std::move(document);
|
output_result = std::move(document);
|
||||||
@ -1589,7 +1625,8 @@ void InlineQueriesManager::on_get_inline_query_results(UserId bot_user_id, uint6
|
|||||||
td_->animations_manager_->get_animation_object(file_id, "inlineQueryResultAnimationCached");
|
td_->animations_manager_->get_animation_object(file_id, "inlineQueryResultAnimationCached");
|
||||||
animation->title_ = std::move(result->title_);
|
animation->title_ = std::move(result->title_);
|
||||||
if (!register_inline_message_content(results->query_id_, animation->id_, file_id,
|
if (!register_inline_message_content(results->query_id_, animation->id_, file_id,
|
||||||
std::move(result->send_message_), td_api::inputMessageAnimation::ID)) {
|
std::move(result->send_message_), td_api::inputMessageAnimation::ID,
|
||||||
|
allow_invoice)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
output_result = std::move(animation);
|
output_result = std::move(animation);
|
||||||
@ -1598,7 +1635,8 @@ void InlineQueriesManager::on_get_inline_query_results(UserId bot_user_id, uint6
|
|||||||
sticker->id_ = std::move(result->id_);
|
sticker->id_ = std::move(result->id_);
|
||||||
sticker->sticker_ = td_->stickers_manager_->get_sticker_object(file_id);
|
sticker->sticker_ = td_->stickers_manager_->get_sticker_object(file_id);
|
||||||
if (!register_inline_message_content(results->query_id_, sticker->id_, file_id,
|
if (!register_inline_message_content(results->query_id_, sticker->id_, file_id,
|
||||||
std::move(result->send_message_), td_api::inputMessageSticker::ID)) {
|
std::move(result->send_message_), td_api::inputMessageSticker::ID,
|
||||||
|
allow_invoice)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
output_result = std::move(sticker);
|
output_result = std::move(sticker);
|
||||||
@ -1609,7 +1647,8 @@ void InlineQueriesManager::on_get_inline_query_results(UserId bot_user_id, uint6
|
|||||||
video->title_ = std::move(result->title_);
|
video->title_ = std::move(result->title_);
|
||||||
video->description_ = std::move(result->description_);
|
video->description_ = std::move(result->description_);
|
||||||
if (!register_inline_message_content(results->query_id_, video->id_, file_id,
|
if (!register_inline_message_content(results->query_id_, video->id_, file_id,
|
||||||
std::move(result->send_message_), td_api::inputMessageVideo::ID)) {
|
std::move(result->send_message_), td_api::inputMessageVideo::ID,
|
||||||
|
allow_invoice)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
output_result = std::move(video);
|
output_result = std::move(video);
|
||||||
@ -1619,7 +1658,8 @@ void InlineQueriesManager::on_get_inline_query_results(UserId bot_user_id, uint6
|
|||||||
voice_note->voice_note_ = td_->voice_notes_manager_->get_voice_note_object(file_id);
|
voice_note->voice_note_ = td_->voice_notes_manager_->get_voice_note_object(file_id);
|
||||||
voice_note->title_ = std::move(result->title_);
|
voice_note->title_ = std::move(result->title_);
|
||||||
if (!register_inline_message_content(results->query_id_, voice_note->id_, file_id,
|
if (!register_inline_message_content(results->query_id_, voice_note->id_, file_id,
|
||||||
std::move(result->send_message_), td_api::inputMessageVoiceNote::ID)) {
|
std::move(result->send_message_), td_api::inputMessageVoiceNote::ID,
|
||||||
|
allow_invoice)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
output_result = std::move(voice_note);
|
output_result = std::move(voice_note);
|
||||||
@ -1753,7 +1793,6 @@ bool InlineQueriesManager::load_recently_used_bots(Promise<Unit> &promise) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tl_object_ptr<td_api::inlineQueryResults> InlineQueriesManager::get_inline_query_results_object(uint64 query_hash) {
|
tl_object_ptr<td_api::inlineQueryResults> InlineQueriesManager::get_inline_query_results_object(uint64 query_hash) {
|
||||||
// TODO filter out games if request is sent in a broadcast channel or in a secret chat
|
|
||||||
return decrease_pending_request_count(query_hash);
|
return decrease_pending_request_count(query_hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ class InlineQueriesManager : public Actor {
|
|||||||
|
|
||||||
UserId get_inline_bot_user_id(int64 query_id) const;
|
UserId get_inline_bot_user_id(int64 query_id) const;
|
||||||
|
|
||||||
void on_get_inline_query_results(UserId bot_user_id, uint64 query_hash,
|
void on_get_inline_query_results(DialogId dialog_id, UserId bot_user_id, uint64 query_hash,
|
||||||
tl_object_ptr<telegram_api::messages_botResults> &&results);
|
tl_object_ptr<telegram_api::messages_botResults> &&results);
|
||||||
|
|
||||||
tl_object_ptr<td_api::inlineQueryResults> get_inline_query_results_object(uint64 query_hash);
|
tl_object_ptr<td_api::inlineQueryResults> get_inline_query_results_object(uint64 query_hash);
|
||||||
@ -95,7 +95,8 @@ class InlineQueriesManager : public Actor {
|
|||||||
|
|
||||||
bool register_inline_message_content(int64 query_id, const string &result_id, FileId file_id,
|
bool register_inline_message_content(int64 query_id, const string &result_id, FileId file_id,
|
||||||
tl_object_ptr<telegram_api::BotInlineMessage> &&inline_message,
|
tl_object_ptr<telegram_api::BotInlineMessage> &&inline_message,
|
||||||
int32 allowed_media_content_id, Photo *photo = nullptr, Game *game = nullptr);
|
int32 allowed_media_content_id, bool allow_invoice, Photo *photo = nullptr,
|
||||||
|
Game *game = nullptr);
|
||||||
|
|
||||||
tl_object_ptr<td_api::thumbnail> register_thumbnail(
|
tl_object_ptr<td_api::thumbnail> register_thumbnail(
|
||||||
tl_object_ptr<telegram_api::WebDocument> &&web_document_ptr) const;
|
tl_object_ptr<telegram_api::WebDocument> &&web_document_ptr) const;
|
||||||
@ -126,6 +127,7 @@ class InlineQueriesManager : public Actor {
|
|||||||
struct PendingInlineQuery {
|
struct PendingInlineQuery {
|
||||||
uint64 query_hash;
|
uint64 query_hash;
|
||||||
UserId bot_user_id;
|
UserId bot_user_id;
|
||||||
|
DialogId dialog_id;
|
||||||
tl_object_ptr<telegram_api::InputPeer> input_peer;
|
tl_object_ptr<telegram_api::InputPeer> input_peer;
|
||||||
Location user_location;
|
Location user_location;
|
||||||
string query;
|
string query;
|
||||||
|
@ -21,7 +21,7 @@ namespace td {
|
|||||||
* Interface for managing the internal logging of TDLib.
|
* Interface for managing the internal logging of TDLib.
|
||||||
* By default TDLib writes logs to stderr or an OS specific log and uses a verbosity level of 5.
|
* By default TDLib writes logs to stderr or an OS specific log and uses a verbosity level of 5.
|
||||||
* These functions are deprecated since TDLib 1.4.0 in favor of the td::td_api::setLogVerbosityLevel,
|
* These functions are deprecated since TDLib 1.4.0 in favor of the td::td_api::setLogVerbosityLevel,
|
||||||
* td::td_api::setLogStream and other synchronous requests for managing the intrenal TDLib logging.
|
* td::td_api::setLogStream and other synchronous requests for managing the internal TDLib logging.
|
||||||
*/
|
*/
|
||||||
class Log {
|
class Log {
|
||||||
public:
|
public:
|
||||||
|
@ -88,6 +88,13 @@ bool MemoryManager::can_manage_memory() const {
|
|||||||
if (!(td_->auth_manager_->is_authorized() && !G()->close_flag())) {
|
if (!(td_->auth_manager_->is_authorized() && !G()->close_flag())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (!do_session_settings_allow_for_memory_management()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MemoryManager::do_session_settings_allow_for_memory_management() {
|
||||||
if (G()->parameters().use_message_db || G()->parameters().use_chat_info_db || G()->parameters().use_file_db) {
|
if (G()->parameters().use_message_db || G()->parameters().use_chat_info_db || G()->parameters().use_file_db) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -96,7 +103,9 @@ bool MemoryManager::can_manage_memory() const {
|
|||||||
|
|
||||||
void MemoryManager::get_memory_stats(bool full, Promise<MemoryStats> promise) const {
|
void MemoryManager::get_memory_stats(bool full, Promise<MemoryStats> promise) const {
|
||||||
if (!can_manage_memory()) {
|
if (!can_manage_memory()) {
|
||||||
promise.set_error(Status::Error(500, "Request aborted"));
|
auto value = MemoryStats("{}");
|
||||||
|
|
||||||
|
promise.set_value(std::move(value));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,7 +211,13 @@ void MemoryManager::get_memory_stats(bool full, Promise<MemoryStats> promise) co
|
|||||||
|
|
||||||
void MemoryManager::clean_memory(bool full, Promise<Unit> promise) const {
|
void MemoryManager::clean_memory(bool full, Promise<Unit> promise) const {
|
||||||
if (!can_manage_memory()) {
|
if (!can_manage_memory()) {
|
||||||
promise.set_error(Status::Error(500, "Request aborted"));
|
if (!do_session_settings_allow_for_memory_management()) {
|
||||||
|
promise.set_error(Status::Error(405, "MEMORY_STATS_DISALLOWED"
|
||||||
|
" Session settings don't allow memory optimization."
|
||||||
|
" If you want to optimize memory, you should completely disable all databases."));
|
||||||
|
} else {
|
||||||
|
promise.set_error(Status::Error(405, "Can't manage memory now"));
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,6 +50,8 @@ class MemoryManager : public Actor {
|
|||||||
|
|
||||||
bool can_manage_memory() const;
|
bool can_manage_memory() const;
|
||||||
|
|
||||||
|
static bool do_session_settings_allow_for_memory_management();
|
||||||
|
|
||||||
void get_memory_stats(bool full, Promise<MemoryStats> promise) const;
|
void get_memory_stats(bool full, Promise<MemoryStats> promise) const;
|
||||||
|
|
||||||
void clean_memory(bool full, Promise<Unit> promise) const;
|
void clean_memory(bool full, Promise<Unit> promise) const;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -6,10 +6,10 @@
|
|||||||
//
|
//
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "td/telegram/Dependencies.h"
|
|
||||||
#include "td/telegram/DialogId.h"
|
#include "td/telegram/DialogId.h"
|
||||||
#include "td/telegram/files/FileId.h"
|
#include "td/telegram/files/FileId.h"
|
||||||
#include "td/telegram/FullMessageId.h"
|
#include "td/telegram/FullMessageId.h"
|
||||||
|
#include "td/telegram/InputGroupCallId.h"
|
||||||
#include "td/telegram/logevent/LogEvent.h"
|
#include "td/telegram/logevent/LogEvent.h"
|
||||||
#include "td/telegram/MessageContentType.h"
|
#include "td/telegram/MessageContentType.h"
|
||||||
#include "td/telegram/MessageCopyOptions.h"
|
#include "td/telegram/MessageCopyOptions.h"
|
||||||
@ -36,6 +36,7 @@
|
|||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
|
|
||||||
|
struct Dependencies;
|
||||||
class Game;
|
class Game;
|
||||||
struct Photo;
|
struct Photo;
|
||||||
class Td;
|
class Td;
|
||||||
@ -87,7 +88,7 @@ void store_message_content(const MessageContent *content, LogEventStorerUnsafe &
|
|||||||
void parse_message_content(unique_ptr<MessageContent> &content, LogEventParser &parser);
|
void parse_message_content(unique_ptr<MessageContent> &content, LogEventParser &parser);
|
||||||
|
|
||||||
InlineMessageContent create_inline_message_content(Td *td, FileId file_id,
|
InlineMessageContent create_inline_message_content(Td *td, FileId file_id,
|
||||||
tl_object_ptr<telegram_api::BotInlineMessage> &&inline_message,
|
tl_object_ptr<telegram_api::BotInlineMessage> &&bot_inline_message,
|
||||||
int32 allowed_media_content_id, Photo *photo, Game *game);
|
int32 allowed_media_content_id, Photo *photo, Game *game);
|
||||||
|
|
||||||
unique_ptr<MessageContent> create_text_message_content(string text, vector<MessageEntity> entities,
|
unique_ptr<MessageContent> create_text_message_content(string text, vector<MessageEntity> entities,
|
||||||
@ -122,6 +123,8 @@ tl_object_ptr<telegram_api::InputMedia> get_fake_input_media(Td *td, tl_object_p
|
|||||||
|
|
||||||
void delete_message_content_thumbnail(MessageContent *content, Td *td);
|
void delete_message_content_thumbnail(MessageContent *content, Td *td);
|
||||||
|
|
||||||
|
Status can_send_message_content(DialogId dialog_id, const MessageContent *content, bool is_forward, const Td *td);
|
||||||
|
|
||||||
bool can_forward_message_content(const MessageContent *content);
|
bool can_forward_message_content(const MessageContent *content);
|
||||||
|
|
||||||
bool update_opened_message_content(MessageContent *content);
|
bool update_opened_message_content(MessageContent *content);
|
||||||
@ -130,7 +133,9 @@ int32 get_message_content_index_mask(const MessageContent *content, const Td *td
|
|||||||
|
|
||||||
MessageId get_message_content_pinned_message_id(const MessageContent *content);
|
MessageId get_message_content_pinned_message_id(const MessageContent *content);
|
||||||
|
|
||||||
MessageId get_message_content_replied_message_id(const MessageContent *content);
|
FullMessageId get_message_content_replied_message_id(DialogId dialog_id, const MessageContent *content);
|
||||||
|
|
||||||
|
std::pair<InputGroupCallId, bool> get_message_content_group_call_info(const MessageContent *content);
|
||||||
|
|
||||||
vector<UserId> get_message_content_added_user_ids(const MessageContent *content);
|
vector<UserId> get_message_content_added_user_ids(const MessageContent *content);
|
||||||
|
|
||||||
@ -140,8 +145,6 @@ int32 get_message_content_live_location_period(const MessageContent *content);
|
|||||||
|
|
||||||
bool get_message_content_poll_is_closed(const Td *td, const MessageContent *content);
|
bool get_message_content_poll_is_closed(const Td *td, const MessageContent *content);
|
||||||
|
|
||||||
bool get_message_content_poll_is_anonymous(const Td *td, const MessageContent *content);
|
|
||||||
|
|
||||||
bool has_message_content_web_page(const MessageContent *content);
|
bool has_message_content_web_page(const MessageContent *content);
|
||||||
|
|
||||||
void remove_message_content_web_page(MessageContent *content);
|
void remove_message_content_web_page(MessageContent *content);
|
||||||
@ -187,10 +190,12 @@ unique_ptr<MessageContent> dup_message_content(Td *td, DialogId dialog_id, const
|
|||||||
MessageContentDupType type, MessageCopyOptions &©_options);
|
MessageContentDupType type, MessageCopyOptions &©_options);
|
||||||
|
|
||||||
unique_ptr<MessageContent> get_action_message_content(Td *td, tl_object_ptr<telegram_api::MessageAction> &&action,
|
unique_ptr<MessageContent> get_action_message_content(Td *td, tl_object_ptr<telegram_api::MessageAction> &&action,
|
||||||
DialogId owner_dialog_id, MessageId reply_to_message_id);
|
DialogId owner_dialog_id, DialogId reply_in_dialog_id,
|
||||||
|
MessageId reply_to_message_id);
|
||||||
|
|
||||||
tl_object_ptr<td_api::MessageContent> get_message_content_object(const MessageContent *content, Td *td,
|
tl_object_ptr<td_api::MessageContent> get_message_content_object(const MessageContent *content, Td *td,
|
||||||
int32 message_date, bool is_content_secret);
|
DialogId dialog_id, int32 message_date,
|
||||||
|
bool is_content_secret);
|
||||||
|
|
||||||
const FormattedText *get_message_content_text(const MessageContent *content);
|
const FormattedText *get_message_content_text(const MessageContent *content);
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
|
|
||||||
|
// increase MessageUnsupported::CURRENT_VERSION each time a new message content type is added
|
||||||
enum class MessageContentType : int32 {
|
enum class MessageContentType : int32 {
|
||||||
None = -1,
|
None = -1,
|
||||||
Text,
|
Text,
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "td/telegram/MessageEntity.h"
|
#include "td/telegram/MessageEntity.h"
|
||||||
|
|
||||||
#include "td/telegram/ContactsManager.h"
|
#include "td/telegram/ContactsManager.h"
|
||||||
|
#include "td/telegram/Dependencies.h"
|
||||||
#include "td/telegram/misc.h"
|
#include "td/telegram/misc.h"
|
||||||
#include "td/telegram/SecretChatActor.h"
|
#include "td/telegram/SecretChatActor.h"
|
||||||
|
|
||||||
@ -1126,7 +1127,8 @@ vector<Slice> find_mentions(Slice str) {
|
|||||||
if (mention.size() >= 5) {
|
if (mention.size() >= 5) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return get_valid_short_usernames().count(mention) == 0;
|
auto lowered_mention = to_lower(mention);
|
||||||
|
return get_valid_short_usernames().count(lowered_mention) == 0;
|
||||||
});
|
});
|
||||||
return mentions;
|
return mentions;
|
||||||
}
|
}
|
||||||
@ -2887,75 +2889,6 @@ Result<vector<MessageEntity>> parse_html(string &text) {
|
|||||||
return entities;
|
return entities;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<tl_object_ptr<telegram_api::MessageEntity>> get_input_message_entities(const ContactsManager *contacts_manager,
|
|
||||||
const vector<MessageEntity> &entities,
|
|
||||||
const char *source) {
|
|
||||||
vector<tl_object_ptr<telegram_api::MessageEntity>> result;
|
|
||||||
for (auto &entity : entities) {
|
|
||||||
if (!is_user_entity(entity.type)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
switch (entity.type) {
|
|
||||||
case MessageEntity::Type::Bold:
|
|
||||||
result.push_back(make_tl_object<telegram_api::messageEntityBold>(entity.offset, entity.length));
|
|
||||||
break;
|
|
||||||
case MessageEntity::Type::Italic:
|
|
||||||
result.push_back(make_tl_object<telegram_api::messageEntityItalic>(entity.offset, entity.length));
|
|
||||||
break;
|
|
||||||
case MessageEntity::Type::Underline:
|
|
||||||
result.push_back(make_tl_object<telegram_api::messageEntityUnderline>(entity.offset, entity.length));
|
|
||||||
break;
|
|
||||||
case MessageEntity::Type::Strikethrough:
|
|
||||||
result.push_back(make_tl_object<telegram_api::messageEntityStrike>(entity.offset, entity.length));
|
|
||||||
break;
|
|
||||||
case MessageEntity::Type::BlockQuote:
|
|
||||||
result.push_back(make_tl_object<telegram_api::messageEntityBlockquote>(entity.offset, entity.length));
|
|
||||||
break;
|
|
||||||
case MessageEntity::Type::Code:
|
|
||||||
result.push_back(make_tl_object<telegram_api::messageEntityCode>(entity.offset, entity.length));
|
|
||||||
break;
|
|
||||||
case MessageEntity::Type::Pre:
|
|
||||||
result.push_back(make_tl_object<telegram_api::messageEntityPre>(entity.offset, entity.length, string()));
|
|
||||||
break;
|
|
||||||
case MessageEntity::Type::PreCode:
|
|
||||||
result.push_back(make_tl_object<telegram_api::messageEntityPre>(entity.offset, entity.length, entity.argument));
|
|
||||||
break;
|
|
||||||
case MessageEntity::Type::TextUrl:
|
|
||||||
result.push_back(
|
|
||||||
make_tl_object<telegram_api::messageEntityTextUrl>(entity.offset, entity.length, entity.argument));
|
|
||||||
break;
|
|
||||||
case MessageEntity::Type::MentionName: {
|
|
||||||
auto input_user = contacts_manager->get_input_user(entity.user_id);
|
|
||||||
LOG_CHECK(input_user != nullptr) << source;
|
|
||||||
result.push_back(make_tl_object<telegram_api::inputMessageEntityMentionName>(entity.offset, entity.length,
|
|
||||||
std::move(input_user)));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MessageEntity::Type::Mention:
|
|
||||||
case MessageEntity::Type::Hashtag:
|
|
||||||
case MessageEntity::Type::BotCommand:
|
|
||||||
case MessageEntity::Type::Url:
|
|
||||||
case MessageEntity::Type::EmailAddress:
|
|
||||||
case MessageEntity::Type::Cashtag:
|
|
||||||
case MessageEntity::Type::PhoneNumber:
|
|
||||||
case MessageEntity::Type::BankCardNumber:
|
|
||||||
default:
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
vector<tl_object_ptr<telegram_api::MessageEntity>> get_input_message_entities(const ContactsManager *contacts_manager,
|
|
||||||
const FormattedText *text,
|
|
||||||
const char *source) {
|
|
||||||
if (text != nullptr && !text->entities.empty()) {
|
|
||||||
return get_input_message_entities(contacts_manager, text->entities, source);
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
vector<tl_object_ptr<secret_api::MessageEntity>> get_input_secret_message_entities(
|
vector<tl_object_ptr<secret_api::MessageEntity>> get_input_secret_message_entities(
|
||||||
const vector<MessageEntity> &entities, int32 layer) {
|
const vector<MessageEntity> &entities, int32 layer) {
|
||||||
vector<tl_object_ptr<secret_api::MessageEntity>> result;
|
vector<tl_object_ptr<secret_api::MessageEntity>> result;
|
||||||
@ -3590,7 +3523,7 @@ static std::pair<size_t, int32> remove_invalid_entities(const string &text, vect
|
|||||||
}
|
}
|
||||||
|
|
||||||
// enitities must contain only splittable entities
|
// enitities must contain only splittable entities
|
||||||
void split_entities(vector<MessageEntity> &entities, const vector<MessageEntity> &other_entities) {
|
static void split_entities(vector<MessageEntity> &entities, const vector<MessageEntity> &other_entities) {
|
||||||
check_is_sorted(entities);
|
check_is_sorted(entities);
|
||||||
check_is_sorted(other_entities);
|
check_is_sorted(other_entities);
|
||||||
|
|
||||||
@ -3975,4 +3908,77 @@ bool need_skip_bot_commands(const ContactsManager *contacts_manager, DialogId di
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vector<tl_object_ptr<telegram_api::MessageEntity>> get_input_message_entities(const ContactsManager *contacts_manager,
|
||||||
|
const vector<MessageEntity> &entities,
|
||||||
|
const char *source) {
|
||||||
|
vector<tl_object_ptr<telegram_api::MessageEntity>> result;
|
||||||
|
vector<MessageEntity> splittable_entities;
|
||||||
|
for (auto &entity : entities) {
|
||||||
|
if (!is_user_entity(entity.type)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (is_splittable_entity(entity.type)) {
|
||||||
|
splittable_entities.push_back(entity);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
switch (entity.type) {
|
||||||
|
case MessageEntity::Type::BlockQuote:
|
||||||
|
result.push_back(make_tl_object<telegram_api::messageEntityBlockquote>(entity.offset, entity.length));
|
||||||
|
break;
|
||||||
|
case MessageEntity::Type::Code:
|
||||||
|
result.push_back(make_tl_object<telegram_api::messageEntityCode>(entity.offset, entity.length));
|
||||||
|
break;
|
||||||
|
case MessageEntity::Type::Pre:
|
||||||
|
result.push_back(make_tl_object<telegram_api::messageEntityPre>(entity.offset, entity.length, string()));
|
||||||
|
break;
|
||||||
|
case MessageEntity::Type::PreCode:
|
||||||
|
result.push_back(make_tl_object<telegram_api::messageEntityPre>(entity.offset, entity.length, entity.argument));
|
||||||
|
break;
|
||||||
|
case MessageEntity::Type::TextUrl:
|
||||||
|
result.push_back(
|
||||||
|
make_tl_object<telegram_api::messageEntityTextUrl>(entity.offset, entity.length, entity.argument));
|
||||||
|
break;
|
||||||
|
case MessageEntity::Type::MentionName: {
|
||||||
|
auto input_user = contacts_manager->get_input_user(entity.user_id);
|
||||||
|
LOG_CHECK(input_user != nullptr) << source;
|
||||||
|
result.push_back(make_tl_object<telegram_api::inputMessageEntityMentionName>(entity.offset, entity.length,
|
||||||
|
std::move(input_user)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
split_entities(splittable_entities, vector<MessageEntity>());
|
||||||
|
for (auto &entity : splittable_entities) {
|
||||||
|
switch (entity.type) {
|
||||||
|
case MessageEntity::Type::Bold:
|
||||||
|
result.push_back(make_tl_object<telegram_api::messageEntityBold>(entity.offset, entity.length));
|
||||||
|
break;
|
||||||
|
case MessageEntity::Type::Italic:
|
||||||
|
result.push_back(make_tl_object<telegram_api::messageEntityItalic>(entity.offset, entity.length));
|
||||||
|
break;
|
||||||
|
case MessageEntity::Type::Underline:
|
||||||
|
result.push_back(make_tl_object<telegram_api::messageEntityUnderline>(entity.offset, entity.length));
|
||||||
|
break;
|
||||||
|
case MessageEntity::Type::Strikethrough:
|
||||||
|
result.push_back(make_tl_object<telegram_api::messageEntityStrike>(entity.offset, entity.length));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<tl_object_ptr<telegram_api::MessageEntity>> get_input_message_entities(const ContactsManager *contacts_manager,
|
||||||
|
const FormattedText *text,
|
||||||
|
const char *source) {
|
||||||
|
if (text != nullptr && !text->entities.empty()) {
|
||||||
|
return get_input_message_entities(contacts_manager, text->entities, source);
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace td
|
} // namespace td
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
//
|
//
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "td/telegram/Dependencies.h"
|
|
||||||
#include "td/telegram/DialogId.h"
|
#include "td/telegram/DialogId.h"
|
||||||
#include "td/telegram/UserId.h"
|
#include "td/telegram/UserId.h"
|
||||||
|
|
||||||
@ -25,6 +24,7 @@
|
|||||||
namespace td {
|
namespace td {
|
||||||
|
|
||||||
class ContactsManager;
|
class ContactsManager;
|
||||||
|
struct Dependencies;
|
||||||
|
|
||||||
class MessageEntity {
|
class MessageEntity {
|
||||||
public:
|
public:
|
||||||
|
@ -114,7 +114,7 @@ Status init_messages_db(SqliteDb &db, int32 version) {
|
|||||||
LOG(INFO) << "Create new message database";
|
LOG(INFO) << "Create new message database";
|
||||||
TRY_STATUS(
|
TRY_STATUS(
|
||||||
db.exec("CREATE TABLE IF NOT EXISTS messages (dialog_id INT8, message_id INT8, unique_message_id INT4, "
|
db.exec("CREATE TABLE IF NOT EXISTS messages (dialog_id INT8, message_id INT8, unique_message_id INT4, "
|
||||||
"sender_user_id INT4, random_id INT8, data BLOB, ttl_expires_at INT4, index_mask INT4, search_id INT8, "
|
"sender_user_id INT8, random_id INT8, data BLOB, ttl_expires_at INT4, index_mask INT4, search_id INT8, "
|
||||||
"text STRING, notification_id INT4, top_thread_message_id INT8, PRIMARY KEY (dialog_id, message_id))"));
|
"text STRING, notification_id INT4, top_thread_message_id INT8, PRIMARY KEY (dialog_id, message_id))"));
|
||||||
|
|
||||||
TRY_STATUS(
|
TRY_STATUS(
|
||||||
@ -297,7 +297,7 @@ class MessagesDbImpl : public MessagesDbSyncInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sender_user_id.is_valid()) {
|
if (sender_user_id.is_valid()) {
|
||||||
add_message_stmt_.bind_int32(4, sender_user_id.get()).ensure();
|
add_message_stmt_.bind_int64(4, sender_user_id.get()).ensure();
|
||||||
} else {
|
} else {
|
||||||
add_message_stmt_.bind_null(4).ensure();
|
add_message_stmt_.bind_null(4).ensure();
|
||||||
}
|
}
|
||||||
@ -430,7 +430,7 @@ class MessagesDbImpl : public MessagesDbSyncInterface {
|
|||||||
delete_dialog_messages_from_user_stmt_.reset();
|
delete_dialog_messages_from_user_stmt_.reset();
|
||||||
};
|
};
|
||||||
delete_dialog_messages_from_user_stmt_.bind_int64(1, dialog_id.get()).ensure();
|
delete_dialog_messages_from_user_stmt_.bind_int64(1, dialog_id.get()).ensure();
|
||||||
delete_dialog_messages_from_user_stmt_.bind_int32(2, sender_user_id.get()).ensure();
|
delete_dialog_messages_from_user_stmt_.bind_int64(2, sender_user_id.get()).ensure();
|
||||||
delete_dialog_messages_from_user_stmt_.step().ensure();
|
delete_dialog_messages_from_user_stmt_.step().ensure();
|
||||||
return Status::OK();
|
return Status::OK();
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -8,7 +8,6 @@
|
|||||||
|
|
||||||
#include "td/telegram/AccessRights.h"
|
#include "td/telegram/AccessRights.h"
|
||||||
#include "td/telegram/ChannelId.h"
|
#include "td/telegram/ChannelId.h"
|
||||||
#include "td/telegram/Dependencies.h"
|
|
||||||
#include "td/telegram/DialogAction.h"
|
#include "td/telegram/DialogAction.h"
|
||||||
#include "td/telegram/DialogDate.h"
|
#include "td/telegram/DialogDate.h"
|
||||||
#include "td/telegram/DialogDb.h"
|
#include "td/telegram/DialogDb.h"
|
||||||
@ -81,17 +80,12 @@
|
|||||||
namespace td {
|
namespace td {
|
||||||
|
|
||||||
struct BinlogEvent;
|
struct BinlogEvent;
|
||||||
|
struct Dependencies;
|
||||||
class DialogFilter;
|
class DialogFilter;
|
||||||
|
|
||||||
class DraftMessage;
|
class DraftMessage;
|
||||||
|
|
||||||
struct InputMessageContent;
|
struct InputMessageContent;
|
||||||
|
|
||||||
class MessageContent;
|
class MessageContent;
|
||||||
|
|
||||||
class MultiSequenceDispatcher;
|
class MultiSequenceDispatcher;
|
||||||
|
|
||||||
class Td;
|
class Td;
|
||||||
|
|
||||||
class MessagesManager : public Actor {
|
class MessagesManager : public Actor {
|
||||||
@ -151,6 +145,8 @@ class MessagesManager : public Actor {
|
|||||||
|
|
||||||
td_api::object_ptr<td_api::MessageSender> get_message_sender_object(UserId user_id, DialogId dialog_id);
|
td_api::object_ptr<td_api::MessageSender> get_message_sender_object(UserId user_id, DialogId dialog_id);
|
||||||
|
|
||||||
|
td_api::object_ptr<td_api::MessageSender> get_message_sender_object_const(DialogId dialog_id) const;
|
||||||
|
|
||||||
td_api::object_ptr<td_api::MessageSender> get_message_sender_object(DialogId dialog_id);
|
td_api::object_ptr<td_api::MessageSender> get_message_sender_object(DialogId dialog_id);
|
||||||
|
|
||||||
static vector<MessageId> get_message_ids(const vector<int64> &input_message_ids);
|
static vector<MessageId> get_message_ids(const vector<int64> &input_message_ids);
|
||||||
@ -193,6 +189,8 @@ class MessagesManager : public Actor {
|
|||||||
void get_channel_difference_if_needed(DialogId dialog_id, MessagesInfo &&messages_info,
|
void get_channel_difference_if_needed(DialogId dialog_id, MessagesInfo &&messages_info,
|
||||||
Promise<MessagesInfo> &&promise);
|
Promise<MessagesInfo> &&promise);
|
||||||
|
|
||||||
|
bool run_get_channel_difference_request(long id);
|
||||||
|
|
||||||
void on_get_messages(vector<tl_object_ptr<telegram_api::Message>> &&messages, bool is_channel_message,
|
void on_get_messages(vector<tl_object_ptr<telegram_api::Message>> &&messages, bool is_channel_message,
|
||||||
bool is_scheduled, const char *source);
|
bool is_scheduled, const char *source);
|
||||||
|
|
||||||
@ -290,10 +288,13 @@ class MessagesManager : public Actor {
|
|||||||
void on_update_dialog_folder_id(DialogId dialog_id, FolderId folder_id);
|
void on_update_dialog_folder_id(DialogId dialog_id, FolderId folder_id);
|
||||||
|
|
||||||
void on_update_dialog_group_call(DialogId dialog_id, bool has_active_group_call, bool is_group_call_empty,
|
void on_update_dialog_group_call(DialogId dialog_id, bool has_active_group_call, bool is_group_call_empty,
|
||||||
const char *source);
|
const char *source, bool force = false);
|
||||||
|
|
||||||
void on_update_dialog_group_call_id(DialogId dialog_id, InputGroupCallId input_group_call_id);
|
void on_update_dialog_group_call_id(DialogId dialog_id, InputGroupCallId input_group_call_id);
|
||||||
|
|
||||||
|
void on_update_dialog_default_join_group_call_as_dialog_id(DialogId dialog_id, DialogId default_join_as_dialog_id,
|
||||||
|
bool force);
|
||||||
|
|
||||||
void on_update_dialog_message_ttl_setting(DialogId dialog_id, MessageTtlSetting message_ttl_setting);
|
void on_update_dialog_message_ttl_setting(DialogId dialog_id, MessageTtlSetting message_ttl_setting);
|
||||||
|
|
||||||
void on_update_dialog_filters();
|
void on_update_dialog_filters();
|
||||||
@ -338,8 +339,9 @@ class MessagesManager : public Actor {
|
|||||||
|
|
||||||
void on_update_delete_scheduled_messages(DialogId dialog_id, vector<ScheduledServerMessageId> &&server_message_ids);
|
void on_update_delete_scheduled_messages(DialogId dialog_id, vector<ScheduledServerMessageId> &&server_message_ids);
|
||||||
|
|
||||||
void on_user_dialog_action(DialogId dialog_id, MessageId top_thread_message_id, UserId user_id, DialogAction action,
|
void on_user_dialog_action(DialogId dialog_id, MessageId top_thread_message_id, DialogId typing_dialog_id,
|
||||||
int32 date, MessageContentType message_content_type = MessageContentType::None);
|
DialogAction action, int32 date,
|
||||||
|
MessageContentType message_content_type = MessageContentType::None);
|
||||||
|
|
||||||
void read_history_inbox(DialogId dialog_id, MessageId max_message_id, int32 unread_count, const char *source);
|
void read_history_inbox(DialogId dialog_id, MessageId max_message_id, int32 unread_count, const char *source);
|
||||||
|
|
||||||
@ -499,8 +501,15 @@ class MessagesManager : public Actor {
|
|||||||
|
|
||||||
tl_object_ptr<td_api::chatEvents> get_chat_events_object(int64 random_id);
|
tl_object_ptr<td_api::chatEvents> get_chat_events_object(int64 random_id);
|
||||||
|
|
||||||
|
string get_dialog_title(DialogId dialog_id) const;
|
||||||
|
|
||||||
bool have_dialog(DialogId dialog_id) const;
|
bool have_dialog(DialogId dialog_id) const;
|
||||||
bool have_dialog_force(DialogId dialog_id);
|
bool have_dialog_force(DialogId dialog_id, const char *source = "have_dialog_force");
|
||||||
|
|
||||||
|
bool have_dialog_info(DialogId dialog_id) const;
|
||||||
|
bool have_dialog_info_force(DialogId dialog_id) const;
|
||||||
|
|
||||||
|
void reload_dialog_info_full(DialogId dialog_id);
|
||||||
|
|
||||||
bool load_dialog(DialogId dialog_id, int left_tries, Promise<Unit> &&promise);
|
bool load_dialog(DialogId dialog_id, int left_tries, Promise<Unit> &&promise);
|
||||||
|
|
||||||
@ -799,6 +808,11 @@ class MessagesManager : public Actor {
|
|||||||
void get_login_url(DialogId dialog_id, MessageId message_id, int32 button_id, bool allow_write_access,
|
void get_login_url(DialogId dialog_id, MessageId message_id, int32 button_id, bool allow_write_access,
|
||||||
Promise<td_api::object_ptr<td_api::httpUrl>> &&promise);
|
Promise<td_api::object_ptr<td_api::httpUrl>> &&promise);
|
||||||
|
|
||||||
|
void get_link_login_url_info(const string &url, Promise<td_api::object_ptr<td_api::LoginUrlInfo>> &&promise);
|
||||||
|
|
||||||
|
void get_link_login_url(const string &url, bool allow_write_access,
|
||||||
|
Promise<td_api::object_ptr<td_api::httpUrl>> &&promise);
|
||||||
|
|
||||||
void on_authorization_success();
|
void on_authorization_success();
|
||||||
|
|
||||||
void before_get_difference();
|
void before_get_difference();
|
||||||
@ -903,16 +917,9 @@ class MessagesManager : public Actor {
|
|||||||
void stop_poll(FullMessageId full_message_id, td_api::object_ptr<td_api::ReplyMarkup> &&reply_markup,
|
void stop_poll(FullMessageId full_message_id, td_api::object_ptr<td_api::ReplyMarkup> &&reply_markup,
|
||||||
Promise<Unit> &&promise);
|
Promise<Unit> &&promise);
|
||||||
|
|
||||||
void get_payment_form(FullMessageId full_message_id, Promise<tl_object_ptr<td_api::paymentForm>> &&promise);
|
Result<ServerMessageId> get_invoice_message_id(FullMessageId full_message_id);
|
||||||
|
|
||||||
void validate_order_info(FullMessageId full_message_id, tl_object_ptr<td_api::orderInfo> order_info, bool allow_save,
|
Result<ServerMessageId> get_payment_successful_message_id(FullMessageId full_message_id);
|
||||||
Promise<tl_object_ptr<td_api::validatedOrderInfo>> &&promise);
|
|
||||||
|
|
||||||
void send_payment_form(FullMessageId full_message_id, const string &order_info_id, const string &shipping_option_id,
|
|
||||||
const tl_object_ptr<td_api::InputCredentials> &credentials,
|
|
||||||
Promise<tl_object_ptr<td_api::paymentResult>> &&promise);
|
|
||||||
|
|
||||||
void get_payment_receipt(FullMessageId full_message_id, Promise<tl_object_ptr<td_api::paymentReceipt>> &&promise);
|
|
||||||
|
|
||||||
void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
|
void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
|
||||||
|
|
||||||
@ -1084,7 +1091,7 @@ class MessagesManager : public Actor {
|
|||||||
|
|
||||||
int32 ttl_period = 0; // counted from message send date
|
int32 ttl_period = 0; // counted from message send date
|
||||||
int32 ttl = 0; // counted from message content view date
|
int32 ttl = 0; // counted from message content view date
|
||||||
double ttl_expires_at = 0; // only for ttl
|
double ttl_expires_at = 0; // only for TTL
|
||||||
|
|
||||||
int64 media_album_id = 0;
|
int64 media_album_id = 0;
|
||||||
|
|
||||||
@ -1100,6 +1107,8 @@ class MessagesManager : public Actor {
|
|||||||
|
|
||||||
int32 last_edit_pts = 0;
|
int32 last_edit_pts = 0;
|
||||||
|
|
||||||
|
const char *debug_source = nullptr;
|
||||||
|
|
||||||
unique_ptr<Message> left;
|
unique_ptr<Message> left;
|
||||||
unique_ptr<Message> right;
|
unique_ptr<Message> right;
|
||||||
|
|
||||||
@ -1165,6 +1174,8 @@ class MessagesManager : public Actor {
|
|||||||
std::unordered_set<MessageId, MessageIdHash> updated_read_history_message_ids;
|
std::unordered_set<MessageId, MessageIdHash> updated_read_history_message_ids;
|
||||||
LogEventIdWithGeneration set_folder_id_log_event_id;
|
LogEventIdWithGeneration set_folder_id_log_event_id;
|
||||||
InputGroupCallId active_group_call_id;
|
InputGroupCallId active_group_call_id;
|
||||||
|
InputGroupCallId expected_active_group_call_id;
|
||||||
|
DialogId default_join_group_call_as_dialog_id;
|
||||||
|
|
||||||
FolderId folder_id;
|
FolderId folder_id;
|
||||||
vector<DialogListId> dialog_list_ids; // TODO replace with mask
|
vector<DialogListId> dialog_list_ids; // TODO replace with mask
|
||||||
@ -1240,6 +1251,7 @@ class MessagesManager : public Actor {
|
|||||||
bool has_active_group_call = false;
|
bool has_active_group_call = false;
|
||||||
bool is_group_call_empty = false;
|
bool is_group_call_empty = false;
|
||||||
bool is_message_ttl_setting_inited = false;
|
bool is_message_ttl_setting_inited = false;
|
||||||
|
bool has_expected_active_group_call_id = false;
|
||||||
|
|
||||||
bool increment_view_counter = false;
|
bool increment_view_counter = false;
|
||||||
|
|
||||||
@ -1646,8 +1658,8 @@ class MessagesManager : public Actor {
|
|||||||
static constexpr int32 MAX_SEARCH_MESSAGES = 100; // server side limit
|
static constexpr int32 MAX_SEARCH_MESSAGES = 100; // server side limit
|
||||||
static constexpr int32 MIN_SEARCH_PUBLIC_DIALOG_PREFIX_LEN = 4; // server side limit
|
static constexpr int32 MIN_SEARCH_PUBLIC_DIALOG_PREFIX_LEN = 4; // server side limit
|
||||||
static constexpr int32 MIN_CHANNEL_DIFFERENCE = 10;
|
static constexpr int32 MIN_CHANNEL_DIFFERENCE = 10;
|
||||||
static constexpr int32 MAX_CHANNEL_DIFFERENCE = 100;
|
static constexpr int32 MAX_BOT_CHANNEL_DIFFERENCE = 1000000; // server side limit
|
||||||
static constexpr int32 MAX_BOT_CHANNEL_DIFFERENCE = 100000; // server side limit
|
static constexpr int32 MAX_CHANNEL_DIFFERENCE = MAX_BOT_CHANNEL_DIFFERENCE;
|
||||||
static constexpr int32 MAX_RECENTLY_FOUND_DIALOGS = 30; // some reasonable value
|
static constexpr int32 MAX_RECENTLY_FOUND_DIALOGS = 30; // some reasonable value
|
||||||
static constexpr size_t MAX_TITLE_LENGTH = 128; // server side limit for chat title
|
static constexpr size_t MAX_TITLE_LENGTH = 128; // server side limit for chat title
|
||||||
static constexpr size_t MAX_DESCRIPTION_LENGTH = 255; // server side limit for chat description
|
static constexpr size_t MAX_DESCRIPTION_LENGTH = 255; // server side limit for chat description
|
||||||
@ -1770,9 +1782,6 @@ class MessagesManager : public Actor {
|
|||||||
|
|
||||||
Status can_send_message(DialogId dialog_id) const TD_WARN_UNUSED_RESULT;
|
Status can_send_message(DialogId dialog_id) const TD_WARN_UNUSED_RESULT;
|
||||||
|
|
||||||
Status can_send_message_content(DialogId dialog_id, const MessageContent *content,
|
|
||||||
bool is_forward) const TD_WARN_UNUSED_RESULT;
|
|
||||||
|
|
||||||
bool can_resend_message(const Message *m) const;
|
bool can_resend_message(const Message *m) const;
|
||||||
|
|
||||||
bool can_edit_message(DialogId dialog_id, const Message *m, bool is_editing, bool only_reply_markup = false) const;
|
bool can_edit_message(DialogId dialog_id, const Message *m, bool is_editing, bool only_reply_markup = false) const;
|
||||||
@ -1805,7 +1814,7 @@ class MessagesManager : public Actor {
|
|||||||
void delete_messages_from_updates(const vector<MessageId> &message_ids);
|
void delete_messages_from_updates(const vector<MessageId> &message_ids);
|
||||||
|
|
||||||
void delete_dialog_messages(DialogId dialog_id, const vector<MessageId> &message_ids, bool from_updates,
|
void delete_dialog_messages(DialogId dialog_id, const vector<MessageId> &message_ids, bool from_updates,
|
||||||
bool skip_update_for_not_found_messages);
|
bool skip_update_for_not_found_messages, const char *source);
|
||||||
|
|
||||||
void update_dialog_pinned_messages_from_updates(DialogId dialog_id, const vector<MessageId> &message_ids,
|
void update_dialog_pinned_messages_from_updates(DialogId dialog_id, const vector<MessageId> &message_ids,
|
||||||
bool is_pin);
|
bool is_pin);
|
||||||
@ -1901,7 +1910,7 @@ class MessagesManager : public Actor {
|
|||||||
void do_delete_all_dialog_messages(Dialog *d, unique_ptr<Message> &message, bool is_permanently_deleted,
|
void do_delete_all_dialog_messages(Dialog *d, unique_ptr<Message> &message, bool is_permanently_deleted,
|
||||||
vector<int64> &deleted_message_ids);
|
vector<int64> &deleted_message_ids);
|
||||||
|
|
||||||
void delete_message_from_server(DialogId dialog_id, MessageId message_ids, bool revoke);
|
void delete_sent_message_from_server(DialogId dialog_id, MessageId message_id);
|
||||||
|
|
||||||
void delete_messages_from_server(DialogId dialog_id, vector<MessageId> message_ids, bool revoke, uint64 log_event_id,
|
void delete_messages_from_server(DialogId dialog_id, vector<MessageId> message_ids, bool revoke, uint64 log_event_id,
|
||||||
Promise<Unit> &&promise);
|
Promise<Unit> &&promise);
|
||||||
@ -1953,7 +1962,7 @@ class MessagesManager : public Actor {
|
|||||||
const Message *m) const;
|
const Message *m) const;
|
||||||
|
|
||||||
bool update_message_interaction_info(DialogId dialog_id, Message *m, int32 view_count, int32 forward_count,
|
bool update_message_interaction_info(DialogId dialog_id, Message *m, int32 view_count, int32 forward_count,
|
||||||
bool has_reply_info, MessageReplyInfo &&reply_info);
|
bool has_reply_info, MessageReplyInfo &&reply_info, const char *source);
|
||||||
|
|
||||||
bool update_message_contains_unread_mention(Dialog *d, Message *m, bool contains_unread_mention, const char *source);
|
bool update_message_contains_unread_mention(Dialog *d, Message *m, bool contains_unread_mention, const char *source);
|
||||||
|
|
||||||
@ -2397,13 +2406,13 @@ class MessagesManager : public Actor {
|
|||||||
|
|
||||||
MessageId get_message_id_by_random_id(Dialog *d, int64 random_id, const char *source);
|
MessageId get_message_id_by_random_id(Dialog *d, int64 random_id, const char *source);
|
||||||
|
|
||||||
Dialog *add_dialog(DialogId dialog_id);
|
Dialog *add_dialog(DialogId dialog_id, const char *source);
|
||||||
|
|
||||||
Dialog *add_new_dialog(unique_ptr<Dialog> &&d, bool is_loaded_from_database);
|
Dialog *add_new_dialog(unique_ptr<Dialog> &&d, bool is_loaded_from_database, const char *source);
|
||||||
|
|
||||||
void fix_new_dialog(Dialog *d, unique_ptr<Message> &&last_database_message, MessageId last_database_message_id,
|
void fix_new_dialog(Dialog *d, unique_ptr<Message> &&last_database_message, MessageId last_database_message_id,
|
||||||
int64 order, int32 last_clear_history_date, MessageId last_clear_history_message_id,
|
int64 order, int32 last_clear_history_date, MessageId last_clear_history_message_id,
|
||||||
bool is_loaded_from_database);
|
DialogId default_join_group_call_as_dialog_id, bool is_loaded_from_database);
|
||||||
|
|
||||||
void add_dialog_last_database_message(Dialog *d, unique_ptr<Message> &&last_database_message);
|
void add_dialog_last_database_message(Dialog *d, unique_ptr<Message> &&last_database_message);
|
||||||
|
|
||||||
@ -2414,17 +2423,16 @@ class MessagesManager : public Actor {
|
|||||||
td_api::object_ptr<td_api::ChatActionBar> get_chat_action_bar_object(const Dialog *d,
|
td_api::object_ptr<td_api::ChatActionBar> get_chat_action_bar_object(const Dialog *d,
|
||||||
bool hide_unarchive = false) const;
|
bool hide_unarchive = false) const;
|
||||||
|
|
||||||
td_api::object_ptr<td_api::chat> get_chat_object(const Dialog *d) const;
|
td_api::object_ptr<td_api::voiceChat> get_voice_chat_object(const Dialog *d) const;
|
||||||
|
|
||||||
bool have_dialog_info(DialogId dialog_id) const;
|
td_api::object_ptr<td_api::chat> get_chat_object(const Dialog *d) const;
|
||||||
bool have_dialog_info_force(DialogId dialog_id) const;
|
|
||||||
|
|
||||||
Dialog *get_dialog(DialogId dialog_id);
|
Dialog *get_dialog(DialogId dialog_id);
|
||||||
const Dialog *get_dialog(DialogId dialog_id) const;
|
const Dialog *get_dialog(DialogId dialog_id) const;
|
||||||
|
|
||||||
Dialog *get_dialog_force(DialogId dialog_id);
|
Dialog *get_dialog_force(DialogId dialog_id, const char *source = "get_dialog_force");
|
||||||
|
|
||||||
Dialog *on_load_dialog_from_database(DialogId dialog_id, const BufferSlice &value);
|
Dialog *on_load_dialog_from_database(DialogId dialog_id, const BufferSlice &value, const char *source);
|
||||||
|
|
||||||
void on_get_dialogs_from_database(FolderId folder_id, int32 limit, DialogDbGetDialogsResult &&dialogs,
|
void on_get_dialogs_from_database(FolderId folder_id, int32 limit, DialogDbGetDialogsResult &&dialogs,
|
||||||
Promise<Unit> &&promise);
|
Promise<Unit> &&promise);
|
||||||
@ -2433,8 +2441,6 @@ class MessagesManager : public Actor {
|
|||||||
|
|
||||||
void send_search_public_dialogs_query(const string &query, Promise<Unit> &&promise);
|
void send_search_public_dialogs_query(const string &query, Promise<Unit> &&promise);
|
||||||
|
|
||||||
void reload_dialog_info_full(DialogId dialog_id);
|
|
||||||
|
|
||||||
vector<DialogId> get_pinned_dialog_ids(DialogListId dialog_list_id) const;
|
vector<DialogId> get_pinned_dialog_ids(DialogListId dialog_list_id) const;
|
||||||
|
|
||||||
void reload_pinned_dialogs(DialogListId dialog_list_id, Promise<Unit> &&promise);
|
void reload_pinned_dialogs(DialogListId dialog_list_id, Promise<Unit> &&promise);
|
||||||
@ -2468,7 +2474,7 @@ class MessagesManager : public Actor {
|
|||||||
|
|
||||||
InputDialogId get_input_dialog_id(DialogId dialog_id) const;
|
InputDialogId get_input_dialog_id(DialogId dialog_id) const;
|
||||||
|
|
||||||
void sort_dialog_filter_input_dialog_ids(DialogFilter *dialog_filter) const;
|
void sort_dialog_filter_input_dialog_ids(DialogFilter *dialog_filter, const char *source) const;
|
||||||
|
|
||||||
Result<unique_ptr<DialogFilter>> create_dialog_filter(DialogFilterId dialog_filter_id,
|
Result<unique_ptr<DialogFilter>> create_dialog_filter(DialogFilterId dialog_filter_id,
|
||||||
td_api::object_ptr<td_api::chatFilter> filter);
|
td_api::object_ptr<td_api::chatFilter> filter);
|
||||||
@ -2689,8 +2695,6 @@ class MessagesManager : public Actor {
|
|||||||
|
|
||||||
const DialogPhoto *get_dialog_photo(DialogId dialog_id) const;
|
const DialogPhoto *get_dialog_photo(DialogId dialog_id) const;
|
||||||
|
|
||||||
string get_dialog_title(DialogId dialog_id) const;
|
|
||||||
|
|
||||||
string get_dialog_username(DialogId dialog_id) const;
|
string get_dialog_username(DialogId dialog_id) const;
|
||||||
|
|
||||||
RestrictedRights get_dialog_permissions(DialogId dialog_id) const;
|
RestrictedRights get_dialog_permissions(DialogId dialog_id) const;
|
||||||
@ -2774,6 +2778,9 @@ class MessagesManager : public Actor {
|
|||||||
|
|
||||||
void on_channel_get_difference_timeout(DialogId dialog_id);
|
void on_channel_get_difference_timeout(DialogId dialog_id);
|
||||||
|
|
||||||
|
void get_channel_difference_delayed(DialogId dialog_id, int32 pts, bool force, bool enable_pull_based_backpressure,
|
||||||
|
const char *source);
|
||||||
|
|
||||||
void get_channel_difference(DialogId dialog_id, int32 pts, bool force, const char *source);
|
void get_channel_difference(DialogId dialog_id, int32 pts, bool force, const char *source);
|
||||||
|
|
||||||
void do_get_channel_difference(DialogId dialog_id, int32 pts, bool force,
|
void do_get_channel_difference(DialogId dialog_id, int32 pts, bool force,
|
||||||
@ -2884,6 +2891,8 @@ class MessagesManager : public Actor {
|
|||||||
|
|
||||||
void reget_message_from_server_if_needed(DialogId dialog_id, const Message *m);
|
void reget_message_from_server_if_needed(DialogId dialog_id, const Message *m);
|
||||||
|
|
||||||
|
void speculatively_update_active_group_call_id(Dialog *d, const Message *m);
|
||||||
|
|
||||||
void speculatively_update_channel_participants(DialogId dialog_id, const Message *m);
|
void speculatively_update_channel_participants(DialogId dialog_id, const Message *m);
|
||||||
|
|
||||||
void update_sent_message_contents(DialogId dialog_id, const Message *m);
|
void update_sent_message_contents(DialogId dialog_id, const Message *m);
|
||||||
@ -2902,7 +2911,7 @@ class MessagesManager : public Actor {
|
|||||||
|
|
||||||
unique_ptr<Message> parse_message(DialogId dialog_id, const BufferSlice &value, bool is_scheduled);
|
unique_ptr<Message> parse_message(DialogId dialog_id, const BufferSlice &value, bool is_scheduled);
|
||||||
|
|
||||||
unique_ptr<Dialog> parse_dialog(DialogId dialog_id, const BufferSlice &value);
|
unique_ptr<Dialog> parse_dialog(DialogId dialog_id, const BufferSlice &value, const char *source);
|
||||||
|
|
||||||
void load_calls_db_state();
|
void load_calls_db_state();
|
||||||
void save_calls_db_state();
|
void save_calls_db_state();
|
||||||
@ -2913,7 +2922,7 @@ class MessagesManager : public Actor {
|
|||||||
|
|
||||||
static void dump_debug_message_op(const Dialog *d, int priority = 0);
|
static void dump_debug_message_op(const Dialog *d, int priority = 0);
|
||||||
|
|
||||||
static void add_message_dependencies(Dependencies &dependencies, DialogId dialog_id, const Message *m);
|
static void add_message_dependencies(Dependencies &dependencies, const Message *m);
|
||||||
|
|
||||||
void save_send_message_log_event(DialogId dialog_id, const Message *m);
|
void save_send_message_log_event(DialogId dialog_id, const Message *m);
|
||||||
|
|
||||||
@ -2966,8 +2975,6 @@ class MessagesManager : public Actor {
|
|||||||
|
|
||||||
Result<string> get_login_button_url(DialogId dialog_id, MessageId message_id, int32 button_id);
|
Result<string> get_login_button_url(DialogId dialog_id, MessageId message_id, int32 button_id);
|
||||||
|
|
||||||
Result<ServerMessageId> get_invoice_message_id(FullMessageId full_message_id);
|
|
||||||
|
|
||||||
bool is_broadcast_channel(DialogId dialog_id) const;
|
bool is_broadcast_channel(DialogId dialog_id) const;
|
||||||
|
|
||||||
bool is_deleted_secret_chat(const Dialog *d) const;
|
bool is_deleted_secret_chat(const Dialog *d) const;
|
||||||
@ -3114,6 +3121,14 @@ class MessagesManager : public Actor {
|
|||||||
};
|
};
|
||||||
std::unordered_map<int64, unique_ptr<PendingMessageImport>> pending_message_imports_;
|
std::unordered_map<int64, unique_ptr<PendingMessageImport>> pending_message_imports_;
|
||||||
|
|
||||||
|
struct PendingChannelDifference {
|
||||||
|
DialogId dialog_id;
|
||||||
|
int32 pts;
|
||||||
|
bool force;
|
||||||
|
};
|
||||||
|
std::unordered_map<int64, PendingChannelDifference> pending_channel_difference_;
|
||||||
|
int64 last_pending_channel_difference_ = 0;
|
||||||
|
|
||||||
struct PendingMessageGroupSend {
|
struct PendingMessageGroupSend {
|
||||||
DialogId dialog_id;
|
DialogId dialog_id;
|
||||||
size_t finished_count = 0;
|
size_t finished_count = 0;
|
||||||
@ -3290,6 +3305,9 @@ class MessagesManager : public Actor {
|
|||||||
std::unordered_map<DialogId, std::pair<int32, unique_ptr<Message>>, DialogIdHash>
|
std::unordered_map<DialogId, std::pair<int32, unique_ptr<Message>>, DialogIdHash>
|
||||||
pending_add_dialog_last_database_message_; // dialog -> dependency counter + message
|
pending_add_dialog_last_database_message_; // dialog -> dependency counter + message
|
||||||
|
|
||||||
|
std::unordered_map<DialogId, vector<DialogId>, DialogIdHash>
|
||||||
|
pending_add_default_join_group_call_as_dialog_id_; // dialog_id -> dependent dialogs
|
||||||
|
|
||||||
struct CallsDbState {
|
struct CallsDbState {
|
||||||
std::array<MessageId, 2> first_calls_database_message_id_by_index;
|
std::array<MessageId, 2> first_calls_database_message_id_by_index;
|
||||||
std::array<int32, 2> message_count_by_index;
|
std::array<int32, 2> message_count_by_index;
|
||||||
|
@ -253,7 +253,8 @@ void NotificationManager::init() {
|
|||||||
VLOG(notifications) << "Load call_notification_group_ids = " << call_notification_group_ids;
|
VLOG(notifications) << "Load call_notification_group_ids = " << call_notification_group_ids;
|
||||||
for (auto &group_id : call_notification_group_ids) {
|
for (auto &group_id : call_notification_group_ids) {
|
||||||
if (group_id.get() > current_notification_group_id_.get()) {
|
if (group_id.get() > current_notification_group_id_.get()) {
|
||||||
LOG(ERROR) << "Fix current notification group id from " << current_notification_group_id_ << " to " << group_id;
|
LOG(ERROR) << "Fix current notification group identifier from " << current_notification_group_id_ << " to "
|
||||||
|
<< group_id;
|
||||||
current_notification_group_id_ = group_id;
|
current_notification_group_id_ = group_id;
|
||||||
G()->td_db()->get_binlog_pmc()->set("notification_group_id_current",
|
G()->td_db()->get_binlog_pmc()->set("notification_group_id_current",
|
||||||
to_string(current_notification_group_id_.get()));
|
to_string(current_notification_group_id_.get()));
|
||||||
@ -417,14 +418,15 @@ NotificationManager::NotificationGroups::iterator NotificationManager::get_group
|
|||||||
group_key.last_notification_date = notification.date;
|
group_key.last_notification_date = notification.date;
|
||||||
}
|
}
|
||||||
if (notification.notification_id.get() > current_notification_id_.get()) {
|
if (notification.notification_id.get() > current_notification_id_.get()) {
|
||||||
LOG(ERROR) << "Fix current notification id from " << current_notification_id_ << " to "
|
LOG(ERROR) << "Fix current notification identifier from " << current_notification_id_ << " to "
|
||||||
<< notification.notification_id;
|
<< notification.notification_id;
|
||||||
current_notification_id_ = notification.notification_id;
|
current_notification_id_ = notification.notification_id;
|
||||||
G()->td_db()->get_binlog_pmc()->set("notification_id_current", to_string(current_notification_id_.get()));
|
G()->td_db()->get_binlog_pmc()->set("notification_id_current", to_string(current_notification_id_.get()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (group_id.get() > current_notification_group_id_.get()) {
|
if (group_id.get() > current_notification_group_id_.get()) {
|
||||||
LOG(ERROR) << "Fix current notification group id from " << current_notification_group_id_ << " to " << group_id;
|
LOG(ERROR) << "Fix current notification group identifier from " << current_notification_group_id_ << " to "
|
||||||
|
<< group_id;
|
||||||
current_notification_group_id_ = group_id;
|
current_notification_group_id_ = group_id;
|
||||||
G()->td_db()->get_binlog_pmc()->set("notification_group_id_current",
|
G()->td_db()->get_binlog_pmc()->set("notification_group_id_current",
|
||||||
to_string(current_notification_group_id_.get()));
|
to_string(current_notification_group_id_.get()));
|
||||||
@ -739,7 +741,7 @@ NotificationId NotificationManager::get_next_notification_id() {
|
|||||||
return NotificationId();
|
return NotificationId();
|
||||||
}
|
}
|
||||||
if (current_notification_id_.get() == std::numeric_limits<int32>::max()) {
|
if (current_notification_id_.get() == std::numeric_limits<int32>::max()) {
|
||||||
LOG(ERROR) << "Notification id overflowed";
|
LOG(ERROR) << "Notification identifier overflowed";
|
||||||
return NotificationId();
|
return NotificationId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -753,7 +755,7 @@ NotificationGroupId NotificationManager::get_next_notification_group_id() {
|
|||||||
return NotificationGroupId();
|
return NotificationGroupId();
|
||||||
}
|
}
|
||||||
if (current_notification_group_id_.get() == std::numeric_limits<int32>::max()) {
|
if (current_notification_group_id_.get() == std::numeric_limits<int32>::max()) {
|
||||||
LOG(ERROR) << "Notification group id overflowed";
|
LOG(ERROR) << "Notification group identifier overflowed";
|
||||||
return NotificationGroupId();
|
return NotificationGroupId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -847,7 +849,8 @@ int32 NotificationManager::get_notification_delay_ms(DialogId dialog_id, const P
|
|||||||
return 0;
|
return 0;
|
||||||
}();
|
}();
|
||||||
|
|
||||||
auto passed_time_ms = max(0, static_cast<int32>((G()->server_time_cached() - notification.date - 1) * 1000));
|
auto passed_time_ms =
|
||||||
|
static_cast<int32>(clamp(G()->server_time_cached() - notification.date - 1, 0.0, 1000000.0) * 1000);
|
||||||
return max(max(min_delay_ms, delay_ms) - passed_time_ms, MIN_NOTIFICATION_DELAY_MS);
|
return max(max(min_delay_ms, delay_ms) - passed_time_ms, MIN_NOTIFICATION_DELAY_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1859,7 +1862,9 @@ void NotificationManager::remove_notification(NotificationGroupId group_id, Noti
|
|||||||
bool is_total_count_changed = false;
|
bool is_total_count_changed = false;
|
||||||
if ((!have_all_notifications && is_permanent) || (have_all_notifications && is_found)) {
|
if ((!have_all_notifications && is_permanent) || (have_all_notifications && is_found)) {
|
||||||
if (group_it->second.total_count == 0) {
|
if (group_it->second.total_count == 0) {
|
||||||
LOG(ERROR) << "Total notification count became negative in " << group_id << " after removing " << notification_id;
|
LOG(ERROR) << "Total notification count became negative in " << group_it->second << " after removing "
|
||||||
|
<< notification_id << " with is_permanent = " << is_permanent << ", is_found = " << is_found
|
||||||
|
<< ", force_update = " << force_update << " from " << source;
|
||||||
} else {
|
} else {
|
||||||
group_it->second.total_count--;
|
group_it->second.total_count--;
|
||||||
is_total_count_changed = true;
|
is_total_count_changed = true;
|
||||||
@ -3822,7 +3827,7 @@ Result<int64> NotificationManager::get_push_receiver_id(string payload) {
|
|||||||
return Status::Error(400, "Expected user_id as a String or a Number");
|
return Status::Error(400, "Expected user_id as a String or a Number");
|
||||||
}
|
}
|
||||||
Slice user_id_str = user_id.type() == JsonValue::Type::String ? user_id.get_string() : user_id.get_number();
|
Slice user_id_str = user_id.type() == JsonValue::Type::String ? user_id.get_string() : user_id.get_number();
|
||||||
auto r_user_id = to_integer_safe<int32>(user_id_str);
|
auto r_user_id = to_integer_safe<int64>(user_id_str);
|
||||||
if (r_user_id.is_error()) {
|
if (r_user_id.is_error()) {
|
||||||
return Status::Error(400, PSLICE() << "Failed to get user_id from " << user_id_str);
|
return Status::Error(400, PSLICE() << "Failed to get user_id from " << user_id_str);
|
||||||
}
|
}
|
||||||
|
@ -6,13 +6,15 @@
|
|||||||
//
|
//
|
||||||
#include "td/telegram/Payments.h"
|
#include "td/telegram/Payments.h"
|
||||||
|
|
||||||
#include "td/telegram/td_api.h"
|
#include "td/telegram/AccessRights.h"
|
||||||
#include "td/telegram/telegram_api.h"
|
|
||||||
|
|
||||||
#include "td/telegram/ContactsManager.h"
|
#include "td/telegram/ContactsManager.h"
|
||||||
|
#include "td/telegram/files/FileManager.h"
|
||||||
|
#include "td/telegram/files/FileType.h"
|
||||||
#include "td/telegram/Global.h"
|
#include "td/telegram/Global.h"
|
||||||
|
#include "td/telegram/MessagesManager.h"
|
||||||
#include "td/telegram/misc.h"
|
#include "td/telegram/misc.h"
|
||||||
#include "td/telegram/PasswordManager.h"
|
#include "td/telegram/PasswordManager.h"
|
||||||
|
#include "td/telegram/ServerMessageId.h"
|
||||||
#include "td/telegram/Td.h"
|
#include "td/telegram/Td.h"
|
||||||
#include "td/telegram/UpdatesManager.h"
|
#include "td/telegram/UpdatesManager.h"
|
||||||
|
|
||||||
@ -20,8 +22,11 @@
|
|||||||
#include "td/utils/buffer.h"
|
#include "td/utils/buffer.h"
|
||||||
#include "td/utils/common.h"
|
#include "td/utils/common.h"
|
||||||
#include "td/utils/format.h"
|
#include "td/utils/format.h"
|
||||||
|
#include "td/utils/HttpUrl.h"
|
||||||
#include "td/utils/JsonBuilder.h"
|
#include "td/utils/JsonBuilder.h"
|
||||||
#include "td/utils/logging.h"
|
#include "td/utils/logging.h"
|
||||||
|
#include "td/utils/MimeType.h"
|
||||||
|
#include "td/utils/PathView.h"
|
||||||
#include "td/utils/Status.h"
|
#include "td/utils/Status.h"
|
||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
@ -129,9 +134,10 @@ static tl_object_ptr<td_api::invoice> convert_invoice(tl_object_ptr<telegram_api
|
|||||||
need_shipping_address = true;
|
need_shipping_address = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return make_tl_object<td_api::invoice>(std::move(invoice->currency_), std::move(labeled_prices), is_test, need_name,
|
return make_tl_object<td_api::invoice>(
|
||||||
need_phone_number, need_email_address, need_shipping_address,
|
std::move(invoice->currency_), std::move(labeled_prices), invoice->max_tip_amount_,
|
||||||
send_phone_number_to_provider, send_email_address_to_provider, is_flexible);
|
vector<int64>(invoice->suggested_tip_amounts_), is_test, need_name, need_phone_number, need_email_address,
|
||||||
|
need_shipping_address, send_phone_number_to_provider, send_email_address_to_provider, is_flexible);
|
||||||
}
|
}
|
||||||
|
|
||||||
static tl_object_ptr<td_api::paymentsProviderStripe> convert_payment_provider(
|
static tl_object_ptr<td_api::paymentsProviderStripe> convert_payment_provider(
|
||||||
@ -158,12 +164,16 @@ static tl_object_ptr<td_api::paymentsProviderStripe> convert_payment_provider(
|
|||||||
auto r_need_postal_code = get_json_object_bool_field(value.get_object(), "need_zip", false);
|
auto r_need_postal_code = get_json_object_bool_field(value.get_object(), "need_zip", false);
|
||||||
auto r_need_cardholder_name = get_json_object_bool_field(value.get_object(), "need_cardholder_name", false);
|
auto r_need_cardholder_name = get_json_object_bool_field(value.get_object(), "need_cardholder_name", false);
|
||||||
auto r_publishable_key = get_json_object_string_field(value.get_object(), "publishable_key", false);
|
auto r_publishable_key = get_json_object_string_field(value.get_object(), "publishable_key", false);
|
||||||
|
// TODO support "gpay_parameters":{"gateway":"stripe","stripe:publishableKey":"...","stripe:version":"..."}
|
||||||
|
|
||||||
if (value.get_object().size() != 4 || r_need_country.is_error() || r_need_postal_code.is_error() ||
|
if (r_need_country.is_error() || r_need_postal_code.is_error() || r_need_cardholder_name.is_error() ||
|
||||||
r_need_cardholder_name.is_error() || r_publishable_key.is_error()) {
|
r_publishable_key.is_error()) {
|
||||||
LOG(WARNING) << "Unsupported JSON data \"" << native_parameters->data_ << '"';
|
LOG(ERROR) << "Unsupported JSON data \"" << native_parameters->data_ << '"';
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
if (value.get_object().size() != 5) {
|
||||||
|
LOG(ERROR) << "Unsupported JSON data \"" << native_parameters->data_ << '"';
|
||||||
|
}
|
||||||
|
|
||||||
return make_tl_object<td_api::paymentsProviderStripe>(r_publishable_key.move_as_ok(), r_need_country.move_as_ok(),
|
return make_tl_object<td_api::paymentsProviderStripe>(r_publishable_key.move_as_ok(), r_need_country.move_as_ok(),
|
||||||
r_need_postal_code.move_as_ok(),
|
r_need_postal_code.move_as_ok(),
|
||||||
@ -186,9 +196,9 @@ static tl_object_ptr<telegram_api::postAddress> convert_address(tl_object_ptr<td
|
|||||||
if (address == nullptr) {
|
if (address == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return make_tl_object<telegram_api::postAddress>(std::move(address->country_code_), std::move(address->state_),
|
return make_tl_object<telegram_api::postAddress>(std::move(address->street_line1_), std::move(address->street_line2_),
|
||||||
std::move(address->city_), std::move(address->street_line1_),
|
std::move(address->city_), std::move(address->state_),
|
||||||
std::move(address->street_line2_), std::move(address->postal_code_));
|
std::move(address->country_code_), std::move(address->postal_code_));
|
||||||
}
|
}
|
||||||
|
|
||||||
static tl_object_ptr<td_api::orderInfo> convert_order_info(
|
static tl_object_ptr<td_api::orderInfo> convert_order_info(
|
||||||
@ -251,13 +261,26 @@ static tl_object_ptr<td_api::savedCredentials> convert_saved_credentials(
|
|||||||
|
|
||||||
class GetPaymentFormQuery : public Td::ResultHandler {
|
class GetPaymentFormQuery : public Td::ResultHandler {
|
||||||
Promise<tl_object_ptr<td_api::paymentForm>> promise_;
|
Promise<tl_object_ptr<td_api::paymentForm>> promise_;
|
||||||
|
DialogId dialog_id_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit GetPaymentFormQuery(Promise<tl_object_ptr<td_api::paymentForm>> &&promise) : promise_(std::move(promise)) {
|
explicit GetPaymentFormQuery(Promise<tl_object_ptr<td_api::paymentForm>> &&promise) : promise_(std::move(promise)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void send(ServerMessageId server_message_id) {
|
void send(DialogId dialog_id, ServerMessageId server_message_id,
|
||||||
send_query(G()->net_query_creator().create(telegram_api::payments_getPaymentForm(server_message_id.get())));
|
tl_object_ptr<telegram_api::dataJSON> &&theme_parameters) {
|
||||||
|
dialog_id_ = dialog_id;
|
||||||
|
auto input_peer = td->messages_manager_->get_input_peer(dialog_id, AccessRights::Read);
|
||||||
|
if (input_peer == nullptr) {
|
||||||
|
return on_error(0, Status::Error(400, "Can't access the chat"));
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 flags = 0;
|
||||||
|
if (theme_parameters != nullptr) {
|
||||||
|
flags |= telegram_api::payments_getPaymentForm::THEME_PARAMS_MASK;
|
||||||
|
}
|
||||||
|
send_query(G()->net_query_creator().create(telegram_api::payments_getPaymentForm(
|
||||||
|
flags, std::move(input_peer), server_message_id.get(), std::move(theme_parameters))));
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_result(uint64 id, BufferSlice packet) override {
|
void on_result(uint64 id, BufferSlice packet) override {
|
||||||
@ -271,31 +294,51 @@ class GetPaymentFormQuery : public Td::ResultHandler {
|
|||||||
|
|
||||||
td->contacts_manager_->on_get_users(std::move(payment_form->users_), "GetPaymentFormQuery");
|
td->contacts_manager_->on_get_users(std::move(payment_form->users_), "GetPaymentFormQuery");
|
||||||
|
|
||||||
|
UserId payments_provider_user_id(payment_form->provider_id_);
|
||||||
|
if (!payments_provider_user_id.is_valid()) {
|
||||||
|
LOG(ERROR) << "Receive invalid payments provider " << payments_provider_user_id;
|
||||||
|
return on_error(id, Status::Error(500, "Receive invalid payments provider identifier"));
|
||||||
|
}
|
||||||
|
UserId seller_bot_user_id(payment_form->bot_id_);
|
||||||
|
if (!seller_bot_user_id.is_valid()) {
|
||||||
|
LOG(ERROR) << "Receive invalid seller " << seller_bot_user_id;
|
||||||
|
return on_error(id, Status::Error(500, "Receive invalid seller identifier"));
|
||||||
|
}
|
||||||
bool can_save_credentials =
|
bool can_save_credentials =
|
||||||
(payment_form->flags_ & telegram_api::payments_paymentForm::CAN_SAVE_CREDENTIALS_MASK) != 0;
|
(payment_form->flags_ & telegram_api::payments_paymentForm::CAN_SAVE_CREDENTIALS_MASK) != 0;
|
||||||
bool need_password = (payment_form->flags_ & telegram_api::payments_paymentForm::PASSWORD_MISSING_MASK) != 0;
|
bool need_password = (payment_form->flags_ & telegram_api::payments_paymentForm::PASSWORD_MISSING_MASK) != 0;
|
||||||
promise_.set_value(make_tl_object<td_api::paymentForm>(
|
promise_.set_value(make_tl_object<td_api::paymentForm>(
|
||||||
convert_invoice(std::move(payment_form->invoice_)), std::move(payment_form->url_),
|
payment_form->form_id_, convert_invoice(std::move(payment_form->invoice_)), std::move(payment_form->url_),
|
||||||
|
td->contacts_manager_->get_user_id_object(seller_bot_user_id, "paymentForm seller"),
|
||||||
|
td->contacts_manager_->get_user_id_object(payments_provider_user_id, "paymentForm provider"),
|
||||||
convert_payment_provider(payment_form->native_provider_, std::move(payment_form->native_params_)),
|
convert_payment_provider(payment_form->native_provider_, std::move(payment_form->native_params_)),
|
||||||
convert_order_info(std::move(payment_form->saved_info_)),
|
convert_order_info(std::move(payment_form->saved_info_)),
|
||||||
convert_saved_credentials(std::move(payment_form->saved_credentials_)), can_save_credentials, need_password));
|
convert_saved_credentials(std::move(payment_form->saved_credentials_)), can_save_credentials, need_password));
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_error(uint64 id, Status status) override {
|
void on_error(uint64 id, Status status) override {
|
||||||
|
td->messages_manager_->on_get_dialog_error(dialog_id_, status, "GetPaymentFormQuery");
|
||||||
promise_.set_error(std::move(status));
|
promise_.set_error(std::move(status));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ValidateRequestedInfoQuery : public Td::ResultHandler {
|
class ValidateRequestedInfoQuery : public Td::ResultHandler {
|
||||||
Promise<tl_object_ptr<td_api::validatedOrderInfo>> promise_;
|
Promise<tl_object_ptr<td_api::validatedOrderInfo>> promise_;
|
||||||
|
DialogId dialog_id_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ValidateRequestedInfoQuery(Promise<tl_object_ptr<td_api::validatedOrderInfo>> &&promise)
|
explicit ValidateRequestedInfoQuery(Promise<tl_object_ptr<td_api::validatedOrderInfo>> &&promise)
|
||||||
: promise_(std::move(promise)) {
|
: promise_(std::move(promise)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void send(ServerMessageId server_message_id, tl_object_ptr<telegram_api::paymentRequestedInfo> requested_info,
|
void send(DialogId dialog_id, ServerMessageId server_message_id,
|
||||||
bool allow_save) {
|
tl_object_ptr<telegram_api::paymentRequestedInfo> requested_info, bool allow_save) {
|
||||||
|
dialog_id_ = dialog_id;
|
||||||
|
auto input_peer = td->messages_manager_->get_input_peer(dialog_id, AccessRights::Read);
|
||||||
|
if (input_peer == nullptr) {
|
||||||
|
return on_error(0, Status::Error(400, "Can't access the chat"));
|
||||||
|
}
|
||||||
|
|
||||||
int32 flags = 0;
|
int32 flags = 0;
|
||||||
if (allow_save) {
|
if (allow_save) {
|
||||||
flags |= telegram_api::payments_validateRequestedInfo::SAVE_MASK;
|
flags |= telegram_api::payments_validateRequestedInfo::SAVE_MASK;
|
||||||
@ -305,7 +348,7 @@ class ValidateRequestedInfoQuery : public Td::ResultHandler {
|
|||||||
requested_info->flags_ = 0;
|
requested_info->flags_ = 0;
|
||||||
}
|
}
|
||||||
send_query(G()->net_query_creator().create(telegram_api::payments_validateRequestedInfo(
|
send_query(G()->net_query_creator().create(telegram_api::payments_validateRequestedInfo(
|
||||||
flags, false /*ignored*/, server_message_id.get(), std::move(requested_info))));
|
flags, false /*ignored*/, std::move(input_peer), server_message_id.get(), std::move(requested_info))));
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_result(uint64 id, BufferSlice packet) override {
|
void on_result(uint64 id, BufferSlice packet) override {
|
||||||
@ -323,21 +366,31 @@ class ValidateRequestedInfoQuery : public Td::ResultHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void on_error(uint64 id, Status status) override {
|
void on_error(uint64 id, Status status) override {
|
||||||
|
td->messages_manager_->on_get_dialog_error(dialog_id_, status, "ValidateRequestedInfoQuery");
|
||||||
promise_.set_error(std::move(status));
|
promise_.set_error(std::move(status));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class SendPaymentFormQuery : public Td::ResultHandler {
|
class SendPaymentFormQuery : public Td::ResultHandler {
|
||||||
Promise<tl_object_ptr<td_api::paymentResult>> promise_;
|
Promise<tl_object_ptr<td_api::paymentResult>> promise_;
|
||||||
|
DialogId dialog_id_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit SendPaymentFormQuery(Promise<tl_object_ptr<td_api::paymentResult>> &&promise)
|
explicit SendPaymentFormQuery(Promise<tl_object_ptr<td_api::paymentResult>> &&promise)
|
||||||
: promise_(std::move(promise)) {
|
: promise_(std::move(promise)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void send(ServerMessageId server_message_id, const string &order_info_id, const string &shipping_option_id,
|
void send(DialogId dialog_id, ServerMessageId server_message_id, int64 payment_form_id, const string &order_info_id,
|
||||||
tl_object_ptr<telegram_api::InputPaymentCredentials> input_credentials) {
|
const string &shipping_option_id, tl_object_ptr<telegram_api::InputPaymentCredentials> input_credentials,
|
||||||
|
int64 tip_amount) {
|
||||||
CHECK(input_credentials != nullptr);
|
CHECK(input_credentials != nullptr);
|
||||||
|
|
||||||
|
dialog_id_ = dialog_id;
|
||||||
|
auto input_peer = td->messages_manager_->get_input_peer(dialog_id, AccessRights::Read);
|
||||||
|
if (input_peer == nullptr) {
|
||||||
|
return on_error(0, Status::Error(400, "Can't access the chat"));
|
||||||
|
}
|
||||||
|
|
||||||
int32 flags = 0;
|
int32 flags = 0;
|
||||||
if (!order_info_id.empty()) {
|
if (!order_info_id.empty()) {
|
||||||
flags |= telegram_api::payments_sendPaymentForm::REQUESTED_INFO_ID_MASK;
|
flags |= telegram_api::payments_sendPaymentForm::REQUESTED_INFO_ID_MASK;
|
||||||
@ -345,8 +398,12 @@ class SendPaymentFormQuery : public Td::ResultHandler {
|
|||||||
if (!shipping_option_id.empty()) {
|
if (!shipping_option_id.empty()) {
|
||||||
flags |= telegram_api::payments_sendPaymentForm::SHIPPING_OPTION_ID_MASK;
|
flags |= telegram_api::payments_sendPaymentForm::SHIPPING_OPTION_ID_MASK;
|
||||||
}
|
}
|
||||||
|
if (tip_amount != 0) {
|
||||||
|
flags |= telegram_api::payments_sendPaymentForm::TIP_AMOUNT_MASK;
|
||||||
|
}
|
||||||
send_query(G()->net_query_creator().create(telegram_api::payments_sendPaymentForm(
|
send_query(G()->net_query_creator().create(telegram_api::payments_sendPaymentForm(
|
||||||
flags, server_message_id.get(), order_info_id, shipping_option_id, std::move(input_credentials))));
|
flags, payment_form_id, std::move(input_peer), server_message_id.get(), order_info_id, shipping_option_id,
|
||||||
|
std::move(input_credentials), tip_amount)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_result(uint64 id, BufferSlice packet) override {
|
void on_result(uint64 id, BufferSlice packet) override {
|
||||||
@ -378,20 +435,29 @@ class SendPaymentFormQuery : public Td::ResultHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void on_error(uint64 id, Status status) override {
|
void on_error(uint64 id, Status status) override {
|
||||||
|
td->messages_manager_->on_get_dialog_error(dialog_id_, status, "SendPaymentFormQuery");
|
||||||
promise_.set_error(std::move(status));
|
promise_.set_error(std::move(status));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class GetPaymentReceiptQuery : public Td::ResultHandler {
|
class GetPaymentReceiptQuery : public Td::ResultHandler {
|
||||||
Promise<tl_object_ptr<td_api::paymentReceipt>> promise_;
|
Promise<tl_object_ptr<td_api::paymentReceipt>> promise_;
|
||||||
|
DialogId dialog_id_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit GetPaymentReceiptQuery(Promise<tl_object_ptr<td_api::paymentReceipt>> &&promise)
|
explicit GetPaymentReceiptQuery(Promise<tl_object_ptr<td_api::paymentReceipt>> &&promise)
|
||||||
: promise_(std::move(promise)) {
|
: promise_(std::move(promise)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void send(ServerMessageId server_message_id) {
|
void send(DialogId dialog_id, ServerMessageId server_message_id) {
|
||||||
send_query(G()->net_query_creator().create(telegram_api::payments_getPaymentReceipt(server_message_id.get())));
|
dialog_id_ = dialog_id;
|
||||||
|
auto input_peer = td->messages_manager_->get_input_peer(dialog_id, AccessRights::Read);
|
||||||
|
if (input_peer == nullptr) {
|
||||||
|
return on_error(0, Status::Error(400, "Can't access the chat"));
|
||||||
|
}
|
||||||
|
|
||||||
|
send_query(G()->net_query_creator().create(
|
||||||
|
telegram_api::payments_getPaymentReceipt(std::move(input_peer), server_message_id.get())));
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_result(uint64 id, BufferSlice packet) override {
|
void on_result(uint64 id, BufferSlice packet) override {
|
||||||
@ -408,17 +474,26 @@ class GetPaymentReceiptQuery : public Td::ResultHandler {
|
|||||||
UserId payments_provider_user_id(payment_receipt->provider_id_);
|
UserId payments_provider_user_id(payment_receipt->provider_id_);
|
||||||
if (!payments_provider_user_id.is_valid()) {
|
if (!payments_provider_user_id.is_valid()) {
|
||||||
LOG(ERROR) << "Receive invalid payments provider " << payments_provider_user_id;
|
LOG(ERROR) << "Receive invalid payments provider " << payments_provider_user_id;
|
||||||
payments_provider_user_id = UserId();
|
return on_error(id, Status::Error(500, "Receive invalid payments provider identifier"));
|
||||||
}
|
}
|
||||||
|
UserId seller_bot_user_id(payment_receipt->bot_id_);
|
||||||
|
if (!seller_bot_user_id.is_valid()) {
|
||||||
|
LOG(ERROR) << "Receive invalid seller " << seller_bot_user_id;
|
||||||
|
return on_error(id, Status::Error(500, "Receive invalid seller identifier"));
|
||||||
|
}
|
||||||
|
auto photo = get_web_document_photo(td->file_manager_.get(), std::move(payment_receipt->photo_), dialog_id_);
|
||||||
|
|
||||||
promise_.set_value(make_tl_object<td_api::paymentReceipt>(
|
promise_.set_value(make_tl_object<td_api::paymentReceipt>(
|
||||||
payment_receipt->date_, td->contacts_manager_->get_user_id_object(payments_provider_user_id, "paymentReceipt"),
|
payment_receipt->title_, payment_receipt->description_, get_photo_object(td->file_manager_.get(), photo),
|
||||||
|
payment_receipt->date_, td->contacts_manager_->get_user_id_object(seller_bot_user_id, "paymentReceipt seller"),
|
||||||
|
td->contacts_manager_->get_user_id_object(payments_provider_user_id, "paymentReceipt provider"),
|
||||||
convert_invoice(std::move(payment_receipt->invoice_)), convert_order_info(std::move(payment_receipt->info_)),
|
convert_invoice(std::move(payment_receipt->invoice_)), convert_order_info(std::move(payment_receipt->info_)),
|
||||||
convert_shipping_option(std::move(payment_receipt->shipping_)),
|
convert_shipping_option(std::move(payment_receipt->shipping_)), std::move(payment_receipt->credentials_title_),
|
||||||
std::move(payment_receipt->credentials_title_)));
|
payment_receipt->tip_amount_));
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_error(uint64 id, Status status) override {
|
void on_error(uint64 id, Status status) override {
|
||||||
|
td->messages_manager_->on_get_dialog_error(dialog_id_, status, "GetPaymentReceiptQuery");
|
||||||
promise_.set_error(std::move(status));
|
promise_.set_error(std::move(status));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -533,7 +608,8 @@ bool operator==(const Invoice &lhs, const Invoice &rhs) {
|
|||||||
lhs.need_shipping_address == rhs.need_shipping_address &&
|
lhs.need_shipping_address == rhs.need_shipping_address &&
|
||||||
lhs.send_phone_number_to_provider == rhs.send_phone_number_to_provider &&
|
lhs.send_phone_number_to_provider == rhs.send_phone_number_to_provider &&
|
||||||
lhs.send_email_address_to_provider == rhs.send_email_address_to_provider &&
|
lhs.send_email_address_to_provider == rhs.send_email_address_to_provider &&
|
||||||
lhs.is_flexible == rhs.is_flexible && lhs.currency == rhs.currency && lhs.price_parts == rhs.price_parts;
|
lhs.is_flexible == rhs.is_flexible && lhs.currency == rhs.currency && lhs.price_parts == rhs.price_parts &&
|
||||||
|
lhs.max_tip_amount == rhs.max_tip_amount && lhs.suggested_tip_amounts == rhs.suggested_tip_amounts;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const Invoice &lhs, const Invoice &rhs) {
|
bool operator!=(const Invoice &lhs, const Invoice &rhs) {
|
||||||
@ -548,7 +624,298 @@ StringBuilder &operator<<(StringBuilder &string_builder, const Invoice &invoice)
|
|||||||
<< (invoice.need_shipping_address ? ", needs shipping address" : "")
|
<< (invoice.need_shipping_address ? ", needs shipping address" : "")
|
||||||
<< (invoice.send_phone_number_to_provider ? ", sends phone number to provider" : "")
|
<< (invoice.send_phone_number_to_provider ? ", sends phone number to provider" : "")
|
||||||
<< (invoice.send_email_address_to_provider ? ", sends email address to provider" : "") << " in "
|
<< (invoice.send_email_address_to_provider ? ", sends email address to provider" : "") << " in "
|
||||||
<< invoice.currency << " with price parts " << format::as_array(invoice.price_parts) << "]";
|
<< invoice.currency << " with price parts " << format::as_array(invoice.price_parts)
|
||||||
|
<< " and suggested tip amounts " << invoice.suggested_tip_amounts << " up to "
|
||||||
|
<< invoice.max_tip_amount << "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const InputInvoice &lhs, const InputInvoice &rhs) {
|
||||||
|
return lhs.title == rhs.title && lhs.description == rhs.description && lhs.photo == rhs.photo &&
|
||||||
|
lhs.start_parameter == rhs.start_parameter && lhs.invoice == rhs.invoice &&
|
||||||
|
lhs.total_amount == rhs.total_amount && lhs.receipt_message_id == rhs.receipt_message_id &&
|
||||||
|
lhs.payload == rhs.payload && lhs.provider_token == rhs.provider_token &&
|
||||||
|
lhs.provider_data == rhs.provider_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const InputInvoice &lhs, const InputInvoice &rhs) {
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
InputInvoice get_input_invoice(tl_object_ptr<telegram_api::messageMediaInvoice> &&message_invoice, Td *td,
|
||||||
|
DialogId owner_dialog_id) {
|
||||||
|
InputInvoice result;
|
||||||
|
result.title = std::move(message_invoice->title_);
|
||||||
|
result.description = std::move(message_invoice->description_);
|
||||||
|
result.photo = get_web_document_photo(td->file_manager_.get(), std::move(message_invoice->photo_), owner_dialog_id);
|
||||||
|
result.start_parameter = std::move(message_invoice->start_param_);
|
||||||
|
result.invoice.currency = std::move(message_invoice->currency_);
|
||||||
|
result.invoice.is_test = (message_invoice->flags_ & telegram_api::messageMediaInvoice::TEST_MASK) != 0;
|
||||||
|
result.invoice.need_shipping_address =
|
||||||
|
(message_invoice->flags_ & telegram_api::messageMediaInvoice::SHIPPING_ADDRESS_REQUESTED_MASK) != 0;
|
||||||
|
// result.payload = string();
|
||||||
|
// result.provider_token = string();
|
||||||
|
// result.provider_data = string();
|
||||||
|
result.total_amount = message_invoice->total_amount_;
|
||||||
|
if ((message_invoice->flags_ & telegram_api::messageMediaInvoice::RECEIPT_MSG_ID_MASK) != 0) {
|
||||||
|
result.receipt_message_id = MessageId(ServerMessageId(message_invoice->receipt_msg_id_));
|
||||||
|
if (!result.receipt_message_id.is_valid()) {
|
||||||
|
LOG(ERROR) << "Receive as receipt message " << result.receipt_message_id << " in " << owner_dialog_id;
|
||||||
|
result.receipt_message_id = MessageId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
InputInvoice get_input_invoice(tl_object_ptr<telegram_api::botInlineMessageMediaInvoice> &&message_invoice, Td *td,
|
||||||
|
DialogId owner_dialog_id) {
|
||||||
|
InputInvoice result;
|
||||||
|
result.title = std::move(message_invoice->title_);
|
||||||
|
result.description = std::move(message_invoice->description_);
|
||||||
|
result.photo = get_web_document_photo(td->file_manager_.get(), std::move(message_invoice->photo_), owner_dialog_id);
|
||||||
|
// result.start_parameter = string();
|
||||||
|
result.invoice.currency = std::move(message_invoice->currency_);
|
||||||
|
result.invoice.is_test = (message_invoice->flags_ & telegram_api::messageMediaInvoice::TEST_MASK) != 0;
|
||||||
|
result.invoice.need_shipping_address =
|
||||||
|
(message_invoice->flags_ & telegram_api::messageMediaInvoice::SHIPPING_ADDRESS_REQUESTED_MASK) != 0;
|
||||||
|
// result.payload = string();
|
||||||
|
// result.provider_token = string();
|
||||||
|
// result.provider_data = string();
|
||||||
|
result.total_amount = message_invoice->total_amount_;
|
||||||
|
// result.receipt_message_id = MessageId();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<InputInvoice> process_input_message_invoice(
|
||||||
|
td_api::object_ptr<td_api::InputMessageContent> &&input_message_content, Td *td) {
|
||||||
|
CHECK(input_message_content != nullptr);
|
||||||
|
CHECK(input_message_content->get_id() == td_api::inputMessageInvoice::ID);
|
||||||
|
auto input_invoice = move_tl_object_as<td_api::inputMessageInvoice>(input_message_content);
|
||||||
|
|
||||||
|
if (!clean_input_string(input_invoice->title_)) {
|
||||||
|
return Status::Error(400, "Invoice title must be encoded in UTF-8");
|
||||||
|
}
|
||||||
|
if (!clean_input_string(input_invoice->description_)) {
|
||||||
|
return Status::Error(400, "Invoice description must be encoded in UTF-8");
|
||||||
|
}
|
||||||
|
if (!clean_input_string(input_invoice->photo_url_)) {
|
||||||
|
return Status::Error(400, "Invoice photo URL must be encoded in UTF-8");
|
||||||
|
}
|
||||||
|
if (!clean_input_string(input_invoice->start_parameter_)) {
|
||||||
|
return Status::Error(400, "Invoice bot start parameter must be encoded in UTF-8");
|
||||||
|
}
|
||||||
|
if (!clean_input_string(input_invoice->provider_token_)) {
|
||||||
|
return Status::Error(400, "Invoice provider token must be encoded in UTF-8");
|
||||||
|
}
|
||||||
|
if (!clean_input_string(input_invoice->provider_data_)) {
|
||||||
|
return Status::Error(400, "Invoice provider data must be encoded in UTF-8");
|
||||||
|
}
|
||||||
|
if (!clean_input_string(input_invoice->invoice_->currency_)) {
|
||||||
|
return Status::Error(400, "Invoice currency must be encoded in UTF-8");
|
||||||
|
}
|
||||||
|
|
||||||
|
InputInvoice result;
|
||||||
|
result.title = std::move(input_invoice->title_);
|
||||||
|
result.description = std::move(input_invoice->description_);
|
||||||
|
|
||||||
|
auto r_http_url = parse_url(input_invoice->photo_url_);
|
||||||
|
if (r_http_url.is_error()) {
|
||||||
|
if (!input_invoice->photo_url_.empty()) {
|
||||||
|
LOG(INFO) << "Can't register url " << input_invoice->photo_url_;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
auto url = r_http_url.ok().get_url();
|
||||||
|
auto r_invoice_file_id = td->file_manager_->from_persistent_id(url, FileType::Temp);
|
||||||
|
if (r_invoice_file_id.is_error()) {
|
||||||
|
LOG(INFO) << "Can't register url " << url;
|
||||||
|
} else {
|
||||||
|
auto invoice_file_id = r_invoice_file_id.move_as_ok();
|
||||||
|
|
||||||
|
PhotoSize s;
|
||||||
|
s.type = 'n';
|
||||||
|
s.dimensions =
|
||||||
|
get_dimensions(input_invoice->photo_width_, input_invoice->photo_height_, "process_input_message_invoice");
|
||||||
|
s.size = input_invoice->photo_size_; // TODO use invoice_file_id size
|
||||||
|
s.file_id = invoice_file_id;
|
||||||
|
|
||||||
|
result.photo.id = 0;
|
||||||
|
result.photo.photos.push_back(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.start_parameter = std::move(input_invoice->start_parameter_);
|
||||||
|
|
||||||
|
result.invoice.currency = std::move(input_invoice->invoice_->currency_);
|
||||||
|
result.invoice.price_parts.reserve(input_invoice->invoice_->price_parts_.size());
|
||||||
|
int64 total_amount = 0;
|
||||||
|
const int64 MAX_AMOUNT = 9999'9999'9999;
|
||||||
|
for (auto &price : input_invoice->invoice_->price_parts_) {
|
||||||
|
if (!clean_input_string(price->label_)) {
|
||||||
|
return Status::Error(400, "Invoice price label must be encoded in UTF-8");
|
||||||
|
}
|
||||||
|
result.invoice.price_parts.emplace_back(std::move(price->label_), price->amount_);
|
||||||
|
if (price->amount_ < -MAX_AMOUNT || price->amount_ > MAX_AMOUNT) {
|
||||||
|
return Status::Error(400, "Too big amount of the currency specified");
|
||||||
|
}
|
||||||
|
total_amount += price->amount_;
|
||||||
|
}
|
||||||
|
if (total_amount <= 0) {
|
||||||
|
return Status::Error(400, "Total price must be positive");
|
||||||
|
}
|
||||||
|
if (total_amount > MAX_AMOUNT) {
|
||||||
|
return Status::Error(400, "Total price is too big");
|
||||||
|
}
|
||||||
|
result.total_amount = total_amount;
|
||||||
|
|
||||||
|
if (input_invoice->invoice_->max_tip_amount_ < 0 || input_invoice->invoice_->max_tip_amount_ > MAX_AMOUNT) {
|
||||||
|
return Status::Error(400, "Invalid max_tip_amount of the currency specified");
|
||||||
|
}
|
||||||
|
for (auto tip_amount : input_invoice->invoice_->suggested_tip_amounts_) {
|
||||||
|
if (tip_amount <= 0) {
|
||||||
|
return Status::Error(400, "Suggested tip amount must be positive");
|
||||||
|
}
|
||||||
|
if (tip_amount > input_invoice->invoice_->max_tip_amount_) {
|
||||||
|
return Status::Error(400, "Suggested tip amount can't be bigger than max_tip_amount");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (input_invoice->invoice_->suggested_tip_amounts_.size() > 4) {
|
||||||
|
return Status::Error(400, "There can be at most 4 suggested tip amounts");
|
||||||
|
}
|
||||||
|
|
||||||
|
result.invoice.max_tip_amount = input_invoice->invoice_->max_tip_amount_;
|
||||||
|
result.invoice.suggested_tip_amounts = std::move(input_invoice->invoice_->suggested_tip_amounts_);
|
||||||
|
result.invoice.is_test = input_invoice->invoice_->is_test_;
|
||||||
|
result.invoice.need_name = input_invoice->invoice_->need_name_;
|
||||||
|
result.invoice.need_phone_number = input_invoice->invoice_->need_phone_number_;
|
||||||
|
result.invoice.need_email_address = input_invoice->invoice_->need_email_address_;
|
||||||
|
result.invoice.need_shipping_address = input_invoice->invoice_->need_shipping_address_;
|
||||||
|
result.invoice.send_phone_number_to_provider = input_invoice->invoice_->send_phone_number_to_provider_;
|
||||||
|
result.invoice.send_email_address_to_provider = input_invoice->invoice_->send_email_address_to_provider_;
|
||||||
|
result.invoice.is_flexible = input_invoice->invoice_->is_flexible_;
|
||||||
|
if (result.invoice.send_phone_number_to_provider) {
|
||||||
|
result.invoice.need_phone_number = true;
|
||||||
|
}
|
||||||
|
if (result.invoice.send_email_address_to_provider) {
|
||||||
|
result.invoice.need_email_address = true;
|
||||||
|
}
|
||||||
|
if (result.invoice.is_flexible) {
|
||||||
|
result.invoice.need_shipping_address = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.payload = std::move(input_invoice->payload_);
|
||||||
|
result.provider_token = std::move(input_invoice->provider_token_);
|
||||||
|
result.provider_data = std::move(input_invoice->provider_data_);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
tl_object_ptr<td_api::messageInvoice> get_message_invoice_object(const InputInvoice &input_invoice, Td *td) {
|
||||||
|
return make_tl_object<td_api::messageInvoice>(
|
||||||
|
input_invoice.title, input_invoice.description, get_photo_object(td->file_manager_.get(), input_invoice.photo),
|
||||||
|
input_invoice.invoice.currency, input_invoice.total_amount, input_invoice.start_parameter,
|
||||||
|
input_invoice.invoice.is_test, input_invoice.invoice.need_shipping_address,
|
||||||
|
input_invoice.receipt_message_id.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
static tl_object_ptr<telegram_api::invoice> get_input_invoice(const Invoice &invoice) {
|
||||||
|
int32 flags = 0;
|
||||||
|
if (invoice.is_test) {
|
||||||
|
flags |= telegram_api::invoice::TEST_MASK;
|
||||||
|
}
|
||||||
|
if (invoice.need_name) {
|
||||||
|
flags |= telegram_api::invoice::NAME_REQUESTED_MASK;
|
||||||
|
}
|
||||||
|
if (invoice.need_phone_number) {
|
||||||
|
flags |= telegram_api::invoice::PHONE_REQUESTED_MASK;
|
||||||
|
}
|
||||||
|
if (invoice.need_email_address) {
|
||||||
|
flags |= telegram_api::invoice::EMAIL_REQUESTED_MASK;
|
||||||
|
}
|
||||||
|
if (invoice.need_shipping_address) {
|
||||||
|
flags |= telegram_api::invoice::SHIPPING_ADDRESS_REQUESTED_MASK;
|
||||||
|
}
|
||||||
|
if (invoice.send_phone_number_to_provider) {
|
||||||
|
flags |= telegram_api::invoice::PHONE_TO_PROVIDER_MASK;
|
||||||
|
}
|
||||||
|
if (invoice.send_email_address_to_provider) {
|
||||||
|
flags |= telegram_api::invoice::EMAIL_TO_PROVIDER_MASK;
|
||||||
|
}
|
||||||
|
if (invoice.is_flexible) {
|
||||||
|
flags |= telegram_api::invoice::FLEXIBLE_MASK;
|
||||||
|
}
|
||||||
|
if (invoice.max_tip_amount != 0) {
|
||||||
|
flags |= telegram_api::invoice::MAX_TIP_AMOUNT_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto prices = transform(invoice.price_parts, [](const LabeledPricePart &price) {
|
||||||
|
return telegram_api::make_object<telegram_api::labeledPrice>(price.label, price.amount);
|
||||||
|
});
|
||||||
|
return make_tl_object<telegram_api::invoice>(
|
||||||
|
flags, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/,
|
||||||
|
false /*ignored*/, false /*ignored*/, false /*ignored*/, invoice.currency, std::move(prices),
|
||||||
|
invoice.max_tip_amount, vector<int64>(invoice.suggested_tip_amounts));
|
||||||
|
}
|
||||||
|
|
||||||
|
static tl_object_ptr<telegram_api::inputWebDocument> get_input_web_document(const FileManager *file_manager,
|
||||||
|
const Photo &photo) {
|
||||||
|
if (photo.is_empty()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
CHECK(photo.photos.size() == 1);
|
||||||
|
const PhotoSize &size = photo.photos[0];
|
||||||
|
CHECK(size.file_id.is_valid());
|
||||||
|
|
||||||
|
vector<tl_object_ptr<telegram_api::DocumentAttribute>> attributes;
|
||||||
|
if (size.dimensions.width != 0 && size.dimensions.height != 0) {
|
||||||
|
attributes.push_back(
|
||||||
|
make_tl_object<telegram_api::documentAttributeImageSize>(size.dimensions.width, size.dimensions.height));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto file_view = file_manager->get_file_view(size.file_id);
|
||||||
|
CHECK(file_view.has_url());
|
||||||
|
|
||||||
|
auto file_name = get_url_file_name(file_view.url());
|
||||||
|
return make_tl_object<telegram_api::inputWebDocument>(
|
||||||
|
file_view.url(), size.size, MimeType::from_extension(PathView(file_name).extension(), "image/jpeg"),
|
||||||
|
std::move(attributes));
|
||||||
|
}
|
||||||
|
|
||||||
|
tl_object_ptr<telegram_api::inputMediaInvoice> get_input_media_invoice(const InputInvoice &input_invoice, Td *td) {
|
||||||
|
int32 flags = 0;
|
||||||
|
if (!input_invoice.start_parameter.empty()) {
|
||||||
|
flags |= telegram_api::inputMediaInvoice::START_PARAM_MASK;
|
||||||
|
}
|
||||||
|
auto input_web_document = get_input_web_document(td->file_manager_.get(), input_invoice.photo);
|
||||||
|
if (input_web_document != nullptr) {
|
||||||
|
flags |= telegram_api::inputMediaInvoice::PHOTO_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return make_tl_object<telegram_api::inputMediaInvoice>(
|
||||||
|
flags, input_invoice.title, input_invoice.description, std::move(input_web_document),
|
||||||
|
get_input_invoice(input_invoice.invoice), BufferSlice(input_invoice.payload), input_invoice.provider_token,
|
||||||
|
telegram_api::make_object<telegram_api::dataJSON>(
|
||||||
|
input_invoice.provider_data.empty() ? "null" : input_invoice.provider_data),
|
||||||
|
input_invoice.start_parameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
tl_object_ptr<telegram_api::inputBotInlineMessageMediaInvoice> get_input_bot_inline_message_media_invoice(
|
||||||
|
const InputInvoice &input_invoice, tl_object_ptr<telegram_api::ReplyMarkup> &&reply_markup, Td *td) {
|
||||||
|
int32 flags = 0;
|
||||||
|
if (reply_markup != nullptr) {
|
||||||
|
flags |= telegram_api::inputBotInlineMessageMediaInvoice::REPLY_MARKUP_MASK;
|
||||||
|
}
|
||||||
|
auto input_web_document = get_input_web_document(td->file_manager_.get(), input_invoice.photo);
|
||||||
|
if (input_web_document != nullptr) {
|
||||||
|
flags |= telegram_api::inputBotInlineMessageMediaInvoice::PHOTO_MASK;
|
||||||
|
}
|
||||||
|
return make_tl_object<telegram_api::inputBotInlineMessageMediaInvoice>(
|
||||||
|
flags, input_invoice.title, input_invoice.description, std::move(input_web_document),
|
||||||
|
get_input_invoice(input_invoice.invoice), BufferSlice(input_invoice.payload), input_invoice.provider_token,
|
||||||
|
telegram_api::make_object<telegram_api::dataJSON>(
|
||||||
|
input_invoice.provider_data.empty() ? "null" : input_invoice.provider_data),
|
||||||
|
std::move(reply_markup));
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<FileId> get_input_invoice_file_ids(const InputInvoice &input_invoice) {
|
||||||
|
return photo_get_file_ids(input_invoice.photo);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const Address &lhs, const Address &rhs) {
|
bool operator==(const Address &lhs, const Address &rhs) {
|
||||||
@ -738,7 +1105,8 @@ StringBuilder &operator<<(StringBuilder &string_builder, const ShippingOption &s
|
|||||||
<< " with price parts " << format::as_array(shipping_option.price_parts) << "]";
|
<< " with price parts " << format::as_array(shipping_option.price_parts) << "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
void answer_shipping_query(int64 shipping_query_id, vector<tl_object_ptr<td_api::shippingOption>> &&shipping_options,
|
void answer_shipping_query(Td *td, int64 shipping_query_id,
|
||||||
|
vector<tl_object_ptr<td_api::shippingOption>> &&shipping_options,
|
||||||
const string &error_message, Promise<Unit> &&promise) {
|
const string &error_message, Promise<Unit> &&promise) {
|
||||||
vector<tl_object_ptr<telegram_api::shippingOption>> options;
|
vector<tl_object_ptr<telegram_api::shippingOption>> options;
|
||||||
for (auto &option : shipping_options) {
|
for (auto &option : shipping_options) {
|
||||||
@ -746,7 +1114,7 @@ void answer_shipping_query(int64 shipping_query_id, vector<tl_object_ptr<td_api:
|
|||||||
return promise.set_error(Status::Error(400, "Shipping option must be non-empty"));
|
return promise.set_error(Status::Error(400, "Shipping option must be non-empty"));
|
||||||
}
|
}
|
||||||
if (!clean_input_string(option->id_)) {
|
if (!clean_input_string(option->id_)) {
|
||||||
return promise.set_error(Status::Error(400, "Shipping option id must be encoded in UTF-8"));
|
return promise.set_error(Status::Error(400, "Shipping option identifier must be encoded in UTF-8"));
|
||||||
}
|
}
|
||||||
if (!clean_input_string(option->title_)) {
|
if (!clean_input_string(option->title_)) {
|
||||||
return promise.set_error(Status::Error(400, "Shipping option title must be encoded in UTF-8"));
|
return promise.set_error(Status::Error(400, "Shipping option title must be encoded in UTF-8"));
|
||||||
@ -768,25 +1136,42 @@ void answer_shipping_query(int64 shipping_query_id, vector<tl_object_ptr<td_api:
|
|||||||
std::move(prices)));
|
std::move(prices)));
|
||||||
}
|
}
|
||||||
|
|
||||||
G()->td()
|
td->create_handler<SetBotShippingAnswerQuery>(std::move(promise))
|
||||||
.get_actor_unsafe()
|
|
||||||
->create_handler<SetBotShippingAnswerQuery>(std::move(promise))
|
|
||||||
->send(shipping_query_id, error_message, std::move(options));
|
->send(shipping_query_id, error_message, std::move(options));
|
||||||
}
|
}
|
||||||
|
|
||||||
void answer_pre_checkout_query(int64 pre_checkout_query_id, const string &error_message, Promise<Unit> &&promise) {
|
void answer_pre_checkout_query(Td *td, int64 pre_checkout_query_id, const string &error_message,
|
||||||
G()->td()
|
Promise<Unit> &&promise) {
|
||||||
.get_actor_unsafe()
|
td->create_handler<SetBotPreCheckoutAnswerQuery>(std::move(promise))->send(pre_checkout_query_id, error_message);
|
||||||
->create_handler<SetBotPreCheckoutAnswerQuery>(std::move(promise))
|
|
||||||
->send(pre_checkout_query_id, error_message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void get_payment_form(ServerMessageId server_message_id, Promise<tl_object_ptr<td_api::paymentForm>> &&promise) {
|
void get_payment_form(Td *td, FullMessageId full_message_id, const td_api::object_ptr<td_api::paymentFormTheme> &theme,
|
||||||
G()->td().get_actor_unsafe()->create_handler<GetPaymentFormQuery>(std::move(promise))->send(server_message_id);
|
Promise<tl_object_ptr<td_api::paymentForm>> &&promise) {
|
||||||
|
TRY_RESULT_PROMISE(promise, server_message_id, td->messages_manager_->get_invoice_message_id(full_message_id));
|
||||||
|
|
||||||
|
tl_object_ptr<telegram_api::dataJSON> theme_parameters;
|
||||||
|
if (theme != nullptr) {
|
||||||
|
theme_parameters = make_tl_object<telegram_api::dataJSON>(string());
|
||||||
|
theme_parameters->data_ = json_encode<string>(json_object([&theme](auto &o) {
|
||||||
|
auto get_color = [](int32 color) {
|
||||||
|
return static_cast<int64>(static_cast<uint32>(color) | 0x000000FF);
|
||||||
|
};
|
||||||
|
o("bg_color", get_color(theme->background_color_));
|
||||||
|
o("text_color", get_color(theme->text_color_));
|
||||||
|
o("hint_color", get_color(theme->hint_color_));
|
||||||
|
o("link_color", get_color(theme->link_color_));
|
||||||
|
o("button_color", get_color(theme->button_color_));
|
||||||
|
o("button_text_color", get_color(theme->button_text_color_));
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
td->create_handler<GetPaymentFormQuery>(std::move(promise))
|
||||||
|
->send(full_message_id.get_dialog_id(), server_message_id, std::move(theme_parameters));
|
||||||
}
|
}
|
||||||
|
|
||||||
void validate_order_info(ServerMessageId server_message_id, tl_object_ptr<td_api::orderInfo> order_info,
|
void validate_order_info(Td *td, FullMessageId full_message_id, tl_object_ptr<td_api::orderInfo> order_info,
|
||||||
bool allow_save, Promise<tl_object_ptr<td_api::validatedOrderInfo>> &&promise) {
|
bool allow_save, Promise<tl_object_ptr<td_api::validatedOrderInfo>> &&promise) {
|
||||||
|
TRY_RESULT_PROMISE(promise, server_message_id, td->messages_manager_->get_invoice_message_id(full_message_id));
|
||||||
|
|
||||||
if (order_info != nullptr) {
|
if (order_info != nullptr) {
|
||||||
if (!clean_input_string(order_info->name_)) {
|
if (!clean_input_string(order_info->name_)) {
|
||||||
return promise.set_error(Status::Error(400, "Name must be encoded in UTF-8"));
|
return promise.set_error(Status::Error(400, "Name must be encoded in UTF-8"));
|
||||||
@ -819,16 +1204,18 @@ void validate_order_info(ServerMessageId server_message_id, tl_object_ptr<td_api
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
G()->td()
|
td->create_handler<ValidateRequestedInfoQuery>(std::move(promise))
|
||||||
.get_actor_unsafe()
|
->send(full_message_id.get_dialog_id(), server_message_id, convert_order_info(std::move(order_info)), allow_save);
|
||||||
->create_handler<ValidateRequestedInfoQuery>(std::move(promise))
|
|
||||||
->send(server_message_id, convert_order_info(std::move(order_info)), allow_save);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void send_payment_form(ServerMessageId server_message_id, const string &order_info_id, const string &shipping_option_id,
|
void send_payment_form(Td *td, FullMessageId full_message_id, int64 payment_form_id, const string &order_info_id,
|
||||||
const tl_object_ptr<td_api::InputCredentials> &credentials,
|
const string &shipping_option_id, const tl_object_ptr<td_api::InputCredentials> &credentials,
|
||||||
Promise<tl_object_ptr<td_api::paymentResult>> &&promise) {
|
int64 tip_amount, Promise<tl_object_ptr<td_api::paymentResult>> &&promise) {
|
||||||
CHECK(credentials != nullptr);
|
TRY_RESULT_PROMISE(promise, server_message_id, td->messages_manager_->get_invoice_message_id(full_message_id));
|
||||||
|
|
||||||
|
if (credentials == nullptr) {
|
||||||
|
return promise.set_error(Status::Error(400, "Input payment credentials must be non-empty"));
|
||||||
|
}
|
||||||
|
|
||||||
tl_object_ptr<telegram_api::InputPaymentCredentials> input_credentials;
|
tl_object_ptr<telegram_api::InputPaymentCredentials> input_credentials;
|
||||||
switch (credentials->get_id()) {
|
switch (credentials->get_id()) {
|
||||||
@ -836,10 +1223,9 @@ void send_payment_form(ServerMessageId server_message_id, const string &order_in
|
|||||||
auto credentials_saved = static_cast<const td_api::inputCredentialsSaved *>(credentials.get());
|
auto credentials_saved = static_cast<const td_api::inputCredentialsSaved *>(credentials.get());
|
||||||
auto credentials_id = credentials_saved->saved_credentials_id_;
|
auto credentials_id = credentials_saved->saved_credentials_id_;
|
||||||
if (!clean_input_string(credentials_id)) {
|
if (!clean_input_string(credentials_id)) {
|
||||||
return promise.set_error(Status::Error(400, "Credentials id must be encoded in UTF-8"));
|
return promise.set_error(Status::Error(400, "Credentials identifier must be encoded in UTF-8"));
|
||||||
}
|
}
|
||||||
auto temp_password_state =
|
auto temp_password_state = td->password_manager_->get_actor_unsafe()->get_temp_password_state_sync();
|
||||||
G()->td().get_actor_unsafe()->password_manager_->get_actor_unsafe()->get_temp_password_state_sync();
|
|
||||||
if (!temp_password_state.has_temp_password) {
|
if (!temp_password_state.has_temp_password) {
|
||||||
return promise.set_error(Status::Error(400, "Temporary password required to use saved credentials"));
|
return promise.set_error(Status::Error(400, "Temporary password required to use saved credentials"));
|
||||||
}
|
}
|
||||||
@ -875,30 +1261,34 @@ void send_payment_form(ServerMessageId server_message_id, const string &order_in
|
|||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
G()->td()
|
td->create_handler<SendPaymentFormQuery>(std::move(promise))
|
||||||
.get_actor_unsafe()
|
->send(full_message_id.get_dialog_id(), server_message_id, payment_form_id, order_info_id, shipping_option_id,
|
||||||
->create_handler<SendPaymentFormQuery>(std::move(promise))
|
std::move(input_credentials), tip_amount);
|
||||||
->send(server_message_id, order_info_id, shipping_option_id, std::move(input_credentials));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void get_payment_receipt(ServerMessageId server_message_id, Promise<tl_object_ptr<td_api::paymentReceipt>> &&promise) {
|
void get_payment_receipt(Td *td, FullMessageId full_message_id,
|
||||||
G()->td().get_actor_unsafe()->create_handler<GetPaymentReceiptQuery>(std::move(promise))->send(server_message_id);
|
Promise<tl_object_ptr<td_api::paymentReceipt>> &&promise) {
|
||||||
|
TRY_RESULT_PROMISE(promise, server_message_id,
|
||||||
|
td->messages_manager_->get_payment_successful_message_id(full_message_id));
|
||||||
|
td->create_handler<GetPaymentReceiptQuery>(std::move(promise))
|
||||||
|
->send(full_message_id.get_dialog_id(), server_message_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void get_saved_order_info(Promise<tl_object_ptr<td_api::orderInfo>> &&promise) {
|
void get_saved_order_info(Td *td, Promise<tl_object_ptr<td_api::orderInfo>> &&promise) {
|
||||||
G()->td().get_actor_unsafe()->create_handler<GetSavedInfoQuery>(std::move(promise))->send();
|
td->create_handler<GetSavedInfoQuery>(std::move(promise))->send();
|
||||||
}
|
}
|
||||||
|
|
||||||
void delete_saved_order_info(Promise<Unit> &&promise) {
|
void delete_saved_order_info(Td *td, Promise<Unit> &&promise) {
|
||||||
G()->td().get_actor_unsafe()->create_handler<ClearSavedInfoQuery>(std::move(promise))->send(false, true);
|
td->create_handler<ClearSavedInfoQuery>(std::move(promise))->send(false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void delete_saved_credentials(Promise<Unit> &&promise) {
|
void delete_saved_credentials(Td *td, Promise<Unit> &&promise) {
|
||||||
G()->td().get_actor_unsafe()->create_handler<ClearSavedInfoQuery>(std::move(promise))->send(true, false);
|
td->create_handler<ClearSavedInfoQuery>(std::move(promise))->send(true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void get_bank_card_info(const string &bank_card_number, Promise<td_api::object_ptr<td_api::bankCardInfo>> &&promise) {
|
void get_bank_card_info(Td *td, const string &bank_card_number,
|
||||||
G()->td().get_actor_unsafe()->create_handler<GetBankCardInfoQuery>(std::move(promise))->send(bank_card_number);
|
Promise<td_api::object_ptr<td_api::bankCardInfo>> &&promise) {
|
||||||
|
td->create_handler<GetBankCardInfoQuery>(std::move(promise))->send(bank_card_number);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace td
|
} // namespace td
|
||||||
|
@ -8,19 +8,23 @@
|
|||||||
|
|
||||||
#include "td/actor/PromiseFuture.h"
|
#include "td/actor/PromiseFuture.h"
|
||||||
|
|
||||||
|
#include "td/telegram/DialogId.h"
|
||||||
|
#include "td/telegram/files/FileId.h"
|
||||||
|
#include "td/telegram/FullMessageId.h"
|
||||||
|
#include "td/telegram/MessageId.h"
|
||||||
#include "td/telegram/Photo.h"
|
#include "td/telegram/Photo.h"
|
||||||
#include "td/telegram/ServerMessageId.h"
|
#include "td/telegram/td_api.h"
|
||||||
|
#include "td/telegram/telegram_api.h"
|
||||||
|
|
||||||
#include "td/utils/common.h"
|
#include "td/utils/common.h"
|
||||||
#include "td/utils/Slice.h"
|
#include "td/utils/Slice.h"
|
||||||
#include "td/utils/Status.h"
|
#include "td/utils/Status.h"
|
||||||
#include "td/utils/StringBuilder.h"
|
#include "td/utils/StringBuilder.h"
|
||||||
|
|
||||||
#include "td/telegram/td_api.h"
|
|
||||||
#include "td/telegram/telegram_api.h"
|
|
||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
|
|
||||||
|
class Td;
|
||||||
|
|
||||||
struct LabeledPricePart {
|
struct LabeledPricePart {
|
||||||
string label;
|
string label;
|
||||||
int64 amount = 0;
|
int64 amount = 0;
|
||||||
@ -33,6 +37,8 @@ struct LabeledPricePart {
|
|||||||
struct Invoice {
|
struct Invoice {
|
||||||
string currency;
|
string currency;
|
||||||
vector<LabeledPricePart> price_parts;
|
vector<LabeledPricePart> price_parts;
|
||||||
|
int64 max_tip_amount = 0;
|
||||||
|
vector<int64> suggested_tip_amounts;
|
||||||
bool is_test = false;
|
bool is_test = false;
|
||||||
bool need_name = false;
|
bool need_name = false;
|
||||||
bool need_phone_number = false;
|
bool need_phone_number = false;
|
||||||
@ -48,6 +54,20 @@ struct Invoice {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct InputInvoice {
|
||||||
|
string title;
|
||||||
|
string description;
|
||||||
|
Photo photo;
|
||||||
|
string start_parameter;
|
||||||
|
Invoice invoice;
|
||||||
|
string payload;
|
||||||
|
string provider_token;
|
||||||
|
string provider_data;
|
||||||
|
|
||||||
|
int64 total_amount = 0;
|
||||||
|
MessageId receipt_message_id;
|
||||||
|
};
|
||||||
|
|
||||||
struct Address {
|
struct Address {
|
||||||
string country_code;
|
string country_code;
|
||||||
string state;
|
string state;
|
||||||
@ -99,6 +119,27 @@ bool operator!=(const Invoice &lhs, const Invoice &rhs);
|
|||||||
|
|
||||||
StringBuilder &operator<<(StringBuilder &string_builder, const Invoice &invoice);
|
StringBuilder &operator<<(StringBuilder &string_builder, const Invoice &invoice);
|
||||||
|
|
||||||
|
bool operator==(const InputInvoice &lhs, const InputInvoice &rhs);
|
||||||
|
bool operator!=(const InputInvoice &lhs, const InputInvoice &rhs);
|
||||||
|
|
||||||
|
InputInvoice get_input_invoice(tl_object_ptr<telegram_api::messageMediaInvoice> &&message_invoice, Td *td,
|
||||||
|
DialogId owner_dialog_id);
|
||||||
|
|
||||||
|
InputInvoice get_input_invoice(tl_object_ptr<telegram_api::botInlineMessageMediaInvoice> &&message_invoice, Td *td,
|
||||||
|
DialogId owner_dialog_id);
|
||||||
|
|
||||||
|
Result<InputInvoice> process_input_message_invoice(
|
||||||
|
td_api::object_ptr<td_api::InputMessageContent> &&input_message_content, Td *td);
|
||||||
|
|
||||||
|
tl_object_ptr<td_api::messageInvoice> get_message_invoice_object(const InputInvoice &input_invoice, Td *td);
|
||||||
|
|
||||||
|
tl_object_ptr<telegram_api::inputMediaInvoice> get_input_media_invoice(const InputInvoice &input_invoice, Td *td);
|
||||||
|
|
||||||
|
tl_object_ptr<telegram_api::inputBotInlineMessageMediaInvoice> get_input_bot_inline_message_media_invoice(
|
||||||
|
const InputInvoice &input_invoice, tl_object_ptr<telegram_api::ReplyMarkup> &&reply_markup, Td *td);
|
||||||
|
|
||||||
|
vector<FileId> get_input_invoice_file_ids(const InputInvoice &input_invoice);
|
||||||
|
|
||||||
bool operator==(const Address &lhs, const Address &rhs);
|
bool operator==(const Address &lhs, const Address &rhs);
|
||||||
bool operator!=(const Address &lhs, const Address &rhs);
|
bool operator!=(const Address &lhs, const Address &rhs);
|
||||||
|
|
||||||
@ -132,28 +173,33 @@ bool operator!=(const ShippingOption &lhs, const ShippingOption &rhs);
|
|||||||
|
|
||||||
StringBuilder &operator<<(StringBuilder &string_builder, const ShippingOption &shipping_option);
|
StringBuilder &operator<<(StringBuilder &string_builder, const ShippingOption &shipping_option);
|
||||||
|
|
||||||
void answer_shipping_query(int64 shipping_query_id, vector<tl_object_ptr<td_api::shippingOption>> &&shipping_options,
|
void answer_shipping_query(Td *td, int64 shipping_query_id,
|
||||||
|
vector<tl_object_ptr<td_api::shippingOption>> &&shipping_options,
|
||||||
const string &error_message, Promise<Unit> &&promise);
|
const string &error_message, Promise<Unit> &&promise);
|
||||||
|
|
||||||
void answer_pre_checkout_query(int64 pre_checkout_query_id, const string &error_message, Promise<Unit> &&promise);
|
void answer_pre_checkout_query(Td *td, int64 pre_checkout_query_id, const string &error_message,
|
||||||
|
Promise<Unit> &&promise);
|
||||||
|
|
||||||
void get_payment_form(ServerMessageId server_message_id, Promise<tl_object_ptr<td_api::paymentForm>> &&promise);
|
void get_payment_form(Td *td, FullMessageId full_message_id, const td_api::object_ptr<td_api::paymentFormTheme> &theme,
|
||||||
|
Promise<tl_object_ptr<td_api::paymentForm>> &&promise);
|
||||||
|
|
||||||
void validate_order_info(ServerMessageId server_message_id, tl_object_ptr<td_api::orderInfo> order_info,
|
void validate_order_info(Td *td, FullMessageId full_message_id, tl_object_ptr<td_api::orderInfo> order_info,
|
||||||
bool allow_save, Promise<tl_object_ptr<td_api::validatedOrderInfo>> &&promise);
|
bool allow_save, Promise<tl_object_ptr<td_api::validatedOrderInfo>> &&promise);
|
||||||
|
|
||||||
void send_payment_form(ServerMessageId server_message_id, const string &order_info_id, const string &shipping_option_id,
|
void send_payment_form(Td *td, FullMessageId full_message_id, int64 payment_form_id, const string &order_info_id,
|
||||||
const tl_object_ptr<td_api::InputCredentials> &credentials,
|
const string &shipping_option_id, const tl_object_ptr<td_api::InputCredentials> &credentials,
|
||||||
Promise<tl_object_ptr<td_api::paymentResult>> &&promise);
|
int64 tip_amount, Promise<tl_object_ptr<td_api::paymentResult>> &&promise);
|
||||||
|
|
||||||
void get_payment_receipt(ServerMessageId server_message_id, Promise<tl_object_ptr<td_api::paymentReceipt>> &&promise);
|
void get_payment_receipt(Td *td, FullMessageId full_message_id,
|
||||||
|
Promise<tl_object_ptr<td_api::paymentReceipt>> &&promise);
|
||||||
|
|
||||||
void get_saved_order_info(Promise<tl_object_ptr<td_api::orderInfo>> &&promise);
|
void get_saved_order_info(Td *td, Promise<tl_object_ptr<td_api::orderInfo>> &&promise);
|
||||||
|
|
||||||
void delete_saved_order_info(Promise<Unit> &&promise);
|
void delete_saved_order_info(Td *td, Promise<Unit> &&promise);
|
||||||
|
|
||||||
void delete_saved_credentials(Promise<Unit> &&promise);
|
void delete_saved_credentials(Td *td, Promise<Unit> &&promise);
|
||||||
|
|
||||||
void get_bank_card_info(const string &bank_card_number, Promise<td_api::object_ptr<td_api::bankCardInfo>> &&promise);
|
void get_bank_card_info(Td *td, const string &bank_card_number,
|
||||||
|
Promise<td_api::object_ptr<td_api::bankCardInfo>> &&promise);
|
||||||
|
|
||||||
} // namespace td
|
} // namespace td
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "td/telegram/Payments.h"
|
#include "td/telegram/Payments.h"
|
||||||
|
|
||||||
#include "td/telegram/Photo.hpp"
|
#include "td/telegram/Photo.hpp"
|
||||||
|
#include "td/telegram/Version.h"
|
||||||
|
|
||||||
#include "td/utils/tl_helpers.h"
|
#include "td/utils/tl_helpers.h"
|
||||||
|
|
||||||
@ -28,6 +29,7 @@ void parse(LabeledPricePart &labeled_price_part, ParserT &parser) {
|
|||||||
|
|
||||||
template <class StorerT>
|
template <class StorerT>
|
||||||
void store(const Invoice &invoice, StorerT &storer) {
|
void store(const Invoice &invoice, StorerT &storer) {
|
||||||
|
bool has_tip = invoice.max_tip_amount != 0;
|
||||||
BEGIN_STORE_FLAGS();
|
BEGIN_STORE_FLAGS();
|
||||||
STORE_FLAG(invoice.is_test);
|
STORE_FLAG(invoice.is_test);
|
||||||
STORE_FLAG(invoice.need_name);
|
STORE_FLAG(invoice.need_name);
|
||||||
@ -37,13 +39,19 @@ void store(const Invoice &invoice, StorerT &storer) {
|
|||||||
STORE_FLAG(invoice.is_flexible);
|
STORE_FLAG(invoice.is_flexible);
|
||||||
STORE_FLAG(invoice.send_phone_number_to_provider);
|
STORE_FLAG(invoice.send_phone_number_to_provider);
|
||||||
STORE_FLAG(invoice.send_email_address_to_provider);
|
STORE_FLAG(invoice.send_email_address_to_provider);
|
||||||
|
STORE_FLAG(has_tip);
|
||||||
END_STORE_FLAGS();
|
END_STORE_FLAGS();
|
||||||
store(invoice.currency, storer);
|
store(invoice.currency, storer);
|
||||||
store(invoice.price_parts, storer);
|
store(invoice.price_parts, storer);
|
||||||
|
if (has_tip) {
|
||||||
|
store(invoice.max_tip_amount, storer);
|
||||||
|
store(invoice.suggested_tip_amounts, storer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ParserT>
|
template <class ParserT>
|
||||||
void parse(Invoice &invoice, ParserT &parser) {
|
void parse(Invoice &invoice, ParserT &parser) {
|
||||||
|
bool has_tip;
|
||||||
BEGIN_PARSE_FLAGS();
|
BEGIN_PARSE_FLAGS();
|
||||||
PARSE_FLAG(invoice.is_test);
|
PARSE_FLAG(invoice.is_test);
|
||||||
PARSE_FLAG(invoice.need_name);
|
PARSE_FLAG(invoice.need_name);
|
||||||
@ -53,9 +61,46 @@ void parse(Invoice &invoice, ParserT &parser) {
|
|||||||
PARSE_FLAG(invoice.is_flexible);
|
PARSE_FLAG(invoice.is_flexible);
|
||||||
PARSE_FLAG(invoice.send_phone_number_to_provider);
|
PARSE_FLAG(invoice.send_phone_number_to_provider);
|
||||||
PARSE_FLAG(invoice.send_email_address_to_provider);
|
PARSE_FLAG(invoice.send_email_address_to_provider);
|
||||||
|
PARSE_FLAG(has_tip);
|
||||||
END_PARSE_FLAGS();
|
END_PARSE_FLAGS();
|
||||||
parse(invoice.currency, parser);
|
parse(invoice.currency, parser);
|
||||||
parse(invoice.price_parts, parser);
|
parse(invoice.price_parts, parser);
|
||||||
|
if (has_tip) {
|
||||||
|
parse(invoice.max_tip_amount, parser);
|
||||||
|
parse(invoice.suggested_tip_amounts, parser);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class StorerT>
|
||||||
|
void store(const InputInvoice &input_invoice, StorerT &storer) {
|
||||||
|
store(input_invoice.title, storer);
|
||||||
|
store(input_invoice.description, storer);
|
||||||
|
store(input_invoice.photo, storer);
|
||||||
|
store(input_invoice.start_parameter, storer);
|
||||||
|
store(input_invoice.invoice, storer);
|
||||||
|
store(input_invoice.payload, storer);
|
||||||
|
store(input_invoice.provider_token, storer);
|
||||||
|
store(input_invoice.provider_data, storer);
|
||||||
|
store(input_invoice.total_amount, storer);
|
||||||
|
store(input_invoice.receipt_message_id, storer);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class ParserT>
|
||||||
|
void parse(InputInvoice &input_invoice, ParserT &parser) {
|
||||||
|
parse(input_invoice.title, parser);
|
||||||
|
parse(input_invoice.description, parser);
|
||||||
|
parse(input_invoice.photo, parser);
|
||||||
|
parse(input_invoice.start_parameter, parser);
|
||||||
|
parse(input_invoice.invoice, parser);
|
||||||
|
parse(input_invoice.payload, parser);
|
||||||
|
parse(input_invoice.provider_token, parser);
|
||||||
|
if (parser.version() >= static_cast<int32>(Version::AddMessageInvoiceProviderData)) {
|
||||||
|
parse(input_invoice.provider_data, parser);
|
||||||
|
} else {
|
||||||
|
input_invoice.provider_data.clear();
|
||||||
|
}
|
||||||
|
parse(input_invoice.total_amount, parser);
|
||||||
|
parse(input_invoice.receipt_message_id, parser);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class StorerT>
|
template <class StorerT>
|
||||||
|
@ -169,6 +169,7 @@ ProfilePhoto get_profile_photo(FileManager *file_manager, UserId user_id, int64
|
|||||||
auto dc_id = DcId::create(profile_photo->dc_id_);
|
auto dc_id = DcId::create(profile_photo->dc_id_);
|
||||||
result.has_animation = (profile_photo->flags_ & telegram_api::userProfilePhoto::HAS_VIDEO_MASK) != 0;
|
result.has_animation = (profile_photo->flags_ & telegram_api::userProfilePhoto::HAS_VIDEO_MASK) != 0;
|
||||||
result.id = profile_photo->photo_id_;
|
result.id = profile_photo->photo_id_;
|
||||||
|
result.minithumbnail = profile_photo->stripped_thumb_.as_slice().str();
|
||||||
result.small_file_id =
|
result.small_file_id =
|
||||||
register_photo(file_manager, {DialogId(user_id), user_access_hash, false}, result.id, 0, "",
|
register_photo(file_manager, {DialogId(user_id), user_access_hash, false}, result.id, 0, "",
|
||||||
std::move(profile_photo->photo_small_), DialogId(), 0, dc_id, PhotoFormat::Jpeg);
|
std::move(profile_photo->photo_small_), DialogId(), 0, dc_id, PhotoFormat::Jpeg);
|
||||||
@ -192,7 +193,8 @@ tl_object_ptr<td_api::profilePhoto> get_profile_photo_object(FileManager *file_m
|
|||||||
}
|
}
|
||||||
return td_api::make_object<td_api::profilePhoto>(
|
return td_api::make_object<td_api::profilePhoto>(
|
||||||
profile_photo.id, file_manager->get_file_object(profile_photo.small_file_id),
|
profile_photo.id, file_manager->get_file_object(profile_photo.small_file_id),
|
||||||
file_manager->get_file_object(profile_photo.big_file_id), profile_photo.has_animation);
|
file_manager->get_file_object(profile_photo.big_file_id), get_minithumbnail_object(profile_photo.minithumbnail),
|
||||||
|
profile_photo.has_animation);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const ProfilePhoto &lhs, const ProfilePhoto &rhs) {
|
bool operator==(const ProfilePhoto &lhs, const ProfilePhoto &rhs) {
|
||||||
@ -210,7 +212,7 @@ bool operator==(const ProfilePhoto &lhs, const ProfilePhoto &rhs) {
|
|||||||
<< ", second profilePhoto: " << rhs;
|
<< ", second profilePhoto: " << rhs;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return lhs.has_animation == rhs.has_animation && !id_differs;
|
return lhs.has_animation == rhs.has_animation && lhs.minithumbnail == rhs.minithumbnail && !id_differs;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const ProfilePhoto &lhs, const ProfilePhoto &rhs) {
|
bool operator!=(const ProfilePhoto &lhs, const ProfilePhoto &rhs) {
|
||||||
@ -218,7 +220,7 @@ bool operator!=(const ProfilePhoto &lhs, const ProfilePhoto &rhs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder &operator<<(StringBuilder &string_builder, const ProfilePhoto &profile_photo) {
|
StringBuilder &operator<<(StringBuilder &string_builder, const ProfilePhoto &profile_photo) {
|
||||||
return string_builder << "<id = " << profile_photo.id << ", small_file_id = " << profile_photo.small_file_id
|
return string_builder << "<ID = " << profile_photo.id << ", small_file_id = " << profile_photo.small_file_id
|
||||||
<< ", big_file_id = " << profile_photo.big_file_id
|
<< ", big_file_id = " << profile_photo.big_file_id
|
||||||
<< ", has_animation = " << profile_photo.has_animation << ">";
|
<< ", has_animation = " << profile_photo.has_animation << ">";
|
||||||
}
|
}
|
||||||
@ -236,6 +238,7 @@ DialogPhoto get_dialog_photo(FileManager *file_manager, DialogId dialog_id, int6
|
|||||||
|
|
||||||
auto dc_id = DcId::create(chat_photo->dc_id_);
|
auto dc_id = DcId::create(chat_photo->dc_id_);
|
||||||
result.has_animation = (chat_photo->flags_ & telegram_api::chatPhoto::HAS_VIDEO_MASK) != 0;
|
result.has_animation = (chat_photo->flags_ & telegram_api::chatPhoto::HAS_VIDEO_MASK) != 0;
|
||||||
|
result.minithumbnail = chat_photo->stripped_thumb_.as_slice().str();
|
||||||
result.small_file_id =
|
result.small_file_id =
|
||||||
register_photo(file_manager, {dialog_id, dialog_access_hash, false}, 0, 0, "",
|
register_photo(file_manager, {dialog_id, dialog_access_hash, false}, 0, 0, "",
|
||||||
std::move(chat_photo->photo_small_), DialogId(), 0, dc_id, PhotoFormat::Jpeg);
|
std::move(chat_photo->photo_small_), DialogId(), 0, dc_id, PhotoFormat::Jpeg);
|
||||||
@ -259,6 +262,7 @@ tl_object_ptr<td_api::chatPhotoInfo> get_chat_photo_info_object(FileManager *fil
|
|||||||
}
|
}
|
||||||
return td_api::make_object<td_api::chatPhotoInfo>(file_manager->get_file_object(dialog_photo->small_file_id),
|
return td_api::make_object<td_api::chatPhotoInfo>(file_manager->get_file_object(dialog_photo->small_file_id),
|
||||||
file_manager->get_file_object(dialog_photo->big_file_id),
|
file_manager->get_file_object(dialog_photo->big_file_id),
|
||||||
|
get_minithumbnail_object(dialog_photo->minithumbnail),
|
||||||
dialog_photo->has_animation);
|
dialog_photo->has_animation);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,7 +323,7 @@ ProfilePhoto as_profile_photo(FileManager *file_manager, UserId user_id, int64 u
|
|||||||
|
|
||||||
bool operator==(const DialogPhoto &lhs, const DialogPhoto &rhs) {
|
bool operator==(const DialogPhoto &lhs, const DialogPhoto &rhs) {
|
||||||
return lhs.small_file_id == rhs.small_file_id && lhs.big_file_id == rhs.big_file_id &&
|
return lhs.small_file_id == rhs.small_file_id && lhs.big_file_id == rhs.big_file_id &&
|
||||||
lhs.has_animation == rhs.has_animation;
|
lhs.minithumbnail == rhs.minithumbnail && lhs.has_animation == rhs.has_animation;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const DialogPhoto &lhs, const DialogPhoto &rhs) {
|
bool operator!=(const DialogPhoto &lhs, const DialogPhoto &rhs) {
|
||||||
@ -401,10 +405,18 @@ Variant<PhotoSize, string> get_photo_size(FileManager *file_manager, PhotoSizeSo
|
|||||||
} else {
|
} else {
|
||||||
LOG(ERROR) << "Receive unexpected JPEG minithumbnail in photo of format " << format;
|
LOG(ERROR) << "Receive unexpected JPEG minithumbnail in photo of format " << format;
|
||||||
}
|
}
|
||||||
|
if (G()->shared_config().get_option_boolean("disable_minithumbnails")) {
|
||||||
|
return std::string("");
|
||||||
|
} else {
|
||||||
return std::move(res);
|
return std::move(res);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (G()->shared_config().get_option_boolean("disable_minithumbnails")) {
|
||||||
|
return std::string("");
|
||||||
|
} else {
|
||||||
return size->bytes_.as_slice().str();
|
return size->bytes_.as_slice().str();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
case telegram_api::photoSizeProgressive::ID: {
|
case telegram_api::photoSizeProgressive::ID: {
|
||||||
auto size = move_tl_object_as<telegram_api::photoSizeProgressive>(size_ptr);
|
auto size = move_tl_object_as<telegram_api::photoSizeProgressive>(size_ptr);
|
||||||
|
|
||||||
@ -717,7 +729,7 @@ Photo get_photo(FileManager *file_manager, tl_object_ptr<telegram_api::photo> &&
|
|||||||
res.has_stickers = (photo->flags_ & telegram_api::photo::HAS_STICKERS_MASK) != 0;
|
res.has_stickers = (photo->flags_ & telegram_api::photo::HAS_STICKERS_MASK) != 0;
|
||||||
|
|
||||||
if (res.is_empty()) {
|
if (res.is_empty()) {
|
||||||
LOG(ERROR) << "Receive photo with id " << res.id.get();
|
LOG(ERROR) << "Receive photo with identifier " << res.id.get();
|
||||||
res.id = -3;
|
res.id = -3;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -733,10 +745,14 @@ Photo get_photo(FileManager *file_manager, tl_object_ptr<telegram_api::photo> &&
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
res.photos.push_back(std::move(size));
|
res.photos.push_back(std::move(size));
|
||||||
|
} else {
|
||||||
|
if (G()->shared_config().get_option_boolean("disable_minithumbnails")) {
|
||||||
|
res.minithumbnail = "";
|
||||||
} else {
|
} else {
|
||||||
res.minithumbnail = std::move(photo_size.get<1>());
|
res.minithumbnail = std::move(photo_size.get<1>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (auto &size_ptr : photo->video_sizes_) {
|
for (auto &size_ptr : photo->video_sizes_) {
|
||||||
auto animation =
|
auto animation =
|
||||||
@ -933,11 +949,11 @@ bool operator!=(const Photo &lhs, const Photo &rhs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder &operator<<(StringBuilder &string_builder, const Photo &photo) {
|
StringBuilder &operator<<(StringBuilder &string_builder, const Photo &photo) {
|
||||||
string_builder << "[id = " << photo.id.get() << ", photos = " << format::as_array(photo.photos);
|
string_builder << "[ID = " << photo.id.get() << ", photos = " << format::as_array(photo.photos);
|
||||||
if (!photo.animations.empty()) {
|
if (!photo.animations.empty()) {
|
||||||
string_builder << ", animations = " << format::as_array(photo.animations);
|
string_builder << ", animations = " << format::as_array(photo.animations);
|
||||||
}
|
}
|
||||||
return string_builder << "]";
|
return string_builder << ']';
|
||||||
}
|
}
|
||||||
|
|
||||||
static tl_object_ptr<telegram_api::fileLocationToBeDeprecated> copy_location(
|
static tl_object_ptr<telegram_api::fileLocationToBeDeprecated> copy_location(
|
||||||
@ -1000,7 +1016,7 @@ tl_object_ptr<telegram_api::userProfilePhoto> convert_photo_to_profile_photo(
|
|||||||
flags |= telegram_api::userProfilePhoto::HAS_VIDEO_MASK;
|
flags |= telegram_api::userProfilePhoto::HAS_VIDEO_MASK;
|
||||||
}
|
}
|
||||||
return make_tl_object<telegram_api::userProfilePhoto>(flags, false /*ignored*/, photo->id_, std::move(photo_small),
|
return make_tl_object<telegram_api::userProfilePhoto>(flags, false /*ignored*/, photo->id_, std::move(photo_small),
|
||||||
std::move(photo_big), photo->dc_id_);
|
std::move(photo_big), BufferSlice(), photo->dc_id_);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace td
|
} // namespace td
|
||||||
|
@ -36,6 +36,7 @@ struct Dimensions {
|
|||||||
struct DialogPhoto {
|
struct DialogPhoto {
|
||||||
FileId small_file_id;
|
FileId small_file_id;
|
||||||
FileId big_file_id;
|
FileId big_file_id;
|
||||||
|
string minithumbnail;
|
||||||
bool has_animation = false;
|
bool has_animation = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -31,29 +31,39 @@ void parse(Dimensions &dimensions, ParserT &parser) {
|
|||||||
template <class StorerT>
|
template <class StorerT>
|
||||||
void store(const DialogPhoto &dialog_photo, StorerT &storer) {
|
void store(const DialogPhoto &dialog_photo, StorerT &storer) {
|
||||||
bool has_file_ids = dialog_photo.small_file_id.is_valid() || dialog_photo.big_file_id.is_valid();
|
bool has_file_ids = dialog_photo.small_file_id.is_valid() || dialog_photo.big_file_id.is_valid();
|
||||||
|
bool has_minithumbnail = !dialog_photo.minithumbnail.empty();
|
||||||
BEGIN_STORE_FLAGS();
|
BEGIN_STORE_FLAGS();
|
||||||
STORE_FLAG(has_file_ids);
|
STORE_FLAG(has_file_ids);
|
||||||
STORE_FLAG(dialog_photo.has_animation);
|
STORE_FLAG(dialog_photo.has_animation);
|
||||||
|
STORE_FLAG(has_minithumbnail);
|
||||||
END_STORE_FLAGS();
|
END_STORE_FLAGS();
|
||||||
if (has_file_ids) {
|
if (has_file_ids) {
|
||||||
store(dialog_photo.small_file_id, storer);
|
store(dialog_photo.small_file_id, storer);
|
||||||
store(dialog_photo.big_file_id, storer);
|
store(dialog_photo.big_file_id, storer);
|
||||||
}
|
}
|
||||||
|
if (has_minithumbnail) {
|
||||||
|
store(dialog_photo.minithumbnail, storer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ParserT>
|
template <class ParserT>
|
||||||
void parse(DialogPhoto &dialog_photo, ParserT &parser) {
|
void parse(DialogPhoto &dialog_photo, ParserT &parser) {
|
||||||
bool has_file_ids = true;
|
bool has_file_ids = true;
|
||||||
|
bool has_minithumbnail = false;
|
||||||
if (parser.version() >= static_cast<int32>(Version::AddDialogPhotoHasAnimation)) {
|
if (parser.version() >= static_cast<int32>(Version::AddDialogPhotoHasAnimation)) {
|
||||||
BEGIN_PARSE_FLAGS();
|
BEGIN_PARSE_FLAGS();
|
||||||
PARSE_FLAG(has_file_ids);
|
PARSE_FLAG(has_file_ids);
|
||||||
PARSE_FLAG(dialog_photo.has_animation);
|
PARSE_FLAG(dialog_photo.has_animation);
|
||||||
|
PARSE_FLAG(has_minithumbnail);
|
||||||
END_PARSE_FLAGS();
|
END_PARSE_FLAGS();
|
||||||
}
|
}
|
||||||
if (has_file_ids) {
|
if (has_file_ids) {
|
||||||
parse(dialog_photo.small_file_id, parser);
|
parse(dialog_photo.small_file_id, parser);
|
||||||
parse(dialog_photo.big_file_id, parser);
|
parse(dialog_photo.big_file_id, parser);
|
||||||
}
|
}
|
||||||
|
if (has_minithumbnail) {
|
||||||
|
parse(dialog_photo.minithumbnail, parser);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class StorerT>
|
template <class StorerT>
|
||||||
|
@ -54,26 +54,35 @@ FileType PhotoSizeSource::get_file_type() const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool operator==(const PhotoSizeSource::Legacy &lhs, const PhotoSizeSource::Legacy &rhs) {
|
||||||
|
return lhs.secret == rhs.secret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool operator==(const PhotoSizeSource::Thumbnail &lhs, const PhotoSizeSource::Thumbnail &rhs) {
|
||||||
|
return lhs.file_type == rhs.file_type && lhs.thumbnail_type == rhs.thumbnail_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool operator==(const PhotoSizeSource::DialogPhoto &lhs, const PhotoSizeSource::DialogPhoto &rhs) {
|
||||||
|
return lhs.dialog_id == rhs.dialog_id && lhs.dialog_access_hash == rhs.dialog_access_hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool operator==(const PhotoSizeSource::DialogPhotoSmall &lhs, const PhotoSizeSource::DialogPhotoSmall &rhs) {
|
||||||
|
return static_cast<const PhotoSizeSource::DialogPhoto &>(lhs) ==
|
||||||
|
static_cast<const PhotoSizeSource::DialogPhoto &>(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool operator==(const PhotoSizeSource::DialogPhotoBig &lhs, const PhotoSizeSource::DialogPhotoBig &rhs) {
|
||||||
|
return static_cast<const PhotoSizeSource::DialogPhoto &>(lhs) ==
|
||||||
|
static_cast<const PhotoSizeSource::DialogPhoto &>(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool operator==(const PhotoSizeSource::StickerSetThumbnail &lhs,
|
||||||
|
const PhotoSizeSource::StickerSetThumbnail &rhs) {
|
||||||
|
return lhs.sticker_set_id == rhs.sticker_set_id && lhs.sticker_set_access_hash == rhs.sticker_set_access_hash;
|
||||||
|
}
|
||||||
|
|
||||||
bool operator==(const PhotoSizeSource &lhs, const PhotoSizeSource &rhs) {
|
bool operator==(const PhotoSizeSource &lhs, const PhotoSizeSource &rhs) {
|
||||||
if (lhs.get_type() != rhs.get_type()) {
|
return lhs.variant == rhs.variant;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
switch (lhs.get_type()) {
|
|
||||||
case PhotoSizeSource::Type::Thumbnail:
|
|
||||||
return lhs.thumbnail().file_type == rhs.thumbnail().file_type &&
|
|
||||||
lhs.thumbnail().thumbnail_type == rhs.thumbnail().thumbnail_type;
|
|
||||||
case PhotoSizeSource::Type::DialogPhotoSmall:
|
|
||||||
case PhotoSizeSource::Type::DialogPhotoBig:
|
|
||||||
return lhs.dialog_photo().dialog_id == rhs.dialog_photo().dialog_id &&
|
|
||||||
lhs.dialog_photo().dialog_access_hash == rhs.dialog_photo().dialog_access_hash;
|
|
||||||
case PhotoSizeSource::Type::StickerSetThumbnail:
|
|
||||||
return lhs.sticker_set_thumbnail().sticker_set_id == rhs.sticker_set_thumbnail().sticker_set_id &&
|
|
||||||
lhs.sticker_set_thumbnail().sticker_set_access_hash == rhs.sticker_set_thumbnail().sticker_set_access_hash;
|
|
||||||
case PhotoSizeSource::Type::Legacy:
|
|
||||||
return lhs.legacy().secret == rhs.legacy().secret;
|
|
||||||
default:
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const PhotoSizeSource &lhs, const PhotoSizeSource &rhs) {
|
bool operator!=(const PhotoSizeSource &lhs, const PhotoSizeSource &rhs) {
|
||||||
|
@ -125,6 +125,8 @@ struct PhotoSizeSource {
|
|||||||
template <class ParserT>
|
template <class ParserT>
|
||||||
void parse(ParserT &parser);
|
void parse(ParserT &parser);
|
||||||
|
|
||||||
|
friend bool operator==(const PhotoSizeSource &lhs, const PhotoSizeSource &rhs);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Variant<Legacy, Thumbnail, DialogPhotoSmall, DialogPhotoBig, StickerSetThumbnail> variant;
|
Variant<Legacy, Thumbnail, DialogPhotoSmall, DialogPhotoBig, StickerSetThumbnail> variant;
|
||||||
};
|
};
|
||||||
|
@ -1177,8 +1177,12 @@ void PollManager::on_update_poll_timeout(PollId poll_id) {
|
|||||||
if (G()->close_flag()) {
|
if (G()->close_flag()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto poll = get_poll(poll_id);
|
auto poll = get_poll(poll_id);
|
||||||
if (!(poll != nullptr)) return;
|
if (poll == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (poll->is_closed && poll->is_updated_after_close) {
|
if (poll->is_closed && poll->is_updated_after_close) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1192,7 +1196,13 @@ void PollManager::on_update_poll_timeout(PollId poll_id) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto full_message_id = *it->second.begin();
|
auto full_message_id_set = std::move(it->second);
|
||||||
|
if (full_message_id_set.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto full_message_id = *full_message_id_set.begin();
|
||||||
|
|
||||||
LOG(INFO) << "Fetching results of " << poll_id << " from " << full_message_id;
|
LOG(INFO) << "Fetching results of " << poll_id << " from " << full_message_id;
|
||||||
auto query_promise = PromiseCreator::lambda([poll_id, generation = current_generation_, actor_id = actor_id(this)](
|
auto query_promise = PromiseCreator::lambda([poll_id, generation = current_generation_, actor_id = actor_id(this)](
|
||||||
Result<tl_object_ptr<telegram_api::Updates>> &&result) {
|
Result<tl_object_ptr<telegram_api::Updates>> &&result) {
|
||||||
|
@ -151,7 +151,7 @@ void PrivacyManager::UserPrivacySettingRule::set_chat_ids(const vector<int64> &d
|
|||||||
auto td = G()->td().get_actor_unsafe();
|
auto td = G()->td().get_actor_unsafe();
|
||||||
for (auto dialog_id_int : dialog_ids) {
|
for (auto dialog_id_int : dialog_ids) {
|
||||||
DialogId dialog_id(dialog_id_int);
|
DialogId dialog_id(dialog_id_int);
|
||||||
if (!td->messages_manager_->have_dialog_force(dialog_id)) {
|
if (!td->messages_manager_->have_dialog_force(dialog_id, "UserPrivacySettingRule::set_chat_ids")) {
|
||||||
LOG(ERROR) << "Ignore not found " << dialog_id;
|
LOG(ERROR) << "Ignore not found " << dialog_id;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -185,7 +185,7 @@ PrivacyManager::UserPrivacySettingRule::UserPrivacySettingRule(const td_api::Use
|
|||||||
break;
|
break;
|
||||||
case td_api::userPrivacySettingRuleAllowUsers::ID:
|
case td_api::userPrivacySettingRuleAllowUsers::ID:
|
||||||
type_ = Type::AllowUsers;
|
type_ = Type::AllowUsers;
|
||||||
user_ids_ = static_cast<const td_api::userPrivacySettingRuleAllowUsers &>(rule).user_ids_;
|
user_ids_ = UserId::get_user_ids(static_cast<const td_api::userPrivacySettingRuleAllowUsers &>(rule).user_ids_);
|
||||||
break;
|
break;
|
||||||
case td_api::userPrivacySettingRuleAllowChatMembers::ID:
|
case td_api::userPrivacySettingRuleAllowChatMembers::ID:
|
||||||
type_ = Type::AllowChatParticipants;
|
type_ = Type::AllowChatParticipants;
|
||||||
@ -199,7 +199,8 @@ PrivacyManager::UserPrivacySettingRule::UserPrivacySettingRule(const td_api::Use
|
|||||||
break;
|
break;
|
||||||
case td_api::userPrivacySettingRuleRestrictUsers::ID:
|
case td_api::userPrivacySettingRuleRestrictUsers::ID:
|
||||||
type_ = Type::RestrictUsers;
|
type_ = Type::RestrictUsers;
|
||||||
user_ids_ = static_cast<const td_api::userPrivacySettingRuleRestrictUsers &>(rule).user_ids_;
|
user_ids_ =
|
||||||
|
UserId::get_user_ids(static_cast<const td_api::userPrivacySettingRuleRestrictUsers &>(rule).user_ids_);
|
||||||
break;
|
break;
|
||||||
case td_api::userPrivacySettingRuleRestrictChatMembers::ID:
|
case td_api::userPrivacySettingRuleRestrictChatMembers::ID:
|
||||||
type_ = Type::RestrictChatParticipants;
|
type_ = Type::RestrictChatParticipants;
|
||||||
@ -220,7 +221,7 @@ PrivacyManager::UserPrivacySettingRule::UserPrivacySettingRule(const telegram_ap
|
|||||||
break;
|
break;
|
||||||
case telegram_api::privacyValueAllowUsers::ID:
|
case telegram_api::privacyValueAllowUsers::ID:
|
||||||
type_ = Type::AllowUsers;
|
type_ = Type::AllowUsers;
|
||||||
user_ids_ = static_cast<const telegram_api::privacyValueAllowUsers &>(rule).users_;
|
user_ids_ = UserId::get_user_ids(static_cast<const telegram_api::privacyValueAllowUsers &>(rule).users_);
|
||||||
break;
|
break;
|
||||||
case telegram_api::privacyValueAllowChatParticipants::ID:
|
case telegram_api::privacyValueAllowChatParticipants::ID:
|
||||||
type_ = Type::AllowChatParticipants;
|
type_ = Type::AllowChatParticipants;
|
||||||
@ -234,7 +235,7 @@ PrivacyManager::UserPrivacySettingRule::UserPrivacySettingRule(const telegram_ap
|
|||||||
break;
|
break;
|
||||||
case telegram_api::privacyValueDisallowUsers::ID:
|
case telegram_api::privacyValueDisallowUsers::ID:
|
||||||
type_ = Type::RestrictUsers;
|
type_ = Type::RestrictUsers;
|
||||||
user_ids_ = static_cast<const telegram_api::privacyValueDisallowUsers &>(rule).users_;
|
user_ids_ = UserId::get_user_ids(static_cast<const telegram_api::privacyValueDisallowUsers &>(rule).users_);
|
||||||
break;
|
break;
|
||||||
case telegram_api::privacyValueDisallowChatParticipants::ID:
|
case telegram_api::privacyValueDisallowChatParticipants::ID:
|
||||||
type_ = Type::RestrictChatParticipants;
|
type_ = Type::RestrictChatParticipants;
|
||||||
@ -253,7 +254,7 @@ PrivacyManager::UserPrivacySettingRule::get_user_privacy_setting_rule_object() c
|
|||||||
case Type::AllowAll:
|
case Type::AllowAll:
|
||||||
return make_tl_object<td_api::userPrivacySettingRuleAllowAll>();
|
return make_tl_object<td_api::userPrivacySettingRuleAllowAll>();
|
||||||
case Type::AllowUsers:
|
case Type::AllowUsers:
|
||||||
return make_tl_object<td_api::userPrivacySettingRuleAllowUsers>(vector<int32>{user_ids_});
|
return make_tl_object<td_api::userPrivacySettingRuleAllowUsers>(UserId::get_input_user_ids(user_ids_));
|
||||||
case Type::AllowChatParticipants:
|
case Type::AllowChatParticipants:
|
||||||
return make_tl_object<td_api::userPrivacySettingRuleAllowChatMembers>(chat_ids_as_dialog_ids());
|
return make_tl_object<td_api::userPrivacySettingRuleAllowChatMembers>(chat_ids_as_dialog_ids());
|
||||||
case Type::RestrictContacts:
|
case Type::RestrictContacts:
|
||||||
@ -261,7 +262,7 @@ PrivacyManager::UserPrivacySettingRule::get_user_privacy_setting_rule_object() c
|
|||||||
case Type::RestrictAll:
|
case Type::RestrictAll:
|
||||||
return make_tl_object<td_api::userPrivacySettingRuleRestrictAll>();
|
return make_tl_object<td_api::userPrivacySettingRuleRestrictAll>();
|
||||||
case Type::RestrictUsers:
|
case Type::RestrictUsers:
|
||||||
return make_tl_object<td_api::userPrivacySettingRuleRestrictUsers>(vector<int32>{user_ids_});
|
return make_tl_object<td_api::userPrivacySettingRuleRestrictUsers>(UserId::get_input_user_ids(user_ids_));
|
||||||
case Type::RestrictChatParticipants:
|
case Type::RestrictChatParticipants:
|
||||||
return make_tl_object<td_api::userPrivacySettingRuleRestrictChatMembers>(chat_ids_as_dialog_ids());
|
return make_tl_object<td_api::userPrivacySettingRuleRestrictChatMembers>(chat_ids_as_dialog_ids());
|
||||||
default:
|
default:
|
||||||
@ -298,7 +299,7 @@ Result<PrivacyManager::UserPrivacySettingRule> PrivacyManager::UserPrivacySettin
|
|||||||
UserPrivacySettingRule result(*rule);
|
UserPrivacySettingRule result(*rule);
|
||||||
auto td = G()->td().get_actor_unsafe();
|
auto td = G()->td().get_actor_unsafe();
|
||||||
for (auto user_id : result.user_ids_) {
|
for (auto user_id : result.user_ids_) {
|
||||||
if (!td->contacts_manager_->have_user(UserId(user_id))) {
|
if (!td->contacts_manager_->have_user(user_id)) {
|
||||||
return Status::Error(500, "Got inaccessible user from the server");
|
return Status::Error(500, "Got inaccessible user from the server");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -320,7 +321,7 @@ Result<PrivacyManager::UserPrivacySettingRule> PrivacyManager::UserPrivacySettin
|
|||||||
vector<tl_object_ptr<telegram_api::InputUser>> PrivacyManager::UserPrivacySettingRule::get_input_users() const {
|
vector<tl_object_ptr<telegram_api::InputUser>> PrivacyManager::UserPrivacySettingRule::get_input_users() const {
|
||||||
vector<tl_object_ptr<telegram_api::InputUser>> result;
|
vector<tl_object_ptr<telegram_api::InputUser>> result;
|
||||||
for (auto user_id : user_ids_) {
|
for (auto user_id : user_ids_) {
|
||||||
auto input_user = G()->td().get_actor_unsafe()->contacts_manager_->get_input_user(UserId(user_id));
|
auto input_user = G()->td().get_actor_unsafe()->contacts_manager_->get_input_user(user_id);
|
||||||
if (input_user != nullptr) {
|
if (input_user != nullptr) {
|
||||||
result.push_back(std::move(input_user));
|
result.push_back(std::move(input_user));
|
||||||
} else {
|
} else {
|
||||||
@ -347,7 +348,7 @@ vector<int64> PrivacyManager::UserPrivacySettingRule::chat_ids_as_dialog_ids() c
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<int32> PrivacyManager::UserPrivacySettingRule::get_restricted_user_ids() const {
|
vector<UserId> PrivacyManager::UserPrivacySettingRule::get_restricted_user_ids() const {
|
||||||
if (type_ == Type::RestrictUsers) {
|
if (type_ == Type::RestrictUsers) {
|
||||||
return user_ids_;
|
return user_ids_;
|
||||||
}
|
}
|
||||||
@ -405,12 +406,13 @@ vector<tl_object_ptr<telegram_api::InputPrivacyRule>> PrivacyManager::UserPrivac
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<int32> PrivacyManager::UserPrivacySettingRules::get_restricted_user_ids() const {
|
vector<UserId> PrivacyManager::UserPrivacySettingRules::get_restricted_user_ids() const {
|
||||||
vector<int32> result;
|
vector<UserId> result;
|
||||||
for (auto &rule : rules_) {
|
for (auto &rule : rules_) {
|
||||||
combine(result, rule.get_restricted_user_ids());
|
combine(result, rule.get_restricted_user_ids());
|
||||||
}
|
}
|
||||||
td::unique(result);
|
std::sort(result.begin(), result.end(), [](UserId lhs, UserId rhs) { return lhs.get() < rhs.get(); });
|
||||||
|
result.erase(std::unique(result.begin(), result.end()), result.end());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -530,12 +532,12 @@ void PrivacyManager::do_update_privacy(UserPrivacySetting user_privacy_setting,
|
|||||||
if (old_restricted != new_restricted) {
|
if (old_restricted != new_restricted) {
|
||||||
// if a user was unrestricted, it is not received from the server anymore
|
// if a user was unrestricted, it is not received from the server anymore
|
||||||
// we need to reget their online status manually
|
// we need to reget their online status manually
|
||||||
std::vector<int32> unrestricted;
|
std::vector<UserId> unrestricted;
|
||||||
std::set_difference(old_restricted.begin(), old_restricted.end(), new_restricted.begin(),
|
std::set_difference(old_restricted.begin(), old_restricted.end(), new_restricted.begin(),
|
||||||
new_restricted.end(), std::back_inserter(unrestricted));
|
new_restricted.end(), std::back_inserter(unrestricted),
|
||||||
|
[](UserId lhs, UserId rhs) { return lhs.get() < rhs.get(); });
|
||||||
for (auto &user_id : unrestricted) {
|
for (auto &user_id : unrestricted) {
|
||||||
send_closure_later(G()->contacts_manager(), &ContactsManager::reload_user, UserId(user_id),
|
send_closure_later(G()->contacts_manager(), &ContactsManager::reload_user, user_id, Promise<Unit>());
|
||||||
Promise<Unit>());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "td/telegram/net/NetQuery.h"
|
#include "td/telegram/net/NetQuery.h"
|
||||||
#include "td/telegram/td_api.h"
|
#include "td/telegram/td_api.h"
|
||||||
#include "td/telegram/telegram_api.h"
|
#include "td/telegram/telegram_api.h"
|
||||||
|
#include "td/telegram/UserId.h"
|
||||||
|
|
||||||
#include "td/actor/actor.h"
|
#include "td/actor/actor.h"
|
||||||
#include "td/actor/PromiseFuture.h"
|
#include "td/actor/PromiseFuture.h"
|
||||||
@ -83,7 +84,7 @@ class PrivacyManager : public NetQueryCallback {
|
|||||||
return type_ == other.type_ && user_ids_ == other.user_ids_ && chat_ids_ == other.chat_ids_;
|
return type_ == other.type_ && user_ids_ == other.user_ids_ && chat_ids_ == other.chat_ids_;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<int32> get_restricted_user_ids() const;
|
vector<UserId> get_restricted_user_ids() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class Type : int32 {
|
enum class Type : int32 {
|
||||||
@ -97,7 +98,7 @@ class PrivacyManager : public NetQueryCallback {
|
|||||||
RestrictChatParticipants
|
RestrictChatParticipants
|
||||||
} type_ = Type::RestrictAll;
|
} type_ = Type::RestrictAll;
|
||||||
|
|
||||||
vector<int32> user_ids_;
|
vector<UserId> user_ids_;
|
||||||
vector<int32> chat_ids_;
|
vector<int32> chat_ids_;
|
||||||
|
|
||||||
vector<tl_object_ptr<telegram_api::InputUser>> get_input_users() const;
|
vector<tl_object_ptr<telegram_api::InputUser>> get_input_users() const;
|
||||||
@ -130,7 +131,7 @@ class PrivacyManager : public NetQueryCallback {
|
|||||||
return rules_ == other.rules_;
|
return rules_ == other.rules_;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<int32> get_restricted_user_ids() const;
|
vector<UserId> get_restricted_user_ids() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
vector<UserPrivacySettingRule> rules_;
|
vector<UserPrivacySettingRule> rules_;
|
||||||
|
@ -82,7 +82,7 @@ static StringBuilder &operator<<(StringBuilder &string_builder, const InlineKeyb
|
|||||||
string_builder << "Buy";
|
string_builder << "Buy";
|
||||||
break;
|
break;
|
||||||
case InlineKeyboardButton::Type::UrlAuth:
|
case InlineKeyboardButton::Type::UrlAuth:
|
||||||
string_builder << "UrlAuth, id = " << keyboard_button.id;
|
string_builder << "UrlAuth, ID = " << keyboard_button.id;
|
||||||
break;
|
break;
|
||||||
case InlineKeyboardButton::Type::CallbackWithPassword:
|
case InlineKeyboardButton::Type::CallbackWithPassword:
|
||||||
string_builder << "CallbackWithPassword";
|
string_builder << "CallbackWithPassword";
|
||||||
|
@ -83,7 +83,7 @@ void SecretChatActor::update_chat(telegram_api::object_ptr<telegram_api::Encrypt
|
|||||||
loop();
|
loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SecretChatActor::create_chat(int32 user_id, int64 user_access_hash, int32 random_id,
|
void SecretChatActor::create_chat(UserId user_id, int64 user_access_hash, int32 random_id,
|
||||||
Promise<SecretChatId> promise) {
|
Promise<SecretChatId> promise) {
|
||||||
if (close_flag_) {
|
if (close_flag_) {
|
||||||
promise.set_error(Status::Error(400, "Chat is closed"));
|
promise.set_error(Status::Error(400, "Chat is closed"));
|
||||||
@ -646,7 +646,7 @@ void SecretChatActor::run_fill_gaps() {
|
|||||||
|
|
||||||
void SecretChatActor::run_pfs() {
|
void SecretChatActor::run_pfs() {
|
||||||
while (true) {
|
while (true) {
|
||||||
LOG(INFO) << "Run pfs loop: " << pfs_state_;
|
LOG(INFO) << "Run PFS loop: " << pfs_state_;
|
||||||
if (pfs_state_.state == PfsState::Empty &&
|
if (pfs_state_.state == PfsState::Empty &&
|
||||||
(pfs_state_.last_message_id + 100 < seq_no_state_.message_id ||
|
(pfs_state_.last_message_id + 100 < seq_no_state_.message_id ||
|
||||||
pfs_state_.last_timestamp + 60 * 60 * 24 * 7 < Time::now()) &&
|
pfs_state_.last_timestamp + 60 * 60 * 24 * 7 < Time::now()) &&
|
||||||
@ -826,7 +826,7 @@ void SecretChatActor::do_create_chat_impl(unique_ptr<log_event::CreateSecretChat
|
|||||||
}
|
}
|
||||||
|
|
||||||
telegram_api::object_ptr<telegram_api::inputUser> SecretChatActor::get_input_user() {
|
telegram_api::object_ptr<telegram_api::inputUser> SecretChatActor::get_input_user() {
|
||||||
return telegram_api::make_object<telegram_api::inputUser>(auth_state_.user_id, auth_state_.user_access_hash);
|
return telegram_api::make_object<telegram_api::inputUser>(auth_state_.user_id.get(), auth_state_.user_access_hash);
|
||||||
}
|
}
|
||||||
telegram_api::object_ptr<telegram_api::inputEncryptedChat> SecretChatActor::get_input_chat() {
|
telegram_api::object_ptr<telegram_api::inputEncryptedChat> SecretChatActor::get_input_chat() {
|
||||||
return telegram_api::make_object<telegram_api::inputEncryptedChat>(auth_state_.id, auth_state_.access_hash);
|
return telegram_api::make_object<telegram_api::inputEncryptedChat>(auth_state_.id, auth_state_.access_hash);
|
||||||
@ -1078,7 +1078,7 @@ void SecretChatActor::do_outbound_message_impl(unique_ptr<log_event::OutboundSec
|
|||||||
binlog_event->crc = crc64(binlog_event->encrypted_message.as_slice());
|
binlog_event->crc = crc64(binlog_event->encrypted_message.as_slice());
|
||||||
LOG(INFO) << "Do outbound message: " << *binlog_event << tag("crc", binlog_event->crc);
|
LOG(INFO) << "Do outbound message: " << *binlog_event << tag("crc", binlog_event->crc);
|
||||||
auto &state_id_ref = random_id_to_outbound_message_state_token_[binlog_event->random_id];
|
auto &state_id_ref = random_id_to_outbound_message_state_token_[binlog_event->random_id];
|
||||||
LOG_CHECK(state_id_ref == 0) << "Random id collision";
|
LOG_CHECK(state_id_ref == 0) << "Random ID collision";
|
||||||
state_id_ref = outbound_message_states_.create();
|
state_id_ref = outbound_message_states_.create();
|
||||||
const uint64 state_id = state_id_ref;
|
const uint64 state_id = state_id_ref;
|
||||||
auto *state = outbound_message_states_.get(state_id);
|
auto *state = outbound_message_states_.get(state_id);
|
||||||
@ -1869,7 +1869,7 @@ Status SecretChatActor::on_update_chat(telegram_api::encryptedChatRequested &upd
|
|||||||
}
|
}
|
||||||
auth_state_.state = State::SendAccept;
|
auth_state_.state = State::SendAccept;
|
||||||
auth_state_.x = 1;
|
auth_state_.x = 1;
|
||||||
auth_state_.user_id = update.admin_id_;
|
auth_state_.user_id = UserId(update.admin_id_);
|
||||||
auth_state_.date = context_->unix_time();
|
auth_state_.date = context_->unix_time();
|
||||||
TRY_STATUS(save_common_info(update));
|
TRY_STATUS(save_common_info(update));
|
||||||
auth_state_.handshake.set_g_a(update.g_a_.as_slice());
|
auth_state_.handshake.set_g_a(update.g_a_.as_slice());
|
||||||
@ -1963,7 +1963,7 @@ void SecretChatActor::start_up() {
|
|||||||
auth_state_ = r_auth_state.move_as_ok();
|
auth_state_ = r_auth_state.move_as_ok();
|
||||||
}
|
}
|
||||||
if (!can_be_empty_ && auth_state_.state == State::Empty) {
|
if (!can_be_empty_ && auth_state_.state == State::Empty) {
|
||||||
LOG(WARNING) << "Close Secret chat because it is empty";
|
LOG(INFO) << "Skip creation of empty secret chat " << auth_state_.id;
|
||||||
return stop();
|
return stop();
|
||||||
}
|
}
|
||||||
if (auth_state_.state == State::Closed) {
|
if (auth_state_.state == State::Closed) {
|
||||||
@ -2283,9 +2283,9 @@ Status SecretChatActor::on_inbound_action(secret_api::DecryptedMessageAction &ac
|
|||||||
// Also, if SeqNoState with message_id greater than current message_id is not saved, then corresponding action will be
|
// Also, if SeqNoState with message_id greater than current message_id is not saved, then corresponding action will be
|
||||||
// replayed.
|
// replayed.
|
||||||
//
|
//
|
||||||
// This works only for ttl, not for pfs. Same ttl action may be processed twice.
|
// This works only for TTL, not for PFS. Same TTL action may be processed twice.
|
||||||
if (message_id < seq_no_state_.message_id) {
|
if (message_id < seq_no_state_.message_id) {
|
||||||
LOG(INFO) << "Drop old inbound DecryptedMessageAction (non-pfs action): " << to_string(action);
|
LOG(INFO) << "Drop old inbound DecryptedMessageAction (non-PFS action): " << to_string(action);
|
||||||
return Status::OK();
|
return Status::OK();
|
||||||
}
|
}
|
||||||
pfs_state_.message_id = message_id; // replay protection
|
pfs_state_.message_id = message_id; // replay protection
|
||||||
@ -2305,7 +2305,7 @@ void SecretChatActor::on_outbound_action(secret_api::DecryptedMessageAction &act
|
|||||||
|
|
||||||
// see comment in on_inbound_action
|
// see comment in on_inbound_action
|
||||||
if (message_id < seq_no_state_.message_id) {
|
if (message_id < seq_no_state_.message_id) {
|
||||||
LOG(INFO) << "Drop old outbound DecryptedMessageAction (non-pfs action): " << to_string(action);
|
LOG(INFO) << "Drop old outbound DecryptedMessageAction (non-PFS action): " << to_string(action);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pfs_state_.message_id = message_id; // replay protection
|
pfs_state_.message_id = message_id; // replay protection
|
||||||
|
@ -6,24 +6,23 @@
|
|||||||
//
|
//
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "td/telegram/secret_api.h"
|
|
||||||
#include "td/telegram/telegram_api.h"
|
|
||||||
|
|
||||||
#include "td/actor/actor.h"
|
|
||||||
#include "td/actor/PromiseFuture.h"
|
|
||||||
|
|
||||||
#include "td/mtproto/AuthKey.h"
|
|
||||||
#include "td/mtproto/DhHandshake.h"
|
|
||||||
|
|
||||||
#include "td/telegram/DhConfig.h"
|
#include "td/telegram/DhConfig.h"
|
||||||
#include "td/telegram/FolderId.h"
|
#include "td/telegram/FolderId.h"
|
||||||
#include "td/telegram/logevent/SecretChatEvent.h"
|
#include "td/telegram/logevent/SecretChatEvent.h"
|
||||||
#include "td/telegram/MessageId.h"
|
#include "td/telegram/MessageId.h"
|
||||||
#include "td/telegram/net/NetQuery.h"
|
#include "td/telegram/net/NetQuery.h"
|
||||||
|
#include "td/telegram/secret_api.h"
|
||||||
#include "td/telegram/SecretChatDb.h"
|
#include "td/telegram/SecretChatDb.h"
|
||||||
#include "td/telegram/SecretChatId.h"
|
#include "td/telegram/SecretChatId.h"
|
||||||
|
#include "td/telegram/telegram_api.h"
|
||||||
#include "td/telegram/UserId.h"
|
#include "td/telegram/UserId.h"
|
||||||
|
|
||||||
|
#include "td/mtproto/AuthKey.h"
|
||||||
|
#include "td/mtproto/DhHandshake.h"
|
||||||
|
|
||||||
|
#include "td/actor/actor.h"
|
||||||
|
#include "td/actor/PromiseFuture.h"
|
||||||
|
|
||||||
#include "td/utils/buffer.h"
|
#include "td/utils/buffer.h"
|
||||||
#include "td/utils/ChangesProcessor.h"
|
#include "td/utils/ChangesProcessor.h"
|
||||||
#include "td/utils/common.h"
|
#include "td/utils/common.h"
|
||||||
@ -115,7 +114,7 @@ class SecretChatActor : public NetQueryCallback {
|
|||||||
|
|
||||||
// First query to new chat must be one of these two
|
// First query to new chat must be one of these two
|
||||||
void update_chat(telegram_api::object_ptr<telegram_api::EncryptedChat> chat);
|
void update_chat(telegram_api::object_ptr<telegram_api::EncryptedChat> chat);
|
||||||
void create_chat(int32 user_id, int64 user_access_hash, int32 random_id, Promise<SecretChatId> promise);
|
void create_chat(UserId user_id, int64 user_access_hash, int32 random_id, Promise<SecretChatId> promise);
|
||||||
|
|
||||||
void cancel_chat(bool delete_history, bool is_already_discarded, Promise<> promise);
|
void cancel_chat(bool delete_history, bool is_already_discarded, Promise<> promise);
|
||||||
|
|
||||||
@ -374,7 +373,7 @@ class SecretChatActor : public NetQueryCallback {
|
|||||||
int32 id = 0;
|
int32 id = 0;
|
||||||
int64 access_hash = 0;
|
int64 access_hash = 0;
|
||||||
|
|
||||||
int32 user_id = 0;
|
UserId user_id;
|
||||||
int64 user_access_hash = 0;
|
int64 user_access_hash = 0;
|
||||||
int32 random_id = 0;
|
int32 random_id = 0;
|
||||||
|
|
||||||
@ -408,7 +407,7 @@ class SecretChatActor : public NetQueryCallback {
|
|||||||
|
|
||||||
storer.store_int(id);
|
storer.store_int(id);
|
||||||
storer.store_long(access_hash);
|
storer.store_long(access_hash);
|
||||||
storer.store_int(user_id);
|
storer.store_int(user_id.get());
|
||||||
storer.store_long(user_access_hash);
|
storer.store_long(user_access_hash);
|
||||||
storer.store_int(random_id);
|
storer.store_int(random_id);
|
||||||
if (has_date) {
|
if (has_date) {
|
||||||
@ -439,7 +438,7 @@ class SecretChatActor : public NetQueryCallback {
|
|||||||
|
|
||||||
id = parser.fetch_int();
|
id = parser.fetch_int();
|
||||||
access_hash = parser.fetch_long();
|
access_hash = parser.fetch_long();
|
||||||
user_id = parser.fetch_int();
|
user_id = UserId(parser.fetch_int());
|
||||||
user_access_hash = parser.fetch_long();
|
user_access_hash = parser.fetch_long();
|
||||||
random_id = parser.fetch_int();
|
random_id = parser.fetch_int();
|
||||||
if (has_date) {
|
if (has_date) {
|
||||||
@ -701,7 +700,7 @@ class SecretChatActor : public NetQueryCallback {
|
|||||||
return SecretChatId(auth_state_.id);
|
return SecretChatId(auth_state_.id);
|
||||||
}
|
}
|
||||||
UserId get_user_id() {
|
UserId get_user_id() {
|
||||||
return UserId(auth_state_.user_id);
|
return auth_state_.user_id;
|
||||||
}
|
}
|
||||||
void send_update_ttl(int32 ttl);
|
void send_update_ttl(int32 ttl);
|
||||||
void send_update_secret_chat();
|
void send_update_secret_chat();
|
||||||
|
@ -96,7 +96,7 @@ void SecretChatsManager::start_up() {
|
|||||||
send_closure(G()->state_manager(), &StateManager::add_callback, make_unique<StateCallback>(actor_id(this)));
|
send_closure(G()->state_manager(), &StateManager::add_callback, make_unique<StateCallback>(actor_id(this)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SecretChatsManager::create_chat(int32 user_id, int64 user_access_hash, Promise<SecretChatId> promise) {
|
void SecretChatsManager::create_chat(UserId user_id, int64 user_access_hash, Promise<SecretChatId> promise) {
|
||||||
int32 random_id;
|
int32 random_id;
|
||||||
ActorId<SecretChatActor> actor;
|
ActorId<SecretChatActor> actor;
|
||||||
do {
|
do {
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "td/telegram/logevent/SecretChatEvent.h"
|
#include "td/telegram/logevent/SecretChatEvent.h"
|
||||||
#include "td/telegram/SecretChatActor.h"
|
#include "td/telegram/SecretChatActor.h"
|
||||||
#include "td/telegram/SecretChatId.h"
|
#include "td/telegram/SecretChatId.h"
|
||||||
|
#include "td/telegram/UserId.h"
|
||||||
|
|
||||||
#include "td/telegram/secret_api.h"
|
#include "td/telegram/secret_api.h"
|
||||||
#include "td/telegram/telegram_api.h"
|
#include "td/telegram/telegram_api.h"
|
||||||
@ -34,7 +35,7 @@ class SecretChatsManager : public Actor {
|
|||||||
void on_update_chat(tl_object_ptr<telegram_api::updateEncryption> update);
|
void on_update_chat(tl_object_ptr<telegram_api::updateEncryption> update);
|
||||||
void on_new_message(tl_object_ptr<telegram_api::EncryptedMessage> &&message_ptr, Promise<Unit> &&promise);
|
void on_new_message(tl_object_ptr<telegram_api::EncryptedMessage> &&message_ptr, Promise<Unit> &&promise);
|
||||||
|
|
||||||
void create_chat(int32 user_id, int64 user_access_hash, Promise<SecretChatId> promise);
|
void create_chat(UserId user_id, int64 user_access_hash, Promise<SecretChatId> promise);
|
||||||
void cancel_chat(SecretChatId secret_chat_id, bool delete_history, Promise<> promise);
|
void cancel_chat(SecretChatId secret_chat_id, bool delete_history, Promise<> promise);
|
||||||
void send_message(SecretChatId secret_chat_id, tl_object_ptr<secret_api::decryptedMessage> message,
|
void send_message(SecretChatId secret_chat_id, tl_object_ptr<secret_api::decryptedMessage> message,
|
||||||
tl_object_ptr<telegram_api::InputEncryptedFile> file, Promise<> promise);
|
tl_object_ptr<telegram_api::InputEncryptedFile> file, Promise<> promise);
|
||||||
|
@ -2101,7 +2101,7 @@ FileId StickersManager::dup_sticker(FileId new_id, FileId old_id) {
|
|||||||
|
|
||||||
bool StickersManager::merge_stickers(FileId new_id, FileId old_id, bool can_delete_old) {
|
bool StickersManager::merge_stickers(FileId new_id, FileId old_id, bool can_delete_old) {
|
||||||
if (!old_id.is_valid()) {
|
if (!old_id.is_valid()) {
|
||||||
LOG(ERROR) << "Old file id is invalid";
|
LOG(ERROR) << "Old file identifier is invalid";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2703,7 +2703,7 @@ StickerSetId StickersManager::on_get_messages_sticker_set(StickerSetId sticker_s
|
|||||||
for (int64 document_id : pack->documents_) {
|
for (int64 document_id : pack->documents_) {
|
||||||
auto it = document_id_to_sticker_id.find(document_id);
|
auto it = document_id_to_sticker_id.find(document_id);
|
||||||
if (it == document_id_to_sticker_id.end()) {
|
if (it == document_id_to_sticker_id.end()) {
|
||||||
LOG(ERROR) << "Can't find document with id " << document_id << " in " << set_id << "/" << s->short_name
|
LOG(ERROR) << "Can't find document with ID " << document_id << " in " << set_id << "/" << s->short_name
|
||||||
<< " from " << source;
|
<< " from " << source;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -570,12 +570,12 @@ class TestProxyRequest : public RequestOnceActor {
|
|||||||
set_timeout_in(timeout_);
|
set_timeout_in(timeout_);
|
||||||
|
|
||||||
promise_ = std::move(promise);
|
promise_ = std::move(promise);
|
||||||
IPAddress ip;
|
IPAddress ip_address;
|
||||||
auto status = ip.init_host_port(proxy_.server(), proxy_.port());
|
auto status = ip_address.init_host_port(proxy_.server(), proxy_.port());
|
||||||
if (status.is_error()) {
|
if (status.is_error()) {
|
||||||
return promise_.set_error(Status::Error(400, status.public_message()));
|
return promise_.set_error(Status::Error(400, status.public_message()));
|
||||||
}
|
}
|
||||||
auto r_socket_fd = SocketFd::open(ip);
|
auto r_socket_fd = SocketFd::open(ip_address);
|
||||||
if (r_socket_fd.is_error()) {
|
if (r_socket_fd.is_error()) {
|
||||||
return promise_.set_error(Status::Error(400, r_socket_fd.error().public_message()));
|
return promise_.set_error(Status::Error(400, r_socket_fd.error().public_message()));
|
||||||
}
|
}
|
||||||
@ -594,9 +594,9 @@ class TestProxyRequest : public RequestOnceActor {
|
|||||||
send_closure(actor_id, &TestProxyRequest::on_connection_data, std::move(r_data));
|
send_closure(actor_id, &TestProxyRequest::on_connection_data, std::move(r_data));
|
||||||
});
|
});
|
||||||
|
|
||||||
child_ =
|
child_ = ConnectionCreator::prepare_connection(ip_address, r_socket_fd.move_as_ok(), proxy_, mtproto_ip_address,
|
||||||
ConnectionCreator::prepare_connection(r_socket_fd.move_as_ok(), proxy_, mtproto_ip_address, get_transport(),
|
get_transport(), "Test", "TestPingDC2", nullptr, {}, false,
|
||||||
"Test", "TestPingDC2", nullptr, {}, false, std::move(connection_promise));
|
std::move(connection_promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_connection_data(Result<ConnectionCreator::ConnectionData> r_data) {
|
void on_connection_data(Result<ConnectionCreator::ConnectionData> r_data) {
|
||||||
@ -617,7 +617,8 @@ class TestProxyRequest : public RequestOnceActor {
|
|||||||
};
|
};
|
||||||
auto handshake = make_unique<mtproto::AuthKeyHandshake>(dc_id_, 3600);
|
auto handshake = make_unique<mtproto::AuthKeyHandshake>(dc_id_, 3600);
|
||||||
auto data = r_data.move_as_ok();
|
auto data = r_data.move_as_ok();
|
||||||
auto raw_connection = make_unique<mtproto::RawConnection>(std::move(data.socket_fd), get_transport(), nullptr);
|
auto raw_connection =
|
||||||
|
mtproto::RawConnection::create(data.ip_address, std::move(data.socket_fd), get_transport(), nullptr);
|
||||||
child_ = create_actor<mtproto::HandshakeActor>(
|
child_ = create_actor<mtproto::HandshakeActor>(
|
||||||
"HandshakeActor", std::move(handshake), std::move(raw_connection), make_unique<HandshakeContext>(), 10.0,
|
"HandshakeActor", std::move(handshake), std::move(raw_connection), make_unique<HandshakeContext>(), 10.0,
|
||||||
PromiseCreator::lambda([actor_id = actor_id(this)](Result<unique_ptr<mtproto::RawConnection>> raw_connection) {
|
PromiseCreator::lambda([actor_id = actor_id(this)](Result<unique_ptr<mtproto::RawConnection>> raw_connection) {
|
||||||
@ -1843,11 +1844,11 @@ class CreateNewGroupChatRequest : public RequestActor<> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CreateNewGroupChatRequest(ActorShared<Td> td, uint64 request_id, vector<int32> user_ids, string title)
|
CreateNewGroupChatRequest(ActorShared<Td> td, uint64 request_id, vector<UserId> user_ids, string title)
|
||||||
: RequestActor(std::move(td), request_id), title_(std::move(title)), random_id_(0) {
|
: RequestActor(std::move(td), request_id)
|
||||||
for (auto user_id : user_ids) {
|
, user_ids_(std::move(user_ids))
|
||||||
user_ids_.emplace_back(user_id);
|
, title_(std::move(title))
|
||||||
}
|
, random_id_(0) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1943,26 +1944,31 @@ class UpgradeGroupChatToSupergroupChatRequest : public RequestActor<> {
|
|||||||
|
|
||||||
class GetChatMemberRequest : public RequestActor<> {
|
class GetChatMemberRequest : public RequestActor<> {
|
||||||
DialogId dialog_id_;
|
DialogId dialog_id_;
|
||||||
UserId user_id_;
|
DialogId participant_dialog_id_;
|
||||||
int64 random_id_;
|
int64 random_id_;
|
||||||
|
|
||||||
DialogParticipant dialog_participant_;
|
DialogParticipant dialog_participant_;
|
||||||
|
|
||||||
void do_run(Promise<Unit> &&promise) override {
|
void do_run(Promise<Unit> &&promise) override {
|
||||||
dialog_participant_ = td->contacts_manager_->get_dialog_participant(dialog_id_, user_id_, random_id_,
|
dialog_participant_ = td->contacts_manager_->get_dialog_participant(dialog_id_, participant_dialog_id_, random_id_,
|
||||||
get_tries() < 3, std::move(promise));
|
get_tries() < 3, std::move(promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_send_result() override {
|
void do_send_result() override {
|
||||||
if (!td->contacts_manager_->have_user(user_id_)) {
|
bool is_user = participant_dialog_id_.get_type() == DialogType::User;
|
||||||
return send_error(Status::Error(3, "User not found"));
|
if ((is_user && !td->contacts_manager_->have_user(participant_dialog_id_.get_user_id())) ||
|
||||||
|
(!is_user && !td->messages_manager_->have_dialog(participant_dialog_id_))) {
|
||||||
|
return send_error(Status::Error(3, "Member not found"));
|
||||||
}
|
}
|
||||||
send_result(td->contacts_manager_->get_chat_member_object(dialog_participant_));
|
send_result(td->contacts_manager_->get_chat_member_object(dialog_participant_));
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GetChatMemberRequest(ActorShared<Td> td, uint64 request_id, int64 dialog_id, int32 user_id)
|
GetChatMemberRequest(ActorShared<Td> td, uint64 request_id, int64 dialog_id, DialogId participant_dialog_id)
|
||||||
: RequestActor(std::move(td), request_id), dialog_id_(dialog_id), user_id_(user_id), random_id_(0) {
|
: RequestActor(std::move(td), request_id)
|
||||||
|
, dialog_id_(dialog_id)
|
||||||
|
, participant_dialog_id_(participant_dialog_id)
|
||||||
|
, random_id_(0) {
|
||||||
set_tries(3);
|
set_tries(3);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -2061,16 +2067,14 @@ class GetChatEventLogRequest : public RequestOnceActor {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
GetChatEventLogRequest(ActorShared<Td> td, uint64 request_id, int64 dialog_id, string &&query, int64 from_event_id,
|
GetChatEventLogRequest(ActorShared<Td> td, uint64 request_id, int64 dialog_id, string &&query, int64 from_event_id,
|
||||||
int32 limit, tl_object_ptr<td_api::chatEventLogFilters> &&filters, vector<int32> user_ids)
|
int32 limit, tl_object_ptr<td_api::chatEventLogFilters> &&filters, vector<UserId> user_ids)
|
||||||
: RequestOnceActor(std::move(td), request_id)
|
: RequestOnceActor(std::move(td), request_id)
|
||||||
, dialog_id_(dialog_id)
|
, dialog_id_(dialog_id)
|
||||||
, query_(std::move(query))
|
, query_(std::move(query))
|
||||||
, from_event_id_(from_event_id)
|
, from_event_id_(from_event_id)
|
||||||
, limit_(limit)
|
, limit_(limit)
|
||||||
, filters_(std::move(filters)) {
|
, filters_(std::move(filters))
|
||||||
for (auto user_id : user_ids) {
|
, user_ids_(std::move(user_ids)) {
|
||||||
user_ids_.emplace_back(user_id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2155,11 +2159,8 @@ class RemoveContactsRequest : public RequestActor<> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RemoveContactsRequest(ActorShared<Td> td, uint64 request_id, vector<int32> &&user_ids)
|
RemoveContactsRequest(ActorShared<Td> td, uint64 request_id, vector<UserId> &&user_ids)
|
||||||
: RequestActor(std::move(td), request_id) {
|
: RequestActor(std::move(td), request_id), user_ids_(std::move(user_ids)) {
|
||||||
for (auto user_id : user_ids) {
|
|
||||||
user_ids_.emplace_back(user_id);
|
|
||||||
}
|
|
||||||
set_tries(3); // load_contacts + delete_contacts
|
set_tries(3); // load_contacts + delete_contacts
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -3195,6 +3196,10 @@ bool Td::is_online() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Td::set_is_bot_online(bool is_bot_online) {
|
void Td::set_is_bot_online(bool is_bot_online) {
|
||||||
|
if (G()->shared_config().get_option_integer("session_count") > 1) {
|
||||||
|
is_bot_online = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (is_bot_online == is_bot_online_) {
|
if (is_bot_online == is_bot_online_) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -3355,7 +3360,7 @@ DbKey Td::as_db_key(string key) {
|
|||||||
|
|
||||||
void Td::request(uint64 id, tl_object_ptr<td_api::Function> function) {
|
void Td::request(uint64 id, tl_object_ptr<td_api::Function> function) {
|
||||||
if (id == 0) {
|
if (id == 0) {
|
||||||
LOG(ERROR) << "Ignore request with id == 0: " << to_string(function);
|
LOG(ERROR) << "Ignore request with ID == 0: " << to_string(function);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3411,17 +3416,14 @@ void Td::request(uint64 id, tl_object_ptr<td_api::Function> function) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case State::Decrypt: {
|
case State::Decrypt: {
|
||||||
string encryption_key;
|
|
||||||
switch (function_id) {
|
switch (function_id) {
|
||||||
case td_api::checkDatabaseEncryptionKey::ID: {
|
case td_api::checkDatabaseEncryptionKey::ID: {
|
||||||
auto check_key = move_tl_object_as<td_api::checkDatabaseEncryptionKey>(function);
|
auto check_key = move_tl_object_as<td_api::checkDatabaseEncryptionKey>(function);
|
||||||
encryption_key = std::move(check_key->encryption_key_);
|
return answer_ok_query(id, init(as_db_key(std::move(check_key->encryption_key_))));
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case td_api::setDatabaseEncryptionKey::ID: {
|
case td_api::setDatabaseEncryptionKey::ID: {
|
||||||
auto set_key = move_tl_object_as<td_api::setDatabaseEncryptionKey>(function);
|
auto set_key = move_tl_object_as<td_api::setDatabaseEncryptionKey>(function);
|
||||||
encryption_key = std::move(set_key->new_encryption_key_);
|
return answer_ok_query(id, init(as_db_key(std::move(set_key->new_encryption_key_))));
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case td_api::destroy::ID:
|
case td_api::destroy::ID:
|
||||||
// need to send response synchronously before actual destroying
|
// need to send response synchronously before actual destroying
|
||||||
@ -3438,7 +3440,7 @@ void Td::request(uint64 id, tl_object_ptr<td_api::Function> function) {
|
|||||||
return send_error_impl(
|
return send_error_impl(
|
||||||
id, make_error(400, "Database encryption key is needed: call checkDatabaseEncryptionKey first"));
|
id, make_error(400, "Database encryption key is needed: call checkDatabaseEncryptionKey first"));
|
||||||
}
|
}
|
||||||
return answer_ok_query(id, init(as_db_key(encryption_key)));
|
break;
|
||||||
}
|
}
|
||||||
case State::Close:
|
case State::Close:
|
||||||
if (destroy_flag_) {
|
if (destroy_flag_) {
|
||||||
@ -4795,7 +4797,7 @@ void Td::on_request(uint64 id, td_api::registerUser &request) {
|
|||||||
|
|
||||||
void Td::on_request(uint64 id, td_api::requestQrCodeAuthentication &request) {
|
void Td::on_request(uint64 id, td_api::requestQrCodeAuthentication &request) {
|
||||||
send_closure(auth_manager_actor_, &AuthManager::request_qr_code_authentication, id,
|
send_closure(auth_manager_actor_, &AuthManager::request_qr_code_authentication, id,
|
||||||
std::move(request.other_user_ids_));
|
UserId::get_user_ids(request.other_user_ids_));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, td_api::checkAuthenticationPassword &request) {
|
void Td::on_request(uint64 id, td_api::checkAuthenticationPassword &request) {
|
||||||
@ -4986,7 +4988,7 @@ void Td::on_request(uint64 id, td_api::registerDevice &request) {
|
|||||||
}
|
}
|
||||||
CREATE_REQUEST_PROMISE();
|
CREATE_REQUEST_PROMISE();
|
||||||
send_closure(device_token_manager_, &DeviceTokenManager::register_device, std::move(request.device_token_),
|
send_closure(device_token_manager_, &DeviceTokenManager::register_device, std::move(request.device_token_),
|
||||||
std::move(request.other_user_ids_), std::move(promise));
|
UserId::get_user_ids(request.other_user_ids_), std::move(promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, td_api::getUserPrivacySettingRules &request) {
|
void Td::on_request(uint64 id, td_api::getUserPrivacySettingRules &request) {
|
||||||
@ -5176,6 +5178,18 @@ void Td::on_request(uint64 id, const td_api::getFile &request) {
|
|||||||
send_closure(actor_id(this), &Td::send_result, id, file_manager_->get_file_object(FileId(request.file_id_, 0)));
|
send_closure(actor_id(this), &Td::send_result, id, file_manager_->get_file_object(FileId(request.file_id_, 0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Td::on_request(uint64 id, const td_api::getChannelDifference &request) {
|
||||||
|
auto result = messages_manager_->run_get_channel_difference_request(request.channel_difference_id_);
|
||||||
|
if (result) {
|
||||||
|
send_closure(actor_id(this), &Td::send_result, id,
|
||||||
|
td_api::make_object<td_api::ok>());
|
||||||
|
} else {
|
||||||
|
send_closure(actor_id(this), &Td::send_result, id,
|
||||||
|
td_api::make_object<td_api::error>(
|
||||||
|
400, "Channel diffence identifier already executed or nonexistent"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, td_api::getRemoteFile &request) {
|
void Td::on_request(uint64 id, td_api::getRemoteFile &request) {
|
||||||
CLEAN_INPUT_STRING(request.remote_file_id_);
|
CLEAN_INPUT_STRING(request.remote_file_id_);
|
||||||
auto file_type = request.file_type_ == nullptr ? FileType::Temp : get_file_type(*request.file_type_);
|
auto file_type = request.file_type_ == nullptr ? FileType::Temp : get_file_type(*request.file_type_);
|
||||||
@ -5533,19 +5547,19 @@ void Td::on_request(uint64 id, const td_api::openMessageContent &request) {
|
|||||||
id, messages_manager_->open_message_content({DialogId(request.chat_id_), MessageId(request.message_id_)}));
|
id, messages_manager_->open_message_content({DialogId(request.chat_id_), MessageId(request.message_id_)}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Td::on_request(uint64 id, td_api::getExternalLinkInfo &request) {
|
||||||
|
CHECK_IS_USER();
|
||||||
|
CLEAN_INPUT_STRING(request.link_);
|
||||||
|
CREATE_REQUEST_PROMISE();
|
||||||
|
send_closure_later(G()->config_manager(), &ConfigManager::get_external_link_info, std::move(request.link_),
|
||||||
|
std::move(promise));
|
||||||
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, td_api::getExternalLink &request) {
|
void Td::on_request(uint64 id, td_api::getExternalLink &request) {
|
||||||
CHECK_IS_USER();
|
CHECK_IS_USER();
|
||||||
CLEAN_INPUT_STRING(request.link_);
|
CLEAN_INPUT_STRING(request.link_);
|
||||||
CREATE_REQUEST_PROMISE();
|
CREATE_REQUEST_PROMISE();
|
||||||
auto query_promise = [promise = std::move(promise)](Result<string> &&result) mutable {
|
messages_manager_->get_link_login_url(request.link_, request.allow_write_access_, std::move(promise));
|
||||||
if (result.is_error()) {
|
|
||||||
promise.set_error(result.move_as_error());
|
|
||||||
} else {
|
|
||||||
promise.set_value(td_api::make_object<td_api::httpUrl>(result.ok()));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
send_closure_later(G()->config_manager(), &ConfigManager::get_external_link, std::move(request.link_),
|
|
||||||
std::move(query_promise));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, const td_api::getChatHistory &request) {
|
void Td::on_request(uint64 id, const td_api::getChatHistory &request) {
|
||||||
@ -5941,7 +5955,7 @@ void Td::on_request(uint64 id, td_api::createSecretChat &request) {
|
|||||||
void Td::on_request(uint64 id, td_api::createNewBasicGroupChat &request) {
|
void Td::on_request(uint64 id, td_api::createNewBasicGroupChat &request) {
|
||||||
CHECK_IS_USER();
|
CHECK_IS_USER();
|
||||||
CLEAN_INPUT_STRING(request.title_);
|
CLEAN_INPUT_STRING(request.title_);
|
||||||
CREATE_REQUEST(CreateNewGroupChatRequest, request.user_ids_, std::move(request.title_));
|
CREATE_REQUEST(CreateNewGroupChatRequest, UserId::get_user_ids(request.user_ids_), std::move(request.title_));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, td_api::createNewSupergroupChat &request) {
|
void Td::on_request(uint64 id, td_api::createNewSupergroupChat &request) {
|
||||||
@ -6024,9 +6038,24 @@ void Td::on_request(uint64 id, td_api::sendCallDebugInformation &request) {
|
|||||||
std::move(request.debug_information_), std::move(promise));
|
std::move(request.debug_information_), std::move(promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, const td_api::createVoiceChat &request) {
|
void Td::on_request(uint64 id, const td_api::getVoiceChatAvailableParticipants &request) {
|
||||||
CHECK_IS_USER();
|
CHECK_IS_USER();
|
||||||
CREATE_REQUEST_PROMISE();
|
CREATE_REQUEST_PROMISE();
|
||||||
|
group_call_manager_->get_group_call_join_as(DialogId(request.chat_id_), std::move(promise));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Td::on_request(uint64 id, const td_api::setVoiceChatDefaultParticipant &request) {
|
||||||
|
CHECK_IS_USER();
|
||||||
|
CREATE_OK_REQUEST_PROMISE();
|
||||||
|
group_call_manager_->set_group_call_default_join_as(
|
||||||
|
DialogId(request.chat_id_), group_call_manager_->get_group_call_participant_id(request.default_participant_id_),
|
||||||
|
std::move(promise));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Td::on_request(uint64 id, td_api::createVoiceChat &request) {
|
||||||
|
CHECK_IS_USER();
|
||||||
|
CLEAN_INPUT_STRING(request.title_);
|
||||||
|
CREATE_REQUEST_PROMISE();
|
||||||
auto query_promise = PromiseCreator::lambda([promise = std::move(promise)](Result<GroupCallId> result) mutable {
|
auto query_promise = PromiseCreator::lambda([promise = std::move(promise)](Result<GroupCallId> result) mutable {
|
||||||
if (result.is_error()) {
|
if (result.is_error()) {
|
||||||
promise.set_error(result.move_as_error());
|
promise.set_error(result.move_as_error());
|
||||||
@ -6034,7 +6063,8 @@ void Td::on_request(uint64 id, const td_api::createVoiceChat &request) {
|
|||||||
promise.set_value(td_api::make_object<td_api::groupCallId>(result.ok().get()));
|
promise.set_value(td_api::make_object<td_api::groupCallId>(result.ok().get()));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
group_call_manager_->create_voice_chat(DialogId(request.chat_id_), std::move(query_promise));
|
group_call_manager_->create_voice_chat(DialogId(request.chat_id_), std::move(request.title_), request.start_date_,
|
||||||
|
std::move(query_promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, const td_api::getGroupCall &request) {
|
void Td::on_request(uint64 id, const td_api::getGroupCall &request) {
|
||||||
@ -6043,11 +6073,34 @@ void Td::on_request(uint64 id, const td_api::getGroupCall &request) {
|
|||||||
group_call_manager_->get_group_call(GroupCallId(request.group_call_id_), std::move(promise));
|
group_call_manager_->get_group_call(GroupCallId(request.group_call_id_), std::move(promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Td::on_request(uint64 id, const td_api::startScheduledGroupCall &request) {
|
||||||
|
CHECK_IS_USER();
|
||||||
|
CREATE_OK_REQUEST_PROMISE();
|
||||||
|
group_call_manager_->start_scheduled_group_call(GroupCallId(request.group_call_id_), std::move(promise));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Td::on_request(uint64 id, const td_api::toggleGroupCallEnabledStartNotification &request) {
|
||||||
|
CHECK_IS_USER();
|
||||||
|
CREATE_OK_REQUEST_PROMISE();
|
||||||
|
group_call_manager_->toggle_group_call_start_subscribed(GroupCallId(request.group_call_id_),
|
||||||
|
request.enabled_start_notification_, std::move(promise));
|
||||||
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, td_api::joinGroupCall &request) {
|
void Td::on_request(uint64 id, td_api::joinGroupCall &request) {
|
||||||
CHECK_IS_USER();
|
CHECK_IS_USER();
|
||||||
|
CLEAN_INPUT_STRING(request.invite_hash_);
|
||||||
CREATE_REQUEST_PROMISE();
|
CREATE_REQUEST_PROMISE();
|
||||||
group_call_manager_->join_group_call(GroupCallId(request.group_call_id_), std::move(request.payload_),
|
group_call_manager_->join_group_call(
|
||||||
request.source_, request.is_muted_, std::move(promise));
|
GroupCallId(request.group_call_id_), group_call_manager_->get_group_call_participant_id(request.participant_id_),
|
||||||
|
std::move(request.payload_), request.source_, request.is_muted_, request.invite_hash_, std::move(promise));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Td::on_request(uint64 id, td_api::setGroupCallTitle &request) {
|
||||||
|
CHECK_IS_USER();
|
||||||
|
CLEAN_INPUT_STRING(request.title_);
|
||||||
|
CREATE_OK_REQUEST_PROMISE();
|
||||||
|
group_call_manager_->set_group_call_title(GroupCallId(request.group_call_id_), std::move(request.title_),
|
||||||
|
std::move(promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, const td_api::toggleGroupCallMuteNewParticipants &request) {
|
void Td::on_request(uint64 id, const td_api::toggleGroupCallMuteNewParticipants &request) {
|
||||||
@ -6057,14 +6110,45 @@ void Td::on_request(uint64 id, const td_api::toggleGroupCallMuteNewParticipants
|
|||||||
request.mute_new_participants_, std::move(promise));
|
request.mute_new_participants_, std::move(promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Td::on_request(uint64 id, const td_api::revokeGroupCallInviteLink &request) {
|
||||||
|
CHECK_IS_USER();
|
||||||
|
CREATE_OK_REQUEST_PROMISE();
|
||||||
|
group_call_manager_->revoke_group_call_invite_link(GroupCallId(request.group_call_id_), std::move(promise));
|
||||||
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, const td_api::inviteGroupCallParticipants &request) {
|
void Td::on_request(uint64 id, const td_api::inviteGroupCallParticipants &request) {
|
||||||
CHECK_IS_USER();
|
CHECK_IS_USER();
|
||||||
CREATE_OK_REQUEST_PROMISE();
|
CREATE_OK_REQUEST_PROMISE();
|
||||||
vector<UserId> user_ids;
|
group_call_manager_->invite_group_call_participants(GroupCallId(request.group_call_id_),
|
||||||
for (auto &user_id : request.user_ids_) {
|
UserId::get_user_ids(request.user_ids_), std::move(promise));
|
||||||
user_ids.emplace_back(user_id);
|
}
|
||||||
|
|
||||||
|
void Td::on_request(uint64 id, const td_api::getGroupCallInviteLink &request) {
|
||||||
|
CHECK_IS_USER();
|
||||||
|
CREATE_REQUEST_PROMISE();
|
||||||
|
auto query_promise = PromiseCreator::lambda([promise = std::move(promise)](Result<string> result) mutable {
|
||||||
|
if (result.is_error()) {
|
||||||
|
promise.set_error(result.move_as_error());
|
||||||
|
} else {
|
||||||
|
promise.set_value(td_api::make_object<td_api::httpUrl>(result.move_as_ok()));
|
||||||
}
|
}
|
||||||
group_call_manager_->invite_group_call_participants(GroupCallId(request.group_call_id_), std::move(user_ids),
|
});
|
||||||
|
group_call_manager_->get_group_call_invite_link(GroupCallId(request.group_call_id_), request.can_self_unmute_,
|
||||||
|
std::move(query_promise));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Td::on_request(uint64 id, td_api::startGroupCallRecording &request) {
|
||||||
|
CHECK_IS_USER();
|
||||||
|
CLEAN_INPUT_STRING(request.title_);
|
||||||
|
CREATE_OK_REQUEST_PROMISE();
|
||||||
|
group_call_manager_->toggle_group_call_recording(GroupCallId(request.group_call_id_), true, std::move(request.title_),
|
||||||
|
std::move(promise));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Td::on_request(uint64 id, const td_api::endGroupCallRecording &request) {
|
||||||
|
CHECK_IS_USER();
|
||||||
|
CREATE_OK_REQUEST_PROMISE();
|
||||||
|
group_call_manager_->toggle_group_call_recording(GroupCallId(request.group_call_id_), false, string(),
|
||||||
std::move(promise));
|
std::move(promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6079,14 +6163,24 @@ void Td::on_request(uint64 id, const td_api::toggleGroupCallParticipantIsMuted &
|
|||||||
CHECK_IS_USER();
|
CHECK_IS_USER();
|
||||||
CREATE_OK_REQUEST_PROMISE();
|
CREATE_OK_REQUEST_PROMISE();
|
||||||
group_call_manager_->toggle_group_call_participant_is_muted(
|
group_call_manager_->toggle_group_call_participant_is_muted(
|
||||||
GroupCallId(request.group_call_id_), UserId(request.user_id_), request.is_muted_, std::move(promise));
|
GroupCallId(request.group_call_id_), group_call_manager_->get_group_call_participant_id(request.participant_id_),
|
||||||
|
request.is_muted_, std::move(promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, const td_api::setGroupCallParticipantVolumeLevel &request) {
|
void Td::on_request(uint64 id, const td_api::setGroupCallParticipantVolumeLevel &request) {
|
||||||
CHECK_IS_USER();
|
CHECK_IS_USER();
|
||||||
CREATE_OK_REQUEST_PROMISE();
|
CREATE_OK_REQUEST_PROMISE();
|
||||||
group_call_manager_->set_group_call_participant_volume_level(
|
group_call_manager_->set_group_call_participant_volume_level(
|
||||||
GroupCallId(request.group_call_id_), UserId(request.user_id_), request.volume_level_, std::move(promise));
|
GroupCallId(request.group_call_id_), group_call_manager_->get_group_call_participant_id(request.participant_id_),
|
||||||
|
request.volume_level_, std::move(promise));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Td::on_request(uint64 id, const td_api::toggleGroupCallParticipantIsHandRaised &request) {
|
||||||
|
CHECK_IS_USER();
|
||||||
|
CREATE_OK_REQUEST_PROMISE();
|
||||||
|
group_call_manager_->toggle_group_call_participant_is_hand_raised(
|
||||||
|
GroupCallId(request.group_call_id_), group_call_manager_->get_group_call_participant_id(request.participant_id_),
|
||||||
|
request.is_hand_raised_, std::move(promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, const td_api::loadGroupCallParticipants &request) {
|
void Td::on_request(uint64 id, const td_api::loadGroupCallParticipants &request) {
|
||||||
@ -6108,6 +6202,22 @@ void Td::on_request(uint64 id, const td_api::discardGroupCall &request) {
|
|||||||
group_call_manager_->discard_group_call(GroupCallId(request.group_call_id_), std::move(promise));
|
group_call_manager_->discard_group_call(GroupCallId(request.group_call_id_), std::move(promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Td::on_request(uint64 id, const td_api::getGroupCallStreamSegment &request) {
|
||||||
|
CHECK_IS_USER();
|
||||||
|
CREATE_REQUEST_PROMISE();
|
||||||
|
auto query_promise = PromiseCreator::lambda([promise = std::move(promise)](Result<string> result) mutable {
|
||||||
|
if (result.is_error()) {
|
||||||
|
promise.set_error(result.move_as_error());
|
||||||
|
} else {
|
||||||
|
auto file_part = td_api::make_object<td_api::filePart>();
|
||||||
|
file_part->data_ = result.move_as_ok();
|
||||||
|
promise.set_value(std::move(file_part));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
group_call_manager_->get_group_call_stream_segment(GroupCallId(request.group_call_id_), request.time_offset_,
|
||||||
|
request.scale_, std::move(query_promise));
|
||||||
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, const td_api::upgradeBasicGroupChatToSupergroupChat &request) {
|
void Td::on_request(uint64 id, const td_api::upgradeBasicGroupChatToSupergroupChat &request) {
|
||||||
CHECK_IS_USER();
|
CHECK_IS_USER();
|
||||||
CREATE_REQUEST(UpgradeGroupChatToSupergroupChatRequest, request.chat_id_);
|
CREATE_REQUEST(UpgradeGroupChatToSupergroupChatRequest, request.chat_id_);
|
||||||
@ -6294,7 +6404,7 @@ void Td::on_request(uint64 id, const td_api::leaveChat &request) {
|
|||||||
CREATE_OK_REQUEST_PROMISE();
|
CREATE_OK_REQUEST_PROMISE();
|
||||||
DialogId dialog_id(request.chat_id_);
|
DialogId dialog_id(request.chat_id_);
|
||||||
td_api::object_ptr<td_api::ChatMemberStatus> new_status = td_api::make_object<td_api::chatMemberStatusLeft>();
|
td_api::object_ptr<td_api::ChatMemberStatus> new_status = td_api::make_object<td_api::chatMemberStatusLeft>();
|
||||||
if (dialog_id.get_type() == DialogType::Channel && messages_manager_->have_dialog_force(dialog_id)) {
|
if (dialog_id.get_type() == DialogType::Channel && messages_manager_->have_dialog_force(dialog_id, "leaveChat")) {
|
||||||
auto status = contacts_manager_->get_channel_status(dialog_id.get_channel_id());
|
auto status = contacts_manager_->get_channel_status(dialog_id.get_channel_id());
|
||||||
if (status.is_creator()) {
|
if (status.is_creator()) {
|
||||||
if (!status.is_member()) {
|
if (!status.is_member()) {
|
||||||
@ -6305,8 +6415,8 @@ void Td::on_request(uint64 id, const td_api::leaveChat &request) {
|
|||||||
td_api::make_object<td_api::chatMemberStatusCreator>(status.get_rank(), status.is_anonymous(), false);
|
td_api::make_object<td_api::chatMemberStatusCreator>(status.get_rank(), status.is_anonymous(), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
contacts_manager_->set_dialog_participant_status(dialog_id, contacts_manager_->get_my_id(), std::move(new_status),
|
contacts_manager_->set_dialog_participant_status(dialog_id, DialogId(contacts_manager_->get_my_id()),
|
||||||
std::move(promise));
|
std::move(new_status), std::move(promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, const td_api::addChatMember &request) {
|
void Td::on_request(uint64 id, const td_api::addChatMember &request) {
|
||||||
@ -6319,22 +6429,21 @@ void Td::on_request(uint64 id, const td_api::addChatMember &request) {
|
|||||||
void Td::on_request(uint64 id, const td_api::addChatMembers &request) {
|
void Td::on_request(uint64 id, const td_api::addChatMembers &request) {
|
||||||
CHECK_IS_USER();
|
CHECK_IS_USER();
|
||||||
CREATE_OK_REQUEST_PROMISE();
|
CREATE_OK_REQUEST_PROMISE();
|
||||||
vector<UserId> user_ids;
|
contacts_manager_->add_dialog_participants(DialogId(request.chat_id_), UserId::get_user_ids(request.user_ids_),
|
||||||
for (auto &user_id : request.user_ids_) {
|
std::move(promise));
|
||||||
user_ids.emplace_back(user_id);
|
|
||||||
}
|
|
||||||
contacts_manager_->add_dialog_participants(DialogId(request.chat_id_), user_ids, std::move(promise));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, td_api::setChatMemberStatus &request) {
|
void Td::on_request(uint64 id, td_api::setChatMemberStatus &request) {
|
||||||
CREATE_OK_REQUEST_PROMISE();
|
CREATE_OK_REQUEST_PROMISE();
|
||||||
contacts_manager_->set_dialog_participant_status(DialogId(request.chat_id_), UserId(request.user_id_),
|
contacts_manager_->set_dialog_participant_status(DialogId(request.chat_id_),
|
||||||
|
ContactsManager::get_participant_dialog_id(request.member_id_),
|
||||||
request.status_, std::move(promise));
|
request.status_, std::move(promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, const td_api::banChatMember &request) {
|
void Td::on_request(uint64 id, const td_api::banChatMember &request) {
|
||||||
CREATE_OK_REQUEST_PROMISE();
|
CREATE_OK_REQUEST_PROMISE();
|
||||||
contacts_manager_->ban_dialog_participant(DialogId(request.chat_id_), UserId(request.user_id_),
|
contacts_manager_->ban_dialog_participant(DialogId(request.chat_id_),
|
||||||
|
ContactsManager::get_participant_dialog_id(request.member_id_),
|
||||||
request.banned_until_date_, request.revoke_messages_, std::move(promise));
|
request.banned_until_date_, request.revoke_messages_, std::move(promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6360,8 +6469,9 @@ void Td::on_request(uint64 id, td_api::transferChatOwnership &request) {
|
|||||||
std::move(promise));
|
std::move(promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, const td_api::getChatMember &request) {
|
void Td::on_request(uint64 id, td_api::getChatMember &request) {
|
||||||
CREATE_REQUEST(GetChatMemberRequest, request.chat_id_, request.user_id_);
|
CREATE_REQUEST(GetChatMemberRequest, request.chat_id_,
|
||||||
|
ContactsManager::get_participant_dialog_id(request.member_id_));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, td_api::searchChatMembers &request) {
|
void Td::on_request(uint64 id, td_api::searchChatMembers &request) {
|
||||||
@ -6470,7 +6580,7 @@ void Td::on_request(uint64 id, td_api::getChatEventLog &request) {
|
|||||||
CHECK_IS_USER();
|
CHECK_IS_USER();
|
||||||
CLEAN_INPUT_STRING(request.query_);
|
CLEAN_INPUT_STRING(request.query_);
|
||||||
CREATE_REQUEST(GetChatEventLogRequest, request.chat_id_, std::move(request.query_), request.from_event_id_,
|
CREATE_REQUEST(GetChatEventLogRequest, request.chat_id_, std::move(request.query_), request.from_event_id_,
|
||||||
request.limit_, std::move(request.filters_), std::move(request.user_ids_));
|
request.limit_, std::move(request.filters_), UserId::get_user_ids(request.user_ids_));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, const td_api::clearAllDraftMessages &request) {
|
void Td::on_request(uint64 id, const td_api::clearAllDraftMessages &request) {
|
||||||
@ -6710,7 +6820,7 @@ void Td::on_request(uint64 id, td_api::searchContacts &request) {
|
|||||||
|
|
||||||
void Td::on_request(uint64 id, td_api::removeContacts &request) {
|
void Td::on_request(uint64 id, td_api::removeContacts &request) {
|
||||||
CHECK_IS_USER();
|
CHECK_IS_USER();
|
||||||
CREATE_REQUEST(RemoveContactsRequest, std::move(request.user_ids_));
|
CREATE_REQUEST(RemoveContactsRequest, UserId::get_user_ids(request.user_ids_));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, const td_api::getImportedContactCount &request) {
|
void Td::on_request(uint64 id, const td_api::getImportedContactCount &request) {
|
||||||
@ -7134,7 +7244,7 @@ void Td::on_request(uint64 id, const td_api::resetAllNotificationSettings &reque
|
|||||||
|
|
||||||
void Td::on_request(uint64 id, const td_api::getMapThumbnailFile &request) {
|
void Td::on_request(uint64 id, const td_api::getMapThumbnailFile &request) {
|
||||||
DialogId dialog_id(request.chat_id_);
|
DialogId dialog_id(request.chat_id_);
|
||||||
if (!messages_manager_->have_dialog_force(dialog_id)) {
|
if (!messages_manager_->have_dialog_force(dialog_id, "getMapThumbnailFile")) {
|
||||||
dialog_id = DialogId();
|
dialog_id = DialogId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7461,6 +7571,9 @@ void Td::on_request(uint64 id, td_api::setOption &request) {
|
|||||||
if (set_boolean_option("experiment_old_postponed_pts_updates_behavior")) {
|
if (set_boolean_option("experiment_old_postponed_pts_updates_behavior")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (set_boolean_option("enable_pull_based_backpressure")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
if (set_boolean_option("ignore_background_updates")) {
|
if (set_boolean_option("ignore_background_updates")) {
|
||||||
@ -7729,7 +7842,7 @@ void Td::on_request(uint64 id, td_api::answerShippingQuery &request) {
|
|||||||
CHECK_IS_BOT();
|
CHECK_IS_BOT();
|
||||||
CLEAN_INPUT_STRING(request.error_message_);
|
CLEAN_INPUT_STRING(request.error_message_);
|
||||||
CREATE_OK_REQUEST_PROMISE();
|
CREATE_OK_REQUEST_PROMISE();
|
||||||
answer_shipping_query(request.shipping_query_id_, std::move(request.shipping_options_), request.error_message_,
|
answer_shipping_query(this, request.shipping_query_id_, std::move(request.shipping_options_), request.error_message_,
|
||||||
std::move(promise));
|
std::move(promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7737,26 +7850,27 @@ void Td::on_request(uint64 id, td_api::answerPreCheckoutQuery &request) {
|
|||||||
CHECK_IS_BOT();
|
CHECK_IS_BOT();
|
||||||
CLEAN_INPUT_STRING(request.error_message_);
|
CLEAN_INPUT_STRING(request.error_message_);
|
||||||
CREATE_OK_REQUEST_PROMISE();
|
CREATE_OK_REQUEST_PROMISE();
|
||||||
answer_pre_checkout_query(request.pre_checkout_query_id_, request.error_message_, std::move(promise));
|
answer_pre_checkout_query(this, request.pre_checkout_query_id_, request.error_message_, std::move(promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, td_api::getBankCardInfo &request) {
|
void Td::on_request(uint64 id, td_api::getBankCardInfo &request) {
|
||||||
CHECK_IS_USER();
|
CHECK_IS_USER();
|
||||||
CLEAN_INPUT_STRING(request.bank_card_number_);
|
CLEAN_INPUT_STRING(request.bank_card_number_);
|
||||||
CREATE_REQUEST_PROMISE();
|
CREATE_REQUEST_PROMISE();
|
||||||
get_bank_card_info(request.bank_card_number_, std::move(promise));
|
get_bank_card_info(this, request.bank_card_number_, std::move(promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, const td_api::getPaymentForm &request) {
|
void Td::on_request(uint64 id, const td_api::getPaymentForm &request) {
|
||||||
CHECK_IS_USER();
|
CHECK_IS_USER();
|
||||||
CREATE_REQUEST_PROMISE();
|
CREATE_REQUEST_PROMISE();
|
||||||
messages_manager_->get_payment_form({DialogId(request.chat_id_), MessageId(request.message_id_)}, std::move(promise));
|
get_payment_form(this, {DialogId(request.chat_id_), MessageId(request.message_id_)}, request.theme_,
|
||||||
|
std::move(promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, td_api::validateOrderInfo &request) {
|
void Td::on_request(uint64 id, td_api::validateOrderInfo &request) {
|
||||||
CHECK_IS_USER();
|
CHECK_IS_USER();
|
||||||
CREATE_REQUEST_PROMISE();
|
CREATE_REQUEST_PROMISE();
|
||||||
messages_manager_->validate_order_info({DialogId(request.chat_id_), MessageId(request.message_id_)},
|
validate_order_info(this, {DialogId(request.chat_id_), MessageId(request.message_id_)},
|
||||||
std::move(request.order_info_), request.allow_save_, std::move(promise));
|
std::move(request.order_info_), request.allow_save_, std::move(promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7764,38 +7878,34 @@ void Td::on_request(uint64 id, td_api::sendPaymentForm &request) {
|
|||||||
CHECK_IS_USER();
|
CHECK_IS_USER();
|
||||||
CLEAN_INPUT_STRING(request.order_info_id_);
|
CLEAN_INPUT_STRING(request.order_info_id_);
|
||||||
CLEAN_INPUT_STRING(request.shipping_option_id_);
|
CLEAN_INPUT_STRING(request.shipping_option_id_);
|
||||||
if (request.credentials_ == nullptr) {
|
|
||||||
return send_error_raw(id, 400, "Input payments credentials must be non-empty");
|
|
||||||
}
|
|
||||||
CREATE_REQUEST_PROMISE();
|
CREATE_REQUEST_PROMISE();
|
||||||
messages_manager_->send_payment_form({DialogId(request.chat_id_), MessageId(request.message_id_)},
|
send_payment_form(this, {DialogId(request.chat_id_), MessageId(request.message_id_)}, request.payment_form_id_,
|
||||||
request.order_info_id_, request.shipping_option_id_, request.credentials_,
|
request.order_info_id_, request.shipping_option_id_, request.credentials_, request.tip_amount_,
|
||||||
std::move(promise));
|
std::move(promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, const td_api::getPaymentReceipt &request) {
|
void Td::on_request(uint64 id, const td_api::getPaymentReceipt &request) {
|
||||||
CHECK_IS_USER();
|
CHECK_IS_USER();
|
||||||
CREATE_REQUEST_PROMISE();
|
CREATE_REQUEST_PROMISE();
|
||||||
messages_manager_->get_payment_receipt({DialogId(request.chat_id_), MessageId(request.message_id_)},
|
get_payment_receipt(this, {DialogId(request.chat_id_), MessageId(request.message_id_)}, std::move(promise));
|
||||||
std::move(promise));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, const td_api::getSavedOrderInfo &request) {
|
void Td::on_request(uint64 id, const td_api::getSavedOrderInfo &request) {
|
||||||
CHECK_IS_USER();
|
CHECK_IS_USER();
|
||||||
CREATE_REQUEST_PROMISE();
|
CREATE_REQUEST_PROMISE();
|
||||||
get_saved_order_info(std::move(promise));
|
get_saved_order_info(this, std::move(promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, const td_api::deleteSavedOrderInfo &request) {
|
void Td::on_request(uint64 id, const td_api::deleteSavedOrderInfo &request) {
|
||||||
CHECK_IS_USER();
|
CHECK_IS_USER();
|
||||||
CREATE_OK_REQUEST_PROMISE();
|
CREATE_OK_REQUEST_PROMISE();
|
||||||
delete_saved_order_info(std::move(promise));
|
delete_saved_order_info(this, std::move(promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, const td_api::deleteSavedCredentials &request) {
|
void Td::on_request(uint64 id, const td_api::deleteSavedCredentials &request) {
|
||||||
CHECK_IS_USER();
|
CHECK_IS_USER();
|
||||||
CREATE_OK_REQUEST_PROMISE();
|
CREATE_OK_REQUEST_PROMISE();
|
||||||
delete_saved_credentials(std::move(promise));
|
delete_saved_credentials(this, std::move(promise));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Td::on_request(uint64 id, td_api::getPassportElement &request) {
|
void Td::on_request(uint64 id, td_api::getPassportElement &request) {
|
||||||
|
@ -249,7 +249,7 @@ class Td final : public NetQueryCallback {
|
|||||||
static td_api::object_ptr<td_api::Object> static_request(td_api::object_ptr<td_api::Function> function);
|
static td_api::object_ptr<td_api::Object> static_request(td_api::object_ptr<td_api::Function> function);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr const char *TDLIB_VERSION = "1.7.2";
|
static constexpr const char *TDLIB_VERSION = "1.7.4";
|
||||||
static constexpr int64 ONLINE_ALARM_ID = 0;
|
static constexpr int64 ONLINE_ALARM_ID = 0;
|
||||||
static constexpr int64 PING_SERVER_ALARM_ID = -1;
|
static constexpr int64 PING_SERVER_ALARM_ID = -1;
|
||||||
static constexpr int32 PING_SERVER_TIMEOUT = 300;
|
static constexpr int32 PING_SERVER_TIMEOUT = 300;
|
||||||
@ -525,6 +525,8 @@ class Td final : public NetQueryCallback {
|
|||||||
|
|
||||||
void on_request(uint64 id, const td_api::getFile &request);
|
void on_request(uint64 id, const td_api::getFile &request);
|
||||||
|
|
||||||
|
void on_request(uint64 id, const td_api::getChannelDifference &request);
|
||||||
|
|
||||||
void on_request(uint64 id, td_api::getRemoteFile &request);
|
void on_request(uint64 id, td_api::getRemoteFile &request);
|
||||||
|
|
||||||
void on_request(uint64 id, td_api::getStorageStatistics &request);
|
void on_request(uint64 id, td_api::getStorageStatistics &request);
|
||||||
@ -593,6 +595,8 @@ class Td final : public NetQueryCallback {
|
|||||||
|
|
||||||
void on_request(uint64 id, const td_api::openMessageContent &request);
|
void on_request(uint64 id, const td_api::openMessageContent &request);
|
||||||
|
|
||||||
|
void on_request(uint64 id, td_api::getExternalLinkInfo &request);
|
||||||
|
|
||||||
void on_request(uint64 id, td_api::getExternalLink &request);
|
void on_request(uint64 id, td_api::getExternalLink &request);
|
||||||
|
|
||||||
void on_request(uint64 id, const td_api::getChatHistory &request);
|
void on_request(uint64 id, const td_api::getChatHistory &request);
|
||||||
@ -715,28 +719,50 @@ class Td final : public NetQueryCallback {
|
|||||||
|
|
||||||
void on_request(uint64 id, td_api::sendCallDebugInformation &request);
|
void on_request(uint64 id, td_api::sendCallDebugInformation &request);
|
||||||
|
|
||||||
void on_request(uint64 id, const td_api::createVoiceChat &request);
|
void on_request(uint64 id, const td_api::getVoiceChatAvailableParticipants &request);
|
||||||
|
|
||||||
|
void on_request(uint64 id, const td_api::setVoiceChatDefaultParticipant &request);
|
||||||
|
|
||||||
|
void on_request(uint64 id, td_api::createVoiceChat &request);
|
||||||
|
|
||||||
void on_request(uint64 id, const td_api::getGroupCall &request);
|
void on_request(uint64 id, const td_api::getGroupCall &request);
|
||||||
|
|
||||||
|
void on_request(uint64 id, const td_api::startScheduledGroupCall &request);
|
||||||
|
|
||||||
|
void on_request(uint64 id, const td_api::toggleGroupCallEnabledStartNotification &request);
|
||||||
|
|
||||||
void on_request(uint64 id, td_api::joinGroupCall &request);
|
void on_request(uint64 id, td_api::joinGroupCall &request);
|
||||||
|
|
||||||
|
void on_request(uint64 id, td_api::setGroupCallTitle &request);
|
||||||
|
|
||||||
void on_request(uint64 id, const td_api::toggleGroupCallMuteNewParticipants &request);
|
void on_request(uint64 id, const td_api::toggleGroupCallMuteNewParticipants &request);
|
||||||
|
|
||||||
|
void on_request(uint64 id, const td_api::revokeGroupCallInviteLink &request);
|
||||||
|
|
||||||
void on_request(uint64 id, const td_api::inviteGroupCallParticipants &request);
|
void on_request(uint64 id, const td_api::inviteGroupCallParticipants &request);
|
||||||
|
|
||||||
|
void on_request(uint64 id, const td_api::getGroupCallInviteLink &request);
|
||||||
|
|
||||||
|
void on_request(uint64 id, td_api::startGroupCallRecording &request);
|
||||||
|
|
||||||
|
void on_request(uint64 id, const td_api::endGroupCallRecording &request);
|
||||||
|
|
||||||
void on_request(uint64 id, const td_api::setGroupCallParticipantIsSpeaking &request);
|
void on_request(uint64 id, const td_api::setGroupCallParticipantIsSpeaking &request);
|
||||||
|
|
||||||
void on_request(uint64 id, const td_api::toggleGroupCallParticipantIsMuted &request);
|
void on_request(uint64 id, const td_api::toggleGroupCallParticipantIsMuted &request);
|
||||||
|
|
||||||
void on_request(uint64 id, const td_api::setGroupCallParticipantVolumeLevel &request);
|
void on_request(uint64 id, const td_api::setGroupCallParticipantVolumeLevel &request);
|
||||||
|
|
||||||
|
void on_request(uint64 id, const td_api::toggleGroupCallParticipantIsHandRaised &request);
|
||||||
|
|
||||||
void on_request(uint64 id, const td_api::loadGroupCallParticipants &request);
|
void on_request(uint64 id, const td_api::loadGroupCallParticipants &request);
|
||||||
|
|
||||||
void on_request(uint64 id, const td_api::leaveGroupCall &request);
|
void on_request(uint64 id, const td_api::leaveGroupCall &request);
|
||||||
|
|
||||||
void on_request(uint64 id, const td_api::discardGroupCall &request);
|
void on_request(uint64 id, const td_api::discardGroupCall &request);
|
||||||
|
|
||||||
|
void on_request(uint64 id, const td_api::getGroupCallStreamSegment &request);
|
||||||
|
|
||||||
void on_request(uint64 id, const td_api::upgradeBasicGroupChatToSupergroupChat &request);
|
void on_request(uint64 id, const td_api::upgradeBasicGroupChatToSupergroupChat &request);
|
||||||
|
|
||||||
void on_request(uint64 id, const td_api::getChatListsToAddChat &request);
|
void on_request(uint64 id, const td_api::getChatListsToAddChat &request);
|
||||||
@ -807,7 +833,7 @@ class Td final : public NetQueryCallback {
|
|||||||
|
|
||||||
void on_request(uint64 id, td_api::transferChatOwnership &request);
|
void on_request(uint64 id, td_api::transferChatOwnership &request);
|
||||||
|
|
||||||
void on_request(uint64 id, const td_api::getChatMember &request);
|
void on_request(uint64 id, td_api::getChatMember &request);
|
||||||
|
|
||||||
void on_request(uint64 id, td_api::searchChatMembers &request);
|
void on_request(uint64 id, td_api::searchChatMembers &request);
|
||||||
|
|
||||||
|
@ -216,7 +216,7 @@ void UpdatesManager::fill_qts_gap(void *td) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void UpdatesManager::fill_get_difference_gap(void *td) {
|
void UpdatesManager::fill_get_difference_gap(void *td) {
|
||||||
fill_gap(td, "rare getDifference calls");
|
fill_gap(td, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdatesManager::fill_gap(void *td, const char *source) {
|
void UpdatesManager::fill_gap(void *td, const char *source) {
|
||||||
@ -226,7 +226,9 @@ void UpdatesManager::fill_gap(void *td, const char *source) {
|
|||||||
}
|
}
|
||||||
auto updates_manager = static_cast<Td *>(td)->updates_manager_.get();
|
auto updates_manager = static_cast<Td *>(td)->updates_manager_.get();
|
||||||
|
|
||||||
|
if (source != nullptr) {
|
||||||
LOG(WARNING) << "Filling gap in " << source << " by running getDifference";
|
LOG(WARNING) << "Filling gap in " << source << " by running getDifference";
|
||||||
|
}
|
||||||
|
|
||||||
updates_manager->get_difference("fill_gap");
|
updates_manager->get_difference("fill_gap");
|
||||||
}
|
}
|
||||||
@ -359,7 +361,7 @@ Promise<> UpdatesManager::set_pts(int32 pts, const char *source) {
|
|||||||
result = add_pts(pts);
|
result = add_pts(pts);
|
||||||
if (last_get_difference_pts_ < get_pts() - FORCED_GET_DIFFERENCE_PTS_DIFF) {
|
if (last_get_difference_pts_ < get_pts() - FORCED_GET_DIFFERENCE_PTS_DIFF) {
|
||||||
last_get_difference_pts_ = get_pts();
|
last_get_difference_pts_ = get_pts();
|
||||||
schedule_get_difference("set_pts");
|
schedule_get_difference("rare pts getDifference");
|
||||||
}
|
}
|
||||||
} else if (pts < get_pts()) {
|
} else if (pts < get_pts()) {
|
||||||
LOG(ERROR) << "Receive wrong pts = " << pts << " from " << source << ". Current pts = " << get_pts();
|
LOG(ERROR) << "Receive wrong pts = " << pts << " from " << source << ". Current pts = " << get_pts();
|
||||||
@ -621,6 +623,7 @@ bool UpdatesManager::is_acceptable_message(const telegram_api::Message *message_
|
|||||||
case telegram_api::messageActionSecureValuesSentMe::ID:
|
case telegram_api::messageActionSecureValuesSentMe::ID:
|
||||||
case telegram_api::messageActionContactSignUp::ID:
|
case telegram_api::messageActionContactSignUp::ID:
|
||||||
case telegram_api::messageActionGroupCall::ID:
|
case telegram_api::messageActionGroupCall::ID:
|
||||||
|
case telegram_api::messageActionGroupCallScheduled::ID:
|
||||||
case telegram_api::messageActionSetMessagesTTL::ID:
|
case telegram_api::messageActionSetMessagesTTL::ID:
|
||||||
break;
|
break;
|
||||||
case telegram_api::messageActionChatCreate::ID: {
|
case telegram_api::messageActionChatCreate::ID: {
|
||||||
@ -904,8 +907,8 @@ void UpdatesManager::on_failed_get_difference(Status &&error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void UpdatesManager::schedule_get_difference(const char *source) {
|
void UpdatesManager::schedule_get_difference(const char *source) {
|
||||||
VLOG(get_difference) << "Schedule getDifference from " << source;
|
|
||||||
if (!retry_timeout_.has_timeout()) {
|
if (!retry_timeout_.has_timeout()) {
|
||||||
|
LOG(WARNING) << "Schedule getDifference in " << retry_time_ << " seconds from " << source;
|
||||||
retry_timeout_.set_callback(std::move(fill_get_difference_gap));
|
retry_timeout_.set_callback(std::move(fill_get_difference_gap));
|
||||||
retry_timeout_.set_callback_data(static_cast<void *>(td_));
|
retry_timeout_.set_callback_data(static_cast<void *>(td_));
|
||||||
retry_timeout_.set_timeout_in(retry_time_);
|
retry_timeout_.set_timeout_in(retry_time_);
|
||||||
@ -913,6 +916,8 @@ void UpdatesManager::schedule_get_difference(const char *source) {
|
|||||||
if (retry_time_ > 60) {
|
if (retry_time_ > 60) {
|
||||||
retry_time_ = Random::fast(60, 80);
|
retry_time_ = Random::fast(60, 80);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
VLOG(get_difference) << "Schedule getDifference from " << source;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1084,7 +1089,7 @@ vector<DialogId> UpdatesManager::get_chat_dialog_ids(const telegram_api::Updates
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(ERROR) << "Can't find id of " << oneline(to_string(chat));
|
LOG(ERROR) << "Can't find identifier of " << oneline(to_string(chat));
|
||||||
}
|
}
|
||||||
return dialog_ids;
|
return dialog_ids;
|
||||||
}
|
}
|
||||||
@ -1653,6 +1658,7 @@ void UpdatesManager::add_pending_qts_update(tl_object_ptr<telegram_api::Update>
|
|||||||
CHECK(update != nullptr);
|
CHECK(update != nullptr);
|
||||||
if (qts <= 1) {
|
if (qts <= 1) {
|
||||||
LOG(ERROR) << "Receive wrong qts " << qts << " in " << oneline(to_string(update));
|
LOG(ERROR) << "Receive wrong qts " << qts << " in " << oneline(to_string(update));
|
||||||
|
schedule_get_difference("wrong qts");
|
||||||
promise.set_value(Unit());
|
promise.set_value(Unit());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1958,7 +1964,7 @@ void UpdatesManager::process_qts_update(tl_object_ptr<telegram_api::Update> &&up
|
|||||||
LOG(DEBUG) << "Process " << to_string(update_ptr);
|
LOG(DEBUG) << "Process " << to_string(update_ptr);
|
||||||
if (last_get_difference_qts_ < qts - FORCED_GET_DIFFERENCE_PTS_DIFF) {
|
if (last_get_difference_qts_ < qts - FORCED_GET_DIFFERENCE_PTS_DIFF) {
|
||||||
if (last_get_difference_qts_ != 0) {
|
if (last_get_difference_qts_ != 0) {
|
||||||
schedule_get_difference("process_qts_update");
|
schedule_get_difference("rare qts getDifference");
|
||||||
}
|
}
|
||||||
last_get_difference_qts_ = qts;
|
last_get_difference_qts_ = qts;
|
||||||
}
|
}
|
||||||
@ -2208,7 +2214,7 @@ void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateChannelTooLong>
|
|||||||
}
|
}
|
||||||
|
|
||||||
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateChannel> update, Promise<Unit> &&promise) {
|
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateChannel> update, Promise<Unit> &&promise) {
|
||||||
td_->contacts_manager_->invalidate_channel_full(ChannelId(update->channel_id_), false, false);
|
td_->contacts_manager_->invalidate_channel_full(ChannelId(update->channel_id_), false);
|
||||||
promise.set_value(Unit());
|
promise.set_value(Unit());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2511,15 +2517,15 @@ int32 UpdatesManager::get_update_qts(const telegram_api::Update *update) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateUserTyping> update, Promise<Unit> &&promise) {
|
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateUserTyping> update, Promise<Unit> &&promise) {
|
||||||
UserId user_id(update->user_id_);
|
DialogId dialog_id(UserId(update->user_id_));
|
||||||
td_->messages_manager_->on_user_dialog_action(DialogId(user_id), MessageId(), user_id,
|
td_->messages_manager_->on_user_dialog_action(dialog_id, MessageId(), dialog_id,
|
||||||
DialogAction(std::move(update->action_)), get_short_update_date());
|
DialogAction(std::move(update->action_)), get_short_update_date());
|
||||||
promise.set_value(Unit());
|
promise.set_value(Unit());
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateChatUserTyping> update, Promise<Unit> &&promise) {
|
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateChatUserTyping> update, Promise<Unit> &&promise) {
|
||||||
td_->messages_manager_->on_user_dialog_action(DialogId(ChatId(update->chat_id_)), MessageId(),
|
td_->messages_manager_->on_user_dialog_action(DialogId(ChatId(update->chat_id_)), MessageId(),
|
||||||
UserId(update->user_id_), DialogAction(std::move(update->action_)),
|
DialogId(update->from_id_), DialogAction(std::move(update->action_)),
|
||||||
get_short_update_date());
|
get_short_update_date());
|
||||||
promise.set_value(Unit());
|
promise.set_value(Unit());
|
||||||
}
|
}
|
||||||
@ -2530,7 +2536,7 @@ void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateChannelUserTypi
|
|||||||
top_thread_message_id = MessageId(ServerMessageId(update->top_msg_id_));
|
top_thread_message_id = MessageId(ServerMessageId(update->top_msg_id_));
|
||||||
}
|
}
|
||||||
td_->messages_manager_->on_user_dialog_action(DialogId(ChannelId(update->channel_id_)), top_thread_message_id,
|
td_->messages_manager_->on_user_dialog_action(DialogId(ChannelId(update->channel_id_)), top_thread_message_id,
|
||||||
UserId(update->user_id_), DialogAction(std::move(update->action_)),
|
DialogId(update->from_id_), DialogAction(std::move(update->action_)),
|
||||||
get_short_update_date());
|
get_short_update_date());
|
||||||
promise.set_value(Unit());
|
promise.set_value(Unit());
|
||||||
}
|
}
|
||||||
@ -2538,7 +2544,7 @@ void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateChannelUserTypi
|
|||||||
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateEncryptedChatTyping> update, Promise<Unit> &&promise) {
|
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateEncryptedChatTyping> update, Promise<Unit> &&promise) {
|
||||||
SecretChatId secret_chat_id(update->chat_id_);
|
SecretChatId secret_chat_id(update->chat_id_);
|
||||||
UserId user_id = td_->contacts_manager_->get_secret_chat_user_id(secret_chat_id);
|
UserId user_id = td_->contacts_manager_->get_secret_chat_user_id(secret_chat_id);
|
||||||
td_->messages_manager_->on_user_dialog_action(DialogId(secret_chat_id), MessageId(), user_id,
|
td_->messages_manager_->on_user_dialog_action(DialogId(secret_chat_id), MessageId(), DialogId(user_id),
|
||||||
DialogAction::get_typing_action(), get_short_update_date());
|
DialogAction::get_typing_action(), get_short_update_date());
|
||||||
promise.set_value(Unit());
|
promise.set_value(Unit());
|
||||||
}
|
}
|
||||||
@ -2818,9 +2824,9 @@ void UpdatesManager::on_update(tl_object_ptr<telegram_api::updatePhoneCallSignal
|
|||||||
|
|
||||||
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateGroupCall> update, Promise<Unit> &&promise) {
|
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateGroupCall> update, Promise<Unit> &&promise) {
|
||||||
DialogId dialog_id(ChatId(update->chat_id_));
|
DialogId dialog_id(ChatId(update->chat_id_));
|
||||||
if (!td_->messages_manager_->have_dialog_force(dialog_id)) {
|
if (!td_->messages_manager_->have_dialog_force(dialog_id, "updateGroupCall")) {
|
||||||
dialog_id = DialogId(ChannelId(update->chat_id_));
|
dialog_id = DialogId(ChannelId(update->chat_id_));
|
||||||
if (!td_->messages_manager_->have_dialog_force(dialog_id)) {
|
if (!td_->messages_manager_->have_dialog_force(dialog_id, "updateGroupCall")) {
|
||||||
dialog_id = DialogId();
|
dialog_id = DialogId();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2831,7 +2837,7 @@ void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateGroupCall> upda
|
|||||||
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateGroupCallParticipants> update,
|
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateGroupCallParticipants> update,
|
||||||
Promise<Unit> &&promise) {
|
Promise<Unit> &&promise) {
|
||||||
send_closure(G()->group_call_manager(), &GroupCallManager::on_update_group_call_participants,
|
send_closure(G()->group_call_manager(), &GroupCallManager::on_update_group_call_participants,
|
||||||
InputGroupCallId(update->call_), std::move(update->participants_), update->version_);
|
InputGroupCallId(update->call_), std::move(update->participants_), update->version_, false);
|
||||||
promise.set_value(Unit());
|
promise.set_value(Unit());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +30,24 @@ class UserId {
|
|||||||
template <class T, typename = std::enable_if_t<std::is_convertible<T, int32>::value>>
|
template <class T, typename = std::enable_if_t<std::is_convertible<T, int32>::value>>
|
||||||
UserId(T user_id) = delete;
|
UserId(T user_id) = delete;
|
||||||
|
|
||||||
|
static vector<UserId> get_user_ids(const vector<int32> &input_user_ids) {
|
||||||
|
vector<UserId> user_ids;
|
||||||
|
user_ids.reserve(input_user_ids.size());
|
||||||
|
for (auto &input_user_id : input_user_ids) {
|
||||||
|
user_ids.emplace_back(input_user_id);
|
||||||
|
}
|
||||||
|
return user_ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
static vector<int32> get_input_user_ids(const vector<UserId> &user_ids) {
|
||||||
|
vector<int32> input_user_ids;
|
||||||
|
input_user_ids.reserve(user_ids.size());
|
||||||
|
for (auto &user_id : user_ids) {
|
||||||
|
input_user_ids.emplace_back(user_id.get());
|
||||||
|
}
|
||||||
|
return input_user_ids;
|
||||||
|
}
|
||||||
|
|
||||||
bool is_valid() const {
|
bool is_valid() const {
|
||||||
return id > 0;
|
return id > 0;
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,11 @@ SecretInputMedia Venue::get_secret_input_media_venue() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tl_object_ptr<telegram_api::inputBotInlineMessageMediaVenue> Venue::get_input_bot_inline_message_media_venue(
|
tl_object_ptr<telegram_api::inputBotInlineMessageMediaVenue> Venue::get_input_bot_inline_message_media_venue(
|
||||||
int32 flags, tl_object_ptr<telegram_api::ReplyMarkup> &&reply_markup) const {
|
tl_object_ptr<telegram_api::ReplyMarkup> &&reply_markup) const {
|
||||||
|
int32 flags = 0;
|
||||||
|
if (reply_markup != nullptr) {
|
||||||
|
flags |= telegram_api::inputBotInlineMessageMediaVenue::REPLY_MARKUP_MASK;
|
||||||
|
}
|
||||||
return make_tl_object<telegram_api::inputBotInlineMessageMediaVenue>(
|
return make_tl_object<telegram_api::inputBotInlineMessageMediaVenue>(
|
||||||
flags, location_.get_input_geo_point(), title_, address_, provider_, id_, type_, std::move(reply_markup));
|
flags, location_.get_input_geo_point(), title_, address_, provider_, id_, type_, std::move(reply_markup));
|
||||||
}
|
}
|
||||||
@ -84,7 +88,7 @@ bool operator!=(const Venue &lhs, const Venue &rhs) {
|
|||||||
StringBuilder &operator<<(StringBuilder &string_builder, const Venue &venue) {
|
StringBuilder &operator<<(StringBuilder &string_builder, const Venue &venue) {
|
||||||
return string_builder << "Venue[location = " << venue.location_ << ", title = " << venue.title_
|
return string_builder << "Venue[location = " << venue.location_ << ", title = " << venue.title_
|
||||||
<< ", address = " << venue.address_ << ", provider = " << venue.provider_
|
<< ", address = " << venue.address_ << ", provider = " << venue.provider_
|
||||||
<< ", id = " << venue.id_ << ", type = " << venue.type_ << "]";
|
<< ", ID = " << venue.id_ << ", type = " << venue.type_ << "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<Venue> process_input_message_venue(tl_object_ptr<td_api::InputMessageContent> &&input_message_content) {
|
Result<Venue> process_input_message_venue(tl_object_ptr<td_api::InputMessageContent> &&input_message_content) {
|
||||||
|
@ -54,9 +54,8 @@ class Venue {
|
|||||||
|
|
||||||
SecretInputMedia get_secret_input_media_venue() const;
|
SecretInputMedia get_secret_input_media_venue() const;
|
||||||
|
|
||||||
// TODO very strange function
|
|
||||||
tl_object_ptr<telegram_api::inputBotInlineMessageMediaVenue> get_input_bot_inline_message_media_venue(
|
tl_object_ptr<telegram_api::inputBotInlineMessageMediaVenue> get_input_bot_inline_message_media_venue(
|
||||||
int32 flags, tl_object_ptr<telegram_api::ReplyMarkup> &&reply_markup) const;
|
tl_object_ptr<telegram_api::ReplyMarkup> &&reply_markup) const;
|
||||||
|
|
||||||
template <class StorerT>
|
template <class StorerT>
|
||||||
void store(StorerT &storer) const {
|
void store(StorerT &storer) const {
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
|
|
||||||
constexpr int32 MTPROTO_LAYER = 124;
|
constexpr int32 MTPROTO_LAYER = 127;
|
||||||
|
|
||||||
enum class Version : int32 {
|
enum class Version : int32 {
|
||||||
Initial, // 0
|
Initial, // 0
|
||||||
@ -42,6 +42,7 @@ enum class Version : int32 {
|
|||||||
AddPhotoProgressiveSizes,
|
AddPhotoProgressiveSizes,
|
||||||
AddLiveLocationHeading,
|
AddLiveLocationHeading,
|
||||||
AddLiveLocationProximityAlertDistance, // 30
|
AddLiveLocationProximityAlertDistance, // 30
|
||||||
|
SupportBannedChannels,
|
||||||
Next
|
Next
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include "td/telegram/files/FileManager.h"
|
#include "td/telegram/files/FileManager.h"
|
||||||
#include "td/telegram/SecretChatActor.h"
|
#include "td/telegram/SecretChatActor.h"
|
||||||
|
#include "td/telegram/ConfigShared.h"
|
||||||
#include "td/telegram/Td.h"
|
#include "td/telegram/Td.h"
|
||||||
|
|
||||||
#include "td/utils/logging.h"
|
#include "td/utils/logging.h"
|
||||||
@ -124,7 +125,7 @@ FileId VideoNotesManager::dup_video_note(FileId new_id, FileId old_id) {
|
|||||||
|
|
||||||
bool VideoNotesManager::merge_video_notes(FileId new_id, FileId old_id, bool can_delete_old) {
|
bool VideoNotesManager::merge_video_notes(FileId new_id, FileId old_id, bool can_delete_old) {
|
||||||
if (!old_id.is_valid()) {
|
if (!old_id.is_valid()) {
|
||||||
LOG(ERROR) << "Old file id is invalid";
|
LOG(ERROR) << "Old file identifier is invalid";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,7 +171,11 @@ void VideoNotesManager::create_video_note(FileId file_id, string minithumbnail,
|
|||||||
} else {
|
} else {
|
||||||
LOG(INFO) << "Receive wrong video note dimensions " << dimensions;
|
LOG(INFO) << "Receive wrong video note dimensions " << dimensions;
|
||||||
}
|
}
|
||||||
|
if (G()->shared_config().get_option_boolean("disable_minithumbnails")) {
|
||||||
|
v->minithumbnail = "";
|
||||||
|
} else {
|
||||||
v->minithumbnail = std::move(minithumbnail);
|
v->minithumbnail = std::move(minithumbnail);
|
||||||
|
}
|
||||||
v->thumbnail = std::move(thumbnail);
|
v->thumbnail = std::move(thumbnail);
|
||||||
on_get_video_note(std::move(v), replace);
|
on_get_video_note(std::move(v), replace);
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "td/telegram/secret_api.h"
|
#include "td/telegram/secret_api.h"
|
||||||
#include "td/telegram/td_api.h"
|
#include "td/telegram/td_api.h"
|
||||||
#include "td/telegram/telegram_api.h"
|
#include "td/telegram/telegram_api.h"
|
||||||
|
#include "td/telegram/ConfigShared.h"
|
||||||
|
|
||||||
#include "td/telegram/files/FileManager.h"
|
#include "td/telegram/files/FileManager.h"
|
||||||
#include "td/telegram/Td.h"
|
#include "td/telegram/Td.h"
|
||||||
@ -164,7 +165,7 @@ FileId VideosManager::dup_video(FileId new_id, FileId old_id) {
|
|||||||
|
|
||||||
bool VideosManager::merge_videos(FileId new_id, FileId old_id, bool can_delete_old) {
|
bool VideosManager::merge_videos(FileId new_id, FileId old_id, bool can_delete_old) {
|
||||||
if (!old_id.is_valid()) {
|
if (!old_id.is_valid()) {
|
||||||
LOG(ERROR) << "Old file id is invalid";
|
LOG(ERROR) << "Old file identifier is invalid";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,7 +216,11 @@ void VideosManager::create_video(FileId file_id, string minithumbnail, PhotoSize
|
|||||||
v->mime_type = std::move(mime_type);
|
v->mime_type = std::move(mime_type);
|
||||||
v->duration = max(duration, 0);
|
v->duration = max(duration, 0);
|
||||||
v->dimensions = dimensions;
|
v->dimensions = dimensions;
|
||||||
|
if (G()->shared_config().get_option_boolean("disable_minithumbnails")) {
|
||||||
|
v->minithumbnail = "";
|
||||||
|
} else {
|
||||||
v->minithumbnail = std::move(minithumbnail);
|
v->minithumbnail = std::move(minithumbnail);
|
||||||
|
}
|
||||||
v->thumbnail = std::move(thumbnail);
|
v->thumbnail = std::move(thumbnail);
|
||||||
v->animated_thumbnail = std::move(animated_thumbnail);
|
v->animated_thumbnail = std::move(animated_thumbnail);
|
||||||
v->supports_streaming = supports_streaming;
|
v->supports_streaming = supports_streaming;
|
||||||
|
@ -92,7 +92,7 @@ FileId VoiceNotesManager::dup_voice_note(FileId new_id, FileId old_id) {
|
|||||||
|
|
||||||
bool VoiceNotesManager::merge_voice_notes(FileId new_id, FileId old_id, bool can_delete_old) {
|
bool VoiceNotesManager::merge_voice_notes(FileId new_id, FileId old_id, bool can_delete_old) {
|
||||||
if (!old_id.is_valid()) {
|
if (!old_id.is_valid()) {
|
||||||
LOG(ERROR) << "Old file id is invalid";
|
LOG(ERROR) << "Old file identifier is invalid";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1074,7 +1074,7 @@ WebPageId WebPagesManager::get_web_page_by_url(const string &url) const {
|
|||||||
return WebPageId();
|
return WebPageId();
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG(INFO) << "Get web page id for the url \"" << url << '"';
|
LOG(INFO) << "Get web page identifier for the url \"" << url << '"';
|
||||||
|
|
||||||
auto it = url_to_web_page_id_.find(url);
|
auto it = url_to_web_page_id_.find(url);
|
||||||
if (it != url_to_web_page_id_.end()) {
|
if (it != url_to_web_page_id_.end()) {
|
||||||
@ -1085,7 +1085,7 @@ WebPageId WebPagesManager::get_web_page_by_url(const string &url) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
WebPageId WebPagesManager::get_web_page_by_url(const string &url, Promise<Unit> &&promise) {
|
WebPageId WebPagesManager::get_web_page_by_url(const string &url, Promise<Unit> &&promise) {
|
||||||
LOG(INFO) << "Trying to get web page id for the url \"" << url << '"';
|
LOG(INFO) << "Trying to get web page identifier for the url \"" << url << '"';
|
||||||
|
|
||||||
auto it = url_to_web_page_id_.find(url);
|
auto it = url_to_web_page_id_.find(url);
|
||||||
if (it != url_to_web_page_id_.end()) {
|
if (it != url_to_web_page_id_.end()) {
|
||||||
|
@ -295,7 +295,7 @@ class CliClient final : public Actor {
|
|||||||
void update_option(const td_api::updateOption &option) {
|
void update_option(const td_api::updateOption &option) {
|
||||||
if (option.name_ == "my_id" && option.value_->get_id() == td_api::optionValueInteger::ID) {
|
if (option.name_ == "my_id" && option.value_->get_id() == td_api::optionValueInteger::ID) {
|
||||||
my_id_ = static_cast<int32>(static_cast<const td_api::optionValueInteger *>(option.value_.get())->value_);
|
my_id_ = static_cast<int32>(static_cast<const td_api::optionValueInteger *>(option.value_.get())->value_);
|
||||||
LOG(INFO) << "Set my id to " << my_id_;
|
LOG(INFO) << "Set my user identifier to " << my_id_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1829,7 +1829,9 @@ class CliClient final : public Actor {
|
|||||||
string chat_id;
|
string chat_id;
|
||||||
string message_id;
|
string message_id;
|
||||||
get_args(args, chat_id, message_id);
|
get_args(args, chat_id, message_id);
|
||||||
send_request(td_api::make_object<td_api::getPaymentForm>(as_chat_id(chat_id), as_message_id(message_id)));
|
send_request(td_api::make_object<td_api::getPaymentForm>(
|
||||||
|
as_chat_id(chat_id), as_message_id(message_id),
|
||||||
|
td_api::make_object<td_api::paymentFormTheme>(0, -1, 256, 65536, 123456789, 65535)));
|
||||||
} else if (op == "voi") {
|
} else if (op == "voi") {
|
||||||
string chat_id;
|
string chat_id;
|
||||||
string message_id;
|
string message_id;
|
||||||
@ -1840,23 +1842,28 @@ class CliClient final : public Actor {
|
|||||||
} else if (op == "spfs") {
|
} else if (op == "spfs") {
|
||||||
string chat_id;
|
string chat_id;
|
||||||
string message_id;
|
string message_id;
|
||||||
|
int64 tip_amount;
|
||||||
|
int64 payment_form_id;
|
||||||
string order_info_id;
|
string order_info_id;
|
||||||
string shipping_option_id;
|
string shipping_option_id;
|
||||||
string saved_credentials_id;
|
string saved_credentials_id;
|
||||||
get_args(args, chat_id, message_id, order_info_id, shipping_option_id, saved_credentials_id);
|
get_args(args, chat_id, message_id, tip_amount, payment_form_id, order_info_id, shipping_option_id,
|
||||||
|
saved_credentials_id);
|
||||||
send_request(td_api::make_object<td_api::sendPaymentForm>(
|
send_request(td_api::make_object<td_api::sendPaymentForm>(
|
||||||
as_chat_id(chat_id), as_message_id(message_id), order_info_id, shipping_option_id,
|
as_chat_id(chat_id), as_message_id(message_id), payment_form_id, order_info_id, shipping_option_id,
|
||||||
td_api::make_object<td_api::inputCredentialsSaved>(saved_credentials_id)));
|
td_api::make_object<td_api::inputCredentialsSaved>(saved_credentials_id), tip_amount));
|
||||||
} else if (op == "spfn") {
|
} else if (op == "spfn") {
|
||||||
string chat_id;
|
string chat_id;
|
||||||
string message_id;
|
string message_id;
|
||||||
|
int64 tip_amount;
|
||||||
|
int64 payment_form_id;
|
||||||
string order_info_id;
|
string order_info_id;
|
||||||
string shipping_option_id;
|
string shipping_option_id;
|
||||||
string data;
|
string data;
|
||||||
get_args(args, chat_id, message_id, order_info_id, shipping_option_id, data);
|
get_args(args, chat_id, message_id, tip_amount, payment_form_id, order_info_id, shipping_option_id, data);
|
||||||
send_request(td_api::make_object<td_api::sendPaymentForm>(
|
send_request(td_api::make_object<td_api::sendPaymentForm>(
|
||||||
as_chat_id(chat_id), as_message_id(message_id), order_info_id, shipping_option_id,
|
as_chat_id(chat_id), as_message_id(message_id), payment_form_id, order_info_id, shipping_option_id,
|
||||||
td_api::make_object<td_api::inputCredentialsNew>(data, true)));
|
td_api::make_object<td_api::inputCredentialsNew>(data, true), tip_amount));
|
||||||
} else if (op == "gpre") {
|
} else if (op == "gpre") {
|
||||||
string chat_id;
|
string chat_id;
|
||||||
string message_id;
|
string message_id;
|
||||||
@ -2455,9 +2462,9 @@ class CliClient final : public Actor {
|
|||||||
get_chat_members_filter(filter)));
|
get_chat_members_filter(filter)));
|
||||||
} else if (op == "gcm") {
|
} else if (op == "gcm") {
|
||||||
string chat_id;
|
string chat_id;
|
||||||
string user_id;
|
string member_id;
|
||||||
get_args(args, chat_id, user_id);
|
get_args(args, chat_id, member_id);
|
||||||
send_request(td_api::make_object<td_api::getChatMember>(as_chat_id(chat_id), as_user_id(user_id)));
|
send_request(td_api::make_object<td_api::getChatMember>(as_chat_id(chat_id), as_message_sender(member_id)));
|
||||||
} else if (op == "GetChatAdministrators") {
|
} else if (op == "GetChatAdministrators") {
|
||||||
string chat_id = args;
|
string chat_id = args;
|
||||||
send_request(td_api::make_object<td_api::getChatAdministrators>(as_chat_id(chat_id)));
|
send_request(td_api::make_object<td_api::getChatAdministrators>(as_chat_id(chat_id)));
|
||||||
@ -2668,23 +2675,52 @@ class CliClient final : public Actor {
|
|||||||
as_call_id(call_id), rating, "Wow, such good call! (TDLib test)", std::move(problems)));
|
as_call_id(call_id), rating, "Wow, such good call! (TDLib test)", std::move(problems)));
|
||||||
} else if (op == "scdi" || op == "SendCallDebugInformation") {
|
} else if (op == "scdi" || op == "SendCallDebugInformation") {
|
||||||
send_request(td_api::make_object<td_api::sendCallDebugInformation>(as_call_id(args), "{}"));
|
send_request(td_api::make_object<td_api::sendCallDebugInformation>(as_call_id(args), "{}"));
|
||||||
|
} else if (op == "gvcap") {
|
||||||
|
send_request(td_api::make_object<td_api::getVoiceChatAvailableParticipants>(as_chat_id(args)));
|
||||||
|
} else if (op == "svcdp") {
|
||||||
|
string chat_id;
|
||||||
|
string participant_id;
|
||||||
|
get_args(args, chat_id, participant_id);
|
||||||
|
send_request(td_api::make_object<td_api::setVoiceChatDefaultParticipant>(as_chat_id(chat_id),
|
||||||
|
as_message_sender(participant_id)));
|
||||||
} else if (op == "cvc") {
|
} else if (op == "cvc") {
|
||||||
send_request(td_api::make_object<td_api::createVoiceChat>(as_chat_id(args)));
|
string chat_id;
|
||||||
|
string title;
|
||||||
|
int32 start_date;
|
||||||
|
get_args(args, chat_id, title, start_date);
|
||||||
|
send_request(td_api::make_object<td_api::createVoiceChat>(as_chat_id(chat_id), title, start_date));
|
||||||
} else if (op == "ggc") {
|
} else if (op == "ggc") {
|
||||||
send_request(td_api::make_object<td_api::getGroupCall>(as_group_call_id(args)));
|
send_request(td_api::make_object<td_api::getGroupCall>(as_group_call_id(args)));
|
||||||
|
} else if (op == "ggcss") {
|
||||||
|
send_request(td_api::make_object<td_api::getGroupCallStreamSegment>(as_group_call_id(args),
|
||||||
|
(std::time(nullptr) - 5) * 1000, 0));
|
||||||
|
} else if (op == "ssgc") {
|
||||||
|
send_request(td_api::make_object<td_api::startScheduledGroupCall>(as_group_call_id(args)));
|
||||||
|
} else if (op == "tgcesn" || op == "tgcesne") {
|
||||||
|
send_request(td_api::make_object<td_api::toggleGroupCallEnabledStartNotification>(as_group_call_id(args),
|
||||||
|
op == "tgcesne"));
|
||||||
} else if (op == "jgc") {
|
} else if (op == "jgc") {
|
||||||
|
string group_call_id;
|
||||||
|
string participant_id;
|
||||||
|
string invite_hash;
|
||||||
|
get_args(args, group_call_id, participant_id, invite_hash);
|
||||||
vector<td_api::object_ptr<td_api::groupCallPayloadFingerprint>> fingerprints;
|
vector<td_api::object_ptr<td_api::groupCallPayloadFingerprint>> fingerprints;
|
||||||
fingerprints.push_back(td_api::make_object<td_api::groupCallPayloadFingerprint>("hash", "setup", "fingerprint"));
|
fingerprints.push_back(td_api::make_object<td_api::groupCallPayloadFingerprint>("hash", "setup", "fingerprint"));
|
||||||
fingerprints.push_back(td_api::make_object<td_api::groupCallPayloadFingerprint>("h2", "s2", "fingerprint2"));
|
fingerprints.push_back(td_api::make_object<td_api::groupCallPayloadFingerprint>("h2", "s2", "fingerprint2"));
|
||||||
send_request(td_api::make_object<td_api::joinGroupCall>(
|
send_request(td_api::make_object<td_api::joinGroupCall>(
|
||||||
as_group_call_id(args),
|
as_group_call_id(group_call_id), as_message_sender(participant_id),
|
||||||
td_api::make_object<td_api::groupCallPayload>("ufrag", "pwd", std::move(fingerprints)), group_call_source_,
|
td_api::make_object<td_api::groupCallPayload>("ufrag", "pwd", std::move(fingerprints)), group_call_source_,
|
||||||
true));
|
true, invite_hash));
|
||||||
} else if (op == "jgcc") {
|
} else if (op == "sgct") {
|
||||||
send_request(td_api::make_object<td_api::joinGroupCall>(as_group_call_id(args), nullptr, 0, true));
|
string chat_id;
|
||||||
|
string title;
|
||||||
|
get_args(args, chat_id, title);
|
||||||
|
send_request(td_api::make_object<td_api::setGroupCallTitle>(as_group_call_id(chat_id), title));
|
||||||
} else if (op == "tgcmnp" || op == "tgcmnpe") {
|
} else if (op == "tgcmnp" || op == "tgcmnpe") {
|
||||||
send_request(
|
send_request(
|
||||||
td_api::make_object<td_api::toggleGroupCallMuteNewParticipants>(as_group_call_id(args), op == "tgcmnpe"));
|
td_api::make_object<td_api::toggleGroupCallMuteNewParticipants>(as_group_call_id(args), op == "tgcmnpe"));
|
||||||
|
} else if (op == "rgcil") {
|
||||||
|
send_request(td_api::make_object<td_api::revokeGroupCallInviteLink>(as_group_call_id(args)));
|
||||||
} else if (op == "sgcpis") {
|
} else if (op == "sgcpis") {
|
||||||
string group_call_id;
|
string group_call_id;
|
||||||
int32 source;
|
int32 source;
|
||||||
@ -2698,20 +2734,41 @@ class CliClient final : public Actor {
|
|||||||
get_args(args, group_call_id, user_ids);
|
get_args(args, group_call_id, user_ids);
|
||||||
send_request(td_api::make_object<td_api::inviteGroupCallParticipants>(as_group_call_id(group_call_id),
|
send_request(td_api::make_object<td_api::inviteGroupCallParticipants>(as_group_call_id(group_call_id),
|
||||||
as_user_ids(user_ids)));
|
as_user_ids(user_ids)));
|
||||||
|
} else if (op == "ggcil") {
|
||||||
|
string group_call_id;
|
||||||
|
bool can_self_unmute;
|
||||||
|
get_args(args, group_call_id, can_self_unmute);
|
||||||
|
send_request(
|
||||||
|
td_api::make_object<td_api::getGroupCallInviteLink>(as_group_call_id(group_call_id), can_self_unmute));
|
||||||
|
} else if (op == "sgcr") {
|
||||||
|
string chat_id;
|
||||||
|
string title;
|
||||||
|
get_args(args, chat_id, title);
|
||||||
|
send_request(td_api::make_object<td_api::startGroupCallRecording>(as_group_call_id(chat_id), title));
|
||||||
|
} else if (op == "egcr") {
|
||||||
|
string chat_id = args;
|
||||||
|
send_request(td_api::make_object<td_api::endGroupCallRecording>(as_group_call_id(chat_id)));
|
||||||
} else if (op == "tgcpim") {
|
} else if (op == "tgcpim") {
|
||||||
string group_call_id;
|
string group_call_id;
|
||||||
string user_id;
|
string participant_id;
|
||||||
bool is_muted;
|
bool is_muted;
|
||||||
get_args(args, group_call_id, user_id, is_muted);
|
get_args(args, group_call_id, participant_id, is_muted);
|
||||||
send_request(td_api::make_object<td_api::toggleGroupCallParticipantIsMuted>(as_group_call_id(group_call_id),
|
send_request(td_api::make_object<td_api::toggleGroupCallParticipantIsMuted>(
|
||||||
as_user_id(user_id), is_muted));
|
as_group_call_id(group_call_id), as_message_sender(participant_id), is_muted));
|
||||||
} else if (op == "sgcpvl") {
|
} else if (op == "sgcpvl") {
|
||||||
string group_call_id;
|
string group_call_id;
|
||||||
string user_id;
|
string participant_id;
|
||||||
int32 volume_level;
|
int32 volume_level;
|
||||||
get_args(args, group_call_id, user_id, volume_level);
|
get_args(args, group_call_id, participant_id, volume_level);
|
||||||
send_request(td_api::make_object<td_api::setGroupCallParticipantVolumeLevel>(as_group_call_id(group_call_id),
|
send_request(td_api::make_object<td_api::setGroupCallParticipantVolumeLevel>(
|
||||||
as_user_id(user_id), volume_level));
|
as_group_call_id(group_call_id), as_message_sender(participant_id), volume_level));
|
||||||
|
} else if (op == "tgcpihr") {
|
||||||
|
string group_call_id;
|
||||||
|
string participant_id;
|
||||||
|
bool is_hand_raised;
|
||||||
|
get_args(args, group_call_id, participant_id, is_hand_raised);
|
||||||
|
send_request(td_api::make_object<td_api::toggleGroupCallParticipantIsHandRaised>(
|
||||||
|
as_group_call_id(group_call_id), as_message_sender(participant_id), is_hand_raised));
|
||||||
} else if (op == "lgcp") {
|
} else if (op == "lgcp") {
|
||||||
string group_call_id;
|
string group_call_id;
|
||||||
string limit;
|
string limit;
|
||||||
@ -3614,11 +3671,11 @@ class CliClient final : public Actor {
|
|||||||
send_request(td_api::make_object<td_api::addChatMembers>(as_chat_id(chat_id), as_user_ids(user_ids)));
|
send_request(td_api::make_object<td_api::addChatMembers>(as_chat_id(chat_id), as_user_ids(user_ids)));
|
||||||
} else if (op == "bcm") {
|
} else if (op == "bcm") {
|
||||||
string chat_id;
|
string chat_id;
|
||||||
string user_id;
|
string member_id;
|
||||||
int32 banned_until_date;
|
int32 banned_until_date;
|
||||||
bool revoke_messages;
|
bool revoke_messages;
|
||||||
get_args(args, chat_id, user_id, banned_until_date, revoke_messages);
|
get_args(args, chat_id, member_id, banned_until_date, revoke_messages);
|
||||||
send_request(td_api::make_object<td_api::banChatMember>(as_chat_id(chat_id), as_user_id(user_id),
|
send_request(td_api::make_object<td_api::banChatMember>(as_chat_id(chat_id), as_message_sender(member_id),
|
||||||
banned_until_date, revoke_messages));
|
banned_until_date, revoke_messages));
|
||||||
} else if (op == "spolla") {
|
} else if (op == "spolla") {
|
||||||
string chat_id;
|
string chat_id;
|
||||||
@ -3647,10 +3704,10 @@ class CliClient final : public Actor {
|
|||||||
|
|
||||||
if (op == "scms") {
|
if (op == "scms") {
|
||||||
string chat_id;
|
string chat_id;
|
||||||
string user_id;
|
string member_id;
|
||||||
string status_str;
|
string status_str;
|
||||||
td_api::object_ptr<td_api::ChatMemberStatus> status;
|
td_api::object_ptr<td_api::ChatMemberStatus> status;
|
||||||
get_args(args, chat_id, user_id, status_str);
|
get_args(args, chat_id, member_id, status_str);
|
||||||
if (status_str == "member") {
|
if (status_str == "member") {
|
||||||
status = td_api::make_object<td_api::chatMemberStatusMember>();
|
status = td_api::make_object<td_api::chatMemberStatusMember>();
|
||||||
} else if (status_str == "left") {
|
} else if (status_str == "left") {
|
||||||
@ -3706,7 +3763,7 @@ class CliClient final : public Actor {
|
|||||||
true, 0, td_api::make_object<td_api::chatPermissions>(true, true, true, true, true, true, true, true));
|
true, 0, td_api::make_object<td_api::chatPermissions>(true, true, true, true, true, true, true, true));
|
||||||
}
|
}
|
||||||
if (status != nullptr) {
|
if (status != nullptr) {
|
||||||
send_request(td_api::make_object<td_api::setChatMemberStatus>(as_chat_id(chat_id), as_user_id(user_id),
|
send_request(td_api::make_object<td_api::setChatMemberStatus>(as_chat_id(chat_id), as_message_sender(member_id),
|
||||||
std::move(status)));
|
std::move(status)));
|
||||||
} else {
|
} else {
|
||||||
LOG(ERROR) << "Unknown status \"" << status_str << "\"";
|
LOG(ERROR) << "Unknown status \"" << status_str << "\"";
|
||||||
@ -3732,14 +3789,14 @@ class CliClient final : public Actor {
|
|||||||
send_request(td_api::make_object<td_api::leaveChat>(as_chat_id(args)));
|
send_request(td_api::make_object<td_api::leaveChat>(as_chat_id(args)));
|
||||||
} else if (op == "dcm") {
|
} else if (op == "dcm") {
|
||||||
string chat_id;
|
string chat_id;
|
||||||
string user_id_str;
|
string member_id;
|
||||||
get_args(args, chat_id, user_id_str);
|
get_args(args, chat_id, member_id);
|
||||||
auto user_id = as_user_id(user_id_str);
|
|
||||||
td_api::object_ptr<td_api::ChatMemberStatus> status = td_api::make_object<td_api::chatMemberStatusBanned>();
|
td_api::object_ptr<td_api::ChatMemberStatus> status = td_api::make_object<td_api::chatMemberStatusBanned>();
|
||||||
if (user_id == my_id_) {
|
if (as_user_id(member_id) == my_id_) {
|
||||||
status = td_api::make_object<td_api::chatMemberStatusLeft>();
|
status = td_api::make_object<td_api::chatMemberStatusLeft>();
|
||||||
}
|
}
|
||||||
send_request(td_api::make_object<td_api::setChatMemberStatus>(as_chat_id(chat_id), user_id, std::move(status)));
|
send_request(td_api::make_object<td_api::setChatMemberStatus>(as_chat_id(chat_id), as_message_sender(member_id),
|
||||||
|
std::move(status)));
|
||||||
} else if (op == "sn") {
|
} else if (op == "sn") {
|
||||||
string first_name;
|
string first_name;
|
||||||
string last_name;
|
string last_name;
|
||||||
@ -3891,9 +3948,12 @@ class CliClient final : public Actor {
|
|||||||
string message_id;
|
string message_id;
|
||||||
get_args(args, chat_id, message_id);
|
get_args(args, chat_id, message_id);
|
||||||
send_request(td_api::make_object<td_api::openMessageContent>(as_chat_id(chat_id), as_message_id(message_id)));
|
send_request(td_api::make_object<td_api::openMessageContent>(as_chat_id(chat_id), as_message_id(message_id)));
|
||||||
} else if (op == "gel") {
|
} else if (op == "geli") {
|
||||||
string link = args;
|
string link = args;
|
||||||
send_request(td_api::make_object<td_api::getExternalLink>(link));
|
send_request(td_api::make_object<td_api::getExternalLinkInfo>(link));
|
||||||
|
} else if (op == "gel" || op == "gelw") {
|
||||||
|
string link = args;
|
||||||
|
send_request(td_api::make_object<td_api::getExternalLink>(link, op == "gelw"));
|
||||||
} else if (op == "racm") {
|
} else if (op == "racm") {
|
||||||
string chat_id = args;
|
string chat_id = args;
|
||||||
send_request(td_api::make_object<td_api::readAllChatMentions>(as_chat_id(chat_id)));
|
send_request(td_api::make_object<td_api::readAllChatMentions>(as_chat_id(chat_id)));
|
||||||
|
@ -275,7 +275,7 @@ class FileDb : public FileDbInterface {
|
|||||||
if (ids.size() > 1) {
|
if (ids.size() > 1) {
|
||||||
send_closure(file_db_actor_id, &FileDbActor::optimize_refs, std::move(ids), id);
|
send_closure(file_db_actor_id, &FileDbActor::optimize_refs, std::move(ids), id);
|
||||||
}
|
}
|
||||||
//LOG(DEBUG) << "By id " << id.get() << " found data " << format::as_hex_dump<4>(Slice(data_str));
|
//LOG(DEBUG) << "By ID " << id.get() << " found data " << format::as_hex_dump<4>(Slice(data_str));
|
||||||
//LOG(INFO) << attempt_count;
|
//LOG(INFO) << attempt_count;
|
||||||
|
|
||||||
log_event::WithVersion<TlParser> parser(data_str);
|
log_event::WithVersion<TlParser> parser(data_str);
|
||||||
@ -292,7 +292,7 @@ class FileDb : public FileDbInterface {
|
|||||||
|
|
||||||
static Result<FileDbId> get_id(SqliteKeyValue &pmc, const string &key) TD_WARN_UNUSED_RESULT {
|
static Result<FileDbId> get_id(SqliteKeyValue &pmc, const string &key) TD_WARN_UNUSED_RESULT {
|
||||||
auto id_str = pmc.get(key);
|
auto id_str = pmc.get(key);
|
||||||
//LOG(DEBUG) << "Found id " << id_str << " by key " << format::as_hex_dump<4>(Slice(key));
|
//LOG(DEBUG) << "Found ID " << id_str << " by key " << format::as_hex_dump<4>(Slice(key));
|
||||||
if (id_str.empty()) {
|
if (id_str.empty()) {
|
||||||
return Status::Error("There is no such a key in database");
|
return Status::Error("There is no such a key in database");
|
||||||
}
|
}
|
||||||
|
@ -413,7 +413,7 @@ void FileGenerateManager::generate_file(uint64 query_id, FullGenerateFileLocatio
|
|||||||
|
|
||||||
CHECK(query_id != 0);
|
CHECK(query_id != 0);
|
||||||
auto it_flag = query_id_to_query_.emplace(query_id, Query{});
|
auto it_flag = query_id_to_query_.emplace(query_id, Query{});
|
||||||
LOG_CHECK(it_flag.second) << "Query id must be unique";
|
LOG_CHECK(it_flag.second) << "Query identifier must be unique";
|
||||||
auto parent = actor_shared(this, query_id);
|
auto parent = actor_shared(this, query_id);
|
||||||
|
|
||||||
Slice file_id_query = "#file_id#";
|
Slice file_id_query = "#file_id#";
|
||||||
|
@ -110,7 +110,7 @@ struct PhotoRemoteFileLocation {
|
|||||||
};
|
};
|
||||||
|
|
||||||
inline StringBuilder &operator<<(StringBuilder &string_builder, const PhotoRemoteFileLocation &location) {
|
inline StringBuilder &operator<<(StringBuilder &string_builder, const PhotoRemoteFileLocation &location) {
|
||||||
return string_builder << "[id = " << location.id_ << ", access_hash = " << location.access_hash_
|
return string_builder << "[ID = " << location.id_ << ", access_hash = " << location.access_hash_
|
||||||
<< ", volume_id = " << location.volume_id_ << ", local_id = " << location.local_id_ << "]";
|
<< ", volume_id = " << location.volume_id_ << ", local_id = " << location.local_id_ << "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,7 +173,7 @@ struct CommonRemoteFileLocation {
|
|||||||
};
|
};
|
||||||
|
|
||||||
inline StringBuilder &operator<<(StringBuilder &string_builder, const CommonRemoteFileLocation &location) {
|
inline StringBuilder &operator<<(StringBuilder &string_builder, const CommonRemoteFileLocation &location) {
|
||||||
return string_builder << "[id = " << location.id_ << ", access_hash = " << location.access_hash_ << "]";
|
return string_builder << "[ID = " << location.id_ << ", access_hash = " << location.access_hash_ << "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
class FullRemoteFileLocation {
|
class FullRemoteFileLocation {
|
||||||
|
@ -932,23 +932,23 @@ Status FileManager::check_local_location(FullLocalFileLocation &location, int64
|
|||||||
constexpr int64 MAX_PHOTO_SIZE = 10 * (1 << 20) /* 10 MB */;
|
constexpr int64 MAX_PHOTO_SIZE = 10 * (1 << 20) /* 10 MB */;
|
||||||
|
|
||||||
if (location.path_.empty()) {
|
if (location.path_.empty()) {
|
||||||
return Status::Error("File must have non-empty path");
|
return Status::Error(400, "File must have non-empty path");
|
||||||
}
|
}
|
||||||
TRY_RESULT(path, realpath(location.path_, true));
|
TRY_RESULT(path, realpath(location.path_, true));
|
||||||
if (bad_paths_.count(path) != 0) {
|
if (bad_paths_.count(path) != 0) {
|
||||||
return Status::Error("Sending of internal database files is forbidden");
|
return Status::Error(400, "Sending of internal database files is forbidden");
|
||||||
}
|
}
|
||||||
location.path_ = std::move(path);
|
location.path_ = std::move(path);
|
||||||
TRY_RESULT(stat, stat(location.path_));
|
TRY_RESULT(stat, stat(location.path_));
|
||||||
if (!stat.is_reg_) {
|
if (!stat.is_reg_) {
|
||||||
return Status::Error("File must be a regular file");
|
return Status::Error(400, "File must be a regular file");
|
||||||
}
|
}
|
||||||
if (stat.size_ < 0) {
|
if (stat.size_ < 0) {
|
||||||
// TODO is it possible?
|
// TODO is it possible?
|
||||||
return Status::Error("File is too big");
|
return Status::Error(400, "File is too big");
|
||||||
}
|
}
|
||||||
if (stat.size_ == 0) {
|
if (stat.size_ == 0) {
|
||||||
return Status::Error("File must be non-empty");
|
return Status::Error(400, "File must be non-empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
@ -960,23 +960,23 @@ Status FileManager::check_local_location(FullLocalFileLocation &location, int64
|
|||||||
} else if (!are_modification_times_equal(location.mtime_nsec_, stat.mtime_nsec_)) {
|
} else if (!are_modification_times_equal(location.mtime_nsec_, stat.mtime_nsec_)) {
|
||||||
VLOG(file_loader) << "File \"" << location.path_ << "\" was modified: old mtime = " << location.mtime_nsec_
|
VLOG(file_loader) << "File \"" << location.path_ << "\" was modified: old mtime = " << location.mtime_nsec_
|
||||||
<< ", new mtime = " << stat.mtime_nsec_;
|
<< ", new mtime = " << stat.mtime_nsec_;
|
||||||
return Status::Error(PSLICE() << "File \"" << location.path_ << "\" was modified");
|
return Status::Error(400, PSLICE() << "File \"" << location.path_ << "\" was modified");
|
||||||
}
|
}
|
||||||
if (skip_file_size_checks) {
|
if (skip_file_size_checks) {
|
||||||
return Status::OK();
|
return Status::OK();
|
||||||
}
|
}
|
||||||
if ((location.file_type_ == FileType::Thumbnail || location.file_type_ == FileType::EncryptedThumbnail) &&
|
if ((location.file_type_ == FileType::Thumbnail || location.file_type_ == FileType::EncryptedThumbnail) &&
|
||||||
size > MAX_THUMBNAIL_SIZE && !begins_with(PathView(location.path_).file_name(), "map")) {
|
size > MAX_THUMBNAIL_SIZE && !begins_with(PathView(location.path_).file_name(), "map")) {
|
||||||
return Status::Error(PSLICE() << "File \"" << location.path_ << "\" is too big for a thumbnail "
|
return Status::Error(400, PSLICE() << "File \"" << location.path_ << "\" is too big for a thumbnail "
|
||||||
<< tag("size", format::as_size(size)));
|
<< tag("size", format::as_size(size)));
|
||||||
}
|
}
|
||||||
if (location.file_type_ == FileType::Photo && size > MAX_PHOTO_SIZE) {
|
if (location.file_type_ == FileType::Photo && size > MAX_PHOTO_SIZE) {
|
||||||
return Status::Error(PSLICE() << "File \"" << location.path_ << "\" is too big for a photo "
|
return Status::Error(400, PSLICE() << "File \"" << location.path_ << "\" is too big for a photo "
|
||||||
<< tag("size", format::as_size(size)));
|
<< tag("size", format::as_size(size)));
|
||||||
}
|
}
|
||||||
if (size > MAX_FILE_SIZE) {
|
if (size > MAX_FILE_SIZE) {
|
||||||
return Status::Error(PSLICE() << "File \"" << location.path_ << "\" is too big "
|
return Status::Error(
|
||||||
<< tag("size", format::as_size(size)));
|
400, PSLICE() << "File \"" << location.path_ << "\" is too big " << tag("size", format::as_size(size)));
|
||||||
}
|
}
|
||||||
return Status::OK();
|
return Status::OK();
|
||||||
}
|
}
|
||||||
@ -1200,7 +1200,7 @@ Result<FileId> FileManager::register_file(FileData &&data, FileLocationSource fi
|
|||||||
bool has_local = data.local_.type() == LocalFileLocation::Type::Full;
|
bool has_local = data.local_.type() == LocalFileLocation::Type::Full;
|
||||||
bool has_location = has_local || has_remote || has_generate;
|
bool has_location = has_local || has_remote || has_generate;
|
||||||
if (!has_location) {
|
if (!has_location) {
|
||||||
return Status::Error("No location");
|
return Status::Error(400, "No location");
|
||||||
}
|
}
|
||||||
|
|
||||||
FileId file_id = next_file_id();
|
FileId file_id = next_file_id();
|
||||||
@ -1447,7 +1447,8 @@ Result<FileId> FileManager::merge(FileId x_file_id, FileId y_file_id, bool no_sy
|
|||||||
}
|
}
|
||||||
FileNodePtr x_node = no_sync ? get_file_node(x_file_id) : get_sync_file_node(x_file_id);
|
FileNodePtr x_node = no_sync ? get_file_node(x_file_id) : get_sync_file_node(x_file_id);
|
||||||
if (!x_node) {
|
if (!x_node) {
|
||||||
return Status::Error(PSLICE() << "Can't merge files. First id is invalid: " << x_file_id << " and " << y_file_id);
|
return Status::Error(PSLICE() << "Can't merge files. First identifier is invalid: " << x_file_id << " and "
|
||||||
|
<< y_file_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!y_file_id.is_valid()) {
|
if (!y_file_id.is_valid()) {
|
||||||
@ -1456,7 +1457,8 @@ Result<FileId> FileManager::merge(FileId x_file_id, FileId y_file_id, bool no_sy
|
|||||||
}
|
}
|
||||||
FileNodePtr y_node = get_file_node(y_file_id);
|
FileNodePtr y_node = get_file_node(y_file_id);
|
||||||
if (!y_node) {
|
if (!y_node) {
|
||||||
return Status::Error(PSLICE() << "Can't merge files. Second id is invalid: " << x_file_id << " and " << y_file_id);
|
return Status::Error(PSLICE() << "Can't merge files. Second identifier is invalid: " << x_file_id << " and "
|
||||||
|
<< y_file_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (x_file_id == x_node->upload_pause_) {
|
if (x_file_id == x_node->upload_pause_) {
|
||||||
@ -2873,11 +2875,11 @@ Result<FileId> FileManager::from_persistent_id(CSlice persistent_id, FileType fi
|
|||||||
|
|
||||||
auto r_binary = base64url_decode(persistent_id);
|
auto r_binary = base64url_decode(persistent_id);
|
||||||
if (r_binary.is_error()) {
|
if (r_binary.is_error()) {
|
||||||
return Status::Error(10, PSLICE() << "Wrong remote file identifier specified: " << r_binary.error().message());
|
return Status::Error(400, PSLICE() << "Wrong remote file identifier specified: " << r_binary.error().message());
|
||||||
}
|
}
|
||||||
auto binary = r_binary.move_as_ok();
|
auto binary = r_binary.move_as_ok();
|
||||||
if (binary.empty()) {
|
if (binary.empty()) {
|
||||||
return Status::Error(10, "Remote file identifier can't be empty");
|
return Status::Error(400, "Remote file identifier can't be empty");
|
||||||
}
|
}
|
||||||
if (binary.back() == FileNode::PERSISTENT_ID_VERSION_OLD) {
|
if (binary.back() == FileNode::PERSISTENT_ID_VERSION_OLD) {
|
||||||
return from_persistent_id_v2(binary, file_type);
|
return from_persistent_id_v2(binary, file_type);
|
||||||
@ -2888,7 +2890,7 @@ Result<FileId> FileManager::from_persistent_id(CSlice persistent_id, FileType fi
|
|||||||
if (binary.back() == FileNode::PERSISTENT_ID_VERSION_MAP) {
|
if (binary.back() == FileNode::PERSISTENT_ID_VERSION_MAP) {
|
||||||
return from_persistent_id_map(binary, file_type);
|
return from_persistent_id_map(binary, file_type);
|
||||||
}
|
}
|
||||||
return Status::Error(10, "Wrong remote file identifier specified: can't unserialize it. Wrong last symbol");
|
return Status::Error(400, "Wrong remote file identifier specified: can't unserialize it. Wrong last symbol");
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<FileId> FileManager::from_persistent_id_map(Slice binary, FileType file_type) {
|
Result<FileId> FileManager::from_persistent_id_map(Slice binary, FileType file_type) {
|
||||||
@ -2897,15 +2899,15 @@ Result<FileId> FileManager::from_persistent_id_map(Slice binary, FileType file_t
|
|||||||
FullGenerateFileLocation generate_location;
|
FullGenerateFileLocation generate_location;
|
||||||
auto status = unserialize(generate_location, decoded_binary);
|
auto status = unserialize(generate_location, decoded_binary);
|
||||||
if (status.is_error()) {
|
if (status.is_error()) {
|
||||||
return Status::Error(10, "Wrong remote file identifier specified: can't unserialize it");
|
return Status::Error(400, "Wrong remote file identifier specified: can't unserialize it");
|
||||||
}
|
}
|
||||||
auto real_file_type = generate_location.file_type_;
|
auto real_file_type = generate_location.file_type_;
|
||||||
if ((real_file_type != file_type && file_type != FileType::Temp) ||
|
if ((real_file_type != file_type && file_type != FileType::Temp) ||
|
||||||
(real_file_type != FileType::Thumbnail && real_file_type != FileType::EncryptedThumbnail)) {
|
(real_file_type != FileType::Thumbnail && real_file_type != FileType::EncryptedThumbnail)) {
|
||||||
return Status::Error(10, "Type of file mismatch");
|
return Status::Error(400, "Type of file mismatch");
|
||||||
}
|
}
|
||||||
if (!begins_with(generate_location.conversion_, "#map#")) {
|
if (!begins_with(generate_location.conversion_, "#map#")) {
|
||||||
return Status::Error(10, "Unexpected conversion type");
|
return Status::Error(400, "Unexpected conversion type");
|
||||||
}
|
}
|
||||||
FileData data;
|
FileData data;
|
||||||
data.generate_ = make_unique<FullGenerateFileLocation>(std::move(generate_location));
|
data.generate_ = make_unique<FullGenerateFileLocation>(std::move(generate_location));
|
||||||
@ -2914,7 +2916,7 @@ Result<FileId> FileManager::from_persistent_id_map(Slice binary, FileType file_t
|
|||||||
|
|
||||||
Result<FileId> FileManager::from_persistent_id_v23(Slice binary, FileType file_type, int32 version) {
|
Result<FileId> FileManager::from_persistent_id_v23(Slice binary, FileType file_type, int32 version) {
|
||||||
if (version < 0 || version >= static_cast<int32>(Version::Next)) {
|
if (version < 0 || version >= static_cast<int32>(Version::Next)) {
|
||||||
return Status::Error("Invalid remote file identifier");
|
return Status::Error(400, "Invalid remote file identifier");
|
||||||
}
|
}
|
||||||
auto decoded_binary = zero_decode(binary);
|
auto decoded_binary = zero_decode(binary);
|
||||||
FullRemoteFileLocation remote_location;
|
FullRemoteFileLocation remote_location;
|
||||||
@ -2924,7 +2926,7 @@ Result<FileId> FileManager::from_persistent_id_v23(Slice binary, FileType file_t
|
|||||||
parser.fetch_end();
|
parser.fetch_end();
|
||||||
auto status = parser.get_status();
|
auto status = parser.get_status();
|
||||||
if (status.is_error()) {
|
if (status.is_error()) {
|
||||||
return Status::Error(10, "Wrong remote file identifier specified: can't unserialize it");
|
return Status::Error(400, "Wrong remote file identifier specified: can't unserialize it");
|
||||||
}
|
}
|
||||||
auto &real_file_type = remote_location.file_type_;
|
auto &real_file_type = remote_location.file_type_;
|
||||||
if (is_document_type(real_file_type) && is_document_type(file_type)) {
|
if (is_document_type(real_file_type) && is_document_type(file_type)) {
|
||||||
@ -2932,7 +2934,7 @@ Result<FileId> FileManager::from_persistent_id_v23(Slice binary, FileType file_t
|
|||||||
} else if (is_background_type(real_file_type) && is_background_type(file_type)) {
|
} else if (is_background_type(real_file_type) && is_background_type(file_type)) {
|
||||||
// type of file matches, but real type is in the stored remote location
|
// type of file matches, but real type is in the stored remote location
|
||||||
} else if (real_file_type != file_type && file_type != FileType::Temp) {
|
} else if (real_file_type != file_type && file_type != FileType::Temp) {
|
||||||
return Status::Error(10, "Type of file mismatch");
|
return Status::Error(400, "Type of file mismatch");
|
||||||
}
|
}
|
||||||
FileData data;
|
FileData data;
|
||||||
data.remote_ = RemoteFileLocation(std::move(remote_location));
|
data.remote_ = RemoteFileLocation(std::move(remote_location));
|
||||||
@ -2949,7 +2951,7 @@ Result<FileId> FileManager::from_persistent_id_v2(Slice binary, FileType file_ty
|
|||||||
Result<FileId> FileManager::from_persistent_id_v3(Slice binary, FileType file_type) {
|
Result<FileId> FileManager::from_persistent_id_v3(Slice binary, FileType file_type) {
|
||||||
binary.remove_suffix(1);
|
binary.remove_suffix(1);
|
||||||
if (binary.empty()) {
|
if (binary.empty()) {
|
||||||
return Status::Error("Invalid remote file identifier");
|
return Status::Error(400, "Invalid remote file identifier");
|
||||||
}
|
}
|
||||||
int32 version = static_cast<uint8>(binary.back());
|
int32 version = static_cast<uint8>(binary.back());
|
||||||
binary.remove_suffix(1);
|
binary.remove_suffix(1);
|
||||||
@ -3201,8 +3203,8 @@ Result<FileId> FileManager::get_map_thumbnail_file_id(Location location, int32 z
|
|||||||
x = clamp(x, 0, size - 1); // just in case
|
x = clamp(x, 0, size - 1); // just in case
|
||||||
y = clamp(y, 0, size - 1); // just in case
|
y = clamp(y, 0, size - 1); // just in case
|
||||||
|
|
||||||
string conversion = PSTRING() << "#map#" << zoom << "#" << x << "#" << y << "#" << width << "#" << height << "#"
|
string conversion = PSTRING() << "#map#" << zoom << '#' << x << '#' << y << '#' << width << '#' << height << '#'
|
||||||
<< scale << "#";
|
<< scale << '#';
|
||||||
return register_generate(
|
return register_generate(
|
||||||
owner_dialog_id.get_type() == DialogType::SecretChat ? FileType::EncryptedThumbnail : FileType::Thumbnail,
|
owner_dialog_id.get_type() == DialogType::SecretChat ? FileType::EncryptedThumbnail : FileType::Thumbnail,
|
||||||
FileLocationSource::FromUser, string(), std::move(conversion), owner_dialog_id, 0);
|
FileLocationSource::FromUser, string(), std::move(conversion), owner_dialog_id, 0);
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user