diff --git a/td/telegram/DialogParticipant.h b/td/telegram/DialogParticipant.h index b8c8d858f..c066c2852 100644 --- a/td/telegram/DialogParticipant.h +++ b/td/telegram/DialogParticipant.h @@ -348,6 +348,12 @@ class DialogParticipantStatus { // forcely returns a restricted or banned DialogParticipantStatus(bool is_member, tl_object_ptr &&banned_rights); + bool has_all_administrator_rights(AdministratorRights administrator_rights) const { + auto flags = administrator_rights.flags_ & + (AdministratorRights::ALL_ADMINISTRATOR_RIGHTS | AdministratorRights::IS_ANONYMOUS); + return (get_administrator_rights().flags_ & flags) == flags; + } + RestrictedRights get_effective_restricted_rights() const; DialogParticipantStatus apply_restrictions(RestrictedRights default_restrictions, bool is_bot) const; diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 53ac24887..54972f5ad 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -29896,7 +29896,13 @@ void MessagesManager::share_dialog_with_bot(FullMessageId full_message_id, int32 } CHECK(m->message_id.is_valid() && m->message_id.is_server()); if (shared_dialog_id.get_type() != DialogType::User) { - get_dialog_force(shared_dialog_id, "share_dialog_with_bot"); + if (!have_dialog_force(shared_dialog_id, "share_dialog_with_bot")) { + return promise.set_error(Status::Error(400, "Shared chat not found")); + } + } else { + if (!td_->contacts_manager_->have_user(shared_dialog_id.get_user_id())) { + return promise.set_error(Status::Error(400, "Shared user not found")); + } } TRY_STATUS_PROMISE(promise, m->reply_markup->check_shared_dialog(td_, button_id, shared_dialog_id)); diff --git a/td/telegram/ReplyMarkup.cpp b/td/telegram/ReplyMarkup.cpp index 6978a31e8..9a3ae0621 100644 --- a/td/telegram/ReplyMarkup.cpp +++ b/td/telegram/ReplyMarkup.cpp @@ -1048,8 +1048,14 @@ tl_object_ptr ReplyMarkup::get_reply_markup_object(Contacts } Status ReplyMarkup::check_shared_dialog(Td *td, int32 button_id, DialogId dialog_id) const { - // TODO - return Status::OK(); + for (auto &row : keyboard) { + for (auto &button : row) { + if (button.requested_dialog_type != nullptr && button.requested_dialog_type->get_button_id() == button_id) { + return button.requested_dialog_type->check_shared_dialog(td, dialog_id); + } + } + } + return Status::Error(400, "Button not found"); } tl_object_ptr get_input_reply_markup(ContactsManager *contacts_manager, diff --git a/td/telegram/RequestedDialogType.cpp b/td/telegram/RequestedDialogType.cpp index c4392e9bc..c61754c30 100644 --- a/td/telegram/RequestedDialogType.cpp +++ b/td/telegram/RequestedDialogType.cpp @@ -7,6 +7,8 @@ #include "td/telegram/RequestedDialogType.h" #include "td/telegram/ChannelType.h" +#include "td/telegram/ContactsManager.h" +#include "td/telegram/Td.h" namespace td { @@ -60,7 +62,7 @@ RequestedDialogType::RequestedDialogType(telegram_api::object_ptrflags_ & telegram_api::requestPeerTypeChat::HAS_USERNAME_MASK) != 0; has_username_ = type->has_username_; is_created_ = type->creator_; - restrict_user_administrator_rights_ = type->user_admin_rights_ != nullptr; + restrict_user_administrator_rights_ = !is_created_ && type->user_admin_rights_ != nullptr; restrict_bot_administrator_rights_ = type->bot_admin_rights_ != nullptr; user_administrator_rights_ = AdministratorRights(type->user_admin_rights_, ChannelType::Megagroup); bot_administrator_rights_ = AdministratorRights(type->bot_admin_rights_, ChannelType::Megagroup); @@ -72,7 +74,7 @@ RequestedDialogType::RequestedDialogType(telegram_api::object_ptrflags_ & telegram_api::requestPeerTypeBroadcast::HAS_USERNAME_MASK) != 0; has_username_ = type->has_username_; is_created_ = type->creator_; - restrict_user_administrator_rights_ = type->user_admin_rights_ != nullptr; + restrict_user_administrator_rights_ = !is_created_ && type->user_admin_rights_ != nullptr; restrict_bot_administrator_rights_ = type->bot_admin_rights_ != nullptr; user_administrator_rights_ = AdministratorRights(type->user_admin_rights_, ChannelType::Broadcast); bot_administrator_rights_ = AdministratorRights(type->bot_admin_rights_, ChannelType::Broadcast); @@ -171,4 +173,95 @@ int32 RequestedDialogType::get_button_id() const { return button_id_; } +Status RequestedDialogType::check_shared_dialog(Td *td, DialogId dialog_id) const { + switch (dialog_id.get_type()) { + case DialogType::User: { + if (type_ != Type::User) { + return Status::Error(400, "Wrong chat type"); + } + auto user_id = dialog_id.get_user_id(); + if (restrict_is_bot_ && td->contacts_manager_->is_user_bot(user_id) != is_bot_) { + return Status::Error(400, "Wrong is_bot value"); + } + if (restrict_is_premium_ && td->contacts_manager_->is_user_premium(user_id) != is_premium_) { + return Status::Error(400, "Wrong is_premium value"); + } + break; + } + case DialogType::Chat: { + if (type_ != Type::Group) { + return Status::Error(400, "Wrong chat type"); + } + if (restrict_is_forum_ && is_forum_) { + return Status::Error(400, "Wrong is_forum value"); + } + if (restrict_has_username_ && has_username_) { + return Status::Error(400, "Wrong has_username value"); + } + auto chat_id = dialog_id.get_chat_id(); + auto status = td->contacts_manager_->get_chat_status(chat_id); + if (is_created_ && !status.is_creator()) { + return Status::Error(400, "The chat must be created by the current user"); + } + if (bot_is_participant_) { + // can't check that the bot is already participant, so check that the user can add it instead + if (!status.can_invite_users()) { + return Status::Error(400, "The bot can't be added to the chat"); + } + } + if (restrict_user_administrator_rights_ && !status.has_all_administrator_rights(user_administrator_rights_)) { + return Status::Error(400, "Not enough rights in the chat"); + } + if (restrict_bot_administrator_rights_) { + // can't check that the bot is already an administrator, so check that the user can promote it instead + if (!status.can_invite_users() || !status.can_promote_members()) { + return Status::Error(400, "The bot can't be promoted in the chat"); + } + } + break; + } + case DialogType::Channel: { + auto channel_id = dialog_id.get_channel_id(); + bool is_broadcast = td->contacts_manager_->is_broadcast_channel(channel_id); + if (type_ != (is_broadcast ? Type::Channel : Type::Group)) { + return Status::Error(400, "Wrong chat type"); + } + if (!is_broadcast && restrict_is_forum_ && td->contacts_manager_->is_forum_channel(channel_id) != is_forum_) { + return Status::Error(400, "Wrong is_forum value"); + } + if (restrict_has_username_ && + td->contacts_manager_->get_channel_first_username(channel_id).empty() == has_username_) { + return Status::Error(400, "Wrong has_username value"); + } + auto status = td->contacts_manager_->get_channel_status(channel_id); + if (is_created_ && !status.is_creator()) { + return Status::Error(400, "The chat must be created by the current user"); + } + bool can_invite_bot = status.can_invite_users() && + (status.is_administrator() || !td->contacts_manager_->is_channel_public(channel_id)); + if (!is_broadcast && bot_is_participant_) { + // can't check that the bot is already participant, so check that the user can add it instead + if (!can_invite_bot) { + return Status::Error(400, "The bot can't be added to the chat"); + } + } + if (restrict_user_administrator_rights_ && !status.has_all_administrator_rights(user_administrator_rights_)) { + return Status::Error(400, "Not enough rights in the chat"); + } + if (restrict_bot_administrator_rights_) { + // can't check that the bot is already an administrator, so check that the user can promote it instead + if (!can_invite_bot || !status.can_promote_members()) { + return Status::Error(400, "The bot can't be promoted in the chat"); + } + } + break; + } + case DialogType::SecretChat: + return Status::Error(400, "Can't share secret chats"); + case DialogType::None: + UNREACHABLE(); + } + return Status::OK(); +} + } // namespace td diff --git a/td/telegram/RequestedDialogType.h b/td/telegram/RequestedDialogType.h index 82522bd56..7247d6aee 100644 --- a/td/telegram/RequestedDialogType.h +++ b/td/telegram/RequestedDialogType.h @@ -6,6 +6,7 @@ // #pragma once +#include "td/telegram/DialogId.h" #include "td/telegram/DialogParticipant.h" #include "td/telegram/td_api.h" #include "td/telegram/telegram_api.h" @@ -14,6 +15,8 @@ namespace td { +class Td; + class RequestedDialogType { enum class Type : int32 { User, Group, Channel }; Type type_ = Type::User; @@ -49,6 +52,8 @@ class RequestedDialogType { int32 get_button_id() const; + Status check_shared_dialog(Td *td, DialogId dialog_id) const; + template void store(StorerT &storer) const;