Destroy messages by ttl_period dates.

This commit is contained in:
John Preston 2021-02-02 18:42:26 +04:00
parent 9262b773cb
commit 046a3906c4
6 changed files with 110 additions and 0 deletions

View File

@ -975,6 +975,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_manage_history_visibility_hidden_about" = "New members won't see earlier messages.";
"lng_manage_history_visibility_hidden_legacy" = "New members won't see more than 100 previous messages.";
"lng_manage_messages_ttl_title" = "Auto-delete messages";
"lng_manage_messages_ttl_never" = "Never";
"lng_manage_messages_ttl_after1" = "After 24 hours";
"lng_manage_messages_ttl_after2" = "After 7 days";
"lng_manage_messages_ttl_about" = "Turning on this setting will make auto-delete messages from this group after the selected period.";
"lng_manage_messages_ttl_about_channel" = "Turning on this setting will make auto-delete messages from this channel after the selected period.";
"lng_report_title" = "Report channel";
"lng_report_group_title" = "Report group";
"lng_report_bot_title" = "Report bot";

View File

@ -220,6 +220,7 @@ Session::Session(not_null<Main::Session*> session)
session->serverConfig().pinnedDialogsCountMax.value())
, _contactsList(Dialogs::SortMode::Name)
, _contactsNoChatsList(Dialogs::SortMode::Name)
, _ttlCheckTimer([=] { checkTTLs(); })
, _selfDestructTimer([=] { checkSelfDestructItems(); })
, _sendActionsAnimation([=](crl::time now) {
return sendActionsAnimationCallback(now);
@ -1959,6 +1960,54 @@ void Session::registerMessage(not_null<HistoryItem*> item) {
list->emplace(itemId, item);
}
void Session::registerMessageTTL(TimeId when, not_null<HistoryItem*> item) {
Expects(when > 0);
auto &list = _ttlMessages[when];
list.emplace(item);
const auto nearest = _ttlMessages.begin()->first;
if (nearest < when && _ttlCheckTimer.isActive()) {
return;
}
scheduleNextTTLs();
}
void Session::scheduleNextTTLs() {
if (_ttlMessages.empty()) {
return;
}
const auto nearest = _ttlMessages.begin()->first;
const auto now = base::unixtime::now();
const auto timeout = (std::max(now, nearest) - now) * crl::time(1000);
_ttlCheckTimer.callOnce(timeout);
}
void Session::unregisterMessageTTL(
TimeId when,
not_null<HistoryItem*> item) {
Expects(when > 0);
const auto i = _ttlMessages.find(when);
if (i == end(_ttlMessages)) {
return;
}
auto &list = i->second;
list.erase(item);
if (list.empty()) {
_ttlMessages.erase(i);
}
}
void Session::checkTTLs() {
_ttlCheckTimer.cancel();
const auto now = base::unixtime::now();
while (!_ttlMessages.empty() && _ttlMessages.begin()->first <= now) {
_ttlMessages.begin()->second.front()->destroy();
}
scheduleNextTTLs();
}
void Session::processMessagesDeleted(
ChannelId channelId,
const QVector<MTPint> &data) {

View File

@ -328,6 +328,9 @@ public:
void registerMessage(not_null<HistoryItem*> item);
void unregisterMessage(not_null<HistoryItem*> item);
void registerMessageTTL(TimeId when, not_null<HistoryItem*> item);
void unregisterMessageTTL(TimeId when, not_null<HistoryItem*> item);
// Returns true if item found and it is not detached.
bool checkEntitiesAndViewsUpdate(const MTPDmessage &data);
void updateEditedMessage(const MTPMessage &data);
@ -686,6 +689,9 @@ private:
void checkSelfDestructItems();
void scheduleNextTTLs();
void checkTTLs();
int computeUnreadBadge(const Dialogs::UnreadState &state) const;
bool computeUnreadBadgeMuted(const Dialogs::UnreadState &state) const;
@ -857,6 +863,8 @@ private:
std::map<
not_null<HistoryItem*>,
base::flat_set<not_null<HistoryItem*>>> _dependentMessages;
std::map<TimeId, base::flat_set<not_null<HistoryItem*>>> _ttlMessages;
base::Timer _ttlCheckTimer;
base::flat_map<uint64, FullMsgId> _messageByRandomId;
base::flat_map<uint64, SentData> _sentMessagesData;

View File

@ -79,6 +79,9 @@ public:
[[nodiscard]] virtual bool notificationReady() const {
return true;
}
[[nodiscard]] virtual TimeId ttlDestroyAt() const {
return 0;
}
[[nodiscard]] PeerData *specialNotificationPeer() const;
[[nodiscard]] UserData *viaBot() const;

View File

@ -50,6 +50,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "styles/style_chat.h"
#include "styles/style_window.h"
#include "base/call_delayed.h" // #TODO ttl
#include "base/unixtime.h"
#include <QtGui/QGuiApplication>
#include <QtGui/QClipboard>
@ -523,6 +526,12 @@ HistoryMessage::HistoryMessage(
setGroupId(
MessageGroupId::FromRaw(history->peer->id, groupedId->v));
}
if (const auto period = data.vttl_period()) {
if (period->v > 0) {
applyTTL(data.vdate().v + period->v);
}
}
}
HistoryMessage::HistoryMessage(
@ -1352,6 +1361,12 @@ void HistoryMessage::applyEdition(const MTPDmessage &message) {
clearReplies();
}
if (const auto period = message.vttl_period(); period && period->v > 0) {
applyTTL(message.vdate().v + period->v);
} else {
applyTTL(0);
}
finishEdition(keyboardTop);
}
@ -1367,6 +1382,25 @@ void HistoryMessage::applyEdition(const MTPDmessageService &message) {
}
}
void HistoryMessage::applyTTL(TimeId destroyAt) {
const auto previousDestroyAt = std::exchange(_ttlDestroyAt, destroyAt);
if (previousDestroyAt) {
history()->owner().unregisterMessageTTL(previousDestroyAt, this);
}
if (!_ttlDestroyAt) {
return;
} else if (base::unixtime::now() >= _ttlDestroyAt) {
const auto session = &history()->session();
crl::on_main(session, [session, id = fullId()]{
if (const auto item = session->data().message(id)) {
item->destroy();
}
});
} else {
history()->owner().registerMessageTTL(_ttlDestroyAt, this);
}
}
void HistoryMessage::updateSentContent(
const TextWithEntities &textWithEntities,
const MTPMessageMedia *media) {
@ -1872,6 +1906,7 @@ std::unique_ptr<HistoryView::Element> HistoryMessage::createView(
}
HistoryMessage::~HistoryMessage() {
applyTTL(0);
_media.reset();
clearSavedMedia();
if (auto reply = Get<HistoryMessageReply>()) {

View File

@ -188,6 +188,10 @@ public:
return replyToId();
}
[[nodiscard]] TimeId ttlDestroyAt() const override {
return _ttlDestroyAt;
}
// dynamic_cast optimization.
[[nodiscard]] HistoryMessage *toHistoryMessage() override {
return this;
@ -240,6 +244,8 @@ private:
const TextWithEntities &textWithEntities) const;
void reapplyText();
void applyTTL(TimeId destroyAt);
[[nodiscard]] bool checkRepliesPts(const MTPMessageReplies &data) const;
QString _timeText;
@ -247,6 +253,8 @@ private:
mutable int32 _fromNameVersion = 0;
TimeId _ttlDestroyAt = 0;
friend class HistoryView::Element;
friend class HistoryView::Message;