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