"Fossies" - the Fresh Open Source Software Archive 
Member "tdesktop-4.8.3/Telegram/SourceFiles/api/api_editing.cpp" (1 Jun 2023, 6319 Bytes) of package /linux/misc/tdesktop-4.8.3.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "api_editing.cpp" see the
Fossies "Dox" file reference documentation.
1 /*
2 This file is part of Telegram Desktop,
3 the official desktop application for the Telegram messaging service.
4
5 For license and copyright information please follow this link:
6 https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
7 */
8 #include "api/api_editing.h"
9
10 #include "apiwrap.h"
11 #include "api/api_media.h"
12 #include "api/api_text_entities.h"
13 #include "ui/boxes/confirm_box.h"
14 #include "data/data_scheduled_messages.h"
15 #include "data/data_session.h"
16 #include "history/history.h"
17 #include "history/history_item.h"
18 #include "lang/lang_keys.h"
19 #include "main/main_session.h"
20 #include "mtproto/mtproto_response.h"
21 #include "boxes/abstract_box.h" // Ui::show().
22
23 namespace Api {
24 namespace {
25
26 using namespace rpl::details;
27
28 template <typename T>
29 constexpr auto WithId =
30 is_callable_plain_v<T, Fn<void()>, mtpRequestId>;
31 template <typename T>
32 constexpr auto WithoutId =
33 is_callable_plain_v<T, Fn<void()>>;
34 template <typename T>
35 constexpr auto WithoutCallback =
36 is_callable_plain_v<T>;
37 template <typename T>
38 constexpr auto ErrorWithId =
39 is_callable_plain_v<T, QString, mtpRequestId>;
40 template <typename T>
41 constexpr auto ErrorWithoutId =
42 is_callable_plain_v<T, QString>;
43
44 template <typename DoneCallback, typename FailCallback>
45 mtpRequestId EditMessage(
46 not_null<HistoryItem*> item,
47 const TextWithEntities &textWithEntities,
48 SendOptions options,
49 DoneCallback &&done,
50 FailCallback &&fail,
51 std::optional<MTPInputMedia> inputMedia = std::nullopt) {
52 const auto session = &item->history()->session();
53 const auto api = &session->api();
54
55 const auto text = textWithEntities.text;
56 const auto sentEntities = EntitiesToMTP(
57 session,
58 textWithEntities.entities,
59 ConvertOption::SkipLocal);
60 const auto media = item->media();
61
62 const auto updateRecentStickers = inputMedia.has_value()
63 ? Api::HasAttachedStickers(*inputMedia)
64 : false;
65
66 const auto emptyFlag = MTPmessages_EditMessage::Flag(0);
67 const auto flags = emptyFlag
68 | (!text.isEmpty() || media
69 ? MTPmessages_EditMessage::Flag::f_message
70 : emptyFlag)
71 | ((media && inputMedia.has_value())
72 ? MTPmessages_EditMessage::Flag::f_media
73 : emptyFlag)
74 | (options.removeWebPageId
75 ? MTPmessages_EditMessage::Flag::f_no_webpage
76 : emptyFlag)
77 | (!sentEntities.v.isEmpty()
78 ? MTPmessages_EditMessage::Flag::f_entities
79 : emptyFlag)
80 | (options.scheduled
81 ? MTPmessages_EditMessage::Flag::f_schedule_date
82 : emptyFlag);
83
84 const auto id = item->isScheduled()
85 ? session->data().scheduledMessages().lookupId(item)
86 : item->id;
87 return api->request(MTPmessages_EditMessage(
88 MTP_flags(flags),
89 item->history()->peer->input,
90 MTP_int(id),
91 MTP_string(text),
92 inputMedia.value_or(MTPInputMedia()),
93 MTPReplyMarkup(),
94 sentEntities,
95 MTP_int(options.scheduled)
96 )).done([=](
97 const MTPUpdates &result,
98 [[maybe_unused]] mtpRequestId requestId) {
99 const auto apply = [=] { api->applyUpdates(result); };
100
101 if constexpr (WithId<DoneCallback>) {
102 done(apply, requestId);
103 } else if constexpr (WithoutId<DoneCallback>) {
104 done(apply);
105 } else if constexpr (WithoutCallback<DoneCallback>) {
106 done();
107 apply();
108 } else {
109 t_bad_callback(done);
110 }
111
112 if (updateRecentStickers) {
113 api->requestRecentStickersForce(true);
114 }
115 }).fail([=](const MTP::Error &error, mtpRequestId requestId) {
116 if constexpr (ErrorWithId<FailCallback>) {
117 fail(error.type(), requestId);
118 } else if constexpr (ErrorWithoutId<FailCallback>) {
119 fail(error.type());
120 } else if constexpr (WithoutCallback<FailCallback>) {
121 fail();
122 } else {
123 t_bad_callback(fail);
124 }
125 }).send();
126 }
127
128 template <typename DoneCallback, typename FailCallback>
129 mtpRequestId EditMessage(
130 not_null<HistoryItem*> item,
131 SendOptions options,
132 DoneCallback &&done,
133 FailCallback &&fail,
134 std::optional<MTPInputMedia> inputMedia = std::nullopt) {
135 const auto &text = item->originalText();
136 return EditMessage(
137 item,
138 text,
139 options,
140 std::forward<DoneCallback>(done),
141 std::forward<FailCallback>(fail),
142 inputMedia);
143 }
144
145 void EditMessageWithUploadedMedia(
146 not_null<HistoryItem*> item,
147 SendOptions options,
148 MTPInputMedia media) {
149 const auto done = [=](Fn<void()> applyUpdates) {
150 if (item) {
151 item->removeFromSharedMediaIndex();
152 item->clearSavedMedia();
153 item->setIsLocalUpdateMedia(true);
154 applyUpdates();
155 item->setIsLocalUpdateMedia(false);
156 }
157 };
158 const auto fail = [=](const QString &error) {
159 const auto session = &item->history()->session();
160 const auto notModified = (error == u"MESSAGE_NOT_MODIFIED"_q);
161 const auto mediaInvalid = (error == u"MEDIA_NEW_INVALID"_q);
162 if (notModified || mediaInvalid) {
163 item->returnSavedMedia();
164 session->data().sendHistoryChangeNotifications();
165 if (mediaInvalid) {
166 Ui::show(
167 Ui::MakeInformBox(tr::lng_edit_media_invalid_file()),
168 Ui::LayerOption::KeepOther);
169 }
170 } else {
171 session->api().sendMessageFail(error, item->history()->peer);
172 }
173 };
174
175 EditMessage(item, options, done, fail, media);
176 }
177
178 } // namespace
179
180 void RescheduleMessage(
181 not_null<HistoryItem*> item,
182 SendOptions options) {
183 const auto empty = [] {};
184 EditMessage(item, options, empty, empty);
185 }
186
187 void EditMessageWithUploadedDocument(
188 HistoryItem *item,
189 RemoteFileInfo info,
190 SendOptions options) {
191 if (!item || !item->media() || !item->media()->document()) {
192 return;
193 }
194 EditMessageWithUploadedMedia(
195 item,
196 options,
197 PrepareUploadedDocument(item, std::move(info)));
198 }
199
200 void EditMessageWithUploadedPhoto(
201 HistoryItem *item,
202 RemoteFileInfo info,
203 SendOptions options) {
204 if (!item || !item->media() || !item->media()->photo()) {
205 return;
206 }
207 EditMessageWithUploadedMedia(
208 item,
209 options,
210 PrepareUploadedPhoto(item, std::move(info)));
211 }
212
213 mtpRequestId EditCaption(
214 not_null<HistoryItem*> item,
215 const TextWithEntities &caption,
216 SendOptions options,
217 Fn<void()> done,
218 Fn<void(const QString &)> fail) {
219 return EditMessage(item, caption, options, done, fail);
220 }
221
222 mtpRequestId EditTextMessage(
223 not_null<HistoryItem*> item,
224 const TextWithEntities &caption,
225 SendOptions options,
226 Fn<void(mtpRequestId requestId)> done,
227 Fn<void(const QString &, mtpRequestId requestId)> fail) {
228 const auto callback = [=](Fn<void()> applyUpdates, mtpRequestId id) {
229 applyUpdates();
230 done(id);
231 };
232 return EditMessage(item, caption, options, callback, fail);
233 }
234
235 } // namespace Api