Merge remote-tracking branch 'td/master'

This commit is contained in:
Andrea Cavalli 2022-03-19 20:01:35 +01:00
commit 2d13cc57ff
14 changed files with 964 additions and 833 deletions

View File

@ -293,6 +293,7 @@ set(TDLIB_SOURCE
td/telegram/CallDiscardReason.cpp
td/telegram/CallManager.cpp
td/telegram/CallbackQueriesManager.cpp
td/telegram/ChannelParticipantFilter.cpp
td/telegram/ClientActor.cpp
td/telegram/ConfigManager.cpp
td/telegram/ConfigShared.cpp
@ -314,6 +315,7 @@ set(TDLIB_SOURCE
td/telegram/DialogInviteLink.cpp
td/telegram/DialogLocation.cpp
td/telegram/DialogParticipant.cpp
td/telegram/DialogParticipantFilter.cpp
td/telegram/DialogSource.cpp
td/telegram/Document.cpp
td/telegram/DocumentsManager.cpp
@ -483,6 +485,7 @@ set(TDLIB_SOURCE
td/telegram/CallbackQueriesManager.h
td/telegram/ChainId.h
td/telegram/ChannelId.h
td/telegram/ChannelParticipantFilter.h
td/telegram/ChatId.h
td/telegram/ClientActor.h
td/telegram/ConfigManager.h
@ -509,6 +512,7 @@ set(TDLIB_SOURCE
td/telegram/DialogListId.h
td/telegram/DialogLocation.h
td/telegram/DialogParticipant.h
td/telegram/DialogParticipantFilter.h
td/telegram/DialogSource.h
td/telegram/Document.h
td/telegram/DocumentsManager.h

View File

@ -0,0 +1,116 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022
//
// 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/ChannelParticipantFilter.h"
namespace td {
tl_object_ptr<telegram_api::ChannelParticipantsFilter> ChannelParticipantFilter::get_input_channel_participants_filter()
const {
switch (type_) {
case Type::Recent:
return make_tl_object<telegram_api::channelParticipantsRecent>();
case Type::Contacts:
return make_tl_object<telegram_api::channelParticipantsContacts>(query_);
case Type::Administrators:
return make_tl_object<telegram_api::channelParticipantsAdmins>();
case Type::Search:
return make_tl_object<telegram_api::channelParticipantsSearch>(query_);
case Type::Mention: {
int32 flags = 0;
if (!query_.empty()) {
flags |= telegram_api::channelParticipantsMentions::Q_MASK;
}
if (top_thread_message_id_.is_valid()) {
flags |= telegram_api::channelParticipantsMentions::TOP_MSG_ID_MASK;
}
return make_tl_object<telegram_api::channelParticipantsMentions>(
flags, query_, top_thread_message_id_.get_server_message_id().get());
}
case Type::Restricted:
return make_tl_object<telegram_api::channelParticipantsBanned>(query_);
case Type::Banned:
return make_tl_object<telegram_api::channelParticipantsKicked>(query_);
case Type::Bots:
return make_tl_object<telegram_api::channelParticipantsBots>();
default:
UNREACHABLE();
return nullptr;
}
}
ChannelParticipantFilter::ChannelParticipantFilter(const tl_object_ptr<td_api::SupergroupMembersFilter> &filter) {
if (filter == nullptr) {
type_ = Type::Recent;
return;
}
switch (filter->get_id()) {
case td_api::supergroupMembersFilterRecent::ID:
type_ = Type::Recent;
return;
case td_api::supergroupMembersFilterContacts::ID:
type_ = Type::Contacts;
query_ = static_cast<const td_api::supergroupMembersFilterContacts *>(filter.get())->query_;
return;
case td_api::supergroupMembersFilterAdministrators::ID:
type_ = Type::Administrators;
return;
case td_api::supergroupMembersFilterSearch::ID:
type_ = Type::Search;
query_ = static_cast<const td_api::supergroupMembersFilterSearch *>(filter.get())->query_;
return;
case td_api::supergroupMembersFilterMention::ID: {
auto mention_filter = static_cast<const td_api::supergroupMembersFilterMention *>(filter.get());
type_ = Type::Mention;
query_ = mention_filter->query_;
top_thread_message_id_ = MessageId(mention_filter->message_thread_id_);
if (!top_thread_message_id_.is_valid() || !top_thread_message_id_.is_server()) {
top_thread_message_id_ = MessageId();
}
return;
}
case td_api::supergroupMembersFilterRestricted::ID:
type_ = Type::Restricted;
query_ = static_cast<const td_api::supergroupMembersFilterRestricted *>(filter.get())->query_;
return;
case td_api::supergroupMembersFilterBanned::ID:
type_ = Type::Banned;
query_ = static_cast<const td_api::supergroupMembersFilterBanned *>(filter.get())->query_;
return;
case td_api::supergroupMembersFilterBots::ID:
type_ = Type::Bots;
return;
default:
UNREACHABLE();
type_ = Type::Recent;
}
}
StringBuilder &operator<<(StringBuilder &string_builder, const ChannelParticipantFilter &filter) {
switch (filter.type_) {
case ChannelParticipantFilter::Type::Recent:
return string_builder << "Recent";
case ChannelParticipantFilter::Type::Contacts:
return string_builder << "Contacts \"" << filter.query_ << '"';
case ChannelParticipantFilter::Type::Administrators:
return string_builder << "Administrators";
case ChannelParticipantFilter::Type::Search:
return string_builder << "Search \"" << filter.query_ << '"';
case ChannelParticipantFilter::Type::Mention:
return string_builder << "Mention \"" << filter.query_ << "\" in thread of " << filter.top_thread_message_id_;
case ChannelParticipantFilter::Type::Restricted:
return string_builder << "Restricted \"" << filter.query_ << '"';
case ChannelParticipantFilter::Type::Banned:
return string_builder << "Banned \"" << filter.query_ << '"';
case ChannelParticipantFilter::Type::Bots:
return string_builder << "Bots";
default:
UNREACHABLE();
return string_builder;
}
}
} // namespace td

View File

@ -0,0 +1,62 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022
//
// 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)
//
#pragma once
#include "td/telegram/MessageId.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/utils/common.h"
#include "td/utils/StringBuilder.h"
namespace td {
class ChannelParticipantFilter {
enum class Type : int32 { Recent, Contacts, Administrators, Search, Mention, Restricted, Banned, Bots };
Type type_;
string query_;
MessageId top_thread_message_id_;
friend StringBuilder &operator<<(StringBuilder &string_builder, const ChannelParticipantFilter &filter);
public:
explicit ChannelParticipantFilter(const td_api::object_ptr<td_api::SupergroupMembersFilter> &filter);
tl_object_ptr<telegram_api::ChannelParticipantsFilter> get_input_channel_participants_filter() const;
bool is_administrators() const {
return type_ == Type::Administrators;
}
bool is_bots() const {
return type_ == Type::Bots;
}
bool is_recent() const {
return type_ == Type::Recent;
}
bool is_contacts() const {
return type_ == Type::Contacts;
}
bool is_search() const {
return type_ == Type::Search;
}
bool is_restricted() const {
return type_ == Type::Restricted;
}
bool is_banned() const {
return type_ == Type::Banned;
}
};
StringBuilder &operator<<(StringBuilder &string_builder, const ChannelParticipantFilter &filter);
} // namespace td

View File

@ -7,6 +7,7 @@
#include "td/telegram/ContactsManager.h"
#include "td/telegram/AuthManager.h"
#include "td/telegram/ChannelParticipantFilter.h"
#include "td/telegram/ConfigShared.h"
#include "td/telegram/Dependencies.h"
#include "td/telegram/DialogInviteLink.h"
@ -2808,7 +2809,7 @@ class GetChannelParticipantsQuery final : public Td::ResultHandler {
: promise_(std::move(promise)) {
}
void send(ChannelId channel_id, const ChannelParticipantsFilter &filter, int32 offset, int32 limit) {
void send(ChannelId channel_id, const ChannelParticipantFilter &filter, int32 offset, int32 limit) {
auto input_channel = td_->contacts_manager_->get_input_channel(channel_id);
if (input_channel == nullptr) {
return promise_.set_error(Status::Error(400, "Supergroup not found"));
@ -5725,15 +5726,16 @@ UserId ContactsManager::search_user_by_phone_number(string phone_number, Promise
void ContactsManager::on_resolved_phone_number(const string &phone_number, UserId user_id) {
if (!user_id.is_valid()) {
resolved_phone_numbers_.emplace(phone_number, user_id); // negative cache
resolved_phone_numbers_.emplace(phone_number, UserId()); // negative cache
return;
}
auto it = resolved_phone_numbers_.find(phone_number);
if (it != resolved_phone_numbers_.end()) {
if (it->second != user_id) {
LOG(ERROR) << "Resolve phone number \"" << phone_number << "\" to " << user_id << ", but have it in "
<< it->second;
LOG(WARNING) << "Resolve phone number \"" << phone_number << "\" to " << user_id << ", but have it in "
<< it->second;
it->second = user_id;
}
return;
}
@ -11194,8 +11196,7 @@ void ContactsManager::on_update_user_phone_number(User *u, UserId user_id, strin
if (u->phone_number != phone_number) {
if (!u->phone_number.empty()) {
auto it = resolved_phone_numbers_.find(u->phone_number);
if (it != resolved_phone_numbers_.end()) {
if (it->second == user_id) {
if (it != resolved_phone_numbers_.end() && it->second == user_id) {
resolved_phone_numbers_.erase(it);
}
}
@ -12057,7 +12058,7 @@ bool ContactsManager::is_user_contact(const User *u, UserId user_id, bool is_mut
}
void ContactsManager::on_get_channel_participants(
ChannelId channel_id, ChannelParticipantsFilter filter, int32 offset, int32 limit, string additional_query,
ChannelId channel_id, ChannelParticipantFilter &&filter, int32 offset, int32 limit, string additional_query,
int32 additional_limit, tl_object_ptr<telegram_api::channels_channelParticipants> &&channel_participants,
Promise<DialogParticipants> &&promise) {
TRY_STATUS_PROMISE(promise, G()->close_status());
@ -15233,7 +15234,7 @@ void ContactsManager::do_get_dialog_participant(DialogId dialog_id, DialogId par
DialogParticipants ContactsManager::search_private_chat_participants(UserId my_user_id, UserId peer_user_id,
const string &query, int32 limit,
DialogParticipantsFilter filter) const {
DialogParticipantFilter filter) const {
vector<DialogId> dialog_ids;
if (filter.is_dialog_participant_suitable(td_, DialogParticipant::private_member(my_user_id, peer_user_id))) {
dialog_ids.push_back(DialogId(my_user_id));
@ -15251,7 +15252,7 @@ DialogParticipants ContactsManager::search_private_chat_participants(UserId my_u
}
void ContactsManager::search_dialog_participants(DialogId dialog_id, const string &query, int32 limit,
DialogParticipantsFilter filter,
DialogParticipantFilter filter,
Promise<DialogParticipants> &&promise) {
LOG(INFO) << "Receive searchChatMembers request to search for \"" << query << "\" in " << dialog_id << " with filter "
<< filter;
@ -15329,7 +15330,7 @@ void ContactsManager::finish_get_chat_participant(ChatId chat_id, UserId user_id
}
void ContactsManager::search_chat_participants(ChatId chat_id, const string &query, int32 limit,
DialogParticipantsFilter filter, Promise<DialogParticipants> &&promise) {
DialogParticipantFilter filter, Promise<DialogParticipants> &&promise) {
if (limit < 0) {
return promise.set_error(Status::Error(400, "Parameter limit must be non-negative"));
}
@ -15347,7 +15348,7 @@ void ContactsManager::search_chat_participants(ChatId chat_id, const string &que
}
void ContactsManager::do_search_chat_participants(ChatId chat_id, const string &query, int32 limit,
DialogParticipantsFilter filter,
DialogParticipantFilter filter,
Promise<DialogParticipants> &&promise) {
TRY_STATUS_PROMISE(promise, G()->close_status());
@ -15432,9 +15433,9 @@ void ContactsManager::get_channel_participants(ChannelId channel_id,
return promise.set_error(Status::Error(400, "Member list is inaccessible"));
}
ChannelParticipantsFilter participants_filter(filter);
ChannelParticipantFilter participant_filter(filter);
auto get_channel_participants_promise = PromiseCreator::lambda(
[actor_id = actor_id(this), channel_id, filter = participants_filter,
[actor_id = actor_id(this), channel_id, filter = participant_filter,
additional_query = std::move(additional_query), offset, limit, additional_limit, promise = std::move(promise)](
Result<tl_object_ptr<telegram_api::channels_channelParticipants>> &&result) mutable {
if (result.is_error()) {
@ -15445,7 +15446,7 @@ void ContactsManager::get_channel_participants(ChannelId channel_id,
}
});
td_->create_handler<GetChannelParticipantsQuery>(std::move(get_channel_participants_promise))
->send(channel_id, participants_filter, offset, limit);
->send(channel_id, participant_filter, offset, limit);
}
td_api::object_ptr<td_api::chatAdministrators> ContactsManager::get_chat_administrators_object(
@ -15674,7 +15675,7 @@ void ContactsManager::on_chat_update(telegram_api::chat &chat, const char *sourc
if (is_creator) {
return DialogParticipantStatus::Creator(!has_left, false, string());
} else if (chat.admin_rights_ != nullptr) {
return get_dialog_participant_status(false, std::move(chat.admin_rights_), string());
return DialogParticipantStatus(false, std::move(chat.admin_rights_), string());
} else if (was_kicked) {
return DialogParticipantStatus::Banned(0);
} else if (has_left) {
@ -15856,9 +15857,9 @@ void ContactsManager::on_chat_update(telegram_api::channel &channel, const char
(channel.admin_rights_->flags_ & telegram_api::chatAdminRights::ANONYMOUS_MASK) != 0;
return DialogParticipantStatus::Creator(!has_left, is_anonymous, string());
} else if (channel.admin_rights_ != nullptr) {
return get_dialog_participant_status(false, std::move(channel.admin_rights_), string());
return DialogParticipantStatus(false, std::move(channel.admin_rights_), string());
} else if (channel.banned_rights_ != nullptr) {
return get_dialog_participant_status(!has_left, std::move(channel.banned_rights_));
return DialogParticipantStatus(!has_left, std::move(channel.banned_rights_));
} else if (has_left) {
return DialogParticipantStatus::Left();
} else {

View File

@ -16,6 +16,7 @@
#include "td/telegram/DialogInviteLink.h"
#include "td/telegram/DialogLocation.h"
#include "td/telegram/DialogParticipant.h"
#include "td/telegram/DialogParticipantFilter.h"
#include "td/telegram/files/FileId.h"
#include "td/telegram/files/FileSourceId.h"
#include "td/telegram/FolderId.h"
@ -55,6 +56,8 @@ namespace td {
struct BinlogEvent;
class ChannelParticipantFilter;
struct MinChannel;
class Td;
@ -542,7 +545,7 @@ class ContactsManager final : public Actor {
void get_dialog_participant(DialogId dialog_id, DialogId participant_dialog_id,
Promise<td_api::object_ptr<td_api::chatMember>> &&promise);
void search_dialog_participants(DialogId dialog_id, const string &query, int32 limit, DialogParticipantsFilter filter,
void search_dialog_participants(DialogId dialog_id, const string &query, int32 limit, DialogParticipantFilter filter,
Promise<DialogParticipants> &&promise);
void get_dialog_administrators(DialogId dialog_id, Promise<td_api::object_ptr<td_api::chatAdministrators>> &&promise);
@ -1472,7 +1475,7 @@ class ContactsManager final : public Actor {
int32 limit) const;
DialogParticipants search_private_chat_participants(UserId my_user_id, UserId peer_user_id, const string &query,
int32 limit, DialogParticipantsFilter filter) const;
int32 limit, DialogParticipantFilter filter) const;
void do_get_dialog_participant(DialogId dialog_id, DialogId participant_dialog_id,
Promise<DialogParticipant> &&promise);
@ -1565,13 +1568,13 @@ class ContactsManager final : public Actor {
void delete_chat_participant(ChatId chat_id, UserId user_id, bool revoke_messages, Promise<Unit> &&promise);
void search_chat_participants(ChatId chat_id, const string &query, int32 limit, DialogParticipantsFilter filter,
void search_chat_participants(ChatId chat_id, const string &query, int32 limit, DialogParticipantFilter filter,
Promise<DialogParticipants> &&promise);
void do_search_chat_participants(ChatId chat_id, const string &query, int32 limit, DialogParticipantsFilter filter,
void do_search_chat_participants(ChatId chat_id, const string &query, int32 limit, DialogParticipantFilter filter,
Promise<DialogParticipants> &&promise);
void on_get_channel_participants(ChannelId channel_id, ChannelParticipantsFilter filter, int32 offset, int32 limit,
void on_get_channel_participants(ChannelId channel_id, ChannelParticipantFilter &&filter, int32 offset, int32 limit,
string additional_query, int32 additional_limit,
tl_object_ptr<telegram_api::channels_channelParticipants> &&channel_participants,
Promise<DialogParticipants> &&promise);

File diff suppressed because it is too large Load Diff

View File

@ -21,6 +21,103 @@ namespace td {
class Td;
class AdministratorRights {
static constexpr uint32 CAN_CHANGE_INFO_AND_SETTINGS = 1 << 0;
static constexpr uint32 CAN_POST_MESSAGES = 1 << 1;
static constexpr uint32 CAN_EDIT_MESSAGES = 1 << 2;
static constexpr uint32 CAN_DELETE_MESSAGES = 1 << 3;
static constexpr uint32 CAN_INVITE_USERS = 1 << 4;
// static constexpr uint32 CAN_EXPORT_DIALOG_INVITE_LINK = 1 << 5;
static constexpr uint32 CAN_RESTRICT_MEMBERS = 1 << 6;
static constexpr uint32 CAN_PIN_MESSAGES = 1 << 7;
static constexpr uint32 CAN_PROMOTE_MEMBERS = 1 << 8;
static constexpr uint32 CAN_MANAGE_CALLS = 1 << 9;
static constexpr uint32 CAN_MANAGE_DIALOG = 1 << 10;
static constexpr uint32 ALL_ADMINISTRATOR_RIGHTS =
CAN_CHANGE_INFO_AND_SETTINGS | CAN_POST_MESSAGES | CAN_EDIT_MESSAGES | CAN_DELETE_MESSAGES | CAN_INVITE_USERS |
CAN_RESTRICT_MEMBERS | CAN_PIN_MESSAGES | CAN_PROMOTE_MEMBERS | CAN_MANAGE_CALLS | CAN_MANAGE_DIALOG;
uint32 flags_;
friend class DialogParticipantStatus;
explicit AdministratorRights(int32 flags) : flags_(flags & ALL_ADMINISTRATOR_RIGHTS) {
}
public:
AdministratorRights(bool can_manage_dialog, bool can_change_info, bool can_post_messages, bool can_edit_messages,
bool can_delete_messages, bool can_invite_users, bool can_restrict_members, bool can_pin_messages,
bool can_promote_members, bool can_manage_calls);
telegram_api::object_ptr<telegram_api::chatAdminRights> get_chat_admin_rights(bool is_anonymous) const;
bool can_manage_dialog() const {
return (flags_ & CAN_MANAGE_DIALOG) != 0;
}
bool can_change_info_and_settings() const {
return (flags_ & CAN_CHANGE_INFO_AND_SETTINGS) != 0;
}
bool can_post_messages() const {
return (flags_ & CAN_POST_MESSAGES) != 0;
}
bool can_edit_messages() const {
return (flags_ & CAN_EDIT_MESSAGES) != 0;
}
bool can_delete_messages() const {
return (flags_ & CAN_DELETE_MESSAGES) != 0;
}
bool can_invite_users() const {
return (flags_ & CAN_INVITE_USERS) != 0;
}
bool can_manage_invite_links() const {
// invite links can be managed, only if administrator was explicitly granted the right
return (flags_ & CAN_INVITE_USERS) != 0;
}
bool can_restrict_members() const {
return (flags_ & CAN_RESTRICT_MEMBERS) != 0;
}
bool can_pin_messages() const {
return (flags_ & CAN_PIN_MESSAGES) != 0;
}
bool can_promote_members() const {
return (flags_ & CAN_PROMOTE_MEMBERS) != 0;
}
bool can_manage_calls() const {
return (flags_ & CAN_MANAGE_CALLS) != 0;
}
template <class StorerT>
void store(StorerT &storer) const {
td::store(flags_, storer);
}
template <class ParserT>
void parse(ParserT &parser) {
td::parse(flags_, parser);
}
friend bool operator==(const AdministratorRights &lhs, const AdministratorRights &rhs);
friend StringBuilder &operator<<(StringBuilder &string_builder, const AdministratorRights &status);
};
bool operator==(const AdministratorRights &lhs, const AdministratorRights &rhs);
bool operator!=(const AdministratorRights &lhs, const AdministratorRights &rhs);
StringBuilder &operator<<(StringBuilder &string_builder, const AdministratorRights &status);
class RestrictedRights {
static constexpr uint32 CAN_SEND_MESSAGES = 1 << 16;
static constexpr uint32 CAN_SEND_MEDIA = 1 << 17;
@ -34,10 +131,20 @@ class RestrictedRights {
static constexpr uint32 CAN_INVITE_USERS = 1 << 25;
static constexpr uint32 CAN_PIN_MESSAGES = 1 << 26;
static constexpr uint32 ALL_ADMIN_PERMISSION_RIGHTS =
CAN_CHANGE_INFO_AND_SETTINGS | CAN_INVITE_USERS | CAN_PIN_MESSAGES;
static constexpr uint32 ALL_RESTRICTED_RIGHTS =
CAN_SEND_MESSAGES | CAN_SEND_MEDIA | CAN_SEND_STICKERS | CAN_SEND_ANIMATIONS | CAN_SEND_GAMES |
CAN_USE_INLINE_BOTS | CAN_ADD_WEB_PAGE_PREVIEWS | CAN_SEND_POLLS | ALL_ADMIN_PERMISSION_RIGHTS;
uint32 flags_;
friend class DialogParticipantStatus;
explicit RestrictedRights(int32 flags) : flags_(flags & ALL_RESTRICTED_RIGHTS) {
}
public:
RestrictedRights(bool can_send_messages, bool can_send_media, bool can_send_stickers, bool can_send_animations,
bool can_send_games, bool can_use_inline_bots, bool can_add_web_page_previews, bool can_send_polls,
@ -113,54 +220,17 @@ bool operator!=(const RestrictedRights &lhs, const RestrictedRights &rhs);
StringBuilder &operator<<(StringBuilder &string_builder, const RestrictedRights &status);
class DialogParticipantStatus {
static constexpr uint32 CAN_CHANGE_INFO_AND_SETTINGS_ADMIN = 1 << 0;
static constexpr uint32 CAN_POST_MESSAGES = 1 << 1;
static constexpr uint32 CAN_EDIT_MESSAGES = 1 << 2;
static constexpr uint32 CAN_DELETE_MESSAGES = 1 << 3;
static constexpr uint32 CAN_INVITE_USERS_ADMIN = 1 << 4;
// static constexpr uint32 CAN_EXPORT_DIALOG_INVITE_LINK = 1 << 5;
static constexpr uint32 CAN_RESTRICT_MEMBERS = 1 << 6;
static constexpr uint32 CAN_PIN_MESSAGES_ADMIN = 1 << 7;
static constexpr uint32 CAN_PROMOTE_MEMBERS = 1 << 8;
static constexpr uint32 CAN_MANAGE_CALLS = 1 << 9;
static constexpr uint32 CAN_MANAGE_DIALOG = 1 << 10;
// only flags 11 and 12 are unused
static constexpr uint32 IS_ANONYMOUS = 1 << 13;
static constexpr uint32 HAS_RANK = 1 << 14;
static constexpr uint32 CAN_BE_EDITED = 1 << 15;
static constexpr uint32 CAN_SEND_MESSAGES = 1 << 16;
static constexpr uint32 CAN_SEND_MEDIA = 1 << 17;
static constexpr uint32 CAN_SEND_STICKERS = 1 << 18;
static constexpr uint32 CAN_SEND_ANIMATIONS = 1 << 19;
static constexpr uint32 CAN_SEND_GAMES = 1 << 20;
static constexpr uint32 CAN_USE_INLINE_BOTS = 1 << 21;
static constexpr uint32 CAN_ADD_WEB_PAGE_PREVIEWS = 1 << 22;
static constexpr uint32 CAN_SEND_POLLS = 1 << 23;
static constexpr uint32 CAN_CHANGE_INFO_AND_SETTINGS_BANNED = 1 << 24;
static constexpr uint32 CAN_INVITE_USERS_BANNED = 1 << 25;
static constexpr uint32 CAN_PIN_MESSAGES_BANNED = 1 << 26;
static constexpr uint32 IS_MEMBER = 1 << 27;
static constexpr uint32 IS_ANONYMOUS = 1 << 13;
static constexpr uint32 HAS_RANK = 1 << 14;
// bits 28-30 reserved for Type
static constexpr int TYPE_SHIFT = 28;
static constexpr uint32 HAS_UNTIL_DATE = 1u << 31;
static constexpr uint32 ALL_ADMINISTRATOR_RIGHTS = CAN_CHANGE_INFO_AND_SETTINGS_ADMIN | CAN_POST_MESSAGES |
CAN_EDIT_MESSAGES | CAN_DELETE_MESSAGES | CAN_INVITE_USERS_ADMIN |
CAN_RESTRICT_MEMBERS | CAN_PIN_MESSAGES_ADMIN |
CAN_PROMOTE_MEMBERS | CAN_MANAGE_CALLS | CAN_MANAGE_DIALOG;
static constexpr uint32 ALL_ADMIN_PERMISSION_RIGHTS =
CAN_CHANGE_INFO_AND_SETTINGS_BANNED | CAN_INVITE_USERS_BANNED | CAN_PIN_MESSAGES_BANNED;
static constexpr uint32 ALL_RESTRICTED_RIGHTS = CAN_SEND_MESSAGES | CAN_SEND_MEDIA | CAN_SEND_STICKERS |
CAN_SEND_ANIMATIONS | CAN_SEND_GAMES | CAN_USE_INLINE_BOTS |
CAN_ADD_WEB_PAGE_PREVIEWS | CAN_SEND_POLLS;
static constexpr uint32 ALL_PERMISSION_RIGHTS = ALL_RESTRICTED_RIGHTS | ALL_ADMIN_PERMISSION_RIGHTS;
enum class Type : int32 { Creator, Administrator, Member, Restricted, Left, Banned };
// all fields are logically const, but should be updated in update_restrictions()
mutable Type type_;
@ -172,6 +242,14 @@ class DialogParticipantStatus {
DialogParticipantStatus(Type type, uint32 flags, int32 until_date, string rank);
AdministratorRights get_administrator_rights() const {
return AdministratorRights(flags_);
}
RestrictedRights get_restricted_rights() const {
return RestrictedRights(flags_);
}
public:
static DialogParticipantStatus Creator(bool is_member, bool is_anonymous, string rank);
@ -200,7 +278,11 @@ class DialogParticipantStatus {
// legacy rights
static DialogParticipantStatus ChannelAdministrator(bool is_creator, bool is_megagroup);
RestrictedRights get_restricted_rights() const;
DialogParticipantStatus(bool can_be_edited, tl_object_ptr<telegram_api::chatAdminRights> &&admin_rights, string rank);
DialogParticipantStatus(bool is_member, tl_object_ptr<telegram_api::chatBannedRights> &&banned_rights);
RestrictedRights get_effective_restricted_rights() const;
DialogParticipantStatus apply_restrictions(RestrictedRights default_restrictions, bool is_bot) const;
@ -214,48 +296,49 @@ class DialogParticipantStatus {
void update_restrictions() const;
bool can_manage_dialog() const {
return (flags_ & CAN_MANAGE_DIALOG) != 0;
return get_administrator_rights().can_manage_dialog();
}
bool can_change_info_and_settings() const {
return (flags_ & CAN_CHANGE_INFO_AND_SETTINGS_ADMIN) != 0 || (flags_ & CAN_CHANGE_INFO_AND_SETTINGS_BANNED) != 0;
return get_administrator_rights().can_change_info_and_settings() ||
get_restricted_rights().can_change_info_and_settings();
}
bool can_post_messages() const {
return (flags_ & CAN_POST_MESSAGES) != 0;
return get_administrator_rights().can_post_messages();
}
bool can_edit_messages() const {
return (flags_ & CAN_EDIT_MESSAGES) != 0;
return get_administrator_rights().can_edit_messages();
}
bool can_delete_messages() const {
return (flags_ & CAN_DELETE_MESSAGES) != 0;
return get_administrator_rights().can_edit_messages();
}
bool can_invite_users() const {
return (flags_ & CAN_INVITE_USERS_ADMIN) != 0 || (flags_ & CAN_INVITE_USERS_BANNED) != 0;
return get_administrator_rights().can_invite_users() || get_restricted_rights().can_invite_users();
}
bool can_manage_invite_links() const {
// invite links can be managed, only if administrator was explicitly granted the right
return (flags_ & CAN_INVITE_USERS_ADMIN) != 0;
return get_administrator_rights().can_invite_users();
}
bool can_restrict_members() const {
return (flags_ & CAN_RESTRICT_MEMBERS) != 0;
return get_administrator_rights().can_restrict_members();
}
bool can_pin_messages() const {
return (flags_ & CAN_PIN_MESSAGES_ADMIN) != 0 || (flags_ & CAN_PIN_MESSAGES_BANNED) != 0;
return get_administrator_rights().can_pin_messages() || get_restricted_rights().can_pin_messages();
}
bool can_promote_members() const {
return (flags_ & CAN_PROMOTE_MEMBERS) != 0;
return get_administrator_rights().can_promote_members();
}
bool can_manage_calls() const {
return (flags_ & CAN_MANAGE_CALLS) != 0;
return get_administrator_rights().can_manage_calls();
}
bool can_be_edited() const {
@ -263,35 +346,35 @@ class DialogParticipantStatus {
}
bool can_send_messages() const {
return (flags_ & CAN_SEND_MESSAGES) != 0;
return get_restricted_rights().can_send_messages();
}
bool can_send_media() const {
return (flags_ & CAN_SEND_MEDIA) != 0;
return get_restricted_rights().can_send_media();
}
bool can_send_stickers() const {
return (flags_ & CAN_SEND_STICKERS) != 0;
return get_restricted_rights().can_send_stickers();
}
bool can_send_animations() const {
return (flags_ & CAN_SEND_ANIMATIONS) != 0;
return get_restricted_rights().can_send_animations();
}
bool can_send_games() const {
return (flags_ & CAN_SEND_GAMES) != 0;
return get_restricted_rights().can_send_games();
}
bool can_use_inline_bots() const {
return (flags_ & CAN_USE_INLINE_BOTS) != 0;
return get_restricted_rights().can_use_inline_bots();
}
bool can_add_web_page_previews() const {
return (flags_ & CAN_ADD_WEB_PAGE_PREVIEWS) != 0;
return get_restricted_rights().can_add_web_page_previews();
}
bool can_send_polls() const {
return (flags_ & CAN_SEND_POLLS) != 0;
return get_restricted_rights().can_send_polls();
}
void set_is_member(bool is_member) {
@ -372,9 +455,9 @@ class DialogParticipantStatus {
flags_ = stored_flags & ((1 << TYPE_SHIFT) - 1);
if (is_creator()) {
flags_ |= ALL_ADMINISTRATOR_RIGHTS | ALL_PERMISSION_RIGHTS;
flags_ |= AdministratorRights::ALL_ADMINISTRATOR_RIGHTS | RestrictedRights::ALL_RESTRICTED_RIGHTS;
} else if (is_administrator()) {
flags_ |= CAN_MANAGE_DIALOG;
flags_ |= AdministratorRights::CAN_MANAGE_DIALOG;
}
}
@ -452,77 +535,9 @@ struct DialogParticipants {
td_api::object_ptr<td_api::chatMembers> get_chat_members_object(Td *td) const;
};
class ChannelParticipantsFilter {
enum class Type : int32 { Recent, Contacts, Administrators, Search, Mention, Restricted, Banned, Bots };
Type type_;
string query_;
MessageId top_thread_message_id_;
friend StringBuilder &operator<<(StringBuilder &string_builder, const ChannelParticipantsFilter &filter);
public:
explicit ChannelParticipantsFilter(const tl_object_ptr<td_api::SupergroupMembersFilter> &filter);
tl_object_ptr<telegram_api::ChannelParticipantsFilter> get_input_channel_participants_filter() const;
bool is_administrators() const {
return type_ == Type::Administrators;
}
bool is_bots() const {
return type_ == Type::Bots;
}
bool is_recent() const {
return type_ == Type::Recent;
}
bool is_contacts() const {
return type_ == Type::Contacts;
}
bool is_search() const {
return type_ == Type::Search;
}
bool is_restricted() const {
return type_ == Type::Restricted;
}
bool is_banned() const {
return type_ == Type::Banned;
}
};
StringBuilder &operator<<(StringBuilder &string_builder, const ChannelParticipantsFilter &filter);
class DialogParticipantsFilter {
enum class Type : int32 { Contacts, Administrators, Members, Restricted, Banned, Mention, Bots };
Type type_;
MessageId top_thread_message_id_;
friend StringBuilder &operator<<(StringBuilder &string_builder, const DialogParticipantsFilter &filter);
public:
explicit DialogParticipantsFilter(const tl_object_ptr<td_api::ChatMembersFilter> &filter);
td_api::object_ptr<td_api::SupergroupMembersFilter> get_supergroup_members_filter_object(const string &query) const;
bool has_query() const;
bool is_dialog_participant_suitable(const Td *td, const DialogParticipant &participant) const;
};
StringBuilder &operator<<(StringBuilder &string_builder, const DialogParticipantsFilter &filter);
DialogParticipantStatus get_dialog_participant_status(const tl_object_ptr<td_api::ChatMemberStatus> &status);
DialogParticipantStatus get_dialog_participant_status(bool can_be_edited,
tl_object_ptr<telegram_api::chatAdminRights> &&admin_rights,
string rank);
DialogParticipantStatus get_dialog_participant_status(bool is_member,
tl_object_ptr<telegram_api::chatBannedRights> &&banned_rights);
AdministratorRights get_administrator_rights(tl_object_ptr<telegram_api::chatAdminRights> &&admin_rights);
RestrictedRights get_restricted_rights(tl_object_ptr<telegram_api::chatBannedRights> &&banned_rights);

View File

@ -0,0 +1,141 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022
//
// 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/DialogParticipantFilter.h"
#include "td/telegram/ContactsManager.h"
#include "td/telegram/DialogParticipant.h"
#include "td/telegram/Td.h"
namespace td {
StringBuilder &operator<<(StringBuilder &string_builder, const DialogParticipantFilter &filter) {
switch (filter.type_) {
case DialogParticipantFilter::Type::Contacts:
return string_builder << "Contacts";
case DialogParticipantFilter::Type::Administrators:
return string_builder << "Administrators";
case DialogParticipantFilter::Type::Members:
return string_builder << "Members";
case DialogParticipantFilter::Type::Restricted:
return string_builder << "Restricted";
case DialogParticipantFilter::Type::Banned:
return string_builder << "Banned";
case DialogParticipantFilter::Type::Mention:
return string_builder << "Mention";
case DialogParticipantFilter::Type::Bots:
return string_builder << "Bots";
default:
UNREACHABLE();
return string_builder;
}
}
DialogParticipantFilter::DialogParticipantFilter(const tl_object_ptr<td_api::ChatMembersFilter> &filter) {
if (filter == nullptr) {
type_ = Type::Members;
return;
}
switch (filter->get_id()) {
case td_api::chatMembersFilterContacts::ID:
type_ = Type::Contacts;
break;
case td_api::chatMembersFilterAdministrators::ID:
type_ = Type::Administrators;
break;
case td_api::chatMembersFilterMembers::ID:
type_ = Type::Members;
break;
case td_api::chatMembersFilterRestricted::ID:
type_ = Type::Restricted;
break;
case td_api::chatMembersFilterBanned::ID:
type_ = Type::Banned;
break;
case td_api::chatMembersFilterMention::ID: {
auto mention_filter = static_cast<const td_api::chatMembersFilterMention *>(filter.get());
top_thread_message_id_ = MessageId(mention_filter->message_thread_id_);
if (!top_thread_message_id_.is_valid() || !top_thread_message_id_.is_server()) {
top_thread_message_id_ = MessageId();
}
type_ = Type::Mention;
break;
}
case td_api::chatMembersFilterBots::ID:
type_ = Type::Bots;
break;
default:
UNREACHABLE();
type_ = Type::Members;
break;
}
}
td_api::object_ptr<td_api::SupergroupMembersFilter> DialogParticipantFilter::get_supergroup_members_filter_object(
const string &query) const {
switch (type_) {
case Type::Contacts:
return td_api::make_object<td_api::supergroupMembersFilterContacts>();
case Type::Administrators:
return td_api::make_object<td_api::supergroupMembersFilterAdministrators>();
case Type::Members:
return td_api::make_object<td_api::supergroupMembersFilterSearch>(query);
case Type::Restricted:
return td_api::make_object<td_api::supergroupMembersFilterRestricted>(query);
case Type::Banned:
return td_api::make_object<td_api::supergroupMembersFilterBanned>(query);
case Type::Mention:
return td_api::make_object<td_api::supergroupMembersFilterMention>(query, top_thread_message_id_.get());
case Type::Bots:
return td_api::make_object<td_api::supergroupMembersFilterBots>();
default:
UNREACHABLE();
return nullptr;
}
}
bool DialogParticipantFilter::has_query() const {
switch (type_) {
case Type::Members:
case Type::Restricted:
case Type::Banned:
case Type::Mention:
return true;
case Type::Contacts:
case Type::Administrators:
case Type::Bots:
return false;
default:
UNREACHABLE();
return false;
}
}
bool DialogParticipantFilter::is_dialog_participant_suitable(const Td *td, const DialogParticipant &participant) const {
switch (type_) {
case Type::Contacts:
return participant.dialog_id_.get_type() == DialogType::User &&
td->contacts_manager_->is_user_contact(participant.dialog_id_.get_user_id());
case Type::Administrators:
return participant.status_.is_administrator();
case Type::Members:
return participant.status_.is_member();
case Type::Restricted:
return participant.status_.is_restricted();
case Type::Banned:
return participant.status_.is_banned();
case Type::Mention:
return true;
case Type::Bots:
return participant.dialog_id_.get_type() == DialogType::User &&
td->contacts_manager_->is_user_bot(participant.dialog_id_.get_user_id());
default:
UNREACHABLE();
return false;
}
}
} // namespace td

View File

@ -0,0 +1,42 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022
//
// 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)
//
#pragma once
#include "td/telegram/DialogId.h"
#include "td/telegram/MessageId.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/telegram/UserId.h"
#include "td/utils/common.h"
#include "td/utils/StringBuilder.h"
namespace td {
struct DialogParticipant;
class Td;
class DialogParticipantFilter {
enum class Type : int32 { Contacts, Administrators, Members, Restricted, Banned, Mention, Bots };
Type type_;
MessageId top_thread_message_id_;
friend StringBuilder &operator<<(StringBuilder &string_builder, const DialogParticipantFilter &filter);
public:
explicit DialogParticipantFilter(const tl_object_ptr<td_api::ChatMembersFilter> &filter);
td_api::object_ptr<td_api::SupergroupMembersFilter> get_supergroup_members_filter_object(const string &query) const;
bool has_query() const;
bool is_dialog_participant_suitable(const Td *td, const DialogParticipant &participant) const;
};
StringBuilder &operator<<(StringBuilder &string_builder, const DialogParticipantFilter &filter);
} // namespace td

View File

@ -12,6 +12,7 @@
#include "td/telegram/ConfigShared.h"
#include "td/telegram/ContactsManager.h"
#include "td/telegram/DialogAction.h"
#include "td/telegram/DialogParticipantFilter.h"
#include "td/telegram/Global.h"
#include "td/telegram/MessageId.h"
#include "td/telegram/MemoryManager.h"
@ -2793,8 +2794,8 @@ void GroupCallManager::try_load_group_call_administrators(InputGroupCallId input
std::move(result));
});
td_->contacts_manager_->search_dialog_participants(
dialog_id, string(), 100,
DialogParticipantsFilter(td_api::make_object<td_api::chatMembersFilterAdministrators>()), std::move(promise));
dialog_id, string(), 100, DialogParticipantFilter(td_api::make_object<td_api::chatMembersFilterAdministrators>()),
std::move(promise));
}
void GroupCallManager::finish_load_group_call_administrators(InputGroupCallId input_group_call_id,

View File

@ -2489,9 +2489,10 @@ Status can_send_message_content(DialogId dialog_id, const MessageContent *conten
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();
return td->contacts_manager_->get_chat_permissions(dialog_id.get_chat_id()).get_effective_restricted_rights();
case DialogType::Channel:
return td->contacts_manager_->get_channel_permissions(dialog_id.get_channel_id()).get_restricted_rights();
return td->contacts_manager_->get_channel_permissions(dialog_id.get_channel_id())
.get_effective_restricted_rights();
case DialogType::SecretChat:
return td->contacts_manager_->get_secret_chat_default_permissions(dialog_id.get_secret_chat_id());
case DialogType::None:

View File

@ -28468,7 +28468,7 @@ Result<MessagesManager::ForwardedMessages> MessagesManager::get_forwarded_messag
if (get_dialog_has_protected_content(from_dialog_id)) {
for (const auto &copy_option : copy_options) {
if (!copy_option.send_copy || !td_->auth_manager_->is_bot()) {
return Status::Error(400, "Administrators of the chat restricted message forwarding");
return Status::Error(400, "Message has protected content and can't be forwarded");
}
}
}
@ -31568,6 +31568,8 @@ void MessagesManager::on_send_message_fail(int64 random_id, Status error) {
error_message = "Failed to get HTTP URL content";
} else if (error.message() == "WEBPAGE_MEDIA_EMPTY") {
error_message = "Wrong type of the web page content";
} else if (error.message() == "CHAT_FORWARDS_RESTRICTED") {
error_message = "Message has protected content and can't be forwarded";
} else if (error.message() == "MEDIA_EMPTY") {
auto content_type = m->content->get_type();
if (content_type == MessageContentType::Game) {

View File

@ -33,6 +33,7 @@
#include "td/telegram/DialogListId.h"
#include "td/telegram/DialogLocation.h"
#include "td/telegram/DialogParticipant.h"
#include "td/telegram/DialogParticipantFilter.h"
#include "td/telegram/DialogSource.h"
#include "td/telegram/DocumentsManager.h"
#include "td/telegram/DownloadManager.h"
@ -6310,7 +6311,7 @@ void Td::on_request(uint64 id, td_api::searchChatMembers &request) {
}
});
contacts_manager_->search_dialog_participants(DialogId(request.chat_id_), request.query_, request.limit_,
DialogParticipantsFilter(request.filter_), std::move(query_promise));
DialogParticipantFilter(request.filter_), std::move(query_promise));
}
void Td::on_request(uint64 id, const td_api::getChatAdministrators &request) {

View File

@ -39,7 +39,7 @@ void TransparentProxy::tear_down() {
if (callback_) {
if (!fd_.input_buffer().empty()) {
LOG(ERROR) << "Have " << fd_.input_buffer().size() << " unread bytes";
callback_->set_result(Status::Error("Proxy has sent to much data"));
callback_->set_result(Status::Error("Proxy has sent too many data"));
} else {
callback_->set_result(std::move(fd_));
}