1 /*
2 This file is part of Telegram Desktop,
3 the official desktop application for the Telegram messaging service.
4
5 For license and copyright information please follow this link:
6 https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
7 */
8 #pragma once
9
10 #include "data/data_types.h"
11 #include "data/data_flags.h"
12 #include "data/data_notify_settings.h"
13 #include "data/data_cloud_file.h"
14
15 class PeerData;
16 class UserData;
17 class ChatData;
18 class ChannelData;
19
20 enum class ChatAdminRight {
21 ChangeInfo = (1 << 0),
22 PostMessages = (1 << 1),
23 EditMessages = (1 << 2),
24 DeleteMessages = (1 << 3),
25 BanUsers = (1 << 4),
26 InviteUsers = (1 << 5),
27 PinMessages = (1 << 7),
28 AddAdmins = (1 << 9),
29 Anonymous = (1 << 10),
30 ManageCall = (1 << 11),
31 Other = (1 << 12),
32 };
is_flag_type(ChatAdminRight)33 inline constexpr bool is_flag_type(ChatAdminRight) { return true; }
34 using ChatAdminRights = base::flags<ChatAdminRight>;
35
36 enum class ChatRestriction {
37 ViewMessages = (1 << 0),
38 SendMessages = (1 << 1),
39 SendMedia = (1 << 2),
40 SendStickers = (1 << 3),
41 SendGifs = (1 << 4),
42 SendGames = (1 << 5),
43 SendInline = (1 << 6),
44 EmbedLinks = (1 << 7),
45 SendPolls = (1 << 8),
46 ChangeInfo = (1 << 10),
47 InviteUsers = (1 << 15),
48 PinMessages = (1 << 17),
49 };
is_flag_type(ChatRestriction)50 inline constexpr bool is_flag_type(ChatRestriction) { return true; }
51 using ChatRestrictions = base::flags<ChatRestriction>;
52
53 namespace Data {
54
55 [[nodiscard]] ChatAdminRights ChatAdminRightsFlags(
56 const MTPChatAdminRights &rights);
57 [[nodiscard]] ChatRestrictions ChatBannedRightsFlags(
58 const MTPChatBannedRights &rights);
59 [[nodiscard]] TimeId ChatBannedRightsUntilDate(
60 const MTPChatBannedRights &rights);
61
62 } // namespace Data
63
64 struct ChatAdminRightsInfo {
65 ChatAdminRightsInfo() = default;
ChatAdminRightsInfoChatAdminRightsInfo66 explicit ChatAdminRightsInfo(ChatAdminRights flags) : flags(flags) {
67 }
ChatAdminRightsInfoChatAdminRightsInfo68 explicit ChatAdminRightsInfo(const MTPChatAdminRights &rights)
69 : flags(Data::ChatAdminRightsFlags(rights)) {
70 }
71
72 ChatAdminRights flags;
73 };
74
75 struct ChatRestrictionsInfo {
76 ChatRestrictionsInfo() = default;
ChatRestrictionsInfoChatRestrictionsInfo77 ChatRestrictionsInfo(ChatRestrictions flags, TimeId until)
78 : flags(flags)
79 , until(until) {
80 }
ChatRestrictionsInfoChatRestrictionsInfo81 explicit ChatRestrictionsInfo(const MTPChatBannedRights &rights)
82 : flags(Data::ChatBannedRightsFlags(rights))
83 , until(Data::ChatBannedRightsUntilDate(rights)) {
84 }
85
86 ChatRestrictions flags;
87 TimeId until = 0;
88 };
89
90 struct BotCommand {
91 QString command;
92 QString description;
93 };
94
95 namespace Ui {
96 class EmptyUserpic;
97 } // namespace Ui
98
99 namespace Main {
100 class Account;
101 class Session;
102 } // namespace Main
103
104 namespace Data {
105
106 class Session;
107 class GroupCall;
108 class CloudImageView;
109
110 int PeerColorIndex(PeerId peerId);
111 int PeerColorIndex(BareId bareId);
112 style::color PeerUserpicColor(PeerId peerId);
113 PeerId FakePeerIdForJustName(const QString &name);
114
115 class RestrictionCheckResult {
116 public:
Allowed()117 [[nodiscard]] static RestrictionCheckResult Allowed() {
118 return { 0 };
119 }
WithEveryone()120 [[nodiscard]] static RestrictionCheckResult WithEveryone() {
121 return { 1 };
122 }
Explicit()123 [[nodiscard]] static RestrictionCheckResult Explicit() {
124 return { 2 };
125 }
126
127 explicit operator bool() const {
128 return (_value != 0);
129 }
130
131 bool operator==(const RestrictionCheckResult &other) const {
132 return (_value == other._value);
133 }
134 bool operator!=(const RestrictionCheckResult &other) const {
135 return !(*this == other);
136 }
137
isAllowed()138 [[nodiscard]] bool isAllowed() const {
139 return (*this == Allowed());
140 }
isWithEveryone()141 [[nodiscard]] bool isWithEveryone() const {
142 return (*this == WithEveryone());
143 }
isExplicit()144 [[nodiscard]] bool isExplicit() const {
145 return (*this == Explicit());
146 }
147
148 private:
RestrictionCheckResult(int value)149 RestrictionCheckResult(int value) : _value(value) {
150 }
151
152 int _value = 0;
153
154 };
155
156 struct UnavailableReason {
157 QString reason;
158 QString text;
159
160 bool operator==(const UnavailableReason &other) const {
161 return (reason == other.reason) && (text == other.text);
162 }
163 bool operator!=(const UnavailableReason &other) const {
164 return !(*this == other);
165 }
166 };
167
168 bool UpdateBotCommands(
169 std::vector<BotCommand> &commands,
170 const MTPVector<MTPBotCommand> &data);
171 bool UpdateBotCommands(
172 base::flat_map<UserId, std::vector<BotCommand>> &commands,
173 UserId botId,
174 const MTPVector<MTPBotCommand> &data);
175 bool UpdateBotCommands(
176 base::flat_map<UserId, std::vector<BotCommand>> &commands,
177 const MTPVector<MTPBotInfo> &data);
178
179 } // namespace Data
180
181 class PeerClickHandler : public ClickHandler {
182 public:
183 PeerClickHandler(not_null<PeerData*> peer);
184 void onClick(ClickContext context) const override;
185
peer()186 not_null<PeerData*> peer() const {
187 return _peer;
188 }
189
190 private:
191 not_null<PeerData*> _peer;
192
193 };
194
195 enum class PeerSetting {
196 ReportSpam = (1 << 0),
197 AddContact = (1 << 1),
198 BlockContact = (1 << 2),
199 ShareContact = (1 << 3),
200 NeedContactsException = (1 << 4),
201 AutoArchived = (1 << 5),
202 Unknown = (1 << 6),
203 };
is_flag_type(PeerSetting)204 inline constexpr bool is_flag_type(PeerSetting) { return true; };
205 using PeerSettings = base::flags<PeerSetting>;
206
207 class PeerData {
208 protected:
209 PeerData(not_null<Data::Session*> owner, PeerId id);
210 PeerData(const PeerData &other) = delete;
211 PeerData &operator=(const PeerData &other) = delete;
212
213 public:
214 using Settings = Data::Flags<PeerSettings>;
215
216 virtual ~PeerData();
217
218 static constexpr auto kServiceNotificationsId = peerFromUser(777000);
219
220 [[nodiscard]] Data::Session &owner() const;
221 [[nodiscard]] Main::Session &session() const;
222 [[nodiscard]] Main::Account &account() const;
223
isUser()224 [[nodiscard]] bool isUser() const {
225 return peerIsUser(id);
226 }
isChat()227 [[nodiscard]] bool isChat() const {
228 return peerIsChat(id);
229 }
isChannel()230 [[nodiscard]] bool isChannel() const {
231 return peerIsChannel(id);
232 }
isSelf()233 [[nodiscard]] bool isSelf() const {
234 return (input.type() == mtpc_inputPeerSelf);
235 }
236 [[nodiscard]] bool isVerified() const;
237 [[nodiscard]] bool isScam() const;
238 [[nodiscard]] bool isFake() const;
239 [[nodiscard]] bool isMegagroup() const;
240 [[nodiscard]] bool isBroadcast() const;
241 [[nodiscard]] bool isGigagroup() const;
242 [[nodiscard]] bool isRepliesChat() const;
sharedMediaInfo()243 [[nodiscard]] bool sharedMediaInfo() const {
244 return isSelf() || isRepliesChat();
245 }
246
isNotificationsUser()247 [[nodiscard]] bool isNotificationsUser() const {
248 return (id == peerFromUser(333000))
249 || (id == kServiceNotificationsId);
250 }
isServiceUser()251 [[nodiscard]] bool isServiceUser() const {
252 return isUser() && !(id.value % 1000);
253 }
254
notifyMuteUntil()255 [[nodiscard]] std::optional<TimeId> notifyMuteUntil() const {
256 return _notify.muteUntil();
257 }
notifyChange(const MTPPeerNotifySettings & settings)258 bool notifyChange(const MTPPeerNotifySettings &settings) {
259 return _notify.change(settings);
260 }
notifyChange(std::optional<int> muteForSeconds,std::optional<bool> silentPosts)261 bool notifyChange(
262 std::optional<int> muteForSeconds,
263 std::optional<bool> silentPosts) {
264 return _notify.change(muteForSeconds, silentPosts);
265 }
notifySettingsUnknown()266 [[nodiscard]] bool notifySettingsUnknown() const {
267 return _notify.settingsUnknown();
268 }
notifySilentPosts()269 [[nodiscard]] std::optional<bool> notifySilentPosts() const {
270 return _notify.silentPosts();
271 }
notifySerialize()272 [[nodiscard]] MTPinputPeerNotifySettings notifySerialize() const {
273 return _notify.serialize();
274 }
275
276 [[nodiscard]] bool canWrite() const;
277 [[nodiscard]] Data::RestrictionCheckResult amRestricted(
278 ChatRestriction right) const;
279 [[nodiscard]] bool amAnonymous() const;
280 [[nodiscard]] bool canRevokeFullHistory() const;
281 [[nodiscard]] bool slowmodeApplied() const;
282 [[nodiscard]] rpl::producer<bool> slowmodeAppliedValue() const;
283 [[nodiscard]] int slowmodeSecondsLeft() const;
284 [[nodiscard]] bool canSendPolls() const;
285 [[nodiscard]] bool canManageGroupCall() const;
286
287 [[nodiscard]] UserData *asUser();
288 [[nodiscard]] const UserData *asUser() const;
289 [[nodiscard]] ChatData *asChat();
290 [[nodiscard]] const ChatData *asChat() const;
291 [[nodiscard]] ChannelData *asChannel();
292 [[nodiscard]] const ChannelData *asChannel() const;
293 [[nodiscard]] ChannelData *asMegagroup();
294 [[nodiscard]] const ChannelData *asMegagroup() const;
295 [[nodiscard]] ChannelData *asBroadcast();
296 [[nodiscard]] const ChannelData *asBroadcast() const;
297 [[nodiscard]] ChatData *asChatNotMigrated();
298 [[nodiscard]] const ChatData *asChatNotMigrated() const;
299 [[nodiscard]] ChannelData *asChannelOrMigrated();
300 [[nodiscard]] const ChannelData *asChannelOrMigrated() const;
301
302 [[nodiscard]] ChatData *migrateFrom() const;
303 [[nodiscard]] ChannelData *migrateTo() const;
304 [[nodiscard]] not_null<PeerData*> migrateToOrMe();
305 [[nodiscard]] not_null<const PeerData*> migrateToOrMe() const;
306
307 void updateFull();
308 void updateFullForced();
309 void fullUpdated();
wasFullUpdated()310 [[nodiscard]] bool wasFullUpdated() const {
311 return (_lastFullUpdate != 0);
312 }
313
314 [[nodiscard]] const Ui::Text::String &nameText() const;
315 [[nodiscard]] const QString &shortName() const;
316 [[nodiscard]] const Ui::Text::String &topBarNameText() const;
317 [[nodiscard]] QString userName() const;
318
nameWords()319 [[nodiscard]] const base::flat_set<QString> &nameWords() const {
320 return _nameWords;
321 }
nameFirstLetters()322 [[nodiscard]] const base::flat_set<QChar> &nameFirstLetters() const {
323 return _nameFirstLetters;
324 }
325
326 void setUserpic(PhotoId photoId, const ImageLocation &location);
327 void setUserpicPhoto(const MTPPhoto &data);
328 void paintUserpic(
329 Painter &p,
330 std::shared_ptr<Data::CloudImageView> &view,
331 int x,
332 int y,
333 int size) const;
paintUserpicLeft(Painter & p,std::shared_ptr<Data::CloudImageView> & view,int x,int y,int w,int size)334 void paintUserpicLeft(
335 Painter &p,
336 std::shared_ptr<Data::CloudImageView> &view,
337 int x,
338 int y,
339 int w,
340 int size) const {
341 paintUserpic(p, view, rtl() ? (w - x - size) : x, y, size);
342 }
343 void loadUserpic();
344 [[nodiscard]] bool hasUserpic() const;
345 [[nodiscard]] std::shared_ptr<Data::CloudImageView> activeUserpicView();
346 [[nodiscard]] std::shared_ptr<Data::CloudImageView> createUserpicView();
347 [[nodiscard]] bool useEmptyUserpic(
348 std::shared_ptr<Data::CloudImageView> &view) const;
349 [[nodiscard]] InMemoryKey userpicUniqueKey(
350 std::shared_ptr<Data::CloudImageView> &view) const;
351 void saveUserpic(
352 std::shared_ptr<Data::CloudImageView> &view,
353 const QString &path,
354 int size) const;
355 void saveUserpicRounded(
356 std::shared_ptr<Data::CloudImageView> &view,
357 const QString &path,
358 int size) const;
359 [[nodiscard]] QPixmap genUserpic(
360 std::shared_ptr<Data::CloudImageView> &view,
361 int size) const;
362 [[nodiscard]] QImage generateUserpicImage(
363 std::shared_ptr<Data::CloudImageView> &view,
364 int size) const;
365 [[nodiscard]] QImage generateUserpicImage(
366 std::shared_ptr<Data::CloudImageView> &view,
367 int size,
368 ImageRoundRadius radius) const;
userpicLocation()369 [[nodiscard]] ImageLocation userpicLocation() const {
370 return _userpic.location();
371 }
372
373 static constexpr auto kUnknownPhotoId = PhotoId(0xFFFFFFFFFFFFFFFFULL);
userpicPhotoUnknown()374 [[nodiscard]] bool userpicPhotoUnknown() const {
375 return (_userpicPhotoId == kUnknownPhotoId);
376 }
userpicPhotoId()377 [[nodiscard]] PhotoId userpicPhotoId() const {
378 return userpicPhotoUnknown() ? 0 : _userpicPhotoId;
379 }
380 [[nodiscard]] Data::FileOrigin userpicOrigin() const;
381 [[nodiscard]] Data::FileOrigin userpicPhotoOrigin() const;
382
383 // If this string is not empty we must not allow to open the
384 // conversation and we must show this string instead.
385 [[nodiscard]] QString computeUnavailableReason() const;
386
387 [[nodiscard]] ClickHandlerPtr createOpenLink();
openLink()388 [[nodiscard]] const ClickHandlerPtr &openLink() {
389 if (!_openLink) {
390 _openLink = createOpenLink();
391 }
392 return _openLink;
393 }
394
395 [[nodiscard]] Image *currentUserpic(
396 std::shared_ptr<Data::CloudImageView> &view) const;
397
398 [[nodiscard]] bool canPinMessages() const;
399 [[nodiscard]] bool canEditMessagesIndefinitely() const;
400
401 [[nodiscard]] bool canExportChatHistory() const;
402
403 // Returns true if about text was changed.
404 bool setAbout(const QString &newAbout);
about()405 const QString &about() const {
406 return _about;
407 }
408
409 void checkFolder(FolderId folderId);
410
setSettings(PeerSettings which)411 void setSettings(PeerSettings which) {
412 _settings.set(which);
413 }
settings()414 auto settings() const {
415 return (_settings.current() & PeerSetting::Unknown)
416 ? std::nullopt
417 : std::make_optional(_settings.current());
418 }
settingsValue()419 auto settingsValue() const {
420 return (_settings.current() & PeerSetting::Unknown)
421 ? _settings.changes()
422 : (_settings.value() | rpl::type_erased());
423 }
424
425 void setSettings(const MTPPeerSettings &data);
426
427 enum class BlockStatus : char {
428 Unknown,
429 Blocked,
430 NotBlocked,
431 };
blockStatus()432 [[nodiscard]] BlockStatus blockStatus() const {
433 return _blockStatus;
434 }
isBlocked()435 [[nodiscard]] bool isBlocked() const {
436 return (blockStatus() == BlockStatus::Blocked);
437 }
438 void setIsBlocked(bool is);
439
440 enum class LoadedStatus : char {
441 Not,
442 Minimal,
443 Normal,
444 Full,
445 };
loadedStatus()446 [[nodiscard]] LoadedStatus loadedStatus() const {
447 return _loadedStatus;
448 }
isMinimalLoaded()449 [[nodiscard]] bool isMinimalLoaded() const {
450 return (loadedStatus() != LoadedStatus::Not);
451 }
isLoaded()452 [[nodiscard]] bool isLoaded() const {
453 return (loadedStatus() == LoadedStatus::Normal) || isFullLoaded();
454 }
isFullLoaded()455 [[nodiscard]] bool isFullLoaded() const {
456 return (loadedStatus() == LoadedStatus::Full);
457 }
458 void setLoadedStatus(LoadedStatus status);
459
460 [[nodiscard]] TimeId messagesTTL() const;
461 void setMessagesTTL(TimeId period);
462
463 [[nodiscard]] Data::GroupCall *groupCall() const;
464 [[nodiscard]] PeerId groupCallDefaultJoinAs() const;
465
466 void setThemeEmoji(const QString &emoticon);
467 [[nodiscard]] const QString &themeEmoji() const;
468
469 const PeerId id;
470 QString name;
471 MTPinputPeer input = MTP_inputPeerEmpty();
472
473 int nameVersion = 1;
474
475 protected:
476 void updateNameDelayed(
477 const QString &newName,
478 const QString &newNameOrPhone,
479 const QString &newUsername);
480 void updateUserpic(PhotoId photoId, MTP::DcId dcId);
481 void clearUserpic();
482
483 private:
484 void fillNames();
485 [[nodiscard]] not_null<Ui::EmptyUserpic*> ensureEmptyUserpic() const;
486 [[nodiscard]] virtual auto unavailableReasons() const
487 -> const std::vector<Data::UnavailableReason> &;
488
489 void setUserpicChecked(PhotoId photoId, const ImageLocation &location);
490
491 const not_null<Data::Session*> _owner;
492
493 mutable Data::CloudImage _userpic;
494 PhotoId _userpicPhotoId = kUnknownPhotoId;
495 mutable std::unique_ptr<Ui::EmptyUserpic> _userpicEmpty;
496 Ui::Text::String _nameText;
497
498 Data::NotifySettings _notify;
499
500 ClickHandlerPtr _openLink;
501 base::flat_set<QString> _nameWords; // for filtering
502 base::flat_set<QChar> _nameFirstLetters;
503
504 crl::time _lastFullUpdate = 0;
505
506 TimeId _ttlPeriod = 0;
507
508 Settings _settings = PeerSettings(PeerSetting::Unknown);
509 BlockStatus _blockStatus = BlockStatus::Unknown;
510 LoadedStatus _loadedStatus = LoadedStatus::Not;
511
512 QString _about;
513 QString _themeEmoticon;
514
515 };
516
517 namespace Data {
518
519 std::vector<ChatRestrictions> ListOfRestrictions();
520
521 std::optional<QString> RestrictionError(
522 not_null<PeerData*> peer,
523 ChatRestriction restriction);
524
525 void SetTopPinnedMessageId(not_null<PeerData*> peer, MsgId messageId);
526 [[nodiscard]] FullMsgId ResolveTopPinnedId(
527 not_null<PeerData*> peer,
528 PeerData *migrated);
529 [[nodiscard]] FullMsgId ResolveMinPinnedId(
530 not_null<PeerData*> peer,
531 PeerData *migrated);
532 [[nodiscard]] std::optional<int> ResolvePinnedCount(
533 not_null<PeerData*> peer,
534 PeerData *migrated);
535
536 } // namespace Data
537