diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 0fe97154b..db7101ddb 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -6091,8 +6091,10 @@ setBio bio:string = Ok; //@description Changes the username of the current user @username The new value of the username. Use an empty string to remove the username setUsername username:string = Ok; -//@description Changes the premium status of the current user; for Telegram Premium users only @premium_status New premium status; pass null to switch to the default badge -setPremiumStatus premium_status:premiumStatus = Ok; +//@description Changes the premium status of the current user; for Telegram Premium users only +//@premium_status New premium status; pass null to switch to the default badge +//@duration Duration of the status, in seconds; pass 0 to keep the status active until it will be changed manually +setPremiumStatus premium_status:premiumStatus duration:int32 = Ok; //@description Changes the location of the current user. Needs to be called if GetOption("is_location_visible") is true and location changes for more than 1 kilometer @location The new location of the user setLocation location:location = Ok; diff --git a/td/telegram/ContactsManager.cpp b/td/telegram/ContactsManager.cpp index 468c97f72..417f421d3 100644 --- a/td/telegram/ContactsManager.cpp +++ b/td/telegram/ContactsManager.cpp @@ -8797,19 +8797,17 @@ void ContactsManager::on_get_user(tl_object_ptr &&user_ptr, int32 bot_info_version = has_bot_info_version ? user->bot_info_version_ : -1; if (u->emoji_status != emoji_status) { u->emoji_status = emoji_status; - u->is_emoji_status_changed = true; } - if (is_verified != u->is_verified || is_premium != u->is_premium || is_support != u->is_support || - is_bot != u->is_bot || can_join_groups != u->can_join_groups || - can_read_all_group_messages != u->can_read_all_group_messages || restriction_reasons != u->restriction_reasons || - is_scam != u->is_scam || is_fake != u->is_fake || is_inline_bot != u->is_inline_bot || - inline_query_placeholder != u->inline_query_placeholder || need_location_bot != u->need_location_bot || - can_be_added_to_attach_menu != u->can_be_added_to_attach_menu || attach_menu_enabled != u->attach_menu_enabled) { + if (is_verified != u->is_verified || is_support != u->is_support || is_bot != u->is_bot || + can_join_groups != u->can_join_groups || can_read_all_group_messages != u->can_read_all_group_messages || + restriction_reasons != u->restriction_reasons || is_scam != u->is_scam || is_fake != u->is_fake || + is_inline_bot != u->is_inline_bot || inline_query_placeholder != u->inline_query_placeholder || + need_location_bot != u->need_location_bot || can_be_added_to_attach_menu != u->can_be_added_to_attach_menu || + attach_menu_enabled != u->attach_menu_enabled) { LOG_IF(ERROR, is_bot != u->is_bot && !is_deleted && !u->is_deleted && u->is_received) << "User.is_bot has changed for " << user_id << "/" << u->username << " from " << source << " from " << u->is_bot << " to " << is_bot; u->is_verified = is_verified; - u->is_premium = is_premium; u->is_support = is_support; u->is_bot = is_bot; u->can_join_groups = can_join_groups; @@ -8826,6 +8824,10 @@ void ContactsManager::on_get_user(tl_object_ptr &&user_ptr, LOG(DEBUG) << "Info has changed for " << user_id; u->is_changed = true; } + if (is_premium != u->is_premium) { + u->is_premium = is_premium; + u->is_changed = true; + } if (u->bot_info_version != bot_info_version) { u->bot_info_version = bot_info_version; @@ -10329,16 +10331,6 @@ void ContactsManager::update_user(User *u, UserId user_id, bool from_binlog, boo } u->is_phone_number_changed = false; } - if (u->is_emoji_status_changed) { - auto effective_custom_emoji_id = u->emoji_status.get_effective_custom_emoji_id(u->is_premium); - if (effective_custom_emoji_id != u->last_sent_emoji_status) { - u->last_sent_emoji_status = effective_custom_emoji_id; - u->is_changed = true; - } else { - u->need_save_to_database = true; - } - u->is_emoji_status_changed = false; - } if (u->is_status_changed && user_id != get_my_id()) { auto left_time = get_user_was_online(u, user_id) - G()->server_time_cached(); if (left_time >= 0 && left_time < 30 * 86400) { @@ -10358,6 +10350,15 @@ void ContactsManager::update_user(User *u, UserId user_id, bool from_binlog, boo } } + auto unix_time = G()->unix_time(); + auto effective_custom_emoji_id = u->emoji_status.get_effective_custom_emoji_id(u->is_premium, unix_time); + if (effective_custom_emoji_id != u->last_sent_emoji_status) { + u->last_sent_emoji_status = effective_custom_emoji_id; + u->is_changed = true; + } else { + u->need_save_to_database = true; + } + if (u->is_deleted) { td_->inline_queries_manager_->remove_recent_inline_bot(user_id, Promise<>()); } @@ -11777,7 +11778,6 @@ void ContactsManager::on_update_user_emoji_status(UserId user_id, void ContactsManager::on_update_user_emoji_status(User *u, UserId user_id, EmojiStatus emoji_status) { if (u->emoji_status != emoji_status) { u->emoji_status = emoji_status; - u->is_emoji_status_changed = true; LOG(DEBUG) << "Emoji status has changed for " << user_id; } } @@ -16781,7 +16781,7 @@ tl_object_ptr ContactsManager::get_user_object(UserId user_id, con type = make_tl_object(); } - auto premium_status = u->is_premium ? u->emoji_status.get_premium_status_object() : nullptr; + auto premium_status = u->last_sent_emoji_status != 0 ? u->emoji_status.get_premium_status_object() : nullptr; return make_tl_object( user_id.get(), u->first_name, u->last_name, u->username, u->phone_number, get_user_status_object(user_id, u), get_profile_photo_object(td_->file_manager_.get(), u->photo), std::move(premium_status), u->is_contact, diff --git a/td/telegram/ContactsManager.h b/td/telegram/ContactsManager.h index 533980644..7a24b1181 100644 --- a/td/telegram/ContactsManager.h +++ b/td/telegram/ContactsManager.h @@ -693,7 +693,6 @@ class ContactsManager final : public Actor { bool is_username_changed = true; bool is_photo_changed = true; bool is_phone_number_changed = true; - bool is_emoji_status_changed = true; bool is_is_contact_changed = true; bool is_is_deleted_changed = true; bool is_changed = true; // have new changes that need to be sent to the client and database diff --git a/td/telegram/EmojiStatus.cpp b/td/telegram/EmojiStatus.cpp index 8bdea56be..0ec888f63 100644 --- a/td/telegram/EmojiStatus.cpp +++ b/td/telegram/EmojiStatus.cpp @@ -193,13 +193,42 @@ class ClearRecentEmojiStatusesQuery final : public Td::ResultHandler { } }; -EmojiStatus::EmojiStatus(const td_api::object_ptr &premium_status) - : custom_emoji_id_(premium_status != nullptr ? premium_status->custom_emoji_id_ : 0) { +EmojiStatus::EmojiStatus(const td_api::object_ptr &premium_status, int32 duration) { + if (premium_status == nullptr) { + return; + } + + custom_emoji_id_ = premium_status->custom_emoji_id_; + if (duration != 0) { + int32 current_time = G()->unix_time(); + if (duration >= std::numeric_limits::max() - current_time) { + until_date_ = std::numeric_limits::max(); + } else { + until_date_ = current_time + duration; + } + } } EmojiStatus::EmojiStatus(tl_object_ptr &&emoji_status) { - if (emoji_status != nullptr && emoji_status->get_id() == telegram_api::emojiStatus::ID) { - custom_emoji_id_ = static_cast(emoji_status.get())->document_id_; + if (emoji_status == nullptr) { + return; + } + switch (emoji_status->get_id()) { + case telegram_api::emojiStatusEmpty::ID: + break; + case telegram_api::emojiStatus::ID: { + auto status = static_cast(emoji_status.get()); + custom_emoji_id_ = status->document_id_; + break; + } + case telegram_api::emojiStatusUntil::ID: { + auto status = static_cast(emoji_status.get()); + custom_emoji_id_ = status->document_id_; + until_date_ = status->until_; + break; + } + default: + UNREACHABLE(); } } @@ -207,6 +236,9 @@ tl_object_ptr EmojiStatus::get_input_emoji_status() c if (is_empty()) { return make_tl_object(); } + if (until_date_ != 0) { + return make_tl_object(custom_emoji_id_, until_date_); + } return make_tl_object(custom_emoji_id_); } @@ -217,15 +249,25 @@ td_api::object_ptr EmojiStatus::get_premium_status_object return td_api::make_object(custom_emoji_id_); } -int64 EmojiStatus::get_effective_custom_emoji_id(bool is_premium) const { - return is_premium ? 0 : custom_emoji_id_; +int64 EmojiStatus::get_effective_custom_emoji_id(bool is_premium, int32 unix_time) const { + if (!is_premium) { + return 0; + } + if (until_date_ != 0 && until_date_ <= unix_time) { + return 0; + } + return custom_emoji_id_; } StringBuilder &operator<<(StringBuilder &string_builder, const EmojiStatus &emoji_status) { if (emoji_status.is_empty()) { return string_builder << "DefaultProfileBadge"; } - return string_builder << "CustomEmoji " << emoji_status.custom_emoji_id_; + string_builder << "CustomEmoji " << emoji_status.custom_emoji_id_; + if (emoji_status.until_date_ != 0) { + string_builder << " until " << emoji_status.until_date_; + } + return string_builder; } void get_default_emoji_statuses(Td *td, Promise> &&promise) { diff --git a/td/telegram/EmojiStatus.h b/td/telegram/EmojiStatus.h index 7bd558e8a..5288f9695 100644 --- a/td/telegram/EmojiStatus.h +++ b/td/telegram/EmojiStatus.h @@ -20,6 +20,7 @@ class Td; class EmojiStatus { int64 custom_emoji_id_ = 0; + int32 until_date_ = 0; friend bool operator==(const EmojiStatus &lhs, const EmojiStatus &rhs); @@ -28,7 +29,7 @@ class EmojiStatus { public: EmojiStatus() = default; - explicit EmojiStatus(const td_api::object_ptr &premium_status); + EmojiStatus(const td_api::object_ptr &premium_status, int32 duration); explicit EmojiStatus(tl_object_ptr &&emoji_status); @@ -36,7 +37,7 @@ class EmojiStatus { td_api::object_ptr get_premium_status_object() const; - int64 get_effective_custom_emoji_id(bool is_premium) const; + int64 get_effective_custom_emoji_id(bool is_premium, int32 unix_time) const; bool is_empty() const { return custom_emoji_id_ == 0; @@ -44,17 +45,31 @@ class EmojiStatus { template void store(StorerT &storer) const { + bool has_until_date = until_date_ != 0; + BEGIN_STORE_FLAGS(); + STORE_FLAG(has_until_date); + END_STORE_FLAGS(); td::store(custom_emoji_id_, storer); + if (has_until_date) { + td::store(until_date_, storer); + } } template void parse(ParserT &parser) { + bool has_until_date; + BEGIN_PARSE_FLAGS(); + PARSE_FLAG(has_until_date); + END_PARSE_FLAGS(); td::parse(custom_emoji_id_, parser); + if (has_until_date) { + td::parse(until_date_, parser); + } } }; inline bool operator==(const EmojiStatus &lhs, const EmojiStatus &rhs) { - return lhs.custom_emoji_id_ == rhs.custom_emoji_id_; + return lhs.custom_emoji_id_ == rhs.custom_emoji_id_ && lhs.until_date_ == rhs.until_date_; } inline bool operator!=(const EmojiStatus &lhs, const EmojiStatus &rhs) { diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index f5d45f873..b924640bf 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -6730,7 +6730,7 @@ void Td::on_request(uint64 id, td_api::setUsername &request) { void Td::on_request(uint64 id, const td_api::setPremiumStatus &request) { CHECK_IS_USER(); CREATE_OK_REQUEST_PROMISE(); - contacts_manager_->set_emoji_status(EmojiStatus(request.premium_status_), std::move(promise)); + contacts_manager_->set_emoji_status(EmojiStatus(request.premium_status_, request.duration_), std::move(promise)); } void Td::on_request(uint64 id, const td_api::getDefaultPremiumStatuses &request) { diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index e7ec0c4e1..3038ad46f 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -4473,10 +4473,14 @@ class CliClient final : public Actor { send_request(td_api::make_object("\n" + args + "\n" + args + "\n")); } else if (op == "sun") { send_request(td_api::make_object(args)); + } else if (op == "spse") { + send_request(td_api::make_object(nullptr, 0)); } else if (op == "sps") { - auto premium_status = - args.empty() ? nullptr : td_api::make_object(to_integer(args)); - send_request(td_api::make_object(std::move(premium_status))); + int64 custom_emoji_id; + int32 until_date; + get_args(args, custom_emoji_id, until_date); + send_request(td_api::make_object( + td_api::make_object(custom_emoji_id), until_date)); } else if (op == "gdps") { send_request(td_api::make_object()); } else if (op == "grps") {