// // 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/RequestedDialogType.h" #include "td/telegram/ChannelType.h" #include "td/telegram/ContactsManager.h" #include "td/telegram/Td.h" namespace td { RequestedDialogType::RequestedDialogType(td_api::object_ptr &&request_users) { CHECK(request_users != nullptr); type_ = Type::User; button_id_ = request_users->id_; max_quantity_ = max(request_users->max_quantity_, 1); restrict_is_bot_ = request_users->restrict_user_is_bot_; is_bot_ = request_users->user_is_bot_; restrict_is_premium_ = request_users->restrict_user_is_premium_; is_premium_ = request_users->user_is_premium_; } RequestedDialogType::RequestedDialogType(td_api::object_ptr &&request_dialog) { CHECK(request_dialog != nullptr); type_ = request_dialog->chat_is_channel_ ? Type::Channel : Type::Group; button_id_ = request_dialog->id_; restrict_is_forum_ = request_dialog->restrict_chat_is_forum_; is_forum_ = request_dialog->chat_is_forum_; bot_is_participant_ = request_dialog->bot_is_member_; restrict_has_username_ = request_dialog->restrict_chat_has_username_; has_username_ = request_dialog->chat_has_username_; is_created_ = request_dialog->chat_is_created_; restrict_user_administrator_rights_ = request_dialog->user_administrator_rights_ != nullptr; restrict_bot_administrator_rights_ = request_dialog->bot_administrator_rights_ != nullptr; auto channel_type = request_dialog->chat_is_channel_ ? ChannelType::Broadcast : ChannelType::Megagroup; user_administrator_rights_ = AdministratorRights(request_dialog->user_administrator_rights_, channel_type); bot_administrator_rights_ = AdministratorRights(request_dialog->bot_administrator_rights_, channel_type); } RequestedDialogType::RequestedDialogType(telegram_api::object_ptr &&peer_type, int32 button_id, int32 max_quantity) { CHECK(peer_type != nullptr); button_id_ = button_id; max_quantity_ = max(max_quantity, 1); switch (peer_type->get_id()) { case telegram_api::requestPeerTypeUser::ID: { auto type = telegram_api::move_object_as(peer_type); type_ = Type::User; restrict_is_bot_ = (type->flags_ & telegram_api::requestPeerTypeUser::BOT_MASK) != 0; is_bot_ = type->bot_; restrict_is_premium_ = (type->flags_ & telegram_api::requestPeerTypeUser::PREMIUM_MASK) != 0; is_premium_ = type->premium_; break; } case telegram_api::requestPeerTypeChat::ID: { auto type = telegram_api::move_object_as(peer_type); type_ = Type::Group; restrict_is_forum_ = (type->flags_ & telegram_api::requestPeerTypeChat::FORUM_MASK) != 0; is_forum_ = type->forum_; bot_is_participant_ = type->bot_participant_; restrict_has_username_ = (type->flags_ & telegram_api::requestPeerTypeChat::HAS_USERNAME_MASK) != 0; has_username_ = type->has_username_; is_created_ = type->creator_; 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); break; } case telegram_api::requestPeerTypeBroadcast::ID: { auto type = telegram_api::move_object_as(peer_type); type_ = Type::Channel; restrict_has_username_ = (type->flags_ & telegram_api::requestPeerTypeBroadcast::HAS_USERNAME_MASK) != 0; has_username_ = type->has_username_; is_created_ = type->creator_; 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); break; } default: UNREACHABLE(); } } td_api::object_ptr RequestedDialogType::get_keyboard_button_type_object() const { if (type_ == Type::User) { return td_api::make_object( button_id_, restrict_is_bot_, is_bot_, restrict_is_premium_, is_premium_, max_quantity_); } else { auto user_administrator_rights = restrict_user_administrator_rights_ ? user_administrator_rights_.get_chat_administrator_rights_object() : nullptr; auto bot_administrator_rights = restrict_bot_administrator_rights_ ? bot_administrator_rights_.get_chat_administrator_rights_object() : nullptr; return td_api::make_object( button_id_, type_ == Type::Channel, restrict_is_forum_, is_forum_, restrict_has_username_, has_username_, is_created_, std::move(user_administrator_rights), std::move(bot_administrator_rights), bot_is_participant_); } } telegram_api::object_ptr RequestedDialogType::get_input_request_peer_type_object() const { switch (type_) { case Type::User: { int32 flags = 0; if (restrict_is_bot_) { flags |= telegram_api::requestPeerTypeUser::BOT_MASK; } if (restrict_is_premium_) { flags |= telegram_api::requestPeerTypeUser::PREMIUM_MASK; } return telegram_api::make_object(flags, is_bot_, is_premium_); } case Type::Group: { int32 flags = 0; if (restrict_is_forum_) { flags |= telegram_api::requestPeerTypeChat::FORUM_MASK; } if (bot_is_participant_) { flags |= telegram_api::requestPeerTypeChat::BOT_PARTICIPANT_MASK; } if (restrict_has_username_) { flags |= telegram_api::requestPeerTypeChat::HAS_USERNAME_MASK; } if (is_created_) { flags |= telegram_api::requestPeerTypeChat::CREATOR_MASK; } if (restrict_user_administrator_rights_) { flags |= telegram_api::requestPeerTypeChat::USER_ADMIN_RIGHTS_MASK; } if (restrict_bot_administrator_rights_) { flags |= telegram_api::requestPeerTypeChat::BOT_ADMIN_RIGHTS_MASK; } auto user_admin_rights = restrict_user_administrator_rights_ ? user_administrator_rights_.get_chat_admin_rights() : nullptr; auto bot_admin_rights = restrict_bot_administrator_rights_ ? bot_administrator_rights_.get_chat_admin_rights() : nullptr; return telegram_api::make_object( flags, false /*ignored*/, false /*ignored*/, has_username_, is_forum_, std::move(user_admin_rights), std::move(bot_admin_rights)); } case Type::Channel: { int32 flags = 0; if (restrict_has_username_) { flags |= telegram_api::requestPeerTypeBroadcast::HAS_USERNAME_MASK; } if (is_created_) { flags |= telegram_api::requestPeerTypeBroadcast::CREATOR_MASK; } if (restrict_user_administrator_rights_) { flags |= telegram_api::requestPeerTypeBroadcast::USER_ADMIN_RIGHTS_MASK; } if (restrict_bot_administrator_rights_) { flags |= telegram_api::requestPeerTypeBroadcast::BOT_ADMIN_RIGHTS_MASK; } auto user_admin_rights = restrict_user_administrator_rights_ ? user_administrator_rights_.get_chat_admin_rights() : nullptr; auto bot_admin_rights = restrict_bot_administrator_rights_ ? bot_administrator_rights_.get_chat_admin_rights() : nullptr; return telegram_api::make_object( flags, false /*ignored*/, has_username_, std::move(user_admin_rights), std::move(bot_admin_rights)); } default: UNREACHABLE(); return nullptr; } } telegram_api::object_ptr RequestedDialogType::get_input_keyboard_button_request_peer(const string &text) const { return telegram_api::make_object( text, button_id_, get_input_request_peer_type_object(), max_quantity_); } 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(); if (!td->contacts_manager_->get_chat_is_active(chat_id)) { return Status::Error(400, "Chat is deactivated"); } 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 synchronously check that the bot is already participant 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 synchronously check that the bot is already an administrator 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(); } Status RequestedDialogType::check_shared_dialog_count(size_t count) const { if (count == 0) { return Status::Error(400, "Too few chats are chosen"); } if (count > static_cast(max_quantity_)) { return Status::Error(400, "Too many chats are chosen"); } return Status::OK(); } } // namespace td