Add admin log events about links, volumes, ttl.

This commit is contained in:
John Preston 2021-02-09 21:52:20 +04:00
parent 7a5dc72f86
commit c1fde61e03
4 changed files with 271 additions and 47 deletions

View file

@ -2134,6 +2134,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_admin_log_deleted_message" = "{from} deleted message:";
"lng_admin_log_participant_joined" = "{from} joined the group";
"lng_admin_log_participant_joined_channel" = "{from} joined the channel";
"lng_admin_log_participant_joined_by_link" = "{from} joined the group via {link}";
"lng_admin_log_participant_joined_by_link_channel" = "{from} joined the channel via {link}";
"lng_admin_log_revoke_invite_link" = "{from} revoked invite link {link}";
"lng_admin_log_delete_invite_link" = "{from} deleted invite link {link}";
"lng_admin_log_participant_left" = "{from} left the group";
"lng_admin_log_participant_left_channel" = "{from} left the channel";
"lng_admin_log_stopped_poll" = "{from} stopped poll:";
@ -2160,7 +2164,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_admin_log_unmuted_participant" = "{from} unmuted {user} in a voice chat";
"lng_admin_log_allowed_unmute_self" = "{from} allowed new voice chat members to speak";
"lng_admin_log_disallowed_unmute_self" = "{from} started muting new voice chat members";
"lng_admin_log_participant_volume" = "{from} changed voice chat volume for {user} to {percent}";
"lng_admin_log_user_with_username" = "{name} ({mention})";
"lng_admin_log_messages_ttl_set" = "{from} enabled messages auto-delete after {duration}";
"lng_admin_log_messages_ttl_changed" = "{from} changed messages auto-delete period from {previous} to {duration}";
"lng_admin_log_messages_ttl_removed" = "{from} disabled messages auto-deletion after {duration}";
"lng_admin_log_edited_invite_link" = "edited invite link {link}";
"lng_admin_log_invite_link_expire_date" = "Expire date: {previous} -> {limit}";
"lng_admin_log_invite_link_usage_limit" = "Usage limit: {previous} -> {limit}";
"lng_admin_log_restricted_forever" = "indefinitely";
"lng_admin_log_restricted_until" = "until {date}";
"lng_admin_log_banned_view_messages" = "Read messages";

View file

@ -238,8 +238,8 @@ void InviteLinks::performEdit(
using Flag = MTPmessages_EditExportedChatInvite::Flag;
_api->request(MTPmessages_EditExportedChatInvite(
MTP_flags((revoke ? Flag::f_revoked : Flag(0))
| ((!revoke && expireDate) ? Flag::f_expire_date : Flag(0))
| ((!revoke && usageLimit) ? Flag::f_usage_limit : Flag(0))),
| (!revoke ? Flag::f_expire_date : Flag(0))
| (!revoke ? Flag::f_usage_limit : Flag(0))),
peer->input,
MTP_string(link),
MTP_int(expireDate),

View file

@ -26,6 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/language_box.h"
#include "passport/passport_form_controller.h"
#include "window/window_session_controller.h"
#include "ui/toast/toast.h"
#include "data/data_session.h"
#include "data/data_document.h"
#include "data/data_cloud_themes.h"
@ -40,6 +41,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "apiwrap.h"
#include "app.h"
#include <QtGui/QGuiApplication>
namespace Core {
namespace {
@ -433,6 +436,23 @@ bool OpenMediaTimestamp(
return false;
}
bool ShowInviteLink(
Window::SessionController *controller,
const Match &match,
const QVariant &context) {
if (!controller) {
return false;
}
const auto base64link = match->captured(1).toLatin1();
const auto link = QString::fromUtf8(QByteArray::fromBase64(base64link));
if (link.isEmpty()) {
return false;
}
QGuiApplication::clipboard()->setText(link);
Ui::Toast::Show(tr::lng_group_invite_copied(tr::now));
return true;
}
} // namespace
const std::vector<LocalUrlHandler> &LocalUrlHandlers() {
@ -507,6 +527,10 @@ const std::vector<LocalUrlHandler> &InternalUrlHandlers() {
qsl("^media_timestamp/?\\?base=([a-zA-Z0-9\\.\\_\\-]+)&t=(\\d+)(&|$)"),
OpenMediaTimestamp
},
{
qsl("^show_invite_link/?\\?link=([a-zA-Z0-9_\\+\\/\\=\\-]+)(&|$)"),
ShowInviteLink
},
};
return Result;
}

View file

@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#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"
@ -261,6 +262,86 @@ TextWithEntities GenerateBannedChangeText(
return result;
}
QString ExtractInviteLink(const MTPExportedChatInvite &data) {
return data.match([&](const MTPDchatInviteExported &data) {
return qs(data.vlink());
});
}
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) {
return ExtractInviteLink(data).replace(
qstr("https://"),
QString()
).replace(
qstr("t.me/+"),
QString()
).replace(
qstr("t.me/joinchat/"),
QString()
);
}
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,
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 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 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 wasExpireDate = expireDate(prevLink);
const auto nowExpireDate = expireDate(newLink);
const auto wasUsageLimit = usageLimit(prevLink);
const auto nowUsageLimit = usageLimit(newLink);
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)));
}
result.entities.push_front(EntityInText(EntityType::Italic, 0, result.text.size()));
return result;
};
auto GenerateUserString(
not_null<Main::Session*> session,
MTPint userId) {
@ -863,52 +944,49 @@ void GenerateItems(
addSimpleServiceMessage(text);
};
auto createParticipantMute = [&](const MTPDchannelAdminLogEventActionParticipantMute &data) {
data.vparticipant().match([&](const MTPDgroupCallParticipant &data) {
const auto user = history->owner().user(data.vuser_id().v);
const auto userLink = user->createOpenLink();
const auto userLinkText = textcmdLink(2, user->name);
auto text = tr::lng_admin_log_muted_participant(
tr::now,
lt_from,
fromLinkText,
lt_user,
userLinkText);
auto message = HistoryService::PreparedText{ text };
message.links.push_back(fromLink);
message.links.push_back(userLink);
addPart(history->makeServiceMessage(
history->nextNonHistoryEntryId(),
MTPDmessage_ClientFlag::f_admin_log_entry,
date,
message,
MTPDmessage::Flags(0),
peerToUser(from->id)));
auto groupCallParticipantUser = [&](const MTPGroupCallParticipant &data) {
return data.match([&](const MTPDgroupCallParticipant &data) {
return history->owner().user(data.vuser_id().v);
});
};
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(),
MTPDmessage_ClientFlag::f_admin_log_entry,
date,
message,
MTPDmessage::Flags(0),
peerToUser(from->id)));
};
auto createParticipantMute = [&](const MTPDchannelAdminLogEventActionParticipantMute &data) {
const auto user = groupCallParticipantUser(data.vparticipant());
const auto userLink = user->createOpenLink();
const auto userLinkText = textcmdLink(2, user->name);
auto text = tr::lng_admin_log_muted_participant(
tr::now,
lt_from,
fromLinkText,
lt_user,
userLinkText);
addServiceMessageWithLink(text, userLink);
};
auto createParticipantUnmute = [&](const MTPDchannelAdminLogEventActionParticipantUnmute &data) {
data.vparticipant().match([&](const MTPDgroupCallParticipant &data) {
const auto user = history->owner().user(data.vuser_id().v);
const auto userLink = user->createOpenLink();
const auto userLinkText = textcmdLink(2, user->name);
auto text = tr::lng_admin_log_unmuted_participant(
tr::now,
lt_from,
fromLinkText,
lt_user,
userLinkText);
auto message = HistoryService::PreparedText{ text };
message.links.push_back(fromLink);
message.links.push_back(userLink);
addPart(history->makeServiceMessage(
history->nextNonHistoryEntryId(),
MTPDmessage_ClientFlag::f_admin_log_entry,
date,
message,
MTPDmessage::Flags(0),
peerToUser(from->id)));
});
const auto user = groupCallParticipantUser(data.vparticipant());
const auto userLink = user->createOpenLink();
const auto userLinkText = textcmdLink(2, user->name);
auto text = tr::lng_admin_log_unmuted_participant(
tr::now,
lt_from,
fromLinkText,
lt_user,
userLinkText);
addServiceMessageWithLink(text, userLink);
};
auto createToggleGroupCallSetting = [&](const MTPDchannelAdminLogEventActionToggleGroupCallSetting &data) {
@ -918,6 +996,114 @@ void GenerateItems(
addSimpleServiceMessage(text);
};
auto addInviteLinkServiceMessage = [&](const QString &text, const MTPExportedChatInvite &data) {
auto message = HistoryService::PreparedText{ text };
message.links.push_back(fromLink);
if (!ExtractInviteLink(data).endsWith("...")) {
message.links.push_back(std::make_shared<UrlClickHandler>(InternalInviteLinkUrl(data)));
}
addPart(history->makeServiceMessage(
history->nextNonHistoryEntryId(),
MTPDmessage_ClientFlag::f_admin_log_entry,
date,
message,
MTPDmessage::Flags(0),
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) {
auto bodyFlags = Flag::f_entities | Flag::f_from_id;
auto bodyClientFlags = MTPDmessage_ClientFlag::f_admin_log_entry;
auto bodyReplyTo = 0;
auto bodyViaBotId = 0;
auto bodyText = GenerateInviteLinkChangeText(data.vnew_invite(), data.vprev_invite());
addPart(history->makeMessage(
history->nextNonHistoryEntryId(),
bodyFlags,
bodyClientFlags,
bodyReplyTo,
bodyViaBotId,
date,
peerToUser(from->id),
QString(),
bodyText));
};
auto createParticipantVolume = [&](const MTPDchannelAdminLogEventActionParticipantVolume &data) {
const auto user = groupCallParticipantUser(data.vparticipant());
const auto userLink = user->createOpenLink();
const auto userLinkText = textcmdLink(2, user->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 = tr::lng_admin_log_participant_volume(
tr::now,
lt_from,
fromLinkText,
lt_user,
userLinkText,
lt_percent,
volumeText);
addServiceMessageWithLink(text, userLink);
};
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 < 3 * 86400)
? tr::lng_manage_messages_ttl_after1(tr::now)
: tr::lng_manage_messages_ttl_after2(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);
};
action.match([&](const MTPDchannelAdminLogEventActionChangeTitle &data) {
createChangeTitle(data);
}, [&](const MTPDchannelAdminLogEventActionChangeAbout &data) {
@ -971,14 +1157,17 @@ void GenerateItems(
}, [&](const MTPDchannelAdminLogEventActionToggleGroupCallSetting &data) {
createToggleGroupCallSetting(data);
}, [&](const MTPDchannelAdminLogEventActionParticipantJoinByInvite &data) {
createParticipantJoinByInvite(data);
}, [&](const MTPDchannelAdminLogEventActionExportedInviteDelete &data) {
createExportedInviteDelete(data);
}, [&](const MTPDchannelAdminLogEventActionExportedInviteRevoke &data) {
createExportedInviteRevoke(data);
}, [&](const MTPDchannelAdminLogEventActionExportedInviteEdit &data) {
// #TODO links
createExportedInviteEdit(data);
}, [&](const MTPDchannelAdminLogEventActionParticipantVolume &data) {
// #TODO calls
createParticipantVolume(data);
}, [&](const MTPDchannelAdminLogEventActionChangeHistoryTTL &data) {
// #TODO ttl
createChangeHistoryTTL(data);
});
}