Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package telegram-desktop for 
openSUSE:Factory checked in at 2026-04-02 17:41:26
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/telegram-desktop (Old)
 and      /work/SRC/openSUSE:Factory/.telegram-desktop.new.21863 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "telegram-desktop"

Thu Apr  2 17:41:26 2026 rev:148 rq:1344244 version:6.7.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/telegram-desktop/telegram-desktop.changes        
2026-03-13 21:21:13.976302920 +0100
+++ 
/work/SRC/openSUSE:Factory/.telegram-desktop.new.21863/telegram-desktop.changes 
    2026-04-02 17:42:41.687144530 +0200
@@ -1,0 +2,8 @@
+Wed Apr  1 23:57:12 UTC 2026 - Илья Индиго <[email protected]>
+
+- Updated ada to 3.4.4.
+- Updated td to git20260317.
+- Updated telegram-desktop to 6.7.1
+  * https://github.com/telegramdesktop/tdesktop/releases/tag/v6.7.1
+
+-------------------------------------------------------------------

Old:
----
  ada-3.4.3.tar.gz
  td-git20260303.tar.xz
  tdesktop-6.6.3-full.tar.gz

New:
----
  ada-3.4.4.tar.gz
  td-git20260317.tar.xz
  tdesktop-6.7.1-full.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ telegram-desktop.spec ++++++
--- /var/tmp/diff_new_pack.Sv3DHa/_old  2026-04-02 17:42:42.987198222 +0200
+++ /var/tmp/diff_new_pack.Sv3DHa/_new  2026-04-02 17:42:42.991198388 +0200
@@ -20,12 +20,12 @@
 # 
https://github.com/telegramdesktop/tdesktop/blob/8fab9167beb2407c1153930ed03a4badd0c2b59f/snap/snapcraft.yaml#L87-L88
 %define api_id    611335
 %define api_hash  d524b414d21f4d37f08684c1df41ac9c
-%define ada_ver   3.4.3
+%define ada_ver   3.4.4
 %define h264_ver  2.6.0
 %define owt_ver   git20260123
-%define td_ver    git20260303
+%define td_ver    git20260317
 Name:           telegram-desktop
-Version:        6.6.3
+Version:        6.7.1
 Release:        0
 Summary:        Messaging application with a focus on speed and security
 License:        GPL-3.0-only

++++++ ada-3.4.3.tar.gz -> ada-3.4.4.tar.gz ++++++
++++ 2711 lines of diff (skipped)

++++++ td-git20260303.tar.xz -> td-git20260317.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/td-git20260303/CMakeLists.txt 
new/td-git20260317/CMakeLists.txt
--- old/td-git20260303/CMakeLists.txt   2026-03-13 07:45:04.531682152 +0100
+++ new/td-git20260317/CMakeLists.txt   2026-04-01 14:40:57.133198682 +0200
@@ -496,6 +496,7 @@
   td/telegram/MessageContent.cpp
   td/telegram/MessageContentType.cpp
   td/telegram/MessageCopyOptions.cpp
+  td/telegram/MessageCover.cpp
   td/telegram/MessageDb.cpp
   td/telegram/MessageEntity.cpp
   td/telegram/MessageExtendedMedia.cpp
@@ -540,6 +541,7 @@
   td/telegram/net/NetQueryVerifier.cpp
   td/telegram/net/NetStatsManager.cpp
   td/telegram/net/Proxy.cpp
+  td/telegram/net/ProxyChecker.cpp
   td/telegram/net/PublicRsaKeySharedCdn.cpp
   td/telegram/net/PublicRsaKeySharedMain.cpp
   td/telegram/net/PublicRsaKeyWatchdog.cpp
@@ -879,6 +881,7 @@
   td/telegram/MessageContent.h
   td/telegram/MessageContentType.h
   td/telegram/MessageCopyOptions.h
+  td/telegram/MessageCover.h
   td/telegram/MessageDb.h
   td/telegram/MessageEffectId.h
   td/telegram/MessageEntity.h
@@ -931,6 +934,7 @@
   td/telegram/net/NetStatsManager.h
   td/telegram/net/NetType.h
   td/telegram/net/Proxy.h
+  td/telegram/net/ProxyChecker.h
   td/telegram/net/PublicRsaKeySharedCdn.h
   td/telegram/net/PublicRsaKeySharedMain.h
   td/telegram/net/PublicRsaKeyWatchdog.h
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/td-git20260303/SplitSource.php 
new/td-git20260317/SplitSource.php
--- old/td-git20260303/SplitSource.php  2026-03-13 07:45:04.531766967 +0100
+++ new/td-git20260317/SplitSource.php  2026-04-01 14:40:57.133198682 +0200
@@ -375,6 +375,7 @@
             'link_manager[_(-](?![.]get[(][)])|LinkManager' => 'LinkManager',
             
'LogeventIdWithGeneration|add_log_event|delete_log_event|get_erase_log_event_promise|parse_time|store_time'
 => 'logevent/LogEventHelper',
             'MessageCopyOptions' => 'MessageCopyOptions',
+            'MessageCover' => 'MessageCover',
             'MessageEffectId' => 'MessageEffectId',
             'MessageForwardInfo|LastForwardedMessageInfo|forward_info' => 
'MessageForwardInfo',
             'MessageFullId' => 'MessageFullId',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/td-git20260303/td/telegram/BusinessConnectionManager.cpp 
new/td-git20260317/td/telegram/BusinessConnectionManager.cpp
--- old/td-git20260303/td/telegram/BusinessConnectionManager.cpp        
2026-03-13 07:45:04.569765648 +0100
+++ new/td-git20260317/td/telegram/BusinessConnectionManager.cpp        
2026-04-01 14:40:57.171109899 +0200
@@ -19,6 +19,7 @@
 #include "td/telegram/MessageContent.h"
 #include "td/telegram/MessageContentType.h"
 #include "td/telegram/MessageCopyOptions.h"
+#include "td/telegram/MessageCover.h"
 #include "td/telegram/MessageEntity.h"
 #include "td/telegram/MessageId.h"
 #include "td/telegram/MessageQueryManager.h"
@@ -1541,7 +1542,7 @@
                                                       bool 
disable_notification, bool protect_content,
                                                       MessageEffectId 
effect_id,
                                                       
vector<InputMessageContent> &&message_contents) {
-  vector<const Photo *> covers;
+  vector<MessageCover> covers;
   for (auto &content : message_contents) {
     append(covers, get_message_content_need_to_upload_covers(td_, 
content.content.get()));
   }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/td-git20260303/td/telegram/DraftMessage.cpp 
new/td-git20260317/td/telegram/DraftMessage.cpp
--- old/td-git20260303/td/telegram/DraftMessage.cpp     2026-03-13 
07:45:04.574765475 +0100
+++ new/td-git20260317/td/telegram/DraftMessage.cpp     2026-04-01 
14:40:57.177109659 +0200
@@ -51,10 +51,7 @@
     bool invert_media = false;
     if (draft_message != nullptr) {
       CHECK(!draft_message->is_local());
-      input_reply_to = 
draft_message->message_input_reply_to_.get_input_reply_to(td_, message_topic);
-      if (input_reply_to != nullptr) {
-        flags |= telegram_api::messages_saveDraft::REPLY_TO_MASK;
-      }
+      input_reply_to = 
draft_message->message_input_reply_to_.get_input_reply_to(td_, message_topic, 
true);
       if (draft_message->input_message_text_.disable_web_page_preview) {
         disable_web_page_preview = true;
       } else if (draft_message->input_message_text_.show_above_text) {
@@ -77,6 +74,11 @@
         flags |= telegram_api::messages_saveDraft::SUGGESTED_POST_MASK;
         suggested_post = 
draft_message->suggested_post_->get_input_suggested_post();
       }
+    } else {
+      input_reply_to = MessageInputReplyTo().get_input_reply_to(td_, 
message_topic, true);
+    }
+    if (input_reply_to != nullptr) {
+      flags |= telegram_api::messages_saveDraft::REPLY_TO_MASK;
     }
     send_query(G()->net_query_creator().create(
         telegram_api::messages_saveDraft(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/td-git20260303/td/telegram/GroupCallMessage.cpp 
new/td-git20260317/td/telegram/GroupCallMessage.cpp
--- old/td-git20260303/td/telegram/GroupCallMessage.cpp 2026-03-13 
07:45:04.576765405 +0100
+++ new/td-git20260317/td/telegram/GroupCallMessage.cpp 2026-04-01 
14:40:57.179109579 +0200
@@ -17,6 +17,7 @@
 #include "td/telegram/UserManager.h"
 #include "td/telegram/Version.h"
 
+#include "td/utils/algorithm.h"
 #include "td/utils/JsonBuilder.h"
 #include "td/utils/logging.h"
 #include "td/utils/Random.h"
@@ -38,7 +39,7 @@
   if (type == "messageEntityUnknown" || type == "messageEntityMention" || type 
== "messageEntityHashtag" ||
       type == "messageEntityCashtag" || type == "messageEntityPhone" || type 
== "messageEntityBotCommand" ||
       type == "messageEntityBankCard" || type == "messageEntityUrl" || type == 
"messageEntityEmail" ||
-      type == "messageEntityMentionName" || min_layer > MTPROTO_LAYER) {
+      type == "messageEntityMentionName" || type == 
"messageEntityFormattedDate" || min_layer > MTPROTO_LAYER) {
     return Status::Error("Skip");
   }
   if (type == "messageEntityPre") {
@@ -202,6 +203,7 @@
     , paid_message_star_count_(paid_message_star_count)
     , from_admin_(from_admin)
     , is_local_(true) {
+  td::remove_if(text.entities, [](auto &entity) { return entity.type == 
MessageEntity::Type::FormattedDate; });
 }
 
 string GroupCallMessage::encode_to_json() const {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/td-git20260303/td/telegram/MessageContent.cpp 
new/td-git20260317/td/telegram/MessageContent.cpp
--- old/td-git20260303/td/telegram/MessageContent.cpp   2026-03-13 
07:45:04.579765301 +0100
+++ new/td-git20260317/td/telegram/MessageContent.cpp   2026-04-01 
14:40:57.181109499 +0200
@@ -11164,32 +11164,32 @@
   }
 }
 
-const Photo *get_message_content_cover(const MessageContent *content) {
+bool has_message_content_cover(const MessageContent *content) {
   switch (content->get_type()) {
     case MessageContentType::Video: {
       const auto *cover = &static_cast<const MessageVideo *>(content)->cover;
       if (cover->is_empty()) {
-        return nullptr;
+        return false;
       }
-      return cover;
+      return true;
     }
     default:
-      return nullptr;
+      return false;
   }
 }
 
-vector<const Photo *> get_message_content_need_to_upload_covers(Td *td, const 
MessageContent *content) {
+vector<MessageCover> get_message_content_need_to_upload_covers(Td *td, const 
MessageContent *content) {
   switch (content->get_type()) {
     case MessageContentType::Video: {
-      const auto *cover = &static_cast<const MessageVideo *>(content)->cover;
-      if (cover->is_empty() ||
-          photo_get_cover_input_media(td->file_manager_.get(), *cover, 
td->auth_manager_->is_bot(), false) != nullptr) {
+      const auto &cover = static_cast<const MessageVideo *>(content)->cover;
+      if (cover.is_empty() ||
+          photo_get_cover_input_media(td->file_manager_.get(), cover, 
td->auth_manager_->is_bot(), false) != nullptr) {
         break;
       }
-      return {cover};
+      return {MessageCover(cover)};
     }
     case MessageContentType::PaidMedia: {
-      vector<const Photo *> result;
+      vector<MessageCover> result;
       for (const auto &media : static_cast<const MessagePaidMedia 
*>(content)->media) {
         const auto *cover = media.get_video_cover();
         if (cover == nullptr || cover->is_empty() ||
@@ -11197,7 +11197,7 @@
                 nullptr) {
           continue;
         }
-        result.push_back(cover);
+        result.emplace_back(*cover);
       }
       return result;
     }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/td-git20260303/td/telegram/MessageContent.h 
new/td-git20260317/td/telegram/MessageContent.h
--- old/td-git20260303/td/telegram/MessageContent.h     2026-03-13 
07:45:04.579765301 +0100
+++ new/td-git20260317/td/telegram/MessageContent.h     2026-04-01 
14:40:57.182109458 +0200
@@ -18,6 +18,7 @@
 #include "td/telegram/logevent/LogEvent.h"
 #include "td/telegram/MessageContentType.h"
 #include "td/telegram/MessageCopyOptions.h"
+#include "td/telegram/MessageCover.h"
 #include "td/telegram/MessageEntity.h"
 #include "td/telegram/MessageFullId.h"
 #include "td/telegram/MessageId.h"
@@ -302,9 +303,9 @@
 
 int32 get_message_content_media_duration(const MessageContent *content, const 
Td *td);
 
-const Photo *get_message_content_cover(const MessageContent *content);
+bool has_message_content_cover(const MessageContent *content);
 
-vector<const Photo *> get_message_content_need_to_upload_covers(Td *td, const 
MessageContent *content);
+vector<MessageCover> get_message_content_need_to_upload_covers(Td *td, const 
MessageContent *content);
 
 FileId get_message_content_any_file_id(const MessageContent *content);
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/td-git20260303/td/telegram/MessageCover.cpp 
new/td-git20260317/td/telegram/MessageCover.cpp
--- old/td-git20260303/td/telegram/MessageCover.cpp     1970-01-01 
01:00:00.000000000 +0100
+++ new/td-git20260317/td/telegram/MessageCover.cpp     2026-04-01 
14:40:57.182109458 +0200
@@ -0,0 +1,77 @@
+//
+// Copyright Aliaksei Levin ([email protected]), Arseny Smirnov 
([email protected]) 2014-2026
+//
+// 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/MessageCover.h"
+
+#include "td/telegram/Td.h"
+
+namespace td {
+
+FileId MessageCover::get_any_file_id() const {
+  switch (type_) {
+    case Type::Empty:
+      return FileId();
+    case Type::Photo:
+      return get_photo_any_file_id(photo_);
+    default:
+      UNREACHABLE();
+      return FileId();
+  }
+}
+
+telegram_api::object_ptr<telegram_api::InputMedia> 
MessageCover::get_cover_input_media(Td *td, bool force,
+                                                                               
        bool allow_external) const {
+  switch (type_) {
+    case Type::Photo:
+      return photo_get_cover_input_media(td->file_manager_.get(), photo_, 
force, allow_external);
+    case Type::Empty:
+    default:
+      UNREACHABLE();
+      return nullptr;
+  }
+}
+
+telegram_api::object_ptr<telegram_api::InputMedia> 
MessageCover::get_input_media(
+    Td *td, telegram_api::object_ptr<telegram_api::InputFile> &&input_file) {
+  switch (type_) {
+    case Type::Photo:
+      return photo_get_input_media(td->file_manager_.get(), photo_, 
std::move(input_file), 0, false);
+    case Type::Empty:
+    default:
+      UNREACHABLE();
+      return nullptr;
+  }
+}
+
+Status MessageCover::merge_with_media(Td *td, DialogId owner_dialog_id,
+                                      
telegram_api::object_ptr<telegram_api::MessageMedia> &&media_ptr) {
+  switch (type_) {
+    case Type::Photo: {
+      if (media_ptr->get_id() != telegram_api::messageMediaPhoto::ID) {
+        return Status::Error(500, "Receive invalid response");
+      }
+      auto media = 
telegram_api::move_object_as<telegram_api::messageMediaPhoto>(media_ptr);
+      if (media->photo_ == nullptr || media->ttl_seconds_ != 0) {
+        return Status::Error(500, "Receive invalid response without photo");
+      }
+      auto new_photo = get_photo(td, std::move(media->photo_), 
owner_dialog_id, FileType::Photo);
+      if (new_photo.is_empty()) {
+        return Status::Error(500, "Receive invalid photo in response");
+      }
+      bool is_content_changed = false;
+      bool need_update = false;
+      merge_photos(td, &photo_, &new_photo, owner_dialog_id, true, 
is_content_changed, need_update);
+      break;
+    }
+    case Type::Empty:
+    default:
+      UNREACHABLE();
+      break;
+  }
+  return Status::OK();
+}
+
+}  // namespace td
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/td-git20260303/td/telegram/MessageCover.h 
new/td-git20260317/td/telegram/MessageCover.h
--- old/td-git20260303/td/telegram/MessageCover.h       1970-01-01 
01:00:00.000000000 +0100
+++ new/td-git20260317/td/telegram/MessageCover.h       2026-04-01 
14:40:57.182109458 +0200
@@ -0,0 +1,48 @@
+//
+// Copyright Aliaksei Levin ([email protected]), Arseny Smirnov 
([email protected]) 2014-2026
+//
+// 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/DialogId.h"
+#include "td/telegram/files/FileId.h"
+#include "td/telegram/Photo.h"
+#include "td/telegram/telegram_api.h"
+
+#include "td/utils/common.h"
+#include "td/utils/Status.h"
+
+namespace td {
+
+class Td;
+
+class MessageCover {
+  enum class Type : int32 { Empty, Photo };
+  Type type_ = Type::Empty;
+  Photo photo_;
+
+ public:
+  MessageCover() = default;
+
+  explicit MessageCover(const Photo &photo) : type_(Type::Photo), 
photo_(photo) {
+  }
+
+  bool is_empty() const {
+    return type_ == Type::Empty;
+  }
+
+  FileId get_any_file_id() const;
+
+  telegram_api::object_ptr<telegram_api::InputMedia> get_cover_input_media(Td 
*td, bool force,
+                                                                           
bool allow_external) const;
+
+  telegram_api::object_ptr<telegram_api::InputMedia> get_input_media(
+      Td *td, telegram_api::object_ptr<telegram_api::InputFile> &&input_file);
+
+  Status merge_with_media(Td *td, DialogId owner_dialog_id,
+                          telegram_api::object_ptr<telegram_api::MessageMedia> 
&&media_ptr);
+};
+
+}  // namespace td
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/td-git20260303/td/telegram/MessageEntity.cpp 
new/td-git20260317/td/telegram/MessageEntity.cpp
--- old/td-git20260303/td/telegram/MessageEntity.cpp    2026-03-13 
07:45:04.579765301 +0100
+++ new/td-git20260317/td/telegram/MessageEntity.cpp    2026-04-01 
14:40:57.182109458 +0200
@@ -1775,6 +1775,25 @@
   }
 }
 
+bool is_found_entity_type(MessageEntity::Type type, bool skip_bot_commands, 
bool skip_media_timestamps) {
+  switch (type) {
+    case MessageEntity::Type::Mention:
+    case MessageEntity::Type::Hashtag:
+    case MessageEntity::Type::Cashtag:
+    case MessageEntity::Type::PhoneNumber:
+    case MessageEntity::Type::BankCardNumber:
+    case MessageEntity::Type::Url:
+    case MessageEntity::Type::EmailAddress:
+      return true;
+    case MessageEntity::Type::BotCommand:
+      return !skip_bot_commands;
+    case MessageEntity::Type::MediaTimestamp:
+      return !skip_media_timestamps;
+    default:
+      return false;
+  }
+}
+
 vector<MessageEntity> find_entities(Slice text, bool skip_bot_commands, bool 
skip_media_timestamps) {
   vector<MessageEntity> entities;
 
@@ -4941,9 +4960,23 @@
   return {};
 }
 
+bool is_allowed_quote_entity_type(MessageEntity::Type type) {
+  switch (type) {
+    case MessageEntity::Type::Bold:
+    case MessageEntity::Type::Italic:
+    case MessageEntity::Type::Underline:
+    case MessageEntity::Type::Strikethrough:
+    case MessageEntity::Type::Spoiler:
+    case MessageEntity::Type::CustomEmoji:
+      return true;
+    default:
+      return false;
+  }
+}
+
 bool keep_only_custom_emoji(FormattedText &text) {
   return td::remove_if(text.entities,
-                       [&](const MessageEntity &entity) { return entity.type 
!= MessageEntity::Type::CustomEmoji; });
+                       [](const MessageEntity &entity) { return entity.type != 
MessageEntity::Type::CustomEmoji; });
 }
 
 void remove_premium_custom_emoji_entities(const Td *td, vector<MessageEntity> 
&entities, bool remove_unknown) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/td-git20260303/td/telegram/MessageEntity.h 
new/td-git20260317/td/telegram/MessageEntity.h
--- old/td-git20260303/td/telegram/MessageEntity.h      2026-03-13 
07:45:04.579765301 +0100
+++ new/td-git20260317/td/telegram/MessageEntity.h      2026-04-01 
14:40:57.182109458 +0200
@@ -176,12 +176,16 @@
                                                                     const 
FormattedText &text, bool skip_bot_commands,
                                                                     int32 
max_media_timestamp);
 
+bool is_allowed_quote_entity_type(MessageEntity::Type type);
+
 bool keep_only_custom_emoji(FormattedText &text);
 
 void remove_premium_custom_emoji_entities(const Td *td, vector<MessageEntity> 
&entities, bool remove_unknown);
 
 void remove_unallowed_entities(const Td *td, FormattedText &text, DialogId 
dialog_id);
 
+bool is_found_entity_type(MessageEntity::Type type, bool skip_bot_commands, 
bool skip_media_timestamps);
+
 vector<MessageEntity> find_entities(Slice text, bool skip_bot_commands, bool 
skip_media_timestamps);
 
 vector<Slice> find_mentions(Slice str);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/td-git20260303/td/telegram/MessageInputReplyTo.cpp 
new/td-git20260317/td/telegram/MessageInputReplyTo.cpp
--- old/td-git20260303/td/telegram/MessageInputReplyTo.cpp      2026-03-13 
07:45:04.580765267 +0100
+++ new/td-git20260317/td/telegram/MessageInputReplyTo.cpp      2026-04-01 
14:40:57.183109419 +0200
@@ -77,9 +77,12 @@
 }
 
 telegram_api::object_ptr<telegram_api::InputReplyTo> 
MessageInputReplyTo::get_input_reply_to(
-    Td *td, const MessageTopic &message_topic, DialogId for_dialog_id, int32 
with_flags) const {
+    Td *td, const MessageTopic &message_topic, bool for_draft, DialogId 
for_dialog_id, int32 with_flags) const {
   if (story_full_id_.is_valid()) {
     CHECK(message_topic.is_empty());
+    if (for_draft) {
+      return nullptr;
+    }
     auto dialog_id = story_full_id_.get_dialog_id();
     auto input_peer = td->dialog_manager_->get_input_peer(dialog_id, 
AccessRights::Read);
     if (input_peer == nullptr) {
@@ -102,7 +105,9 @@
     if (message_topic.is_empty()) {
       return nullptr;
     }
-    reply_to_message_id = message_topic.get_implicit_reply_to_message_id(td);
+    if (!for_draft) {
+      reply_to_message_id = message_topic.get_implicit_reply_to_message_id(td);
+    }
   }
   int32 flags = 0;
   auto top_msg_id = message_topic.get_input_top_msg_id();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/td-git20260303/td/telegram/MessageInputReplyTo.h 
new/td-git20260317/td/telegram/MessageInputReplyTo.h
--- old/td-git20260303/td/telegram/MessageInputReplyTo.h        2026-03-13 
07:45:04.580765267 +0100
+++ new/td-git20260317/td/telegram/MessageInputReplyTo.h        2026-04-01 
14:40:57.183109419 +0200
@@ -90,6 +90,7 @@
   void add_dependencies(Dependencies &dependencies) const;
 
   telegram_api::object_ptr<telegram_api::InputReplyTo> get_input_reply_to(Td 
*td, const MessageTopic &message_topic,
+                                                                          bool 
for_draft = false,
                                                                           
DialogId for_dialog_id = DialogId(),
                                                                           
int32 with_flags = 0) const;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/td-git20260303/td/telegram/MessageQueryManager.cpp 
new/td-git20260317/td/telegram/MessageQueryManager.cpp
--- old/td-git20260303/td/telegram/MessageQueryManager.cpp      2026-03-13 
07:45:04.580765267 +0100
+++ new/td-git20260317/td/telegram/MessageQueryManager.cpp      2026-04-01 
14:40:57.184109379 +0200
@@ -70,7 +70,7 @@
   Promise<Unit> promise_;
   BusinessConnectionId business_connection_id_;
   DialogId dialog_id_;
-  Photo photo_;
+  MessageCover cover_;
   FileUploadId file_upload_id_;
   bool was_uploaded_ = false;
 
@@ -78,12 +78,12 @@
   explicit UploadCoverQuery(Promise<Unit> &&promise) : 
promise_(std::move(promise)) {
   }
 
-  void send(BusinessConnectionId business_connection_id, DialogId dialog_id, 
Photo &&photo, FileUploadId file_upload_id,
-            telegram_api::object_ptr<telegram_api::InputMedia> &&input_media) {
+  void send(BusinessConnectionId business_connection_id, DialogId dialog_id, 
MessageCover &&cover,
+            FileUploadId file_upload_id, 
telegram_api::object_ptr<telegram_api::InputMedia> &&input_media) {
     CHECK(input_media != nullptr);
     business_connection_id_ = business_connection_id;
     dialog_id_ = dialog_id;
-    photo_ = std::move(photo);
+    cover_ = std::move(cover);
     file_upload_id_ = file_upload_id;
     was_uploaded_ = FileManager::extract_was_uploaded(input_media);
 
@@ -113,7 +113,7 @@
 
     auto ptr = result_ptr.move_as_ok();
     LOG(INFO) << "Receive result for UploadCoverQuery: " << to_string(ptr);
-    
td_->message_query_manager_->complete_upload_message_cover(business_connection_id_,
 dialog_id_, std::move(photo_),
+    
td_->message_query_manager_->complete_upload_message_cover(business_connection_id_,
 dialog_id_, std::move(cover_),
                                                                
file_upload_id_, std::move(ptr), std::move(promise_));
   }
 
@@ -123,7 +123,7 @@
     if (was_uploaded_) {
       auto bad_parts = FileManager::get_missing_file_parts(status);
       if (!bad_parts.empty()) {
-        
td_->message_query_manager_->upload_message_cover(business_connection_id_, 
dialog_id_, std::move(photo_),
+        
td_->message_query_manager_->upload_message_cover(business_connection_id_, 
dialog_id_, std::move(cover_),
                                                           file_upload_id_, 
std::move(promise_), std::move(bad_parts));
         return;
       } else {
@@ -783,6 +783,8 @@
   }
 
   void on_result(BufferSlice packet) final {
+    
static_assert(std::is_same<telegram_api::messages_getSavedHistory::ReturnType,
+                               
telegram_api::messages_search::ReturnType>::value);
     auto result_ptr = fetch_result<telegram_api::messages_search>(packet);
     if (result_ptr.is_error()) {
       return on_error(result_ptr.move_as_error());
@@ -1872,32 +1874,31 @@
 }
 
 void MessageQueryManager::upload_message_covers(BusinessConnectionId 
business_connection_id, DialogId dialog_id,
-                                                vector<const Photo *> covers, 
Promise<Unit> &&promise) {
+                                                vector<MessageCover> covers, 
Promise<Unit> &&promise) {
   TRY_STATUS_PROMISE(promise, G()->close_status());
   CHECK(!covers.empty());
   MultiPromiseActorSafe mpas{"UploadMessageCoversMultiPromiseActor"};
   mpas.add_promise(std::move(promise));
   auto lock = mpas.get_promise();
-  for (const Photo *cover : covers) {
-    CHECK(cover != nullptr);
-    auto file_upload_id = FileUploadId(get_photo_any_file_id(*cover), 
FileManager::get_internal_upload_id());
-    upload_message_cover(business_connection_id, dialog_id, *cover, 
file_upload_id, mpas.get_promise());
+  for (const MessageCover &cover : covers) {
+    CHECK(!cover.is_empty());
+    auto file_upload_id = FileUploadId(cover.get_any_file_id(), 
FileManager::get_internal_upload_id());
+    upload_message_cover(business_connection_id, dialog_id, cover, 
file_upload_id, mpas.get_promise());
   }
   lock.set_value(Unit());
 }
 
 void MessageQueryManager::upload_message_cover(BusinessConnectionId 
business_connection_id, DialogId dialog_id,
-                                               Photo photo, FileUploadId 
file_upload_id, Promise<Unit> &&promise,
-                                               vector<int> bad_parts) {
+                                               MessageCover message_cover, 
FileUploadId file_upload_id,
+                                               Promise<Unit> &&promise, 
vector<int> bad_parts) {
   TRY_STATUS_PROMISE(promise, G()->close_status());
   BeingUploadedCover cover;
   cover.business_connection_id_ = business_connection_id;
   cover.dialog_id_ = dialog_id;
-  cover.photo_ = std::move(photo);
+  cover.cover_ = std::move(message_cover);
   cover.promise_ = std::move(promise);
 
-  auto input_media = photo_get_cover_input_media(td_->file_manager_.get(), 
cover.photo_,
-                                                 td_->auth_manager_->is_bot() 
&& bad_parts.empty(), true);
+  auto input_media = cover.cover_.get_cover_input_media(td_, 
td_->auth_manager_->is_bot() && bad_parts.empty(), true);
   if (input_media != nullptr && bad_parts.empty()) {
     return do_upload_cover(file_upload_id, std::move(cover));
   }
@@ -1939,39 +1940,23 @@
   bool have_input_file = input_file != nullptr;
   LOG(INFO) << "Do upload cover " << file_upload_id << ", have_input_file = " 
<< have_input_file;
 
-  auto input_media =
-      photo_get_input_media(td_->file_manager_.get(), 
being_uploaded_cover.photo_, std::move(input_file), 0, false);
+  auto input_media = being_uploaded_cover.cover_.get_input_media(td_, 
std::move(input_file));
   CHECK(input_media != nullptr);
   if (is_uploaded_input_media(input_media)) {
     return being_uploaded_cover.promise_.set_value(Unit());
   } else {
     
td_->create_handler<UploadCoverQuery>(std::move(being_uploaded_cover.promise_))
         ->send(being_uploaded_cover.business_connection_id_, 
being_uploaded_cover.dialog_id_,
-               std::move(being_uploaded_cover.photo_), file_upload_id, 
std::move(input_media));
+               std::move(being_uploaded_cover.cover_), file_upload_id, 
std::move(input_media));
   }
 }
 
 void MessageQueryManager::complete_upload_message_cover(
-    BusinessConnectionId business_connection_id, DialogId dialog_id, Photo 
photo, FileUploadId file_upload_id,
+    BusinessConnectionId business_connection_id, DialogId dialog_id, 
MessageCover cover, FileUploadId file_upload_id,
     telegram_api::object_ptr<telegram_api::MessageMedia> &&media_ptr, 
Promise<Unit> &&promise) {
   send_closure_later(G()->file_manager(), &FileManager::cancel_upload, 
file_upload_id);
-
-  if (media_ptr->get_id() != telegram_api::messageMediaPhoto::ID) {
-    return promise.set_error(500, "Receive invalid response");
-  }
-  auto media = 
telegram_api::move_object_as<telegram_api::messageMediaPhoto>(media_ptr);
-  if (media->photo_ == nullptr || media->ttl_seconds_ != 0) {
-    return promise.set_error(500, "Receive invalid response without photo");
-  }
-  auto new_photo = get_photo(td_, std::move(media->photo_), dialog_id, 
FileType::Photo);
-  if (new_photo.is_empty()) {
-    return promise.set_error(500, "Receive invalid photo in response");
-  }
-  bool is_content_changed = false;
-  bool need_update = false;
-  merge_photos(td_, &photo, &new_photo, dialog_id, true, is_content_changed, 
need_update);
-
-  auto input_media = photo_get_cover_input_media(td_->file_manager_.get(), 
photo, true, true);
+  TRY_STATUS_PROMISE(promise, cover.merge_with_media(td_, dialog_id, 
std::move(media_ptr)));
+  auto input_media = cover.get_cover_input_media(td_, true, true);
   if (input_media == nullptr) {
     return promise.set_error(500, "Failed to upload file");
   }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/td-git20260303/td/telegram/MessageQueryManager.h 
new/td-git20260317/td/telegram/MessageQueryManager.h
--- old/td-git20260303/td/telegram/MessageQueryManager.h        2026-03-13 
07:45:04.581765232 +0100
+++ new/td-git20260317/td/telegram/MessageQueryManager.h        2026-04-01 
14:40:57.184109379 +0200
@@ -14,6 +14,7 @@
 #include "td/telegram/EmojiGameInfo.h"
 #include "td/telegram/files/FileUploadId.h"
 #include "td/telegram/ForumTopicId.h"
+#include "td/telegram/MessageCover.h"
 #include "td/telegram/MessageFullId.h"
 #include "td/telegram/MessageId.h"
 #include "td/telegram/MessageSearchFilter.h"
@@ -53,13 +54,13 @@
                                                  bool get_affected_messages, 
Promise<Unit> &&promise);
 
   void upload_message_covers(BusinessConnectionId business_connection_id, 
DialogId dialog_id,
-                             vector<const Photo *> covers, Promise<Unit> 
&&promise);
+                             vector<MessageCover> covers, Promise<Unit> 
&&promise);
 
-  void upload_message_cover(BusinessConnectionId business_connection_id, 
DialogId dialog_id, Photo photo,
+  void upload_message_cover(BusinessConnectionId business_connection_id, 
DialogId dialog_id, MessageCover message_cover,
                             FileUploadId file_upload_id, Promise<Unit> 
&&promise, vector<int> bad_parts = {});
 
-  void complete_upload_message_cover(BusinessConnectionId 
business_connection_id, DialogId dialog_id, Photo photo,
-                                     FileUploadId file_upload_id,
+  void complete_upload_message_cover(BusinessConnectionId 
business_connection_id, DialogId dialog_id,
+                                     MessageCover cover, FileUploadId 
file_upload_id,
                                      
telegram_api::object_ptr<telegram_api::MessageMedia> &&media_ptr,
                                      Promise<Unit> &&promise);
 
@@ -241,7 +242,7 @@
   struct BeingUploadedCover {
     BusinessConnectionId business_connection_id_;
     DialogId dialog_id_;
-    Photo photo_;
+    MessageCover cover_;
     telegram_api::object_ptr<telegram_api::InputFile> input_file_;
     Promise<Unit> promise_;
   };
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/td-git20260303/td/telegram/MessageQuote.cpp 
new/td-git20260317/td/telegram/MessageQuote.cpp
--- old/td-git20260303/td/telegram/MessageQuote.cpp     2026-03-13 
07:45:04.581765232 +0100
+++ new/td-git20260317/td/telegram/MessageQuote.cpp     2026-04-01 
14:40:57.184109379 +0200
@@ -159,21 +159,7 @@
 }
 
 void MessageQuote::remove_unallowed_quote_entities(FormattedText &text) {
-  auto is_allowed_quote_entity = [](const MessageEntity &entity) {
-    switch (entity.type) {
-      case MessageEntity::Type::Bold:
-      case MessageEntity::Type::Italic:
-      case MessageEntity::Type::Underline:
-      case MessageEntity::Type::Strikethrough:
-      case MessageEntity::Type::Spoiler:
-      case MessageEntity::Type::CustomEmoji:
-        return true;
-      default:
-        return false;
-    }
-  };
-
-  td::remove_if(text.entities, [&](const auto &entity) { return 
!is_allowed_quote_entity(entity); });
+  td::remove_if(text.entities, [](const auto &entity) { return 
!is_allowed_quote_entity_type(entity.type); });
 }
 
 int32 MessageQuote::search_quote(FormattedText &&text, FormattedText &&quote, 
int32 quote_position) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/td-git20260303/td/telegram/MessagesManager.cpp 
new/td-git20260317/td/telegram/MessagesManager.cpp
--- old/td-git20260303/td/telegram/MessagesManager.cpp  2026-03-13 
07:45:04.582765197 +0100
+++ new/td-git20260317/td/telegram/MessagesManager.cpp  2026-04-01 
14:40:57.186109299 +0200
@@ -1192,7 +1192,7 @@
       return on_error(Status::Error(400, "Have no write access to the chat"));
     }
 
-    auto reply_to = input_reply_to.get_input_reply_to(td_, message_topic, 
dialog_id, flags);
+    auto reply_to = input_reply_to.get_input_reply_to(td_, message_topic, 
false, dialog_id, flags);
 
     if (reply_to != nullptr) {
       flags |= telegram_api::messages_sendMessage::REPLY_TO_MASK;
@@ -1341,7 +1341,7 @@
     auto input_peer = td_->dialog_manager_->get_input_peer(dialog_id, 
AccessRights::Write);
     CHECK(input_peer != nullptr);
 
-    auto reply_to = input_reply_to.get_input_reply_to(td_, message_topic);
+    auto reply_to = input_reply_to.get_input_reply_to(td_, message_topic, 
false, dialog_id, flags);
 
     if (reply_to != nullptr) {
       flags |= telegram_api::messages_sendInlineBotResult::REPLY_TO_MASK;
@@ -1413,7 +1413,7 @@
       return on_error(Status::Error(400, "Have no write access to the chat"));
     }
 
-    auto reply_to = input_reply_to.get_input_reply_to(td_, message_topic);
+    auto reply_to = input_reply_to.get_input_reply_to(td_, message_topic, 
false, dialog_id, flags);
 
     if (reply_to != nullptr) {
       flags |= telegram_api::messages_sendMultiMedia::REPLY_TO_MASK;
@@ -1555,7 +1555,7 @@
       return on_error(Status::Error(400, "Have no write access to the chat"));
     }
 
-    auto reply_to = input_reply_to.get_input_reply_to(td_, message_topic);
+    auto reply_to = input_reply_to.get_input_reply_to(td_, message_topic, 
false, dialog_id, flags);
 
     if (reply_to != nullptr) {
       flags |= telegram_api::messages_sendMedia::REPLY_TO_MASK;
@@ -1938,7 +1938,7 @@
       return on_error(Status::Error(400, "Can't access the chat to forward 
messages from"));
     }
 
-    auto input_reply_to = message_input_reply_to.get_input_reply_to(td_, 
message_topic);
+    auto input_reply_to = message_input_reply_to.get_input_reply_to(td_, 
message_topic, false, to_dialog_id, flags);
     if (input_reply_to != nullptr) {
       flags |= telegram_api::messages_forwardMessages::REPLY_TO_MASK;
     }
@@ -20402,6 +20402,7 @@
       !have_message_force(d, implicit_reply_to_message_id, 
"create_message_input_reply_to 1")) {
     LOG(INFO) << "Have implicit reply to unknown " << 
implicit_reply_to_message_id;
   }
+  CHECK(implicit_reply_to_message_id == MessageId() || 
implicit_reply_to_message_id.is_server());
   if (reply_to == nullptr) {
     if (!for_draft && implicit_reply_to_message_id.is_valid()) {
       return MessageInputReplyTo{implicit_reply_to_message_id, DialogId(), 
MessageQuote(), 0};
@@ -20626,6 +20627,7 @@
 
         auto implicit_reply_to_message_id =
             get_message_topic(reply_d->dialog_id, 
replied_m).get_implicit_reply_to_message_id(td_);
+        CHECK(implicit_reply_to_message_id == MessageId() || 
implicit_reply_to_message_id.is_server());
         set_message_reply(reply_d, replied_m,
                           MessageInputReplyTo{implicit_reply_to_message_id, 
DialogId(), MessageQuote(), 0}, true);
       }
@@ -28942,7 +28944,7 @@
 
   auto file_upload_id = get_message_send_file_upload_id(dialog_id, m, 0);
   if (!file_upload_id.is_valid()) {
-    if (get_message_content_cover(m->content.get()) == nullptr) {
+    if (!has_message_content_cover(m->content.get())) {
       LOG(ERROR) << "Have no being uploaded file in " << 
to_string(get_message_message_content_object(dialog_id, m));
     }
     return;
@@ -34886,10 +34888,11 @@
       << replied_message_full_id << ' ' << m->replied_message_info << ' ' << 
*input_reply_to;
 
   auto message_id = get_message_id_by_random_id(d, m->reply_to_random_id, 
"restore_message_reply_to_message_id");
-  if (message_id.is_valid() || message_id.is_valid_scheduled()) {
+  if ((message_id.is_valid() || message_id.is_valid_scheduled()) && 
!message_id.is_local()) {
     update_message_reply_to_message_id(d, m, message_id, false);
   } else {
     auto implicit_reply_to_message_id = get_message_topic(d->dialog_id, 
m).get_implicit_reply_to_message_id(td_);
+    CHECK(implicit_reply_to_message_id == MessageId() || 
implicit_reply_to_message_id.is_server());
     set_message_reply(d, m, MessageInputReplyTo{implicit_reply_to_message_id, 
DialogId(), MessageQuote(), 0}, false);
   }
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/td-git20260303/td/telegram/PollManager.cpp 
new/td-git20260317/td/telegram/PollManager.cpp
--- old/td-git20260303/td/telegram/PollManager.cpp      2026-03-13 
07:45:04.585765093 +0100
+++ new/td-git20260317/td/telegram/PollManager.cpp      2026-04-01 
14:40:57.188109218 +0200
@@ -431,10 +431,6 @@
   return get_poll_editable(poll_id);
 }
 
-void PollManager::remove_unallowed_entities(FormattedText &text) {
-  td::remove_if(text.entities, [](MessageEntity &entity) { return entity.type 
!= MessageEntity::Type::CustomEmoji; });
-}
-
 td_api::object_ptr<td_api::pollOption> 
PollManager::get_poll_option_object(const PollOption &poll_option) {
   return 
td_api::make_object<td_api::pollOption>(get_formatted_text_object(nullptr, 
poll_option.text_, true, -1),
                                                  poll_option.voter_count_, 0, 
poll_option.is_chosen_, false);
@@ -654,9 +650,9 @@
 PollId PollManager::create_poll(FormattedText &&question, 
vector<FormattedText> &&options, bool is_anonymous,
                                 bool allow_multiple_answers, bool is_quiz, 
int32 correct_option_id,
                                 FormattedText &&explanation, int32 
open_period, int32 close_date, bool is_closed) {
-  remove_unallowed_entities(question);
+  keep_only_custom_emoji(question);
   for (auto &option : options) {
-    remove_unallowed_entities(option);
+    keep_only_custom_emoji(option);
   }
   auto poll = make_unique<Poll>();
   poll->question_ = std::move(question);
@@ -1517,13 +1513,13 @@
   CHECK(poll != nullptr);
 
   auto question = poll->question_;
-  ::td::remove_unallowed_entities(td_, question, dialog_id);
+  remove_unallowed_entities(td_, question, dialog_id);
   auto options = transform(poll->options_, [](auto &option) { return 
option.text_; });
   for (auto &option : options) {
-    ::td::remove_unallowed_entities(td_, option, dialog_id);
+    remove_unallowed_entities(td_, option, dialog_id);
   }
   auto explanation = poll->explanation_;
-  ::td::remove_unallowed_entities(td_, explanation, dialog_id);
+  remove_unallowed_entities(td_, explanation, dialog_id);
   return create_poll(std::move(question), std::move(options), 
poll->is_anonymous_, poll->allow_multiple_answers_,
                      poll->is_quiz_, poll->correct_option_id_, 
std::move(explanation), poll->open_period_,
                      poll->open_period_ == 0 ? 0 : G()->unix_time(), false);
@@ -1574,7 +1570,7 @@
   return transform(std::move(poll_options), 
[](telegram_api::object_ptr<telegram_api::pollAnswer> &&poll_option) {
     PollOption option;
     option.text_ = get_formatted_text(nullptr, std::move(poll_option->text_), 
true, true, "get_poll_options");
-    remove_unallowed_entities(option.text_);
+    keep_only_custom_emoji(option.text_);
     option.data_ = poll_option->option_.as_slice().str();
     return option;
   });
@@ -1686,7 +1682,7 @@
       is_changed = true;
     }
     auto question = get_formatted_text(nullptr, 
std::move(poll_server->question_), true, true, "on_get_poll");
-    remove_unallowed_entities(question);
+    keep_only_custom_emoji(question);
     if (poll->question_ != question) {
       poll->question_ = std::move(question);
       is_changed = true;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/td-git20260303/td/telegram/PollManager.h 
new/td-git20260317/td/telegram/PollManager.h
--- old/td-git20260303/td/telegram/PollManager.h        2026-03-13 
07:45:04.585765093 +0100
+++ new/td-git20260317/td/telegram/PollManager.h        2026-04-01 
14:40:57.188109218 +0200
@@ -159,8 +159,6 @@
 
   static void on_unload_poll_timeout_callback(void *poll_manager_ptr, int64 
poll_id_int);
 
-  static void remove_unallowed_entities(FormattedText &text);
-
   static td_api::object_ptr<td_api::pollOption> get_poll_option_object(const 
PollOption &poll_option);
 
   static telegram_api::object_ptr<telegram_api::pollAnswer> 
get_input_poll_option(const PollOption &poll_option);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/td-git20260303/td/telegram/Requests.cpp 
new/td-git20260317/td/telegram/Requests.cpp
--- old/td-git20260303/td/telegram/Requests.cpp 2026-03-13 07:45:04.588764989 
+0100
+++ new/td-git20260317/td/telegram/Requests.cpp 2026-04-01 14:40:57.191109098 
+0200
@@ -109,6 +109,7 @@
 #include "td/telegram/net/NetStatsManager.h"
 #include "td/telegram/net/NetType.h"
 #include "td/telegram/net/Proxy.h"
+#include "td/telegram/net/ProxyChecker.h"
 #include "td/telegram/NotificationGroupId.h"
 #include "td/telegram/NotificationId.h"
 #include "td/telegram/NotificationManager.h"
@@ -9003,8 +9004,8 @@
     return send_closure(td_actor_, &Td::send_error, id, 
r_proxy.move_as_error());
   }
   CREATE_OK_REQUEST_PROMISE();
-  send_closure(G()->connection_creator(), &ConnectionCreator::test_proxy, 
r_proxy.move_as_ok(), request.dc_id_,
-               request.timeout_, std::move(promise));
+  send_closure(td_->proxy_checker_, &ProxyChecker::test_proxy, 
r_proxy.move_as_ok(), request.dc_id_, request.timeout_,
+               std::move(promise));
 }
 
 void Requests::on_request(uint64 id, const td_api::testGetDifference &request) 
{
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/td-git20260303/td/telegram/SecretChatActor.cpp 
new/td-git20260317/td/telegram/SecretChatActor.cpp
--- old/td-git20260303/td/telegram/SecretChatActor.cpp  2026-03-13 
07:45:04.588764989 +0100
+++ new/td-git20260317/td/telegram/SecretChatActor.cpp  2026-04-01 
14:40:57.191109098 +0200
@@ -841,8 +841,7 @@
     parser.fetch_end();
     if (!parser.get_error()) {
       auto layer = message_with_layer->layer_;
-      if (layer < static_cast<int32>(SecretChatLayer::Default) &&
-          false /* old Android app could send such messages */) {
+      if (layer < static_cast<int32>(SecretChatLayer::Default) && false /* 
Android app can send such messages */) {
         LOG(ERROR) << "Layer " << layer << " is not supported, drop message " 
<< to_string(message_with_layer);
         return Status::OK();
       }
@@ -872,19 +871,6 @@
                   static_cast<int32>(SecretChatLayer::Current)),
               SendFlag::None, Promise<>());
 
-  if (config_state_.his_layer == 8) {
-    TlBufferParser new_parser(&data_buffer);
-    auto message_without_layer = 
secret_api::DecryptedMessage::fetch(new_parser);
-    parser.fetch_end();
-    if (!new_parser.get_error()) {
-      message->decrypted_message_layer = 
secret_api::make_object<secret_api::decryptedMessageLayer>(
-          BufferSlice(), config_state_.his_layer, -1, -1, 
std::move(message_without_layer));
-      return do_inbound_message_decrypted_unchecked(std::move(message), 
mtproto_version);
-    }
-    LOG(ERROR) << "Failed to fetch update (DecryptedMessage): " << 
new_parser.get_error()
-               << format::as_hex_dump<4>(data_buffer.as_slice());
-  }
-
   return status;
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/td-git20260303/td/telegram/SecretChatActor.h 
new/td-git20260317/td/telegram/SecretChatActor.h
--- old/td-git20260303/td/telegram/SecretChatActor.h    2026-03-13 
07:45:04.589764954 +0100
+++ new/td-git20260317/td/telegram/SecretChatActor.h    2026-04-01 
14:40:57.191109098 +0200
@@ -184,8 +184,8 @@
   };
 
   struct ConfigState {
-    int32 his_layer = 8;
-    int32 my_layer = 8;
+    int32 his_layer = 23;
+    int32 my_layer = 23;
     int32 ttl = 0;
 
     static Slice key() {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/td-git20260303/td/telegram/Td.cpp 
new/td-git20260317/td/telegram/Td.cpp
--- old/td-git20260303/td/telegram/Td.cpp       2026-03-13 07:45:04.592764850 
+0100
+++ new/td-git20260317/td/telegram/Td.cpp       2026-04-01 14:40:57.195108938 
+0200
@@ -60,6 +60,7 @@
 #include "td/telegram/net/NetQueryDispatcher.h"
 #include "td/telegram/net/NetStatsManager.h"
 #include "td/telegram/net/Proxy.h"
+#include "td/telegram/net/ProxyChecker.h"
 #include "td/telegram/net/TempAuthKeyWatchdog.h"
 #include "td/telegram/NotificationManager.h"
 #include "td/telegram/NotificationSettingsManager.h"
@@ -446,6 +447,7 @@
   inc_actor_refcnt();          // guard
 
   alarm_manager_ = create_actor<AlarmManager>("AlarmManager", 
create_reference());
+  proxy_checker_ = create_actor<ProxyChecker>("ProxyChecker", 
create_reference());
 
   CHECK(state_ == State::WaitParameters);
   for (auto &update : get_fake_current_state()) {
@@ -671,6 +673,7 @@
   reset_actor(ActorOwn<Actor>(std::move(language_pack_manager_)));
   reset_actor(ActorOwn<Actor>(std::move(net_stats_manager_)));
   reset_actor(ActorOwn<Actor>(std::move(password_manager_)));
+  reset_actor(ActorOwn<Actor>(std::move(proxy_checker_)));
   reset_actor(ActorOwn<Actor>(std::move(secure_manager_)));
   reset_actor(ActorOwn<Actor>(std::move(secret_chats_manager_)));
   reset_actor(ActorOwn<Actor>(std::move(storage_manager_)));
@@ -770,6 +773,7 @@
     G()->set_close_flag();
     clear_requests();
     alarm_manager_.reset();
+    proxy_checker_.reset();
     send_update(td_api::make_object<td_api::updateAuthorizationState>(
         td_api::make_object<td_api::authorizationStateClosing>()));
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/td-git20260303/td/telegram/Td.h 
new/td-git20260317/td/telegram/Td.h
--- old/td-git20260303/td/telegram/Td.h 2026-03-13 07:45:04.592764850 +0100
+++ new/td-git20260317/td/telegram/Td.h 2026-04-01 14:40:57.195108938 +0200
@@ -84,6 +84,7 @@
 class PollManager;
 class PrivacyManager;
 class PromoDataManager;
+class ProxyChecker;
 class QuickReplyManager;
 class ReactionManager;
 class ReferralProgramManager;
@@ -300,6 +301,7 @@
   ActorOwn<LanguagePackManager> language_pack_manager_;
   ActorOwn<NetStatsManager> net_stats_manager_;
   ActorOwn<PasswordManager> password_manager_;
+  ActorOwn<ProxyChecker> proxy_checker_;
   ActorOwn<SecretChatsManager> secret_chats_manager_;
   ActorOwn<SecureManager> secure_manager_;
   ActorOwn<StateManager> state_manager_;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/td-git20260303/td/telegram/ToDoItem.cpp 
new/td-git20260317/td/telegram/ToDoItem.cpp
--- old/td-git20260303/td/telegram/ToDoItem.cpp 2026-03-13 07:45:04.593764815 
+0100
+++ new/td-git20260317/td/telegram/ToDoItem.cpp 2026-04-01 14:40:57.196108898 
+0200
@@ -55,24 +55,8 @@
 }
 
 bool ToDoItem::remove_unsupported_entities(FormattedText &text) {
-  return td::remove_if(text.entities, [&](const MessageEntity &entity) {
-    switch (entity.type) {
-      case MessageEntity::Type::Bold:
-      case MessageEntity::Type::Italic:
-      case MessageEntity::Type::Underline:
-      case MessageEntity::Type::Strikethrough:
-      case MessageEntity::Type::Spoiler:
-      case MessageEntity::Type::CustomEmoji:
-      case MessageEntity::Type::Url:
-      case MessageEntity::Type::EmailAddress:
-      case MessageEntity::Type::Mention:
-      case MessageEntity::Type::Hashtag:
-      case MessageEntity::Type::Cashtag:
-      case MessageEntity::Type::PhoneNumber:
-        return false;
-      default:
-        return true;
-    }
+  return td::remove_if(text.entities, [](const MessageEntity &entity) {
+    return !is_allowed_quote_entity_type(entity.type) && 
!is_found_entity_type(entity.type, false, false);
   });
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/td-git20260303/td/telegram/ToDoList.cpp 
new/td-git20260317/td/telegram/ToDoList.cpp
--- old/td-git20260303/td/telegram/ToDoList.cpp 2026-03-13 07:45:04.593764815 
+0100
+++ new/td-git20260317/td/telegram/ToDoList.cpp 2026-04-01 14:40:57.196108898 
+0200
@@ -94,19 +94,8 @@
 }
 
 bool ToDoList::remove_unsupported_entities(FormattedText &text) {
-  return td::remove_if(text.entities, [&](const MessageEntity &entity) {
-    switch (entity.type) {
-      case MessageEntity::Type::Bold:
-      case MessageEntity::Type::Italic:
-      case MessageEntity::Type::Underline:
-      case MessageEntity::Type::Strikethrough:
-      case MessageEntity::Type::Spoiler:
-      case MessageEntity::Type::CustomEmoji:
-        return false;
-      default:
-        return true;
-    }
-  });
+  return td::remove_if(text.entities,
+                       [](const MessageEntity &entity) { return 
!is_allowed_quote_entity_type(entity.type); });
 }
 
 void ToDoList::validate(const char *source) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/td-git20260303/td/telegram/files/FileDownloadManager.cpp 
new/td-git20260317/td/telegram/files/FileDownloadManager.cpp
--- old/td-git20260303/td/telegram/files/FileDownloadManager.cpp        
2026-03-13 07:45:04.597808504 +0100
+++ new/td-git20260317/td/telegram/files/FileDownloadManager.cpp        
2026-04-01 14:40:57.199998225 +0200
@@ -22,7 +22,7 @@
 }
 
 void FileDownloadManager::start_up() {
-  if (G()->get_option_boolean("is_premium")) {
+  if (G()->get_option_boolean("is_premium") || 
G()->get_option_integer("session_count") > 1) {
     max_download_resource_limit_ *= 8;
   }
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/td-git20260303/td/telegram/net/ConnectionCreator.cpp 
new/td-git20260317/td/telegram/net/ConnectionCreator.cpp
--- old/td-git20260303/td/telegram/net/ConnectionCreator.cpp    2026-03-13 
07:45:04.599652464 +0100
+++ new/td-git20260317/td/telegram/net/ConnectionCreator.cpp    2026-04-01 
14:40:57.201848347 +0200
@@ -371,138 +371,6 @@
                                create_reference(token))};
 }
 
-void ConnectionCreator::test_proxy(Proxy &&proxy, int32 dc_id, double timeout, 
Promise<Unit> &&promise) {
-  auto start_time = Time::now();
-
-  IPAddress ip_address;
-  auto status = ip_address.init_host_port(proxy.server(), proxy.port());
-  if (status.is_error()) {
-    return promise.set_error(400, status.public_message());
-  }
-  auto r_socket_fd = SocketFd::open(ip_address);
-  if (r_socket_fd.is_error()) {
-    return promise.set_error(400, r_socket_fd.error().public_message());
-  }
-
-  auto dc_options = get_default_dc_options(false);
-  IPAddress mtproto_ip_address;
-  for (auto &dc_option : dc_options.dc_options) {
-    if (dc_option.get_dc_id().get_raw_id() == dc_id) {
-      mtproto_ip_address = dc_option.get_ip_address();
-      break;
-    }
-  }
-  if (!mtproto_ip_address.is_valid()) {
-    return promise.set_error(400, "Invalid datacenter identifier specified");
-  }
-
-  auto request_id = ++test_proxy_request_id_;
-  auto request = make_unique<TestProxyRequest>();
-  request->proxy_ = std::move(proxy);
-  request->dc_id_ = static_cast<int16>(dc_id);
-  request->promise_ = std::move(promise);
-
-  auto connection_promise =
-      PromiseCreator::lambda([actor_id = actor_id(this), 
request_id](Result<ConnectionData> r_data) {
-        send_closure(actor_id, 
&ConnectionCreator::on_test_proxy_connection_data, request_id, 
std::move(r_data));
-      });
-  request->child_ = prepare_connection(ip_address, r_socket_fd.move_as_ok(), 
request->proxy_, mtproto_ip_address,
-                                       request->get_transport(), "Test", 
"TestPingDC2", nullptr, {}, false,
-                                       std::move(connection_promise));
-
-  test_proxy_requests_.emplace(request_id, std::move(request));
-
-  create_actor<SleepActor>("TestProxyTimeoutActor", timeout + start_time - 
Time::now(),
-                           PromiseCreator::lambda([actor_id = actor_id(this), 
request_id](Unit) {
-                             send_closure(actor_id, 
&ConnectionCreator::on_test_proxy_timeout, request_id);
-                           }))
-      .release();
-}
-
-void ConnectionCreator::on_test_proxy_connection_data(uint64 request_id, 
Result<ConnectionData> r_data) {
-  auto it = test_proxy_requests_.find(request_id);
-  if (it == test_proxy_requests_.end()) {
-    return;
-  }
-  auto *request = it->second.get();
-  if (r_data.is_error()) {
-    auto promise = std::move(request->promise_);
-    test_proxy_requests_.erase(it);
-    return promise.set_error(r_data.move_as_error());
-  }
-
-  class HandshakeContext final : public mtproto::AuthKeyHandshakeContext {
-   public:
-    mtproto::DhCallback *get_dh_callback() final {
-      return nullptr;
-    }
-    mtproto::PublicRsaKeyInterface *get_public_rsa_key_interface() final {
-      return public_rsa_key_.get();
-    }
-
-   private:
-    std::shared_ptr<mtproto::PublicRsaKeyInterface> public_rsa_key_ = 
PublicRsaKeySharedMain::create(false);
-  };
-  auto handshake = make_unique<mtproto::AuthKeyHandshake>(request->dc_id_, 
3600);
-  auto data = r_data.move_as_ok();
-  auto raw_connection = mtproto::RawConnection::create(data.ip_address, 
std::move(data.buffered_socket_fd),
-                                                       
request->get_transport(), nullptr);
-  request->child_ = create_actor<mtproto::HandshakeActor>(
-      "HandshakeActor", std::move(handshake), std::move(raw_connection), 
make_unique<HandshakeContext>(), 10.0,
-      PromiseCreator::lambda(
-          [actor_id = actor_id(this), 
request_id](Result<unique_ptr<mtproto::RawConnection>> raw_connection) {
-            send_closure(actor_id, 
&ConnectionCreator::on_test_proxy_handshake_connection, request_id,
-                         std::move(raw_connection));
-          }),
-      PromiseCreator::lambda(
-          [actor_id = actor_id(this), 
request_id](Result<unique_ptr<mtproto::AuthKeyHandshake>> handshake) {
-            send_closure(actor_id, 
&ConnectionCreator::on_test_proxy_handshake, request_id, std::move(handshake));
-          }));
-}
-
-void ConnectionCreator::on_test_proxy_handshake_connection(
-    uint64 request_id, Result<unique_ptr<mtproto::RawConnection>> 
r_raw_connection) {
-  if (r_raw_connection.is_error()) {
-    auto it = test_proxy_requests_.find(request_id);
-    if (it == test_proxy_requests_.end()) {
-      return;
-    }
-    auto promise = std::move(it->second->promise_);
-    test_proxy_requests_.erase(it);
-    return promise.set_error(400, 
r_raw_connection.move_as_error().public_message());
-  }
-}
-
-void ConnectionCreator::on_test_proxy_handshake(uint64 request_id,
-                                                
Result<unique_ptr<mtproto::AuthKeyHandshake>> r_handshake) {
-  auto it = test_proxy_requests_.find(request_id);
-  if (it == test_proxy_requests_.end()) {
-    return;
-  }
-  auto promise = std::move(it->second->promise_);
-  test_proxy_requests_.erase(it);
-
-  if (r_handshake.is_error()) {
-    return promise.set_error(400, 
r_handshake.move_as_error().public_message());
-  }
-  auto handshake = r_handshake.move_as_ok();
-  if (!handshake->is_ready_for_finish()) {
-    return promise.set_error(400, "Handshake is not ready");
-  }
-  promise.set_value(Unit());
-}
-
-void ConnectionCreator::on_test_proxy_timeout(uint64 request_id) {
-  auto it = test_proxy_requests_.find(request_id);
-  if (it == test_proxy_requests_.end()) {
-    return;
-  }
-  auto promise = std::move(it->second->promise_);
-  test_proxy_requests_.erase(it);
-
-  promise.set_error(400, "Timeout expired");
-}
-
 void ConnectionCreator::set_active_proxy_id(int32 proxy_id, bool from_binlog) {
   active_proxy_id_ = proxy_id;
   if (proxy_id == 0) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/td-git20260303/td/telegram/net/ConnectionCreator.h 
new/td-git20260317/td/telegram/net/ConnectionCreator.h
--- old/td-git20260303/td/telegram/net/ConnectionCreator.h      2026-03-13 
07:45:04.599652464 +0100
+++ new/td-git20260317/td/telegram/net/ConnectionCreator.h      2026-04-01 
14:40:57.201848347 +0200
@@ -84,9 +84,9 @@
 
   void ping_proxy(td_api::object_ptr<td_api::proxy> input_proxy, 
Promise<double> promise);
 
-  void test_proxy(Proxy &&proxy, int32 dc_id, double timeout, Promise<Unit> 
&&promise);
-
  private:
+  friend class ProxyChecker;
+
   ActorShared<> parent_;
   DcOptionsSet dc_options_set_;
   bool network_flag_ = false;
@@ -182,19 +182,6 @@
     unique_ptr<mtproto::RawConnection::StatsCallback> stats_callback;
   };
 
-  struct TestProxyRequest {
-    Proxy proxy_;
-    int16 dc_id_ = -1;
-    ActorOwn<> child_;
-    Promise<Unit> promise_;
-
-    mtproto::TransportType get_transport() const {
-      return mtproto::TransportType{mtproto::TransportType::ObfuscatedTcp, 
dc_id_, proxy_.secret()};
-    }
-  };
-  uint64 test_proxy_request_id_ = 0;
-  FlatHashMap<uint64, unique_ptr<TestProxyRequest>> test_proxy_requests_;
-
   uint64 next_token() {
     return ++current_token_;
   }
@@ -271,15 +258,6 @@
                                      mtproto::TransportType transport_type, 
string debug_str, Promise<double> promise);
 
   void on_ping_main_dc_result(uint64 token, Result<double> result);
-
-  void on_test_proxy_connection_data(uint64 request_id, Result<ConnectionData> 
r_data);
-
-  void on_test_proxy_handshake_connection(uint64 request_id,
-                                          
Result<unique_ptr<mtproto::RawConnection>> r_raw_connection);
-
-  void on_test_proxy_handshake(uint64 request_id, 
Result<unique_ptr<mtproto::AuthKeyHandshake>> r_handshake);
-
-  void on_test_proxy_timeout(uint64 request_id);
 };
 
 }  // namespace td
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/td-git20260303/td/telegram/net/NetQueryDispatcher.cpp 
new/td-git20260317/td/telegram/net/NetQueryDispatcher.cpp
--- old/td-git20260303/td/telegram/net/NetQueryDispatcher.cpp   2026-03-13 
07:45:04.599764607 +0100
+++ new/td-git20260317/td/telegram/net/NetQueryDispatcher.cpp   2026-04-01 
14:40:57.202108657 +0200
@@ -243,7 +243,7 @@
     int32 slow_net_scheduler_id = G()->get_slow_net_scheduler_id();
 
     auto raw_dc_id = dc_id.get_raw_id();
-    bool is_premium = G()->get_option_boolean("is_premium");
+    bool is_premium = G()->get_option_boolean("is_premium") || session_count > 
1;
     int32 upload_session_count = (raw_dc_id != 2 && raw_dc_id != 4) || 
is_premium ? 8 : 4;
     int32 download_session_count = is_premium ? 8 : 2;
     int32 download_small_session_count = is_premium ? 8 : 2;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/td-git20260303/td/telegram/net/ProxyChecker.cpp 
new/td-git20260317/td/telegram/net/ProxyChecker.cpp
--- old/td-git20260303/td/telegram/net/ProxyChecker.cpp 1970-01-01 
01:00:00.000000000 +0100
+++ new/td-git20260317/td/telegram/net/ProxyChecker.cpp 2026-04-01 
14:40:57.202108657 +0200
@@ -0,0 +1,161 @@
+//
+// Copyright Aliaksei Levin ([email protected]), Arseny Smirnov 
([email protected]) 2014-2026
+//
+// 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/net/ProxyChecker.h"
+
+#include "td/telegram/net/PublicRsaKeySharedMain.h"
+
+#include "td/mtproto/DhCallback.h"
+#include "td/mtproto/HandshakeActor.h"
+#include "td/mtproto/RSA.h"
+#include "td/mtproto/TlsInit.h"
+
+#include "td/actor/SleepActor.h"
+
+#include "td/utils/port/IPAddress.h"
+#include "td/utils/port/SocketFd.h"
+#include "td/utils/Time.h"
+
+#include <memory>
+
+namespace td {
+
+ProxyChecker::ProxyChecker(ActorShared<> parent) : parent_(std::move(parent)) {
+}
+
+void ProxyChecker::test_proxy(Proxy &&proxy, int32 dc_id, double timeout, 
Promise<Unit> &&promise) {
+  auto start_time = Time::now();
+
+  IPAddress ip_address;
+  auto status = ip_address.init_host_port(proxy.server(), proxy.port());
+  if (status.is_error()) {
+    return promise.set_error(400, status.public_message());
+  }
+  auto r_socket_fd = SocketFd::open(ip_address);
+  if (r_socket_fd.is_error()) {
+    return promise.set_error(400, r_socket_fd.error().public_message());
+  }
+
+  auto dc_options = ConnectionCreator::get_default_dc_options(false);
+  IPAddress mtproto_ip_address;
+  for (auto &dc_option : dc_options.dc_options) {
+    if (dc_option.get_dc_id().get_raw_id() == dc_id) {
+      mtproto_ip_address = dc_option.get_ip_address();
+      break;
+    }
+  }
+  if (!mtproto_ip_address.is_valid()) {
+    return promise.set_error(400, "Invalid datacenter identifier specified");
+  }
+
+  auto request_id = ++test_proxy_request_id_;
+  auto request = make_unique<TestProxyRequest>();
+  request->proxy_ = std::move(proxy);
+  request->dc_id_ = static_cast<int16>(dc_id);
+  request->promise_ = std::move(promise);
+
+  auto connection_promise =
+      PromiseCreator::lambda([actor_id = actor_id(this), 
request_id](Result<ConnectionCreator::ConnectionData> r_data) {
+        send_closure(actor_id, &ProxyChecker::on_test_proxy_connection_data, 
request_id, std::move(r_data));
+      });
+  request->child_ = ConnectionCreator::prepare_connection(
+      ip_address, r_socket_fd.move_as_ok(), request->proxy_, 
mtproto_ip_address, request->get_transport(), "Test",
+      "TestPingDC2", nullptr, {}, false, std::move(connection_promise));
+
+  test_proxy_requests_.emplace(request_id, std::move(request));
+
+  create_actor<SleepActor>("TestProxyTimeoutActor", timeout + start_time - 
Time::now(),
+                           PromiseCreator::lambda([actor_id = actor_id(this), 
request_id](Unit) {
+                             send_closure(actor_id, 
&ProxyChecker::on_test_proxy_timeout, request_id);
+                           }))
+      .release();
+}
+
+void ProxyChecker::on_test_proxy_connection_data(uint64 request_id, 
Result<ConnectionCreator::ConnectionData> r_data) {
+  auto it = test_proxy_requests_.find(request_id);
+  if (it == test_proxy_requests_.end()) {
+    return;
+  }
+  auto *request = it->second.get();
+  if (r_data.is_error()) {
+    auto promise = std::move(request->promise_);
+    test_proxy_requests_.erase(it);
+    return promise.set_error(r_data.move_as_error());
+  }
+
+  class HandshakeContext final : public mtproto::AuthKeyHandshakeContext {
+   public:
+    mtproto::DhCallback *get_dh_callback() final {
+      return nullptr;
+    }
+    mtproto::PublicRsaKeyInterface *get_public_rsa_key_interface() final {
+      return public_rsa_key_.get();
+    }
+
+   private:
+    std::shared_ptr<mtproto::PublicRsaKeyInterface> public_rsa_key_ = 
PublicRsaKeySharedMain::create(false);
+  };
+  auto handshake = make_unique<mtproto::AuthKeyHandshake>(request->dc_id_, 
3600);
+  auto data = r_data.move_as_ok();
+  auto raw_connection = mtproto::RawConnection::create(data.ip_address, 
std::move(data.buffered_socket_fd),
+                                                       
request->get_transport(), nullptr);
+  request->child_ = create_actor<mtproto::HandshakeActor>(
+      "HandshakeActor", std::move(handshake), std::move(raw_connection), 
make_unique<HandshakeContext>(), 10.0,
+      PromiseCreator::lambda(
+          [actor_id = actor_id(this), 
request_id](Result<unique_ptr<mtproto::RawConnection>> raw_connection) {
+            send_closure(actor_id, 
&ProxyChecker::on_test_proxy_handshake_connection, request_id,
+                         std::move(raw_connection));
+          }),
+      PromiseCreator::lambda(
+          [actor_id = actor_id(this), 
request_id](Result<unique_ptr<mtproto::AuthKeyHandshake>> handshake) {
+            send_closure(actor_id, &ProxyChecker::on_test_proxy_handshake, 
request_id, std::move(handshake));
+          }));
+}
+
+void ProxyChecker::on_test_proxy_handshake_connection(uint64 request_id,
+                                                      
Result<unique_ptr<mtproto::RawConnection>> r_raw_connection) {
+  if (r_raw_connection.is_error()) {
+    auto it = test_proxy_requests_.find(request_id);
+    if (it == test_proxy_requests_.end()) {
+      return;
+    }
+    auto promise = std::move(it->second->promise_);
+    test_proxy_requests_.erase(it);
+    return promise.set_error(400, 
r_raw_connection.move_as_error().public_message());
+  }
+}
+
+void ProxyChecker::on_test_proxy_handshake(uint64 request_id,
+                                           
Result<unique_ptr<mtproto::AuthKeyHandshake>> r_handshake) {
+  auto it = test_proxy_requests_.find(request_id);
+  if (it == test_proxy_requests_.end()) {
+    return;
+  }
+  auto promise = std::move(it->second->promise_);
+  test_proxy_requests_.erase(it);
+
+  if (r_handshake.is_error()) {
+    return promise.set_error(400, 
r_handshake.move_as_error().public_message());
+  }
+  auto handshake = r_handshake.move_as_ok();
+  if (!handshake->is_ready_for_finish()) {
+    return promise.set_error(400, "Handshake is not ready");
+  }
+  promise.set_value(Unit());
+}
+
+void ProxyChecker::on_test_proxy_timeout(uint64 request_id) {
+  auto it = test_proxy_requests_.find(request_id);
+  if (it == test_proxy_requests_.end()) {
+    return;
+  }
+  auto promise = std::move(it->second->promise_);
+  test_proxy_requests_.erase(it);
+
+  promise.set_error(400, "Timeout expired");
+}
+
+}  // namespace td
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/td-git20260303/td/telegram/net/ProxyChecker.h 
new/td-git20260317/td/telegram/net/ProxyChecker.h
--- old/td-git20260303/td/telegram/net/ProxyChecker.h   1970-01-01 
01:00:00.000000000 +0100
+++ new/td-git20260317/td/telegram/net/ProxyChecker.h   2026-04-01 
14:40:57.202108657 +0200
@@ -0,0 +1,63 @@
+//
+// Copyright Aliaksei Levin ([email protected]), Arseny Smirnov 
([email protected]) 2014-2026
+//
+// 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/net/ConnectionCreator.h"
+#include "td/telegram/net/NetQuery.h"
+#include "td/telegram/net/Proxy.h"
+
+#include "td/mtproto/Handshake.h"
+#include "td/mtproto/RawConnection.h"
+#include "td/mtproto/TransportType.h"
+
+#include "td/actor/actor.h"
+
+#include "td/utils/common.h"
+#include "td/utils/FlatHashMap.h"
+#include "td/utils/Promise.h"
+#include "td/utils/Status.h"
+
+namespace td {
+
+class ProxyChecker final : public NetQueryCallback {
+ public:
+  explicit ProxyChecker(ActorShared<> parent);
+  ProxyChecker(const ProxyChecker &) = delete;
+  ProxyChecker &operator=(const ProxyChecker &) = delete;
+  ProxyChecker(ProxyChecker &&other) = delete;
+  ProxyChecker &operator=(ProxyChecker &&other) = delete;
+  ~ProxyChecker() final = default;
+
+  void test_proxy(Proxy &&proxy, int32 dc_id, double timeout, Promise<Unit> 
&&promise);
+
+ private:
+  ActorShared<> parent_;
+
+  struct TestProxyRequest {
+    Proxy proxy_;
+    int16 dc_id_ = -1;
+    ActorOwn<> child_;
+    Promise<Unit> promise_;
+
+    mtproto::TransportType get_transport() const {
+      return mtproto::TransportType{mtproto::TransportType::ObfuscatedTcp, 
dc_id_, proxy_.secret()};
+    }
+  };
+  uint64 test_proxy_request_id_ = 0;
+  FlatHashMap<uint64, unique_ptr<TestProxyRequest>> test_proxy_requests_;
+
+  void on_test_proxy_connection_data(uint64 request_id, 
Result<ConnectionCreator::ConnectionData> r_data);
+
+  void on_test_proxy_handshake_connection(uint64 request_id,
+                                          
Result<unique_ptr<mtproto::RawConnection>> r_raw_connection);
+
+  void on_test_proxy_handshake(uint64 request_id, 
Result<unique_ptr<mtproto::AuthKeyHandshake>> r_handshake);
+
+  void on_test_proxy_timeout(uint64 request_id);
+};
+
+}  // namespace td
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/td-git20260303/tde2e/td/e2e/Blockchain.cpp 
new/td-git20260317/tde2e/td/e2e/Blockchain.cpp
--- old/td-git20260303/tde2e/td/e2e/Blockchain.cpp      2026-03-13 
07:45:04.602711154 +0100
+++ new/td-git20260317/tde2e/td/e2e/Blockchain.cpp      2026-04-01 
14:40:57.205000810 +0200
@@ -185,7 +185,7 @@
   }
   result.signature_ = Signature::from_u512(block.signature_);
   result.prev_block_hash_ = block.prev_block_hash_;
-  auto change_from_tl = [&](auto &obj) {
+  auto change_from_tl = [](auto &obj) {
     return Change::from_tl(*obj);
   };
   result.changes_ = td::transform(block.changes_, change_from_tl);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/td-git20260303/tde2e/td/e2e/EncryptedStorage.cpp 
new/td-git20260317/tde2e/td/e2e/EncryptedStorage.cpp
--- old/td-git20260303/tde2e/td/e2e/EncryptedStorage.cpp        2026-03-13 
07:45:04.602764503 +0100
+++ new/td-git20260317/tde2e/td/e2e/EncryptedStorage.cpp        2026-04-01 
14:40:57.205108537 +0200
@@ -225,7 +225,7 @@
   for (auto &change : changes) {
     bool skip = false;
     td::Result<std::pair<Key, std::optional<Value>>> r_p;
-    std::visit(td::overloaded([&](ChangeNoop &noop) {},
+    std::visit(td::overloaded([](ChangeNoop &noop) {},
                               [&](ChangeSetValue &set_value) { r_p = 
parse(set_value.key, set_value.value); },
                               [&](ChangeSetGroupState &) { skip = true; }, 
[&](ChangeSetSharedKey &) { skip = true; }),
                change.value);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/td-git20260303/tde2e/td/e2e/e2e_api.cpp 
new/td-git20260317/tde2e/td/e2e/e2e_api.cpp
--- old/td-git20260303/tde2e/td/e2e/e2e_api.cpp 2026-03-13 07:45:04.602764503 
+0100
+++ new/td-git20260317/tde2e/td/e2e/e2e_api.cpp 2026-04-01 14:40:57.205108537 
+0200
@@ -68,7 +68,7 @@
 
   td::Result<api::PrivateKeyId> generate_dummy_key() {
     auto hash = to_hash("dummy key", "...");
-    return container_.try_build<Key>(hash, [&]() -> 
td::Result<PrivateKeyWithMnemonic> {
+    return container_.try_build<Key>(hash, []() -> 
td::Result<PrivateKeyWithMnemonic> {
       td::SecureString key(32, 1);
       return 
PrivateKeyWithMnemonic::from_private_key(PrivateKey::from_slice(key).move_as_ok(),
 {});
     });
@@ -295,7 +295,7 @@
 
   td::Result<api::SymmetricKeyId> handshake_get_shared_key_id(api::HandshakeId 
handshake_id) {
     TRY_RESULT(handshake, container_.get_unique<Handshake>(handshake_id));
-    TRY_RESULT(shared_secret, std::visit([&](auto &&v) { return 
v.shared_secret(); }, *handshake));
+    TRY_RESULT(shared_secret, std::visit([](auto &&v) { return 
v.shared_secret(); }, *handshake));
     auto hash = to_hash("handshake shared_secret", shared_secret.as_slice());
     return container_.try_build<Key>(hash, [&]() -> 
td::Result<td::SecureString> { return std::move(shared_secret); });
   }
@@ -559,8 +559,8 @@
   td::Result<PublicKey> to_public_key(api::AnyKeyId key_id) const {
     TRY_RESULT(key, container_.get_shared<Key>(key_id));
     return std::visit(
-        td::overloaded([&](const PrivateKeyWithMnemonic &pk) -> 
td::Result<PublicKey> { return pk.to_public_key(); },
-                       [&](const PublicKey &pk) -> td::Result<PublicKey> { 
return pk; },
+        td::overloaded([](const PrivateKeyWithMnemonic &pk) -> 
td::Result<PublicKey> { return pk.to_public_key(); },
+                       [](const PublicKey &pk) -> td::Result<PublicKey> { 
return pk; },
                        [](const auto &) -> td::Result<PublicKey> {
                          return 
td::Status::Error(static_cast<int>(api::ErrorCode::InvalidInput),
                                                   "key_id doesn't contain 
public key");
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/td-git20260303/tde2e/test/e2e.cpp 
new/td-git20260317/tde2e/test/e2e.cpp
--- old/td-git20260303/tde2e/test/e2e.cpp       2026-03-13 07:45:04.603829225 
+0100
+++ new/td-git20260317/tde2e/test/e2e.cpp       2026-04-01 14:40:57.206123661 
+0200
@@ -590,7 +590,7 @@
   }
   void apply_changes(const std::vector<Change> &changes) {
     for (const auto &change_v : changes) {
-      std::visit(td::overloaded([&](const ChangeNoop &) {},
+      std::visit(td::overloaded([](const ChangeNoop &) {},
                                 [&](const ChangeSetValue &change) { 
key_value_state[change.key] = change.value; },
                                 [&](const ChangeSetGroupState &change) { 
group_state = change.group_state; },
                                 [&](const ChangeSetSharedKey &change) { 
shared_key = change.shared_key; }),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/td-git20260303/tdutils/td/utils/port/FileFd.cpp 
new/td-git20260317/tdutils/td/utils/port/FileFd.cpp
--- old/td-git20260303/tdutils/td/utils/port/FileFd.cpp 2026-03-13 
07:45:04.608523490 +0100
+++ new/td-git20260317/tdutils/td/utils/port/FileFd.cpp 2026-04-01 
14:40:57.210901132 +0200
@@ -168,7 +168,7 @@
     if (native_fd < MINIMUM_FILE_DESCRIPTOR) {
       ::close(native_fd);
       LOG(ERROR) << "Receive " << native_fd << " as a file descriptor";
-      int dummy_fd = detail::skip_eintr([&] { return ::open("/dev/null", 
O_RDONLY, 0); });
+      int dummy_fd = detail::skip_eintr([] { return ::open("/dev/null", 
O_RDONLY, 0); });
       if (dummy_fd < 0) {
         return OS_ERROR("Can't open /dev/null");
       }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/td-git20260303/tdutils/td/utils/port/SocketFd.cpp 
new/td-git20260317/tdutils/td/utils/port/SocketFd.cpp
--- old/td-git20260303/tdutils/td/utils/port/SocketFd.cpp       2026-03-13 
07:45:04.608523490 +0100
+++ new/td-git20260317/tdutils/td/utils/port/SocketFd.cpp       2026-04-01 
14:40:57.210901132 +0200
@@ -643,7 +643,7 @@
   while (native_fd.socket() < MINIMUM_FILE_DESCRIPTOR) {
     native_fd.close();
     LOG(ERROR) << "Receive " << native_fd << " as a file descriptor";
-    int dummy_fd = detail::skip_eintr([&] { return ::open("/dev/null", 
O_RDONLY, 0); });
+    int dummy_fd = detail::skip_eintr([] { return ::open("/dev/null", 
O_RDONLY, 0); });
     if (dummy_fd < 0) {
       return OS_ERROR("Can't open /dev/null");
     }

++++++ tdesktop-6.6.3-full.tar.gz -> tdesktop-6.7.1-full.tar.gz ++++++
/work/SRC/openSUSE:Factory/telegram-desktop/tdesktop-6.6.3-full.tar.gz 
/work/SRC/openSUSE:Factory/.telegram-desktop.new.21863/tdesktop-6.7.1-full.tar.gz
 differ: char 5, line 1

Reply via email to