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/DialogActionBar.h"
8 
9 #include "td/telegram/ContactsManager.h"
10 #include "td/telegram/Td.h"
11 
12 namespace td {
13 
create(bool can_report_spam,bool can_add_contact,bool can_block_user,bool can_share_phone_number,bool can_report_location,bool can_unarchive,int32 distance,bool can_invite_members,string join_request_dialog_title,bool is_join_request_broadcast,int32 join_request_date)14 unique_ptr<DialogActionBar> DialogActionBar::create(bool can_report_spam, bool can_add_contact, bool can_block_user,
15                                                     bool can_share_phone_number, bool can_report_location,
16                                                     bool can_unarchive, int32 distance, bool can_invite_members,
17                                                     string join_request_dialog_title, bool is_join_request_broadcast,
18                                                     int32 join_request_date) {
19   if (!can_report_spam && !can_add_contact && !can_block_user && !can_share_phone_number && !can_report_location &&
20       !can_invite_members && join_request_dialog_title.empty()) {
21     return nullptr;
22   }
23 
24   auto action_bar = make_unique<DialogActionBar>();
25   action_bar->can_report_spam_ = can_report_spam;
26   action_bar->can_add_contact_ = can_add_contact;
27   action_bar->can_block_user_ = can_block_user;
28   action_bar->can_share_phone_number_ = can_share_phone_number;
29   action_bar->can_report_location_ = can_report_location;
30   action_bar->can_unarchive_ = can_unarchive;
31   action_bar->distance_ = distance >= 0 ? distance : -1;
32   action_bar->can_invite_members_ = can_invite_members;
33   action_bar->join_request_dialog_title_ = std::move(join_request_dialog_title);
34   action_bar->is_join_request_broadcast_ = is_join_request_broadcast;
35   action_bar->join_request_date_ = join_request_date;
36   return action_bar;
37 }
38 
is_empty() const39 bool DialogActionBar::is_empty() const {
40   return !can_report_spam_ && !can_add_contact_ && !can_block_user_ && !can_share_phone_number_ &&
41          !can_report_location_ && !can_invite_members_ && join_request_dialog_title_.empty();
42 }
43 
fix(Td * td,DialogId dialog_id,bool is_dialog_blocked,FolderId folder_id)44 void DialogActionBar::fix(Td *td, DialogId dialog_id, bool is_dialog_blocked, FolderId folder_id) {
45   auto dialog_type = dialog_id.get_type();
46   if (distance_ >= 0 && dialog_type != DialogType::User) {
47     LOG(ERROR) << "Receive distance " << distance_ << " to " << dialog_id;
48     distance_ = -1;
49   }
50 
51   if (!join_request_dialog_title_.empty()) {
52     if (dialog_type != DialogType::User || join_request_date_ <= 0) {
53       LOG(ERROR) << "Receive join_request_date = " << join_request_date_ << " in " << dialog_id;
54       join_request_dialog_title_.clear();
55       is_join_request_broadcast_ = false;
56       join_request_date_ = 0;
57     } else if (can_report_location_ || can_report_spam_ || can_add_contact_ || can_block_user_ ||
58                can_share_phone_number_ || can_unarchive_ || can_invite_members_) {
59       LOG(ERROR) << "Receive action bar " << can_report_location_ << '/' << can_report_spam_ << '/' << can_add_contact_
60                  << '/' << can_block_user_ << '/' << can_share_phone_number_ << '/' << can_report_location_ << '/'
61                  << can_unarchive_ << '/' << can_invite_members_;
62       can_report_location_ = false;
63       can_report_spam_ = false;
64       can_add_contact_ = false;
65       can_block_user_ = false;
66       can_share_phone_number_ = false;
67       can_unarchive_ = false;
68       can_invite_members_ = false;
69       distance_ = -1;
70     }
71   }
72   if (join_request_dialog_title_.empty() && (is_join_request_broadcast_ || join_request_date_ != 0)) {
73     LOG(ERROR) << "Receive join request date = " << join_request_date_ << " and " << is_join_request_broadcast_
74                << " in " << dialog_id;
75     is_join_request_broadcast_ = false;
76     join_request_date_ = 0;
77   }
78   if (can_report_location_) {
79     if (dialog_type != DialogType::Channel) {
80       LOG(ERROR) << "Receive can_report_location in " << dialog_id;
81       can_report_location_ = false;
82     } else if (can_report_spam_ || can_add_contact_ || can_block_user_ || can_share_phone_number_ || can_unarchive_ ||
83                can_invite_members_) {
84       LOG(ERROR) << "Receive action bar " << can_report_spam_ << '/' << can_add_contact_ << '/' << can_block_user_
85                  << '/' << can_share_phone_number_ << '/' << can_report_location_ << '/' << can_unarchive_ << '/'
86                  << can_invite_members_;
87       can_report_spam_ = false;
88       can_add_contact_ = false;
89       can_block_user_ = false;
90       can_share_phone_number_ = false;
91       can_unarchive_ = false;
92       can_invite_members_ = false;
93       CHECK(distance_ == -1);
94     }
95   }
96   if (can_invite_members_) {
97     if (dialog_type != DialogType::Chat &&
98         (dialog_type != DialogType::Channel || td->contacts_manager_->get_channel_type(dialog_id.get_channel_id()) ==
99                                                    ContactsManager::ChannelType::Broadcast)) {
100       LOG(ERROR) << "Receive can_invite_members in " << dialog_id;
101       can_invite_members_ = false;
102     } else if (can_report_spam_ || can_add_contact_ || can_block_user_ || can_share_phone_number_ || can_unarchive_) {
103       LOG(ERROR) << "Receive action bar " << can_report_spam_ << '/' << can_add_contact_ << '/' << can_block_user_
104                  << '/' << can_share_phone_number_ << '/' << can_unarchive_ << '/' << can_invite_members_;
105       can_report_spam_ = false;
106       can_add_contact_ = false;
107       can_block_user_ = false;
108       can_share_phone_number_ = false;
109       can_unarchive_ = false;
110       CHECK(distance_ == -1);
111     }
112   }
113   if (dialog_type == DialogType::User) {
114     auto user_id = dialog_id.get_user_id();
115     bool is_me = user_id == td->contacts_manager_->get_my_id();
116     bool is_deleted = td->contacts_manager_->is_user_deleted(user_id);
117     bool is_contact = td->contacts_manager_->is_user_contact(user_id);
118     if (is_me || is_dialog_blocked) {
119       can_report_spam_ = false;
120       can_unarchive_ = false;
121     }
122     if (is_me || is_dialog_blocked || is_deleted) {
123       can_share_phone_number_ = false;
124     }
125     if (is_me || is_dialog_blocked || is_deleted || is_contact) {
126       can_block_user_ = false;
127       can_add_contact_ = false;
128     }
129   }
130   if (folder_id != FolderId::archive()) {
131     can_unarchive_ = false;
132   }
133   if (can_share_phone_number_) {
134     CHECK(!can_report_location_);
135     CHECK(!can_invite_members_);
136     if (dialog_type != DialogType::User) {
137       LOG(ERROR) << "Receive can_share_phone_number in " << dialog_id;
138       can_share_phone_number_ = false;
139     } else if (can_report_spam_ || can_add_contact_ || can_block_user_ || can_unarchive_ || distance_ >= 0) {
140       LOG(ERROR) << "Receive action bar " << can_report_spam_ << '/' << can_add_contact_ << '/' << can_block_user_
141                  << '/' << can_share_phone_number_ << '/' << can_unarchive_ << '/' << distance_;
142       can_report_spam_ = false;
143       can_add_contact_ = false;
144       can_block_user_ = false;
145       can_unarchive_ = false;
146     }
147   }
148   if (can_block_user_) {
149     CHECK(!can_report_location_);
150     CHECK(!can_invite_members_);
151     CHECK(!can_share_phone_number_);
152     if (dialog_type != DialogType::User) {
153       LOG(ERROR) << "Receive can_block_user in " << dialog_id;
154       can_block_user_ = false;
155     } else if (!can_report_spam_ || !can_add_contact_) {
156       LOG(ERROR) << "Receive action bar " << can_report_spam_ << '/' << can_add_contact_ << '/' << can_block_user_;
157       can_report_spam_ = true;
158       can_add_contact_ = true;
159     }
160   }
161   if (can_add_contact_) {
162     CHECK(!can_report_location_);
163     CHECK(!can_invite_members_);
164     CHECK(!can_share_phone_number_);
165     if (dialog_type != DialogType::User) {
166       LOG(ERROR) << "Receive can_add_contact in " << dialog_id;
167       can_add_contact_ = false;
168     } else if (can_report_spam_ != can_block_user_) {
169       LOG(ERROR) << "Receive action bar " << can_report_spam_ << '/' << can_add_contact_ << '/' << can_block_user_;
170       can_report_spam_ = false;
171       can_block_user_ = false;
172       can_unarchive_ = false;
173     }
174   }
175   if (!can_block_user_) {
176     distance_ = -1;
177   }
178   if (!can_report_spam_) {
179     can_unarchive_ = false;
180   }
181 }
182 
get_chat_action_bar_object(DialogType dialog_type,bool hide_unarchive) const183 td_api::object_ptr<td_api::ChatActionBar> DialogActionBar::get_chat_action_bar_object(DialogType dialog_type,
184                                                                                       bool hide_unarchive) const {
185   if (!join_request_dialog_title_.empty()) {
186     CHECK(dialog_type == DialogType::User);
187     CHECK(!can_report_location_ && !can_share_phone_number_ && !can_block_user_ && !can_add_contact_ &&
188           !can_report_spam_ && !can_invite_members_);
189     return td_api::make_object<td_api::chatActionBarJoinRequest>(join_request_dialog_title_, is_join_request_broadcast_,
190                                                                  join_request_date_);
191   }
192   if (can_report_location_) {
193     CHECK(dialog_type == DialogType::Channel);
194     CHECK(!can_share_phone_number_ && !can_block_user_ && !can_add_contact_ && !can_report_spam_ &&
195           !can_invite_members_);
196     return td_api::make_object<td_api::chatActionBarReportUnrelatedLocation>();
197   }
198   if (can_invite_members_) {
199     CHECK(!can_share_phone_number_ && !can_block_user_ && !can_add_contact_ && !can_report_spam_);
200     return td_api::make_object<td_api::chatActionBarInviteMembers>();
201   }
202   if (can_share_phone_number_) {
203     CHECK(dialog_type == DialogType::User);
204     CHECK(!can_block_user_ && !can_add_contact_ && !can_report_spam_);
205     return td_api::make_object<td_api::chatActionBarSharePhoneNumber>();
206   }
207   if (hide_unarchive) {
208     if (can_add_contact_) {
209       return td_api::make_object<td_api::chatActionBarAddContact>();
210     } else {
211       return nullptr;
212     }
213   }
214   if (can_block_user_) {
215     CHECK(dialog_type == DialogType::User);
216     CHECK(can_report_spam_ && can_add_contact_);
217     return td_api::make_object<td_api::chatActionBarReportAddBlock>(can_unarchive_, distance_);
218   }
219   if (can_add_contact_) {
220     CHECK(dialog_type == DialogType::User);
221     CHECK(!can_report_spam_);
222     return td_api::make_object<td_api::chatActionBarAddContact>();
223   }
224   if (can_report_spam_) {
225     return td_api::make_object<td_api::chatActionBarReportSpam>(can_unarchive_);
226   }
227   return nullptr;
228 }
229 
on_dialog_unarchived()230 bool DialogActionBar::on_dialog_unarchived() {
231   if (!can_unarchive_) {
232     return false;
233   }
234 
235   can_unarchive_ = false;
236   can_report_spam_ = false;
237   can_block_user_ = false;
238   // keep can_add_contact_
239   return true;
240 }
241 
on_user_contact_added()242 bool DialogActionBar::on_user_contact_added() {
243   if (!can_block_user_ && !can_add_contact_) {
244     return false;
245   }
246 
247   can_block_user_ = false;
248   can_add_contact_ = false;
249   // keep can_unarchive_
250   distance_ = -1;
251   return true;
252 }
253 
on_user_deleted()254 bool DialogActionBar::on_user_deleted() {
255   if (join_request_dialog_title_.empty() && !can_share_phone_number_ && !can_block_user_ && !can_add_contact_ &&
256       distance_ < 0) {
257     return false;
258   }
259 
260   join_request_dialog_title_.clear();
261   is_join_request_broadcast_ = false;
262   join_request_date_ = 0;
263   can_share_phone_number_ = false;
264   can_block_user_ = false;
265   can_add_contact_ = false;
266   distance_ = -1;
267   return true;
268 }
269 
on_outgoing_message()270 bool DialogActionBar::on_outgoing_message() {
271   if (distance_ < 0) {
272     return false;
273   }
274 
275   distance_ = -1;
276   return true;
277 }
278 
operator ==(const unique_ptr<DialogActionBar> & lhs,const unique_ptr<DialogActionBar> & rhs)279 bool operator==(const unique_ptr<DialogActionBar> &lhs, const unique_ptr<DialogActionBar> &rhs) {
280   if (lhs == nullptr) {
281     return rhs == nullptr;
282   }
283   if (rhs == nullptr) {
284     return false;
285   }
286   return lhs->can_report_spam_ == rhs->can_report_spam_ && lhs->can_add_contact_ == rhs->can_add_contact_ &&
287          lhs->can_block_user_ == rhs->can_block_user_ && lhs->can_share_phone_number_ == rhs->can_share_phone_number_ &&
288          lhs->can_report_location_ == rhs->can_report_location_ && lhs->can_unarchive_ == rhs->can_unarchive_ &&
289          lhs->distance_ == rhs->distance_ && lhs->can_invite_members_ == rhs->can_invite_members_ &&
290          lhs->join_request_dialog_title_ == rhs->join_request_dialog_title_ &&
291          lhs->is_join_request_broadcast_ == lhs->is_join_request_broadcast_ &&
292          lhs->join_request_date_ == rhs->join_request_date_;
293   ;
294 }
295 
296 }  // namespace td
297