Description: Add deleted_messages update type for regular chats
 Dispatches a deleted_messages update to bots when messages are
 permanently deleted (not cache evictions). Opt-in via
 allowed_updates, disabled by default.
Forwarded: no
Last-Update: 2026-08-08

--- a/telegram-bot-api/Client.cpp
+++ b/telegram-bot-api/Client.cpp
@@ -6236,6 +6236,23 @@ class Client::JsonBusinessMessagesDelete
   const Client *client_;
 };
 
+class Client::JsonDeletedMessages final : public td::Jsonable {
+ public:
+  JsonDeletedMessages(int64 chat_id, const td::vector<int64> &message_ids, const Client *client)
+      : chat_id_(chat_id), message_ids_(message_ids), client_(client) {
+  }
+  void store(td::JsonValueScope *scope) const {
+    auto object = scope->enter_object();
+    object("chat", JsonChat(chat_id_, client_));
+    object("message_ids", td::json_array(message_ids_, as_client_message_id));
+  }
+
+ private:
+  int64 chat_id_;
+  const td::vector<int64> &message_ids_;
+  const Client *client_;
+};
+
 class Client::JsonReceivedGift final : public td::Jsonable {
  public:
   JsonReceivedGift(const td_api::receivedGift *received_gift, bool can_be_managed, const Client *client)
@@ -9567,6 +9584,11 @@ void Client::on_update(object_ptr<td_api
     }
     case td_api::updateDeleteMessages::ID: {
       auto update = move_object_as<td_api::updateDeleteMessages>(result);
+      if (update->is_permanent_ && !update->from_cache_) {
+        add_update(UpdateType::DeletedMessages,
+                   JsonDeletedMessages(update->chat_id_, update->message_ids_, this), 86400,
+                   update->chat_id_ + (static_cast<int64>(11) << 33));
+      }
       td::vector<td::unique_ptr<MessageInfo>> deleted_messages;
       for (auto message_id : update->message_ids_) {
         auto deleted_message = delete_message(update->chat_id_, message_id, update->from_cache_);
@@ -18088,6 +18110,8 @@ td::Slice Client::get_update_type_name(U
       return td::Slice("guest_message");
     case UpdateType::Subscription:
       return td::Slice("subscription");
+    case UpdateType::DeletedMessages:
+      return td::Slice("deleted_messages");
     default:
       UNREACHABLE();
       return td::Slice();
--- a/telegram-bot-api/Client.h
+++ b/telegram-bot-api/Client.h
@@ -248,6 +248,7 @@ class Client final : public WebhookActor
   class JsonManagedBotCreated;
   class JsonManagedBotUpdated;
   class JsonCommunityChatAdded;
+  class JsonDeletedMessages;
   class JsonBotSubscriptionUpdated;
   class JsonGiveawayCreated;
   class JsonGiveaway;
@@ -1511,6 +1512,7 @@ class Client final : public WebhookActor
     ManagedBot,
     GuestMessage,
     Subscription,
+    DeletedMessages,
     Size
   };
 
@@ -1546,12 +1548,13 @@ class Client final : public WebhookActor
 
   bool have_message_access(int64 chat_id) const;
 
-  // by default ChatMember, MessageReaction, and MessageReactionCount updates are disabled
+  // by default ChatMember, MessageReaction, MessageReactionCount, and DeletedMessages updates are disabled
   static constexpr td::uint64 DEFAULT_ALLOWED_UPDATE_TYPES =
       (static_cast<td::uint64>(1) << static_cast<int32>(UpdateType::Size)) - 1 -
       (static_cast<td::uint64>(1) << static_cast<int32>(UpdateType::ChatMember)) -
       (static_cast<td::uint64>(1) << static_cast<int32>(UpdateType::MessageReaction)) -
-      (static_cast<td::uint64>(1) << static_cast<int32>(UpdateType::MessageReactionCount));
+      (static_cast<td::uint64>(1) << static_cast<int32>(UpdateType::MessageReactionCount)) -
+      (static_cast<td::uint64>(1) << static_cast<int32>(UpdateType::DeletedMessages));
 
   object_ptr<td_api::AuthorizationState> authorization_state_;
   bool was_authorized_ = false;
