diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 0d3a97d48..ccb2aeda0 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -2234,18 +2234,24 @@ userPrivacySettingRuleAllowAll = UserPrivacySettingRule; //@description A rule to allow all of a user's contacts to do something userPrivacySettingRuleAllowContacts = UserPrivacySettingRule; -//@description A rule to allow certain specified users to do something @user_ids The user identifiers +//@description A rule to allow certain specified users to do something @user_ids The user identifiers, total number of users in all rules must not exceed 1000 userPrivacySettingRuleAllowUsers user_ids:vector = UserPrivacySettingRule; +//@description A rule to allow all members of certain specified basic groups and supergroups to doing something @chat_ids The chat identifiers, total number of chats in all rules must not exceed 20 +userPrivacySettingRuleAllowChatMembers chat_ids:vector = UserPrivacySettingRule; + //@description A rule to restrict all users from doing something userPrivacySettingRuleRestrictAll = UserPrivacySettingRule; //@description A rule to restrict all contacts of a user from doing something userPrivacySettingRuleRestrictContacts = UserPrivacySettingRule; -//@description A rule to restrict all specified users from doing something @user_ids The user identifiers +//@description A rule to restrict all specified users from doing something @user_ids The user identifiers, total number of users in all rules must not exceed 1000 userPrivacySettingRuleRestrictUsers user_ids:vector = UserPrivacySettingRule; +//@description A rule to restrict all members of specified basic groups and supergroups from doing something @chat_ids The chat identifiers, total number of chats in all rules must not exceed 20 +userPrivacySettingRuleRestrictChatMembers chat_ids:vector = UserPrivacySettingRule; + //@description A list of privacy rules. Rules are matched in the specified order. The first matched rule defines the privacy setting for a given user. If no rule matches, the action is not allowed @rules A list of rules userPrivacySettingRules rules:vector = UserPrivacySettingRules; diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index 82b1de95e..75340a52f 100644 Binary files a/td/generate/scheme/td_api.tlo and b/td/generate/scheme/td_api.tlo differ diff --git a/td/telegram/PrivacyManager.cpp b/td/telegram/PrivacyManager.cpp index 3f5964d8c..747535f7c 100644 --- a/td/telegram/PrivacyManager.cpp +++ b/td/telegram/PrivacyManager.cpp @@ -9,8 +9,12 @@ #include "td/telegram/td_api.h" #include "td/telegram/telegram_api.h" +#include "td/telegram/ChannelId.h" +#include "td/telegram/ChatId.h" #include "td/telegram/ContactsManager.h" +#include "td/telegram/DialogId.h" #include "td/telegram/Global.h" +#include "td/telegram/MessagesManager.h" #include "td/telegram/net/NetQueryCreator.h" #include "td/telegram/net/NetQueryDispatcher.h" #include "td/telegram/Td.h" @@ -129,6 +133,35 @@ PrivacyManager::UserPrivacySetting::UserPrivacySetting(const td_api::UserPrivacy } } +void PrivacyManager::UserPrivacySettingRule::set_chat_ids(const vector &dialog_ids) { + chat_ids_.clear(); + auto td = G()->td().get_actor_unsafe(); + for (auto dialog_id_int : dialog_ids) { + DialogId dialog_id(dialog_id_int); + if (!td->messages_manager_->have_dialog_force(dialog_id)) { + LOG(ERROR) << "Ignore not found " << dialog_id; + continue; + } + + switch (dialog_id.get_type()) { + case DialogType::Chat: + chat_ids_.push_back(dialog_id.get_chat_id().get()); + break; + case DialogType::Channel: { + auto channel_id = dialog_id.get_channel_id(); + if (td->contacts_manager_->get_channel_type(channel_id) != ChannelType::Megagroup) { + LOG(ERROR) << "Ignore broadcast " << channel_id; + break; + } + chat_ids_.push_back(channel_id.get()); + break; + } + default: + LOG(ERROR) << "Ignore " << dialog_id; + } + } +} + PrivacyManager::UserPrivacySettingRule::UserPrivacySettingRule(const td_api::UserPrivacySettingRule &rule) { switch (rule.get_id()) { case td_api::userPrivacySettingRuleAllowContacts::ID: @@ -141,6 +174,10 @@ PrivacyManager::UserPrivacySettingRule::UserPrivacySettingRule(const td_api::Use type_ = Type::AllowUsers; user_ids_ = static_cast(rule).user_ids_; break; + case td_api::userPrivacySettingRuleAllowChatMembers::ID: + type_ = Type::AllowChatParticipants; + set_chat_ids(static_cast(rule).chat_ids_); + break; case td_api::userPrivacySettingRuleRestrictContacts::ID: type_ = Type::RestrictContacts; break; @@ -151,6 +188,10 @@ PrivacyManager::UserPrivacySettingRule::UserPrivacySettingRule(const td_api::Use type_ = Type::RestrictUsers; user_ids_ = static_cast(rule).user_ids_; break; + case td_api::userPrivacySettingRuleRestrictChatMembers::ID: + type_ = Type::RestrictChatParticipants; + set_chat_ids(static_cast(rule).chat_ids_); + break; default: UNREACHABLE(); } @@ -168,6 +209,10 @@ PrivacyManager::UserPrivacySettingRule::UserPrivacySettingRule(const telegram_ap type_ = Type::AllowUsers; user_ids_ = static_cast(rule).users_; break; + case telegram_api::privacyValueAllowChatParticipants::ID: + type_ = Type::AllowChatParticipants; + chat_ids_ = static_cast(rule).chats_; + break; case telegram_api::privacyValueDisallowContacts::ID: type_ = Type::RestrictContacts; break; @@ -178,6 +223,10 @@ PrivacyManager::UserPrivacySettingRule::UserPrivacySettingRule(const telegram_ap type_ = Type::RestrictUsers; user_ids_ = static_cast(rule).users_; break; + case telegram_api::privacyValueDisallowChatParticipants::ID: + type_ = Type::RestrictChatParticipants; + chat_ids_ = static_cast(rule).chats_; + break; default: UNREACHABLE(); } @@ -190,13 +239,17 @@ tl_object_ptr PrivacyManager::UserPrivacySetting case Type::AllowAll: return make_tl_object(); case Type::AllowUsers: - return make_tl_object(user_ids_as_td_api()); + return make_tl_object(vector{user_ids_}); + case Type::AllowChatParticipants: + return make_tl_object(chat_ids_as_dialog_ids()); case Type::RestrictContacts: return make_tl_object(); case Type::RestrictAll: return make_tl_object(); case Type::RestrictUsers: - return make_tl_object(user_ids_as_td_api()); + return make_tl_object(vector{user_ids_}); + case Type::RestrictChatParticipants: + return make_tl_object(chat_ids_as_dialog_ids()); default: UNREACHABLE(); } @@ -210,12 +263,16 @@ tl_object_ptr PrivacyManager::UserPrivacySetting return make_tl_object(); case Type::AllowUsers: return make_tl_object(user_ids_as_telegram_api()); + case Type::AllowChatParticipants: + return make_tl_object(vector{chat_ids_}); case Type::RestrictContacts: return make_tl_object(); case Type::RestrictAll: return make_tl_object(); case Type::RestrictUsers: return make_tl_object(user_ids_as_telegram_api()); + case Type::RestrictChatParticipants: + return make_tl_object(vector{chat_ids_}); default: UNREACHABLE(); } @@ -224,31 +281,57 @@ tl_object_ptr PrivacyManager::UserPrivacySetting Result PrivacyManager::UserPrivacySettingRule::from_telegram_api( tl_object_ptr rule) { CHECK(rule != nullptr); - UserPrivacySettingRule res(*rule); - for (auto user_id : res.user_ids_) { - if (!G()->td().get_actor_unsafe()->contacts_manager_->have_user(UserId(user_id))) { + UserPrivacySettingRule result(*rule); + auto td = G()->td().get_actor_unsafe(); + for (auto user_id : result.user_ids_) { + if (!td->contacts_manager_->have_user(UserId(user_id))) { return Status::Error(500, "Got inaccessible user from the server"); } } - return res; + for (auto chat_id_int : result.chat_ids_) { + ChatId chat_id(chat_id_int); + DialogId dialog_id(chat_id); + if (!td->contacts_manager_->have_chat(chat_id)) { + ChannelId channel_id(chat_id_int); + dialog_id = DialogId(channel_id); + if (!td->contacts_manager_->have_channel(channel_id)) { + return Status::Error(500, "Got inaccessible chat from the server"); + } + } + td->messages_manager_->force_create_dialog(dialog_id, "UserPrivacySettingRule"); + } + return result; } vector> PrivacyManager::UserPrivacySettingRule::user_ids_as_telegram_api() const { - vector> res; + vector> result; for (auto user_id : user_ids_) { auto input_user = G()->td().get_actor_unsafe()->contacts_manager_->get_input_user(UserId(user_id)); if (input_user != nullptr) { - res.push_back(std::move(input_user)); + result.push_back(std::move(input_user)); } else { LOG(ERROR) << "Have no access to " << user_id; } } - return res; + return result; } -vector PrivacyManager::UserPrivacySettingRule::user_ids_as_td_api() const { - return user_ids_; +vector PrivacyManager::UserPrivacySettingRule::chat_ids_as_dialog_ids() const { + vector result; + auto td = G()->td().get_actor_unsafe(); + for (auto chat_id_int : chat_ids_) { + ChatId chat_id(chat_id_int); + DialogId dialog_id(chat_id); + if (!td->contacts_manager_->have_chat(chat_id)) { + ChannelId channel_id(chat_id_int); + dialog_id = DialogId(channel_id); + CHECK(td->contacts_manager_->have_channel(channel_id)); + } + CHECK(td->messages_manager_->have_dialog(dialog_id)); + result.push_back(dialog_id.get()); + } + return result; } Result PrivacyManager::UserPrivacySettingRules::from_telegram_api( @@ -260,12 +343,12 @@ Result PrivacyManager::UserPrivacySetti Result PrivacyManager::UserPrivacySettingRules::from_telegram_api( vector> rules) { - UserPrivacySettingRules res; + UserPrivacySettingRules result; for (auto &rule : rules) { TRY_RESULT(new_rule, UserPrivacySettingRule::from_telegram_api(std::move(rule))); - res.rules_.push_back(new_rule); + result.rules_.push_back(new_rule); } - return res; + return result; } Result PrivacyManager::UserPrivacySettingRules::from_td_api( @@ -273,14 +356,14 @@ Result PrivacyManager::UserPrivacySetti if (!rules) { return Status::Error(5, "UserPrivacySettingRules should not be empty"); } - UserPrivacySettingRules res; + UserPrivacySettingRules result; for (auto &rule : rules->rules_) { if (!rule) { return Status::Error(5, "UserPrivacySettingRule should not be empty"); } - res.rules_.emplace_back(*rule); + result.rules_.emplace_back(*rule); } - return res; + return result; } tl_object_ptr PrivacyManager::UserPrivacySettingRules::as_td_api() const { @@ -316,6 +399,7 @@ void PrivacyManager::get_privacy(tl_object_ptr key, on_get_result(user_privacy_setting, [&]() -> Result { TRY_RESULT(net_query, std::move(x_net_query)); TRY_RESULT(rules, fetch_result(std::move(net_query))); + LOG(INFO) << "Receive " << to_string(rules); return UserPrivacySettingRules::from_telegram_api(std::move(rules)); }()); })); @@ -350,6 +434,7 @@ void PrivacyManager::set_privacy(tl_object_ptr key, promise.set_result([&]() -> Result { TRY_RESULT(net_query, std::move(x_net_query)); TRY_RESULT(rules, fetch_result(std::move(net_query))); + LOG(INFO) << "Receive " << to_string(rules); TRY_RESULT(privacy_rules, UserPrivacySettingRules::from_telegram_api(std::move(rules))); get_info(user_privacy_setting).has_set_query = false; do_update_privacy(user_privacy_setting, std::move(privacy_rules), true); diff --git a/td/telegram/PrivacyManager.h b/td/telegram/PrivacyManager.h index 07c46ccea..d8e2056f7 100644 --- a/td/telegram/PrivacyManager.h +++ b/td/telegram/PrivacyManager.h @@ -6,14 +6,13 @@ // #pragma once +#include "td/telegram/net/NetQuery.h" #include "td/telegram/td_api.h" #include "td/telegram/telegram_api.h" #include "td/actor/actor.h" #include "td/actor/PromiseFuture.h" -#include "td/telegram/net/NetQuery.h" - #include "td/utils/common.h" #include "td/utils/Container.h" #include "td/utils/Status.h" @@ -73,7 +72,7 @@ class PrivacyManager : public NetQueryCallback { tl_object_ptr as_telegram_api() const; bool operator==(const UserPrivacySettingRule &other) const { - return type_ == other.type_ && user_ids_ == other.user_ids_; + return type_ == other.type_ && user_ids_ == other.user_ids_ && chat_ids_ == other.chat_ids_; } private: @@ -81,17 +80,22 @@ class PrivacyManager : public NetQueryCallback { AllowContacts, AllowAll, AllowUsers, + AllowChatParticipants, RestrictContacts, RestrictAll, - RestrictUsers + RestrictUsers, + RestrictChatParticipants } type_ = Type::RestrictAll; vector user_ids_; - - vector user_ids_as_td_api() const; + vector chat_ids_; vector> user_ids_as_telegram_api() const; + void set_chat_ids(const vector &dialog_ids); + + vector chat_ids_as_dialog_ids() const; + explicit UserPrivacySettingRule(const telegram_api::PrivacyRule &rule); }; diff --git a/td/telegram/Version.h b/td/telegram/Version.h index 90970fceb..407b5ad75 100644 --- a/td/telegram/Version.h +++ b/td/telegram/Version.h @@ -8,7 +8,7 @@ namespace td { -constexpr int32 MTPROTO_LAYER = 99; +constexpr int32 MTPROTO_LAYER = 100; enum class Version : int32 { Initial, diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index ed7500c70..47dd9c325 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -944,6 +944,9 @@ class CliClient final : public Actor { if (setting == "photo") { return td_api::make_object(); } + if (setting == "phone_number") { + return td_api::make_object(); + } return nullptr; } @@ -1044,6 +1047,8 @@ class CliClient final : public Actor { return td_api::make_object(); } else if (category == "call") { return td_api::make_object(); + } else if (category == "forward") { + return td_api::make_object(); } else { return td_api::make_object(); } @@ -1557,11 +1562,17 @@ class CliClient final : public Actor { } else if (op == "spr") { string setting; string allow; - std::tie(setting, allow) = split(args); + string ids; + std::tie(setting, args) = split(args); + std::tie(allow, ids) = split(args); std::vector> rules; if (allow == "c" || allow == "contacts") { rules.push_back(td_api::make_object()); + } else if (allow == "users") { + rules.push_back(td_api::make_object(as_user_ids(ids))); + } else if (allow == "chats") { + rules.push_back(td_api::make_object(as_chat_ids(ids))); } else if (as_bool(allow)) { rules.push_back(td_api::make_object()); } else {