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 "data/data_pts_waiter.h"
12 #include "data/data_location.h"
13 
14 struct ChannelLocation {
15 	QString address;
16 	Data::LocationPoint point;
17 
18 	friend inline bool operator==(
19 			const ChannelLocation &a,
20 			const ChannelLocation &b) {
21 		return a.address.isEmpty()
22 			? b.address.isEmpty()
23 			: (a.address == b.address && a.point == b.point);
24 	}
25 	friend inline bool operator!=(
26 			const ChannelLocation &a,
27 			const ChannelLocation &b) {
28 		return !(a == b);
29 	}
30 };
31 
32 enum class ChannelDataFlag {
33 	Left = (1 << 0),
34 	Creator = (1 << 1),
35 	Forbidden = (1 << 2),
36 	CallActive = (1 << 3),
37 	CallNotEmpty = (1 << 4),
38 	Signatures = (1 << 5),
39 	Verified = (1 << 6),
40 	Scam = (1 << 7),
41 	Fake = (1 << 8),
42 	Megagroup = (1 << 9),
43 	Broadcast = (1 << 10),
44 	Gigagroup = (1 << 11),
45 	Username = (1 << 12),
46 	Location = (1 << 13),
47 	CanSetUsername = (1 << 14),
48 	CanSetStickers = (1 << 15),
49 	PreHistoryHidden = (1 << 16),
50 	CanViewParticipants = (1 << 17),
51 	HasLink = (1 << 18),
52 	SlowmodeEnabled = (1 << 19),
53 };
is_flag_type(ChannelDataFlag)54 inline constexpr bool is_flag_type(ChannelDataFlag) { return true; };
55 using ChannelDataFlags = base::flags<ChannelDataFlag>;
56 
57 class MegagroupInfo {
58 public:
59 	struct Admin {
AdminAdmin60 		explicit Admin(ChatAdminRightsInfo rights)
61 		: rights(rights) {
62 		}
AdminAdmin63 		Admin(ChatAdminRightsInfo rights, bool canEdit)
64 		: rights(rights)
65 		, canEdit(canEdit) {
66 		}
67 		ChatAdminRightsInfo rights;
68 		bool canEdit = false;
69 	};
70 
71 	struct Restricted {
RestrictedRestricted72 		explicit Restricted(ChatRestrictionsInfo rights)
73 		: rights(rights) {
74 		}
75 		ChatRestrictionsInfo rights;
76 	};
77 
78 	ChatData *getMigrateFromChat() const;
79 	void setMigrateFromChat(ChatData *chat);
80 
81 	const ChannelLocation *getLocation() const;
82 	void setLocation(const ChannelLocation &location);
83 
84 	bool updateBotCommands(const MTPVector<MTPBotInfo> &data);
85 	bool updateBotCommands(
86 		UserId botId,
87 		const MTPVector<MTPBotCommand> &data);
88 	[[nodiscard]] auto botCommands() const
89 		-> const base::flat_map<UserId, std::vector<BotCommand>> & {
90 		return _botCommands;
91 	}
92 
93 	std::deque<not_null<UserData*>> lastParticipants;
94 	base::flat_map<not_null<UserData*>, Admin> lastAdmins;
95 	base::flat_map<not_null<UserData*>, Restricted> lastRestricted;
96 	base::flat_set<not_null<PeerData*>> markupSenders;
97 	base::flat_set<not_null<UserData*>> bots;
98 
99 	// For admin badges, full admins list with ranks.
100 	base::flat_map<UserId, QString> admins;
101 
102 	UserData *creator = nullptr; // nullptr means unknown
103 	QString creatorRank;
104 	int botStatus = 0; // -1 - no bots, 0 - unknown, 1 - one bot, that sees all history, 2 - other
105 	bool joinedMessageFound = false;
106 	StickerSetIdentifier stickerSet;
107 
108 	enum LastParticipantsStatus {
109 		LastParticipantsUpToDate       = 0x00,
110 		LastParticipantsOnceReceived   = 0x01,
111 		LastParticipantsCountOutdated  = 0x02,
112 	};
113 	mutable int lastParticipantsStatus = LastParticipantsUpToDate;
114 	int lastParticipantsCount = 0;
115 
116 private:
117 	ChatData *_migratedFrom = nullptr;
118 	ChannelLocation _location;
119 	base::flat_map<UserId, std::vector<BotCommand>> _botCommands;
120 
121 };
122 
123 class ChannelData : public PeerData {
124 public:
125 	using Flag = ChannelDataFlag;
126 	using Flags = Data::Flags<ChannelDataFlags>;
127 
128 	using AdminRight = ChatAdminRight;
129 	using Restriction = ChatRestriction;
130 	using AdminRights = ChatAdminRights;
131 	using Restrictions = ChatRestrictions;
132 	using AdminRightFlags = Data::Flags<AdminRights>;
133 	using RestrictionFlags = Data::Flags<Restrictions>;
134 
135 	ChannelData(not_null<Data::Session*> owner, PeerId id);
136 
137 	void setName(const QString &name, const QString &username);
138 	void setPhoto(const MTPChatPhoto &photo);
139 	void setAccessHash(uint64 accessHash);
140 
setFlags(ChannelDataFlags which)141 	void setFlags(ChannelDataFlags which) {
142 		_flags.set(which);
143 	}
addFlags(ChannelDataFlags which)144 	void addFlags(ChannelDataFlags which) {
145 		_flags.add(which);
146 	}
removeFlags(ChannelDataFlags which)147 	void removeFlags(ChannelDataFlags which) {
148 		_flags.remove(which);
149 	}
flags()150 	[[nodiscard]] auto flags() const {
151 		return _flags.current();
152 	}
flagsValue()153 	[[nodiscard]] auto flagsValue() const {
154 		return _flags.value();
155 	}
156 
membersCount()157 	[[nodiscard]] int membersCount() const {
158 		return std::max(_membersCount, 1);
159 	}
160 	void setMembersCount(int newMembersCount);
membersCountKnown()161 	[[nodiscard]] bool membersCountKnown() const {
162 		return (_membersCount >= 0);
163 	}
164 
adminsCount()165 	[[nodiscard]] int adminsCount() const {
166 		return _adminsCount;
167 	}
168 	void setAdminsCount(int newAdminsCount);
169 
restrictedCount()170 	[[nodiscard]] int restrictedCount() const {
171 		return _restrictedCount;
172 	}
173 	void setRestrictedCount(int newRestrictedCount);
174 
kickedCount()175 	[[nodiscard]] int kickedCount() const {
176 		return _kickedCount;
177 	}
178 	void setKickedCount(int newKickedCount);
179 
pendingRequestsCount()180 	[[nodiscard]] int pendingRequestsCount() const {
181 		return _pendingRequestsCount;
182 	}
recentRequesters()183 	[[nodiscard]] const std::vector<UserId> &recentRequesters() const {
184 		return _recentRequesters;
185 	}
186 	void setPendingRequestsCount(
187 		int count,
188 		const QVector<MTPlong> &recentRequesters);
189 	void setPendingRequestsCount(
190 		int count,
191 		std::vector<UserId> recentRequesters);
192 
haveLeft()193 	[[nodiscard]] bool haveLeft() const {
194 		return flags() & Flag::Left;
195 	}
amIn()196 	[[nodiscard]] bool amIn() const {
197 		return !isForbidden() && !haveLeft();
198 	}
addsSignature()199 	[[nodiscard]] bool addsSignature() const {
200 		return flags() & Flag::Signatures;
201 	}
isForbidden()202 	[[nodiscard]] bool isForbidden() const {
203 		return flags() & Flag::Forbidden;
204 	}
isVerified()205 	[[nodiscard]] bool isVerified() const {
206 		return flags() & Flag::Verified;
207 	}
isScam()208 	[[nodiscard]] bool isScam() const {
209 		return flags() & Flag::Scam;
210 	}
isFake()211 	[[nodiscard]] bool isFake() const {
212 		return flags() & Flag::Fake;
213 	}
214 
215 	[[nodiscard]] static ChatRestrictionsInfo KickedRestrictedRights(
216 		not_null<PeerData*> participant);
217 	static constexpr auto kRestrictUntilForever = TimeId(INT_MAX);
IsRestrictedForever(TimeId until)218 	[[nodiscard]] static bool IsRestrictedForever(TimeId until) {
219 		return !until || (until == kRestrictUntilForever);
220 	}
221 	void applyEditAdmin(
222 		not_null<UserData*> user,
223 		ChatAdminRightsInfo oldRights,
224 		ChatAdminRightsInfo newRights,
225 		const QString &rank);
226 	void applyEditBanned(
227 		not_null<PeerData*> participant,
228 		ChatRestrictionsInfo oldRights,
229 		ChatRestrictionsInfo newRights);
230 
231 	void markForbidden();
232 
233 	[[nodiscard]] bool isGroupAdmin(not_null<UserData*> user) const;
234 	[[nodiscard]] bool lastParticipantsRequestNeeded() const;
isMegagroup()235 	[[nodiscard]] bool isMegagroup() const {
236 		return flags() & Flag::Megagroup;
237 	}
isBroadcast()238 	[[nodiscard]] bool isBroadcast() const {
239 		return flags() & Flag::Broadcast;
240 	}
isGigagroup()241 	[[nodiscard]] bool isGigagroup() const {
242 		return flags() & Flag::Gigagroup;
243 	}
hasUsername()244 	[[nodiscard]] bool hasUsername() const {
245 		return flags() & Flag::Username;
246 	}
hasLocation()247 	[[nodiscard]] bool hasLocation() const {
248 		return flags() & Flag::Location;
249 	}
isPublic()250 	[[nodiscard]] bool isPublic() const {
251 		return hasUsername() || hasLocation();
252 	}
amCreator()253 	[[nodiscard]] bool amCreator() const {
254 		return flags() & Flag::Creator;
255 	}
256 
adminRights()257 	[[nodiscard]] auto adminRights() const {
258 		return _adminRights.current();
259 	}
adminRightsValue()260 	[[nodiscard]] auto adminRightsValue() const {
261 		return _adminRights.value();
262 	}
263 	void setAdminRights(ChatAdminRights rights);
hasAdminRights()264 	[[nodiscard]] bool hasAdminRights() const {
265 		return (adminRights() != 0);
266 	}
267 
restrictions()268 	[[nodiscard]] auto restrictions() const {
269 		return _restrictions.current();
270 	}
restrictionsValue()271 	[[nodiscard]] auto restrictionsValue() const {
272 		return _restrictions.value();
273 	}
restrictedUntil()274 	[[nodiscard]] TimeId restrictedUntil() const {
275 		return _restrictedUntil;
276 	}
277 	void setRestrictions(ChatRestrictionsInfo rights);
hasRestrictions()278 	[[nodiscard]] bool hasRestrictions() const {
279 		return (restrictions() != 0);
280 	}
hasRestrictions(TimeId now)281 	[[nodiscard]] bool hasRestrictions(TimeId now) const {
282 		return hasRestrictions()
283 			&& (restrictedUntil() > now);
284 	}
285 
defaultRestrictions()286 	[[nodiscard]] auto defaultRestrictions() const {
287 		return _defaultRestrictions.current();
288 	}
defaultRestrictionsValue()289 	[[nodiscard]] auto defaultRestrictionsValue() const {
290 		return _defaultRestrictions.value();
291 	}
292 	void setDefaultRestrictions(ChatRestrictions rights);
293 
294 	// Like in ChatData.
295 	[[nodiscard]] bool canWrite() const;
296 	[[nodiscard]] bool canEditInformation() const;
297 	[[nodiscard]] bool canEditPermissions() const;
298 	[[nodiscard]] bool canEditUsername() const;
299 	[[nodiscard]] bool canEditPreHistoryHidden() const;
300 	[[nodiscard]] bool canAddMembers() const;
301 	[[nodiscard]] bool canAddAdmins() const;
302 	[[nodiscard]] bool canBanMembers() const;
303 	[[nodiscard]] bool canSendPolls() const;
304 	[[nodiscard]] bool anyoneCanAddMembers() const;
305 
306 	[[nodiscard]] bool canEditMessages() const;
307 	[[nodiscard]] bool canDeleteMessages() const;
308 	[[nodiscard]] bool hiddenPreHistory() const;
309 	[[nodiscard]] bool canPublish() const;
310 	[[nodiscard]] bool canViewMembers() const;
311 	[[nodiscard]] bool canViewAdmins() const;
312 	[[nodiscard]] bool canViewBanned() const;
313 	[[nodiscard]] bool canEditSignatures() const;
314 	[[nodiscard]] bool canEditStickers() const;
315 	[[nodiscard]] bool canDelete() const;
316 	[[nodiscard]] bool canEditAdmin(not_null<UserData*> user) const;
317 	[[nodiscard]] bool canRestrictParticipant(
318 		not_null<PeerData*> participant) const;
319 
320 	void setInviteLink(const QString &newInviteLink);
inviteLink()321 	[[nodiscard]] QString inviteLink() const {
322 		return _inviteLink;
323 	}
324 	[[nodiscard]] bool canHaveInviteLink() const;
325 
326 	void setLocation(const MTPChannelLocation &data);
327 	[[nodiscard]] const ChannelLocation *getLocation() const;
328 
329 	void setLinkedChat(ChannelData *linked);
330 	[[nodiscard]] ChannelData *linkedChat() const;
331 	[[nodiscard]] bool linkedChatKnown() const;
332 
ptsInit(int32 pts)333 	void ptsInit(int32 pts) {
334 		_ptsWaiter.init(pts);
335 	}
ptsReceived(int32 pts)336 	void ptsReceived(int32 pts) {
337 		_ptsWaiter.updateAndApply(this, pts, 0);
338 	}
ptsUpdateAndApply(int32 pts,int32 count)339 	bool ptsUpdateAndApply(int32 pts, int32 count) {
340 		return _ptsWaiter.updateAndApply(this, pts, count);
341 	}
ptsUpdateAndApply(int32 pts,int32 count,const MTPUpdate & update)342 	bool ptsUpdateAndApply(
343 		int32 pts,
344 		int32 count,
345 		const MTPUpdate &update) {
346 		return _ptsWaiter.updateAndApply(this, pts, count, update);
347 	}
ptsUpdateAndApply(int32 pts,int32 count,const MTPUpdates & updates)348 	bool ptsUpdateAndApply(
349 			int32 pts,
350 			int32 count,
351 			const MTPUpdates &updates) {
352 		return _ptsWaiter.updateAndApply(this, pts, count, updates);
353 	}
pts()354 	[[nodiscard]] int32 pts() const {
355 		return _ptsWaiter.current();
356 	}
ptsInited()357 	[[nodiscard]] bool ptsInited() const {
358 		return _ptsWaiter.inited();
359 	}
ptsRequesting()360 	[[nodiscard]] bool ptsRequesting() const {
361 		return _ptsWaiter.requesting();
362 	}
ptsSetRequesting(bool isRequesting)363 	void ptsSetRequesting(bool isRequesting) {
364 		return _ptsWaiter.setRequesting(isRequesting);
365 	}
366 	// < 0 - not waiting
ptsWaitingForShortPoll(int32 ms)367 	void ptsWaitingForShortPoll(int32 ms) {
368 		return _ptsWaiter.setWaitingForShortPoll(this, ms);
369 	}
ptsWaitingForSkipped()370 	[[nodiscard]] bool ptsWaitingForSkipped() const {
371 		return _ptsWaiter.waitingForSkipped();
372 	}
ptsWaitingForShortPoll()373 	[[nodiscard]] bool ptsWaitingForShortPoll() const {
374 		return _ptsWaiter.waitingForShortPoll();
375 	}
376 
377 	void setUnavailableReasons(
378 		std::vector<Data::UnavailableReason> &&reason);
379 
availableMinId()380 	[[nodiscard]] MsgId availableMinId() const {
381 		return _availableMinId;
382 	}
383 	void setAvailableMinId(MsgId availableMinId);
384 
385 	[[nodiscard]] ChatData *getMigrateFromChat() const;
386 	void setMigrateFromChat(ChatData *chat);
387 
388 	[[nodiscard]] int slowmodeSeconds() const;
389 	void setSlowmodeSeconds(int seconds);
390 	[[nodiscard]] TimeId slowmodeLastMessage() const;
391 	void growSlowmodeLastMessage(TimeId when);
392 
393 	void setInvitePeek(const QString &hash, TimeId expires);
394 	void clearInvitePeek();
395 	[[nodiscard]] TimeId invitePeekExpires() const;
396 	[[nodiscard]] QString invitePeekHash() const;
397 	void privateErrorReceived();
398 
groupCall()399 	[[nodiscard]] Data::GroupCall *groupCall() const {
400 		return _call.get();
401 	}
402 	void migrateCall(std::unique_ptr<Data::GroupCall> call);
403 	void setGroupCall(
404 		const MTPInputGroupCall &call,
405 		TimeId scheduleDate = 0);
406 	void clearGroupCall();
407 	void setGroupCallDefaultJoinAs(PeerId peerId);
408 	[[nodiscard]] PeerId groupCallDefaultJoinAs() const;
409 
410 	// Still public data members.
411 	uint64 access = 0;
412 
413 	MTPinputChannel inputChannel = MTP_inputChannelEmpty();
414 
415 	QString username;
416 
417 	int32 date = 0;
418 	std::unique_ptr<MegagroupInfo> mgInfo;
419 
420 	// > 0 - user who invited me to channel, < 0 - not in channel.
421 	UserId inviter = 0;
422 	TimeId inviteDate = 0;
423 	bool inviteViaRequest = false;
424 
425 private:
426 	struct InvitePeek {
427 		QString hash;
428 		TimeId expires = 0;
429 	};
430 
431 	auto unavailableReasons() const
432 		-> const std::vector<Data::UnavailableReason> & override;
433 	bool canEditLastAdmin(not_null<UserData*> user) const;
434 
435 	Flags _flags = ChannelDataFlags(Flag::Forbidden);
436 
437 	PtsWaiter _ptsWaiter;
438 
439 	int _membersCount = -1;
440 	int _adminsCount = 1;
441 	int _restrictedCount = 0;
442 	int _kickedCount = 0;
443 	int _pendingRequestsCount = 0;
444 	std::vector<UserId> _recentRequesters;
445 	MsgId _availableMinId = 0;
446 
447 	RestrictionFlags _defaultRestrictions;
448 	AdminRightFlags _adminRights;
449 	RestrictionFlags _restrictions;
450 	TimeId _restrictedUntil;
451 
452 	std::vector<Data::UnavailableReason> _unavailableReasons;
453 	std::unique_ptr<InvitePeek> _invitePeek;
454 	QString _inviteLink;
455 	std::optional<ChannelData*> _linkedChat;
456 
457 	std::unique_ptr<Data::GroupCall> _call;
458 	PeerId _callDefaultJoinAs = 0;
459 
460 	int _slowmodeSeconds = 0;
461 	TimeId _slowmodeLastMessage = 0;
462 
463 	rpl::lifetime _lifetime;
464 
465 };
466 
467 namespace Data {
468 
469 void ApplyMigration(
470 	not_null<ChatData*> chat,
471 	not_null<ChannelData*> channel);
472 
473 void ApplyChannelUpdate(
474 	not_null<ChannelData*> channel,
475 	const MTPDupdateChatDefaultBannedRights &update);
476 
477 void ApplyChannelUpdate(
478 	not_null<ChannelData*> channel,
479 	const MTPDchannelFull &update);
480 
481 void ApplyMegagroupAdmins(
482 	not_null<ChannelData*> channel,
483 	const MTPDchannels_channelParticipants &data);
484 
485 } // namespace Data
486