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