| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358 |
- /*
- 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 "api/api_text_entities.h"
- #include "data/data_document.h"
- #include "data/data_session.h"
- #include "data/data_user.h"
- #include "data/stickers/data_custom_emoji.h"
- #include "data/stickers/data_stickers_set.h"
- #include "main/main_session.h"
- namespace Api {
- namespace {
- using namespace TextUtilities;
- [[nodiscard]] QString CustomEmojiEntityData(
- const MTPDmessageEntityCustomEmoji &data) {
- return Data::SerializeCustomEmojiId(data.vdocument_id().v);
- }
- [[nodiscard]] std::optional<MTPMessageEntity> CustomEmojiEntity(
- MTPint offset,
- MTPint length,
- const QString &data) {
- const auto parsed = Data::ParseCustomEmojiData(data);
- if (!parsed) {
- return {};
- }
- return MTP_messageEntityCustomEmoji(
- offset,
- length,
- MTP_long(parsed));
- }
- [[nodiscard]] std::optional<MTPMessageEntity> MentionNameEntity(
- not_null<Main::Session*> session,
- MTPint offset,
- MTPint length,
- const QString &data) {
- const auto parsed = MentionNameDataToFields(data);
- if (!parsed.userId || parsed.selfId != session->userId().bare) {
- return {};
- }
- return MTP_inputMessageEntityMentionName(
- offset,
- length,
- (parsed.userId == parsed.selfId
- ? MTP_inputUserSelf()
- : MTP_inputUser(
- MTP_long(parsed.userId),
- MTP_long(parsed.accessHash))));
- }
- } // namespace
- EntitiesInText EntitiesFromMTP(
- Main::Session *session,
- const QVector<MTPMessageEntity> &entities) {
- if (entities.isEmpty()) {
- return {};
- }
- auto result = EntitiesInText();
- result.reserve(entities.size());
- for (const auto &entity : entities) {
- entity.match([&](const MTPDmessageEntityUnknown &d) {
- }, [&](const MTPDmessageEntityMention &d) {
- result.push_back({
- EntityType::Mention,
- d.voffset().v,
- d.vlength().v,
- });
- }, [&](const MTPDmessageEntityHashtag &d) {
- result.push_back({
- EntityType::Hashtag,
- d.voffset().v,
- d.vlength().v,
- });
- }, [&](const MTPDmessageEntityBotCommand &d) {
- result.push_back({
- EntityType::BotCommand,
- d.voffset().v,
- d.vlength().v,
- });
- }, [&](const MTPDmessageEntityUrl &d) {
- result.push_back({
- EntityType::Url,
- d.voffset().v,
- d.vlength().v,
- });
- }, [&](const MTPDmessageEntityEmail &d) {
- result.push_back({
- EntityType::Email,
- d.voffset().v,
- d.vlength().v,
- });
- }, [&](const MTPDmessageEntityBold &d) {
- result.push_back({
- EntityType::Bold,
- d.voffset().v,
- d.vlength().v,
- });
- }, [&](const MTPDmessageEntityItalic &d) {
- result.push_back({
- EntityType::Italic,
- d.voffset().v,
- d.vlength().v,
- });
- }, [&](const MTPDmessageEntityCode &d) {
- result.push_back({
- EntityType::Code,
- d.voffset().v,
- d.vlength().v,
- });
- }, [&](const MTPDmessageEntityPre &d) {
- result.push_back({
- EntityType::Pre,
- d.voffset().v,
- d.vlength().v,
- qs(d.vlanguage()),
- });
- }, [&](const MTPDmessageEntityTextUrl &d) {
- result.push_back({
- EntityType::CustomUrl,
- d.voffset().v,
- d.vlength().v,
- qs(d.vurl()),
- });
- }, [&](const MTPDmessageEntityMentionName &d) {
- if (!session) {
- return;
- }
- const auto userId = UserId(d.vuser_id());
- const auto user = session->data().userLoaded(userId);
- const auto data = MentionNameDataFromFields({
- .selfId = session->userId().bare,
- .userId = userId.bare,
- .accessHash = user ? user->accessHash() : 0,
- });
- result.push_back({
- EntityType::MentionName,
- d.voffset().v,
- d.vlength().v,
- data,
- });
- }, [&](const MTPDinputMessageEntityMentionName &d) {
- if (!session) {
- return;
- }
- const auto data = d.vuser_id().match([&](
- const MTPDinputUserSelf &) {
- return MentionNameDataFromFields({
- .selfId = session->userId().bare,
- .userId = session->userId().bare,
- .accessHash = session->user()->accessHash(),
- });
- }, [&](const MTPDinputUser &data) {
- return MentionNameDataFromFields({
- .selfId = session->userId().bare,
- .userId = UserId(data.vuser_id()).bare,
- .accessHash = data.vaccess_hash().v,
- });
- }, [](const auto &) {
- return QString();
- });
- if (!data.isEmpty()) {
- result.push_back({
- EntityType::MentionName,
- d.voffset().v,
- d.vlength().v,
- data,
- });
- }
- }, [&](const MTPDmessageEntityPhone &d) {
- result.push_back({
- EntityType::Phone,
- d.voffset().v,
- d.vlength().v,
- });
- }, [&](const MTPDmessageEntityCashtag &d) {
- result.push_back({
- EntityType::Cashtag,
- d.voffset().v,
- d.vlength().v,
- });
- }, [&](const MTPDmessageEntityUnderline &d) {
- result.push_back({
- EntityType::Underline,
- d.voffset().v,
- d.vlength().v,
- });
- }, [&](const MTPDmessageEntityStrike &d) {
- result.push_back({
- EntityType::StrikeOut,
- d.voffset().v,
- d.vlength().v,
- });
- }, [&](const MTPDmessageEntityBankCard &d) {
- // Skipping cards. // #TODO entities
- }, [&](const MTPDmessageEntitySpoiler &d) {
- result.push_back({
- EntityType::Spoiler,
- d.voffset().v,
- d.vlength().v,
- });
- }, [&](const MTPDmessageEntityCustomEmoji &d) {
- result.push_back({
- EntityType::CustomEmoji,
- d.voffset().v,
- d.vlength().v,
- CustomEmojiEntityData(d),
- });
- }, [&](const MTPDmessageEntityBlockquote &d) {
- result.push_back({
- EntityType::Blockquote,
- d.voffset().v,
- d.vlength().v,
- d.is_collapsed() ? u"1"_q : QString(),
- });
- });
- }
- return result;
- }
- MTPVector<MTPMessageEntity> EntitiesToMTP(
- Main::Session *session,
- const EntitiesInText &entities,
- ConvertOption option) {
- auto v = QVector<MTPMessageEntity>();
- v.reserve(entities.size());
- for (const auto &entity : entities) {
- if (entity.length() <= 0) {
- continue;
- }
- if (option == ConvertOption::SkipLocal
- && entity.type() != EntityType::Bold
- //&& entity.type() != EntityType::Semibold // Not in API.
- && entity.type() != EntityType::Italic
- && entity.type() != EntityType::Underline
- && entity.type() != EntityType::StrikeOut
- && entity.type() != EntityType::Code // #TODO entities
- && entity.type() != EntityType::Pre
- && entity.type() != EntityType::Blockquote
- && entity.type() != EntityType::Spoiler
- && entity.type() != EntityType::MentionName
- && entity.type() != EntityType::CustomUrl
- && entity.type() != EntityType::CustomEmoji) {
- continue;
- }
- auto offset = MTP_int(entity.offset());
- auto length = MTP_int(entity.length());
- switch (entity.type()) {
- case EntityType::Url: {
- v.push_back(MTP_messageEntityUrl(offset, length));
- } break;
- case EntityType::CustomUrl: {
- v.push_back(
- MTP_messageEntityTextUrl(
- offset,
- length,
- MTP_string(entity.data())));
- } break;
- case EntityType::Email: {
- v.push_back(MTP_messageEntityEmail(offset, length));
- } break;
- case EntityType::Phone: {
- v.push_back(MTP_messageEntityPhone(offset, length));
- } break;
- case EntityType::Hashtag: {
- v.push_back(MTP_messageEntityHashtag(offset, length));
- } break;
- case EntityType::Cashtag: {
- v.push_back(MTP_messageEntityCashtag(offset, length));
- } break;
- case EntityType::Mention: {
- v.push_back(MTP_messageEntityMention(offset, length));
- } break;
- case EntityType::MentionName: {
- Assert(session != nullptr);
- const auto valid = MentionNameEntity(
- session,
- offset,
- length,
- entity.data());
- if (valid) {
- v.push_back(*valid);
- }
- } break;
- case EntityType::BotCommand: {
- v.push_back(MTP_messageEntityBotCommand(offset, length));
- } break;
- case EntityType::Bold: {
- v.push_back(MTP_messageEntityBold(offset, length));
- } break;
- case EntityType::Italic: {
- v.push_back(MTP_messageEntityItalic(offset, length));
- } break;
- case EntityType::Underline: {
- v.push_back(MTP_messageEntityUnderline(offset, length));
- } break;
- case EntityType::StrikeOut: {
- v.push_back(MTP_messageEntityStrike(offset, length));
- } break;
- case EntityType::Code: {
- // #TODO entities.
- v.push_back(MTP_messageEntityCode(offset, length));
- } break;
- case EntityType::Pre: {
- v.push_back(
- MTP_messageEntityPre(
- offset,
- length,
- MTP_string(entity.data())));
- } break;
- case EntityType::Blockquote: {
- using Flag = MTPDmessageEntityBlockquote::Flag;
- const auto collapsed = !entity.data().isEmpty();
- v.push_back(
- MTP_messageEntityBlockquote(
- MTP_flags(collapsed ? Flag::f_collapsed : Flag()),
- offset,
- length));
- } break;
- case EntityType::Spoiler: {
- v.push_back(MTP_messageEntitySpoiler(offset, length));
- } break;
- case EntityType::CustomEmoji: {
- const auto valid = CustomEmojiEntity(
- offset,
- length,
- entity.data());
- if (valid) {
- v.push_back(*valid);
- }
- } break;
- }
- }
- return MTP_vector<MTPMessageEntity>(std::move(v));
- }
- TextWithEntities ParseTextWithEntities(
- Main::Session *session,
- const MTPTextWithEntities &text) {
- const auto &data = text.data();
- return {
- .text = qs(data.vtext()),
- .entities = EntitiesFromMTP(session, data.ventities().v),
- };
- }
- } // namespace Api
|