mirror of
https://github.com/vale981/tdesktop
synced 2025-03-09 12:36:39 -04:00
286 lines
13 KiB
C++
286 lines
13 KiB
C++
![]() |
/*
|
||
|
This file is part of Telegram Desktop,
|
||
|
the official desktop version of Telegram messaging app, see https://telegram.org
|
||
|
|
||
|
Telegram Desktop is free software: you can redistribute it and/or modify
|
||
|
it under the terms of the GNU General Public License as published by
|
||
|
the Free Software Foundation, either version 3 of the License, or
|
||
|
(at your option) any later version.
|
||
|
|
||
|
It is distributed in the hope that it will be useful,
|
||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
GNU General Public License for more details.
|
||
|
|
||
|
In addition, as a special exception, the copyright holders give permission
|
||
|
to link the code of portions of this program with the OpenSSL library.
|
||
|
|
||
|
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
|
||
|
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||
|
*/
|
||
|
#include "history/history_admin_log_item.h"
|
||
|
|
||
|
#include "lang/lang_keys.h"
|
||
|
#include "messenger.h"
|
||
|
|
||
|
namespace AdminLog {
|
||
|
namespace {
|
||
|
|
||
|
MTPMessage PrepareLogMessage(const MTPMessage &message, MsgId newId, int32 newDate) {
|
||
|
switch (message.type()) {
|
||
|
case mtpc_messageEmpty: return MTP_messageEmpty(MTP_int(newId));
|
||
|
case mtpc_messageService: {
|
||
|
auto &data = message.c_messageService();
|
||
|
auto flags = data.vflags.v & ~(MTPDmessageService::Flag::f_out | MTPDmessageService::Flag::f_post/* | MTPDmessageService::Flag::f_reply_to_msg_id*/);
|
||
|
return MTP_messageService(MTP_flags(flags), MTP_int(newId), data.vfrom_id, data.vto_id, data.vreply_to_msg_id, data.vdate, data.vaction);
|
||
|
} break;
|
||
|
case mtpc_message: {
|
||
|
auto &data = message.c_message();
|
||
|
auto flags = data.vflags.v & ~(MTPDmessage::Flag::f_out | MTPDmessage::Flag::f_post | MTPDmessage::Flag::f_reply_to_msg_id);
|
||
|
return MTP_message(MTP_flags(flags), MTP_int(newId), data.vfrom_id, data.vto_id, data.vfwd_from, data.vvia_bot_id, data.vreply_to_msg_id, MTP_int(newDate), data.vmessage, data.vmedia, data.vreply_markup, data.ventities, data.vviews, data.vedit_date);
|
||
|
} break;
|
||
|
}
|
||
|
Unexpected("Type in PrepareLogMessage()");
|
||
|
}
|
||
|
|
||
|
bool MessageHasCaption(const MTPMessage &message) {
|
||
|
if (message.type() != mtpc_message) {
|
||
|
return false;
|
||
|
}
|
||
|
auto &data = message.c_message();
|
||
|
auto mediaType = data.has_media() ? data.vmedia.type() : mtpc_messageMediaEmpty;
|
||
|
return (mediaType == mtpc_messageMediaDocument || mediaType == mtpc_messageMediaPhoto);
|
||
|
}
|
||
|
|
||
|
} // namespace
|
||
|
|
||
|
Item::Item(gsl::not_null<History*> history, LocalIdManager &idManager, const MTPDchannelAdminLogEvent &event)
|
||
|
: _id(event.vid.v)
|
||
|
, _history(history)
|
||
|
, _from(App::user(event.vuser_id.v)) {
|
||
|
auto &action = event.vaction;
|
||
|
auto date = event.vdate;
|
||
|
|
||
|
using ServiceFlag = MTPDmessageService::Flag;
|
||
|
using Flag = MTPDmessage::Flag;
|
||
|
auto fromName = App::peerName(_from);
|
||
|
auto fromLink = _from->openLink();
|
||
|
auto fromLinkText = textcmdLink(1, fromName);
|
||
|
|
||
|
auto addSimpleServiceMessage = [this, &idManager, date, fromLink](const QString &text) {
|
||
|
auto message = HistoryService::PreparedText { text };
|
||
|
message.links.push_back(fromLink);
|
||
|
addPart(HistoryService::create(_history, idManager.next(), ::date(date), message, 0, peerToUser(_from->id)));
|
||
|
};
|
||
|
|
||
|
auto createChangeTitle = [this, addSimpleServiceMessage, fromLinkText](const MTPDchannelAdminLogEventActionChangeTitle &action) {
|
||
|
auto text = (channel()->isMegagroup() ? lng_action_changed_title : lng_admin_log_changed_title_channel)(lt_from, fromLinkText, lt_title, qs(action.vnew_value));
|
||
|
addSimpleServiceMessage(text);
|
||
|
};
|
||
|
|
||
|
auto createChangeAbout = [this, &idManager, date, addSimpleServiceMessage, fromLinkText](const MTPDchannelAdminLogEventActionChangeAbout &action) {
|
||
|
auto newValue = qs(action.vnew_value);
|
||
|
auto oldValue = qs(action.vprev_value);
|
||
|
auto text = (channel()->isMegagroup()
|
||
|
? (newValue.isEmpty() ? lng_admin_log_removed_description_group : lng_admin_log_changed_description_group)
|
||
|
: (newValue.isEmpty() ? lng_admin_log_removed_description_channel : lng_admin_log_changed_description_channel)
|
||
|
)(lt_from, fromLinkText);
|
||
|
addSimpleServiceMessage(text);
|
||
|
|
||
|
auto bodyFlags = Flag::f_entities | Flag::f_from_id;
|
||
|
auto bodyReplyTo = 0;
|
||
|
auto bodyViaBotId = 0;
|
||
|
auto newDescription = PrepareText(newValue, QString());
|
||
|
auto body = HistoryMessage::create(_history, idManager.next(), bodyFlags, bodyReplyTo, bodyViaBotId, ::date(date), peerToUser(_from->id), newDescription);
|
||
|
if (!oldValue.isEmpty()) {
|
||
|
auto oldDescription = PrepareText(oldValue, QString());
|
||
|
body->addLogEntryOriginal(lang(lng_admin_log_previous_description), oldDescription);
|
||
|
}
|
||
|
addPart(body);
|
||
|
};
|
||
|
|
||
|
auto createChangeUsername = [this, &idManager, date, addSimpleServiceMessage, fromLinkText](const MTPDchannelAdminLogEventActionChangeUsername &action) {
|
||
|
auto newValue = qs(action.vnew_value);
|
||
|
auto oldValue = qs(action.vprev_value);
|
||
|
auto text = (channel()->isMegagroup()
|
||
|
? (newValue.isEmpty() ? lng_admin_log_removed_link_group : lng_admin_log_changed_link_group)
|
||
|
: (newValue.isEmpty() ? lng_admin_log_removed_link_channel : lng_admin_log_changed_link_channel)
|
||
|
)(lt_from, fromLinkText);
|
||
|
addSimpleServiceMessage(text);
|
||
|
|
||
|
auto bodyFlags = Flag::f_entities | Flag::f_from_id;
|
||
|
auto bodyReplyTo = 0;
|
||
|
auto bodyViaBotId = 0;
|
||
|
auto newLink = newValue.isEmpty() ? TextWithEntities() : PrepareText(Messenger::Instance().createInternalLinkFull(newValue), QString());
|
||
|
auto body = HistoryMessage::create(_history, idManager.next(), bodyFlags, bodyReplyTo, bodyViaBotId, ::date(date), peerToUser(_from->id), newLink);
|
||
|
if (!oldValue.isEmpty()) {
|
||
|
auto oldLink = PrepareText(Messenger::Instance().createInternalLinkFull(oldValue), QString());
|
||
|
body->addLogEntryOriginal(lang(lng_admin_log_previous_link), oldLink);
|
||
|
}
|
||
|
addPart(body);
|
||
|
};
|
||
|
|
||
|
auto createChangePhoto = [this, addSimpleServiceMessage, fromLinkText](const MTPDchannelAdminLogEventActionChangePhoto &action) {
|
||
|
auto text = (channel()->isMegagroup() ? lng_admin_log_changed_photo_group : lng_admin_log_changed_photo_channel)(lt_from, fromLinkText);
|
||
|
addSimpleServiceMessage(text);
|
||
|
};
|
||
|
|
||
|
auto createToggleInvites = [this, addSimpleServiceMessage, fromLinkText](const MTPDchannelAdminLogEventActionToggleInvites &action) {
|
||
|
auto enabled = (action.vnew_value.type() == mtpc_boolTrue);
|
||
|
auto text = (enabled ? lng_admin_log_invites_enabled : lng_admin_log_invites_disabled)(lt_from, fromLinkText);
|
||
|
addSimpleServiceMessage(text);
|
||
|
};
|
||
|
|
||
|
auto createToggleSignatures = [this, addSimpleServiceMessage, fromLinkText](const MTPDchannelAdminLogEventActionToggleSignatures &action) {
|
||
|
auto enabled = (action.vnew_value.type() == mtpc_boolTrue);
|
||
|
auto text = (enabled ? lng_admin_log_signatures_enabled : lng_admin_log_signatures_disabled)(lt_from, fromLinkText);
|
||
|
addSimpleServiceMessage(text);
|
||
|
};
|
||
|
|
||
|
auto createUpdatePinned = [this, &idManager, date, addSimpleServiceMessage, fromLinkText](const MTPDchannelAdminLogEventActionUpdatePinned &action) {
|
||
|
auto text = lng_admin_log_pinned_message(lt_from, fromLinkText);
|
||
|
addSimpleServiceMessage(text);
|
||
|
|
||
|
auto applyServiceAction = false;
|
||
|
auto detachExistingItem = false;
|
||
|
addPart(_history->createItem(PrepareLogMessage(action.vmessage, idManager.next(), date.v), applyServiceAction, detachExistingItem));
|
||
|
};
|
||
|
|
||
|
auto createEditMessage = [this, &idManager, date, addSimpleServiceMessage, fromLinkText](const MTPDchannelAdminLogEventActionEditMessage &action) {
|
||
|
auto text = (MessageHasCaption(action.vnew_message) ? lng_admin_log_edited_caption : lng_admin_log_edited_message)(lt_from, fromLinkText);
|
||
|
addSimpleServiceMessage(text);
|
||
|
|
||
|
auto applyServiceAction = false;
|
||
|
auto detachExistingItem = false;
|
||
|
addPart(_history->createItem(PrepareLogMessage(action.vnew_message, idManager.next(), date.v), applyServiceAction, detachExistingItem));
|
||
|
};
|
||
|
|
||
|
auto createDeleteMessage = [this, &idManager, date, addSimpleServiceMessage, fromLinkText](const MTPDchannelAdminLogEventActionDeleteMessage &action) {
|
||
|
auto text = lng_admin_log_deleted_message(lt_from, fromLinkText);
|
||
|
addSimpleServiceMessage(text);
|
||
|
|
||
|
auto applyServiceAction = false;
|
||
|
auto detachExistingItem = false;
|
||
|
addPart(_history->createItem(PrepareLogMessage(action.vmessage, idManager.next(), date.v), applyServiceAction, detachExistingItem));
|
||
|
};
|
||
|
|
||
|
auto createParticipantJoin = [this, &idManager, addSimpleServiceMessage, fromLinkText]() {
|
||
|
auto text = lng_admin_log_participant_joined(lt_from, fromLinkText);
|
||
|
addSimpleServiceMessage(text);
|
||
|
};
|
||
|
|
||
|
auto createParticipantLeave = [this, &idManager, addSimpleServiceMessage, fromLinkText]() {
|
||
|
auto text = lng_admin_log_participant_left(lt_from, fromLinkText);
|
||
|
addSimpleServiceMessage(text);
|
||
|
};
|
||
|
|
||
|
auto createParticipantInvite = [this, &idManager, date](const MTPDchannelAdminLogEventActionParticipantInvite &action) {
|
||
|
auto bodyFlags = Flag::f_entities | Flag::f_from_id;
|
||
|
auto bodyReplyTo = 0;
|
||
|
auto bodyViaBotId = 0;
|
||
|
addPart(HistoryMessage::create(_history, idManager.next(), bodyFlags, bodyReplyTo, bodyViaBotId, ::date(date), peerToUser(_from->id), { "participant invite text", EntitiesInText() }));
|
||
|
};
|
||
|
|
||
|
auto createParticipantToggleBan = [this, &idManager, date](const MTPDchannelAdminLogEventActionParticipantToggleBan &action) {
|
||
|
auto bodyFlags = Flag::f_entities | Flag::f_from_id;
|
||
|
auto bodyReplyTo = 0;
|
||
|
auto bodyViaBotId = 0;
|
||
|
addPart(HistoryMessage::create(_history, idManager.next(), bodyFlags, bodyReplyTo, bodyViaBotId, ::date(date), peerToUser(_from->id), { "participant toggle ban text", EntitiesInText() }));
|
||
|
};
|
||
|
|
||
|
auto createParticipantToggleAdmin = [this, &idManager, date](const MTPDchannelAdminLogEventActionParticipantToggleAdmin &action) {
|
||
|
auto bodyFlags = Flag::f_entities | Flag::f_from_id;
|
||
|
auto bodyReplyTo = 0;
|
||
|
auto bodyViaBotId = 0;
|
||
|
addPart(HistoryMessage::create(_history, idManager.next(), bodyFlags, bodyReplyTo, bodyViaBotId, ::date(date), peerToUser(_from->id), { "participant toggle admin text", EntitiesInText() }));
|
||
|
};
|
||
|
|
||
|
switch (action.type()) {
|
||
|
case mtpc_channelAdminLogEventActionChangeTitle: createChangeTitle(action.c_channelAdminLogEventActionChangeTitle()); break;
|
||
|
case mtpc_channelAdminLogEventActionChangeAbout: createChangeAbout(action.c_channelAdminLogEventActionChangeAbout()); break;
|
||
|
case mtpc_channelAdminLogEventActionChangeUsername: createChangeUsername(action.c_channelAdminLogEventActionChangeUsername()); break;
|
||
|
case mtpc_channelAdminLogEventActionChangePhoto: createChangePhoto(action.c_channelAdminLogEventActionChangePhoto()); break;
|
||
|
case mtpc_channelAdminLogEventActionToggleInvites: createToggleInvites(action.c_channelAdminLogEventActionToggleInvites()); break;
|
||
|
case mtpc_channelAdminLogEventActionToggleSignatures: createToggleSignatures(action.c_channelAdminLogEventActionToggleSignatures()); break;
|
||
|
case mtpc_channelAdminLogEventActionUpdatePinned: createUpdatePinned(action.c_channelAdminLogEventActionUpdatePinned()); break;
|
||
|
case mtpc_channelAdminLogEventActionEditMessage: createEditMessage(action.c_channelAdminLogEventActionEditMessage()); break;
|
||
|
case mtpc_channelAdminLogEventActionDeleteMessage: createDeleteMessage(action.c_channelAdminLogEventActionDeleteMessage()); break;
|
||
|
case mtpc_channelAdminLogEventActionParticipantJoin: createParticipantJoin(); break;
|
||
|
case mtpc_channelAdminLogEventActionParticipantLeave: createParticipantLeave(); break;
|
||
|
case mtpc_channelAdminLogEventActionParticipantInvite: createParticipantInvite(action.c_channelAdminLogEventActionParticipantInvite()); break;
|
||
|
case mtpc_channelAdminLogEventActionParticipantToggleBan: createParticipantToggleBan(action.c_channelAdminLogEventActionParticipantToggleBan()); break;
|
||
|
case mtpc_channelAdminLogEventActionParticipantToggleAdmin: createParticipantToggleAdmin(action.c_channelAdminLogEventActionParticipantToggleAdmin()); break;
|
||
|
default: Unexpected("channelAdminLogEventAction type in AdminLog::Item::Item()");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void Item::addPart(HistoryItem *item) {
|
||
|
_parts.push_back(item);
|
||
|
}
|
||
|
|
||
|
int Item::resizeGetHeight(int newWidth) {
|
||
|
_height = 0;
|
||
|
for (auto part : _parts) {
|
||
|
_height += part->resizeGetHeight(newWidth);
|
||
|
}
|
||
|
return _height;
|
||
|
}
|
||
|
|
||
|
void Item::draw(Painter &p, QRect clip, TextSelection selection, TimeMs ms) {
|
||
|
auto top = 0;
|
||
|
for (auto part : _parts) {
|
||
|
auto height = part->height();
|
||
|
if (clip.top() < top + height && clip.top() + clip.height() > top) {
|
||
|
p.translate(0, top);
|
||
|
part->draw(p, clip.translated(0, -top), selection, ms);
|
||
|
p.translate(0, -top);
|
||
|
}
|
||
|
top += height;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool Item::hasPoint(QPoint point) const {
|
||
|
auto top = 0;
|
||
|
for (auto part : _parts) {
|
||
|
auto height = part->height();
|
||
|
if (point.y() >= top && point.y() < top + height) {
|
||
|
return part->hasPoint(point.x(), point.y() - top);
|
||
|
}
|
||
|
top += height;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
HistoryTextState Item::getState(QPoint point, HistoryStateRequest request) const {
|
||
|
auto top = 0;
|
||
|
for (auto part : _parts) {
|
||
|
auto height = part->height();
|
||
|
if (point.y() >= top && point.y() < top + height) {
|
||
|
return part->getState(point.x(), point.y() - top, request);
|
||
|
}
|
||
|
top += height;
|
||
|
}
|
||
|
return HistoryTextState();
|
||
|
}
|
||
|
|
||
|
TextWithEntities Item::PrepareText(const QString &value, const QString &emptyValue) {
|
||
|
auto result = TextWithEntities { textClean(value) };
|
||
|
if (result.text.isEmpty()) {
|
||
|
result.text = emptyValue;
|
||
|
if (!emptyValue.isEmpty()) {
|
||
|
result.entities.push_back(EntityInText(EntityInTextItalic, 0, emptyValue.size()));
|
||
|
}
|
||
|
} else {
|
||
|
textParseEntities(result.text, TextParseLinks | TextParseMentions | TextParseHashtags | TextParseBotCommands, &result.entities);
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
Item::~Item() {
|
||
|
for (auto part : _parts) {
|
||
|
part->destroy();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
} // namespace AdminLog
|