diff --git a/td/telegram/MessageContent.cpp b/td/telegram/MessageContent.cpp index feb7c0c59..f7c6867da 100644 --- a/td/telegram/MessageContent.cpp +++ b/td/telegram/MessageContent.cpp @@ -17,6 +17,7 @@ #include "td/telegram/Contact.h" #include "td/telegram/ContactsManager.h" #include "td/telegram/Dependencies.h" +#include "td/telegram/DialogParticipant.h" #include "td/telegram/Document.h" #include "td/telegram/DocumentsManager.h" #include "td/telegram/DocumentsManager.hpp" @@ -49,6 +50,7 @@ #include "td/telegram/PollId.hpp" #include "td/telegram/PollManager.h" #include "td/telegram/secret_api.hpp" +#include "td/telegram/SecretChatActor.h" #include "td/telegram/SecureValue.h" #include "td/telegram/SecureValue.hpp" #include "td/telegram/StickersManager.h" @@ -82,6 +84,7 @@ #include "td/utils/tl_helpers.h" #include "td/utils/utf8.h" +#include #include namespace td { @@ -2432,6 +2435,181 @@ void delete_message_content_thumbnail(MessageContent *content, Td *td) { } } +Status can_send_message_content(DialogId dialog_id, const MessageContent *content, bool is_forward, const Td *td) { + auto dialog_type = dialog_id.get_type(); + int32 secret_chat_layer = std::numeric_limits::max(); + if (dialog_type == DialogType::SecretChat) { + auto secret_chat_id = dialog_id.get_secret_chat_id(); + secret_chat_layer = td->contacts_manager_->get_secret_chat_layer(secret_chat_id); + } + + auto content_type = content->get_type(); + RestrictedRights permissions = [&] { + switch (dialog_type) { + case DialogType::User: + return td->contacts_manager_->get_user_default_permissions(dialog_id.get_user_id()); + case DialogType::Chat: + return td->contacts_manager_->get_chat_permissions(dialog_id.get_chat_id()).get_restricted_rights(); + case DialogType::Channel: + return td->contacts_manager_->get_channel_permissions(dialog_id.get_channel_id()).get_restricted_rights(); + case DialogType::SecretChat: + return td->contacts_manager_->get_secret_chat_default_permissions(dialog_id.get_secret_chat_id()); + case DialogType::None: + default: + UNREACHABLE(); + return td->contacts_manager_->get_user_default_permissions(UserId()); + } + }(); + + switch (content_type) { + case MessageContentType::Animation: + if (!permissions.can_send_animations()) { + return Status::Error(400, "Not enough rights to send animations to the chat"); + } + break; + case MessageContentType::Audio: + if (!permissions.can_send_media()) { + return Status::Error(400, "Not enough rights to send music to the chat"); + } + break; + case MessageContentType::Contact: + if (!permissions.can_send_messages()) { + return Status::Error(400, "Not enough rights to send contacts to the chat"); + } + break; + case MessageContentType::Dice: + if (!permissions.can_send_stickers()) { + return Status::Error(400, "Not enough rights to send dice to the chat"); + } + if (dialog_type == DialogType::SecretChat) { + return Status::Error(400, "Dice can't be sent to secret chats"); + } + break; + case MessageContentType::Document: + if (!permissions.can_send_media()) { + return Status::Error(400, "Not enough rights to send documents to the chat"); + } + break; + case MessageContentType::Game: + if (dialog_type == DialogType::Channel && + td->contacts_manager_->get_channel_type(dialog_id.get_channel_id()) == ChannelType::Broadcast) { + // return Status::Error(400, "Games can't be sent to channel chats"); + } + if (dialog_type == DialogType::SecretChat) { + return Status::Error(400, "Games can't be sent to secret chats"); + } + if (!permissions.can_send_games()) { + return Status::Error(400, "Not enough rights to send games to the chat"); + } + break; + case MessageContentType::Invoice: + if (!permissions.can_send_messages()) { + return Status::Error(400, "Not enough rights to send invoice messages to the chat"); + } + if (dialog_type == DialogType::SecretChat) { + return Status::Error(400, "Invoice messages can't be sent to secret chats"); + } + break; + case MessageContentType::LiveLocation: + if (!permissions.can_send_messages()) { + return Status::Error(400, "Not enough rights to send live locations to the chat"); + } + break; + case MessageContentType::Location: + if (!permissions.can_send_messages()) { + return Status::Error(400, "Not enough rights to send locations to the chat"); + } + break; + case MessageContentType::Photo: + if (!permissions.can_send_media()) { + return Status::Error(400, "Not enough rights to send photos to the chat"); + } + break; + case MessageContentType::Poll: + if (!permissions.can_send_polls()) { + return Status::Error(400, "Not enough rights to send polls to the chat"); + } + if (dialog_type == DialogType::Channel && + td->contacts_manager_->get_channel_type(dialog_id.get_channel_id()) == ChannelType::Broadcast && + !td->poll_manager_->get_poll_is_anonymous(static_cast(content)->poll_id)) { + return Status::Error(400, "Non-anonymous polls can't be sent to channel chats"); + } + if (dialog_type == DialogType::User && !is_forward && !td->auth_manager_->is_bot() && + !td->contacts_manager_->is_user_bot(dialog_id.get_user_id())) { + return Status::Error(400, "Polls can't be sent to the private chat"); + } + if (dialog_type == DialogType::SecretChat) { + return Status::Error(400, "Polls can't be sent to secret chats"); + } + break; + case MessageContentType::Sticker: + if (!permissions.can_send_stickers()) { + return Status::Error(400, "Not enough rights to send stickers to the chat"); + } + break; + case MessageContentType::Text: + if (!permissions.can_send_messages()) { + return Status::Error(400, "Not enough rights to send text messages to the chat"); + } + break; + case MessageContentType::Venue: + if (!permissions.can_send_messages()) { + return Status::Error(400, "Not enough rights to send venues to the chat"); + } + break; + case MessageContentType::Video: + if (!permissions.can_send_media()) { + return Status::Error(400, "Not enough rights to send videos to the chat"); + } + break; + case MessageContentType::VideoNote: + if (!permissions.can_send_media()) { + return Status::Error(400, "Not enough rights to send video notes to the chat"); + } + if (secret_chat_layer < SecretChatActor::VIDEO_NOTES_LAYER) { + return Status::Error(400, PSLICE() + << "Video notes can't be sent to secret chat with layer " << secret_chat_layer); + } + break; + case MessageContentType::VoiceNote: + if (!permissions.can_send_media()) { + return Status::Error(400, "Not enough rights to send voice notes to the chat"); + } + break; + case MessageContentType::None: + case MessageContentType::ChatCreate: + case MessageContentType::ChatChangeTitle: + case MessageContentType::ChatChangePhoto: + case MessageContentType::ChatDeletePhoto: + case MessageContentType::ChatDeleteHistory: + case MessageContentType::ChatAddUsers: + case MessageContentType::ChatJoinedByLink: + case MessageContentType::ChatDeleteUser: + case MessageContentType::ChatMigrateTo: + case MessageContentType::ChannelCreate: + case MessageContentType::ChannelMigrateFrom: + case MessageContentType::PinMessage: + case MessageContentType::GameScore: + case MessageContentType::ScreenshotTaken: + case MessageContentType::ChatSetTtl: + case MessageContentType::Unsupported: + case MessageContentType::Call: + case MessageContentType::PaymentSuccessful: + case MessageContentType::ContactRegistered: + case MessageContentType::ExpiredPhoto: + case MessageContentType::ExpiredVideo: + case MessageContentType::CustomServiceAction: + case MessageContentType::WebsiteConnected: + case MessageContentType::PassportDataSent: + case MessageContentType::PassportDataReceived: + case MessageContentType::ProximityAlertTriggered: + case MessageContentType::GroupCall: + case MessageContentType::InviteToGroupCall: + UNREACHABLE(); + } + return Status::OK(); +} + bool can_forward_message_content(const MessageContent *content) { auto content_type = content->get_type(); if (content_type == MessageContentType::Text) { @@ -2631,15 +2809,6 @@ bool get_message_content_poll_is_closed(const Td *td, const MessageContent *cont } } -bool get_message_content_poll_is_anonymous(const Td *td, const MessageContent *content) { - switch (content->get_type()) { - case MessageContentType::Poll: - return td->poll_manager_->get_poll_is_anonymous(static_cast(content)->poll_id); - default: - return true; - } -} - bool has_message_content_web_page(const MessageContent *content) { if (content->get_type() == MessageContentType::Text) { return static_cast(content)->web_page_id.is_valid(); diff --git a/td/telegram/MessageContent.h b/td/telegram/MessageContent.h index 5d3148e0c..fbd5fe8ba 100644 --- a/td/telegram/MessageContent.h +++ b/td/telegram/MessageContent.h @@ -123,6 +123,8 @@ tl_object_ptr get_fake_input_media(Td *td, tl_object_p void delete_message_content_thumbnail(MessageContent *content, Td *td); +Status can_send_message_content(DialogId dialog_id, const MessageContent *content, bool is_forward, const Td *td); + bool can_forward_message_content(const MessageContent *content); bool update_opened_message_content(MessageContent *content); @@ -143,8 +145,6 @@ int32 get_message_content_live_location_period(const MessageContent *content); bool get_message_content_poll_is_closed(const Td *td, const MessageContent *content); -bool get_message_content_poll_is_anonymous(const Td *td, const MessageContent *content); - bool has_message_content_web_page(const MessageContent *content); void remove_message_content_web_page(MessageContent *content); diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index dfc2f15dc..25bd1a096 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -44,7 +44,6 @@ #include "td/telegram/NotificationType.h" #include "td/telegram/ReplyMarkup.h" #include "td/telegram/ReplyMarkup.hpp" -#include "td/telegram/SecretChatActor.h" #include "td/telegram/SecretChatsManager.h" #include "td/telegram/SequenceDispatcher.h" #include "td/telegram/Td.h" @@ -23120,179 +23119,6 @@ Status MessagesManager::can_send_message(DialogId dialog_id) const { return Status::OK(); } -Status MessagesManager::can_send_message_content(DialogId dialog_id, const MessageContent *content, - bool is_forward) const { - auto dialog_type = dialog_id.get_type(); - int32 secret_chat_layer = std::numeric_limits::max(); - if (dialog_type == DialogType::SecretChat) { - auto secret_chat_id = dialog_id.get_secret_chat_id(); - secret_chat_layer = td_->contacts_manager_->get_secret_chat_layer(secret_chat_id); - } - - auto content_type = content->get_type(); - RestrictedRights permissions = [&] { - switch (dialog_type) { - case DialogType::User: - return td_->contacts_manager_->get_user_default_permissions(dialog_id.get_user_id()); - case DialogType::Chat: - return td_->contacts_manager_->get_chat_permissions(dialog_id.get_chat_id()).get_restricted_rights(); - case DialogType::Channel: - return td_->contacts_manager_->get_channel_permissions(dialog_id.get_channel_id()).get_restricted_rights(); - case DialogType::SecretChat: - return td_->contacts_manager_->get_secret_chat_default_permissions(dialog_id.get_secret_chat_id()); - case DialogType::None: - default: - UNREACHABLE(); - return td_->contacts_manager_->get_user_default_permissions(UserId()); - } - }(); - - switch (content_type) { - case MessageContentType::Animation: - if (!permissions.can_send_animations()) { - return Status::Error(400, "Not enough rights to send animations to the chat"); - } - break; - case MessageContentType::Audio: - if (!permissions.can_send_media()) { - return Status::Error(400, "Not enough rights to send music to the chat"); - } - break; - case MessageContentType::Contact: - if (!permissions.can_send_messages()) { - return Status::Error(400, "Not enough rights to send contacts to the chat"); - } - break; - case MessageContentType::Dice: - if (!permissions.can_send_stickers()) { - return Status::Error(400, "Not enough rights to send dice to the chat"); - } - if (dialog_type == DialogType::SecretChat) { - return Status::Error(400, "Dice can't be sent to secret chats"); - } - break; - case MessageContentType::Document: - if (!permissions.can_send_media()) { - return Status::Error(400, "Not enough rights to send documents to the chat"); - } - break; - case MessageContentType::Game: - if (is_broadcast_channel(dialog_id)) { - // return Status::Error(400, "Games can't be sent to channel chats"); - } - if (dialog_type == DialogType::SecretChat) { - return Status::Error(400, "Games can't be sent to secret chats"); - } - if (!permissions.can_send_games()) { - return Status::Error(400, "Not enough rights to send games to the chat"); - } - break; - case MessageContentType::Invoice: - if (!permissions.can_send_messages()) { - return Status::Error(400, "Not enough rights to send invoice messages to the chat"); - } - if (dialog_type == DialogType::SecretChat) { - return Status::Error(400, "Invoice messages can't be sent to secret chats"); - } - break; - case MessageContentType::LiveLocation: - if (!permissions.can_send_messages()) { - return Status::Error(400, "Not enough rights to send live locations to the chat"); - } - break; - case MessageContentType::Location: - if (!permissions.can_send_messages()) { - return Status::Error(400, "Not enough rights to send locations to the chat"); - } - break; - case MessageContentType::Photo: - if (!permissions.can_send_media()) { - return Status::Error(400, "Not enough rights to send photos to the chat"); - } - break; - case MessageContentType::Poll: - if (!permissions.can_send_polls()) { - return Status::Error(400, "Not enough rights to send polls to the chat"); - } - if (!get_message_content_poll_is_anonymous(td_, content) && is_broadcast_channel(dialog_id)) { - return Status::Error(400, "Non-anonymous polls can't be sent to channel chats"); - } - if (dialog_type == DialogType::User && !is_forward && !td_->auth_manager_->is_bot() && - !td_->contacts_manager_->is_user_bot(dialog_id.get_user_id())) { - return Status::Error(400, "Polls can't be sent to the private chat"); - } - if (dialog_type == DialogType::SecretChat) { - return Status::Error(400, "Polls can't be sent to secret chats"); - } - break; - case MessageContentType::Sticker: - if (!permissions.can_send_stickers()) { - return Status::Error(400, "Not enough rights to send stickers to the chat"); - } - break; - case MessageContentType::Text: - if (!permissions.can_send_messages()) { - return Status::Error(400, "Not enough rights to send text messages to the chat"); - } - break; - case MessageContentType::Venue: - if (!permissions.can_send_messages()) { - return Status::Error(400, "Not enough rights to send venues to the chat"); - } - break; - case MessageContentType::Video: - if (!permissions.can_send_media()) { - return Status::Error(400, "Not enough rights to send videos to the chat"); - } - break; - case MessageContentType::VideoNote: - if (!permissions.can_send_media()) { - return Status::Error(400, "Not enough rights to send video notes to the chat"); - } - if (secret_chat_layer < SecretChatActor::VIDEO_NOTES_LAYER) { - return Status::Error(400, PSLICE() - << "Video notes can't be sent to secret chat with layer " << secret_chat_layer); - } - break; - case MessageContentType::VoiceNote: - if (!permissions.can_send_media()) { - return Status::Error(400, "Not enough rights to send voice notes to the chat"); - } - break; - case MessageContentType::None: - case MessageContentType::ChatCreate: - case MessageContentType::ChatChangeTitle: - case MessageContentType::ChatChangePhoto: - case MessageContentType::ChatDeletePhoto: - case MessageContentType::ChatDeleteHistory: - case MessageContentType::ChatAddUsers: - case MessageContentType::ChatJoinedByLink: - case MessageContentType::ChatDeleteUser: - case MessageContentType::ChatMigrateTo: - case MessageContentType::ChannelCreate: - case MessageContentType::ChannelMigrateFrom: - case MessageContentType::PinMessage: - case MessageContentType::GameScore: - case MessageContentType::ScreenshotTaken: - case MessageContentType::ChatSetTtl: - case MessageContentType::Unsupported: - case MessageContentType::Call: - case MessageContentType::PaymentSuccessful: - case MessageContentType::ContactRegistered: - case MessageContentType::ExpiredPhoto: - case MessageContentType::ExpiredVideo: - case MessageContentType::CustomServiceAction: - case MessageContentType::WebsiteConnected: - case MessageContentType::PassportDataSent: - case MessageContentType::PassportDataReceived: - case MessageContentType::ProximityAlertTriggered: - case MessageContentType::GroupCall: - case MessageContentType::InviteToGroupCall: - UNREACHABLE(); - } - return Status::OK(); -} - MessageId MessagesManager::get_persistent_message_id(const Dialog *d, MessageId message_id) const { if (!message_id.is_valid() && !message_id.is_valid_scheduled()) { return MessageId(); @@ -23648,7 +23474,7 @@ Result MessagesManager::process_input_message_content( } if (dialog_id != DialogId()) { - TRY_STATUS(can_send_message_content(dialog_id, content.content.get(), false)); + TRY_STATUS(can_send_message_content(dialog_id, content.content.get(), false, td_)); } return std::move(content); @@ -24602,7 +24428,7 @@ Result MessagesManager::send_inline_query_result_message(DialogId dia reply_to_message_id = get_reply_to_message_id(d, top_thread_message_id, reply_to_message_id, false); TRY_STATUS(can_use_message_send_options(message_send_options, content->message_content, 0)); - TRY_STATUS(can_send_message_content(dialog_id, content->message_content.get(), false)); + TRY_STATUS(can_send_message_content(dialog_id, content->message_content.get(), false, td_)); TRY_STATUS(can_use_top_thread_message_id(d, top_thread_message_id, reply_to_message_id)); bool need_update_dialog_pos = false; @@ -26237,7 +26063,7 @@ Result> MessagesManager::forward_messages(DialogId to_dialog_i continue; } - auto can_send_status = can_send_message_content(to_dialog_id, content.get(), !need_copy); + auto can_send_status = can_send_message_content(to_dialog_id, content.get(), !need_copy, td_); if (can_send_status.is_error()) { LOG(INFO) << "Can't forward " << message_id << ": " << can_send_status.message(); continue; @@ -26498,7 +26324,7 @@ Result> MessagesManager::resend_messages(DialogId dialog_id, v continue; } - auto can_send_status = can_send_message_content(dialog_id, content.get(), false); + auto can_send_status = can_send_message_content(dialog_id, content.get(), false, td_); if (can_send_status.is_error()) { LOG(INFO) << "Can't resend " << m->message_id << ": " << can_send_status.message(); continue; diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 5a0b9a552..7afe60190 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -1774,9 +1774,6 @@ class MessagesManager : public Actor { Status can_send_message(DialogId dialog_id) const TD_WARN_UNUSED_RESULT; - Status can_send_message_content(DialogId dialog_id, const MessageContent *content, - bool is_forward) const TD_WARN_UNUSED_RESULT; - bool can_resend_message(const Message *m) const; bool can_edit_message(DialogId dialog_id, const Message *m, bool is_editing, bool only_reply_markup = false) const;