// // Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2026 // // 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/ChatManager.h" #include "td/telegram/misc.h" #include "td/telegram/Td.h" #include "td/telegram/UserManager.h" #include "td/utils/logging.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_; request_name_ = request_users->request_name_; request_username_ = request_users->request_username_; request_photo_ = request_users->request_photo_; } 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); request_name_ = request_dialog->request_title_; request_username_ = request_dialog->request_username_; request_photo_ = request_dialog->request_photo_; } RequestedDialogType::RequestedDialogType(td_api::object_ptr &&request) { CHECK(request != nullptr); type_ = Type::CreateBot; button_id_ = request->id_; suggested_name_ = request->suggested_name_; suggested_username_ = request->suggested_username_; if (!clean_input_string(suggested_name_)) { suggested_name_.clear(); } if (!clean_input_string(suggested_username_)) { suggested_username_.clear(); } } 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; } case telegram_api::requestPeerTypeCreateBot::ID: { auto type = telegram_api::move_object_as(peer_type); if (type->bot_managed_) { type_ = Type::CreateBot; suggested_name_ = std::move(type->suggested_name_); suggested_username_ = std::move(type->suggested_username_); } else { LOG(ERROR) << "Receive request to create an unmanaged bot " << to_string(type); type_ = Type::User; restrict_is_bot_ = true; is_bot_ = true; } 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_, request_name_, request_username_, request_photo_); } else if (type_ == Type::CreateBot) { return td_api::make_object(button_id_, suggested_name_, suggested_username_); } 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_, request_name_, request_username_, request_photo_); } } 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 (restrict_has_username_) { flags |= telegram_api::requestPeerTypeChat::HAS_USERNAME_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, is_created_, bot_is_participant_, 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 (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, is_created_, has_username_, std::move(user_admin_rights), std::move(bot_admin_rights)); } case Type::CreateBot: { int32 flags = 0; if (!suggested_name_.empty()) { flags |= telegram_api::requestPeerTypeCreateBot::SUGGESTED_NAME_MASK; } if (!suggested_username_.empty()) { flags |= telegram_api::requestPeerTypeCreateBot::SUGGESTED_USERNAME_MASK; } return telegram_api::make_object(flags, true, suggested_name_, suggested_username_); } default: UNREACHABLE(); return nullptr; } } telegram_api::object_ptr RequestedDialogType::get_input_keyboard_button_request_peer( int32 flags, telegram_api::object_ptr style, const string &text) const { return telegram_api::make_object( flags, request_name_, request_username_, request_photo_, std::move(style), 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->user_manager_->is_user_bot(user_id) != is_bot_) { return Status::Error(400, "Wrong is_bot value"); } if (restrict_is_premium_ && td->user_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->chat_manager_->get_chat_is_active(chat_id)) { return Status::Error(400, "Chat is deactivated"); } auto status = td->chat_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->chat_manager_->is_broadcast_channel(channel_id); if (type_ != (is_broadcast ? Type::Channel : Type::Group)) { return Status::Error(400, "Wrong chat type"); } if (td->chat_manager_->is_monoforum_channel(channel_id)) { return Status::Error(400, "Channel direct messages chats can't be shared with bots"); } if (!is_broadcast && restrict_is_forum_ && td->chat_manager_->is_forum_channel(channel_id) != is_forum_) { return Status::Error(400, "Wrong is_forum value"); } if (restrict_has_username_ && td->chat_manager_->get_channel_first_username(channel_id).empty() == has_username_) { return Status::Error(400, "Wrong has_username value"); } auto status = td->chat_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->chat_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