From 328b090877dda57c325c983555fecceac7396184 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 16 Jul 2019 13:46:50 +0200 Subject: [PATCH] Save slowmode settings in groups. --- Telegram/SourceFiles/apiwrap.cpp | 53 ++---- Telegram/SourceFiles/apiwrap.h | 51 +++++- .../boxes/peers/edit_peer_info_box.cpp | 101 ++++++++++- .../boxes/peers/edit_peer_permissions_box.cpp | 18 +- .../boxes/peers/edit_peer_permissions_box.h | 11 +- Telegram/SourceFiles/data/data_channel.cpp | 33 ++++ Telegram/SourceFiles/data/data_channel.h | 160 ++++++++++-------- Telegram/SourceFiles/observer_peer.h | 1 + 8 files changed, 289 insertions(+), 139 deletions(-) diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index 9120f9caf..b17b93b24 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -1896,43 +1896,6 @@ void ApiWrap::unblockParticipant( _kickRequests.emplace(kick, requestId); } -void ApiWrap::saveDefaultRestrictions( - not_null peer, - const MTPChatBannedRights &rights, - Fn callback) { - if (_defaultRestrictionsRequests.contains(peer)) { - return; - } - const auto requestId = request(MTPmessages_EditChatDefaultBannedRights( - peer->input, - rights - )).done([=](const MTPUpdates &result) { - _defaultRestrictionsRequests.erase(peer); - applyUpdates(result); - if (callback) { - callback(true); - } - }).fail([=](const RPCError &error) { - _defaultRestrictionsRequests.erase(peer); - if (error.type() == qstr("CHAT_NOT_MODIFIED")) { - if (const auto chat = peer->asChat()) { - chat->setDefaultRestrictions(rights); - } else if (const auto channel = peer->asChannel()) { - channel->setDefaultRestrictions(rights); - } else { - Unexpected("Peer in ApiWrap::saveDefaultRestrictions."); - } - if (callback) { - callback(true); - } - return; - } - if (callback) { - callback(false); - } - }).send(); -} - void ApiWrap::deleteAllFromUser( not_null channel, not_null from) { @@ -2683,6 +2646,22 @@ void ApiWrap::checkQuitPreventFinished() { } } +void ApiWrap::registerModifyRequest( + const QString &key, + mtpRequestId requestId) { + const auto i = _modifyRequests.find(key); + if (i != end(_modifyRequests)) { + request(i->second).cancel(); + i->second = requestId; + } else { + _modifyRequests.emplace(key, requestId); + } +} + +void ApiWrap::clearModifyRequest(const QString &key) { + _modifyRequests.remove(key); +} + void ApiWrap::applyNotifySettings( MTPInputNotifyPeer notifyPeer, const MTPPeerNotifySettings &settings) { diff --git a/Telegram/SourceFiles/apiwrap.h b/Telegram/SourceFiles/apiwrap.h index 9c6089517..a846a3190 100644 --- a/Telegram/SourceFiles/apiwrap.h +++ b/Telegram/SourceFiles/apiwrap.h @@ -46,6 +46,21 @@ struct CloudPasswordState; } // namespace Core namespace Api { +namespace details { + +inline QString ToString(const QString &value) { + return value; +} + +inline QString ToString(int32 value) { + return QString::number(value); +} + +inline QString ToString(uint64 value) { + return QString::number(value); +} + +} // namespace details template inline int32 CountHash(IntRange &&range) { @@ -56,6 +71,24 @@ inline int32 CountHash(IntRange &&range) { return int32(acc & 0x7FFFFFFF); } +template < + typename ...Types, + typename = std::enable_if_t<(sizeof...(Types) > 0)>> +QString RequestKey(Types &&...values) { + const auto strings = { details::ToString(values)... }; + if (strings.size() == 1) { + return *strings.begin(); + } + + auto result = QString(); + result.reserve( + ranges::accumulate(strings, 0, ranges::plus(), &QString::size)); + for (const auto &string : strings) { + result.append(string); + } + return result; +} + } // namespace Api class ApiWrap : public MTP::Sender, private base::Subscriber { @@ -103,7 +136,13 @@ public: AuthSession &session() const; - void applyUpdates(const MTPUpdates &updates, uint64 sentMessageRandomId = 0); + void applyUpdates( + const MTPUpdates &updates, + uint64 sentMessageRandomId = 0); + + void registerModifyRequest(const QString &key, mtpRequestId requestId); + void clearModifyRequest(const QString &key); + void applyNotifySettings( MTPInputNotifyPeer peer, const MTPPeerNotifySettings &settings); @@ -214,10 +253,6 @@ public: void deleteAllFromUser( not_null channel, not_null from); - void saveDefaultRestrictions( - not_null peer, - const MTPChatBannedRights &rights, - Fn callback = nullptr); void requestWebPageDelayed(WebPageData *page); void clearWebPageRequest(WebPageData *page); @@ -683,6 +718,8 @@ private: not_null _session; + base::flat_map _modifyRequests; + MessageDataRequests _messageDataRequests; QMap _channelMessageDataRequests; SingleQueuedInvokation _messageDataResolveDelayed; @@ -710,10 +747,6 @@ private: not_null>; base::flat_map _kickRequests; - base::flat_map< - not_null, - mtpRequestId> _defaultRestrictionsRequests; - base::flat_set> _selfParticipantRequests; base::flat_map< diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp index b4afc728b..56af4bf24 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp @@ -130,21 +130,104 @@ void AddButtonDelete( nullptr)); } +void SaveDefaultRestrictions( + not_null peer, + MTPChatBannedRights rights, + Fn done) { + const auto api = &peer->session().api(); + const auto key = Api::RequestKey("default_restrictions", peer->id); + + const auto requestId = api->request( + MTPmessages_EditChatDefaultBannedRights( + peer->input, + rights) + ).done([=](const MTPUpdates &result) { + api->clearModifyRequest(key); + api->applyUpdates(result); + done(); + }).fail([=](const RPCError &error) { + api->clearModifyRequest(key); + if (error.type() != qstr("CHAT_NOT_MODIFIED")) { + return; + } + if (const auto chat = peer->asChat()) { + chat->setDefaultRestrictions(rights); + } else if (const auto channel = peer->asChannel()) { + channel->setDefaultRestrictions(rights); + } else { + Unexpected("Peer in ApiWrap::saveDefaultRestrictions."); + } + done(); + }).send(); + + api->registerModifyRequest(key, requestId); +} + +void SaveSlowmodeSeconds( + not_null channel, + int seconds, + Fn done) { + const auto api = &channel->session().api(); + const auto key = Api::RequestKey("slowmode_seconds", channel->id); + + const auto requestId = api->request(MTPchannels_ToggleSlowMode( + channel->inputChannel, + MTP_int(seconds) + )).done([=](const MTPUpdates &result) { + api->clearModifyRequest(key); + api->applyUpdates(result); + channel->setSlowmodeSeconds(seconds); + done(); + }).fail([=](const RPCError &error) { + api->clearModifyRequest(key); + if (error.type() != qstr("CHAT_NOT_MODIFIED")) { + return; + } + channel->setSlowmodeSeconds(seconds); + done(); + }).send(); + + api->registerModifyRequest(key, requestId); +} + void ShowEditPermissions(not_null peer) { const auto box = Ui::show( Box(peer), LayerOption::KeepOther); + const auto saving = box->lifetime().make_state(0); + const auto save = [=]( + not_null peer, + EditPeerPermissionsBox::Result result) { + Expects(result.slowmodeSeconds == 0 || peer->isChannel()); + + const auto close = crl::guard(box, [=] { box->closeBox(); }); + SaveDefaultRestrictions( + peer, + MTP_chatBannedRights(MTP_flags(result.rights), MTP_int(0)), + close); + if (const auto channel = peer->asChannel()) { + SaveSlowmodeSeconds(channel, result.slowmodeSeconds, close); + } + }; box->saveEvents( - ) | rpl::start_with_next([=](MTPDchatBannedRights::Flags restrictions) { - const auto callback = crl::guard(box, [=](bool success) { - if (success) { - box->closeBox(); - } + ) | rpl::start_with_next([=](EditPeerPermissionsBox::Result result) { + if (*saving) { + return; + } + *saving = true; + + const auto saveFor = peer->migrateToOrMe(); + const auto chat = saveFor->asChat(); + if (!result.slowmodeSeconds || !chat) { + save(saveFor, result); + return; + } + const auto api = &peer->session().api(); + api->migrateChat(chat, [=](not_null channel) { + save(channel, result); + }, [=](const RPCError &error) { + *saving = false; }); - peer->session().api().saveDefaultRestrictions( - peer->migrateToOrMe(), - MTP_chatBannedRights(MTP_flags(restrictions), MTP_int(0)), - callback); }, box->lifetime()); } diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp index 596cd71d5..dd20ddffa 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp @@ -308,8 +308,7 @@ EditPeerPermissionsBox::EditPeerPermissionsBox( : _peer(peer->migrateToOrMe()) { } -auto EditPeerPermissionsBox::saveEvents() const --> rpl::producer { +auto EditPeerPermissionsBox::saveEvents() const -> rpl::producer { Expects(_save != nullptr); return _save->clicks() | rpl::map(_value); @@ -360,28 +359,31 @@ void EditPeerPermissionsBox::prepare() { inner->add(std::move(checkboxes)); - addSlowmodeSlider(inner); + const auto getSlowmodeSeconds = addSlowmodeSlider(inner); addBannedButtons(inner); - _value = getRestrictions; + _value = [=, rights = getRestrictions]() -> Result { + return { rights(), getSlowmodeSeconds() }; + }; _save = addButton(tr::lng_settings_save()); addButton(tr::lng_cancel(), [=] { closeBox(); }); setDimensionsToContent(st::boxWidth, inner); } -void EditPeerPermissionsBox::addSlowmodeSlider( +Fn EditPeerPermissionsBox::addSlowmodeSlider( not_null container) { using namespace rpl::mappers; if (const auto chat = _peer->asChat()) { if (!chat->amCreator()) { - return; + return [] { return 0; }; } } const auto channel = _peer->asChannel(); auto &lifetime = container->lifetime(); - const auto secondsCount = lifetime.make_state>(0); + const auto secondsCount = lifetime.make_state>( + channel ? channel->slowmodeSeconds() : 0); container->add( object_ptr(container), @@ -455,6 +457,8 @@ void EditPeerPermissionsBox::addSlowmodeSlider( st::boxDividerLabel), st::proxyAboutPadding), style::margins(0, st::infoProfileSkip, 0, st::infoProfileSkip)); + + return [=] { return secondsCount->current(); }; } void EditPeerPermissionsBox::addSlowmodeLabels( diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.h b/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.h index 79fa3e017..c62a28a56 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.h +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.h @@ -19,19 +19,24 @@ class EditPeerPermissionsBox : public BoxContent { public: EditPeerPermissionsBox(QWidget*, not_null peer); - rpl::producer saveEvents() const; + struct Result { + MTPDchatBannedRights::Flags rights; + int slowmodeSeconds = 0; + }; + + rpl::producer saveEvents() const; protected: void prepare() override; private: - void addSlowmodeSlider(not_null container); + Fn addSlowmodeSlider(not_null container); void addSlowmodeLabels(not_null container); void addBannedButtons(not_null container); not_null _peer; Ui::RoundButton *_save = nullptr; - Fn _value; + Fn _value; }; diff --git a/Telegram/SourceFiles/data/data_channel.cpp b/Telegram/SourceFiles/data/data_channel.cpp index b13f80ace..0919a12d5 100644 --- a/Telegram/SourceFiles/data/data_channel.cpp +++ b/Telegram/SourceFiles/data/data_channel.cpp @@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_session.h" #include "data/data_folder.h" #include "data/data_location.h" +#include "base/unixtime.h" #include "history/history.h" #include "observer_peer.h" #include "auth_session.h" @@ -580,6 +581,31 @@ void ChannelData::setMigrateFromChat(ChatData *chat) { } } +int ChannelData::slowmodeSeconds() const { + return _slowmodeSeconds; +} + +void ChannelData::setSlowmodeSeconds(int seconds) { + if (_slowmodeSeconds == seconds) { + return; + } + _slowmodeSeconds = seconds; + Notify::peerUpdatedDelayed(this, UpdateFlag::ChannelSlowmode); +} + +TimeId ChannelData::slowmodeLastMessage() const { + return (hasAdminRights() || amCreator()) ? 0 : _slowmodeLastMessage; +} + +void ChannelData::setSlowmodeLastMessage(TimeId when) { + const auto time = when ? when : base::unixtime::now(); + if (_slowmodeLastMessage == time) { + return; + } + _slowmodeLastMessage = time; + Notify::peerUpdatedDelayed(this, UpdateFlag::ChannelSlowmode); +} + namespace Data { void ApplyMigration( @@ -630,6 +656,13 @@ void ApplyChannelUpdate( channel->setAdminsCount(update.vadmins_count().value_or_empty()); channel->setRestrictedCount(update.vbanned_count().value_or_empty()); channel->setKickedCount(update.vkicked_count().value_or_empty()); + channel->setSlowmodeSeconds(update.vslowmode_seconds().value_or_empty()); + if (const auto next = update.vslowmode_next_send_date()) { + if (next->v > base::unixtime::now()) { + channel->growSlowmodeLastMessage( + next->v - channel->slowmodeSeconds()); + } + } channel->setInviteLink(update.vexported_invite().match([&]( const MTPDchatInviteExported &data) { return qs(data.vlink()); diff --git a/Telegram/SourceFiles/data/data_channel.h b/Telegram/SourceFiles/data/data_channel.h index f225a0fe5..8ac00face 100644 --- a/Telegram/SourceFiles/data/data_channel.h +++ b/Telegram/SourceFiles/data/data_channel.h @@ -104,7 +104,9 @@ public: | MTPDchannelFull::Flag::f_can_view_participants | MTPDchannelFull::Flag::f_can_set_username | MTPDchannelFull::Flag::f_can_set_stickers - | MTPDchannelFull::Flag::f_location; + | MTPDchannelFull::Flag::f_location + | MTPDchannelFull::Flag::f_slowmode_seconds + | MTPDchannelFull::Flag::f_slowmode_next_send_date; using FullFlags = Data::Flags< MTPDchannelFull::Flags, kEssentialFullFlags>; @@ -132,10 +134,10 @@ public: void removeFlags(MTPDchannel::Flags which) { _flags.remove(which); } - auto flags() const { + [[nodiscard]] auto flags() const { return _flags.current(); } - auto flagsValue() const { + [[nodiscard]] auto flagsValue() const { return _flags.value(); } @@ -148,58 +150,58 @@ public: void removeFullFlags(MTPDchannelFull::Flags which) { _fullFlags.remove(which); } - auto fullFlags() const { + [[nodiscard]] auto fullFlags() const { return _fullFlags.current(); } - auto fullFlagsValue() const { + [[nodiscard]] auto fullFlagsValue() const { return _fullFlags.value(); } - int membersCount() const { + [[nodiscard]] int membersCount() const { return std::max(_membersCount, 1); } void setMembersCount(int newMembersCount); - bool membersCountKnown() const { + [[nodiscard]] bool membersCountKnown() const { return (_membersCount >= 0); } - int adminsCount() const { + [[nodiscard]] int adminsCount() const { return _adminsCount; } void setAdminsCount(int newAdminsCount); - int restrictedCount() const { + [[nodiscard]] int restrictedCount() const { return _restrictedCount; } void setRestrictedCount(int newRestrictedCount); - int kickedCount() const { + [[nodiscard]] int kickedCount() const { return _kickedCount; } void setKickedCount(int newKickedCount); - bool haveLeft() const { + [[nodiscard]] bool haveLeft() const { return flags() & MTPDchannel::Flag::f_left; } - bool amIn() const { + [[nodiscard]] bool amIn() const { return !isForbidden() && !haveLeft(); } - bool addsSignature() const { + [[nodiscard]] bool addsSignature() const { return flags() & MTPDchannel::Flag::f_signatures; } - bool isForbidden() const { + [[nodiscard]] bool isForbidden() const { return flags() & MTPDchannel_ClientFlag::f_forbidden; } - bool isVerified() const { + [[nodiscard]] bool isVerified() const { return flags() & MTPDchannel::Flag::f_verified; } - bool isScam() const { + [[nodiscard]] bool isScam() const { return flags() & MTPDchannel::Flag::f_scam; } static MTPChatBannedRights KickedRestrictedRights(); static constexpr auto kRestrictUntilForever = TimeId(INT_MAX); - static bool IsRestrictedForever(TimeId until) { + [[nodiscard]] static bool IsRestrictedForever(TimeId until) { return !until || (until == kRestrictUntilForever); } void applyEditAdmin( @@ -213,9 +215,9 @@ public: void markForbidden(); - bool isGroupAdmin(not_null user) const; + [[nodiscard]] bool isGroupAdmin(not_null user) const; - bool lastParticipantsCountOutdated() const { + [[nodiscard]] bool lastParticipantsCountOutdated() const { if (!mgInfo || !(mgInfo->lastParticipantsStatus & MegagroupInfo::LastParticipantsCountOutdated)) { @@ -228,96 +230,96 @@ public: } return true; } - bool isMegagroup() const { + [[nodiscard]] bool isMegagroup() const { return flags() & MTPDchannel::Flag::f_megagroup; } - bool isBroadcast() const { + [[nodiscard]] bool isBroadcast() const { return flags() & MTPDchannel::Flag::f_broadcast; } - bool hasUsername() const { + [[nodiscard]] bool hasUsername() const { return flags() & MTPDchannel::Flag::f_username; } - bool hasLocation() const { + [[nodiscard]] bool hasLocation() const { return fullFlags() & MTPDchannelFull::Flag::f_location; } - bool isPublic() const { + [[nodiscard]] bool isPublic() const { return hasUsername() || hasLocation(); } - bool amCreator() const { + [[nodiscard]] bool amCreator() const { return flags() & MTPDchannel::Flag::f_creator; } - auto adminRights() const { + [[nodiscard]] auto adminRights() const { return _adminRights.current(); } - auto adminRightsValue() const { + [[nodiscard]] auto adminRightsValue() const { return _adminRights.value(); } void setAdminRights(const MTPChatAdminRights &rights); - bool hasAdminRights() const { + [[nodiscard]] bool hasAdminRights() const { return (adminRights() != 0); } - auto restrictions() const { + [[nodiscard]] auto restrictions() const { return _restrictions.current(); } - auto restrictionsValue() const { + [[nodiscard]] auto restrictionsValue() const { return _restrictions.value(); } - TimeId restrictedUntil() const { + [[nodiscard]] TimeId restrictedUntil() const { return _restrictedUntil; } void setRestrictions(const MTPChatBannedRights &rights); - bool hasRestrictions() const { + [[nodiscard]] bool hasRestrictions() const { return (restrictions() != 0); } - bool hasRestrictions(TimeId now) const { + [[nodiscard]] bool hasRestrictions(TimeId now) const { return hasRestrictions() && (restrictedUntil() > now); } - auto defaultRestrictions() const { + [[nodiscard]] auto defaultRestrictions() const { return _defaultRestrictions.current(); } - auto defaultRestrictionsValue() const { + [[nodiscard]] auto defaultRestrictionsValue() const { return _defaultRestrictions.value(); } void setDefaultRestrictions(const MTPChatBannedRights &rights); // Like in ChatData. - bool canWrite() const; - bool canEditInformation() const; - bool canEditPermissions() const; - bool canEditUsername() const; - bool canEditPreHistoryHidden() const; - bool canAddMembers() const; - bool canAddAdmins() const; - bool canBanMembers() const; - bool canSendPolls() const; - bool anyoneCanAddMembers() const; + [[nodiscard]] bool canWrite() const; + [[nodiscard]] bool canEditInformation() const; + [[nodiscard]] bool canEditPermissions() const; + [[nodiscard]] bool canEditUsername() const; + [[nodiscard]] bool canEditPreHistoryHidden() const; + [[nodiscard]] bool canAddMembers() const; + [[nodiscard]] bool canAddAdmins() const; + [[nodiscard]] bool canBanMembers() const; + [[nodiscard]] bool canSendPolls() const; + [[nodiscard]] bool anyoneCanAddMembers() const; - bool canEditMessages() const; - bool canDeleteMessages() const; - bool hiddenPreHistory() const; - bool canPublish() const; - bool canViewMembers() const; - bool canViewAdmins() const; - bool canViewBanned() const; - bool canEditSignatures() const; - bool canEditStickers() const; - bool canDelete() const; - bool canEditAdmin(not_null user) const; - bool canRestrictUser(not_null user) const; + [[nodiscard]] bool canEditMessages() const; + [[nodiscard]] bool canDeleteMessages() const; + [[nodiscard]] bool hiddenPreHistory() const; + [[nodiscard]] bool canPublish() const; + [[nodiscard]] bool canViewMembers() const; + [[nodiscard]] bool canViewAdmins() const; + [[nodiscard]] bool canViewBanned() const; + [[nodiscard]] bool canEditSignatures() const; + [[nodiscard]] bool canEditStickers() const; + [[nodiscard]] bool canDelete() const; + [[nodiscard]] bool canEditAdmin(not_null user) const; + [[nodiscard]] bool canRestrictUser(not_null user) const; void setInviteLink(const QString &newInviteLink); - QString inviteLink() const; - bool canHaveInviteLink() const; + [[nodiscard]] QString inviteLink() const; + [[nodiscard]] bool canHaveInviteLink() const; void setLocation(const MTPChannelLocation &data); - const ChannelLocation *getLocation() const; + [[nodiscard]] const ChannelLocation *getLocation() const; void setLinkedChat(ChannelData *linked); - ChannelData *linkedChat() const; + [[nodiscard]] ChannelData *linkedChat() const; void ptsInit(int32 pts) { _ptsWaiter.init(pts); @@ -335,37 +337,38 @@ public: return _ptsWaiter.updateAndApply(this, pts, count, update); } bool ptsUpdateAndApply( - int32 pts, - int32 count, - const MTPUpdates &updates) { + int32 pts, + int32 count, + const MTPUpdates &updates) { return _ptsWaiter.updateAndApply(this, pts, count, updates); } - int32 pts() const { + [[nodiscard]] int32 pts() const { return _ptsWaiter.current(); } - bool ptsInited() const { + [[nodiscard]] bool ptsInited() const { return _ptsWaiter.inited(); } - bool ptsRequesting() const { + [[nodiscard]] bool ptsRequesting() const { return _ptsWaiter.requesting(); } void ptsSetRequesting(bool isRequesting) { return _ptsWaiter.setRequesting(isRequesting); } - void ptsWaitingForShortPoll(int32 ms) { // < 0 - not waiting + // < 0 - not waiting + void ptsWaitingForShortPoll(int32 ms) { return _ptsWaiter.setWaitingForShortPoll(this, ms); } - bool ptsWaitingForSkipped() const { + [[nodiscard]] bool ptsWaitingForSkipped() const { return _ptsWaiter.waitingForSkipped(); } - bool ptsWaitingForShortPoll() const { + [[nodiscard]] bool ptsWaitingForShortPoll() const { return _ptsWaiter.waitingForShortPoll(); } - QString unavailableReason() const override; + [[nodiscard]] QString unavailableReason() const override; void setUnavailableReason(const QString &reason); - MsgId availableMinId() const { + [[nodiscard]] MsgId availableMinId() const { return _availableMinId; } void setAvailableMinId(MsgId availableMinId); @@ -383,9 +386,14 @@ public: } UpdateStatus applyUpdateVersion(int version); - ChatData *getMigrateFromChat() const; + [[nodiscard]] ChatData *getMigrateFromChat() const; void setMigrateFromChat(ChatData *chat); + [[nodiscard]] int slowmodeSeconds() const; + void setSlowmodeSeconds(int seconds); + [[nodiscard]] TimeId slowmodeLastMessage() const; + void setSlowmodeLastMessage(TimeId when = 0); + // Still public data members. uint64 access = 0; @@ -396,7 +404,8 @@ public: int32 date = 0; std::unique_ptr mgInfo; - UserId inviter = 0; // > 0 - user who invited me to channel, < 0 - not in channel + // > 0 - user who invited me to channel, < 0 - not in channel. + UserId inviter = 0; TimeId inviteDate = 0; private: @@ -423,6 +432,9 @@ private: QString _inviteLink; ChannelData *_linkedChat = nullptr; + int _slowmodeSeconds = 0; + TimeId _slowmodeLastMessage = 0; + rpl::lifetime _lifetime; }; diff --git a/Telegram/SourceFiles/observer_peer.h b/Telegram/SourceFiles/observer_peer.h index 4eaf46c3c..231342793 100644 --- a/Telegram/SourceFiles/observer_peer.h +++ b/Telegram/SourceFiles/observer_peer.h @@ -67,6 +67,7 @@ struct PeerUpdate { ChannelPromotedChanged = (1 << 19), ChannelLinkedChat = (1 << 20), ChannelLocation = (1 << 21), + ChannelSlowmode = (1 << 22), }; using Flags = base::flags; friend inline constexpr auto is_flag_type(Flag) { return true; }