diff --git a/td/telegram/AuthManager.cpp b/td/telegram/AuthManager.cpp index b4e569b45..a2cd48f71 100644 --- a/td/telegram/AuthManager.cpp +++ b/td/telegram/AuthManager.cpp @@ -725,6 +725,7 @@ void AuthManager::on_get_authorization(tl_object_ptrupdates_manager_->get_difference("on_get_authorization"); td->on_online_updated(false, true); td->schedule_get_terms_of_service(0); + td->schedule_get_promo_data(0); if (!is_bot()) { G()->td_db()->get_binlog_pmc()->set("fetched_marks_as_unread", "1"); } diff --git a/td/telegram/MessagesManager.cpp b/td/telegram/MessagesManager.cpp index 39d891a81..c590b4e06 100644 --- a/td/telegram/MessagesManager.cpp +++ b/td/telegram/MessagesManager.cpp @@ -8867,6 +8867,7 @@ void MessagesManager::delete_dialog_history(DialogId dialog_id, bool remove_from remove_sponsored_dialog(); td_->create_handler()->send(dialog_id); + promise.set_value(Unit()); return; } @@ -9845,7 +9846,7 @@ void MessagesManager::recalc_unread_count(FolderId folder_id) { } } } - if (d->order != DEFAULT_ORDER || is_dialog_sponsored(d)) { + if (d->order != DEFAULT_ORDER) { // must not count sponsored dialog, which is added independently if (dialog_id.get_type() == DialogType::SecretChat) { secret_chat_total_count++; } else { @@ -30677,13 +30678,18 @@ void MessagesManager::add_sponsored_dialog(const Dialog *d, DialogSource source) if (is_dialog_sponsored(d)) { send_update_chat_chat_list(d); - auto folder_id = FolderId::main(); - auto &list = get_dialog_list(folder_id); - DialogDate max_dialog_date(SPONSORED_DIALOG_ORDER, d->dialog_id); - if (list.last_server_dialog_date_ < max_dialog_date) { - list.last_server_dialog_date_ = max_dialog_date; - update_last_dialog_date(folder_id); - } + } + + // update last_server_dialog_date in any case, because all chats before SPONSORED_DIALOG_ORDER are known + auto folder_id = FolderId::main(); + auto &list = get_dialog_list(folder_id); + DialogDate max_dialog_date(SPONSORED_DIALOG_ORDER, d->dialog_id); + if (list.last_server_dialog_date_ < max_dialog_date) { + list.last_server_dialog_date_ = max_dialog_date; + update_last_dialog_date(folder_id); + } + + if (is_dialog_sponsored(d)) { send_update_chat_source(d); // the sponsored dialog must not be saved there } diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 43cef2e73..5593e36e1 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -177,6 +177,33 @@ class GetNearestDcQuery : public Td::ResultHandler { } }; +class GetPromoDataQuery : public Td::ResultHandler { + Promise> promise_; + + public: + explicit GetPromoDataQuery(Promise> &&promise) + : promise_(std::move(promise)) { + } + + void send() { + // we don't poll promo data before authorization + send_query(G()->net_query_creator().create(telegram_api::help_getPromoData())); + } + + void on_result(uint64 id, BufferSlice packet) override { + auto result_ptr = fetch_result(packet); + if (result_ptr.is_error()) { + return on_error(id, result_ptr.move_as_error()); + } + + promise_.set_value(result_ptr.move_as_ok()); + } + + void on_error(uint64 id, Status status) override { + promise_.set_error(std::move(status)); + } +}; + class GetRecentMeUrlsQuery : public Td::ResultHandler { Promise> promise_; @@ -2989,6 +3016,16 @@ void Td::on_alarm_timeout(int64 alarm_id) { } return; } + if (alarm_id == PROMO_DATA_ALARM_ID) { + if (!close_flag_ && !auth_manager_->is_bot()) { + auto promise = PromiseCreator::lambda( + [actor_id = actor_id(this)](Result> result) { + send_closure(actor_id, &Td::on_get_promo_data, std::move(result), false); + }); + create_handler(std::move(promise))->send(); + } + return; + } if (close_flag_ >= 2) { // pending_alarms_ was already cleared return; @@ -3067,6 +3104,63 @@ void Td::schedule_get_terms_of_service(int32 expires_in) { } } +void Td::on_get_promo_data(Result> r_promo_data, bool dummy) { + if (G()->close_flag()) { + return; + } + + if (r_promo_data.is_error()) { + LOG(ERROR) << "Receive error for getPromoData: " << r_promo_data.error(); + return schedule_get_promo_data(60); + } + + auto promo_data_ptr = r_promo_data.move_as_ok(); + CHECK(promo_data_ptr != nullptr); + LOG(DEBUG) << "Receive " << to_string(promo_data_ptr); + int32 expires = 0; + switch (promo_data_ptr->get_id()) { + case telegram_api::help_promoDataEmpty::ID: { + auto promo = telegram_api::move_object_as(promo_data_ptr); + expires = promo->expires_; + messages_manager_->remove_sponsored_dialog(); + break; + } + case telegram_api::help_promoData::ID: { + auto promo = telegram_api::move_object_as(promo_data_ptr); + expires = promo->expires_; + bool is_proxy = (promo->flags_ & telegram_api::help_promoData::PROXY_MASK) != 0; + messages_manager_->on_get_sponsored_dialog( + std::move(promo->peer_), + is_proxy ? DialogSource::mtproto_proxy() + : DialogSource::public_service_announcement(promo->psa_type_, promo->psa_message_), + std::move(promo->users_), std::move(promo->chats_)); + break; + } + default: + UNREACHABLE(); + } + if (expires != 0) { + expires -= G()->unix_time(); + } + schedule_get_promo_data(expires); +} + +void Td::schedule_get_promo_data(int32 expires_in) { + if (expires_in < 0) { + LOG(ERROR) << "Receive wrong expires_in: " << expires_in; + expires_in = 0; + } + if (expires_in != 0 && expires_in < 60) { + expires_in = 60; + } + if (expires_in > 86400) { + expires_in = 86400; + } + if (!close_flag_ && !auth_manager_->is_bot()) { + alarm_timeout_.set_timeout_in(PROMO_DATA_ALARM_ID, expires_in); + } +} + void Td::on_channel_unban_timeout(int64 channel_id_long) { if (close_flag_ >= 2) { return; @@ -3802,6 +3896,7 @@ void Td::clear() { } alarm_timeout_.cancel_timeout(PING_SERVER_ALARM_ID); alarm_timeout_.cancel_timeout(TERMS_OF_SERVICE_ALARM_ID); + alarm_timeout_.cancel_timeout(PROMO_DATA_ALARM_ID); LOG(DEBUG) << "Requests was answered " << timer; // close all pure actors @@ -4084,6 +4179,7 @@ Status Td::init(DbKey key) { } else { updates_manager_->get_difference("init"); schedule_get_terms_of_service(0); + schedule_get_promo_data(0); } complete_pending_preauthentication_requests([](int32 id) { return true; }); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 4d552aaab..35f03301b 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -105,6 +105,8 @@ class Td final : public NetQueryCallback { void schedule_get_terms_of_service(int32 expires_in); + void schedule_get_promo_data(int32 expires_in); + void on_result(NetQueryPtr query) override; void on_update_server_time_difference(); @@ -232,6 +234,7 @@ class Td final : public NetQueryCallback { static constexpr int64 PING_SERVER_ALARM_ID = -1; static constexpr int32 PING_SERVER_TIMEOUT = 300; static constexpr int64 TERMS_OF_SERVICE_ALARM_ID = -2; + static constexpr int64 PROMO_DATA_ALARM_ID = -3; void on_connection_state_changed(StateManager::State new_state); @@ -305,6 +308,8 @@ class Td final : public NetQueryCallback { void on_get_terms_of_service(Result> result, bool dummy); + void on_get_promo_data(Result> result, bool dummy); + template friend class RequestActor; // uses send_result/send_error friend class TestQuery; // uses send_result/send_error, TODO pass Promise<> diff --git a/td/telegram/net/ConnectionCreator.cpp b/td/telegram/net/ConnectionCreator.cpp index 73e35a37c..2536273c4 100644 --- a/td/telegram/net/ConnectionCreator.cpp +++ b/td/telegram/net/ConnectionCreator.cpp @@ -18,6 +18,7 @@ #include "td/telegram/net/NetQueryDispatcher.h" #include "td/telegram/net/NetType.h" #include "td/telegram/StateManager.h" +#include "td/telegram/Td.h" #include "td/telegram/TdDb.h" #include "td/mtproto/Ping.h" @@ -440,7 +441,8 @@ void ConnectionCreator::enable_proxy_impl(int32 proxy_id) { void ConnectionCreator::disable_proxy_impl() { if (active_proxy_id_ == 0) { - on_get_proxy_info(make_tl_object(0)); + send_closure(G()->messages_manager(), &MessagesManager::remove_sponsored_dialog); + send_closure(G()->td(), &Td::schedule_get_promo_data, 0); return; } CHECK(proxies_.count(active_proxy_id_) == 1); @@ -472,13 +474,10 @@ void ConnectionCreator::on_proxy_changed(bool from_db) { resolve_proxy_timestamp_ = Timestamp(); proxy_ip_address_ = IPAddress(); - get_proxy_info_query_token_ = 0; - get_proxy_info_timestamp_ = Timestamp(); if (active_proxy_id_ == 0 || !from_db) { - on_get_proxy_info(make_tl_object(0)); - } else { - schedule_get_proxy_info(0); + send_closure(G()->messages_manager(), &MessagesManager::remove_sponsored_dialog); } + send_closure(G()->td(), &Td::schedule_get_promo_data, 0); loop(); } @@ -549,7 +548,6 @@ void ConnectionCreator::on_network(bool network_flag, uint32 network_generation) VLOG(connections) << "Set proxy query token to 0: " << old_generation << " " << network_generation_; resolve_proxy_query_token_ = 0; resolve_proxy_timestamp_ = Timestamp(); - get_proxy_info_timestamp_ = Timestamp(); for (auto &client : clients_) { client.second.backoff.clear(); @@ -1235,20 +1233,6 @@ void ConnectionCreator::loop() { } Timestamp timeout; - if (active_proxy_id_ != 0 && proxies_[active_proxy_id_].type() == Proxy::Type::Mtproto) { - if (get_proxy_info_timestamp_.is_in_past()) { - if (get_proxy_info_query_token_ == 0) { - get_proxy_info_query_token_ = next_token(); - auto query = G()->net_query_creator().create(telegram_api::help_getPromoData()); - G()->net_query_dispatcher().dispatch_with_callback(std::move(query), - actor_shared(this, get_proxy_info_query_token_)); - } - } else { - CHECK(get_proxy_info_query_token_ == 0); - timeout.relax(get_proxy_info_timestamp_); - } - } - if (active_proxy_id_ != 0) { if (resolve_proxy_timestamp_.is_in_past()) { if (resolve_proxy_query_token_ == 0) { @@ -1273,71 +1257,6 @@ void ConnectionCreator::loop() { } } -void ConnectionCreator::on_result(NetQueryPtr query) { - SCOPE_EXIT { - loop(); - }; - - if (get_link_token() != get_proxy_info_query_token_) { - return; - } - - get_proxy_info_query_token_ = 0; - auto res = fetch_result(std::move(query)); - if (res.is_error()) { - if (G()->close_flag()) { - return; - } - LOG(ERROR) << "Receive error for getProxyData: " << res.error(); - return schedule_get_proxy_info(60); - } - on_get_proxy_info(res.move_as_ok()); -} - -void ConnectionCreator::on_get_proxy_info(telegram_api::object_ptr promo_data_ptr) { - CHECK(promo_data_ptr != nullptr); - LOG(DEBUG) << "Receive " << to_string(promo_data_ptr); - int32 expires = 0; - switch (promo_data_ptr->get_id()) { - case telegram_api::help_promoDataEmpty::ID: { - auto promo = telegram_api::move_object_as(promo_data_ptr); - expires = promo->expires_; - send_closure(G()->messages_manager(), &MessagesManager::remove_sponsored_dialog); - break; - } - case telegram_api::help_promoData::ID: { - auto promo = telegram_api::move_object_as(promo_data_ptr); - expires = promo->expires_; - bool is_proxy = (promo->flags_ & telegram_api::help_promoData::PROXY_MASK) != 0; - send_closure(G()->messages_manager(), &MessagesManager::on_get_sponsored_dialog, std::move(promo->peer_), - is_proxy ? DialogSource::mtproto_proxy() - : DialogSource::public_service_announcement(promo->psa_type_, promo->psa_message_), - std::move(promo->users_), std::move(promo->chats_)); - break; - } - default: - UNREACHABLE(); - } - if (expires != 0) { - expires -= G()->unix_time(); - } - schedule_get_proxy_info(expires); -} - -void ConnectionCreator::schedule_get_proxy_info(int32 expires) { - if (expires < 0) { - LOG(ERROR) << "Receive wrong expires: " << expires; - expires = 0; - } - if (expires != 0 && expires < 60) { - expires = 60; - } - if (expires > 86400) { - expires = 86400; - } - get_proxy_info_timestamp_ = Timestamp::in(expires); -} - void ConnectionCreator::on_proxy_resolved(Result r_ip_address, bool dummy) { SCOPE_EXIT { loop(); diff --git a/td/telegram/net/ConnectionCreator.h b/td/telegram/net/ConnectionCreator.h index 61de8f1d8..6b1fc90cb 100644 --- a/td/telegram/net/ConnectionCreator.h +++ b/td/telegram/net/ConnectionCreator.h @@ -118,9 +118,6 @@ class ConnectionCreator : public NetQueryCallback { Timestamp resolve_proxy_timestamp_; uint64 resolve_proxy_query_token_{0}; - uint64 get_proxy_info_query_token_{0}; - Timestamp get_proxy_info_timestamp_; - struct ClientInfo { class Backoff { #if TD_ANDROID || TD_DARWIN_IOS || TD_DARWIN_WATCH_OS || TD_TIZEN @@ -207,8 +204,6 @@ class ConnectionCreator : public NetQueryCallback { void hangup() override; void loop() override; - void on_result(NetQueryPtr query) override; - void save_dc_options(); Result do_request_connection(DcId dc_id, bool allow_media_only); Result, bool>> do_request_raw_connection(DcId dc_id, @@ -229,10 +224,6 @@ class ConnectionCreator : public NetQueryCallback { uint64 auth_data_generation, int64 session_id); void client_set_timeout_at(ClientInfo &client, double wakeup_at); - void on_get_proxy_info(telegram_api::object_ptr proxy_data_ptr); - - void schedule_get_proxy_info(int32 expires); - void on_proxy_resolved(Result ip_address, bool dummy); struct FindConnectionExtra {