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_peer.h"
11 #include "dialogs/dialogs_key.h"
12 
13 struct BotInfo {
14 	bool inited = false;
15 	bool readsAllHistory = false;
16 	bool cantJoinGroups = false;
17 	int version = 0;
18 	QString description, inlinePlaceholder;
19 	std::vector<BotCommand> commands;
20 	Ui::Text::String text = { int(st::msgMinWidth) }; // description
21 
22 	QString startToken, startGroupToken, shareGameShortName;
23 	Dialogs::EntryState inlineReturnTo;
24 };
25 
26 enum class UserDataFlag {
27 	Contact = (1 << 0),
28 	MutualContact = (1 << 1),
29 	Deleted = (1 << 2),
30 	Verified = (1 << 3),
31 	Scam = (1 << 4),
32 	Fake = (1 << 5),
33 	BotInlineGeo = (1 << 6),
34 	Blocked = (1 << 7),
35 	HasPhoneCalls = (1 << 8),
36 	PhoneCallsPrivate = (1 << 9),
37 	Support = (1 << 10),
38 	CanPinMessages = (1 << 11),
39 	DiscardMinPhoto = (1 << 12),
40 };
is_flag_type(UserDataFlag)41 inline constexpr bool is_flag_type(UserDataFlag) { return true; };
42 using UserDataFlags = base::flags<UserDataFlag>;
43 
44 class UserData : public PeerData {
45 public:
46 	using Flag = UserDataFlag;
47 	using Flags = Data::Flags<UserDataFlags>;
48 
49 	UserData(not_null<Data::Session*> owner, PeerId id);
50 	void setPhoto(const MTPUserProfilePhoto &photo);
51 
52 	void setName(
53 		const QString &newFirstName,
54 		const QString &newLastName,
55 		const QString &newPhoneName,
56 		const QString &newUsername);
57 
58 	void setPhone(const QString &newPhone);
59 	void setBotInfoVersion(int version);
60 	void setBotInfo(const MTPBotInfo &info);
61 
62 	void setNameOrPhone(const QString &newNameOrPhone);
63 
64 	void madeAction(TimeId when); // pseudo-online
65 
accessHash()66 	uint64 accessHash() const {
67 		return _accessHash;
68 	}
69 	void setAccessHash(uint64 accessHash);
70 
setFlags(UserDataFlags which)71 	void setFlags(UserDataFlags which) {
72 		_flags.set(which);
73 	}
addFlags(UserDataFlags which)74 	void addFlags(UserDataFlags which) {
75 		_flags.add(which);
76 	}
removeFlags(UserDataFlags which)77 	void removeFlags(UserDataFlags which) {
78 		_flags.remove(which);
79 	}
flags()80 	auto flags() const {
81 		return _flags.current();
82 	}
flagsValue()83 	auto flagsValue() const {
84 		return _flags.value();
85 	}
86 
isVerified()87 	[[nodiscard]] bool isVerified() const {
88 		return flags() & UserDataFlag::Verified;
89 	}
isScam()90 	[[nodiscard]] bool isScam() const {
91 		return flags() & UserDataFlag::Scam;
92 	}
isFake()93 	[[nodiscard]] bool isFake() const {
94 		return flags() & UserDataFlag::Fake;
95 	}
isBotInlineGeo()96 	[[nodiscard]] bool isBotInlineGeo() const {
97 		return flags() & UserDataFlag::BotInlineGeo;
98 	}
isBot()99 	[[nodiscard]] bool isBot() const {
100 		return botInfo != nullptr;
101 	}
isSupport()102 	[[nodiscard]] bool isSupport() const {
103 		return flags() & UserDataFlag::Support;
104 	}
isInaccessible()105 	[[nodiscard]] bool isInaccessible() const {
106 		return flags() & UserDataFlag::Deleted;
107 	}
canWrite()108 	[[nodiscard]] bool canWrite() const {
109 		// Duplicated in Data::CanWriteValue().
110 		return !isInaccessible() && !isRepliesChat();
111 	}
applyMinPhoto()112 	[[nodiscard]] bool applyMinPhoto() const {
113 		return !(flags() & UserDataFlag::DiscardMinPhoto);
114 	}
115 
116 	[[nodiscard]] bool canShareThisContact() const;
canAddContact()117 	[[nodiscard]] bool canAddContact() const {
118 		return canShareThisContact() && !isContact();
119 	}
120 
121 	// In Data::Session::processUsers() we check only that.
122 	// When actually trying to share contact we perform
123 	// a full check by canShareThisContact() call.
canShareThisContactFast()124 	[[nodiscard]] bool canShareThisContactFast() const {
125 		return !_phone.isEmpty();
126 	}
127 
128 	MTPInputUser inputUser = MTP_inputUserEmpty();
129 
130 	QString firstName;
131 	QString lastName;
132 	QString username;
phone()133 	[[nodiscard]] const QString &phone() const {
134 		return _phone;
135 	}
136 	QString nameOrPhone;
137 	Ui::Text::String phoneText;
138 	TimeId onlineTill = 0;
139 
140 	enum class ContactStatus : char {
141 		Unknown,
142 		Contact,
143 		NotContact,
144 	};
contactStatus()145 	[[nodiscard]] ContactStatus contactStatus() const {
146 		return _contactStatus;
147 	}
isContact()148 	[[nodiscard]] bool isContact() const {
149 		return (contactStatus() == ContactStatus::Contact);
150 	}
151 	void setIsContact(bool is);
152 
153 	enum class CallsStatus : char {
154 		Unknown,
155 		Enabled,
156 		Disabled,
157 		Private,
158 	};
callsStatus()159 	CallsStatus callsStatus() const {
160 		return _callsStatus;
161 	}
162 	bool hasCalls() const;
163 	void setCallsStatus(CallsStatus callsStatus);
164 
165 	std::unique_ptr<BotInfo> botInfo;
166 
167 	void setUnavailableReasons(
168 		std::vector<Data::UnavailableReason> &&reasons);
169 
commonChatsCount()170 	int commonChatsCount() const {
171 		return _commonChatsCount;
172 	}
173 	void setCommonChatsCount(int count);
174 
175 private:
176 	auto unavailableReasons() const
177 		-> const std::vector<Data::UnavailableReason> & override;
178 
179 	Flags _flags;
180 
181 	std::vector<Data::UnavailableReason> _unavailableReasons;
182 	QString _phone;
183 	ContactStatus _contactStatus = ContactStatus::Unknown;
184 	CallsStatus _callsStatus = CallsStatus::Unknown;
185 	int _commonChatsCount = 0;
186 
187 	uint64 _accessHash = 0;
188 	static constexpr auto kInaccessibleAccessHashOld
189 		= 0xFFFFFFFFFFFFFFFFULL;
190 
191 };
192 
193 namespace Data {
194 
195 void ApplyUserUpdate(not_null<UserData*> user, const MTPDuserFull &update);
196 
197 } // namespace Data
198