From e29dcf7489b7faf9623bf1bb5e3b8a9ac4d5f469 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 20 Jun 2025 13:13:17 +0400 Subject: [PATCH] Update API scheme on layer 206. Re-Suggest. --- Telegram/SourceFiles/api/api_suggest_post.cpp | 163 +++++++++++++++++- Telegram/SourceFiles/apiwrap.cpp | 12 +- Telegram/SourceFiles/boxes/share_box.cpp | 6 +- .../SourceFiles/history/history_widget.cpp | 19 +- Telegram/SourceFiles/history/history_widget.h | 1 + .../history/view/history_view_element.cpp | 4 +- .../view/history_view_suggest_options.cpp | 76 ++++---- .../view/history_view_suggest_options.h | 29 ++++ .../view/media/history_view_media_generic.cpp | 7 +- Telegram/SourceFiles/main/main_app_config.cpp | 8 + Telegram/SourceFiles/main/main_app_config.h | 2 + Telegram/SourceFiles/mtproto/scheme/api.tl | 2 +- 12 files changed, 278 insertions(+), 51 deletions(-) diff --git a/Telegram/SourceFiles/api/api_suggest_post.cpp b/Telegram/SourceFiles/api/api_suggest_post.cpp index 0a8f4ffa36..8734cd8986 100644 --- a/Telegram/SourceFiles/api/api_suggest_post.cpp +++ b/Telegram/SourceFiles/api/api_suggest_post.cpp @@ -11,19 +11,24 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/unixtime.h" #include "core/click_handler_types.h" #include "data/data_session.h" +#include "history/view/history_view_suggest_options.h" #include "history/history.h" #include "history/history_item.h" #include "history/history_item_components.h" +#include "history/history_item_helpers.h" #include "lang/lang_keys.h" #include "main/main_session.h" +#include "mainwindow.h" #include "ui/boxes/choose_date_time.h" #include "ui/layers/generic_box.h" #include "ui/boxes/confirm_box.h" #include "ui/text/text_utilities.h" #include "ui/widgets/fields/input_field.h" +#include "ui/widgets/popup_menu.h" #include "window/window_session_controller.h" #include "styles/style_chat.h" #include "styles/style_layers.h" +#include "styles/style_menu_icons.h" namespace Api { namespace { @@ -116,19 +121,22 @@ void SendDecline( void RequestApprovalDate( not_null controller, not_null item) { + const auto id = item->fullId(); const auto weak = std::make_shared>(); const auto done = [=](TimeId result) { - SendApproval(controller, item, result); + if (const auto item = controller->session().data().message(id)) { + SendApproval(controller, item, result); + } if (const auto strong = weak->data()) { strong->closeBox(); } }; - auto dateBox = Box(Ui::ChooseDateTimeBox, Ui::ChooseDateTimeBoxArgs{ + using namespace HistoryView; + auto dateBox = Box(ChooseSuggestTimeBox, SuggestTimeBoxArgs{ + .session = &controller->session(), .title = tr::lng_suggest_options_date(), .submit = tr::lng_settings_save(), .done = done, - .min = [] { return base::unixtime::now() + 1; }, - .time = (base::unixtime::now() + 86400), }); *weak = dateBox.data(); controller->uiShow()->show(std::move(dateBox)); @@ -177,6 +185,137 @@ void RequestDeclineComment( })); } +struct SendSuggestState { + SendPaymentHelper sendPayment; +}; +void SendSuggest( + not_null controller, + not_null item, + std::shared_ptr state, + Fn modify, + Fn done = nullptr, + int starsApproved = 0) { + const auto suggestion = item->Get(); + if (!suggestion) { + return; + } + const auto id = item->fullId(); + const auto withPaymentApproved = [=](int stars) { + if (const auto item = controller->session().data().message(id)) { + SendSuggest(controller, item, state, modify, done, stars); + } + }; + const auto checked = state->sendPayment.check( + controller->uiShow(), + item->history()->peer, + 1, + starsApproved, + withPaymentApproved); + if (!checked) { + return; + } + const auto isForward = item->Get(); + auto action = SendAction(item->history()); + action.options.suggest.exists = 1; + action.options.suggest.date = suggestion->date; + action.options.suggest.stars = suggestion->stars; + action.options.starsApproved = starsApproved; + action.replyTo.monoforumPeerId = item->history()->amMonoforumAdmin() + ? item->sublistPeerId() + : PeerId(); + action.replyTo.messageId = item->fullId(); + modify(action.options.suggest); + controller->session().api().forwardMessages({ + .items = { item }, + .options = (isForward + ? Data::ForwardOptions::PreserveInfo + : Data::ForwardOptions::NoSenderNames), + }, action); + if (const auto onstack = done) { + onstack(); + } +} + +void SuggestApprovalDate( + not_null controller, + not_null item) { + const auto suggestion = item->Get(); + if (!suggestion) { + return; + } + const auto id = item->fullId(); + const auto state = std::make_shared(); + const auto weak = std::make_shared>(); + const auto done = [=](TimeId result) { + const auto item = controller->session().data().message(id); + if (!item) { + return; + } + const auto close = [=] { + if (const auto strong = weak->data()) { + strong->closeBox(); + } + }; + SendSuggest( + controller, + item, + state, + [=](SuggestPostOptions &options) { options.date = result; }, + close); + }; + using namespace HistoryView; + auto dateBox = Box(ChooseSuggestTimeBox, SuggestTimeBoxArgs{ + .session = &controller->session(), + .title = tr::lng_suggest_menu_edit_time(), + .submit = tr::lng_profile_suggest_button(), + .done = done, + .value = suggestion->date, + }); + *weak = dateBox.data(); + controller->uiShow()->show(std::move(dateBox)); +} + +void SuggestApprovalPrice( + not_null controller, + not_null item) { + const auto suggestion = item->Get(); + if (!suggestion) { + return; + } + const auto id = item->fullId(); + const auto state = std::make_shared(); + const auto weak = std::make_shared>(); + const auto done = [=](SuggestPostOptions result) { + const auto item = controller->session().data().message(id); + if (!item) { + return; + } + const auto close = [=] { + if (const auto strong = weak->data()) { + strong->closeBox(); + } + }; + SendSuggest( + controller, + item, + state, + [=](SuggestPostOptions &options) { options = result; }, + close); + }; + using namespace HistoryView; + auto dateBox = Box(ChooseSuggestPriceBox, SuggestPriceBoxArgs{ + .session = &controller->session(), + .done = done, + .value = { + .exists = true, + .stars = uint32(suggestion->stars), + .date = suggestion->date, + }, + }); + *weak = dateBox.data(); + controller->uiShow()->show(std::move(dateBox)); +} + } // namespace std::shared_ptr AcceptClickHandler( @@ -231,7 +370,23 @@ std::shared_ptr SuggestChangesClickHandler( if (!item) { return; } + const auto menu = Ui::CreateChild( + window->widget(), + st::popupMenuWithIcons); + menu->addAction(tr::lng_suggest_menu_edit_message(tr::now), [=] { + }, &st::menuIconEdit); + menu->addAction(tr::lng_suggest_menu_edit_price(tr::now), [=] { + if (const auto item = session->data().message(id)) { + SuggestApprovalPrice(window, item); + } + }, &st::menuIconTagSell); + menu->addAction(tr::lng_suggest_menu_edit_time(tr::now), [=] { + if (const auto item = session->data().message(id)) { + SuggestApprovalDate(window, item); + } + }, &st::menuIconSchedule); + menu->popup(QCursor::pos()); }); } diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index 7d74812110..d4c72646c3 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -3410,6 +3410,9 @@ void ApiWrap::forwardMessages( if (sendAs) { sendFlags |= SendFlag::f_send_as; } + if (action.options.suggest) { + sendFlags |= SendFlag::f_suggested_post; + } const auto kGeneralId = Data::ForumTopic::kGeneralId; const auto topicRootId = action.replyTo.topicRootId; const auto topMsgId = (topicRootId == kGeneralId) @@ -3422,7 +3425,7 @@ void ApiWrap::forwardMessages( const auto monoforumPeer = monoforumPeerId ? session().data().peer(monoforumPeerId).get() : nullptr; - if (monoforumPeer) { + if (monoforumPeer || (action.options.suggest && action.replyTo)) { sendFlags |= SendFlag::f_reply_to; } @@ -3454,14 +3457,17 @@ void ApiWrap::forwardMessages( MTP_vector(randomIds), peer->input, MTP_int(topMsgId), - (monoforumPeer + (action.options.suggest + ? ReplyToForMTP(history, action.replyTo) + : monoforumPeer ? MTP_inputReplyToMonoForum(monoforumPeer->input) : MTPInputReplyTo()), MTP_int(action.options.scheduled), (sendAs ? sendAs->input : MTP_inputPeerEmpty()), Data::ShortcutIdToMTP(_session, action.options.shortcutId), MTPint(), // video_timestamp - MTP_long(starsPaid) + MTP_long(starsPaid), + Api::SuggestToMTP(action.options.suggest) )).done([=](const MTPUpdates &result) { if (!scheduled) { this->updates().checkForSentToScheduled(result); diff --git a/Telegram/SourceFiles/boxes/share_box.cpp b/Telegram/SourceFiles/boxes/share_box.cpp index 385ea7ea4f..dac3fe5d97 100644 --- a/Telegram/SourceFiles/boxes/share_box.cpp +++ b/Telegram/SourceFiles/boxes/share_box.cpp @@ -1769,7 +1769,8 @@ ShareBox::SubmitCallback ShareBox::DefaultForwardCallback( ? Flag::f_quick_reply_shortcut : Flag(0)) | (starsPaid ? Flag::f_allow_paid_stars : Flag()) - | (sublistPeer ? Flag::f_reply_to : Flag()); + | (sublistPeer ? Flag::f_reply_to : Flag()) + | (options.suggest ? Flag::f_suggested_post : Flag()); threadHistory->sendRequestId = api.request( MTPmessages_ForwardMessages( MTP_flags(sendFlags), @@ -1785,7 +1786,8 @@ ShareBox::SubmitCallback ShareBox::DefaultForwardCallback( MTP_inputPeerEmpty(), // send_as Data::ShortcutIdToMTP(session, options.shortcutId), MTP_int(videoTimestamp.value_or(0)), - MTP_long(starsPaid) + MTP_long(starsPaid), + Api::SuggestToMTP(options.suggest) )).done([=](const MTPUpdates &updates, mtpRequestId reqId) { threadHistory->session().api().applyUpdates(updates); state->requests.remove(reqId); diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 29114bb086..4d251798a9 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -981,7 +981,7 @@ HistoryWidget::HistoryWidget( action.replyTo.messageId); if (action.replaceMediaOf) { } else if (action.options.scheduled) { - cancelReply(lastKeyboardUsed); + cancelReplyOrSuggest(lastKeyboardUsed); crl::on_main(this, [=, history = action.history] { controller->showSection( std::make_shared(history)); @@ -989,7 +989,7 @@ HistoryWidget::HistoryWidget( } else { fastShowAtEnd(action.history); if (!_justMarkingAsRead - && cancelReply(lastKeyboardUsed) + && cancelReplyOrSuggest(lastKeyboardUsed) && !action.clearDraft) { saveCloudDraft(); } @@ -8758,6 +8758,12 @@ bool HistoryWidget::lastForceReplyReplied() const { == FullMsgId(_peer->id, _history->lastKeyboardId)); } +bool HistoryWidget::cancelReplyOrSuggest(bool lastKeyboardUsed) { + const auto ok1 = cancelReply(lastKeyboardUsed); + const auto ok2 = cancelSuggestPost(); + return ok1 || ok2; +} + bool HistoryWidget::cancelReply(bool lastKeyboardUsed) { bool wasReply = false; if (_replyTo) { @@ -8804,7 +8810,7 @@ bool HistoryWidget::cancelReply(bool lastKeyboardUsed) { } void HistoryWidget::cancelReplyAfterMediaSend(bool lastKeyboardUsed) { - if (cancelReply(lastKeyboardUsed)) { + if (cancelReplyOrSuggest(lastKeyboardUsed)) { saveCloudDraft(); } } @@ -8989,7 +8995,7 @@ bool HistoryWidget::updateCanSendMessage() { _canSendMessages = newCanSendMessages; _canSendTexts = newCanSendTexts; if (!_canSendMessages) { - cancelReply(); + cancelReplyOrSuggest(); } refreshSuggestPostToggle(); refreshScheduledToggle(); @@ -9064,8 +9070,9 @@ void HistoryWidget::escape() { } } else if (_autocomplete && !_autocomplete->isHidden()) { _autocomplete->hideAnimated(); - } else if (_replyTo && _field->getTextWithTags().text.isEmpty()) { - cancelReply(); + } else if ((_replyTo || _suggestOptions) + && _field->getTextWithTags().empty()) { + cancelReplyOrSuggest(); } else if (auto &voice = _voiceRecordBar; voice->isActive()) { voice->showDiscardBox(nullptr, anim::type::normal); } else { diff --git a/Telegram/SourceFiles/history/history_widget.h b/Telegram/SourceFiles/history/history_widget.h index e225f5bf41..ac39ce3988 100644 --- a/Telegram/SourceFiles/history/history_widget.h +++ b/Telegram/SourceFiles/history/history_widget.h @@ -218,6 +218,7 @@ public: [[nodiscard]] SuggestPostOptions suggestOptions() const; bool lastForceReplyReplied(const FullMsgId &replyTo) const; bool lastForceReplyReplied() const; + bool cancelReplyOrSuggest(bool lastKeyboardUsed = false); bool cancelReply(bool lastKeyboardUsed = false); bool cancelSuggestPost(); void cancelEdit(); diff --git a/Telegram/SourceFiles/history/view/history_view_element.cpp b/Telegram/SourceFiles/history/view/history_view_element.cpp index 89949f8636..293a4064b9 100644 --- a/Telegram/SourceFiles/history/view/history_view_element.cpp +++ b/Telegram/SourceFiles/history/view/history_view_element.cpp @@ -668,7 +668,9 @@ void ServicePreMessage::paint( const auto top = g.top() - height - st::msgMargin.bottom(); const auto position = QPoint(left, top); p.translate(position); - media->draw(p, context.translated(-position).withSelection({})); + media->draw(p, context.selected() + ? context.translated(-position) + : context.translated(-position).withSelection({})); p.translate(-position); } else { const auto top = g.top() - height - st::msgMargin.top(); diff --git a/Telegram/SourceFiles/history/view/history_view_suggest_options.cpp b/Telegram/SourceFiles/history/view/history_view_suggest_options.cpp index 1996ba2d42..0550266b2b 100644 --- a/Telegram/SourceFiles/history/view/history_view_suggest_options.cpp +++ b/Telegram/SourceFiles/history/view/history_view_suggest_options.cpp @@ -25,23 +25,36 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "styles/style_settings.h" namespace HistoryView { -namespace { -struct EditOptionsArgs { - int starsLimit = 0; - QString channelName; - SuggestPostOptions values; - Fn save; -}; - -void EditOptionsBox( +void ChooseSuggestTimeBox( not_null box, - EditOptionsArgs &&args) { + SuggestTimeBoxArgs &&args) { + const auto now = base::unixtime::now(); + const auto min = args.session->appConfig().suggestedPostDelayMin() + 60; + const auto max = args.session->appConfig().suggestedPostDelayMax(); + const auto value = args.value + ? std::clamp(args.value, now + min, now + max) + : (now + 86400); + Ui::ChooseDateTimeBox(box, { + .title = std::move(args.title), + .submit = std::move(args.submit), + .done = std::move(args.done), + .min = [=] { return now + min; }, + .time = value, + .max = [=] { return now + max; }, + }); +} + +void ChooseSuggestPriceBox( + not_null box, + SuggestPriceBoxArgs &&args) { struct State { rpl::variable date; }; const auto state = box->lifetime().make_state(); - state->date = args.values.date; + state->date = args.value.date; + + const auto limit = args.session->appConfig().suggestedPostStarsMax(); box->setTitle(tr::lng_suggest_options_title()); @@ -57,8 +70,8 @@ void EditOptionsBox( wrap, st::editTagField, tr::lng_paid_cost_placeholder(), - args.values.stars ? QString::number(args.values.stars) : QString(), - args.starsLimit); + args.value.stars ? QString::number(args.value.stars) : QString(), + limit); const auto field = owned.data(); wrap->widthValue() | rpl::start_with_next([=](int width) { field->move(0, 0); @@ -102,14 +115,12 @@ void EditOptionsBox( strong->closeBox(); } }; - auto dateBox = Box(Ui::ChooseDateTimeBox, Ui::ChooseDateTimeBoxArgs{ + auto dateBox = Box(ChooseSuggestTimeBox, SuggestTimeBoxArgs{ + .session = args.session, .title = tr::lng_suggest_options_date(), .submit = tr::lng_settings_save(), .done = done, - .min = [] { return base::unixtime::now() + 1; }, - .time = (state->date.current() - ? state->date.current() - : (base::unixtime::now() + 86400)), + .value = state->date.current(), }); *weak = dateBox.data(); box->uiShow()->show(std::move(dateBox)); @@ -120,15 +131,15 @@ void EditOptionsBox( AssertIsDebug()//tr::lng_suggest_options_offer const auto save = [=] { const auto now = uint32(field->getLastText().toULongLong()); - if (now > args.starsLimit) { + if (now > limit) { field->showError(); return; } - const auto weak = Ui::MakeWeak(box); - args.save({ .stars = now, .date = state->date.current()}); - if (const auto strong = weak.data()) { - strong->closeBox(); - } + args.done({ + .exists = true, + .stars = now, + .date = state->date.current(), + }); }; QObject::connect(field, &Ui::NumberInput::submitted, box, save); @@ -139,8 +150,6 @@ void EditOptionsBox( }); } -} // namespace - SuggestOptions::SuggestOptions( not_null controller, not_null peer, @@ -179,18 +188,19 @@ void SuggestOptions::paintBar(QPainter &p, int x, int y, int outerWidth) { } void SuggestOptions::edit() { + const auto weak = std::make_shared>(); const auto apply = [=](SuggestPostOptions values) { _values = values; updateTexts(); _updates.fire({}); + if (const auto strong = weak->data()) { + strong->closeBox(); + } }; - const auto broadcast = _peer->monoforumBroadcast(); - const auto &appConfig = _peer->session().appConfig(); - _controller->show(Box(EditOptionsBox, EditOptionsArgs{ - .starsLimit = appConfig.suggestedPostStarsMax(), - .channelName = (broadcast ? broadcast : _peer.get())->shortName(), - .values = _values, - .save = apply, + *weak = _controller->show(Box(ChooseSuggestPriceBox, SuggestPriceBoxArgs{ + .session = &_peer->session(), + .done = apply, + .value = _values, })); } diff --git a/Telegram/SourceFiles/history/view/history_view_suggest_options.h b/Telegram/SourceFiles/history/view/history_view_suggest_options.h index 8c5ef1ae41..c326696d6b 100644 --- a/Telegram/SourceFiles/history/view/history_view_suggest_options.h +++ b/Telegram/SourceFiles/history/view/history_view_suggest_options.h @@ -9,12 +9,41 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "api/api_common.h" +namespace Ui { +class GenericBox; +} // namespace Ui + +namespace Main { +class Session; +} // namespace Main + namespace Window { class SessionController; } // namespace Window namespace HistoryView { +struct SuggestTimeBoxArgs { + not_null session; + rpl::producer title; + rpl::producer submit; + Fn done; + TimeId value = 0; +}; +void ChooseSuggestTimeBox( + not_null box, + SuggestTimeBoxArgs &&args); + +struct SuggestPriceBoxArgs { + not_null session; + bool updating = false; + Fn done; + SuggestPostOptions value; +}; +void ChooseSuggestPriceBox( + not_null box, + SuggestPriceBoxArgs &&args); + class SuggestOptions final { public: SuggestOptions( diff --git a/Telegram/SourceFiles/history/view/media/history_view_media_generic.cpp b/Telegram/SourceFiles/history/view/media/history_view_media_generic.cpp index f0991f8f95..cacaf4f59c 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_media_generic.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_media_generic.cpp @@ -134,7 +134,12 @@ void MediaGeneric::draw(Painter &p, const PaintContext &context) const { const auto radius = st::msgServiceGiftBoxRadius; p.setPen(Qt::NoPen); p.setBrush(context.st->msgServiceBg()); - p.drawRoundedRect(QRect(0, 0, width(), height()), radius, radius); + const auto rect = QRect(0, 0, width(), height()); + p.drawRoundedRect(rect, radius, radius); + //if (context.selected()) { + // p.setBrush(context.st->serviceTextPalette().selectBg); + // p.drawRoundedRect(rect, radius, radius); + //} } auto translated = 0; diff --git a/Telegram/SourceFiles/main/main_app_config.cpp b/Telegram/SourceFiles/main/main_app_config.cpp index 1adcc5a856..3b9c79ea26 100644 --- a/Telegram/SourceFiles/main/main_app_config.cpp +++ b/Telegram/SourceFiles/main/main_app_config.cpp @@ -166,6 +166,14 @@ int AppConfig::suggestedPostStarsMax() const { return get(u"stars_suggested_post_amount_max"_q, 100'000); } +int AppConfig::suggestedPostDelayMin() const { + return get(u"stars_suggested_post_future_min"_q, 300); +} + +int AppConfig::suggestedPostDelayMax() const { + return get(u"appConfig.stars_suggested_post_future_max"_q, 2678400); +} + void AppConfig::refresh(bool force) { if (_requestId || !_api) { if (force) { diff --git a/Telegram/SourceFiles/main/main_app_config.h b/Telegram/SourceFiles/main/main_app_config.h index 886e11280c..0d9a4f6fbc 100644 --- a/Telegram/SourceFiles/main/main_app_config.h +++ b/Telegram/SourceFiles/main/main_app_config.h @@ -89,6 +89,8 @@ public: [[nodiscard]] int todoListItemTextLimit() const; [[nodiscard]] int suggestedPostStarsMax() const; + [[nodiscard]] int suggestedPostDelayMin() const; + [[nodiscard]] int suggestedPostDelayMax() const; void refresh(bool force = false); diff --git a/Telegram/SourceFiles/mtproto/scheme/api.tl b/Telegram/SourceFiles/mtproto/scheme/api.tl index 1b9bc0a06f..22fd24059c 100644 --- a/Telegram/SourceFiles/mtproto/scheme/api.tl +++ b/Telegram/SourceFiles/mtproto/scheme/api.tl @@ -2194,7 +2194,7 @@ messages.receivedMessages#5a954c0 max_id:int = Vector; messages.setTyping#58943ee2 flags:# peer:InputPeer top_msg_id:flags.0?int action:SendMessageAction = Bool; messages.sendMessage#fe05dc9a flags:# no_webpage:flags.1?true silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true update_stickersets_order:flags.15?true invert_media:flags.16?true allow_paid_floodskip:flags.19?true peer:InputPeer reply_to:flags.0?InputReplyTo message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut effect:flags.18?long allow_paid_stars:flags.21?long suggested_post:flags.22?SuggestedPost = Updates; messages.sendMedia#ac55d9c1 flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true update_stickersets_order:flags.15?true invert_media:flags.16?true allow_paid_floodskip:flags.19?true peer:InputPeer reply_to:flags.0?InputReplyTo media:InputMedia message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut effect:flags.18?long allow_paid_stars:flags.21?long suggested_post:flags.22?SuggestedPost = Updates; -messages.forwardMessages#38f0188c flags:# silent:flags.5?true background:flags.6?true with_my_score:flags.8?true drop_author:flags.11?true drop_media_captions:flags.12?true noforwards:flags.14?true allow_paid_floodskip:flags.19?true from_peer:InputPeer id:Vector random_id:Vector to_peer:InputPeer top_msg_id:flags.9?int reply_to:flags.22?InputReplyTo schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut video_timestamp:flags.20?int allow_paid_stars:flags.21?long = Updates; +messages.forwardMessages#978928ca flags:# silent:flags.5?true background:flags.6?true with_my_score:flags.8?true drop_author:flags.11?true drop_media_captions:flags.12?true noforwards:flags.14?true allow_paid_floodskip:flags.19?true from_peer:InputPeer id:Vector random_id:Vector to_peer:InputPeer top_msg_id:flags.9?int reply_to:flags.22?InputReplyTo schedule_date:flags.10?int send_as:flags.13?InputPeer quick_reply_shortcut:flags.17?InputQuickReplyShortcut video_timestamp:flags.20?int allow_paid_stars:flags.21?long suggested_post:flags.23?SuggestedPost = Updates; messages.reportSpam#cf1592db peer:InputPeer = Bool; messages.getPeerSettings#efd9a6a2 peer:InputPeer = messages.PeerSettings; messages.report#fc78af9b peer:InputPeer id:Vector option:bytes message:string = ReportResult;