diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 953c6abae..538032d2f 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -706,6 +706,38 @@ premiumGiftCodePaymentOptions options:vector = Pre premiumGiftCodeInfo creator_id:MessageSender creation_date:int32 is_from_giveaway:Bool giveaway_message_id:int53 month_count:int32 user_id:int53 use_date:int32 = PremiumGiftCodeInfo; +//@class PremiumGiveawayParticipantStatus @description Contains information about status of a user in a Telegram Premium giveaway + +//@description The user is eligible for the giveaway +premiumGiveawayParticipantStatusEligible = PremiumGiveawayParticipantStatus; + +//@description The user participates in the giveaway +premiumGiveawayParticipantStatusParticipating = PremiumGiveawayParticipantStatus; + +//@description The user can't participate in the giveaway, because it has already been member of the chat +//@joined_chat_date Point in time (Unix timestamp) when the user joined the chat +premiumGiveawayParticipantStatusAlreadyWasMember joined_chat_date:int32 = PremiumGiveawayParticipantStatus; + +//@description The user is an administrator in one of the chats that created the giveaway @chat_id Identifier of the chat administered by the user +premiumGiveawayParticipantStatusAdministrator chat_id:int53 = PremiumGiveawayParticipantStatus; + + +//@class PremiumGiveawayInfo @description Contains information about Telegram Premium giveaway + +//@description Describes an ongoing giveaway +//@status Status of the current user in the giveaway +//@is_ended True, if the giveaway has ended and results are being prepared +premiumGiveawayInfoOngoing status:PremiumGiveawayParticipantStatus is_ended:Bool = PremiumGiveawayInfo; + +//@description Describes a completed giveaway +//@winners_selection_date Point in time (Unix timestamp) when the winners were selected +//@was_refunded True, if the giveaway was canceled and was fully refunded +//@winner_count Number of winners in the giveaway +//@activation_count Number of winners, which activated their gift codes +//@gift_code Telegram Premium gift code that was received by the current user; empty if the user isn't a winner in the giveaway +premiumGiveawayInfoCompleted winners_selection_date:int32 was_refunded:Bool winner_count:int32 activation_count:int32 gift_code:string = PremiumGiveawayInfo; + + //@description Describes a custom emoji to be shown instead of the Telegram Premium badge //@custom_emoji_id Identifier of the custom emoji in stickerFormatTgs format //@expiration_date Point in time (Unix timestamp) when the status will expire; 0 if never @@ -9116,6 +9148,11 @@ checkPremiumGiftCode code:string = PremiumGiftCodeInfo; //@description Applies a Telegram Premium gift code @code The code to apply applyPremiumGiftCode code:string = Ok; +//@description Returns information about a Telegram Premium giveaway +//@chat_id Identifier of the channel chat which started the giveaway +//@message_id Identifier of the giveaway message in the chat +getPremiumGiveawayInfo chat_id:int53 message_id:int53 = PremiumGiveawayInfo; + //@description Checks whether Telegram Premium purchase is possible. Must be called before in-store Premium purchase @purpose Transaction purpose canPurchasePremium purpose:StorePaymentPurpose = Ok; diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index eb0e8b964..cc6ed23bf 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -28219,10 +28219,10 @@ Result> MessagesManager::resend_messages(DialogId dialog_id, v MessageSendOptions options(message->disable_notification, message->from_background, message->update_stickersets_order, message->noforwards, get_message_schedule_date(message.get()), message->sending_id); - Message *m = get_message_to_send( - d, message->top_thread_message_id, get_message_input_reply_to(message.get()), options, - std::move(new_contents[i]), &need_update_dialog_pos, false, nullptr, message->is_copy, - need_another_sender ? DialogId() : get_message_sender(message.get())); + Message *m = + get_message_to_send(d, message->top_thread_message_id, get_message_input_reply_to(message.get()), options, + std::move(new_contents[i]), &need_update_dialog_pos, false, nullptr, message->is_copy, + need_another_sender ? DialogId() : get_message_sender(message.get())); m->reply_markup = std::move(message->reply_markup); // m->via_bot_user_id = message->via_bot_user_id; m->disable_web_page_preview = message->disable_web_page_preview; @@ -40077,6 +40077,24 @@ Result MessagesManager::get_payment_successful_message_id(Messa return m->message_id.get_server_message_id(); } +Result MessagesManager::get_giveaway_message_id(MessageFullId message_full_id) { + auto m = get_message_force(message_full_id, "get_giveaway_message_id"); + if (m == nullptr) { + return Status::Error(400, "Message not found"); + } + if (m->content->get_type() != MessageContentType::Giveaway) { + return Status::Error(400, "Message has wrong type"); + } + if (m->message_id.is_scheduled()) { + return Status::Error(400, "Wrong scheduled message identifier"); + } + if (!m->message_id.is_server()) { + return Status::Error(400, "Wrong message identifier"); + } + + return m->message_id.get_server_message_id(); +} + void MessagesManager::remove_sponsored_dialog() { set_sponsored_dialog(DialogId(), DialogSource()); } diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index a038625b9..4c7aa7d10 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -1019,6 +1019,8 @@ class MessagesManager final : public Actor { Result get_payment_successful_message_id(MessageFullId message_full_id); + Result get_giveaway_message_id(MessageFullId message_full_id); + bool can_set_game_score(MessageFullId message_full_id) const; void get_current_state(vector> &updates) const; diff --git a/td/telegram/Premium.cpp b/td/telegram/Premium.cpp index 13a08b09c..d629a5bb1 100644 --- a/td/telegram/Premium.cpp +++ b/td/telegram/Premium.cpp @@ -18,6 +18,7 @@ #include "td/telegram/MessagesManager.h" #include "td/telegram/misc.h" #include "td/telegram/PremiumGiftOption.h" +#include "td/telegram/ServerMessageId.h" #include "td/telegram/SuggestedAction.h" #include "td/telegram/Td.h" #include "td/telegram/telegram_api.h" @@ -398,6 +399,94 @@ class ApplyGiftCodeQuery final : public Td::ResultHandler { } }; +class GetGiveawayInfoQuery final : public Td::ResultHandler { + Promise> promise_; + DialogId dialog_id_; + + public: + explicit GetGiveawayInfoQuery(Promise> &&promise) + : promise_(std::move(promise)) { + } + + void send(DialogId dialog_id, ServerMessageId server_message_id) { + dialog_id_ = dialog_id; + auto input_peer = td_->messages_manager_->get_input_peer(dialog_id, AccessRights::Read); + if (input_peer == nullptr) { + return on_error(Status::Error(400, "Can't access the chat")); + } + send_query(G()->net_query_creator().create( + telegram_api::payments_getGiveawayInfo(std::move(input_peer), server_message_id.get()))); + } + + void on_result(BufferSlice packet) final { + auto result_ptr = fetch_result(packet); + if (result_ptr.is_error()) { + return on_error(result_ptr.move_as_error()); + } + + auto ptr = result_ptr.move_as_ok(); + LOG(INFO) << "Receive result for GetGiveawayInfoQuery: " << to_string(ptr); + switch (ptr->get_id()) { + case telegram_api::payments_giveawayInfo::ID: { + auto info = telegram_api::move_object_as(ptr); + auto status = [&]() -> td_api::object_ptr { + if (info->joined_too_early_date_ > 0) { + return td_api::make_object( + info->joined_too_early_date_); + } + if (info->admin_disallowed_chat_id_ > 0) { + ChannelId channel_id(info->admin_disallowed_chat_id_); + if (!channel_id.is_valid() || + !td_->contacts_manager_->have_channel_force(channel_id, "GetGiveawayInfoQuery")) { + LOG(ERROR) << "Receive " << to_string(info); + } else { + DialogId dialog_id(channel_id); + td_->messages_manager_->force_create_dialog(dialog_id, "GetGiveawayInfoQuery"); + return td_api::make_object( + td_->messages_manager_->get_chat_id_object(dialog_id, + "premiumGiveawayParticipantStatusAdministrator")); + } + } + if (info->participating_) { + return td_api::make_object(); + } + return td_api::make_object(); + }(); + promise_.set_value( + td_api::make_object(std::move(status), info->preparing_results_)); + break; + } + case telegram_api::payments_giveawayInfoResults::ID: { + auto info = telegram_api::move_object_as(ptr); + auto winner_count = info->winners_count_; + auto activated_count = info->activated_count_; + if (activated_count < 0 || activated_count > winner_count) { + LOG(ERROR) << "Receive " << to_string(info); + if (activated_count < 0) { + activated_count = 0; + } + if (winner_count < 0) { + winner_count = 0; + } + if (activated_count > winner_count) { + activated_count = winner_count; + } + } + promise_.set_value(td_api::make_object( + max(0, info->finish_date_), info->refunded_, winner_count, activated_count, info->gift_code_slug_)); + break; + } + default: + UNREACHABLE(); + } + } + + void on_error(Status status) final { + td_->messages_manager_->on_get_dialog_error(dialog_id_, status, "GetGiveawayInfoQuery"); + promise_.set_error(std::move(status)); + } +}; + class CanPurchasePremiumQuery final : public Td::ResultHandler { Promise promise_; @@ -838,6 +927,13 @@ void apply_premium_gift_code(Td *td, const string &code, Promise &&promise td->create_handler(std::move(promise))->send(code); } +void get_premium_giveaway_info(Td *td, MessageFullId message_full_id, + Promise> &&promise) { + TRY_RESULT_PROMISE(promise, server_message_id, td->messages_manager_->get_giveaway_message_id(message_full_id)); + td->create_handler(std::move(promise)) + ->send(message_full_id.get_dialog_id(), server_message_id); +} + void can_purchase_premium(Td *td, td_api::object_ptr &&purpose, Promise &&promise) { td->create_handler(std::move(promise))->send(std::move(purpose)); } diff --git a/td/telegram/Premium.h b/td/telegram/Premium.h index 90b692506..fcb8f668c 100644 --- a/td/telegram/Premium.h +++ b/td/telegram/Premium.h @@ -7,6 +7,7 @@ #pragma once #include "td/telegram/DialogId.h" +#include "td/telegram/MessageFullId.h" #include "td/telegram/td_api.h" #include "td/telegram/telegram_api.h" @@ -43,6 +44,9 @@ void check_premium_gift_code(Td *td, const string &code, void apply_premium_gift_code(Td *td, const string &code, Promise &&promise); +void get_premium_giveaway_info(Td *td, MessageFullId message_full_id, + Promise> &&promise); + void can_purchase_premium(Td *td, td_api::object_ptr &&purpose, Promise &&promise); void assign_app_store_transaction(Td *td, const string &receipt, diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 35bf4b8a7..ab1c7db1b 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -8809,6 +8809,12 @@ void Td::on_request(uint64 id, td_api::applyPremiumGiftCode &request) { apply_premium_gift_code(this, request.code_, std::move(promise)); } +void Td::on_request(uint64 id, const td_api::getPremiumGiveawayInfo &request) { + CHECK_IS_USER(); + CREATE_REQUEST_PROMISE(); + get_premium_giveaway_info(this, {DialogId(request.chat_id_), MessageId(request.message_id_)}, std::move(promise)); +} + void Td::on_request(uint64 id, td_api::canPurchasePremium &request) { CHECK_IS_USER(); CREATE_OK_REQUEST_PROMISE(); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index d64bbd1df..d20263596 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -1603,6 +1603,8 @@ class Td final : public Actor { void on_request(uint64 id, td_api::applyPremiumGiftCode &request); + void on_request(uint64 id, const td_api::getPremiumGiveawayInfo &request); + void on_request(uint64 id, td_api::canPurchasePremium &request); void on_request(uint64 id, td_api::assignAppStoreTransaction &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index ee8fb06de..95310b6a5 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -3101,6 +3101,11 @@ class CliClient final : public Actor { send_request(td_api::make_object(args)); } else if (op == "apgc") { send_request(td_api::make_object(args)); + } else if (op == "gpgi") { + ChatId chat_id; + MessageId message_id; + get_args(args, chat_id, message_id); + send_request(td_api::make_object(chat_id, message_id)); } else if (op == "cppr" || op == "cpprb" || op == "cpprg") { UserId user_id; string currency;