1189 lines
41 KiB
C++
1189 lines
41 KiB
C++
/*
|
|
This file is part of Telegram Desktop,
|
|
the official desktop application for the Telegram messaging service.
|
|
|
|
For license and copyright information please follow this link:
|
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|
*/
|
|
#include "history/admin_log/history_admin_log_item.h"
|
|
|
|
#include "history/admin_log/history_admin_log_inner.h"
|
|
#include "history/view/history_view_element.h"
|
|
#include "history/history_location_manager.h"
|
|
#include "history/history_service.h"
|
|
#include "history/history_message.h"
|
|
#include "history/history.h"
|
|
#include "api/api_text_entities.h"
|
|
#include "data/data_channel.h"
|
|
#include "data/data_user.h"
|
|
#include "data/data_session.h"
|
|
#include "lang/lang_keys.h"
|
|
#include "ui/text/text_utilities.h"
|
|
#include "ui/basic_click_handlers.h"
|
|
#include "boxes/sticker_set_box.h"
|
|
#include "base/unixtime.h"
|
|
#include "core/application.h"
|
|
#include "mainwindow.h" // App::wnd()->sessionController
|
|
#include "main/main_session.h"
|
|
#include "facades.h"
|
|
|
|
namespace AdminLog {
|
|
namespace {
|
|
|
|
TextWithEntities PrepareText(const QString &value, const QString &emptyValue) {
|
|
auto result = TextWithEntities { TextUtilities::Clean(value) };
|
|
if (result.text.isEmpty()) {
|
|
result.text = emptyValue;
|
|
if (!emptyValue.isEmpty()) {
|
|
result.entities.push_back({
|
|
EntityType::Italic,
|
|
0,
|
|
int(emptyValue.size()) });
|
|
}
|
|
} else {
|
|
TextUtilities::ParseEntities(result, TextParseLinks | TextParseMentions | TextParseHashtags | TextParseBotCommands);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TimeId ExtractSentDate(const MTPMessage &message) {
|
|
return message.match([&](const MTPDmessageEmpty &) {
|
|
return 0;
|
|
}, [&](const MTPDmessageService &data) {
|
|
return data.vdate().v;
|
|
}, [&](const MTPDmessage &data) {
|
|
return data.vdate().v;
|
|
});
|
|
}
|
|
|
|
MTPMessage PrepareLogMessage(const MTPMessage &message, TimeId newDate) {
|
|
return message.match([&](const MTPDmessageEmpty &data) {
|
|
return MTP_messageEmpty(
|
|
data.vflags(),
|
|
data.vid(),
|
|
data.vpeer_id() ? *data.vpeer_id() : MTPPeer());
|
|
}, [&](const MTPDmessageService &data) {
|
|
const auto removeFlags = MTPDmessageService::Flag::f_out
|
|
| MTPDmessageService::Flag::f_post
|
|
| MTPDmessageService::Flag::f_reply_to
|
|
| MTPDmessageService::Flag::f_ttl_period;
|
|
return MTP_messageService(
|
|
MTP_flags(data.vflags().v & ~removeFlags),
|
|
data.vid(),
|
|
data.vfrom_id() ? *data.vfrom_id() : MTPPeer(),
|
|
data.vpeer_id(),
|
|
MTPMessageReplyHeader(),
|
|
MTP_int(newDate),
|
|
data.vaction(),
|
|
MTPint()); // ttl_period
|
|
}, [&](const MTPDmessage &data) {
|
|
const auto removeFlags = MTPDmessage::Flag::f_out
|
|
| MTPDmessage::Flag::f_post
|
|
| MTPDmessage::Flag::f_reply_to
|
|
| MTPDmessage::Flag::f_replies
|
|
| MTPDmessage::Flag::f_edit_date
|
|
| MTPDmessage::Flag::f_grouped_id
|
|
| MTPDmessage::Flag::f_views
|
|
| MTPDmessage::Flag::f_forwards
|
|
//| MTPDmessage::Flag::f_reactions
|
|
| MTPDmessage::Flag::f_restriction_reason
|
|
| MTPDmessage::Flag::f_ttl_period;
|
|
return MTP_message(
|
|
MTP_flags(data.vflags().v & ~removeFlags),
|
|
data.vid(),
|
|
data.vfrom_id() ? *data.vfrom_id() : MTPPeer(),
|
|
data.vpeer_id(),
|
|
data.vfwd_from() ? *data.vfwd_from() : MTPMessageFwdHeader(),
|
|
MTP_long(data.vvia_bot_id().value_or_empty()),
|
|
MTPMessageReplyHeader(),
|
|
MTP_int(newDate),
|
|
data.vmessage(),
|
|
data.vmedia() ? *data.vmedia() : MTPMessageMedia(),
|
|
data.vreply_markup() ? *data.vreply_markup() : MTPReplyMarkup(),
|
|
(data.ventities()
|
|
? *data.ventities()
|
|
: MTPVector<MTPMessageEntity>()),
|
|
MTP_int(data.vviews().value_or_empty()),
|
|
MTP_int(data.vforwards().value_or_empty()),
|
|
MTPMessageReplies(),
|
|
MTPint(), // edit_date
|
|
MTP_string(),
|
|
MTP_long(0), // grouped_id
|
|
//MTPMessageReactions(),
|
|
MTPVector<MTPRestrictionReason>(),
|
|
MTPint()); // ttl_period
|
|
});
|
|
}
|
|
|
|
bool MediaCanHaveCaption(const MTPMessage &message) {
|
|
if (message.type() != mtpc_message) {
|
|
return false;
|
|
}
|
|
const auto &data = message.c_message();
|
|
const auto media = data.vmedia();
|
|
const auto mediaType = media ? media->type() : mtpc_messageMediaEmpty;
|
|
return (mediaType == mtpc_messageMediaDocument || mediaType == mtpc_messageMediaPhoto);
|
|
}
|
|
|
|
TextWithEntities ExtractEditedText(
|
|
not_null<Main::Session*> session,
|
|
const MTPMessage &message) {
|
|
if (message.type() != mtpc_message) {
|
|
return TextWithEntities();
|
|
}
|
|
const auto &data = message.c_message();
|
|
return {
|
|
TextUtilities::Clean(qs(data.vmessage())),
|
|
Api::EntitiesFromMTP(session, data.ventities().value_or_empty())
|
|
};
|
|
}
|
|
|
|
const auto CollectChanges = [](auto &phraseMap, auto plusFlags, auto minusFlags) {
|
|
auto withPrefix = [&phraseMap](auto flags, QChar prefix) {
|
|
auto result = QString();
|
|
for (auto &phrase : phraseMap) {
|
|
if (flags & phrase.first) {
|
|
result.append('\n' + (prefix + phrase.second(tr::now)));
|
|
}
|
|
}
|
|
return result;
|
|
};
|
|
const auto kMinus = QChar(0x2212);
|
|
return withPrefix(plusFlags & ~minusFlags, '+') + withPrefix(minusFlags & ~plusFlags, kMinus);
|
|
};
|
|
|
|
TextWithEntities GenerateAdminChangeText(
|
|
not_null<ChannelData*> channel,
|
|
const TextWithEntities &user,
|
|
ChatAdminRightsInfo newRights,
|
|
ChatAdminRightsInfo prevRights) {
|
|
using Flag = ChatAdminRight;
|
|
using Flags = ChatAdminRights;
|
|
|
|
auto result = tr::lng_admin_log_promoted(tr::now, lt_user, user, Ui::Text::WithEntities);
|
|
|
|
const auto useInviteLinkPhrase = channel->isMegagroup()
|
|
&& channel->anyoneCanAddMembers();
|
|
const auto invitePhrase = useInviteLinkPhrase
|
|
? tr::lng_admin_log_admin_invite_link
|
|
: tr::lng_admin_log_admin_invite_users;
|
|
const auto callPhrase = channel->isBroadcast()
|
|
? tr::lng_admin_log_admin_manage_calls_channel
|
|
: tr::lng_admin_log_admin_manage_calls;
|
|
static auto phraseMap = std::map<Flags, tr::phrase<>> {
|
|
{ Flag::ChangeInfo, tr::lng_admin_log_admin_change_info },
|
|
{ Flag::PostMessages, tr::lng_admin_log_admin_post_messages },
|
|
{ Flag::EditMessages, tr::lng_admin_log_admin_edit_messages },
|
|
{ Flag::DeleteMessages, tr::lng_admin_log_admin_delete_messages },
|
|
{ Flag::BanUsers, tr::lng_admin_log_admin_ban_users },
|
|
{ Flag::InviteUsers, invitePhrase },
|
|
{ Flag::PinMessages, tr::lng_admin_log_admin_pin_messages },
|
|
{ Flag::ManageCall, tr::lng_admin_log_admin_manage_calls },
|
|
{ Flag::AddAdmins, tr::lng_admin_log_admin_add_admins },
|
|
};
|
|
phraseMap[Flag::InviteUsers] = invitePhrase;
|
|
phraseMap[Flag::ManageCall] = callPhrase;
|
|
|
|
if (!channel->isMegagroup()) {
|
|
// Don't display "Ban users" changes in channels.
|
|
newRights.flags &= ~Flag::BanUsers;
|
|
prevRights.flags &= ~Flag::BanUsers;
|
|
}
|
|
|
|
auto changes = CollectChanges(phraseMap, newRights.flags, prevRights.flags);
|
|
if (!changes.isEmpty()) {
|
|
result.text.append('\n' + changes);
|
|
}
|
|
|
|
return result;
|
|
};
|
|
|
|
QString GenerateBannedChangeText(
|
|
ChatRestrictionsInfo newRights,
|
|
ChatRestrictionsInfo prevRights) {
|
|
using Flag = ChatRestriction;
|
|
using Flags = ChatRestrictions;
|
|
|
|
static auto phraseMap = std::map<Flags, tr::phrase<>>{
|
|
{ Flag::ViewMessages, tr::lng_admin_log_banned_view_messages },
|
|
{ Flag::SendMessages, tr::lng_admin_log_banned_send_messages },
|
|
{ Flag::SendMedia, tr::lng_admin_log_banned_send_media },
|
|
{ Flag::SendStickers
|
|
| Flag::SendGifs
|
|
| Flag::SendInline
|
|
| Flag::SendGames, tr::lng_admin_log_banned_send_stickers },
|
|
{ Flag::EmbedLinks, tr::lng_admin_log_banned_embed_links },
|
|
{ Flag::SendPolls, tr::lng_admin_log_banned_send_polls },
|
|
{ Flag::ChangeInfo, tr::lng_admin_log_admin_change_info },
|
|
{ Flag::InviteUsers, tr::lng_admin_log_admin_invite_users },
|
|
{ Flag::PinMessages, tr::lng_admin_log_admin_pin_messages },
|
|
};
|
|
return CollectChanges(phraseMap, prevRights.flags, newRights.flags);
|
|
}
|
|
|
|
TextWithEntities GenerateBannedChangeText(
|
|
PeerId participantId,
|
|
const TextWithEntities &user,
|
|
ChatRestrictionsInfo newRights,
|
|
ChatRestrictionsInfo prevRights) {
|
|
using Flag = ChatRestriction;
|
|
|
|
auto newFlags = newRights.flags;
|
|
auto newUntil = newRights.until;
|
|
auto prevFlags = prevRights.flags;
|
|
auto indefinitely = ChannelData::IsRestrictedForever(newUntil);
|
|
if (newFlags & Flag::ViewMessages) {
|
|
return tr::lng_admin_log_banned(tr::now, lt_user, user, Ui::Text::WithEntities);
|
|
} else if (newFlags == 0 && (prevFlags & Flag::ViewMessages) && !peerIsUser(participantId)) {
|
|
return tr::lng_admin_log_unbanned(tr::now, lt_user, user, Ui::Text::WithEntities);
|
|
}
|
|
auto untilText = indefinitely
|
|
? tr::lng_admin_log_restricted_forever(tr::now)
|
|
: tr::lng_admin_log_restricted_until(
|
|
tr::now,
|
|
lt_date,
|
|
langDateTime(base::unixtime::parse(newUntil)));
|
|
auto result = tr::lng_admin_log_restricted(
|
|
tr::now,
|
|
lt_user,
|
|
user,
|
|
lt_until,
|
|
TextWithEntities { untilText },
|
|
Ui::Text::WithEntities);
|
|
const auto changes = GenerateBannedChangeText(newRights, prevRights);
|
|
if (!changes.isEmpty()) {
|
|
result.text.append('\n' + changes);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
QString ExtractInviteLink(const MTPExportedChatInvite &data) {
|
|
return data.match([&](const MTPDchatInviteExported &data) {
|
|
return qs(data.vlink());
|
|
});
|
|
}
|
|
|
|
QString ExtractInviteLinkLabel(const MTPExportedChatInvite &data) {
|
|
return data.match([&](const MTPDchatInviteExported &data) {
|
|
return qs(data.vtitle().value_or_empty());
|
|
});
|
|
}
|
|
|
|
QString InternalInviteLinkUrl(const MTPExportedChatInvite &data) {
|
|
const auto base64 = ExtractInviteLink(data).toUtf8().toBase64();
|
|
return "internal:show_invite_link/?link=" + QString::fromLatin1(base64);
|
|
}
|
|
|
|
QString GenerateInviteLinkText(const MTPExportedChatInvite &data) {
|
|
const auto label = ExtractInviteLinkLabel(data);
|
|
return label.isEmpty() ? ExtractInviteLink(data).replace(
|
|
qstr("https://"),
|
|
QString()
|
|
).replace(
|
|
qstr("t.me/+"),
|
|
QString()
|
|
).replace(
|
|
qstr("t.me/joinchat/"),
|
|
QString()
|
|
) : label;
|
|
}
|
|
|
|
QString GenerateInviteLinkLink(const MTPExportedChatInvite &data) {
|
|
const auto text = GenerateInviteLinkText(data);
|
|
return text.endsWith("...")
|
|
? text
|
|
: textcmdLink(InternalInviteLinkUrl(data), text);
|
|
}
|
|
|
|
TextWithEntities GenerateInviteLinkChangeText(
|
|
const MTPExportedChatInvite &newLink,
|
|
const MTPExportedChatInvite &prevLink) {
|
|
auto link = TextWithEntities{ GenerateInviteLinkText(newLink) };
|
|
if (!link.text.endsWith("...")) {
|
|
link.entities.push_back({
|
|
EntityType::CustomUrl,
|
|
0,
|
|
int(link.text.size()),
|
|
InternalInviteLinkUrl(newLink) });
|
|
}
|
|
auto result = tr::lng_admin_log_edited_invite_link(tr::now, lt_link, link, Ui::Text::WithEntities);
|
|
result.text.append('\n');
|
|
|
|
const auto label = [](const MTPExportedChatInvite &link) {
|
|
return link.match([](const MTPDchatInviteExported &data) {
|
|
return qs(data.vtitle().value_or_empty());
|
|
});
|
|
};
|
|
const auto expireDate = [](const MTPExportedChatInvite &link) {
|
|
return link.match([](const MTPDchatInviteExported &data) {
|
|
return data.vexpire_date().value_or_empty();
|
|
});
|
|
};
|
|
const auto usageLimit = [](const MTPExportedChatInvite &link) {
|
|
return link.match([](const MTPDchatInviteExported &data) {
|
|
return data.vusage_limit().value_or_empty();
|
|
});
|
|
};
|
|
const auto requestApproval = [](const MTPExportedChatInvite &link) {
|
|
return link.match([](const MTPDchatInviteExported &data) {
|
|
return data.is_request_needed();
|
|
});
|
|
};
|
|
const auto wrapDate = [](TimeId date) {
|
|
return date
|
|
? langDateTime(base::unixtime::parse(date))
|
|
: tr::lng_group_invite_expire_never(tr::now);
|
|
};
|
|
const auto wrapUsage = [](int count) {
|
|
return count
|
|
? QString::number(count)
|
|
: tr::lng_group_invite_usage_any(tr::now);
|
|
};
|
|
const auto wasLabel = label(prevLink);
|
|
const auto nowLabel = label(newLink);
|
|
const auto wasExpireDate = expireDate(prevLink);
|
|
const auto nowExpireDate = expireDate(newLink);
|
|
const auto wasUsageLimit = usageLimit(prevLink);
|
|
const auto nowUsageLimit = usageLimit(newLink);
|
|
const auto wasRequestApproval = requestApproval(prevLink);
|
|
const auto nowRequestApproval = requestApproval(newLink);
|
|
if (wasLabel != nowLabel) {
|
|
result.text.append('\n').append(tr::lng_admin_log_invite_link_label(tr::now, lt_previous, wasLabel, lt_limit, nowLabel));
|
|
}
|
|
if (wasExpireDate != nowExpireDate) {
|
|
result.text.append('\n').append(tr::lng_admin_log_invite_link_expire_date(tr::now, lt_previous, wrapDate(wasExpireDate), lt_limit, wrapDate(nowExpireDate)));
|
|
}
|
|
if (wasUsageLimit != nowUsageLimit) {
|
|
result.text.append('\n').append(tr::lng_admin_log_invite_link_usage_limit(tr::now, lt_previous, wrapUsage(wasUsageLimit), lt_limit, wrapUsage(nowUsageLimit)));
|
|
}
|
|
if (wasRequestApproval != nowRequestApproval) {
|
|
result.text.append('\n').append(nowRequestApproval ? tr::lng_admin_log_invite_link_request_needed(tr::now) : tr::lng_admin_log_invite_link_request_not_needed(tr::now));
|
|
}
|
|
|
|
result.entities.push_front(EntityInText(EntityType::Italic, 0, result.text.size()));
|
|
return result;
|
|
};
|
|
|
|
auto GenerateParticipantString(
|
|
not_null<Main::Session*> session,
|
|
PeerId participantId) {
|
|
// User name in "User name (@username)" format with entities.
|
|
auto peer = session->data().peer(participantId);
|
|
auto name = TextWithEntities { peer->name };
|
|
if (const auto user = peer->asUser()) {
|
|
auto entityData = QString::number(user->id.value)
|
|
+ '.'
|
|
+ QString::number(user->accessHash());
|
|
name.entities.push_back({
|
|
EntityType::MentionName,
|
|
0,
|
|
int(name.text.size()),
|
|
entityData });
|
|
}
|
|
auto username = peer->userName();
|
|
if (username.isEmpty()) {
|
|
return name;
|
|
}
|
|
auto mention = TextWithEntities { '@' + username };
|
|
mention.entities.push_back({
|
|
EntityType::Mention,
|
|
0,
|
|
int(mention.text.size()) });
|
|
return tr::lng_admin_log_user_with_username(
|
|
tr::now,
|
|
lt_name,
|
|
name,
|
|
lt_mention,
|
|
mention,
|
|
Ui::Text::WithEntities);
|
|
}
|
|
|
|
auto GenerateParticipantChangeTextInner(
|
|
not_null<ChannelData*> channel,
|
|
const MTPChannelParticipant &participant,
|
|
const MTPChannelParticipant *oldParticipant) {
|
|
const auto oldType = oldParticipant ? oldParticipant->type() : 0;
|
|
const auto generateOther = [&](PeerId participantId) {
|
|
auto user = GenerateParticipantString(
|
|
&channel->session(),
|
|
participantId);
|
|
if (oldType == mtpc_channelParticipantAdmin) {
|
|
return GenerateAdminChangeText(
|
|
channel,
|
|
user,
|
|
ChatAdminRightsInfo(),
|
|
ChatAdminRightsInfo(
|
|
oldParticipant->c_channelParticipantAdmin().vadmin_rights()));
|
|
} else if (oldType == mtpc_channelParticipantBanned) {
|
|
return GenerateBannedChangeText(
|
|
participantId,
|
|
user,
|
|
ChatRestrictionsInfo(),
|
|
ChatRestrictionsInfo(
|
|
oldParticipant->c_channelParticipantBanned().vbanned_rights()));
|
|
}
|
|
return tr::lng_admin_log_invited(tr::now, lt_user, user, Ui::Text::WithEntities);
|
|
};
|
|
return participant.match([&](const MTPDchannelParticipantCreator &data) {
|
|
// No valid string here :(
|
|
return tr::lng_admin_log_transferred(
|
|
tr::now,
|
|
lt_user,
|
|
GenerateParticipantString(
|
|
&channel->session(),
|
|
peerFromUser(data.vuser_id())),
|
|
Ui::Text::WithEntities);
|
|
}, [&](const MTPDchannelParticipantAdmin &data) {
|
|
const auto user = GenerateParticipantString(
|
|
&channel->session(),
|
|
peerFromUser(data.vuser_id()));
|
|
return GenerateAdminChangeText(
|
|
channel,
|
|
user,
|
|
ChatAdminRightsInfo(data.vadmin_rights()),
|
|
(oldType == mtpc_channelParticipantAdmin
|
|
? ChatAdminRightsInfo(
|
|
oldParticipant->c_channelParticipantAdmin().vadmin_rights())
|
|
: ChatAdminRightsInfo()));
|
|
}, [&](const MTPDchannelParticipantBanned &data) {
|
|
const auto participantId = peerFromMTP(data.vpeer());
|
|
const auto user = GenerateParticipantString(
|
|
&channel->session(),
|
|
participantId);
|
|
return GenerateBannedChangeText(
|
|
participantId,
|
|
user,
|
|
ChatRestrictionsInfo(data.vbanned_rights()),
|
|
(oldType == mtpc_channelParticipantBanned
|
|
? ChatRestrictionsInfo(
|
|
oldParticipant->c_channelParticipantBanned().vbanned_rights())
|
|
: ChatRestrictionsInfo()));
|
|
}, [&](const MTPDchannelParticipantLeft &data) {
|
|
return generateOther(peerFromMTP(data.vpeer()));
|
|
}, [&](const auto &data) {
|
|
return generateOther(peerFromUser(data.vuser_id()));
|
|
});
|
|
}
|
|
|
|
TextWithEntities GenerateParticipantChangeText(not_null<ChannelData*> channel, const MTPChannelParticipant &participant, const MTPChannelParticipant *oldParticipant = nullptr) {
|
|
auto result = GenerateParticipantChangeTextInner(channel, participant, oldParticipant);
|
|
result.entities.push_front(EntityInText(EntityType::Italic, 0, result.text.size()));
|
|
return result;
|
|
}
|
|
|
|
TextWithEntities GenerateDefaultBannedRightsChangeText(not_null<ChannelData*> channel, ChatRestrictionsInfo rights, ChatRestrictionsInfo oldRights) {
|
|
auto result = TextWithEntities{ tr::lng_admin_log_changed_default_permissions(tr::now) };
|
|
const auto changes = GenerateBannedChangeText(rights, oldRights);
|
|
if (!changes.isEmpty()) {
|
|
result.text.append('\n' + changes);
|
|
}
|
|
result.entities.push_front(EntityInText(EntityType::Italic, 0, result.text.size()));
|
|
return result;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
OwnedItem::OwnedItem(std::nullptr_t) {
|
|
}
|
|
|
|
OwnedItem::OwnedItem(
|
|
not_null<HistoryView::ElementDelegate*> delegate,
|
|
not_null<HistoryItem*> data)
|
|
: _data(data)
|
|
, _view(_data->createView(delegate)) {
|
|
}
|
|
|
|
OwnedItem::OwnedItem(OwnedItem &&other)
|
|
: _data(base::take(other._data))
|
|
, _view(base::take(other._view)) {
|
|
}
|
|
|
|
OwnedItem &OwnedItem::operator=(OwnedItem &&other) {
|
|
_data = base::take(other._data);
|
|
_view = base::take(other._view);
|
|
return *this;
|
|
}
|
|
|
|
OwnedItem::~OwnedItem() {
|
|
clearView();
|
|
if (_data) {
|
|
_data->destroy();
|
|
}
|
|
}
|
|
|
|
void OwnedItem::refreshView(
|
|
not_null<HistoryView::ElementDelegate*> delegate) {
|
|
_view = _data->createView(delegate);
|
|
}
|
|
|
|
void OwnedItem::clearView() {
|
|
_view = nullptr;
|
|
}
|
|
|
|
void GenerateItems(
|
|
not_null<HistoryView::ElementDelegate*> delegate,
|
|
not_null<History*> history,
|
|
const MTPDchannelAdminLogEvent &event,
|
|
Fn<void(OwnedItem item, TimeId sentDate)> callback) {
|
|
Expects(history->peer->isChannel());
|
|
|
|
const auto session = &history->session();
|
|
const auto id = event.vid().v;
|
|
const auto from = history->owner().user(event.vuser_id().v);
|
|
const auto channel = history->peer->asChannel();
|
|
const auto broadcast = channel->isBroadcast();
|
|
const auto &action = event.vaction();
|
|
const auto date = event.vdate().v;
|
|
const auto addPart = [&](
|
|
not_null<HistoryItem*> item,
|
|
TimeId sentDate = 0) {
|
|
return callback(OwnedItem(delegate, item), sentDate);
|
|
};
|
|
|
|
const auto fromName = from->name;
|
|
const auto fromLink = from->createOpenLink();
|
|
const auto fromLinkText = textcmdLink(1, fromName);
|
|
|
|
auto addSimpleServiceMessage = [&](const QString &text, PhotoData *photo = nullptr) {
|
|
auto message = HistoryService::PreparedText { text };
|
|
message.links.push_back(fromLink);
|
|
addPart(history->makeServiceMessage(
|
|
history->nextNonHistoryEntryId(),
|
|
MessageFlag::AdminLogEntry,
|
|
date,
|
|
message,
|
|
peerToUser(from->id),
|
|
photo));
|
|
};
|
|
|
|
auto createChangeTitle = [&](const MTPDchannelAdminLogEventActionChangeTitle &action) {
|
|
auto text = (channel->isMegagroup()
|
|
? tr::lng_action_changed_title
|
|
: tr::lng_admin_log_changed_title_channel)(
|
|
tr::now,
|
|
lt_from,
|
|
fromLinkText,
|
|
lt_title,
|
|
qs(action.vnew_value()));
|
|
addSimpleServiceMessage(text);
|
|
};
|
|
|
|
auto makeSimpleTextMessage = [&](TextWithEntities &&text) {
|
|
auto bodyFlags = MessageFlag::HasFromId | MessageFlag::AdminLogEntry;
|
|
auto bodyReplyTo = MsgId();
|
|
auto bodyViaBotId = UserId();
|
|
auto bodyGroupedId = uint64();
|
|
return history->makeMessage(
|
|
history->nextNonHistoryEntryId(),
|
|
bodyFlags,
|
|
bodyReplyTo,
|
|
bodyViaBotId,
|
|
date,
|
|
peerToUser(from->id),
|
|
QString(),
|
|
std::move(text),
|
|
MTP_messageMediaEmpty(),
|
|
HistoryMessageMarkupData(),
|
|
bodyGroupedId);
|
|
};
|
|
|
|
auto addSimpleTextMessage = [&](TextWithEntities &&text) {
|
|
addPart(makeSimpleTextMessage(std::move(text)));
|
|
};
|
|
|
|
auto createChangeAbout = [&](const MTPDchannelAdminLogEventActionChangeAbout &action) {
|
|
auto newValue = qs(action.vnew_value());
|
|
auto oldValue = qs(action.vprev_value());
|
|
auto text = (channel->isMegagroup()
|
|
? (newValue.isEmpty()
|
|
? tr::lng_admin_log_removed_description_group
|
|
: tr::lng_admin_log_changed_description_group)
|
|
: (newValue.isEmpty()
|
|
? tr::lng_admin_log_removed_description_channel
|
|
: tr::lng_admin_log_changed_description_channel)
|
|
)(tr::now, lt_from, fromLinkText);
|
|
addSimpleServiceMessage(text);
|
|
|
|
auto newDescription = PrepareText(newValue, QString());
|
|
auto body = makeSimpleTextMessage(PrepareText(newValue, QString()));
|
|
if (!oldValue.isEmpty()) {
|
|
auto oldDescription = PrepareText(oldValue, QString());
|
|
body->addLogEntryOriginal(id, tr::lng_admin_log_previous_description(tr::now), oldDescription);
|
|
}
|
|
addPart(body);
|
|
};
|
|
|
|
auto createChangeUsername = [&](const MTPDchannelAdminLogEventActionChangeUsername &action) {
|
|
auto newValue = qs(action.vnew_value());
|
|
auto oldValue = qs(action.vprev_value());
|
|
auto text = (channel->isMegagroup()
|
|
? (newValue.isEmpty()
|
|
? tr::lng_admin_log_removed_link_group
|
|
: tr::lng_admin_log_changed_link_group)
|
|
: (newValue.isEmpty()
|
|
? tr::lng_admin_log_removed_link_channel
|
|
: tr::lng_admin_log_changed_link_channel)
|
|
)(tr::now, lt_from, fromLinkText);
|
|
addSimpleServiceMessage(text);
|
|
|
|
auto newLink = newValue.isEmpty()
|
|
? TextWithEntities()
|
|
: PrepareText(
|
|
history->session().createInternalLinkFull(newValue),
|
|
QString());
|
|
auto body = makeSimpleTextMessage(newValue.isEmpty()
|
|
? TextWithEntities()
|
|
: PrepareText(
|
|
history->session().createInternalLinkFull(newValue),
|
|
QString()));
|
|
if (!oldValue.isEmpty()) {
|
|
auto oldLink = PrepareText(
|
|
history->session().createInternalLinkFull(oldValue),
|
|
QString());
|
|
body->addLogEntryOriginal(id, tr::lng_admin_log_previous_link(tr::now), oldLink);
|
|
}
|
|
addPart(body);
|
|
};
|
|
|
|
auto createChangePhoto = [&](const MTPDchannelAdminLogEventActionChangePhoto &action) {
|
|
action.vnew_photo().match([&](const MTPDphoto &data) {
|
|
auto photo = history->owner().processPhoto(data);
|
|
auto text = (channel->isMegagroup()
|
|
? tr::lng_admin_log_changed_photo_group
|
|
: tr::lng_admin_log_changed_photo_channel)(
|
|
tr::now,
|
|
lt_from,
|
|
fromLinkText);
|
|
addSimpleServiceMessage(text, photo);
|
|
}, [&](const MTPDphotoEmpty &data) {
|
|
auto text = (channel->isMegagroup()
|
|
? tr::lng_admin_log_removed_photo_group
|
|
: tr::lng_admin_log_removed_photo_channel)(
|
|
tr::now,
|
|
lt_from,
|
|
fromLinkText);
|
|
addSimpleServiceMessage(text);
|
|
});
|
|
};
|
|
|
|
auto createToggleInvites = [&](const MTPDchannelAdminLogEventActionToggleInvites &action) {
|
|
auto enabled = (action.vnew_value().type() == mtpc_boolTrue);
|
|
auto text = (enabled
|
|
? tr::lng_admin_log_invites_enabled
|
|
: tr::lng_admin_log_invites_disabled);
|
|
addSimpleServiceMessage(text(tr::now, lt_from, fromLinkText));
|
|
};
|
|
|
|
auto createToggleSignatures = [&](const MTPDchannelAdminLogEventActionToggleSignatures &action) {
|
|
auto enabled = (action.vnew_value().type() == mtpc_boolTrue);
|
|
auto text = (enabled
|
|
? tr::lng_admin_log_signatures_enabled
|
|
: tr::lng_admin_log_signatures_disabled);
|
|
addSimpleServiceMessage(text(tr::now, lt_from, fromLinkText));
|
|
};
|
|
|
|
auto createUpdatePinned = [&](const MTPDchannelAdminLogEventActionUpdatePinned &action) {
|
|
action.vmessage().match([&](const MTPDmessage &data) {
|
|
const auto pinned = data.is_pinned();
|
|
auto text = (pinned
|
|
? tr::lng_admin_log_pinned_message
|
|
: tr::lng_admin_log_unpinned_message)(tr::now, lt_from, fromLinkText);
|
|
addSimpleServiceMessage(text);
|
|
|
|
auto detachExistingItem = false;
|
|
addPart(
|
|
history->createItem(
|
|
history->nextNonHistoryEntryId(),
|
|
PrepareLogMessage(action.vmessage(), date),
|
|
MessageFlag::AdminLogEntry,
|
|
detachExistingItem),
|
|
ExtractSentDate(action.vmessage()));
|
|
}, [&](const auto &) {
|
|
auto text = tr::lng_admin_log_unpinned_message(tr::now, lt_from, fromLinkText);
|
|
addSimpleServiceMessage(text);
|
|
});
|
|
};
|
|
|
|
auto createEditMessage = [&](const MTPDchannelAdminLogEventActionEditMessage &action) {
|
|
auto newValue = ExtractEditedText(session, action.vnew_message());
|
|
auto canHaveCaption = MediaCanHaveCaption(action.vnew_message());
|
|
auto text = (!canHaveCaption
|
|
? tr::lng_admin_log_edited_message
|
|
: newValue.text.isEmpty()
|
|
? tr::lng_admin_log_removed_caption
|
|
: tr::lng_admin_log_edited_caption)(
|
|
tr::now,
|
|
lt_from,
|
|
fromLinkText);
|
|
addSimpleServiceMessage(text);
|
|
|
|
auto oldValue = ExtractEditedText(session, action.vprev_message());
|
|
auto detachExistingItem = false;
|
|
auto body = history->createItem(
|
|
history->nextNonHistoryEntryId(),
|
|
PrepareLogMessage(action.vnew_message(), date),
|
|
MessageFlag::AdminLogEntry,
|
|
detachExistingItem);
|
|
if (oldValue.text.isEmpty()) {
|
|
oldValue = PrepareText(QString(), tr::lng_admin_log_empty_text(tr::now));
|
|
}
|
|
|
|
body->addLogEntryOriginal(
|
|
id,
|
|
(canHaveCaption
|
|
? tr::lng_admin_log_previous_caption
|
|
: tr::lng_admin_log_previous_message)(tr::now),
|
|
oldValue);
|
|
addPart(body);
|
|
};
|
|
|
|
auto createDeleteMessage = [&](const MTPDchannelAdminLogEventActionDeleteMessage &action) {
|
|
auto text = tr::lng_admin_log_deleted_message(tr::now, lt_from, fromLinkText);
|
|
addSimpleServiceMessage(text);
|
|
|
|
auto detachExistingItem = false;
|
|
addPart(
|
|
history->createItem(
|
|
history->nextNonHistoryEntryId(),
|
|
PrepareLogMessage(action.vmessage(), date),
|
|
MessageFlag::AdminLogEntry,
|
|
detachExistingItem),
|
|
ExtractSentDate(action.vmessage()));
|
|
};
|
|
|
|
auto createParticipantJoin = [&]() {
|
|
auto text = (channel->isMegagroup()
|
|
? tr::lng_admin_log_participant_joined
|
|
: tr::lng_admin_log_participant_joined_channel);
|
|
addSimpleServiceMessage(text(tr::now, lt_from, fromLinkText));
|
|
};
|
|
|
|
auto createParticipantLeave = [&]() {
|
|
auto text = (channel->isMegagroup()
|
|
? tr::lng_admin_log_participant_left
|
|
: tr::lng_admin_log_participant_left_channel);
|
|
addSimpleServiceMessage(text(tr::now, lt_from, fromLinkText));
|
|
};
|
|
|
|
auto createParticipantInvite = [&](const MTPDchannelAdminLogEventActionParticipantInvite &action) {
|
|
addSimpleTextMessage(
|
|
GenerateParticipantChangeText(channel, action.vparticipant()));
|
|
};
|
|
|
|
auto createParticipantToggleBan = [&](const MTPDchannelAdminLogEventActionParticipantToggleBan &action) {
|
|
addSimpleTextMessage(
|
|
GenerateParticipantChangeText(channel, action.vnew_participant(), &action.vprev_participant()));
|
|
};
|
|
|
|
auto createParticipantToggleAdmin = [&](const MTPDchannelAdminLogEventActionParticipantToggleAdmin &action) {
|
|
if (action.vnew_participant().type() == mtpc_channelParticipantAdmin
|
|
&& action.vprev_participant().type() == mtpc_channelParticipantCreator) {
|
|
// In case of ownership transfer we show that message in
|
|
// the "User > Creator" part and skip the "Creator > Admin" part.
|
|
return;
|
|
}
|
|
addSimpleTextMessage(
|
|
GenerateParticipantChangeText(channel, action.vnew_participant(), &action.vprev_participant()));
|
|
};
|
|
|
|
auto createChangeStickerSet = [&](const MTPDchannelAdminLogEventActionChangeStickerSet &action) {
|
|
auto set = action.vnew_stickerset();
|
|
auto removed = (set.type() == mtpc_inputStickerSetEmpty);
|
|
if (removed) {
|
|
auto text = tr::lng_admin_log_removed_stickers_group(tr::now, lt_from, fromLinkText);
|
|
addSimpleServiceMessage(text);
|
|
} else {
|
|
auto text = tr::lng_admin_log_changed_stickers_group(
|
|
tr::now,
|
|
lt_from,
|
|
fromLinkText,
|
|
lt_sticker_set,
|
|
textcmdLink(2, tr::lng_admin_log_changed_stickers_set(tr::now)));
|
|
auto setLink = std::make_shared<LambdaClickHandler>([set] {
|
|
Ui::show(Box<StickerSetBox>(
|
|
App::wnd()->sessionController(),
|
|
Data::FromInputSet(set)));
|
|
});
|
|
auto message = HistoryService::PreparedText { text };
|
|
message.links.push_back(fromLink);
|
|
message.links.push_back(setLink);
|
|
addPart(history->makeServiceMessage(
|
|
history->nextNonHistoryEntryId(),
|
|
MessageFlag::AdminLogEntry,
|
|
date,
|
|
message,
|
|
peerToUser(from->id)));
|
|
}
|
|
};
|
|
|
|
auto createTogglePreHistoryHidden = [&](const MTPDchannelAdminLogEventActionTogglePreHistoryHidden &action) {
|
|
auto hidden = (action.vnew_value().type() == mtpc_boolTrue);
|
|
auto text = (hidden
|
|
? tr::lng_admin_log_history_made_hidden
|
|
: tr::lng_admin_log_history_made_visible);
|
|
addSimpleServiceMessage(text(tr::now, lt_from, fromLinkText));
|
|
};
|
|
|
|
auto createDefaultBannedRights = [&](const MTPDchannelAdminLogEventActionDefaultBannedRights &action) {
|
|
addSimpleTextMessage(
|
|
GenerateDefaultBannedRightsChangeText(
|
|
channel,
|
|
ChatRestrictionsInfo(action.vnew_banned_rights()),
|
|
ChatRestrictionsInfo(action.vprev_banned_rights())));
|
|
};
|
|
|
|
auto createStopPoll = [&](const MTPDchannelAdminLogEventActionStopPoll &action) {
|
|
auto text = tr::lng_admin_log_stopped_poll(tr::now, lt_from, fromLinkText);
|
|
addSimpleServiceMessage(text);
|
|
|
|
auto detachExistingItem = false;
|
|
addPart(
|
|
history->createItem(
|
|
history->nextNonHistoryEntryId(),
|
|
PrepareLogMessage(action.vmessage(), date),
|
|
MessageFlag::AdminLogEntry,
|
|
detachExistingItem),
|
|
ExtractSentDate(action.vmessage()));
|
|
};
|
|
|
|
auto createChangeLinkedChat = [&](const MTPDchannelAdminLogEventActionChangeLinkedChat &action) {
|
|
const auto now = history->owner().channelLoaded(action.vnew_value().v);
|
|
if (!now) {
|
|
auto text = (broadcast
|
|
? tr::lng_admin_log_removed_linked_chat
|
|
: tr::lng_admin_log_removed_linked_channel)(
|
|
tr::now,
|
|
lt_from,
|
|
fromLinkText);
|
|
addSimpleServiceMessage(text);
|
|
} else {
|
|
auto text = (broadcast
|
|
? tr::lng_admin_log_changed_linked_chat
|
|
: tr::lng_admin_log_changed_linked_channel)(
|
|
tr::now,
|
|
lt_from,
|
|
fromLinkText,
|
|
lt_chat,
|
|
textcmdLink(2, now->name));
|
|
auto chatLink = std::make_shared<LambdaClickHandler>([=] {
|
|
Ui::showPeerHistory(now, ShowAtUnreadMsgId);
|
|
});
|
|
auto message = HistoryService::PreparedText{ text };
|
|
message.links.push_back(fromLink);
|
|
message.links.push_back(chatLink);
|
|
addPart(history->makeServiceMessage(
|
|
history->nextNonHistoryEntryId(),
|
|
MessageFlag::AdminLogEntry,
|
|
date,
|
|
message,
|
|
peerToUser(from->id)));
|
|
}
|
|
};
|
|
|
|
auto createChangeLocation = [&](const MTPDchannelAdminLogEventActionChangeLocation &action) {
|
|
action.vnew_value().match([&](const MTPDchannelLocation &data) {
|
|
const auto address = qs(data.vaddress());
|
|
const auto link = data.vgeo_point().match([&](const MTPDgeoPoint &data) {
|
|
return textcmdLink(
|
|
LocationClickHandler::Url(Data::LocationPoint(data)),
|
|
address);
|
|
}, [&](const MTPDgeoPointEmpty &) {
|
|
return address;
|
|
});
|
|
const auto text = tr::lng_admin_log_changed_location_chat(
|
|
tr::now,
|
|
lt_from,
|
|
fromLinkText,
|
|
lt_address,
|
|
link);
|
|
addSimpleServiceMessage(text);
|
|
}, [&](const MTPDchannelLocationEmpty &) {
|
|
const auto text = tr::lng_admin_log_removed_location_chat(tr::now, lt_from, fromLinkText);
|
|
addSimpleServiceMessage(text);
|
|
});
|
|
};
|
|
|
|
auto createToggleSlowMode = [&](const MTPDchannelAdminLogEventActionToggleSlowMode &action) {
|
|
if (const auto seconds = action.vnew_value().v) {
|
|
const auto duration = (seconds >= 60)
|
|
? tr::lng_admin_log_slow_mode_minutes(tr::now, lt_count, seconds / 60)
|
|
: tr::lng_admin_log_slow_mode_seconds(tr::now, lt_count, seconds);
|
|
const auto text = tr::lng_admin_log_changed_slow_mode(
|
|
tr::now,
|
|
lt_from,
|
|
fromLinkText,
|
|
lt_duration,
|
|
duration);
|
|
addSimpleServiceMessage(text);
|
|
} else {
|
|
const auto text = tr::lng_admin_log_removed_slow_mode(tr::now, lt_from, fromLinkText);
|
|
addSimpleServiceMessage(text);
|
|
}
|
|
};
|
|
|
|
auto createStartGroupCall = [&](const MTPDchannelAdminLogEventActionStartGroupCall &data) {
|
|
const auto text = (broadcast
|
|
? tr::lng_admin_log_started_group_call_channel
|
|
: tr::lng_admin_log_started_group_call)(tr::now, lt_from, fromLinkText);
|
|
addSimpleServiceMessage(text);
|
|
};
|
|
|
|
auto createDiscardGroupCall = [&](const MTPDchannelAdminLogEventActionDiscardGroupCall &data) {
|
|
const auto text = (broadcast
|
|
? tr::lng_admin_log_discarded_group_call_channel
|
|
: tr::lng_admin_log_discarded_group_call)(tr::now, lt_from, fromLinkText);
|
|
addSimpleServiceMessage(text);
|
|
};
|
|
|
|
auto groupCallParticipantPeer = [&](const MTPGroupCallParticipant &data) {
|
|
return data.match([&](const MTPDgroupCallParticipant &data) {
|
|
return history->owner().peer(peerFromMTP(data.vpeer()));
|
|
});
|
|
};
|
|
|
|
auto addServiceMessageWithLink = [&](const QString &text, const ClickHandlerPtr &link) {
|
|
auto message = HistoryService::PreparedText{ text };
|
|
message.links.push_back(fromLink);
|
|
message.links.push_back(link);
|
|
addPart(history->makeServiceMessage(
|
|
history->nextNonHistoryEntryId(),
|
|
MessageFlag::AdminLogEntry,
|
|
date,
|
|
message,
|
|
peerToUser(from->id)));
|
|
};
|
|
|
|
auto createParticipantMute = [&](const MTPDchannelAdminLogEventActionParticipantMute &data) {
|
|
const auto participantPeer = groupCallParticipantPeer(data.vparticipant());
|
|
const auto participantPeerLink = participantPeer->createOpenLink();
|
|
const auto participantPeerLinkText = textcmdLink(2, participantPeer->name);
|
|
auto text = (broadcast
|
|
? tr::lng_admin_log_muted_participant_channel
|
|
: tr::lng_admin_log_muted_participant)(
|
|
tr::now,
|
|
lt_from,
|
|
fromLinkText,
|
|
lt_user,
|
|
participantPeerLinkText);
|
|
addServiceMessageWithLink(text, participantPeerLink);
|
|
};
|
|
|
|
auto createParticipantUnmute = [&](const MTPDchannelAdminLogEventActionParticipantUnmute &data) {
|
|
const auto participantPeer = groupCallParticipantPeer(data.vparticipant());
|
|
const auto participantPeerLink = participantPeer->createOpenLink();
|
|
const auto participantPeerLinkText = textcmdLink(2, participantPeer->name);
|
|
auto text = (broadcast
|
|
? tr::lng_admin_log_unmuted_participant_channel
|
|
: tr::lng_admin_log_unmuted_participant)(
|
|
tr::now,
|
|
lt_from,
|
|
fromLinkText,
|
|
lt_user,
|
|
participantPeerLinkText);
|
|
addServiceMessageWithLink(text, participantPeerLink);
|
|
};
|
|
|
|
auto createToggleGroupCallSetting = [&](const MTPDchannelAdminLogEventActionToggleGroupCallSetting &data) {
|
|
const auto text = (mtpIsTrue(data.vjoin_muted())
|
|
? (broadcast
|
|
? tr::lng_admin_log_disallowed_unmute_self_channel
|
|
: tr::lng_admin_log_disallowed_unmute_self)
|
|
: (broadcast
|
|
? tr::lng_admin_log_allowed_unmute_self_channel
|
|
: tr::lng_admin_log_allowed_unmute_self))(tr::now, lt_from, fromLinkText);
|
|
addSimpleServiceMessage(text);
|
|
};
|
|
|
|
auto addInviteLinkServiceMessage = [&](const QString &text, const MTPExportedChatInvite &data, ClickHandlerPtr additional = nullptr) {
|
|
auto message = HistoryService::PreparedText{ text };
|
|
message.links.push_back(fromLink);
|
|
if (!ExtractInviteLink(data).endsWith("...")) {
|
|
message.links.push_back(std::make_shared<UrlClickHandler>(InternalInviteLinkUrl(data)));
|
|
}
|
|
if (additional) {
|
|
message.links.push_back(std::move(additional));
|
|
}
|
|
addPart(history->makeServiceMessage(
|
|
history->nextNonHistoryEntryId(),
|
|
MessageFlag::AdminLogEntry,
|
|
date,
|
|
message,
|
|
peerToUser(from->id),
|
|
nullptr));
|
|
};
|
|
|
|
auto createParticipantJoinByInvite = [&](const MTPDchannelAdminLogEventActionParticipantJoinByInvite &data) {
|
|
auto text = (channel->isMegagroup()
|
|
? tr::lng_admin_log_participant_joined_by_link
|
|
: tr::lng_admin_log_participant_joined_by_link_channel);
|
|
addInviteLinkServiceMessage(
|
|
text(
|
|
tr::now,
|
|
lt_from,
|
|
fromLinkText,
|
|
lt_link,
|
|
GenerateInviteLinkLink(data.vinvite())),
|
|
data.vinvite());
|
|
};
|
|
|
|
auto createExportedInviteDelete = [&](const MTPDchannelAdminLogEventActionExportedInviteDelete &data) {
|
|
addInviteLinkServiceMessage(
|
|
tr::lng_admin_log_delete_invite_link(
|
|
tr::now,
|
|
lt_from,
|
|
fromLinkText,
|
|
lt_link,
|
|
GenerateInviteLinkLink(data.vinvite())),
|
|
data.vinvite());
|
|
};
|
|
|
|
auto createExportedInviteRevoke = [&](const MTPDchannelAdminLogEventActionExportedInviteRevoke &data) {
|
|
addInviteLinkServiceMessage(
|
|
tr::lng_admin_log_revoke_invite_link(
|
|
tr::now,
|
|
lt_from,
|
|
fromLinkText,
|
|
lt_link,
|
|
GenerateInviteLinkLink(data.vinvite())),
|
|
data.vinvite());
|
|
};
|
|
|
|
auto createExportedInviteEdit = [&](const MTPDchannelAdminLogEventActionExportedInviteEdit &data) {
|
|
addSimpleTextMessage(
|
|
GenerateInviteLinkChangeText(data.vnew_invite(), data.vprev_invite()));
|
|
};
|
|
|
|
auto createParticipantVolume = [&](const MTPDchannelAdminLogEventActionParticipantVolume &data) {
|
|
const auto participantPeer = groupCallParticipantPeer(data.vparticipant());
|
|
const auto participantPeerLink = participantPeer->createOpenLink();
|
|
const auto participantPeerLinkText = textcmdLink(2, participantPeer->name);
|
|
const auto volume = data.vparticipant().match([&](
|
|
const MTPDgroupCallParticipant &data) {
|
|
return data.vvolume().value_or(10000);
|
|
});
|
|
const auto volumeText = QString::number(volume / 100) + '%';
|
|
auto text = (broadcast
|
|
? tr::lng_admin_log_participant_volume_channel
|
|
: tr::lng_admin_log_participant_volume)(
|
|
tr::now,
|
|
lt_from,
|
|
fromLinkText,
|
|
lt_user,
|
|
participantPeerLinkText,
|
|
lt_percent,
|
|
volumeText);
|
|
addServiceMessageWithLink(text, participantPeerLink);
|
|
};
|
|
|
|
auto createChangeHistoryTTL = [&](const MTPDchannelAdminLogEventActionChangeHistoryTTL &data) {
|
|
const auto was = data.vprev_value().v;
|
|
const auto now = data.vnew_value().v;
|
|
const auto wrap = [](int duration) {
|
|
return (duration == 5)
|
|
? u"5 seconds"_q
|
|
: (duration < 2 * 86400)
|
|
? tr::lng_manage_messages_ttl_after1(tr::now)
|
|
: (duration < 8 * 86400)
|
|
? tr::lng_manage_messages_ttl_after2(tr::now)
|
|
: tr::lng_manage_messages_ttl_after3(tr::now);
|
|
};
|
|
auto text = !was
|
|
? tr::lng_admin_log_messages_ttl_set(tr::now, lt_from, fromLinkText, lt_duration, wrap(now))
|
|
: !now
|
|
? tr::lng_admin_log_messages_ttl_removed(tr::now, lt_from, fromLinkText, lt_duration, wrap(was))
|
|
: tr::lng_admin_log_messages_ttl_changed(tr::now, lt_from, fromLinkText, lt_previous, wrap(was), lt_duration, wrap(now));
|
|
addSimpleServiceMessage(text);
|
|
};
|
|
|
|
auto createParticipantJoinByRequest = [&](const MTPDchannelAdminLogEventActionParticipantJoinByRequest &data) {
|
|
const auto user = channel->owner().user(UserId(data.vapproved_by()));
|
|
auto text = (channel->isMegagroup()
|
|
? tr::lng_admin_log_participant_approved_by_link
|
|
: tr::lng_admin_log_participant_approved_by_link_channel);
|
|
const auto linkText = GenerateInviteLinkLink(data.vinvite());
|
|
const auto adminIndex = linkText.endsWith("...") ? 2 : 3;
|
|
addInviteLinkServiceMessage(
|
|
text(
|
|
tr::now,
|
|
lt_from,
|
|
fromLinkText,
|
|
lt_link,
|
|
linkText,
|
|
lt_user,
|
|
textcmdLink(adminIndex, user->name)),
|
|
data.vinvite(),
|
|
user->createOpenLink());
|
|
|
|
};
|
|
|
|
action.match([&](const MTPDchannelAdminLogEventActionChangeTitle &data) {
|
|
createChangeTitle(data);
|
|
}, [&](const MTPDchannelAdminLogEventActionChangeAbout &data) {
|
|
createChangeAbout(data);
|
|
}, [&](const MTPDchannelAdminLogEventActionChangeUsername &data) {
|
|
createChangeUsername(data);
|
|
}, [&](const MTPDchannelAdminLogEventActionChangePhoto &data) {
|
|
createChangePhoto(data);
|
|
}, [&](const MTPDchannelAdminLogEventActionToggleInvites &data) {
|
|
createToggleInvites(data);
|
|
}, [&](const MTPDchannelAdminLogEventActionToggleSignatures &data) {
|
|
createToggleSignatures(data);
|
|
}, [&](const MTPDchannelAdminLogEventActionUpdatePinned &data) {
|
|
createUpdatePinned(data);
|
|
}, [&](const MTPDchannelAdminLogEventActionEditMessage &data) {
|
|
createEditMessage(data);
|
|
}, [&](const MTPDchannelAdminLogEventActionDeleteMessage &data) {
|
|
createDeleteMessage(data);
|
|
}, [&](const MTPDchannelAdminLogEventActionParticipantJoin &) {
|
|
createParticipantJoin();
|
|
}, [&](const MTPDchannelAdminLogEventActionParticipantLeave &) {
|
|
createParticipantLeave();
|
|
}, [&](const MTPDchannelAdminLogEventActionParticipantInvite &data) {
|
|
createParticipantInvite(data);
|
|
}, [&](const MTPDchannelAdminLogEventActionParticipantToggleBan &data) {
|
|
createParticipantToggleBan(data);
|
|
}, [&](const MTPDchannelAdminLogEventActionParticipantToggleAdmin &data) {
|
|
createParticipantToggleAdmin(data);
|
|
}, [&](const MTPDchannelAdminLogEventActionChangeStickerSet &data) {
|
|
createChangeStickerSet(data);
|
|
}, [&](const MTPDchannelAdminLogEventActionTogglePreHistoryHidden &data) {
|
|
createTogglePreHistoryHidden(data);
|
|
}, [&](const MTPDchannelAdminLogEventActionDefaultBannedRights &data) {
|
|
createDefaultBannedRights(data);
|
|
}, [&](const MTPDchannelAdminLogEventActionStopPoll &data) {
|
|
createStopPoll(data);
|
|
}, [&](const MTPDchannelAdminLogEventActionChangeLinkedChat &data) {
|
|
createChangeLinkedChat(data);
|
|
}, [&](const MTPDchannelAdminLogEventActionChangeLocation &data) {
|
|
createChangeLocation(data);
|
|
}, [&](const MTPDchannelAdminLogEventActionToggleSlowMode &data) {
|
|
createToggleSlowMode(data);
|
|
}, [&](const MTPDchannelAdminLogEventActionStartGroupCall &data) {
|
|
createStartGroupCall(data);
|
|
}, [&](const MTPDchannelAdminLogEventActionDiscardGroupCall &data) {
|
|
createDiscardGroupCall(data);
|
|
}, [&](const MTPDchannelAdminLogEventActionParticipantMute &data) {
|
|
createParticipantMute(data);
|
|
}, [&](const MTPDchannelAdminLogEventActionParticipantUnmute &data) {
|
|
createParticipantUnmute(data);
|
|
}, [&](const MTPDchannelAdminLogEventActionToggleGroupCallSetting &data) {
|
|
createToggleGroupCallSetting(data);
|
|
}, [&](const MTPDchannelAdminLogEventActionParticipantJoinByInvite &data) {
|
|
createParticipantJoinByInvite(data);
|
|
}, [&](const MTPDchannelAdminLogEventActionExportedInviteDelete &data) {
|
|
createExportedInviteDelete(data);
|
|
}, [&](const MTPDchannelAdminLogEventActionExportedInviteRevoke &data) {
|
|
createExportedInviteRevoke(data);
|
|
}, [&](const MTPDchannelAdminLogEventActionExportedInviteEdit &data) {
|
|
createExportedInviteEdit(data);
|
|
}, [&](const MTPDchannelAdminLogEventActionParticipantVolume &data) {
|
|
createParticipantVolume(data);
|
|
}, [&](const MTPDchannelAdminLogEventActionChangeHistoryTTL &data) {
|
|
createChangeHistoryTTL(data);
|
|
}, [&](const MTPDchannelAdminLogEventActionParticipantJoinByRequest &data) {
|
|
createParticipantJoinByRequest(data);
|
|
});
|
|
}
|
|
|
|
} // namespace AdminLog
|