Update to tdlib 1.6.10

This commit is contained in:
Andrea Cavalli 2020-11-04 20:03:14 +01:00
commit 2e31ced59b
49 changed files with 2085 additions and 961 deletions

View File

@ -0,0 +1,14 @@
function(prevent_in_source_build)
get_filename_component(REAL_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" REALPATH)
get_filename_component(REAL_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}" REALPATH)
if (REAL_BINARY_DIR STREQUAL REAL_SOURCE_DIR)
message(" Out-of-source build must be used. Remove the files already")
message(" created by CMake and rerun CMake from a new directory:")
message(" rm -rf CMakeFiles CMakeCache.txt")
message(" mkdir build")
message(" cd build")
message(" cmake ..")
message(FATAL_ERROR "In-source build failed.")
endif()
endfunction()

145
CMake/TdSetUpCompiler.cmake Normal file
View File

@ -0,0 +1,145 @@
# - Configures C++14 compiler, setting TDLib-specific compilation options.
function(td_set_up_compiler)
set(CMAKE_EXPORT_COMPILE_COMMANDS 1 PARENT_SCOPE)
set(CMAKE_POSITION_INDEPENDENT_CODE ON PARENT_SCOPE)
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(GCC 1)
set(GCC 1 PARENT_SCOPE)
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CLANG 1)
set(CLANG 1 PARENT_SCOPE)
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
set(INTEL 1)
set(INTEL 1 PARENT_SCOPE)
elseif (NOT MSVC)
message(FATAL_ERROR "Compiler isn't supported")
endif()
include(CheckCXXCompilerFlag)
if (GCC OR CLANG OR INTEL)
if (WIN32 AND INTEL)
set(STD14_FLAG /Qstd=c++14)
else()
set(STD14_FLAG -std=c++14)
endif()
check_cxx_compiler_flag(${STD14_FLAG} HAVE_STD14)
if (NOT HAVE_STD14)
string(REPLACE "c++14" "c++1y" STD14_FLAG "${STD14_FLAG}")
check_cxx_compiler_flag(${STD14_FLAG} HAVE_STD1Y)
set(HAVE_STD14 ${HAVE_STD1Y})
endif()
elseif (MSVC)
set(HAVE_STD14 MSVC_VERSION>=1900)
endif()
if (NOT HAVE_STD14)
message(FATAL_ERROR "No C++14 support in the compiler. Please upgrade the compiler.")
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
if (MSVC)
if (CMAKE_CXX_FLAGS_DEBUG MATCHES "/RTC1")
string(REPLACE "/RTC1" " " CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
endif()
add_definitions(-D_SCL_SECURE_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /utf-8 /GR- /W4 /wd4100 /wd4127 /wd4324 /wd4505 /wd4814 /wd4702 /bigobj")
elseif (CLANG OR GCC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${STD14_FLAG} -fno-omit-frame-pointer -fno-exceptions -fno-rtti")
if (APPLE)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-dead_strip,-x,-S")
else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffunction-sections -fdata-sections")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--gc-sections -Wl,--exclude-libs,ALL")
endif()
if (WIN32 OR CYGWIN)
if (GCC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wa,-mbig-obj")
endif()
endif()
elseif (INTEL)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${STD14_FLAG}")
endif()
if (WIN32)
add_definitions(-DNTDDI_VERSION=0x06020000 -DWINVER=0x0602 -D_WIN32_WINNT=0x0602 -DPSAPI_VERSION=1 -DNOMINMAX -DUNICODE -D_UNICODE -DWIN32_LEAN_AND_MEAN)
endif()
if (CYGWIN)
add_definitions(-D_DEFAULT_SOURCE=1 -DFD_SETSIZE=4096)
endif()
if (NOT ANDROID) # _FILE_OFFSET_BITS is broken in NDK r15, r15b and r17 and doesn't work prior to Android 7.0
add_definitions(-D_FILE_OFFSET_BITS=64)
endif()
include(AddCXXCompilerFlag)
if (NOT MSVC)
add_cxx_compiler_flag("-Wall")
add_cxx_compiler_flag("-Wextra")
add_cxx_compiler_flag("-Wimplicit-fallthrough=2")
add_cxx_compiler_flag("-Wpointer-arith")
add_cxx_compiler_flag("-Wcast-qual")
add_cxx_compiler_flag("-Wsign-compare")
add_cxx_compiler_flag("-Wduplicated-branches")
add_cxx_compiler_flag("-Wduplicated-cond")
add_cxx_compiler_flag("-Walloc-zero")
add_cxx_compiler_flag("-Wlogical-op")
add_cxx_compiler_flag("-Wno-tautological-compare")
add_cxx_compiler_flag("-Wpointer-arith")
add_cxx_compiler_flag("-Wvla")
add_cxx_compiler_flag("-Wnon-virtual-dtor")
add_cxx_compiler_flag("-Wno-unused-parameter")
add_cxx_compiler_flag("-Wconversion")
add_cxx_compiler_flag("-Wno-sign-conversion")
add_cxx_compiler_flag("-Wc++14-compat-pedantic")
add_cxx_compiler_flag("-Wdeprecated")
add_cxx_compiler_flag("-Wno-unused-command-line-argument")
add_cxx_compiler_flag("-Qunused-arguments")
add_cxx_compiler_flag("-Wodr")
add_cxx_compiler_flag("-flto-odr-type-merging")
# add_cxx_compiler_flag("-Werror")
# add_cxx_compiler_flag("-Wcast-align")
#std::int32_t <-> int and off_t <-> std::size_t/std::int64_t
# add_cxx_compiler_flag("-Wuseless-cast")
#external headers like openssl
# add_cxx_compiler_flag("-Wzero-as-null-pointer-constant")
endif()
if (GCC AND NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.0))
add_cxx_compiler_flag("-Wno-maybe-uninitialized") # too much false positives
endif()
if (GCC AND NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.0))
# warns about a lot of "return std::move", which are not redundant for compilers without fix for DR 1579, i.e. GCC 4.9 or clang 3.8
# 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++")
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread")
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined")
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=leak")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" PARENT_SCOPE)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}" PARENT_SCOPE)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}" PARENT_SCOPE)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" PARENT_SCOPE)
endfunction()

View File

@ -1,6 +1,11 @@
cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR)
project(TDLib VERSION 1.6.9 LANGUAGES CXX C)
project(TDLib VERSION 1.6.10 LANGUAGES CXX C)
if (NOT DEFINED CMAKE_MODULE_PATH)
set(CMAKE_MODULE_PATH "")
endif()
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake" "${CMAKE_MODULE_PATH}")
if (NOT DEFINED CMAKE_INSTALL_LIBDIR)
set(CMAKE_INSTALL_LIBDIR "lib")
@ -17,20 +22,8 @@ if (POLICY CMP0054)
cmake_policy(SET CMP0054 NEW)
endif()
# Prevent in-source build
get_filename_component(TD_REAL_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" REALPATH)
get_filename_component(TD_REAL_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}" REALPATH)
if (TD_REAL_BINARY_DIR STREQUAL TD_REAL_SOURCE_DIR)
message(" Out-of-source build should be used to build TDLib.")
message(" You need to remove the files already created by CMake and")
message(" rerun CMake from a new directory:")
message(" rm -rf CMakeFiles CMakeCache.txt")
message(" mkdir build")
message(" cd build")
message(" cmake ..")
message(FATAL_ERROR "In-source build failed.")
endif()
include(PreventInSourceBuild)
prevent_in_source_build()
option(TD_ENABLE_JNI "Use \"ON\" to enable JNI-compatible TDLib API.")
option(TD_ENABLE_DOTNET "Use \"ON\" to enable generation of C++/CLI or C++/CX TDLib API bindings.")
@ -39,15 +32,6 @@ if (TD_ENABLE_DOTNET AND (CMAKE_VERSION VERSION_LESS "3.1.0"))
message(FATAL_ERROR "CMake 3.1.0 or higher is required. You are running version ${CMAKE_VERSION}.")
endif()
if (NOT DEFINED CMAKE_MODULE_PATH)
set(CMAKE_MODULE_PATH "")
endif()
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake" "${CMAKE_MODULE_PATH}")
set(CMAKE_EXPORT_COMPILE_COMMANDS 1)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
enable_testing()
if (POLICY CMP0069)
@ -123,38 +107,6 @@ if (OPENSSL_FOUND)
message(STATUS "Found OpenSSL: ${OPENSSL_INCLUDE_DIR} ${OPENSSL_LIBRARIES}")
endif()
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(GCC 1)
elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CLANG 1)
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
set(INTEL 1)
elseif (NOT MSVC)
message(FATAL_ERROR "Compiler isn't supported")
endif()
include(CheckCXXCompilerFlag)
if (GCC OR CLANG OR INTEL)
if (WIN32 AND INTEL)
set(STD14_FLAG /Qstd=c++14)
else()
set(STD14_FLAG -std=c++14)
endif()
check_cxx_compiler_flag(${STD14_FLAG} HAVE_STD14)
if (NOT HAVE_STD14)
string(REPLACE "c++14" "c++1y" STD14_FLAG "${STD14_FLAG}")
check_cxx_compiler_flag(${STD14_FLAG} HAVE_STD1Y)
set(HAVE_STD14 ${HAVE_STD1Y})
endif()
elseif (MSVC)
set(HAVE_STD14 MSVC_VERSION>=1900)
endif()
if (NOT HAVE_STD14)
message(FATAL_ERROR "No C++14 support in the compiler. Please upgrade the compiler.")
endif()
set(CMAKE_THREAD_PREFER_PTHREAD ON)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
@ -163,23 +115,12 @@ if (THREADS_HAVE_PTHREAD_ARG)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
endif()
if (MSVC)
if (CMAKE_CXX_FLAGS_DEBUG MATCHES "/RTC1")
string(REPLACE "/RTC1" " " CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
endif()
add_definitions(-D_SCL_SECURE_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /utf-8 /GR- /W4 /wd4100 /wd4127 /wd4324 /wd4505 /wd4814 /wd4702")
elseif (CLANG OR GCC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${STD14_FLAG} -fno-omit-frame-pointer -fno-exceptions -fno-rtti")
if (APPLE)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-dead_strip,-x,-S")
else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ffunction-sections -fdata-sections")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--gc-sections -Wl,--exclude-libs,ALL")
endif()
include(TdSetUpCompiler)
td_set_up_compiler()
if (CLANG OR GCC)
if (MEMPROF)
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag(-no-pie CXX_NO_PIE_FLAG)
if (CXX_NO_PIE_FLAG)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -no-pie")
@ -187,78 +128,8 @@ elseif (CLANG OR GCC)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-no_pie")
endif()
endif()
elseif (INTEL)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${STD14_FLAG}")
endif()
if (WIN32)
add_definitions(-DNTDDI_VERSION=0x06020000 -DWINVER=0x0602 -D_WIN32_WINNT=0x0602 -DPSAPI_VERSION=1 -DNOMINMAX -DUNICODE -D_UNICODE -DWIN32_LEAN_AND_MEAN)
endif()
if (CYGWIN)
add_definitions(-D_DEFAULT_SOURCE=1 -DFD_SETSIZE=4096)
endif()
if (NOT ANDROID) # _FILE_OFFSET_BITS is broken in NDK r15, r15b and r17 and doesn't work prior to Android 7.0
add_definitions(-D_FILE_OFFSET_BITS=64)
endif()
include(AddCXXCompilerFlag)
if (NOT MSVC)
add_cxx_compiler_flag("-Wall")
add_cxx_compiler_flag("-Wextra")
add_cxx_compiler_flag("-Wimplicit-fallthrough=2")
add_cxx_compiler_flag("-Wpointer-arith")
add_cxx_compiler_flag("-Wcast-qual")
add_cxx_compiler_flag("-Wsign-compare")
add_cxx_compiler_flag("-Wduplicated-branches")
add_cxx_compiler_flag("-Wduplicated-cond")
add_cxx_compiler_flag("-Walloc-zero")
add_cxx_compiler_flag("-Wlogical-op")
add_cxx_compiler_flag("-Wno-tautological-compare")
add_cxx_compiler_flag("-Wpointer-arith")
add_cxx_compiler_flag("-Wvla")
add_cxx_compiler_flag("-Wnon-virtual-dtor")
add_cxx_compiler_flag("-Wno-unused-parameter")
add_cxx_compiler_flag("-Wconversion")
add_cxx_compiler_flag("-Wno-sign-conversion")
add_cxx_compiler_flag("-Wc++14-compat-pedantic")
add_cxx_compiler_flag("-Wdeprecated")
add_cxx_compiler_flag("-Wno-unused-command-line-argument")
add_cxx_compiler_flag("-Qunused-arguments")
add_cxx_compiler_flag("-Wodr")
add_cxx_compiler_flag("-flto-odr-type-merging")
# add_cxx_compiler_flag("-Werror")
# add_cxx_compiler_flag("-Wcast-align")
#std::int32_t <-> int and off_t <-> std::size_t/std::int64_t
# add_cxx_compiler_flag("-Wuseless-cast")
#external headers like openssl
# add_cxx_compiler_flag("-Wzero-as-null-pointer-constant")
endif()
if (GCC AND NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.0))
add_cxx_compiler_flag("-Wno-maybe-uninitialized") # too much false positives
endif()
if (GCC AND NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.0))
# warns about a lot of "return std::move", which are not redundant for compilers without fix for DR 1579, i.e. GCC 4.9 or clang 3.8
# 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++")
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread")
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined")
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=leak")
add_subdirectory(tdtl)
add_subdirectory(tdutils)
@ -906,26 +777,6 @@ target_include_directories(tdjson_static PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
set(BIGOBJ)
if (WIN32 OR CYGWIN)
if (MSVC)
set(BIGOBJ "/bigobj")
elseif (GCC)
set(BIGOBJ "-Wa,-mbig-obj")
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})
target_compile_options(tdjson PUBLIC ${BIGOBJ})
target_compile_options(tdjson_static PUBLIC ${BIGOBJ})
if (TD_ENABLE_DOTNET)
target_compile_options(tddotnet PUBLIC "/bigobj")
endif()
endif()
if (EMSCRIPTEN)
set(TD_EMSCRIPTEN_SRC td/telegram/td_emscripten.cpp)
add_executable(${TD_EMSCRIPTEN} ${TD_EMSCRIPTEN_SRC})

View File

@ -206,7 +206,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.6.9 REQUIRED)
find_package(Td 1.6.10 REQUIRED)
target_link_libraries(YourTarget PRIVATE Td::TdStatic)
```
See [example/cpp/CMakeLists.txt](https://github.com/tdlib/td/tree/master/example/cpp/CMakeLists.txt).

View File

@ -14,34 +14,32 @@ select.large { font-size: large; }
<body onpopstate="onLoad(false)">
<div class="main">
<div align="center">
<div id="languageSelectDiv">
<p>Choose a programming language, from which you want to use TDLib:</p>
<select id="languageSelect" onchange="onLanguageChanged(false)" autofocus="true" class="large">
<option>Choose a programming language:</option>
<option>Python</option>
<option>JavaScript</option>
<option>Go</option>
<option>Java</option>
<option>Kotlin</option>
<option>C#</option>
<option>C++</option>
<option>Swift</option>
<option>Objective-C</option>
<option>Object Pascal</option>
<option>Dart</option>
<option>Rust</option>
<option>Erlang</option>
<option>PHP</option>
<option>Lua</option>
<option>Ruby</option>
<option>Clojure</option>
<option>D</option>
<option>Elixir</option>
<option>C</option>
<option>Other</option>
</select>
</div>
<div id="languageSelectDiv" align="center">
<p>Choose a programming language, from which you want to use TDLib:</p>
<select id="languageSelect" onchange="onLanguageChanged(false)" autofocus="true" class="large">
<option>Choose a programming language:</option>
<option>Python</option>
<option>JavaScript</option>
<option>Go</option>
<option>Java</option>
<option>Kotlin</option>
<option>C#</option>
<option>C++</option>
<option>Swift</option>
<option>Objective-C</option>
<option>Object Pascal</option>
<option>Dart</option>
<option>Rust</option>
<option>Erlang</option>
<option>PHP</option>
<option>Lua</option>
<option>Ruby</option>
<option>Clojure</option>
<option>D</option>
<option>Elixir</option>
<option>C</option>
<option>Other</option>
</select>
</div>
<div id="osSelectDiv" class="hide" align="center">
@ -52,24 +50,24 @@ select.large { font-size: large; }
<p></p>
</div>
<div id="buildOptionsDiv" class="hide" align="center">
<div id="linuxSelectDiv" class="hide">
<p>Choose a Linux distro, on which you want to use TDLib:</p>
<select id="linuxSelect" onchange="onOptionsChanged()" class="large">
<option>Choose a Linux distro:</option>
<option>Alpine</option>
<option>Debian 8</option>
<option>Debian 9</option>
<option>Debian 10</option>
<option>Ubuntu 14</option>
<option>Ubuntu 16</option>
<option>Ubuntu 18</option>
<option>Ubuntu 20</option>
<option>Other</option>
</select>
<p></p>
</div>
<div id="linuxSelectDiv" class="hide" align="center">
<p>Choose a Linux distro, on which you want to use TDLib:</p>
<select id="linuxSelect" onchange="onOsChanged()" class="large">
<option>Choose a Linux distro:</option>
<option>Alpine</option>
<option>Debian 8</option>
<option>Debian 9</option>
<option>Debian 10</option>
<option>Ubuntu 14</option>
<option>Ubuntu 16</option>
<option>Ubuntu 18</option>
<option>Ubuntu 20</option>
<option>Other</option>
</select>
<p></p>
</div>
<div id="buildOptionsDiv" class="hide" align="center">
<div id="buildLtoDiv" class="hide">
<label><input type="checkbox" id="buildLtoCheckbox" onchange="onOptionsChanged()"/>Enable Link Time Optimization (requires CMake >= 3.9.0). It can significantly reduce binary size and increase performance, but sometimes it can lead to build failures.</label>
</div>
@ -150,13 +148,13 @@ function onLoad(initial) {
language = 'c#';
} else if (language === 'cxx') {
language = 'c++';
} else if (!language) {
language = '';
}
var language_options = document.getElementById('languageSelect').options;
for (var i = 0; i < language_options.length; i++) {
if (language_options[i].text.toLowerCase() === language.toLowerCase()) {
language_options[i].selected = true;
}
language_options[i].selected = language_options[i].text.toLowerCase() === language.toLowerCase();
}
onLanguageChanged(initial || !history.state);
@ -335,11 +333,27 @@ function onOsChanged() {
document.getElementById('buildText').innerHTML = text;
if (!target) {
document.getElementById('linuxSelectDiv').style.display = 'none';
document.getElementById('buildOptionsDiv').style.display = 'none';
document.getElementById('buildCommandsDiv').style.display = 'none';
return;
}
var os_linux = os.includes('Linux');
if (os_linux) {
document.getElementById('linuxSelectDiv').style.display = 'block';
var linux_distro = document.getElementById('linuxSelect').value;
if (linux_distro.includes('Choose ')) {
document.getElementById('buildTextDiv').style.display = 'none';
document.getElementById('buildOptionsDiv').style.display = 'none';
document.getElementById('buildCommandsDiv').style.display = 'none';
return;
}
} else {
document.getElementById('linuxSelectDiv').style.display = 'none';
}
document.getElementById('buildOptionsDiv').style.display = 'block';
onOptionsChanged();
@ -357,18 +371,11 @@ function onOptionsChanged() {
var os_openbsd = os.includes('OpenBSD');
var os_netbsd = os.includes('NetBSD');
var display_commands = 'block';
var linux_distro = 'none';
if (os_linux) {
document.getElementById('linuxSelectDiv').style.display = 'block';
linux_distro = document.getElementById('linuxSelect').value;
if (linux_distro.indexOf('Choose') === 0) {
display_commands = 'none';
}
} else {
document.getElementById('linuxSelectDiv').style.display = 'none';
}
document.getElementById('buildCommandsDiv').style.display = display_commands;
document.getElementById('buildCommandsDiv').style.display = 'block';
var use_clang = os_freebsd || os_openbsd;
if (os_linux && linux_distro !== 'Alpine') {
@ -821,10 +828,10 @@ function onOptionsChanged() {
build_command += ' --target install';
}
if (use_msvc) {
if (target === 'C++/CX' || target === 'C++/CLI' || !is_debug_build) {
if (target === 'C++/CLI' || !is_debug_build) {
commands.push(build_command + ' --config Release');
}
if (target === 'C++/CX' || target === 'C++/CLI' || is_debug_build) {
if (target === 'C++/CLI' || is_debug_build) {
commands.push(build_command + ' --config Debug');
}
} else {

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.6.9 REQUIRED)
find_package(Td 1.6.10 REQUIRED)
add_executable(tdjson_example tdjson_example.cpp)
target_link_libraries(tdjson_example PRIVATE Td::TdJson)

View File

@ -172,7 +172,7 @@ class TdExample {
}
}
std::string get_user_name(std::int32_t user_id) {
std::string get_user_name(std::int32_t user_id) const {
auto it = users_.find(user_id);
if (it == users_.end()) {
return "unknown user";
@ -180,6 +180,14 @@ class TdExample {
return it->second->first_name_ + " " + it->second->last_name_;
}
std::string get_chat_title(std::int64_t chat_id) const {
auto it = chat_title_.find(chat_id);
if (it == chat_title_.end()) {
return "unknown chat";
}
return it->second;
}
void process_update(td_api::object_ptr<td_api::Object> update) {
td_api::downcast_call(
*update, overloaded(
@ -199,13 +207,21 @@ class TdExample {
},
[this](td_api::updateNewMessage &update_new_message) {
auto chat_id = update_new_message.message_->chat_id_;
auto sender_user_name = get_user_name(update_new_message.message_->sender_user_id_);
std::string sender_name;
td_api::downcast_call(*update_new_message.message_->sender_,
overloaded(
[this, &sender_name](td_api::messageSenderUser &user) {
sender_name = get_user_name(user.user_id_);
},
[this, &sender_name](td_api::messageSenderChat &chat) {
sender_name = get_chat_title(chat.chat_id_);
}));
std::string text;
if (update_new_message.message_->content_->get_id() == td_api::messageText::ID) {
text = static_cast<td_api::messageText &>(*update_new_message.message_->content_).text_->text_;
}
std::cout << "Got message: [chat_id:" << chat_id << "] [from:" << sender_user_name << "] ["
<< text << "]" << std::endl;
std::cout << "Got message: [chat_id:" << chat_id << "] [from:" << sender_name << "] [" << text
<< "]" << std::endl;
},
[](auto &update) {}));
}

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.6.9" Language="en-US" Publisher="Telegram LLC" />
<Identity Id="Telegram.Td.UWP" Version="1.6.10" 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

@ -293,7 +293,8 @@ voiceNote duration:int32 waveform:bytes mime_type:string voice:file = VoiceNote;
contact phone_number:string first_name:string last_name:string vcard:string user_id:int32 = Contact;
//@description Describes a location on planet Earth @latitude Latitude of the location in degrees; as defined by the sender @longitude Longitude of the location, in degrees; as defined by the sender
location latitude:double longitude:double = Location;
//@horizontal_accuracy The estimated horizontal accuracy of the location, in meters; as defined by the sender. 0 if unknown
location latitude:double longitude:double horizontal_accuracy:double = Location;
//@description Describes a venue @location Venue location; as defined by the sender @title Venue name; as defined by the sender @address Venue address; as defined by the sender @provider Provider of the venue database; as defined by the sender. Currently only "foursquare" and "gplaces" (Google Places) need to be supported
//@id Identifier of the venue in the provider database; as defined by the sender @type Type of the venue in the provider database; as defined by the sender
@ -405,6 +406,7 @@ user id:int32 first_name:string last_name:string username:string phone_number:st
//@description Contains full information about a user
//@photo User profile photo; may be null
//@is_blocked True, if the user is blocked by the current user
//@can_be_called True, if the user can be called
//@supports_video_calls True, if a video call can be created with the user
//@has_private_calls True, if the user can't be called due to their privacy settings
@ -412,7 +414,7 @@ user id:int32 first_name:string last_name:string username:string phone_number:st
//@bio A short user bio @share_text For bots, the text that is included with the link when users share the bot
//@group_in_common_count Number of group chats where both the other user and the current user are a member; 0 for the current user
//@bot_info If the user is a bot, information about the bot; may be null
userFullInfo photo:chatPhoto can_be_called:Bool supports_video_calls:Bool has_private_calls:Bool need_phone_number_privacy_exception:Bool bio:string share_text:string group_in_common_count:int32 bot_info:botInfo = UserFullInfo;
userFullInfo photo:chatPhoto is_blocked:Bool can_be_called:Bool supports_video_calls:Bool has_private_calls:Bool need_phone_number_privacy_exception:Bool bio:string share_text:string group_in_common_count:int32 bot_info:botInfo = UserFullInfo;
//@description Represents a list of users @total_count Approximate total count of users found @user_ids A list of user identifiers
users total_count:int32 user_ids:vector<int32> = Users;
@ -498,6 +500,9 @@ chatMembersFilterAdministrators = ChatMembersFilter;
//@description Returns all chat members, including restricted chat members
chatMembersFilterMembers = ChatMembersFilter;
//@description Returns users which can be mentioned in the chat @message_thread_id If non-zero, the identifier of the current message thread
chatMembersFilterMention message_thread_id:int53 = ChatMembersFilter;
//@description Returns users under certain restrictions in the chat; can be used only by administrators in a supergroup
chatMembersFilterRestricted = ChatMembersFilter;
@ -528,6 +533,9 @@ supergroupMembersFilterRestricted query:string = SupergroupMembersFilter;
//@description Returns users banned from the supergroup or channel; can be used only by administrators @query Query to search for
supergroupMembersFilterBanned query:string = SupergroupMembersFilter;
//@description Returns users which can be mentioned in the supergroup @query Query to search for @message_thread_id If non-zero, the identifier of the current message thread
supergroupMembersFilterMention query:string message_thread_id:int53 = SupergroupMembersFilter;
//@description Returns bot members of the supergroup or channel
supergroupMembersFilterBots = SupergroupMembersFilter;
@ -613,15 +621,30 @@ secretChatStateClosed = SecretChatState;
secretChat id:int32 user_id:int32 state:SecretChatState is_outbound:Bool ttl:int32 key_hash:bytes layer:int32 = SecretChat;
//@class MessageSender @description Contains information about the sender of a message
//@description The message was sent by a known user @user_id Identifier of the user that sent the message
messageSenderUser user_id:int32 = MessageSender;
//@description The message was sent on behalf of a chat @chat_id Identifier of the chat that sent the message
messageSenderChat chat_id:int53 = MessageSender;
//@description Represents a list of message senders @total_count Approximate total count of messages senders found @senders List of message senders
messageSenders total_count:int32 senders:vector<MessageSender> = MessageSenders;
//@class MessageForwardOrigin @description Contains information about the origin of a forwarded message
//@description The message was originally written by a known user @sender_user_id Identifier of the user that originally sent the message
//@description The message was originally sent by a known user @sender_user_id Identifier of the user that originally sent the message
messageForwardOriginUser sender_user_id:int32 = MessageForwardOrigin;
//@description The message was originally written by an anonymous chat administrator on behalf of the chat @sender_chat_id Identifier of the chat that originally sent the message
messageForwardOriginChat sender_chat_id:int53 = MessageForwardOrigin;
//@description The message was originally sent by an anonymous chat administrator on behalf of the chat
//@sender_chat_id Identifier of the chat that originally sent the message
//@author_signature Original message author signature
messageForwardOriginChat sender_chat_id:int53 author_signature:string = MessageForwardOrigin;
//@description The message was originally written by a user, which is hidden by their privacy settings @sender_name Name of the sender
//@description The message was originally sent by a user, which is hidden by their privacy settings @sender_name Name of the sender
messageForwardOriginHiddenUser sender_name:string = MessageForwardOrigin;
//@description The message was originally a post in a channel
@ -641,11 +664,11 @@ messageForwardInfo origin:MessageForwardOrigin date:int32 public_service_announc
//@description Contains information about message replies
//@reply_count Number of times the message was directly or indirectly replied
//@recent_replier_user_ids User identifiers of the recent repliers to the message; available in channels with a discussion supergroup
//@recent_repliers Recent repliers to the message; available in channels with a discussion supergroup
//@last_read_inbox_message_id Identifier of the last read incoming reply to the message
//@last_read_outbox_message_id Identifier of the last read outgoing reply to the message
//@last_message_id Identifier of the last reply to the message
messageReplyInfo reply_count:int32 recent_replier_user_ids:vector<int32> last_read_inbox_message_id:int53 last_read_outbox_message_id:int53 last_message_id:int53 = MessageReplyInfo;
messageReplyInfo reply_count:int32 recent_repliers:vector<MessageSender> last_read_inbox_message_id:int53 last_read_outbox_message_id:int53 last_message_id:int53 = MessageReplyInfo;
//@description Contains information about interactions with a message
//@view_count Number of times the message was viewed
@ -666,12 +689,12 @@ messageSendingStateFailed error_code:int32 error_message:string can_retry:Bool r
//@description Describes a message
//@id Message identifier; unique for the chat to which the message belongs
//@sender_user_id Identifier of the user who sent the message; 0 if unknown. Currently, it is unknown for channel posts, for channel posts automatically forwarded to discussion group and for anonymously sent supergroup messages
//@sender_chat_id Identifier of the chat on behalf of which the message was sent; 0 if none
//@sender The sender of the message
//@chat_id Chat identifier
//@sending_state Information about the sending state of the message; may be null
//@scheduling_state Information about the scheduling state of the message; may be null
//@is_outgoing True, if the message is outgoing
//@is_pinned True, if the message is pinned
//@can_be_edited True, if the message can be edited. For live location and poll messages this fields shows whether editMessageLiveLocation or stopPoll can be used with this message by the application
//@can_be_forwarded True, if the message can be forwarded
//@can_be_deleted_only_for_self True, if the message can be deleted only for the current user while other users will continue to see it
@ -690,12 +713,12 @@ messageSendingStateFailed error_code:int32 error_message:string can_retry:Bool r
//@ttl For self-destructing messages, the message's TTL (Time To Live), in seconds; 0 if none. TDLib will send updateDeleteMessages or updateMessageContent once the TTL expires
//@ttl_expires_in Time left before the message expires, in seconds
//@via_bot_user_id If non-zero, the user identifier of the bot through which this message was sent
//@author_signature For channel posts, optional author signature
//@author_signature For channel posts and anonymous administrator messages, optional author signature
//@media_album_id Unique identifier of an album this message belongs to. Only photos and videos can be grouped together in albums
//@restriction_reason If non-empty, contains a human-readable description of the reason why access to this message must be restricted
//@content Content of the message
//@reply_markup Reply markup for the message; may be null
message id:int53 sender_user_id:int32 sender_chat_id:int53 chat_id:int53 sending_state:MessageSendingState scheduling_state:MessageSchedulingState is_outgoing:Bool can_be_edited:Bool can_be_forwarded:Bool can_be_deleted_only_for_self:Bool can_be_deleted_for_all_users:Bool can_get_statistics:Bool can_get_message_thread:Bool is_channel_post:Bool contains_unread_mention:Bool date:int32 edit_date:int32 forward_info:messageForwardInfo interaction_info:messageInteractionInfo reply_in_chat_id:int53 reply_to_message_id:int53 message_thread_id:int53 ttl:int32 ttl_expires_in:double via_bot_user_id:int32 author_signature:string media_album_id:int64 restriction_reason:string content:MessageContent reply_markup:ReplyMarkup = Message;
message id:int53 sender:MessageSender chat_id:int53 sending_state:MessageSendingState scheduling_state:MessageSchedulingState is_outgoing:Bool is_pinned:Bool can_be_edited:Bool can_be_forwarded:Bool can_be_deleted_only_for_self:Bool can_be_deleted_for_all_users:Bool can_get_statistics:Bool can_get_message_thread:Bool is_channel_post:Bool contains_unread_mention:Bool date:int32 edit_date:int32 forward_info:messageForwardInfo interaction_info:messageInteractionInfo reply_in_chat_id:int53 reply_to_message_id:int53 message_thread_id:int53 ttl:int32 ttl_expires_in:double via_bot_user_id:int32 author_signature:string media_album_id:int64 restriction_reason:string content:MessageContent reply_markup:ReplyMarkup = Message;
//@description Contains a list of messages @total_count Approximate total count of messages found @messages List of messages; messages may be null
messages total_count:int32 messages:vector<message> = Messages;
@ -838,17 +861,16 @@ chatPosition list:ChatList order:int64 is_pinned:Bool source:ChatSource = ChatPo
//@unread_mention_count Number of unread messages with a mention/reply in the chat
//@notification_settings Notification settings for this chat
//@action_bar Describes actions which should be possible to do through a chat action bar; may be null
//@pinned_message_id Identifier of the pinned message in the chat; 0 if none
//@reply_markup_message_id Identifier of the message from which reply markup needs to be used; 0 if there is no default custom reply markup in the chat
//@draft_message A draft of a message in the chat; may be null
//@client_data Contains application-specific data associated with the chat. (For example, the chat scroll position or local chat notification settings can be stored here.) Persistent if the message database is used
chat id:int53 type:ChatType title:string photo:chatPhotoInfo permissions:chatPermissions last_message:message positions:vector<chatPosition> is_marked_as_unread:Bool is_blocked:Bool has_scheduled_messages:Bool can_be_deleted_only_for_self:Bool can_be_deleted_for_all_users:Bool can_be_reported:Bool default_disable_notification:Bool unread_count:int32 last_read_inbox_message_id:int53 last_read_outbox_message_id:int53 unread_mention_count:int32 notification_settings:chatNotificationSettings action_bar:ChatActionBar pinned_message_id:int53 reply_markup_message_id:int53 draft_message:draftMessage client_data:string = Chat;
chat id:int53 type:ChatType title:string photo:chatPhotoInfo permissions:chatPermissions last_message:message positions:vector<chatPosition> is_marked_as_unread:Bool is_blocked:Bool has_scheduled_messages:Bool can_be_deleted_only_for_self:Bool can_be_deleted_for_all_users:Bool can_be_reported:Bool default_disable_notification:Bool unread_count:int32 last_read_inbox_message_id:int53 last_read_outbox_message_id:int53 unread_mention_count:int32 notification_settings:chatNotificationSettings action_bar:ChatActionBar reply_markup_message_id:int53 draft_message:draftMessage client_data:string = Chat;
//@description Represents a list of chats @total_count Approximate total count of chats found @chat_ids List of chat identifiers
chats total_count:int32 chat_ids:vector<int53> = Chats;
//@description Describes a chat located nearby @chat_id Chat identifier @distance Distance to the chat location in meters
//@description Describes a chat located nearby @chat_id Chat identifier @distance Distance to the chat location, in meters
chatNearby chat_id:int53 distance:int32 = ChatNearby;
//@description Represents a list of chats located nearby @users_nearby List of users nearby @supergroups_nearby List of location-based supergroups nearby
@ -1570,9 +1592,11 @@ messageVideoNote video_note:videoNote is_viewed:Bool is_secret:Bool = MessageCon
//@description A voice note message @voice_note The voice note description @caption Voice note caption @is_listened True, if at least one of the recipients has listened to the voice note
messageVoiceNote voice_note:voiceNote caption:formattedText is_listened:Bool = MessageContent;
//@description A message with a location @location The location description @live_period Time relative to the message sent date until which the location can be updated, in seconds
//@description A message with a location @location The location description @live_period Time relative to the message send date, for which the location can be updated, in seconds
//@expires_in Left time for which the location can be updated, in seconds. updateMessageContent is not sent when this field changes
messageLocation location:location live_period:int32 expires_in:int32 = MessageContent;
//@heading For live locations, a direction in which the location moves, in degrees; 1-360. If 0 the direction is unknown
//@proximity_alert_radius For live locations, a maximum distance to another chat member for proximity alerts, in meters (0-100000). 0 if the notification is disabled. Available only for the message sender
messageLocation location:location live_period:int32 expires_in:int32 heading:int32 proximity_alert_radius:int32 = MessageContent;
//@description A message with information about a venue @venue The venue description
messageVenue venue:venue = MessageContent;
@ -1581,12 +1605,12 @@ messageVenue venue:venue = MessageContent;
messageContact contact:contact = MessageContent;
//@description A dice message. The dice value is randomly generated by the server
//@initial_state_sticker The animated sticker with the initial dice animation; may be null if unknown. updateMessageContent will be sent when the sticker became known
//@final_state_sticker The animated sticker with the final dice animation; may be null if unknown. updateMessageContent will be sent when the sticker became known
//@initial_state The animated stickers with the initial dice animation; may be null if unknown. updateMessageContent will be sent when the sticker became known
//@final_state The animated stickers with the final dice animation; may be null if unknown. updateMessageContent will be sent when the sticker became known
//@emoji Emoji on which the dice throw animation is based
//@value The dice value. If the value is 0, the dice don't have final state yet
//@success_animation_frame_number Number of frame after which a success animation like a shower of confetti needs to be shown on updateMessageSendSucceeded
messageDice initial_state_sticker:sticker final_state_sticker:sticker emoji:string value:int32 success_animation_frame_number:int32 = MessageContent;
messageDice initial_state:DiceStickers final_state:DiceStickers emoji:string value:int32 success_animation_frame_number:int32 = MessageContent;
//@description A message with a game @game The game description
messageGame game:game = MessageContent;
@ -1667,6 +1691,9 @@ messagePassportDataSent types:vector<PassportElementType> = MessageContent;
//@description Telegram Passport data has been received; for bots only @elements List of received Telegram Passport elements @credentials Encrypted data credentials
messagePassportDataReceived elements:vector<encryptedPassportElement> credentials:encryptedCredentials = MessageContent;
//@description A user in the chat came within proximity alert range @approacher The user or chat, which approached another user @observer The user or chat, which subscribed for the proximity alert @distance The distance between the users
messageProximityAlertTriggered approacher:MessageSender observer:MessageSender distance:int32 = MessageContent;
//@description Message content that is not supported in the current TDLib version
messageUnsupported = MessageContent;
@ -1788,7 +1815,9 @@ inputMessageVideoNote video_note:InputFile thumbnail:inputThumbnail duration:int
inputMessageVoiceNote voice_note:InputFile duration:int32 waveform:bytes caption:formattedText = InputMessageContent;
//@description A message with a location @location Location to be sent @live_period Period for which the location can be updated, in seconds; should be between 60 and 86400 for a live location and 0 otherwise
inputMessageLocation location:location live_period:int32 = InputMessageContent;
//@heading For live locations, a direction in which the location moves, in degrees; 1-360. Pass 0 if unknown
//@proximity_alert_radius For live locations, a maximum distance to another chat member for proximity alerts, in meters (0-100000). Pass 0 if the notification is disabled. Can't be enabled in channels and Saved Messages
inputMessageLocation location:location live_period:int32 heading:int32 proximity_alert_radius:int32 = InputMessageContent;
//@description A message with information about a venue @venue Venue to send
inputMessageVenue venue:venue = InputMessageContent;
@ -1872,6 +1901,9 @@ searchMessagesFilterUnreadMention = SearchMessagesFilter;
//@description Returns only failed to send messages. This filter can be used only if the message database is used
searchMessagesFilterFailedToSend = SearchMessagesFilter;
//@description Returns only pinned messages
searchMessagesFilterPinned = SearchMessagesFilter;
//@class ChatAction @description Describes the different types of activity in a chat
@ -2058,6 +2090,20 @@ phoneNumberAuthenticationSettings allow_flash_call:Bool is_current_phone_number:
animations animations:vector<animation> = Animations;
//@class DiceStickers @description Contains animated stickers which should be used for dice animation rendering
//@description A regular animated sticker @sticker The animated sticker with the dice animation
diceStickersRegular sticker:sticker = DiceStickers;
//@description Animated stickers to be combined into a slot machine
//@background The animated sticker with the slot machine background. The background animation must start playing after all reel animations finish
//@lever The animated sticker with the lever animation. The lever animation must play once in the initial dice state
//@left_reel The animated sticker with the left reel
//@center_reel The animated sticker with the center reel
//@right_reel The animated sticker with the right reel
diceStickersSlotMachine background:sticker lever:sticker left_reel:sticker center_reel:sticker right_reel:sticker = DiceStickers;
//@description Represents the result of an ImportContacts request @user_ids User identifiers of the imported contacts in the same order as they were specified in the request; 0 if the contact is not yet a registered user
//@importer_count The number of users that imported the corresponding contact; 0 for already registered users or if unavailable
importedContacts user_ids:vector<int32> importer_count:vector<int32> = ImportedContacts;
@ -2104,7 +2150,9 @@ inputInlineQueryResultDocument id:string title:string description:string documen
//@description Represents a game @id Unique identifier of the query result @game_short_name Short name of the game @reply_markup Message reply markup. Must be of type replyMarkupInlineKeyboard or null
inputInlineQueryResultGame id:string game_short_name:string reply_markup:ReplyMarkup = InputInlineQueryResult;
//@description Represents a point on the map @id Unique identifier of the query result @location Location result @live_period Amount of time relative to the message sent time until the location can be updated, in seconds @title Title of the result @thumbnail_url URL of the result thumbnail, if it exists @thumbnail_width Thumbnail width, if known @thumbnail_height Thumbnail height, if known
//@description Represents a point on the map @id Unique identifier of the query result @location Location result
//@live_period Amount of time relative to the message sent time until the location can be updated, in seconds
//@title Title of the result @thumbnail_url URL of the result thumbnail, if it exists @thumbnail_width Thumbnail width, if known @thumbnail_height Thumbnail height, if known
//@reply_markup The message reply markup. Must be of type replyMarkupInlineKeyboard or null
//@input_message_content The content of the message to be sent. Must be one of the following types: InputMessageText, InputMessageLocation, InputMessageVenue or InputMessageContact
inputInlineQueryResultLocation id:string location:location live_period:int32 title:string thumbnail_url:string thumbnail_width:int32 thumbnail_height:int32 reply_markup:ReplyMarkup input_message_content:InputMessageContent = InputInlineQueryResult;
@ -2226,8 +2274,8 @@ chatEventPollStopped message:message = ChatEventAction;
//@description A message was pinned @message Pinned message
chatEventMessagePinned message:message = ChatEventAction;
//@description A message was unpinned
chatEventMessageUnpinned = ChatEventAction;
//@description A message was unpinned @message Unpinned message
chatEventMessageUnpinned message:message = ChatEventAction;
//@description A new member joined the chat
chatEventMemberJoined = ChatEventAction;
@ -2542,7 +2590,8 @@ pushMessageContentChatJoinByLink = PushMessageContent;
pushMessageContentMessageForwards total_count:int32 = PushMessageContent;
//@description A media album @total_count Number of messages in the album @has_photos True, if the album has at least one photo @has_videos True, if the album has at least one video
pushMessageContentMediaAlbum total_count:int32 has_photos:Bool has_videos:Bool = PushMessageContent;
//@has_audios True, if the album has at least one audio file @has_documents True, if the album has at least one document
pushMessageContentMediaAlbum total_count:int32 has_photos:Bool has_videos:Bool has_audios:Bool has_documents:Bool = PushMessageContent;
//@class NotificationType @description Contains detailed information about a notification
@ -2558,12 +2607,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, or as reply_to_message_id
//@sender_user_id Sender of the message; 0 if unknown. Corresponding user may be inaccessible
//@sender_chat_id Sender chat of the message; 0 if none
//@sender The sender of the message. Corresponding user or chat 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_chat_id:int53 sender_name:string is_outgoing:Bool content:PushMessageContent = NotificationType;
notificationTypeNewPushMessage message_id:int53 sender:MessageSender sender_name:string is_outgoing:Bool content:PushMessageContent = NotificationType;
//@class NotificationGroupType @description Describes the type of notifications in a notification group
@ -3127,6 +3175,9 @@ updateMessageContent chat_id:int53 message_id:int53 new_content:MessageContent =
//@description A message was edited. Changes in the message content will come in a separate updateMessageContent @chat_id Chat identifier @message_id Message identifier @edit_date Point in time (Unix timestamp) when the message was edited @reply_markup New message reply markup; may be null
updateMessageEdited chat_id:int53 message_id:int53 edit_date:int32 reply_markup:ReplyMarkup = Update;
//@description The message pinned state was changed @chat_id Chat identifier @message_id The message identifier @is_pinned True, if the message is pinned
updateMessageIsPinned chat_id:int53 message_id:int53 is_pinned:Bool = Update;
//@description The information about interactions with a message has changed @chat_id Chat identifier @message_id Message identifier @interaction_info New information about interactions with the message; may be null
updateMessageInteractionInfo chat_id:int53 message_id:int53 interaction_info:messageInteractionInfo = Update;
@ -3188,9 +3239,6 @@ updateScopeNotificationSettings scope:NotificationSettingsScope notification_set
//@description The chat action bar was changed @chat_id Chat identifier @action_bar The new value of the action bar; may be null
updateChatActionBar chat_id:int53 action_bar:ChatActionBar = Update;
//@description The chat pinned message was changed @chat_id Chat identifier @pinned_message_id The new identifier of the pinned message; 0 if there is no pinned message in the chat
updateChatPinnedMessage chat_id:int53 pinned_message_id:int53 = Update;
//@description The default chat reply markup was changed. Can occur because new messages with reply markup were received or because an old reply markup was hidden by the user
//@chat_id Chat identifier @reply_markup_message_id Identifier of the message from which reply markup needs to be used; 0 if there is no default custom reply markup in the chat
updateChatReplyMarkup chat_id:int53 reply_markup_message_id:int53 = Update;
@ -3554,9 +3602,12 @@ getMessageLocally chat_id:int53 message_id:int53 = Message;
//@chat_id Identifier of the chat the message belongs to @message_id Identifier of the message reply to which to get
getRepliedMessage chat_id:int53 message_id:int53 = Message;
//@description Returns information about a pinned chat message @chat_id Identifier of the chat the message belongs to
//@description Returns information about a newest pinned chat message @chat_id Identifier of the chat the message belongs to
getChatPinnedMessage chat_id:int53 = Message;
//@description Returns information about a message with the callback button that originated a callback query; for bots only @chat_id Identifier of the chat the message belongs to @message_id Message identifier @callback_query_id Identifier of the callback query
getCallbackQueryMessage chat_id:int53 message_id:int53 callback_query_id:int64 = Message;
//@description Returns information about messages. If a message is not found, returns null on the corresponding position of the result @chat_id Identifier of the chat the messages belong to @message_ids Identifiers of the messages to get
getMessages chat_id:int53 message_ids:vector<int53> = Messages;
@ -3654,13 +3705,13 @@ deleteChatHistory chat_id:int53 remove_from_chat_list:Bool revoke:Bool = Ok;
//-(searchSecretMessages should be used instead), or without an enabled message database. For optimal performance the number of returned messages is chosen by the library
//@chat_id Identifier of the chat in which to search messages
//@query Query to search for
//@sender_user_id If not 0, only messages sent by the specified user will be returned. Not supported in secret chats
//@sender If not null, only messages sent by the specified sender will be returned. Not supported in secret chats
//@from_message_id Identifier of the message starting from which history must be fetched; use 0 to get results from the last message
//@offset Specify 0 to get results from exactly the from_message_id or a negative offset to get the specified message and some newer messages
//@limit The maximum number of messages to be returned; must be positive and can't be greater than 100. If the offset is negative, the limit must be greater than -offset. Fewer messages may be returned than specified by the limit, even if the end of the message history has not been reached
//@filter Filter for message content in the search results
//@message_thread_id If not 0, only messages in the specified thread will be returned; supergroups only
searchChatMessages chat_id:int53 query:string sender_user_id:int32 from_message_id:int53 offset:int32 limit:int32 filter:SearchMessagesFilter message_thread_id:int53 = Messages;
searchChatMessages chat_id:int53 query:string sender:MessageSender from_message_id:int53 offset:int32 limit:int32 filter:SearchMessagesFilter message_thread_id:int53 = Messages;
//@description Searches for messages in all chats except secret chats. Returns the results in reverse chronological order (i.e., in order of decreasing (date, chat_id, message_id)).
//-For optimal performance the number of returned messages is chosen by the library
@ -3670,7 +3721,7 @@ searchChatMessages chat_id:int53 query:string sender_user_id:int32 from_message_
//@offset_chat_id The chat identifier of the last found message, or 0 for the first request
//@offset_message_id The message identifier of the last found message, or 0 for the first request
//@limit The maximum number of messages to be returned; up to 100. Fewer messages may be returned than specified by the limit, even if the end of the message history has not been reached
//@filter Filter for message content in the search results; searchMessagesFilterCall, searchMessagesFilterMissedCall, searchMessagesFilterMention, searchMessagesFilterUnreadMention and searchMessagesFilterFailedToSend are unsupported in this function
//@filter Filter for message content in the search results; searchMessagesFilterCall, searchMessagesFilterMissedCall, searchMessagesFilterMention, searchMessagesFilterUnreadMention, searchMessagesFilterFailedToSend and searchMessagesFilterPinned are unsupported in this function
//@min_date If not 0, the minimum date of the messages to return
//@max_date If not 0, the maximum date of the messages to return
searchMessages chat_list:ChatList query:string offset_date:int32 offset_chat_id:int53 offset_message_id:int53 limit:int32 filter:SearchMessagesFilter min_date:int32 max_date:int32 = Messages;
@ -3782,9 +3833,13 @@ sendChatSetTtlMessage chat_id:int53 ttl:int32 = Message;
//@description Sends a notification about a screenshot taken in a chat. Supported only in private and secret chats @chat_id Chat identifier
sendChatScreenshotTakenNotification chat_id:int53 = Ok;
//@description Adds a local message to a chat. The message is persistent across application restarts only if the message database is used. Returns the added message @chat_id Target chat @sender_user_id Identifier of the user who will be shown as the sender of the message; may be 0 for channel posts
//@reply_to_message_id Identifier of the message to reply to or 0 @disable_notification Pass true to disable notification for the message @input_message_content The content of the message to be added
addLocalMessage chat_id:int53 sender_user_id:int32 reply_to_message_id:int53 disable_notification:Bool input_message_content:InputMessageContent = Message;
//@description Adds a local message to a chat. The message is persistent across application restarts only if the message database is used. Returns the added message
//@chat_id Target chat
//@sender The sender sender of the message
//@reply_to_message_id Identifier of the message to reply to or 0
//@disable_notification Pass true to disable notification for the message
//@input_message_content The content of the message to be added
addLocalMessage chat_id:int53 sender:MessageSender reply_to_message_id:int53 disable_notification:Bool input_message_content:InputMessageContent = Message;
//@description Deletes messages @chat_id Chat identifier @message_ids Identifiers of the messages to be deleted @revoke Pass true to try to delete messages for all chat members. Always true for supergroups, channels and secret chats
deleteMessages chat_id:int53 message_ids:vector<int53> revoke:Bool = Ok;
@ -3799,7 +3854,9 @@ editMessageText chat_id:int53 message_id:int53 reply_markup:ReplyMarkup input_me
//@description Edits the message content of a live location. Messages can be edited for a limited period of time specified in the live location. Returns the edited message after the edit is completed on the server side
//@chat_id The chat the message belongs to @message_id Identifier of the message @reply_markup The new message reply markup; for bots only @location New location content of the message; may be null. Pass null to stop sharing the live location
editMessageLiveLocation chat_id:int53 message_id:int53 reply_markup:ReplyMarkup location:location = Message;
//@heading The new direction in which the location moves, in degrees; 1-360. Pass 0 if unknown
//@proximity_alert_radius The new maximum distance for proximity alerts, in meters (0-100000). Pass 0 if the notification is disabled
editMessageLiveLocation chat_id:int53 message_id:int53 reply_markup:ReplyMarkup location:location heading:int32 proximity_alert_radius:int32 = Message;
//@description Edits the content of a message with an animation, an audio, a document, a photo or a video. The media in the message can't be replaced if the message was set to self-destruct. Media can't be replaced by self-destructing media. Media in an album can be edited only to contain a photo or a video. Returns the edited message after the edit is completed on the server side
//@chat_id The chat the message belongs to @message_id Identifier of the message @reply_markup The new message reply markup; for bots only @input_message_content New content of the message. Must be one of the following types: InputMessageAnimation, InputMessageAudio, InputMessageDocument, InputMessagePhoto or InputMessageVideo
@ -3816,8 +3873,11 @@ editMessageReplyMarkup chat_id:int53 message_id:int53 reply_markup:ReplyMarkup =
//@description Edits the text of an inline text or game message sent via a bot; for bots only @inline_message_id Inline message identifier @reply_markup The new message reply markup @input_message_content New text content of the message. Should be of type InputMessageText
editInlineMessageText inline_message_id:string reply_markup:ReplyMarkup input_message_content:InputMessageContent = Ok;
//@description Edits the content of a live location in an inline message sent via a bot; for bots only @inline_message_id Inline message identifier @reply_markup The new message reply markup @location New location content of the message; may be null. Pass null to stop sharing the live location
editInlineMessageLiveLocation inline_message_id:string reply_markup:ReplyMarkup location:location = Ok;
//@description Edits the content of a live location in an inline message sent via a bot; for bots only @inline_message_id Inline message identifier @reply_markup The new message reply markup
//@location New location content of the message; may be null. Pass null to stop sharing the live location
//@heading The new direction in which the location moves, in degrees; 1-360. Pass 0 if unknown
//@proximity_alert_radius The new maximum distance for proximity alerts, in meters (0-100000). Pass 0 if the notification is disabled
editInlineMessageLiveLocation inline_message_id:string reply_markup:ReplyMarkup location:location heading:int32 proximity_alert_radius:int32 = Ok;
//@description Edits the content of a message with an animation, an audio, a document, a photo or a video in an inline message sent via a bot; for bots only @inline_message_id Inline message identifier
//@reply_markup The new message reply markup; for bots only @input_message_content New content of the message. Must be one of the following types: InputMessageAnimation, InputMessageAudio, InputMessageDocument, InputMessagePhoto or InputMessageVideo
@ -4043,9 +4103,6 @@ setChatNotificationSettings chat_id:int53 notification_settings:chatNotification
//@description Changes the marked as unread state of a chat @chat_id Chat identifier @is_marked_as_unread New value of is_marked_as_unread
toggleChatIsMarkedAsUnread chat_id:int53 is_marked_as_unread:Bool = Ok;
//@description Changes the block state of a chat. Currently, only private chats and supergroups can be blocked @chat_id Chat identifier @is_blocked New value of is_blocked
toggleChatIsBlocked chat_id:int53 is_blocked:Bool = Ok;
//@description Changes the value of the default disable_notification parameter, used when a message is sent to a chat @chat_id Chat identifier @default_disable_notification New value of default_disable_notification
toggleChatDefaultDisableNotification chat_id:int53 default_disable_notification:Bool = Ok;
@ -4065,11 +4122,18 @@ setChatLocation chat_id:int53 location:chatLocation = Ok;
//@description Changes the slow mode delay of a chat. Available only for supergroups; requires can_restrict_members rights @chat_id Chat identifier @slow_mode_delay New slow mode delay for the chat; must be one of 0, 10, 30, 60, 300, 900, 3600
setChatSlowModeDelay chat_id:int53 slow_mode_delay:int32 = Ok;
//@description Pins a message in a chat; requires can_pin_messages rights @chat_id Identifier of the chat @message_id Identifier of the new pinned message @disable_notification True, if there should be no notification about the pinned message
pinChatMessage chat_id:int53 message_id:int53 disable_notification:Bool = Ok;
//@description Pins a message in a chat; requires can_pin_messages rights or can_edit_messages rights in the channel
//@chat_id Identifier of the chat
//@message_id Identifier of the new pinned message
//@disable_notification True, if there should be no notification about the pinned message. Notifications are always disabled in channels and private chats
//@only_for_self True, if the message needs to be pinned only for self; private chats only
pinChatMessage chat_id:int53 message_id:int53 disable_notification:Bool only_for_self:Bool = Ok;
//@description Removes the pinned message from a chat; requires can_pin_messages rights in the group or channel @chat_id Identifier of the chat
unpinChatMessage chat_id:int53 = Ok;
//@description Removes a pinned message from a chat; requires can_pin_messages rights in the group or can_edit_messages rights in the channel @chat_id Identifier of the chat @message_id Identifier of the removed pinned message
unpinChatMessage chat_id:int53 message_id:int53 = Ok;
//@description Removes all pinned messages from a chat; requires can_pin_messages rights in the group or can_edit_messages rights in the channel @chat_id Identifier of the chat
unpinAllChatMessages chat_id:int53 = Ok;
//@description Adds current user as a new member to a chat. Private and secret chats can't be joined using this method @chat_id Chat identifier
@ -4209,15 +4273,18 @@ sendCallRating call_id:int32 rating:int32 comment:string problems:vector<CallPro
sendCallDebugInformation call_id:int32 debug_information:string = Ok;
//@description Changes the block state of a message sender. Currently, only users and supergroup chats can be blocked @sender Message Sender @is_blocked New value of is_blocked
toggleMessageSenderIsBlocked sender:MessageSender is_blocked:Bool = Ok;
//@description Blocks an original sender of a message in the Replies chat
//@message_id The identifier of an incoming message in the Replies chat
//@delete_message Pass true if the message must be deleted
//@delete_all_messages Pass true if all messages from the same sender must be deleted
//@report_spam Pass true if the sender must be reported to the Telegram moderators
blockChatFromReplies message_id:int53 delete_message:Bool delete_all_messages:Bool report_spam:Bool = Ok;
blockMessageSenderFromReplies message_id:int53 delete_message:Bool delete_all_messages:Bool report_spam:Bool = Ok;
//@description Returns chats that were blocked by the current user @offset Number of chats to skip in the result; must be non-negative @limit The maximum number of chats to return; up to 100
getBlockedChats offset:int32 limit:int32 = Chats;
//@description Returns users and chats that were blocked by the current user @offset Number of users and chats to skip in the result; must be non-negative @limit The maximum number of users and chats to return; up to 100
getBlockedMessageSenders offset:int32 limit:int32 = MessageSenders;
//@description Adds a user to the contact list or edits an existing contact by their user identifier @contact The contact to add or edit; phone number can be empty and needs to be specified only if known, vCard is ignored

View File

@ -56,7 +56,7 @@ inputMediaPhotoExternal#e5bbfe1a flags:# url:string ttl_seconds:flags.0?int = In
inputMediaDocumentExternal#fb52dc99 flags:# url:string ttl_seconds:flags.0?int = InputMedia;
inputMediaGame#d33f43f3 id:InputGame = InputMedia;
inputMediaInvoice#f4e096c3 flags:# title:string description:string photo:flags.0?InputWebDocument invoice:Invoice payload:bytes provider:string provider_data:DataJSON start_param:string = InputMedia;
inputMediaGeoLive#ce4e82fd flags:# stopped:flags.0?true geo_point:InputGeoPoint period:flags.1?int = InputMedia;
inputMediaGeoLive#971fa843 flags:# stopped:flags.0?true geo_point:InputGeoPoint heading:flags.2?int period:flags.1?int proximity_notification_radius:flags.3?int = InputMedia;
inputMediaPoll#f94e5f1 flags:# poll:Poll correct_answers:flags.0?Vector<bytes> solution:flags.1?string solution_entities:flags.1?Vector<MessageEntity> = InputMedia;
inputMediaDice#e66fbf7b emoticon:string = InputMedia;
@ -65,7 +65,7 @@ inputChatUploadedPhoto#c642724e flags:# file:flags.0?InputFile video:flags.1?Inp
inputChatPhoto#8953ad37 id:InputPhoto = InputChatPhoto;
inputGeoPointEmpty#e4c123d6 = InputGeoPoint;
inputGeoPoint#f3b7acc9 lat:double long:double = InputGeoPoint;
inputGeoPoint#48222faf flags:# lat:double long:double accuracy_radius:flags.0?int = InputGeoPoint;
inputPhotoEmpty#1cd7bf0d = InputPhoto;
inputPhoto#3bb3b94a id:long access_hash:long file_reference:bytes = InputPhoto;
@ -128,7 +128,7 @@ chatPhotoEmpty#37c1011c = ChatPhoto;
chatPhoto#d20b9f3c flags:# has_video:flags.0?true photo_small:FileLocation photo_big:FileLocation dc_id:int = ChatPhoto;
messageEmpty#83e5de54 id:int = Message;
message#58ae39c9 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true legacy:flags.19?true edit_hide:flags.21?true id:int from_id:flags.8?Peer peer_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?int reply_to:flags.3?MessageReplyHeader date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> views:flags.10?int forwards:flags.10?int replies:flags.23?MessageReplies edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long restriction_reason:flags.22?Vector<RestrictionReason> = Message;
message#58ae39c9 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true legacy:flags.19?true edit_hide:flags.21?true pinned:flags.24?true id:int from_id:flags.8?Peer peer_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?int reply_to:flags.3?MessageReplyHeader date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> views:flags.10?int forwards:flags.10?int replies:flags.23?MessageReplies edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long restriction_reason:flags.22?Vector<RestrictionReason> = Message;
messageService#286fa604 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true legacy:flags.19?true id:int from_id:flags.8?Peer peer_id:Peer reply_to:flags.3?MessageReplyHeader date:int action:MessageAction = Message;
messageMediaEmpty#3ded6320 = MessageMedia;
@ -141,7 +141,7 @@ messageMediaWebPage#a32dd600 webpage:WebPage = MessageMedia;
messageMediaVenue#2ec0533f geo:GeoPoint title:string address:string provider:string venue_id:string venue_type:string = MessageMedia;
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;
messageMediaGeoLive#b940c666 flags:# geo:GeoPoint heading:flags.0?int period:int proximity_notification_radius:flags.1?int = MessageMedia;
messageMediaPoll#4bd6e798 poll:Poll results:PollResults = MessageMedia;
messageMediaDice#3f7ee58b value:int emoticon:string = MessageMedia;
@ -168,6 +168,7 @@ messageActionBotAllowed#abe9affe domain:string = MessageAction;
messageActionSecureValuesSentMe#1b287353 values:Vector<SecureValue> credentials:SecureCredentialsEncrypted = MessageAction;
messageActionSecureValuesSent#d95c6154 types:Vector<SecureValueType> = MessageAction;
messageActionContactSignUp#f3f25f76 = MessageAction;
messageActionGeoProximityReached#98e0d697 from_id:Peer to_id:Peer distance:int = MessageAction;
dialog#2c171f72 flags:# pinned:flags.2?true unread_mark:flags.3?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int notify_settings:PeerNotifySettings pts:flags.0?int draft:flags.1?DraftMessage folder_id:flags.4?int = Dialog;
dialogFolder#71bd134c flags:# pinned:flags.2?true folder:Folder peer:Peer top_message:int unread_muted_peers_count:int unread_unmuted_peers_count:int unread_muted_messages_count:int unread_unmuted_messages_count:int = Dialog;
@ -182,7 +183,7 @@ photoStrippedSize#e0b0bc2e type:string bytes:bytes = PhotoSize;
photoSizeProgressive#5aa86a51 type:string location:FileLocation w:int h:int sizes:Vector<int> = PhotoSize;
geoPointEmpty#1117dd5f = GeoPoint;
geoPoint#296f104 long:double lat:double access_hash:long = GeoPoint;
geoPoint#b2a2f663 flags:# long:double lat:double access_hash:long accuracy_radius:flags.0?int = GeoPoint;
auth.sentCode#5e002502 flags:# type:auth.SentCodeType phone_code_hash:string next_type:flags.1?auth.CodeType timeout:flags.2?int = auth.SentCode;
@ -234,8 +235,8 @@ messages.dialogsSlice#71e094f3 count:int dialogs:Vector<Dialog> messages:Vector<
messages.dialogsNotModified#f0e3e596 count:int = messages.Dialogs;
messages.messages#8c718e87 messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
messages.messagesSlice#c8edce1e flags:# inexact:flags.1?true count:int next_rate:flags.0?int messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
messages.channelMessages#99262e37 flags:# inexact:flags.1?true pts:int count:int messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
messages.messagesSlice#3a54685e flags:# inexact:flags.1?true count:int next_rate:flags.0?int offset_id_offset:flags.2?int messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
messages.channelMessages#64479808 flags:# inexact:flags.1?true pts:int count:int offset_id_offset:flags.2?int messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
messages.messagesNotModified#74535f21 count:int = messages.Messages;
messages.chats#64ff9fd5 chats:Vector<Chat> = messages.Chats;
@ -261,6 +262,7 @@ inputMessagesFilterRoundVideo#b549da53 = MessagesFilter;
inputMessagesFilterMyMentions#c1f8e69a = MessagesFilter;
inputMessagesFilterGeo#e7026d0d = MessagesFilter;
inputMessagesFilterContacts#e062db83 = MessagesFilter;
inputMessagesFilterPinned#1bb00451 = MessagesFilter;
updateNewMessage#1f2b0afd message:Message pts:int pts_count:int = Update;
updateMessageID#4e90bfd6 id:int random_id:long = Update;
@ -300,7 +302,6 @@ updateSavedGifs#9375341e = Update;
updateBotInlineQuery#54826690 flags:# query_id:long user_id:int query:string geo:flags.0?GeoPoint offset:string = Update;
updateBotInlineSend#e48f964 flags:# user_id:int query:string geo:flags.0?GeoPoint id:string msg_id:flags.1?InputBotInlineMessageID = Update;
updateEditChannelMessage#1b3f4df7 message:Message pts:int pts_count:int = Update;
updateChannelPinnedMessage#98592475 channel_id:int id:int = Update;
updateBotCallbackQuery#e73547e1 flags:# query_id:long user_id:int peer:Peer msg_id:int chat_instance:long data:flags.0?bytes game_short_name:flags.1?string = Update;
updateEditMessage#e40370a3 message:Message pts:int pts_count:int = Update;
updateInlineBotCallbackQuery#f9d27a5a flags:# query_id:long user_id:int msg_id:InputBotInlineMessageID chat_instance:long data:flags.0?bytes game_short_name:flags.1?string = Update;
@ -325,8 +326,6 @@ updateChannelReadMessagesContents#89893b45 channel_id:int messages:Vector<int> =
updateContactsReset#7084a7be = Update;
updateChannelAvailableMessages#70db6837 channel_id:int available_min_id:int = Update;
updateDialogUnreadMark#e16459c3 flags:# unread:flags.0?true peer:DialogPeer = Update;
updateUserPinnedMessage#4c43da18 user_id:int id:int = Update;
updateChatPinnedMessage#e10db349 chat_id:int id:int version:int = Update;
updateMessagePoll#aca1657b flags:# poll_id:long poll:flags.0?Poll results:PollResults = Update;
updateChatDefaultBannedRights#54c01850 peer:Peer default_banned_rights:ChatBannedRights version:int = Update;
updateFolderPeers#19360dc0 folder_peers:Vector<FolderPeer> pts:int pts_count:int = Update;
@ -348,6 +347,8 @@ updateReadChannelDiscussionInbox#1cc7de54 flags:# channel_id:int top_msg_id:int
updateReadChannelDiscussionOutbox#4638a26c channel_id:int top_msg_id:int read_max_id:int = Update;
updatePeerBlocked#246a4b22 peer_id:Peer blocked:Bool = Update;
updateChannelUserTyping#ff2abe9f flags:# channel_id:int top_msg_id:flags.0?int user_id:int action:SendMessageAction = Update;
updatePinnedMessages#ed85eab5 flags:# pinned:flags.0?true peer:Peer messages:Vector<int> pts:int pts_count:int = Update;
updatePinnedChannelMessages#8588878b flags:# pinned:flags.0?true channel_id:int messages:Vector<int> pts:int pts_count:int = Update;
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
@ -594,6 +595,7 @@ channelParticipantSelf#a3289a6d user_id:int inviter_id:int date:int = ChannelPar
channelParticipantCreator#447dca4b flags:# user_id:int admin_rights:ChatAdminRights rank:flags.0?string = ChannelParticipant;
channelParticipantAdmin#ccbebbaf flags:# can_edit:flags.0?true self:flags.1?true user_id:int inviter_id:flags.1?int promoted_by:int date:int admin_rights:ChatAdminRights rank:flags.2?string = ChannelParticipant;
channelParticipantBanned#1c0facaf flags:# left:flags.0?true user_id:int kicked_by:int date:int banned_rights:ChatBannedRights = ChannelParticipant;
channelParticipantLeft#c3c6796b user_id:int = ChannelParticipant;
channelParticipantsRecent#de3f3c79 = ChannelParticipantsFilter;
channelParticipantsAdmins#b4608969 = ChannelParticipantsFilter;
@ -602,6 +604,7 @@ channelParticipantsBots#b0d1865b = ChannelParticipantsFilter;
channelParticipantsBanned#1427a5e1 q:string = ChannelParticipantsFilter;
channelParticipantsSearch#656ac4b q:string = ChannelParticipantsFilter;
channelParticipantsContacts#bb6ae88d q:string = ChannelParticipantsFilter;
channelParticipantsMentions#e04b5ceb flags:# q:flags.0?string top_msg_id:flags.1?int = ChannelParticipantsFilter;
channels.channelParticipants#f56ee2a8 count:int participants:Vector<ChannelParticipant> users:Vector<User> = channels.ChannelParticipants;
channels.channelParticipantsNotModified#f0173fe9 = channels.ChannelParticipants;
@ -615,7 +618,7 @@ messages.savedGifs#2e0709a5 hash:int gifs:Vector<Document> = messages.SavedGifs;
inputBotInlineMessageMediaAuto#3380c786 flags:# message:string entities:flags.1?Vector<MessageEntity> reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
inputBotInlineMessageText#3dcd7a87 flags:# no_webpage:flags.0?true message:string entities:flags.1?Vector<MessageEntity> reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
inputBotInlineMessageMediaGeo#c1b15d65 flags:# geo_point:InputGeoPoint period:int reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
inputBotInlineMessageMediaGeo#96929a85 flags:# geo_point:InputGeoPoint heading:flags.0?int period:flags.1?int proximity_notification_radius:flags.3?int reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
inputBotInlineMessageMediaVenue#417bbf11 flags:# geo_point:InputGeoPoint title:string address:string provider:string venue_id:string venue_type:string reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
inputBotInlineMessageMediaContact#a6edbffd flags:# phone_number:string first_name:string last_name:string vcard:string reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
inputBotInlineMessageGame#4b425864 flags:# reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
@ -627,7 +630,7 @@ inputBotInlineResultGame#4fa417f2 id:string short_name:string send_message:Input
botInlineMessageMediaAuto#764cf810 flags:# message:string entities:flags.1?Vector<MessageEntity> reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
botInlineMessageText#8c7f65e2 flags:# no_webpage:flags.0?true message:string entities:flags.1?Vector<MessageEntity> reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
botInlineMessageMediaGeo#b722de65 flags:# geo:GeoPoint period:int reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
botInlineMessageMediaGeo#51846fd flags:# geo:GeoPoint heading:flags.0?int period:flags.1?int proximity_notification_radius:flags.3?int reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
botInlineMessageMediaVenue#8a86659c flags:# geo:GeoPoint title:string address:string provider:string venue_id:string venue_type:string reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
botInlineMessageMediaContact#18d1cdc2 flags:# phone_number:string first_name:string last_name:string vcard:string reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
@ -886,6 +889,7 @@ account.webAuthorizations#ed56c9fc authorizations:Vector<WebAuthorization> users
inputMessageID#a676a322 id:int = InputMessage;
inputMessageReplyTo#bad88395 id:int = InputMessage;
inputMessagePinned#86872538 = InputMessage;
inputMessageCallbackQuery#acfa1a7e id:int query_id:long = InputMessage;
inputDialogPeer#fcaafeb7 peer:InputPeer = InputDialogPeer;
inputDialogPeerFolder#64600527 folder_id:int = InputDialogPeer;
@ -1151,8 +1155,6 @@ messageViews#455b853d flags:# views:flags.0?int forwards:flags.1?int replies:fla
messages.messageViews#b6c4f543 views:Vector<MessageViews> chats:Vector<Chat> users:Vector<User> = messages.MessageViews;
stats.messageStats#8999f295 views_graph:StatsGraph = stats.MessageStats;
messages.discussionMessage#f5dd8f9d flags:# messages:Vector<Message> max_id:flags.0?int read_inbox_max_id:flags.1?int read_outbox_max_id:flags.2?int chats:Vector<Chat> users:Vector<User> = messages.DiscussionMessage;
messageReplyHeader#a6d57763 flags:# reply_to_msg_id:int reply_to_peer_id:flags.0?Peer reply_to_top_id:flags.1?int = MessageReplyHeader;
@ -1161,6 +1163,8 @@ messageReplies#4128faac flags:# comments:flags.0?true replies:int replies_pts:in
peerBlocked#e8fd8014 peer_id:Peer date:int = PeerBlocked;
stats.messageStats#8999f295 views_graph:StatsGraph = stats.MessageStats;
---functions---
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
@ -1286,7 +1290,7 @@ contacts.blockFromReplies#29a8962c flags:# delete_message:flags.0?true delete_hi
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;
messages.getHistory#dcbb8260 peer:InputPeer offset_id:int offset_date:int add_offset:int limit:int max_id:int min_id:int hash:int = messages.Messages;
messages.search#4e17810b flags:# peer:InputPeer q:string from_id:flags.0?InputUser top_msg_id:flags.1?int filter:MessagesFilter min_date:int max_date:int offset_id:int add_offset:int limit:int max_id:int min_id:int hash:int = messages.Messages;
messages.search#c352eec flags:# peer:InputPeer q:string from_id:flags.0?InputPeer top_msg_id:flags.1?int filter:MessagesFilter min_date:int max_date:int offset_id:int add_offset:int limit:int max_id:int min_id:int hash:int = messages.Messages;
messages.readHistory#e306d3a peer:InputPeer max_id:int = messages.AffectedMessages;
messages.deleteHistory#1c015b09 flags:# just_clear:flags.0?true revoke:flags.1?true peer:InputPeer max_id:int = messages.AffectedHistory;
messages.deleteMessages#e58e95d2 flags:# revoke:flags.0?true id:Vector<int> = messages.AffectedMessages;
@ -1380,7 +1384,7 @@ messages.getSplitRanges#1cff7e08 = Vector<MessageRange>;
messages.markDialogUnread#c286d98f flags:# unread:flags.0?true peer:InputDialogPeer = Bool;
messages.getDialogUnreadMarks#22e24e22 = Vector<DialogPeer>;
messages.clearAllDrafts#7e58ee9c = Bool;
messages.updatePinnedMessage#d2aaf7ec flags:# silent:flags.0?true peer:InputPeer id:int = Updates;
messages.updatePinnedMessage#d2aaf7ec flags:# silent:flags.0?true unpin:flags.1?true pm_oneside:flags.2?true peer:InputPeer id:int = Updates;
messages.sendVote#10ea6184 peer:InputPeer msg_id:int options:Vector<bytes> = Updates;
messages.getPollResults#73bb643b peer:InputPeer msg_id:int = Updates;
messages.getOnlines#6e2be050 peer:InputPeer = ChatOnlines;
@ -1409,6 +1413,7 @@ messages.getOldFeaturedStickers#5fe7025b offset:int limit:int hash:int = message
messages.getReplies#24b581ba peer:InputPeer msg_id:int offset_id:int offset_date:int add_offset:int limit:int max_id:int min_id:int hash:int = messages.Messages;
messages.getDiscussionMessage#446972fd peer:InputPeer msg_id:int = messages.DiscussionMessage;
messages.readDiscussion#f731a9f4 peer:InputPeer msg_id:int read_max_id:int = Bool;
messages.unpinAllMessages#f025bc8b peer:InputPeer = messages.AffectedHistory;
updates.getState#edd4882a = updates.State;
updates.getDifference#25939651 flags:# pts:int pts_total_limit:flags.0?int date:int qts:int = updates.Difference;

Binary file not shown.

View File

@ -13,6 +13,7 @@
#include "td/utils/JsonBuilder.h"
#include "td/utils/logging.h"
#include "td/utils/port/thread_local.h"
#include "td/utils/StackAllocator.h"
#include "td/utils/StringBuilder.h"
#include <utility>
@ -54,21 +55,23 @@ static std::pair<td_api::object_ptr<td_api::Function>, string> to_request(Slice
}
static string from_response(const td_api::Object &object, const string &extra, int client_id) {
auto str = json_encode<string>(ToJson(object));
CHECK(!str.empty() && str.back() == '}');
str.reserve(str.size() + (extra.empty() ? 0 : 10 + extra.size()) + (client_id == 0 ? 0 : 14 + 10));
auto buf = StackAllocator::alloc(1 << 18);
JsonBuilder jb(StringBuilder(buf.as_slice(), true), -1);
jb.enter_value() << ToJson(object);
auto slice = jb.string_builder().as_cslice();
CHECK(!slice.empty() && slice.back() == '}');
string str;
str.reserve(slice.size() + (extra.empty() ? 0 : 10 + extra.size()) + (client_id == 0 ? 0 : 14 + 10));
str.append(slice.begin(), slice.size() - 1);
if (!extra.empty()) {
str.pop_back();
str += ",\"@extra\":";
str += extra;
str += '}';
}
if (client_id != 0) {
str.pop_back();
str += ",\"@client_id\":";
str += to_string(client_id);
str += '}';
}
str += '}';
return str;
}

View File

@ -3317,7 +3317,7 @@ void ContactsManager::UserFull::store(StorerT &storer) const {
bool has_photo = !photo.is_empty();
BEGIN_STORE_FLAGS();
STORE_FLAG(has_about);
STORE_FLAG(false);
STORE_FLAG(is_blocked);
STORE_FLAG(can_be_called);
STORE_FLAG(has_private_calls);
STORE_FLAG(can_pin_messages);
@ -3340,10 +3340,9 @@ void ContactsManager::UserFull::parse(ParserT &parser) {
using td::parse;
bool has_about;
bool has_photo;
bool legacy_is_blocked;
BEGIN_PARSE_FLAGS();
PARSE_FLAG(has_about);
PARSE_FLAG(legacy_is_blocked);
PARSE_FLAG(is_blocked);
PARSE_FLAG(can_be_called);
PARSE_FLAG(has_private_calls);
PARSE_FLAG(can_pin_messages);
@ -3359,10 +3358,6 @@ void ContactsManager::UserFull::parse(ParserT &parser) {
if (has_photo) {
parse(photo, parser);
}
if (legacy_is_blocked) {
LOG(DEBUG) << "Ignore legacy is_blocked flag";
}
}
template <class StorerT>
@ -4213,8 +4208,7 @@ RestrictedRights ContactsManager::get_user_default_permissions(UserId user_id) c
return RestrictedRights(false, false, false, false, false, false, false, false, false, false, false);
}
bool can_pin_messages = user_id == get_my_id(); /* TODO */
return RestrictedRights(true, true, true, true, true, true, true, true, false, false, can_pin_messages);
return RestrictedRights(true, true, true, true, true, true, true, true, false, false, true);
}
RestrictedRights ContactsManager::get_chat_default_permissions(ChatId chat_id) const {
@ -9165,16 +9159,12 @@ void ContactsManager::on_get_user_full(tl_object_ptr<telegram_api::userFull> &&u
td_->messages_manager_->on_update_dialog_notify_settings(DialogId(user_id), std::move(user_full->notify_settings_),
"on_get_user_full");
{
bool is_blocked = (user_full->flags_ & USER_FULL_FLAG_IS_BLOCKED) != 0;
td_->messages_manager_->on_update_dialog_is_blocked(DialogId(user_id), is_blocked);
}
{
MessageId pinned_message_id;
if ((user_full->flags_ & USER_FULL_FLAG_HAS_PINNED_MESSAGE) != 0) {
pinned_message_id = MessageId(ServerMessageId(user_full->pinned_msg_id_));
}
td_->messages_manager_->on_update_dialog_pinned_message_id(DialogId(user_id), pinned_message_id);
td_->messages_manager_->on_update_dialog_last_pinned_message_id(DialogId(user_id), pinned_message_id);
}
{
FolderId folder_id;
@ -9189,6 +9179,12 @@ void ContactsManager::on_get_user_full(tl_object_ptr<telegram_api::userFull> &&u
UserFull *user = add_user_full(user_id);
user->expires_at = Time::now() + USER_FULL_EXPIRE_TIME;
{
bool is_blocked = (user_full->flags_ & USER_FULL_FLAG_IS_BLOCKED) != 0;
on_update_user_full_is_blocked(user, user_id, is_blocked);
td_->messages_manager_->on_update_dialog_is_blocked(DialogId(user_id), is_blocked);
}
on_update_user_full_common_chat_count(user, user_id, user_full->common_chats_count_);
on_update_user_full_need_phone_number_privacy_exception(
user, user_id, (user_full->settings_->flags_ & telegram_api::peerSettings::NEED_CONTACTS_EXCEPTION_MASK) != 0);
@ -9412,7 +9408,7 @@ void ContactsManager::on_get_chat_full(tl_object_ptr<telegram_api::ChatFull> &&c
} else if (c->version >= c->pinned_message_version) {
LOG(INFO) << "Receive pinned " << pinned_message_id << " in " << chat_id << " with version " << c->version
<< ". Current version is " << c->pinned_message_version;
td_->messages_manager_->on_update_dialog_pinned_message_id(DialogId(chat_id), pinned_message_id);
td_->messages_manager_->on_update_dialog_last_pinned_message_id(DialogId(chat_id), pinned_message_id);
if (c->version > c->pinned_message_version) {
c->pinned_message_version = c->version;
c->need_save_to_database = true;
@ -9581,7 +9577,7 @@ void ContactsManager::on_get_chat_full(tl_object_ptr<telegram_api::ChatFull> &&c
if ((channel_full->flags_ & CHANNEL_FULL_FLAG_HAS_PINNED_MESSAGE) != 0) {
pinned_message_id = MessageId(ServerMessageId(channel_full->pinned_msg_id_));
}
td_->messages_manager_->on_update_dialog_pinned_message_id(DialogId(channel_id), pinned_message_id);
td_->messages_manager_->on_update_dialog_last_pinned_message_id(DialogId(channel_id), pinned_message_id);
}
{
FolderId folder_id;
@ -9974,6 +9970,29 @@ void ContactsManager::on_update_user_local_was_online(User *u, UserId user_id, i
}
}
void ContactsManager::on_update_user_is_blocked(UserId user_id, bool is_blocked) {
if (!user_id.is_valid()) {
LOG(ERROR) << "Receive invalid " << user_id;
return;
}
UserFull *user_full = get_user_full_force(user_id);
if (user_full == nullptr) {
return;
}
on_update_user_full_is_blocked(user_full, user_id, is_blocked);
update_user_full(user_full, user_id);
}
void ContactsManager::on_update_user_full_is_blocked(UserFull *user_full, UserId user_id, bool is_blocked) {
CHECK(user_full != nullptr);
if (user_full->is_blocked != is_blocked) {
LOG(INFO) << "Receive update user full is blocked with " << user_id << " and is_blocked = " << is_blocked;
user_full->is_blocked = is_blocked;
user_full->is_changed = true;
}
}
void ContactsManager::on_update_user_common_chat_count(UserId user_id, int32 common_chat_count) {
LOG(INFO) << "Receive " << common_chat_count << " common chat count with " << user_id;
if (!user_id.is_valid()) {
@ -10249,6 +10268,7 @@ void ContactsManager::drop_user_full(UserId user_id) {
user_full->expires_at = 0.0;
user_full->photo = Photo();
user_full->is_blocked = false;
user_full->can_be_called = false;
user_full->supports_video_calls = false;
user_full->has_private_calls = false;
@ -11747,7 +11767,7 @@ void ContactsManager::on_update_chat_pinned_message(ChatId chat_id, MessageId pi
c->version = version;
c->need_save_to_database = true;
}
td_->messages_manager_->on_update_dialog_pinned_message_id(DialogId(chat_id), pinned_message_id);
td_->messages_manager_->on_update_dialog_last_pinned_message_id(DialogId(chat_id), pinned_message_id);
if (version > c->pinned_message_version) {
LOG(INFO) << "Change pinned message version of " << chat_id << " from " << c->pinned_message_version << " to "
<< version;
@ -12278,9 +12298,9 @@ Result<BotData> ContactsManager::get_bot_data(UserId user_id) const {
return bot_data;
}
bool ContactsManager::is_user_online(UserId user_id) const {
bool ContactsManager::is_user_online(UserId user_id, int32 tolerance) const {
int32 was_online = get_user_was_online(get_user(user_id), user_id);
return was_online > G()->unix_time();
return was_online > G()->unix_time() - tolerance;
}
bool ContactsManager::is_user_status_exact(UserId user_id) const {
@ -12341,7 +12361,7 @@ void ContactsManager::reload_dialog_info(DialogId dialog_id, Promise<Unit> &&pro
case DialogType::Channel:
return reload_channel(dialog_id.get_channel_id(), std::move(promise));
default:
promise.set_error(Status::Error("Invalid dialog ID to reload"));
return promise.set_error(Status::Error("Invalid dialog ID to reload"));
}
}
@ -12433,7 +12453,6 @@ ContactsManager::UserFull *ContactsManager::add_user_full(UserId user_id) {
auto &user_full_ptr = users_full_[user_id];
if (user_full_ptr == nullptr) {
user_full_ptr = make_unique<UserFull>();
user_full_ptr->can_pin_messages = (user_id == get_my_id());
}
user_id.set_time();
return user_full_ptr.get();
@ -13341,18 +13360,20 @@ std::pair<int32, vector<DialogParticipant>> ContactsManager::search_chat_partici
}
auto is_dialog_participant_suitable = [this](const DialogParticipant &participant, DialogParticipantsFilter filter) {
switch (filter) {
case DialogParticipantsFilter::Contacts:
switch (filter.type) {
case DialogParticipantsFilter::Type::Contacts:
return is_user_contact(participant.user_id);
case DialogParticipantsFilter::Administrators:
case DialogParticipantsFilter::Type::Administrators:
return participant.status.is_administrator();
case DialogParticipantsFilter::Members:
case DialogParticipantsFilter::Type::Members:
return participant.status.is_member(); // should be always true
case DialogParticipantsFilter::Restricted:
case DialogParticipantsFilter::Type::Restricted:
return participant.status.is_restricted(); // should be always false
case DialogParticipantsFilter::Banned:
case DialogParticipantsFilter::Type::Banned:
return participant.status.is_banned(); // should be always false
case DialogParticipantsFilter::Bots:
case DialogParticipantsFilter::Type::Mention:
return true;
case DialogParticipantsFilter::Type::Bots:
return is_user_bot(participant.user_id);
default:
UNREACHABLE();
@ -14196,9 +14217,10 @@ tl_object_ptr<td_api::userFullInfo> ContactsManager::get_user_full_info_object(U
CHECK(user_full != nullptr);
bool is_bot = is_user_bot(user_id);
return make_tl_object<td_api::userFullInfo>(
get_chat_photo_object(td_->file_manager_.get(), user_full->photo), user_full->can_be_called,
user_full->supports_video_calls, user_full->has_private_calls, user_full->need_phone_number_privacy_exception,
is_bot ? string() : user_full->about, is_bot ? user_full->about : string(), user_full->common_chat_count,
get_chat_photo_object(td_->file_manager_.get(), user_full->photo), user_full->is_blocked,
user_full->can_be_called, user_full->supports_video_calls, user_full->has_private_calls,
user_full->need_phone_number_privacy_exception, is_bot ? string() : user_full->about,
is_bot ? user_full->about : string(), user_full->common_chat_count,
is_bot ? get_bot_info_object(user_id) : nullptr);
}

View File

@ -179,6 +179,7 @@ class ContactsManager : public Actor {
void on_update_user_photo(UserId user_id, tl_object_ptr<telegram_api::UserProfilePhoto> &&photo_ptr);
void on_update_user_online(UserId user_id, tl_object_ptr<telegram_api::UserStatus> &&status);
void on_update_user_local_was_online(UserId user_id, int32 local_was_online);
void on_update_user_is_blocked(UserId user_id, bool is_blocked);
void on_update_user_common_chat_count(UserId user_id, int32 common_chat_count);
void on_update_user_need_phone_number_privacy_exception(UserId user_id, bool need_phone_number_privacy_exception);
@ -434,7 +435,7 @@ class ContactsManager : public Actor {
bool is_user_bot(UserId user_id) const;
Result<BotData> get_bot_data(UserId user_id) const TD_WARN_UNUSED_RESULT;
bool is_user_online(UserId user_id) const;
bool is_user_online(UserId user_id, int32 tolerance = 0) const;
bool is_user_status_exact(UserId user_id) const;
@ -699,10 +700,11 @@ class ContactsManager : public Actor {
int32 common_chat_count = 0;
bool is_blocked = false;
bool can_be_called = false;
bool supports_video_calls = false;
bool has_private_calls = false;
bool can_pin_messages = false;
bool can_pin_messages = true;
bool need_phone_number_privacy_exception = false;
bool is_common_chat_count_changed = true;
@ -1175,6 +1177,7 @@ class ContactsManager : public Actor {
void register_user_photo(User *u, UserId user_id, const Photo &photo);
void on_update_user_full_is_blocked(UserFull *user_full, UserId user_id, bool is_blocked);
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);

View File

@ -43,6 +43,14 @@ void add_dialog_dependencies(Dependencies &dependencies, DialogId dialog_id) {
}
}
void add_message_sender_dependencies(Dependencies &dependencies, DialogId dialog_id) {
if (dialog_id.get_type() == DialogType::User) {
dependencies.user_ids.insert(dialog_id.get_user_id());
} else {
add_dialog_and_dependencies(dependencies, dialog_id);
}
}
void resolve_dependencies_force(Td *td, const Dependencies &dependencies, const char *source) {
for (auto user_id : dependencies.user_ids) {
if (user_id.is_valid() && !td->contacts_manager_->have_user_force(user_id)) {

View File

@ -32,6 +32,8 @@ void add_dialog_and_dependencies(Dependencies &dependencies, DialogId dialog_id)
void add_dialog_dependencies(Dependencies &dependencies, DialogId dialog_id);
void add_message_sender_dependencies(Dependencies &dependencies, DialogId dialog_id);
void resolve_dependencies_force(Td *td, const Dependencies &dependencies, const char *source);
} // namespace td

View File

@ -305,6 +305,7 @@ bool DialogAction::is_cancelled_by_message_of_type(MessageContentType message_co
case MessageContentType::PassportDataReceived:
case MessageContentType::Poll:
case MessageContentType::Dice:
case MessageContentType::ProximityAlertTriggered:
return false;
default:
UNREACHABLE();

View File

@ -661,6 +661,11 @@ DialogParticipant::DialogParticipant(tl_object_ptr<telegram_api::ChannelParticip
std::move(participant->rank_))};
break;
}
case telegram_api::channelParticipantLeft::ID: {
auto participant = move_tl_object_as<telegram_api::channelParticipantLeft>(participant_ptr);
*this = {UserId(participant->user_id_), UserId(), 0, DialogParticipantStatus::Left()};
break;
}
case telegram_api::channelParticipantBanned::ID: {
auto participant = move_tl_object_as<telegram_api::channelParticipantBanned>(participant_ptr);
auto is_member = (participant->flags_ & telegram_api::channelParticipantBanned::LEFT_MASK) == 0;
@ -701,6 +706,17 @@ ChannelParticipantsFilter::get_input_channel_participants_filter() const {
return make_tl_object<telegram_api::channelParticipantsAdmins>();
case Type::Search:
return make_tl_object<telegram_api::channelParticipantsSearch>(query);
case Type::Mention: {
int32 flags = 0;
if (!query.empty()) {
flags |= telegram_api::channelParticipantsMentions::Q_MASK;
}
if (!top_thread_message_id.is_valid()) {
flags |= telegram_api::channelParticipantsMentions::TOP_MSG_ID_MASK;
}
return make_tl_object<telegram_api::channelParticipantsMentions>(
flags, query, top_thread_message_id.get_server_message_id().get());
}
case Type::Restricted:
return make_tl_object<telegram_api::channelParticipantsBanned>(query);
case Type::Banned:
@ -733,6 +749,16 @@ ChannelParticipantsFilter::ChannelParticipantsFilter(const tl_object_ptr<td_api:
type = Type::Search;
query = static_cast<const td_api::supergroupMembersFilterSearch *>(filter.get())->query_;
return;
case td_api::supergroupMembersFilterMention::ID: {
auto mention_filter = static_cast<const td_api::supergroupMembersFilterMention *>(filter.get());
type = Type::Mention;
query = mention_filter->query_;
top_thread_message_id = MessageId(mention_filter->message_thread_id_);
if (!top_thread_message_id.is_valid() || !top_thread_message_id.is_server()) {
top_thread_message_id = MessageId();
}
return;
}
case td_api::supergroupMembersFilterRestricted::ID:
type = Type::Restricted;
query = static_cast<const td_api::supergroupMembersFilterRestricted *>(filter.get())->query_;
@ -760,6 +786,8 @@ StringBuilder &operator<<(StringBuilder &string_builder, const ChannelParticipan
return string_builder << "Administrators";
case ChannelParticipantsFilter::Type::Search:
return string_builder << "Search \"" << filter.query << '"';
case ChannelParticipantsFilter::Type::Mention:
return string_builder << "Mention \"" << filter.query << "\" in thread of " << filter.top_thread_message_id;
case ChannelParticipantsFilter::Type::Restricted:
return string_builder << "Restricted \"" << filter.query << '"';
case ChannelParticipantsFilter::Type::Banned:
@ -774,24 +802,32 @@ StringBuilder &operator<<(StringBuilder &string_builder, const ChannelParticipan
DialogParticipantsFilter get_dialog_participants_filter(const tl_object_ptr<td_api::ChatMembersFilter> &filter) {
if (filter == nullptr) {
return DialogParticipantsFilter::Members;
return DialogParticipantsFilter{DialogParticipantsFilter::Type::Members};
}
switch (filter->get_id()) {
case td_api::chatMembersFilterContacts::ID:
return DialogParticipantsFilter::Contacts;
return DialogParticipantsFilter{DialogParticipantsFilter::Type::Contacts};
case td_api::chatMembersFilterAdministrators::ID:
return DialogParticipantsFilter::Administrators;
return DialogParticipantsFilter{DialogParticipantsFilter::Type::Administrators};
case td_api::chatMembersFilterMembers::ID:
return DialogParticipantsFilter::Members;
return DialogParticipantsFilter{DialogParticipantsFilter::Type::Members};
case td_api::chatMembersFilterRestricted::ID:
return DialogParticipantsFilter::Restricted;
return DialogParticipantsFilter{DialogParticipantsFilter::Type::Restricted};
case td_api::chatMembersFilterBanned::ID:
return DialogParticipantsFilter::Banned;
return DialogParticipantsFilter{DialogParticipantsFilter::Type::Banned};
case td_api::chatMembersFilterMention::ID: {
auto mention_filter = static_cast<const td_api::chatMembersFilterMention *>(filter.get());
auto top_thread_message_id = MessageId(mention_filter->message_thread_id_);
if (!top_thread_message_id.is_valid() || !top_thread_message_id.is_server()) {
top_thread_message_id = MessageId();
}
return DialogParticipantsFilter{DialogParticipantsFilter::Type::Mention, top_thread_message_id};
}
case td_api::chatMembersFilterBots::ID:
return DialogParticipantsFilter::Bots;
return DialogParticipantsFilter{DialogParticipantsFilter::Type::Bots};
default:
UNREACHABLE();
return DialogParticipantsFilter::Members;
return DialogParticipantsFilter{DialogParticipantsFilter::Type::Members};
}
}

View File

@ -6,9 +6,9 @@
//
#pragma once
#include "td/telegram/MessageId.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/telegram/UserId.h"
#include "td/utils/common.h"
@ -401,8 +401,9 @@ struct DialogParticipant {
StringBuilder &operator<<(StringBuilder &string_builder, const DialogParticipant &dialog_participant);
class ChannelParticipantsFilter {
enum class Type : int32 { Recent, Contacts, Administrators, Search, Restricted, Banned, Bots } type;
enum class Type : int32 { Recent, Contacts, Administrators, Search, Mention, Restricted, Banned, Bots } type;
string query;
MessageId top_thread_message_id;
friend StringBuilder &operator<<(StringBuilder &string_builder, const ChannelParticipantsFilter &filter);
@ -442,7 +443,16 @@ class ChannelParticipantsFilter {
StringBuilder &operator<<(StringBuilder &string_builder, const ChannelParticipantsFilter &filter);
enum class DialogParticipantsFilter : int32 { Contacts, Administrators, Members, Restricted, Banned, Bots };
class DialogParticipantsFilter {
public:
enum class Type : int32 { Contacts, Administrators, Members, Restricted, Banned, Mention, Bots };
Type type;
MessageId top_thread_message_id;
explicit DialogParticipantsFilter(Type type, MessageId top_thread_message_id = MessageId())
: type(type), top_thread_message_id(top_thread_message_id) {
}
};
DialogParticipantsFilter get_dialog_participants_filter(const tl_object_ptr<td_api::ChatMembersFilter> &filter);

View File

@ -257,8 +257,16 @@ Result<tl_object_ptr<telegram_api::InputBotInlineMessage>> InlineQueriesManager:
}
if (constructor_id == td_api::inputMessageLocation::ID) {
TRY_RESULT(location, process_input_message_location(std::move(input_message_content)));
return make_tl_object<telegram_api::inputBotInlineMessageMediaGeo>(flags, location.first.get_input_geo_point(),
location.second, std::move(input_reply_markup));
if (location.heading != 0) {
flags |= telegram_api::inputBotInlineMessageMediaGeo::HEADING_MASK;
}
if (location.live_period != 0) {
flags |= telegram_api::inputBotInlineMessageMediaGeo::PERIOD_MASK;
flags |= telegram_api::inputBotInlineMessageMediaGeo::PROXIMITY_NOTIFICATION_RADIUS_MASK;
}
return make_tl_object<telegram_api::inputBotInlineMessageMediaGeo>(
flags, location.location.get_input_geo_point(), location.heading, location.live_period,
location.proximity_alert_radius, std::move(input_reply_markup));
}
if (constructor_id == td_api::inputMessageVenue::ID) {
TRY_RESULT(venue, process_input_message_venue(std::move(input_message_content)));
@ -971,7 +979,7 @@ tl_object_ptr<td_api::contact> copy(const td_api::contact &obj) {
template <>
tl_object_ptr<td_api::location> copy(const td_api::location &obj) {
return make_tl_object<td_api::location>(obj.latitude_, obj.longitude_);
return make_tl_object<td_api::location>(obj.latitude_, obj.longitude_, obj.horizontal_accuracy_);
}
template <>
@ -1380,8 +1388,11 @@ void InlineQueriesManager::on_get_inline_query_results(UserId bot_user_id, uint6
Location l(inline_message_geo->geo_);
location->location_ = l.get_location_object();
} else {
auto coordinates = split(Slice(result->description_));
Location l(to_double(coordinates.first), to_double(coordinates.second), 0);
Slice latitude;
Slice longitude;
Slice horizontal_accuracy;
std::tie(latitude, longitude) = split(Slice(result->description_));
Location l(to_double(latitude), to_double(longitude), 0.0, 0);
location->location_ = l.get_location_object();
}
location->thumbnail_ = register_thumbnail(std::move(result->thumb_));

View File

@ -10,22 +10,33 @@
namespace td {
void Location::init(double latitude, double longitude, int64 access_hash) {
double Location::fix_accuracy(double accuracy) {
if (!std::isfinite(accuracy) || accuracy <= 0.0) {
return 0.0;
}
if (accuracy >= 1500.0) {
return 1500.0;
}
return accuracy;
}
void Location::init(double latitude, double longitude, double horizontal_accuracy, int64 access_hash) {
if (std::isfinite(latitude) && std::isfinite(longitude) && std::abs(latitude) <= 90 && std::abs(longitude) <= 180) {
is_empty_ = false;
latitude_ = latitude;
longitude_ = longitude;
horizontal_accuracy_ = fix_accuracy(horizontal_accuracy);
access_hash_ = access_hash;
G()->add_location_access_hash(latitude_, longitude_, access_hash_);
}
}
Location::Location(double latitude, double longitude, int64 access_hash) {
init(latitude, longitude, access_hash);
Location::Location(double latitude, double longitude, double horizontal_accuracy, int64 access_hash) {
init(latitude, longitude, horizontal_accuracy, access_hash);
}
Location::Location(const tl_object_ptr<secret_api::decryptedMessageMediaGeoPoint> &geo_point)
: Location(geo_point->lat_, geo_point->long_, 0) {
: Location(geo_point->lat_, geo_point->long_, 0.0, 0) {
}
Location::Location(const tl_object_ptr<telegram_api::GeoPoint> &geo_point_ptr) {
@ -37,7 +48,7 @@ Location::Location(const tl_object_ptr<telegram_api::GeoPoint> &geo_point_ptr) {
break;
case telegram_api::geoPoint::ID: {
auto geo_point = static_cast<const telegram_api::geoPoint *>(geo_point_ptr.get());
init(geo_point->lat_, geo_point->long_, geo_point->access_hash_);
init(geo_point->lat_, geo_point->long_, geo_point->accuracy_radius_, geo_point->access_hash_);
break;
}
default:
@ -51,7 +62,7 @@ Location::Location(const tl_object_ptr<td_api::location> &location) {
return;
}
init(location->latitude_, location->longitude_, 0);
init(location->latitude_, location->longitude_, location->horizontal_accuracy_, 0);
}
bool Location::empty() const {
@ -67,7 +78,7 @@ tl_object_ptr<td_api::location> Location::get_location_object() const {
if (empty()) {
return nullptr;
}
return make_tl_object<td_api::location>(latitude_, longitude_);
return make_tl_object<td_api::location>(latitude_, longitude_, horizontal_accuracy_);
}
tl_object_ptr<telegram_api::InputGeoPoint> Location::get_input_geo_point() const {
@ -75,7 +86,13 @@ tl_object_ptr<telegram_api::InputGeoPoint> Location::get_input_geo_point() const
return make_tl_object<telegram_api::inputGeoPointEmpty>();
}
return make_tl_object<telegram_api::inputGeoPoint>(latitude_, longitude_);
int32 flags = 0;
if (horizontal_accuracy_ > 0) {
flags |= telegram_api::inputGeoPoint::ACCURACY_RADIUS_MASK;
}
return make_tl_object<telegram_api::inputGeoPoint>(flags, latitude_, longitude_,
static_cast<int32>(std::ceil(horizontal_accuracy_)));
}
tl_object_ptr<telegram_api::inputMediaGeoPoint> Location::get_input_media_geo_point() const {
@ -91,7 +108,8 @@ bool operator==(const Location &lhs, const Location &rhs) {
return rhs.is_empty_;
}
return !rhs.is_empty_ && std::abs(lhs.latitude_ - rhs.latitude_) < 1e-6 &&
std::abs(lhs.longitude_ - rhs.longitude_) < 1e-6;
std::abs(lhs.longitude_ - rhs.longitude_) < 1e-6 &&
std::abs(lhs.horizontal_accuracy_ - rhs.horizontal_accuracy_) < 1e-6;
}
bool operator!=(const Location &lhs, const Location &rhs) {
@ -103,10 +121,10 @@ StringBuilder &operator<<(StringBuilder &string_builder, const Location &locatio
return string_builder << "Location[empty]";
}
return string_builder << "Location[latitude = " << location.latitude_ << ", longitude = " << location.longitude_
<< "]";
<< ", accuracy = " << location.horizontal_accuracy_ << "]";
}
Result<std::pair<Location, int32>> process_input_message_location(
Result<InputMessageLocation> process_input_message_location(
tl_object_ptr<td_api::InputMessageContent> &&input_message_content) {
CHECK(input_message_content != nullptr);
CHECK(input_message_content->get_id() == td_api::inputMessageLocation::ID);
@ -125,7 +143,26 @@ Result<std::pair<Location, int32>> process_input_message_location(
return Status::Error(400, "Wrong live location period specified");
}
return std::make_pair(std::move(location), period);
constexpr int32 MIN_LIVE_LOCATION_HEADING = 1; // degrees, server side limit
constexpr int32 MAX_LIVE_LOCATION_HEADING = 360; // degrees, server side limit
auto heading = input_location->heading_;
if (heading != 0 && (heading < MIN_LIVE_LOCATION_HEADING || heading > MAX_LIVE_LOCATION_HEADING)) {
return Status::Error(400, "Wrong live location heading specified");
}
constexpr int32 MAX_PROXIMITY_ALERT_RADIUS = 100000; // meters, server side limit
auto proximity_alert_radius = input_location->proximity_alert_radius_;
if (proximity_alert_radius < 0 || proximity_alert_radius > MAX_PROXIMITY_ALERT_RADIUS) {
return Status::Error(400, "Wrong live location proximity alert radius specified");
}
InputMessageLocation result;
result.location = std::move(location);
result.live_period = period;
result.heading = heading;
result.proximity_alert_radius = proximity_alert_radius;
return std::move(result);
}
} // namespace td

View File

@ -18,14 +18,13 @@
#include "td/utils/StringBuilder.h"
#include "td/utils/tl_helpers.h"
#include <utility>
namespace td {
class Location {
bool is_empty_ = true;
double latitude_ = 0.0;
double longitude_ = 0.0;
double horizontal_accuracy_ = 0.0;
mutable int64 access_hash_ = 0;
friend bool operator==(const Location &lhs, const Location &rhs);
@ -33,12 +32,14 @@ class Location {
friend StringBuilder &operator<<(StringBuilder &string_builder, const Location &location);
void init(double latitude, double longitude, int64 access_hash);
void init(double latitude, double longitude, double horizontal_accuracy, int64 access_hash);
double fix_accuracy(double accuracy);
public:
Location() = default;
Location(double latitude, double longitude, int64 access_hash);
Location(double latitude, double longitude, double horizontal_accuracy, int64 access_hash);
explicit Location(const tl_object_ptr<secret_api::decryptedMessageMediaGeoPoint> &geo_point);
@ -78,24 +79,31 @@ class Location {
void store(StorerT &storer) const {
using td::store;
bool has_access_hash = access_hash_ != 0;
bool has_horizontal_accuracy = horizontal_accuracy_ > 0.0;
BEGIN_STORE_FLAGS();
STORE_FLAG(is_empty_);
STORE_FLAG(has_access_hash);
STORE_FLAG(has_horizontal_accuracy);
END_STORE_FLAGS();
store(latitude_, storer);
store(longitude_, storer);
if (has_access_hash) {
store(access_hash_, storer);
}
if (has_horizontal_accuracy) {
store(horizontal_accuracy_, storer);
}
}
template <class ParserT>
void parse(ParserT &parser) {
using td::parse;
bool has_access_hash;
bool has_horizontal_accuracy;
BEGIN_PARSE_FLAGS();
PARSE_FLAG(is_empty_);
PARSE_FLAG(has_access_hash);
PARSE_FLAG(has_horizontal_accuracy);
END_PARSE_FLAGS();
parse(latitude_, parser);
parse(longitude_, parser);
@ -103,6 +111,9 @@ class Location {
parse(access_hash_, parser);
G()->add_location_access_hash(latitude_, longitude_, access_hash_);
}
if (has_horizontal_accuracy) {
parse(horizontal_accuracy_, parser);
}
}
};
@ -111,7 +122,13 @@ bool operator!=(const Location &lhs, const Location &rhs);
StringBuilder &operator<<(StringBuilder &string_builder, const Location &location);
Result<std::pair<Location, int32>> process_input_message_location(
struct InputMessageLocation {
Location location;
int32 live_period;
int32 heading;
int32 proximity_alert_radius;
};
Result<InputMessageLocation> process_input_message_location(
td_api::object_ptr<td_api::InputMessageContent> &&input_message_content) TD_WARN_UNUSED_RESULT;
} // namespace td

View File

@ -33,6 +33,7 @@
#include "td/telegram/MessageEntity.h"
#include "td/telegram/MessageEntity.hpp"
#include "td/telegram/MessageId.h"
#include "td/telegram/MessagesManager.h"
#include "td/telegram/MessageSearchFilter.h"
#include "td/telegram/misc.h"
#include "td/telegram/net/DcId.h"
@ -565,10 +566,26 @@ class MessageExpiredVideo : public MessageContent {
class MessageLiveLocation : public MessageContent {
public:
Location location;
int32 period;
int32 period = 0;
int32 heading = 0;
int32 proximity_alert_radius = 0;
MessageLiveLocation() = default;
MessageLiveLocation(Location &&location, int32 period) : location(std::move(location)), period(period) {
MessageLiveLocation(Location &&location, int32 period, int32 heading, int32 proximity_alert_radius)
: location(std::move(location))
, period(period)
, heading(heading)
, proximity_alert_radius(proximity_alert_radius) {
if (period < 0) {
period = 0;
}
if (heading < 0 || heading > 360) {
LOG(ERROR) << "Receive wrong heading " << heading;
heading = 0;
}
if (proximity_alert_radius < 0) {
proximity_alert_radius = 0;
}
}
MessageContentType get_type() const override {
@ -671,6 +688,22 @@ class MessageDice : public MessageContent {
}
};
class MessageProximityAlertTriggered : public MessageContent {
public:
DialogId approacher_dialog_id;
DialogId observer_dialog_id;
int32 distance = 0;
MessageProximityAlertTriggered() = default;
MessageProximityAlertTriggered(DialogId approacher_dialog_id, DialogId observer_dialog_id, int32 distance)
: approacher_dialog_id(approacher_dialog_id), observer_dialog_id(observer_dialog_id), distance(distance) {
}
MessageContentType get_type() const override {
return MessageContentType::ProximityAlertTriggered;
}
};
constexpr const char *MessageDice::DEFAULT_EMOJI;
template <class StorerT>
@ -731,6 +764,8 @@ static void store(const MessageContent *content, StorerT &storer) {
auto m = static_cast<const MessageLiveLocation *>(content);
store(m->location, storer);
store(m->period, storer);
store(m->heading, storer);
store(m->proximity_alert_radius, storer);
break;
}
case MessageContentType::Location: {
@ -936,6 +971,13 @@ static void store(const MessageContent *content, StorerT &storer) {
store(m->dice_value, storer);
break;
}
case MessageContentType::ProximityAlertTriggered: {
auto m = static_cast<const MessageProximityAlertTriggered *>(content);
store(m->approacher_dialog_id, storer);
store(m->observer_dialog_id, storer);
store(m->distance, storer);
break;
}
default:
UNREACHABLE();
}
@ -1025,6 +1067,16 @@ static void parse(unique_ptr<MessageContent> &content, ParserT &parser) {
auto m = make_unique<MessageLiveLocation>();
parse(m->location, parser);
parse(m->period, parser);
if (parser.version() >= static_cast<int32>(Version::AddLiveLocationHeading)) {
parse(m->heading, parser);
} else {
m->heading = 0;
}
if (parser.version() >= static_cast<int32>(Version::AddLiveLocationProximityAlertDistance)) {
parse(m->proximity_alert_radius, parser);
} else {
m->proximity_alert_radius = 0;
}
content = std::move(m);
break;
}
@ -1292,6 +1344,14 @@ static void parse(unique_ptr<MessageContent> &content, ParserT &parser) {
content = std::move(m);
break;
}
case MessageContentType::ProximityAlertTriggered: {
auto m = make_unique<MessageProximityAlertTriggered>();
parse(m->approacher_dialog_id, parser);
parse(m->observer_dialog_id, parser);
parse(m->distance, parser);
content = std::move(m);
break;
}
default:
LOG(FATAL) << "Have unknown message content type " << static_cast<int32>(content_type);
}
@ -1352,9 +1412,18 @@ InlineMessageContent create_inline_message_content(Td *td, FileId file_id,
}
case telegram_api::botInlineMessageMediaGeo::ID: {
auto inline_message_geo = move_tl_object_as<telegram_api::botInlineMessageMediaGeo>(inline_message);
if (inline_message_geo->period_ > 0) {
result.message_content =
make_unique<MessageLiveLocation>(Location(inline_message_geo->geo_), inline_message_geo->period_);
if ((inline_message_geo->flags_ & telegram_api::botInlineMessageMediaGeo::PERIOD_MASK) != 0 &&
inline_message_geo->period_ > 0) {
auto heading = (inline_message_geo->flags_ & telegram_api::botInlineMessageMediaGeo::HEADING_MASK) != 0
? inline_message_geo->heading_
: 0;
auto approacing_notification_radius =
(inline_message_geo->flags_ & telegram_api::botInlineMessageMediaGeo::PROXIMITY_NOTIFICATION_RADIUS_MASK) !=
0
? inline_message_geo->proximity_notification_radius_
: 0;
result.message_content = make_unique<MessageLiveLocation>(
Location(inline_message_geo->geo_), inline_message_geo->period_, heading, approacing_notification_radius);
} else {
result.message_content = make_unique<MessageLocation>(Location(inline_message_geo->geo_));
}
@ -1614,10 +1683,11 @@ static Result<InputMessageContent> create_input_message_content(
}
case td_api::inputMessageLocation::ID: {
TRY_RESULT(location, process_input_message_location(std::move(input_message_content)));
if (location.second == 0) {
content = make_unique<MessageLocation>(std::move(location.first));
if (location.live_period == 0) {
content = make_unique<MessageLocation>(std::move(location.location));
} else {
content = make_unique<MessageLiveLocation>(std::move(location.first), location.second);
content = make_unique<MessageLiveLocation>(std::move(location.location), location.live_period, location.heading,
location.proximity_alert_radius);
}
break;
}
@ -1976,6 +2046,7 @@ bool can_have_input_media(const Td *td, const MessageContent *content) {
case MessageContentType::WebsiteConnected:
case MessageContentType::PassportDataSent:
case MessageContentType::PassportDataReceived:
case MessageContentType::ProximityAlertTriggered:
return false;
case MessageContentType::Animation:
case MessageContentType::Audio:
@ -2088,6 +2159,7 @@ SecretInputMedia get_secret_input_media(const MessageContent *content, Td *td,
case MessageContentType::WebsiteConnected:
case MessageContentType::PassportDataSent:
case MessageContentType::PassportDataReceived:
case MessageContentType::ProximityAlertTriggered:
break;
default:
UNREACHABLE();
@ -2211,8 +2283,13 @@ static tl_object_ptr<telegram_api::InputMedia> get_input_media_impl(
case MessageContentType::LiveLocation: {
auto m = static_cast<const MessageLiveLocation *>(content);
int32 flags = telegram_api::inputMediaGeoLive::PERIOD_MASK;
if (m->heading != 0) {
flags |= telegram_api::inputMediaGeoLive::HEADING_MASK;
}
flags |= telegram_api::inputMediaGeoLive::PROXIMITY_NOTIFICATION_RADIUS_MASK;
return make_tl_object<telegram_api::inputMediaGeoLive>(flags, false /*ignored*/,
m->location.get_input_geo_point(), m->period);
m->location.get_input_geo_point(), m->heading, m->period,
m->proximity_alert_radius);
}
case MessageContentType::Location: {
auto m = static_cast<const MessageLocation *>(content);
@ -2272,6 +2349,7 @@ static tl_object_ptr<telegram_api::InputMedia> get_input_media_impl(
case MessageContentType::WebsiteConnected:
case MessageContentType::PassportDataSent:
case MessageContentType::PassportDataReceived:
case MessageContentType::ProximityAlertTriggered:
break;
default:
UNREACHABLE();
@ -2394,6 +2472,7 @@ void delete_message_content_thumbnail(MessageContent *content, Td *td) {
case MessageContentType::PassportDataSent:
case MessageContentType::PassportDataReceived:
case MessageContentType::Poll:
case MessageContentType::ProximityAlertTriggered:
break;
default:
UNREACHABLE();
@ -2453,36 +2532,23 @@ static int32 get_message_content_text_index_mask(const MessageContent *content)
return 0;
}
static int32 get_message_content_media_index_mask(const MessageContent *content, const Td *td, bool is_secret,
bool is_outgoing) {
static int32 get_message_content_media_index_mask(const MessageContent *content, const Td *td, bool is_outgoing) {
switch (content->get_type()) {
case MessageContentType::Animation:
return message_search_filter_index_mask(MessageSearchFilter::Animation);
case MessageContentType::Audio: {
auto message_audio = static_cast<const MessageAudio *>(content);
auto duration = td->audios_manager_->get_audio_duration(message_audio->file_id);
return is_secret || duration > 0 ? message_search_filter_index_mask(MessageSearchFilter::Audio)
: message_search_filter_index_mask(MessageSearchFilter::Document);
}
case MessageContentType::Audio:
return message_search_filter_index_mask(MessageSearchFilter::Audio);
case MessageContentType::Document:
return message_search_filter_index_mask(MessageSearchFilter::Document);
case MessageContentType::Photo:
return message_search_filter_index_mask(MessageSearchFilter::Photo) |
message_search_filter_index_mask(MessageSearchFilter::PhotoAndVideo);
case MessageContentType::Video: {
auto message_video = static_cast<const MessageVideo *>(content);
auto duration = td->videos_manager_->get_video_duration(message_video->file_id);
return is_secret || duration > 0 ? message_search_filter_index_mask(MessageSearchFilter::Video) |
message_search_filter_index_mask(MessageSearchFilter::PhotoAndVideo)
: message_search_filter_index_mask(MessageSearchFilter::Document);
}
case MessageContentType::VideoNote: {
auto message_video_note = static_cast<const MessageVideoNote *>(content);
auto duration = td->video_notes_manager_->get_video_note_duration(message_video_note->file_id);
return is_secret || duration > 0 ? message_search_filter_index_mask(MessageSearchFilter::VideoNote) |
message_search_filter_index_mask(MessageSearchFilter::VoiceAndVideoNote)
: message_search_filter_index_mask(MessageSearchFilter::Document);
}
case MessageContentType::Video:
return message_search_filter_index_mask(MessageSearchFilter::Video) |
message_search_filter_index_mask(MessageSearchFilter::PhotoAndVideo);
case MessageContentType::VideoNote:
return message_search_filter_index_mask(MessageSearchFilter::VideoNote) |
message_search_filter_index_mask(MessageSearchFilter::VoiceAndVideoNote);
case MessageContentType::VoiceNote:
return message_search_filter_index_mask(MessageSearchFilter::VoiceNote) |
message_search_filter_index_mask(MessageSearchFilter::VoiceAndVideoNote);
@ -2530,6 +2596,7 @@ static int32 get_message_content_media_index_mask(const MessageContent *content,
case MessageContentType::PassportDataReceived:
case MessageContentType::Poll:
case MessageContentType::Dice:
case MessageContentType::ProximityAlertTriggered:
return 0;
default:
UNREACHABLE();
@ -2538,9 +2605,8 @@ static int32 get_message_content_media_index_mask(const MessageContent *content,
return 0;
}
int32 get_message_content_index_mask(const MessageContent *content, const Td *td, bool is_secret, bool is_outgoing) {
return get_message_content_text_index_mask(content) |
get_message_content_media_index_mask(content, td, is_secret, is_outgoing);
int32 get_message_content_index_mask(const MessageContent *content, const Td *td, bool is_outgoing) {
return get_message_content_text_index_mask(content) | get_message_content_media_index_mask(content, td, is_outgoing);
}
MessageId get_message_content_pinned_message_id(const MessageContent *content) {
@ -2805,7 +2871,8 @@ void merge_message_contents(Td *td, const MessageContent *old_content, MessageCo
if (old_->location != new_->location) {
need_update = true;
}
if (old_->period != new_->period) {
if (old_->period != new_->period || old_->heading != new_->heading ||
old_->proximity_alert_radius != new_->proximity_alert_radius) {
need_update = true;
}
if (old_->location.get_access_hash() != new_->location.get_access_hash()) {
@ -2893,8 +2960,8 @@ void merge_message_contents(Td *td, const MessageContent *old_content, MessageCo
auto volume_id = -new_file_view.remote_location().get_id();
FileId file_id = td->file_manager_->register_remote(
FullRemoteFileLocation({FileType::Photo, 'i'}, new_file_view.remote_location().get_id(),
new_file_view.remote_location().get_access_hash(), 0, volume_id,
DcId::invalid(), new_file_view.remote_location().get_file_reference().str()),
new_file_view.remote_location().get_access_hash(), 0, volume_id, DcId::invalid(),
new_file_view.remote_location().get_file_reference().str()),
FileLocationSource::FromServer, dialog_id, old_photo->photos.back().size, 0, "");
LOG_STATUS(td->file_manager_->merge(file_id, old_file_id));
}
@ -3142,6 +3209,15 @@ void merge_message_contents(Td *td, const MessageContent *old_content, MessageCo
}
break;
}
case MessageContentType::ProximityAlertTriggered: {
auto old_ = static_cast<const MessageProximityAlertTriggered *>(old_content);
auto new_ = static_cast<const MessageProximityAlertTriggered *>(new_content);
if (old_->approacher_dialog_id != new_->approacher_dialog_id ||
old_->observer_dialog_id != new_->observer_dialog_id || old_->distance != new_->distance) {
need_update = true;
}
break;
}
case MessageContentType::Unsupported: {
auto old_ = static_cast<const MessageUnsupported *>(old_content);
auto new_ = static_cast<const MessageUnsupported *>(new_content);
@ -3274,6 +3350,7 @@ bool merge_message_content_file_id(Td *td, MessageContent *message_content, File
case MessageContentType::PassportDataReceived:
case MessageContentType::Poll:
case MessageContentType::Dice:
case MessageContentType::ProximityAlertTriggered:
LOG(ERROR) << "Receive new file " << new_file_id << " in a sent message of the type " << content_type;
break;
default:
@ -3661,7 +3738,7 @@ unique_ptr<MessageContent> get_secret_message_content(
message_venue->venue_id_.clear();
}
auto m = make_unique<MessageVenue>(Venue(Location(message_venue->lat_, message_venue->long_, 0),
auto m = make_unique<MessageVenue>(Venue(Location(message_venue->lat_, message_venue->long_, 0.0, 0),
std::move(message_venue->title_), std::move(message_venue->address_),
std::move(message_venue->provider_), std::move(message_venue->venue_id_),
string()));
@ -3820,17 +3897,18 @@ unique_ptr<MessageContent> get_message_content(Td *td, FormattedText message,
}
case telegram_api::messageMediaGeoLive::ID: {
auto message_geo_point_live = move_tl_object_as<telegram_api::messageMediaGeoLive>(media);
int32 period = message_geo_point_live->period_;
auto location = Location(std::move(message_geo_point_live->geo_));
if (location.empty()) {
break;
}
int32 period = message_geo_point_live->period_;
if (period <= 0) {
LOG(ERROR) << "Receive wrong live location period = " << period;
return make_unique<MessageLocation>(std::move(location));
}
return make_unique<MessageLiveLocation>(std::move(location), period);
return make_unique<MessageLiveLocation>(std::move(location), period, message_geo_point_live->heading_,
message_geo_point_live->proximity_notification_radius_);
}
case telegram_api::messageMediaVenue::ID: {
auto message_venue = move_tl_object_as<telegram_api::messageMediaVenue>(media);
@ -4165,6 +4243,7 @@ unique_ptr<MessageContent> dup_message_content(Td *td, DialogId dialog_id, const
case MessageContentType::WebsiteConnected:
case MessageContentType::PassportDataSent:
case MessageContentType::PassportDataReceived:
case MessageContentType::ProximityAlertTriggered:
return nullptr;
default:
UNREACHABLE();
@ -4347,6 +4426,18 @@ unique_ptr<MessageContent> get_action_message_content(Td *td, tl_object_ptr<tele
LOG_IF(ERROR, td->auth_manager_->is_bot()) << "Receive ContactRegistered in " << owner_dialog_id;
return td::make_unique<MessageContactRegistered>();
}
case telegram_api::messageActionGeoProximityReached::ID: {
auto geo_proximity_reached = move_tl_object_as<telegram_api::messageActionGeoProximityReached>(action);
DialogId approacher_id(geo_proximity_reached->from_id_);
DialogId observer_id(geo_proximity_reached->to_id_);
int32 distance = geo_proximity_reached->distance_;
if (!approacher_id.is_valid() || !observer_id.is_valid() || distance < 0) {
LOG(ERROR) << "Receive invalid " << oneline(to_string(geo_proximity_reached));
break;
}
return make_unique<MessageProximityAlertTriggered>(approacher_id, observer_id, distance);
}
default:
UNREACHABLE();
}
@ -4393,12 +4484,15 @@ tl_object_ptr<td_api::MessageContent> get_message_content_object(const MessageCo
case MessageContentType::LiveLocation: {
const MessageLiveLocation *m = static_cast<const MessageLiveLocation *>(content);
auto passed = max(G()->unix_time_cached() - message_date, 0);
return make_tl_object<td_api::messageLocation>(m->location.get_location_object(), m->period,
max(0, m->period - passed));
auto expires_in = max(0, m->period - passed);
auto heading = expires_in == 0 ? 0 : m->heading;
auto proximity_alert_radius = expires_in == 0 ? 0 : m->proximity_alert_radius;
return make_tl_object<td_api::messageLocation>(m->location.get_location_object(), m->period, expires_in, heading,
proximity_alert_radius);
}
case MessageContentType::Location: {
const MessageLocation *m = static_cast<const MessageLocation *>(content);
return make_tl_object<td_api::messageLocation>(m->location.get_location_object(), 0, 0);
return make_tl_object<td_api::messageLocation>(m->location.get_location_object(), 0, 0, 0, 0);
}
case MessageContentType::Photo: {
const MessagePhoto *m = static_cast<const MessagePhoto *>(content);
@ -4539,14 +4633,20 @@ tl_object_ptr<td_api::MessageContent> get_message_content_object(const MessageCo
}
case MessageContentType::Dice: {
const MessageDice *m = static_cast<const MessageDice *>(content);
auto initial_state = td->stickers_manager_->get_dice_sticker_object(m->emoji, 0);
auto initial_state = td->stickers_manager_->get_dice_stickers_object(m->emoji, 0);
auto final_state =
m->dice_value == 0 ? nullptr : td->stickers_manager_->get_dice_sticker_object(m->emoji, m->dice_value);
m->dice_value == 0 ? nullptr : td->stickers_manager_->get_dice_stickers_object(m->emoji, m->dice_value);
auto success_animation_frame_number =
td->stickers_manager_->get_dice_success_animation_frame_number(m->emoji, m->dice_value);
return make_tl_object<td_api::messageDice>(std::move(initial_state), std::move(final_state), m->emoji,
m->dice_value, success_animation_frame_number);
}
case MessageContentType::ProximityAlertTriggered: {
const MessageProximityAlertTriggered *m = static_cast<const MessageProximityAlertTriggered *>(content);
return make_tl_object<td_api::messageProximityAlertTriggered>(
td->messages_manager_->get_message_sender_object(m->approacher_dialog_id),
td->messages_manager_->get_message_sender_object(m->observer_dialog_id), m->distance);
}
default:
UNREACHABLE();
return nullptr;
@ -4858,6 +4958,7 @@ string get_message_content_search_text(const Td *td, const MessageContent *conte
case MessageContentType::PassportDataSent:
case MessageContentType::PassportDataReceived:
case MessageContentType::Dice:
case MessageContentType::ProximityAlertTriggered:
return string();
default:
UNREACHABLE();
@ -5051,6 +5152,12 @@ void add_message_content_dependencies(Dependencies &dependencies, const MessageC
break;
case MessageContentType::Dice:
break;
case MessageContentType::ProximityAlertTriggered: {
auto content = static_cast<const MessageProximityAlertTriggered *>(message_content);
add_message_sender_dependencies(dependencies, content->approacher_dialog_id);
add_message_sender_dependencies(dependencies, content->observer_dialog_id);
break;
}
default:
UNREACHABLE();
break;

View File

@ -120,7 +120,7 @@ bool can_forward_message_content(const MessageContent *content);
bool update_opened_message_content(MessageContent *content);
int32 get_message_content_index_mask(const MessageContent *content, const Td *td, bool is_secret, bool is_outgoing);
int32 get_message_content_index_mask(const MessageContent *content, const Td *td, bool is_outgoing);
MessageId get_message_content_pinned_message_id(const MessageContent *content);

View File

@ -96,6 +96,8 @@ StringBuilder &operator<<(StringBuilder &string_builder, MessageContentType cont
return string_builder << "Poll";
case MessageContentType::Dice:
return string_builder << "Dice";
case MessageContentType::ProximityAlertTriggered:
return string_builder << "ProximityAlertTriggered";
default:
UNREACHABLE();
return string_builder;
@ -104,15 +106,15 @@ StringBuilder &operator<<(StringBuilder &string_builder, MessageContentType cont
bool is_allowed_media_group_content(MessageContentType content_type) {
switch (content_type) {
case MessageContentType::Audio:
case MessageContentType::Document:
case MessageContentType::Photo:
case MessageContentType::Video:
case MessageContentType::ExpiredPhoto:
case MessageContentType::ExpiredVideo:
return true;
case MessageContentType::Animation:
case MessageContentType::Audio:
case MessageContentType::Contact:
case MessageContentType::Document:
case MessageContentType::Game:
case MessageContentType::Invoice:
case MessageContentType::LiveLocation:
@ -147,6 +149,7 @@ bool is_allowed_media_group_content(MessageContentType content_type) {
case MessageContentType::PassportDataReceived:
case MessageContentType::Poll:
case MessageContentType::Dice:
case MessageContentType::ProximityAlertTriggered:
return false;
default:
UNREACHABLE();
@ -154,6 +157,10 @@ bool is_allowed_media_group_content(MessageContentType content_type) {
}
}
bool is_homogenous_media_group_content(MessageContentType content_type) {
return content_type == MessageContentType::Audio || content_type == MessageContentType::Document;
}
bool is_secret_message_content(int32 ttl, MessageContentType content_type) {
if (ttl <= 0 || ttl > 60) {
return false;
@ -202,6 +209,7 @@ bool is_secret_message_content(int32 ttl, MessageContentType content_type) {
case MessageContentType::PassportDataReceived:
case MessageContentType::Poll:
case MessageContentType::Dice:
case MessageContentType::ProximityAlertTriggered:
return false;
default:
UNREACHABLE();
@ -254,6 +262,7 @@ bool is_service_message_content(MessageContentType content_type) {
case MessageContentType::WebsiteConnected:
case MessageContentType::PassportDataSent:
case MessageContentType::PassportDataReceived:
case MessageContentType::ProximityAlertTriggered:
return true;
default:
UNREACHABLE();
@ -306,6 +315,7 @@ bool can_have_message_content_caption(MessageContentType content_type) {
case MessageContentType::PassportDataReceived:
case MessageContentType::Poll:
case MessageContentType::Dice:
case MessageContentType::ProximityAlertTriggered:
return false;
default:
UNREACHABLE();

View File

@ -54,13 +54,16 @@ enum class MessageContentType : int32 {
PassportDataSent,
PassportDataReceived,
Poll,
Dice
Dice,
ProximityAlertTriggered
};
StringBuilder &operator<<(StringBuilder &string_builder, MessageContentType content_type);
bool is_allowed_media_group_content(MessageContentType content_type);
bool is_homogenous_media_group_content(MessageContentType content_type);
bool is_secret_message_content(int32 ttl, MessageContentType content_type);
bool is_service_message_content(MessageContentType content_type);

View File

@ -7,6 +7,7 @@
#include "td/telegram/MessageReplyInfo.h"
#include "td/telegram/ContactsManager.h"
#include "td/telegram/MessagesManager.h"
#include "td/telegram/ServerMessageId.h"
#include "td/utils/logging.h"
@ -40,6 +41,7 @@ MessageReplyInfo::MessageReplyInfo(tl_object_ptr<telegram_api::messageReplies> &
for (const auto &peer : reply_info->recent_repliers_) {
DialogId dialog_id(peer);
if (dialog_id.is_valid()) {
// save all valid dialog_id, despite we can have no info about some of them
recent_replier_dialog_ids.push_back(dialog_id);
} else {
LOG(ERROR) << "Receive " << dialog_id << " as a recent replier";
@ -125,20 +127,28 @@ void MessageReplyInfo::add_reply(DialogId replier_dialog_id, MessageId reply_mes
}
td_api::object_ptr<td_api::messageReplyInfo> MessageReplyInfo::get_message_reply_info_object(
ContactsManager *contacts_manager) const {
ContactsManager *contacts_manager, const MessagesManager *messages_manager) const {
if (is_empty()) {
return nullptr;
}
vector<UserId> recent_replier_user_ids;
vector<td_api::object_ptr<td_api::MessageSender>> recent_repliers;
for (auto recent_replier_dialog_id : recent_replier_dialog_ids) {
if (recent_replier_dialog_id.get_type() == DialogType::User) {
recent_replier_user_ids.push_back(recent_replier_dialog_id.get_user_id());
auto user_id = recent_replier_dialog_id.get_user_id();
if (contacts_manager->have_min_user(user_id)) {
recent_repliers.push_back(td_api::make_object<td_api::messageSenderUser>(
contacts_manager->get_user_id_object(user_id, "get_message_reply_info_object")));
}
} else {
if (messages_manager->have_dialog(recent_replier_dialog_id)) {
recent_repliers.push_back(td_api::make_object<td_api::messageSenderChat>(recent_replier_dialog_id.get()));
}
}
}
return td_api::make_object<td_api::messageReplyInfo>(
reply_count, contacts_manager->get_user_ids_object(recent_replier_user_ids, "get_message_reply_info_object"),
last_read_inbox_message_id.get(), last_read_outbox_message_id.get(), max_message_id.get());
return td_api::make_object<td_api::messageReplyInfo>(reply_count, std::move(recent_repliers),
last_read_inbox_message_id.get(),
last_read_outbox_message_id.get(), max_message_id.get());
}
StringBuilder &operator<<(StringBuilder &string_builder, const MessageReplyInfo &reply_info) {

View File

@ -19,6 +19,7 @@
namespace td {
class ContactsManager;
class MessagesManager;
struct MessageReplyInfo {
int32 reply_count = -1;
@ -47,7 +48,8 @@ struct MessageReplyInfo {
void add_reply(DialogId replier_dialog_id, MessageId reply_message_id);
td_api::object_ptr<td_api::messageReplyInfo> get_message_reply_info_object(ContactsManager *contacts_manager) const;
td_api::object_ptr<td_api::messageReplyInfo> get_message_reply_info_object(
ContactsManager *contacts_manager, const MessagesManager *messages_manager) const;
template <class StorerT>
void store(StorerT &storer) const {

View File

@ -43,6 +43,8 @@ tl_object_ptr<telegram_api::MessagesFilter> get_input_messages_filter(MessageSea
return make_tl_object<telegram_api::inputMessagesFilterRoundVoice>();
case MessageSearchFilter::Mention:
return make_tl_object<telegram_api::inputMessagesFilterMyMentions>();
case MessageSearchFilter::Pinned:
return make_tl_object<telegram_api::inputMessagesFilterPinned>();
case MessageSearchFilter::UnreadMention:
case MessageSearchFilter::FailedToSend:
default:
@ -90,6 +92,8 @@ MessageSearchFilter get_message_search_filter(const tl_object_ptr<td_api::Search
return MessageSearchFilter::UnreadMention;
case td_api::searchMessagesFilterFailedToSend::ID:
return MessageSearchFilter::FailedToSend;
case td_api::searchMessagesFilterPinned::ID:
return MessageSearchFilter::Pinned;
default:
UNREACHABLE();
return MessageSearchFilter::Empty;
@ -132,6 +136,8 @@ StringBuilder &operator<<(StringBuilder &string_builder, MessageSearchFilter fil
return string_builder << "UnreadMention";
case MessageSearchFilter::FailedToSend:
return string_builder << "FailedToSend";
case MessageSearchFilter::Pinned:
return string_builder << "Pinned";
default:
UNREACHABLE();
return string_builder;

View File

@ -33,6 +33,7 @@ enum class MessageSearchFilter : int32 {
Mention,
UnreadMention,
FailedToSend,
Pinned,
Size
};

File diff suppressed because it is too large Load Diff

View File

@ -167,6 +167,7 @@ class MessagesManager : public Actor {
static constexpr int32 MESSAGE_FLAG_HIDE_EDIT_DATE = 1 << 21;
static constexpr int32 MESSAGE_FLAG_IS_RESTRICTED = 1 << 22;
static constexpr int32 MESSAGE_FLAG_HAS_REPLY_INFO = 1 << 23;
static constexpr int32 MESSAGE_FLAG_IS_PINNED = 1 << 24;
static constexpr int32 SEND_MESSAGE_FLAG_IS_REPLY = 1 << 0;
static constexpr int32 SEND_MESSAGE_FLAG_DISABLE_WEB_PAGE_PREVIEW = 1 << 1;
@ -194,6 +195,12 @@ class MessagesManager : public Actor {
void memory_stats(vector<string> &output);
td_api::object_ptr<td_api::MessageSender> get_message_sender_object_const(UserId user_id, DialogId dialog_id) const;
td_api::object_ptr<td_api::MessageSender> get_message_sender_object(UserId user_id, DialogId dialog_id);
td_api::object_ptr<td_api::MessageSender> get_message_sender_object(DialogId dialog_id);
static vector<MessageId> get_message_ids(const vector<int64> &input_message_ids);
static vector<int32> get_server_message_ids(const vector<MessageId> &message_ids);
@ -241,7 +248,7 @@ class MessagesManager : public Actor {
vector<tl_object_ptr<telegram_api::Peer>> &&peers);
void on_failed_public_dialogs_search(const string &query, Status &&error);
void on_get_dialog_messages_search_result(DialogId dialog_id, const string &query, UserId sender_user_id,
void on_get_dialog_messages_search_result(DialogId dialog_id, const string &query, DialogId sender_dialog_id,
MessageId from_message_id, int32 offset, int32 limit,
MessageSearchFilter filter, MessageId top_thread_message_id,
int64 random_id, int32 total_count,
@ -320,7 +327,7 @@ class MessagesManager : public Actor {
void on_update_dialog_is_blocked(DialogId dialog_id, bool is_blocked);
void on_update_dialog_pinned_message_id(DialogId dialog_id, MessageId pinned_message_id);
void on_update_dialog_last_pinned_message_id(DialogId dialog_id, MessageId last_pinned_message_id);
void on_update_dialog_has_scheduled_server_messages(DialogId dialog_id, bool has_scheduled_server_messages);
@ -427,15 +434,17 @@ class MessagesManager : public Actor {
Status send_screenshot_taken_notification_message(DialogId dialog_id);
Result<MessageId> add_local_message(
DialogId dialog_id, UserId sender_user_id, MessageId reply_to_message_id, bool disable_notification,
tl_object_ptr<td_api::InputMessageContent> &&input_message_content) TD_WARN_UNUSED_RESULT;
Result<MessageId> add_local_message(DialogId dialog_id, td_api::object_ptr<td_api::MessageSender> &&sender,
MessageId reply_to_message_id, bool disable_notification,
tl_object_ptr<td_api::InputMessageContent> &&input_message_content)
TD_WARN_UNUSED_RESULT;
void edit_message_text(FullMessageId full_message_id, tl_object_ptr<td_api::ReplyMarkup> &&reply_markup,
tl_object_ptr<td_api::InputMessageContent> &&input_message_content, Promise<Unit> &&promise);
void edit_message_live_location(FullMessageId full_message_id, tl_object_ptr<td_api::ReplyMarkup> &&reply_markup,
tl_object_ptr<td_api::location> &&input_location, Promise<Unit> &&promise);
tl_object_ptr<td_api::location> &&input_location, int32 heading,
int32 proximity_alert_radius, Promise<Unit> &&promise);
void edit_message_media(FullMessageId full_message_id, tl_object_ptr<td_api::ReplyMarkup> &&reply_markup,
tl_object_ptr<td_api::InputMessageContent> &&input_message_content, Promise<Unit> &&promise);
@ -452,7 +461,8 @@ class MessagesManager : public Actor {
void edit_inline_message_live_location(const string &inline_message_id,
tl_object_ptr<td_api::ReplyMarkup> &&reply_markup,
tl_object_ptr<td_api::location> &&input_location, Promise<Unit> &&promise);
tl_object_ptr<td_api::location> &&input_location, int32 heading,
int32 proximity_alert_radius, Promise<Unit> &&promise);
void edit_inline_message_media(const string &inline_message_id, tl_object_ptr<td_api::ReplyMarkup> &&reply_markup,
tl_object_ptr<td_api::InputMessageContent> &&input_message_content,
@ -499,8 +509,10 @@ class MessagesManager : public Actor {
void set_dialog_permissions(DialogId dialog_id, const td_api::object_ptr<td_api::chatPermissions> &permissions,
Promise<Unit> &&promise);
void pin_dialog_message(DialogId dialog_id, MessageId message_id, bool disable_notification, bool is_unpin,
Promise<Unit> &&promise);
void pin_dialog_message(DialogId dialog_id, MessageId message_id, bool disable_notification, bool only_for_self,
bool is_unpin, Promise<Unit> &&promise);
void unpin_all_dialog_messages(DialogId dialog_id, Promise<Unit> &&promise);
void add_dialog_participant(DialogId dialog_id, UserId user_id, int32 forward_limit, Promise<Unit> &&promise);
@ -560,8 +572,8 @@ class MessagesManager : public Actor {
std::pair<int32, vector<DialogId>> get_common_dialogs(UserId user_id, DialogId offset_dialog_id, int32 limit,
bool force, Promise<Unit> &&promise);
void block_dialog_from_replies(MessageId message_id, bool delete_message, bool delete_all_messages, bool report_spam,
Promise<Unit> &&promise);
void block_message_sender_from_replies(MessageId message_id, bool delete_message, bool delete_all_messages,
bool report_spam, Promise<Unit> &&promise);
std::pair<int32, vector<DialogId>> get_blocked_dialogs(int32 offset, int32 limit, int64 &random_id,
Promise<Unit> &&promise);
@ -579,6 +591,19 @@ class MessagesManager : public Actor {
FullMessageId get_replied_message(DialogId dialog_id, MessageId message_id, bool force, Promise<Unit> &&promise);
MessageId get_dialog_pinned_message(DialogId dialog_id, Promise<Unit> &&promise);
void get_callback_query_message(DialogId dialog_id, MessageId message_id, int64 callback_query_id,
Promise<Unit> &&promise);
bool get_messages(DialogId dialog_id, const vector<MessageId> &message_ids, Promise<Unit> &&promise);
void get_message_from_server(FullMessageId full_message_id, Promise<Unit> &&promise,
tl_object_ptr<telegram_api::InputMessage> input_message = nullptr);
void get_messages_from_server(vector<FullMessageId> &&message_ids, Promise<Unit> &&promise,
tl_object_ptr<telegram_api::InputMessage> input_message = nullptr);
struct MessageThreadInfo {
DialogId dialog_id;
vector<MessageId> message_ids;
@ -590,16 +615,6 @@ class MessagesManager : public Actor {
void on_get_discussion_message(DialogId dialog_id, MessageId message_id, vector<FullMessageId> full_message_ids,
Promise<MessageThreadInfo> &&promise);
MessageId get_dialog_pinned_message(DialogId dialog_id, Promise<Unit> &&promise);
bool get_messages(DialogId dialog_id, const vector<MessageId> &message_ids, Promise<Unit> &&promise);
void get_message_from_server(FullMessageId full_message_id, Promise<Unit> &&promise,
tl_object_ptr<telegram_api::InputMessage> input_message = nullptr);
void get_messages_from_server(vector<FullMessageId> &&message_ids, Promise<Unit> &&promise,
tl_object_ptr<telegram_api::InputMessage> input_message = nullptr);
bool is_message_edited_recently(FullMessageId full_message_id, int32 seconds);
Result<std::pair<string, bool>> get_message_link(FullMessageId full_message_id, bool for_group, bool for_comment);
@ -645,7 +660,8 @@ class MessagesManager : public Actor {
Status toggle_dialog_is_marked_as_unread(DialogId dialog_id, bool is_marked_as_unread) TD_WARN_UNUSED_RESULT;
Status toggle_dialog_is_blocked(DialogId dialog_id, bool is_blocked) TD_WARN_UNUSED_RESULT;
Status toggle_message_sender_is_blocked(const td_api::object_ptr<td_api::MessageSender> &sender,
bool is_blocked) TD_WARN_UNUSED_RESULT;
Status toggle_dialog_silent_send_message(DialogId dialog_id, bool silent_send_message) TD_WARN_UNUSED_RESULT;
@ -711,8 +727,9 @@ class MessagesManager : public Actor {
Promise<Unit> &&promise);
std::pair<int32, vector<MessageId>> search_dialog_messages(DialogId dialog_id, const string &query,
UserId sender_user_id, MessageId from_message_id,
int32 offset, int32 limit, MessageSearchFilter filter,
const td_api::object_ptr<td_api::MessageSender> &sender,
MessageId from_message_id, int32 offset, int32 limit,
MessageSearchFilter filter,
MessageId top_thread_message_id, int64 &random_id,
bool use_db, Promise<Unit> &&promise);
@ -1062,9 +1079,10 @@ class MessagesManager : public Actor {
bool hide_edit_date = false;
bool had_reply_markup = false; // had non-inline reply markup?
bool had_forward_info = false;
bool is_content_secret = false; // should be shown only while tapped
bool is_content_secret = false; // must be shown only while tapped
bool is_mention_notification_disabled = false;
bool is_from_scheduled = false;
bool is_pinned = false;
bool is_copy = false; // for send_message
bool from_background = false; // for send_message
@ -1164,7 +1182,7 @@ class MessagesManager : public Actor {
MessageId last_read_inbox_message_id;
int32 last_read_inbox_message_date = 0; // secret chats only
MessageId last_read_outbox_message_id;
MessageId pinned_message_id;
MessageId last_pinned_message_id;
MessageId reply_markup_message_id;
DialogNotificationSettings notification_settings;
unique_ptr<DraftMessage> draft_message;
@ -1230,7 +1248,7 @@ class MessagesManager : public Actor {
bool is_last_read_inbox_message_id_inited = false;
bool is_last_read_outbox_message_id_inited = false;
bool is_pinned_message_id_inited = false;
bool is_last_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;
@ -1609,7 +1627,7 @@ class MessagesManager : public Actor {
}
};
class BlockDialogFromRepliesOnServerLogEvent;
class BlockMessageSenderFromRepliesOnServerLogEvent;
class ChangeDialogReportSpamStateOnServerLogEvent;
class DeleteAllChannelMessagesFromUserOnServerLogEvent;
class DeleteDialogHistoryFromServerLogEvent;
@ -1635,6 +1653,7 @@ class MessagesManager : public Actor {
class ToggleDialogIsBlockedOnServerLogEvent;
class ToggleDialogIsMarkedAsUnreadOnServerLogEvent;
class ToggleDialogIsPinnedOnServerLogEvent;
class UnpinAllDialogMessagesOnServerLogEvent;
class UpdateDialogNotificationSettingsOnServerLogEvent;
class UpdateScopeNotificationSettingsOnServerLogEvent;
@ -1698,8 +1717,6 @@ class MessagesManager : public Actor {
static int32 get_message_date(const tl_object_ptr<telegram_api::Message> &message_ptr);
static tl_object_ptr<telegram_api::InputMessage> get_input_message(MessageId message_id);
static bool is_dialog_inited(const Dialog *d);
int32 get_dialog_mute_until(const Dialog *d) const;
@ -1773,6 +1790,8 @@ class MessagesManager : public Actor {
bool can_report_dialog(DialogId dialog_id) const;
Status can_pin_messages(DialogId dialog_id) const;
void cancel_edit_message_media(DialogId dialog_id, Message *m, Slice error_message);
void on_message_media_edited(DialogId dialog_id, MessageId message_id, FileId file_id, FileId thumbnail_file_id,
@ -1803,6 +1822,11 @@ class MessagesManager : public Actor {
void delete_dialog_messages_from_updates(DialogId dialog_id, const vector<MessageId> &message_ids,
bool skip_update_for_not_found_messages);
void update_dialog_pinned_messages_from_updates(DialogId dialog_id, const vector<MessageId> &message_ids,
bool is_pin);
bool update_message_is_pinned(Dialog *d, Message *m, bool is_pin, const char *source);
void do_forward_messages(DialogId to_dialog_id, DialogId from_dialog_id, const vector<Message *> &messages,
const vector<MessageId> &message_ids, uint64 log_event_id);
@ -1903,14 +1927,16 @@ class MessagesManager : public Actor {
void delete_dialog_history_from_server(DialogId dialog_id, MessageId max_message_id, bool remove_from_dialog_list,
bool revoke, bool allow_error, uint64 log_event_id, Promise<Unit> &&promise);
void block_dialog_from_replies_on_server(MessageId message_id, bool delete_message, bool delete_all_messages,
bool report_spam, uint64 log_event_id, Promise<Unit> &&promise);
void block_message_sender_from_replies_on_server(MessageId message_id, bool delete_message, bool delete_all_messages,
bool report_spam, uint64 log_event_id, Promise<Unit> &&promise);
void delete_all_channel_messages_from_user_on_server(ChannelId channel_id, UserId user_id, uint64 log_event_id,
Promise<Unit> &&promise);
void read_all_dialog_mentions_on_server(DialogId dialog_id, uint64 log_event_id, Promise<Unit> &&promise);
void unpin_all_dialog_messages_on_server(DialogId dialog_id, uint64 log_event_id, Promise<Unit> &&promise);
static MessageId find_message_by_date(const Message *m, int32 date);
static void find_messages(const Message *m, vector<MessageId> &message_ids,
@ -2294,7 +2320,9 @@ class MessagesManager : public Actor {
void set_dialog_is_blocked(Dialog *d, bool is_blocked);
void set_dialog_pinned_message_id(Dialog *d, MessageId pinned_message_id);
void set_dialog_last_pinned_message_id(Dialog *d, MessageId last_pinned_message_id);
void drop_dialog_last_pinned_message_id(Dialog *d);
void repair_dialog_scheduled_messages(Dialog *d);
@ -2404,6 +2432,8 @@ class MessagesManager : public Actor {
void send_search_public_dialogs_query(const string &query, Promise<Unit> &&promise);
void reload_dialog_info_full(DialogId dialog_id);
vector<DialogId> get_pinned_dialog_ids(DialogListId dialog_list_id) const;
void reload_pinned_dialogs(DialogListId dialog_list_id, Promise<Unit> &&promise);
@ -2877,8 +2907,8 @@ class MessagesManager : public Actor {
uint64 save_delete_dialog_history_from_server_log_event(DialogId dialog_id, MessageId max_message_id,
bool remove_from_dialog_list, bool revoke);
uint64 save_block_dialog_from_replies_on_server_log_event(MessageId message_id, bool delete_message,
bool delete_all_messages, bool report_spam);
uint64 save_block_message_sender_from_replies_on_server_log_event(MessageId message_id, bool delete_message,
bool delete_all_messages, bool report_spam);
uint64 save_delete_all_channel_messages_from_user_on_server_log_event(ChannelId channel_id, UserId user_id);
@ -2903,6 +2933,8 @@ class MessagesManager : public Actor {
uint64 save_forward_messages_log_event(DialogId to_dialog_id, DialogId from_dialog_id,
const vector<Message *> &messages, const vector<MessageId> &message_ids);
uint64 save_unpin_all_dialog_messages_on_server_log_event(DialogId dialog_id);
void suffix_load_loop(Dialog *d);
void suffix_load_update_first_message_id(Dialog *d);
void suffix_load_query_ready(DialogId dialog_id);

View File

@ -2726,6 +2726,9 @@ string NotificationManager::convert_loc_key(const string &loc_key) {
if (loc_key == "MESSAGE_DOC") {
return "MESSAGE_DOCUMENT";
}
if (loc_key == "MESSAGE_DOCS") {
return "MESSAGE_DOCUMENTS";
}
if (loc_key == "ENCRYPTED_MESSAGE") {
return "MESSAGE";
}
@ -2833,6 +2836,9 @@ string NotificationManager::convert_loc_key(const string &loc_key) {
if (loc_key == "MESSAGE_PHOTO_SECRET") {
return "MESSAGE_SECRET_PHOTO";
}
if (loc_key == "MESSAGE_PLAYLIST") {
return "MESSAGE_AUDIOS";
}
if (loc_key == "MESSAGE_POLL") {
return "MESSAGE_POLL";
}

View File

@ -156,7 +156,8 @@ class NotificationTypePushMessage : public NotificationType {
return td_api::make_object<td_api::pushMessageContentHidden>(is_pinned);
}
if (key == "MESSAGES") {
return td_api::make_object<td_api::pushMessageContentMediaAlbum>(to_integer<int32>(arg), true, true);
return td_api::make_object<td_api::pushMessageContentMediaAlbum>(to_integer<int32>(arg), true, true, false,
false);
}
CHECK(key.size() > 8);
switch (key[8]) {
@ -171,6 +172,10 @@ class NotificationTypePushMessage : public NotificationType {
return td_api::make_object<td_api::pushMessageContentAudio>(
audios_manager->get_audio_object(document.file_id), is_pinned);
}
if (key == "MESSAGE_AUDIOS") {
return td_api::make_object<td_api::pushMessageContentMediaAlbum>(to_integer<int32>(arg), false, false, true,
false);
}
break;
case 'B':
if (key == "MESSAGE_BASIC_GROUP_CHAT_CREATE") {
@ -218,6 +223,10 @@ class NotificationTypePushMessage : public NotificationType {
return td_api::make_object<td_api::pushMessageContentDocument>(
documents_manager->get_document_object(document.file_id, PhotoFormat::Jpeg), is_pinned);
}
if (key == "MESSAGE_DOCUMENTS") {
return td_api::make_object<td_api::pushMessageContentMediaAlbum>(to_integer<int32>(arg), false, false, false,
true);
}
break;
case 'F':
if (key == "MESSAGE_FORWARDS") {
@ -259,7 +268,8 @@ class NotificationTypePushMessage : public NotificationType {
is_pinned);
}
if (key == "MESSAGE_PHOTOS") {
return td_api::make_object<td_api::pushMessageContentMediaAlbum>(to_integer<int32>(arg), true, false);
return td_api::make_object<td_api::pushMessageContentMediaAlbum>(to_integer<int32>(arg), true, false, false,
false);
}
if (key == "MESSAGE_POLL") {
return td_api::make_object<td_api::pushMessageContentPoll>(arg, true, is_pinned);
@ -303,7 +313,8 @@ class NotificationTypePushMessage : public NotificationType {
video_notes_manager->get_video_note_object(document.file_id), is_pinned);
}
if (key == "MESSAGE_VIDEOS") {
return td_api::make_object<td_api::pushMessageContentMediaAlbum>(to_integer<int32>(arg), false, true);
return td_api::make_object<td_api::pushMessageContentMediaAlbum>(to_integer<int32>(arg), false, true, false,
false);
}
if (key == "MESSAGE_VOICE_NOTE") {
auto voice_notes_manager = G()->td().get_actor_unsafe()->voice_notes_manager_.get();
@ -318,10 +329,10 @@ class NotificationTypePushMessage : public NotificationType {
}
td_api::object_ptr<td_api::NotificationType> get_notification_type_object(DialogId dialog_id) const override {
auto sender_user_id = G()->td().get_actor_unsafe()->contacts_manager_->get_user_id_object(
sender_user_id_, "get_notification_type_object");
auto sender =
G()->td().get_actor_unsafe()->messages_manager_->get_message_sender_object(sender_user_id_, sender_dialog_id_);
return td_api::make_object<td_api::notificationTypeNewPushMessage>(
message_id_.get(), sender_user_id, sender_dialog_id_.get(), sender_name_, is_outgoing_,
message_id_.get(), std::move(sender), sender_name_, is_outgoing_,
get_push_message_content_object(key_, arg_, photo_, document_));
}

View File

@ -1163,7 +1163,8 @@ void StickersManager::init() {
animated_emoji_sticker_set.short_name_);
}
dice_emojis_str_ = G()->shared_config().get_option_string("dice_emojis", "🎲\x01🎯\x01🏀\x01\x01⚽️");
dice_emojis_str_ =
G()->shared_config().get_option_string("dice_emojis", "🎲\x01🎯\x01🏀\x01\x01⚽️\x01🎰");
dice_emojis_ = full_split(dice_emojis_str_, '\x01');
for (auto &dice_emoji : dice_emojis_) {
auto &animated_dice_sticker_set = add_special_sticker_set(SpecialStickerSetType::animated_dice(dice_emoji));
@ -1295,7 +1296,9 @@ void StickersManager::on_load_special_sticker_set(const SpecialStickerSetType &t
CHECK(special_sticker_set.id_.is_valid());
auto sticker_set = get_sticker_set(special_sticker_set.id_);
CHECK(sticker_set != nullptr);
if (sticker_set == nullptr) {
return;
}
CHECK(sticker_set->was_loaded);
auto it = dice_messages_.find(emoji);
@ -1381,7 +1384,7 @@ tl_object_ptr<td_api::stickers> StickersManager::get_stickers_object(const vecto
return result;
}
tl_object_ptr<td_api::sticker> StickersManager::get_dice_sticker_object(const string &emoji, int32 value) const {
tl_object_ptr<td_api::DiceStickers> StickersManager::get_dice_stickers_object(const string &emoji, int32 value) const {
if (td_->auth_manager_->is_bot()) {
return nullptr;
}
@ -1395,12 +1398,44 @@ tl_object_ptr<td_api::sticker> StickersManager::get_dice_sticker_object(const st
}
auto sticker_set_id = it->second.id_;
if (sticker_set_id.is_valid()) {
auto sticker_set = get_sticker_set(sticker_set_id);
CHECK(sticker_set != nullptr);
if (sticker_set->was_loaded && value >= 0 && value < static_cast<int32>(sticker_set->sticker_ids.size())) {
return get_sticker_object(sticker_set->sticker_ids[value]);
if (!sticker_set_id.is_valid()) {
return nullptr;
}
auto sticker_set = get_sticker_set(sticker_set_id);
if (sticker_set == nullptr) {
return nullptr;
}
if (!sticker_set->was_loaded) {
return nullptr;
}
auto get_sticker = [&](int32 value) {
return get_sticker_object(sticker_set->sticker_ids[value]);
};
if (emoji == "🎰") {
if (sticker_set->sticker_ids.size() < 21 || value < 0 || value > 64) {
return nullptr;
}
int32 background_id = value == 1 || value == 22 || value == 43 || value == 64 ? 1 : 0;
int32 lever_id = 2;
int32 left_reel_id = value == 64 ? 3 : 8;
int32 center_reel_id = value == 64 ? 9 : 14;
int32 right_reel_id = value == 64 ? 15 : 20;
if (value != 0 && value != 64) {
left_reel_id = 4 + (value % 4);
center_reel_id = 10 + ((value + 3) / 4 % 4);
right_reel_id = 16 + ((value + 15) / 16 % 4);
}
return td_api::make_object<td_api::diceStickersSlotMachine>(get_sticker(background_id), get_sticker(lever_id),
get_sticker(left_reel_id), get_sticker(center_reel_id),
get_sticker(right_reel_id));
}
if (value >= 0 && value < static_cast<int32>(sticker_set->sticker_ids.size())) {
return td_api::make_object<td_api::diceStickersRegular>(get_sticker(value));
}
return nullptr;
}
@ -3470,7 +3505,8 @@ void StickersManager::on_update_dice_emojis() {
return;
}
auto dice_emojis_str = G()->shared_config().get_option_string("dice_emojis", "🎲\x01🎯\x01🏀\x01\x01⚽️");
auto dice_emojis_str =
G()->shared_config().get_option_string("dice_emojis", "🎲\x01🎯\x01🏀\x01\x01⚽️\x01🎰");
if (dice_emojis_str == dice_emojis_str_) {
return;
}
@ -3505,7 +3541,7 @@ void StickersManager::on_update_dice_success_values() {
}
auto dice_success_values_str =
G()->shared_config().get_option_string("dice_success_values", "0,6:62,5:110,5:110,5:110");
G()->shared_config().get_option_string("dice_success_values", "0,6:62,5:110,5:110,5:110,64:110");
if (dice_success_values_str == dice_success_values_str_) {
return;
}

View File

@ -57,7 +57,7 @@ class StickersManager : public Actor {
tl_object_ptr<td_api::stickers> get_stickers_object(const vector<FileId> &sticker_ids) const;
tl_object_ptr<td_api::sticker> get_dice_sticker_object(const string &emoji, int32 value) const;
tl_object_ptr<td_api::DiceStickers> get_dice_stickers_object(const string &emoji, int32 value) const;
int32 get_dice_success_animation_frame_number(const string &emoji, int32 value) const;

View File

@ -1103,6 +1103,29 @@ class GetChatPinnedMessageRequest : public RequestOnceActor {
}
};
class GetCallbackQueryMessageRequest : public RequestOnceActor {
DialogId dialog_id_;
MessageId message_id_;
int64 callback_query_id_;
void do_run(Promise<Unit> &&promise) override {
td->messages_manager_->get_callback_query_message(dialog_id_, message_id_, callback_query_id_, std::move(promise));
}
void do_send_result() override {
send_result(td->messages_manager_->get_message_object({dialog_id_, message_id_}));
}
public:
GetCallbackQueryMessageRequest(ActorShared<Td> td, uint64 request_id, int64 dialog_id, int64 message_id,
int64 callback_query_id)
: RequestOnceActor(std::move(td), request_id)
, dialog_id_(dialog_id)
, message_id_(message_id)
, callback_query_id_(callback_query_id) {
}
};
class GetMessagesRequest : public RequestOnceActor {
DialogId dialog_id_;
vector<MessageId> message_ids_;
@ -1202,10 +1225,12 @@ class EditMessageLiveLocationRequest : public RequestOnceActor {
FullMessageId full_message_id_;
tl_object_ptr<td_api::ReplyMarkup> reply_markup_;
tl_object_ptr<td_api::location> location_;
int32 heading_;
int32 proximity_alert_radius_;
void do_run(Promise<Unit> &&promise) override {
td->messages_manager_->edit_message_live_location(full_message_id_, std::move(reply_markup_), std::move(location_),
std::move(promise));
heading_, proximity_alert_radius_, std::move(promise));
}
void do_send_result() override {
@ -1215,11 +1240,13 @@ class EditMessageLiveLocationRequest : public RequestOnceActor {
public:
EditMessageLiveLocationRequest(ActorShared<Td> td, uint64 request_id, int64 dialog_id, int64 message_id,
tl_object_ptr<td_api::ReplyMarkup> reply_markup,
tl_object_ptr<td_api::location> location)
tl_object_ptr<td_api::location> location, int32 heading, int32 proximity_alert_radius)
: RequestOnceActor(std::move(td), request_id)
, full_message_id_(DialogId(dialog_id), MessageId(message_id))
, reply_markup_(std::move(reply_markup))
, location_(std::move(location)) {
, location_(std::move(location))
, heading_(heading)
, proximity_alert_radius_(proximity_alert_radius) {
}
};
@ -1439,7 +1466,7 @@ class GetMessageThreadHistoryRequest : public RequestActor<> {
class SearchChatMessagesRequest : public RequestActor<> {
DialogId dialog_id_;
string query_;
UserId sender_user_id_;
td_api::object_ptr<td_api::MessageSender> sender_;
MessageId from_message_id_;
int32 offset_;
int32 limit_;
@ -1450,9 +1477,9 @@ class SearchChatMessagesRequest : public RequestActor<> {
std::pair<int32, vector<MessageId>> messages_;
void do_run(Promise<Unit> &&promise) override {
messages_ = td->messages_manager_->search_dialog_messages(dialog_id_, query_, sender_user_id_, from_message_id_,
offset_, limit_, filter_, top_thread_message_id_,
random_id_, get_tries() == 3, std::move(promise));
messages_ = td->messages_manager_->search_dialog_messages(dialog_id_, query_, sender_, from_message_id_, offset_,
limit_, filter_, top_thread_message_id_, random_id_,
get_tries() == 3, std::move(promise));
}
void do_send_result() override {
@ -1469,13 +1496,13 @@ class SearchChatMessagesRequest : public RequestActor<> {
}
public:
SearchChatMessagesRequest(ActorShared<Td> td, uint64 request_id, int64 dialog_id, string query, int32 user_id,
int64 from_message_id, int32 offset, int32 limit,
tl_object_ptr<td_api::SearchMessagesFilter> filter, int64 message_thread_id)
SearchChatMessagesRequest(ActorShared<Td> td, uint64 request_id, int64 dialog_id, string query,
td_api::object_ptr<td_api::MessageSender> sender, int64 from_message_id, int32 offset,
int32 limit, tl_object_ptr<td_api::SearchMessagesFilter> filter, int64 message_thread_id)
: RequestActor(std::move(td), request_id)
, dialog_id_(dialog_id)
, query_(std::move(query))
, sender_user_id_(user_id)
, sender_(std::move(sender))
, from_message_id_(from_message_id)
, offset_(offset)
, limit_(limit)
@ -2093,23 +2120,27 @@ class GetChatEventLogRequest : public RequestOnceActor {
}
};
class GetBlockedChatsRequest : public RequestActor<> {
class GetBlockedMessageSendersRequest : public RequestActor<> {
int32 offset_;
int32 limit_;
int64 random_id_;
std::pair<int32, vector<DialogId>> dialog_ids_;
std::pair<int32, vector<DialogId>> message_senders_;
void do_run(Promise<Unit> &&promise) override {
dialog_ids_ = td->messages_manager_->get_blocked_dialogs(offset_, limit_, random_id_, std::move(promise));
message_senders_ = td->messages_manager_->get_blocked_dialogs(offset_, limit_, random_id_, std::move(promise));
}
void do_send_result() override {
send_result(MessagesManager::get_chats_object(dialog_ids_));
auto senders =
transform(message_senders_.second, [messages_manager = td->messages_manager_.get()](DialogId dialog_id) {
return messages_manager->get_message_sender_object(dialog_id);
});
send_result(td_api::make_object<td_api::messageSenders>(message_senders_.first, std::move(senders)));
}
public:
GetBlockedChatsRequest(ActorShared<Td> td, uint64 request_id, int32 offset, int32 limit)
GetBlockedMessageSendersRequest(ActorShared<Td> td, uint64 request_id, int32 offset, int32 limit)
: RequestActor(std::move(td), request_id), offset_(offset), limit_(limit), random_id_(0) {
}
};
@ -5164,15 +5195,20 @@ void Td::on_request(uint64 id, const td_api::getChatPinnedMessage &request) {
CREATE_REQUEST(GetChatPinnedMessageRequest, request.chat_id_);
}
void Td::on_request(uint64 id, const td_api::getMessageThread &request) {
CHECK_IS_USER();
CREATE_REQUEST(GetMessageThreadRequest, request.chat_id_, request.message_id_);
void Td::on_request(uint64 id, const td_api::getCallbackQueryMessage &request) {
CHECK_IS_BOT();
CREATE_REQUEST(GetCallbackQueryMessageRequest, request.chat_id_, request.message_id_, request.callback_query_id_);
}
void Td::on_request(uint64 id, const td_api::getMessages &request) {
CREATE_REQUEST(GetMessagesRequest, request.chat_id_, request.message_ids_);
}
void Td::on_request(uint64 id, const td_api::getMessageThread &request) {
CHECK_IS_USER();
CREATE_REQUEST(GetMessageThreadRequest, request.chat_id_, request.message_id_);
}
void Td::on_request(uint64 id, const td_api::getMessageLink &request) {
auto r_message_link = messages_manager_->get_message_link(
{DialogId(request.chat_id_), MessageId(request.message_id_)}, request.for_album_, request.for_comment_);
@ -5577,7 +5613,7 @@ void Td::on_request(uint64 id, const td_api::getMessageThreadHistory &request) {
void Td::on_request(uint64 id, td_api::searchChatMessages &request) {
CHECK_IS_USER();
CLEAN_INPUT_STRING(request.query_);
CREATE_REQUEST(SearchChatMessagesRequest, request.chat_id_, std::move(request.query_), request.sender_user_id_,
CREATE_REQUEST(SearchChatMessagesRequest, request.chat_id_, std::move(request.query_), std::move(request.sender_),
request.from_message_id_, request.offset_, request.limit_, std::move(request.filter_),
request.message_thread_id_);
}
@ -5750,8 +5786,8 @@ void Td::on_request(uint64 id, td_api::addLocalMessage &request) {
DialogId dialog_id(request.chat_id_);
auto r_new_message_id = messages_manager_->add_local_message(
dialog_id, UserId(request.sender_user_id_), MessageId(request.reply_to_message_id_),
request.disable_notification_, std::move(request.input_message_content_));
dialog_id, std::move(request.sender_), MessageId(request.reply_to_message_id_), request.disable_notification_,
std::move(request.input_message_content_));
if (r_new_message_id.is_error()) {
return send_closure(actor_id(this), &Td::send_error, id, r_new_message_id.move_as_error());
}
@ -5768,7 +5804,8 @@ void Td::on_request(uint64 id, td_api::editMessageText &request) {
void Td::on_request(uint64 id, td_api::editMessageLiveLocation &request) {
CREATE_REQUEST(EditMessageLiveLocationRequest, request.chat_id_, request.message_id_,
std::move(request.reply_markup_), std::move(request.location_));
std::move(request.reply_markup_), std::move(request.location_), request.heading_,
request.proximity_alert_radius_);
}
void Td::on_request(uint64 id, td_api::editMessageMedia &request) {
@ -5799,9 +5836,9 @@ void Td::on_request(uint64 id, td_api::editInlineMessageLiveLocation &request) {
CHECK_IS_BOT();
CLEAN_INPUT_STRING(request.inline_message_id_);
CREATE_OK_REQUEST_PROMISE();
messages_manager_->edit_inline_message_live_location(std::move(request.inline_message_id_),
std::move(request.reply_markup_), std::move(request.location_),
std::move(promise));
messages_manager_->edit_inline_message_live_location(
std::move(request.inline_message_id_), std::move(request.reply_markup_), std::move(request.location_),
request.heading_, request.proximity_alert_radius_, std::move(promise));
}
void Td::on_request(uint64 id, td_api::editInlineMessageMedia &request) {
@ -6123,9 +6160,9 @@ void Td::on_request(uint64 id, const td_api::toggleChatIsMarkedAsUnread &request
request.is_marked_as_unread_));
}
void Td::on_request(uint64 id, const td_api::toggleChatIsBlocked &request) {
void Td::on_request(uint64 id, const td_api::toggleMessageSenderIsBlocked &request) {
CHECK_IS_USER();
answer_ok_query(id, messages_manager_->toggle_dialog_is_blocked(DialogId(request.chat_id_), request.is_blocked_));
answer_ok_query(id, messages_manager_->toggle_message_sender_is_blocked(request.sender_, request.is_blocked_));
}
void Td::on_request(uint64 id, const td_api::toggleChatDefaultDisableNotification &request) {
@ -6176,12 +6213,19 @@ void Td::on_request(uint64 id, const td_api::setChatSlowModeDelay &request) {
void Td::on_request(uint64 id, const td_api::pinChatMessage &request) {
CREATE_OK_REQUEST_PROMISE();
messages_manager_->pin_dialog_message(DialogId(request.chat_id_), MessageId(request.message_id_),
request.disable_notification_, false, std::move(promise));
request.disable_notification_, request.only_for_self_, false,
std::move(promise));
}
void Td::on_request(uint64 id, const td_api::unpinChatMessage &request) {
CREATE_OK_REQUEST_PROMISE();
messages_manager_->pin_dialog_message(DialogId(request.chat_id_), MessageId(), false, true, std::move(promise));
messages_manager_->pin_dialog_message(DialogId(request.chat_id_), MessageId(request.message_id_), false, false, true,
std::move(promise));
}
void Td::on_request(uint64 id, const td_api::unpinAllChatMessages &request) {
CREATE_OK_REQUEST_PROMISE();
messages_manager_->unpin_all_dialog_messages(DialogId(request.chat_id_), std::move(promise));
}
void Td::on_request(uint64 id, const td_api::joinChat &request) {
@ -6451,16 +6495,17 @@ void Td::on_request(uint64 id, const td_api::deleteFile &request) {
"td_api::deleteFile");
}
void Td::on_request(uint64 id, const td_api::blockChatFromReplies &request) {
void Td::on_request(uint64 id, const td_api::blockMessageSenderFromReplies &request) {
CHECK_IS_USER();
CREATE_OK_REQUEST_PROMISE();
messages_manager_->block_dialog_from_replies(MessageId(request.message_id_), request.delete_message_,
request.delete_all_messages_, request.report_spam_, std::move(promise));
messages_manager_->block_message_sender_from_replies(MessageId(request.message_id_), request.delete_message_,
request.delete_all_messages_, request.report_spam_,
std::move(promise));
}
void Td::on_request(uint64 id, const td_api::getBlockedChats &request) {
void Td::on_request(uint64 id, const td_api::getBlockedMessageSenders &request) {
CHECK_IS_USER();
CREATE_REQUEST(GetBlockedChatsRequest, request.offset_, request.limit_);
CREATE_REQUEST(GetBlockedMessageSendersRequest, request.offset_, request.limit_);
}
void Td::on_request(uint64 id, td_api::addContact &request) {
@ -7321,6 +7366,12 @@ void Td::on_request(uint64 id, td_api::setOption &request) {
return;
}
break;
case 'r':
// temporary option
if (set_boolean_option("reuse_uploaded_photos_by_hash")) {
return;
}
break;
case 's':
if (set_integer_option("session_count", 0, 50)) {
return;

View File

@ -241,7 +241,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.6.9";
static constexpr const char *TDLIB_VERSION = "1.6.10";
static constexpr int64 ONLINE_ALARM_ID = 0;
static constexpr int64 PING_SERVER_ALARM_ID = -1;
static constexpr int32 PING_SERVER_TIMEOUT = 300;
@ -502,6 +502,8 @@ class Td final : public NetQueryCallback {
void on_request(uint64 id, const td_api::getChatPinnedMessage &request);
void on_request(uint64 id, const td_api::getCallbackQueryMessage &request);
void on_request(uint64 id, const td_api::getMessageThread &request);
void on_request(uint64 id, const td_api::getMessages &request);
@ -730,7 +732,7 @@ class Td final : public NetQueryCallback {
void on_request(uint64 id, const td_api::toggleChatIsMarkedAsUnread &request);
void on_request(uint64 id, const td_api::toggleChatIsBlocked &request);
void on_request(uint64 id, const td_api::toggleMessageSenderIsBlocked &request);
void on_request(uint64 id, const td_api::toggleChatDefaultDisableNotification &request);
@ -750,6 +752,8 @@ class Td final : public NetQueryCallback {
void on_request(uint64 id, const td_api::unpinChatMessage &request);
void on_request(uint64 id, const td_api::unpinAllChatMessages &request);
void on_request(uint64 id, const td_api::joinChat &request);
void on_request(uint64 id, const td_api::leaveChat &request);
@ -800,9 +804,9 @@ class Td final : public NetQueryCallback {
void on_request(uint64 id, const td_api::deleteFile &request);
void on_request(uint64 id, const td_api::blockChatFromReplies &request);
void on_request(uint64 id, const td_api::blockMessageSenderFromReplies &request);
void on_request(uint64 id, const td_api::getBlockedChats &request);
void on_request(uint64 id, const td_api::getBlockedMessageSenders &request);
void on_request(uint64 id, td_api::addContact &request);

View File

@ -114,7 +114,8 @@ Status init_binlog(Binlog &binlog, string path, BinlogKeyValue<Binlog> &binlog_p
case LogEvent::HandlerType::DeleteScheduledMessagesFromServer:
case LogEvent::HandlerType::ToggleDialogIsBlockedOnServer:
case LogEvent::HandlerType::ReadMessageThreadHistoryOnServer:
case LogEvent::HandlerType::BlockDialogFromRepliesOnServer:
case LogEvent::HandlerType::BlockMessageSenderFromRepliesOnServer:
case LogEvent::HandlerType::UnpinAllDialogMessagesOnServer:
events.to_messages_manager.push_back(event.clone());
break;
case LogEvent::HandlerType::AddMessagePushNotification:

View File

@ -604,6 +604,16 @@ bool UpdatesManager::is_acceptable_message(const telegram_api::Message *message_
}
break;
}
case telegram_api::messageActionGeoProximityReached::ID: {
auto geo_proximity_reached = static_cast<const telegram_api::messageActionGeoProximityReached *>(action);
if (!is_acceptable_peer(geo_proximity_reached->from_id_)) {
return false;
}
if (!is_acceptable_peer(geo_proximity_reached->to_id_)) {
return false;
}
break;
}
default:
UNREACHABLE();
return false;
@ -704,16 +714,17 @@ void UpdatesManager::on_get_updates(tl_object_ptr<telegram_api::Updates> &&updat
auto from_id = update->flags_ & MessagesManager::MESSAGE_FLAG_IS_OUT ? td_->contacts_manager_->get_my_id().get()
: update->user_id_;
update->flags_ |= MessagesManager::MESSAGE_FLAG_HAS_FROM_ID;
on_pending_update(make_tl_object<telegram_api::updateNewMessage>(
make_tl_object<telegram_api::message>(
update->flags_, false /*ignored*/, false /*ignored*/, false /*ignored*/,
false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/,
false /*ignored*/, update->id_, make_tl_object<telegram_api::peerUser>(from_id),
make_tl_object<telegram_api::peerUser>(update->user_id_), std::move(update->fwd_from_),
update->via_bot_id_, std::move(update->reply_to_), update->date_, update->message_,
nullptr, nullptr, std::move(update->entities_), 0, 0, nullptr, 0, string(), 0, Auto()),
update->pts_, update->pts_count_),
0, "telegram_api::updatesShortMessage");
on_pending_update(
make_tl_object<telegram_api::updateNewMessage>(
make_tl_object<telegram_api::message>(
update->flags_, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/,
false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/,
update->id_, make_tl_object<telegram_api::peerUser>(from_id),
make_tl_object<telegram_api::peerUser>(update->user_id_), std::move(update->fwd_from_),
update->via_bot_id_, std::move(update->reply_to_), update->date_, update->message_, nullptr, nullptr,
std::move(update->entities_), 0, 0, nullptr, 0, string(), 0, Auto()),
update->pts_, update->pts_count_),
0, "telegram_api::updatesShortMessage");
break;
}
case telegram_api::updateShortChatMessage::ID: {
@ -732,8 +743,8 @@ void UpdatesManager::on_get_updates(tl_object_ptr<telegram_api::Updates> &&updat
make_tl_object<telegram_api::updateNewMessage>(
make_tl_object<telegram_api::message>(
update->flags_, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/,
false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, update->id_,
make_tl_object<telegram_api::peerUser>(update->from_id_),
false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/,
update->id_, make_tl_object<telegram_api::peerUser>(update->from_id_),
make_tl_object<telegram_api::peerChat>(update->chat_id_), std::move(update->fwd_from_),
update->via_bot_id_, std::move(update->reply_to_), update->date_, update->message_, nullptr, nullptr,
std::move(update->entities_), 0, 0, nullptr, 0, string(), 0, Auto()),
@ -1325,8 +1336,8 @@ void UpdatesManager::on_pending_updates(vector<tl_object_ptr<telegram_api::Updat
if (id == telegram_api::updateNewMessage::ID || id == telegram_api::updateReadMessagesContents::ID ||
id == telegram_api::updateEditMessage::ID || id == telegram_api::updateDeleteMessages::ID ||
id == telegram_api::updateReadHistoryInbox::ID || id == telegram_api::updateReadHistoryOutbox::ID ||
id == telegram_api::updateWebPage::ID || id == telegram_api::updateNewEncryptedMessage::ID ||
id == telegram_api::updateChannelParticipant::ID) {
id == telegram_api::updateWebPage::ID || id == telegram_api::updatePinnedMessages::ID ||
id == telegram_api::updateNewEncryptedMessage::ID || id == telegram_api::updateChannelParticipant::ID) {
if (!downcast_call(*update, OnUpdate(this, update, false))) {
LOG(ERROR) << "Can't call on some update received from " << source;
}
@ -1744,19 +1755,25 @@ void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateReadChannelDisc
MessageId(), MessageId(ServerMessageId(update->read_max_id_)));
}
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateUserPinnedMessage> update, bool /*force_apply*/) {
td_->messages_manager_->on_update_dialog_pinned_message_id(DialogId(UserId(update->user_id_)),
MessageId(ServerMessageId(update->id_)));
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updatePinnedMessages> update, bool force_apply) {
CHECK(update != nullptr);
int new_pts = update->pts_;
int pts_count = update->pts_count_;
td_->messages_manager_->add_pending_update(std::move(update), new_pts, pts_count, force_apply,
"on_updatePinnedMessages");
}
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateChatPinnedMessage> update, bool /*force_apply*/) {
td_->contacts_manager_->on_update_chat_pinned_message(ChatId(update->chat_id_),
MessageId(ServerMessageId(update->id_)), update->version_);
}
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateChannelPinnedMessage> update, bool /*force_apply*/) {
td_->messages_manager_->on_update_dialog_pinned_message_id(DialogId(ChannelId(update->channel_id_)),
MessageId(ServerMessageId(update->id_)));
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updatePinnedChannelMessages> update, bool /*force_apply*/) {
ChannelId channel_id(update->channel_id_);
if (!channel_id.is_valid()) {
LOG(ERROR) << "Receive invalid " << channel_id;
return;
}
DialogId dialog_id(channel_id);
int new_pts = update->pts_;
int pts_count = update->pts_count_;
td_->messages_manager_->add_pending_channel_update(dialog_id, std::move(update), new_pts, pts_count,
"on_updatePinnedChannelMessages");
}
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateNotifySettings> update, bool /*force_apply*/) {
@ -1836,74 +1853,31 @@ int32 UpdatesManager::get_short_update_date() const {
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateUserTyping> update, bool /*force_apply*/) {
UserId user_id(update->user_id_);
if (!td_->contacts_manager_->have_min_user(user_id)) {
LOG(DEBUG) << "Ignore user typing of unknown " << user_id;
return;
}
DialogId dialog_id(user_id);
if (!td_->messages_manager_->have_dialog(dialog_id)) {
LOG(DEBUG) << "Ignore user typing in unknown " << dialog_id;
return;
}
td_->messages_manager_->on_user_dialog_action(dialog_id, MessageId(), user_id,
td_->messages_manager_->on_user_dialog_action(DialogId(user_id), MessageId(), user_id,
DialogAction(std::move(update->action_)), get_short_update_date());
}
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateChatUserTyping> update, bool /*force_apply*/) {
UserId user_id(update->user_id_);
if (!td_->contacts_manager_->have_min_user(user_id)) {
LOG(DEBUG) << "Ignore user chat typing of unknown " << user_id;
return;
}
DialogId dialog_id(ChatId(update->chat_id_));
if (!td_->messages_manager_->have_dialog(dialog_id)) {
LOG(DEBUG) << "Ignore user chat typing in unknown " << dialog_id;
return;
}
td_->messages_manager_->on_user_dialog_action(dialog_id, MessageId(), user_id,
DialogAction(std::move(update->action_)), get_short_update_date());
td_->messages_manager_->on_user_dialog_action(DialogId(ChatId(update->chat_id_)), MessageId(),
UserId(update->user_id_), DialogAction(std::move(update->action_)),
get_short_update_date());
}
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateChannelUserTyping> update, bool /*force_apply*/) {
UserId user_id(update->user_id_);
if (!td_->contacts_manager_->have_min_user(user_id)) {
LOG(DEBUG) << "Ignore user channel typing of unknown " << user_id;
return;
}
DialogId dialog_id(ChannelId(update->channel_id_));
if (!td_->messages_manager_->have_dialog(dialog_id)) {
LOG(DEBUG) << "Ignore user channel typing in unknown " << dialog_id;
return;
}
MessageId top_thread_message_id;
if ((update->flags_ & telegram_api::updateChannelUserTyping::TOP_MSG_ID_MASK) != 0) {
top_thread_message_id = MessageId(ServerMessageId(update->top_msg_id_));
if (!top_thread_message_id.is_valid() && top_thread_message_id != MessageId()) {
LOG(ERROR) << "Ignore user channel typing in the message thread of " << top_thread_message_id;
return;
}
}
td_->messages_manager_->on_user_dialog_action(dialog_id, top_thread_message_id, user_id,
DialogAction(std::move(update->action_)), get_short_update_date());
td_->messages_manager_->on_user_dialog_action(DialogId(ChannelId(update->channel_id_)), top_thread_message_id,
UserId(update->user_id_), DialogAction(std::move(update->action_)),
get_short_update_date());
}
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateEncryptedChatTyping> update, bool /*force_apply*/) {
SecretChatId secret_chat_id(update->chat_id_);
DialogId dialog_id(secret_chat_id);
if (!td_->messages_manager_->have_dialog(dialog_id)) {
LOG(DEBUG) << "Ignore secret chat typing in unknown " << dialog_id;
return;
}
UserId user_id = td_->contacts_manager_->get_secret_chat_user_id(secret_chat_id);
if (!td_->contacts_manager_->have_user_force(user_id)) {
LOG(DEBUG) << "Ignore secret chat typing of unknown " << user_id;
return;
}
td_->messages_manager_->on_user_dialog_action(dialog_id, MessageId(), user_id, DialogAction::get_typing_action(),
get_short_update_date());
td_->messages_manager_->on_user_dialog_action(DialogId(secret_chat_id), MessageId(), user_id,
DialogAction::get_typing_action(), get_short_update_date());
}
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updateUserStatus> update, bool /*force_apply*/) {

View File

@ -250,9 +250,8 @@ class UpdatesManager : public Actor {
void on_update(tl_object_ptr<telegram_api::updateReadChannelDiscussionInbox> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateReadChannelDiscussionOutbox> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateUserPinnedMessage> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateChatPinnedMessage> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updateChannelPinnedMessage> update, bool /*force_apply*/);
void on_update(tl_object_ptr<telegram_api::updatePinnedMessages> update, bool force_apply);
void on_update(tl_object_ptr<telegram_api::updatePinnedChannelMessages> update, bool force_apply);
void on_update(tl_object_ptr<telegram_api::updateDraftMessage> update, bool /*force_apply*/);

View File

@ -8,7 +8,7 @@
namespace td {
constexpr int32 MTPROTO_LAYER = 119;
constexpr int32 MTPROTO_LAYER = 120;
enum class Version : int32 {
Initial, // 0
@ -40,6 +40,8 @@ enum class Version : int32 {
AddAnimationStickers,
AddDialogPhotoHasAnimation,
AddPhotoProgressiveSizes,
AddLiveLocationHeading,
AddLiveLocationProximityAlertDistance, // 30
Next
};

View File

@ -322,7 +322,7 @@ class CliClient final : public Actor {
auto last_message_id = messages.messages_.back()->id_;
LOG(ERROR) << (last_message_id >> 20);
send_request(td_api::make_object<td_api::searchChatMessages>(
search_chat_id_, "", 0, last_message_id, 0, 100,
search_chat_id_, "", nullptr, last_message_id, 0, 100,
td_api::make_object<td_api::searchMessagesFilterPhotoAndVideo>(), 0));
} else {
search_chat_id_ = 0;
@ -514,6 +514,15 @@ class CliClient final : public Actor {
return as_message_id(str);
}
td_api::object_ptr<td_api::MessageSender> as_message_sender(Slice sender_id) const {
sender_id = trim(sender_id);
if (sender_id.empty() || sender_id[0] != '-') {
return td_api::make_object<td_api::messageSenderUser>(as_user_id(sender_id));
} else {
return td_api::make_object<td_api::messageSenderChat>(as_chat_id(sender_id));
}
}
static int32 as_button_id(Slice str) {
return to_integer<int32>(trim(str));
}
@ -631,11 +640,11 @@ class CliClient final : public Actor {
return to_integer<int32>(trim(std::move(str)));
}
static td_api::object_ptr<td_api::location> as_location(string latitude, string longitude) {
static td_api::object_ptr<td_api::location> as_location(string latitude, string longitude, string accuracy = "") {
if (trim(latitude).empty() && trim(longitude).empty()) {
return nullptr;
}
return td_api::make_object<td_api::location>(to_double(latitude), to_double(longitude));
return td_api::make_object<td_api::location>(to_double(latitude), to_double(longitude), to_double(accuracy));
}
static bool as_bool(string str) {
@ -1068,6 +1077,9 @@ class CliClient final : public Actor {
if (filter == "f" || filter == "failed") {
return td_api::make_object<td_api::searchMessagesFilterFailedToSend>();
}
if (filter == "pi" || filter == "pinned") {
return td_api::make_object<td_api::searchMessagesFilterPinned>();
}
if (!filter.empty()) {
LOG(ERROR) << "Unsupported message filter " << filter;
}
@ -1092,6 +1104,9 @@ class CliClient final : public Actor {
if (filter == "m" || filter == "members") {
return td_api::make_object<td_api::chatMembersFilterMembers>();
}
if (begins_with(filter, "@")) {
return td_api::make_object<td_api::chatMembersFilterMention>(as_message_thread_id(filter.substr(1)));
}
if (filter == "r" || filter == "rest" || filter == "restricted") {
return td_api::make_object<td_api::chatMembersFilterRestricted>();
}
@ -1882,13 +1897,14 @@ class CliClient final : public Actor {
string message_thread_id;
std::tie(chat_id, message_thread_id) = split(args);
send_request(td_api::make_object<td_api::searchChatMessages>(as_chat_id(chat_id), "", 0, 0, 0, 100, nullptr,
send_request(td_api::make_object<td_api::searchChatMessages>(as_chat_id(chat_id), "", nullptr, 0, 0, 100, nullptr,
as_message_thread_id(message_thread_id)));
} else if (op == "spvf") {
search_chat_id_ = as_chat_id(args);
send_request(td_api::make_object<td_api::searchChatMessages>(
search_chat_id_, "", 0, 0, 0, 100, td_api::make_object<td_api::searchMessagesFilterPhotoAndVideo>(), 0));
search_chat_id_, "", nullptr, 0, 0, 100, td_api::make_object<td_api::searchMessagesFilterPhotoAndVideo>(),
0));
} else if (op == "Search" || op == "SearchA" || op == "SearchM") {
string from_date;
string limit;
@ -1922,7 +1938,7 @@ class CliClient final : public Actor {
limit = "10";
}
send_request(td_api::make_object<td_api::searchChatMessages>(as_chat_id(chat_id), query, 0, 0, 0,
send_request(td_api::make_object<td_api::searchChatMessages>(as_chat_id(chat_id), query, nullptr, 0, 0,
to_integer<int32>(limit), nullptr, 0));
} else if (op == "SMME") {
string chat_id;
@ -1933,21 +1949,22 @@ class CliClient final : public Actor {
limit = "10";
}
send_request(td_api::make_object<td_api::searchChatMessages>(as_chat_id(chat_id), "", my_id_, 0, 0,
to_integer<int32>(limit), nullptr, 0));
} else if (op == "SMU") {
send_request(td_api::make_object<td_api::searchChatMessages>(
as_chat_id(chat_id), "", td_api::make_object<td_api::messageSenderUser>(my_id_), 0, 0,
to_integer<int32>(limit), nullptr, 0));
} else if (op == "SMU" || op == "SMC") {
string chat_id;
string user_id;
string sender_id;
string limit;
std::tie(chat_id, args) = split(args);
std::tie(user_id, limit) = split(args);
std::tie(sender_id, limit) = split(args);
if (limit.empty()) {
limit = "10";
}
send_request(td_api::make_object<td_api::searchChatMessages>(as_chat_id(chat_id), "", as_user_id(user_id), 0, 0,
to_integer<int32>(limit), nullptr, 0));
send_request(td_api::make_object<td_api::searchChatMessages>(
as_chat_id(chat_id), "", as_message_sender(sender_id), 0, 0, to_integer<int32>(limit), nullptr, 0));
} else if (op == "SM") {
string chat_id;
string filter;
@ -1970,7 +1987,7 @@ class CliClient final : public Actor {
}
send_request(td_api::make_object<td_api::searchChatMessages>(
as_chat_id(chat_id), "", 0, as_message_id(offset_message_id), to_integer<int32>(offset),
as_chat_id(chat_id), "", nullptr, as_message_id(offset_message_id), to_integer<int32>(offset),
to_integer<int32>(limit), as_search_messages_filter(filter), 0));
} else if (op == "SC") {
string limit;
@ -2015,7 +2032,7 @@ class CliClient final : public Actor {
limit = "10";
}
send_request(td_api::make_object<td_api::searchChatMessages>(
as_chat_id(chat_id), query, 0, as_message_id(offset_message_id), 0, to_integer<int32>(limit),
as_chat_id(chat_id), query, nullptr, as_message_id(offset_message_id), 0, to_integer<int32>(limit),
td_api::make_object<td_api::searchMessagesFilterAudio>(), 0));
} else if (op == "SearchDocument") {
string chat_id;
@ -2033,7 +2050,7 @@ class CliClient final : public Actor {
limit = "10";
}
send_request(td_api::make_object<td_api::searchChatMessages>(
as_chat_id(chat_id), query, 0, to_integer<int64>(offset_message_id), 0, to_integer<int32>(limit),
as_chat_id(chat_id), query, nullptr, to_integer<int64>(offset_message_id), 0, to_integer<int32>(limit),
td_api::make_object<td_api::searchMessagesFilterDocument>(), 0));
} else if (op == "SearchPhoto") {
string chat_id;
@ -2051,7 +2068,7 @@ class CliClient final : public Actor {
limit = "10";
}
send_request(td_api::make_object<td_api::searchChatMessages>(
as_chat_id(chat_id), query, 0, as_message_id(offset_message_id), 0, to_integer<int32>(limit),
as_chat_id(chat_id), query, nullptr, as_message_id(offset_message_id), 0, to_integer<int32>(limit),
td_api::make_object<td_api::searchMessagesFilterPhoto>(), 0));
} else if (op == "SearchChatPhoto") {
string chat_id;
@ -2069,7 +2086,7 @@ class CliClient final : public Actor {
limit = "10";
}
send_request(td_api::make_object<td_api::searchChatMessages>(
as_chat_id(chat_id), query, 0, as_message_id(offset_message_id), 0, to_integer<int32>(limit),
as_chat_id(chat_id), query, nullptr, as_message_id(offset_message_id), 0, to_integer<int32>(limit),
td_api::make_object<td_api::searchMessagesFilterChatPhoto>(), 0));
} else if (op == "gcmc") {
string chat_id;
@ -2306,7 +2323,7 @@ class CliClient final : public Actor {
send_request(td_api::make_object<td_api::getDeepLinkInfo>(args));
} else if (op == "tme") {
send_request(td_api::make_object<td_api::getRecentlyVisitedTMeUrls>(args));
} else if (op == "gbc") {
} else if (op == "gbms") {
string offset;
string limit;
@ -2317,7 +2334,8 @@ class CliClient final : public Actor {
if (limit.empty()) {
limit = "10";
}
send_request(td_api::make_object<td_api::getBlockedChats>(to_integer<int32>(offset), to_integer<int32>(limit)));
send_request(
td_api::make_object<td_api::getBlockedMessageSenders>(to_integer<int32>(offset), to_integer<int32>(limit)));
} else if (op == "gu") {
send_request(td_api::make_object<td_api::getUser>(as_user_id(args)));
} else if (op == "gsu") {
@ -2548,17 +2566,21 @@ class CliClient final : public Actor {
send_request(td_api::make_object<td_api::getChatAdministrators>(as_chat_id(chat_id)));
} else if (op == "GetSupergroupAdministrators" || op == "GetSupergroupBanned" || op == "GetSupergroupBots" ||
op == "GetSupergroupContacts" || op == "GetSupergroupMembers" || op == "GetSupergroupRestricted" ||
op == "SearchSupergroupMembers") {
op == "SearchSupergroupMembers" || op == "SearchSupergroupMentions") {
string supergroup_id;
string query;
string message_thread_id;
string offset;
string limit;
std::tie(supergroup_id, args) = split(args);
if (op == "GetSupergroupBanned" || op == "GetSupergroupContacts" || op == "GetSupergroupRestricted" ||
op == "SearchSupergroupMembers") {
op == "SearchSupergroupMembers" || op == "SearchSupergroupMentions") {
std::tie(query, args) = split(args);
}
if (op == "SearchSupergroupMentions") {
std::tie(message_thread_id, args) = split(args);
}
std::tie(offset, limit) = split(args);
if (offset.empty()) {
offset = "0";
@ -2581,6 +2603,9 @@ class CliClient final : public Actor {
filter = td_api::make_object<td_api::supergroupMembersFilterRestricted>(query);
} else if (op == "SearchSupergroupMembers") {
filter = td_api::make_object<td_api::supergroupMembersFilterSearch>(query);
} else if (op == "SearchSupergroupMentions") {
filter =
td_api::make_object<td_api::supergroupMembersFilterMention>(query, as_message_thread_id(message_thread_id));
}
send_request(td_api::make_object<td_api::getSupergroupMembers>(
as_supergroup_id(supergroup_id), std::move(filter), to_integer<int32>(offset), to_integer<int32>(limit)));
@ -2935,12 +2960,13 @@ class CliClient final : public Actor {
std::tie(chat_id, is_marked_as_read) = split(args);
send_request(
td_api::make_object<td_api::toggleChatIsMarkedAsUnread>(as_chat_id(chat_id), as_bool(is_marked_as_read)));
} else if (op == "tcib") {
} else if (op == "tmsib") {
string chat_id;
string is_blocked;
std::tie(chat_id, is_blocked) = split(args);
send_request(td_api::make_object<td_api::toggleChatIsBlocked>(as_chat_id(chat_id), as_bool(is_blocked)));
} else if (op == "bcfr") {
send_request(
td_api::make_object<td_api::toggleMessageSenderIsBlocked>(as_message_sender(chat_id), as_bool(is_blocked)));
} else if (op == "bmsfr") {
string message_id;
string delete_message;
string delete_all_messages;
@ -2948,7 +2974,7 @@ class CliClient final : public Actor {
std::tie(message_id, args) = split(args);
std::tie(delete_message, args) = split(args);
std::tie(delete_all_messages, report_spam) = split(args);
send_request(td_api::make_object<td_api::blockChatFromReplies>(
send_request(td_api::make_object<td_api::blockMessageSenderFromReplies>(
as_message_id(message_id), as_bool(delete_message), as_bool(delete_all_messages), as_bool(report_spam)));
} else if (op == "tcddn") {
string chat_id;
@ -3020,18 +3046,18 @@ class CliClient final : public Actor {
op == "sms", false, as_message_id(reply_to_message_id));
} else if (op == "alm" || op == "almr") {
string chat_id;
string user_id;
string sender_id;
string reply_to_message_id;
string message;
std::tie(chat_id, args) = split(args);
std::tie(user_id, message) = split(args);
std::tie(sender_id, message) = split(args);
if (op == "almr") {
std::tie(reply_to_message_id, message) = split(message);
}
send_request(td_api::make_object<td_api::addLocalMessage>(
as_chat_id(chat_id), as_user_id(user_id), as_message_id(reply_to_message_id), false,
as_chat_id(chat_id), as_message_sender(sender_id), as_message_id(reply_to_message_id), false,
td_api::make_object<td_api::inputMessageText>(as_formatted_text(message), false, true)));
} else if (op == "smap" || op == "smapr") {
string chat_id;
@ -3046,9 +3072,23 @@ class CliClient final : public Actor {
send_request(td_api::make_object<td_api::sendMessageAlbum>(
as_chat_id(chat_id), as_message_thread_id(message_thread_id_), as_message_id(reply_to_message_id),
default_message_send_options(), transform(photos, [](const string &photo_path) {
default_message_send_options(), transform(photos, [](const string &photo) {
td_api::object_ptr<td_api::InputMessageContent> content = td_api::make_object<td_api::inputMessagePhoto>(
as_input_file(photo_path), nullptr, Auto(), 0, 0, as_caption(""), 0);
as_input_file(photo), nullptr, Auto(), 0, 0, as_caption(""), 0);
return content;
})));
} else if (op == "smad") {
string chat_id;
vector<string> documents;
std::tie(chat_id, args) = split(args);
documents = full_split(args);
send_request(td_api::make_object<td_api::sendMessageAlbum>(
as_chat_id(chat_id), as_message_thread_id(message_thread_id_), 0, default_message_send_options(),
transform(documents, [](const string &document) {
td_api::object_ptr<td_api::InputMessageContent> content = td_api::make_object<td_api::inputMessageDocument>(
as_input_file(document), nullptr, true, as_caption(""));
return content;
})));
} else if (op == "em") {
@ -3124,11 +3164,18 @@ class CliClient final : public Actor {
string message_id;
string latitude;
string longitude;
string accuracy;
string heading;
string proximity_alert_radius;
std::tie(chat_id, args) = split(args);
std::tie(message_id, args) = split(args);
std::tie(latitude, longitude) = split(args);
send_request(td_api::make_object<td_api::editMessageLiveLocation>(as_chat_id(chat_id), as_message_id(message_id),
nullptr, as_location(latitude, longitude)));
std::tie(latitude, args) = split(args);
std::tie(longitude, args) = split(args);
std::tie(accuracy, args) = split(args);
std::tie(heading, proximity_alert_radius) = split(args);
send_request(td_api::make_object<td_api::editMessageLiveLocation>(
as_chat_id(chat_id), as_message_id(message_id), nullptr, as_location(latitude, longitude, accuracy),
to_integer<int32>(heading), to_integer<int32>(proximity_alert_radius)));
} else if (op == "emss") {
string chat_id;
string message_id;
@ -3376,24 +3423,33 @@ class CliClient final : public Actor {
send_message(chat_id, td_api::make_object<td_api::inputMessageGame>(as_user_id(bot_user_id), game_short_name));
} else if (op == "sl") {
string chat_id;
std::tie(chat_id, args) = split(args);
string latitude;
string longitude;
std::tie(latitude, longitude) = split(args);
string accuracy;
std::tie(chat_id, args) = split(args);
std::tie(latitude, args) = split(args);
std::tie(longitude, accuracy) = split(args);
send_message(chat_id, td_api::make_object<td_api::inputMessageLocation>(as_location(latitude, longitude), 0));
send_message(chat_id, td_api::make_object<td_api::inputMessageLocation>(
as_location(latitude, longitude, accuracy), 0, 0, 0));
} else if (op == "sll") {
string chat_id;
string period;
string latitude;
string longitude;
string accuracy;
string heading;
string proximity_alert_radius;
std::tie(chat_id, args) = split(args);
std::tie(period, args) = split(args);
std::tie(latitude, longitude) = split(args);
std::tie(latitude, args) = split(args);
std::tie(longitude, args) = split(args);
std::tie(accuracy, args) = split(args);
std::tie(heading, proximity_alert_radius) = split(args);
send_message(chat_id, td_api::make_object<td_api::inputMessageLocation>(as_location(latitude, longitude),
to_integer<int32>(period)));
send_message(chat_id, td_api::make_object<td_api::inputMessageLocation>(
as_location(latitude, longitude, accuracy), to_integer<int32>(period),
to_integer<int32>(heading), to_integer<int32>(proximity_alert_radius)));
} else if (op == "spoll" || op == "spollm" || op == "spollp" || op == "squiz") {
string chat_id;
string question;
@ -3542,6 +3598,7 @@ class CliClient final : public Actor {
string latitude;
string longitude;
string accuracy;
string title;
string address;
string provider;
@ -3550,13 +3607,15 @@ class CliClient final : public Actor {
std::tie(chat_id, args) = split(args);
std::tie(latitude, args) = split(args);
std::tie(longitude, args) = split(args);
std::tie(accuracy, args) = split(args);
std::tie(title, args) = split(args);
std::tie(address, args) = split(args);
std::tie(provider, args) = split(args);
std::tie(venue_id, venue_type) = split(args);
send_message(chat_id, td_api::make_object<td_api::inputMessageVenue>(td_api::make_object<td_api::venue>(
as_location(latitude, longitude), title, address, provider, venue_id, venue_type)));
send_message(chat_id,
td_api::make_object<td_api::inputMessageVenue>(td_api::make_object<td_api::venue>(
as_location(latitude, longitude, accuracy), title, address, provider, venue_id, venue_type)));
} else if (op == "test") {
send_request(td_api::make_object<td_api::testNetwork>());
} else if (op == "alarm") {
@ -3587,7 +3646,7 @@ class CliClient final : public Actor {
} else if (op == "cngc") {
send_request(td_api::make_object<td_api::createNewSupergroupChat>(
args, false, "Description",
td_api::make_object<td_api::chatLocation>(td_api::make_object<td_api::location>(40.0, 60.0), "address")));
td_api::make_object<td_api::chatLocation>(as_location("40.0", "60.0"), "address")));
} else if (op == "UpgradeBasicGroupChatToSupergroupChat") {
send_request(td_api::make_object<td_api::upgradeBasicGroupChatToSupergroupChat>(as_chat_id(args)));
} else if (op == "DeleteSupergroup") {
@ -3783,6 +3842,9 @@ class CliClient final : public Actor {
} else if (status_str == "anonadmin") {
status = td_api::make_object<td_api::chatMemberStatusAdministrator>("anon", false, false, false, false, false,
false, false, false, false, true);
} else if (status_str == "addadmin") {
status = td_api::make_object<td_api::chatMemberStatusAdministrator>("anon", false, false, false, false, false,
false, false, false, true, false);
} else if (status_str == "admin") {
status = td_api::make_object<td_api::chatMemberStatusAdministrator>("", true, true, true, true, true, true,
true, true, true, false);
@ -3920,15 +3982,22 @@ class CliClient final : public Actor {
std::tie(chat_id, slow_mode_delay) = split(args);
send_request(
td_api::make_object<td_api::setChatSlowModeDelay>(as_chat_id(chat_id), to_integer<int32>(slow_mode_delay)));
} else if (op == "pcm" || op == "pcms") {
} else if (op == "pcm" || op == "pcms" || op == "pcmo") {
string chat_id;
string message_id;
std::tie(chat_id, message_id) = split(args);
send_request(
td_api::make_object<td_api::pinChatMessage>(as_chat_id(chat_id), as_message_id(message_id), op == "pcms"));
send_request(td_api::make_object<td_api::pinChatMessage>(as_chat_id(chat_id), as_message_id(message_id),
op == "pcms", op == "pcmo"));
} else if (op == "upcm") {
send_request(td_api::make_object<td_api::unpinChatMessage>(as_chat_id(args)));
string chat_id;
string message_id;
std::tie(chat_id, message_id) = split(args);
send_request(td_api::make_object<td_api::unpinChatMessage>(as_chat_id(chat_id), as_message_id(message_id)));
} else if (op == "uacm") {
string chat_id = args;
send_request(td_api::make_object<td_api::unpinAllChatMessages>(as_chat_id(chat_id)));
} else if (op == "grib") {
send_request(td_api::make_object<td_api::getRecentInlineBots>());
} else if (op == "spc" || op == "su" || op == "sch") {

View File

@ -190,7 +190,8 @@ class MapDownloadGenerateActor : public FileGenerateActor {
int64 access_hash = G()->get_location_access_hash(latitude, longitude);
return make_tl_object<telegram_api::inputWebFileGeoPointLocation>(
make_tl_object<telegram_api::inputGeoPoint>(latitude, longitude), access_hash, width, height, zoom, scale);
make_tl_object<telegram_api::inputGeoPoint>(0, latitude, longitude, 0), access_hash, width, height, zoom,
scale);
}
void start_up() override {

View File

@ -3151,7 +3151,7 @@ Result<FileId> FileManager::get_input_file_id(FileType type, const tl_object_ptr
return FileId();
}
string hash;
if (false && new_type == FileType::Photo) {
if (G()->shared_config().get_option_boolean("reuse_uploaded_photos_by_hash") && new_type == FileType::Photo) {
auto r_stat = stat(path);
if (r_stat.is_ok() && r_stat.ok().size_ > 0 && r_stat.ok().size_ < 5000000) {
auto r_file_content = read_file_str(path, r_stat.ok().size_);

View File

@ -98,7 +98,8 @@ class LogEvent {
DeleteScheduledMessagesFromServer = 0x117,
ToggleDialogIsBlockedOnServer = 0x118,
ReadMessageThreadHistoryOnServer = 0x119,
BlockDialogFromRepliesOnServer = 0x120,
BlockMessageSenderFromRepliesOnServer = 0x120,
UnpinAllDialogMessagesOnServer = 0x121,
GetChannelDifference = 0x140,
AddMessagePushNotification = 0x200,
EditMessagePushNotification = 0x201,

View File

@ -10,6 +10,7 @@
#include "td/utils/format.h"
#include "td/utils/logging.h"
#include "td/utils/misc.h"
#include "td/utils/Time.h"
namespace td {
@ -37,7 +38,8 @@ void NetQueryStats::dump_pending_network_queries() {
}
const NetQueryDebug &debug = cur->get_data_unsafe();
const NetQuery &nq = *static_cast<const NetQuery *>(cur);
LOG(WARNING) << tag("user", debug.my_id_) << nq << tag("total flood", format::as_time(nq.total_timeout_))
LOG(WARNING) << tag("user", lpad(PSTRING() << debug.my_id_, 10, ' ')) << nq
<< tag("total flood", format::as_time(nq.total_timeout_))
<< tag("since start", format::as_time(Time::now_cached() - debug.start_timestamp_))
<< tag("state", debug.state_)
<< tag("in this state", format::as_time(Time::now_cached() - debug.state_timestamp_))

View File

@ -47,6 +47,13 @@ string lpad0(string str, size_t size) {
return lpad(std::move(str), size, '0');
}
string rpad(string str, size_t size, char c) {
if (str.size() >= size) {
return str;
}
return str + string(size - str.size(), c);
}
string oneline(Slice str) {
string result;
result.reserve(str.size());

View File

@ -273,6 +273,8 @@ string lpad(string str, size_t size, char c);
string lpad0(const string str, size_t size);
string rpad(string str, size_t size, char c);
string oneline(Slice str);
template <class T>