Merge branch 'master' into fork

This commit is contained in:
Andrea Cavalli 2020-01-28 10:43:22 +01:00
commit d86c298fc2
43 changed files with 919 additions and 739 deletions

View File

@ -4,7 +4,13 @@ project(TDLib VERSION 1.5.5 LANGUAGES CXX C)
if (NOT DEFINED CMAKE_INSTALL_LIBDIR)
set(CMAKE_INSTALL_LIBDIR "lib")
endif(NOT DEFINED CMAKE_INSTALL_LIBDIR)
endif()
if (NOT DEFINED CMAKE_INSTALL_BINDIR)
set(CMAKE_INSTALL_BINDIR "bin")
endif()
if (NOT DEFINED CMAKE_INSTALL_INCLUDEDIR)
set(CMAKE_INSTALL_INCLUDEDIR "include")
endif()
if (POLICY CMP0054)
# do not expand quoted arguments
@ -255,7 +261,7 @@ if (NOT CMAKE_CROSSCOMPILING)
add_custom_target(prepare_cross_compiling DEPENDS tl_generate_common tdmime_auto tl_generate_json)
if (TD_ENABLE_DOTNET)
add_custom_target(remove_cpp_documentation
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMAND remove_documentation ${TL_TD_AUTO} td/telegram/Client.h td/telegram/Log.h td/tl/TlObject.h
COMMENT "Remove C++ documentation from sources"
DEPENDS remove_documentation tl_generate_common generate_dotnet_api ${TL_TD_AUTO} td/telegram/Client.h td/telegram/Log.h td/tl/TlObject.h
@ -295,7 +301,6 @@ endif()
get_directory_property(HAS_PARENT PARENT_DIRECTORY)
if (HAS_PARENT)
set(TL_TD_AUTO_INCLUDES ${TL_TD_AUTO_INCLUDES} PARENT_SCOPE)
set(TL_TD_API_TLO ${TL_TD_API_TLO} PARENT_SCOPE)
set(TL_TD_JSON_AUTO ${TL_TD_JSON_AUTO} PARENT_SCOPE)
set(TD_TEST_SOURCE ${TD_TEST_SOURCE} PARENT_SCOPE)
@ -375,6 +380,7 @@ set(TDLIB_SOURCE
td/telegram/Contact.cpp
td/telegram/ContactsManager.cpp
td/telegram/DelayDispatcher.cpp
td/telegram/Dependencies.cpp
td/telegram/DeviceTokenManager.cpp
td/telegram/DhCache.cpp
td/telegram/DialogAdministrator.cpp
@ -414,6 +420,7 @@ set(TDLIB_SOURCE
td/telegram/Location.cpp
td/telegram/Logging.cpp
td/telegram/MessageContent.cpp
td/telegram/MessageContentType.cpp
td/telegram/MessageEntity.cpp
td/telegram/MessageId.cpp
td/telegram/MessagesDb.cpp
@ -576,6 +583,7 @@ set(TDLIB_SOURCE
td/telegram/logevent/SecretChatEvent.h
td/telegram/Logging.h
td/telegram/MessageContent.h
td/telegram/MessageContentType.h
td/telegram/MessageEntity.h
td/telegram/MessageId.h
td/telegram/MessagesDb.h
@ -647,6 +655,7 @@ set(TDLIB_SOURCE
td/telegram/TdDb.h
td/telegram/TdParameters.h
td/telegram/TermsOfService.h
td/telegram/TopDialogCategory.h
td/telegram/TopDialogManager.h
td/telegram/UniqueId.h
td/telegram/UpdatesManager.h
@ -709,7 +718,7 @@ else()
endif()
add_custom_target(git_commit ALL
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMAND ${GIT_COMMIT_CMD}
COMMENT "Generate git_commit.h"
)
@ -734,7 +743,7 @@ endif()
# tdcore - mostly internal TDLib interface. One should use tdactor for interactions with it.
add_library(tdcore STATIC ${TDLIB_SOURCE})
target_include_directories(tdcore PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> $<BUILD_INTERFACE:${TL_TD_AUTO_INCLUDES}>)
target_include_directories(tdcore PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> $<BUILD_INTERFACE:${TL_TD_AUTO_INCLUDE_DIR}>)
target_include_directories(tdcore SYSTEM PRIVATE ${OPENSSL_INCLUDE_DIR})
target_link_libraries(tdcore PUBLIC tdactor tdutils tdnet tddb PRIVATE ${OPENSSL_CRYPTO_LIBRARY} ${CMAKE_DL_LIBS} ${ZLIB_LIBRARIES})
@ -760,7 +769,7 @@ endif()
add_library(tdclient td/telegram/Client.cpp td/telegram/Client.h td/telegram/Log.cpp td/telegram/Log.h)
target_include_directories(tdclient PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<BUILD_INTERFACE:${TL_TD_AUTO_INCLUDES}>
$<BUILD_INTERFACE:${TL_TD_AUTO_INCLUDE_DIR}>
)
target_link_libraries(tdclient PRIVATE tdcore)
@ -780,7 +789,7 @@ if (TD_ENABLE_DOTNET)
set_target_properties(tddotnet PROPERTIES OUTPUT_NAME Telegram.Td)
target_link_libraries(tddotnet PRIVATE tdclient tdutils)
target_include_directories(tddotnet PUBLIC
$<BUILD_INTERFACE:${TL_TD_AUTO_INCLUDES}>
$<BUILD_INTERFACE:${TL_TD_AUTO_INCLUDE_DIR}>
)
if (NOT CMAKE_CROSSCOMPILING)
add_dependencies(tddotnet generate_dotnet_api)
@ -800,7 +809,7 @@ endif()
add_library(tdc STATIC EXCLUDE_FROM_ALL ${TL_C_SCHEME_SOURCE} td/telegram/td_c_client.cpp td/telegram/td_c_client.h)
target_include_directories(tdc PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<BUILD_INTERFACE:${TL_TD_AUTO_INCLUDES}>)
$<BUILD_INTERFACE:${TL_TD_AUTO_INCLUDE_DIR}>)
target_link_libraries(tdc PRIVATE tdclient tdutils)
if (NOT CMAKE_CROSSCOMPILING)
add_dependencies(tdc tl_generate_c)
@ -809,7 +818,7 @@ endif()
add_library(tdjson_private STATIC ${TL_TD_JSON} td/telegram/ClientJson.cpp td/telegram/ClientJson.h)
target_include_directories(tdjson_private PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<BUILD_INTERFACE:${TL_TD_AUTO_INCLUDES}>)
$<BUILD_INTERFACE:${TL_TD_AUTO_INCLUDE_DIR}>)
target_link_libraries(tdjson_private PUBLIC tdclient tdutils)
if (NOT CMAKE_CROSSCOMPILING)
add_dependencies(tdjson_private tl_generate_common tl_generate_json)
@ -914,35 +923,35 @@ add_library(Td::TdJson ALIAS TdJson)
add_library(Td::TdJsonStatic ALIAS TdJsonStatic)
install(TARGETS tdjson TdJson tdjson_static TdJsonStatic tdjson_private tdclient tdcore TdStatic EXPORT TdTargets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION bin
INCLUDES DESTINATION include
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
)
install(EXPORT TdTargets
FILE TdTargets.cmake
NAMESPACE Td::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/Td
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Td"
)
install(FILES ${TD_JSON_HEADERS} ${CMAKE_CURRENT_BINARY_DIR}/td/telegram/tdjson_export.h DESTINATION include/td/telegram)
install(FILES td/telegram/Client.h td/telegram/Log.h DESTINATION include/td/telegram)
install(FILES td/tl/TlObject.h DESTINATION include/td/tl)
install(FILES ${TL_TD_AUTO_INCLUDES}/td/telegram/td_api.h ${TL_TD_AUTO_INCLUDES}/td/telegram/td_api.hpp DESTINATION include/td/telegram)
install(FILES ${TD_JSON_HEADERS} "${CMAKE_CURRENT_BINARY_DIR}/td/telegram/tdjson_export.h" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/td/telegram")
install(FILES td/telegram/Client.h td/telegram/Log.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/td/telegram")
install(FILES td/tl/TlObject.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/td/tl")
install(FILES "${TL_TD_AUTO_INCLUDE_DIR}/td/telegram/td_api.h" "${TL_TD_AUTO_INCLUDE_DIR}/td/telegram/td_api.hpp" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/td/telegram")
if (TD_ENABLE_JNI)
install(FILES td/tl/tl_jni_object.h DESTINATION include/td/tl)
install(FILES td/tl/tl_jni_object.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/td/tl")
endif()
include(CMakePackageConfigHelpers)
write_basic_package_version_file("TdConfigVersion.cmake"
VERSION ${TDLib_VERSION}
VERSION "${TDLib_VERSION}"
COMPATIBILITY ExactVersion
)
install(FILES "TdConfig.cmake" "${CMAKE_CURRENT_BINARY_DIR}/TdConfigVersion.cmake"
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/Td
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Td"
)
# Add SOVERSION to shared libraries
set_property(TARGET tdclient PROPERTY SOVERSION ${TDLib_VERSION})
set_property(TARGET tdjson PROPERTY SOVERSION ${TDLib_VERSION})
set_property(TARGET tdclient PROPERTY SOVERSION "${TDLib_VERSION}")
set_property(TARGET tdjson PROPERTY SOVERSION "${TDLib_VERSION}")

View File

@ -281,6 +281,7 @@ function split_file($file, $chunks, $undo) {
'secret_chats_manager[_(-][^.]|SecretChatsManager' => 'SecretChatsManager',
'stickers_manager[_(-][^.]|StickersManager' => 'StickersManager',
'[>](td_db[(][)]|get_td_db_impl[(])|TdDb[^A-Za-z]' => 'TdDb',
'TopDialogCategory|top_dialog_category_from_td_api' => 'TopDialogCategory',
'top_dialog_manager[_(-][^.]|TopDialogManager' => 'TopDialogManager',
'updates_manager[_(-][^.]|UpdatesManager|get_difference[)]' => 'UpdatesManager',
'WebPageId(Hash)?' => 'WebPageId',

View File

@ -91,7 +91,7 @@ You can also see [JTDLib](https://github.com/ErnyTech/JTDLib) for another exampl
<a name="kotlin"></a>
## Using TDLib in Kotlin projects
TDLib can be used from the Kotlin/JVM programming language through same way as in [JAVA](#java).
TDLib can be used from the Kotlin/JVM programming language through same way as in [Java](#java).
You can also use [ktd](https://github.com/whyoleg/ktd) library with kotlin specific bindings.

View File

@ -3,7 +3,7 @@
[TDLib](https://github.com/tdlib/td) is a library for building Telegram clients. tdweb is a convenient wrapper for TDLib in a browser which controls TDLib instance creation,
handles interaction with TDLib and manages a filesystem for persistent TDLib data.
For interaction with TDLib you need to create an instance of the class `TdClient`, providing a handler for incoming updates and other options if needed.
For interaction with TDLib, you need to create an instance of the class `TdClient`, providing a handler for incoming updates and other options if needed.
Once this is done, you can send queries to the TDLib instance using the method `TdClient.send` which returns a Promise object representing the result of the query.
See [Getting Started](https://core.telegram.org/tdlib/getting-started) for a description of basic TDLib concepts and a short introduction to TDLib usage.
@ -14,16 +14,16 @@ TDLib [methods](https://core.telegram.org/tdlib/docs/classtd_1_1td__api_1_1_func
The JSON representation of TDLib API objects is straightforward: all API objects are represented as JSON objects with the same keys as the API object field names in the
[td_api.tl](https://github.com/tdlib/td/blob/master/td/generate/scheme/td_api.tl) scheme. Note that in the automatically generated C++ documentation all fields have an additional terminating underscore
which shouldn't be used in the JSON interface. The object type name is stored in the special field '@type' which is optional in places where type is uniquely determined by the context.
Fields of Bool type are stored as Boolean, fields of int32, int53 and double types are stored as Number, fields of int64 and string types are stored as String,
Fields of Bool type are stored as Boolean, fields of int32, int53, and double types are stored as Number, fields of int64 and string types are stored as String,
fields of bytes type are base64 encoded and then stored as String, fields of vector type are stored as Array.
You can also add the field '@extra' to any query to TDLib and the response will contain the field '@extra' with exactly the same value.
## Installation
As usual, add npm tdweb package into you project:
As usual, add npm tdweb package into your project:
```
npm install tdweb
```
All files will be installed into `node_modules/tdweb/dist/` folder. For now it is your responsibility to make
All files will be installed into `node_modules/tdweb/dist/` folder. For now, it is your responsibility to make
those files loadable from your server. For example, [telegram-react](https://github.com/evgeny-nadymov/telegram-react)
manually copies this files into the `public` folder. If you know how to avoid this problem, please tell us.
manually copies these files into the `public` folder. If you know how to avoid this problem, please tell us.

View File

@ -1,5 +1,9 @@
cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR)
if (NOT DEFINED CMAKE_INSTALL_LIBDIR)
set(CMAKE_INSTALL_LIBDIR "lib")
endif()
if (NOT OPENSSL_FOUND)
find_package(OpenSSL REQUIRED)
find_package(ZLIB REQUIRED)
@ -43,8 +47,6 @@ elseif (MSVC)
endif()
install(TARGETS tdsqlite EXPORT TdTargets
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin
INCLUDES DESTINATION include
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
)

View File

@ -1,29 +1,35 @@
cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR)
if (NOT DEFINED CMAKE_INSTALL_BINDIR)
set(CMAKE_INSTALL_BINDIR "bin")
endif()
file(MAKE_DIRECTORY auto/td/telegram)
file(MAKE_DIRECTORY auto/td/mtproto)
set(TL_TD_AUTO_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}/auto PARENT_SCOPE)
set(TL_TD_AUTO_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/auto PARENT_SCOPE)
set(TD_AUTO_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/auto/td)
set(TL_TD_AUTO
${CMAKE_CURRENT_SOURCE_DIR}/auto/td/mtproto/mtproto_api.cpp
${CMAKE_CURRENT_SOURCE_DIR}/auto/td/mtproto/mtproto_api.h
${CMAKE_CURRENT_SOURCE_DIR}/auto/td/mtproto/mtproto_api.hpp
${CMAKE_CURRENT_SOURCE_DIR}/auto/td/telegram/td_api.cpp
${CMAKE_CURRENT_SOURCE_DIR}/auto/td/telegram/td_api.h
${CMAKE_CURRENT_SOURCE_DIR}/auto/td/telegram/td_api.hpp
${CMAKE_CURRENT_SOURCE_DIR}/auto/td/telegram/telegram_api.cpp
${CMAKE_CURRENT_SOURCE_DIR}/auto/td/telegram/telegram_api.h
${CMAKE_CURRENT_SOURCE_DIR}/auto/td/telegram/telegram_api.hpp
${CMAKE_CURRENT_SOURCE_DIR}/auto/td/telegram/secret_api.cpp
${CMAKE_CURRENT_SOURCE_DIR}/auto/td/telegram/secret_api.h
${CMAKE_CURRENT_SOURCE_DIR}/auto/td/telegram/secret_api.hpp
${TD_AUTO_INCLUDE_DIR}/mtproto/mtproto_api.cpp
${TD_AUTO_INCLUDE_DIR}/mtproto/mtproto_api.h
${TD_AUTO_INCLUDE_DIR}/mtproto/mtproto_api.hpp
${TD_AUTO_INCLUDE_DIR}/telegram/td_api.cpp
${TD_AUTO_INCLUDE_DIR}/telegram/td_api.h
${TD_AUTO_INCLUDE_DIR}/telegram/td_api.hpp
${TD_AUTO_INCLUDE_DIR}/telegram/telegram_api.cpp
${TD_AUTO_INCLUDE_DIR}/telegram/telegram_api.h
${TD_AUTO_INCLUDE_DIR}/telegram/telegram_api.hpp
${TD_AUTO_INCLUDE_DIR}/telegram/secret_api.cpp
${TD_AUTO_INCLUDE_DIR}/telegram/secret_api.h
${TD_AUTO_INCLUDE_DIR}/telegram/secret_api.hpp
PARENT_SCOPE
)
set(TL_TD_JSON_AUTO
${CMAKE_CURRENT_SOURCE_DIR}/auto/td/telegram/td_api_json.cpp
${CMAKE_CURRENT_SOURCE_DIR}/auto/td/telegram/td_api_json.h
${TD_AUTO_INCLUDE_DIR}/telegram/td_api_json.cpp
${TD_AUTO_INCLUDE_DIR}/telegram/td_api_json.h
PARENT_SCOPE
)
@ -31,15 +37,15 @@ set(TL_TD_API_TLO ${CMAKE_CURRENT_SOURCE_DIR}/scheme/td_api.tlo)
set(TL_TD_API_TLO ${TL_TD_API_TLO} PARENT_SCOPE)
set(TL_C_AUTO
${CMAKE_CURRENT_SOURCE_DIR}/auto/td/telegram/td_tdc_api.cpp
${CMAKE_CURRENT_SOURCE_DIR}/auto/td/telegram/td_tdc_api.h
${CMAKE_CURRENT_SOURCE_DIR}/auto/td/telegram/td_tdc_api_inner.h
${TD_AUTO_INCLUDE_DIR}/telegram/td_tdc_api.cpp
${TD_AUTO_INCLUDE_DIR}/telegram/td_tdc_api.h
${TD_AUTO_INCLUDE_DIR}/telegram/td_tdc_api_inner.h
PARENT_SCOPE
)
set(TL_DOTNET_AUTO
${CMAKE_CURRENT_SOURCE_DIR}/auto/td/telegram/TdDotNetApi.cpp
${CMAKE_CURRENT_SOURCE_DIR}/auto/td/telegram/TdDotNetApi.h
${TD_AUTO_INCLUDE_DIR}/telegram/TdDotNetApi.cpp
${TD_AUTO_INCLUDE_DIR}/telegram/TdDotNetApi.h
PARENT_SCOPE
)
@ -129,9 +135,9 @@ if (NOT CMAKE_CROSSCOMPILING)
)
if (TD_ENABLE_JNI)
install(TARGETS td_generate_java_api RUNTIME DESTINATION bin)
install(FILES JavadocTlDocumentationGenerator.php TlDocumentationGenerator.php DESTINATION bin/td/generate)
install(FILES scheme/td_api.tlo scheme/td_api.tl DESTINATION bin/td/generate/scheme)
install(TARGETS td_generate_java_api RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
install(FILES JavadocTlDocumentationGenerator.php TlDocumentationGenerator.php DESTINATION "${CMAKE_INSTALL_BINDIR}/td/generate")
install(FILES scheme/td_api.tlo scheme/td_api.tl DESTINATION "${CMAKE_INSTALL_BINDIR}/td/generate/scheme")
endif()
if (TD_ENABLE_DOTNET)

View File

@ -12,7 +12,7 @@
namespace td {
namespace mtproto {
Result<ProxySecret> ProxySecret::from_link(Slice encoded_secret) {
Result<ProxySecret> ProxySecret::from_link(Slice encoded_secret, bool truncate_if_needed) {
auto r_decoded = hex_decode(encoded_secret);
if (r_decoded.is_error()) {
r_decoded = base64url_decode(encoded_secret);
@ -20,10 +20,17 @@ Result<ProxySecret> ProxySecret::from_link(Slice encoded_secret) {
if (r_decoded.is_error()) {
return Status::Error(400, "Wrong proxy secret");
}
return from_binary(r_decoded.ok());
return from_binary(r_decoded.ok(), truncate_if_needed);
}
Result<ProxySecret> ProxySecret::from_binary(Slice raw_unchecked_secret) {
Result<ProxySecret> ProxySecret::from_binary(Slice raw_unchecked_secret, bool truncate_if_needed) {
if (raw_unchecked_secret.size() > 17 + MAX_DOMAIN_LENGTH) {
if (truncate_if_needed) {
raw_unchecked_secret.truncate(17 + MAX_DOMAIN_LENGTH);
} else {
return Status::Error(400, "Too long secret");
}
}
if (raw_unchecked_secret.size() == 16 ||
(raw_unchecked_secret.size() == 17 && static_cast<unsigned char>(raw_unchecked_secret[0]) == 0xdd) ||
(raw_unchecked_secret.size() >= 18 && static_cast<unsigned char>(raw_unchecked_secret[0]) == 0xee)) {

View File

@ -15,8 +15,12 @@ namespace mtproto {
class ProxySecret {
public:
static Result<ProxySecret> from_link(Slice encoded_secret);
static Result<ProxySecret> from_binary(Slice raw_unchecked_secret);
static constexpr size_t MAX_DOMAIN_LENGTH = 182; // must be small enough to not overflow TLS-hello length
static Result<ProxySecret> from_link(Slice encoded_secret, bool truncate_if_needed = false);
static Result<ProxySecret> from_binary(Slice raw_unchecked_secret, bool truncate_if_needed = false);
static ProxySecret from_raw(Slice raw_secret) {
ProxySecret result;
result.secret_ = raw_secret.str();

View File

@ -6,6 +6,8 @@
//
#include "td/mtproto/TlsInit.h"
#include "td/mtproto/ProxySecret.h"
#include "td/utils/as.h"
#include "td/utils/BigNum.h"
#include "td/utils/common.h"
@ -91,6 +93,33 @@ class TlsHello {
static const TlsHello &get_default() {
static TlsHello result = [] {
TlsHello res;
#if TD_DARWIN
res.ops_ = {
Op::string("\x16\x03\x01\x02\x00\x01\x00\x01\xfc\x03\x03"),
Op::zero(32),
Op::string("\x20"),
Op::random(32),
Op::string("\x00\x34\x13\x03\x13\x01\x13\x02\xc0\x2c\xc0\x2b\xc0\x24\xc0\x23\xc0\x0a\xc0\x09\xcc\xa9\xc0\x30"
"\xc0\x2f\xc0\x28\xc0\x27\xc0\x14\xc0\x13\xcc\xa8\x00\x9d\x00\x9c\x00\x3d\x00\x3c\x00\x35\x00\x2f"
"\xc0\x08\xc0\x12\x00\x0a\x01\x00\x01\x7f\xff\x01\x00\x01\x00\x00\x00"),
Op::begin_scope(),
Op::begin_scope(),
Op::string("\x00"),
Op::begin_scope(),
Op::domain(),
Op::end_scope(),
Op::end_scope(),
Op::end_scope(),
Op::string("\x00\x17\x00\x00\x00\x0d\x00\x18\x00\x16\x04\x03\x08\x04\x04\x01\x05\x03\x02\x03\x08\x05\x08\x05"
"\x05\x01\x08\x06\x06\x01\x02\x01\x00\x05\x00\x05\x01\x00\x00\x00\x00\x33\x74\x00\x00\x00\x12\x00"
"\x00\x00\x10\x00\x30\x00\x2e\x02\x68\x32\x05\x68\x32\x2d\x31\x36\x05\x68\x32\x2d\x31\x35\x05\x68"
"\x32\x2d\x31\x34\x08\x73\x70\x64\x79\x2f\x33\x2e\x31\x06\x73\x70\x64\x79\x2f\x33\x08\x68\x74\x74"
"\x70\x2f\x31\x2e\x31\x00\x0b\x00\x02\x01\x00\x00\x33\x00\x26\x00\x24\x00\x1d\x00\x20"),
Op::key(),
Op::string("\x00\x2d\x00\x02\x01\x01\x00\x2b\x00\x09\x08\x03\x04\x03\x03\x03\x02\x03\x01\x00\x0a\x00\x0a\x00"
"\x08\x00\x1d\x00\x17\x00\x18\x00\x19\x00\x15")};
res.grease_size_ = 0;
#else
res.ops_ = {
Op::string("\x16\x03\x01\x02\x00\x01\x00\x01\xfc\x03\x03"),
Op::zero(32),
@ -125,6 +154,7 @@ class TlsHello {
Op::grease(3),
Op::string("\x00\x01\x00\x00\x15")};
res.grease_size_ = 7;
#endif
return res;
}();
return result;
@ -157,7 +187,7 @@ class TlsHelloContext {
return grease_.size();
}
Slice get_domain() const {
return domain_;
return Slice(domain_).substr(0, ProxySecret::MAX_DOMAIN_LENGTH);
}
private:
@ -225,7 +255,7 @@ class TlsHelloCalcLength {
}
Result<size_t> finish() {
if (size_ > 515) {
if (size_ > 514) {
on_error(Status::Error("Too long for zero padding"));
}
if (size_ < 11 + 32) {

View File

@ -288,7 +288,7 @@ static ActorOwn<> get_simple_config_dns(Slice address, Slice host, Promise<Simpl
ActorOwn<> get_simple_config_google_dns(Promise<SimpleConfigResult> promise, const ConfigShared *shared_config,
bool is_test, int32 scheduler_id) {
return get_simple_config_dns("www.google.com/resolve", "dns.google.com", std::move(promise), shared_config, is_test,
return get_simple_config_dns("dns.google/resolve", "dns.google", std::move(promise), shared_config, is_test,
scheduler_id);
}

View File

@ -35,7 +35,6 @@
#include "td/telegram/StickersManager.h"
#include "td/telegram/Td.h"
#include "td/telegram/TdDb.h"
#include "td/telegram/TopDialogManager.h"
#include "td/telegram/UpdatesManager.h"
#include "td/telegram/Version.h"
@ -7535,7 +7534,7 @@ void ContactsManager::on_load_user_full_from_database(UserId user_id, string val
Dependencies dependencies;
dependencies.user_ids.insert(user_id);
td_->messages_manager_->resolve_dependencies_force(dependencies);
resolve_dependencies_force(td_, dependencies);
if (user_full->need_phone_number_privacy_exception && is_user_contact(user_id)) {
user_full->need_phone_number_privacy_exception = false;
@ -7705,7 +7704,7 @@ void ContactsManager::on_load_chat_full_from_database(ChatId chat_id, string val
dependencies.user_ids.insert(participant.user_id);
dependencies.user_ids.insert(participant.inviter_user_id);
}
td_->messages_manager_->resolve_dependencies_force(dependencies);
resolve_dependencies_force(td_, dependencies);
for (auto &participant : chat_full->participants) {
get_bot_info_force(participant.user_id);
@ -7778,10 +7777,10 @@ void ContactsManager::on_load_channel_full_from_database(ChannelId channel_id, s
Dependencies dependencies;
dependencies.channel_ids.insert(channel_id);
td_->messages_manager_->add_dialog_dependencies(dependencies, DialogId(channel_full->linked_channel_id));
MessagesManager::add_dialog_dependencies(dependencies, DialogId(channel_full->linked_channel_id));
dependencies.chat_ids.insert(channel_full->migrated_from_chat_id);
dependencies.user_ids.insert(channel_full->bot_user_ids.begin(), channel_full->bot_user_ids.end());
td_->messages_manager_->resolve_dependencies_force(dependencies);
resolve_dependencies_force(td_, dependencies);
for (auto &user_id : channel_full->bot_user_ids) {
get_bot_info_force(user_id);
@ -7894,13 +7893,6 @@ void ContactsManager::update_user(User *u, UserId user_id, bool from_binlog, boo
if (u->is_deleted) {
td_->inline_queries_manager_->remove_recent_inline_bot(user_id, Promise<>());
/*
DialogId dialog_id(user_id);
for (auto category : {TopDialogCategory::Correspondent, TopDialogCategory::BotPM, TopDialogCategory::BotInline}) {
send_closure(G()->top_dialog_manager(), &TopDialogManager::delete_dialog, category, dialog_id,
get_input_peer_user(user_id, AccessRights::Read));
}
*/
}
LOG(DEBUG) << "Update " << user_id << ": need_save_to_database = " << u->need_save_to_database

View File

@ -0,0 +1,52 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "td/telegram/Dependencies.h"
#include "td/telegram/ContactsManager.h"
#include "td/telegram/MessagesManager.h"
#include "td/telegram/Td.h"
#include "td/telegram/WebPagesManager.h"
#include "td/utils/logging.h"
namespace td {
void resolve_dependencies_force(Td *td, const Dependencies &dependencies) {
for (auto user_id : dependencies.user_ids) {
if (user_id.is_valid() && !td->contacts_manager_->have_user_force(user_id)) {
LOG(ERROR) << "Can't find " << user_id;
}
}
for (auto chat_id : dependencies.chat_ids) {
if (chat_id.is_valid() && !td->contacts_manager_->have_chat_force(chat_id)) {
LOG(ERROR) << "Can't find " << chat_id;
}
}
for (auto channel_id : dependencies.channel_ids) {
if (channel_id.is_valid() && !td->contacts_manager_->have_channel_force(channel_id)) {
LOG(ERROR) << "Can't find " << channel_id;
}
}
for (auto secret_chat_id : dependencies.secret_chat_ids) {
if (secret_chat_id.is_valid() && !td->contacts_manager_->have_secret_chat_force(secret_chat_id)) {
LOG(ERROR) << "Can't find " << secret_chat_id;
}
}
for (auto dialog_id : dependencies.dialog_ids) {
if (dialog_id.is_valid() && !td->messages_manager_->have_dialog_force(dialog_id)) {
LOG(ERROR) << "Can't find " << dialog_id;
td->messages_manager_->force_create_dialog(dialog_id, "resolve_dependencies_force");
}
}
for (auto web_page_id : dependencies.web_page_ids) {
if (web_page_id.is_valid()) {
td->web_pages_manager_->have_web_page_force(web_page_id);
}
}
}
} // namespace td

View File

@ -17,6 +17,8 @@
namespace td {
class Td;
struct Dependencies {
std::unordered_set<UserId, UserIdHash> user_ids;
std::unordered_set<ChatId, ChatIdHash> chat_ids;
@ -26,4 +28,6 @@ struct Dependencies {
std::unordered_set<WebPageId, WebPageIdHash> web_page_ids;
};
void resolve_dependencies_force(Td *td, const Dependencies &dependencies);
} // namespace td

View File

@ -56,6 +56,14 @@ void Document::append_file_ids(const Td *td, vector<FileId> &file_ids) const {
}
}
bool operator==(const Document &lhs, const Document &rhs) {
return lhs.type == rhs.type && lhs.file_id == rhs.file_id;
}
bool operator!=(const Document &lhs, const Document &rhs) {
return !(lhs == rhs);
}
StringBuilder &operator<<(StringBuilder &string_builder, const Document::Type &document_type) {
switch (document_type) {
case Document::Type::Unknown:

View File

@ -35,6 +35,10 @@ struct Document {
void append_file_ids(const Td *td, vector<FileId> &file_ids) const;
};
bool operator==(const Document &lhs, const Document &rhs);
bool operator!=(const Document &lhs, const Document &rhs);
StringBuilder &operator<<(StringBuilder &string_builder, const Document::Type &document_type);
StringBuilder &operator<<(StringBuilder &string_builder, const Document &document);

View File

@ -110,7 +110,7 @@ Status Global::init(const TdParameters &parameters, ActorId<Td> td, unique_ptr<T
<< tag("saved_system_time", saved_diff.system_time) << tag("system_time", system_time);
}
diff += time_backwards_fix;
} else {
} else if (saved_diff.system_time != 0) {
const double MAX_TIME_FORWARD = 367 * 86400; // if more than 1 year has passed, the session is logged out anyway
if (saved_diff.system_time + MAX_TIME_FORWARD < system_time) {
double time_forward_fix = system_time - (saved_diff.system_time + MAX_TIME_FORWARD);

View File

@ -27,6 +27,7 @@
#include "td/telegram/Game.h"
#include "td/telegram/Game.hpp"
#include "td/telegram/Global.h"
#include "td/telegram/HashtagHints.h"
#include "td/telegram/InputMessageText.h"
#include "td/telegram/Location.h"
#include "td/telegram/MessageEntity.h"
@ -50,6 +51,7 @@
#include "td/telegram/StickersManager.h"
#include "td/telegram/StickersManager.hpp"
#include "td/telegram/Td.h"
#include "td/telegram/TopDialogManager.h"
#include "td/telegram/UserId.h"
#include "td/telegram/Venue.h"
#include "td/telegram/Version.h"
@ -62,6 +64,7 @@
#include "td/telegram/WebPageId.h"
#include "td/telegram/WebPagesManager.h"
#include "td/actor/actor.h"
#include "td/actor/MultiPromise.h"
#include "td/actor/PromiseFuture.h"
@ -71,6 +74,7 @@
#include "td/utils/MimeType.h"
#include "td/utils/misc.h"
#include "td/utils/PathView.h"
#include "td/utils/Slice.h"
#include "td/utils/tl_helpers.h"
#include "td/utils/utf8.h"
@ -639,98 +643,6 @@ class MessagePoll : public MessageContent {
}
};
StringBuilder &operator<<(StringBuilder &string_builder, MessageContentType content_type) {
switch (content_type) {
case MessageContentType::None:
return string_builder << "None";
case MessageContentType::Animation:
return string_builder << "Animation";
case MessageContentType::Audio:
return string_builder << "Audio";
case MessageContentType::Document:
return string_builder << "Document";
case MessageContentType::ExpiredPhoto:
return string_builder << "ExpiredPhoto";
case MessageContentType::Photo:
return string_builder << "Photo";
case MessageContentType::ExpiredVideo:
return string_builder << "ExpiredVideo";
case MessageContentType::Video:
return string_builder << "Video";
case MessageContentType::VideoNote:
return string_builder << "VideoNote";
case MessageContentType::VoiceNote:
return string_builder << "VoiceNote";
case MessageContentType::Contact:
return string_builder << "Contact";
case MessageContentType::LiveLocation:
return string_builder << "LiveLocation";
case MessageContentType::Location:
return string_builder << "Location";
case MessageContentType::Venue:
return string_builder << "Venue";
case MessageContentType::Game:
return string_builder << "Game";
case MessageContentType::Invoice:
return string_builder << "Invoice";
case MessageContentType::Sticker:
return string_builder << "Sticker";
case MessageContentType::Text:
return string_builder << "Text";
case MessageContentType::Unsupported:
return string_builder << "Unsupported";
case MessageContentType::ChatCreate:
return string_builder << "ChatCreate";
case MessageContentType::ChatChangeTitle:
return string_builder << "ChatChangeTitle";
case MessageContentType::ChatChangePhoto:
return string_builder << "ChatChangePhoto";
case MessageContentType::ChatDeletePhoto:
return string_builder << "ChatDeletePhoto";
case MessageContentType::ChatDeleteHistory:
return string_builder << "ChatDeleteHistory";
case MessageContentType::ChatAddUsers:
return string_builder << "ChatAddUsers";
case MessageContentType::ChatJoinedByLink:
return string_builder << "ChatJoinedByLink";
case MessageContentType::ChatDeleteUser:
return string_builder << "ChatDeleteUser";
case MessageContentType::ChatMigrateTo:
return string_builder << "ChatMigrateTo";
case MessageContentType::ChannelCreate:
return string_builder << "ChannelCreate";
case MessageContentType::ChannelMigrateFrom:
return string_builder << "ChannelMigrateFrom";
case MessageContentType::PinMessage:
return string_builder << "PinMessage";
case MessageContentType::GameScore:
return string_builder << "GameScore";
case MessageContentType::ScreenshotTaken:
return string_builder << "ScreenshotTaken";
case MessageContentType::ChatSetTtl:
return string_builder << "ChatSetTtl";
case MessageContentType::Call:
return string_builder << "Call";
case MessageContentType::PaymentSuccessful:
return string_builder << "PaymentSuccessful";
case MessageContentType::ContactRegistered:
return string_builder << "ContactRegistered";
case MessageContentType::CustomServiceAction:
return string_builder << "CustomServiceAction";
case MessageContentType::WebsiteConnected:
return string_builder << "WebsiteConnected";
case MessageContentType::PassportDataSent:
return string_builder << "PassportDataSent";
case MessageContentType::PassportDataReceived:
return string_builder << "PassportDataReceived";
case MessageContentType::Poll:
return string_builder << "Poll";
default:
UNREACHABLE();
return string_builder;
}
}
template <class StorerT>
static void store(const MessageContent *content, StorerT &storer) {
CHECK(content != nullptr);
@ -2395,57 +2307,6 @@ void delete_message_content_thumbnail(MessageContent *content, Td *td) {
}
}
bool is_allowed_media_group_content(MessageContentType content_type) {
switch (content_type) {
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:
case MessageContentType::Location:
case MessageContentType::Sticker:
case MessageContentType::Text:
case MessageContentType::Unsupported:
case MessageContentType::Venue:
case MessageContentType::VideoNote:
case MessageContentType::VoiceNote:
case MessageContentType::ChatCreate:
case MessageContentType::ChatChangeTitle:
case MessageContentType::ChatChangePhoto:
case MessageContentType::ChatDeletePhoto:
case MessageContentType::ChatDeleteHistory:
case MessageContentType::ChatAddUsers:
case MessageContentType::ChatJoinedByLink:
case MessageContentType::ChatDeleteUser:
case MessageContentType::ChatMigrateTo:
case MessageContentType::ChannelCreate:
case MessageContentType::ChannelMigrateFrom:
case MessageContentType::PinMessage:
case MessageContentType::GameScore:
case MessageContentType::ScreenshotTaken:
case MessageContentType::ChatSetTtl:
case MessageContentType::Call:
case MessageContentType::PaymentSuccessful:
case MessageContentType::ContactRegistered:
case MessageContentType::CustomServiceAction:
case MessageContentType::WebsiteConnected:
case MessageContentType::PassportDataSent:
case MessageContentType::PassportDataReceived:
case MessageContentType::Poll:
return false;
default:
UNREACHABLE();
return false;
}
}
bool can_forward_message_content(const MessageContent *content) {
auto content_type = content->get_type();
if (content_type == MessageContentType::Text) {
@ -2461,162 +2322,6 @@ bool can_forward_message_content(const MessageContent *content) {
content_type != MessageContentType::ExpiredPhoto && content_type != MessageContentType::ExpiredVideo;
}
bool is_secret_message_content(int32 ttl, MessageContentType content_type) {
if (ttl <= 0 || ttl > 60) {
return false;
}
switch (content_type) {
case MessageContentType::Animation:
case MessageContentType::Audio:
case MessageContentType::Photo:
case MessageContentType::Video:
case MessageContentType::VideoNote:
case MessageContentType::VoiceNote:
return true;
case MessageContentType::Contact:
case MessageContentType::Document:
case MessageContentType::Game:
case MessageContentType::Invoice:
case MessageContentType::LiveLocation:
case MessageContentType::Location:
case MessageContentType::Sticker:
case MessageContentType::Text:
case MessageContentType::Unsupported:
case MessageContentType::Venue:
case MessageContentType::ExpiredPhoto:
case MessageContentType::ExpiredVideo:
case MessageContentType::ChatCreate:
case MessageContentType::ChatChangeTitle:
case MessageContentType::ChatChangePhoto:
case MessageContentType::ChatDeletePhoto:
case MessageContentType::ChatDeleteHistory:
case MessageContentType::ChatAddUsers:
case MessageContentType::ChatJoinedByLink:
case MessageContentType::ChatDeleteUser:
case MessageContentType::ChatMigrateTo:
case MessageContentType::ChannelCreate:
case MessageContentType::ChannelMigrateFrom:
case MessageContentType::PinMessage:
case MessageContentType::GameScore:
case MessageContentType::ScreenshotTaken:
case MessageContentType::ChatSetTtl:
case MessageContentType::Call:
case MessageContentType::PaymentSuccessful:
case MessageContentType::ContactRegistered:
case MessageContentType::CustomServiceAction:
case MessageContentType::WebsiteConnected:
case MessageContentType::PassportDataSent:
case MessageContentType::PassportDataReceived:
case MessageContentType::Poll:
return false;
default:
UNREACHABLE();
return false;
}
}
bool is_service_message_content(MessageContentType content_type) {
switch (content_type) {
case MessageContentType::Animation:
case MessageContentType::Audio:
case MessageContentType::Contact:
case MessageContentType::Document:
case MessageContentType::Game:
case MessageContentType::Invoice:
case MessageContentType::LiveLocation:
case MessageContentType::Location:
case MessageContentType::Photo:
case MessageContentType::Sticker:
case MessageContentType::Text:
case MessageContentType::Unsupported:
case MessageContentType::Venue:
case MessageContentType::Video:
case MessageContentType::VideoNote:
case MessageContentType::VoiceNote:
case MessageContentType::ExpiredPhoto:
case MessageContentType::ExpiredVideo:
case MessageContentType::Poll:
return false;
case MessageContentType::ChatCreate:
case MessageContentType::ChatChangeTitle:
case MessageContentType::ChatChangePhoto:
case MessageContentType::ChatDeletePhoto:
case MessageContentType::ChatDeleteHistory:
case MessageContentType::ChatAddUsers:
case MessageContentType::ChatJoinedByLink:
case MessageContentType::ChatDeleteUser:
case MessageContentType::ChatMigrateTo:
case MessageContentType::ChannelCreate:
case MessageContentType::ChannelMigrateFrom:
case MessageContentType::PinMessage:
case MessageContentType::GameScore:
case MessageContentType::ScreenshotTaken:
case MessageContentType::ChatSetTtl:
case MessageContentType::Call:
case MessageContentType::PaymentSuccessful:
case MessageContentType::ContactRegistered:
case MessageContentType::CustomServiceAction:
case MessageContentType::WebsiteConnected:
case MessageContentType::PassportDataSent:
case MessageContentType::PassportDataReceived:
return true;
default:
UNREACHABLE();
return false;
}
}
bool can_have_message_content_caption(MessageContentType content_type) {
switch (content_type) {
case MessageContentType::Animation:
case MessageContentType::Audio:
case MessageContentType::Document:
case MessageContentType::Photo:
case MessageContentType::Video:
case MessageContentType::VoiceNote:
return true;
case MessageContentType::Contact:
case MessageContentType::Game:
case MessageContentType::Invoice:
case MessageContentType::LiveLocation:
case MessageContentType::Location:
case MessageContentType::Sticker:
case MessageContentType::Text:
case MessageContentType::Unsupported:
case MessageContentType::Venue:
case MessageContentType::VideoNote:
case MessageContentType::ChatCreate:
case MessageContentType::ChatChangeTitle:
case MessageContentType::ChatChangePhoto:
case MessageContentType::ChatDeletePhoto:
case MessageContentType::ChatDeleteHistory:
case MessageContentType::ChatAddUsers:
case MessageContentType::ChatJoinedByLink:
case MessageContentType::ChatDeleteUser:
case MessageContentType::ChatMigrateTo:
case MessageContentType::ChannelCreate:
case MessageContentType::ChannelMigrateFrom:
case MessageContentType::PinMessage:
case MessageContentType::GameScore:
case MessageContentType::ScreenshotTaken:
case MessageContentType::ChatSetTtl:
case MessageContentType::Call:
case MessageContentType::PaymentSuccessful:
case MessageContentType::ContactRegistered:
case MessageContentType::ExpiredPhoto:
case MessageContentType::ExpiredVideo:
case MessageContentType::CustomServiceAction:
case MessageContentType::WebsiteConnected:
case MessageContentType::PassportDataSent:
case MessageContentType::PassportDataReceived:
case MessageContentType::Poll:
return false;
default:
UNREACHABLE();
return false;
}
}
bool update_opened_message_content(MessageContent *content) {
switch (content->get_type()) {
case MessageContentType::VideoNote: {
@ -2807,16 +2512,11 @@ bool get_message_content_poll_is_anonymous(const Td *td, const MessageContent *c
}
}
WebPageId get_message_content_web_page_id(const MessageContent *content) {
if (content->get_type() == MessageContentType::Text) {
return static_cast<const MessageText *>(content)->web_page_id;
}
return WebPageId();
}
void set_message_content_web_page_id(MessageContent *content, WebPageId web_page_id) {
void remove_message_content_web_page(MessageContent *content) {
CHECK(content->get_type() == MessageContentType::Text);
static_cast<MessageText *>(content)->web_page_id = web_page_id;
auto &web_page_id = static_cast<MessageText *>(content)->web_page_id;
CHECK(web_page_id.is_valid());
web_page_id = WebPageId();
}
void set_message_content_poll_answer(Td *td, const MessageContent *content, FullMessageId full_message_id,
@ -3475,10 +3175,10 @@ bool merge_message_content_file_id(Td *td, MessageContent *message_content, File
}
void register_message_content(Td *td, const MessageContent *content, FullMessageId full_message_id) {
if (full_message_id.get_message_id().is_scheduled()) {
return;
}
switch (content->get_type()) {
case MessageContentType::Text:
return td->web_pages_manager_->register_web_page(static_cast<const MessageText *>(content)->web_page_id,
full_message_id);
case MessageContentType::Poll:
return td->poll_manager_->register_poll(static_cast<const MessagePoll *>(content)->poll_id, full_message_id);
default:
@ -3486,11 +3186,37 @@ void register_message_content(Td *td, const MessageContent *content, FullMessage
}
}
void unregister_message_content(Td *td, const MessageContent *content, FullMessageId full_message_id) {
if (full_message_id.get_message_id().is_scheduled()) {
return;
void reregister_message_content(Td *td, const MessageContent *old_content, const MessageContent *new_content,
FullMessageId full_message_id) {
auto old_content_type = old_content->get_type();
auto new_content_type = new_content->get_type();
if (old_content_type == new_content_type) {
switch (old_content_type) {
case MessageContentType::Text:
if (static_cast<const MessageText *>(old_content)->web_page_id ==
static_cast<const MessageText *>(new_content)->web_page_id) {
return;
}
break;
case MessageContentType::Poll:
if (static_cast<const MessagePoll *>(old_content)->poll_id ==
static_cast<const MessagePoll *>(new_content)->poll_id) {
return;
}
break;
default:
return;
}
}
unregister_message_content(td, old_content, full_message_id);
register_message_content(td, new_content, full_message_id);
}
void unregister_message_content(Td *td, const MessageContent *content, FullMessageId full_message_id) {
switch (content->get_type()) {
case MessageContentType::Text:
return td->web_pages_manager_->unregister_web_page(static_cast<const MessageText *>(content)->web_page_id,
full_message_id);
case MessageContentType::Poll:
return td->poll_manager_->unregister_poll(static_cast<const MessagePoll *>(content)->poll_id, full_message_id);
default:
@ -5163,4 +4889,39 @@ StickerSetId add_sticker_set(Td *td, tl_object_ptr<telegram_api::InputStickerSet
return td->stickers_manager_->add_sticker_set(std::move(input_sticker_set));
}
void on_dialog_used(TopDialogCategory category, DialogId dialog_id, int32 date) {
send_closure(G()->top_dialog_manager(), &TopDialogManager::on_dialog_used, category, dialog_id, date);
}
void update_used_hashtags(Td *td, const MessageContent *content) {
const FormattedText *text = get_message_content_text(content);
if (text == nullptr || text->text.empty()) {
return;
}
const unsigned char *ptr = Slice(text->text).ubegin();
const unsigned char *end = Slice(text->text).uend();
int32 utf16_pos = 0;
for (auto &entity : text->entities) {
if (entity.type != MessageEntity::Type::Hashtag) {
continue;
}
while (utf16_pos < entity.offset && ptr < end) {
utf16_pos += 1 + (ptr[0] >= 0xf0);
ptr = next_utf8_unsafe(ptr, nullptr, "update_used_hashtags");
}
CHECK(utf16_pos == entity.offset);
auto from = ptr;
while (utf16_pos < entity.offset + entity.length && ptr < end) {
utf16_pos += 1 + (ptr[0] >= 0xf0);
ptr = next_utf8_unsafe(ptr, nullptr, "update_used_hashtags 2");
}
CHECK(utf16_pos == entity.offset + entity.length);
auto to = ptr;
send_closure(td->hashtag_hints_, &HashtagHints::hashtag_used, Slice(from + 1, to).str());
}
}
} // namespace td

View File

@ -11,14 +11,17 @@
#include "td/telegram/files/FileId.h"
#include "td/telegram/FullMessageId.h"
#include "td/telegram/logevent/LogEvent.h"
#include "td/telegram/MessageContentType.h"
#include "td/telegram/MessageEntity.h"
#include "td/telegram/MessageId.h"
#include "td/telegram/Photo.h"
#include "td/telegram/ReplyMarkup.h"
#include "td/telegram/secret_api.h"
#include "td/telegram/SecretInputMedia.h"
#include "td/telegram/StickerSetId.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/telegram/TopDialogCategory.h"
#include "td/telegram/UserId.h"
#include "td/telegram/WebPageId.h"
@ -27,7 +30,8 @@
#include "td/utils/buffer.h"
#include "td/utils/common.h"
#include "td/utils/Status.h"
#include "td/utils/StringBuilder.h"
#include <utility>
namespace td {
@ -37,53 +41,6 @@ class Td;
class MultiPromiseActor;
enum class MessageContentType : int32 {
None = -1,
Text,
Animation,
Audio,
Document,
Photo,
Sticker,
Video,
VoiceNote,
Contact,
Location,
Venue,
ChatCreate,
ChatChangeTitle,
ChatChangePhoto,
ChatDeletePhoto,
ChatDeleteHistory,
ChatAddUsers,
ChatJoinedByLink,
ChatDeleteUser,
ChatMigrateTo,
ChannelCreate,
ChannelMigrateFrom,
PinMessage,
Game,
GameScore,
ScreenshotTaken,
ChatSetTtl,
Unsupported,
Call,
Invoice,
PaymentSuccessful,
VideoNote,
ContactRegistered,
ExpiredPhoto,
ExpiredVideo,
LiveLocation,
CustomServiceAction,
WebsiteConnected,
PassportDataSent,
PassportDataReceived,
Poll
};
StringBuilder &operator<<(StringBuilder &string_builder, MessageContentType content_type);
// Do not forget to update merge_message_contents when one of the inheritors of this class changes
class MessageContent {
public:
@ -158,16 +115,8 @@ tl_object_ptr<telegram_api::InputMedia> get_input_media(const MessageContent *co
void delete_message_content_thumbnail(MessageContent *content, Td *td);
bool is_allowed_media_group_content(MessageContentType content_type);
bool can_forward_message_content(const MessageContent *content);
bool is_secret_message_content(int32 ttl, MessageContentType content_type);
bool is_service_message_content(MessageContentType content_type);
bool can_have_message_content_caption(MessageContentType content_type);
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);
@ -186,9 +135,7 @@ bool get_message_content_poll_is_closed(const Td *td, const MessageContent *cont
bool get_message_content_poll_is_anonymous(const Td *td, const MessageContent *content);
WebPageId get_message_content_web_page_id(const MessageContent *content);
void set_message_content_web_page_id(MessageContent *content, WebPageId web_page_id);
void remove_message_content_web_page(MessageContent *content);
void set_message_content_poll_answer(Td *td, const MessageContent *content, FullMessageId full_message_id,
vector<int32> &&option_ids, Promise<Unit> &&promise);
@ -208,6 +155,9 @@ bool merge_message_content_file_id(Td *td, MessageContent *message_content, File
void register_message_content(Td *td, const MessageContent *content, FullMessageId full_message_id);
void reregister_message_content(Td *td, const MessageContent *old_content, const MessageContent *new_content,
FullMessageId full_message_id);
void unregister_message_content(Td *td, const MessageContent *content, FullMessageId full_message_id);
unique_ptr<MessageContent> get_secret_message_content(
@ -264,4 +214,8 @@ void on_sent_message_content(Td *td, const MessageContent *content);
StickerSetId add_sticker_set(Td *td, tl_object_ptr<telegram_api::InputStickerSet> &&input_sticker_set);
void on_dialog_used(TopDialogCategory category, DialogId dialog_id, int32 date);
void update_used_hashtags(Td *td, const MessageContent *content);
} // namespace td

View File

@ -0,0 +1,310 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "td/telegram/MessageContentType.h"
namespace td {
StringBuilder &operator<<(StringBuilder &string_builder, MessageContentType content_type) {
switch (content_type) {
case MessageContentType::None:
return string_builder << "None";
case MessageContentType::Animation:
return string_builder << "Animation";
case MessageContentType::Audio:
return string_builder << "Audio";
case MessageContentType::Document:
return string_builder << "Document";
case MessageContentType::ExpiredPhoto:
return string_builder << "ExpiredPhoto";
case MessageContentType::Photo:
return string_builder << "Photo";
case MessageContentType::ExpiredVideo:
return string_builder << "ExpiredVideo";
case MessageContentType::Video:
return string_builder << "Video";
case MessageContentType::VideoNote:
return string_builder << "VideoNote";
case MessageContentType::VoiceNote:
return string_builder << "VoiceNote";
case MessageContentType::Contact:
return string_builder << "Contact";
case MessageContentType::LiveLocation:
return string_builder << "LiveLocation";
case MessageContentType::Location:
return string_builder << "Location";
case MessageContentType::Venue:
return string_builder << "Venue";
case MessageContentType::Game:
return string_builder << "Game";
case MessageContentType::Invoice:
return string_builder << "Invoice";
case MessageContentType::Sticker:
return string_builder << "Sticker";
case MessageContentType::Text:
return string_builder << "Text";
case MessageContentType::Unsupported:
return string_builder << "Unsupported";
case MessageContentType::ChatCreate:
return string_builder << "ChatCreate";
case MessageContentType::ChatChangeTitle:
return string_builder << "ChatChangeTitle";
case MessageContentType::ChatChangePhoto:
return string_builder << "ChatChangePhoto";
case MessageContentType::ChatDeletePhoto:
return string_builder << "ChatDeletePhoto";
case MessageContentType::ChatDeleteHistory:
return string_builder << "ChatDeleteHistory";
case MessageContentType::ChatAddUsers:
return string_builder << "ChatAddUsers";
case MessageContentType::ChatJoinedByLink:
return string_builder << "ChatJoinedByLink";
case MessageContentType::ChatDeleteUser:
return string_builder << "ChatDeleteUser";
case MessageContentType::ChatMigrateTo:
return string_builder << "ChatMigrateTo";
case MessageContentType::ChannelCreate:
return string_builder << "ChannelCreate";
case MessageContentType::ChannelMigrateFrom:
return string_builder << "ChannelMigrateFrom";
case MessageContentType::PinMessage:
return string_builder << "PinMessage";
case MessageContentType::GameScore:
return string_builder << "GameScore";
case MessageContentType::ScreenshotTaken:
return string_builder << "ScreenshotTaken";
case MessageContentType::ChatSetTtl:
return string_builder << "ChatSetTtl";
case MessageContentType::Call:
return string_builder << "Call";
case MessageContentType::PaymentSuccessful:
return string_builder << "PaymentSuccessful";
case MessageContentType::ContactRegistered:
return string_builder << "ContactRegistered";
case MessageContentType::CustomServiceAction:
return string_builder << "CustomServiceAction";
case MessageContentType::WebsiteConnected:
return string_builder << "WebsiteConnected";
case MessageContentType::PassportDataSent:
return string_builder << "PassportDataSent";
case MessageContentType::PassportDataReceived:
return string_builder << "PassportDataReceived";
case MessageContentType::Poll:
return string_builder << "Poll";
default:
UNREACHABLE();
return string_builder;
}
}
bool is_allowed_media_group_content(MessageContentType content_type) {
switch (content_type) {
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:
case MessageContentType::Location:
case MessageContentType::Sticker:
case MessageContentType::Text:
case MessageContentType::Unsupported:
case MessageContentType::Venue:
case MessageContentType::VideoNote:
case MessageContentType::VoiceNote:
case MessageContentType::ChatCreate:
case MessageContentType::ChatChangeTitle:
case MessageContentType::ChatChangePhoto:
case MessageContentType::ChatDeletePhoto:
case MessageContentType::ChatDeleteHistory:
case MessageContentType::ChatAddUsers:
case MessageContentType::ChatJoinedByLink:
case MessageContentType::ChatDeleteUser:
case MessageContentType::ChatMigrateTo:
case MessageContentType::ChannelCreate:
case MessageContentType::ChannelMigrateFrom:
case MessageContentType::PinMessage:
case MessageContentType::GameScore:
case MessageContentType::ScreenshotTaken:
case MessageContentType::ChatSetTtl:
case MessageContentType::Call:
case MessageContentType::PaymentSuccessful:
case MessageContentType::ContactRegistered:
case MessageContentType::CustomServiceAction:
case MessageContentType::WebsiteConnected:
case MessageContentType::PassportDataSent:
case MessageContentType::PassportDataReceived:
case MessageContentType::Poll:
return false;
default:
UNREACHABLE();
return false;
}
}
bool is_secret_message_content(int32 ttl, MessageContentType content_type) {
if (ttl <= 0 || ttl > 60) {
return false;
}
switch (content_type) {
case MessageContentType::Animation:
case MessageContentType::Audio:
case MessageContentType::Photo:
case MessageContentType::Video:
case MessageContentType::VideoNote:
case MessageContentType::VoiceNote:
return true;
case MessageContentType::Contact:
case MessageContentType::Document:
case MessageContentType::Game:
case MessageContentType::Invoice:
case MessageContentType::LiveLocation:
case MessageContentType::Location:
case MessageContentType::Sticker:
case MessageContentType::Text:
case MessageContentType::Unsupported:
case MessageContentType::Venue:
case MessageContentType::ExpiredPhoto:
case MessageContentType::ExpiredVideo:
case MessageContentType::ChatCreate:
case MessageContentType::ChatChangeTitle:
case MessageContentType::ChatChangePhoto:
case MessageContentType::ChatDeletePhoto:
case MessageContentType::ChatDeleteHistory:
case MessageContentType::ChatAddUsers:
case MessageContentType::ChatJoinedByLink:
case MessageContentType::ChatDeleteUser:
case MessageContentType::ChatMigrateTo:
case MessageContentType::ChannelCreate:
case MessageContentType::ChannelMigrateFrom:
case MessageContentType::PinMessage:
case MessageContentType::GameScore:
case MessageContentType::ScreenshotTaken:
case MessageContentType::ChatSetTtl:
case MessageContentType::Call:
case MessageContentType::PaymentSuccessful:
case MessageContentType::ContactRegistered:
case MessageContentType::CustomServiceAction:
case MessageContentType::WebsiteConnected:
case MessageContentType::PassportDataSent:
case MessageContentType::PassportDataReceived:
case MessageContentType::Poll:
return false;
default:
UNREACHABLE();
return false;
}
}
bool is_service_message_content(MessageContentType content_type) {
switch (content_type) {
case MessageContentType::Animation:
case MessageContentType::Audio:
case MessageContentType::Contact:
case MessageContentType::Document:
case MessageContentType::Game:
case MessageContentType::Invoice:
case MessageContentType::LiveLocation:
case MessageContentType::Location:
case MessageContentType::Photo:
case MessageContentType::Sticker:
case MessageContentType::Text:
case MessageContentType::Unsupported:
case MessageContentType::Venue:
case MessageContentType::Video:
case MessageContentType::VideoNote:
case MessageContentType::VoiceNote:
case MessageContentType::ExpiredPhoto:
case MessageContentType::ExpiredVideo:
case MessageContentType::Poll:
return false;
case MessageContentType::ChatCreate:
case MessageContentType::ChatChangeTitle:
case MessageContentType::ChatChangePhoto:
case MessageContentType::ChatDeletePhoto:
case MessageContentType::ChatDeleteHistory:
case MessageContentType::ChatAddUsers:
case MessageContentType::ChatJoinedByLink:
case MessageContentType::ChatDeleteUser:
case MessageContentType::ChatMigrateTo:
case MessageContentType::ChannelCreate:
case MessageContentType::ChannelMigrateFrom:
case MessageContentType::PinMessage:
case MessageContentType::GameScore:
case MessageContentType::ScreenshotTaken:
case MessageContentType::ChatSetTtl:
case MessageContentType::Call:
case MessageContentType::PaymentSuccessful:
case MessageContentType::ContactRegistered:
case MessageContentType::CustomServiceAction:
case MessageContentType::WebsiteConnected:
case MessageContentType::PassportDataSent:
case MessageContentType::PassportDataReceived:
return true;
default:
UNREACHABLE();
return false;
}
}
bool can_have_message_content_caption(MessageContentType content_type) {
switch (content_type) {
case MessageContentType::Animation:
case MessageContentType::Audio:
case MessageContentType::Document:
case MessageContentType::Photo:
case MessageContentType::Video:
case MessageContentType::VoiceNote:
return true;
case MessageContentType::Contact:
case MessageContentType::Game:
case MessageContentType::Invoice:
case MessageContentType::LiveLocation:
case MessageContentType::Location:
case MessageContentType::Sticker:
case MessageContentType::Text:
case MessageContentType::Unsupported:
case MessageContentType::Venue:
case MessageContentType::VideoNote:
case MessageContentType::ChatCreate:
case MessageContentType::ChatChangeTitle:
case MessageContentType::ChatChangePhoto:
case MessageContentType::ChatDeletePhoto:
case MessageContentType::ChatDeleteHistory:
case MessageContentType::ChatAddUsers:
case MessageContentType::ChatJoinedByLink:
case MessageContentType::ChatDeleteUser:
case MessageContentType::ChatMigrateTo:
case MessageContentType::ChannelCreate:
case MessageContentType::ChannelMigrateFrom:
case MessageContentType::PinMessage:
case MessageContentType::GameScore:
case MessageContentType::ScreenshotTaken:
case MessageContentType::ChatSetTtl:
case MessageContentType::Call:
case MessageContentType::PaymentSuccessful:
case MessageContentType::ContactRegistered:
case MessageContentType::ExpiredPhoto:
case MessageContentType::ExpiredVideo:
case MessageContentType::CustomServiceAction:
case MessageContentType::WebsiteConnected:
case MessageContentType::PassportDataSent:
case MessageContentType::PassportDataReceived:
case MessageContentType::Poll:
return false;
default:
UNREACHABLE();
return false;
}
}
} // namespace td

View File

@ -0,0 +1,69 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/utils/common.h"
#include "td/utils/StringBuilder.h"
namespace td {
enum class MessageContentType : int32 {
None = -1,
Text,
Animation,
Audio,
Document,
Photo,
Sticker,
Video,
VoiceNote,
Contact,
Location,
Venue,
ChatCreate,
ChatChangeTitle,
ChatChangePhoto,
ChatDeletePhoto,
ChatDeleteHistory,
ChatAddUsers,
ChatJoinedByLink,
ChatDeleteUser,
ChatMigrateTo,
ChannelCreate,
ChannelMigrateFrom,
PinMessage,
Game,
GameScore,
ScreenshotTaken,
ChatSetTtl,
Unsupported,
Call,
Invoice,
PaymentSuccessful,
VideoNote,
ContactRegistered,
ExpiredPhoto,
ExpiredVideo,
LiveLocation,
CustomServiceAction,
WebsiteConnected,
PassportDataSent,
PassportDataReceived,
Poll
};
StringBuilder &operator<<(StringBuilder &string_builder, MessageContentType content_type);
bool is_allowed_media_group_content(MessageContentType content_type);
bool is_secret_message_content(int32 ttl, MessageContentType content_type);
bool is_service_message_content(MessageContentType content_type);
bool can_have_message_content_caption(MessageContentType content_type);
} // namespace td

View File

@ -20,7 +20,6 @@
#include "td/telegram/files/FileManager.h"
#include "td/telegram/files/FileType.h"
#include "td/telegram/Global.h"
#include "td/telegram/HashtagHints.h"
#include "td/telegram/InlineQueriesManager.h"
#include "td/telegram/InputMessageText.h"
#include "td/telegram/Location.h"
@ -45,11 +44,10 @@
#include "td/telegram/SequenceDispatcher.h"
#include "td/telegram/Td.h"
#include "td/telegram/TdDb.h"
#include "td/telegram/TopDialogManager.h"
#include "td/telegram/TopDialogCategory.h"
#include "td/telegram/UpdatesManager.h"
#include "td/telegram/Version.h"
#include "td/telegram/WebPageId.h"
#include "td/telegram/WebPagesManager.h"
#include "td/actor/PromiseFuture.h"
#include "td/actor/SleepActor.h"
@ -5744,15 +5742,17 @@ void MessagesManager::on_update_some_live_location_viewed(Promise<Unit> &&promis
promise.set_value(Unit());
}
void MessagesManager::on_update_message_content(FullMessageId full_message_id) {
void MessagesManager::on_external_update_message_content(FullMessageId full_message_id) {
const Dialog *d = get_dialog(full_message_id.get_dialog_id());
CHECK(d != nullptr);
const Message *m = get_message(d, full_message_id.get_message_id());
CHECK(m != nullptr);
auto live_location_date = m->is_failed_to_send ? 0 : m->date;
send_update_message_content(full_message_id.get_dialog_id(), m->message_id, m->content.get(), live_location_date,
m->is_content_secret, "on_update_message_content");
on_message_changed(d, m, true, "on_update_message_content");
m->is_content_secret, "on_external_update_message_content");
if (m->message_id == d->last_message_id) {
send_update_chat_last_message_impl(d, "on_external_update_message_content");
}
}
bool MessagesManager::update_message_contains_unread_mention(Dialog *d, Message *m, bool contains_unread_mention,
@ -11870,59 +11870,37 @@ void MessagesManager::on_update_sent_text_message(int64 random_id,
return;
}
unregister_message_content(td_, m->content.get(), full_message_id);
bool need_update = false;
bool is_content_changed = false;
merge_message_contents(td_, m->content.get(), new_content.get(), need_message_changed_warning(m), dialog_id, false,
is_content_changed, need_update);
if (is_content_changed || need_update) {
reregister_message_content(td_, m->content.get(), new_content.get(), full_message_id);
m->content = std::move(new_content);
m->is_content_secret = is_secret_message_content(m->ttl, MessageContentType::Text);
}
register_message_content(td_, m->content.get(), full_message_id);
if (need_update) {
send_update_message_content(dialog_id, m->message_id, m->content.get(), m->date, m->is_content_secret,
"on_update_sent_text_message");
}
}
void MessagesManager::on_update_message_web_page(FullMessageId full_message_id, bool have_web_page) {
waiting_for_web_page_messages_.erase(full_message_id);
void MessagesManager::delete_pending_message_web_page(FullMessageId full_message_id) {
auto dialog_id = full_message_id.get_dialog_id();
Dialog *d = get_dialog(dialog_id);
if (d == nullptr) {
LOG(INFO) << "Can't find " << dialog_id;
// dialog can be not yet added
return;
}
CHECK(d != nullptr);
Message *m = get_message(d, full_message_id.get_message_id());
if (m == nullptr) {
// message can be already deleted
return;
}
CHECK(m->date > 0);
CHECK(m != nullptr);
MessageContent *content = m->content.get();
auto old_web_page_id = get_message_content_web_page_id(content);
if (!old_web_page_id.is_valid()) {
// webpage has already been received as empty
LOG_IF(ERROR, have_web_page) << "Receive earlier not received web page";
return;
}
CHECK(content->get_type() == MessageContentType::Text);
unregister_message_content(td_, content, full_message_id);
remove_message_content_web_page(content);
register_message_content(td_, content, full_message_id);
if (!have_web_page) {
set_message_content_web_page_id(content, WebPageId());
// don't need to send an update
// don't need to send an updateMessageContent, because the web page was pending
on_message_changed(d, m, true, "on_update_message_web_page");
return;
}
send_update_message_content(dialog_id, m->message_id, content, m->date, m->is_content_secret,
"on_update_message_web_page");
on_message_changed(d, m, false, "delete_pending_message_web_page");
}
void MessagesManager::on_get_dialogs(FolderId folder_id, vector<tl_object_ptr<telegram_api::Dialog>> &&dialog_folders,
@ -12322,7 +12300,6 @@ bool MessagesManager::can_unload_message(const Dialog *d, const Message *m) cons
CHECK(m->message_id.is_valid());
// don't want to unload messages from opened dialogs
// don't want to unload messages to which there are replies in yet unsent messages
// don't want to unload messages with pending web pages
// don't want to unload message with active reply markup
// don't want to unload pinned message
// don't want to unload last edited message, because server can send updateEditChannelMessage again
@ -12332,9 +12309,8 @@ bool MessagesManager::can_unload_message(const Dialog *d, const Message *m) cons
return !d->is_opened && m->message_id != d->last_message_id && m->message_id != d->last_database_message_id &&
!m->message_id.is_yet_unsent() && active_live_location_full_message_ids_.count(full_message_id) == 0 &&
replied_by_yet_unsent_messages_.count(full_message_id) == 0 && m->edited_content == nullptr &&
waiting_for_web_page_messages_.count(full_message_id) == 0 && d->suffix_load_queries_.empty() &&
m->message_id != d->reply_markup_message_id && m->message_id != d->pinned_message_id &&
m->message_id != d->last_edited_message_id;
d->suffix_load_queries_.empty() && m->message_id != d->reply_markup_message_id &&
m->message_id != d->pinned_message_id && m->message_id != d->last_edited_message_id;
}
void MessagesManager::unload_message(Dialog *d, MessageId message_id) {
@ -12602,10 +12578,9 @@ unique_ptr<MessagesManager::Message> MessagesManager::do_delete_message(Dialog *
return nullptr;
}
LOG_CHECK(!d->being_deleted_message_id.is_valid()) << d->being_deleted_message_id << " " << message_id << " "
<< d->debug_being_deleted_message_id_source << " " << source;
LOG_CHECK(!d->being_deleted_message_id.is_valid())
<< d->being_deleted_message_id << " " << message_id << " " << source;
d->being_deleted_message_id = message_id;
d->debug_being_deleted_message_id_source = source;
if (is_debug_message_op_enabled()) {
d->debug_message_op.emplace_back(Dialog::MessageOp::Delete, m->message_id, m->content->get_type(), false,
@ -12732,7 +12707,6 @@ unique_ptr<MessagesManager::Message> MessagesManager::do_delete_message(Dialog *
auto result = treap_delete_message(v);
d->being_deleted_message_id = MessageId();
d->debug_being_deleted_message_id_source = "";
if (!only_from_memory) {
if (need_get_history && !td_->auth_manager_->is_bot() && have_input_peer(d->dialog_id, AccessRights::Read)) {
@ -12851,6 +12825,8 @@ unique_ptr<MessagesManager::Message> MessagesManager::do_delete_scheduled_messag
cancel_send_deleted_message(d->dialog_id, result.get(), is_permanently_deleted);
unregister_message_content(td_, result->content.get(), {d->dialog_id, message_id});
return result;
}
@ -12894,7 +12870,7 @@ void MessagesManager::load_dialogs(vector<DialogId> dialog_ids, Promise<Unit> &&
add_dialog_dependencies(dependencies, dialog_id);
}
}
resolve_dependencies_force(dependencies);
resolve_dependencies_force(td_, dependencies);
for (auto dialog_id : dialog_ids) {
if (dialog_id.is_valid()) {
@ -16296,7 +16272,7 @@ void MessagesManager::on_load_active_live_location_full_message_ids_from_databas
on_load_active_live_location_messages_finished();
if (!new_full_message_ids.empty()) {
if (!new_full_message_ids.empty() || old_full_message_ids.size() != active_live_location_full_message_ids_.size()) {
save_active_live_locations();
}
}
@ -16345,7 +16321,7 @@ void MessagesManager::add_active_live_location(FullMessageId full_message_id) {
if (are_active_live_location_messages_loaded_) {
save_active_live_locations();
} else {
} else if (load_active_live_location_messages_queries_.empty()) {
// load active live locations and save after that
get_active_live_location_messages(Auto());
}
@ -17148,12 +17124,6 @@ void MessagesManager::on_get_history_from_database(DialogId dialog_id, MessageId
message->from_database = true;
auto old_message = get_message(d, message->message_id);
if (old_message == nullptr) {
auto web_page_id = get_message_content_web_page_id(message->content.get());
if (web_page_id.is_valid()) {
td_->web_pages_manager_->have_web_page_force(web_page_id);
}
}
Message *m = old_message ? old_message
: add_message_to_dialog(d, std::move(message), false, &need_update,
&need_update_dialog_pos, "on_get_history_from_database");
@ -17190,7 +17160,7 @@ void MessagesManager::on_get_history_from_database(DialogId dialog_id, MessageId
is_first = false;
pos++;
}
resolve_dependencies_force(dependencies);
resolve_dependencies_force(td_, dependencies);
if (!added_new_message && !only_local && dialog_id.get_type() != DialogType::SecretChat) {
if (from_the_end) {
@ -17459,10 +17429,6 @@ void MessagesManager::on_get_scheduled_messages_from_database(DialogId dialog_id
continue;
}
auto web_page_id = get_message_content_web_page_id(message->content.get());
if (web_page_id.is_valid()) {
td_->web_pages_manager_->have_web_page_force(web_page_id);
}
bool need_update = false;
Message *m = add_scheduled_message_to_dialog(d, std::move(message), false, &need_update,
"on_get_scheduled_messages_from_database");
@ -17471,7 +17437,7 @@ void MessagesManager::on_get_scheduled_messages_from_database(DialogId dialog_id
added_message_ids.push_back(m->message_id);
}
}
resolve_dependencies_force(dependencies);
resolve_dependencies_force(td_, dependencies);
for (auto message_id : added_message_ids) {
send_update_new_message(d, get_message(d, message_id));
@ -18153,40 +18119,6 @@ void MessagesManager::add_dialog_dependencies(Dependencies &dependencies, Dialog
}
}
void MessagesManager::resolve_dependencies_force(const Dependencies &dependencies) {
for (auto user_id : dependencies.user_ids) {
if (user_id.is_valid() && !td_->contacts_manager_->have_user_force(user_id)) {
LOG(ERROR) << "Can't find " << user_id;
}
}
for (auto chat_id : dependencies.chat_ids) {
if (chat_id.is_valid() && !td_->contacts_manager_->have_chat_force(chat_id)) {
LOG(ERROR) << "Can't find " << chat_id;
}
}
for (auto channel_id : dependencies.channel_ids) {
if (channel_id.is_valid() && !td_->contacts_manager_->have_channel_force(channel_id)) {
LOG(ERROR) << "Can't find " << channel_id;
}
}
for (auto secret_chat_id : dependencies.secret_chat_ids) {
if (secret_chat_id.is_valid() && !td_->contacts_manager_->have_secret_chat_force(secret_chat_id)) {
LOG(ERROR) << "Can't find " << secret_chat_id;
}
}
for (auto dialog_id : dependencies.dialog_ids) {
if (dialog_id.is_valid() && !have_dialog_force(dialog_id)) {
LOG(ERROR) << "Can't find " << dialog_id;
force_create_dialog(dialog_id, "resolve_dependencies_force");
}
}
for (auto web_page_id : dependencies.web_page_ids) {
if (web_page_id.is_valid()) {
td_->web_pages_manager_->have_web_page_force(web_page_id);
}
}
}
class MessagesManager::SendMessageLogEvent {
public:
DialogId dialog_id;
@ -25743,7 +25675,7 @@ MessagesManager::Message *MessagesManager::on_get_message_from_database(DialogId
Dependencies dependencies;
add_message_dependencies(dependencies, d->dialog_id, m.get());
resolve_dependencies_force(dependencies);
resolve_dependencies_force(td_, dependencies);
m->have_previous = false;
m->have_next = false;
@ -25876,7 +25808,7 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq
if (message_id.is_server()) {
if (d->being_added_message_id.is_valid()) {
// if a too new message not from update has failed to preload before being_added_message_id was set,
// then it should fail to load event after it is set and last_new_message_id has changed
// then it should fail to load even after it is set and last_new_message_id has changed
max_message_id = d->being_updated_last_new_message_id;
} else {
max_message_id = d->last_new_message_id;
@ -25944,13 +25876,6 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq
return nullptr;
}
auto web_page_id = get_message_content_web_page_id(message->content.get());
if (web_page_id.is_valid() && !td_->web_pages_manager_->have_web_page(web_page_id)) {
waiting_for_web_page_messages_.emplace(dialog_id, message_id);
send_closure(G()->web_pages_manager(), &WebPagesManager::wait_for_pending_web_page,
FullMessageId{dialog_id, message_id}, web_page_id);
}
if (*need_update && message_id <= d->last_new_message_id) {
*need_update = false;
}
@ -26065,7 +25990,6 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq
}
MessageId added_pinned_message_id; // TODO remove
MessageId preloaded_pinned_message_id; // TODO remove
const char *add_error_reason = "";
if (*need_update) {
auto pinned_message_id = get_message_content_pinned_message_id(message->content.get());
added_pinned_message_id = pinned_message_id;
@ -26073,7 +25997,6 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq
preloaded_pinned_message_id = pinned_message_id;
LOG(INFO) << "Preloaded pinned " << pinned_message_id << " from database";
}
add_error_reason = debug_add_message_to_dialog_fail_reason_;
if (d->pinned_message_notification_message_id.is_valid() &&
have_message_force({dialog_id, d->pinned_message_notification_message_id},
@ -26085,19 +26008,13 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq
// there must be no two recursive calls to add_message_to_dialog
LOG_CHECK(!d->being_added_message_id.is_valid())
<< d->dialog_id << " " << d->being_added_message_id << " " << message_id << " " << *need_update << " "
<< d->debug_being_added_need_update << " " << d->pinned_message_notification_message_id << " "
<< preloaded_pinned_message_id << " " << d->debug_preloaded_pinned_message_id << " "
<< d->debug_added_pinned_message_id << " " << d->debug_add_message_to_dialog_fail_reason << " " << source;
LOG_CHECK(!d->being_deleted_message_id.is_valid()) << d->being_deleted_message_id << " " << message_id << " "
<< d->debug_being_deleted_message_id_source << " " << source;
<< d->pinned_message_notification_message_id << " " << preloaded_pinned_message_id << " " << source;
LOG_CHECK(!d->being_deleted_message_id.is_valid())
<< d->being_deleted_message_id << " " << message_id << " " << source;
d->being_added_message_id = message_id;
d->being_updated_last_new_message_id = d->last_new_message_id;
d->being_updated_last_database_message_id = d->last_database_message_id;
d->debug_being_added_need_update = *need_update;
d->debug_preloaded_pinned_message_id = preloaded_pinned_message_id;
d->debug_added_pinned_message_id = added_pinned_message_id;
d->debug_add_message_to_dialog_fail_reason = add_error_reason;
if (d->new_secret_chat_notification_id.is_valid()) {
remove_new_secret_chat_notification(d, true);
@ -26523,13 +26440,6 @@ MessagesManager::Message *MessagesManager::add_scheduled_message_to_dialog(Dialo
return nullptr;
}
auto web_page_id = get_message_content_web_page_id(message->content.get());
if (web_page_id.is_valid() && !td_->web_pages_manager_->have_web_page(web_page_id)) {
waiting_for_web_page_messages_.emplace(dialog_id, message_id);
send_closure(G()->web_pages_manager(), &WebPagesManager::wait_for_pending_web_page,
FullMessageId{dialog_id, message_id}, web_page_id);
}
{
Message *m = message->from_database ? get_message(d, message_id)
: get_message_force(d, message_id, "add_scheduled_message_to_dialog");
@ -26572,6 +26482,8 @@ MessagesManager::Message *MessagesManager::add_scheduled_message_to_dialog(Dialo
add_message_file_sources(dialog_id, m);
register_message_content(td_, m->content.get(), {dialog_id, m->message_id});
if (from_update) {
update_sent_message_contents(dialog_id, m);
update_used_hashtags(dialog_id, m);
@ -26931,7 +26843,8 @@ bool MessagesManager::update_message(Dialog *d, Message *old_message, unique_ptr
bool need_send_update = false;
bool is_new_available = new_message->content->get_type() != MessageContentType::ChatDeleteHistory;
bool replace_legacy = (old_message->legacy_layer != 0 &&
(new_message->legacy_layer == 0 || old_message->legacy_layer < new_message->legacy_layer));
(new_message->legacy_layer == 0 || old_message->legacy_layer < new_message->legacy_layer)) ||
old_message->content->get_type() == MessageContentType::Unsupported;
if (old_message->date != new_message->date) {
if (new_message->date > 0) {
LOG_IF(ERROR, !is_scheduled && !new_message->is_outgoing && dialog_id != get_my_dialog_id())
@ -27181,7 +27094,7 @@ bool MessagesManager::update_message(Dialog *d, Message *old_message, unique_ptr
// MessageGame and MessageInvoice reply markup can be generated server side
// some forwards retain their reply markup
if (content_type != MessageContentType::Game && content_type != MessageContentType::Invoice &&
old_message->forward_info == nullptr) {
old_message->forward_info == nullptr && !replace_legacy) {
LOG(ERROR) << message_id << " in " << dialog_id << " has received reply markup " << *new_message->reply_markup
<< ", message content type is " << old_message->content->get_type() << '/'
<< new_message->content->get_type();
@ -27332,12 +27245,9 @@ bool MessagesManager::update_message_content(DialogId dialog_id, Message *old_me
if (is_content_changed || need_update) {
if (is_message_in_dialog) {
unregister_message_content(td_, old_content.get(), {dialog_id, old_message->message_id});
reregister_message_content(td_, old_content.get(), new_content.get(), {dialog_id, old_message->message_id});
}
old_content = std::move(new_content);
if (is_message_in_dialog) {
register_message_content(td_, old_content.get(), {dialog_id, old_message->message_id});
}
update_message_content_file_id_remote(old_content.get(), old_file_id);
} else {
update_message_content_file_id_remote(old_content.get(), get_message_content_any_file_id(new_content.get()));
@ -28383,7 +28293,7 @@ unique_ptr<MessagesManager::Dialog> MessagesManager::parse_dialog(DialogId dialo
if (d->draft_message != nullptr) {
add_formatted_text_dependencies(dependencies, &d->draft_message->input_message_text.text);
}
resolve_dependencies_force(dependencies);
resolve_dependencies_force(td_, dependencies);
return d;
}
@ -29093,33 +29003,8 @@ void MessagesManager::update_used_hashtags(DialogId dialog_id, const Message *m)
m->via_bot_user_id.is_valid() || m->hide_via_bot || m->forward_info != nullptr || m->had_forward_info) {
return;
}
const FormattedText *text = get_message_content_text(m->content.get());
if (text == nullptr || text->text.empty()) {
return;
}
const unsigned char *ptr = Slice(text->text).ubegin();
const unsigned char *end = Slice(text->text).uend();
int32 utf16_pos = 0;
for (auto &entity : text->entities) {
if (entity.type != MessageEntity::Type::Hashtag) {
continue;
}
while (utf16_pos < entity.offset && ptr < end) {
utf16_pos += 1 + (ptr[0] >= 0xf0);
ptr = next_utf8_unsafe(ptr, nullptr, "update_used_hashtags");
}
CHECK(utf16_pos == entity.offset);
auto from = ptr;
while (utf16_pos < entity.offset + entity.length && ptr < end) {
utf16_pos += 1 + (ptr[0] >= 0xf0);
ptr = next_utf8_unsafe(ptr, nullptr, "update_used_hashtags 2");
}
CHECK(utf16_pos == entity.offset + entity.length);
auto to = ptr;
send_closure(td_->hashtag_hints_, &HashtagHints::hashtag_used, Slice(from + 1, to).str());
}
::td::update_used_hashtags(td_, m->content.get());
}
void MessagesManager::update_top_dialogs(DialogId dialog_id, const Message *m) {
@ -29133,8 +29018,7 @@ void MessagesManager::update_top_dialogs(DialogId dialog_id, const Message *m) {
bool is_forward = m->forward_info != nullptr || m->had_forward_info;
if (m->via_bot_user_id.is_valid() && !is_forward) {
// forwarded game messages can't be distinguished from sent via bot game messages, so increase rating anyway
send_closure(G()->top_dialog_manager(), &TopDialogManager::on_dialog_used, TopDialogCategory::BotInline,
DialogId(m->via_bot_user_id), m->date);
on_dialog_used(TopDialogCategory::BotInline, DialogId(m->via_bot_user_id), m->date);
}
if (is_forward) {
@ -29142,7 +29026,7 @@ void MessagesManager::update_top_dialogs(DialogId dialog_id, const Message *m) {
if (last_forward_date < m->date) {
TopDialogCategory category =
dialog_type == DialogType::User ? TopDialogCategory::ForwardUsers : TopDialogCategory::ForwardChats;
send_closure(G()->top_dialog_manager(), &TopDialogManager::on_dialog_used, category, dialog_id, m->date);
on_dialog_used(category, dialog_id, m->date);
last_forward_date = m->date;
}
}
@ -29181,7 +29065,7 @@ void MessagesManager::update_top_dialogs(DialogId dialog_id, const Message *m) {
UNREACHABLE();
}
if (category != TopDialogCategory::Size) {
send_closure(G()->top_dialog_manager(), &TopDialogManager::on_dialog_used, category, dialog_id, m->date);
on_dialog_used(category, dialog_id, m->date);
}
}
@ -29271,7 +29155,7 @@ void MessagesManager::on_binlog_events(vector<BinlogEvent> &&events) {
Dependencies dependencies;
add_dialog_dependencies(dependencies, dialog_id);
add_message_dependencies(dependencies, dialog_id, m.get());
resolve_dependencies_force(dependencies);
resolve_dependencies_force(td_, dependencies);
m->content = dup_message_content(td_, dialog_id, m->content.get(), MessageContentDupType::Send);
@ -29299,7 +29183,7 @@ void MessagesManager::on_binlog_events(vector<BinlogEvent> &&events) {
Dependencies dependencies;
add_dialog_dependencies(dependencies, dialog_id);
add_message_dependencies(dependencies, dialog_id, m.get());
resolve_dependencies_force(dependencies);
resolve_dependencies_force(td_, dependencies);
auto bot_user_id = log_event.bot_user_id;
if (!td_->contacts_manager_->have_user_force(bot_user_id)) {
@ -29336,7 +29220,7 @@ void MessagesManager::on_binlog_events(vector<BinlogEvent> &&events) {
Dependencies dependencies;
add_dialog_dependencies(dependencies, dialog_id);
add_message_dependencies(dependencies, dialog_id, m.get());
resolve_dependencies_force(dependencies);
resolve_dependencies_force(td_, dependencies);
m->content = dup_message_content(td_, dialog_id, m->content.get(), MessageContentDupType::SendViaBot);
@ -29364,7 +29248,7 @@ void MessagesManager::on_binlog_events(vector<BinlogEvent> &&events) {
Dependencies dependencies;
add_dialog_dependencies(dependencies, dialog_id);
add_message_dependencies(dependencies, dialog_id, m.get());
resolve_dependencies_force(dependencies);
resolve_dependencies_force(td_, dependencies);
auto result_message = continue_send_message(dialog_id, std::move(m), event.id_);
if (result_message != nullptr) {
@ -29391,7 +29275,7 @@ void MessagesManager::on_binlog_events(vector<BinlogEvent> &&events) {
for (auto &m : messages) {
add_message_dependencies(dependencies, to_dialog_id, m.get());
}
resolve_dependencies_force(dependencies);
resolve_dependencies_force(td_, dependencies);
Dialog *to_dialog = get_dialog_force(to_dialog_id);
if (to_dialog == nullptr) {
@ -29819,7 +29703,7 @@ void MessagesManager::on_binlog_events(vector<BinlogEvent> &&events) {
auto dialog_id = log_event.dialog_id_;
Dependencies dependencies;
add_dialog_dependencies(dependencies, dialog_id);
resolve_dependencies_force(dependencies);
resolve_dependencies_force(td_, dependencies);
get_dialog_force(dialog_id); // load it if exists

View File

@ -24,7 +24,7 @@
#include "td/telegram/FolderId.h"
#include "td/telegram/FullMessageId.h"
#include "td/telegram/Global.h"
#include "td/telegram/MessageContent.h"
#include "td/telegram/MessageContentType.h"
#include "td/telegram/MessageEntity.h"
#include "td/telegram/MessageId.h"
#include "td/telegram/MessagesDb.h"
@ -73,11 +73,15 @@ namespace td {
struct BinlogEvent;
class Td;
class DraftMessage;
struct InputMessageContent;
class MessageContent;
class MultiSequenceDispatcher;
class DraftMessage;
class Td;
class dummyUpdate : public telegram_api::Update {
public:
@ -266,7 +270,7 @@ class MessagesManager : public Actor {
void on_update_sent_text_message(int64 random_id, tl_object_ptr<telegram_api::MessageMedia> message_media,
vector<tl_object_ptr<telegram_api::MessageEntity>> &&entities);
void on_update_message_web_page(FullMessageId full_message_id, bool have_web_page);
void delete_pending_message_web_page(FullMessageId full_message_id);
void on_get_dialogs(FolderId folder_id, vector<tl_object_ptr<telegram_api::Dialog>> &&dialog_folders,
int32 total_count, vector<tl_object_ptr<telegram_api::Message>> &&messages,
@ -315,7 +319,7 @@ class MessagesManager : public Actor {
void on_update_some_live_location_viewed(Promise<Unit> &&promise);
void on_update_message_content(FullMessageId full_message_id);
void on_external_update_message_content(FullMessageId full_message_id);
void on_read_channel_inbox(ChannelId channel_id, MessageId max_message_id, int32 server_unread_count, int32 pts,
const char *source);
@ -824,8 +828,6 @@ class MessagesManager : public Actor {
static void add_dialog_dependencies(Dependencies &dependencies, DialogId dialog_id);
void resolve_dependencies_force(const Dependencies &dependencies);
ActorOwn<MultiSequenceDispatcher> sequence_dispatcher_;
private:
@ -1071,11 +1073,6 @@ class MessagesManager : public Actor {
MessageId being_updated_last_new_message_id;
MessageId being_updated_last_database_message_id;
MessageId being_deleted_message_id;
const char *debug_being_deleted_message_id_source = "";
bool debug_being_added_need_update = false; // TODO remove
MessageId debug_preloaded_pinned_message_id; // TODO remove
MessageId debug_added_pinned_message_id; // TODO remove
const char *debug_add_message_to_dialog_fail_reason = "";
NotificationGroupInfo message_notification_group;
NotificationGroupInfo mention_notification_group;
@ -2626,8 +2623,6 @@ class MessagesManager : public Actor {
std::unordered_map<FullMessageId, int32, FullMessageIdHash> replied_by_yet_unsent_messages_;
std::unordered_set<FullMessageId, FullMessageIdHash> waiting_for_web_page_messages_;
struct ActiveDialogAction {
UserId user_id;
int32 action_id;

View File

@ -17,6 +17,7 @@
#include "td/telegram/DocumentsManager.h"
#include "td/telegram/files/FileManager.h"
#include "td/telegram/Global.h"
#include "td/telegram/logevent/LogEvent.h"
#include "td/telegram/MessagesManager.h"
#include "td/telegram/misc.h"
#include "td/telegram/net/ConnectionCreator.h"

View File

@ -304,7 +304,7 @@ void PollManager::notify_on_poll_update(PollId poll_id) {
}
for (auto full_message_id : it->second) {
td_->messages_manager_->on_update_message_content(full_message_id);
td_->messages_manager_->on_external_update_message_content(full_message_id);
}
}
@ -572,7 +572,9 @@ PollId PollManager::create_poll(string &&question, vector<string> &&options, boo
void PollManager::register_poll(PollId poll_id, FullMessageId full_message_id) {
CHECK(have_poll(poll_id));
CHECK(!full_message_id.get_message_id().is_scheduled());
if (full_message_id.get_message_id().is_scheduled()) {
return;
}
if (!full_message_id.get_message_id().is_server()) {
return;
}
@ -586,7 +588,9 @@ void PollManager::register_poll(PollId poll_id, FullMessageId full_message_id) {
void PollManager::unregister_poll(PollId poll_id, FullMessageId full_message_id) {
CHECK(have_poll(poll_id));
CHECK(!full_message_id.get_message_id().is_scheduled());
if (full_message_id.get_message_id().is_scheduled()) {
return;
}
if (!full_message_id.get_message_id().is_server()) {
return;
}
@ -1274,6 +1278,8 @@ PollId PollManager::on_get_poll(PollId poll_id, tl_object_ptr<telegram_api::poll
option.is_chosen = is_chosen;
is_changed = true;
}
}
if (!is_min || poll->is_closed) {
bool is_correct = (poll_result->flags_ & telegram_api::pollAnswerVoters::CORRECT_MASK) != 0;
if (is_correct) {
if (correct_option_id != -1) {
@ -1409,8 +1415,8 @@ void PollManager::on_binlog_events(vector<BinlogEvent> &&events) {
auto dialog_id = log_event.full_message_id_.get_dialog_id();
Dependencies dependencies;
td_->messages_manager_->add_dialog_dependencies(dependencies, dialog_id);
td_->messages_manager_->resolve_dependencies_force(dependencies);
MessagesManager::add_dialog_dependencies(dependencies, dialog_id);
resolve_dependencies_force(td_, dependencies);
do_set_poll_answer(log_event.poll_id_, log_event.full_message_id_, std::move(log_event.options_), event.id_,
Auto());
@ -1428,8 +1434,8 @@ void PollManager::on_binlog_events(vector<BinlogEvent> &&events) {
auto dialog_id = log_event.full_message_id_.get_dialog_id();
Dependencies dependencies;
td_->messages_manager_->add_dialog_dependencies(dependencies, dialog_id);
td_->messages_manager_->resolve_dependencies_force(dependencies);
MessagesManager::add_dialog_dependencies(dependencies, dialog_id);
resolve_dependencies_force(td_, dependencies);
do_stop_poll(log_event.poll_id_, log_event.full_message_id_, nullptr, event.id_, Auto());
break;

View File

@ -18,11 +18,13 @@
#include "td/actor/PromiseFuture.h"
#include "td/actor/Timeout.h"
#include "td/utils/buffer.h"
#include "td/utils/common.h"
#include "td/utils/Status.h"
#include <unordered_map>
#include <unordered_set>
#include <utility>
namespace td {

View File

@ -2022,7 +2022,8 @@ StickerSetId StickersManager::on_get_messages_sticker_set(StickerSetId sticker_s
}
}
if (static_cast<int>(s->sticker_ids.size()) != s->sticker_count) {
LOG(ERROR) << "Wrong sticker set size specified in " << set_id << " from " << source;
LOG(ERROR) << "Wrong sticker set size " << s->sticker_count << " instead of " << s->sticker_ids.size()
<< " specified in " << set_id << " from " << source;
s->sticker_count = static_cast<int>(s->sticker_ids.size());
}

View File

@ -229,25 +229,25 @@ void StickersManager::parse_sticker_set(StickerSet *sticker_set, ParserT &parser
sticker_set->is_masks = is_masks;
sticker_set->is_animated = is_animated;
short_name_to_sticker_set_id_.emplace(clean_username(sticker_set->short_name), StickerSetId(sticker_set_id));
short_name_to_sticker_set_id_.emplace(clean_username(sticker_set->short_name), sticker_set->id);
on_update_sticker_set(sticker_set, is_installed, is_archived, false, true);
} else {
if (sticker_set->title != title) {
LOG(INFO) << "Title of " << sticker_set_id << " has changed";
LOG(INFO) << "Title of " << sticker_set->id << " has changed";
}
if (sticker_set->short_name != short_name) {
LOG(ERROR) << "Short name of " << sticker_set_id << " has changed from \"" << short_name << "\" to \""
LOG(ERROR) << "Short name of " << sticker_set->id << " has changed from \"" << short_name << "\" to \""
<< sticker_set->short_name << "\"";
}
if (sticker_set->sticker_count != sticker_count || sticker_set->hash != hash) {
sticker_set->is_loaded = false;
}
if (sticker_set->is_animated != is_animated) {
LOG(ERROR) << "Is animated of " << sticker_set_id << " has changed from \"" << is_animated << "\" to \""
LOG(ERROR) << "Is animated of " << sticker_set->id << " has changed from \"" << is_animated << "\" to \""
<< sticker_set->is_animated << "\"";
}
if (sticker_set->is_masks != is_masks) {
LOG(ERROR) << "Is masks of " << sticker_set_id << " has changed from \"" << is_masks << "\" to \""
LOG(ERROR) << "Is masks of " << sticker_set->id << " has changed from \"" << is_masks << "\" to \""
<< sticker_set->is_masks << "\"";
}
}

View File

@ -80,6 +80,7 @@
#include "td/telegram/StickersManager.h"
#include "td/telegram/StorageManager.h"
#include "td/telegram/TdDb.h"
#include "td/telegram/TopDialogCategory.h"
#include "td/telegram/TopDialogManager.h"
#include "td/telegram/UpdatesManager.h"
#include "td/telegram/VideoNotesManager.h"
@ -4407,7 +4408,7 @@ Status Td::init(DbKey key) {
// that RequestKey was already sent.
//
// 3. During replay of binlog some queries may be sent to other actors. They shouldn't process such events before all
// their binlog events are processed. So actor may receive some old queries. It must be in it's actual state in
// their binlog events are processed. So actor may receive some old queries. It must be in its actual state in
// orded to handle them properly.
//
// -- Use send_closure_later, so actors don't even start process binlog events, before all binlog events are sent

View File

@ -0,0 +1,48 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/td_api.h"
#include "td/utils/common.h"
namespace td {
enum class TopDialogCategory : int32 {
Correspondent,
BotPM,
BotInline,
Group,
Channel,
Call,
ForwardUsers,
ForwardChats,
Size
};
inline TopDialogCategory top_dialog_category_from_td_api(const td_api::TopChatCategory &category) {
switch (category.get_id()) {
case td_api::topChatCategoryUsers::ID:
return TopDialogCategory::Correspondent;
case td_api::topChatCategoryBots::ID:
return TopDialogCategory::BotPM;
case td_api::topChatCategoryInlineBots::ID:
return TopDialogCategory::BotInline;
case td_api::topChatCategoryGroups::ID:
return TopDialogCategory::Group;
case td_api::topChatCategoryChannels::ID:
return TopDialogCategory::Channel;
case td_api::topChatCategoryCalls::ID:
return TopDialogCategory::Call;
case td_api::topChatCategoryForwardChats::ID:
return TopDialogCategory::ForwardUsers;
default:
UNREACHABLE();
}
}
} // namespace td

View File

@ -9,11 +9,10 @@
#include "td/actor/actor.h"
#include "td/actor/PromiseFuture.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/telegram/DialogId.h"
#include "td/telegram/net/NetQuery.h"
#include "td/telegram/telegram_api.h"
#include "td/telegram/TopDialogCategory.h"
#include "td/utils/common.h"
#include "td/utils/Time.h"
@ -23,39 +22,6 @@
namespace td {
enum class TopDialogCategory : int32 {
Correspondent,
BotPM,
BotInline,
Group,
Channel,
Call,
ForwardUsers,
ForwardChats,
Size
};
inline TopDialogCategory top_dialog_category_from_td_api(const td_api::TopChatCategory &category) {
switch (category.get_id()) {
case td_api::topChatCategoryUsers::ID:
return TopDialogCategory::Correspondent;
case td_api::topChatCategoryBots::ID:
return TopDialogCategory::BotPM;
case td_api::topChatCategoryInlineBots::ID:
return TopDialogCategory::BotInline;
case td_api::topChatCategoryGroups::ID:
return TopDialogCategory::Group;
case td_api::topChatCategoryChannels::ID:
return TopDialogCategory::Channel;
case td_api::topChatCategoryCalls::ID:
return TopDialogCategory::Call;
case td_api::topChatCategoryForwardChats::ID:
return TopDialogCategory::ForwardUsers;
default:
UNREACHABLE();
}
}
class TopDialogManager : public NetQueryCallback {
public:
explicit TopDialogManager(ActorShared<> parent) : parent_(std::move(parent)) {

View File

@ -10,7 +10,6 @@
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/telegram/AuthManager.h"
#include "td/telegram/files/FileManager.h"
#include "td/telegram/Td.h"

View File

@ -10,6 +10,7 @@
#include "td/telegram/AnimationsManager.h"
#include "td/telegram/AudiosManager.h"
#include "td/telegram/AuthManager.h"
#include "td/telegram/Document.h"
#include "td/telegram/Document.hpp"
#include "td/telegram/DocumentsManager.h"
@ -361,6 +362,16 @@ class WebPagesManager::WebPage {
instant_view.is_v2 = true;
}
}
friend bool operator==(const WebPage &lhs, const WebPage &rhs) {
return lhs.url == rhs.url && lhs.display_url == rhs.display_url && lhs.type == rhs.type &&
lhs.site_name == rhs.site_name && lhs.title == rhs.title && lhs.description == rhs.description &&
lhs.photo == rhs.photo && lhs.type == rhs.type && lhs.embed_url == rhs.embed_url &&
lhs.embed_type == rhs.embed_type && lhs.embed_dimensions == rhs.embed_dimensions &&
lhs.duration == rhs.duration && lhs.author == rhs.author && lhs.document == rhs.document &&
lhs.documents == rhs.documents && lhs.instant_view.is_empty == rhs.instant_view.is_empty &&
lhs.instant_view.is_v2 == rhs.instant_view.is_v2;
}
};
WebPagesManager::WebPagesManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::move(parent)) {
@ -402,20 +413,10 @@ WebPageId WebPagesManager::on_get_web_page(tl_object_ptr<telegram_api::WebPage>
web_pages_.erase(web_page_id);
}
update_messages_content(web_page_id, false);
if (!G()->parameters().use_message_db) {
// update_messages_content(web_page_id, false);
} else {
on_web_page_changed(web_page_id, false);
if (G()->parameters().use_message_db) {
LOG(INFO) << "Delete " << web_page_id << " from database";
G()->td_db()->get_sqlite_pmc()->erase(get_web_page_database_key(web_page_id), Auto()
/*
PromiseCreator::lambda([web_page_id](Result<> result) {
if (result.is_ok()) {
send_closure(G()->web_pages_manager(), &WebPagesManager::update_messages_content, web_page_id, false);
}
})
*/
);
G()->td_db()->get_sqlite_pmc()->erase(get_web_page_database_key(web_page_id), Auto());
G()->td_db()->get_sqlite_pmc()->erase(get_web_page_instant_view_database_key(web_page_id), Auto());
}
@ -518,7 +519,12 @@ void WebPagesManager::update_web_page(unique_ptr<WebPage> web_page, WebPageId we
auto &page = web_pages_[web_page_id];
auto old_file_ids = get_web_page_file_ids(page.get());
WebPageInstantView old_instant_view;
bool is_changed = true;
if (page != nullptr) {
if (*page == *web_page) {
is_changed = false;
}
old_instant_view = std::move(page->instant_view);
web_page->logevent_id = page->logevent_id;
} else {
@ -540,9 +546,9 @@ void WebPagesManager::update_web_page(unique_ptr<WebPage> web_page, WebPageId we
on_get_web_page_by_url(page->url, web_page_id, from_database);
update_messages_content(web_page_id, true);
if (is_changed && !from_database) {
on_web_page_changed(web_page_id, true);
if (!from_database) {
save_web_page(page.get(), web_page_id, from_binlog);
}
}
@ -626,15 +632,17 @@ bool WebPagesManager::need_use_old_instant_view(const WebPageInstantView &new_in
}
void WebPagesManager::on_get_web_page_by_url(const string &url, WebPageId web_page_id, bool from_database) {
auto &cached_web_page_id = url_to_web_page_id_[url];
if (!from_database && G()->parameters().use_message_db) {
if (web_page_id.is_valid()) {
G()->td_db()->get_sqlite_pmc()->set(get_web_page_url_database_key(url), to_string(web_page_id.get()), Auto());
if (cached_web_page_id != web_page_id) { //not already saved
G()->td_db()->get_sqlite_pmc()->set(get_web_page_url_database_key(url), to_string(web_page_id.get()), Auto());
}
} else {
G()->td_db()->get_sqlite_pmc()->erase(get_web_page_url_database_key(url), Auto());
}
}
auto &cached_web_page_id = url_to_web_page_id_[url];
if (cached_web_page_id.is_valid() && web_page_id.is_valid() && web_page_id != cached_web_page_id) {
LOG(ERROR) << "Url \"" << url << "\" preview is changed from " << cached_web_page_id << " to " << web_page_id;
}
@ -642,10 +650,37 @@ void WebPagesManager::on_get_web_page_by_url(const string &url, WebPageId web_pa
cached_web_page_id = web_page_id;
}
void WebPagesManager::wait_for_pending_web_page(FullMessageId full_message_id, WebPageId web_page_id) {
LOG(INFO) << "Waiting for " << web_page_id << " needed in " << full_message_id;
pending_web_pages_[web_page_id].emplace(full_message_id);
pending_web_pages_timeout_.add_timeout_in(web_page_id.get(), 1.0);
void WebPagesManager::register_web_page(WebPageId web_page_id, FullMessageId full_message_id) {
if (!web_page_id.is_valid()) {
return;
}
LOG(INFO) << "Register " << web_page_id << " from " << full_message_id;
bool is_inserted = web_page_messages_[web_page_id].insert(full_message_id).second;
CHECK(is_inserted);
if (!td_->auth_manager_->is_bot() && !have_web_page_force(web_page_id)) {
LOG(INFO) << "Waiting for " << web_page_id << " needed in " << full_message_id;
pending_web_pages_timeout_.add_timeout_in(web_page_id.get(), 1.0);
}
}
void WebPagesManager::unregister_web_page(WebPageId web_page_id, FullMessageId full_message_id) {
if (!web_page_id.is_valid()) {
return;
}
LOG(INFO) << "Unregister " << web_page_id << " from " << full_message_id;
auto &message_ids = web_page_messages_[web_page_id];
auto is_deleted = message_ids.erase(full_message_id);
CHECK(is_deleted);
if (message_ids.empty()) {
web_page_messages_.erase(web_page_id);
if (pending_get_web_pages_.count(web_page_id) == 0) {
pending_web_pages_timeout_.cancel_timeout(web_page_id.get());
}
}
}
void WebPagesManager::on_get_web_page_preview_success(int64 request_id, const string &url,
@ -672,7 +707,6 @@ void WebPagesManager::on_get_web_page_preview_success(int64 request_id, const st
if (web_page_id.is_valid() && !have_web_page(web_page_id)) {
pending_get_web_pages_[web_page_id].emplace(request_id,
std::make_pair(url, std::move(promise))); // TODO MultiPromise ?
pending_web_pages_timeout_.add_timeout_in(web_page_id.get(), 1.0);
return;
}
@ -1142,15 +1176,26 @@ tl_object_ptr<td_api::webPageInstantView> WebPagesManager::get_web_page_instant_
web_page_instant_view->is_rtl, web_page_instant_view->is_full);
}
void WebPagesManager::update_messages_content(WebPageId web_page_id, bool have_web_page) {
LOG(INFO) << "Update messages awaiting " << web_page_id;
auto it = pending_web_pages_.find(web_page_id);
if (it != pending_web_pages_.end()) {
auto full_message_ids = std::move(it->second);
pending_web_pages_.erase(it);
void WebPagesManager::on_web_page_changed(WebPageId web_page_id, bool have_web_page) {
LOG(INFO) << "Updated " << web_page_id;
auto it = web_page_messages_.find(web_page_id);
if (it != web_page_messages_.end()) {
vector<FullMessageId> full_message_ids;
for (auto full_message_id : it->second) {
full_message_ids.push_back(full_message_id);
}
CHECK(!full_message_ids.empty());
for (auto full_message_id : full_message_ids) {
send_closure_later(G()->messages_manager(), &MessagesManager::on_update_message_web_page, full_message_id,
have_web_page);
if (!have_web_page) {
td_->messages_manager_->delete_pending_message_web_page(full_message_id);
} else {
td_->messages_manager_->on_external_update_message_content(full_message_id);
}
}
if (have_web_page) {
CHECK(web_page_messages_[web_page_id].size() == full_message_ids.size());
} else {
CHECK(web_page_messages_.count(web_page_id) == 0);
}
}
auto get_it = pending_get_web_pages_.find(web_page_id);
@ -1187,9 +1232,13 @@ void WebPagesManager::on_pending_web_page_timeout_callback(void *web_pages_manag
}
void WebPagesManager::on_pending_web_page_timeout(WebPageId web_page_id) {
if (have_web_page(web_page_id)) {
return;
}
int32 count = 0;
auto it = pending_web_pages_.find(web_page_id);
if (it != pending_web_pages_.end()) {
auto it = web_page_messages_.find(web_page_id);
if (it != web_page_messages_.end()) {
vector<FullMessageId> full_message_ids;
for (auto full_message_id : it->second) {
full_message_ids.push_back(full_message_id);
@ -1209,7 +1258,7 @@ void WebPagesManager::on_pending_web_page_timeout(WebPageId web_page_id) {
}
}
if (count == 0) {
LOG(WARNING) << "Have no messages waiting for " << web_page_id;
LOG(WARNING) << "Have no messages and requests waiting for " << web_page_id;
}
}

View File

@ -13,7 +13,7 @@
#include "td/telegram/files/FileId.h"
#include "td/telegram/files/FileSourceId.h"
#include "td/telegram/FullMessageId.h"
#include "td/telegram/Photo.h"
#include "td/telegram/SecretInputMedia.h"
#include "td/telegram/WebPageId.h"
#include "td/actor/actor.h"
@ -47,7 +47,9 @@ class WebPagesManager : public Actor {
void on_get_web_page_by_url(const string &url, WebPageId web_page_id, bool from_database);
void wait_for_pending_web_page(FullMessageId full_message_id, WebPageId web_page_id);
void register_web_page(WebPageId web_page_id, FullMessageId full_message_id);
void unregister_web_page(WebPageId web_page_id, FullMessageId full_message_id);
bool have_web_page(WebPageId web_page_id) const;
@ -111,7 +113,7 @@ class WebPagesManager : public Actor {
static bool need_use_old_instant_view(const WebPageInstantView &new_instant_view,
const WebPageInstantView &old_instant_view);
void update_messages_content(WebPageId web_page_id, bool have_web_page);
void on_web_page_changed(WebPageId web_page_id, bool have_web_page);
const WebPage *get_web_page(WebPageId web_page_id) const;
@ -181,7 +183,8 @@ class WebPagesManager : public Actor {
};
std::unordered_map<WebPageId, PendingWebPageInstantViewQueries, WebPageIdHash> load_web_page_instant_view_queries_;
std::unordered_map<WebPageId, std::unordered_set<FullMessageId, FullMessageIdHash>, WebPageIdHash> pending_web_pages_;
std::unordered_map<WebPageId, std::unordered_set<FullMessageId, FullMessageIdHash>, WebPageIdHash> web_page_messages_;
std::unordered_map<WebPageId, std::unordered_map<int64, std::pair<string, Promise<Unit>>>, WebPageIdHash>
pending_get_web_pages_;

View File

@ -3522,7 +3522,8 @@ void FileManager::on_error_impl(FileNodePtr node, Query::Type type, bool was_act
node->set_generate_location(nullptr);
}
if (status.message() == "FILE_ID_INVALID" && FileView(node).may_reload_photo()) {
if ((status.message() == "FILE_ID_INVALID" || status.message() == "LOCATION_INVALID") &&
FileView(node).may_reload_photo()) {
node->need_reload_photo_ = true;
run_download(node);
return;

View File

@ -17,6 +17,9 @@ Result<Proxy> Proxy::from_td_api(string server, int port, td_api::ProxyType *pro
if (server.empty()) {
return Status::Error(400, "Server name can't be empty");
}
if (server.size() > 255) {
return Status::Error(400, "Server name is too long");
}
if (port <= 0 || port > 65535) {
return Status::Error(400, "Wrong port number");
}

View File

@ -134,7 +134,7 @@ class Proxy {
} else if (type_ == Proxy::Type::Mtproto) {
parse(server_, parser);
parse(port_, parser);
secret_ = mtproto::ProxySecret::from_link(parser.template fetch_string<Slice>()).move_as_ok();
secret_ = mtproto::ProxySecret::from_link(parser.template fetch_string<Slice>(), true).move_as_ok();
} else {
CHECK(type_ == Proxy::Type::None);
}

View File

@ -1,5 +1,9 @@
cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR)
if (NOT DEFINED CMAKE_INSTALL_LIBDIR)
set(CMAKE_INSTALL_LIBDIR "lib")
endif()
#SOURCE SETS
set(TDACTOR_SOURCE
td/actor/impl/ConcurrentScheduler.cpp
@ -50,8 +54,6 @@ if (NOT CMAKE_CROSSCOMPILING)
endif()
install(TARGETS tdactor EXPORT TdTargets
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin
INCLUDES DESTINATION include
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
)

View File

@ -1,5 +1,9 @@
cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR)
if (NOT DEFINED CMAKE_INSTALL_LIBDIR)
set(CMAKE_INSTALL_LIBDIR "lib")
endif()
#SOURCE SETS
set(TDDB_SOURCE
td/db/binlog/Binlog.cpp
@ -50,8 +54,6 @@ if (NOT CMAKE_CROSSCOMPILING)
endif()
install(TARGETS tddb EXPORT TdTargets
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin
INCLUDES DESTINATION include
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
)

View File

@ -159,8 +159,8 @@ Status SqliteDb::commit_transaction() {
return Status::OK();
}
bool SqliteDb::is_encrypted() {
return true;
Status SqliteDb::check_encryption() {
return Status::OK();
}
Result<SqliteDb> SqliteDb::open_with_key(CSlice path, const DbKey &db_key) {

View File

@ -81,7 +81,7 @@ class SqliteDb {
}
std::shared_ptr<detail::RawSqliteDb> raw_;
bool is_encrypted();
Status check_encryption();
};
} // namespace td

View File

@ -1,5 +1,9 @@
cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR)
if (NOT DEFINED CMAKE_INSTALL_LIBDIR)
set(CMAKE_INSTALL_LIBDIR "lib")
endif()
if (NOT OPENSSL_FOUND)
find_package(OpenSSL REQUIRED)
find_package(ZLIB REQUIRED)
@ -59,8 +63,6 @@ if (WIN32)
endif()
install(TARGETS tdnet EXPORT TdTargets
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin
INCLUDES DESTINATION include
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
)

View File

@ -53,8 +53,8 @@ class GoogleDnsResolver : public Actor {
});
wget_ = create_actor<Wget>(
"GoogleDnsResolver", std::move(wget_promise),
PSTRING() << "https://www.google.com/resolve?name=" << url_encode(host_) << "&type=" << (prefer_ipv6_ ? 28 : 1),
std::vector<std::pair<string, string>>({{"Host", "dns.google.com"}}), timeout, ttl, prefer_ipv6_,
PSTRING() << "https://dns.google/resolve?name=" << url_encode(host_) << "&type=" << (prefer_ipv6_ ? 28 : 1),
std::vector<std::pair<string, string>>({{"Host", "dns.google"}}), timeout, ttl, prefer_ipv6_,
SslStream::VerifyPeer::Off);
}

View File

@ -1,5 +1,9 @@
cmake_minimum_required(VERSION 3.0.2 FATAL_ERROR)
if (NOT DEFINED CMAKE_INSTALL_LIBDIR)
set(CMAKE_INSTALL_LIBDIR "lib")
endif()
if (WIN32)
if (WINGETOPT_FOUND)
set(TD_HAVE_GETOPT 1)
@ -326,8 +330,6 @@ if (CMAKE_HOST_SYSTEM_NAME MATCHES "NetBSD")
endif()
install(TARGETS tdutils EXPORT TdTargets
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin
INCLUDES DESTINATION include
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
)