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 #pragma once
8 
9 #include "td/telegram/DialogId.h"
10 #include "td/telegram/MessageId.h"
11 #include "td/telegram/td_api.h"
12 #include "td/telegram/telegram_api.h"
13 #include "td/telegram/UserId.h"
14 #include "td/telegram/Version.h"
15 
16 #include "td/utils/common.h"
17 #include "td/utils/StringBuilder.h"
18 #include "td/utils/tl_helpers.h"
19 
20 namespace td {
21 
22 class Td;
23 
24 class RestrictedRights {
25   static constexpr uint32 CAN_SEND_MESSAGES = 1 << 16;
26   static constexpr uint32 CAN_SEND_MEDIA = 1 << 17;
27   static constexpr uint32 CAN_SEND_STICKERS = 1 << 18;
28   static constexpr uint32 CAN_SEND_ANIMATIONS = 1 << 19;
29   static constexpr uint32 CAN_SEND_GAMES = 1 << 20;
30   static constexpr uint32 CAN_USE_INLINE_BOTS = 1 << 21;
31   static constexpr uint32 CAN_ADD_WEB_PAGE_PREVIEWS = 1 << 22;
32   static constexpr uint32 CAN_SEND_POLLS = 1 << 23;
33   static constexpr uint32 CAN_CHANGE_INFO_AND_SETTINGS = 1 << 24;
34   static constexpr uint32 CAN_INVITE_USERS = 1 << 25;
35   static constexpr uint32 CAN_PIN_MESSAGES = 1 << 26;
36 
37   uint32 flags_;
38 
39   friend class DialogParticipantStatus;
40 
41  public:
42   RestrictedRights(bool can_send_messages, bool can_send_media, bool can_send_stickers, bool can_send_animations,
43                    bool can_send_games, bool can_use_inline_bots, bool can_add_web_page_previews, bool can_send_polls,
44                    bool can_change_info_and_settings, bool can_invite_users, bool can_pin_messages);
45 
46   td_api::object_ptr<td_api::chatPermissions> get_chat_permissions_object() const;
47 
48   tl_object_ptr<telegram_api::chatBannedRights> get_chat_banned_rights() const;
49 
can_change_info_and_settings()50   bool can_change_info_and_settings() const {
51     return (flags_ & CAN_CHANGE_INFO_AND_SETTINGS) != 0;
52   }
53 
can_invite_users()54   bool can_invite_users() const {
55     return (flags_ & CAN_INVITE_USERS) != 0;
56   }
57 
can_pin_messages()58   bool can_pin_messages() const {
59     return (flags_ & CAN_PIN_MESSAGES) != 0;
60   }
61 
can_send_messages()62   bool can_send_messages() const {
63     return (flags_ & CAN_SEND_MESSAGES) != 0;
64   }
65 
can_send_media()66   bool can_send_media() const {
67     return (flags_ & CAN_SEND_MEDIA) != 0;
68   }
69 
can_send_stickers()70   bool can_send_stickers() const {
71     return (flags_ & CAN_SEND_STICKERS) != 0;
72   }
73 
can_send_animations()74   bool can_send_animations() const {
75     return (flags_ & CAN_SEND_ANIMATIONS) != 0;
76   }
77 
can_send_games()78   bool can_send_games() const {
79     return (flags_ & CAN_SEND_GAMES) != 0;
80   }
81 
can_use_inline_bots()82   bool can_use_inline_bots() const {
83     return (flags_ & CAN_USE_INLINE_BOTS) != 0;
84   }
85 
can_add_web_page_previews()86   bool can_add_web_page_previews() const {
87     return (flags_ & CAN_ADD_WEB_PAGE_PREVIEWS) != 0;
88   }
89 
can_send_polls()90   bool can_send_polls() const {
91     return (flags_ & CAN_SEND_POLLS) != 0;
92   }
93 
94   template <class StorerT>
store(StorerT & storer)95   void store(StorerT &storer) const {
96     td::store(flags_, storer);
97   }
98 
99   template <class ParserT>
parse(ParserT & parser)100   void parse(ParserT &parser) {
101     td::parse(flags_, parser);
102   }
103 
104   friend bool operator==(const RestrictedRights &lhs, const RestrictedRights &rhs);
105 
106   friend StringBuilder &operator<<(StringBuilder &string_builder, const RestrictedRights &status);
107 };
108 
109 bool operator==(const RestrictedRights &lhs, const RestrictedRights &rhs);
110 
111 bool operator!=(const RestrictedRights &lhs, const RestrictedRights &rhs);
112 
113 StringBuilder &operator<<(StringBuilder &string_builder, const RestrictedRights &status);
114 
115 class DialogParticipantStatus {
116   static constexpr uint32 CAN_CHANGE_INFO_AND_SETTINGS_ADMIN = 1 << 0;
117   static constexpr uint32 CAN_POST_MESSAGES = 1 << 1;
118   static constexpr uint32 CAN_EDIT_MESSAGES = 1 << 2;
119   static constexpr uint32 CAN_DELETE_MESSAGES = 1 << 3;
120   static constexpr uint32 CAN_INVITE_USERS_ADMIN = 1 << 4;
121   // static constexpr uint32 CAN_EXPORT_DIALOG_INVITE_LINK = 1 << 5;
122   static constexpr uint32 CAN_RESTRICT_MEMBERS = 1 << 6;
123   static constexpr uint32 CAN_PIN_MESSAGES_ADMIN = 1 << 7;
124   static constexpr uint32 CAN_PROMOTE_MEMBERS = 1 << 8;
125   static constexpr uint32 CAN_MANAGE_CALLS = 1 << 9;
126   static constexpr uint32 CAN_MANAGE_DIALOG = 1 << 10;
127 
128   static constexpr uint32 CAN_BE_EDITED = 1 << 15;
129 
130   static constexpr uint32 CAN_SEND_MESSAGES = 1 << 16;
131   static constexpr uint32 CAN_SEND_MEDIA = 1 << 17;
132   static constexpr uint32 CAN_SEND_STICKERS = 1 << 18;
133   static constexpr uint32 CAN_SEND_ANIMATIONS = 1 << 19;
134   static constexpr uint32 CAN_SEND_GAMES = 1 << 20;
135   static constexpr uint32 CAN_USE_INLINE_BOTS = 1 << 21;
136   static constexpr uint32 CAN_ADD_WEB_PAGE_PREVIEWS = 1 << 22;
137   static constexpr uint32 CAN_SEND_POLLS = 1 << 23;
138   static constexpr uint32 CAN_CHANGE_INFO_AND_SETTINGS_BANNED = 1 << 24;
139   static constexpr uint32 CAN_INVITE_USERS_BANNED = 1 << 25;
140   static constexpr uint32 CAN_PIN_MESSAGES_BANNED = 1 << 26;
141 
142   static constexpr uint32 IS_MEMBER = 1 << 27;
143 
144   static constexpr uint32 IS_ANONYMOUS = 1 << 13;
145   static constexpr uint32 HAS_RANK = 1 << 14;
146   // bits 28-30 reserved for Type
147   static constexpr int TYPE_SHIFT = 28;
148   static constexpr uint32 HAS_UNTIL_DATE = 1u << 31;
149 
150   static constexpr uint32 ALL_ADMINISTRATOR_RIGHTS = CAN_CHANGE_INFO_AND_SETTINGS_ADMIN | CAN_POST_MESSAGES |
151                                                      CAN_EDIT_MESSAGES | CAN_DELETE_MESSAGES | CAN_INVITE_USERS_ADMIN |
152                                                      CAN_RESTRICT_MEMBERS | CAN_PIN_MESSAGES_ADMIN |
153                                                      CAN_PROMOTE_MEMBERS | CAN_MANAGE_CALLS | CAN_MANAGE_DIALOG;
154 
155   static constexpr uint32 ALL_ADMIN_PERMISSION_RIGHTS =
156       CAN_CHANGE_INFO_AND_SETTINGS_BANNED | CAN_INVITE_USERS_BANNED | CAN_PIN_MESSAGES_BANNED;
157 
158   static constexpr uint32 ALL_RESTRICTED_RIGHTS = CAN_SEND_MESSAGES | CAN_SEND_MEDIA | CAN_SEND_STICKERS |
159                                                   CAN_SEND_ANIMATIONS | CAN_SEND_GAMES | CAN_USE_INLINE_BOTS |
160                                                   CAN_ADD_WEB_PAGE_PREVIEWS | CAN_SEND_POLLS;
161 
162   static constexpr uint32 ALL_PERMISSION_RIGHTS = ALL_RESTRICTED_RIGHTS | ALL_ADMIN_PERMISSION_RIGHTS;
163 
164   enum class Type : int32 { Creator, Administrator, Member, Restricted, Left, Banned };
165   // all fields are logically const, but should be updated in update_restrictions()
166   mutable Type type_;
167   mutable uint32 flags_;
168   mutable int32 until_date_;  // restricted and banned only
169   string rank_;               // creator and administrator only
170 
171   static int32 fix_until_date(int32 date);
172 
173   DialogParticipantStatus(Type type, uint32 flags, int32 until_date, string rank);
174 
175  public:
176   static DialogParticipantStatus Creator(bool is_member, bool is_anonymous, string rank);
177 
178   static DialogParticipantStatus Administrator(bool is_anonymous, string rank, bool can_be_edited,
179                                                bool can_manage_dialog, bool can_change_info, bool can_post_messages,
180                                                bool can_edit_messages, bool can_delete_messages, bool can_invite_users,
181                                                bool can_restrict_members, bool can_pin_messages,
182                                                bool can_promote_members, bool can_manage_calls);
183 
184   static DialogParticipantStatus Member();
185 
186   static DialogParticipantStatus Restricted(bool is_member, int32 restricted_until_date, bool can_send_messages,
187                                             bool can_send_media, bool can_send_stickers, bool can_send_animations,
188                                             bool can_send_games, bool can_use_inline_bots,
189                                             bool can_add_web_page_previews, bool can_send_polls,
190                                             bool can_change_info_and_settings, bool can_invite_users,
191                                             bool can_pin_messages);
192 
193   static DialogParticipantStatus Left();
194 
195   static DialogParticipantStatus Banned(int32 banned_until_date);
196 
197   // legacy rights
198   static DialogParticipantStatus GroupAdministrator(bool is_creator);
199 
200   // legacy rights
201   static DialogParticipantStatus ChannelAdministrator(bool is_creator, bool is_megagroup);
202 
203   RestrictedRights get_restricted_rights() const;
204 
205   DialogParticipantStatus apply_restrictions(RestrictedRights default_restrictions, bool is_bot) const;
206 
207   tl_object_ptr<td_api::ChatMemberStatus> get_chat_member_status_object() const;
208 
209   tl_object_ptr<telegram_api::chatAdminRights> get_chat_admin_rights() const;
210 
211   tl_object_ptr<telegram_api::chatBannedRights> get_chat_banned_rights() const;
212 
213   // unrestricts user if restriction time expired. Should be called before all privileges checks
214   void update_restrictions() const;
215 
can_manage_dialog()216   bool can_manage_dialog() const {
217     return (flags_ & CAN_MANAGE_DIALOG) != 0;
218   }
219 
can_change_info_and_settings()220   bool can_change_info_and_settings() const {
221     return (flags_ & CAN_CHANGE_INFO_AND_SETTINGS_ADMIN) != 0 || (flags_ & CAN_CHANGE_INFO_AND_SETTINGS_BANNED) != 0;
222   }
223 
can_post_messages()224   bool can_post_messages() const {
225     return (flags_ & CAN_POST_MESSAGES) != 0;
226   }
227 
can_edit_messages()228   bool can_edit_messages() const {
229     return (flags_ & CAN_EDIT_MESSAGES) != 0;
230   }
231 
can_delete_messages()232   bool can_delete_messages() const {
233     return (flags_ & CAN_DELETE_MESSAGES) != 0;
234   }
235 
can_invite_users()236   bool can_invite_users() const {
237     return (flags_ & CAN_INVITE_USERS_ADMIN) != 0 || (flags_ & CAN_INVITE_USERS_BANNED) != 0;
238   }
239 
can_manage_invite_links()240   bool can_manage_invite_links() const {
241     // invite links can be managed, only if administrator was explicitly granted the right
242     return (flags_ & CAN_INVITE_USERS_ADMIN) != 0;
243   }
244 
can_restrict_members()245   bool can_restrict_members() const {
246     return (flags_ & CAN_RESTRICT_MEMBERS) != 0;
247   }
248 
can_pin_messages()249   bool can_pin_messages() const {
250     return (flags_ & CAN_PIN_MESSAGES_ADMIN) != 0 || (flags_ & CAN_PIN_MESSAGES_BANNED) != 0;
251   }
252 
can_promote_members()253   bool can_promote_members() const {
254     return (flags_ & CAN_PROMOTE_MEMBERS) != 0;
255   }
256 
can_manage_calls()257   bool can_manage_calls() const {
258     return (flags_ & CAN_MANAGE_CALLS) != 0;
259   }
260 
can_be_edited()261   bool can_be_edited() const {
262     return (flags_ & CAN_BE_EDITED) != 0;
263   }
264 
can_send_messages()265   bool can_send_messages() const {
266     return (flags_ & CAN_SEND_MESSAGES) != 0;
267   }
268 
can_send_media()269   bool can_send_media() const {
270     return (flags_ & CAN_SEND_MEDIA) != 0;
271   }
272 
can_send_stickers()273   bool can_send_stickers() const {
274     return (flags_ & CAN_SEND_STICKERS) != 0;
275   }
276 
can_send_animations()277   bool can_send_animations() const {
278     return (flags_ & CAN_SEND_ANIMATIONS) != 0;
279   }
280 
can_send_games()281   bool can_send_games() const {
282     return (flags_ & CAN_SEND_GAMES) != 0;
283   }
284 
can_use_inline_bots()285   bool can_use_inline_bots() const {
286     return (flags_ & CAN_USE_INLINE_BOTS) != 0;
287   }
288 
can_add_web_page_previews()289   bool can_add_web_page_previews() const {
290     return (flags_ & CAN_ADD_WEB_PAGE_PREVIEWS) != 0;
291   }
292 
can_send_polls()293   bool can_send_polls() const {
294     return (flags_ & CAN_SEND_POLLS) != 0;
295   }
296 
set_is_member(bool is_member)297   void set_is_member(bool is_member) {
298     if (is_member) {
299       flags_ |= IS_MEMBER;
300     } else {
301       flags_ &= ~IS_MEMBER;
302     }
303   }
304 
is_member()305   bool is_member() const {
306     return (flags_ & IS_MEMBER) != 0;
307   }
308 
is_left()309   bool is_left() const {
310     return (flags_ & IS_MEMBER) == 0;
311   }
312 
is_creator()313   bool is_creator() const {
314     return type_ == Type::Creator;
315   }
316 
is_administrator()317   bool is_administrator() const {
318     return type_ == Type::Administrator || type_ == Type::Creator;
319   }
320 
is_restricted()321   bool is_restricted() const {
322     return type_ == Type::Restricted;
323   }
324 
is_banned()325   bool is_banned() const {
326     return type_ == Type::Banned;
327   }
328 
get_until_date()329   int32 get_until_date() const {
330     return until_date_;
331   }
332 
is_anonymous()333   bool is_anonymous() const {
334     return (flags_ & IS_ANONYMOUS) != 0;
335   }
336 
get_rank()337   const string &get_rank() const {
338     return rank_;
339   }
340 
341   template <class StorerT>
store(StorerT & storer)342   void store(StorerT &storer) const {
343     uint32 stored_flags = flags_ | (static_cast<uint32>(type_) << TYPE_SHIFT);
344     if (until_date_ > 0) {
345       stored_flags |= HAS_UNTIL_DATE;
346     }
347     if (!rank_.empty()) {
348       stored_flags |= HAS_RANK;
349     }
350     td::store(stored_flags, storer);
351     if (until_date_ > 0) {
352       td::store(until_date_, storer);
353     }
354     if (!rank_.empty()) {
355       td::store(rank_, storer);
356     }
357   }
358 
359   template <class ParserT>
parse(ParserT & parser)360   void parse(ParserT &parser) {
361     uint32 stored_flags;
362     td::parse(stored_flags, parser);
363     if ((stored_flags & HAS_UNTIL_DATE) != 0) {
364       td::parse(until_date_, parser);
365       stored_flags &= ~HAS_UNTIL_DATE;
366     }
367     if ((stored_flags & HAS_RANK) != 0) {
368       td::parse(rank_, parser);
369       stored_flags &= ~HAS_RANK;
370     }
371     type_ = static_cast<Type>(stored_flags >> TYPE_SHIFT);
372     flags_ = stored_flags & ((1 << TYPE_SHIFT) - 1);
373 
374     if (is_creator()) {
375       flags_ |= ALL_ADMINISTRATOR_RIGHTS | ALL_PERMISSION_RIGHTS;
376     } else if (is_administrator()) {
377       flags_ |= CAN_MANAGE_DIALOG;
378     }
379   }
380 
381   friend bool operator==(const DialogParticipantStatus &lhs, const DialogParticipantStatus &rhs);
382 
383   friend StringBuilder &operator<<(StringBuilder &string_builder, const DialogParticipantStatus &status);
384 };
385 
386 bool operator==(const DialogParticipantStatus &lhs, const DialogParticipantStatus &rhs);
387 
388 bool operator!=(const DialogParticipantStatus &lhs, const DialogParticipantStatus &rhs);
389 
390 StringBuilder &operator<<(StringBuilder &string_builder, const DialogParticipantStatus &status);
391 
392 struct DialogParticipant {
393   DialogId dialog_id_;
394   UserId inviter_user_id_;
395   int32 joined_date_ = 0;
396   DialogParticipantStatus status_ = DialogParticipantStatus::Left();
397 
398   DialogParticipant() = default;
399 
400   DialogParticipant(DialogId dialog_id, UserId inviter_user_id, int32 joined_date, DialogParticipantStatus status);
401 
402   DialogParticipant(tl_object_ptr<telegram_api::ChatParticipant> &&participant_ptr, int32 chat_creation_date,
403                     bool is_creator);
404 
405   explicit DialogParticipant(tl_object_ptr<telegram_api::ChannelParticipant> &&participant_ptr);
406 
leftDialogParticipant407   static DialogParticipant left(DialogId dialog_id) {
408     return {dialog_id, UserId(), 0, DialogParticipantStatus::Left()};
409   }
410 
private_memberDialogParticipant411   static DialogParticipant private_member(UserId user_id, UserId other_user_id) {
412     auto inviter_user_id = other_user_id.is_valid() ? other_user_id : user_id;
413     return {DialogId(user_id), inviter_user_id, 0, DialogParticipantStatus::Member()};
414   }
415 
416   bool is_valid() const;
417 
418   template <class StorerT>
storeDialogParticipant419   void store(StorerT &storer) const {
420     td::store(dialog_id_, storer);
421     td::store(inviter_user_id_, storer);
422     td::store(joined_date_, storer);
423     td::store(status_, storer);
424   }
425 
426   template <class ParserT>
parseDialogParticipant427   void parse(ParserT &parser) {
428     if (parser.version() >= static_cast<int32>(Version::SupportBannedChannels)) {
429       td::parse(dialog_id_, parser);
430     } else {
431       UserId user_id;
432       td::parse(user_id, parser);
433       dialog_id_ = DialogId(user_id);
434     }
435     td::parse(inviter_user_id_, parser);
436     td::parse(joined_date_, parser);
437     td::parse(status_, parser);
438   }
439 };
440 
441 StringBuilder &operator<<(StringBuilder &string_builder, const DialogParticipant &dialog_participant);
442 
443 struct DialogParticipants {
444   int32 total_count_ = 0;
445   vector<DialogParticipant> participants_;
446 
447   DialogParticipants() = default;
DialogParticipantsDialogParticipants448   DialogParticipants(int32 total_count, vector<DialogParticipant> &&participants)
449       : total_count_(total_count), participants_(std::move(participants)) {
450   }
451 
452   td_api::object_ptr<td_api::chatMembers> get_chat_members_object(Td *td) const;
453 };
454 
455 class ChannelParticipantsFilter {
456   enum class Type : int32 { Recent, Contacts, Administrators, Search, Mention, Restricted, Banned, Bots };
457   Type type_;
458   string query_;
459   MessageId top_thread_message_id_;
460 
461   friend StringBuilder &operator<<(StringBuilder &string_builder, const ChannelParticipantsFilter &filter);
462 
463  public:
464   explicit ChannelParticipantsFilter(const tl_object_ptr<td_api::SupergroupMembersFilter> &filter);
465 
466   tl_object_ptr<telegram_api::ChannelParticipantsFilter> get_input_channel_participants_filter() const;
467 
is_administrators()468   bool is_administrators() const {
469     return type_ == Type::Administrators;
470   }
471 
is_bots()472   bool is_bots() const {
473     return type_ == Type::Bots;
474   }
475 
is_recent()476   bool is_recent() const {
477     return type_ == Type::Recent;
478   }
479 
is_contacts()480   bool is_contacts() const {
481     return type_ == Type::Contacts;
482   }
483 
is_search()484   bool is_search() const {
485     return type_ == Type::Search;
486   }
487 
is_restricted()488   bool is_restricted() const {
489     return type_ == Type::Restricted;
490   }
491 
is_banned()492   bool is_banned() const {
493     return type_ == Type::Banned;
494   }
495 };
496 
497 StringBuilder &operator<<(StringBuilder &string_builder, const ChannelParticipantsFilter &filter);
498 
499 class DialogParticipantsFilter {
500   enum class Type : int32 { Contacts, Administrators, Members, Restricted, Banned, Mention, Bots };
501   Type type_;
502   MessageId top_thread_message_id_;
503 
504   friend StringBuilder &operator<<(StringBuilder &string_builder, const DialogParticipantsFilter &filter);
505 
506  public:
507   explicit DialogParticipantsFilter(const tl_object_ptr<td_api::ChatMembersFilter> &filter);
508 
509   td_api::object_ptr<td_api::SupergroupMembersFilter> get_supergroup_members_filter_object(const string &query) const;
510 
511   bool has_query() const;
512 
513   bool is_dialog_participant_suitable(const Td *td, const DialogParticipant &participant) const;
514 };
515 
516 StringBuilder &operator<<(StringBuilder &string_builder, const DialogParticipantsFilter &filter);
517 
518 DialogParticipantStatus get_dialog_participant_status(const tl_object_ptr<td_api::ChatMemberStatus> &status);
519 
520 DialogParticipantStatus get_dialog_participant_status(bool can_be_edited,
521                                                       tl_object_ptr<telegram_api::chatAdminRights> &&admin_rights,
522                                                       string rank);
523 
524 DialogParticipantStatus get_dialog_participant_status(bool is_member,
525                                                       tl_object_ptr<telegram_api::chatBannedRights> &&banned_rights);
526 
527 RestrictedRights get_restricted_rights(tl_object_ptr<telegram_api::chatBannedRights> &&banned_rights);
528 
529 RestrictedRights get_restricted_rights(const td_api::object_ptr<td_api::chatPermissions> &permissions);
530 
531 }  // namespace td
532