Update API scheme, improve service messages.

This commit is contained in:
John Preston 2025-02-20 12:22:20 +04:00
parent e302f328f7
commit 3633c19208
15 changed files with 253 additions and 155 deletions

View file

@ -2166,12 +2166,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_action_boost_apply#other" = "{from} boosted the group {count} times"; "lng_action_boost_apply#other" = "{from} boosted the group {count} times";
"lng_action_set_chat_intro" = "{from} added the message below for all empty chats. How?"; "lng_action_set_chat_intro" = "{from} added the message below for all empty chats. How?";
"lng_action_payment_refunded" = "{peer} refunded {amount}"; "lng_action_payment_refunded" = "{peer} refunded {amount}";
"lng_action_paid_message_sent#one" = "You paid {count} Star to send a message"; "lng_action_paid_message_sent#one" = "You paid {count} Star to {action}";
"lng_action_paid_message_sent#other" = "You paid {count} Stars to send a message"; "lng_action_paid_message_sent#other" = "You paid {count} Star to {action}";
"lng_action_paid_message_group#one" = "{from} paid {count} Star to {action}";
"lng_action_paid_message_group#other" = "{from} paid {count} Star to {action}";
"lng_action_paid_message_one" = "send a message";
"lng_action_paid_message_some#one" = "send {count} message";
"lng_action_paid_message_some#other" = "send {count} messages";
"lng_action_paid_message_got#one" = "You received {count} Star from {name}"; "lng_action_paid_message_got#one" = "You received {count} Star from {name}";
"lng_action_paid_message_got#other" = "You received {count} Stars from {name}"; "lng_action_paid_message_got#other" = "You received {count} Stars from {name}";
"lng_action_paid_message_group#one" = "{from} paid {count} Star to send a message";
"lng_action_paid_message_group#other" = "{from} paid {count} Stars to send a message";
"lng_similar_channels_title" = "Similar channels"; "lng_similar_channels_title" = "Similar channels";
"lng_similar_channels_view_all" = "View all"; "lng_similar_channels_view_all" = "View all";

View file

@ -634,7 +634,9 @@ void SendConfirmedFile(
.replyTo = file->to.replyTo, .replyTo = file->to.replyTo,
.date = NewMessageDate(file->to.options), .date = NewMessageDate(file->to.options),
.shortcutId = file->to.options.shortcutId, .shortcutId = file->to.options.shortcutId,
.starsPaid = file->to.options.starsApproved, .starsPaid = std::min(
history->peer->starsPerMessageChecked(),
file->to.options.starsApproved),
.postAuthor = NewMessagePostAuthor(action), .postAuthor = NewMessagePostAuthor(action),
.groupedId = groupId, .groupedId = groupId,
.effectId = file->to.options.effectId, .effectId = file->to.options.effectId,

View file

@ -4481,7 +4481,7 @@ void ApiWrap::sendAlbumIfReady(not_null<SendingAlbum*> album) {
const auto replyTo = sample->replyTo(); const auto replyTo = sample->replyTo();
const auto sendAs = album->options.sendAs; const auto sendAs = album->options.sendAs;
const auto starsPaid = std::min( const auto starsPaid = std::min(
history->peer->starsPerMessageChecked(), history->peer->starsPerMessageChecked() * int(medias.size()),
album->options.starsApproved); album->options.starsApproved);
if (starsPaid) { if (starsPaid) {
album->options.starsApproved -= starsPaid; album->options.starsApproved -= starsPaid;

View file

@ -17,14 +17,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_user.h" #include "data/data_user.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "settings/settings_credits_graphics.h"
#include "storage/storage_account.h"
#include "ui/boxes/confirm_box.h" #include "ui/boxes/confirm_box.h"
#include "ui/chat/attach/attach_prepare.h" #include "ui/chat/attach/attach_prepare.h"
#include "ui/layers/generic_box.h" #include "ui/layers/generic_box.h"
#include "ui/text/text_utilities.h" #include "ui/text/text_utilities.h"
#include "ui/toast/toast.h" #include "ui/toast/toast.h"
#include "ui/widgets/checkbox.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "styles/style_widgets.h" #include "styles/style_widgets.h"
@ -431,85 +428,4 @@ void ShowSendErrorToast(
}); });
} }
void ShowSendPaidConfirm(
not_null<Window::SessionNavigation*> navigation,
not_null<PeerData*> peer,
SendError error,
Fn<void()> confirmed) {
return ShowSendPaidConfirm(navigation->uiShow(), peer, error, confirmed);
}
void ShowSendPaidConfirm(
std::shared_ptr<ChatHelpers::Show> show,
not_null<PeerData*> peer,
Data::SendError error,
Fn<void()> confirmed) {
const auto check = [=] {
const auto required = error.paidStars;
if (!required) {
return;
}
const auto done = [=](Settings::SmallBalanceResult result) {
if (result == Settings::SmallBalanceResult::Success
|| result == Settings::SmallBalanceResult::Already) {
confirmed();
}
};
Settings::MaybeRequestBalanceIncrease(
show,
required,
Settings::SmallBalanceForMessage{ .recipientId = peer->id },
done);
};
const auto session = &peer->session();
if (session->local().isPeerTrustedPayForMessage(peer->id)) {
check();
return;
}
const auto messages = error.paidMessages;
const auto stars = error.paidStars;
show->showBox(Box([=](not_null<Ui::GenericBox*> box) {
const auto trust = std::make_shared<QPointer<Ui::Checkbox>>();
const auto proceed = [=](Fn<void()> close) {
if ((*trust)->checked()) {
session->local().markPeerTrustedPayForMessage(peer->id);
}
check();
close();
};
Ui::ConfirmBox(box, {
.text = tr::lng_payment_confirm_text(
tr::now,
lt_count,
stars / messages,
lt_name,
Ui::Text::Bold(peer->shortName()),
Ui::Text::RichLangValue).append(' ').append(
tr::lng_payment_confirm_sure(
tr::now,
lt_count,
messages,
lt_amount,
tr::lng_payment_confirm_amount(
tr::now,
lt_count,
stars,
Ui::Text::RichLangValue),
Ui::Text::RichLangValue)),
.confirmed = proceed,
.confirmText = tr::lng_payment_confirm_button(
lt_count,
rpl::single(messages * 1.)),
.title = tr::lng_payment_confirm_title(),
});
const auto skip = st::defaultCheckbox.margin.top();
*trust = box->addRow(
object_ptr<Ui::Checkbox>(
box,
tr::lng_payment_confirm_dont_ask(tr::now)),
st::boxRowPadding + QMargins(0, skip, 0, skip));
}));
}
} // namespace Data } // namespace Data

View file

@ -244,15 +244,4 @@ void ShowSendErrorToast(
not_null<PeerData*> peer, not_null<PeerData*> peer,
SendError error); SendError error);
void ShowSendPaidConfirm(
not_null<Window::SessionNavigation*> navigation,
not_null<PeerData*> peer,
SendError error,
Fn<void()> confirmed);
void ShowSendPaidConfirm(
std::shared_ptr<ChatHelpers::Show> show,
not_null<PeerData*> peer,
SendError error,
Fn<void()> confirmed);
} // namespace Data } // namespace Data

View file

@ -38,10 +38,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/unixtime.h" #include "base/unixtime.h"
#include "core/application.h" #include "core/application.h"
#include "core/click_handler_types.h" // ClickHandlerContext. #include "core/click_handler_types.h" // ClickHandlerContext.
#include "settings/settings_credits_graphics.h"
#include "storage/storage_account.h"
#include "ui/boxes/confirm_box.h" #include "ui/boxes/confirm_box.h"
#include "ui/text/format_values.h" #include "ui/text/format_values.h"
#include "ui/text/text_utilities.h" #include "ui/text/text_utilities.h"
#include "ui/toast/toast.h" #include "ui/toast/toast.h"
#include "ui/widgets/checkbox.h"
#include "ui/item_text_options.h" #include "ui/item_text_options.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
@ -242,6 +245,91 @@ object_ptr<Ui::BoxContent> MakeSendErrorBox(
}); });
} }
void ShowSendPaidConfirm(
not_null<Window::SessionNavigation*> navigation,
not_null<PeerData*> peer,
SendPaymentDetails details,
Fn<void()> confirmed) {
return ShowSendPaidConfirm(
navigation->uiShow(),
peer,
details,
confirmed);
}
void ShowSendPaidConfirm(
std::shared_ptr<ChatHelpers::Show> show,
not_null<PeerData*> peer,
SendPaymentDetails details,
Fn<void()> confirmed) {
const auto check = [=] {
const auto required = details.stars;
if (!required) {
return;
}
const auto done = [=](Settings::SmallBalanceResult result) {
if (result == Settings::SmallBalanceResult::Success
|| result == Settings::SmallBalanceResult::Already) {
confirmed();
}
};
Settings::MaybeRequestBalanceIncrease(
show,
required,
Settings::SmallBalanceForMessage{ .recipientId = peer->id },
done);
};
const auto session = &peer->session();
if (session->local().isPeerTrustedPayForMessage(peer->id)) {
check();
return;
}
const auto messages = details.messages;
const auto stars = details.stars;
show->showBox(Box([=](not_null<Ui::GenericBox*> box) {
const auto trust = std::make_shared<QPointer<Ui::Checkbox>>();
const auto proceed = [=](Fn<void()> close) {
if ((*trust)->checked()) {
session->local().markPeerTrustedPayForMessage(peer->id);
}
check();
close();
};
Ui::ConfirmBox(box, {
.text = tr::lng_payment_confirm_text(
tr::now,
lt_count,
stars / messages,
lt_name,
Ui::Text::Bold(peer->shortName()),
Ui::Text::RichLangValue).append(' ').append(
tr::lng_payment_confirm_sure(
tr::now,
lt_count,
messages,
lt_amount,
tr::lng_payment_confirm_amount(
tr::now,
lt_count,
stars,
Ui::Text::RichLangValue),
Ui::Text::RichLangValue)),
.confirmed = proceed,
.confirmText = tr::lng_payment_confirm_button(
lt_count,
rpl::single(messages * 1.)),
.title = tr::lng_payment_confirm_title(),
});
const auto skip = st::defaultCheckbox.margin.top();
*trust = box->addRow(
object_ptr<Ui::Checkbox>(
box,
tr::lng_payment_confirm_dont_ask(tr::now)),
st::boxRowPadding + QMargins(0, skip, 0, skip));
}));
}
void RequestDependentMessageItem( void RequestDependentMessageItem(
not_null<HistoryItem*> item, not_null<HistoryItem*> item,
PeerId peerId, PeerId peerId,

View file

@ -16,6 +16,10 @@ struct SendOptions;
struct SendAction; struct SendAction;
} // namespace Api } // namespace Api
namespace ChatHelpers {
class Show;
} // namespace ChatHelpers
namespace Data { namespace Data {
class Story; class Story;
class Thread; class Thread;
@ -31,6 +35,10 @@ namespace Ui {
class BoxContent; class BoxContent;
} // namespace Ui } // namespace Ui
namespace Window {
class SessionNavigation;
} // namespace Window
struct PreparedServiceText { struct PreparedServiceText {
TextWithEntities text; TextWithEntities text;
std::vector<ClickHandlerPtr> links; std::vector<ClickHandlerPtr> links;
@ -135,6 +143,17 @@ struct SendPaymentDetails {
not_null<PeerData*> peer, not_null<PeerData*> peer,
int messagesCount); int messagesCount);
void ShowSendPaidConfirm(
not_null<Window::SessionNavigation*> navigation,
not_null<PeerData*> peer,
SendPaymentDetails details,
Fn<void()> confirmed);
void ShowSendPaidConfirm(
std::shared_ptr<ChatHelpers::Show> show,
not_null<PeerData*> peer,
SendPaymentDetails details,
Fn<void()> confirmed);
[[nodiscard]] Data::SendErrorWithThread GetErrorForSending( [[nodiscard]] Data::SendErrorWithThread GetErrorForSending(
const std::vector<not_null<Data::Thread*>> &threads, const std::vector<not_null<Data::Thread*>> &threads,
SendingErrorRequest request); SendingErrorRequest request);

View file

@ -225,6 +225,14 @@ const auto kPsaAboutPrefix = "cloud_lng_about_psa_";
} // namespace } // namespace
struct HistoryWidget::SendingFiles {
Ui::PreparedList list;
Ui::SendFilesWay way;
TextWithTags caption;
Api::SendOptions options;
bool ctrlShiftEnter = false;
};
HistoryWidget::HistoryWidget( HistoryWidget::HistoryWidget(
QWidget *parent, QWidget *parent,
not_null<Window::SessionController*> controller) not_null<Window::SessionController*> controller)
@ -5896,8 +5904,7 @@ bool HistoryWidget::showSendMessageError(
const TextWithTags &textWithTags, const TextWithTags &textWithTags,
bool ignoreSlowmodeCountdown, bool ignoreSlowmodeCountdown,
Fn<void(int starsApproved)> resend, Fn<void(int starsApproved)> resend,
int starsApproved, int starsApproved) {
bool mediaMessage) {
if (!_canSendMessages) { if (!_canSendMessages) {
return false; return false;
} }
@ -5908,8 +5915,7 @@ bool HistoryWidget::showSendMessageError(
.text = &textWithTags, .text = &textWithTags,
.ignoreSlowmodeCountdown = ignoreSlowmodeCountdown, .ignoreSlowmodeCountdown = ignoreSlowmodeCountdown,
}; };
request.messagesCount = ComputeSendingMessagesCount(_history, request) request.messagesCount = ComputeSendingMessagesCount(_history, request);
+ (mediaMessage ? 1 : 0);
const auto error = GetErrorForSending(_peer, request); const auto error = GetErrorForSending(_peer, request);
if (error) { if (error) {
Data::ShowSendErrorToast(controller(), _peer, error); Data::ShowSendErrorToast(controller(), _peer, error);
@ -5926,14 +5932,14 @@ bool HistoryWidget::checkSendPayment(
const auto details = ComputePaymentDetails(_peer, messagesCount); const auto details = ComputePaymentDetails(_peer, messagesCount);
if (!details) { if (!details) {
_resendOnFullUpdated = [=] { resend(starsApproved); }; _resendOnFullUpdated = [=] { resend(starsApproved); };
return true; return false;
} else if (const auto stars = details->stars) { } else if (const auto stars = details->stars; stars > starsApproved) {
Data::ShowSendPaidConfirm(controller(), _peer, error, [=] { ShowSendPaidConfirm(controller(), _peer, *details, [=] {
resend(stars); resend(stars);
}); });
return true; return false;
} }
return false; return true;
} }
bool HistoryWidget::confirmSendingFiles(const QStringList &files) { bool HistoryWidget::confirmSendingFiles(const QStringList &files) {
@ -6019,28 +6025,53 @@ bool HistoryWidget::confirmSendingFiles(
} }
void HistoryWidget::sendingFilesConfirmed( void HistoryWidget::sendingFilesConfirmed(
Ui::PreparedList &&list, Ui::PreparedList &&list,
Ui::SendFilesWay way, Ui::SendFilesWay way,
TextWithTags &&caption, TextWithTags &&caption,
Api::SendOptions options, Api::SendOptions options,
bool ctrlShiftEnter) { bool ctrlShiftEnter) {
Expects(list.filesToProcess.empty()); Expects(list.filesToProcess.empty());
const auto compress = way.sendImagesAsPhotos(); const auto compress = way.sendImagesAsPhotos();
if (showSendingFilesError(list, compress)) { if (showSendingFilesError(list, compress)) {
return; return;
} }
sendingFilesConfirmed(std::make_shared<SendingFiles>(SendingFiles{
.list = std::move(list),
.way = way,
.caption = std::move(caption),
.options = options,
.ctrlShiftEnter = ctrlShiftEnter,
}));
}
void HistoryWidget::sendingFilesConfirmed(
std::shared_ptr<SendingFiles> args) {
const auto withPaymentApproved = [=](int approved) {
args->options.starsApproved = approved;
sendingFilesConfirmed(args);
};
const auto checked = checkSendPayment(
args->list.files.size(),
args->options.starsApproved,
withPaymentApproved);
if (!checked) {
return;
}
auto groups = DivideByGroups( auto groups = DivideByGroups(
std::move(list), std::move(args->list),
way, args->way,
_peer->slowmodeApplied()); _peer->slowmodeApplied());
const auto compress = args->way.sendImagesAsPhotos();
const auto type = compress ? SendMediaType::Photo : SendMediaType::File; const auto type = compress ? SendMediaType::Photo : SendMediaType::File;
auto action = prepareSendAction(options); auto action = prepareSendAction(args->options);
action.clearDraft = false; action.clearDraft = false;
if ((groups.size() != 1 || !groups.front().sentWithCaption()) if ((groups.size() != 1 || !groups.front().sentWithCaption())
&& !caption.text.isEmpty()) { && !args->caption.text.isEmpty()) {
auto message = Api::MessageToSend(action); auto message = Api::MessageToSend(action);
message.textWithTags = base::take(caption); message.textWithTags = base::take(args->caption);
session().api().sendMessage(std::move(message)); session().api().sendMessage(std::move(message));
} }
for (auto &group : groups) { for (auto &group : groups) {
@ -6050,7 +6081,7 @@ void HistoryWidget::sendingFilesConfirmed(
session().api().sendFiles( session().api().sendFiles(
std::move(group.list), std::move(group.list),
type, type,
base::take(caption), base::take(args->caption),
album, album,
action); action);
} }

View file

@ -320,6 +320,7 @@ private:
using TabbedPanel = ChatHelpers::TabbedPanel; using TabbedPanel = ChatHelpers::TabbedPanel;
using TabbedSelector = ChatHelpers::TabbedSelector; using TabbedSelector = ChatHelpers::TabbedSelector;
using VoiceToSend = HistoryView::Controls::VoiceToSend; using VoiceToSend = HistoryView::Controls::VoiceToSend;
struct SendingFiles;
enum ScrollChangeType { enum ScrollChangeType {
ScrollChangeNone, ScrollChangeNone,
@ -472,8 +473,7 @@ private:
const TextWithTags &textWithTags, const TextWithTags &textWithTags,
bool ignoreSlowmodeCountdown, bool ignoreSlowmodeCountdown,
Fn<void(int starsApproved)> resend = nullptr, Fn<void(int starsApproved)> resend = nullptr,
int starsApproved = 0, int starsApproved = 0);
bool mediaMessage = false);
bool checkSendPayment( bool checkSendPayment(
int messagesCount, int messagesCount,
int starsApproved, int starsApproved,
@ -485,6 +485,7 @@ private:
TextWithTags &&caption, TextWithTags &&caption,
Api::SendOptions options, Api::SendOptions options,
bool ctrlShiftEnter); bool ctrlShiftEnter);
void sendingFilesConfirmed(std::shared_ptr<SendingFiles> args);
void uploadFile(const QByteArray &fileContent, SendMediaType type); void uploadFile(const QByteArray &fileContent, SendMediaType type);
void itemRemoved(not_null<const HistoryItem*> item); void itemRemoved(not_null<const HistoryItem*> item);

View file

@ -431,35 +431,7 @@ Message::Message(
_rightAction->second->link = ReportSponsoredClickHandler(data); _rightAction->second->link = ReportSponsoredClickHandler(data);
} }
} }
if (const auto stars = data->starsPaid()) { initPaidInformation();
auto text = PreparedServiceText{
.text = data->out()
? tr::lng_action_paid_message_sent(
tr::now,
lt_count,
stars,
Ui::Text::WithEntities)
: history()->peer->isUser()
? tr::lng_action_paid_message_got(
tr::now,
lt_count,
stars,
lt_name,
Ui::Text::Link(data->from()->shortName(), 1),
Ui::Text::WithEntities)
: tr::lng_action_paid_message_group(
tr::now,
lt_count,
stars,
lt_from,
Ui::Text::Link(data->from()->shortName(), 1),
Ui::Text::WithEntities),
};
if (!data->out()) {
text.links.push_back(data->from()->createOpenLink());
}
setServicePreMessage(std::move(text));
}
} }
Message::~Message() { Message::~Message() {
@ -470,6 +442,61 @@ Message::~Message() {
} }
} }
void Message::initPaidInformation() {
const auto item = data();
const auto media = this->media();
const auto mine = PaidInformation{
.messages = 1,
.stars = item->starsPaid(),
};
auto info = media ? media->paidInformation().value_or(mine) : mine;
if (!info) {
return;
}
const auto action = [&] {
return (info.messages == 1)
? tr::lng_action_paid_message_one(
tr::now,
Ui::Text::WithEntities)
: tr::lng_action_paid_message_some(
tr::now,
lt_count,
info.messages,
Ui::Text::WithEntities);
};
auto text = PreparedServiceText{
.text = item->out()
? tr::lng_action_paid_message_sent(
tr::now,
lt_count,
info.stars,
lt_action,
action(),
Ui::Text::WithEntities)
: history()->peer->isUser()
? tr::lng_action_paid_message_got(
tr::now,
lt_count,
info.stars,
lt_name,
Ui::Text::Link(item->from()->shortName(), 1),
Ui::Text::WithEntities)
: tr::lng_action_paid_message_group(
tr::now,
lt_count,
info.stars,
lt_from,
Ui::Text::Link(item->from()->shortName(), 1),
lt_action,
action(),
Ui::Text::WithEntities),
};
if (!item->out()) {
text.links.push_back(item ->from()->createOpenLink());
}
setServicePreMessage(std::move(text));
}
void Message::refreshRightBadge() { void Message::refreshRightBadge() {
const auto item = data(); const auto item = data();
const auto text = [&] { const auto text = [&] {

View file

@ -178,6 +178,7 @@ private:
bool updateBottomInfo(); bool updateBottomInfo();
void initPaidInformation();
void initLogEntryOriginal(); void initLogEntryOriginal();
void initPsa(); void initPsa();
void fromNameUpdated(int width) const; void fromNameUpdated(int width) const;

View file

@ -78,6 +78,15 @@ enum class MediaInBubbleState : uchar {
TimeId duration, TimeId duration,
const QString &base); const QString &base);
struct PaidInformation {
int messages = 0;
int stars = 0;
explicit operator bool() const {
return stars != 0;
}
};
class Media : public Object, public base::has_weak_ptr { class Media : public Object, public base::has_weak_ptr {
public: public:
explicit Media(not_null<Element*> parent) : _parent(parent) { explicit Media(not_null<Element*> parent) : _parent(parent) {
@ -121,6 +130,10 @@ public:
[[nodiscard]] virtual bool allowsFastShare() const { [[nodiscard]] virtual bool allowsFastShare() const {
return false; return false;
} }
[[nodiscard]] virtual auto paidInformation() const
-> std::optional<PaidInformation> {
return {};
}
virtual void refreshParentId(not_null<HistoryItem*> realParent) { virtual void refreshParentId(not_null<HistoryItem*> realParent) {
} }
virtual void drawHighlight( virtual void drawHighlight(

View file

@ -867,6 +867,15 @@ QPoint GroupedMedia::resolveCustomInfoRightBottom() const {
return QPoint(width() - skipx, height() - skipy); return QPoint(width() - skipx, height() - skipy);
} }
std::optional<PaidInformation> GroupedMedia::paidInformation() const {
auto result = PaidInformation();
for (const auto &part : _parts) {
++result.messages;
result.stars += part.item->starsPaid();
}
return result;
}
bool GroupedMedia::enforceBubbleWidth() const { bool GroupedMedia::enforceBubbleWidth() const {
return _mode == Mode::Grid; return _mode == Mode::Grid;
} }

View file

@ -93,6 +93,7 @@ public:
bool allowsFastShare() const override { bool allowsFastShare() const override {
return true; return true;
} }
std::optional<PaidInformation> paidInformation() const override;
bool customHighlight() const override { bool customHighlight() const override {
return true; return true;
} }

View file

@ -236,7 +236,7 @@ inputReportReasonFake#f5ddd6e7 = ReportReason;
inputReportReasonIllegalDrugs#a8eb2be = ReportReason; inputReportReasonIllegalDrugs#a8eb2be = ReportReason;
inputReportReasonPersonalDetails#9ec7863d = ReportReason; inputReportReasonPersonalDetails#9ec7863d = ReportReason;
userFull#8555f3c2 flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true can_pin_message:flags.7?true has_scheduled:flags.12?true video_calls_available:flags.13?true voice_messages_forbidden:flags.20?true translations_disabled:flags.23?true stories_pinned_available:flags.26?true blocked_my_stories_from:flags.27?true wallpaper_overridden:flags.28?true contact_require_premium:flags.29?true read_dates_private:flags.30?true flags2:# sponsored_enabled:flags2.7?true can_view_revenue:flags2.9?true bot_can_manage_emoji_status:flags2.10?true id:long about:flags.1?string settings:PeerSettings personal_photo:flags.21?Photo profile_photo:flags.2?Photo fallback_photo:flags.22?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo pinned_msg_id:flags.6?int common_chats_count:int folder_id:flags.11?int ttl_period:flags.14?int theme_emoticon:flags.15?string private_forward_name:flags.16?string bot_group_admin_rights:flags.17?ChatAdminRights bot_broadcast_admin_rights:flags.18?ChatAdminRights premium_gifts:flags.19?Vector<PremiumGiftOption> wallpaper:flags.24?WallPaper stories:flags.25?PeerStories business_work_hours:flags2.0?BusinessWorkHours business_location:flags2.1?BusinessLocation business_greeting_message:flags2.2?BusinessGreetingMessage business_away_message:flags2.3?BusinessAwayMessage business_intro:flags2.4?BusinessIntro birthday:flags2.5?Birthday personal_channel_id:flags2.6?long personal_channel_message:flags2.6?int stargifts_count:flags2.8?int starref_program:flags2.11?StarRefProgram bot_verification:flags2.12?BotVerification send_paid_messages_stars:flags2.14?long = UserFull; userFull#d2234ea0 flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true can_pin_message:flags.7?true has_scheduled:flags.12?true video_calls_available:flags.13?true voice_messages_forbidden:flags.20?true translations_disabled:flags.23?true stories_pinned_available:flags.26?true blocked_my_stories_from:flags.27?true wallpaper_overridden:flags.28?true contact_require_premium:flags.29?true read_dates_private:flags.30?true flags2:# sponsored_enabled:flags2.7?true can_view_revenue:flags2.9?true bot_can_manage_emoji_status:flags2.10?true id:long about:flags.1?string settings:PeerSettings personal_photo:flags.21?Photo profile_photo:flags.2?Photo fallback_photo:flags.22?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo pinned_msg_id:flags.6?int common_chats_count:int folder_id:flags.11?int ttl_period:flags.14?int theme_emoticon:flags.15?string private_forward_name:flags.16?string bot_group_admin_rights:flags.17?ChatAdminRights bot_broadcast_admin_rights:flags.18?ChatAdminRights wallpaper:flags.24?WallPaper stories:flags.25?PeerStories business_work_hours:flags2.0?BusinessWorkHours business_location:flags2.1?BusinessLocation business_greeting_message:flags2.2?BusinessGreetingMessage business_away_message:flags2.3?BusinessAwayMessage business_intro:flags2.4?BusinessIntro birthday:flags2.5?Birthday personal_channel_id:flags2.6?long personal_channel_message:flags2.6?int stargifts_count:flags2.8?int starref_program:flags2.11?StarRefProgram bot_verification:flags2.12?BotVerification send_paid_messages_stars:flags2.14?long = UserFull;
contact#145ade0b user_id:long mutual:Bool = Contact; contact#145ade0b user_id:long mutual:Bool = Contact;
@ -1496,8 +1496,6 @@ inputStorePaymentStarsTopup#dddd0f56 stars:long currency:string amount:long = In
inputStorePaymentStarsGift#1d741ef7 user_id:InputUser stars:long currency:string amount:long = InputStorePaymentPurpose; inputStorePaymentStarsGift#1d741ef7 user_id:InputUser stars:long currency:string amount:long = InputStorePaymentPurpose;
inputStorePaymentStarsGiveaway#751f08fa flags:# only_new_subscribers:flags.0?true winners_are_visible:flags.3?true stars:long boost_peer:InputPeer additional_peers:flags.1?Vector<InputPeer> countries_iso2:flags.2?Vector<string> prize_description:flags.4?string random_id:long until_date:int currency:string amount:long users:int = InputStorePaymentPurpose; inputStorePaymentStarsGiveaway#751f08fa flags:# only_new_subscribers:flags.0?true winners_are_visible:flags.3?true stars:long boost_peer:InputPeer additional_peers:flags.1?Vector<InputPeer> countries_iso2:flags.2?Vector<string> prize_description:flags.4?string random_id:long until_date:int currency:string amount:long users:int = InputStorePaymentPurpose;
premiumGiftOption#79c059f7 flags:# months:int currency:string amount:long bot_url:flags.1?string store_product:flags.0?string = PremiumGiftOption;
paymentFormMethod#88f8f21b url:string title:string = PaymentFormMethod; paymentFormMethod#88f8f21b url:string title:string = PaymentFormMethod;
emojiStatusEmpty#2de11aae = EmojiStatus; emojiStatusEmpty#2de11aae = EmojiStatus;