Add class MessageSelfDestructType.

This commit is contained in:
levlam 2024-01-30 15:07:21 +03:00
parent 437c2d0c6e
commit 3d539f1bcc
11 changed files with 270 additions and 126 deletions

View File

@ -409,6 +409,7 @@ set(TDLIB_SOURCE
td/telegram/MessageReplyHeader.cpp
td/telegram/MessageReplyInfo.cpp
td/telegram/MessageSearchFilter.cpp
td/telegram/MessageSelfDestructType.cpp
td/telegram/MessageSender.cpp
td/telegram/MessagesInfo.cpp
td/telegram/MessagesManager.cpp
@ -712,6 +713,7 @@ set(TDLIB_SOURCE
td/telegram/MessageReplyHeader.h
td/telegram/MessageReplyInfo.h
td/telegram/MessageSearchFilter.h
td/telegram/MessageSelfDestructType.h
td/telegram/MessageSender.h
td/telegram/MessagesInfo.h
td/telegram/MessagesManager.h

View File

@ -2834,28 +2834,10 @@ static Result<InputMessageContent> create_input_message_content(
UNREACHABLE();
}
if (self_destruct_type != nullptr && dialog_id.get_type() != DialogType::User) {
TRY_RESULT(ttl, MessageSelfDestructType::get_message_self_destruct_type(std::move(self_destruct_type)));
if (!ttl.is_empty() && dialog_id.get_type() != DialogType::User) {
return Status::Error(400, "Messages can self-destruct only in private chats");
}
int32 ttl = 0;
if (self_destruct_type != nullptr) {
switch (self_destruct_type->get_id()) {
case td_api::messageSelfDestructTypeTimer::ID: {
ttl = static_cast<const td_api::messageSelfDestructTypeTimer *>(self_destruct_type.get())->self_destruct_time_;
static constexpr int32 MAX_PRIVATE_MESSAGE_TTL = 60; // server side limit
if (ttl <= 0 || ttl > MAX_PRIVATE_MESSAGE_TTL) {
return Status::Error(400, "Invalid message content self-destruct time specified");
}
break;
}
case td_api::messageSelfDestructTypeImmediately::ID:
ttl = 0x7FFFFFFF;
break;
default:
UNREACHABLE();
}
}
return InputMessageContent{std::move(content), disable_web_page_preview, invert_media, clear_draft, ttl,
via_bot_user_id, std::move(emoji)};
@ -3174,7 +3156,7 @@ SecretInputMedia get_secret_input_media(const MessageContent *content, Td *td,
static tl_object_ptr<telegram_api::InputMedia> get_input_media_impl(
const MessageContent *content, Td *td, tl_object_ptr<telegram_api::InputFile> input_file,
tl_object_ptr<telegram_api::InputFile> input_thumbnail, int32 ttl, const string &emoji) {
tl_object_ptr<telegram_api::InputFile> input_thumbnail, MessageSelfDestructType ttl, const string &emoji) {
if (!can_have_input_media(td, content, false)) {
return nullptr;
}
@ -3225,7 +3207,8 @@ static tl_object_ptr<telegram_api::InputMedia> get_input_media_impl(
}
case MessageContentType::Photo: {
const auto *m = static_cast<const MessagePhoto *>(content);
return photo_get_input_media(td->file_manager_.get(), m->photo, std::move(input_file), ttl, m->has_spoiler);
return photo_get_input_media(td->file_manager_.get(), m->photo, std::move(input_file), ttl.get_input_ttl(),
m->has_spoiler);
}
case MessageContentType::Poll: {
const auto *m = static_cast<const MessagePoll *>(content);
@ -3246,17 +3229,17 @@ static tl_object_ptr<telegram_api::InputMedia> get_input_media_impl(
}
case MessageContentType::Video: {
const auto *m = static_cast<const MessageVideo *>(content);
return td->videos_manager_->get_input_media(m->file_id, std::move(input_file), std::move(input_thumbnail), ttl,
m->has_spoiler);
return td->videos_manager_->get_input_media(m->file_id, std::move(input_file), std::move(input_thumbnail),
ttl.get_input_ttl(), m->has_spoiler);
}
case MessageContentType::VideoNote: {
const auto *m = static_cast<const MessageVideoNote *>(content);
return td->video_notes_manager_->get_input_media(m->file_id, std::move(input_file), std::move(input_thumbnail),
ttl);
ttl.get_input_ttl());
}
case MessageContentType::VoiceNote: {
const auto *m = static_cast<const MessageVoiceNote *>(content);
return td->voice_notes_manager_->get_input_media(m->file_id, std::move(input_file), ttl);
return td->voice_notes_manager_->get_input_media(m->file_id, std::move(input_file), ttl.get_input_ttl());
}
case MessageContentType::Text:
case MessageContentType::Unsupported:
@ -3316,8 +3299,8 @@ static tl_object_ptr<telegram_api::InputMedia> get_input_media_impl(
tl_object_ptr<telegram_api::InputMedia> get_input_media(const MessageContent *content, Td *td,
tl_object_ptr<telegram_api::InputFile> input_file,
tl_object_ptr<telegram_api::InputFile> input_thumbnail,
FileId file_id, FileId thumbnail_file_id, int32 ttl,
const string &emoji, bool force) {
FileId file_id, FileId thumbnail_file_id,
MessageSelfDestructType ttl, const string &emoji, bool force) {
bool had_input_file = input_file != nullptr;
bool had_input_thumbnail = input_thumbnail != nullptr;
auto input_media = get_input_media_impl(content, td, std::move(input_file), std::move(input_thumbnail), ttl, emoji);
@ -3349,8 +3332,8 @@ tl_object_ptr<telegram_api::InputMedia> get_input_media(const MessageContent *co
return input_media;
}
tl_object_ptr<telegram_api::InputMedia> get_input_media(const MessageContent *content, Td *td, int32 ttl,
const string &emoji, bool force) {
tl_object_ptr<telegram_api::InputMedia> get_input_media(const MessageContent *content, Td *td,
MessageSelfDestructType ttl, const string &emoji, bool force) {
auto input_media = get_input_media_impl(content, td, nullptr, nullptr, ttl, emoji);
auto file_reference = FileManager::extract_file_reference(input_media);
if (file_reference == FileReferenceView::invalid_file_reference()) {
@ -5873,8 +5856,8 @@ unique_ptr<MessageContent> get_secret_message_content(
unique_ptr<MessageContent> get_message_content(Td *td, FormattedText message,
tl_object_ptr<telegram_api::MessageMedia> &&media_ptr,
DialogId owner_dialog_id, int32 message_date, bool is_content_read,
UserId via_bot_user_id, int32 *ttl, bool *disable_web_page_preview,
const char *source) {
UserId via_bot_user_id, MessageSelfDestructType *ttl,
bool *disable_web_page_preview, const char *source) {
if (!td->auth_manager_->was_authorized() && !G()->close_flag() && media_ptr != nullptr &&
media_ptr->get_id() != telegram_api::messageMediaEmpty::ID) {
LOG(ERROR) << "Receive without authorization from " << source << ": " << to_string(media_ptr);
@ -5911,7 +5894,7 @@ unique_ptr<MessageContent> get_message_content(Td *td, FormattedText message,
}
if (ttl != nullptr && (media->flags_ & telegram_api::messageMediaPhoto::TTL_SECONDS_MASK) != 0) {
*ttl = media->ttl_seconds_;
*ttl = MessageSelfDestructType(media->ttl_seconds_, true);
}
return make_unique<MessagePhoto>(std::move(photo), std::move(message), media->spoiler_);
}
@ -6002,7 +5985,7 @@ unique_ptr<MessageContent> get_message_content(Td *td, FormattedText message,
CHECK(document_id == telegram_api::document::ID);
if (ttl != nullptr && (media->flags_ & telegram_api::messageMediaDocument::TTL_SECONDS_MASK) != 0) {
*ttl = media->ttl_seconds_;
*ttl = MessageSelfDestructType(media->ttl_seconds_, true);
}
return get_document_message_content(td, move_tl_object_as<telegram_api::document>(document_ptr), owner_dialog_id,
std::move(message), is_content_read, !media->nopremium_, media->spoiler_,

View File

@ -18,6 +18,7 @@
#include "td/telegram/MessageEntity.h"
#include "td/telegram/MessageFullId.h"
#include "td/telegram/MessageId.h"
#include "td/telegram/MessageSelfDestructType.h"
#include "td/telegram/Photo.h"
#include "td/telegram/ReplyMarkup.h"
#include "td/telegram/secret_api.h"
@ -65,12 +66,12 @@ struct InputMessageContent {
bool disable_web_page_preview = false;
bool invert_media = false;
bool clear_draft = false;
int32 ttl = 0;
MessageSelfDestructType ttl;
UserId via_bot_user_id;
string emoji;
InputMessageContent(unique_ptr<MessageContent> &&content, bool disable_web_page_preview, bool invert_media,
bool clear_draft, int32 ttl, UserId via_bot_user_id, string emoji)
bool clear_draft, MessageSelfDestructType ttl, UserId via_bot_user_id, string emoji)
: content(std::move(content))
, disable_web_page_preview(disable_web_page_preview)
, invert_media(invert_media)
@ -121,11 +122,11 @@ SecretInputMedia get_secret_input_media(const MessageContent *content, Td *td,
tl_object_ptr<telegram_api::InputMedia> get_input_media(const MessageContent *content, Td *td,
tl_object_ptr<telegram_api::InputFile> input_file,
tl_object_ptr<telegram_api::InputFile> input_thumbnail,
FileId file_id, FileId thumbnail_file_id, int32 ttl,
const string &emoji, bool force);
FileId file_id, FileId thumbnail_file_id,
MessageSelfDestructType ttl, const string &emoji, bool force);
tl_object_ptr<telegram_api::InputMedia> get_input_media(const MessageContent *content, Td *td, int32 ttl,
const string &emoji, bool force);
tl_object_ptr<telegram_api::InputMedia> get_input_media(const MessageContent *content, Td *td,
MessageSelfDestructType ttl, const string &emoji, bool force);
tl_object_ptr<telegram_api::InputMedia> get_fake_input_media(Td *td, tl_object_ptr<telegram_api::InputFile> input_file,
FileId file_id);
@ -218,8 +219,8 @@ unique_ptr<MessageContent> get_secret_message_content(
unique_ptr<MessageContent> get_message_content(Td *td, FormattedText message_text,
tl_object_ptr<telegram_api::MessageMedia> &&media_ptr,
DialogId owner_dialog_id, int32 message_date, bool is_content_read,
UserId via_bot_user_id, int32 *ttl, bool *disable_web_page_preview,
const char *source);
UserId via_bot_user_id, MessageSelfDestructType *ttl,
bool *disable_web_page_preview, const char *source);
enum class MessageContentDupType : int32 {
Send, // normal message sending

View File

@ -226,10 +226,7 @@ bool is_homogenous_media_group_content(MessageContentType content_type) {
return content_type == MessageContentType::Audio || content_type == MessageContentType::Document;
}
bool is_secret_message_content(int32 ttl, MessageContentType content_type) {
if (ttl <= 0 || ttl > 60) {
return ttl == 0x7FFFFFFF;
}
bool can_be_secret_message_content(MessageContentType content_type) {
switch (content_type) {
case MessageContentType::Animation:
case MessageContentType::Audio:

View File

@ -88,7 +88,7 @@ bool is_allowed_media_group_content(MessageContentType content_type);
bool is_homogenous_media_group_content(MessageContentType content_type);
bool is_secret_message_content(int32 ttl, MessageContentType content_type);
bool can_be_secret_message_content(MessageContentType content_type);
bool is_service_message_content(MessageContentType content_type);

View File

@ -113,7 +113,7 @@ Result<MessageExtendedMedia> MessageExtendedMedia::get_message_extended_media(
}
TRY_RESULT(input_message_content,
get_input_message_content(owner_dialog_id, std::move(extended_media_content), td, is_premium));
if (input_message_content.ttl != 0) {
if (!input_message_content.ttl.is_empty()) {
return Status::Error("Can't use self-destructing extended media");
}

View File

@ -0,0 +1,90 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
//
// 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/MessageSelfDestructType.h"
namespace td {
bool MessageSelfDestructType::is_valid() const {
return ttl_ > 0;
}
bool MessageSelfDestructType::is_empty() const {
return ttl_ == 0;
}
bool MessageSelfDestructType::is_immediate() const {
return ttl_ == 0x7FFFFFFF;
}
bool MessageSelfDestructType::is_secret_message_content(MessageContentType content_type) {
if (ttl_ <= 0 || ttl_ > 60) {
return is_immediate();
}
return can_be_secret_message_content(content_type);
}
void MessageSelfDestructType::ensure_at_least(int32 ttl) {
if (is_immediate() || ttl_ >= ttl || ttl_ <= 0 || ttl <= 0) {
return;
}
ttl_ = ttl;
}
Result<MessageSelfDestructType> MessageSelfDestructType::get_message_self_destruct_type(
td_api::object_ptr<td_api::MessageSelfDestructType> &&self_destruct_type) {
if (self_destruct_type == nullptr) {
return MessageSelfDestructType();
}
switch (self_destruct_type->get_id()) {
case td_api::messageSelfDestructTypeTimer::ID: {
auto ttl =
static_cast<const td_api::messageSelfDestructTypeTimer *>(self_destruct_type.get())->self_destruct_time_;
static constexpr int32 MAX_PRIVATE_MESSAGE_TTL = 60; // server side limit
if (ttl <= 0 || ttl > MAX_PRIVATE_MESSAGE_TTL) {
return Status::Error(400, "Invalid message content self-destruct time specified");
}
return MessageSelfDestructType(ttl, true);
}
case td_api::messageSelfDestructTypeImmediately::ID:
return MessageSelfDestructType(0x7FFFFFFF, true);
default:
UNREACHABLE();
return MessageSelfDestructType();
}
}
td_api::object_ptr<td_api::MessageSelfDestructType> MessageSelfDestructType::get_message_self_desctruct_type_object()
const {
if (is_immediate()) {
return td_api::make_object<td_api::messageSelfDestructTypeImmediately>();
}
if (!is_empty()) {
return td_api::make_object<td_api::messageSelfDestructTypeTimer>(ttl_);
}
return nullptr;
}
int32 MessageSelfDestructType::get_input_ttl() const {
return ttl_;
}
bool operator==(const MessageSelfDestructType &lhs, const MessageSelfDestructType &rhs) {
return lhs.ttl_ == rhs.ttl_;
}
StringBuilder &operator<<(StringBuilder &string_builder, const MessageSelfDestructType &message_ttl) {
if (message_ttl.is_empty()) {
return string_builder << "non-self-destruct";
}
if (message_ttl.is_immediate()) {
return string_builder << "self-destruct immediately";
}
return string_builder << "self-destruct at " << message_ttl.get_input_ttl();
}
} // namespace td

View File

@ -0,0 +1,73 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
//
// 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/MessageContentType.h"
#include "td/telegram/td_api.h"
#include "td/utils/common.h"
#include "td/utils/StringBuilder.h"
#include "td/utils/tl_helpers.h"
#include <type_traits>
namespace td {
class MessageSelfDestructType {
int32 ttl_ = 0;
friend bool operator==(const MessageSelfDestructType &lhs, const MessageSelfDestructType &rhs);
public:
MessageSelfDestructType() = default;
template <class T, typename = std::enable_if_t<std::is_convertible<T, int32>::value>>
MessageSelfDestructType(T ttl) = delete;
MessageSelfDestructType(int32 ttl, bool allow_immediate) : ttl_(ttl) {
if (!allow_immediate && is_immediate()) {
ttl_ = 0x7FFFFFFE;
}
}
bool is_valid() const;
bool is_empty() const;
bool is_immediate() const;
bool is_secret_message_content(MessageContentType content_type);
void ensure_at_least(int32 ttl);
static Result<MessageSelfDestructType> get_message_self_destruct_type(
td_api::object_ptr<td_api::MessageSelfDestructType> &&self_destruct_type);
td_api::object_ptr<td_api::MessageSelfDestructType> get_message_self_desctruct_type_object() const;
int32 get_input_ttl() const;
template <class StorerT>
void store(StorerT &storer) const {
td::store(ttl_, storer);
}
template <class ParserT>
void parse(ParserT &parser) {
td::parse(ttl_, parser);
}
};
bool operator==(const MessageSelfDestructType &lhs, const MessageSelfDestructType &rhs);
inline bool operator!=(const MessageSelfDestructType &lhs, const MessageSelfDestructType &rhs) {
return !(lhs == rhs);
}
StringBuilder &operator<<(StringBuilder &string_builder, const MessageSelfDestructType &message_self_destruct_type);
} // namespace td

View File

@ -4277,7 +4277,7 @@ void MessagesManager::Message::store(StorerT &storer) const {
bool is_via_bot = via_bot_user_id.is_valid();
bool has_view_count = view_count > 0;
bool has_reply_markup = reply_markup != nullptr;
bool has_ttl = ttl != 0;
bool has_ttl = ttl.is_valid();
bool has_author_signature = !author_signature.empty();
bool has_media_album_id = media_album_id != 0;
bool has_send_date = message_id.is_yet_unsent() && send_date != 0;
@ -4826,8 +4826,7 @@ void MessagesManager::Message::parse(ParserT &parser) {
}
CHECK(content != nullptr);
is_content_secret |=
is_secret_message_content(ttl, content->get_type()); // repair is_content_secret for old messages
is_content_secret |= ttl.is_secret_message_content(content->get_type()); // repair is_content_secret for old messages
if (hide_edit_date && content->get_type() == MessageContentType::LiveLocation) {
hide_edit_date = false;
}
@ -5827,7 +5826,7 @@ int32 MessagesManager::get_message_index_mask(DialogId dialog_id, const Message
index_mask |= message_search_filter_index_mask(MessageSearchFilter::Pinned);
}
// retain second condition just in case
if (m->is_content_secret || (m->ttl > 0 && !is_secret)) {
if (m->is_content_secret || (!m->ttl.is_empty() && !is_secret)) {
return index_mask;
}
index_mask |= get_message_content_index_mask(m->content.get(), td_, m->is_outgoing);
@ -6040,11 +6039,11 @@ void MessagesManager::on_update_service_notification(tl_object_ptr<telegram_api:
auto message_text = get_message_text(contacts_manager, std::move(update->message_), std::move(update->entities_),
skip_new_entities, !is_user, date, false, "on_update_service_notification");
DialogId owner_dialog_id = is_user ? get_service_notifications_dialog()->dialog_id : DialogId();
int32 ttl = 0;
MessageSelfDestructType ttl;
bool disable_web_page_preview = false;
auto content = get_message_content(td_, std::move(message_text), std::move(update->media_), owner_dialog_id, date,
false, UserId(), &ttl, &disable_web_page_preview, "updateServiceNotification");
bool is_content_secret = is_secret_message_content(ttl, content->get_type());
bool is_content_secret = ttl.is_secret_message_content(content->get_type());
if (update->popup_) {
send_closure(
@ -7766,7 +7765,7 @@ ChatReactions MessagesManager::get_dialog_active_reactions(const Dialog *d) cons
ChatReactions MessagesManager::get_message_active_reactions(const Dialog *d, const Message *m) const {
CHECK(d != nullptr);
CHECK(m != nullptr);
if (is_service_message_content(m->content->get_type()) || m->ttl > 0 || !m->message_id.is_valid() ||
if (is_service_message_content(m->content->get_type()) || !m->ttl.is_empty() || !m->message_id.is_valid() ||
!m->message_id.is_server()) {
return ChatReactions();
}
@ -9722,7 +9721,7 @@ bool MessagesManager::can_forward_message(DialogId from_dialog_id, const Message
if (m == nullptr) {
return false;
}
if (m->ttl > 0) {
if (!m->ttl.is_empty()) {
return false;
}
if (m->message_id.is_scheduled()) {
@ -12128,9 +12127,9 @@ void MessagesManager::ttl_read_history_impl(DialogId dialog_id, bool is_outgoing
}
void MessagesManager::ttl_on_view(const Dialog *d, Message *m, double view_date, double now) {
if (m->ttl > 0 && m->ttl_expires_at == 0 && !m->message_id.is_scheduled() && !m->message_id.is_yet_unsent() &&
if (!m->ttl.is_empty() && m->ttl_expires_at == 0 && !m->message_id.is_scheduled() && !m->message_id.is_yet_unsent() &&
!m->is_failed_to_send && !m->is_content_secret) {
m->ttl_expires_at = m->ttl + view_date;
m->ttl_expires_at = m->ttl.get_input_ttl() + view_date;
ttl_register_message(d->dialog_id, m, now);
on_message_changed(d, m, true, "ttl_on_view");
}
@ -12138,10 +12137,10 @@ void MessagesManager::ttl_on_view(const Dialog *d, Message *m, double view_date,
bool MessagesManager::ttl_on_open(Dialog *d, Message *m, double now, bool is_local_read, int32 read_date) {
CHECK(!m->message_id.is_scheduled());
if (m->ttl > 0 && m->ttl_expires_at == 0) {
if (!m->ttl.is_empty() && m->ttl_expires_at == 0) {
int32 passed_after_read_time = 0;
auto can_destroy_immediately = [&] {
if (m->ttl == 0x7FFFFFFF) {
if (m->ttl.is_immediate()) {
return true;
}
if (is_local_read) {
@ -12151,7 +12150,7 @@ bool MessagesManager::ttl_on_open(Dialog *d, Message *m, double now, bool is_loc
return d->dialog_id.get_type() != DialogType::SecretChat;
}
passed_after_read_time = max(G()->unix_time() - read_date, 0);
if (m->ttl <= passed_after_read_time) {
if (m->ttl.get_input_ttl() <= passed_after_read_time) {
return true;
}
return false;
@ -12159,7 +12158,7 @@ bool MessagesManager::ttl_on_open(Dialog *d, Message *m, double now, bool is_loc
if (can_destroy_immediately) {
on_message_ttl_expired(d, m);
} else {
m->ttl_expires_at = m->ttl + now - passed_after_read_time;
m->ttl_expires_at = m->ttl.get_input_ttl() + now - passed_after_read_time;
ttl_register_message(d->dialog_id, m, now);
}
return true;
@ -12202,7 +12201,7 @@ void MessagesManager::ttl_unregister_message(DialogId dialog_id, const Message *
auto it = ttl_nodes_.find(TtlNode(dialog_id, m->message_id, false));
// expect m->ttl == 0, but m->ttl_expires_at > 0 from binlog
// expect m->ttl.is_empty(), but m->ttl_expires_at > 0 from binlog
CHECK(it != ttl_nodes_.end());
auto *heap_node = it->as_heap_node();
@ -12269,7 +12268,7 @@ void MessagesManager::ttl_update_timeout(double now) {
void MessagesManager::on_message_ttl_expired(Dialog *d, Message *m) {
CHECK(d != nullptr);
CHECK(m != nullptr);
CHECK(m->ttl > 0);
CHECK(m->ttl.is_valid());
CHECK(d->dialog_id.get_type() != DialogType::SecretChat);
ttl_unregister_message(d->dialog_id, m, "on_message_ttl_expired");
unregister_message_content(td_, m->content.get(), {d->dialog_id, m->message_id}, "on_message_ttl_expired");
@ -12285,11 +12284,11 @@ void MessagesManager::on_message_ttl_expired_impl(Dialog *d, Message *m, bool is
CHECK(m != nullptr);
CHECK(m->message_id.is_valid());
CHECK(!m->message_id.is_yet_unsent());
CHECK(m->ttl > 0);
CHECK(m->ttl.is_valid());
CHECK(d->dialog_id.get_type() != DialogType::SecretChat);
delete_message_files(d->dialog_id, m);
update_expired_message_content(m->content);
m->ttl = 0;
m->ttl = {};
m->ttl_expires_at = 0;
if (m->reply_markup != nullptr) {
if (m->reply_markup->type != ReplyMarkup::Type::InlineKeyboard) {
@ -12971,7 +12970,7 @@ void MessagesManager::on_get_secret_message(SecretChatId secret_chat_id, UserId
message_info.sender_user_id = user_id;
message_info.date = date;
message_info.random_id = message->random_id_;
message_info.ttl = min(message->ttl_, 0x7FFFFFFE);
message_info.ttl = MessageSelfDestructType(message->ttl_, false);
message_info.has_unread_content = true;
message_info.is_silent = message->silent_;
message_info.media_album_id = message->grouped_id_;
@ -13453,16 +13452,15 @@ std::pair<DialogId, unique_ptr<MessagesManager::Message>> MessagesManager::creat
ttl_period = 0;
}
int32 ttl = message_info.ttl;
if (dialog_type == DialogType::SecretChat && ttl == 0x7FFFFFFF) {
ttl = 0x7FFFFFFE;
}
bool is_content_secret = is_secret_message_content(ttl, content_type); // must be calculated before TTL is adjusted
if (ttl < 0 || (message_id.is_scheduled() && ttl != 0)) {
LOG(ERROR) << "Wrong self-destruct time " << ttl << " received in " << message_id << " in " << dialog_id;
ttl = 0;
} else if (ttl > 0) {
ttl = max(ttl, get_message_content_duration(message_info.content.get(), td_) + 1);
auto ttl = message_info.ttl;
bool is_content_secret = ttl.is_secret_message_content(content_type); // must be calculated before TTL is adjusted
if (!ttl.is_empty()) {
if (!ttl.is_valid() || message_id.is_scheduled()) {
LOG(ERROR) << "Wrong " << ttl << " received in " << message_id << " in " << dialog_id;
ttl = {};
} else {
ttl.ensure_at_least(get_message_content_duration(message_info.content.get(), td_) + 1);
}
}
if (message_id.is_scheduled()) {
@ -13516,7 +13514,7 @@ std::pair<DialogId, unique_ptr<MessagesManager::Message>> MessagesManager::creat
bool noforwards = message_info.noforwards;
bool is_expired = is_expired_message_content(content_type);
if (is_expired) {
CHECK(ttl == 0); // self-destruct time is ignored/set to 0 if the message has already been expired
CHECK(ttl.is_empty()); // self-destruct time is ignored/set to 0 if the message has already been expired
message_info.reply_header.replied_message_info_ = {};
reply_to_story_full_id = StoryFullId();
noforwards = false;
@ -14405,7 +14403,7 @@ void MessagesManager::on_update_sent_text_message(int64 random_id,
reregister_message_content(td_, m->content.get(), new_content.get(), message_full_id,
"on_update_sent_text_message");
m->content = std::move(new_content);
m->is_content_secret = is_secret_message_content(m->ttl, MessageContentType::Text);
m->is_content_secret = m->ttl.is_secret_message_content(MessageContentType::Text);
if (need_update) {
send_update_message_content(d, m, true, "on_update_sent_text_message");
@ -23144,7 +23142,8 @@ tl_object_ptr<td_api::message> MessagesManager::get_message_object(DialogId dial
(!m->forward_info->get_last_dialog_id().is_valid() && !m->forward_info->get_origin().is_sender_hidden());
}
double ttl_expires_in = m->ttl_expires_at != 0 ? clamp(m->ttl_expires_at - Time::now(), 1e-3, m->ttl - 1e-3) : 0.0;
double ttl_expires_in =
m->ttl_expires_at != 0 ? clamp(m->ttl_expires_at - Time::now(), 1e-3, m->ttl.get_input_ttl() - 1e-3) : 0.0;
double auto_delete_in =
m->ttl_period == 0 ? 0.0 : clamp(m->date + m->ttl_period - G()->server_time(), 1e-3, m->ttl_period - 1e-3);
auto sender = get_message_sender_object_const(td_, m->sender_user_id, m->sender_dialog_id, source);
@ -23188,15 +23187,7 @@ tl_object_ptr<td_api::message> MessagesManager::get_message_object(DialogId dial
auto has_timestamped_media = reply_to == nullptr || m->max_own_media_timestamp >= 0;
auto reply_markup = get_reply_markup_object(td_->contacts_manager_.get(), m->reply_markup);
auto content = get_message_message_content_object(dialog_id, m);
auto self_destruct_type = [&]() -> td_api::object_ptr<td_api::MessageSelfDestructType> {
if (m->ttl == 0x7FFFFFFF) {
return td_api::make_object<td_api::messageSelfDestructTypeImmediately>();
}
if (m->ttl > 0) {
return td_api::make_object<td_api::messageSelfDestructTypeTimer>(m->ttl);
}
return nullptr;
}();
auto self_destruct_type = m->ttl.get_message_self_desctruct_type_object();
return td_api::make_object<td_api::message>(
m->message_id.get(), std::move(sender), get_chat_id_object(dialog_id, "get_message_object"),
@ -23415,11 +23406,13 @@ unique_ptr<MessagesManager::Message> MessagesManager::create_message_to_send(
if (dialog_type == DialogType::SecretChat) {
CHECK(!is_scheduled);
m->ttl = min(td_->contacts_manager_->get_secret_chat_ttl(dialog_id.get_secret_chat_id()), 0x7FFFFFFE);
if (is_service_message_content(m->content->get_type())) {
m->ttl = 0;
m->ttl = {};
} else {
m->ttl =
MessageSelfDestructType(td_->contacts_manager_->get_secret_chat_ttl(dialog_id.get_secret_chat_id()), false);
}
m->is_content_secret = is_secret_message_content(m->ttl, m->content->get_type());
m->is_content_secret = m->ttl.is_secret_message_content(m->content->get_type());
}
if (dialog_id == DialogId(my_id)) {
m->saved_messages_topic_id = SavedMessagesTopicId(dialog_id, m->forward_info.get(), m->real_forward_from_dialog_id);
@ -23993,9 +23986,9 @@ Result<td_api::object_ptr<td_api::message>> MessagesManager::send_message(
m->via_bot_user_id = message_content.via_bot_user_id;
m->disable_web_page_preview = message_content.disable_web_page_preview;
m->clear_draft = message_content.clear_draft;
if (message_content.ttl > 0) {
if (message_content.ttl.is_valid()) {
m->ttl = message_content.ttl;
m->is_content_secret = is_secret_message_content(m->ttl, m->content->get_type());
m->is_content_secret = m->ttl.is_secret_message_content(m->content->get_type());
}
m->send_emoji = std::move(message_content.emoji);
@ -24065,7 +24058,8 @@ Result<InputMessageContent> MessagesManager::process_input_message_content(
}
return InputMessageContent(std::move(content), get_message_disable_web_page_preview(copied_message),
copied_message->invert_media, false, 0, UserId(), copied_message->send_emoji);
copied_message->invert_media, false, MessageSelfDestructType(), UserId(),
copied_message->send_emoji);
}
bool is_premium = td_->option_manager_->get_option_boolean("is_premium");
@ -24135,9 +24129,10 @@ Result<MessagesManager::MessageSendOptions> MessagesManager::process_message_sen
}
Status MessagesManager::can_use_message_send_options(const MessageSendOptions &options,
const unique_ptr<MessageContent> &content, int32 ttl) {
const unique_ptr<MessageContent> &content,
MessageSelfDestructType ttl) {
if (options.schedule_date != 0) {
if (ttl > 0) {
if (ttl.is_valid()) {
return Status::Error(400, "Can't send scheduled self-destructing messages");
}
if (content->get_type() == MessageContentType::LiveLocation) {
@ -24265,9 +24260,9 @@ Result<td_api::object_ptr<td_api::messages>> MessagesManager::send_message_group
}
auto ttl = message_content.ttl;
if (ttl > 0) {
if (ttl.is_valid()) {
m->ttl = ttl;
m->is_content_secret = is_secret_message_content(m->ttl, m->content->get_type());
m->is_content_secret = m->ttl.is_secret_message_content(m->content->get_type());
}
m->media_album_id = media_album_id;
@ -24544,7 +24539,7 @@ void MessagesManager::send_secret_message(DialogId dialog_id, const Message *m,
send_closure(
td_->secret_chats_manager_, &SecretChatsManager::send_message, dialog_id.get_secret_chat_id(),
make_tl_object<secret_api::decryptedMessage>(
flags, false /*ignored*/, random_id, m->ttl,
flags, false /*ignored*/, random_id, m->ttl.get_input_ttl(),
m->content->get_type() == MessageContentType::Text ? text->text : string(), std::move(media.decrypted_media_),
std::move(entities), td_->contacts_manager_->get_user_first_username(m->via_bot_user_id),
m->reply_to_random_id, -m->media_album_id),
@ -25132,7 +25127,7 @@ Result<td_api::object_ptr<td_api::message>> MessagesManager::send_inline_query_r
}
auto input_reply_to = get_message_input_reply_to(d, top_thread_message_id, std::move(reply_to), false);
TRY_STATUS(can_use_message_send_options(message_send_options, content->message_content, 0));
TRY_STATUS(can_use_message_send_options(message_send_options, content->message_content, MessageSelfDestructType()));
TRY_STATUS(can_send_message_content(dialog_id, content->message_content.get(), false, true, td_));
TRY_STATUS(can_use_top_thread_message_id(d, top_thread_message_id, input_reply_to));
@ -25799,7 +25794,7 @@ void MessagesManager::edit_message_media(MessageFullId message_full_id,
old_message_content_type != MessageContentType::Photo && old_message_content_type != MessageContentType::Video) {
return promise.set_error(Status::Error(400, "There is no media in the message to edit"));
}
if (m->ttl > 0) {
if (!m->ttl.is_empty()) {
return promise.set_error(Status::Error(400, "Can't edit media in self-destructing message"));
}
@ -25808,7 +25803,7 @@ void MessagesManager::edit_message_media(MessageFullId message_full_id,
return promise.set_error(r_input_message_content.move_as_error());
}
InputMessageContent content = r_input_message_content.move_as_ok();
if (content.ttl > 0) {
if (!content.ttl.is_empty()) {
return promise.set_error(Status::Error(400, "Can't enable self-destruction for media"));
}
@ -26029,7 +26024,7 @@ void MessagesManager::edit_inline_message_media(const string &inline_message_id,
return promise.set_error(r_input_message_content.move_as_error());
}
InputMessageContent content = r_input_message_content.move_as_ok();
if (content.ttl > 0) {
if (!content.ttl.is_empty()) {
return promise.set_error(Status::Error(400, "Can't enable self-destruction for media"));
}
@ -26043,7 +26038,7 @@ void MessagesManager::edit_inline_message_media(const string &inline_message_id,
return promise.set_error(Status::Error(400, "Invalid inline message identifier specified"));
}
auto input_media = get_input_media(content.content.get(), td_, 0, string(), true);
auto input_media = get_input_media(content.content.get(), td_, MessageSelfDestructType(), string(), true);
if (input_media == nullptr) {
return promise.set_error(Status::Error(400, "Invalid message content specified"));
}
@ -26927,7 +26922,8 @@ Result<MessagesManager::ForwardedMessages> MessagesManager::get_forwarded_messag
continue;
}
auto can_use_options_status = can_use_message_send_options(message_send_options, content, 0);
auto can_use_options_status =
can_use_message_send_options(message_send_options, content, MessageSelfDestructType());
if (can_use_options_status.is_error()) {
LOG(INFO) << "Can't forward " << message_id << ": " << can_send_status.message();
continue;
@ -27506,14 +27502,14 @@ Result<MessageId> MessagesManager::add_local_message(
m->disable_web_page_preview = message_content.disable_web_page_preview;
m->clear_draft = message_content.clear_draft;
if (dialog_type == DialogType::SecretChat) {
m->ttl = min(td_->contacts_manager_->get_secret_chat_ttl(dialog_id.get_secret_chat_id()), 0x7FFFFFFE);
if (is_service_message_content(m->content->get_type())) {
m->ttl = 0;
if (!is_service_message_content(m->content->get_type())) {
m->ttl =
MessageSelfDestructType(td_->contacts_manager_->get_secret_chat_ttl(dialog_id.get_secret_chat_id()), false);
}
} else if (message_content.ttl > 0) {
} else if (message_content.ttl.is_valid()) {
m->ttl = message_content.ttl;
}
m->is_content_secret = is_secret_message_content(m->ttl, m->content->get_type());
m->is_content_secret = m->ttl.is_secret_message_content(m->content->get_type());
m->send_emoji = std::move(message_content.emoji);
if (dialog_id == DialogId(my_id)) {
m->saved_messages_topic_id = SavedMessagesTopicId(dialog_id, m->forward_info.get(), DialogId());
@ -32982,7 +32978,7 @@ MessagesManager::Message *MessagesManager::add_message_to_dialog(Dialog *d, uniq
d->has_unload_timeout = true;
}
if (message->ttl > 0 && message->ttl_expires_at != 0) {
if (message->ttl.is_valid() && message->ttl_expires_at != 0) {
auto now = Time::now();
if (message->ttl_expires_at <= now) {
if (dialog_type == DialogType::SecretChat) {
@ -33284,9 +33280,9 @@ MessagesManager::Message *MessagesManager::add_scheduled_message_to_dialog(Dialo
debug_add_message_to_dialog_fail_reason_ = "skip adding scheduled message to secret chat";
return nullptr;
}
if (message->ttl != 0 || message->ttl_expires_at != 0) {
LOG(ERROR) << "Tried to add " << message_id << " with self-destruct timer " << message->ttl << '/'
<< message->ttl_expires_at << " to " << dialog_id << " from " << source;
if (message->ttl != MessageSelfDestructType() || message->ttl_expires_at != 0) {
LOG(ERROR) << "Tried to add " << message_id << " with " << message->ttl << '/' << message->ttl_expires_at << " to "
<< dialog_id << " from " << source;
debug_add_message_to_dialog_fail_reason_ = "skip adding secret scheduled message";
return nullptr;
}
@ -34287,7 +34283,7 @@ bool MessagesManager::need_message_changed_warning(const Message *old_message) {
// original message may be edited
return false;
}
if (old_message->ttl > 0) {
if (old_message->ttl.is_valid()) {
// message can expire
return false;
}
@ -34310,7 +34306,7 @@ bool MessagesManager::update_message_content(DialogId dialog_id, Message *old_me
auto old_file_id = get_message_content_any_file_id(old_content.get());
bool need_finish_upload = old_file_id.is_valid() && need_merge_files;
if (old_content_type != new_content_type) {
if (old_message->ttl > 0 && old_message->ttl_expires_at > 0 &&
if (old_message->ttl.is_valid() && old_message->ttl_expires_at > 0 &&
((new_content_type == MessageContentType::ExpiredPhoto && old_content_type == MessageContentType::Photo) ||
(new_content_type == MessageContentType::ExpiredVideo && old_content_type == MessageContentType::Video) ||
(new_content_type == MessageContentType::ExpiredVideoNote &&
@ -34322,7 +34318,7 @@ bool MessagesManager::update_message_content(DialogId dialog_id, Message *old_me
need_update = true;
LOG(INFO) << "Message content has changed type from " << old_content_type << " to " << new_content_type;
old_message->is_content_secret = is_secret_message_content(old_message->ttl, new_content->get_type());
old_message->is_content_secret = old_message->ttl.is_secret_message_content(new_content->get_type());
}
if (need_merge_files && old_file_id.is_valid()) {

View File

@ -36,6 +36,7 @@
#include "td/telegram/MessageReplyHeader.h"
#include "td/telegram/MessageReplyInfo.h"
#include "td/telegram/MessageSearchFilter.h"
#include "td/telegram/MessageSelfDestructType.h"
#include "td/telegram/MessagesInfo.h"
#include "td/telegram/MessageSource.h"
#include "td/telegram/MessageThreadInfo.h"
@ -987,7 +988,7 @@ class MessagesManager final : public Actor {
SavedMessagesTopicId saved_messages_topic_id;
int32 date = 0;
int32 ttl_period = 0;
int32 ttl = 0;
MessageSelfDestructType ttl;
bool disable_web_page_preview = false;
int64 random_id = 0;
tl_object_ptr<telegram_api::messageFwdHeader> forward_header;
@ -1106,9 +1107,9 @@ class MessagesManager final : public Actor {
string send_error_message;
double try_resend_at = 0;
int32 ttl_period = 0; // counted from message send date
int32 ttl = 0; // counted from message content view date
double ttl_expires_at = 0; // only for TTL
int32 ttl_period = 0; // counted from message send date
MessageSelfDestructType ttl; // counted from message content view date
double ttl_expires_at = 0; // only for TTL
int64 media_album_id = 0;
@ -1675,7 +1676,7 @@ class MessagesManager final : public Actor {
bool allow_update_stickersets_order) const;
static Status can_use_message_send_options(const MessageSendOptions &options,
const unique_ptr<MessageContent> &content, int32 ttl);
const unique_ptr<MessageContent> &content, MessageSelfDestructType ttl);
static Status can_use_message_send_options(const MessageSendOptions &options, const InputMessageContent &content);

View File

@ -14,6 +14,7 @@
#include "td/telegram/LinkManager.h"
#include "td/telegram/MessageContent.h"
#include "td/telegram/MessageEntity.h"
#include "td/telegram/MessageSelfDestructType.h"
#include "td/telegram/net/NetQueryCreator.h"
#include "td/telegram/OptionManager.h"
#include "td/telegram/Photo.h"
@ -429,13 +430,13 @@ void SponsoredMessageManager::on_get_dialog_sponsored_messages(
auto message_text = get_message_text(td_->contacts_manager_.get(), std::move(sponsored_message->message_),
std::move(sponsored_message->entities_), true, true, 0, false,
"on_get_dialog_sponsored_messages");
int32 ttl = 0;
MessageSelfDestructType ttl;
bool disable_web_page_preview = false;
auto content =
get_message_content(td_, std::move(message_text), nullptr, sponsor_dialog_id, G()->unix_time(), true,
UserId(), &ttl, &disable_web_page_preview, "on_get_dialog_sponsored_messages");
if (ttl != 0) {
LOG(ERROR) << "Receive sponsored message with self-destruct time " << ttl;
if (!ttl.is_empty()) {
LOG(ERROR) << "Receive sponsored message with " << ttl;
continue;
}
CHECK(disable_web_page_preview);