1 //
2 // Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 #include "td/telegram/DialogParticipant.h"
8 
9 #include "td/telegram/ContactsManager.h"
10 #include "td/telegram/Global.h"
11 #include "td/telegram/misc.h"
12 #include "td/telegram/Td.h"
13 
14 #include "td/utils/common.h"
15 #include "td/utils/logging.h"
16 
17 #include <limits>
18 
19 namespace td {
20 
DialogParticipantStatus(Type type,uint32 flags,int32 until_date,string rank)21 DialogParticipantStatus::DialogParticipantStatus(Type type, uint32 flags, int32 until_date, string rank)
22     : type_(type), flags_(flags), until_date_(until_date), rank_(strip_empty_characters(std::move(rank), 16)) {
23 }
24 
fix_until_date(int32 date)25 int32 DialogParticipantStatus::fix_until_date(int32 date) {
26   if (date == std::numeric_limits<int32>::max() || date < 0) {
27     return 0;
28   }
29   return date;
30 }
31 
Creator(bool is_member,bool is_anonymous,string rank)32 DialogParticipantStatus DialogParticipantStatus::Creator(bool is_member, bool is_anonymous, string rank) {
33   return DialogParticipantStatus(Type::Creator,
34                                  ALL_ADMINISTRATOR_RIGHTS | ALL_PERMISSION_RIGHTS | (is_member ? IS_MEMBER : 0) |
35                                      (is_anonymous ? IS_ANONYMOUS : 0),
36                                  0, std::move(rank));
37 }
38 
Administrator(bool is_anonymous,string rank,bool can_be_edited,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)39 DialogParticipantStatus DialogParticipantStatus::Administrator(bool is_anonymous, string rank, bool can_be_edited,
40                                                                bool can_manage_dialog, bool can_change_info,
41                                                                bool can_post_messages, bool can_edit_messages,
42                                                                bool can_delete_messages, bool can_invite_users,
43                                                                bool can_restrict_members, bool can_pin_messages,
44                                                                bool can_promote_members, bool can_manage_calls) {
45   uint32 flags = (static_cast<uint32>(can_be_edited) * CAN_BE_EDITED) |
46                  (static_cast<uint32>(can_manage_dialog) * CAN_MANAGE_DIALOG) |
47                  (static_cast<uint32>(can_change_info) * CAN_CHANGE_INFO_AND_SETTINGS_ADMIN) |
48                  (static_cast<uint32>(can_post_messages) * CAN_POST_MESSAGES) |
49                  (static_cast<uint32>(can_edit_messages) * CAN_EDIT_MESSAGES) |
50                  (static_cast<uint32>(can_delete_messages) * CAN_DELETE_MESSAGES) |
51                  (static_cast<uint32>(can_invite_users) * CAN_INVITE_USERS_ADMIN) |
52                  (static_cast<uint32>(can_restrict_members) * CAN_RESTRICT_MEMBERS) |
53                  (static_cast<uint32>(can_pin_messages) * CAN_PIN_MESSAGES_ADMIN) |
54                  (static_cast<uint32>(can_promote_members) * CAN_PROMOTE_MEMBERS) |
55                  (static_cast<uint32>(can_manage_calls) * CAN_MANAGE_CALLS) |
56                  (static_cast<uint32>(is_anonymous) * IS_ANONYMOUS);
57   if (flags == 0 || flags == CAN_BE_EDITED) {
58     return Member();
59   }
60   flags |= CAN_MANAGE_DIALOG;
61   return DialogParticipantStatus(Type::Administrator, IS_MEMBER | ALL_RESTRICTED_RIGHTS | flags, 0, std::move(rank));
62 }
63 
Member()64 DialogParticipantStatus DialogParticipantStatus::Member() {
65   return DialogParticipantStatus(Type::Member, IS_MEMBER | ALL_PERMISSION_RIGHTS, 0, string());
66 }
67 
Restricted(bool is_member,int32 restricted_until_date,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,bool can_change_info_and_settings,bool can_invite_users,bool can_pin_messages)68 DialogParticipantStatus DialogParticipantStatus::Restricted(
69     bool is_member, int32 restricted_until_date, bool can_send_messages, bool can_send_media, bool can_send_stickers,
70     bool can_send_animations, bool can_send_games, bool can_use_inline_bots, bool can_add_web_page_previews,
71     bool can_send_polls, bool can_change_info_and_settings, bool can_invite_users, bool can_pin_messages) {
72   uint32 flags = (static_cast<uint32>(can_send_messages) * CAN_SEND_MESSAGES) |
73                  (static_cast<uint32>(can_send_media) * CAN_SEND_MEDIA) |
74                  (static_cast<uint32>(can_send_stickers) * CAN_SEND_STICKERS) |
75                  (static_cast<uint32>(can_send_animations) * CAN_SEND_ANIMATIONS) |
76                  (static_cast<uint32>(can_send_games) * CAN_SEND_GAMES) |
77                  (static_cast<uint32>(can_use_inline_bots) * CAN_USE_INLINE_BOTS) |
78                  (static_cast<uint32>(can_add_web_page_previews) * CAN_ADD_WEB_PAGE_PREVIEWS) |
79                  (static_cast<uint32>(can_send_polls) * CAN_SEND_POLLS) |
80                  (static_cast<uint32>(can_change_info_and_settings) * CAN_CHANGE_INFO_AND_SETTINGS_BANNED) |
81                  (static_cast<uint32>(can_invite_users) * CAN_INVITE_USERS_BANNED) |
82                  (static_cast<uint32>(can_pin_messages) * CAN_PIN_MESSAGES_BANNED) |
83                  (static_cast<uint32>(is_member) * IS_MEMBER);
84   if (flags == (IS_MEMBER | ALL_PERMISSION_RIGHTS)) {
85     return Member();
86   }
87   return DialogParticipantStatus(Type::Restricted, flags, fix_until_date(restricted_until_date), string());
88 }
89 
Left()90 DialogParticipantStatus DialogParticipantStatus::Left() {
91   return DialogParticipantStatus(Type::Left, ALL_PERMISSION_RIGHTS, 0, string());
92 }
93 
Banned(int32 banned_until_date)94 DialogParticipantStatus DialogParticipantStatus::Banned(int32 banned_until_date) {
95   return DialogParticipantStatus(Type::Banned, 0, fix_until_date(banned_until_date), string());
96 }
97 
GroupAdministrator(bool is_creator)98 DialogParticipantStatus DialogParticipantStatus::GroupAdministrator(bool is_creator) {
99   return Administrator(false, string(), is_creator, true, true, false, false, true, true, true, true, false, true);
100 }
101 
ChannelAdministrator(bool is_creator,bool is_megagroup)102 DialogParticipantStatus DialogParticipantStatus::ChannelAdministrator(bool is_creator, bool is_megagroup) {
103   if (is_megagroup) {
104     return Administrator(false, string(), is_creator, true, true, false, false, true, true, true, true, false, false);
105   } else {
106     return Administrator(false, string(), is_creator, true, false, true, true, true, false, true, false, false, false);
107   }
108 }
109 
get_restricted_rights() const110 RestrictedRights DialogParticipantStatus::get_restricted_rights() const {
111   return RestrictedRights(can_send_messages(), can_send_media(), can_send_stickers(), can_send_animations(),
112                           can_send_games(), can_use_inline_bots(), can_add_web_page_previews(), can_send_polls(),
113                           can_change_info_and_settings(), can_invite_users(), can_pin_messages());
114 }
115 
get_chat_member_status_object() const116 tl_object_ptr<td_api::ChatMemberStatus> DialogParticipantStatus::get_chat_member_status_object() const {
117   switch (type_) {
118     case Type::Creator:
119       return td_api::make_object<td_api::chatMemberStatusCreator>(rank_, is_anonymous(), is_member());
120     case Type::Administrator:
121       return td_api::make_object<td_api::chatMemberStatusAdministrator>(
122           rank_, can_be_edited(), can_manage_dialog(), can_change_info_and_settings(), can_post_messages(),
123           can_edit_messages(), can_delete_messages(), can_invite_users(), can_restrict_members(), can_pin_messages(),
124           can_promote_members(), can_manage_calls(), is_anonymous());
125     case Type::Member:
126       return td_api::make_object<td_api::chatMemberStatusMember>();
127     case Type::Restricted:
128       return td_api::make_object<td_api::chatMemberStatusRestricted>(
129           is_member(), until_date_, get_restricted_rights().get_chat_permissions_object());
130     case Type::Left:
131       return td_api::make_object<td_api::chatMemberStatusLeft>();
132     case Type::Banned:
133       return td_api::make_object<td_api::chatMemberStatusBanned>(until_date_);
134     default:
135       UNREACHABLE();
136       return nullptr;
137   }
138 }
139 
get_chat_admin_rights() const140 tl_object_ptr<telegram_api::chatAdminRights> DialogParticipantStatus::get_chat_admin_rights() const {
141   int32 flags = 0;
142   if ((flags_ & CAN_CHANGE_INFO_AND_SETTINGS_ADMIN) != 0) {
143     flags |= telegram_api::chatAdminRights::CHANGE_INFO_MASK;
144   }
145   if (can_post_messages()) {
146     flags |= telegram_api::chatAdminRights::POST_MESSAGES_MASK;
147   }
148   if (can_edit_messages()) {
149     flags |= telegram_api::chatAdminRights::EDIT_MESSAGES_MASK;
150   }
151   if (can_delete_messages()) {
152     flags |= telegram_api::chatAdminRights::DELETE_MESSAGES_MASK;
153   }
154   if ((flags_ & CAN_INVITE_USERS_ADMIN) != 0) {
155     flags |= telegram_api::chatAdminRights::INVITE_USERS_MASK;
156   }
157   if (can_restrict_members()) {
158     flags |= telegram_api::chatAdminRights::BAN_USERS_MASK;
159   }
160   if ((flags_ & CAN_PIN_MESSAGES_ADMIN) != 0) {
161     flags |= telegram_api::chatAdminRights::PIN_MESSAGES_MASK;
162   }
163   if (can_promote_members()) {
164     flags |= telegram_api::chatAdminRights::ADD_ADMINS_MASK;
165   }
166   if (can_manage_calls()) {
167     flags |= telegram_api::chatAdminRights::MANAGE_CALL_MASK;
168   }
169   if (is_anonymous()) {
170     flags |= telegram_api::chatAdminRights::ANONYMOUS_MASK;
171   }
172   if (can_manage_dialog()) {
173     flags |= telegram_api::chatAdminRights::OTHER_MASK;
174   }
175 
176   LOG(INFO) << "Create chat admin rights " << flags;
177   return make_tl_object<telegram_api::chatAdminRights>(
178       flags, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/,
179       false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/);
180 }
181 
get_chat_banned_rights() const182 tl_object_ptr<telegram_api::chatBannedRights> DialogParticipantStatus::get_chat_banned_rights() const {
183   int32 flags = 0;
184   if (type_ == Type::Banned) {
185     flags |= telegram_api::chatBannedRights::VIEW_MESSAGES_MASK;
186   }
187   if (!can_send_messages()) {
188     flags |= telegram_api::chatBannedRights::SEND_MESSAGES_MASK;
189   }
190   if (!can_send_media()) {
191     flags |= telegram_api::chatBannedRights::SEND_MEDIA_MASK;
192   }
193   if (!can_send_stickers()) {
194     flags |= telegram_api::chatBannedRights::SEND_STICKERS_MASK;
195   }
196   if (!can_send_animations()) {
197     flags |= telegram_api::chatBannedRights::SEND_GIFS_MASK;
198   }
199   if (!can_send_games()) {
200     flags |= telegram_api::chatBannedRights::SEND_GAMES_MASK;
201   }
202   if (!can_use_inline_bots()) {
203     flags |= telegram_api::chatBannedRights::SEND_INLINE_MASK;
204   }
205   if (!can_add_web_page_previews()) {
206     flags |= telegram_api::chatBannedRights::EMBED_LINKS_MASK;
207   }
208   if (!can_send_polls()) {
209     flags |= telegram_api::chatBannedRights::SEND_POLLS_MASK;
210   }
211   if ((flags_ & CAN_CHANGE_INFO_AND_SETTINGS_BANNED) == 0) {
212     flags |= telegram_api::chatBannedRights::CHANGE_INFO_MASK;
213   }
214   if ((flags_ & CAN_INVITE_USERS_BANNED) == 0) {
215     flags |= telegram_api::chatBannedRights::INVITE_USERS_MASK;
216   }
217   if ((flags_ & CAN_PIN_MESSAGES_BANNED) == 0) {
218     flags |= telegram_api::chatBannedRights::PIN_MESSAGES_MASK;
219   }
220 
221   LOG(INFO) << "Create chat banned rights " << flags << " until " << until_date_;
222   return make_tl_object<telegram_api::chatBannedRights>(
223       flags, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/,
224       false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/,
225       false /*ignored*/, until_date_);
226 }
227 
apply_restrictions(RestrictedRights default_restrictions,bool is_bot) const228 DialogParticipantStatus DialogParticipantStatus::apply_restrictions(RestrictedRights default_restrictions,
229                                                                     bool is_bot) const {
230   auto flags = flags_;
231   switch (type_) {
232     case Type::Creator:
233       // creator can do anything and isn't affected by restrictions
234       break;
235     case Type::Administrator:
236       // administrators aren't affected by restrictions, but if everyone can invite users,
237       // pin messages or change info, they also can do that
238       if (!is_bot) {
239         flags |= default_restrictions.flags_ & ALL_ADMIN_PERMISSION_RIGHTS;
240       }
241       break;
242     case Type::Member:
243     case Type::Restricted:
244     case Type::Left:
245       // members and restricted are affected by default restrictions
246       flags &= ~ALL_PERMISSION_RIGHTS | default_restrictions.flags_;
247       if (is_bot) {
248         flags &= ~ALL_ADMIN_PERMISSION_RIGHTS;
249       }
250       break;
251     case Type::Banned:
252       // banned can do nothing, even restrictions allows them to do that
253       break;
254     default:
255       UNREACHABLE();
256       break;
257   }
258 
259   return DialogParticipantStatus(type_, flags, 0, string());
260 }
261 
update_restrictions() const262 void DialogParticipantStatus::update_restrictions() const {
263   if (until_date_ != 0 && G()->unix_time() > until_date_) {
264     until_date_ = 0;
265     if (type_ == Type::Restricted) {
266       if (is_member()) {
267         type_ = Type::Member;
268       } else {
269         type_ = Type::Left;
270       }
271       flags_ |= ALL_PERMISSION_RIGHTS;
272     } else if (type_ == Type::Banned) {
273       type_ = Type::Left;
274     } else {
275       UNREACHABLE();
276     }
277   }
278 }
279 
operator ==(const DialogParticipantStatus & lhs,const DialogParticipantStatus & rhs)280 bool operator==(const DialogParticipantStatus &lhs, const DialogParticipantStatus &rhs) {
281   return lhs.type_ == rhs.type_ && lhs.flags_ == rhs.flags_ && lhs.until_date_ == rhs.until_date_ &&
282          lhs.rank_ == rhs.rank_;
283 }
284 
operator !=(const DialogParticipantStatus & lhs,const DialogParticipantStatus & rhs)285 bool operator!=(const DialogParticipantStatus &lhs, const DialogParticipantStatus &rhs) {
286   return !(lhs == rhs);
287 }
288 
operator <<(StringBuilder & string_builder,const DialogParticipantStatus & status)289 StringBuilder &operator<<(StringBuilder &string_builder, const DialogParticipantStatus &status) {
290   switch (status.type_) {
291     case DialogParticipantStatus::Type::Creator:
292       string_builder << "Creator";
293       if (!status.is_member()) {
294         string_builder << "-non-member";
295       }
296       if (!status.rank_.empty()) {
297         string_builder << " [" << status.rank_ << "]";
298       }
299       if (status.is_anonymous()) {
300         string_builder << "-anonymous";
301       }
302       return string_builder;
303     case DialogParticipantStatus::Type::Administrator:
304       string_builder << "Administrator: ";
305       if (status.can_manage_dialog()) {
306         string_builder << "(manage)";
307       }
308       if (status.can_change_info_and_settings()) {
309         string_builder << "(change)";
310       }
311       if (status.can_post_messages()) {
312         string_builder << "(post)";
313       }
314       if (status.can_edit_messages()) {
315         string_builder << "(edit)";
316       }
317       if (status.can_delete_messages()) {
318         string_builder << "(delete)";
319       }
320       if (status.can_invite_users()) {
321         string_builder << "(invite)";
322       }
323       if (status.can_restrict_members()) {
324         string_builder << "(restrict)";
325       }
326       if (status.can_pin_messages()) {
327         string_builder << "(pin)";
328       }
329       if (status.can_promote_members()) {
330         string_builder << "(promote)";
331       }
332       if (status.can_manage_calls()) {
333         string_builder << "(voice chat)";
334       }
335       if (!status.rank_.empty()) {
336         string_builder << " [" << status.rank_ << "]";
337       }
338       if (status.is_anonymous()) {
339         string_builder << "-anonymous";
340       }
341       return string_builder;
342     case DialogParticipantStatus::Type::Member:
343       return string_builder << "Member";
344     case DialogParticipantStatus::Type::Restricted:
345       string_builder << "Restricted ";
346       if (status.until_date_ == 0) {
347         string_builder << "forever ";
348       } else {
349         string_builder << "until " << status.until_date_ << " ";
350       }
351       if (!status.is_member()) {
352         string_builder << "non-";
353       }
354       string_builder << "member: ";
355       if (!status.can_send_messages()) {
356         string_builder << "(text)";
357       }
358       if (!status.can_send_media()) {
359         string_builder << "(media)";
360       }
361       if (!status.can_send_stickers()) {
362         string_builder << "(stickers)";
363       }
364       if (!status.can_send_animations()) {
365         string_builder << "(animations)";
366       }
367       if (!status.can_send_games()) {
368         string_builder << "(games)";
369       }
370       if (!status.can_send_polls()) {
371         string_builder << "(polls)";
372       }
373       if (!status.can_use_inline_bots()) {
374         string_builder << "(inline bots)";
375       }
376       if (!status.can_add_web_page_previews()) {
377         string_builder << "(links)";
378       }
379       if (!status.can_change_info_and_settings()) {
380         string_builder << "(change)";
381       }
382       if (!status.can_invite_users()) {
383         string_builder << "(invite)";
384       }
385       if (!status.can_pin_messages()) {
386         string_builder << "(pin)";
387       }
388       return string_builder;
389     case DialogParticipantStatus::Type::Left:
390       return string_builder << "Left";
391     case DialogParticipantStatus::Type::Banned:
392       string_builder << "Banned ";
393       if (status.until_date_ == 0) {
394         string_builder << "forever";
395       } else {
396         string_builder << "until " << status.until_date_;
397       }
398       return string_builder;
399     default:
400       UNREACHABLE();
401       return string_builder << "Impossible";
402   }
403 }
404 
get_dialog_participant_status(const tl_object_ptr<td_api::ChatMemberStatus> & status)405 DialogParticipantStatus get_dialog_participant_status(const tl_object_ptr<td_api::ChatMemberStatus> &status) {
406   auto constructor_id = status == nullptr ? td_api::chatMemberStatusMember::ID : status->get_id();
407   switch (constructor_id) {
408     case td_api::chatMemberStatusCreator::ID: {
409       auto st = static_cast<const td_api::chatMemberStatusCreator *>(status.get());
410       auto custom_title = st->custom_title_;
411       if (!clean_input_string(custom_title)) {
412         custom_title.clear();
413       }
414       return DialogParticipantStatus::Creator(st->is_member_, st->is_anonymous_, custom_title);
415     }
416     case td_api::chatMemberStatusAdministrator::ID: {
417       auto st = static_cast<const td_api::chatMemberStatusAdministrator *>(status.get());
418       auto custom_title = st->custom_title_;
419       if (!clean_input_string(custom_title)) {
420         custom_title.clear();
421       }
422       return DialogParticipantStatus::Administrator(
423           st->is_anonymous_, custom_title, true /*st->can_be_edited_*/, st->can_manage_chat_, st->can_change_info_,
424           st->can_post_messages_, st->can_edit_messages_, st->can_delete_messages_, st->can_invite_users_,
425           st->can_restrict_members_, st->can_pin_messages_, st->can_promote_members_, st->can_manage_video_chats_);
426     }
427     case td_api::chatMemberStatusMember::ID:
428       return DialogParticipantStatus::Member();
429     case td_api::chatMemberStatusRestricted::ID: {
430       auto st = static_cast<const td_api::chatMemberStatusRestricted *>(status.get());
431       auto permissions = st->permissions_.get();
432       if (permissions == nullptr) {
433         return DialogParticipantStatus::Restricted(st->is_member_, st->restricted_until_date_, false, false, false,
434                                                    false, false, false, false, false, false, false, false);
435       }
436       bool can_send_polls = permissions->can_send_polls_;
437       bool can_send_media = permissions->can_send_media_messages_;
438       bool can_send_messages = permissions->can_send_messages_ || can_send_media || can_send_polls ||
439                                permissions->can_send_other_messages_ || permissions->can_add_web_page_previews_;
440       return DialogParticipantStatus::Restricted(
441           st->is_member_, st->restricted_until_date_, can_send_messages, can_send_media,
442           permissions->can_send_other_messages_, permissions->can_send_other_messages_,
443           permissions->can_send_other_messages_, permissions->can_send_other_messages_,
444           permissions->can_add_web_page_previews_, permissions->can_send_polls_, permissions->can_change_info_,
445           permissions->can_invite_users_, permissions->can_pin_messages_);
446     }
447     case td_api::chatMemberStatusLeft::ID:
448       return DialogParticipantStatus::Left();
449     case td_api::chatMemberStatusBanned::ID: {
450       auto st = static_cast<const td_api::chatMemberStatusBanned *>(status.get());
451       return DialogParticipantStatus::Banned(st->banned_until_date_);
452     }
453     default:
454       UNREACHABLE();
455       return DialogParticipantStatus::Member();
456   }
457 }
458 
get_dialog_participant_status(bool can_be_edited,tl_object_ptr<telegram_api::chatAdminRights> && admin_rights,string rank)459 DialogParticipantStatus get_dialog_participant_status(bool can_be_edited,
460                                                       tl_object_ptr<telegram_api::chatAdminRights> &&admin_rights,
461                                                       string rank) {
462   bool can_change_info = (admin_rights->flags_ & telegram_api::chatAdminRights::CHANGE_INFO_MASK) != 0;
463   bool can_post_messages = (admin_rights->flags_ & telegram_api::chatAdminRights::POST_MESSAGES_MASK) != 0;
464   bool can_edit_messages = (admin_rights->flags_ & telegram_api::chatAdminRights::EDIT_MESSAGES_MASK) != 0;
465   bool can_delete_messages = (admin_rights->flags_ & telegram_api::chatAdminRights::DELETE_MESSAGES_MASK) != 0;
466   bool can_invite_users = (admin_rights->flags_ & telegram_api::chatAdminRights::INVITE_USERS_MASK) != 0;
467   bool can_restrict_members = (admin_rights->flags_ & telegram_api::chatAdminRights::BAN_USERS_MASK) != 0;
468   bool can_pin_messages = (admin_rights->flags_ & telegram_api::chatAdminRights::PIN_MESSAGES_MASK) != 0;
469   bool can_promote_members = (admin_rights->flags_ & telegram_api::chatAdminRights::ADD_ADMINS_MASK) != 0;
470   bool can_manage_calls = (admin_rights->flags_ & telegram_api::chatAdminRights::MANAGE_CALL_MASK) != 0;
471   bool is_anonymous = (admin_rights->flags_ & telegram_api::chatAdminRights::ANONYMOUS_MASK) != 0;
472   bool can_manage_dialog = (admin_rights->flags_ & telegram_api::chatAdminRights::OTHER_MASK) != 0;
473   if (!can_manage_dialog) {
474     LOG(ERROR) << "Receive wrong other flag in " << to_string(admin_rights);
475   }
476   return DialogParticipantStatus::Administrator(is_anonymous, std::move(rank), can_be_edited, can_manage_dialog,
477                                                 can_change_info, can_post_messages, can_edit_messages,
478                                                 can_delete_messages, can_invite_users, can_restrict_members,
479                                                 can_pin_messages, can_promote_members, can_manage_calls);
480 }
481 
get_dialog_participant_status(bool is_member,tl_object_ptr<telegram_api::chatBannedRights> && banned_rights)482 DialogParticipantStatus get_dialog_participant_status(bool is_member,
483                                                       tl_object_ptr<telegram_api::chatBannedRights> &&banned_rights) {
484   bool can_view_messages = (banned_rights->flags_ & telegram_api::chatBannedRights::VIEW_MESSAGES_MASK) == 0;
485   if (!can_view_messages) {
486     return DialogParticipantStatus::Banned(banned_rights->until_date_);
487   }
488   bool can_send_messages = (banned_rights->flags_ & telegram_api::chatBannedRights::SEND_MESSAGES_MASK) == 0;
489   bool can_send_media_messages = (banned_rights->flags_ & telegram_api::chatBannedRights::SEND_MEDIA_MASK) == 0;
490   bool can_send_stickers = (banned_rights->flags_ & telegram_api::chatBannedRights::SEND_STICKERS_MASK) == 0;
491   bool can_send_animations = (banned_rights->flags_ & telegram_api::chatBannedRights::SEND_GIFS_MASK) == 0;
492   bool can_send_games = (banned_rights->flags_ & telegram_api::chatBannedRights::SEND_GAMES_MASK) == 0;
493   bool can_use_inline_bots = (banned_rights->flags_ & telegram_api::chatBannedRights::SEND_INLINE_MASK) == 0;
494   bool can_add_web_page_previews = (banned_rights->flags_ & telegram_api::chatBannedRights::EMBED_LINKS_MASK) == 0;
495   bool can_send_polls = (banned_rights->flags_ & telegram_api::chatBannedRights::SEND_POLLS_MASK) == 0;
496   bool can_change_info_and_settings = (banned_rights->flags_ & telegram_api::chatBannedRights::CHANGE_INFO_MASK) == 0;
497   bool can_invite_users = (banned_rights->flags_ & telegram_api::chatBannedRights::INVITE_USERS_MASK) == 0;
498   bool can_pin_messages = (banned_rights->flags_ & telegram_api::chatBannedRights::PIN_MESSAGES_MASK) == 0;
499   return DialogParticipantStatus::Restricted(
500       is_member, banned_rights->until_date_, can_send_messages, can_send_media_messages, can_send_stickers,
501       can_send_animations, can_send_games, can_use_inline_bots, can_add_web_page_previews, can_send_polls,
502       can_change_info_and_settings, can_invite_users, can_pin_messages);
503 }
504 
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,bool can_change_info_and_settings,bool can_invite_users,bool can_pin_messages)505 RestrictedRights::RestrictedRights(bool can_send_messages, bool can_send_media, bool can_send_stickers,
506                                    bool can_send_animations, bool can_send_games, bool can_use_inline_bots,
507                                    bool can_add_web_page_previews, bool can_send_polls,
508                                    bool can_change_info_and_settings, bool can_invite_users, bool can_pin_messages) {
509   flags_ = (static_cast<uint32>(can_send_messages) * CAN_SEND_MESSAGES) |
510            (static_cast<uint32>(can_send_media) * CAN_SEND_MEDIA) |
511            (static_cast<uint32>(can_send_stickers) * CAN_SEND_STICKERS) |
512            (static_cast<uint32>(can_send_animations) * CAN_SEND_ANIMATIONS) |
513            (static_cast<uint32>(can_send_games) * CAN_SEND_GAMES) |
514            (static_cast<uint32>(can_use_inline_bots) * CAN_USE_INLINE_BOTS) |
515            (static_cast<uint32>(can_add_web_page_previews) * CAN_ADD_WEB_PAGE_PREVIEWS) |
516            (static_cast<uint32>(can_send_polls) * CAN_SEND_POLLS) |
517            (static_cast<uint32>(can_change_info_and_settings) * CAN_CHANGE_INFO_AND_SETTINGS) |
518            (static_cast<uint32>(can_invite_users) * CAN_INVITE_USERS) |
519            (static_cast<uint32>(can_pin_messages) * CAN_PIN_MESSAGES);
520 }
521 
get_chat_permissions_object() const522 tl_object_ptr<td_api::chatPermissions> RestrictedRights::get_chat_permissions_object() const {
523   return td_api::make_object<td_api::chatPermissions>(
524       can_send_messages(), can_send_media(), can_send_polls(),
525       can_send_stickers() || can_send_animations() || can_send_games() || can_use_inline_bots(),
526       can_add_web_page_previews(), can_change_info_and_settings(), can_invite_users(), can_pin_messages());
527 }
528 
get_chat_banned_rights() const529 tl_object_ptr<telegram_api::chatBannedRights> RestrictedRights::get_chat_banned_rights() const {
530   int32 flags = 0;
531   if (!can_send_messages()) {
532     flags |= telegram_api::chatBannedRights::SEND_MESSAGES_MASK;
533   }
534   if (!can_send_media()) {
535     flags |= telegram_api::chatBannedRights::SEND_MEDIA_MASK;
536   }
537   if (!can_send_stickers()) {
538     flags |= telegram_api::chatBannedRights::SEND_STICKERS_MASK;
539   }
540   if (!can_send_animations()) {
541     flags |= telegram_api::chatBannedRights::SEND_GIFS_MASK;
542   }
543   if (!can_send_games()) {
544     flags |= telegram_api::chatBannedRights::SEND_GAMES_MASK;
545   }
546   if (!can_use_inline_bots()) {
547     flags |= telegram_api::chatBannedRights::SEND_INLINE_MASK;
548   }
549   if (!can_add_web_page_previews()) {
550     flags |= telegram_api::chatBannedRights::EMBED_LINKS_MASK;
551   }
552   if (!can_send_polls()) {
553     flags |= telegram_api::chatBannedRights::SEND_POLLS_MASK;
554   }
555   if (!can_change_info_and_settings()) {
556     flags |= telegram_api::chatBannedRights::CHANGE_INFO_MASK;
557   }
558   if (!can_invite_users()) {
559     flags |= telegram_api::chatBannedRights::INVITE_USERS_MASK;
560   }
561   if (!can_pin_messages()) {
562     flags |= telegram_api::chatBannedRights::PIN_MESSAGES_MASK;
563   }
564 
565   LOG(INFO) << "Create chat banned rights " << flags;
566   return make_tl_object<telegram_api::chatBannedRights>(flags, false /*ignored*/, false /*ignored*/, false /*ignored*/,
567                                                         false /*ignored*/, false /*ignored*/, false /*ignored*/,
568                                                         false /*ignored*/, false /*ignored*/, false /*ignored*/,
569                                                         false /*ignored*/, false /*ignored*/, false /*ignored*/, 0);
570 }
571 
operator ==(const RestrictedRights & lhs,const RestrictedRights & rhs)572 bool operator==(const RestrictedRights &lhs, const RestrictedRights &rhs) {
573   return lhs.flags_ == rhs.flags_;
574 }
575 
operator !=(const RestrictedRights & lhs,const RestrictedRights & rhs)576 bool operator!=(const RestrictedRights &lhs, const RestrictedRights &rhs) {
577   return !(lhs == rhs);
578 }
579 
operator <<(StringBuilder & string_builder,const RestrictedRights & status)580 StringBuilder &operator<<(StringBuilder &string_builder, const RestrictedRights &status) {
581   string_builder << "Restricted: ";
582   if (!status.can_send_messages()) {
583     string_builder << "(text)";
584   }
585   if (!status.can_send_media()) {
586     string_builder << "(media)";
587   }
588   if (!status.can_send_stickers()) {
589     string_builder << "(stickers)";
590   }
591   if (!status.can_send_animations()) {
592     string_builder << "(animations)";
593   }
594   if (!status.can_send_games()) {
595     string_builder << "(games)";
596   }
597   if (!status.can_send_polls()) {
598     string_builder << "(polls)";
599   }
600   if (!status.can_use_inline_bots()) {
601     string_builder << "(inline bots)";
602   }
603   if (!status.can_add_web_page_previews()) {
604     string_builder << "(links)";
605   }
606   if (!status.can_change_info_and_settings()) {
607     string_builder << "(change)";
608   }
609   if (!status.can_invite_users()) {
610     string_builder << "(invite)";
611   }
612   if (!status.can_pin_messages()) {
613     string_builder << "(pin)";
614   }
615   return string_builder;
616 }
617 
get_restricted_rights(tl_object_ptr<telegram_api::chatBannedRights> && banned_rights)618 RestrictedRights get_restricted_rights(tl_object_ptr<telegram_api::chatBannedRights> &&banned_rights) {
619   if (banned_rights == nullptr) {
620     return RestrictedRights(false, false, false, false, false, false, false, false, false, false, false);
621   }
622   bool can_view_messages = (banned_rights->flags_ & telegram_api::chatBannedRights::VIEW_MESSAGES_MASK) == 0;
623   if (!can_view_messages) {
624     LOG(ERROR) << "Can't view messages in restricted rights " << to_string(banned_rights);
625   }
626   LOG_IF(ERROR, banned_rights->until_date_ != std::numeric_limits<int32>::max())
627       << "Have until date " << banned_rights->until_date_ << " in restricted rights";
628 
629   bool can_send_messages = (banned_rights->flags_ & telegram_api::chatBannedRights::SEND_MESSAGES_MASK) == 0;
630   bool can_send_media_messages = (banned_rights->flags_ & telegram_api::chatBannedRights::SEND_MEDIA_MASK) == 0;
631   bool can_send_stickers = (banned_rights->flags_ & telegram_api::chatBannedRights::SEND_STICKERS_MASK) == 0;
632   bool can_send_animations = (banned_rights->flags_ & telegram_api::chatBannedRights::SEND_GIFS_MASK) == 0;
633   bool can_send_games = (banned_rights->flags_ & telegram_api::chatBannedRights::SEND_GAMES_MASK) == 0;
634   bool can_use_inline_bots = (banned_rights->flags_ & telegram_api::chatBannedRights::SEND_INLINE_MASK) == 0;
635   bool can_add_web_page_previews = (banned_rights->flags_ & telegram_api::chatBannedRights::EMBED_LINKS_MASK) == 0;
636   bool can_send_polls = (banned_rights->flags_ & telegram_api::chatBannedRights::SEND_POLLS_MASK) == 0;
637   bool can_change_info_and_settings = (banned_rights->flags_ & telegram_api::chatBannedRights::CHANGE_INFO_MASK) == 0;
638   bool can_invite_users = (banned_rights->flags_ & telegram_api::chatBannedRights::INVITE_USERS_MASK) == 0;
639   bool can_pin_messages = (banned_rights->flags_ & telegram_api::chatBannedRights::PIN_MESSAGES_MASK) == 0;
640   return RestrictedRights(can_send_messages, can_send_media_messages, can_send_stickers, can_send_animations,
641                           can_send_games, can_use_inline_bots, can_add_web_page_previews, can_send_polls,
642                           can_change_info_and_settings, can_invite_users, can_pin_messages);
643 }
644 
get_restricted_rights(const td_api::object_ptr<td_api::chatPermissions> & permissions)645 RestrictedRights get_restricted_rights(const td_api::object_ptr<td_api::chatPermissions> &permissions) {
646   bool can_send_polls = permissions->can_send_polls_;
647   bool can_send_media = permissions->can_send_media_messages_;
648   bool can_send_messages = permissions->can_send_messages_ || can_send_media || can_send_polls ||
649                            permissions->can_send_other_messages_ || permissions->can_add_web_page_previews_;
650   return RestrictedRights(can_send_messages, can_send_media, permissions->can_send_other_messages_,
651                           permissions->can_send_other_messages_, permissions->can_send_other_messages_,
652                           permissions->can_send_other_messages_, permissions->can_add_web_page_previews_,
653                           permissions->can_send_polls_, permissions->can_change_info_, permissions->can_invite_users_,
654                           permissions->can_pin_messages_);
655 }
656 
DialogParticipant(DialogId dialog_id,UserId inviter_user_id,int32 joined_date,DialogParticipantStatus status)657 DialogParticipant::DialogParticipant(DialogId dialog_id, UserId inviter_user_id, int32 joined_date,
658                                      DialogParticipantStatus status)
659     : dialog_id_(dialog_id), inviter_user_id_(inviter_user_id), joined_date_(joined_date), status_(std::move(status)) {
660   if (!inviter_user_id_.is_valid() && inviter_user_id_ != UserId()) {
661     LOG(ERROR) << "Receive inviter " << inviter_user_id_;
662     inviter_user_id_ = UserId();
663   }
664   if (joined_date_ < 0) {
665     LOG(ERROR) << "Receive date " << joined_date_;
666     joined_date_ = 0;
667   }
668 }
669 
DialogParticipant(tl_object_ptr<telegram_api::ChatParticipant> && participant_ptr,int32 chat_creation_date,bool is_creator)670 DialogParticipant::DialogParticipant(tl_object_ptr<telegram_api::ChatParticipant> &&participant_ptr,
671                                      int32 chat_creation_date, bool is_creator) {
672   switch (participant_ptr->get_id()) {
673     case telegram_api::chatParticipant::ID: {
674       auto participant = move_tl_object_as<telegram_api::chatParticipant>(participant_ptr);
675       *this = {DialogId(UserId(participant->user_id_)), UserId(participant->inviter_id_), participant->date_,
676                DialogParticipantStatus::Member()};
677       break;
678     }
679     case telegram_api::chatParticipantCreator::ID: {
680       auto participant = move_tl_object_as<telegram_api::chatParticipantCreator>(participant_ptr);
681       *this = {DialogId(UserId(participant->user_id_)), UserId(participant->user_id_), chat_creation_date,
682                DialogParticipantStatus::Creator(true, false, string())};
683       break;
684     }
685     case telegram_api::chatParticipantAdmin::ID: {
686       auto participant = move_tl_object_as<telegram_api::chatParticipantAdmin>(participant_ptr);
687       *this = {DialogId(UserId(participant->user_id_)), UserId(participant->inviter_id_), participant->date_,
688                DialogParticipantStatus::GroupAdministrator(is_creator)};
689       break;
690     }
691     default:
692       UNREACHABLE();
693   }
694 }
695 
DialogParticipant(tl_object_ptr<telegram_api::ChannelParticipant> && participant_ptr)696 DialogParticipant::DialogParticipant(tl_object_ptr<telegram_api::ChannelParticipant> &&participant_ptr) {
697   CHECK(participant_ptr != nullptr);
698 
699   switch (participant_ptr->get_id()) {
700     case telegram_api::channelParticipant::ID: {
701       auto participant = move_tl_object_as<telegram_api::channelParticipant>(participant_ptr);
702       *this = {DialogId(UserId(participant->user_id_)), UserId(), participant->date_,
703                DialogParticipantStatus::Member()};
704       break;
705     }
706     case telegram_api::channelParticipantSelf::ID: {
707       auto participant = move_tl_object_as<telegram_api::channelParticipantSelf>(participant_ptr);
708       *this = {DialogId(UserId(participant->user_id_)), UserId(participant->inviter_id_), participant->date_,
709                DialogParticipantStatus::Member()};
710       break;
711     }
712     case telegram_api::channelParticipantCreator::ID: {
713       auto participant = move_tl_object_as<telegram_api::channelParticipantCreator>(participant_ptr);
714       *this = {DialogId(UserId(participant->user_id_)), UserId(), 0,
715                DialogParticipantStatus::Creator(true, participant->admin_rights_->anonymous_,
716                                                 std::move(participant->rank_))};
717       break;
718     }
719     case telegram_api::channelParticipantAdmin::ID: {
720       auto participant = move_tl_object_as<telegram_api::channelParticipantAdmin>(participant_ptr);
721       *this = {DialogId(UserId(participant->user_id_)), UserId(participant->promoted_by_), participant->date_,
722                get_dialog_participant_status(participant->can_edit_, std::move(participant->admin_rights_),
723                                              std::move(participant->rank_))};
724       break;
725     }
726     case telegram_api::channelParticipantLeft::ID: {
727       auto participant = move_tl_object_as<telegram_api::channelParticipantLeft>(participant_ptr);
728       *this = {DialogId(participant->peer_), UserId(), 0, DialogParticipantStatus::Left()};
729       break;
730     }
731     case telegram_api::channelParticipantBanned::ID: {
732       auto participant = move_tl_object_as<telegram_api::channelParticipantBanned>(participant_ptr);
733       *this = {DialogId(participant->peer_), UserId(participant->kicked_by_), participant->date_,
734                get_dialog_participant_status(!participant->left_, std::move(participant->banned_rights_))};
735       break;
736     }
737     default:
738       UNREACHABLE();
739       break;
740   }
741 }
742 
is_valid() const743 bool DialogParticipant::is_valid() const {
744   if (!dialog_id_.is_valid() || joined_date_ < 0) {
745     return false;
746   }
747   if (status_.is_restricted() || status_.is_banned() || (status_.is_administrator() && !status_.is_creator())) {
748     return inviter_user_id_.is_valid();
749   }
750   return true;
751 }
752 
operator <<(StringBuilder & string_builder,const DialogParticipant & dialog_participant)753 StringBuilder &operator<<(StringBuilder &string_builder, const DialogParticipant &dialog_participant) {
754   return string_builder << '[' << dialog_participant.dialog_id_ << " invited by " << dialog_participant.inviter_user_id_
755                         << " at " << dialog_participant.joined_date_ << " with status " << dialog_participant.status_
756                         << ']';
757 }
758 
get_chat_members_object(Td * td) const759 td_api::object_ptr<td_api::chatMembers> DialogParticipants::get_chat_members_object(Td *td) const {
760   vector<tl_object_ptr<td_api::chatMember>> chat_members;
761   chat_members.reserve(participants_.size());
762   for (auto &participant : participants_) {
763     chat_members.push_back(td->contacts_manager_->get_chat_member_object(participant));
764   }
765 
766   return td_api::make_object<td_api::chatMembers>(total_count_, std::move(chat_members));
767 }
768 
769 tl_object_ptr<telegram_api::ChannelParticipantsFilter>
get_input_channel_participants_filter() const770 ChannelParticipantsFilter::get_input_channel_participants_filter() const {
771   switch (type_) {
772     case Type::Recent:
773       return make_tl_object<telegram_api::channelParticipantsRecent>();
774     case Type::Contacts:
775       return make_tl_object<telegram_api::channelParticipantsContacts>(query_);
776     case Type::Administrators:
777       return make_tl_object<telegram_api::channelParticipantsAdmins>();
778     case Type::Search:
779       return make_tl_object<telegram_api::channelParticipantsSearch>(query_);
780     case Type::Mention: {
781       int32 flags = 0;
782       if (!query_.empty()) {
783         flags |= telegram_api::channelParticipantsMentions::Q_MASK;
784       }
785       if (top_thread_message_id_.is_valid()) {
786         flags |= telegram_api::channelParticipantsMentions::TOP_MSG_ID_MASK;
787       }
788       return make_tl_object<telegram_api::channelParticipantsMentions>(
789           flags, query_, top_thread_message_id_.get_server_message_id().get());
790     }
791     case Type::Restricted:
792       return make_tl_object<telegram_api::channelParticipantsBanned>(query_);
793     case Type::Banned:
794       return make_tl_object<telegram_api::channelParticipantsKicked>(query_);
795     case Type::Bots:
796       return make_tl_object<telegram_api::channelParticipantsBots>();
797     default:
798       UNREACHABLE();
799       return nullptr;
800   }
801 }
802 
ChannelParticipantsFilter(const tl_object_ptr<td_api::SupergroupMembersFilter> & filter)803 ChannelParticipantsFilter::ChannelParticipantsFilter(const tl_object_ptr<td_api::SupergroupMembersFilter> &filter) {
804   if (filter == nullptr) {
805     type_ = Type::Recent;
806     return;
807   }
808   switch (filter->get_id()) {
809     case td_api::supergroupMembersFilterRecent::ID:
810       type_ = Type::Recent;
811       return;
812     case td_api::supergroupMembersFilterContacts::ID:
813       type_ = Type::Contacts;
814       query_ = static_cast<const td_api::supergroupMembersFilterContacts *>(filter.get())->query_;
815       return;
816     case td_api::supergroupMembersFilterAdministrators::ID:
817       type_ = Type::Administrators;
818       return;
819     case td_api::supergroupMembersFilterSearch::ID:
820       type_ = Type::Search;
821       query_ = static_cast<const td_api::supergroupMembersFilterSearch *>(filter.get())->query_;
822       return;
823     case td_api::supergroupMembersFilterMention::ID: {
824       auto mention_filter = static_cast<const td_api::supergroupMembersFilterMention *>(filter.get());
825       type_ = Type::Mention;
826       query_ = mention_filter->query_;
827       top_thread_message_id_ = MessageId(mention_filter->message_thread_id_);
828       if (!top_thread_message_id_.is_valid() || !top_thread_message_id_.is_server()) {
829         top_thread_message_id_ = MessageId();
830       }
831       return;
832     }
833     case td_api::supergroupMembersFilterRestricted::ID:
834       type_ = Type::Restricted;
835       query_ = static_cast<const td_api::supergroupMembersFilterRestricted *>(filter.get())->query_;
836       return;
837     case td_api::supergroupMembersFilterBanned::ID:
838       type_ = Type::Banned;
839       query_ = static_cast<const td_api::supergroupMembersFilterBanned *>(filter.get())->query_;
840       return;
841     case td_api::supergroupMembersFilterBots::ID:
842       type_ = Type::Bots;
843       return;
844     default:
845       UNREACHABLE();
846       type_ = Type::Recent;
847   }
848 }
849 
operator <<(StringBuilder & string_builder,const ChannelParticipantsFilter & filter)850 StringBuilder &operator<<(StringBuilder &string_builder, const ChannelParticipantsFilter &filter) {
851   switch (filter.type_) {
852     case ChannelParticipantsFilter::Type::Recent:
853       return string_builder << "Recent";
854     case ChannelParticipantsFilter::Type::Contacts:
855       return string_builder << "Contacts \"" << filter.query_ << '"';
856     case ChannelParticipantsFilter::Type::Administrators:
857       return string_builder << "Administrators";
858     case ChannelParticipantsFilter::Type::Search:
859       return string_builder << "Search \"" << filter.query_ << '"';
860     case ChannelParticipantsFilter::Type::Mention:
861       return string_builder << "Mention \"" << filter.query_ << "\" in thread of " << filter.top_thread_message_id_;
862     case ChannelParticipantsFilter::Type::Restricted:
863       return string_builder << "Restricted \"" << filter.query_ << '"';
864     case ChannelParticipantsFilter::Type::Banned:
865       return string_builder << "Banned \"" << filter.query_ << '"';
866     case ChannelParticipantsFilter::Type::Bots:
867       return string_builder << "Bots";
868     default:
869       UNREACHABLE();
870       return string_builder;
871   }
872 }
873 
operator <<(StringBuilder & string_builder,const DialogParticipantsFilter & filter)874 StringBuilder &operator<<(StringBuilder &string_builder, const DialogParticipantsFilter &filter) {
875   switch (filter.type_) {
876     case DialogParticipantsFilter::Type::Contacts:
877       return string_builder << "Contacts";
878     case DialogParticipantsFilter::Type::Administrators:
879       return string_builder << "Administrators";
880     case DialogParticipantsFilter::Type::Members:
881       return string_builder << "Members";
882     case DialogParticipantsFilter::Type::Restricted:
883       return string_builder << "Restricted";
884     case DialogParticipantsFilter::Type::Banned:
885       return string_builder << "Banned";
886     case DialogParticipantsFilter::Type::Mention:
887       return string_builder << "Mention";
888     case DialogParticipantsFilter::Type::Bots:
889       return string_builder << "Bots";
890     default:
891       UNREACHABLE();
892       return string_builder;
893   }
894 }
895 
DialogParticipantsFilter(const tl_object_ptr<td_api::ChatMembersFilter> & filter)896 DialogParticipantsFilter::DialogParticipantsFilter(const tl_object_ptr<td_api::ChatMembersFilter> &filter) {
897   if (filter == nullptr) {
898     type_ = Type::Members;
899     return;
900   }
901   switch (filter->get_id()) {
902     case td_api::chatMembersFilterContacts::ID:
903       type_ = Type::Contacts;
904       break;
905     case td_api::chatMembersFilterAdministrators::ID:
906       type_ = Type::Administrators;
907       break;
908     case td_api::chatMembersFilterMembers::ID:
909       type_ = Type::Members;
910       break;
911     case td_api::chatMembersFilterRestricted::ID:
912       type_ = Type::Restricted;
913       break;
914     case td_api::chatMembersFilterBanned::ID:
915       type_ = Type::Banned;
916       break;
917     case td_api::chatMembersFilterMention::ID: {
918       auto mention_filter = static_cast<const td_api::chatMembersFilterMention *>(filter.get());
919       top_thread_message_id_ = MessageId(mention_filter->message_thread_id_);
920       if (!top_thread_message_id_.is_valid() || !top_thread_message_id_.is_server()) {
921         top_thread_message_id_ = MessageId();
922       }
923       type_ = Type::Mention;
924       break;
925     }
926     case td_api::chatMembersFilterBots::ID:
927       type_ = Type::Bots;
928       break;
929     default:
930       UNREACHABLE();
931       type_ = Type::Members;
932       break;
933   }
934 }
935 
get_supergroup_members_filter_object(const string & query) const936 td_api::object_ptr<td_api::SupergroupMembersFilter> DialogParticipantsFilter::get_supergroup_members_filter_object(
937     const string &query) const {
938   switch (type_) {
939     case Type::Contacts:
940       return td_api::make_object<td_api::supergroupMembersFilterContacts>();
941     case Type::Administrators:
942       return td_api::make_object<td_api::supergroupMembersFilterAdministrators>();
943     case Type::Members:
944       return td_api::make_object<td_api::supergroupMembersFilterSearch>(query);
945     case Type::Restricted:
946       return td_api::make_object<td_api::supergroupMembersFilterRestricted>(query);
947     case Type::Banned:
948       return td_api::make_object<td_api::supergroupMembersFilterBanned>(query);
949     case Type::Mention:
950       return td_api::make_object<td_api::supergroupMembersFilterMention>(query, top_thread_message_id_.get());
951     case Type::Bots:
952       return td_api::make_object<td_api::supergroupMembersFilterBots>();
953     default:
954       UNREACHABLE();
955       return nullptr;
956   }
957 }
958 
has_query() const959 bool DialogParticipantsFilter::has_query() const {
960   switch (type_) {
961     case Type::Members:
962     case Type::Restricted:
963     case Type::Banned:
964     case Type::Mention:
965       return true;
966     case Type::Contacts:
967     case Type::Administrators:
968     case Type::Bots:
969       return false;
970     default:
971       UNREACHABLE();
972       return false;
973   }
974 }
975 
is_dialog_participant_suitable(const Td * td,const DialogParticipant & participant) const976 bool DialogParticipantsFilter::is_dialog_participant_suitable(const Td *td,
977                                                               const DialogParticipant &participant) const {
978   switch (type_) {
979     case Type::Contacts:
980       return participant.dialog_id_.get_type() == DialogType::User &&
981              td->contacts_manager_->is_user_contact(participant.dialog_id_.get_user_id());
982     case Type::Administrators:
983       return participant.status_.is_administrator();
984     case Type::Members:
985       return participant.status_.is_member();
986     case Type::Restricted:
987       return participant.status_.is_restricted();
988     case Type::Banned:
989       return participant.status_.is_banned();
990     case Type::Mention:
991       return true;
992     case Type::Bots:
993       return participant.dialog_id_.get_type() == DialogType::User &&
994              td->contacts_manager_->is_user_bot(participant.dialog_id_.get_user_id());
995     default:
996       UNREACHABLE();
997       return false;
998   }
999 }
1000 
1001 }  // namespace td
1002