diff --git a/CMakeLists.txt b/CMakeLists.txt index a10015f59..1ababcafd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -414,6 +414,7 @@ set(TDLIB_SOURCE td/telegram/PhotoSizeSource.cpp td/telegram/PollManager.cpp td/telegram/Premium.cpp + td/telegram/PremiumGiftOption.cpp td/telegram/QueryCombiner.cpp td/telegram/RecentDialogList.cpp td/telegram/ReplyMarkup.cpp @@ -650,6 +651,7 @@ set(TDLIB_SOURCE td/telegram/PollId.h td/telegram/PollManager.h td/telegram/Premium.h + td/telegram/PremiumGiftOption.h td/telegram/PrivacyManager.h td/telegram/PtsManager.h td/telegram/PublicDialogType.h @@ -729,6 +731,7 @@ set(TDLIB_SOURCE td/telegram/PhotoSizeSource.hpp td/telegram/PollId.hpp td/telegram/PollManager.hpp + td/telegram/PremiumGiftOption.hpp td/telegram/ReplyMarkup.hpp td/telegram/SecureValue.hpp td/telegram/SendCodeHelper.hpp diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 95c4222e0..85534c05a 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -455,6 +455,15 @@ chatPermissions can_send_messages:Bool can_send_media_messages:Bool can_send_pol chatAdministratorRights can_manage_chat:Bool can_change_info:Bool can_post_messages:Bool can_edit_messages:Bool can_delete_messages:Bool can_invite_users:Bool can_restrict_members:Bool can_pin_messages:Bool can_promote_members:Bool can_manage_video_chats:Bool is_anonymous:Bool = ChatAdministratorRights; +//@description Describes an option for gifting Telegram Premium to a user +//@currency ISO 4217 currency code for Telegram Premium subscription payment +//@amount The amount to pay, in the smallest units of the currency +//@month_count Number of month the Telegram Premium subscription will be active +//@store_product Name of the store product associated with the option +//@payment_link An internal link to be opened for gifting Telegram Premium to the user if store payment isn't possible; may be null if direct payment isn't available +premiumGiftOption currency:string amount:int53 month_count:int32 store_product:string payment_link:InternalLinkType = PremiumGiftOption; + + //@description Represents a user //@id User identifier //@first_name First name of the user @@ -477,6 +486,7 @@ chatAdministratorRights can_manage_chat:Bool can_change_info:Bool can_post_messa //@added_to_attachment_menu True, if the user added the current bot to attachment menu; only available to bots user id:int53 first_name:string last_name:string username:string phone_number:string status:UserStatus profile_photo:profilePhoto is_contact:Bool is_mutual_contact:Bool is_verified:Bool is_premium:Bool is_support:Bool restriction_reason:string is_scam:Bool is_fake:Bool have_access:Bool type:UserType language_code:string added_to_attachment_menu:Bool = User; + //@description Contains information about a bot //@share_text The text that is shown on the bot's profile page and is sent together with the link when users share the bot //@param_description The text shown in the chat with the bot if the chat is empty @@ -488,7 +498,6 @@ user id:int53 first_name:string last_name:string username:string phone_number:st //@default_channel_administrator_rights Default administrator rights for adding the bot to channels; may be null botInfo share_text:string description:string photo:photo animation:animation menu_button:botMenuButton commands:vector default_group_administrator_rights:chatAdministratorRights default_channel_administrator_rights:chatAdministratorRights = BotInfo; - //@description Contains full information about a user //@photo User profile photo; may be null //@is_blocked True, if the user is blocked by the current user @@ -498,9 +507,10 @@ botInfo share_text:string description:string photo:photo animation:animation men //@has_private_forwards True, if the user can't be linked in forwarded messages due to their privacy settings //@need_phone_number_privacy_exception True, if the current user needs to explicitly allow to share their phone number with the user when the method addContact is used //@bio A short user bio; may be null for bots +//@premium_gift_options The list of available options for gifting Telegram Premium to the user //@group_in_common_count Number of group chats where both the other user and the current user are a member; 0 for the current user //@bot_info For bots, information about the bot; may be null -userFullInfo photo:chatPhoto is_blocked:Bool can_be_called:Bool supports_video_calls:Bool has_private_calls:Bool has_private_forwards:Bool need_phone_number_privacy_exception:Bool bio:formattedText group_in_common_count:int32 bot_info:botInfo = UserFullInfo; +userFullInfo photo:chatPhoto is_blocked:Bool can_be_called:Bool supports_video_calls:Bool has_private_calls:Bool has_private_forwards:Bool need_phone_number_privacy_exception:Bool bio:formattedText premium_gift_options:vector group_in_common_count:int32 bot_info:botInfo = UserFullInfo; //@description Represents a list of users @total_count Approximate total number of users found @user_ids A list of user identifiers users total_count:int32 user_ids:vector = Users; diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 4dc5e2134..603c3ed78 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -38,6 +38,7 @@ #include "td/telegram/PasswordManager.h" #include "td/telegram/Photo.h" #include "td/telegram/Photo.hpp" +#include "td/telegram/PremiumGiftOption.hpp" #include "td/telegram/SecretChatLayer.h" #include "td/telegram/SecretChatsManager.h" #include "td/telegram/ServerMessageId.h" @@ -3808,6 +3809,7 @@ void ContactsManager::UserFull::store(StorerT &storer) const { bool has_menu_button = menu_button != nullptr; bool has_description_photo = !description_photo.is_empty(); bool has_description_animation = description_animation_file_id.is_valid(); + bool has_premium_gift_options = !premium_gift_options.empty(); BEGIN_STORE_FLAGS(); STORE_FLAG(has_about); STORE_FLAG(is_blocked); @@ -3825,6 +3827,7 @@ void ContactsManager::UserFull::store(StorerT &storer) const { STORE_FLAG(has_menu_button); STORE_FLAG(has_description_photo); STORE_FLAG(has_description_animation); + STORE_FLAG(has_premium_gift_options); END_STORE_FLAGS(); if (has_about) { store(about, storer); @@ -3859,6 +3862,9 @@ void ContactsManager::UserFull::store(StorerT &storer) const { storer.context()->td().get_actor_unsafe()->animations_manager_->store_animation(description_animation_file_id, storer); } + if (has_premium_gift_options) { + store(premium_gift_options, storer); + } } template @@ -3874,6 +3880,7 @@ void ContactsManager::UserFull::parse(ParserT &parser) { bool has_menu_button; bool has_description_photo; bool has_description_animation; + bool has_premium_gift_options; BEGIN_PARSE_FLAGS(); PARSE_FLAG(has_about); PARSE_FLAG(is_blocked); @@ -3891,6 +3898,7 @@ void ContactsManager::UserFull::parse(ParserT &parser) { PARSE_FLAG(has_menu_button); PARSE_FLAG(has_description_photo); PARSE_FLAG(has_description_animation); + PARSE_FLAG(has_premium_gift_options); END_PARSE_FLAGS(); if (has_about) { parse(about, parser); @@ -3925,6 +3933,9 @@ void ContactsManager::UserFull::parse(ParserT &parser) { description_animation_file_id = parser.context()->td().get_actor_unsafe()->animations_manager_->parse_animation(parser); } + if (has_premium_gift_options) { + parse(premium_gift_options, parser); + } } template @@ -10757,19 +10768,24 @@ void ContactsManager::on_get_user_full(tl_object_ptr &&u bool can_be_called = user->phone_calls_available_ && !user->phone_calls_private_; bool supports_video_calls = user->video_calls_available_ && !user->phone_calls_private_; bool has_private_calls = user->phone_calls_private_; + auto premium_gift_options = transform(std::move(user->premium_gifts_), [](auto &&premium_gift_option) { + return PremiumGiftOption(std::move(premium_gift_option)); + }); AdministratorRights group_administrator_rights(user->bot_group_admin_rights_, ChannelType::Megagroup); AdministratorRights broadcast_administrator_rights(user->bot_broadcast_admin_rights_, ChannelType::Broadcast); if (user_full->can_be_called != can_be_called || user_full->supports_video_calls != supports_video_calls || user_full->has_private_calls != has_private_calls || user_full->private_forward_name != user->private_forward_name_ || user_full->group_administrator_rights != group_administrator_rights || - user_full->broadcast_administrator_rights != broadcast_administrator_rights) { + user_full->broadcast_administrator_rights != broadcast_administrator_rights || + user_full->premium_gift_options != premium_gift_options) { user_full->can_be_called = can_be_called; user_full->supports_video_calls = supports_video_calls; user_full->has_private_calls = has_private_calls; user_full->private_forward_name = std::move(user->private_forward_name_); user_full->group_administrator_rights = group_administrator_rights; user_full->broadcast_administrator_rights = broadcast_administrator_rights; + user_full->premium_gift_options = std::move(premium_gift_options); user_full->is_changed = true; } @@ -12087,6 +12103,7 @@ void ContactsManager::drop_user_full(UserId user_id) { user_full->private_forward_name.clear(); user_full->group_administrator_rights = {}; user_full->broadcast_administrator_rights = {}; + user_full->premium_gift_options.clear(); user_full->is_changed = true; update_user_full(user_full, user_id, "drop_user_full"); @@ -16722,11 +16739,15 @@ tl_object_ptr ContactsManager::get_user_full_info_object(U } bio_object = get_formatted_text_object(bio, true, 0); } + auto premium_gift_options = transform(user_full->premium_gift_options, [](const auto &option) { + return option.get_premium_gift_option_object(); + }); return make_tl_object( get_chat_photo_object(td_->file_manager_.get(), user_full->photo), user_full->is_blocked, user_full->can_be_called, user_full->supports_video_calls, user_full->has_private_calls, !user_full->private_forward_name.empty(), user_full->need_phone_number_privacy_exception, std::move(bio_object), - user_full->common_chat_count, std::move(bot_info)); + std::move(premium_gift_options), user_full->common_chat_count, + std::move(bot_info)); } td_api::object_ptr ContactsManager::get_update_unknown_basic_group_object(ChatId chat_id) { diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index 339b87047..05ce95c67 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -27,6 +27,7 @@ #include "td/telegram/MessageId.h" #include "td/telegram/net/DcId.h" #include "td/telegram/Photo.h" +#include "td/telegram/PremiumGiftOption.h" #include "td/telegram/PublicDialogType.h" #include "td/telegram/QueryCombiner.h" #include "td/telegram/RestrictionReason.h" @@ -715,6 +716,8 @@ class ContactsManager final : public Actor { Photo description_photo; FileId description_animation_file_id; + vector premium_gift_options; + unique_ptr menu_button; vector commands; AdministratorRights group_administrator_rights; diff --git a/td/telegram/PremiumGiftOption.cpp b/td/telegram/PremiumGiftOption.cpp new file mode 100644 index 000000000..688830ac2 --- /dev/null +++ b/td/telegram/PremiumGiftOption.cpp @@ -0,0 +1,39 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#include "td/telegram/PremiumGiftOption.h" + +#include "td/telegram/LinkManager.h" + +#include "td/utils/common.h" + +namespace td { + +PremiumGiftOption::PremiumGiftOption(telegram_api::object_ptr &&option) + : months_(option->months_) + , currency_(std::move(option->currency_)) + , amount_(option->amount_) + , bot_url_(std::move(option->bot_url_)) + , store_product_(std::move(option->store_product_)) { +} + +td_api::object_ptr PremiumGiftOption::get_premium_gift_option_object() const { + auto link_type = LinkManager::parse_internal_link(bot_url_, true); + return td_api::make_object( + currency_, amount_, months_, store_product_, + link_type == nullptr ? nullptr : link_type->get_internal_link_type_object()); +} + +bool operator==(const PremiumGiftOption &lhs, const PremiumGiftOption &rhs) { + return lhs.months_ == rhs.months_ && lhs.currency_ == rhs.currency_ && lhs.amount_ == rhs.amount_ && + lhs.bot_url_ == rhs.bot_url_ && lhs.store_product_ == rhs.store_product_; +} + +bool operator!=(const PremiumGiftOption &lhs, const PremiumGiftOption &rhs) { + return !(lhs == rhs); +} + +} // namespace td diff --git a/td/telegram/PremiumGiftOption.h b/td/telegram/PremiumGiftOption.h new file mode 100644 index 000000000..5c6ee87af --- /dev/null +++ b/td/telegram/PremiumGiftOption.h @@ -0,0 +1,41 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#pragma once + +#include "td/telegram/td_api.h" +#include "td/telegram/telegram_api.h" + +#include "td/utils/common.h" + +namespace td { + +class PremiumGiftOption { + int32 months_ = 0; + string currency_; + int64 amount_ = 0; + string bot_url_; + string store_product_; + + friend bool operator==(const PremiumGiftOption &lhs, const PremiumGiftOption &rhs); + + public: + PremiumGiftOption() = default; + explicit PremiumGiftOption(telegram_api::object_ptr &&option); + + td_api::object_ptr get_premium_gift_option_object() const; + + template + void store(StorerT &storer) const; + + template + void parse(ParserT &parser); +}; + +bool operator==(const PremiumGiftOption &lhs, const PremiumGiftOption &rhs); +bool operator!=(const PremiumGiftOption &lhs, const PremiumGiftOption &rhs); + +} // namespace td diff --git a/td/telegram/PremiumGiftOption.hpp b/td/telegram/PremiumGiftOption.hpp new file mode 100644 index 000000000..507b66994 --- /dev/null +++ b/td/telegram/PremiumGiftOption.hpp @@ -0,0 +1,77 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022 +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#pragma once + +#include "td/telegram/PremiumGiftOption.h" + +#include "td/utils/tl_helpers.h" + +namespace td { + +template +void PremiumGiftOption::store(StorerT &storer) const { + bool has_months = months_ != 0; + bool has_currency = !currency_.empty(); + bool has_amount = amount_ != 0; + bool has_bot_url = !bot_url_.empty(); + bool has_store_product = !store_product_.empty(); + BEGIN_STORE_FLAGS(); + STORE_FLAG(has_months); + STORE_FLAG(has_currency); + STORE_FLAG(has_amount); + STORE_FLAG(has_bot_url); + STORE_FLAG(has_store_product); + END_STORE_FLAGS(); + if (has_months) { + td::store(months_, storer); + } + if (has_currency) { + td::store(currency_, storer); + } + if (has_amount) { + td::store(amount_, storer); + } + if (has_bot_url) { + td::store(bot_url_, storer); + } + if (has_store_product) { + td::store(store_product_, storer); + } +} + +template +void PremiumGiftOption::parse(ParserT &parser) { + bool has_months; + bool has_currency; + bool has_amount; + bool has_bot_url; + bool has_store_product; + BEGIN_PARSE_FLAGS(); + PARSE_FLAG(has_months); + PARSE_FLAG(has_currency); + PARSE_FLAG(has_amount); + PARSE_FLAG(has_bot_url); + PARSE_FLAG(has_store_product); + END_PARSE_FLAGS(); + if (has_months) { + td::parse(months_, parser); + } + if (has_currency) { + td::parse(currency_, parser); + } + if (has_amount) { + td::parse(amount_, parser); + } + if (has_bot_url) { + td::parse(bot_url_, parser); + } + if (has_store_product) { + td::parse(store_product_, parser); + } +} + +} // namespace td