Save slowmode settings in groups.

This commit is contained in:
John Preston 2019-07-16 13:46:50 +02:00
parent 1d2c86839b
commit 328b090877
8 changed files with 289 additions and 139 deletions

View File

@ -1896,43 +1896,6 @@ void ApiWrap::unblockParticipant(
_kickRequests.emplace(kick, requestId); _kickRequests.emplace(kick, requestId);
} }
void ApiWrap::saveDefaultRestrictions(
not_null<PeerData*> peer,
const MTPChatBannedRights &rights,
Fn<void(bool)> 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( void ApiWrap::deleteAllFromUser(
not_null<ChannelData*> channel, not_null<ChannelData*> channel,
not_null<UserData*> from) { not_null<UserData*> 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( void ApiWrap::applyNotifySettings(
MTPInputNotifyPeer notifyPeer, MTPInputNotifyPeer notifyPeer,
const MTPPeerNotifySettings &settings) { const MTPPeerNotifySettings &settings) {

View File

@ -46,6 +46,21 @@ struct CloudPasswordState;
} // namespace Core } // namespace Core
namespace Api { 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 <typename IntRange> template <typename IntRange>
inline int32 CountHash(IntRange &&range) { inline int32 CountHash(IntRange &&range) {
@ -56,6 +71,24 @@ inline int32 CountHash(IntRange &&range) {
return int32(acc & 0x7FFFFFFF); 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 } // namespace Api
class ApiWrap : public MTP::Sender, private base::Subscriber { class ApiWrap : public MTP::Sender, private base::Subscriber {
@ -103,7 +136,13 @@ public:
AuthSession &session() const; 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( void applyNotifySettings(
MTPInputNotifyPeer peer, MTPInputNotifyPeer peer,
const MTPPeerNotifySettings &settings); const MTPPeerNotifySettings &settings);
@ -214,10 +253,6 @@ public:
void deleteAllFromUser( void deleteAllFromUser(
not_null<ChannelData*> channel, not_null<ChannelData*> channel,
not_null<UserData*> from); not_null<UserData*> from);
void saveDefaultRestrictions(
not_null<PeerData*> peer,
const MTPChatBannedRights &rights,
Fn<void(bool)> callback = nullptr);
void requestWebPageDelayed(WebPageData *page); void requestWebPageDelayed(WebPageData *page);
void clearWebPageRequest(WebPageData *page); void clearWebPageRequest(WebPageData *page);
@ -683,6 +718,8 @@ private:
not_null<AuthSession*> _session; not_null<AuthSession*> _session;
base::flat_map<QString, int> _modifyRequests;
MessageDataRequests _messageDataRequests; MessageDataRequests _messageDataRequests;
QMap<ChannelData*, MessageDataRequests> _channelMessageDataRequests; QMap<ChannelData*, MessageDataRequests> _channelMessageDataRequests;
SingleQueuedInvokation _messageDataResolveDelayed; SingleQueuedInvokation _messageDataResolveDelayed;
@ -710,10 +747,6 @@ private:
not_null<UserData*>>; not_null<UserData*>>;
base::flat_map<KickRequest, mtpRequestId> _kickRequests; base::flat_map<KickRequest, mtpRequestId> _kickRequests;
base::flat_map<
not_null<PeerData*>,
mtpRequestId> _defaultRestrictionsRequests;
base::flat_set<not_null<ChannelData*>> _selfParticipantRequests; base::flat_set<not_null<ChannelData*>> _selfParticipantRequests;
base::flat_map< base::flat_map<

View File

@ -130,21 +130,104 @@ void AddButtonDelete(
nullptr)); nullptr));
} }
void SaveDefaultRestrictions(
not_null<PeerData*> peer,
MTPChatBannedRights rights,
Fn<void()> 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<ChannelData*> channel,
int seconds,
Fn<void()> 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<PeerData*> peer) { void ShowEditPermissions(not_null<PeerData*> peer) {
const auto box = Ui::show( const auto box = Ui::show(
Box<EditPeerPermissionsBox>(peer), Box<EditPeerPermissionsBox>(peer),
LayerOption::KeepOther); LayerOption::KeepOther);
box->saveEvents( const auto saving = box->lifetime().make_state<int>(0);
) | rpl::start_with_next([=](MTPDchatBannedRights::Flags restrictions) { const auto save = [=](
const auto callback = crl::guard(box, [=](bool success) { not_null<PeerData*> peer,
if (success) { EditPeerPermissionsBox::Result result) {
box->closeBox(); 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([=](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<ChannelData*> 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()); }, box->lifetime());
} }

View File

@ -308,8 +308,7 @@ EditPeerPermissionsBox::EditPeerPermissionsBox(
: _peer(peer->migrateToOrMe()) { : _peer(peer->migrateToOrMe()) {
} }
auto EditPeerPermissionsBox::saveEvents() const auto EditPeerPermissionsBox::saveEvents() const -> rpl::producer<Result> {
-> rpl::producer<MTPDchatBannedRights::Flags> {
Expects(_save != nullptr); Expects(_save != nullptr);
return _save->clicks() | rpl::map(_value); return _save->clicks() | rpl::map(_value);
@ -360,28 +359,31 @@ void EditPeerPermissionsBox::prepare() {
inner->add(std::move(checkboxes)); inner->add(std::move(checkboxes));
addSlowmodeSlider(inner); const auto getSlowmodeSeconds = addSlowmodeSlider(inner);
addBannedButtons(inner); addBannedButtons(inner);
_value = getRestrictions; _value = [=, rights = getRestrictions]() -> Result {
return { rights(), getSlowmodeSeconds() };
};
_save = addButton(tr::lng_settings_save()); _save = addButton(tr::lng_settings_save());
addButton(tr::lng_cancel(), [=] { closeBox(); }); addButton(tr::lng_cancel(), [=] { closeBox(); });
setDimensionsToContent(st::boxWidth, inner); setDimensionsToContent(st::boxWidth, inner);
} }
void EditPeerPermissionsBox::addSlowmodeSlider( Fn<int()> EditPeerPermissionsBox::addSlowmodeSlider(
not_null<Ui::VerticalLayout*> container) { not_null<Ui::VerticalLayout*> container) {
using namespace rpl::mappers; using namespace rpl::mappers;
if (const auto chat = _peer->asChat()) { if (const auto chat = _peer->asChat()) {
if (!chat->amCreator()) { if (!chat->amCreator()) {
return; return [] { return 0; };
} }
} }
const auto channel = _peer->asChannel(); const auto channel = _peer->asChannel();
auto &lifetime = container->lifetime(); auto &lifetime = container->lifetime();
const auto secondsCount = lifetime.make_state<rpl::variable<int>>(0); const auto secondsCount = lifetime.make_state<rpl::variable<int>>(
channel ? channel->slowmodeSeconds() : 0);
container->add( container->add(
object_ptr<BoxContentDivider>(container), object_ptr<BoxContentDivider>(container),
@ -455,6 +457,8 @@ void EditPeerPermissionsBox::addSlowmodeSlider(
st::boxDividerLabel), st::boxDividerLabel),
st::proxyAboutPadding), st::proxyAboutPadding),
style::margins(0, st::infoProfileSkip, 0, st::infoProfileSkip)); style::margins(0, st::infoProfileSkip, 0, st::infoProfileSkip));
return [=] { return secondsCount->current(); };
} }
void EditPeerPermissionsBox::addSlowmodeLabels( void EditPeerPermissionsBox::addSlowmodeLabels(

View File

@ -19,19 +19,24 @@ class EditPeerPermissionsBox : public BoxContent {
public: public:
EditPeerPermissionsBox(QWidget*, not_null<PeerData*> peer); EditPeerPermissionsBox(QWidget*, not_null<PeerData*> peer);
rpl::producer<MTPDchatBannedRights::Flags> saveEvents() const; struct Result {
MTPDchatBannedRights::Flags rights;
int slowmodeSeconds = 0;
};
rpl::producer<Result> saveEvents() const;
protected: protected:
void prepare() override; void prepare() override;
private: private:
void addSlowmodeSlider(not_null<Ui::VerticalLayout*> container); Fn<int()> addSlowmodeSlider(not_null<Ui::VerticalLayout*> container);
void addSlowmodeLabels(not_null<Ui::VerticalLayout*> container); void addSlowmodeLabels(not_null<Ui::VerticalLayout*> container);
void addBannedButtons(not_null<Ui::VerticalLayout*> container); void addBannedButtons(not_null<Ui::VerticalLayout*> container);
not_null<PeerData*> _peer; not_null<PeerData*> _peer;
Ui::RoundButton *_save = nullptr; Ui::RoundButton *_save = nullptr;
Fn<MTPDchatBannedRights::Flags()> _value; Fn<Result()> _value;
}; };

View File

@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_folder.h" #include "data/data_folder.h"
#include "data/data_location.h" #include "data/data_location.h"
#include "base/unixtime.h"
#include "history/history.h" #include "history/history.h"
#include "observer_peer.h" #include "observer_peer.h"
#include "auth_session.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 { namespace Data {
void ApplyMigration( void ApplyMigration(
@ -630,6 +656,13 @@ void ApplyChannelUpdate(
channel->setAdminsCount(update.vadmins_count().value_or_empty()); channel->setAdminsCount(update.vadmins_count().value_or_empty());
channel->setRestrictedCount(update.vbanned_count().value_or_empty()); channel->setRestrictedCount(update.vbanned_count().value_or_empty());
channel->setKickedCount(update.vkicked_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([&]( channel->setInviteLink(update.vexported_invite().match([&](
const MTPDchatInviteExported &data) { const MTPDchatInviteExported &data) {
return qs(data.vlink()); return qs(data.vlink());

View File

@ -104,7 +104,9 @@ public:
| MTPDchannelFull::Flag::f_can_view_participants | MTPDchannelFull::Flag::f_can_view_participants
| MTPDchannelFull::Flag::f_can_set_username | MTPDchannelFull::Flag::f_can_set_username
| MTPDchannelFull::Flag::f_can_set_stickers | 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< using FullFlags = Data::Flags<
MTPDchannelFull::Flags, MTPDchannelFull::Flags,
kEssentialFullFlags>; kEssentialFullFlags>;
@ -132,10 +134,10 @@ public:
void removeFlags(MTPDchannel::Flags which) { void removeFlags(MTPDchannel::Flags which) {
_flags.remove(which); _flags.remove(which);
} }
auto flags() const { [[nodiscard]] auto flags() const {
return _flags.current(); return _flags.current();
} }
auto flagsValue() const { [[nodiscard]] auto flagsValue() const {
return _flags.value(); return _flags.value();
} }
@ -148,58 +150,58 @@ public:
void removeFullFlags(MTPDchannelFull::Flags which) { void removeFullFlags(MTPDchannelFull::Flags which) {
_fullFlags.remove(which); _fullFlags.remove(which);
} }
auto fullFlags() const { [[nodiscard]] auto fullFlags() const {
return _fullFlags.current(); return _fullFlags.current();
} }
auto fullFlagsValue() const { [[nodiscard]] auto fullFlagsValue() const {
return _fullFlags.value(); return _fullFlags.value();
} }
int membersCount() const { [[nodiscard]] int membersCount() const {
return std::max(_membersCount, 1); return std::max(_membersCount, 1);
} }
void setMembersCount(int newMembersCount); void setMembersCount(int newMembersCount);
bool membersCountKnown() const { [[nodiscard]] bool membersCountKnown() const {
return (_membersCount >= 0); return (_membersCount >= 0);
} }
int adminsCount() const { [[nodiscard]] int adminsCount() const {
return _adminsCount; return _adminsCount;
} }
void setAdminsCount(int newAdminsCount); void setAdminsCount(int newAdminsCount);
int restrictedCount() const { [[nodiscard]] int restrictedCount() const {
return _restrictedCount; return _restrictedCount;
} }
void setRestrictedCount(int newRestrictedCount); void setRestrictedCount(int newRestrictedCount);
int kickedCount() const { [[nodiscard]] int kickedCount() const {
return _kickedCount; return _kickedCount;
} }
void setKickedCount(int newKickedCount); void setKickedCount(int newKickedCount);
bool haveLeft() const { [[nodiscard]] bool haveLeft() const {
return flags() & MTPDchannel::Flag::f_left; return flags() & MTPDchannel::Flag::f_left;
} }
bool amIn() const { [[nodiscard]] bool amIn() const {
return !isForbidden() && !haveLeft(); return !isForbidden() && !haveLeft();
} }
bool addsSignature() const { [[nodiscard]] bool addsSignature() const {
return flags() & MTPDchannel::Flag::f_signatures; return flags() & MTPDchannel::Flag::f_signatures;
} }
bool isForbidden() const { [[nodiscard]] bool isForbidden() const {
return flags() & MTPDchannel_ClientFlag::f_forbidden; return flags() & MTPDchannel_ClientFlag::f_forbidden;
} }
bool isVerified() const { [[nodiscard]] bool isVerified() const {
return flags() & MTPDchannel::Flag::f_verified; return flags() & MTPDchannel::Flag::f_verified;
} }
bool isScam() const { [[nodiscard]] bool isScam() const {
return flags() & MTPDchannel::Flag::f_scam; return flags() & MTPDchannel::Flag::f_scam;
} }
static MTPChatBannedRights KickedRestrictedRights(); static MTPChatBannedRights KickedRestrictedRights();
static constexpr auto kRestrictUntilForever = TimeId(INT_MAX); static constexpr auto kRestrictUntilForever = TimeId(INT_MAX);
static bool IsRestrictedForever(TimeId until) { [[nodiscard]] static bool IsRestrictedForever(TimeId until) {
return !until || (until == kRestrictUntilForever); return !until || (until == kRestrictUntilForever);
} }
void applyEditAdmin( void applyEditAdmin(
@ -213,9 +215,9 @@ public:
void markForbidden(); void markForbidden();
bool isGroupAdmin(not_null<UserData*> user) const; [[nodiscard]] bool isGroupAdmin(not_null<UserData*> user) const;
bool lastParticipantsCountOutdated() const { [[nodiscard]] bool lastParticipantsCountOutdated() const {
if (!mgInfo if (!mgInfo
|| !(mgInfo->lastParticipantsStatus || !(mgInfo->lastParticipantsStatus
& MegagroupInfo::LastParticipantsCountOutdated)) { & MegagroupInfo::LastParticipantsCountOutdated)) {
@ -228,96 +230,96 @@ public:
} }
return true; return true;
} }
bool isMegagroup() const { [[nodiscard]] bool isMegagroup() const {
return flags() & MTPDchannel::Flag::f_megagroup; return flags() & MTPDchannel::Flag::f_megagroup;
} }
bool isBroadcast() const { [[nodiscard]] bool isBroadcast() const {
return flags() & MTPDchannel::Flag::f_broadcast; return flags() & MTPDchannel::Flag::f_broadcast;
} }
bool hasUsername() const { [[nodiscard]] bool hasUsername() const {
return flags() & MTPDchannel::Flag::f_username; return flags() & MTPDchannel::Flag::f_username;
} }
bool hasLocation() const { [[nodiscard]] bool hasLocation() const {
return fullFlags() & MTPDchannelFull::Flag::f_location; return fullFlags() & MTPDchannelFull::Flag::f_location;
} }
bool isPublic() const { [[nodiscard]] bool isPublic() const {
return hasUsername() || hasLocation(); return hasUsername() || hasLocation();
} }
bool amCreator() const { [[nodiscard]] bool amCreator() const {
return flags() & MTPDchannel::Flag::f_creator; return flags() & MTPDchannel::Flag::f_creator;
} }
auto adminRights() const { [[nodiscard]] auto adminRights() const {
return _adminRights.current(); return _adminRights.current();
} }
auto adminRightsValue() const { [[nodiscard]] auto adminRightsValue() const {
return _adminRights.value(); return _adminRights.value();
} }
void setAdminRights(const MTPChatAdminRights &rights); void setAdminRights(const MTPChatAdminRights &rights);
bool hasAdminRights() const { [[nodiscard]] bool hasAdminRights() const {
return (adminRights() != 0); return (adminRights() != 0);
} }
auto restrictions() const { [[nodiscard]] auto restrictions() const {
return _restrictions.current(); return _restrictions.current();
} }
auto restrictionsValue() const { [[nodiscard]] auto restrictionsValue() const {
return _restrictions.value(); return _restrictions.value();
} }
TimeId restrictedUntil() const { [[nodiscard]] TimeId restrictedUntil() const {
return _restrictedUntil; return _restrictedUntil;
} }
void setRestrictions(const MTPChatBannedRights &rights); void setRestrictions(const MTPChatBannedRights &rights);
bool hasRestrictions() const { [[nodiscard]] bool hasRestrictions() const {
return (restrictions() != 0); return (restrictions() != 0);
} }
bool hasRestrictions(TimeId now) const { [[nodiscard]] bool hasRestrictions(TimeId now) const {
return hasRestrictions() return hasRestrictions()
&& (restrictedUntil() > now); && (restrictedUntil() > now);
} }
auto defaultRestrictions() const { [[nodiscard]] auto defaultRestrictions() const {
return _defaultRestrictions.current(); return _defaultRestrictions.current();
} }
auto defaultRestrictionsValue() const { [[nodiscard]] auto defaultRestrictionsValue() const {
return _defaultRestrictions.value(); return _defaultRestrictions.value();
} }
void setDefaultRestrictions(const MTPChatBannedRights &rights); void setDefaultRestrictions(const MTPChatBannedRights &rights);
// Like in ChatData. // Like in ChatData.
bool canWrite() const; [[nodiscard]] bool canWrite() const;
bool canEditInformation() const; [[nodiscard]] bool canEditInformation() const;
bool canEditPermissions() const; [[nodiscard]] bool canEditPermissions() const;
bool canEditUsername() const; [[nodiscard]] bool canEditUsername() const;
bool canEditPreHistoryHidden() const; [[nodiscard]] bool canEditPreHistoryHidden() const;
bool canAddMembers() const; [[nodiscard]] bool canAddMembers() const;
bool canAddAdmins() const; [[nodiscard]] bool canAddAdmins() const;
bool canBanMembers() const; [[nodiscard]] bool canBanMembers() const;
bool canSendPolls() const; [[nodiscard]] bool canSendPolls() const;
bool anyoneCanAddMembers() const; [[nodiscard]] bool anyoneCanAddMembers() const;
bool canEditMessages() const; [[nodiscard]] bool canEditMessages() const;
bool canDeleteMessages() const; [[nodiscard]] bool canDeleteMessages() const;
bool hiddenPreHistory() const; [[nodiscard]] bool hiddenPreHistory() const;
bool canPublish() const; [[nodiscard]] bool canPublish() const;
bool canViewMembers() const; [[nodiscard]] bool canViewMembers() const;
bool canViewAdmins() const; [[nodiscard]] bool canViewAdmins() const;
bool canViewBanned() const; [[nodiscard]] bool canViewBanned() const;
bool canEditSignatures() const; [[nodiscard]] bool canEditSignatures() const;
bool canEditStickers() const; [[nodiscard]] bool canEditStickers() const;
bool canDelete() const; [[nodiscard]] bool canDelete() const;
bool canEditAdmin(not_null<UserData*> user) const; [[nodiscard]] bool canEditAdmin(not_null<UserData*> user) const;
bool canRestrictUser(not_null<UserData*> user) const; [[nodiscard]] bool canRestrictUser(not_null<UserData*> user) const;
void setInviteLink(const QString &newInviteLink); void setInviteLink(const QString &newInviteLink);
QString inviteLink() const; [[nodiscard]] QString inviteLink() const;
bool canHaveInviteLink() const; [[nodiscard]] bool canHaveInviteLink() const;
void setLocation(const MTPChannelLocation &data); void setLocation(const MTPChannelLocation &data);
const ChannelLocation *getLocation() const; [[nodiscard]] const ChannelLocation *getLocation() const;
void setLinkedChat(ChannelData *linked); void setLinkedChat(ChannelData *linked);
ChannelData *linkedChat() const; [[nodiscard]] ChannelData *linkedChat() const;
void ptsInit(int32 pts) { void ptsInit(int32 pts) {
_ptsWaiter.init(pts); _ptsWaiter.init(pts);
@ -340,32 +342,33 @@ public:
const MTPUpdates &updates) { const MTPUpdates &updates) {
return _ptsWaiter.updateAndApply(this, pts, count, updates); return _ptsWaiter.updateAndApply(this, pts, count, updates);
} }
int32 pts() const { [[nodiscard]] int32 pts() const {
return _ptsWaiter.current(); return _ptsWaiter.current();
} }
bool ptsInited() const { [[nodiscard]] bool ptsInited() const {
return _ptsWaiter.inited(); return _ptsWaiter.inited();
} }
bool ptsRequesting() const { [[nodiscard]] bool ptsRequesting() const {
return _ptsWaiter.requesting(); return _ptsWaiter.requesting();
} }
void ptsSetRequesting(bool isRequesting) { void ptsSetRequesting(bool isRequesting) {
return _ptsWaiter.setRequesting(isRequesting); return _ptsWaiter.setRequesting(isRequesting);
} }
void ptsWaitingForShortPoll(int32 ms) { // < 0 - not waiting // < 0 - not waiting
void ptsWaitingForShortPoll(int32 ms) {
return _ptsWaiter.setWaitingForShortPoll(this, ms); return _ptsWaiter.setWaitingForShortPoll(this, ms);
} }
bool ptsWaitingForSkipped() const { [[nodiscard]] bool ptsWaitingForSkipped() const {
return _ptsWaiter.waitingForSkipped(); return _ptsWaiter.waitingForSkipped();
} }
bool ptsWaitingForShortPoll() const { [[nodiscard]] bool ptsWaitingForShortPoll() const {
return _ptsWaiter.waitingForShortPoll(); return _ptsWaiter.waitingForShortPoll();
} }
QString unavailableReason() const override; [[nodiscard]] QString unavailableReason() const override;
void setUnavailableReason(const QString &reason); void setUnavailableReason(const QString &reason);
MsgId availableMinId() const { [[nodiscard]] MsgId availableMinId() const {
return _availableMinId; return _availableMinId;
} }
void setAvailableMinId(MsgId availableMinId); void setAvailableMinId(MsgId availableMinId);
@ -383,9 +386,14 @@ public:
} }
UpdateStatus applyUpdateVersion(int version); UpdateStatus applyUpdateVersion(int version);
ChatData *getMigrateFromChat() const; [[nodiscard]] ChatData *getMigrateFromChat() const;
void setMigrateFromChat(ChatData *chat); 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. // Still public data members.
uint64 access = 0; uint64 access = 0;
@ -396,7 +404,8 @@ public:
int32 date = 0; int32 date = 0;
std::unique_ptr<MegagroupInfo> mgInfo; std::unique_ptr<MegagroupInfo> 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; TimeId inviteDate = 0;
private: private:
@ -423,6 +432,9 @@ private:
QString _inviteLink; QString _inviteLink;
ChannelData *_linkedChat = nullptr; ChannelData *_linkedChat = nullptr;
int _slowmodeSeconds = 0;
TimeId _slowmodeLastMessage = 0;
rpl::lifetime _lifetime; rpl::lifetime _lifetime;
}; };

View File

@ -67,6 +67,7 @@ struct PeerUpdate {
ChannelPromotedChanged = (1 << 19), ChannelPromotedChanged = (1 << 19),
ChannelLinkedChat = (1 << 20), ChannelLinkedChat = (1 << 20),
ChannelLocation = (1 << 21), ChannelLocation = (1 << 21),
ChannelSlowmode = (1 << 22),
}; };
using Flags = base::flags<Flag>; using Flags = base::flags<Flag>;
friend inline constexpr auto is_flag_type(Flag) { return true; } friend inline constexpr auto is_flag_type(Flag) { return true; }