Support chats as members of other chats.

This commit is contained in:
levlam 2021-03-22 04:03:24 +03:00
parent 06791bbbf3
commit adedc7ad4f
7 changed files with 164 additions and 123 deletions

View File

@ -477,20 +477,21 @@ chatMemberStatusMember = ChatMemberStatus;
//@permissions User permissions in the chat
chatMemberStatusRestricted is_member:Bool restricted_until_date:int32 permissions:chatPermissions = ChatMemberStatus;
//@description The user is not a chat member
//@description The user or the chat is not a chat member
chatMemberStatusLeft = ChatMemberStatus;
//@description The user was banned (and hence is not a member of the chat). Implies the user can't return to the chat or view messages
//@description The user or the chat was banned (and hence is not a member of the chat). Implies the user can't return to the chat, view messages, or be used as an alias to join a voice chat of the chat
//@banned_until_date Point in time (Unix timestamp) when the user will be unbanned; 0 if never. If the user is banned for more than 366 days or for less than 30 seconds from the current time, the user is considered to be banned forever. Always 0 in basic groups
chatMemberStatusBanned banned_until_date:int32 = ChatMemberStatus;
//@description A user with information about joining/leaving a chat @user_id User identifier of the chat member
//@description Information about a user or a chat as a member of another chat
//@member_id Identifier of the chat member. Currently, other chats can be only Left or Banned. Only supergroups and channels can have other chats as Left or Banned members and these chats must be supergroups or channels
//@inviter_user_id Identifier of a user that invited/promoted/banned this member in the chat; 0 if unknown
//@joined_chat_date Point in time (Unix timestamp) when the user joined the chat
//@status Status of the member in the chat
//@bot_info If the user is a bot, information about the bot; may be null. Can be null even for a bot if the bot is not the chat member
chatMember user_id:int32 inviter_user_id:int32 joined_chat_date:int32 status:ChatMemberStatus bot_info:botInfo = ChatMember;
chatMember member_id:MessageSender inviter_user_id:int32 joined_chat_date:int32 status:ChatMemberStatus bot_info:botInfo = ChatMember;
//@description Contains a list of chat members @total_count Approximate total count of chat members found @members A list of chat members
chatMembers total_count:int32 members:vector<chatMember> = ChatMembers;
@ -2411,11 +2412,11 @@ chatEventMemberLeft = ChatEventAction;
//@description A new chat member was invited @user_id New member user identifier @status New member status
chatEventMemberInvited user_id:int32 status:ChatMemberStatus = ChatEventAction;
//@description A chat member has gained/lost administrator status, or the list of their administrator privileges has changed @user_id Chat member user identifier @old_status Previous status of the chat member @new_status New status of the chat member
//@description A chat member has gained/lost administrator status, or the list of their administrator privileges has changed @user_id Affected chat member user identifier @old_status Previous status of the chat member @new_status New status of the chat member
chatEventMemberPromoted user_id:int32 old_status:ChatMemberStatus new_status:ChatMemberStatus = ChatEventAction;
//@description A chat member was restricted/unrestricted or banned/unbanned, or the list of their restrictions has changed @user_id Chat member user identifier @old_status Previous status of the chat member @new_status New status of the chat member
chatEventMemberRestricted user_id:int32 old_status:ChatMemberStatus new_status:ChatMemberStatus = ChatEventAction;
//@description A chat member was restricted/unrestricted or banned/unbanned, or the list of their restrictions has changed @member_id Affected chat member identifier @old_status Previous status of the chat member @new_status New status of the chat member
chatEventMemberRestricted member_id:MessageSender old_status:ChatMemberStatus new_status:ChatMemberStatus = ChatEventAction;
//@description The chat title was changed @old_title Previous chat title @new_title New chat title
chatEventTitleChanged old_title:string new_title:string = ChatEventAction;

View File

@ -2946,7 +2946,7 @@ class GetChannelParticipantQuery : public Td::ResultHandler {
void on_error(uint64 id, Status status) override {
if (status.message() == "USER_NOT_PARTICIPANT") {
promise_.set_value(DialogParticipant::left(user_id_));
promise_.set_value(DialogParticipant::left(DialogId(user_id_)));
return;
}
@ -3041,11 +3041,12 @@ class GetChannelAdministratorsQuery : public Td::ResultHandler {
administrators.reserve(participants->participants_.size());
for (auto &participant : participants->participants_) {
DialogParticipant dialog_participant(std::move(participant));
if (!dialog_participant.is_valid() || !dialog_participant.status.is_administrator()) {
if (!dialog_participant.is_valid() || !dialog_participant.status.is_administrator() ||
dialog_participant.dialog_id.get_type() != DialogType::User) {
LOG(ERROR) << "Receive " << dialog_participant << " as an administrator of " << channel_id_;
continue;
}
administrators.emplace_back(dialog_participant.user_id, dialog_participant.status.get_rank(),
administrators.emplace_back(dialog_participant.dialog_id.get_user_id(), dialog_participant.status.get_rank(),
dialog_participant.status.is_creator());
}
@ -9428,7 +9429,7 @@ void ContactsManager::on_load_chat_full_from_database(ChatId chat_id, string val
dependencies.chat_ids.insert(chat_id);
dependencies.user_ids.insert(chat_full->creator_user_id);
for (auto &participant : chat_full->participants) {
dependencies.user_ids.insert(participant.user_id);
add_message_sender_dependencies(dependencies, participant.dialog_id);
dependencies.user_ids.insert(participant.inviter_user_id);
}
dependencies.user_ids.insert(chat_full->invite_link.get_creator_user_id());
@ -9439,7 +9440,9 @@ void ContactsManager::on_load_chat_full_from_database(ChatId chat_id, string val
}
for (auto &participant : chat_full->participants) {
get_bot_info_force(participant.user_id);
if (participant.dialog_id.get_type() == DialogType::User) {
get_bot_info_force(participant.dialog_id.get_user_id());
}
}
Chat *c = get_chat(chat_id);
@ -9978,12 +9981,15 @@ void ContactsManager::update_chat_full(ChatFull *chat_full, ChatId chat_id, bool
vector<DialogAdministrator> administrators;
vector<UserId> bot_user_ids;
for (const auto &participant : chat_full->participants) {
auto user_id = participant.user_id;
if (participant.status.is_administrator()) {
administrators.emplace_back(user_id, participant.status.get_rank(), participant.status.is_creator());
if (participant.status.is_administrator() && participant.dialog_id.get_type() == DialogType::User) {
administrators.emplace_back(participant.dialog_id.get_user_id(), participant.status.get_rank(),
participant.status.is_creator());
}
if (is_user_bot(user_id)) {
bot_user_ids.push_back(user_id);
if (participant.dialog_id.get_type() == DialogType::User) {
auto user_id = participant.dialog_id.get_user_id();
if (is_user_bot(user_id)) {
bot_user_ids.push_back(user_id);
}
}
}
on_update_dialog_administrators(DialogId(chat_id), std::move(administrators), chat_full->version != -1,
@ -11388,9 +11394,13 @@ void ContactsManager::update_dialog_online_member_count(const vector<DialogParti
int32 online_member_count = 0;
int32 time = G()->unix_time();
for (const auto &participant : participants) {
auto u = get_user(participant.user_id);
if (participant.dialog_id.get_type() != DialogType::User) {
continue;
}
auto user_id = participant.dialog_id.get_user_id();
auto u = get_user(user_id);
if (u != nullptr && !u->is_deleted && !u->is_bot) {
if (get_user_was_online(u, participant.user_id) > time) {
if (get_user_was_online(u, user_id) > time) {
online_member_count++;
}
if (is_from_server) {
@ -11453,18 +11463,18 @@ void ContactsManager::on_get_chat_participants(tl_object_ptr<telegram_api::ChatP
continue;
}
LOG_IF(ERROR, !have_user(dialog_participant.user_id))
<< "Have no information about " << dialog_participant.user_id << " as a member of " << chat_id;
LOG_IF(ERROR, !td_->messages_manager_->have_dialog_info(dialog_participant.dialog_id))
<< "Have no information about " << dialog_participant.dialog_id << " as a member of " << chat_id;
LOG_IF(ERROR, !have_user(dialog_participant.inviter_user_id))
<< "Have no information about " << dialog_participant.inviter_user_id << " as a member of " << chat_id;
if (dialog_participant.joined_date < c->date) {
LOG_IF(ERROR, dialog_participant.joined_date < c->date - 30 && c->date >= 1486000000)
<< "Wrong join date = " << dialog_participant.joined_date << " for " << dialog_participant.user_id << ", "
<< chat_id << " was created at " << c->date;
<< "Wrong join date = " << dialog_participant.joined_date << " for " << dialog_participant.dialog_id
<< ", " << chat_id << " was created at " << c->date;
dialog_participant.joined_date = c->date;
}
if (dialog_participant.status.is_creator()) {
new_creator_user_id = dialog_participant.user_id;
if (dialog_participant.status.is_creator() && dialog_participant.dialog_id.get_type() == DialogType::User) {
new_creator_user_id = dialog_participant.dialog_id.get_user_id();
}
new_participants.push_back(std::move(dialog_participant));
}
@ -11498,7 +11508,7 @@ const DialogParticipant *ContactsManager::get_chat_participant(ChatId chat_id, U
const DialogParticipant *ContactsManager::get_chat_full_participant(const ChatFull *chat_full, UserId user_id) {
for (const auto &dialog_participant : chat_full->participants) {
if (dialog_participant.user_id == user_id) {
if (dialog_participant.dialog_id == DialogId(user_id)) {
return &dialog_participant;
}
}
@ -11507,9 +11517,12 @@ const DialogParticipant *ContactsManager::get_chat_full_participant(const ChatFu
tl_object_ptr<td_api::chatMember> ContactsManager::get_chat_member_object(
const DialogParticipant &dialog_participant) const {
UserId participant_user_id = dialog_participant.user_id;
UserId participant_user_id;
if (dialog_participant.dialog_id.get_type() == DialogType::User) {
participant_user_id = dialog_participant.dialog_id.get_user_id();
}
return td_api::make_object<td_api::chatMember>(
get_user_id_object(participant_user_id, "chatMember.user_id"),
td_->messages_manager_->get_message_sender_object_const(dialog_participant.dialog_id),
get_user_id_object(dialog_participant.inviter_user_id, "chatMember.inviter_user_id"),
dialog_participant.joined_date, dialog_participant.status.get_chat_member_status_object(),
get_bot_info_object(participant_user_id));
@ -11609,14 +11622,18 @@ void ContactsManager::on_get_channel_participants(
auto debug_participant = to_string(participant_ptr);
result.emplace_back(std::move(participant_ptr));
const auto &participant = result.back();
if (!participant.is_valid() || (filter.is_bots() && !is_user_bot(participant.user_id)) ||
UserId participant_user_id;
if (participant.dialog_id.get_type() == DialogType::User) {
participant_user_id = participant.dialog_id.get_user_id();
}
if (!participant.is_valid() || (filter.is_bots() && !is_user_bot(participant_user_id)) ||
(filter.is_administrators() && !participant.status.is_administrator()) ||
((filter.is_recent() || filter.is_contacts() || filter.is_search()) && !participant.status.is_member()) ||
(filter.is_contacts() && !is_user_contact(participant.user_id)) ||
(filter.is_contacts() && !is_user_contact(participant_user_id)) ||
(filter.is_restricted() && !participant.status.is_restricted()) ||
(filter.is_banned() && !participant.status.is_banned())) {
bool skip_error = ((filter.is_administrators() || filter.is_bots()) && is_user_deleted(participant.user_id)) ||
(filter.is_contacts() && participant.user_id == get_my_id());
bool skip_error = ((filter.is_administrators() || filter.is_bots()) && is_user_deleted(participant_user_id)) ||
(filter.is_contacts() && participant_user_id == get_my_id());
if (!skip_error) {
LOG(ERROR) << "Receive " << participant << ", while searching for " << filter << " in " << channel_id
<< " with offset " << offset << " and limit " << limit << ": " << oneline(debug_participant);
@ -11645,12 +11662,15 @@ void ContactsManager::on_get_channel_participants(
{
if (filter.is_recent()) {
for (const auto &participant : result) {
if (participant.status.is_administrator()) {
administrators.emplace_back(participant.user_id, participant.status.get_rank(),
participant.status.is_creator());
}
if (is_user_bot(participant.user_id)) {
bot_user_ids.push_back(participant.user_id);
if (participant.dialog_id.get_type() == DialogType::User) {
auto participant_user_id = participant.dialog_id.get_user_id();
if (participant.status.is_administrator()) {
administrators.emplace_back(participant_user_id, participant.status.get_rank(),
participant.status.is_creator());
}
if (is_user_bot(participant_user_id)) {
bot_user_ids.push_back(participant_user_id);
}
}
}
administrator_count = narrow_cast<int32>(administrators.size());
@ -11661,11 +11681,16 @@ void ContactsManager::on_get_channel_participants(
}
} else if (filter.is_administrators()) {
for (const auto &participant : result) {
administrators.emplace_back(participant.user_id, participant.status.get_rank(),
participant.status.is_creator());
if (participant.dialog_id.get_type() == DialogType::User) {
administrators.emplace_back(participant.dialog_id.get_user_id(), participant.status.get_rank(),
participant.status.is_creator());
}
}
} else if (filter.is_bots()) {
bot_user_ids = transform(result, [](const DialogParticipant &participant) { return participant.user_id; });
bot_user_ids = transform(result, [](const DialogParticipant &participant) {
CHECK(participant.dialog_id.get_type() == DialogType::User);
return participant.dialog_id.get_user_id();
});
}
}
if (filter.is_administrators() || filter.is_recent()) {
@ -11709,7 +11734,9 @@ void ContactsManager::on_get_channel_participants(
}
if (!additional_query.empty()) {
auto user_ids = transform(result, [](const auto &participant) { return participant.user_id; });
auto dialog_ids = transform(result, [](const DialogParticipant &participant) { return participant.dialog_id; });
td::remove_if(dialog_ids, [](DialogId dialog_id) { return dialog_id.get_type() != DialogType::User; });
auto user_ids = transform(dialog_ids, [](DialogId dialog_id) { return dialog_id.get_user_id(); });
std::pair<int32, vector<UserId>> result_user_ids = search_among_users(user_ids, additional_query, additional_limit);
total_count = result_user_ids.first;
@ -11718,9 +11745,12 @@ void ContactsManager::on_get_channel_participants(
auto all_participants = std::move(result);
result.clear();
for (auto &participant : all_participants) {
if (result_user_ids_set.count(participant.user_id)) {
if (participant.dialog_id.get_type() != DialogType::User) {
continue;
}
if (result_user_ids_set.count(participant.dialog_id.get_user_id())) {
result_user_ids_set.erase(participant.dialog_id.get_user_id());
result.push_back(std::move(participant));
result_user_ids_set.erase(participant.user_id);
}
}
}
@ -11759,14 +11789,14 @@ void ContactsManager::speculative_add_channel_participants(ChannelId channel_id,
auto &participants = it->second;
bool is_found = false;
for (auto &participant : participants) {
if (participant.user_id == user_id) {
if (participant.dialog_id == DialogId(user_id)) {
is_found = true;
break;
}
}
if (!is_found) {
is_participants_cache_changed = true;
participants.emplace_back(user_id, inviter_user_id, date, DialogParticipantStatus::Member());
participants.emplace_back(DialogId(user_id), inviter_user_id, date, DialogParticipantStatus::Member());
}
}
@ -11797,7 +11827,7 @@ void ContactsManager::speculative_delete_channel_participant(ChannelId channel_i
if (it != cached_channel_participants_.end()) {
auto &participants = it->second;
for (size_t i = 0; i < participants.size(); i++) {
if (participants[i].user_id == deleted_user_id) {
if (participants[i].dialog_id == DialogId(deleted_user_id)) {
participants.erase(participants.begin() + i);
update_channel_online_member_count(channel_id, false);
break;
@ -11909,7 +11939,7 @@ void ContactsManager::speculative_add_channel_user(ChannelId channel_id, UserId
auto &participants = it->second;
bool is_found = false;
for (size_t i = 0; i < participants.size(); i++) {
if (participants[i].user_id == user_id) {
if (participants[i].dialog_id == DialogId(user_id)) {
if (!new_status.is_member()) {
participants.erase(participants.begin() + i);
update_channel_online_member_count(channel_id, false);
@ -11921,7 +11951,7 @@ void ContactsManager::speculative_add_channel_user(ChannelId channel_id, UserId
}
}
if (!is_found && new_status.is_member()) {
participants.emplace_back(user_id, get_my_id(), G()->unix_time(), new_status);
participants.emplace_back(DialogId(user_id), get_my_id(), G()->unix_time(), new_status);
update_channel_online_member_count(channel_id, false);
}
}
@ -12473,7 +12503,7 @@ void ContactsManager::on_update_chat_add_user(ChatId chat_id, UserId inviter_use
}
if (on_update_chat_full_participants_short(chat_full, chat_id, version)) {
for (auto &participant : chat_full->participants) {
if (participant.user_id == user_id) {
if (participant.dialog_id == DialogId(user_id)) {
if (participant.inviter_user_id != inviter_user_id) {
LOG(ERROR) << user_id << " was readded to " << chat_id << " by " << inviter_user_id
<< ", previously invited by " << participant.inviter_user_id;
@ -12487,7 +12517,7 @@ void ContactsManager::on_update_chat_add_user(ChatId chat_id, UserId inviter_use
return;
}
}
chat_full->participants.push_back(DialogParticipant{user_id, inviter_user_id, date,
chat_full->participants.push_back(DialogParticipant{DialogId(user_id), inviter_user_id, date,
user_id == chat_full->creator_user_id
? DialogParticipantStatus::Creator(true, false, string())
: DialogParticipantStatus::Member()});
@ -12562,7 +12592,7 @@ void ContactsManager::on_update_chat_edit_administrator(ChatId chat_id, UserId u
if (chat_full != nullptr) {
if (chat_full->version + 1 == version) {
for (auto &participant : chat_full->participants) {
if (participant.user_id == user_id) {
if (participant.dialog_id == DialogId(user_id)) {
participant.status = std::move(status);
chat_full->is_changed = true;
update_chat_full(chat_full, chat_id);
@ -12613,7 +12643,7 @@ void ContactsManager::on_update_chat_delete_user(ChatId chat_id, UserId user_id,
}
if (on_update_chat_full_participants_short(chat_full, chat_id, version)) {
for (size_t i = 0; i < chat_full->participants.size(); i++) {
if (chat_full->participants[i].user_id == user_id) {
if (chat_full->participants[i].dialog_id == DialogId(user_id)) {
chat_full->participants[i] = chat_full->participants.back();
chat_full->participants.resize(chat_full->participants.size() - 1);
chat_full->is_changed = true;
@ -13220,8 +13250,8 @@ void ContactsManager::on_update_bot_stopped(UserId user_id, int32 date, bool is_
return;
}
DialogParticipant old_dialog_participant(get_my_id(), user_id, date, DialogParticipantStatus::Banned(0));
DialogParticipant new_dialog_participant(get_my_id(), user_id, date, DialogParticipantStatus::Member());
DialogParticipant old_dialog_participant(DialogId(get_my_id()), user_id, date, DialogParticipantStatus::Banned(0));
DialogParticipant new_dialog_participant(DialogId(get_my_id()), user_id, date, DialogParticipantStatus::Member());
if (is_stopped) {
std::swap(old_dialog_participant.status, new_dialog_participant.status);
}
@ -13256,15 +13286,15 @@ void ContactsManager::on_update_chat_participant(ChatId chat_id, UserId user_id,
if (old_participant != nullptr) {
old_dialog_participant = DialogParticipant(std::move(old_participant), c->date, c->status.is_creator());
if (new_participant == nullptr) {
new_dialog_participant = DialogParticipant::left(old_dialog_participant.user_id);
new_dialog_participant = DialogParticipant::left(old_dialog_participant.dialog_id);
} else {
new_dialog_participant = DialogParticipant(std::move(new_participant), c->date, c->status.is_creator());
}
} else {
new_dialog_participant = DialogParticipant(std::move(new_participant), c->date, c->status.is_creator());
old_dialog_participant = DialogParticipant::left(new_dialog_participant.user_id);
old_dialog_participant = DialogParticipant::left(new_dialog_participant.dialog_id);
}
if (old_dialog_participant.user_id != new_dialog_participant.user_id || !old_dialog_participant.is_valid() ||
if (old_dialog_participant.dialog_id != new_dialog_participant.dialog_id || !old_dialog_participant.is_valid() ||
!new_dialog_participant.is_valid()) {
LOG(ERROR) << "Receive wrong updateChannelParticipant: " << old_dialog_participant << " -> "
<< new_dialog_participant;
@ -13295,15 +13325,15 @@ void ContactsManager::on_update_channel_participant(ChannelId channel_id, UserId
if (old_participant != nullptr) {
old_dialog_participant = DialogParticipant(std::move(old_participant));
if (new_participant == nullptr) {
new_dialog_participant = DialogParticipant::left(old_dialog_participant.user_id);
new_dialog_participant = DialogParticipant::left(old_dialog_participant.dialog_id);
} else {
new_dialog_participant = DialogParticipant(std::move(new_participant));
}
} else {
new_dialog_participant = DialogParticipant(std::move(new_participant));
old_dialog_participant = DialogParticipant::left(new_dialog_participant.user_id);
old_dialog_participant = DialogParticipant::left(new_dialog_participant.dialog_id);
}
if (old_dialog_participant.user_id != new_dialog_participant.user_id || !old_dialog_participant.is_valid() ||
if (old_dialog_participant.dialog_id != new_dialog_participant.dialog_id || !old_dialog_participant.is_valid() ||
!new_dialog_participant.is_valid()) {
LOG(ERROR) << "Receive wrong updateChannelParticipant: " << old_dialog_participant << " -> "
<< new_dialog_participant;
@ -13884,11 +13914,14 @@ bool ContactsManager::is_chat_full_outdated(const ChatFull *chat_full, const Cha
}
for (const auto &participant : chat_full->participants) {
auto u = get_user(participant.user_id);
if (u != nullptr && is_bot_info_expired(participant.user_id, u->bot_info_version)) {
LOG(INFO) << "Have outdated botInfo for " << participant.user_id << " in " << chat_id << "; expected version "
<< u->bot_info_version;
return true;
if (participant.dialog_id.get_type() == DialogType::User) {
auto user_id = participant.dialog_id.get_user_id();
auto u = get_user(user_id);
if (u != nullptr && is_bot_info_expired(user_id, u->bot_info_version)) {
LOG(INFO) << "Have outdated botInfo for " << user_id << " in " << chat_id << "; expected version "
<< u->bot_info_version;
return true;
}
}
}
@ -14512,11 +14545,11 @@ DialogParticipant ContactsManager::get_dialog_participant(DialogId dialog_id, Us
auto peer_user_id = dialog_id.get_user_id();
if (user_id == get_my_id()) {
promise.set_value(Unit());
return {user_id, peer_user_id, 0, DialogParticipantStatus::Member()};
return {DialogId(user_id), peer_user_id, 0, DialogParticipantStatus::Member()};
}
if (user_id == peer_user_id) {
promise.set_value(Unit());
return {peer_user_id, user_id, 0, DialogParticipantStatus::Member()};
return {DialogId(peer_user_id), user_id, 0, DialogParticipantStatus::Member()};
}
promise.set_error(Status::Error(3, "User is not a member of the private chat"));
@ -14530,11 +14563,12 @@ DialogParticipant ContactsManager::get_dialog_participant(DialogId dialog_id, Us
auto peer_user_id = get_secret_chat_user_id(dialog_id.get_secret_chat_id());
if (user_id == get_my_id()) {
promise.set_value(Unit());
return {user_id, peer_user_id.is_valid() ? peer_user_id : user_id, 0, DialogParticipantStatus::Member()};
return {DialogId(user_id), peer_user_id.is_valid() ? peer_user_id : user_id, 0,
DialogParticipantStatus::Member()};
}
if (peer_user_id.is_valid() && user_id == peer_user_id) {
promise.set_value(Unit());
return {peer_user_id, user_id, 0, DialogParticipantStatus::Member()};
return {DialogId(peer_user_id), user_id, 0, DialogParticipantStatus::Member()};
}
promise.set_error(Status::Error(3, "User is not a member of the secret chat"));
@ -14585,7 +14619,7 @@ DialogParticipants ContactsManager::search_private_chat_participants(UserId my_u
auto result = search_among_users(user_ids, query, limit);
return {result.first, transform(result.second, [&](UserId user_id) {
return DialogParticipant(user_id,
return DialogParticipant(DialogId(user_id),
user_id == my_user_id && peer_user_id.is_valid() ? peer_user_id : my_user_id, 0,
DialogParticipantStatus::Member());
})};
@ -14685,7 +14719,7 @@ DialogParticipant ContactsManager::get_chat_participant(ChatId chat_id, UserId u
auto result = get_chat_participant(chat_id, user_id);
if (result == nullptr) {
return DialogParticipant::left(user_id);
return DialogParticipant::left(DialogId(user_id));
}
return *result;
@ -14722,9 +14756,12 @@ void ContactsManager::do_search_chat_participants(ChatId chat_id, const string &
}
auto is_dialog_participant_suitable = [this, filter](const DialogParticipant &participant) {
if (participant.dialog_id.get_type() != DialogType::User) {
return false;
}
switch (filter.type) {
case DialogParticipantsFilter::Type::Contacts:
return is_user_contact(participant.user_id);
return is_user_contact(participant.dialog_id.get_user_id());
case DialogParticipantsFilter::Type::Administrators:
return participant.status.is_administrator();
case DialogParticipantsFilter::Type::Members:
@ -14736,7 +14773,7 @@ void ContactsManager::do_search_chat_participants(ChatId chat_id, const string &
case DialogParticipantsFilter::Type::Mention:
return true;
case DialogParticipantsFilter::Type::Bots:
return is_user_bot(participant.user_id);
return is_user_bot(participant.dialog_id.get_user_id());
default:
UNREACHABLE();
return false;
@ -14746,7 +14783,7 @@ void ContactsManager::do_search_chat_participants(ChatId chat_id, const string &
vector<UserId> user_ids;
for (const auto &participant : chat_full->participants) {
if (is_dialog_participant_suitable(participant)) {
user_ids.push_back(participant.user_id);
user_ids.push_back(participant.dialog_id.get_user_id());
}
}

View File

@ -642,9 +642,9 @@ RestrictedRights get_restricted_rights(const td_api::object_ptr<td_api::chatPerm
permissions->can_pin_messages_);
}
DialogParticipant::DialogParticipant(UserId user_id, UserId inviter_user_id, int32 joined_date,
DialogParticipant::DialogParticipant(DialogId dialog_id, UserId inviter_user_id, int32 joined_date,
DialogParticipantStatus status)
: user_id(user_id), inviter_user_id(inviter_user_id), joined_date(joined_date), status(status) {
: dialog_id(dialog_id), inviter_user_id(inviter_user_id), joined_date(joined_date), status(status) {
if (!inviter_user_id.is_valid() && inviter_user_id != UserId()) {
LOG(ERROR) << "Receive inviter " << inviter_user_id;
inviter_user_id = UserId();
@ -660,19 +660,19 @@ DialogParticipant::DialogParticipant(tl_object_ptr<telegram_api::ChatParticipant
switch (participant_ptr->get_id()) {
case telegram_api::chatParticipant::ID: {
auto participant = move_tl_object_as<telegram_api::chatParticipant>(participant_ptr);
*this = {UserId(participant->user_id_), UserId(participant->inviter_id_), participant->date_,
*this = {DialogId(UserId(participant->user_id_)), UserId(participant->inviter_id_), participant->date_,
DialogParticipantStatus::Member()};
break;
}
case telegram_api::chatParticipantCreator::ID: {
auto participant = move_tl_object_as<telegram_api::chatParticipantCreator>(participant_ptr);
*this = {UserId(participant->user_id_), UserId(participant->user_id_), chat_creation_date,
*this = {DialogId(UserId(participant->user_id_)), UserId(participant->user_id_), chat_creation_date,
DialogParticipantStatus::Creator(true, false, string())};
break;
}
case telegram_api::chatParticipantAdmin::ID: {
auto participant = move_tl_object_as<telegram_api::chatParticipantAdmin>(participant_ptr);
*this = {UserId(participant->user_id_), UserId(participant->inviter_id_), participant->date_,
*this = {DialogId(UserId(participant->user_id_)), UserId(participant->inviter_id_), participant->date_,
DialogParticipantStatus::GroupAdministrator(is_creator)};
break;
}
@ -684,50 +684,43 @@ DialogParticipant::DialogParticipant(tl_object_ptr<telegram_api::ChatParticipant
DialogParticipant::DialogParticipant(tl_object_ptr<telegram_api::ChannelParticipant> &&participant_ptr) {
CHECK(participant_ptr != nullptr);
auto get_peer_user_id = [](const tl_object_ptr<telegram_api::Peer> &peer) {
DialogId dialog_id(peer);
if (dialog_id.get_type() == DialogType::User) {
return dialog_id.get_user_id();
}
return UserId();
};
switch (participant_ptr->get_id()) {
case telegram_api::channelParticipant::ID: {
auto participant = move_tl_object_as<telegram_api::channelParticipant>(participant_ptr);
*this = {UserId(participant->user_id_), UserId(), participant->date_, DialogParticipantStatus::Member()};
*this = {DialogId(UserId(participant->user_id_)), UserId(), participant->date_,
DialogParticipantStatus::Member()};
break;
}
case telegram_api::channelParticipantSelf::ID: {
auto participant = move_tl_object_as<telegram_api::channelParticipantSelf>(participant_ptr);
*this = {UserId(participant->user_id_), UserId(participant->inviter_id_), participant->date_,
*this = {DialogId(UserId(participant->user_id_)), UserId(participant->inviter_id_), participant->date_,
DialogParticipantStatus::Member()};
break;
}
case telegram_api::channelParticipantCreator::ID: {
auto participant = move_tl_object_as<telegram_api::channelParticipantCreator>(participant_ptr);
bool is_anonymous = (participant->admin_rights_->flags_ & telegram_api::chatAdminRights::ANONYMOUS_MASK) != 0;
*this = {UserId(participant->user_id_), UserId(), 0,
*this = {DialogId(UserId(participant->user_id_)), UserId(), 0,
DialogParticipantStatus::Creator(true, is_anonymous, std::move(participant->rank_))};
break;
}
case telegram_api::channelParticipantAdmin::ID: {
auto participant = move_tl_object_as<telegram_api::channelParticipantAdmin>(participant_ptr);
bool can_be_edited = (participant->flags_ & telegram_api::channelParticipantAdmin::CAN_EDIT_MASK) != 0;
*this = {UserId(participant->user_id_), UserId(participant->promoted_by_), participant->date_,
*this = {DialogId(UserId(participant->user_id_)), UserId(participant->promoted_by_), participant->date_,
get_dialog_participant_status(can_be_edited, std::move(participant->admin_rights_),
std::move(participant->rank_))};
break;
}
case telegram_api::channelParticipantLeft::ID: {
auto participant = move_tl_object_as<telegram_api::channelParticipantLeft>(participant_ptr);
*this = {get_peer_user_id(participant->peer_), UserId(), 0, DialogParticipantStatus::Left()};
*this = {DialogId(participant->peer_), UserId(), 0, DialogParticipantStatus::Left()};
break;
}
case telegram_api::channelParticipantBanned::ID: {
auto participant = move_tl_object_as<telegram_api::channelParticipantBanned>(participant_ptr);
auto is_member = (participant->flags_ & telegram_api::channelParticipantBanned::LEFT_MASK) == 0;
*this = {get_peer_user_id(participant->peer_), UserId(participant->kicked_by_), participant->date_,
*this = {DialogId(participant->peer_), UserId(participant->kicked_by_), participant->date_,
get_dialog_participant_status(is_member, std::move(participant->banned_rights_))};
break;
}
@ -738,7 +731,7 @@ DialogParticipant::DialogParticipant(tl_object_ptr<telegram_api::ChannelParticip
}
bool DialogParticipant::is_valid() const {
if (!user_id.is_valid() || joined_date < 0) {
if (!dialog_id.is_valid() || joined_date < 0) {
return false;
}
if (status.is_restricted() || status.is_banned() || (status.is_administrator() && !status.is_creator())) {
@ -748,7 +741,7 @@ bool DialogParticipant::is_valid() const {
}
StringBuilder &operator<<(StringBuilder &string_builder, const DialogParticipant &dialog_participant) {
return string_builder << '[' << dialog_participant.user_id << " invited by " << dialog_participant.inviter_user_id
return string_builder << '[' << dialog_participant.dialog_id << " invited by " << dialog_participant.inviter_user_id
<< " at " << dialog_participant.joined_date << " with status " << dialog_participant.status
<< ']';
}

View File

@ -6,6 +6,7 @@
//
#pragma once
#include "td/telegram/DialogId.h"
#include "td/telegram/MessageId.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
@ -140,7 +141,7 @@ class DialogParticipantStatus {
static constexpr uint32 IS_MEMBER = 1 << 27;
static constexpr uint32 IS_ANONYMOUS = 1 << 13;
static constexpr uint32 HAS_RANK = 1u << 14;
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;
@ -388,29 +389,29 @@ bool operator!=(const DialogParticipantStatus &lhs, const DialogParticipantStatu
StringBuilder &operator<<(StringBuilder &string_builder, const DialogParticipantStatus &status);
struct DialogParticipant {
UserId user_id;
DialogId dialog_id;
UserId inviter_user_id;
int32 joined_date = 0;
DialogParticipantStatus status = DialogParticipantStatus::Left();
DialogParticipant() = default;
DialogParticipant(UserId user_id, UserId inviter_user_id, int32 joined_date, DialogParticipantStatus status);
DialogParticipant(DialogId user_id, UserId inviter_user_id, int32 joined_date, DialogParticipantStatus status);
DialogParticipant(tl_object_ptr<telegram_api::ChatParticipant> &&participant_ptr, int32 chat_creation_date,
bool is_creator);
explicit DialogParticipant(tl_object_ptr<telegram_api::ChannelParticipant> &&participant_ptr);
static DialogParticipant left(UserId user_id) {
return {user_id, UserId(), 0, DialogParticipantStatus::Left()};
static DialogParticipant left(DialogId dialog_id) {
return {dialog_id, UserId(), 0, DialogParticipantStatus::Left()};
}
bool is_valid() const;
template <class StorerT>
void store(StorerT &storer) const {
td::store(user_id, storer);
td::store(dialog_id, storer);
td::store(inviter_user_id, storer);
td::store(joined_date, storer);
td::store(status, storer);
@ -418,7 +419,13 @@ struct DialogParticipant {
template <class ParserT>
void parse(ParserT &parser) {
td::parse(user_id, parser);
if (parser.version() >= static_cast<int32>(Version::SupportBannedChannels)) {
td::parse(dialog_id, parser);
} else {
UserId user_id;
td::parse(user_id, parser);
dialog_id = DialogId(user_id);
}
td::parse(inviter_user_id, parser);
td::parse(joined_date, parser);
td::parse(status, parser);

View File

@ -675,7 +675,7 @@ struct GroupCallManager::GroupCallParticipants {
bool joined_date_asc = false;
bool are_administrators_loaded = false;
vector<UserId> administrator_user_ids;
vector<DialogId> administrator_dialog_ids;
struct PendingUpdates {
std::unordered_map<DialogId, GroupCallParticipant, DialogIdHash> updates;
@ -1790,8 +1790,7 @@ void GroupCallManager::process_group_call_participants(
bool GroupCallManager::update_group_call_participant_can_be_muted(bool can_manage,
const GroupCallParticipants *participants,
GroupCallParticipant &participant) {
bool is_admin = participant.dialog_id.get_type() == DialogType::User &&
td::contains(participants->administrator_user_ids, participant.dialog_id.get_user_id());
bool is_admin = td::contains(participants->administrator_dialog_ids, participant.dialog_id);
return participant.update_can_be_muted(can_manage, is_admin);
}
@ -2233,23 +2232,24 @@ void GroupCallManager::finish_load_group_call_administrators(InputGroupCallId in
return;
}
vector<UserId> administrator_user_ids;
vector<DialogId> administrator_dialog_ids;
auto participants = result.move_as_ok();
for (auto &administrator : participants.participants_) {
if (administrator.status.can_manage_calls() && administrator.user_id != td_->contacts_manager_->get_my_id()) {
administrator_user_ids.push_back(administrator.user_id);
if (administrator.status.can_manage_calls() &&
administrator.dialog_id != DialogId(td_->contacts_manager_->get_my_id())) {
administrator_dialog_ids.push_back(administrator.dialog_id);
}
}
auto *group_call_participants = add_group_call_participants(input_group_call_id);
if (group_call_participants->are_administrators_loaded &&
group_call_participants->administrator_user_ids == administrator_user_ids) {
group_call_participants->administrator_dialog_ids == administrator_dialog_ids) {
return;
}
LOG(INFO) << "Set administrators of " << input_group_call_id << " to " << administrator_user_ids;
LOG(INFO) << "Set administrators of " << input_group_call_id << " to " << administrator_dialog_ids;
group_call_participants->are_administrators_loaded = true;
group_call_participants->administrator_user_ids = std::move(administrator_user_ids);
group_call_participants->administrator_dialog_ids = std::move(administrator_dialog_ids);
update_group_call_participants_can_be_muted(input_group_call_id, true, group_call_participants);
}
@ -2884,8 +2884,7 @@ void GroupCallManager::toggle_group_call_participant_is_muted(GroupCallId group_
}
bool can_manage = can_manage_group_call(input_group_call_id);
bool is_admin = dialog_id.get_type() == DialogType::User &&
td::contains(participants->administrator_user_ids, dialog_id.get_user_id());
bool is_admin = td::contains(participants->administrator_dialog_ids, dialog_id);
auto participant_copy = *participant;
if (!participant_copy.set_pending_is_muted(is_muted, can_manage, is_admin)) {

View File

@ -31369,20 +31369,21 @@ tl_object_ptr<td_api::ChatEventAction> MessagesManager::get_chat_event_action_ob
case telegram_api::channelAdminLogEventActionParticipantInvite::ID: {
auto action = move_tl_object_as<telegram_api::channelAdminLogEventActionParticipantInvite>(action_ptr);
DialogParticipant dialog_participant(std::move(action->participant_));
if (!dialog_participant.is_valid()) {
if (!dialog_participant.is_valid() || dialog_participant.dialog_id.get_type() != DialogType::User) {
LOG(ERROR) << "Wrong invite: " << dialog_participant;
return nullptr;
}
return make_tl_object<td_api::chatEventMemberInvited>(
td_->contacts_manager_->get_user_id_object(dialog_participant.user_id, "chatEventMemberInvited"),
td_->contacts_manager_->get_user_id_object(dialog_participant.dialog_id.get_user_id(),
"chatEventMemberInvited"),
dialog_participant.status.get_chat_member_status_object());
}
case telegram_api::channelAdminLogEventActionParticipantToggleBan::ID: {
auto action = move_tl_object_as<telegram_api::channelAdminLogEventActionParticipantToggleBan>(action_ptr);
DialogParticipant old_dialog_participant(std::move(action->prev_participant_));
DialogParticipant new_dialog_participant(std::move(action->new_participant_));
if (old_dialog_participant.user_id != new_dialog_participant.user_id) {
LOG(ERROR) << old_dialog_participant.user_id << " VS " << new_dialog_participant.user_id;
if (old_dialog_participant.dialog_id != new_dialog_participant.dialog_id) {
LOG(ERROR) << old_dialog_participant.dialog_id << " VS " << new_dialog_participant.dialog_id;
return nullptr;
}
if (!old_dialog_participant.is_valid() || !new_dialog_participant.is_valid()) {
@ -31390,7 +31391,7 @@ tl_object_ptr<td_api::ChatEventAction> MessagesManager::get_chat_event_action_ob
return nullptr;
}
return make_tl_object<td_api::chatEventMemberRestricted>(
td_->contacts_manager_->get_user_id_object(old_dialog_participant.user_id, "chatEventMemberRestricted"),
get_message_sender_object(old_dialog_participant.dialog_id),
old_dialog_participant.status.get_chat_member_status_object(),
new_dialog_participant.status.get_chat_member_status_object());
}
@ -31398,16 +31399,18 @@ tl_object_ptr<td_api::ChatEventAction> MessagesManager::get_chat_event_action_ob
auto action = move_tl_object_as<telegram_api::channelAdminLogEventActionParticipantToggleAdmin>(action_ptr);
DialogParticipant old_dialog_participant(std::move(action->prev_participant_));
DialogParticipant new_dialog_participant(std::move(action->new_participant_));
if (old_dialog_participant.user_id != new_dialog_participant.user_id) {
LOG(ERROR) << old_dialog_participant.user_id << " VS " << new_dialog_participant.user_id;
if (old_dialog_participant.dialog_id != new_dialog_participant.dialog_id) {
LOG(ERROR) << old_dialog_participant.dialog_id << " VS " << new_dialog_participant.dialog_id;
return nullptr;
}
if (!old_dialog_participant.is_valid() || !new_dialog_participant.is_valid()) {
if (!old_dialog_participant.is_valid() || !new_dialog_participant.is_valid() ||
old_dialog_participant.dialog_id.get_type() != DialogType::User) {
LOG(ERROR) << "Wrong edit administrator: " << old_dialog_participant << " -> " << new_dialog_participant;
return nullptr;
}
return make_tl_object<td_api::chatEventMemberPromoted>(
td_->contacts_manager_->get_user_id_object(old_dialog_participant.user_id, "chatEventMemberPromoted"),
td_->contacts_manager_->get_user_id_object(old_dialog_participant.dialog_id.get_user_id(),
"chatEventMemberPromoted"),
old_dialog_participant.status.get_chat_member_status_object(),
new_dialog_participant.status.get_chat_member_status_object());
}

View File

@ -42,6 +42,7 @@ enum class Version : int32 {
AddPhotoProgressiveSizes,
AddLiveLocationHeading,
AddLiveLocationProximityAlertDistance, // 30
SupportBannedChannels,
Next
};