165 lines
4.9 KiB
C++
165 lines
4.9 KiB
C++
//
|
|
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024
|
|
//
|
|
// 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/OnlineManager.h"
|
|
|
|
#include "td/telegram/AuthManager.h"
|
|
#include "td/telegram/Global.h"
|
|
#include "td/telegram/OptionManager.h"
|
|
#include "td/telegram/StateManager.h"
|
|
#include "td/telegram/Td.h"
|
|
#include "td/telegram/telegram_api.h"
|
|
#include "td/telegram/UpdatesManager.h"
|
|
#include "td/telegram/UserManager.h"
|
|
|
|
#include "td/utils/buffer.h"
|
|
#include "td/utils/logging.h"
|
|
#include "td/utils/Random.h"
|
|
#include "td/utils/Status.h"
|
|
|
|
namespace td {
|
|
|
|
class UpdateStatusQuery final : public Td::ResultHandler {
|
|
bool is_offline_;
|
|
|
|
public:
|
|
NetQueryRef send(bool is_offline) {
|
|
is_offline_ = is_offline;
|
|
auto net_query = G()->net_query_creator().create(telegram_api::account_updateStatus(is_offline));
|
|
auto result = net_query.get_weak();
|
|
send_query(std::move(net_query));
|
|
return result;
|
|
}
|
|
|
|
void on_result(BufferSlice packet) final {
|
|
auto result_ptr = fetch_result<telegram_api::account_updateStatus>(packet);
|
|
if (result_ptr.is_error()) {
|
|
return on_error(result_ptr.move_as_error());
|
|
}
|
|
|
|
bool result = result_ptr.ok();
|
|
LOG(INFO) << "Receive result for UpdateStatusQuery: " << result;
|
|
td_->online_manager_->on_update_status_success(!is_offline_);
|
|
}
|
|
|
|
void on_error(Status status) final {
|
|
if (status.code() != NetQuery::Canceled && !G()->is_expected_error(status)) {
|
|
LOG(ERROR) << "Receive error for UpdateStatusQuery: " << status;
|
|
}
|
|
}
|
|
};
|
|
|
|
OnlineManager::OnlineManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::move(parent)) {
|
|
}
|
|
|
|
void OnlineManager::tear_down() {
|
|
parent_.reset();
|
|
}
|
|
|
|
void OnlineManager::start_up() {
|
|
init();
|
|
}
|
|
|
|
void OnlineManager::init() {
|
|
if (is_online_) {
|
|
on_online_updated(false /*ignored*/, true);
|
|
}
|
|
if (td_->auth_manager_->is_bot()) {
|
|
set_is_bot_online(true);
|
|
}
|
|
}
|
|
|
|
void OnlineManager::on_online_timeout_callback(void *online_manager_ptr) {
|
|
if (G()->close_flag()) {
|
|
return;
|
|
}
|
|
|
|
auto online_manager = static_cast<OnlineManager *>(online_manager_ptr);
|
|
send_closure_later(online_manager->actor_id(online_manager), &OnlineManager::on_online_updated, false, true);
|
|
}
|
|
|
|
void OnlineManager::on_ping_server_timeout_callback(void *online_manager_ptr) {
|
|
if (G()->close_flag()) {
|
|
return;
|
|
}
|
|
|
|
auto online_manager = static_cast<OnlineManager *>(online_manager_ptr);
|
|
send_closure_later(online_manager->actor_id(online_manager), &OnlineManager::on_ping_server_timeout);
|
|
}
|
|
|
|
void OnlineManager::on_online_updated(bool force, bool send_update) {
|
|
if (G()->close_flag() || !td_->auth_manager_->is_authorized() || td_->auth_manager_->is_bot()) {
|
|
return;
|
|
}
|
|
if (force || is_online_) {
|
|
td_->user_manager_->set_my_online_status(is_online_, send_update, true);
|
|
if (!update_status_query_.empty()) {
|
|
LOG(INFO) << "Cancel previous update status query";
|
|
cancel_query(update_status_query_);
|
|
}
|
|
update_status_query_ = td_->create_handler<UpdateStatusQuery>()->send(!is_online_);
|
|
}
|
|
if (is_online_) {
|
|
online_timeout_.set_callback(std::move(on_online_timeout_callback));
|
|
online_timeout_.set_callback_data(static_cast<void *>(this));
|
|
online_timeout_.set_timeout_in(static_cast<double>(G()->get_option_integer("online_update_period_ms", 210000)) *
|
|
1e-3);
|
|
} else {
|
|
online_timeout_.cancel_timeout();
|
|
}
|
|
}
|
|
|
|
void OnlineManager::on_update_status_success(bool is_online) {
|
|
if (is_online == is_online_) {
|
|
if (!update_status_query_.empty()) {
|
|
update_status_query_ = NetQueryRef();
|
|
}
|
|
td_->user_manager_->set_my_online_status(is_online_, true, false);
|
|
}
|
|
}
|
|
|
|
bool OnlineManager::is_online() const {
|
|
return is_online_;
|
|
}
|
|
|
|
void OnlineManager::set_is_online(bool is_online) {
|
|
if (is_online == is_online_) {
|
|
return;
|
|
}
|
|
|
|
is_online_ = is_online;
|
|
if (td_->auth_manager_ != nullptr) { // postpone if there is no AuthManager yet
|
|
on_online_updated(true, true);
|
|
}
|
|
}
|
|
|
|
void OnlineManager::set_is_bot_online(bool is_bot_online) {
|
|
ping_server_timeout_.set_callback(std::move(on_ping_server_timeout_callback));
|
|
ping_server_timeout_.set_callback_data(static_cast<void *>(this));
|
|
ping_server_timeout_.set_timeout_in(PING_SERVER_TIMEOUT + Random::fast(0, PING_SERVER_TIMEOUT / 5));
|
|
|
|
if (td_->option_manager_->get_option_integer("session_count") > 1) {
|
|
is_bot_online = false;
|
|
}
|
|
|
|
if (is_bot_online == is_bot_online_) {
|
|
return;
|
|
}
|
|
|
|
is_bot_online_ = is_bot_online;
|
|
send_closure(G()->state_manager(), &StateManager::on_online, is_bot_online_);
|
|
}
|
|
|
|
void OnlineManager::on_ping_server_timeout() {
|
|
if (G()->close_flag() || td_->updates_manager_ == nullptr || !td_->auth_manager_->is_authorized()) {
|
|
return;
|
|
}
|
|
td_->updates_manager_->ping_server();
|
|
set_is_bot_online(false);
|
|
}
|
|
|
|
} // namespace td
|