Move some methods to PeopleNearbyManager.
This commit is contained in:
parent
1e6c1dbb12
commit
2c61318a11
@ -47,6 +47,7 @@
|
||||
#include "td/telegram/NotificationManager.h"
|
||||
#include "td/telegram/OptionManager.h"
|
||||
#include "td/telegram/PeerColor.h"
|
||||
#include "td/telegram/PeopleNearbyManager.h"
|
||||
#include "td/telegram/Photo.h"
|
||||
#include "td/telegram/Photo.hpp"
|
||||
#include "td/telegram/PhotoSize.h"
|
||||
@ -443,40 +444,6 @@ class ResetContactsQuery final : public Td::ResultHandler {
|
||||
}
|
||||
};
|
||||
|
||||
class SearchDialogsNearbyQuery final : public Td::ResultHandler {
|
||||
Promise<tl_object_ptr<telegram_api::Updates>> promise_;
|
||||
|
||||
public:
|
||||
explicit SearchDialogsNearbyQuery(Promise<tl_object_ptr<telegram_api::Updates>> &&promise)
|
||||
: promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
void send(const Location &location, bool from_background, int32 expire_date) {
|
||||
int32 flags = 0;
|
||||
if (from_background) {
|
||||
flags |= telegram_api::contacts_getLocated::BACKGROUND_MASK;
|
||||
}
|
||||
if (expire_date != -1) {
|
||||
flags |= telegram_api::contacts_getLocated::SELF_EXPIRES_MASK;
|
||||
}
|
||||
send_query(G()->net_query_creator().create(
|
||||
telegram_api::contacts_getLocated(flags, false /*ignored*/, location.get_input_geo_point(), expire_date)));
|
||||
}
|
||||
|
||||
void on_result(BufferSlice packet) final {
|
||||
auto result_ptr = fetch_result<telegram_api::contacts_getLocated>(packet);
|
||||
if (result_ptr.is_error()) {
|
||||
return on_error(result_ptr.move_as_error());
|
||||
}
|
||||
|
||||
promise_.set_value(result_ptr.move_as_ok());
|
||||
}
|
||||
|
||||
void on_error(Status status) final {
|
||||
promise_.set_error(std::move(status));
|
||||
}
|
||||
};
|
||||
|
||||
class UploadProfilePhotoQuery final : public Td::ResultHandler {
|
||||
Promise<Unit> promise_;
|
||||
UserId user_id_;
|
||||
@ -2851,21 +2818,6 @@ ContactsManager::ContactsManager(Td *td, ActorShared<> parent) : td_(td), parent
|
||||
if (was_online_local_ >= unix_time && !td_->is_online()) {
|
||||
was_online_local_ = unix_time - 1;
|
||||
}
|
||||
|
||||
location_visibility_expire_date_ =
|
||||
to_integer<int32>(G()->td_db()->get_binlog_pmc()->get("location_visibility_expire_date"));
|
||||
if (location_visibility_expire_date_ != 0 && location_visibility_expire_date_ <= G()->unix_time()) {
|
||||
location_visibility_expire_date_ = 0;
|
||||
G()->td_db()->get_binlog_pmc()->erase("location_visibility_expire_date");
|
||||
}
|
||||
auto pending_location_visibility_expire_date_string =
|
||||
G()->td_db()->get_binlog_pmc()->get("pending_location_visibility_expire_date");
|
||||
if (!pending_location_visibility_expire_date_string.empty()) {
|
||||
pending_location_visibility_expire_date_ = to_integer<int32>(pending_location_visibility_expire_date_string);
|
||||
}
|
||||
update_is_location_visible();
|
||||
LOG(INFO) << "Loaded location_visibility_expire_date = " << location_visibility_expire_date_
|
||||
<< " and pending_location_visibility_expire_date = " << pending_location_visibility_expire_date_;
|
||||
}
|
||||
|
||||
user_online_timeout_.set_callback(on_user_online_timeout_callback);
|
||||
@ -2880,9 +2832,6 @@ ContactsManager::ContactsManager(Td *td, ActorShared<> parent) : td_(td), parent
|
||||
channel_unban_timeout_.set_callback(on_channel_unban_timeout_callback);
|
||||
channel_unban_timeout_.set_callback_data(static_cast<void *>(this));
|
||||
|
||||
user_nearby_timeout_.set_callback(on_user_nearby_timeout_callback);
|
||||
user_nearby_timeout_.set_callback_data(static_cast<void *>(this));
|
||||
|
||||
slow_mode_delay_timeout_.set_callback(on_slow_mode_delay_timeout_callback);
|
||||
slow_mode_delay_timeout_.set_callback_data(static_cast<void *>(this));
|
||||
|
||||
@ -2928,12 +2877,6 @@ ContactsManager::~ContactsManager() {
|
||||
restricted_user_ids_, restricted_channel_ids_);
|
||||
}
|
||||
|
||||
void ContactsManager::start_up() {
|
||||
if (!pending_location_visibility_expire_date_) {
|
||||
try_send_set_location_visibility_query();
|
||||
}
|
||||
}
|
||||
|
||||
void ContactsManager::tear_down() {
|
||||
parent_.reset();
|
||||
|
||||
@ -3066,35 +3009,6 @@ void ContactsManager::on_channel_unban_timeout(ChannelId channel_id) {
|
||||
update_channel(c, channel_id); // always call, because in case of failure we need to reactivate timeout
|
||||
}
|
||||
|
||||
void ContactsManager::on_user_nearby_timeout_callback(void *contacts_manager_ptr, int64 user_id_long) {
|
||||
if (G()->close_flag()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto contacts_manager = static_cast<ContactsManager *>(contacts_manager_ptr);
|
||||
send_closure_later(contacts_manager->actor_id(contacts_manager), &ContactsManager::on_user_nearby_timeout,
|
||||
UserId(user_id_long));
|
||||
}
|
||||
|
||||
void ContactsManager::on_user_nearby_timeout(UserId user_id) {
|
||||
if (G()->close_flag()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto u = get_user(user_id);
|
||||
CHECK(u != nullptr);
|
||||
|
||||
LOG(INFO) << "Remove " << user_id << " from nearby list";
|
||||
DialogId dialog_id(user_id);
|
||||
for (size_t i = 0; i < users_nearby_.size(); i++) {
|
||||
if (users_nearby_[i].dialog_id == dialog_id) {
|
||||
users_nearby_.erase(users_nearby_.begin() + i);
|
||||
send_update_users_nearby();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ContactsManager::on_slow_mode_delay_timeout_callback(void *contacts_manager_ptr, int64 channel_id_long) {
|
||||
if (G()->close_flag()) {
|
||||
return;
|
||||
@ -6133,330 +6047,6 @@ void ContactsManager::share_phone_number(UserId user_id, Promise<Unit> &&promise
|
||||
td_->create_handler<AcceptContactQuery>(std::move(promise))->send(user_id, std::move(input_user));
|
||||
}
|
||||
|
||||
void ContactsManager::search_dialogs_nearby(const Location &location,
|
||||
Promise<td_api::object_ptr<td_api::chatsNearby>> &&promise) {
|
||||
if (location.empty()) {
|
||||
return promise.set_error(Status::Error(400, "Invalid location specified"));
|
||||
}
|
||||
last_user_location_ = location;
|
||||
try_send_set_location_visibility_query();
|
||||
|
||||
auto query_promise = PromiseCreator::lambda([actor_id = actor_id(this), promise = std::move(promise)](
|
||||
Result<tl_object_ptr<telegram_api::Updates>> result) mutable {
|
||||
send_closure(actor_id, &ContactsManager::on_get_dialogs_nearby, std::move(result), std::move(promise));
|
||||
});
|
||||
td_->create_handler<SearchDialogsNearbyQuery>(std::move(query_promise))->send(location, false, -1);
|
||||
}
|
||||
|
||||
vector<td_api::object_ptr<td_api::chatNearby>> ContactsManager::get_chats_nearby_object(
|
||||
const vector<DialogNearby> &dialogs_nearby) const {
|
||||
return transform(dialogs_nearby, [td = td_](const DialogNearby &dialog_nearby) {
|
||||
return td_api::make_object<td_api::chatNearby>(
|
||||
td->dialog_manager_->get_chat_id_object(dialog_nearby.dialog_id, "chatNearby"), dialog_nearby.distance);
|
||||
});
|
||||
}
|
||||
|
||||
void ContactsManager::send_update_users_nearby() const {
|
||||
send_closure(G()->td(), &Td::send_update,
|
||||
td_api::make_object<td_api::updateUsersNearby>(get_chats_nearby_object(users_nearby_)));
|
||||
}
|
||||
|
||||
void ContactsManager::on_get_dialogs_nearby(Result<tl_object_ptr<telegram_api::Updates>> result,
|
||||
Promise<td_api::object_ptr<td_api::chatsNearby>> &&promise) {
|
||||
if (result.is_error()) {
|
||||
return promise.set_error(result.move_as_error());
|
||||
}
|
||||
|
||||
auto updates_ptr = result.move_as_ok();
|
||||
if (updates_ptr->get_id() != telegram_api::updates::ID) {
|
||||
LOG(ERROR) << "Receive " << oneline(to_string(*updates_ptr)) << " instead of updates";
|
||||
return promise.set_error(Status::Error(500, "Receive unsupported response from the server"));
|
||||
}
|
||||
|
||||
auto update = telegram_api::move_object_as<telegram_api::updates>(updates_ptr);
|
||||
LOG(INFO) << "Receive chats nearby in " << to_string(update);
|
||||
|
||||
on_get_users(std::move(update->users_), "on_get_dialogs_nearby");
|
||||
on_get_chats(std::move(update->chats_), "on_get_dialogs_nearby");
|
||||
|
||||
for (auto &dialog_nearby : users_nearby_) {
|
||||
user_nearby_timeout_.cancel_timeout(dialog_nearby.dialog_id.get_user_id().get());
|
||||
}
|
||||
auto old_users_nearby = std::move(users_nearby_);
|
||||
users_nearby_.clear();
|
||||
channels_nearby_.clear();
|
||||
int32 location_visibility_expire_date = 0;
|
||||
for (auto &update_ptr : update->updates_) {
|
||||
if (update_ptr->get_id() != telegram_api::updatePeerLocated::ID) {
|
||||
LOG(ERROR) << "Receive unexpected " << to_string(update);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto expire_date = on_update_peer_located(
|
||||
std::move(static_cast<telegram_api::updatePeerLocated *>(update_ptr.get())->peers_), false);
|
||||
if (expire_date != -1) {
|
||||
location_visibility_expire_date = expire_date;
|
||||
}
|
||||
}
|
||||
if (location_visibility_expire_date != location_visibility_expire_date_) {
|
||||
set_location_visibility_expire_date(location_visibility_expire_date);
|
||||
update_is_location_visible();
|
||||
}
|
||||
|
||||
std::sort(users_nearby_.begin(), users_nearby_.end());
|
||||
if (old_users_nearby != users_nearby_) {
|
||||
send_update_users_nearby(); // for other clients connected to the same TDLib instance
|
||||
}
|
||||
promise.set_value(td_api::make_object<td_api::chatsNearby>(get_chats_nearby_object(users_nearby_),
|
||||
get_chats_nearby_object(channels_nearby_)));
|
||||
}
|
||||
|
||||
void ContactsManager::set_location(const Location &location, Promise<Unit> &&promise) {
|
||||
if (location.empty()) {
|
||||
return promise.set_error(Status::Error(400, "Invalid location specified"));
|
||||
}
|
||||
last_user_location_ = location;
|
||||
try_send_set_location_visibility_query();
|
||||
|
||||
auto query_promise = PromiseCreator::lambda(
|
||||
[promise = std::move(promise)](Result<tl_object_ptr<telegram_api::Updates>> result) mutable {
|
||||
promise.set_value(Unit());
|
||||
});
|
||||
td_->create_handler<SearchDialogsNearbyQuery>(std::move(query_promise))->send(location, true, -1);
|
||||
}
|
||||
|
||||
void ContactsManager::set_location_visibility(Td *td) {
|
||||
bool is_location_visible = td->option_manager_->get_option_boolean("is_location_visible");
|
||||
auto pending_location_visibility_expire_date = is_location_visible ? std::numeric_limits<int32>::max() : 0;
|
||||
if (td->contacts_manager_ == nullptr) {
|
||||
G()->td_db()->get_binlog_pmc()->set("pending_location_visibility_expire_date",
|
||||
to_string(pending_location_visibility_expire_date));
|
||||
return;
|
||||
}
|
||||
if (td->contacts_manager_->pending_location_visibility_expire_date_ == -1 &&
|
||||
pending_location_visibility_expire_date == td->contacts_manager_->location_visibility_expire_date_) {
|
||||
return;
|
||||
}
|
||||
if (td->contacts_manager_->pending_location_visibility_expire_date_ != pending_location_visibility_expire_date) {
|
||||
td->contacts_manager_->pending_location_visibility_expire_date_ = pending_location_visibility_expire_date;
|
||||
G()->td_db()->get_binlog_pmc()->set("pending_location_visibility_expire_date",
|
||||
to_string(pending_location_visibility_expire_date));
|
||||
}
|
||||
td->contacts_manager_->try_send_set_location_visibility_query();
|
||||
}
|
||||
|
||||
void ContactsManager::try_send_set_location_visibility_query() {
|
||||
if (G()->close_flag()) {
|
||||
return;
|
||||
}
|
||||
if (pending_location_visibility_expire_date_ == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(INFO) << "Trying to send set location visibility query";
|
||||
if (is_set_location_visibility_request_sent_) {
|
||||
return;
|
||||
}
|
||||
if (pending_location_visibility_expire_date_ != 0 && last_user_location_.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
is_set_location_visibility_request_sent_ = true;
|
||||
auto query_promise =
|
||||
PromiseCreator::lambda([actor_id = actor_id(this), set_expire_date = pending_location_visibility_expire_date_](
|
||||
Result<tl_object_ptr<telegram_api::Updates>> result) {
|
||||
send_closure(actor_id, &ContactsManager::on_set_location_visibility_expire_date, set_expire_date,
|
||||
result.is_ok() ? 0 : result.error().code());
|
||||
});
|
||||
td_->create_handler<SearchDialogsNearbyQuery>(std::move(query_promise))
|
||||
->send(last_user_location_, true, pending_location_visibility_expire_date_);
|
||||
}
|
||||
|
||||
void ContactsManager::on_set_location_visibility_expire_date(int32 set_expire_date, int32 error_code) {
|
||||
bool success = error_code == 0;
|
||||
is_set_location_visibility_request_sent_ = false;
|
||||
|
||||
if (set_expire_date != pending_location_visibility_expire_date_) {
|
||||
try_send_set_location_visibility_query();
|
||||
return;
|
||||
}
|
||||
|
||||
if (success) {
|
||||
set_location_visibility_expire_date(pending_location_visibility_expire_date_);
|
||||
} else {
|
||||
if (G()->close_flag()) {
|
||||
// request will be re-sent after restart
|
||||
return;
|
||||
}
|
||||
if (error_code != 406) {
|
||||
LOG(ERROR) << "Failed to set location visibility expire date to " << pending_location_visibility_expire_date_;
|
||||
}
|
||||
}
|
||||
G()->td_db()->get_binlog_pmc()->erase("pending_location_visibility_expire_date");
|
||||
pending_location_visibility_expire_date_ = -1;
|
||||
update_is_location_visible();
|
||||
}
|
||||
|
||||
void ContactsManager::get_is_location_visible(Promise<Unit> &&promise) {
|
||||
auto query_promise = PromiseCreator::lambda([actor_id = actor_id(this), promise = std::move(promise)](
|
||||
Result<tl_object_ptr<telegram_api::Updates>> result) mutable {
|
||||
send_closure(actor_id, &ContactsManager::on_get_is_location_visible, std::move(result), std::move(promise));
|
||||
});
|
||||
td_->create_handler<SearchDialogsNearbyQuery>(std::move(query_promise))->send(Location(), true, -1);
|
||||
}
|
||||
|
||||
void ContactsManager::on_get_is_location_visible(Result<tl_object_ptr<telegram_api::Updates>> &&result,
|
||||
Promise<Unit> &&promise) {
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
if (result.is_error()) {
|
||||
if (result.error().message() == "GEO_POINT_INVALID" && pending_location_visibility_expire_date_ == -1 &&
|
||||
location_visibility_expire_date_ > 0) {
|
||||
set_location_visibility_expire_date(0);
|
||||
update_is_location_visible();
|
||||
}
|
||||
return promise.set_value(Unit());
|
||||
}
|
||||
|
||||
auto updates_ptr = result.move_as_ok();
|
||||
if (updates_ptr->get_id() != telegram_api::updates::ID) {
|
||||
LOG(ERROR) << "Receive " << oneline(to_string(*updates_ptr)) << " instead of updates";
|
||||
return promise.set_value(Unit());
|
||||
}
|
||||
|
||||
auto updates = std::move(telegram_api::move_object_as<telegram_api::updates>(updates_ptr)->updates_);
|
||||
if (updates.size() != 1 || updates[0]->get_id() != telegram_api::updatePeerLocated::ID) {
|
||||
LOG(ERROR) << "Receive unexpected " << to_string(updates);
|
||||
return promise.set_value(Unit());
|
||||
}
|
||||
|
||||
auto peers = std::move(static_cast<telegram_api::updatePeerLocated *>(updates[0].get())->peers_);
|
||||
if (peers.size() != 1 || peers[0]->get_id() != telegram_api::peerSelfLocated::ID) {
|
||||
LOG(ERROR) << "Receive unexpected " << to_string(peers);
|
||||
return promise.set_value(Unit());
|
||||
}
|
||||
|
||||
auto location_visibility_expire_date = static_cast<telegram_api::peerSelfLocated *>(peers[0].get())->expires_;
|
||||
if (location_visibility_expire_date != location_visibility_expire_date_) {
|
||||
set_location_visibility_expire_date(location_visibility_expire_date);
|
||||
update_is_location_visible();
|
||||
}
|
||||
|
||||
promise.set_value(Unit());
|
||||
}
|
||||
|
||||
int32 ContactsManager::on_update_peer_located(vector<tl_object_ptr<telegram_api::PeerLocated>> &&peers,
|
||||
bool from_update) {
|
||||
auto now = G()->unix_time();
|
||||
bool need_update = false;
|
||||
int32 location_visibility_expire_date = -1;
|
||||
for (auto &peer_located_ptr : peers) {
|
||||
if (peer_located_ptr->get_id() == telegram_api::peerSelfLocated::ID) {
|
||||
auto peer_self_located = telegram_api::move_object_as<telegram_api::peerSelfLocated>(peer_located_ptr);
|
||||
if (peer_self_located->expires_ == 0 || peer_self_located->expires_ > G()->unix_time()) {
|
||||
location_visibility_expire_date = peer_self_located->expires_;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
CHECK(peer_located_ptr->get_id() == telegram_api::peerLocated::ID);
|
||||
auto peer_located = telegram_api::move_object_as<telegram_api::peerLocated>(peer_located_ptr);
|
||||
DialogId dialog_id(peer_located->peer_);
|
||||
int32 expires_at = peer_located->expires_;
|
||||
int32 distance = peer_located->distance_;
|
||||
if (distance < 0 || distance > 50000000) {
|
||||
LOG(ERROR) << "Receive wrong distance to " << to_string(peer_located);
|
||||
continue;
|
||||
}
|
||||
if (expires_at <= now) {
|
||||
LOG(INFO) << "Skip expired result " << to_string(peer_located);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto dialog_type = dialog_id.get_type();
|
||||
if (dialog_type == DialogType::User) {
|
||||
auto user_id = dialog_id.get_user_id();
|
||||
if (!have_user(user_id)) {
|
||||
LOG(ERROR) << "Can't find " << user_id;
|
||||
continue;
|
||||
}
|
||||
if (expires_at < now + 86400) {
|
||||
user_nearby_timeout_.set_timeout_in(user_id.get(), expires_at - now + 1);
|
||||
}
|
||||
} else if (dialog_type == DialogType::Channel) {
|
||||
auto channel_id = dialog_id.get_channel_id();
|
||||
if (!have_channel(channel_id)) {
|
||||
LOG(ERROR) << "Can't find " << channel_id;
|
||||
continue;
|
||||
}
|
||||
if (expires_at != std::numeric_limits<int32>::max()) {
|
||||
LOG(ERROR) << "Receive expiring at " << expires_at << " group location in " << to_string(peer_located);
|
||||
}
|
||||
if (from_update) {
|
||||
LOG(ERROR) << "Receive nearby " << channel_id << " from update";
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
LOG(ERROR) << "Receive chat of wrong type in " << to_string(peer_located);
|
||||
continue;
|
||||
}
|
||||
|
||||
td_->dialog_manager_->force_create_dialog(dialog_id, "on_update_peer_located");
|
||||
|
||||
if (from_update) {
|
||||
CHECK(dialog_type == DialogType::User);
|
||||
bool is_found = false;
|
||||
for (auto &dialog_nearby : users_nearby_) {
|
||||
if (dialog_nearby.dialog_id == dialog_id) {
|
||||
if (dialog_nearby.distance != distance) {
|
||||
dialog_nearby.distance = distance;
|
||||
need_update = true;
|
||||
}
|
||||
is_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!is_found) {
|
||||
users_nearby_.emplace_back(dialog_id, distance);
|
||||
all_users_nearby_.insert(dialog_id.get_user_id());
|
||||
need_update = true;
|
||||
}
|
||||
} else {
|
||||
if (dialog_type == DialogType::User) {
|
||||
users_nearby_.emplace_back(dialog_id, distance);
|
||||
all_users_nearby_.insert(dialog_id.get_user_id());
|
||||
} else {
|
||||
channels_nearby_.emplace_back(dialog_id, distance);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (need_update) {
|
||||
std::sort(users_nearby_.begin(), users_nearby_.end());
|
||||
send_update_users_nearby();
|
||||
}
|
||||
return location_visibility_expire_date;
|
||||
}
|
||||
|
||||
void ContactsManager::set_location_visibility_expire_date(int32 expire_date) {
|
||||
if (location_visibility_expire_date_ == expire_date) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(INFO) << "Set set_location_visibility_expire_date to " << expire_date;
|
||||
location_visibility_expire_date_ = expire_date;
|
||||
if (expire_date == 0) {
|
||||
G()->td_db()->get_binlog_pmc()->erase("location_visibility_expire_date");
|
||||
} else {
|
||||
G()->td_db()->get_binlog_pmc()->set("location_visibility_expire_date", to_string(expire_date));
|
||||
}
|
||||
// the caller must call update_is_location_visible() itself
|
||||
}
|
||||
|
||||
void ContactsManager::update_is_location_visible() {
|
||||
auto expire_date = pending_location_visibility_expire_date_ != -1 ? pending_location_visibility_expire_date_
|
||||
: location_visibility_expire_date_;
|
||||
td_->option_manager_->set_option_boolean("is_location_visible", expire_date != 0);
|
||||
}
|
||||
|
||||
void ContactsManager::on_update_bot_menu_button(UserId bot_user_id,
|
||||
tl_object_ptr<telegram_api::BotMenuButton> &&bot_menu_button) {
|
||||
if (!bot_user_id.is_valid()) {
|
||||
@ -15081,7 +14671,8 @@ bool ContactsManager::is_user_status_exact(UserId user_id) const {
|
||||
|
||||
bool ContactsManager::can_report_user(UserId user_id) const {
|
||||
auto u = get_user(user_id);
|
||||
return u != nullptr && !u->is_deleted && !u->is_support && (u->is_bot || all_users_nearby_.count(user_id) != 0);
|
||||
return u != nullptr && !u->is_deleted && !u->is_support &&
|
||||
(u->is_bot || td_->people_nearby_manager_->is_user_nearby(user_id));
|
||||
}
|
||||
|
||||
const ContactsManager::User *ContactsManager::get_user(UserId user_id) const {
|
||||
|
@ -23,7 +23,6 @@
|
||||
#include "td/telegram/files/FileId.h"
|
||||
#include "td/telegram/files/FileSourceId.h"
|
||||
#include "td/telegram/FolderId.h"
|
||||
#include "td/telegram/Location.h"
|
||||
#include "td/telegram/MessageFullId.h"
|
||||
#include "td/telegram/MessageId.h"
|
||||
#include "td/telegram/MessageTtl.h"
|
||||
@ -306,8 +305,6 @@ class ContactsManager final : public Actor {
|
||||
void on_update_channel_administrator_count(ChannelId channel_id, int32 administrator_count);
|
||||
void on_update_channel_bot_commands(ChannelId channel_id, BotCommands &&bot_commands);
|
||||
|
||||
int32 on_update_peer_located(vector<tl_object_ptr<telegram_api::PeerLocated>> &&peers, bool from_update);
|
||||
|
||||
void on_update_bot_menu_button(UserId bot_user_id, tl_object_ptr<telegram_api::BotMenuButton> &&bot_menu_button);
|
||||
|
||||
void speculative_add_channel_participants(ChannelId channel_id, const vector<UserId> &added_user_ids,
|
||||
@ -423,14 +420,6 @@ class ContactsManager final : public Actor {
|
||||
|
||||
void share_phone_number(UserId user_id, Promise<Unit> &&promise);
|
||||
|
||||
void search_dialogs_nearby(const Location &location, Promise<td_api::object_ptr<td_api::chatsNearby>> &&promise);
|
||||
|
||||
void set_location(const Location &location, Promise<Unit> &&promise);
|
||||
|
||||
static void set_location_visibility(Td *td);
|
||||
|
||||
void get_is_location_visible(Promise<Unit> &&promise);
|
||||
|
||||
void register_suggested_profile_photo(const Photo &photo);
|
||||
|
||||
FileId get_profile_photo_file_id(int64 photo_id) const;
|
||||
@ -1138,26 +1127,6 @@ class ContactsManager final : public Actor {
|
||||
vector<PendingGetPhotoRequest> pending_requests;
|
||||
};
|
||||
|
||||
struct DialogNearby {
|
||||
DialogId dialog_id;
|
||||
int32 distance;
|
||||
|
||||
DialogNearby(DialogId dialog_id, int32 distance) : dialog_id(dialog_id), distance(distance) {
|
||||
}
|
||||
|
||||
bool operator<(const DialogNearby &other) const {
|
||||
return distance < other.distance || (distance == other.distance && dialog_id.get() < other.dialog_id.get());
|
||||
}
|
||||
|
||||
bool operator==(const DialogNearby &other) const {
|
||||
return distance == other.distance && dialog_id == other.dialog_id;
|
||||
}
|
||||
|
||||
bool operator!=(const DialogNearby &other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
};
|
||||
|
||||
struct RecommendedDialogs {
|
||||
int32 total_count_ = 0;
|
||||
vector<DialogId> dialog_ids_;
|
||||
@ -1654,24 +1623,6 @@ class ContactsManager final : public Actor {
|
||||
void on_clear_imported_contacts(vector<Contact> &&contacts, vector<size_t> contacts_unique_id,
|
||||
std::pair<vector<size_t>, vector<Contact>> &&to_add, Promise<Unit> &&promise);
|
||||
|
||||
vector<td_api::object_ptr<td_api::chatNearby>> get_chats_nearby_object(
|
||||
const vector<DialogNearby> &dialogs_nearby) const;
|
||||
|
||||
void send_update_users_nearby() const;
|
||||
|
||||
void on_get_dialogs_nearby(Result<tl_object_ptr<telegram_api::Updates>> result,
|
||||
Promise<td_api::object_ptr<td_api::chatsNearby>> &&promise);
|
||||
|
||||
void try_send_set_location_visibility_query();
|
||||
|
||||
void on_set_location_visibility_expire_date(int32 set_expire_date, int32 error_code);
|
||||
|
||||
void set_location_visibility_expire_date(int32 expire_date);
|
||||
|
||||
void on_get_is_location_visible(Result<tl_object_ptr<telegram_api::Updates>> &&result, Promise<Unit> &&promise);
|
||||
|
||||
void update_is_location_visible();
|
||||
|
||||
bool is_suitable_recommended_channel(DialogId dialog_id) const;
|
||||
|
||||
bool is_suitable_recommended_channel(ChannelId channel_id) const;
|
||||
@ -1802,8 +1753,6 @@ class ContactsManager final : public Actor {
|
||||
|
||||
static void on_channel_unban_timeout_callback(void *contacts_manager_ptr, int64 channel_id_long);
|
||||
|
||||
static void on_user_nearby_timeout_callback(void *contacts_manager_ptr, int64 user_id_long);
|
||||
|
||||
static void on_slow_mode_delay_timeout_callback(void *contacts_manager_ptr, int64 channel_id_long);
|
||||
|
||||
void on_user_online_timeout(UserId user_id);
|
||||
@ -1814,12 +1763,8 @@ class ContactsManager final : public Actor {
|
||||
|
||||
void on_channel_unban_timeout(ChannelId channel_id);
|
||||
|
||||
void on_user_nearby_timeout(UserId user_id);
|
||||
|
||||
void on_slow_mode_delay_timeout(ChannelId channel_id);
|
||||
|
||||
void start_up() final;
|
||||
|
||||
void tear_down() final;
|
||||
|
||||
Td *td_;
|
||||
@ -1959,15 +1904,6 @@ class ContactsManager final : public Actor {
|
||||
bool are_imported_contacts_changing_ = false;
|
||||
bool need_clear_imported_contacts_ = false;
|
||||
|
||||
vector<DialogNearby> users_nearby_;
|
||||
vector<DialogNearby> channels_nearby_;
|
||||
FlatHashSet<UserId, UserIdHash> all_users_nearby_;
|
||||
|
||||
int32 location_visibility_expire_date_ = 0;
|
||||
int32 pending_location_visibility_expire_date_ = -1;
|
||||
bool is_set_location_visibility_request_sent_ = false;
|
||||
Location last_user_location_;
|
||||
|
||||
FlatHashMap<UserId, bool, UserIdHash> user_full_contact_require_premium_;
|
||||
|
||||
WaitFreeHashMap<ChannelId, ChannelId, ChannelIdHash> linked_channel_ids_;
|
||||
@ -1986,7 +1922,6 @@ class ContactsManager final : public Actor {
|
||||
MultiTimeout user_emoji_status_timeout_{"UserEmojiStatusTimeout"};
|
||||
MultiTimeout channel_emoji_status_timeout_{"ChannelEmojiStatusTimeout"};
|
||||
MultiTimeout channel_unban_timeout_{"ChannelUnbanTimeout"};
|
||||
MultiTimeout user_nearby_timeout_{"UserNearbyTimeout"};
|
||||
MultiTimeout slow_mode_delay_timeout_{"SlowModeDelayTimeout"};
|
||||
};
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "td/telegram/net/MtprotoHeader.h"
|
||||
#include "td/telegram/net/NetQueryDispatcher.h"
|
||||
#include "td/telegram/NotificationManager.h"
|
||||
#include "td/telegram/PeopleNearbyManager.h"
|
||||
#include "td/telegram/ReactionType.h"
|
||||
#include "td/telegram/StateManager.h"
|
||||
#include "td/telegram/StickersManager.h"
|
||||
@ -636,7 +637,8 @@ void OptionManager::get_option(const string &name, Promise<td_api::object_ptr<td
|
||||
}
|
||||
if (!is_bot && name == "is_location_visible") {
|
||||
if (is_td_inited_) {
|
||||
send_closure_later(td_->contacts_manager_actor_, &ContactsManager::get_is_location_visible, wrap_promise());
|
||||
send_closure_later(td_->people_nearby_manager_actor_, &PeopleNearbyManager::get_is_location_visible,
|
||||
wrap_promise());
|
||||
} else {
|
||||
pending_get_options_.emplace_back(name, std::move(promise));
|
||||
}
|
||||
@ -842,7 +844,7 @@ void OptionManager::set_option(const string &name, td_api::object_ptr<td_api::Op
|
||||
return;
|
||||
}
|
||||
if (!is_bot && set_boolean_option("is_location_visible")) {
|
||||
ContactsManager::set_location_visibility(td_);
|
||||
PeopleNearbyManager::set_location_visibility(td_);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
@ -6,13 +6,444 @@
|
||||
//
|
||||
#include "td/telegram/PeopleNearbyManager.h"
|
||||
|
||||
#include "td/telegram/AuthManager.h"
|
||||
#include "td/telegram/ContactsManager.h"
|
||||
#include "td/telegram/DialogManager.h"
|
||||
#include "td/telegram/Global.h"
|
||||
#include "td/telegram/OptionManager.h"
|
||||
#include "td/telegram/Td.h"
|
||||
#include "td/telegram/TdDb.h"
|
||||
#include "td/telegram/telegram_api.h"
|
||||
|
||||
#include "td/utils/algorithm.h"
|
||||
#include "td/utils/buffer.h"
|
||||
#include "td/utils/logging.h"
|
||||
#include "td/utils/misc.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
|
||||
namespace td {
|
||||
|
||||
class SearchDialogsNearbyQuery final : public Td::ResultHandler {
|
||||
Promise<telegram_api::object_ptr<telegram_api::Updates>> promise_;
|
||||
|
||||
public:
|
||||
explicit SearchDialogsNearbyQuery(Promise<telegram_api::object_ptr<telegram_api::Updates>> &&promise)
|
||||
: promise_(std::move(promise)) {
|
||||
}
|
||||
|
||||
void send(const Location &location, bool from_background, int32 expire_date) {
|
||||
int32 flags = 0;
|
||||
if (from_background) {
|
||||
flags |= telegram_api::contacts_getLocated::BACKGROUND_MASK;
|
||||
}
|
||||
if (expire_date != -1) {
|
||||
flags |= telegram_api::contacts_getLocated::SELF_EXPIRES_MASK;
|
||||
}
|
||||
send_query(G()->net_query_creator().create(
|
||||
telegram_api::contacts_getLocated(flags, false /*ignored*/, location.get_input_geo_point(), expire_date)));
|
||||
}
|
||||
|
||||
void on_result(BufferSlice packet) final {
|
||||
auto result_ptr = fetch_result<telegram_api::contacts_getLocated>(packet);
|
||||
if (result_ptr.is_error()) {
|
||||
return on_error(result_ptr.move_as_error());
|
||||
}
|
||||
|
||||
promise_.set_value(result_ptr.move_as_ok());
|
||||
}
|
||||
|
||||
void on_error(Status status) final {
|
||||
promise_.set_error(std::move(status));
|
||||
}
|
||||
};
|
||||
|
||||
PeopleNearbyManager::PeopleNearbyManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::move(parent)) {
|
||||
if (!td_->auth_manager_->is_bot()) {
|
||||
location_visibility_expire_date_ =
|
||||
to_integer<int32>(G()->td_db()->get_binlog_pmc()->get("location_visibility_expire_date"));
|
||||
if (location_visibility_expire_date_ != 0 && location_visibility_expire_date_ <= G()->unix_time()) {
|
||||
location_visibility_expire_date_ = 0;
|
||||
G()->td_db()->get_binlog_pmc()->erase("location_visibility_expire_date");
|
||||
}
|
||||
auto pending_location_visibility_expire_date_string =
|
||||
G()->td_db()->get_binlog_pmc()->get("pending_location_visibility_expire_date");
|
||||
if (!pending_location_visibility_expire_date_string.empty()) {
|
||||
pending_location_visibility_expire_date_ = to_integer<int32>(pending_location_visibility_expire_date_string);
|
||||
}
|
||||
update_is_location_visible();
|
||||
LOG(INFO) << "Loaded location_visibility_expire_date = " << location_visibility_expire_date_
|
||||
<< " and pending_location_visibility_expire_date = " << pending_location_visibility_expire_date_;
|
||||
}
|
||||
|
||||
user_nearby_timeout_.set_callback(on_user_nearby_timeout_callback);
|
||||
user_nearby_timeout_.set_callback_data(static_cast<void *>(this));
|
||||
}
|
||||
|
||||
void PeopleNearbyManager::tear_down() {
|
||||
parent_.reset();
|
||||
}
|
||||
|
||||
void PeopleNearbyManager::start_up() {
|
||||
if (!pending_location_visibility_expire_date_) {
|
||||
try_send_set_location_visibility_query();
|
||||
}
|
||||
}
|
||||
|
||||
void PeopleNearbyManager::on_user_nearby_timeout_callback(void *people_nearby_manager_ptr, int64 user_id_long) {
|
||||
if (G()->close_flag()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto people_nearby_manager = static_cast<PeopleNearbyManager *>(people_nearby_manager_ptr);
|
||||
send_closure_later(people_nearby_manager->actor_id(people_nearby_manager),
|
||||
&PeopleNearbyManager::on_user_nearby_timeout, UserId(user_id_long));
|
||||
}
|
||||
|
||||
void PeopleNearbyManager::on_user_nearby_timeout(UserId user_id) {
|
||||
if (G()->close_flag()) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(INFO) << "Remove " << user_id << " from nearby list";
|
||||
DialogId dialog_id(user_id);
|
||||
for (size_t i = 0; i < users_nearby_.size(); i++) {
|
||||
if (users_nearby_[i].dialog_id == dialog_id) {
|
||||
users_nearby_.erase(users_nearby_.begin() + i);
|
||||
send_update_users_nearby();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool PeopleNearbyManager::is_user_nearby(UserId user_id) const {
|
||||
return all_users_nearby_.count(user_id) != 0;
|
||||
}
|
||||
|
||||
void PeopleNearbyManager::search_dialogs_nearby(const Location &location,
|
||||
Promise<td_api::object_ptr<td_api::chatsNearby>> &&promise) {
|
||||
if (location.empty()) {
|
||||
return promise.set_error(Status::Error(400, "Invalid location specified"));
|
||||
}
|
||||
last_user_location_ = location;
|
||||
try_send_set_location_visibility_query();
|
||||
|
||||
auto query_promise =
|
||||
PromiseCreator::lambda([actor_id = actor_id(this), promise = std::move(promise)](
|
||||
Result<telegram_api::object_ptr<telegram_api::Updates>> result) mutable {
|
||||
send_closure(actor_id, &PeopleNearbyManager::on_get_dialogs_nearby, std::move(result), std::move(promise));
|
||||
});
|
||||
td_->create_handler<SearchDialogsNearbyQuery>(std::move(query_promise))->send(location, false, -1);
|
||||
}
|
||||
|
||||
vector<td_api::object_ptr<td_api::chatNearby>> PeopleNearbyManager::get_chats_nearby_object(
|
||||
const vector<DialogNearby> &dialogs_nearby) const {
|
||||
return transform(dialogs_nearby, [td = td_](const DialogNearby &dialog_nearby) {
|
||||
return td_api::make_object<td_api::chatNearby>(
|
||||
td->dialog_manager_->get_chat_id_object(dialog_nearby.dialog_id, "chatNearby"), dialog_nearby.distance);
|
||||
});
|
||||
}
|
||||
|
||||
void PeopleNearbyManager::send_update_users_nearby() const {
|
||||
send_closure(G()->td(), &Td::send_update,
|
||||
td_api::make_object<td_api::updateUsersNearby>(get_chats_nearby_object(users_nearby_)));
|
||||
}
|
||||
|
||||
void PeopleNearbyManager::on_get_dialogs_nearby(Result<telegram_api::object_ptr<telegram_api::Updates>> result,
|
||||
Promise<td_api::object_ptr<td_api::chatsNearby>> &&promise) {
|
||||
if (result.is_error()) {
|
||||
return promise.set_error(result.move_as_error());
|
||||
}
|
||||
|
||||
auto updates_ptr = result.move_as_ok();
|
||||
if (updates_ptr->get_id() != telegram_api::updates::ID) {
|
||||
LOG(ERROR) << "Receive " << oneline(to_string(*updates_ptr)) << " instead of updates";
|
||||
return promise.set_error(Status::Error(500, "Receive unsupported response from the server"));
|
||||
}
|
||||
|
||||
auto update = telegram_api::move_object_as<telegram_api::updates>(updates_ptr);
|
||||
LOG(INFO) << "Receive chats nearby in " << to_string(update);
|
||||
|
||||
td_->contacts_manager_->on_get_users(std::move(update->users_), "on_get_dialogs_nearby");
|
||||
td_->contacts_manager_->on_get_chats(std::move(update->chats_), "on_get_dialogs_nearby");
|
||||
|
||||
for (auto &dialog_nearby : users_nearby_) {
|
||||
user_nearby_timeout_.cancel_timeout(dialog_nearby.dialog_id.get_user_id().get());
|
||||
}
|
||||
auto old_users_nearby = std::move(users_nearby_);
|
||||
users_nearby_.clear();
|
||||
channels_nearby_.clear();
|
||||
int32 location_visibility_expire_date = 0;
|
||||
for (auto &update_ptr : update->updates_) {
|
||||
if (update_ptr->get_id() != telegram_api::updatePeerLocated::ID) {
|
||||
LOG(ERROR) << "Receive unexpected " << to_string(update);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto expire_date = on_update_peer_located(
|
||||
std::move(static_cast<telegram_api::updatePeerLocated *>(update_ptr.get())->peers_), false);
|
||||
if (expire_date != -1) {
|
||||
location_visibility_expire_date = expire_date;
|
||||
}
|
||||
}
|
||||
if (location_visibility_expire_date != location_visibility_expire_date_) {
|
||||
set_location_visibility_expire_date(location_visibility_expire_date);
|
||||
update_is_location_visible();
|
||||
}
|
||||
|
||||
std::sort(users_nearby_.begin(), users_nearby_.end());
|
||||
if (old_users_nearby != users_nearby_) {
|
||||
send_update_users_nearby(); // for other clients connected to the same TDLib instance
|
||||
}
|
||||
promise.set_value(td_api::make_object<td_api::chatsNearby>(get_chats_nearby_object(users_nearby_),
|
||||
get_chats_nearby_object(channels_nearby_)));
|
||||
}
|
||||
|
||||
void PeopleNearbyManager::set_location(const Location &location, Promise<Unit> &&promise) {
|
||||
if (location.empty()) {
|
||||
return promise.set_error(Status::Error(400, "Invalid location specified"));
|
||||
}
|
||||
last_user_location_ = location;
|
||||
try_send_set_location_visibility_query();
|
||||
|
||||
auto query_promise = PromiseCreator::lambda(
|
||||
[promise = std::move(promise)](Result<telegram_api::object_ptr<telegram_api::Updates>> result) mutable {
|
||||
promise.set_value(Unit());
|
||||
});
|
||||
td_->create_handler<SearchDialogsNearbyQuery>(std::move(query_promise))->send(location, true, -1);
|
||||
}
|
||||
|
||||
void PeopleNearbyManager::set_location_visibility(Td *td) {
|
||||
bool is_location_visible = td->option_manager_->get_option_boolean("is_location_visible");
|
||||
auto pending_location_visibility_expire_date = is_location_visible ? std::numeric_limits<int32>::max() : 0;
|
||||
if (td->people_nearby_manager_ == nullptr) {
|
||||
G()->td_db()->get_binlog_pmc()->set("pending_location_visibility_expire_date",
|
||||
to_string(pending_location_visibility_expire_date));
|
||||
return;
|
||||
}
|
||||
if (td->people_nearby_manager_->pending_location_visibility_expire_date_ == -1 &&
|
||||
pending_location_visibility_expire_date == td->people_nearby_manager_->location_visibility_expire_date_) {
|
||||
return;
|
||||
}
|
||||
if (td->people_nearby_manager_->pending_location_visibility_expire_date_ != pending_location_visibility_expire_date) {
|
||||
td->people_nearby_manager_->pending_location_visibility_expire_date_ = pending_location_visibility_expire_date;
|
||||
G()->td_db()->get_binlog_pmc()->set("pending_location_visibility_expire_date",
|
||||
to_string(pending_location_visibility_expire_date));
|
||||
}
|
||||
td->people_nearby_manager_->try_send_set_location_visibility_query();
|
||||
}
|
||||
|
||||
void PeopleNearbyManager::try_send_set_location_visibility_query() {
|
||||
if (G()->close_flag()) {
|
||||
return;
|
||||
}
|
||||
if (pending_location_visibility_expire_date_ == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(INFO) << "Trying to send set location visibility query";
|
||||
if (is_set_location_visibility_request_sent_) {
|
||||
return;
|
||||
}
|
||||
if (pending_location_visibility_expire_date_ != 0 && last_user_location_.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
is_set_location_visibility_request_sent_ = true;
|
||||
auto query_promise =
|
||||
PromiseCreator::lambda([actor_id = actor_id(this), set_expire_date = pending_location_visibility_expire_date_](
|
||||
Result<telegram_api::object_ptr<telegram_api::Updates>> result) {
|
||||
send_closure(actor_id, &PeopleNearbyManager::on_set_location_visibility_expire_date, set_expire_date,
|
||||
result.is_ok() ? 0 : result.error().code());
|
||||
});
|
||||
td_->create_handler<SearchDialogsNearbyQuery>(std::move(query_promise))
|
||||
->send(last_user_location_, true, pending_location_visibility_expire_date_);
|
||||
}
|
||||
|
||||
void PeopleNearbyManager::on_set_location_visibility_expire_date(int32 set_expire_date, int32 error_code) {
|
||||
bool success = error_code == 0;
|
||||
is_set_location_visibility_request_sent_ = false;
|
||||
|
||||
if (set_expire_date != pending_location_visibility_expire_date_) {
|
||||
return try_send_set_location_visibility_query();
|
||||
}
|
||||
|
||||
if (success) {
|
||||
set_location_visibility_expire_date(pending_location_visibility_expire_date_);
|
||||
} else {
|
||||
if (G()->close_flag()) {
|
||||
// request will be re-sent after restart
|
||||
return;
|
||||
}
|
||||
if (error_code != 406) {
|
||||
LOG(ERROR) << "Failed to set location visibility expire date to " << pending_location_visibility_expire_date_;
|
||||
}
|
||||
}
|
||||
G()->td_db()->get_binlog_pmc()->erase("pending_location_visibility_expire_date");
|
||||
pending_location_visibility_expire_date_ = -1;
|
||||
update_is_location_visible();
|
||||
}
|
||||
|
||||
void PeopleNearbyManager::get_is_location_visible(Promise<Unit> &&promise) {
|
||||
auto query_promise =
|
||||
PromiseCreator::lambda([actor_id = actor_id(this), promise = std::move(promise)](
|
||||
Result<telegram_api::object_ptr<telegram_api::Updates>> result) mutable {
|
||||
send_closure(actor_id, &PeopleNearbyManager::on_get_is_location_visible, std::move(result), std::move(promise));
|
||||
});
|
||||
td_->create_handler<SearchDialogsNearbyQuery>(std::move(query_promise))->send(Location(), true, -1);
|
||||
}
|
||||
|
||||
void PeopleNearbyManager::on_get_is_location_visible(Result<telegram_api::object_ptr<telegram_api::Updates>> &&result,
|
||||
Promise<Unit> &&promise) {
|
||||
TRY_STATUS_PROMISE(promise, G()->close_status());
|
||||
if (result.is_error()) {
|
||||
if (result.error().message() == "GEO_POINT_INVALID" && pending_location_visibility_expire_date_ == -1 &&
|
||||
location_visibility_expire_date_ > 0) {
|
||||
set_location_visibility_expire_date(0);
|
||||
update_is_location_visible();
|
||||
}
|
||||
return promise.set_value(Unit());
|
||||
}
|
||||
|
||||
auto updates_ptr = result.move_as_ok();
|
||||
if (updates_ptr->get_id() != telegram_api::updates::ID) {
|
||||
LOG(ERROR) << "Receive " << oneline(to_string(*updates_ptr)) << " instead of updates";
|
||||
return promise.set_value(Unit());
|
||||
}
|
||||
|
||||
auto updates = std::move(telegram_api::move_object_as<telegram_api::updates>(updates_ptr)->updates_);
|
||||
if (updates.size() != 1 || updates[0]->get_id() != telegram_api::updatePeerLocated::ID) {
|
||||
LOG(ERROR) << "Receive unexpected " << to_string(updates);
|
||||
return promise.set_value(Unit());
|
||||
}
|
||||
|
||||
auto peers = std::move(static_cast<telegram_api::updatePeerLocated *>(updates[0].get())->peers_);
|
||||
if (peers.size() != 1 || peers[0]->get_id() != telegram_api::peerSelfLocated::ID) {
|
||||
LOG(ERROR) << "Receive unexpected " << to_string(peers);
|
||||
return promise.set_value(Unit());
|
||||
}
|
||||
|
||||
auto location_visibility_expire_date = static_cast<telegram_api::peerSelfLocated *>(peers[0].get())->expires_;
|
||||
if (location_visibility_expire_date != location_visibility_expire_date_) {
|
||||
set_location_visibility_expire_date(location_visibility_expire_date);
|
||||
update_is_location_visible();
|
||||
}
|
||||
|
||||
promise.set_value(Unit());
|
||||
}
|
||||
|
||||
int32 PeopleNearbyManager::on_update_peer_located(vector<telegram_api::object_ptr<telegram_api::PeerLocated>> &&peers,
|
||||
bool from_update) {
|
||||
auto now = G()->unix_time();
|
||||
bool need_update = false;
|
||||
int32 location_visibility_expire_date = -1;
|
||||
for (auto &peer_located_ptr : peers) {
|
||||
if (peer_located_ptr->get_id() == telegram_api::peerSelfLocated::ID) {
|
||||
auto peer_self_located = telegram_api::move_object_as<telegram_api::peerSelfLocated>(peer_located_ptr);
|
||||
if (peer_self_located->expires_ == 0 || peer_self_located->expires_ > G()->unix_time()) {
|
||||
location_visibility_expire_date = peer_self_located->expires_;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
CHECK(peer_located_ptr->get_id() == telegram_api::peerLocated::ID);
|
||||
auto peer_located = telegram_api::move_object_as<telegram_api::peerLocated>(peer_located_ptr);
|
||||
DialogId dialog_id(peer_located->peer_);
|
||||
int32 expires_at = peer_located->expires_;
|
||||
int32 distance = peer_located->distance_;
|
||||
if (distance < 0 || distance > 50000000) {
|
||||
LOG(ERROR) << "Receive wrong distance to " << to_string(peer_located);
|
||||
continue;
|
||||
}
|
||||
if (expires_at <= now) {
|
||||
LOG(INFO) << "Skip expired result " << to_string(peer_located);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto dialog_type = dialog_id.get_type();
|
||||
if (dialog_type == DialogType::User) {
|
||||
auto user_id = dialog_id.get_user_id();
|
||||
if (!td_->contacts_manager_->have_user(user_id)) {
|
||||
LOG(ERROR) << "Can't find " << user_id;
|
||||
continue;
|
||||
}
|
||||
if (expires_at < now + 86400) {
|
||||
user_nearby_timeout_.set_timeout_in(user_id.get(), expires_at - now + 1);
|
||||
}
|
||||
} else if (dialog_type == DialogType::Channel) {
|
||||
auto channel_id = dialog_id.get_channel_id();
|
||||
if (!td_->contacts_manager_->have_channel(channel_id)) {
|
||||
LOG(ERROR) << "Can't find " << channel_id;
|
||||
continue;
|
||||
}
|
||||
if (expires_at != std::numeric_limits<int32>::max()) {
|
||||
LOG(ERROR) << "Receive expiring at " << expires_at << " group location in " << to_string(peer_located);
|
||||
}
|
||||
if (from_update) {
|
||||
LOG(ERROR) << "Receive nearby " << channel_id << " from update";
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
LOG(ERROR) << "Receive chat of wrong type in " << to_string(peer_located);
|
||||
continue;
|
||||
}
|
||||
|
||||
td_->dialog_manager_->force_create_dialog(dialog_id, "on_update_peer_located");
|
||||
|
||||
if (from_update) {
|
||||
CHECK(dialog_type == DialogType::User);
|
||||
bool is_found = false;
|
||||
for (auto &dialog_nearby : users_nearby_) {
|
||||
if (dialog_nearby.dialog_id == dialog_id) {
|
||||
if (dialog_nearby.distance != distance) {
|
||||
dialog_nearby.distance = distance;
|
||||
need_update = true;
|
||||
}
|
||||
is_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!is_found) {
|
||||
users_nearby_.emplace_back(dialog_id, distance);
|
||||
all_users_nearby_.insert(dialog_id.get_user_id());
|
||||
need_update = true;
|
||||
}
|
||||
} else {
|
||||
if (dialog_type == DialogType::User) {
|
||||
users_nearby_.emplace_back(dialog_id, distance);
|
||||
all_users_nearby_.insert(dialog_id.get_user_id());
|
||||
} else {
|
||||
channels_nearby_.emplace_back(dialog_id, distance);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (need_update) {
|
||||
std::sort(users_nearby_.begin(), users_nearby_.end());
|
||||
send_update_users_nearby();
|
||||
}
|
||||
return location_visibility_expire_date;
|
||||
}
|
||||
|
||||
void PeopleNearbyManager::set_location_visibility_expire_date(int32 expire_date) {
|
||||
if (location_visibility_expire_date_ == expire_date) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(INFO) << "Set set_location_visibility_expire_date to " << expire_date;
|
||||
location_visibility_expire_date_ = expire_date;
|
||||
if (expire_date == 0) {
|
||||
G()->td_db()->get_binlog_pmc()->erase("location_visibility_expire_date");
|
||||
} else {
|
||||
G()->td_db()->get_binlog_pmc()->set("location_visibility_expire_date", to_string(expire_date));
|
||||
}
|
||||
// the caller must call update_is_location_visible() itself
|
||||
}
|
||||
|
||||
void PeopleNearbyManager::update_is_location_visible() {
|
||||
auto expire_date = pending_location_visibility_expire_date_ != -1 ? pending_location_visibility_expire_date_
|
||||
: location_visibility_expire_date_;
|
||||
td_->option_manager_->set_option_boolean("is_location_visible", expire_date != 0);
|
||||
}
|
||||
|
||||
} // namespace td
|
||||
|
@ -6,9 +6,19 @@
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include "td/telegram/DialogId.h"
|
||||
#include "td/telegram/Location.h"
|
||||
#include "td/telegram/td_api.h"
|
||||
#include "td/telegram/telegram_api.h"
|
||||
#include "td/telegram/UserId.h"
|
||||
|
||||
#include "td/actor/actor.h"
|
||||
#include "td/actor/MultiTimeout.h"
|
||||
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/FlatHashSet.h"
|
||||
#include "td/utils/Promise.h"
|
||||
#include "td/utils/Status.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
@ -18,11 +28,78 @@ class PeopleNearbyManager final : public Actor {
|
||||
public:
|
||||
PeopleNearbyManager(Td *td, ActorShared<> parent);
|
||||
|
||||
void search_dialogs_nearby(const Location &location, Promise<td_api::object_ptr<td_api::chatsNearby>> &&promise);
|
||||
|
||||
void set_location(const Location &location, Promise<Unit> &&promise);
|
||||
|
||||
static void set_location_visibility(Td *td);
|
||||
|
||||
void get_is_location_visible(Promise<Unit> &&promise);
|
||||
|
||||
int32 on_update_peer_located(vector<telegram_api::object_ptr<telegram_api::PeerLocated>> &&peers, bool from_update);
|
||||
|
||||
bool is_user_nearby(UserId user_id) const;
|
||||
|
||||
private:
|
||||
struct DialogNearby {
|
||||
DialogId dialog_id;
|
||||
int32 distance;
|
||||
|
||||
DialogNearby(DialogId dialog_id, int32 distance) : dialog_id(dialog_id), distance(distance) {
|
||||
}
|
||||
|
||||
bool operator<(const DialogNearby &other) const {
|
||||
return distance < other.distance || (distance == other.distance && dialog_id.get() < other.dialog_id.get());
|
||||
}
|
||||
|
||||
bool operator==(const DialogNearby &other) const {
|
||||
return distance == other.distance && dialog_id == other.dialog_id;
|
||||
}
|
||||
|
||||
bool operator!=(const DialogNearby &other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
};
|
||||
|
||||
void start_up() final;
|
||||
|
||||
void tear_down() final;
|
||||
|
||||
static void on_user_nearby_timeout_callback(void *contacts_manager_ptr, int64 user_id_long);
|
||||
|
||||
void on_user_nearby_timeout(UserId user_id);
|
||||
|
||||
vector<td_api::object_ptr<td_api::chatNearby>> get_chats_nearby_object(
|
||||
const vector<DialogNearby> &dialogs_nearby) const;
|
||||
|
||||
void send_update_users_nearby() const;
|
||||
|
||||
void on_get_dialogs_nearby(Result<telegram_api::object_ptr<telegram_api::Updates>> result,
|
||||
Promise<td_api::object_ptr<td_api::chatsNearby>> &&promise);
|
||||
|
||||
void try_send_set_location_visibility_query();
|
||||
|
||||
void on_set_location_visibility_expire_date(int32 set_expire_date, int32 error_code);
|
||||
|
||||
void set_location_visibility_expire_date(int32 expire_date);
|
||||
|
||||
void on_get_is_location_visible(Result<telegram_api::object_ptr<telegram_api::Updates>> &&result,
|
||||
Promise<Unit> &&promise);
|
||||
|
||||
void update_is_location_visible();
|
||||
|
||||
Td *td_;
|
||||
ActorShared<> parent_;
|
||||
|
||||
vector<DialogNearby> users_nearby_;
|
||||
vector<DialogNearby> channels_nearby_;
|
||||
FlatHashSet<UserId, UserIdHash> all_users_nearby_;
|
||||
MultiTimeout user_nearby_timeout_{"UserNearbyTimeout"};
|
||||
|
||||
int32 location_visibility_expire_date_ = 0;
|
||||
int32 pending_location_visibility_expire_date_ = -1;
|
||||
bool is_set_location_visibility_request_sent_ = false;
|
||||
Location last_user_location_;
|
||||
};
|
||||
|
||||
} // namespace td
|
||||
|
@ -5164,7 +5164,7 @@ void Td::on_request(uint64 id, td_api::searchChatsOnServer &request) {
|
||||
void Td::on_request(uint64 id, const td_api::searchChatsNearby &request) {
|
||||
CHECK_IS_USER();
|
||||
CREATE_REQUEST_PROMISE();
|
||||
contacts_manager_->search_dialogs_nearby(Location(request.location_), std::move(promise));
|
||||
people_nearby_manager_->search_dialogs_nearby(Location(request.location_), std::move(promise));
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, const td_api::getGroupsInCommon &request) {
|
||||
@ -7816,7 +7816,7 @@ void Td::on_request(uint64 id, const td_api::getBotInfoShortDescription &request
|
||||
void Td::on_request(uint64 id, const td_api::setLocation &request) {
|
||||
CHECK_IS_USER();
|
||||
CREATE_OK_REQUEST_PROMISE();
|
||||
contacts_manager_->set_location(Location(request.location_), std::move(promise));
|
||||
people_nearby_manager_->set_location(Location(request.location_), std::move(promise));
|
||||
}
|
||||
|
||||
void Td::on_request(uint64 id, td_api::setBusinessLocation &request) {
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "td/telegram/NotificationSettingsScope.h"
|
||||
#include "td/telegram/OptionManager.h"
|
||||
#include "td/telegram/OrderInfo.h"
|
||||
#include "td/telegram/PeopleNearbyManager.h"
|
||||
#include "td/telegram/PollId.h"
|
||||
#include "td/telegram/PollManager.h"
|
||||
#include "td/telegram/PrivacyManager.h"
|
||||
@ -3693,7 +3694,7 @@ void UpdatesManager::on_update(tl_object_ptr<telegram_api::updatePeerHistoryTTL>
|
||||
}
|
||||
|
||||
void UpdatesManager::on_update(tl_object_ptr<telegram_api::updatePeerLocated> update, Promise<Unit> &&promise) {
|
||||
td_->contacts_manager_->on_update_peer_located(std::move(update->peers_), true);
|
||||
td_->people_nearby_manager_->on_update_peer_located(std::move(update->peers_), true);
|
||||
promise.set_value(Unit());
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user