Merge commit '64dd422b1ee7811dbd7a423c42d603a51215143d'

Conflicts:
	CMakeLists.txt
	td/telegram/ContactsManager.cpp
	td/telegram/MessagesDb.cpp
	tddb/td/db/SqliteDb.cpp
This commit is contained in:
Andrea Cavalli 2020-04-17 19:53:49 +02:00
commit c6b4f5a58d
180 changed files with 7289 additions and 3423 deletions

View File

@ -206,7 +206,7 @@ Changes in 1.5.0:
instead of `can_send_media_messages`.
- Allowed administrators in basic groups to use the method `generateChatInviteLink`.
* Added out of the box `OpenBSD` and `NetBSD` operating systems support.
* Added possibility to use `LibreSSL` instead of `OpenSSL` to build TDLib.
* Added possibility to use `LibreSSL` >= 2.7.0 instead of `OpenSSL` to build TDLib.
* Added instructions for building TDLib on `Debian 10`, `OpenBSD` and `NetBSD` to
the [TDLib build instructions generator](https://tdlib.github.io/td/build.html).
* Added support for Backgrounds 2.0:

View File

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR)
project(TDLib VERSION 1.5.5 LANGUAGES CXX C)
project(TDLib VERSION 1.6.2 LANGUAGES CXX C)
if (NOT DEFINED CMAKE_INSTALL_LIBDIR)
set(CMAKE_INSTALL_LIBDIR "lib")
@ -189,7 +189,7 @@ elseif (INTEL)
endif()
if (WIN32)
add_definitions(-DNTDDI_VERSION=0x06020000 -DWINVER=0x0602 -D_WIN32_WINNT=0x0602 -DNOMINMAX -DUNICODE -D_UNICODE)
add_definitions(-DNTDDI_VERSION=0x06020000 -DWINVER=0x0602 -D_WIN32_WINNT=0x0602 -DNOMINMAX -DUNICODE -D_UNICODE -DWIN32_LEAN_AND_MEAN)
endif()
if (CYGWIN)
add_definitions(-D_DEFAULT_SOURCE=1 -DFD_SETSIZE=4096)
@ -243,6 +243,10 @@ if (GCC AND NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.0))
# see http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1579
add_cxx_compiler_flag("-Wno-redundant-move")
endif()
if (CLANG AND (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5))
# https://stackoverflow.com/questions/26744556/warning-returning-a-captured-reference-from-a-lambda
add_cxx_compiler_flag("-Wno-return-stack-address")
endif()
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem /usr/include/c++/v1")
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
@ -262,9 +266,9 @@ if (NOT CMAKE_CROSSCOMPILING)
if (TD_ENABLE_DOTNET)
add_custom_target(remove_cpp_documentation
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMAND remove_documentation ${TL_TD_AUTO} td/telegram/Client.h td/telegram/Log.h td/tl/TlObject.h
COMMAND remove_documentation ${TL_TD_API_AUTO_SOURCE} td/telegram/Client.h td/telegram/Log.h td/tl/TlObject.h
COMMENT "Remove C++ documentation from sources"
DEPENDS remove_documentation tl_generate_common generate_dotnet_api ${TL_TD_AUTO} td/telegram/Client.h td/telegram/Log.h td/tl/TlObject.h
DEPENDS remove_documentation tl_generate_common generate_dotnet_api ${TL_TD_API_AUTO_SOURCE} td/telegram/Client.h td/telegram/Log.h td/tl/TlObject.h
)
add_dependencies(prepare_cross_compiling generate_dotnet_api remove_cpp_documentation)
@ -301,46 +305,52 @@ endif()
get_directory_property(HAS_PARENT PARENT_DIRECTORY)
if (HAS_PARENT)
set(TL_TD_API_TLO ${TL_TD_API_TLO} PARENT_SCOPE)
set(TL_TD_JSON_AUTO ${TL_TD_JSON_AUTO} PARENT_SCOPE)
set(TD_TEST_SOURCE ${TD_TEST_SOURCE} PARENT_SCOPE)
set(TL_TD_API_TLO ${TL_TD_API_TLO} PARENT_SCOPE) # was used in standalone binding generators
set(TL_TD_JSON_AUTO ${TL_TD_JSON_AUTO_SOURCE} PARENT_SCOPE) # used in tdbot
set(TD_TEST_SOURCE ${TD_TEST_SOURCE} PARENT_SCOPE) # used to build tests
endif()
#SOURCE SETS
set_source_files_properties(${TL_TD_AUTO} PROPERTIES GENERATED TRUE)
set_source_files_properties(${TL_TD_API_AUTO_SOURCE} PROPERTIES GENERATED TRUE)
if (TD_ENABLE_JNI OR ANDROID)
set(TL_JNI_OBJECT
set(TL_JNI_OBJECT_SOURCE
td/tl/tl_jni_object.cpp
td/tl/tl_jni_object.h
)
else()
set(TL_JNI_OBJECT)
set(TL_JNI_OBJECT_SOURCE)
endif()
set(TL_TD_API_SOURCE
${TL_TD_API_AUTO_SOURCE}
${TL_JNI_OBJECT_SOURCE}
td/tl/TlObject.h
)
set_source_files_properties(${TL_TD_AUTO_SOURCE} PROPERTIES GENERATED TRUE)
set(TL_TD_SCHEME_SOURCE
${TL_TD_AUTO}
${TL_JNI_OBJECT}
${TL_TD_AUTO_SOURCE}
td/tl/TlObject.h
td/tl/tl_object_parse.h
td/tl/tl_object_store.h
)
set_source_files_properties(${TL_TD_JSON_AUTO} PROPERTIES GENERATED TRUE)
set(TL_TD_JSON
${TL_TD_JSON_AUTO}
set_source_files_properties(${TL_TD_JSON_AUTO_SOURCE} PROPERTIES GENERATED TRUE)
set(TL_TD_JSON_SOURCE
${TL_TD_JSON_AUTO_SOURCE}
td/tl/tl_json.h
)
set_source_files_properties(${TL_C_AUTO} PROPERTIES GENERATED TRUE)
set_source_files_properties(${TL_C_AUTO_SOURCE} PROPERTIES GENERATED TRUE)
set(TL_C_SCHEME_SOURCE
${TL_C_AUTO}
${TL_C_AUTO_SOURCE}
)
set_source_files_properties(${TL_DOTNET_AUTO} PROPERTIES GENERATED TRUE)
set_source_files_properties(${TL_DOTNET_AUTO_SOURCE} PROPERTIES GENERATED TRUE)
set(TL_DOTNET_SCHEME_SOURCE
${TL_DOTNET_AUTO}
${TL_DOTNET_AUTO_SOURCE}
td/tl/tl_dotnet_object.h
)
@ -741,21 +751,29 @@ if (MEMPROF)
endif()
# tdcore - mostly internal TDLib interface. One should use tdactor for interactions with it.
add_library(tdcore STATIC ${TDLIB_SOURCE})
target_include_directories(tdcore PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> $<BUILD_INTERFACE:${TL_TD_AUTO_INCLUDE_DIR}>)
target_include_directories(tdcore SYSTEM PRIVATE ${OPENSSL_INCLUDE_DIR})
target_link_libraries(tdcore PUBLIC tdactor tdutils tdnet tddb PRIVATE ${OPENSSL_CRYPTO_LIBRARY} ${CMAKE_DL_LIBS} ${ZLIB_LIBRARIES})
add_library(tdapi STATIC ${TL_TD_API_SOURCE})
target_include_directories(tdapi PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> INTERFACE $<BUILD_INTERFACE:${TL_TD_AUTO_INCLUDE_DIR}>)
target_link_libraries(tdapi PRIVATE tdutils)
if (TD_ENABLE_JNI AND NOT ANDROID) # jni is available by default on Android
if (NOT JNI_FOUND)
find_package(JNI REQUIRED)
endif()
message(STATUS "Found JNI: ${JNI_INCLUDE_DIRS} ${JNI_LIBRARIES}")
target_include_directories(tdcore PUBLIC ${JAVA_INCLUDE_PATH} ${JAVA_INCLUDE_PATH2})
target_link_libraries(tdcore PUBLIC ${JAVA_JVM_LIBRARY})
target_include_directories(tdapi PUBLIC ${JAVA_INCLUDE_PATH} ${JAVA_INCLUDE_PATH2})
target_link_libraries(tdapi PUBLIC ${JAVA_JVM_LIBRARY})
endif()
if (NOT CMAKE_CROSSCOMPILING)
add_dependencies(tdapi tl_generate_common)
endif()
# tdcore - mostly internal TDLib interface. One should use tdactor for interactions with it.
add_library(tdcore STATIC ${TDLIB_SOURCE})
target_include_directories(tdcore PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> $<BUILD_INTERFACE:${TL_TD_AUTO_INCLUDE_DIR}>)
target_include_directories(tdcore SYSTEM PRIVATE ${OPENSSL_INCLUDE_DIR})
target_link_libraries(tdcore PUBLIC tdapi tdactor tdutils tdnet tddb PRIVATE ${OPENSSL_CRYPTO_LIBRARY} ${CMAKE_DL_LIBS} ${ZLIB_LIBRARIES})
if (NOT CMAKE_CROSSCOMPILING)
add_dependencies(tdcore tl_generate_common)
if (TD_ENABLE_JNI)
@ -769,15 +787,8 @@ endif()
add_library(tdclient td/telegram/Client.cpp td/telegram/Client.h td/telegram/Log.cpp td/telegram/Log.h)
target_include_directories(tdclient PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<BUILD_INTERFACE:${TL_TD_AUTO_INCLUDE_DIR}>
)
target_link_libraries(tdclient PRIVATE tdcore)
if (TD_ENABLE_JNI AND NOT ANDROID) # jni is available by default on Android
target_include_directories(tdclient PUBLIC ${JAVA_INCLUDE_PATH} ${JAVA_INCLUDE_PATH2})
target_link_libraries(tdclient PUBLIC ${JAVA_JVM_LIBRARY})
endif()
target_link_libraries(tdclient PUBLIC tdapi PRIVATE tdcore)
if (TD_ENABLE_DOTNET)
add_library(tddotnet SHARED
@ -815,7 +826,7 @@ if (NOT CMAKE_CROSSCOMPILING)
add_dependencies(tdc tl_generate_c)
endif()
add_library(tdjson_private STATIC ${TL_TD_JSON} td/telegram/ClientJson.cpp td/telegram/ClientJson.h)
add_library(tdjson_private STATIC ${TL_TD_JSON_SOURCE} td/telegram/ClientJson.cpp td/telegram/ClientJson.h)
target_include_directories(tdjson_private PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<BUILD_INTERFACE:${TL_TD_AUTO_INCLUDE_DIR}>)
@ -858,6 +869,7 @@ if (WIN32 OR CYGWIN)
endif()
endif()
if (BIGOBJ)
target_compile_options(tdapi PUBLIC ${BIGOBJ})
target_compile_options(tdc PUBLIC ${BIGOBJ})
target_compile_options(tdcore PUBLIC ${BIGOBJ})
target_compile_options(tdclient PUBLIC ${BIGOBJ})
@ -877,7 +889,7 @@ endif()
#EXECUTABLES
if (NOT CMAKE_CROSSCOMPILING)
add_executable(tg_cli td/telegram/cli.cpp ${TL_TD_JSON})
add_executable(tg_cli td/telegram/cli.cpp ${TL_TD_JSON_SOURCE})
if (NOT READLINE_FOUND)
find_package(Readline)
@ -904,7 +916,7 @@ if (NOT CMAKE_CROSSCOMPILING)
target_compile_definitions(tg_cli PRIVATE -DUSE_READLINE=1)
endif()
endif()
target_link_libraries(tg_cli PRIVATE memprof tdclient tdcore tdtl)
target_link_libraries(tg_cli PRIVATE memprof tdclient tdcore)
add_dependencies(tg_cli tl_generate_json)
endif()
@ -922,7 +934,7 @@ add_library(Td::TdStatic ALIAS TdStatic)
add_library(Td::TdJson ALIAS TdJson)
add_library(Td::TdJsonStatic ALIAS TdJsonStatic)
install(TARGETS tdjson TdJson tdjson_static TdJsonStatic tdjson_private tdclient tdcore TdStatic EXPORT TdTargets
install(TARGETS tdjson TdJson tdjson_static TdJsonStatic tdjson_private tdclient tdcore tdapi TdStatic EXPORT TdTargets
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
@ -935,8 +947,11 @@ install(EXPORT TdTargets
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Td"
)
# Install tdjson/tdjson_static:
install(FILES ${TD_JSON_HEADERS} "${CMAKE_CURRENT_BINARY_DIR}/td/telegram/tdjson_export.h" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/td/telegram")
# Install tdclient:
install(FILES td/telegram/Client.h td/telegram/Log.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/td/telegram")
# Install tdapi:
install(FILES td/tl/TlObject.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/td/tl")
install(FILES "${TL_TD_AUTO_INCLUDE_DIR}/td/telegram/td_api.h" "${TL_TD_AUTO_INCLUDE_DIR}/td/telegram/td_api.hpp" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/td/telegram")
if (TD_ENABLE_JNI)

View File

@ -31,10 +31,10 @@ TDLib (Telegram Database library) is a cross-platform library for building [Tele
<a name="usage"></a>
## Examples and documentation
Take a look at our [examples](https://github.com/tdlib/td/blob/master/example/README.md#tdlib-usage-and-build-examples).
See our [Getting Started](https://core.telegram.org/tdlib/getting-started) tutorial for a description of basic TDLib concepts.
Take a look at our [examples](https://github.com/tdlib/td/blob/master/example/README.md#tdlib-usage-and-build-examples).
See a [TDLib build instructions generator](https://tdlib.github.io/td/build.html) for detailed instructions on how to build TDLib.
See description of our [JSON](#using-json), [C++](#using-cxx), [Java](#using-java) and [.NET](#using-dotnet) interfaces.
@ -115,7 +115,7 @@ cd <path to vcpkg>
* Download and install [CMake](https://cmake.org/download/); choose "Add CMake to the system PATH" option while installing.
* Build `TDLib` with CMake as explained in [building](#building), but instead of `cmake -DCMAKE_BUILD_TYPE=Release ..` use
```
cmake -DCMAKE_TOOLCHAIN_FILE=<path to vcpkg>\scripts\buildsystems\vcpkg.cmake ..
cmake -DCMAKE_TOOLCHAIN_FILE=<path to vcpkg>/scripts/buildsystems/vcpkg.cmake ..
```
To build 32-bit/64-bit `TDLib` using MSVC, you will need to additionally specify parameter `-A Win32`/`-A x64` to CMake.
@ -146,7 +146,7 @@ target_link_libraries(YourTarget PRIVATE Td::TdStatic)
Or you could install `TDLib` and then reference it in your CMakeLists.txt like this:
```
find_package(Td 1.5.5 REQUIRED)
find_package(Td 1.6.2 REQUIRED)
target_link_libraries(YourTarget PRIVATE Td::TdStatic)
```
See [example/cpp/CMakeLists.txt](https://github.com/tdlib/td/tree/master/example/cpp/CMakeLists.txt).
@ -160,7 +160,7 @@ See [example/java](https://github.com/tdlib/td/tree/master/example/java) for exa
<a name="using-dotnet"></a>
## Using in .NET projects
`TDLib` provides native .NET interface through `C++/CLI` and `C++/CX`. To enable it, specify option `-DTD_ENABLE_DOTNET=ON` to CMake.
.NET Core doesn't support `C++/CLI`, so if .NET Core is used, then `TDLib` JSON interface should be used through P/Invoke instead.
.NET Core supports `C++/CLI` only since version 3.1 and only on Windows, so if older .NET Core is used or portability is needed, then `TDLib` JSON interface should be used through P/Invoke instead.
See [example/csharp](https://github.com/tdlib/td/tree/master/example/csharp) for example of using `TDLib` from C# and detailed build and usage instructions.
See [example/uwp](https://github.com/tdlib/td/tree/master/example/uwp) for example of using `TDLib` from C# UWP application and detailed build and usage instructions for Visual Studio Extension "TDLib for Universal Windows Platform".

View File

@ -7,7 +7,7 @@ endif()
#TODO: all benchmarks in one file
add_executable(bench_crypto bench_crypto.cpp)
target_link_libraries(bench_crypto PRIVATE tdcore tdutils ${OPENSSL_CRYPTO_LIBRARY} ${CMAKE_DL_LIBS} ${ZLIB_LIBRARIES})
target_link_libraries(bench_crypto PRIVATE tdutils ${OPENSSL_CRYPTO_LIBRARY} ${CMAKE_DL_LIBS} ${ZLIB_LIBRARIES})
target_include_directories(bench_crypto SYSTEM PRIVATE ${OPENSSL_INCLUDE_DIR})
add_executable(bench_actor bench_actor.cpp)
@ -41,7 +41,7 @@ add_executable(bench_misc bench_misc.cpp)
target_link_libraries(bench_misc PRIVATE tdcore tdutils)
add_executable(check_proxy check_proxy.cpp)
target_link_libraries(check_proxy PRIVATE tdclient tdcore)
target_link_libraries(check_proxy PRIVATE tdclient tdutils)
add_executable(check_tls check_tls.cpp)
target_link_libraries(check_tls PRIVATE tdutils)

View File

@ -30,7 +30,7 @@ class SHA1Bench : public td::Benchmark {
alignas(64) unsigned char data[DATA_SIZE];
std::string get_description() const override {
return PSTRING() << "SHA1 OpenSSL [" << (DATA_SIZE >> 10) << "kB]";
return PSTRING() << "SHA1 OpenSSL [" << (DATA_SIZE >> 10) << "KB]";
}
void start_up() override {
@ -55,7 +55,7 @@ class AESBench : public td::Benchmark {
td::UInt256 iv;
std::string get_description() const override {
return PSTRING() << "AES OpenSSL [" << (DATA_SIZE >> 10) << "kB]";
return PSTRING() << "AES OpenSSL [" << (DATA_SIZE >> 10) << "KB]";
}
void start_up() override {
@ -152,7 +152,7 @@ class Crc32Bench : public td::Benchmark {
alignas(64) unsigned char data[DATA_SIZE];
std::string get_description() const override {
return PSTRING() << "Crc32 zlib [" << (DATA_SIZE >> 10) << "kB]";
return PSTRING() << "Crc32 zlib [" << (DATA_SIZE >> 10) << "KB]";
}
void start_up() override {
@ -176,7 +176,7 @@ class Crc64Bench : public td::Benchmark {
alignas(64) unsigned char data[DATA_SIZE];
std::string get_description() const override {
return PSTRING() << "Crc64 Anton [" << (DATA_SIZE >> 10) << "kB]";
return PSTRING() << "Crc64 Anton [" << (DATA_SIZE >> 10) << "KB]";
}
void start_up() override {

View File

@ -43,7 +43,6 @@
//}
//}
// TODO: warnings and asserts. There should be no warnings or debug output in production.
using qvalue_t = int;
// Just for testing, not production

View File

@ -7,11 +7,13 @@
#include "td/telegram/Client.h"
#include "td/telegram/td_api.h"
#include "td/utils/base64.h"
#include "td/utils/common.h"
#include "td/utils/filesystem.h"
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <utility>
@ -34,11 +36,36 @@ int main(int argc, char **argv) {
td::vector<std::pair<td::string, td::td_api::object_ptr<td::td_api::testProxy>>> requests;
auto add_proxy = [&requests](const td::string &arg) {
auto add_proxy = [&requests](td::string arg) {
if (arg.empty()) {
return;
}
std::size_t offset = 0;
if (arg[0] == '[') {
auto end_ipv6_pos = arg.find(']');
if (end_ipv6_pos == td::string::npos) {
td::TsCerr() << "Error: failed to find end of IPv6 address in \"" << arg << "\"\n";
usage();
}
offset = end_ipv6_pos;
}
if (std::count(arg.begin() + offset, arg.end(), ':') == 3) {
auto secret_domain_pos = arg.find(':', arg.find(':', offset) + 1) + 1;
auto domain_pos = arg.find(':', secret_domain_pos);
auto secret = arg.substr(secret_domain_pos, domain_pos - secret_domain_pos);
auto domain = arg.substr(domain_pos + 1);
auto r_decoded_secret = td::hex_decode(secret);
if (r_decoded_secret.is_error()) {
r_decoded_secret = td::base64url_decode(secret);
if (r_decoded_secret.is_error()) {
td::TsCerr() << "Error: failed to find proxy port and secret in \"" << arg << "\"\n";
usage();
}
}
arg = arg.substr(0, secret_domain_pos) + td::base64url_encode(r_decoded_secret.ok() + domain);
}
auto secret_pos = arg.rfind(':');
if (secret_pos == td::string::npos) {
td::TsCerr() << "Error: failed to find proxy port and secret in \"" << arg << "\"\n";
@ -57,6 +84,9 @@ int main(int argc, char **argv) {
}
auto port = r_port.move_as_ok();
auto server = arg.substr(0, port_pos);
if (server[0] == '[' && server.back() == ']') {
server = server.substr(1, server.size() - 2);
}
if (server.empty() || port <= 0 || port > 65536 || secret.empty()) {
td::TsCerr() << "Error: proxy address to check is in wrong format: \"" << arg << "\"\n";

View File

@ -668,14 +668,14 @@ function onOptionsChanged() {
commands.push('git clone https://github.com/tdlib/td.git');
commands.push('cd td');
commands.push('git checkout v1.5.0');
commands.push('git checkout v1.6.0');
if (use_vcpkg) {
commands.push('git clone https://github.com/Microsoft/vcpkg.git');
commands.push('cd vcpkg');
commands.push(local + 'bootstrap-vcpkg.bat');
if (target === 'C++/CX') {
commands.push(local + 'vcpkg.exe install openssl:arm-uwp openssl:x64-uwp openssl:x86-uwp zlib:arm-uwp zlib:x64-uwp zlib:x86-uwp');
commands.push(local + 'vcpkg.exe install openssl-uwp:arm-uwp openssl-uwp:x64-uwp openssl-uwp:x86-uwp zlib:arm-uwp zlib:x64-uwp zlib:x86-uwp');
} else {
if (build_64bit) {
commands.push(local + 'vcpkg.exe install openssl:x64-windows zlib:x64-windows');

View File

@ -164,7 +164,7 @@ See [erl-tdlib](https://github.com/lattenwald/erl-tdlib) for an example of TDLib
TDLib can be used from the PHP programming language by wrapping its functionality in a PHP extension.
See [phptdlib](https://github.com/yaroslavche/phptdlib) or [PIF-TDPony](https://github.com/danog/pif-tdpony) for examples of such extensions which provide access to TDLib from PHP.
See [phptdlib](https://github.com/yaroslavche/phptdlib), [tdlib](https://github.com/aurimasniekis/php-ext-tdlib) or [PIF-TDPony](https://github.com/danog/pif-tdpony) for examples of such extensions which provide access to TDLib from PHP.
See [tdlib-bundle](https://github.com/yaroslavche/tdlib-bundle) a Symfony bundle based on [phptdlib](https://github.com/yaroslavche/phptdlib).
<a name="lua"></a>

View File

@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
project(TdExample VERSION 1.0 LANGUAGES CXX)
find_package(Td 1.5.5 REQUIRED)
find_package(Td 1.6.2 REQUIRED)
add_executable(tdjson_example tdjson_example.cpp)
target_link_libraries(tdjson_example PRIVATE Td::TdJson)

View File

@ -19,7 +19,13 @@ cd <path to vcpkg>
cd <path to TDLib sources>/example/csharp
mkdir build
cd build
cmake -DTD_ENABLE_DOTNET=ON -DCMAKE_TOOLCHAIN_FILE=<path to vcpkg>\scripts\buildsystems\vcpkg.cmake ../../..
cmake -A Win32 -DTD_ENABLE_DOTNET=ON -DCMAKE_TOOLCHAIN_FILE=<path to vcpkg>/scripts/buildsystems/vcpkg.cmake ../../..
cmake --build . --config Release
cmake --build . --config Debug
cd ..
mkdir build64
cd build64
cmake -A x64 -DTD_ENABLE_DOTNET=ON -DCMAKE_TOOLCHAIN_FILE=<path to vcpkg>/scripts/buildsystems/vcpkg.cmake ../../..
cmake --build . --config Release
cmake --build . --config Debug
```

View File

@ -33,6 +33,24 @@
<PropertyGroup>
<RootNamespace>TdExample</RootNamespace>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.CSharp" />
<Reference Include="System" />
@ -43,41 +61,57 @@
<Reference Include="System.Xml.Linq" />
<Reference Include="Telegram.Td, Version=0.0.0.0, Culture=neutral, processorArchitecture=AMD64">
<SpecificVersion>False</SpecificVersion>
<HintPath Condition=" '$(Configuration)' == 'Debug' ">build\Debug\Telegram.Td.dll</HintPath>
<HintPath Condition=" '$(Configuration)' == 'Release' ">build\Release\Telegram.Td.dll</HintPath>
<HintPath Condition=" '$(Platform)' == 'x86' ">build\$(Configuration)\Telegram.Td.dll</HintPath>
<HintPath Condition=" '$(Platform)' == 'x64' ">build64\$(Configuration)\Telegram.Td.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="TdExample.cs" />
</ItemGroup>
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
<Content Include="build\Debug\LIBEAY32.dll">
<Link>LIBEAY32.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="build\Debug\SSLEAY32.dll">
<Link>SSLEAY32.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<Content Include="build\Debug\zlibd1.dll">
<Link>zlibd1.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup Condition=" '$(Configuration)' == 'Release' ">
<Content Include="build\Release\LIBEAY32.dll">
<Link>LIBEAY32.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="build\Release\SSLEAY32.dll">
<Link>SSLEAY32.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<Content Include="build\Release\zlib1.dll">
<Link>zlib1.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
<Content Include="build64\Debug\zlibd1.dll">
<Link>zlibd1.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
<Content Include="build64\Release\zlib1.dll">
<Link>zlib1.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup Condition=" '$(Platform)' == 'x86' ">
<Content Include="build\$(Configuration)\libcrypto-1_1.dll">
<Link>libcrypto-1_1.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="build\$(Configuration)\libssl-1_1.dll">
<Link>libssl-1_1.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup Condition=" '$(Platform)' == 'x64' ">
<Content Include="build64\$(Configuration)\libcrypto-1_1-x64.dll">
<Link>libcrypto-1_1-x64.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="build64\$(Configuration)\libssl-1_1-x64.dll">
<Link>libssl-1_1-x64.dll</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSHARP.Targets" />
<ProjectExtensions>
<VisualStudio AllowExistingFolder="true" />

View File

@ -1,22 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
# Visual Studio 15
VisualStudioVersion = 15.0.28010.2046
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TdExample", "TdExample.csproj", "{3F9A93EA-DC26-4F8B-ACE0-131B33B00CA7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{3F9A93EA-DC26-4F8B-ACE0-131B33B00CA7}.Debug|x64.ActiveCfg = Debug|x64
{3F9A93EA-DC26-4F8B-ACE0-131B33B00CA7}.Debug|x64.Build.0 = Debug|x64
{3F9A93EA-DC26-4F8B-ACE0-131B33B00CA7}.Debug|x86.ActiveCfg = Debug|x86
{3F9A93EA-DC26-4F8B-ACE0-131B33B00CA7}.Debug|x86.Build.0 = Debug|x86
{3F9A93EA-DC26-4F8B-ACE0-131B33B00CA7}.Release|x64.ActiveCfg = Release|x64
{3F9A93EA-DC26-4F8B-ACE0-131B33B00CA7}.Release|x64.Build.0 = Release|x64
{3F9A93EA-DC26-4F8B-ACE0-131B33B00CA7}.Release|x86.ActiveCfg = Release|x86
{3F9A93EA-DC26-4F8B-ACE0-131B33B00CA7}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {865856BA-F733-45DF-B35F-12607605B023}
EndGlobalSection
EndGlobal

View File

@ -21,6 +21,9 @@ message(STATUS "Found Java: ${Java_JAVAC_EXECUTABLE} ${Java_JAVADOC_EXECUTABLE}"
# Generating TdApi.java
find_program(PHP_EXECUTABLE php)
if ((CMAKE_SYSTEM_NAME MATCHES "FreeBSD") AND (CMAKE_SYSTEM_VERSION MATCHES "HBSD"))
set(PHP_EXECUTABLE "PHP_EXECUTABLE-NOTFOUND")
endif()
set(TD_API_JAVA_PACKAGE "org/drinkless/tdlib")
set(TD_API_JAVA_PATH ${CMAKE_CURRENT_SOURCE_DIR})

View File

@ -112,7 +112,7 @@ while True:
# set an encryption key for database to let know TDLib how to open the database
if auth_state['@type'] == 'authorizationStateWaitEncryptionKey':
td_send({'@type': 'checkDatabaseEncryptionKey', 'key': 'my_key'})
td_send({'@type': 'checkDatabaseEncryptionKey', 'encryption_key': ''})
# enter phone number to log in
if auth_state['@type'] == 'authorizationStateWaitPhoneNumber':

View File

@ -124,7 +124,7 @@ func updateAuthorizationState(authorizationState: Dictionary<String, Any>) {
]);
case "authorizationStateWaitEncryptionKey":
client.queryAsync(query: ["@type":"checkDatabaseEncryptionKey", "key":"cucumber"])
client.queryAsync(query: ["@type":"checkDatabaseEncryptionKey", "encryption_key":""])
case "authorizationStateWaitPhoneNumber":
print("Enter your phone number: ")

View File

@ -10,7 +10,7 @@ This is an example of building TDLib SDK for Universal Windows Platform and an e
* Install `zlib` and `openssl` for all UWP architectures using `vcpkg`:
```
cd <path to vcpkg>
.\vcpkg.exe install openssl:arm-uwp openssl:x64-uwp openssl:x86-uwp zlib:arm-uwp zlib:x64-uwp zlib:x86-uwp
.\vcpkg.exe install openssl-uwp:arm-uwp openssl-uwp:x64-uwp openssl-uwp:x86-uwp zlib:arm-uwp zlib:x64-uwp zlib:x86-uwp
```
* (Optional. For XML documentation generation.) Download [PHP](https://windows.php.net/download#php-7.2). Add the path to php.exe to the PATH environment variable.
* Download and install [gperf](https://sourceforge.net/projects/gnuwin32/files/gperf/3.0.1/). Add the path to gperf.exe to the PATH environment variable.

View File

@ -35,7 +35,7 @@ function prepare {
cd build-native
cmake $td_root -DCMAKE_TOOLCHAIN_FILE="$vcpkg_cmake" -DTD_ENABLE_DOTNET=ON
cmake "$td_root" -A Win32 -DCMAKE_TOOLCHAIN_FILE="$vcpkg_cmake" -DTD_ENABLE_DOTNET=ON
CheckLastExitCode
cmake --build . --target prepare_cross_compiling
CheckLastExitCode
@ -92,8 +92,8 @@ function export {
New-Item -ItemType Directory -Force -Path vsix/Redist/Retail/${arch}
New-Item -ItemType Directory -Force -Path vsix/References/CommonConfiguration/${arch}
cp ${arch}/Debug/* -include "LIBEAY*","SSLEAY*","zlib*" vsix/Redist/Debug/${arch}/
cp ${arch}/Release/* -include "LIBEAY*","SSLEAY*","zlib*" vsix/Redist/Retail/${arch}/
cp ${arch}/Debug/* -include "SSLEAY*","LIBEAY*","libcrypto*","libssl*","zlib*" vsix/Redist/Debug/${arch}/
cp ${arch}/Release/* -include "SSLEAY*","LIBEAY*","libcrypto*","libssl*","zlib*" vsix/Redist/Retail/${arch}/
cp ${arch}/Debug/* -filter "Telegram.Td.*" -include "*.lib" vsix/DesignTime/Debug/${arch}/
cp ${arch}/Release/* -filter "Telegram.Td.*" -include "*.lib" vsix/DesignTime/Retail/${arch}/

View File

@ -1,6 +1,6 @@
<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011">
<Metadata>
<Identity Id="Telegram.Td.UWP" Version="1.5.5" Language="en-US" Publisher="Telegram LLC" />
<Identity Id="Telegram.Td.UWP" Version="1.6.2" Language="en-US" Publisher="Telegram LLC" />
<DisplayName>TDLib for Universal Windows Platform</DisplayName>
<Description>TDLib is a library for building Telegram clients</Description>
<MoreInfo>https://core.telegram.org/tdlib</MoreInfo>

View File

@ -1,6 +1,6 @@
{
"name": "tdweb",
"version": "1.5.0",
"version": "1.6.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@ -1162,6 +1162,12 @@
"integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==",
"dev": true
},
"ajv-keywords": {
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz",
"integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==",
"dev": true
},
"ansi-escapes": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz",
@ -1485,9 +1491,9 @@
"dev": true
},
"bluebird": {
"version": "3.5.4",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.4.tgz",
"integrity": "sha512-FG+nFEZChJrbQ9tIccIfZJBz3J7mLrAhxakAbnrJWn8d7aKOC+LWifa0G+p4ZqKp4y13T7juYvdhq9NzKdsrjw==",
"version": "3.7.2",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
"integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
"dev": true
},
"bn.js": {
@ -1686,41 +1692,41 @@
"dev": true
},
"cacache": {
"version": "11.3.2",
"resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.2.tgz",
"integrity": "sha512-E0zP4EPGDOaT2chM08Als91eYnf8Z+eH1awwwVsngUmgppfM5jjJ8l3z5vO5p5w/I3LsiXawb1sW0VY65pQABg==",
"version": "12.0.3",
"resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.3.tgz",
"integrity": "sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw==",
"dev": true,
"requires": {
"bluebird": "^3.5.3",
"bluebird": "^3.5.5",
"chownr": "^1.1.1",
"figgy-pudding": "^3.5.1",
"glob": "^7.1.3",
"glob": "^7.1.4",
"graceful-fs": "^4.1.15",
"infer-owner": "^1.0.3",
"lru-cache": "^5.1.1",
"mississippi": "^3.0.0",
"mkdirp": "^0.5.1",
"move-concurrently": "^1.0.1",
"promise-inflight": "^1.0.1",
"rimraf": "^2.6.2",
"rimraf": "^2.6.3",
"ssri": "^6.0.1",
"unique-filename": "^1.1.1",
"y18n": "^4.0.0"
},
"dependencies": {
"lru-cache": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
"integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
"glob": {
"version": "7.1.6",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
"dev": true,
"requires": {
"yallist": "^3.0.2"
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
},
"yallist": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz",
"integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==",
"dev": true
}
}
},
@ -1818,9 +1824,9 @@
}
},
"chownr": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz",
"integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==",
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.3.tgz",
"integrity": "sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw==",
"dev": true
},
"chrome-trace-event": {
@ -2225,9 +2231,9 @@
}
},
"cyclist": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz",
"integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=",
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz",
"integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=",
"dev": true
},
"damerau-levenshtein": {
@ -2769,10 +2775,21 @@
}
},
"eslint-utils": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz",
"integrity": "sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q==",
"dev": true
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz",
"integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==",
"dev": true,
"requires": {
"eslint-visitor-keys": "^1.1.0"
},
"dependencies": {
"eslint-visitor-keys": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz",
"integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==",
"dev": true
}
}
},
"eslint-visitor-keys": {
"version": "1.0.0",
@ -4433,6 +4450,12 @@
"integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=",
"dev": true
},
"infer-owner": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz",
"integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==",
"dev": true
},
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
@ -4794,6 +4817,12 @@
"integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
"dev": true
},
"is-wsl": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
"integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=",
"dev": true
},
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
@ -5378,6 +5407,15 @@
"js-tokens": "^3.0.0 || ^4.0.0"
}
},
"lru-cache": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
"integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
"dev": true,
"requires": {
"yallist": "^3.0.2"
}
},
"make-dir": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
@ -5997,12 +6035,12 @@
"dev": true
},
"parallel-transform": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz",
"integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=",
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz",
"integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==",
"dev": true,
"requires": {
"cyclist": "~0.2.2",
"cyclist": "^1.0.1",
"inherits": "^2.0.3",
"readable-stream": "^2.1.5"
}
@ -6676,9 +6714,9 @@
"dev": true
},
"serialize-javascript": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.7.0.tgz",
"integrity": "sha512-ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA==",
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz",
"integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==",
"dev": true
},
"set-blocking": {
@ -6934,9 +6972,9 @@
}
},
"source-map-support": {
"version": "0.5.12",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz",
"integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==",
"version": "0.5.16",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz",
"integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==",
"dev": true,
"requires": {
"buffer-from": "^1.0.0",
@ -7074,9 +7112,9 @@
}
},
"stream-shift": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz",
"integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=",
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz",
"integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==",
"dev": true
},
"string-argv": {
@ -7224,16 +7262,22 @@
"dev": true
},
"terser": {
"version": "3.17.0",
"resolved": "https://registry.npmjs.org/terser/-/terser-3.17.0.tgz",
"integrity": "sha512-/FQzzPJmCpjAH9Xvk2paiWrFq+5M6aVOf+2KRbwhByISDX/EujxsK+BAvrhb6H+2rtrLCHK9N01wO014vrIwVQ==",
"version": "4.6.3",
"resolved": "https://registry.npmjs.org/terser/-/terser-4.6.3.tgz",
"integrity": "sha512-Lw+ieAXmY69d09IIc/yqeBqXpEQIpDGZqT34ui1QWXIUpR2RjbqEkT8X7Lgex19hslSqcWM5iMN2kM11eMsESQ==",
"dev": true,
"requires": {
"commander": "^2.19.0",
"commander": "^2.20.0",
"source-map": "~0.6.1",
"source-map-support": "~0.5.10"
"source-map-support": "~0.5.12"
},
"dependencies": {
"commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
"dev": true
},
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
@ -7243,51 +7287,22 @@
}
},
"terser-webpack-plugin": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.2.3.tgz",
"integrity": "sha512-GOK7q85oAb/5kE12fMuLdn2btOS9OBZn4VsecpHDywoUC/jLhSAKOiYo0ezx7ss2EXPMzyEWFoE0s1WLE+4+oA==",
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz",
"integrity": "sha512-QMxecFz/gHQwteWwSo5nTc6UaICqN1bMedC5sMtUc7y3Ha3Q8y6ZO0iCR8pq4RJC8Hjf0FEPEHZqcMB/+DFCrA==",
"dev": true,
"requires": {
"cacache": "^11.0.2",
"find-cache-dir": "^2.0.0",
"cacache": "^12.0.2",
"find-cache-dir": "^2.1.0",
"is-wsl": "^1.1.0",
"schema-utils": "^1.0.0",
"serialize-javascript": "^1.4.0",
"serialize-javascript": "^2.1.2",
"source-map": "^0.6.1",
"terser": "^3.16.1",
"webpack-sources": "^1.1.0",
"worker-farm": "^1.5.2"
"terser": "^4.1.2",
"webpack-sources": "^1.4.0",
"worker-farm": "^1.7.0"
},
"dependencies": {
"ajv": {
"version": "6.10.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz",
"integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==",
"dev": true,
"requires": {
"fast-deep-equal": "^2.0.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
}
},
"ajv-keywords": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.0.tgz",
"integrity": "sha512-aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw==",
"dev": true
},
"fast-deep-equal": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
"integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
"dev": true
},
"json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
"dev": true
},
"schema-utils": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
@ -7304,6 +7319,16 @@
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true
},
"webpack-sources": {
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz",
"integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==",
"dev": true,
"requires": {
"source-list-map": "^2.0.0",
"source-map": "~0.6.1"
}
}
}
},
@ -7499,9 +7524,9 @@
}
},
"unique-slug": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.1.tgz",
"integrity": "sha512-n9cU6+gITaVu7VGj1Z8feKMmfAjEAQGhwD9fE3zvpRRa0wEIx8ODYkVGfSc94M2OX00tUFV8wH3zYbm1I8mxFg==",
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz",
"integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==",
"dev": true,
"requires": {
"imurmurhash": "^0.1.4"
@ -7860,9 +7885,9 @@
"dev": true
},
"worker-farm": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.6.0.tgz",
"integrity": "sha512-6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ==",
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz",
"integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==",
"dev": true,
"requires": {
"errno": "~0.1.7"
@ -7936,6 +7961,12 @@
"integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
"dev": true
},
"yallist": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
"dev": true
},
"yargs": {
"version": "12.0.5",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz",

View File

@ -1,6 +1,6 @@
{
"name": "tdweb",
"version": "1.5.0",
"version": "1.6.0",
"description": "Javascript interface for TDLib (telegram library)",
"main": "dist/tdweb.js",
"repository": {

View File

@ -589,7 +589,7 @@ class FileManager {
'@type': 'readFilePart',
path: info.file.local.path,
offset: offset,
size: size
count: size
});
res.data = new Blob([res.data]);
res.transaction_id = -2;
@ -632,7 +632,7 @@ class FileManager {
this.lru.onUsed(info.node);
}
query.offset = query.offset || 0;
query.size = query.size || 0;
query.size = query.count || query.size || 0;
const response = await this.doLoad(info, query.offset, query.size);
return {
'@type': 'filePart',

View File

@ -11,13 +11,10 @@ set(TL_TD_AUTO_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/auto PARENT_SCOPE)
set(TD_AUTO_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/auto/td)
set(TL_TD_AUTO
set(TL_TD_AUTO_SOURCE
${TD_AUTO_INCLUDE_DIR}/mtproto/mtproto_api.cpp
${TD_AUTO_INCLUDE_DIR}/mtproto/mtproto_api.h
${TD_AUTO_INCLUDE_DIR}/mtproto/mtproto_api.hpp
${TD_AUTO_INCLUDE_DIR}/telegram/td_api.cpp
${TD_AUTO_INCLUDE_DIR}/telegram/td_api.h
${TD_AUTO_INCLUDE_DIR}/telegram/td_api.hpp
${TD_AUTO_INCLUDE_DIR}/telegram/telegram_api.cpp
${TD_AUTO_INCLUDE_DIR}/telegram/telegram_api.h
${TD_AUTO_INCLUDE_DIR}/telegram/telegram_api.hpp
@ -27,7 +24,14 @@ set(TL_TD_AUTO
PARENT_SCOPE
)
set(TL_TD_JSON_AUTO
set(TL_TD_API_AUTO_SOURCE
${TD_AUTO_INCLUDE_DIR}/telegram/td_api.cpp
${TD_AUTO_INCLUDE_DIR}/telegram/td_api.h
${TD_AUTO_INCLUDE_DIR}/telegram/td_api.hpp
PARENT_SCOPE
)
set(TL_TD_JSON_AUTO_SOURCE
${TD_AUTO_INCLUDE_DIR}/telegram/td_api_json.cpp
${TD_AUTO_INCLUDE_DIR}/telegram/td_api_json.h
PARENT_SCOPE
@ -36,14 +40,14 @@ set(TL_TD_JSON_AUTO
set(TL_TD_API_TLO ${CMAKE_CURRENT_SOURCE_DIR}/scheme/td_api.tlo)
set(TL_TD_API_TLO ${TL_TD_API_TLO} PARENT_SCOPE)
set(TL_C_AUTO
set(TL_C_AUTO_SOURCE
${TD_AUTO_INCLUDE_DIR}/telegram/td_tdc_api.cpp
${TD_AUTO_INCLUDE_DIR}/telegram/td_tdc_api.h
${TD_AUTO_INCLUDE_DIR}/telegram/td_tdc_api_inner.h
PARENT_SCOPE
)
set(TL_DOTNET_AUTO
set(TL_DOTNET_AUTO_SOURCE
${TD_AUTO_INCLUDE_DIR}/telegram/TdDotNetApi.cpp
${TD_AUTO_INCLUDE_DIR}/telegram/TdDotNetApi.h
PARENT_SCOPE
@ -92,6 +96,10 @@ set(TL_GENERATE_JSON_SOURCE
if (NOT CMAKE_CROSSCOMPILING)
find_program(PHP_EXECUTABLE php)
if ((CMAKE_SYSTEM_NAME MATCHES "FreeBSD") AND (CMAKE_SYSTEM_VERSION MATCHES "HBSD"))
set(PHP_EXECUTABLE "PHP_EXECUTABLE-NOTFOUND")
endif()
if (PHP_EXECUTABLE AND NOT TD_ENABLE_DOTNET)
set(GENERATE_COMMON_CMD generate_common && ${PHP_EXECUTABLE} DoxygenTlDocumentationGenerator.php scheme/td_api.tl auto/td/telegram/td_api.h)
else()

View File

@ -54,7 +54,7 @@ class DotnetTlDocumentationGenerator extends TlDocumentationGenerator
case 'string':
return 'String^';
case 'bytes':
return 'Array<byte>^';
return 'Array<BYTE>^';
case 'bool':
case 'int':
case 'long':
@ -210,7 +210,7 @@ EOT
while (substr($field_type, $pos, 6) === 'Array<') {
$pos += 6;
}
if (substr($field_type, $pos, 6) !== 'String' && ucfirst(substr($field_type, $pos)) === substr($field_type, $pos)) {
if (substr($field_type, $pos, 4) !== 'BYTE' && substr($field_type, $pos, 6) !== 'String' && ucfirst(substr($field_type, $pos)) === substr($field_type, $pos)) {
$field_type = substr($field_type, 0, $pos).'::Telegram::Td::Api::'.substr($field_type, $pos);
}
$full_constructor .= $colon.$field_type.' '.$this->getParameterName($name, $class_name);

View File

@ -10,15 +10,17 @@ class DoxygenTlDocumentationGenerator extends TlDocumentationGenerator
case 'Bool':
return 'bool ';
case 'int32':
return 'std::int32_t ';
return 'int32 ';
case 'int53':
return 'int53 ';
case 'int64':
return 'std::int64_t ';
return 'int64 ';
case 'double':
return 'double ';
case 'string':
return 'string const &';
case 'bytes':
return 'std::string const &';
return 'bytes const &';
default:
if (substr($type, 0, 6) === 'vector') {
@ -67,15 +69,17 @@ class DoxygenTlDocumentationGenerator extends TlDocumentationGenerator
case 'Bool':
return 'bool';
case 'int32':
return 'std::int32_t';
return 'int32';
case 'int53':
return 'int53';
case 'int64':
return 'std::int64_t';
return 'int64';
case 'double':
return 'double';
case 'string':
return 'string';
case 'bytes':
return 'std::string';
return 'bytes';
case 'bool':
case 'int':
case 'long':
@ -163,6 +167,41 @@ class DoxygenTlDocumentationGenerator extends TlDocumentationGenerator
* Contains declarations of all functions and types which represent a public TDLib interface.
*/
EOT
);
$this->addDocumentation('using int32 = std::int32_t;', <<<EOT
/**
* This type is used to store 32-bit signed integers, which can be represented as Number in JSON.
*/
EOT
);
$this->addDocumentation('using int53 = std::int64_t;', <<<EOT
/**
* This type is used to store 53-bit signed integers, which can be represented as Number in JSON.
*/
EOT
);
$this->addDocumentation('using int64 = std::int64_t;', <<<EOT
/**
* This type is used to store 64-bit signed integers, which can't be represented as Number in JSON and are represented as String instead.
*/
EOT
);
$this->addDocumentation('using string = std::string;', <<<EOT
/**
* This type is used to store UTF-8 strings.
*/
EOT
);
$this->addDocumentation('using bytes = std::string;', <<<EOT
/**
* This type is used to store arbitrary sequences of bytes. In JSON interface the bytes are base64-encoded.
*/
EOT
);
$this->addDocumentation('using BaseObject', <<<EOT

View File

@ -95,6 +95,7 @@ messageEntityTextUrl#76a6d327 offset:int length:int url:string = MessageEntity;
messageEntityMentionName#352dca58 offset:int length:int user_id:int = MessageEntity;
messageEntityPhone#9b69e34b offset:int length:int = MessageEntity;
messageEntityCashtag#4c4e743f offset:int length:int = MessageEntity;
messageEntityBankCard#761e6af4 offset:int length:int = MessageEntity;
inputStickerSetShortName#861cc8a0 short_name:string = InputStickerSet;
inputStickerSetEmpty#ffb62b95 = InputStickerSet;
decryptedMessageMediaVenue#8a0df56f lat:double long:double title:string address:string provider:string venue_id:string = DecryptedMessageMedia;

Binary file not shown.

View File

@ -297,7 +297,7 @@ userTypeBot can_join_groups:Bool can_read_all_group_messages:Bool is_inline:Bool
userTypeUnknown = UserType;
//@description Represents commands supported by a bot @command Text of the bot command @param_description Description of the bot command
//@description Represents a command supported by a bot @command Text of the bot command @param_description Description of the bot command
botCommand command:string description:string = BotCommand;
//@description Provides information about a bot and its supported commands @param_description Long description shown on the user info page @commands A list of commands supported by the bot
@ -460,7 +460,7 @@ basicGroupFullInfo description:string creator_user_id:int32 members:vector<chatM
//@username Username of the supergroup or channel; empty for private supergroups or channels
//@date Point in time (Unix timestamp) when the current user joined, or the point in time when the supergroup or channel was created, in case the user is not a member
//@status Status of the current user in the supergroup or channel; custom title will be always empty
//@member_count Member count; 0 if unknown. Currently it is guaranteed to be known only if the supergroup or channel was found through SearchPublicChats
//@member_count Number of members in the supergroup or channel; 0 if unknown. Currently it is guaranteed to be known only if the supergroup or channel was found through SearchPublicChats
//@has_linked_chat True, if the channel has a discussion group, or the supergroup is the designated discussion group for a channel
//@has_location True, if the supergroup is connected to a location, i.e. the supergroup is a location-based supergroup
//@sign_messages True, if messages sent to the channel should contain information about the sender. This field is only applicable to channels
@ -484,7 +484,7 @@ supergroup id:int32 username:string date:int32 status:ChatMemberStatus member_co
//@can_set_username True, if the chat username can be changed
//@can_set_sticker_set True, if the supergroup sticker set can be changed
//@can_set_location True, if the supergroup location can be changed
//@can_view_statistics True, if the channel statistics is available through getChatStatisticsUrl
//@can_view_statistics True, if the channel statistics is available
//@is_all_history_available True, if new chat members will have access to old messages. In public or discussion groups and both public and private channels, old messages are always available, so this option affects only private supergroups without a linked chat. The value of this field is only available for chat administrators
//@sticker_set_id Identifier of the supergroup sticker set; 0 if none
//@location Location to which the supergroup is connected; may be null
@ -615,8 +615,11 @@ chatNotificationSettings use_default_mute_for:Bool mute_for:int32 use_default_so
scopeNotificationSettings mute_for:int32 sound:string show_preview:Bool disable_pinned_message_notifications:Bool disable_mention_notifications:Bool = ScopeNotificationSettings;
//@description Contains information about a message draft @reply_to_message_id Identifier of the message to reply to; 0 if none @input_message_text Content of the message draft; this should always be of type inputMessageText
draftMessage reply_to_message_id:int53 input_message_text:InputMessageContent = DraftMessage;
//@description Contains information about a message draft
//@reply_to_message_id Identifier of the message to reply to; 0 if none
//@date Point in time (Unix timestamp) when the draft was created
//@input_message_text Content of the message draft; this should always be of type inputMessageText
draftMessage reply_to_message_id:int53 date:int32 input_message_text:InputMessageContent = DraftMessage;
//@class ChatType @description Describes the type of a chat
@ -691,7 +694,7 @@ chatInviteLink invite_link:string = ChatInviteLink;
//@type Contains information about the type of the chat
//@title Title of the chat
//@photo Chat photo; may be null
//@member_count Number of members
//@member_count Number of members in the chat
//@member_user_ids User identifiers of some chat members that may be known to the current user
//@is_public True, if the chat is a public supergroup or channel, i.e. it has a username or it is a location-based supergroup
chatInviteLinkInfo chat_id:int53 type:ChatType title:string photo:chatPhoto member_count:int32 member_user_ids:vector<int32> is_public:Bool = ChatInviteLinkInfo;
@ -843,8 +846,14 @@ richTextPhoneNumber text:RichText phone_number:string = RichText;
//@height Height of a bounding box in which the image should be shown; 0 if unknown
richTextIcon document:document width:int32 height:int32 = RichText;
//@description A rich text anchor @text Text @name Anchor name
richTextAnchor text:RichText name:string = RichText;
//@description A rich text reference of a text on the same web page @text The text @reference_text The text to show on click @url An HTTP URL, opening the reference
richTextReference text:RichText reference_text:RichText url:string = RichText;
//@description An anchor @name Anchor name
richTextAnchor name:string = RichText;
//@description A link to an anchor on the same web page @text The link text @name The anchor name. If the name is empty, the link should bring back to top @url An HTTP URL, opening the anchor
richTextAnchorLink text:RichText name:string url:string = RichText;
//@description A concatenation of rich texts @texts Texts
richTexts texts:vector<RichText> = RichText;
@ -978,12 +987,13 @@ pageBlockRelatedArticles header:RichText articles:vector<pageBlockRelatedArticle
pageBlockMap location:location zoom:int32 width:int32 height:int32 caption:pageBlockCaption = PageBlock;
//@description Describes an instant view page for a web page @page_blocks Content of the web page
//@description Describes an instant view page for a web page
//@page_blocks Content of the web page
//@view_count Number of the instant view views; 0 if unknown
//@version Version of the instant view, currently can be 1 or 2
//@url Instant view URL; may be different from WebPage.url and must be used for the correct anchors handling
//@is_rtl True, if the instant view must be shown from right to left
//@is_full True, if the instant view contains the full page. A network request might be needed to get the full web page instant view
webPageInstantView page_blocks:vector<PageBlock> version:int32 url:string is_rtl:Bool is_full:Bool = WebPageInstantView;
webPageInstantView page_blocks:vector<PageBlock> view_count:int32 version:int32 is_rtl:Bool is_full:Bool = WebPageInstantView;
//@description Describes a web page preview
@ -1008,7 +1018,14 @@ webPageInstantView page_blocks:vector<PageBlock> version:int32 url:string is_rtl
//@video_note Preview of the content as a video note, if available; may be null
//@voice_note Preview of the content as a voice note, if available; may be null
//@instant_view_version Version of instant view, available for the web page (currently can be 1 or 2), 0 if none
webPage url:string display_url:string type:string site_name:string title:string description:string photo:photo embed_url:string embed_type:string embed_width:int32 embed_height:int32 duration:int32 author:string animation:animation audio:audio document:document sticker:sticker video:video video_note:videoNote voice_note:voiceNote instant_view_version:int32 = WebPage;
webPage url:string display_url:string type:string site_name:string title:string description:formattedText photo:photo embed_url:string embed_type:string embed_width:int32 embed_height:int32 duration:int32 author:string animation:animation audio:audio document:document sticker:sticker video:video video_note:videoNote voice_note:voiceNote instant_view_version:int32 = WebPage;
//@description Describes an action associated with a bank card number @text Action text @url The URL to be opened
bankCardActionOpenUrl text:string url:string = BankCardActionOpenUrl;
//@description Information about a bank card @title Title of the bank card description @actions Actions that can be done with the bank card number
bankCardInfo title:string actions:vector<bankCardActionOpenUrl> = BankCardInfo;
//@description Describes an address @country_code A two-letter ISO 3166-1 alpha-2 country code @state State, if applicable @city City @street_line1 First line of the address @street_line2 Second line of the address @postal_code Address postal code
@ -1360,6 +1377,9 @@ messageVenue venue:venue = MessageContent;
//@description A message with a user contact @contact The contact description
messageContact contact:contact = MessageContent;
//@description A dice message. The dice value is randomly generated by the server @value The dice value; 0-6. If the value is 0, the dice must roll infinitely
messageDice value:int32 = MessageContent;
//@description A message with a game @game The game description
messageGame game:game = MessageContent;
@ -1466,6 +1486,9 @@ textEntityTypeEmailAddress = TextEntityType;
//@description A phone number
textEntityTypePhoneNumber = TextEntityType;
//@description A bank card number. The getBankCardInfo method can be used to get information about the bank card
textEntityTypeBankCardNumber = TextEntityType;
//@description A bold text
textEntityTypeBold = TextEntityType;
@ -1494,7 +1517,7 @@ textEntityTypeTextUrl url:string = TextEntityType;
textEntityTypeMentionName user_id:int32 = TextEntityType;
//@description A thumbnail to be sent along with a file; should be in JPEG or WEBP format for stickers, and less than 200 kB in size @thumbnail Thumbnail file to send. Sending thumbnails by file_id is currently not supported
//@description A thumbnail to be sent along with a file; should be in JPEG or WEBP format for stickers, and less than 200 KB in size @thumbnail Thumbnail file to send. Sending thumbnails by file_id is currently not supported
//@width Thumbnail width, usually shouldn't exceed 320. Use 0 if unknown @height Thumbnail height, usually shouldn't exceed 320. Use 0 if unknown
inputThumbnail thumbnail:InputFile width:int32 height:int32 = InputThumbnail;
@ -1558,6 +1581,9 @@ inputMessageVenue venue:venue = InputMessageContent;
//@description A message containing a user contact @contact Contact to send
inputMessageContact contact:contact = InputMessageContent;
//@description A dice message
inputMessageDice = 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
inputMessageGame bot_user_id:int32 game_short_name:string = InputMessageContent;
@ -1720,8 +1746,13 @@ callDiscardReasonDisconnected = CallDiscardReason;
callDiscardReasonHungUp = CallDiscardReason;
//@description Specifies the supported call protocols @udp_p2p True, if UDP peer-to-peer connections are supported @udp_reflector True, if connection through UDP reflectors is supported @min_layer The minimum supported API layer; use 65 @max_layer The maximum supported API layer; use 65
callProtocol udp_p2p:Bool udp_reflector:Bool min_layer:int32 max_layer:int32 = CallProtocol;
//@description Specifies the supported call protocols
//@udp_p2p True, if UDP peer-to-peer connections are supported
//@udp_reflector True, if connection through UDP reflectors is supported
//@min_layer The minimum supported API layer; use 65
//@max_layer The maximum supported API layer; use 65
//@library_versions List of supported libtgvoip versions
callProtocol udp_p2p:Bool udp_reflector:Bool min_layer:int32 max_layer:int32 library_versions:vector<string> = CallProtocol;
//@description Describes the address of UDP reflectors @id Reflector identifier @ip IPv4 reflector address @ipv6 IPv6 reflector address @port Reflector port number @peer_tag Connection peer tag
callConnection id:int64 ip:string ipv6:string port:int32 peer_tag:bytes = CallConnection;
@ -2291,8 +2322,11 @@ notificationTypeNewCall call_id:int32 = NotificationType;
//@description New message was received through a push notification
//@message_id The message identifier. The message will not be available in the chat history, but the ID can be used in viewMessages and as reply_to_message_id
//@sender_user_id Sender of the message. Corresponding user may be inaccessible @content Push message content
notificationTypeNewPushMessage message_id:int53 sender_user_id:int32 content:PushMessageContent = NotificationType;
//@sender_user_id Sender of the message; 0 if unknown. Corresponding user may be inaccessible
//@sender_name Name of the sender; can be different from the name of the sender user
//@is_outgoing True, if the message is outgoing
//@content Push message content
notificationTypeNewPushMessage message_id:int53 sender_user_id:int32 sender_name:string is_outgoing:Bool content:PushMessageContent = NotificationType;
//@class NotificationGroupType @description Describes the type of notifications in a notification group
@ -2687,11 +2721,11 @@ deepLinkInfo text:formattedText need_update_application:Bool = DeepLinkInfo;
//@class TextParseMode @description Describes the way the text should be parsed for TextEntities
//@description The text should be parsed in markdown-style
//@version Version of the parser: 0 or 1 - Bot API Markdown parse mode, 2 - Bot API MarkdownV2 parse mode
//@description The text uses Markdown-style formatting
//@version Version of the parser: 0 or 1 - Telegram Bot API "Markdown" parse mode, 2 - Telegram Bot API "MarkdownV2" parse mode
textParseModeMarkdown version:int32 = TextParseMode;
//@description The text should be parsed in HTML-style
//@description The text uses HTML-style formatting. The same as Telegram Bot API "HTML" parse mode
textParseModeHTML = TextParseMode;
@ -2700,7 +2734,7 @@ textParseModeHTML = TextParseMode;
//@description A SOCKS5 proxy server @username Username for logging in; may be empty @password Password for logging in; may be empty
proxyTypeSocks5 username:string password:string = ProxyType;
//@description A HTTP transparent proxy server @username Username for logging in; may be empty @password Password for logging in; may be empty @http_only Pass true, if the proxy supports only HTTP requests and doesn't support transparent TCP connections via HTTP CONNECT method
//@description A HTTP transparent proxy server @username Username for logging in; may be empty @password Password for logging in; may be empty @http_only Pass true if the proxy supports only HTTP requests and doesn't support transparent TCP connections via HTTP CONNECT method
proxyTypeHttp username:string password:string http_only:Bool = ProxyType;
//@description An MTProto proxy server @secret The proxy's secret in hexadecimal encoding
@ -2714,8 +2748,64 @@ proxy id:int32 server:string port:int32 last_used_date:int32 is_enabled:Bool typ
proxies proxies:vector<proxy> = Proxies;
//@description Describes a sticker that should be added to a sticker set @png_sticker PNG image with the sticker; must be up to 512 kB in size and fit in a 512x512 square @emojis Emoji corresponding to the sticker @mask_position For masks, position where the mask should be placed; may be null
inputSticker png_sticker:InputFile emojis:string mask_position:maskPosition = InputSticker;
//@class InputSticker @description Describes a sticker that needs to be added to a sticker set
//@description A static sticker in PNG format, which will be converted to WEBP server-side
//@sticker PNG image with the sticker; must be up to 512 KB in size and fit in a 512x512 square
//@emojis Emojis corresponding to the sticker
//@mask_position For masks, position where the mask should be placed; may be null
inputStickerStatic sticker:InputFile emojis:string mask_position:maskPosition = InputSticker;
//@description An animated sticker in TGS format
//@sticker File with the animated sticker. Only local or uploaded within a week files are supported. See https://core.telegram.org/animated_stickers#technical-requirements for technical requirements
//@emojis Emojis corresponding to the sticker
inputStickerAnimated sticker:InputFile emojis:string = InputSticker;
//@description Represents a date range @start_date Point in time (Unix timestamp) at which the date range begins @end_date Point in time (Unix timestamp) at which the date range ends
dateRange start_date:int32 end_date:int32 = DateRange;
//@description A statistics value @value The value @previous_value The value for the previous day @growth_rate_percentage The growth rate of the value, as a percentage
statisticsValue value:double previous_value:double growth_rate_percentage:double = StatisticsValue;
//@class StatisticsGraph @description Descrbes a statistics graph
//@description A graph data @json_data Graph data in JSON format @zoom_token If non-empty, a token which can be used to receive a zoomed in graph
statisticsGraphData json_data:string zoom_token:string = StatisticsGraph;
//@description The graph data to be asynchronously loaded through getChatStatisticsGraph @token The token to use for data loading
statisticsGraphAsync token:string = StatisticsGraph;
//@description An error message to be shown to the user instead of the graph @error_message The error message
statisticsGraphError error_message:string = StatisticsGraph;
//@description Contains statistics about interactions with a message
//@message_id Message identifier
//@view_count Number of times the message was viewed
//@forward_count Number of times the message was forwarded
chatStatisticsMessageInteractionCounters message_id:int53 view_count:int32 forward_count:int32 = ChatStatisticsMessageInteractionCounters;
//@description A detailed statistics about a chat
//@period A period to which the statistics applies
//@member_count Number of members in the chat
//@mean_view_count Mean number of times the recently sent messages was viewed
//@mean_share_count Mean number of times the recently sent messages was shared
//@enabled_notifications_percentage A percentage of users with enabled notifications for the chat
//@member_count_graph A graph containing number of members in the chat
//@join_graph A graph containing number of members joined and left the chat
//@mute_graph A graph containing number of members muted and unmuted the chat
//@view_count_by_hour_graph A graph containing number of message views in a given hour in the last two weeks
//@view_count_by_source_graph A graph containing number of message views per source
//@join_by_source_graph A graph containing number of new member joins per source
//@language_graph A graph containing number of users viewed chat messages per language
//@message_interaction_graph A graph containing number of chat message views and shares
//@instant_view_interaction_graph A graph containing number of views of associated with the chat instant views
//@recent_message_interactions Detailed statistics about number of views and shares of recently sent messages
chatStatistics period:dateRange member_count:statisticsValue mean_view_count:statisticsValue mean_share_count:statisticsValue enabled_notifications_percentage:double member_count_graph:StatisticsGraph join_graph:StatisticsGraph mute_graph:StatisticsGraph view_count_by_hour_graph:StatisticsGraph view_count_by_source_graph:StatisticsGraph join_by_source_graph:StatisticsGraph language_graph:StatisticsGraph message_interaction_graph:StatisticsGraph instant_view_interaction_graph:StatisticsGraph recent_message_interactions:vector<chatStatisticsMessageInteractionCounters> = ChatStatistics;
//@class Update @description Contains notifications about data changes
@ -3400,12 +3490,19 @@ editInlineMessageReplyMarkup inline_message_id:string reply_markup:ReplyMarkup =
editMessageSchedulingState chat_id:int53 message_id:int53 scheduling_state:MessageSchedulingState = Ok;
//@description Returns all entities (mentions, hashtags, cashtags, bot commands, URLs, and email addresses) contained in the text. This is an offline method. Can be called before authorization. Can be called synchronously @text The text in which to look for entites
//@description Returns all entities (mentions, hashtags, cashtags, bot commands, bank card numbers, URLs, and email addresses) contained in the text. This is an offline method. Can be called before authorization. Can be called synchronously @text The text in which to look for entites
getTextEntities text:string = TextEntities;
//@description Parses Bold, Italic, Underline, Strikethrough, Code, Pre, PreCode, TextUrl and MentionName entities contained in the text. This is an offline method. Can be called before authorization. Can be called synchronously @text The text which should be parsed @parse_mode Text parse mode
//@description Parses Bold, Italic, Underline, Strikethrough, Code, Pre, PreCode, TextUrl and MentionName entities contained in the text. This is an offline method. Can be called before authorization. Can be called synchronously @text The text to parse @parse_mode Text parse mode
parseTextEntities text:string parse_mode:TextParseMode = FormattedText;
//@description Parses Markdown entities in a human-friendly format, ignoring mark up errors. This is an offline method. Can be called before authorization. Can be called synchronously
//@text The text to parse. For example, "__italic__ ~~strikethrough~~ **bold** `code` ```pre``` __[italic__ text_url](telegram.org) __italic**bold italic__bold**"
parseMarkdown text:formattedText = FormattedText;
//@description Replaces text entities with Markdown formatting in a human-friendly format. Entities that can't be represented in Markdown unambiguously are kept as is. This is an offline method. Can be called before authorization. Can be called synchronously @text The text
getMarkdownText text:formattedText = FormattedText;
//@description Returns the MIME type of a file, guessed by its extension. Returns an empty string on failure. This is an offline method. Can be called before authorization. Can be called synchronously @file_name The name of the file or path to the file
getFileMimeType file_name:string = Text;
@ -3545,7 +3642,7 @@ createNewSecretChat user_id:int32 = Chat;
upgradeBasicGroupChatToSupergroupChat chat_id:int53 = Chat;
//@description Moves a chat to a different chat list. Current chat list of the chat must ne non-null @chat_id Chat identifier @chat_list New chat list of the chat
//@description Moves a chat to a different chat list. Current chat list of the chat must ne non-null @chat_id Chat identifier @chat_list New chat list of the chat. The chat with the current user (Saved Messages) and the chat 777000 (Telegram) can't be moved to the Archive chat list
setChatChatList chat_id:int53 chat_list:ChatList = Ok;
//@description Changes the chat title. Supported only for basic groups, supergroups and channels. Requires can_change_info rights. The title will not be changed until the request to the server has been completed
@ -3891,6 +3988,9 @@ setBio bio:string = Ok;
//@description Changes the username of the current user. If something changes, updateUser will be sent @username The new value of the username. Use an empty string to remove the username
setUsername username:string = Ok;
//@description Changes the location of the current user. Needs to be called if GetOption("is_location_visible") is true and location changes for more than 1 kilometer @location The new location of the user
setLocation location:location = Ok;
//@description Changes the phone number of the user and sends an authentication code to the user's new phone number. On success, returns information about the sent code
//@phone_number The new phone number of the user in international format @settings Settings for the authentication of the user's phone number
changePhoneNumber phone_number:string settings:phoneNumberAuthenticationSettings = AuthenticationCodeInfo;
@ -3901,6 +4001,9 @@ resendChangePhoneNumberCode = AuthenticationCodeInfo;
//@description Checks the authentication code sent to confirm a new phone number of the user @code Verification code received by SMS, phone call or flash call
checkChangePhoneNumberCode code:string = Ok;
//@description Sets the list of commands supported by the bot; for bots only @commands List of the bot's commands
setCommands commands:vector<botCommand> = Ok;
//@description Returns all active sessions of the current user
getActiveSessions = Sessions;
@ -4076,13 +4179,19 @@ deleteAccount reason:string = Ok;
//@description Removes a chat action bar without any other action @chat_id Chat identifier
removeChatActionBar chat_id:int53 = Ok;
//@description Reports a chat to the Telegram moderators. Supported only for supergroups, channels, or private chats with bots, since other chats can't be checked by moderators, or when the report is done from the chat action bar @chat_id Chat identifier @reason The reason for reporting the chat @message_ids Identifiers of reported messages, if any
//@description Reports a chat to the Telegram moderators. A chat can be reported only from the chat action bar, or if this is a private chats with a bot, a private chat with a user sharing their location, a supergroup, or a channel, since other chats can't be checked by moderators @chat_id Chat identifier @reason The reason for reporting the chat @message_ids Identifiers of reported messages, if any
reportChat chat_id:int53 reason:ChatReportReason message_ids:vector<int53> = Ok;
//@description Returns an HTTP URL with the chat statistics. Currently this method can be used only for channels. Can be used only if SupergroupFullInfo.can_view_statistics == true @chat_id Chat identifier @parameters Parameters from "tg://statsrefresh?params=******" link @is_dark Pass true if a URL with the dark theme must be returned
//@description Returns an HTTP URL with the chat statistics. Currently this method of getting the statistics is disabled and can be deleted in the future @chat_id Chat identifier @parameters Parameters from "tg://statsrefresh?params=******" link @is_dark Pass true if a URL with the dark theme must be returned
getChatStatisticsUrl chat_id:int53 parameters:string is_dark:Bool = HttpUrl;
//@description Returns detailed statistics about a chat. Currently this method can be used only for channels. Requires administrator rights in the channel @chat_id Chat identifier @is_dark Pass true if a dark theme is used by the app
getChatStatistics chat_id:int53 is_dark:Bool = ChatStatistics;
//@description Loads asynchronous or zoomed in chat statistics graph @chat_id Chat identifer @token The token for graph loading @x X-value for zoomed in graph or 0 otherwise
getChatStatisticsGraph chat_id:int53 token:string x:int53 = StatisticsGraph;
//@description Returns storage usage statistics. Can be called before authorization @chat_limit The maximum number of chats with the largest storage usage for which separate statistics should be returned. All other chats will be grouped in entries with chat_id == 0. If the chat info database is not used, the chat_limit is ignored and is always set to 0
getStorageStatistics chat_limit:int32 = StorageStatistics;
@ -4101,8 +4210,9 @@ getDatabaseStatistics = DatabaseStatistics;
//@file_types If not empty, only files with the given type(s) are considered. By default, all types except thumbnails, profile photos, stickers and wallpapers are deleted
//@chat_ids If not empty, only files from the given chats are considered. Use 0 as chat identifier to delete files not belonging to any chat (e.g., profile photos)
//@exclude_chat_ids If not empty, files from the given chats are excluded. Use 0 as chat identifier to exclude all files not belonging to any chat (e.g., profile photos)
//@return_deleted_file_statistics Pass true if deleted file statistics needs to be returned instead of the whole storage usage statistics. Affects only returned statistics
//@chat_limit Same as in getStorageStatistics. Affects only returned statistics
optimizeStorage size:int53 ttl:int32 count:int32 immunity_delay:int32 file_types:vector<FileType> chat_ids:vector<int53> exclude_chat_ids:vector<int53> chat_limit:int32 = StorageStatistics;
optimizeStorage size:int53 ttl:int32 count:int32 immunity_delay:int32 file_types:vector<FileType> chat_ids:vector<int53> exclude_chat_ids:vector<int53> return_deleted_file_statistics:Bool chat_limit:int32 = StorageStatistics;
//@description Sets the current network type. Can be called before authorization. Calling this method forces all network connections to reopen, mitigating the delay in switching between different networks, so it should be called whenever the network is changed, even if the network type remains the same.
@ -4125,6 +4235,10 @@ getAutoDownloadSettingsPresets = AutoDownloadSettingsPresets;
setAutoDownloadSettings settings:autoDownloadSettings type:NetworkType = Ok;
//@description Returns information about a bank card @bank_card_number The bank card number
getBankCardInfo bank_card_number:string = BankCardInfo;
//@description Returns one of the available Telegram Passport elements @type Telegram Passport element type @password Password of the current user
getPassportElement type:PassportElementType password:string = PassportElement;
@ -4192,17 +4306,29 @@ checkPhoneNumberConfirmationCode code:string = Ok;
setBotUpdatesStatus pending_update_count:int32 error_message:string = Ok;
//@description Uploads a PNG image with a sticker; for bots only; returns the uploaded file @user_id Sticker file owner @png_sticker PNG image with the sticker; must be up to 512 kB in size and fit in 512x512 square
//@description Uploads a PNG image with a sticker; for bots only; returns the uploaded file
//@user_id Sticker file owner @png_sticker PNG image with the sticker; must be up to 512 KB in size and fit in 512x512 square
uploadStickerFile user_id:int32 png_sticker:InputFile = File;
//@description Creates a new sticker set; for bots only. Returns the newly created sticker set @user_id Sticker set owner @title Sticker set title; 1-64 characters @name Sticker set name. Can contain only English letters, digits and underscores. Must end with *"_by_<bot username>"* (*<bot_username>* is case insensitive); 1-64 characters
//@is_masks True, if stickers are masks @stickers List of stickers to be added to the set
createNewStickerSet user_id:int32 title:string name:string is_masks:Bool stickers:vector<inputSticker> = StickerSet;
//@description Creates a new sticker set; for bots only. Returns the newly created sticker set
//@user_id Sticker set owner
//@title Sticker set title; 1-64 characters
//@name Sticker set name. Can contain only English letters, digits and underscores. Must end with *"_by_<bot username>"* (*<bot_username>* is case insensitive); 1-64 characters
//@is_masks True, if stickers are masks. Animated stickers can't be masks
//@stickers List of stickers to be added to the set; must be non-empty. All stickers must be of the same type
createNewStickerSet user_id:int32 title:string name:string is_masks:Bool stickers:vector<InputSticker> = StickerSet;
//@description Adds a new sticker to a set; for bots only. Returns the sticker set @user_id Sticker set owner @name Sticker set name @sticker Sticker to add to the set
addStickerToSet user_id:int32 name:string sticker:inputSticker = StickerSet;
//@description Adds a new sticker to a set; for bots only. Returns the sticker set
//@user_id Sticker set owner @name Sticker set name @sticker Sticker to add to the set
addStickerToSet user_id:int32 name:string sticker:InputSticker = StickerSet;
//@description Changes the position of a sticker in the set to which it belongs; for bots only. The sticker set must have been created by the bot @sticker Sticker @position New position of the sticker in the set, zero-based
//@description Sets a sticker set thumbnail; for bots only. Returns the sticker set
//@user_id Sticker set owner @name Sticker set name
//@thumbnail Thumbnail to set in PNG or TGS format. Animated thumbnail must be set for animated sticker sets and only for them. You can use a zero InputFileId to delete the thumbnail
setStickerSetThumbnail user_id:int32 name:string thumbnail:InputFile = StickerSet;
//@description Changes the position of a sticker in the set to which it belongs; for bots only. The sticker set must have been created by the bot
//@sticker Sticker @position New position of the sticker in the set, zero-based
setStickerPositionInSet sticker:InputFile position:int32 = Ok;
//@description Removes a sticker from the set to which it belongs; for bots only. The sticker set must have been created by the bot @sticker Sticker

Binary file not shown.

View File

@ -59,6 +59,7 @@ 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;
inputMediaGeoLive#ce4e82fd flags:# stopped:flags.0?true geo_point:InputGeoPoint period:flags.1?int = InputMedia;
inputMediaPoll#abe9ca25 flags:# poll:Poll correct_answers:flags.0?Vector<bytes> = InputMedia;
inputMediaDice#aeffa807 = InputMedia;
inputChatPhotoEmpty#1ca48f57 = InputChatPhoto;
inputChatUploadedPhoto#927c55b4 file:InputFile = InputChatPhoto;
@ -115,7 +116,7 @@ channel#d31a961e flags:# creator:flags.0?true left:flags.2?true broadcast:flags.
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#1b7c9db3 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:ExportedChatInvite bot_info:flags.3?Vector<BotInfo> pinned_msg_id:flags.6?int folder_id:flags.11?int = ChatFull;
channelFull#2d895c74 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_view_stats:flags.12?true can_set_location:flags.16?true has_scheduled:flags.19?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: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 pts:int = ChatFull;
channelFull#f0e6672a 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_view_stats:flags.12?true can_set_location:flags.16?true has_scheduled:flags.19?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: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 = ChatFull;
chatParticipant#c8d7493e user_id:int inviter_id:int date:int = ChatParticipant;
chatParticipantCreator#da13538a user_id:int = ChatParticipant;
@ -143,6 +144,7 @@ messageMediaGame#fdb19008 game:Game = MessageMedia;
messageMediaInvoice#84551347 flags:# shipping_address_requested:flags.1?true test:flags.3?true title:string description:string photo:flags.0?WebDocument receipt_msg_id:flags.2?int currency:string total_amount:long start_param:string = MessageMedia;
messageMediaGeoLive#7c3c2609 geo:GeoPoint period:int = MessageMedia;
messageMediaPoll#4bd6e798 poll:Poll results:PollResults = MessageMedia;
messageMediaDice#638fe46b value:int = MessageMedia;
messageActionEmpty#b6aef7b0 = MessageAction;
messageActionChatCreate#a6638b9a title:string users:Vector<int> = MessageAction;
@ -339,6 +341,9 @@ updateTheme#8216fba3 theme:Theme = Update;
updateGeoLiveViewed#871fb939 peer:Peer msg_id:int = Update;
updateLoginToken#564fe691 = Update;
updateMessagePollVote#42f88f2c poll_id:long user_id:int options:Vector<bytes> = Update;
updateDialogFilter#26ffde7d flags:# id:int filter:flags.0?DialogFilter = Update;
updateDialogFilterOrder#a5d72105 order:Vector<int> = Update;
updateDialogFilters#3504914f = Update;
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
@ -489,7 +494,7 @@ messages.affectedMessages#84d19185 pts:int pts_count:int = messages.AffectedMess
webPageEmpty#eb1477e8 id:long = WebPage;
webPagePending#c586da1c id:long date:int = WebPage;
webPage#e89c45b2 flags:# id:long url:string display_url:string hash:int type:flags.0?string site_name:flags.1?string title:flags.2?string description:flags.3?string photo:flags.4?Photo embed_url:flags.5?string embed_type:flags.5?string embed_width:flags.6?int embed_height:flags.6?int duration:flags.7?int author:flags.8?string document:flags.9?Document cached_page:flags.10?Page attributes:flags.12?Vector<WebPageAttribute> = WebPage;
webPageNotModified#85849473 = WebPage;
webPageNotModified#7311ca11 flags:# cached_page_views:flags.0?int = WebPage;
authorization#ad01d61d flags:# current:flags.0?true official_app:flags.1?true password_pending:flags.2?true hash:long device_model:string platform:string system_version:string api_id:int app_name:string app_version:string date_created:int date_active:int ip:string country:string region:string = Authorization;
@ -515,6 +520,7 @@ inputStickerSetEmpty#ffb62b95 = InputStickerSet;
inputStickerSetID#9de7a269 id:long access_hash:long = InputStickerSet;
inputStickerSetShortName#861cc8a0 short_name:string = InputStickerSet;
inputStickerSetAnimatedEmoji#28703c8 = InputStickerSet;
inputStickerSetDice#79e21a53 = InputStickerSet;
stickerSet#eeb46f27 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 thumb:flags.4?PhotoSize thumb_dc_id:flags.4?int count:int hash:int = StickerSet;
@ -561,6 +567,7 @@ messageEntityCashtag#4c4e743f offset:int length:int = MessageEntity;
messageEntityUnderline#9c4e7e8b offset:int length:int = MessageEntity;
messageEntityStrike#bf0693d4 offset:int length:int = MessageEntity;
messageEntityBlockquote#20df5d0 offset:int length:int = MessageEntity;
messageEntityBankCard#761e6af4 offset:int length:int = MessageEntity;
inputChannelEmpty#ee8c1e86 = InputChannel;
inputChannel#afeb712e channel_id:int access_hash:long = InputChannel;
@ -809,7 +816,7 @@ phoneCallDiscarded#50ca4de1 flags:# need_rating:flags.2?true need_debug:flags.3?
phoneConnection#9d4c17c0 id:long ip:string ipv6:string port:int peer_tag:bytes = PhoneConnection;
phoneCallProtocol#a2bb35cb flags:# udp_p2p:flags.0?true udp_reflector:flags.1?true min_layer:int max_layer:int = PhoneCallProtocol;
phoneCallProtocol#fc878fc8 flags:# udp_p2p:flags.0?true udp_reflector:flags.1?true min_layer:int max_layer:int library_versions:Vector<string> = PhoneCallProtocol;
phone.phoneCall#ec82e140 phone_call:PhoneCall users:Vector<User> = phone.PhoneCall;
@ -995,7 +1002,7 @@ pageListOrderedItemBlocks#98dd8936 num:string blocks:Vector<PageBlock> = PageLis
pageRelatedArticle#b390dc08 flags:# url:string webpage_id:long title:flags.0?string description:flags.1?string photo_id:flags.2?long author:flags.3?string published_date:flags.4?int = PageRelatedArticle;
page#ae891bec flags:# part:flags.0?true rtl:flags.1?true v2:flags.2?true url:string blocks:Vector<PageBlock> photos:Vector<Photo> documents:Vector<Document> = Page;
page#98657f0d flags:# part:flags.0?true rtl:flags.1?true v2:flags.2?true url:string blocks:Vector<PageBlock> photos:Vector<Photo> documents:Vector<Document> views:flags.3?int = Page;
help.supportName#8c05f1c9 name:string = help.SupportName;
@ -1060,6 +1067,7 @@ channelLocationEmpty#bfb5ad8b = ChannelLocation;
channelLocation#209b82db geo_point:GeoPoint address:string = ChannelLocation;
peerLocated#ca461b5d peer:Peer expires:int distance:int = PeerLocated;
peerSelfLocated#f8ec284b expires:int = PeerLocated;
restrictionReason#d072acb4 platform:string reason:string text:string = RestrictionReason;
@ -1097,6 +1105,28 @@ messageUserVoteMultiple#e8fe0de user_id:int options:Vector<bytes> date:int = Mes
messages.votesList#823f649 flags:# count:int votes:Vector<MessageUserVote> users:Vector<User> next_offset:flags.0?string = messages.VotesList;
bankCardOpenUrl#f568028a url:string name:string = BankCardOpenUrl;
payments.bankCardData#3e24e573 title:string open_urls:Vector<BankCardOpenUrl> = payments.BankCardData;
dialogFilter#7438f7e8 flags:# contacts:flags.0?true non_contacts:flags.1?true groups:flags.2?true broadcasts:flags.3?true bots:flags.4?true exclude_muted:flags.11?true exclude_read:flags.12?true exclude_archived:flags.13?true id:int title:string emoticon:flags.25?string pinned_peers:Vector<InputPeer> include_peers:Vector<InputPeer> exclude_peers:Vector<InputPeer> = DialogFilter;
dialogFilterSuggested#77744d4a filter:DialogFilter description:string = DialogFilterSuggested;
statsDateRangeDays#b637edaf min_date:int max_date:int = StatsDateRangeDays;
statsAbsValueAndPrev#cb43acde current:double previous:double = StatsAbsValueAndPrev;
statsPercentValue#cbce2fe0 part:double total:double = StatsPercentValue;
statsGraphAsync#4a27eb2d token:string = StatsGraph;
statsGraphError#bedc9822 error:string = StatsGraph;
statsGraph#8ea464b6 flags:# json:DataJSON zoom_token:flags.0?string = StatsGraph;
messageInteractionCounters#ad4fc9bd msg_id:int views:int forwards:int = MessageInteractionCounters;
stats.broadcastStats#bdf78394 period:StatsDateRangeDays followers:StatsAbsValueAndPrev views_per_post:StatsAbsValueAndPrev shares_per_post:StatsAbsValueAndPrev enabled_notifications:StatsPercentValue growth_graph:StatsGraph followers_graph:StatsGraph mute_graph:StatsGraph top_hours_graph:StatsGraph interactions_graph:StatsGraph iv_interactions_graph:StatsGraph views_by_source_graph:StatsGraph new_followers_by_source_graph:StatsGraph languages_graph:StatsGraph recent_message_interactions:Vector<MessageInteractionCounters> = stats.BroadcastStats;
---functions---
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
@ -1214,7 +1244,7 @@ contacts.getSaved#82f1e39f = Vector<SavedContact>;
contacts.toggleTopPeers#8514bdda enabled:Bool = Bool;
contacts.addContact#e8f463d0 flags:# add_phone_privacy_exception:flags.0?true id:InputUser first_name:string last_name:string phone:string = Updates;
contacts.acceptContact#f831a20f id:InputUser = Updates;
contacts.getLocated#a356056 geo_point:InputGeoPoint = Updates;
contacts.getLocated#d348bc44 flags:# background:flags.1?true geo_point:InputGeoPoint self_expires:flags.0?int = Updates;
messages.getMessages#63c66506 id:Vector<InputMessage> = messages.Messages;
messages.getDialogs#a0ee3b73 flags:# exclude_pinned:flags.0?true folder_id:flags.1?int offset_date:int offset_id:int offset_peer:InputPeer limit:int hash:int = messages.Dialogs;
@ -1335,6 +1365,10 @@ messages.sendScheduledMessages#bd38850a peer:InputPeer id:Vector<int> = Updates;
messages.deleteScheduledMessages#59ae2b16 peer:InputPeer id:Vector<int> = Updates;
messages.getPollVotes#b86e380e flags:# peer:InputPeer id:int option:flags.0?bytes offset:flags.1?string limit:int = messages.VotesList;
messages.toggleStickerSets#b5052fea flags:# uninstall:flags.0?true archive:flags.1?true unarchive:flags.2?true stickersets:Vector<InputStickerSet> = Bool;
messages.getDialogFilters#f19ed96d = Vector<DialogFilter>;
messages.getSuggestedDialogFilters#a29cd42c = Vector<DialogFilterSuggested>;
messages.updateDialogFilter#1ad4a04a flags:# id:int filter:flags.0?DialogFilter = Bool;
messages.updateDialogFiltersOrder#c563c1e4 order:Vector<int> = Bool;
updates.getState#edd4882a = updates.State;
updates.getDifference#25939651 flags:# pts:int pts_total_limit:flags.0?int date:int qts:int = updates.Difference;
@ -1412,6 +1446,7 @@ channels.getInactiveChannels#11e831ee = messages.InactiveChats;
bots.sendCustomRequest#aa2769ed custom_method:string params:DataJSON = DataJSON;
bots.answerWebhookJSONQuery#e6213f4d query_id:long data:DataJSON = Bool;
bots.setBotCommands#805d46f6 commands:Vector<BotCommand> = Bool;
payments.getPaymentForm#99f09745 msg_id:int = payments.PaymentForm;
payments.getPaymentReceipt#a092a980 msg_id:int = payments.PaymentReceipt;
@ -1419,11 +1454,13 @@ payments.validateRequestedInfo#770a8e74 flags:# save:flags.0?true msg_id:int inf
payments.sendPaymentForm#2b8879b3 flags:# msg_id:int requested_info_id:flags.0?string shipping_option_id:flags.1?string credentials:InputPaymentCredentials = payments.PaymentResult;
payments.getSavedInfo#227d824b = payments.SavedInfo;
payments.clearSavedInfo#d83d70c1 flags:# credentials:flags.0?true info:flags.1?true = Bool;
payments.getBankCardData#2e79d779 number:string = payments.BankCardData;
stickers.createStickerSet#9bd86e6a flags:# masks:flags.0?true user_id:InputUser title:string short_name:string stickers:Vector<InputStickerSetItem> = messages.StickerSet;
stickers.createStickerSet#f1036780 flags:# masks:flags.0?true animated:flags.1?true user_id:InputUser title:string short_name:string thumb:flags.2?InputDocument stickers:Vector<InputStickerSetItem> = messages.StickerSet;
stickers.removeStickerFromSet#f7760f51 sticker:InputDocument = messages.StickerSet;
stickers.changeStickerPosition#ffb6d4ca sticker:InputDocument position:int = messages.StickerSet;
stickers.addStickerToSet#8653febe stickerset:InputStickerSet sticker:InputStickerSetItem = messages.StickerSet;
stickers.setStickerSetThumb#9a364e30 stickerset:InputStickerSet thumb:InputDocument = messages.StickerSet;
phone.getCallConfig#55451fa9 = DataJSON;
phone.requestCall#42ff96ed flags:# video:flags.0?true user_id:InputUser random_id:int g_a_hash:bytes protocol:PhoneCallProtocol = phone.PhoneCall;
@ -1442,3 +1479,6 @@ langpack.getLanguage#6a596502 lang_pack:string lang_code:string = LangPackLangua
folders.editPeerFolders#6847d0ab folder_peers:Vector<InputFolderPeer> = Updates;
folders.deleteFolder#1c295881 folder_id:int = Updates;
stats.getBroadcastStats#ab42441a flags:# dark:flags.0?true channel:InputChannel = stats.BroadcastStats;
stats.loadAsyncGraph#621d5fa0 flags:# token:string x:flags.0?long = StatsGraph;

Binary file not shown.

View File

@ -147,10 +147,10 @@ std::string TD_TL_writer_cpp::gen_fetch_class_name(const tl::tl_tree_type *tree_
return "TlFetch" + name;
}
if (name == "String") {
return "TlFetchString<" + string_type + ">";
return "TlFetchString<string>";
}
if (name == "Bytes") {
return "TlFetchBytes<" + bytes_type + ">";
return "TlFetchBytes<bytes>";
}
if (name == "Vector") {
@ -662,7 +662,7 @@ std::string TD_TL_writer_cpp::gen_constructor_field_init(int field_num, const st
}
std::string move_begin;
std::string move_end;
if ((field_type == bytes_type || field_type.compare(0, 11, "std::vector") == 0 ||
if ((field_type == "bytes" || field_type.compare(0, 11, "std::vector") == 0 ||
field_type.compare(0, 10, "object_ptr") == 0) &&
!is_default) {
move_begin = "std::move(";

View File

@ -158,7 +158,7 @@ class TlWriterDotNet : public TL_writer {
return "String^";
}
if (name == "Bytes") {
return "Array<byte>^";
return "Array<BYTE>^";
}
if (name == "Vector") {
@ -288,7 +288,8 @@ class TlWriterDotNet : public TL_writer {
while (field_type.substr(pos, 6) == "Array<") {
pos += 6;
}
if (field_type.substr(pos, 6) != "String" && to_upper(field_type[pos]) == field_type[pos]) {
if (field_type.substr(pos, 4) != "BYTE" && field_type.substr(pos, 6) != "String" &&
to_upper(field_type[pos]) == field_type[pos]) {
field_type = field_type.substr(0, pos) + "::Telegram::Td::Api::" + field_type.substr(pos);
}
ss << field_type << " " << to_camelCase(a.name);
@ -383,7 +384,7 @@ class TlWriterDotNet : public TL_writer {
} else {
ss << ", ";
}
bool need_bytes = gen_field_type(it) == "Array<byte>^" || gen_field_type(it) == "Array<Array<byte>^>^";
bool need_bytes = gen_field_type(it) == "Array<BYTE>^" || gen_field_type(it) == "Array<Array<BYTE>^>^";
ss << (need_bytes ? "Bytes" : "") << "FromUnmanaged(from." << gen_native_field_name(it.name) << ")";
}
ss << ");\n}\n";

View File

@ -56,6 +56,18 @@ std::string TD_TL_writer_h::gen_output_begin() const {
ext_forward_declaration + "namespace " + tl_name +
" {\n\n"
"using int32 = std::int32_t;\n"
"using int53 = std::int64_t;\n"
"using int64 = std::int64_t;\n\n"
"using string = " +
string_type +
";\n\n"
"using bytes = " +
bytes_type +
";\n\n"
"using BaseObject = ::td::TlObject;\n\n"
"template <class Type>\n"

View File

@ -83,10 +83,10 @@ std::string TD_TL_writer_jni_cpp::gen_vector_fetch(std::string field_name, const
std::string fetch_object = "jni::fetch_object(env, p, " + field_name + "fieldID)";
std::string array_type;
if (vector_type == "std::int32_t") {
if (vector_type == "int32") {
array_type = "jintArray";
}
if (vector_type == "std::int64_t") {
if (vector_type == "int53" || vector_type == "int64") {
array_type = "jlongArray";
}
if (vector_type == "double") {
@ -94,12 +94,12 @@ std::string TD_TL_writer_jni_cpp::gen_vector_fetch(std::string field_name, const
}
if (!array_type.empty()) {
return "jni::fetch_vector(env, (" + array_type + ")" + fetch_object + ");";
return "jni::fetch_vector(env, (" + array_type + ")" + fetch_object + ")";
}
std::string template_type;
if (vector_type == string_type) {
template_type = "std::string";
if (vector_type == "string") {
template_type = "string";
} else if (vector_type.compare(0, 11, "std::vector") == 0) {
const tl::tl_tree_type *child = static_cast<const tl::tl_tree_type *>(t->children[0]);
template_type = gen_type_name(child);
@ -107,14 +107,13 @@ std::string TD_TL_writer_jni_cpp::gen_vector_fetch(std::string field_name, const
template_type = gen_main_class_name(child->type);
}
template_type = "std::vector<" + template_type + ">";
} else if (vector_type == bytes_type) {
std::fprintf(stderr, "Vector of Bytes is not supported\n");
assert(false);
} else if (vector_type == "bytes") {
template_type = "jbyteArray";
} else {
assert(vector_type.compare(0, 10, "object_ptr") == 0);
template_type = gen_main_class_name(t->type);
}
return "jni::FetchVector<" + template_type + ">::fetch(env, (jobjectArray)" + fetch_object + ");";
return "jni::FetchVector<" + template_type + ">::fetch(env, (jobjectArray)" + fetch_object + ")";
}
std::string TD_TL_writer_jni_cpp::gen_type_fetch(const std::string &field_name, const tl::tl_tree_type *tree_type,
@ -179,7 +178,7 @@ std::string TD_TL_writer_jni_cpp::gen_type_fetch(const std::string &field_name,
return gen_main_class_name(tree_type->type) + "::fetch(env, p)";
}
res = "jni::fetch_tl_object<" + gen_main_class_name(tree_type->type) + ">(env, jni::fetch_object(env, p, " +
field_name + "fieldID));";
field_name + "fieldID))";
}
return res_begin + res;
}
@ -248,8 +247,8 @@ std::string TD_TL_writer_jni_cpp::gen_vector_store(const std::string &field_name
if (vector_type == "bool") {
assert(false); // TODO
}
if (vector_type == "std::int32_t" || vector_type == "std::int64_t" || vector_type == "double" ||
vector_type == string_type || vector_type.compare(0, 11, "std::vector") == 0 ||
if (vector_type == "int32" || vector_type == "int53" || vector_type == "int64" || vector_type == "double" ||
vector_type == "string" || vector_type.compare(0, 11, "std::vector") == 0 ||
vector_type.compare(0, 10, "object_ptr") == 0) {
return "{ "
"auto arr_tmp_ = jni::store_vector(env, " +
@ -262,7 +261,7 @@ std::string TD_TL_writer_jni_cpp::gen_vector_store(const std::string &field_name
"env->DeleteLocalRef(arr_tmp_); "
"} }";
}
if (vector_type == bytes_type) {
if (vector_type == "bytes") {
std::fprintf(stderr, "Vector of Bytes is not supported\n");
assert(false);
}

View File

@ -79,6 +79,18 @@ std::string TD_TL_writer_jni_h::gen_output_begin() const {
tl_name +
" {\n\n"
"using int32 = std::int32_t;\n"
"using int53 = std::int64_t;\n"
"using int64 = std::int64_t;\n\n"
"using string = " +
string_type +
";\n\n"
"using bytes = " +
bytes_type +
";\n\n"
"class " +
gen_base_tl_class_name() +
";\n"

View File

@ -121,7 +121,7 @@ std::string TD_TL_writer::gen_class_name(std::string name) const {
assert(false);
}
if (name == "#") {
return "std::int32_t";
return "int32";
}
for (std::size_t i = 0; i < name.size(); i++) {
if (!is_alnum(name[i])) {
@ -161,7 +161,7 @@ std::string TD_TL_writer::gen_type_name(const tl::tl_tree_type *tree_type) const
const std::string &name = t->name;
if (name == "#") {
return "std::int32_t";
return "int32";
}
if (name == "True") {
return "bool";
@ -170,16 +170,19 @@ std::string TD_TL_writer::gen_type_name(const tl::tl_tree_type *tree_type) const
return "bool";
}
if (name == "Int" || name == "Int32") {
return "std::int32_t";
return "int32";
}
if (name == "Long" || name == "Int53" || name == "Int64") {
return "std::int64_t";
if (name == "Int53") {
return "int53";
}
if (name == "Long" || name == "Int64") {
return "int64";
}
if (name == "Double") {
return "double";
}
if (name == "String") {
return string_type;
return "string";
}
if (name == "Int128") {
return "UInt128";
@ -188,7 +191,7 @@ std::string TD_TL_writer::gen_type_name(const tl::tl_tree_type *tree_type) const
return "UInt256";
}
if (name == "Bytes") {
return bytes_type;
return "bytes";
}
if (name == "Vector") {
@ -239,12 +242,13 @@ std::string TD_TL_writer::gen_constructor_parameter(int field_num, const std::st
}
std::string res = (field_num == 0 ? "" : ", ");
if (field_type == "bool " || field_type == "std::int32_t " || field_type == "std::int64_t " ||
if (field_type == "bool " || field_type == "int32 " || field_type == "int53 " || field_type == "int64 " ||
field_type == "double ") {
res += field_type;
} else if (field_type == "UInt128 " || field_type == "UInt256 " || field_type == string_type + " ") {
} else if (field_type == "UInt128 " || field_type == "UInt256 " || field_type == "string " ||
(string_type == bytes_type && field_type == "bytes ")) {
res += field_type + "const &";
} else if (field_type.compare(0, 11, "std::vector") == 0 || field_type == bytes_type + " ") {
} else if (field_type.compare(0, 11, "std::vector") == 0 || field_type == "bytes ") {
res += field_type + "&&";
} else if (field_type.compare(0, 10, "object_ptr") == 0) {
res += field_type + "&&";

View File

@ -27,6 +27,23 @@
namespace td {
namespace mtproto {
template <class T>
static Result<typename T::ReturnType> fetch_result(Slice message, bool check_end = true) {
TlParser parser(message);
auto result = T::fetch_result(parser);
if (check_end) {
parser.fetch_end();
}
const char *error = parser.get_error();
if (error != nullptr) {
LOG(ERROR) << "Can't parse: " << format::as_hex_dump<4>(message);
return Status::Error(500, Slice(error));
}
return std::move(result);
}
void AuthKeyHandshake::clear() {
last_query_ = BufferSlice();
state_ = Start;
@ -109,7 +126,8 @@ Status AuthKeyHandshake::on_res_pq(Slice message, Callback *connection, PublicRs
// encrypted_data := RSA (data_with_hash, server_public_key); a 255-byte long number (big endian)
// is raised to the requisite power over the requisite modulus, and the result is stored as a 256-byte number.
string encrypted_data(256, 0);
rsa.encrypt(data_with_hash, size, reinterpret_cast<unsigned char *>(&encrypted_data[0]));
rsa.encrypt(data_with_hash, size, sizeof(data_with_hash), reinterpret_cast<unsigned char *>(&encrypted_data[0]),
encrypted_data.size());
// req_DH_params#d712e4be nonce:int128 server_nonce:int128 p:string q:string public_key_fingerprint:long
// encrypted_data:string = Server_DH_Params

View File

@ -79,6 +79,10 @@ class AuthKeyHandshake {
void clear();
const AuthKey &get_auth_key() const {
return auth_key_;
}
AuthKey release_auth_key() {
return std::move(auth_key_);
}

View File

@ -27,14 +27,13 @@ namespace td {
/*** RSA ***/
RSA::RSA(BigNum n, BigNum e) : n_(std::move(n)), e_(std::move(e)) {
e_.ensure_const_time();
}
RSA RSA::clone() const {
return RSA(n_.clone(), e_.clone());
}
Result<RSA> RSA::from_pem(Slice pem) {
Result<RSA> RSA::from_pem_public_key(Slice pem) {
init_crypto();
auto *bio =
@ -91,17 +90,19 @@ int64 RSA::get_fingerprint() const {
}
size_t RSA::size() const {
// Checked in RSA::from_pem step
// Checked in RSA::from_pem_public_key step
return 256;
}
size_t RSA::encrypt(unsigned char *from, size_t from_len, unsigned char *to) const {
size_t RSA::encrypt(unsigned char *from, size_t from_len, size_t max_from_len, unsigned char *to, size_t to_len) const {
CHECK(from_len > 0 && from_len <= 2550);
size_t pad = (25500 - from_len - 32) % 255 + 32;
size_t chunks = (from_len + pad) / 255;
int bits = n_.get_num_bits();
CHECK(bits >= 2041 && bits <= 2048);
CHECK(chunks * 255 == from_len + pad);
CHECK(from_len + pad <= max_from_len);
CHECK(chunks * 256 <= to_len);
Random::secure_bytes(from + from_len, pad);
BigNumContext ctx;
@ -115,7 +116,7 @@ size_t RSA::encrypt(unsigned char *from, size_t from_len, unsigned char *to) con
return chunks * 256;
}
void RSA::decrypt(Slice from, MutableSlice to) const {
void RSA::decrypt_signature(Slice from, MutableSlice to) const {
CHECK(from.size() == 256);
BigNumContext ctx;
BigNum x = BigNum::from_binary(from);

View File

@ -21,11 +21,11 @@ class RSA {
RSA clone() const;
int64 get_fingerprint() const;
size_t size() const;
size_t encrypt(unsigned char *from, size_t from_len, unsigned char *to) const;
size_t encrypt(unsigned char *from, size_t from_len, size_t max_from_len, unsigned char *to, size_t to_len) const;
void decrypt(Slice from, MutableSlice to) const;
void decrypt_signature(Slice from, MutableSlice to) const;
static Result<RSA> from_pem(Slice pem);
static Result<RSA> from_pem_public_key(Slice pem);
private:
RSA(BigNum n, BigNum e);

View File

@ -7,9 +7,6 @@
#include "td/mtproto/utils.h"
#include "td/mtproto/mtproto_api.h"
#include "td/telegram/telegram_api.h"
#include "td/utils/logging.h"
namespace td {
@ -17,17 +14,8 @@ TLStorer<mtproto_api::Function> create_storer(const mtproto_api::Function &funct
return TLStorer<mtproto_api::Function>(function);
}
TLStorer<telegram_api::Function> create_storer(const telegram_api::Function &function) {
LOG(DEBUG) << "Create storer for " << to_string(function);
return TLStorer<telegram_api::Function>(function);
}
TLObjectStorer<mtproto_api::Object> create_storer(const mtproto_api::Object &object) {
return TLObjectStorer<mtproto_api::Object>(object);
}
TLObjectStorer<telegram_api::Object> create_storer(const telegram_api::Object &object) {
return TLObjectStorer<telegram_api::Object>(object);
}
} // namespace td

View File

@ -6,54 +6,14 @@
//
#pragma once
#include "td/utils/buffer.h"
#include "td/utils/format.h"
#include "td/utils/logging.h"
#include "td/utils/Slice.h"
#include "td/utils/Status.h"
#include "td/utils/Storer.h"
#include "td/utils/StorerBase.h"
#include "td/utils/tl_parsers.h"
#include "td/utils/tl_storers.h"
#include <limits>
namespace td {
template <class T>
Result<typename T::ReturnType> fetch_result(Slice message, bool check_end = true) {
TlParser parser(message);
auto result = T::fetch_result(parser);
if (check_end) {
parser.fetch_end();
}
const char *error = parser.get_error();
if (error != nullptr) {
LOG(ERROR) << "Can't parse: " << format::as_hex_dump<4>(message);
return Status::Error(500, Slice(error));
}
return std::move(result);
}
template <class T>
Result<typename T::ReturnType> fetch_result(const BufferSlice &message, bool check_end = true) {
TlBufferParser parser(&message);
auto result = T::fetch_result(parser);
if (check_end) {
parser.fetch_end();
}
const char *error = parser.get_error();
if (error != nullptr) {
LOG(ERROR) << "Can't parse: " << format::as_hex_dump<4>(message.as_slice());
return Status::Error(500, Slice(error));
}
return std::move(result);
}
template <class T>
using TLStorer = DefaultStorer<T>;
@ -88,17 +48,8 @@ class Object;
class Function;
} // namespace mtproto_api
namespace telegram_api {
class Object;
class Function;
} // namespace telegram_api
TLStorer<mtproto_api::Function> create_storer(const mtproto_api::Function &function);
TLStorer<telegram_api::Function> create_storer(const telegram_api::Function &function);
TLObjectStorer<mtproto_api::Object> create_storer(const mtproto_api::Object &object);
TLObjectStorer<telegram_api::Object> create_storer(const telegram_api::Object &object);
} // namespace td

View File

@ -45,7 +45,7 @@ class GetSavedGifsQuery : public Td::ResultHandler {
void send(bool is_repair, int32 hash) {
is_repair_ = is_repair;
LOG(INFO) << "Send get saved animations request with hash = " << hash;
send_query(G()->net_query_creator().create(create_storer(telegram_api::messages_getSavedGifs(hash))));
send_query(G()->net_query_creator().create(telegram_api::messages_getSavedGifs(hash)));
}
void on_result(uint64 id, BufferSlice packet) override {
@ -59,7 +59,7 @@ class GetSavedGifsQuery : public Td::ResultHandler {
}
void on_error(uint64 id, Status status) override {
if (!G()->close_flag()) {
if (!G()->is_expected_error(status)) {
LOG(ERROR) << "Receive error for get saved animations: " << status;
}
td->animations_manager_->on_get_saved_animations_failed(is_repair_, std::move(status));
@ -83,8 +83,7 @@ class SaveGifQuery : public Td::ResultHandler {
file_id_ = file_id;
file_reference_ = input_document->file_reference_.as_slice().str();
unsave_ = unsave;
send_query(G()->net_query_creator().create(
create_storer(telegram_api::messages_saveGif(std::move(input_document), unsave))));
send_query(G()->net_query_creator().create(telegram_api::messages_saveGif(std::move(input_document), unsave)));
}
void on_result(uint64 id, BufferSlice packet) override {
@ -119,7 +118,7 @@ class SaveGifQuery : public Td::ResultHandler {
return;
}
if (!G()->close_flag()) {
if (!G()->is_expected_error(status)) {
LOG(ERROR) << "Receive error for save GIF: " << status;
}
td->animations_manager_->reload_saved_animations(true);
@ -606,7 +605,10 @@ int32 AnimationsManager::get_saved_animations_hash(const char *source) const {
CHECK(animation != nullptr);
auto file_view = td_->file_manager_->get_file_view(animation_id);
CHECK(file_view.has_remote_location());
LOG_CHECK(file_view.remote_location().is_document()) << source << " " << file_view.remote_location();
if (!file_view.remote_location().is_document()) {
LOG(ERROR) << "Saved animation remote location is not document: " << source << " " << file_view.remote_location();
continue;
}
auto id = static_cast<uint64>(file_view.remote_location().get_id());
numbers.push_back(static_cast<uint32>(id >> 32));
numbers.push_back(static_cast<uint32>(id & 0xFFFFFFFF));

View File

@ -69,7 +69,7 @@ AuthManager::AuthManager(int32 api_id, const string &api_hash, ActorShared<> par
void AuthManager::start_up() {
if (state_ == State::LoggingOut) {
start_net_query(NetQueryType::LogOut, G()->net_query_creator().create(create_storer(telegram_api::auth_logOut())));
start_net_query(NetQueryType::LogOut, G()->net_query_creator().create(telegram_api::auth_logOut()));
} else if (state_ == State::DestroyingKeys) {
destroy_auth_keys();
}
@ -175,9 +175,8 @@ void AuthManager::check_bot_token(uint64 query_id, string bot_token) {
bot_token_ = bot_token;
was_check_bot_token_ = true;
start_net_query(NetQueryType::BotAuthentication,
G()->net_query_creator().create(
create_storer(telegram_api::auth_importBotAuthorization(0, api_id_, api_hash_, bot_token_)),
DcId::main(), NetQuery::Type::Common, NetQuery::AuthFlag::Off));
G()->net_query_creator().create_unauth(
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) {
@ -215,9 +214,8 @@ void AuthManager::request_qr_code_authentication(uint64 query_id, vector<int32>
void AuthManager::send_export_login_token_query() {
poll_export_login_code_timeout_.cancel_timeout();
start_net_query(NetQueryType::RequestQrCode,
G()->net_query_creator().create(create_storer(telegram_api::auth_exportLoginToken(
api_id_, api_hash_, vector<int32>(other_user_ids_))),
DcId::main(), NetQuery::Type::Common, NetQuery::AuthFlag::Off));
G()->net_query_creator().create_unauth(
telegram_api::auth_exportLoginToken(api_id_, api_hash_, vector<int32>(other_user_ids_))));
}
void AuthManager::set_login_token_expires_at(double login_token_expires_at) {
@ -271,10 +269,8 @@ void AuthManager::set_phone_number(uint64 query_id, string phone_number,
on_new_query(query_id);
start_net_query(NetQueryType::SendCode,
G()->net_query_creator().create(
create_storer(send_code_helper_.send_code(phone_number, settings, api_id_, api_hash_)),
DcId::main(), NetQuery::Type::Common, NetQuery::AuthFlag::Off));
start_net_query(NetQueryType::SendCode, G()->net_query_creator().create_unauth(
send_code_helper_.send_code(phone_number, settings, api_id_, api_hash_)));
}
void AuthManager::resend_authentication_code(uint64 query_id) {
@ -289,9 +285,7 @@ void AuthManager::resend_authentication_code(uint64 query_id) {
on_new_query(query_id);
start_net_query(NetQueryType::SendCode,
G()->net_query_creator().create(create_storer(r_resend_code.move_as_ok()), DcId::main(),
NetQuery::Type::Common, NetQuery::AuthFlag::Off));
start_net_query(NetQueryType::SendCode, G()->net_query_creator().create_unauth(r_resend_code.move_as_ok()));
}
void AuthManager::check_code(uint64 query_id, string code) {
@ -302,10 +296,8 @@ void AuthManager::check_code(uint64 query_id, string code) {
code_ = std::move(code);
on_new_query(query_id);
start_net_query(NetQueryType::SignIn,
G()->net_query_creator().create(
create_storer(telegram_api::auth_signIn(send_code_helper_.phone_number().str(),
send_code_helper_.phone_code_hash().str(), code_)),
DcId::main(), NetQuery::Type::Common, NetQuery::AuthFlag::Off));
G()->net_query_creator().create_unauth(telegram_api::auth_signIn(
send_code_helper_.phone_number().str(), send_code_helper_.phone_code_hash().str(), code_)));
}
void AuthManager::register_user(uint64 query_id, string first_name, string last_name) {
@ -320,12 +312,9 @@ void AuthManager::register_user(uint64 query_id, string first_name, string last_
}
last_name = clean_name(last_name, MAX_NAME_LENGTH);
start_net_query(
NetQueryType::SignUp,
G()->net_query_creator().create(
create_storer(telegram_api::auth_signUp(send_code_helper_.phone_number().str(),
send_code_helper_.phone_code_hash().str(), first_name, last_name)),
DcId::main(), NetQuery::Type::Common, NetQuery::AuthFlag::Off));
start_net_query(NetQueryType::SignUp, G()->net_query_creator().create_unauth(telegram_api::auth_signUp(
send_code_helper_.phone_number().str(),
send_code_helper_.phone_code_hash().str(), first_name, last_name)));
}
void AuthManager::check_password(uint64 query_id, string password) {
@ -337,8 +326,7 @@ void AuthManager::check_password(uint64 query_id, string password) {
on_new_query(query_id);
password_ = std::move(password);
start_net_query(NetQueryType::GetPassword,
G()->net_query_creator().create(create_storer(telegram_api::account_getPassword()), DcId::main(),
NetQuery::Type::Common, NetQuery::AuthFlag::Off));
G()->net_query_creator().create_unauth(telegram_api::account_getPassword()));
}
void AuthManager::request_password_recovery(uint64 query_id) {
@ -348,8 +336,7 @@ void AuthManager::request_password_recovery(uint64 query_id) {
on_new_query(query_id);
start_net_query(NetQueryType::RequestPasswordRecovery,
G()->net_query_creator().create(create_storer(telegram_api::auth_requestPasswordRecovery()),
DcId::main(), NetQuery::Type::Common, NetQuery::AuthFlag::Off));
G()->net_query_creator().create_unauth(telegram_api::auth_requestPasswordRecovery()));
}
void AuthManager::recover_password(uint64 query_id, string code) {
@ -359,8 +346,7 @@ void AuthManager::recover_password(uint64 query_id, string code) {
on_new_query(query_id);
start_net_query(NetQueryType::RecoverPassword,
G()->net_query_creator().create(create_storer(telegram_api::auth_recoverPassword(code)), DcId::main(),
NetQuery::Type::Common, NetQuery::AuthFlag::Off));
G()->net_query_creator().create_unauth(telegram_api::auth_recoverPassword(code)));
}
void AuthManager::logout(uint64 query_id) {
@ -380,7 +366,7 @@ void AuthManager::logout(uint64 query_id) {
LOG(INFO) << "Logging out";
G()->td_db()->get_binlog_pmc()->set("auth", "logout");
update_state(State::LoggingOut);
start_net_query(NetQueryType::LogOut, G()->net_query_creator().create(create_storer(telegram_api::auth_logOut())));
start_net_query(NetQueryType::LogOut, G()->net_query_creator().create(telegram_api::auth_logOut()));
}
}
@ -391,8 +377,7 @@ void AuthManager::delete_account(uint64 query_id, const string &reason) {
on_new_query(query_id);
LOG(INFO) << "Deleting account";
start_net_query(NetQueryType::DeleteAccount,
G()->net_query_creator().create(create_storer(telegram_api::account_deleteAccount(reason)),
DcId::main(), NetQuery::Type::Common, NetQuery::AuthFlag::Off));
G()->net_query_creator().create_unauth(telegram_api::account_deleteAccount(reason)));
}
void AuthManager::on_closing(bool destroy_flag) {
@ -524,10 +509,9 @@ void AuthManager::on_get_login_token(tl_object_ptr<telegram_api::auth_LoginToken
}
imported_dc_id_ = token->dc_id_;
start_net_query(NetQueryType::ImportQrCode,
G()->net_query_creator().create(
create_storer(telegram_api::auth_importLoginToken(std::move(token->token_))),
DcId::internal(token->dc_id_), NetQuery::Type::Common, NetQuery::AuthFlag::Off));
start_net_query(NetQueryType::ImportQrCode, G()->net_query_creator().create_unauth(
telegram_api::auth_importLoginToken(std::move(token->token_)),
DcId::internal(token->dc_id_)));
break;
}
case telegram_api::auth_loginTokenSuccess::ID: {
@ -582,10 +566,8 @@ void AuthManager::on_get_password_result(NetQueryPtr &result) {
return;
} else {
start_net_query(NetQueryType::SignIn,
G()->net_query_creator().create(
create_storer(telegram_api::auth_signIn(send_code_helper_.phone_number().str(),
send_code_helper_.phone_code_hash().str(), code_)),
DcId::main(), NetQuery::Type::Common, NetQuery::AuthFlag::Off));
G()->net_query_creator().create_unauth(telegram_api::auth_signIn(
send_code_helper_.phone_number().str(), send_code_helper_.phone_code_hash().str(), code_)));
return;
}
@ -602,8 +584,7 @@ void AuthManager::on_get_password_result(NetQueryPtr &result) {
wait_password_state_.srp_B_, wait_password_state_.srp_id_);
start_net_query(NetQueryType::CheckPassword,
G()->net_query_creator().create(create_storer(telegram_api::auth_checkPassword(std::move(hash))),
DcId::main(), NetQuery::Type::Common, NetQuery::AuthFlag::Off));
G()->net_query_creator().create_unauth(telegram_api::auth_checkPassword(std::move(hash))));
} else {
update_state(State::WaitPassword);
if (query_id_ != 0) {
@ -779,8 +760,7 @@ void AuthManager::on_result(NetQueryPtr result) {
dc_id = DcId::internal(imported_dc_id_);
}
start_net_query(NetQueryType::GetPassword,
G()->net_query_creator().create(create_storer(telegram_api::account_getPassword()), dc_id,
NetQuery::Type::Common, NetQuery::AuthFlag::Off));
G()->net_query_creator().create_unauth(telegram_api::account_getPassword(), dc_id));
return;
}
if (result->error().message() == CSlice("PHONE_NUMBER_BANNED")) {

View File

@ -39,7 +39,7 @@ class GetAutoDownloadSettingsQuery : public Td::ResultHandler {
}
void send() {
send_query(G()->net_query_creator().create(create_storer(telegram_api::account_getAutoDownloadSettings())));
send_query(G()->net_query_creator().create(telegram_api::account_getAutoDownloadSettings()));
}
void on_result(uint64 id, BufferSlice packet) override {
@ -94,8 +94,8 @@ class SaveAutoDownloadSettingsQuery : public Td::ResultHandler {
if (type == NetType::WiFi) {
flags |= telegram_api::account_saveAutoDownloadSettings::HIGH_MASK;
}
send_query(G()->net_query_creator().create(create_storer(telegram_api::account_saveAutoDownloadSettings(
flags, false /*ignored*/, false /*ignored*/, get_input_auto_download_settings(settings)))));
send_query(G()->net_query_creator().create(telegram_api::account_saveAutoDownloadSettings(
flags, false /*ignored*/, false /*ignored*/, get_input_auto_download_settings(settings))));
}
void on_result(uint64 id, BufferSlice packet) override {

View File

@ -51,8 +51,7 @@ class GetBackgroundQuery : public Td::ResultHandler {
background_id_ = background_id;
background_name_ = background_name;
LOG(INFO) << "Load " << background_id_ << "/" << background_name_ << " from server: " << to_string(input_wallpaper);
send_query(
G()->net_query_creator().create(create_storer(telegram_api::account_getWallPaper(std::move(input_wallpaper)))));
send_query(G()->net_query_creator().create(telegram_api::account_getWallPaper(std::move(input_wallpaper))));
}
void on_result(uint64 id, BufferSlice packet) override {
@ -81,7 +80,7 @@ class GetBackgroundsQuery : public Td::ResultHandler {
}
void send() {
send_query(G()->net_query_creator().create(create_storer(telegram_api::account_getWallPapers(0))));
send_query(G()->net_query_creator().create(telegram_api::account_getWallPapers(0)));
}
void on_result(uint64 id, BufferSlice packet) override {
@ -106,9 +105,9 @@ class InstallBackgroundQuery : public Td::ResultHandler {
}
void send(BackgroundId background_id, int64 access_hash, const BackgroundType &type) {
send_query(G()->net_query_creator().create(create_storer(telegram_api::account_installWallPaper(
send_query(G()->net_query_creator().create(telegram_api::account_installWallPaper(
telegram_api::make_object<telegram_api::inputWallPaper>(background_id.get(), access_hash),
get_input_wallpaper_settings(type)))));
get_input_wallpaper_settings(type))));
}
void on_result(uint64 id, BufferSlice packet) override {
@ -143,8 +142,8 @@ class UploadBackgroundQuery : public Td::ResultHandler {
type_ = type;
for_dark_theme_ = for_dark_theme;
string mime_type = type.type == BackgroundType::Type::Pattern ? "image/png" : "image/jpeg";
send_query(G()->net_query_creator().create(create_storer(
telegram_api::account_uploadWallPaper(std::move(input_file), mime_type, get_input_wallpaper_settings(type)))));
send_query(G()->net_query_creator().create(
telegram_api::account_uploadWallPaper(std::move(input_file), mime_type, get_input_wallpaper_settings(type))));
}
void on_result(uint64 id, BufferSlice packet) override {
@ -181,9 +180,9 @@ class SaveBackgroundQuery : public Td::ResultHandler {
}
void send(BackgroundId background_id, int64 access_hash, const BackgroundType &type, bool unsave) {
send_query(G()->net_query_creator().create(create_storer(telegram_api::account_saveWallPaper(
send_query(G()->net_query_creator().create(telegram_api::account_saveWallPaper(
telegram_api::make_object<telegram_api::inputWallPaper>(background_id.get(), access_hash), unsave,
get_input_wallpaper_settings(type)))));
get_input_wallpaper_settings(type))));
}
void on_result(uint64 id, BufferSlice packet) override {
@ -198,7 +197,7 @@ class SaveBackgroundQuery : public Td::ResultHandler {
}
void on_error(uint64 id, Status status) override {
if (!G()->close_flag()) {
if (!G()->is_expected_error(status)) {
LOG(ERROR) << "Receive error for save background: " << status;
}
promise_.set_error(std::move(status));
@ -213,7 +212,7 @@ class ResetBackgroundsQuery : public Td::ResultHandler {
}
void send() {
send_query(G()->net_query_creator().create(create_storer(telegram_api::account_resetWallPapers())));
send_query(G()->net_query_creator().create(telegram_api::account_resetWallPapers()));
}
void on_result(uint64 id, BufferSlice packet) override {
@ -228,7 +227,7 @@ class ResetBackgroundsQuery : public Td::ResultHandler {
}
void on_error(uint64 id, Status status) override {
if (!G()->close_flag()) {
if (!G()->is_expected_error(status)) {
LOG(ERROR) << "Receive error for reset backgrounds: " << status;
}
promise_.set_error(std::move(status));

View File

@ -22,6 +22,8 @@
#include "td/telegram/Td.h"
#include "td/telegram/UpdatesManager.h"
#include "td/utils/as.h"
#include "td/utils/bits.h"
#include "td/utils/buffer.h"
#include "td/utils/common.h"
#include "td/utils/crypto.h"
@ -39,6 +41,7 @@ CallProtocol CallProtocol::from_telegram_api(const telegram_api::phoneCallProtoc
res.udp_reflector = protocol.udp_reflector_;
res.min_layer = protocol.min_layer_;
res.max_layer = protocol.max_layer_;
res.library_versions = protocol.library_versions_;
return res;
}
@ -50,7 +53,8 @@ tl_object_ptr<telegram_api::phoneCallProtocol> CallProtocol::as_telegram_api() c
if (udp_reflector) {
flags |= telegram_api::phoneCallProtocol::UDP_REFLECTOR_MASK;
}
return make_tl_object<telegram_api::phoneCallProtocol>(flags, udp_p2p, udp_reflector, min_layer, max_layer);
return make_tl_object<telegram_api::phoneCallProtocol>(flags, udp_p2p, udp_reflector, min_layer, max_layer,
vector<string>(library_versions));
}
CallProtocol CallProtocol::from_td_api(const td_api::callProtocol &protocol) {
@ -59,10 +63,13 @@ CallProtocol CallProtocol::from_td_api(const td_api::callProtocol &protocol) {
res.udp_reflector = protocol.udp_reflector_;
res.min_layer = protocol.min_layer_;
res.max_layer = protocol.max_layer_;
res.library_versions = protocol.library_versions_;
return res;
}
tl_object_ptr<td_api::callProtocol> CallProtocol::as_td_api() const {
return make_tl_object<td_api::callProtocol>(udp_p2p, udp_reflector, min_layer, max_layer);
return make_tl_object<td_api::callProtocol>(udp_p2p, udp_reflector, min_layer, max_layer,
vector<string>(library_versions));
}
CallConnection CallConnection::from_telegram_api(const telegram_api::phoneConnection &connection) {
@ -235,7 +242,7 @@ void CallActor::rate_call(int32 rating, string comment, vector<td_api::object_pt
auto tl_query = telegram_api::phone_setCallRating(0, false /*ignored*/, get_input_phone_call("rate_call"), rating,
std::move(comment));
auto query = G()->net_query_creator().create(create_storer(tl_query));
auto query = G()->net_query_creator().create(tl_query);
send_with_promise(std::move(query), PromiseCreator::lambda([actor_id = actor_id(this)](NetQueryPtr net_query) {
send_closure(actor_id, &CallActor::on_set_rating_query_result, std::move(net_query));
}));
@ -258,7 +265,7 @@ void CallActor::send_call_debug_information(string data, Promise<> promise) {
promise.set_value(Unit());
auto tl_query = telegram_api::phone_saveCallDebug(get_input_phone_call("send_call_debug_information"),
make_tl_object<telegram_api::dataJSON>(std::move(data)));
auto query = G()->net_query_creator().create(create_storer(tl_query));
auto query = G()->net_query_creator().create(tl_query);
send_with_promise(std::move(query), PromiseCreator::lambda([actor_id = actor_id(this)](NetQueryPtr net_query) {
send_closure(actor_id, &CallActor::on_set_debug_query_result, std::move(net_query));
}));
@ -508,7 +515,7 @@ void CallActor::do_load_dh_config(Promise<std::shared_ptr<DhConfig>> promise) {
}
int random_length = 0;
telegram_api::messages_getDhConfig tl_query(version, random_length);
auto query = G()->net_query_creator().create(create_storer(tl_query));
auto query = G()->net_query_creator().create(tl_query);
send_with_promise(std::move(query),
PromiseCreator::lambda([actor_id = actor_id(this), old_dh_config = std::move(dh_config),
promise = std::move(promise)](Result<NetQueryPtr> result_query) mutable {
@ -538,7 +545,7 @@ void CallActor::do_load_dh_config(Promise<std::shared_ptr<DhConfig>> promise) {
void CallActor::send_received_query() {
auto tl_query = telegram_api::phone_receivedCall(get_input_phone_call("send_received_query"));
auto query = G()->net_query_creator().create(create_storer(tl_query));
auto query = G()->net_query_creator().create(tl_query);
send_with_promise(std::move(query), PromiseCreator::lambda([actor_id = actor_id(this)](NetQueryPtr net_query) {
send_closure(actor_id, &CallActor::on_received_query_result, std::move(net_query));
}));
@ -565,7 +572,7 @@ void CallActor::try_send_request_query() {
auto tl_query = telegram_api::phone_requestCall(flags, false /*ignored*/, std::move(input_user_),
Random::secure_int32(), BufferSlice(dh_handshake_.get_g_b_hash()),
call_state_.protocol.as_telegram_api());
auto query = G()->net_query_creator().create(create_storer(tl_query));
auto query = G()->net_query_creator().create(tl_query);
state_ = State::WaitRequestResult;
int32 call_receive_timeout_ms = G()->shared_config().get_option_integer("call_receive_timeout_ms", 20000);
double timeout = call_receive_timeout_ms * 0.001;
@ -600,7 +607,7 @@ void CallActor::try_send_accept_query() {
auto tl_query =
telegram_api::phone_acceptCall(get_input_phone_call("try_send_accept_query"),
BufferSlice(dh_handshake_.get_g_b()), call_state_.protocol.as_telegram_api());
auto query = G()->net_query_creator().create(create_storer(tl_query));
auto query = G()->net_query_creator().create(tl_query);
state_ = State::WaitAcceptResult;
send_with_promise(std::move(query), PromiseCreator::lambda([actor_id = actor_id(this)](NetQueryPtr net_query) {
send_closure(actor_id, &CallActor::on_accept_query_result, std::move(net_query));
@ -624,7 +631,7 @@ void CallActor::try_send_confirm_query() {
auto tl_query = telegram_api::phone_confirmCall(get_input_phone_call("try_send_confirm_query"),
BufferSlice(dh_handshake_.get_g_b()), call_state_.key_fingerprint,
call_state_.protocol.as_telegram_api());
auto query = G()->net_query_creator().create(create_storer(tl_query));
auto query = G()->net_query_creator().create(tl_query);
state_ = State::WaitConfirmResult;
send_with_promise(std::move(query), PromiseCreator::lambda([actor_id = actor_id(this)](NetQueryPtr net_query) {
send_closure(actor_id, &CallActor::on_confirm_query_result, std::move(net_query));
@ -654,7 +661,7 @@ void CallActor::try_send_discard_query() {
auto tl_query = telegram_api::phone_discardCall(
flags, false /*ignored*/, get_input_phone_call("try_send_discard_query"), duration_,
get_input_phone_call_discard_reason(call_state_.discard_reason), connection_id_);
auto query = G()->net_query_creator().create(create_storer(tl_query));
auto query = G()->net_query_creator().create(tl_query);
state_ = State::WaitDiscardResult;
send_with_promise(std::move(query), PromiseCreator::lambda([actor_id = actor_id(this)](NetQueryPtr net_query) {
send_closure(actor_id, &CallActor::on_discard_query_result, std::move(net_query));
@ -703,7 +710,7 @@ void CallActor::flush_call_state() {
void CallActor::start_up() {
auto tl_query = telegram_api::phone_getCallConfig();
auto query = G()->net_query_creator().create(create_storer(tl_query));
auto query = G()->net_query_creator().create(tl_query);
send_with_promise(std::move(query), PromiseCreator::lambda([actor_id = actor_id(this)](NetQueryPtr net_query) {
send_closure(actor_id, &CallActor::on_get_call_config_result, std::move(net_query));
}));
@ -779,11 +786,7 @@ vector<string> CallActor::get_emojis_fingerprint(const string &key, const string
vector<string> result;
result.reserve(4);
for (int i = 0; i < 4; i++) {
uint64 num =
(static_cast<uint64>(sha256_buf[8 * i + 0]) << 56) | (static_cast<uint64>(sha256_buf[8 * i + 1]) << 48) |
(static_cast<uint64>(sha256_buf[8 * i + 2]) << 40) | (static_cast<uint64>(sha256_buf[8 * i + 3]) << 32) |
(static_cast<uint64>(sha256_buf[8 * i + 4]) << 24) | (static_cast<uint64>(sha256_buf[8 * i + 5]) << 16) |
(static_cast<uint64>(sha256_buf[8 * i + 6]) << 8) | (static_cast<uint64>(sha256_buf[8 * i + 7]));
uint64 num = bswap64(as<uint64>(sha256_buf + 8 * i));
result.push_back(get_emoji_fingerprint(num));
}
return result;

View File

@ -32,6 +32,7 @@ struct CallProtocol {
bool udp_reflector{true};
int32 min_layer{65};
int32 max_layer{65};
vector<string> library_versions;
static CallProtocol from_telegram_api(const telegram_api::phoneCallProtocol &protocol);
tl_object_ptr<telegram_api::phoneCallProtocol> as_telegram_api() const;

View File

@ -6,9 +6,6 @@
//
#include "td/telegram/CallDiscardReason.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/utils/common.h"
namespace td {

View File

@ -6,20 +6,13 @@
//
#pragma once
#include "td/tl/TlObject.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/utils/int_types.h"
namespace td {
namespace td_api {
class CallDiscardReason;
} // namespace td_api
namespace telegram_api {
class PhoneCallDiscardReason;
} // namespace telegram_api
enum class CallDiscardReason : int32 { Empty, Missed, Disconnected, HungUp, Declined };
CallDiscardReason get_call_discard_reason(const tl_object_ptr<telegram_api::PhoneCallDiscardReason> &reason);

View File

@ -61,8 +61,8 @@ class GetBotCallbackAnswerQuery : public Td::ResultHandler {
UNREACHABLE();
}
auto net_query = G()->net_query_creator().create(create_storer(telegram_api::messages_getBotCallbackAnswer(
flags, false /*ignored*/, std::move(input_peer), message_id.get_server_message_id().get(), std::move(data))));
auto net_query = G()->net_query_creator().create(telegram_api::messages_getBotCallbackAnswer(
flags, false /*ignored*/, std::move(input_peer), message_id.get_server_message_id().get(), std::move(data)));
net_query->need_resend_on_503 = false;
send_query(std::move(net_query));
}
@ -95,8 +95,8 @@ class SetBotCallbackAnswerQuery : public Td::ResultHandler {
}
void send(int32 flags, int64 callback_query_id, const string &text, const string &url, int32 cache_time) {
send_query(G()->net_query_creator().create(create_storer(telegram_api::messages_setBotCallbackAnswer(
flags, false /*ignored*/, callback_query_id, text, url, cache_time))));
send_query(G()->net_query_creator().create(telegram_api::messages_setBotCallbackAnswer(
flags, false /*ignored*/, callback_query_id, text, url, cache_time)));
}
void on_result(uint64 id, BufferSlice packet) override {
@ -226,7 +226,7 @@ int64 CallbackQueriesManager::send_callback_query(FullMessageId full_message_id,
}
if (payload == nullptr) {
promise.set_error(Status::Error(5, "Payload should not be empty"));
promise.set_error(Status::Error(5, "Payload must be non-empty"));
return 0;
}

View File

@ -12,6 +12,7 @@
#include "td/telegram/Td.h"
namespace td {
ClientActor::ClientActor(unique_ptr<TdCallback> callback) {
td_ = create_actor<Td>("Td", std::move(callback));
}

View File

@ -141,7 +141,7 @@ Result<int32> HttpDate::parse_http_date(std::string slice) {
}
Result<SimpleConfig> decode_config(Slice input) {
static auto rsa = RSA::from_pem(
static auto rsa = RSA::from_pem_public_key(
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIIBCgKCAQEAyr+18Rex2ohtVy8sroGP\n"
"BwXD3DOoKCSpjDqYoXgCqB7ioln4eDCFfOBUlfXUEvM/fnKCpF46VkAftlb4VuPD\n"
@ -167,7 +167,7 @@ Result<SimpleConfig> decode_config(Slice input) {
}
MutableSlice data_rsa_slice(data_rsa);
rsa.decrypt(data_rsa_slice, data_rsa_slice);
rsa.decrypt_signature(data_rsa_slice, data_rsa_slice);
MutableSlice data_cbc = data_rsa_slice.substr(32);
UInt256 key;
@ -254,6 +254,7 @@ static ActorOwn<> get_simple_config_dns(Slice address, Slice host, Promise<Simpl
name = is_test ? "tapv3.stel.com" : "apv3.stel.com";
}
auto get_config = [](HttpQuery &http_query) -> Result<string> {
VLOG(config_recoverer) << "Receive DNS response " << http_query.content_;
TRY_RESULT(json, json_decode(http_query.content_));
if (json.type() != JsonValue::Type::Object) {
return Status::Error("Expected JSON object");
@ -282,7 +283,7 @@ static ActorOwn<> get_simple_config_dns(Slice address, Slice host, Promise<Simpl
return data;
};
return get_simple_config_impl(std::move(promise), scheduler_id,
PSTRING() << "https://" << address << "?name=" << url_encode(name) << "&type=16",
PSTRING() << "https://" << address << "?name=" << url_encode(name) << "&type=TXT",
host.str(), {{"Accept", "application/dns-json"}}, prefer_ipv6, std::move(get_config));
}
@ -503,9 +504,8 @@ ActorOwn<> get_full_config(DcOption option, Promise<FullConfig> promise, ActorSh
int_dc_id, false /*is_main*/, true /*use_pfs*/, false /*is_cdn*/,
false /*need_destroy_auth_key*/, mtproto::AuthKey(),
std::vector<mtproto::ServerSalt>());
auto query = G()->net_query_creator().create(create_storer(telegram_api::help_getConfig()), DcId::empty(),
NetQuery::Type::Common, NetQuery::AuthFlag::Off,
NetQuery::GzipFlag::On, 60 * 60 * 24);
auto query = G()->net_query_creator().create_unauth(telegram_api::help_getConfig(), DcId::empty());
query->total_timeout_limit = 60 * 60 * 24;
query->set_callback(actor_shared(this));
query->dispatch_ttl = 0;
send_closure(session_, &Session::send, std::move(query));
@ -790,7 +790,7 @@ class ConfigRecoverer : public Actor {
PromiseCreator::lambda([actor_id = actor_shared(this)](Result<SimpleConfigResult> r_simple_config) {
send_closure(actor_id, &ConfigRecoverer::on_simple_config, std::move(r_simple_config), false);
});
auto get_simple_config = [&]() {
auto get_simple_config = [&] {
switch (simple_config_turn_ % 4) {
case 2:
return get_simple_config_azure;
@ -931,11 +931,9 @@ void ConfigManager::get_app_config(Promise<td_api::object_ptr<td_api::JsonValue>
get_app_config_queries_.push_back(std::move(promise));
if (get_app_config_queries_.size() == 1) {
G()->net_query_dispatcher().dispatch_with_callback(
G()->net_query_creator().create(create_storer(telegram_api::help_getAppConfig()), DcId::main(),
NetQuery::Type::Common, NetQuery::AuthFlag::Off, NetQuery::GzipFlag::On,
60 * 60 * 24),
actor_shared(this, 1));
auto query = G()->net_query_creator().create_unauth(telegram_api::help_getAppConfig());
query->total_timeout_limit = 60 * 60 * 24;
G()->net_query_dispatcher().dispatch_with_callback(std::move(query), actor_shared(this, 1));
}
}
@ -952,8 +950,7 @@ void ConfigManager::get_content_settings(Promise<Unit> &&promise) {
get_content_settings_queries_.push_back(std::move(promise));
if (get_content_settings_queries_.size() == 1) {
G()->net_query_dispatcher().dispatch_with_callback(
G()->net_query_creator().create(create_storer(telegram_api::account_getContentSettings())),
actor_shared(this, 2));
G()->net_query_creator().create(telegram_api::account_getContentSettings()), actor_shared(this, 2));
}
}
@ -972,8 +969,7 @@ void ConfigManager::set_content_settings(bool ignore_sensitive_content_restricti
flags |= telegram_api::account_setContentSettings::SENSITIVE_ENABLED_MASK;
}
G()->net_query_dispatcher().dispatch_with_callback(
G()->net_query_creator().create(
create_storer(telegram_api::account_setContentSettings(flags, false /*ignored*/))),
G()->net_query_creator().create(telegram_api::account_setContentSettings(flags, false /*ignored*/)),
actor_shared(this, 3 + static_cast<uint64>(ignore_sensitive_content_restrictions)));
}
}
@ -991,10 +987,9 @@ void ConfigManager::on_dc_options_update(DcOptions dc_options) {
void ConfigManager::request_config_from_dc_impl(DcId dc_id) {
config_sent_cnt_++;
G()->net_query_dispatcher().dispatch_with_callback(
G()->net_query_creator().create(create_storer(telegram_api::help_getConfig()), dc_id, NetQuery::Type::Common,
NetQuery::AuthFlag::Off, NetQuery::GzipFlag::On, 60 * 60 * 24),
actor_shared(this, 0));
auto query = G()->net_query_creator().create_unauth(telegram_api::help_getConfig(), dc_id);
query->total_timeout_limit = 60 * 60 * 24;
G()->net_query_dispatcher().dispatch_with_callback(std::move(query), actor_shared(this, 0));
}
void ConfigManager::set_ignore_sensitive_content_restrictions(bool ignore_sensitive_content_restrictions) {
@ -1098,7 +1093,7 @@ void ConfigManager::on_result(NetQueryPtr res) {
auto r_config = fetch_result<telegram_api::help_getConfig>(std::move(res));
if (r_config.is_error()) {
if (!G()->close_flag()) {
LOG(ERROR) << "TODO: getConfig failed: " << r_config.error();
LOG(ERROR) << "getConfig failed: " << r_config.error();
expire_time_ = Timestamp::in(60.0); // try again in a minute
set_timeout_in(expire_time_.in());
}

File diff suppressed because it is too large Load Diff

View File

@ -21,6 +21,7 @@
#include "td/telegram/files/FileSourceId.h"
#include "td/telegram/Location.h"
#include "td/telegram/MessageId.h"
#include "td/telegram/net/DcId.h"
#include "td/telegram/Photo.h"
#include "td/telegram/PublicDialogType.h"
#include "td/telegram/QueryCombiner.h"
@ -163,6 +164,7 @@ class ContactsManager : public Actor {
void on_get_chat_full(tl_object_ptr<telegram_api::ChatFull> &&chat_full, Promise<Unit> &&promise);
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_update_user_name(UserId user_id, string &&first_name, string &&last_name, string &&username);
void on_update_user_phone_number(UserId user_id, string &&phone_number);
@ -196,7 +198,7 @@ class ContactsManager : public Actor {
void on_update_channel_default_permissions(ChannelId channel_id, RestrictedRights default_permissions);
void on_update_channel_administrator_count(ChannelId channel_id, int32 administrator_count);
void on_update_peer_located(vector<tl_object_ptr<telegram_api::peerLocated>> &&peers, bool from_update);
int32 on_update_peer_located(vector<tl_object_ptr<telegram_api::PeerLocated>> &&peers, bool from_update);
void on_update_dialog_administrators(DialogId dialog_id, vector<DialogAdministrator> &&administrators,
bool have_access);
@ -313,6 +315,10 @@ class ContactsManager : public Actor {
void search_dialogs_nearby(const Location &location, Promise<td_api::object_ptr<td_api::chatsNearby>> &&promise);
void set_location(const Location &location, Promise<Unit> &&promise);
void set_location_visibility();
void set_profile_photo(const tl_object_ptr<td_api::InputFile> &input_photo, Promise<Unit> &&promise);
void delete_profile_photo(int64 profile_photo_id, Promise<Unit> &&promise);
@ -325,6 +331,8 @@ class ContactsManager : public Actor {
void set_username(const string &username, Promise<Unit> &&promise);
void set_commands(vector<td_api::object_ptr<td_api::botCommand>> &&commands, Promise<Unit> &&promise);
void set_chat_description(ChatId chat_id, const string &description, Promise<Unit> &&promise);
void set_channel_username(ChannelId channel_id, const string &username, Promise<Unit> &&promise);
@ -349,6 +357,12 @@ class ContactsManager : public Actor {
void delete_channel(ChannelId channel_id, Promise<Unit> &&promise);
void get_channel_statistics(DialogId dialog_id, bool is_dark,
Promise<td_api::object_ptr<td_api::chatStatistics>> &&promise);
void load_statistics_graph(DialogId dialog_id, const string &token, int64 x,
Promise<td_api::object_ptr<td_api::StatisticsGraph>> &&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,
@ -414,7 +428,7 @@ class ContactsManager : public Actor {
UserId get_me(Promise<Unit> &&promise);
bool get_user(UserId user_id, int left_tries, Promise<Unit> &&promise);
void reload_user(UserId user_id, Promise<Unit> &&promise);
bool get_user_full(UserId user_id, Promise<Unit> &&promise);
bool get_user_full(UserId user_id, bool force, Promise<Unit> &&promise);
void reload_user_full(UserId user_id);
std::pair<int32, vector<const Photo *>> get_user_profile_photos(UserId user_id, int32 offset, int32 limit,
@ -426,7 +440,7 @@ class ContactsManager : public Actor {
bool have_chat_force(ChatId chat_id);
bool get_chat(ChatId chat_id, int left_tries, Promise<Unit> &&promise);
void reload_chat(ChatId chat_id, Promise<Unit> &&promise);
bool get_chat_full(ChatId chat_id, Promise<Unit> &&promise);
bool get_chat_full(ChatId chat_id, bool force, Promise<Unit> &&promise);
bool get_chat_is_active(ChatId chat_id) const;
DialogParticipantStatus get_chat_status(ChatId chat_id) const;
@ -439,7 +453,7 @@ class ContactsManager : public Actor {
bool have_channel_force(ChannelId channel_id);
bool get_channel(ChannelId channel_id, int left_tries, Promise<Unit> &&promise);
void reload_channel(ChannelId chnanel_id, Promise<Unit> &&promise);
bool get_channel_full(ChannelId channel_id, Promise<Unit> &&promise);
bool get_channel_full(ChannelId channel_id, bool force, Promise<Unit> &&promise);
bool is_channel_public(ChannelId channel_id) const;
@ -525,6 +539,16 @@ class ContactsManager : public Actor {
void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
static tl_object_ptr<td_api::StatisticsGraph> convert_stats_graph(tl_object_ptr<telegram_api::StatsGraph> obj);
static double get_percentage_value(double new_value, double old_value);
static tl_object_ptr<td_api::statisticsValue> convert_stats_absolute_value(
const tl_object_ptr<telegram_api::statsAbsValueAndPrev> &obj);
static tl_object_ptr<td_api::chatStatistics> convert_broadcast_stats(
tl_object_ptr<telegram_api::stats_broadcastStats> obj);
private:
struct User {
string first_name;
@ -767,6 +791,8 @@ class ContactsManager : public Actor {
DialogLocation location;
DcId stats_dc_id;
int32 slow_mode_delay = 0;
int32 slow_mode_next_send_date = 0;
@ -779,7 +805,6 @@ class ContactsManager : public Actor {
bool can_set_username = false;
bool can_set_sticker_set = false;
bool can_set_location = false;
bool can_view_statistics = false;
bool is_all_history_available = true;
bool is_slow_mode_next_send_date_changed = true;
@ -1065,7 +1090,7 @@ class ContactsManager : public Actor {
void on_update_user_full_common_chat_count(UserFull *user_full, UserId user_id, int32 common_chat_count);
void on_update_user_full_need_phone_number_privacy_exception(UserFull *user_full, UserId user_id,
bool need_phone_number_privacy_exception);
void drop_user_photos(UserId user_id, bool is_empty);
void drop_user_photos(UserId user_id, bool is_empty, const char *source);
void drop_user_full(UserId user_id);
void on_set_user_is_blocked_failed(UserId user_id, bool is_blocked, Status error);
@ -1238,6 +1263,14 @@ class ContactsManager : public Actor {
void on_get_dialogs_nearby(Result<tl_object_ptr<telegram_api::Updates>> result,
Promise<td_api::object_ptr<td_api::chatsNearby>> &&promise);
void try_send_set_location_visibility_query();
void on_set_location_visibility_expire_date(int32 set_expire_date, int32 error_code);
void set_location_visibility_expire_date(int32 expire_date);
void update_is_location_visible();
static bool is_channel_public(const Channel *c);
static bool is_valid_invite_link(const string &invite_link);
@ -1305,6 +1338,16 @@ class ContactsManager : public Actor {
tl_object_ptr<telegram_api::InputCheckPasswordSRP> input_check_password,
Promise<Unit> &&promise);
void get_channel_statistics_dc_id(DialogId dialog_id, Promise<DcId> &&promise);
void get_channel_statistics_dc_id_impl(ChannelId channel_id, Promise<DcId> &&promise);
void send_get_broadcast_stats_query(DcId dc_id, ChannelId channel_id, bool is_dark,
Promise<td_api::object_ptr<td_api::chatStatistics>> &&promise);
void send_load_async_graph_query(DcId dc_id, string token, int64 x,
Promise<td_api::object_ptr<td_api::StatisticsGraph>> &&promise);
static void on_user_online_timeout_callback(void *contacts_manager_ptr, int64 user_id_long);
static void on_channel_unban_timeout_callback(void *contacts_manager_ptr, int64 channel_id_long);
@ -1425,6 +1468,12 @@ class ContactsManager : public Actor {
vector<DialogNearby> users_nearby_;
vector<DialogNearby> channels_nearby_;
std::unordered_set<UserId, UserIdHash> all_users_nearby_;
int32 location_visibility_expire_date_ = 0;
int32 pending_location_visibility_expire_date_ = -1;
bool is_set_location_visibility_request_sent_ = false;
Location last_user_location_;
std::unordered_map<ChannelId, ChannelId, ChannelIdHash> linked_channel_ids_;

View File

@ -373,12 +373,12 @@ void DeviceTokenManager::loop() {
auto other_user_ids = info.other_user_ids;
if (info.state == TokenInfo::State::Unregister) {
net_query = G()->net_query_creator().create(
create_storer(telegram_api::account_unregisterDevice(token_type, info.token, std::move(other_user_ids))));
telegram_api::account_unregisterDevice(token_type, info.token, std::move(other_user_ids)));
} else {
int32 flags = telegram_api::account_registerDevice::NO_MUTED_MASK;
net_query = G()->net_query_creator().create(create_storer(
net_query = G()->net_query_creator().create(
telegram_api::account_registerDevice(flags, false /*ignored*/, token_type, info.token, info.is_app_sandbox,
BufferSlice(info.encryption_key), std::move(other_user_ids))));
BufferSlice(info.encryption_key), std::move(other_user_ids)));
}
info.net_query_id = net_query->id();
G()->net_query_dispatcher().dispatch_with_callback(std::move(net_query), actor_shared(this, token_type));
@ -418,7 +418,7 @@ void DeviceTokenManager::on_result(NetQueryPtr net_query) {
info.state = TokenInfo::State::Sync;
} else {
if (r_flag.is_error()) {
if (!G()->close_flag()) {
if (!G()->is_expected_error(r_flag.error())) {
LOG(ERROR) << "Failed to " << info.state << " device: " << r_flag.error();
}
info.promise.set_error(r_flag.move_as_error());

View File

@ -38,19 +38,19 @@ Status init_dialog_db(SqliteDb &db, int32 version, bool &was_created) {
version = 0;
}
auto create_notification_group_table = [&db]() {
auto create_notification_group_table = [&db] {
return db.exec(
"CREATE TABLE IF NOT EXISTS notification_groups (notification_group_id INT4 PRIMARY KEY, dialog_id "
"INT8, last_notification_date INT4)");
};
auto create_last_notification_date_index = [&db]() {
auto create_last_notification_date_index = [&db] {
return db.exec(
"CREATE INDEX IF NOT EXISTS notification_group_by_last_notification_date ON notification_groups "
"(last_notification_date, dialog_id, notification_group_id) WHERE last_notification_date IS NOT NULL");
};
auto add_dialogs_in_folder_index = [&db]() {
auto add_dialogs_in_folder_index = [&db] {
return db.exec(
"CREATE INDEX IF NOT EXISTS dialog_in_folder_by_dialog_order ON dialogs (folder_id, dialog_order, dialog_id) "
"WHERE folder_id IS NOT NULL");
@ -75,7 +75,7 @@ Status init_dialog_db(SqliteDb &db, int32 version, bool &was_created) {
TRY_STATUS(db.exec("DROP INDEX IF EXISTS dialog_by_dialog_order"));
TRY_STATUS(db.exec("ALTER TABLE dialogs ADD COLUMN folder_id INT4"));
TRY_STATUS(add_dialogs_in_folder_index());
TRY_STATUS(db.exec("UPDATE dialogs SET folder_id = 0 WHERE dialog_id < -1500000000000 AND dialog_order != 0"));
TRY_STATUS(db.exec("UPDATE dialogs SET folder_id = 0 WHERE dialog_id < -1500000000000 AND dialog_order > 0"));
}
return Status::OK();
@ -129,7 +129,7 @@ class DialogDbImpl : public DialogDbSyncInterface {
TRY_RESULT_ASSIGN(
get_secret_chat_count_stmt_,
db_.get_statement(
"SELECT COUNT(*) FROM dialogs WHERE folder_id = ?1 AND dialog_order != 0 AND dialog_id < -1500000000000"));
"SELECT COUNT(*) FROM dialogs WHERE folder_id = ?1 AND dialog_order > 0 AND dialog_id < -1500000000000"));
// LOG(ERROR) << get_dialog_stmt_.explain().ok();
// LOG(ERROR) << get_dialogs_stmt_.explain().ok();

View File

@ -18,7 +18,7 @@ td_api::object_ptr<td_api::draftMessage> get_draft_message_object(const unique_p
if (draft_message == nullptr) {
return nullptr;
}
return td_api::make_object<td_api::draftMessage>(draft_message->reply_to_message_id.get(),
return td_api::make_object<td_api::draftMessage>(draft_message->reply_to_message_id.get(), draft_message->date,
get_input_message_text_object(draft_message->input_message_text));
}
@ -51,7 +51,7 @@ unique_ptr<DraftMessage> get_draft_message(ContactsManager *contacts_manager,
if (!clean_input_string(draft->message_)) {
draft->message_.clear();
}
entities.clear();
entities = find_entities(draft->message_, false);
}
result->input_message_text.text = FormattedText{std::move(draft->message_), std::move(entities)};
result->input_message_text.disable_web_page_preview = (flags & telegram_api::draftMessage::NO_WEBPAGE_MASK) != 0;

View File

@ -102,6 +102,9 @@ Status Global::init(const TdParameters &parameters, ActorId<Td> td, unique_ptr<T
ServerTimeDiff saved_diff;
unserialize(saved_diff, saved_diff_str).ensure();
saved_diff_ = saved_diff.diff;
saved_system_time_ = saved_diff.system_time;
double diff = saved_diff.diff + default_time_difference;
if (saved_diff.system_time > system_time) {
double time_backwards_fix = saved_diff.system_time - system_time;
@ -118,6 +121,8 @@ Status Global::init(const TdParameters &parameters, ActorId<Td> td, unique_ptr<T
<< tag("saved_system_time", saved_diff.system_time) << tag("system_time", system_time);
diff -= time_forward_fix;
}
} else if (saved_diff.diff >= 1500000000 && system_time >= 1500000000) { // only for saved_diff.system_time == 0
diff = default_time_difference;
}
LOG(DEBUG) << "LOAD: " << tag("server_time_difference", diff);
server_time_difference_ = diff;
@ -129,8 +134,10 @@ Status Global::init(const TdParameters &parameters, ActorId<Td> td, unique_ptr<T
return Status::OK();
}
int32 Global::to_unix_time(double server_time) {
LOG_CHECK(1.0 <= server_time && server_time <= 2140000000.0) << server_time << " " << Clocks::system();
int32 Global::to_unix_time(double server_time) const {
LOG_CHECK(1.0 <= server_time && server_time <= 2140000000.0)
<< server_time << " " << Clocks::system() << " " << is_server_time_reliable() << " "
<< get_server_time_difference() << " " << Time::now() << saved_diff_ << " " << saved_system_time_;
return static_cast<int32>(server_time);
}
@ -250,4 +257,8 @@ void Global::add_location_access_hash(double latitude, double longitude, int64 a
location_access_hashes_[get_location_key(latitude, longitude)] = access_hash;
}
double get_server_time() {
return G()->server_time();
}
} // namespace td

View File

@ -343,6 +343,19 @@ class Global : public ActorContext {
return close_flag_.load();
}
bool is_expected_error(const Status &error) const {
CHECK(error.is_error());
if (error.code() == 401) {
// authorization is lost
return true;
}
if (error.code() == 420 || error.code() == 429) {
// flood wait
return true;
}
return close_flag();
}
const std::vector<std::shared_ptr<NetStatsCallback>> &get_net_stats_file_callbacks() {
return net_stats_file_callbacks_;
}
@ -398,6 +411,8 @@ class Global : public ActorContext {
std::atomic<bool> dns_time_difference_was_updated_{false};
std::atomic<bool> close_flag_{false};
std::atomic<double> system_time_saved_at_{-1e10};
double saved_diff_ = 0.0;
double saved_system_time_ = 0.0;
#if !TD_HAVE_ATOMIC_SHARED_PTR
std::mutex dh_config_mutex_;
@ -418,7 +433,7 @@ class Global : public ActorContext {
std::unordered_map<int64, int64> location_access_hashes_;
static int32 to_unix_time(double server_time);
int32 to_unix_time(double server_time) const;
void do_save_server_time_difference();
@ -434,4 +449,6 @@ inline Global *G_impl(const char *file, int line) {
return static_cast<Global *>(context);
}
double get_server_time();
} // namespace td

View File

@ -80,9 +80,9 @@ class GetInlineBotResultsQuery : public Td::ResultHandler {
input_peer = make_tl_object<telegram_api::inputPeerEmpty>();
}
auto net_query = G()->net_query_creator().create(create_storer(telegram_api::messages_getInlineBotResults(
auto net_query = G()->net_query_creator().create(telegram_api::messages_getInlineBotResults(
flags, std::move(bot_input_user), std::move(input_peer),
user_location.empty() ? nullptr : user_location.get_input_geo_point(), query, offset)));
user_location.empty() ? nullptr : user_location.get_input_geo_point(), query, offset));
auto result = net_query.get_weak();
net_query->need_resend_on_503 = false;
send_query(std::move(net_query));
@ -135,9 +135,9 @@ class SetInlineBotResultsQuery : public Td::ResultHandler {
flags |= telegram_api::messages_setInlineBotResults::SWITCH_PM_MASK;
inline_bot_switch_pm = make_tl_object<telegram_api::inlineBotSwitchPM>(switch_pm_text, switch_pm_parameter);
}
send_query(G()->net_query_creator().create(create_storer(telegram_api::messages_setInlineBotResults(
send_query(G()->net_query_creator().create(telegram_api::messages_setInlineBotResults(
flags, false /*ignored*/, false /*ignored*/, inline_query_id, std::move(results), cache_time, next_offset,
std::move(inline_bot_switch_pm)))));
std::move(inline_bot_switch_pm))));
}
void on_result(uint64 id, BufferSlice packet) override {
@ -450,7 +450,7 @@ void InlineQueriesManager::answer_inline_query(int64 inline_query_id, bool is_pe
return promise.set_error(Status::Error(400, "Field \"phone_number\" must contain a valid phone number"));
}
if (first_name.empty()) {
return promise.set_error(Status::Error(400, "Field \"first_name\" should be non-empty"));
return promise.set_error(Status::Error(400, "Field \"first_name\" must be non-empty"));
}
title = last_name.empty() ? first_name : first_name + " " + last_name;
description = std::move(phone_number);
@ -633,7 +633,7 @@ void InlineQueriesManager::answer_inline_query(int64 inline_query_id, bool is_pe
}
auto inline_message = r_inline_message.move_as_ok();
if (inline_message->get_id() == telegram_api::inputBotInlineMessageMediaAuto::ID && file_type == FileType::Temp) {
return promise.set_error(Status::Error(400, "Sent message content should be explicitly specified"));
return promise.set_error(Status::Error(400, "Sent message content must be explicitly specified"));
}
if (duration < 0) {

View File

@ -6,6 +6,8 @@
//
#include "td/telegram/InputMessageText.h"
#include "td/telegram/ConfigShared.h"
#include "td/telegram/Global.h"
#include "td/telegram/MessageEntity.h"
#include "td/utils/common.h"
@ -37,10 +39,18 @@ Result<InputMessageText> process_input_message_text(const ContactsManager *conta
}
TRY_RESULT(entities, get_message_entities(contacts_manager, std::move(input_message_text->text_->entities_)));
TRY_STATUS(fix_formatted_text(input_message_text->text_->text_, entities, for_draft, false,
need_skip_bot_commands(contacts_manager, dialog_id, is_bot), for_draft));
return InputMessageText{FormattedText{std::move(input_message_text->text_->text_), std::move(entities)},
auto need_skip_commands = need_skip_bot_commands(contacts_manager, dialog_id, is_bot);
bool parse_markdown = G()->shared_config().get_option_boolean("always_parse_markdown");
TRY_STATUS(fix_formatted_text(input_message_text->text_->text_, entities, for_draft, parse_markdown,
need_skip_commands, for_draft));
InputMessageText result{FormattedText{std::move(input_message_text->text_->text_), std::move(entities)},
input_message_text->disable_web_page_preview_, input_message_text->clear_draft_};
if (G()->shared_config().get_option_boolean("always_parse_markdown")) {
result.text = parse_markdown_v3(std::move(result.text));
fix_formatted_text(result.text.text, result.text.entities, for_draft, false, need_skip_commands, for_draft)
.ensure();
}
return std::move(result);
}
td_api::object_ptr<td_api::inputMessageText> get_input_message_text_object(const InputMessageText &input_message_text) {

View File

@ -10,7 +10,6 @@
#include "td/telegram/Global.h"
#include "td/telegram/logevent/LogEvent.h"
#include "td/telegram/misc.h"
#include "td/telegram/net/DcId.h"
#include "td/telegram/net/NetQueryDispatcher.h"
#include "td/telegram/Td.h"
@ -383,9 +382,8 @@ void LanguagePackManager::send_language_get_difference_query(Language *language,
std::move(language_code), result->version_, true, vector<string>(), std::move(result->strings_),
Promise<td_api::object_ptr<td_api::languagePackStrings>>());
});
send_with_promise(G()->net_query_creator().create(
create_storer(telegram_api::langpack_getDifference(language_pack_, language_code, version)),
DcId::main(), NetQuery::Type::Common, NetQuery::AuthFlag::Off),
send_with_promise(G()->net_query_creator().create_unauth(
telegram_api::langpack_getDifference(language_pack_, language_code, version)),
std::move(request_promise));
}
@ -798,8 +796,7 @@ void LanguagePackManager::get_languages(bool only_local,
send_closure(actor_id, &LanguagePackManager::on_get_languages, r_result.move_as_ok(), std::move(language_pack),
false, std::move(promise));
});
send_with_promise(G()->net_query_creator().create(create_storer(telegram_api::langpack_getLanguages(language_pack_)),
DcId::main(), NetQuery::Type::Common, NetQuery::AuthFlag::Off),
send_with_promise(G()->net_query_creator().create_unauth(telegram_api::langpack_getLanguages(language_pack_)),
std::move(request_promise));
}
@ -821,8 +818,7 @@ void LanguagePackManager::search_language_info(string language_code,
std::move(language_code), std::move(promise));
});
send_with_promise(
G()->net_query_creator().create(create_storer(telegram_api::langpack_getLanguage(language_pack_, language_code)),
DcId::main(), NetQuery::Type::Common, NetQuery::AuthFlag::Off),
G()->net_query_creator().create_unauth(telegram_api::langpack_getLanguage(language_pack_, language_code)),
std::move(request_promise));
}
@ -1082,10 +1078,9 @@ void LanguagePackManager::get_language_pack_strings(string language_code, vector
std::move(language_code), result->version_, false, vector<string>(), std::move(result->strings_),
std::move(promise));
});
send_with_promise(G()->net_query_creator().create(
create_storer(telegram_api::langpack_getLangPack(language_pack_, language_code)),
DcId::main(), NetQuery::Type::Common, NetQuery::AuthFlag::Off),
std::move(request_promise));
send_with_promise(
G()->net_query_creator().create_unauth(telegram_api::langpack_getLangPack(language_pack_, language_code)),
std::move(request_promise));
} else {
auto request_promise =
PromiseCreator::lambda([actor_id = actor_id(this), language_pack = language_pack_, language_code, keys,
@ -1098,9 +1093,8 @@ void LanguagePackManager::get_language_pack_strings(string language_code, vector
send_closure(actor_id, &LanguagePackManager::on_get_language_pack_strings, std::move(language_pack),
std::move(language_code), -1, false, std::move(keys), r_result.move_as_ok(), std::move(promise));
});
send_with_promise(G()->net_query_creator().create(create_storer(telegram_api::langpack_getStrings(
language_pack_, language_code, std::move(keys))),
DcId::main(), NetQuery::Type::Common, NetQuery::AuthFlag::Off),
send_with_promise(G()->net_query_creator().create_unauth(
telegram_api::langpack_getStrings(language_pack_, language_code, std::move(keys))),
std::move(request_promise));
}
}

View File

@ -59,7 +59,7 @@ Status Logging::set_current_stream(td_api::object_ptr<td_api::LogStream> stream)
auto file_stream = td_api::move_object_as<td_api::logStreamFile>(stream);
auto max_log_file_size = file_stream->max_file_size_;
if (max_log_file_size <= 0) {
return Status::Error("Max log file size should be positive");
return Status::Error("Max log file size must be positive");
}
TRY_STATUS(file_log.init(file_stream->path_, max_log_file_size));

View File

@ -643,6 +643,19 @@ class MessagePoll : public MessageContent {
}
};
class MessageDice : public MessageContent {
public:
int32 dice_value = 0;
MessageDice() = default;
explicit MessageDice(int32 dice_value) : dice_value(dice_value) {
}
MessageContentType get_type() const override {
return MessageContentType::Dice;
}
};
template <class StorerT>
static void store(const MessageContent *content, StorerT &storer) {
CHECK(content != nullptr);
@ -900,6 +913,11 @@ static void store(const MessageContent *content, StorerT &storer) {
store(m->poll_id, storer);
break;
}
case MessageContentType::Dice: {
auto m = static_cast<const MessageDice *>(content);
store(m->dice_value, storer);
break;
}
default:
UNREACHABLE();
}
@ -1242,6 +1260,13 @@ static void parse(unique_ptr<MessageContent> &content, ParserT &parser) {
content = std::move(m);
break;
}
case MessageContentType::Dice: {
auto m = make_unique<MessageDice>();
parse(m->dice_value, parser);
is_bad = m->dice_value < 0 || m->dice_value > 6;
content = std::move(m);
break;
}
default:
LOG(FATAL) << "Have unknown message content type " << static_cast<int32>(content_type);
}
@ -1330,9 +1355,9 @@ InlineMessageContent create_inline_message_content(Td *td, FileId file_id,
}
case telegram_api::botInlineMessageMediaAuto::ID: {
auto input_message_media_auto = move_tl_object_as<telegram_api::botInlineMessageMediaAuto>(inline_message);
auto caption =
get_message_text(td->contacts_manager_.get(), input_message_media_auto->message_,
std::move(input_message_media_auto->entities_), true, 0, "register_inline_message_content");
auto caption = get_message_text(td->contacts_manager_.get(), input_message_media_auto->message_,
std::move(input_message_media_auto->entities_), true, 0, false,
"register_inline_message_content");
if (allowed_media_content_id == td_api::inputMessageAnimation::ID) {
result.message_content = make_unique<MessageAnimation>(file_id, std::move(caption));
} else if (allowed_media_content_id == td_api::inputMessageAudio::ID) {
@ -1450,6 +1475,9 @@ static Result<InputMessageContent> create_input_message_content(
content = make_unique<MessageAudio>(file_id, std::move(caption));
break;
}
case td_api::inputMessageDice::ID:
content = make_unique<MessageDice>();
break;
case td_api::inputMessageDocument::ID:
td->documents_manager_->create_document(file_id, string(), thumbnail, std::move(file_name), std::move(mime_type),
false);
@ -1903,6 +1931,7 @@ bool can_have_input_media(const Td *td, const MessageContent *content) {
case MessageContentType::Animation:
case MessageContentType::Audio:
case MessageContentType::Contact:
case MessageContentType::Dice:
case MessageContentType::Document:
case MessageContentType::Invoice:
case MessageContentType::LiveLocation:
@ -1981,6 +2010,7 @@ SecretInputMedia get_secret_input_media(const MessageContent *content, Td *td,
return td->voice_notes_manager_->get_secret_input_media(m->file_id, std::move(input_file), m->caption.text);
}
case MessageContentType::Call:
case MessageContentType::Dice:
case MessageContentType::Game:
case MessageContentType::Invoice:
case MessageContentType::LiveLocation:
@ -2113,6 +2143,8 @@ static tl_object_ptr<telegram_api::InputMedia> get_input_media_impl(
auto m = static_cast<const MessageContact *>(content);
return m->contact.get_input_media_contact();
}
case MessageContentType::Dice:
return make_tl_object<telegram_api::inputMediaDice>();
case MessageContentType::Document: {
auto m = static_cast<const MessageDocument *>(content);
return td->documents_manager_->get_input_media(m->file_id, std::move(input_file), std::move(input_thumbnail));
@ -2268,6 +2300,7 @@ void delete_message_content_thumbnail(MessageContent *content, Td *td) {
return td->video_notes_manager_->delete_video_note_thumbnail(m->file_id);
}
case MessageContentType::Contact:
case MessageContentType::Dice:
case MessageContentType::Game:
case MessageContentType::Invoice:
case MessageContentType::LiveLocation:
@ -2436,6 +2469,7 @@ static int32 get_message_content_media_index_mask(const MessageContent *content,
case MessageContentType::PassportDataSent:
case MessageContentType::PassportDataReceived:
case MessageContentType::Poll:
case MessageContentType::Dice:
return 0;
default:
UNREACHABLE();
@ -2512,11 +2546,16 @@ bool get_message_content_poll_is_anonymous(const Td *td, const MessageContent *c
}
}
bool has_message_content_web_page(const MessageContent *content) {
if (content->get_type() == MessageContentType::Text) {
return static_cast<const MessageText *>(content)->web_page_id.is_valid();
}
return false;
}
void remove_message_content_web_page(MessageContent *content) {
CHECK(content->get_type() == MessageContentType::Text);
auto &web_page_id = static_cast<MessageText *>(content)->web_page_id;
CHECK(web_page_id.is_valid());
web_page_id = WebPageId();
static_cast<MessageText *>(content)->web_page_id = WebPageId();
}
void set_message_content_poll_answer(Td *td, const MessageContent *content, FullMessageId full_message_id,
@ -3034,6 +3073,14 @@ void merge_message_contents(Td *td, const MessageContent *old_content, MessageCo
}
break;
}
case MessageContentType::Dice: {
auto old_ = static_cast<const MessageDice *>(old_content);
auto new_ = static_cast<const MessageDice *>(new_content);
if (old_->dice_value != new_->dice_value) {
need_update = true;
}
break;
}
case MessageContentType::Unsupported: {
auto old_ = static_cast<const MessageUnsupported *>(old_content);
auto new_ = static_cast<const MessageUnsupported *>(new_content);
@ -3165,6 +3212,7 @@ bool merge_message_content_file_id(Td *td, MessageContent *message_content, File
case MessageContentType::PassportDataSent:
case MessageContentType::PassportDataReceived:
case MessageContentType::Poll:
case MessageContentType::Dice:
LOG(ERROR) << "Receive new file " << new_file_id << " in a sent message of the type " << content_type;
break;
default:
@ -3174,20 +3222,22 @@ bool merge_message_content_file_id(Td *td, MessageContent *message_content, File
return false;
}
void register_message_content(Td *td, const MessageContent *content, FullMessageId full_message_id) {
void register_message_content(Td *td, const MessageContent *content, FullMessageId full_message_id,
const char *source) {
switch (content->get_type()) {
case MessageContentType::Text:
return td->web_pages_manager_->register_web_page(static_cast<const MessageText *>(content)->web_page_id,
full_message_id);
full_message_id, source);
case MessageContentType::Poll:
return td->poll_manager_->register_poll(static_cast<const MessagePoll *>(content)->poll_id, full_message_id);
return td->poll_manager_->register_poll(static_cast<const MessagePoll *>(content)->poll_id, full_message_id,
source);
default:
return;
}
}
void reregister_message_content(Td *td, const MessageContent *old_content, const MessageContent *new_content,
FullMessageId full_message_id) {
FullMessageId full_message_id, const char *source) {
auto old_content_type = old_content->get_type();
auto new_content_type = new_content->get_type();
if (old_content_type == new_content_type) {
@ -3208,41 +3258,24 @@ void reregister_message_content(Td *td, const MessageContent *old_content, const
return;
}
}
unregister_message_content(td, old_content, full_message_id);
register_message_content(td, new_content, full_message_id);
unregister_message_content(td, old_content, full_message_id, source);
register_message_content(td, new_content, full_message_id, source);
}
void unregister_message_content(Td *td, const MessageContent *content, FullMessageId full_message_id) {
void unregister_message_content(Td *td, const MessageContent *content, FullMessageId full_message_id,
const char *source) {
switch (content->get_type()) {
case MessageContentType::Text:
return td->web_pages_manager_->unregister_web_page(static_cast<const MessageText *>(content)->web_page_id,
full_message_id);
full_message_id, source);
case MessageContentType::Poll:
return td->poll_manager_->unregister_poll(static_cast<const MessagePoll *>(content)->poll_id, full_message_id);
return td->poll_manager_->unregister_poll(static_cast<const MessagePoll *>(content)->poll_id, full_message_id,
source);
default:
return;
}
}
static FormattedText get_secret_media_caption(string &&message_text, string &&message_caption) {
// message_text was already cleaned
if (!clean_input_string(message_caption)) {
message_caption.clear();
}
FormattedText caption;
if (message_text.empty()) {
caption.text = std::move(message_caption);
} else if (message_caption.empty()) {
caption.text = std::move(message_text);
} else {
caption.text = message_text + "\n\n" + message_caption;
}
caption.entities = find_entities(caption.text, false);
return caption;
}
template <class ToT, class FromT>
static tl_object_ptr<ToT> secret_to_telegram(FromT &from);
@ -3444,17 +3477,6 @@ static unique_ptr<MessageContent> get_document_message_content(Document &&parsed
}
}
static unique_ptr<MessageContent> get_secret_document_message_content(
Td *td, tl_object_ptr<telegram_api::encryptedFile> file,
tl_object_ptr<secret_api::decryptedMessageMediaDocument> &&document,
vector<tl_object_ptr<telegram_api::DocumentAttribute>> &&attributes, DialogId owner_dialog_id,
FormattedText &&caption, bool is_opened) {
return get_document_message_content(
td->documents_manager_->on_get_document({std::move(file), std::move(document), std::move(attributes)},
owner_dialog_id),
std::move(caption), is_opened);
}
static unique_ptr<MessageContent> get_document_message_content(Td *td, tl_object_ptr<telegram_api::document> &&document,
DialogId owner_dialog_id, FormattedText &&caption,
bool is_opened,
@ -3469,6 +3491,35 @@ unique_ptr<MessageContent> get_secret_message_content(
tl_object_ptr<secret_api::DecryptedMessageMedia> &&media,
vector<tl_object_ptr<secret_api::MessageEntity>> &&secret_entities, DialogId owner_dialog_id,
MultiPromiseActor &load_data_multipromise) {
int32 constructor_id = media == nullptr ? secret_api::decryptedMessageMediaEmpty::ID : media->get_id();
auto caption = [&] {
switch (constructor_id) {
case secret_api::decryptedMessageMediaVideo::ID: {
auto video = static_cast<secret_api::decryptedMessageMediaVideo *>(media.get());
return std::move(video->caption_);
}
case secret_api::decryptedMessageMediaPhoto::ID: {
auto photo = static_cast<secret_api::decryptedMessageMediaPhoto *>(media.get());
return std::move(photo->caption_);
}
case secret_api::decryptedMessageMediaDocument::ID: {
auto document = static_cast<secret_api::decryptedMessageMediaDocument *>(media.get());
return std::move(document->caption_);
}
default:
return string();
}
}();
if (!clean_input_string(caption)) {
caption.clear();
}
if (message_text.empty()) {
message_text = std::move(caption);
} else if (!caption.empty()) {
message_text = message_text + "\n\n" + caption;
}
auto entities = get_message_entities(std::move(secret_entities));
auto status = fix_formatted_text(message_text, entities, true, false, true, false);
if (status.is_error()) {
@ -3477,20 +3528,7 @@ unique_ptr<MessageContent> get_secret_message_content(
if (!clean_input_string(message_text)) {
message_text.clear();
}
entities.clear();
}
if (media == nullptr) {
return create_text_message_content(std::move(message_text), std::move(entities), WebPageId());
}
int32 constructor_id = media->get_id();
if (message_text.size()) {
if (constructor_id != secret_api::decryptedMessageMediaEmpty::ID) {
LOG(INFO) << "Receive non-empty message text and media";
} else {
return create_text_message_content(std::move(message_text), std::move(entities), WebPageId());
}
entities = find_entities(message_text, true);
}
// support of old layer and old constructions
@ -3502,7 +3540,7 @@ unique_ptr<MessageContent> get_secret_message_content(
make_tl_object<secret_api::documentAttributeVideo>(video->duration_, video->w_, video->h_));
media = make_tl_object<secret_api::decryptedMessageMediaDocument>(
std::move(video->thumb_), video->thumb_w_, video->thumb_h_, video->mime_type_, video->size_,
std::move(video->key_), std::move(video->iv_), std::move(attributes), std::move(video->caption_));
std::move(video->key_), std::move(video->iv_), std::move(attributes), string());
constructor_id = secret_api::decryptedMessageMediaDocument::ID;
break;
@ -3512,7 +3550,9 @@ unique_ptr<MessageContent> get_secret_message_content(
bool is_media_empty = false;
switch (constructor_id) {
case secret_api::decryptedMessageMediaEmpty::ID:
LOG(ERROR) << "Receive empty message text and media";
if (message_text.empty()) {
LOG(ERROR) << "Receive empty message text and media";
}
is_media_empty = true;
break;
case secret_api::decryptedMessageMediaGeoPoint::ID: {
@ -3612,7 +3652,7 @@ unique_ptr<MessageContent> get_secret_message_content(
auto message_photo = move_tl_object_as<secret_api::decryptedMessageMediaPhoto>(media);
return make_unique<MessagePhoto>(
get_encrypted_file_photo(td->file_manager_.get(), std::move(file), std::move(message_photo), owner_dialog_id),
get_secret_media_caption(std::move(message_text), std::move(message_photo->caption_)));
FormattedText{std::move(message_text), std::move(entities)});
}
case secret_api::decryptedMessageMediaDocument::ID: {
auto message_document = move_tl_object_as<secret_api::decryptedMessageMediaDocument>(media);
@ -3621,9 +3661,9 @@ unique_ptr<MessageContent> get_secret_message_content(
}
auto attributes = secret_to_telegram(message_document->attributes_);
message_document->attributes_.clear();
return get_secret_document_message_content(
td, std::move(file), std::move(message_document), std::move(attributes), owner_dialog_id,
get_secret_media_caption(std::move(message_text), std::move(message_document->caption_)), false);
auto document = td->documents_manager_->on_get_document(
{std::move(file), std::move(message_document), std::move(attributes)}, owner_dialog_id);
return get_document_message_content(std::move(document), {std::move(message_text), std::move(entities)}, false);
}
default:
LOG(ERROR) << "Unsupported: " << to_string(media);
@ -3635,21 +3675,17 @@ unique_ptr<MessageContent> get_message_content(Td *td, FormattedText message,
tl_object_ptr<telegram_api::MessageMedia> &&media,
DialogId owner_dialog_id, bool is_content_read, UserId via_bot_user_id,
int32 *ttl) {
if (media == nullptr) {
return make_unique<MessageText>(std::move(message), WebPageId());
if (!td->auth_manager_->is_authorized() && !G()->close_flag() && media != nullptr) {
LOG(ERROR) << "Receive without authorization " << to_string(media);
media = nullptr;
}
int32 constructor_id = media->get_id();
if (message.text.size()) {
if (constructor_id != telegram_api::messageMediaEmpty::ID) {
LOG(INFO) << "Receive non-empty message text and media for message from " << owner_dialog_id;
} else {
return make_unique<MessageText>(std::move(message), WebPageId());
}
}
int32 constructor_id = media == nullptr ? telegram_api::messageMediaEmpty::ID : media->get_id();
switch (constructor_id) {
case telegram_api::messageMediaEmpty::ID:
LOG(ERROR) << "Receive empty message text and media for message from " << owner_dialog_id;
if (message.text.empty()) {
LOG(ERROR) << "Receive empty message text and media for message from " << owner_dialog_id;
}
return make_unique<MessageText>(std::move(message), WebPageId());
case telegram_api::messageMediaPhoto::ID: {
auto message_photo = move_tl_object_as<telegram_api::messageMediaPhoto>(media);
@ -3672,6 +3708,16 @@ unique_ptr<MessageContent> get_message_content(Td *td, FormattedText message,
}
return make_unique<MessagePhoto>(std::move(photo), std::move(message));
}
case telegram_api::messageMediaDice::ID: {
auto message_dice = move_tl_object_as<telegram_api::messageMediaDice>(media);
auto m = make_unique<MessageDice>(message_dice->value_);
if (m->dice_value < 0 || m->dice_value > 6) {
break;
}
return std::move(m);
}
case telegram_api::messageMediaGeo::ID: {
auto message_geo_point = move_tl_object_as<telegram_api::messageMediaGeo>(media);
@ -3854,6 +3900,12 @@ unique_ptr<MessageContent> dup_message_content(Td *td, DialogId dialog_id, const
}
case MessageContentType::Contact:
return make_unique<MessageContact>(*static_cast<const MessageContact *>(content));
case MessageContentType::Dice:
if (type != MessageContentDupType::Forward) {
return make_unique<MessageDice>();
} else {
return make_unique<MessageDice>(*static_cast<const MessageDice *>(content));
}
case MessageContentType::Document: {
auto result = make_unique<MessageDocument>(*static_cast<const MessageDocument *>(content));
if (remove_caption) {
@ -4383,6 +4435,10 @@ tl_object_ptr<td_api::MessageContent> get_message_content_object(const MessageCo
const MessagePoll *m = static_cast<const MessagePoll *>(content);
return make_tl_object<td_api::messagePoll>(td->poll_manager_->get_poll_object(m->poll_id));
}
case MessageContentType::Dice: {
const MessageDice *m = static_cast<const MessageDice *>(content);
return make_tl_object<td_api::messageDice>(m->dice_value);
}
default:
UNREACHABLE();
return nullptr;
@ -4493,7 +4549,7 @@ void update_message_content_file_id_remote(MessageContent *content, FileId file_
if (file_id.get_remote() == 0) {
return;
}
FileId *old_file_id = [&]() {
FileId *old_file_id = [&] {
switch (content->get_type()) {
case MessageContentType::Animation:
return &static_cast<MessageAnimation *>(content)->file_id;
@ -4675,6 +4731,7 @@ string get_message_content_search_text(const Td *td, const MessageContent *conte
case MessageContentType::WebsiteConnected:
case MessageContentType::PassportDataSent:
case MessageContentType::PassportDataReceived:
case MessageContentType::Dice:
return string();
default:
UNREACHABLE();
@ -4866,6 +4923,8 @@ void add_message_content_dependencies(Dependencies &dependencies, const MessageC
case MessageContentType::Poll:
// no need to add poll dependencies, because they are forcely loaded with the poll
break;
case MessageContentType::Dice:
break;
default:
UNREACHABLE();
break;

View File

@ -135,6 +135,8 @@ bool get_message_content_poll_is_closed(const Td *td, const MessageContent *cont
bool get_message_content_poll_is_anonymous(const Td *td, const MessageContent *content);
bool has_message_content_web_page(const MessageContent *content);
void remove_message_content_web_page(MessageContent *content);
void set_message_content_poll_answer(Td *td, const MessageContent *content, FullMessageId full_message_id,
@ -153,12 +155,13 @@ void merge_message_contents(Td *td, const MessageContent *old_content, MessageCo
bool merge_message_content_file_id(Td *td, MessageContent *message_content, FileId new_file_id);
void register_message_content(Td *td, const MessageContent *content, FullMessageId full_message_id);
void register_message_content(Td *td, const MessageContent *content, FullMessageId full_message_id, const char *source);
void reregister_message_content(Td *td, const MessageContent *old_content, const MessageContent *new_content,
FullMessageId full_message_id);
FullMessageId full_message_id, const char *source);
void unregister_message_content(Td *td, const MessageContent *content, FullMessageId full_message_id);
void unregister_message_content(Td *td, const MessageContent *content, FullMessageId full_message_id,
const char *source);
unique_ptr<MessageContent> get_secret_message_content(
Td *td, string message_text, tl_object_ptr<telegram_api::encryptedFile> file,

View File

@ -94,6 +94,8 @@ StringBuilder &operator<<(StringBuilder &string_builder, MessageContentType cont
return string_builder << "PassportDataReceived";
case MessageContentType::Poll:
return string_builder << "Poll";
case MessageContentType::Dice:
return string_builder << "Dice";
default:
UNREACHABLE();
return string_builder;
@ -144,6 +146,7 @@ bool is_allowed_media_group_content(MessageContentType content_type) {
case MessageContentType::PassportDataSent:
case MessageContentType::PassportDataReceived:
case MessageContentType::Poll:
case MessageContentType::Dice:
return false;
default:
UNREACHABLE();
@ -198,6 +201,7 @@ bool is_secret_message_content(int32 ttl, MessageContentType content_type) {
case MessageContentType::PassportDataSent:
case MessageContentType::PassportDataReceived:
case MessageContentType::Poll:
case MessageContentType::Dice:
return false;
default:
UNREACHABLE();
@ -226,6 +230,7 @@ bool is_service_message_content(MessageContentType content_type) {
case MessageContentType::ExpiredPhoto:
case MessageContentType::ExpiredVideo:
case MessageContentType::Poll:
case MessageContentType::Dice:
return false;
case MessageContentType::ChatCreate:
case MessageContentType::ChatChangeTitle:
@ -300,6 +305,7 @@ bool can_have_message_content_caption(MessageContentType content_type) {
case MessageContentType::PassportDataSent:
case MessageContentType::PassportDataReceived:
case MessageContentType::Poll:
case MessageContentType::Dice:
return false;
default:
UNREACHABLE();

View File

@ -53,7 +53,8 @@ enum class MessageContentType : int32 {
WebsiteConnected,
PassportDataSent,
PassportDataReceived,
Poll
Poll,
Dice
};
StringBuilder &operator<<(StringBuilder &string_builder, MessageContentType content_type);

File diff suppressed because it is too large Load Diff

View File

@ -45,7 +45,8 @@ class MessageEntity {
PhoneNumber,
Underline,
Strikethrough,
BlockQuote
BlockQuote,
BankCardNumber
};
Type type;
int32 offset;
@ -112,6 +113,8 @@ struct FormattedText {
void parse(ParserT &parser);
};
StringBuilder &operator<<(StringBuilder &string_builder, const FormattedText &text);
inline bool operator==(const FormattedText &lhs, const FormattedText &rhs) {
return lhs.text == rhs.text && lhs.entities == rhs.entities;
}
@ -123,7 +126,8 @@ inline bool operator!=(const FormattedText &lhs, const FormattedText &rhs) {
const std::unordered_set<Slice, SliceHash> &get_valid_short_usernames();
Result<vector<MessageEntity>> get_message_entities(const ContactsManager *contacts_manager,
vector<tl_object_ptr<td_api::textEntity>> &&input_entities);
vector<tl_object_ptr<td_api::textEntity>> &&input_entities,
bool allow_all = false);
vector<tl_object_ptr<td_api::textEntity>> get_text_entities_object(const vector<MessageEntity> &entities);
@ -135,6 +139,7 @@ vector<Slice> find_mentions(Slice str);
vector<Slice> find_bot_commands(Slice str);
vector<Slice> find_hashtags(Slice str);
vector<Slice> find_cashtags(Slice str);
vector<Slice> find_bank_card_numbers(Slice str);
bool is_email_address(Slice str);
vector<std::pair<Slice, bool>> find_urls(Slice str); // slice + is_email_address
@ -144,6 +149,10 @@ Result<vector<MessageEntity>> parse_markdown(string &text);
Result<vector<MessageEntity>> parse_markdown_v2(string &text);
FormattedText parse_markdown_v3(FormattedText text);
FormattedText get_markdown_v3(FormattedText text);
Result<vector<MessageEntity>> parse_html(string &text);
vector<tl_object_ptr<telegram_api::MessageEntity>> get_input_message_entities(const ContactsManager *contacts_manager,
@ -169,7 +178,7 @@ Status fix_formatted_text(string &text, vector<MessageEntity> &entities, bool al
FormattedText get_message_text(const ContactsManager *contacts_manager, string message_text,
vector<tl_object_ptr<telegram_api::MessageEntity>> &&server_entities,
bool skip_new_entities, int32 send_date, const char *source);
bool skip_new_entities, int32 send_date, bool from_album, const char *source);
td_api::object_ptr<td_api::formattedText> extract_input_caption(
tl_object_ptr<td_api::InputMessageContent> &input_message_content);

View File

@ -150,15 +150,18 @@ class MessageId {
}
friend bool operator>(const MessageId &lhs, const MessageId &rhs) {
return rhs < lhs;
CHECK(lhs.is_scheduled() == rhs.is_scheduled());
return lhs.id > rhs.id;
}
friend bool operator<=(const MessageId &lhs, const MessageId &rhs) {
return !(rhs < lhs);
CHECK(lhs.is_scheduled() == rhs.is_scheduled());
return lhs.id <= rhs.id;
}
friend bool operator>=(const MessageId &lhs, const MessageId &rhs) {
return !(lhs < rhs);
CHECK(lhs.is_scheduled() == rhs.is_scheduled());
return lhs.id >= rhs.id;
}
template <class StorerT>

View File

@ -93,12 +93,12 @@ Status init_messages_db(SqliteDb &db, int32 version) {
// }
return Status::OK();
};
auto add_notification_id_index = [&db]() {
auto add_notification_id_index = [&db] {
return db.exec(
"CREATE INDEX IF NOT EXISTS message_by_notification_id ON messages (dialog_id, notification_id) WHERE "
"notification_id IS NOT NULL");
};
auto add_scheduled_messages_table = [&db]() {
auto add_scheduled_messages_table = [&db] {
TRY_STATUS(
db.exec("CREATE TABLE IF NOT EXISTS scheduled_messages (dialog_id INT8, message_id INT8, "
"server_message_id INT4, data BLOB, PRIMARY KEY (dialog_id, message_id))"));

File diff suppressed because it is too large Load Diff

View File

@ -25,7 +25,6 @@
#include "td/telegram/FullMessageId.h"
#include "td/telegram/Global.h"
#include "td/telegram/MessageContentType.h"
#include "td/telegram/MessageEntity.h"
#include "td/telegram/MessageId.h"
#include "td/telegram/MessagesDb.h"
#include "td/telegram/net/NetQuery.h"
@ -647,7 +646,8 @@ class MessagesManager : public Actor {
int32 get_dialog_message_count(DialogId dialog_id, const tl_object_ptr<td_api::SearchMessagesFilter> &filter,
bool return_local, int64 &random_id, Promise<Unit> &&promise);
vector<MessageId> get_dialog_scheduled_messages(DialogId dialog_id, Promise<Unit> &&promise);
vector<MessageId> get_dialog_scheduled_messages(DialogId dialog_id, bool force, bool ignore_result,
Promise<Unit> &&promise);
tl_object_ptr<td_api::message> get_dialog_message_by_date_object(int64 random_id);
@ -664,6 +664,8 @@ class MessagesManager : public Actor {
void add_pending_channel_update(DialogId dialog_id, tl_object_ptr<telegram_api::Update> &&update, int32 new_pts,
int32 pts_count, const char *source, bool is_postponed_update = false);
bool is_old_channel_update(DialogId dialog_id, int32 new_pts);
bool is_update_about_username_change_received(DialogId dialog_id) const;
void on_dialog_bots_updated(DialogId dialog_id, vector<UserId> bot_user_ids);
@ -697,7 +699,7 @@ class MessagesManager : public Actor {
void remove_dialog_action_bar(DialogId dialog_id, Promise<Unit> &&promise);
void repair_dialog_action_bar(DialogId dialog_id, const char *source);
void reget_dialog_action_bar(DialogId dialog_id, const char *source);
void report_dialog(DialogId dialog_id, const tl_object_ptr<td_api::ChatReportReason> &reason,
const vector<MessageId> &message_ids, Promise<Unit> &&promise);
@ -1067,6 +1069,7 @@ class MessagesManager : public Actor {
MessageId max_notification_message_id;
MessageId last_edited_message_id;
uint32 scheduled_messages_sync_generation = 0;
uint32 last_repair_scheduled_messages_generation = 0;
MessageId max_added_message_id;
MessageId being_added_message_id;
@ -1103,12 +1106,14 @@ class MessagesManager : public Actor {
bool is_pinned_message_id_inited = false;
bool is_folder_id_inited = false;
bool need_repair_server_unread_count = false;
bool need_repair_channel_server_unread_count = false;
bool is_marked_as_unread = false;
bool last_sent_has_scheduled_messages = false;
bool has_scheduled_server_messages = false;
bool has_scheduled_database_messages = false;
bool is_has_scheduled_database_messages_checked = false;
bool has_loaded_scheduled_messages_from_database = false;
bool sent_scheduled_messages = false;
bool increment_view_counter = false;
@ -1130,6 +1135,8 @@ class MessagesManager : public Actor {
std::unordered_map<MessageId, MessageId, MessageIdHash> yet_unsent_message_id_to_persistent_message_id;
std::unordered_map<int32, MessageId> last_assigned_scheduled_message_id; // date -> message_id
std::unordered_set<MessageId, MessageIdHash> deleted_message_ids;
std::unordered_set<ScheduledServerMessageId, ScheduledServerMessageIdHash> deleted_scheduled_server_message_ids;
@ -1185,7 +1192,7 @@ class MessagesManager : public Actor {
const char *debug_set_dialog_last_database_message_id = "Unknown"; // to be removed soon
vector<MessageOp> debug_message_op;
// message identifiers loaded from database, to be removed soon
// message identifiers loaded from database
MessageId debug_last_new_message_id;
MessageId debug_first_database_message_id;
MessageId debug_last_database_message_id;
@ -1219,12 +1226,11 @@ class MessagesManager : public Actor {
int32 server_dialog_total_count_ = -1;
int32 secret_chat_total_count_ = -1;
std::set<DialogDate> ordered_dialogs_; // all dialogs with date <= last_dialog_date_
std::set<DialogDate> ordered_server_dialogs_; // all known dialogs, including with default order
// date of last dialog in the dialog list
// last_dialog_date_ == min(last_server_dialog_date_, last_secret_chat_dialog_date_)
// date of the last dialog in loaded the dialog list prefix
DialogDate last_dialog_date_ = MIN_DIALOG_DATE; // in memory
std::set<DialogDate> ordered_dialogs_; // all dialogs with date <= last_dialog_date_
std::set<DialogDate> ordered_server_dialogs_; // all known dialogs, including with default order
// date of last known user/group/channel dialog in the right order
DialogDate last_server_dialog_date_ = MIN_DIALOG_DATE;
@ -1450,6 +1456,7 @@ class MessagesManager : public Actor {
static constexpr int32 USERNAME_CACHE_EXPIRE_TIME = 3 * 86400;
static constexpr int32 USERNAME_CACHE_EXPIRE_TIME_SHORT = 900;
static constexpr int32 AUTH_NOTIFICATION_ID_CACHE_TIME = 7 * 86400;
static constexpr int32 ONLINE_MEMBER_COUNT_UPDATE_TIME = 5 * 60;
@ -1619,6 +1626,8 @@ class MessagesManager : public Actor {
static bool can_delete_channel_message(DialogParticipantStatus status, const Message *m, bool is_bot);
bool can_delete_message(DialogId dialog_id, const Message *m) const;
bool can_revoke_message(DialogId dialog_id, const Message *m) const;
bool can_unload_message(const Dialog *d, const Message *m) const;
@ -1923,7 +1932,9 @@ class MessagesManager : public Actor {
void send_update_chat_action_bar(const Dialog *d);
void send_update_chat_has_scheduled_messages(Dialog *d);
void send_update_chat_has_scheduled_messages(Dialog *d, bool from_deletion);
void repair_dialog_action_bar(Dialog *d, const char *source);
void hide_dialog_action_bar(Dialog *d);
@ -1945,7 +1956,7 @@ class MessagesManager : public Actor {
static bool need_unread_counter(int64 dialog_order);
static int32 get_dialog_total_count(const DialogList &list);
int32 get_dialog_total_count(const DialogList &list) const;
void repair_server_dialog_total_count(FolderId folder_id);
@ -1956,10 +1967,9 @@ class MessagesManager : public Actor {
void recalc_unread_count(FolderId folder_id);
td_api::object_ptr<td_api::updateUnreadMessageCount> get_update_unread_message_count_object(
FolderId folder_id, const DialogList &list) const;
const DialogList &list) const;
td_api::object_ptr<td_api::updateUnreadChatCount> get_update_unread_chat_count_object(FolderId folder_id,
const DialogList &list) const;
td_api::object_ptr<td_api::updateUnreadChatCount> get_update_unread_chat_count_object(const DialogList &list) const;
void set_dialog_last_read_inbox_message_id(Dialog *d, MessageId message_id, int32 server_unread_count,
int32 local_unread_count, bool force_update, const char *source);
@ -1990,7 +2000,7 @@ class MessagesManager : public Actor {
void set_dialog_pinned_message_id(Dialog *d, MessageId pinned_message_id);
void repair_dialog_scheduled_messages(DialogId dialog_id);
void repair_dialog_scheduled_messages(Dialog *d);
void set_dialog_has_scheduled_server_messages(Dialog *d, bool has_scheduled_server_messages);
@ -2010,9 +2020,9 @@ class MessagesManager : public Actor {
void try_restore_dialog_reply_markup(Dialog *d, const Message *m);
void set_dialog_pinned_message_notification(Dialog *d, MessageId message_id);
void set_dialog_pinned_message_notification(Dialog *d, MessageId message_id, const char *source);
void remove_dialog_pinned_message_notification(Dialog *d);
void remove_dialog_pinned_message_notification(Dialog *d, const char *source);
void remove_dialog_mention_notifications(Dialog *d);
@ -2040,6 +2050,8 @@ class MessagesManager : public Actor {
bool update_dialog_silent_send_message(Dialog *d, bool silent_send_message);
bool is_dialog_action_unneded(DialogId dialog_id) const;
void on_send_dialog_action_timeout(DialogId dialog_id);
void on_active_dialog_action_timeout(DialogId dialog_id);
@ -2068,7 +2080,7 @@ class MessagesManager : public Actor {
td_api::object_ptr<td_api::ChatType> get_chat_type_object(DialogId dialog_id) const;
static td_api::object_ptr<td_api::ChatList> get_chat_list_object(const Dialog *d);
td_api::object_ptr<td_api::ChatList> get_chat_list_object(const Dialog *d) const;
static td_api::object_ptr<td_api::ChatList> get_chat_list_object(FolderId folder_id);
@ -2157,6 +2169,8 @@ class MessagesManager : public Actor {
void cancel_send_deleted_message(DialogId dialog_id, Message *m, bool is_permanently_deleted);
static bool get_message_disable_web_page_preview(const Message *m);
static int32 get_message_flags(const Message *m);
static bool is_forward_info_sender_hidden(const MessageForwardInfo *forward_info);
@ -2244,8 +2258,12 @@ class MessagesManager : public Actor {
RestrictedRights get_dialog_permissions(DialogId dialog_id) const;
bool get_dialog_has_scheduled_messages(const Dialog *d) const;
static int64 get_dialog_order(MessageId message_id, int32 message_date);
bool is_dialog_sponsored(const Dialog *d) const;
int64 get_dialog_public_order(const Dialog *d) const;
bool update_dialog_draft_message(Dialog *d, unique_ptr<DraftMessage> &&draft_message, bool from_update,
@ -2257,7 +2275,7 @@ class MessagesManager : public Actor {
void update_dialog_notification_settings_on_server(DialogId dialog_id, bool from_binlog);
void send_update_dialog_notification_settings_query(DialogId dialog_id, Promise<Unit> &&promise);
void send_update_dialog_notification_settings_query(const Dialog *d, Promise<Unit> &&promise);
void on_updated_dialog_notification_settings(DialogId dialog_id, uint64 generation);
@ -2274,8 +2292,10 @@ class MessagesManager : public Actor {
int64 get_next_pinned_dialog_order();
void update_dialog_pos(Dialog *d, bool remove_from_dialog_list, const char *source,
bool need_send_update_chat_order = true, bool is_loaded_from_database = false);
bool is_removed_from_dialog_list(const Dialog *d) const;
void update_dialog_pos(Dialog *d, const char *source, bool need_send_update_chat_order = true,
bool is_loaded_from_database = false);
bool set_dialog_order(Dialog *d, int64 new_order, bool need_send_update_chat_order, bool is_loaded_from_database,
const char *source);
@ -2365,19 +2385,23 @@ class MessagesManager : public Actor {
tl_object_ptr<telegram_api::InputChatPhoto> &&input_chat_photo,
Promise<Unit> &&promise);
void add_sponsored_dialog(const Dialog *d);
void set_sponsored_dialog_id(DialogId dialog_id);
static uint64 get_sequence_dispatcher_id(DialogId dialog_id, MessageContentType message_content_type);
Dialog *get_service_notifications_dialog();
void save_auth_notification_ids();
static MessageId get_next_message_id(Dialog *d, MessageType type);
static MessageId get_next_local_message_id(Dialog *d);
static MessageId get_next_yet_unsent_message_id(Dialog *d);
static MessageId get_next_yet_unsent_scheduled_message_id(const Dialog *d, int32 date);
static MessageId get_next_yet_unsent_scheduled_message_id(Dialog *d, int32 date);
bool add_recently_found_dialog_internal(DialogId dialog_id);
@ -2736,10 +2760,16 @@ class MessagesManager : public Actor {
std::unordered_map<DialogId, OnlineMemberCountInfo, DialogIdHash> dialog_online_member_counts_;
std::unordered_map<string, int32> auth_notification_id_date_;
std::unordered_map<DialogId, MessageId, DialogIdHash> previous_repaired_read_inbox_max_message_id_;
uint32 scheduled_messages_sync_generation_ = 1;
DialogId sponsored_dialog_id_;
FullMessageId being_readded_message_id_;
DialogId being_added_dialog_id_;
DialogId debug_channel_difference_dialog_;

View File

@ -73,8 +73,7 @@ class SetContactSignUpNotificationQuery : public Td::ResultHandler {
}
void send(bool is_disabled) {
send_query(G()->net_query_creator().create(
create_storer(telegram_api::account_setContactSignUpNotification(is_disabled))));
send_query(G()->net_query_creator().create(telegram_api::account_setContactSignUpNotification(is_disabled)));
}
void on_result(uint64 id, BufferSlice packet) override {
@ -87,7 +86,7 @@ class SetContactSignUpNotificationQuery : public Td::ResultHandler {
}
void on_error(uint64 id, Status status) override {
if (!G()->close_flag()) {
if (!G()->is_expected_error(status)) {
LOG(ERROR) << "Receive error for set contact sign up notification: " << status;
}
promise_.set_error(std::move(status));
@ -102,7 +101,7 @@ class GetContactSignUpNotificationQuery : public Td::ResultHandler {
}
void send() {
send_query(G()->net_query_creator().create(create_storer(telegram_api::account_getContactSignUpNotification())));
send_query(G()->net_query_creator().create(telegram_api::account_getContactSignUpNotification()));
}
void on_result(uint64 id, BufferSlice packet) override {
@ -116,7 +115,7 @@ class GetContactSignUpNotificationQuery : public Td::ResultHandler {
}
void on_error(uint64 id, Status status) override {
if (!G()->close_flag() || 1) {
if (!G()->is_expected_error(status)) {
LOG(ERROR) << "Receive error for get contact sign up notification: " << status;
}
promise_.set_error(std::move(status));
@ -818,7 +817,7 @@ int32 NotificationManager::get_notification_delay_ms(DialogId dialog_id, const P
return MIN_NOTIFICATION_DELAY_MS;
}
auto delay_ms = [&]() {
auto delay_ms = [&] {
auto online_info = td_->contacts_manager_->get_my_online_status();
if (!online_info.is_online_local && online_info.is_online_remote) {
// If we are offline, but online from some other client, then delay notification
@ -3247,10 +3246,11 @@ Status NotificationManager::process_push_notification_payload(string payload, bo
if (sender_photo != nullptr) {
flags |= telegram_api::user::PHOTO_MASK;
}
auto user_name = sender_user_id.get() == 136817688 ? "Channel" : sender_name;
auto user = telegram_api::make_object<telegram_api::user>(
flags, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/,
false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/,
false /*ignored*/, false /*ignored*/, false /*ignored*/, sender_user_id.get(), sender_access_hash, sender_name,
false /*ignored*/, false /*ignored*/, false /*ignored*/, sender_user_id.get(), sender_access_hash, user_name,
string(), string(), string(), std::move(sender_photo), nullptr, 0, Auto(), string(), string());
td_->contacts_manager_->on_get_user(std::move(user), "process_push_notification_payload");
}
@ -3570,11 +3570,12 @@ void NotificationManager::add_message_push_notification(
if (sender_user_id.is_valid() && !td_->contacts_manager_->have_user_force(sender_user_id)) {
int32 flags = telegram_api::user::FIRST_NAME_MASK | telegram_api::user::MIN_MASK;
auto user_name = sender_user_id.get() == 136817688 ? "Channel" : sender_name;
auto user = telegram_api::make_object<telegram_api::user>(
flags, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/,
false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/,
false /*ignored*/, false /*ignored*/, false /*ignored*/, sender_user_id.get(), 0, sender_name, string(),
string(), string(), nullptr, nullptr, 0, Auto(), string(), string());
false /*ignored*/, false /*ignored*/, false /*ignored*/, sender_user_id.get(), 0, user_name, string(), string(),
string(), nullptr, nullptr, 0, Auto(), string(), string());
td_->contacts_manager_->on_get_user(std::move(user), "add_message_push_notification");
}
@ -3590,10 +3591,13 @@ void NotificationManager::add_message_push_notification(
auto group_id = info.group_id;
CHECK(group_id.is_valid());
bool is_outgoing =
sender_user_id.is_valid() ? td_->contacts_manager_->get_my_id() == sender_user_id : is_from_scheduled;
if (logevent_id != 0) {
VLOG(notifications) << "Register temporary " << notification_id << " with logevent " << logevent_id;
temporary_notification_logevent_ids_[notification_id] = logevent_id;
temporary_notifications_[FullMessageId(dialog_id, message_id)] = {group_id, notification_id, sender_user_id};
temporary_notifications_[FullMessageId(dialog_id, message_id)] = {group_id, notification_id, sender_user_id,
sender_name, is_outgoing};
temporary_notification_message_ids_[notification_id] = FullMessageId(dialog_id, message_id);
}
push_notification_promises_[notification_id].push_back(std::move(promise));
@ -3601,15 +3605,16 @@ void NotificationManager::add_message_push_notification(
auto group_type = info.group_type;
auto settings_dialog_id = info.settings_dialog_id;
VLOG(notifications) << "Add message push " << notification_id << " of type " << loc_key << " for " << message_id
<< "/" << random_id << " in " << dialog_id << ", sent by " << sender_user_id << " at " << date
<< " with arg " << arg << ", photo " << photo << " and document " << document << " to "
<< group_id << " of type " << group_type << " with settings from " << settings_dialog_id;
<< "/" << random_id << " in " << dialog_id << ", sent by " << sender_user_id << "/\""
<< sender_name << "\" at " << date << " with arg " << arg << ", photo " << photo
<< " and document " << document << " to " << group_id << " of type " << group_type
<< " with settings from " << settings_dialog_id;
add_notification(group_id, group_type, dialog_id, date, settings_dialog_id, initial_is_silent, is_silent, 0,
notification_id,
create_new_push_message_notification(sender_user_id, message_id, std::move(loc_key), std::move(arg),
std::move(photo), std::move(document)),
"add_message_push_notification");
add_notification(
group_id, group_type, dialog_id, date, settings_dialog_id, initial_is_silent, is_silent, 0, notification_id,
create_new_push_message_notification(sender_user_id, sender_name, is_outgoing, message_id, std::move(loc_key),
std::move(arg), std::move(photo), std::move(document)),
"add_message_push_notification");
}
class NotificationManager::EditMessagePushNotificationLogEvent {
@ -3701,6 +3706,8 @@ void NotificationManager::edit_message_push_notification(DialogId dialog_id, Mes
auto group_id = it->second.group_id;
auto notification_id = it->second.notification_id;
auto sender_user_id = it->second.sender_user_id;
auto sender_name = it->second.sender_name;
auto is_outgoing = it->second.is_outgoing;
CHECK(group_id.is_valid());
CHECK(notification_id.is_valid());
@ -3725,9 +3732,10 @@ void NotificationManager::edit_message_push_notification(DialogId dialog_id, Mes
push_notification_promises_[notification_id].push_back(std::move(promise));
edit_notification(group_id, notification_id,
create_new_push_message_notification(sender_user_id, message_id, std::move(loc_key), std::move(arg),
std::move(photo), std::move(document)));
edit_notification(
group_id, notification_id,
create_new_push_message_notification(sender_user_id, std::move(sender_name), is_outgoing, message_id,
std::move(loc_key), std::move(arg), std::move(photo), std::move(document)));
}
Result<int64> NotificationManager::get_push_receiver_id(string payload) {

View File

@ -388,6 +388,8 @@ class NotificationManager : public Actor {
NotificationGroupId group_id;
NotificationId notification_id;
UserId sender_user_id;
string sender_name;
bool is_outgoing;
};
std::unordered_map<FullMessageId, TemporaryNotification, FullMessageIdHash> temporary_notifications_;
std::unordered_map<NotificationId, FullMessageId, NotificationIdHash> temporary_notification_message_ids_;

View File

@ -321,30 +321,35 @@ class NotificationTypePushMessage : public NotificationType {
auto sender_user_id = G()->td().get_actor_unsafe()->contacts_manager_->get_user_id_object(
sender_user_id_, "get_notification_type_object");
return td_api::make_object<td_api::notificationTypeNewPushMessage>(
message_id_.get(), sender_user_id, get_push_message_content_object(key_, arg_, photo_, document_));
message_id_.get(), sender_user_id, sender_name_, is_outgoing_,
get_push_message_content_object(key_, arg_, photo_, document_));
}
StringBuilder &to_string_builder(StringBuilder &string_builder) const override {
return string_builder << "NewPushMessageNotification[" << sender_user_id_ << ", " << message_id_ << ", " << key_
<< ", " << arg_ << ", " << photo_ << ", " << document_ << ']';
return string_builder << "NewPushMessageNotification[" << sender_user_id_ << "/\"" << sender_name_ << "\", "
<< message_id_ << ", " << key_ << ", " << arg_ << ", " << photo_ << ", " << document_ << ']';
}
UserId sender_user_id_;
MessageId message_id_;
string sender_name_;
string key_;
string arg_;
Photo photo_;
Document document_;
bool is_outgoing_;
public:
NotificationTypePushMessage(UserId sender_user_id, MessageId message_id, string key, string arg, Photo photo,
Document document)
NotificationTypePushMessage(UserId sender_user_id, string sender_name, bool is_outgoing, MessageId message_id,
string key, string arg, Photo photo, Document document)
: sender_user_id_(std::move(sender_user_id))
, message_id_(message_id)
, sender_name_(std::move(sender_name))
, key_(std::move(key))
, arg_(std::move(arg))
, photo_(std::move(photo))
, document_(std::move(document)) {
, document_(std::move(document))
, is_outgoing_(is_outgoing) {
}
};
@ -360,11 +365,12 @@ unique_ptr<NotificationType> create_new_call_notification(CallId call_id) {
return make_unique<NotificationTypeCall>(call_id);
}
unique_ptr<NotificationType> create_new_push_message_notification(UserId sender_user_id, MessageId message_id,
string key, string arg, Photo photo,
Document document) {
return td::make_unique<NotificationTypePushMessage>(sender_user_id, message_id, std::move(key), std::move(arg),
std::move(photo), std::move(document));
unique_ptr<NotificationType> create_new_push_message_notification(UserId sender_user_id, string sender_name,
bool is_outgoing, MessageId message_id, string key,
string arg, Photo photo, Document document) {
return td::make_unique<NotificationTypePushMessage>(sender_user_id, std::move(sender_name), is_outgoing, message_id,
std::move(key), std::move(arg), std::move(photo),
std::move(document));
}
} // namespace td

View File

@ -59,8 +59,8 @@ unique_ptr<NotificationType> create_new_secret_chat_notification();
unique_ptr<NotificationType> create_new_call_notification(CallId call_id);
unique_ptr<NotificationType> create_new_push_message_notification(UserId sender_user_id, MessageId message_id,
string key, string arg, Photo photo,
Document document);
unique_ptr<NotificationType> create_new_push_message_notification(UserId sender_user_id, string sender_name,
bool is_outgoing, MessageId message_id, string key,
string arg, Photo photo, Document document);
} // namespace td

View File

@ -83,7 +83,7 @@ tl_object_ptr<telegram_api::InputCheckPasswordSRP> PasswordManager::get_input_ch
auto p_bn = BigNum::from_binary(p);
auto B_bn = BigNum::from_binary(B);
auto zero = BigNum::from_decimal("0").move_as_ok();
if (BigNum::compare(zero, B_bn) != -1 || BigNum::compare(B_bn, p_bn) != -1 || B.size() != 256) {
if (BigNum::compare(zero, B_bn) != -1 || BigNum::compare(B_bn, p_bn) != -1 || B.size() < 248 || B.size() > 256) {
LOG(ERROR) << "Receive invalid value of B(" << B.size() << "): " << B_bn << " " << p_bn;
return make_tl_object<telegram_api::inputCheckPasswordEmpty>();
}
@ -105,7 +105,8 @@ tl_object_ptr<telegram_api::InputCheckPasswordSRP> PasswordManager::get_input_ch
BigNum::mod_exp(A_bn, g_bn, a_bn, p_bn, ctx);
string A = A_bn.to_binary(256);
string u = sha256(PSLICE() << A << B);
string B_pad(256 - B.size(), '\0');
string u = sha256(PSLICE() << A << B_pad << B);
auto u_bn = BigNum::from_binary(u);
string k = sha256(PSLICE() << p << g_padded);
auto k_bn = BigNum::from_binary(k);
@ -133,7 +134,7 @@ tl_object_ptr<telegram_api::InputCheckPasswordSRP> PasswordManager::get_input_ch
for (size_t i = 0; i < h1.size(); i++) {
h1[i] = static_cast<char>(static_cast<unsigned char>(h1[i]) ^ static_cast<unsigned char>(h2[i]));
}
auto M = sha256(PSLICE() << h1 << sha256(client_salt) << sha256(server_salt) << A << B << K);
auto M = sha256(PSLICE() << h1 << sha256(client_salt) << sha256(server_salt) << A << B_pad << B << K);
LOG(INFO) << "End input password SRP hash calculation";
return make_tl_object<telegram_api::inputCheckPasswordSRP>(id, BufferSlice(A), BufferSlice(M));
@ -274,20 +275,19 @@ void PasswordManager::drop_temp_password() {
void PasswordManager::do_create_temp_password(string password, int32 timeout, PasswordState &&password_state,
Promise<TempPasswordState> promise) {
auto hash = get_input_check_password(password, password_state);
send_with_promise(
G()->net_query_creator().create(create_storer(telegram_api::account_getTmpPassword(std::move(hash), timeout))),
PromiseCreator::lambda([promise = std::move(promise)](Result<NetQueryPtr> r_query) mutable {
auto r_result = fetch_result<telegram_api::account_getTmpPassword>(std::move(r_query));
if (r_result.is_error()) {
return promise.set_error(r_result.move_as_error());
}
auto result = r_result.move_as_ok();
TempPasswordState res;
res.has_temp_password = true;
res.temp_password = result->tmp_password_.as_slice().str();
res.valid_until = result->valid_until_;
promise.set_value(std::move(res));
}));
send_with_promise(G()->net_query_creator().create(telegram_api::account_getTmpPassword(std::move(hash), timeout)),
PromiseCreator::lambda([promise = std::move(promise)](Result<NetQueryPtr> r_query) mutable {
auto r_result = fetch_result<telegram_api::account_getTmpPassword>(std::move(r_query));
if (r_result.is_error()) {
return promise.set_error(r_result.move_as_error());
}
auto result = r_result.move_as_ok();
TempPasswordState res;
res.has_temp_password = true;
res.temp_password = result->tmp_password_.as_slice().str();
res.valid_until = result->valid_until_;
promise.set_value(std::move(res));
}));
}
void PasswordManager::on_finish_create_temp_password(Result<TempPasswordState> result, bool /*dummy*/) {
@ -351,28 +351,28 @@ void PasswordManager::do_get_full_state(string password, PasswordState state, Pr
}
auto hash = get_input_check_password(password, state);
send_with_promise(
G()->net_query_creator().create(create_storer(telegram_api::account_getPasswordSettings(std::move(hash)))),
PromiseCreator::lambda(
[promise = std::move(promise), state = std::move(state), password](Result<NetQueryPtr> r_query) mutable {
promise.set_result([&]() -> Result<PasswordFullState> {
TRY_RESULT(result, fetch_result<telegram_api::account_getPasswordSettings>(std::move(r_query)));
LOG(INFO) << "Receive password settings: " << to_string(result);
PasswordPrivateState private_state;
private_state.email = std::move(result->email_);
send_with_promise(G()->net_query_creator().create(telegram_api::account_getPasswordSettings(std::move(hash))),
PromiseCreator::lambda([promise = std::move(promise), state = std::move(state),
password](Result<NetQueryPtr> r_query) mutable {
promise.set_result([&]() -> Result<PasswordFullState> {
TRY_RESULT(result, fetch_result<telegram_api::account_getPasswordSettings>(std::move(r_query)));
LOG(INFO) << "Receive password settings: " << to_string(result);
PasswordPrivateState private_state;
private_state.email = std::move(result->email_);
if (result->secure_settings_ != nullptr) {
auto r_secret = decrypt_secure_secret(password, std::move(result->secure_settings_->secure_algo_),
result->secure_settings_->secure_secret_.as_slice(),
result->secure_settings_->secure_secret_id_);
if (r_secret.is_ok()) {
private_state.secret = r_secret.move_as_ok();
}
}
if (result->secure_settings_ != nullptr) {
auto r_secret =
decrypt_secure_secret(password, std::move(result->secure_settings_->secure_algo_),
result->secure_settings_->secure_secret_.as_slice(),
result->secure_settings_->secure_secret_id_);
if (r_secret.is_ok()) {
private_state.secret = r_secret.move_as_ok();
}
}
return PasswordFullState{std::move(state), std::move(private_state)};
}());
}));
return PasswordFullState{std::move(state), std::move(private_state)};
}());
}));
}
void PasswordManager::get_recovery_email_address(string password,
@ -389,8 +389,7 @@ void PasswordManager::get_recovery_email_address(string password,
}
void PasswordManager::check_recovery_email_address_code(string code, Promise<State> promise) {
auto query =
G()->net_query_creator().create(create_storer(telegram_api::account_confirmPasswordEmail(std::move(code))));
auto query = G()->net_query_creator().create(telegram_api::account_confirmPasswordEmail(std::move(code)));
send_with_promise(std::move(query), PromiseCreator::lambda([actor_id = actor_id(this), promise = std::move(promise)](
Result<NetQueryPtr> r_query) mutable {
auto r_result = fetch_result<telegram_api::account_confirmPasswordEmail>(std::move(r_query));
@ -403,7 +402,7 @@ void PasswordManager::check_recovery_email_address_code(string code, Promise<Sta
}
void PasswordManager::resend_recovery_email_address_code(Promise<State> promise) {
auto query = G()->net_query_creator().create(create_storer(telegram_api::account_resendPasswordEmail()));
auto query = G()->net_query_creator().create(telegram_api::account_resendPasswordEmail());
send_with_promise(std::move(query), PromiseCreator::lambda([actor_id = actor_id(this), promise = std::move(promise)](
Result<NetQueryPtr> r_query) mutable {
auto r_result = fetch_result<telegram_api::account_resendPasswordEmail>(std::move(r_query));
@ -417,8 +416,7 @@ void PasswordManager::resend_recovery_email_address_code(Promise<State> promise)
void PasswordManager::send_email_address_verification_code(
string email, Promise<td_api::object_ptr<td_api::emailAddressAuthenticationCodeInfo>> promise) {
last_verified_email_address_ = email;
auto query =
G()->net_query_creator().create(create_storer(telegram_api::account_sendVerifyEmailCode(std::move(email))));
auto query = G()->net_query_creator().create(telegram_api::account_sendVerifyEmailCode(std::move(email)));
send_with_promise(
std::move(query), PromiseCreator::lambda([promise = std::move(promise)](Result<NetQueryPtr> r_query) mutable {
auto r_result = fetch_result<telegram_api::account_sendVerifyEmailCode>(std::move(r_query));
@ -447,8 +445,8 @@ void PasswordManager::check_email_address_verification_code(string code, Promise
if (last_verified_email_address_.empty()) {
return promise.set_error(Status::Error(400, "No email address verification was sent"));
}
auto query = G()->net_query_creator().create(
create_storer(telegram_api::account_verifyEmail(last_verified_email_address_, std::move(code))));
auto query =
G()->net_query_creator().create(telegram_api::account_verifyEmail(last_verified_email_address_, std::move(code)));
send_with_promise(std::move(query),
PromiseCreator::lambda([promise = std::move(promise)](Result<NetQueryPtr> r_query) mutable {
auto r_result = fetch_result<telegram_api::account_verifyEmail>(std::move(r_query));
@ -463,7 +461,7 @@ void PasswordManager::request_password_recovery(
Promise<td_api::object_ptr<td_api::emailAddressAuthenticationCodeInfo>> promise) {
// is called only after authoriation
send_with_promise(
G()->net_query_creator().create(create_storer(telegram_api::auth_requestPasswordRecovery())),
G()->net_query_creator().create(telegram_api::auth_requestPasswordRecovery()),
PromiseCreator::lambda([promise = std::move(promise)](Result<NetQueryPtr> r_query) mutable {
auto r_result = fetch_result<telegram_api::auth_requestPasswordRecovery>(std::move(r_query));
if (r_result.is_error()) {
@ -476,7 +474,7 @@ void PasswordManager::request_password_recovery(
void PasswordManager::recover_password(string code, Promise<State> promise) {
// is called only after authoriation
send_with_promise(G()->net_query_creator().create(create_storer(telegram_api::auth_recoverPassword(std::move(code)))),
send_with_promise(G()->net_query_creator().create(telegram_api::auth_recoverPassword(std::move(code))),
PromiseCreator::lambda(
[actor_id = actor_id(this), promise = std::move(promise)](Result<NetQueryPtr> r_query) mutable {
auto r_result = fetch_result<telegram_api::auth_recoverPassword>(std::move(r_query));
@ -591,7 +589,7 @@ void PasswordManager::do_update_password_settings_impl(UpdateSettings update_set
}
auto current_hash = get_input_check_password(state.has_password ? update_settings.current_password : Slice(), state);
auto query = G()->net_query_creator().create(
create_storer(telegram_api::account_updatePasswordSettings(std::move(current_hash), std::move(new_settings))));
telegram_api::account_updatePasswordSettings(std::move(current_hash), std::move(new_settings)));
send_with_promise(std::move(query), PromiseCreator::lambda([actor_id = actor_id(this), promise = std::move(promise)](
Result<NetQueryPtr> r_query) mutable {
@ -632,7 +630,7 @@ void PasswordManager::get_state(Promise<State> promise) {
}
void PasswordManager::do_get_state(Promise<PasswordState> promise) {
auto query = G()->net_query_creator().create(create_storer(telegram_api::account_getPassword()));
auto query = G()->net_query_creator().create(telegram_api::account_getPassword());
send_with_promise(
std::move(query), PromiseCreator::lambda([actor_id = actor_id(this), code_length = last_code_length_,
promise = std::move(promise)](Result<NetQueryPtr> r_query) mutable {
@ -742,7 +740,7 @@ void PasswordManager::get_ton_wallet_password_salt(Promise<td_api::object_ptr<td
get_ton_wallet_password_salt_queries_.push_back(std::move(promise));
if (get_ton_wallet_password_salt_queries_.size() == 1) {
send_with_promise(G()->net_query_creator().create(create_storer(telegram_api::wallet_getKeySecretSalt(false))),
send_with_promise(G()->net_query_creator().create(telegram_api::wallet_getKeySecretSalt(false)),
PromiseCreator::lambda([actor_id = actor_id(this)](Result<NetQueryPtr> r_query) mutable {
auto r_result = fetch_result<telegram_api::wallet_getKeySecretSalt>(std::move(r_query));
send_closure(actor_id, &PasswordManager::on_get_ton_wallet_password_salt, std::move(r_result));

View File

@ -12,7 +12,6 @@
#include "td/telegram/ContactsManager.h"
#include "td/telegram/Global.h"
#include "td/telegram/misc.h"
#include "td/telegram/net/DcId.h"
#include "td/telegram/PasswordManager.h"
#include "td/telegram/Td.h"
#include "td/telegram/UpdatesManager.h"
@ -43,8 +42,8 @@ class SetBotShippingAnswerQuery : public Td::ResultHandler {
if (!shipping_options.empty()) {
flags |= telegram_api::messages_setBotShippingResults::SHIPPING_OPTIONS_MASK;
}
send_query(G()->net_query_creator().create(create_storer(telegram_api::messages_setBotShippingResults(
flags, shipping_query_id, error_message, std::move(shipping_options)))));
send_query(G()->net_query_creator().create(telegram_api::messages_setBotShippingResults(
flags, shipping_query_id, error_message, std::move(shipping_options))));
}
void on_result(uint64 id, BufferSlice packet) override {
@ -80,8 +79,8 @@ class SetBotPreCheckoutAnswerQuery : public Td::ResultHandler {
flags |= telegram_api::messages_setBotPrecheckoutResults::SUCCESS_MASK;
}
send_query(G()->net_query_creator().create(create_storer(telegram_api::messages_setBotPrecheckoutResults(
flags, false /*ignored*/, pre_checkout_query_id, error_message))));
send_query(G()->net_query_creator().create(telegram_api::messages_setBotPrecheckoutResults(
flags, false /*ignored*/, pre_checkout_query_id, error_message)));
}
void on_result(uint64 id, BufferSlice packet) override {
@ -258,8 +257,7 @@ class GetPaymentFormQuery : public Td::ResultHandler {
}
void send(ServerMessageId server_message_id) {
send_query(
G()->net_query_creator().create(create_storer(telegram_api::payments_getPaymentForm(server_message_id.get()))));
send_query(G()->net_query_creator().create(telegram_api::payments_getPaymentForm(server_message_id.get())));
}
void on_result(uint64 id, BufferSlice packet) override {
@ -306,8 +304,8 @@ class ValidateRequestedInfoQuery : public Td::ResultHandler {
requested_info = make_tl_object<telegram_api::paymentRequestedInfo>();
requested_info->flags_ = 0;
}
send_query(G()->net_query_creator().create(create_storer(telegram_api::payments_validateRequestedInfo(
flags, false /*ignored*/, server_message_id.get(), std::move(requested_info)))));
send_query(G()->net_query_creator().create(telegram_api::payments_validateRequestedInfo(
flags, false /*ignored*/, server_message_id.get(), std::move(requested_info))));
}
void on_result(uint64 id, BufferSlice packet) override {
@ -347,8 +345,8 @@ class SendPaymentFormQuery : public Td::ResultHandler {
if (!shipping_option_id.empty()) {
flags |= telegram_api::payments_sendPaymentForm::SHIPPING_OPTION_ID_MASK;
}
send_query(G()->net_query_creator().create(create_storer(telegram_api::payments_sendPaymentForm(
flags, server_message_id.get(), order_info_id, shipping_option_id, std::move(input_credentials)))));
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))));
}
void on_result(uint64 id, BufferSlice packet) override {
@ -391,8 +389,7 @@ class GetPaymentReceiptQuery : public Td::ResultHandler {
}
void send(ServerMessageId server_message_id) {
send_query(G()->net_query_creator().create(
create_storer(telegram_api::payments_getPaymentReceipt(server_message_id.get()))));
send_query(G()->net_query_creator().create(telegram_api::payments_getPaymentReceipt(server_message_id.get())));
}
void on_result(uint64 id, BufferSlice packet) override {
@ -434,7 +431,7 @@ class GetSavedInfoQuery : public Td::ResultHandler {
}
void send() {
send_query(G()->net_query_creator().create(create_storer(telegram_api::payments_getSavedInfo())));
send_query(G()->net_query_creator().create(telegram_api::payments_getSavedInfo()));
}
void on_result(uint64 id, BufferSlice packet) override {
@ -470,7 +467,7 @@ class ClearSavedInfoQuery : public Td::ResultHandler {
flags |= telegram_api::payments_clearSavedInfo::INFO_MASK;
}
send_query(G()->net_query_creator().create(
create_storer(telegram_api::payments_clearSavedInfo(flags, false /*ignored*/, false /*ignored*/))));
telegram_api::payments_clearSavedInfo(flags, false /*ignored*/, false /*ignored*/)));
}
void on_result(uint64 id, BufferSlice packet) override {
@ -486,6 +483,37 @@ class ClearSavedInfoQuery : public Td::ResultHandler {
promise_.set_error(std::move(status));
}
};
class GetBankCardInfoQuery : public Td::ResultHandler {
Promise<td_api::object_ptr<td_api::bankCardInfo>> promise_;
public:
explicit GetBankCardInfoQuery(Promise<td_api::object_ptr<td_api::bankCardInfo>> &&promise)
: promise_(std::move(promise)) {
}
void send(const string &bank_card_number) {
send_query(G()->net_query_creator().create(telegram_api::payments_getBankCardData(bank_card_number),
G()->get_webfile_dc_id()));
}
void on_result(uint64 id, BufferSlice packet) override {
auto result_ptr = fetch_result<telegram_api::payments_getBankCardData>(packet);
if (result_ptr.is_error()) {
return on_error(id, result_ptr.move_as_error());
}
auto response = result_ptr.move_as_ok();
auto actions = transform(response->open_urls_, [](auto &open_url) {
return td_api::make_object<td_api::bankCardActionOpenUrl>(open_url->name_, open_url->url_);
});
promise_.set_value(td_api::make_object<td_api::bankCardInfo>(response->title_, std::move(actions)));
}
void on_error(uint64 id, Status status) override {
promise_.set_error(std::move(status));
}
};
/*
class SendLiteRequestQuery : public Td::ResultHandler {
Promise<td_api::object_ptr<td_api::tonLiteServerResponse>> promise_;
@ -496,8 +524,7 @@ class SendLiteRequestQuery : public Td::ResultHandler {
}
void send(BufferSlice request) {
send_query(G()->net_query_creator().create(create_storer(telegram_api::wallet_sendLiteRequest(std::move(request))),
DcId::main(), NetQuery::Type::Common, NetQuery::AuthFlag::Off));
send_query(G()->net_query_creator().create_unauth(telegram_api::wallet_sendLiteRequest(std::move(request))));
}
void on_result(uint64 id, BufferSlice packet) override {
@ -666,7 +693,7 @@ Result<Address> address_from_json(Slice json) {
auto value = r_value.move_as_ok();
if (value.type() != JsonValue::Type::Object) {
return Status::Error(400, "Address should be an Object");
return Status::Error(400, "Address must be an Object");
}
auto &object = value.get_object();
@ -896,6 +923,10 @@ void delete_saved_order_info(Promise<Unit> &&promise) {
void delete_saved_credentials(Promise<Unit> &&promise) {
G()->td().get_actor_unsafe()->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) {
G()->td().get_actor_unsafe()->create_handler<GetBankCardInfoQuery>(std::move(promise))->send(bank_card_number);
}
/*
void send_ton_lite_server_request(Slice request, Promise<td_api::object_ptr<td_api::tonLiteServerResponse>> &&promise) {
G()->td().get_actor_unsafe()->create_handler<SendLiteRequestQuery>(std::move(promise))->send(BufferSlice{request});

View File

@ -154,6 +154,8 @@ void delete_saved_order_info(Promise<Unit> &&promise);
void delete_saved_credentials(Promise<Unit> &&promise);
void get_bank_card_info(const string &bank_card_number, Promise<td_api::object_ptr<td_api::bankCardInfo>> &&promise);
// void send_ton_lite_server_request(Slice request, Promise<td_api::object_ptr<td_api::tonLiteServerResponse>> &&promise);
} // namespace td

View File

@ -7,7 +7,6 @@
#include "td/telegram/PhoneNumberManager.h"
#include "td/telegram/Global.h"
#include "td/telegram/net/DcId.h"
#include "td/telegram/net/NetQueryDispatcher.h"
#include "td/telegram/Td.h"
#include "td/telegram/td_api.h"
@ -39,7 +38,7 @@ PhoneNumberManager::PhoneNumberManager(PhoneNumberManager::Type type, ActorShare
template <class T>
void PhoneNumberManager::process_send_code_result(uint64 query_id, const T &send_code) {
on_new_query(query_id);
start_net_query(NetQueryType::SendCode, G()->net_query_creator().create(create_storer(send_code)));
start_net_query(NetQueryType::SendCode, G()->net_query_creator().create(send_code));
}
void PhoneNumberManager::set_phone_number(uint64 query_id, string phone_number, Settings settings) {
@ -90,14 +89,12 @@ void PhoneNumberManager::resend_authentication_code(uint64 query_id) {
on_new_query(query_id);
start_net_query(NetQueryType::SendCode,
G()->net_query_creator().create(create_storer(r_resend_code.move_as_ok()), DcId::main(),
NetQuery::Type::Common, NetQuery::AuthFlag::Off));
start_net_query(NetQueryType::SendCode, G()->net_query_creator().create_unauth(r_resend_code.move_as_ok()));
}
template <class T>
void PhoneNumberManager::send_new_check_code_query(const T &query) {
start_net_query(NetQueryType::CheckCode, G()->net_query_creator().create(create_storer(query)));
start_net_query(NetQueryType::CheckCode, G()->net_query_creator().create(query));
}
void PhoneNumberManager::check_code(uint64 query_id, string code) {

View File

@ -64,8 +64,8 @@ class GetPollResultsQuery : public Td::ResultHandler {
}
auto message_id = full_message_id.get_message_id().get_server_message_id().get();
send_query(G()->net_query_creator().create(
create_storer(telegram_api::messages_getPollResults(std::move(input_peer), message_id))));
send_query(
G()->net_query_creator().create(telegram_api::messages_getPollResults(std::move(input_peer), message_id)));
}
void on_result(uint64 id, BufferSlice packet) override {
@ -112,8 +112,8 @@ class GetPollVotersQuery : public Td::ResultHandler {
}
auto message_id = full_message_id.get_message_id().get_server_message_id().get();
send_query(G()->net_query_creator().create(create_storer(telegram_api::messages_getPollVotes(
flags, std::move(input_peer), message_id, std::move(option), offset, limit))));
send_query(G()->net_query_creator().create(telegram_api::messages_getPollVotes(
flags, std::move(input_peer), message_id, std::move(option), offset, limit)));
}
void on_result(uint64 id, BufferSlice packet) override {
@ -152,7 +152,7 @@ class SetPollAnswerActor : public NetActorOnce {
auto message_id = full_message_id.get_message_id().get_server_message_id().get();
auto query = G()->net_query_creator().create(
create_storer(telegram_api::messages_sendVote(std::move(input_peer), message_id, std::move(options))));
telegram_api::messages_sendVote(std::move(input_peer), message_id, std::move(options)));
*query_ref = query.get_weak();
auto sequence_id = -1;
send_closure(td->messages_manager_->sequence_dispatcher_, &MultiSequenceDispatcher::send_with_callback,
@ -203,9 +203,9 @@ class StopPollActor : public NetActorOnce {
poll->flags_ |= telegram_api::poll::CLOSED_MASK;
auto input_media =
telegram_api::make_object<telegram_api::inputMediaPoll>(0, std::move(poll), vector<BufferSlice>());
auto query = G()->net_query_creator().create(create_storer(telegram_api::messages_editMessage(
auto query = G()->net_query_creator().create(telegram_api::messages_editMessage(
flags, false /*ignored*/, std::move(input_peer), message_id, string(), std::move(input_media),
std::move(input_reply_markup), vector<tl_object_ptr<telegram_api::MessageEntity>>(), 0)));
std::move(input_reply_markup), vector<tl_object_ptr<telegram_api::MessageEntity>>(), 0));
auto sequence_id = -1;
send_closure(td->messages_manager_->sequence_dispatcher_, &MultiSequenceDispatcher::send_with_callback,
std::move(query), actor_shared(this), sequence_id);
@ -314,6 +314,7 @@ string PollManager::get_poll_database_key(PollId poll_id) {
void PollManager::save_poll(const Poll *poll, PollId poll_id) {
CHECK(!is_local_poll_id(poll_id));
poll->was_saved = true;
if (!G()->parameters().use_message_db) {
return;
@ -570,7 +571,7 @@ PollId PollManager::create_poll(string &&question, vector<string> &&options, boo
return poll_id;
}
void PollManager::register_poll(PollId poll_id, FullMessageId full_message_id) {
void PollManager::register_poll(PollId poll_id, FullMessageId full_message_id, const char *source) {
CHECK(have_poll(poll_id));
if (full_message_id.get_message_id().is_scheduled()) {
return;
@ -578,15 +579,15 @@ void PollManager::register_poll(PollId poll_id, FullMessageId full_message_id) {
if (!full_message_id.get_message_id().is_server()) {
return;
}
LOG(INFO) << "Register " << poll_id << " from " << full_message_id;
LOG(INFO) << "Register " << poll_id << " from " << full_message_id << " from " << source;
bool is_inserted = poll_messages_[poll_id].insert(full_message_id).second;
CHECK(is_inserted);
LOG_CHECK(is_inserted) << source << " " << poll_id << " " << full_message_id;
if (!td_->auth_manager_->is_bot() && !is_local_poll_id(poll_id) && !get_poll_is_closed(poll_id)) {
update_poll_timeout_.add_timeout_in(poll_id.get(), 0);
}
}
void PollManager::unregister_poll(PollId poll_id, FullMessageId full_message_id) {
void PollManager::unregister_poll(PollId poll_id, FullMessageId full_message_id, const char *source) {
CHECK(have_poll(poll_id));
if (full_message_id.get_message_id().is_scheduled()) {
return;
@ -594,10 +595,10 @@ void PollManager::unregister_poll(PollId poll_id, FullMessageId full_message_id)
if (!full_message_id.get_message_id().is_server()) {
return;
}
LOG(INFO) << "Unregister " << poll_id << " from " << full_message_id;
LOG(INFO) << "Unregister " << poll_id << " from " << full_message_id << " from " << source;
auto &message_ids = poll_messages_[poll_id];
auto is_deleted = message_ids.erase(full_message_id);
CHECK(is_deleted);
LOG_CHECK(is_deleted) << source << " " << poll_id << " " << full_message_id;
if (message_ids.empty()) {
poll_messages_.erase(poll_id);
update_poll_timeout_.cancel_timeout(poll_id.get());
@ -788,6 +789,10 @@ void PollManager::on_set_poll_answer(PollId poll_id, uint64 generation,
auto promises = std::move(pending_answer.promises_);
pending_answers_.erase(it);
auto poll = get_poll(poll_id);
if (poll != nullptr) {
poll->was_saved = false;
}
if (result.is_ok()) {
td_->updates_manager_->on_get_updates(result.move_as_ok());
@ -799,6 +804,17 @@ void PollManager::on_set_poll_answer(PollId poll_id, uint64 generation,
promise.set_error(result.error().clone());
}
}
if (poll != nullptr && !poll->was_saved) {
// no updates was sent during updates processing, so send them
// poll wasn't changed, so there is no reason to actually save it
if (!poll->is_closed) {
LOG(INFO) << "Schedule updating of " << poll_id << " soon";
update_poll_timeout_.set_timeout_in(poll_id.get(), 0.0);
}
notify_on_poll_update(poll_id);
poll->was_saved = true;
}
}
void PollManager::invalidate_poll_voters(const Poll *poll, PollId poll_id) {
@ -973,6 +989,10 @@ void PollManager::on_get_poll_voters(PollId poll_id, int32 option_id, int32 limi
if (static_cast<int32>(user_ids.size()) > limit) {
user_ids.resize(limit);
}
if (voters.next_offset.empty() && narrow_cast<int32>(voters.voter_user_ids.size()) != vote_list->count_) {
// invalidate_poll_option_voters(poll, poll_id, option_id);
voters.was_invalidated = true;
}
for (auto &promise : promises) {
promise.set_value({vote_list->count_, vector<UserId>(user_ids)});
@ -1336,7 +1356,7 @@ PollId PollManager::on_get_poll(PollId poll_id, tl_object_ptr<telegram_api::poll
LOG(ERROR) << "Receive correct option " << correct_option_id << " in non-quiz " << poll_id;
}
vector<UserId> recent_voter_user_ids;
if (!td_->auth_manager_->is_bot()) {
if (!is_bot) {
for (auto &user_id_int : poll_results->recent_voters_) {
UserId user_id(user_id_int);
if (user_id.is_valid()) {

View File

@ -47,9 +47,9 @@ class PollManager : public Actor {
PollId create_poll(string &&question, vector<string> &&options, bool is_anonymous, bool allow_multiple_answers,
bool is_quiz, int32 correct_option_id, bool is_closed);
void register_poll(PollId poll_id, FullMessageId full_message_id);
void register_poll(PollId poll_id, FullMessageId full_message_id, const char *source);
void unregister_poll(PollId poll_id, FullMessageId full_message_id);
void unregister_poll(PollId poll_id, FullMessageId full_message_id, const char *source);
bool get_poll_is_closed(PollId poll_id) const;
@ -112,6 +112,7 @@ class PollManager : public Actor {
bool allow_multiple_answers = false;
bool is_quiz = false;
bool is_closed = false;
mutable bool was_saved = false;
template <class StorerT>
void store(StorerT &storer) const;

View File

@ -27,7 +27,7 @@ namespace td {
Result<PrivacyManager::UserPrivacySetting> PrivacyManager::UserPrivacySetting::from_td_api(
tl_object_ptr<td_api::UserPrivacySetting> key) {
if (!key) {
return Status::Error(5, "UserPrivacySetting should not be empty");
return Status::Error(5, "UserPrivacySetting must be non-empty");
}
return UserPrivacySetting(*key);
}
@ -368,12 +368,12 @@ Result<PrivacyManager::UserPrivacySettingRules> PrivacyManager::UserPrivacySetti
Result<PrivacyManager::UserPrivacySettingRules> PrivacyManager::UserPrivacySettingRules::from_td_api(
tl_object_ptr<td_api::userPrivacySettingRules> rules) {
if (!rules) {
return Status::Error(5, "UserPrivacySettingRules should not be empty");
return Status::Error(5, "UserPrivacySettingRules must be non-empty");
}
UserPrivacySettingRules result;
for (auto &rule : rules->rules_) {
if (!rule) {
return Status::Error(5, "UserPrivacySettingRule should not be empty");
return Status::Error(5, "UserPrivacySettingRule must be non-empty");
}
result.rules_.emplace_back(*rule);
}
@ -409,8 +409,8 @@ void PrivacyManager::get_privacy(tl_object_ptr<td_api::UserPrivacySetting> key,
// query has already been sent, just wait for the result
return;
}
auto net_query = G()->net_query_creator().create(
create_storer(telegram_api::account_getPrivacy(user_privacy_setting.as_telegram_api())));
auto net_query =
G()->net_query_creator().create(telegram_api::account_getPrivacy(user_privacy_setting.as_telegram_api()));
send_with_promise(std::move(net_query),
PromiseCreator::lambda([this, user_privacy_setting](Result<NetQueryPtr> x_net_query) {
@ -442,8 +442,8 @@ void PrivacyManager::set_privacy(tl_object_ptr<td_api::UserPrivacySetting> key,
// TODO cancel previous query
return promise.set_error(Status::Error(5, "Another set_privacy query is active"));
}
auto net_query = G()->net_query_creator().create(create_storer(
telegram_api::account_setPrivacy(user_privacy_setting.as_telegram_api(), privacy_rules.as_telegram_api())));
auto net_query = G()->net_query_creator().create(
telegram_api::account_setPrivacy(user_privacy_setting.as_telegram_api(), privacy_rules.as_telegram_api()));
info.has_set_query = true;
send_with_promise(std::move(net_query),

View File

@ -30,13 +30,15 @@ class RequestActor : public Actor {
}
void loop() override {
PromiseActor<T> promise;
PromiseActor<T> promise_actor;
FutureActor<T> future;
init_promise_future(&promise, &future);
init_promise_future(&promise_actor, &future);
do_run(PromiseCreator::from_promise_actor(std::move(promise)));
auto promise = PromiseCreator::from_promise_actor(std::move(promise_actor));
do_run(std::move(promise));
if (future.is_ready()) {
CHECK(!promise);
if (future.is_error()) {
do_send_error(future.move_as_error());
} else {
@ -45,6 +47,9 @@ class RequestActor : public Actor {
}
stop();
} else {
LOG_CHECK(!promise.was_set_value) << future.empty() << " " << future.get_state();
CHECK(!future.empty());
CHECK(future.get_state() == FutureActor<T>::State::Waiting);
if (--tries_left_ == 0) {
future.close();
do_send_error(Status::Error(400, "Requested data is inaccessible"));

View File

@ -6,6 +6,7 @@
//
#include "td/telegram/SecretChatActor.h"
#include "td/telegram/net/DcId.h"
#include "td/telegram/net/NetQueryCreator.h"
#include "td/telegram/SecretChatId.h"
#include "td/telegram/ServerMessageId.h"
@ -68,6 +69,12 @@ SecretChatActor::SecretChatActor(int32 id, unique_ptr<Context> context, bool can
auth_state_.id = id;
}
template <class T>
NetQueryPtr SecretChatActor::create_net_query(QueryType type, const T &function) {
return context_->net_query_creator().create(UniqueId::next(UniqueId::Type::Default, static_cast<uint8>(type)),
function, DcId::main(), NetQuery::Type::Common, NetQuery::AuthFlag::On);
}
void SecretChatActor::update_chat(telegram_api::object_ptr<telegram_api::EncryptedChat> chat) {
if (close_flag_) {
return;
@ -358,9 +365,8 @@ void SecretChatActor::send_message_action(tl_object_ptr<secret_api::SendMessageA
}
bool flag = action->get_id() != secret_api::sendMessageCancelAction::ID;
auto net_query = context_->net_query_creator().create(
UniqueId::next(UniqueId::Type::Default, static_cast<uint8>(QueryType::Ignore)),
create_storer(telegram_api::messages_setEncryptedTyping(get_input_chat(), flag)));
auto net_query =
create_net_query(QueryType::Ignore, telegram_api::messages_setEncryptedTyping(get_input_chat(), flag));
if (!set_typing_query_.empty()) {
LOG(INFO) << "Cancel previous set typing query";
cancel_query(set_typing_query_);
@ -390,9 +396,8 @@ void SecretChatActor::send_read_history(int32 date, Promise<> promise) {
cancel_query(read_history_query_);
}
auto net_query = context_->net_query_creator().create(
UniqueId::next(UniqueId::Type::Default, static_cast<uint8>(QueryType::ReadHistory)),
create_storer(telegram_api::messages_readEncryptedHistory(get_input_chat(), date)));
auto net_query =
create_net_query(QueryType::ReadHistory, telegram_api::messages_readEncryptedHistory(get_input_chat(), date));
read_history_query_ = net_query.get_weak();
last_read_history_date_ = date;
read_history_promise_ = std::move(promise);
@ -566,11 +571,9 @@ Status SecretChatActor::run_auth() {
return Status::OK();
}
// messages.requestEncryption#f64daf43 user_id:InputUser random_id:int g_a:bytes = EncryptedChat;
telegram_api::messages_requestEncryption tl_query(get_input_user(), auth_state_.random_id,
BufferSlice(auth_state_.handshake.get_g_b()));
auto query = context_->net_query_creator().create(
UniqueId::next(UniqueId::Type::Default, static_cast<uint8>(QueryType::EncryptedChat)),
create_storer(tl_query));
auto query = create_net_query(QueryType::EncryptedChat, telegram_api::messages_requestEncryption(
get_input_user(), auth_state_.random_id,
BufferSlice(auth_state_.handshake.get_g_b())));
context_->send_net_query(std::move(query), actor_shared(this), false);
auth_state_.state = State::WaitRequestResponse;
return Status::OK();
@ -584,11 +587,10 @@ Status SecretChatActor::run_auth() {
pfs_state_.auth_key = mtproto::AuthKey(id_and_key.first, std::move(id_and_key.second));
calc_key_hash();
// messages.acceptEncryption#3dbc0415 peer:InputEncryptedChat g_b:bytes key_fingerprint:long = EncryptedChat;
telegram_api::messages_acceptEncryption tl_query(get_input_chat(), BufferSlice(auth_state_.handshake.get_g_b()),
pfs_state_.auth_key.id());
auto query = context_->net_query_creator().create(
UniqueId::next(UniqueId::Type::Default, static_cast<uint8>(QueryType::EncryptedChat)),
create_storer(tl_query));
auto query = create_net_query(
QueryType::EncryptedChat,
telegram_api::messages_acceptEncryption(get_input_chat(), BufferSlice(auth_state_.handshake.get_g_b()),
pfs_state_.auth_key.id()));
context_->send_net_query(std::move(query), actor_shared(this), false);
auth_state_.state = State::WaitAcceptResponse;
return Status::OK();
@ -756,10 +758,7 @@ void SecretChatActor::do_close_chat_impl(unique_ptr<logevent::CloseSecretChat> e
context_->secret_chat_db()->erase_value(config_state_);
context_->secret_chat_db()->erase_value(pfs_state_);
context_->secret_chat_db()->erase_value(seq_no_state_);
telegram_api::messages_discardEncryption tl_query(auth_state_.id);
auto query = context_->net_query_creator().create(
UniqueId::next(UniqueId::Type::Default, static_cast<uint8>(QueryType::DiscardEncryption)),
create_storer(tl_query));
auto query = create_net_query(QueryType::DiscardEncryption, telegram_api::messages_discardEncryption(auth_state_.id));
send_update_secret_chat();
@ -895,9 +894,8 @@ Status SecretChatActor::do_inbound_message_encrypted(unique_ptr<logevent::Inboun
parser.fetch_end();
if (!parser.get_error()) {
auto layer = message_with_layer->layer_;
if (layer < DEFAULT_LAYER && false /*TODO: fix android app bug? */) {
LOG(ERROR) << "All or nothing, " << tag("layer", layer) << " is not supported, drop message "
<< to_string(message_with_layer);
if (layer < DEFAULT_LAYER && false /* Android app can send such messages */) {
LOG(ERROR) << "Layer " << layer << " is not supported, drop message " << to_string(message_with_layer);
return Status::OK();
}
if (config_state_.his_layer < layer) {
@ -917,7 +915,7 @@ Status SecretChatActor::do_inbound_message_encrypted(unique_ptr<logevent::Inboun
status = Status::Error(PSLICE() << parser.get_error() << format::as_hex_dump<4>(data_buffer.as_slice()));
}
} else {
status = Status::Error(PSLICE() << "Unknown constructor " << tag("ID", format::as_hex(id)));
status = Status::Error(PSLICE() << "Unknown constructor " << format::as_hex(id));
}
// support for older layer
@ -1464,22 +1462,19 @@ NetQueryPtr SecretChatActor::create_net_query(const logevent::OutboundSecretMess
NetQueryPtr query;
if (message.is_service) {
CHECK(message.file.empty());
query = context_->net_query_creator().create(
UniqueId::next(UniqueId::Type::Default, static_cast<uint8>(QueryType::Message)),
create_storer(telegram_api::messages_sendEncryptedService(get_input_chat(), message.random_id,
message.encrypted_message.clone())));
query->total_timeout_limit = 1000000000; // inf. We will re-sent it immediately anyway.
query = create_net_query(QueryType::Message,
telegram_api::messages_sendEncryptedService(get_input_chat(), message.random_id,
message.encrypted_message.clone()));
query->total_timeout_limit = 1000000000; // inf. We will re-sent it immediately anyway
} else if (message.file.empty()) {
query = context_->net_query_creator().create(
UniqueId::next(UniqueId::Type::Default, static_cast<uint8>(QueryType::Message)),
create_storer(telegram_api::messages_sendEncrypted(get_input_chat(), message.random_id,
message.encrypted_message.clone())));
query = create_net_query(
QueryType::Message,
telegram_api::messages_sendEncrypted(get_input_chat(), message.random_id, message.encrypted_message.clone()));
} else {
query = context_->net_query_creator().create(
UniqueId::next(UniqueId::Type::Default, static_cast<uint8>(QueryType::Message)),
create_storer(telegram_api::messages_sendEncryptedFile(get_input_chat(), message.random_id,
message.encrypted_message.clone(),
message.file.as_input_encrypted_file())));
query = create_net_query(
QueryType::Message,
telegram_api::messages_sendEncryptedFile(get_input_chat(), message.random_id, message.encrypted_message.clone(),
message.file.as_input_encrypted_file()));
}
if (message.is_external && context_->get_config_option_boolean("use_quick_ack")) {
query->quick_ack_promise_ =
@ -1964,11 +1959,8 @@ void SecretChatActor::get_dh_config() {
}
auto version = auth_state_.dh_config.version;
int random_length = 0;
telegram_api::messages_getDhConfig tl_query(version, random_length);
auto query = context_->net_query_creator().create(
UniqueId::next(UniqueId::Type::Default, static_cast<uint8>(QueryType::DhConfig)), create_storer(tl_query));
int32 random_length = 0;
auto query = create_net_query(QueryType::DhConfig, telegram_api::messages_getDhConfig(version, random_length));
context_->send_net_query(std::move(query), actor_shared(this), false);
}

View File

@ -18,6 +18,7 @@
#include "td/telegram/DhConfig.h"
#include "td/telegram/logevent/SecretChatEvent.h"
#include "td/telegram/MessageId.h"
#include "td/telegram/net/NetQuery.h"
#include "td/telegram/SecretChatDb.h"
#include "td/telegram/SecretChatId.h"
#include "td/telegram/UserId.h"
@ -589,6 +590,9 @@ class SecretChatActor : public NetQueryCallback {
int32 last_read_history_date_ = -1;
Promise<Unit> read_history_promise_;
template <class T>
NetQueryPtr create_net_query(QueryType type, const T &function);
enum SendFlag : int32 {
None = 0,
External = 1,

View File

@ -136,7 +136,7 @@ class SetSecureValueErrorsQuery : public Td::ResultHandler {
void send(tl_object_ptr<telegram_api::InputUser> input_user,
vector<tl_object_ptr<telegram_api::SecureValueError>> input_errors) {
send_query(G()->net_query_creator().create(
create_storer(telegram_api::users_setSecureValueErrors(std::move(input_user), std::move(input_errors)))));
telegram_api::users_setSecureValueErrors(std::move(input_user), std::move(input_errors))));
}
void on_result(uint64 id, BufferSlice packet) override {
@ -178,7 +178,7 @@ void GetSecureValue::on_error(Status error) {
void GetSecureValue::on_secret(Result<secure_storage::Secret> r_secret, bool dummy) {
if (r_secret.is_error()) {
if (!G()->close_flag()) {
if (!G()->is_expected_error(r_secret.error())) {
LOG(ERROR) << "Receive error instead of secret: " << r_secret.error();
}
return on_error(r_secret.move_as_error());
@ -208,7 +208,7 @@ void GetSecureValue::start_up() {
std::vector<telegram_api::object_ptr<telegram_api::SecureValueType>> types;
types.push_back(get_input_secure_value_type(type_));
auto query = G()->net_query_creator().create(create_storer(telegram_api::account_getSecureValue(std::move(types))));
auto query = G()->net_query_creator().create(telegram_api::account_getSecureValue(std::move(types)));
G()->net_query_dispatcher().dispatch_with_callback(std::move(query), actor_shared(this));
@ -257,7 +257,7 @@ void GetAllSecureValues::on_error(Status error) {
void GetAllSecureValues::on_secret(Result<secure_storage::Secret> r_secret, bool dummy) {
if (r_secret.is_error()) {
if (!G()->close_flag()) {
if (!G()->is_expected_error(r_secret.error())) {
LOG(ERROR) << "Receive error instead of secret: " << r_secret.error();
}
return on_error(r_secret.move_as_error());
@ -288,7 +288,7 @@ void GetAllSecureValues::loop() {
}
void GetAllSecureValues::start_up() {
auto query = G()->net_query_creator().create(create_storer(telegram_api::account_getAllSecureValues()));
auto query = G()->net_query_creator().create(telegram_api::account_getAllSecureValues());
G()->net_query_dispatcher().dispatch_with_callback(std::move(query), actor_shared(this));
@ -393,7 +393,7 @@ void SetSecureValue::on_error(Status error) {
void SetSecureValue::on_secret(Result<secure_storage::Secret> r_secret, bool x) {
if (r_secret.is_error()) {
if (!G()->close_flag()) {
if (!G()->is_expected_error(r_secret.error())) {
LOG(ERROR) << "Receive error instead of secret: " << r_secret.error();
}
return on_error(r_secret.move_as_error());
@ -572,7 +572,7 @@ void SetSecureValue::loop() {
files_to_upload_, front_side_, reverse_side_, selfie_, translations_to_upload_);
auto save_secure_value =
telegram_api::account_saveSecureValue(std::move(input_secure_value), secret_.value().get_hash());
auto query = G()->net_query_creator().create(create_storer(save_secure_value));
auto query = G()->net_query_creator().create(save_secure_value);
G()->net_query_dispatcher().dispatch_with_callback(std::move(query), actor_shared(this));
state_ = State::WaitSetValue;
@ -664,8 +664,7 @@ class DeleteSecureValue : public NetQueryCallback {
void start_up() override {
std::vector<telegram_api::object_ptr<telegram_api::SecureValueType>> types;
types.push_back(get_input_secure_value_type(type_));
auto query =
G()->net_query_creator().create(create_storer(telegram_api::account_deleteSecureValue(std::move(types))));
auto query = G()->net_query_creator().create(telegram_api::account_deleteSecureValue(std::move(types)));
G()->net_query_dispatcher().dispatch_with_callback(std::move(query), actor_shared(this));
}
@ -710,7 +709,7 @@ class GetPassportAuthorizationForm : public NetQueryCallback {
void start_up() override {
auto account_get_authorization_form =
telegram_api::account_getAuthorizationForm(bot_user_id_.get(), std::move(scope_), std::move(public_key_));
auto query = G()->net_query_creator().create(create_storer(account_get_authorization_form));
auto query = G()->net_query_creator().create(account_get_authorization_form);
G()->net_query_dispatcher().dispatch_with_callback(std::move(query), actor_shared(this));
}
@ -764,7 +763,7 @@ class GetPassportConfig : public NetQueryCallback {
Promise<td_api::object_ptr<td_api::text>> promise_;
void start_up() override {
auto query = G()->net_query_creator().create(create_storer(telegram_api::help_getPassportConfig(0)));
auto query = G()->net_query_creator().create(telegram_api::help_getPassportConfig(0));
G()->net_query_dispatcher().dispatch_with_callback(std::move(query), actor_shared(this));
}
@ -1062,7 +1061,7 @@ void SecureManager::on_get_passport_authorization_form_secret(int32 authorizatio
if (r_secret.is_error()) {
auto error = r_secret.move_as_error();
if (!G()->close_flag()) {
if (!G()->is_expected_error(error)) {
LOG(ERROR) << "Receive error instead of secret: " << error;
}
if (error.code() <= 0) {
@ -1269,7 +1268,7 @@ void SecureManager::send_passport_authorization_form(int32 authorization_form_id
auto td_query = telegram_api::account_acceptAuthorization(
it->second.bot_user_id.get(), it->second.scope, it->second.public_key, std::move(hashes),
get_secure_credentials_encrypted_object(r_encrypted_credentials.move_as_ok()));
auto query = G()->net_query_creator().create(create_storer(td_query));
auto query = G()->net_query_creator().create(td_query);
auto new_promise =
PromiseCreator::lambda([promise = std::move(promise)](Result<NetQueryPtr> r_net_query_ptr) mutable {
auto r_result = fetch_result<telegram_api::account_acceptAuthorization>(std::move(r_net_query_ptr));

View File

@ -225,7 +225,7 @@ Secret Secret::clone() const {
}
EncryptedSecret Secret::encrypt(Slice key, Slice salt, EnryptionAlgorithm algorithm) {
auto aes_cbc_state = [&]() {
auto aes_cbc_state = [&] {
switch (algorithm) {
case EnryptionAlgorithm::Sha512:
return calc_aes_cbc_state_sha512(PSLICE() << salt << key << salt);
@ -255,7 +255,7 @@ Result<EncryptedSecret> EncryptedSecret::create(Slice encrypted_secret) {
}
Result<Secret> EncryptedSecret::decrypt(Slice key, Slice salt, EnryptionAlgorithm algorithm) {
auto aes_cbc_state = [&]() {
auto aes_cbc_state = [&] {
switch (algorithm) {
case EnryptionAlgorithm::Sha512:
return calc_aes_cbc_state_sha512(PSLICE() << salt << key << salt);
@ -288,7 +288,7 @@ Result<BufferSlice> Decryptor::append(BufferSlice data) {
return BufferSlice();
}
if (data.size() % 16 != 0) {
return Status::Error("Part size should be divisible by 16");
return Status::Error("Part size must be divisible by 16");
}
aes_cbc_state_.decrypt(data.as_slice(), data.as_slice());
sha256_state_.feed(data.as_slice());
@ -330,7 +330,7 @@ Result<BufferSlice> Encryptor::pread(int64 offset, int64 size) const {
return Status::Error("Arbitrary offset is not supported");
}
if (size % 16 != 0) {
return Status::Error("Part size should be divisible by 16");
return Status::Error("Part size must be divisible by 16");
}
TRY_RESULT(part, data_view_.pread(offset, size));
aes_cbc_state_.encrypt(part.as_slice(), part.as_slice());

View File

@ -796,7 +796,7 @@ static Result<td_api::object_ptr<td_api::personalDetails>> get_personal_details_
auto value = r_value.move_as_ok();
if (value.type() != JsonValue::Type::Object) {
return Status::Error(400, "Personal details should be an Object");
return Status::Error(400, "Personal details must be an Object");
}
auto &object = value.get_object();
@ -888,7 +888,7 @@ static Result<SecureValue> get_identity_document(SecureValueType type, FileManag
}
} else {
if (!need_reverse_side) {
return Status::Error(400, "Document shouldn't have a reverse side");
return Status::Error(400, "Document can't have a reverse side");
}
}
@ -930,7 +930,7 @@ static Result<td_api::object_ptr<td_api::identityDocument>> get_identity_documen
auto json_value = r_value.move_as_ok();
if (json_value.type() != JsonValue::Type::Object) {
return Status::Error(400, "Identity document should be an Object");
return Status::Error(400, "Identity document must be an Object");
}
auto &object = json_value.get_object();

File diff suppressed because it is too large Load Diff

View File

@ -108,7 +108,9 @@ class StickersManager : public Actor {
StickerSetId on_get_sticker_set_covered(tl_object_ptr<telegram_api::StickerSetCovered> &&set_ptr, bool is_changed,
const char *source);
void on_get_animated_emoji_sticker_set(StickerSetId sticker_set_id);
enum SpecialStickerSetType : int32 { AnimatedEmoji, AnimatedDice };
void on_get_special_sticker_set(StickerSetId sticker_set_id, SpecialStickerSetType type);
void on_load_sticker_set_fail(StickerSetId sticker_set_id, const Status &error);
@ -145,11 +147,14 @@ class StickersManager : public Actor {
FileId upload_sticker_file(UserId user_id, const tl_object_ptr<td_api::InputFile> &sticker, Promise<Unit> &&promise);
void create_new_sticker_set(UserId user_id, string &title, string &short_name, bool is_masks,
vector<tl_object_ptr<td_api::inputSticker>> &&stickers, Promise<Unit> &&promise);
vector<tl_object_ptr<td_api::InputSticker>> &&stickers, Promise<Unit> &&promise);
void add_sticker_to_set(UserId user_id, string &short_name, tl_object_ptr<td_api::inputSticker> &&sticker,
void add_sticker_to_set(UserId user_id, string &short_name, tl_object_ptr<td_api::InputSticker> &&sticker,
Promise<Unit> &&promise);
void set_sticker_set_thumbnail(UserId user_id, string &short_name, tl_object_ptr<td_api::InputFile> &&thumbnail,
Promise<Unit> &&promise);
void set_sticker_position_in_set(const tl_object_ptr<td_api::InputFile> &sticker, int32 position,
Promise<Unit> &&promise);
@ -265,10 +270,13 @@ class StickersManager : public Actor {
private:
static constexpr int32 MAX_FEATURED_STICKER_SET_VIEW_DELAY = 5;
static constexpr int32 MAX_FOUND_STICKERS = 100; // server side limit
static constexpr int64 MAX_STICKER_FILE_SIZE = 1 << 19; // server side limit
static constexpr size_t MAX_STICKER_SET_TITLE_LENGTH = 64; // server side limit
static constexpr size_t MAX_STICKER_SET_SHORT_NAME_LENGTH = 64; // server side limit
static constexpr int32 MAX_FOUND_STICKERS = 100; // server side limit
static constexpr int64 MAX_STICKER_FILE_SIZE = 1 << 19; // server side limit
static constexpr int64 MAX_THUMBNAIL_FILE_SIZE = 1 << 17; // server side limit
static constexpr int64 MAX_ANIMATED_STICKER_FILE_SIZE = 1 << 16; // server side limit
static constexpr int64 MAX_ANIMATED_THUMBNAIL_FILE_SIZE = 1 << 15; // server side limit
static constexpr size_t MAX_STICKER_SET_TITLE_LENGTH = 64; // server side limit
static constexpr size_t MAX_STICKER_SET_SHORT_NAME_LENGTH = 64; // server side limit
static constexpr int32 EMOJI_KEYWORDS_UPDATE_DELAY = 3600;
@ -329,18 +337,32 @@ class StickersManager : public Actor {
string title;
string short_name;
bool is_masks;
bool is_animated;
vector<FileId> file_ids;
vector<tl_object_ptr<td_api::inputSticker>> stickers;
vector<tl_object_ptr<td_api::InputSticker>> stickers;
Promise<> promise;
};
struct PendingAddStickerToSet {
string short_name;
FileId file_id;
tl_object_ptr<td_api::inputSticker> sticker;
tl_object_ptr<td_api::InputSticker> sticker;
Promise<> promise;
};
struct PendingSetStickerSetThumbnail {
string short_name;
FileId file_id;
Promise<> promise;
};
struct SpecialStickerSet {
StickerSetId id_;
int64 access_hash_ = 0;
string name_;
string type_;
};
class StickerListLogEvent;
class StickerSetListLogEvent;
@ -463,11 +485,14 @@ class StickersManager : public Actor {
template <class ParserT>
void parse_sticker_set(StickerSet *sticker_set, ParserT &parser);
Result<std::tuple<FileId, bool, bool>> prepare_input_file(const tl_object_ptr<td_api::InputFile> &input_file);
static string &get_input_sticker_emojis(td_api::InputSticker *sticker);
Result<std::tuple<FileId, bool, bool>> prepare_input_sticker(td_api::inputSticker *sticker);
Result<std::tuple<FileId, bool, bool, bool>> prepare_input_file(const tl_object_ptr<td_api::InputFile> &input_file,
bool is_animated, bool for_thumbnail);
tl_object_ptr<telegram_api::inputStickerSetItem> get_input_sticker(td_api::inputSticker *sticker,
Result<std::tuple<FileId, bool, bool, bool>> prepare_input_sticker(td_api::InputSticker *sticker);
tl_object_ptr<telegram_api::inputStickerSetItem> get_input_sticker(td_api::InputSticker *sticker,
FileId file_id) const;
void upload_sticker_file(UserId user_id, FileId file_id, Promise<Unit> &&promise);
@ -483,12 +508,22 @@ class StickersManager : public Actor {
void on_added_sticker_uploaded(int64 random_id, Result<Unit> result);
void on_sticker_set_thumbnail_uploaded(int64 random_id, Result<Unit> result);
void do_set_sticker_set_thumbnail(UserId user_id, string short_name, tl_object_ptr<td_api::InputFile> &&thumbnail,
Promise<Unit> &&promise);
bool update_sticker_set_cache(const StickerSet *sticker_set, Promise<Unit> &promise);
void start_up() override;
void tear_down() override;
static void init_special_sticker_set(SpecialStickerSet &sticker_set, int64 sticker_set_id, int64 access_hash,
string name);
void load_special_sticker_set(SpecialStickerSet &sticker_set);
static void add_sticker_thumbnail(Sticker *s, PhotoSize thumbnail);
static string get_sticker_mime_type(const Sticker *s);
@ -589,9 +624,7 @@ class StickersManager : public Actor {
int32 recent_stickers_limit_ = 200;
int32 favorite_stickers_limit_ = 5;
StickerSetId animated_emoji_sticker_set_id_;
int64 animated_emoji_sticker_set_access_hash_ = 0;
string animated_emoji_sticker_set_name_;
SpecialStickerSet special_sticker_sets_[2];
struct StickerSetLoadRequest {
Promise<Unit> promise;
@ -606,6 +639,8 @@ class StickersManager : public Actor {
std::unordered_map<int64, unique_ptr<PendingAddStickerToSet>> pending_add_sticker_to_sets_;
std::unordered_map<int64, unique_ptr<PendingSetStickerSetThumbnail>> pending_set_sticker_set_thumbnails_;
std::shared_ptr<UploadStickerFileCallback> upload_sticker_file_callback_;
std::unordered_map<FileId, std::pair<UserId, Promise<Unit>>, FileIdHash> being_uploaded_files_;

View File

@ -199,7 +199,7 @@ void StickersManager::parse_sticker_set(StickerSet *sticker_set, ParserT &parser
parse(access_hash, parser);
CHECK(sticker_set->id.get() == sticker_set_id);
if (sticker_set->access_hash != access_hash) {
LOG(ERROR) << "Access hash of " << sticker_set_id << " has changed from " << access_hash << " to "
LOG(ERROR) << "Access hash of " << sticker_set->id << " has changed from " << access_hash << " to "
<< sticker_set->access_hash;
}

View File

@ -7,7 +7,6 @@
#include "td/telegram/StorageManager.h"
#include "td/telegram/ConfigShared.h"
#include "td/telegram/DialogId.h"
#include "td/telegram/files/FileGcWorker.h"
#include "td/telegram/files/FileStatsWorker.h"
#include "td/telegram/Global.h"
@ -42,13 +41,19 @@ void StorageManager::start_up() {
load_fast_stat();
}
void StorageManager::on_new_file(int64 size, int32 cnt) {
LOG(INFO) << "Add " << cnt << " file of size " << size << " to fast storage statistics";
void StorageManager::on_new_file(int64 size, int64 real_size, int32 cnt) {
LOG(INFO) << "Add " << cnt << " file of size " << size << " with real size " << real_size
<< " to fast storage statistics";
fast_stat_.cnt += cnt;
fast_stat_.size += size;
#if TD_WINDOWS
auto add_size = size;
#else
auto add_size = real_size;
#endif
fast_stat_.size += add_size;
if (fast_stat_.cnt < 0 || fast_stat_.size < 0) {
LOG(ERROR) << "Wrong fast stat after adding size " << size << " and cnt " << cnt;
LOG(ERROR) << "Wrong fast stat after adding size " << add_size << " and cnt " << cnt;
fast_stat_ = FileTypeStat();
}
save_fast_stat();
@ -67,7 +72,7 @@ void StorageManager::get_storage_stats(bool need_all_files, int32 dialog_limit,
//TODO group same queries
close_stats_worker();
}
if (!pending_run_gc_.empty()) {
if (!pending_run_gc_[0].empty() || !pending_run_gc_[1].empty()) {
close_gc_worker();
}
stats_dialog_limit_ = dialog_limit;
@ -101,12 +106,12 @@ void StorageManager::update_use_storage_optimizer() {
schedule_next_gc();
}
void StorageManager::run_gc(FileGcParameters parameters, Promise<FileStats> promise) {
void StorageManager::run_gc(FileGcParameters parameters, bool return_deleted_file_statistics,
Promise<FileStats> promise) {
if (is_closed_) {
promise.set_error(Status::Error(500, "Request aborted"));
return;
return promise.set_error(Status::Error(500, "Request aborted"));
}
if (!pending_run_gc_.empty()) {
if (!pending_run_gc_[0].empty() || !pending_run_gc_[1].empty()) {
close_gc_worker();
}
@ -116,11 +121,11 @@ void StorageManager::run_gc(FileGcParameters parameters, Promise<FileStats> prom
PromiseCreator::lambda(
[actor_id = actor_id(this), parameters = std::move(parameters)](Result<FileStats> file_stats) {
send_closure(actor_id, &StorageManager::on_all_files, std::move(parameters),
std::move(file_stats), false);
std::move(file_stats));
}));
//NB: get_storage_stats will cancel all gc queries, so promise needs to be added after the call
pending_run_gc_.emplace_back(std::move(promise));
pending_run_gc_[return_deleted_file_statistics].push_back(std::move(promise));
}
void StorageManager::on_file_stats(Result<FileStats> r_file_stats, uint32 generation) {
@ -135,6 +140,7 @@ void StorageManager::on_file_stats(Result<FileStats> r_file_stats, uint32 genera
return;
}
update_fast_stats(r_file_stats.ok());
send_stats(r_file_stats.move_as_ok(), stats_dialog_limit_, std::move(pending_storage_stats_));
}
@ -147,20 +153,20 @@ void StorageManager::create_stats_worker() {
}
}
void StorageManager::on_all_files(FileGcParameters gc_parameters, Result<FileStats> r_file_stats, bool dummy) {
void StorageManager::on_all_files(FileGcParameters gc_parameters, Result<FileStats> r_file_stats) {
int32 dialog_limit = gc_parameters.dialog_limit;
if (is_closed_ && r_file_stats.is_ok()) {
r_file_stats = Status::Error(500, "Request aborted");
}
if (r_file_stats.is_error()) {
return on_gc_finished(dialog_limit, std::move(r_file_stats), false);
return on_gc_finished(dialog_limit, r_file_stats.move_as_error());
}
create_gc_worker();
send_closure(gc_worker_, &FileGcWorker::run_gc, std::move(gc_parameters), r_file_stats.move_as_ok().all_files,
PromiseCreator::lambda([actor_id = actor_id(this), dialog_limit](Result<FileStats> r_file_stats) {
send_closure(actor_id, &StorageManager::on_gc_finished, dialog_limit, std::move(r_file_stats), false);
send_closure(gc_worker_, &FileGcWorker::run_gc, std::move(gc_parameters), std::move(r_file_stats.ok_ref().all_files),
PromiseCreator::lambda([actor_id = actor_id(this), dialog_limit](Result<FileGcResult> r_file_gc_result) {
send_closure(actor_id, &StorageManager::on_gc_finished, dialog_limit, std::move(r_file_gc_result));
}));
}
@ -206,19 +212,27 @@ void StorageManager::create_gc_worker() {
}
}
void StorageManager::on_gc_finished(int32 dialog_limit, Result<FileStats> r_file_stats, bool dummy) {
if (r_file_stats.is_error()) {
if (r_file_stats.error().code() != 500) {
LOG(ERROR) << "GC failed: " << r_file_stats.error();
void StorageManager::on_gc_finished(int32 dialog_limit, Result<FileGcResult> r_file_gc_result) {
if (r_file_gc_result.is_error()) {
if (r_file_gc_result.error().code() != 500) {
LOG(ERROR) << "GC failed: " << r_file_gc_result.error();
}
auto promises = std::move(pending_run_gc_);
auto promises = std::move(pending_run_gc_[0]);
append(promises, std::move(pending_run_gc_[1]));
pending_run_gc_[0].clear();
pending_run_gc_[1].clear();
for (auto &promise : promises) {
promise.set_error(r_file_stats.error().clone());
promise.set_error(r_file_gc_result.error().clone());
}
return;
}
send_stats(r_file_stats.move_as_ok(), dialog_limit, std::move(pending_run_gc_));
update_fast_stats(r_file_gc_result.ok().kept_file_stats_);
auto kept_file_promises = std::move(pending_run_gc_[0]);
auto removed_file_promises = std::move(pending_run_gc_[1]);
send_stats(std::move(r_file_gc_result.ok_ref().kept_file_stats_), dialog_limit, std::move(kept_file_promises));
send_stats(std::move(r_file_gc_result.ok_ref().removed_file_stats_), dialog_limit, std::move(removed_file_promises));
}
void StorageManager::save_fast_stat() {
@ -233,21 +247,26 @@ void StorageManager::load_fast_stat() {
LOG(INFO) << "Loaded fast storage statistics with " << fast_stat_.cnt << " files of total size " << fast_stat_.size;
}
void StorageManager::send_stats(FileStats &&stats, int32 dialog_limit, std::vector<Promise<FileStats>> promises) {
void StorageManager::update_fast_stats(const FileStats &stats) {
fast_stat_ = stats.get_total_nontemp_stat();
LOG(INFO) << "Recalculate fast storage statistics to " << fast_stat_.cnt << " files of total size "
<< fast_stat_.size;
save_fast_stat();
}
void StorageManager::send_stats(FileStats &&stats, int32 dialog_limit, std::vector<Promise<FileStats>> &&promises) {
if (promises.empty()) {
return;
}
stats.apply_dialog_limit(dialog_limit);
std::vector<DialogId> dialog_ids = stats.get_dialog_ids();
auto dialog_ids = stats.get_dialog_ids();
auto promise =
PromiseCreator::lambda([promises = std::move(promises), stats = std::move(stats)](Result<Unit>) mutable {
for (auto &promise : promises) {
promise.set_value(FileStats(stats));
}
});
auto promise = PromiseCreator::lambda([promises = std::move(promises), stats = std::move(stats)](Unit) mutable {
for (auto &promise : promises) {
promise.set_value(FileStats(stats));
}
});
send_closure(G()->messages_manager(), &MessagesManager::load_dialogs, std::move(dialog_ids), std::move(promise));
}
@ -276,8 +295,10 @@ void StorageManager::close_stats_worker() {
}
void StorageManager::close_gc_worker() {
auto promises = std::move(pending_run_gc_);
pending_run_gc_.clear();
auto promises = std::move(pending_run_gc_[0]);
append(promises, std::move(pending_run_gc_[1]));
pending_run_gc_[0].clear();
pending_run_gc_[1].clear();
for (auto &promise : promises) {
promise.set_error(Status::Error(500, "Request aborted"));
}
@ -332,14 +353,14 @@ void StorageManager::timeout_expired() {
if (next_gc_at_ == 0) {
return;
}
if (!pending_run_gc_.empty() || !pending_storage_stats_.empty()) {
if (!pending_run_gc_[0].empty() || !pending_run_gc_[1].empty() || !pending_storage_stats_.empty()) {
set_timeout_in(60);
return;
}
next_gc_at_ = 0;
run_gc({}, PromiseCreator::lambda([actor_id = actor_id(this)](Result<FileStats> r_stats) {
run_gc({}, false, PromiseCreator::lambda([actor_id = actor_id(this)](Result<FileStats> r_stats) {
if (!r_stats.is_error() || r_stats.error().code() != 500) {
// do not save gc timestamp is request was cancelled
// do not save gc timestamp if request was cancelled
send_closure(actor_id, &StorageManager::save_last_gc_timestamp);
}
send_closure(actor_id, &StorageManager::schedule_next_gc);

View File

@ -35,10 +35,10 @@ class StorageManager : public Actor {
void get_storage_stats(bool need_all_files, int32 dialog_limit, Promise<FileStats> promise);
void get_storage_stats_fast(Promise<FileStatsFast> promise);
void get_database_stats(Promise<DatabaseStats> promise);
void run_gc(FileGcParameters parameters, Promise<FileStats> promise);
void run_gc(FileGcParameters parameters, bool return_deleted_file_statistics, Promise<FileStats> promise);
void update_use_storage_optimizer();
void on_new_file(int64 size, int32 cnt);
void on_new_file(int64 size, int64 real_size, int32 cnt);
private:
static constexpr uint32 GC_EACH = 60 * 60 * 24; // 1 day
@ -63,7 +63,8 @@ class StorageManager : public Actor {
void on_file_stats(Result<FileStats> r_file_stats, uint32 generation);
void create_stats_worker();
void send_stats(FileStats &&stats, int32 dialog_limit, std::vector<Promise<FileStats>> promises);
void update_fast_stats(const FileStats &stats);
void send_stats(FileStats &&stats, int32 dialog_limit, std::vector<Promise<FileStats>> &&promises);
void save_fast_stat();
void load_fast_stat();
@ -82,14 +83,14 @@ class StorageManager : public Actor {
// Gc
ActorOwn<FileGcWorker> gc_worker_;
std::vector<Promise<FileStats>> pending_run_gc_;
std::vector<Promise<FileStats>> pending_run_gc_[2];
uint32 last_gc_timestamp_ = 0;
double next_gc_at_ = 0;
void on_all_files(FileGcParameters gc_parameters, Result<FileStats> r_file_stats, bool dummy);
void on_all_files(FileGcParameters gc_parameters, Result<FileStats> r_file_stats);
void create_gc_worker();
void on_gc_finished(int32 dialog_limit, Result<FileStats> r_file_stats, bool dummy);
void on_gc_finished(int32 dialog_limit, Result<FileGcResult> r_file_gc_result);
void close_stats_worker();
void close_gc_worker();

File diff suppressed because it is too large Load Diff

View File

@ -227,7 +227,7 @@ class Td final : public NetQueryCallback {
static td_api::object_ptr<td_api::Object> static_request(td_api::object_ptr<td_api::Function> function);
private:
static constexpr const char *TDLIB_VERSION = "1.5.5";
static constexpr const char *TDLIB_VERSION = "1.6.2";
static constexpr int64 ONLINE_ALARM_ID = 0;
static constexpr int64 PING_SERVER_ALARM_ID = -1;
static constexpr int32 PING_SERVER_TIMEOUT = 300;
@ -781,6 +781,10 @@ class Td final : public NetQueryCallback {
void on_request(uint64 id, td_api::setUsername &request);
void on_request(uint64 id, td_api::setCommands &request);
void on_request(uint64 id, const td_api::setLocation &request);
void on_request(uint64 id, td_api::setProfilePhoto &request);
void on_request(uint64 id, const td_api::deleteProfilePhoto &request);
@ -835,6 +839,8 @@ class Td final : public NetQueryCallback {
void on_request(uint64 id, td_api::addStickerToSet &request);
void on_request(uint64 id, td_api::setStickerSetThumbnail &request);
void on_request(uint64 id, td_api::setStickerPositionInSet &request);
void on_request(uint64 id, td_api::removeStickerFromSet &request);
@ -881,6 +887,10 @@ class Td final : public NetQueryCallback {
void on_request(uint64 id, td_api::getChatStatisticsUrl &request);
void on_request(uint64 id, const td_api::getChatStatistics &request);
void on_request(uint64 id, td_api::getChatStatisticsGraph &request);
void on_request(uint64 id, const td_api::getMapThumbnailFile &request);
void on_request(uint64 id, const td_api::getLocalizationTargetInfo &request);
@ -927,6 +937,8 @@ class Td final : public NetQueryCallback {
void on_request(uint64 id, td_api::answerPreCheckoutQuery &request);
void on_request(uint64 id, td_api::getBankCardInfo &request);
void on_request(uint64 id, const td_api::getPaymentForm &request);
void on_request(uint64 id, td_api::validateOrderInfo &request);
@ -1041,6 +1053,10 @@ class Td final : public NetQueryCallback {
void on_request(uint64 id, const td_api::parseTextEntities &request);
void on_request(uint64 id, const td_api::parseMarkdown &request);
void on_request(uint64 id, const td_api::getMarkdownText &request);
void on_request(uint64 id, const td_api::getFileMimeType &request);
void on_request(uint64 id, const td_api::getFileExtension &request);
@ -1092,6 +1108,8 @@ class Td final : public NetQueryCallback {
}
static td_api::object_ptr<td_api::Object> do_static_request(const td_api::getTextEntities &request);
static td_api::object_ptr<td_api::Object> do_static_request(td_api::parseTextEntities &request);
static td_api::object_ptr<td_api::Object> do_static_request(td_api::parseMarkdown &request);
static td_api::object_ptr<td_api::Object> do_static_request(td_api::getMarkdownText &request);
static td_api::object_ptr<td_api::Object> do_static_request(const td_api::getFileMimeType &request);
static td_api::object_ptr<td_api::Object> do_static_request(const td_api::getFileExtension &request);
static td_api::object_ptr<td_api::Object> do_static_request(const td_api::cleanFileName &request);

View File

@ -27,7 +27,7 @@ class GetTermsOfServiceUpdateQuery : public Td::ResultHandler {
void send() {
// we don't poll terms of service before authorization
send_query(G()->net_query_creator().create(create_storer(telegram_api::help_getTermsOfServiceUpdate())));
send_query(G()->net_query_creator().create(telegram_api::help_getTermsOfServiceUpdate()));
}
void on_result(uint64 id, BufferSlice packet) override {
@ -66,8 +66,8 @@ class AcceptTermsOfServiceQuery : public Td::ResultHandler {
}
void send(string terms_of_service_id) {
send_query(G()->net_query_creator().create(create_storer(telegram_api::help_acceptTermsOfService(
telegram_api::make_object<telegram_api::dataJSON>(std::move(terms_of_service_id))))));
send_query(G()->net_query_creator().create(telegram_api::help_acceptTermsOfService(
telegram_api::make_object<telegram_api::dataJSON>(std::move(terms_of_service_id)))));
}
void on_result(uint64 id, BufferSlice packet) override {
@ -100,7 +100,7 @@ TermsOfService::TermsOfService(telegram_api::object_ptr<telegram_api::help_terms
if (!clean_input_string(terms->text_)) {
terms->text_.clear();
}
entities.clear();
entities = find_entities(terms->text_, true);
}
if (terms->text_.empty()) {
id_.clear();

Some files were not shown because too many files have changed in this diff Show More